diff options
author | Shawn Rutledge <shawn.rutledge@theqtcompany.com> | 2014-12-15 22:30:01 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@theqtcompany.com> | 2014-12-16 00:45:47 +0100 |
commit | 86b7ed4df30f57fb994e5d032070ed118a9a7afa (patch) | |
tree | 1a0b7277772826be337ab4f025b1e23214f798f2 /examples/widgets/pdfviewer/sequentialpagewidget.cpp | |
parent | 5359a1473bf5c2310c50dbe239c28084cf7ae81f (diff) |
pdfviewer example: PageRenderer owns document and thread. Smooth
PageCache renamed to PageRenderer and minimized to just being a
worker thread. The UI is finally responsive, biecause the locking in
QPdfDocument is isolated behind PageRenderer.
ATM only renders visible pages though.
Diffstat (limited to 'examples/widgets/pdfviewer/sequentialpagewidget.cpp')
-rw-r--r-- | examples/widgets/pdfviewer/sequentialpagewidget.cpp | 74 |
1 files changed, 41 insertions, 33 deletions
diff --git a/examples/widgets/pdfviewer/sequentialpagewidget.cpp b/examples/widgets/pdfviewer/sequentialpagewidget.cpp index da880be..2f4e3fb 100644 --- a/examples/widgets/pdfviewer/sequentialpagewidget.cpp +++ b/examples/widgets/pdfviewer/sequentialpagewidget.cpp @@ -1,5 +1,5 @@ #include "sequentialpagewidget.h" -#include "pagecache.h" +#include "pagerenderer.h" #include <QPaintEvent> #include <QPainter> #include <QPdfDocument> @@ -12,30 +12,27 @@ Q_DECLARE_LOGGING_CATEGORY(lcExample) SequentialPageWidget::SequentialPageWidget(QWidget *parent) : QWidget(parent) - , m_doc(Q_NULLPTR) - , m_pageCache(Q_NULLPTR) + , m_pageRenderer(new PageRenderer()) , m_background(Qt::darkGray) - , m_pageSpacing(3) , m_placeholderIcon(":icons/images/busy.png") , m_placeholderBackground(Qt::white) + , m_pageSpacing(3) , m_topPageShowing(0) , m_zoom(1.) , m_screenResolution(QGuiApplication::primaryScreen()->logicalDotsPerInch() / 72.0) { + connect(m_pageRenderer, SIGNAL(pageReady(int, qreal, QImage)), this, SLOT(pageLoaded(int, qreal, QImage)), Qt::QueuedConnection); } SequentialPageWidget::~SequentialPageWidget() { + delete m_pageRenderer; } -void SequentialPageWidget::setDocument(QPdfDocument *doc) +void SequentialPageWidget::openDocument(const QUrl &url) { - m_doc = doc; + m_pageSizes = m_pageRenderer->openDocument(url); m_topPageShowing = 0; - if (m_pageCache) - delete m_pageCache; - m_pageCache = new PageCache(doc, m_screenResolution * m_zoom); - connect(m_pageCache, SIGNAL(pageReady(int)), this, SLOT(update())); invalidate(); } @@ -48,20 +45,19 @@ void SequentialPageWidget::setZoom(qreal factor) QSizeF SequentialPageWidget::pageSize(int page) { - return m_doc->pageSize(page) * m_screenResolution * m_zoom; +// if (!m_pageSizes.length() <= page) +// return QSizeF(); + return m_pageSizes[page] * m_screenResolution * m_zoom; } void SequentialPageWidget::invalidate() { - if (m_pageCache) - delete m_pageCache; - if (m_doc) - m_pageCache = new PageCache(m_doc, m_screenResolution * m_zoom); - connect(m_pageCache, SIGNAL(pageReady(int)), this, SLOT(update())); QSizeF totalSize(0, m_pageSpacing); - for (int page = 0; page < m_doc->pageCount(); ++page) { +qDebug() << "pageCount" << pageCount(); + + for (int page = 0; page < pageCount(); ++page) { QSizeF size = pageSize(page); - qDebug() << "page" << page << "size" << size; + qDebug() << "page" << page << "size" << size << "from" << m_pageSizes[page]; totalSize.setHeight(totalSize.height() + size.height()); if (size.width() > totalSize.width()) totalSize.setWidth(size.width()); @@ -73,20 +69,30 @@ void SequentialPageWidget::invalidate() update(); } +void SequentialPageWidget::pageLoaded(int page, qreal zoom, QImage image) +{ + Q_UNUSED(zoom) + m_pageCache.insert(page, image); + update(); +} + +int SequentialPageWidget::pageCount() +{ + return m_pageSizes.count(); +} + void SequentialPageWidget::paintEvent(QPaintEvent * event) { QPainter painter(this); - if (!m_doc) { - painter.drawText(rect(), Qt::AlignCenter, tr("no document loaded")); - return; - } - painter.fillRect(event->rect(), m_background); + if (m_pageSizes.isEmpty()) + return; + // Find the first page that needs to be rendered int page = 0; int y = 0; - while (page < m_doc->pageCount()) { + while (page < pageCount()) { QSizeF size = pageSize(page); int height = size.toSize().height(); if (y + height >= event->rect().top()) @@ -96,20 +102,22 @@ void SequentialPageWidget::paintEvent(QPaintEvent * event) } y += m_pageSpacing; m_topPageShowing = page; - if (!m_pageCache) return; + +qDebug() << y << m_topPageShowing << pageCount(); // Actually render pages - while (y < event->rect().bottom() && page < m_doc->pageCount()) { - const QPixmap &pm = m_pageCache->get(page); - if (pm.isNull()) { - QSizeF size = pageSize(page); + while (y < event->rect().bottom() && page < pageCount()) { + QSizeF size = pageSize(page); + if (m_pageCache.contains(page)) { + const QImage &img = m_pageCache[page]; + painter.drawImage((width() - img.width()) / 2, y, img); + } else { painter.fillRect((width() - size.width()) / 2, y, size.width(), size.height(), m_placeholderBackground); painter.drawPixmap((size.width() - m_placeholderIcon.width()) / 2, (size.height() - m_placeholderIcon.height()) / 2, m_placeholderIcon); - } else { - painter.drawPixmap((width() - pm.width()) / 2, y, pm); + m_pageRenderer->requestPage(page, m_screenResolution * m_zoom); } - y += pm.height() + m_pageSpacing; + y += size.height() + m_pageSpacing; ++page; } m_bottomPageShowing = page - 1; @@ -120,7 +128,7 @@ qreal SequentialPageWidget::yForPage(int endPage) { // TODO maybe put this loop into a page iterator class int y = m_pageSpacing; - for (int page = 0; page < m_doc->pageCount() && page < endPage; ++page) { + for (int page = 0; page < pageCount() && page < endPage; ++page) { QSizeF size = pageSize(page); int height = size.toSize().height(); y += height + m_pageSpacing; |