1 | // Copyright (C) 2016 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 | |
4 | #include "qhelpsearchengine.h" |
5 | #include "qhelpenginecore.h" |
6 | #include "qhelpsearchenginecore.h" |
7 | #include "qhelpsearchquerywidget.h" |
8 | #include "qhelpsearchresultwidget.h" |
9 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | class QHelpSearchEnginePrivate |
13 | { |
14 | public: |
15 | QHelpSearchEngineCore m_searchEngine; |
16 | QHelpSearchQueryWidget *queryWidget = nullptr; |
17 | QHelpSearchResultWidget *resultWidget = nullptr; |
18 | }; |
19 | |
20 | /*! |
21 | \class QHelpSearchQuery |
22 | \deprecated |
23 | \since 4.4 |
24 | \inmodule QtHelp |
25 | \brief The QHelpSearchQuery class contains the field name and the associated |
26 | search term. |
27 | |
28 | The QHelpSearchQuery class contains the field name and the associated search |
29 | term. Depending on the field the search term might get split up into separate |
30 | terms to be parsed differently by the search engine. |
31 | |
32 | \note This class has been deprecated in favor of QString. |
33 | |
34 | \sa QHelpSearchQueryWidget |
35 | */ |
36 | |
37 | /*! |
38 | \fn QHelpSearchQuery::QHelpSearchQuery() |
39 | |
40 | Constructs a new empty QHelpSearchQuery. |
41 | */ |
42 | |
43 | /*! |
44 | \fn QHelpSearchQuery::QHelpSearchQuery(FieldName field, const QStringList &wordList) |
45 | |
46 | Constructs a new QHelpSearchQuery and initializes it with the given \a field and \a wordList. |
47 | */ |
48 | |
49 | /*! |
50 | \enum QHelpSearchQuery::FieldName |
51 | This enum type specifies the field names that are handled by the search engine. |
52 | |
53 | \value DEFAULT the default field provided by the search widget, several terms should be |
54 | split and stored in the word list except search terms enclosed in quotes. |
55 | \value FUZZY \deprecated Terms should be split in separate |
56 | words and passed to the search engine. |
57 | \value WITHOUT \deprecated Terms should be split in separate |
58 | words and passed to the search engine. |
59 | \value PHRASE \deprecated Terms should not be split in separate words. |
60 | \value ALL \deprecated Terms should be split in separate |
61 | words and passed to the search engine |
62 | \value ATLEAST \deprecated Terms should be split in separate |
63 | words and passed to the search engine |
64 | */ |
65 | |
66 | /*! |
67 | \class QHelpSearchEngine |
68 | \since 4.4 |
69 | \inmodule QtHelp |
70 | \brief The QHelpSearchEngine class provides access to widgets reusable |
71 | to integrate fulltext search as well as to index and search documentation. |
72 | |
73 | Before the search engine can be used, one has to instantiate at least a |
74 | QHelpEngineCore object that needs to be passed to the search engines constructor. |
75 | This is required as the search engine needs to be connected to the help |
76 | engines setupFinished() signal to know when it can start to index documentation. |
77 | |
78 | After starting the indexing process the signal indexingStarted() is emitted and |
79 | on the end of the indexing process the indexingFinished() is emitted. To stop |
80 | the indexing one can call cancelIndexing(). |
81 | |
82 | When the indexing process has finished, the search engine can be used to |
83 | search through the index for a given term using the search() function. When |
84 | the search input is passed to the search engine, the searchingStarted() |
85 | signal is emitted. When the search finishes, the searchingFinished() signal |
86 | is emitted. The search process can be stopped by calling cancelSearching(). |
87 | |
88 | If the search succeeds, searchingFinished() is called with the search result |
89 | count to fetch the search results from the search engine. Calling the |
90 | searchResults() function with a range returns a list of QHelpSearchResult |
91 | objects within the range. The results consist of the document title and URL, |
92 | as well as a snippet from the document that contains the best match for the |
93 | search input. |
94 | |
95 | To display the given search results use the QHelpSearchResultWidget or build up your own one if you need |
96 | more advanced functionality. Note that the QHelpSearchResultWidget can not be instantiated |
97 | directly, you must retrieve the widget from the search engine in use as all connections will be |
98 | established for you by the widget itself. |
99 | */ |
100 | |
101 | /*! |
102 | \fn void QHelpSearchEngine::indexingStarted() |
103 | |
104 | This signal is emitted when indexing process is started. |
105 | */ |
106 | |
107 | /*! |
108 | \fn void QHelpSearchEngine::indexingFinished() |
109 | |
110 | This signal is emitted when the indexing process is complete. |
111 | */ |
112 | |
113 | /*! |
114 | \fn void QHelpSearchEngine::searchingStarted() |
115 | |
116 | This signal is emitted when the search process is started. |
117 | */ |
118 | |
119 | /*! |
120 | \fn void QHelpSearchEngine::searchingFinished(int searchResultCount) |
121 | |
122 | This signal is emitted when the search process is complete. |
123 | The search result count is stored in \a searchResultCount. |
124 | */ |
125 | |
126 | /*! |
127 | Constructs a new search engine with the given \a parent. The search engine |
128 | uses the given \a helpEngine to access the documentation that needs to be indexed. |
129 | The QHelpEngine's setupFinished() signal is automatically connected to the |
130 | QHelpSearchEngine's indexing function, so that new documentation will be indexed |
131 | after the signal is emitted. |
132 | */ |
133 | QHelpSearchEngine::QHelpSearchEngine(QHelpEngineCore *helpEngine, QObject *parent) |
134 | : QObject(parent) |
135 | , d(new QHelpSearchEnginePrivate{.m_searchEngine: QHelpSearchEngineCore(helpEngine)}) |
136 | { |
137 | connect(sender: &d->m_searchEngine, signal: &QHelpSearchEngineCore::indexingStarted, |
138 | context: this, slot: &QHelpSearchEngine::indexingStarted); |
139 | connect(sender: &d->m_searchEngine, signal: &QHelpSearchEngineCore::indexingFinished, |
140 | context: this, slot: &QHelpSearchEngine::indexingFinished); |
141 | connect(sender: &d->m_searchEngine, signal: &QHelpSearchEngineCore::searchingStarted, |
142 | context: this, slot: &QHelpSearchEngine::searchingStarted); |
143 | connect(sender: &d->m_searchEngine, signal: &QHelpSearchEngineCore::searchingFinished, |
144 | context: this, slot: [this] { emit searchingFinished(searchResultCount: d->m_searchEngine.searchResultCount()); }); |
145 | } |
146 | |
147 | /*! |
148 | Destructs the search engine. |
149 | */ |
150 | QHelpSearchEngine::~QHelpSearchEngine() |
151 | { |
152 | delete d; |
153 | } |
154 | |
155 | /*! |
156 | Returns a widget to use as input widget. Depending on your search engine |
157 | configuration you will get a different widget with more or less subwidgets. |
158 | */ |
159 | QHelpSearchQueryWidget* QHelpSearchEngine::queryWidget() |
160 | { |
161 | if (!d->queryWidget) |
162 | d->queryWidget = new QHelpSearchQueryWidget(); |
163 | return d->queryWidget; |
164 | } |
165 | |
166 | /*! |
167 | Returns a widget that can hold and display the search results. |
168 | */ |
169 | QHelpSearchResultWidget* QHelpSearchEngine::resultWidget() |
170 | { |
171 | if (!d->resultWidget) |
172 | d->resultWidget = new QHelpSearchResultWidget(this); |
173 | return d->resultWidget; |
174 | } |
175 | |
176 | #if QT_DEPRECATED_SINCE(5, 9) |
177 | /*! |
178 | \deprecated |
179 | Use searchResultCount() instead. |
180 | */ |
181 | int QHelpSearchEngine::hitsCount() const |
182 | { |
183 | return searchResultCount(); |
184 | } |
185 | |
186 | /*! |
187 | \since 4.6 |
188 | \deprecated |
189 | Use searchResultCount() instead. |
190 | */ |
191 | int QHelpSearchEngine::hitCount() const |
192 | { |
193 | return searchResultCount(); |
194 | } |
195 | #endif // QT_DEPRECATED_SINCE(5, 9) |
196 | |
197 | /*! |
198 | \since 5.9 |
199 | Returns the number of results the search engine found. |
200 | */ |
201 | int QHelpSearchEngine::searchResultCount() const |
202 | { |
203 | return d->m_searchEngine.searchResultCount(); |
204 | } |
205 | |
206 | #if QT_DEPRECATED_SINCE(5, 9) |
207 | /*! |
208 | \typedef QHelpSearchEngine::SearchHit |
209 | \deprecated |
210 | |
211 | Use QHelpSearchResult instead. |
212 | |
213 | Typedef for QPair<QString, QString>. |
214 | The values of that pair are the documentation file path and the page title. |
215 | |
216 | \sa hits() |
217 | */ |
218 | |
219 | /*! |
220 | \deprecated |
221 | Use searchResults() instead. |
222 | */ |
223 | QList<QHelpSearchEngine::SearchHit> QHelpSearchEngine::hits(int start, int end) const |
224 | { |
225 | QList<QHelpSearchEngine::SearchHit> hits; |
226 | for (const QHelpSearchResult &result : searchResults(start, end)) |
227 | hits.append(t: qMakePair(value1: result.url().toString(), value2: result.title())); |
228 | return hits; |
229 | } |
230 | #endif // QT_DEPRECATED_SINCE(5, 9) |
231 | |
232 | /*! |
233 | \since 5.9 |
234 | Returns a list of search results within the range from the index |
235 | specified by \a start to the index specified by \a end. |
236 | */ |
237 | QList<QHelpSearchResult> QHelpSearchEngine::searchResults(int start, int end) const |
238 | { |
239 | return d->m_searchEngine.searchResults(start, end); |
240 | } |
241 | |
242 | /*! |
243 | \since 5.9 |
244 | Returns the phrase that was last searched for. |
245 | */ |
246 | QString QHelpSearchEngine::searchInput() const |
247 | { |
248 | return d->m_searchEngine.searchInput(); |
249 | } |
250 | |
251 | #if QT_DEPRECATED_SINCE(5, 9) |
252 | QT_WARNING_PUSH |
253 | QT_WARNING_DISABLE_DEPRECATED |
254 | /*! |
255 | \deprecated |
256 | \since 4.5 |
257 | Use searchInput() instead. |
258 | */ |
259 | QList<QHelpSearchQuery> QHelpSearchEngine::query() const |
260 | { |
261 | return {{QHelpSearchQuery::DEFAULT, searchInput().split(sep: QChar::Space)}}; |
262 | } |
263 | QT_WARNING_POP |
264 | #endif // QT_DEPRECATED_SINCE(5, 9) |
265 | |
266 | /*! |
267 | Forces the search engine to reindex all documentation files. |
268 | */ |
269 | void QHelpSearchEngine::reindexDocumentation() |
270 | { |
271 | d->m_searchEngine.reindexDocumentation(); |
272 | } |
273 | |
274 | /*! |
275 | Stops the indexing process. |
276 | */ |
277 | void QHelpSearchEngine::cancelIndexing() |
278 | { |
279 | d->m_searchEngine.cancelIndexing(); |
280 | } |
281 | |
282 | /*! |
283 | Stops the search process. |
284 | */ |
285 | void QHelpSearchEngine::cancelSearching() |
286 | { |
287 | d->m_searchEngine.cancelSearching(); |
288 | } |
289 | |
290 | /*! |
291 | \since 5.9 |
292 | Starts the search process using the given search phrase \a searchInput. |
293 | |
294 | The phrase may consist of several words. By default, the search engine returns |
295 | the list of documents that contain all the specified words. |
296 | The phrase may contain any combination of the logical operators AND, OR, and |
297 | NOT. The operator must be written in all capital letters, otherwise it will |
298 | be considered a part of the search phrase. |
299 | |
300 | If double quotation marks are used to group the words, |
301 | the search engine will search for an exact match of the quoted phrase. |
302 | |
303 | For more information about the text query syntax, |
304 | see \l {https://sqlite.org/fts5.html#full_text_query_syntax} |
305 | {SQLite FTS5 Extension}. |
306 | */ |
307 | void QHelpSearchEngine::search(const QString &searchInput) |
308 | { |
309 | d->m_searchEngine.search(searchInput); |
310 | } |
311 | |
312 | #if QT_DEPRECATED_SINCE(5, 9) |
313 | /*! |
314 | \deprecated |
315 | Use search(const QString &searchInput) instead. |
316 | */ |
317 | void QHelpSearchEngine::search(const QList<QHelpSearchQuery> &queryList) |
318 | { |
319 | if (queryList.isEmpty()) |
320 | return; |
321 | |
322 | d->m_searchEngine.search(searchInput: queryList.first().wordList.join(sep: QChar::Space)); |
323 | } |
324 | #endif // QT_DEPRECATED_SINCE(5, 9) |
325 | |
326 | /*! |
327 | \internal |
328 | */ |
329 | void QHelpSearchEngine::scheduleIndexDocumentation() |
330 | { |
331 | d->m_searchEngine.scheduleIndexDocumentation(); |
332 | } |
333 | |
334 | // TODO: Deprecate me (but it's private???) |
335 | void QHelpSearchEngine::indexDocumentation() |
336 | {} |
337 | |
338 | QT_END_NAMESPACE |
339 | |