From dbf1be9c98337701b18dae66892f645c51b8bd22 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge <shawn.rutledge@qt.io> Date: Mon, 24 Feb 2020 21:19:14 +0100 Subject: [PATCH] PdfMultiPageView: retain position after pinch zoom If you do the pinch on a trackpad, the mouse cursor doesn't move, and the same visible part of the page will remain under the cursor after the page is re-rendered. Likewise when doing the pinch on a touchscreen, the centroid (midpoint between the two fingers) is held in place, subject to the constraints that Flickable.returnToBounds() imposes. Similar to 29cb44ee471908ac7c4cac70e3defb8bd72a80cd. Also corrected the horizontal scrolling range according to rotation; added left and right margins so that the page edges are more visible when the page is wider than the view, and thus the horizontal scrolling range feels more accurate while the scrollbars are still shown. Change-Id: Ia2a15eee5bcd5c9e7f025634f02a5a546e6aab68 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> --- src/pdf/quick/qml/PdfMultiPageView.qml | 43 +++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/pdf/quick/qml/PdfMultiPageView.qml b/src/pdf/quick/qml/PdfMultiPageView.qml index e8eccaf3b..cb4419b4d 100644 --- a/src/pdf/quick/qml/PdfMultiPageView.qml +++ b/src/pdf/quick/qml/PdfMultiPageView.qml @@ -121,13 +121,14 @@ Item { TableView { id: tableView anchors.fill: parent + anchors.leftMargin: 2 model: root.document === undefined ? 0 : root.document.pageCount rowSpacing: 6 - property real rotationModulus: Math.abs(root.pageRotation % 180) - property bool rot90: rotationModulus > 45 && rotationModulus < 135 + property real rotationNorm: Math.round((360 + (root.pageRotation % 360)) % 360) + property bool rot90: rotationNorm == 90 || rotationNorm == 270 onRot90Changed: forceLayout() property size firstPagePointSize: document === undefined ? Qt.size(0, 0) : document.pagePointSize(0) - contentWidth: document === undefined ? 0 : document.maxPageWidth * root.renderScale + contentWidth: document === undefined ? 0 : (rot90 ? document.maxPageHeight : document.maxPageWidth) * root.renderScale + vscroll.width + 2 // workaround for missing function (see https://codereview.qt-project.org/c/qt/qtdeclarative/+/248464) function itemAtPos(x, y, includeSpacing) { // we don't care about x (assume col 0), and assume includeSpacing is true @@ -139,7 +140,7 @@ Item { if (child.y < y && (!ret || child.y > ret.y)) ret = child } - if (root.debug) + if (root.debug && ret !== null) console.log("given y", y, "found", ret, "@", ret.y) return ret // the delegate with the largest y that is less than the given y } @@ -164,7 +165,7 @@ Item { width: image.width height: image.height rotation: root.pageRotation - anchors.centerIn: parent + anchors.centerIn: pinch.active ? undefined : parent property size pagePointSize: document.pagePointSize(index) property real pageScale: image.paintedWidth / pagePointSize.width Image { @@ -223,19 +224,46 @@ Item { id: pinch minimumScale: 0.1 maximumScale: root.renderScale < 4 ? 2 : 1 - minimumRotation: 0 - maximumRotation: 0 + minimumRotation: root.pageRotation + maximumRotation: root.pageRotation enabled: image.sourceSize.width < 5000 onActiveChanged: if (active) { paper.z = 10 } else { paper.z = 0 + var centroidInPoints = Qt.point(pinch.centroid.position.x / root.renderScale, + pinch.centroid.position.y / root.renderScale) + var centroidInFlickable = tableView.mapFromItem(paper, pinch.centroid.position.x, pinch.centroid.position.y) var newSourceWidth = image.sourceSize.width * paper.scale var ratio = newSourceWidth / image.sourceSize.width + if (root.debug) + console.log("pinch ended on page", index, "with centroid", pinch.centroid.position, centroidInPoints, "wrt flickable", centroidInFlickable, + "page at", pageHolder.x.toFixed(2), pageHolder.y.toFixed(2), + "contentX/Y were", tableView.contentX.toFixed(2), tableView.contentY.toFixed(2)) if (ratio > 1.1 || ratio < 0.9) { + var centroidOnPage = Qt.point(centroidInPoints.x * root.renderScale * ratio, centroidInPoints.y * root.renderScale * ratio) paper.scale = 1 + paper.x = 0 + paper.y = 0 root.renderScale *= ratio + tableView.forceLayout() + if (tableView.rotationNorm == 0) { + tableView.contentX = pageHolder.x + tableView.originX + centroidOnPage.x - centroidInFlickable.x + tableView.contentY = pageHolder.y + tableView.originY + centroidOnPage.y - centroidInFlickable.y + } else if (tableView.rotationNorm == 90) { + tableView.contentX = pageHolder.x + tableView.originX + image.height - centroidOnPage.y - centroidInFlickable.x + tableView.contentY = pageHolder.y + tableView.originY + centroidOnPage.x - centroidInFlickable.y + } else if (tableView.rotationNorm == 180) { + tableView.contentX = pageHolder.x + tableView.originX + image.width - centroidOnPage.x - centroidInFlickable.x + tableView.contentY = pageHolder.y + tableView.originY + image.height - centroidOnPage.y - centroidInFlickable.y + } else if (tableView.rotationNorm == 270) { + tableView.contentX = pageHolder.x + tableView.originX + centroidOnPage.y - centroidInFlickable.x + tableView.contentY = pageHolder.y + tableView.originY + image.width - centroidOnPage.x - centroidInFlickable.y + } + if (root.debug) + console.log("contentX/Y adjusted to", tableView.contentX.toFixed(2), tableView.contentY.toFixed(2), "y @top", pageHolder.y) + tableView.returnToBounds() } } grabPermissions: PointerHandler.CanTakeOverFromAnything @@ -298,6 +326,7 @@ Item { } } ScrollBar.vertical: ScrollBar { + id: vscroll property bool moved: false onPositionChanged: moved = true onActiveChanged: { -- GitLab