KDECore
filter.cpp
Go to the documentation of this file.00001
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
00039
00040
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
00112
00113
00114
00115
00116
00117 while ( currentChar.isLetter() ||
00118 ( currentChar == '\'' && start != m_currentPosition ) ) {
00119 if ( currentChar.category() & QChar::Letter_Lowercase )
00120 allUppercase = false;
00121
00122
00123
00124
00125
00126
00127
00128
00129 foundWord += currentChar;
00130
00131 if( (m_currentPosition + 1) >= m_buffer.length()) {
00132
00133
00134
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
00152
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
00196
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
00215
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
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
00238
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
00267 if ( currentChar == ':'
00268 && (m_currentPosition+1 < length)
00269 && (m_buffer.at( ++m_currentPosition ) == '/' || ( m_currentPosition + 1 ) >= length ) ) {
00270
00271
00272 while ( !m_buffer.at( m_currentPosition++ ).isSpace() && m_currentPosition < length )
00273 ;
00274 return true;
00275 }
00276
00277
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
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 }