Wireshark 5.1.0
The Wireshark network protocol analyzer
Loading...
Searching...
No Matches
theme_manager.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include <QColor>
13#include <QFont>
14#include <QHash>
15#include <QMutex>
16#include <QObject>
17#include <QPalette>
18#include <QString>
19
21
25struct ThemeInfo {
26 QString name;
27 QString internalName;
28 int version = 0;
29 QString description;
30 QString author;
31};
32
34 bool required;
35 QStringList tokens;
36};
37
39 QColor light;
40 QColor dark;
41};
42
73class ThemeManager : public QObject {
74 Q_OBJECT
75public:
76
86 enum class ThemeMode {
87 System,
88 Dark,
89 Light
90 };
91 Q_ENUM(ThemeMode)
92
93
108 enum class PreviewScheme {
109 Default,
110 PreferLight,
111 PreferDark
112 };
113 Q_ENUM(PreviewScheme)
114
115 enum ThemeToken {
116 // Brand
117 BrandPrimary,
118
119 // Accent
120 AccentSuccess,
121 AccentWarning,
122 AccentError,
123 AccentInfo,
124
125 // Expert
126 ExpertNone,
127 ExpertComment,
128 ExpertChat,
129 ExpertNote,
130 ExpertWarn,
131 ExpertError,
132 ExpertForeground,
133
134 // Packets — for each state, <Name> is the row background tint and
135 // <Name>Text is the foreground. Hidden is text-only by design (it
136 // dims an item that otherwise renders with the normal row bg).
137 // When a theme omits a Text token, ThemeTokenHandler derives it
138 // from contrastingText(<Name>) or PaletteText as appropriate.
139 PacketsSelection,
140 PacketsSelectionText,
141 PacketsInactive,
142 PacketsInactiveText,
143 PacketsMarked,
144 PacketsMarkedText,
145 PacketsIgnored,
146 PacketsIgnoredText,
147 PacketsHidden,
148
149 // Conversation — same fg/bg convention as Packets.
150 ConversationClient,
151 ConversationClientText,
152 ConversationServer,
153 ConversationServerText,
154
155 // Filter state (single color per state — use as bg tint; pair
156 // with QPalette::Text for foreground). Derived from accent
157 // when no explicit theme.filter override is set; the JSONC
158 // "filter" section lets a theme pin saturated/historical values
159 // that alpha-tinting the accent can't reach. FilterBusy and
160 // FilterBusyText carry the "I'm working" look used while a
161 // capture filter compiles off-thread.
162 FilterValid,
163 FilterInvalid,
164 FilterDeprecated,
165 FilterBusy,
166 FilterBusyText,
167
168 // Inline filter-affordance glyph colours (icon fills, not bg tints):
169 // the bookmark / clear / apply buttons inside the filter line. Each
170 // derives from the matching accent when a theme omits it (so every
171 // theme has them defined), and theme.filter.<name> overrides per-token.
172 // Display and capture bookmarks differ on purpose (blue vs green); the
173 // match colour marks a filter already saved.
174 FilterBookmark, // display-filter bookmark (← AccentInfo, blue)
175 FilterBookmarkCapture, // capture-filter bookmark (← AccentSuccess, green)
176 FilterBookmarkMatch, // current filter is saved (← AccentWarning, yellow)
177 FilterClear, // clear affordance (active) (← AccentError, red)
178 FilterApply, // apply affordance (← AccentInfo, blue)
179 FilterHistory, // recent-filters arrow, dimmed at rest (← PaletteMid);
180 // the default theme pins the classic Tango grays
181 // (#555753 / #d3d7cf) via theme.filter.history.
182
183 // Syntax highlighting — foreground text colours for code- and
184 // data-viewers (JSON, hex, Lua debugger, etc.). Derived so
185 // the variant is darker in light mode and lighter in dark
186 // mode, keeping enough contrast against PaletteBase.
187 SyntaxKey,
188 SyntaxString,
189 SyntaxNumber,
190
191 // Palette Overrides
192 PaletteWindow,
193 PaletteBase,
194 PaletteText,
195 PaletteWindowText,
196 PaletteAlternateBase,
197 PaletteMid,
198 PaletteMidLight,
199 // Selection background — when omitted, the builder uses
200 // packets.selection, else brand.primary.
201 PaletteHighlight,
202 // Selection foreground — when omitted, the builder picks
203 // contrastingText() of the resolved highlight. Themes whose
204 // selection colour sits on the WCAG luminance threshold (e.g.
205 // saturated mid-tone teals/blues where contrastingText flips to
206 // black even though white reads better) can pin this explicitly
207 // to white.
208 PaletteHighlightedText,
209#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
210 PaletteAccent,
211#endif
212
213 // Welcome header bar (derived from the palette's Highlight)
214 HeaderBackground,
215
216 // Section headers (derived from brand + QPalette)
217 SectionHeader,
218 SectionHeaderHover,
219
220 // Structural form chrome — borders, dividers, muted text.
221 // FieldBorder is the WCAG-enforced derivation of palette.mid
222 // against palette.base (≥ 3.0:1 ratio), used to frame
223 // interactive controls without overshooting like palette.shadow
224 // does in light mode. Separator is a softer mix of base + mid
225 // for hairlines between cards / sections; themes can override
226 // it via the JSONC "separator" top-level key when the derived
227 // value is too pronounced (Stratoshark uses an explicit value
228 // matching its midlight). MutedText is a derived de-emphasized
229 // text color (palette text mixed toward base, contrast-adapted
230 // to base) for secondary labels and plot reference lines.
231 FieldBorder,
232 Separator,
233 MutedText,
234
235 // Welcome header title and version text (derived with HeaderBackground)
236 HeaderText,
237 HeaderTextMuted,
238
239 // Update bar (derived from accent.success)
240 UpdateBackground,
241 UpdateBorder,
242 UpdateText,
243 UpdateTextHighlight,
244 UpdateLink,
245 UpdateLinkHover,
246 UpdateLinkPressed,
247 UpdateButtonBg,
248 UpdateButtonHover,
249 UpdateButtonPressed,
250 UpdateButtonDisabledBg,
251 UpdateButtonDisabledText,
252 UpdateDismissHoverBg,
253 UpdateDismissPressedBg,
254
255 // Accent aliases (derived)
256 HighlightColorOrange,
257 HighlightColorGreen,
258
259 // Foreground colors for solid accent backgrounds — derived via
260 // contrastingText() so they pick black or white depending on
261 // the accent's WCAG luminance. Use these when a QSS rule
262 // paints text on top of an accent-coloured surface (the
263 // "Development Build" badge, the "Download Update" button,
264 // etc.) so the text stays readable across themes whose
265 // accents fall on different sides of the contrast threshold.
266 //
267 // NOTE: these are intentionally named `TextOn*` rather than
268 // `Accent*Text`. ThemeManager's section auto-grouping treats
269 // any enum name starting with "accent" as a required input in
270 // the "accent" JSONC section (theme_manager.cpp section loop),
271 // so `Accent*Text` derived tokens would make the parser demand
272 // them from every theme file. The `TextOn*` prefix keeps
273 // them out of the accent section.
274 TextOnSuccess,
275 TextOnWarning,
276 TextOnError,
277 TextOnInfo,
278
279 // Foreground on the filter validity tints, derived as the
280 // contrastingText() of the matching Filter* token. Named
281 // `TextOn*` for the same section-grouping reason as above.
282 TextOnFilterValid,
283 TextOnFilterInvalid,
284 TextOnFilterDeprecated,
285
286 // None
287 NoRole
288 };
289 Q_ENUM(ThemeToken)
290
291 static ThemeManager* instance();
292
311 static QString defaultThemeName();
312
324 static QString resolveThemeName(const QString &name);
325
331 static void init(const QString &theme = QString());
332
333 void cleanup();
334
338 ThemeInfo info() const;
339
351 static QList<ThemeInfo> availableThemes();
352
361 QColor color(ThemeToken role) const;
362
363 bool colorIsAvailable(ThemeToken role) const;
364
388 QHash<ThemeToken, QColor> previewTheme(const QString &internalName,
389 PreviewScheme scheme) const;
390
405 bool validateThemeFile(const QString &filePath) const;
406
425 QString loadStyleSheet(const QString &name) const;
426
440 static QString styleSheet(const QString &name);
441
453 static void setValidationState(QWidget *w, const QString &state);
454
460 static bool isDark();
461
482 bool isDarkMode() const;
483
490 ThemeMode mode() const;
491
498 void setMode(ThemeMode mode);
499
510 QColor graphColor(int idx) const;
511
512 QColor graphDefaultColor() const;
513
519 qsizetype graphColorCount() const;
520
521signals:
522 void themeChanged();
523
524protected:
525 explicit ThemeManager(QObject *parent = nullptr);
527
528private:
529 static ThemeManager* instance_;
530 static QMutex mutex_;
531
532 ThemeInfo info_;
533
534 // Flattened token -> color value, one map per mode
535 QHash<ThemeManager::ThemeToken, ThemeColorPair> themeColors_;
537 QHash<ThemeManager::ThemeToken, ThemeColorPair> parsedColors_;
538 QList<ThemeColorPair> graphColors_;
539
540 QHash<QString, ThemeSectionInfo> sections_;
541
542 // mapping caches for role and palette resolution
543 QHash<QString, ThemeToken> colorRoleCache_;
544 QHash<QString, QPalette::ColorRole> paletteRoleCache_;
545
546 // Light/dark selection: user's explicit choice plus the detector
547 // that tracks the OS preference when mode == System. The detector
548 // is a private member — external code never sees it. Lifetime is
549 // managed via Qt's parent-child ownership: constructed with `this`
550 // as parent, destroyed automatically with the ThemeManager.
551 ThemeMode mode_ = ThemeMode::System;
552 SystemThemeDetector *detector_ = nullptr;
553
554 // Pristine OS palette snapshot used as the baseline when the palette
555 // builder constructs a new theme palette. Captured once at ctor
556 // entry (before any setPalette() call could pollute QApplication's
557 // live palette), and refreshed from `qApp->style()->standardPalette()`
558 // whenever the effective light/dark scheme changes (mode flip or OS
559 // notification). Using this snapshot instead of
560 // QApplication::palette() prevents the previous theme's palette
561 // overrides from leaking into the next theme's baseline — without it,
562 // switching from a theme with palette overrides (e.g. "inverted") to
563 // one without (e.g. "default") would leave the prior overrides
564 // visible. Only consulted on platforms where the OS palette is
565 // trusted (macOS, Windows Qt ≥ 6.8); ignored elsewhere.
566 QPalette osBaseline_;
567
578 QPalette baselineForBuild() const;
579
586 void reapplyForSchemeChange();
587
593 static ThemeMode modeFromPrefs(int gui_color_scheme);
594
601 void applyToStyleHints();
602
609 void applyApplicationStyleSheet();
610
624 bool loadTheme(const QString &themeName = QString());
625
626};
Definition system_theme_detector.h:38
static bool isDark()
Definition theme_manager.cpp:367
static void init(const QString &theme=QString())
Definition theme_manager.cpp:256
void setMode(ThemeMode mode)
Definition theme_manager.cpp:412
QColor graphColor(int idx) const
Returns the graph color for the given index, cycling through available graph colors if necessary.
Definition theme_manager.cpp:821
static QString styleSheet(const QString &name)
Definition theme_manager.cpp:614
PreviewScheme
Definition theme_manager.h:108
QString loadStyleSheet(const QString &name) const
Definition theme_manager.cpp:606
ThemeMode
Definition theme_manager.h:86
ThemeMode mode() const
Definition theme_manager.cpp:407
static QString defaultThemeName()
Definition theme_manager.cpp:228
QHash< ThemeToken, QColor > previewTheme(const QString &internalName, PreviewScheme scheme) const
Definition theme_manager.cpp:630
qsizetype graphColorCount() const
Returns the number of graph colors defined in the theme.
Definition theme_manager.cpp:848
bool isDarkMode() const
Definition theme_manager.cpp:372
static void setValidationState(QWidget *w, const QString &state)
Definition theme_manager.cpp:619
static QList< ThemeInfo > availableThemes()
Definition theme_manager.cpp:293
static QString resolveThemeName(const QString &name)
Definition theme_manager.cpp:244
bool validateThemeFile(const QString &filePath) const
Definition theme_manager.cpp:722
ThemeManager(QObject *parent=nullptr)
Definition theme_manager.cpp:88
ThemeInfo info() const
Definition theme_manager.cpp:288
QColor color(ThemeToken role) const
Definition theme_manager.cpp:523
Definition theme_manager.h:38
Definition theme_manager.h:25
int version
Schema version (currently 1).
Definition theme_manager.h:28
QString name
Display name, e.g. "Wireshark Default".
Definition theme_manager.h:26
QString author
Theme author or organization.
Definition theme_manager.h:30
QString description
One-line description shown in preferences.
Definition theme_manager.h:29
QString internalName
Internal name, e.g. "default".
Definition theme_manager.h:27
Definition theme_manager.h:33