diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 024bcfab426..db7c0590611 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -1059,6 +1059,11 @@ qt_internal_extend_target(Gui CONDITION UNIX AND (QT_FEATURE_xcb OR NOT MACOS) A platform/unix/qgnometheme_p.h platform/unix/qgnometheme.cpp ) +qt_internal_extend_target(Gui CONDITION UNIX AND QT_FEATURE_dbus AND (QT_FEATURE_xcb OR QT_FEATURE_wayland) + SOURCES + platform/unix/qgnomeportalinterface.cpp platform/unix/qgnomeportalinterface_p.h +) + qt_internal_extend_target(Gui CONDITION TARGET Qt::DBus AND UNIX AND (QT_FEATURE_xcb OR NOT MACOS) AND (QT_FEATURE_xcb OR NOT UIKIT) SOURCES platform/unix/dbusmenu/qdbusmenuadaptor.cpp platform/unix/dbusmenu/qdbusmenuadaptor_p.h @@ -1068,6 +1073,7 @@ qt_internal_extend_target(Gui CONDITION TARGET Qt::DBus AND UNIX AND (QT_FEATURE platform/unix/dbusmenu/qdbusmenutypes.cpp platform/unix/dbusmenu/qdbusmenutypes_p.h platform/unix/dbusmenu/qdbusplatformmenu.cpp platform/unix/dbusmenu/qdbusplatformmenu_p.h platform/unix/qdbuslistener_p.h platform/unix/qdbuslistener.cpp + platform/unix/qdbussettings_p.h platform/unix/qdbussettings.cpp ) qt_internal_extend_target(Gui CONDITION QT_FEATURE_systemtrayicon AND TARGET Qt::DBus AND UNIX AND (QT_FEATURE_xcb OR NOT MACOS) AND (QT_FEATURE_xcb OR NOT UIKIT) diff --git a/src/gui/platform/unix/qdbuslistener.cpp b/src/gui/platform/unix/qdbuslistener.cpp index 374b3a0f8ec..5057931b12d 100644 --- a/src/gui/platform/unix/qdbuslistener.cpp +++ b/src/gui/platform/unix/qdbuslistener.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qdbuslistener_p.h" +#include "qdbussettings_p.h" #include #include #include @@ -48,38 +49,6 @@ constexpr auto setting() { return "Setting"_L1; } constexpr auto dbusSignals() { return "DbusSignals"_L1; } constexpr auto root() { return "Q_L1.qpa.DBusSignals"_L1; } } // namespace JsonKeys - -namespace XdgSettings { -// XDG Desktop Portal Settings (Preferred) -// https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Settings.html -constexpr auto contrastNamespace = "org.freedesktop.appearance"_L1; -constexpr auto contrastKey = "contrast"_L1; -// XDG portal provides the contrast preference value as uint: -// 0 for no-preference, and, 1 for high-contrast. -Qt::ContrastPreference convertContrastPreference(const QVariant &value) -{ - if (!value.isValid()) - return Qt::ContrastPreference::NoPreference; - return static_cast(value.toUInt()); -} -} // namespace XdgSettings - -namespace GSettings { -// GNOME Destop Settings (Alternative) -// https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2069 -// https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/-/commit/0e97f1f571c495184f80d875c68f241261a50e30 -constexpr auto contrastNamespace = "org.gnome.desktop.a11y.interface"_L1; -constexpr auto contrastKey = "high-contrast"_L1; -// GSetting provides the contrast value as boolean: -// true for enabled high-contrast, and, false for disabled high-contrast. -Qt::ContrastPreference convertContrastPreference(const QVariant &value) -{ - if (!value.isValid()) - return Qt::ContrastPreference::NoPreference; - return value.toBool() ? Qt::ContrastPreference::HighContrast - : Qt::ContrastPreference::NoPreference; -} -} // namespace GSettings } // namespace void QDBusListener::init(const QString &service, const QString &path, @@ -237,14 +206,15 @@ void QDBusListener::populateSignalMap() m_signalMap.insert(DBusKey("org.gnome.desktop.interface"_L1, "gtk-theme"_L1), ChangeSignal(Provider::Gtk, Setting::Theme)); - m_signalMap.insert(DBusKey("org.freedesktop.appearance"_L1, "color-scheme"_L1), + using namespace QDBusSettings; + m_signalMap.insert(DBusKey(XdgSettings::AppearanceNamespace, XdgSettings::ColorSchemeKey), ChangeSignal(Provider::Gnome, Setting::ColorScheme)); - m_signalMap.insert(DBusKey(XdgSettings::contrastNamespace, XdgSettings::contrastKey), + m_signalMap.insert(DBusKey(XdgSettings::AppearanceNamespace, XdgSettings::ContrastKey), ChangeSignal(Provider::Gnome, Setting::Contrast)); // Alternative solution if XDG desktop portal setting is not accessible, // e.g. when using the XDG portal version 1. - m_signalMap.insert(DBusKey(GSettings::contrastNamespace, GSettings::contrastKey), + m_signalMap.insert(DBusKey(GnomeSettings::AllyNamespace, GnomeSettings::ContrastKey), ChangeSignal(Provider::Gnome, Setting::Contrast)); const QString &saveJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS_SAVE"); @@ -274,13 +244,17 @@ void QDBusListener::onSettingChanged(const QString &location, const QString &key QVariant settingValue = value.variant(); switch (setting) { + case Setting::ColorScheme: + settingValue.setValue(QDBusSettings::XdgSettings::convertColorScheme(settingValue)); + break; case Setting::Contrast: + using namespace QDBusSettings; // To unify the value, it's necessary to convert the DBus value to Qt::ContrastPreference. // Then the users of the value don't need to parse the raw value. - if (key == XdgSettings::contrastKey) + if (key == XdgSettings::ContrastKey) settingValue.setValue(XdgSettings::convertContrastPreference(settingValue)); - else if (key == GSettings::contrastKey) - settingValue.setValue(GSettings::convertContrastPreference(settingValue)); + else if (key == GnomeSettings::ContrastKey) + settingValue.setValue(GnomeSettings::convertContrastPreference(settingValue)); else Q_UNREACHABLE_IMPL(); break; diff --git a/src/gui/platform/unix/qdbussettings.cpp b/src/gui/platform/unix/qdbussettings.cpp new file mode 100644 index 00000000000..8d5f5d972bc --- /dev/null +++ b/src/gui/platform/unix/qdbussettings.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qdbussettings_p.h" +#include + +QT_BEGIN_NAMESPACE + +namespace QDBusSettings::XdgSettings { +// https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Settings.html +enum class ColorScheme : uint { NoPreference, PreferDark, PreferLight }; +} // namespace QDBusSettings::XdgSettings + +Qt::ContrastPreference QDBusSettings::XdgSettings::convertContrastPreference(const QVariant &value) +{ + // XDG portal provides the contrast preference value as uint: + // 0 for no-preference, and, 1 for high-contrast. + if (!value.isValid()) + return Qt::ContrastPreference::NoPreference; + return static_cast(value.toUInt()); +} + +Qt::ColorScheme QDBusSettings::XdgSettings::convertColorScheme(const QVariant &value) +{ + switch (ColorScheme{ value.toUInt() }) { + case ColorScheme::NoPreference: + return Qt::ColorScheme::Unknown; + case ColorScheme::PreferDark: + return Qt::ColorScheme::Dark; + case ColorScheme::PreferLight: + return Qt::ColorScheme::Light; + } + Q_UNREACHABLE_RETURN(Qt::ColorScheme::Unknown); +} + +Qt::ContrastPreference +QDBusSettings::GnomeSettings::convertContrastPreference(const QVariant &value) +{ + // GSetting provides the contrast value as boolean: + // true for enabled high-contrast, and, false for disabled high-contrast. + if (!value.isValid()) + return Qt::ContrastPreference::NoPreference; + return value.toBool() ? Qt::ContrastPreference::HighContrast + : Qt::ContrastPreference::NoPreference; +} + +QT_END_NAMESPACE diff --git a/src/gui/platform/unix/qdbussettings_p.h b/src/gui/platform/unix/qdbussettings_p.h new file mode 100644 index 00000000000..7d7ea476464 --- /dev/null +++ b/src/gui/platform/unix/qdbussettings_p.h @@ -0,0 +1,46 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QDBUSSETTINGS_P_H +#define QDBUSSETTINGS_P_H + +#include +#include +QT_REQUIRE_CONFIG(dbus); + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +namespace QDBusSettings { +// XDG Desktop Portal Settings (Preferred) +// https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Settings.html +namespace XdgSettings { +static constexpr QLatin1StringView AppearanceNamespace{ "org.freedesktop.appearance" }; +static constexpr QLatin1StringView ColorSchemeKey{ "color-scheme" }; +static constexpr QLatin1StringView ContrastKey{ "contrast" }; +Qt::ContrastPreference convertContrastPreference(const QVariant &value); +Qt::ColorScheme convertColorScheme(const QVariant &value); +} // namespace XdgSettings + +namespace GnomeSettings { +// GNOME Destop Settings (Alternative) +// https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2069 +// https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/-/commit/0e97f1f571c495184f80d875c68f241261a50e30 +static constexpr QLatin1StringView AllyNamespace{ "org.gnome.desktop.a11y.interface" }; +static constexpr QLatin1StringView ContrastKey{ "high-contrast" }; +Qt::ContrastPreference convertContrastPreference(const QVariant &value); +} // namespace GnomeSettings +} // namespace QDBusSettings + +QT_END_NAMESPACE +#endif // QDBUSSETTINGS_P_H diff --git a/src/gui/platform/unix/qgnomeportalinterface.cpp b/src/gui/platform/unix/qgnomeportalinterface.cpp new file mode 100644 index 00000000000..8528ed19328 --- /dev/null +++ b/src/gui/platform/unix/qgnomeportalinterface.cpp @@ -0,0 +1,175 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qgnomeportalinterface_p.h" +#include "qdbussettings_p.h" +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#if QT_CONFIG(dbus) +Q_STATIC_LOGGING_CATEGORY(lcQpaThemeGnome, "qt.qpa.theme.gnome") +#endif // QT_CONFIG(dbus) + +using namespace Qt::StringLiterals; + +QGnomePortalInterface::QGnomePortalInterface(QObject *parent) + : QObject(parent), m_dbus{ new QDBusListener } +{ + QObject::connect(m_dbus.get(), &QDBusListener::settingChanged, this, + &QGnomePortalInterface::dbusSettingChanged); + + querySettings(); +} + +/*! + \internal + \brief QGnomePortalInterface::colorScheme + This is a getter method for the color-scheme loaded from the DBus portal. + \param fallback indicates the fallback color-scheme. + \return returns the cached color-scheme. If the color-scheme was not loaded + it returns the \a fallback color-scheme. + */ +Qt::ColorScheme QGnomePortalInterface::colorScheme(Qt::ColorScheme fallback) const +{ + if (!m_colorScheme.has_value()) + return fallback; + return m_colorScheme.value(); +} + +/*! + \internal + \brief QGnomePortalInterface::contrastPreference + This is a getter method for the contrast-preference loaded from the DBus portal. + \param fallback indicates the fallback contrast-preference. + \return returns the cached contrast-preference if it was loaded. Otherwise, + returns the \a fallback contrast-preference. + */ +Qt::ContrastPreference +QGnomePortalInterface::contrastPreference(Qt::ContrastPreference fallback) const +{ + if (!m_contrast.has_value()) + return fallback; + return m_contrast.value(); +} + +void QGnomePortalInterface::querySettings() +{ + QDBusConnection dbus = QDBusConnection::sessionBus(); + if (!dbus.isConnected()) { + qCWarning(lcQpaThemeGnome) << "dbus connection failed. Last error: " << dbus.lastError(); + return; + } + + constexpr auto method = "ReadAll"_L1; + auto message = QDBusMessage::createMethodCall(s_service, s_path, s_interface, method); + + message << QStringList{ QDBusSettings::XdgSettings::AppearanceNamespace, + QDBusSettings::GnomeSettings::AllyNamespace }; + + QDBusPendingCall pendingCall = dbus.asyncCall(message); + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this); + + auto onWatcherFinished = [&](QDBusPendingCallWatcher *watcher) { + const QDBusMessage reply = watcher->reply(); + if (QDBusMessage::ErrorMessage == reply.type()) { + qCWarning(lcQpaThemeGnome) + << "dbus reply error: [" << reply.errorName() << "]" << reply.errorMessage(); + watcher->deleteLater(); + return; + } + + const auto convertXdgColorScheme = [](const QVariant &value) { + using namespace QDBusSettings::XdgSettings; + return QVariant::fromValue(convertColorScheme(value)); + }; + + constexpr auto XdgContrastKey = QDBusSettings::XdgSettings::ContrastKey; + const auto convertXdgContrast = [](const QVariant &value) { + using namespace QDBusSettings::XdgSettings; + return QVariant::fromValue(convertContrastPreference(value)); + }; + + constexpr auto GnomeContrastKey = QDBusSettings::GnomeSettings::ContrastKey; + const auto convrtGnomeContrast = [](const QVariant &value) { + using namespace QDBusSettings::GnomeSettings; + return QVariant::fromValue(convertContrastPreference(value)); + }; + + const QVariantList &args = reply.arguments(); + for (const QVariant &arg_ : args) { + const QMap arg = qdbus_cast>(arg_); + for (auto aIt = arg.begin(); aIt != arg.end(); ++aIt) { + const QString &namespace_ = aIt.key(); + const QVariantMap &settings = aIt.value(); + for (auto sIt = settings.begin(); sIt != settings.end(); ++sIt) { + const QString &key = sIt.key(); + const QVariant &value = sIt.value(); + if ((key == QDBusSettings::XdgSettings::ColorSchemeKey) + && (namespace_ == QDBusSettings::XdgSettings::AppearanceNamespace)) + dbusSettingChanged(QDBusListener::Provider::Gnome, + QDBusListener::Setting::ColorScheme, + convertXdgColorScheme(value)); + else if ((key == XdgContrastKey) + && (namespace_ == QDBusSettings::XdgSettings::AppearanceNamespace)) + dbusSettingChanged(QDBusListener::Provider::Gnome, + QDBusListener::Setting::Contrast, + convertXdgContrast(value)); + else if ((key == GnomeContrastKey) + && (namespace_ == QDBusSettings::GnomeSettings::AllyNamespace)) + dbusSettingChanged(QDBusListener::Provider::Gnome, + QDBusListener::Setting::Contrast, + convrtGnomeContrast(value)); + } + } + } + watcher->deleteLater(); + }; + connect(watcher, &QDBusPendingCallWatcher::finished, this, onWatcherFinished); +} + +void QGnomePortalInterface::updateColorScheme(Qt::ColorScheme colorScheme) +{ + if (m_colorScheme.has_value() && (m_colorScheme.value() == colorScheme)) + return; + m_colorScheme = colorScheme; + emit colorSchemeChanged(colorScheme); +} + +void QGnomePortalInterface::updateContrast(Qt::ContrastPreference contrast) +{ + if (m_contrast.has_value() && (m_contrast.value() == contrast)) + return; + m_contrast = contrast; + emit contrastChanged(contrast); +} + +void QGnomePortalInterface::dbusSettingChanged(QDBusListener::Provider provider, + QDBusListener::Setting setting, + const QVariant &value) +{ + if (provider != QDBusListener::Provider::Gnome && provider != QDBusListener::Provider::Gtk) + return; + + switch (setting) { + case QDBusListener::Setting::ColorScheme: + updateColorScheme(value.value()); + break; + case QDBusListener::Setting::Contrast: + updateContrast(value.value()); + break; + case QDBusListener::Setting::Theme: + emit themeNameChanged(value.toString()); + break; + default: + break; + } +} + +QT_END_NAMESPACE + +#include "moc_qgnomeportalinterface_p.cpp" diff --git a/src/gui/platform/unix/qgnomeportalinterface_p.h b/src/gui/platform/unix/qgnomeportalinterface_p.h new file mode 100644 index 00000000000..4dee4f310f5 --- /dev/null +++ b/src/gui/platform/unix/qgnomeportalinterface_p.h @@ -0,0 +1,63 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QGNOMEPORTALINTERFACE_P_H +#define QGNOMEPORTALINTERFACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +QT_REQUIRE_CONFIG(dbus); + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QGnomePortalInterface : public QObject +{ + Q_OBJECT + +public: + QGnomePortalInterface(QObject *parent = nullptr); + ~QGnomePortalInterface() = default; + + Qt::ColorScheme colorScheme(Qt::ColorScheme fallback = Qt::ColorScheme::Unknown) const; + Qt::ContrastPreference contrastPreference( + Qt::ContrastPreference fallback = Qt::ContrastPreference::NoPreference) const; + +private: + void querySettings(); + void updateColorScheme(Qt::ColorScheme colorScheme); + void updateContrast(Qt::ContrastPreference contrast); + +Q_SIGNALS: + void colorSchemeChanged(Qt::ColorScheme); + void contrastChanged(Qt::ContrastPreference); + void themeNameChanged(const QString &themeName); + +private Q_SLOTS: + void dbusSettingChanged(QDBusListener::Provider, QDBusListener::Setting, const QVariant &value); + +private: + mutable uint m_version = 0; // cached version value + std::optional m_colorScheme; + std::optional m_contrast; + std::unique_ptr m_dbus; + static constexpr QLatin1StringView s_service{ "org.freedesktop.portal.Desktop" }; + static constexpr QLatin1StringView s_path{ "/org/freedesktop/portal/desktop" }; + static constexpr QLatin1StringView s_interface{ "org.freedesktop.portal.Settings" }; +}; + +QT_END_NAMESPACE + +#endif // QGNOMEPORTALINTERFACE_P_H diff --git a/src/gui/platform/unix/qgnometheme.cpp b/src/gui/platform/unix/qgnometheme.cpp index 389ea0238aa..a9fb85e15bc 100644 --- a/src/gui/platform/unix/qgnometheme.cpp +++ b/src/gui/platform/unix/qgnometheme.cpp @@ -5,163 +5,13 @@ #include #include #if QT_CONFIG(dbus) -#include "qdbuslistener_p.h" -#include -#include -#include -#include -#include -#include -#include -#include +# include +# include #endif #include QT_BEGIN_NAMESPACE -#if QT_CONFIG(dbus) -Q_STATIC_LOGGING_CATEGORY(lcQpaThemeGnome, "qt.qpa.theme.gnome") - -using namespace Qt::StringLiterals; - -namespace { -// https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Settings.html -enum class XDG_ColorScheme : uint { NoPreference, PreferDark, PreferLight }; - -constexpr Qt::ColorScheme convertColorScheme(XDG_ColorScheme colorScheme) -{ - switch (colorScheme) { - case XDG_ColorScheme::NoPreference: - return Qt::ColorScheme::Unknown; - case XDG_ColorScheme::PreferDark: - return Qt::ColorScheme::Dark; - case XDG_ColorScheme::PreferLight: - return Qt::ColorScheme::Light; - default: - Q_UNREACHABLE_RETURN(Qt::ColorScheme::Unknown); - break; - } -} - -constexpr XDG_ColorScheme convertColorScheme(Qt::ColorScheme colorScheme) -{ - switch (colorScheme) { - case Qt::ColorScheme::Unknown: - return XDG_ColorScheme::NoPreference; - case Qt::ColorScheme::Light: - return XDG_ColorScheme::PreferLight; - case Qt::ColorScheme::Dark: - return XDG_ColorScheme::PreferDark; - default: - Q_UNREACHABLE_RETURN(XDG_ColorScheme::NoPreference); - break; - } -} - -class DBusInterface -{ - DBusInterface() = delete; - - constexpr static auto Service = "org.freedesktop.portal.Desktop"_L1; - constexpr static auto Path = "/org/freedesktop/portal/desktop"_L1; - -public: - static inline QVariant query(QLatin1StringView interface, QLatin1StringView method, - QLatin1StringView name_space, QLatin1StringView key); - static inline uint queryPortalVersion(); - static inline QLatin1StringView readOneMethod(); - static inline std::optional queryColorScheme(); - static inline std::optional queryContrast(); -}; - -QVariant DBusInterface::query(QLatin1StringView interface, QLatin1StringView method, - QLatin1StringView name_space, QLatin1StringView key) -{ - QDBusConnection dbus = QDBusConnection::sessionBus(); - if (dbus.isConnected()) { - QDBusMessage message = QDBusMessage::createMethodCall( - DBusInterface::Service, DBusInterface::Path, interface, method); - message << name_space << key; - - QDBusReply reply = dbus.call(message); - if (Q_LIKELY(reply.isValid())) - return reply.value(); - } else { - qCWarning(lcQpaThemeGnome) << "dbus connection failed. Last error: " << dbus.lastError(); - } - - return {}; -} - -uint DBusInterface::queryPortalVersion() -{ - constexpr auto interface = "org.freedesktop.DBus.Properties"_L1; - constexpr auto method = "Get"_L1; - constexpr auto name_space = "org.freedesktop.portal.Settings"_L1; - constexpr auto key = "version"_L1; - - static uint version = 0; // cached version value - - if (version == 0) { - QVariant reply = query(interface, method, name_space, key); - if (reply.isValid()) - version = reply.toUInt(); // caches the value for the next calls - } - - return version; -} - -QLatin1StringView DBusInterface::readOneMethod() -{ - // Based on the documentation on flatpak: - // https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Settings.html - // The method name "Read" has changed to "ReadOne" since version 2. - const uint version = queryPortalVersion(); - if (version == 1) - return "Read"_L1; - return "ReadOne"_L1; -} - -std::optional DBusInterface::queryColorScheme() -{ - constexpr auto interface = "org.freedesktop.portal.Settings"_L1; - constexpr auto name_space = "org.freedesktop.appearance"_L1; - constexpr auto key = "color-scheme"_L1; - const auto method = readOneMethod(); - - QVariant reply = query(interface, method, name_space, key); - if (reply.isValid()) - return convertColorScheme( - XDG_ColorScheme{ reply.value().variant().toUInt() }); - - return {}; -} - -std::optional DBusInterface::queryContrast() -{ - constexpr auto interface = "org.freedesktop.portal.Settings"_L1; - const auto method = readOneMethod(); - - constexpr auto namespace_xdg_portal = "org.freedesktop.appearance"_L1; - constexpr auto key_xdg_portal = "contrast"_L1; - QVariant reply = query(interface, method, namespace_xdg_portal, key_xdg_portal); - if (reply.isValid()) - return static_cast(reply.toUInt()); - - // Fall back to desktop-specific methods (GSettings for GNOME) - constexpr auto namespace_gsettings = "org.gnome.desktop.a11y.interface"_L1; - constexpr auto key_gsettings = "high-contrast"_L1; - reply = query(interface, method, namespace_gsettings, key_gsettings); - if (reply.isValid()) - return reply.toBool() ? Qt::ContrastPreference::HighContrast - : Qt::ContrastPreference::NoPreference; - - return {}; -} -} // namespace - -#endif // QT_CONFIG(dbus) - /*! \class QGnomeTheme \brief QGnomeTheme is a theme implementation for the Gnome desktop. @@ -174,13 +24,8 @@ const char *QGnomeTheme::name = "gnome"; QGnomeThemePrivate::QGnomeThemePrivate() { #if QT_CONFIG(dbus) - initDbus(); - - if (auto value = DBusInterface::queryColorScheme(); value.has_value()) - updateColorScheme(value.value()); - - if (auto value = DBusInterface::queryContrast(); value.has_value()) - updateHighContrast(value.value()); + QObject::connect(&m_gnomePortal, &QGnomePortalInterface::themeNameChanged, &m_gnomePortal, + [this](const QString &themeName) { m_themeName = themeName; }); #endif // QT_CONFIG(dbus) } @@ -205,43 +50,15 @@ void QGnomeThemePrivate::configureFonts(const QString >kFontName) const qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont; } -#if QT_CONFIG(dbus) -bool QGnomeThemePrivate::initDbus() -{ - dbus.reset(new QDBusListener()); - Q_ASSERT(dbus); - - // Wrap slot in a lambda to avoid inheriting QGnomeThemePrivate from QObject - auto wrapper = [this](QDBusListener::Provider provider, - QDBusListener::Setting setting, - const QVariant &value) { - if (provider != QDBusListener::Provider::Gnome - && provider != QDBusListener::Provider::Gtk) { - return; - } - - switch (setting) { - case QDBusListener::Setting::ColorScheme: - updateColorScheme(convertColorScheme(XDG_ColorScheme{ value.toUInt() })); - break; - case QDBusListener::Setting::Theme: - m_themeName = value.toString(); - break; - case QDBusListener::Setting::Contrast: - updateHighContrast(value.value()); - break; - default: - break; - } - }; - - return QObject::connect(dbus.get(), &QDBusListener::settingChanged, dbus.get(), wrapper); -} - Qt::ColorScheme QGnomeThemePrivate::colorScheme() const { - if (m_colorScheme != Qt::ColorScheme::Unknown) - return m_colorScheme; + if (hasRequestedColorScheme()) + return m_requestedColorScheme; + +#if QT_CONFIG(dbus) + if (Qt::ColorScheme colorScheme = m_gnomePortal.colorScheme(); + colorScheme != Qt::ColorScheme::Unknown) + return colorScheme; // If the color scheme is set to Unknown by mistake or is not set at all, // then maybe the theme name contains a hint about the color scheme. @@ -251,31 +68,31 @@ Qt::ColorScheme QGnomeThemePrivate::colorScheme() const return Qt::ColorScheme::Light; else if (m_themeName.contains(QLatin1StringView("dark"), Qt::CaseInsensitive)) return Qt::ColorScheme::Dark; - else - return Qt::ColorScheme::Unknown; -} - -void QGnomeThemePrivate::updateColorScheme(Qt::ColorScheme colorScheme) -{ - if (m_colorScheme == colorScheme) - return; - m_colorScheme = colorScheme; - QWindowSystemInterface::handleThemeChange(); -} - -void QGnomeThemePrivate::updateHighContrast(Qt::ContrastPreference contrast) -{ - if (m_contrast == contrast) - return; - m_contrast = contrast; - QWindowSystemInterface::handleThemeChange(); -} - #endif // QT_CONFIG(dbus) + // Fallback to Unknown if no color scheme is set or detected + return Qt::ColorScheme::Unknown; +} + +bool QGnomeThemePrivate::hasRequestedColorScheme() const +{ + return m_requestedColorScheme != Qt::ColorScheme::Unknown; +} + QGnomeTheme::QGnomeTheme() : QGenericUnixTheme(new QGnomeThemePrivate()) { +#if QT_CONFIG(dbus) + Q_D(QGnomeTheme); + + QGnomePortalInterface *portal = &d->m_gnomePortal; + + QObject::connect(portal, &QGnomePortalInterface::colorSchemeChanged, portal, + [this](Qt::ColorScheme colorScheme) { updateColorScheme(colorScheme); }); + + QObject::connect(portal, &QGnomePortalInterface::contrastChanged, portal, + [this](Qt::ContrastPreference contrast) { updateHighContrast(contrast); }); +#endif // QT_CONFIG(dbus) } QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const @@ -352,7 +169,38 @@ QString QGnomeTheme::gtkFontName() const .arg(defaultSystemFontSize); } +void QGnomeTheme::requestColorScheme(Qt::ColorScheme scheme) +{ + Q_D(QGnomeTheme); + if (d->m_requestedColorScheme == scheme) + return; + QPlatformTheme::requestColorScheme(scheme); + d->m_requestedColorScheme = scheme; + QWindowSystemInterface::handleThemeChange(); +} + +Qt::ColorScheme QGnomeTheme::colorScheme() const +{ + Q_D(const QGnomeTheme); + if (auto colorScheme = d->colorScheme(); colorScheme != Qt::ColorScheme::Unknown) + return colorScheme; + // If the color scheme is not set or detected, fall back to the default + return QPlatformTheme::colorScheme(); +} + #if QT_CONFIG(dbus) +void QGnomeTheme::updateColorScheme(Qt::ColorScheme colorScheme) +{ + Q_UNUSED(colorScheme); + QWindowSystemInterface::handleThemeChange(); +} + +void QGnomeTheme::updateHighContrast(Qt::ContrastPreference contrast) +{ + Q_UNUSED(contrast); + QWindowSystemInterface::handleThemeChange(); +} + QPlatformMenuBar *QGnomeTheme::createPlatformMenuBar() const { if (isDBusGlobalMenuAvailable()) @@ -360,26 +208,21 @@ QPlatformMenuBar *QGnomeTheme::createPlatformMenuBar() const return nullptr; } -Qt::ColorScheme QGnomeTheme::colorScheme() const -{ - return d_func()->colorScheme(); -} - Qt::ContrastPreference QGnomeTheme::contrastPreference() const { - return d_func()->m_contrast; + Q_D(const QGnomeTheme); + return d->m_gnomePortal.contrastPreference(); } -#endif - -#if QT_CONFIG(dbus) && QT_CONFIG(systemtrayicon) +# if QT_CONFIG(systemtrayicon) QPlatformSystemTrayIcon *QGnomeTheme::createPlatformSystemTrayIcon() const { if (shouldUseDBusTray()) return new QDBusTrayIcon(); return nullptr; } -#endif +# endif // QT_CONFIG(systemtrayicon) +#endif // QT_CONFIG(dbus) QString QGnomeTheme::standardButtonText(int button) const { diff --git a/src/gui/platform/unix/qgnometheme_p.h b/src/gui/platform/unix/qgnometheme_p.h index 9c59646c715..17b91931876 100644 --- a/src/gui/platform/unix/qgnometheme_p.h +++ b/src/gui/platform/unix/qgnometheme_p.h @@ -19,17 +19,19 @@ #include #include #include +#if QT_CONFIG(dbus) +# include "qgnomeportalinterface_p.h" +#endif // QT_CONFIG(dbus) QT_BEGIN_NAMESPACE + class QGnomeThemePrivate; -#if QT_CONFIG(dbus) -class QDBusListener; -class QDBusPendingCallWatcher; -#endif class Q_GUI_EXPORT QGnomeTheme : public QGenericUnixTheme { +protected: Q_DECLARE_PRIVATE(QGnomeTheme) + public: QGnomeTheme(); QVariant themeHint(ThemeHint hint) const override; @@ -39,47 +41,51 @@ public: QString standardButtonText(int button) const override; virtual QString gtkFontName() const; + + virtual void requestColorScheme(Qt::ColorScheme) override; + virtual Qt::ColorScheme colorScheme() const override; + #if QT_CONFIG(dbus) +protected: + virtual void updateColorScheme(Qt::ColorScheme); + virtual void updateHighContrast(Qt::ContrastPreference); + +public: QPlatformMenuBar *createPlatformMenuBar() const override; - Qt::ColorScheme colorScheme() const override; Qt::ContrastPreference contrastPreference() const override; -#endif -#if QT_CONFIG(dbus) && QT_CONFIG(systemtrayicon) + +# if QT_CONFIG(systemtrayicon) QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override; -#endif +# endif // QT_CONFIG(systemtrayicon) +#endif // QT_CONFIG(dbus) static const char *name; }; -class QGnomeThemePrivate : public QGenericUnixThemePrivate +class Q_GUI_EXPORT QGnomeThemePrivate : public QGenericUnixThemePrivate { + friend QGnomeTheme; + public: QGnomeThemePrivate(); ~QGnomeThemePrivate(); void configureFonts(const QString >kFontName) const; + Qt::ColorScheme colorScheme() const; + bool hasRequestedColorScheme() const; + +private: mutable QFont *systemFont = nullptr; mutable QFont *fixedFont = nullptr; + Qt::ColorScheme m_requestedColorScheme = Qt::ColorScheme::Unknown; + #if QT_CONFIG(dbus) - Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown; - Qt::ContrastPreference m_contrast = Qt::ContrastPreference::NoPreference; -private: - std::unique_ptr dbus; - std::unique_ptr pendingCallWatcher; + QGnomePortalInterface m_gnomePortal; QString m_themeName; - -public: - Qt::ColorScheme colorScheme() const; - -private: - bool initDbus(); - void updateColorScheme(Qt::ColorScheme colorScheme); - void updateHighContrast(Qt::ContrastPreference contrast); #endif // QT_CONFIG(dbus) }; - QT_END_NAMESPACE #endif // QGNOMETHEME_P_H diff --git a/src/gui/platform/unix/qkdetheme.cpp b/src/gui/platform/unix/qkdetheme.cpp index c3de0213780..ef1f9b3455c 100644 --- a/src/gui/platform/unix/qkdetheme.cpp +++ b/src/gui/platform/unix/qkdetheme.cpp @@ -130,7 +130,7 @@ void QKdeThemePrivate::settingChangedHandler(QDBusListener::Provider provider, switch (setting) { case QDBusListener::Setting::ColorScheme: - qCDebug(lcQpaThemeKde) << "KDE color theme changed to:" << value.toUInt(); + qCDebug(lcQpaThemeKde) << "KDE color theme changed to:" << value.value(); break; case QDBusListener::Setting::Theme: qCDebug(lcQpaThemeKde) << "KDE global theme changed to:" << value.toString(); diff --git a/src/plugins/platformthemes/gtk3/CMakeLists.txt b/src/plugins/platformthemes/gtk3/CMakeLists.txt index 40c425d367a..6b0613b42fb 100644 --- a/src/plugins/platformthemes/gtk3/CMakeLists.txt +++ b/src/plugins/platformthemes/gtk3/CMakeLists.txt @@ -37,8 +37,6 @@ qt_internal_add_plugin(QGtk3ThemePlugin ) qt_internal_extend_target(QGtk3ThemePlugin CONDITION QT_FEATURE_dbus - SOURCES - qgtk3portalinterface.cpp LIBRARIES Qt::DBus ) diff --git a/src/plugins/platformthemes/gtk3/qgtk3portalinterface.cpp b/src/plugins/platformthemes/gtk3/qgtk3portalinterface.cpp deleted file mode 100644 index 1ffdda74fa8..00000000000 --- a/src/plugins/platformthemes/gtk3/qgtk3portalinterface.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2024 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qgtk3portalinterface_p.h" -#include "qgtk3storage_p.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(lcQGtk3PortalInterface, "qt.qpa.gtk"); - -using namespace Qt::StringLiterals; - -static constexpr QLatin1StringView appearanceInterface("org.freedesktop.appearance"); -static constexpr QLatin1StringView colorSchemeKey("color-scheme"); - -const QDBusArgument &operator>>(const QDBusArgument &argument, QMap &map) -{ - argument.beginMap(); - map.clear(); - - while (!argument.atEnd()) { - QString key; - QVariantMap value; - argument.beginMapEntry(); - argument >> key >> value; - argument.endMapEntry(); - map.insert(key, value); - } - - argument.endMap(); - return argument; -} - -QGtk3PortalInterface::QGtk3PortalInterface(QGtk3Storage *s) - : m_storage(s) { - qRegisterMetaType(); - qDBusRegisterMetaType>(); - - queryColorScheme(); - - if (!s) { - qCDebug(lcQGtk3PortalInterface) << "QGtk3PortalInterface instantiated without QGtk3Storage." - << "No reaction to runtime theme changes."; - } -} - -Qt::ColorScheme QGtk3PortalInterface::colorScheme() const -{ - return m_colorScheme; -} - -void QGtk3PortalInterface::queryColorScheme() { - QDBusConnection connection = QDBusConnection::sessionBus(); - QDBusMessage message = QDBusMessage::createMethodCall( - "org.freedesktop.portal.Desktop"_L1, - "/org/freedesktop/portal/desktop"_L1, - "org.freedesktop.portal.Settings"_L1, "ReadAll"_L1); - message << QStringList{ appearanceInterface }; - - QDBusPendingCall pendingCall = connection.asyncCall(message); - QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall, this); - QObject::connect( - watcher, &QDBusPendingCallWatcher::finished, this, - [this](QDBusPendingCallWatcher *watcher) { - QDBusPendingReply> reply = *watcher; - if (reply.isValid()) { - QMap settings = reply.value(); - if (!settings.isEmpty()) { - settingChanged(appearanceInterface, colorSchemeKey, - QDBusVariant(settings.value(appearanceInterface).value(colorSchemeKey))); - } - } else { - qCDebug(lcQGtk3PortalInterface) << "Failed to query org.freedesktop.portal.Settings: " - << reply.error().message(); - } - watcher->deleteLater(); - }); - - QDBusConnection::sessionBus().connect( - "org.freedesktop.portal.Desktop"_L1, "/org/freedesktop/portal/desktop"_L1, - "org.freedesktop.portal.Settings"_L1, "SettingChanged"_L1, this, - SLOT(settingChanged(QString, QString, QDBusVariant))); -} - -void QGtk3PortalInterface::settingChanged(const QString &group, const QString &key, - const QDBusVariant &value) -{ - if (group == appearanceInterface && key == colorSchemeKey) { - const uint colorScheme = value.variant().toUInt(); - // From org.freedesktop.portal.Settings.xml - // "1" - Prefer dark appearance - Qt::ColorScheme newColorScheme = colorScheme == 1 ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light; - if (m_colorScheme != newColorScheme) { - m_colorScheme = newColorScheme; - if (m_storage) - m_storage->handleThemeChange(); - } - } -} - -QT_END_NAMESPACE - -#include "moc_qgtk3portalinterface_p.cpp" diff --git a/src/plugins/platformthemes/gtk3/qgtk3portalinterface_p.h b/src/plugins/platformthemes/gtk3/qgtk3portalinterface_p.h deleted file mode 100644 index 25a5f58ab1a..00000000000 --- a/src/plugins/platformthemes/gtk3/qgtk3portalinterface_p.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2024 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -#ifndef QGTK3PORTALINTERFACE_H -#define QGTK3PORTALINTERFACE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - -class QDBusVariant; -class QGtk3Storage; - -Q_DECLARE_LOGGING_CATEGORY(lcQGtk3PortalInterface); - -class QGtk3PortalInterface : public QObject -{ - Q_OBJECT -public: - QGtk3PortalInterface(QGtk3Storage *s); - ~QGtk3PortalInterface() = default; - - Qt::ColorScheme colorScheme() const; - -private Q_SLOTS: - void settingChanged(const QString &group, const QString &key, - const QDBusVariant &value); -private: - void queryColorScheme(); - - Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown; - QGtk3Storage *m_storage = nullptr; -}; - -QT_END_NAMESPACE - -#endif // QGTK3PORTALINTERFACE_H diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp index 2991212d033..ae4502183da 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3storage.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3storage.cpp @@ -15,6 +15,9 @@ #include "qgtk3json_p.h" #include "qgtk3storage_p.h" #include +#if QT_CONFIG(dbus) +# include +#endif QT_BEGIN_NAMESPACE @@ -22,11 +25,13 @@ QGtk3Storage::QGtk3Storage() { m_interface.reset(new QGtk3Interface(this)); #if QT_CONFIG(dbus) - m_portalInterface.reset(new QGtk3PortalInterface(this)); + m_portalInterface.reset(new QGnomePortalInterface); #endif populateMap(); } +QGtk3Storage::~QGtk3Storage() { } + /*! \internal \enum QGtk3Storage::SourceType diff --git a/src/plugins/platformthemes/gtk3/qgtk3storage_p.h b/src/plugins/platformthemes/gtk3/qgtk3storage_p.h index 002e916377e..d0668a97216 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3storage_p.h +++ b/src/plugins/platformthemes/gtk3/qgtk3storage_p.h @@ -16,9 +16,6 @@ // #include "qgtk3interface_p.h" -#if QT_CONFIG(dbus) -#include "qgtk3portalinterface_p.h" -#endif #include #include @@ -30,11 +27,17 @@ #include QT_BEGIN_NAMESPACE + +#if QT_CONFIG(dbus) +class QGnomePortalInterface; +#endif + class QGtk3Storage { Q_GADGET public: QGtk3Storage(); + ~QGtk3Storage(); // Enum documented in cpp file. Please keep it in line with updates made here. enum class SourceType { @@ -242,7 +245,7 @@ private: std::unique_ptr m_interface; #if QT_CONFIG(dbus) - std::unique_ptr m_portalInterface; + std::unique_ptr m_portalInterface; #endif Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown; diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp index c1c1e623a27..c720fc41dbd 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3theme.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3theme.cpp @@ -163,29 +163,34 @@ QString QGtk3Theme::gtkFontName() const return QGnomeTheme::gtkFontName(); } -void QGtk3Theme::requestColorScheme(Qt::ColorScheme scheme) -{ - if (m_requestedColorScheme == scheme) - return; - qCDebug(lcQGtk3Interface) << scheme << "has been requested. Theme supports color scheme:" - << m_storage->colorScheme(); - QPlatformTheme::requestColorScheme(scheme); - m_requestedColorScheme = scheme; - m_storage->handleThemeChange(); -} - Qt::ColorScheme QGtk3Theme::colorScheme() const { Q_ASSERT(m_storage); + + Q_D(const QGnomeTheme); + const Qt::ColorScheme colorScheme = d->colorScheme(); + const bool hasRequestedColorScheme = d->hasRequestedColorScheme(); + #ifdef QT_DEBUG - if (m_requestedColorScheme != Qt::ColorScheme::Unknown - && m_requestedColorScheme != m_storage->colorScheme()) { - qCDebug(lcQGtk3Interface) << "Requested color scheme" << m_requestedColorScheme + if (hasRequestedColorScheme && colorScheme != m_storage->colorScheme()) { + qCDebug(lcQGtk3Interface) << "Requested color scheme" << colorScheme << "differs from theme color scheme" << m_storage->colorScheme(); } #endif - return m_requestedColorScheme == Qt::ColorScheme::Unknown ? m_storage->colorScheme() - : m_requestedColorScheme; + + return hasRequestedColorScheme ? colorScheme : m_storage->colorScheme(); +} + +void QGtk3Theme::requestColorScheme(Qt::ColorScheme scheme) +{ + const Qt::ColorScheme oldColorScheme = colorScheme(); + QGnomeTheme::requestColorScheme(scheme); + if (oldColorScheme == colorScheme()) + return; + qCDebug(lcQGtk3Interface) << scheme << "has been requested. Theme supports color scheme:" + << m_storage->colorScheme(); + m_storage->handleThemeChange(); + QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents); } bool QGtk3Theme::usePlatformNativeDialog(DialogType type) const @@ -234,18 +239,22 @@ bool QGtk3Theme::useNativeFileDialog() const QPalette *QGtk3Theme::palette(Palette type) const { Q_ASSERT(m_storage); + + Q_D(const QGnomeTheme); + const Qt::ColorScheme colorScheme = d->colorScheme(); + const bool hasRequestedColorScheme = d->hasRequestedColorScheme(); + #ifdef QT_DEBUG - if (m_requestedColorScheme != Qt::ColorScheme::Unknown - && m_requestedColorScheme != m_storage->colorScheme()) { + if (hasRequestedColorScheme && colorScheme != m_storage->colorScheme()) { qCDebug(lcQGtk3Interface) << "Current KDE theme doesn't support requested color scheme" - << m_requestedColorScheme << "Falling back to fusion palette."; + << colorScheme << "Falling back to fusion palette."; return QPlatformTheme::palette(type); } #endif - return (m_requestedColorScheme != Qt::ColorScheme::Unknown - && m_requestedColorScheme != m_storage->colorScheme()) - ? QPlatformTheme::palette(type) : m_storage->palette(type); + return (hasRequestedColorScheme && colorScheme != m_storage->colorScheme()) + ? QPlatformTheme::palette(type) + : m_storage->palette(type); } QPixmap QGtk3Theme::standardPixmap(StandardPixmap sp, const QSizeF &size) const @@ -268,4 +277,14 @@ QIcon QGtk3Theme::fileIcon(const QFileInfo &fileInfo, return m_storage->fileIcon(fileInfo); } +#if QT_CONFIG(dbus) +void QGtk3Theme::updateColorScheme(Qt::ColorScheme newColorScheme) +{ + if (newColorScheme == colorScheme()) + QGnomeTheme::updateColorScheme(newColorScheme); + else + m_storage->handleThemeChange(); +} +#endif // QT_CONFIG(dbus) + QT_END_NAMESPACE diff --git a/src/plugins/platformthemes/gtk3/qgtk3theme.h b/src/plugins/platformthemes/gtk3/qgtk3theme.h index d2f2efff51f..ce7dc9c9dc8 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3theme.h +++ b/src/plugins/platformthemes/gtk3/qgtk3theme.h @@ -31,8 +31,11 @@ public: QPlatformTheme::IconOptions iconOptions = { }) const override; static const char *name; + private: - Qt::ColorScheme m_requestedColorScheme = Qt::ColorScheme::Unknown; +#if QT_CONFIG(dbus) + void updateColorScheme(Qt::ColorScheme) override; +#endif // QT_CONFIG(dbus) static bool useNativeFileDialog(); std::unique_ptr m_storage; };