Sonnet

backgroundchecker.cpp
1/*
2 * backgroundchecker.cpp
3 *
4 * SPDX-FileCopyrightText: 2004 Zack Rusin <zack@kde.org>
5 * SPDX-FileCopyrightText: 2009 Jakub Stachowski <qbast@go2.pl>
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
14using namespace Sonnet;
15
16void BackgroundCheckerPrivate::start()
17{
18 sentenceOffset = -1;
19 continueChecking();
20}
21
22void BackgroundCheckerPrivate::continueChecking()
23{
24 metaObject()->invokeMethod(this, "checkNext", Qt::QueuedConnection);
25}
26
27void 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
67BackgroundChecker::BackgroundChecker(QObject *parent)
68 : QObject(parent)
69 , d(new BackgroundCheckerPrivate)
70{
71 connect(d.get(), &BackgroundCheckerPrivate::misspelling, this, &BackgroundChecker::misspelling);
72 connect(d.get(), &BackgroundCheckerPrivate::done, this, &BackgroundChecker::slotEngineDone);
73}
74
75BackgroundChecker::BackgroundChecker(const Speller &speller, QObject *parent)
76 : QObject(parent)
77 , d(new BackgroundCheckerPrivate)
78{
79 d->currentDict = speller;
80 connect(d.get(), &BackgroundCheckerPrivate::misspelling, this, &BackgroundChecker::misspelling);
81 connect(d.get(), &BackgroundCheckerPrivate::done, this, &BackgroundChecker::slotEngineDone);
82}
83
84BackgroundChecker::~BackgroundChecker() = default;
85
87{
88 d->mainTokenizer.setBuffer(text);
89 d->start();
90}
91
92void BackgroundChecker::start()
93{
94 // ## what if d->currentText.isEmpty()?
95
96 // TODO: carry state from last buffer
97 d->mainTokenizer.setBuffer(fetchMoreText());
98 d->start();
99}
100
101void BackgroundChecker::stop()
102{
103 // d->stop();
104}
105
110
114
116{
117 return d->autoDetectLanguageDisabled;
118}
119
121{
122 d->autoDetectLanguageDisabled = autoDetectDisabled;
123}
124
125void BackgroundChecker::setSpeller(const Speller &speller)
126{
127 d->currentDict = speller;
128}
129
130Speller BackgroundChecker::speller() const
131{
132 return d->currentDict;
133}
134
135bool BackgroundChecker::checkWord(const QString &word)
136{
137 return d->currentDict.isCorrect(word);
138}
139
140bool BackgroundChecker::addWordToPersonal(const QString &word)
141{
142 return d->currentDict.addToPersonal(word);
143}
144
146{
147 return d->currentDict.addToSession(word);
148}
149
150QStringList BackgroundChecker::suggest(const QString &word) const
151{
152 return d->currentDict.suggest(word);
153}
154
155void BackgroundChecker::changeLanguage(const QString &lang)
156{
157 // this sets language only for current sentence
158 d->currentDict.setLanguage(lang);
159}
160
162{
163 d->continueChecking();
164}
165
166void BackgroundChecker::slotEngineDone()
167{
169 const QString currentText = fetchMoreText();
170
171 if (currentText.isNull()) {
172 Q_EMIT done();
173 } else {
174 d->mainTokenizer.setBuffer(currentText);
175 d->start();
176 }
177}
178
179QString BackgroundChecker::text() const
180{
181 return d->mainTokenizer.buffer();
182}
183
184QString BackgroundChecker::currentContext() const
185{
186 int len = 60;
187 // we don't want the expression underneath casted to an unsigned int
188 // which would cause it to always evaluate to false
189 int currentPosition = d->lastMisspelled.position() + d->sentenceOffset;
190 bool begin = ((currentPosition - len / 2) <= 0) ? true : false;
191
192 QString buffer = d->mainTokenizer.buffer();
193 buffer.replace(currentPosition, d->lastMisspelled.length(), QStringLiteral("<b>%1</b>").arg(d->lastMisspelled.toString()));
194
195 QString context;
196 if (begin) {
197 context = QStringLiteral("%1...").arg(buffer.mid(0, len));
198 } else {
199 context = QStringLiteral("...%1...").arg(buffer.mid(currentPosition - 20, len));
200 }
201
202 context.replace(QLatin1Char('\n'), QLatin1Char(' '));
203
204 return context;
205}
206
207void Sonnet::BackgroundChecker::replace(int start, const QString &oldText, const QString &newText)
208{
209 // FIXME: here we assume that replacement is in current fragment. So 'words' has
210 // to be adjusted and sentenceOffset does not
211 d->words.replace(start - (d->sentenceOffset), oldText.length(), newText);
212 d->mainTokenizer.replace(start, oldText.length(), newText);
213}
214
215#include "moc_backgroundchecker.cpp"
216#include "moc_backgroundchecker_p.cpp"
virtual void finishedCurrentFeed()
This function will be called whenever the background checker will be finished text which it got from ...
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.
void misspelling(const QString &word, int start)
Emitted whenever a misspelled word is found.
void done()
Emitted after the whole text has been spell checked.
bool autoDetectLanguageDisabled() const
Returns whether the automatic language detection is disabled, overriding the Sonnet settings.
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.
virtual void continueChecking()
After emitting misspelling signal the background checker stops.
Spell checker object.
Q_SCRIPTABLE Q_NOREPLY void start()
const QList< QKeySequence > & begin()
The sonnet namespace.
Q_EMITQ_EMIT
QString arg(Args &&... args) const const
bool isNull() const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QueuedConnection
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 11:48:53 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.