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
qhelpsearchresultwidget.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
5
6#include <QtCore/qcoreevent.h>
7#include <QtCore/qlist.h>
8#include <QtCore/qpointer.h>
9#include <QtCore/qtextstream.h>
10#include <QtWidgets/qlabel.h>
11#include <QtWidgets/qlayout.h>
12#include <QtWidgets/qlayoutitem.h>
13#include <QtWidgets/qtoolbutton.h>
14#include <QtWidgets/qtextbrowser.h>
15
17
18static constexpr int ResultsRange = 20;
19
21{
22 Q_OBJECT
23 Q_PROPERTY(QColor linkColor READ linkColor WRITE setLinkColor)
24
25public:
33
34 QColor linkColor() const { return m_linkColor; }
36 {
38 const QString sheet = QString::fromLatin1("a { text-decoration: underline; color: %1 }")
41 }
42
44 {
47 str << "<html><head><title>" << tr("Search Results") << "</title></head><body>";
48
49 const int count = results.size();
50 if (count != 0) {
51 if (isIndexing) {
52 str << "<div style=\"text-align:left;"
53 " font-weight:bold; color:red\">" << tr("Note:")
54 << "&nbsp;<span style=\"font-weight:normal; color:black\">"
55 << tr("The search results may not be complete since the "
56 "documentation is still being indexed.")
57 << "</span></div></div><br>";
58 }
59
60 for (const QHelpSearchResult &result : results) {
61 str << "<div style=\"text-align:left\"><a href=\""
62 << result.url().toString() << "\">"
63 << result.title() << "</a></div>"
64 "<div style =\"margin:5px\">" << result.snippet() << "</div>";
65 }
66 } else {
67 str << "<div align=\"center\"><br><br><h2>"
68 << tr("Your search did not match any documents.")
69 << "</h2><div>";
70 if (isIndexing) {
71 str << "<div align=\"center\"><h3>"
72 << tr("(The reason for this might be that the documentation "
73 "is still being indexed.)") << "</h3><div>";
74 }
75 }
76
77 str << "</body></html>";
79 }
80
82 void requestShowLink(const QUrl &url);
83
84private slots:
85 void doSetSource(const QUrl & /*name*/, QTextDocument::ResourceType /*type*/) override {}
86
87private:
89};
90
92{
93public:
95 {
96 delete searchEngine; // TODO: This it probably wrong, why the widget owns the engine?
97 }
98
99 QToolButton* setupToolButton(const QString &iconPath)
100 {
101 QToolButton *button = new QToolButton;
102 button->setEnabled(false);
103 button->setAutoRaise(true);
104 button->setIcon(QIcon(iconPath));
105 button->setIconSize({12, 12});
106 button->setMaximumSize({16, 16});
107 return button;
108 }
109
111 {
112 int last = 0;
113 int first = 0;
114 int count = 0;
115
116 if (!searchEngine.isNull()) {
117 count = searchEngine->searchResultCount();
118 if (count > 0) {
119 last = qMin(resultFirstToShow + ResultsRange, count);
120 first = resultFirstToShow + 1;
121 }
122 resultTextBrowser->showResultPage(searchEngine->searchResults(resultFirstToShow, last),
123 isIndexing);
124 }
125
126 hitsLabel->setText(QHelpSearchResultWidget::tr("%1 - %2 of %n Hits", nullptr, count)
127 .arg(first).arg(last));
128 firstResultPage->setEnabled(resultFirstToShow);
129 previousResultPage->setEnabled(resultFirstToShow);
130 lastResultPage->setEnabled(count - last);
131 nextResultPage->setEnabled(count - last);
132 }
133
136
138
143 QLabel *hitsLabel = nullptr;
145 bool isIndexing = false;
146};
147
148/*!
149 \class QHelpSearchResultWidget
150 \since 4.4
151 \inmodule QtHelp
152 \brief The QHelpSearchResultWidget class provides a text browser to display
153 search results.
154*/
155
156/*!
157 \fn void QHelpSearchResultWidget::requestShowLink(const QUrl &link)
158
159 This signal is emitted when a item is activated and its associated
160 \a link should be shown.
161*/
162
163QHelpSearchResultWidget::QHelpSearchResultWidget(QHelpSearchEngine *engine)
164 : QWidget(0)
165 , d(new QHelpSearchResultWidgetPrivate)
166{
167 d->q = this;
168 d->searchEngine = engine;
169
170 connect(engine, &QHelpSearchEngine::indexingStarted, this, [this] { d->isIndexing = true; });
171 connect(engine, &QHelpSearchEngine::indexingFinished, this, [this] { d->isIndexing = false; });
172
173 QVBoxLayout *vLayout = new QVBoxLayout(this);
174 vLayout->setContentsMargins({});
175 vLayout->setSpacing(0);
176
177 QHBoxLayout *hBoxLayout = new QHBoxLayout();
178#ifndef Q_OS_MAC
179 hBoxLayout->setContentsMargins({});
180 hBoxLayout->setSpacing(0);
181#endif
182 hBoxLayout->addWidget(d->firstResultPage = d->setupToolButton(
183 QString::fromUtf8(":/qt-project.org/assistant/images/3leftarrow.png")));
184
185 hBoxLayout->addWidget(d->previousResultPage = d->setupToolButton(
186 QString::fromUtf8(":/qt-project.org/assistant/images/1leftarrow.png")));
187
188 d->hitsLabel = new QLabel(tr("0 - 0 of 0 Hits"), this);
189 hBoxLayout->addWidget(d->hitsLabel);
190 d->hitsLabel->setAlignment(Qt::AlignCenter);
191 d->hitsLabel->setMinimumSize(QSize(150, d->hitsLabel->height()));
192
193 hBoxLayout->addWidget(d->nextResultPage = d->setupToolButton(
194 QString::fromUtf8(":/qt-project.org/assistant/images/1rightarrow.png")));
195
196 hBoxLayout->addWidget(d->lastResultPage = d->setupToolButton(
197 QString::fromUtf8(":/qt-project.org/assistant/images/3rightarrow.png")));
198
199 QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
200 hBoxLayout->addItem(spacer);
201
202 vLayout->addLayout(hBoxLayout);
203
204 d->resultTextBrowser = new QResultWidget(this);
205 vLayout->addWidget(d->resultTextBrowser);
206
207 connect(d->resultTextBrowser, &QResultWidget::requestShowLink,
208 this, &QHelpSearchResultWidget::requestShowLink);
209
210 connect(d->nextResultPage, &QAbstractButton::clicked, this, [this] {
211 if (!d->searchEngine.isNull()
212 && d->resultFirstToShow + ResultsRange < d->searchEngine->searchResultCount()) {
213 d->resultFirstToShow += ResultsRange;
214 }
215 d->updateHitRange();
216 });
217 connect(d->previousResultPage, &QAbstractButton::clicked, this, [this] {
218 if (!d->searchEngine.isNull()) {
219 d->resultFirstToShow -= ResultsRange;
220 if (d->resultFirstToShow < 0)
221 d->resultFirstToShow = 0;
222 }
223 d->updateHitRange();
224 });
225 connect(d->lastResultPage, &QAbstractButton::clicked, this, [this] {
226 if (!d->searchEngine.isNull())
227 d->resultFirstToShow = (d->searchEngine->searchResultCount() - 1) / ResultsRange * ResultsRange;
228 d->updateHitRange();
229 });
230 const auto showFirstPage = [this] {
231 if (!d->searchEngine.isNull())
232 d->resultFirstToShow = 0;
233 d->updateHitRange();
234 };
235 connect(d->firstResultPage, &QAbstractButton::clicked, this, showFirstPage);
236 connect(engine, &QHelpSearchEngine::searchingFinished, this, showFirstPage);
237}
238
239/*! \reimp
240*/
241void QHelpSearchResultWidget::changeEvent(QEvent *event)
242{
243 if (event->type() == QEvent::LanguageChange)
244 d->updateHitRange();
245}
246
247/*!
248 Destroys the search result widget.
249*/
250QHelpSearchResultWidget::~QHelpSearchResultWidget()
251{
252 delete d;
253}
254
255/*!
256 Returns a reference of the URL that the item at \a point owns, or an
257 empty URL if no item exists at that point.
258*/
259QUrl QHelpSearchResultWidget::linkAt(const QPoint &point)
260{
261 if (d->resultTextBrowser)
262 return d->resultTextBrowser->anchorAt(point);
263 return {};
264}
265
266QT_END_NAMESPACE
267
268#include "qhelpsearchresultwidget.moc"
QToolButton * setupToolButton(const QString &iconPath)
QPointer< QHelpSearchEngine > searchEngine
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE constexpr int ResultsRange