• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • sources
  • kde-4.12
  • kdelibs
  • kdecore
  • sonnet
filter.cpp
Go to the documentation of this file.
1 // -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
24 #include "filter_p.h"
25 
26 #include "settings_p.h"
27 
28 #include <kglobal.h>
29 #include <kdebug.h>
30 
31 namespace Sonnet
32 {
33 
34 static Word endWord;
35 
36 class Filter::Private
37 {
38 public:
39  // The reason it's not in the class directly is that
40  // I'm not 100% sure that having the settings() here is
41  // the way i want to be doing this.
42  Settings *settings;
43 };
44 
45 Filter* Filter::defaultFilter()
46 {
47  return new Filter();
48 }
49 
50 Word Filter::end()
51 {
52  return endWord;
53 }
54 
55 Filter::Filter()
56  : d(new Private)
57 {
58  d->settings = 0;
59 }
60 
61 Filter::~Filter()
62 {
63  delete d;
64 }
65 
66 void Filter::setSettings( Settings *conf )
67 {
68  d->settings = conf;
69 }
70 
71 Settings *Filter::settings() const
72 {
73  return d->settings;
74 }
75 
76 void Filter::restart()
77 {
78  m_finder.toStart();
79 }
80 
81 void Filter::setBuffer( const QString& buffer )
82 {
83  m_buffer = buffer;
84  m_finder = QTextBoundaryFinder(QTextBoundaryFinder::Word, m_buffer);
85 }
86 
87 QString Filter::buffer() const
88 {
89  return m_buffer;
90 }
91 
92 bool Filter::atEnd() const
93 {
94  return m_finder.position() >= m_buffer.length() || m_finder.position() < 0;
95 }
96 
97 // we don't want to spell check empty words, or single-char words of the form
98 // '<', '=', etc.
99 static bool
100 isValidWord(const QString &str)
101 {
102  if(str.isEmpty() || (str.length() == 1 && !str[0].isLetter())) {
103  return false;
104  }
105  const int length = str.length();
106  for(int i = 0; i < length; ++i) {
107  if(!str[i].isNumber()) {
108  return true;
109  }
110  }
111  // 'str' only contains numbers
112  return false;
113 }
114 
115 static bool
116 finderNextWord(QTextBoundaryFinder &finder, QString &word, int &bufferStart)
117 {
118  QTextBoundaryFinder::BoundaryReasons boundary = finder.boundaryReasons();
119  int start = finder.position(), end = finder.position();
120  bool inWord = (boundary & QTextBoundaryFinder::StartWord) != 0;
121  while (finder.toNextBoundary() > 0) {
122  boundary = finder.boundaryReasons();
123  if ((boundary & QTextBoundaryFinder::EndWord) && inWord) {
124  end = finder.position();
125  QString str = finder.string().mid(start, end - start);
126  if (isValidWord(str)) {
127  word = str;
128  bufferStart = start;
129 #if 0
130  kDebug() << "Word at " << start << " word = '"
131  << str << "', len = " << str.length();
132 #endif
133  return true;
134  }
135  inWord = false;
136  }
137  if ((boundary & QTextBoundaryFinder::StartWord)) {
138  start = finder.position();
139  inWord = true;
140  }
141  }
142  return false;
143 }
144 
145 static bool finderWordAt(QTextBoundaryFinder &finder,
146  int at,
147  QString &word, int &bufferStart)
148 {
149  int oldPosition = finder.position();
150 
151  finder.setPosition(at);
152  if (!finder.isAtBoundary() || (finder.boundaryReasons() & QTextBoundaryFinder::EndWord)) {
153  if (finder.toPreviousBoundary() <= 0) {
154  /* QTextBoundaryIterator doesn't consider start of the string
155  * a boundary so we need to rewind to the beginning to catch
156  * the first word */
157  if (at > 0 && finder.string().length() > 0) {
158  finder.toStart();
159  } else
160  return false;
161  }
162  }
163  bool ret = finderNextWord(finder, word, bufferStart);
164  finder.setPosition(oldPosition);
165  return ret;
166 }
167 
168 Word Filter::nextWord() const
169 {
170  QString foundWord;
171  int start;
172  bool allUppercase = false;
173  bool runTogether = false;
174 
175  if (!finderNextWord(m_finder, foundWord, start))
176  return Filter::end();
177 
178  allUppercase = ( foundWord == foundWord.toUpper() );
179 
180  //TODO implement runtogether correctly.
181  //We must ask to sonnet plugins to do it and not directly here.
182 
183  if ( shouldBeSkipped( allUppercase, runTogether, foundWord ) )
184  return nextWord();
185  return Word( foundWord, start );
186 }
187 
188 Word Filter::wordAtPosition( unsigned int pos ) const
189 {
190  QString foundWord;
191  int start;
192  if (!finderWordAt(m_finder, pos, foundWord, start))
193  return Filter::end();
194  return Word( foundWord, start );
195 }
196 
197 
198 void Filter::setCurrentPosition( int i )
199 {
200  QString word;
201  int pos;
202 
203  //to make sure we're at an reasonable word boundary
204  if (!finderWordAt(m_finder, i, word, pos)) {
205  return;
206  }
207  m_finder.setPosition(pos);
208 }
209 
210 int Filter::currentPosition() const
211 {
212  return m_finder.position();
213 }
214 
215 void Filter::replace( const Word& w, const QString& newWord)
216 {
217  int oldLen = w.word.length();
218 
219  //start spell checkin from the just correct word
220  m_buffer = m_buffer.replace( w.start, oldLen, newWord );
221  m_finder = QTextBoundaryFinder(QTextBoundaryFinder::Word,
222  m_buffer);
223  m_finder.setPosition(w.start);
224 }
225 
226 QString Filter::context() const
227 {
228  int len = 60;
229  //we don't want the expression underneath casted to an unsigned int
230  //which would cause it to always evaluate to false
231  int signedPosition = m_finder.position();
232  bool begin = (signedPosition - len/2)<=0;
233 
234 
235  QString buffer = m_buffer;
236  Word word = wordAtPosition( m_finder.position() );
237  buffer = buffer.replace( word.start, word.word.length(),
238  QString::fromLatin1( "<b>%1</b>" ).arg( word.word ) );
239 
240  QString context;
241  if ( begin )
242  context = QString::fromLatin1("%1...")
243  .arg( buffer.mid( 0, len ) );
244  else
245  context = QString::fromLatin1("...%1...")
246  .arg( buffer.mid( m_finder.position() - 20, len ) );
247 
248  context.replace( QLatin1Char('\n'), QLatin1Char(' ') );
249 
250  return context;
251 }
252 
253 bool Filter::trySkipLinks() const
254 {
255  QChar currentChar;
256  int currentPosition = m_finder.position();
257 
258  if (currentPosition < 0 || currentPosition >= m_buffer.length())
259  return false;
260  currentChar = m_buffer.at( currentPosition );
261 
262  int length = m_buffer.length();
263  //URL - if so skip
264  if ( currentChar == QLatin1Char(':')
265  && (currentPosition+1 < length)
266  && (m_buffer.at( ++currentPosition ) == QLatin1Char('/') || ( currentPosition + 1 ) >= length ) ) {
267  //in both cases url is considered finished at the first whitespace occurrence
268  //TODO hey, "http://en.wikipedia.org/wiki/Main Page" --Nick Shaforostoff
269  while ( !m_buffer.at( currentPosition++ ).isSpace() && currentPosition < length )
270  ;
271  m_finder.setPosition(currentPosition);
272  return true;
273  }
274 
275  //Email - if so skip
276  if ( currentChar == QLatin1Char('@')) {
277  while ( ++currentPosition < length && !m_buffer.at( currentPosition ).isSpace() )
278  ;
279  m_finder.setPosition(currentPosition);
280  return true;
281  }
282 
283  return false;
284 }
285 
286 bool Filter::ignore( const QString& word ) const
287 {
288  return d->settings && d->settings->ignore( word );
289 }
290 
291 bool Filter::shouldBeSkipped( bool wordWasUppercase, bool wordWasRunTogether,
292  const QString& foundWord ) const
293 {
294  bool checkUpper = ( d->settings ) ?
295  d->settings->checkUppercase () : true;
296 
297  bool skipRunTogether = ( d->settings ) ?
298  d->settings->skipRunTogether() : true;
299 
300  if ( trySkipLinks() )
301  return true;
302 
303  if ( wordWasUppercase && !checkUpper )
304  return true;
305 
306  if ( wordWasRunTogether && skipRunTogether )
307  return true;
308 
309  return ignore( foundWord );
310 }
311 
312 }
kdebug.h
Sonnet::Filter::end
static Word end()
Definition: filter.cpp:50
Sonnet::endWord
static Word endWord
Definition: filter.cpp:34
Sonnet::Filter::m_buffer
QString m_buffer
Definition: filter_p.h:110
Sonnet::Filter::Filter
Filter()
Definition: filter.cpp:55
Sonnet::Filter::m_finder
QTextBoundaryFinder m_finder
Definition: filter_p.h:111
Sonnet::isValidWord
static bool isValidWord(const QString &str)
Definition: filter.cpp:100
Sonnet::Filter::wordAtPosition
virtual Word wordAtPosition(unsigned int pos) const
Definition: filter.cpp:188
Sonnet::Filter
Filter is used to split text into words which will be spell checked.
Definition: filter_p.h:65
Sonnet::Filter::nextWord
virtual Word nextWord() const
Definition: filter.cpp:168
Sonnet::Filter::settings
Settings * settings() const
Returns currently used Settings object.
Definition: filter.cpp:71
settings_p.h
QString
Sonnet::Settings
Settings class.
Definition: settings_p.h:37
Sonnet::Filter::setCurrentPosition
virtual void setCurrentPosition(int)
Definition: filter.cpp:198
Sonnet::Filter::buffer
QString buffer() const
Definition: filter.cpp:87
kglobal.h
Sonnet::Filter::currentPosition
virtual int currentPosition() const
Definition: filter.cpp:210
Sonnet::Word
Structure abstracts the word and its position in the parent text.
Definition: filter_p.h:40
Sonnet::finderWordAt
static bool finderWordAt(QTextBoundaryFinder &finder, int at, QString &word, int &bufferStart)
Definition: filter.cpp:145
Sonnet::Filter::shouldBeSkipped
bool shouldBeSkipped(bool wordWasUppercase, bool wordWasRunTogether, const QString &foundWord) const
Definition: filter.cpp:291
Sonnet::Filter::setSettings
void setSettings(Settings *)
Sets the Settings object for this Filter.
Definition: filter.cpp:66
Sonnet::Filter::context
virtual QString context() const
Should return the sentence containing the current word.
Definition: filter.cpp:226
Sonnet::Filter::replace
virtual void replace(const Word &w, const QString &newWord)
Definition: filter.cpp:215
Sonnet::Filter::defaultFilter
static Filter * defaultFilter()
Definition: filter.cpp:45
Sonnet::Word::start
int start
Definition: filter_p.h:54
Sonnet::finderNextWord
static bool finderNextWord(QTextBoundaryFinder &finder, QString &word, int &bufferStart)
Definition: filter.cpp:116
Sonnet::Filter::atEnd
bool atEnd() const
Definition: filter.cpp:92
Sonnet::Filter::trySkipLinks
bool trySkipLinks() const
Definition: filter.cpp:253
Sonnet::Filter::restart
void restart()
Definition: filter.cpp:76
Sonnet::Filter::ignore
bool ignore(const QString &word) const
Definition: filter.cpp:286
kDebug
#define kDebug
Definition: kdebug.h:316
Sonnet::Word::word
QString word
Definition: filter_p.h:53
Sonnet::Filter::setBuffer
void setBuffer(const QString &buffer)
Definition: filter.cpp:81
filter_p.h
Sonnet::Filter::~Filter
virtual ~Filter()
Definition: filter.cpp:61
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:47:07 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal