mirror of
https://github.com/YACReader/yacreader
synced 2026-04-12 15:49:53 -04:00
124 lines
3.6 KiB
C++
124 lines
3.6 KiB
C++
#include "theme_manager.h"
|
|
|
|
#include "appearance_configuration.h"
|
|
#include "theme.h"
|
|
#include "theme_factory.h"
|
|
#include "theme_repository.h"
|
|
|
|
#include <QGuiApplication>
|
|
#include <QStyleHints>
|
|
|
|
ThemeManager::ThemeManager()
|
|
{
|
|
}
|
|
|
|
ThemeManager &ThemeManager::instance()
|
|
{
|
|
static ThemeManager instance;
|
|
return instance;
|
|
}
|
|
|
|
void ThemeManager::initialize(AppearanceConfiguration *config, ThemeRepository *repository)
|
|
{
|
|
this->config = config;
|
|
this->repository = repository;
|
|
|
|
auto *styleHints = qGuiApp->styleHints();
|
|
|
|
// Re-resolve when OS color scheme changes (relevant for FollowSystem mode)
|
|
connect(styleHints, &QStyleHints::colorSchemeChanged, this, &ThemeManager::resolveTheme, Qt::QueuedConnection);
|
|
|
|
// Re-resolve when the user changes any theme setting
|
|
connect(config, &AppearanceConfiguration::selectionChanged, this, &ThemeManager::resolveTheme);
|
|
|
|
resolveTheme();
|
|
}
|
|
|
|
void ThemeManager::setTheme(const Theme &theme)
|
|
{
|
|
currentTheme = theme;
|
|
emit themeChanged();
|
|
}
|
|
|
|
Theme ThemeManager::themeFromId(const QString &id, ThemeVariant fallbackVariant)
|
|
{
|
|
// Try the repository first (handles both builtin and user themes via JSON)
|
|
if (repository && repository->contains(id)) {
|
|
QJsonObject json = repository->loadThemeJson(id);
|
|
if (!json.isEmpty())
|
|
return makeTheme(json);
|
|
}
|
|
|
|
// Fallback to the builtin that matches the current dark/light intent.
|
|
const QString fallbackId = (fallbackVariant == ThemeVariant::Dark)
|
|
? QStringLiteral("builtin/dark")
|
|
: QStringLiteral("builtin/light");
|
|
if (repository && repository->contains(fallbackId)) {
|
|
QJsonObject json = repository->loadThemeJson(fallbackId);
|
|
if (!json.isEmpty())
|
|
return makeTheme(json);
|
|
}
|
|
|
|
return { };
|
|
}
|
|
|
|
void ThemeManager::resolveTheme()
|
|
{
|
|
if (!config)
|
|
return;
|
|
|
|
const auto &sel = config->selection();
|
|
|
|
QString id;
|
|
ThemeVariant fallbackVariant;
|
|
switch (sel.mode) {
|
|
case ThemeMode::FollowSystem: {
|
|
const bool isDark = (qGuiApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark);
|
|
id = isDark ? sel.darkThemeId : sel.lightThemeId;
|
|
fallbackVariant = isDark ? ThemeVariant::Dark : ThemeVariant::Light;
|
|
break;
|
|
}
|
|
case ThemeMode::Light:
|
|
id = sel.lightThemeId;
|
|
fallbackVariant = ThemeVariant::Light;
|
|
break;
|
|
case ThemeMode::Dark:
|
|
id = sel.darkThemeId;
|
|
fallbackVariant = ThemeVariant::Dark;
|
|
break;
|
|
case ThemeMode::ForcedTheme:
|
|
id = sel.fixedThemeId;
|
|
fallbackVariant = (qGuiApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark)
|
|
? ThemeVariant::Dark
|
|
: ThemeVariant::Light;
|
|
break;
|
|
}
|
|
|
|
const Theme theme = themeFromId(id, fallbackVariant);
|
|
|
|
// Sync Qt's application-level color scheme so native widgets (menus, scrollbars,
|
|
// standard dialogs) use the correct palette before themeChanged() is emitted.
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
|
|
Qt::ColorScheme scheme;
|
|
switch (sel.mode) {
|
|
case ThemeMode::FollowSystem:
|
|
scheme = Qt::ColorScheme::Unknown; // delegate to OS
|
|
break;
|
|
case ThemeMode::Light:
|
|
scheme = Qt::ColorScheme::Light;
|
|
break;
|
|
case ThemeMode::Dark:
|
|
scheme = Qt::ColorScheme::Dark;
|
|
break;
|
|
case ThemeMode::ForcedTheme:
|
|
scheme = (theme.meta.variant == ThemeVariant::Dark)
|
|
? Qt::ColorScheme::Dark
|
|
: Qt::ColorScheme::Light;
|
|
break;
|
|
}
|
|
qGuiApp->styleHints()->setColorScheme(scheme);
|
|
#endif
|
|
|
|
setTheme(theme);
|
|
}
|