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

Kate

  • sources
  • kde-4.12
  • applications
  • kate
  • part
  • spellcheck
ontheflycheck.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries and the Kate part.
2  *
3  * Copyright (C) 2008-2010 by Michel Ludwig <michel.ludwig@kdemail.net>
4  * Copyright (C) 2009 by Joseph Wenninger <jowenn@kde.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 /* If ever threads should be used again, thread communication and
23  * synchronization ought to be done with blocking queued signal connections.
24  */
25 
26 #include "ontheflycheck.h"
27 
28 #include <QTimer>
29 
30 #include "kateconfig.h"
31 #include "kateglobal.h"
32 #include "katerenderer.h"
33 #include "katebuffer.h"
34 #include "kateview.h"
35 #include "spellcheck.h"
36 #include "spellingmenu.h"
37 
38 #define ON_THE_FLY_DEBUG kDebug(debugArea())
39 
40 KateOnTheFlyChecker::KateOnTheFlyChecker(KateDocument *document)
41 : QObject(document),
42  m_document(document),
43  m_backgroundChecker(NULL),
44  m_currentlyCheckedItem(invalidSpellCheckQueueItem),
45  m_refreshView(NULL)
46 {
47  ON_THE_FLY_DEBUG << "created";
48 
49  m_viewRefreshTimer = new QTimer(this);
50  m_viewRefreshTimer->setSingleShot(true);
51  connect(m_viewRefreshTimer, SIGNAL(timeout()), this, SLOT(viewRefreshTimeout()));
52 
53  connect(document, SIGNAL(textInserted(KTextEditor::Document*,KTextEditor::Range)),
54  this, SLOT(textInserted(KTextEditor::Document*,KTextEditor::Range)));
55  connect(document, SIGNAL(textRemoved(KTextEditor::Document*,KTextEditor::Range)),
56  this, SLOT(textRemoved(KTextEditor::Document*,KTextEditor::Range)));
57  connect(document, SIGNAL(viewCreated(KTextEditor::Document*,KTextEditor::View*)),
58  this, SLOT(addView(KTextEditor::Document*,KTextEditor::View*)));
59  connect(document, SIGNAL(highlightingModeChanged(KTextEditor::Document*)),
60  this, SLOT(updateConfig()));
61  connect(&document->buffer(), SIGNAL(respellCheckBlock(KateDocument*,int,int)),
62  this, SLOT(handleRespellCheckBlock(KateDocument*,int,int)));
63 
64  // load the settings for the speller
65  updateConfig();
66 
67  foreach(KTextEditor::View* view, document->views()) {
68  addView(document, view);
69  }
70  refreshSpellCheck();
71 }
72 
73 KateOnTheFlyChecker::~KateOnTheFlyChecker()
74 {
75  freeDocument();
76 }
77 
78 int KateOnTheFlyChecker::debugArea()
79 {
80  static int s_area = KDebug::registerArea("Kate (On-The-Fly Spellcheck)");
81  return s_area;
82 }
83 
84 QPair<KTextEditor::Range, QString> KateOnTheFlyChecker::getMisspelledItem(const KTextEditor::Cursor &cursor) const
85 {
86  foreach(const MisspelledItem &item, m_misspelledList) {
87  KTextEditor::MovingRange *movingRange = item.first;
88  if(movingRange->contains(cursor)) {
89  return QPair<KTextEditor::Range, QString>(*movingRange, item.second);
90  }
91  }
92  return QPair<KTextEditor::Range, QString>(KTextEditor::Range::invalid(), QString());
93 }
94 
95 QString KateOnTheFlyChecker::dictionaryForMisspelledRange(const KTextEditor::Range& range) const
96 {
97  foreach(const MisspelledItem &item, m_misspelledList) {
98  KTextEditor::MovingRange *movingRange = item.first;
99  if(*movingRange == range) {
100  return item.second;
101  }
102  }
103  return QString();
104 }
105 
106 void KateOnTheFlyChecker::clearMisspellingForWord(const QString& word)
107 {
108  MisspelledList misspelledList = m_misspelledList; // make a copy
109  foreach(const MisspelledItem &item, misspelledList) {
110  KTextEditor::MovingRange *movingRange = item.first;
111  if(m_document->text(*movingRange) == word) {
112  deleteMovingRange(movingRange);
113  }
114  }
115 }
116 
117 const KateOnTheFlyChecker::SpellCheckItem KateOnTheFlyChecker::invalidSpellCheckQueueItem =
118  SpellCheckItem(NULL, "");
119 
120 void KateOnTheFlyChecker::handleRespellCheckBlock(KateDocument *kateDocument, int start, int end)
121 {
122  Q_ASSERT(kateDocument == m_document);
123  Q_UNUSED(kateDocument);
124 
125  ON_THE_FLY_DEBUG << start << end;
126  KTextEditor::Range range(start, 0, end, m_document->lineLength(end));
127  bool listEmpty = m_modificationList.isEmpty();
128  KTextEditor::MovingRange *movingRange = m_document->newMovingRange(range);
129  movingRange->setFeedback(this);
130  // we don't handle this directly as the highlighting information might not be up-to-date yet
131  m_modificationList.push_back(ModificationItem(TEXT_INSERTED, movingRange));
132  ON_THE_FLY_DEBUG << "added" << *movingRange;
133  if(listEmpty) {
134  QTimer::singleShot(0, this, SLOT(handleModifiedRanges()));
135  }
136 }
137 
138 void KateOnTheFlyChecker::textInserted(KTextEditor::Document *document, const KTextEditor::Range &range)
139 {
140  Q_ASSERT(document == m_document);
141  Q_UNUSED(document);
142  if(!range.isValid()) {
143  return;
144  }
145 
146  bool listEmptyAtStart = m_modificationList.isEmpty();
147 
148  // don't consider a range that is not within the document range
149  const KTextEditor::Range documentIntersection = m_document->documentRange().intersect(range);
150  if(!documentIntersection.isValid()) {
151  return;
152  }
153  // for performance reasons we only want to schedule spellchecks for ranges that are visible
154  foreach(KTextEditor::View* i, m_document->views()) {
155  KateView *view = static_cast<KateView*>(i);
156  KTextEditor::Range visibleIntersection = documentIntersection.intersect(view->visibleRange());
157  if(visibleIntersection.isValid()) { // allow empty intersections
158  // we don't handle this directly as the highlighting information might not be up-to-date yet
159  KTextEditor::MovingRange *movingRange = m_document->newMovingRange(visibleIntersection);
160  movingRange->setFeedback(this);
161  m_modificationList.push_back(ModificationItem(TEXT_INSERTED, movingRange));
162  ON_THE_FLY_DEBUG << "added" << *movingRange;
163  }
164  }
165 
166  if(listEmptyAtStart && !m_modificationList.isEmpty()) {
167  QTimer::singleShot(0, this, SLOT(handleModifiedRanges()));
168  }
169 }
170 
171 void KateOnTheFlyChecker::handleInsertedText(const KTextEditor::Range &range)
172 {
173  KTextEditor::Range consideredRange = range;
174  ON_THE_FLY_DEBUG << m_document << range;
175 
176  bool spellCheckInProgress = m_currentlyCheckedItem != invalidSpellCheckQueueItem;
177 
178  if(spellCheckInProgress) {
179  KTextEditor::MovingRange *spellCheckRange = m_currentlyCheckedItem.first;
180  if(spellCheckRange->contains(consideredRange)) {
181  consideredRange = *spellCheckRange;
182  stopCurrentSpellCheck();
183  deleteMovingRangeQuickly(spellCheckRange);
184  }
185  else if(consideredRange.contains(*spellCheckRange)) {
186  stopCurrentSpellCheck();
187  deleteMovingRangeQuickly(spellCheckRange);
188  }
189  else if(consideredRange.overlaps(*spellCheckRange)) {
190  consideredRange.expandToRange(*spellCheckRange);
191  stopCurrentSpellCheck();
192  deleteMovingRangeQuickly(spellCheckRange);
193  }
194  else {
195  spellCheckInProgress = false;
196  }
197  }
198  for(QList<SpellCheckItem>::iterator i = m_spellCheckQueue.begin();
199  i != m_spellCheckQueue.end();) {
200  KTextEditor::MovingRange *spellCheckRange = (*i).first;
201  if(spellCheckRange->contains(consideredRange)) {
202  consideredRange = *spellCheckRange;
203  ON_THE_FLY_DEBUG << "erasing range " << *i;
204  i = m_spellCheckQueue.erase(i);
205  deleteMovingRangeQuickly(spellCheckRange);
206  }
207  else if(consideredRange.contains(*spellCheckRange)) {
208  ON_THE_FLY_DEBUG << "erasing range " << *i;
209  i = m_spellCheckQueue.erase(i);
210  deleteMovingRangeQuickly(spellCheckRange);
211  }
212  else if(consideredRange.overlaps(*spellCheckRange)) {
213  consideredRange.expandToRange(*spellCheckRange);
214  ON_THE_FLY_DEBUG << "erasing range " << *i;
215  i = m_spellCheckQueue.erase(i);
216  deleteMovingRangeQuickly(spellCheckRange);
217  }
218  else {
219  ++i;
220  }
221  }
222  KTextEditor::Range spellCheckRange = findWordBoundaries(consideredRange.start(),
223  consideredRange.end());
224  const bool emptyAtStart = m_spellCheckQueue.isEmpty();
225 
226  queueSpellCheckVisibleRange(spellCheckRange);
227 
228  if(spellCheckInProgress || (emptyAtStart && !m_spellCheckQueue.isEmpty())) {
229  QTimer::singleShot(0, this, SLOT(performSpellCheck()));
230  }
231 }
232 
233 void KateOnTheFlyChecker::textRemoved(KTextEditor::Document *document, const KTextEditor::Range &range)
234 {
235  Q_ASSERT(document == m_document);
236  Q_UNUSED(document);
237  if(!range.isValid()) {
238  return;
239  }
240 
241  bool listEmptyAtStart = m_modificationList.isEmpty();
242 
243  // don't consider a range that is behind the end of the document
244  const KTextEditor::Range documentIntersection = m_document->documentRange().intersect(range);
245  if(!documentIntersection.isValid()) { // the intersection might however be empty if the last
246  return; // word has been removed, for example
247  }
248 
249  // for performance reasons we only want to schedule spellchecks for ranges that are visible
250  foreach(KTextEditor::View *i, m_document->views()) {
251  KateView *view = static_cast<KateView*>(i);
252  KTextEditor::Range visibleIntersection = documentIntersection.intersect(view->visibleRange());
253  if(visibleIntersection.isValid()) { // see above
254  // we don't handle this directly as the highlighting information might not be up-to-date yet
255  KTextEditor::MovingRange *movingRange = m_document->newMovingRange(visibleIntersection);
256  movingRange->setFeedback(this);
257  m_modificationList.push_back(ModificationItem(TEXT_REMOVED, movingRange));
258  ON_THE_FLY_DEBUG << "added" << *movingRange << view->visibleRange();
259  }
260  }
261  if(listEmptyAtStart && !m_modificationList.isEmpty()) {
262  QTimer::singleShot(0, this, SLOT(handleModifiedRanges()));
263  }
264 }
265 
266 inline bool rangesAdjacent(const KTextEditor::Range &r1, const KTextEditor::Range &r2)
267 {
268  return (r1.end() == r2.start()) || (r2.end() == r1.start());
269 }
270 
271 void KateOnTheFlyChecker::handleRemovedText(const KTextEditor::Range &range)
272 {
273 
274  ON_THE_FLY_DEBUG << range;
275 
276  QList<KTextEditor::Range> rangesToReCheck;
277  for(QList<SpellCheckItem>::iterator i = m_spellCheckQueue.begin();
278  i != m_spellCheckQueue.end();) {
279  KTextEditor::MovingRange *spellCheckRange = (*i).first;
280  if(rangesAdjacent(*spellCheckRange, range) || spellCheckRange->contains(range)) {
281  ON_THE_FLY_DEBUG << "erasing range " << *i;
282  if(!spellCheckRange->isEmpty()) {
283  rangesToReCheck.push_back(*spellCheckRange);
284  }
285  deleteMovingRangeQuickly(spellCheckRange);
286  i = m_spellCheckQueue.erase(i);
287  }
288  else {
289  ++i;
290  }
291  }
292  bool spellCheckInProgress = m_currentlyCheckedItem != invalidSpellCheckQueueItem;
293  const bool emptyAtStart = m_spellCheckQueue.isEmpty();
294  if(spellCheckInProgress) {
295  KTextEditor::MovingRange *spellCheckRange = m_currentlyCheckedItem.first;
296  ON_THE_FLY_DEBUG << *spellCheckRange;
297  if(m_document->documentRange().contains(*spellCheckRange)
298  && (rangesAdjacent(*spellCheckRange, range) || spellCheckRange->contains(range))
299  && !spellCheckRange->isEmpty()) {
300  rangesToReCheck.push_back(*spellCheckRange);
301  ON_THE_FLY_DEBUG << "added the range " << *spellCheckRange;
302  stopCurrentSpellCheck();
303  deleteMovingRangeQuickly(spellCheckRange);
304  }
305  else if(spellCheckRange->isEmpty()) {
306  stopCurrentSpellCheck();
307  deleteMovingRangeQuickly(spellCheckRange);
308  }
309  else {
310  spellCheckInProgress = false;
311  }
312  }
313  for(QList<KTextEditor::Range>::iterator i = rangesToReCheck.begin(); i != rangesToReCheck.end(); ++i) {
314  queueSpellCheckVisibleRange(*i);
315  }
316 
317  KTextEditor::Range spellCheckRange = findWordBoundaries(range.start(), range.start());
318  KTextEditor::Cursor spellCheckEnd = spellCheckRange.end();
319 
320  queueSpellCheckVisibleRange(spellCheckRange);
321 
322  if(range.numberOfLines() > 0) {
323  //FIXME: there is no currently no way of doing this better as we only get notifications for removals of
324  // of single lines, i.e. we don't know here how many lines have been removed in total
325  KTextEditor::Cursor nextLineStart(spellCheckEnd.line() + 1, 0);
326  const KTextEditor::Cursor documentEnd = m_document->documentEnd();
327  if(nextLineStart < documentEnd) {
328  KTextEditor::Range rangeBelow = KTextEditor::Range(nextLineStart, documentEnd);
329 
330  const QList<KTextEditor::View*>& viewList = m_document->views();
331  for(QList<KTextEditor::View*>::const_iterator i = viewList.begin(); i != viewList.end(); ++i) {
332  KateView *view = static_cast<KateView*>(*i);
333  const KTextEditor::Range visibleRange = view->visibleRange();
334  KTextEditor::Range intersection = visibleRange.intersect(rangeBelow);
335  if(intersection.isValid()) {
336  queueSpellCheckVisibleRange(view, intersection);
337  }
338  }
339  }
340  }
341 
342  ON_THE_FLY_DEBUG << "finished";
343  if(spellCheckInProgress || (emptyAtStart && !m_spellCheckQueue.isEmpty())) {
344  QTimer::singleShot(0, this, SLOT(performSpellCheck()));
345  }
346 }
347 
348 void KateOnTheFlyChecker::freeDocument()
349 {
350  ON_THE_FLY_DEBUG;
351 
352  // empty the spell check queue
353  for(QList<SpellCheckItem>::iterator i = m_spellCheckQueue.begin();
354  i != m_spellCheckQueue.end();) {
355  ON_THE_FLY_DEBUG << "erasing range " << *i;
356  KTextEditor::MovingRange *movingRange = (*i).first;
357  deleteMovingRangeQuickly(movingRange);
358  i = m_spellCheckQueue.erase(i);
359  }
360  if(m_currentlyCheckedItem != invalidSpellCheckQueueItem) {
361  KTextEditor::MovingRange *movingRange = m_currentlyCheckedItem.first;
362  deleteMovingRangeQuickly(movingRange);
363  }
364  stopCurrentSpellCheck();
365 
366  MisspelledList misspelledList = m_misspelledList; // make a copy!
367  foreach(const MisspelledItem &i, misspelledList) {
368  deleteMovingRange(i.first);
369  }
370  m_misspelledList.clear();
371  clearModificationList();
372 }
373 
374 void KateOnTheFlyChecker::performSpellCheck()
375 {
376  if(m_currentlyCheckedItem != invalidSpellCheckQueueItem) {
377  ON_THE_FLY_DEBUG << "exited as a check is currently in progress";
378  return;
379  }
380  if(m_spellCheckQueue.isEmpty()) {
381  ON_THE_FLY_DEBUG << "exited as there is nothing to do";
382  return;
383  }
384  m_currentlyCheckedItem = m_spellCheckQueue.takeFirst();
385 
386  KTextEditor::MovingRange *spellCheckRange = m_currentlyCheckedItem.first;
387  const QString& language = m_currentlyCheckedItem.second;
388  ON_THE_FLY_DEBUG << "for the range " << *spellCheckRange;
389  // clear all the highlights that are currently present in the range that
390  // is supposed to be checked
391  const MovingRangeList highlightsList = installedMovingRanges(*spellCheckRange); // make a copy!
392  deleteMovingRanges(highlightsList);
393 
394  m_currentDecToEncOffsetList.clear();
395  KateDocument::OffsetList encToDecOffsetList;
396  QString text = m_document->decodeCharacters(*spellCheckRange,
397  m_currentDecToEncOffsetList,
398  encToDecOffsetList);
399  ON_THE_FLY_DEBUG << "next spell checking" << text;
400  if(text.isEmpty()) { // passing an empty string to Sonnet can lead to a bad allocation exception
401  spellCheckDone(); // (bug 225867)
402  return;
403  }
404  if(m_speller.language() != language) {
405  m_speller.setLanguage(language);
406  }
407  if(!m_backgroundChecker) {
408  m_backgroundChecker = new Sonnet::BackgroundChecker(m_speller, this);
409  connect(m_backgroundChecker,
410  SIGNAL(misspelling(QString,int)),
411  this,
412  SLOT(misspelling(QString,int)));
413  connect(m_backgroundChecker, SIGNAL(done()), this, SLOT(spellCheckDone()));
414 
415  m_backgroundChecker->restore(KGlobal::config().data());
416  }
417  m_backgroundChecker->setSpeller(m_speller);
418  m_backgroundChecker->setText(text); // don't call 'start()' after this!
419 }
420 
421 void KateOnTheFlyChecker::removeRangeFromEverything(KTextEditor::MovingRange *movingRange)
422 {
423  Q_ASSERT(m_document == movingRange->document());
424  ON_THE_FLY_DEBUG << *movingRange << "(" << movingRange << ")";
425 
426  if(removeRangeFromModificationList(movingRange)) {
427  return; // range was part of the modification queue, so we don't have
428  // to look further for it
429  }
430 
431  if(removeRangeFromSpellCheckQueue(movingRange)) {
432  return; // range was part of the spell check queue, so it cannot have been
433  // a misspelled range
434  }
435 
436  for(MisspelledList::iterator i = m_misspelledList.begin(); i != m_misspelledList.end();) {
437  if((*i).first == movingRange) {
438  i = m_misspelledList.erase(i);
439  }
440  else {
441  ++i;
442  }
443  }
444 }
445 
446 bool KateOnTheFlyChecker::removeRangeFromCurrentSpellCheck(KTextEditor::MovingRange *range)
447 {
448  if(m_currentlyCheckedItem != invalidSpellCheckQueueItem
449  && m_currentlyCheckedItem.first == range) {
450  stopCurrentSpellCheck();
451  return true;
452  }
453  return false;
454 }
455 
456 void KateOnTheFlyChecker::stopCurrentSpellCheck()
457 {
458  m_currentDecToEncOffsetList.clear();
459  m_currentlyCheckedItem = invalidSpellCheckQueueItem;
460  if(m_backgroundChecker) {
461  m_backgroundChecker->stop();
462  }
463 }
464 
465 bool KateOnTheFlyChecker::removeRangeFromSpellCheckQueue(KTextEditor::MovingRange *range)
466 {
467  if(removeRangeFromCurrentSpellCheck(range)) {
468  if(!m_spellCheckQueue.isEmpty()) {
469  QTimer::singleShot(0, this, SLOT(performSpellCheck()));
470  }
471  return true;
472  }
473  bool found = false;
474  for(QList<SpellCheckItem>::iterator i = m_spellCheckQueue.begin();
475  i != m_spellCheckQueue.end();) {
476  if((*i).first == range) {
477  i = m_spellCheckQueue.erase(i);
478  found = true;
479  }
480  else {
481  ++i;
482  }
483  }
484  return found;
485 }
486 
487 void KateOnTheFlyChecker::rangeEmpty(KTextEditor::MovingRange *range)
488 {
489  ON_THE_FLY_DEBUG << range->start() << range->end() << "(" << range << ")";
490  deleteMovingRange (range);
491 }
492 
493 void KateOnTheFlyChecker::rangeInvalid (KTextEditor::MovingRange* range)
494 {
495  ON_THE_FLY_DEBUG << range->start() << range->end() << "(" << range << ")";
496  deleteMovingRange (range);
497 }
498 
499 void KateOnTheFlyChecker::mouseEnteredRange(KTextEditor::MovingRange *range, KTextEditor::View *view)
500 {
501  KateView *kateView = static_cast<KateView*>(view);
502  kateView->spellingMenu()->mouseEnteredMisspelledRange(range);
503 }
504 
505 void KateOnTheFlyChecker::mouseExitedRange(KTextEditor::MovingRange *range, KTextEditor::View *view)
506 {
507  KateView *kateView = static_cast<KateView*>(view);
508  kateView->spellingMenu()->mouseExitedMisspelledRange(range);
509 }
510 
515 void KateOnTheFlyChecker::caretEnteredRange(KTextEditor::MovingRange *range, KTextEditor::View *view)
516 {
517  KateView *kateView = static_cast<KateView*>(view);
518  kateView->spellingMenu()->caretEnteredMisspelledRange(range);
519 }
520 
521 void KateOnTheFlyChecker::caretExitedRange(KTextEditor::MovingRange *range, KTextEditor::View *view)
522 {
523  KateView *kateView = static_cast<KateView*>(view);
524  kateView->spellingMenu()->caretExitedMisspelledRange(range);
525 }
526 
527 void KateOnTheFlyChecker::deleteMovingRange(KTextEditor::MovingRange *range)
528 {
529  ON_THE_FLY_DEBUG << range;
530  // remove it from all our structures
531  removeRangeFromEverything(range);
532  range->setFeedback(NULL);
533  foreach(KTextEditor::View *view, m_document->views()) {
534  static_cast<KateView*>(view)->spellingMenu()->rangeDeleted(range);
535  }
536  delete(range);
537 }
538 
539 void KateOnTheFlyChecker::deleteMovingRanges(const QList<KTextEditor::MovingRange*>& list)
540 {
541  foreach(KTextEditor::MovingRange *r, list) {
542  deleteMovingRange(r);
543  }
544 }
545 
546 KTextEditor::Range KateOnTheFlyChecker::findWordBoundaries(const KTextEditor::Cursor& begin,
547  const KTextEditor::Cursor& end)
548 {
549  // FIXME: QTextBoundaryFinder should be ideally used for this, but it is currently
550  // still broken in Qt
551  const QRegExp boundaryRegExp("\\b");
552  const QRegExp boundaryQuoteRegExp("\\b\\w+'\\w*$"); // handle spell checking of "isn't", "doesn't", etc.
553  const QRegExp extendedBoundaryRegExp("(\\W|$)");
554  const QRegExp extendedBoundaryQuoteRegExp("^\\w*'\\w+\\b"); // see above
555  KateDocument::OffsetList decToEncOffsetList, encToDecOffsetList;
556  const int startLine = begin.line();
557  const int startColumn = begin.column();
558  KTextEditor::Cursor boundaryStart, boundaryEnd;
559  // first we take care of the start position
560  const KTextEditor::Range startLineRange(startLine, 0, startLine, m_document->lineLength(startLine));
561  QString decodedLineText = m_document->decodeCharacters(startLineRange,
562  decToEncOffsetList,
563  encToDecOffsetList);
564  int translatedColumn = m_document->computePositionWrtOffsets(encToDecOffsetList,
565  startColumn);
566  QString text = decodedLineText.mid(0, translatedColumn);
567  boundaryStart.setLine(startLine);
568  int match = text.lastIndexOf(boundaryQuoteRegExp);
569  if(match < 0) {
570  match = text.lastIndexOf(boundaryRegExp);
571  }
572  boundaryStart.setColumn(m_document->computePositionWrtOffsets(decToEncOffsetList, qMax(0, match)));
573  // and now the end position
574  const int endLine = end.line();
575  const int endColumn = end.column();
576  if(endLine != startLine) {
577  decToEncOffsetList.clear();
578  encToDecOffsetList.clear();
579  const KTextEditor::Range endLineRange(endLine, 0, endLine, m_document->lineLength(endLine));
580  decodedLineText = m_document->decodeCharacters(endLineRange,
581  decToEncOffsetList,
582  encToDecOffsetList);
583  }
584  translatedColumn = m_document->computePositionWrtOffsets(encToDecOffsetList,
585  endColumn);
586  text = decodedLineText.mid(translatedColumn);
587  boundaryEnd.setLine(endLine);
588  match = extendedBoundaryQuoteRegExp.indexIn(text);
589  if(match == 0) {
590  match = extendedBoundaryQuoteRegExp.matchedLength();
591  }
592  else {
593  match = extendedBoundaryRegExp.indexIn(text);
594  }
595  boundaryEnd.setColumn(m_document->computePositionWrtOffsets(decToEncOffsetList,
596  translatedColumn + qMax(0, match)));
597  return KTextEditor::Range(boundaryStart, boundaryEnd);
598 }
599 
600 void KateOnTheFlyChecker::misspelling(const QString &word, int start)
601 {
602  if(m_currentlyCheckedItem == invalidSpellCheckQueueItem) {
603  ON_THE_FLY_DEBUG << "exited as no spell check is taking place";
604  return;
605  }
606  int translatedStart = m_document->computePositionWrtOffsets(m_currentDecToEncOffsetList,
607  start);
608 // ON_THE_FLY_DEBUG << "misspelled " << word
609 // << " at line "
610 // << *m_currentlyCheckedItem.first
611 // << " column " << start;
612 
613  KTextEditor::MovingRange *spellCheckRange = m_currentlyCheckedItem.first;
614  int line = spellCheckRange->start().line();
615  int rangeStart = spellCheckRange->start().column();
616  int translatedEnd = m_document->computePositionWrtOffsets(m_currentDecToEncOffsetList,
617  start + word.length());
618 
619  KTextEditor::MovingRange *movingRange =
620  m_document->newMovingRange(KTextEditor::Range(line,
621  rangeStart + translatedStart,
622  line,
623  rangeStart + translatedEnd));
624  movingRange->setFeedback(this);
625  KTextEditor::Attribute *attribute = new KTextEditor::Attribute();
626  attribute->setUnderlineStyle(QTextCharFormat::SpellCheckUnderline);
627  attribute->setUnderlineColor(KateRendererConfig::global()->spellingMistakeLineColor());
628 
629  // don't print this range
630  movingRange->setAttributeOnlyForViews (true);
631 
632  movingRange->setAttribute(KTextEditor::Attribute::Ptr(attribute));
633  m_misspelledList.push_back(MisspelledItem(movingRange, m_currentlyCheckedItem.second));
634 
635  if(m_backgroundChecker) {
636  m_backgroundChecker->continueChecking();
637  }
638 }
639 
640 void KateOnTheFlyChecker::spellCheckDone()
641 {
642  ON_THE_FLY_DEBUG << "on-the-fly spell check done, queue length " << m_spellCheckQueue.size();
643  if(m_currentlyCheckedItem == invalidSpellCheckQueueItem) {
644  return;
645  }
646  KTextEditor::MovingRange *movingRange = m_currentlyCheckedItem.first;
647  stopCurrentSpellCheck();
648  deleteMovingRangeQuickly(movingRange);
649 
650  if(!m_spellCheckQueue.empty()) {
651  QTimer::singleShot(0, this, SLOT(performSpellCheck()));
652  }
653 }
654 
655 QList<KTextEditor::MovingRange*> KateOnTheFlyChecker::installedMovingRanges(const KTextEditor::Range& range)
656 {
657  ON_THE_FLY_DEBUG << range;
658  MovingRangeList toReturn;
659 
660  for(QList<SpellCheckItem>::iterator i = m_misspelledList.begin();
661  i != m_misspelledList.end(); ++i) {
662  KTextEditor::MovingRange *movingRange = (*i).first;
663  if(movingRange->overlaps(range)) {
664  toReturn.push_back(movingRange);
665  }
666  }
667  return toReturn;
668 }
669 
670 void KateOnTheFlyChecker::updateConfig()
671 {
672  ON_THE_FLY_DEBUG;
673  m_speller.restore(KGlobal::config().data());
674 
675  if(m_backgroundChecker) {
676  m_backgroundChecker->restore(KGlobal::config().data());
677  }
678 }
679 
680 void KateOnTheFlyChecker::refreshSpellCheck(const KTextEditor::Range &range)
681 {
682  if(range.isValid()) {
683  textInserted(m_document, range);
684  }
685  else {
686  freeDocument();
687  textInserted(m_document, m_document->documentRange());
688  }
689 }
690 
691 void KateOnTheFlyChecker::addView(KTextEditor::Document *document, KTextEditor::View *view)
692 {
693  Q_ASSERT(document == m_document);
694  Q_UNUSED(document);
695  ON_THE_FLY_DEBUG;
696  connect(view, SIGNAL(destroyed(QObject*)), this, SLOT(viewDestroyed(QObject*)));
697  connect(view, SIGNAL(displayRangeChanged(KateView*)), this, SLOT(restartViewRefreshTimer(KateView*)));
698  updateInstalledMovingRanges(static_cast<KateView*>(view));
699 }
700 
701 void KateOnTheFlyChecker::viewDestroyed(QObject* obj)
702 {
703  ON_THE_FLY_DEBUG;
704  KTextEditor::View *view = static_cast<KTextEditor::View*>(obj);
705  m_displayRangeMap.remove(view);
706 }
707 
708 void KateOnTheFlyChecker::removeView(KTextEditor::View *view)
709 {
710  ON_THE_FLY_DEBUG;
711  m_displayRangeMap.remove(view);
712 }
713 
714 void KateOnTheFlyChecker::updateInstalledMovingRanges(KateView *view)
715 {
716  Q_ASSERT(m_document == view->document());
717  ON_THE_FLY_DEBUG;
718  KTextEditor::Range oldDisplayRange = m_displayRangeMap[view];
719 
720  KTextEditor::Range newDisplayRange = view->visibleRange();
721  ON_THE_FLY_DEBUG << "new range: " << newDisplayRange;
722  ON_THE_FLY_DEBUG << "old range: " << oldDisplayRange;
723  QList<KTextEditor::MovingRange*> toDelete;
724  foreach(const MisspelledItem &item, m_misspelledList) {
725  KTextEditor::MovingRange *movingRange = item.first;
726  if(!movingRange->overlaps(newDisplayRange)) {
727  bool stillVisible = false;
728  foreach(KTextEditor::View *it2, m_document->views()) {
729  KateView *view2 = static_cast<KateView*>(it2);
730  if(view != view2 && movingRange->overlaps(view2->visibleRange())) {
731  stillVisible = true;
732  break;
733  }
734  }
735  if(!stillVisible) {
736  toDelete.push_back(movingRange);
737  }
738  }
739  }
740  deleteMovingRanges (toDelete);
741  m_displayRangeMap[view] = newDisplayRange;
742  if(oldDisplayRange.isValid()) {
743  bool emptyAtStart = m_spellCheckQueue.empty();
744  for(int line = newDisplayRange.end().line(); line >= newDisplayRange.start().line(); --line) {
745  if(!oldDisplayRange.containsLine(line)) {
746  bool visible = false;
747  foreach(KTextEditor::View *it2, m_document->views()) {
748  KateView *view2 = static_cast<KateView*>(it2);
749  if(view != view2 && view2->visibleRange().containsLine(line)) {
750  visible = true;
751  break;
752  }
753  }
754  if(!visible) {
755  queueLineSpellCheck(m_document, line);
756  }
757  }
758  }
759  if(emptyAtStart && !m_spellCheckQueue.isEmpty()) {
760  QTimer::singleShot(0, this, SLOT(performSpellCheck()));
761  }
762  }
763 }
764 
765 void KateOnTheFlyChecker::queueSpellCheckVisibleRange(const KTextEditor::Range& range)
766 {
767  const QList<KTextEditor::View*>& viewList = m_document->views();
768  for(QList<KTextEditor::View*>::const_iterator i = viewList.begin(); i != viewList.end(); ++i) {
769  queueSpellCheckVisibleRange(static_cast<KateView*>(*i), range);
770  }
771 }
772 
773 void KateOnTheFlyChecker::queueSpellCheckVisibleRange(KateView *view, const KTextEditor::Range& range)
774 {
775  Q_ASSERT(m_document == view->doc());
776  KTextEditor::Range visibleRange = view->visibleRange();
777  KTextEditor::Range intersection = visibleRange.intersect(range);
778  if(intersection.isEmpty()) {
779  return;
780  }
781 
782  // clear all the highlights that are currently present in the range that
783  // is supposed to be checked, necessary due to highlighting
784  const MovingRangeList highlightsList = installedMovingRanges(intersection);
785  deleteMovingRanges(highlightsList);
786 
787  QList<QPair<KTextEditor::Range, QString> > spellCheckRanges
788  = KateGlobal::self()->spellCheckManager()->spellCheckRanges(m_document,
789  intersection,
790  true);
791  //we queue them up in reverse
792  QListIterator<QPair<KTextEditor::Range, QString> > i(spellCheckRanges);
793  i.toBack();
794  while(i.hasPrevious()) {
795  QPair<KTextEditor::Range, QString> p = i.previous();
796  queueLineSpellCheck(p.first, p.second);
797  }
798 }
799 
800 void KateOnTheFlyChecker::queueLineSpellCheck(KateDocument *kateDocument, int line)
801 {
802  const KTextEditor::Range range = KTextEditor::Range(line, 0, line, kateDocument->lineLength(line));
803  // clear all the highlights that are currently present in the range that
804  // is supposed to be checked, necessary due to highlighting
805 
806  const MovingRangeList highlightsList = installedMovingRanges(range);
807  deleteMovingRanges(highlightsList);
808 
809  QList<QPair<KTextEditor::Range, QString> > spellCheckRanges
810  = KateGlobal::self()->spellCheckManager()->spellCheckRanges(kateDocument,
811  range,
812  true);
813  //we queue them up in reverse
814  QListIterator<QPair<KTextEditor::Range, QString> > i(spellCheckRanges);
815  i.toBack();
816  while(i.hasPrevious()) {
817  QPair<KTextEditor::Range, QString> p = i.previous();
818  queueLineSpellCheck(p.first, p.second);
819  }
820 }
821 
822 void KateOnTheFlyChecker::queueLineSpellCheck(const KTextEditor::Range& range, const QString& dictionary)
823 {
824  ON_THE_FLY_DEBUG << m_document << range;
825 
826  Q_ASSERT(range.onSingleLine());
827 
828  if(range.isEmpty()) {
829  return;
830  }
831 
832  addToSpellCheckQueue(range, dictionary);
833 }
834 
835 void KateOnTheFlyChecker::addToSpellCheckQueue(const KTextEditor::Range& range, const QString& dictionary)
836 {
837  addToSpellCheckQueue(m_document->newMovingRange(range), dictionary);
838 }
839 
840 void KateOnTheFlyChecker::addToSpellCheckQueue(KTextEditor::MovingRange *range, const QString& dictionary)
841 {
842  ON_THE_FLY_DEBUG << m_document << *range << dictionary;
843 
844  range->setFeedback(this);
845 
846  // if the queue contains a subrange of 'range', we remove that one
847  for(QList<SpellCheckItem>::iterator i = m_spellCheckQueue.begin();
848  i != m_spellCheckQueue.end();) {
849  KTextEditor::MovingRange *spellCheckRange = (*i).first;
850  if(range->contains(*spellCheckRange)) {
851  deleteMovingRangeQuickly(spellCheckRange);
852  i = m_spellCheckQueue.erase(i);
853  }
854  else {
855  ++i;
856  }
857  }
858  // leave 'push_front' here as it is a LIFO queue, i.e. a stack
859  m_spellCheckQueue.push_front(SpellCheckItem(range, dictionary));
860  ON_THE_FLY_DEBUG << "added"
861  << *range << dictionary
862  << "to the queue, which has a length of" << m_spellCheckQueue.size();
863 }
864 
865 void KateOnTheFlyChecker::viewRefreshTimeout()
866 {
867  if(m_refreshView) {
868  updateInstalledMovingRanges(m_refreshView);
869  }
870  m_refreshView = NULL;
871 }
872 
873 void KateOnTheFlyChecker::restartViewRefreshTimer(KateView *view)
874 {
875  if(m_refreshView && view != m_refreshView) { // a new view should be refreshed
876  updateInstalledMovingRanges(m_refreshView); // so refresh the old one first
877  }
878  m_refreshView = view;
879  m_viewRefreshTimer->start(100);
880 }
881 
882 void KateOnTheFlyChecker::deleteMovingRangeQuickly(KTextEditor::MovingRange *range)
883 {
884  range->setFeedback(NULL);
885  foreach(KTextEditor::View *view, m_document->views()) {
886  static_cast<KateView*>(view)->spellingMenu()->rangeDeleted(range);
887  }
888  delete(range);
889 }
890 
891 void KateOnTheFlyChecker::handleModifiedRanges()
892 {
893  foreach(const ModificationItem &item, m_modificationList) {
894  KTextEditor::MovingRange *movingRange = item.second;
895  KTextEditor::Range range = *movingRange;
896  deleteMovingRangeQuickly(movingRange);
897  if(item.first == TEXT_INSERTED) {
898  handleInsertedText(range);
899  }
900  else {
901  handleRemovedText(range);
902  }
903  }
904  m_modificationList.clear();
905 }
906 
907 bool KateOnTheFlyChecker::removeRangeFromModificationList(KTextEditor::MovingRange *range)
908 {
909  bool found = false;
910  for(ModificationList::iterator i = m_modificationList.begin(); i != m_modificationList.end();) {
911  ModificationItem item = *i;
912  KTextEditor::MovingRange *movingRange = item.second;
913  if(movingRange == range) {
914  found = true;
915  i = m_modificationList.erase(i);
916  }
917  else {
918  ++i;
919  }
920  }
921  return found;
922 }
923 
924 void KateOnTheFlyChecker::clearModificationList()
925 {
926  foreach(const ModificationItem &item, m_modificationList) {
927  KTextEditor::MovingRange *movingRange = item.second;
928  deleteMovingRangeQuickly(movingRange);
929  }
930  m_modificationList.clear();
931 }
932 
933 #include "ontheflycheck.moc"
934 
935 // kate: space-indent on; indent-width 2; replace-tabs on;
KTextEditor::MovingRange::setFeedback
virtual void setFeedback(MovingRangeFeedback *feedback)=0
KateDocument::buffer
KateBuffer & buffer()
Get access to buffer of this document.
Definition: katedocument.h:946
KTextEditor::Range::start
Cursor & start()
KateOnTheFlyChecker::m_speller
Sonnet::Speller m_speller
Definition: ontheflycheck.h:75
KSharedPtr< Attribute >
KateOnTheFlyChecker::dictionaryForMisspelledRange
QString dictionaryForMisspelledRange(const KTextEditor::Range &range) const
Definition: ontheflycheck.cpp:95
KateGlobal::spellCheckManager
KateSpellCheckManager * spellCheckManager()
spell check manager
Definition: kateglobal.h:344
KateOnTheFlyChecker::getMisspelledItem
QPair< KTextEditor::Range, QString > getMisspelledItem(const KTextEditor::Cursor &cursor) const
Definition: ontheflycheck.cpp:84
kateview.h
KateDocument::computePositionWrtOffsets
int computePositionWrtOffsets(const OffsetList &offsetList, int pos)
Definition: katedocument.cpp:5254
KateOnTheFlyChecker::textInserted
void textInserted(KTextEditor::Document *document, const KTextEditor::Range &range)
Definition: ontheflycheck.cpp:138
KateDocument::newMovingRange
virtual KTextEditor::MovingRange * newMovingRange(const KTextEditor::Range &range, KTextEditor::MovingRange::InsertBehaviors insertBehaviors=KTextEditor::MovingRange::DoNotExpand, KTextEditor::MovingRange::EmptyBehavior emptyBehavior=KTextEditor::MovingRange::AllowEmpty)
Create a new moving range for this document.
Definition: katedocument.cpp:4742
KTextEditor::MovingCursor::column
virtual int column() const =0
KateView::document
KTextEditor::Document * document() const
Definition: kateview.cpp:2769
katerenderer.h
KTextEditor::Attribute
KateOnTheFlyChecker::removeRangeFromEverything
virtual void removeRangeFromEverything(KTextEditor::MovingRange *range)
Definition: ontheflycheck.cpp:421
KateOnTheFlyChecker::viewDestroyed
void viewDestroyed(QObject *obj)
Definition: ontheflycheck.cpp:701
KateOnTheFlyChecker::m_refreshView
QPointer< KateView > m_refreshView
Definition: ontheflycheck.h:101
KTextEditor::Range::isValid
virtual bool isValid() const
Sonnet::BackgroundChecker::setText
void setText(const QString &text)
KateOnTheFlyChecker::misspelling
void misspelling(const QString &word, int start)
Definition: ontheflycheck.cpp:600
timeout
int timeout
KateOnTheFlyChecker::m_viewRefreshTimer
QTimer * m_viewRefreshTimer
Definition: ontheflycheck.h:100
KateDocument::lineLength
virtual int lineLength(int line) const
Definition: katedocument.cpp:758
KateOnTheFlyChecker::m_currentlyCheckedItem
SpellCheckItem m_currentlyCheckedItem
Definition: ontheflycheck.h:78
KateOnTheFlyChecker::m_misspelledList
MisspelledList m_misspelledList
Definition: ontheflycheck.h:80
KateOnTheFlyChecker::m_currentDecToEncOffsetList
KateDocument::OffsetList m_currentDecToEncOffsetList
Definition: ontheflycheck.h:82
KateOnTheFlyChecker::handleInsertedText
void handleInsertedText(const KTextEditor::Range &range)
Definition: ontheflycheck.cpp:171
KateOnTheFlyChecker::removeView
void removeView(KTextEditor::View *view)
Definition: ontheflycheck.cpp:708
KateOnTheFlyChecker::stopCurrentSpellCheck
void stopCurrentSpellCheck()
Definition: ontheflycheck.cpp:456
KateGlobal::self
static KateGlobal * self()
Kate Part Internal stuff ;)
Definition: kateglobal.cpp:462
KTextEditor::MovingRange
QString
QObject
KTextEditor::Cursor
Sonnet::BackgroundChecker::continueChecking
virtual void continueChecking()
spellcheck.h
KateOnTheFlyChecker::queueSpellCheckVisibleRange
void queueSpellCheckVisibleRange(const KTextEditor::Range &range)
Definition: ontheflycheck.cpp:765
KGlobal::config
KSharedConfigPtr config()
KTextEditor::MovingRange::setAttributeOnlyForViews
virtual void setAttributeOnlyForViews(bool onlyForViews)=0
katebuffer.h
Sonnet::BackgroundChecker::stop
virtual void stop()
KTextEditor::MovingRange::contains
bool contains(const Range &range) const
KateView::visibleRange
KTextEditor::Range visibleRange()
Definition: kateview.cpp:3021
KateOnTheFlyChecker::m_backgroundChecker
Sonnet::BackgroundChecker * m_backgroundChecker
Definition: ontheflycheck.h:77
KateDocument::decodeCharacters
QString decodeCharacters(const KTextEditor::Range &range, KateDocument::OffsetList &decToEncOffsetList, KateDocument::OffsetList &encToDecOffsetList)
The first OffsetList is from decoded to encoded, and the second OffsetList from encoded to decoded...
Definition: katedocument.cpp:5266
KateOnTheFlyChecker::findWordBoundaries
KTextEditor::Range findWordBoundaries(const KTextEditor::Cursor &begin, const KTextEditor::Cursor &end)
Definition: ontheflycheck.cpp:546
KateOnTheFlyChecker::handleModifiedRanges
void handleModifiedRanges()
Definition: ontheflycheck.cpp:891
ON_THE_FLY_DEBUG
#define ON_THE_FLY_DEBUG
Definition: ontheflycheck.cpp:38
KateOnTheFlyChecker::updateInstalledMovingRanges
void updateInstalledMovingRanges(KateView *view)
Definition: ontheflycheck.cpp:714
KTextEditor::Document
kateglobal.h
KateOnTheFlyChecker::m_modificationList
ModificationList m_modificationList
Definition: ontheflycheck.h:81
rangesAdjacent
bool rangesAdjacent(const KTextEditor::Range &r1, const KTextEditor::Range &r2)
Definition: ontheflycheck.cpp:266
KTextEditor::Range::invalid
static Range invalid()
Sonnet::BackgroundChecker::restore
void restore(KConfig *config)
Sonnet::BackgroundChecker::setSpeller
void setSpeller(const Speller &speller)
KDebug::registerArea
static int registerArea(const QByteArray &areaName, bool enabled=true)
KateOnTheFlyChecker::addView
void addView(KTextEditor::Document *document, KTextEditor::View *view)
Definition: ontheflycheck.cpp:691
KateDocument::documentEnd
virtual KTextEditor::Cursor documentEnd() const
Definition: katedocument.cpp:4682
KTextEditor::MovingRange::isEmpty
bool isEmpty() const
KTextEditor::MovingRange::document
virtual Document * document() const =0
KateOnTheFlyChecker::installedMovingRanges
MovingRangeList installedMovingRanges(const KTextEditor::Range &range)
Definition: ontheflycheck.cpp:655
KateOnTheFlyChecker::handleRemovedText
void handleRemovedText(const KTextEditor::Range &range)
Definition: ontheflycheck.cpp:271
KateRendererConfig::global
static KateRendererConfig * global()
Definition: kateconfig.h:613
KTextEditor::MovingRange::setAttribute
virtual void setAttribute(Attribute::Ptr attribute)=0
KateOnTheFlyChecker::deleteMovingRanges
void deleteMovingRanges(const QList< KTextEditor::MovingRange * > &list)
Definition: ontheflycheck.cpp:539
KateOnTheFlyChecker::deleteMovingRangeQuickly
void deleteMovingRangeQuickly(KTextEditor::MovingRange *range)
Definition: ontheflycheck.cpp:882
KateOnTheFlyChecker::mouseExitedRange
virtual void mouseExitedRange(KTextEditor::MovingRange *range, KTextEditor::View *view)
Definition: ontheflycheck.cpp:505
KateSpellingMenu::caretEnteredMisspelledRange
void caretEnteredMisspelledRange(KTextEditor::MovingRange *range)
Definition: spellingmenu.cpp:112
KTextEditor::Document::documentRange
Range documentRange() const
KateOnTheFlyChecker::m_spellCheckQueue
QList< SpellCheckItem > m_spellCheckQueue
Definition: ontheflycheck.h:76
KateView
Definition: kateview.h:78
KateOnTheFlyChecker::m_displayRangeMap
QMap< KTextEditor::View *, KTextEditor::Range > m_displayRangeMap
Definition: ontheflycheck.h:83
KateOnTheFlyChecker::textRemoved
void textRemoved(KTextEditor::Document *document, const KTextEditor::Range &range)
Definition: ontheflycheck.cpp:233
KTextEditor::Range
KateView::spellingMenu
KateSpellingMenu * spellingMenu()
Definition: kateview.cpp:3040
KateOnTheFlyChecker::refreshSpellCheck
void refreshSpellCheck(const KTextEditor::Range &range=KTextEditor::Range::invalid())
Definition: ontheflycheck.cpp:680
KateDocument
Definition: katedocument.h:74
KateOnTheFlyChecker::restartViewRefreshTimer
void restartViewRefreshTimer(KateView *view)
Definition: ontheflycheck.cpp:873
KTextEditor::Range::expandToRange
virtual bool expandToRange(const Range &range)
KateSpellingMenu::mouseExitedMisspelledRange
void mouseExitedMisspelledRange(KTextEditor::MovingRange *range)
Definition: spellingmenu.cpp:139
KateOnTheFlyChecker::handleRespellCheckBlock
void handleRespellCheckBlock(KateDocument *document, int start, int end)
Definition: ontheflycheck.cpp:120
KateOnTheFlyChecker::~KateOnTheFlyChecker
~KateOnTheFlyChecker()
Definition: ontheflycheck.cpp:73
KateOnTheFlyChecker::performSpellCheck
void performSpellCheck()
Definition: ontheflycheck.cpp:374
KateOnTheFlyChecker::invalidSpellCheckQueueItem
static const SpellCheckItem invalidSpellCheckQueueItem
Definition: ontheflycheck.h:79
KateOnTheFlyChecker::caretExitedRange
virtual void caretExitedRange(KTextEditor::MovingRange *range, KTextEditor::View *view)
Definition: ontheflycheck.cpp:521
KTextEditor::Cursor::line
virtual int line() const
KTextEditor::MovingRange::start
virtual const MovingCursor & start() const =0
KTextEditor::MovingCursor::line
virtual int line() const =0
KTextEditor::Cursor::setLine
virtual void setLine(int line)
spellingmenu.h
Sonnet::Speller::restore
void restore(KConfig *config)
KateOnTheFlyChecker::spellCheckDone
void spellCheckDone()
Definition: ontheflycheck.cpp:640
KateOnTheFlyChecker::freeDocument
void freeDocument()
Definition: ontheflycheck.cpp:348
Sonnet::BackgroundChecker
KateSpellingMenu::caretExitedMisspelledRange
void caretExitedMisspelledRange(KTextEditor::MovingRange *range)
Definition: spellingmenu.cpp:122
KTextEditor::Range::end
Cursor & end()
KateOnTheFlyChecker::clearMisspellingForWord
void clearMisspellingForWord(const QString &word)
Definition: ontheflycheck.cpp:106
KateOnTheFlyChecker::KateOnTheFlyChecker
KateOnTheFlyChecker(KateDocument *document)
Definition: ontheflycheck.cpp:40
KTextEditor::Range::containsLine
bool containsLine(int line) const
KateOnTheFlyChecker::m_document
KateDocument *const m_document
Definition: ontheflycheck.h:74
KateDocument::views
virtual const QList< KTextEditor::View * > & views() const
Definition: katedocument.cpp:309
KateDocument::text
virtual QString text(const KTextEditor::Range &range, bool blockwise=false) const
Definition: katedocument.cpp:337
KateOnTheFlyChecker::rangeInvalid
virtual void rangeInvalid(KTextEditor::MovingRange *range)
Definition: ontheflycheck.cpp:493
KTextEditor::Range::intersect
Range intersect(const Range &range) const
KateOnTheFlyChecker::queueLineSpellCheck
void queueLineSpellCheck(KateDocument *document, int line)
Definition: ontheflycheck.cpp:800
KateSpellingMenu::mouseEnteredMisspelledRange
void mouseEnteredMisspelledRange(KTextEditor::MovingRange *range)
Definition: spellingmenu.cpp:131
QPair
KateSpellCheckManager::spellCheckRanges
QList< QPair< KTextEditor::Range, QString > > spellCheckRanges(KateDocument *doc, const KTextEditor::Range &range, bool singleLine=false)
Definition: spellcheck.cpp:226
KateOnTheFlyChecker::viewRefreshTimeout
void viewRefreshTimeout()
Definition: ontheflycheck.cpp:865
KateView::doc
KateDocument * doc()
accessor to katedocument pointer
Definition: kateview.h:552
KateOnTheFlyChecker::removeRangeFromModificationList
bool removeRangeFromModificationList(KTextEditor::MovingRange *range)
Definition: ontheflycheck.cpp:907
Sonnet::Speller::language
QString language() const
KTextEditor::Range::contains
bool contains(const Range &range) const
KTextEditor::MovingRange::end
virtual const MovingCursor & end() const =0
ontheflycheck.h
KTextEditor::View
KateOnTheFlyChecker::debugArea
static int debugArea()
Definition: ontheflycheck.cpp:78
KateOnTheFlyChecker::clearModificationList
void clearModificationList()
Definition: ontheflycheck.cpp:924
KateOnTheFlyChecker::caretEnteredRange
virtual void caretEnteredRange(KTextEditor::MovingRange *range, KTextEditor::View *view)
It is not enough to use 'caret/Entered/ExitedRange' only as the cursor doesn't move when some text ha...
Definition: ontheflycheck.cpp:515
KTextEditor::Range::isEmpty
bool isEmpty() const
KateOnTheFlyChecker::deleteMovingRange
void deleteMovingRange(KTextEditor::MovingRange *range)
Definition: ontheflycheck.cpp:527
KateOnTheFlyChecker::addToSpellCheckQueue
void addToSpellCheckQueue(const KTextEditor::Range &range, const QString &dictionary)
Definition: ontheflycheck.cpp:835
KateOnTheFlyChecker::rangeEmpty
virtual void rangeEmpty(KTextEditor::MovingRange *range)
Definition: ontheflycheck.cpp:487
kateconfig.h
KTextEditor::Cursor::setColumn
virtual void setColumn(int column)
KTextEditor::Cursor::column
int column() const
Sonnet::Speller::setLanguage
void setLanguage(const QString &lang)
KTextEditor::MovingRange::overlaps
bool overlaps(const Range &range) const
KateOnTheFlyChecker::mouseEnteredRange
virtual void mouseEnteredRange(KTextEditor::MovingRange *range, KTextEditor::View *view)
Definition: ontheflycheck.cpp:499
QList< MisspelledItem >
KTextEditor::Range::overlaps
bool overlaps(const Range &range) const
KateOnTheFlyChecker::removeRangeFromCurrentSpellCheck
bool removeRangeFromCurrentSpellCheck(KTextEditor::MovingRange *range)
Definition: ontheflycheck.cpp:446
KateOnTheFlyChecker::removeRangeFromSpellCheckQueue
bool removeRangeFromSpellCheckQueue(KTextEditor::MovingRange *range)
Definition: ontheflycheck.cpp:465
KateOnTheFlyChecker::updateConfig
void updateConfig()
Definition: ontheflycheck.cpp:670
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:31:54 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Kate

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

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Applications
  •   Libraries
  •     libkonq
  • Konsole

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