00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <QDebug>
00025 #include <QObject>
00026 #include <QFrame>
00027 #include <QLineEdit>
00028 #include <QEvent>
00029 #include <QKeyEvent>
00030 #include <QShortcut>
00031 #include <QKeySequence>
00032 #include <QTime>
00033
00034 #include <klfguiutil.h>
00035
00036 #include <ui_klfsearchbar.h>
00037 #include "klfsearchbar.h"
00038 #include "klfsearchbar_p.h"
00039
00040
00041
00134 QDebug& operator<<(QDebug& str, const KLFPosSearchable::Pos& pos)
00135 {
00136 QString s;
00137 s.sprintf("%p", (const void*)(const KLFPosSearchable::Pos::PosData*)pos.posdata);
00138 str << "Pos("<<qPrintable(s);
00139 if (pos.posdata != NULL) {
00140 QString desc;
00141 if (!(desc = pos.posdata->toDebug()).isEmpty())
00142 str << " " << qPrintable(desc);
00143 }
00144 return str <<")";
00145 }
00146
00147
00148
00149 KLFPosSearchable::Pos KLFPosSearchable::searchStartFrom(bool forward)
00150 {
00151 klfDbg("start from: base implementation, will return invalid. forward="<<forward) ;
00152 Q_UNUSED(forward) ;
00153 return Pos();
00154 }
00155
00156 void KLFPosSearchable::setSearchInterruptRequested(bool on)
00157 {
00158 klfDbg("on="<<on) ;
00159 pInterruptRequested = on;
00160 }
00161
00162
00163
00164
00165
00166 KLFPosSearchableProxy::~KLFPosSearchableProxy()
00167 {
00168 }
00169
00170 KLFPosSearchable::Pos KLFPosSearchableProxy::searchStartFrom(bool forward)
00171 {
00172 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return Pos() );
00173 return target()->searchStartFrom(forward);
00174 }
00175
00176 KLFPosSearchable::Pos KLFPosSearchableProxy::searchFind(const QString& queryString, const Pos& fromPos, bool forward)
00177 {
00178 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return Pos() );
00179 return target()->searchFind(queryString, fromPos, forward);
00180 }
00181
00182 void KLFPosSearchableProxy::searchMoveToPos(const Pos& pos)
00183 {
00184 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
00185 return target()->searchMoveToPos(pos);
00186 }
00187
00188 void KLFPosSearchableProxy::searchPerformed(const QString& queryString, bool found, const Pos& pos)
00189 {
00190 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
00191 target()->searchPerformed(queryString, found, pos);
00192 }
00193
00194 void KLFPosSearchableProxy::searchAborted()
00195 {
00196 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
00197 target()->searchAborted();
00198 }
00199
00200 void KLFPosSearchableProxy::searchReinitialized()
00201 {
00202 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
00203 target()->searchReinitialized();
00204 }
00205
00206 QString KLFPosSearchableProxy::searchQueryString() const
00207 {
00208 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return QString(); );
00209 return target()->searchQueryString();
00210 }
00211
00212 void KLFPosSearchableProxy::setSearchQueryString(const QString& s)
00213 {
00214 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
00215 target()->setSearchQueryString(s);
00216 }
00217
00218 bool KLFPosSearchableProxy::searchHasInterruptRequested()
00219 {
00220 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return false; );
00221 return target()->searchHasInterruptRequested();
00222 }
00223
00224 void KLFPosSearchableProxy::setSearchInterruptRequested(bool on)
00225 {
00226 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
00227 target()->setSearchInterruptRequested(on);
00228 }
00229
00230
00231
00232
00233
00234 struct DummySearchPosData : public KLFPosSearchable::Pos::PosData
00235 {
00236 bool equals(PosData *) const { return true; }
00237 };
00238
00239
00240 KLFSearchable::KLFSearchable()
00241 {
00242 }
00243 KLFSearchable::~KLFSearchable()
00244 {
00245 }
00246
00247 KLFPosSearchable::Pos KLFSearchable::searchFind(const QString& queryString, const Pos& fromPos, bool forward)
00248 {
00249 bool r;
00250
00251
00252 if (!fromPos.valid())
00253 r = searchFind(queryString, forward);
00254 else
00255 r = searchFindNext(forward);
00256 Pos p = Pos();
00257 if (!r)
00258 return p;
00259
00260 p.posdata = new DummySearchPosData;
00261 return p;
00262 }
00263
00264
00265
00266
00267 KLFSearchableProxy::~KLFSearchableProxy()
00268 {
00269 }
00270
00271 void KLFSearchableProxy::setTarget(KLFTarget *target)
00272 {
00273 KLFSearchable *s = dynamic_cast<KLFSearchable*>(target);
00274 KLF_ASSERT_CONDITION( (s!=NULL) || (target==NULL),
00275 "target is not a valid KLFSearchable object !",
00276 return; ) ;
00277 KLFTargeter::setTarget(s);
00278 }
00279
00280 bool KLFSearchableProxy::searchFind(const QString& queryString, bool forward)
00281 {
00282 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return false );
00283 return target()->searchFind(queryString, forward);
00284 }
00285 bool KLFSearchableProxy::searchFindNext(bool forward)
00286 {
00287 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return false );
00288 return target()->searchFindNext(forward);
00289 }
00290 void KLFSearchableProxy::searchAbort()
00291 {
00292 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return );
00293 return target()->searchAbort();
00294 }
00295
00296
00297
00298
00299 KLFSearchBar::KLFSearchBar(QWidget *parent)
00300 : QFrame(parent)
00301 {
00302 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00303 klfDbg("parent: "<<parent) ;
00304
00305 _isInQtDesigner = false;
00306
00307 d = new KLFSearchBarPrivate;
00308
00309 u = new Ui::KLFSearchBar;
00310 u->setupUi(this);
00311
00312 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
00313
00314 u->txtSearch->installEventFilter(this);
00315 connect(u->btnSearchClear, SIGNAL(clicked()), this, SLOT(clear()));
00316 connect(u->txtSearch, SIGNAL(textChanged(const QString&)),
00317 this, SLOT(find(const QString&)));
00318 connect(u->btnFindNext, SIGNAL(clicked()), this, SLOT(findNext()));
00319 connect(u->btnFindPrev, SIGNAL(clicked()), this, SLOT(findPrev()));
00320
00321 QPalette defaultpal = u->txtSearch->palette();
00322 u->txtSearch->setProperty(palettePropName(Default).toLatin1(), QVariant::fromValue<QPalette>(defaultpal));
00323 QPalette pal0 = defaultpal;
00324 pal0.setColor(QPalette::Text, QColor(180,180,180));
00325 pal0.setColor(QPalette::WindowText, QColor(180,180,180));
00326 pal0.setColor(u->txtSearch->foregroundRole(), QColor(180,180,180));
00327 u->txtSearch->setProperty(palettePropName(FocusOut).toLatin1(), QVariant::fromValue<QPalette>(pal0));
00328
00329 setColorFound(QColor(128,255,128));
00330 setColorNotFound(QColor(255,128,128));
00331
00332 connect(u->btnHide, SIGNAL(clicked()), this, SLOT(hide()));
00333 setShowHideButton(false);
00334
00335 d->pResetTimeout = 10000;
00336 connect(&d->pFocusOutResetTimer, SIGNAL(timeout()), this, SLOT(slotSearchReset()));
00337
00338 d->pWaitLabel = new KLFWaitAnimationOverlay(u->txtSearch);
00339 d->pWaitLabel->setWaitMovie(":/pics/wait_anim.mng");
00340
00341
00342
00343
00344 d->pAutoHide = false;
00345
00346 d->pShowOverlayMode = false;
00347
00348
00349 d->pShowOverlayRelativeGeometry = QRect(QPoint(50, 95), QSize(90, 0));
00350
00351 d->pFocusOutText = " "+tr("Hit Ctrl-F, Ctrl-S or / to start searching");
00352
00353 d->pSearchForward = true;
00354 d->pSearchText = QString();
00355 d->pIsSearching = false;
00356 d->pCurPos = KLFPosSearchable::Pos();
00357 d->pLastPos = KLFPosSearchable::Pos();
00358 d->pState = FocusOut;
00359 displayState(FocusOut);
00360
00361 d->pIsFinding = false;
00362 d->pHasQueuedFind = false;
00363 d->pQueuedFindString = QString();
00364 d->pQueuedFindForward = true;
00365
00366 klfDbg("pCurPos is "<<d->pCurPos<<"; pLastPos is "<<d->pLastPos) ;
00367
00368 d->pUseEsbs = true;
00369 }
00370 KLFSearchBar::~KLFSearchBar()
00371 {
00372 delete d;
00373 }
00374
00375 QString KLFSearchBar::currentSearchText() const
00376 {
00377 if (d->pState == FocusOut)
00378 return QString();
00379 return u->txtSearch->text();
00380 }
00381
00382 QColor KLFSearchBar::colorFound() const
00383 {
00384 QPalette p = u->txtSearch->property(palettePropName(Found).toLatin1()).value<QPalette>();
00385 return p.color(QPalette::Base);
00386 }
00387 QColor KLFSearchBar::colorNotFound() const
00388 {
00389 QPalette p = u->txtSearch->property(palettePropName(NotFound).toLatin1()).value<QPalette>();
00390 return p.color(QPalette::Base);
00391 }
00392
00393 bool KLFSearchBar::hideButtonShown() const
00394 {
00395 return u->btnHide->isVisible();
00396 }
00397
00398 bool KLFSearchBar::showSearchLabel() const
00399 {
00400 return u->lblSearch->isVisible();
00401 }
00402
00403 bool KLFSearchBar::emacsStyleBackspace() const
00404 {
00405 return d->pUseEsbs;
00406 }
00407
00408 int KLFSearchBar::resetTimeout() const
00409 {
00410 return d->pResetTimeout;
00411 }
00412
00413 KLFPosSearchable::Pos KLFSearchBar::currentSearchPos() const
00414 {
00415 return d->pCurPos;
00416 }
00417
00418 KLFSearchBar::SearchState KLFSearchBar::currentState() const
00419 {
00420 return d->pState;
00421 }
00422
00423
00424 void KLFSearchBar::setColorFound(const QColor& color)
00425 {
00426 QPalette pal1 = u->txtSearch->property(palettePropName(Default).toLatin1()).value<QPalette>();
00427 pal1.setColor(QPalette::Base, color);
00428 pal1.setColor(QPalette::Window, color);
00429 pal1.setColor(u->txtSearch->backgroundRole(), color);
00430 u->txtSearch->setProperty(palettePropName(Found).toLatin1(), QVariant::fromValue<QPalette>(pal1));
00431 }
00432
00433 void KLFSearchBar::setColorNotFound(const QColor& color)
00434 {
00435 QPalette pal2 = u->txtSearch->property(palettePropName(Default).toLatin1()).value<QPalette>();
00436 pal2.setColor(QPalette::Base, color);
00437 pal2.setColor(QPalette::Window, color);
00438 pal2.setColor(u->txtSearch->backgroundRole(), color);
00439 u->txtSearch->setProperty(palettePropName(NotFound).toLatin1(), QVariant::fromValue<QPalette>(pal2));
00440 }
00441
00442 void KLFSearchBar::setShowHideButton(bool showHideButton)
00443 {
00444 u->btnHide->setVisible(showHideButton);
00445 }
00446
00447 void KLFSearchBar::setShowSearchLabel(bool on)
00448 {
00449 u->lblSearch->setVisible(on);
00450 }
00451
00452 void KLFSearchBar::setEmacsStyleBackspace(bool on)
00453 {
00454 if (d->pIsSearching)
00455 abortSearch();
00456 d->pUseEsbs = on;
00457 }
00458
00459 void KLFSearchBar::setResetTimeout(int ms)
00460 {
00461 d->pResetTimeout = ms;
00462 }
00463
00464
00466 #define DECLARE_SEARCH_SHORTCUT(shortcut, parent, slotmember) \
00467 { QShortcut *s = new QShortcut(parent); s->setKey(QKeySequence(shortcut)); \
00468 connect(s, SIGNAL(activated()), this, slotmember); }
00469
00470 void KLFSearchBar::registerShortcuts(QWidget *parent)
00471 {
00472 DECLARE_SEARCH_SHORTCUT(tr("Ctrl+F", "[[find]]"), parent, SLOT(focusOrNext()));
00473 DECLARE_SEARCH_SHORTCUT(tr("Ctrl+S", "[[find]]"), parent, SLOT(focusOrNext()));
00474 DECLARE_SEARCH_SHORTCUT(tr("Ctrl+G", "[[find]]"), parent, SLOT(focusOrNext()));
00475 DECLARE_SEARCH_SHORTCUT(tr("/", "[[find]]"), parent, SLOT(clear()));
00476 DECLARE_SEARCH_SHORTCUT(tr("F3", "[[find next]]"), parent, SLOT(findNext()));
00477 DECLARE_SEARCH_SHORTCUT(tr("Shift+F3", "[[find prev]]"), parent, SLOT(findPrev()));
00478 DECLARE_SEARCH_SHORTCUT(tr("Ctrl+R", "[[find rev]]"), parent, SLOT(focusOrPrev()));
00479
00480 }
00481
00482 void KLFSearchBar::setTarget(KLFTarget * target)
00483 {
00484 if (d->pIsSearching)
00485 abortSearch();
00486
00487 KLFPosSearchable *s = dynamic_cast<KLFPosSearchable*>(target);
00488 KLF_ASSERT_CONDITION( (s!=NULL) || (target==NULL),
00489 "target is not a valid KLFPosSearchable object !",
00490 return; ) ;
00491 KLFTargeter::setTarget(s);
00492 }
00493
00494 void KLFSearchBar::setSearchText(const QString& text)
00495 {
00496 u->txtSearch->setText(text);
00497 }
00498
00499 bool KLFSearchBar::autoHide() const
00500 {
00501 return d->pAutoHide;
00502 }
00503
00504 bool KLFSearchBar::showOverlayMode() const
00505 {
00506 return d->pShowOverlayMode;
00507 }
00508 QRect KLFSearchBar::showOverlayRelativeGeometry() const
00509 {
00510 return d->pShowOverlayRelativeGeometry;
00511 }
00512 QString KLFSearchBar::focusOutText() const
00513 {
00514 return d->pFocusOutText;
00515 }
00516
00517
00518 void KLFSearchBar::setFocusOutText(const QString& focusOutText)
00519 {
00520 d->pFocusOutText = focusOutText;
00521 if (d->pState == FocusOut) {
00522
00523 displayState(FocusOut);
00524 }
00525 }
00526
00527
00528 static KLFSearchBarPrivate::HistBuffer::CurLastPosPair
00529 esbs_get_last_pos(const QList<KLFSearchBarPrivate::HistBuffer>& hb, int offset = 0)
00530 {
00531 if (hb.size() <= offset) {
00532 return KLFSearchBarPrivate::HistBuffer::CurLastPosPair(KLFPosSearchable::Pos(),
00533 KLFPosSearchable::Pos());
00534 }
00535 const QList<KLFSearchBarPrivate::HistBuffer::CurLastPosPair>& poslist = hb[hb.size()-1 - offset].poslist;
00536
00537 if (poslist.isEmpty()) {
00538 return esbs_get_last_pos(hb, offset+1);
00539 }
00540 return poslist.last();
00541 }
00542
00543 bool KLFSearchBar::eventFilter(QObject *obj, QEvent *ev)
00544 {
00545 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00546
00547 if (obj == u->txtSearch) {
00548 if (ev->type() == QEvent::FocusIn) {
00549 klfDbg("focus-in event...") ;
00550 slotSearchFocusIn();
00551
00552 } else if (ev->type() == QEvent::FocusOut) {
00553 klfDbg("focus-out event...") ;
00554 slotSearchFocusOut();
00555
00556 } else if (ev->type() == QEvent::KeyPress) {
00557 klfDbg("key press event!") ;
00558 QKeyEvent *ke = (QKeyEvent*)ev;
00559 if (ke->key() == Qt::Key_Escape) {
00560 abortSearch();
00561 emit escapePressed();
00562 return true;
00563 }
00564
00565 if (d->pUseEsbs) {
00566
00567 if (ke->key() == Qt::Key_Backspace) {
00568
00569 if (d->pIsFinding) {
00570 KLF_ASSERT_CONDITION_ELSE(target()!=NULL, "Search Target is NULL!", ; ) {
00571 target()->setSearchInterruptRequested(true);
00572 return true;
00573 }
00574 }
00575 if ( ! d->esbs_histbuffer.size() ) {
00576
00577 promptEmptySearch();
00578 } else {
00579
00580 KLFSearchBarPrivate::HistBuffer& histbuf = d->esbs_histbuffer.last();
00581 if (histbuf.poslist.size() > 1) {
00582
00583 histbuf.poslist.pop_back();
00584 const KLFSearchBarPrivate::HistBuffer::CurLastPosPair& pos = histbuf.poslist.last();
00585
00586 KLF_ASSERT_CONDITION_ELSE(target()!=NULL, "Search Target is NULL!", ; ) {
00587 d->pCurPos = pos.cur;
00588 d->pLastPos = pos.last;
00589
00590 target()->searchMoveToPos(d->pCurPos);
00591 target()->searchPerformed(d->pSearchText, d->pCurPos.valid(), d->pCurPos);
00592 updateSearchFound(d->pCurPos.valid());
00593 emit hasMatch(d->pCurPos.valid());
00594 }
00595 } else {
00596 d->esbs_histbuffer.pop_back();
00597
00598 if (!d->esbs_histbuffer.size()) {
00599
00600 promptEmptySearch();
00601 } else {
00602
00603 d->pSearchText = d->esbs_histbuffer.last().str;
00604
00605 u->txtSearch->blockSignals(true);
00606 u->txtSearch->setText(d->pSearchText);
00607 u->txtSearch->blockSignals(false);
00608 const QList<KLFSearchBarPrivate::HistBuffer::CurLastPosPair> poslist
00609 = d->esbs_histbuffer.last().poslist;
00610 KLF_ASSERT_CONDITION_ELSE(target()!=NULL, "Search Target is NULL!", ; ) {
00611
00612 KLFSearchBarPrivate::HistBuffer::CurLastPosPair clpos = esbs_get_last_pos(d->esbs_histbuffer);
00613 d->pCurPos = clpos.cur;
00614 d->pLastPos = clpos.last;
00615
00616 target()->setSearchQueryString(d->pSearchText);
00617 if (poslist.isEmpty()) {
00618
00619 d->pCurPos = d->pLastPos;
00620 findNext(clpos.reachedForward);
00621 } else {
00622 target()->searchMoveToPos(d->pCurPos);
00623 target()->searchPerformed(d->pSearchText, d->pCurPos.valid(), d->pCurPos);
00624 updateSearchFound(d->pCurPos.valid());
00625 emitFoundSignals(d->pCurPos, d->pSearchText, clpos.reachedForward);
00626 emit hasMatch(d->pCurPos.valid());
00627 }
00628 }
00629 }
00630 }
00631 }
00632
00633 return true;
00634 } else if (ke->key() == Qt::Key_Left || ke->key() == Qt::Key_Right) {
00635
00636 return true;
00637 } else if (ke->key() == Qt::Key_Home || ke->key() == Qt::Key_End) {
00638
00639 return true;
00640 } else if (ke->text().size() && ke->text()[0].isPrint()) {
00641
00642
00643
00644 }
00645 }
00646 else {
00647 klfDbg("key press, but not using e-s-b-s.");
00648 return false;
00649 }
00650 }
00651
00652 }
00653 return QFrame::eventFilter(obj, ev);
00654 }
00655
00656 QLineEdit * KLFSearchBar::editor()
00657 {
00658 return u->txtSearch;
00659 }
00660
00661 void KLFSearchBar::setAutoHide(bool autohide)
00662 {
00663 klfDbg("autohide="<<autohide) ;
00664 d->pAutoHide = autohide;
00665 if (d->pAutoHide && !searchBarHasFocus() && !_isInQtDesigner)
00666 hide();
00667 }
00668
00669 void KLFSearchBar::setShowOverlayMode(bool overlayMode)
00670 {
00671 klfDbg("setting show overlay mode to "<<overlayMode) ;
00672 d->pShowOverlayMode = overlayMode;
00673 setProperty("klfShowOverlayMode", QVariant::fromValue<bool>(d->pShowOverlayMode));
00674
00675 setProperty("klfTopLevelWidget", QVariant::fromValue<bool>(d->pShowOverlayMode));
00676
00677 adjustOverlayGeometry();
00680 }
00681
00682 void KLFSearchBar::setShowOverlayRelativeGeometry(const QRect& relativeGeometryPercent)
00683 {
00684 d->pShowOverlayRelativeGeometry = relativeGeometryPercent;
00685 adjustOverlayGeometry();
00686 }
00687 void KLFSearchBar::setShowOverlayRelativeGeometry(int widthPercent, int heightPercent,
00688 int positionXPercent, int positionYPercent)
00689 {
00690 setShowOverlayRelativeGeometry(QRect(QPoint(positionXPercent, positionYPercent),
00691 QSize(widthPercent, heightPercent)));
00692 adjustOverlayGeometry();
00693 }
00694
00695
00696
00697 void KLFSearchBar::clear()
00698 {
00699 klfDbgT("clear") ;
00700 setSearchText("");
00701 focus();
00702 }
00703
00704 void KLFSearchBar::focusOrNext(bool forward)
00705 {
00706 d->pSearchForward = forward;
00707
00708 if (d->pState != FocusOut) {
00709 klfDbgT("already are in focus state") ;
00710
00711 if (!searchBarHasFocus())
00712 focus();
00713
00714
00715
00716 if (u->txtSearch->text().isEmpty()) {
00717 setSearchText(d->pLastSearchText);
00718 } else {
00719 if (!d->pIsSearching) {
00720 find(u->txtSearch->text(), forward);
00721 } else {
00722 findNext(forward);
00723 }
00724 }
00725 } else {
00726 klfDbgT("setting focus") ;
00727 setSearchText("");
00728 focus();
00729 }
00730 }
00731
00732 void KLFSearchBar::find(const QString& string)
00733 {
00734 find(string, d->pSearchForward);
00735 }
00736
00737 void KLFSearchBar::find(const QString& text, bool forward)
00738 {
00739 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00740 klfDbgT("text="<<text<<", forward="<<forward) ;
00741
00742 if (target() == NULL && text.isEmpty())
00743 return;
00744
00745 KLF_ASSERT_NOT_NULL( target() , "search target is NULL!", return ) ;
00746
00747 if (d->pIsFinding) {
00748 klfDbg("find()ing already. queueing and requesting to stop previous find.");
00749 target()->setSearchInterruptRequested(true);
00750 d->pHasQueuedFind = true;
00751 d->pQueuedFindString = text;
00752 d->pQueuedFindForward = forward;
00753 return;
00754 }
00755
00756 if ( text.isEmpty() ||
00757 (d->pUseEsbs && text.mid(0, d->pSearchText.size()) != d->pSearchText) ) {
00758 promptEmptySearch();
00759 return;
00760 }
00761
00762 if (!d->pIsSearching) {
00763 klfDbg("new search. find start from position.") ;
00764
00765 d->pCurPos = target()->searchStartFrom(forward);
00766 d->pLastPos = d->pCurPos;
00767 klfDbg("Starting from d->pCurPos="<<d->pCurPos) ;
00768 }
00769
00770 d->pIsSearching = true;
00771 d->pSearchText = text;
00772 performFind(forward, false);
00773 }
00774
00775
00776
00777 void KLFSearchBar::performFind(bool forward, bool isfindnext)
00778 {
00779 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00780
00781 KLF_ASSERT_NOT_NULL( target() , "search target is NULL!", return ) ;
00782
00783 if (!isfindnext) {
00784
00785 if (d->pUseEsbs) {
00786 KLFSearchBarPrivate::HistBuffer buf;
00787 buf.str = d->pSearchText;
00788 d->esbs_histbuffer << buf;
00789 }
00790 }
00791
00792 klfDbg("pSearchText="<<d->pSearchText<<"; pCurPos="<<d->pCurPos<<"; pLastPos="<<d->pLastPos) ;
00793
00794
00795 target()->setSearchInterruptRequested(false);
00796
00797 d->pIsFinding = true;
00798 d->pWaitLabel->startWait();
00799 target()->setSearchQueryString(d->pSearchText);
00800 klfDbg("pSearchText="<<d->pSearchText<<"; target()->searchQueryString()="<<target()->searchQueryString()) ;
00801 KLFPosSearchable::Pos pos = target()->searchFind(d->pSearchText, d->pLastPos, forward);
00802 d->pWaitLabel->stopWait();
00803 d->pIsFinding = false;
00804
00805 if (!d->pIsSearching) {
00806
00807 return;
00808 }
00809
00810 d->pCurPos = pos;
00811
00812 if (target()->searchHasInterruptRequested()) {
00813
00814 if (d->pHasQueuedFind) {
00815 QString s = d->pQueuedFindString;
00816 bool f = d->pQueuedFindForward;
00817 d->pHasQueuedFind = false;
00818 d->pQueuedFindString = QString();
00819 d->pQueuedFindForward = true;
00820 find(s, f);
00821 }
00822 return;
00823 }
00824
00825 target()->searchMoveToPos(d->pCurPos);
00826 target()->searchPerformed(d->pSearchText, d->pCurPos.valid(), d->pCurPos);
00827 updateSearchFound(d->pCurPos.valid());
00828 emitFoundSignals(d->pCurPos, d->pSearchText, forward);
00829 emit hasMatch(d->pCurPos.valid());
00830
00831 klfDbg("Are now at position pCurPos="<<d->pCurPos) ;
00832
00833 if (d->pUseEsbs) {
00834 KLF_ASSERT_CONDITION_ELSE(d->esbs_histbuffer.size(), "HistBuffer is empty!!", ;) {
00835 if (d->pCurPos.valid() ||
00836
00837 (d->esbs_histbuffer.last().poslist.isEmpty() ||
00838 d->esbs_histbuffer.last().poslist.last().cur.valid())) {
00839 d->esbs_histbuffer.last().poslist
00840 << KLFSearchBarPrivate::HistBuffer::CurLastPosPair(d->pCurPos, d->pLastPos, forward);
00841 }
00842 }
00843 }
00844 }
00845
00846 void KLFSearchBar::findNext(bool forward)
00847 {
00848 klfDbgT("forward="<<forward) ;
00849
00850 if (d->pIsFinding) {
00851 klfDbg("finding already. Must wait, ignoring request.");
00852 return;
00853 }
00854
00855
00856 if (!searchBarHasFocus())
00857 focus();
00858
00859 if (d->pSearchText.isEmpty()) {
00860 klfDbg("called but not in search mode. recalling history="<<d->pLastSearchText) ;
00861
00862
00863 showSearchBarText(d->pLastSearchText);
00864
00865
00866 find(u->txtSearch->text(), forward);
00867 return;
00868 }
00869
00870 KLF_ASSERT_NOT_NULL( pTarget , "Search target is NULL!" , return ) ;
00871
00872 d->pLastPos = d->pCurPos;
00873 d->pLastSearchText = d->pSearchText;
00874 performFind(forward, true);
00875 }
00876
00877 void KLFSearchBar::promptEmptySearch()
00878 {
00879 setCurrentState(Default);
00880 u->txtSearch->blockSignals(true);
00881 u->txtSearch->setText("");
00882 u->txtSearch->blockSignals(false);
00883 d->pSearchText = QString();
00884 d->pCurPos = KLFPosSearchable::Pos();
00885 d->pLastPos = KLFPosSearchable::Pos();
00886 if (target() != NULL) {
00887 klfDbg("telling target to reinitialize search...") ;
00888 if (d->pIsFinding)
00889 target()->setSearchInterruptRequested(true);
00890 target()->setSearchQueryString(QString());
00891 target()->searchMoveToPos(d->pCurPos);
00892 target()->searchReinitialized();
00893 emit searchReinitialized();
00894 emit hasMatch(d->pCurPos.valid());
00895 }
00896 }
00897
00898 void KLFSearchBar::abortSearch()
00899 {
00900 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00901
00904 d->pSearchText = QString();
00905 d->pIsSearching = false;
00906 d->pCurPos = KLFPosSearchable::Pos();
00907 d->pLastPos = KLFPosSearchable::Pos();
00908 klfDbg("pCurPos="<<d->pCurPos) ;
00909
00910 if ( ! u->txtSearch->text().isEmpty() ) {
00911 showSearchBarText("");
00912 }
00913 if (d->pUseEsbs)
00914 d->esbs_histbuffer.clear();
00915
00916 if (searchBarHasFocus()) {
00917 setCurrentState(Aborted);
00918 } else {
00919 setCurrentState(FocusOut);
00920 }
00921
00922 if (target() != NULL) {
00923 klfDbg("telling target to abort search...") ;
00924 if (d->pIsFinding)
00925 target()->setSearchInterruptRequested(true);
00926 target()->searchAborted();
00927 target()->setSearchQueryString(QString());
00928 klfDbg("...done") ;
00929 }
00930
00931 emit searchAborted();
00932 emit hasMatch(false);
00933 }
00934
00935 void KLFSearchBar::adjustOverlayGeometry()
00936 {
00937 if (d->pShowOverlayMode) {
00938 QWidget *pw = parentWidget();
00939 if (pw != NULL) {
00940
00941 QSize pws = pw->size();
00942
00943 QPoint relPos = d->pShowOverlayRelativeGeometry.topLeft();
00944 QSize relSz = d->pShowOverlayRelativeGeometry.size();
00945
00946 QSize sz = QSize(pws.width()*relSz.width()/100, pws.height()*relSz.height()/100);
00947 sz = sz.expandedTo(minimumSizeHint()) ;
00948 QRect gm = QRect( QPoint( (pws.width()-sz.width())*relPos.x()/100, (pws.height()-sz.height())*relPos.y()/100 ),
00949 sz );
00950 klfDbg("Geometry is "<<gm) ;
00951 setGeometry(gm);
00952
00953 setStyleSheet(styleSheet());
00954 raise();
00955 } else {
00956
00957 setWindowFlags(Qt::Tool);
00958
00959 setWindowOpacity(0.95);
00960 }
00961 }
00962 }
00963
00964 void KLFSearchBar::focus()
00965 {
00966 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00967
00968 if (d->pShowOverlayMode)
00969 adjustOverlayGeometry();
00970
00971 if (!isVisible()) {
00972
00973
00974 show();
00975 }
00976 u->txtSearch->setFocus();
00977 }
00978
00979 void KLFSearchBar::slotSearchFocusIn()
00980 {
00981 klfDbgT("focus in") ;
00982 if (d->pState != FocusOut) {
00983
00984 if (d->pFocusOutResetTimer.isActive()) {
00985 d->pFocusOutResetTimer.stop();
00986 }
00987 return;
00988 }
00989 setCurrentState(Default);
00990 showSearchBarText("");
00991 }
00992
00993 void KLFSearchBar::slotSearchFocusOut()
00994 {
00995 klfDbgT("focus out") ;
00996
00997 if (d->pResetTimeout == 0) {
00998 slotSearchReset();
00999 return;
01000 }
01001 if (d->pResetTimeout > 0) {
01002 d->pFocusOutResetTimer.setInterval(d->pResetTimeout);
01003 d->pFocusOutResetTimer.setSingleShot(true);
01004 d->pFocusOutResetTimer.start();
01005 return;
01006 }
01007
01008 }
01009
01010 void KLFSearchBar::slotSearchReset()
01011 {
01012 klfDbgT("search reset after focus out.");
01013
01014 if (d->pAutoHide && !_isInQtDesigner)
01015 hide();
01016
01017 abortSearch();
01018 }
01019
01020 void KLFSearchBar::updateSearchFound(bool found)
01021 {
01022 setCurrentState(found ? Found : NotFound);
01023 }
01024
01025
01026 QString KLFSearchBar::palettePropName(SearchState state) const
01027 {
01028 switch (state) {
01029 case Default: return QString("paletteDefault");
01030 case FocusOut: return QString("paletteFocusOut");
01031 case Found: return QString("paletteFound");
01032 case NotFound: return QString("paletteNotFound");
01033 case Aborted: return QString("paletteDefault");
01034 default:
01035 qWarning()<<KLF_FUNC_NAME<<": invalid state: "<<state;
01036 }
01037 return QString();
01038 }
01039
01040 QString KLFSearchBar::statePropValue(SearchState state) const
01041 {
01042 switch (state) {
01043 case Default: return QLatin1String("default");
01044 case FocusOut: return QLatin1String("focus-out");
01045 case Found: return QLatin1String("found");
01046 case NotFound: return QLatin1String("not-found");
01047 case Aborted: return QLatin1String("aborted");
01048 default: return QLatin1String("invalid");
01049 }
01050 }
01051
01052 void KLFSearchBar::setCurrentState(SearchState state)
01053 {
01054 klfDbg("state: "<<state) ;
01055
01056 if (d->pState == state)
01057 return;
01058
01059 d->pState = state;
01060 displayState(state);
01061 emit stateChanged(state);
01062 }
01063
01064 void KLFSearchBar::displayState(SearchState s)
01065 {
01066 klfDbg("Setting state: "<<statePropValue(s));
01067 u->txtSearch->setProperty("searchState", statePropValue(s));
01068 QPalette pal = u->txtSearch->property(palettePropName(s).toLatin1()).value<QPalette>();
01070 u->txtSearch->setStyleSheet(u->txtSearch->styleSheet());
01071 u->txtSearch->setPalette(pal);
01072 u->txtSearch->update();
01073
01074 if (s == FocusOut) {
01075 showSearchBarText(d->pFocusOutText);
01076 }
01077 }
01078
01079 void KLFSearchBar::emitFoundSignals(const KLFPosSearchable::Pos& pos, const QString& searchstring, bool forward)
01080 {
01081 bool resultfound = pos.valid();
01082 emit searchPerformed(resultfound);
01083 emit searchPerformed(searchstring, resultfound);
01084 if (resultfound) {
01085 emit found();
01086 emit found(d->pSearchText, forward);
01087 emit found(d->pSearchText, forward, pos);
01088 } else {
01089 emit didNotFind();
01090 emit didNotFind(d->pSearchText, forward);
01091 }
01092 }
01093
01094 void KLFSearchBar::showSearchBarText(const QString& text)
01095 {
01096 u->txtSearch->blockSignals(true);
01097 u->txtSearch->setText(text);
01098 if (d->pUseEsbs)
01099 d->esbs_histbuffer.clear();
01100 u->txtSearch->blockSignals(false);
01101 }
01102 bool KLFSearchBar::searchBarHasFocus()
01103 {
01104 return QApplication::focusWidget() == u->txtSearch;
01105 }
01106
01107
01108 bool KLFSearchBar::event(QEvent *event)
01109 {
01110 if (event->type() == QEvent::Polish)
01111 setMinimumSize(minimumSizeHint());
01112
01113 if (event->type() == QEvent::Show) {
01114 emit visibilityChanged(true);
01115 }
01116 if (event->type() == QEvent::Hide) {
01117 emit visibilityChanged(false);
01118 }
01119
01120 return QFrame::event(event);
01121 }