• Skip to content
  • Skip to link menu
KDE 4.1 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     : m_currentPosition( 0 ),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_currentPosition = 0;
00078 }
00079 
00080 void Filter::setBuffer( const QString& buffer )
00081 {
00082     m_buffer          = buffer;
00083     m_currentPosition = 0;
00084 }
00085 
00086 QString Filter::buffer() const
00087 {
00088     return m_buffer;
00089 }
00090 
00091 bool Filter::atEnd() const
00092 {
00093     if ( m_currentPosition >= m_buffer.length() ) {
00094         return true;
00095     } else
00096         return false;
00097 }
00098 
00099 Word Filter::nextWord() const
00100 {
00101     QChar currentChar = skipToLetter( m_currentPosition );
00102 
00103     if ( m_currentPosition >= m_buffer.length() || currentChar.isNull() ) {
00104         return Filter::end();
00105     }
00106 
00107     bool allUppercase = currentChar.category() & QChar::Letter_Uppercase;
00108     bool runTogether = false;
00109 
00110     QString foundWord;
00111     int start = m_currentPosition;
00112 
00113     // Loop through the chars of the word, until the current char is not a letter
00114     // anymore.
00115     // Include apostrophes in the word, but not when it is the first character,
00116     // as it might be used as 'quotes'.
00117     // This way, we'll pass contractions like "I've" to the spellchecker, and
00118     // only the word inside apostrophe-quotes, without the apostrophes.
00119     while ( currentChar.isLetter() ||
00120             ( currentChar == '\'' && start != m_currentPosition ) ) {
00121         if ( currentChar.category() & QChar::Letter_Lowercase )
00122             allUppercase = false;
00123 
00124     /* FIXME: this does not work for Hebrew for example
00125         //we consider run-together words as mixed-case words
00126         if ( !allUppercase &&
00127              currentChar.category() & QChar::Letter_Uppercase )
00128             runTogether = true;
00129     */
00130 
00131         foundWord += currentChar;
00132         //Test if currentPosition exists, otherwise go out
00133         if( (m_currentPosition + 1) >= m_buffer.length()) {
00134 
00135             // Remove apostrophes at the end of the word, it probably comes from
00136             // quoting with apostrophes.
00137             if ( foundWord.endsWith( '\'' ) )
00138                 foundWord.chop( 1 );
00139 
00140             if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) ) {
00141                 ++m_currentPosition;
00142                 return nextWord();
00143             }
00144             else {
00145                 ++m_currentPosition;
00146                 return Word( foundWord, start );
00147             }
00148         }
00149         ++m_currentPosition;
00150         currentChar = m_buffer.at( m_currentPosition );
00151     }
00152 
00153     // Remove apostrophes at the end of the word, it probably comes from
00154     // quoting with apostrophes.
00155     if ( foundWord.endsWith( '\'' ) )
00156         foundWord.chop( 1 );
00157 
00158     if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) )
00159         return nextWord();
00160     return Word( foundWord, start );
00161 }
00162 
00163 Word Filter::previousWord() const
00164 {
00165     while ( !m_buffer.at( m_currentPosition ).isLetter() &&
00166             m_currentPosition != 0) {
00167         --m_currentPosition;
00168     }
00169 
00170     if ( m_currentPosition == 0 ) {
00171         return Filter::end();
00172     }
00173 
00174     QString foundWord;
00175     int start = m_currentPosition;
00176     while ( m_buffer.at( start ).isLetter() ) {
00177         foundWord.prepend( m_buffer.at( m_currentPosition ) );
00178         --start;
00179     }
00180 
00181     return Word( foundWord, start );
00182 }
00183 
00184 Word Filter::wordAtPosition( unsigned int pos ) const
00185 {
00186     if ( (int)pos > m_buffer.length() )
00187         return Filter::end();
00188 
00189     int currentPosition = pos - 1;
00190     QString foundWord;
00191     while ( currentPosition >= 0 &&
00192             m_buffer.at( currentPosition ).isLetter() ) {
00193         foundWord.prepend( m_buffer.at( currentPosition ) );
00194         --currentPosition;
00195     }
00196 
00197     // currentPosition == 0 means the first char is not letter
00198     // currentPosition == -1 means we reached the beginning
00199     int start = (currentPosition < 0) ? 0 : ++currentPosition;
00200     currentPosition = pos ;
00201     if ( currentPosition < m_buffer.length() && m_buffer.at( currentPosition ).isLetter() ) {
00202         while ( m_buffer.at( currentPosition ).isLetter() ) {
00203             foundWord.append( m_buffer.at( currentPosition ) );
00204             ++currentPosition;
00205         }
00206     }
00207 
00208     return Word( foundWord, start );
00209 }
00210 
00211 
00212 void Filter::setCurrentPosition( int i )
00213 {
00214     m_currentPosition = i;
00215 
00216     //go back to the last word so that next word returns something
00217     //useful
00218     while ( m_buffer.at( m_currentPosition ).isLetter() && m_currentPosition > 0 )
00219         --m_currentPosition;
00220 }
00221 
00222 int Filter::currentPosition() const
00223 {
00224     return m_currentPosition;
00225 }
00226 
00227 void Filter::replace( const Word& w, const QString& newWord)
00228 {
00229     int oldLen = w.word.length();
00230     int newLen = newWord.length();
00231 
00232     if ( oldLen != newLen && m_currentPosition > w.start ) {
00233         if ( m_currentPosition > w.start ) {
00234             int len = newLen - oldLen;
00235             m_currentPosition += len;
00236         }
00237     }
00238     m_buffer = m_buffer.replace( w.start, oldLen, newWord );
00239 }
00240 
00241 QString Filter::context() const
00242 {
00243     int len = 60;
00244     //we don't want the expression underneath casted to an unsigned int
00245     //which would cause it to always evaluate to false
00246     int signedPosition = m_currentPosition;
00247     bool begin = ( (signedPosition - len/2)<=0 ) ? true : false;
00248 
00249 
00250     QString buffer = m_buffer;
00251     Word word = wordAtPosition( m_currentPosition );
00252     buffer = buffer.replace( word.start, word.word.length(),
00253                              QString( "<b>%1</b>" ).arg( word.word ) );
00254 
00255     QString context;
00256     if ( begin )
00257         context = QString( "%1...")
00258                   .arg( buffer.mid(  0, len ) );
00259     else
00260         context = QString( "...%1..." )
00261                   .arg( buffer.mid(  m_currentPosition - 20, len ) );
00262 
00263     context = context.replace( '\n', ' ' );
00264 
00265     return context;
00266 }
00267 
00268 bool Filter::trySkipLinks() const
00269 {
00270     QChar currentChar = m_buffer.at( m_currentPosition );
00271 
00272     int length = m_buffer.length();
00273     //URL - if so skip
00274     if ( currentChar == ':'
00275          && (m_currentPosition+1 < length)
00276          && (m_buffer.at( ++m_currentPosition ) == '/' || ( m_currentPosition + 1 ) >= length ) ) {
00277         //in both cases url is considered finished at the first whitespace occurrence
00278         //TODO hey, "http://en.wikipedia.org/wiki/Main Page" --Nick Shaforostoff
00279         while ( !m_buffer.at( m_currentPosition++ ).isSpace() && m_currentPosition < length )
00280             ;
00281         return true;
00282     }
00283 
00284     //Email - if so skip
00285     if ( currentChar == '@') {
00286         while ( ++m_currentPosition < length && !m_buffer.at( m_currentPosition ).isSpace() )
00287             ;
00288         return true;
00289     }
00290 
00291     return false;
00292 }
00293 
00294 bool Filter::ignore( const QString& word ) const
00295 {
00296     if ( d->settings ) {
00297         return d->settings->ignore( word );
00298     }
00299     return false;
00300 }
00301 
00302 QChar Filter::skipToLetter( int &fromPosition ) const
00303 {
00304     //if( m_buffer.isEmpty())
00305     if (fromPosition>=m_buffer.size())
00306         return QChar();
00307     QChar currentChar = m_buffer.at( fromPosition );
00308     while ( !currentChar.isLetter() &&
00309             (int)++fromPosition < m_buffer.length() ) {
00310         currentChar = m_buffer.at( fromPosition );
00311     }
00312     return currentChar;
00313 }
00314 
00315 bool Filter::shouldBeSkipped( bool wordWasUppercase, bool wordWasRunTogether,
00316                              const QString& foundWord ) const
00317 {
00318     bool checkUpper = ( d->settings ) ?
00319                       d->settings->checkUppercase () : true;
00320     bool skipRunTogether = ( d->settings ) ?
00321                            d->settings->skipRunTogether() : true;
00322 
00323     if ( trySkipLinks() )
00324         return true;
00325 
00326     if ( wordWasUppercase && !checkUpper )
00327         return true;
00328 
00329     if ( wordWasRunTogether && skipRunTogether )
00330         return true;
00331 
00332     return ignore( foundWord );
00333 }
00334 
00335 }

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
  • Kross
  • KUtils
  • Nepomuk
  • 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