Fix tray visibility and message reception issues
Some checks failed
build / build-pip (push) Failing after 16s
build / build-win64 (push) Has been cancelled
build / build-macos (push) Has been cancelled

- Disable sound initialization to prevent hanging
- Add missing import re in utils.py
- Fix settings loading for QSettings
- Update file paths to use PROJECT_ROOT
- Revert to working API paths and listener from commit efdc63e
This commit is contained in:
kdusek
2025-12-07 22:39:07 +01:00
parent 7b695d7b7f
commit 5138303016
4060 changed files with 579123 additions and 23 deletions

View File

@@ -0,0 +1,15 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
import QtQuick
import QtQuick.Controls.Material
QtObject {
property SystemPalette palette: SystemPalette { }
function withAlpha(color, alpha) {
return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha)
}
property color selectionColor: withAlpha(palette.highlight, 0.5)
property color pageSearchResultsColor: withAlpha(Qt.lighter(Material.accentColor, 1.5), 0.5)
property color currentSearchResultStrokeColor: Material.accentColor
property real currentSearchResultStrokeWidth: 2
}

View File

@@ -0,0 +1,15 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
import QtQuick
import QtQuick.Controls.Universal
QtObject {
property SystemPalette palette: SystemPalette { }
function withAlpha(color, alpha) {
return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha)
}
property color selectionColor: withAlpha(palette.highlight, 0.5)
property color pageSearchResultsColor: withAlpha(Qt.lighter(Universal.accent, 1.5), 0.5)
property color currentSearchResultStrokeColor: Universal.accent
property real currentSearchResultStrokeWidth: 2
}

View File

@@ -0,0 +1,74 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
/*!
\qmltype PdfLinkDelegate
\inqmlmodule QtQuick.Pdf
\brief A component to decorate hyperlinks on a PDF page.
PdfLinkDelegate provides the component that QML-based PDF viewers
instantiate on top of each hyperlink that is found on each PDF page.
This component does not provide any visual decoration, because often the
hyperlinks will already be formatted in a distinctive way; but when the
mouse cursor hovers, it changes to Qt::PointingHandCursor, and a tooltip
appears after a delay. Clicking emits the goToLocation() signal if the link
is internal, or calls Qt.openUrlExternally() if the link contains a URL.
\sa PdfPageView, PdfScrollablePageView, PdfMultiPageView
*/
Item {
id: root
required property var link
required property rect rectangle
required property url url
required property int page
required property point location
required property real zoom
/*!
\qmlsignal PdfLinkDelegate::tapped(link)
Emitted on mouse click or touch tap. The \a link argument is an
instance of QPdfLink with information about the hyperlink.
*/
signal tapped(var link)
/*!
\qmlsignal PdfLinkDelegate::contextMenuRequested(link)
Emitted on mouse right-click or touch long-press. The \a link argument
is an instance of QPdfLink with information about the hyperlink.
*/
signal contextMenuRequested(var link)
HoverHandler {
id: linkHH
cursorShape: Qt.PointingHandCursor
}
TapHandler {
gesturePolicy: TapHandler.ReleaseWithinBounds
onTapped: root.tapped(root.link)
}
TapHandler {
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus
acceptedButtons: Qt.RightButton
gesturePolicy: TapHandler.ReleaseWithinBounds
onTapped: root.contextMenuRequested(root.link)
}
TapHandler {
acceptedDevices: PointerDevice.TouchScreen
onLongPressed: root.contextMenuRequested(root.link)
}
ToolTip {
visible: linkHH.hovered
delay: 1000
property string destFormat: qsTr("Page %1 location %2, %3 zoom %4")
text: root.page >= 0 ?
destFormat.arg(root.page + 1).arg(root.location.x.toFixed(1))
.arg(root.location.y.toFixed(1)).arg(root.zoom) :
root.url
}
}

View File

