Remove namespace, fold I/O into structs.

Took 12 minutes
This commit is contained in:
Lukas Brübach 2026-05-17 09:26:49 +02:00
parent 829d1a1e9c
commit a39e133351
4 changed files with 115 additions and 99 deletions

View file

@ -163,8 +163,8 @@ void PaletteEditorDialog::retranslateUi()
titleLabel->setText(tr("<b>Palette Editor</b> &nbsp;·&nbsp; %1").arg(themeName)); titleLabel->setText(tr("<b>Palette Editor</b> &nbsp;·&nbsp; %1").arg(themeName));
// Revert button only makes sense when the theme ships default palette files // Revert button only makes sense when the theme ships default palette files
const bool hasDefault = ThemeConfigParser::parsePaletteDefault(themeDirPath, "Light").hasPalette() || const bool hasDefault = PaletteConfig::fromDefault(themeDirPath, "Light").hasPalette() ||
ThemeConfigParser::parsePaletteDefault(themeDirPath, "Dark").hasPalette(); PaletteConfig::fromDefault(themeDirPath, "Dark").hasPalette();
revertButton->setEnabled(hasDefault); revertButton->setEnabled(hasDefault);
if (!hasDefault) { if (!hasDefault) {
revertButton->setToolTip(tr("This theme ships no default palette files")); revertButton->setToolTip(tr("This theme ships no default palette files"));
@ -195,10 +195,10 @@ void PaletteEditorDialog::loadSchemes()
{ {
const QStringList schemes = {"Light", "Dark"}; const QStringList schemes = {"Light", "Dark"};
for (const QString &scheme : schemes) { for (const QString &scheme : schemes) {
PaletteConfig cfg = ThemeConfigParser::parsePaletteForScheme(themeDirPath, scheme); PaletteConfig cfg = PaletteConfig::fromScheme(themeDirPath, scheme);
if (!cfg.hasPalette()) { if (!cfg.hasPalette()) {
cfg = ThemeConfigParser::parsePaletteDefault(themeDirPath, scheme); cfg = PaletteConfig::fromDefault(themeDirPath, scheme);
} }
if (!cfg.hasPalette()) { if (!cfg.hasPalette()) {
@ -259,13 +259,13 @@ void PaletteEditorDialog::onSave()
if (!ThemeManager::savePaletteConfig(themeDirPath, loadedScheme, cfg)) { if (!ThemeManager::savePaletteConfig(themeDirPath, loadedScheme, cfg)) {
QMessageBox::warning( QMessageBox::warning(
this, tr("Save failed"), this, tr("Save failed"),
tr("Could not write %1 to:\n%2").arg(ThemeConfigParser::paletteFileName(loadedScheme), themeDirPath)); tr("Could not write %1 to:\n%2").arg(PaletteConfig::fileName(loadedScheme), themeDirPath));
return; return;
} }
ThemeConfig globalCfg = ThemeConfigParser::parseThemeConfig(themeDirPath); ThemeConfig globalCfg = ThemeConfig::fromThemeDir(themeDirPath);
globalCfg.colorScheme = loadedScheme; globalCfg.colorScheme = loadedScheme;
ThemeConfigParser::saveThemeConfig(themeDirPath, globalCfg); globalCfg.save(themeDirPath);
savedConfig[loadedScheme] = cfg; savedConfig[loadedScheme] = cfg;
workingConfig[loadedScheme] = cfg; workingConfig[loadedScheme] = cfg;
@ -281,7 +281,7 @@ void PaletteEditorDialog::onReset()
void PaletteEditorDialog::onRevertToDefault() void PaletteEditorDialog::onRevertToDefault()
{ {
PaletteConfig def = ThemeConfigParser::parsePaletteDefault(themeDirPath, loadedScheme); PaletteConfig def = PaletteConfig::fromDefault(themeDirPath, loadedScheme);
if (!def.hasPalette()) { if (!def.hasPalette()) {
QMessageBox::information(this, tr("No default found"), QMessageBox::information(this, tr("No default found"),
tr("No default palette file found for the \"%1\" scheme.").arg(loadedScheme)); tr("No default palette file found for the \"%1\" scheme.").arg(loadedScheme));

View file

@ -20,49 +20,7 @@ QString ThemeConfig::toIni() const
return out; return out;
} }
bool PaletteConfig::hasPalette() const ThemeConfig ThemeConfig::fromThemeDir(const QString &themeDirPath)
{
return !colors.isEmpty();
}
QString PaletteConfig::toToml() const
{
QMetaEnum roleEnum = QMetaEnum::fromType<QPalette::ColorRole>();
QString out;
static const QList<QPair<QPalette::ColorGroup, QString>> groups = {
{QPalette::Active, "Palette"},
{QPalette::Disabled, "Palette.Disabled"},
{QPalette::Inactive, "Palette.Inactive"},
};
for (const auto &[group, sectionName] : groups) {
if (!colors.contains(group)) {
continue;
}
out += QString("[%1]\n").arg(sectionName);
const auto &roleMap = colors[group];
for (auto it = roleMap.cbegin(); it != roleMap.cend(); ++it) {
const char *roleName = roleEnum.valueToKey(it.key());
if (!roleName) {
continue;
}
out += QString("%1 = %2\n").arg(QString(roleName), -20).arg(it.value().name(QColor::HexArgb));
}
out += "\n";
}
return out;
}
namespace ThemeConfigParser
{
ThemeConfig parseThemeConfig(const QString &themeDirPath)
{ {
ThemeConfig cfg; ThemeConfig cfg;
@ -78,6 +36,7 @@ ThemeConfig parseThemeConfig(const QString &themeDirPath)
QString currentSection; QString currentSection;
QTextStream in(&f); QTextStream in(&f);
while (!in.atEnd()) { while (!in.atEnd()) {
QString line = in.readLine().trimmed(); QString line = in.readLine().trimmed();
@ -112,7 +71,7 @@ ThemeConfig parseThemeConfig(const QString &themeDirPath)
return cfg; return cfg;
} }
bool saveThemeConfig(const QString &themeDirPath, const ThemeConfig &cfg) bool ThemeConfig::save(const QString &themeDirPath) const
{ {
if (themeDirPath.isEmpty()) { if (themeDirPath.isEmpty()) {
return false; return false;
@ -130,21 +89,68 @@ bool saveThemeConfig(const QString &themeDirPath, const ThemeConfig &cfg)
} }
QTextStream out(&f); QTextStream out(&f);
out << cfg.toIni(); out << toIni();
return true; return true;
} }
QString paletteFileName(const QString &colorScheme) bool PaletteConfig::hasPalette() const
{ {
return colorScheme.compare("Dark", Qt::CaseInsensitive) == 0 ? "palette-dark.toml" : "palette-light.toml"; return !colors.isEmpty();
} }
PaletteConfig parsePalette(const QString &filePath) QString PaletteConfig::toToml() const
{
QMetaEnum roleEnum = QMetaEnum::fromType<QPalette::ColorRole>();
QString out;
static const QList<QPair<QPalette::ColorGroup, QString>> groups = {
{QPalette::Active, "Palette"},
{QPalette::Disabled, "Palette.Disabled"},
{QPalette::Inactive, "Palette.Inactive"},
};
for (const auto &[group, sectionName] : groups) {
if (!colors.contains(group)) {
continue;
}
out += QString("[%1]\n").arg(sectionName);
const auto &roleMap = colors[group];
for (auto it = roleMap.cbegin(); it != roleMap.cend(); ++it) {
const char *roleName = roleEnum.valueToKey(it.key());
if (!roleName) {
continue;
}
out += QString("%1 = %2\n")
.arg(QString(roleName), -20)
.arg(it.value().name(QColor::HexArgb));
}
out += "\n";
}
return out;
}
QString PaletteConfig::fileName(const QString &colorScheme)
{
return colorScheme.compare("Dark", Qt::CaseInsensitive) == 0
? "palette-dark.toml"
: "palette-light.toml";
}
PaletteConfig PaletteConfig::fromFile(const QString &filePath)
{ {
PaletteConfig cfg; PaletteConfig cfg;
QFile f(filePath); QFile f(filePath);
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
return cfg; return cfg;
} }
@ -168,7 +174,10 @@ PaletteConfig parsePalette(const QString &filePath)
if (currentSection.startsWith("Palette", Qt::CaseInsensitive)) { if (currentSection.startsWith("Palette", Qt::CaseInsensitive)) {
int dot = currentSection.indexOf('.'); int dot = currentSection.indexOf('.');
QString groupStr = (dot >= 0) ? currentSection.mid(dot + 1) : "Active";
QString groupStr = (dot >= 0)
? currentSection.mid(dot + 1)
: "Active";
if (groupStr.compare("Disabled", Qt::CaseInsensitive) == 0) { if (groupStr.compare("Disabled", Qt::CaseInsensitive) == 0) {
currentGroup = QPalette::Disabled; currentGroup = QPalette::Disabled;
@ -183,6 +192,7 @@ PaletteConfig parsePalette(const QString &filePath)
} }
int eq = line.indexOf('='); int eq = line.indexOf('=');
if (eq < 0) { if (eq < 0) {
continue; continue;
} }
@ -207,6 +217,7 @@ PaletteConfig parsePalette(const QString &filePath)
} }
int roleInt = roleEnum.keyToValue(key.toUtf8().constData()); int roleInt = roleEnum.keyToValue(key.toUtf8().constData());
if (roleInt < 0) { if (roleInt < 0) {
continue; continue;
} }
@ -221,16 +232,19 @@ PaletteConfig parsePalette(const QString &filePath)
return cfg; return cfg;
} }
PaletteConfig parsePaletteForScheme(const QString &themeDirPath, const QString &colorScheme) PaletteConfig PaletteConfig::fromScheme(const QString &themeDirPath,
const QString &colorScheme)
{ {
if (themeDirPath.isEmpty()) { if (themeDirPath.isEmpty()) {
return {}; return {};
} }
return parsePalette(QDir(themeDirPath).absoluteFilePath(paletteFileName(colorScheme))); return fromFile(
QDir(themeDirPath).absoluteFilePath(fileName(colorScheme)));
} }
PaletteConfig parsePaletteDefault(const QString &themeDirPath, const QString &colorScheme) PaletteConfig PaletteConfig::fromDefault(const QString &themeDirPath,
const QString &colorScheme)
{ {
if (themeDirPath.isEmpty()) { if (themeDirPath.isEmpty()) {
return {}; return {};
@ -238,27 +252,35 @@ PaletteConfig parsePaletteDefault(const QString &themeDirPath, const QString &co
QDir dir(themeDirPath); QDir dir(themeDirPath);
bool wantDark = colorScheme.compare("Dark", Qt::CaseInsensitive) == 0; bool wantDark =
colorScheme.compare("Dark", Qt::CaseInsensitive) == 0;
PaletteConfig cfg = PaletteConfig cfg = fromFile(
parsePalette(dir.absoluteFilePath(wantDark ? "palette-default-dark.toml" : "palette-default-light.toml")); dir.absoluteFilePath(
wantDark
? "palette-default-dark.toml"
: "palette-default-light.toml"));
if (!cfg.hasPalette()) { if (!cfg.hasPalette()) {
cfg = parsePalette(dir.absoluteFilePath(wantDark ? "palette-default-light.toml" : "palette-default-dark.toml")); cfg = fromFile(
dir.absoluteFilePath(
wantDark
? "palette-default-light.toml"
: "palette-default-dark.toml"));
} }
return cfg; return cfg;
} }
QPalette applyToPalette(const PaletteConfig &cfg, QPalette base) QPalette PaletteConfig::apply(QPalette base) const
{ {
for (auto git = cfg.colors.cbegin(); git != cfg.colors.cend(); ++git) { for (auto git = colors.cbegin(); git != colors.cend(); ++git) {
for (auto rit = git.value().cbegin(); rit != git.value().cend(); ++rit) { for (auto rit = git.value().cbegin();
rit != git.value().cend();
++rit) {
base.setColor(git.key(), rit.key(), rit.value()); base.setColor(git.key(), rit.key(), rit.value());
} }
} }
return base; return base;
} }
} // namespace ThemeConfigParser

View file

@ -13,6 +13,9 @@ struct ThemeConfig
bool isEmpty() const; bool isEmpty() const;
QString toIni() const; QString toIni() const;
static ThemeConfig fromThemeDir(const QString &themeDirPath);
bool save(const QString &themeDirPath) const;
}; };
struct PaletteConfig struct PaletteConfig
@ -21,25 +24,16 @@ struct PaletteConfig
bool hasPalette() const; bool hasPalette() const;
QString toToml() const; QString toToml() const;
static QString fileName(const QString &colorScheme);
static PaletteConfig fromFile(const QString &filePath);
static PaletteConfig fromScheme(const QString &themeDirPath,
const QString &colorScheme);
static PaletteConfig fromDefault(const QString &themeDirPath,
const QString &colorScheme);
QPalette apply(QPalette base) const;
}; };
namespace ThemeConfigParser
{
ThemeConfig parseThemeConfig(const QString &themeDirPath);
bool saveThemeConfig(const QString &themeDirPath, const ThemeConfig &cfg);
QString paletteFileName(const QString &colorScheme);
PaletteConfig parsePalette(const QString &filePath);
PaletteConfig parsePaletteForScheme(const QString &themeDirPath, const QString &colorScheme);
PaletteConfig parsePaletteDefault(const QString &themeDirPath, const QString &colorScheme);
QPalette applyToPalette(const PaletteConfig &cfg, QPalette base);
} // namespace ThemeConfigParser
#endif // COCKATRICE_THEME_CONFIG_H #endif // COCKATRICE_THEME_CONFIG_H

View file

@ -115,7 +115,7 @@ void ThemeManager::ensureThemeDirectoryExists()
bool ThemeManager::isDarkMode(const QString &themeDirPath) bool ThemeManager::isDarkMode(const QString &themeDirPath)
{ {
ThemeConfig themeConfig = ThemeConfigParser::parseThemeConfig(themeDirPath); ThemeConfig themeConfig = ThemeConfig::fromThemeDir(themeDirPath);
if (themeConfig.colorScheme.compare("Dark", Qt::CaseInsensitive) == 0) { if (themeConfig.colorScheme.compare("Dark", Qt::CaseInsensitive) == 0) {
return true; return true;
} else if (themeConfig.colorScheme.compare("Light", Qt::CaseInsensitive) == 0) { } else if (themeConfig.colorScheme.compare("Light", Qt::CaseInsensitive) == 0) {
@ -206,12 +206,12 @@ QBrush ThemeManager::loadExtraBrush(QString fileName, QBrush &fallbackBrush)
ThemeConfig ThemeManager::loadGlobalConfig(const QString &themeDirPath) ThemeConfig ThemeManager::loadGlobalConfig(const QString &themeDirPath)
{ {
return ThemeConfigParser::parseThemeConfig(themeDirPath); return ThemeConfig::fromThemeDir(themeDirPath);
} }
bool ThemeManager::saveGlobalConfig(const QString &themeDirPath, const ThemeConfig &cfg) bool ThemeManager::saveGlobalConfig(const QString &themeDirPath, const ThemeConfig &cfg)
{ {
return ThemeConfigParser::saveThemeConfig(themeDirPath, cfg); return cfg.save(themeDirPath);
} }
PaletteConfig ThemeManager::loadPaletteConfig(const QString &themeDirPath, const QString &colorScheme) PaletteConfig ThemeManager::loadPaletteConfig(const QString &themeDirPath, const QString &colorScheme)
@ -219,7 +219,7 @@ PaletteConfig ThemeManager::loadPaletteConfig(const QString &themeDirPath, const
if (themeDirPath.isEmpty()) { if (themeDirPath.isEmpty()) {
return {}; return {};
} }
return ThemeConfigParser::parsePaletteForScheme(themeDirPath, colorScheme); return PaletteConfig::fromScheme(themeDirPath, colorScheme);
} }
bool ThemeManager::savePaletteConfig(const QString &themeDirPath, const QString &colorScheme, const PaletteConfig &cfg) bool ThemeManager::savePaletteConfig(const QString &themeDirPath, const QString &colorScheme, const PaletteConfig &cfg)
@ -233,7 +233,7 @@ bool ThemeManager::savePaletteConfig(const QString &themeDirPath, const QString
dir.mkpath("."); dir.mkpath(".");
} }
QFile f(dir.absoluteFilePath(ThemeConfigParser::paletteFileName(colorScheme))); QFile f(dir.absoluteFilePath(PaletteConfig::fileName(colorScheme)));
if (!f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { if (!f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
return false; return false;
} }
@ -251,7 +251,7 @@ void ThemeManager::previewPalette(const PaletteConfig &cfg, const QString &schem
{ {
const QString themeName = SettingsCache::instance().getThemeName(); const QString themeName = SettingsCache::instance().getThemeName();
const QString dirPath = getAvailableThemes().value(themeName); const QString dirPath = getAvailableThemes().value(themeName);
const ThemeConfig themeCfg = ThemeConfigParser::parseThemeConfig(dirPath); const ThemeConfig themeCfg = ThemeConfig::fromThemeDir(dirPath);
applyStyleAndPalette(themeName, themeCfg, cfg, scheme); applyStyleAndPalette(themeName, themeCfg, cfg, scheme);
} }
@ -288,7 +288,7 @@ void ThemeManager::applyStyleAndPalette(const QString &themeName,
// Overlay custom palette colours // Overlay custom palette colours
if (palCfg.hasPalette()) { if (palCfg.hasPalette()) {
base = ThemeConfigParser::applyToPalette(palCfg, base); base = palCfg.apply( base);
} }
// Palette BEFORE style — setStyle() triggers a synchronous repolish of all // Palette BEFORE style — setStyle() triggers a synchronous repolish of all
@ -328,7 +328,7 @@ void ThemeManager::themeChangedSlot()
} }
// load theme.cfg for style + scheme preference // load theme.cfg for style + scheme preference
ThemeConfig themeCfg = ThemeConfigParser::parseThemeConfig(dirPath); ThemeConfig themeCfg = ThemeConfig::fromThemeDir(dirPath);
// Resolve active scheme: // Resolve active scheme:
// theme.cfg says Dark/Light → use that // theme.cfg says Dark/Light → use that
@ -336,9 +336,9 @@ void ThemeManager::themeChangedSlot()
QString activeScheme = isDarkMode(dirPath) ? "Dark" : "Light"; QString activeScheme = isDarkMode(dirPath) ? "Dark" : "Light";
// ── Load palette: custom first, then theme default ──────────────────── // ── Load palette: custom first, then theme default ────────────────────
PaletteConfig palette = ThemeConfigParser::parsePaletteForScheme(dirPath, activeScheme); PaletteConfig palette = PaletteConfig::fromScheme(dirPath, activeScheme);
if (!palette.hasPalette()) { if (!palette.hasPalette()) {
palette = ThemeConfigParser::parsePaletteDefault(dirPath, activeScheme); palette = PaletteConfig::fromDefault(dirPath, activeScheme);
} }
applyStyleAndPalette(themeName, themeCfg, palette, activeScheme); applyStyleAndPalette(themeName, themeCfg, palette, activeScheme);