Changeset View
Changeset View
Standalone View
Standalone View
kcms/translations/translationsmodel.cpp
Show All 16 Lines | |||||
17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | * Boston, MA 02110-1301, USA. | 18 | * Boston, MA 02110-1301, USA. | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "translationsmodel.h" | 21 | #include "translationsmodel.h" | ||
22 | 22 | | |||
23 | #include <KLocalizedString> | 23 | #include <KLocalizedString> | ||
24 | 24 | | |||
25 | #include <QCollator> | ||||
25 | #include <QDebug> | 26 | #include <QDebug> | ||
26 | #include <QLocale> | 27 | #include <QLocale> | ||
27 | #include <QMetaEnum> | 28 | #include <QMetaEnum> | ||
28 | 29 | | |||
30 | QStringList TranslationsModel::m_languages = QStringList(); | ||||
31 | QSet<QString> TranslationsModel::m_installedLanguages = QSet<QString>(); | ||||
32 | | ||||
29 | TranslationsModel::TranslationsModel(QObject *parent) | 33 | TranslationsModel::TranslationsModel(QObject *parent) | ||
30 | : QAbstractListModel(parent) | 34 | : QAbstractListModel(parent) | ||
31 | { | 35 | { | ||
36 | if (m_installedLanguages.isEmpty()) { | ||||
32 | m_installedLanguages = KLocalizedString::availableDomainTranslations("systemsettings"); | 37 | m_installedLanguages = KLocalizedString::availableDomainTranslations("systemsettings"); | ||
33 | m_languages = m_installedLanguages.toList(); | 38 | m_languages = m_installedLanguages.toList(); | ||
34 | } | 39 | } | ||
40 | } | ||||
35 | 41 | | |||
36 | TranslationsModel::~TranslationsModel() | 42 | TranslationsModel::~TranslationsModel() | ||
37 | { | 43 | { | ||
38 | } | 44 | } | ||
39 | 45 | | |||
40 | QHash<int, QByteArray> TranslationsModel::roleNames() const | 46 | QHash<int, QByteArray> TranslationsModel::roleNames() const | ||
41 | { | 47 | { | ||
42 | QHash<int, QByteArray> roles = QAbstractItemModel::roleNames(); | 48 | QHash<int, QByteArray> roles = QAbstractItemModel::roleNames(); | ||
Show All 12 Lines | 60 | { | |||
55 | if (!index.isValid() || index.row() < 0 || index.row() >= m_languages.count()) { | 61 | if (!index.isValid() || index.row() < 0 || index.row() >= m_languages.count()) { | ||
56 | return QVariant(); | 62 | return QVariant(); | ||
57 | } | 63 | } | ||
58 | 64 | | |||
59 | if (role == Qt::DisplayRole) { | 65 | if (role == Qt::DisplayRole) { | ||
60 | return languageCodeToName(m_languages.at(index.row())); | 66 | return languageCodeToName(m_languages.at(index.row())); | ||
61 | } else if (role == LanguageCode) { | 67 | } else if (role == LanguageCode) { | ||
62 | return m_languages.at(index.row()); | 68 | return m_languages.at(index.row()); | ||
63 | } else if (role == IsSelected) { | | |||
64 | return m_selectedLanguages.contains(m_languages.at(index.row())); | | |||
65 | } else if (role == SelectedPriority) { | | |||
66 | return m_selectedLanguages.indexOf(m_languages.at(index.row())); | | |||
67 | } else if (role == IsMissing) { | 69 | } else if (role == IsMissing) { | ||
68 | return m_missingLanguages.contains(m_languages.at(index.row())); | 70 | return false; | ||
69 | } | 71 | } | ||
70 | 72 | | |||
71 | return QVariant(); | 73 | return QVariant(); | ||
72 | } | 74 | } | ||
73 | 75 | | |||
74 | int TranslationsModel::rowCount(const QModelIndex &parent) const | 76 | int TranslationsModel::rowCount(const QModelIndex &parent) const | ||
75 | { | 77 | { | ||
76 | if (parent.isValid()) { | 78 | if (parent.isValid()) { | ||
77 | return 0; | 79 | return 0; | ||
78 | } | 80 | } | ||
79 | 81 | | |||
80 | return m_languages.count(); | 82 | return m_languages.count(); | ||
81 | } | 83 | } | ||
82 | 84 | | |||
83 | QStringList TranslationsModel::selectedLanguages() const | 85 | QString TranslationsModel::languageCodeToName(const QString& languageCode) const | ||
84 | { | 86 | { | ||
85 | return m_selectedLanguages; | 87 | const QLocale locale(languageCode); | ||
88 | const QString &languageName = locale.nativeLanguageName(); | ||||
89 | | ||||
90 | if (languageName.isEmpty()) { | ||||
91 | return languageCode; | ||||
86 | } | 92 | } | ||
87 | 93 | | |||
94 | if (languageCode.contains(QStringLiteral("@"))) { | ||||
95 | return i18nc("%1 is language name, %2 is language code name", "%1 (%2)", languageName, languageCode); | ||||
96 | } | ||||
88 | 97 | | |||
89 | void TranslationsModel::setSelectedLanguages(const QStringList &languages) | 98 | if (locale.name() != languageCode && m_installedLanguages.contains(locale.name())) { | ||
99 | // KDE languageCode got translated by QLocale to a locale code we also have on | ||||
100 | // the list. Currently this only happens with pt that gets translated to pt_BR. | ||||
101 | if (languageCode == QLatin1String("pt")) { | ||||
102 | return QLocale(QStringLiteral("pt_PT")).nativeLanguageName(); | ||||
103 | } else { | ||||
zzag: Coding style nitpick: don't use `else` after `return`.
References:
* https://releases.llvm. | |||||
104 | qWarning() << "Language code morphed into another existing language code, please report!" << languageCode << locale.name(); | ||||
105 | return i18nc("%1 is language name, %2 is language code name", "%1 (%2)", languageName, languageCode); | ||||
106 | } | ||||
107 | } | ||||
108 | | ||||
109 | return languageName; | ||||
110 | } | ||||
111 | | ||||
112 | SelectedTranslationsModel::SelectedTranslationsModel(QObject *parent) | ||||
113 | : TranslationsModel(parent) | ||||
114 | { | ||||
115 | } | ||||
116 | | ||||
117 | SelectedTranslationsModel::~SelectedTranslationsModel() | ||||
118 | { | ||||
119 | } | ||||
120 | | ||||
121 | QVariant SelectedTranslationsModel::data(const QModelIndex &index, int role) const | ||||
122 | { | ||||
123 | if (!index.isValid() || index.row() < 0 || index.row() >= m_selectedLanguages.count()) { | ||||
124 | return QVariant(); | ||||
125 | } | ||||
126 | | ||||
127 | if (role == Qt::DisplayRole) { | ||||
128 | return languageCodeToName(m_selectedLanguages.at(index.row())); | ||||
129 | } else if (role == LanguageCode) { | ||||
130 | return m_selectedLanguages.at(index.row()); | ||||
131 | } else if (role == IsMissing) { | ||||
132 | return m_missingLanguages.contains(m_selectedLanguages.at(index.row())); | ||||
133 | } | ||||
134 | | ||||
135 | return QVariant(); | ||||
136 | | ||||
137 | return TranslationsModel::data(index, role); | ||||
138 | } | ||||
139 | | ||||
140 | int SelectedTranslationsModel::rowCount(const QModelIndex &parent) const | ||||
141 | { | ||||
142 | if (parent.isValid()) { | ||||
143 | return 0; | ||||
144 | } | ||||
145 | | ||||
146 | return m_selectedLanguages.count(); | ||||
147 | } | ||||
148 | | ||||
149 | QStringList SelectedTranslationsModel::selectedLanguages() const | ||||
150 | { | ||||
151 | return m_selectedLanguages; | ||||
152 | } | ||||
153 | | ||||
154 | void SelectedTranslationsModel::setSelectedLanguages(const QStringList &languages) | ||||
90 | { | 155 | { | ||
91 | if (m_selectedLanguages != languages) { | 156 | if (m_selectedLanguages != languages) { | ||
92 | QStringList missingLanguages; | 157 | QStringList missingLanguages; | ||
93 | 158 | | |||
94 | for (const QString& lang : languages) { | 159 | for (const QString& lang : languages) { | ||
95 | if (!m_installedLanguages.contains(lang)) { | 160 | if (!m_installedLanguages.contains(lang)) { | ||
96 | missingLanguages << lang; | 161 | missingLanguages << lang; | ||
97 | } | 162 | } | ||
98 | } | 163 | } | ||
99 | 164 | | |||
100 | missingLanguages.sort(); | 165 | missingLanguages.sort(); | ||
101 | 166 | | |||
102 | if (missingLanguages != m_missingLanguages) { | 167 | if (missingLanguages != m_missingLanguages) { | ||
103 | m_missingLanguages = missingLanguages; | 168 | m_missingLanguages = missingLanguages; | ||
104 | emit missingLanguagesChanged(); | 169 | emit missingLanguagesChanged(); | ||
105 | } | 170 | } | ||
106 | 171 | | |||
107 | beginResetModel(); | 172 | beginResetModel(); | ||
108 | 173 | | |||
109 | m_selectedLanguages = languages; | 174 | m_selectedLanguages = languages; | ||
110 | m_languages = (m_installedLanguages | QSet<QString>::fromList(m_selectedLanguages)).toList(); | | |||
111 | 175 | | |||
112 | endResetModel(); | 176 | endResetModel(); | ||
113 | 177 | | |||
114 | emit selectedLanguagesChanged(); | 178 | emit selectedLanguagesChanged(m_selectedLanguages); | ||
115 | } | 179 | } | ||
116 | } | 180 | } | ||
117 | 181 | | |||
118 | QStringList TranslationsModel::missingLanguages() const | 182 | QStringList SelectedTranslationsModel::missingLanguages() const | ||
119 | { | 183 | { | ||
120 | return m_missingLanguages; | 184 | return m_missingLanguages; | ||
121 | } | 185 | } | ||
122 | 186 | | |||
123 | void TranslationsModel::moveSelectedLanguage(int from, int to) | 187 | void SelectedTranslationsModel::move(int from, int to) | ||
124 | { | 188 | { | ||
125 | if (from >= m_selectedLanguages.count() || to >= m_selectedLanguages.count()) { | 189 | if (from >= m_selectedLanguages.count() || to >= m_selectedLanguages.count()) { | ||
126 | return; | 190 | return; | ||
127 | } | 191 | } | ||
128 | 192 | | |||
129 | if (from == to) { | 193 | if (from == to) { | ||
130 | return; | 194 | return; | ||
131 | } | 195 | } | ||
132 | 196 | | |||
197 | int modelTo = to + (to > from ? 1 : 0); | ||||
zzag: Can be const. | |||||
198 | | ||||
199 | bool ok = beginMoveRows(QModelIndex(), from, from, QModelIndex(), modelTo); | ||||
200 | | ||||
201 | if (ok) { | ||||
133 | m_selectedLanguages.move(from, to); | 202 | m_selectedLanguages.move(from, to); | ||
134 | 203 | | |||
135 | emit selectedLanguagesChanged(); | 204 | endMoveRows(); | ||
136 | 205 | | |||
137 | auto idx = index(m_languages.indexOf(m_selectedLanguages.at(from)), 0); | 206 | emit selectedLanguagesChanged(m_selectedLanguages); | ||
207 | } | ||||
208 | } | ||||
138 | 209 | | |||
139 | if (idx.isValid()) { | 210 | void SelectedTranslationsModel::remove(const QString &languageCode) | ||
140 | emit dataChanged(idx, idx, QVector<int>{SelectedPriority}); | 211 | { | ||
212 | if (languageCode.isEmpty()) { | ||||
213 | return; | ||||
141 | } | 214 | } | ||
142 | 215 | | |||
143 | idx = index(m_languages.indexOf(m_selectedLanguages.at(to)), 0); | 216 | int index = m_selectedLanguages.indexOf(languageCode); | ||
217 | | ||||
218 | if (index != -1) { | ||||
219 | beginRemoveRows(QModelIndex(), index, index); | ||||
zzag: How about early return? E.g.
```lang=cpp
if (index < 0) {
return;
}
// ...
``` | |||||
144 | 220 | | |||
145 | if (idx.isValid()) { | 221 | m_selectedLanguages.removeAt(index); | ||
146 | emit dataChanged(idx, idx, QVector<int>{SelectedPriority}); | 222 | | ||
223 | endRemoveRows(); | ||||
224 | | ||||
225 | emit selectedLanguagesChanged(m_selectedLanguages); | ||||
147 | } | 226 | } | ||
148 | } | 227 | } | ||
149 | 228 | | |||
150 | void TranslationsModel::removeSelectedLanguage(const QString &languageCode) | 229 | AvailableTranslationsModel::AvailableTranslationsModel(QObject *parent) | ||
230 | : TranslationsModel(parent) | ||||
151 | { | 231 | { | ||
152 | m_selectedLanguages.removeOne(languageCode); | 232 | } | ||
153 | 233 | | |||
154 | emit selectedLanguagesChanged(); | 234 | AvailableTranslationsModel::~AvailableTranslationsModel() | ||
235 | { | ||||
236 | } | ||||
155 | 237 | | |||
156 | auto idx = index(m_languages.indexOf(languageCode), 0); | 238 | QVariant AvailableTranslationsModel::data(const QModelIndex &index, int role) const | ||
239 | { | ||||
240 | if (!index.isValid() || index.row() < 0 || index.row() >= m_availableLanguages.count()) { | ||||
241 | return QVariant(); | ||||
242 | } | ||||
157 | 243 | | |||
158 | if (idx.isValid()) { | 244 | if (role == Qt::DisplayRole) { | ||
159 | emit dataChanged(idx, idx, QVector<int>{IsSelected, SelectedPriority}); | 245 | return languageCodeToName(m_availableLanguages.at(index.row())); | ||
246 | } else if (role == LanguageCode) { | ||||
247 | return m_availableLanguages.at(index.row()); | ||||
248 | } else if (role == IsMissing) { | ||||
249 | return false; | ||||
160 | } | 250 | } | ||
251 | | ||||
252 | return QVariant(); | ||||
253 | | ||||
254 | return TranslationsModel::data(index, role); | ||||
zzag: Dead code. | |||||
161 | } | 255 | } | ||
162 | 256 | | |||
163 | QString TranslationsModel::languageCodeToName(const QString& languageCode) const | 257 | int AvailableTranslationsModel::rowCount(const QModelIndex &parent) const | ||
164 | { | 258 | { | ||
165 | const QLocale locale(languageCode); | 259 | if (parent.isValid()) { | ||
166 | const QString &languageName = locale.nativeLanguageName(); | 260 | return 0; | ||
167 | | ||||
168 | if (languageName.isEmpty()) { | | |||
169 | return languageCode; | | |||
170 | } | 261 | } | ||
171 | 262 | | |||
172 | if (languageCode.contains(QStringLiteral("@"))) { | 263 | return m_availableLanguages.count(); | ||
173 | return i18nc("%1 is language name, %2 is language code name", "%1 (%2)", languageName, languageCode); | | |||
174 | } | 264 | } | ||
175 | 265 | | |||
176 | if (locale.name() != languageCode && m_installedLanguages.contains(locale.name())) { | 266 | QString AvailableTranslationsModel::langCodeAt(int row) | ||
177 | // KDE languageCode got translated by QLocale to a locale code we also have on | 267 | { | ||
178 | // the list. Currently this only happens with pt that gets translated to pt_BR. | 268 | if (row < 0 || row >= m_availableLanguages.count()) { | ||
179 | if (languageCode == QLatin1String("pt")) { | 269 | return QString(); | ||
180 | return QLocale(QStringLiteral("pt_PT")).nativeLanguageName(); | | |||
181 | } else { | | |||
182 | qWarning() << "Language code morphed into another existing language code, please report!" << languageCode << locale.name(); | | |||
183 | return i18nc("%1 is language name, %2 is language code name", "%1 (%2)", languageName, languageCode); | | |||
184 | } | 270 | } | ||
271 | | ||||
272 | return m_availableLanguages.at(row); | ||||
185 | } | 273 | } | ||
186 | 274 | | |||
187 | return languageName; | 275 | void AvailableTranslationsModel::setSelectedLanguages(const QStringList &languages) | ||
276 | { | ||||
277 | beginResetModel(); | ||||
278 | | ||||
279 | m_availableLanguages = (m_installedLanguages - QSet<QString>::fromList(languages)).toList(); | ||||
280 | | ||||
281 | QCollator c; | ||||
282 | c.setCaseSensitivity(Qt::CaseInsensitive); | ||||
283 | | ||||
284 | std::sort(m_availableLanguages.begin(), m_availableLanguages.end(), | ||||
285 | [this, &c](const QString &a, const QString &b) { | ||||
286 | return c.compare(languageCodeToName(a), languageCodeToName(b)) < 0; | ||||
287 | }); | ||||
288 | | ||||
289 | endResetModel(); | ||||
188 | } | 290 | } |
Coding style nitpick: don't use else after return.
References: