summaryrefslogtreecommitdiffstats
path: root/src/pdf/quick/qml/PdfMultiPageView.qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdf/quick/qml/PdfMultiPageView.qml')
-rw-r--r--src/pdf/quick/qml/PdfMultiPageView.qml171
1 files changed, 113 insertions, 58 deletions
diff --git a/src/pdf/quick/qml/PdfMultiPageView.qml b/src/pdf/quick/qml/PdfMultiPageView.qml
index 70bb5454f..71485c214 100644
--- a/src/pdf/quick/qml/PdfMultiPageView.qml
+++ b/src/pdf/quick/qml/PdfMultiPageView.qml
@@ -48,15 +48,15 @@ Item {
property string selectedText
function selectAll() {
- var currentItem = tableView.itemAtPos(0, tableView.contentY + root.height / 2)
- if (currentItem !== null)
+ var currentItem = tableHelper.itemAtCell(tableHelper.cellAtPos(root.width / 2, root.height / 2))
+ if (currentItem)
currentItem.selection.selectAll()
}
function copySelectionToClipboard() {
- var currentItem = tableView.itemAtPos(0, tableView.contentY + root.height / 2)
+ var currentItem = tableHelper.itemAtCell(tableHelper.cellAtPos(root.width / 2, root.height / 2))
if (debug)
console.log("currentItem", currentItem, "sel", currentItem.selection.text)
- if (currentItem !== null)
+ if (currentItem)
currentItem.selection.copyToClipboard()
}
@@ -69,14 +69,19 @@ Item {
function goToPage(page) {
if (page === navigationStack.currentPage)
return
- goToLocation(page, Qt.point(0, 0), 0)
+ goToLocation(page, Qt.point(-1, -1), 0)
}
function goToLocation(page, location, zoom) {
- if (zoom > 0)
+ if (zoom > 0) {
+ navigationStack.jumping = true // don't call navigationStack.update() because we will push() instead
root.renderScale = zoom
- navigationStack.push(page, location, zoom)
- searchModel.currentPage = page
+ tableView.forceLayout() // but do ensure that the table layout is correct before we try to jump
+ navigationStack.jumping = false
+ }
+ navigationStack.push(page, location, zoom) // actually jump
}
+ property vector2d jumpLocationMargin: Qt.vector2d(10, 10) // px from top-left corner
+ property int currentPageRenderingStatus: Image.Null
// page scaling
property real renderScale: 1
@@ -115,29 +120,27 @@ Item {
id: tableView
anchors.fill: parent
anchors.leftMargin: 2
- model: root.document === undefined ? 0 : root.document.pageCount
+ model: modelInUse && root.document !== undefined ? root.document.pageCount : 0
+ // workaround to make TableView do scheduleRebuildTable(RebuildOption::All) in cases when forceLayout() doesn't
+ property bool modelInUse: true
+ function rebuild() {
+ modelInUse = false
+ modelInUse = true
+ }
+ // end workaround
rowSpacing: 6
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 : (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
- var ret = null
- for (var i = 0; i < contentItem.children.length; ++i) {
- var child = contentItem.children[i];
- if (root.debug)
- console.log(child, "@y", child.y)
- if (child.y < y && (!ret || child.y > ret.y))
- ret = child
- }
- 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
- }
+ property real pageHolderWidth: Math.max(root.width, document === undefined ? 0 :
+ (rot90 ? document.maxPageHeight : document.maxPageWidth) * root.renderScale)
+ contentWidth: document === undefined ? 0 : pageHolderWidth + vscroll.width + 2
rowHeightProvider: function(row) { return (rot90 ? document.pagePointSize(row).width : document.pagePointSize(row).height) * root.renderScale }
+ TableViewExtra {
+ id: tableHelper
+ tableView: tableView
+ }
delegate: Rectangle {
id: pageHolder
color: root.debug ? "beige" : "transparent"
@@ -147,11 +150,8 @@ Item {
rotation: -90; text: pageHolder.width.toFixed(1) + "x" + pageHolder.height.toFixed(1) + "\n" +
image.width.toFixed(1) + "x" + image.height.toFixed(1)
}
- implicitWidth: Math.max(root.width, (tableView.rot90 ? document.maxPageHeight : document.maxPageWidth) * root.renderScale)
+ implicitWidth: tableView.pageHolderWidth
implicitHeight: tableView.rot90 ? image.width : image.height
- onImplicitWidthChanged: tableView.forceLayout()
- objectName: "page " + index
- property int delegateIndex: row // expose the context property for JS outside of the delegate
property alias selection: selection
Rectangle {
id: paper
@@ -177,6 +177,10 @@ Item {
paper.scale = 1
searchHighlights.update()
}
+ onStatusChanged: {
+ if (index === navigationStack.currentPage)
+ root.currentPageRenderingStatus = status
+ }
}
Shape {
anchors.fill: parent
@@ -276,9 +280,17 @@ Item {
target: null
}
TapHandler {
- id: tapHandler
+ id: mouseClickHandler
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
}
+ TapHandler {
+ id: touchTapHandler
+ acceptedDevices: PointerDevice.TouchScreen
+ onTapped: {
+ selection.clear()
+ selection.forceActiveFocus()
+ }
+ }
Repeater {
model: PdfLinkModel {
id: linkModel
@@ -290,6 +302,7 @@ Item {
y: rect.y * paper.pageScale
width: rect.width * paper.pageScale
height: rect.height * paper.pageScale
+ visible: image.status === Image.Ready
ShapePath {
strokeWidth: style.linkUnderscoreStrokeWidth
strokeColor: style.linkUnderscoreColor
@@ -320,17 +333,18 @@ Item {
}
}
}
- }
- PdfSelection {
- 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)
- hold: !textSelectionDrag.active && !tapHandler.pressed
- onTextChanged: root.selectedText = text
+ PdfSelection {
+ id: selection
+ anchors.fill: parent
+ document: root.document
+ page: image.currentFrame
+ renderScale: image.renderScale
+ fromPoint: textSelectionDrag.centroid.pressPosition
+ toPoint: textSelectionDrag.centroid.position
+ hold: !textSelectionDrag.active && !mouseClickHandler.pressed
+ onTextChanged: root.selectedText = text
+ focus: true
+ }
}
}
ScrollBar.vertical: ScrollBar {
@@ -338,42 +352,83 @@ Item {
property bool moved: false
onPositionChanged: moved = true
onActiveChanged: {
- var currentItem = tableView.itemAtPos(0, tableView.contentY + root.height / 2)
- var currentPage = currentItem.delegateIndex
- var currentLocation = Qt.point((tableView.contentX - currentItem.x + root.width / 2) / root.renderScale,
- (tableView.contentY - currentItem.y + root.height / 2) / root.renderScale)
+ var cell = tableHelper.cellAtPos(root.width / 2, root.height / 2)
+ var currentItem = tableHelper.itemAtCell(cell)
+ var currentLocation = Qt.point(0, 0)
+ if (currentItem) { // maybe the delegate wasn't loaded yet
+ currentLocation = Qt.point((tableView.contentX - currentItem.x + jumpLocationMargin.x) / root.renderScale,
+ (tableView.contentY - currentItem.y + jumpLocationMargin.y) / root.renderScale)
+ }
if (active) {
moved = false
- navigationStack.push(currentPage, currentLocation, root.renderScale)
+ // emitJumped false to avoid interrupting a pinch if TableView thinks it should scroll at the same time
+ navigationStack.push(cell.y, currentLocation, root.renderScale, false)
} else if (moved) {
- navigationStack.update(currentPage, currentLocation, root.renderScale)
+ navigationStack.update(cell.y, currentLocation, root.renderScale)
}
}
}
ScrollBar.horizontal: ScrollBar { }
}
onRenderScaleChanged: {
- tableView.forceLayout()
- var currentItem = tableView.itemAtPos(tableView.contentX + root.width / 2, tableView.contentY + root.height / 2)
- if (currentItem !== undefined)
- navigationStack.update(currentItem.delegateIndex, Qt.point(currentItem.x / renderScale, currentItem.y / renderScale), renderScale)
+ // if navigationStack.jumped changes the scale, don't turn around and update the stack again;
+ // and don't force layout either, because positionViewAtCell() will do that
+ if (navigationStack.jumping)
+ return
+ // make TableView rebuild from scratch, because otherwise it doesn't know the delegates are changing size
+ tableView.rebuild()
+ var cell = tableHelper.cellAtPos(root.width / 2, root.height / 2)
+ var currentItem = tableHelper.itemAtCell(cell)
+ if (currentItem) {
+ var currentLocation = Qt.point((tableView.contentX - currentItem.x + jumpLocationMargin.x) / root.renderScale,
+ (tableView.contentY - currentItem.y + jumpLocationMargin.y) / root.renderScale)
+ navigationStack.update(cell.y, currentLocation, renderScale)
+ }
}
PdfNavigationStack {
id: navigationStack
+ property bool jumping: false
+ property int previousPage: 0
onJumped: {
+ jumping = true
root.renderScale = zoom
- tableView.contentX = Math.max(0, location.x - root.width / 2) * root.renderScale
- tableView.contentY = tableView.originY + root.document.heightSumBeforePage(page, tableView.rowSpacing / root.renderScale) * root.renderScale
- if (root.debug) {
- console.log("going to page", page,
- "@y", root.document.heightSumBeforePage(page, tableView.rowSpacing / root.renderScale) * root.renderScale,
- "ended up @", tableView.contentY, "originY is", tableView.originY)
+ if (location.y < 0) {
+ // invalid to indicate that a specific location was not needed,
+ // so attempt to position the new page just as the current page is
+ var currentYOffset = 0
+ var previousPageDelegate = tableHelper.itemAtCell(0, previousPage)
+ if (previousPageDelegate)
+ currentYOffset = tableView.contentY - previousPageDelegate.y
+ tableHelper.positionViewAtRow(page, Qt.AlignTop, currentYOffset)
+ if (root.debug) {
+ console.log("going from page", previousPage, "to", page, "offset", currentYOffset,
+ "ended up @", tableView.contentX.toFixed(1) + ", " + tableView.contentY.toFixed(1))
+ }
+ } else {
+ // jump to a page and position the given location relative to the top-left corner of the viewport
+ var pageSize = root.document.pagePointSize(page)
+ pageSize.width *= root.renderScale
+ pageSize.height *= root.renderScale
+ var xOffsetLimit = Math.max(0, pageSize.width - root.width) / 2
+ var offset = Qt.point(Math.max(-xOffsetLimit, Math.min(xOffsetLimit,
+ location.x * root.renderScale - jumpLocationMargin.x)),
+ Math.max(0, location.y * root.renderScale - jumpLocationMargin.y))
+ tableHelper.positionViewAtCell(0, page, Qt.AlignLeft | Qt.AlignTop, offset)
+ if (root.debug) {
+ console.log("going to zoom", zoom, "loc", location, "on page", page,
+ "ended up @", tableView.contentX.toFixed(1) + ", " + tableView.contentY.toFixed(1))
+ }
}
+ jumping = false
+ previousPage = page
}
+ onCurrentPageChanged: searchModel.currentPage = currentPage
}
PdfSearchModel {
id: searchModel
document: root.document === undefined ? null : root.document
- onCurrentPageChanged: if (currentPage != navigationStack.currentPage) root.goToPage(currentPage)
+ // TODO maybe avoid jumping if the result is already fully visible in the viewport
+ onCurrentResultBoundingRectChanged: root.goToLocation(currentPage,
+ Qt.point(currentResultBoundingRect.x, currentResultBoundingRect.y), 0)
}
}