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