summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2020-02-03 18:11:16 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2020-02-04 17:27:18 +0000
commit25a371caa376c513f22d5c01e425a18629657fdc (patch)
tree4b50ee8135c7d92621685739a433348a8b6a6409
parent130b058352077b88f8839871f88c226e3e1fa705 (diff)
Add zoom and rotation to PdfMultiPageView
Currently, scaleToWidth() and scaleToPage() choose the scale of the first page to fit the given viewport size, and as long as all pages are the same size, it works. On the other hand, the PinchHandler only affects the scale of the page on which the pinch gesture occurs. Calling resetScale(), scaleToWidth() or scaleToPage() undoes the effect of any previous pinch gesture or any other kind of scaling change. Task-number: QTBUG-77513 Change-Id: Ia3227ca9c4af263eb8505dbd6336657984c66ab0 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r--examples/pdf/multipage/viewer.qml13
-rw-r--r--src/pdf/quick/qml/PdfMultiPageView.qml95
2 files changed, 88 insertions, 20 deletions
diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml
index d20ad4a5b..77c06f80f 100644
--- a/examples/pdf/multipage/viewer.qml
+++ b/examples/pdf/multipage/viewer.qml
@@ -75,11 +75,10 @@ ApplicationWindow {
onTriggered: fileDialog.open()
}
}
- /* TODO zoom & rotation
ToolButton {
action: Action {
shortcut: StandardKey.ZoomIn
- enabled: view.sourceSize.width < 10000
+ enabled: view.renderScale < 10
icon.source: "resources/zoom-in.svg"
onTriggered: view.renderScale *= Math.sqrt(2)
}
@@ -87,7 +86,7 @@ ApplicationWindow {
ToolButton {
action: Action {
shortcut: StandardKey.ZoomOut
- enabled: view.sourceSize.width > 50
+ enabled: view.renderScale > 0.1
icon.source: "resources/zoom-out.svg"
onTriggered: view.renderScale /= Math.sqrt(2)
}
@@ -115,17 +114,16 @@ ApplicationWindow {
action: Action {
shortcut: "Ctrl+L"
icon.source: "resources/rotate-left.svg"
- onTriggered: view.rotation -= 90
+ onTriggered: view.pageRotation -= 90
}
}
ToolButton {
action: Action {
shortcut: "Ctrl+R"
icon.source: "resources/rotate-right.svg"
- onTriggered: view.rotation += 90
+ onTriggered: view.pageRotation += 90
}
}
- */
ToolButton {
action: Action {
icon.source: "resources/go-previous-view-page.svg"
@@ -269,7 +267,8 @@ ApplicationWindow {
x: 6
property size implicitPointSize: document.pagePointSize(view.currentPage)
text: "page " + (currentPageSB.value) + " of " + document.pageCount +
- " original " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1)
+ " scale " + view.renderScale.toFixed(2) +
+ " original size " + implicitPointSize.width.toFixed(1) + "x" + implicitPointSize.height.toFixed(1) + " pt"
visible: document.pageCount > 0
}
}
diff --git a/src/pdf/quick/qml/PdfMultiPageView.qml b/src/pdf/quick/qml/PdfMultiPageView.qml
index f64238eec..28436b90d 100644
--- a/src/pdf/quick/qml/PdfMultiPageView.qml
+++ b/src/pdf/quick/qml/PdfMultiPageView.qml
@@ -59,6 +59,7 @@ Item {
// TODO 5.15: required property
property var document: undefined
property real renderScale: 1
+ property real pageRotation: 0
property string searchString
property string selectedText
property alias currentPage: listView.currentIndex
@@ -72,6 +73,32 @@ Item {
function forward() { navigationStack.forward() }
signal currentPageReallyChanged(page: int)
+ function resetScale() {
+ root.renderScale = 1
+ }
+
+ function scaleToWidth(width, height) {
+ root.renderScale = width / (listView.rot90 ? listView.firstPagePointSize.height : listView.firstPagePointSize.width)
+ }
+
+ function scaleToPage(width, height) {
+ var windowAspect = width / height
+ var pageAspect = listView.firstPagePointSize.width / listView.firstPagePointSize.height
+ if (listView.rot90) {
+ if (windowAspect > pageAspect) {
+ root.renderScale = height / listView.firstPagePointSize.width
+ } else {
+ root.renderScale = width / listView.firstPagePointSize.height
+ }
+ } else {
+ if (windowAspect > pageAspect) {
+ root.renderScale = height / listView.firstPagePointSize.height
+ } else {
+ root.renderScale = width / listView.firstPagePointSize.width
+ }
+ }
+ }
+
id: root
ListView {
id: listView
@@ -80,24 +107,38 @@ Item {
spacing: 6
highlightRangeMode: ListView.ApplyRange
highlightMoveVelocity: 2000 // TODO increase velocity when setting currentIndex somehow, too
+ property real rotationModulus: Math.abs(root.pageRotation % 180)
+ property bool rot90: rotationModulus > 45 && rotationModulus < 135
+ property size firstPagePointSize: document.pagePointSize(0)
onCurrentIndexChanged: {
navigationStack.currentPage = currentIndex
root.currentPageReallyChanged(currentIndex)
}
delegate: Rectangle {
id: paper
- width: image.width
- height: image.height
+ implicitWidth: image.width
+ implicitHeight: image.height
+ rotation: root.pageRotation
property alias selection: selection
- property real __pageScale: image.paintedWidth / document.pagePointSize(index).width
+ property size pagePointSize: document.pagePointSize(index)
+ property real pageScale: image.paintedWidth / pagePointSize.width
Image {
id: image
source: document.source
currentFrame: index
asynchronous: true
fillMode: Image.PreserveAspectFit
- width: document.pagePointSize(currentFrame).width
- height: document.pagePointSize(currentFrame).height
+ width: pagePointSize.width * root.renderScale
+ height: pagePointSize.height * root.renderScale
+ property real renderScale: root.renderScale
+ property real oldRenderScale: 1
+ onRenderScaleChanged: {
+ image.sourceSize.width = pagePointSize.width * renderScale
+ image.sourceSize.height = 0
+ paper.scale = 1
+ paper.x = 0
+ paper.y = 0
+ }
}
Shape {
anchors.fill: parent
@@ -107,7 +148,7 @@ Item {
strokeWidth: 1
strokeColor: "blue"
fillColor: "cyan"
- scale: Qt.size(paper.__pageScale, paper.__pageScale)
+ scale: Qt.size(paper.pageScale, paper.pageScale)
PathMultiline {
id: searchResultBoundaries
paths: searchModel.matchGeometry
@@ -115,7 +156,7 @@ Item {
}
ShapePath {
fillColor: "orange"
- scale: Qt.size(paper.__pageScale, paper.__pageScale)
+ scale: Qt.size(paper.pageScale, paper.pageScale)
PathMultiline {
id: selectionBoundaries
paths: selection.geometry
@@ -132,11 +173,39 @@ Item {
id: selection
document: root.document
page: image.currentFrame
- fromPoint: Qt.point(textSelectionDrag.centroid.pressPosition.x / paper.__pageScale, textSelectionDrag.centroid.pressPosition.y / paper.__pageScale)
- toPoint: Qt.point(textSelectionDrag.centroid.position.x / paper.__pageScale, textSelectionDrag.centroid.position.y / paper.__pageScale)
+ fromPoint: Qt.point(textSelectionDrag.centroid.pressPosition.x / paper.pageScale, textSelectionDrag.centroid.pressPosition.y / paper.pageScale)
+ toPoint: Qt.point(textSelectionDrag.centroid.position.x / paper.pageScale, textSelectionDrag.centroid.position.y / paper.pageScale)
hold: !textSelectionDrag.active && !tapHandler.pressed
onTextChanged: root.selectedText = text
}
+ function reRenderIfNecessary() {
+ var newSourceWidth = image.sourceSize.width * paper.scale
+ var ratio = newSourceWidth / image.sourceSize.width
+ if (ratio > 1.1 || ratio < 0.9) {
+ image.sourceSize.height = 0
+ image.sourceSize.width = newSourceWidth
+ paper.scale = 1
+ }
+ }
+ PinchHandler {
+ id: pinch
+ minimumScale: 0.1
+ maximumScale: 10
+ minimumRotation: 0
+ maximumRotation: 0
+ onActiveChanged:
+ if (active) {
+ paper.z = 10
+ } else {
+ paper.x = 0
+ paper.y = 0
+ paper.z = 0
+ image.width = undefined
+ image.height = undefined
+ paper.reRenderIfNecessary()
+ }
+ grabPermissions: PointerHandler.CanTakeOverFromAnything
+ }
DragHandler {
id: textSelectionDrag
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
@@ -155,10 +224,10 @@ Item {
delegate: Rectangle {
color: "transparent"
border.color: "lightgrey"
- x: rect.x * paper.__pageScale
- y: rect.y * paper.__pageScale
- width: rect.width * paper.__pageScale
- height: rect.height * paper.__pageScale
+ x: rect.x * paper.pageScale
+ y: rect.y * paper.pageScale
+ width: rect.width * paper.pageScale
+ height: rect.height * paper.pageScale
MouseArea { // TODO switch to TapHandler / HoverHandler in 5.15
anchors.fill: parent
cursorShape: Qt.PointingHandCursor