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

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • kdeui
  • sonnet
highlighter.cpp
Go to the documentation of this file.
1 
23 #include "highlighter.h"
24 #include "highlighter.moc"
25 
26 #include "speller.h"
27 #include "loader_p.h"
28 #include "filter_p.h"
29 #include "settings_p.h"
30 
31 #include <kconfig.h>
32 #include <kdebug.h>
33 #include <klocale.h>
34 #include <kmessagebox.h>
35 
36 #include <QTextEdit>
37 #include <QTextCharFormat>
38 #include <QTimer>
39 #include <QColor>
40 #include <QHash>
41 #include <QTextCursor>
42 #include <QEvent>
43 #include <QKeyEvent>
44 #include <QApplication>
45 
46 namespace Sonnet {
47 
48 class Highlighter::Private
49 {
50 public:
51  ~Private();
52  Filter *filter;
53  Loader *loader;
54  Speller *dict;
55  QHash<QString, Speller*> dictCache;
56  QTextEdit *edit;
57  bool active;
58  bool automatic;
59  bool completeRehighlightRequired;
60  bool intraWordEditing;
61  bool spellCheckerFound; //cached d->dict->isValid() value
62  int disablePercentage;
63  int disableWordCount;
64  int wordCount, errorCount;
65  QTimer *rehighlightRequest;
66  QColor spellColor;
67  int suggestionListeners; // #of connections for the newSuggestions signal
68 };
69 
70 Highlighter::Private::~Private()
71 {
72  qDeleteAll(dictCache);
73  delete filter;
74 }
75 
76 Highlighter::Highlighter(QTextEdit *textEdit,
77  const QString& configFile,
78  const QColor& _col)
79  : QSyntaxHighlighter(textEdit),
80  d(new Private)
81 {
82  d->filter = Filter::defaultFilter();
83  d->edit = textEdit;
84  d->active = true;
85  d->automatic = true;
86  d->wordCount = 0;
87  d->errorCount = 0;
88  d->intraWordEditing = false;
89  d->completeRehighlightRequired = false;
90  d->spellColor = _col.isValid() ? _col : Qt::red;
91  d->suggestionListeners = 0;
92 
93  textEdit->installEventFilter( this );
94  textEdit->viewport()->installEventFilter( this );
95 
96  d->loader = Loader::openLoader();
97 
98  //Do not load an empty settings file as it will cause the spellchecker to fail
99  //if the KGlobal::locale()->language() (default value) spellchecker is not installed,
100  //and we have a global sonnetrc file with a spellcheck lang installed which could be used.
101  if (!configFile.isEmpty()) {
102  KConfig conf(configFile);
103  if (conf.hasGroup("Spelling")) {
104  d->loader->settings()->restore(&conf);
105  d->filter->setSettings(d->loader->settings());
106  }
107  }
108 
109  d->dict = new Sonnet::Speller();
110  d->spellCheckerFound = d->dict->isValid();
111  d->rehighlightRequest = new QTimer(this);
112  connect( d->rehighlightRequest, SIGNAL(timeout()),
113  this, SLOT(slotRehighlight()));
114 
115  if(!d->spellCheckerFound)
116  return;
117 
118  d->dictCache.insert(d->dict->language(), d->dict);
119 
120  d->disablePercentage = d->loader->settings()->disablePercentageWordError();
121  d->disableWordCount = d->loader->settings()->disableWordErrorCount();
122 
123  //Add kde personal word
124  const QStringList l = Highlighter::personalWords();
125  for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) {
126  d->dict->addToSession( *it );
127  }
128  d->completeRehighlightRequired = true;
129  d->rehighlightRequest->setInterval(0);
130  d->rehighlightRequest->setSingleShot(true);
131  d->rehighlightRequest->start();
132 }
133 
134 Highlighter::~Highlighter()
135 {
136  delete d;
137 }
138 
139 bool Highlighter::spellCheckerFound() const
140 {
141  return d->spellCheckerFound;
142 }
143 
144 // Since figuring out spell correction suggestions is extremely costly,
145 // we keep track of whether the user actually wants some, and only offer them
146 // in that case
147 void Highlighter::connectNotify(const char* signal)
148 {
149  if (QLatin1String(signal) == SIGNAL(newSuggestions(QString,QStringList)))
150  ++d->suggestionListeners;
151  QSyntaxHighlighter::connectNotify(signal);
152 }
153 
154 void Highlighter::disconnectNotify(const char* signal)
155 {
156  if (QLatin1String(signal) == SIGNAL(newSuggestions(QString,QStringList)))
157  --d->suggestionListeners;
158  QSyntaxHighlighter::disconnectNotify(signal);
159 }
160 
161 void Highlighter::slotRehighlight()
162 {
163  kDebug(0) << "Highlighter::slotRehighlight()";
164  if (d->completeRehighlightRequired) {
165  d->wordCount = 0;
166  d->errorCount = 0;
167  rehighlight();
168 
169  } else {
170  //rehighlight the current para only (undo/redo safe)
171  QTextCursor cursor = d->edit->textCursor();
172  cursor.insertText( "" );
173  }
174  //if (d->checksDone == d->checksRequested)
175  //d->completeRehighlightRequired = false;
176  QTimer::singleShot( 0, this, SLOT(slotAutoDetection()));
177 }
178 
179 
180 QStringList Highlighter::personalWords()
181 {
182  QStringList l;
183  l.append( "KMail" );
184  l.append( "KOrganizer" );
185  l.append( "KAddressBook" );
186  l.append( "KHTML" );
187  l.append( "KIO" );
188  l.append( "KJS" );
189  l.append( "Konqueror" );
190  l.append( "Sonnet" );
191  l.append( "Kontact" );
192  l.append( "Qt" );
193  return l;
194 }
195 
196 bool Highlighter::automatic() const
197 {
198  return d->automatic;
199 }
200 
201 bool Highlighter::intraWordEditing() const
202 {
203  return d->intraWordEditing;
204 }
205 
206 void Highlighter::setIntraWordEditing( bool editing )
207 {
208  d->intraWordEditing = editing;
209 }
210 
211 
212 void Highlighter::setAutomatic( bool automatic )
213 {
214  if ( automatic == d->automatic )
215  return;
216 
217  d->automatic = automatic;
218  if ( d->automatic )
219  slotAutoDetection();
220 }
221 
222 void Highlighter::slotAutoDetection()
223 {
224  bool savedActive = d->active;
225 
226  //don't disable just because 1 of 4 is misspelled.
227  if (d->automatic && d->wordCount >= 10) {
228  // tme = Too many errors
229  bool tme = (d->errorCount >= d->disableWordCount) && (
230  d->errorCount * 100 >= d->disablePercentage * d->wordCount);
231  if (d->active && tme) {
232  d->active = false;
233  } else if (!d->active && !tme) {
234  d->active = true;
235  }
236  }
237 
238  if (d->active != savedActive) {
239  if (d->active) {
240  emit activeChanged(i18n("As-you-type spell checking enabled."));
241  } else {
242  emit activeChanged(i18n( "Too many misspelled words. "
243  "As-you-type spell checking disabled."));
244  }
245 
246  d->completeRehighlightRequired = true;
247  d->rehighlightRequest->setInterval(100);
248  d->rehighlightRequest->setSingleShot(true);
249  kDebug()<<" Highlighter::slotAutoDetection :"<<d->active;
250  }
251 
252 }
253 
254 void Highlighter::setActive( bool active )
255 {
256  if ( active == d->active )
257  return;
258  d->active = active;
259  rehighlight();
260 
261 
262  if ( d->active )
263  emit activeChanged( i18n("As-you-type spell checking enabled.") );
264  else
265  emit activeChanged( i18n("As-you-type spell checking disabled.") );
266 }
267 
268 bool Highlighter::isActive() const
269 {
270  return d->active;
271 }
272 
273 void Highlighter::highlightBlock(const QString &text)
274 {
275  if (text.isEmpty() || !d->active || !d->spellCheckerFound)
276  return;
277 
278  d->filter->setBuffer( text );
279  Word w = d->filter->nextWord();
280  while ( !w.end ) {
281  ++d->wordCount;
282  if (d->dict->isMisspelled(w.word)) {
283  ++d->errorCount;
284  setMisspelled(w.start, w.word.length());
285  if (d->suggestionListeners)
286  emit newSuggestions(w.word, d->dict->suggest(w.word));
287  } else
288  unsetMisspelled(w.start, w.word.length());
289  w = d->filter->nextWord();
290  }
291  //QTimer::singleShot( 0, this, SLOT(checkWords()) );
292  setCurrentBlockState(0);
293 }
294 
295 QString Highlighter::currentLanguage() const
296 {
297  return d->dict->language();
298 }
299 
300 void Highlighter::setCurrentLanguage(const QString &lang)
301 {
302  if (!d->dictCache.contains(lang)) {
303  d->dict = new Speller(*d->dict);
304  d->dict->setLanguage(lang);
305  if (d->dict->isValid()) {
306  d->dictCache.insert(lang, d->dict);
307  } else {
308  d->spellCheckerFound = false;
309  kDebug()<<"No dictionary for \""
310  <<lang
311  <<"\" staying with the current language."
312  <<endl;
313  return;
314  }
315  }
316  d->dict = d->dictCache[lang];
317  d->spellCheckerFound = d->dict->isValid();
318  d->wordCount = 0;
319  d->errorCount = 0;
320  if (d->automatic)
321  slotAutoDetection();
322 }
323 
324 void Highlighter::setMisspelled(int start, int count)
325 {
326  QTextCharFormat format;
327  format.setFontUnderline(true);
328  format.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
329  format.setUnderlineColor(d->spellColor);
330  setFormat(start, count, format);
331 }
332 
333 void Highlighter::unsetMisspelled( int start, int count )
334 {
335  setFormat(start, count, QTextCharFormat());
336 }
337 
338 bool Highlighter::eventFilter( QObject *o, QEvent *e)
339 {
340 #if 0
341  if (o == textEdit() && (e->type() == QEvent::FocusIn)) {
342  if ( d->globalConfig ) {
343  QString skey = spellKey();
344  if ( d->spell && d->spellKey != skey ) {
345  d->spellKey = skey;
346  KDictSpellingHighlighter::dictionaryChanged();
347  }
348  }
349  }
350 #endif
351  if (!d->spellCheckerFound)
352  return false;
353  if (o == d->edit && (e->type() == QEvent::KeyPress)) {
354  QKeyEvent *k = static_cast<QKeyEvent *>(e);
355  //d->autoReady = true;
356  if (d->rehighlightRequest->isActive()) // try to stay out of the users way
357  d->rehighlightRequest->start( 500 );
358  if ( k->key() == Qt::Key_Enter ||
359  k->key() == Qt::Key_Return ||
360  k->key() == Qt::Key_Up ||
361  k->key() == Qt::Key_Down ||
362  k->key() == Qt::Key_Left ||
363  k->key() == Qt::Key_Right ||
364  k->key() == Qt::Key_PageUp ||
365  k->key() == Qt::Key_PageDown ||
366  k->key() == Qt::Key_Home ||
367  k->key() == Qt::Key_End ||
368  (( k->modifiers()== Qt::ControlModifier ) &&
369  ((k->key() == Qt::Key_A) ||
370  (k->key() == Qt::Key_B) ||
371  (k->key() == Qt::Key_E) ||
372  (k->key() == Qt::Key_N) ||
373  (k->key() == Qt::Key_P))) ) {
374  if ( intraWordEditing() ) {
375  setIntraWordEditing( false );
376  d->completeRehighlightRequired = true;
377  d->rehighlightRequest->setInterval(500);
378  d->rehighlightRequest->setSingleShot(true);
379  d->rehighlightRequest->start();
380  }
381 #if 0
382  if (d->checksDone != d->checksRequested) {
383  // Handle possible change of paragraph while
384  // words are pending spell checking
385  d->completeRehighlightRequired = true;
386  d->rehighlightRequest->start( 500, true );
387  }
388 #endif
389  } else {
390  setIntraWordEditing( true );
391  }
392  if ( k->key() == Qt::Key_Space ||
393  k->key() == Qt::Key_Enter ||
394  k->key() == Qt::Key_Return ) {
395  QTimer::singleShot( 0, this, SLOT(slotAutoDetection()));
396  }
397  }
398 
399  else if ( o == d->edit->viewport() &&
400  ( e->type() == QEvent::MouseButtonPress )) {
401  //d->autoReady = true;
402  if ( intraWordEditing() ) {
403  setIntraWordEditing( false );
404  d->completeRehighlightRequired = true;
405  d->rehighlightRequest->setInterval(0);
406  d->rehighlightRequest->setSingleShot(true);
407  d->rehighlightRequest->start();
408  }
409  }
410  return false;
411 }
412 
413 void Highlighter::addWordToDictionary(const QString &word)
414 {
415  d->dict->addToPersonal(word);
416 }
417 
418 void Highlighter::ignoreWord(const QString &word)
419 {
420  d->dict->addToSession(word);
421 }
422 
423 QStringList Highlighter::suggestionsForWord(const QString &word, int max)
424 {
425  QStringList suggestions = d->dict->suggest(word);
426  if ( max != -1 ) {
427  while ( suggestions.count() > max )
428  suggestions.removeLast();
429  }
430  return suggestions;
431 }
432 
433 bool Highlighter::isWordMisspelled(const QString &word)
434 {
435  return d->dict->isMisspelled(word);
436 }
437 
438 void Highlighter::setMisspelledColor(const QColor &color)
439 {
440  d->spellColor = color;
441 }
442 
443 bool Highlighter::checkerEnabledByDefault() const
444 {
445  return d->loader->settings()->checkerEnabledByDefault();
446 }
447 
448 
449 }
Sonnet::Highlighter::setMisspelled
virtual void setMisspelled(int start, int count)
Definition: highlighter.cpp:324
i18n
QString i18n(const char *text)
QEvent
Sonnet::Highlighter::spellCheckerFound
bool spellCheckerFound() const
Definition: highlighter.cpp:139
QKeyEvent::modifiers
Qt::KeyboardModifiers modifiers() const
QTextCharFormat::setUnderlineStyle
void setUnderlineStyle(UnderlineStyle style)
QEvent::type
Type type() const
QSyntaxHighlighter::rehighlight
void rehighlight()
Sonnet::Highlighter::~Highlighter
~Highlighter()
Definition: highlighter.cpp:134
QTextCursor
Sonnet::Highlighter::highlightBlock
virtual void highlightBlock(const QString &text)
Definition: highlighter.cpp:273
kdebug.h
QSyntaxHighlighter::setCurrentBlockState
void setCurrentBlockState(int newState)
timeout
int timeout
kconfig.h
Sonnet::Highlighter::personalWords
static QStringList personalWords()
Definition: highlighter.cpp:180
Sonnet::Highlighter::ignoreWord
void ignoreWord(const QString &word)
Ignores the given word.
Definition: highlighter.cpp:418
KConfig::hasGroup
bool hasGroup(const QString &group) const
QAbstractScrollArea::viewport
QWidget * viewport() const
settings_p.h
QSyntaxHighlighter::setFormat
void setFormat(int start, int count, const QTextCharFormat &format)
Sonnet::Word::end
bool end
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
klocale.h
QSyntaxHighlighter
Sonnet::Highlighter::currentLanguage
QString currentLanguage() const
Definition: highlighter.cpp:295
QList::count
int count(const T &value) const
Sonnet::Highlighter::automatic
bool automatic() const
Definition: highlighter.cpp:196
QList::append
void append(const T &value)
Sonnet::Highlighter::setAutomatic
void setAutomatic(bool automatic)
Definition: highlighter.cpp:212
Sonnet::Word
QObject::installEventFilter
void installEventFilter(QObject *filterObj)
QTimer
QHash
QObject
highlighter.h
QTextCursor::insertText
void insertText(const QString &text)
QString::isEmpty
bool isEmpty() const
speller.h
Sonnet::Highlighter::setIntraWordEditing
void setIntraWordEditing(bool editing)
Definition: highlighter.cpp:206
QString
QColor
Sonnet::Highlighter::intraWordEditing
bool intraWordEditing() const
Definition: highlighter.cpp:201
Sonnet::Highlighter::slotAutoDetection
void slotAutoDetection()
Definition: highlighter.cpp:222
Sonnet::Highlighter::newSuggestions
QT_MOC_COMPAT void newSuggestions(const QString &originalWord, const QStringList &suggestions)
Sonnet::Highlighter::addWordToDictionary
void addWordToDictionary(const QString &word)
Adds the given word permanently to the dictionary.
Definition: highlighter.cpp:413
QStringList
Sonnet::Filter::defaultFilter
static Filter * defaultFilter()
Sonnet::Speller
Sonnet::Highlighter::setCurrentLanguage
void setCurrentLanguage(const QString &lang)
Definition: highlighter.cpp:300
Sonnet::Highlighter::isWordMisspelled
bool isWordMisspelled(const QString &word)
Checks if a given word is marked as misspelled by the highlighter.
Definition: highlighter.cpp:433
Sonnet::Highlighter::Highlighter
Highlighter(QTextEdit *textEdit, const QString &configFile=QString(), const QColor &col=QColor())
Definition: highlighter.cpp:76
QObject::connectNotify
virtual void connectNotify(const char *signal)
QTextCharFormat
QList::end
iterator end()
QKeyEvent::key
int key() const
loader_p.h
Sonnet::Highlighter::suggestionsForWord
QStringList suggestionsForWord(const QString &word, int max=10)
Returns a list of suggested replacements for the given misspelled word.
Definition: highlighter.cpp:423
Sonnet::Highlighter::activeChanged
void activeChanged(const QString &description)
Emitted when as-you-type spell checking is enabled or disabled.
QObject::disconnectNotify
virtual void disconnectNotify(const char *signal)
Sonnet::Word::start
int start
QSyntaxHighlighter::format
QTextCharFormat format(int position) const
QKeyEvent
Sonnet::Highlighter::unsetMisspelled
virtual void unsetMisspelled(int start, int count)
Definition: highlighter.cpp:333
Sonnet::Highlighter::setActive
void setActive(bool active)
Enable/Disable spell checking.
Definition: highlighter.cpp:254
Sonnet::Highlighter::eventFilter
bool eventFilter(QObject *o, QEvent *e)
Definition: highlighter.cpp:338
KConfig
QLatin1String
Sonnet::Loader::openLoader
static Loader * openLoader()
QList::ConstIterator
typedef ConstIterator
QList::removeLast
void removeLast()
QString::length
int length() const
QTextCharFormat::setFontUnderline
void setFontUnderline(bool underline)
QTextCharFormat::setUnderlineColor
void setUnderlineColor(const QColor &color)
QtConcurrent::filter
QFuture< void > filter(Sequence &sequence, FilterFunction filterFunction)
Sonnet::Highlighter::checkerEnabledByDefault
bool checkerEnabledByDefault() const
Return true if checker is enabled by default.
Definition: highlighter.cpp:443
kmessagebox.h
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QTextEdit
Sonnet::Highlighter::setMisspelledColor
void setMisspelledColor(const QColor &color)
Sets the color in which the highlighter underlines misspelled words.
Definition: highlighter.cpp:438
Sonnet::Word::word
QString word
Sonnet::Highlighter::isActive
bool isActive() const
Returns the state of spell checking.
Definition: highlighter.cpp:268
QList::begin
iterator begin()
filter_p.h
QColor::isValid
bool isValid() const
Sonnet::Highlighter::slotRehighlight
void slotRehighlight()
Definition: highlighter.cpp:161
QTimer::singleShot
singleShot
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:23:58 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • 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
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • 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