9#include "settingsimpl_p.h"
10#include "spellerplugin_p.h"
12#include "core_debug.h"
14#include <QCoreApplication>
20#include <QPluginLoader>
25#include "../plugins/hunspell/hunspellclient.h"
27#include "../plugins/nsspellchecker/nsspellcheckerclient.h"
36 SettingsImpl *settings;
48Q_GLOBAL_STATIC(Loader, s_loader)
50Loader *Loader::openLoader()
52 if (s_loader.isDestroyed()) {
60 : d(new LoaderPrivate)
62 d->settings =
new SettingsImpl(
this);
63 d->settings->restore();
69 qCDebug(SONNET_LOG_CORE) <<
"Removing loader: " <<
this;
71 d->settings =
nullptr;
74SpellerPlugin *Loader::createSpeller(
const QString &language,
const QString &clientName)
const
80 plang = d->settings->defaultLanguage();
83 auto clientsItr = d->languageClients.constFind(plang);
84 if (clientsItr == d->languageClients.constEnd()) {
85 if (language.
isEmpty() || language == QStringLiteral(
"C")) {
86 qCDebug(SONNET_LOG_CORE) <<
"No language dictionaries for the language:" << plang <<
"trying to load en_US as default";
87 return createSpeller(QStringLiteral(
"en_US"), clientName);
89 qCDebug(SONNET_LOG_CORE) <<
"No language dictionaries for the language:" << plang;
90 Q_EMIT loadingDictionaryFailed(plang);
97 backend = d->settings->defaultClient();
101 bool unknown = !std::any_of(lClients.
constBegin(), lClients.
constEnd(), [backend](
const Client *client) {
102 return client->name() == backend;
105 qCWarning(SONNET_LOG_CORE) <<
"Default client" << backend <<
"doesn't support language:" << plang;
112 while (itr.hasNext()) {
113 Client *item = itr.next();
115 if (backend == item->name()) {
116 SpellerPlugin *dict = item->createSpeller(plang);
117 qCDebug(SONNET_LOG_CORE) <<
"Using the" << item->name() <<
"plugin for language" << plang;
123 SpellerPlugin *dict = item->createSpeller(plang);
124 qCDebug(SONNET_LOG_CORE) <<
"Using the" << item->name() <<
"plugin for language" << plang;
129 qCWarning(SONNET_LOG_CORE) <<
"The default client" << backend <<
"has no language dictionaries for the language:" << plang;
135 auto &speller = d->spellerCache[language];
137 speller.reset(createSpeller(language));
142void Loader::clearSpellerCache()
144 d->spellerCache.clear();
154 return d->languageClients.keys();
159 QString currentDictionary = langCode;
168 int variantCount = 0;
170 struct variantListType {
171 const char *variantShortName;
172 const char *variantEnglishName;
181#undef QT_TRANSLATE_NOOP3
182#define QT_TRANSLATE_NOOP3(a, b, c) b
184 const variantListType variantList[] = {{
"40", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"40",
"dictionary variant")},
185 {
"60", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"60",
"dictionary variant")},
186 {
"80", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"80",
"dictionary variant")},
187 {
"ise", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"-ise suffixes",
"dictionary variant")},
188 {
"ize", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"-ize suffixes",
"dictionary variant")},
189 {
"ise-w_accents", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"-ise suffixes and with accents",
"dictionary variant")},
190 {
"ise-wo_accents", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"-ise suffixes and without accents",
"dictionary variant")},
191 {
"ize-w_accents", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"-ize suffixes and with accents",
"dictionary variant")},
192 {
"ize-wo_accents", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"-ize suffixes and without accents",
"dictionary variant")},
193 {
"lrg", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"large",
"dictionary variant")},
194 {
"med", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"medium",
"dictionary variant")},
195 {
"sml", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"small",
"dictionary variant")},
196 {
"variant_0", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"variant 0",
"dictionary variant")},
197 {
"variant_1", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"variant 1",
"dictionary variant")},
198 {
"variant_2", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"variant 2",
"dictionary variant")},
199 {
"wo_accents", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"without accents",
"dictionary variant")},
200 {
"w_accents", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"with accents",
"dictionary variant")},
201 {
"ye", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"with ye, modern russian",
"dictionary variant")},
202 {
"yeyo", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"with yeyo, modern and old russian",
"dictionary variant")},
203 {
"yo", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"with yo, old russian",
"dictionary variant")},
204 {
"extended", QT_TRANSLATE_NOOP3(
"Sonnet::Loader",
"extended",
"dictionary variant")},
208 if (minusPos != -1) {
209 variantName = currentDictionary.
right(currentDictionary.
length() - minusPos - 1);
210 while (variantList[variantCount].variantShortName !=
nullptr) {
211 if (
QLatin1String(variantList[variantCount].variantShortName) == variantName) {
217 if (variantList[variantCount].variantShortName !=
nullptr) {
218 variantEnglish = variantList[variantCount].variantEnglishName;
220 variantEnglish = variantName.
toLatin1();
223 localizedVariant = tr(variantEnglish.
constData(),
"dictionary variant");
224 isoCode = currentDictionary.
left(minusPos);
226 isoCode = currentDictionary;
230 localizedCountry = locale.nativeTerritoryName();
231 localizedLang = locale.nativeLanguageName();
238 return tr(
"%1 (%2) [%3]",
"dictionary name; %1 = language name, %2 = country name and %3 = language variant name")
239 .arg(localizedLang, localizedCountry, localizedVariant);
240 }
else if (!localizedCountry.
isEmpty()) {
241 return tr(
"%1 (%2)",
"dictionary name; %1 = language name, %2 = country name").arg(localizedLang, localizedCountry);
243 return localizedLang;
252 if (d->languagesNameCache.count() ==
languages().count()) {
253 return d->languagesNameCache;
258 allLocalizedDictionaries.
append(languageNameForCode(langCode));
261 d->languagesNameCache = allLocalizedDictionaries;
262 return allLocalizedDictionaries;
265SettingsImpl *Loader::settings()
const
270void Loader::loadPlugins()
274 const QString pathSuffix(QStringLiteral(
"/kf6/sonnet/"));
275 for (
const QString &libPath : libPaths) {
276 QDir dir(libPath + pathSuffix);
281 loadPlugin(
dir.absoluteFilePath(fileName));
285 if (d->loadedPlugins.isEmpty()) {
286 qCWarning(SONNET_LOG_CORE) <<
"Sonnet: No speller backends available!";
292 loadPlugin(QStringLiteral(
"Hunspell"));
296void Loader::loadPlugin(
const QString &pluginPath)
300 const QString pluginIID = plugin.metaData()[QStringLiteral(
"IID")].toString();
302 if (d->loadedPlugins.contains(pluginIID)) {
303 qCDebug(SONNET_LOG_CORE) <<
"Skipping already loaded" << pluginPath;
306 d->loadedPlugins.insert(pluginIID);
309 if (!plugin.load()) {
310 qCDebug(SONNET_LOG_CORE) <<
"Sonnet: Unable to load plugin" << pluginPath <<
"Error:" << plugin.errorString();
311 d->loadedPlugins.
remove(pluginIID);
315 Client *client = qobject_cast<Client *>(plugin.instance());
317 qCWarning(SONNET_LOG_CORE) <<
"Sonnet: Invalid plugin loaded" << pluginPath;
322 Client *client =
nullptr;
324 client =
new HunspellClient(
this);
328 client =
new NSSpellCheckerClient(
this);
334 d->clients.
append(client->name());
336 for (
const QString &language : languages) {
340 || client->reliability() < languageClients.
first()->reliability()) {
341 languageClients.
append(client);
343 languageClients.
prepend(client);
348void Loader::changed()
350 Q_EMIT configurationChanged();
354#include "moc_loader_p.cpp"
KIOCORE_EXPORT QString dir(const QString &fileClass)
KEDUVOCDOCUMENT_EXPORT QStringList languages()
const char * constData() const const
QStringList libraryPaths()
void append(QList< T > &&value)
const_iterator constBegin() const const
const_iterator constEnd() const const
bool isEmpty() const const
void prepend(parameter_type value)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString left(qsizetype n) const const
qsizetype length() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString right(qsizetype n) const const
QByteArray toLatin1() const const