summaryrefslogtreecommitdiffstats
path: root/src/plugins/platformthemes/gtk3/qgtk3storage_p.h
blob: 45192263a913d0c49a4536271e511ecefe51954e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#ifndef QGTK3STORAGE_P_H
#define QGTK3STORAGE_P_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include "qgtk3interface_p.h"
#if QT_CONFIG(dbus)
#include "qgtk3portalinterface_p.h"
#endif

#include <QtCore/QJsonDocument>
#include <QtCore/QCache>
#include <QtCore/QString>
#include <QtGui/QGuiApplication>
#include <QtGui/QPalette>

#include <qpa/qplatformtheme.h>
#include <private/qflatmap_p.h>

QT_BEGIN_NAMESPACE
class QGtk3Storage
{
    Q_GADGET
public:
    QGtk3Storage();

    // Enum documented in cpp file. Please keep it in line with updates made here.
    enum class SourceType {
        Gtk,
        Fixed,
        Modified,
        Invalid
    };
    Q_ENUM(SourceType)

    // Standard GTK source: Populate a brush from GTK
    struct Gtk3Source  {
        QGtk3Interface::QGtkWidget gtkWidgetType;
        QGtk3Interface::QGtkColorSource source;
        GtkStateFlags state;
        int width = -1;
        int height = -1;
        QDebug operator<<(QDebug dbg)
        {
            return dbg << "QGtkStorage::Gtk3Source(gtkwidgetType=" << gtkWidgetType << ", source="
                       << source << ", state=" << state << ", width=" << width << ", height="
                       << height << ")";
        }
    };

    // Recursive source: Populate a brush by altering another source
    struct RecursiveSource  {
        QPalette::ColorGroup colorGroup;
        QPalette::ColorRole colorRole;
        Qt::ColorScheme colorScheme;
        int lighter = 100;
        int deltaRed = 0;
        int deltaGreen = 0;
        int deltaBlue = 0;
        int width = -1;
        int height = -1;
        QDebug operator<<(QDebug dbg)
        {
            return dbg << "QGtkStorage::RecursiceSource(colorGroup=" << colorGroup << ", colorRole="
                       << colorRole << ", colorScheme=" << colorScheme << ", lighter=" << lighter
                       << ", deltaRed="<< deltaRed << "deltaBlue =" << deltaBlue << "deltaGreen="
                       << deltaGreen << ", width=" << width << ", height=" << height << ")";
        }
    };

    // Fixed source: Populate a brush with fixed values rather than reading GTK
    struct FixedSource  {
        QBrush fixedBrush;
        QDebug operator<<(QDebug dbg)
        {
            return dbg << "QGtkStorage::FixedSource(" << fixedBrush << ")";
        }
    };

    // Data source for brushes
    struct Source {
        SourceType sourceType = SourceType::Invalid;
        Gtk3Source gtk3;
        RecursiveSource rec;
        FixedSource fix;

        // GTK constructor
        Source(QGtk3Interface::QGtkWidget wtype, QGtk3Interface::QGtkColorSource csource,
               GtkStateFlags cstate, int bwidth = -1, int bheight = -1) : sourceType(SourceType::Gtk)
        {
             gtk3.gtkWidgetType = wtype;
             gtk3.source = csource;
             gtk3.state = cstate;
             gtk3.width = bwidth;
             gtk3.height = bheight;
        }

        // Recursive constructor for darker/lighter colors
        Source(QPalette::ColorGroup group, QPalette::ColorRole role,
               Qt::ColorScheme scheme, int p_lighter = 100)
               : sourceType(SourceType::Modified)
        {
            rec.colorGroup = group;
            rec.colorRole = role;
            rec.colorScheme = scheme;
            rec.lighter = p_lighter;
        }

        // Recursive ocnstructor for color modification
        Source(QPalette::ColorGroup group, QPalette::ColorRole role,
               Qt::ColorScheme scheme, int p_red, int p_green, int p_blue)
               : sourceType(SourceType::Modified)
        {
            rec.colorGroup = group;
            rec.colorRole = role;
            rec.colorScheme = scheme;
            rec.deltaRed = p_red;
            rec.deltaGreen = p_green;
            rec.deltaBlue = p_blue;
        }

        // Recursive constructor for all: color modification and darker/lighter
        Source(QPalette::ColorGroup group, QPalette::ColorRole role,
               Qt::ColorScheme scheme, int p_lighter,
               int p_red, int p_green, int p_blue) : sourceType(SourceType::Modified)
        {
            rec.colorGroup = group;
            rec.colorRole = role;
            rec.colorScheme = scheme;
            rec.lighter = p_lighter;
            rec.deltaRed = p_red;
            rec.deltaGreen = p_green;
            rec.deltaBlue = p_blue;
        }

        // Fixed Source constructor
        Source(const QBrush &brush) : sourceType(SourceType::Fixed)
        {
            fix.fixedBrush = brush;
        };

        // Invalid constructor and getter
        Source() : sourceType(SourceType::Invalid) {};
        bool isValid() const { return sourceType != SourceType::Invalid; }

        // Debug
        QDebug operator<<(QDebug dbg)
        {
            return dbg << "QGtk3Storage::Source(sourceType=" << sourceType << ")";
        }
    };

    // Struct with key attributes to identify a brush: color group, color role and color scheme
    struct TargetBrush {
        QPalette::ColorGroup colorGroup;
        QPalette::ColorRole colorRole;
        Qt::ColorScheme colorScheme;

        // Generic constructor
        TargetBrush(QPalette::ColorGroup group, QPalette::ColorRole role,
                    Qt::ColorScheme scheme = Qt::ColorScheme::Unknown) :
                    colorGroup(group), colorRole(role), colorScheme(scheme) {};

        // Copy constructor with color scheme modifier for dark/light aware search
        TargetBrush(const TargetBrush &other, Qt::ColorScheme scheme) :
            colorGroup(other.colorGroup), colorRole(other.colorRole), colorScheme(scheme) {};

        // struct becomes key of a map, so operator< is needed
        bool operator<(const TargetBrush& other) const {
           return std::tie(colorGroup, colorRole, colorScheme) <
                  std::tie(other.colorGroup, other.colorRole, other.colorScheme);
        }
    };

    // Mapping a palette's brushes to their GTK sources
    typedef QFlatMap<TargetBrush, Source> BrushMap;

    // Storage of palettes and their GTK sources
    typedef QFlatMap<QPlatformTheme::Palette, BrushMap> PaletteMap;

    // Public getters
    const QPalette *palette(QPlatformTheme::Palette = QPlatformTheme::SystemPalette) const;
    QPixmap standardPixmap(QPlatformTheme::StandardPixmap standardPixmap, const QSizeF &size) const;
    Qt::ColorScheme colorScheme() const { return m_colorScheme; };
    static QPalette standardPalette();
    const QString themeName() const { return m_interface ? m_interface->themeName() : QString(); };
    const QFont *font(QPlatformTheme::Font type) const;
    QIcon fileIcon(const QFileInfo &fileInfo) const;

    // Initialization
    void populateMap();
    void handleThemeChange();

private:
    // Storage for palettes and their brushes
    PaletteMap m_palettes;

    std::unique_ptr<QGtk3Interface> m_interface;
#if QT_CONFIG(dbus)
    std::unique_ptr<QGtk3PortalInterface> m_portalInterface;
#endif

    Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;

    // Caches for Pixmaps, fonts and palettes
    mutable QCache<QPlatformTheme::StandardPixmap, QImage> m_pixmapCache;
    mutable std::array<std::optional<QPalette>, QPlatformTheme::Palette::NPalettes> m_paletteCache;
    mutable std::array<std::optional<QFont>, QPlatformTheme::NFonts> m_fontCache;

    // Search brush with a given GTK3 source
    QBrush brush(const Source &source, const BrushMap &map) const;

    // Get GTK3 source for a target brush
    Source brush (const TargetBrush &brush, const BrushMap &map) const;

    // clear cache, palettes and color scheme
    void clear();

    // Data creation, import & export
    void createMapping ();
    const PaletteMap savePalettes() const;
    bool save(const QString &filename, const QJsonDocument::JsonFormat f = QJsonDocument::Indented) const;
    QJsonDocument save() const;
    bool load(const QString &filename);
};

QT_END_NAMESPACE
#endif // QGTK3STORAGE_H