[KLF Backend][KLF Tools][KLF Home]
KLatexFormula Project
klfsearchbar.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * file klfsearchbar.cpp
3 * This file is part of the KLatexFormula Project.
4 * Copyright (C) 2011 by Philippe Faist
5 * philippe.faist at bluewin.ch
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22/* $Id$ */
23
24#include <QDebug>
25#include <QObject>
26#include <QFrame>
27#include <QLineEdit>
28#include <QEvent>
29#include <QKeyEvent>
30#include <QShortcut>
31#include <QKeySequence>
32#include <QTime>
33
34#include <klfguiutil.h>
35
36#include <ui_klfsearchbar.h>
37#include "klfsearchbar.h"
38#include "klfsearchbar_p.h"
39
40
41
135{
136 QString s;
137 s.sprintf("%p", (const void*)(const KLFPosSearchable::Pos::PosData*)pos.posdata);
138 str << "Pos("<<qPrintable(s);
139 if (pos.posdata != NULL) {
140 QString desc;
141 if (!(desc = pos.posdata->toDebug()).isEmpty())
142 str << " " << qPrintable(desc);
143 }
144 return str <<")";
145}
146
147// --
148
150{
151 klfDbg("start from: base implementation, will return invalid. forward="<<forward) ;
152 Q_UNUSED(forward) ;
153 return Pos();
154}
155
157{
158 klfDbg("on="<<on) ;
159 pInterruptRequested = on;
160}
161
162
163// ------------------------------------------------
164
165
167{
168}
169
171{
172 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return Pos() );
173 return target()->searchStartFrom(forward);
174}
175
176KLFPosSearchable::Pos KLFPosSearchableProxy::searchFind(const QString& queryString, const Pos& fromPos, bool forward)
177{
178 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return Pos() );
179 return target()->searchFind(queryString, fromPos, forward);
180}
181
183{
184 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
185 return target()->searchMoveToPos(pos);
186}
187
188void KLFPosSearchableProxy::searchPerformed(const QString& queryString, bool found, const Pos& pos)
189{
190 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
191 target()->searchPerformed(queryString, found, pos);
192}
193
195{
196 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
198}
199
201{
202 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
204}
205
207{
208 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return QString(); );
209 return target()->searchQueryString();
210}
211
213{
214 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
216}
217
219{
220 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return false; );
222}
223
225{
226 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return ; );
228}
229
230
231
232// ---
233
234struct DummySearchPosData : public KLFPosSearchable::Pos::PosData
235{
236 bool equals(PosData *) const { return true; }
237};
238
239
241{
242}
244{
245}
246
247KLFPosSearchable::Pos KLFSearchable::searchFind(const QString& queryString, const Pos& fromPos, bool forward)
248{
249 bool r;
250 // simulate first search, then 'find next', by detecting if we're required to search from a given pos
251 // (heuristic that will fail in special cases!!)
252 if (!fromPos.valid())
253 r = searchFind(queryString, forward);
254 else
255 r = searchFindNext(forward);
256 Pos p = Pos();
257 if (!r)
258 return p;
259 // return dummy valid pos
260 p.posdata = new DummySearchPosData;
261 return p;
262}
263
264
265// -----
266
268{
269}
270
272{
273 KLFSearchable *s = dynamic_cast<KLFSearchable*>(target);
274 KLF_ASSERT_CONDITION( (s!=NULL) || (target==NULL),
275 "target is not a valid KLFSearchable object !",
276 return; ) ;
278}
279
280bool KLFSearchableProxy::searchFind(const QString& queryString, bool forward)
281{
282 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return false );
283 return target()->searchFind(queryString, forward);
284}
286{
287 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return false );
288 return target()->searchFindNext(forward);
289}
291{
292 KLF_ASSERT_NOT_NULL( target(), "Search target is NULL!", return );
293 return target()->searchAbort();
294}
295
296
297// ------------------------
298
300 : QFrame(parent)
301{
303 klfDbg("parent: "<<parent) ;
304
305 _isInQtDesigner = false;
306
307 d = new KLFSearchBarPrivate;
308
309 u = new Ui::KLFSearchBar;
310 u->setupUi(this);
311
312 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
313
314 u->txtSearch->installEventFilter(this);
315 connect(u->btnSearchClear, SIGNAL(clicked()), this, SLOT(clear()));
316 connect(u->txtSearch, SIGNAL(textChanged(const QString&)),
317 this, SLOT(find(const QString&)));
318 connect(u->btnFindNext, SIGNAL(clicked()), this, SLOT(findNext()));
319 connect(u->btnFindPrev, SIGNAL(clicked()), this, SLOT(findPrev()));
320
321 QPalette defaultpal = u->txtSearch->palette();
322 u->txtSearch->setProperty(palettePropName(Default).toLatin1(), QVariant::fromValue<QPalette>(defaultpal));
323 QPalette pal0 = defaultpal;
324 pal0.setColor(QPalette::Text, QColor(180,180,180));
325 pal0.setColor(QPalette::WindowText, QColor(180,180,180));
326 pal0.setColor(u->txtSearch->foregroundRole(), QColor(180,180,180));
327 u->txtSearch->setProperty(palettePropName(FocusOut).toLatin1(), QVariant::fromValue<QPalette>(pal0));
328 // default found/not-found colors
329 setColorFound(QColor(128,255,128));
330 setColorNotFound(QColor(255,128,128));
331
332 connect(u->btnHide, SIGNAL(clicked()), this, SLOT(hide()));
333 setShowHideButton(false); // not shown by default
334
335 d->pResetTimeout = 10000;
336 connect(&d->pFocusOutResetTimer, SIGNAL(timeout()), this, SLOT(slotSearchReset()));
337
338 d->pWaitLabel = new KLFWaitAnimationOverlay(u->txtSearch);
339 d->pWaitLabel->setWaitMovie(":/pics/wait_anim.mng");
340 /* // amusing test
341 d->pWaitLabel->setWaitMovie("/home/philippe/projects/klf/artwork/experimental/packman_anim.gif");
342 */
343
344 d->pAutoHide = false;
345
346 d->pShowOverlayMode = false;
347 // default relative geometry: position at (50%, 95%) (centered, quasi-bottom)
348 // size of (90%, 0%) [remember: expanded to minimum size]
349 d->pShowOverlayRelativeGeometry = QRect(QPoint(50, 95), QSize(90, 0));
350
351 d->pFocusOutText = " "+tr("Hit Ctrl-F, Ctrl-S or / to start searching");
352
353 d->pSearchForward = true;
354 d->pSearchText = QString();
355 d->pIsSearching = false;
356 d->pCurPos = KLFPosSearchable::Pos();
357 d->pLastPos = KLFPosSearchable::Pos();
358 d->pState = FocusOut;
360
361 d->pIsFinding = false;
362 d->pHasQueuedFind = false;
363 d->pQueuedFindString = QString();
364 d->pQueuedFindForward = true;
365
366 klfDbg("pCurPos is "<<d->pCurPos<<"; pLastPos is "<<d->pLastPos) ;
367
368 d->pUseEsbs = true;
369}
371{
372 delete d;
373}
374
376{
377 if (d->pState == FocusOut)
378 return QString();
379 return u->txtSearch->text();
380}
381
383{
384 QPalette p = u->txtSearch->property(palettePropName(Found).toLatin1()).value<QPalette>();
385 return p.color(QPalette::Base);
386}
388{
389 QPalette p = u->txtSearch->property(palettePropName(NotFound).toLatin1()).value<QPalette>();
390 return p.color(QPalette::Base);
391}
392
394{
395 return u->btnHide->isVisible();
396}
397
399{
400 return u->lblSearch->isVisible();
401}
402
404{
405 return d->pUseEsbs;
406}
407
409{
410 return d->pResetTimeout;
411}
412
414{
415 return d->pCurPos;
416}
417
419{
420 return d->pState;
421}
422
423
425{
426 QPalette pal1 = u->txtSearch->property(palettePropName(Default).toLatin1()).value<QPalette>();
427 pal1.setColor(QPalette::Base, color);
428 pal1.setColor(QPalette::Window, color);
429 pal1.setColor(u->txtSearch->backgroundRole(), color);
430 u->txtSearch->setProperty(palettePropName(Found).toLatin1(), QVariant::fromValue<QPalette>(pal1));
431}
432
434{
435 QPalette pal2 = u->txtSearch->property(palettePropName(Default).toLatin1()).value<QPalette>();
436 pal2.setColor(QPalette::Base, color);
437 pal2.setColor(QPalette::Window, color);
438 pal2.setColor(u->txtSearch->backgroundRole(), color);
439 u->txtSearch->setProperty(palettePropName(NotFound).toLatin1(), QVariant::fromValue<QPalette>(pal2));
440}
441
442void KLFSearchBar::setShowHideButton(bool showHideButton)
443{
444 u->btnHide->setVisible(showHideButton);
445}
446
448{
449 u->lblSearch->setVisible(on);
450}
451
453{
454 if (d->pIsSearching)
455 abortSearch();
456 d->pUseEsbs = on;
457}
458
460{
461 d->pResetTimeout = ms;
462}
463
464
466#define DECLARE_SEARCH_SHORTCUT(shortcut, parent, slotmember) \
467 { QShortcut *s = new QShortcut(parent); s->setKey(QKeySequence(shortcut)); \
468 connect(s, SIGNAL(activated()), this, slotmember); }
469
471{
472 DECLARE_SEARCH_SHORTCUT(tr("Ctrl+F", "[[find]]"), parent, SLOT(focusOrNext()));
473 DECLARE_SEARCH_SHORTCUT(tr("Ctrl+S", "[[find]]"), parent, SLOT(focusOrNext()));
474 DECLARE_SEARCH_SHORTCUT(tr("Ctrl+G", "[[find]]"), parent, SLOT(focusOrNext()));
475 DECLARE_SEARCH_SHORTCUT(tr("/", "[[find]]"), parent, SLOT(clear()));
476 DECLARE_SEARCH_SHORTCUT(tr("F3", "[[find next]]"), parent, SLOT(findNext()));
477 DECLARE_SEARCH_SHORTCUT(tr("Shift+F3", "[[find prev]]"), parent, SLOT(findPrev()));
478 DECLARE_SEARCH_SHORTCUT(tr("Ctrl+R", "[[find rev]]"), parent, SLOT(focusOrPrev()));
479 // Esc will be captured through event filter so that it isn't too obstrusive...
480}
481
483{
484 if (d->pIsSearching)
485 abortSearch();
486
487 KLFPosSearchable *s = dynamic_cast<KLFPosSearchable*>(target);
488 KLF_ASSERT_CONDITION( (s!=NULL) || (target==NULL),
489 "target is not a valid KLFPosSearchable object !",
490 return; ) ;
492}
493
495{
496 u->txtSearch->setText(text);
497}
498
500{
501 return d->pAutoHide;
502}
503
505{
506 return d->pShowOverlayMode;
507}
509{
510 return d->pShowOverlayRelativeGeometry;
511}
513{
514 return d->pFocusOutText;
515}
516
517
518void KLFSearchBar::setFocusOutText(const QString& focusOutText)
519{
520 d->pFocusOutText = focusOutText;
521 if (d->pState == FocusOut) {
522 // re-display focus-out state
524 }
525}
526
527
528static KLFSearchBarPrivate::HistBuffer::CurLastPosPair
529/* */ esbs_get_last_pos(const QList<KLFSearchBarPrivate::HistBuffer>& hb, int offset = 0)
530{
531 if (hb.size() <= offset) { // there is no preceeding histbuffer
532 return KLFSearchBarPrivate::HistBuffer::CurLastPosPair(KLFPosSearchable::Pos(),
534 }
535 const QList<KLFSearchBarPrivate::HistBuffer::CurLastPosPair>& poslist = hb[hb.size()-1 - offset].poslist;
536
537 if (poslist.isEmpty()) {
538 return esbs_get_last_pos(hb, offset+1);
539 }
540 return poslist.last();
541}
542
544{
546
547 if (obj == u->txtSearch) {
548 if (ev->type() == QEvent::FocusIn) {
549 klfDbg("focus-in event...") ;
551 // don't eat event
552 } else if (ev->type() == QEvent::FocusOut) {
553 klfDbg("focus-out event...") ;
555 // don't eat event
556 } else if (ev->type() == QEvent::KeyPress) {
557 klfDbg("key press event!") ;
558 QKeyEvent *ke = (QKeyEvent*)ev;
559 if (ke->key() == Qt::Key_Escape) {
560 abortSearch();
561 emit escapePressed();
562 return true;
563 }
564 // Emacs-Style Backspace handling
565 if (d->pUseEsbs) {
566 // what kind of key press is this
567 if (ke->key() == Qt::Key_Backspace) {
568 // if searching, backspace interrupts the search.
569 if (d->pIsFinding) {
570 KLF_ASSERT_CONDITION_ELSE(target()!=NULL, "Search Target is NULL!", ; ) {
571 target()->setSearchInterruptRequested(true);
572 return true;
573 }
574 }
575 if ( ! d->esbs_histbuffer.size() ) {
576 // back to beginning of text buffer...
578 } else {
579 // there is a current history buffer
580 KLFSearchBarPrivate::HistBuffer& histbuf = d->esbs_histbuffer.last();
581 if (histbuf.poslist.size() > 1) {
582 // jump to previous match
583 histbuf.poslist.pop_back();
584 const KLFSearchBarPrivate::HistBuffer::CurLastPosPair& pos = histbuf.poslist.last();
585 // move to previous match
586 KLF_ASSERT_CONDITION_ELSE(target()!=NULL, "Search Target is NULL!", ; ) {
587 d->pCurPos = pos.cur;
588 d->pLastPos = pos.last;
589 // move to given pos, and present found result
590 target()->searchMoveToPos(d->pCurPos);
591 target()->searchPerformed(d->pSearchText, d->pCurPos.valid(), d->pCurPos);
592 updateSearchFound(d->pCurPos.valid());
593 emit hasMatch(d->pCurPos.valid());
594 }
595 } else {
596 d->esbs_histbuffer.pop_back();
597 // if there is left
598 if (!d->esbs_histbuffer.size()) {
599 // back to beginning of text buffer...
601 } else {
602 // remove last item in buffer
603 d->pSearchText = d->esbs_histbuffer.last().str;
604 // check if there actually is text left
605 u->txtSearch->blockSignals(true);
606 u->txtSearch->setText(d->pSearchText);
607 u->txtSearch->blockSignals(false);
609 = d->esbs_histbuffer.last().poslist;
610 KLF_ASSERT_CONDITION_ELSE(target()!=NULL, "Search Target is NULL!", ; ) {
611 // find the last position where we were
612 KLFSearchBarPrivate::HistBuffer::CurLastPosPair clpos = esbs_get_last_pos(d->esbs_histbuffer);
613 d->pCurPos = clpos.cur;
614 d->pLastPos = clpos.last;
615 // make sure query string is up-to-date
616 target()->setSearchQueryString(d->pSearchText);
617 if (poslist.isEmpty()) {
618 // can be the result of an interrupted find, search from the preceeding poslist
619 d->pCurPos = d->pLastPos;
620 findNext(clpos.reachedForward);
621 } else {
622 target()->searchMoveToPos(d->pCurPos);
623 target()->searchPerformed(d->pSearchText, d->pCurPos.valid(), d->pCurPos);
624 updateSearchFound(d->pCurPos.valid());
625 emitFoundSignals(d->pCurPos, d->pSearchText, clpos.reachedForward);
626 emit hasMatch(d->pCurPos.valid());
627 }
628 }
629 }
630 }
631 }
632 // in every case, eat the event
633 return true;
634 } else if (ke->key() == Qt::Key_Left || ke->key() == Qt::Key_Right) {
635 // no left/right navigation
636 return true;
637 } else if (ke->key() == Qt::Key_Home || ke->key() == Qt::Key_End) {
638 // don't allow text navigation
639 return true;
640 } else if (ke->text().size() && ke->text()[0].isPrint()) {
641 // pass on the event further to QLineEdit
642 // Also, it is in find() that will we will create a new HistBuffer for this exact
643 // new partial search string.
644 }
645 } // if (use e-s-b-s)
646 else {
647 klfDbg("key press, but not using e-s-b-s.");
648 return false;
649 }
650 } // if (is key-press)
651
652 }
653 return QFrame::eventFilter(obj, ev);
654}
655
657{
658 return u->txtSearch;
659}
660
661void KLFSearchBar::setAutoHide(bool autohide)
662{
663 klfDbg("autohide="<<autohide) ;
664 d->pAutoHide = autohide;
665 if (d->pAutoHide && !searchBarHasFocus() && !_isInQtDesigner)
666 hide();
667}
668
670{
671 klfDbg("setting show overlay mode to "<<overlayMode) ;
672 d->pShowOverlayMode = overlayMode;
673 setProperty("klfShowOverlayMode", QVariant::fromValue<bool>(d->pShowOverlayMode));
674 // cheat with klfTopLevelWidget property, set it always in show-overlay-mode
675 setProperty("klfTopLevelWidget", QVariant::fromValue<bool>(d->pShowOverlayMode));
676
677 adjustOverlayGeometry();
680}
681
682void KLFSearchBar::setShowOverlayRelativeGeometry(const QRect& relativeGeometryPercent)
683{
684 d->pShowOverlayRelativeGeometry = relativeGeometryPercent;
685 adjustOverlayGeometry();
686}
687void KLFSearchBar::setShowOverlayRelativeGeometry(int widthPercent, int heightPercent,
688 int positionXPercent, int positionYPercent)
689{
690 setShowOverlayRelativeGeometry(QRect(QPoint(positionXPercent, positionYPercent),
691 QSize(widthPercent, heightPercent)));
692 adjustOverlayGeometry();
693}
694
695
696
698{
699 klfDbgT("clear") ;
700 setSearchText("");
701 focus();
702}
703
705{
706 d->pSearchForward = forward;
707
708 if (d->pState != FocusOut) {
709 klfDbgT("already are in focus state") ;
710 // focus search bar if not yet focused.
711 if (!searchBarHasFocus())
712 focus();
713 // already has focus
714 // -> either recall history (if empty search text)
715 // -> or find next
716 if (u->txtSearch->text().isEmpty()) {
717 setSearchText(d->pLastSearchText);
718 } else {
719 if (!d->pIsSearching) {
720 find(u->txtSearch->text(), forward);
721 } else {
722 findNext(forward);
723 }
724 }
725 } else {
726 klfDbgT("setting focus") ;
727 setSearchText("");
728 focus();
729 }
730}
731
732void KLFSearchBar::find(const QString& string)
733{
734 find(string, d->pSearchForward);
735}
736
737void KLFSearchBar::find(const QString& text, bool forward)
738{
740 klfDbgT("text="<<text<<", forward="<<forward) ;
741
742 if (target() == NULL && text.isEmpty())
743 return;
744
745 KLF_ASSERT_NOT_NULL( target() , "search target is NULL!", return ) ;
746
747 if (d->pIsFinding) {
748 klfDbg("find()ing already. queueing and requesting to stop previous find.");
749 target()->setSearchInterruptRequested(true);
750 d->pHasQueuedFind = true;
751 d->pQueuedFindString = text;
752 d->pQueuedFindForward = forward;
753 return;
754 }
755
756 if ( text.isEmpty() ||
757 (d->pUseEsbs && text.mid(0, d->pSearchText.size()) != d->pSearchText) ) {
759 return;
760 }
761
762 if (!d->pIsSearching) {
763 klfDbg("new search. find start from position.") ;
764 // first find() call, started new search, start from suggested position
765 d->pCurPos = target()->searchStartFrom(forward);
766 d->pLastPos = d->pCurPos;
767 klfDbg("Starting from d->pCurPos="<<d->pCurPos) ;
768 }
769
770 d->pIsSearching = true;
771 d->pSearchText = text;
772 performFind(forward, false);
773}
774
775
776// private
777void KLFSearchBar::performFind(bool forward, bool isfindnext)
778{
780
781 KLF_ASSERT_NOT_NULL( target() , "search target is NULL!", return ) ;
782
783 if (!isfindnext) {
784 // prepare this esbs-hist-buffer
785 if (d->pUseEsbs) {
786 KLFSearchBarPrivate::HistBuffer buf;
787 buf.str = d->pSearchText;
788 d->esbs_histbuffer << buf;
789 }
790 }
791
792 klfDbg("pSearchText="<<d->pSearchText<<"; pCurPos="<<d->pCurPos<<"; pLastPos="<<d->pLastPos) ;
793
794 // reset the interrupt request flag
795 target()->setSearchInterruptRequested(false);
796
797 d->pIsFinding = true;
798 d->pWaitLabel->startWait();
799 target()->setSearchQueryString(d->pSearchText);
800 klfDbg("pSearchText="<<d->pSearchText<<"; target()->searchQueryString()="<<target()->searchQueryString()) ;
801 KLFPosSearchable::Pos pos = target()->searchFind(d->pSearchText, d->pLastPos, forward);
802 d->pWaitLabel->stopWait();
803 d->pIsFinding = false;
804
805 if (!d->pIsSearching) {
806 // search was aborted.
807 return;
808 }
809
810 d->pCurPos = pos;
811
812 if (target()->searchHasInterruptRequested()) {
813 // perform queued find
814 if (d->pHasQueuedFind) {
815 QString s = d->pQueuedFindString;
816 bool f = d->pQueuedFindForward;
817 d->pHasQueuedFind = false;
818 d->pQueuedFindString = QString();
819 d->pQueuedFindForward = true;
820 find(s, f);
821 }
822 return;
823 }
824
825 target()->searchMoveToPos(d->pCurPos);
826 target()->searchPerformed(d->pSearchText, d->pCurPos.valid(), d->pCurPos);
827 updateSearchFound(d->pCurPos.valid());
828 emitFoundSignals(d->pCurPos, d->pSearchText, forward);
829 emit hasMatch(d->pCurPos.valid());
830
831 klfDbg("Are now at position pCurPos="<<d->pCurPos) ;
832
833 if (d->pUseEsbs) {
834 KLF_ASSERT_CONDITION_ELSE(d->esbs_histbuffer.size(), "HistBuffer is empty!!", ;) {
835 if (d->pCurPos.valid() ||
836 // append invalid item only if poslist is empty or if the last poslist item is valid
837 (d->esbs_histbuffer.last().poslist.isEmpty() ||
838 d->esbs_histbuffer.last().poslist.last().cur.valid())) {
839 d->esbs_histbuffer.last().poslist
840 << KLFSearchBarPrivate::HistBuffer::CurLastPosPair(d->pCurPos, d->pLastPos, forward);
841 }
842 }
843 }
844}
845
846void KLFSearchBar::findNext(bool forward)
847{
848 klfDbgT("forward="<<forward) ;
849
850 if (d->pIsFinding) {
851 klfDbg("finding already. Must wait, ignoring request.");
852 return;
853 }
854
855 // focus search bar if not yet focused.
856 if (!searchBarHasFocus())
857 focus();
858
859 if (d->pSearchText.isEmpty()) {
860 klfDbg("called but not in search mode. recalling history="<<d->pLastSearchText) ;
861 // we're not in search mode
862 // recall history
863 showSearchBarText(d->pLastSearchText);
864
865 // and initiate search mode
866 find(u->txtSearch->text(), forward);
867 return;
868 }
869
870 KLF_ASSERT_NOT_NULL( pTarget , "Search target is NULL!" , return ) ;
871
872 d->pLastPos = d->pCurPos; // precisely, find _next_
873 d->pLastSearchText = d->pSearchText;
874 performFind(forward, true);
875}
876
878{
880 u->txtSearch->blockSignals(true);
881 u->txtSearch->setText("");
882 u->txtSearch->blockSignals(false);
883 d->pSearchText = QString();
884 d->pCurPos = KLFPosSearchable::Pos();
885 d->pLastPos = KLFPosSearchable::Pos();
886 if (target() != NULL) {
887 klfDbg("telling target to reinitialize search...") ;
888 if (d->pIsFinding)
889 target()->setSearchInterruptRequested(true);
890 target()->setSearchQueryString(QString());
891 target()->searchMoveToPos(d->pCurPos);
892 target()->searchReinitialized();
893 emit searchReinitialized();
894 emit hasMatch(d->pCurPos.valid());
895 }
896}
897
899{
901
904 d->pSearchText = QString();
905 d->pIsSearching = false;
906 d->pCurPos = KLFPosSearchable::Pos();
907 d->pLastPos = KLFPosSearchable::Pos();
908 klfDbg("pCurPos="<<d->pCurPos) ;
909
910 if ( ! u->txtSearch->text().isEmpty() ) {
912 }
913 if (d->pUseEsbs)
914 d->esbs_histbuffer.clear();
915
916 if (searchBarHasFocus()) {
918 } else {
920 }
921
922 if (target() != NULL) {
923 klfDbg("telling target to abort search...") ;
924 if (d->pIsFinding)
925 target()->setSearchInterruptRequested(true);
926 target()->searchAborted();
927 target()->setSearchQueryString(QString());
928 klfDbg("...done") ;
929 }
930
931 emit searchAborted();
932 emit hasMatch(false);
933}
934
935void KLFSearchBar::adjustOverlayGeometry()
936{
937 if (d->pShowOverlayMode) {
938 QWidget *pw = parentWidget();
939 if (pw != NULL) {
940 // if we have a parent widget, adjust using our relative geometry
941 QSize pws = pw->size();
942
943 QPoint relPos = d->pShowOverlayRelativeGeometry.topLeft();
944 QSize relSz = d->pShowOverlayRelativeGeometry.size();
945
946 QSize sz = QSize(pws.width()*relSz.width()/100, pws.height()*relSz.height()/100);
947 sz = sz.expandedTo(minimumSizeHint()) ;
948 QRect gm = QRect( QPoint( (pws.width()-sz.width())*relPos.x()/100, (pws.height()-sz.height())*relPos.y()/100 ),
949 sz );
950 klfDbg("Geometry is "<<gm) ;
951 setGeometry(gm);
952 // setAutoFillBackground(true);
953 setStyleSheet(styleSheet());
954 raise();
955 } else {
956 // set some widget window flags if we're parent-less...
957 setWindowFlags(Qt::Tool);
958 // just for fun...
959 setWindowOpacity(0.95);
960 }
961 }
962}
963
965{
967
968 if (d->pShowOverlayMode)
969 adjustOverlayGeometry();
970
971 if (!isVisible()) {
972 // show the search bar. This works with in overlay mode as well as when the widget is hidden
973 // with the hide button.
974 show();
975 }
976 u->txtSearch->setFocus();
977}
978
980{
981 klfDbgT("focus in") ;
982 if (d->pState != FocusOut) {
983 // don't have to reinitialize from focusout state.
984 if (d->pFocusOutResetTimer.isActive()) {
985 d->pFocusOutResetTimer.stop();
986 }
987 return;
988 }
991}
992
994{
995 klfDbgT("focus out") ;
996
997 if (d->pResetTimeout == 0) {
999 return;
1000 }
1001 if (d->pResetTimeout > 0) {
1002 d->pFocusOutResetTimer.setInterval(d->pResetTimeout);
1003 d->pFocusOutResetTimer.setSingleShot(true);
1004 d->pFocusOutResetTimer.start();
1005 return;
1006 }
1007 // if d->pResetTimeout < 0, do not abort search.
1008}
1009
1011{
1012 klfDbgT("search reset after focus out.");
1013
1014 if (d->pAutoHide && !_isInQtDesigner)
1015 hide();
1016
1017 abortSearch();
1018}
1019
1021{
1023}
1024
1025// private
1026QString KLFSearchBar::palettePropName(SearchState state) const
1027{
1028 switch (state) {
1029 case Default: return QString("paletteDefault");
1030 case FocusOut: return QString("paletteFocusOut");
1031 case Found: return QString("paletteFound");
1032 case NotFound: return QString("paletteNotFound");
1033 case Aborted: return QString("paletteDefault");
1034 default:
1035 qWarning()<<KLF_FUNC_NAME<<": invalid state: "<<state;
1036 }
1037 return QString();
1038}
1039// private
1040QString KLFSearchBar::statePropValue(SearchState state) const
1041{
1042 switch (state) {
1043 case Default: return QLatin1String("default");
1044 case FocusOut: return QLatin1String("focus-out");
1045 case Found: return QLatin1String("found");
1046 case NotFound: return QLatin1String("not-found");
1047 case Aborted: return QLatin1String("aborted");
1048 default: return QLatin1String("invalid");
1049 }
1050}
1051
1053{
1054 klfDbg("state: "<<state) ;
1055
1056 if (d->pState == state)
1057 return;
1058
1059 d->pState = state;
1060 displayState(state);
1061 emit stateChanged(state);
1062}
1063
1065{
1066 klfDbg("Setting state: "<<statePropValue(s));
1067 u->txtSearch->setProperty("searchState", statePropValue(s));
1068 QPalette pal = u->txtSearch->property(palettePropName(s).toLatin1()).value<QPalette>();
1070 u->txtSearch->setStyleSheet(u->txtSearch->styleSheet());
1071 u->txtSearch->setPalette(pal);
1072 u->txtSearch->update();
1073
1074 if (s == FocusOut) {
1075 showSearchBarText(d->pFocusOutText);
1076 }
1077}
1078
1079void KLFSearchBar::emitFoundSignals(const KLFPosSearchable::Pos& pos, const QString& searchstring, bool forward)
1080{
1081 bool resultfound = pos.valid();
1082 emit searchPerformed(resultfound);
1083 emit searchPerformed(searchstring, resultfound);
1084 if (resultfound) {
1085 emit found();
1086 emit found(d->pSearchText, forward);
1087 emit found(d->pSearchText, forward, pos);
1088 } else {
1089 emit didNotFind();
1090 emit didNotFind(d->pSearchText, forward);
1091 }
1092}
1093
1095{
1096 u->txtSearch->blockSignals(true);
1097 u->txtSearch->setText(text);
1098 if (d->pUseEsbs)
1099 d->esbs_histbuffer.clear();
1100 u->txtSearch->blockSignals(false);
1101}
1103{
1104 return QApplication::focusWidget() == u->txtSearch;
1105}
1106
1107
1109{
1110 if (event->type() == QEvent::Polish)
1111 setMinimumSize(minimumSizeHint());
1112
1113 if (event->type() == QEvent::Show) {
1114 emit visibilityChanged(true);
1115 }
1116 if (event->type() == QEvent::Hide) {
1117 emit visibilityChanged(false);
1118 }
1119
1120 return QFrame::event(event);
1121}
An object that can be searched with a KLFSearchBar.
Definition: klfsearchbar.h:74
virtual bool searchHasInterruptRequested()
Definition: klfsearchbar.h:286
virtual void searchMoveToPos(const Pos &pos)
Definition: klfsearchbar.h:256
virtual void searchAborted()=0
virtual Pos searchStartFrom(bool forward)
virtual QString searchQueryString() const
The current query string.
Definition: klfsearchbar.h:279
virtual Pos searchFind(const QString &queryString, const Pos &fromPos, bool forward)=0
virtual void searchPerformed(const QString &queryString, bool found, const Pos &pos)
Definition: klfsearchbar.h:262
virtual void setSearchQueryString(const QString &s)
Definition: klfsearchbar.h:284
virtual void searchReinitialized()
Definition: klfsearchbar.h:272
virtual void setSearchInterruptRequested(bool on)
virtual void searchMoveToPos(const Pos &pos)
virtual Pos searchStartFrom(bool forward)
virtual bool searchHasInterruptRequested()
virtual void searchAborted()
virtual void setSearchQueryString(const QString &s)
virtual ~KLFPosSearchableProxy()
virtual void searchPerformed(const QString &queryString, bool found, const Pos &pos)
virtual void searchReinitialized()
virtual Pos searchFind(const QString &queryString, const Pos &fromPos, bool forward)
virtual QString searchQueryString() const
virtual void setSearchInterruptRequested(bool on)
virtual KLFPosSearchable * target()
Definition: klfsearchbar.h:318
void setShowHideButton(bool showHideButton)
KLFPosSearchable::Pos currentSearchPos() const
QColor colorFound
Definition: klfsearchbar.h:474
void setColorFound(const QColor &color)
QLineEdit * editor()
virtual ~KLFSearchBar()
bool showSearchLabel
Definition: klfsearchbar.h:477
bool showHideButton
Definition: klfsearchbar.h:476
virtual void slotSearchReset()
void hasMatch(bool hasmatch)
Reflects whether the search is currently pointing on a valid result.
bool searchBarHasFocus()
Ui::KLFSearchBar * u
Definition: klfsearchbar.h:586
void setColorNotFound(const QColor &color)
virtual void updateSearchFound(bool found)
QString currentSearchText
Definition: klfsearchbar.h:468
bool showOverlayMode
Definition: klfsearchbar.h:470
void visibilityChanged(bool isShown)
QRect showOverlayRelativeGeometry
Definition: klfsearchbar.h:472
void setShowSearchLabel(bool show)
virtual void setSearchText(const QString &text)
void escapePressed()
virtual void registerShortcuts(QWidget *parent)
void findNext(bool forward=true)
virtual void displayState(SearchState state)
void find(const QString &string)
void didNotFind()
void searchAborted()
void setFocusOutText(const QString &focusOutText)
void stateChanged(SearchState state)
void setAutoHide(bool autohide)
virtual bool eventFilter(QObject *obj, QEvent *ev)
void setResetTimeout(int ms)
void emitFoundSignals(const KLFPosSearchable::Pos &pos, const QString &searchstring, bool forward)
void promptEmptySearch()
bool emacsStyleBackspace
Definition: klfsearchbar.h:478
QColor colorNotFound
Definition: klfsearchbar.h:475
bool hideButtonShown() const
void searchPerformed(bool found)
void setEmacsStyleBackspace(bool on)
void findPrev()
Definition: klfsearchbar.h:577
virtual void slotSearchFocusIn()
void focusOrPrev()
Definition: klfsearchbar.h:573
void setShowOverlayRelativeGeometry(const QRect &relativeGeometryPercent)
void showSearchBarText(const QString &text)
QString focusOutText
Definition: klfsearchbar.h:473
KLFSearchBar(QWidget *parent=NULL)
bool _isInQtDesigner
Definition: klfsearchbar.h:594
void setCurrentState(SearchState state)
virtual bool event(QEvent *event)
virtual void setTarget(KLFTarget *target)
void abortSearch()
void setShowOverlayMode(bool showOverlayMode)
SearchState currentState() const
virtual void slotSearchFocusOut()
void focusOrNext(bool forward=true)
void searchReinitialized()
An interface for objects that can be I-searched with a KLFSearchBar (OBSOLETE)
Definition: klfsearchbar.h:347
virtual bool searchFindNext(bool forward)=0
Find next or previous occurence of query string.
virtual ~KLFSearchable()
virtual void searchAbort()=0
Abort I-Search.
virtual bool searchFind(const QString &queryString, bool forward)=0
Find the first occurence of a query string.
virtual ~KLFSearchableProxy()
virtual KLFSearchable * target()
Definition: klfsearchbar.h:426
virtual void setTarget(KLFTarget *target)
virtual bool searchFind(const QString &queryString, bool forward)
virtual void searchAbort()
virtual bool searchFindNext(bool forward)
KLFTarget * pTarget
Definition: klfutil.h:530
virtual void setTarget(KLFTarget *target)
Definition: klfutil.cpp:667
An animation display.
Definition: klfguiutil.h:413
#define KLF_DEBUG_TIME_BLOCK(msg)
Utility to time the execution of a block.
#define KLF_ASSERT_CONDITION_ELSE(expr, msg, failaction)
Asserting Conditions previous to block (NON-FATAL)
#define KLF_DEBUG_BLOCK(msg)
Utility to debug the execution of a block.
#define KLF_ASSERT_NOT_NULL(ptr, msg, failaction)
Asserting Non-NULL pointers (NON-FATAL)
#define KLF_ASSERT_CONDITION(expr, msg, failaction)
Asserting Conditions (NON-FATAL)
#define klfDbgT(streamableItems)
print debug stream items, with current time
#define KLF_FUNC_NAME
#define klfDbg(streamableItems)
print debug stream items
#define DECLARE_SEARCH_SHORTCUT(shortcut, parent, slotmember)
QDebug & operator<<(QDebug &str, const KLFPosSearchable::Pos &pos)
Type type() const
int key() const
QString text() const
bool isEmpty() const
T & last()
int size() const
const QColor & color(ColorGroup group, ColorRole role) const
void setColor(ColorGroup group, ColorRole role, const QColor &color)
int x() const
int y() const
QSize expandedTo(const QSize &otherSize) const
int height() const
int width() const
QString & sprintf(const char *cformat,...)
bool isEmpty() const
QString mid(int position, int n) const
int size() const
QByteArray toLatin1() const
A Base class for storing abstract position data.
Definition: klfsearchbar.h:124
virtual bool equals(PosData *other) const =0
An abstract position in a searchable object.
Definition: klfsearchbar.h:97
KLFRefPtr< PosData > posdata
Stores the actual position data, see PosData.
Definition: klfsearchbar.h:196

Generated by doxygen 1.9.5