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