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

Kate

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