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

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
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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