KConfigWidgets

klanguagebutton.cpp
1/*
2 SPDX-FileCopyrightText: 1999-2003 Hans Petter Bieker <bieker@kde.org>
3 SPDX-FileCopyrightText: 2007 David Jarvie <djarvie@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "klanguagebutton.h"
9
10#include <QDir>
11#include <QFile>
12#include <QHBoxLayout>
13#include <QLocale>
14#include <QMenu>
15#include <QPushButton>
16
17#include <KConfig>
18#include <KConfigGroup>
19
20static void checkInsertPos(QMenu *popup, const QString &str, int &index)
21{
22 if (index != -1) {
23 return;
24 }
25
26 int a = 0;
27 const QList<QAction *> actions = popup->actions();
28 int b = actions.count();
29
30 while (a < b) {
31 int w = (a + b) / 2;
32 QAction *ac = actions[w];
33 int j = str.localeAwareCompare(ac->text());
34 if (j > 0) {
35 a = w + 1;
36 } else {
37 b = w;
38 }
39 }
40
41 index = a; // it doesn't really matter ... a == b here.
42
43 Q_ASSERT(a == b);
44}
45
46class KLanguageButtonPrivate
47{
48public:
49 explicit KLanguageButtonPrivate(KLanguageButton *parent);
50 ~KLanguageButtonPrivate()
51 {
52 delete button;
53 delete popup;
54 }
55 void setCurrentItem(QAction *);
56 void clear();
57 QAction *findAction(const QString &data) const;
58
59 QPushButton *button = nullptr;
60 QStringList ids;
61 QMenu *popup = nullptr;
62 QString current;
63 QString locale;
64 bool staticText : 1;
65 bool showCodes : 1;
66};
67
69 : QWidget(parent)
70 , d(new KLanguageButtonPrivate(this))
71{
72}
73
75 : QWidget(parent)
76 , d(new KLanguageButtonPrivate(this))
77{
78 setText(text);
79}
80
81KLanguageButtonPrivate::KLanguageButtonPrivate(KLanguageButton *parent)
82 : button(new QPushButton(parent))
83 , popup(new QMenu(parent))
84 , locale(QLocale::system().name())
85 , staticText(false)
86 , showCodes(false)
87{
89 layout->setContentsMargins(0, 0, 0, 0);
90 layout->addWidget(button);
91
92 parent->setFocusProxy(button);
93 parent->setFocusPolicy(button->focusPolicy());
94
95 button->setMenu(popup);
96
97 QObject::connect(popup, &QMenu::triggered, parent, &KLanguageButton::slotTriggered);
98 QObject::connect(popup, &QMenu::hovered, parent, &KLanguageButton::slotHovered);
99}
100
102
104{
105 d->staticText = true;
106 d->button->setText(text);
107}
108
110{
111 d->locale = locale;
112}
113
115{
116 d->showCodes = show;
117}
118
119static QString nameFromEntryFile(const QString &entryFile)
120{
121 const KConfig entry(entryFile, KConfig::SimpleConfig);
122 const KConfigGroup group(&entry, QStringLiteral("KCM Locale"));
123 return group.readEntry("Name", QString());
124}
125
126void KLanguageButton::insertLanguage(const QString &languageCode, const QString &name, int index)
127{
128 QString text;
129 bool showCodes = d->showCodes;
130 if (name.isEmpty()) {
131 const QString entryFile =
132 QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("locale/") + languageCode + QLatin1String("/kf6_entry.desktop"));
133 if (QFile::exists(entryFile)) {
134 text = nameFromEntryFile(entryFile);
135 }
136
137 if (text.isEmpty()) {
138 text = languageCode;
139 QLocale locale(languageCode);
140 if (locale != QLocale::c()) {
141 text = locale.nativeLanguageName();
142 // For some languages the native name might be empty.
143 // In this case use the non native language name as fallback.
144 // See: QTBUG-51323
145 text = text.isEmpty() ? QLocale::languageToString(locale.language()) : text;
146 } else {
147 showCodes = false;
148 }
149 }
150 } else {
151 text = name;
152 }
153 if (showCodes) {
154 text += QLatin1String(" (") + languageCode + QLatin1Char(')');
155 }
156
157 checkInsertPos(d->popup, text, index);
158 QAction *a = new QAction(QIcon(), text, this);
159 a->setData(languageCode);
160 if (index >= 0 && index < d->popup->actions().count() - 1) {
161 d->popup->insertAction(d->popup->actions()[index], a);
162 } else {
163 d->popup->addAction(a);
164 }
165 d->ids.append(languageCode);
166}
167
169{
170 if (index >= 0 && index < d->popup->actions().count() - 1) {
171 d->popup->insertSeparator(d->popup->actions()[index]);
172 } else {
173 d->popup->addSeparator();
174 }
175}
176
178{
180 for (const QString &localeDir : localeDirs) {
181 const QStringList entries = QDir(localeDir).entryList(QDir::Dirs, QDir::Name);
182 for (const QString &d : entries) {
183 const QString entryFile = localeDir + QLatin1Char('/') + d + QStringLiteral("/kf6_entry.desktop");
184 if (QFile::exists(entryFile)) {
186 }
187 }
188 }
189
190 d->ids.removeDuplicates();
191 setCurrentItem(d->locale);
192}
193
194void KLanguageButton::slotTriggered(QAction *a)
195{
196 // qCDebug(KCONFIG_WIDGETS_LOG) << "slotTriggered" << index;
197 if (!a) {
198 return;
199 }
200
201 d->setCurrentItem(a);
202
203 // Forward event from popup menu as if it was emitted from this widget:
204 Q_EMIT activated(d->current);
205}
206
207void KLanguageButton::slotHovered(QAction *a)
208{
209 // qCDebug(KCONFIG_WIDGETS_LOG) << "slotHovered" << index;
210
212}
213
215{
216 return d->ids.count();
217}
218
220{
221 d->clear();
222}
223
224void KLanguageButtonPrivate::clear()
225{
226 ids.clear();
227 popup->clear();
228
229 if (!staticText) {
230 button->setText(QString());
231 }
232}
233
234bool KLanguageButton::contains(const QString &languageCode) const
235{
236 return d->ids.contains(languageCode);
237}
238
240{
241 return d->current.isEmpty() ? QStringLiteral("en") : d->current;
242}
243
244QAction *KLanguageButtonPrivate::findAction(const QString &data) const
245{
246 const auto listActions = popup->actions();
247 for (QAction *a : listActions) {
248 if (!a->data().toString().compare(data)) {
249 return a;
250 }
251 }
252 return nullptr;
253}
254
256{
257 if (d->ids.isEmpty()) {
258 return;
259 }
260 QAction *a;
261 if (d->ids.indexOf(languageCode) < 0) {
262 a = d->findAction(d->ids[0]);
263 } else {
264 a = d->findAction(languageCode);
265 }
266 if (a) {
267 d->setCurrentItem(a);
268 }
269}
270
271void KLanguageButtonPrivate::setCurrentItem(QAction *a)
272{
273 if (!a->data().isValid()) {
274 return;
275 }
276 current = a->data().toString();
277
278 if (!staticText) {
279 button->setText(a->text());
280 }
281}
282
283#include "moc_klanguagebutton.cpp"
KLanguageButton is a pushbutton which allows a language to be selected from a popup list.
int count() const
Returns the number of items in the combo box.
QString current() const
Returns the language code of the combobox's current item.
void insertSeparator(int index=-1)
Inserts a separator item into the combo box.
void highlighted(const QString &languageCode)
This signal is emitted when a new item is highlighted.
KLanguageButton(QWidget *parent=nullptr)
Constructs a button whose text is determined by the current language in the popup list.
void activated(const QString &languageCode)
This signal is emitted when a new item is activated.
void clear()
Removes all combobox items.
void insertLanguage(const QString &languageCode, const QString &name=QString(), int index=-1)
Inserts a language into the combo box.
void setCurrentItem(const QString &languageCode)
Sets a given language to be the current item.
void showLanguageCodes(bool show)
Specifies whether language codes should be shown alongside language names in the popup.
void loadAllLanguages()
Load all known languages into the popup list.
~KLanguageButton() override
Deconstructor.
void setText(const QString &text)
Sets a static button text.
bool contains(const QString &languageCode) const
Checks whether the specified language is in the popup list.
void setLocale(const QString &locale)
Sets the locale to display language names.
void setText(const QString &text)
QVariant data() const const
void setData(const QVariant &data)
QStringList entryList(Filters filters, SortFlags sort) const const
bool exists() const const
void addWidget(QWidget *w)
void setContentsMargins(const QMargins &margins)
void clear()
qsizetype count() const const
QLocale c()
QString languageToString(Language language)
void clear()
void hovered(QAction *action)
void triggered(QAction *action)
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
QString locate(StandardLocation type, const QString &fileName, LocateOptions options)
QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options)
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
bool isEmpty() const const
int localeAwareCompare(QStringView s1, QStringView s2)
bool isValid() const const
QString toString() const const
QList< QAction * > actions() const const
QLayout * layout() const const
void show()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:07:46 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.