Wireshark 5.1.0
The Wireshark network protocol analyzer
Loading...
Searching...
No Matches
ThemeManager Class Reference

#include <theme_manager.h>

Inheritance diagram for ThemeManager:

Classes

struct  SettableKey

Public Types

enum class  ThemeMode { System , Dark , Light }
enum class  PreviewScheme { Default , PreferLight , PreferDark }
enum  ThemeToken {
  BrandPrimary , AccentSuccess , AccentWarning , AccentError ,
  AccentInfo , ExpertNone , ExpertComment , ExpertChat ,
  ExpertNote , ExpertWarn , ExpertError , ExpertForeground ,
  PacketsSelection , PacketsSelectionText , PacketsInactive , PacketsInactiveText ,
  PacketsMarked , PacketsMarkedText , PacketsIgnored , PacketsIgnoredText ,
  PacketsHidden , ConversationClient , ConversationClientText , ConversationServer ,
  ConversationServerText , FilterValid , FilterInvalid , FilterDeprecated ,
  FilterBusy , FilterBusyText , FilterBookmarkDisplay , FilterBookmarkCapture ,
  FilterBookmarkMatch , FilterClear , FilterApply , FilterHistory ,
  CodeBackground , CodeText , CodeSelection , CodeSelectionText ,
  CodeGutter , CodeGutterText , CodePausedLine , CodeString ,
  CodeKeyword , CodeNumber , CodeBuiltIn , CodeFunctionCall ,
  CodeComment , SyntaxKey , SyntaxString , SyntaxNumber ,
  PaletteWindow , PaletteBase , PaletteText , PaletteWindowText ,
  PaletteAlternateBase , PaletteMid , PaletteMidlight , PaletteHighlight ,
  PaletteHighlightedText , PaletteAccent , HeaderBackground , SectionHeader ,
  SectionHeaderHover , ControlBorder , MutedText , BorderField ,
  BorderSeparator , CardBackground , CardBorder , CardSectionHeader ,
  CardSectionHeaderHover , CardLink , CardLinkHover , CardFocusRing ,
  OverlayCardBackground , OverlayCardBorder , HeaderText , HeaderTextMuted ,
  UpdateBackground , UpdateBorder , UpdateText , UpdateTextHighlight ,
  UpdateLink , UpdateLinkHover , UpdateLinkPressed , UpdateButtonBg ,
  UpdateButtonHover , UpdateButtonPressed , UpdateButtonDisabledBg , UpdateButtonDisabledText ,
  UpdateDismissHoverBg , UpdateDismissPressedBg , UpdateDot , HighlightColorOrange ,
  HighlightColorGreen , TextOnSuccess , TextOnWarning , TextOnError ,
  TextOnInfo , TextOnFilterValid , TextOnFilterInvalid , TextOnFilterDeprecated ,
  DiffAdded , DiffChanged , DiffRemoved , NoticeInfo ,
  NoticeInfoBorder , NoticeError , NoticeErrorBorder , NoRole
}

Signals

void themeChanged ()

Public Member Functions

void cleanup ()
ThemeInfo info () const
bool loadDraft (const QString &internalName, ThemeDraft &out, QString *errorString=nullptr, ThemeParseReport *report=nullptr) const
bool parseDraft (const QByteArray &jsonc, const QString &internalName, ThemeDraft &out, QString *errorString=nullptr, ThemeParseReport *report=nullptr) const
QHash< ThemeToken, ThemeColorPair > resolveDraftTokens (const ThemeDraft &draft, bool dark, QPalette *palette=nullptr, QHash< ThemeToken, const char * > *sources=nullptr, int gui_contrast=UseRecentContrast) const
ThemeToken paletteRoleToken (QPalette::ColorRole role) const
ThemeToken tokenForName (const QString &name) const
const QList< ThemeToken > & requiredTokens () const
const QList< SettableKey > & settableKeys () const
QColor color (ThemeToken role) const
bool colorIsAvailable (ThemeToken role) const
QHash< ThemeToken, QColor > previewTheme (const QString &internalName, PreviewScheme scheme, int gui_contrast=UseRecentContrast, bool *declaresWindow=nullptr) const
bool validateThemeFile (const QString &filePath) const
QString loadStyleSheet (const QString &name) const
bool isDarkMode () const
ThemeMode mode () const
void setMode (ThemeMode mode)
ThemeContrast contrast () const
QColor graphColor (int idx) const
 Returns the graph color for the given index, cycling through available graph colors if necessary.