@@ -0,0 +1,623 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Pdf
import QtQuick.Shapes
/*!
\qmltype PdfMultiPageView
\inqmlmodule QtQuick.Pdf
\brief A complete PDF viewer component for scrolling through multiple pages.
PdfMultiPageView provides a PDF viewer component that offers a user
experience similar to many common PDF viewer applications. It supports
flicking through the pages in the entire document, with narrow gaps between
the page images.
PdfMultiPageView also supports selecting text and copying it to the
clipboard, zooming in and out, clicking an internal link to jump to another
section in the document, rotating the view, and searching for text. The
\l {PDF Multipage Viewer Example} demonstrates how to use these features
in an application.
The implementation is a QML assembly of smaller building blocks that are
available separately. In case you want to make changes in your own version
of this component, you can copy the QML, which is installed into the
\c QtQuick/Pdf/qml module directory, and modify it as needed.
\sa PdfPageView, PdfScrollablePageView, PdfStyle
*/
Item {
/*!
\qmlproperty PdfDocument PdfMultiPageView::document
A PdfDocument object with a valid \c source URL is required:
\snippet multipageview.qml 0
*/
required property PdfDocument document
/*!
\qmlproperty PdfDocument PdfMultiPageView::selectedText
The selected text.
*/
property string selectedText
/*!
\qmlmethod void PdfMultiPageView::selectAll()
Selects all the text on the \l {currentPage}{current page}, and makes it
available as the system \l {QClipboard::Selection}{selection} on systems
that support that feature.
\sa copySelectionToClipboard()
*/
function selectAll() {
const currentItem = tableView.itemAtCell(tableView.cellAtPos(root.width / 2, root.height / 2))
const pdfSelection = currentItem?.selection as PdfSelection
pdfSelection?.selectAll()
}
/*!
\qmlmethod void PdfMultiPageView::copySelectionToClipboard()
Copies the selected text (if any) to the
\l {QClipboard::Clipboard}{system clipboard}.
\sa selectAll()
*/
function copySelectionToClipboard() {
const currentItem = tableView.itemAtCell(tableView.cellAtPos(root.width / 2, root.height / 2))
const pdfSelection = currentItem?.selection as PdfSelection
console.log(lcMPV, "currentItem", currentItem, "sel", pdfSelection?.text)
pdfSelection?.copyToClipboard()
}
// --------------------------------
// page navigation
/*!
\qmlproperty int PdfMultiPageView::currentPage
\readonly
This property holds the zero-based page number of the page visible in the
scrollable view. If there is no current page, it holds -1.
This property is read-only, and is typically used in a binding (or
\c onCurrentPageChanged script) to update the part of the user interface
that shows the current page number, such as a \l SpinBox.
\sa PdfPageNavigator::currentPage
*/
property alias currentPage: pageNavigator.currentPage
/*!
\qmlproperty bool PdfMultiPageView::backEnabled
\readonly
This property indicates if it is possible to go back in the navigation
history to a previous-viewed page.
\sa PdfPageNavigator::backAvailable, back()
*/
property alias backEnabled: pageNavigator.backAvailable
/*!
\qmlproperty bool PdfMultiPageView::forwardEnabled
\readonly
This property indicates if it is possible to go to next location in the
navigation history.
\sa PdfPageNavigator::forwardAvailable, forward()
*/
property alias forwardEnabled: pageNavigator.forwardAvailable
/*!
\qmlmethod void PdfMultiPageView::back()
Scrolls the view back to the previous page that the user visited most
recently; or does nothing if there is no previous location on the
navigation stack.
\sa PdfPageNavigator::back(), currentPage, backEnabled
*/
function back() { pageNavigator.back() }
/*!
\qmlmethod void PdfMultiPageView::forward()
Scrolls the view to the page that the user was viewing when the back()
method was called; or does nothing if there is no "next" location on the
navigation stack.
\sa PdfPageNavigator::forward(), currentPage
*/
function forward() { pageNavigator.forward() }
/*!
\qmlmethod void PdfMultiPageView::goToPage(int page)
Scrolls the view to the given \a page number, if possible.
\sa PdfPageNavigator::jump(), currentPage
*/
function goToPage(page) {
if (page === pageNavigator.currentPage)
return
goToLocation(page, Qt.point(-1, -1), 0)
}
/*!
\qmlmethod void PdfMultiPageView::goToLocation(int page, point location, real zoom)
Scrolls the view to the \a location on the \a page, if possible,
and sets the \a zoom level.
\sa PdfPageNavigator::jump(), currentPage
*/
function goToLocation(page, location, zoom) {
if (tableView.rows === 0) {
// save this request for later
tableView.pendingRow = page
tableView.pendingLocation = location
tableView.pendingZoom = zoom
return
}
if (zoom > 0) {
pageNavigator.jumping = true // don't call pageNavigator.update() because we will jump() instead
root.renderScale = zoom
pageNavigator.jumping = false
}
pageNavigator.jump(page, location, zoom) // actually jump
}
/*!
\qmlproperty int PdfMultiPageView::currentPageRenderingStatus
This property holds the \l {QtQuick::Image::status}{rendering status} of
the \l {currentPage}{current page}.
*/
property int currentPageRenderingStatus: Image.Null
// --------------------------------
// page scaling
/*!
\qmlproperty real PdfMultiPageView::renderScale
This property holds the ratio of pixels to points. The default is \c 1,
meaning one point (1/72 of an inch) equals 1 logical pixel.
*/
property real renderScale: 1
/*!
\qmlproperty real PdfMultiPageView::pageRotation
This property holds the clockwise rotation of the pages.
The default value is \c 0 degrees (that is, no rotation relative to the
orientation of the pages as stored in the PDF file).
*/
property real pageRotation: 0
/*!
\qmlmethod void PdfMultiPageView::resetScale()
Sets \l renderScale back to its default value of \c 1.
*/
function resetScale() { root.renderScale = 1 }
/*!
\qmlmethod void PdfMultiPageView::scaleToWidth(real width, real height)
Sets \l renderScale such that the width of the first page will fit into a
viewport with the given \a width and \a height. If the page is not rotated,
it will be scaled so that its width fits \a width. If it is rotated +/- 90
degrees, it will be scaled so that its width fits \a height.
*/
function scaleToWidth(width, height) {
root.renderScale = width / (tableView.rot90 ? tableView.firstPagePointSize.height : tableView.firstPagePointSize.width)
}
/*!
\qmlmethod void PdfMultiPageView::scaleToPage(real width, real height)
Sets \l renderScale such that the whole first page will fit into a viewport
with the given \a width and \a height. The resulting \l renderScale depends
on \l pageRotation: the page will fit into the viewport at a larger size if
it is first rotated to have a matching aspect ratio.
*/
function scaleToPage(width, height) {
const windowAspect = width / height
const pageAspect = tableView.firstPagePointSize.width / tableView.firstPagePointSize.height
if (tableView.rot90) {
if (windowAspect > pageAspect) {
root.renderScale = height / tableView.firstPagePointSize.width
} else {
root.renderScale = width / tableView.firstPagePointSize.height
}
} else {
if (windowAspect > pageAspect) {
root.renderScale = height / tableView.firstPagePointSize.height
} else {
root.renderScale = width / tableView.firstPagePointSize.width
}
}
}
// --------------------------------
// text search
/*!
\qmlproperty PdfSearchModel PdfMultiPageView::searchModel
This property holds a PdfSearchModel containing the list of search results
for a given \l searchString.
\sa PdfSearchModel
*/
property alias searchModel: searchModel
/*!
\qmlproperty string PdfMultiPageView::searchString
This property holds the search string that the user may choose to search
for. It is typically used in a binding to the \c text property of a
TextField.
\sa searchModel
*/
property alias searchString: searchModel.searchString
/*!
\qmlmethod void PdfMultiPageView::searchBack()
Decrements the
\l{PdfSearchModel::currentResult}{searchModel's current result}
so that the view will jump to the previous search result.
*/
function searchBack() { --searchModel.currentResult }
/*!
\qmlmethod void PdfMultiPageView::searchForward()
Increments the
\l{PdfSearchModel::currentResult}{searchModel's current result}
so that the view will jump to the next search result.
*/
function searchForward() { ++searchModel.currentResult }
LoggingCategory {
id: lcMPV
name: "qt.pdf.multipageview"
}
id: root
PdfStyle { id: style }
TableView {
id: tableView
property bool debug: false
property real minScale: 0.1
property real maxScale: 10
property point jumpLocationMargin: Qt.point(10, 10) // px away from viewport edges
anchors.fill: parent
anchors.leftMargin: 2
model: root.document ? root.document.pageCount : 0
rowSpacing: 6
property real rotationNorm: Math.round((360 + (root.pageRotation % 360)) % 360)
property bool rot90: rotationNorm == 90 || rotationNorm == 270
onRot90Changed: forceLayout()
onHeightChanged: forceLayout()
onWidthChanged: forceLayout()
property size firstPagePointSize: root.document?.status === PdfDocument.Ready ? root.document.pagePointSize(0) : Qt.size(1, 1)
property real pageHolderWidth: Math.max(root.width, ((rot90 ? root.document?.maxPageHeight : root.document?.maxPageWidth) ?? 0) * root.renderScale)
columnWidthProvider: function(col) { return root.document ? pageHolderWidth + vscroll.width + 2 : 0 }
rowHeightProvider: function(row) { return (rot90 ? root.document.pagePointSize(row).width : root.document.pagePointSize(row).height) * root.renderScale }
// delayed-jump feature in case the user called goToPage() or goToLocation() too early
property int pendingRow: -1
property point pendingLocation
property real pendingZoom: -1
onRowsChanged: {
if (rows > 0 && tableView.pendingRow >= 0) {
console.log(lcMPV, "initiating delayed jump to page", tableView.pendingRow, "loc", tableView.pendingLocation, "zoom", tableView.pendingZoom)
root.goToLocation(tableView.pendingRow, tableView.pendingLocation, tableView.pendingZoom)
tableView.pendingRow = -1
tableView.pendingLocation = Qt.point(-1, -1)
tableView.pendingZoom = -1
}
}
delegate: Rectangle {
id: pageHolder
required property int index
color: tableView.debug ? "beige" : "transparent"
Text {
visible: tableView.debug
anchors { right: parent.right; verticalCenter: parent.verticalCenter }
rotation: -90; text: pageHolder.width.toFixed(1) + "x" + pageHolder.height.toFixed(1) + "\n" +
image.width.toFixed(1) + "x" + image.height.toFixed(1)
}
property alias selection: selection
Rectangle {
id: paper
width: image.width
height: image.height
rotation: root.pageRotation
anchors.centerIn: pinch.active ? undefined : parent
property size pagePointSize: root.document.pagePointSize(pageHolder.index)
property real pageScale: image.paintedWidth / pagePointSize.width
PdfPageImage {
id: image
document: root.document
currentFrame: pageHolder.index
asynchronous: true
fillMode: Image.PreserveAspectFit
width: paper.pagePointSize.width * root.renderScale
height: paper.pagePointSize.height * root.renderScale
property real renderScale: root.renderScale
property real oldRenderScale: 1
onRenderScaleChanged: {
image.sourceSize.width = paper.pagePointSize.width * renderScale * Screen.devicePixelRatio
image.sourceSize.height = 0
paper.scale = 1
searchHighlights.update()
}
onStatusChanged: {
if (pageHolder.index === pageNavigator.currentPage)
root.currentPageRenderingStatus = status
}
}
Shape {
anchors.fill: parent
visible: image.status === Image.Ready
onVisibleChanged: searchHighlights.update()
ShapePath {
strokeWidth: -1
fillColor: style.pageSearchResultsColor
scale: Qt.size(paper.pageScale, paper.pageScale)
PathMultiline {
id: searchHighlights
function update() {
// paths could be a binding, but we need to be able to "kick" it sometimes
paths = searchModel.boundingPolygonsOnPage(pageHolder.index)
}
}
}
Connections {
target: searchModel
// whenever the highlights on the _current_ page change, they actually need to change on _all_ pages
// (usually because the search string has changed)
function onCurrentPageBoundingPolygonsChanged() { searchHighlights.update() }
}
ShapePath {
strokeWidth: -1
fillColor: style.selectionColor
scale: Qt.size(paper.pageScale, paper.pageScale)
PathMultiline {
paths: selection.geometry
}
}
}
Shape {
anchors.fill: parent
visible: image.status === Image.Ready && searchModel.currentPage === pageHolder.index
ShapePath {
strokeWidth: style.currentSearchResultStrokeWidth
strokeColor: style.currentSearchResultStrokeColor
fillColor: "transparent"
scale: Qt.size(paper.pageScale, paper.pageScale)
PathMultiline {
paths: searchModel.currentResultBoundingPolygons
}
}
}
PinchHandler {
id: pinch
minimumScale: tableView.minScale / root.renderScale
maximumScale: Math.max(1, tableView.maxScale / root.renderScale)
minimumRotation: root.pageRotation
maximumRotation: root.pageRotation
onActiveChanged:
if (active) {
paper.z = 10
} else {
paper.z = 0
const centroidInPoints = Qt.point(pinch.centroid.position.x / root.renderScale,
pinch.centroid.position.y / root.renderScale)
const centroidInFlickable = tableView.mapFromItem(paper, pinch.centroid.position.x, pinch.centroid.position.y)
const newSourceWidth = image.sourceSize.width * paper.scale
const ratio = newSourceWidth / image.sourceSize.width
console.log(lcMPV, "pinch ended on page", pageHolder.index,
"with scale", paper.scale.toFixed(3), "ratio", ratio.toFixed(3),
"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) {
const centroidOnPage = Qt.point(centroidInPoints.x * root.renderScale * ratio, centroidInPoints.y * root.renderScale * ratio)
paper.scale = 1
pinch.persistentScale = 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
}
console.log(lcMPV, "contentX/Y adjusted to", tableView.contentX.toFixed(2), tableView.contentY.toFixed(2), "y @top", pageHolder.y)
tableView.returnToBounds()
}
}
grabPermissions: PointerHandler.CanTakeOverFromAnything
}
DragHandler {
id: textSelectionDrag
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
target: null
}
TapHandler {
id: mouseClickHandler
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
}
TapHandler {
id: touchTapHandler
acceptedDevices: PointerDevice.TouchScreen
onTapped: {
selection.clear()
selection.forceActiveFocus()
}
}
Repeater {
model: PdfLinkModel {
id: linkModel
document: root.document
page: image.currentFrame
}
delegate: PdfLinkDelegate {
x: rectangle.x * paper.pageScale
y: rectangle.y * paper.pageScale
width: rectangle.width * paper.pageScale
height: rectangle.height * paper.pageScale
visible: image.status === Image.Ready
onTapped:
(link) => {
if (link.page >= 0)
root.goToLocation(link.page, link.location, link.zoom)
else
Qt.openUrlExternally(url)
}
}
}
PdfSelection {
id: selection
anchors.fill: parent
document: root.document
page: image.currentFrame
renderScale: image.renderScale
from: textSelectionDrag.centroid.pressPosition
to: textSelectionDrag.centroid.position
hold: !textSelectionDrag.active && !mouseClickHandler.pressed
onTextChanged: root.selectedText = text
focus: true
}
}
}
ScrollBar.vertical: ScrollBar {
id: vscroll
property bool moved: false
onPositionChanged: moved = true
onPressedChanged: if (pressed) {
// When the user starts scrolling, push the location where we came from so the user can go "back" there
const cell = tableView.cellAtPos(root.width / 2, root.height / 2)
const currentItem = tableView.itemAtCell(cell)
const currentLocation = currentItem
? Qt.point((tableView.contentX - currentItem.x + tableView.jumpLocationMargin.x) / root.renderScale,
(tableView.contentY - currentItem.y + tableView.jumpLocationMargin.y) / root.renderScale)
: Qt.point(0, 0) // maybe the delegate wasn't loaded yet
pageNavigator.jump(cell.y, currentLocation, root.renderScale)
}
onActiveChanged: if (!active ) {
// When the scrollbar stops moving, tell navstack where we are, so as to update currentPage etc.
const cell = tableView.cellAtPos(root.width / 2, root.height / 2)
const currentItem = tableView.itemAtCell(cell)
const currentLocation = currentItem
? Qt.point((tableView.contentX - currentItem.x + tableView.jumpLocationMargin.x) / root.renderScale,
(tableView.contentY - currentItem.y + tableView.jumpLocationMargin.y) / root.renderScale)
: Qt.point(0, 0) // maybe the delegate wasn't loaded yet
pageNavigator.update(cell.y, currentLocation, root.renderScale)
}
}
ScrollBar.horizontal: ScrollBar { }
}
onRenderScaleChanged: {
// if pageNavigator.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 (pageNavigator.jumping)
return
// page size changed: TableView needs to redo layout to avoid overlapping delegates or gaps between them
tableView.forceLayout()
const cell = tableView.cellAtPos(root.width / 2, root.height / 2)
const currentItem = tableView.itemAtCell(cell)
if (currentItem) {
const currentLocation = Qt.point((tableView.contentX - currentItem.x + tableView.jumpLocationMargin.x) / root.renderScale,
(tableView.contentY - currentItem.y + tableView.jumpLocationMargin.y) / root.renderScale)
pageNavigator.update(cell.y, currentLocation, renderScale)
}
}
PdfPageNavigator {
id: pageNavigator
property bool jumping: false
property int previousPage: 0
onJumped: function(current) {
jumping = true
if (current.zoom > 0)
root.renderScale = current.zoom
const pageSize = root.document.pagePointSize(current.page)
if (current.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
const previousPageDelegate = tableView.itemAtCell(0, previousPage)
const currentYOffset = previousPageDelegate
? tableView.contentY - previousPageDelegate.y
: 0
tableView.positionViewAtRow(current.page, Qt.AlignTop, currentYOffset)
console.log(lcMPV, "going from page", previousPage, "to", current.page, "offset", currentYOffset,
"ended up @", tableView.contentX.toFixed(1) + ", " + tableView.contentY.toFixed(1))
} else if (current.rectangles.length > 0) {
// jump to a search result and position the covered area within the viewport
pageSize.width *= root.renderScale
pageSize.height *= root.renderScale
const rectPts = current.rectangles[0]
const rectPx = Qt.rect(rectPts.x * root.renderScale - tableView.jumpLocationMargin.x,
rectPts.y * root.renderScale - tableView.jumpLocationMargin.y,
rectPts.width * root.renderScale + tableView.jumpLocationMargin.x * 2,
rectPts.height * root.renderScale + tableView.jumpLocationMargin.y * 2)
tableView.positionViewAtCell(0, current.page, TableView.Contain, Qt.point(0, 0), rectPx)
console.log(lcMPV, "going to zoom", root.renderScale, "rect", rectPx, "on page", current.page,
"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
pageSize.width *= root.renderScale
pageSize.height *= root.renderScale
const rectPx = Qt.rect(current.location.x * root.renderScale - tableView.jumpLocationMargin.x,
current.location.y * root.renderScale - tableView.jumpLocationMargin.y,
tableView.jumpLocationMargin.x * 2, tableView.jumpLocationMargin.y * 2)
tableView.positionViewAtCell(0, current.page, TableView.AlignLeft | TableView.AlignTop, Qt.point(0, 0), rectPx)
console.log(lcMPV, "going to zoom", root.renderScale, "loc", current.location, "on page", current.page,
"ended up @", tableView.contentX.toFixed(1) + ", " + tableView.contentY.toFixed(1))
}
jumping = false
previousPage = current.page
}
property url documentSource: root.document.source
onDocumentSourceChanged: {
pageNavigator.clear()
root.resetScale()
tableView.contentX = 0
tableView.contentY = 0
}
}
PdfSearchModel {
id: searchModel
document: root.document === undefined ? null : root.document
onCurrentResultChanged: pageNavigator.jump(currentResultLink)
}
}

