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
qgnometheme.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 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
6#include <qpa/qplatformdialoghelper.h>
7#include <qpa/qplatformfontdatabase.h>
8#if QT_CONFIG(dbus) && QT_CONFIG(systemtrayicon)
9# include <private/qdbustrayicon_p.h>
10#endif
11#if QT_CONFIG(dbus)
12# include <private/qdbusmenubar_p.h>
13#endif
14#include <qpa/qwindowsysteminterface.h>
15
17
18/*!
19 \class QGnomeTheme
20 \brief QGnomeTheme is a theme implementation for the Gnome desktop.
21 \since 5.0
22 \internal
23 \ingroup qpa
24*/
25const char *QGnomeTheme::name = "gnome";
26
27QGnomeThemePrivate::QGnomeThemePrivate()
28{
29#if QT_CONFIG(dbus)
30 QObject::connect(&m_gnomePortal, &QGnomePortalInterface::themeNameChanged, &m_gnomePortal,
31 [this](const QString &themeName) { m_themeName = themeName; });
32#endif // QT_CONFIG(dbus)
33}
34
35QGnomeThemePrivate::~QGnomeThemePrivate()
36{
37 if (systemFont)
38 delete systemFont;
39 if (fixedFont)
40 delete fixedFont;
41}
42
43void QGnomeThemePrivate::configureFonts(const QString &gtkFontName) const
44{
45 Q_ASSERT(!systemFont);
46 const int split = gtkFontName.lastIndexOf(QChar::Space);
47 float size = QStringView{gtkFontName}.mid(split + 1).toFloat();
48 QString fontName = gtkFontName.left(split);
49
50 systemFont = new QFont(fontName, size);
51 fixedFont = new QFont(QLatin1StringView(QGenericUnixTheme::defaultFixedFontNameC), systemFont->pointSize());
52 fixedFont->setStyleHint(QFont::TypeWriter);
53 qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
54}
55
56Qt::ColorScheme QGnomeThemePrivate::colorScheme() const
57{
58 if (hasRequestedColorScheme())
59 return m_requestedColorScheme;
60
61#if QT_CONFIG(dbus)
62 if (Qt::ColorScheme colorScheme = m_gnomePortal.colorScheme();
63 colorScheme != Qt::ColorScheme::Unknown)
64 return colorScheme;
65
66 // If the color scheme is set to Unknown by mistake or is not set at all,
67 // then maybe the theme name contains a hint about the color scheme.
68 // Let's hope the theme name does not include any accent color name
69 // which contains "dark" or "light" in it (e.g. lightblue). At the moment they don't.
70 if (m_themeName.contains(QLatin1StringView("light"), Qt::CaseInsensitive))
71 return Qt::ColorScheme::Light;
72 else if (m_themeName.contains(QLatin1StringView("dark"), Qt::CaseInsensitive))
73 return Qt::ColorScheme::Dark;
74#endif // QT_CONFIG(dbus)
75
76 // Fallback to Unknown if no color scheme is set or detected
77 return Qt::ColorScheme::Unknown;
78}
79
80bool QGnomeThemePrivate::hasRequestedColorScheme() const
81{
82 return m_requestedColorScheme != Qt::ColorScheme::Unknown;
83}
84
85QGnomeTheme::QGnomeTheme()
86 : QGenericUnixTheme(new QGnomeThemePrivate())
87{
88#if QT_CONFIG(dbus)
89 Q_D(QGnomeTheme);
90
91 QGnomePortalInterface *portal = &d->m_gnomePortal;
92
93 QObject::connect(portal, &QGnomePortalInterface::colorSchemeChanged, portal,
94 [this](Qt::ColorScheme colorScheme) { updateColorScheme(colorScheme); });
95
96 QObject::connect(portal, &QGnomePortalInterface::contrastChanged, portal,
97 [this](Qt::ContrastPreference contrast) { updateHighContrast(contrast); });
98 QObject::connect(portal, &QGnomePortalInterface::motionChanged, portal,
99 [this](Qt::MotionPreference motion){ updateReducedMotion(motion); });
100#endif // QT_CONFIG(dbus)
101}
102
103QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
104{
105 switch (hint) {
106 case QPlatformTheme::DialogButtonBoxButtonsHaveIcons:
107 return QVariant(true);
108 case QPlatformTheme::DialogButtonBoxLayout:
109 return QVariant(QPlatformDialogHelper::GnomeLayout);
110 case QPlatformTheme::SystemIconThemeName:
111 return QVariant(QStringLiteral("Adwaita"));
112 case QPlatformTheme::SystemIconFallbackThemeName:
113 return QVariant(QStringLiteral("gnome"));
114 case QPlatformTheme::IconThemeSearchPaths:
115 return QVariant(xdgIconThemePaths());
116 case QPlatformTheme::IconPixmapSizes:
117 return QVariant::fromValue(availableXdgFileIconSizes());
118 case QPlatformTheme::StyleNames: {
119 QStringList styleNames;
120 styleNames << QStringLiteral("Fusion") << QStringLiteral("windows");
121 return QVariant(styleNames);
122 }
123 case QPlatformTheme::KeyboardScheme:
124 return QVariant(int(GnomeKeyboardScheme));
125 case QPlatformTheme::PasswordMaskCharacter:
126 return QVariant(QChar(0x2022));
127 case QPlatformTheme::UiEffects:
128 return QVariant(int(HoverEffect));
129 case QPlatformTheme::ButtonPressKeys:
130 return QVariant::fromValue(
131 QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Return, Qt::Key_Enter, Qt::Key_Select }));
132 case QPlatformTheme::PreselectFirstFileInDirectory:
133 return true;
134 case QPlatformTheme::MouseCursorTheme:
135 return QVariant(mouseCursorTheme());
136 case QPlatformTheme::MouseCursorSize:
137 return QVariant(mouseCursorSize());
138 case QPlatformTheme::PreferFileIconFromTheme:
139 return true;
140 default:
141 break;
142 }
143 return QPlatformTheme::themeHint(hint);
144}
145
146QIcon QGnomeTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions) const
147{
148#if QT_CONFIG(mimetype)
149 return xdgFileIcon(fileInfo);
150#else
151 Q_UNUSED(fileInfo);
152 return QIcon();
153#endif
154}
155
156const QFont *QGnomeTheme::font(Font type) const
157{
158 Q_D(const QGnomeTheme);
159 if (!d->systemFont)
160 d->configureFonts(gtkFontName());
161 switch (type) {
162 case QPlatformTheme::SystemFont:
163 return d->systemFont;
164 case QPlatformTheme::FixedFont:
165 return d->fixedFont;
166 default:
167 return nullptr;
168 }
169}
170
171QString QGnomeTheme::gtkFontName() const
172{
173 return QStringLiteral("%1 %2").arg(QLatin1StringView(defaultSystemFontNameC))
174 .arg(defaultSystemFontSize);
175}
176
177void QGnomeTheme::requestColorScheme(Qt::ColorScheme scheme)
178{
179 Q_D(QGnomeTheme);
180 if (d->m_requestedColorScheme == scheme)
181 return;
182 QPlatformTheme::requestColorScheme(scheme);
183 d->m_requestedColorScheme = scheme;
184 QWindowSystemInterface::handleThemeChange();
185}
186
187Qt::ColorScheme QGnomeTheme::colorScheme() const
188{
189 Q_D(const QGnomeTheme);
190 if (auto colorScheme = d->colorScheme(); colorScheme != Qt::ColorScheme::Unknown)
191 return colorScheme;
192 // If the color scheme is not set or detected, fall back to the default
193 return QPlatformTheme::colorScheme();
194}
195
196#if QT_CONFIG(dbus)
197void QGnomeTheme::updateColorScheme(Qt::ColorScheme colorScheme)
198{
199 Q_UNUSED(colorScheme);
200 QWindowSystemInterface::handleThemeChange();
201}
202
203void QGnomeTheme::updateHighContrast(Qt::ContrastPreference contrast)
204{
205 Q_UNUSED(contrast);
206 QWindowSystemInterface::handleThemeChange();
207}
208
209void QGnomeTheme::updateReducedMotion(Qt::MotionPreference motion)
210{
211 Q_UNUSED(motion);
212 QWindowSystemInterface::handleThemeChange();
213}
214
215QPlatformMenuBar *QGnomeTheme::createPlatformMenuBar() const
216{
217 if (isDBusGlobalMenuAvailable())
218 return new QDBusMenuBar();
219 return nullptr;
220}
221
222Qt::ContrastPreference QGnomeTheme::contrastPreference() const
223{
224 Q_D(const QGnomeTheme);
225 return d->m_gnomePortal.contrastPreference();
226}
227
228Qt::MotionPreference QGnomeTheme::motionPreference() const
229{
230 Q_D(const QGnomeTheme);
231 return d->m_gnomePortal.motionPreference();
232}
233
234# if QT_CONFIG(systemtrayicon)
235QPlatformSystemTrayIcon *QGnomeTheme::createPlatformSystemTrayIcon() const
236{
237 if (shouldUseDBusTray())
238 return new QDBusTrayIcon();
239 return nullptr;
240}
241# endif // QT_CONFIG(systemtrayicon)
242#endif // QT_CONFIG(dbus)
243
244QString QGnomeTheme::standardButtonText(int button) const
245{
246 switch (button) {
247 case QPlatformDialogHelper::Ok:
248 return QCoreApplication::translate("QGnomeTheme", "&OK");
249 case QPlatformDialogHelper::Save:
250 return QCoreApplication::translate("QGnomeTheme", "&Save");
251 case QPlatformDialogHelper::Cancel:
252 return QCoreApplication::translate("QGnomeTheme", "&Cancel");
253 case QPlatformDialogHelper::Close:
254 return QCoreApplication::translate("QGnomeTheme", "&Close");
255 case QPlatformDialogHelper::Discard:
256 return QCoreApplication::translate("QGnomeTheme", "Close without Saving");
257 default:
258 break;
259 }
260 return QPlatformTheme::standardButtonText(button);
261}
262
263QT_END_NAMESPACE
Combined button and popup list for selecting options.