qsizetype graphColorCount () const
 Returns the number of graph colors defined in the theme.

Static Public Member Functions

static ThemeToken tokenFromName (const QString &name)
static ThemeManager * instance ()
static QString defaultThemeName ()
static QString resolveThemeName (const QString &name)
static void init (const QString &theme=QString())
static QList< ThemeInfo > availableThemes ()
static bool isBuiltInTheme (const QString &internalName)
static QString personalThemesDir ()
static QString personalThemePath (const QString &stem)
static QString selectedThemeName ()
static void setSelectedThemeName (const QString &name)
static QHash< ThemeToken, QColor > flattenTokens (const QHash< ThemeToken, ThemeColorPair > &tokens, bool dark)
static QString styleSheet (const QString &name)
static void setValidationState (QWidget *w, const QString &state)
static void setNoticeState (QWidget *w, const QString &state)
static bool isDark ()
static bool canDetectSystemContrast ()
static bool systemPrefersHighContrast ()
static ThemeContrast effectiveContrast (int gui_contrast, ThemeContrast declared)

Static Public Attributes

static constexpr int UseRecentContrast = -1

Protected Member Functions

 ThemeManager (QObject *parent=nullptr)

Detailed Description

Gateway for Wireshark's theme system.

Owns the process-wide theme state (current theme, mode, token map, font choices, the platform scheme detector) and fronts the public API. Non-trivial work is delegated to helpers under ui/qt/utils/themes/, split by responsibility:

themes/theme_parser.{h,cpp} — reads theme.jsonc themes/theme_token_handler.{h,cpp} — derives Header* / Update* / … from the brand + accent inputs themes/theme_palette_builder.{h,cpp} — constructs the QPalette themes/theme_stylesheet_loader.{h,cpp} — reads :/stylesheets/ and resolves wstheme(...) tokens themes/color_math.{h,cpp} — pure color-math statics (mix/darken/lighten/contrast/…) themes/system_theme_detector*.{h,cpp,mm} — platform-native OS light/dark detection.

A theme file (resources/themes/<name>/theme.jsonc) declares five mandatory colors — brand.primary and four accent.* values. Every other token the UI consumes (Header*, Section*, Update*, Packets*, Conversation*, Expert*, …) is derived from those inputs by ThemeTokenHandler at load time.

Stylesheets reference tokens via wstheme(TokenName). The loader rewrites each occurrence to the resolved #rrggbb hex value at the widget's setStyleSheet() call site.

Member Enumeration Documentation

◆ PreviewScheme

enum class ThemeManager::PreviewScheme
strong

Caller-visible appearance preference for previewTheme().

Mirrors the vocabulary of SystemThemeDetector::Scheme but is intentionally a separate type: previewTheme() is the only public surface that needs it, and reusing the detector enum would leak an otherwise-private dependency to the dialog.

Default — "no preference, resolve against the OS now". previewTheme() asks the system detector, which every back-end resolves to Light or Dark via its startup calibration. PreferLight — caller explicitly wants the light side. PreferDark — caller explicitly wants the dark side.

◆ ThemeMode

enum class ThemeManager::ThemeMode
strong

Selects how the app decides between the light and dark sides of the current theme.

System — follow the OS preference (default). Flips live when the user changes the OS appearance. Dark — always return the dark side, regardless of the OS. Light — always return the light side, regardless of the OS.

Constructor & Destructor Documentation

◆ ThemeManager()