View File

@@ -0,0 +1,439 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Pdf
import QtQuick.Shapes
/*!
\qmltype PdfPageView
\inqmlmodule QtQuick.Pdf
\brief A PDF viewer component to show one page a time.
PdfPageView provides a PDF viewer component that shows one whole page at a
time, without scrolling. It supports selecting text and copying it to the
clipboard, zooming in and out, clicking an internal link to jump to another
section in the document, rotating the view, and searching for text.
The implementation is a QML assembly of smaller building blocks that are
available separately. In case you want to make changes in your own version
of this component, you can copy the QML, which is installed into the
\c QtQuick/Pdf/qml module directory, and modify it as needed.
\sa PdfScrollablePageView, PdfMultiPageView, PdfStyle
*/
Rectangle {
/*!
\qmlproperty PdfDocument PdfPageView::document
A PdfDocument object with a valid \c source URL is required:
\snippet pdfpageview.qml 0
*/
required property PdfDocument document
/*!
\qmlproperty int PdfPageView::status
This property holds the \l {QtQuick::Image::status}{rendering status} of
the \l {currentPage}{current page}.
*/
property alias status: image.status
/*!
\qmlproperty PdfDocument PdfPageView::selectedText
The selected text.
*/
property alias selectedText: selection.text
/*!
\qmlmethod void PdfPageView::selectAll()
Selects all the text on the \l {currentPage}{current page}, and makes it
available as the system \l {QClipboard::Selection}{selection} on systems
that support that feature.
\sa copySelectionToClipboard()
*/
function selectAll() {
selection.selectAll()
}
/*!
\qmlmethod void PdfPageView::copySelectionToClipboard()
Copies the selected text (if any) to the
\l {QClipboard::Clipboard}{system clipboard}.
\sa selectAll()
*/
function copySelectionToClipboard() {
selection.copyToClipboard()
}
// --------------------------------
// page navigation
/*!
\qmlproperty int PdfPageView::currentPage
\readonly
This property holds the zero-based page number of the page visible in the
scrollable view. If there is no current page, it holds -1.
This property is read-only, and is typically used in a binding (or
\c onCurrentPageChanged script) to update the part of the user interface
that shows the current page number, such as a \l SpinBox.
\sa PdfPageNavigator::currentPage
*/
property alias currentPage: pageNavigator.currentPage
/*!
\qmlproperty bool PdfPageView::backEnabled
\readonly
This property indicates if it is possible to go back in the navigation
history to a previous-viewed page.
\sa PdfPageNavigator::backAvailable, back()
*/
property alias backEnabled: pageNavigator.backAvailable
/*!
\qmlproperty bool PdfPageView::forwardEnabled
\readonly
This property indicates if it is possible to go to next location in the
navigation history.
\sa PdfPageNavigator::forwardAvailable, forward()
*/
property alias forwardEnabled: pageNavigator.forwardAvailable
/*!
\qmlmethod void PdfPageView::back()
Scrolls the view back to the previous page that the user visited most
recently; or does nothing if there is no previous location on the
navigation stack.
\sa PdfPageNavigator::back(), currentPage, backEnabled
*/
function back() { pageNavigator.back() }
/*!
\qmlmethod void PdfPageView::forward()
Scrolls the view to the page that the user was viewing when the back()
method was called; or does nothing if there is no "next" location on the
navigation stack.
\sa PdfPageNavigator::forward(), currentPage
*/
function forward() { pageNavigator.forward() }
/*!
\qmlmethod void PdfPageView::goToPage(int page)
Changes the view to the \a page, if possible.
\sa PdfPageNavigator::jump(), currentPage
*/
function goToPage(page) { goToLocation(page, Qt.point(0, 0), 0) }
/*!
\qmlmethod void PdfPageView::goToLocation(int page, point location, real zoom)
Scrolls the view to the \a location on the \a page, if possible,
and sets the \a zoom level.
\sa PdfPageNavigator::jump(), currentPage
*/
function goToLocation(page, location, zoom) {
if (zoom > 0)
root.renderScale = zoom
pageNavigator.jump(page, location, zoom)
}
// --------------------------------
// page scaling
/*!
\qmlproperty bool PdfPageView::zoomEnabled
This property holds whether the user can use the pinch gesture or
Control + mouse wheel to zoom. The default is \c true.
When the user zooms the page, the size of PdfPageView changes.
*/
property bool zoomEnabled: true
/*!
\qmlproperty real PdfPageView::renderScale
This property holds the ratio of pixels to points. The default is \c 1,
meaning one point (1/72 of an inch) equals 1 logical pixel.
*/
property real renderScale: 1
/*!
\qmlproperty size PdfPageView::sourceSize
This property holds the scaled width and height of the full-frame image.
\sa {QtQuick::Image::sourceSize}{Image.sourceSize}
*/
property alias sourceSize: image.sourceSize
/*!
\qmlmethod void PdfPageView::resetScale()
Sets \l renderScale back to its default value of \c 1.
*/
function resetScale() {
image.sourceSize.width = 0
image.sourceSize.height = 0
root.scale = 1
}
/*!
\qmlmethod void PdfPageView::scaleToWidth(real width, real height)
Sets \l renderScale such that the width of the first page will fit into a
viewport with the given \a width and \a height. If the page is not rotated,
it will be scaled so that its width fits \a width. If it is rotated +/- 90
degrees, it will be scaled so that its width fits \a height.
*/
function scaleToWidth(width, height) {
const halfRotation = Math.abs(root.rotation % 180)
image.sourceSize = Qt.size((halfRotation > 45 && halfRotation < 135) ? height : width, 0)
image.centerInSize = Qt.size(width, height)
image.centerOnLoad = true
image.vCenterOnLoad = (halfRotation > 45 && halfRotation < 135)
root.scale = 1
}
/*!
\qmlmethod void PdfPageView::scaleToPage(real width, real height)
Sets \l renderScale such that the whole first page will fit into a viewport
with the given \a width and \a height. The resulting \l renderScale depends
on page rotation: the page will fit into the viewport at a larger size if it
is first rotated to have a matching aspect ratio.
*/
function scaleToPage(width, height) {
const windowAspect = width / height
const halfRotation = Math.abs(root.rotation % 180)
const pagePointSize = document.pagePointSize(pageNavigator.currentPage)
const pageAspect = pagePointSize.height / pagePointSize.width
if (halfRotation > 45 && halfRotation < 135) {
// rotated 90 or 270º
if (windowAspect > pageAspect) {
image.sourceSize = Qt.size(height, 0)
} else {
image.sourceSize = Qt.size(0, width)
}
} else {
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
/*!
\qmlproperty PdfSearchModel PdfPageView::searchModel
This property holds a PdfSearchModel containing the list of search results
for a given \l searchString.
\sa PdfSearchModel
*/
property alias searchModel: searchModel
/*!
\qmlproperty string PdfPageView::searchString
This property holds the search string that the user may choose to search
for. It is typically used in a binding to the \c text property of a
TextField.
\sa searchModel
*/
property alias searchString: searchModel.searchString
/*!
\qmlmethod void PdfPageView::searchBack()
Decrements the
\l{PdfSearchModel::currentResult}{searchModel's current result}
so that the view will jump to the previous search result.
*/
function searchBack() { --searchModel.currentResult }
/*!
\qmlmethod void PdfPageView::searchForward()
Increments the
\l{PdfSearchModel::currentResult}{searchModel's current result}
so that the view will jump to the next search result.
*/
function searchForward() { ++searchModel.currentResult }
// --------------------------------
// implementation
id: root
width: image.width
height: image.height
PdfSelection {
id: selection
document: root.document
page: pageNavigator.currentPage
from: Qt.point(textSelectionDrag.centroid.pressPosition.x / image.pageScale, textSelectionDrag.centroid.pressPosition.y / image.pageScale)
to: Qt.point(textSelectionDrag.centroid.position.x / image.pageScale, textSelectionDrag.centroid.position.y / image.pageScale)
hold: !textSelectionDrag.active && !tapHandler.pressed
}
PdfSearchModel {
id: searchModel
document: root.document === undefined ? null : root.document
onCurrentPageChanged: root.goToPage(currentPage)
}
PdfPageNavigator {
id: pageNavigator
onCurrentPageChanged: searchModel.currentPage = currentPage
onCurrentZoomChanged: root.renderScale = currentZoom
property url documentSource: root.document.source
onDocumentSourceChanged: {
pageNavigator.clear()
root.goToPage(0)
}
}
PdfPageImage {
id: image
document: root.document
currentFrame: pageNavigator.currentPage
asynchronous: true
fillMode: Image.PreserveAspectFit
property bool centerOnLoad: false
property bool vCenterOnLoad: false
property size centerInSize
property real pageScale: image.paintedWidth / document.pagePointSize(pageNavigator.currentPage).width
function reRenderIfNecessary() {
const newSourceWidth = image.sourceSize.width * root.scale * Screen.devicePixelRatio
const 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(pageNavigator.currentPage).width * renderScale
image.sourceSize.height = 0
root.scale = 1
}
Shape {
anchors.fill: parent
opacity: 0.25
visible: image.status === Image.Ready
ShapePath {
strokeWidth: 1
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(image.pageScale, image.pageScale)
PathMultiline {
paths: searchModel.currentResultBoundingPolygons
}
}
ShapePath {
fillColor: "orange"
scale: Qt.size(image.pageScale, image.pageScale)
PathMultiline {
paths: selection.geometry
}
}
}
Repeater {
model: PdfLinkModel {
id: linkModel
document: root.document
page: pageNavigator.currentPage
}
delegate: PdfLinkDelegate {
x: rectangle.x * image.pageScale
y: rectangle.y * image.pageScale
width: rectangle.width * image.pageScale
height: rectangle.height * image.pageScale
visible: image.status === Image.Ready
onTapped:
(link) => {
if (link.page >= 0)
pageNavigator.jump(link)
else
Qt.openUrlExternally(url)
}
}
}
PinchHandler {
id: pinch
enabled: root.zoomEnabled && root.scale * root.renderScale <= 10 && root.scale * root.renderScale >= 0.1
minimumScale: 0.1
maximumScale: 10
minimumRotation: 0
maximumRotation: 0
onActiveChanged: if (!active) image.reRenderIfNecessary()
grabPermissions: PinchHandler.TakeOverForbidden // don't allow takeover if pinch has started
}
WheelHandler {
enabled: pinch.enabled
acceptedModifiers: Qt.ControlModifier
property: "scale"
onActiveChanged: if (!active) image.reRenderIfNecessary()
}
DragHandler {
id: textSelectionDrag
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
target: null
}
TapHandler {
id: tapHandler
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
}
}

View File

@@ -0,0 +1,487 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Pdf
import QtQuick.Shapes
/*!
\qmltype PdfScrollablePageView
\inqmlmodule QtQuick.Pdf
\brief A complete PDF viewer component to show one page a time, with scrolling.
PdfScrollablePageView provides a PDF viewer component that shows one page
at a time, with scrollbars to move around the page. It also supports
selecting text and copying it to the clipboard, zooming in and out,
clicking an internal link to jump to another section in the document,
rotating the view, and searching for text. The pdfviewer example
demonstrates how to use these features in an application.
The implementation is a QML assembly of smaller building blocks that are
available separately. In case you want to make changes in your own version
of this component, you can copy the QML, which is installed into the
\c QtQuick/Pdf/qml module directory, and modify it as needed.
\sa PdfPageView, PdfMultiPageView, PdfStyle
*/
Flickable {
/*!
\qmlproperty PdfDocument PdfScrollablePageView::document
A PdfDocument object with a valid \c source URL is required:
\snippet multipageview.qml 0
*/
required property PdfDocument document
/*!
\qmlproperty int PdfScrollablePageView::status
This property holds the \l {QtQuick::Image::status}{rendering status} of
the \l {currentPage}{current page}.
*/
property alias status: image.status
/*!
\qmlproperty PdfDocument PdfScrollablePageView::selectedText
The selected text.
*/
property alias selectedText: selection.text
/*!
\qmlmethod void PdfScrollablePageView::selectAll()
Selects all the text on the \l {currentPage}{current page}, and makes it
available as the system \l {QClipboard::Selection}{selection} on systems
that support that feature.
\sa copySelectionToClipboard()
*/
function selectAll() {
selection.selectAll()
}
/*!
\qmlmethod void PdfScrollablePageView::copySelectionToClipboard()
Copies the selected text (if any) to the
\l {QClipboard::Clipboard}{system clipboard}.
\sa selectAll()
*/
function copySelectionToClipboard() {
selection.copyToClipboard()
}
// --------------------------------
// page navigation
/*!
\qmlproperty int PdfScrollablePageView::currentPage
\readonly
This property holds the zero-based page number of the page visible in the
scrollable view. If there is no current page, it holds -1.
This property is read-only, and is typically used in a binding (or
\c onCurrentPageChanged script) to update the part of the user interface
that shows the current page number, such as a \l SpinBox.
\sa PdfPageNavigator::currentPage
*/
property alias currentPage: pageNavigator.currentPage
/*!
\qmlproperty bool PdfScrollablePageView::backEnabled
\readonly
This property indicates if it is possible to go back in the navigation
history to a previous-viewed page.
\sa PdfPageNavigator::backAvailable, back()
*/
property alias backEnabled: pageNavigator.backAvailable
/*!
\qmlproperty bool PdfScrollablePageView::forwardEnabled
\readonly
This property indicates if it is possible to go to next location in the
navigation history.
\sa PdfPageNavigator::forwardAvailable, forward()
*/
property alias forwardEnabled: pageNavigator.forwardAvailable
/*!
\qmlmethod void PdfScrollablePageView::back()
Scrolls the view back to the previous page that the user visited most
recently; or does nothing if there is no previous location on the
navigation stack.
\sa PdfPageNavigator::back(), currentPage, backEnabled
*/
function back() { pageNavigator.back() }
/*!
\qmlmethod void PdfScrollablePageView::forward()
Scrolls the view to the page that the user was viewing when the back()
method was called; or does nothing if there is no "next" location on the
navigation stack.
\sa PdfPageNavigator::forward(), currentPage
*/
function forward() { pageNavigator.forward() }
/*!
\qmlmethod void PdfScrollablePageView::goToPage(int page)
Changes the view to the \a page, if possible.
\sa PdfPageNavigator::jump(), currentPage
*/
function goToPage(page) {
if (page === pageNavigator.currentPage)
return
goToLocation(page, Qt.point(0, 0), 0)
}
/*!
\qmlmethod void PdfScrollablePageView::goToLocation(int page, point location, real zoom)
Scrolls the view to the \a location on the \a page, if possible,
and sets the \a zoom level.
\sa PdfPageNavigator::jump(), currentPage
*/
function goToLocation(page, location, zoom) {
if (zoom > 0)
root.renderScale = zoom
pageNavigator.jump(page, location, zoom)
}
// --------------------------------
// page scaling
/*!
\qmlproperty real PdfScrollablePageView::renderScale
This property holds the ratio of pixels to points. The default is \c 1,
meaning one point (1/72 of an inch) equals 1 logical pixel.
*/
property real renderScale: 1
/*!
\qmlproperty real PdfScrollablePageView::pageRotation
This property holds the clockwise rotation of the pages.
The default value is \c 0 degrees (that is, no rotation relative to the
orientation of the pages as stored in the PDF file).
*/
property real pageRotation: 0
/*!
\qmlproperty size PdfScrollablePageView::sourceSize
This property holds the scaled width and height of the full-frame image.
\sa {QtQuick::Image::sourceSize}{Image.sourceSize}
*/
property alias sourceSize: image.sourceSize
/*!
\qmlmethod void PdfScrollablePageView::resetScale()
Sets \l renderScale back to its default value of \c 1.
*/
function resetScale() {
paper.scale = 1
root.renderScale = 1
}
/*!
\qmlmethod void PdfScrollablePageView::scaleToWidth(real width, real height)
Sets \l renderScale such that the width of the first page will fit into a
viewport with the given \a width and \a height. If the page is not rotated,
it will be scaled so that its width fits \a width. If it is rotated +/- 90
degrees, it will be scaled so that its width fits \a height.
*/
function scaleToWidth(width, height) {
const pagePointSize = document.pagePointSize(pageNavigator.currentPage)
root.renderScale = root.width / (paper.rot90 ? pagePointSize.height : pagePointSize.width)
console.log(lcSPV, "scaling", pagePointSize, "to fit", root.width, "rotated?", paper.rot90, "scale", root.renderScale)
root.contentX = 0
root.contentY = 0
}
/*!
\qmlmethod void PdfScrollablePageView::scaleToPage(real width, real height)
Sets \l renderScale such that the whole first page will fit into a viewport
with the given \a width and \a height. The resulting \l renderScale depends
on \l pageRotation: the page will fit into the viewport at a larger size if
it is first rotated to have a matching aspect ratio.
*/
function scaleToPage(width, height) {
const pagePointSize = document.pagePointSize(pageNavigator.currentPage)
root.renderScale = Math.min(
root.width / (paper.rot90 ? pagePointSize.height : pagePointSize.width),
root.height / (paper.rot90 ? pagePointSize.width : pagePointSize.height) )
root.contentX = 0
root.contentY = 0
}
// --------------------------------
// text search
/*!
\qmlproperty PdfSearchModel PdfScrollablePageView::searchModel
This property holds a PdfSearchModel containing the list of search results
for a given \l searchString.
\sa PdfSearchModel
*/
property alias searchModel: searchModel
/*!
\qmlproperty string PdfScrollablePageView::searchString
This property holds the search string that the user may choose to search
for. It is typically used in a binding to the \c text property of a
TextField.
\sa searchModel
*/
property alias searchString: searchModel.searchString
/*!
\qmlmethod void PdfScrollablePageView::searchBack()
Decrements the
\l{PdfSearchModel::currentResult}{searchModel's current result}
so that the view will jump to the previous search result.
*/
function searchBack() { --searchModel.currentResult }
/*!
\qmlmethod void PdfScrollablePageView::searchForward()
Increments the
\l{PdfSearchModel::currentResult}{searchModel's current result}
so that the view will jump to the next search result.
*/
function searchForward() { ++searchModel.currentResult }
// --------------------------------
// implementation
id: root
PdfStyle { id: style }
contentWidth: paper.width
contentHeight: paper.height
ScrollBar.vertical: ScrollBar {
onActiveChanged:
if (!active ) {
const currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale,
(root.contentY + root.height / 2) / root.renderScale)
pageNavigator.update(pageNavigator.currentPage, currentLocation, root.renderScale)
}
}
ScrollBar.horizontal: ScrollBar {
onActiveChanged:
if (!active ) {
const currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale,
(root.contentY + root.height / 2) / root.renderScale)
pageNavigator.update(pageNavigator.currentPage, currentLocation, root.renderScale)
}
}
onRenderScaleChanged: {
paper.scale = 1
const currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale,
(root.contentY + root.height / 2) / root.renderScale)
pageNavigator.update(pageNavigator.currentPage, currentLocation, root.renderScale)
}
PdfSearchModel {
id: searchModel
document: root.document === undefined ? null : root.document
onCurrentResultChanged: pageNavigator.jump(currentResultLink)
}
PdfPageNavigator {
id: pageNavigator
onJumped: function(current) {
root.renderScale = current.zoom
const dx = Math.max(0, current.location.x * root.renderScale - root.width / 2) - root.contentX
const dy = Math.max(0, current.location.y * root.renderScale - root.height / 2) - root.contentY
// don't jump if location is in the viewport already, i.e. if the "error" between desired and actual contentX/Y is small
if (Math.abs(dx) > root.width / 3)
root.contentX += dx
if (Math.abs(dy) > root.height / 3)
root.contentY += dy
console.log(lcSPV, "going to zoom", current.zoom, "loc", current.location,
"on page", current.page, "ended up @", root.contentX + ", " + root.contentY)
}
onCurrentPageChanged: searchModel.currentPage = currentPage
property url documentSource: root.document.source
onDocumentSourceChanged: {
pageNavigator.clear()
root.resetScale()
root.contentX = 0
root.contentY = 0
}
}
LoggingCategory {
id: lcSPV
name: "qt.pdf.singlepageview"
}
Rectangle {
id: paper
width: rot90 ? image.height : image.width
height: rot90 ? image.width : image.height
property real rotationModulus: Math.abs(root.pageRotation % 180)
property bool rot90: rotationModulus > 45 && rotationModulus < 135
property real minScale: 0.1
property real maxScale: 10
PdfPageImage {
id: image
document: root.document
currentFrame: pageNavigator.currentPage
asynchronous: true
fillMode: Image.PreserveAspectFit
rotation: root.pageRotation
anchors.centerIn: parent
property real pageScale: image.paintedWidth / document.pagePointSize(pageNavigator.currentPage).width
width: document.pagePointSize(pageNavigator.currentPage).width * root.renderScale
height: document.pagePointSize(pageNavigator.currentPage).height * root.renderScale
sourceSize.width: width * Screen.devicePixelRatio
sourceSize.height: 0
Shape {
anchors.fill: parent
visible: image.status === Image.Ready
ShapePath {
strokeWidth: -1
fillColor: style.pageSearchResultsColor
scale: Qt.size(image.pageScale, image.pageScale)
PathMultiline {
paths: searchModel.currentPageBoundingPolygons
}
}
ShapePath {
strokeWidth: style.currentSearchResultStrokeWidth
strokeColor: style.currentSearchResultStrokeColor
fillColor: "transparent"
scale: Qt.size(image.pageScale, image.pageScale)
PathMultiline {
paths: searchModel.currentResultBoundingPolygons
}
}
ShapePath {
fillColor: style.selectionColor
scale: Qt.size(image.pageScale, image.pageScale)
PathMultiline {
paths: selection.geometry
}
}
}
Repeater {
model: PdfLinkModel {
id: linkModel
document: root.document
page: pageNavigator.currentPage
}
delegate: PdfLinkDelegate {
x: rectangle.x * image.pageScale
y: rectangle.y * image.pageScale
width: rectangle.width * image.pageScale
height: rectangle.height * image.pageScale
visible: image.status === Image.Ready
onTapped:
(link) => {
if (link.page >= 0)
pageNavigator.jump(link.page, link.location, link.zoom)
else
Qt.openUrlExternally(url)
}
}
}
DragHandler {
id: textSelectionDrag
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
target: null
}
TapHandler {
id: mouseClickHandler
acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
}
TapHandler {
id: touchTapHandler
acceptedDevices: PointerDevice.TouchScreen
onTapped: {
selection.clear()
selection.focus = true
}
}
}
PdfSelection {
id: selection
anchors.fill: parent
document: root.document
page: pageNavigator.currentPage
renderScale: image.pageScale == 0 ? 1.0 : image.pageScale
from: textSelectionDrag.centroid.pressPosition
to: textSelectionDrag.centroid.position
hold: !textSelectionDrag.active && !mouseClickHandler.pressed
focus: true
}
PinchHandler {
id: pinch
minimumScale: paper.minScale / root.renderScale
maximumScale: Math.max(1, paper.maxScale / root.renderScale)
minimumRotation: 0
maximumRotation: 0
onActiveChanged:
if (!active) {
const centroidInPoints = Qt.point(pinch.centroid.position.x / root.renderScale,
pinch.centroid.position.y / root.renderScale)
const centroidInFlickable = root.mapFromItem(paper, pinch.centroid.position.x, pinch.centroid.position.y)
const newSourceWidth = image.sourceSize.width * paper.scale
const ratio = newSourceWidth / image.sourceSize.width
console.log(lcSPV, "pinch ended with centroid", pinch.centroid.position, centroidInPoints, "wrt flickable", centroidInFlickable,
"page at", paper.x.toFixed(2), paper.y.toFixed(2),
"contentX/Y were", root.contentX.toFixed(2), root.contentY.toFixed(2))
if (ratio > 1.1 || ratio < 0.9) {
const centroidOnPage = Qt.point(centroidInPoints.x * root.renderScale * ratio, centroidInPoints.y * root.renderScale * ratio)
paper.scale = 1
paper.x = 0
paper.y = 0
root.contentX = centroidOnPage.x - centroidInFlickable.x
root.contentY = centroidOnPage.y - centroidInFlickable.y
root.renderScale *= ratio // onRenderScaleChanged calls pageNavigator.update() so we don't need to here
console.log(lcSPV, "contentX/Y adjusted to", root.contentX.toFixed(2), root.contentY.toFixed(2))
} else {
paper.x = 0
paper.y = 0
}
}
grabPermissions: PointerHandler.CanTakeOverFromAnything
}
}
}

