summaryrefslogtreecommitdiff
path: root/src/pdfquick
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2020-01-10 07:47:52 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2022-03-03 06:05:18 +0100
commit7b8832ca2b84d549c9d374550c3c46b3d4d42a38 (patch)
tree47eed7bcd915b7db53d06e8cef749cf6df913609 /src/pdfquick
parentaf190c9d05d2a5afc2de4dd9b2172fec8e4ce3b7 (diff)
downloadqtwebengine-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.txt1
-rw-r--r--src/pdfquick/PdfMultiPageView.qml10
-rw-r--r--src/pdfquick/PdfPageView.qml6
-rw-r--r--src/pdfquick/PdfScrollablePageView.qml6
-rw-r--r--src/pdfquick/qquickpdfdocument.cpp13
-rw-r--r--src/pdfquick/qquickpdfdocument_p.h5
-rw-r--r--src/pdfquick/qquickpdfpageimage.cpp155
-rw-r--r--src/pdfquick/qquickpdfpageimage_p.h89
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