ThemeManager::ThemeManager ( QObject * parent = nullptr)
explicitprotected

CONVENIENCE PRE-CACHING

These pre-caches make it cheap to answer "which theme.jsonc section does this token belong to?" and "which QPalette role does this palette-prefixed token map to?" at runtime. The parser and the palette builder both consult them by string name during a load.

Adding a new token only requires:

  • Append the new ThemeToken to the enum in the header.
  • If a new top-level section is introduced, list it in sections_ below with its required/optional flag. The required flag also makes every token of the section required for the Theme Designer.
  • Name the enumerator <section prefix><file key with its first letter upper-cased>: the enumerator name after the section prefix, first letter lowered, is the key written in theme files (settableKeys()), so it must match the schema.

Everything else (section-to-token grouping, palette-role lookup) falls out of the Q_ENUM metaobject scanning in the loops below.

Member Function Documentation

◆ availableThemes()

QList< ThemeInfo > ThemeManager::availableThemes ( )
static

Enumerates every theme bundled under :/themes/. For each one the JSONC file is parsed to extract its metadata (display name, author, description, internal name). Intended for populating a theme picker in the preferences dialog.

Themes whose JSONC fails to parse are skipped silently (a warning is logged by ThemeParser). The returned list is not sorted — callers that want alphabetical order should sort by display name themselves.

◆ canDetectSystemContrast()

bool ThemeManager::canDetectSystemContrast ( )
static

True when this build can read the OS contrast preference, i.e. it was built with Qt 6.10 or later. Below that the System contrast setting acts as Standard.

◆ color()

QColor ThemeManager::color ( ThemeToken role) const

Returns the resolved color value for a given ThemeToken in the current light/dark mode.

Parameters
roleThe ThemeToken enum value, e.g. ThemeManager::HeaderBackground
Returns
The color defined for the role in the current mode, or an invalid QColor if the role is not defined.

◆ contrast()

ThemeContrast ThemeManager::contrast ( ) const

Contrast level the current theme was applied with: the result of effectiveContrast() for recent.gui_contrast and the theme's declared level at the last apply.

◆ defaultThemeName()

QString ThemeManager::defaultThemeName ( )
static

Internal name of the theme that ships as the out-of-the-box default for the current application flavor. Returns "stratoshark" for Stratoshark builds and "wireshark" for everything else (Wireshark, future flavors without their own theme directory).

Phrased as "wireshark unless stratoshark" so a custom build that strips one flavor's theme but keeps the other still has a working default — no separate ultimate-fallback knob needed. The flavor lookup goes through application_flavor_is_wireshark() (app/application_flavor.h) so the same shared Qt code picks the right default automatically without per-app #ifdef branches.

Use this anywhere you used to write the literal "default" — init(), the recent_common fallback, the preferences picker's "currently selected" comparison, etc.

◆ effectiveContrast()

ThemeContrast ThemeManager::effectiveContrast ( int gui_contrast,
ThemeContrast declared )
static

Resolves the contrast level to apply. High when the theme declares high contrast, when gui_contrast is GUI_CONTRAST_HIGH, or when it is GUI_CONTRAST_SYSTEM and the OS prefers high contrast; Standard otherwise.

Parameters
gui_contrasta gui_contrast_e value (ui/recent.h).
declaredthe level the theme file declares.

◆ flattenTokens()

QHash< ThemeManager::ThemeToken, QColor > ThemeManager::flattenTokens ( const QHash< ThemeToken, ThemeColorPair > & tokens,
bool dark )
static

Picks one side of every pair of a resolved token table.

◆ graphColor()

QColor ThemeManager::graphColor ( int idx) const

Returns the graph color for the given index, cycling through available graph colors if necessary.

NOTE: if no graph colors are defined, this will return an invalid QColor. NOTE: the index will be modulo'd by the number of available graph colors, so callers can safely pass any index and it will cycle through the defined colors.

Parameters
idxthe index for the graph color.
Returns
QColor

◆ graphColorCount()

qsizetype ThemeManager::graphColorCount ( ) const

