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//
5// W A R N I N G
6// -------------
7//
8// This file is not part of the Qt API. It exists purely as an
9// implementation detail. This header file may change from version to
10// version without notice, or even be removed.
11//
12// We mean it.
13//
14
15#include "qgtk3json_p.h"
16#include "qgtk3storage_p.h"
17#include <qpa/qwindowsysteminterface.h>
18#if QT_CONFIG(dbus)
19# include <QtGui/private/qgnomeportalinterface_p.h>
20#endif
21
22QT_BEGIN_NAMESPACE
23
24QGtk3Storage::QGtk3Storage()
25{
26 m_interface.reset(p: new QGtk3Interface(this));
27#if QT_CONFIG(dbus)
28 m_portalInterface.reset(p: new QGnomePortalInterface);
29#endif
30 populateMap();
31}
32
33QGtk3Storage::~QGtk3Storage() { }
34
35/*!
36 \internal
37 \enum QGtk3Storage::SourceType
38 \brief This enum represents the type of a color source.
39
40 \value Gtk Color is read from a GTK widget
41 \value Fixed A fixed brush is specified
42 \value Modified The color is a modification of another color (fixed or read from GTK)
43 \omitvalue Invalid
44 */
45
46/*!
47 \internal
48 \brief Find a brush from a source.
49
50 Returns a QBrush from a given \param source and a \param map of available brushes
51 to search from.
52
53 A null QBrush is returned, if no brush corresponding to the source has been found.
54 */
55QBrush QGtk3Storage::brush(const Source &source, const BrushMap &map) const
56{
57 switch (source.sourceType) {
58 case SourceType::Gtk:
59 return m_interface ? QBrush(m_interface->brush(wtype: source.gtk3.gtkWidgetType,
60 source: source.gtk3.source, state: source.gtk3.state))
61 : QBrush();
62
63 case SourceType::Modified: {
64 // don't loop through modified sources, break if modified source not found
65 Source recSource = brush(brush: TargetBrush(source.rec.colorGroup, source.rec.colorRole,
66 source.rec.colorScheme), map);
67
68 if (!recSource.isValid() || (recSource.sourceType == SourceType::Modified))
69 return QBrush();
70
71 // Set brush and alter color
72 QBrush b = brush(source: recSource, map);
73 if (source.rec.width > 0 && source.rec.height > 0)
74 b.setTexture(QPixmap(source.rec.width, source.rec.height));
75 QColor c = b.color().lighter(f: source.rec.lighter);
76 c = QColor((c.red() + source.rec.deltaRed),
77 (c.green() + source.rec.deltaGreen),
78 (c.blue() + source.rec.deltaBlue));
79 b.setColor(c);
80 return b;
81 }
82
83 case SourceType::Mixed: {
84 // check the mixing source to be valid and be a Gtk source
85 constexpr auto check_source = [](const Source &source) -> bool
86 {
87 return source.isValid() && (source.sourceType == SourceType::Gtk);
88 };
89
90 const Source source1 = brush(brush: TargetBrush(source.mix.sourceGroup,
91 source.mix.colorRole1), map);
92 if (!check_source(source1))
93 return QBrush();
94
95 const Source source2 = brush(brush: TargetBrush(source.mix.sourceGroup,
96 source.mix.colorRole2), map);
97 if (!check_source(source2))
98 return QBrush();
99
100 const QBrush brush2 = brush(source: source2, map);
101 // the output brush is a copy of the brush from the first source
102 QBrush brush1 = brush(source: source1, map);
103 // only color is mixed
104 brush1.setColor(MixSources::mixColors(color1: brush1.color(), color2: brush2.color()));
105 return brush1;
106 }
107
108 case SourceType::Fixed:
109 return source.fix.fixedBrush;
110
111 case SourceType::Invalid:
112 return QBrush();
113 }
114
115 // needed because of the scope after recursive
116 Q_UNREACHABLE();
117}
118
119/*!
120 \internal
121 \brief Recurse to find a source brush for modification.
122
123 Returns the source specified by the target brush \param b in the \param map of brushes.
124 Takes dark/light/unknown into consideration.
125 Returns an empty brush if no suitable one can be found.
126 */
127QGtk3Storage::Source QGtk3Storage::brush(const TargetBrush &b, const BrushMap &map) const
128{
129#define FIND(brush) if (map.contains(brush))\
130 return map.value(brush)
131
132 // Return exact match
133 FIND(b);
134
135 // unknown color scheme can find anything
136 if (b.colorScheme == Qt::ColorScheme::Unknown) {
137 FIND(TargetBrush(b, Qt::ColorScheme::Dark));
138 FIND(TargetBrush(b, Qt::ColorScheme::Light));
139 }
140
141 // Color group All can always be found
142 if (b.colorGroup != QPalette::All)
143 return brush(b: TargetBrush(QPalette::All, b.colorRole, b.colorScheme), map);
144
145 // Brush not found
146 return Source();
147#undef FIND
148}
149
150/*!
151 \internal
152 \brief Returns a simple, hard coded base palette.
153
154 Create a hard coded palette with default colors as a fallback for any color that can't be
155 obtained from GTK.
156
157 \note This palette will be used as a default baseline for the system palette, which then
158 will be used as a default baseline for any other palette type.
159 */
160QPalette QGtk3Storage::standardPalette()
161{
162 QColor backgroundColor(0xd4, 0xd0, 0xc8);
163 QColor lightColor(backgroundColor.lighter());
164 QColor darkColor(backgroundColor.darker());
165 const QBrush darkBrush(darkColor);
166 QColor midColor(Qt::gray);
167 QPalette palette(Qt::black, backgroundColor, lightColor, darkColor,
168 midColor, Qt::black, Qt::white);
169 palette.setBrush(cg: QPalette::Disabled, cr: QPalette::WindowText, brush: darkBrush);
170 palette.setBrush(cg: QPalette::Disabled, cr: QPalette::Text, brush: darkBrush);
171 palette.setBrush(cg: QPalette::Disabled, cr: QPalette::ButtonText, brush: darkBrush);
172 palette.setBrush(cg: QPalette::Disabled, cr: QPalette::Base, brush: QBrush(backgroundColor));
173 return palette;
174}
175
176/*!
177 \internal
178 \brief Return a GTK styled QPalette.
179
180 Returns the pointer to a (cached) QPalette for \param type, with its brushes
181 populated according to the current GTK theme.
182 */
183const QPalette *QGtk3Storage::palette(QPlatformTheme::Palette type) const
184{
185 if (type >= QPlatformTheme::NPalettes)
186 return nullptr;
187
188 if (m_paletteCache[type].has_value()) {
189 qCDebug(lcQGtk3Interface) << "Returning palette from cache:"
190 << QGtk3Json::fromPalette(palette: type);
191
192 return &m_paletteCache[type].value();
193 }
194
195 // Read system palette as a baseline first
196 if (!m_paletteCache[QPlatformTheme::SystemPalette].has_value() && type != QPlatformTheme::SystemPalette)
197 palette();
198
199 // Fall back to system palette for unknown types
200 if (!m_palettes.contains(key: type) && type != QPlatformTheme::SystemPalette) {
201 qCDebug(lcQGtk3Interface) << "Returning system palette for unknown type"
202 << QGtk3Json::fromPalette(palette: type);
203 return palette();
204 }
205
206 BrushMap brushes = m_palettes.value(key: type);
207
208 // Standard palette is base for system palette. System palette is base for all others.
209 QPalette p = QPalette( type == QPlatformTheme::SystemPalette ? standardPalette()
210 : m_paletteCache[QPlatformTheme::SystemPalette].value());
211
212 qCDebug(lcQGtk3Interface) << "Creating palette:" << QGtk3Json::fromPalette(palette: type);
213 for (auto i = brushes.begin(); i != brushes.end(); ++i) {
214 Source source = i.value();
215
216 // Brush is set if
217 // - theme and source color scheme match
218 // - or either of them is unknown
219 const auto appSource = i.key().colorScheme;
220 const auto appTheme = colorScheme();
221 const bool setBrush = (appSource == appTheme) ||
222 (appSource == Qt::ColorScheme::Unknown) ||
223 (appTheme == Qt::ColorScheme::Unknown);
224
225 if (setBrush) {
226 p.setBrush(cg: i.key().colorGroup, cr: i.key().colorRole, brush: brush(source, map: brushes));
227 }
228 }
229
230 m_paletteCache[type].emplace(args&: p);
231 if (type == QPlatformTheme::SystemPalette)
232 qCDebug(lcQGtk3Interface) << "System Palette defined" << themeName() << colorScheme() << p;
233
234 return &m_paletteCache[type].value();
235}
236
237/*!
238 \internal
239 \brief Return a GTK styled font.
240
241 Returns a QFont of \param type, styled according to the current GTK theme.
242*/
243const QFont *QGtk3Storage::font(QPlatformTheme::Font type) const
244{
245 if (m_fontCache[type].has_value())
246 return &m_fontCache[type].value();
247
248 m_fontCache[type].emplace(args: m_interface->font(type));
249 return &m_fontCache[type].value();
250}
251
252/*!
253 \internal
254 \brief Return a GTK styled standard pixmap if available.
255
256 Returns a pixmap specified by \param standardPixmap and \param size.
257 Returns an empty pixmap if GTK doesn't support the requested one.
258 */
259QPixmap QGtk3Storage::standardPixmap(QPlatformTheme::StandardPixmap standardPixmap,
260 const QSizeF &size) const
261{
262 if (m_pixmapCache.contains(key: standardPixmap))
263 return QPixmap::fromImage(image: m_pixmapCache.object(key: standardPixmap)->scaled(s: size.toSize()));
264
265 if (!m_interface)
266 return QPixmap();
267
268 QImage image = m_interface->standardPixmap(standardPixmap);
269 if (image.isNull())
270 return QPixmap();
271
272 m_pixmapCache.insert(key: standardPixmap, object: new QImage(image));
273 return QPixmap::fromImage(image: image.scaled(s: size.toSize()));
274}
275
276/*!
277 \internal
278 \brief Returns a GTK styled file icon corresponding to \param fileInfo.
279 */
280QIcon QGtk3Storage::fileIcon(const QFileInfo &fileInfo) const
281{
282 return m_interface ? m_interface->fileIcon(fileInfo) : QIcon();
283}
284
285/*!
286 \internal
287 \brief Clears all caches.
288 */
289void QGtk3Storage::clear()
290{
291 m_colorScheme = Qt::ColorScheme::Unknown;
292 m_palettes.clear();
293 for (auto &cache : m_paletteCache)
294 cache.reset();
295
296 for (auto &cache : m_fontCache)
297 cache.reset();
298}
299
300/*!
301 \internal
302 \brief Handles a theme change at runtime.
303
304 Clear all caches, re-populate with current GTK theme and notify the window system interface.
305 This method is a callback for the theme change signal sent from GTK.
306 */
307void QGtk3Storage::handleThemeChange()
308{
309 populateMap();
310 QWindowSystemInterface::handleThemeChange();
311}
312
313/*!
314 \internal
315 \brief Populates a map with information about how to locate colors in GTK.
316
317 This method creates a data structure to locate color information for each brush of a QPalette
318 within GTK. The structure can hold mapping information for each QPlatformTheme::Palette
319 enum value. If no specific mapping is stored for an enum value, the system palette is returned
320 instead of a specific one. If no mapping is stored for the system palette, it will fall back to
321 QGtk3Storage::standardPalette.
322
323 The method will populate the data structure with a standard mapping, covering the following
324 palette types:
325 \list
326 \li QPlatformTheme::SystemPalette
327 \li QPlatformTheme::CheckBoxPalette
328 \li QPlatformTheme::RadioButtonPalette
329 \li QPlatformTheme::ComboBoxPalette
330 \li QPlatformTheme::GroupBoxPalette
331 \li QPlatformTheme::MenuPalette
332 \li QPlatformTheme::TextLineEditPalette
333 \endlist
334
335 The method will check the environment variable {{QT_GUI_GTK_JSON_SAVE}}. If it points to a
336 valid path with write access, it will write the standard mapping into a Json file.
337 That Json file can be modified and/or extended.
338 The Json syntax is
339 - "QGtk3Palettes" (top level value)
340 - QPlatformTheme::Palette
341 - QPalette::ColorRole
342 - Qt::ColorScheme
343 - Qt::ColorGroup
344 - Source data
345 - Source Type
346 - [source data]
347
348 If the environment variable {{QT_GUI_GTK_JSON_HARDCODED}} contains the keyword \c true,
349 all sources are converted to fixed sources. In that case, they contain the hard coded HexRGBA
350 values read from GTK.
351
352 The method will also check the environment variable {{QT_GUI_GTK_JSON}}. If it points to a valid
353 Json file with read access, it will be parsed instead of creating a standard mapping.
354 Parsing errors will be printed out with qCInfo if the logging category {{qt.qpa.gtk}} is activated.
355 In case of a parsing error, the method will fall back to creating a standard mapping.
356
357 \note
358 If a Json file contains only fixed brushes (e.g. exported with {{QT_GUI_GTK_JSON_HARDCODED=true}}),
359 no colors will be imported from GTK.
360 */
361void QGtk3Storage::populateMap()
362{
363 static QString m_themeName;
364
365 // Distiguish initialization, theme change or call without theme change
366 Qt::ColorScheme newColorScheme = Qt::ColorScheme::Unknown;
367 const QString newThemeName = themeName();
368
369#if QT_CONFIG(dbus)
370 // Prefer color scheme we get from xdg-desktop-portal as this is what GNOME
371 // relies on these days
372 newColorScheme = m_portalInterface->colorScheme();
373#endif
374
375 if (newColorScheme == Qt::ColorScheme::Unknown) {
376 // Derive color scheme from theme name
377 newColorScheme = newThemeName.contains(s: "dark"_L1, cs: Qt::CaseInsensitive)
378 ? Qt::ColorScheme::Dark : m_interface->colorSchemeByColors();
379 }
380
381 if (m_themeName == newThemeName && m_colorScheme == newColorScheme)
382 return;
383
384 clear();
385
386 if (m_themeName.isEmpty()) {
387 qCDebug(lcQGtk3Interface) << "GTK theme initialized:" << newThemeName << newColorScheme;
388 } else {
389 qCDebug(lcQGtk3Interface) << "GTK theme changed to:" << newThemeName << newColorScheme;
390 }
391 m_colorScheme = newColorScheme;
392 m_themeName = newThemeName;
393
394 // create standard mapping or load from Json file?
395 const QString jsonInput = qEnvironmentVariable(varName: "QT_GUI_GTK_JSON");
396 if (!jsonInput.isEmpty()) {
397 if (load(filename: jsonInput)) {
398 return;
399 } else {
400 qWarning() << "Falling back to standard GTK mapping.";
401 }
402 }
403
404 createMapping();
405
406 const QString jsonOutput = qEnvironmentVariable(varName: "QT_GUI_GTK_JSON_SAVE");
407 if (!jsonOutput.isEmpty() && !save(filename: jsonOutput))
408 qWarning() << "File" << jsonOutput << "could not be saved.\n";
409}
410
411/*!
412 \internal
413 \brief Return a palette map for saving.
414
415 This method returns the existing palette map, if the environment variable
416 {{QT_GUI_GTK_JSON_HARDCODED}} is not set or does not contain the keyword \c true.
417 If it contains the keyword \c true, it returns a palette map with all brush
418 sources converted to fixed sources.
419 */
420const QGtk3Storage::PaletteMap QGtk3Storage::savePalettes() const
421{
422 const QString hard = qEnvironmentVariable(varName: "QT_GUI_GTK_JSON_HARDCODED");
423 if (!hard.contains(s: "true"_L1, cs: Qt::CaseInsensitive))
424 return m_palettes;
425
426 // Json output is supposed to be readable without GTK connection
427 // convert palette map into hard coded brushes
428 PaletteMap map = m_palettes;
429 for (auto paletteIterator = map.begin(); paletteIterator != map.end();
430 ++paletteIterator) {
431 QGtk3Storage::BrushMap &bm = paletteIterator.value();
432 for (auto brushIterator = bm.begin(); brushIterator != bm.end();
433 ++brushIterator) {
434 QGtk3Storage::Source &s = brushIterator.value();
435 switch (s.sourceType) {
436
437 // Read the brush and convert it into a fixed brush
438 case SourceType::Gtk: {
439 const QBrush fixedBrush = brush(source: s, map: bm);
440 s.fix.fixedBrush = fixedBrush;
441 s.sourceType = SourceType::Fixed;
442 }
443 break;
444 case SourceType::Fixed:
445 case SourceType::Modified:
446 case SourceType::Mixed:
447 case SourceType::Invalid:
448 break;
449 }
450 }
451 }
452 return map;
453}
454
455/*!
456 \internal
457 \brief Saves current palette mapping to a \param filename with Json format \param f.
458
459 Saves the current palette mapping into a QJson file,
460 taking {{QT_GUI_GTK_JSON_HARDCODED}} into consideration.
461 Returns \c true if saving was successful and \c false otherwise.
462 */
463bool QGtk3Storage::save(const QString &filename, QJsonDocument::JsonFormat f) const
464{
465 return QGtk3Json::save(map: savePalettes(), fileName: filename, format: f);
466}
467
468/*!
469 \internal
470 \brief Returns a QJsonDocument with current palette mapping.
471
472 Saves the current palette mapping into a QJsonDocument,
473 taking {{QT_GUI_GTK_JSON_HARDCODED}} into consideration.
474 Returns \c true if saving was successful and \c false otherwise.
475 */
476QJsonDocument QGtk3Storage::save() const
477{
478 return QGtk3Json::save(map: savePalettes());
479}
480
481/*!
482 \internal
483 \brief Loads palette mapping from Json file \param filename.
484
485 Returns \c true if the file was successfully parsed and \c false otherwise.
486 */
487bool QGtk3Storage::load(const QString &filename)
488{
489 return QGtk3Json::load(map&: m_palettes, fileName: filename);
490}
491
492/*!
493 \internal
494 \brief Creates a standard palette mapping.
495
496 The method creates a hard coded standard mapping, used if no external Json file
497 containing a valid mapping has been specified in the environment variable {{QT_GUI_GTK_JSON}}.
498 */
499void QGtk3Storage::createMapping()
500{
501 // Hard code standard mapping
502 BrushMap map;
503 Source source;
504
505 // Define a GTK source
506#define GTK(wtype, colorSource, state)\
507 source = Source(QGtk3Interface::QGtkWidget::gtk_ ##wtype,\
508 QGtk3Interface::QGtkColorSource::colorSource, GTK_STATE_FLAG_ ##state)
509
510 // Define a modified source
511#define LIGHTER(group, role, lighter)\
512 source = Source(QPalette::group, QPalette::role,\
513 Qt::ColorScheme::Unknown, lighter)
514#define MODIFY(group, role, red, green, blue)\
515 source = Source(QPalette::group, QPalette::role,\
516 Qt::ColorScheme::Unknown, red, green, blue)
517
518 // Define fixed source
519#define FIX(color) source = FixedSource(color);
520
521 // Add the source to a target brush
522 // Use default Qt::ColorScheme::Unknown, if no color scheme was specified
523#define ADD_2(group, role) map.insert(TargetBrush(QPalette::group, QPalette::role), source);
524#define ADD_3(group, role, app) map.insert(TargetBrush(QPalette::group, QPalette::role,\
525 Qt::ColorScheme::app), source);
526#define ADD_X(x, group, role, app, FUNC, ...) FUNC
527#define ADD(...) ADD_X(,##__VA_ARGS__, ADD_3(__VA_ARGS__), ADD_2(__VA_ARGS__))
528 // Save target brushes to a palette type
529#define SAVE(palette) m_palettes.insert(QPlatformTheme::palette, map)
530 // Clear brushes to start next palette
531#define CLEAR map.clear()
532
533 /*
534 Macro usage:
535
536 1. Define a source
537 GTK(QGtkWidget, QGtkColorSource, GTK_STATE_FLAG)
538 Fetch the color from a GtkWidget, related to a source and a state.
539
540 LIGHTER(ColorGroup, ColorROle, lighter)
541 Use a color of the same QPalette related to ColorGroup and ColorRole.
542 Make the color lighter (if lighter >100) or darker (if lighter < 100)
543
544 MODIFY(ColorGroup, ColorRole, red, green, blue)
545 Use a color of the same QPalette related to ColorGroup and ColorRole.
546 Modify it by adding red, green, blue.
547
548 FIX(const QBrush &)
549 Use a fixed brush without querying GTK
550
551 2. Define the target
552 Use ADD(ColorGroup, ColorRole) to use the defined source for the
553 color group / role in the current palette.
554
555 Use ADD(ColorGroup, ColorRole, ColorScheme) to use the defined source
556 only for a specific color scheme
557
558 3. Save mapping
559 Save the defined mappings for a specific palette.
560 If a mapping entry does not cover all color groups and roles of a palette,
561 the system palette will be used for the remaining values.
562 If the system palette does not have all combination of color groups and roles,
563 the remaining ones will be populated by a hard coded fusion-style like palette.
564
565 4. Clear mapping
566 Use CLEAR to clear the mapping and begin a new one.
567 */
568
569
570 // System palette
571 {
572 // background color and calculate derivates
573 GTK(Default, Background, INSENSITIVE);
574 ADD(All, Window);
575 ADD(All, Button);
576 ADD(All, Base);
577 LIGHTER(Normal, Window, 125);
578 ADD(Normal, Light);
579 ADD(Inactive, Light);
580 LIGHTER(Normal, Window, 70);
581 ADD(Normal, Shadow);
582 LIGHTER(Normal, Window, 80);
583 ADD(Normal, Dark);
584 ADD(Inactive, Dark)
585
586 GTK(button, Foreground, ACTIVE);
587 ADD(Inactive, WindowText);
588
589 auto ADD_MIX = [&map](QPalette::ColorGroup targetGroup,
590 QPalette::ColorRole targetRole,
591 QPalette::ColorGroup sourceGroup,
592 QPalette::ColorRole role1,
593 QPalette::ColorRole role2)
594 {
595 const Source source{sourceGroup, role1, role2};
596 map.insert(key: TargetBrush(targetGroup, targetRole), value: source);
597 };
598 ADD_MIX(QPalette::Disabled, QPalette::Text,
599 QPalette::Normal, QPalette::Base, QPalette::Text);
600 ADD_MIX(QPalette::Disabled, QPalette::WindowText,
601 QPalette::Normal, QPalette::Window, QPalette::WindowText);
602 ADD_MIX(QPalette::Disabled, QPalette::ButtonText,
603 QPalette::Normal, QPalette::Button, QPalette::ButtonText);
604
605 GTK(button, Text, NORMAL);
606 ADD(Inactive, ButtonText);
607
608 // special background colors
609 GTK(Default, Background, SELECTED);
610 ADD(Disabled, Highlight);
611 ADD(Normal, Highlight);
612 ADD(Inactive, Highlight);
613
614 GTK(entry, Foreground, SELECTED);
615 ADD(Normal, HighlightedText);
616 ADD(Inactive, HighlightedText);
617
618 // text color and friends
619 GTK(entry, Text, NORMAL);
620 ADD(Normal, ButtonText);
621 ADD(Normal, WindowText);
622 ADD(Disabled, HighlightedText);
623
624 GTK(Default, Text, NORMAL);
625 ADD(Normal, Text);
626 ADD(Inactive, Text);
627 ADD(Normal, HighlightedText);
628 LIGHTER(Normal, Base, 93);
629 ADD(All, AlternateBase);
630
631 GTK(Default, Foreground, NORMAL);
632 MODIFY(Normal, Text, 100, 100, 100);
633 ADD(All, PlaceholderText, Light);
634 MODIFY(Normal, Text, -100, -100, -100);
635 ADD(All, PlaceholderText, Dark);
636
637 // Light, midlight, dark, mid, shadow colors
638 LIGHTER(Normal, Button, 125);
639 ADD(All, Light)
640 LIGHTER(Normal, Button, 113);
641 ADD(All, Midlight)
642 LIGHTER(Normal, Button, 113);
643 ADD(All, Mid)
644 LIGHTER(Normal, Button, 87);
645 ADD(All, Dark)
646 LIGHTER(Normal, Button, 5);
647 ADD(All, Shadow)
648
649 SAVE(SystemPalette);
650 CLEAR;
651 }
652
653 // Label and TabBar Palette
654 {
655 GTK(entry, Text, NORMAL);
656 ADD(Normal, WindowText);
657 ADD(Inactive, WindowText);
658
659 SAVE(LabelPalette);
660 SAVE(TabBarPalette);
661 CLEAR;
662 }
663
664 // Checkbox and RadioButton Palette
665 {
666 GTK(button, Text, ACTIVE);
667 ADD(Normal, Base, Dark);
668 ADD(Inactive, WindowText, Dark);
669
670 GTK(Default, Foreground, NORMAL);
671 ADD(All, Text);
672
673 GTK(Default, Background, NORMAL);
674 ADD(All, Base);
675
676 GTK(button, Text, NORMAL);
677 ADD(Normal, Base, Light);
678 ADD(Inactive, WindowText, Light);
679
680 SAVE(CheckBoxPalette);
681 SAVE(RadioButtonPalette);
682 CLEAR;
683 }
684
685 // ComboBox, GroupBox & Frame Palette
686 {
687 GTK(combo_box, Text, NORMAL);
688 ADD(Normal, ButtonText, Dark);
689 ADD(Normal, Text, Dark);
690 ADD(Inactive, WindowText, Dark);
691
692 GTK(combo_box, Text, ACTIVE);
693 ADD(Normal, ButtonText, Light);
694 ADD(Normal, Text, Light);
695 ADD(Inactive, WindowText, Light);
696
697 SAVE(ComboBoxPalette);
698 SAVE(GroupBoxPalette);
699 CLEAR;
700 }
701
702 // MenuBar Palette
703 {
704 GTK(Default, Text, ACTIVE);
705 ADD(Normal, ButtonText);
706 SAVE(MenuPalette);
707 CLEAR;
708 }
709
710 // LineEdit Palette
711 {
712 GTK(Default, Background, NORMAL);
713 ADD(All, Base);
714 SAVE(TextLineEditPalette);
715 CLEAR;
716 }
717
718#undef GTK
719#undef REC
720#undef FIX
721#undef ADD
722#undef ADD_2
723#undef ADD_3
724#undef ADD_X
725#undef SAVE
726#undef LOAD
727}
728
729QT_END_NAMESPACE
730

source code of qtbase/src/plugins/platformthemes/gtk3/qgtk3storage.cpp