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

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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  •     Sodep
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.9-20090814
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