• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

filter.cpp

Go to the documentation of this file.
00001 // -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00023 #include "filter_p.h"
00024 
00025 #include "settings_p.h"
00026 
00027 #include <kglobal.h>
00028 #include <kdebug.h>
00029 
00030 namespace Sonnet
00031 {
00032 
00033 static Word endWord;
00034 
00035 class Filter::Private
00036 {
00037 public:
00038     // The reason it's not in the class directly is that
00039     // I'm not 100% sure that having the settings() here is
00040     // the way i want to be doing this.
00041     Settings *settings;
00042 };
00043 
00044 Filter* Filter::defaultFilter()
00045 {
00046     return new Filter();
00047 }
00048 
00049 Word Filter::end()
00050 {
00051     return endWord;
00052 }
00053 
00054 Filter::Filter()
00055     : d(new Private)
00056 {
00057     d->settings = 0;
00058 }
00059 
00060 Filter::~Filter()
00061 {
00062     delete d;
00063 }
00064 
00065 void Filter::setSettings( Settings *conf )
00066 {
00067     d->settings = conf;
00068 }
00069 
00070 Settings *Filter::settings() const
00071 {
00072     return d->settings;
00073 }
00074 
00075 void Filter::restart()
00076 {
00077     m_finder.toStart();
00078 }
00079 
00080 void Filter::setBuffer( const QString& buffer )
00081 {
00082     m_buffer = buffer;
00083     m_finder = QTextBoundaryFinder(QTextBoundaryFinder::Word, m_buffer);
00084 }
00085 
00086 QString Filter::buffer() const
00087 {
00088     return m_buffer;
00089 }
00090 
00091 bool Filter::atEnd() const
00092 {
00093     return m_finder.position() >= m_buffer.length();
00094 }
00095 
00096 static inline bool
00097 isSpaceOrPunct(const QString &str)
00098 {
00099     return (str.length() <= 1 && (str[0].isSpace() || str[0].isPunct()));
00100 }
00101 
00102 static bool
00103 finderNextWord(QTextBoundaryFinder &finder, QString &word, int &bufferStart)
00104 {
00105     QTextBoundaryFinder::BoundaryReasons boundary = finder.boundaryReasons();
00106     int start = finder.position(), end = finder.position();
00107     bool inWord = (boundary & QTextBoundaryFinder::StartWord) != 0;
00108 
00109     while (finder.toNextBoundary() > 0) {
00110         boundary = finder.boundaryReasons();
00111 
00112         if ((boundary & QTextBoundaryFinder::EndWord) && inWord) {
00113             end = finder.position();
00114             QString str = finder.string().mid(start, end - start);
00115             if (!isSpaceOrPunct(str)) {
00116                 word = str;
00117                 bufferStart = start;
00118 #if 0
00119                 qDebug()<< "Word at " << start<< " word = '"
00120                         <<  str << "', len = " << str.length();
00121 #endif
00122                 return true;
00123             }
00124             inWord = false;
00125         }
00126         if ((boundary & QTextBoundaryFinder::StartWord)) {
00127             start = finder.position();
00128             inWord = true;
00129         }
00130     }
00131     return false;
00132 }
00133 
00134 static bool finderWordAt(QTextBoundaryFinder &finder,
00135                          int at,
00136                          QString &word, int &bufferStart)
00137 {
00138     int oldPosition = finder.position();
00139 
00140     finder.setPosition(at);
00141     if (!finder.isAtBoundary() || (finder.boundaryReasons() & QTextBoundaryFinder::EndWord)) {
00142         if (finder.toPreviousBoundary() <= 0) {
00143             /* QTextBoundaryIterator doesn't consider start of the string
00144              * a boundary so we need to rewind to the beginning to catch
00145              * the first word */
00146             if (at > 0 && finder.string().length() > 0) {
00147                 finder.toStart();
00148             } else
00149                 return false;
00150         }
00151     }
00152     bool ret = finderNextWord(finder, word, bufferStart);
00153     finder.setPosition(oldPosition);
00154     return ret;
00155 }
00156 
00157 Word Filter::nextWord() const
00158 {
00159     QString foundWord;
00160     int start;
00161     bool allUppercase = false;
00162     bool runTogether = false;
00163 
00164     if (!finderNextWord(m_finder, foundWord, start))
00165         return Filter::end();
00166 
00167     if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) )
00168         return nextWord();
00169     return Word( foundWord, start );
00170 }
00171 
00172 Word Filter::wordAtPosition( unsigned int pos ) const
00173 {
00174     QString foundWord;
00175     int start;
00176     if (!finderWordAt(m_finder, pos, foundWord, start))
00177         return Filter::end();
00178     return Word( foundWord, start );
00179 }
00180 
00181 
00182 void Filter::setCurrentPosition( int i )
00183 {
00184     QString word;
00185     int pos;
00186 
00187     //to make sure we're at an reasonable word boundary
00188     if (!finderWordAt(m_finder, i, word, pos)) {
00189         return;
00190     }
00191     m_finder.setPosition(pos);
00192 }
00193 
00194 int Filter::currentPosition() const
00195 {
00196     return m_finder.position();
00197 }
00198 
00199 void Filter::replace( const Word& w, const QString& newWord)
00200 {
00201     int oldLen = w.word.length();
00202 
00203     //start spell checkin from the just correct word
00204     m_buffer = m_buffer.replace( w.start, oldLen, newWord );
00205     m_finder = QTextBoundaryFinder(QTextBoundaryFinder::Word,
00206                                      m_buffer);
00207     m_finder.setPosition(w.start);
00208 }
00209 
00210 QString Filter::context() const
00211 {
00212     int len = 60;
00213     //we don't want the expression underneath casted to an unsigned int
00214     //which would cause it to always evaluate to false
00215     int signedPosition = m_finder.position();
00216     bool begin = (signedPosition - len/2)<=0;
00217 
00218 
00219     QString buffer = m_buffer;
00220     Word word = wordAtPosition( m_finder.position() );
00221     buffer = buffer.replace( word.start, word.word.length(),
00222                              QString( "<b>%1</b>" ).arg( word.word ) );
00223 
00224     QString context;
00225     if ( begin )
00226         context = QString( "%1...")
00227                   .arg( buffer.mid(  0, len ) );
00228     else
00229         context = QString( "...%1..." )
00230                   .arg( buffer.mid(  m_finder.position() - 20, len ) );
00231 
00232     context.replace( '\n', ' ' );
00233 
00234     return context;
00235 }
00236 
00237 bool Filter::trySkipLinks() const
00238 {
00239     QChar currentChar = m_buffer.at( m_finder.position() );
00240     int currentPosition = m_finder.position();
00241 
00242     int length = m_buffer.length();
00243     //URL - if so skip
00244     if ( currentChar == ':'
00245          && (currentPosition+1 < length)
00246          && (m_buffer.at( ++currentPosition ) == '/' || ( currentPosition + 1 ) >= length ) ) {
00247         //in both cases url is considered finished at the first whitespace occurrence
00248         //TODO hey, "http://en.wikipedia.org/wiki/Main Page" --Nick Shaforostoff
00249         while ( !m_buffer.at( currentPosition++ ).isSpace() && currentPosition < length )
00250             ;
00251         m_finder.setPosition(currentPosition);
00252         return true;
00253     }
00254 
00255     //Email - if so skip
00256     if ( currentChar == '@') {
00257         while ( ++currentPosition < length && !m_buffer.at( currentPosition ).isSpace() )
00258             ;
00259         m_finder.setPosition(currentPosition);
00260         return true;
00261     }
00262 
00263     return false;
00264 }
00265 
00266 bool Filter::ignore( const QString& word ) const
00267 {
00268     return d->settings && d->settings->ignore( word );
00269 }
00270 
00271 bool Filter::shouldBeSkipped( bool wordWasUppercase, bool wordWasRunTogether,
00272                              const QString& foundWord ) const
00273 {
00274     bool checkUpper = ( d->settings ) ?
00275                       d->settings->checkUppercase () : true;
00276     bool skipRunTogether = ( d->settings ) ?
00277                            d->settings->skipRunTogether() : true;
00278 
00279     if ( trySkipLinks() )
00280         return true;
00281 
00282     if ( wordWasUppercase && !checkUpper )
00283         return true;
00284 
00285     if ( wordWasRunTogether && skipRunTogether )
00286         return true;
00287 
00288     return ignore( foundWord );
00289 }
00290 
00291 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal