Changeset View
Changeset View
Standalone View
Standalone View
runners/spellchecker/spellcheck.cpp
Show All 22 Lines | |||||
23 | #include <QDebug> | 23 | #include <QDebug> | ||
24 | #include <QLocale> | 24 | #include <QLocale> | ||
25 | #include <QSet> | 25 | #include <QSet> | ||
26 | #include <QIcon> | 26 | #include <QIcon> | ||
27 | #include <QMimeData> | 27 | #include <QMimeData> | ||
28 | 28 | | |||
29 | #include <KLocalizedString> | 29 | #include <KLocalizedString> | ||
30 | 30 | | |||
31 | namespace { | | |||
32 | namespace ActionIds { | | |||
33 | inline QString copyToClipboard() { return QStringLiteral("copyToClipboard"); } | | |||
34 | } | | |||
35 | } | | |||
36 | | ||||
37 | SpellCheckRunner::SpellCheckRunner(QObject* parent, const QVariantList &args) | 31 | SpellCheckRunner::SpellCheckRunner(QObject* parent, const QVariantList &args) | ||
38 | : Plasma::AbstractRunner(parent, args) | 32 | : Plasma::AbstractRunner(parent, args) | ||
39 | { | 33 | { | ||
40 | Q_UNUSED(args) | 34 | Q_UNUSED(args) | ||
41 | setObjectName(QLatin1String( "Spell Checker" )); | 35 | setObjectName(QStringLiteral("Spell Checker")); | ||
42 | setIgnoredTypes(Plasma::RunnerContext::FileSystem | Plasma::RunnerContext::NetworkLocation); | 36 | setIgnoredTypes(Plasma::RunnerContext::FileSystem | Plasma::RunnerContext::NetworkLocation); | ||
43 | setSpeed(AbstractRunner::SlowSpeed); | 37 | setSpeed(AbstractRunner::SlowSpeed); | ||
44 | | ||||
45 | addAction(ActionIds::copyToClipboard(), QIcon::fromTheme(QStringLiteral("edit-copy")), i18nc("@action", "Copy to Clipboard")); | | |||
46 | } | 38 | } | ||
47 | 39 | | |||
48 | SpellCheckRunner::~SpellCheckRunner() | 40 | SpellCheckRunner::~SpellCheckRunner() = default; | ||
49 | { | | |||
50 | } | | |||
51 | 41 | | |||
52 | void SpellCheckRunner::init() | 42 | void SpellCheckRunner::init() | ||
53 | { | 43 | { | ||
54 | Plasma::AbstractRunner::init(); | 44 | m_actions = {addAction(QStringLiteral("copyToClipboard"), | ||
45 | QIcon::fromTheme(QStringLiteral("edit-copy")), | ||||
46 | i18nc("@action", "Copy to Clipboard"))}; | ||||
55 | 47 | | |||
56 | //Connect prepare and teardown signals | 48 | //Connect prepare and teardown signals | ||
57 | connect(this, SIGNAL(prepare()), this, SLOT(loaddata())); | 49 | connect(this, &SpellCheckRunner::prepare, this, &SpellCheckRunner::loadData); | ||
58 | connect(this, SIGNAL(teardown()), this, SLOT(destroydata())); | 50 | connect(this, &SpellCheckRunner::teardown, this, &SpellCheckRunner::destroydata); | ||
51 | | ||||
52 | reloadConfiguration(); | ||||
59 | } | 53 | } | ||
60 | 54 | | |||
61 | //Load a default dictionary and some locale names | 55 | //Load a default dictionary and some locale names | ||
62 | void SpellCheckRunner::loaddata() | 56 | void SpellCheckRunner::loadData() | ||
63 | { | 57 | { | ||
64 | //Load the default speller, with the default language | 58 | //Load the default speller, with the default language | ||
65 | auto defaultSpellerIt = m_spellers.find(QString()); | 59 | auto defaultSpellerIt = m_spellers.find(QString()); | ||
66 | if (defaultSpellerIt == m_spellers.end()) { | 60 | if (defaultSpellerIt == m_spellers.end()) { | ||
67 | defaultSpellerIt = m_spellers.insert(QString(), QSharedPointer<Sonnet::Speller> (new Sonnet::Speller(QString()))); | 61 | defaultSpellerIt = m_spellers.insert(QString(), QSharedPointer<Sonnet::Speller> (new Sonnet::Speller(QString()))); | ||
68 | } | 62 | } | ||
69 | auto& defaultSpeller = defaultSpellerIt.value(); | 63 | auto& defaultSpeller = defaultSpellerIt.value(); | ||
70 | 64 | | |||
71 | //store all language names, makes it possible to type "spell german TERM" if english locale is set | 65 | //store all language names, makes it possible to type "spell german TERM" if english locale is set | ||
72 | //Need to construct a map between natual language names and names the spell-check recognises. | 66 | //Need to construct a map between natual language names and names the spell-check recognises. | ||
73 | const QStringList avail = defaultSpeller->availableLanguages(); | 67 | const QStringList avail = defaultSpeller->availableLanguages(); | ||
74 | //We need to filter the available languages so that we associate the natural language | 68 | //We need to filter the available languages so that we associate the natural language | ||
75 | //name (eg. 'german') with one sub-code. | 69 | //name (eg. 'german') with one sub-code. | ||
76 | QSet<QString> families; | 70 | QSet<QString> families; | ||
77 | //First get the families | 71 | //First get the families | ||
78 | foreach (const QString &code, avail) { | 72 | for (const QString &code: avail) { | ||
79 | families +=code.left(2); | 73 | families +=code.left(2); | ||
80 | } | 74 | } | ||
81 | //Now for each family figure out which is the main code. | 75 | //Now for each family figure out which is the main code. | ||
82 | foreach (const QString &fcode,families) { | 76 | for (const QString &fcode: qAsConst(families)) { | ||
83 | QStringList family = avail.filter(fcode); | 77 | const QStringList family = avail.filter(fcode); | ||
84 | QString code; | 78 | QString code; | ||
85 | //If we only have one code, use it. | 79 | //If we only have one code, use it. | ||
86 | //If a string is the default language, use it | 80 | //If a string is the default language, use it | ||
87 | if (family.contains(defaultSpeller->language())) { | 81 | if (family.contains(defaultSpeller->language())) { | ||
88 | code = defaultSpeller->language(); | 82 | code = defaultSpeller->language(); | ||
89 | } else if (fcode == QLatin1String("en")) { | 83 | } else if (fcode == QLatin1String("en")) { | ||
90 | //If the family is english, default to en_US. | 84 | //If the family is english, default to en_US. | ||
91 | const auto enUS = QStringLiteral("en_US"); | 85 | const auto enUS = QStringLiteral("en_US"); | ||
Show All 9 Lines | 93 | } else { | |||
101 | code = family.first(); | 95 | code = family.first(); | ||
102 | } | 96 | } | ||
103 | //Finally, add code to the map. | 97 | //Finally, add code to the map. | ||
104 | // FIXME: We need someway to map languageCodeToName | 98 | // FIXME: We need someway to map languageCodeToName | ||
105 | const QString name;// = locale->languageCodeToName(fcode); | 99 | const QString name;// = locale->languageCodeToName(fcode); | ||
106 | if (!name.isEmpty()) { | 100 | if (!name.isEmpty()) { | ||
107 | m_languages[name.toLower()] = code; | 101 | m_languages[name.toLower()] = code; | ||
108 | } | 102 | } | ||
109 | // kDebug() << "SPELL lang: " << fcode<< "::"<< name << " : " << code; | | |||
110 | } | 103 | } | ||
111 | 104 | | |||
112 | } | 105 | } | ||
113 | 106 | | |||
114 | void SpellCheckRunner::destroydata() | 107 | void SpellCheckRunner::destroydata() | ||
115 | { | 108 | { | ||
116 | //Clear the data arrays to save memory | 109 | //Clear the data arrays to save memory | ||
117 | m_spellers.clear(); | 110 | m_spellers.clear(); | ||
118 | } | 111 | } | ||
119 | 112 | | |||
120 | void SpellCheckRunner::reloadConfiguration() | 113 | void SpellCheckRunner::reloadConfiguration() | ||
121 | { | 114 | { | ||
122 | m_triggerWord = config().readEntry("trigger", i18n("spell")); | 115 | const KConfigGroup cfg = config(); | ||
116 | m_triggerWord = cfg.readEntry("trigger", i18n("spell")); | ||||
123 | //Processing will be triggered by "keyword " | 117 | //Processing will be triggered by "keyword " | ||
118 | m_requireTriggerWord = cfg.readEntry("requireTriggerWord", true) && !m_triggerWord.isEmpty(); | ||||
124 | m_triggerWord += QLatin1Char( ' ' ); | 119 | m_triggerWord += QLatin1Char( ' ' ); | ||
125 | 120 | | |||
126 | m_requireTriggerWord = config().readEntry("requireTriggerWord", true); | | |||
127 | | ||||
128 | Plasma::RunnerSyntax s(i18nc("Spelling checking runner syntax, first word is trigger word, e.g. \"spell\".", | 121 | Plasma::RunnerSyntax s(i18nc("Spelling checking runner syntax, first word is trigger word, e.g. \"spell\".", | ||
129 | "%1:q:", m_triggerWord), | 122 | "%1:q:", m_triggerWord), i18n("Checks the spelling of :q:.")); | ||
130 | i18n("Checks the spelling of :q:.")); | | |||
131 | 123 | | |||
132 | if (!m_requireTriggerWord) { | 124 | if (!m_requireTriggerWord) { | ||
133 | s.addExampleQuery(QLatin1String( ":q:" )); | 125 | s.addExampleQuery(QStringLiteral(":q:")); | ||
134 | } | 126 | } | ||
135 | 127 | | |||
136 | QList<Plasma::RunnerSyntax> syns; | 128 | setSyntaxes({s}); | ||
137 | syns << s; | | |||
138 | setSyntaxes(syns); | | |||
139 | } | 129 | } | ||
140 | 130 | | |||
141 | /* Take the input query, split into a list, and see if it contains a language to spell in. | 131 | /* Take the input query, split into a list, and see if it contains a language to spell in. | ||
142 | * Return the empty string if we can't match a language. */ | 132 | * Return the empty string if we can't match a language. */ | ||
143 | QString SpellCheckRunner::findlang(const QStringList& terms) | 133 | QString SpellCheckRunner::findLang(const QStringList& terms) | ||
144 | { | 134 | { | ||
145 | auto defaultSpeller = m_spellers[QString()]; | 135 | const auto &defaultSpeller = m_spellers[QString()]; | ||
davidedmundson: Const auto &
| |||||
146 | //If first term is a language code (like en_GB), set it as the spell-check language | 136 | //If first term is a language code (like en_GB), set it as the spell-check language | ||
147 | if (terms.count() >= 1 && defaultSpeller->availableLanguages().contains(terms[0])) { | 137 | if (!terms.isEmpty() && defaultSpeller->availableLanguages().contains(terms[0])) { | ||
148 | return terms[0]; | 138 | return terms[0]; | ||
149 | } | 139 | } | ||
150 | //If we have two terms and the first is a language name (eg 'french'), | 140 | //If we have two terms and the first is a language name (eg 'french'), | ||
151 | //set it as the available language | 141 | //set it as the available language | ||
152 | else if (terms.count() >=2) { | 142 | else if (terms.count() >=2) { | ||
153 | QString code; | 143 | QString code; | ||
154 | { | 144 | { | ||
155 | //Is this a descriptive language name? | 145 | //Is this a descriptive language name? | ||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | 173 | { | |||
200 | QSharedPointer<Sonnet::Speller> speller = m_spellers[QString()]; | 190 | QSharedPointer<Sonnet::Speller> speller = m_spellers[QString()]; | ||
201 | 191 | | |||
202 | if (speller->isValid()) { | 192 | if (speller->isValid()) { | ||
203 | #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) | 193 | #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) | ||
204 | QStringList terms = query.split(QLatin1Char(' '), QString::SkipEmptyParts); | 194 | QStringList terms = query.split(QLatin1Char(' '), QString::SkipEmptyParts); | ||
205 | #else | 195 | #else | ||
206 | QStringList terms = query.split(QLatin1Char(' '), Qt::SkipEmptyParts); | 196 | QStringList terms = query.split(QLatin1Char(' '), Qt::SkipEmptyParts); | ||
207 | #endif | 197 | #endif | ||
208 | QString lang = findlang(terms); | 198 | const QString lang = findlang(terms); | ||
209 | //If we found a language, create a new speller object using it. | 199 | //If we found a language, create a new speller object using it. | ||
210 | if (!lang.isEmpty()) { | 200 | if (!lang.isEmpty()) { | ||
211 | //First term is the language | 201 | //First term is the language | ||
212 | terms.removeFirst(); | 202 | terms.removeFirst(); | ||
213 | //New speller object if we don't already have one | 203 | //New speller object if we don't already have one | ||
214 | if (!m_spellers.contains(lang)) { | 204 | if (!m_spellers.contains(lang)) { | ||
215 | QMutexLocker lock (&m_spellLock); | 205 | QMutexLocker lock (&m_spellLock); | ||
216 | //Check nothing happened while we were acquiring the lock | 206 | //Check nothing happened while we were acquiring the lock | ||
217 | if (!m_spellers.contains(lang)) { | 207 | if (!m_spellers.contains(lang)) { | ||
218 | m_spellers[lang] = QSharedPointer<Sonnet::Speller>(new Sonnet::Speller(lang)); | 208 | m_spellers[lang] = QSharedPointer<Sonnet::Speller>(new Sonnet::Speller(lang)); | ||
219 | } | 209 | } | ||
220 | } | 210 | } | ||
221 | speller = m_spellers[lang]; | 211 | speller = m_spellers[lang]; | ||
222 | //Rejoin the strings | 212 | //Rejoin the strings | ||
223 | query = terms.join(QLatin1String(" ")); | 213 | query = terms.join(QLatin1Char(' ')); | ||
224 | } | 214 | } | ||
225 | } | 215 | } | ||
226 | 216 | | |||
227 | if (query.size() < 2) { | 217 | if (query.size() < 2) { | ||
228 | return; | 218 | return; | ||
229 | } | 219 | } | ||
230 | 220 | | |||
231 | if (speller->isValid()) { | 221 | if (speller->isValid()) { | ||
Show All 25 Lines | 243 | } else { | |||
257 | match.setText(i18n("Could not find a dictionary.")); | 247 | match.setText(i18n("Could not find a dictionary.")); | ||
258 | context.addMatch(match); | 248 | context.addMatch(match); | ||
259 | } | 249 | } | ||
260 | } | 250 | } | ||
261 | 251 | | |||
262 | void SpellCheckRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) | 252 | void SpellCheckRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) | ||
263 | { | 253 | { | ||
264 | Q_UNUSED(context) | 254 | Q_UNUSED(context) | ||
265 | if (match.selectedAction() == action(ActionIds::copyToClipboard())) { | 255 | | ||
266 | //Copy words to clipboard | 256 | QGuiApplication::clipboard()->setText(match.data().toString()); | ||
267 | const QString text = match.data().toString(); | | |||
268 | QGuiApplication::clipboard()->setText(text); | | |||
269 | } | | |||
270 | } | 257 | } | ||
271 | 258 | | |||
272 | QList<QAction *> SpellCheckRunner::actionsForMatch(const Plasma::QueryMatch &match) | 259 | QList<QAction *> SpellCheckRunner::actionsForMatch(const Plasma::QueryMatch &match) | ||
273 | { | 260 | { | ||
274 | Q_UNUSED(match) | 261 | Q_UNUSED(match) | ||
275 | 262 | | |||
276 | return {action(ActionIds::copyToClipboard())}; | 263 | return m_actions; | ||
277 | } | 264 | } | ||
278 | 265 | | |||
279 | QMimeData * SpellCheckRunner::mimeDataForMatch(const Plasma::QueryMatch &match) | 266 | QMimeData * SpellCheckRunner::mimeDataForMatch(const Plasma::QueryMatch &match) | ||
280 | { | 267 | { | ||
281 | QMimeData *result = new QMimeData(); | 268 | QMimeData *result = new QMimeData(); | ||
282 | const QString text = match.data().toString(); | 269 | const QString text = match.data().toString(); | ||
283 | result->setText(text); | 270 | result->setText(text); | ||
284 | return result; | 271 | return result; | ||
285 | } | 272 | } | ||
286 | 273 | | |||
287 | K_EXPORT_PLASMA_RUNNER(krunner_spellcheck, SpellCheckRunner) | 274 | K_EXPORT_PLASMA_RUNNER(krunner_spellcheck, SpellCheckRunner) | ||
288 | 275 | | |||
289 | #include "spellcheck.moc" | 276 | #include "spellcheck.moc" |
Const auto &