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 12c8fad2c..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. @@ -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/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..27fd065a5 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.cpp +++ b/cockatrice/src/interface/widgets/general/home_widget.cpp @@ -61,6 +61,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 +106,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) 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..c45373757 100644 --- a/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp +++ b/cockatrice/src/interface/widgets/settings_page/appearance_settings_page.cpp @@ -510,7 +510,7 @@ void AppearanceSettingsPage::retranslateUi() homeTabDisplayCardNameCheckBox.setText(tr("Display card name of background in bottom right")); 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/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/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