File indexing completed on 2024-11-24 05:00:56

0001 /*  This file is part of the KDE libraries
0002     SPDX-FileCopyrightText: 2013 Kevin Ottens <ervin+bluesystems@kde.org>
0003     SPDX-FileCopyrightText: 2013 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0004     SPDX-FileCopyrightText: 2013 Alejandro Fiestas Olivares <afiestas@kde.org>
0005     SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0008 */
0009 
0010 #include "khintssettings.h"
0011 
0012 #include <QApplication>
0013 #include <QDebug>
0014 #include <QDialogButtonBox>
0015 #include <QDir>
0016 #include <QFileInfo>
0017 #include <QGuiApplication>
0018 #include <QMainWindow>
0019 #include <QPalette>
0020 #include <QScreen>
0021 #include <QStandardPaths>
0022 #include <QString>
0023 #include <QTemporaryFile>
0024 #include <QToolBar>
0025 #include <QToolButton>
0026 
0027 #include <QDBusArgument>
0028 #include <QDBusConnection>
0029 #include <QDBusInterface>
0030 
0031 #include <KSandbox>
0032 #include <kcolorscheme.h>
0033 #include <kconfiggroup.h>
0034 #include <kiconloader.h>
0035 
0036 #include <config-platformtheme.h>
0037 #ifdef UNIT_TEST
0038 #undef HAVE_X11
0039 #define HAVE_X11 0
0040 #endif
0041 #if HAVE_X11
0042 #include <QX11Info>
0043 #include <X11/Xcursor/Xcursor.h>
0044 #endif
0045 
0046 static const QString defaultLookAndFeelPackage = QStringLiteral("org.kde.breeze.desktop");
0047 
0048 const QDBusArgument &operator>>(const QDBusArgument &argument, QMap<QString, QVariantMap> &map)
0049 {
0050     argument.beginMap();
0051     map.clear();
0052 
0053     while (!argument.atEnd()) {
0054         QString key;
0055         QVariantMap value;
0056         argument.beginMapEntry();
0057         argument >> key >> value;
0058         argument.endMapEntry();
0059         map.insert(key, value);
0060     }
0061 
0062     argument.endMap();
0063     return argument;
0064 }
0065 
0066 KHintsSettings::KHintsSettings(const KSharedConfig::Ptr &kdeglobals)
0067     : QObject(nullptr)
0068     , mKdeGlobals(kdeglobals)
0069     , mUsePortal(KSandbox::isInside())
0070 {
0071     if (!mKdeGlobals) {
0072         mKdeGlobals = KSharedConfig::openConfig();
0073     }
0074     KConfigGroup cg(mKdeGlobals, "KDE");
0075 
0076     if (mUsePortal) {
0077         updatePortalSetting();
0078     }
0079 
0080     const auto cursorBlinkRate = readConfigValue(cg, QStringLiteral("CursorBlinkRate"), 1000).toInt();
0081     m_hints[QPlatformTheme::CursorFlashTime] = cursorBlinkRate > 0 ? qBound(200, cursorBlinkRate, 2000) : 0; // 0 => no blinking
0082     m_hints[QPlatformTheme::MouseDoubleClickInterval] = readConfigValue(cg, QStringLiteral("DoubleClickInterval"), 400);
0083     m_hints[QPlatformTheme::StartDragDistance] = readConfigValue(cg, QStringLiteral("StartDragDist"), 10);
0084     m_hints[QPlatformTheme::StartDragTime] = readConfigValue(cg, QStringLiteral("StartDragTime"), 500);
0085 
0086     KConfigGroup cgToolbar(mKdeGlobals, "Toolbar style");
0087     m_hints[QPlatformTheme::ToolButtonStyle] = toolButtonStyle(cgToolbar);
0088 
0089     m_hints[QPlatformTheme::ToolBarIconSize] = KIconLoader::global()->currentSize(KIconLoader::MainToolbar);
0090 
0091     m_hints[QPlatformTheme::ItemViewActivateItemOnSingleClick] = readConfigValue(cg, QStringLiteral("SingleClick"), false);
0092 
0093     m_hints[QPlatformTheme::SystemIconThemeName] = readConfigValue(QStringLiteral("Icons"), QStringLiteral("Theme"), QStringLiteral("breeze"));
0094 
0095     m_hints[QPlatformTheme::SystemIconFallbackThemeName] = QStringLiteral("hicolor");
0096     m_hints[QPlatformTheme::IconThemeSearchPaths] = xdgIconThemePaths();
0097 
0098     QStringList styleNames{
0099         QStringLiteral("breeze"),
0100         QStringLiteral("oxygen"),
0101         QStringLiteral("fusion"),
0102         QStringLiteral("windows"),
0103     };
0104     const QString configuredStyle = readConfigValue(cg, QStringLiteral("widgetStyle"), QString()).toString();
0105     if (!configuredStyle.isEmpty()) {
0106         styleNames.removeOne(configuredStyle);
0107         styleNames.prepend(configuredStyle);
0108     }
0109     const QString lnfStyle = readConfigValue(QStringLiteral("KDE"), QStringLiteral("widgetStyle"), QString()).toString();
0110     if (!lnfStyle.isEmpty()) {
0111         styleNames.removeOne(lnfStyle);
0112         styleNames.prepend(lnfStyle);
0113     }
0114     m_hints[QPlatformTheme::StyleNames] = styleNames;
0115 
0116     m_hints[QPlatformTheme::DialogButtonBoxLayout] = QDialogButtonBox::KdeLayout;
0117     m_hints[QPlatformTheme::DialogButtonBoxButtonsHaveIcons] = readConfigValue(cg, QStringLiteral("ShowIconsOnPushButtons"), true);
0118     m_hints[QPlatformTheme::UseFullScreenForPopupMenu] = true;
0119     m_hints[QPlatformTheme::KeyboardScheme] = QPlatformTheme::KdeKeyboardScheme;
0120 
0121     int uiEffectsFlags = readConfigValue(cg, QStringLiteral("GraphicEffectsLevel"), 0) != 0 ? QPlatformTheme::GeneralUiEffect : 0;
0122     uiEffectsFlags |= QPlatformTheme::HoverEffect;
0123     m_hints[QPlatformTheme::UiEffects] = uiEffectsFlags;
0124 
0125     m_hints[QPlatformTheme::IconPixmapSizes] = QVariant::fromValue(QList<int>() << 512 << 256 << 128 << 64 << 32 << 22 << 16 << 8);
0126 
0127     m_hints[QPlatformTheme::WheelScrollLines] = readConfigValue(cg, QStringLiteral("WheelScrollLines"), 3);
0128     if (qobject_cast<QApplication *>(QCoreApplication::instance())) {
0129         QApplication::setWheelScrollLines(readConfigValue(cg, QStringLiteral("WheelScrollLines"), 3).toInt());
0130     }
0131 
0132     updateShowIconsInMenuItems(cg);
0133 
0134     m_hints[QPlatformTheme::ShowShortcutsInContextMenus] = true;
0135 
0136     QMetaObject::invokeMethod(this, "delayedDBusConnects", Qt::QueuedConnection);
0137     QMetaObject::invokeMethod(this, "setupIconLoader", Qt::QueuedConnection);
0138 
0139     loadPalettes();
0140     updateCursorTheme();
0141 }
0142 
0143 KHintsSettings::~KHintsSettings()
0144 {
0145     qDeleteAll(m_palettes);
0146 }
0147 
0148 QVariant KHintsSettings::readConfigValue(const QString &group, const QString &key, const QVariant &defaultValue)
0149 {
0150     KConfigGroup userCg(mKdeGlobals, group);
0151     return readConfigValue(userCg, key, defaultValue);
0152 }
0153 
0154 QVariant KHintsSettings::readConfigValue(const KConfigGroup &cg, const QString &key, const QVariant &defaultValue) const
0155 {
0156     if (mUsePortal) {
0157         const QString settingName = QStringLiteral("org.kde.kdeglobals.%1").arg(cg.name());
0158         auto groupIt = mKdeGlobalsPortal.constFind(settingName);
0159         if (groupIt != mKdeGlobalsPortal.constEnd()) {
0160             auto valueIt = groupIt.value().constFind(key);
0161             if (valueIt != groupIt.value().constEnd()) {
0162                 return valueIt.value();
0163             }
0164         }
0165     }
0166 
0167     return cg.readEntry(key, defaultValue);
0168 }
0169 
0170 QStringList KHintsSettings::xdgIconThemePaths() const
0171 {
0172     QStringList paths;
0173 
0174     // make sure we have ~/.local/share/icons in paths if it exists
0175     paths << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("icons"), QStandardPaths::LocateDirectory);
0176 
0177     const QFileInfo homeIconDir(QDir::homePath() + QStringLiteral("/.icons"));
0178     if (homeIconDir.isDir()) {
0179         paths << homeIconDir.absoluteFilePath();
0180     }
0181 
0182     return paths;
0183 }
0184 
0185 void KHintsSettings::delayedDBusConnects()
0186 {
0187     QDBusConnection::sessionBus()
0188         .connect(QString(), QStringLiteral("/KToolBar"), QStringLiteral("org.kde.KToolBar"), QStringLiteral("styleChanged"), this, SLOT(toolbarStyleChanged()));
0189     QDBusConnection::sessionBus().connect(QString(),
0190                                           QStringLiteral("/KGlobalSettings"),
0191                                           QStringLiteral("org.kde.KGlobalSettings"),
0192                                           QStringLiteral("notifyChange"),
0193                                           this,
0194                                           SLOT(slotNotifyChange(int, int)));
0195     if (mUsePortal) {
0196         QDBusConnection::sessionBus().connect(QString(),
0197                                               QStringLiteral("/org/freedesktop/portal/desktop"),
0198                                               QStringLiteral("org.freedesktop.portal.Settings"),
0199                                               QStringLiteral("SettingChanged"),
0200                                               this,
0201                                               SLOT(slotPortalSettingChanged(QString, QString, QDBusVariant)));
0202     }
0203 }
0204 
0205 void KHintsSettings::setupIconLoader()
0206 {
0207     connect(KIconLoader::global(), &KIconLoader::iconChanged, this, &KHintsSettings::iconChanged);
0208 }
0209 
0210 void KHintsSettings::toolbarStyleChanged()
0211 {
0212     mKdeGlobals->reparseConfiguration();
0213     KConfigGroup cg(mKdeGlobals, "Toolbar style");
0214 
0215     m_hints[QPlatformTheme::ToolButtonStyle] = toolButtonStyle(cg);
0216     // from gtksymbol.cpp
0217     QWidgetList widgets = QApplication::allWidgets();
0218     for (int i = 0; i < widgets.size(); ++i) {
0219         QWidget *widget = widgets.at(i);
0220         if (qobject_cast<QToolButton *>(widget)) {
0221             QEvent event(QEvent::StyleChange);
0222             QApplication::sendEvent(widget, &event);
0223         }
0224     }
0225 }
0226 
0227 void KHintsSettings::slotNotifyChange(int type, int arg)
0228 {
0229     mKdeGlobals->reparseConfiguration();
0230     KConfigGroup cg(mKdeGlobals, "KDE");
0231 
0232     switch (type) {
0233     case PaletteChanged: {
0234         // Don't change the palette if the application has a custom one set
0235         if (!qApp->property("KDE_COLOR_SCHEME_PATH").toString().isEmpty()) {
0236             break;
0237         }
0238         loadPalettes();
0239 
0240         // QApplication::setPalette and QGuiApplication::setPalette are different functions
0241         // and non virtual. Call the correct one
0242         if (qobject_cast<QApplication *>(QCoreApplication::instance())) {
0243             QPalette palette = *m_palettes[QPlatformTheme::SystemPalette];
0244             QApplication::setPalette(palette);
0245             // QTBUG QGuiApplication::paletteChanged() signal is only emitted by QGuiApplication
0246             // so things like SystemPalette QtQuick item that use it won't notice a palette
0247             // change when a QApplication which causes e.g. QML System Settings modules to not update
0248             Q_EMIT qApp->paletteChanged(palette);
0249         } else if (qobject_cast<QGuiApplication *>(QCoreApplication::instance())) {
0250             QGuiApplication::setPalette(*m_palettes[QPlatformTheme::SystemPalette]);
0251         }
0252         break;
0253     }
0254     case SettingsChanged: {
0255         SettingsCategory category = static_cast<SettingsCategory>(arg);
0256         if (category == SETTINGS_QT || category == SETTINGS_MOUSE) {
0257             updateQtSettings(cg);
0258         } else if (category == SETTINGS_STYLE) {
0259             m_hints[QPlatformTheme::DialogButtonBoxButtonsHaveIcons] = cg.readEntry("ShowIconsOnPushButtons", true);
0260             m_hints[QPlatformTheme::UiEffects] = cg.readEntry("GraphicEffectsLevel", 0) != 0 ? QPlatformTheme::GeneralUiEffect : 0;
0261 
0262             updateShowIconsInMenuItems(cg);
0263         }
0264         break;
0265     }
0266     case ToolbarStyleChanged: {
0267         toolbarStyleChanged();
0268         break;
0269     }
0270     case IconChanged:
0271         iconChanged(arg); // Once the KCM is ported to use IconChanged, this should not be needed
0272         break;
0273     case CursorChanged:
0274         updateCursorTheme();
0275         updateX11CursorTheme();
0276         break;
0277     case StyleChanged: {
0278         QApplication *app = qobject_cast<QApplication *>(QCoreApplication::instance());
0279         if (!app) {
0280             return;
0281         }
0282 
0283         // HOTFIX here. Hardcoded default value is duplicated and may be inconsistent with the one actually defined in kcm_style kcfg
0284         const QString theme = readConfigValue(cg, QStringLiteral("widgetStyle"), QStringLiteral("breeze")).toString();
0285 
0286         QStringList styleNames;
0287         if (theme != QStringLiteral("breeze")) {
0288             styleNames << theme;
0289         }
0290         styleNames << QStringLiteral("breeze") << QStringLiteral("oxygen") << QStringLiteral("fusion") << QStringLiteral("windows");
0291         const QString lnfStyle = readConfigValue(QStringLiteral("KDE"), QStringLiteral("widgetStyle"), QString()).toString();
0292         if (!lnfStyle.isEmpty() && !styleNames.contains(lnfStyle)) {
0293             styleNames.prepend(lnfStyle);
0294         }
0295         m_hints[QPlatformTheme::StyleNames] = styleNames;
0296 
0297         app->setStyle(theme);
0298         loadPalettes();
0299         break;
0300     }
0301     default:
0302         qWarning() << "Unknown type of change in KGlobalSettings::slotNotifyChange: " << type;
0303     }
0304 }
0305 
0306 void KHintsSettings::slotPortalSettingChanged(const QString &group, const QString &key, const QDBusVariant &value)
0307 {
0308     if (group == QLatin1String("org.kde.kdeglobals.General") && key == QLatin1String("ColorScheme")) {
0309         // For colors obtain complete configuration again
0310         updatePortalSetting();
0311         slotNotifyChange(PaletteChanged, 0);
0312     } else if (group == QLatin1String("org.kde.kdeglobals.KDE") && key == QLatin1String("widgetStyle")) {
0313         mKdeGlobalsPortal[group][key] = value.variant().toString();
0314         slotNotifyChange(StyleChanged, 0);
0315     } else if (group == QLatin1String("org.kde.kdeglobals.Icons") && key == QLatin1String("Theme")) {
0316         mKdeGlobalsPortal[group][key] = value.variant().toString();
0317         // Change icons for each group
0318         for (int i = 0; i <= 5; ++i) {
0319             iconChanged(i);
0320         }
0321     } else if (group == QLatin1String("org.kde.kdeglobals.Toolbar style") && key == QLatin1String("ToolButtonStyle")) {
0322         mKdeGlobalsPortal[group][key] = value.variant().toString();
0323         toolbarStyleChanged();
0324     }
0325 }
0326 
0327 void KHintsSettings::iconChanged(int group)
0328 {
0329     KIconLoader::Group iconGroup = (KIconLoader::Group)group;
0330     if (iconGroup != KIconLoader::MainToolbar) {
0331         m_hints[QPlatformTheme::SystemIconThemeName] = readConfigValue(QStringLiteral("Icons"), QStringLiteral("Theme"), QStringLiteral("breeze"));
0332         return;
0333     }
0334 
0335     const int currentSize = KIconLoader::global()->currentSize(KIconLoader::MainToolbar);
0336     if (m_hints[QPlatformTheme::ToolBarIconSize] == currentSize) {
0337         return;
0338     }
0339 
0340     m_hints[QPlatformTheme::ToolBarIconSize] = currentSize;
0341 
0342     // If we are not a QApplication, means that we are a QGuiApplication, then we do nothing.
0343     if (!qobject_cast<QApplication *>(QCoreApplication::instance())) {
0344         return;
0345     }
0346 
0347     const QWidgetList widgets = QApplication::allWidgets();
0348     for (QWidget *widget : widgets) {
0349         if (qobject_cast<QToolBar *>(widget) || qobject_cast<QMainWindow *>(widget)) {
0350             QEvent event(QEvent::StyleChange);
0351             QApplication::sendEvent(widget, &event);
0352         }
0353     }
0354 }
0355 
0356 void KHintsSettings::updateQtSettings(KConfigGroup &cg)
0357 {
0358     int flash = qBound(200, cg.readEntry("CursorBlinkRate", 1000), 2000);
0359     m_hints[QPlatformTheme::CursorFlashTime] = flash;
0360 
0361     int doubleClickInterval = cg.readEntry("DoubleClickInterval", 400);
0362     m_hints[QPlatformTheme::MouseDoubleClickInterval] = doubleClickInterval;
0363 
0364     int startDragDistance = cg.readEntry("StartDragDist", 10);
0365     m_hints[QPlatformTheme::StartDragDistance] = startDragDistance;
0366 
0367     int startDragTime = cg.readEntry("StartDragTime", 500);
0368     m_hints[QPlatformTheme::StartDragTime] = startDragTime;
0369 
0370     m_hints[QPlatformTheme::ItemViewActivateItemOnSingleClick] = cg.readEntry("SingleClick", false);
0371 
0372     updateShowIconsInMenuItems(cg);
0373 
0374     int wheelScrollLines = cg.readEntry("WheelScrollLines", 3);
0375     m_hints[QPlatformTheme::WheelScrollLines] = wheelScrollLines;
0376     QApplication *app = qobject_cast<QApplication *>(QCoreApplication::instance());
0377     if (app) {
0378         QApplication::setWheelScrollLines(cg.readEntry("WheelScrollLines", 3));
0379     }
0380 }
0381 
0382 void KHintsSettings::updateShowIconsInMenuItems(KConfigGroup &cg)
0383 {
0384     bool showIcons = readConfigValue(cg, QStringLiteral("ShowIconsInMenuItems"), true).toBool();
0385     QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus, !showIcons);
0386 }
0387 
0388 Qt::ToolButtonStyle KHintsSettings::toolButtonStyle(const KConfigGroup &cg)
0389 {
0390     const QString buttonStyle = readConfigValue(cg, QStringLiteral("ToolButtonStyle"), QStringLiteral("TextBesideIcon")).toString().toLower();
0391     return buttonStyle == QLatin1String("textbesideicon") ? Qt::ToolButtonTextBesideIcon
0392         : buttonStyle == QLatin1String("icontextright")   ? Qt::ToolButtonTextBesideIcon
0393         : buttonStyle == QLatin1String("textundericon")   ? Qt::ToolButtonTextUnderIcon
0394         : buttonStyle == QLatin1String("icontextbottom")  ? Qt::ToolButtonTextUnderIcon
0395         : buttonStyle == QLatin1String("textonly")        ? Qt::ToolButtonTextOnly
0396                                                           : Qt::ToolButtonIconOnly;
0397 }
0398 
0399 void KHintsSettings::loadPalettes()
0400 {
0401     qDeleteAll(m_palettes);
0402     m_palettes.clear();
0403 
0404     if (mUsePortal && mKdeGlobalsPortal.contains(QStringLiteral("org.kde.kdeglobals.Colors:View"))) {
0405         // Construct a temporary KConfig file containing color setting so we can create a KColorScheme from it
0406         QTemporaryFile file;
0407         file.open();
0408 
0409         KSharedConfigPtr tempConfig = KSharedConfig::openConfig(file.fileName(), KConfig::SimpleConfig);
0410         for (auto groupIt = mKdeGlobalsPortal.constBegin(); groupIt != mKdeGlobalsPortal.constEnd(); ++groupIt) {
0411             if (groupIt.key().startsWith(QStringLiteral("org.kde.kdeglobals.Colors:"))) {
0412                 KConfigGroup tempGroup(tempConfig, groupIt.key().right(groupIt.key().length() - QStringLiteral("org.kde.kdeglobals.").length()));
0413                 for (auto valueIt = groupIt.value().constBegin(); valueIt != groupIt.value().constEnd(); ++valueIt) {
0414                     tempGroup.writeEntry(valueIt.key(), valueIt.value());
0415                 }
0416             }
0417         }
0418         m_palettes[QPlatformTheme::SystemPalette] = new QPalette(KColorScheme::createApplicationPalette(tempConfig));
0419     } else if (mKdeGlobals->hasGroup("Colors:View")) {
0420         m_palettes[QPlatformTheme::SystemPalette] = new QPalette(KColorScheme::createApplicationPalette(mKdeGlobals));
0421     } else {
0422         KConfigGroup cg(mKdeGlobals, "KDE");
0423         const QString looknfeel = readConfigValue(cg, QStringLiteral("LookAndFeelPackage"), defaultLookAndFeelPackage).toString();
0424         QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation,
0425                                               QStringLiteral("plasma/look-and-feel/") + looknfeel + QStringLiteral("/contents/colors"));
0426         if (!path.isEmpty()) {
0427             m_palettes[QPlatformTheme::SystemPalette] = new QPalette(KColorScheme::createApplicationPalette(KSharedConfig::openConfig(path)));
0428             return;
0429         }
0430 
0431         const QString scheme = readConfigValue(QStringLiteral("General"), QStringLiteral("ColorScheme"), QStringLiteral("BreezeLight")).toString();
0432         path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("color-schemes/") + scheme + QStringLiteral(".colors"));
0433 
0434         if (path.isEmpty()) {
0435             qWarning() << "Could not find color scheme" << scheme << "falling back to BreezeLight";
0436             path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("color-schemes/BreezeLight.colors"));
0437         }
0438 
0439         m_palettes[QPlatformTheme::SystemPalette] = new QPalette(KColorScheme::createApplicationPalette(KSharedConfig::openConfig(path)));
0440     }
0441 }
0442 
0443 void KHintsSettings::updateCursorTheme()
0444 {
0445     KSharedConfig::Ptr inputConfig = KSharedConfig::openConfig(QStringLiteral("kcminputrc"));
0446     KConfigGroup mouseConfig(inputConfig, "Mouse");
0447 
0448     const QString cursorTheme = readConfigValue(mouseConfig, QStringLiteral("cursorTheme"), QStringLiteral("breeze_cursors")).toString();
0449     const int cursorSize = readConfigValue(mouseConfig, QStringLiteral("cursorSize"), 24).toInt();
0450 
0451     if (QGuiApplication::platformName() == QLatin1String("wayland")) {
0452         qputenv("XCURSOR_THEME", cursorTheme.toUtf8());
0453         qputenv("XCURSOR_SIZE", QByteArray::number(cursorSize));
0454     }
0455 }
0456 
0457 void KHintsSettings::updateX11CursorTheme()
0458 {
0459 #if HAVE_X11
0460     if (QX11Info::isPlatformX11()) {
0461         KConfig config(QStringLiteral("kcminputrc"));
0462         KConfigGroup g(&config, "Mouse");
0463 
0464         int size = g.readEntry("cursorSize", 24);
0465         const QString theme = g.readEntry("cursorTheme", QString());
0466         // Note that in X11R7.1 and earlier, calling XcursorSetTheme()
0467         // with a NULL theme would cause Xcursor to use "default", but
0468         // in 7.2 and later it will cause it to revert to the theme that
0469         // was configured when the application was started.
0470         XcursorSetTheme(QX11Info::display(), theme.isNull() ? "default" : QFile::encodeName(theme).constData());
0471         XcursorSetDefaultSize(QX11Info::display(), size);
0472     }
0473 #endif
0474 }
0475 
0476 void KHintsSettings::updatePortalSetting()
0477 {
0478     mKdeGlobalsPortal.clear();
0479 
0480     QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.portal.Desktop"),
0481                                                           QStringLiteral("/org/freedesktop/portal/desktop"),
0482                                                           QStringLiteral("org.freedesktop.portal.Settings"),
0483                                                           QStringLiteral("ReadAll"));
0484     message << QStringList{QStringLiteral("org.kde.kdeglobals.*")};
0485 
0486     // FIXME: async?
0487     QDBusMessage resultMessage = QDBusConnection::sessionBus().call(message);
0488     if (resultMessage.type() == QDBusMessage::ReplyMessage) {
0489         QDBusArgument dbusArgument = resultMessage.arguments().at(0).value<QDBusArgument>();
0490         dbusArgument >> mKdeGlobalsPortal;
0491     }
0492 }