summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/examples.pro2
-rw-r--r--examples/pdf/pdf.pro3
-rw-r--r--examples/pdf/pdfviewer/main.cpp70
-rw-r--r--examples/pdf/pdfviewer/pdfviewer.pro14
-rw-r--r--examples/pdf/pdfviewer/resources/document-open.svg13
-rw-r--r--examples/pdf/pdfviewer/resources/edit-clear.svg15
-rw-r--r--examples/pdf/pdfviewer/resources/go-next-view-page.svg13
-rw-r--r--examples/pdf/pdfviewer/resources/go-previous-view-page.svg13
-rw-r--r--examples/pdf/pdfviewer/resources/zoom-in.svg13
-rw-r--r--examples/pdf/pdfviewer/resources/zoom-original.svg13
-rw-r--r--examples/pdf/pdfviewer/resources/zoom-out.svg13
-rw-r--r--examples/pdf/pdfviewer/viewer.qml188
-rw-r--r--examples/pdf/pdfviewer/viewer.qrc12
-rw-r--r--src/pdf/api/qpdfdocument.h1
-rw-r--r--src/pdf/api/qpdfsearchmodel.h74
-rw-r--r--src/pdf/pdfcore.pro8
-rw-r--r--src/pdf/qpdfsearchmodel.cpp115
-rw-r--r--src/pdf/qpdfsearchmodel_p.h56
-rw-r--r--src/pdf/quick/plugin.cpp4
-rw-r--r--src/pdf/quick/qml/PdfPageView.qml120
-rw-r--r--src/pdf/quick/qquickpdfdocument.cpp35
-rw-r--r--src/pdf/quick/qquickpdfdocument_p.h4
-rw-r--r--src/pdf/quick/qquickpdfsearchmodel.cpp165
-rw-r--r--src/pdf/quick/qquickpdfsearchmodel_p.h103
-rw-r--r--src/pdf/quick/quick.pro13
-rw-r--r--src/pdf/quick/resources.qrc5
-rw-r--r--tests/auto/pdf/qpdfsearchmodel/qpdfsearchmodel.pro5
-rw-r--r--tests/auto/pdf/qpdfsearchmodel/test.pdfbin0 -> 80045 bytes
-rw-r--r--tests/auto/pdf/qpdfsearchmodel/tst_qpdfsearchmodel.cpp69
29 files changed, 1154 insertions, 5 deletions
diff --git a/examples/examples.pro b/examples/examples.pro
index 825cacaae..b4f411aeb 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -5,3 +5,5 @@ qtHaveModule(webengine): SUBDIRS += webengine
qtHaveModule(webenginewidgets): SUBDIRS += webenginewidgets
qtHaveModule(pdfwidgets): SUBDIRS += pdfwidgets
+
+qtHaveModule(quick): qtHaveModule(pdf): qtHaveModule(pdfwidgets): SUBDIRS += pdf
diff --git a/examples/pdf/pdf.pro b/examples/pdf/pdf.pro
new file mode 100644
index 000000000..45df33e46
--- /dev/null
+++ b/examples/pdf/pdf.pro
@@ -0,0 +1,3 @@
+TEMPLATE=subdirs
+
+SUBDIRS += pdfviewer
diff --git a/examples/pdf/pdfviewer/main.cpp b/examples/pdf/pdfviewer/main.cpp
new file mode 100644
index 000000000..6b94a3de1
--- /dev/null
+++ b/examples/pdf/pdfviewer/main.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char* argv[])
+{
+ QApplication app(argc, argv);
+ QCoreApplication::setApplicationName("Qt Quick PDF Viewer Example");
+ QCoreApplication::setOrganizationName("QtProject");
+ QCoreApplication::setApplicationVersion(QT_VERSION_STR);
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:///pdfviewer/viewer.qml")));
+ if (app.arguments().count() > 1) {
+ QUrl toLoad = QUrl::fromUserInput(app.arguments().at(1));
+ engine.rootObjects().first()->setProperty("source", toLoad);
+ }
+
+ return app.exec();
+}
diff --git a/examples/pdf/pdfviewer/pdfviewer.pro b/examples/pdf/pdfviewer/pdfviewer.pro
new file mode 100644
index 000000000..697349cee
--- /dev/null
+++ b/examples/pdf/pdfviewer/pdfviewer.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+
+QT += qml quick pdf widgets
+
+SOURCES += main.cpp
+
+RESOURCES += \
+ viewer.qrc
+EXAMPLE_FILES = \
+ viewer.qml
+
+target.path = $$[QT_INSTALL_EXAMPLES]/pdf/pdfviewer
+INSTALLS += target
+
diff --git a/examples/pdf/pdfviewer/resources/document-open.svg b/examples/pdf/pdfviewer/resources/document-open.svg
new file mode 100644
index 000000000..bf23123a3
--- /dev/null
+++ b/examples/pdf/pdfviewer/resources/document-open.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="m4 4v24h24l-1-1h-22v-13h5l3-3h14v16l1 1v-21h-10l-3-3z"
+ class="ColorScheme-Text"
+ />
+</svg>
diff --git a/examples/pdf/pdfviewer/resources/edit-clear.svg b/examples/pdf/pdfviewer/resources/edit-clear.svg
new file mode 100644
index 000000000..1c35aaf04
--- /dev/null
+++ b/examples/pdf/pdfviewer/resources/edit-clear.svg
@@ -0,0 +1,15 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path
+ style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="M 8 3 L 0.94335938 10.056641 L 0 11 L 0.94335938 11.943359 L 8 19 L 20.333984 19 L 22 19 L 22 3 L 20.333984 3 L 8 3 z M 11.320312 7 L 14 9.6796875 L 16.679688 7 L 18 8.3203125 L 15.320312 11 L 18 13.679688 L 16.679688 15 L 14 12.320312 L 11.320312 15 L 10 13.679688 L 12.679688 11 L 10 8.3203125 L 11.320312 7 z "
+ class="ColorScheme-Text"
+ transform="translate(1,1)"
+ />
+</svg>
diff --git a/examples/pdf/pdfviewer/resources/go-next-view-page.svg b/examples/pdf/pdfviewer/resources/go-next-view-page.svg
new file mode 100644
index 000000000..e453ddbec
--- /dev/null
+++ b/examples/pdf/pdfviewer/resources/go-next-view-page.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="M 8.7070312 4 L 8 4.7070312 L 14.125 10.832031 L 15.292969 12 L 14.125 13.167969 L 8 19.292969 L 8.7070312 20 L 14.832031 13.875 L 16.707031 12 L 14.832031 10.125 L 8.7070312 4 z "
+ class="ColorScheme-Text"
+ />
+</svg>
diff --git a/examples/pdf/pdfviewer/resources/go-previous-view-page.svg b/examples/pdf/pdfviewer/resources/go-previous-view-page.svg
new file mode 100644
index 000000000..b032309e9
--- /dev/null
+++ b/examples/pdf/pdfviewer/resources/go-previous-view-page.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="M 15.292969 4 L 9.1679688 10.125 L 7.2929688 12 L 9.1679688 13.875 L 15.292969 20 L 16 19.292969 L 9.875 13.167969 L 8.7070312 12 L 9.875 10.832031 L 16 4.7070312 L 15.292969 4 z "
+ class="ColorScheme-Text"
+ />
+</svg>
diff --git a/examples/pdf/pdfviewer/resources/zoom-in.svg b/examples/pdf/pdfviewer/resources/zoom-in.svg
new file mode 100644
index 000000000..efdc9f17d
--- /dev/null
+++ b/examples/pdf/pdfviewer/resources/zoom-in.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="M 4 4 L 4 6 L 5 6 L 5 5 L 6 5 L 6 4 L 4 4 z M 9 4 L 9 5 L 11 5 L 11 4 L 9 4 z M 13 4 L 13 5 L 15 5 L 15 4 L 13 4 z M 18 4 L 18 5 L 19 5 L 19 6 L 20 6 L 20 4 L 18 4 z M 12 8 L 12 9 L 14.292969 9 L 11 12.292969 L 11.707031 13 L 15 9.7070312 L 15 12 L 16 12 L 16 8 L 15 8 L 12 8 z M 4 9 L 4 11 L 5 11 L 5 9 L 4 9 z M 19 9 L 19 11 L 20 11 L 20 9 L 19 9 z M 19 13 L 19 15 L 20 15 L 20 13 L 19 13 z M 4 14 L 4 20 L 10 20 L 10 14 L 4 14 z M 5 15 L 9 15 L 9 19 L 5 19 L 5 15 z M 19 18 L 19 19 L 18 19 L 18 20 L 20 20 L 20 18 L 19 18 z "
+ class="ColorScheme-Text"
+ />
+</svg>
diff --git a/examples/pdf/pdfviewer/resources/zoom-original.svg b/examples/pdf/pdfviewer/resources/zoom-original.svg
new file mode 100644
index 000000000..1b4080a03
--- /dev/null
+++ b/examples/pdf/pdfviewer/resources/zoom-original.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="M 4 4 L 4 5 L 4 7 L 5 7 L 5 5 L 7 5 L 7 4 L 5 4 L 4 4 z M 17 4 L 17 5 L 19 5 L 19 7 L 20 7 L 20 5 L 20 4 L 19 4 L 17 4 z M 6 6 L 6 18 L 18 18 L 18 6 L 6 6 z M 7 7 L 17 7 L 17 17 L 7 17 L 7 7 z M 4 17 L 4 19 L 4 20 L 7 20 L 7 19 L 5 19 L 5 17 L 4 17 z M 19 17 L 19 19 L 17 19 L 17 20 L 20 20 L 20 17 L 19 17 z "
+ class="ColorScheme-Text"
+ />
+</svg>
diff --git a/examples/pdf/pdfviewer/resources/zoom-out.svg b/examples/pdf/pdfviewer/resources/zoom-out.svg
new file mode 100644
index 000000000..fcde9e526
--- /dev/null
+++ b/examples/pdf/pdfviewer/resources/zoom-out.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
+ <defs id="defs3051">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ </defs>
+ <path style="fill:currentColor;fill-opacity:1;stroke:none"
+ d="M 4 4 L 4 11 L 5 11 L 5 5 L 19 5 L 19 19 L 13 19 L 13 20 L 20 20 L 20 19 L 20 5 L 20 4 L 5 4 L 4 4 z M 15.292969 8 L 12 11.292969 L 12 9 L 11 9 L 11 13 L 12 13 L 15 13 L 15 12 L 12.707031 12 L 16 8.7070312 L 15.292969 8 z M 4 14 L 4 16 L 5 16 L 5 15 L 6 15 L 6 14 L 4 14 z M 8 14 L 8 15 L 9 15 L 9 16 L 10 16 L 10 14 L 8 14 z M 4 18 L 4 20 L 6 20 L 6 19 L 5 19 L 5 18 L 4 18 z M 9 18 L 9 19 L 8 19 L 8 20 L 10 20 L 10 18 L 9 18 z "
+ class="ColorScheme-Text"
+ />
+</svg>
diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml
new file mode 100644
index 000000000..47853aa31
--- /dev/null
+++ b/examples/pdf/pdfviewer/viewer.qml
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import QtQuick.Pdf 5.15
+import QtQuick.Shapes 1.15
+import QtQuick.Window 2.15
+import Qt.labs.platform 1.1 as Platform
+
+ApplicationWindow {
+ id: root
+ width: 800
+ height: 640
+ color: "lightgrey"
+ title: document.title
+ visible: true
+ property alias source: document.source // for main.cpp
+ property real scaleStep: Math.sqrt(2)
+
+ header: ToolBar {
+ RowLayout {
+ anchors.fill: parent
+ anchors.rightMargin: 6
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.Open
+ icon.source: "resources/document-open.svg"
+ onTriggered: fileDialog.open()
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomIn
+ enabled: pageView.sourceSize.width < 10000
+ icon.source: "resources/zoom-in.svg"
+ onTriggered: pageView.renderScale *= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomOut
+ enabled: pageView.sourceSize.width > 50
+ icon.source: "resources/zoom-out.svg"
+ onTriggered: pageView.renderScale /= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: "Ctrl+0"
+ icon.source: "resources/zoom-original.svg"
+ onTriggered: pageView.renderScale = 1
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.MoveToPreviousPage
+ icon.source: "resources/go-previous-view-page.svg"
+ enabled: pageView.currentPage > 0
+ onTriggered: pageView.currentPage--
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.MoveToNextPage
+ icon.source: "resources/go-next-view-page.svg"
+ enabled: pageView.currentPage < pageView.pageCount - 1
+ onTriggered: pageView.currentPage++
+ }
+ }
+ TextField {
+ id: searchField
+ placeholderText: "search"
+ Layout.minimumWidth: 200
+ Layout.fillWidth: true
+ Image {
+ visible: searchField.text !== ""
+ source: "resources/edit-clear.svg"
+ anchors {
+ right: parent.right
+ top: parent.top
+ bottom: parent.bottom
+ margins: 3
+ rightMargin: 5
+ }
+ TapHandler {
+ onTapped: searchField.clear()
+ }
+ }
+ }
+ Shortcut {
+ sequence: StandardKey.Find
+ onActivated: searchField.forceActiveFocus()
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+ }
+ }
+
+ Platform.FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: document.source = file
+ }
+
+ Dialog {
+ id: errorDialog
+ title: "Error loading " + document.source
+ standardButtons: Dialog.Ok
+ modal: true
+ closePolicy: Popup.CloseOnEscape
+ anchors.centerIn: parent
+ width: 300
+
+ Label {
+ id: errorField
+ text: document.error
+ }
+ }
+
+ PdfPageView {
+ id: pageView
+ document: PdfDocument {
+ id: document
+ onStatusChanged: if (status === PdfDocument.Error) errorDialog.open()
+ }
+ searchString: searchField.text
+ }
+
+ footer: Label {
+ property size implicitPointSize: document.pagePointSize(pageView.currentPage)
+ text: "page " + (pageView.currentPage + 1) + " of " + pageView.pageCount +
+ " scale " + pageView.renderScale.toFixed(2) +
+ " sourceSize " + pageView.sourceSize.width.toFixed(1) + "x" + pageView.sourceSize.height.toFixed(1) +
+ " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1)
+ visible: pageView.pageCount > 0
+ }
+}
diff --git a/examples/pdf/pdfviewer/viewer.qrc b/examples/pdf/pdfviewer/viewer.qrc
new file mode 100644
index 000000000..59045b75c
--- /dev/null
+++ b/examples/pdf/pdfviewer/viewer.qrc
@@ -0,0 +1,12 @@
+<RCC>
+ <qresource prefix="/pdfviewer">
+ <file>viewer.qml</file>
+ <file>resources/edit-clear.svg</file>
+ <file>resources/go-next-view-page.svg</file>
+ <file>resources/go-previous-view-page.svg</file>
+ <file>resources/zoom-in.svg</file>
+ <file>resources/zoom-original.svg</file>
+ <file>resources/zoom-out.svg</file>
+ <file>resources/document-open.svg</file>
+ </qresource>
+</RCC>
diff --git a/src/pdf/api/qpdfdocument.h b/src/pdf/api/qpdfdocument.h
index a0a2a21be..1252fa6d2 100644
--- a/src/pdf/api/qpdfdocument.h
+++ b/src/pdf/api/qpdfdocument.h
@@ -119,6 +119,7 @@ Q_SIGNALS:
private:
friend class QPdfBookmarkModelPrivate;
+ friend class QPdfSearchModel;
Q_PRIVATE_SLOT(d, void _q_tryLoadingWithSizeFromContentHeader())
Q_PRIVATE_SLOT(d, void _q_copyFromSequentialSourceDevice())
diff --git a/src/pdf/api/qpdfsearchmodel.h b/src/pdf/api/qpdfsearchmodel.h
new file mode 100644
index 000000000..02d2a20d5
--- /dev/null
+++ b/src/pdf/api/qpdfsearchmodel.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** 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 QPDFSEARCHMODEL_H
+#define QPDFSEARCHMODEL_H
+
+#include "qtpdfglobal.h"
+#include "qpdfdocument.h"
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QPdfSearchModelPrivate;
+
+class Q_PDF_EXPORT QPdfSearchModel : public QObject // TODO QAIM?
+{
+ Q_OBJECT
+ Q_PROPERTY(QPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged)
+
+public:
+ explicit QPdfSearchModel(QObject *parent = nullptr);
+ ~QPdfSearchModel();
+
+ QVector<QRectF> matches(int page, const QString &searchString);
+
+ QPdfDocument *document() const;
+
+public Q_SLOTS:
+ void setDocument(QPdfDocument *document);
+
+Q_SIGNALS:
+ void documentChanged();
+
+private:
+ QScopedPointer<QPdfSearchModelPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPDFSEARCHMODEL_H
diff --git a/src/pdf/pdfcore.pro b/src/pdf/pdfcore.pro
index 5314d30d2..1f9f21e0a 100644
--- a/src/pdf/pdfcore.pro
+++ b/src/pdf/pdfcore.pro
@@ -62,7 +62,8 @@ SOURCES += \
qpdfbookmarkmodel.cpp \
qpdfdocument.cpp \
qpdfpagenavigation.cpp \
- qpdfpagerenderer.cpp
+ qpdfpagerenderer.cpp \
+ qpdfsearchmodel.cpp \
# all "public" headers must be in "api" for sync script and to hide auto generated headers
# by Chromium in case of in-source build
@@ -72,10 +73,11 @@ HEADERS += \
api/qpdfdocument.h \
api/qpdfdocument_p.h \
api/qpdfdocumentrenderoptions.h \
+ api/qtpdfglobal.h \
api/qpdfnamespace.h \
api/qpdfpagenavigation.h \
api/qpdfpagerenderer.h \
- api/qtpdfglobal.h \
- api/qpdfdocument_p.h
+ api/qpdfsearchmodel.h \
+ qpdfsearchmodel_p.h \
load(qt_module)
diff --git a/src/pdf/qpdfsearchmodel.cpp b/src/pdf/qpdfsearchmodel.cpp
new file mode 100644
index 000000000..9010d76d3
--- /dev/null
+++ b/src/pdf/qpdfsearchmodel.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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 "qpdfsearchmodel.h"
+#include "qpdfsearchmodel_p.h"
+#include "qpdfdocument_p.h"
+
+#include "third_party/pdfium/public/fpdf_doc.h"
+#include "third_party/pdfium/public/fpdf_text.h"
+
+#include <QLoggingCategory>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(qLcS, "qt.pdf.search")
+
+QPdfSearchModel::QPdfSearchModel(QObject *parent)
+ : QObject(parent),
+ d(new QPdfSearchModelPrivate())
+{
+}
+
+QPdfSearchModel::~QPdfSearchModel() {}
+
+QVector<QRectF> QPdfSearchModel::matches(int page, const QString &searchString)
+{
+ const QPdfMutexLocker lock;
+ FPDF_PAGE pdfPage = FPDF_LoadPage(d->document->d->doc, page);
+ if (!pdfPage) {
+ qWarning() << "failed to load page" << page;
+ return {};
+ }
+ double pageHeight = FPDF_GetPageHeight(pdfPage);
+ FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage);
+ if (!textPage) {
+ qWarning() << "failed to load text of page" << page;
+ FPDF_ClosePage(pdfPage);
+ return {};
+ }
+ QVector<QRectF> ret;
+ if (searchString.isEmpty())
+ return ret;
+ FPDF_SCHHANDLE sh = FPDFText_FindStart(textPage, searchString.utf16(), 0, 0);
+ while (FPDFText_FindNext(sh)) {
+ int idx = FPDFText_GetSchResultIndex(sh);
+ int count = FPDFText_GetSchCount(sh);
+ int rectCount = FPDFText_CountRects(textPage, idx, count);
+ qCDebug(qLcS) << searchString << ": matched" << count << "chars @" << idx << "across" << rectCount << "rects";
+ for (int r = 0; r < rectCount; ++r) {
+ double left, top, right, bottom;
+ FPDFText_GetRect(textPage, r, &left, &top, &right, &bottom);
+ ret << QRectF(left, pageHeight - top, right - left, top - bottom);
+ qCDebug(qLcS) << ret.last();
+ }
+ }
+ FPDFText_FindClose(sh);
+ FPDFText_ClosePage(textPage);
+ FPDF_ClosePage(pdfPage);
+
+ return ret;
+}
+
+QPdfDocument *QPdfSearchModel::document() const
+{
+ return d->document;
+}
+
+void QPdfSearchModel::setDocument(QPdfDocument *document)
+{
+ if (d->document == document)
+ return;
+ d->document = document;
+ emit documentChanged();
+}
+
+QPdfSearchModelPrivate::QPdfSearchModelPrivate()
+{
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qpdfsearchmodel.cpp"
diff --git a/src/pdf/qpdfsearchmodel_p.h b/src/pdf/qpdfsearchmodel_p.h
new file mode 100644
index 000000000..90490d8e5
--- /dev/null
+++ b/src/pdf/qpdfsearchmodel_p.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** 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 QPDFSEARCHMODEL_P_H
+#define QPDFSEARCHMODEL_P_H
+
+#include "qpdfsearchmodel.h"
+
+#include "third_party/pdfium/public/fpdfview.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPdfSearchModelPrivate
+{
+public:
+ QPdfSearchModelPrivate();
+
+ QPdfDocument *document = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPDFSEARCHMODEL_P_H
diff --git a/src/pdf/quick/plugin.cpp b/src/pdf/quick/plugin.cpp
index 59aca576b..664ba51ab 100644
--- a/src/pdf/quick/plugin.cpp
+++ b/src/pdf/quick/plugin.cpp
@@ -39,6 +39,7 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlextensionplugin.h>
#include "qquickpdfdocument_p.h"
+#include "qquickpdfsearchmodel_p.h"
QT_BEGIN_NAMESPACE
@@ -79,6 +80,9 @@ public:
qmlRegisterModule(uri, 2, QT_VERSION_MINOR);
qmlRegisterType<QQuickPdfDocument>(uri, 5, 15, "PdfDocument");
+ qmlRegisterType<QQuickPdfSearchModel>(uri, 5, 15, "PdfSearchModel");
+
+ qmlRegisterType(QUrl("qrc:/qt-project.org/qtpdf/qml/PdfPageView.qml"), uri, 5, 15, "PdfPageView");
}
};
diff --git a/src/pdf/quick/qml/PdfPageView.qml b/src/pdf/quick/qml/PdfPageView.qml
new file mode 100644
index 000000000..adcdc807a
--- /dev/null
+++ b/src/pdf/quick/qml/PdfPageView.qml
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Pdf 5.15
+import QtQuick.Shapes 1.15
+
+Rectangle {
+ id: paper
+ width: image.width
+ height: image.height
+ transformOrigin: Item.TopLeft
+
+ // public API
+ // TODO 5.15: required property
+ property var document: null
+ property real renderScale: 1
+ property alias sourceSize: image.sourceSize
+ property alias currentPage: image.currentFrame
+ property alias pageCount: image.frameCount
+ property alias searchString: searchModel.searchString
+ property alias status: image.status
+
+ property real __pageScale: image.paintedWidth / document.pagePointSize(image.currentFrame).width
+
+ PdfSearchModel {
+ id: searchModel
+ document: paper.document
+ page: image.currentFrame
+ }
+
+ Image {
+ id: image
+ source: document.status === PdfDocument.Ready ? document.source : ""
+ asynchronous: true
+ fillMode: Image.PreserveAspectFit
+ }
+ function reRenderIfNecessary() {
+ var newSourceWidth = image.sourceSize.width * paper.scale
+ var ratio = newSourceWidth / image.sourceSize.width
+ if (ratio > 1.1 || ratio < 0.9) {
+ image.sourceSize.width = newSourceWidth
+ image.sourceSize.height = 1
+ paper.scale = 1
+ }
+ }
+ onRenderScaleChanged: {
+ image.sourceSize.width = document.pagePointSize(image.currentFrame).width * renderScale
+ image.sourceSize.height = 0
+ paper.scale = 1
+ }
+
+ Shape {
+ anchors.fill: parent
+ opacity: 0.25
+ visible: image.status === Image.Ready
+ ShapePath {
+ strokeWidth: 1
+ strokeColor: "blue"
+ fillColor: "cyan"
+ scale: Qt.size(paper.__pageScale, paper.__pageScale)
+ PathMultiline {
+ id: searchResultBoundaries
+ paths: searchModel.matchGeometry
+ }
+ }
+ }
+ PinchHandler {
+ id: pinch
+ minimumScale: 0.1
+ maximumScale: 10
+ minimumRotation: 0
+ maximumRotation: 0
+ onActiveChanged: if (!active) paper.reRenderIfNecessary()
+ grabPermissions: PinchHandler.TakeOverForbidden // don't allow takeover if pinch has started
+ }
+ DragHandler {
+ id: pageMovingTouchDrag
+ acceptedDevices: PointerDevice.TouchScreen
+ }
+ DragHandler {
+ id: pageMovingMiddleMouseDrag
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
+ acceptedButtons: Qt.MiddleButton
+ snapMode: DragHandler.NoSnap
+ }
+}
diff --git a/src/pdf/quick/qquickpdfdocument.cpp b/src/pdf/quick/qquickpdfdocument.cpp
index f0f40c227..73b3d4537 100644
--- a/src/pdf/quick/qquickpdfdocument.cpp
+++ b/src/pdf/quick/qquickpdfdocument.cpp
@@ -95,6 +95,41 @@ void QQuickPdfDocument::setSource(QUrl source)
}
/*!
+ \qmlproperty string Document::error
+
+ This property holds a translated string representation of the current
+ error, if any.
+
+ \sa status
+*/
+QString QQuickPdfDocument::error() const
+{
+ switch (m_doc.error()) {
+ case QPdfDocument::NoError:
+ return tr("no error");
+ break;
+ case QPdfDocument::UnknownError:
+ break;
+ case QPdfDocument::DataNotYetAvailableError:
+ return tr("data not yet available");
+ break;
+ case QPdfDocument::FileNotFoundError:
+ return tr("file not found");
+ break;
+ case QPdfDocument::InvalidFileFormatError:
+ return tr("invalid file format");
+ break;
+ case QPdfDocument::IncorrectPasswordError:
+ return tr("incorrect password");
+ break;
+ case QPdfDocument::UnsupportedSecuritySchemeError:
+ return tr("unsupported security scheme");
+ break;
+ }
+ return tr("unknown error");
+}
+
+/*!
\qmlproperty bool Document::password
This property holds the document password. If the passwordRequired()
diff --git a/src/pdf/quick/qquickpdfdocument_p.h b/src/pdf/quick/qquickpdfdocument_p.h
index ee6195679..1ec7edb1a 100644
--- a/src/pdf/quick/qquickpdfdocument_p.h
+++ b/src/pdf/quick/qquickpdfdocument_p.h
@@ -64,6 +64,7 @@ class QQuickPdfDocument : public QObject, public QQmlParserStatus
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 error READ error NOTIFY statusChanged FINAL)
Q_PROPERTY(QString title READ title NOTIFY metaDataChanged)
Q_PROPERTY(QString subject READ subject NOTIFY metaDataChanged)
@@ -86,6 +87,8 @@ public:
int pageCount() const { return m_doc.pageCount(); }
QPdfDocument::Status status() const { return m_doc.status(); }
+ QString error() const;
+
QString password() const { return m_doc.password(); }
void setPassword(const QString &password);
@@ -115,6 +118,7 @@ private:
QUrl m_source;
QPdfDocument m_doc;
+ friend class QQuickPdfSearchModel;
friend class QQuickPdfSelection;
Q_DISABLE_COPY(QQuickPdfDocument)
diff --git a/src/pdf/quick/qquickpdfsearchmodel.cpp b/src/pdf/quick/qquickpdfsearchmodel.cpp
new file mode 100644
index 000000000..8b0e88673
--- /dev/null
+++ b/src/pdf/quick/qquickpdfsearchmodel.cpp
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** 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 "qquickpdfsearchmodel_p.h"
+#include <QQuickItem>
+#include <QQmlEngine>
+#include <QStandardPaths>
+#include <private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype PdfSearchModel
+ \instantiates QQuickPdfSearchModel
+ \inqmlmodule QtQuick.Pdf
+ \ingroup pdf
+ \brief A representation of text search results within a PDF Document.
+ \since 5.15
+
+ PdfSearchModel provides the ability to search for text strings within a
+ document and get the geometric locations of matches on each page.
+*/
+
+QQuickPdfSearchModel::QQuickPdfSearchModel(QObject *parent)
+ : QPdfSearchModel(parent)
+{
+}
+
+QQuickPdfDocument *QQuickPdfSearchModel::document() const
+{
+ return m_quickDocument;
+}
+
+void QQuickPdfSearchModel::setDocument(QQuickPdfDocument *document)
+{
+ if (document == m_quickDocument)
+ return;
+ m_quickDocument = document;
+ QPdfSearchModel::setDocument(&document->m_doc);
+}
+
+/*!
+ \qmlproperty list<list<point>> PdfSearchModel::matchGeometry
+
+ A set of paths in a form that can be bound to the \c paths property of a
+ \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of
+ rectangles around all the locations where search results are found:
+
+ \qml
+ PdfDocument {
+ id: doc
+ }
+ PdfSearchModel {
+ id: searchModel
+ document: doc
+ page: doc.currentPage
+ }
+ Shape {
+ ShapePath {
+ PathMultiline {
+ paths: searchModel.matchGeometry
+ }
+ }
+ }
+ \endqml
+
+ \sa PathMultiline
+*/
+QVector<QPolygonF> QQuickPdfSearchModel::matchGeometry() const
+{
+ return m_matchGeometry;
+}
+
+/*!
+ \qmlproperty string PdfSearchModel::searchString
+
+ The string to search for.
+*/
+QString QQuickPdfSearchModel::searchString() const
+{
+ return m_searchString;
+}
+
+void QQuickPdfSearchModel::setSearchString(QString searchString)
+{
+ if (m_searchString == searchString)
+ return;
+
+ m_searchString = searchString;
+ emit searchStringChanged();
+ updateResults();
+}
+
+/*!
+ \qmlproperty int PdfSearchModel::page
+
+ The page number on which to search.
+
+ \sa QtQuick::Image::currentFrame
+*/
+int QQuickPdfSearchModel::page() const
+{
+ return m_page;
+}
+
+void QQuickPdfSearchModel::setPage(int page)
+{
+ if (m_page == page)
+ return;
+
+ m_page = page;
+ emit pageChanged();
+ updateResults();
+}
+
+void QQuickPdfSearchModel::updateResults()
+{
+ if (!document() || (m_searchString.isEmpty() && !m_matchGeometry.isEmpty()) || m_page < 0 || m_page > document()->pageCount()) {
+ m_matchGeometry.clear();
+ emit matchGeometryChanged();
+ }
+ QVector<QRectF> m = QPdfSearchModel::matches(m_page, m_searchString);
+ QVector<QPolygonF> matches;
+ for (QRectF r : m)
+ matches << QPolygonF(r);
+ if (matches != m_matchGeometry) {
+ m_matchGeometry = matches;
+ emit matchGeometryChanged();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/pdf/quick/qquickpdfsearchmodel_p.h b/src/pdf/quick/qquickpdfsearchmodel_p.h
new file mode 100644
index 000000000..799ef825f
--- /dev/null
+++ b/src/pdf/quick/qquickpdfsearchmodel_p.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** 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 QQUICKPDFSEARCHMODEL_P_H
+#define QQUICKPDFSEARCHMODEL_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 "qquickpdfdocument_p.h"
+#include "../api/qpdfsearchmodel.h"
+
+#include <QVariant>
+#include <QtQml/qqml.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPdfSearchModel : public QPdfSearchModel
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuickPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged)
+ Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged)
+ Q_PROPERTY(QString searchString READ searchString WRITE setSearchString NOTIFY searchStringChanged)
+ Q_PROPERTY(QVector<QPolygonF> matchGeometry READ matchGeometry NOTIFY matchGeometryChanged)
+
+public:
+ explicit QQuickPdfSearchModel(QObject *parent = nullptr);
+
+ QQuickPdfDocument *document() const;
+ void setDocument(QQuickPdfDocument * document);
+
+ int page() const;
+ void setPage(int page);
+
+ QString searchString() const;
+ void setSearchString(QString searchString);
+
+ QVector<QPolygonF> matchGeometry() const;
+
+signals:
+ void documentChanged();
+ void pageChanged();
+ void searchStringChanged();
+ void matchGeometryChanged();
+
+private:
+ void updateResults();
+
+private:
+ QQuickPdfDocument *m_quickDocument = nullptr;
+ QString m_searchString;
+ QVector<QPolygonF> m_matchGeometry;
+ int m_page;
+
+ Q_DISABLE_COPY(QQuickPdfSearchModel)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickPdfSearchModel)
+
+#endif // QQUICKPDFSEARCHMODEL_P_H
diff --git a/src/pdf/quick/quick.pro b/src/pdf/quick/quick.pro
index eb88bc003..cda768369 100644
--- a/src/pdf/quick/quick.pro
+++ b/src/pdf/quick/quick.pro
@@ -5,12 +5,21 @@ IMPORT_VERSION = 1.0
#QMAKE_DOCS = $$PWD/doc/qtquickpdf.qdocconf
+PDF_QML_FILES = \
+ qml/PdfPageView.qml \
+
+QML_FILES += $$PDF_QML_FILES qmldir
+
+RESOURCES += resources.qrc
+
SOURCES += \
+ plugin.cpp \
qquickpdfdocument.cpp \
- plugin.cpp
+ qquickpdfsearchmodel.cpp \
HEADERS += \
- qquickpdfdocument_p.h
+ qquickpdfdocument_p.h \
+ qquickpdfsearchmodel_p.h \
QT += pdf quick-private gui gui-private core core-private qml qml-private
diff --git a/src/pdf/quick/resources.qrc b/src/pdf/quick/resources.qrc
new file mode 100644
index 000000000..a3f34189c
--- /dev/null
+++ b/src/pdf/quick/resources.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/qt-project.org/qtpdf">
+ <file>qml/PdfPageView.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/pdf/qpdfsearchmodel/qpdfsearchmodel.pro b/tests/auto/pdf/qpdfsearchmodel/qpdfsearchmodel.pro
new file mode 100644
index 000000000..205fef175
--- /dev/null
+++ b/tests/auto/pdf/qpdfsearchmodel/qpdfsearchmodel.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+TARGET = tst_qpdfsearchmodel
+QT += pdf testlib network
+macos:CONFIG -= app_bundle
+SOURCES += tst_qpdfsearchmodel.cpp
diff --git a/tests/auto/pdf/qpdfsearchmodel/test.pdf b/tests/auto/pdf/qpdfsearchmodel/test.pdf
new file mode 100644
index 000000000..a9dc1bc29
--- /dev/null
+++ b/tests/auto/pdf/qpdfsearchmodel/test.pdf
Binary files differ
diff --git a/tests/auto/pdf/qpdfsearchmodel/tst_qpdfsearchmodel.cpp b/tests/auto/pdf/qpdfsearchmodel/tst_qpdfsearchmodel.cpp
new file mode 100644
index 000000000..e690bfc11
--- /dev/null
+++ b/tests/auto/pdf/qpdfsearchmodel/tst_qpdfsearchmodel.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite 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 <QtTest/QtTest>
+
+#include <QPdfDocument>
+#include <QPdfSearchModel>
+
+class tst_QPdfSearchModel: public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QPdfSearchModel() {}
+
+private slots:
+ void findText();
+};
+
+void tst_QPdfSearchModel::findText()
+{
+ QPdfDocument document;
+ QCOMPARE(document.load(QFINDTESTDATA("test.pdf")), QPdfDocument::NoError);
+
+ QPdfSearchModel model;
+ model.setDocument(&document);
+ QVector<QRectF> matches = model.matches(1, "ai");
+
+ qDebug() << matches;
+ QCOMPARE(matches.count(), 3);
+}
+
+QTEST_MAIN(tst_QPdfSearchModel)
+
+#include "tst_qpdfsearchmodel.moc"