Returns the number of graph colors defined in the theme.

Returns
int > 0 if graph colors are defined, 0 if not.

◆ info()

ThemeInfo ThemeManager::info ( ) const

Returns metadata about the currently loaded theme.

◆ init()

void ThemeManager::init ( const QString & theme = QString())
static

Initializes the ThemeManager by loading the default theme from the built-in resources. Call once during application startup after QApplication is constructed.

◆ isBuiltInTheme()

bool ThemeManager::isBuiltInTheme ( const QString & internalName)
static

True when internalName is a theme bundled as a resource (:/themes/<name>/theme.jsonc exists).

◆ isDark()

bool ThemeManager::isDark ( )
static

Convenience shortcut for ThemeManager::instance()->isDarkMode().

The color-manipulation helpers (mix, darken, contrastingText, …) previously declared here have moved to ColorMath in ui/qt/utils/themes/color_math.h.

◆ isDarkMode()

bool ThemeManager::isDarkMode ( ) const

Returns true if the current appearance is dark.

Resolves in this order:

  • ThemeMode::Dark → true
  • ThemeMode::Light → false
  • ThemeMode::System → value reported by the platform-native SystemThemeDetector. If the detector cannot determine the OS preference, falls back to Qt's own QStyleHints::colorScheme() (Qt ≥ 6.5), and finally to a QPalette window/text luminance comparison.

This is the single authority for the "is the app dark?" question. The static isDark() convenience delegates here.

Named *Mode because the class also has a static isDark(QColor) luminance helper; keeping the instance method's name distinct avoids overload confusion at call sites.

◆ loadDraft()

bool ThemeManager::loadDraft ( const QString & internalName,
ThemeDraft & out,
QString * errorString = nullptr,
ThemeParseReport * report = nullptr ) const

Loads and parses a theme into an editable draft without touching the live theme state. The built-in-then-personal lookup is the one loadTheme() uses. The draft holds exactly what the parser stored, so entries with an invalid color are still present; see ThemeDraft::removeInvalidEntries().

Parameters
internalNametheme to load.
outfilled on success, including info.builtIn and info.filePath.
errorStringoptional; set to the fatal error on failure.
reportoptional; receives the non-fatal parse messages.
Returns
true on a usable parse.

◆ loadStyleSheet()

QString ThemeManager::loadStyleSheet ( const QString & name) const

Loads a QSS stylesheet from the built-in :/stylesheets/ resource tree and replaces all wstheme(TokenName) references with their resolved color values. Thin delegator; see ThemeStyleSheetLoader::load() for the full semantics.

The result is scaled by the current text zoom: font sizes (px and pt in font / font-size) and every other Npx length greater than 1 (heights, radii, padding, margins, sizes) grow with FontManager::zoomFactor(). 0px and 1px, comments and url() are left alone, and zoom level 0 returns the text unchanged.

The stylesheet is always looked up under :/stylesheets/, with a ".qss" extension automatically appended. The name is sanitized to prevent path traversal: it must consist of alphanumerics, underscores, hyphens, dots and forward slashes only, must not start with '/' or '.', and must not contain "..". Invalid or missing stylesheets fail silently and return an empty string.

Parameters
nameLogical stylesheet name relative to :/stylesheets/, without extension, e.g. "widgets/learn-card".
Returns
The processed stylesheet string, or an empty string if the name is invalid or the file could not be read.

◆ mode()

ThemeManager::ThemeMode ThemeManager::mode ( ) const

Returns the currently active mode. Reflects whichever of gui.color_scheme the user picked at app start plus any live setMode() calls (setMode is currently only invoked by the preferences re-apply path).

◆ paletteRoleToken()

ThemeManager::ThemeToken ThemeManager::paletteRoleToken ( QPalette::ColorRole role) const

The Palette<Role> token of role.

Returns
the token, NoRole when the role has none.

◆ parseDraft()

