Sonnet

backgroundchecker.cpp
1 /*
2  * backgroundchecker.cpp
3  *
4  * SPDX-FileCopyrightText: 2004 Zack Rusin <[email protected]>
5  * SPDX-FileCopyrightText: 2009 Jakub Stachowski <[email protected]>
6  *
7  * SPDX-License-Identifier: LGPL-2.1-or-later
8  */
9 #include "backgroundchecker.h"
10 #include "backgroundchecker_p.h"
11 
12 #include "core_debug.h"
13 
14 using namespace Sonnet;
15 
17 {
18  sentenceOffset = -1;
19  continueChecking();
20 }
21 
22 void BackgroundCheckerPrivate::continueChecking()
23 {
24  metaObject()->invokeMethod(this, "checkNext", Qt::QueuedConnection);
25 }
26 
27 void BackgroundCheckerPrivate::checkNext()
28 {
29  do {
30  // go over current sentence
31  while (sentenceOffset != -1 && words.hasNext()) {
32  Token word = words.next();
33  if (!words.isSpellcheckable()) {
34  continue;
35  }
36 
37  // ok, this is valid word, do something
38  if (currentDict.isMisspelled(word.toString())) {
39  lastMisspelled = word;
40  Q_EMIT misspelling(word.toString(), word.position() + sentenceOffset);
41  return;
42  }
43  }
44  // current sentence done, grab next suitable
45 
46  sentenceOffset = -1;
47  const bool autodetectLanguage = currentDict.testAttribute(Speller::AutoDetectLanguage);
48  const bool ignoreUpperCase = !currentDict.testAttribute(Speller::CheckUppercase);
49  while (mainTokenizer.hasNext()) {
50  Token sentence = mainTokenizer.next();
51  if (autodetectLanguage && !autoDetectLanguageDisabled) {
52  if (!mainTokenizer.isSpellcheckable()) {
53  continue;
54  }
55  // FIXME: find best from family en -> en_US, en_GB, ... ?
56  currentDict.setLanguage(mainTokenizer.language());
57  }
58  sentenceOffset = sentence.position();
59  words.setBuffer(sentence.toString());
60  words.setIgnoreUppercase(ignoreUpperCase);
61  break;
62  }
63  } while (sentenceOffset != -1);
64  Q_EMIT done();
65 }
66 
67 BackgroundChecker::BackgroundChecker(QObject *parent)
68  : QObject(parent)
69  , d(new BackgroundCheckerPrivate)
70 {
71  connect(d, &BackgroundCheckerPrivate::misspelling, this, &BackgroundChecker::misspelling);
72  connect(d, &BackgroundCheckerPrivate::done, this, &BackgroundChecker::slotEngineDone);
73 }
74 
75 BackgroundChecker::BackgroundChecker(const Speller &speller, QObject *parent)
76  : QObject(parent)
77  , d(new BackgroundCheckerPrivate)
78 {
79  d->currentDict = speller;
80  connect(d, &BackgroundCheckerPrivate::misspelling, this, &BackgroundChecker::misspelling);
81  connect(d, &BackgroundCheckerPrivate::done, this, &BackgroundChecker::slotEngineDone);
82 }
83 
84 BackgroundChecker::~BackgroundChecker()
85 {
86  delete d;
87 }
88 
90 {
91  d->mainTokenizer.setBuffer(text);
92  d->start();
93 }
94 
95 void BackgroundChecker::start()
96 {
97  // ## what if d->currentText.isEmpty()?
98 
99  // TODO: carry state from last buffer
100  d->mainTokenizer.setBuffer(fetchMoreText());
101  d->start();
102 }
103 
104 void BackgroundChecker::stop()
105 {
106  // d->stop();
107 }
108 
110 {
111  return QString();
112 }
113 
115 {
116 }
117 
119 {
120  return d->autoDetectLanguageDisabled;
121 }
122 
124 {
125  d->autoDetectLanguageDisabled = autoDetectDisabled;
126 }
127 
128 void BackgroundChecker::setSpeller(const Speller &speller)
129 {
130  d->currentDict = speller;
131 }
132 
133 Speller BackgroundChecker::speller() const
134 {
135  return d->currentDict;
136 }
137 
138 bool BackgroundChecker::checkWord(const QString &word)
139 {
140  return d->currentDict.isCorrect(word);
141 }
142 
143 bool BackgroundChecker::addWordToPersonal(const QString &word)
144 {
145  return d->currentDict.addToPersonal(word);
146 }
147 
149 {
150  return d->currentDict.addToSession(word);
151 }
152 
153 QStringList BackgroundChecker::suggest(const QString &word) const
154 {
155  return d->currentDict.suggest(word);
156 }
157 
158 void BackgroundChecker::changeLanguage(const QString &lang)
159 {
160  // this sets language only for current sentence
161  d->currentDict.setLanguage(lang);
162 }
163 
165 {
166  d->continueChecking();
167 }
168 
169 void BackgroundChecker::slotEngineDone()
170 {
172  const QString currentText = fetchMoreText();
173 
174  if (currentText.isNull()) {
175  Q_EMIT done();
176  } else {
177  d->mainTokenizer.setBuffer(currentText);
178  d->start();
179  }
180 }
181 
182 QString BackgroundChecker::text() const
183 {
184  return d->mainTokenizer.buffer();
185 }
186 
187 QString BackgroundChecker::currentContext() const
188 {
189  int len = 60;
190  // we don't want the expression underneath casted to an unsigned int
191  // which would cause it to always evaluate to false
192  int currentPosition = d->lastMisspelled.position() + d->sentenceOffset;
193  bool begin = ((currentPosition - len / 2) <= 0) ? true : false;
194 
195  QString buffer = d->mainTokenizer.buffer();
196  buffer.replace(currentPosition, d->lastMisspelled.length(), QStringLiteral("<b>%1</b>").arg(d->lastMisspelled.toString()));
197 
198  QString context;
199  if (begin) {
200  context = QStringLiteral("%1...").arg(buffer.mid(0, len));
201  } else {
202  context = QStringLiteral("...%1...").arg(buffer.mid(currentPosition - 20, len));
203  }
204 
205  context.replace(QLatin1Char('\n'), QLatin1Char(' '));
206 
207  return context;
208 }
209 
210 void Sonnet::BackgroundChecker::replace(int start, const QString &oldText, const QString &newText)
211 {
212  // FIXME: here we assume that replacement is in current fragment. So 'words' has
213  // to be adjusted and sentenceOffset does not
214  d->words.replace(start - (d->sentenceOffset), oldText.length(), newText);
215  d->mainTokenizer.replace(start, oldText.length(), newText);
216 }
bool autoDetectLanguageDisabled() const
Returns whether the automatic language detection is disabled, overriding the Sonnet settings.
bool isNull() const const
Q_EMITQ_EMIT
Q_SCRIPTABLE Q_NOREPLY void start()
void done()
Emitted after the whole text has been spell checked.
const QList< QKeySequence > & begin()
class used for actual spell checking
Definition: speller.h:25
int length() const const
QueuedConnection
bool addWordToSession(const QString &word)
This method is used to add a word to the session of the speller currently set in BackgroundChecker.
void setText(const QString &text)
This method is used to spell check static text.
QString & replace(int position, int n, QChar after)
The sonnet namespace.
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
virtual void finishedCurrentFeed()
This function will be called whenever the background checker will be finished text which it got from ...
virtual void continueChecking()
After emitting misspelling signal the background checker stops.
QString mid(int position, int n) const const
virtual QString fetchMoreText()
This function is called to get the text to spell check.
void setAutoDetectLanguageDisabled(bool autoDetectDisabled)
Sets whether to disable the automatic language detection.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sun Sep 25 2022 04:14:52 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.