source: trunk/tools/assistant/lib/qhelpsearchquerywidget.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

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

File size: 18.4 KB
RevLine 
[2]1/****************************************************************************
2**
[846]3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
[561]4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
[2]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**
[561]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.
[2]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**
[561]36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
[2]38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qhelpsearchquerywidget.h"
43
[561]44#include <QtCore/QAbstractListModel>
[2]45#include <QtCore/QObject>
46#include <QtCore/QStringList>
[561]47#include <QtCore/QtGlobal>
[2]48
[561]49#include <QtGui/QCompleter>
[2]50#include <QtGui/QLabel>
51#include <QtGui/QLayout>
52#include <QtGui/QLineEdit>
53#include <QtGui/QFocusEvent>
54#include <QtGui/QPushButton>
55#include <QtGui/QToolButton>
56
57QT_BEGIN_NAMESPACE
58
59class QHelpSearchQueryWidgetPrivate : public QObject
60{
61 Q_OBJECT
62
63private:
[561]64 struct QueryHistory {
65 explicit QueryHistory() : curQuery(-1) {}
66 QList<QList<QHelpSearchQuery> > queries;
67 int curQuery;
68 };
69
70 class CompleterModel : public QAbstractListModel
71 {
72 public:
73 explicit CompleterModel(QObject *parent)
74 : QAbstractListModel(parent) {}
75
76 int rowCount(const QModelIndex &parent = QModelIndex()) const
77 {
78 return parent.isValid() ? 0 : termList.size();
79 }
80
81 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
82 {
83 if (!index.isValid() || index.row() >= termList.count()||
84 (role != Qt::EditRole && role != Qt::DisplayRole))
85 return QVariant();
86 return termList.at(index.row());
87 }
88
89 void addTerm(const QString &term)
90 {
91 if (!termList.contains(term)) {
92 termList.append(term);
93 reset();
94 }
95 }
96
97 private:
98 QStringList termList;
99 };
100
[2]101 QHelpSearchQueryWidgetPrivate()
[846]102 : QObject()
103 , simpleSearch(true)
104 , searchCompleter(new CompleterModel(this), this)
[2]105 {
106 searchButton = 0;
107 advancedSearchWidget = 0;
108 showHideAdvancedSearchButton = 0;
109 defaultQuery = 0;
110 exactQuery = 0;
111 similarQuery = 0;
112 withoutQuery = 0;
113 allQuery = 0;
114 atLeastQuery = 0;
115 }
116
117 ~QHelpSearchQueryWidgetPrivate()
118 {
119 // nothing todo
120 }
121
[651]122 void retranslate()
123 {
124 simpleSearchLabel->setText(QHelpSearchQueryWidget::tr("Search for:"));
125 prevQueryButton->setToolTip(QHelpSearchQueryWidget::tr("Previous search"));
126 nextQueryButton->setToolTip(QHelpSearchQueryWidget::tr("Next search"));
127 searchButton->setText(QHelpSearchQueryWidget::tr("Search"));
128#ifdef QT_CLUCENE_SUPPORT
129 advancedSearchLabel->setText(QHelpSearchQueryWidget::tr("Advanced search"));
130 similarLabel->setText(QHelpSearchQueryWidget::tr("words <B>similar</B> to:"));
131 withoutLabel->setText(QHelpSearchQueryWidget::tr("<B>without</B> the words:"));
132 exactLabel->setText(QHelpSearchQueryWidget::tr("with <B>exact phrase</B>:"));
133 allLabel->setText(QHelpSearchQueryWidget::tr("with <B>all</B> of the words:"));
134 atLeastLabel->setText(QHelpSearchQueryWidget::tr("with <B>at least one</B> of the words:"));
135#endif
136 }
137
[2]138 QStringList buildTermList(const QString query)
139 {
140 bool s = false;
141 QString phrase;
142 QStringList wordList;
143 QString searchTerm = query;
144
145 for (int i = 0; i < searchTerm.length(); ++i) {
146 if (searchTerm[i] == QLatin1Char('\"') && !s) {
147 s = true;
148 phrase = searchTerm[i];
149 continue;
150 }
151 if (searchTerm[i] != QLatin1Char('\"') && s)
152 phrase += searchTerm[i];
153 if (searchTerm[i] == QLatin1Char('\"') && s) {
154 s = false;
155 phrase += searchTerm[i];
156 wordList.append(phrase);
157 searchTerm.remove(phrase);
158 }
159 }
160 if (s)
161 searchTerm.replace(phrase, phrase.mid(1));
162
163 const QRegExp exp(QLatin1String("\\s+"));
164 wordList += searchTerm.split(exp, QString::SkipEmptyParts);
165 return wordList;
166 }
167
[561]168 void saveQuery(const QList<QHelpSearchQuery> &query, QueryHistory &queryHist)
169 {
170 // We only add the query to the list if it is different from the last one.
171 bool insert = false;
172 if (queryHist.queries.empty())
173 insert = true;
174 else {
175 const QList<QHelpSearchQuery> &lastQuery = queryHist.queries.last();
176 if (lastQuery.size() != query.size()) {
177 insert = true;
178 } else {
179 for (int i = 0; i < query.size(); ++i) {
180 if (query.at(i).fieldName != lastQuery.at(i).fieldName
181 || query.at(i).wordList != lastQuery.at(i).wordList) {
182 insert = true;
183 break;
184 }
185 }
186 }
187 }
188 if (insert) {
189 queryHist.queries.append(query);
190 foreach (const QHelpSearchQuery &queryPart, query) {
191 static_cast<CompleterModel *>(searchCompleter.model())->
192 addTerm(queryPart.wordList.join(" "));
193 }
194 }
195 }
196
[846]197 void nextOrPrevQuery(int maxOrMinIndex, int addend, QToolButton *thisButton,
198 QToolButton *otherButton)
[561]199 {
200 QueryHistory *queryHist;
201 QList<QLineEdit *> lineEdits;
202 if (simpleSearch) {
203 queryHist = &simpleQueries;
204 lineEdits << defaultQuery;
205 } else {
206 queryHist = &complexQueries;
207 lineEdits << allQuery << atLeastQuery << similarQuery
[846]208 << withoutQuery << exactQuery;
[561]209 }
210 foreach (QLineEdit *lineEdit, lineEdits)
211 lineEdit->clear();
212
213 // Otherwise, the respective button would be disabled.
214 Q_ASSERT(queryHist->curQuery != maxOrMinIndex);
215
216 queryHist->curQuery += addend;
217 const QList<QHelpSearchQuery> &query =
218 queryHist->queries.at(queryHist->curQuery);
219 foreach (const QHelpSearchQuery &queryPart, query) {
220 QLineEdit *lineEdit = 0;
221 switch (queryPart.fieldName) {
222 case QHelpSearchQuery::DEFAULT:
223 lineEdit = defaultQuery;
224 break;
225 case QHelpSearchQuery::ALL:
226 lineEdit = allQuery;
227 break;
228 case QHelpSearchQuery::ATLEAST:
229 lineEdit = atLeastQuery;
230 break;
231 case QHelpSearchQuery::FUZZY:
232 lineEdit = similarQuery;
233 break;
234 case QHelpSearchQuery::WITHOUT:
235 lineEdit = withoutQuery;
236 break;
237 case QHelpSearchQuery::PHRASE:
238 lineEdit = exactQuery;
239 break;
240 default:
241 Q_ASSERT(0);
242 }
243 lineEdit->setText(queryPart.wordList.join(" "));
244 }
245
246 if (queryHist->curQuery == maxOrMinIndex)
247 thisButton->setEnabled(false);
248 otherButton->setEnabled(true);
249 }
250
251 void enableOrDisableToolButtons()
252 {
[846]253 const QueryHistory &queryHist = simpleSearch ? simpleQueries
254 : complexQueries;
[561]255 prevQueryButton->setEnabled(queryHist.curQuery > 0);
[846]256 nextQueryButton->setEnabled(queryHist.curQuery
257 < queryHist.queries.size() - 1);
[561]258 }
259
[2]260private slots:
261 void showHideAdvancedSearch()
262 {
[561]263 if (simpleSearch) {
[2]264 advancedSearchWidget->show();
265 showHideAdvancedSearchButton->setText((QLatin1String("-")));
266 } else {
267 advancedSearchWidget->hide();
268 showHideAdvancedSearchButton->setText((QLatin1String("+")));
269 }
270
[561]271 simpleSearch = !simpleSearch;
272 defaultQuery->setEnabled(simpleSearch);
273 enableOrDisableToolButtons();
[2]274 }
275
[561]276 void searchRequested()
277 {
278 QList<QHelpSearchQuery> queryList;
279#if !defined(QT_CLUCENE_SUPPORT)
280 queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
[846]281 QStringList(defaultQuery->text())));
[561]282
283#else
284 if (defaultQuery->isEnabled()) {
285 queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
[846]286 buildTermList(defaultQuery->text())));
[561]287 } else {
288 const QRegExp exp(QLatin1String("\\s+"));
[846]289 QStringList lst = similarQuery->text().split(exp,
290 QString::SkipEmptyParts);
[561]291 if (!lst.isEmpty()) {
292 QStringList fuzzy;
[769]293 foreach (const QString &term, lst)
[846]294 fuzzy += buildTermList(term);
295 queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY,
296 fuzzy));
[561]297 }
298
299 lst = withoutQuery->text().split(exp, QString::SkipEmptyParts);
300 if (!lst.isEmpty()) {
301 QStringList without;
[769]302 foreach (const QString &term, lst)
[846]303 without.append(term);
304 queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT,
305 without));
[561]306 }
307
308 if (!exactQuery->text().isEmpty()) {
309 QString phrase = exactQuery->text().remove(QLatin1Char('\"'));
[846]310 phrase = phrase.simplified();
311 queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE,
312 QStringList(phrase)));
[561]313 }
314
315 lst = allQuery->text().split(exp, QString::SkipEmptyParts);
316 if (!lst.isEmpty()) {
317 QStringList all;
[769]318 foreach (const QString &term, lst)
[846]319 all.append(term);
[561]320 queryList.append(QHelpSearchQuery(QHelpSearchQuery::ALL, all));
321 }
322
323 lst = atLeastQuery->text().split(exp, QString::SkipEmptyParts);
324 if (!lst.isEmpty()) {
325 QStringList atLeast;
[769]326 foreach (const QString &term, lst)
[846]327 atLeast += buildTermList(term);
328 queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST,
329 atLeast));
[561]330 }
331 }
332#endif
333 QueryHistory &queryHist = simpleSearch ? simpleQueries : complexQueries;
334 saveQuery(queryList, queryHist);
335 queryHist.curQuery = queryHist.queries.size() - 1;
336 if (queryHist.curQuery > 0)
337 prevQueryButton->setEnabled(true);
338 nextQueryButton->setEnabled(false);
339 }
340
341 void nextQuery()
342 {
[846]343 nextOrPrevQuery((simpleSearch ? simpleQueries
344 : complexQueries).queries.size() - 1, 1, nextQueryButton,
345 prevQueryButton);
[561]346 }
347
348 void prevQuery()
349 {
350 nextOrPrevQuery(0, -1, prevQueryButton, nextQueryButton);
351 }
352
[2]353private:
354 friend class QHelpSearchQueryWidget;
355
[561]356 bool simpleSearch;
[651]357 QLabel *simpleSearchLabel;
358 QLabel *advancedSearchLabel;
359 QLabel *similarLabel;
360 QLabel *withoutLabel;
361 QLabel *exactLabel;
362 QLabel *allLabel;
363 QLabel *atLeastLabel;
[2]364 QPushButton *searchButton;
365 QWidget* advancedSearchWidget;
366 QToolButton *showHideAdvancedSearchButton;
367 QLineEdit *defaultQuery;
368 QLineEdit *exactQuery;
369 QLineEdit *similarQuery;
370 QLineEdit *withoutQuery;
371 QLineEdit *allQuery;
372 QLineEdit *atLeastQuery;
[561]373 QToolButton *nextQueryButton;
374 QToolButton *prevQueryButton;
375 QueryHistory simpleQueries;
376 QueryHistory complexQueries;
377 QCompleter searchCompleter;
[2]378};
379
380#include "qhelpsearchquerywidget.moc"
381
382
383/*!
384 \class QHelpSearchQueryWidget
385 \since 4.4
386 \inmodule QtHelp
387 \brief The QHelpSearchQueryWidget class provides a simple line edit or
388 an advanced widget to enable the user to input a search term in a
389 standardized input mask.
390*/
391
392/*!
393 \fn void QHelpSearchQueryWidget::search()
394
395 This signal is emitted when a the user has the search button invoked.
[846]396 After reciving the signal you can ask the QHelpSearchQueryWidget for the
397 build list of QHelpSearchQuery's that you may pass to the QHelpSearchEngine's
398 search() function.
[2]399*/
400
401/*!
402 Constructs a new search query widget with the given \a parent.
403*/
404QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent)
405 : QWidget(parent)
406{
407 d = new QHelpSearchQueryWidgetPrivate();
408
409 QVBoxLayout *vLayout = new QVBoxLayout(this);
410 vLayout->setMargin(0);
411
412 QHBoxLayout* hBoxLayout = new QHBoxLayout();
[651]413 d->simpleSearchLabel = new QLabel(this);
[2]414 d->defaultQuery = new QLineEdit(this);
[561]415 d->defaultQuery->setCompleter(&d->searchCompleter);
416 d->prevQueryButton = new QToolButton(this);
417 d->prevQueryButton->setArrowType(Qt::LeftArrow);
418 d->prevQueryButton->setEnabled(false);
419 d->nextQueryButton = new QToolButton(this);
420 d->nextQueryButton->setArrowType(Qt::RightArrow);
421 d->nextQueryButton->setEnabled(false);
[651]422 d->searchButton = new QPushButton(this);
423 hBoxLayout->addWidget(d->simpleSearchLabel);
[2]424 hBoxLayout->addWidget(d->defaultQuery);
[561]425 hBoxLayout->addWidget(d->prevQueryButton);
426 hBoxLayout->addWidget(d->nextQueryButton);
[2]427 hBoxLayout->addWidget(d->searchButton);
428
429 vLayout->addLayout(hBoxLayout);
430
[561]431 connect(d->prevQueryButton, SIGNAL(clicked()), d, SLOT(prevQuery()));
432 connect(d->nextQueryButton, SIGNAL(clicked()), d, SLOT(nextQuery()));
[2]433 connect(d->searchButton, SIGNAL(clicked()), this, SIGNAL(search()));
434 connect(d->defaultQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
435
436#if defined(QT_CLUCENE_SUPPORT)
437 hBoxLayout = new QHBoxLayout();
438 d->showHideAdvancedSearchButton = new QToolButton(this);
439 d->showHideAdvancedSearchButton->setText(QLatin1String("+"));
440 d->showHideAdvancedSearchButton->setMinimumSize(25, 20);
441
[651]442 d->advancedSearchLabel = new QLabel(this);
[2]443 QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
[651]444 sizePolicy.setHeightForWidth(d->advancedSearchLabel->sizePolicy().hasHeightForWidth());
445 d->advancedSearchLabel->setSizePolicy(sizePolicy);
[2]446
447 QFrame* hLine = new QFrame(this);
448 hLine->setFrameStyle(QFrame::HLine);
449 hBoxLayout->addWidget(d->showHideAdvancedSearchButton);
[651]450 hBoxLayout->addWidget(d->advancedSearchLabel);
[2]451 hBoxLayout->addWidget(hLine);
452
453 vLayout->addLayout(hBoxLayout);
454
455 // setup advanced search layout
456 d->advancedSearchWidget = new QWidget(this);
457 QGridLayout *gLayout = new QGridLayout(d->advancedSearchWidget);
458 gLayout->setMargin(0);
459
[651]460 d->similarLabel = new QLabel(this);
461 gLayout->addWidget(d->similarLabel, 0, 0);
[2]462 d->similarQuery = new QLineEdit(this);
[561]463 d->similarQuery->setCompleter(&d->searchCompleter);
[2]464 gLayout->addWidget(d->similarQuery, 0, 1);
465
[651]466 d->withoutLabel = new QLabel(this);
467 gLayout->addWidget(d->withoutLabel, 1, 0);
[2]468 d->withoutQuery = new QLineEdit(this);
[561]469 d->withoutQuery->setCompleter(&d->searchCompleter);
[2]470 gLayout->addWidget(d->withoutQuery, 1, 1);
471
[651]472 d->exactLabel = new QLabel(this);
473 gLayout->addWidget(d->exactLabel, 2, 0);
[2]474 d->exactQuery = new QLineEdit(this);
[561]475 d->exactQuery->setCompleter(&d->searchCompleter);
[2]476 gLayout->addWidget(d->exactQuery, 2, 1);
477
[651]478 d->allLabel = new QLabel(this);
479 gLayout->addWidget(d->allLabel, 3, 0);
[2]480 d->allQuery = new QLineEdit(this);
[561]481 d->allQuery->setCompleter(&d->searchCompleter);
[2]482 gLayout->addWidget(d->allQuery, 3, 1);
483
[651]484 d->atLeastLabel = new QLabel(this);
485 gLayout->addWidget(d->atLeastLabel, 4, 0);
[2]486 d->atLeastQuery = new QLineEdit(this);
[561]487 d->atLeastQuery->setCompleter(&d->searchCompleter);
[2]488 gLayout->addWidget(d->atLeastQuery, 4, 1);
489
490 vLayout->addWidget(d->advancedSearchWidget);
491 d->advancedSearchWidget->hide();
492
[651]493 d->retranslate();
494
[2]495 connect(d->exactQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
496 connect(d->similarQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
497 connect(d->withoutQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
498 connect(d->allQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
499 connect(d->atLeastQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
500 connect(d->showHideAdvancedSearchButton, SIGNAL(clicked()),
501 d, SLOT(showHideAdvancedSearch()));
502#endif
[561]503 connect(this, SIGNAL(search()), d, SLOT(searchRequested()));
[2]504}
505
506/*!
507 Destroys the search query widget.
508*/
509QHelpSearchQueryWidget::~QHelpSearchQueryWidget()
510{
511 delete d;
512}
513
514/*!
[769]515 Returns a list of queries to use in combination with the search engines
[2]516 search(QList<QHelpSearchQuery> &query) function.
517*/
518QList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const
519{
[561]520 const QHelpSearchQueryWidgetPrivate::QueryHistory &queryHist =
521 d->simpleSearch ? d->simpleQueries : d->complexQueries;
522 return queryHist.queries.isEmpty() ?
523 QList<QHelpSearchQuery>() : queryHist.queries.last();
[2]524}
525
[846]526/*!
527 \reimp
[2]528*/
529void QHelpSearchQueryWidget::focusInEvent(QFocusEvent *focusEvent)
530{
531 if (focusEvent->reason() != Qt::MouseFocusReason) {
532 d->defaultQuery->selectAll();
533 d->defaultQuery->setFocus();
534 }
535}
536
[651]537/*! \reimp
538*/
539void QHelpSearchQueryWidget::changeEvent(QEvent *event)
540{
541 if (event->type() == QEvent::LanguageChange)
542 d->retranslate();
543 else
544 QWidget::changeEvent(event);
545}
546
[2]547QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.