summaryrefslogtreecommitdiffstats
path: root/src/pdfwidgets
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2023-03-15 10:42:07 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2023-03-17 12:35:38 +0100
commit288e9be6ba2be40761333036f3397298df5e1018 (patch)
treec274dc8466e134c3d3e0e6211e9c2c8c09951021 /src/pdfwidgets
parentf36f0d5202fee3b778290dd68d1c30911b75b5b4 (diff)
Teach QPdfView to render search result highlights
The bounding boxes of all visible search results are filled with a translucent color on top of the page image, because we don't know whether the image is opaque or not. currentSearchResult is further highlighted by drawing bounding box borders. The colors are the same as PdfStyle.pageSearchResultsColor and PdfStyle.currentSearchResultStrokeColor, respectively. Perhaps they could be configurable somehow in the future, but it's not clear yet what API that ought to have, since we do not have suitable QPalette roles (except QPalette::Highlight, which is not translucent). Task-number: QTBUG-77507 Task-number: QTBUG-92973 Change-Id: I3df634229811e72d2d438a39997e0b4887d6bf11 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src/pdfwidgets')
-rw-r--r--src/pdfwidgets/qpdfview.cpp85
-rw-r--r--src/pdfwidgets/qpdfview.h13
-rw-r--r--src/pdfwidgets/qpdfview_p.h3
3 files changed, 100 insertions, 1 deletions
diff --git a/src/pdfwidgets/qpdfview.cpp b/src/pdfwidgets/qpdfview.cpp
index ce49245e9..8295fd57b 100644
--- a/src/pdfwidgets/qpdfview.cpp
+++ b/src/pdfwidgets/qpdfview.cpp
@@ -13,6 +13,7 @@
#include <QPaintEvent>
#include <QPdfDocument>
#include <QPdfPageNavigator>
+#include <QPdfSearchModel>
#include <QScreen>
#include <QScrollBar>
#include <QScroller>
@@ -22,6 +23,10 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcLink, "qt.pdf.links")
//#define DEBUG_LINKS
+static const QColor SearchResultHighlight("#80B0C4DE");
+static const QColor CurrentSearchResultHighlight(Qt::cyan);
+static const int CurrentSearchResultWidth(2);
+
QPdfViewPrivate::QPdfViewPrivate(QPdfView *q)
: q_ptr(q)
, m_document(nullptr)
@@ -340,6 +345,69 @@ QPdfDocument *QPdfView::document() const
}
/*!
+ \since 6.6
+ \property QPdfView::searchModel
+
+ If this property is set, QPdfView draws highlight rectangles over the
+ search results provided by \l QPdfSearchModel::resultsOnPage(). By default
+ it is \c nullptr.
+*/
+void QPdfView::setSearchModel(QPdfSearchModel *searchModel)
+{
+ Q_D(QPdfView);
+ if (d->m_searchModel == searchModel)
+ return;
+
+ if (d->m_searchModel)
+ d->m_searchModel->disconnect(this);
+
+ d->m_searchModel = searchModel;
+ emit searchModelChanged(searchModel);
+
+ if (searchModel) {
+ connect(searchModel, &QPdfSearchModel::dataChanged, this,
+ [this](const QModelIndex &, const QModelIndex &, const QList<int> &) { update(); });
+ }
+ setCurrentSearchResult(-1);
+}
+
+QPdfSearchModel *QPdfView::searchModel() const
+{
+ Q_D(const QPdfView);
+ return d->m_searchModel;
+}
+
+/*!
+ \since 6.6
+ \property QPdfView::currentSearchResult
+
+ If this property is set to a positive number, and \l searchModel is set,
+ QPdfView draws a frame around the search result provided by
+ \l QPdfSearchModel at the given index. For example, if QPdfSearchModel is
+ used as the model for a QListView, you can keep this property updated by
+ connecting QItemSelectionModel::currentChanged() from
+ QListView::selectionModel() to a function that will in turn call this function.
+
+ By default it is \c -1, so that no search results are framed.
+*/
+void QPdfView::setCurrentSearchResult(int currentResult)
+{
+ Q_D(QPdfView);
+ if (d->m_currentSearchResult == currentResult)
+ return;
+
+ d->m_currentSearchResult = currentResult;
+ emit currentSearchResultChanged(currentResult);
+ viewport()->update(); //update();
+}
+
+int QPdfView::currentSearchResult() const
+{
+ Q_D(const QPdfView);
+ return d->m_currentSearchResult;
+}
+
+/*!
This accessor returns the navigation stack that will handle back/forward navigation.
*/
QPdfPageNavigator *QPdfView::pageNavigator() const
@@ -522,8 +590,8 @@ void QPdfView::paintEvent(QPaintEvent *event)
d->m_pageRenderer->requestPage(page, pageGeometry.size() * devicePixelRatioF());
}
-#ifdef DEBUG_LINKS
const QTransform scaleTransform = d->screenScaleTransform();
+#ifdef DEBUG_LINKS
const QString fmt = u"page %1 @ %2, %3"_s;
d->m_linkModel.setPage(page);
const int linkCount = d->m_linkModel.rowCount({});
@@ -544,6 +612,21 @@ void QPdfView::paintEvent(QPaintEvent *event)
.arg(loc.x()).arg(loc.y()));
}
#endif
+ if (d->m_searchModel) {
+ for (const QPdfLink &result : d->m_searchModel->resultsOnPage(page)) {
+ for (const QRectF &rect : result.rectangles())
+ painter.fillRect(scaleTransform.mapRect(rect).translated(pageGeometry.topLeft()), SearchResultHighlight);
+ }
+
+ if (d->m_currentSearchResult >= 0 && d->m_currentSearchResult < d->m_searchModel->rowCount({})) {
+ const QPdfLink &cur = d->m_searchModel->resultAtIndex(d->m_currentSearchResult);
+ if (cur.page() == page) {
+ painter.setPen({CurrentSearchResultHighlight, CurrentSearchResultWidth});
+ for (const auto &rect : cur.rectangles())
+ painter.drawRect(scaleTransform.mapRect(rect).translated(pageGeometry.topLeft()));
+ }
+ }
+ }
}
}
}
diff --git a/src/pdfwidgets/qpdfview.h b/src/pdfwidgets/qpdfview.h
index 886ed697f..54e9ddfd5 100644
--- a/src/pdfwidgets/qpdfview.h
+++ b/src/pdfwidgets/qpdfview.h
@@ -1,4 +1,5 @@
// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König <tobias.koenig@kdab.com>
+// Copyright (C) 2023 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
#ifndef QPDFVIEW_H
@@ -13,6 +14,7 @@ QT_BEGIN_NAMESPACE
class QPdfDocument;
class QPdfPageNavigator;
+class QPdfSearchModel;
class QPdfViewPrivate;
class Q_PDF_WIDGETS_EXPORT QPdfView : public QAbstractScrollArea
@@ -28,6 +30,9 @@ class Q_PDF_WIDGETS_EXPORT QPdfView : public QAbstractScrollArea
Q_PROPERTY(int pageSpacing READ pageSpacing WRITE setPageSpacing NOTIFY pageSpacingChanged)
Q_PROPERTY(QMargins documentMargins READ documentMargins WRITE setDocumentMargins NOTIFY documentMarginsChanged)
+ Q_PROPERTY(QPdfSearchModel* searchModel READ searchModel WRITE setSearchModel NOTIFY searchModelChanged)
+ Q_PROPERTY(int currentSearchResult READ currentSearchResult WRITE setCurrentSearchResult NOTIFY currentSearchResultChanged)
+
public:
enum class PageMode
{
@@ -51,6 +56,11 @@ public:
void setDocument(QPdfDocument *document);
QPdfDocument *document() const;
+ QPdfSearchModel *searchModel() const;
+ void setSearchModel(QPdfSearchModel *searchModel);
+
+ int currentSearchResult() const;
+
QPdfPageNavigator *pageNavigator() const;
PageMode pageMode() const;
@@ -67,6 +77,7 @@ public Q_SLOTS:
void setPageMode(QPdfView::PageMode mode);
void setZoomMode(QPdfView::ZoomMode mode);
void setZoomFactor(qreal factor);
+ void setCurrentSearchResult(int currentResult);
Q_SIGNALS:
void documentChanged(QPdfDocument *document);
@@ -75,6 +86,8 @@ Q_SIGNALS:
void zoomFactorChanged(qreal zoomFactor);
void pageSpacingChanged(int pageSpacing);
void documentMarginsChanged(QMargins documentMargins);
+ void searchModelChanged(QPdfSearchModel *searchModel);
+ void currentSearchResultChanged(int currentResult);
protected:
void paintEvent(QPaintEvent *event) override;
diff --git a/src/pdfwidgets/qpdfview_p.h b/src/pdfwidgets/qpdfview_p.h
index 97dc3de4f..37222ce8c 100644
--- a/src/pdfwidgets/qpdfview_p.h
+++ b/src/pdfwidgets/qpdfview_p.h
@@ -58,6 +58,7 @@ public:
QPdfView *q_ptr;
QPointer<QPdfDocument> m_document;
+ QPointer<QPdfSearchModel> m_searchModel;
QPdfPageNavigator* m_pageNavigator;
QPdfPageRenderer *m_pageRenderer;
QPdfLinkModel m_linkModel;
@@ -66,6 +67,8 @@ public:
QPdfView::ZoomMode m_zoomMode;
qreal m_zoomFactor;
+ int m_currentSearchResult = -1;
+
int m_pageSpacing;
QMargins m_documentMargins;