Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qgenericunixthemes.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QPalette>
7#include <QFont>
8#include <QGuiApplication>
9#include <QDir>
10#include <QFileInfo>
11#include <QFile>
12#include <QDebug>
13#include <QHash>
14#include <QLoggingCategory>
15#include <QVariant>
16#include <QStandardPaths>
17#include <QStringList>
18#if QT_CONFIG(mimetype)
19#include <QMimeDatabase>
20#endif
21#if QT_CONFIG(settings)
22#include <QSettings>
23#endif
24
25#include <qpa/qplatformfontdatabase.h> // lcQpaFonts
26#include <qpa/qplatformintegration.h>
27#include <qpa/qplatformservices.h>
28#include <qpa/qplatformdialoghelper.h>
29#include <qpa/qplatformtheme_p.h>
30
31#include <private/qguiapplication_p.h>
32#ifndef QT_NO_DBUS
33#include <QDBusConnectionInterface>
34#include <private/qdbusplatformmenu_p.h>
35#include <private/qdbusmenubar_p.h>
36#include <private/qflatmap_p.h>
37#include <QJsonDocument>
38#include <QJsonArray>
39#include <QJsonObject>
40#include <QJsonValue>
41#include <QJsonParseError>
42#endif
43#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
44#include <private/qdbustrayicon_p.h>
45#endif
46
47#include <algorithm>
48
50#ifndef QT_NO_DBUS
51Q_LOGGING_CATEGORY(lcQpaThemeDBus, "qt.qpa.theme.dbus")
52#endif
53
54using namespace Qt::StringLiterals;
55
57
59{
60 std::fill(palettes, palettes + QPlatformTheme::NPalettes, static_cast<QPalette *>(nullptr));
61 std::fill(fonts, fonts + QPlatformTheme::NFonts, static_cast<QFont *>(nullptr));
62}
63
65{
68 std::fill(palettes, palettes + QPlatformTheme::NPalettes, static_cast<QPalette *>(nullptr));
69 std::fill(fonts, fonts + QPlatformTheme::NFonts, static_cast<QFont *>(nullptr));
70}
71
72const char *QGenericUnixTheme::name = "generic";
73
74// Default system font, corresponding to the value returned by 4.8 for
75// XRender/FontConfig which we can now assume as default.
76static const char defaultSystemFontNameC[] = "Sans Serif";
77static const char defaultFixedFontNameC[] = "monospace";
79
80#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
81static bool isDBusTrayAvailable() {
82 static bool dbusTrayAvailable = false;
83 static bool dbusTrayAvailableKnown = false;
84 if (!dbusTrayAvailableKnown) {
86 if (conn.isWatcherRegistered())
87 dbusTrayAvailable = true;
88 dbusTrayAvailableKnown = true;
89 qCDebug(qLcTray) << "D-Bus tray available:" << dbusTrayAvailable;
90 }
91 return dbusTrayAvailable;
92}
93#endif
94
96{
97 static QString themeName = qEnvironmentVariable("XCURSOR_THEME");
98 return themeName;
99}
100
102{
103 constexpr int defaultCursorSize = 24;
104 static const int xCursorSize = qEnvironmentVariableIntValue("XCURSOR_SIZE");
105 static const int s = xCursorSize > 0 ? xCursorSize : defaultCursorSize;
106 return QSize(s, s);
107}
108
109#ifndef QT_NO_DBUS
111{
113 static const QString registrarService = QStringLiteral("com.canonical.AppMenu.Registrar");
114 if (const auto iface = connection.interface())
115 return iface->isServiceRegistered(registrarService);
116 return false;
117}
118
120{
121 static bool dbusGlobalMenuAvailable = checkDBusGlobalMenuAvailable();
122 return dbusGlobalMenuAvailable;
123}
124
136{
138
139public:
140
141 enum class Provider {
142 Kde,
143 Gtk,
144 Gnome,
145 };
147
148 enum class Setting {
149 Theme,
152 };
154
156 QGenericUnixThemeDBusListener(const QString &service, const QString &path,
157 const QString &interface, const QString &signal);
158
159private Q_SLOTS:
160 void onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value);
161
165 const QString &value);
166
167private:
168 struct DBusKey
169 {
171 QString key;
172 DBusKey(const QString &loc, const QString &k) : location(loc), key(k) {};
173 bool operator<(const DBusKey &other) const
174 {
175 return location + key < other.location + other.key;
176 }
177 };
178
179 struct ChangeSignal
180 {
181 Provider provider;
182 Setting setting;
183 ChangeSignal(Provider p, Setting s) : provider(p), setting(s) {}
184 ChangeSignal() {}
185 };
186
187 // Json keys
188 static constexpr QLatin1StringView s_dbusLocation = QLatin1StringView("DBusLocation");
189 static constexpr QLatin1StringView s_dbusKey = QLatin1StringView("DBusKey");
190 static constexpr QLatin1StringView s_provider = QLatin1StringView("Provider");
191 static constexpr QLatin1StringView s_setting = QLatin1StringView("Setting");
192 static constexpr QLatin1StringView s_signals = QLatin1StringView("DbusSignals");
193 static constexpr QLatin1StringView s_root = QLatin1StringView("Qt.qpa.DBusSignals");
194
195 QFlatMap <DBusKey, ChangeSignal> m_signalMap;
196
197 void init(const QString &service, const QString &path,
198 const QString &interface, const QString &signal);
199
200 std::optional<ChangeSignal> findSignal(const QString &location, const QString &key) const;
201 void populateSignalMap();
202 void loadJson(const QString &fileName);
203 void saveJson(const QString &fileName) const;
204};
205
207 const QString &path, const QString &interface, const QString &signal)
208{
209 init (service, path, interface, signal);
210}
211
213{
214 static constexpr QLatin1StringView service("");
215 static constexpr QLatin1StringView path("/org/freedesktop/portal/desktop");
216 static constexpr QLatin1StringView interface("org.freedesktop.portal.Settings");
217 static constexpr QLatin1StringView signal("SettingChanged");
218
219 init (service, path, interface, signal);
220}
221
222void QGenericUnixThemeDBusListener::init(const QString &service, const QString &path,
223 const QString &interface, const QString &signal)
224{
226 const bool dBusRunning = dbus.isConnected();
227 bool dBusSignalConnected = false;
228#define LOG service << path << interface << signal;
229
230 if (dBusRunning) {
231 populateSignalMap();
232 qRegisterMetaType<QDBusVariant>();
233 dBusSignalConnected = dbus.connect(service, path, interface, signal, this,
234 SLOT(onSettingChanged(QString,QString,QDBusVariant)));
235 }
236
237 if (dBusSignalConnected) {
238 // Connection successful
239 qCDebug(lcQpaThemeDBus) << LOG;
240 } else {
241 if (dBusRunning) {
242 // DBus running, but connection failed
243 qCWarning(lcQpaThemeDBus) << "DBus connection failed:" << LOG;
244 } else {
245 // DBus not running
246 qCWarning(lcQpaThemeDBus) << "Session DBus not running.";
247 }
248 qCWarning(lcQpaThemeDBus) << "Application will not react to setting changes.\n"
249 << "Check your DBus installation.";
250 }
251#undef LOG
252}
253
254void QGenericUnixThemeDBusListener::loadJson(const QString &fileName)
255{
256 Q_ASSERT(!fileName.isEmpty());
257#define CHECK(cond, warning)\
258 if (!cond) {\
259 qCWarning(lcQpaThemeDBus) << fileName << warning << "Falling back to default.";\
260 return;\
261 }
262
263#define PARSE(var, enumeration, string)\
264 enumeration var;\
265 {\
266 bool success;\
267 const int val = QMetaEnum::fromType<enumeration>().keyToValue(string.toLatin1(), &success);\
268 CHECK(success, "Parse Error: Invalid value" << string << "for" << #var);\
269 var = static_cast<enumeration>(val);\
270 }
271
273 CHECK(file.exists(), fileName << "doesn't exist.");
274 CHECK(file.open(QIODevice::ReadOnly), "could not be opened for reading.");
275
278 CHECK((error.error == QJsonParseError::NoError), error.errorString());
279 qDebug() << doc;
280 CHECK(doc.isObject(), "Parse Error: Expected root object" << s_root);
281
282 const QJsonObject &root = doc.object();
283 CHECK(root.contains(s_root), "Parse Error: Expected root object" << s_root);
284 CHECK(root[s_root][s_signals].isArray(), "Parse Error: Expected array" << s_signals);
285
286 const QJsonArray &sigs = root[s_root][s_signals].toArray();
287 CHECK((sigs.count() > 0), "Parse Error: Found empty array" << s_signals);
288
289 for (auto sig = sigs.constBegin(); sig != sigs.constEnd(); ++sig) {
290 CHECK(sig->isObject(), "Parse Error: Expected object array" << s_signals);
291 const QJsonObject &obj = sig->toObject();
292 CHECK(obj.contains(s_dbusLocation), "Parse Error: Expected key" << s_dbusLocation);
293 CHECK(obj.contains(s_dbusKey), "Parse Error: Expected key" << s_dbusKey);
294 CHECK(obj.contains(s_provider), "Parse Error: Expected key" << s_provider);
295 CHECK(obj.contains(s_setting), "Parse Error: Expected key" << s_setting);
296 const QString &location = obj[s_dbusLocation].toString();
297 const QString &key = obj[s_dbusKey].toString();
298 const QString &providerString = obj[s_provider].toString();
299 const QString &settingString = obj[s_setting].toString();
300 PARSE(provider, Provider, providerString);
301 PARSE(setting, Setting, settingString);
302 const DBusKey dkey(location, key);
303 CHECK (!m_signalMap.contains(dkey), "Duplicate key" << location << key);
304 m_signalMap.insert(dkey, ChangeSignal(provider, setting));
305 }
306#undef PARSE
307#undef CHECK
308
309 if (m_signalMap.count() > 0)
310 qCInfo(lcQpaThemeDBus) << "Successfully imported" << fileName;
311 else
312 qCWarning(lcQpaThemeDBus) << "No data imported from" << fileName << "falling back to default.";
313
314#ifdef QT_DEBUG
315 const int count = m_signalMap.count();
316 if (count == 0)
317 return;
318
319 qCDebug(lcQpaThemeDBus) << "Listening to" << count << "signals:";
320 for (auto it = m_signalMap.constBegin(); it != m_signalMap.constEnd(); ++it) {
321 qDebug() << it.key().key << it.key().location << "mapped to"
322 << it.value().provider << it.value().setting;
323 }
324
325#endif
326}
327
328void QGenericUnixThemeDBusListener::saveJson(const QString &fileName) const
329{
330 Q_ASSERT(!m_signalMap.isEmpty());
331 Q_ASSERT(!fileName.isEmpty());
334 qCWarning(lcQpaThemeDBus) << fileName << "could not be opened for writing.";
335 return;
336 }
337
338 QJsonArray sigs;
339 for (auto sig = m_signalMap.constBegin(); sig != m_signalMap.constEnd(); ++sig) {
340 const DBusKey &dkey = sig.key();
341 const ChangeSignal &csig = sig.value();
343 obj[s_dbusLocation] = dkey.location;
344 obj[s_dbusKey] = dkey.key;
345 obj[s_provider] = QLatin1StringView(QMetaEnum::fromType<Provider>()
346 .valueToKey(static_cast<int>(csig.provider)));
347 obj[s_setting] = QLatin1StringView(QMetaEnum::fromType<Setting>()
348 .valueToKey(static_cast<int>(csig.setting)));
349 sigs.append(obj);
350 }
352 obj[s_signals] = sigs;
353 QJsonObject root;
354 root[s_root] = obj;
355 QJsonDocument doc(root);
356 file.write(doc.toJson());
357 file.close();
358}
359
360void QGenericUnixThemeDBusListener::populateSignalMap()
361{
362 m_signalMap.clear();
363 const QString &loadJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS");
364 if (!loadJsonFile.isEmpty())
365 loadJson(loadJsonFile);
366 if (!m_signalMap.isEmpty())
367 return;
368
369 m_signalMap.insert(DBusKey("org.kde.kdeglobals.KDE"_L1, "widgetStyle"_L1),
371
372 m_signalMap.insert(DBusKey("org.kde.kdeglobals.General"_L1, "ColorScheme"_L1),
373 ChangeSignal(Provider::Kde, Setting::Theme));
374
375 m_signalMap.insert(DBusKey("org.gnome.desktop.interface"_L1, "gtk-theme"_L1),
376 ChangeSignal(Provider::Gtk, Setting::Theme));
377
378 m_signalMap.insert(DBusKey("org.freedesktop.appearance"_L1, "color-scheme"_L1),
379 ChangeSignal(Provider::Gnome, Setting::ColorTheme));
380
381 const QString &saveJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS_SAVE");
382 if (!saveJsonFile.isEmpty())
383 saveJson(saveJsonFile);
384}
385
386std::optional<QGenericUnixThemeDBusListener::ChangeSignal>
387 QGenericUnixThemeDBusListener::findSignal(const QString &location, const QString &key) const
388{
389 const DBusKey dkey(location, key);
390 std::optional<QGenericUnixThemeDBusListener::ChangeSignal> ret;
391 if (m_signalMap.contains(dkey))
392 ret.emplace(m_signalMap.value(dkey));
393
394 return ret;
395}
396
397void QGenericUnixThemeDBusListener::onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value)
398{
399 auto sig = findSignal(location, key);
400 if (!sig.has_value())
401 return;
402
403 emit settingChanged(sig.value().provider, sig.value().setting, value.variant().toString());
404}
405
406#endif //QT_NO_DBUS
407
409{
410public:
415 {
417 qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
418 }
419
422};
423
426{
427}
428
430{
431 Q_D(const QGenericUnixTheme);
432 switch (type) {
434 return &d->systemFont;
436 return &d->fixedFont;
437 default:
438 return nullptr;
439 }
440}
441
442// Helper to return the icon theme paths from XDG.
444{
446 // Add home directory first in search path
447 const QFileInfo homeIconDir(QDir::homePath() + "/.icons"_L1);
448 if (homeIconDir.isDir())
449 paths.prepend(homeIconDir.absoluteFilePath());
450
452 QStringLiteral("icons"),
454
455 return paths;
456}
457
459{
461 const QFileInfo pixmapsIconsDir(QStringLiteral("/usr/share/pixmaps"));
462 if (pixmapsIconsDir.isDir())
463 paths.append(pixmapsIconsDir.absoluteFilePath());
464
465 return paths;
466}
467
468#ifndef QT_NO_DBUS
470{
472 return new QDBusMenuBar();
473 return nullptr;
474}
475#endif
476
477#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
479{
481 return new QDBusTrayIcon();
482 return nullptr;
483}
484#endif
485
487{
488 switch (hint) {
490 return QVariant(QString(QStringLiteral("hicolor")));
492 return xdgIconThemePaths();
494 return iconFallbackPaths();
496 return QVariant(true);
499 styleNames << QStringLiteral("Fusion") << QStringLiteral("Windows");
500 return QVariant(styleNames);
501 }
503 return QVariant(int(X11KeyboardScheme));
505 return QVariant(int(HoverEffect));
507 return QVariant(mouseCursorTheme());
509 return QVariant(mouseCursorSize());
510 default:
511 break;
512 }
514}
515
516// Helper functions for implementing QPlatformTheme::fileIcon() for XDG icon themes.
518{
519 return QIcon::fromTheme(QStringLiteral("inode-directory")).availableSizes();
520}
521
522#if QT_CONFIG(mimetype)
523static QIcon xdgFileIcon(const QFileInfo &fileInfo)
524{
525 QMimeDatabase mimeDatabase;
526 QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo);
527 if (!mimeType.isValid())
528 return QIcon();
529 const QString &iconName = mimeType.iconName();
530 if (!iconName.isEmpty()) {
531 const QIcon icon = QIcon::fromTheme(iconName);
532 if (!icon.isNull())
533 return icon;
534 }
535 const QString &genericIconName = mimeType.genericIconName();
536 return genericIconName.isEmpty() ? QIcon() : QIcon::fromTheme(genericIconName);
537}
538#endif
539
540#if QT_CONFIG(settings)
541class QKdeThemePrivate : public QPlatformThemePrivate
542{
543
544public:
545 QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion);
546
547 static QString kdeGlobals(const QString &kdeDir, int kdeVersion)
548 {
549 if (kdeVersion > 4)
550 return kdeDir + "/kdeglobals"_L1;
551 return kdeDir + "/share/config/kdeglobals"_L1;
552 }
553
554 void refresh();
555 static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings);
556 static void readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal);
557 static QFont *kdeFont(const QVariant &fontValue);
558 static QStringList kdeIconThemeSearchPaths(const QStringList &kdeDirs);
559
560 const QStringList kdeDirs;
561 const int kdeVersion;
562
563 ResourceHelper resources;
564 QString iconThemeName;
565 QString iconFallbackThemeName;
567 int toolButtonStyle = Qt::ToolButtonTextBesideIcon;
568 int toolBarIconSize = 0;
569 bool singleClick = true;
570 bool showIconsOnPushButtons = true;
571 int wheelScrollLines = 3;
572 int doubleClickInterval = 400;
573 int startDragDist = 10;
574 int startDragTime = 500;
575 int cursorBlinkRate = 1000;
577 void updateColorScheme(const QString &themeName);
578
579#ifndef QT_NO_DBUS
580private:
581 std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
582 bool initDbus();
583 void settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
585 const QString &value);
586#endif // QT_NO_DBUS
587};
588
589#ifndef QT_NO_DBUS
590void QKdeThemePrivate::settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
592 const QString &value)
593{
595 return;
596
597 switch (setting) {
599 qCDebug(lcQpaThemeDBus) << "KDE color theme changed to:" << value;
600 break;
602 qCDebug(lcQpaThemeDBus) << "KDE global theme changed to:" << value;
603 break;
605 qCDebug(lcQpaThemeDBus) << "KDE application style changed to:" << value;
606 break;
607 }
608
609 refresh();
610}
611
612bool QKdeThemePrivate::initDbus()
613{
615 Q_ASSERT(dbus);
616
617 // Wrap slot in a lambda to avoid inheriting QKdeThemePrivate from QObject
620 const QString &value) {
621 settingChangedHandler(provider, setting, value);
622 };
623
625}
626#endif // QT_NO_DBUS
627
628QKdeThemePrivate::QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion)
629 : kdeDirs(kdeDirs), kdeVersion(kdeVersion)
630{
631#ifndef QT_NO_DBUS
632 initDbus();
633#endif // QT_NO_DBUS
634}
635
636void QKdeThemePrivate::refresh()
637{
638 resources.clear();
639
640 toolButtonStyle = Qt::ToolButtonTextBesideIcon;
641 toolBarIconSize = 0;
642 styleNames.clear();
643 if (kdeVersion >= 5)
644 styleNames << QStringLiteral("breeze");
645 styleNames << QStringLiteral("Oxygen") << QStringLiteral("Fusion") << QStringLiteral("windows");
646 if (kdeVersion >= 5)
647 iconFallbackThemeName = iconThemeName = QStringLiteral("breeze");
648 else
649 iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen");
650
651 QHash<QString, QSettings*> kdeSettings;
652
653 QPalette systemPalette = QPalette();
654 readKdeSystemPalette(kdeDirs, kdeVersion, kdeSettings, &systemPalette);
655 resources.palettes[QPlatformTheme::SystemPalette] = new QPalette(systemPalette);
656 //## TODO tooltip color
657
658 const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle"), kdeDirs, kdeVersion, kdeSettings);
659 if (styleValue.isValid()) {
660 const QString style = styleValue.toString();
661 if (style != styleNames.front())
662 styleNames.push_front(style);
663 }
664
665 const QVariant colorScheme = readKdeSetting(QStringLiteral("ColorScheme"), kdeDirs,
666 kdeVersion, kdeSettings);
667
668 if (colorScheme.isValid())
669 updateColorScheme(colorScheme.toString());
670 else
671 m_colorScheme = Qt::ColorScheme::Unknown;
672
673 const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeVersion, kdeSettings);
674 if (singleClickValue.isValid())
675 singleClick = singleClickValue.toBool();
676
677 const QVariant showIconsOnPushButtonsValue = readKdeSetting(QStringLiteral("KDE/ShowIconsOnPushButtons"), kdeDirs, kdeVersion, kdeSettings);
678 if (showIconsOnPushButtonsValue.isValid())
679 showIconsOnPushButtons = showIconsOnPushButtonsValue.toBool();
680
681 const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme"), kdeDirs, kdeVersion, kdeSettings);
682 if (themeValue.isValid())
683 iconThemeName = themeValue.toString();
684
685 const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size"), kdeDirs, kdeVersion, kdeSettings);
686 if (toolBarIconSizeValue.isValid())
687 toolBarIconSize = toolBarIconSizeValue.toInt();
688
689 const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeVersion, kdeSettings);
690 if (toolbarStyleValue.isValid()) {
691 const QString toolBarStyle = toolbarStyleValue.toString();
692 if (toolBarStyle == "TextBesideIcon"_L1)
693 toolButtonStyle = Qt::ToolButtonTextBesideIcon;
694 else if (toolBarStyle == "TextOnly"_L1)
695 toolButtonStyle = Qt::ToolButtonTextOnly;
696 else if (toolBarStyle == "TextUnderIcon"_L1)
697 toolButtonStyle = Qt::ToolButtonTextUnderIcon;
698 }
699
700 const QVariant wheelScrollLinesValue = readKdeSetting(QStringLiteral("KDE/WheelScrollLines"), kdeDirs, kdeVersion, kdeSettings);
701 if (wheelScrollLinesValue.isValid())
702 wheelScrollLines = wheelScrollLinesValue.toInt();
703
704 const QVariant doubleClickIntervalValue = readKdeSetting(QStringLiteral("KDE/DoubleClickInterval"), kdeDirs, kdeVersion, kdeSettings);
705 if (doubleClickIntervalValue.isValid())
706 doubleClickInterval = doubleClickIntervalValue.toInt();
707
708 const QVariant startDragDistValue = readKdeSetting(QStringLiteral("KDE/StartDragDist"), kdeDirs, kdeVersion, kdeSettings);
709 if (startDragDistValue.isValid())
710 startDragDist = startDragDistValue.toInt();
711
712 const QVariant startDragTimeValue = readKdeSetting(QStringLiteral("KDE/StartDragTime"), kdeDirs, kdeVersion, kdeSettings);
713 if (startDragTimeValue.isValid())
714 startDragTime = startDragTimeValue.toInt();
715
716 const QVariant cursorBlinkRateValue = readKdeSetting(QStringLiteral("KDE/CursorBlinkRate"), kdeDirs, kdeVersion, kdeSettings);
717 if (cursorBlinkRateValue.isValid()) {
718 cursorBlinkRate = cursorBlinkRateValue.toInt();
719 cursorBlinkRate = cursorBlinkRate > 0 ? qBound(200, cursorBlinkRate, 2000) : 0;
720 }
721
722 // Read system font, ignore 'smallestReadableFont'
723 if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeVersion, kdeSettings)))
724 resources.fonts[QPlatformTheme::SystemFont] = systemFont;
725 else
727
728 if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeVersion, kdeSettings))) {
729 resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
730 } else {
732 fixedFont->setStyleHint(QFont::TypeWriter);
733 resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
734 }
735
736 if (QFont *menuFont = kdeFont(readKdeSetting(QStringLiteral("menuFont"), kdeDirs, kdeVersion, kdeSettings))) {
737 resources.fonts[QPlatformTheme::MenuFont] = menuFont;
738 resources.fonts[QPlatformTheme::MenuBarFont] = new QFont(*menuFont);
739 }
740
741 if (QFont *toolBarFont = kdeFont(readKdeSetting(QStringLiteral("toolBarFont"), kdeDirs, kdeVersion, kdeSettings)))
742 resources.fonts[QPlatformTheme::ToolButtonFont] = toolBarFont;
743
745
746 qCDebug(lcQpaFonts) << "default fonts: system" << resources.fonts[QPlatformTheme::SystemFont]
747 << "fixed" << resources.fonts[QPlatformTheme::FixedFont];
748 qDeleteAll(kdeSettings);
749}
750
751QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings)
752{
753 for (const QString &kdeDir : kdeDirs) {
754 QSettings *settings = kdeSettings.value(kdeDir);
755 if (!settings) {
756 const QString kdeGlobalsPath = kdeGlobals(kdeDir, kdeVersion);
757 if (QFileInfo(kdeGlobalsPath).isReadable()) {
758 settings = new QSettings(kdeGlobalsPath, QSettings::IniFormat);
759 kdeSettings.insert(kdeDir, settings);
760 }
761 }
762 if (settings) {
763 const QVariant value = settings->value(key);
764 if (value.isValid())
765 return value;
766 }
767 }
768 return QVariant();
769}
770
771// Reads the color from the KDE configuration, and store it in the
772// palette with the given color role if found.
773static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVariant &value)
774{
775 if (!value.isValid())
776 return false;
777 const QStringList values = value.toStringList();
778 if (values.size() != 3)
779 return false;
780 pal->setBrush(role, QColor(values.at(0).toInt(), values.at(1).toInt(), values.at(2).toInt()));
781 return true;
782}
783
784void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal)
785{
786 if (!kdeColor(pal, QPalette::Button, readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings))) {
787 // kcolorscheme.cpp: SetDefaultColors
788 const QColor defaultWindowBackground(214, 210, 208);
789 const QColor defaultButtonBackground(223, 220, 217);
790 *pal = QPalette(defaultButtonBackground, defaultWindowBackground);
791 return;
792 }
793
794 kdeColor(pal, QPalette::Window, readKdeSetting(QStringLiteral("Colors:Window/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
795 kdeColor(pal, QPalette::Text, readKdeSetting(QStringLiteral("Colors:View/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
796 kdeColor(pal, QPalette::WindowText, readKdeSetting(QStringLiteral("Colors:Window/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
797 kdeColor(pal, QPalette::Base, readKdeSetting(QStringLiteral("Colors:View/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
798 kdeColor(pal, QPalette::Highlight, readKdeSetting(QStringLiteral("Colors:Selection/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
799 kdeColor(pal, QPalette::HighlightedText, readKdeSetting(QStringLiteral("Colors:Selection/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
800 kdeColor(pal, QPalette::AlternateBase, readKdeSetting(QStringLiteral("Colors:View/BackgroundAlternate"), kdeDirs, kdeVersion, kdeSettings));
801 kdeColor(pal, QPalette::ButtonText, readKdeSetting(QStringLiteral("Colors:Button/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
802 kdeColor(pal, QPalette::Link, readKdeSetting(QStringLiteral("Colors:View/ForegroundLink"), kdeDirs, kdeVersion, kdeSettings));
803 kdeColor(pal, QPalette::LinkVisited, readKdeSetting(QStringLiteral("Colors:View/ForegroundVisited"), kdeDirs, kdeVersion, kdeSettings));
804 kdeColor(pal, QPalette::ToolTipBase, readKdeSetting(QStringLiteral("Colors:Tooltip/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
805 kdeColor(pal, QPalette::ToolTipText, readKdeSetting(QStringLiteral("Colors:Tooltip/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
806
807 // The above code sets _all_ color roles to "normal" colors. In KDE, the disabled
808 // color roles are calculated by applying various effects described in kdeglobals.
809 // We use a bit simpler approach here, similar logic than in qt_palette_from_color().
810 const QColor button = pal->color(QPalette::Button);
811 int h, s, v;
812 button.getHsv(&h, &s, &v);
813
814 const QBrush whiteBrush = QBrush(Qt::white);
815 const QBrush buttonBrush = QBrush(button);
816 const QBrush buttonBrushDark = QBrush(button.darker(v > 128 ? 200 : 50));
817 const QBrush buttonBrushDark150 = QBrush(button.darker(v > 128 ? 150 : 75));
818 const QBrush buttonBrushLight150 = QBrush(button.lighter(v > 128 ? 150 : 75));
819 const QBrush buttonBrushLight = QBrush(button.lighter(v > 128 ? 200 : 50));
820
821 pal->setBrush(QPalette::Disabled, QPalette::WindowText, buttonBrushDark);
822 pal->setBrush(QPalette::Disabled, QPalette::ButtonText, buttonBrushDark);
823 pal->setBrush(QPalette::Disabled, QPalette::Button, buttonBrush);
824 pal->setBrush(QPalette::Disabled, QPalette::Text, buttonBrushDark);
826 pal->setBrush(QPalette::Disabled, QPalette::Base, buttonBrush);
827 pal->setBrush(QPalette::Disabled, QPalette::Window, buttonBrush);
828 pal->setBrush(QPalette::Disabled, QPalette::Highlight, buttonBrushDark150);
829 pal->setBrush(QPalette::Disabled, QPalette::HighlightedText, buttonBrushLight150);
830
831 // set calculated colors for all groups
832 pal->setBrush(QPalette::Light, buttonBrushLight);
833 pal->setBrush(QPalette::Midlight, buttonBrushLight150);
834 pal->setBrush(QPalette::Mid, buttonBrushDark150);
835 pal->setBrush(QPalette::Dark, buttonBrushDark);
836}
837
846const char *QKdeTheme::name = "kde";
847
848QKdeTheme::QKdeTheme(const QStringList& kdeDirs, int kdeVersion)
849 : QPlatformTheme(new QKdeThemePrivate(kdeDirs,kdeVersion))
850{
851 d_func()->refresh();
852}
853
854QFont *QKdeThemePrivate::kdeFont(const QVariant &fontValue)
855{
856 if (fontValue.isValid()) {
857 // Read font value: Might be a QStringList as KDE stores fonts without quotes.
858 // Also retrieve the family for the constructor since we cannot use the
859 // default constructor of QFont, which accesses QGuiApplication::systemFont()
860 // causing recursion.
861 QString fontDescription;
862 QString fontFamily;
863 if (fontValue.userType() == QMetaType::QStringList) {
864 const QStringList list = fontValue.toStringList();
865 if (!list.isEmpty()) {
866 fontFamily = list.first();
867 fontDescription = list.join(u',');
868 }
869 } else {
870 fontDescription = fontFamily = fontValue.toString();
871 }
872 if (!fontDescription.isEmpty()) {
873 QFont font(fontFamily);
874 if (font.fromString(fontDescription))
875 return new QFont(font);
876 }
877 }
878 return nullptr;
879}
880
881
882QStringList QKdeThemePrivate::kdeIconThemeSearchPaths(const QStringList &kdeDirs)
883{
885 const QString iconPath = QStringLiteral("/share/icons");
886 for (const QString &candidate : kdeDirs) {
887 const QFileInfo fi(candidate + iconPath);
888 if (fi.isDir())
889 paths.append(fi.absoluteFilePath());
890 }
891 return paths;
892}
893
894QVariant QKdeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
895{
896 Q_D(const QKdeTheme);
897 switch (hint) {
899 return QVariant(true);
901 return QVariant(d->showIconsOnPushButtons);
905 return QVariant(d->toolButtonStyle);
907 return QVariant(d->toolBarIconSize);
909 return QVariant(d->iconThemeName);
911 return QVariant(d->iconFallbackThemeName);
913 return QVariant(d->kdeIconThemeSearchPaths(d->kdeDirs));
917 return QVariant(d->styleNames);
919 return QVariant(int(KdeKeyboardScheme));
921 return QVariant(d->singleClick);
923 return QVariant(d->wheelScrollLines);
925 return QVariant(d->doubleClickInterval);
927 return QVariant(d->startDragTime);
929 return QVariant(d->startDragDist);
931 return QVariant(d->cursorBlinkRate);
933 return QVariant(int(HoverEffect));
935 return QVariant(mouseCursorTheme());
937 return QVariant(mouseCursorSize());
938 default:
939 break;
940 }
942}
943
944QIcon QKdeTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions) const
945{
946#if QT_CONFIG(mimetype)
947 return xdgFileIcon(fileInfo);
948#else
949 Q_UNUSED(fileInfo);
950 return QIcon();
951#endif
952}
953
954Qt::ColorScheme QKdeTheme::colorScheme() const
955{
956 return d_func()->m_colorScheme;
957}
958
970void QKdeThemePrivate::updateColorScheme(const QString &themeName)
971{
973 m_colorScheme = Qt::ColorScheme::Light;
974 return;
975 }
977 m_colorScheme = Qt::ColorScheme::Dark;
978 return;
979 }
980
981 if (systemPalette) {
982 if (systemPalette->text().color().lightness() < systemPalette->base().color().lightness()) {
983 m_colorScheme = Qt::ColorScheme::Light;
984 return;
985 }
986 if (systemPalette->text().color().lightness() > systemPalette->base().color().lightness()) {
987 m_colorScheme = Qt::ColorScheme::Dark;
988 return;
989 }
990 }
991
992 m_colorScheme = Qt::ColorScheme::Unknown;
993}
994
995
996const QPalette *QKdeTheme::palette(Palette type) const
997{
998 Q_D(const QKdeTheme);
999 return d->resources.palettes[type];
1000}
1001
1002const QFont *QKdeTheme::font(Font type) const
1003{
1004 Q_D(const QKdeTheme);
1005 return d->resources.fonts[type];
1006}
1007
1008QPlatformTheme *QKdeTheme::createKdeTheme()
1009{
1010 const QByteArray kdeVersionBA = qgetenv("KDE_SESSION_VERSION");
1011 const int kdeVersion = kdeVersionBA.toInt();
1012 if (kdeVersion < 4)
1013 return nullptr;
1014
1015 if (kdeVersion > 4)
1016 // Plasma 5 follows XDG spec
1017 // but uses the same config file format:
1019
1020 // Determine KDE prefixes in the following priority order:
1021 // - KDEHOME and KDEDIRS environment variables
1022 // - ~/.kde(<version>)
1023 // - read prefixes from /etc/kde<version>rc
1024 // - fallback to /etc/kde<version>
1025
1026 QStringList kdeDirs;
1027 const QString kdeHomePathVar = QFile::decodeName(qgetenv("KDEHOME"));
1028 if (!kdeHomePathVar.isEmpty())
1029 kdeDirs += kdeHomePathVar;
1030
1031 const QString kdeDirsVar = QFile::decodeName(qgetenv("KDEDIRS"));
1032 if (!kdeDirsVar.isEmpty())
1033 kdeDirs += kdeDirsVar.split(u':', Qt::SkipEmptyParts);
1034
1035 const QString kdeVersionHomePath = QDir::homePath() + "/.kde"_L1 + QLatin1StringView(kdeVersionBA);
1036 if (QFileInfo(kdeVersionHomePath).isDir())
1037 kdeDirs += kdeVersionHomePath;
1038
1039 const QString kdeHomePath = QDir::homePath() + "/.kde"_L1;
1040 if (QFileInfo(kdeHomePath).isDir())
1041 kdeDirs += kdeHomePath;
1042
1043 const QString kdeRcPath = "/etc/kde"_L1 + QLatin1StringView(kdeVersionBA) + "rc"_L1;
1044 if (QFileInfo(kdeRcPath).isReadable()) {
1045 QSettings kdeSettings(kdeRcPath, QSettings::IniFormat);
1046 kdeSettings.beginGroup(QStringLiteral("Directories-default"));
1047 kdeDirs += kdeSettings.value(QStringLiteral("prefixes")).toStringList();
1048 }
1049
1050 const QString kdeVersionPrefix = "/etc/kde"_L1 + QLatin1StringView(kdeVersionBA);
1051 if (QFileInfo(kdeVersionPrefix).isDir())
1052 kdeDirs += kdeVersionPrefix;
1053
1054 kdeDirs.removeDuplicates();
1055 if (kdeDirs.isEmpty()) {
1056 qWarning("Unable to determine KDE dirs");
1057 return nullptr;
1058 }
1059
1060 return new QKdeTheme(kdeDirs, kdeVersion);
1061}
1062
1063#ifndef QT_NO_DBUS
1064QPlatformMenuBar *QKdeTheme::createPlatformMenuBar() const
1065{
1067 return new QDBusMenuBar();
1068 return nullptr;
1069}
1070#endif
1071
1072#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
1073QPlatformSystemTrayIcon *QKdeTheme::createPlatformSystemTrayIcon() const
1074{
1075 if (isDBusTrayAvailable())
1076 return new QDBusTrayIcon();
1077 return nullptr;
1078}
1079#endif
1080
1081#endif // settings
1082
1091const char *QGnomeTheme::name = "gnome";
1092
1094{
1095public:
1098
1099 void configureFonts(const QString &gtkFontName) const
1100 {
1102 const int split = gtkFontName.lastIndexOf(QChar::Space);
1103 float size = QStringView{gtkFontName}.mid(split + 1).toFloat();
1104 QString fontName = gtkFontName.left(split);
1105
1106 systemFont = new QFont(fontName, size);
1109 qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
1110 }
1111
1112 mutable QFont *systemFont = nullptr;
1113 mutable QFont *fixedFont = nullptr;
1114
1115#ifndef QT_NO_DBUS
1117private:
1118 std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
1119 bool initDbus();
1120 void updateColorScheme(const QString &themeName);
1121#endif // QT_NO_DBUS
1122};
1123
1125{
1126#ifndef QT_NO_DBUS
1127 initDbus();
1128#endif // QT_NO_DBUS
1129}
1131{
1132 if (systemFont)
1133 delete systemFont;
1134 if (fixedFont)
1135 delete fixedFont;
1136}
1137
1138#ifndef QT_NO_DBUS
1139bool QGnomeThemePrivate::initDbus()
1140{
1142 Q_ASSERT(dbus);
1143
1144 // Wrap slot in a lambda to avoid inheriting QGnomeThemePrivate from QObject
1145 auto wrapper = [this](QGenericUnixThemeDBusListener::Provider provider,
1147 const QString &value) {
1150 return;
1151 }
1152
1154 updateColorScheme(value);
1155 };
1156
1158}
1159
1160void QGnomeThemePrivate::updateColorScheme(const QString &themeName)
1161{
1162 const auto oldColorScheme = m_colorScheme;
1167 } else {
1169 }
1170
1171 if (oldColorScheme != m_colorScheme)
1173}
1174#endif // QT_NO_DBUS
1175
1178{
1179}
1180
1182{
1183 switch (hint) {
1185 return QVariant(true);
1189 return QVariant(QStringLiteral("Adwaita"));
1191 return QVariant(QStringLiteral("gnome"));
1198 styleNames << QStringLiteral("Fusion") << QStringLiteral("windows");
1199 return QVariant(styleNames);
1200 }
1202 return QVariant(int(GnomeKeyboardScheme));
1204 return QVariant(QChar(0x2022));
1206 return QVariant(int(HoverEffect));
1208 return QVariant::fromValue(
1211 return true;
1213 return QVariant(mouseCursorTheme());
1215 return QVariant(mouseCursorSize());
1216 default:
1217 break;
1218 }
1220}
1221
1222QIcon QGnomeTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions) const
1223{
1224#if QT_CONFIG(mimetype)
1225 return xdgFileIcon(fileInfo);
1226#else
1227 Q_UNUSED(fileInfo);
1228 return QIcon();
1229#endif
1230}
1231
1233{
1234 Q_D(const QGnomeTheme);
1235 if (!d->systemFont)
1236 d->configureFonts(gtkFontName());
1237 switch (type) {
1239 return d->systemFont;
1241 return d->fixedFont;
1242 default:
1243 return nullptr;
1244 }
1245}
1246
1248{
1250}
1251
1252#ifndef QT_NO_DBUS
1254{
1256 return new QDBusMenuBar();
1257 return nullptr;
1258}
1259
1261{
1262 return d_func()->m_colorScheme;
1263}
1264
1265#endif
1266
1267#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
1269{
1270 if (isDBusTrayAvailable())
1271 return new QDBusTrayIcon();
1272 return nullptr;
1273}
1274#endif
1275
1277{
1278 switch (button) {
1280 return QCoreApplication::translate("QGnomeTheme", "&OK");
1282 return QCoreApplication::translate("QGnomeTheme", "&Save");
1284 return QCoreApplication::translate("QGnomeTheme", "&Cancel");
1286 return QCoreApplication::translate("QGnomeTheme", "&Close");
1288 return QCoreApplication::translate("QGnomeTheme", "Close without Saving");
1289 default:
1290 break;
1291 }
1293}
1294
1300{
1302 return new QGenericUnixTheme;
1303#if QT_CONFIG(settings)
1304 if (name == QLatin1StringView(QKdeTheme::name))
1305 if (QPlatformTheme *kdeTheme = QKdeTheme::createKdeTheme())
1306 return kdeTheme;
1307#endif
1309 return new QGnomeTheme;
1310 return nullptr;
1311}
1312
1314{
1318 QList<QByteArray> gtkBasedEnvironments;
1319 gtkBasedEnvironments << "GNOME"
1320 << "X-CINNAMON"
1321 << "UNITY"
1322 << "MATE"
1323 << "XFCE"
1324 << "LXDE";
1325 const QList<QByteArray> desktopNames = desktopEnvironment.split(':');
1326 for (const QByteArray &desktopName : desktopNames) {
1327 if (desktopEnvironment == "KDE") {
1328#if QT_CONFIG(settings)
1329 result.push_back(QLatin1StringView(QKdeTheme::name));
1330#endif
1331 } else if (gtkBasedEnvironments.contains(desktopName)) {
1332 // prefer the GTK3 theme implementation with native dialogs etc.
1333 result.push_back(QStringLiteral("gtk3"));
1334 // fallback to the generic Gnome theme if loading the GTK3 theme fails
1336 } else {
1337 // unknown, but lowercase the name (our standard practice) and
1338 // remove any "x-" prefix
1339 QString s = QString::fromLatin1(desktopName.toLower());
1340 result.push_back(s.startsWith("x-"_L1) ? s.mid(2) : s);
1341 }
1342 }
1343 } // desktopSettingsAware
1345 return result;
1346}
1347
1349
1350#ifndef QT_NO_DBUS
1351#include "qgenericunixthemes.moc"
1352#endif // QT_NO_DBUS
\inmodule QtGui
Definition qbrush.h:30
const QColor & color() const
Returns the brush color.
Definition qbrush.h:121
\inmodule QtCore
Definition qbytearray.h:57
int toInt(bool *ok=nullptr, int base=10) const
Returns the byte array converted to an int using base base, which is ten by default.
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays.
\inmodule QtCore
Definition qchar.h:48
@ Space
Definition qchar.h:56
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
int lightness() const noexcept
Definition qcolor.cpp:1860
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
\inmodule QtDBus
static QDBusConnection sessionBus()
Returns a QDBusConnection object opened with the session bus.
\inmodule QtDBus
static QString homePath()
Returns the absolute path of the user's home directory.
Definition qdir.cpp:2100
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString absoluteFilePath() const
Returns an absolute path including the file name.
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
Definition qfile.h:162
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
bool isEmpty() const noexcept
Definition qflatmap_p.h:579
size_type count() const noexcept
Definition qflatmap_p.h:576
bool contains(const Key &key) const
Definition qflatmap_p.h:625
const_iterator constBegin() const
Definition qflatmap_p.h:772
const_iterator constEnd() const
Definition qflatmap_p.h:776
std::pair< iterator, bool > insert(const Key &key, const T &value)
Definition qflatmap_p.h:678
T value(const Key &key, const T &defaultValue) const
Definition qflatmap_p.h:636
void clear()
Definition qflatmap_p.h:591
\reentrant
Definition qfont.h:20
@ TypeWriter
Definition qfont.h:26
bool fromString(const QString &)
Sets this font to match the description descrip.
Definition qfont.cpp:2151
int pointSize() const
Returns the point size of the font.
Definition qfont.cpp:863
void setStyleHint(StyleHint, StyleStrategy=PreferDefault)
Sets the style hint and strategy to hint and strategy, respectively.
Definition qfont.cpp:1482
void settingChanged(QGenericUnixThemeDBusListener::Provider provider, QGenericUnixThemeDBusListener::Setting setting, const QString &value)
static const char * name
QVariant themeHint(ThemeHint hint) const override
static QStringList iconFallbackPaths()
const QFont * font(Font type) const override
QPlatformMenuBar * createPlatformMenuBar() const override
static QPlatformTheme * createUnixTheme(const QString &name)
Creates a UNIX theme according to the detected desktop environment.
QPlatformSystemTrayIcon * createPlatformSystemTrayIcon() const override
Factory function for QSystemTrayIcon.
static QStringList xdgIconThemePaths()
static QStringList themeNames()
Qt::ColorScheme m_colorScheme
void configureFonts(const QString &gtkFontName) const
QGnomeTheme is a theme implementation for the Gnome desktop.
QPlatformMenuBar * createPlatformMenuBar() const override
virtual QString gtkFontName() const
QVariant themeHint(ThemeHint hint) const override
QPlatformSystemTrayIcon * createPlatformSystemTrayIcon() const override
Factory function for QSystemTrayIcon.
QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions={ }) const override
Return an icon for fileInfo, observing iconOptions.
Qt::ColorScheme colorScheme() const override
QString standardButtonText(int button) const override
Returns the text of a standard button.
static const char * name
const QFont * font(Font type) const override
static QPlatformIntegration * platformIntegration()
static bool desktopSettingsAware()
Returns true if Qt is set to use the system's standard colors, fonts, etc.; otherwise returns false.
\inmodule QtCore
Definition qhash.h:818
T value(const Key &key) const noexcept
Definition qhash.h:1044
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:973
QList< QSize > availableSizes(Mode mode=Normal, State state=Off) const
Definition qicon.cpp:1098
static QIcon fromTheme(const QString &name)
Definition qicon.cpp:1296
\inmodule QtCore\reentrant
Definition qjsonarray.h:18
const_iterator constBegin() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the array.
Definition qjsonarray.h:182
const_iterator constEnd() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
Definition qjsonarray.h:186
qsizetype count() const
Same as size().
Definition qjsonarray.h:42
void append(const QJsonValue &value)
Inserts value at the end of the array.
\inmodule QtCore\reentrant
QByteArray toJson(JsonFormat format=Indented) const
QJsonObject object() const
Returns the QJsonObject contained in the document.
bool isObject() const
Returns true if the document contains an object.
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=nullptr)
Parses json as a UTF-8 encoded JSON document, and creates a QJsonDocument from it.
\inmodule QtCore\reentrant
Definition qjsonobject.h:20
bool contains(const QString &key) const
Returns true if the object contains key key.
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
T & first()
Definition qlist.h:628
void push_back(parameter_type t)
Definition qlist.h:672
\inmodule QtCore
QMimeType mimeTypeForFile(const QString &fileName, MatchMode mode=MatchDefault) const
Returns a MIME type for the file named fileName using mode.
\inmodule QtCore
Definition qmimetype.h:25
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
const QBrush & text() const
Returns the text foreground brush of the current color group.
Definition qpalette.h:87
const QColor & color(ColorGroup cg, ColorRole cr) const
Returns the color in the specified color group, used for the given color role.
Definition qpalette.h:66
void setBrush(ColorRole cr, const QBrush &brush)
Sets the brush for the given color role to the specified brush for all groups in the palette.
Definition qpalette.h:150
@ Disabled
Definition qpalette.h:48
const QBrush & base() const
Returns the base brush of the current color group.
Definition qpalette.h:88
@ HighlightedText
Definition qpalette.h:52
@ ToolTipBase
Definition qpalette.h:56
@ BrightText
Definition qpalette.h:51
@ AlternateBase
Definition qpalette.h:54
@ ButtonText
Definition qpalette.h:51
@ WindowText
Definition qpalette.h:50
@ Highlight
Definition qpalette.h:52
@ ToolTipText
Definition qpalette.h:56
@ Midlight
Definition qpalette.h:50
@ LinkVisited
Definition qpalette.h:53
virtual QPlatformServices * services() const
virtual QByteArray desktopEnvironment() const
QPlatformServices::desktopEnvironment returns the active desktop environment.
The QPlatformTheme class allows customizing the UI based on themes.
virtual QVariant themeHint(ThemeHint hint) const
virtual QString standardButtonText(int button) const
Returns the text of a standard button.
ThemeHint
This enum describes the available theme hints.
@ DialogButtonBoxButtonsHaveIcons
@ ItemViewActivateItemOnSingleClick
\inmodule QtCore
Definition qsettings.h:30
QVariant value(QAnyStringView key, const QVariant &defaultValue) const
Returns the value for setting key.
\inmodule QtCore
Definition qsize.h:25
static QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options=LocateFile)
[0]
static QStringList standardLocations(StandardLocation type)
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:7956
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
float toFloat(bool *ok=nullptr) const
Returns the string converted to a float value.
Definition qstring.cpp:7688
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.h:1217
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
\inmodule QtCore
Definition qvariant.h:64
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
int userType() const
Definition qvariant.h:336
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
QStringList toStringList() const
Returns the variant as a QStringList if the variant has userType() \l QMetaType::QStringList,...
static void handleThemeChange(QWindow *window=nullptr)
QPalette * palettes[QPlatformTheme::NPalettes]
QFont * fonts[QPlatformTheme::NFonts]
QPushButton * button
[2]
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
auto signal
Combined button and popup list for selecting options.
ColorScheme
Definition qnamespace.h:49
@ white
Definition qnamespace.h:30
@ Key_Select
@ Key_Return
Definition qnamespace.h:662
@ Key_Enter
Definition qnamespace.h:663
@ Key_Space
Definition qnamespace.h:512
@ CaseInsensitive
@ SkipEmptyParts
Definition qnamespace.h:127
@ ToolButtonTextOnly
@ ToolButtonTextUnderIcon
@ ToolButtonTextBesideIcon
constexpr bool operator<(const timespec &t1, const timespec &t2)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char * interface
DBusConnection const char DBusError * error
DBusConnection * connection
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
const char * mimeType
#define LOG
static bool isDBusGlobalMenuAvailable()
#define CHECK(cond, warning)
static const char defaultFixedFontNameC[]
@ defaultSystemFontSize
static const char defaultSystemFontNameC[]
static QString mouseCursorTheme()
static bool isDBusTrayAvailable()
static QList< QSize > availableXdgFileIconSizes()
#define PARSE(var, enumeration, string)
static bool checkDBusGlobalMenuAvailable()
static QSize mouseCursorSize()
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
#define Q_LOGGING_CATEGORY(name,...)
#define qCInfo(category,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
return ret
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
#define SLOT(a)
Definition qobjectdefs.h:51
static QString themeName()
GLint location
GLenum GLsizei GLsizei GLint * values
[15]
GLsizei const GLfloat * v
[13]
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLenum type
GLsizei const GLuint * paths
GLenum const void * fontName
GLuint name
GLfloat GLfloat GLfloat GLfloat h
GLhandleARB obj
[2]
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static void split(QT_FT_Vector *b)
#define QStringLiteral(str)
static QT_BEGIN_NAMESPACE QVariant hint(QPlatformIntegration::StyleHint h)
QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define Q_ENUM(x)
#define Q_OBJECT
#define Q_SLOTS
#define Q_SIGNALS
#define emit
#define Q_UNUSED(x)
static QStringList styleNames()
QList< int > list
[14]
QFile file
[0]
QFileInfo fi("c:/temp/foo")
[newstuff]
QSettings settings("MySoft", "Star Runner")
[0]
QSharedPointer< T > other(t)
[5]
void dbus()
[0-0]
\inmodule QtCore\reentrant
bool contains(const AT &t) const noexcept
Definition qlist.h:44
void wrapper()