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

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