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 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
00115
00116
00117
00118
00119
00120 while ( currentChar.isLetter() ||
00121 ( currentChar == '\'' && start != m_currentPosition ) ) {
00122 if ( currentChar.category() & QChar::Letter_Lowercase )
00123 allUppercase = false;
00124
00125
00126
00127
00128
00129
00130
00131
00132 foundWord += currentChar;
00133
00134 if( (m_currentPosition + 1) >= m_buffer.length()) {
00135
00136
00137
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
00155
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
00199
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
00218
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 int newLen = newWord.length();
00232
00233
00234 m_currentPosition = w.start;
00235 m_buffer = m_buffer.replace( w.start, oldLen, newWord );
00236 }
00237
00238 QString Filter::context() const
00239 {
00240 int len = 60;
00241
00242
00243 int signedPosition = m_currentPosition;
00244 bool begin = ( (signedPosition - len/2)<=0 ) ? true : false;
00245
00246
00247 QString buffer = m_buffer;
00248 Word word = wordAtPosition( m_currentPosition );
00249 buffer = buffer.replace( word.start, word.word.length(),
00250 QString( "<b>%1</b>" ).arg( word.word ) );
00251
00252 QString context;
00253 if ( begin )
00254 context = QString( "%1...")
00255 .arg( buffer.mid( 0, len ) );
00256 else
00257 context = QString( "...%1..." )
00258 .arg( buffer.mid( m_currentPosition - 20, len ) );
00259
00260 context = context.replace( '\n', ' ' );
00261
00262 return context;
00263 }
00264
00265 bool Filter::trySkipLinks() const
00266 {
00267 QChar currentChar = m_buffer.at( m_currentPosition );
00268
00269 int length = m_buffer.length();
00270
00271 if ( currentChar == ':'
00272 && (m_currentPosition+1 < length)
00273 && (m_buffer.at( ++m_currentPosition ) == '/' || ( m_currentPosition + 1 ) >= length ) ) {
00274
00275
00276 while ( !m_buffer.at( m_currentPosition++ ).isSpace() && m_currentPosition < length )
00277 ;
00278 return true;
00279 }
00280
00281
00282 if ( currentChar == '@') {
00283 while ( ++m_currentPosition < length && !m_buffer.at( m_currentPosition ).isSpace() )
00284 ;
00285 return true;
00286 }
00287
00288 return false;
00289 }
00290
00291 bool Filter::ignore( const QString& word ) const
00292 {
00293 if ( d->settings ) {
00294 return d->settings->ignore( word );
00295 }
00296 return false;
00297 }
00298
00299 QChar Filter::skipToLetter( int &fromPosition ) const
00300 {
00301
00302 if (fromPosition>=m_buffer.size())
00303 return QChar();
00304 QChar currentChar = m_buffer.at( fromPosition );
00305 while ( !currentChar.isLetter() &&
00306 (int)++fromPosition < m_buffer.length() ) {
00307 currentChar = m_buffer.at( fromPosition );
00308 }
00309 return currentChar;
00310 }
00311
00312 bool Filter::shouldBeSkipped( bool wordWasUppercase, bool wordWasRunTogether,
00313 const QString& foundWord ) const
00314 {
00315 bool checkUpper = ( d->settings ) ?
00316 d->settings->checkUppercase () : true;
00317 bool skipRunTogether = ( d->settings ) ?
00318 d->settings->skipRunTogether() : true;
00319
00320 if ( trySkipLinks() )
00321 return true;
00322
00323 if ( wordWasUppercase && !checkUpper )
00324 return true;
00325
00326 if ( wordWasRunTogether && skipRunTogether )
00327 return true;
00328
00329 return ignore( foundWord );
00330 }
00331
00332 }