From d1749c375ea924390d19225b40ef2631b524849b Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 22 Jan 2020 00:08:15 +0100 Subject: Use SpinBox for page navigation to get jump-to-page feature Change-Id: Ic4c7d1a7458995415452e899b3dc369c9fe574f4 Reviewed-by: Shawn Rutledge --- examples/pdf/pdfviewer/viewer.qml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index adc2a4b5b..8f2603659 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -113,20 +113,19 @@ ApplicationWindow { onTriggered: pageView.rotation += 90 } } - ToolButton { - action: Action { - shortcut: StandardKey.MoveToPreviousPage - icon.source: "resources/go-previous-view-page.svg" - enabled: pageView.currentPage > 0 - onTriggered: pageView.currentPage-- + SpinBox { + id: currentPageSB + from: 1 + to: document.pageCount + value: 1 + editable: true + Shortcut { + sequence: StandardKey.MoveToPreviousPage + onActivated: currentPageSB.value-- } - } - ToolButton { - action: Action { - shortcut: StandardKey.MoveToNextPage - icon.source: "resources/go-next-view-page.svg" - enabled: pageView.currentPage < pageView.pageCount - 1 - onTriggered: pageView.currentPage++ + Shortcut { + sequence: StandardKey.MoveToNextPage + onActivated: currentPageSB.value++ } } TextField { @@ -184,6 +183,7 @@ ApplicationWindow { PdfPageView { id: pageView + currentPage: currentPageSB.value - 1 document: PdfDocument { id: document onStatusChanged: if (status === PdfDocument.Error) errorDialog.open() -- cgit v1.2.3 From bc1d6ddeb5076f68e0a758725a20c3f2a6d081f0 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 20 Jan 2020 18:29:05 +0100 Subject: Add QPdfSelection and QQuickPdfSelection So now you can select text by mouse-drag and copy it to the clipboard. Task-number: QTBUG-77509 Change-Id: I689ee4158974de8bc541c319a5a5cc2f8f3c2ae6 Reviewed-by: Michal Klocek --- examples/pdf/pdfviewer/resources/edit-copy.svg | 15 +++++++++++++++ examples/pdf/pdfviewer/viewer.qml | 8 ++++++++ examples/pdf/pdfviewer/viewer.qrc | 1 + 3 files changed, 24 insertions(+) create mode 100644 examples/pdf/pdfviewer/resources/edit-copy.svg (limited to 'examples/pdf') diff --git a/examples/pdf/pdfviewer/resources/edit-copy.svg b/examples/pdf/pdfviewer/resources/edit-copy.svg new file mode 100644 index 000000000..9dd16877d --- /dev/null +++ b/examples/pdf/pdfviewer/resources/edit-copy.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index 8f2603659..99d9b8ed0 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -128,6 +128,14 @@ ApplicationWindow { onActivated: currentPageSB.value++ } } + ToolButton { + action: Action { + shortcut: StandardKey.Copy + icon.source: "resources/edit-copy.svg" + enabled: pageView.selectedText !== "" + onTriggered: pageView.copySelectionToClipboard() + } + } TextField { id: searchField placeholderText: "search" diff --git a/examples/pdf/pdfviewer/viewer.qrc b/examples/pdf/pdfviewer/viewer.qrc index 78f9c8d30..c376803c2 100644 --- a/examples/pdf/pdfviewer/viewer.qrc +++ b/examples/pdf/pdfviewer/viewer.qrc @@ -2,6 +2,7 @@ viewer.qml resources/edit-clear.svg + resources/edit-copy.svg resources/go-next-view-page.svg resources/go-previous-view-page.svg resources/rotate-left.svg -- cgit v1.2.3 From a8e4ad7726f1aa52624a0367558650cd4d899c79 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 28 Nov 2019 11:51:07 +0100 Subject: PdfPageView: Add zoom-to-fit and zoom-to-width features Change-Id: I40b92000a4def105d22a3bd10d0544b0b0f0fe1e Reviewed-by: Shawn Rutledge --- examples/pdf/pdfviewer/resources/zoom-fit-best.svg | 13 +++++++++++++ examples/pdf/pdfviewer/resources/zoom-fit-width.svg | 13 +++++++++++++ examples/pdf/pdfviewer/viewer.qml | 14 +++++++++++++- examples/pdf/pdfviewer/viewer.qrc | 2 ++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 examples/pdf/pdfviewer/resources/zoom-fit-best.svg create mode 100644 examples/pdf/pdfviewer/resources/zoom-fit-width.svg (limited to 'examples/pdf') diff --git a/examples/pdf/pdfviewer/resources/zoom-fit-best.svg b/examples/pdf/pdfviewer/resources/zoom-fit-best.svg new file mode 100644 index 000000000..adf302621 --- /dev/null +++ b/examples/pdf/pdfviewer/resources/zoom-fit-best.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/pdfviewer/resources/zoom-fit-width.svg b/examples/pdf/pdfviewer/resources/zoom-fit-width.svg new file mode 100644 index 000000000..985ee5205 --- /dev/null +++ b/examples/pdf/pdfviewer/resources/zoom-fit-width.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index 99d9b8ed0..1cf0b432b 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -92,11 +92,23 @@ ApplicationWindow { onTriggered: pageView.renderScale /= root.scaleStep } } + ToolButton { + action: Action { + icon.source: "resources/zoom-fit-width.svg" + onTriggered: pageView.scaleToWidth(root.contentItem.width, root.contentItem.height) + } + } + ToolButton { + action: Action { + icon.source: "resources/zoom-fit-best.svg" + onTriggered: pageView.scaleToPage(root.contentItem.width, root.contentItem.height) + } + } ToolButton { action: Action { shortcut: "Ctrl+0" icon.source: "resources/zoom-original.svg" - onTriggered: pageView.renderScale = 1 + onTriggered: pageView.resetScale() } } ToolButton { diff --git a/examples/pdf/pdfviewer/viewer.qrc b/examples/pdf/pdfviewer/viewer.qrc index c376803c2..fa3561caf 100644 --- a/examples/pdf/pdfviewer/viewer.qrc +++ b/examples/pdf/pdfviewer/viewer.qrc @@ -8,6 +8,8 @@ resources/rotate-left.svg resources/rotate-right.svg resources/zoom-in.svg + resources/zoom-fit-best.svg + resources/zoom-fit-width.svg resources/zoom-original.svg resources/zoom-out.svg resources/document-open.svg -- cgit v1.2.3 From 7cf69cb52d434f5e74619b0577104d05688b0c22 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 22 Jan 2020 00:56:16 +0100 Subject: Add PdfNavigationStack for forward/back navigation Works well enough to use, but needs autotests and at least one fix. Change-Id: I2114b9fb3b5ddf7cfe2106d4a4fbc7d74852c61d Reviewed-by: Shawn Rutledge --- examples/pdf/pdfviewer/viewer.qml | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index 1cf0b432b..b0cd8985d 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -57,8 +57,8 @@ import Qt.labs.platform 1.1 as Platform ApplicationWindow { id: root - width: 800 - height: 640 + width: 1280 + height: 1024 color: "lightgrey" title: document.title visible: true @@ -125,12 +125,22 @@ ApplicationWindow { onTriggered: pageView.rotation += 90 } } + ToolButton { + action: Action { + icon.source: "resources/go-previous-view-page.svg" + enabled: pageView.backEnabled + onTriggered: pageView.back() + } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "go back" + } SpinBox { id: currentPageSB from: 1 to: document.pageCount - value: 1 editable: true + onValueChanged: pageView.currentPage = value - 1 Shortcut { sequence: StandardKey.MoveToPreviousPage onActivated: currentPageSB.value-- @@ -140,6 +150,16 @@ ApplicationWindow { onActivated: currentPageSB.value++ } } + ToolButton { + action: Action { + icon.source: "resources/go-next-view-page.svg" + enabled: pageView.forwardEnabled + onTriggered: pageView.forward() + } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "go forward" + } ToolButton { action: Action { shortcut: StandardKey.Copy @@ -203,7 +223,10 @@ ApplicationWindow { PdfPageView { id: pageView - currentPage: currentPageSB.value - 1 +// currentPage: currentPageSB.value - 1 + // TODO should work but ends up being NaN in QQuickSpinBoxPrivate::setValue() (?!) +// onCurrentPageChanged: currentPageSB.value = pageView.currrentPage + 1 + onCurrentPageReallyChanged: currentPageSB.value = page + 1 document: PdfDocument { id: document onStatusChanged: if (status === PdfDocument.Error) errorDialog.open() -- cgit v1.2.3 From bf3133033236afb34974fec63ac21e1749d503ad Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 20 Jan 2020 15:12:01 +0100 Subject: Add PdfMultiPageView So far it's a ListView with a page per delegate. Many features are working, but zooming and rotation are not working yet. Change-Id: I9ee7aa60ad4411bd8734fe2cd987a68906a5cf57 Reviewed-by: Shawn Rutledge --- examples/pdf/multipage/main.cpp | 69 ++++++ examples/pdf/multipage/multipage.pro | 14 ++ examples/pdf/multipage/resources/document-open.svg | 13 + examples/pdf/multipage/resources/edit-clear.svg | 15 ++ examples/pdf/multipage/resources/edit-copy.svg | 15 ++ .../pdf/multipage/resources/go-next-view-page.svg | 13 + .../multipage/resources/go-previous-view-page.svg | 13 + examples/pdf/multipage/resources/rotate-left.svg | 6 + examples/pdf/multipage/resources/rotate-right.svg | 6 + examples/pdf/multipage/resources/zoom-fit-best.svg | 13 + .../pdf/multipage/resources/zoom-fit-width.svg | 13 + examples/pdf/multipage/resources/zoom-in.svg | 13 + examples/pdf/multipage/resources/zoom-original.svg | 13 + examples/pdf/multipage/resources/zoom-out.svg | 13 + examples/pdf/multipage/viewer.qml | 276 +++++++++++++++++++++ examples/pdf/multipage/viewer.qrc | 17 ++ 16 files changed, 522 insertions(+) create mode 100644 examples/pdf/multipage/main.cpp create mode 100644 examples/pdf/multipage/multipage.pro create mode 100644 examples/pdf/multipage/resources/document-open.svg create mode 100644 examples/pdf/multipage/resources/edit-clear.svg create mode 100644 examples/pdf/multipage/resources/edit-copy.svg create mode 100644 examples/pdf/multipage/resources/go-next-view-page.svg create mode 100644 examples/pdf/multipage/resources/go-previous-view-page.svg create mode 100644 examples/pdf/multipage/resources/rotate-left.svg create mode 100644 examples/pdf/multipage/resources/rotate-right.svg create mode 100644 examples/pdf/multipage/resources/zoom-fit-best.svg create mode 100644 examples/pdf/multipage/resources/zoom-fit-width.svg create mode 100644 examples/pdf/multipage/resources/zoom-in.svg create mode 100644 examples/pdf/multipage/resources/zoom-original.svg create mode 100644 examples/pdf/multipage/resources/zoom-out.svg create mode 100644 examples/pdf/multipage/viewer.qml create mode 100644 examples/pdf/multipage/viewer.qrc (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/main.cpp b/examples/pdf/multipage/main.cpp new file mode 100644 index 000000000..451521f80 --- /dev/null +++ b/examples/pdf/multipage/main.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 +#include + +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); + QCoreApplication::setApplicationName("Qt Quick Multi-page PDF Viewer Example"); + QCoreApplication::setOrganizationName("QtProject"); + QCoreApplication::setApplicationVersion(QT_VERSION_STR); + + 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/multipage/multipage.pro b/examples/pdf/multipage/multipage.pro new file mode 100644 index 000000000..5fff58fe1 --- /dev/null +++ b/examples/pdf/multipage/multipage.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/multipage +INSTALLS += target + diff --git a/examples/pdf/multipage/resources/document-open.svg b/examples/pdf/multipage/resources/document-open.svg new file mode 100644 index 000000000..bf23123a3 --- /dev/null +++ b/examples/pdf/multipage/resources/document-open.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/edit-clear.svg b/examples/pdf/multipage/resources/edit-clear.svg new file mode 100644 index 000000000..1c35aaf04 --- /dev/null +++ b/examples/pdf/multipage/resources/edit-clear.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/edit-copy.svg b/examples/pdf/multipage/resources/edit-copy.svg new file mode 100644 index 000000000..9dd16877d --- /dev/null +++ b/examples/pdf/multipage/resources/edit-copy.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/go-next-view-page.svg b/examples/pdf/multipage/resources/go-next-view-page.svg new file mode 100644 index 000000000..e453ddbec --- /dev/null +++ b/examples/pdf/multipage/resources/go-next-view-page.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/go-previous-view-page.svg b/examples/pdf/multipage/resources/go-previous-view-page.svg new file mode 100644 index 000000000..b032309e9 --- /dev/null +++ b/examples/pdf/multipage/resources/go-previous-view-page.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/rotate-left.svg b/examples/pdf/multipage/resources/rotate-left.svg new file mode 100644 index 000000000..90ce53c9d --- /dev/null +++ b/examples/pdf/multipage/resources/rotate-left.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/rotate-right.svg b/examples/pdf/multipage/resources/rotate-right.svg new file mode 100644 index 000000000..7383d1c84 --- /dev/null +++ b/examples/pdf/multipage/resources/rotate-right.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/zoom-fit-best.svg b/examples/pdf/multipage/resources/zoom-fit-best.svg new file mode 100644 index 000000000..adf302621 --- /dev/null +++ b/examples/pdf/multipage/resources/zoom-fit-best.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/zoom-fit-width.svg b/examples/pdf/multipage/resources/zoom-fit-width.svg new file mode 100644 index 000000000..985ee5205 --- /dev/null +++ b/examples/pdf/multipage/resources/zoom-fit-width.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/zoom-in.svg b/examples/pdf/multipage/resources/zoom-in.svg new file mode 100644 index 000000000..efdc9f17d --- /dev/null +++ b/examples/pdf/multipage/resources/zoom-in.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/zoom-original.svg b/examples/pdf/multipage/resources/zoom-original.svg new file mode 100644 index 000000000..1b4080a03 --- /dev/null +++ b/examples/pdf/multipage/resources/zoom-original.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/zoom-out.svg b/examples/pdf/multipage/resources/zoom-out.svg new file mode 100644 index 000000000..fcde9e526 --- /dev/null +++ b/examples/pdf/multipage/resources/zoom-out.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml new file mode 100644 index 000000000..d20ad4a5b --- /dev/null +++ b/examples/pdf/multipage/viewer.qml @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** 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.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Pdf 5.15 +import QtQuick.Shapes 1.14 +import QtQuick.Window 2.14 +import Qt.labs.platform 1.1 as Platform + +ApplicationWindow { + id: root + width: 800 + height: 1024 + color: "lightgrey" + title: document.title + visible: true + property alias source: document.source // for main.cpp + + header: ToolBar { + RowLayout { + anchors.fill: parent + anchors.rightMargin: 6 + ToolButton { + action: Action { + shortcut: StandardKey.Open + icon.source: "resources/document-open.svg" + onTriggered: fileDialog.open() + } + } + /* TODO zoom & rotation + ToolButton { + action: Action { + shortcut: StandardKey.ZoomIn + enabled: view.sourceSize.width < 10000 + icon.source: "resources/zoom-in.svg" + onTriggered: view.renderScale *= Math.sqrt(2) + } + } + ToolButton { + action: Action { + shortcut: StandardKey.ZoomOut + enabled: view.sourceSize.width > 50 + icon.source: "resources/zoom-out.svg" + onTriggered: view.renderScale /= Math.sqrt(2) + } + } + ToolButton { + action: Action { + icon.source: "resources/zoom-fit-width.svg" + onTriggered: view.scaleToWidth(root.contentItem.width, root.contentItem.height) + } + } + ToolButton { + action: Action { + icon.source: "resources/zoom-fit-best.svg" + onTriggered: view.scaleToPage(root.contentItem.width, root.contentItem.height) + } + } + ToolButton { + action: Action { + shortcut: "Ctrl+0" + icon.source: "resources/zoom-original.svg" + onTriggered: view.resetScale() + } + } + ToolButton { + action: Action { + shortcut: "Ctrl+L" + icon.source: "resources/rotate-left.svg" + onTriggered: view.rotation -= 90 + } + } + ToolButton { + action: Action { + shortcut: "Ctrl+R" + icon.source: "resources/rotate-right.svg" + onTriggered: view.rotation += 90 + } + } + */ + ToolButton { + action: Action { + icon.source: "resources/go-previous-view-page.svg" + enabled: view.backEnbled + onTriggered: view.back() + } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "go back" + } + SpinBox { + id: currentPageSB + from: 1 + to: document.pageCount + editable: true + onValueChanged: view.currentPage = value - 1 + Shortcut { + sequence: StandardKey.MoveToPreviousPage + onActivated: currentPageSB.value-- + } + Shortcut { + sequence: StandardKey.MoveToNextPage + onActivated: currentPageSB.value++ + } + } + ToolButton { + action: Action { + icon.source: "resources/go-next-view-page.svg" + enabled: view.forwardEnabled + onTriggered: view.forward() + } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "go forward" + } + ToolButton { + action: Action { + shortcut: StandardKey.Copy + icon.source: "resources/edit-copy.svg" + enabled: view.selectedText !== "" + onTriggered: view.copySelectionToClipboard() + } + } + 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: passwordDialog + title: "Password" + standardButtons: Dialog.Ok | Dialog.Cancel + modal: true + closePolicy: Popup.CloseOnEscape + anchors.centerIn: parent + width: 300 + + TextField { + id: passwordField + placeholderText: qsTr("Please provide the password") + echoMode: TextInput.Password + width: parent.width + onAccepted: passwordDialog.accept() + } + onAccepted: document.password = passwordField.text + } + + 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 + } + } + + PdfDocument { + id: document + onStatusChanged: { + if (status === PdfDocument.Error) errorDialog.open() + view.document = (status === PdfDocument.Ready ? document : undefined) + } + onPasswordRequired: { + passwordDialog.open() + passwordField.forceActiveFocus() + } + } + + PdfMultiPageView { + id: view + anchors.fill: parent + document: root.document + searchString: searchField.text + onCurrentPageReallyChanged: currentPageSB.value = page + 1 + } + + footer: ToolBar { + height: statusLabel.implicitHeight * 1.5 + Label { + id: statusLabel + anchors.verticalCenter: parent.verticalCenter + x: 6 + property size implicitPointSize: document.pagePointSize(view.currentPage) + text: "page " + (currentPageSB.value) + " of " + document.pageCount + + " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + visible: document.pageCount > 0 + } + } +} diff --git a/examples/pdf/multipage/viewer.qrc b/examples/pdf/multipage/viewer.qrc new file mode 100644 index 000000000..fa3561caf --- /dev/null +++ b/examples/pdf/multipage/viewer.qrc @@ -0,0 +1,17 @@ + + + viewer.qml + resources/edit-clear.svg + resources/edit-copy.svg + resources/go-next-view-page.svg + resources/go-previous-view-page.svg + resources/rotate-left.svg + resources/rotate-right.svg + resources/zoom-in.svg + resources/zoom-fit-best.svg + resources/zoom-fit-width.svg + resources/zoom-original.svg + resources/zoom-out.svg + resources/document-open.svg + + -- cgit v1.2.3 From 130b058352077b88f8839871f88c226e3e1fa705 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 4 Feb 2020 16:08:42 +0100 Subject: Add multipage example to pdf.pro; work with 5.14; fix main.cpp - build the multipage example by default - don't import anything that won't work with Qt 5.14 - set application attributes before creating an instance (to fix the warning about that) Change-Id: I265f49ca75cae1908d4c23848cba8c42e5e3824b Reviewed-by: Shawn Rutledge --- examples/pdf/multipage/main.cpp | 3 ++- examples/pdf/pdf.pro | 2 +- examples/pdf/pdfviewer/main.cpp | 2 +- examples/pdf/pdfviewer/viewer.qml | 10 +++++----- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/main.cpp b/examples/pdf/multipage/main.cpp index 451521f80..7b766d77e 100644 --- a/examples/pdf/multipage/main.cpp +++ b/examples/pdf/multipage/main.cpp @@ -53,10 +53,11 @@ int main(int argc, char* argv[]) { - QApplication app(argc, argv); QCoreApplication::setApplicationName("Qt Quick Multi-page PDF Viewer Example"); QCoreApplication::setOrganizationName("QtProject"); QCoreApplication::setApplicationVersion(QT_VERSION_STR); + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:///pdfviewer/viewer.qml"))); diff --git a/examples/pdf/pdf.pro b/examples/pdf/pdf.pro index 45df33e46..7130f3560 100644 --- a/examples/pdf/pdf.pro +++ b/examples/pdf/pdf.pro @@ -1,3 +1,3 @@ TEMPLATE=subdirs -SUBDIRS += pdfviewer +SUBDIRS += pdfviewer multipage diff --git a/examples/pdf/pdfviewer/main.cpp b/examples/pdf/pdfviewer/main.cpp index 6b94a3de1..639b11825 100644 --- a/examples/pdf/pdfviewer/main.cpp +++ b/examples/pdf/pdfviewer/main.cpp @@ -53,11 +53,11 @@ 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); + QApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:///pdfviewer/viewer.qml"))); diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index b0cd8985d..a8e581a45 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -47,12 +47,12 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 import QtQuick.Pdf 5.15 -import QtQuick.Shapes 1.15 -import QtQuick.Window 2.15 +import QtQuick.Shapes 1.14 +import QtQuick.Window 2.14 import Qt.labs.platform 1.1 as Platform ApplicationWindow { -- cgit v1.2.3 From 25a371caa376c513f22d5c01e425a18629657fdc Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 3 Feb 2020 18:11:16 +0100 Subject: Add zoom and rotation to PdfMultiPageView Currently, scaleToWidth() and scaleToPage() choose the scale of the first page to fit the given viewport size, and as long as all pages are the same size, it works. On the other hand, the PinchHandler only affects the scale of the page on which the pinch gesture occurs. Calling resetScale(), scaleToWidth() or scaleToPage() undoes the effect of any previous pinch gesture or any other kind of scaling change. Task-number: QTBUG-77513 Change-Id: Ia3227ca9c4af263eb8505dbd6336657984c66ab0 Reviewed-by: Shawn Rutledge --- examples/pdf/multipage/viewer.qml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index d20ad4a5b..77c06f80f 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -75,11 +75,10 @@ ApplicationWindow { onTriggered: fileDialog.open() } } - /* TODO zoom & rotation ToolButton { action: Action { shortcut: StandardKey.ZoomIn - enabled: view.sourceSize.width < 10000 + enabled: view.renderScale < 10 icon.source: "resources/zoom-in.svg" onTriggered: view.renderScale *= Math.sqrt(2) } @@ -87,7 +86,7 @@ ApplicationWindow { ToolButton { action: Action { shortcut: StandardKey.ZoomOut - enabled: view.sourceSize.width > 50 + enabled: view.renderScale > 0.1 icon.source: "resources/zoom-out.svg" onTriggered: view.renderScale /= Math.sqrt(2) } @@ -115,17 +114,16 @@ ApplicationWindow { action: Action { shortcut: "Ctrl+L" icon.source: "resources/rotate-left.svg" - onTriggered: view.rotation -= 90 + onTriggered: view.pageRotation -= 90 } } ToolButton { action: Action { shortcut: "Ctrl+R" icon.source: "resources/rotate-right.svg" - onTriggered: view.rotation += 90 + onTriggered: view.pageRotation += 90 } } - */ ToolButton { action: Action { icon.source: "resources/go-previous-view-page.svg" @@ -269,7 +267,8 @@ ApplicationWindow { x: 6 property size implicitPointSize: document.pagePointSize(view.currentPage) text: "page " + (currentPageSB.value) + " of " + document.pageCount + - " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + " scale " + view.renderScale.toFixed(2) + + " original size " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + " pt" visible: document.pageCount > 0 } } -- cgit v1.2.3 From 09a6eac4a63b32548ecc1ff5b16a5d8fc3ba1c04 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 5 Feb 2020 15:53:57 +0100 Subject: Add QPdfDestination; NavigationStack stores page, location and zoom Push/back/forward behavior seems more correct now, but still no autotest yet. QPdfDestination might be useful to represent locations of search results, for link destinations and maybe named destinations too. Fixes: QTBUG-77512 Change-Id: I113b2c535a2cd302106e6546104c64e12985d387 Reviewed-by: Shawn Rutledge --- examples/pdf/pdfviewer/viewer.qml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index a8e581a45..095bc3985 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -140,7 +140,7 @@ ApplicationWindow { from: 1 to: document.pageCount editable: true - onValueChanged: pageView.currentPage = value - 1 + onValueChanged: pageView.goToPage(value - 1) Shortcut { sequence: StandardKey.MoveToPreviousPage onActivated: currentPageSB.value-- @@ -223,7 +223,6 @@ ApplicationWindow { PdfPageView { id: pageView -// currentPage: currentPageSB.value - 1 // TODO should work but ends up being NaN in QQuickSpinBoxPrivate::setValue() (?!) // onCurrentPageChanged: currentPageSB.value = pageView.currrentPage + 1 onCurrentPageReallyChanged: currentPageSB.value = page + 1 -- cgit v1.2.3 From 7afe95f14d7d048a73baa12b3bd5f6a9bcea2ccb Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 5 Feb 2020 10:56:48 +0100 Subject: PDF multipage view: track specific link and navigation destinations Unfortunately it's getting harder to do things declaratively, because we have to avoid circular bindings, and because of needing to use imperative APIs. The current-page spinbox provides onValueModified() to detect when the user modifies it, distinct from the simple fact that the value changed. We shouldn't make bindings to set ListView.currentIndex anyway, because that results in slow animation (and loading pages in all delegates along the way) rather than quick jumping to the correct page. Instead we need to use ListView.positionViewAtIndex(), another imperative API, to get quick jumps without having to calculate and set contentY in some other way. Now we move toward the NavigationStack providing storage for the current destination at all times. Changes there will trigger programmatically moving the ListView. When the user scrolls manually, that generates a "destination" in the navigation stack, such that the back button can jump back to the previous location, and then the forward button can return to the destination where manual scrolling ended up. Fixes: QTBUG-77510 Change-Id: I47544210d2e0f9aa790f3d2594839678374e463d Reviewed-by: Shawn Rutledge --- examples/pdf/multipage/viewer.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index 77c06f80f..bbc28cd8d 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -139,7 +139,7 @@ ApplicationWindow { from: 1 to: document.pageCount editable: true - onValueChanged: view.currentPage = value - 1 + onValueModified: view.goToPage(value - 1) Shortcut { sequence: StandardKey.MoveToPreviousPage onActivated: currentPageSB.value-- @@ -256,7 +256,7 @@ ApplicationWindow { anchors.fill: parent document: root.document searchString: searchField.text - onCurrentPageReallyChanged: currentPageSB.value = page + 1 + onCurrentPageChanged: currentPageSB.value = view.currentPage + 1 } footer: ToolBar { -- cgit v1.2.3 From e5a33355798d3277c631b0024f389cdca2f2c683 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 7 Feb 2020 14:54:31 +0100 Subject: PDF multipage viewer: iterate search results This version still has separate PdfSearchModel instances on each page, but now there are buttons to iterate and highlight the search results in order. When you come to the last result on one page, hitting the "Find Next" button will jump to the next page, and keep jumping forward from there until another result is found. Unfortunately this jumping takes time if it skips over a lot of pages because of empty search results. That seems to be another reason to make PdfSearchModel into a whole-document search model and use one instance. Also reorganize PdfMultiPageView.qml's public API into sections according to functionality rather than by type. Change-Id: I677a764fcbf231b2656aff8abe7240a27582a696 Reviewed-by: Shawn Rutledge --- .../pdf/multipage/resources/go-down-search.svg | 13 ++++ examples/pdf/multipage/resources/go-up-search.svg | 8 +++ examples/pdf/multipage/viewer.qml | 81 +++++++++++++++------- examples/pdf/multipage/viewer.qrc | 2 + 4 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 examples/pdf/multipage/resources/go-down-search.svg create mode 100644 examples/pdf/multipage/resources/go-up-search.svg (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/resources/go-down-search.svg b/examples/pdf/multipage/resources/go-down-search.svg new file mode 100644 index 000000000..ae17ab93b --- /dev/null +++ b/examples/pdf/multipage/resources/go-down-search.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/multipage/resources/go-up-search.svg b/examples/pdf/multipage/resources/go-up-search.svg new file mode 100644 index 000000000..5cc155873 --- /dev/null +++ b/examples/pdf/multipage/resources/go-up-search.svg @@ -0,0 +1,8 @@ + + + + diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index bbc28cd8d..3d9cd371a 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -167,30 +167,6 @@ ApplicationWindow { onTriggered: view.copySelectionToClipboard() } } - 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() @@ -259,6 +235,63 @@ ApplicationWindow { onCurrentPageChanged: currentPageSB.value = view.currentPage + 1 } + Drawer { + id: searchDrawer + edge: Qt.BottomEdge + x: 20 + width: searchLayout.implicitWidth + height: searchLayout.implicitHeight + dim: false + Shortcut { + sequence: StandardKey.Find + onActivated: { + searchDrawer.open() + searchField.forceActiveFocus() + } + } + RowLayout { + id: searchLayout + ToolButton { + action: Action { + icon.source: "resources/go-up-search.svg" + onTriggered: view.searchBack() + } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find previous" + } + 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() + } + } + } + ToolButton { + action: Action { + icon.source: "resources/go-down-search.svg" + onTriggered: view.searchForward() + } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find next" + } + } + } + footer: ToolBar { height: statusLabel.implicitHeight * 1.5 Label { diff --git a/examples/pdf/multipage/viewer.qrc b/examples/pdf/multipage/viewer.qrc index fa3561caf..9698a2689 100644 --- a/examples/pdf/multipage/viewer.qrc +++ b/examples/pdf/multipage/viewer.qrc @@ -3,8 +3,10 @@ viewer.qml resources/edit-clear.svg resources/edit-copy.svg + resources/go-down-search.svg resources/go-next-view-page.svg resources/go-previous-view-page.svg + resources/go-up-search.svg resources/rotate-left.svg resources/rotate-right.svg resources/zoom-in.svg -- cgit v1.2.3 From 0b6a4d94945a975390b2574e6aff2568ebb7f061 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 10 Feb 2020 10:49:33 +0100 Subject: PdfSearchModel: be QALM and find search results on all pages It's a QAbstractListModel, so now PdfMultiPageView has a ListView in a left-side Drawer showing all results found so far. - In PdfMultiPageView, multiple pages exist at once, so it makes sense to use the same searchmodel for all. - It's faster and saves memory. - Search results on each page can be cached. - It's possible to show search results in a ListView or QListView. Change-Id: I66fba6975954a09a4d23262be87ff8cc25ee7478 Reviewed-by: Shawn Rutledge --- examples/pdf/multipage/viewer.qml | 96 +++++++++++------ .../pdf/pdfviewer/resources/go-down-search.svg | 13 +++ examples/pdf/pdfviewer/resources/go-up-search.svg | 8 ++ examples/pdf/pdfviewer/viewer.qml | 119 +++++++++++++++------ examples/pdf/pdfviewer/viewer.qrc | 2 + 5 files changed, 172 insertions(+), 66 deletions(-) create mode 100644 examples/pdf/pdfviewer/resources/go-down-search.svg create mode 100644 examples/pdf/pdfviewer/resources/go-up-search.svg (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index 3d9cd371a..8f102a3c1 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -230,6 +230,7 @@ ApplicationWindow { PdfMultiPageView { id: view anchors.fill: parent + anchors.leftMargin: searchDrawer.position * searchDrawer.width document: root.document searchString: searchField.text onCurrentPageChanged: currentPageSB.value = view.currentPage + 1 @@ -237,10 +238,11 @@ ApplicationWindow { Drawer { id: searchDrawer - edge: Qt.BottomEdge - x: 20 + edge: Qt.LeftEdge + modal: false width: searchLayout.implicitWidth - height: searchLayout.implicitHeight + y: root.header.height + height: view.height dim: false Shortcut { sequence: StandardKey.Find @@ -249,45 +251,69 @@ ApplicationWindow { searchField.forceActiveFocus() } } - RowLayout { + ColumnLayout { id: searchLayout - ToolButton { - action: Action { - icon.source: "resources/go-up-search.svg" - onTriggered: view.searchBack() + anchors.fill: parent + anchors.margins: 2 + RowLayout { + ToolButton { + action: Action { + icon.source: "resources/go-up-search.svg" + shortcut: StandardKey.FindPrevious + onTriggered: view.searchBack() + } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find previous" } - ToolTip.visible: enabled && hovered - ToolTip.delay: 2000 - ToolTip.text: "find previous" - } - 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 + 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() + } } - TapHandler { - onTapped: searchField.clear() + } + ToolButton { + action: Action { + icon.source: "resources/go-down-search.svg" + shortcut: StandardKey.FindNext + onTriggered: view.searchForward() } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find next" } } - ToolButton { - action: Action { - icon.source: "resources/go-down-search.svg" - onTriggered: view.searchForward() + ListView { + id: searchResultsList + ColumnLayout.fillWidth: true + ColumnLayout.fillHeight: true + clip: true + model: view.searchModel + ScrollBar.vertical: ScrollBar { } + delegate: ItemDelegate { + width: parent ? parent.width : 0 + text: "page " + (page + 1) + ": " + context + highlighted: ListView.isCurrentItem + onClicked: { + searchResultsList.currentIndex = index + view.goToLocation(page, location, 0) + view.searchModel.currentResult = indexOnPage + } } - ToolTip.visible: enabled && hovered - ToolTip.delay: 2000 - ToolTip.text: "find next" } } } diff --git a/examples/pdf/pdfviewer/resources/go-down-search.svg b/examples/pdf/pdfviewer/resources/go-down-search.svg new file mode 100644 index 000000000..ae17ab93b --- /dev/null +++ b/examples/pdf/pdfviewer/resources/go-down-search.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/examples/pdf/pdfviewer/resources/go-up-search.svg b/examples/pdf/pdfviewer/resources/go-up-search.svg new file mode 100644 index 000000000..5cc155873 --- /dev/null +++ b/examples/pdf/pdfviewer/resources/go-up-search.svg @@ -0,0 +1,8 @@ + + + + diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index 095bc3985..e94642c5e 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -57,7 +57,7 @@ import Qt.labs.platform 1.1 as Platform ApplicationWindow { id: root - width: 1280 + width: 800 height: 1024 color: "lightgrey" title: document.title @@ -140,14 +140,15 @@ ApplicationWindow { from: 1 to: document.pageCount editable: true - onValueChanged: pageView.goToPage(value - 1) + value: pageView.currentPage + 1 + onValueModified: pageView.goToPage(value - 1) Shortcut { sequence: StandardKey.MoveToPreviousPage - onActivated: currentPageSB.value-- + onActivated: pageView.goToPage(currentPageSB.value - 2) } Shortcut { sequence: StandardKey.MoveToNextPage - onActivated: currentPageSB.value++ + onActivated: pageView.goToPage(currentPageSB.value) } } ToolButton { @@ -168,30 +169,6 @@ ApplicationWindow { onTriggered: pageView.copySelectionToClipboard() } } - 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() @@ -223,9 +200,7 @@ ApplicationWindow { PdfPageView { id: pageView - // TODO should work but ends up being NaN in QQuickSpinBoxPrivate::setValue() (?!) -// onCurrentPageChanged: currentPageSB.value = pageView.currrentPage + 1 - onCurrentPageReallyChanged: currentPageSB.value = page + 1 + x: searchDrawer.position * searchDrawer.width // TODO binding gets broken during centering document: PdfDocument { id: document onStatusChanged: if (status === PdfDocument.Error) errorDialog.open() @@ -233,6 +208,88 @@ ApplicationWindow { searchString: searchField.text } + Drawer { + id: searchDrawer + edge: Qt.LeftEdge + modal: false + width: searchLayout.implicitWidth + y: root.header.height + height: root.contentItem.height + dim: false + Shortcut { + sequence: StandardKey.Find + onActivated: { + searchDrawer.open() + searchField.forceActiveFocus() + } + } + ColumnLayout { + id: searchLayout + anchors.fill: parent + anchors.margins: 2 + RowLayout { + ToolButton { + action: Action { + icon.source: "resources/go-up-search.svg" + shortcut: StandardKey.FindPrevious + onTriggered: pageView.searchBack() + } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find previous" + } + 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() + } + } + } + ToolButton { + action: Action { + icon.source: "resources/go-down-search.svg" + shortcut: StandardKey.FindNext + onTriggered: pageView.searchForward() + } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find next" + } + } + ListView { + id: searchResultsList + ColumnLayout.fillWidth: true + ColumnLayout.fillHeight: true + clip: true + model: pageView.searchModel + ScrollBar.vertical: ScrollBar { } + delegate: ItemDelegate { + width: parent ? parent.width : 0 + text: "page " + (page + 1) + ": " + context + highlighted: ListView.isCurrentItem + onClicked: { + searchResultsList.currentIndex = index + pageView.goToLocation(page, location, 0) + pageView.searchModel.currentResult = indexOnPage + } + } + } + } + } + footer: Label { property size implicitPointSize: document.pagePointSize(pageView.currentPage) text: "page " + (pageView.currentPage + 1) + " of " + pageView.pageCount + diff --git a/examples/pdf/pdfviewer/viewer.qrc b/examples/pdf/pdfviewer/viewer.qrc index fa3561caf..9698a2689 100644 --- a/examples/pdf/pdfviewer/viewer.qrc +++ b/examples/pdf/pdfviewer/viewer.qrc @@ -3,8 +3,10 @@ viewer.qml resources/edit-clear.svg resources/edit-copy.svg + resources/go-down-search.svg resources/go-next-view-page.svg resources/go-previous-view-page.svg + resources/go-up-search.svg resources/rotate-left.svg resources/rotate-right.svg resources/zoom-in.svg -- cgit v1.2.3 From 24cd9f79bf7cf21e275b73ded63ee46bcc706db3 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 17 Feb 2020 16:42:56 +0100 Subject: Rearrange PdfPageView.qml Now it looks more similar to PdfMultiPageView.qml: public properties and functions are grouped by functionality, implementation details are "below the fold", and properties and functions that we don't want to expose as API are nested inside inner items. Also fixed ColumnLayout attached properties. Change-Id: Iafe6f983a34ca6bac9b0d4f3a26aba5a426e0232 Reviewed-by: Shawn Rutledge --- examples/pdf/multipage/viewer.qml | 4 ++-- examples/pdf/pdfviewer/viewer.qml | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index 8f102a3c1..3a6347f5a 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -299,8 +299,8 @@ ApplicationWindow { } ListView { id: searchResultsList - ColumnLayout.fillWidth: true - ColumnLayout.fillHeight: true + Layout.fillWidth: true + Layout.fillHeight: true clip: true model: view.searchModel ScrollBar.vertical: ScrollBar { } diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index e94642c5e..c63485dd3 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -271,8 +271,8 @@ ApplicationWindow { } ListView { id: searchResultsList - ColumnLayout.fillWidth: true - ColumnLayout.fillHeight: true + Layout.fillWidth: true + Layout.fillHeight: true clip: true model: pageView.searchModel ScrollBar.vertical: ScrollBar { } @@ -292,10 +292,9 @@ ApplicationWindow { footer: Label { property size implicitPointSize: document.pagePointSize(pageView.currentPage) - text: "page " + (pageView.currentPage + 1) + " of " + pageView.pageCount + + text: "page " + (pageView.currentPage + 1) + " of " + document.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 + " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + "pts" + visible: document.status === PdfDocument.Ready } } -- cgit v1.2.3 From d294872b34667199455ca169d68be392942c3b00 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 17 Feb 2020 22:28:38 +0100 Subject: Enable mouse wheel scrolling in single-page PdfPageView Change-Id: I20512187dcc872b2e0429968e9ad2a9899aee6c2 Reviewed-by: Shawn Rutledge --- examples/pdf/pdfviewer/viewer.qml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'examples/pdf') diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index c63485dd3..586a822a0 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -53,6 +53,7 @@ import QtQuick.Layouts 1.14 import QtQuick.Pdf 5.15 import QtQuick.Shapes 1.14 import QtQuick.Window 2.14 +import Qt.labs.animation 1.0 import Qt.labs.platform 1.1 as Platform ApplicationWindow { @@ -208,6 +209,21 @@ ApplicationWindow { searchString: searchField.text } + WheelHandler { + rotationScale: 15 + target: pageView + property: "x" + orientation: Qt.Horizontal + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + } + WheelHandler { + rotationScale: 15 + target: pageView + property: "y" + orientation: Qt.Vertical + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + } + Drawer { id: searchDrawer edge: Qt.LeftEdge -- cgit v1.2.3 From a2be3a7a79dc4fabe8675ea80a6ba550e0e4deec Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 19 Feb 2020 10:30:52 +0100 Subject: PDF multipage example: move search field to the footer Hiding the search feature in a closed Drawer might not have been sufficiently touch-friendly and discoverable, for example on iOS where the user is not going to press control-F to start searching. But the top toolbar is too full to put the search field back up there. It's familiar from Firefox to have the search field at the bottom, and we have enough space for it there. So now you can search and jump around the search results without opening the drawer; but pressing Enter in the search field opens the drawer. Hopefully swiping to open the drawer is also convenient enough on touch platforms; otherwise we could add another button for that, perhaps at the left of the footer. Change-Id: Iaec63bc22b03e29156fee817d197daae5b0cf9d5 Reviewed-by: Shawn Rutledge --- examples/pdf/multipage/viewer.qml | 145 ++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 76 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index 3a6347f5a..ba54065b7 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -167,6 +167,10 @@ ApplicationWindow { onTriggered: view.copySelectionToClipboard() } } + Shortcut { + sequence: StandardKey.Find + onActivated: searchField.forceActiveFocus() + } Shortcut { sequence: StandardKey.Quit onActivated: Qt.quit() @@ -240,95 +244,84 @@ ApplicationWindow { id: searchDrawer edge: Qt.LeftEdge modal: false - width: searchLayout.implicitWidth + width: 300 y: root.header.height height: view.height dim: false - Shortcut { - sequence: StandardKey.Find - onActivated: { - searchDrawer.open() - searchField.forceActiveFocus() + ListView { + id: searchResultsList + anchors.fill: parent + anchors.margins: 2 + model: view.searchModel + ScrollBar.vertical: ScrollBar { } + delegate: ItemDelegate { + width: parent ? parent.width : 0 + text: "page " + (page + 1) + ": " + context + highlighted: ListView.isCurrentItem + onClicked: { + searchResultsList.currentIndex = index + view.goToLocation(page, location, 0) + view.searchModel.currentResult = indexOnPage + } } } - ColumnLayout { - id: searchLayout + } + + footer: ToolBar { + height: footerRow.implicitHeight + RowLayout { + id: footerRow anchors.fill: parent - anchors.margins: 2 - RowLayout { - ToolButton { - action: Action { - icon.source: "resources/go-up-search.svg" - shortcut: StandardKey.FindPrevious - onTriggered: view.searchBack() - } - ToolTip.visible: enabled && hovered - ToolTip.delay: 2000 - ToolTip.text: "find previous" + ToolButton { + action: Action { + icon.source: "resources/go-up-search.svg" + shortcut: StandardKey.FindPrevious + onTriggered: view.searchBack() } - 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() - } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find previous" + } + TextField { + id: searchField + placeholderText: "search" + Layout.minimumWidth: 200 + Layout.fillWidth: true + onAccepted: searchDrawer.open() + Image { + visible: searchField.text !== "" + source: "resources/edit-clear.svg" + anchors { + right: parent.right + top: parent.top + bottom: parent.bottom + margins: 3 + rightMargin: 5 } - } - ToolButton { - action: Action { - icon.source: "resources/go-down-search.svg" - shortcut: StandardKey.FindNext - onTriggered: view.searchForward() + TapHandler { + onTapped: searchField.clear() } - ToolTip.visible: enabled && hovered - ToolTip.delay: 2000 - ToolTip.text: "find next" } } - ListView { - id: searchResultsList - Layout.fillWidth: true - Layout.fillHeight: true - clip: true - model: view.searchModel - ScrollBar.vertical: ScrollBar { } - delegate: ItemDelegate { - width: parent ? parent.width : 0 - text: "page " + (page + 1) + ": " + context - highlighted: ListView.isCurrentItem - onClicked: { - searchResultsList.currentIndex = index - view.goToLocation(page, location, 0) - view.searchModel.currentResult = indexOnPage - } + ToolButton { + action: Action { + icon.source: "resources/go-down-search.svg" + shortcut: StandardKey.FindNext + onTriggered: view.searchForward() } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find next" + } + Label { + id: statusLabel + Layout.fillWidth: true + property size implicitPointSize: document.pagePointSize(view.currentPage) + text: "page " + (currentPageSB.value) + " of " + document.pageCount + + " scale " + view.renderScale.toFixed(2) + + " original size " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + " pt" + visible: document.pageCount > 0 } - } - } - - footer: ToolBar { - height: statusLabel.implicitHeight * 1.5 - Label { - id: statusLabel - anchors.verticalCenter: parent.verticalCenter - x: 6 - property size implicitPointSize: document.pagePointSize(view.currentPage) - text: "page " + (currentPageSB.value) + " of " + document.pageCount + - " scale " + view.renderScale.toFixed(2) + - " original size " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + " pt" - visible: document.pageCount > 0 } } } -- cgit v1.2.3 From 1acd9ad2bfa1c54f19fa8a71fb41e8a90233f76b Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 19 Feb 2020 17:47:01 +0100 Subject: QtPdf examples: use test.pdf from resources if no file given On iOS, the native FileDialog doesn't work, sharing doesn't work, and packaging files along with the application requires manual effort; so a PDF file in resources seems to be the easiest alternative to make the examples demo-able. QPdfDocument wants a file path, because it uses QFile; but we like to use URLs in Qt Quick. So it's a bit of an impedance mismatch, there are several choices about when and where to do the conversion, and it's hard to say which way is more correct. This way happens to work for now. Also do the rest of the things necessary to get this working on iOS. Change-Id: Icb8614d5eed2510f101aefba534ef80cf890518f Reviewed-by: Shawn Rutledge --- examples/pdf/multipage/main.cpp | 3 +++ examples/pdf/multipage/multipage.pro | 2 +- examples/pdf/multipage/resources/test.pdf | Bin 0 -> 80045 bytes examples/pdf/multipage/viewer.qml | 3 ++- examples/pdf/multipage/viewer.qrc | 3 ++- examples/pdf/pdfviewer/main.cpp | 2 ++ examples/pdf/pdfviewer/pdfviewer.pro | 2 +- examples/pdf/pdfviewer/resources/test.pdf | Bin 0 -> 80045 bytes examples/pdf/pdfviewer/viewer.qml | 3 ++- examples/pdf/pdfviewer/viewer.qrc | 3 ++- 10 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 examples/pdf/multipage/resources/test.pdf create mode 100644 examples/pdf/pdfviewer/resources/test.pdf (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/main.cpp b/examples/pdf/multipage/main.cpp index 7b766d77e..35aaa8c64 100644 --- a/examples/pdf/multipage/main.cpp +++ b/examples/pdf/multipage/main.cpp @@ -64,7 +64,10 @@ int main(int argc, char* argv[]) if (app.arguments().count() > 1) { QUrl toLoad = QUrl::fromUserInput(app.arguments().at(1)); engine.rootObjects().first()->setProperty("source", toLoad); + } else { + engine.rootObjects().first()->setProperty("source", QStringLiteral("resources/test.pdf")); } + return app.exec(); } diff --git a/examples/pdf/multipage/multipage.pro b/examples/pdf/multipage/multipage.pro index 5fff58fe1..5df9e653d 100644 --- a/examples/pdf/multipage/multipage.pro +++ b/examples/pdf/multipage/multipage.pro @@ -1,6 +1,6 @@ TEMPLATE = app -QT += qml quick pdf widgets +QT += qml quick pdf widgets svg SOURCES += main.cpp diff --git a/examples/pdf/multipage/resources/test.pdf b/examples/pdf/multipage/resources/test.pdf new file mode 100644 index 000000000..a9dc1bc29 Binary files /dev/null and b/examples/pdf/multipage/resources/test.pdf differ diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index ba54065b7..ac6d2cd9a 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -62,7 +62,7 @@ ApplicationWindow { color: "lightgrey" title: document.title visible: true - property alias source: document.source // for main.cpp + property string source // for main.cpp header: ToolBar { RowLayout { @@ -221,6 +221,7 @@ ApplicationWindow { PdfDocument { id: document + source: Qt.resolvedUrl(root.source) onStatusChanged: { if (status === PdfDocument.Error) errorDialog.open() view.document = (status === PdfDocument.Ready ? document : undefined) diff --git a/examples/pdf/multipage/viewer.qrc b/examples/pdf/multipage/viewer.qrc index 9698a2689..1b6fa52f7 100644 --- a/examples/pdf/multipage/viewer.qrc +++ b/examples/pdf/multipage/viewer.qrc @@ -1,6 +1,7 @@ viewer.qml + resources/document-open.svg resources/edit-clear.svg resources/edit-copy.svg resources/go-down-search.svg @@ -9,11 +10,11 @@ resources/go-up-search.svg resources/rotate-left.svg resources/rotate-right.svg + resources/test.pdf resources/zoom-in.svg resources/zoom-fit-best.svg resources/zoom-fit-width.svg resources/zoom-original.svg resources/zoom-out.svg - resources/document-open.svg diff --git a/examples/pdf/pdfviewer/main.cpp b/examples/pdf/pdfviewer/main.cpp index 639b11825..5f65e3061 100644 --- a/examples/pdf/pdfviewer/main.cpp +++ b/examples/pdf/pdfviewer/main.cpp @@ -64,6 +64,8 @@ int main(int argc, char* argv[]) if (app.arguments().count() > 1) { QUrl toLoad = QUrl::fromUserInput(app.arguments().at(1)); engine.rootObjects().first()->setProperty("source", toLoad); + } else { + engine.rootObjects().first()->setProperty("source", QStringLiteral("resources/test.pdf")); } return app.exec(); diff --git a/examples/pdf/pdfviewer/pdfviewer.pro b/examples/pdf/pdfviewer/pdfviewer.pro index 697349cee..b8817c9be 100644 --- a/examples/pdf/pdfviewer/pdfviewer.pro +++ b/examples/pdf/pdfviewer/pdfviewer.pro @@ -1,6 +1,6 @@ TEMPLATE = app -QT += qml quick pdf widgets +QT += qml quick pdf widgets svg SOURCES += main.cpp diff --git a/examples/pdf/pdfviewer/resources/test.pdf b/examples/pdf/pdfviewer/resources/test.pdf new file mode 100644 index 000000000..a9dc1bc29 Binary files /dev/null and b/examples/pdf/pdfviewer/resources/test.pdf differ diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index 586a822a0..a2bccab44 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -63,7 +63,7 @@ ApplicationWindow { color: "lightgrey" title: document.title visible: true - property alias source: document.source // for main.cpp + property string source // for main.cpp property real scaleStep: Math.sqrt(2) header: ToolBar { @@ -204,6 +204,7 @@ ApplicationWindow { x: searchDrawer.position * searchDrawer.width // TODO binding gets broken during centering document: PdfDocument { id: document + source: Qt.resolvedUrl(root.source) onStatusChanged: if (status === PdfDocument.Error) errorDialog.open() } searchString: searchField.text diff --git a/examples/pdf/pdfviewer/viewer.qrc b/examples/pdf/pdfviewer/viewer.qrc index 9698a2689..1b6fa52f7 100644 --- a/examples/pdf/pdfviewer/viewer.qrc +++ b/examples/pdf/pdfviewer/viewer.qrc @@ -1,6 +1,7 @@ viewer.qml + resources/document-open.svg resources/edit-clear.svg resources/edit-copy.svg resources/go-down-search.svg @@ -9,11 +10,11 @@ resources/go-up-search.svg resources/rotate-left.svg resources/rotate-right.svg + resources/test.pdf resources/zoom-in.svg resources/zoom-fit-best.svg resources/zoom-fit-width.svg resources/zoom-original.svg resources/zoom-out.svg - resources/document-open.svg -- cgit v1.2.3 From f467edc97e66727be7fa3747913e4e01672d4b71 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 18 Feb 2020 21:42:35 +0100 Subject: PdfMultiPageView: use TableView; horz. scroll; control page position TableView is missing some features compared to ListView; so finding out where we currently are (which row) and programmatic positioning on a specific y coordinate of a specific row require some workarounds for now, including helpers in PdfDocument. TableView also assumes (and sporadically enforces) that all cells in a column have the same width. So we need a placeholder Item for each page. This also helps with rotation: the placeholder is now as wide as the window or the image, whichever is wider, and the "paper" is centered within; thus there's always room to rotate it. There's still some problem with setting contentY in goToPage() after the page has been zoomed to a size larger than the window: the values look correct, but it scrolls too far. But on the plus side, horizontal scrolling works. So now we attempt to control the horizontal position too: NavigationStack tracks it, and can go back to a previous position; and links can in theory jump to specific positions and zoom levels, scrolling horizontally such that a specific x coordinate is visible. Includes minor UI tweaks to make it look better on iOS. Change-Id: I643d8ef48ef815aeb49cae77dcb84c3682563d56 Reviewed-by: Shawn Rutledge --- examples/pdf/multipage/viewer.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index ac6d2cd9a..9e5f92407 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -249,6 +249,7 @@ ApplicationWindow { y: root.header.height height: view.height dim: false + clip: true ListView { id: searchResultsList anchors.fill: parent @@ -286,7 +287,7 @@ ApplicationWindow { TextField { id: searchField placeholderText: "search" - Layout.minimumWidth: 200 + Layout.minimumWidth: 150 Layout.fillWidth: true onAccepted: searchDrawer.open() Image { @@ -316,11 +317,10 @@ ApplicationWindow { } Label { id: statusLabel - Layout.fillWidth: true property size implicitPointSize: document.pagePointSize(view.currentPage) text: "page " + (currentPageSB.value) + " of " + document.pageCount + " scale " + view.renderScale.toFixed(2) + - " original size " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + " pt" + " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + " pt" visible: document.pageCount > 0 } } -- cgit v1.2.3 From ff13e6532975b5372280c02061cb1b7227cf6699 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 20 Feb 2020 14:09:27 +0100 Subject: Add PdfScrollablePageView, use it in the pdfviewer example PdfPageView might be useful in some cases, but we need to get feature parity with PdfMultiPageView as much as possible, including scrollbars. Including them in the view is convenient, but also less flexible. Change-Id: Ibbe6a090a5f5b1d340124986fe49672d682ddedb Reviewed-by: Shawn Rutledge --- examples/pdf/pdfviewer/viewer.qml | 75 ++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 45 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index a2bccab44..777a9660b 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -80,57 +80,57 @@ ApplicationWindow { ToolButton { action: Action { shortcut: StandardKey.ZoomIn - enabled: pageView.sourceSize.width < 10000 + enabled: view.sourceSize.width < 10000 icon.source: "resources/zoom-in.svg" - onTriggered: pageView.renderScale *= root.scaleStep + onTriggered: view.renderScale *= root.scaleStep } } ToolButton { action: Action { shortcut: StandardKey.ZoomOut - enabled: pageView.sourceSize.width > 50 + enabled: view.sourceSize.width > 50 icon.source: "resources/zoom-out.svg" - onTriggered: pageView.renderScale /= root.scaleStep + onTriggered: view.renderScale /= root.scaleStep } } ToolButton { action: Action { icon.source: "resources/zoom-fit-width.svg" - onTriggered: pageView.scaleToWidth(root.contentItem.width, root.contentItem.height) + onTriggered: view.scaleToWidth(root.contentItem.width, root.contentItem.height) } } ToolButton { action: Action { icon.source: "resources/zoom-fit-best.svg" - onTriggered: pageView.scaleToPage(root.contentItem.width, root.contentItem.height) + onTriggered: view.scaleToPage(root.contentItem.width, root.contentItem.height) } } ToolButton { action: Action { shortcut: "Ctrl+0" icon.source: "resources/zoom-original.svg" - onTriggered: pageView.resetScale() + onTriggered: view.resetScale() } } ToolButton { action: Action { shortcut: "Ctrl+L" icon.source: "resources/rotate-left.svg" - onTriggered: pageView.rotation -= 90 + onTriggered: view.pageRotation -= 90 } } ToolButton { action: Action { shortcut: "Ctrl+R" icon.source: "resources/rotate-right.svg" - onTriggered: pageView.rotation += 90 + onTriggered: view.pageRotation += 90 } } ToolButton { action: Action { icon.source: "resources/go-previous-view-page.svg" - enabled: pageView.backEnabled - onTriggered: pageView.back() + enabled: view.backEnabled + onTriggered: view.back() } ToolTip.visible: enabled && hovered ToolTip.delay: 2000 @@ -141,22 +141,22 @@ ApplicationWindow { from: 1 to: document.pageCount editable: true - value: pageView.currentPage + 1 - onValueModified: pageView.goToPage(value - 1) + value: view.currentPage + 1 + onValueModified: view.goToPage(value - 1) Shortcut { sequence: StandardKey.MoveToPreviousPage - onActivated: pageView.goToPage(currentPageSB.value - 2) + onActivated: view.goToPage(currentPageSB.value - 2) } Shortcut { sequence: StandardKey.MoveToNextPage - onActivated: pageView.goToPage(currentPageSB.value) + onActivated: view.goToPage(currentPageSB.value) } } ToolButton { action: Action { icon.source: "resources/go-next-view-page.svg" - enabled: pageView.forwardEnabled - onTriggered: pageView.forward() + enabled: view.forwardEnabled + onTriggered: view.forward() } ToolTip.visible: enabled && hovered ToolTip.delay: 2000 @@ -166,8 +166,8 @@ ApplicationWindow { action: Action { shortcut: StandardKey.Copy icon.source: "resources/edit-copy.svg" - enabled: pageView.selectedText !== "" - onTriggered: pageView.copySelectionToClipboard() + enabled: view.selectedText !== "" + onTriggered: view.copySelectionToClipboard() } } Shortcut { @@ -199,9 +199,9 @@ ApplicationWindow { } } - PdfPageView { - id: pageView - x: searchDrawer.position * searchDrawer.width // TODO binding gets broken during centering + PdfScrollablePageView { + id: view + anchors.fill: parent document: PdfDocument { id: document source: Qt.resolvedUrl(root.source) @@ -210,21 +210,6 @@ ApplicationWindow { searchString: searchField.text } - WheelHandler { - rotationScale: 15 - target: pageView - property: "x" - orientation: Qt.Horizontal - acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad - } - WheelHandler { - rotationScale: 15 - target: pageView - property: "y" - orientation: Qt.Vertical - acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad - } - Drawer { id: searchDrawer edge: Qt.LeftEdge @@ -249,7 +234,7 @@ ApplicationWindow { action: Action { icon.source: "resources/go-up-search.svg" shortcut: StandardKey.FindPrevious - onTriggered: pageView.searchBack() + onTriggered: view.searchBack() } ToolTip.visible: enabled && hovered ToolTip.delay: 2000 @@ -279,7 +264,7 @@ ApplicationWindow { action: Action { icon.source: "resources/go-down-search.svg" shortcut: StandardKey.FindNext - onTriggered: pageView.searchForward() + onTriggered: view.searchForward() } ToolTip.visible: enabled && hovered ToolTip.delay: 2000 @@ -291,7 +276,7 @@ ApplicationWindow { Layout.fillWidth: true Layout.fillHeight: true clip: true - model: pageView.searchModel + model: view.searchModel ScrollBar.vertical: ScrollBar { } delegate: ItemDelegate { width: parent ? parent.width : 0 @@ -299,8 +284,8 @@ ApplicationWindow { highlighted: ListView.isCurrentItem onClicked: { searchResultsList.currentIndex = index - pageView.goToLocation(page, location, 0) - pageView.searchModel.currentResult = indexOnPage + view.goToLocation(page, location, 0) + view.searchModel.currentResult = indexOnPage } } } @@ -308,9 +293,9 @@ ApplicationWindow { } footer: Label { - property size implicitPointSize: document.pagePointSize(pageView.currentPage) - text: "page " + (pageView.currentPage + 1) + " of " + document.pageCount + - " scale " + pageView.renderScale.toFixed(2) + + property size implicitPointSize: document.pagePointSize(view.currentPage) + text: "page " + (view.currentPage + 1) + " of " + document.pageCount + + " scale " + view.renderScale.toFixed(2) + " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + "pts" visible: document.status === PdfDocument.Ready } -- cgit v1.2.3 From 23e2fd1e2b13f4a6587152d8e26bb5de5d75a231 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 20 Feb 2020 14:53:32 +0100 Subject: PDF single-page example: move search field to the footer As with a2be3a7a79dc4fabe8675ea80a6ba550e0e4deec, this makes the search feature more discoverable and touch-friendly. Change-Id: I47e37273c583121d60985cc27c22f56e6d655ab0 Reviewed-by: Shawn Rutledge --- examples/pdf/pdfviewer/viewer.qml | 142 +++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 71 deletions(-) (limited to 'examples/pdf') diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index 777a9660b..e3bb4b474 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -170,6 +170,10 @@ ApplicationWindow { onTriggered: view.copySelectionToClipboard() } } + Shortcut { + sequence: StandardKey.Find + onActivated: searchField.forceActiveFocus() + } Shortcut { sequence: StandardKey.Quit onActivated: Qt.quit() @@ -214,89 +218,85 @@ ApplicationWindow { id: searchDrawer edge: Qt.LeftEdge modal: false - width: searchLayout.implicitWidth + width: 300 y: root.header.height - height: root.contentItem.height + height: view.height dim: false - Shortcut { - sequence: StandardKey.Find - onActivated: { - searchDrawer.open() - searchField.forceActiveFocus() + clip: true + ListView { + id: searchResultsList + anchors.fill: parent + anchors.margins: 2 + model: view.searchModel + ScrollBar.vertical: ScrollBar { } + delegate: ItemDelegate { + width: parent ? parent.width : 0 + text: "page " + (page + 1) + ": " + context + highlighted: ListView.isCurrentItem + onClicked: { + searchResultsList.currentIndex = index + view.goToLocation(page, location, 0) + view.searchModel.currentResult = indexOnPage + } } } - ColumnLayout { - id: searchLayout + } + + footer: ToolBar { + height: footerRow.implicitHeight + RowLayout { + id: footerRow anchors.fill: parent - anchors.margins: 2 - RowLayout { - ToolButton { - action: Action { - icon.source: "resources/go-up-search.svg" - shortcut: StandardKey.FindPrevious - onTriggered: view.searchBack() - } - ToolTip.visible: enabled && hovered - ToolTip.delay: 2000 - ToolTip.text: "find previous" + ToolButton { + action: Action { + icon.source: "resources/go-up-search.svg" + shortcut: StandardKey.FindPrevious + onTriggered: view.searchBack() } - 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() - } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find previous" + } + TextField { + id: searchField + placeholderText: "search" + Layout.minimumWidth: 150 + Layout.maximumWidth: 300 + Layout.fillWidth: true + onAccepted: searchDrawer.open() + Image { + visible: searchField.text !== "" + source: "resources/edit-clear.svg" + anchors { + right: parent.right + top: parent.top + bottom: parent.bottom + margins: 3 + rightMargin: 5 } - } - ToolButton { - action: Action { - icon.source: "resources/go-down-search.svg" - shortcut: StandardKey.FindNext - onTriggered: view.searchForward() + TapHandler { + onTapped: searchField.clear() } - ToolTip.visible: enabled && hovered - ToolTip.delay: 2000 - ToolTip.text: "find next" } } - ListView { - id: searchResultsList - Layout.fillWidth: true - Layout.fillHeight: true - clip: true - model: view.searchModel - ScrollBar.vertical: ScrollBar { } - delegate: ItemDelegate { - width: parent ? parent.width : 0 - text: "page " + (page + 1) + ": " + context - highlighted: ListView.isCurrentItem - onClicked: { - searchResultsList.currentIndex = index - view.goToLocation(page, location, 0) - view.searchModel.currentResult = indexOnPage - } + ToolButton { + action: Action { + icon.source: "resources/go-down-search.svg" + shortcut: StandardKey.FindNext + onTriggered: view.searchForward() } + ToolTip.visible: enabled && hovered + ToolTip.delay: 2000 + ToolTip.text: "find next" + } + Label { + Layout.fillWidth: true + property size implicitPointSize: document.pagePointSize(view.currentPage) + text: "page " + (view.currentPage + 1) + " of " + document.pageCount + + " scale " + view.renderScale.toFixed(2) + + " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + "pts" + visible: document.status === PdfDocument.Ready } } } - - footer: Label { - property size implicitPointSize: document.pagePointSize(view.currentPage) - text: "page " + (view.currentPage + 1) + " of " + document.pageCount + - " scale " + view.renderScale.toFixed(2) + - " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + "pts" - visible: document.status === PdfDocument.Ready - } } -- cgit v1.2.3