Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquickpdfsearchmodel.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include <QtCore/qloggingcategory.h>
6#include <QtPdf/private/qtpdfglobal_p.h>
7
8QT_BEGIN_NAMESPACE
9
10Q_PDF_LOGGING_CATEGORY(qLcSearch, "qt.pdf.search")
11
12/*!
13 \qmltype PdfSearchModel
14//! \nativetype QQuickPdfSearchModel
15 \inqmlmodule QtQuick.Pdf
16 \ingroup pdf
17 \brief A representation of text search results within a PDF Document.
18 \since 5.15
19
20 PdfSearchModel provides the ability to search for text strings within a
21 document and get the geometric locations of matches on each page.
22*/
23
24QQuickPdfSearchModel::QQuickPdfSearchModel(QObject *parent)
25 : QPdfSearchModel(parent)
26{
27 connect(this, &QPdfSearchModel::modelReset, this, [this]() {
28 // The previous results are gone, so none of them can be current anymore.
29 if (m_currentResult != 0) {
30 m_currentResult = 0;
31 emit currentResultChanged();
32 }
33 onResultsChanged();
34 });
35}
36
37/*!
38 \internal
39*/
40QQuickPdfSearchModel::~QQuickPdfSearchModel() = default;
41
42QQuickPdfDocument *QQuickPdfSearchModel::document() const
43{
44 return m_quickDocument;
45}
46
47void QQuickPdfSearchModel::setDocument(QQuickPdfDocument *document)
48{
49 if (document == m_quickDocument || !document)
50 return;
51
52 m_quickDocument = document;
53 QPdfSearchModel::setDocument(document->document());
54}
55
56/*!
57 \qmlproperty list<list<point>> PdfSearchModel::currentResultBoundingPolygons
58
59 A set of paths in a form that can be bound to the \c paths property of a
60 \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of
61 rectangles around the regions comprising the search result \l currentResult
62 on \l currentPage. This is normally used to highlight one search result
63 at a time, in a UI that allows stepping through the results:
64
65 \qml
66 PdfDocument {
67 id: doc
68 }
69 PdfSearchModel {
70 id: searchModel
71 document: doc
72 currentPage: view.currentPage
73 currentResult: ...
74 }
75 Shape {
76 ShapePath {
77 PathMultiline {
78 paths: searchModel.currentResultBoundingPolygons
79 }
80 }
81 }
82 \endqml
83
84 It becomes empty whenever \c {currentPage != currentResultLink.page}.
85
86 \sa PathMultiline
87*/
88QList<QPolygonF> QQuickPdfSearchModel::currentResultBoundingPolygons() const
89{
90 QList<QPolygonF> ret;
91 const auto result = currentResultLink();
92 if (result.page() != m_currentPage)
93 return ret;
94 for (auto rect : result.rectangles())
95 ret << QPolygonF(rect);
96 return ret;
97}
98
99/*!
100 \qmlproperty point PdfSearchModel::currentResultBoundingRect
101
102 The bounding box containing all \l currentResultBoundingPolygons,
103 if \c {currentPage == currentResultLink.page}; otherwise, an invalid rectangle.
104*/
105QRectF QQuickPdfSearchModel::currentResultBoundingRect() const
106{
107 QRectF ret;
108 const auto result = currentResultLink();
109 if (result.page() != m_currentPage)
110 return ret;
111 auto rects = result.rectangles();
112 if (!rects.isEmpty()) {
113 ret = rects.takeFirst();
114 for (auto rect : rects)
115 ret = ret.united(rect);
116 }
117 return ret;
118}
119
120void QQuickPdfSearchModel::onResultsChanged()
121{
122 emit currentPageBoundingPolygonsChanged();
123 emit currentResultLinkChanged();
124 emit currentResultBoundingPolygonsChanged();
125 emit currentResultBoundingRectChanged();
126}
127
128/*!
129 \qmlproperty list<list<point>> PdfSearchModel::currentPageBoundingPolygons
130
131 A set of paths in a form that can be bound to the \c paths property of a
132 \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of
133 rectangles around all the regions where search results are found on
134 \l currentPage:
135
136 \qml
137 PdfDocument {
138 id: doc
139 }
140 PdfSearchModel {
141 id: searchModel
142 document: doc
143 }
144 Shape {
145 ShapePath {
146 PathMultiline {
147 paths: searchModel.matchGeometry(view.currentPage)
148 }
149 }
150 }
151 \endqml
152
153 \sa PathMultiline
154*/
155QList<QPolygonF> QQuickPdfSearchModel::currentPageBoundingPolygons() const
156{
157 return const_cast<QQuickPdfSearchModel *>(this)->boundingPolygonsOnPage(m_currentPage);
158}
159
160/*!
161 \qmlmethod list<list<point>> PdfSearchModel::boundingPolygonsOnPage(int page)
162
163 Returns a set of paths in a form that can be bound to the \c paths property of a
164 \l {QtQuick::PathMultiline}{PathMultiline} instance, which is used to render a
165 batch of rectangles around all the matching locations on the \a page:
166
167 \qml
168 PdfDocument {
169 id: doc
170 }
171 PdfSearchModel {
172 id: searchModel
173 document: doc
174 }
175 Shape {
176 ShapePath {
177 PathMultiline {
178 paths: searchModel.matchGeometry(view.currentPage)
179 }
180 }
181 }
182 \endqml
183
184 \sa PathMultiline
185*/
186QList<QPolygonF> QQuickPdfSearchModel::boundingPolygonsOnPage(int page)
187{
188 if (!document() || searchString().isEmpty() || page < 0 || page > document()->document()->pageCount())
189 return {};
190
191 updatePage(page);
192
193 QList<QPolygonF> ret;
194 const auto m = QPdfSearchModel::resultsOnPage(page);
195 for (const auto &result : m) {
196 for (const auto &rect : result.rectangles())
197 ret << QPolygonF(rect);
198 }
199
200 return ret;
201}
202
203/*!
204 \qmlproperty int PdfSearchModel::currentPage
205
206 The page on which \l currentResultBoundingPolygons should provide filtered
207 search results.
208*/
209void QQuickPdfSearchModel::setCurrentPage(int currentPage)
210{
211 if (m_currentPage == currentPage || !document())
212 return;
213
214 const auto pageCount = document()->document()->pageCount();
215 if (currentPage < 0)
216 currentPage = pageCount - 1;
217 else if (currentPage >= pageCount)
218 currentPage = 0;
219
220 m_currentPage = currentPage;
221 if (!m_suspendSignals) {
222 emit currentPageChanged();
223 onResultsChanged();
224 }
225}
226
227/*!
228 \qmlproperty int PdfSearchModel::currentResult
229
230 The result index within the whole set of search results, for which
231 \l currentResultBoundingPolygons should provide the regions to highlight
232 if currentPage matches \c currentResultLink.page.
233
234 It is initially \c 0, and is reset to \c 0 whenever \l searchString changes.
235 Incrementing it goes to the next result; decrementing it from \c 0
236 wraps around to the last result, so that it changes to a positive number.
237*/
238void QQuickPdfSearchModel::setCurrentResult(int currentResult)
239{
240 if (m_currentResult == currentResult)
241 return;
242
243 const int currentResultWas = m_currentResult;
244 const int currentPageWas = m_currentPage;
245 const int resultCount = rowCount({});
246
247 // wrap around at the ends
248 if (currentResult >= resultCount) {
249 currentResult = 0;
250 } else if (currentResult < 0) {
251 currentResult = resultCount - 1;
252 }
253
254 const QPdfLink link = resultAtIndex(currentResult);
255 if (link.isValid()) {
256 setCurrentPage(link.page());
257 m_currentResult = currentResult;
258 emit currentResultChanged();
259 emit currentResultLinkChanged();
260 emit currentResultBoundingPolygonsChanged();
261 emit currentResultBoundingRectChanged();
262 qCDebug(qLcSearch) << "currentResult was" << currentResultWas
263 << "requested" << currentResult << "on page" << currentPageWas
264 << "->" << m_currentResult << "on page" << m_currentPage;
265 } else {
266 qWarning() << "failed to find result" << currentResult << "in range 0 ->" << resultCount;
267 }
268}
269
270/*!
271 \qmlproperty QPdfLink PdfSearchModel::currentResultLink
272
273 The result at index \l currentResult.
274*/
275QPdfLink QQuickPdfSearchModel::currentResultLink() const
276{
277 return resultAtIndex(m_currentResult);
278}
279
280/*!
281 \qmlproperty string PdfSearchModel::searchString
282
283 The string to search for.
284*/
285
286/*!
287 \since 6.8
288 \qmlproperty int PdfSearchModel::count
289
290 The number of search results found.
291*/
292
293QT_END_NAMESPACE
294
295#include "moc_qquickpdfsearchmodel_p.cpp"