View File

@@ -0,0 +1,71 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
import QtQuick
/*!
\qmltype PdfStyle
\inqmlmodule QtQuick.Pdf
\brief A styling interface for the PDF viewer components.
PdfStyle provides properties to modify the appearance of PdfMultiPageView,
PdfScrollablePageView, and PdfPageView.
Default styles are provided to match the
\l {Styling Qt Quick Controls}{styles in Qt Quick Controls}.
\l {Using File Selectors with Qt Quick Controls}{File selectors}
are used to load the PDF style corresponding to the Controls style in use.
Custom styles are possible, using different \l {QFileSelector}{file selectors}.
*/
QtObject {
/*! \internal
\qmlproperty SystemPalette PdfStyle::palette
*/
property SystemPalette palette: SystemPalette { }
/*! \internal
\qmlmethod color PdfStyle::withAlpha()
*/
function withAlpha(color, alpha) {
return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha)
}
/*!
\qmlproperty color PdfStyle::selectionColor
The color of translucent rectangles that are overlaid on
\l {PdfMultiPageView::selectedText}{selected text}.
\sa PdfSelection
*/
property color selectionColor: withAlpha(palette.highlight, 0.5)
/*!
\qmlproperty color PdfStyle::pageSearchResultsColor
The color of translucent rectangles that are overlaid on text that
matches the \l {PdfMultiPageView::searchString}{search string}.
\sa PdfSearchModel
*/
property color pageSearchResultsColor: "#80B0C4DE"
/*!
\qmlproperty color PdfStyle::currentSearchResultStrokeColor
The color of the box outline around the
\l {PdfSearchModel::currentResult}{current search result}.
\sa PdfMultiPageView::searchBack(), PdfMultiPageView::searchForward(), PdfSearchModel::currentResult
*/
property color currentSearchResultStrokeColor: "cyan"
/*!
\qmlproperty real PdfStyle::currentSearchResultStrokeWidth
The line width of the box outline around the
\l {PdfSearchModel::currentResult}{current search result}.
\sa PdfMultiPageView::searchBack(), PdfMultiPageView::searchForward(), PdfSearchModel::currentResult
*/
property real currentSearchResultStrokeWidth: 2
}

