From a4c2b1411f9585fc9ac348268d7cffa6f0aaa5bf Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 8 May 2026 13:47:14 +0200 Subject: [PATCH] Utility method to check if a theme is supposed to be in dark or light mode. (#6785) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Utility method to check if a theme is supposed to be in dark or light mode. Took 22 minutes Took 4 seconds * Method is public. Took 3 minutes * Add a utility method to check if we're using a built-in theme Took 3 minutes Took 3 seconds * Use built-in theme detection for home screen. Took 6 minutes * Re-polish on theme change Took 2 minutes * Fetch background on theme change. Took 4 minutes Took 6 seconds * No need to double polish. Took 4 minutes * No need to repaint. Took 32 seconds * Only repolish visible widgets. Took 5 minutes --------- Co-authored-by: Lukas Brübach --- cockatrice/src/interface/theme_manager.cpp | 81 ++++++++++++++++--- cockatrice/src/interface/theme_manager.h | 2 + .../interface/widgets/general/home_widget.cpp | 5 +- 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp index 19353b1e9..c7f259ec0 100644 --- a/cockatrice/src/interface/theme_manager.cpp +++ b/cockatrice/src/interface/theme_manager.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #define NONE_THEME_NAME "Default" @@ -112,6 +113,39 @@ void ThemeManager::ensureThemeDirectoryExists() } } +bool ThemeManager::isDarkMode() +{ + auto themeName = SettingsCache::instance().getThemeName(); + // Explicit Dark Mode + if (themeName == FUSION_THEME_NAME_LIGHT || themeName.endsWith("(Light)")) { + return false; + } + // Explicit Light Mode + if (themeName == FUSION_THEME_NAME_DARK || themeName.endsWith("(Dark)")) { + return true; + } + + // Auto detection on compatible Qt versions +#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) + if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark && + (themeName == NONE_THEME_NAME || themeName == FUSION_THEME_NAME || themeName.endsWith("(System Default)"))) { + return true; + } else { + return false; + } +#endif + // Default to light mode + return false; +} + +bool ThemeManager::isBuiltInTheme() +{ + const auto themeName = SettingsCache::instance().getThemeName(); + + return themeName == NONE_THEME_NAME || themeName == FUSION_THEME_NAME || themeName == FUSION_THEME_NAME_LIGHT || + themeName == FUSION_THEME_NAME_DARK; +} + QStringMap &ThemeManager::getAvailableThemes() { QDir dir; @@ -335,26 +369,53 @@ void ThemeManager::themeChangedSlot() qApp->setStyleSheet(""); } + QStyle *newStyle = nullptr; + QPalette newPalette; + if (themeName == FUSION_THEME_NAME) { - QStyle *fusionStyle = QStyleFactory::create("Fusion"); - qApp->setStyle(fusionStyle); + newStyle = QStyleFactory::create("Fusion"); + #if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) // Start from Fusion's own palette so dark mode is handled correctly, // then apply any tweaks on top of it. - QPalette palette = fusionStyle->standardPalette(); + newPalette = newStyle->standardPalette(); if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark) { - palette.setColor(QPalette::AlternateBase, QColor(53, 53, 53)); + newPalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53)); } - qApp->setPalette(palette); +#else + newPalette = qApp->palette(); #endif } else if (themeName == FUSION_THEME_NAME_LIGHT) { - qApp->setStyle(QStyleFactory::create("Fusion")); - qApp->setPalette(createLightGreenFusionPalette()); + newStyle = QStyleFactory::create("Fusion"); + newPalette = createLightGreenFusionPalette(); } else if (themeName == FUSION_THEME_NAME_DARK) { - qApp->setStyle(QStyleFactory::create("Fusion")); - qApp->setPalette(createDarkGreenFusionPalette()); + newStyle = QStyleFactory::create("Fusion"); + newPalette = createDarkGreenFusionPalette(); } else { - qApp->setStyle(QStyleFactory::create(defaultStyleName)); // setting the style also sets the palette + newStyle = QStyleFactory::create(defaultStyleName); + // Use the style's default palette. + newPalette = newStyle->standardPalette(); + } + + // Apply palette FIRST. + qApp->setPalette(newPalette); + // Then apply style. + qApp->setStyle(newStyle); + + // 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. + // Note: we do NOT call widget->setPalette(base) here — qApp->setPalette() + // already propagates to all widgets that haven't explicitly overridden their + // palette (WA_SetPalette not set). Calling it unconditionally would clobber + // intentional per-widget palette customisations across the whole app. + for (QWidget *widget : qApp->allWidgets()) { + if (widget->isVisible()) { + newStyle->unpolish(widget); + newStyle->polish(widget); + + widget->update(); + } } if (dirPath.isEmpty()) { diff --git a/cockatrice/src/interface/theme_manager.h b/cockatrice/src/interface/theme_manager.h index d942f0fef..416923128 100644 --- a/cockatrice/src/interface/theme_manager.h +++ b/cockatrice/src/interface/theme_manager.h @@ -54,6 +54,8 @@ protected: QBrush loadExtraBrush(QString fileName, QBrush &fallbackBrush); public: + bool isBuiltInTheme(); + bool isDarkMode(); QStringMap &getAvailableThemes(); QBrush &getBgBrush(Role zone); diff --git a/cockatrice/src/interface/widgets/general/home_widget.cpp b/cockatrice/src/interface/widgets/general/home_widget.cpp index ea20ef6a0..a87d69119 100644 --- a/cockatrice/src/interface/widgets/general/home_widget.cpp +++ b/cockatrice/src/interface/widgets/general/home_widget.cpp @@ -2,6 +2,7 @@ #include "../../../client/settings/cache_settings.h" #include "../../../interface/widgets/tabs/tab_supervisor.h" +#include "../../theme_manager.h" #include "../../window_main.h" #include "background_sources.h" #include "home_styled_button.h" @@ -46,6 +47,8 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor) &HomeWidget::onBackgroundShuffleFrequencyChanged); // Lambda is cleaner to read than overloading this connect(&SettingsCache::instance(), &SettingsCache::homeTabDisplayCardNameChanged, this, [this] { repaint(); }); + connect(&SettingsCache::instance(), &SettingsCache::themeChanged, this, + &HomeWidget::initializeBackgroundFromSource); connect(&SettingsCache::instance(), &SettingsCache::themeChanged, this, &HomeWidget::updateButtonsToBackgroundColor); } @@ -256,7 +259,7 @@ void HomeWidget::updateConnectButton(const ClientStatus status) QPair HomeWidget::extractDominantColors(const QPixmap &pixmap) { - if (SettingsCache::instance().getThemeName() == "Default" && + if (themeManager->isBuiltInTheme() && SettingsCache::instance().getHomeTabBackgroundSource() == BackgroundSources::toId(BackgroundSources::Theme)) { return QPair(QColor::fromRgb(20, 140, 60), QColor::fromRgb(120, 200, 80)); }