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 K_GLOBAL_STATIC(Filter, s_defFilter)
00036
00037 class Filter::Private
00038 {
00039 public:
00040
00041
00042
00043 Settings *settings;
00044 };
00045
00046 Filter* Filter::defaultFilter()
00047 {
00048 return s_defFilter;
00049 }
00050
00051 Word Filter::end()
00052 {
00053 return endWord;
00054 }
00055
00056 Filter::Filter()
00057 : m_currentPosition( 0 ),d(new Private)
00058 {
00059 d->settings = 0;
00060 }
00061
00062 Filter::~Filter()
00063 {
00064 delete d;
00065 }
00066
00067 void Filter::setSettings( Settings *conf )
00068 {
00069 d->settings = conf;
00070 }
00071
00072 Settings *Filter::settings() const
00073 {
00074 return d->settings;
00075 }
00076
00077 void Filter::restart()
00078 {
00079 m_currentPosition = 0;
00080 }
00081
00082 void Filter::setBuffer( const QString& buffer )
00083 {
00084 m_buffer = buffer;
00085 m_currentPosition = 0;
00086 }
00087
00088 QString Filter::buffer() const
00089 {
00090 return m_buffer;
00091 }
00092
00093 bool Filter::atEnd() const
00094 {
00095 if ( m_currentPosition >= m_buffer.length() ) {
00096 return true;
00097 } else
00098 return false;
00099 }
00100
00101 Word Filter::nextWord() const
00102 {
00103 QChar currentChar = skipToLetter( m_currentPosition );
00104
00105 if ( m_currentPosition >= m_buffer.length() || currentChar.isNull() ) {
00106 return Filter::end();
00107 }
00108
00109 bool allUppercase = currentChar.category() & QChar::Letter_Uppercase;
00110 bool runTogether = false;
00111
00112 QString foundWord;
00113 int start = m_currentPosition;
00114 while ( currentChar.isLetter() ) {
00115 if ( currentChar.category() & QChar::Letter_Lowercase )
00116 allUppercase = false;
00117
00118
00119
00120
00121
00122
00123
00124
00125 foundWord += currentChar;
00126
00127 if( (m_currentPosition + 1) >= m_buffer.length()) {
00128 if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) ) {
00129 ++m_currentPosition;
00130 return nextWord();
00131 }
00132 else {
00133 ++m_currentPosition;
00134 return Word( foundWord, start );
00135 }
00136 }
00137 ++m_currentPosition;
00138 currentChar = m_buffer.at( m_currentPosition );
00139 }
00140 if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) )
00141 return nextWord();
00142 return Word( foundWord, start );
00143 }
00144
00145 Word Filter::previousWord() const
00146 {
00147 while ( !m_buffer.at( m_currentPosition ).isLetter() &&
00148 m_currentPosition != 0) {
00149 --m_currentPosition;
00150 }
00151
00152 if ( m_currentPosition == 0 ) {
00153 return Filter::end();
00154 }
00155
00156 QString foundWord;
00157 int start = m_currentPosition;
00158 while ( m_buffer.at( start ).isLetter() ) {
00159 foundWord.prepend( m_buffer.at( m_currentPosition ) );
00160 --start;
00161 }
00162
00163 return Word( foundWord, start );
00164 }
00165
00166 Word Filter::wordAtPosition( unsigned int pos ) const
00167 {
00168 if ( (int)pos > m_buffer.length() )
00169 return Filter::end();
00170
00171 int currentPosition = pos - 1;
00172 QString foundWord;
00173 while ( currentPosition >= 0 &&
00174 m_buffer.at( currentPosition ).isLetter() ) {
00175 foundWord.prepend( m_buffer.at( currentPosition ) );
00176 --currentPosition;
00177 }
00178
00179
00180
00181 int start = (currentPosition < 0) ? 0 : ++currentPosition;
00182 currentPosition = pos ;
00183 if ( currentPosition < m_buffer.length() && m_buffer.at( currentPosition ).isLetter() ) {
00184 while ( m_buffer.at( currentPosition ).isLetter() ) {
00185 foundWord.append( m_buffer.at( currentPosition ) );
00186 ++currentPosition;
00187 }
00188 }
00189
00190 return Word( foundWord, start );
00191 }
00192
00193
00194 void Filter::setCurrentPosition( int i )
00195 {
00196 m_currentPosition = i;
00197
00198
00199
00200 while ( m_buffer.at( m_currentPosition ).isLetter() && m_currentPosition > 0 )
00201 --m_currentPosition;
00202 }
00203
00204 int Filter::currentPosition() const
00205 {
00206 return m_currentPosition;
00207 }
00208
00209 void Filter::replace( const Word& w, const QString& newWord)
00210 {
00211 int oldLen = w.word.length();
00212 int newLen = newWord.length();
00213
00214 if ( oldLen != newLen && m_currentPosition > w.start ) {
00215 if ( m_currentPosition > w.start ) {
00216 int len = newLen - oldLen;
00217 m_currentPosition += len;
00218 }
00219 }
00220 m_buffer = m_buffer.replace( w.start, oldLen, newWord );
00221 }
00222
00223 QString Filter::context() const
00224 {
00225 int len = 60;
00226
00227
00228 int signedPosition = m_currentPosition;
00229 bool begin = ( (signedPosition - len/2)<=0 ) ? true : false;
00230
00231
00232 QString buffer = m_buffer;
00233 Word word = wordAtPosition( m_currentPosition );
00234 buffer = buffer.replace( word.start, word.word.length(),
00235 QString( "<b>%1</b>" ).arg( word.word ) );
00236
00237 QString context;
00238 if ( begin )
00239 context = QString( "%1...")
00240 .arg( buffer.mid( 0, len ) );
00241 else
00242 context = QString( "...%1..." )
00243 .arg( buffer.mid( m_currentPosition - 20, len ) );
00244
00245 context = context.replace( '\n', ' ' );
00246
00247 return context;
00248 }
00249
00250 bool Filter::trySkipLinks() const
00251 {
00252 QChar currentChar = m_buffer.at( m_currentPosition );
00253
00254 int length = m_buffer.length();
00255
00256 if ( currentChar == ':'
00257 && (m_currentPosition+1 < length)
00258 && (m_buffer.at( ++m_currentPosition ) == '/' || ( m_currentPosition + 1 ) >= length ) ) {
00259
00260
00261 while ( !m_buffer.at( m_currentPosition++ ).isSpace() && m_currentPosition < length )
00262 ;
00263 return true;
00264 }
00265
00266
00267 if ( currentChar == '@') {
00268 while ( ++m_currentPosition < length && !m_buffer.at( m_currentPosition ).isSpace() )
00269 ;
00270 return true;
00271 }
00272
00273 return false;
00274 }
00275
00276 bool Filter::ignore( const QString& word ) const
00277 {
00278 if ( d->settings ) {
00279 return d->settings->ignore( word );
00280 }
00281 return false;
00282 }
00283
00284 QChar Filter::skipToLetter( int &fromPosition ) const
00285 {
00286
00287 if (fromPosition>=m_buffer.size())
00288 return QChar();
00289 QChar currentChar = m_buffer.at( fromPosition );
00290 while ( !currentChar.isLetter() &&
00291 (int)++fromPosition < m_buffer.length() ) {
00292 currentChar = m_buffer.at( fromPosition );
00293 }
00294 return currentChar;
00295 }
00296
00297 bool Filter::shouldBeSkipped( bool wordWasUppercase, bool wordWasRunTogether,
00298 const QString& foundWord ) const
00299 {
00300 bool checkUpper = ( d->settings ) ?
00301 d->settings->checkUppercase () : true;
00302 bool skipRunTogether = ( d->settings ) ?
00303 d->settings->skipRunTogether() : true;
00304
00305 if ( trySkipLinks() )
00306 return true;
00307
00308 if ( wordWasUppercase && !checkUpper )
00309 return true;
00310
00311 if ( wordWasRunTogether && skipRunTogether )
00312 return true;
00313
00314 return ignore( foundWord );
00315 }
00316
00317 }