bool ThemeManager::parseDraft ( const QByteArray & jsonc,
const QString & internalName,
ThemeDraft & out,
QString * errorString = nullptr,
ThemeParseReport * report = nullptr ) const

Like loadDraft(), but parses theme file content that is already in memory (for example an import candidate).

Parameters
jsonctheme file content.
internalNamename stored on the draft.
outfilled on success.
errorStringoptional; set to the fatal error on failure.
reportoptional; receives the non-fatal parse messages.
Returns
true on a usable parse.

◆ personalThemePath()

QString ThemeManager::personalThemePath ( const QString & stem)
static

Path of the personal theme file <stem>.jsonc.

Returns
empty when the personal themes directory is unknown.

◆ personalThemesDir()

QString ThemeManager::personalThemesDir ( )
static

Directory that holds the user's personal theme files.

◆ previewTheme()

QHash< ThemeManager::ThemeToken, QColor > ThemeManager::previewTheme ( const QString & internalName,
PreviewScheme scheme,
int gui_contrast = UseRecentContrast,
bool * declaresWindow = nullptr ) const

Resolves the color table for a named theme in the requested light/dark mode without altering live application state.

Runs the same parser + derive pipeline as loadTheme(), but on a stack-local copy of the parsed result — the active theme, application palette, and stylesheet are untouched. Useful for offering a "preview" of a theme inside the preferences dialog: the dropdown can drive a swatch / mockup widget with no risk of leaking partial state into the running app.

Returns an empty hash if the theme cannot be found or fails to parse — callers should treat that as "fall back to the live ThemeManager's colors".

Parameters
internalNameinternal theme name (e.g. "default").
schemewhich light/dark side to render. Default defers to the OS detector so the preview tracks the live system preference; the Prefer* variants pin the side regardless of the live mode or OS.
gui_contrastgui_contrast_e value to preview, resolved with effectiveContrast() against the theme's declared level. The default UseRecentContrast reads recent.gui_contrast, so a caller that does not pass it previews the saved setting.
declaresWindowif not null, set to whether the theme itself declares palette.window: the test colorIsAvailable(PaletteWindow) makes for the applied theme. False when the theme cannot be loaded. The returned hash always carries PaletteWindow, so it cannot answer this.
Returns
token → resolved QColor for the requested mode.

◆ requiredTokens()

const QList< ThemeToken > & ThemeManager::requiredTokens ( ) const
inline

Every token of a section the parser requires (sections_ entries flagged required), in enum order. A theme must set all of them.

◆ resolveDraftTokens()

QHash< ThemeManager::ThemeToken, ThemeColorPair > ThemeManager::resolveDraftTokens ( const ThemeDraft & draft,
bool dark,
QPalette * palette = nullptr,
QHash< ThemeToken, const char * > * sources = nullptr,
int gui_contrast = UseRecentContrast ) const

Resolves the complete token table of a draft for one side: the baseline palette the live theme builds on when that side is the live mode (the built-in palette of that side otherwise), the theme's palette overrides, every derived token, and every palette token pinned into the requested side when the theme leaves it out. Live application state is not touched.

Parameters
draftthe draft to resolve.
darktrue for the dark side, false for the light side.
paletteoptional; receives the palette built for that side.
sourcesoptional; receives the rule text of every derived token, see ThemeTokenHandler::deriveAll().
gui_contrastgui_contrast_e value to resolve with, combined with the draft's declared level by effectiveContrast(). The default UseRecentContrast reads recent.gui_contrast, the level the live theme is applied with.
Returns
token to color pair; only the requested side is guaranteed to be filled for derived tokens.

◆ resolveThemeName()

QString ThemeManager::resolveThemeName ( const QString & name)
static

Normalises a saved-theme-name to a current resource name.

Recognises the legacy sentinel "default" (written by older builds that knew only one theme directory) and empty strings as "use whatever this flavor considers default" — both get mapped to defaultThemeName(). Any other input is returned unchanged and assumed to be a real theme directory name; the caller is responsible for handling the case where that directory has been removed from the build.

