source: trunk/tools/assistant/lib/qhelpsearchresultwidget.cpp@ 315

Last change on this file since 315 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 13.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the Qt Assistant of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qhelpsearchresultwidget.h"
43
44#include <QtCore/QList>
45#include <QtCore/QString>
46#include <QtCore/QPointer>
47#include <QtCore/QStringList>
48
49#include <QtGui/QLabel>
50#include <QtGui/QLayout>
51#include <QtGui/QMouseEvent>
52#include <QtGui/QHeaderView>
53#include <QtGui/QSpacerItem>
54#include <QtGui/QToolButton>
55#include <QtGui/QTreeWidget>
56#include <QtGui/QTextBrowser>
57#include <QtGui/QTreeWidgetItem>
58
59QT_BEGIN_NAMESPACE
60
61class QDefaultResultWidget : public QTreeWidget
62{
63 Q_OBJECT
64
65public:
66 QDefaultResultWidget(QWidget *parent = 0)
67 : QTreeWidget(parent)
68 {
69 header()->hide();
70 connect(this, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
71 this, SLOT(itemActivated(QTreeWidgetItem*, int)));
72 }
73
74 void showResultPage(const QList<QHelpSearchEngine::SearchHit> hits)
75 {
76 foreach (const QHelpSearchEngine::SearchHit hit, hits)
77 new QTreeWidgetItem(this, QStringList(hit.first) << hit.second);
78 }
79
80signals:
81 void requestShowLink(const QUrl &url);
82
83private slots:
84 void itemActivated(QTreeWidgetItem *item, int /* column */)
85 {
86 if (item) {
87 QString data = item->data(1, Qt::DisplayRole).toString();
88 emit requestShowLink(data);
89 }
90 }
91};
92
93
94class QCLuceneResultWidget : public QTextBrowser
95{
96 Q_OBJECT
97
98public:
99 QCLuceneResultWidget(QWidget *parent = 0)
100 : QTextBrowser(parent)
101 {
102 connect(this, SIGNAL(anchorClicked(const QUrl&)),
103 this, SIGNAL(requestShowLink(const QUrl&)));
104 setContextMenuPolicy(Qt::NoContextMenu);
105 }
106
107 void showResultPage(const QList<QHelpSearchEngine::SearchHit> hits, bool isIndexing)
108 {
109 QString htmlFile = QString(QLatin1String("<html><head><title>%1</title></head><body>"))
110 .arg(tr("Search Results"));
111
112 int count = hits.count();
113 if (count != 0) {
114 if (isIndexing)
115 htmlFile += QString(QLatin1String("<div style=\"text-align:left; font-weight:bold; color:red\">"
116 "%1&nbsp;<span style=\"font-weight:normal; color:black\">"
117 "%2</span></div></div><br>")).arg(tr("Note:"))
118 .arg(tr("The search results may not be complete since the "
119 "documentation is still being indexed!"));
120
121 foreach (const QHelpSearchEngine::SearchHit hit, hits) {
122 htmlFile += QString(QLatin1String("<div style=\"text-align:left; font-weight:bold\""
123 "><a href=\"%1\">%2</a><div style=\"color:green; font-weight:normal;"
124 " margin:5px\">%1</div></div><p></p>"))
125 .arg(hit.first).arg(hit.second);
126 }
127 } else {
128 htmlFile += QLatin1String("<div align=\"center\"><br><br><h2>")
129 + tr("Your search did not match any documents.")
130 + QLatin1String("</h2><div>");
131 if (isIndexing)
132 htmlFile += QLatin1String("<div align=\"center\"><h3>")
133 + tr("(The reason for this might be that the documentation "
134 "is still being indexed.)")
135 + QLatin1String("</h3><div>");
136 }
137
138 htmlFile += QLatin1String("</body></html>");
139
140 setHtml(htmlFile);
141 }
142
143signals:
144 void requestShowLink(const QUrl &url);
145
146private slots:
147 void setSource(const QUrl & /* name */) {}
148};
149
150
151class QHelpSearchResultWidgetPrivate : public QObject
152{
153 Q_OBJECT
154
155private slots:
156 void setResults(int hitsCount)
157 {
158 if (!searchEngine.isNull()) {
159#if defined(QT_CLUCENE_SUPPORT)
160 showFirstResultPage();
161 updateNextButtonState(((hitsCount > 20) ? true : false));
162#else
163 resultTreeWidget->clear();
164 resultTreeWidget->showResultPage(searchEngine->hits(0, hitsCount));
165#endif
166 }
167 }
168
169 void showNextResultPage()
170 {
171 if (!searchEngine.isNull()
172 && resultLastToShow < searchEngine->hitsCount()) {
173 resultLastToShow += 20;
174 resultFirstToShow += 20;
175
176 resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow,
177 resultLastToShow), isIndexing);
178 if (resultLastToShow >= searchEngine->hitsCount())
179 updateNextButtonState(false);
180 }
181 updateHitRange();
182 }
183
184 void showLastResultPage()
185 {
186 if (!searchEngine.isNull()) {
187 resultLastToShow = searchEngine->hitsCount();
188 resultFirstToShow = resultLastToShow - (resultLastToShow % 20);
189
190 if (resultFirstToShow == resultLastToShow)
191 resultFirstToShow -= 20;
192
193 resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow,
194 resultLastToShow), isIndexing);
195 updateNextButtonState(false);
196 }
197 updateHitRange();
198 }
199
200 void showFirstResultPage()
201 {
202 if (!searchEngine.isNull()) {
203 resultLastToShow = 20;
204 resultFirstToShow = 0;
205
206 resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow,
207 resultLastToShow), isIndexing);
208 updatePrevButtonState(false);
209 }
210 updateHitRange();
211 }
212
213 void showPreviousResultPage()
214 {
215 if (!searchEngine.isNull()) {
216 int count = resultLastToShow % 20;
217 if (count == 0 || resultLastToShow != searchEngine->hitsCount())
218 count = 20;
219
220 resultLastToShow -= count;
221 resultFirstToShow = resultLastToShow -20;
222
223 resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow,
224 resultLastToShow), isIndexing);
225 if (resultFirstToShow == 0)
226 updatePrevButtonState(false);
227 }
228 updateHitRange();
229 }
230
231 void updatePrevButtonState(bool state = true)
232 {
233 firstResultPage->setEnabled(state);
234 previousResultPage->setEnabled(state);
235 }
236
237 void updateNextButtonState(bool state = true)
238 {
239 nextResultPage->setEnabled(state);
240 lastResultPage->setEnabled(state);
241 }
242
243 void indexingStarted()
244 {
245 isIndexing = true;
246 }
247
248 void indexingFinished()
249 {
250 isIndexing = false;
251 }
252
253private:
254 QHelpSearchResultWidgetPrivate(QHelpSearchEngine *engine)
255 : QObject()
256 , searchEngine(engine)
257 , isIndexing(false)
258 {
259 resultTreeWidget = 0;
260 resultTextBrowser = 0;
261
262 resultLastToShow = 20;
263 resultFirstToShow = 0;
264
265 firstResultPage = 0;
266 previousResultPage = 0;
267 hitsLabel = 0;
268 nextResultPage = 0;
269 lastResultPage = 0;
270
271 connect(searchEngine, SIGNAL(indexingStarted()),
272 this, SLOT(indexingStarted()));
273 connect(searchEngine, SIGNAL(indexingFinished()),
274 this, SLOT(indexingFinished()));
275 }
276
277 ~QHelpSearchResultWidgetPrivate()
278 {
279 delete searchEngine;
280 }
281
282 QToolButton* setupToolButton(const QString &iconPath)
283 {
284 QToolButton *button = new QToolButton();
285 button->setEnabled(false);
286 button->setAutoRaise(true);
287 button->setIcon(QIcon(iconPath));
288 button->setIconSize(QSize(12, 12));
289 button->setMaximumSize(QSize(16, 16));
290
291 return button;
292 }
293
294 void updateHitRange()
295 {
296 int last = 0;
297 int first = 0;
298 int count = 0;
299
300 if (!searchEngine.isNull()) {
301 count = searchEngine->hitsCount();
302 if (count > 0) {
303 first = resultFirstToShow +1;
304 last = resultLastToShow > count ? count : resultLastToShow;
305 }
306 }
307 hitsLabel->setText(tr("%1 - %2 of %3 Hits").arg(first).arg(last).arg(count));
308 }
309
310private:
311 friend class QHelpSearchResultWidget;
312
313 QPointer<QHelpSearchEngine> searchEngine;
314
315 QDefaultResultWidget *resultTreeWidget;
316 QCLuceneResultWidget *resultTextBrowser;
317
318 int resultLastToShow;
319 int resultFirstToShow;
320 bool isIndexing;
321
322 QToolButton *firstResultPage;
323 QToolButton *previousResultPage;
324 QLabel *hitsLabel;
325 QToolButton *nextResultPage;
326 QToolButton *lastResultPage;
327};
328
329#include "qhelpsearchresultwidget.moc"
330
331
332/*!
333 \class QHelpSearchResultWidget
334 \since 4.4
335 \inmodule QtHelp
336 \brief The QHelpSearchResultWidget class provides either a tree
337 widget or a text browser depending on the used search engine to display
338 the hits found by the search.
339*/
340
341/*!
342 \fn void QHelpSearchResultWidget::requestShowLink(const QUrl &link)
343
344 This signal is emitted when a item is activated and its associated
345 \a link should be shown.
346*/
347
348QHelpSearchResultWidget::QHelpSearchResultWidget(QHelpSearchEngine *engine)
349 : QWidget(0)
350 , d(new QHelpSearchResultWidgetPrivate(engine))
351{
352 QVBoxLayout *vLayout = new QVBoxLayout(this);
353 vLayout->setMargin(0);
354 vLayout->setSpacing(0);
355
356#if defined(QT_CLUCENE_SUPPORT)
357 QHBoxLayout *hBoxLayout = new QHBoxLayout();
358#ifndef Q_OS_MAC
359 hBoxLayout->setMargin(0);
360 hBoxLayout->setSpacing(0);
361#endif
362 hBoxLayout->addWidget(d->firstResultPage = d->setupToolButton(
363 QString::fromUtf8(":/trolltech/assistant/images/3leftarrow.png")));
364
365 hBoxLayout->addWidget(d->previousResultPage = d->setupToolButton(
366 QString::fromUtf8(":/trolltech/assistant/images/1leftarrow.png")));
367
368 d->hitsLabel = new QLabel(tr("0 - 0 of 0 Hits"), this);
369 d->hitsLabel->setEnabled(false);
370 hBoxLayout->addWidget(d->hitsLabel);
371 d->hitsLabel->setAlignment(Qt::AlignCenter);
372 d->hitsLabel->setMinimumSize(QSize(150, d->hitsLabel->height()));
373
374 hBoxLayout->addWidget(d->nextResultPage = d->setupToolButton(
375 QString::fromUtf8(":/trolltech/assistant/images/1rightarrow.png")));
376
377 hBoxLayout->addWidget(d->lastResultPage = d->setupToolButton(
378 QString::fromUtf8(":/trolltech/assistant/images/3rightarrow.png")));
379
380 QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
381 hBoxLayout->addItem(spacer);
382
383 vLayout->addLayout(hBoxLayout);
384
385 d->resultTextBrowser = new QCLuceneResultWidget(this);
386 vLayout->addWidget(d->resultTextBrowser);
387
388 connect(d->resultTextBrowser, SIGNAL(requestShowLink(const QUrl&)), this,
389 SIGNAL(requestShowLink(const QUrl&)));
390
391 connect(d->nextResultPage, SIGNAL(clicked()), d, SLOT(showNextResultPage()));
392 connect(d->lastResultPage, SIGNAL(clicked()), d, SLOT(showLastResultPage()));
393 connect(d->firstResultPage, SIGNAL(clicked()), d, SLOT(showFirstResultPage()));
394 connect(d->previousResultPage, SIGNAL(clicked()), d, SLOT(showPreviousResultPage()));
395
396 connect(d->firstResultPage, SIGNAL(clicked()), d, SLOT(updateNextButtonState()));
397 connect(d->previousResultPage, SIGNAL(clicked()), d, SLOT(updateNextButtonState()));
398 connect(d->nextResultPage, SIGNAL(clicked()), d, SLOT(updatePrevButtonState()));
399 connect(d->lastResultPage, SIGNAL(clicked()), d, SLOT(updatePrevButtonState()));
400
401#else
402 d->resultTreeWidget = new QDefaultResultWidget(this);
403 vLayout->addWidget(d->resultTreeWidget);
404 connect(d->resultTreeWidget, SIGNAL(requestShowLink(const QUrl&)), this,
405 SIGNAL(requestShowLink(const QUrl&)));
406#endif
407
408 connect(engine, SIGNAL(searchingFinished(int)), d, SLOT(setResults(int)));
409}
410
411/*!
412 Destroys the search result widget.
413*/
414QHelpSearchResultWidget::~QHelpSearchResultWidget()
415{
416 delete d;
417}
418
419/*!
420 Returns a reference of the URL that the item at \a point owns, or an
421 empty URL if no item exists at that point.
422*/
423QUrl QHelpSearchResultWidget::linkAt(const QPoint &point)
424{
425 QUrl url;
426#if defined(QT_CLUCENE_SUPPORT)
427 if (d->resultTextBrowser)
428 url = d->resultTextBrowser->anchorAt(point);
429#else
430 if (d->resultTreeWidget) {
431 QTreeWidgetItem *item = d->resultTreeWidget->itemAt(point);
432 if (item)
433 url = item->data(1, Qt::DisplayRole).toString();
434 }
435#endif
436 return url;
437}
438
439QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.