summaryrefslogtreecommitdiffstats
path: root/tests/manual/quick/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/quick/pdf')
-rw-r--r--tests/manual/quick/pdf/bookmarks-list.qml136
-rw-r--r--tests/manual/quick/pdf/bookmarks.qml147
-rw-r--r--tests/manual/quick/pdf/gridview.qml62
-rw-r--r--tests/manual/quick/pdf/listview.qml58
-rw-r--r--tests/manual/quick/pdf/multipleDocuments.qml182
-rw-r--r--tests/manual/quick/pdf/pdfPageView.qml316
-rw-r--r--tests/manual/quick/pdf/pessimizedListView.qml69
-rw-r--r--tests/manual/quick/pdf/simplest.qml53
-rw-r--r--tests/manual/quick/pdf/test.pdfbin80045 -> 76633 bytes
-rw-r--r--tests/manual/quick/pdf/underscoredLinks.qml146
-rw-r--r--tests/manual/quick/pdf/withdoc.qml99
11 files changed, 1044 insertions, 224 deletions
diff --git a/tests/manual/quick/pdf/bookmarks-list.qml b/tests/manual/quick/pdf/bookmarks-list.qml
new file mode 100644
index 000000000..2be0d6848
--- /dev/null
+++ b/tests/manual/quick/pdf/bookmarks-list.qml
@@ -0,0 +1,136 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Pdf
+import QtQuick.Shapes
+
+ApplicationWindow {
+ id: root
+ width: 800
+ height: 940
+ title: doc.source
+ visible: true
+
+ property PdfDocument doc: PdfDocument { source: "test.pdf" }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ doc.source = Application.arguments[Application.arguments.length - 1]
+ }
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: doc.source = selectedFile
+ }
+
+ SplitView {
+ anchors.fill: parent
+
+ Pane {
+ SplitView.minimumWidth: 6
+ SplitView.preferredWidth: 200
+ clip: true
+ ListView {
+ ScrollIndicator.vertical: ScrollIndicator { }
+ anchors.fill: parent
+ delegate: ItemDelegate {
+ width: parent.width
+ text: model.title
+ background: Item { }
+ onClicked: image.currentFrame = page
+ }
+ model: PdfBookmarkModel {
+ document: root.doc
+ }
+ }
+ }
+
+ Flickable {
+ contentWidth: paper.width
+ contentHeight: paper.height
+ z: -1
+ Rectangle {
+ id: paper
+ width: image.width
+ height: image.height
+ PdfPageImage {
+ id: image
+ document: doc
+
+ property real zoomFactor: Math.sqrt(2)
+
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ enabled: image.currentFrame < image.frameCount - 1
+ onActivated: image.currentFrame++
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ enabled: image.currentFrame > 0
+ onActivated: image.currentFrame--
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomIn
+ enabled: image.sourceSize.width < 5000
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth * image.zoomFactor
+ image.sourceSize.height = image.implicitHeight * image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomOut
+ enabled: image.width > 50
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth / image.zoomFactor
+ image.sourceSize.height = image.implicitHeight / image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: "Ctrl+0"
+ onActivated: image.sourceSize = undefined
+ }
+ Shortcut {
+ sequence: StandardKey.Open
+ onActivated: fileDialog.open()
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+ }
+
+ Repeater {
+ model: PdfLinkModel {
+ id: linkModel
+ document: doc
+ page: image.currentFrame
+ }
+ delegate: Rectangle {
+ color: "transparent"
+ border.color: "lightgrey"
+ x: rect.x
+ y: rect.y
+ width: rect.width
+ height: rect.height
+ HoverHandler { cursorShape: Qt.PointingHandCursor }
+ TapHandler {
+ onTapped: {
+ if (page >= 0)
+ image.currentFrame = page
+ else
+ Qt.openUrlExternally(url)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ Text {
+ anchors { bottom: parent.bottom; right: parent.right; margins: 6 }
+ text: "page " + doc.pageLabel(image.currentFrame) + " of " + doc.pageCount
+ }
+}
diff --git a/tests/manual/quick/pdf/bookmarks.qml b/tests/manual/quick/pdf/bookmarks.qml
new file mode 100644
index 000000000..e12629b31
--- /dev/null
+++ b/tests/manual/quick/pdf/bookmarks.qml
@@ -0,0 +1,147 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Pdf
+import QtQuick.Shapes
+
+ApplicationWindow {
+ id: root
+ width: 800
+ height: 940
+ color: "darkgrey"
+ title: doc.source
+ visible: true
+
+ property PdfDocument doc: PdfDocument { source: "test.pdf" }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ doc.source = Application.arguments[Application.arguments.length - 1]
+ }
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: doc.source = selectedFile
+ }
+
+ SplitView {
+ anchors.fill: parent
+
+ Pane {
+ SplitView.minimumWidth: 6
+ SplitView.preferredWidth: 200
+ TreeView {
+ id: bookmarksTree
+ anchors.fill: parent
+ columnWidthProvider: function() { return width }
+ onWidthChanged: forceLayout() // workaround to avoid column width getting stuck
+ clip: true
+ delegate: TreeViewDelegate {
+ width: parent.width
+ onClicked: image.currentFrame = page
+ }
+ model: PdfBookmarkModel {
+ document: root.doc
+ }
+ ScrollIndicator.vertical: ScrollIndicator {
+ // get the ScrollIndicator out into the margin area of the Pane...
+ // no need to overlap the tree when so much space is wasted anyway
+ parent: bookmarksTree.parent
+ anchors {
+ top: bookmarksTree.top
+ left: bookmarksTree.right
+ bottom: bookmarksTree.bottom
+ }
+ }
+ }
+ }
+
+ ScrollView {
+ contentWidth: paper.width
+ contentHeight: paper.height
+
+ Rectangle {
+ id: paper
+ width: image.width
+ height: image.height
+ PdfPageImage {
+ id: image
+ document: doc
+
+ property real zoomFactor: Math.sqrt(2)
+
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ enabled: image.currentFrame < image.frameCount - 1
+ onActivated: image.currentFrame++
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ enabled: image.currentFrame > 0
+ onActivated: image.currentFrame--
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomIn
+ enabled: image.sourceSize.width < 5000
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth * image.zoomFactor
+ image.sourceSize.height = image.implicitHeight * image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomOut
+ enabled: image.width > 50
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth / image.zoomFactor
+ image.sourceSize.height = image.implicitHeight / image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: "Ctrl+0"
+ onActivated: image.sourceSize = undefined
+ }
+ Shortcut {
+ sequence: StandardKey.Open
+ onActivated: fileDialog.open()
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+ }
+
+ Repeater {
+ model: PdfLinkModel {
+ id: linkModel
+ document: doc
+ page: image.currentFrame
+ }
+ delegate: Rectangle {
+ color: "transparent"
+ border.color: "lightgrey"
+ x: rect.x
+ y: rect.y
+ width: rect.width
+ height: rect.height
+ HoverHandler { cursorShape: Qt.PointingHandCursor }
+ TapHandler {
+ onTapped: {
+ if (page >= 0)
+ image.currentFrame = page
+ else
+ Qt.openUrlExternally(url)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ Label {
+ anchors { bottom: parent.bottom; right: parent.right; margins: 6 }
+ text: "page " + doc.pageLabel(image.currentFrame) + " of " + doc.pageCount
+ }
+}
diff --git a/tests/manual/quick/pdf/gridview.qml b/tests/manual/quick/pdf/gridview.qml
new file mode 100644
index 000000000..773e72388
--- /dev/null
+++ b/tests/manual/quick/pdf/gridview.qml
@@ -0,0 +1,62 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Pdf
+
+Window {
+ width: 320
+ height: 440
+ color: "lightgrey"
+ title: doc.source
+ visible: true
+
+ property real cellSize: 150
+
+ PdfDocument {
+ id: doc
+ source: "test.pdf"
+ }
+
+ GridView {
+ id: view
+ anchors.fill: parent
+ anchors.margins: 10
+ model: doc.pageModel
+ cellWidth: cellSize
+ cellHeight: cellSize
+ delegate: Item {
+ required property int index
+ required property string label
+ required property size pointSize
+ width: view.cellWidth
+ height: view.cellHeight
+ Rectangle {
+ id: paper
+ width: image.width
+ height: image.height
+ x: (parent.width - width) / 2
+ y: (parent.height - height - pageNumber.height) / 2
+ PdfPageImage {
+ id: image
+ document: doc
+ currentFrame: index
+ asynchronous: true
+ fillMode: Image.PreserveAspectFit
+ property bool landscape: pointSize.width > pointSize.height
+ width: landscape ? Math.min(view.cellWidth, pointSize.width)
+ : height * pointSize.width / pointSize.height
+ height: landscape ? width * pointSize.height / pointSize.width
+ : Math.min(view.cellHeight - pageNumber.height, pointSize.height)
+ sourceSize.width: width
+ sourceSize.height: height
+ }
+ }
+ Text {
+ id: pageNumber
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "Page " + label
+ }
+ }
+ }
+}
diff --git a/tests/manual/quick/pdf/listview.qml b/tests/manual/quick/pdf/listview.qml
index 361ae7d89..d01be9e86 100644
--- a/tests/manual/quick/pdf/listview.qml
+++ b/tests/manual/quick/pdf/listview.qml
@@ -1,55 +1,7 @@
-/****************************************************************************
-**
-** 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.Window 2.14
-import QtQuick.Pdf 5.15
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Pdf
Window {
width: 600
@@ -82,7 +34,7 @@ Window {
}
}
Text {
- text: "Page " + (image.currentFrame + 1)
+ text: "Page " + doc.pageLabel(image.currentFrame)
}
}
}
diff --git a/tests/manual/quick/pdf/multipleDocuments.qml b/tests/manual/quick/pdf/multipleDocuments.qml
new file mode 100644
index 000000000..9d08178f0
--- /dev/null
+++ b/tests/manual/quick/pdf/multipleDocuments.qml
@@ -0,0 +1,182 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Layouts
+import QtQuick.Pdf
+import Qt.labs.animation
+
+ApplicationWindow {
+ id: root
+ width: 1280
+ height: 1024
+ color: "transparent"
+ flags: Qt.FramelessWindowHint
+ visibility: Window.FullScreen
+ property string source // for main.cpp
+ property real scaleStep: Math.sqrt(2)
+
+ Component {
+ id: pdfWindow
+
+ PdfPageView {
+ property alias source: document.source
+
+ Rectangle {
+ visible: parent.activeFocus
+ color: "transparent"
+ border.color: "cyan"
+ border.width: 3
+ anchors.fill: parent
+ anchors.margins: -border.width
+ anchors.topMargin: -toolbar.height - border.width
+ }
+
+ ToolBar {
+ id: toolbar
+ width: parent.width
+ y: -height
+ RowLayout {
+ anchors.fill: parent
+ anchors.rightMargin: 6
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomIn
+ enabled: pageView.sourceSize.width < 10000
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/zoom-in.svg"
+ onTriggered: pageView.renderScale *= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomOut
+ enabled: pageView.sourceSize.width > 50
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/zoom-out.svg"
+ onTriggered: pageView.renderScale /= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: "Ctrl+0"
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/zoom-original.svg"
+ onTriggered: pageView.resetScale()
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/pdfviewer/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
+ editable: true
+ value: pageView.currentPage + 1
+ onValueModified: pageView.goToPage(value - 1)
+ Layout.maximumWidth: 60
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/go-next-view-page.svg"
+ enabled: pageView.forwardEnabled
+ onTriggered: pageView.forward()
+ }
+ ToolTip.visible: enabled && hovered
+ ToolTip.delay: 2000
+ ToolTip.text: "go forward"
+ }
+ Text {
+ text: document.title
+ elide: Text.ElideRight
+ Layout.fillWidth: true
+ }
+ DragHandler {
+ target: pageView
+ }
+ TapHandler {
+ onTapped: pageView.z++
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.Close
+ text: "☒"
+ onTriggered: pageView.destroy()
+ }
+ }
+ }
+ }
+
+ id: pageView
+ document: PdfDocument {
+ id: document
+ source: Qt.resolvedUrl(root.source)
+ onStatusChanged: (status) => { if (status === PdfDocument.Error) errorDialog.open() }
+ }
+
+ DragHandler {
+ acceptedButtons: Qt.MiddleButton
+ }
+ DragHandler {
+ acceptedDevices: PointerDevice.TouchScreen
+ }
+ HoverHandler {
+ onHoveredChanged: if (hovered) pageView.forceActiveFocus()
+ }
+
+ 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
+ }
+ }
+ }
+ }
+
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ onActivated: root.activeFocusItem.goToPage(root.activeFocusItem.currentPage - 1)
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ onActivated: root.activeFocusItem.goToPage(root.activeFocusItem.currentPage + 1)
+ }
+ Shortcut {
+ sequence: StandardKey.Open
+ onActivated: fileDialog.open()
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+
+ function open(src) {
+ var win = pdfWindow.createObject(root, { source: src, y: 50 })
+ }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ root.open(Application.arguments[Application.arguments.length - 1])
+ }
+
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: root.open(selectedFile)
+ }
+}
diff --git a/tests/manual/quick/pdf/pdfPageView.qml b/tests/manual/quick/pdf/pdfPageView.qml
new file mode 100644
index 000000000..475e1d608
--- /dev/null
+++ b/tests/manual/quick/pdf/pdfPageView.qml
@@ -0,0 +1,316 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Layouts
+import QtQuick.Pdf
+import Qt.labs.animation
+
+ApplicationWindow {
+ id: root
+ width: 800
+ height: 1024
+ color: "lightgrey"
+ title: document.title
+ visible: true
+ property string 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: "../../../../examples/pdf/pdfviewer/resources/document-open.svg"
+ onTriggered: fileDialog.open()
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomIn
+ enabled: pageView.sourceSize.width < 10000
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/zoom-in.svg"
+ onTriggered: pageView.renderScale *= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: StandardKey.ZoomOut
+ enabled: pageView.sourceSize.width > 50
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/zoom-out.svg"
+ onTriggered: pageView.renderScale /= root.scaleStep
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/zoom-fit-width.svg"
+ onTriggered: pageView.scaleToWidth(root.contentItem.width, root.contentItem.height)
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/zoom-fit-best.svg"
+ onTriggered: pageView.scaleToPage(root.contentItem.width, root.contentItem.height)
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: "Ctrl+0"
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/zoom-original.svg"
+ onTriggered: pageView.resetScale()
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: "Ctrl+L"
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/rotate-left.svg"
+ onTriggered: pageView.rotation -= 90
+ }
+ }
+ ToolButton {
+ action: Action {
+ shortcut: "Ctrl+R"
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/rotate-right.svg"
+ onTriggered: pageView.rotation += 90
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/pdfviewer/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: 0
+ to: document.pageCount
+ editable: true
+ value: pageView.currentPage
+ onValueModified: pageView.goToPage(value)
+
+ textFromValue: function(value) { return document.pageLabel(value) }
+ valueFromText: function(text) {
+ for (var i = 0; i < document.pageCount; ++i) {
+ if (document.pageLabel(i).toLowerCase().indexOf(text.toLowerCase()) === 0)
+ return i
+ }
+ return spinBox.value
+ }
+
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ onActivated: pageView.goToPage(currentPageSB.value - 1)
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ onActivated: pageView.goToPage(currentPageSB.value + 1)
+ }
+ }
+ ToolButton {
+ action: Action {
+ icon.source: "../../../../examples/pdf/pdfviewer/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
+ icon.source: "../../../../examples/pdf/pdfviewer/resources/edit-copy.svg"
+ enabled: pageView.selectedText !== ""
+ onTriggered: pageView.copySelectionToClipboard()
+ }
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+ }
+ }
+
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: document.source = selectedFile
+ }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ document.source = Application.arguments[Application.arguments.length - 1]
+ }
+
+ 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
+ x: searchDrawer.position * searchDrawer.width // TODO binding gets broken during centering
+ document: PdfDocument {
+ id: document
+ source: Qt.resolvedUrl(root.source)
+ onStatusChanged: (status) => { if (status === PdfDocument.Error) errorDialog.open() }
+ }
+ searchString: searchField.text
+ onRenderScaleChanged: pageView.returnToBounds()
+
+ DragHandler {
+ acceptedButtons: Qt.MiddleButton
+ onActiveChanged: if (!active) pageView.returnToBounds()
+ }
+ DragHandler {
+ acceptedDevices: PointerDevice.TouchScreen
+ onActiveChanged: if (!active) pageView.returnToBounds()
+ }
+
+ BoundaryRule on x {
+ id: brx
+ minimumOvershoot: 100
+ maximumOvershoot: 100
+ minimum: Math.min(0, root.width - pageView.width)
+ maximum: 0
+ }
+
+ BoundaryRule on y {
+ id: bry
+ minimumOvershoot: 100
+ maximumOvershoot: 100
+ minimum: Math.min(0, root.height - pageView.height)
+ maximum: 0
+ }
+
+ function returnToBounds() {
+ bry.returnToBounds()
+ brx.returnToBounds()
+ }
+ }
+
+ WheelHandler {
+ target: pageView
+ property: "x"
+ orientation: Qt.Horizontal
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
+ acceptedModifiers: Qt.NoModifier
+ onActiveChanged: if (!active) brx.returnToBounds()
+ }
+ WheelHandler {
+ target: pageView
+ property: "y"
+ orientation: Qt.Vertical
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
+ acceptedModifiers: Qt.NoModifier
+ onActiveChanged: if (!active) bry.returnToBounds()
+ }
+
+ 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: "../../../../examples/pdf/pdfviewer/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: "../../../../examples/pdf/pdfviewer/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: "../../../../examples/pdf/pdfviewer/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
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ clip: true
+ model: pageView.searchModel
+ ScrollBar.vertical: ScrollBar { }
+ delegate: ItemDelegate {
+ width: parent ? parent.width : 0
+ text: "page " + document.pageLabel(page) + ": " + contextBefore + pageView.searchString + contextAfter
+ 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 " + document.pageCount +
+ " scale " + pageView.renderScale.toFixed(2) +
+ " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + "pts"
+ visible: document.status === PdfDocument.Ready
+ }
+}
diff --git a/tests/manual/quick/pdf/pessimizedListView.qml b/tests/manual/quick/pdf/pessimizedListView.qml
index 4ae0edabe..1b514668e 100644
--- a/tests/manual/quick/pdf/pessimizedListView.qml
+++ b/tests/manual/quick/pdf/pessimizedListView.qml
@@ -1,57 +1,10 @@
-/****************************************************************************
-**
-** 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 Qt.labs.platform 1.1 as P
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Layouts
+import QtQuick.Pdf
ApplicationWindow {
width: 900
@@ -127,11 +80,11 @@ ApplicationWindow {
source: "test.pdf"
}
- P.FileDialog {
+ FileDialog {
id: fileDialog
title: "Open a PDF file"
nameFilters: [ "PDF files (*.pdf)" ]
- onAccepted: doc.source = file
+ onAccepted: doc.source = selectedFile
}
ListView {
@@ -150,15 +103,15 @@ ApplicationWindow {
anchors.centerIn: parent
running: image.status === Image.Loading
}
- Image {
+ PdfPageImage {
id: image
+ document: doc
scale: imageScale
anchors.centerIn: parent
sourceSize.width: doc.pagePointSize(index).width * oversamplingSB.value
height: 100
fillMode: Image.PreserveAspectFit
objectName: "PDF page " + index
- source: doc.source
currentFrame: index
asynchronous: asyncCB.checked
cache: cacheCB.checked
diff --git a/tests/manual/quick/pdf/simplest.qml b/tests/manual/quick/pdf/simplest.qml
index 0571493af..3f39bb213 100644
--- a/tests/manual/quick/pdf/simplest.qml
+++ b/tests/manual/quick/pdf/simplest.qml
@@ -1,53 +1,6 @@
-/****************************************************************************
-**
-** 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
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
Image {
id: image
diff --git a/tests/manual/quick/pdf/test.pdf b/tests/manual/quick/pdf/test.pdf
index a9dc1bc29..0832dfbed 100644
--- a/tests/manual/quick/pdf/test.pdf
+++ b/tests/manual/quick/pdf/test.pdf
Binary files differ
diff --git a/tests/manual/quick/pdf/underscoredLinks.qml b/tests/manual/quick/pdf/underscoredLinks.qml
new file mode 100644
index 000000000..514008ca2
--- /dev/null
+++ b/tests/manual/quick/pdf/underscoredLinks.qml
@@ -0,0 +1,146 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Pdf
+import QtQuick.Shapes
+
+ApplicationWindow {
+ id: root
+ width: 800
+ height: 940
+ color: "darkgrey"
+ title: doc.source
+ visible: true
+
+ property PdfDocument doc: PdfDocument { source: "test.pdf" }
+
+ Component.onCompleted: {
+ if (Application.arguments.length > 2)
+ doc.source = Application.arguments[Application.arguments.length - 1]
+ }
+ FileDialog {
+ id: fileDialog
+ title: "Open a PDF file"
+ nameFilters: [ "PDF files (*.pdf)" ]
+ onAccepted: doc.source = selectedFile
+ }
+ ScrollView {
+ anchors.fill: parent
+ contentWidth: paper.width
+ contentHeight: paper.height
+
+ Rectangle {
+ id: paper
+ width: image.width
+ height: image.height
+ PdfPageImage {
+ id: image
+ document: doc
+
+ property real zoomFactor: Math.sqrt(2)
+
+ Shortcut {
+ sequence: StandardKey.MoveToNextPage
+ enabled: image.currentFrame < image.frameCount - 1
+ onActivated: image.currentFrame++
+ }
+ Shortcut {
+ sequence: StandardKey.MoveToPreviousPage
+ enabled: image.currentFrame > 0
+ onActivated: image.currentFrame--
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomIn
+ enabled: image.sourceSize.width < 5000
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth * image.zoomFactor
+ image.sourceSize.height = image.implicitHeight * image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: StandardKey.ZoomOut
+ enabled: image.width > 50
+ onActivated: {
+ image.sourceSize.width = image.implicitWidth / image.zoomFactor
+ image.sourceSize.height = image.implicitHeight / image.zoomFactor
+ }
+ }
+ Shortcut {
+ sequence: "Ctrl+0"
+ onActivated: image.sourceSize = undefined
+ }
+ Shortcut {
+ sequence: StandardKey.Open
+ onActivated: fileDialog.open()
+ }
+ Shortcut {
+ sequence: StandardKey.Quit
+ onActivated: Qt.quit()
+ }
+ }
+
+ Menu {
+ id: linkContextMenu
+ property var currentLink
+ MenuItem {
+ text: "Go"
+ onTriggered: {
+ if (linkContextMenu.currentLink.page >= 0)
+ image.currentFrame = linkContextMenu.currentLink.page
+ else
+ Qt.openUrlExternally(linkContextMenu.currentLink.url)
+ }
+ }
+ MenuItem {
+ text: "Copy"
+ onTriggered: linkContextMenu.currentLink.copyToClipboard()
+ }
+ }
+
+ Repeater {
+ model: PdfLinkModel {
+ id: linkModel
+ document: doc
+ page: image.currentFrame
+ }
+ delegate: PdfLinkDelegate {
+ x: rectangle.x
+ y: rectangle.y
+ width: rectangle.width
+ height: rectangle.height
+ onTapped:
+ (link) => {
+ if (link.page >= 0)
+ image.currentFrame = link.page
+ else
+ Qt.openUrlExternally(url)
+ }
+ onContextMenuRequested:
+ (link) => {
+ linkContextMenu.currentLink = link
+ linkContextMenu.x = x
+ linkContextMenu.y = y
+ linkContextMenu.open()
+ }
+ Shape {
+ anchors.fill: parent
+ ShapePath {
+ strokeWidth: 1
+ strokeColor: palette.link
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ startX: 0; startY: height
+ PathLine { x: width; y: height }
+ }
+ }
+ }
+ }
+ }
+ }
+ Label {
+ anchors { bottom: parent.bottom; right: parent.right; margins: 6 }
+ text: "page " + (image.currentFrame + 1) + " of " + doc.pageCount
+ }
+}
diff --git a/tests/manual/quick/pdf/withdoc.qml b/tests/manual/quick/pdf/withdoc.qml
index 2d82a6abf..d4bf12e29 100644
--- a/tests/manual/quick/pdf/withdoc.qml
+++ b/tests/manual/quick/pdf/withdoc.qml
@@ -1,58 +1,10 @@
-/****************************************************************************
-**
-** 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 Qt.labs.platform 1.1 as Platform
-import QtQuick.Pdf 5.15
-import QtQuick.Shapes 1.14
-import QtQuick.Window 2.14
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Dialogs
+import QtQuick.Pdf
+import QtQuick.Shapes
Window {
width: 800
@@ -64,21 +16,42 @@ Window {
PdfDocument {
id: doc
source: "test.pdf"
+ onPasswordRequired: function() { passwordDialog.open() }
}
- Platform.FileDialog {
+ FileDialog {
id: fileDialog
title: "Open a PDF file"
nameFilters: [ "PDF files (*.pdf)" ]
- onAccepted: doc.source = file
+ onAccepted: doc.source = selectedFile
+ }
+
+ Dialog {
+ id: passwordDialog
+ title: "Password"
+ standardButtons: Dialog.Ok | Dialog.Cancel
+ modal: true
+ closePolicy: Popup.CloseOnEscape
+ anchors.centerIn: parent
+ width: 300
+
+ contentItem: TextField {
+ id: passwordField
+ placeholderText: qsTr("Please provide the password")
+ echoMode: TextInput.Password
+ width: parent.width
+ onAccepted: passwordDialog.accept()
+ }
+ onOpened: function() { passwordField.forceActiveFocus() }
+ onAccepted: doc.password = passwordField.text
}
PdfSelection {
id: selection
document: doc
page: image.currentFrame
- fromPoint: dragHandler.centroid.pressPosition
- toPoint: dragHandler.centroid.position
+ from: dragHandler.centroid.pressPosition
+ to: dragHandler.centroid.position
hold: !dragHandler.active
}
@@ -109,9 +82,9 @@ Window {
id: paper
width: image.width
height: image.height
- Image {
+ PdfPageImage {
id: image
- source: doc.status === PdfDocument.Ready ? doc.source : ""
+ document: doc
property real zoomFactor: Math.sqrt(2)
@@ -185,7 +158,7 @@ Window {
y: rect.y
width: rect.width
height: rect.height
-// HoverHandler { cursorShape: Qt.PointingHandCursor } // 5.15 onward (QTBUG-68073)
+ HoverHandler { cursorShape: Qt.PointingHandCursor }
TapHandler {
onTapped: {
if (page >= 0)
@@ -201,6 +174,6 @@ Window {
}
Text {
anchors.bottom: parent.bottom
- text: "page " + (image.currentFrame + 1) + " of " + doc.pageCount
+ text: "page " + (image.currentFrame + 1) + " of " + doc.pageCount + " label: " + doc.pageLabel(image.currentFrame)
}
}