1// Copyright (C) 2022 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
4#ifndef QGTK3STORAGE_P_H
5#define QGTK3STORAGE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qgtk3interface_p.h"
19
20#include <QtCore/QJsonDocument>
21#include <QtCore/QCache>
22#include <QtCore/QString>
23#include <QtGui/QGuiApplication>
24#include <QtGui/QPalette>
25
26#include <qpa/qplatformtheme.h>
27#include <private/qflatmap_p.h>
28
29QT_BEGIN_NAMESPACE
30
31#if QT_CONFIG(dbus)
32class QGnomePortalInterface;
33#endif
34
35class QGtk3Storage
36{
37 Q_GADGET
38public:
39 QGtk3Storage();
40 ~QGtk3Storage();
41
42 // Enum documented in cpp file. Please keep it in line with updates made here.
43 enum class SourceType {
44 Gtk,
45 Fixed,
46 Modified,
47 Mixed,
48 Invalid
49 };
50 Q_ENUM(SourceType)
51
52 // Standard GTK source: Populate a brush from GTK
53 struct Gtk3Source {
54 QGtk3Interface::QGtkWidget gtkWidgetType;
55 QGtk3Interface::QGtkColorSource source;
56 GtkStateFlags state;
57 int width = -1;
58 int height = -1;
59 QDebug operator<<(QDebug dbg)
60 {
61 return dbg << "QGtkStorage::Gtk3Source(gtkwidgetType=" << gtkWidgetType << ", source="
62 << source << ", state=" << state << ", width=" << width << ", height="
63 << height << ")";
64 }
65 };
66
67 // Recursive source: Populate a brush by altering another source
68 struct RecursiveSource {
69 QPalette::ColorGroup colorGroup;
70 QPalette::ColorRole colorRole;
71 Qt::ColorScheme colorScheme;
72 int lighter = 100;
73 int deltaRed = 0;
74 int deltaGreen = 0;
75 int deltaBlue = 0;
76 int width = -1;
77 int height = -1;
78 QDebug operator<<(QDebug dbg)
79 {
80 return dbg << "QGtkStorage::RecursiceSource(colorGroup=" << colorGroup << ", colorRole="
81 << colorRole << ", colorScheme=" << colorScheme << ", lighter=" << lighter
82 << ", deltaRed="<< deltaRed << "deltaBlue =" << deltaBlue << "deltaGreen="
83 << deltaGreen << ", width=" << width << ", height=" << height << ")";
84 }
85 };
86
87 // Mixed source: Populate a brush by mixing two brushes.
88 // Useful for creating disabled color by mixing,
89 // for example the background and foreground colors.
90 struct MixSources {
91 QPalette::ColorGroup sourceGroup; // source group of the mixing color roles
92 QPalette::ColorRole colorRole1;
93 QPalette::ColorRole colorRole2;
94 QDebug operator<<(QDebug dbg)
95 {
96 return dbg << "QGtkStorage::MixSources(sourceGroup=" << sourceGroup
97 << ", colorRole1=" << colorRole1
98 << ", colorRole2=" << colorRole2 << ")";
99 }
100 static inline QColor mixColors(const QColor &color1, const QColor &color2)
101 {
102 return QColor{ (color1.red() + color2.red()) / 2,
103 (color1.green() + color2.green()) / 2,
104 (color1.blue() + color2.blue()) / 2 };
105 }
106 };
107
108 // Fixed source: Populate a brush with fixed values rather than reading GTK
109 struct FixedSource {
110 QBrush fixedBrush;
111 QDebug operator<<(QDebug dbg)
112 {
113 return dbg << "QGtkStorage::FixedSource(" << fixedBrush << ")";
114 }
115 };
116
117 // Data source for brushes
118 struct Source {
119 SourceType sourceType = SourceType::Invalid;
120 Gtk3Source gtk3;
121 RecursiveSource rec;
122 FixedSource fix;
123 MixSources mix;
124
125 // GTK constructor
126 Source(QGtk3Interface::QGtkWidget wtype, QGtk3Interface::QGtkColorSource csource,
127 GtkStateFlags cstate, int bwidth = -1, int bheight = -1) : sourceType(SourceType::Gtk)
128 {
129 gtk3.gtkWidgetType = wtype;
130 gtk3.source = csource;
131 gtk3.state = cstate;
132 gtk3.width = bwidth;
133 gtk3.height = bheight;
134 }
135
136 // Recursive constructor for darker/lighter colors
137 Source(QPalette::ColorGroup group, QPalette::ColorRole role,
138 Qt::ColorScheme scheme, int p_lighter = 100)
139 : sourceType(SourceType::Modified)
140 {
141 rec.colorGroup = group;
142 rec.colorRole = role;
143 rec.colorScheme = scheme;
144 rec.lighter = p_lighter;
145 }
146
147 // Recursive constructor for color modification
148 Source(QPalette::ColorGroup group, QPalette::ColorRole role,
149 Qt::ColorScheme scheme, int p_red, int p_green, int p_blue)
150 : sourceType(SourceType::Modified)
151 {
152 rec.colorGroup = group;
153 rec.colorRole = role;
154 rec.colorScheme = scheme;
155 rec.deltaRed = p_red;
156 rec.deltaGreen = p_green;
157 rec.deltaBlue = p_blue;
158 }
159
160 // Recursive constructor for all: color modification and darker/lighter
161 Source(QPalette::ColorGroup group, QPalette::ColorRole role,
162 Qt::ColorScheme scheme, int p_lighter,
163 int p_red, int p_green, int p_blue) : sourceType(SourceType::Modified)
164 {
165 rec.colorGroup = group;
166 rec.colorRole = role;
167 rec.colorScheme = scheme;
168 rec.lighter = p_lighter;
169 rec.deltaRed = p_red;
170 rec.deltaGreen = p_green;
171 rec.deltaBlue = p_blue;
172 }
173
174 // Mixed constructor for color modification
175 Source(QPalette::ColorGroup sourceGroup,
176 QPalette::ColorRole role1, QPalette::ColorRole role2)
177 : sourceType(SourceType::Mixed)
178 {
179 mix.sourceGroup = sourceGroup;
180 mix.colorRole1 = role1;
181 mix.colorRole2 = role2;
182 }
183
184 // Fixed Source constructor
185 Source(const QBrush &brush) : sourceType(SourceType::Fixed)
186 {
187 fix.fixedBrush = brush;
188 }
189
190 // Invalid constructor and getter
191 Source() : sourceType(SourceType::Invalid) {}
192 bool isValid() const { return sourceType != SourceType::Invalid; }
193
194 // Debug
195 QDebug operator<<(QDebug dbg)
196 {
197 return dbg << "QGtk3Storage::Source(sourceType=" << sourceType << ")";
198 }
199 };
200
201 // Struct with key attributes to identify a brush: color group, color role and color scheme
202 struct TargetBrush {
203 QPalette::ColorGroup colorGroup;
204 QPalette::ColorRole colorRole;
205 Qt::ColorScheme colorScheme;
206
207 // Generic constructor
208 TargetBrush(QPalette::ColorGroup group, QPalette::ColorRole role,
209 Qt::ColorScheme scheme = Qt::ColorScheme::Unknown) :
210 colorGroup(group), colorRole(role), colorScheme(scheme) {}
211
212 // Copy constructor with color scheme modifier for dark/light aware search
213 TargetBrush(const TargetBrush &other, Qt::ColorScheme scheme) :
214 colorGroup(other.colorGroup), colorRole(other.colorRole), colorScheme(scheme) {}
215
216 // struct becomes key of a map, so operator< is needed
217 bool operator<(const TargetBrush& other) const {
218 return std::tie(args: colorGroup, args: colorRole, args: colorScheme) <
219 std::tie(args: other.colorGroup, args: other.colorRole, args: other.colorScheme);
220 }
221 };
222
223 // Mapping a palette's brushes to their GTK sources
224 typedef QFlatMap<TargetBrush, Source> BrushMap;
225
226 // Storage of palettes and their GTK sources
227 typedef QFlatMap<QPlatformTheme::Palette, BrushMap> PaletteMap;
228
229 // Public getters
230 const QPalette *palette(QPlatformTheme::Palette = QPlatformTheme::SystemPalette) const;
231 QPixmap standardPixmap(QPlatformTheme::StandardPixmap standardPixmap, const QSizeF &size) const;
232 Qt::ColorScheme colorScheme() const { return m_colorScheme; }
233 static QPalette standardPalette();
234 const QString themeName() const { return m_interface ? m_interface->themeName() : QString(); }
235 const QFont *font(QPlatformTheme::Font type) const;
236 QIcon fileIcon(const QFileInfo &fileInfo) const;
237
238 // Initialization
239 void populateMap();
240 void handleThemeChange();
241
242private:
243 // Storage for palettes and their brushes
244 PaletteMap m_palettes;
245
246 std::unique_ptr<QGtk3Interface> m_interface;
247#if QT_CONFIG(dbus)
248 std::unique_ptr<QGnomePortalInterface> m_portalInterface;
249#endif
250
251 Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
252
253 // Caches for Pixmaps, fonts and palettes
254 mutable QCache<QPlatformTheme::StandardPixmap, QImage> m_pixmapCache;
255 mutable std::array<std::optional<QPalette>, QPlatformTheme::Palette::NPalettes> m_paletteCache;
256 mutable std::array<std::optional<QFont>, QPlatformTheme::NFonts> m_fontCache;
257
258 // Search brush with a given GTK3 source
259 QBrush brush(const Source &source, const BrushMap &map) const;
260
261 // Get GTK3 source for a target brush
262 Source brush (const TargetBrush &brush, const BrushMap &map) const;
263
264 // clear cache, palettes and color scheme
265 void clear();
266
267 // Data creation, import & export
268 void createMapping ();
269 const PaletteMap savePalettes() const;
270 bool save(const QString &filename, const QJsonDocument::JsonFormat f = QJsonDocument::Indented) const;
271 QJsonDocument save() const;
272 bool load(const QString &filename);
273};
274
275QT_END_NAMESPACE
276#endif // QGTK3STORAGE_H
277

source code of qtbase/src/plugins/platformthemes/gtk3/qgtk3storage_p.h