1/*
2 * SPDX-FileCopyrightText: 2020 Benjamin Port <benjamin.port@enioka.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6#include "settingsimpl_p.h"
7
8#include <QLocale>
9
10#include "loader_p.h"
11#include "settings.h"
12#include <QDebug>
13#include <speller.h>
14
15namespace Sonnet
16{
17class DictionaryModel : public QAbstractListModel
18{
19 Q_OBJECT
20public:
21 explicit DictionaryModel(QObject *parent = nullptr)
22 : QAbstractListModel(parent)
23 {
24 reload();
25 }
26
27 ~DictionaryModel() override
28 {
29 }
30
31 void reload()
32 {
33 beginResetModel();
34 Sonnet::Speller speller;
35 m_preferredDictionaries = speller.preferredDictionaries();
36 m_availableDictionaries = speller.availableDictionaries();
37 endResetModel();
38 }
39
40 void setDefaultLanguage(const QString &language)
41 {
42 m_defaultDictionary = language;
43 Q_EMIT dataChanged(topLeft: index(row: 0, column: 0), bottomRight: index(row: rowCount(parent: QModelIndex()) - 1, column: 0), roles: {Settings::DefaultRole});
44 }
45
46 bool setData(const QModelIndex &idx, const QVariant &value, int role = Qt::EditRole) override
47 {
48 Q_UNUSED(value)
49
50 if (!checkIndex(index: idx) || role != Qt::CheckStateRole) {
51 return false;
52 }
53 const int row = idx.row();
54 const auto language = m_availableDictionaries.keys().at(i: row);
55 const auto inPreferredDictionaries = m_preferredDictionaries.contains(key: m_availableDictionaries.keys().at(i: row));
56
57 if (inPreferredDictionaries) {
58 m_preferredDictionaries.remove(key: language);
59 } else {
60 m_preferredDictionaries[language] = m_availableDictionaries.values().at(i: row);
61 }
62 qobject_cast<Settings *>(object: parent())->setPreferredLanguages(m_preferredDictionaries.values());
63 Q_EMIT dataChanged(topLeft: index(row, column: 0), bottomRight: index(row, column: 0), roles: {Qt::CheckStateRole});
64 return true;
65 }
66
67 QVariant data(const QModelIndex &index, int role) const override
68 {
69 if (!checkIndex(index)) {
70 return {};
71 }
72 const int row = index.row();
73
74 switch (role) {
75 case Qt::DisplayRole:
76 return m_availableDictionaries.keys().at(i: row);
77 case Settings::LanguageCodeRole:
78 return m_availableDictionaries.values().at(i: row);
79 case Qt::CheckStateRole:
80 return m_preferredDictionaries.contains(key: m_availableDictionaries.keys().at(i: row));
81 case Settings::DefaultRole:
82 return data(index, role: Settings::LanguageCodeRole) == m_defaultDictionary;
83 }
84 return {};
85 }
86
87 int rowCount(const QModelIndex &parent) const override
88 {
89 Q_UNUSED(parent)
90 return m_availableDictionaries.count();
91 }
92
93 QHash<int, QByteArray> roleNames() const override
94 {
95 return {
96 {Qt::DisplayRole, QByteArrayLiteral("display")},
97 {Qt::CheckStateRole, QByteArrayLiteral("checked")},
98 {Settings::PreferredRole, QByteArrayLiteral("isPreferred")},
99 {Settings::LanguageCodeRole, QByteArrayLiteral("languageCode")},
100 {Settings::DefaultRole, QByteArrayLiteral("isDefault")},
101 };
102 }
103
104private:
105 QMap<QString, QString> m_preferredDictionaries;
106 QMap<QString, QString> m_availableDictionaries;
107 QString m_defaultDictionary;
108};
109
110class SettingsPrivate
111{
112public:
113 Loader *loader = nullptr;
114 DictionaryModel *dictionaryModel = nullptr;
115};
116
117Settings::Settings(QObject *parent)
118 : QObject(parent)
119 , d(new SettingsPrivate)
120{
121 d->loader = Loader::openLoader();
122}
123
124Settings::~Settings() = default;
125
126void Settings::setDefaultLanguage(const QString &lang)
127{
128 if (defaultLanguage() == lang) {
129 return;
130 }
131 d->loader->settings()->setDefaultLanguage(lang);
132 Q_EMIT defaultLanguageChanged();
133 Q_EMIT modifiedChanged();
134
135 if (d->dictionaryModel) {
136 d->dictionaryModel->setDefaultLanguage(lang);
137 }
138}
139
140QString Settings::defaultLanguage() const
141{
142 return d->loader->settings()->defaultLanguage();
143}
144
145void Settings::setPreferredLanguages(const QStringList &lang)
146{
147 if (!d->loader->settings()->setPreferredLanguages(lang)) {
148 return;
149 }
150 Q_EMIT modifiedChanged();
151 Q_EMIT preferredLanguagesChanged();
152}
153
154QStringList Settings::preferredLanguages() const
155{
156 return d->loader->settings()->preferredLanguages();
157}
158
159void Settings::setDefaultClient(const QString &client)
160{
161 if (!d->loader->settings()->setDefaultClient(client)) {
162 return;
163 }
164 Q_EMIT defaultClientChanged();
165 Q_EMIT modifiedChanged();
166}
167
168QString Settings::defaultClient() const
169{
170 return d->loader->settings()->defaultClient();
171}
172
173void Settings::setSkipUppercase(bool skip)
174{
175 if (!d->loader->settings()->setCheckUppercase(!skip)) {
176 return;
177 }
178 Q_EMIT skipUppercaseChanged();
179 Q_EMIT modifiedChanged();
180}
181
182bool Settings::skipUppercase() const
183{
184 return !d->loader->settings()->checkUppercase();
185}
186
187void Settings::setAutodetectLanguage(bool detect)
188{
189 if (!d->loader->settings()->setAutodetectLanguage(detect)) {
190 return;
191 }
192 Q_EMIT autodetectLanguageChanged();
193 Q_EMIT modifiedChanged();
194}
195
196bool Settings::autodetectLanguage() const
197{
198 return d->loader->settings()->autodetectLanguage();
199}
200
201void Settings::setSkipRunTogether(bool skip)
202{
203 if (skipRunTogether() == skip) {
204 return;
205 }
206 d->loader->settings()->setSkipRunTogether(skip);
207 Q_EMIT skipRunTogetherChanged();
208 Q_EMIT modifiedChanged();
209}
210
211bool Settings::skipRunTogether() const
212{
213 return d->loader->settings()->skipRunTogether();
214}
215
216void Settings::setCheckerEnabledByDefault(bool check)
217{
218 if (checkerEnabledByDefault() == check) {
219 return;
220 }
221 d->loader->settings()->setCheckerEnabledByDefault(check);
222 Q_EMIT checkerEnabledByDefaultChanged();
223 Q_EMIT modifiedChanged();
224}
225
226bool Settings::checkerEnabledByDefault() const
227{
228 return d->loader->settings()->checkerEnabledByDefault();
229}
230
231void Settings::setBackgroundCheckerEnabled(bool enable)
232{
233 if (backgroundCheckerEnabled() == enable) {
234 return;
235 }
236 d->loader->settings()->setBackgroundCheckerEnabled(enable);
237 Q_EMIT backgroundCheckerEnabledChanged();
238 Q_EMIT modifiedChanged();
239}
240
241bool Settings::backgroundCheckerEnabled() const
242{
243 return d->loader->settings()->backgroundCheckerEnabled();
244}
245
246void Settings::setCurrentIgnoreList(const QStringList &ignores)
247{
248 if (currentIgnoreList() == ignores) {
249 return;
250 }
251 d->loader->settings()->setCurrentIgnoreList(ignores);
252 Q_EMIT currentIgnoreListChanged();
253 Q_EMIT modifiedChanged();
254}
255
256QStringList Settings::currentIgnoreList() const
257{
258 return d->loader->settings()->currentIgnoreList();
259}
260
261QStringList Settings::clients() const
262{
263 return d->loader->clients();
264}
265
266void Settings::save()
267{
268 d->loader->settings()->save();
269 Q_EMIT modifiedChanged();
270}
271
272bool Settings::modified() const
273{
274 return d->loader->settings()->modified();
275}
276
277// default values
278// A static list of KDE specific words that we want to recognize
279QStringList Settings::defaultIgnoreList()
280{
281 QStringList l;
282 l.append(QStringLiteral("KMail"));
283 l.append(QStringLiteral("KOrganizer"));
284 l.append(QStringLiteral("KAddressBook"));
285 l.append(QStringLiteral("KHTML"));
286 l.append(QStringLiteral("KIO"));
287 l.append(QStringLiteral("KJS"));
288 l.append(QStringLiteral("Konqueror"));
289 l.append(QStringLiteral("Sonnet"));
290 l.append(QStringLiteral("Kontact"));
291 l.append(QStringLiteral("Qt"));
292 l.append(QStringLiteral("Okular"));
293 l.append(QStringLiteral("KMix"));
294 l.append(QStringLiteral("Amarok"));
295 l.append(QStringLiteral("KDevelop"));
296 l.append(QStringLiteral("Nepomuk"));
297 return l;
298}
299
300bool Settings::defaultSkipUppercase()
301{
302 return false;
303}
304
305bool Settings::defaultAutodetectLanguage()
306{
307 return true;
308}
309
310bool Settings::defaultBackgroundCheckerEnabled()
311{
312 return true;
313}
314
315bool Settings::defaultCheckerEnabledByDefault()
316{
317 return false;
318}
319
320bool Settings::defauktSkipRunTogether()
321{
322 return true;
323}
324
325QString Settings::defaultDefaultLanguage()
326{
327 return QLocale::system().name();
328}
329
330QStringList Settings::defaultPreferredLanguages()
331{
332 return QStringList();
333}
334
335QAbstractListModel *Settings::dictionaryModel()
336{
337 // Lazy loading
338 if (d->dictionaryModel) {
339 return d->dictionaryModel;
340 }
341
342 d->dictionaryModel = new DictionaryModel(this);
343 d->dictionaryModel->setDefaultLanguage(defaultLanguage());
344 return d->dictionaryModel;
345}
346}
347
348#include "moc_settings.cpp"
349#include "settings.moc"
350

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