diff --git a/cockatrice/src/interface/palette_editor/font_grid_widget.cpp b/cockatrice/src/interface/palette_editor/font_grid_widget.cpp index c3841b95f..1dd8345bb 100644 --- a/cockatrice/src/interface/palette_editor/font_grid_widget.cpp +++ b/cockatrice/src/interface/palette_editor/font_grid_widget.cpp @@ -76,9 +76,11 @@ void FontGridWidget::loadFonts(const FontConfig &cfg) auto role = static_cast(fontEnum.value(i)); const FontRow &row = fontRows[role]; - // Roles absent from the file resolve to the theme's effective font, so - // unset roles visibly show the system default instead of blanks. - const QFont font = cfg.fonts.value(role, themeManager->appFont(role)); + // Roles absent from the file resolve to the startup font, not to the + // live preview: appFont() would return the previewed config, so Reset + // and a first load would both show the edited font instead of the + // theme's real default. + const QFont font = cfg.fonts.value(role, themeManager->defaultAppFont(role)); row.familyCombo->setCurrentFont(font); int size = font.pointSize(); diff --git a/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp b/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp index c3412bd09..36027f7d0 100644 --- a/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp +++ b/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp @@ -392,6 +392,10 @@ void PaletteEditorDialog::onReset() { workingConfig[loadedScheme] = savedConfig[loadedScheme]; paletteGrid->loadPalette(savedConfig[loadedScheme]); + // Restore the live theme before re-reading the grid: loadFonts resolves + // unset roles, and the preview has currentFonts pointing at the edited + // config until the theme is reloaded. + themeManager->reloadCurrentTheme(); fontGrid->loadFonts(savedFontConfig); seedAccentFromScheme(loadedScheme); } diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp index f9d5a67c4..777bd1908 100644 --- a/cockatrice/src/interface/theme_manager.cpp +++ b/cockatrice/src/interface/theme_manager.cpp @@ -128,9 +128,9 @@ static QString usableDefaultStyle(const QString &style) ThemeManager::ThemeManager(QObject *parent) : QObject(parent) { defaultStyleName = usableDefaultStyle(qApp->style()->objectName()); - // Capture the untouched application palette before any theme is applied. + // Capture the untouched application palette and font before any theme is + // applied. defaultPalette = qApp->palette(); - // Capture the untouched application font before any theme font is applied. defaultFont = qApp->font(); ensureThemeDirectoryExists(); #if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)) @@ -535,18 +535,15 @@ void ThemeManager::previewFonts(const FontConfig &cfg) { currentFonts = cfg; + // QApplication::setFont already sends a font change to every widget, so a + // repolish pass is not needed for fonts (unlike the palette path). const auto it = cfg.fonts.constFind(AppFont::InterfaceDefault); if (it != cfg.fonts.constEnd()) { qApp->setFont(it.value()); - - // Repolish every widget immediately so the preview applies without - // waiting for natural expose events, mirroring applyStyleAndPalette. - QStyle *style = qApp->style(); - for (QWidget *widget : qApp->allWidgets()) { - style->unpolish(widget); - style->polish(widget); - widget->update(); - } + } else { + // A config without InterfaceDefault means "no override": restore the + // startup font instead of leaving the last preview applied. + qApp->setFont(defaultFont); } emit fontsChanged(); @@ -663,13 +660,11 @@ QFont ThemeManager::appFont(AppFont::Role role) const // present: chat logs rendered monospace (matching the report dialogs), // card text from a serif basis, everything else from the app font. if (role == AppFont::ChatLog) { - QFont monoFont(QStringLiteral("monospace")); - monoFont.setStyleHint(QFont::Monospace); - const int systemPointSize = QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize(); - if (systemPointSize > 0) { - monoFont.setPointSize(systemPointSize); - } - return monoFont; + // ChatView never set a font before the theme role existed, so an unset + // ChatLog must keep resolving to the application font. The report + // dialogs that used to hardcode monospace ask for it explicitly + // (report_utils::reportLogFont) instead of through this fallback. + return qApp->font(); } if (role == AppFont::CardText) { return QFont(QStringLiteral("Serif")); @@ -680,6 +675,19 @@ QFont ThemeManager::appFont(AppFont::Role role) const return qApp->font(); } +bool ThemeManager::hasAppFont(AppFont::Role role) const +{ + return currentFonts.fonts.contains(role); +} + +QFont ThemeManager::defaultAppFont(AppFont::Role /*role*/) const +{ + // No per-role scaling and no preview: an unset role resolves to the font + // captured at startup, which is what the theme falls back to once the + // editor closes. + return defaultFont; +} + void ThemeManager::themeChangedSlot() { QString themeName = SettingsCache::instance().getThemeName(); diff --git a/cockatrice/src/interface/theme_manager.h b/cockatrice/src/interface/theme_manager.h index 8a0e6919b..7e74e4c31 100644 --- a/cockatrice/src/interface/theme_manager.h +++ b/cockatrice/src/interface/theme_manager.h @@ -49,8 +49,8 @@ private: // switching away from a custom palette restores the original colours. QPalette defaultPalette; // Pristine application font captured at startup, before any theme font is - // applied. Used to restore the original font when a theme supplies none, - // mirroring defaultPalette above. + // applied. Restored when a theme (or a preview) supplies no InterfaceDefault + // font, so switching away from a themed font cannot leave it behind. QFont defaultFont; QString currentThemePath; std::array brushes; @@ -154,6 +154,13 @@ public: * ChatLog, serif basis for CardText, the application font for the * remaining roles). */ QFont appFont(AppFont::Role role) const; + /** @brief Whether the active theme defines this role in fonts.toml. */ + bool hasAppFont(AppFont::Role role) const; + /** @brief Resolves an application font role against the startup font only, + * ignoring any previewed config in currentFonts. Editors that show + * "what this role resolves to" must use this, because appFont() + * reflects a live preview while the editor is open. */ + QFont defaultAppFont(AppFont::Role role) const; QBrush &getBgBrush(Role zone); QBrush getExtraBgBrush(Role zone, int zoneId = 0); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp index a259b6a56..a7387a068 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -127,14 +126,7 @@ DlgMyReports::DlgMyReports(AbstractClient *_client, QWidget *parent) void DlgMyReports::applyChatLogFont() { - // Family comes from the ChatLog theme role; size stays caller-side as before. - QFont monoFont = themeManager->appFont(AppFont::ChatLog); - monoFont.setStyleHint(QFont::Monospace); - const int systemPointSize = QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize(); - if (systemPointSize > 0) { - monoFont.setPointSize(systemPointSize); - } - chatLogEdit->setFont(monoFont); + chatLogEdit->setFont(report_utils::reportLogFont()); } void DlgMyReports::refreshList() diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_report_user.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_report_user.cpp index 5cdeb22a1..5b0937177 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_report_user.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_report_user.cpp @@ -1,13 +1,13 @@ #include "dlg_report_user.h" #include "../interface/theme_manager.h" +#include "../utility/report_utils.h" #include "abstract_client.h" #include "libcockatrice/protocol/pb/response.pb.h" #include #include #include -#include #include #include #include @@ -125,14 +125,7 @@ DlgReportUser::DlgReportUser(AbstractClient *_client, void DlgReportUser::applyChatLogFont() { - // Family comes from the ChatLog theme role; size stays caller-side as before. - QFont monoFont = themeManager->appFont(AppFont::ChatLog); - monoFont.setStyleHint(QFont::Monospace); - const int systemPointSize = QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize(); - if (systemPointSize > 0) { - monoFont.setPointSize(systemPointSize); - } - chatLogEdit->setFont(monoFont); + chatLogEdit->setFont(report_utils::reportLogFont()); } void DlgReportUser::actSubmit() diff --git a/cockatrice/src/interface/widgets/tabs/tab_report.cpp b/cockatrice/src/interface/widgets/tabs/tab_report.cpp index bcb6e7191..1df5bc078 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_report.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_report.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -275,14 +274,7 @@ TabReport::TabReport(TabSupervisor *_tabSupervisor, AbstractClient *_client) : T void TabReport::applyChatLogFont() { - // Family comes from the ChatLog theme role; size stays caller-side as before. - QFont monoFont = themeManager->appFont(AppFont::ChatLog); - monoFont.setStyleHint(QFont::Monospace); - const int systemPointSize = QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize(); - if (systemPointSize > 0) { - monoFont.setPointSize(systemPointSize); - } - chatLogEdit->setFont(monoFont); + chatLogEdit->setFont(report_utils::reportLogFont()); } void TabReport::retranslateUi() diff --git a/cockatrice/src/interface/widgets/utility/report_utils.cpp b/cockatrice/src/interface/widgets/utility/report_utils.cpp index d7fc083c6..df2400b14 100644 --- a/cockatrice/src/interface/widgets/utility/report_utils.cpp +++ b/cockatrice/src/interface/widgets/utility/report_utils.cpp @@ -1,5 +1,6 @@ #include "report_utils.h" +#include "../../theme_manager.h" #include "libcockatrice/protocol/pb/serverinfo_report.pb.h" #include @@ -7,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +21,20 @@ namespace report_utils { +QFont reportLogFont() +{ + if (themeManager->hasAppFont(AppFont::ChatLog)) { + return themeManager->appFont(AppFont::ChatLog); + } + QFont monoFont(QStringLiteral("monospace")); + monoFont.setStyleHint(QFont::Monospace); + const int systemPointSize = QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize(); + if (systemPointSize > 0) { + monoFont.setPointSize(systemPointSize); + } + return monoFont; +} + namespace { QColor reportStatusColor(const QString &status) diff --git a/cockatrice/src/interface/widgets/utility/report_utils.h b/cockatrice/src/interface/widgets/utility/report_utils.h index 679989486..32cc19eac 100644 --- a/cockatrice/src/interface/widgets/utility/report_utils.h +++ b/cockatrice/src/interface/widgets/utility/report_utils.h @@ -1,6 +1,7 @@ #ifndef REPORT_UTILS_H #define REPORT_UTILS_H +#include #include #include @@ -11,6 +12,12 @@ class ServerInfo_Report; namespace report_utils { +/** @brief Font for the report chat-log views: the theme's ChatLog role when it + * sets one, otherwise the monospace font these views used before the + * role existed. Shared by the three report surfaces so they cannot + * drift apart. */ +QFont reportLogFont(); + QString formatReportCategory(const QString &category); QString formatReportTime(qint64 secondsSinceEpoch);