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

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

trunk: Merged in qt 4.6.1 sources.

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