Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qxdgdesktopportaltheme.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 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// Qt-Security score:significant reason:default
4
7
8#include <private/qguiapplication_p.h>
9#include <qpa/qplatformtheme_p.h>
10#include <qpa/qplatformthemefactory_p.h>
11#include <qpa/qplatformintegration.h>
12
13#include <QDBusConnection>
14#include <QDBusMessage>
15#include <QDBusPendingCall>
16#include <QDBusPendingCallWatcher>
17#include <QDBusPendingReply>
18#include <QDBusReply>
19
20QT_BEGIN_NAMESPACE
21
22using namespace Qt::StringLiterals;
23
24static constexpr QLatin1StringView appearanceInterface("org.freedesktop.appearance");
25static constexpr QLatin1StringView colorSchemeKey("color-scheme");
26static constexpr QLatin1StringView contrastKey("contrast");
27static constexpr QLatin1StringView motionKey("reduced-motion");
28
30 {
32public:
38
42
44 {
45 delete baseTheme;
46 }
47
48 /*! \internal
49
50 Converts the given Freedesktop color scheme setting \a colorschemePref to a Qt::ColorScheme value.
51 Specification: https://github.com/flatpak/xdg-desktop-portal/blob/d7a304a00697d7d608821253cd013f3b97ac0fb6/data/org.freedesktop.impl.portal.Settings.xml#L33-L45
52
53 Unfortunately the enum numerical values are not defined identically, so we have to convert them.
54
55 The mapping is as follows:
56
57 Enum Index: Freedesktop definition | Qt definition
58 ----------------------------------- | -------------
59 0: No preference | 0: Unknown
60 1: Prefer dark appearance | 2: Dark
61 2: Prefer light appearance | 1: Light
62 */
63 static Qt::ColorScheme colorSchemeFromXdgPref(const XdgColorschemePref colorschemePref)
64 {
65 switch (colorschemePref) {
66 case PreferDark: return Qt::ColorScheme::Dark;
67 case PreferLight: return Qt::ColorScheme::Light;
68 default: return Qt::ColorScheme::Unknown;
69 }
70 }
71
72public Q_SLOTS:
89
90public:
96};
97
98QXdgDesktopPortalTheme::QXdgDesktopPortalTheme()
99 : d_ptr(new QXdgDesktopPortalThemePrivate)
100{
101 Q_D(QXdgDesktopPortalTheme);
102
103 const QStringList themeNames = QGuiApplicationPrivate::platform_integration->themeNames();
104 for (const QString &themeName : themeNames) {
105 if (QXdgDesktopPortalTheme::isXdgPlugin(themeName))
106 continue;
107 // 1) Look for a theme plugin.
108 d->baseTheme = QPlatformThemeFactory::create(themeName, nullptr);
109 if (d->baseTheme)
110 break;
111
112 // 2) If no theme plugin was found ask the platform integration to create a theme
113 d->baseTheme = QGuiApplicationPrivate::platform_integration->createPlatformTheme(themeName);
114 if (d->baseTheme)
115 break;
116 }
117
118 // 3) Fall back on the built-in "null" platform theme.
119 if (!d->baseTheme)
120 d->baseTheme = new QPlatformTheme;
121
122 // Get information about portal version
123 QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
124 "/org/freedesktop/portal/desktop"_L1,
125 "org.freedesktop.DBus.Properties"_L1,
126 "Get"_L1);
127 message << "org.freedesktop.portal.FileChooser"_L1 << "version"_L1;
128 QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
129 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingCall);
130 QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher, [d] (QDBusPendingCallWatcher *watcher) {
131 QDBusPendingReply<QVariant> reply = *watcher;
132 if (reply.isValid()) {
133 d->fileChooserPortalVersion = reply.value().toUInt();
134 } else {
135 qWarning() << "Call for getting org.freedesktop.portal.FileChooser version failed"
136 << reply.error();
137 }
138 watcher->deleteLater();
139 });
140
141 // Get information about system theme preference
142 message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
143 "/org/freedesktop/portal/desktop"_L1,
144 "org.freedesktop.portal.Settings"_L1,
145 "ReadAll"_L1);
146
147 QStringList namespaces = { appearanceInterface };
148 message << namespaces;
149
150 // this must not be asyncCall() because we have to set appearance now
151 QDBusReply<QMap<QString, QVariantMap>> reply = QDBusConnection::sessionBus().call(message);
152 if (reply.isValid()) {
153 const QMap<QString, QVariantMap> settingsMap = reply.value();
154 if (!settingsMap.isEmpty()) {
155 const auto xdgColorSchemePref = static_cast<QXdgDesktopPortalThemePrivate::XdgColorschemePref>(settingsMap.value(appearanceInterface).value(colorSchemeKey).toUInt());
156 d->colorScheme = QXdgDesktopPortalThemePrivate::colorSchemeFromXdgPref(xdgColorSchemePref);
157 d->contrast = static_cast<Qt::ContrastPreference>(settingsMap.value(appearanceInterface).value(contrastKey).toUInt());
158 d->motion = static_cast<Qt::MotionPreference>(settingsMap.value(appearanceInterface).value(motionKey).toUInt());
159 }
160 } else {
161 qWarning() << "Call to org.freedesktop.portal.Settings.ReadAll failed" << reply.error();
162 }
163
164 QDBusConnection::sessionBus().connect(
165 "org.freedesktop.portal.Desktop"_L1, "/org/freedesktop/portal/desktop"_L1,
166 "org.freedesktop.portal.Settings"_L1, "SettingChanged"_L1, d_ptr.get(),
167 SLOT(settingChanged(QString,QString,QDBusVariant)));
168}
169
171{
172 Q_D(const QXdgDesktopPortalTheme);
173 return d->baseTheme->createPlatformMenuItem();
174}
175
177{
178 Q_D(const QXdgDesktopPortalTheme);
179 return d->baseTheme->createPlatformMenu();
180}
181
183{
184 Q_D(const QXdgDesktopPortalTheme);
185 return d->baseTheme->createPlatformMenuBar();
186}
187
189{
190 Q_D(const QXdgDesktopPortalTheme);
191 return d->baseTheme->showPlatformMenuBar();
192}
193
195{
196 Q_D(const QXdgDesktopPortalTheme);
197
198 if (type == FileDialog)
199 return true;
200
201 return d->baseTheme->usePlatformNativeDialog(type);
202}
203
205{
206 Q_D(const QXdgDesktopPortalTheme);
207
208 if (type == FileDialog && d->fileChooserPortalVersion) {
209 // Older versions of FileChooser portal don't support opening directories, therefore we fallback
210 // to native file dialog opened inside the sandbox to open a directory.
211 if (d->baseTheme->usePlatformNativeDialog(type))
212 return new QXdgDesktopPortalFileDialog(static_cast<QPlatformFileDialogHelper*>(d->baseTheme->createPlatformDialogHelper(type)),
213 d->fileChooserPortalVersion);
214
216 }
217
218 return d->baseTheme->createPlatformDialogHelper(type);
219}
220
221#ifndef QT_NO_SYSTEMTRAYICON
223{
224 Q_D(const QXdgDesktopPortalTheme);
225 return d->baseTheme->createPlatformSystemTrayIcon();
226}
227#endif
228
229const QPalette *QXdgDesktopPortalTheme::palette(Palette type) const
230{
231 Q_D(const QXdgDesktopPortalTheme);
232 return d->baseTheme->palette(type);
233}
234
235const QFont* QXdgDesktopPortalTheme::font(Font type) const
236{
237 Q_D(const QXdgDesktopPortalTheme);
238 return d->baseTheme->font(type);
239}
240
242{
243 Q_D(const QXdgDesktopPortalTheme);
244 return d->baseTheme->themeHint(hint);
245}
246
248{
249 Q_D(const QXdgDesktopPortalTheme);
250 if (d->colorScheme == Qt::ColorScheme::Unknown)
251 return d->baseTheme->colorScheme();
252 return d->colorScheme;
253}
254
256{
257 Q_D(const QXdgDesktopPortalTheme);
258 return d->contrast;
259}
260
262{
263 Q_D(const QXdgDesktopPortalTheme);
264 return d->motion;
265}
266
267QPixmap QXdgDesktopPortalTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
268{
269 Q_D(const QXdgDesktopPortalTheme);
270 return d->baseTheme->standardPixmap(sp, size);
271}
272
273QIcon QXdgDesktopPortalTheme::fileIcon(const QFileInfo &fileInfo,
274 QPlatformTheme::IconOptions iconOptions) const
275{
276 Q_D(const QXdgDesktopPortalTheme);
277 return d->baseTheme->fileIcon(fileInfo, iconOptions);
278}
279
280QIconEngine * QXdgDesktopPortalTheme::createIconEngine(const QString &iconName) const
281{
282 Q_D(const QXdgDesktopPortalTheme);
283 return d->baseTheme->createIconEngine(iconName);
284}
285
286#if QT_CONFIG(shortcut)
287QList<QKeySequence> QXdgDesktopPortalTheme::keyBindings(QKeySequence::StandardKey key) const
288{
289 Q_D(const QXdgDesktopPortalTheme);
290 return d->baseTheme->keyBindings(key);
291}
292#endif
293
295{
296 Q_D(const QXdgDesktopPortalTheme);
297 return d->baseTheme->standardButtonText(button);
298}
299
300bool QXdgDesktopPortalTheme::isXdgPlugin(const QString &key)
301{
302 return key.compare("xdgdesktopportal"_L1, Qt::CaseInsensitive) == 0 ||
303 key.compare("flatpak"_L1, Qt::CaseInsensitive) == 0 ||
304 key.compare("snap"_L1, Qt::CaseInsensitive) == 0;
305}
306
307QT_END_NAMESPACE
308
309#include "qxdgdesktopportaltheme.moc"
static Qt::ColorScheme colorSchemeFromXdgPref(const XdgColorschemePref colorschemePref)
Qt::ColorScheme colorScheme() const override
Qt::ContrastPreference contrastPreference() const override
QPlatformMenuItem * createPlatformMenuItem() const override
QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override
Return a pixmap for standardPixmap, at the given size.
QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions={ }) const override
Return an icon for fileInfo, observing iconOptions.
QString standardButtonText(int button) const override
Returns the text of a standard button.
bool usePlatformNativeDialog(DialogType type) const override
QPlatformSystemTrayIcon * createPlatformSystemTrayIcon() const override
Factory function for QSystemTrayIcon.
QIconEngine * createIconEngine(const QString &iconName) const override
Factory function for the QIconEngine used by QIcon::fromTheme().
QPlatformDialogHelper * createPlatformDialogHelper(DialogType type) const override
Qt::MotionPreference motionPreference() const override
const QPalette * palette(Palette type=SystemPalette) const override
Return a color palette for type type.
const QFont * font(Font type=SystemFont) const override
QPlatformMenuBar * createPlatformMenuBar() const override
QPlatformMenu * createPlatformMenu() const override
QVariant themeHint(ThemeHint hint) const override
static constexpr QLatin1StringView contrastKey("contrast")
static constexpr QLatin1StringView motionKey("reduced-motion")
static constexpr QLatin1StringView colorSchemeKey("color-scheme")
static constexpr QLatin1StringView appearanceInterface("org.freedesktop.appearance")