mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-09-21 09:05:10 -07:00
[App] Add onboarding wizard (#7064)
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
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>
This commit is contained in:
parent
815c5987b4
commit
2b7b4e8168
45 changed files with 3207 additions and 336 deletions
|
|
@ -0,0 +1,231 @@
|
|||
#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)"));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue