1/*
2 * SPDX-FileCopyrightText: 2007 Zack Rusin <zack@kde.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6#include "speller.h"
7
8#include "loader_p.h"
9#include "settingsimpl_p.h"
10#include "spellerplugin_p.h"
11
12#include "core_debug.h"
13
14#include <QCache>
15
16namespace Sonnet
17{
18class SpellerPrivate
19{
20public:
21 SpellerPrivate()
22 {
23 }
24
25 ~SpellerPrivate()
26 {
27 }
28
29 void init(const QString &lang)
30 {
31 Loader *loader = Loader::openLoader();
32 settings = loader->settings();
33
34 language = lang;
35 updateDict();
36 }
37
38 void updateDict()
39 {
40 dict = Loader::openLoader()->cachedSpeller(language);
41 }
42
43 bool isValid()
44 {
45 if (settings->modified()) {
46 recreateDict();
47 settings->setModified(false);
48 }
49 return !dict.isNull();
50 }
51
52 void recreateDict()
53 {
54 Loader::openLoader()->clearSpellerCache();
55 updateDict();
56 }
57
58 QSharedPointer<SpellerPlugin> dict;
59 SettingsImpl *settings = nullptr;
60 QString language;
61};
62
63Speller::Speller(const QString &lang)
64 : d(new SpellerPrivate)
65{
66 d->init(lang);
67}
68
69Speller::~Speller()
70{
71 qCDebug(SONNET_LOG_CORE) << "deleting" << this << "for" << d->language;
72}
73
74Speller::Speller(const Speller &speller)
75 : d(new SpellerPrivate)
76{
77 d->language = speller.language();
78 d->init(lang: d->language);
79}
80
81Speller &Speller::operator=(const Speller &speller)
82{
83 d->language = speller.language();
84 d->updateDict();
85 return *this;
86}
87
88bool Speller::isCorrect(const QString &word) const
89{
90 if (!d->isValid()) {
91 return true;
92 }
93 return d->dict->isCorrect(word);
94}
95
96bool Speller::isMisspelled(const QString &word) const
97{
98 if (!d->isValid()) {
99 return false;
100 }
101 return d->dict->isMisspelled(word);
102}
103
104QStringList Speller::suggest(const QString &word) const
105{
106 if (!d->isValid()) {
107 return QStringList();
108 }
109 return d->dict->suggest(word);
110}
111
112bool Speller::checkAndSuggest(const QString &word, QStringList &suggestions) const
113{
114 if (!d->isValid()) {
115 return true;
116 }
117 return d->dict->checkAndSuggest(word, suggestions);
118}
119
120bool Speller::storeReplacement(const QString &bad, const QString &good)
121{
122 if (!d->isValid()) {
123 return false;
124 }
125 return d->dict->storeReplacement(bad, good);
126}
127
128bool Speller::addToPersonal(const QString &word)
129{
130 if (!d->isValid()) {
131 return false;
132 }
133 return d->dict->addToPersonal(word);
134}
135
136bool Speller::addToSession(const QString &word)
137{
138 if (!d->isValid()) {
139 return false;
140 }
141 return d->dict->addToSession(word);
142}
143
144QString Speller::language() const
145{
146 if (!d->isValid()) {
147 return QString();
148 }
149 return d->dict->language();
150}
151
152void Speller::save()
153{
154 if (d->settings) {
155 d->settings->save();
156 }
157}
158
159void Speller::restore()
160{
161 if (d->settings) {
162 d->settings->restore();
163 d->recreateDict();
164 }
165}
166
167QStringList Speller::availableBackends() const
168{
169 Loader *l = Loader::openLoader();
170 return l->clients();
171}
172
173QStringList Speller::availableLanguages() const
174{
175 Loader *l = Loader::openLoader();
176 return l->languages();
177}
178
179QStringList Speller::availableLanguageNames() const
180{
181 Loader *l = Loader::openLoader();
182 return l->languageNames();
183}
184
185void Speller::setDefaultLanguage(const QString &lang)
186{
187 if (d->settings->setDefaultLanguage(lang)) {
188 d->settings->save();
189 }
190}
191
192QString Speller::defaultLanguage() const
193{
194 return d->settings->defaultLanguage();
195}
196
197void Speller::setDefaultClient(const QString &client)
198{
199 if (d->settings->setDefaultClient(client)) {
200 d->settings->save();
201 }
202}
203
204QString Speller::defaultClient() const
205{
206 return d->settings->defaultClient();
207}
208
209void Speller::setAttribute(Attribute attr, bool b)
210{
211 switch (attr) {
212 case CheckUppercase:
213 d->settings->setCheckUppercase(b);
214 break;
215 case SkipRunTogether:
216 d->settings->setSkipRunTogether(b);
217 break;
218 case AutoDetectLanguage:
219 d->settings->setAutodetectLanguage(b);
220 break;
221 }
222 d->settings->save();
223}
224
225bool Speller::testAttribute(Attribute attr) const
226{
227 switch (attr) {
228 case CheckUppercase:
229 return d->settings->checkUppercase();
230 case SkipRunTogether:
231 return d->settings->skipRunTogether();
232 case AutoDetectLanguage:
233 return d->settings->autodetectLanguage();
234 }
235 return false;
236}
237
238bool Speller::isValid() const
239{
240 return !d->dict.isNull();
241}
242
243void Speller::setLanguage(const QString &lang)
244{
245 d->language = lang;
246 d->updateDict();
247}
248
249QMap<QString, QString> Sonnet::Speller::availableDictionaries() const
250{
251 Loader *l = Loader::openLoader();
252 const QStringList lst = l->languages();
253 QMap<QString, QString> langs;
254
255 for (const QString &tag : lst) {
256 langs.insert(key: l->languageNameForCode(langCode: tag), value: tag);
257 }
258
259 return langs;
260}
261
262QMap<QString, QString> Speller::preferredDictionaries() const
263{
264 Loader *l = Loader::openLoader();
265 QMap<QString, QString> langs;
266
267 for (const QString &tag : l->settings()->preferredLanguages()) {
268 langs.insert(key: l->languageNameForCode(langCode: tag), value: tag);
269 }
270
271 return langs;
272}
273
274} // namespace Sonnet
275

source code of sonnet/src/core/speller.cpp