diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-06-02 21:51:21 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-06-04 20:55:31 +0200 |
commit | 33f6047ef17421fd07d0350fedcfbd049e31fe28 (patch) | |
tree | 0e64e05110dd5536bf07c4ed5cdaf72633d831ed /src/pdf | |
parent | fa260888d9c9a59acd6e35aa472ca53990ce6635 (diff) | |
download | qtwebengine-33f6047ef17421fd07d0350fedcfbd049e31fe28.tar.gz |
Use QPdfLink in PageNavigator jump() / jumped(); QML views
One reason for this is to use the new
tableView.positionViewAtCell(.., TableView.Contain, offset, rect) to do
less scrolling when iterating search results. Now in that case, the
QPdfLink object contains correct rectangles, so that we can scale the
first one and pass it directly to positionViewAtCell().
When clicking a hyperlink, the destination is a point rather than a
rectangle; but positionViewAtCell with a subRect works better than
calling it with just an offset, so we construct a small rectangle for
that purpose. It's important that the QPdfLink object emitted in the
jumped() signal must not contain any rectangles in this case, so that we
can distinguish a hyperlink destination from a search-result
destination. The QPdfLink object from PdfLinkModel has its own
rectangle, but that's the place where the user clicks. When clicked,
the view calls pageNavigator.jump(page, location, zoom), rather
than the jump(QPdfLink) overload, so that rectangle is not passed along.
In an onJumped() handler, we expect the rectangles to be the
destination, if present; otherwise we fall back to using the location
property, which is always the destination, never the source.
In both cases, we need to grow the destination rectangle by
jumpLocationMargin, because the offset argument to positionViewAtCell()
is an offset, not a margin. But since the rectangle needs to be scaled
from points to pixels anyway (according to the current renderScale),
it's not much more trouble to add the margin. It looks better to avoid
having a search result and its highlight rectangle banging up against
the corner of the viewport: the margin lets the user see a bit of
context on the page, and the highlight looks more distinct by being
spaced out away from the edge. And since the margin gets added to
the rectangle's edges, it makes more sense to use the (qreal) point type
rather than vector2d.
To make it possible to emit a QPdfLink object and access its properties
in QML, it's now registered as a QML type.
Fixes: QTBUG-102740
Change-Id: I74ccd11a106c5e49a0ce94eef9cf2d50992923b4
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src/pdf')
-rw-r--r-- | src/pdf/qpdflink.h | 3 | ||||
-rw-r--r-- | src/pdf/qpdfpagenavigator.cpp | 71 | ||||
-rw-r--r-- | src/pdf/qpdfpagenavigator.h | 7 |
3 files changed, 74 insertions, 7 deletions
diff --git a/src/pdf/qpdflink.h b/src/pdf/qpdflink.h index 69f7f25a9..22de24063 100644 --- a/src/pdf/qpdflink.h +++ b/src/pdf/qpdflink.h @@ -88,6 +88,7 @@ private: // methods QPdfLink(QPdfLinkPrivate *d); friend class QPdfDocument; friend class QPdfSearchModelPrivate; + friend class QPdfPageNavigator; friend class QQuickPdfPageNavigator; private: // storage @@ -100,4 +101,6 @@ Q_PDF_EXPORT QDebug operator<<(QDebug, const QPdfLink &); QT_END_NAMESPACE +Q_DECLARE_METATYPE(QPdfLink) + #endif // QPDFLINK_H diff --git a/src/pdf/qpdfpagenavigator.cpp b/src/pdf/qpdfpagenavigator.cpp index db40233e3..e73c6fc24 100644 --- a/src/pdf/qpdfpagenavigator.cpp +++ b/src/pdf/qpdfpagenavigator.cpp @@ -106,7 +106,7 @@ void QPdfPageNavigator::forward() qreal currentZoomWas = currentZoom(); ++d->currentHistoryIndex; d->changing = true; - emit jumped(currentPage(), currentLocation(), currentZoom()); + emit jumped(currentLink()); if (currentZoomWas != currentZoom()) emit currentZoomChanged(currentZoom()); emit currentPageChanged(currentPage()); @@ -136,7 +136,7 @@ void QPdfPageNavigator::back() qreal currentZoomWas = currentZoom(); --d->currentHistoryIndex; d->changing = true; - emit jumped(currentPage(), currentLocation(), currentZoom()); + emit jumped(currentLink()); if (currentZoomWas != currentZoom()) emit currentZoomChanged(currentZoom()); emit currentPageChanged(currentPage()); @@ -190,6 +190,13 @@ qreal QPdfPageNavigator::currentZoom() const return d->pageHistory.at(d->currentHistoryIndex)->zoom; } +QPdfLink QPdfPageNavigator::currentLink() const +{ + if (d->currentHistoryIndex < 0 || d->currentHistoryIndex >= d->pageHistory.count()) + return QPdfLink(); + return QPdfLink(d->pageHistory.at(d->currentHistoryIndex).data()); +} + /*! Clear the history and restore \l currentPage, \l currentLocation and \l currentZoom to their default values. @@ -204,6 +211,53 @@ void QPdfPageNavigator::clear() } /*! + Adds the given \a destination to the history of visited locations. + + In this case, PDF views respond to the \l jumped signal by scrolling to + place \c destination.rectangles in the viewport, as opposed to placing + \c destination.location in the viewport. So it's appropriate to call this + method to jump to a search result from QPdfSearchModel (because the + rectangles cover the region of text found). To jump to a hyperlink + destination, call jump(page, location, zoom) instead, because in that + case the QPdfLink object's \c rectangles cover the hyperlink origin + location rather than the destination. +*/ +void QPdfPageNavigator::jump(QPdfLink destination) +{ + const bool zoomChange = !qFuzzyCompare(destination.zoom(), currentZoom()); + const bool pageChange = (destination.page() != currentPage()); + const bool locationChange = (destination.location() != currentLocation()); + const bool backAvailableWas = backAvailable(); + const bool forwardAvailableWas = forwardAvailable(); + if (!d->changing) { + if (d->currentHistoryIndex >= 0 && forwardAvailableWas) + d->pageHistory.remove(d->currentHistoryIndex + 1, d->pageHistory.count() - d->currentHistoryIndex - 1); + d->pageHistory.append(destination.d); + d->currentHistoryIndex = d->pageHistory.count() - 1; + } + if (zoomChange) + emit currentZoomChanged(currentZoom()); + if (pageChange) + emit currentPageChanged(currentPage()); + if (locationChange) + emit currentLocationChanged(currentLocation()); + if (d->changing) + return; + if (!backAvailableWas) + emit backAvailableChanged(backAvailable()); + if (forwardAvailableWas) + emit forwardAvailableChanged(forwardAvailable()); + emit jumped(currentLink()); + qCDebug(qLcNav) << "push: index" << d->currentHistoryIndex << destination << "-> history" << + [this]() { + QStringList ret; + for (auto d : d->pageHistory) + ret << QString::number(d->page); + return ret.join(QLatin1Char(',')); + }(); +} + +/*! Adds the given destination, consisting of \a page, \a location, and \a zoom, to the history of visited locations. @@ -249,7 +303,7 @@ void QPdfPageNavigator::jump(int page, const QPointF &location, qreal zoom) emit backAvailableChanged(backAvailable()); if (forwardAvailableWas) emit forwardAvailableChanged(forwardAvailable()); - emit jumped(page, location, zoom); + emit jumped(currentLink()); qCDebug(qLcNav) << "push: index" << d->currentHistoryIndex << "page" << page << "@" << location << "zoom" << zoom << "-> history" << [this]() { @@ -326,12 +380,17 @@ bool QPdfPageNavigator::forwardAvailable() const } /*! - \fn void QPdfPageNavigator::jumped(int page, const QPointF &location, qreal zoom) + \fn void QPdfPageNavigator::jumped(QPdfLink current) - This signal is emitted when an abrupt jump occurs, to the specified \a page - index, \a location on the page, and \a zoom level; but \e not when simply + This signal is emitted when an abrupt jump occurs, to the \a current + page index, location on the page, and zoom level; but \e not when simply scrolling through the document one page at a time. That is, jump(), forward() and back() emit this signal, but update() does not. + + If \c {current.rectangles.length > 0}, they are rectangles that cover + a specific destination area: a search result that should be made + visible; otherwise, \c {current.location} is the destination location on + the \c page (a hyperlink destination, or during forward/back navigation). */ QT_END_NAMESPACE diff --git a/src/pdf/qpdfpagenavigator.h b/src/pdf/qpdfpagenavigator.h index 2e92b2dc1..35579a02d 100644 --- a/src/pdf/qpdfpagenavigator.h +++ b/src/pdf/qpdfpagenavigator.h @@ -41,6 +41,7 @@ #define QPDFPAGENAVIGATOR_H #include <QtPdf/qtpdfglobal.h> +#include <QtPdf/qpdflink.h> #include <QtCore/qobject.h> QT_BEGIN_NAMESPACE @@ -71,6 +72,7 @@ public: public Q_SLOTS: void clear(); + void jump(QPdfLink destination); void jump(int page, const QPointF &location, qreal zoom = 0); void update(int page, const QPointF &location, qreal zoom); void forward(); @@ -82,7 +84,10 @@ Q_SIGNALS: void currentZoomChanged(qreal zoom); void backAvailableChanged(bool available); void forwardAvailableChanged(bool available); - void jumped(int page, const QPointF &location, qreal zoom); + void jumped(QPdfLink current); + +protected: + QPdfLink currentLink() const; private: QScopedPointer<QPdfPageNavigatorPrivate> d; |