diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 63ce7d1af..dfe405e97 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -172,6 +172,7 @@ set(cockatrice_SOURCES src/interface/palette_editor/palette_generator.cpp src/interface/palette_editor/quick_setup_panel.cpp src/interface/palette_editor/palette_grid_widget.cpp + src/interface/palette_editor/font_grid_widget.cpp src/interface/palette_editor/palette_editor_dialog.cpp src/interface/widgets/cards/additional_info/color_identity_widget.cpp src/interface/widgets/cards/additional_info/deck_color_identity.cpp diff --git a/cockatrice/src/interface/palette_editor/font_grid_widget.cpp b/cockatrice/src/interface/palette_editor/font_grid_widget.cpp new file mode 100644 index 000000000..c3841b95f --- /dev/null +++ b/cockatrice/src/interface/palette_editor/font_grid_widget.cpp @@ -0,0 +1,124 @@ +#include "font_grid_widget.h" + +#include "../theme_manager.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static constexpr int MIN_FONT_SIZE = 6; +static constexpr int MAX_FONT_SIZE = 72; +static constexpr int FALLBACK_FONT_SIZE = 10; + +static const QMap APP_FONT_DESCRIPTIONS = { + {AppFont::InterfaceDefault, QT_TR_NOOP("Default font for menus, dialogs and widgets")}, + {AppFont::ChatLog, QT_TR_NOOP("Font for chat messages and logs")}, + {AppFont::CardText, QT_TR_NOOP("Font for text rendered on cards")}, + {AppFont::DeckList, QT_TR_NOOP("Font for deck lists and the deck editor")}, +}; + +static QString roleDisplayName(AppFont::Role role) +{ + switch (role) { + case AppFont::InterfaceDefault: + return FontGridWidget::tr("Interface default"); + case AppFont::ChatLog: + return FontGridWidget::tr("Chat log"); + case AppFont::CardText: + return FontGridWidget::tr("Card text"); + case AppFont::DeckList: + return FontGridWidget::tr("Deck list"); + default: + return QString(); + } +} + +FontGridWidget::FontGridWidget(QWidget *parent) : QWidget(parent) +{ + auto *grid = new QGridLayout(this); + grid->setSpacing(3); + grid->setContentsMargins(12, 8, 12, 8); + grid->setColumnStretch(0, 0); + grid->setColumnStretch(1, 1); + grid->setColumnStretch(2, 0); + + QMetaEnum fontEnum = QMetaEnum::fromType(); + for (int i = 0; i < fontEnum.keyCount(); ++i) { + auto role = static_cast(fontEnum.value(i)); + + auto *label = new QLabel(this); + grid->addWidget(label, i, 0); + + auto *familyCombo = new QFontComboBox(this); + grid->addWidget(familyCombo, i, 1); + connect(familyCombo, &QFontComboBox::currentFontChanged, this, [this] { emit fontsChanged(); }); + + auto *sizeSpin = new QSpinBox(this); + sizeSpin->setRange(MIN_FONT_SIZE, MAX_FONT_SIZE); + grid->addWidget(sizeSpin, i, 2); + connect(sizeSpin, &QSpinBox::valueChanged, this, [this] { emit fontsChanged(); }); + + fontRows[role] = {label, familyCombo, sizeSpin}; + } + + retranslateUi(); +} + +void FontGridWidget::loadFonts(const FontConfig &cfg) +{ + QMetaEnum fontEnum = QMetaEnum::fromType(); + for (int i = 0; i < fontEnum.keyCount(); ++i) { + 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)); + row.familyCombo->setCurrentFont(font); + + int size = font.pointSize(); + if (size <= 0) { + size = qApp->font().pointSize(); + } + if (size <= 0) { + size = FALLBACK_FONT_SIZE; + } + row.sizeSpin->setValue(qBound(MIN_FONT_SIZE, size, MAX_FONT_SIZE)); + } +} + +FontConfig FontGridWidget::currentFontConfig() const +{ + FontConfig cfg; + QMetaEnum fontEnum = QMetaEnum::fromType(); + for (int i = 0; i < fontEnum.keyCount(); ++i) { + auto role = static_cast(fontEnum.value(i)); + const FontRow &row = fontRows.value(role); + + // Canonical family + point size only: a fresh QFont carries default + // (non-bold, non-italic) weight/style, so nothing combo-side leaks in. + QFont font(row.familyCombo->currentFont().family()); + font.setPointSize(row.sizeSpin->value()); + cfg.fonts[role] = font; + } + return cfg; +} + +void FontGridWidget::retranslateUi() +{ + QMetaEnum fontEnum = QMetaEnum::fromType(); + for (int i = 0; i < fontEnum.keyCount(); ++i) { + auto role = static_cast(fontEnum.value(i)); + const FontRow &row = fontRows.value(role); + + row.label->setText(roleDisplayName(role)); + row.label->setToolTip(tr(APP_FONT_DESCRIPTIONS.value(role, ""))); + row.familyCombo->setToolTip(tr(APP_FONT_DESCRIPTIONS.value(role, ""))); + row.sizeSpin->setToolTip(tr("Point size")); + } +} diff --git a/cockatrice/src/interface/palette_editor/font_grid_widget.h b/cockatrice/src/interface/palette_editor/font_grid_widget.h new file mode 100644 index 000000000..8c80306d3 --- /dev/null +++ b/cockatrice/src/interface/palette_editor/font_grid_widget.h @@ -0,0 +1,43 @@ +#ifndef COCKATRICE_FONT_GRID_WIDGET_H +#define COCKATRICE_FONT_GRID_WIDGET_H + +#include "../theme_config.h" + +#include +#include +#include + +class QFontComboBox; +class QGridLayout; +class QLabel; +class QSpinBox; + +// Per-role font editors — one (family, point size) row per AppFont::Role. +// Owns the load/read round-trip for FontConfig but has no file I/O, mirroring +// PaletteGridWidget. Only family and point size are edited; weight and italic +// stay caller-side concerns and are stripped when reading back. +class FontGridWidget : public QWidget +{ + Q_OBJECT +public: + explicit FontGridWidget(QWidget *parent = nullptr); + + void loadFonts(const FontConfig &cfg); + FontConfig currentFontConfig() const; + void retranslateUi(); + +signals: + void fontsChanged(); + +private: + struct FontRow + { + QLabel *label = nullptr; + QFontComboBox *familyCombo = nullptr; + QSpinBox *sizeSpin = nullptr; + }; + + QMap fontRows; +}; + +#endif // COCKATRICE_FONT_GRID_WIDGET_H diff --git a/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp b/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp index 20e16614a..c3412bd09 100644 --- a/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp +++ b/cockatrice/src/interface/palette_editor/palette_editor_dialog.cpp @@ -2,6 +2,7 @@ #include "../theme_config.h" #include "../theme_manager.h" +#include "font_grid_widget.h" #include "palette_generator.h" #include "palette_grid_widget.h" #include "quick_setup_panel.h" @@ -40,6 +41,7 @@ PaletteEditorDialog::PaletteEditorDialog(const QString &_themeDirPath, const QSt // Load both scheme configs upfront so switching is instant loadSchemes(); + loadFonts(); loadedScheme = themeManager->isDarkMode(themeDirPath) ? "Dark" : "Light"; @@ -126,6 +128,32 @@ void PaletteEditorDialog::setupUi() paletteGrid->setVisible(false); root->addWidget(paletteGrid, 1); + // Font section — sibling to the palette grid, sharing its collapsible + // advanced area pattern. Fonts are shared per theme, not split by scheme. + fontToggleButton = new QPushButton(this); + fontToggleButton->setCheckable(true); + fontToggleButton->setChecked(false); + fontToggleButton->setFlat(true); + fontToggleButton->setStyleSheet("QPushButton { text-align: left; padding: 5px 12px; font-weight: bold; }" + "QPushButton:checked { }"); + root->addWidget(fontToggleButton); + + fontSeparator = makeSeparator(); + fontSeparator->setVisible(false); + root->addWidget(fontSeparator); + + fontSection = new QWidget; + auto *fontSectionLayout = new QVBoxLayout(fontSection); + fontSectionLayout->setContentsMargins(0, 0, 0, 0); + fontSectionLayout->setSpacing(0); + fontNoteLabel = new QLabel(fontSection); + fontNoteLabel->setContentsMargins(12, 4, 12, 0); + fontSectionLayout->addWidget(fontNoteLabel); + fontGrid = new FontGridWidget(fontSection); + fontSectionLayout->addWidget(fontGrid); + fontSection->setVisible(false); + root->addWidget(fontSection); + // Footer root->addWidget(makeSeparator()); footer = new QWidget; @@ -158,6 +186,7 @@ void PaletteEditorDialog::setupUi() connect(autoApplyTimer, &QTimer::timeout, this, &PaletteEditorDialog::onApply); connect(quickSetupPanel, &QuickSetupPanel::valueChanged, this, &PaletteEditorDialog::onGenerateFromAccent); connect(paletteGrid, &PaletteGridWidget::paletteChanged, this, [this] { autoApplyTimer->start(); }); + connect(fontGrid, &FontGridWidget::fontsChanged, this, [this] { autoApplyTimer->start(); }); connect(revertButton, &QPushButton::clicked, this, &PaletteEditorDialog::onRevertToDefault); connect(resetBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onReset); connect(saveBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onSave); @@ -167,15 +196,32 @@ void PaletteEditorDialog::setupUi() paletteGridToggleButton->setText(open ? tr("▼ Edit Palette") : tr("▶ Edit Palette")); paletteGridSeparator->setVisible(open); paletteGrid->setVisible(open); - - if (open) { - setMinimumHeight(680); - resize(width(), 680); - } else { - setMinimumHeight(220); - adjustSize(); // shrinks to fit just the visible content - } + updateAdvancedHeight(); }); + connect(fontToggleButton, &QPushButton::toggled, this, [this](bool open) { + fontToggleButton->setText(open ? tr("▼ Edit Fonts") : tr("▶ Edit Fonts")); + fontSeparator->setVisible(open); + fontSection->setVisible(open); + updateAdvancedHeight(); + }); +} + +void PaletteEditorDialog::updateAdvancedHeight() +{ + int height = 220; + if (paletteGridToggleButton->isChecked()) { + height += 460; + } + if (fontToggleButton->isChecked()) { + height += 200; + } + setMinimumHeight(height); + + if (paletteGrid->isVisible() || fontSection->isVisible()) { + resize(width(), height); + } else { + adjustSize(); // shrinks to fit just the visible content + } } void PaletteEditorDialog::retranslateUi() @@ -190,12 +236,16 @@ void PaletteEditorDialog::retranslateUi() editingLabel->setText(tr("Editing:")); paletteGridToggleButton->setText(tr("▶ Edit Palette")); paletteGridToggleButton->setToolTip(tr("Show or hide the per-role colour grid for manual tweaks")); + fontToggleButton->setText(fontSection->isVisible() ? tr("▼ Edit Fonts") : tr("▶ Edit Fonts")); + fontToggleButton->setToolTip(tr("Show or hide the per-purpose font settings for this theme")); + fontNoteLabel->setText(tr("Fonts belong to theme %1").arg(themeName)); + fontGrid->retranslateUi(); revertButton->setText(tr("↺ Revert to theme default")); resetBtn->setText(tr("Reset")); saveBtn->setText(tr("Save")); - resetBtn->setToolTip(tr("Discard unsaved edits and restore the last saved palette")); - saveBtn->setToolTip(tr("Write palette-%1.toml and reload the theme").arg(loadedScheme.toLower())); + resetBtn->setToolTip(tr("Discard unsaved edits and restore the last saved palette and fonts")); + saveBtn->setToolTip(tr("Write palette-%1.toml and fonts.toml, then reload the theme").arg(loadedScheme.toLower())); if (saveDir.isEmpty() || !ThemeManager::isDirReallyWritable(saveDir)) { saveBtn->setEnabled(false); @@ -229,6 +279,19 @@ void PaletteEditorDialog::loadSchemes() } } +void PaletteEditorDialog::loadFonts() +{ + // Same user-dir > system-dir fallback ThemeManager uses: the shipped + // fonts.toml may live in the system theme directory rather than the + // resolved (user) theme directory. + FontConfig cfg = ThemeManager::loadFontConfig(themeDirPath); + if (!cfg.hasFonts()) { + cfg = ThemeManager::loadDefaultFontConfig(themeDirPath, themeName); + } + savedFontConfig = cfg; + fontGrid->loadFonts(cfg); +} + void PaletteEditorDialog::seedAccentFromScheme(const QString &scheme) { QColor seed = workingConfig.value(scheme).colors.value(QPalette::Active).value(QPalette::Highlight); @@ -259,6 +322,7 @@ void PaletteEditorDialog::onGenerateFromAccent(const QColor &accent, int intensi void PaletteEditorDialog::onApply() { themeManager->previewPalette(paletteGrid->currentPaletteConfig(), loadedScheme); + themeManager->previewFonts(fontGrid->currentFontConfig()); } void PaletteEditorDialog::onSave() @@ -309,6 +373,17 @@ void PaletteEditorDialog::onSave() savedConfig[it.key()] = it.value(); } + // Persist the shared per-theme fonts when they changed. + const FontConfig fontCfg = fontGrid->currentFontConfig(); + if (fontCfg != savedFontConfig) { + if (!ThemeManager::saveFontConfig(saveDir, fontCfg)) { + QMessageBox::warning(this, tr("Save failed"), + tr("Could not write %1 to:\n%2").arg(FontConfig::fileName(), saveDir)); + return; + } + savedFontConfig = fontCfg; + } + themeManager->reloadCurrentTheme(); accept(); } @@ -317,6 +392,7 @@ void PaletteEditorDialog::onReset() { workingConfig[loadedScheme] = savedConfig[loadedScheme]; paletteGrid->loadPalette(savedConfig[loadedScheme]); + fontGrid->loadFonts(savedFontConfig); seedAccentFromScheme(loadedScheme); } @@ -351,6 +427,18 @@ void PaletteEditorDialog::onRevertToDefault() workingConfig[loadedScheme] = def; paletteGrid->loadPalette(def); seedAccentFromScheme(loadedScheme); + + // Revert the shared per-theme fonts the same way: delete the user-written + // fonts.toml so the theme falls back to its shipped default, then reflect + // the resolved fonts in the editor. + QFile::remove(QDir(saveDir).absoluteFilePath(FontConfig::fileName())); + + // Reload the live theme so the font revert takes effect immediately. + themeManager->reloadCurrentTheme(); + + const FontConfig fontDef = ThemeManager::loadDefaultFontConfig(themeDirPath, themeName); + savedFontConfig = fontDef; + fontGrid->loadFonts(fontDef); } void PaletteEditorDialog::changeEvent(QEvent *e) diff --git a/cockatrice/src/interface/palette_editor/palette_editor_dialog.h b/cockatrice/src/interface/palette_editor/palette_editor_dialog.h index e29a70cb0..0a9d47c6c 100644 --- a/cockatrice/src/interface/palette_editor/palette_editor_dialog.h +++ b/cockatrice/src/interface/palette_editor/palette_editor_dialog.h @@ -15,6 +15,7 @@ class QComboBox; class QDialogButtonBox; class QPushButton; class PaletteGridWidget; +class FontGridWidget; class QuickSetupPanel; class QFrame; class QWidget; @@ -38,8 +39,10 @@ private: void setupUi(); void retranslateUi(); void refreshChromePalettes(); + void updateAdvancedHeight(); void loadScheme(const QString &scheme); // snapshot current, switch, load void seedAccentFromScheme(const QString &scheme); + void loadFonts(); // shared per theme, not split by light/dark // Sub-widgets QWidget *header; @@ -49,6 +52,11 @@ private: PaletteGridWidget *paletteGrid = nullptr; QPushButton *paletteGridToggleButton = nullptr; QFrame *paletteGridSeparator = nullptr; + FontGridWidget *fontGrid = nullptr; + QPushButton *fontToggleButton = nullptr; + QFrame *fontSeparator = nullptr; + QWidget *fontSection = nullptr; + QLabel *fontNoteLabel = nullptr; QWidget *footer; QComboBox *schemeComboBox = nullptr; QDialogButtonBox *buttonBox = nullptr; @@ -68,6 +76,10 @@ private: QMap workingConfig; QMap savedConfig; + // 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. + FontConfig savedFontConfig; + QTimer *autoApplyTimer = nullptr; protected: diff --git a/cockatrice/src/interface/theme_manager.cpp b/cockatrice/src/interface/theme_manager.cpp index f24be4437..f9d5a67c4 100644 --- a/cockatrice/src/interface/theme_manager.cpp +++ b/cockatrice/src/interface/theme_manager.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,8 @@ ThemeManager::ThemeManager(QObject *parent) : QObject(parent) defaultStyleName = usableDefaultStyle(qApp->style()->objectName()); // Capture the untouched application palette 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)) connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, [this] { @@ -448,6 +451,18 @@ FontConfig ThemeManager::loadFontConfig(const QString &themeDirPath) return FontConfig::fromThemeDir(themeDirPath); } +FontConfig ThemeManager::loadDefaultFontConfig(const QString &themeDirPath, const QString &themeName) +{ + FontConfig cfg = FontConfig::fromThemeDir(themeDirPath); + if (!cfg.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. + cfg = FontConfig::fromThemeDir(QDir(systemThemesBasePath()).absoluteFilePath(themeName)); + } + return cfg; +} + bool ThemeManager::saveFontConfig(const QString &themeDirPath, const FontConfig &cfg) { if (themeDirPath.isEmpty()) { @@ -644,8 +659,24 @@ QFont ThemeManager::appFont(AppFont::Role role) const return it.value(); } - // No per-role scaling: every unset role resolves to the application font, - // so with no fonts.toml present the result is identical to before. + // Role fallbacks preserve the pre-theme defaults when no fonts.toml is + // 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; + } + if (role == AppFont::CardText) { + return QFont(QStringLiteral("Serif")); + } + + // No per-role scaling: every other unset role resolves to the application + // font, so with no fonts.toml present the result is identical to before. return qApp->font(); } @@ -715,6 +746,10 @@ void ThemeManager::themeChangedSlot() const auto fontIt = currentFonts.fonts.constFind(AppFont::InterfaceDefault); if (fontIt != currentFonts.fonts.constEnd()) { qApp->setFont(fontIt.value()); + } else { + // No theme font: restore the pristine application font captured at + // startup, so a reverted preview cannot leak into the live theme. + qApp->setFont(defaultFont); } emit fontsChanged(); diff --git a/cockatrice/src/interface/theme_manager.h b/cockatrice/src/interface/theme_manager.h index d59212e92..8a0e6919b 100644 --- a/cockatrice/src/interface/theme_manager.h +++ b/cockatrice/src/interface/theme_manager.h @@ -48,6 +48,10 @@ private: // palette is applied. Used as the base when a theme supplies no palette, so // 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. + QFont defaultFont; QString currentThemePath; std::array brushes; QStringMap availableThemes; @@ -128,6 +132,9 @@ public: // theme directory when it is absent from the resolved (user) directory. static PaletteConfig loadDefaultPaletteConfig(const QString &themeDirPath, const QString &themeName, const QString &colorScheme); + // Load the theme's shipped default fonts, falling back to the system theme + // directory when fonts.toml is absent from the resolved (user) directory. + static FontConfig loadDefaultFontConfig(const QString &themeDirPath, const QString &themeName); /** @brief Writes cfg to disk as the theme's palette-.toml and updates the * theme's stored colour scheme to match. Shared by PaletteEditorDialog::onSave * and FirstRunWizard's theme step so the two "generate + keep" paths can't drift. */ @@ -143,7 +150,9 @@ public: // when present, otherwise a palette-accent-derived fallback. QColor appColor(AppColor::Role role) const; /** @brief Resolves an application font role: the theme's stored [Fonts] - * value when present, otherwise the application font. */ + * value when present, otherwise a per-role fallback (monospace for + * ChatLog, serif basis for CardText, the application font for the + * remaining roles). */ QFont appFont(AppFont::Role role) const; QBrush &getBgBrush(Role zone); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp index 52c9eaef0..a259b6a56 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp @@ -1,5 +1,6 @@ #include "dlg_my_reports.h" +#include "../interface/theme_manager.h" #include "../utility/report_utils.h" #include "abstract_client.h" #include "libcockatrice/protocol/pb/response.pb.h" @@ -70,13 +71,8 @@ DlgMyReports::DlgMyReports(AbstractClient *_client, QWidget *parent) auto *chatGroup = new QGroupBox(tr("Chat Log Context")); chatLogEdit = new QTextEdit; chatLogEdit->setReadOnly(true); - QFont monoFont("monospace"); - monoFont.setStyleHint(QFont::Monospace); - const int systemPointSize = QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize(); - if (systemPointSize > 0) { - monoFont.setPointSize(systemPointSize); - } - chatLogEdit->setFont(monoFont); + applyChatLogFont(); + connect(themeManager, &ThemeManager::fontsChanged, this, &DlgMyReports::applyChatLogFont); auto *chatLayout = new QVBoxLayout(chatGroup); chatLayout->setContentsMargins(4, 4, 4, 4); chatLayout->addWidget(chatLogEdit); @@ -129,6 +125,18 @@ DlgMyReports::DlgMyReports(AbstractClient *_client, QWidget *parent) refreshList(); } +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); +} + void DlgMyReports::refreshList() { selectedReportIdBeforeRefresh = selectedReportId; diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.h b/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.h index dc9f90d2d..90772f051 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.h @@ -29,6 +29,7 @@ private slots: void reportDetailsResponse(const Response &response); void addComment(); void addCommentResponse(const Response &response); + void applyChatLogFont(); private: void loadReportDetails(const ServerInfo_Report &report); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_report_user.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_report_user.cpp index b1ae479fe..5cdeb22a1 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_report_user.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_report_user.cpp @@ -1,5 +1,6 @@ #include "dlg_report_user.h" +#include "../interface/theme_manager.h" #include "abstract_client.h" #include "libcockatrice/protocol/pb/response.pb.h" @@ -92,13 +93,8 @@ DlgReportUser::DlgReportUser(AbstractClient *_client, auto *chatLayout = new QVBoxLayout(chatGroup); chatLogEdit = new QTextEdit; chatLogEdit->setReadOnly(true); - QFont monoFont("monospace"); - monoFont.setStyleHint(QFont::Monospace); - const int systemPointSize = QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize(); - if (systemPointSize > 0) { - monoFont.setPointSize(systemPointSize); - } - chatLogEdit->setFont(monoFont); + applyChatLogFont(); + connect(themeManager, &ThemeManager::fontsChanged, this, &DlgReportUser::applyChatLogFont); if (!_autoChatLog.isEmpty()) { chatLogEdit->setPlainText(_autoChatLog); } else { @@ -127,6 +123,18 @@ DlgReportUser::DlgReportUser(AbstractClient *_client, layout->addWidget(buttonBox); } +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); +} + void DlgReportUser::actSubmit() { const QString description = descriptionEdit->toPlainText().trimmed(); diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_report_user.h b/cockatrice/src/interface/widgets/dialogs/dlg_report_user.h index c7fce055d..0f2fa5080 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_report_user.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_report_user.h @@ -27,6 +27,7 @@ public: private slots: void actSubmit(); void reportResponse(const Response &response); + void applyChatLogFont(); private: static QString categoryLabel(const QString &key); diff --git a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp index 037a4a1e5..c57f65352 100644 --- a/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp +++ b/cockatrice/src/interface/widgets/server/chat_view/chat_view.cpp @@ -4,6 +4,7 @@ #include "../../client/sound_engine.h" #include "../../interface/card_localization.h" #include "../../interface/pixel_map_generator.h" +#include "../../interface/theme_manager.h" #include "../../tabs/tab_supervisor.h" #include "../user/user_context_menu.h" #include "../user/user_list_manager.h" @@ -63,6 +64,9 @@ ChatView::ChatView(TabSupervisor *_tabSupervisor, AbstractGame *_game, bool _sho connect(&SettingsCache::instance(), &SettingsCache::themeChanged, this, &ChatView::adjustColorsToPalette); + applyChatFont(); + connect(themeManager, &ThemeManager::fontsChanged, this, &ChatView::applyChatFont); + userContextMenu = new UserContextMenu(tabSupervisor, this, game); connect(userContextMenu, SIGNAL(openMessageDialog(QString, bool)), this, SIGNAL(openMessageDialog(QString, bool))); @@ -108,6 +112,16 @@ void ChatView::adjustColorsToPalette() QTimer::singleShot(0, this, &ChatView::refreshBlockColors); } +void ChatView::applyChatFont() +{ + // Family comes from the ChatLog theme role; the message char formats carry + // no family of their own, so they (and new content) follow the widget and + // document default fonts. Weights/italics stay caller-side as before. + const QFont chatFont = themeManager->appFont(AppFont::ChatLog); + setFont(chatFont); + document()->setDefaultFont(chatFont); +} + void ChatView::refreshBlockColors() { QTextDocument *doc = document(); diff --git a/cockatrice/src/interface/widgets/server/chat_view/chat_view.h b/cockatrice/src/interface/widgets/server/chat_view/chat_view.h index 3fa7224e5..a2e2f33dd 100644 --- a/cockatrice/src/interface/widgets/server/chat_view/chat_view.h +++ b/cockatrice/src/interface/widgets/server/chat_view/chat_view.h @@ -111,6 +111,7 @@ private slots: void openLink(const QUrl &link); void actMessageClicked(); void adjustColorsToPalette(); + void applyChatFont(); void refreshBlockColors(); void onScrollBarRangeChanged(); void onScrollBarValueChanged(int value); diff --git a/cockatrice/src/interface/widgets/tabs/tab_report.cpp b/cockatrice/src/interface/widgets/tabs/tab_report.cpp index 9018e2477..bcb6e7191 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_report.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_report.cpp @@ -1,5 +1,6 @@ #include "tab_report.h" +#include "../interface/theme_manager.h" #include "../server/user/user_context_menu.h" #include "../utility/report_utils.h" #include "abstract_client.h" @@ -138,13 +139,8 @@ TabReport::TabReport(TabSupervisor *_tabSupervisor, AbstractClient *_client) : T chatGroup = new QGroupBox; chatLogEdit = new QTextEdit; chatLogEdit->setReadOnly(true); - QFont monoFont("monospace"); - monoFont.setStyleHint(QFont::Monospace); - const int systemPointSize = QFontDatabase::systemFont(QFontDatabase::GeneralFont).pointSize(); - if (systemPointSize > 0) { - monoFont.setPointSize(systemPointSize); - } - chatLogEdit->setFont(monoFont); + applyChatLogFont(); + connect(themeManager, &ThemeManager::fontsChanged, this, &TabReport::applyChatLogFont); auto *chatLayout = new QVBoxLayout(chatGroup); chatLayout->setContentsMargins(4, 4, 4, 4); chatLayout->addWidget(chatLogEdit); @@ -277,6 +273,18 @@ TabReport::TabReport(TabSupervisor *_tabSupervisor, AbstractClient *_client) : T refreshList(); } +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); +} + void TabReport::retranslateUi() { userContextMenu->retranslateUi(); diff --git a/cockatrice/src/interface/widgets/tabs/tab_report.h b/cockatrice/src/interface/widgets/tabs/tab_report.h index 32ebe1a3f..43e778f4b 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_report.h +++ b/cockatrice/src/interface/widgets/tabs/tab_report.h @@ -62,6 +62,7 @@ private slots: void statsResponse(const Response &response); void reopenReport(); void reopenResponse(const Response &response); + void applyChatLogFont(); private: int selectedReportId() const;