[Client] Add [AppColors] application palette roles

The home-tab buttons' gradient over the static theme background was hardcoded, and accent-derived fallbacks could not be themed or edited: QPalette's role set is closed, so any application-specific color has to live in Cockatrice's own palette layer.

- Add an AppColor::Role enum (AccentStrong / AccentSoft) stored on PaletteConfig and round-tripped from palette-<scheme>.toml under a new [AppColors] section.
- Cache the applied app colors in ThemeManager and expose appColor(Role) with a palette-accent-derived fallback; emit paletteChanged() from applyStyleAndPalette so previews, scheme switches and OS dark mode repaint palette-driven widgets.
- Fill both app roles in PaletteGenerator::fromAccent and surface them as a dedicated section in the palette editor.
- Drive the home-tab buttons from appColor() whenever the background source is the theme (any theme, not just built-ins).
- Ship AccentStrong / AccentSoft values in the Fusion and Default default palettes so the static home-tab buttons keep their classic greens.

# Conflicts:
#	cockatrice/src/interface/widgets/general/home_widget.cpp
This commit is contained in:
Lukas Brübach 2026-09-10 16:34:49 +02:00 committed by GitHub
parent 5d025ca0bd
commit 03684bf41d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 195 additions and 12 deletions

View file

@ -416,6 +416,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 +430,37 @@ 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; before that the nearest
// accent is the selection highlight, which Accent defaults to when unset.
const QColor accent = qApp->palette().color(QPalette::Active,
#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0)
QPalette::Accent);
#else
QPalette::Highlight);
#endif
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()