diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc
index e21bdb0be..49c3f27b5 100644
--- a/cockatrice/cockatrice.qrc
+++ b/cockatrice/cockatrice.qrc
@@ -63,6 +63,8 @@
resources/icons/mana/W.svg
resources/backgrounds/home.png
+ resources/backgrounds/home-dark.png
+ resources/backgrounds/home-light.png
resources/backgrounds/card_triplet.svg
resources/backgrounds/placeholder_printing_selector.svg
diff --git a/cockatrice/resources/backgrounds/home-dark.png b/cockatrice/resources/backgrounds/home-dark.png
new file mode 100644
index 000000000..68f48e2c2
Binary files /dev/null and b/cockatrice/resources/backgrounds/home-dark.png differ
diff --git a/cockatrice/resources/backgrounds/home-light.png b/cockatrice/resources/backgrounds/home-light.png
new file mode 100644
index 000000000..eaaaba932
Binary files /dev/null and b/cockatrice/resources/backgrounds/home-light.png differ
diff --git a/cockatrice/resources/backgrounds/home.png b/cockatrice/resources/backgrounds/home.png
index 68f48e2c2..eaaaba932 100644
Binary files a/cockatrice/resources/backgrounds/home.png and b/cockatrice/resources/backgrounds/home.png differ
diff --git a/cockatrice/src/client/sound_engine.cpp b/cockatrice/src/client/sound_engine.cpp
index 18de2264d..96cafa3d3 100644
--- a/cockatrice/src/client/sound_engine.cpp
+++ b/cockatrice/src/client/sound_engine.cpp
@@ -94,7 +94,7 @@ QStringMap &SoundEngine::getAvailableThemes()
QDir dir;
availableThemes.clear();
- // load themes from user profile dir
+ // Load themes from user profile dir
dir.setPath(SettingsCache::instance().getDataPath() + "/sounds");
@@ -104,7 +104,7 @@ QStringMap &SoundEngine::getAvailableThemes()
}
}
- // load themes from cockatrice system dir
+ // Load themes from Cockatrice system dir
dir.setPath(qApp->applicationDirPath() +
#ifdef Q_OS_MAC
"/../Resources/sounds"
diff --git a/cockatrice/src/interface/deck_loader/deck_file_format.h b/cockatrice/src/interface/deck_loader/deck_file_format.h
index 995de32c0..3a25797ec 100644
--- a/cockatrice/src/interface/deck_loader/deck_file_format.h
+++ b/cockatrice/src/interface/deck_loader/deck_file_format.h
@@ -17,7 +17,7 @@ enum Format
PlainText,
/**
- * This is cockatrice's native deck file format, and supports deck metadata such as banner cards and tags.
+ * This is Cockatrice's native deck file format, and supports deck metadata such as banner cards and tags.
* Stored as .cod files.
*/
Cockatrice
diff --git a/cockatrice/src/interface/deck_loader/deck_loader.cpp b/cockatrice/src/interface/deck_loader/deck_loader.cpp
index f03339da8..f29b4eed2 100644
--- a/cockatrice/src/interface/deck_loader/deck_loader.cpp
+++ b/cockatrice/src/interface/deck_loader/deck_loader.cpp
@@ -50,7 +50,7 @@ DeckLoader::loadFromFile(const QString &fileName, DeckFileFormat::Format fmt, bo
result = deckList.loadFromFile_Native(&file);
if (!result) {
qCInfo(DeckLoaderLog) << "Failed to load " << fileName
- << "as cockatrice format; retrying as plain format";
+ << "as Cockatrice format; retrying as plain format";
file.seek(0);
result = deckList.loadFromFile_Plain(&file, CardNameNormalizer());
fmt = DeckFileFormat::PlainText;
diff --git a/cockatrice/src/interface/deck_loader/deck_loader.h b/cockatrice/src/interface/deck_loader/deck_loader.h
index b851c6895..be0df311d 100644
--- a/cockatrice/src/interface/deck_loader/deck_loader.h
+++ b/cockatrice/src/interface/deck_loader/deck_loader.h
@@ -131,7 +131,7 @@ public:
static void printDeckList(QPrinter *printer, const DeckList &deckList);
/**
- * Converts the given deck's file to the cockatrice file format.
+ * Converts the given deck's file to the Cockatrice file format.
* Uses the lastLoadInfo in the LoadedDeck to determine the current name of the file and where to save to.
* @param deck The deck to convert. Should have valid lastLoadInfo. Will update the lastLoadInfo.
* @return Whether the conversion succeeded.
diff --git a/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp b/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp
index 9cde72c01..d5a168708 100644
--- a/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp
+++ b/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp
@@ -1,6 +1,5 @@
#include "palette_editor_dialog.h"
-#include "../../client/settings/cache_settings.h"
#include "../theme_manager.h"
#include "palette_generator.h"
#include "palette_grid_widget.h"
@@ -11,31 +10,11 @@
#include
#include
#include
-#include
#include
-#include
#include
-#include
#include
#include
-#include
#include
-#include
-
-// Probe whether a directory is truly writable by trying to create and remove a
-// temporary file. QFileInfo::isWritable() on a directory is unreliable (notably
-// on Windows where UAC VirtualStore can make a system dir appear writable).
-static bool isDirReallyWritable(const QString &dirPath)
-{
- const QString probe = QDir(dirPath).absoluteFilePath(".cockatrice_write_test");
- QFile f(probe);
- if (!f.open(QIODevice::WriteOnly)) {
- return false;
- }
- f.close();
- f.remove();
- return true;
-}
PaletteEditorDialog::PaletteEditorDialog(const QString &_themeDirPath, const QString &_themeName, QWidget *parent)
: QDialog(parent), themeDirPath(_themeDirPath), themeName(_themeName)
@@ -46,14 +25,7 @@ PaletteEditorDialog::PaletteEditorDialog(const QString &_themeDirPath, const QSt
// Resolve a writable directory for saving. Built-in (Default / Fusion) and
// other read-only theme directories must be customised in the user-writable
// themes directory; otherwise the write would fail or be lost on upgrade.
- if (!themeDirPath.isEmpty() && isDirReallyWritable(themeDirPath)) {
- saveDir = themeDirPath;
- } else {
- saveDir = QDir(SettingsCache::instance().paths().getThemesPath()).absoluteFilePath(themeName);
- if (!QDir().mkpath(saveDir)) {
- qWarning() << "Failed to create palette save directory:" << saveDir;
- }
- }
+ saveDir = ThemeManager::writableThemeDir(themeName);
// Load both scheme configs upfront so switching is instant
loadSchemes();
@@ -214,7 +186,7 @@ void PaletteEditorDialog::retranslateUi()
resetBtn->setToolTip(tr("Discard unsaved edits and restore the last saved palette"));
saveBtn->setToolTip(tr("Write palette-%1.toml and reload the theme").arg(loadedScheme.toLower()));
- if (saveDir.isEmpty() || !isDirReallyWritable(saveDir)) {
+ if (saveDir.isEmpty() || !ThemeManager::isDirReallyWritable(saveDir)) {
saveBtn->setEnabled(false);
saveBtn->setToolTip(tr("Cannot save: this theme has no writable directory"));
}
@@ -297,7 +269,7 @@ void PaletteEditorDialog::onSave()
if (it.key() == loadedScheme) {
continue;
}
- if (it.value().colors == savedConfig.value(it.key()).colors) {
+ if (it.value() == savedConfig.value(it.key())) {
continue;
}
if (!ThemeManager::commitPalette(saveDir, it.key(), it.value())) {
@@ -308,7 +280,7 @@ void PaletteEditorDialog::onSave()
}
// Commit the active scheme last so the global colour scheme matches.
- if (workingConfig[loadedScheme].colors != savedConfig.value(loadedScheme).colors) {
+ if (workingConfig[loadedScheme] != savedConfig.value(loadedScheme)) {
if (!ThemeManager::commitPalette(saveDir, loadedScheme, workingConfig[loadedScheme])) {
QMessageBox::warning(this, tr("Save failed"),
tr("Could not write %1 to:\n%2").arg(PaletteConfig::fileName(loadedScheme), saveDir));
diff --git a/cockatrice/src/interface/palette_editor/palette_generator.cpp b/cockatrice/src/interface/palette_editor/palette_generator.cpp
index d30dd14f1..822e57250 100644
--- a/cockatrice/src/interface/palette_editor/palette_generator.cpp
+++ b/cockatrice/src/interface/palette_editor/palette_generator.cpp
@@ -150,6 +150,17 @@ PaletteConfig fromAccent(const QColor &accent, int intensity, const QString &sch
cfg.colors[CG::Disabled][CR::HighlightedText] = disText;
cfg.colors[CG::Inactive][CR::HighlightedText] = dark ? Qt::white : Qt::black;
+ // Accent: same primary hue as Highlight, so palettes derived from a
+ // QuickSetup accent always carry a matching Accent role.
+#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
+ set3(CR::Accent, hl, disText, hl);
+#endif
+
+ // Application role colors: Strong tracks the primary accent, while Soft is
+ // the lightened, desaturated companion used for button-gradient highlights.
+ cfg.appColors[AppColor::AccentStrong] = hl;
+ cfg.appColors[AppColor::AccentSoft] = hsl(accent.lightness() + 60, qRound(accent.hslSaturation() * 70 / 100.0));
+
// BrightText
QColor bright;
if (achromatic) {
diff --git a/cockatrice/src/interface/palette_editor/palette_grid_widget.cpp b/cockatrice/src/interface/palette_editor/palette_grid_widget.cpp
index 67294cd98..97d28b731 100644
--- a/cockatrice/src/interface/palette_editor/palette_grid_widget.cpp
+++ b/cockatrice/src/interface/palette_editor/palette_grid_widget.cpp
@@ -1,5 +1,7 @@
#include "palette_grid_widget.h"
+#include "../theme_manager.h"
+
#include
#include
#include
@@ -45,6 +47,11 @@ static const QMap ROLE_DESCRIPTIONS = {
{QPalette::Shadow, QT_TR_NOOP("Very dark shadow colour")},
};
+static const QMap APP_ROLE_DESCRIPTIONS = {
+ {AppColor::AccentStrong, QT_TR_NOOP("Vivid primary accent (e.g. home-tab button gradient start)")},
+ {AppColor::AccentSoft, QT_TR_NOOP("Lightened, desaturated accent (e.g. home-tab button gradient end)")},
+};
+
PaletteGridWidget::PaletteGridWidget(QWidget *parent) : QWidget(parent)
{
scroll = new QScrollArea(this);
@@ -122,6 +129,46 @@ void PaletteGridWidget::buildGrid(QWidget *host)
grid->addWidget(btn, row + 1, col + 1, Qt::AlignHCenter | Qt::AlignVCenter);
}
}
+
+ // Application color section: one ColorButton per role below the role grid.
+ // These are not tied to a color group, so a single button spans the row.
+ QMetaEnum appEnum = QMetaEnum::fromType();
+
+ const int appHeaderRow = roles.size() + 1;
+
+ auto *appHeader = new QLabel(tr("App colors"), host);
+ appHeader->setToolTip(tr("Application-specific colors layered on top of the Qt palette"));
+ QFont appHeaderFont = appHeader->font();
+ appHeaderFont.setBold(true);
+ appHeader->setFont(appHeaderFont);
+ appHeader->setAutoFillBackground(true);
+ appHeader->setContentsMargins(4, 4, 4, 4);
+ grid->addWidget(appHeader, appHeaderRow, 0, 1, 4);
+ headerLabels.append(appHeader);
+
+ for (int i = 0; i < appEnum.keyCount(); ++i) {
+ auto role = static_cast(appEnum.value(i));
+ const int row = appHeaderRow + 1 + i;
+
+ if (i % 2 == 0) {
+ for (int col = 0; col < 4; ++col) {
+ auto *shade = new QWidget(host);
+ shade->setAutoFillBackground(true);
+ grid->addWidget(shade, row, col);
+ rowShadeWidgets.push_back(shade);
+ }
+ }
+
+ auto *label = new QLabel(QString(appEnum.valueToKey(role)), host);
+ label->setToolTip(APP_ROLE_DESCRIPTIONS.value(role, {}));
+ label->setContentsMargins(4, 2, 8, 2);
+ grid->addWidget(label, row, 0);
+
+ auto *btn = new ColorButton(host);
+ connect(btn, &ColorButton::colorChanged, this, [this] { emit paletteChanged(); });
+ appColorButtons[role] = btn;
+ grid->addWidget(btn, row, 1, Qt::AlignHCenter | Qt::AlignVCenter);
+ }
}
void PaletteGridWidget::changeEvent(QEvent *e)
@@ -166,6 +213,16 @@ void PaletteGridWidget::loadPalette(const PaletteConfig &cfg)
colorButtons[group][role]->setColor(color);
}
}
+
+ QMetaEnum appEnum = QMetaEnum::fromType();
+ for (int i = 0; i < appEnum.keyCount(); ++i) {
+ auto role = static_cast(appEnum.value(i));
+ QColor color = cfg.appColors.value(role);
+ if (!color.isValid()) {
+ color = themeManager->appColor(role);
+ }
+ appColorButtons[role]->setColor(color);
+ }
}
PaletteConfig PaletteGridWidget::currentPaletteConfig() const
@@ -176,5 +233,12 @@ PaletteConfig PaletteGridWidget::currentPaletteConfig() const
cfg.colors[group][role] = colorButtons[group][role]->getColor();
}
}
+
+ QMetaEnum appEnum = QMetaEnum::fromType();
+ for (int i = 0; i < appEnum.keyCount(); ++i) {
+ auto role = static_cast(appEnum.value(i));
+ cfg.appColors[role] = appColorButtons[role]->getColor();
+ }
+
return cfg;
}
\ No newline at end of file
diff --git a/cockatrice/src/interface/palette_editor/palette_grid_widget.h b/cockatrice/src/interface/palette_editor/palette_grid_widget.h
index 1a665971a..77cbf1c62 100644
--- a/cockatrice/src/interface/palette_editor/palette_grid_widget.h
+++ b/cockatrice/src/interface/palette_editor/palette_grid_widget.h
@@ -31,6 +31,7 @@ private:
void refreshChromePalettes();
QMap> colorButtons;
+ QMap appColorButtons;
QScrollArea *scroll;
QWidget *gridHost;
QVBoxLayout *layout;
diff --git a/cockatrice/src/interface/theme_config.cpp b/cockatrice/src/interface/theme_config.cpp
index 3c43c467d..4420eefe1 100644
--- a/cockatrice/src/interface/theme_config.cpp
+++ b/cockatrice/src/interface/theme_config.cpp
@@ -96,7 +96,7 @@ bool ThemeConfig::save(const QString &themeDirPath) const
bool PaletteConfig::hasPalette() const
{
- return !colors.isEmpty();
+ return !colors.isEmpty() || !appColors.isEmpty();
}
QString PaletteConfig::toToml() const
@@ -133,6 +133,24 @@ QString PaletteConfig::toToml() const
out += "\n";
}
+ if (!appColors.isEmpty()) {
+ QMetaEnum appEnum = QMetaEnum::fromType();
+
+ out += "[AppColors]\n";
+
+ for (auto it = appColors.cbegin(); it != appColors.cend(); ++it) {
+ const char *roleName = appEnum.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;
}
@@ -152,6 +170,7 @@ PaletteConfig PaletteConfig::fromFile(const QString &filePath)
}
QMetaEnum roleEnum = QMetaEnum::fromType();
+ QMetaEnum appEnum = QMetaEnum::fromType();
QString currentSection;
QPalette::ColorGroup currentGroup = QPalette::Active;
@@ -202,6 +221,26 @@ PaletteConfig PaletteConfig::fromFile(const QString &filePath)
}
}
+ QColor color(value);
+
+ if (!color.isValid()) {
+ continue;
+ }
+
+ if (currentSection.compare("AppColors", Qt::CaseInsensitive) == 0) {
+ if (key.startsWith("AppColor::")) {
+ key = key.mid(10);
+ }
+
+ int appRoleInt = appEnum.keyToValue(key.toUtf8().constData());
+
+ if (appRoleInt >= 0) {
+ cfg.appColors[static_cast(appRoleInt)] = color;
+ }
+
+ continue;
+ }
+
if (!currentSection.startsWith("Palette", Qt::CaseInsensitive)) {
continue;
}
@@ -216,11 +255,7 @@ PaletteConfig PaletteConfig::fromFile(const QString &filePath)
continue;
}
- QColor color(value);
-
- if (color.isValid()) {
- cfg.colors[currentGroup][static_cast(roleInt)] = color;
- }
+ cfg.colors[currentGroup][static_cast(roleInt)] = color;
}
return cfg;
diff --git a/cockatrice/src/interface/theme_config.h b/cockatrice/src/interface/theme_config.h
index 07bf55b7a..567aeccda 100644
--- a/cockatrice/src/interface/theme_config.h
+++ b/cockatrice/src/interface/theme_config.h
@@ -3,9 +3,25 @@
#include
#include
+#include
#include
#include
+// Application-specific color roles, layered on top of the fixed QPalette role
+// set. Stored in the same palette-.toml under an [AppColors] section
+// and editable from the palette editor, so theme authors can control colors
+// beyond what Qt's palette can express.
+namespace AppColor
+{
+Q_NAMESPACE
+enum Role
+{
+ AccentStrong,
+ AccentSoft,
+};
+Q_ENUM_NS(Role)
+} // namespace AppColor
+
struct ThemeConfig
{
QString colorScheme;
@@ -21,7 +37,16 @@ struct ThemeConfig
struct PaletteConfig
{
QMap> colors;
+ QMap appColors;
+ bool operator==(const PaletteConfig &rhs) const
+ {
+ return colors == rhs.colors && appColors == rhs.appColors;
+ }
+ bool operator!=(const PaletteConfig &rhs) const
+ {
+ return !(*this == rhs);
+ }
bool hasPalette() const;
QString toToml() const;
diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp
index cc6be175a..da9f14408 100644
--- a/cockatrice/src/interface/theme_manager.cpp
+++ b/cockatrice/src/interface/theme_manager.cpp
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -184,11 +185,32 @@ QString ThemeManager::assetPath(QStringView prefix) const
return resolvedPlain.isEmpty() ? prefix.toString() : resolvedPlain;
}
-bool ThemeManager::isBuiltInTheme()
+// Probe whether a directory is truly writable by trying to create and remove a
+// temporary file. QFileInfo::isWritable() on a directory is unreliable (notably
+// on Windows where UAC VirtualStore can make a system dir appear writable).
+bool ThemeManager::isDirReallyWritable(const QString &dirPath)
{
- const auto themeName = SettingsCache::instance().getThemeName();
+ const QString probe = QDir(dirPath).absoluteFilePath(".cockatrice_write_test");
+ QFile f(probe);
+ if (!f.open(QIODevice::WriteOnly)) {
+ return false;
+ }
+ f.close();
+ f.remove();
+ return true;
+}
- return themeName == NONE_THEME_NAME || themeName == FUSION_THEME_NAME;
+QString ThemeManager::writableThemeDir(const QString &themeName)
+{
+ // All theme writes go to the user themes directory regardless of whether
+ // the resolved (system) theme directory happens to be writable. Even when a
+ // write would succeed in-place, routing it to the user directory keeps the
+ // install intact and guarantees changes survive upgrades.
+ const QString dirPath = QDir(SettingsCache::instance().paths().getThemesPath()).absoluteFilePath(themeName);
+ if (!QDir().mkpath(dirPath)) {
+ qWarning() << "Failed to create theme save directory:" << dirPath;
+ }
+ return dirPath;
}
// System (read-only) themes location, relative to the application binary.
@@ -224,7 +246,7 @@ QStringMap &ThemeManager::getAvailableThemes()
}
}
- // load themes from cockatrice system dir
+ // Load themes from Cockatrice system dir
dir.setPath(systemThemesBasePath());
for (QString themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) {
@@ -331,7 +353,7 @@ bool ThemeManager::commitPalette(const QString &themeDirPath, const QString &col
void ThemeManager::setColorScheme(const QString &scheme)
{
- const QString dirPath = getAvailableThemes().value(SettingsCache::instance().getThemeName());
+ const QString dirPath = writableThemeDir(SettingsCache::instance().getThemeName());
ThemeConfig cfg = ThemeConfig::fromThemeDir(dirPath);
cfg.colorScheme = scheme;
@@ -342,7 +364,7 @@ void ThemeManager::setColorScheme(const QString &scheme)
void ThemeManager::setStyleName(const QString &styleName)
{
- const QString dirPath = getAvailableThemes().value(SettingsCache::instance().getThemeName());
+ const QString dirPath = writableThemeDir(SettingsCache::instance().getThemeName());
ThemeConfig cfg = ThemeConfig::fromThemeDir(dirPath);
cfg.styleName = styleName;
@@ -416,6 +438,8 @@ void ThemeManager::applyStyleAndPalette(const QString &themeName,
qApp->setPalette(base);
qApp->setStyle(style);
+ currentAppColors = palCfg.appColors;
+
// Force every widget to re-polish and repaint immediately rather than
// waiting for natural expose events, which produces a patchwork of old
// and new colours during a live preview.
@@ -428,6 +452,35 @@ void ThemeManager::applyStyleAndPalette(const QString &themeName,
style->polish(widget);
widget->update();
}
+
+ emit paletteChanged();
+}
+
+QColor ThemeManager::appColor(AppColor::Role role) const
+{
+ const auto it = currentAppColors.constFind(role);
+ if (it != currentAppColors.constEnd()) {
+ return it.value();
+ }
+
+ // QPalette::Accent was introduced in Qt 6.6 and several shipped palettes
+ // set it to a value barely distinguishable from Window, so it is not a
+ // reliable accent source. The selection highlight is the stable accent
+ // (Accent defaults to Highlight when unset), and deriving from it
+ // unconditionally keeps every Qt version rendering identically.
+ const QColor accent = qApp->palette().color(QPalette::Active, QPalette::Highlight);
+
+ if (role == AppColor::AccentSoft) {
+ constexpr int SOFT_SATURATION_PERCENT = 70;
+ constexpr int SOFT_LIGHTNESS_OFFSET = 60;
+
+ // Light end of the gradient: same hue, softened and lightened
+ return QColor::fromHsl(qMax(0, accent.hslHue()),
+ qBound(0, qRound(accent.hslSaturation() * SOFT_SATURATION_PERCENT / 100.0), 255),
+ qBound(0, accent.lightness() + SOFT_LIGHTNESS_OFFSET, 255));
+ }
+
+ return accent;
}
void ThemeManager::themeChangedSlot()
@@ -464,8 +517,19 @@ void ThemeManager::themeChangedSlot()
// ── Load palette: custom first, then theme default ────────────────────
PaletteConfig palette = PaletteConfig::fromScheme(dirPath, activeScheme);
- if (!palette.hasPalette()) {
- palette = ThemeManager::loadDefaultPaletteConfig(dirPath, themeName, activeScheme);
+ const PaletteConfig themeDefault = ThemeManager::loadDefaultPaletteConfig(dirPath, themeName, activeScheme);
+ if (palette.hasPalette()) {
+ // A custom palette written before [AppColors] existed carries no app
+ // colors; merge the theme's shipped defaults so the identity colors
+ // survive (hasPalette() counts an app-colors-only file as a palette,
+ // so those are kept wholesale and never reach here empty).
+ for (auto it = themeDefault.appColors.cbegin(); it != themeDefault.appColors.cend(); ++it) {
+ if (!palette.appColors.contains(it.key())) {
+ palette.appColors.insert(it.key(), it.value());
+ }
+ }
+ } else {
+ palette = themeDefault;
}
applyStyleAndPalette(themeName, themeCfg, palette, activeScheme);
diff --git a/cockatrice/src/interface/theme_manager.h b/cockatrice/src/interface/theme_manager.h
index ac35042a0..aadb38ee9 100644
--- a/cockatrice/src/interface/theme_manager.h
+++ b/cockatrice/src/interface/theme_manager.h
@@ -50,6 +50,7 @@ private:
QString currentThemePath;
std::array brushes;
QStringMap availableThemes;
+ QMap currentAppColors;
/*
Internal cache for multiple backgrounds
*/
@@ -65,7 +66,16 @@ protected:
const QString &activeScheme);
public:
- bool isBuiltInTheme();
+ // Resolves the directory to write theme changes to for the given theme
+ // name. The resolved theme dir (user or system) is used when writable;
+ // read-only system themes fall back to the user themes directory, creating
+ // it if needed, so customisations never get lost on upgrade.
+ static QString writableThemeDir(const QString &themeName);
+ // Probe whether a directory is truly writable by trying to create and remove
+ // a temporary file. QFileInfo::isWritable() on a directory is unreliable
+ // (notably on Windows where UAC VirtualStore can make a system dir appear
+ // writable).
+ static bool isDirReallyWritable(const QString &dirPath);
// Explicit color scheme of the theme: theme.cfg's ColorScheme setting
// (Dark/Light), falling back to the OS color scheme when it is "System".
bool isDarkMode(const QString &themeDirPath) const;
@@ -115,12 +125,17 @@ public:
void reloadCurrentTheme();
void previewPalette(const PaletteConfig &cfg, const QString &scheme);
+ // Resolves an application color role: the theme's stored [AppColors] value
+ // when present, otherwise a palette-accent-derived fallback.
+ QColor appColor(AppColor::Role role) const;
+
QBrush &getBgBrush(Role zone);
QBrush getExtraBgBrush(Role zone, int zoneId = 0);
protected slots:
void themeChangedSlot();
signals:
void themeChanged();
+ void paletteChanged();
};
extern ThemeManager *themeManager;
diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp
index de7dd3e97..fb559fc4b 100644
--- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp
+++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp
@@ -478,13 +478,13 @@ void DlgSettings::closeEvent(QCloseEvent *event)
case Invalid:
loadErrorMessage = tr("Your card database is invalid.\n\n"
"Cockatrice may not function correctly with an invalid database\n\n"
- "You may need to rerun oracle to update your card database.\n\n"
+ "You may need to rerun Oracle to update your card database.\n\n"
"Would you like to change your database location setting?");
break;
case VersionTooOld:
loadErrorMessage = tr("Your card database version is too old.\n\n"
"This can cause problems loading card information or images\n\n"
- "Usually this can be fixed by rerunning oracle to to update your card database.\n\n"
+ "Usually this can be fixed by rerunning Oracle to to update your card database.\n\n"
"Would you like to change your database location setting?");
break;
case NotLoaded:
diff --git a/cockatrice/src/interface/widgets/general/home_tab_button_color.h b/cockatrice/src/interface/widgets/general/home_tab_button_color.h
index 1550b57e7..b45bd7a92 100644
--- a/cockatrice/src/interface/widgets/general/home_tab_button_color.h
+++ b/cockatrice/src/interface/widgets/general/home_tab_button_color.h
@@ -11,8 +11,8 @@ namespace HomeTabButtonColor
*/
enum Source
{
- Automatic, ///< Extract color from background, or use theme color if no background
- FromBackground, ///< Always extract color from background
+ FromThemeColors, ///< Use the theme's identity accent colors
+ FromBackground, ///< Extract colour from the background image
};
struct Entry
@@ -23,7 +23,7 @@ struct Entry
inline QList all()
{
- static QList entries = {{Automatic, QT_TR_NOOP("Automatic")},
+ static QList entries = {{FromThemeColors, QT_TR_NOOP("From theme colors")},
{FromBackground, QT_TR_NOOP("Extract from background")}};
return entries;
@@ -33,12 +33,12 @@ inline QList all()
* Safely converts an int into the corresponding Source.
*
* @param value The int value
- * @return The Source. Returns Source::Automatic if the value is not within range
+ * @return The Source. Returns Source::FromThemeColors if the value is not within range
*/
inline Source intToSource(int value)
{
if (value > FromBackground) {
- return Automatic; // default
+ return FromThemeColors; // default
}
return static_cast(value);
diff --git a/cockatrice/src/interface/widgets/general/home_widget.cpp b/cockatrice/src/interface/widgets/general/home_widget.cpp
index 0d030b973..79544c5a8 100644
--- a/cockatrice/src/interface/widgets/general/home_widget.cpp
+++ b/cockatrice/src/interface/widgets/general/home_widget.cpp
@@ -54,6 +54,8 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
// Lambda is cleaner to read than overloading this
connect(&SettingsCache::instance().appearance(), &AppearanceSettings::homeTabDisplayCardNameChanged, this,
[this] { repaint(); });
+ connect(&SettingsCache::instance().appearance(), &AppearanceSettings::homeTabBackgroundDimChanged, this,
+ [this] { repaint(); });
connect(&SettingsCache::instance(), &SettingsCache::themeChanged, this,
&HomeWidget::initializeBackgroundFromSource);
connect(&SettingsCache::instance(), &SettingsCache::themeChanged, this,
@@ -61,6 +63,7 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
// Scheme flips (light/dark/system with an OS switch) fire on themeManager,
// not on SettingsCache::themeChanged, so re-resolve the variant background.
connect(themeManager, &ThemeManager::themeChanged, this, &HomeWidget::initializeBackgroundFromSource);
+ connect(themeManager, &ThemeManager::paletteChanged, this, &HomeWidget::updateButtonsToBackgroundColor);
connect(&SettingsCache::instance().appearance(), &AppearanceSettings::homeTabButtonColorChanged, this,
&HomeWidget::updateButtonsToBackgroundColor);
}
@@ -105,32 +108,24 @@ void HomeWidget::loadBackgroundSourceDeck()
backgroundSourceDeck = deckOpt.has_value() ? deckOpt.value().deckList : DeckList();
}
-static bool isDefaultBackgroundAndTheme()
+static QPair paletteDerivedButtonColors()
{
- QString sourceId = SettingsCache::instance().appearance().getHomeTabBackgroundSource();
- return themeManager->isBuiltInTheme() && BackgroundSources::fromId(sourceId) == BackgroundSources::Theme;
+ return {themeManager->appColor(AppColor::AccentStrong), themeManager->appColor(AppColor::AccentSoft)};
}
QPair HomeWidget::determineButtonColor() const
{
- static QPair defaultColor = {QColor::fromRgb(20, 140, 60), QColor::fromRgb(120, 200, 80)};
-
auto colorSource =
HomeTabButtonColor::intToSource(SettingsCache::instance().appearance().getHomeTabButtonColorSourceIndex());
switch (colorSource) {
- case HomeTabButtonColor::Automatic: {
- if (isDefaultBackgroundAndTheme()) {
- return defaultColor;
- } else {
- return extractDominantColors(background);
- }
- }
+ case HomeTabButtonColor::FromThemeColors:
+ return paletteDerivedButtonColors();
case HomeTabButtonColor::FromBackground:
return extractDominantColors(background);
}
- return defaultColor;
+ return paletteDerivedButtonColors();
}
void HomeWidget::setRandomCard(ExactCard &newCard)
@@ -365,13 +360,15 @@ void HomeWidget::paintEvent(QPaintEvent *event)
painter.drawPixmap(topLeft, toDraw);
}
- // Draw translucent black overlay with rounded corners
- QRectF overlayRect(5, 5, width() - 10, height() - 10);
- QPainterPath roundedRectPath;
- roundedRectPath.addRoundedRect(overlayRect, 20, 20);
+ if (SettingsCache::instance().appearance().getHomeTabBackgroundDim()) {
+ // Draw translucent black overlay with rounded corners
+ QRectF overlayRect(5, 5, width() - 10, height() - 10);
+ QPainterPath roundedRectPath;
+ roundedRectPath.addRoundedRect(overlayRect, 20, 20);
- QColor semiTransparentBlack(0, 0, 0, static_cast(255 * 0.33));
- painter.fillPath(roundedRectPath, semiTransparentBlack);
+ QColor semiTransparentBlack(0, 0, 0, static_cast(255 * 0.33));
+ painter.fillPath(roundedRectPath, semiTransparentBlack);
+ }
// Card name overlay (above the attribution, bottom-right)
QString cardName;
diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp
index c8494f095..e4e6b6ace 100644
--- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp
+++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp
@@ -132,6 +132,10 @@ AppearanceSettingsPage::AppearanceSettingsPage()
connect(&homeTabDisplayCardNameCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings.appearance(),
&AppearanceSettings::setHomeTabDisplayCardName);
+ homeTabBackgroundDimCheckBox.setChecked(settings.appearance().getHomeTabBackgroundDim());
+ connect(&homeTabBackgroundDimCheckBox, &QCheckBox::QT_STATE_CHANGED, &settings.appearance(),
+ &AppearanceSettings::setHomeTabBackgroundDim);
+
for (const auto &entry : HomeTabButtonColor::all()) {
homeTabButtonColorSourceBox.addItem(QObject::tr(entry.trKey));
}
@@ -148,8 +152,9 @@ AppearanceSettingsPage::AppearanceSettingsPage()
homeTabGrid->addWidget(&homeTabBackgroundShuffleFrequencyLabel, 1, 0);
homeTabGrid->addWidget(&homeTabBackgroundShuffleFrequencySpinBox, 1, 1);
homeTabGrid->addWidget(&homeTabDisplayCardNameCheckBox, 2, 0, 1, 2);
- homeTabGrid->addWidget(&homeTabButtonColorSourceLabel, 3, 0);
- homeTabGrid->addWidget(&homeTabButtonColorSourceBox, 3, 1);
+ homeTabGrid->addWidget(&homeTabBackgroundDimCheckBox, 3, 0, 1, 2);
+ homeTabGrid->addWidget(&homeTabButtonColorSourceLabel, 4, 0);
+ homeTabGrid->addWidget(&homeTabButtonColorSourceBox, 4, 1);
homeTabGroupBox = new QGroupBox;
homeTabGroupBox->setLayout(homeTabGrid);
@@ -508,9 +513,12 @@ void AppearanceSettingsPage::retranslateUi()
homeTabBackgroundShuffleFrequencyLabel.setText(tr("Home tab background shuffle frequency:"));
homeTabBackgroundShuffleFrequencySpinBox.setSpecialValueText(tr("Disabled"));
homeTabDisplayCardNameCheckBox.setText(tr("Display card name of background in bottom right"));
+ homeTabBackgroundDimCheckBox.setText(tr("Dim the home tab background"));
+ homeTabBackgroundDimCheckBox.setToolTip(
+ tr("Draw a translucent overlay over the home tab background so buttons and text stand out"));
homeTabButtonColorSourceLabel.setText(tr("Home tab button color:"));
homeTabButtonColorSourceBox.setToolTip(
- tr("Automatic: extract from background if present, otherwise use theme default"));
+ tr("Use the theme's identity accent colors, or extract colors from the background image"));
playmatGroupBox->setTitle(tr("Playmat settings"));
playmatVisibilityLabel.setText(tr("Playmat visibility:"));
diff --git a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h
index 8db71ff8f..bec4cd72f 100644
--- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h
+++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.h
@@ -41,6 +41,7 @@ private:
QLabel homeTabBackgroundShuffleFrequencyLabel;
QSpinBox homeTabBackgroundShuffleFrequencySpinBox;
QCheckBox homeTabDisplayCardNameCheckBox;
+ QCheckBox homeTabBackgroundDimCheckBox;
QLabel homeTabButtonColorSourceLabel;
QComboBox homeTabButtonColorSourceBox;
diff --git a/cockatrice/src/interface/window_main.cpp b/cockatrice/src/interface/window_main.cpp
index ce28fc24a..3daaeb8d3 100644
--- a/cockatrice/src/interface/window_main.cpp
+++ b/cockatrice/src/interface/window_main.cpp
@@ -92,8 +92,8 @@
#include
#define GITHUB_PAGES_URL "https://cockatrice.github.io"
-#define GITHUB_CONTRIBUTORS_URL "https://github.com/Cockatrice/Cockatrice/graphs/contributors?type=c"
-#define GITHUB_CONTRIBUTE_URL "https://github.com/Cockatrice/Cockatrice#cockatrice"
+#define GITHUB_CONTRIBUTORS_URL "https://github.com/Cockatrice/Cockatrice/graphs/contributors"
+#define GITHUB_CONTRIBUTE_URL "https://github.com/Cockatrice/Cockatrice#"
#define GITHUB_TRANSIFEX_TRANSLATORS_URL "https://github.com/Cockatrice/Cockatrice/wiki/Translator-Hall-of-Fame"
#define GITHUB_TRANSLATOR_FAQ_URL "https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ"
#define GITHUB_ISSUES_URL "https://github.com/Cockatrice/Cockatrice/issues"
@@ -1050,7 +1050,7 @@ void MainWindow::createCardUpdateProcess(bool background)
if (dir.exists(binaryName)) {
updaterCmd = dir.absoluteFilePath(binaryName);
- } else { // try and find the directory oracle is stored in the build directory
+ } else { // try and find the directory Oracle is stored in the build directory
QDir findLocalDir(dir);
findLocalDir.cdUp();
findLocalDir.cd(getCardUpdaterBinaryName());
diff --git a/cockatrice/src/main.cpp b/cockatrice/src/main.cpp
index ac77b4241..829e08742 100644
--- a/cockatrice/src/main.cpp
+++ b/cockatrice/src/main.cpp
@@ -231,7 +231,7 @@ int main(int argc, char *argv[])
// These values are only used by the settings loader/saver
// Wrong or outdated values are kept to not break things
QCoreApplication::setOrganizationName("Cockatrice");
- QCoreApplication::setOrganizationDomain("cockatrice.de");
+ QCoreApplication::setOrganizationDomain("cockatrice.github.io");
QCoreApplication::setApplicationName("Cockatrice");
QCoreApplication::setApplicationVersion(VERSION_STRING);
@@ -250,7 +250,7 @@ int main(int argc, char *argv[])
// Command-line parser
QCommandLineParser parser;
- parser.setApplicationDescription("Cockatrice");
+ parser.setApplicationDescription("Cockatrice Client");
parser.addHelpOption();
parser.addVersionOption();
@@ -350,8 +350,8 @@ int main(int argc, char *argv[])
qCInfo(MainLog) << "MainWindow constructor finished";
ui.setWindowIcon(themePixmap(QStringLiteral("cockatrice")));
- // set name of the app desktop file; used by wayland to load the window icon
- QGuiApplication::setDesktopFileName("cockatrice");
+ // Set name of the app desktop file; used by wayland to load the window icon
+ QGuiApplication::setDesktopFileName("Cockatrice");
SettingsCache::instance().network().setClientID(generateClientID());
diff --git a/cockatrice/themes/Default/palette-default-dark.toml b/cockatrice/themes/Default/palette-default-dark.toml
index 3ee174a2f..e101935b4 100644
--- a/cockatrice/themes/Default/palette-default-dark.toml
+++ b/cockatrice/themes/Default/palette-default-dark.toml
@@ -61,3 +61,7 @@ ToolTipBase = #ffffffdc
ToolTipText = #ff000000
PlaceholderText = #6effffff
+
+[AppColors]
+AccentStrong = #ff148c3c
+AccentSoft = #ff78c850
diff --git a/cockatrice/themes/Default/palette-default-light.toml b/cockatrice/themes/Default/palette-default-light.toml
new file mode 100644
index 000000000..14c215cdf
--- /dev/null
+++ b/cockatrice/themes/Default/palette-default-light.toml
@@ -0,0 +1,67 @@
+[Palette]
+WindowText = #ff000000
+Button = #fff0f0f0
+Light = #ffffffff
+Midlight = #ffe3e3e3
+Dark = #ffa0a0a0
+Mid = #ffa0a0a0
+Text = #ff000000
+BrightText = #ffffffff
+ButtonText = #ff000000
+Base = #ffffffff
+Window = #fff0f0f0
+Shadow = #ff696969
+HighlightedText = #ffffffff
+Link = #ff0d5f28
+LinkVisited = #ff08401b
+AlternateBase = #ffe9e7e3
+ToolTipBase = #ffffffdc
+ToolTipText = #ff000000
+PlaceholderText = #80000000
+
+[Palette.Disabled]
+WindowText = #ff787878
+Button = #fff0f0f0
+Light = #ffffffff
+Midlight = #fff7f7f7
+Dark = #ffa0a0a0
+Mid = #ffa0a0a0
+Text = #ff787878
+BrightText = #ffffffff
+ButtonText = #ff787878
+Base = #fff0f0f0
+Window = #fff0f0f0
+Shadow = #ff000000
+HighlightedText = #ffffffff
+Link = #ff0000ff
+LinkVisited = #ffff00ff
+AlternateBase = #fff7f7f7
+ToolTipBase = #ffffffdc
+ToolTipText = #ff000000
+PlaceholderText = #80000000
+
+[Palette.Inactive]
+WindowText = #ff000000
+Button = #fff0f0f0
+Light = #ffffffff
+Midlight = #ffe3e3e3
+Dark = #ffa0a0a0
+Mid = #ffa0a0a0
+Text = #ff000000
+BrightText = #ffffffff
+ButtonText = #ff000000
+Base = #ffffffff
+Window = #fff0f0f0
+Shadow = #ff696969
+HighlightedText = #ff000000
+Link = #ff0d5f28
+LinkVisited = #ff08401b
+AlternateBase = #ffe9e7e3
+ToolTipBase = #ffffffdc
+ToolTipText = #ff000000
+PlaceholderText = #80000000
+
+
+[AppColors]
+AccentStrong = #ff148c3c
+AccentSoft = #ff78c850
\ No newline at end of file
diff --git a/cockatrice/themes/Fabric/backgrounds/home-dark.png b/cockatrice/themes/Fabric/backgrounds/home-dark.png
new file mode 100644
index 000000000..8d9514626
Binary files /dev/null and b/cockatrice/themes/Fabric/backgrounds/home-dark.png differ
diff --git a/cockatrice/themes/Fabric/backgrounds/home-light.png b/cockatrice/themes/Fabric/backgrounds/home-light.png
new file mode 100644
index 000000000..78f51a686
Binary files /dev/null and b/cockatrice/themes/Fabric/backgrounds/home-light.png differ
diff --git a/cockatrice/themes/Fabric/palette-default-dark.toml b/cockatrice/themes/Fabric/palette-default-dark.toml
new file mode 100644
index 000000000..cad18921a
--- /dev/null
+++ b/cockatrice/themes/Fabric/palette-default-dark.toml
@@ -0,0 +1,74 @@
+# Fabric — dark identity palette (navy-cloth chrome)
+[Palette]
+WindowText = #e8ecf2
+Button = #2b374a
+Light = #3a4759
+Midlight = #333f50
+Dark = #141a23
+Mid = #252c38
+Text = #e8ecf2
+BrightText = #8ec2ff
+ButtonText = #f2f4f8
+Base = #222c3d
+Window = #18202e
+Shadow = #0b0f15
+Highlight = #4a82e6
+HighlightedText = #ffffff
+Link = #7fb0f2
+LinkVisited = #a98ad9
+AlternateBase = #1d2636
+ToolTipBase = #2b3546
+ToolTipText = #f2f4f8
+PlaceholderText = #6ee8ecf2
+Accent = #4a82e6
+
+[Palette.Disabled]
+WindowText = #9d9d9d
+Button = #18202e
+Light = #3a4759
+Midlight = #333f50
+Dark = #141a23
+Mid = #252c38
+Text = #9d9d9d
+BrightText = #8ec2ff
+ButtonText = #787878
+Base = #18202e
+Window = #18202e
+Shadow = #0b0f15
+Highlight = #222d40
+HighlightedText = #9d9d9d
+Link = #308cc6
+LinkVisited = #b450ff
+AlternateBase = #1d2636
+ToolTipBase = #2b3546
+ToolTipText = #f2f4f8
+PlaceholderText = #6ee8ecf2
+Accent = #9d9d9d
+
+[Palette.Inactive]
+WindowText = #e8ecf2
+Button = #2b374a
+Light = #3a4759
+Midlight = #333f50
+Dark = #141a23
+Mid = #252c38
+Text = #e8ecf2
+BrightText = #8ec2ff
+ButtonText = #f2f4f8
+Base = #222c3d
+Window = #18202e
+Shadow = #0b0f15
+Highlight = #222d40
+HighlightedText = #ffffff
+Link = #7fb0f2
+LinkVisited = #a98ad9
+AlternateBase = #1d2636
+ToolTipBase = #2b3546
+ToolTipText = #f2f4f8
+PlaceholderText = #6ee8ecf2
+Accent = #4a82e6
+
+[AppColors]
+AccentStrong = #3a6fd6
+AccentSoft = #8fb8f2
+
diff --git a/cockatrice/themes/Fabric/palette-default-light.toml b/cockatrice/themes/Fabric/palette-default-light.toml
new file mode 100644
index 000000000..f5151af3e
--- /dev/null
+++ b/cockatrice/themes/Fabric/palette-default-light.toml
@@ -0,0 +1,74 @@
+# Fabric — light identity palette (navy-cloth chrome)
+[Palette]
+WindowText = #1c2330
+Button = #c8d6ea
+Light = #ffffff
+Midlight = #b9c6dc
+Dark = #8fa0bd
+Mid = #a3b3cd
+Text = #1c2330
+BrightText = #1d4fa0
+ButtonText = #141c29
+Base = #f6f8fc
+Window = #dbe3ef
+Shadow = #5a6a85
+Highlight = #2f6fd6
+HighlightedText = #ffffff
+Link = #2555b0
+LinkVisited = #6a4bb8
+AlternateBase = #e9eef7
+ToolTipBase = #e9eff8
+ToolTipText = #141c29
+PlaceholderText = #7a1c2330
+Accent = #2f6fd6
+
+[Palette.Disabled]
+WindowText = #787878
+Button = #dbe3ef
+Light = #ffffff
+Midlight = #b9c6dc
+Dark = #8fa0bd
+Mid = #a3b3cd
+Text = #787878
+BrightText = #1d4fa0
+ButtonText = #969696
+Base = #dbe3ef
+Window = #dbe3ef
+Shadow = #5a6a85
+Highlight = #cdd8e9
+HighlightedText = #787878
+Link = #0000ff
+LinkVisited = #ff00ff
+AlternateBase = #e9eef7
+ToolTipBase = #e9eff8
+ToolTipText = #141c29
+PlaceholderText = #7a1c2330
+Accent = #787878
+
+[Palette.Inactive]
+WindowText = #1c2330
+Button = #c8d6ea
+Light = #ffffff
+Midlight = #b9c6dc
+Dark = #8fa0bd
+Mid = #a3b3cd
+Text = #1c2330
+BrightText = #1d4fa0
+ButtonText = #141c29
+Base = #f6f8fc
+Window = #dbe3ef
+Shadow = #5a6a85
+Highlight = #cdd8e9
+HighlightedText = #000000
+Link = #2555b0
+LinkVisited = #6a4bb8
+AlternateBase = #e9eef7
+ToolTipBase = #e9eff8
+ToolTipText = #141c29
+PlaceholderText = #7a1c2330
+Accent = #2f6fd6
+
+[AppColors]
+AccentStrong = #3a6fd6
+AccentSoft = #8fb8f2
+
diff --git a/cockatrice/themes/Fabric/theme.cfg b/cockatrice/themes/Fabric/theme.cfg
new file mode 100644
index 000000000..55b916e71
--- /dev/null
+++ b/cockatrice/themes/Fabric/theme.cfg
@@ -0,0 +1,5 @@
+[Appearance]
+ColorScheme = System
+
+[Style]
+Name = Fusion
\ No newline at end of file
diff --git a/cockatrice/themes/Fusion/palette-default-dark.toml b/cockatrice/themes/Fusion/palette-default-dark.toml
index c1d83a4cd..a988c2f14 100644
--- a/cockatrice/themes/Fusion/palette-default-dark.toml
+++ b/cockatrice/themes/Fusion/palette-default-dark.toml
@@ -67,3 +67,7 @@ ToolTipText = #ffd4d4d4
PlaceholderText = #80ffffff
Accent = #ff1e1e1e
+
+[AppColors]
+AccentStrong = #ff148c3c
+AccentSoft = #ff78c850
diff --git a/cockatrice/themes/Fusion/palette-default-light.toml b/cockatrice/themes/Fusion/palette-default-light.toml
index 86c41be78..b72b79b11 100644
--- a/cockatrice/themes/Fusion/palette-default-light.toml
+++ b/cockatrice/themes/Fusion/palette-default-light.toml
@@ -67,3 +67,7 @@ ToolTipText = #ff000000
PlaceholderText = #80000000
Accent = #fff0f0f0
+
+[AppColors]
+AccentStrong = #ff148c3c
+AccentSoft = #ff78c850
diff --git a/cockatrice/themes/Leather/backgrounds/home-dark.png b/cockatrice/themes/Leather/backgrounds/home-dark.png
new file mode 100644
index 000000000..20d16a27f
Binary files /dev/null and b/cockatrice/themes/Leather/backgrounds/home-dark.png differ
diff --git a/cockatrice/themes/Leather/backgrounds/home-light.png b/cockatrice/themes/Leather/backgrounds/home-light.png
new file mode 100644
index 000000000..ee1da361d
Binary files /dev/null and b/cockatrice/themes/Leather/backgrounds/home-light.png differ
diff --git a/cockatrice/themes/Leather/palette-default-dark.toml b/cockatrice/themes/Leather/palette-default-dark.toml
new file mode 100644
index 000000000..b0db0e90a
--- /dev/null
+++ b/cockatrice/themes/Leather/palette-default-dark.toml
@@ -0,0 +1,74 @@
+# Leather — dark identity palette (black-brown chrome with brass accents)
+[Palette]
+WindowText = #eee9e2
+Button = #332d26
+Light = #4a4239
+Midlight = #3d3730
+Dark = #131009
+Mid = #26221c
+Text = #eee9e2
+BrightText = #e3c27e
+ButtonText = #f5f1ea
+Base = #26221d
+Window = #1d1a16
+Shadow = #0d0b07
+Highlight = #4a5f8f
+HighlightedText = #ffffff
+Link = #cfa263
+LinkVisited = #9a7db8
+AlternateBase = #211d19
+ToolTipBase = #37302a
+ToolTipText = #f5f1ea
+PlaceholderText = #6eeee9e2
+Accent = #c9995a
+
+[Palette.Disabled]
+WindowText = #9d9d9d
+Button = #1d1a16
+Light = #4a4239
+Midlight = #3d3730
+Dark = #131009
+Mid = #26221c
+Text = #9d9d9d
+BrightText = #e3c27e
+ButtonText = #787878
+Base = #1d1a16
+Window = #1d1a16
+Shadow = #0d0b07
+Highlight = #2d2822
+HighlightedText = #9d9d9d
+Link = #308cc6
+LinkVisited = #b450ff
+AlternateBase = #211d19
+ToolTipBase = #37302a
+ToolTipText = #f5f1ea
+PlaceholderText = #6eeee9e2
+Accent = #9d9d9d
+
+[Palette.Inactive]
+WindowText = #eee9e2
+Button = #332d26
+Light = #4a4239
+Midlight = #3d3730
+Dark = #131009
+Mid = #26221c
+Text = #eee9e2
+BrightText = #e3c27e
+ButtonText = #f5f1ea
+Base = #26221d
+Window = #1d1a16
+Shadow = #0d0b07
+Highlight = #2d2822
+HighlightedText = #ffffff
+Link = #cfa263
+LinkVisited = #9a7db8
+AlternateBase = #211d19
+ToolTipBase = #37302a
+ToolTipText = #f5f1ea
+PlaceholderText = #6eeee9e2
+Accent = #c9995a
+
+[AppColors]
+AccentStrong = #b7823b
+AccentSoft = #e4c58f
+
diff --git a/cockatrice/themes/Leather/palette-default-light.toml b/cockatrice/themes/Leather/palette-default-light.toml
new file mode 100644
index 000000000..ff122db76
--- /dev/null
+++ b/cockatrice/themes/Leather/palette-default-light.toml
@@ -0,0 +1,74 @@
+# Leather — light identity palette (black-brown chrome with brass accents)
+[Palette]
+WindowText = #2a2114
+Button = #dfcbb0
+Light = #ffffff
+Midlight = #c6b08c
+Dark = #a18a64
+Mid = #b29a74
+Text = #2a2114
+BrightText = #7a531c
+ButtonText = #1f1710
+Base = #fdf8ee
+Window = #f0e2cb
+Shadow = #5d4d33
+Highlight = #34508c
+HighlightedText = #ffffff
+Link = #8a5e1e
+LinkVisited = #6b5190
+AlternateBase = #f5ebd7
+ToolTipBase = #fff7e8
+ToolTipText = #1f1710
+PlaceholderText = #7a2a2114
+Accent = #a5712f
+
+[Palette.Disabled]
+WindowText = #787878
+Button = #f0e2cb
+Light = #ffffff
+Midlight = #c6b08c
+Dark = #a18a64
+Mid = #b29a74
+Text = #787878
+BrightText = #7a531c
+ButtonText = #969696
+Base = #f0e2cb
+Window = #f0e2cb
+Shadow = #5d4d33
+Highlight = #ecd9bb
+HighlightedText = #787878
+Link = #0000ff
+LinkVisited = #ff00ff
+AlternateBase = #f5ebd7
+ToolTipBase = #fff7e8
+ToolTipText = #1f1710
+PlaceholderText = #7a2a2114
+Accent = #787878
+
+[Palette.Inactive]
+WindowText = #2a2114
+Button = #dfcbb0
+Light = #ffffff
+Midlight = #c6b08c
+Dark = #a18a64
+Mid = #b29a74
+Text = #2a2114
+BrightText = #7a531c
+ButtonText = #1f1710
+Base = #fdf8ee
+Window = #f0e2cb
+Shadow = #5d4d33
+Highlight = #ecd9bb
+HighlightedText = #000000
+Link = #8a5e1e
+LinkVisited = #6b5190
+AlternateBase = #f5ebd7
+ToolTipBase = #fff7e8
+ToolTipText = #1f1710
+PlaceholderText = #7a2a2114
+Accent = #a5712f
+
+[AppColors]
+AccentStrong = #b7823b
+AccentSoft = #e4c58f
+
diff --git a/cockatrice/themes/Leather/theme.cfg b/cockatrice/themes/Leather/theme.cfg
new file mode 100644
index 000000000..55b916e71
--- /dev/null
+++ b/cockatrice/themes/Leather/theme.cfg
@@ -0,0 +1,5 @@
+[Appearance]
+ColorScheme = System
+
+[Style]
+Name = Fusion
\ No newline at end of file
diff --git a/cockatrice/themes/Plasma/backgrounds/home-dark.png b/cockatrice/themes/Plasma/backgrounds/home-dark.png
new file mode 100644
index 000000000..ce1469e2b
Binary files /dev/null and b/cockatrice/themes/Plasma/backgrounds/home-dark.png differ
diff --git a/cockatrice/themes/Plasma/backgrounds/home-light.png b/cockatrice/themes/Plasma/backgrounds/home-light.png
new file mode 100644
index 000000000..2e9000bd6
Binary files /dev/null and b/cockatrice/themes/Plasma/backgrounds/home-light.png differ
diff --git a/cockatrice/themes/Plasma/palette-default-dark.toml b/cockatrice/themes/Plasma/palette-default-dark.toml
new file mode 100644
index 000000000..222456f4f
--- /dev/null
+++ b/cockatrice/themes/Plasma/palette-default-dark.toml
@@ -0,0 +1,74 @@
+# Plasma — dark identity palette (electric violet chrome with cyan sparks)
+[Palette]
+WindowText = #eeebff
+Button = #2a2440
+Light = #453d63
+Midlight = #383252
+Dark = #0e0c16
+Mid = #211e31
+Text = #eeebff
+BrightText = #7fd7ff
+ButtonText = #f6f4ff
+Base = #1e1a2e
+Window = #151220
+Shadow = #08070e
+Highlight = #6a4df0
+HighlightedText = #ffffff
+Link = #37c7e8
+LinkVisited = #9b7aff
+AlternateBase = #1a1726
+ToolTipBase = #2c2745
+ToolTipText = #f6f4ff
+PlaceholderText = #6eeeebff
+Accent = #6a4df0
+
+[Palette.Disabled]
+WindowText = #9d9d9d
+Button = #151220
+Light = #453d63
+Midlight = #383252
+Dark = #0e0c16
+Mid = #211e31
+Text = #9d9d9d
+BrightText = #7fd7ff
+ButtonText = #787878
+Base = #151220
+Window = #151220
+Shadow = #08070e
+Highlight = #211c32
+HighlightedText = #9d9d9d
+Link = #308cc6
+LinkVisited = #b450ff
+AlternateBase = #1a1726
+ToolTipBase = #2c2745
+ToolTipText = #f6f4ff
+PlaceholderText = #6eeeebff
+Accent = #9d9d9d
+
+[Palette.Inactive]
+WindowText = #eeebff
+Button = #2a2440
+Light = #453d63
+Midlight = #383252
+Dark = #0e0c16
+Mid = #211e31
+Text = #eeebff
+BrightText = #7fd7ff
+ButtonText = #f6f4ff
+Base = #1e1a2e
+Window = #151220
+Shadow = #08070e
+Highlight = #211c32
+HighlightedText = #ffffff
+Link = #37c7e8
+LinkVisited = #9b7aff
+AlternateBase = #1a1726
+ToolTipBase = #2c2745
+ToolTipText = #f6f4ff
+PlaceholderText = #6eeeebff
+Accent = #6a4df0
+
+[AppColors]
+AccentStrong = #5b3ee0
+AccentSoft = #a28bf7
+
diff --git a/cockatrice/themes/Plasma/palette-default-light.toml b/cockatrice/themes/Plasma/palette-default-light.toml
new file mode 100644
index 000000000..d54db31d2
--- /dev/null
+++ b/cockatrice/themes/Plasma/palette-default-light.toml
@@ -0,0 +1,74 @@
+# Plasma — light identity palette (electric violet chrome with cyan sparks)
+[Palette]
+WindowText = #1d1830
+Button = #cfc6f0
+Light = #ffffff
+Midlight = #b7adde
+Dark = #9589c8
+Mid = #a49ad2
+Text = #1d1830
+BrightText = #10406e
+ButtonText = #120d26
+Base = #f9f7ff
+Window = #e3dcf7
+Shadow = #554c85
+Highlight = #5a3ee2
+HighlightedText = #ffffff
+Link = #0f8fb5
+LinkVisited = #6a45d6
+AlternateBase = #ece8fa
+ToolTipBase = #f5f3ff
+ToolTipText = #120d26
+PlaceholderText = #7a1d1830
+Accent = #5a3ee2
+
+[Palette.Disabled]
+WindowText = #787878
+Button = #e3dcf7
+Light = #ffffff
+Midlight = #b7adde
+Dark = #9589c8
+Mid = #a49ad2
+Text = #787878
+BrightText = #10406e
+ButtonText = #969696
+Base = #e3dcf7
+Window = #e3dcf7
+Shadow = #554c85
+Highlight = #d6ccf3
+HighlightedText = #787878
+Link = #0000ff
+LinkVisited = #ff00ff
+AlternateBase = #ece8fa
+ToolTipBase = #f5f3ff
+ToolTipText = #120d26
+PlaceholderText = #7a1d1830
+Accent = #787878
+
+[Palette.Inactive]
+WindowText = #1d1830
+Button = #cfc6f0
+Light = #ffffff
+Midlight = #b7adde
+Dark = #9589c8
+Mid = #a49ad2
+Text = #1d1830
+BrightText = #10406e
+ButtonText = #120d26
+Base = #f9f7ff
+Window = #e3dcf7
+Shadow = #554c85
+Highlight = #d6ccf3
+HighlightedText = #000000
+Link = #0f8fb5
+LinkVisited = #6a45d6
+AlternateBase = #ece8fa
+ToolTipBase = #f5f3ff
+ToolTipText = #120d26
+PlaceholderText = #7a1d1830
+Accent = #5a3ee2
+
+[AppColors]
+AccentStrong = #5b3ee0
+AccentSoft = #a28bf7
+
diff --git a/cockatrice/themes/Plasma/theme.cfg b/cockatrice/themes/Plasma/theme.cfg
new file mode 100644
index 000000000..55b916e71
--- /dev/null
+++ b/cockatrice/themes/Plasma/theme.cfg
@@ -0,0 +1,5 @@
+[Appearance]
+ColorScheme = System
+
+[Style]
+Name = Fusion
\ No newline at end of file
diff --git a/cockatrice/themes/VelvetMarble/backgrounds/home-dark.png b/cockatrice/themes/VelvetMarble/backgrounds/home-dark.png
new file mode 100644
index 000000000..34738090f
Binary files /dev/null and b/cockatrice/themes/VelvetMarble/backgrounds/home-dark.png differ
diff --git a/cockatrice/themes/VelvetMarble/backgrounds/home-light.png b/cockatrice/themes/VelvetMarble/backgrounds/home-light.png
new file mode 100644
index 000000000..de783e086
Binary files /dev/null and b/cockatrice/themes/VelvetMarble/backgrounds/home-light.png differ
diff --git a/cockatrice/themes/VelvetMarble/palette-default-dark.toml b/cockatrice/themes/VelvetMarble/palette-default-dark.toml
new file mode 100644
index 000000000..496943931
--- /dev/null
+++ b/cockatrice/themes/VelvetMarble/palette-default-dark.toml
@@ -0,0 +1,74 @@
+# VelvetMarble — dark identity palette (charcoal-velvet chrome with slate marble)
+[Palette]
+WindowText = #e8eaee
+Button = #262a31
+Light = #3a3f47
+Midlight = #31363d
+Dark = #0e1013
+Mid = #1f2329
+Text = #e8eaee
+BrightText = #c3d8f2
+ButtonText = #f2f3f6
+Base = #1b1e23
+Window = #131519
+Shadow = #08090b
+Highlight = #8fa6c0
+HighlightedText = #101318
+Link = #a9c6e8
+LinkVisited = #b9a8d9
+AlternateBase = #171a1f
+ToolTipBase = #2d323a
+ToolTipText = #f2f3f6
+PlaceholderText = #6ee8eaee
+Accent = #8fa6c0
+
+[Palette.Disabled]
+WindowText = #9d9d9d
+Button = #131519
+Light = #3a3f47
+Midlight = #31363d
+Dark = #0e1013
+Mid = #1f2329
+Text = #9d9d9d
+BrightText = #c3d8f2
+ButtonText = #787878
+Base = #131519
+Window = #131519
+Shadow = #08090b
+Highlight = #1f2229
+HighlightedText = #9d9d9d
+Link = #308cc6
+LinkVisited = #b450ff
+AlternateBase = #171a1f
+ToolTipBase = #2d323a
+ToolTipText = #f2f3f6
+PlaceholderText = #6ee8eaee
+Accent = #9d9d9d
+
+[Palette.Inactive]
+WindowText = #e8eaee
+Button = #262a31
+Light = #3a3f47
+Midlight = #31363d
+Dark = #0e1013
+Mid = #1f2329
+Text = #e8eaee
+BrightText = #c3d8f2
+ButtonText = #f2f3f6
+Base = #1b1e23
+Window = #131519
+Shadow = #08090b
+Highlight = #1f2229
+HighlightedText = #ffffff
+Link = #a9c6e8
+LinkVisited = #b9a8d9
+AlternateBase = #171a1f
+ToolTipBase = #2d323a
+ToolTipText = #f2f3f6
+PlaceholderText = #6ee8eaee
+Accent = #8fa6c0
+
+[AppColors]
+AccentStrong = #54687e
+AccentSoft = #9db0c4
+
diff --git a/cockatrice/themes/VelvetMarble/palette-default-light.toml b/cockatrice/themes/VelvetMarble/palette-default-light.toml
new file mode 100644
index 000000000..5323fd320
--- /dev/null
+++ b/cockatrice/themes/VelvetMarble/palette-default-light.toml
@@ -0,0 +1,74 @@
+# VelvetMarble — light identity palette (charcoal-velvet chrome with slate marble)
+[Palette]
+WindowText = #1b1d21
+Button = #c7d1dd
+Light = #ffffff
+Midlight = #b3becb
+Dark = #93a0b1
+Mid = #a1adbc
+Text = #1b1d21
+BrightText = #26465f
+ButtonText = #121418
+Base = #f7f9fb
+Window = #d9e0ea
+Shadow = #57626f
+Highlight = #54687e
+HighlightedText = #ffffff
+Link = #2e4d6b
+LinkVisited = #5d4a78
+AlternateBase = #e6ebf2
+ToolTipBase = #f2f4f6
+ToolTipText = #121418
+PlaceholderText = #7a1b1d21
+Accent = #54687e
+
+[Palette.Disabled]
+WindowText = #787878
+Button = #d9e0ea
+Light = #ffffff
+Midlight = #b3becb
+Dark = #93a0b1
+Mid = #a1adbc
+Text = #787878
+BrightText = #26465f
+ButtonText = #969696
+Base = #d9e0ea
+Window = #d9e0ea
+Shadow = #57626f
+Highlight = #ccd5e3
+HighlightedText = #787878
+Link = #0000ff
+LinkVisited = #ff00ff
+AlternateBase = #e6ebf2
+ToolTipBase = #f2f4f6
+ToolTipText = #121418
+PlaceholderText = #7a1b1d21
+Accent = #787878
+
+[Palette.Inactive]
+WindowText = #1b1d21
+Button = #c7d1dd
+Light = #ffffff
+Midlight = #b3becb
+Dark = #93a0b1
+Mid = #a1adbc
+Text = #1b1d21
+BrightText = #26465f
+ButtonText = #121418
+Base = #f7f9fb
+Window = #d9e0ea
+Shadow = #57626f
+Highlight = #ccd5e3
+HighlightedText = #000000
+Link = #2e4d6b
+LinkVisited = #5d4a78
+AlternateBase = #e6ebf2
+ToolTipBase = #f2f4f6
+ToolTipText = #121418
+PlaceholderText = #7a1b1d21
+Accent = #54687e
+
+[AppColors]
+AccentStrong = #54687e
+AccentSoft = #9db0c4
+
diff --git a/cockatrice/themes/VelvetMarble/theme.cfg b/cockatrice/themes/VelvetMarble/theme.cfg
new file mode 100644
index 000000000..55b916e71
--- /dev/null
+++ b/cockatrice/themes/VelvetMarble/theme.cfg
@@ -0,0 +1,5 @@
+[Appearance]
+ColorScheme = System
+
+[Style]
+Name = Fusion
\ No newline at end of file
diff --git a/libcockatrice_settings/libcockatrice/settings/appearance_settings.cpp b/libcockatrice_settings/libcockatrice/settings/appearance_settings.cpp
index 2f19d6224..839e33be4 100644
--- a/libcockatrice_settings/libcockatrice/settings/appearance_settings.cpp
+++ b/libcockatrice_settings/libcockatrice/settings/appearance_settings.cpp
@@ -70,6 +70,17 @@ void AppearanceSettings::setHomeTabDisplayCardName(bool _displayCardName)
emit homeTabDisplayCardNameChanged();
}
+bool AppearanceSettings::getHomeTabBackgroundDim() const
+{
+ return getValue("homeTabBackgroundDim", QString(), QString(), true).toBool();
+}
+
+void AppearanceSettings::setHomeTabBackgroundDim(bool _dimBackground)
+{
+ setValue(_dimBackground, "homeTabBackgroundDim");
+ emit homeTabBackgroundDimChanged();
+}
+
int AppearanceSettings::getHomeTabButtonColorSourceIndex() const
{
return getValue("homeTabButtonColorSource", "", "", 0).toInt();
diff --git a/libcockatrice_settings/libcockatrice/settings/appearance_settings.h b/libcockatrice_settings/libcockatrice/settings/appearance_settings.h
index 3a63f0df0..a4504798e 100644
--- a/libcockatrice_settings/libcockatrice/settings/appearance_settings.h
+++ b/libcockatrice_settings/libcockatrice/settings/appearance_settings.h
@@ -27,6 +27,8 @@ public:
void setHomeTabBackgroundShuffleFrequency(int _frequency);
[[nodiscard]] bool getHomeTabDisplayCardName() const;
void setHomeTabDisplayCardName(bool _displayCardName);
+ [[nodiscard]] bool getHomeTabBackgroundDim() const;
+ void setHomeTabBackgroundDim(bool _dimBackground);
[[nodiscard]] int getHomeTabButtonColorSourceIndex() const;
void setHomeTabButtonColorSourceIndex(int index);
@@ -36,6 +38,7 @@ signals:
void homeTabBackgroundSourceChanged();
void homeTabBackgroundShuffleFrequencyChanged();
void homeTabDisplayCardNameChanged();
+ void homeTabBackgroundDimChanged();
void homeTabButtonColorChanged();
public:
diff --git a/oracle/src/main.cpp b/oracle/src/main.cpp
index bb88153b1..0f962f9be 100644
--- a/oracle/src/main.cpp
+++ b/oracle/src/main.cpp
@@ -50,8 +50,8 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
QCoreApplication::setOrganizationName("Cockatrice");
- QCoreApplication::setOrganizationDomain("cockatrice");
- // this can't be changed, as it influences the default save path for cards.xml
+ QCoreApplication::setOrganizationDomain("Cockatrice");
+ // This can't be changed, as it influences the default save path for cards.xml
QCoreApplication::setApplicationName("Cockatrice");
// If the program is opened with the -s flag, it will only do spoilers. Otherwise it will do MTGJSON/Tokens
@@ -83,7 +83,7 @@ int main(int argc, char *argv[])
QIcon icon("theme:appicon.svg");
wizard.setWindowIcon(icon);
// set name of the app desktop file; used by wayland to load the window icon
- QGuiApplication::setDesktopFileName("oracle");
+ QGuiApplication::setDesktopFileName("Oracle");
wizard.show();
diff --git a/oracle/src/pages.cpp b/oracle/src/pages.cpp
index a10daadb3..df0c3f51d 100644
--- a/oracle/src/pages.cpp
+++ b/oracle/src/pages.cpp
@@ -796,7 +796,7 @@ void SaveSetsPage::retranslateUi()
{
setTitle(tr("Sets imported"));
if (wizard()->downloadedPlainXml) {
- setSubTitle(tr("A cockatrice database file of %1 MB has been downloaded.")
+ setSubTitle(tr("A Cockatrice card database file of %1 MB has been downloaded.")
.arg(qRound(wizard()->xmlData.size() / 1000000.0)));
} else {
setSubTitle(tr("The following sets have been found:"));
diff --git a/oracle/src/parsehelpers.cpp b/oracle/src/parsehelpers.cpp
index a97bf67c9..ee7c4eb2e 100644
--- a/oracle/src/parsehelpers.cpp
+++ b/oracle/src/parsehelpers.cpp
@@ -20,7 +20,7 @@
* Note that "...enters tapped unless..." returns false.
*
* @param name The name of the card
- * @param text The oracle text of the card
+ * @param text The Oracle text of the card
*/
bool parseCipt(const QString &name, const QString &text)
{
diff --git a/oracle/src/raw_json_scanner.h b/oracle/src/raw_json_scanner.h
index 086f2b3e3..04fcc52e4 100644
--- a/oracle/src/raw_json_scanner.h
+++ b/oracle/src/raw_json_scanner.h
@@ -54,7 +54,7 @@ using ScanProgressCallback = std::function expectedversion) {
- qCCritical(DatabaseInterfaceLog) << poolStr << "Error opening database: the database schema version"
- << dbversion << "is too new, you need to update servatrice"
- << "(this servatrice actually uses version" << expectedversion << ")";
+ qCCritical(DatabaseInterfaceLog)
+ << poolStr << "Error opening database: the database schema version" << dbversion
+ << "is too new, you need to update Servatrice" << "(Currently running Servatrice actually uses version"
+ << expectedversion << ")";
return false;
}
} else {
diff --git a/tests/settings/settings_defaults_test.cpp b/tests/settings/settings_defaults_test.cpp
index eda778ae9..4f5155677 100644
--- a/tests/settings/settings_defaults_test.cpp
+++ b/tests/settings/settings_defaults_test.cpp
@@ -386,6 +386,19 @@ TEST_F(SettingsDefaultsTest, Appearance_HomeTabDisplayCardName_Default)
ASSERT_EQ(s.getHomeTabDisplayCardName(), true);
}
+TEST_F(SettingsDefaultsTest, Appearance_HomeTabBackgroundDim_Default)
+{
+ AppearanceSettings s(settingsPath, nullptr);
+ ASSERT_EQ(s.getHomeTabBackgroundDim(), true);
+}
+
+TEST_F(SettingsDefaultsTest, Appearance_HomeTabBackgroundDim_SetAndGet)
+{
+ AppearanceSettings s(settingsPath, nullptr);
+ s.setHomeTabBackgroundDim(false);
+ ASSERT_EQ(s.getHomeTabBackgroundDim(), false);
+}
+
// --- InterfaceSettings ---
TEST_F(SettingsDefaultsTest, Interface_ShowStatusBar_Default)