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
qgtk3json.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
5//
6// W A R N I N G
7// -------------
8//
9// This file is not part of the Qt API. It exists purely as an
10// implementation detail. This header file may change from version to
11// version without notice, or even be removed.
12//
13// We mean it.
14//
15
16#include "qgtk3json_p.h"
17#include <QtCore/QFile>
18#include <QMetaEnum>
19
21
22QLatin1String QGtk3Json::fromPalette(QPlatformTheme::Palette palette)
23{
24 return QLatin1String(QMetaEnum::fromType<QPlatformTheme::Palette>().valueToKey(static_cast<int>(palette)));
25}
26
27QLatin1String QGtk3Json::fromGtkState(GtkStateFlags state)
28{
29 return QGtk3Interface::fromGtkState(state);
30}
31
32QLatin1String fromColor(const QColor &color)
33{
34 return QLatin1String(QByteArray(color.name(QColor::HexRgb).toLatin1()));
35}
36
37QLatin1String QGtk3Json::fromColorRole(QPalette::ColorRole role)
38{
39 return QLatin1String(QMetaEnum::fromType<QPalette::ColorRole>().valueToKey(static_cast<int>(role)));
40}
41
42QLatin1String QGtk3Json::fromColorGroup(QPalette::ColorGroup group)
43{
44 return QLatin1String(QMetaEnum::fromType<QPalette::ColorGroup>().valueToKey(static_cast<int>(group)));
45}
46
47QLatin1String QGtk3Json::fromGdkSource(QGtk3Interface::QGtkColorSource source)
48{
49 return QLatin1String(QMetaEnum::fromType<QGtk3Interface::QGtkColorSource>().valueToKey(static_cast<int>(source)));
50}
51
52QLatin1String QGtk3Json::fromWidgetType(QGtk3Interface::QGtkWidget widgetType)
53{
54 return QLatin1String(QMetaEnum::fromType<QGtk3Interface::QGtkWidget>().valueToKey(static_cast<int>(widgetType)));
55}
56
57QLatin1String QGtk3Json::fromColorScheme(Qt::ColorScheme app)
58{
59 return QLatin1String(QMetaEnum::fromType<Qt::ColorScheme>().valueToKey(static_cast<int>(app)));
60}
61
62#define CONVERT(type, key, def)
63 bool ok;
64 const int intVal = QMetaEnum::fromType<type>().keyToValue(key.toLatin1().constData(), &ok);
65 return ok ? static_cast<type>(intVal) : type::def
66
67Qt::ColorScheme QGtk3Json::toColorScheme(const QString &colorScheme)
68{
69 CONVERT(Qt::ColorScheme, colorScheme, Unknown);
70}
71
72QPlatformTheme::Palette QGtk3Json::toPalette(const QString &palette)
73{
74 CONVERT(QPlatformTheme::Palette, palette, NPalettes);
75}
76
77GtkStateFlags QGtk3Json::toGtkState(const QString &type)
78{
79 int i = QGtk3Interface::toGtkState(type);
80 if (i < 0)
81 return GTK_STATE_FLAG_NORMAL;
82 return static_cast<GtkStateFlags>(i);
83}
84
85QColor toColor(const QStringView &color)
86{
87 return QColor::fromString(color);
88}
89
90QPalette::ColorRole QGtk3Json::toColorRole(const QString &role)
91{
92 CONVERT(QPalette::ColorRole, role, NColorRoles);
93}
94
95QPalette::ColorGroup QGtk3Json::toColorGroup(const QString &group)
96{
97 CONVERT(QPalette::ColorGroup, group, NColorGroups);
98}
99
100QGtk3Interface::QGtkColorSource QGtk3Json::toGdkSource(const QString &source)
101{
102 CONVERT(QGtk3Interface::QGtkColorSource, source, Background);
103}
104
105QLatin1String QGtk3Json::fromSourceType(QGtk3Storage::SourceType sourceType)
106{
107 return QLatin1String(QMetaEnum::fromType<QGtk3Storage::SourceType>().valueToKey(static_cast<int>(sourceType)));
108}
109
110QGtk3Storage::SourceType QGtk3Json::toSourceType(const QString &sourceType)
111{
113}
114
115QGtk3Interface::QGtkWidget QGtk3Json::toWidgetType(const QString &widgetType)
116{
118}
119
120#undef CONVERT
121
122bool QGtk3Json::save(const QGtk3Storage::PaletteMap &map, const QString &fileName,
123 QJsonDocument::JsonFormat format)
124{
125 QJsonDocument doc = save(map);
126 if (doc.isEmpty()) {
127 qWarning() << "Nothing to save to" << fileName;
128 return false;
129 }
130
131 QFile file(fileName);
132 if (!file.open(QIODevice::WriteOnly)) {
133 qWarning() << "Unable to open file" << fileName << "for writing.";
134 return false;
135 }
136
137 if (!file.write(doc.toJson(format))) {
138 qWarning() << "Unable to serialize Json document.";
139 return false;
140 }
141
142 file.close();
143 qInfo() << "Saved mapping data to" << fileName;
144 return true;
145}
146
147const QJsonDocument QGtk3Json::save(const QGtk3Storage::PaletteMap &map)
148{
149 QJsonObject paletteObject;
150 for (auto paletteIterator = map.constBegin(); paletteIterator != map.constEnd();
151 ++paletteIterator) {
152 const QGtk3Storage::BrushMap &bm = paletteIterator.value();
153 QFlatMap<QPalette::ColorRole, QGtk3Storage::BrushMap> brushMaps;
154 for (auto brushIterator = bm.constBegin(); brushIterator != bm.constEnd();
155 ++brushIterator) {
156 const QPalette::ColorRole role = brushIterator.key().colorRole;
157 if (brushMaps.contains(role)) {
158 brushMaps[role].insert(brushIterator.key(), brushIterator.value());
159 } else {
160 QGtk3Storage::BrushMap newMap;
161 newMap.insert(brushIterator.key(), brushIterator.value());
162 brushMaps.insert(role, newMap);
163 }
164 }
165
166 QJsonObject brushArrayObject;
167 for (auto brushMapIterator = brushMaps.constBegin();
168 brushMapIterator != brushMaps.constEnd(); ++brushMapIterator) {
169
170 QJsonArray brushArray;
171 int brushIndex = 0;
172 const QGtk3Storage::BrushMap &bm = brushMapIterator.value();
173 for (auto brushIterator = bm.constBegin(); brushIterator != bm.constEnd();
174 ++brushIterator) {
175 QJsonObject brushObject;
176 const QGtk3Storage::TargetBrush tb = brushIterator.key();
177 QGtk3Storage::Source s = brushIterator.value();
178 brushObject.insert(ceColorGroup, fromColorGroup(tb.colorGroup));
179 brushObject.insert(ceColorScheme, fromColorScheme(tb.colorScheme));
180 brushObject.insert(ceSourceType, fromSourceType(s.sourceType));
181
182 QJsonObject sourceObject;
183 switch (s.sourceType) {
185 sourceObject.insert(ceGtkWidget, fromWidgetType(s.gtk3.gtkWidgetType));
186 sourceObject.insert(ceGdkSource, fromGdkSource(s.gtk3.source));
187 sourceObject.insert(ceGtkState, fromGtkState(s.gtk3.state));
188 sourceObject.insert(ceWidth, s.gtk3.width);
189 sourceObject.insert(ceHeight, s.gtk3.height);
190 }
191 break;
192
194 QJsonObject fixedObject;
195 fixedObject.insert(ceColor, s.fix.fixedBrush.color().name());
196 fixedObject.insert(ceWidth, s.fix.fixedBrush.texture().width());
197 fixedObject.insert(ceHeight, s.fix.fixedBrush.texture().height());
198 sourceObject.insert(ceBrush, fixedObject);
199 }
200 break;
201
203 sourceObject.insert(ceColorGroup, fromColorGroup(s.rec.colorGroup));
204 sourceObject.insert(ceColorRole, fromColorRole(s.rec.colorRole));
205 sourceObject.insert(ceColorScheme, fromColorScheme(s.rec.colorScheme));
206 sourceObject.insert(ceRed, s.rec.deltaRed);
207 sourceObject.insert(ceGreen, s.rec.deltaGreen);
208 sourceObject.insert(ceBlue, s.rec.deltaBlue);
209 sourceObject.insert(ceWidth, s.rec.width);
210 sourceObject.insert(ceHeight, s.rec.height);
211 sourceObject.insert(ceLighter, s.rec.lighter);
212 }
213 break;
214
216 sourceObject.insert(ceColorGroup, fromColorGroup(s.mix.sourceGroup));
217 QJsonArray colorRoles;
218 colorRoles << fromColorRole(s.mix.colorRole1)
219 << fromColorRole(s.mix.colorRole2);
220 sourceObject.insert(ceColorRole, colorRoles);
221 }
222 break;
223
225 break;
226 }
227
228 brushObject.insert(ceData, sourceObject);
229 brushArray.insert(brushIndex, brushObject);
230 ++brushIndex;
231 }
232 brushArrayObject.insert(fromColorRole(brushMapIterator.key()), brushArray);
233 }
234 paletteObject.insert(fromPalette(paletteIterator.key()), brushArrayObject);
235 }
236
237 QJsonObject top;
238 top.insert(cePalettes, paletteObject);
239 return paletteObject.keys().isEmpty() ? QJsonDocument() : QJsonDocument(top);
240}
241
242bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QString &fileName)
243{
244 QFile file(fileName);
245 if (!file.open(QIODevice::ReadOnly)) {
246 qCWarning(lcQGtk3Interface) << "Unable to open file:" << fileName;
247 return false;
248 }
249
250 QJsonParseError err;
251 QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &err);
252 if (err.error != QJsonParseError::NoError) {
253 qCWarning(lcQGtk3Interface) << "Unable to parse Json document from" << fileName
254 << err.error << err.errorString();
255 return false;
256 }
257
258 if (Q_LIKELY(load(map, doc))) {
259 qInfo() << "GTK mapping successfully imported from" << fileName;
260 return true;
261 }
262
263 qWarning() << "File" << fileName << "could not be loaded.";
264 return false;
265}
266
267bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
268{
269#define GETSTR(obj, key)
270 if (!obj.contains(key)) {
271 qCInfo(lcQGtk3Interface) << key << "missing for palette" << paletteName
272 << ", Brush" << colorRoleName;
273 return false;
274 }
275 value = obj[key].toString()
276
277#define GETINT(obj, key, var) GETSTR(obj, key);
278 if (!obj[key].isDouble()) {
279 qCInfo(lcQGtk3Interface) << key << "type mismatch" << value
280 << "is not an integer!"
281 << "(Palette" << paletteName << "), Brush" << colorRoleName;
282 return false;
283 }
284 const int var = obj[key].toInt()
285
286 map.clear();
287 const QJsonObject top(doc.object());
288 if (doc.isEmpty() || top.isEmpty() || !top.contains(cePalettes)) {
289 qCInfo(lcQGtk3Interface) << "Document does not contain Palettes.";
290 return false;
291 }
292
293 const QStringList &paletteList = top[cePalettes].toObject().keys();
294 for (const QString &paletteName : paletteList) {
295 bool ok;
296 const int intVal = QMetaEnum::fromType<QPlatformTheme::Palette>().keyToValue(paletteName
297 .toLatin1().constData(), &ok);
298 if (!ok) {
299 qCInfo(lcQGtk3Interface) << "Invalid Palette name:" << paletteName;
300 return false;
301 }
302 const QJsonObject &paletteObject = top[cePalettes][paletteName].toObject();
303 const QStringList &brushList = paletteObject.keys();
304 if (brushList.isEmpty()) {
305 qCInfo(lcQGtk3Interface) << "Palette" << paletteName << "does not contain brushes";
306 return false;
307 }
308
309 const QPlatformTheme::Palette paletteType = static_cast<QPlatformTheme::Palette>(intVal);
310 QGtk3Storage::BrushMap brushes;
311 const QStringList &colorRoles = paletteObject.keys();
312 for (const QString &colorRoleName : colorRoles) {
313 const int intVal = QMetaEnum::fromType<QPalette::ColorRole>().keyToValue(colorRoleName
314 .toLatin1().constData(), &ok);
315 if (!ok) {
316 qCInfo(lcQGtk3Interface) << "Palette" << paletteName
317 << "contains invalid color role" << colorRoleName;
318 return false;
319 }
320 const QPalette::ColorRole colorRole = static_cast<QPalette::ColorRole>(intVal);
321 const QJsonArray &brushArray = paletteObject[colorRoleName].toArray();
322 for (int brushIndex = 0; brushIndex < brushArray.size(); ++brushIndex) {
323 const QJsonObject brushObject = brushArray.at(brushIndex).toObject();
324 if (brushObject.isEmpty()) {
325 qCInfo(lcQGtk3Interface) << "Brush specification missing at for palette"
326 << paletteName << ", Brush" << colorRoleName;
327 return false;
328 }
329
330 QString value;
331 GETSTR(brushObject, ceSourceType);
332 const QGtk3Storage::SourceType sourceType = toSourceType(value);
333 GETSTR(brushObject, ceColorGroup);
334 const QPalette::ColorGroup colorGroup = toColorGroup(value);
335 GETSTR(brushObject, ceColorScheme);
336 const Qt::ColorScheme colorScheme = toColorScheme(value);
337 QGtk3Storage::TargetBrush tb(colorGroup, colorRole, colorScheme);
338 QGtk3Storage::Source s;
339
340 if (!brushObject.contains(ceData) || !brushObject[ceData].isObject()) {
341 qCInfo(lcQGtk3Interface) << "Source specification missing for palette" << paletteName
342 << "Brush" << colorRoleName;
343 return false;
344 }
345 const QJsonObject &sourceObject = brushObject[ceData].toObject();
346
347 switch (sourceType) {
348 case QGtk3Storage::SourceType::Gtk: {
349 GETSTR(sourceObject, ceGdkSource);
350 const QGtk3Interface::QGtkColorSource gtkSource = toGdkSource(value);
351 GETSTR(sourceObject, ceGtkState);
352 const GtkStateFlags gtkState = toGtkState(value);
353 GETSTR(sourceObject, ceGtkWidget);
354 const QGtk3Interface::QGtkWidget widgetType = toWidgetType(value);
355 GETINT(sourceObject, ceHeight, height);
356 GETINT(sourceObject, ceWidth, width);
357 s = QGtk3Storage::Source(widgetType, gtkSource, gtkState, width, height);
358 }
359 break;
360
361 case QGtk3Storage::SourceType::Fixed: {
362 if (!sourceObject.contains(ceBrush)) {
363 qCInfo(lcQGtk3Interface) << "Fixed brush specification missing for palette" << paletteName
364 << "Brush" << colorRoleName;
365 return false;
366 }
367 const QJsonObject &fixedSource = sourceObject[ceBrush].toObject();
368 GETINT(fixedSource, ceWidth, width);
369 GETINT(fixedSource, ceHeight, height);
370 GETSTR(fixedSource, ceColor);
371 const QColor color(value);
372 if (!color.isValid()) {
373 qCInfo(lcQGtk3Interface) << "Color" << value << "can't be parsed for:" << paletteName
374 << "Brush" << colorRoleName;
375 return false;
376 }
377 const QBrush fixedBrush = (width < 0 && height < 0)
378 ? QBrush(color, QPixmap(width, height))
379 : QBrush(color);
380 s = QGtk3Storage::Source(fixedBrush);
381 }
382 break;
383
384 case QGtk3Storage::SourceType::Modified: {
385 GETSTR(sourceObject, ceColorGroup);
386 const QPalette::ColorGroup colorGroup = toColorGroup(value);
387 GETSTR(sourceObject, ceColorRole);
388 const QPalette::ColorRole colorRole = toColorRole(value);
389 GETSTR(sourceObject, ceColorScheme);
390 const Qt::ColorScheme colorScheme = toColorScheme(value);
391 GETINT(sourceObject, ceLighter, lighter);
392 GETINT(sourceObject, ceRed, red);
393 GETINT(sourceObject, ceBlue, blue);
394 GETINT(sourceObject, ceGreen, green);
395 s = QGtk3Storage::Source(colorGroup, colorRole, colorScheme,
396 lighter, red, green, blue);
397 }
398 break;
399
400 case QGtk3Storage::SourceType::Mixed: {
401 if (!sourceObject[ceColorRole].isArray()) {
402 qCInfo(lcQGtk3Interface) << "Mixed brush missing the array of color roles for palette:" << paletteName
403 << "Brush" << colorRoleName;
404 return false;
405 }
406 QJsonArray colorRoles = sourceObject[ceColorRole].toArray();
407 if (colorRoles.size() < 2) {
408 qCInfo(lcQGtk3Interface) << "Mixed brush missing enough color roles for palette" << paletteName
409 << "Brush" << colorRoleName;
410 return false;
411 }
412 const QPalette::ColorRole colorRole1 = toColorRole(colorRoles[0].toString());
413 const QPalette::ColorRole colorRole2 = toColorRole(colorRoles[1].toString());
414 GETSTR(sourceObject, ceColorGroup);
415 const QPalette::ColorGroup sourceGroup = toColorGroup(value);
416 s = QGtk3Storage::Source(sourceGroup, colorRole1, colorRole2);
417 }
418 break;
419
420 case QGtk3Storage::SourceType::Invalid:
421 qCInfo(lcQGtk3Interface) << "Invalid source type for palette" << paletteName
422 << "Brush." << colorRoleName;
423 return false;
424 }
425 brushes.insert(tb, s);
426 }
427 }
428 map.insert(paletteType, brushes);
429 }
430 return true;
431}
432
433QT_END_NAMESPACE
The QGtk3Interface class centralizes communication with the GTK3 library.
QFlatMap< QPlatformTheme::Palette, BrushMap > PaletteMap
QFlatMap< TargetBrush, Source > BrushMap
SourceType
This enum represents the type of a color source.
#define CONVERT
#define GETINT(obj, key, var)
QColor toColor(const QStringView &color)
Definition qgtk3json.cpp:85
#define GETSTR(obj, key)
QLatin1String fromColor(const QColor &color)
Definition qgtk3json.cpp:32