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 ),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
00114
00115
00116
00117
00118
00119 while ( currentChar.isLetter() ||
00120 ( currentChar == '\'' && start != m_currentPosition ) ) {
00121 if ( currentChar.category() & QChar::Letter_Lowercase )
00122 allUppercase = false;
00123
00124
00125
00126
00127
00128
00129
00130
00131 foundWord += currentChar;
00132
00133 if( (m_currentPosition + 1) >= m_buffer.length()) {
00134
00135
00136
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
00154
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
00198
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
00217
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
00245
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
00274 if ( currentChar == ':'
00275 && (m_currentPosition+1 < length)
00276 && (m_buffer.at( ++m_currentPosition ) == '/' || ( m_currentPosition + 1 ) >= length ) ) {
00277
00278
00279 while ( !m_buffer.at( m_currentPosition++ ).isSpace() && m_currentPosition < length )
00280 ;
00281 return true;
00282 }
00283
00284
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
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 }