mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-28 00:42:19 -07:00
Some checks are pending
CodeQL / Analyze (cpp) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 26 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker / Servatrice (arm) (push) Waiting to run
Build Docker / Servatrice (x86) (push) Waiting to run
Build Docker / Publish multi-platform Servatrice image (push) Blocked by required conditions
* [App] Add onboarding wizard Took 10 minutes Took 3 minutes Took 7 minutes Took 9 minutes Took 2 minutes Took 1 minute Took 7 minutes * Adjust CI Took 14 minutes Took 56 seconds Took 2 seconds Took 3 seconds * Adjust CI again Took 14 minutes Took 2 seconds * Comments and fixes Took 9 seconds Took 1 minute * Rebase. Took 5 minutes Took 50 seconds Took 15 seconds * Comments. Took 7 minutes * CI lol Took 3 minutes * CI again lol Took 4 minutes * Drop some settings, add some new ones. Took 19 minutes * Resize when expanding section Took 4 minutes Took 3 minutes Took 7 minutes --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
231 lines
No EOL
8.6 KiB
C++
231 lines
No EOL
8.6 KiB
C++
#include "theme_setup_page.h"
|
|
|
|
#include "../../client/settings/cache_settings.h"
|
|
#include "../../interface/palette_editor/palette_generator.h"
|
|
#include "../../interface/palette_editor/quick_setup_panel.h"
|
|
#include "../../interface/theme_manager.h"
|
|
#include "../../interface/widgets/general/background_sources.h"
|
|
#include "libcockatrice/settings/appearance_settings.h"
|
|
|
|
#include <QComboBox>
|
|
#include <QDir>
|
|
#include <QFile>
|
|
#include <QFormLayout>
|
|
#include <QGroupBox>
|
|
#include <QLabel>
|
|
#include <QMessageBox>
|
|
#include <QVBoxLayout>
|
|
#include <libcockatrice/settings/paths_settings.h>
|
|
#include <libcockatrice/settings/personal_settings.h>
|
|
|
|
ThemeSetupPage::ThemeSetupPage(QWidget *parent) : FirstRunWizardPage(parent)
|
|
{
|
|
themeCombo = new QComboBox(this);
|
|
schemeCombo = new QComboBox(this);
|
|
schemeCombo->addItem(tr("Light"), QStringLiteral("Light"));
|
|
schemeCombo->addItem(tr("Dark"), QStringLiteral("Dark"));
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
|
|
schemeCombo->addItem(tr("Match system"), QStringLiteral("System"));
|
|
#endif
|
|
|
|
quickSetupPanel = new QuickSetupPanel(this);
|
|
|
|
connect(themeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ThemeSetupPage::onThemeChanged);
|
|
connect(schemeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ThemeSetupPage::onSchemeChanged);
|
|
connect(quickSetupPanel, &QuickSetupPanel::valueChanged, this, &ThemeSetupPage::onGenerateFromAccent);
|
|
|
|
homeTabBackgroundCombo = new QComboBox(this);
|
|
for (const auto &entry : BackgroundSources::all()) {
|
|
homeTabBackgroundCombo->addItem(QObject::tr(entry.trKey), QVariant::fromValue(entry.type));
|
|
}
|
|
connect(homeTabBackgroundCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
|
|
&ThemeSetupPage::onHomeTabBackgroundChanged);
|
|
|
|
// Keep the scheme combo honest when the *theme* changes underneath it
|
|
// (switching theme reloads that theme's own stored colorScheme), and
|
|
// opportunistically seed a palette for themes that ship none at all.
|
|
// Mirrors AppearanceSettingsPage's identical listener for the combo-sync
|
|
// half of this.
|
|
connect(themeManager, &ThemeManager::themeChanged, this, [this] {
|
|
const QString newDir = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName());
|
|
const ThemeConfig cfg = ThemeConfig::fromThemeDir(newDir);
|
|
const QString current = cfg.colorScheme;
|
|
|
|
schemeCombo->blockSignals(true);
|
|
const int idx = schemeCombo->findData(current);
|
|
schemeCombo->setCurrentIndex(idx >= 0 ? idx : 0);
|
|
schemeCombo->blockSignals(false);
|
|
|
|
maybeAutoGeneratePalette();
|
|
});
|
|
|
|
auto *form = new QFormLayout;
|
|
form->addRow(tr("Theme:"), themeCombo);
|
|
form->addRow(tr("Appearance:"), schemeCombo);
|
|
form->addRow(tr("Home screen background:"), homeTabBackgroundCombo);
|
|
|
|
accentGroup = new QGroupBox(this);
|
|
auto *accentLayout = new QVBoxLayout(accentGroup);
|
|
accentLayout->addWidget(quickSetupPanel);
|
|
|
|
auto *layout = new QVBoxLayout(this);
|
|
layout->addLayout(form);
|
|
layout->addWidget(accentGroup);
|
|
layout->addStretch();
|
|
|
|
retranslateUi();
|
|
}
|
|
|
|
void ThemeSetupPage::initializePage()
|
|
{
|
|
themeCombo->blockSignals(true);
|
|
themeCombo->clear();
|
|
const QString currentTheme = SettingsCache::instance().getThemeName();
|
|
for (const QString &name : themeManager->getAvailableThemes().keys()) {
|
|
themeCombo->addItem(name);
|
|
}
|
|
const int idx = themeCombo->findText(currentTheme);
|
|
themeCombo->setCurrentIndex(idx >= 0 ? idx : 0);
|
|
themeCombo->blockSignals(false);
|
|
|
|
const QString dirPath = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName());
|
|
const ThemeConfig cfg = ThemeConfig::fromThemeDir(dirPath);
|
|
schemeCombo->blockSignals(true);
|
|
const int schemeIdx = schemeCombo->findData(cfg.colorScheme);
|
|
schemeCombo->setCurrentIndex(schemeIdx >= 0 ? schemeIdx : 0);
|
|
schemeCombo->blockSignals(false);
|
|
|
|
homeTabBackgroundCombo->blockSignals(true);
|
|
QString homeTabSource = SettingsCache::instance().appearance().getHomeTabBackgroundSource();
|
|
int homeTabIdx = homeTabBackgroundCombo->findData(BackgroundSources::fromId(homeTabSource));
|
|
homeTabBackgroundCombo->setCurrentIndex(homeTabIdx >= 0 ? homeTabIdx : 0);
|
|
homeTabBackgroundCombo->blockSignals(false);
|
|
|
|
// Opening the page must not touch the running application's palette:
|
|
// previews and auto-generation only happen in response to the user
|
|
// actually changing a control, never on mere page visibility.
|
|
paletteDirty = false;
|
|
}
|
|
|
|
QString ThemeSetupPage::currentScheme() const
|
|
{
|
|
return schemeCombo->currentData().toString();
|
|
}
|
|
|
|
QString ThemeSetupPage::resolvedScheme() const
|
|
{
|
|
const QString scheme = currentScheme();
|
|
if (scheme.isEmpty() || scheme == QStringLiteral("System")) {
|
|
return themeManager->isDarkMode(themeManager->getCurrentThemePath()) ? "Dark" : "Light";
|
|
}
|
|
return scheme;
|
|
}
|
|
|
|
void ThemeSetupPage::onThemeChanged(int index)
|
|
{
|
|
if (index < 0) {
|
|
return;
|
|
}
|
|
paletteDirty = false;
|
|
SettingsCache::instance().setThemeName(themeCombo->itemText(index));
|
|
// Scheme-combo sync and auto-generation both happen via the
|
|
// ThemeManager::themeChanged listener above, triggered by setThemeName.
|
|
}
|
|
|
|
void ThemeSetupPage::onSchemeChanged()
|
|
{
|
|
themeManager->setColorScheme(currentScheme());
|
|
}
|
|
|
|
void ThemeSetupPage::onHomeTabBackgroundChanged(int index)
|
|
{
|
|
if (index < 0) {
|
|
return;
|
|
}
|
|
auto type = homeTabBackgroundCombo->currentData().value<BackgroundSources::Type>();
|
|
SettingsCache::instance().appearance().setHomeTabBackgroundSource(BackgroundSources::toId(type));
|
|
}
|
|
|
|
void ThemeSetupPage::onGenerateFromAccent(const QColor &accent, int intensity)
|
|
{
|
|
PaletteConfig cfg = PaletteGenerator::fromAccent(accent, intensity, resolvedScheme());
|
|
themeManager->previewPalette(cfg, resolvedScheme());
|
|
paletteDirty = true;
|
|
}
|
|
|
|
void ThemeSetupPage::maybeAutoGeneratePalette()
|
|
{
|
|
const QString dirPath = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName());
|
|
const QString scheme = resolvedScheme();
|
|
|
|
if (PaletteConfig::fromScheme(dirPath, scheme).hasPalette() ||
|
|
PaletteConfig::fromDefault(dirPath, scheme).hasPalette()) {
|
|
return; // theme already has something real to show -- leave it alone
|
|
}
|
|
|
|
// The theme+scheme combination has nothing saved and nothing shipped, and
|
|
// the user just switched to it. Rather than leaving a flat, unstyled look,
|
|
// seed one from whatever accent QuickSetupPanel currently holds and mark
|
|
// it dirty so it's written to disk if the user moves on. Only ever reached
|
|
// through user interaction (theme/scheme change, accent drag) -- never on
|
|
// page open.
|
|
PaletteConfig generated =
|
|
PaletteGenerator::fromAccent(quickSetupPanel->accentColor(), quickSetupPanel->intensity(), scheme);
|
|
themeManager->previewPalette(generated, scheme);
|
|
paletteDirty = true;
|
|
}
|
|
|
|
bool ThemeSetupPage::validatePage()
|
|
{
|
|
if (paletteDirty) {
|
|
const QString scheme = resolvedScheme();
|
|
PaletteConfig cfg =
|
|
PaletteGenerator::fromAccent(quickSetupPanel->accentColor(), quickSetupPanel->intensity(), scheme);
|
|
if (!ThemeManager::commitPalette(writableThemeDir(), scheme, cfg)) {
|
|
QMessageBox::warning(this, tr("Save failed"),
|
|
tr("Could not write the theme palette to:\n%1").arg(writableThemeDir()));
|
|
return false;
|
|
}
|
|
themeManager->reloadCurrentTheme();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
QString ThemeSetupPage::writableThemeDir() const
|
|
{
|
|
// Built-in themes resolve to the read-only system themes directory;
|
|
// palette edits must go to the user themes directory instead, exactly
|
|
// as PaletteEditorDialog does.
|
|
const QString dirPath = themeManager->getAvailableThemes().value(SettingsCache::instance().getThemeName());
|
|
if (!dirPath.isEmpty()) {
|
|
const QString probe = QDir(dirPath).absoluteFilePath(".cockatrice_write_test");
|
|
QFile f(probe);
|
|
if (f.open(QIODevice::WriteOnly)) {
|
|
f.close();
|
|
f.remove();
|
|
return dirPath;
|
|
}
|
|
}
|
|
return QDir(SettingsCache::instance().paths().getThemesPath())
|
|
.absoluteFilePath(SettingsCache::instance().getThemeName());
|
|
}
|
|
|
|
bool ThemeSetupPage::isSkippable() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
QString ThemeSetupPage::stepTitle() const
|
|
{
|
|
return tr("Pick a Look");
|
|
}
|
|
|
|
QString ThemeSetupPage::stepSubtitle() const
|
|
{
|
|
return tr("You can fine-tune every colour later from Settings → Appearance.");
|
|
}
|
|
|
|
void ThemeSetupPage::retranslateUi()
|
|
{
|
|
accentGroup->setTitle(tr("Accent colour (optional)"));
|
|
} |