[Fonts] Fix font preview leaks and reuse default-font loader

This commit is contained in:
Lukas Brübach 2026-10-16 09:57:01 +02:00
parent e834339c71
commit 42895e92a3
4 changed files with 41 additions and 29 deletions

View file

@ -71,6 +71,9 @@ FontGridWidget::FontGridWidget(QWidget *parent) : QWidget(parent)
void FontGridWidget::loadFonts(const FontConfig &cfg) void FontGridWidget::loadFonts(const FontConfig &cfg)
{ {
// Suppress fontsChanged while materializing fallback rows so the initial
// load never reads as a user edit (mirrors paletteGrid blocking).
blockSignals(true);
QMetaEnum fontEnum = QMetaEnum::fromType<AppFont::Role>(); QMetaEnum fontEnum = QMetaEnum::fromType<AppFont::Role>();
for (int i = 0; i < fontEnum.keyCount(); ++i) { for (int i = 0; i < fontEnum.keyCount(); ++i) {
auto role = static_cast<AppFont::Role>(fontEnum.value(i)); auto role = static_cast<AppFont::Role>(fontEnum.value(i));
@ -93,6 +96,7 @@ void FontGridWidget::loadFonts(const FontConfig &cfg)
} }
row.sizeSpin->setValue(qBound(MIN_FONT_SIZE, size, MAX_FONT_SIZE)); row.sizeSpin->setValue(qBound(MIN_FONT_SIZE, size, MAX_FONT_SIZE));
} }
blockSignals(false);
} }
FontConfig FontGridWidget::currentFontConfig() const FontConfig FontGridWidget::currentFontConfig() const

View file

@ -186,7 +186,10 @@ void PaletteEditorDialog::setupUi()
connect(autoApplyTimer, &QTimer::timeout, this, &PaletteEditorDialog::onApply); connect(autoApplyTimer, &QTimer::timeout, this, &PaletteEditorDialog::onApply);
connect(quickSetupPanel, &QuickSetupPanel::valueChanged, this, &PaletteEditorDialog::onGenerateFromAccent); connect(quickSetupPanel, &QuickSetupPanel::valueChanged, this, &PaletteEditorDialog::onGenerateFromAccent);
connect(paletteGrid, &PaletteGridWidget::paletteChanged, this, [this] { autoApplyTimer->start(); }); connect(paletteGrid, &PaletteGridWidget::paletteChanged, this, [this] { autoApplyTimer->start(); });
connect(fontGrid, &FontGridWidget::fontsChanged, this, [this] { autoApplyTimer->start(); }); connect(fontGrid, &FontGridWidget::fontsChanged, this, [this] {
fontsDirty = true;
autoApplyTimer->start();
});
connect(revertButton, &QPushButton::clicked, this, &PaletteEditorDialog::onRevertToDefault); connect(revertButton, &QPushButton::clicked, this, &PaletteEditorDialog::onRevertToDefault);
connect(resetBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onReset); connect(resetBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onReset);
connect(saveBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onSave); connect(saveBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onSave);
@ -281,15 +284,9 @@ void PaletteEditorDialog::loadSchemes()
void PaletteEditorDialog::loadFonts() void PaletteEditorDialog::loadFonts()
{ {
// Same user-dir > system-dir fallback ThemeManager uses: the shipped savedFontConfig = ThemeManager::loadDefaultFontConfig(themeDirPath, themeName);
// fonts.toml may live in the system theme directory rather than the fontGrid->loadFonts(savedFontConfig);
// resolved (user) theme directory. fontsDirty = false;
FontConfig cfg = ThemeManager::loadFontConfig(themeDirPath);
if (!cfg.hasFonts()) {
cfg = ThemeManager::loadDefaultFontConfig(themeDirPath, themeName);
}
savedFontConfig = cfg;
fontGrid->loadFonts(cfg);
} }
void PaletteEditorDialog::seedAccentFromScheme(const QString &scheme) void PaletteEditorDialog::seedAccentFromScheme(const QString &scheme)
@ -322,7 +319,9 @@ void PaletteEditorDialog::onGenerateFromAccent(const QColor &accent, int intensi
void PaletteEditorDialog::onApply() void PaletteEditorDialog::onApply()
{ {
themeManager->previewPalette(paletteGrid->currentPaletteConfig(), loadedScheme); themeManager->previewPalette(paletteGrid->currentPaletteConfig(), loadedScheme);
themeManager->previewFonts(fontGrid->currentFontConfig()); if (fontsDirty) {
themeManager->previewFonts(fontGrid->currentFontConfig());
}
} }
void PaletteEditorDialog::onSave() void PaletteEditorDialog::onSave()
@ -374,14 +373,17 @@ void PaletteEditorDialog::onSave()
} }
// Persist the shared per-theme fonts when they changed. // Persist the shared per-theme fonts when they changed.
const FontConfig fontCfg = fontGrid->currentFontConfig(); if (fontsDirty) {
if (fontCfg != savedFontConfig) { const FontConfig fontCfg = fontGrid->currentFontConfig();
if (!ThemeManager::saveFontConfig(saveDir, fontCfg)) { if (fontCfg != savedFontConfig) {
QMessageBox::warning(this, tr("Save failed"), if (!ThemeManager::saveFontConfig(saveDir, fontCfg)) {
tr("Could not write %1 to:\n%2").arg(FontConfig::fileName(), saveDir)); QMessageBox::warning(this, tr("Save failed"),
return; tr("Could not write %1 to:\n%2").arg(FontConfig::fileName(), saveDir));
return;
}
savedFontConfig = fontCfg;
} }
savedFontConfig = fontCfg; fontsDirty = false;
} }
themeManager->reloadCurrentTheme(); themeManager->reloadCurrentTheme();
@ -397,6 +399,7 @@ void PaletteEditorDialog::onReset()
// config until the theme is reloaded. // config until the theme is reloaded.
themeManager->reloadCurrentTheme(); themeManager->reloadCurrentTheme();
fontGrid->loadFonts(savedFontConfig); fontGrid->loadFonts(savedFontConfig);
fontsDirty = false;
seedAccentFromScheme(loadedScheme); seedAccentFromScheme(loadedScheme);
} }
@ -443,6 +446,15 @@ void PaletteEditorDialog::onRevertToDefault()
const FontConfig fontDef = ThemeManager::loadDefaultFontConfig(themeDirPath, themeName); const FontConfig fontDef = ThemeManager::loadDefaultFontConfig(themeDirPath, themeName);
savedFontConfig = fontDef; savedFontConfig = fontDef;
fontGrid->loadFonts(fontDef); fontGrid->loadFonts(fontDef);
fontsDirty = false;
}
void PaletteEditorDialog::reject()
{
// Discard any unsaved live preview (palette and fonts) so closing without
// Save restores the active theme instead of leaking the preview globally.
themeManager->reloadCurrentTheme();
QDialog::reject();
} }
void PaletteEditorDialog::changeEvent(QEvent *e) void PaletteEditorDialog::changeEvent(QEvent *e)

View file

@ -26,6 +26,7 @@ class PaletteEditorDialog : public QDialog
public: public:
explicit PaletteEditorDialog(const QString &themeDirPath, const QString &themeName, QWidget *parent = nullptr); explicit PaletteEditorDialog(const QString &themeDirPath, const QString &themeName, QWidget *parent = nullptr);
void loadSchemes(); void loadSchemes();
void reject() override;
private slots: private slots:
void onSave(); void onSave();
@ -79,6 +80,10 @@ private:
// Fonts are shared per theme (fonts.toml, not split by light/dark), so a // Fonts are shared per theme (fonts.toml, not split by light/dark), so a
// single saved config suffices; the live edits are read from fontGrid. // single saved config suffices; the live edits are read from fontGrid.
FontConfig savedFontConfig; FontConfig savedFontConfig;
// Set only by user-driven fontsChanged after the initial load completes.
// Gates both previewFonts and the fonts.toml write so a palette-only Save
// never materializes fallback fonts to disk.
bool fontsDirty = false;
QTimer *autoApplyTimer = nullptr; QTimer *autoApplyTimer = nullptr;
@ -86,4 +91,4 @@ protected:
void changeEvent(QEvent *e) override; void changeEvent(QEvent *e) override;
}; };
#endif // COCKATRICE_PALETTE_EDITOR_DIALOG_H #endif // COCKATRICE_PALETTE_EDITOR_DIALOG_H

View file

@ -739,16 +739,7 @@ void ThemeManager::themeChangedSlot()
applyStyleAndPalette(themeName, themeCfg, palette, activeScheme); applyStyleAndPalette(themeName, themeCfg, palette, activeScheme);
// ── Load fonts: shared per theme, no light/dark split ─────────────────── // ── Load fonts: shared per theme, no light/dark split ───────────────────
FontConfig fonts = loadFontConfig(dirPath); FontConfig fonts = loadDefaultFontConfig(dirPath, themeName);
if (!fonts.hasFonts()) {
// The shipped fonts.toml may live in the system theme directory rather
// than the resolved (user) theme directory, so built-in themes still
// get their curated fonts.
const QString sysFontPath = QDir(systemThemesBasePath()).absoluteFilePath(themeName);
if (sysFontPath != dirPath) {
fonts = loadFontConfig(sysFontPath);
}
}
currentFonts = fonts; currentFonts = fonts;
const auto fontIt = currentFonts.fonts.constFind(AppFont::InterfaceDefault); const auto fontIt = currentFonts.fonts.constFind(AppFont::InterfaceDefault);
if (fontIt != currentFonts.fonts.constEnd()) { if (fontIt != currentFonts.fonts.constEnd()) {