diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-01-10 07:47:52 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-03-03 06:05:18 +0100 |
commit | 7b8832ca2b84d549c9d374550c3c46b3d4d42a38 (patch) | |
tree | 47eed7bcd915b7db53d06e8cef749cf6df913609 /src/pdfquick | |
parent | af190c9d05d2a5afc2de4dd9b2172fec8e4ce3b7 (diff) | |
download | qtwebengine-7b8832ca2b84d549c9d374550c3c46b3d4d42a38.tar.gz |
Add QQuickPdfPageImage and use in the PDF viewer components
Image works fine, except that if QPdfIOHandler is not given an
already-allocated QPdfDocument instance, it needs to construct its own.
So we now have QPdfFile: a subclass of QFile acting as a wrapper, to
carry the document instance (that the user has most likely declared)
down into QPdfIOHandler::load(QIODevice *). Thus, in nontrivial
PDF-viewing use cases, there is now usually only one multi-purpose
document instance. And this takes care of viewing password-protected
PDFs in the multipage example, because we already prompt for it
and set the document.password property.
In trivial use cases, it's OK to continue using Image, and QPdfIOHandler
will still construct its own QPdfDocument instance if the QIODevice
cannot be cast to a QPdfFile.
Task-number: QTBUG-77506
Task-number: QTBUG-83988
Task-number: QTBUG-96574
Change-Id: I3adfa54c30b0baa5dedebcf3bc759758f136b757
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/pdfquick')
-rw-r--r-- | src/pdfquick/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/pdfquick/PdfMultiPageView.qml | 10 | ||||
-rw-r--r-- | src/pdfquick/PdfPageView.qml | 6 | ||||
-rw-r--r-- | src/pdfquick/PdfScrollablePageView.qml | 6 | ||||
-rw-r--r-- | src/pdfquick/qquickpdfdocument.cpp | 13 | ||||
-rw-r--r-- | src/pdfquick/qquickpdfdocument_p.h | 5 | ||||
-rw-r--r-- | src/pdfquick/qquickpdfpageimage.cpp | 155 | ||||
-rw-r--r-- | src/pdfquick/qquickpdfpageimage_p.h | 89 |
8 files changed, 274 insertions, 11 deletions
diff --git a/src/pdfquick/CMakeLists.txt b/src/pdfquick/CMakeLists.txt index 19520d2da..1e58120da 100644 --- a/src/pdfquick/CMakeLists.txt +++ b/src/pdfquick/CMakeLists.txt @@ -20,6 +20,7 @@ qt_internal_add_qml_module(PdfQuick qquickpdfdocument.cpp qquickpdfdocument_p.h qquickpdflinkmodel.cpp qquickpdflinkmodel_p.h qquickpdfnavigationstack.cpp qquickpdfnavigationstack_p.h + qquickpdfpageimage.cpp qquickpdfpageimage_p.h qquickpdfsearchmodel.cpp qquickpdfsearchmodel_p.h qquickpdfselection.cpp qquickpdfselection_p.h qtpdfquickglobal_p.h diff --git a/src/pdfquick/PdfMultiPageView.qml b/src/pdfquick/PdfMultiPageView.qml index 8ab5e2c2e..f67e2c17a 100644 --- a/src/pdfquick/PdfMultiPageView.qml +++ b/src/pdfquick/PdfMultiPageView.qml @@ -156,10 +156,10 @@ Item { anchors.centerIn: pinch.active ? undefined : parent property size pagePointSize: document.pagePointSize(index) property real pageScale: image.paintedWidth / pagePointSize.width - Image { + PdfPageImage { id: image - source: document.source - currentFrame: index + document: root.document + currentPage: index asynchronous: true fillMode: Image.PreserveAspectFit width: paper.pagePointSize.width * root.renderScale @@ -290,7 +290,7 @@ Item { model: PdfLinkModel { id: linkModel document: root.document - page: image.currentFrame + page: image.currentPage } delegate: Shape { required property rect rect @@ -337,7 +337,7 @@ Item { id: selection anchors.fill: parent document: root.document - page: image.currentFrame + page: image.currentPage renderScale: image.renderScale fromPoint: textSelectionDrag.centroid.pressPosition toPoint: textSelectionDrag.centroid.position diff --git a/src/pdfquick/PdfPageView.qml b/src/pdfquick/PdfPageView.qml index ed1f00372..bcb286c0c 100644 --- a/src/pdfquick/PdfPageView.qml +++ b/src/pdfquick/PdfPageView.qml @@ -146,10 +146,10 @@ Rectangle { // TODO deal with horizontal location (need WheelHandler or Flickable probably) } - Image { + PdfPageImage { id: image - currentFrame: navigationStack.currentPage - source: document.status === PdfDocument.Ready ? document.source : "" + document: root.document + currentPage: navigationStack.currentPage asynchronous: true fillMode: Image.PreserveAspectFit property bool centerOnLoad: false diff --git a/src/pdfquick/PdfScrollablePageView.qml b/src/pdfquick/PdfScrollablePageView.qml index 40be27176..9e458397e 100644 --- a/src/pdfquick/PdfScrollablePageView.qml +++ b/src/pdfquick/PdfScrollablePageView.qml @@ -168,10 +168,10 @@ Flickable { property real rotationModulus: Math.abs(root.pageRotation % 180) property bool rot90: rotationModulus > 45 && rotationModulus < 135 - Image { + PdfPageImage { id: image - currentFrame: navigationStack.currentPage - source: document.status === PdfDocument.Ready ? document.source : "" + document: root.document + currentPage: navigationStack.currentPage asynchronous: true fillMode: Image.PreserveAspectFit rotation: root.pageRotation diff --git a/src/pdfquick/qquickpdfdocument.cpp b/src/pdfquick/qquickpdfdocument.cpp index 64ad0071a..bdfad3905 100644 --- a/src/pdfquick/qquickpdfdocument.cpp +++ b/src/pdfquick/qquickpdfdocument.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qquickpdfdocument_p.h" +#include <private/qpdffile_p.h> #include <QtCore/qstandardpaths.h> #include <QtQml/qqmlcontext.h> #include <QtQml/qqmlengine.h> @@ -221,6 +222,18 @@ qreal QQuickPdfDocument::heightSumBeforePage(int page, qreal spacing, int facing return ret; } +/*! + \internal + Returns a QPdfFile instance that can carry this document down into + QPdfIOHandler::load(QIODevice *). It should not be used for other purposes. +*/ +QPdfFile *QQuickPdfDocument::carrierFile() +{ + if (!m_carrierFile) + m_carrierFile = new QPdfFile(&m_doc); + return m_carrierFile; +} + void QQuickPdfDocument::updateMaxPageSize() { if (m_maxPageWidthHeight.isValid()) diff --git a/src/pdfquick/qquickpdfdocument_p.h b/src/pdfquick/qquickpdfdocument_p.h index 2d6f2ca3b..fb7f06b97 100644 --- a/src/pdfquick/qquickpdfdocument_p.h +++ b/src/pdfquick/qquickpdfdocument_p.h @@ -61,6 +61,8 @@ QT_BEGIN_NAMESPACE +class QPdfFile; + class Q_PDFQUICK_EXPORT QQuickPdfDocument : public QObject, public QQmlParserStatus { Q_OBJECT @@ -128,15 +130,18 @@ Q_SIGNALS: private: QPdfDocument &document() { return m_doc; } + QPdfFile *carrierFile(); void updateMaxPageSize(); private: QUrl m_source; QUrl m_resolvedSource; QPdfDocument m_doc; + QPdfFile *m_carrierFile = nullptr; QSizeF m_maxPageWidthHeight; friend class QQuickPdfLinkModel; + friend class QQuickPdfPageImage; friend class QQuickPdfSearchModel; friend class QQuickPdfSelection; diff --git a/src/pdfquick/qquickpdfpageimage.cpp b/src/pdfquick/qquickpdfpageimage.cpp new file mode 100644 index 000000000..18513fba4 --- /dev/null +++ b/src/pdfquick/qquickpdfpageimage.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickpdfpageimage_p.h" +#include "qquickpdfdocument_p.h" +#include <private/qpdffile_p.h> +#include <QtPdf/QPdfPageNavigation> +#include <QtQuick/private/qquickimage_p_p.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcImg, "qt.pdf.image") + +/*! + \qmltype PdfPageImage + \instantiates QQuickPdfPageImage + \inqmlmodule QtPdf + \ingroup pdf + \inherits Item + \brief Displays one page from a PDF document. + \since 6.4 + + The PdfPageImage type is an Image specialized to render a page from a PDF document. +*/ + +class QQuickPdfPageImagePrivate: public QQuickImagePrivate +{ +public: + QQuickPdfPageImagePrivate() : QQuickImagePrivate() {} + + QQuickPdfDocument *doc = nullptr; +}; + +QQuickPdfPageImage::QQuickPdfPageImage(QQuickItem *parent) + : QQuickImage(*(new QQuickPdfPageImagePrivate), parent) +{ +} + +QQuickPdfPageImage::~QQuickPdfPageImage() +{ + Q_D(QQuickPdfPageImage); + // cancel any async rendering job that is running on my behalf + d->pix.clear(); +} + +void QQuickPdfPageImage::setDocument(QQuickPdfDocument *document) +{ + Q_D(QQuickPdfPageImage); + if (d->doc == document) + return; + + if (d->doc) + disconnect(d->doc, &QQuickPdfDocument::statusChanged, this, &QQuickPdfPageImage::documentStatusChanged); + d->doc = document; + if (document) { + connect(document, &QQuickPdfDocument::statusChanged, this, &QQuickPdfPageImage::documentStatusChanged); + if (document->status() == QPdfDocument::Status::Ready) + setSource(document->resolvedSource()); // calls load() + } + emit documentChanged(); +} + +QQuickPdfDocument *QQuickPdfPageImage::document() const +{ + Q_D(const QQuickPdfPageImage); + return d->doc; +} + +void QQuickPdfPageImage::load() +{ + Q_D(QQuickPdfPageImage); + auto carrierFile = d->doc->carrierFile(); + static int thisRequestProgress = -1; + static int thisRequestFinished = -1; + if (thisRequestProgress == -1) { + thisRequestProgress = + QQuickImageBase::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)"); + thisRequestFinished = + QQuickImageBase::staticMetaObject.indexOfSlot("requestFinished()"); + } + + d->pix.loadImageFromDevice(qmlEngine(this), carrierFile, d->url, + d->sourceClipRect.toRect(), d->sourcesize * d->devicePixelRatio, + QQuickImageProviderOptions(), d->currentFrame, d->frameCount); + + qCDebug(qLcImg) << "loading page" << d->currentFrame << "of" << d->frameCount + << "from" << carrierFile->fileName() << "status" << d->pix.status(); + + switch (d->pix.status()) { + case QQuickPixmap::Ready: + pixmapChange(); + break; + case QQuickPixmap::Loading: + d->pix.connectFinished(this, thisRequestFinished); + d->pix.connectDownloadProgress(this, thisRequestProgress); + if (d->progress != 0.0) { + d->progress = 0.0; + emit progressChanged(d->progress); + } + if (d->status != Loading) { + d->status = Loading; + emit statusChanged(d->status); + } + break; + default: + qCDebug(qLcImg) << "unexpected status" << d->pix.status(); + break; + } +} + +void QQuickPdfPageImage::documentStatusChanged() +{ + Q_D(QQuickPdfPageImage); + qCDebug(qLcImg) << "document status" << d->doc->status(); + if (d->doc->status() == QPdfDocument::Status::Ready) + setSource(d->doc->resolvedSource()); // calls load() +} + +QT_END_NAMESPACE diff --git a/src/pdfquick/qquickpdfpageimage_p.h b/src/pdfquick/qquickpdfpageimage_p.h new file mode 100644 index 000000000..b77a4f037 --- /dev/null +++ b/src/pdfquick/qquickpdfpageimage_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPDFPAGEIMAGE_P_H +#define QQUICKPDFPAGEIMAGE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtPdfQuick/private/qtpdfquickglobal_p.h> +#include <QtQuick/private/qquickimage_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickPdfDocument; +class QQuickPdfPageImagePrivate; +class Q_PDFQUICK_EXPORT QQuickPdfPageImage : public QQuickImage +{ + Q_OBJECT + Q_PROPERTY(QQuickPdfDocument* document READ document WRITE setDocument NOTIFY documentChanged FINAL) + Q_PROPERTY(int currentPage READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged FINAL) + QML_NAMED_ELEMENT(PdfPageImage) + QML_ADDED_IN_VERSION(6, 4) + +public: + QQuickPdfPageImage(QQuickItem *parent = nullptr); + ~QQuickPdfPageImage(); + + void setDocument(QQuickPdfDocument *document); + QQuickPdfDocument *document() const; + +signals: + void documentChanged(); + +protected: + void load() override; + void documentStatusChanged(); + +private: + Q_DECLARE_PRIVATE(QQuickPdfPageImage) +}; + +QT_END_NAMESPACE + +#endif // QQUICKPDFPAGEIMAGE_P_H |