summaryrefslogtreecommitdiffstats
path: root/src/pdf/quick/qml/PdfPageView.qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdf/quick/qml/PdfPageView.qml')
-rw-r--r--src/pdf/quick/qml/PdfPageView.qml212
1 files changed, 183 insertions, 29 deletions
diff --git a/src/pdf/quick/qml/PdfPageView.qml b/src/pdf/quick/qml/PdfPageView.qml
index b7f75f4c2..dfd00a1a8 100644
--- a/src/pdf/quick/qml/PdfPageView.qml
+++ b/src/pdf/quick/qml/PdfPageView.qml
@@ -33,53 +33,147 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-import QtQuick 2.15
-import QtQuick.Controls 2.15
+import QtQuick 2.14
+import QtQuick.Controls 2.14
import QtQuick.Pdf 5.15
-import QtQuick.Shapes 1.15
+import QtQuick.Shapes 1.14
+import Qt.labs.animation 1.0
Rectangle {
- id: paper
- width: image.width
- height: image.height
-
// public API
// TODO 5.15: required property
- property var document: null
+ property var document: undefined
+ property alias status: image.status
+
+ property alias selectedText: selection.text
+ function copySelectionToClipboard() {
+ selection.copyToClipboard()
+ }
+
+ // page navigation
+ property alias currentPage: navigationStack.currentPage
+ property alias backEnabled: navigationStack.backAvailable
+ property alias forwardEnabled: navigationStack.forwardAvailable
+ function back() { navigationStack.back() }
+ function forward() { navigationStack.forward() }
+ function goToPage(page) { goToLocation(page, Qt.point(0, 0), 0) }
+ function goToLocation(page, location, zoom) {
+ if (zoom > 0)
+ root.renderScale = zoom
+ navigationStack.push(page, location, zoom)
+ }
+
+ // page scaling
property real renderScale: 1
property alias sourceSize: image.sourceSize
- property alias currentPage: image.currentFrame
- property alias pageCount: image.frameCount
+ function resetScale() {
+ image.sourceSize.width = 0
+ image.sourceSize.height = 0
+ root.x = 0
+ root.y = 0
+ root.scale = 1
+ }
+ function scaleToWidth(width, height) {
+ var halfRotation = Math.abs(root.rotation % 180)
+ image.sourceSize = Qt.size((halfRotation > 45 && halfRotation < 135) ? height : width, 0)
+ root.x = 0
+ root.y = 0
+ image.centerInSize = Qt.size(width, height)
+ image.centerOnLoad = true
+ image.vCenterOnLoad = (halfRotation > 45 && halfRotation < 135)
+ root.scale = 1
+ }
+ function scaleToPage(width, height) {
+ var windowAspect = width / height
+ var halfRotation = Math.abs(root.rotation % 180)
+ var pagePointSize = document.pagePointSize(navigationStack.currentPage)
+ if (halfRotation > 45 && halfRotation < 135) {
+ // rotated 90 or 270ยบ
+ var pageAspect = pagePointSize.height / pagePointSize.width
+ if (windowAspect > pageAspect) {
+ image.sourceSize = Qt.size(height, 0)
+ } else {
+ image.sourceSize = Qt.size(0, width)
+ }
+ } else {
+ var pageAspect = pagePointSize.width / pagePointSize.height
+ if (windowAspect > pageAspect) {
+ image.sourceSize = Qt.size(0, height)
+ } else {
+ image.sourceSize = Qt.size(width, 0)
+ }
+ }
+ image.centerInSize = Qt.size(width, height)
+ image.centerOnLoad = true
+ image.vCenterOnLoad = true
+ root.scale = 1
+ }
+
+ // text search
+ property alias searchModel: searchModel
property alias searchString: searchModel.searchString
- property alias status: image.status
+ function searchBack() { --searchModel.currentResult }
+ function searchForward() { ++searchModel.currentResult }
+
+ // implementation
+ id: root
+ width: image.width
+ height: image.height
- property real __pageScale: image.paintedWidth / document.pagePointSize(image.currentFrame).width
+ PdfSelection {
+ id: selection
+ document: root.document
+ page: navigationStack.currentPage
+ fromPoint: Qt.point(textSelectionDrag.centroid.pressPosition.x / image.pageScale, textSelectionDrag.centroid.pressPosition.y / image.pageScale)
+ toPoint: Qt.point(textSelectionDrag.centroid.position.x / image.pageScale, textSelectionDrag.centroid.position.y / image.pageScale)
+ hold: !textSelectionDrag.active && !tapHandler.pressed
+ }
PdfSearchModel {
id: searchModel
- document: paper.document
- page: image.currentFrame
+ document: root.document === undefined ? null : root.document
+ onCurrentPageChanged: root.goToPage(currentPage)
+ }
+
+ PdfNavigationStack {
+ id: navigationStack
+ onCurrentPageChanged: searchModel.currentPage = currentPage
+ // TODO onCurrentLocationChanged: position currentLocation.x and .y in middle // currentPageChanged() MUST occur first!
+ onCurrentZoomChanged: root.renderScale = currentZoom
+ // TODO deal with horizontal location (need WheelHandler or Flickable probably)
}
Image {
id: image
+ currentFrame: navigationStack.currentPage
source: document.status === PdfDocument.Ready ? document.source : ""
asynchronous: true
fillMode: Image.PreserveAspectFit
- }
- function reRenderIfNecessary() {
- var newSourceWidth = image.sourceSize.width * paper.scale
- var ratio = newSourceWidth / image.sourceSize.width
- if (ratio > 1.1 || ratio < 0.9) {
- image.sourceSize.width = newSourceWidth
- image.sourceSize.height = 1
- paper.scale = 1
+ property bool centerOnLoad: false
+ property bool vCenterOnLoad: false
+ property size centerInSize
+ property real pageScale: image.paintedWidth / document.pagePointSize(navigationStack.currentPage).width
+ function reRenderIfNecessary() {
+ var newSourceWidth = image.sourceSize.width * root.scale
+ var ratio = newSourceWidth / image.sourceSize.width
+ if (ratio > 1.1 || ratio < 0.9) {
+ image.sourceSize.width = newSourceWidth
+ image.sourceSize.height = 0
+ root.scale = 1
+ }
}
+ onStatusChanged:
+ if (status == Image.Ready && centerOnLoad) {
+ root.x = (centerInSize.width - image.implicitWidth) / 2
+ root.y = vCenterOnLoad ? (centerInSize.height - image.implicitHeight) / 2 : 0
+ centerOnLoad = false
+ vCenterOnLoad = false
+ }
}
onRenderScaleChanged: {
- image.sourceSize.width = document.pagePointSize(image.currentFrame).width * renderScale
+ image.sourceSize.width = document.pagePointSize(navigationStack.currentPage).width * renderScale
image.sourceSize.height = 0
- paper.scale = 1
+ root.scale = 1
}
Shape {
@@ -88,22 +182,64 @@ Rectangle {
visible: image.status === Image.Ready
ShapePath {
strokeWidth: 1
- strokeColor: "blue"
+ strokeColor: "cyan"
+ fillColor: "steelblue"
+ scale: Qt.size(image.pageScale, image.pageScale)
+ PathMultiline {
+ paths: searchModel.currentPageBoundingPolygons
+ }
+ }
+ ShapePath {
+ strokeWidth: 1
+ strokeColor: "orange"
fillColor: "cyan"
- scale: Qt.size(paper.__pageScale, paper.__pageScale)
+ scale: Qt.size(image.pageScale, image.pageScale)
+ PathMultiline {
+ paths: searchModel.currentResultBoundingPolygons
+ }
+ }
+ ShapePath {
+ fillColor: "orange"
+ scale: Qt.size(image.pageScale, image.pageScale)
PathMultiline {
- id: searchResultBoundaries
- paths: searchModel.matchGeometry
+ paths: selection.geometry
+ }
+ }
+ }
+
+ Repeater {
+ model: PdfLinkModel {
+ id: linkModel
+ document: root.document
+ page: navigationStack.currentPage
+ }
+ delegate: Rectangle {
+ color: "transparent"
+ border.color: "lightgrey"
+ x: rect.x * image.pageScale
+ y: rect.y * image.pageScale
+ width: rect.width * image.pageScale
+ height: rect.height * image.pageScale
+ MouseArea { // TODO switch to TapHandler / HoverHandler in 5.15
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ onClicked: {
+ if (page >= 0)
+ navigationStack.push(page, Qt.point(0, 0), root.renderScale)
+ else
+ Qt.openUrlExternally(url)
+ }
}
}
}
+
PinchHandler {
id: pinch
minimumScale: 0.1
maximumScale: 10
minimumRotation: 0
maximumRotation: 0
- onActiveChanged: if (!active) paper.reRenderIfNecessary()
+ onActiveChanged: if (!active) image.reRenderIfNecessary()
grabPermissions: PinchHandler.TakeOverForbidden // don't allow takeover if pinch has started
}
DragHandler {
@@ -116,4 +252,22 @@ Rectangle {
acceptedButtons: Qt.MiddleButton
snapMode: DragHandler.NoSnap
}
+ DragHandler {
+ id: textSelectionDrag
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
+ target: null
+ }
+ TapHandler {
+ id: tapHandler
+ acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
+ }
+ // prevent it from being scrolled out of view
+ BoundaryRule on x {
+ minimum: 100 - root.width
+ maximum: root.parent.width - 100
+ }
+ BoundaryRule on y {
+ minimum: 100 - root.height
+ maximum: root.parent.height - 100
+ }
}