• Skip to content
  • Skip to link menu
KDE 4.0 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 K_GLOBAL_STATIC(Filter, s_defFilter)
00036 
00037 class Filter::Private
00038 {
00039 public:
00040     // The reason it's not in the class directly is that
00041     // I'm not 100% sure that having the settings() here is
00042     // the way i want to be doing this.
00043     Settings *settings;
00044 };
00045 
00046 Filter* Filter::defaultFilter()
00047 {
00048     return s_defFilter;
00049 }
00050 
00051 Word Filter::end()
00052 {
00053     return endWord;
00054 }
00055 
00056 Filter::Filter()
00057     : m_currentPosition( 0 ),d(new Private)
00058 {
00059     d->settings = 0;
00060 }
00061 
00062 Filter::~Filter()
00063 {
00064     delete d;
00065 }
00066 
00067 void Filter::setSettings( Settings *conf )
00068 {
00069     d->settings = conf;
00070 }
00071 
00072 Settings *Filter::settings() const
00073 {
00074     return d->settings;
00075 }
00076 
00077 void Filter::restart()
00078 {
00079     m_currentPosition = 0;
00080 }
00081 
00082 void Filter::setBuffer( const QString& buffer )
00083 {
00084     m_buffer          = buffer;
00085     m_currentPosition = 0;
00086 }
00087 
00088 QString Filter::buffer() const
00089 {
00090     return m_buffer;
00091 }
00092 
00093 bool Filter::atEnd() const
00094 {
00095     if ( m_currentPosition >= m_buffer.length() ) {
00096         return true;
00097     } else
00098         return false;
00099 }
00100 
00101 Word Filter::nextWord() const
00102 {
00103     QChar currentChar = skipToLetter( m_currentPosition );
00104 
00105     if ( m_currentPosition >= m_buffer.length() || currentChar.isNull() ) {
00106         return Filter::end();
00107     }
00108 
00109     bool allUppercase = currentChar.category() & QChar::Letter_Uppercase;
00110     bool runTogether = false;
00111 
00112     QString foundWord;
00113     int start = m_currentPosition;
00114     while ( currentChar.isLetter() ) {
00115         if ( currentChar.category() & QChar::Letter_Lowercase )
00116             allUppercase = false;
00117 
00118     /* FIXME: this does not work for Hebrew for example
00119         //we consider run-together words as mixed-case words
00120         if ( !allUppercase &&
00121              currentChar.category() & QChar::Letter_Uppercase )
00122             runTogether = true;
00123     */
00124 
00125         foundWord += currentChar;
00126         //Test if currentPosition exists, otherwise go out
00127         if( (m_currentPosition + 1) >= m_buffer.length()) {
00128             if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) ) {
00129                 ++m_currentPosition;
00130                 return nextWord();
00131             }
00132             else {
00133                 ++m_currentPosition;
00134                 return Word( foundWord, start );
00135             }
00136         }
00137         ++m_currentPosition;
00138         currentChar = m_buffer.at( m_currentPosition );
00139     }
00140     if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) )
00141         return nextWord();
00142     return Word( foundWord, start );
00143 }
00144 
00145 Word Filter::previousWord() const
00146 {
00147     while ( !m_buffer.at( m_currentPosition ).isLetter() &&
00148             m_currentPosition != 0) {
00149         --m_currentPosition;
00150     }
00151 
00152     if ( m_currentPosition == 0 ) {
00153         return Filter::end();
00154     }
00155 
00156     QString foundWord;
00157     int start = m_currentPosition;
00158     while ( m_buffer.at( start ).isLetter() ) {
00159         foundWord.prepend( m_buffer.at( m_currentPosition ) );
00160         --start;
00161     }
00162 
00163     return Word( foundWord, start );
00164 }
00165 
00166 Word Filter::wordAtPosition( unsigned int pos ) const
00167 {
00168     if ( (int)pos > m_buffer.length() )
00169         return Filter::end();
00170 
00171     int currentPosition = pos - 1;
00172     QString foundWord;
00173     while ( currentPosition >= 0 &&
00174             m_buffer.at( currentPosition ).isLetter() ) {
00175         foundWord.prepend( m_buffer.at( currentPosition ) );
00176         --currentPosition;
00177     }
00178 
00179     // currentPosition == 0 means the first char is not letter
00180     // currentPosition == -1 means we reached the beginning
00181     int start = (currentPosition < 0) ? 0 : ++currentPosition;
00182     currentPosition = pos ;
00183     if ( currentPosition < m_buffer.length() && m_buffer.at( currentPosition ).isLetter() ) {
00184         while ( m_buffer.at( currentPosition ).isLetter() ) {
00185             foundWord.append( m_buffer.at( currentPosition ) );
00186             ++currentPosition;
00187         }
00188     }
00189 
00190     return Word( foundWord, start );
00191 }
00192 
00193 
00194 void Filter::setCurrentPosition( int i )
00195 {
00196     m_currentPosition = i;
00197 
00198     //go back to the last word so that next word returns something
00199     //useful
00200     while ( m_buffer.at( m_currentPosition ).isLetter() && m_currentPosition > 0 )
00201         --m_currentPosition;
00202 }
00203 
00204 int Filter::currentPosition() const
00205 {
00206     return m_currentPosition;
00207 }
00208 
00209 void Filter::replace( const Word& w, const QString& newWord)
00210 {
00211     int oldLen = w.word.length();
00212     int newLen = newWord.length();
00213 
00214     if ( oldLen != newLen && m_currentPosition > w.start ) {
00215         if ( m_currentPosition > w.start ) {
00216             int len = newLen - oldLen;
00217             m_currentPosition += len;
00218         }
00219     }
00220     m_buffer = m_buffer.replace( w.start, oldLen, newWord );
00221 }
00222 
00223 QString Filter::context() const
00224 {
00225     int len = 60;
00226     //we don't want the expression underneath casted to an unsigned int
00227     //which would cause it to always evaluate to false
00228     int signedPosition = m_currentPosition;
00229     bool begin = ( (signedPosition - len/2)<=0 ) ? true : false;
00230 
00231 
00232     QString buffer = m_buffer;
00233     Word word = wordAtPosition( m_currentPosition );
00234     buffer = buffer.replace( word.start, word.word.length(),
00235                              QString( "<b>%1</b>" ).arg( word.word ) );
00236 
00237     QString context;
00238     if ( begin )
00239         context = QString( "%1...")
00240                   .arg( buffer.mid(  0, len ) );
00241     else
00242         context = QString( "...%1..." )
00243                   .arg( buffer.mid(  m_currentPosition - 20, len ) );
00244 
00245     context = context.replace( '\n', ' ' );
00246 
00247     return context;
00248 }
00249 
00250 bool Filter::trySkipLinks() const
00251 {
00252     QChar currentChar = m_buffer.at( m_currentPosition );
00253 
00254     int length = m_buffer.length();
00255     //URL - if so skip
00256     if ( currentChar == ':'
00257          && (m_currentPosition+1 < length)
00258          && (m_buffer.at( ++m_currentPosition ) == '/' || ( m_currentPosition + 1 ) >= length ) ) {
00259         //in both cases url is considered finished at the first whitespace occurrence
00260         //TODO hey, "http://en.wikipedia.org/wiki/Main Page" --Nick Shaforostoff
00261         while ( !m_buffer.at( m_currentPosition++ ).isSpace() && m_currentPosition < length )
00262             ;
00263         return true;
00264     }
00265 
00266     //Email - if so skip
00267     if ( currentChar == '@') {
00268         while ( ++m_currentPosition < length && !m_buffer.at( m_currentPosition ).isSpace() )
00269             ;
00270         return true;
00271     }
00272 
00273     return false;
00274 }
00275 
00276 bool Filter::ignore( const QString& word ) const
00277 {
00278     if ( d->settings ) {
00279         return d->settings->ignore( word );
00280     }
00281     return false;
00282 }
00283 
00284 QChar Filter::skipToLetter( int &fromPosition ) const
00285 {
00286     //if( m_buffer.isEmpty())
00287     if (fromPosition>=m_buffer.size())
00288         return QChar();
00289     QChar currentChar = m_buffer.at( fromPosition );
00290     while ( !currentChar.isLetter() &&
00291             (int)++fromPosition < m_buffer.length() ) {
00292         currentChar = m_buffer.at( fromPosition );
00293     }
00294     return currentChar;
00295 }
00296 
00297 bool Filter::shouldBeSkipped( bool wordWasUppercase, bool wordWasRunTogether,
00298                              const QString& foundWord ) const
00299 {
00300     bool checkUpper = ( d->settings ) ?
00301                       d->settings->checkUppercase () : true;
00302     bool skipRunTogether = ( d->settings ) ?
00303                            d->settings->skipRunTogether() : true;
00304 
00305     if ( trySkipLinks() )
00306         return true;
00307 
00308     if ( wordWasUppercase && !checkUpper )
00309         return true;
00310 
00311     if ( wordWasRunTogether && skipRunTogether )
00312         return true;
00313 
00314     return ignore( foundWord );
00315 }
00316 
00317 }

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
  •   WTF
  • KJSEmbed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  •   core
  • Phonon
  •   Backend
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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