From 157b3e8e0aed03e2131c2900cffbb16e3ea34663 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 15 Dec 2014 16:39:28 +0100 Subject: pdfviewer example: can scroll through pages and render on demand --- examples/widgets/pdfviewer/mainwindow.cpp | 22 +++++++++- examples/widgets/pdfviewer/mainwindow.h | 3 ++ examples/widgets/pdfviewer/mainwindow.ui | 25 +++++++---- .../widgets/pdfviewer/sequentialpagewidget.cpp | 48 ++++++++++++++++++---- examples/widgets/pdfviewer/sequentialpagewidget.h | 8 +++- 5 files changed, 87 insertions(+), 19 deletions(-) (limited to 'examples') diff --git a/examples/widgets/pdfviewer/mainwindow.cpp b/examples/widgets/pdfviewer/mainwindow.cpp index 1316dede1..e5b29edfd 100644 --- a/examples/widgets/pdfviewer/mainwindow.cpp +++ b/examples/widgets/pdfviewer/mainwindow.cpp @@ -4,6 +4,7 @@ #include #include #include +#include "sequentialpagewidget.h" Q_LOGGING_CATEGORY(lcExample, "qt.examples.pdfviewer") @@ -11,9 +12,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) , m_doc(new QPdfDocument(this)) + , m_pageWidget(new SequentialPageWidget(this)) { ui->setupUi(this); - ui->pageWidget->setDocument(m_doc); + m_pageWidget->setDocument(m_doc); + ui->scrollArea->setWidget(m_pageWidget); + connect(m_pageWidget, SIGNAL(showingPageRange(int,int)), + this, SLOT(showingPageRange(int,int)), Qt::QueuedConnection); } MainWindow::~MainWindow() @@ -29,11 +34,24 @@ void MainWindow::open(const QUrl &docLocation) qCDebug(lcExample) << docLocation << "is not a valid local file"; QMessageBox::critical(this, tr("Failed to open"), tr("%1 is not a valid local file").arg(docLocation.toString())); } + // TODO: connect to signal from document + m_pageWidget->invalidate(); + qCDebug(lcExample) << docLocation; + ui->scrollArea->ensureVisible(0, 0, 0, 0); +} + +void MainWindow::showingPageRange(int start, int end) +{ + ui->statusBar->clearMessage(); + if (start == end) + ui->statusBar->showMessage(tr("showing page %1").arg(start)); + else + ui->statusBar->showMessage(tr("showing pages %1 to %2").arg(start).arg(end)); } void MainWindow::on_actionOpen_triggered() { - QUrl toOpen = QFileDialog::getOpenFileUrl(this); + QUrl toOpen = QFileDialog::getOpenFileUrl(this, tr("Choose a PDF"), QUrl(), "Portable Documents (*.pdf)"); if (toOpen.isValid()) open(toOpen); } diff --git a/examples/widgets/pdfviewer/mainwindow.h b/examples/widgets/pdfviewer/mainwindow.h index e31f0b970..bcad93ebb 100644 --- a/examples/widgets/pdfviewer/mainwindow.h +++ b/examples/widgets/pdfviewer/mainwindow.h @@ -11,6 +11,7 @@ class MainWindow; } class QPdfDocument; +class SequentialPageWidget; class MainWindow : public QMainWindow { @@ -24,11 +25,13 @@ public slots: void open(const QUrl &docLocation); private slots: + void showingPageRange(int start, int end); void on_actionOpen_triggered(); private: Ui::MainWindow *ui; QPdfDocument *m_doc; + SequentialPageWidget *m_pageWidget; }; #endif // MAINWINDOW_H diff --git a/examples/widgets/pdfviewer/mainwindow.ui b/examples/widgets/pdfviewer/mainwindow.ui index 16994fa57..f1f90b307 100644 --- a/examples/widgets/pdfviewer/mainwindow.ui +++ b/examples/widgets/pdfviewer/mainwindow.ui @@ -16,7 +16,22 @@ - + + + true + + + + + 0 + 0 + 380 + 210 + + + + + @@ -54,14 +69,6 @@ - - - SequentialPageWidget - QWidget -
sequentialpagewidget.h
- 1 -
-
diff --git a/examples/widgets/pdfviewer/sequentialpagewidget.cpp b/examples/widgets/pdfviewer/sequentialpagewidget.cpp index 5de4f2ee8..e7dd08746 100644 --- a/examples/widgets/pdfviewer/sequentialpagewidget.cpp +++ b/examples/widgets/pdfviewer/sequentialpagewidget.cpp @@ -14,25 +14,45 @@ SequentialPageWidget::SequentialPageWidget(QWidget *parent) , m_background(Qt::darkGray) , m_pageSpacing(3) , m_zoom(1.) - , m_top(0.) , m_screenResolution(QGuiApplication::primaryScreen()->logicalDotsPerInch() / 72.0) { } SequentialPageWidget::~SequentialPageWidget() { - } void SequentialPageWidget::setDocument(QPdfDocument *doc) { m_doc = doc; + invalidate(); } void SequentialPageWidget::setZoom(qreal factor) { m_zoom = factor; + invalidate(); +} + +QSizeF SequentialPageWidget::pageSize(int page) +{ + return m_doc->pageSize(page) * m_screenResolution * m_zoom; +} + +void SequentialPageWidget::invalidate() +{ m_pageCache.clear(); + QSizeF totalSize(0, m_pageSpacing); + for (int page = 0; page < m_doc->pageCount(); ++page) { + QSizeF size = pageSize(page); + qDebug() << "page" << page << "size" << size; + totalSize.setHeight(totalSize.height() + size.height()); + if (size.width() > totalSize.width()) + totalSize.setWidth(size.width()); + } + m_totalSize = totalSize.toSize(); + setMinimumSize(m_totalSize); + qCDebug(lcExample) << "total size" << m_totalSize; update(); } @@ -45,19 +65,33 @@ void SequentialPageWidget::paintEvent(QPaintEvent * event) } painter.fillRect(event->rect(), m_background); - qCDebug(lcExample) << event->rect() << m_doc->pageCount(); - int page = 0; // qFloor(m_top); - int y = 0; // TODO event->rect().top(); + // Find the first page that needs to be rendered + int page = 0; + int y = 0; + while (page < m_doc->pageCount()) { + QSizeF size = pageSize(page); + int height = size.toSize().height(); + if (y + height >= event->rect().top()) + break; + y += height; + ++page; + } + y += m_pageSpacing; + int startPage = page; + + // Actually render pages while (y < event->rect().bottom() && page < m_doc->pageCount()) { - QSizeF size = m_doc->pageSize(page) * m_screenResolution * m_zoom; if (!m_pageCache.contains(page)) { + QSizeF size = pageSize(page); qCDebug(lcExample) << "rendering page" << page << "to size" << size; m_pageCache.insert(page, QPixmap::fromImage(m_doc->render(page, size))); } const QPixmap &pm = m_pageCache[page]; - painter.drawPixmap(0, y, pm); + painter.drawPixmap((width() - pm.width()) / 2, y, pm); y += pm.height() + m_pageSpacing; ++page; } + + emit showingPageRange(startPage, page - 1); } diff --git a/examples/widgets/pdfviewer/sequentialpagewidget.h b/examples/widgets/pdfviewer/sequentialpagewidget.h index 6741fe37e..44b27faad 100644 --- a/examples/widgets/pdfviewer/sequentialpagewidget.h +++ b/examples/widgets/pdfviewer/sequentialpagewidget.h @@ -2,6 +2,7 @@ #define SEQUENTIALPAGEWIDGET_H #include +#include class QPdfDocument; @@ -17,8 +18,13 @@ public: public slots: void setDocument(QPdfDocument *doc); void setZoom(qreal factor); + void invalidate(); + +signals: + void showingPageRange(int start, int end); private: + QSizeF pageSize(int page); void render(int page); private: @@ -26,8 +32,8 @@ private: QHash m_pageCache; QBrush m_background; int m_pageSpacing; + QSize m_totalSize; qreal m_zoom; - qreal m_top; // 1.5 means start from the bottom half of page 1 qreal m_screenResolution; // pixels per point }; -- cgit v1.2.3