summaryrefslogtreecommitdiffstats
path: root/src/pdfquick/PdfScrollablePageView.qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdfquick/PdfScrollablePageView.qml')
-rw-r--r--src/pdfquick/PdfScrollablePageView.qml187
1 files changed, 61 insertions, 126 deletions
diff --git a/src/pdfquick/PdfScrollablePageView.qml b/src/pdfquick/PdfScrollablePageView.qml
index 6b03c1c1c..9fa0547c6 100644
--- a/src/pdfquick/PdfScrollablePageView.qml
+++ b/src/pdfquick/PdfScrollablePageView.qml
@@ -1,41 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtPDF module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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 Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+pragma ComponentBehavior: Bound
+
import QtQuick
import QtQuick.Controls
import QtQuick.Pdf
@@ -75,8 +42,6 @@ Flickable {
This property holds the \l {QtQuick::Image::status}{rendering status} of
the \l {currentPage}{current page}.
-
- \sa PdfPageImage::status
*/
property alias status: image.status
@@ -126,9 +91,9 @@ Flickable {
\c onCurrentPageChanged script) to update the part of the user interface
that shows the current page number, such as a \l SpinBox.
- \sa PdfNavigationStack::currentPage
+ \sa PdfPageNavigator::currentPage
*/
- property alias currentPage: navigationStack.currentPage
+ property alias currentPage: pageNavigator.currentPage
/*!
\qmlproperty bool PdfScrollablePageView::backEnabled
@@ -137,9 +102,9 @@ Flickable {
This property indicates if it is possible to go back in the navigation
history to a previous-viewed page.
- \sa PdfNavigationStack::backAvailable, back()
+ \sa PdfPageNavigator::backAvailable, back()
*/
- property alias backEnabled: navigationStack.backAvailable
+ property alias backEnabled: pageNavigator.backAvailable
/*!
\qmlproperty bool PdfScrollablePageView::forwardEnabled
@@ -148,9 +113,9 @@ Flickable {
This property indicates if it is possible to go to next location in the
navigation history.
- \sa PdfNavigationStack::forwardAvailable, forward()
+ \sa PdfPageNavigator::forwardAvailable, forward()
*/
- property alias forwardEnabled: navigationStack.forwardAvailable
+ property alias forwardEnabled: pageNavigator.forwardAvailable
/*!
\qmlmethod void PdfScrollablePageView::back()
@@ -159,9 +124,9 @@ Flickable {
recently; or does nothing if there is no previous location on the
navigation stack.
- \sa PdfNavigationStack::back(), currentPage, backEnabled
+ \sa PdfPageNavigator::back(), currentPage, backEnabled
*/
- function back() { navigationStack.back() }
+ function back() { pageNavigator.back() }
/*!
\qmlmethod void PdfScrollablePageView::forward()
@@ -170,19 +135,19 @@ Flickable {
method was called; or does nothing if there is no "next" location on the
navigation stack.
- \sa PdfNavigationStack::forward(), currentPage
+ \sa PdfPageNavigator::forward(), currentPage
*/
- function forward() { navigationStack.forward() }
+ function forward() { pageNavigator.forward() }
/*!
\qmlmethod void PdfScrollablePageView::goToPage(int page)
Changes the view to the \a page, if possible.
- \sa PdfNavigationStack::jump(), currentPage
+ \sa PdfPageNavigator::jump(), currentPage
*/
function goToPage(page) {
- if (page === navigationStack.currentPage)
+ if (page === pageNavigator.currentPage)
return
goToLocation(page, Qt.point(0, 0), 0)
}
@@ -193,12 +158,12 @@ Flickable {
Scrolls the view to the \a location on the \a page, if possible,
and sets the \a zoom level.
- \sa PdfNavigationStack::jump(), currentPage
+ \sa PdfPageNavigator::jump(), currentPage
*/
function goToLocation(page, location, zoom) {
if (zoom > 0)
root.renderScale = zoom
- navigationStack.jump(page, location, zoom)
+ pageNavigator.jump(page, location, zoom)
}
// --------------------------------
@@ -209,8 +174,6 @@ Flickable {
This property holds the ratio of pixels to points. The default is \c 1,
meaning one point (1/72 of an inch) equals 1 logical pixel.
-
- \sa PdfPageImage::status
*/
property real renderScale: 1
@@ -221,8 +184,6 @@ Flickable {
The default value is \c 0 degrees (that is, no rotation relative to the
orientation of the pages as stored in the PDF file).
-
- \sa PdfPageImage::rotation
*/
property real pageRotation: 0
@@ -231,7 +192,7 @@ Flickable {
This property holds the scaled width and height of the full-frame image.
- \sa PdfPageImage::sourceSize
+ \sa {QtQuick::Image::sourceSize}{Image.sourceSize}
*/
property alias sourceSize: image.sourceSize
@@ -254,7 +215,7 @@ Flickable {
degrees, it will be scaled so that its width fits \a height.
*/
function scaleToWidth(width, height) {
- const pagePointSize = document.pagePointSize(navigationStack.currentPage)
+ const pagePointSize = document.pagePointSize(pageNavigator.currentPage)
root.renderScale = root.width / (paper.rot90 ? pagePointSize.height : pagePointSize.width)
console.log(lcSPV, "scaling", pagePointSize, "to fit", root.width, "rotated?", paper.rot90, "scale", root.renderScale)
root.contentX = 0
@@ -270,7 +231,7 @@ Flickable {
it is first rotated to have a matching aspect ratio.
*/
function scaleToPage(width, height) {
- const pagePointSize = document.pagePointSize(navigationStack.currentPage)
+ const pagePointSize = document.pagePointSize(pageNavigator.currentPage)
root.renderScale = Math.min(
root.width / (paper.rot90 ? pagePointSize.height : pagePointSize.width),
root.height / (paper.rot90 ? pagePointSize.width : pagePointSize.height) )
@@ -295,8 +256,8 @@ Flickable {
\qmlproperty string PdfScrollablePageView::searchString
This property holds the search string that the user may choose to search
- for. It is typically used in a binding to the
- \l {QtQuick.Controls::TextField::text}{text} property of a TextField.
+ for. It is typically used in a binding to the \c text property of a
+ TextField.
\sa searchModel
*/
@@ -331,7 +292,7 @@ Flickable {
if (!active ) {
const currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale,
(root.contentY + root.height / 2) / root.renderScale)
- navigationStack.update(navigationStack.currentPage, currentLocation, root.renderScale)
+ pageNavigator.update(pageNavigator.currentPage, currentLocation, root.renderScale)
}
}
ScrollBar.horizontal: ScrollBar {
@@ -339,47 +300,42 @@ Flickable {
if (!active ) {
const currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale,
(root.contentY + root.height / 2) / root.renderScale)
- navigationStack.update(navigationStack.currentPage, currentLocation, root.renderScale)
+ pageNavigator.update(pageNavigator.currentPage, currentLocation, root.renderScale)
}
}
onRenderScaleChanged: {
- image.sourceSize.width = document.pagePointSize(navigationStack.currentPage).width *
- renderScale * Screen.devicePixelRatio
- image.sourceSize.height = 0
paper.scale = 1
const currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale,
(root.contentY + root.height / 2) / root.renderScale)
- navigationStack.update(navigationStack.currentPage, currentLocation, root.renderScale)
+ pageNavigator.update(pageNavigator.currentPage, currentLocation, root.renderScale)
}
PdfSearchModel {
id: searchModel
document: root.document === undefined ? null : root.document
- // TODO maybe avoid jumping if the result is already fully visible in the viewport
- onCurrentResultBoundingRectChanged: root.goToLocation(currentPage,
- Qt.point(currentResultBoundingRect.x, currentResultBoundingRect.y), 0)
+ onCurrentResultChanged: pageNavigator.jump(currentResultLink)
}
- PdfNavigationStack {
- id: navigationStack
- onJumped: function(page, location, zoom) {
- root.renderScale = zoom
- const dx = Math.max(0, location.x * root.renderScale - root.width / 2) - root.contentX
- const dy = Math.max(0, location.y * root.renderScale - root.height / 2) - root.contentY
+ PdfPageNavigator {
+ id: pageNavigator
+ onJumped: function(current) {
+ root.renderScale = current.zoom
+ const dx = Math.max(0, current.location.x * root.renderScale - root.width / 2) - root.contentX
+ const dy = Math.max(0, current.location.y * root.renderScale - root.height / 2) - root.contentY
// don't jump if location is in the viewport already, i.e. if the "error" between desired and actual contentX/Y is small
if (Math.abs(dx) > root.width / 3)
root.contentX += dx
if (Math.abs(dy) > root.height / 3)
root.contentY += dy
- console.log(lcSPV, "going to zoom", zoom, "loc", location,
- "on page", page, "ended up @", root.contentX + ", " + root.contentY)
+ console.log(lcSPV, "going to zoom", current.zoom, "loc", current.location,
+ "on page", current.page, "ended up @", root.contentX + ", " + root.contentY)
}
onCurrentPageChanged: searchModel.currentPage = currentPage
property url documentSource: root.document.source
onDocumentSourceChanged: {
- navigationStack.clear()
+ pageNavigator.clear()
root.resetScale()
root.contentX = 0
root.contentY = 0
@@ -397,16 +353,22 @@ Flickable {
height: rot90 ? image.width : image.height
property real rotationModulus: Math.abs(root.pageRotation % 180)
property bool rot90: rotationModulus > 45 && rotationModulus < 135
+ property real minScale: 0.1
+ property real maxScale: 10
PdfPageImage {
id: image
document: root.document
- currentPage: navigationStack.currentPage
+ currentFrame: pageNavigator.currentPage
asynchronous: true
fillMode: Image.PreserveAspectFit
rotation: root.pageRotation
anchors.centerIn: parent
- property real pageScale: image.paintedWidth / document.pagePointSize(navigationStack.currentPage).width
+ property real pageScale: image.paintedWidth / document.pagePointSize(pageNavigator.currentPage).width
+ width: document.pagePointSize(pageNavigator.currentPage).width * root.renderScale
+ height: document.pagePointSize(pageNavigator.currentPage).height * root.renderScale
+ sourceSize.width: width * Screen.devicePixelRatio
+ sourceSize.height: 0
Shape {
anchors.fill: parent
@@ -441,47 +403,21 @@ Flickable {
model: PdfLinkModel {
id: linkModel
document: root.document
- page: navigationStack.currentPage
+ page: pageNavigator.currentPage
}
- delegate: Shape {
- required property rect rect
- required property url url
- required property int page
- required property point location
- required property real zoom
- x: rect.x * image.pageScale
- y: rect.y * image.pageScale
- width: rect.width * image.pageScale
- height: rect.height * image.pageScale
+ delegate: PdfLinkDelegate {
+ x: rectangle.x * image.pageScale
+ y: rectangle.y * image.pageScale
+ width: rectangle.width * image.pageScale
+ height: rectangle.height * image.pageScale
visible: image.status === Image.Ready
- ShapePath {
- strokeWidth: style.linkUnderscoreStrokeWidth
- strokeColor: style.linkUnderscoreColor
- strokeStyle: style.linkUnderscoreStrokeStyle
- dashPattern: style.linkUnderscoreDashPattern
- startX: 0; startY: height
- PathLine { x: width; y: height }
- }
- HoverHandler {
- id: linkHH
- cursorShape: Qt.PointingHandCursor
- }
- TapHandler {
- onTapped: {
- if (page >= 0)
- navigationStack.jump(page, Qt.point(0, 0), root.renderScale)
+ onTapped:
+ (link) => {
+ if (link.page >= 0)
+ pageNavigator.jump(link.page, link.location, link.zoom)
else
Qt.openUrlExternally(url)
}
- }
- ToolTip {
- visible: linkHH.hovered
- delay: 1000
- text: page >= 0 ?
- ("page " + (page + 1) +
- " location " + location.x.toFixed(1) + ", " + location.y.toFixed(1) +
- " zoom " + zoom) : url
- }
}
}
DragHandler {
@@ -507,21 +443,20 @@ Flickable {
id: selection
anchors.fill: parent
document: root.document
- page: navigationStack.currentPage
+ page: pageNavigator.currentPage
renderScale: image.pageScale == 0 ? 1.0 : image.pageScale
- fromPoint: textSelectionDrag.centroid.pressPosition
- toPoint: textSelectionDrag.centroid.position
+ from: textSelectionDrag.centroid.pressPosition
+ to: textSelectionDrag.centroid.position
hold: !textSelectionDrag.active && !mouseClickHandler.pressed
focus: true
}
PinchHandler {
id: pinch
- minimumScale: 0.1
- maximumScale: root.renderScale < 4 ? 2 : 1
+ minimumScale: paper.minScale / root.renderScale
+ maximumScale: Math.max(1, paper.maxScale / root.renderScale)
minimumRotation: 0
maximumRotation: 0
- enabled: image.sourceSize.width < 5000
onActiveChanged:
if (!active) {
const centroidInPoints = Qt.point(pinch.centroid.position.x / root.renderScale,
@@ -539,7 +474,7 @@ Flickable {
paper.y = 0
root.contentX = centroidOnPage.x - centroidInFlickable.x
root.contentY = centroidOnPage.y - centroidInFlickable.y
- root.renderScale *= ratio // onRenderScaleChanged calls navigationStack.update() so we don't need to here
+ root.renderScale *= ratio // onRenderScaleChanged calls pageNavigator.update() so we don't need to here
console.log(lcSPV, "contentX/Y adjusted to", root.contentX.toFixed(2), root.contentY.toFixed(2))
} else {
paper.x = 0