source: branches/vendor/trolltech/qt/current/tools/assistant/lib/qhelpsearchresultwidget.cpp @ 2

Last change on this file since 2 was 2, checked in by Dmitry A. Kuminov, 13 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 (qt-info@nokia.com)
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 qt-sales@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(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.