summaryrefslogtreecommitdiffstats
path: root/src/pdf
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2019-08-26 10:13:55 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2020-01-21 21:22:14 +0100
commit9968e2578f96081d2a242340620fcb2b96d9a1d3 (patch)
treed6fb8b53b4c66f7d11a0fa372e9db6aecbf15c1a /src/pdf
parente3536648d338cd0d0d96e6b5c8a82d4211db3312 (diff)
Add QtQuick.Pdf module with QQuickPdfDocument; manual tests
QQuickPdfDocument is a wrapper for QPdfDocument providing appropriate QML API. Task-number: QTBUG-77506 Change-Id: Ifa2ef50d3d31179f1955c2f673495e727b962bd1 Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'src/pdf')
-rw-r--r--src/pdf/api/qpdfdocument.h1
-rw-r--r--src/pdf/pdf.pro4
-rw-r--r--src/pdf/qpdfdocument.cpp27
-rw-r--r--src/pdf/quick/plugin.cpp87
-rw-r--r--src/pdf/quick/plugins.qmltypes52
-rw-r--r--src/pdf/quick/qmldir4
-rw-r--r--src/pdf/quick/qquickpdfdocument.cpp202
-rw-r--r--src/pdf/quick/qquickpdfdocument_p.h125
-rw-r--r--src/pdf/quick/quick.pro17
9 files changed, 514 insertions, 5 deletions
diff --git a/src/pdf/api/qpdfdocument.h b/src/pdf/api/qpdfdocument.h
index 50525eb9d..a0a2a21be 100644
--- a/src/pdf/api/qpdfdocument.h
+++ b/src/pdf/api/qpdfdocument.h
@@ -68,6 +68,7 @@ public:
enum DocumentError {
NoError,
UnknownError,
+ DataNotYetAvailableError,
FileNotFoundError,
InvalidFileFormatError,
IncorrectPasswordError,
diff --git a/src/pdf/pdf.pro b/src/pdf/pdf.pro
index 251b10a1b..c5513ce93 100644
--- a/src/pdf/pdf.pro
+++ b/src/pdf/pdf.pro
@@ -5,10 +5,12 @@ gn_run.file = gn_run.pro
gn_run.depends = pdfcore_generator
pdfcore.depends = gn_run
+quick.depends = pdfcore
SUBDIRS += \
pdfcore_generator \
gn_run \
- pdfcore
+ pdfcore \
+ quick
diff --git a/src/pdf/qpdfdocument.cpp b/src/pdf/qpdfdocument.cpp
index 5c6a9e078..690953691 100644
--- a/src/pdf/qpdfdocument.cpp
+++ b/src/pdf/qpdfdocument.cpp
@@ -39,7 +39,12 @@
#include "third_party/pdfium/public/fpdf_doc.h"
+#include <QDateTime>
+#include <QDebug>
+#include <QElapsedTimer>
#include <QFile>
+#include <QHash>
+#include <QLoggingCategory>
#include <QMutex>
QT_BEGIN_NAMESPACE
@@ -47,6 +52,7 @@ QT_BEGIN_NAMESPACE
// The library is not thread-safe at all, it has a lot of global variables.
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, pdfMutex, (QMutex::Recursive));
static int libraryRefCount;
+Q_LOGGING_CATEGORY(qLcDoc, "qt.pdf.document")
QPdfMutexLocker::QPdfMutexLocker()
: QMutexLocker(pdfMutex())
@@ -237,9 +243,19 @@ void QPdfDocumentPrivate::_q_copyFromSequentialSourceDevice()
void QPdfDocumentPrivate::tryLoadDocument()
{
QPdfMutexLocker lock;
-
- if (!FPDFAvail_IsDocAvail(avail, this))
- return;
+ switch (FPDFAvail_IsDocAvail(avail, this)) {
+ case PDF_DATA_ERROR:
+ qCDebug(qLcDoc) << "error loading";
+ break;
+ case PDF_DATA_NOTAVAIL:
+ qCDebug(qLcDoc) << "data not yet available";
+ lastError = QPdfDocument::DataNotYetAvailableError;
+ setStatus(QPdfDocument::Error);
+ break;
+ case PDF_DATA_AVAIL:
+ // all good
+ break;
+ }
Q_ASSERT(!doc);
@@ -570,6 +586,9 @@ QImage QPdfDocument::render(int page, QSize imageSize, QPdfDocumentRenderOptions
const QPdfMutexLocker lock;
+ QElapsedTimer timer;
+ if (Q_UNLIKELY(qLcDoc().isDebugEnabled()))
+ timer.start();
FPDF_PAGE pdfPage = FPDF_LoadPage(d->doc, page);
if (!pdfPage)
return QImage();
@@ -616,7 +635,7 @@ QImage QPdfDocument::render(int page, QSize imageSize, QPdfDocumentRenderOptions
FPDFBitmap_Destroy(bitmap);
FPDF_ClosePage(pdfPage);
-
+ qCDebug(qLcDoc) << "page" << page << imageSize << "took" << timer.elapsed() << "ms";
return result;
}
diff --git a/src/pdf/quick/plugin.cpp b/src/pdf/quick/plugin.cpp
new file mode 100644
index 000000000..59aca576b
--- /dev/null
+++ b/src/pdf/quick/plugin.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtPDF module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQml/qqml.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlextensionplugin.h>
+#include "qquickpdfdocument_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlmodule QtQuick.Pdf 5.15
+ \title Qt Quick PDF QML Types
+ \ingroup qmlmodules
+ \brief Provides QML types for handling PDF documents.
+
+ This QML module contains types for handling PDF documents.
+
+ To use the types in this module, import the module with the following line:
+
+ \code
+ import QtQuick.Pdf 5.15
+ \endcode
+*/
+
+class QtQuick2PdfPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+ QtQuick2PdfPlugin() : QQmlExtensionPlugin() { }
+
+ void initializeEngine(QQmlEngine *engine, const char *uri) override {
+ Q_UNUSED(uri);
+#ifndef QT_STATIC
+ engine->addImportPath(QStringLiteral("qrc:/"));
+#endif
+ }
+
+ void registerTypes(const char *uri) override {
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Pdf"));
+
+ // Register the latest version, even if there are no new types or new revisions for existing types yet.
+ qmlRegisterModule(uri, 2, QT_VERSION_MINOR);
+
+ qmlRegisterType<QQuickPdfDocument>(uri, 5, 15, "PdfDocument");
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/pdf/quick/plugins.qmltypes b/src/pdf/quick/plugins.qmltypes
new file mode 100644
index 000000000..a30361d33
--- /dev/null
+++ b/src/pdf/quick/plugins.qmltypes
@@ -0,0 +1,52 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQuick.Pdf 5.14'
+
+Module {
+ dependencies: [
+ "QtGraphicalEffects 1.12",
+ "QtQuick 2.14",
+ "QtQuick.Controls 2.14",
+ "QtQuick.Controls.Fusion 2.14",
+ "QtQuick.Controls.Fusion.impl 2.14",
+ "QtQuick.Controls.Imagine 2.14",
+ "QtQuick.Controls.Imagine.impl 2.14",
+ "QtQuick.Controls.Material 2.14",
+ "QtQuick.Controls.Material.impl 2.14",
+ "QtQuick.Controls.Universal 2.14",
+ "QtQuick.Controls.Universal.impl 2.12",
+ "QtQuick.Controls.impl 2.14",
+ "QtQuick.Shapes 1.14",
+ "QtQuick.Templates 2.14",
+ "QtQuick.Window 2.2"
+ ]
+ Component {
+ name: "QQuickPdfDocument"
+ prototype: "QObject"
+ exports: ["QtQuick.Pdf/PdfDocument 5.14"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "source"; type: "QUrl" }
+ Property { name: "pageCount"; type: "int"; isReadonly: true }
+ Property { name: "password"; type: "string" }
+ Property { name: "status"; type: "QPdfDocument::Status"; isReadonly: true }
+ Property { name: "title"; type: "string"; isReadonly: true }
+ Property { name: "subject"; type: "string"; isReadonly: true }
+ Property { name: "author"; type: "string"; isReadonly: true }
+ Property { name: "keywords"; type: "string"; isReadonly: true }
+ Property { name: "producer"; type: "string"; isReadonly: true }
+ Property { name: "creator"; type: "string"; isReadonly: true }
+ Property { name: "creationDate"; type: "QDateTime"; isReadonly: true }
+ Property { name: "modificationDate"; type: "QDateTime"; isReadonly: true }
+ Signal { name: "passwordRequired" }
+ Signal { name: "metaDataLoaded" }
+ Method {
+ name: "pagePointSize"
+ type: "QSizeF"
+ Parameter { name: "page"; type: "int" }
+ }
+ }
+}
diff --git a/src/pdf/quick/qmldir b/src/pdf/quick/qmldir
new file mode 100644
index 000000000..65fa95cda
--- /dev/null
+++ b/src/pdf/quick/qmldir
@@ -0,0 +1,4 @@
+module QtQuick.Pdf
+plugin pdfplugin
+classname QtQuick2PdfPlugin
+typeinfo plugins.qmltypes
diff --git a/src/pdf/quick/qquickpdfdocument.cpp b/src/pdf/quick/qquickpdfdocument.cpp
new file mode 100644
index 000000000..f0f40c227
--- /dev/null
+++ b/src/pdf/quick/qquickpdfdocument.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtPDF module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickpdfdocument_p.h"
+#include <QQuickItem>
+#include <QQmlEngine>
+#include <QStandardPaths>
+#include <private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Document
+ \instantiates QQuickPdfDocument
+ \inqmlmodule QtQuick.Pdf
+ \ingroup pdf
+ \brief A representation of a PDF document.
+ \since 5.15
+
+ A Document provides access to PDF document meta-information.
+ It is not necessary for rendering, as it is enough to use an
+ \l Image with source set to the URL of the PDF.
+*/
+
+/*!
+ Constructs a PDF document.
+*/
+QQuickPdfDocument::QQuickPdfDocument(QObject *parent)
+ : QObject(parent)
+{
+ connect(&m_doc, &QPdfDocument::passwordChanged, this, &QQuickPdfDocument::passwordChanged);
+ connect(&m_doc, &QPdfDocument::passwordRequired, this, &QQuickPdfDocument::passwordRequired);
+ connect(&m_doc, &QPdfDocument::statusChanged, [=] (QPdfDocument::Status status) {
+ emit statusChanged();
+ if (status == QPdfDocument::Ready)
+ emit metaDataChanged();
+ });
+ connect(&m_doc, &QPdfDocument::pageCountChanged, this, &QQuickPdfDocument::pageCountChanged);
+}
+
+void QQuickPdfDocument::componentComplete()
+{
+ if (m_doc.error() == QPdfDocument::IncorrectPasswordError)
+ emit passwordRequired();
+}
+
+/*!
+ \qmlproperty url Document::source
+
+ This property holds a URL pointing to the PDF file to be loaded.
+
+ \note At this time, only local filesystem URLs are supported.
+*/
+void QQuickPdfDocument::setSource(QUrl source)
+{
+ if (m_source == source)
+ return;
+
+ m_source = source;
+ emit sourceChanged();
+ m_doc.load(source.path());
+}
+
+/*!
+ \qmlproperty bool Document::password
+
+ This property holds the document password. If the passwordRequired()
+ signal is emitted, the UI should prompt the user and then set this
+ property so that document opening can continue.
+*/
+void QQuickPdfDocument::setPassword(const QString &password)
+{
+ if (m_doc.password() == password)
+ return;
+ m_doc.setPassword(password);
+ if (source().isValid() && source().isLocalFile())
+ m_doc.load(source().path());
+}
+
+/*!
+ \qmlproperty int Document::pageCount
+
+ This property holds the number of pages the PDF contains.
+*/
+
+/*!
+ \qmlsignal Document::passwordRequired()
+
+ This signal is emitted when the PDF requires a password in order to open.
+ The UI in a typical PDF viewer should prompt the user for the password
+ and then set the password property when the user has provided it.
+*/
+
+/*!
+ \qmlmethod size Document::pagePointSize(int page)
+
+ Returns the size of the given \a page in points.
+*/
+QSizeF QQuickPdfDocument::pagePointSize(int page) const
+{
+ return m_doc.pageSize(page);
+}
+
+/*!
+ \qmlproperty string Document::title
+
+ This property holds the document's title. A typical viewer UI can bind this
+ to the \c Window.title property.
+*/
+
+/*!
+ \qmlproperty string Document::author
+
+ This property holds the name of the person who created the document.
+*/
+
+/*!
+ \qmlproperty string Document::subject
+
+ This property holds the subject of the document.
+*/
+
+/*!
+ \qmlproperty string Document::keywords
+
+ This property holds the keywords associated with the document.
+*/
+
+/*!
+ \qmlproperty string Document::creator
+
+ If the document was converted to PDF from another format, this property
+ holds the name of the software that created the original document.
+*/
+
+/*!
+ \qmlproperty string Document::producer
+
+ If the document was converted to PDF from another format, this property
+ holds the name of the software that converted it to PDF.
+*/
+
+/*!
+ \qmlproperty string Document::creationDate
+
+ This property holds the date and time the document was created.
+*/
+
+/*!
+ \qmlproperty string Document::modificationDate
+
+ This property holds the date and time the document was most recently
+ modified.
+*/
+
+/*!
+ \qmlproperty enum Document::status
+
+ This property tells the current status of the document. The possible values are:
+
+ \value PdfDocument.Null The initial status after the document has been created or after it has been closed.
+ \value PdfDocument.Loading The status after load() has been called and before the document is fully loaded.
+ \value PdfDocument.Ready The status when the document is fully loaded and its data can be accessed.
+ \value PdfDocument.Unloading The status after close() has been called on an open document.
+ At this point the document is still valid and all its data can be accessed.
+ \value PdfDocument.Error The status after Loading, if loading has failed.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/pdf/quick/qquickpdfdocument_p.h b/src/pdf/quick/qquickpdfdocument_p.h
new file mode 100644
index 000000000..ee6195679
--- /dev/null
+++ b/src/pdf/quick/qquickpdfdocument_p.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtPDF module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKPDFDOCUMENT_P_H
+#define QQUICKPDFDOCUMENT_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 <QtPdf/QPdfDocument>
+#include <QDateTime>
+#include <QJSValue>
+#include <QQmlParserStatus>
+#include <QUrl>
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPdfDocument : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
+ Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged FINAL)
+ Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged FINAL)
+ Q_PROPERTY(QPdfDocument::Status status READ status NOTIFY statusChanged FINAL)
+
+ Q_PROPERTY(QString title READ title NOTIFY metaDataChanged)
+ Q_PROPERTY(QString subject READ subject NOTIFY metaDataChanged)
+ Q_PROPERTY(QString author READ author NOTIFY metaDataChanged)
+ Q_PROPERTY(QString keywords READ keywords NOTIFY metaDataChanged)
+ Q_PROPERTY(QString producer READ producer NOTIFY metaDataChanged)
+ Q_PROPERTY(QString creator READ creator NOTIFY metaDataChanged)
+ Q_PROPERTY(QDateTime creationDate READ creationDate NOTIFY metaDataChanged)
+ Q_PROPERTY(QDateTime modificationDate READ modificationDate NOTIFY metaDataChanged)
+
+public:
+ explicit QQuickPdfDocument(QObject *parent = nullptr);
+
+ void classBegin() override {}
+ void componentComplete() override;
+
+ QUrl source() const { return m_source; }
+ void setSource(QUrl source);
+
+ int pageCount() const { return m_doc.pageCount(); }
+ QPdfDocument::Status status() const { return m_doc.status(); }
+
+ QString password() const { return m_doc.password(); }
+ void setPassword(const QString &password);
+
+ QString title() { return m_doc.metaData(QPdfDocument::Title).toString(); }
+ QString author() { return m_doc.metaData(QPdfDocument::Author).toString(); }
+ QString subject() { return m_doc.metaData(QPdfDocument::Subject).toString(); }
+ QString keywords() { return m_doc.metaData(QPdfDocument::Keywords).toString(); }
+ QString producer() { return m_doc.metaData(QPdfDocument::Producer).toString(); }
+ QString creator() { return m_doc.metaData(QPdfDocument::Creator).toString(); }
+ QDateTime creationDate() { return m_doc.metaData(QPdfDocument::CreationDate).toDateTime(); }
+ QDateTime modificationDate() { return m_doc.metaData(QPdfDocument::ModificationDate).toDateTime(); }
+
+ Q_INVOKABLE QSizeF pagePointSize(int page) const;
+
+Q_SIGNALS:
+ void sourceChanged();
+ void passwordChanged();
+ void passwordRequired();
+ void statusChanged();
+ void pageCountChanged();
+ void metaDataChanged();
+
+private:
+ QPdfDocument &document() { return m_doc; }
+
+private:
+ QUrl m_source;
+ QPdfDocument m_doc;
+
+ friend class QQuickPdfSelection;
+
+ Q_DISABLE_COPY(QQuickPdfDocument)
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPDFDOCUMENT_P_H
diff --git a/src/pdf/quick/quick.pro b/src/pdf/quick/quick.pro
new file mode 100644
index 000000000..eb88bc003
--- /dev/null
+++ b/src/pdf/quick/quick.pro
@@ -0,0 +1,17 @@
+CXX_MODULE = qml
+TARGET = pdfplugin
+TARGETPATH = QtQuick/Pdf
+IMPORT_VERSION = 1.0
+
+#QMAKE_DOCS = $$PWD/doc/qtquickpdf.qdocconf
+
+SOURCES += \
+ qquickpdfdocument.cpp \
+ plugin.cpp
+
+HEADERS += \
+ qquickpdfdocument_p.h
+
+QT += pdf quick-private gui gui-private core core-private qml qml-private
+
+load(qml_plugin)