View File

@@ -0,0 +1,894 @@
import QtQuick.tooling 1.2
// This file describes the plugin-supplied types contained in the library.
// It is used for QML tooling purposes only.
//
// This file was auto-generated by qmltyperegistrar.
Module {
Component {
file: "qpdfbookmarkmodel.h"
lineNumber: 15
name: "QPdfBookmarkModel"
accessSemantics: "reference"
prototype: "QAbstractItemModel"
Enum {
name: "Role"
isScoped: true
type: "int"
lineNumber: 22
values: ["Title", "Level", "Page", "Location", "Zoom", "NRoles"]
}
Property {
name: "document"
type: "QPdfDocument"
isPointer: true
read: "document"
write: "setDocument"
notify: "documentChanged"
index: 0
lineNumber: 19
}
Signal {
name: "documentChanged"
lineNumber: 48
Parameter { name: "document"; type: "QPdfDocument"; isPointer: true }
}
Method { name: "_q_documentStatusChanged"; lineNumber: 53 }
}
Component {
file: "qpdfdocument.h"
lineNumber: 20
name: "QPdfDocument"
accessSemantics: "reference"
prototype: "QObject"
Enum {
name: "Status"
isScoped: true
lineNumber: 30
values: ["Null", "Loading", "Ready", "Unloading", "Error"]
}
Enum {
name: "Error"
isScoped: true
lineNumber: 39
values: [
"None",
"Unknown",
"DataNotYetAvailable",
"FileNotFound",
"InvalidFileFormat",
"IncorrectPassword",
"UnsupportedSecurityScheme"
]
}
Enum {
name: "MetaDataField"
isScoped: true
lineNumber: 50
values: [
"Title",
"Subject",
"Author",
"Keywords",
"Producer",
"Creator",
"CreationDate",
"ModificationDate"
]
}
Enum {
name: "PageModelRole"
isScoped: true
lineNumber: 62
values: ["Label", "PointSize", "NRoles"]
}
Property {
name: "pageCount"
type: "int"
read: "pageCount"
notify: "pageCountChanged"
index: 0
lineNumber: 24
isReadonly: true
isFinal: true
}
Property {
name: "password"
type: "QString"
read: "password"
write: "setPassword"
notify: "passwordChanged"
index: 1
lineNumber: 25
isFinal: true
}
Property {
name: "status"
type: "Status"
read: "status"
notify: "statusChanged"
index: 2
lineNumber: 26
isReadonly: true
isFinal: true
}
Property {
name: "pageModel"
type: "QAbstractListModel"
isPointer: true
read: "pageModel"
notify: "pageModelChanged"
index: 3
lineNumber: 27
isReadonly: true
isFinal: true
}
Signal { name: "passwordChanged"; lineNumber: 103 }
Signal { name: "passwordRequired"; lineNumber: 104 }
Signal {
name: "statusChanged"
lineNumber: 105
Parameter { name: "status"; type: "QPdfDocument::Status" }
}
Signal {
name: "pageCountChanged"
lineNumber: 106
Parameter { name: "pageCount"; type: "int" }
}
Signal { name: "pageModelChanged"; lineNumber: 107 }
Method { name: "_q_tryLoadingWithSizeFromContentHeader"; lineNumber: 120 }
Method { name: "_q_copyFromSequentialSourceDevice"; lineNumber: 121 }
Method {
name: "pagePointSize"
type: "QSizeF"
isMethodConstant: true
lineNumber: 89
Parameter { name: "page"; type: "int" }
}
Method {
name: "pageLabel"
type: "QString"
lineNumber: 91
Parameter { name: "page"; type: "int" }
}
Method {
name: "pageIndexForLabel"
type: "int"
lineNumber: 92
Parameter { name: "label"; type: "QString" }
}
Method {
name: "getSelection"
type: "QPdfSelection"
lineNumber: 98
Parameter { name: "page"; type: "int" }
Parameter { name: "start"; type: "QPointF" }
Parameter { name: "end"; type: "QPointF" }
}
Method {
name: "getSelectionAtIndex"
type: "QPdfSelection"
lineNumber: 99
Parameter { name: "page"; type: "int" }
Parameter { name: "startIndex"; type: "int" }
Parameter { name: "maxLength"; type: "int" }
}
Method {
name: "getAllText"
type: "QPdfSelection"
lineNumber: 100
Parameter { name: "page"; type: "int" }
}
}
Component {
file: "private/qquickpdfpagenavigator_p.h"
lineNumber: 26
name: "QPdfLink"
accessSemantics: "value"
exports: ["QtQuick.Pdf/pdfLink 6.4"]
isCreatable: false
exportMetaObjectRevisions: [1540]
Property { name: "valid"; type: "bool"; read: "isValid"; index: 0; lineNumber: 23; isReadonly: true }
Property { name: "page"; type: "int"; read: "page"; index: 1; lineNumber: 24; isReadonly: true }
Property {
name: "location"
type: "QPointF"
read: "location"
index: 2
lineNumber: 25
isReadonly: true
}
Property { name: "zoom"; type: "double"; read: "zoom"; index: 3; lineNumber: 26; isReadonly: true }
Property { name: "url"; type: "QUrl"; read: "url"; index: 4; lineNumber: 27; isReadonly: true }
Property {
name: "contextBefore"
type: "QString"
read: "contextBefore"
index: 5
lineNumber: 28
isReadonly: true
}
Property {
name: "contextAfter"
type: "QString"
read: "contextAfter"
index: 6
lineNumber: 29
isReadonly: true
}
Property {
name: "rectangles"
type: "QRectF"
isList: true
read: "rectangles"
index: 7
lineNumber: 30
isReadonly: true
}
Method { name: "toString"; type: "QString"; isMethodConstant: true; lineNumber: 51 }
Method {
name: "copyToClipboard"
isMethodConstant: true
lineNumber: 52
Parameter { name: "mode"; type: "QClipboard::Mode" }
}
Method { name: "copyToClipboard"; isCloned: true; isMethodConstant: true; lineNumber: 52 }
}
Component {
file: "qpdflinkmodel.h"
lineNumber: 19
name: "QPdfLinkModel"
accessSemantics: "reference"
prototype: "QAbstractListModel"
Enum {
name: "Role"
isScoped: true
lineNumber: 26
values: [
"Link",
"Rectangle",
"Url",
"Page",
"Location",
"Zoom",
"NRoles"
]
}
Property {
name: "document"
type: "QPdfDocument"
isPointer: true
read: "document"
write: "setDocument"
notify: "documentChanged"
index: 0
lineNumber: 22
}
Property {
name: "page"
type: "int"
read: "page"
write: "setPage"
notify: "pageChanged"
index: 1
lineNumber: 23
}
Signal { name: "documentChanged"; lineNumber: 54 }
Signal {
name: "pageChanged"
lineNumber: 55
Parameter { name: "page"; type: "int" }
}
Method {
name: "setDocument"
lineNumber: 50
Parameter { name: "document"; type: "QPdfDocument"; isPointer: true }
}
Method {
name: "setPage"
lineNumber: 51
Parameter { name: "page"; type: "int" }
}
Method {
name: "onStatusChanged"
lineNumber: 58
Parameter { name: "status"; type: "QPdfDocument::Status" }
}
}
Component {
file: "qpdfpagenavigator.h"
lineNumber: 15
name: "QPdfPageNavigator"
accessSemantics: "reference"
prototype: "QObject"
Property {
name: "currentPage"
type: "int"
read: "currentPage"
notify: "currentPageChanged"
index: 0
lineNumber: 19
isReadonly: true
}
Property {
name: "currentLocation"
type: "QPointF"
read: "currentLocation"
notify: "currentLocationChanged"
index: 1
lineNumber: 20
isReadonly: true
}
Property {
name: "currentZoom"
type: "double"
read: "currentZoom"
notify: "currentZoomChanged"
index: 2
lineNumber: 21
isReadonly: true
}
Property {
name: "backAvailable"
type: "bool"
read: "backAvailable"
notify: "backAvailableChanged"
index: 3
lineNumber: 22
isReadonly: true
}
Property {
name: "forwardAvailable"
type: "bool"
read: "forwardAvailable"
notify: "forwardAvailableChanged"
index: 4
lineNumber: 23
isReadonly: true
}
Signal {
name: "currentPageChanged"
lineNumber: 46
Parameter { name: "page"; type: "int" }
}
Signal {
name: "currentLocationChanged"
lineNumber: 47
Parameter { name: "location"; type: "QPointF" }
}
Signal {
name: "currentZoomChanged"
lineNumber: 48
Parameter { name: "zoom"; type: "double" }
}
Signal {
name: "backAvailableChanged"
lineNumber: 49
Parameter { name: "available"; type: "bool" }
}
Signal {
name: "forwardAvailableChanged"
lineNumber: 50
Parameter { name: "available"; type: "bool" }
}
Signal {
name: "jumped"
lineNumber: 51
Parameter { name: "current"; type: "QPdfLink" }
}
Method { name: "clear"; lineNumber: 38 }
Method {
name: "jump"
lineNumber: 39
Parameter { name: "destination"; type: "QPdfLink" }
}
Method {
name: "jump"
lineNumber: 40
Parameter { name: "page"; type: "int" }
Parameter { name: "location"; type: "QPointF" }
Parameter { name: "zoom"; type: "double" }
}
Method {
name: "jump"
isCloned: true
lineNumber: 40
Parameter { name: "page"; type: "int" }
Parameter { name: "location"; type: "QPointF" }
}
Method {
name: "update"
lineNumber: 41
Parameter { name: "page"; type: "int" }
Parameter { name: "location"; type: "QPointF" }
Parameter { name: "zoom"; type: "double" }
}
Method { name: "forward"; lineNumber: 42 }
Method { name: "back"; lineNumber: 43 }
}
Component {
file: "qpdfsearchmodel.h"
lineNumber: 17
name: "QPdfSearchModel"
accessSemantics: "reference"
prototype: "QAbstractListModel"
Enum {
name: "Role"
isScoped: true
type: "int"
lineNumber: 25
values: [
"Page",
"IndexOnPage",
"Location",
"ContextBefore",
"ContextAfter",
"NRoles"
]
}
Property {
name: "document"
type: "QPdfDocument"
isPointer: true
read: "document"
write: "setDocument"
notify: "documentChanged"
index: 0
lineNumber: 20
}
Property {
name: "searchString"
type: "QString"
read: "searchString"
write: "setSearchString"
notify: "searchStringChanged"
index: 1
lineNumber: 21
}
Property {
name: "count"
revision: 1544
type: "int"
read: "count"
notify: "countChanged"
index: 2
lineNumber: 22
isReadonly: true
isFinal: true
}
Signal { name: "documentChanged"; lineNumber: 55 }
Signal { name: "searchStringChanged"; lineNumber: 56 }
Signal { name: "countChanged"; revision: 1544; lineNumber: 57 }
Method {
name: "setSearchString"
lineNumber: 51
Parameter { name: "searchString"; type: "QString" }
}
Method {
name: "setDocument"
lineNumber: 52
Parameter { name: "document"; type: "QPdfDocument"; isPointer: true }
}
}
Component {
file: "private/qquickpdfbookmarkmodel_p.h"
lineNumber: 26
name: "QQuickPdfBookmarkModel"
accessSemantics: "reference"
prototype: "QPdfBookmarkModel"
exports: ["QtQuick.Pdf/PdfBookmarkModel 6.4"]
exportMetaObjectRevisions: [1540]
Property {
name: "document"
type: "QQuickPdfDocument"
isPointer: true
read: "document"
write: "setDocument"
notify: "documentChanged"
index: 0
lineNumber: 29
}
Signal { name: "documentChanged"; lineNumber: 41 }
}
Component {
file: "private/qquickpdfdocument_p.h"
lineNumber: 30
name: "QQuickPdfDocument"
accessSemantics: "reference"
prototype: "QObject"
extension: "QPdfDocument"
interfaces: ["QQmlParserStatus"]
exports: [
"QtQuick.Pdf/PdfDocument 5.15",
"QtQuick.Pdf/PdfDocument 6.0"
]
exportMetaObjectRevisions: [1295, 1536]
Property {
name: "source"
type: "QUrl"
read: "source"
write: "setSource"
notify: "sourceChanged"
index: 0
lineNumber: 35
isFinal: true
}
Property {
name: "maxPageWidth"
type: "double"
read: "maxPageWidth"
notify: "metaDataChanged"
index: 1
lineNumber: 36
isReadonly: true
isFinal: true
}
Property {
name: "maxPageHeight"
type: "double"
read: "maxPageHeight"
notify: "metaDataChanged"
index: 2
lineNumber: 37
isReadonly: true
isFinal: true
}
Property {
name: "error"
type: "QString"
read: "error"
notify: "errorChanged"
index: 3
lineNumber: 38
isReadonly: true
isFinal: true
}
Property {
name: "title"
type: "QString"
read: "title"
notify: "metaDataChanged"
index: 4
lineNumber: 40
isReadonly: true
isFinal: true
}
Property {
name: "subject"
type: "QString"
read: "subject"
notify: "metaDataChanged"
index: 5
lineNumber: 41
isReadonly: true
isFinal: true
}
Property {
name: "author"
type: "QString"
read: "author"
notify: "metaDataChanged"
index: 6
lineNumber: 42
isReadonly: true
isFinal: true
}
Property {
name: "keywords"
type: "QString"
read: "keywords"
notify: "metaDataChanged"
index: 7
lineNumber: 43
isReadonly: true
isFinal: true
}
Property {
name: "producer"
type: "QString"
read: "producer"
notify: "metaDataChanged"
index: 8
lineNumber: 44
isReadonly: true
isFinal: true
}
Property {
name: "creator"
type: "QString"
read: "creator"
notify: "metaDataChanged"
index: 9
lineNumber: 45
isReadonly: true
isFinal: true
}
Property {
name: "creationDate"
type: "QDateTime"
read: "creationDate"
notify: "metaDataChanged"
index: 10
lineNumber: 46
isReadonly: true
isFinal: true
}
Property {
name: "modificationDate"
type: "QDateTime"
read: "modificationDate"
notify: "metaDataChanged"
index: 11
lineNumber: 47
isReadonly: true
isFinal: true
}
Signal { name: "sourceChanged"; lineNumber: 78 }
Signal { name: "errorChanged"; lineNumber: 79 }
Signal { name: "metaDataChanged"; lineNumber: 80 }
}
Component {
file: "private/qquickpdflinkmodel_p.h"
lineNumber: 26
name: "QQuickPdfLinkModel"
accessSemantics: "reference"
prototype: "QPdfLinkModel"
exports: [
"QtQuick.Pdf/PdfLinkModel 5.15",
"QtQuick.Pdf/PdfLinkModel 6.0",
"QtQuick.Pdf/PdfLinkModel 6.4"
]
exportMetaObjectRevisions: [1295, 1536, 1540]
Property {
name: "document"
type: "QQuickPdfDocument"
isPointer: true
read: "document"
write: "setDocument"
notify: "documentChanged"
index: 0
lineNumber: 29
}
}
Component {
file: "private/qquickpdfpageimage_p.h"
lineNumber: 25
name: "QQuickPdfPageImage"
accessSemantics: "reference"
prototype: "QQuickImage"
exports: [
"QtQuick.Pdf/PdfPageImage 6.4",
"QtQuick.Pdf/PdfPageImage 6.7",
"QtQuick.Pdf/PdfPageImage 6.8"
]
exportMetaObjectRevisions: [1540, 1543, 1544]
Property {
name: "document"
type: "QQuickPdfDocument"
isPointer: true
read: "document"
write: "setDocument"
notify: "documentChanged"
index: 0
lineNumber: 28
isFinal: true
}
Signal { name: "documentChanged"; lineNumber: 40 }
}
Component {
file: "private/qquickpdfpagenavigator_p.h"
lineNumber: 34
name: "QQuickPdfPageNavigator"
accessSemantics: "reference"
prototype: "QObject"
extension: "QPdfPageNavigator"
exports: [
"QtQuick.Pdf/PdfPageNavigator 5.15",
"QtQuick.Pdf/PdfPageNavigator 6.0"
]
exportMetaObjectRevisions: [1295, 1536]
}
Component {
file: "private/qquickpdfsearchmodel_p.h"
lineNumber: 26
name: "QQuickPdfSearchModel"
accessSemantics: "reference"
prototype: "QPdfSearchModel"
exports: [
"QtQuick.Pdf/PdfSearchModel 5.15",
"QtQuick.Pdf/PdfSearchModel 6.0",
"QtQuick.Pdf/PdfSearchModel 6.4",
"QtQuick.Pdf/PdfSearchModel 6.8"
]
exportMetaObjectRevisions: [1295, 1536, 1540, 1544]
Property {
name: "document"
type: "QQuickPdfDocument"
isPointer: true
read: "document"
write: "setDocument"
notify: "documentChanged"
index: 0
lineNumber: 29
}
Property {
name: "currentPage"
type: "int"
read: "currentPage"
write: "setCurrentPage"
notify: "currentPageChanged"
index: 1
lineNumber: 30
}
Property {
name: "currentResult"
type: "int"
read: "currentResult"
write: "setCurrentResult"
notify: "currentResultChanged"
index: 2
lineNumber: 31
}
Property {
name: "currentResultLink"
type: "QPdfLink"
read: "currentResultLink"
notify: "currentResultLinkChanged"
index: 3
lineNumber: 32
isReadonly: true
}
Property {
name: "currentPageBoundingPolygons"
type: "QPolygonF"
isList: true
read: "currentPageBoundingPolygons"
notify: "currentPageBoundingPolygonsChanged"
index: 4
lineNumber: 33
isReadonly: true
}
Property {
name: "currentResultBoundingPolygons"
type: "QPolygonF"
isList: true
read: "currentResultBoundingPolygons"
notify: "currentResultBoundingPolygonsChanged"
index: 5
lineNumber: 34
isReadonly: true
}
Property {
name: "currentResultBoundingRect"
type: "QRectF"
read: "currentResultBoundingRect"
notify: "currentResultBoundingRectChanged"
index: 6
lineNumber: 35
isReadonly: true
}
Signal { name: "currentPageChanged"; lineNumber: 60 }
Signal { name: "currentResultChanged"; lineNumber: 61 }
Signal { name: "currentResultLinkChanged"; lineNumber: 62 }
Signal { name: "currentPageBoundingPolygonsChanged"; lineNumber: 63 }
Signal { name: "currentResultBoundingPolygonsChanged"; lineNumber: 64 }
Signal { name: "currentResultBoundingRectChanged"; lineNumber: 65 }
Method {
name: "boundingPolygonsOnPage"
type: "QPolygonF"
isList: true
lineNumber: 46
Parameter { name: "page"; type: "int" }
}
}
Component {
file: "private/qquickpdfselection_p.h"
lineNumber: 30
name: "QQuickPdfSelection"
accessSemantics: "reference"
defaultProperty: "data"
parentProperty: "parent"
prototype: "QQuickItem"
exports: [
"QtQuick.Pdf/PdfSelection 5.15",
"QtQuick.Pdf/PdfSelection 6.0",
"QtQuick.Pdf/PdfSelection 6.3",
"QtQuick.Pdf/PdfSelection 6.7"
]
exportMetaObjectRevisions: [1295, 1536, 1539, 1543]
Property {
name: "document"
type: "QQuickPdfDocument"
isPointer: true
read: "document"
write: "setDocument"
notify: "documentChanged"
index: 0
lineNumber: 33
}
Property {
name: "page"
type: "int"
read: "page"
write: "setPage"
notify: "pageChanged"
index: 1
lineNumber: 34
}
Property {
name: "renderScale"
type: "double"
read: "renderScale"
write: "setRenderScale"
notify: "renderScaleChanged"
index: 2
lineNumber: 35
}
Property {
name: "from"
type: "QPointF"
read: "from"
write: "setFrom"
notify: "fromChanged"
index: 3
lineNumber: 36
}
Property {
name: "to"
type: "QPointF"
read: "to"
write: "setTo"
notify: "toChanged"
index: 4
lineNumber: 37
}
Property {
name: "hold"
type: "bool"
read: "hold"
write: "setHold"
notify: "holdChanged"
index: 5
lineNumber: 38
}
Property {
name: "text"
type: "QString"
read: "text"
notify: "textChanged"
index: 6
lineNumber: 40
isReadonly: true
}
Property {
name: "geometry"
type: "QPolygonF"
isList: true
read: "geometry"
notify: "selectedAreaChanged"
index: 7
lineNumber: 41
isReadonly: true
}
Signal { name: "documentChanged"; lineNumber: 72 }
Signal { name: "pageChanged"; lineNumber: 73 }
Signal { name: "renderScaleChanged"; lineNumber: 74 }
Signal { name: "fromChanged"; lineNumber: 75 }
Signal { name: "toChanged"; lineNumber: 76 }
Signal { name: "holdChanged"; lineNumber: 77 }
Signal { name: "textChanged"; lineNumber: 78 }
Signal { name: "selectedAreaChanged"; lineNumber: 79 }
Method { name: "clear"; lineNumber: 65 }
Method { name: "selectAll"; lineNumber: 66 }
Method { name: "copyToClipboard"; isMethodConstant: true; lineNumber: 68 }
Method {
name: "inputMethodQuery"
type: "QVariant"
isMethodConstant: true
lineNumber: 85
Parameter { name: "query"; type: "Qt::InputMethodQuery" }
Parameter { name: "argument"; type: "QVariant" }
}
}
}

View File

@@ -0,0 +1,23 @@
module QtQuick.Pdf
linktarget Qt6::PdfQuickplugin
optional plugin pdfquickplugin
classname QtQuick_PdfPlugin
typeinfo plugins.qmltypes
depends QtQuick auto
prefer :/qt-project.org/imports/QtQuick/Pdf/
PdfStyle 6.0 +Material/PdfStyle.qml
PdfStyle 5.0 +Material/PdfStyle.qml
PdfStyle 6.0 +Universal/PdfStyle.qml
PdfStyle 5.0 +Universal/PdfStyle.qml
PdfLinkDelegate 6.0 PdfLinkDelegate.qml
PdfLinkDelegate 5.0 PdfLinkDelegate.qml
PdfMultiPageView 6.0 PdfMultiPageView.qml
PdfMultiPageView 5.0 PdfMultiPageView.qml
PdfPageView 6.0 PdfPageView.qml
PdfPageView 5.0 PdfPageView.qml
PdfScrollablePageView 6.0 PdfScrollablePageView.qml
PdfScrollablePageView 5.0 PdfScrollablePageView.qml
PdfStyle 6.0 PdfStyle.qml
PdfStyle 5.0 PdfStyle.qml
depends QtQuick