Cockatrice 2026-10-19-Development-3.1.2-beta.2
A virtual tabletop for multiplayer card games
Loading...
Searching...
No Matches
theme_manager.h
Go to the documentation of this file.
1
6
7#ifndef THEMEMANAGER_H
8#define THEMEMANAGER_H
9
10#include "theme_config.h"
11
12#include <QBrush>
13#include <QColor>
14#include <QLoggingCategory>
15#include <QMap>
16#include <QObject>
17#include <QPalette>
18#include <QString>
19#include <QStringView>
20#include <array>
21#include <qtmetamacros.h>
22
23inline Q_LOGGING_CATEGORY(ThemeManagerLog, "theme_manager");
24
27
28class ThemeManager : public QObject
29{
30 Q_OBJECT
31public:
32 ThemeManager(QObject *parent = nullptr);
33
43
44private:
46 // Pristine application palette captured at startup, before any custom theme
47 // palette is applied. Used as the base when a theme supplies no palette, so
48 // switching away from a custom palette restores the original colours.
51 std::array<QBrush, Role::MaxRole + 1> brushes;
54 /*
55 Internal cache for multiple backgrounds
56 */
57 std::array<QBrushMap, Role::MaxRole + 1> brushesCache;
58
59protected:
61 QBrush loadBrush(QString fileName, QColor fallbackColor);
62 QBrush loadExtraBrush(QString fileName, QBrush &fallbackBrush);
63 void applyStyleAndPalette(const QString &themeName,
64 const ThemeConfig &themeCfg,
65 const PaletteConfig &palCfg,
66 const QString &activeScheme);
67
68public:
69 // Resolves the directory to write theme changes to for the given theme
70 // name. The resolved theme dir (user or system) is used when writable;
71 // read-only system themes fall back to the user themes directory, creating
72 // it if needed, so customisations never get lost on upgrade.
73 static QString writableThemeDir(const QString &themeName);
74 // Carries a user profile's customised "Default" theme directory over to the
75 // "System" directory the theme was renamed to, so zone graphics,
76 // stylesheets, palettes and theme.cfg survive the rename. Renames the
77 // directory when "System" does not exist yet, otherwise merges file by
78 // file without overwriting what "System" already has. No-op unless the
79 // active theme is one of the two names, so a hand-made "Default" folder of
80 // a user on another theme is left alone.
81 static void migrateLegacyThemeDir(const QString &themesPath, const QString &currentThemeName);
82 // Probe whether a directory is truly writable by trying to create and remove
83 // a temporary file. QFileInfo::isWritable() on a directory is unreliable
84 // (notably on Windows where UAC VirtualStore can make a system dir appear
85 // writable).
86 static bool isDirReallyWritable(const QString &dirPath);
87 // Explicit color scheme of the theme: theme.cfg's ColorScheme setting
88 // (Dark/Light), falling back to the OS color scheme when it is "System".
89 bool isDarkMode(const QString &themeDirPath) const;
90 // The resolved scheme of the currently active theme.
91 bool isDarkModeActive() const
92 {
94 }
96 // Returns the path to the currently active theme directory (empty = default)
97 QString getCurrentThemePath() const
98 {
99 return currentThemePath;
100 }
101 // Load the global theme settings (style + color scheme preference)
102 static ThemeConfig loadGlobalConfig(const QString &themeDirPath);
103 static bool saveGlobalConfig(const QString &themeDirPath, const ThemeConfig &cfg);
104
105 // Load/save per-scheme palette colors
106 static PaletteConfig loadPaletteConfig(const QString &themeDirPath, const QString &colorScheme);
107 static bool savePaletteConfig(const QString &themeDirPath, const QString &colorScheme, const PaletteConfig &cfg);
108 // Resolve prefix to a scheme-qualified "theme:" path. Existence is probed
109 // internally across the formats themes may ship (.png/.jpg/.svg), so
110 // callers load the returned path directly. Prefers "<prefix>-<dark|light>"
111 // when a file exists at that stem, otherwise the plain "<prefix>" as the
112 // super fallback. The resolved scheme covers explicit light/dark as well
113 // as OS-resolved "system". Returns the path with its file extension when a
114 // match is found; unqualified assets keep working unchanged.
115 QString assetPath(QStringView prefix) const;
116 // Like assetPath, but resolves only the scheme-qualified variant
117 // ("<prefix>-<dark|light>.<ext>") and returns an empty string when no
118 // variant exists — it never falls back to the plain "<prefix>" asset.
119 // Callers that must distinguish "no authored variant" (e.g. to keep a
120 // legacy runtime fallback alive) should use this instead of assetPath.
121 QString schemeVariantPath(QStringView prefix) const;
122 // Load the theme's shipped default palette, falling back to the system
123 // theme directory when it is absent from the resolved (user) directory.
124 static PaletteConfig
125 loadDefaultPaletteConfig(const QString &themeDirPath, const QString &themeName, const QString &colorScheme);
129 static bool commitPalette(const QString &themeDirPath, const QString &colorScheme, const PaletteConfig &cfg);
130 void setColorScheme(const QString &scheme);
131 void setStyleName(const QString &styleName);
132
133 void reloadCurrentTheme();
134 void previewPalette(const PaletteConfig &cfg, const QString &scheme);
135
136 // Resolves an application color role: the theme's stored [AppColors] value
137 // when present, otherwise a palette-accent-derived fallback.
138 QColor appColor(AppColor::Role role) const;
139
140 QBrush &getBgBrush(Role zone);
141 QBrush getExtraBgBrush(Role zone, int zoneId = 0);
142protected slots:
143 void themeChangedSlot();
144signals:
147};
148
150
151#endif
Definition game.h:18
Definition theme_manager.h:29
static QString writableThemeDir(const QString &themeName)
Definition theme_manager.cpp:307
void paletteChanged()
QBrush loadBrush(QString fileName, QColor fallbackColor)
Definition theme_manager.cpp:363
QBrush & getBgBrush(Role zone)
Definition theme_manager.cpp:698
void setStyleName(const QString &styleName)
Definition theme_manager.cpp:467
QColor appColor(AppColor::Role role) const
Definition theme_manager.cpp:564
QMap< AppColor::Role, QColor > currentAppColors
Definition theme_manager.h:53
QString defaultStyleName
Definition theme_manager.h:45
Role
Definition theme_manager.h:35
@ Table
Definition theme_manager.h:39
@ Hand
Definition theme_manager.h:37
@ MinRole
Definition theme_manager.h:36
@ Player
Definition theme_manager.h:40
@ MaxRole
Definition theme_manager.h:41
@ Stack
Definition theme_manager.h:38
QString assetPath(QStringView prefix) const
Definition theme_manager.cpp:265
std::array< QBrushMap, Role::MaxRole+1 > brushesCache
Definition theme_manager.h:57
bool isDarkMode(const QString &themeDirPath) const
Definition theme_manager.cpp:233
static PaletteConfig loadDefaultPaletteConfig(const QString &themeDirPath, const QString &themeName, const QString &colorScheme)
Definition theme_manager.cpp:429
std::array< QBrush, Role::MaxRole+1 > brushes
Definition theme_manager.h:51
QString currentThemePath
Definition theme_manager.h:50
void setColorScheme(const QString &scheme)
Definition theme_manager.cpp:456
static ThemeConfig loadGlobalConfig(const QString &themeDirPath)
Definition theme_manager.cpp:391
void themeChanged()
static bool saveGlobalConfig(const QString &themeDirPath, const ThemeConfig &cfg)
Definition theme_manager.cpp:396
bool isDarkModeActive() const
Definition theme_manager.h:91
void themeChangedSlot()
Definition theme_manager.cpp:591
QBrush loadExtraBrush(QString fileName, QBrush &fallbackBrush)
Definition theme_manager.cpp:377
QPalette defaultPalette
Definition theme_manager.h:49
void applyStyleAndPalette(const QString &themeName, const ThemeConfig &themeCfg, const PaletteConfig &palCfg, const QString &activeScheme)
Definition theme_manager.cpp:491
static bool isDirReallyWritable(const QString &dirPath)
Definition theme_manager.cpp:295
void reloadCurrentTheme()
Definition theme_manager.cpp:478
QStringMap & getAvailableThemes()
Definition theme_manager.cpp:334
static bool commitPalette(const QString &themeDirPath, const QString &colorScheme, const PaletteConfig &cfg)
Writes cfg to disk as the theme's palette-<scheme>.toml and updates the theme's stored colour scheme ...
Definition theme_manager.cpp:443
QString getCurrentThemePath() const
Definition theme_manager.h:97
static PaletteConfig loadPaletteConfig(const QString &themeDirPath, const QString &colorScheme)
Definition theme_manager.cpp:401
QBrush getExtraBgBrush(Role zone, int zoneId=0)
Definition theme_manager.cpp:703
static bool savePaletteConfig(const QString &themeDirPath, const QString &colorScheme, const PaletteConfig &cfg)
Definition theme_manager.cpp:409
void previewPalette(const PaletteConfig &cfg, const QString &scheme)
Definition theme_manager.cpp:483
static void migrateLegacyThemeDir(const QString &themesPath, const QString &currentThemeName)
Definition theme_manager.cpp:171
void ensureThemeDirectoryExists()
Definition theme_manager.cpp:214
QString schemeVariantPath(QStringView prefix) const
Definition theme_manager.cpp:250
ThemeManager(QObject *parent=nullptr)
Definition theme_manager.cpp:127
QStringMap availableThemes
Definition theme_manager.h:52
Q_LOGGING_CATEGORY(CrashReportLog, "crash_report")
Role
Definition theme_config.h:19
QMap< QString, QString > QStringMap
Definition sound_engine.h:21
Definition theme_config.h:39
Definition theme_config.h:27
QMap< int, QBrush > QBrushMap
Definition theme_manager.h:26
ThemeManager * themeManager
Definition main.cpp:84
QMap< QString, QString > QStringMap
Definition theme_manager.h:25