Krita Source Code Documentation
Loading...
Searching...
No Matches
LocaleHandler.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2025 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6#include <QDebug>
7
9#include <KLocalizedString>
10#include <KConfigGroup>
11#include <KSharedConfig>
12
13#include "LocaleHandler.h"
14
15const QString localeName (const KoWritingSystemUtils::Bcp47Locale &locale) {
16 if (!locale.isValid()) return i18nc("Empty locale", "Empty");
17
18 QString name;
19 const QLocale l = KoWritingSystemUtils::localeFromBcp47Locale(locale);
20 const QString lang = QLocale::languageToString(l.language());
21#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
22 const QString region = QLocale::countryToString(l.country());
23#else
24 const QString region = QLocale::territoryToString(l.territory());
25#endif
26
27 if (!lang.isEmpty() && lang != "C") {
28 if (!locale.regionTag.isEmpty()) {
29 if (!locale.variantTags.isEmpty()) {
30 name = i18nc("language, region, variant", "%1, %2, variant: %3", lang, region, locale.variantTags.join("-"));
31 } else {
32 name = i18nc("language, variant", "%1, variant: %2", lang, region);
33 }
34 } else {
35 if (!locale.variantTags.isEmpty()) {
36 name = i18nc("language, variant", "%1, variant: %2", lang, locale.variantTags.join("-"));
37 } else {
38 name = lang;
39 }
40 }
41 } else {
42 name = locale.toString();
43 }
44
45 return name;
46}
47
49 Private(QObject *parent = nullptr) {
50 allLanguages = new AllLanguagesModel(parent);
52 filteredLanguagesModel->setSourceModel(allLanguages);
53 filteredLanguagesModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
54
55 favorites = new FavoriteLocaleModel(parent);
56 }
57
62};
63
65 : QObject(parent)
66 , d(new Private(parent))
67{
68
69}
70
75
77{
78 return d->locale.toString();
79}
80
81void LocaleHandler::setBcp47Tag(const QString &newBcp47Tag)
82{
83 if (d->locale.toString() == newBcp47Tag)
84 return;
85 d->locale = KoWritingSystemUtils::parseBcp47Locale(newBcp47Tag);
86
87
88 d->favorites->addCode(language());
89 emit bcp47TagChanged();
90 emit languageChanged();
91 emit scriptChanged();
92}
93
94QString LocaleHandler::script() const
95{
96 return d->locale.scriptTag;
97}
98
99void LocaleHandler::setScript(const QString &newScript)
100{
101 if (d->locale.scriptTag == newScript)
102 return;
103 d->locale.scriptTag = newScript;
104 emit scriptChanged();
105 emit bcp47TagChanged();
106}
107
109{
110 KoWritingSystemUtils::Bcp47Locale langOnly = d->locale;
111 langOnly.scriptTag.clear();
112 return langOnly.toString();
113}
114
115void LocaleHandler::setLanguage(const QString &newLanguage)
116{
117 KoWritingSystemUtils::Bcp47Locale langOnly = d->locale;
118 langOnly.scriptTag.clear();
119 if (langOnly.toString() == newLanguage)
120 return;
121
122 langOnly = KoWritingSystemUtils::parseBcp47Locale(newLanguage);
123 langOnly.scriptTag.clear();
124 if (!langOnly.isValid()) return;
125
126 d->favorites->addCode(langOnly.toString());
127
128 langOnly.scriptTag = d->locale.scriptTag;
129 d->locale = langOnly;
130
131 emit languageChanged();
132 emit bcp47TagChanged();
133}
134
135QVariantList LocaleHandler::scriptModel() const
136{
137 QVariantList model;
138 const QString code = "code";
139 const QString name = "name";
140
141 for (int i = 0; i< int(QLocale::LastScript); i++) {
142 const QLocale::Script script = QLocale::Script(i);
143 QVariantMap map;
145 map.insert(name, QLocale::scriptToString(script));
146 model.append(map);
147 }
148 return model;
149}
150
151QAbstractItemModel *LocaleHandler::languagesModel() const
152{
153 return d->filteredLanguagesModel;
154}
155
156QAbstractItemModel *LocaleHandler::favoritesModel() const
157{
158 return d->favorites;
159}
160
162{
163 return d->filteredLanguagesModel->filterRegularExpression().pattern();
164}
165
166void LocaleHandler::setSearchString(const QString &newSearchString)
167{
168 if (d->filteredLanguagesModel->filterRegularExpression().pattern() == newSearchString)
169 return;
170 d->filteredLanguagesModel->setFilterRegularExpression(newSearchString);
171 emit searchStringChanged();
172}
173
175{
176 return d->locale.isValid();
177}
178
179bool LocaleHandler::validBcp47Tag(const QString &tag) const
180{
182}
183
186 for (int i = 0; i < QLocale::LastLanguage; i++) {
187 const QLocale::Language lang = QLocale::Language(i);
188 const QString langName = QLocale(lang).bcp47Name();
189 if (!locales.contains(langName)) {
190 locales.append(langName);
191 }
192 Q_FOREACH(const QLocale::Country region, QLocale::countriesForLanguage(lang)) {
193 const QLocale locale(lang, region);
194 const QString bcp = locale.name().split("_").join("-");
195 if (!locales.contains(bcp)) {
196 locales.append(bcp);
197 }
198 }
199 }
200 }
201
203};
204
206 : QAbstractListModel(parent)
207 , d(new Private())
208{
209
210}
211
216
217int AllLanguagesModel::rowCount(const QModelIndex &parent) const
218{
219 Q_UNUSED(parent)
220 return d->locales.size();
221}
222
223QVariant AllLanguagesModel::data(const QModelIndex &index, int role) const
224{
225 if (index.isValid()) {
226
227 const QString code = d->locales.at(index.row());
228 if (role == Qt::DisplayRole) {
230 return localeName(bcp47);
231 } else if (role == Code) {
232 return code;
233 }
234 }
235 return QVariant();
236}
237
238QHash<int, QByteArray> AllLanguagesModel::roleNames() const
239{
240 QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
241 roles[Code] = "code";
242 return roles;
243}
244
247 config = KSharedConfig::openConfig()->group("TextProperties");
248 Q_FOREACH(const QString lang, config.readEntry<QStringList>(configKey, KLocalizedString::languages())) {
249 const QLocale locale(lang);
250 const QString code = locale.bcp47Name().split("_").join("-");
251 locales.append(code);
252 }
254 locales.insert(0, ""); // Add empty locale...
255 }
256
259 KConfigGroup config;
260
261 const QString configKey = "favoriteLocales";
262};
264 : QAbstractListModel(parent)
265 , d(new Private ())
266{
267}
268
273
274int FavoriteLocaleModel::rowCount(const QModelIndex &parent) const
275{
276 Q_UNUSED(parent)
277 return d->locales.size();
278}
279
280QVariant FavoriteLocaleModel::data(const QModelIndex &index, int role) const
281{
282 if (index.isValid()) {
283 const QString code = d->locales.at(index.row());
284 if (role == Qt::DisplayRole) {
286 return localeName(bcp47);
287 } else if (role == Code) {
288 return code;
289 } else if (role == Favorite) {
290 return d->favorites.contains(code);
291 }
292 }
293 return QVariant();
294}
295#include <QDebug>
296bool FavoriteLocaleModel::setData(const QModelIndex &index, const QVariant &value, int role)
297{
298 if (!index.isValid()) return false;
299
300 const QString code = d->locales.at(index.row());
301 if (role == Favorite) {
302
303 const bool fav = value.toBool();
304 bool updated = false;
305
306 if (fav) {
307 if (!d->favorites.contains(code)) {
308 d->favorites.append(code);
309 updated = true;
310 }
311 } else {
312 const int i = d->favorites.indexOf(code);
313 if (i > 0) {
314 d->favorites.removeAt(i);
315 updated = true;
316 }
317 }
318 if (updated) {
319 updateConfig();
320 emit dataChanged(index, index, {role});
321 return true;
322 }
323 }
324 return false;
325}
326
327void FavoriteLocaleModel::addCode(const QString &code)
328{
329 if (!d->locales.contains(code)) {
330 beginInsertRows(QModelIndex(), d->locales.size(), d->locales.size());
331 d->locales.append(code);
332 endInsertRows();
333 }
334}
335
336QHash<int, QByteArray> FavoriteLocaleModel::roleNames() const
337{
338 QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
339 roles[Code] = "code";
340 roles[Favorite] = "favorite";
341 return roles;
342}
343
345{
346 d->config.writeEntry<QStringList>(d->configKey, d->favorites);
347}
348
350 : QSortFilterProxyModel(parent)
351{
352
353}
354
355bool LanguagesFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
356{
357 QModelIndex idx = sourceModel()->index(source_row, 0, source_parent);
358 const QString name = sourceModel()->data(idx).toString();
359 const QString code = sourceModel()->data(idx, AllLanguagesModel::Code).toString();
360
361 return (name.contains(filterRegularExpression()) || code.contains(filterRegularExpression()));
362}
363
364
float value(const T *src, size_t ch)
const QString localeName(const KoWritingSystemUtils::Bcp47Locale &locale)
int rowCount(const QModelIndex &parent) const override
QVariant data(const QModelIndex &index, int role) const override
AllLanguagesModel(QObject *parent=nullptr)
const QScopedPointer< Private > d
QHash< int, QByteArray > roleNames() const override
The FavoriteLocaleModel class This class keeps track of favorite locales from the config.
QVariant data(const QModelIndex &index, int role) const override
int rowCount(const QModelIndex &parent) const override
void addCode(const QString &code)
FavoriteLocaleModel(QObject *parent=nullptr)
QHash< int, QByteArray > roleNames() const override
bool setData(const QModelIndex &index, const QVariant &value, int role) override
const QScopedPointer< Private > d
static QString scriptTagForQLocaleScript(QLocale::Script script)
static Bcp47Locale parseBcp47Locale(const QString &locale)
static QLocale localeFromBcp47Locale(const Bcp47Locale &locale)
The LanguagesFilterModel class class that tests both the name and the code.
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
LanguagesFilterModel(QObject *parent=nullptr)
QString searchString
void setLanguage(const QString &newLanguage)
void setSearchString(const QString &newSearchString)
Q_INVOKABLE QVariantList scriptModel() const
QAbstractItemModel * favoritesModel
QAbstractItemModel * languagesModel
LocaleHandler(QObject *parent=nullptr)
void languageChanged()
const QScopedPointer< Private > d
void setBcp47Tag(const QString &newBcp47Tag)
void bcp47TagChanged()
Q_INVOKABLE bool validBcp47Tag(const QString &tag) const
void setScript(const QString &newScript)
void scriptChanged()
void searchStringChanged()
The Bcp47Locale class This holds a parsed BCP47 locale. QLocale is primarily made for POSIX locale fo...
FavoriteLocaleModel * favorites
AllLanguagesModel * allLanguages
KoWritingSystemUtils::Bcp47Locale locale
Private(QObject *parent=nullptr)
LanguagesFilterModel * filteredLanguagesModel