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

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

File size: 13.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the Qt Assistant of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this 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 have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
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(QUrl)),
103 this, SIGNAL(requestShowLink(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->hitCount()) {
173 resultLastToShow += 20;
174 resultFirstToShow += 20;
175
176 resultTextBrowser->showResultPage(searchEngine->hits(resultFirstToShow,
177 resultLastToShow), isIndexing);
178 if (resultLastToShow >= searchEngine->hitCount())
179 updateNextButtonState(false);
180 }
181 updateHitRange();
182 }
183
184 void showLastResultPage()
185 {
186 if (!searchEngine.isNull()) {
187 resultLastToShow = searchEngine->hitCount();
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->hitCount())
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->hitCount();
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(QUrl)), this,
389 SIGNAL(requestShowLink(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(QUrl)), this,
405 SIGNAL(requestShowLink(QUrl)));
406#endif
407
408 connect(engine, SIGNAL(searchingFinished(int)), d, SLOT(setResults(int)));
409}
410
411/*! \reimp
412*/
413void QHelpSearchResultWidget::changeEvent(QEvent *event)
414{
415 if (event->type() == QEvent::LanguageChange)
416 d->setResults(d->searchEngine->hitCount());
417}
418
419/*!
420 Destroys the search result widget.
421*/
422QHelpSearchResultWidget::~QHelpSearchResultWidget()
423{
424 delete d;
425}
426
427/*!
428 Returns a reference of the URL that the item at \a point owns, or an
429 empty URL if no item exists at that point.
430*/
431QUrl QHelpSearchResultWidget::linkAt(const QPoint &point)
432{
433 QUrl url;
434#if defined(QT_CLUCENE_SUPPORT)
435 if (d->resultTextBrowser)
436 url = d->resultTextBrowser->anchorAt(point);
437#else
438 if (d->resultTreeWidget) {
439 QTreeWidgetItem *item = d->resultTreeWidget->itemAt(point);
440 if (item)
441 url = item->data(1, Qt::DisplayRole).toString();
442 }
443#endif
444 return url;
445}
446
447QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.