55 */
66
77#include " model.h"
8+ #include < QAbstractItemModel>
89#include < QCollator>
10+ #include < QHash>
911#include < QLocale>
12+ #include < QObject>
13+ #include < QSet>
14+ #include < QSortFilterProxyModel>
15+ #include < QString>
16+ #include < QStringLiteral>
17+ #include < Qt>
18+ #include < QtTypes>
19+ #include < algorithm>
1020#include < fcitx-utils/i18n.h>
11-
12- namespace fcitx {
13- namespace kcm {
21+ #include < fcitxqtdbustypes.h>
22+ #include < utility>
23+
24+ namespace fcitx ::kcm {
25+
26+ const IMConfigModelInterface::LanguageNames &
27+ IMConfigModelInterface::languageNames (const QString &langCode) const {
28+ auto iter = languageNames_.find (langCode);
29+ if (iter == languageNames_.end ()) {
30+ LanguageNames names;
31+ if (langCode.isEmpty ()) {
32+ names.nativeName = names.localName = _ (" Unknown" );
33+ } else if (langCode == " *" || langCode == " mul" ) {
34+ names.nativeName = names.localName = _ (" Multilingual" );
35+ } else {
36+ QString lang = langCode;
37+ // The lang before _.
38+ QString territory;
39+ if (auto items = langCode.split (' _' ); !items.isEmpty ()) {
40+ if (!items.first ().isEmpty ()) {
41+ lang = items.first ();
42+ }
43+ if (items.size () > 1 ) {
44+ QLocale locale (langCode);
45+ if (locale.territory () != QLocale::AnyTerritory) {
46+ territory =
47+ QLocale::territoryToString (locale.territory ());
48+ }
49+ if (!territory.isEmpty ()) {
50+ territory =
51+ D_ (" iso_3166" , territory.toUtf8 ().constData ());
52+ }
53+ }
54+ }
55+ names.nativeName = iso639_.queryNative (lang);
56+ names.localName = iso639_.query (lang);
57+ if (!territory.isEmpty ()) {
58+ names.localName =
59+ QString (C_ (" %1 is language name, %2 is country name" ,
60+ " %1 (%2)" ))
61+ .arg (names.localName , territory);
62+ }
63+ }
64+ iter = languageNames_.insert (langCode, std::move (names));
65+ }
66+ return iter.value ();
67+ }
1468
1569CategorizedItemModel::CategorizedItemModel (QObject *parent)
1670 : QAbstractItemModel(parent) {}
@@ -31,7 +85,9 @@ int CategorizedItemModel::rowCount(const QModelIndex &parent) const {
3185 return subListSize (parent.row ());
3286}
3387
34- int CategorizedItemModel::columnCount (const QModelIndex &) const { return 1 ; }
88+ int CategorizedItemModel::columnCount (const QModelIndex & /* parent*/ ) const {
89+ return 1 ;
90+ }
3591
3692QModelIndex CategorizedItemModel::parent (const QModelIndex &child) const {
3793 if (!child.isValid ()) {
@@ -52,9 +108,8 @@ QModelIndex CategorizedItemModel::index(int row, int column,
52108 if (!parent.isValid ()) {
53109 if (column > 0 || row >= listSize ()) {
54110 return QModelIndex ();
55- } else {
56- return createIndex (row, column, static_cast <quintptr>(0 ));
57111 }
112+ return createIndex (row, column, static_cast <quintptr>(0 ));
58113 }
59114
60115 // return im index
@@ -90,62 +145,14 @@ QVariant CategorizedItemModel::data(const QModelIndex &index, int role) const {
90145 return dataForItem (index, role);
91146}
92147
93- static QString languageName (const QString &langCode) {
94- if (langCode.isEmpty ()) {
95- return _ (" Unknown" );
96- } else if (langCode == " *" )
97- return _ (" Multilingual" );
98- else {
99- QLocale locale (langCode);
100- if (locale.language () == QLocale::C) {
101- // return lang code seems to be a better solution other than
102- // indistinguishable "unknown"
103- return langCode;
104- }
105-
106- const bool hasTerritory = (langCode.indexOf (" _" ) != -1 &&
107- locale.territory () != QLocale::AnyTerritory);
108- QString languageName;
109- if (hasTerritory) {
110- languageName = locale.nativeLanguageName ();
111- }
112- if (languageName.isEmpty ()) {
113- languageName =
114- D_ (" iso_639" ,
115- QLocale::languageToString (locale.language ()).toUtf8 ());
116- }
117- if (languageName.isEmpty ()) {
118- languageName = _ (" Other" );
119- }
120- QString territoryName;
121- // QLocale will always assign a default country for us, check if our
122- // lang code
123-
124- if (hasTerritory) {
125- territoryName = locale.nativeTerritoryName ();
126- if (territoryName.isEmpty ()) {
127- territoryName = QLocale::territoryToString (locale.territory ());
128- }
129- }
130-
131- if (territoryName.isEmpty ()) {
132- return languageName;
133- } else {
134- return QString (
135- C_ (" %1 is language name, %2 is country name" , " %1 (%2)" ))
136- .arg (languageName, territoryName);
137- }
138- }
139- }
140-
141148AvailIMModel::AvailIMModel (QObject *parent) : CategorizedItemModel(parent) {}
142149
143150QVariant AvailIMModel::dataForCategory (const QModelIndex &index,
144151 int role) const {
145152 switch (role) {
146153
147154 case Qt::DisplayRole:
148- return languageName (filteredIMEntryList[index.row ()].first );
155+ return languageNames (filteredIMEntryList[index.row ()].first ). localName ;
149156
150157 case FcitxLanguageRole:
151158 return filteredIMEntryList[index.row ()].first ;
@@ -180,8 +187,11 @@ QVariant AvailIMModel::dataForItem(const QModelIndex &index, int role) const {
180187
181188 case FcitxLanguageRole:
182189 return imEntry.languageCode ();
190+
191+ default :
192+ break ;
183193 }
184- return QVariant () ;
194+ return {} ;
185195}
186196
187197void AvailIMModel::filterIMEntryList (
@@ -292,24 +302,33 @@ bool IMProxyModel::filterIM(const QModelIndex &index) const {
292302 return true ;
293303 }
294304
295- bool flag = true ;
296- QString lang = langCode.left (2 );
297- bool showOnlyCurrentLanguage =
298- filterText_.isEmpty () && showOnlyCurrentLanguage_;
299-
300- flag =
301- flag && (showOnlyCurrentLanguage
302- ? !lang.isEmpty () && (QLocale ().name ().startsWith (lang) ||
303- languageSet_.contains (lang))
304- : true );
305- if (!filterText_.isEmpty ()) {
306- flag = flag && (name.contains (filterText_, Qt::CaseInsensitive) ||
307- uniqueName.contains (filterText_, Qt::CaseInsensitive) ||
308- langCode.contains (filterText_, Qt::CaseInsensitive) ||
309- languageName (langCode).contains (filterText_,
310- Qt::CaseInsensitive));
311- }
312- return flag;
305+ QString lang = langCode;
306+ // The lang before _.
307+ if (auto items = langCode.split (' _' );
308+ !items.isEmpty () && !items[0 ].isEmpty ()) {
309+ lang = items.first ();
310+ }
311+
312+ if (filterText_.isEmpty ()) {
313+ if (showOnlyCurrentLanguage_) {
314+ return !lang.isEmpty () && (QLocale ().name ().startsWith (lang) ||
315+ languageSet_.contains (lang));
316+ }
317+ return true ;
318+ }
319+
320+ if (name.contains (filterText_, Qt::CaseInsensitive) ||
321+ uniqueName.contains (filterText_, Qt::CaseInsensitive) ||
322+ langCode.contains (filterText_, Qt::CaseInsensitive)) {
323+ return true ;
324+ }
325+
326+ const auto &langNames = languageNames (langCode);
327+ if (langNames.localName .contains (filterText_, Qt::CaseInsensitive) ||
328+ langNames.nativeName .contains (filterText_, Qt::CaseInsensitive)) {
329+ return true ;
330+ }
331+ return false ;
313332}
314333
315334bool IMProxyModel::lessThan (const QModelIndex &left,
@@ -378,7 +397,7 @@ QVariant FilteredIMModel::data(const QModelIndex &index, int role) const {
378397 return imEntry.configurable ();
379398
380399 case FcitxLanguageNameRole:
381- return languageName (imEntry.languageCode ());
400+ return languageNames (imEntry.languageCode ()). localName ;
382401
383402 case FcitxIMLayoutRole: {
384403 auto iter = std::find_if (enabledIMList_.begin (), enabledIMList_.end (),
@@ -395,7 +414,7 @@ QVariant FilteredIMModel::data(const QModelIndex &index, int role) const {
395414 : QStringLiteral (" inactive" );
396415
397416 default :
398- return QVariant () ;
417+ return {} ;
399418 }
400419}
401420
@@ -477,5 +496,4 @@ void FilteredIMModel::remove(int idx) {
477496 Q_EMIT imListChanged (filteredIMEntryList_);
478497}
479498
480- } // namespace kcm
481- } // namespace fcitx
499+ } // namespace fcitx::kcm
0 commit comments