diff options
Diffstat (limited to 'src/gui/platform/unix/qgnomeportalinterface.cpp')
| -rw-r--r-- | src/gui/platform/unix/qgnomeportalinterface.cpp | 175 |
1 files changed, 175 insertions, 0 deletions
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 <private/qdbusplatformmenu_p.h> +#include <QtDBus/QDBusMessage> +#include <QtDBus/QDBusPendingCall> +#include <QtDBus/QDBusReply> +#include <QtDBus/QDBusVariant> + +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<QString, QVariantMap> arg = qdbus_cast<QMap<QString, QVariantMap>>(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<Qt::ColorScheme>()); + break; + case QDBusListener::Setting::Contrast: + updateContrast(value.value<Qt::ContrastPreference>()); + break; + case QDBusListener::Setting::Theme: + emit themeNameChanged(value.toString()); + break; + default: + break; + } +} + +QT_END_NAMESPACE + +#include "moc_qgnomeportalinterface_p.cpp" |
