summaryrefslogtreecommitdiffstats
path: root/examples/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'examples/pdf')
-rw-r--r--examples/pdf/multipage/CMakeLists.txt13
-rw-r--r--examples/pdf/multipage/doc/src/multipage.qdoc31
-rw-r--r--examples/pdf/multipage/main.cpp61
-rw-r--r--examples/pdf/multipage/multipage.pro4
-rw-r--r--examples/pdf/multipage/pdfapplication.cpp16
-rw-r--r--examples/pdf/multipage/pdfapplication.h24
-rw-r--r--examples/pdf/multipage/resources/macos/Info.plist29
-rw-r--r--examples/pdf/multipage/resources/multipage.icnsbin0 -> 117648 bytes
-rw-r--r--examples/pdf/multipage/resources/sidebar-collapse-left.svg13
-rw-r--r--examples/pdf/multipage/resources/sidebar-expand-left.svg13
-rw-r--r--examples/pdf/multipage/resources/test.pdfbin80045 -> 76633 bytes
-rw-r--r--examples/pdf/multipage/viewer.qml321
-rw-r--r--examples/pdf/multipage/viewer.qrc2
-rw-r--r--examples/pdf/pdfviewer/main.cpp78
-rw-r--r--examples/pdf/pdfviewer/resources/test.pdfbin80045 -> 76633 bytes
-rw-r--r--examples/pdf/pdfviewer/viewer.qml102
16 files changed, 389 insertions, 318 deletions
diff --git a/examples/pdf/multipage/CMakeLists.txt b/examples/pdf/multipage/CMakeLists.txt
index 7fdfbf678..92c2bce22 100644
--- a/examples/pdf/multipage/CMakeLists.txt
+++ b/examples/pdf/multipage/CMakeLists.txt
@@ -13,8 +13,19 @@ find_package(Qt6 REQUIRED COMPONENTS Gui Qml)
qt_add_executable(multipage
main.cpp
+ pdfapplication.h
+ pdfapplication.cpp
)
+if (APPLE AND NOT IOS)
+ set(MACOSX_BUNDLE_ICON_FILE multipage.icns)
+ set(app_icon_macos "${CMAKE_CURRENT_SOURCE_DIR}/resources/multipage.icns")
+ set_source_files_properties(${app_icon_macos} PROPERTIES
+ MACOSX_PACKAGE_LOCATION "Resources")
+ target_sources(multipage PRIVATE ${app_icon_macos})
+ set(MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resources/macos/Info.plist")
+endif()
+
set_target_properties(multipage PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
@@ -36,6 +47,8 @@ set(viewer_resource_files
"resources/go-up-search.svg"
"resources/rotate-left.svg"
"resources/rotate-right.svg"
+ "resources/sidebar-collapse-left.svg"
+ "resources/sidebar-expand-left.svg"
"resources/test.pdf"
"resources/zoom-fit-best.svg"
"resources/zoom-fit-width.svg"
diff --git a/examples/pdf/multipage/doc/src/multipage.qdoc b/examples/pdf/multipage/doc/src/multipage.qdoc
index ecb8127b1..b4963c508 100644
--- a/examples/pdf/multipage/doc/src/multipage.qdoc
+++ b/examples/pdf/multipage/doc/src/multipage.qdoc
@@ -1,36 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\example multipage
+ \meta installpath pdf
\ingroup qtpdf-examples
\title PDF Multipage Viewer Example
- \brief A PDF viewer that allows scrolling through the pages.
+ \brief A Qt Quick PDF viewer that allows scrolling through the pages.
\image multipageviewer.png
diff --git a/examples/pdf/multipage/main.cpp b/examples/pdf/multipage/main.cpp
index 9311afa8e..9f9272d69 100644
--- a/examples/pdf/multipage/main.cpp
+++ b/examples/pdf/multipage/main.cpp
@@ -1,54 +1,7 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-#include <QGuiApplication>
+#include "pdfapplication.h"
#include <QQmlApplicationEngine>
int main(int argc, char* argv[])
@@ -56,17 +9,17 @@ int main(int argc, char* argv[])
QCoreApplication::setApplicationName("Qt Quick Multi-page PDF Viewer Example");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
- QGuiApplication app(argc, argv);
+ PdfApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:///pdfviewer/viewer.qml")));
+ app.setFileOpener(engine.rootObjects().constFirst());
if (app.arguments().count() > 1) {
QUrl toLoad = QUrl::fromUserInput(app.arguments().at(1));
- engine.rootObjects().first()->setProperty("source", toLoad);
+ engine.rootObjects().constFirst()->setProperty("source", toLoad);
} else {
- engine.rootObjects().first()->setProperty("source", QStringLiteral("resources/test.pdf"));
+ engine.rootObjects().constFirst()->setProperty("source", QStringLiteral("resources/test.pdf"));
}
-
return app.exec();
}
diff --git a/examples/pdf/multipage/multipage.pro b/examples/pdf/multipage/multipage.pro
index bd08ba0de..c12651335 100644
--- a/examples/pdf/multipage/multipage.pro
+++ b/examples/pdf/multipage/multipage.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
QT += qml quick pdf svg
-SOURCES += main.cpp
+SOURCES += main.cpp pdfapplication.cpp
RESOURCES += \
viewer.qrc
@@ -12,3 +12,5 @@ EXAMPLE_FILES = \
target.path = $$[QT_INSTALL_EXAMPLES]/pdf/multipage
INSTALLS += target
+macos:QMAKE_INFO_PLIST = resources/macos/Info.plist
+macos:ICON = resources/multipage.icns
diff --git a/examples/pdf/multipage/pdfapplication.cpp b/examples/pdf/multipage/pdfapplication.cpp
new file mode 100644
index 000000000..d8e7c6486
--- /dev/null
+++ b/examples/pdf/multipage/pdfapplication.cpp
@@ -0,0 +1,16 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "pdfapplication.h"
+#include <QFileOpenEvent>
+
+PdfApplication::PdfApplication(int &argc, char **argv)
+ : QGuiApplication(argc, argv) { }
+
+bool PdfApplication::event(QEvent *e) {
+ if (e->type() == QEvent::FileOpen) {
+ QFileOpenEvent *foEvent = static_cast<QFileOpenEvent *>(e);
+ m_fileOpener->setProperty("source", foEvent->url());
+ }
+ return QGuiApplication::event(e);
+}
diff --git a/examples/pdf/multipage/pdfapplication.h b/examples/pdf/multipage/pdfapplication.h
new file mode 100644
index 000000000..06c998e1c
--- /dev/null
+++ b/examples/pdf/multipage/pdfapplication.h
@@ -0,0 +1,24 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef PDFAPPLICATION_H
+#define PDFAPPLICATION_H
+
+#include <QGuiApplication>
+#include <QObject>
+
+class PdfApplication : public QGuiApplication
+{
+public:
+ PdfApplication(int &argc, char **argv);
+ void setFileOpener(QObject *opener) {
+ m_fileOpener = opener;
+ }
+
+protected:
+ bool event(QEvent *e) override;
+
+ QObject *m_fileOpener;
+};
+
+#endif // PDFAPPLICATION_H
diff --git a/examples/pdf/multipage/resources/macos/Info.plist b/examples/pdf/multipage/resources/macos/Info.plist
new file mode 100644
index 000000000..512becda0
--- /dev/null
+++ b/examples/pdf/multipage/resources/macos/Info.plist
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.1">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>multipage</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.qt-project.multipage</string>
+ <key>CFBundleDisplayName</key>
+ <string>Multi-page PDF Viewer</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleExecutable</key>
+ <string>multipage</string>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ <key>CFBundleTypeName</key>
+ <string>pdf</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>com.adobe.pdf</string>
+ </array>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/examples/pdf/multipage/resources/multipage.icns b/examples/pdf/multipage/resources/multipage.icns
new file mode 100644
index 000000000..2e3756903
--- /dev/null
+++ b/examples/pdf/multipage/resources/multipage.icns
Binary files differ
diff --git a/examples/pdf/multipage/resources/sidebar-collapse-left.svg b/examples/pdf/multipage/resources/sidebar-collapse-left.svg
new file mode 100644
index 000000000..06f84afb4
--- /dev/null
+++ b/examples/pdf/multipage/resources/sidebar-collapse-left.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ <g transform="translate(1,1)">
+ <g class="ColorScheme-Text" fill="currentColor">
+ <path d="m3 3v16h16v-16zm5 1h10v14h-10z" stroke-linecap="square" stroke-linejoin="round"/>
+ <path d="m14.646484 6.6464844-4.353515 4.3535156 4.353515 4.353516.707032-.707032-3.646485-3.646484 3.646485-3.6464844z"/>
+ </g>
+ </g>
+</svg>
diff --git a/examples/pdf/multipage/resources/sidebar-expand-left.svg b/examples/pdf/multipage/resources/sidebar-expand-left.svg
new file mode 100644
index 000000000..83b35206e
--- /dev/null
+++ b/examples/pdf/multipage/resources/sidebar-expand-left.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
+ <style type="text/css" id="current-color-scheme">
+ .ColorScheme-Text {
+ color:#232629;
+ }
+ </style>
+ <g transform="translate(1,1)">
+ <g class="ColorScheme-Text" fill="currentColor">
+ <path d="m3 3v16h16v-16zm5 1h10v14h-10z" stroke-linecap="square" stroke-linejoin="round"/>
+ <path d="m11.353516 6.6464844 4.353515 4.3535156-4.353515 4.353516-.707032-.707032 3.646485-3.646484-3.646485-3.6464844z"/>
+ </g>
+ </g>
+</svg>
diff --git a/examples/pdf/multipage/resources/test.pdf b/examples/pdf/multipage/resources/test.pdf
index a9dc1bc29..0832dfbed 100644
--- a/examples/pdf/multipage/resources/test.pdf
+++ b/examples/pdf/multipage/resources/test.pdf
Binary files differ
diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml
index 7c883a02b..fcf326869 100644
--- a/examples/pdf/multipage/viewer.qml
+++ b/examples/pdf/multipage/viewer.qml
@@ -1,67 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 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 QtQml // workaround for QTBUG-82873
+// 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 QtQuick.Shapes
-import QtQuick.Window
ApplicationWindow {
id: root
width: 800
height: 1024
color: "lightgrey"
- title: document.title
+ title: doc.title
visible: true
property string source // for main.cpp
@@ -128,7 +78,7 @@ ApplicationWindow {
ToolButton {
action: Action {
icon.source: "qrc:/pdfviewer/resources/go-previous-view-page.svg"
- enabled: view.backEnbled
+ enabled: view.backEnabled
onTriggered: view.back()
}
ToolTip.visible: enabled && hovered
@@ -138,7 +88,7 @@ ApplicationWindow {
SpinBox {
id: currentPageSB
from: 1
- to: document.pageCount
+ to: doc.pageCount
editable: true
onValueModified: view.goToPage(value - 1)
Shortcut {
@@ -190,7 +140,7 @@ ApplicationWindow {
id: fileDialog
title: "Open a PDF file"
nameFilters: [ "PDF files (*.pdf)" ]
- onAccepted: document.source = selectedFile
+ onAccepted: doc.source = selectedFile
}
Dialog {
@@ -202,55 +152,63 @@ ApplicationWindow {
anchors.centerIn: parent
width: 300
- TextField {
+ contentItem: TextField {
id: passwordField
placeholderText: qsTr("Please provide the password")
echoMode: TextInput.Password
width: parent.width
onAccepted: passwordDialog.accept()
}
- onAccepted: document.password = passwordField.text
+ onOpened: passwordField.forceActiveFocus()
+ onAccepted: doc.password = passwordField.text
}
Dialog {
id: errorDialog
- title: "Error loading " + document.source
- standardButtons: Dialog.Ok
+ title: "Error loading " + doc.source
+ standardButtons: Dialog.Close
modal: true
closePolicy: Popup.CloseOnEscape
anchors.centerIn: parent
width: 300
+ visible: doc.status === PdfDocument.Error
- Label {
+ contentItem: Label {
id: errorField
- text: document.error
+ text: doc.error
}
}
PdfDocument {
- id: document
+ id: doc
source: Qt.resolvedUrl(root.source)
- onStatusChanged: {
- if (status === PdfDocument.Error) errorDialog.open()
- view.document = (status === PdfDocument.Ready ? document : undefined)
- }
- onPasswordRequired: {
- passwordDialog.open()
- passwordField.forceActiveFocus()
- }
+ onPasswordRequired: passwordDialog.open()
}
PdfMultiPageView {
id: view
anchors.fill: parent
- anchors.leftMargin: searchDrawer.position * searchDrawer.width
- document: root.document
+ anchors.leftMargin: sidebar.position * sidebar.width
+ document: doc
searchString: searchField.text
onCurrentPageChanged: currentPageSB.value = view.currentPage + 1
}
+ DropArea {
+ anchors.fill: parent
+ keys: ["text/uri-list"]
+ onEntered: (drag) => {
+ drag.accepted = (drag.proposedAction === Qt.MoveAction || drag.proposedAction === Qt.CopyAction) &&
+ drag.hasUrls && drag.urls[0].endsWith("pdf")
+ }
+ onDropped: (drop) => {
+ doc.source = drop.urls[0]
+ drop.acceptProposedAction()
+ }
+ }
+
Drawer {
- id: searchDrawer
+ id: sidebar
edge: Qt.LeftEdge
modal: false
width: 300
@@ -258,56 +216,186 @@ ApplicationWindow {
height: view.height
dim: false
clip: true
- ListView {
- id: searchResultsList
+
+ TabBar {
+ id: sidebarTabs
+ x: -width
+ rotation: -90
+ transformOrigin: Item.TopRight
+ currentIndex: 2 // bookmarks by default
+ TabButton {
+ text: qsTr("Info")
+ }
+ TabButton {
+ text: qsTr("Search Results")
+ }
+ TabButton {
+ text: qsTr("Bookmarks")
+ }
+ TabButton {
+ text: qsTr("Pages")
+ }
+ }
+
+ GroupBox {
anchors.fill: parent
- anchors.margins: 2
- model: view.searchModel
- ScrollBar.vertical: ScrollBar { }
- delegate: ItemDelegate {
- width: parent ? parent.width : 0
- RowLayout {
- anchors.fill: parent
- spacing: 0
- Label {
- text: "Page " + (page + 1) + ": "
- }
- Label {
- text: contextBefore
- elide: Text.ElideLeft
- horizontalAlignment: Text.AlignRight
- Layout.fillWidth: true
- Layout.preferredWidth: parent.width / 2
+ anchors.leftMargin: sidebarTabs.height
+
+ StackLayout {
+ anchors.fill: parent
+ currentIndex: sidebarTabs.currentIndex
+ component InfoField: TextInput {
+ width: parent.width
+ selectByMouse: true
+ readOnly: true
+ wrapMode: Text.WordWrap
+ }
+ Column {
+ spacing: 6
+ width: parent.width - 6
+ Label { font.bold: true; text: qsTr("Title") }
+ InfoField { text: doc.title }
+ Label { font.bold: true; text: qsTr("Author") }
+ InfoField { text: doc.author }
+ Label { font.bold: true; text: qsTr("Subject") }
+ InfoField { text: doc.subject }
+ Label { font.bold: true; text: qsTr("Keywords") }
+ InfoField { text: doc.keywords }
+ Label { font.bold: true; text: qsTr("Producer") }
+ InfoField { text: doc.producer }
+ Label { font.bold: true; text: qsTr("Creator") }
+ InfoField { text: doc.creator }
+ Label { font.bold: true; text: qsTr("Creation date") }
+ InfoField { text: doc.creationDate }
+ Label { font.bold: true; text: qsTr("Modification date") }
+ InfoField { text: doc.modificationDate }
+ }
+ ListView {
+ id: searchResultsList
+ implicitHeight: parent.height
+ model: view.searchModel
+ currentIndex: view.searchModel.currentResult
+ ScrollBar.vertical: ScrollBar { }
+ delegate: ItemDelegate {
+ id: resultDelegate
+ required property int index
+ required property int page
+ required property string contextBefore
+ required property string contextAfter
+ width: parent ? parent.width : 0
+ RowLayout {
+ anchors.fill: parent
+ spacing: 0
+ Label {
+ text: "Page " + (resultDelegate.page + 1) + ": "
+ }
+ Label {
+ text: resultDelegate.contextBefore
+ elide: Text.ElideLeft
+ horizontalAlignment: Text.AlignRight
+ Layout.fillWidth: true
+ Layout.preferredWidth: parent.width / 2
+ }
+ Label {
+ font.bold: true
+ text: view.searchString
+ width: implicitWidth
+ }
+ Label {
+ text: resultDelegate.contextAfter
+ elide: Text.ElideRight
+ Layout.fillWidth: true
+ Layout.preferredWidth: parent.width / 2
+ }
+ }
+ highlighted: ListView.isCurrentItem
+ onClicked: view.searchModel.currentResult = resultDelegate.index
}
- Label {
- font.bold: true
- text: view.searchString
- width: implicitWidth
+ }
+ TreeView {
+ id: bookmarksTree
+ implicitHeight: parent.height
+ implicitWidth: parent.width
+ columnWidthProvider: function() { return width }
+ delegate: TreeViewDelegate {
+ required property int page
+ required property point location
+ required property real zoom
+ onClicked: view.goToLocation(page, location, zoom)
}
- Label {
- text: contextAfter
- elide: Text.ElideRight
- Layout.fillWidth: true
- Layout.preferredWidth: parent.width / 2
+ model: PdfBookmarkModel {
+ document: doc
}
+ ScrollBar.vertical: ScrollBar { }
}
- highlighted: ListView.isCurrentItem
- onClicked: {
- searchResultsList.currentIndex = index
- view.goToLocation(page, location, 0)
- view.searchModel.currentResult = indexOnPage
+ GridView {
+ id: thumbnailsView
+ implicitWidth: parent.width
+ implicitHeight: parent.height
+ model: doc.pageModel
+ cellWidth: width / 2
+ cellHeight: cellWidth + 10
+ delegate: Item {
+ required property int index
+ required property string label
+ required property size pointSize
+ width: thumbnailsView.cellWidth
+ height: thumbnailsView.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 ? thumbnailsView.cellWidth - 6
+ : height * pointSize.width / pointSize.height
+ height: landscape ? width * pointSize.height / pointSize.width
+ : thumbnailsView.cellHeight - 14
+ sourceSize.width: width
+ sourceSize.height: height
+ }
+ }
+ Text {
+ id: pageNumber
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: label
+ }
+ TapHandler {
+ onTapped: view.goToPage(index)
+ }
+ }
}
}
}
}
footer: ToolBar {
- height: footerRow.implicitHeight
+ height: footerRow.implicitHeight + 6
RowLayout {
id: footerRow
anchors.fill: parent
ToolButton {
action: Action {
+ id: sidebarOpenAction
+ checkable: true
+ checked: sidebar.opened
+ icon.source: checked ? "qrc:/pdfviewer/resources/sidebar-collapse-left.svg" : "qrc:/pdfviewer/resources/sidebar-expand-left.svg"
+ onTriggered: sidebar.open()
+ }
+ ToolTip.visible: enabled && hovered
+ ToolTip.delay: 2000
+ ToolTip.text: "open sidebar"
+ }
+ ToolButton {
+ action: Action {
icon.source: "qrc:/pdfviewer/resources/go-up-search.svg"
shortcut: StandardKey.FindPrevious
onTriggered: view.searchBack()
@@ -321,16 +409,19 @@ ApplicationWindow {
placeholderText: "search"
Layout.minimumWidth: 150
Layout.fillWidth: true
- onAccepted: searchDrawer.open()
+ Layout.bottomMargin: 3
+ onAccepted: {
+ sidebar.open()
+ sidebarTabs.setCurrentIndex(0)
+ }
Image {
visible: searchField.text !== ""
source: "qrc:/pdfviewer/resources/edit-clear.svg"
+ sourceSize.height: searchField.height - 6
anchors {
right: parent.right
- top: parent.top
- bottom: parent.bottom
+ verticalCenter: parent.verticalCenter
margins: 3
- rightMargin: 5
}
TapHandler {
onTapped: searchField.clear()
@@ -349,11 +440,11 @@ ApplicationWindow {
}
Label {
id: statusLabel
- property size implicitPointSize: document.pagePointSize(view.currentPage)
- text: "page " + (currentPageSB.value) + " of " + document.pageCount +
+ property size implicitPointSize: doc.pagePointSize(view.currentPage)
+ text: "page " + (currentPageSB.value) + " of " + doc.pageCount +
" scale " + view.renderScale.toFixed(2) +
" original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + " pt"
- visible: document.pageCount > 0
+ visible: doc.pageCount > 0
}
}
}
diff --git a/examples/pdf/multipage/viewer.qrc b/examples/pdf/multipage/viewer.qrc
index ffca51679..541ff3016 100644
--- a/examples/pdf/multipage/viewer.qrc
+++ b/examples/pdf/multipage/viewer.qrc
@@ -11,6 +11,8 @@
<file>resources/go-up-search.svg</file>
<file>resources/rotate-left.svg</file>
<file>resources/rotate-right.svg</file>
+ <file>resources/sidebar-collapse-left.svg</file>
+ <file>resources/sidebar-expand-left.svg</file>
<file>resources/test.pdf</file>
<file>resources/zoom-in.svg</file>
<file>resources/zoom-fit-best.svg</file>
diff --git a/examples/pdf/pdfviewer/main.cpp b/examples/pdf/pdfviewer/main.cpp
index b9f1e22de..bed0e5860 100644
--- a/examples/pdf/pdfviewer/main.cpp
+++ b/examples/pdf/pdfviewer/main.cpp
@@ -1,56 +1,13 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-#include <QGuiApplication>
#include <QQmlApplicationEngine>
+#include <QGuiApplication>
+
+#include <QCommandLineParser>
+#include <QCommandLineOption>
+
int main(int argc, char* argv[])
{
QCoreApplication::setApplicationName("Qt Quick PDF Viewer Example");
@@ -58,14 +15,23 @@ int main(int argc, char* argv[])
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QGuiApplication app(argc, argv);
+ QCommandLineParser parser;
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.addPositionalArgument("file", "The file to open.");
+ parser.process(app);
+
QQmlApplicationEngine engine;
+
+ QUrl toLoad = QUrl("qrc:/pdfviewer/resources/test.pdf");
+ if (!parser.positionalArguments().isEmpty())
+ toLoad = QUrl::fromLocalFile(parser.positionalArguments().constFirst());
+
+ engine.setInitialProperties({{"source", toLoad}});
+
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);
- } else {
- engine.rootObjects().first()->setProperty("source", QStringLiteral("resources/test.pdf"));
- }
+ if (engine.rootObjects().isEmpty())
+ return -1;
return app.exec();
}
diff --git a/examples/pdf/pdfviewer/resources/test.pdf b/examples/pdf/pdfviewer/resources/test.pdf
index a9dc1bc29..0832dfbed 100644
--- a/examples/pdf/pdfviewer/resources/test.pdf
+++ b/examples/pdf/pdfviewer/resources/test.pdf
Binary files differ
diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml
index ef52b0b99..a62035166 100644
--- a/examples/pdf/pdfviewer/viewer.qml
+++ b/examples/pdf/pdfviewer/viewer.qml
@@ -1,61 +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 QtQml // workaround for QTBUG-82873
+// 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 QtQuick.Shapes
-import QtQuick.Window
-import Qt.labs.animation
ApplicationWindow {
id: root
@@ -64,7 +13,7 @@ ApplicationWindow {
color: "lightgrey"
title: document.title
visible: true
- property string source // for main.cpp
+ required property url source // for main.cpp
property real scaleStep: Math.sqrt(2)
header: ToolBar {
@@ -197,15 +146,36 @@ ApplicationWindow {
}
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: document.password = passwordField.text
+ }
+
+ Dialog {
id: errorDialog
title: "Error loading " + document.source
- standardButtons: Dialog.Ok
+ standardButtons: Dialog.Close
modal: true
closePolicy: Popup.CloseOnEscape
anchors.centerIn: parent
width: 300
+ visible: document.status === PdfDocument.Error
- Label {
+ contentItem: Label {
id: errorField
text: document.error
}
@@ -218,7 +188,7 @@ ApplicationWindow {
document: PdfDocument {
id: document
source: Qt.resolvedUrl(root.source)
- onStatusChanged: if (status === PdfDocument.Error) errorDialog.open()
+ onPasswordRequired: passwordDialog.open()
}
searchString: searchField.text
}
@@ -237,17 +207,23 @@ ApplicationWindow {
anchors.fill: parent
anchors.margins: 2
model: view.searchModel
+ currentIndex: view.searchModel.currentResult
ScrollBar.vertical: ScrollBar { }
delegate: ItemDelegate {
+ id: resultDelegate
+ required property int index
+ required property int page
+ required property string contextBefore
+ required property string contextAfter
width: parent ? parent.width : 0
RowLayout {
anchors.fill: parent
spacing: 0
Label {
- text: "Page " + (page + 1) + ": "
+ text: "Page " + (resultDelegate.page + 1) + ": "
}
Label {
- text: contextBefore
+ text: resultDelegate.contextBefore
elide: Text.ElideLeft
horizontalAlignment: Text.AlignRight
Layout.fillWidth: true
@@ -259,18 +235,14 @@ ApplicationWindow {
width: implicitWidth
}
Label {
- text: contextAfter
+ text: resultDelegate.contextAfter
elide: Text.ElideRight
Layout.fillWidth: true
Layout.preferredWidth: parent.width / 2
}
}
highlighted: ListView.isCurrentItem
- onClicked: {
- searchResultsList.currentIndex = index
- view.goToLocation(page, location, 0)
- view.searchModel.currentResult = indexOnPage
- }
+ onClicked: view.searchModel.currentResult = resultDelegate.index
}
}
}