diff options
Diffstat (limited to 'src/pdf/quick/qml/PdfPageView.qml')
-rw-r--r-- | src/pdf/quick/qml/PdfPageView.qml | 212 |
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 + } } |