diff options
Diffstat (limited to 'src/gui/platform/unix/qgenericunixthemes.cpp')
-rw-r--r-- | src/gui/platform/unix/qgenericunixthemes.cpp | 155 |
1 files changed, 150 insertions, 5 deletions
diff --git a/src/gui/platform/unix/qgenericunixthemes.cpp b/src/gui/platform/unix/qgenericunixthemes.cpp index d90d5de098..1efd759bcf 100644 --- a/src/gui/platform/unix/qgenericunixthemes.cpp +++ b/src/gui/platform/unix/qgenericunixthemes.cpp @@ -41,6 +41,9 @@ #include <algorithm> QT_BEGIN_NAMESPACE +#ifndef QT_NO_DBUS +Q_LOGGING_CATEGORY(lcQpaThemeDBus, "qt.qpa.theme.dbus") +#endif using namespace Qt::StringLiterals; @@ -98,7 +101,92 @@ static bool isDBusGlobalMenuAvailable() static bool dbusGlobalMenuAvailable = checkDBusGlobalMenuAvailable(); return dbusGlobalMenuAvailable; } -#endif + +/*! + * \internal + * The QGenericUnixThemeDBusListener class listens to the SettingChanged DBus signal + * and translates it into the QDbusSettingType enum. + * Upon construction, it logs success/failure of the DBus connection. + * + * The signal settingChanged delivers the normalized setting type and the new value as a string. + * It is emitted on known setting types only. + */ + +class QGenericUnixThemeDBusListener : public QObject +{ + Q_OBJECT + +public: + QGenericUnixThemeDBusListener(const QString &service, const QString &path, const QString &interface, const QString &signal); + + enum class SettingType { + KdeGlobalTheme, + KdeApplicationStyle, + Unknown + }; + Q_ENUM(SettingType) + + static SettingType toSettingType(const QString &location, const QString &key); + +private Q_SLOTS: + void onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value); + +Q_SIGNALS: + void settingChanged(QGenericUnixThemeDBusListener::SettingType type, const QString &value); + +}; + +QGenericUnixThemeDBusListener::QGenericUnixThemeDBusListener(const QString &service, + const QString &path, const QString &interface, const QString &signal) +{ + QDBusConnection dbus = QDBusConnection::sessionBus(); + const bool dBusRunning = dbus.isConnected(); + bool dBusSignalConnected = false; +#define LOG service << path << interface << signal; + + if (dBusRunning) { + qRegisterMetaType<QDBusVariant>(); + dBusSignalConnected = dbus.connect(service, path, interface, signal, this, + SLOT(onSettingChanged(QString,QString,QDBusVariant))); + } + + if (dBusSignalConnected) { + // Connection successful + qCDebug(lcQpaThemeDBus) << LOG; + } else { + if (dBusRunning) { + // DBus running, but connection failed + qCWarning(lcQpaThemeDBus) << "DBus connection failed:" << LOG; + } else { + // DBus not running + qCWarning(lcQpaThemeDBus) << "Session DBus not running."; + } + qCWarning(lcQpaThemeDBus) << "Application will not react to KDE setting changes.\n" + << "Check your DBus installation."; + } +#undef LOG +} + +QGenericUnixThemeDBusListener::SettingType QGenericUnixThemeDBusListener::toSettingType( + const QString &location, const QString &key) +{ + if (location == QLatin1StringView("org.kde.kdeglobals.KDE") + && key == QLatin1StringView("widgetStyle")) + return SettingType::KdeApplicationStyle; + if (location == QLatin1StringView("org.kde.kdeglobals.General") + && key == QLatin1StringView("ColorScheme")) + return SettingType::KdeGlobalTheme; + return SettingType::Unknown; +} + +void QGenericUnixThemeDBusListener::onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value) +{ + const SettingType type = toSettingType(location, key); + if (type != SettingType::Unknown) + emit settingChanged(type, value.variant().toString()); +} + +#endif //QT_NO_DBUS class QGenericUnixThemePrivate : public QPlatformThemePrivate { @@ -231,11 +319,9 @@ static QIcon xdgFileIcon(const QFileInfo &fileInfo) #if QT_CONFIG(settings) class QKdeThemePrivate : public QPlatformThemePrivate { + public: - QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion) - : kdeDirs(kdeDirs) - , kdeVersion(kdeVersion) - { } + QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion); static QString kdeGlobals(const QString &kdeDir, int kdeVersion) { @@ -266,8 +352,59 @@ public: int startDragDist = 10; int startDragTime = 500; int cursorBlinkRate = 1000; + +#ifndef QT_NO_DBUS +private: + std::unique_ptr<QGenericUnixThemeDBusListener> dbus; + bool initDbus(); + void settingChangedHandler(QGenericUnixThemeDBusListener::SettingType type, const QString &value); +#endif // QT_NO_DBUS }; +#ifndef QT_NO_DBUS +void QKdeThemePrivate::settingChangedHandler(QGenericUnixThemeDBusListener::SettingType type, const QString &value) +{ + switch (type) { + case QGenericUnixThemeDBusListener::SettingType::KdeGlobalTheme: + qCDebug(lcQpaThemeDBus) << "KDE global theme changed to:" << value; + break; + case QGenericUnixThemeDBusListener::SettingType::KdeApplicationStyle: + qCDebug(lcQpaThemeDBus) << "KDE application style changed to:" << value; + break; + case QGenericUnixThemeDBusListener::SettingType::Unknown: + Q_UNREACHABLE(); + } + + refresh(); +} + +bool QKdeThemePrivate::initDbus() +{ + constexpr QLatin1StringView service(""); + constexpr QLatin1StringView path("/org/freedesktop/portal/desktop"); + constexpr QLatin1StringView interface("org.freedesktop.portal.Settings"); + constexpr QLatin1StringView signal("SettingChanged"); + + dbus.reset(new QGenericUnixThemeDBusListener(service, path, interface, signal)); + Q_ASSERT(dbus); + + // Wrap slot in a lambda to avoid inheriting QKdeThemePrivate from QObject + auto wrapper = [this](QGenericUnixThemeDBusListener::SettingType type, const QString &value) { + settingChangedHandler(type, value); + }; + + return QObject::connect(dbus.get(), &QGenericUnixThemeDBusListener::settingChanged, wrapper); +} +#endif // QT_NO_DBUS + +QKdeThemePrivate::QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion) + : kdeDirs(kdeDirs), kdeVersion(kdeVersion) +{ +#ifndef QT_NO_DBUS + initDbus(); +#endif // QT_NO_DBUS +} + void QKdeThemePrivate::refresh() { resources.clear(); @@ -368,6 +505,8 @@ void QKdeThemePrivate::refresh() if (QFont *toolBarFont = kdeFont(readKdeSetting(QStringLiteral("toolBarFont"), kdeDirs, kdeVersion, kdeSettings))) resources.fonts[QPlatformTheme::ToolButtonFont] = toolBarFont; + QWindowSystemInterface::handleThemeChange(); + qCDebug(lcQpaFonts) << "default fonts: system" << resources.fonts[QPlatformTheme::SystemFont] << "fixed" << resources.fonts[QPlatformTheme::FixedFont]; qDeleteAll(kdeSettings); @@ -726,6 +865,8 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const case QPlatformTheme::ButtonPressKeys: return QVariant::fromValue( QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Return, Qt::Key_Enter, Qt::Key_Select })); + case QPlatformTheme::PreselectFirstFileInDirectory: + return true; default: break; } @@ -853,3 +994,7 @@ QStringList QGenericUnixTheme::themeNames() } QT_END_NAMESPACE + +#ifndef QT_NO_DBUS +#include "qgenericunixthemes.moc" +#endif // QT_NO_DBUS |