[Fonts] Fix font preview leaks and reuse default-font loader (#7540)

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2026-11-04 07:57:55 +01:00 • committed by GitHub
parent 3bcdfc3793
commit 13e7a3baaf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
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

@ -185,7 +185,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);
@ -280,15 +283,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)
@ -321,7 +318,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()
@ -373,14 +372,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();
@ -396,6 +398,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);
} }
@ -442,6 +445,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;

View file

@ -742,16 +742,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()) {