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
qhelpindexwidget.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
7#include "qhelplink.h"
8
9#if QT_CONFIG(future)
10#include <QtCore/qfuturewatcher.h>
11#endif
12
14
16{
17#if QT_CONFIG(future)
19
20 struct WatcherDeleter
21 {
24 watcher->cancel();
26 delete watcher;
27 }
28 };
29#endif
30
31public:
32#if QT_CONFIG(future)
34#endif
35
36 QHelpIndexModel *q = nullptr;
37 QHelpEngineCore *helpEngine = nullptr;
39#if QT_CONFIG(future)
41#endif
42};
43
44#if QT_CONFIG(future)
45void QHelpIndexModelPrivate::createIndex(const FutureProvider &futureProvider)
46{
47 const bool wasRunning = bool(watcher);
48 watcher.reset(new QFutureWatcher<QStringList>);
49 QObject::connect(watcher.get(), &QFutureWatcherBase::finished, q, [this] {
50 if (!watcher->isCanceled()) {
51 indices = watcher->result();
52 q->filter({});
53 }
54 watcher.release()->deleteLater();
55 emit q->indexCreated();
56 });
57 watcher->setFuture(futureProvider());
58
59 if (wasRunning)
60 return;
61
62 indices.clear();
63 q->filter({});
64 emit q->indexCreationStarted();
65}
66#endif
67
68/*!
69 \class QHelpIndexModel
70 \since 4.4
71 \inmodule QtHelp
72 \brief The QHelpIndexModel class provides a model that
73 supplies index keywords to views.
74*/
75
76/*!
77 \fn void QHelpIndexModel::indexCreationStarted()
78
79 This signal is emitted when the creation of a new index
80 has started. The current index is invalid from this
81 point on until the signal indexCreated() is emitted.
82
83 \sa isCreatingIndex()
84*/
85
86/*!
87 \fn void QHelpIndexModel::indexCreated()
88
89 This signal is emitted when the index has been created.
90*/
91
92QHelpIndexModel::QHelpIndexModel(QHelpEngineCore *helpEngine)
93 : QStringListModel(helpEngine)
94 , d(new QHelpIndexModelPrivate{this, helpEngine})
95{}
96
97QHelpIndexModel::~QHelpIndexModel()
98{
99 delete d;
100}
101
102/*!
103 \since 6.8
104
105 Creates a new index by querying the help system for keywords for the current filter.
106*/
107void QHelpIndexModel::createIndexForCurrentFilter()
108{
109#if QT_CONFIG(future)
110 d->createIndex([this] { return d->helpEngine->requestIndexForCurrentFilter(); });
111#endif
112}
113
114/*!
115 Creates a new index by querying the help system for
116 keywords for the specified custom \a filter name.
117*/
118void QHelpIndexModel::createIndex(const QString &filter)
119{
120#if QT_CONFIG(future)
121 d->createIndex([this, filter] { return d->helpEngine->requestIndex(filter); });
122#endif
123}
124
125// TODO: Remove me
126void QHelpIndexModel::insertIndices()
127{}
128
129/*!
130 Returns true if the index is currently built up, otherwise
131 false.
132*/
133bool QHelpIndexModel::isCreatingIndex() const
134{
135#if QT_CONFIG(future)
136 return bool(d->watcher);
137#else
138 return false;
139#endif
140}
141
142/*!
143 \since 5.15
144
145 Returns the associated help engine that manages this model.
146*/
147QHelpEngineCore *QHelpIndexModel::helpEngine() const
148{
149 return d->helpEngine;
150}
151
152/*!
153 Filters the indices and returns the model index of the best
154 matching keyword. In a first step, only the keywords containing
155 \a filter are kept in the model's index list. Analogously, if
156 \a wildcard is not empty, only the keywords matched are left
157 in the index list. In a second step, the best match is
158 determined and its index model returned. When specifying a
159 wildcard expression, the \a filter string is used to
160 search for the best match.
161*/
162QModelIndex QHelpIndexModel::filter(const QString &filter, const QString &wildcard)
163{
164 if (filter.isEmpty()) {
165 setStringList(d->indices);
166 return index(-1, 0, {});
167 }
168
169 using Checker = std::function<bool(const QString &)>;
170 const auto checkIndices = [this, filter](const Checker &checker) {
171 QStringList filteredList;
172 int goodMatch = -1;
173 int perfectMatch = -1;
174 for (const QString &index : std::as_const(d->indices)) {
175 if (checker(index)) {
176 filteredList.append(index);
177 if (perfectMatch == -1 && index.startsWith(filter, Qt::CaseInsensitive)) {
178 if (goodMatch == -1)
179 goodMatch = filteredList.size() - 1;
180 if (filter.size() == index.size())
181 perfectMatch = filteredList.size() - 1;
182 } else if (perfectMatch > -1 && index == filter) {
183 perfectMatch = filteredList.size() - 1;
184 }
185 }
186 }
187 setStringList(filteredList);
188 return perfectMatch >= 0 ? perfectMatch : qMax(0, goodMatch);
189 };
190
191 int perfectMatch = -1;
192 if (!wildcard.isEmpty()) {
193 const auto re = QRegularExpression::wildcardToRegularExpression(wildcard,
194 QRegularExpression::UnanchoredWildcardConversion);
195 const QRegularExpression regExp(re, QRegularExpression::CaseInsensitiveOption);
196 perfectMatch = checkIndices([regExp](const QString &index) {
197 return index.contains(regExp);
198 });
199 } else {
200 perfectMatch = checkIndices([filter](const QString &index) {
201 return index.contains(filter, Qt::CaseInsensitive);
202 });
203 }
204 return index(perfectMatch, 0, {});
205}
206
207/*!
208 \class QHelpIndexWidget
209 \inmodule QtHelp
210 \since 4.4
211 \brief The QHelpIndexWidget class provides a list view
212 displaying the QHelpIndexModel.
213*/
214
215/*!
216 \fn void QHelpIndexWidget::linkActivated(const QUrl &link,
217 const QString &keyword)
218
219 \deprecated
220
221 Use documentActivated() instead.
222
223 This signal is emitted when an item is activated and its
224 associated \a link should be shown. To know where the link
225 belongs to, the \a keyword is given as a second parameter.
226*/
227
228/*!
229 \fn void QHelpIndexWidget::documentActivated(const QHelpLink &document,
230 const QString &keyword)
231
232 \since 5.15
233
234 This signal is emitted when an item is activated and its
235 associated \a document should be shown. To know where the link
236 belongs to, the \a keyword is given as a second parameter.
237*/
238
239/*!
240 \fn void QHelpIndexWidget::documentsActivated(const QList<QHelpLink> &documents,
241 const QString &keyword)
242
243 \since 5.15
244
245 This signal is emitted when the item representing the \a keyword
246 is activated and the item has more than one document associated.
247 The \a documents consist of the document titles and their URLs.
248*/
249
250QHelpIndexWidget::QHelpIndexWidget()
251{
252 setEditTriggers(QAbstractItemView::NoEditTriggers);
253 setUniformItemSizes(true);
254 connect(this, &QAbstractItemView::activated, this, &QHelpIndexWidget::showLink);
255}
256
257void QHelpIndexWidget::showLink(const QModelIndex &index)
258{
259 if (!index.isValid())
260 return;
261
262 QHelpIndexModel *indexModel = qobject_cast<QHelpIndexModel*>(model());
263 if (!indexModel)
264 return;
265
266 const QVariant &v = indexModel->data(index, Qt::DisplayRole);
267 const QString name = v.isValid() ? v.toString() : QString();
268
269 const QList<QHelpLink> &docs = indexModel->helpEngine()->documentsForKeyword(name);
270 if (docs.size() > 1) {
271 emit documentsActivated(docs, name);
272#if QT_DEPRECATED_SINCE(5, 15)
273 QT_WARNING_PUSH
274 QT_WARNING_DISABLE_DEPRECATED
275 QMultiMap<QString, QUrl> links;
276 for (const auto &doc : docs)
277 links.insert(doc.title, doc.url);
278 emit linksActivated(links, name);
279 QT_WARNING_POP
280#endif
281 } else if (!docs.isEmpty()) {
282 emit documentActivated(docs.first(), name);
283#if QT_DEPRECATED_SINCE(5, 15)
284 QT_WARNING_PUSH
285 QT_WARNING_DISABLE_DEPRECATED
286 emit linkActivated(docs.first().url, name);
287 QT_WARNING_POP
288#endif
289 }
290}
291
292/*!
293 Activates the current item which will result eventually in
294 the emitting of a linkActivated() or linksActivated()
295 signal.
296*/
297void QHelpIndexWidget::activateCurrentItem()
298{
299 showLink(currentIndex());
300}
301
302/*!
303 Filters the indices according to \a filter or \a wildcard.
304 The item with the best match is set as current item.
305
306 \sa QHelpIndexModel::filter()
307*/
308void QHelpIndexWidget::filterIndices(const QString &filter, const QString &wildcard)
309{
310 QHelpIndexModel *indexModel = qobject_cast<QHelpIndexModel *>(model());
311 if (!indexModel)
312 return;
313 const QModelIndex &idx = indexModel->filter(filter, wildcard);
314 if (idx.isValid())
315 setCurrentIndex(idx);
316}
317
318QT_END_NAMESPACE
QHelpEngineCore * helpEngine
Combined button and popup list for selecting options.