diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index d20ad4a5b71fee95cccd3a20b7a21e67cf3cee6c..77c06f80fd9c22a0ea8056626334cf7dc628df23 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 f64238eec82cf2a536aed4c4a78a32af1cc46115..28436b90d4bd0e57cbc07f88c6f3631c485be91d 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