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 : 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_finder.toStart();
00078 }
00079
00080 void Filter::setBuffer( const QString& buffer )
00081 {
00082 m_buffer = buffer;
00083 m_finder = QTextBoundaryFinder(QTextBoundaryFinder::Word, m_buffer);
00084 }
00085
00086 QString Filter::buffer() const
00087 {
00088 return m_buffer;
00089 }
00090
00091 bool Filter::atEnd() const
00092 {
00093 return m_finder.position() >= m_buffer.length();
00094 }
00095
00096 static inline bool
00097 isSpaceOrPunct(const QString &str)
00098 {
00099 return (str.length() <= 1 && (str[0].isSpace() || str[0].isPunct()));
00100 }
00101
00102 static bool
00103 finderNextWord(QTextBoundaryFinder &finder, QString &word, int &bufferStart)
00104 {
00105 QTextBoundaryFinder::BoundaryReasons boundary = finder.boundaryReasons();
00106 int start = finder.position(), end = finder.position();
00107 bool inWord = (boundary & QTextBoundaryFinder::StartWord) != 0;
00108
00109 while (finder.toNextBoundary() > 0) {
00110 boundary = finder.boundaryReasons();
00111
00112 if ((boundary & QTextBoundaryFinder::EndWord) && inWord) {
00113 end = finder.position();
00114 QString str = finder.string().mid(start, end - start);
00115 if (!isSpaceOrPunct(str)) {
00116 word = str;
00117 bufferStart = start;
00118 #if 0
00119 qDebug()<< "Word at " << start<< " word = '"
00120 << str << "', len = " << str.length();
00121 #endif
00122 return true;
00123 }
00124 inWord = false;
00125 }
00126 if ((boundary & QTextBoundaryFinder::StartWord)) {
00127 start = finder.position();
00128 inWord = true;
00129 }
00130 }
00131 return false;
00132 }
00133
00134 static bool finderWordAt(QTextBoundaryFinder &finder,
00135 int at,
00136 QString &word, int &bufferStart)
00137 {
00138 int oldPosition = finder.position();
00139
00140 finder.setPosition(at);
00141 if (!finder.isAtBoundary() || (finder.boundaryReasons() & QTextBoundaryFinder::EndWord)) {
00142 if (finder.toPreviousBoundary() <= 0) {
00143
00144
00145
00146 if (at > 0 && finder.string().length() > 0) {
00147 finder.toStart();
00148 } else
00149 return false;
00150 }
00151 }
00152 bool ret = finderNextWord(finder, word, bufferStart);
00153 finder.setPosition(oldPosition);
00154 return ret;
00155 }
00156
00157 Word Filter::nextWord() const
00158 {
00159 QString foundWord;
00160 int start;
00161 bool allUppercase = false;
00162 bool runTogether = false;
00163
00164 if (!finderNextWord(m_finder, foundWord, start))
00165 return Filter::end();
00166
00167 if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) )
00168 return nextWord();
00169 return Word( foundWord, start );
00170 }
00171
00172 Word Filter::wordAtPosition( unsigned int pos ) const
00173 {
00174 QString foundWord;
00175 int start;
00176 if (!finderWordAt(m_finder, pos, foundWord, start))
00177 return Filter::end();
00178 return Word( foundWord, start );
00179 }
00180
00181
00182 void Filter::setCurrentPosition( int i )
00183 {
00184 QString word;
00185 int pos;
00186
00187
00188 if (!finderWordAt(m_finder, i, word, pos)) {
00189 return;
00190 }
00191 m_finder.setPosition(pos);
00192 }
00193
00194 int Filter::currentPosition() const
00195 {
00196 return m_finder.position();
00197 }
00198
00199 void Filter::replace( const Word& w, const QString& newWord)
00200 {
00201 int oldLen = w.word.length();
00202
00203
00204 m_buffer = m_buffer.replace( w.start, oldLen, newWord );
00205 m_finder = QTextBoundaryFinder(QTextBoundaryFinder::Word,
00206 m_buffer);
00207 m_finder.setPosition(w.start);
00208 }
00209
00210 QString Filter::context() const
00211 {
00212 int len = 60;
00213
00214
00215 int signedPosition = m_finder.position();
00216 bool begin = (signedPosition - len/2)<=0;
00217
00218
00219 QString buffer = m_buffer;
00220 Word word = wordAtPosition( m_finder.position() );
00221 buffer = buffer.replace( word.start, word.word.length(),
00222 QString( "<b>%1</b>" ).arg( word.word ) );
00223
00224 QString context;
00225 if ( begin )
00226 context = QString( "%1...")
00227 .arg( buffer.mid( 0, len ) );
00228 else
00229 context = QString( "...%1..." )
00230 .arg( buffer.mid( m_finder.position() - 20, len ) );
00231
00232 context.replace( '\n', ' ' );
00233
00234 return context;
00235 }
00236
00237 bool Filter::trySkipLinks() const
00238 {
00239 QChar currentChar = m_buffer.at( m_finder.position() );
00240 int currentPosition = m_finder.position();
00241
00242 int length = m_buffer.length();
00243
00244 if ( currentChar == ':'
00245 && (currentPosition+1 < length)
00246 && (m_buffer.at( ++currentPosition ) == '/' || ( currentPosition + 1 ) >= length ) ) {
00247
00248
00249 while ( !m_buffer.at( currentPosition++ ).isSpace() && currentPosition < length )
00250 ;
00251 m_finder.setPosition(currentPosition);
00252 return true;
00253 }
00254
00255
00256 if ( currentChar == '@') {
00257 while ( ++currentPosition < length && !m_buffer.at( currentPosition ).isSpace() )
00258 ;
00259 m_finder.setPosition(currentPosition);
00260 return true;
00261 }
00262
00263 return false;
00264 }
00265
00266 bool Filter::ignore( const QString& word ) const
00267 {
00268 return d->settings && d->settings->ignore( word );
00269 }
00270
00271 bool Filter::shouldBeSkipped( bool wordWasUppercase, bool wordWasRunTogether,
00272 const QString& foundWord ) const
00273 {
00274 bool checkUpper = ( d->settings ) ?
00275 d->settings->checkUppercase () : true;
00276 bool skipRunTogether = ( d->settings ) ?
00277 d->settings->skipRunTogether() : true;
00278
00279 if ( trySkipLinks() )
00280 return true;
00281
00282 if ( wordWasUppercase && !checkUpper )
00283 return true;
00284
00285 if ( wordWasRunTogether && skipRunTogether )
00286 return true;
00287
00288 return ignore( foundWord );
00289 }
00290
00291 }