source: trunk/tools/assistant/lib/qhelpsearchengine.cpp@ 397

Last change on this file since 397 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.7 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 "qhelpenginecore.h"
43#include "qhelpsearchengine.h"
44#include "qhelpsearchquerywidget.h"
45#include "qhelpsearchresultwidget.h"
46
47#if defined(QT_CLUCENE_SUPPORT)
48# include "qhelpsearchindexreader_clucene_p.h"
49# include "qhelpsearchindexwriter_clucene_p.h"
50#else
51# include "qhelpsearchindexreader_default_p.h"
52# include "qhelpsearchindexwriter_default_p.h"
53#endif
54
55#include <QtCore/QDir>
56#include <QtCore/QFile>
57#include <QtCore/QFileInfo>
58#include <QtCore/QVariant>
59#include <QtCore/QThread>
60#include <QtCore/QPointer>
61
62QT_BEGIN_NAMESPACE
63
64#if defined(QT_CLUCENE_SUPPORT)
65 using namespace qt::fulltextsearch::clucene;
66#else
67 using namespace qt::fulltextsearch::std;
68#endif
69
70class QHelpSearchEnginePrivate : public QObject
71{
72 Q_OBJECT
73
74signals:
75 void indexingStarted();
76 void indexingFinished();
77
78 void searchingStarted();
79 void searchingFinished(int hits);
80
81private:
82 QHelpSearchEnginePrivate(QHelpEngineCore *helpEngine)
83 : queryWidget(0)
84 , resultWidget(0)
85 , helpEngine(helpEngine)
86 {
87 hitList.clear();
88 indexReader = 0;
89 indexWriter = 0;
90 }
91
92 ~QHelpSearchEnginePrivate()
93 {
94 hitList.clear();
95 delete indexReader;
96 delete indexWriter;
97 }
98
99 int hitsCount() const
100 {
101 int count = 0;
102 if (indexReader)
103 count = indexReader->hitsCount();
104
105 return count;
106 }
107
108 QList<QHelpSearchEngine::SearchHit> hits(int start, int end) const
109 {
110 QList<QHelpSearchEngine::SearchHit> returnValue;
111 if (indexReader) {
112 for (int i = start; i < end && i < hitsCount(); ++i)
113 returnValue.append(indexReader->hit(i));
114 }
115 return returnValue;
116 }
117
118 void updateIndex(bool reindex = false)
119 {
120 if (helpEngine.isNull())
121 return;
122
123 if (!QFile::exists(QFileInfo(helpEngine->collectionFile()).path()))
124 return;
125
126 if (!indexWriter) {
127 indexWriter = new QHelpSearchIndexWriter();
128
129 connect(indexWriter, SIGNAL(indexingStarted()), this, SIGNAL(indexingStarted()));
130 connect(indexWriter, SIGNAL(indexingFinished()), this, SIGNAL(indexingFinished()));
131 connect(indexWriter, SIGNAL(indexingFinished()), this, SLOT(optimizeIndex()));
132 }
133
134 if (indexWriter) {
135 indexWriter->cancelIndexing();
136 indexWriter->updateIndex(helpEngine->collectionFile(),
137 indexFilesFolder(), reindex);
138 }
139 }
140
141 void cancelIndexing()
142 {
143 if (indexWriter)
144 indexWriter->cancelIndexing();
145 }
146
147 void search(const QList<QHelpSearchQuery> &queryList)
148 {
149 if (helpEngine.isNull())
150 return;
151
152 if (!QFile::exists(QFileInfo(helpEngine->collectionFile()).path()))
153 return;
154
155 if (!indexReader) {
156 indexReader = new QHelpSearchIndexReader();
157
158 connect(indexReader, SIGNAL(searchingStarted()), this, SIGNAL(searchingStarted()));
159 connect(indexReader, SIGNAL(searchingFinished(int)), this, SIGNAL(searchingFinished(int)));
160 }
161
162 if (indexReader) {
163 m_queryList = queryList;
164 indexReader->cancelSearching();
165 indexReader->search(helpEngine->collectionFile(), indexFilesFolder(), queryList);
166 }
167 }
168
169 void cancelSearching()
170 {
171 if (indexReader)
172 indexReader->cancelSearching();
173 }
174
175 QString indexFilesFolder() const
176 {
177 QString indexFilesFolder = QLatin1String(".fulltextsearch");
178 if (helpEngine && !helpEngine->collectionFile().isEmpty()) {
179 QFileInfo fi(helpEngine->collectionFile());
180 indexFilesFolder = fi.absolutePath() + QDir::separator()
181 + QLatin1Char('.')
182 + fi.fileName().left(fi.fileName().lastIndexOf(QLatin1String(".qhc")));
183 }
184 return indexFilesFolder;
185 }
186
187private slots:
188 void optimizeIndex()
189 {
190#if defined(QT_CLUCENE_SUPPORT)
191 if (indexWriter && !helpEngine.isNull()) {
192 indexWriter->optimizeIndex();
193 }
194#endif
195 }
196
197private:
198 friend class QHelpSearchEngine;
199
200 QHelpSearchQueryWidget *queryWidget;
201 QHelpSearchResultWidget *resultWidget;
202
203 QHelpSearchIndexReader *indexReader;
204 QHelpSearchIndexWriter *indexWriter;
205
206 QPointer<QHelpEngineCore> helpEngine;
207 QList<QHelpSearchEngine::SearchHit> hitList;
208
209 QList<QHelpSearchQuery> m_queryList;
210};
211
212#include "qhelpsearchengine.moc"
213
214
215/*!
216 \class QHelpSearchQuery
217 \since 4.4
218 \inmodule QtHelp
219 \brief The QHelpSearchQuery class contains the field name and the associated
220 search term
221
222 The QHelpSearchQuery class contains the field name and the associated search
223 term. Depending on the field the search term might get split up into seperate
224 terms to be parsed differently by the search engine.
225
226 \sa QHelpSearchQueryWidget
227*/
228
229/*!
230 \fn QHelpSearchQuery::QHelpSearchQuery()
231
232 Constructs a new empty QHelpSearchQuery.
233*/
234
235/*!
236 \fn QHelpSearchQuery::QHelpSearchQuery(FieldName field, const QStringList &wordList)
237
238 Constructs a new QHelpSearchQuery and initializes it with the given \a field and \a wordList.
239*/
240
241/*!
242 \enum QHelpSearchQuery::FieldName
243 This enum type specifies the field names that are handled by the search engine.
244
245 \value DEFAULT the default field provided by the search widget, several terms should be
246 splitted and stored in the wordlist except search terms enclosed in quotes.
247 \value FUZZY a field only provided in use with clucene. Terms should be split in seperate
248 words and passed to the search engine.
249 \value WITHOUT a field only provided in use with clucene. Terms should be split in seperate
250 words and passed to the search engine.
251 \value PHRASE a field only provided in use with clucene. Terms should not be split in seperate
252 words.
253 \value ALL a field only provided in use with clucene. Terms should be split in seperate
254 words and passed to the search engine
255 \value ATLEAST a field only provided in use with clucene. Terms should be split in seperate
256 words and passed to the search engine
257*/
258
259/*!
260 \class QHelpSearchEngine
261 \since 4.4
262 \inmodule QtHelp
263 \brief The QHelpSearchEngine class provides access to widgets reusable
264 to integrate fulltext search as well as to index and search documentation.
265
266 Before the search engine can be used, one has to instantiate at least a
267 QHelpEngineCore object that needs to be passed to the search engines constructor.
268 This is required as the search engine needs to be connected to the help
269 engines setupFinished() signal to know when it can start to index documentation.
270
271 After starting the indexing process the signal indexingStarted() is emitted and
272 on the end of the indexing process the indexingFinished() is emited. To stop
273 the indexing one can call cancelIndexing().
274
275 While the indexing process has finished, the search engine can now be used to search
276 thru its index for a given term. To do this one may use the possibility of creating the
277 QHelpSearchQuery list by self or reuse the QHelpSearchQueryWidget which has the inbuild
278 functionality to set up a proper search querys list that get's passed to the search engines
279 search() function.
280
281 After the list of querys has been passed to the search engine, the signal searchingStarted()
282 is emited and after the search has finished the searchingFinished() signal is emited. The
283 search process can be stopped by calling cancelSearching().
284
285 If the search succeeds, the searchingFinished() will be called with the search hits count,
286 which can be reused to fetch the search hits from the search engine. Calling the hits()
287 function with the range of hits you would like to get will return a list of the requested
288 SearchHits. They basically constist at the moment of a pair of strings where the values
289 of that pair are the documentation file path and the page title.
290
291 To display the given hits use the QHelpSearchResultWidget or build up your own one if you need
292 more advanced functionality. Note that the QHelpSearchResultWidget can not be instantiated
293 directly, you must retrieve the widget from the search engine in use as all connections will be
294 established for you by the widget itself.
295*/
296
297/*!
298 \fn void QHelpSearchEngine::indexingStarted()
299
300 This signal is emitted when indexing process is started.
301*/
302
303/*!
304 \fn void QHelpSearchEngine::indexingFinished()
305
306 This signal is emitted when the indexing process is complete.
307*/
308
309/*!
310 \fn void QHelpSearchEngine::searchingStarted()
311
312 This signal is emitted when the search process is started.
313*/
314
315/*!
316 \fn void QHelpSearchEngine::searchingFinished(int hits)
317
318 This signal is emitted when the search process is complete.
319 The hit count is stored in \a hits.
320*/
321
322/*!
323 Constructs a new search engine with the given \a parent. The search engine
324 uses the given \a helpEngine to access the documentation that needs to be indexed.
325 The QHelpEngine's setupFinished() signal is automatically connected to the
326 QHelpSearchEngine's indexing function, so that new documentation will be indexed
327 after the signal is emited.
328*/
329QHelpSearchEngine::QHelpSearchEngine(QHelpEngineCore *helpEngine, QObject *parent)
330 : QObject(parent)
331{
332 d = new QHelpSearchEnginePrivate(helpEngine);
333
334 connect(helpEngine, SIGNAL(setupFinished()), this, SLOT(indexDocumentation()));
335
336 connect(d, SIGNAL(indexingStarted()), this, SIGNAL(indexingStarted()));
337 connect(d, SIGNAL(indexingFinished()), this, SIGNAL(indexingFinished()));
338 connect(d, SIGNAL(searchingStarted()), this, SIGNAL(searchingStarted()));
339 connect(d, SIGNAL(searchingFinished(int)), this, SIGNAL(searchingFinished(int)));
340}
341
342/*!
343 Destructs the search engine.
344*/
345QHelpSearchEngine::~QHelpSearchEngine()
346{
347 delete d;
348}
349
350/*!
351 Returns a widget to use as input widget. Depending on your search engine
352 configuration you will get a different widget with more or less subwidgets.
353*/
354QHelpSearchQueryWidget* QHelpSearchEngine::queryWidget()
355{
356 if (!d->queryWidget)
357 d->queryWidget = new QHelpSearchQueryWidget();
358
359 return d->queryWidget;
360}
361
362/*!
363 Returns a widget that can hold and display the search results.
364*/
365QHelpSearchResultWidget* QHelpSearchEngine::resultWidget()
366{
367 if (!d->resultWidget)
368 d->resultWidget = new QHelpSearchResultWidget(this);
369
370 return d->resultWidget;
371}
372
373/*!
374 Returns the amount of hits the search engine found.
375*/
376int QHelpSearchEngine::hitsCount() const
377{
378 return d->hitsCount();
379}
380
381/*!
382 \typedef QHelpSearchEngine::SearchHit
383
384 Typedef for QPair<QString, QString>.
385 The values of that pair are the documentation file path and the page title.
386
387 \sa hits()
388*/
389
390/*!
391 Returns a list of search hits within the range of \a start \a end.
392*/
393QList<QHelpSearchEngine::SearchHit> QHelpSearchEngine::hits(int start, int end) const
394{
395 return d->hits(start, end);
396}
397
398/*!
399 Returns the list of queries last searched for.
400 \since 4.5
401*/
402QList<QHelpSearchQuery> QHelpSearchEngine::query() const
403{
404 return d->m_queryList;
405}
406
407/*!
408 Forces the search engine to reindex all documentation files.
409*/
410void QHelpSearchEngine::reindexDocumentation()
411{
412 d->updateIndex(true);
413}
414
415/*!
416 Stops the indexing process.
417*/
418void QHelpSearchEngine::cancelIndexing()
419{
420 d->cancelIndexing();
421}
422
423/*!
424 Stops the search process.
425*/
426void QHelpSearchEngine::cancelSearching()
427{
428 d->cancelSearching();
429}
430
431/*!
432 Starts the search process using the given list of querys \a queryList
433 build by the search field name and the values to search for.
434*/
435void QHelpSearchEngine::search(const QList<QHelpSearchQuery> &queryList)
436{
437 d->search(queryList);
438}
439
440void QHelpSearchEngine::indexDocumentation()
441{
442 d->updateIndex();
443}
444
445QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.