[KLF Application][KLF Tools][KLF Backend][KLF Home]
KLatexFormula Project

src/klftools/klfiteratorsearchable.h

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   file klfiteratorsearchable.h
00003  *   This file is part of the KLatexFormula Project.
00004  *   Copyright (C) 2010 by Philippe Faist
00005  *   philippe.faist at bluewin.ch
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 /* $Id: klfiteratorsearchable.h 497 2010-09-21 00:08:27Z philippe $ */
00023 
00024 #ifndef KLF_ITERATORSEARCHABLE_H
00025 #define KLF_ITERATORSEARCHABLE_H
00026 
00027 #include <QString>
00028 #include <QTime>
00029 #include <QApplication>
00030 
00031 #include <klfdefs.h>
00032 #include <klfsearchbar.h>
00033 
00034 
00036 
00068 template<class Iter>
00069 class KLF_EXPORT KLFIteratorSearchable : public KLFSearchable
00070 {
00071 public:
00072   KLFIteratorSearchable() : KLFSearchable(), pSearchAborted(false) { }
00073   virtual ~KLFIteratorSearchable() { }
00074 
00075   typedef Iter SearchIterator;
00076 
00077 
00078   // FUNCTIONS TO ACCESS SEARCHABLE DATA (REIMPLEMENT TO FIT YOUR NEEDS)
00079 
00082   virtual SearchIterator searchIterBegin() = 0;
00083 
00087   virtual SearchIterator searchIterEnd() = 0;
00088 
00091   virtual SearchIterator searchIterAdvance(const SearchIterator& pos, bool forward) { return forward ? (pos+1) : (pos-1); }
00092 
00094   inline SearchIterator searchIterNext(const SearchIterator& pos) { return searchIterAdvance(pos, true); }
00095 
00097   inline SearchIterator searchIterPrev(const SearchIterator& pos) { return searchIterAdvance(pos, false); }
00098 
00107   virtual SearchIterator searchIterStartFrom(bool forward)
00108   { return forward ? searchIterBegin() : searchIterEnd(); }
00109 
00115   virtual bool searchIterMatches(const SearchIterator& pos, const QString& queryString) = 0;
00116 
00117 
00126   virtual void searchPerformed(const SearchIterator& resultMatchPosition) { Q_UNUSED(resultMatchPosition); }
00127 
00128 
00129   // FUNCTIONS THAT PERFORM THE SEARCH (NO NEED TO REIMPLEMENT)
00130 
00132 
00145   virtual SearchIterator searchIterFind(const SearchIterator& startPos, const QString& queryString, bool forward)
00146   {
00147     klfDbg( " s="<<queryString<<" from "<<startPos<<" forward="<<forward ) ;
00148     // start searching from pCurPos _included_, but findNext() immediately increments to next position. so
00149     // simply go back one position before calling findNext()
00150     // however when finding reverse we are searching from pos _not inclusive_, see function dox doc
00151     if (forward)
00152       pCurPos = safe_cycl_advance_iterator(startPos, !forward);
00153     pSearchAborted = false;
00154     pQString = queryString;
00155     SearchIterator it = searchIterFindNext(forward);
00156     return it;
00157   }
00158 
00160 
00165   virtual SearchIterator searchIterFindNext(bool forward)
00166   {
00167     KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00168     pSearchAborted = false;
00169     if (pQString.isEmpty())
00170       return tee_notify_search_result(searchIterEnd());
00171     
00172     QTime t;
00173     
00174     bool found = false;
00175     while ( ! found ) {
00176       // advance iterator.
00177       
00178       pCurPos = safe_cycl_advance_iterator(pCurPos, forward);
00179 
00180       // stop if we reached the end
00181       if (pCurPos == searchIterEnd())
00182         break;
00183       
00184       // at this point pCurPos points on something valid
00185       
00186       if ( searchIterMatches(pCurPos, pQString) ) {
00187         found = true;
00188         break;
00189       }
00190       
00191       // call application's processEvents() from time to time to prevent GUI from freezing
00192       if (t.elapsed() > 150) {
00193         qApp->processEvents();
00194         if (pSearchAborted)
00195           break;
00196         t.restart();
00197       }
00198     }
00199     if (found) {
00200       klfDbg( "found "<<pQString<<" at "<<pCurPos ) ;
00201       return tee_notify_search_result(pCurPos);
00202     }
00203     
00204     // not found
00205     return tee_notify_search_result(searchIterEnd());
00206   }
00207 
00208 
00209   // reimplemented from KLFSearchable (do not reimplement)
00210 
00211   /* Calls searchIterFind() with searchIterStartFrom() as start position.
00212    *
00213    * This function need not be reimplemented, the default implementation should suffice for most cases. */
00214   virtual bool searchFind(const QString& queryString, bool forward)
00215   {
00216     KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00217     return KLF_DEBUG_TEE( ! (searchIterFind(searchIterStartFrom(forward), queryString, forward)
00218                              == searchIterEnd()) );
00219   }
00220 
00221   /* Calls searchIterFindNext().
00222    *
00223    * This function need not be reimplemented, the default implementation should suffice for most cases. */
00224   virtual bool searchFindNext(bool forward)
00225   {
00226     KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00227     return KLF_DEBUG_TEE( ! (searchIterFindNext(forward) == searchIterEnd()) );
00228   }
00229 
00230   /* Aborts the search.
00231    *
00232    * If you reimplement this function to perform additional actions when aborting searches, make sure you
00233    * call the base class implementation, since searchAbort() may be called by the event loop while
00234    * refreshing the GUI during an active search, in which case the base implementation of this function
00235    * tells the search to stop.
00236    *
00237    * This function need not be reimplemented, the default implementation should suffice for most cases. */
00238   virtual void searchAbort()
00239   {
00240     pSearchAborted = true;
00241   }
00242 
00252   SearchIterator searchAdvanceIteratorSafe(const SearchIterator& it, int n = 1)
00253   {
00254     if (n == 0)
00255       return it;
00256     bool forward = (n>0);
00257     if (n < 0)
00258       n = -n;
00259     // 'n' is number of steps (positive) to perform in direction 'forward'
00260     SearchIterator a = it;
00261     while (n--)
00262       a = safe_cycl_advance_iterator(a, forward);
00263 
00264     return a;
00265   }
00266 
00267 protected:
00268 
00269   inline QString searchQueryString() const { return pQString; }
00270   inline SearchIterator searchCurrentIterPos() const { return pCurPos; }
00271 
00272 private:
00273   QString pQString;
00275   SearchIterator pCurPos;
00277   bool pSearchAborted;
00278 
00279   inline SearchIterator tee_notify_search_result(const SearchIterator& iter)
00280   {
00281     searchPerformed(iter);
00282     return iter;
00283   }
00284 
00285   inline SearchIterator safe_cycl_advance_iterator(const SearchIterator& it, bool forward)
00286   {
00287     if (forward) {
00288       if (it == searchIterEnd())
00289         return searchIterBegin();
00290       return searchIterNext(it);
00291     } else {
00292       if (it == searchIterBegin())
00293         return searchIterEnd();
00294       return searchIterPrev(it);
00295     }
00296   }
00297 };
00298 
00299 
00300 
00301 #endif

Generated by doxygen 1.7.3