◆ selectedThemeName()

QString ThemeManager::selectedThemeName ( )
static

Name of the theme the user selected (recent.gui_theme_name), mapped through resolveThemeName().

◆ setMode()

void ThemeManager::setMode ( ThemeMode mode)

Switches the mode. If the new mode differs from the current one, re-runs the theme's derive/apply path and emits themeChanged so cached stylesheets reload. Does NOT persist to preferences; that is the caller's responsibility.

◆ setNoticeState()

void ThemeManager::setNoticeState ( QWidget * w,
const QString & state )
static

Sets the wsNotice property ("info", "error", or empty to clear) that application.qss styles as a notice banner, and repolishes, including the frame widths, so the rule's border and padding move the text in from the frame.

◆ setSelectedThemeName()

void ThemeManager::setSelectedThemeName ( const QString & name)
static

Stores name as the selected theme (recent.gui_theme_name); an empty name clears it. It only stores the choice; the caller emits PreferencesChanged to apply it.

◆ settableKeys()

const QList< SettableKey > & ThemeManager::settableKeys ( ) const
inline

Every token a theme file can set, in enum order. Section and key are derived from the enumerator name: the sections_ name it starts with, then the rest with its first letter lowered (PacketsSelectionText -> packets.selectionText).

◆ setValidationState()

void ThemeManager::setValidationState ( QWidget * w,
const QString & state )
static

Marks a widget as being in a named validation state for QSS rule matching. Sets the dynamic property wsValidation on w and re-polishes the widget so selectors in ui/stylesheets/application.qss (e.g. QLineEdit[wsValidation="invalid"]) take effect immediately.

Pass an empty QString to clear the state and fall back to the default palette. Conventional values are "valid", "invalid", and "deprecated" — see application.qss.

◆ styleSheet()

QString ThemeManager::styleSheet ( const QString & name)
static

Convenience static accessor equivalent to ThemeManager::instance()->loadStyleSheet(name)

Allows callers to load a themed stylesheet without first resolving the singleton, e.g. widget->setStyleSheet(ThemeManager::styleSheet("widgets/learn-card"));

Parameters
nameLogical stylesheet name relative to :/stylesheets/, without extension, e.g. "widgets/learn-card".
Returns
The processed stylesheet string, or an empty string if the name is invalid or the file could not be read.

◆ systemPrefersHighContrast()

bool ThemeManager::systemPrefersHighContrast ( )
static

True when the OS reports a high-contrast preference. Always false when canDetectSystemContrast() is false.

◆ tokenForName()

ThemeManager::ThemeToken ThemeManager::tokenForName ( const QString & name) const

The token a rule text or theme key names, such as palette.highlight or HeaderText, by the same name rule as the theme files.

Returns
the token, NoRole when the name is not a token.

◆ tokenFromName()

ThemeManager::ThemeToken ThemeManager::tokenFromName ( const QString & name)
static

ThemeToken enumerator named exactly name (case-sensitive), as written in wstheme() stylesheet references and in theme resources such as learn_card.json and SVG token maps.

Returns
The token, or NoRole when no enumerator has that name.

◆ validateThemeFile()

bool ThemeManager::validateThemeFile ( const QString & filePath) const

Runs ThemeParser on filePath and returns true if it produces a usable result. Reuses the live section / role caches so the validation criteria match what a real load would apply — required sections, required tokens, schema-typed values.

Intended for callers that have just written a theme file and need to confirm it parses before persisting a reference to it (e.g. the legacy color prefs migration, which avoids stamping recent.gui_theme_name with a name that points at a broken file).

Parameters
filePathAbsolute filesystem path to the candidate JSONC.
Returns
true if the file parses cleanly; false on any parse error.

Member Data Documentation

◆ UseRecentContrast

int ThemeManager::UseRecentContrast = -1
staticconstexpr

previewTheme() argument meaning "preview the saved contrast setting (recent.gui_contrast)". Not a gui_contrast_e value.


The documentation for this class was generated from the following files: