[KLF Backend][KLF Tools][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) 2011 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$ */
00023 
00024 #ifndef KLF_ITERATORSEARCHABLE_H
00025 #define KLF_ITERATORSEARCHABLE_H
00026 
00027 #include <QDebug>
00028 #include <QObject>
00029 #include <QString>
00030 #include <QApplication>
00031 #include <QTime>
00032 #include <QEvent>
00033 #include <QLineEdit>
00034 
00035 #include <klfdefs.h>
00036 #include <klfsearchbar.h>
00037 
00038 
00040 
00072 template<class Iter>
00073 class KLF_EXPORT KLFIteratorSearchable : public KLFPosSearchable
00074 {
00075 public:
00076   KLFIteratorSearchable() : KLFPosSearchable()
00077   {
00078   }
00079 
00080   virtual ~KLFIteratorSearchable()
00081   {
00082   }
00083 
00084   typedef Iter SearchIterator;
00085 
00086 
00087   // FUNCTIONS TO ACCESS SEARCHABLE DATA (REIMPLEMENT TO FIT YOUR NEEDS)
00088 
00091   virtual SearchIterator searchIterBegin() = 0;
00092 
00096   virtual SearchIterator searchIterEnd() = 0;
00097 
00100   virtual SearchIterator searchIterAdvance(const SearchIterator& pos, bool forward) = 0;
00101 
00103   inline SearchIterator searchIterNext(const SearchIterator& pos) { return searchIterAdvance(pos, true); }
00104 
00106   inline SearchIterator searchIterPrev(const SearchIterator& pos) { return searchIterAdvance(pos, false); }
00107 
00115   virtual SearchIterator searchIterStartFrom(bool forward)
00116   {  Q_UNUSED(forward);  return searchIterEnd();  }
00117 
00123   virtual bool searchIterMatches(const SearchIterator& pos, const QString& queryString) = 0;
00124 
00125 
00134   virtual void searchPerformed(const SearchIterator& resultMatchPosition, bool found, const QString& queryString)
00135   {  Q_UNUSED(resultMatchPosition); Q_UNUSED(found); Q_UNUSED(queryString);  }
00136 
00140   virtual void searchMoveToIterPos(const SearchIterator& pos)
00141   {  Q_UNUSED(pos);  }
00142 
00147   virtual void searchPerformed(const SearchIterator& resultMatchPosition)
00148   {  Q_UNUSED(resultMatchPosition);  }
00149 
00150 
00151   /* Aborts the search.
00152    *
00153    * If you reimplement this function to perform additional actions when aborting searches, make sure you
00154    * call the base class implementation, since searchAbort() may be called by the event loop while
00155    * refreshing the GUI during an active search, in which case the base implementation of this function
00156    * tells the search to stop.
00157    */
00158   virtual void searchAborted()
00159   {
00160     setSearchInterruptRequested(true);
00161   }
00162 
00163 
00164 
00165   // REIMPLEMENTATIONS THAT TRANSLATE POS OBJECTS TO ITERATORS
00166   // ... don't reimplement unless really necessary.
00167 
00168   virtual Pos searchStartFrom(bool forward)
00169   {
00170     KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00171     return posForIterator(searchIterStartFrom(forward));
00172   }
00173 
00176   virtual void searchPerformed(const QString& queryString, bool found, const Pos& pos)
00177   {
00178     searchPerformed(iteratorForPos(pos), found, queryString);
00179     searchPerformed(iteratorForPos(pos));
00180   }
00181 
00182   virtual void searchMoveToPos(const Pos& pos)
00183   {
00184     searchMoveToIterPos(iteratorForPos(pos));
00185   }
00186 
00187 
00188   // FUNCTIONS THAT PERFORM THE SEARCH
00189   // ... don't reimplement unless _ABSOLUTELY_ necessary.
00190 
00192 
00201   virtual SearchIterator searchIterFind(const SearchIterator& startPos, const QString& queryString, bool forward)
00202   {
00203     KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00204     Q_UNUSED(queryString) ;
00205     klfDbg( " s="<<queryString<<" from "<<startPos<<" forward="<<forward
00206             <<"; searchQueryString()="<<searchQueryString() ) ;
00207     pCurPos = startPos;
00208     SearchIterator it = searchIterFindNext(forward);
00209     return it;
00210   }
00211 
00213 
00218   virtual SearchIterator searchIterFindNext(bool forward)
00219   {
00220     KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00221 
00222     if (searchQueryString().isEmpty()) {
00223       klfDbg("empty search query string.") ;
00224       return tee_notify_search_result(searchIterEnd());
00225     }
00226     
00227     QTime t;
00228     
00229     bool found = false;
00230     while ( ! found ) {
00231       klfDbg("advancing iterator in search... pCurPos="<<pCurPos) ;
00232       // advance iterator.
00233       
00234       pCurPos = safe_cycl_advance_iterator(pCurPos, forward);
00235 
00236       klfDbg("advanced. pCurPos="<<pCurPos) ;
00237 
00238       // stop if we reached the end
00239       if (pCurPos == searchIterEnd())
00240         break;
00241       
00242       // at this point pCurPos points on something valid
00243       
00244       if ( searchIterMatches(pCurPos, searchQueryString()) ) {
00245         found = true;
00246         break;
00247       }
00248       
00249       // call application's processEvents() from time to time to prevent GUI from freezing
00250       if (t.elapsed() > 150) {
00251         qApp->processEvents();
00252         if (searchHasInterruptRequested()) {
00253           klfDbg("interrupting...") ;
00254           break;
00255         }
00256         t.restart();
00257       }
00258     }
00259     if (found) {
00260       klfDbg( "found "<<searchQueryString()<<" at "<<pCurPos ) ;
00261       return tee_notify_search_result(pCurPos);
00262     }
00263     
00264     // not found
00265     return tee_notify_search_result(searchIterEnd());
00266   }
00267 
00268 
00269   // reimplemented from KLFPosSearchable (do not reimplement)
00270 
00271   virtual Pos searchFind(const QString& queryString, const Pos& fromPos, bool forward)
00272   {
00273     KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00274     klfDbg("queryString="<<queryString<<"; searchQueryString="<<searchQueryString()) ;
00275     SearchIterator startit = iteratorForPos(fromPos);
00276     SearchIterator matchit = searchIterFind(startit, queryString, forward);
00277     return posForIterator(matchit);
00278   }
00279 
00280 
00292   SearchIterator searchAdvanceIteratorSafe(const SearchIterator& it, int n = 1)
00293   {
00294     if (n == 0)
00295       return it;
00296     bool forward = (n>0);
00297     if (n < 0)
00298       n = -n;
00299     // 'n' is number of steps (positive) to perform in direction 'forward'
00300     SearchIterator a = it;
00301     while (n--)
00302       a = safe_cycl_advance_iterator(a, forward);
00303 
00304     return a;
00305   }
00306 
00310   SearchIterator searchAdvanceIteratorCycle(const SearchIterator& it, int n = 1, bool skipEnd = false)
00311   {
00312     bool forward = (n >= 0);
00313     if (!forward)
00314       n = -n;
00315     SearchIterator it2 = it;
00316     while (n--) {
00317       it2 = safe_cycl_advance_iterator(it2, forward);
00318       if (it2 == searchIterEnd() && skipEnd)
00319         it2 = safe_cycl_advance_iterator(it2, forward);
00320     }
00321     return it2;
00322   }
00323 
00324 protected:
00325 
00326   inline SearchIterator searchCurrentIterPos() const { return pCurPos; }
00327 
00328 private:
00330   SearchIterator pCurPos;
00331 
00332 
00333   struct IterPosData : public KLFPosSearchable::Pos::PosData {
00334     IterPosData(Iter iterator) : it(iterator) { }
00335 
00336     Iter it;
00337 
00338     virtual bool equals(KLFPosSearchable::Pos::PosData * other) const
00339     {
00340       IterPosData * itpd = dynamic_cast<IterPosData*>(other);
00341       KLF_ASSERT_NOT_NULL(itpd, "posdata of pos ptr `other' is NULL!", return false; ) ;
00342       return  (it == itpd->it) ;
00343     }
00344   };
00345 
00346   SearchIterator iteratorForPos(const KLFPosSearchable::Pos& p)
00347   {
00348     KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00349     if (!p.valid())
00350       return searchIterEnd();
00351     IterPosData *itpd = p.data<IterPosData>();
00352     KLF_ASSERT_NOT_NULL(itpd, "posdata of pos `p' is NULL!", return searchIterEnd() ) ;
00353     return itpd->it;
00354   }
00355   KLFPosSearchable::Pos posForIterator(const SearchIterator& it)
00356   {
00357     KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00358     Pos p = Pos();
00359     if (it == searchIterEnd())
00360       return p; // an invalid pos
00361     p.posdata = new IterPosData(it);
00362     return p;
00363   }
00364 
00365   inline SearchIterator tee_notify_search_result(const SearchIterator& iter)
00366   {
00367     searchPerformed(iter);
00368     return iter;
00369   }
00370 
00371   inline SearchIterator safe_cycl_advance_iterator(const SearchIterator& it, bool forward)
00372   {
00373     if (forward) {
00374       if (it == searchIterEnd())
00375         return searchIterBegin();
00376       return searchIterNext(it);
00377     } else {
00378       if (it == searchIterBegin())
00379         return searchIterEnd();
00380       return searchIterPrev(it);
00381     }
00382   }
00383 };
00384 
00385 
00386 
00387 #endif

Generated by doxygen 1.7.6.1. The KLatexFormula website is hosted on sourceforge.net