Compare commits

...

9 commits

Author SHA1 Message Date
Lukas Brübach
42895e92a3 [Fonts] Fix font preview leaks and reuse default-font loader 2026-11-02 10:29:11 +01:00
Lukas Brübach
e834339c71 [Fonts] Fix pixel sizes and game overlay fonts from review
- Set the sizes the stylesheets carried with setPixelSize() rather than
  setPointSize(): home buttons (34), banner (24), home group box (20),
  the placeholder labels (14), the analytics drag handle (10), the EDHREC
  navigation buttons (24), the user info popup (11/14/11/10/11) and the
  game overlays (14/16/12). Points at 96 DPI were ~33% larger.
- The drag/total counters and tally columns keep the monospace family the
  stylesheets set, so digit widths stop changing as counts tick and
  white-space: pre stays aligned.
- applyDeckListFont() drops the cached tally rows before re-measuring, so
  previewing a larger DeckList font no longer leaves the tally clipped.
- Tally labels and the constructor/fontsChanged pairs in the shared-deck
  preview, quick setup, analytics panel, home box and public decks build
  their font once in a local lambda instead of twice.
2026-11-02 10:28:01 +01:00
Lukas Brübach
70f0f14665 [Fonts] Drop unused lambda captures in font-refresh handlers 2026-11-02 10:28:01 +01:00
Lukas Brübach
e23efebd71 [Fonts] Migrate DeckList and InterfaceDefault surfaces to theme roles 2026-11-02 10:28:01 +01:00
Lukas Brübach
7b3d43c4ea [Fonts] Keep CardText call sites on the app font and fix px sizes
- CardText's unset fallback is qApp->font() again: only the three counter
  painters (paintNumberEllipse, GeneralCounter, PlayerCounter) were Serif
  before the role existed, and they now ask for it through
  ThemeManager::cardTextFont(). Card names, player names, counters, the
  overlay, the Archidekt and EDHREC labels and the completer delegate keep the
  app font they used before.
- Use setPixelSize for the EDHREC card name (20px) and commander name (28px)
  and details (16px) sizes: the stylesheets said px, and setPointSize made
  them about a third larger.
2026-11-02 10:27:43 +01:00
Lukas Brübach
0ff2c4e246 [Fonts] Migrate CardText surfaces to theme font role 2026-11-02 10:27:15 +01:00
Lukas Brübach
bbf055c483 [Fonts] Keep ChatView on the app font and share the report log font
- ChatLog's unset fallback is qApp->font() again: ChatView never set a font
  before the role existed, so an unset role must not switch chat and the game
  log to monospace at the system GeneralFont size.
- Move the monospace fallback the report dialogs used before into
  report_utils::reportLogFont(), which returns the theme's ChatLog role when it
  is set and the old monospace otherwise. tab_report, dlg_my_reports and
  dlg_report_user now share it, so they cannot drift and they honour a themed
  size instead of overriding it.
2026-11-02 10:26:15 +01:00
Lukas Brübach
eeb5cfc333 [Fonts] Migrate ChatLog surfaces to theme font role 2026-11-02 10:26:15 +01:00
Lukas Brübach
7472f69f01 [Fonts] Make the editor's fallback and Reset preview-independent
- Add ThemeManager::defaultAppFont(), which resolves an unset role against the
  startup font instead of currentFonts, and use it in FontGridWidget::loadFonts
  so the grid never shows the live preview as the theme's default.
- Reload the live theme in PaletteEditorDialog::onReset before re-reading the
  grid, so Reset restores the saved fonts before loadFonts resolves fallbacks.
2026-11-02 10:26:05 +01:00
77 changed files with 671 additions and 168 deletions

View file

@ -1,5 +1,6 @@
#include "shortcut_treeview.h"
#include "../../interface/theme_manager.h"
#include "cache_settings.h"
#include "shortcuts_settings.h"
@ -93,7 +94,8 @@ void ShortcutTreeView::populateShortcutsModel()
curParent = parentItems.value(group);
} else {
curParent = new QStandardItem(group);
static QFont font = curParent->font();
// Family comes from the InterfaceDefault theme role; bold stays caller-side.
QFont font = themeManager->appFont(AppFont::InterfaceDefault);
font.setBold(true);
curParent->setFont(font);
parentItems.insert(group, curParent);

View file

@ -1,5 +1,7 @@
#include "filter_tree_model.h"
#include "../interface/theme_manager.h"
#include <QFlags>
#include <QFont>
#include <QString>
@ -196,7 +198,8 @@ QVariant FilterTreeModel::data(const QModelIndex &index, int role) const
switch (role) {
case Qt::FontRole:
if (!node->isLeaf()) {
QFont f;
// Family comes from the DeckList theme role; bold stays caller-side.
QFont f = themeManager->appFont(AppFont::DeckList);
f.setBold(true);
return f;
}

View file

@ -3,6 +3,7 @@
#include "../../client/settings/cache_settings.h"
#include "../../interface/card_localization.h"
#include "../../interface/card_picture_loader/card_picture_loader.h"
#include "../../interface/theme_manager.h"
#include "../card_dimensions.h"
#include "../game_scene.h"
#include "../z_values.h"
@ -146,7 +147,7 @@ void AbstractCardItem::transformPainter(QPainter *painter, const QSizeF &transla
painter->rotate(angle);
painter->translate(-translatedSize.width() / 2, -translatedSize.height() / 2);
QFont f;
QFont f = themeManager->appFont(AppFont::CardText);
f.setPixelSize(fontSize * scale);
painter->setFont(f);

View file

@ -1,5 +1,7 @@
#include "abstract_graphics_item.h"
#include "../../interface/theme_manager.h"
#include <QBrush>
#include <QFont>
#include <QFontMetrics>
@ -20,7 +22,7 @@ void AbstractGraphicsItem::paintNumberEllipse(int number,
painter->save();
QString numStr = QString::number(number);
QFont font("Serif");
QFont font = themeManager->cardTextFont();
font.setPixelSize(fontSize);
font.setWeight(QFont::Bold);

View file

@ -1,6 +1,7 @@
#include "counter_general.h"
#include "../../interface/pixel_map_generator.h"
#include "../../interface/theme_manager.h"
#include "abstract_graphics_item.h"
#include <QFont>
@ -41,7 +42,7 @@ void GeneralCounter::paint(QPainter *painter, const QStyleOptionGraphicsItem * /
painter->drawPixmap(QPoint(0, 0), pixmap);
if (value) {
QFont f("Serif");
QFont f = themeManager->cardTextFont();
f.setPixelSize(qMax((int)(radius * scaleFactor), 10));
f.setWeight(QFont::Bold);
painter->setPen(Qt::black);

View file

@ -240,7 +240,8 @@ void DeckViewCardContainer::paint(QPainter *painter, const QStyleOptionGraphicsI
painter->drawLine(QPointF(0, separatorY), QPointF(width, separatorY));
painter->setPen(QColor(Qt::white));
QFont f("Serif");
// Family comes from the DeckList theme role; pixel sizes/weights unchanged.
QFont f = themeManager->appFont(AppFont::DeckList);
f.setStyleHint(QFont::Serif);
f.setPixelSize(24);
f.setWeight(QFont::Bold);
@ -292,7 +293,8 @@ QList<QPair<int, int>> DeckViewCardContainer::getRowsAndCols() const
int DeckViewCardContainer::getCardTypeTextWidth() const
{
QFont f("Serif");
// Family comes from the DeckList theme role; pixel size/weight unchanged.
QFont f = themeManager->appFont(AppFont::DeckList);
f.setStyleHint(QFont::Serif);
f.setPixelSize(16);
f.setWeight(QFont::Bold);

View file

@ -2,12 +2,14 @@
#include "../client/settings/cache_settings.h"
#include "../client/settings/shortcuts_settings.h"
#include "../interface/theme_manager.h"
#include "game_scene.h"
#include <QAction>
#include <QBrush>
#include <QColor>
#include <QEvent>
#include <QFont>
#include <QGraphicsScene>
#include <QGridLayout>
#include <QLabel>
@ -24,6 +26,21 @@
#include <libcockatrice/utility/qt_utils.h>
#include <qnamespace.h>
namespace
{
QFont deckOverlayFont(int pixelSize, bool bold)
{
// The drag/total counters and the tally columns are in-game overlays, not
// deck list text: keep the monospace family the stylesheets used to set so
// digit widths stay stable as counts tick and `white-space: pre` lines up.
QFont font(QStringLiteral("monospace"));
font.setStyleHint(QFont::Monospace);
font.setPixelSize(pixelSize);
font.setBold(bold);
return font;
}
} // namespace
// QRubberBand calls raise() in showEvent() and changeEvent() to stay on top of siblings.
// This subclass disables that behavior so dragCountLabel can appear above it.
class SelectionRubberBand : public QRubberBand
@ -75,15 +92,14 @@ GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, par
rubberBand = new SelectionRubberBand(QRubberBand::Rectangle, this);
const QString baseProperties = "color: white; "
"font-family: monospace; "
"background-color: rgba(0, 0, 0, 160); "
"border-radius: 3px; "
"padding: 1px 2px; "
"white-space: pre;";
const QString dragCountLabelStyle = baseProperties + "font-size: 14px; font-weight: bold;";
const QString totalCountLabelStyle = baseProperties + "font-size: 16px; font-weight: bold;";
const QString subtypeTallyLabelStyle = baseProperties + "font-size: 12px;";
const QString dragCountLabelStyle = baseProperties;
const QString totalCountLabelStyle = baseProperties;
const QString subtypeTallyLabelStyle = baseProperties;
dragCountLabel = new QLabel(this);
dragCountLabel->setStyleSheet(dragCountLabelStyle);
@ -100,6 +116,27 @@ GameView::GameView(GameScene *scene, QWidget *parent) : QGraphicsView(scene, par
tallyLayout->setContentsMargins(2, 2, 2, 2);
tallyLayout->setSpacing(2);
tallyContainer->hide();
applyDeckOverlayFonts();
}
void GameView::applyDeckOverlayFonts()
{
dragCountLabel->setFont(deckOverlayFont(14, true));
totalCountLabel->setFont(deckOverlayFont(16, true));
tallyContainer->setFont(deckOverlayFont(12, false));
for (int i = 0; i < tallyLayout->count(); ++i) {
if (auto *label = qobject_cast<QLabel *>(tallyLayout->itemAt(i)->widget())) {
// Count column (odd positions) keeps the bold emphasis.
const bool count = i % 2 == 1;
label->setFont(deckOverlayFont(count ? 14 : 12, count));
}
}
// The container keeps the size computed from the previous fonts, so force
// rebuildTallyLabels() to re-measure it instead of reusing cachedTallyRows.
cachedTallyRows.clear();
updateTotalSelectionCount();
}
void GameView::resizeEvent(QResizeEvent *event)
@ -219,9 +256,8 @@ QSize GameView::rebuildTallyLabels(const QList<TallyRow> &entries)
{
clearTallyLabels();
const QString nameStyle = QStringLiteral("color: white; font-size: 12px; background: transparent;");
const QString countStyle =
QStringLiteral("color: white; font-size: 14px; font-weight: bold; background: transparent;");
const QString nameStyle = QStringLiteral("color: white; background: transparent;");
const QString countStyle = QStringLiteral("color: white; background: transparent;");
int totalHeight = 0;
int maxNameWidth = 0;
@ -231,11 +267,13 @@ QSize GameView::rebuildTallyLabels(const QList<TallyRow> &entries)
for (const TallyRow &entry : entries) {
auto *nameLabel = new QLabel(entry.name, tallyContainer);
nameLabel->setStyleSheet(nameStyle);
nameLabel->setFont(deckOverlayFont(12, false));
nameLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
tallyLayout->addWidget(nameLabel, row, 0);
auto *countLabel = new QLabel(entry.value, tallyContainer);
countLabel->setStyleSheet(countStyle);
countLabel->setFont(deckOverlayFont(14, true));
countLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
tallyLayout->addWidget(countLabel, row, 1);

View file

@ -50,6 +50,7 @@ private slots:
void refreshShortcuts();
void updateTotalSelectionCount(const QSize &viewSize = QSize());
void setFocusDisabled(bool disabled);
void applyDeckOverlayFonts();
public slots:
void updateSceneRect(const QRectF &rect);

View file

@ -4,6 +4,7 @@
#include "../../game/player/player_info.h"
#include "../../game/player/player_logic.h"
#include "../../interface/pixel_map_generator.h"
#include "../../interface/theme_manager.h"
#include "../board/abstract_counter.h"
#include "../board/abstract_graphics_item.h"
#include "../board/arrow_target.h"
@ -76,7 +77,7 @@ void PlayerCounter::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*
QRectF translatedRect = path.controlPointRect();
QSize translatedSize = translatedRect.size().toSize();
QFont font("Serif");
QFont font = themeManager->cardTextFont();
font.setWeight(QFont::Bold);
font.setPixelSize(qMax(qRound(translatedSize.height() / 1.3), 9));
painter->setFont(font);
@ -226,7 +227,7 @@ void PlayerTarget::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*o
name = name.mid(0, 10) + "...";
}
QFont font;
QFont font = themeManager->appFont(AppFont::CardText);
font.setPixelSize(qMax(qRound(translatedNameRect.height() / 1.5), 9));
painter->setFont(font);
painter->setPen(Qt::white);

View file

@ -1,5 +1,6 @@
#include "deck_loader.h"
#include "../theme_manager.h"
#include "libcockatrice/card/card_info.h"
#include "libcockatrice/card/database/card_database_querier.h"
#include "libcockatrice/deck_list/tree/abstract_deck_list_card_node.h"
@ -579,6 +580,8 @@ void DeckLoader::printDeckListNode(QTextCursor *cursor, const InnerDecklistNode
if (!cards.isEmpty()) {
QTextBlockFormat blockFormat;
QTextCharFormat charFormat;
// Family comes from the DeckList theme role; sizes/weights unchanged.
charFormat.setFontFamilies({themeManager->appFont(AppFont::DeckList).family()});
charFormat.setFontPointSize(11);
charFormat.setFontWeight(QFont::Bold);
cursor->insertBlock(blockFormat, charFormat);
@ -592,6 +595,7 @@ void DeckLoader::printDeckListNode(QTextCursor *cursor, const InnerDecklistNode
const AbstractDecklistCardNode *card = cards[i];
QTextCharFormat cellCharFormat;
cellCharFormat.setFontFamilies({themeManager->appFont(AppFont::DeckList).family()});
cellCharFormat.setFontPointSize(9);
QTextTableCell cell = table->cellAt(i, 0);
@ -613,6 +617,7 @@ void DeckLoader::printDeckListNode(QTextCursor *cursor, const InnerDecklistNode
QTextBlockFormat blockFormat;
QTextCharFormat charFormat;
charFormat.setFontFamilies({themeManager->appFont(AppFont::DeckList).family()});
charFormat.setFontPointSize(14);
charFormat.setFontWeight(QFont::Bold);
@ -640,7 +645,8 @@ void DeckLoader::printDeckList(QPrinter *printer, const DeckList &deckList)
{
QTextDocument doc;
QFont font("Serif");
// Family comes from the DeckList theme role; the print sizes/weights below stay unchanged.
QFont font = themeManager->appFont(AppFont::DeckList);
font.setStyleHint(QFont::Serif);
doc.setDefaultFont(font);
@ -648,6 +654,7 @@ void DeckLoader::printDeckList(QPrinter *printer, const DeckList &deckList)
QTextBlockFormat headerBlockFormat;
QTextCharFormat headerCharFormat;
headerCharFormat.setFontFamilies({themeManager->appFont(AppFont::DeckList).family()});
headerCharFormat.setFontPointSize(16);
headerCharFormat.setFontWeight(QFont::Bold);

View file

@ -1,5 +1,7 @@
#include "color_button.h"
#include "../theme_manager.h"
#include <QBrush>
#include <QColorDialog>
#include <QFont>
@ -21,6 +23,7 @@ ColorButton::ColorButton(QWidget *parent) : QToolButton(parent)
setCursor(Qt::PointingHandCursor);
setToolTip(tr("Click to pick a color"));
connect(this, &QToolButton::clicked, this, &ColorButton::pickColor);
connect(themeManager, &ThemeManager::fontsChanged, this, &ColorButton::updateSwatch);
}
void ColorButton::setColor(const QColor &c)
@ -73,7 +76,8 @@ void ColorButton::updateSwatch()
// Hex label — black or white for contrast
int luma = 0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue();
painter.setPen((luma > 128 && color.alpha() > 80) ? QColor(0, 0, 0, 180) : QColor(255, 255, 255, 200));
QFont f = font();
// Family comes from the InterfaceDefault theme role; the 8px size stays caller-side.
QFont f = themeManager->appFont(AppFont::InterfaceDefault);
f.setPixelSize(8);
painter.setFont(f);
painter.drawText(rect(), Qt::AlignCenter, color.name().toUpper());

View file

@ -71,14 +71,20 @@ FontGridWidget::FontGridWidget(QWidget *parent) : QWidget(parent)
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>();
for (int i = 0; i < fontEnum.keyCount(); ++i) {
auto role = static_cast<AppFont::Role>(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 the same way the runtime does: an unset
// role falls back to the config's InterfaceDefault, and only then to the
// startup font. appFont() would return the live preview instead, so Reset and
// a first load must not measure against it.
const QFont fallback = cfg.fonts.value(AppFont::InterfaceDefault, themeManager->defaultAppFont(role));
const QFont font = cfg.fonts.value(role, fallback);
row.familyCombo->setCurrentFont(font);
int size = font.pointSize();
@ -90,6 +96,7 @@ void FontGridWidget::loadFonts(const FontConfig &cfg)
}
row.sizeSpin->setValue(qBound(MIN_FONT_SIZE, size, MAX_FONT_SIZE));
}
blockSignals(false);
}
FontConfig FontGridWidget::currentFontConfig() const

View file

@ -186,7 +186,10 @@ 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(fontGrid, &FontGridWidget::fontsChanged, this, [this] {
fontsDirty = true;
autoApplyTimer->start();
});
connect(revertButton, &QPushButton::clicked, this, &PaletteEditorDialog::onRevertToDefault);
connect(resetBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onReset);
connect(saveBtn, &QPushButton::clicked, this, &PaletteEditorDialog::onSave);
@ -281,15 +284,9 @@ 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);
savedFontConfig = ThemeManager::loadDefaultFontConfig(themeDirPath, themeName);
fontGrid->loadFonts(savedFontConfig);
fontsDirty = false;
}
void PaletteEditorDialog::seedAccentFromScheme(const QString &scheme)
@ -322,7 +319,9 @@ void PaletteEditorDialog::onGenerateFromAccent(const QColor &accent, int intensi
void PaletteEditorDialog::onApply()
{
themeManager->previewPalette(paletteGrid->currentPaletteConfig(), loadedScheme);
themeManager->previewFonts(fontGrid->currentFontConfig());
if (fontsDirty) {
themeManager->previewFonts(fontGrid->currentFontConfig());
}
}
void PaletteEditorDialog::onSave()
@ -374,14 +373,17 @@ void PaletteEditorDialog::onSave()
}
// 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;
if (fontsDirty) {
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;
}
savedFontConfig = fontCfg;
fontsDirty = false;
}
themeManager->reloadCurrentTheme();
@ -392,7 +394,12 @@ 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);
fontsDirty = false;
seedAccentFromScheme(loadedScheme);
}
@ -439,6 +446,15 @@ void PaletteEditorDialog::onRevertToDefault()
const FontConfig fontDef = ThemeManager::loadDefaultFontConfig(themeDirPath, themeName);
savedFontConfig = 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)

View file

@ -26,6 +26,7 @@ class PaletteEditorDialog : public QDialog
public:
explicit PaletteEditorDialog(const QString &themeDirPath, const QString &themeName, QWidget *parent = nullptr);
void loadSchemes();
void reject() override;
private slots:
void onSave();
@ -79,6 +80,10 @@ private:
// 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;
// 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;
@ -86,4 +91,4 @@ protected:
void changeEvent(QEvent *e) override;
};
#endif // COCKATRICE_PALETTE_EDITOR_DIALOG_H
#endif // COCKATRICE_PALETTE_EDITOR_DIALOG_H

View file

@ -77,6 +77,18 @@ PaletteGridWidget::PaletteGridWidget(QWidget *parent) : QWidget(parent)
layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(scroll);
connect(themeManager, &ThemeManager::fontsChanged, this, &PaletteGridWidget::applyInterfaceDefaultFont);
}
void PaletteGridWidget::applyInterfaceDefaultFont()
{
// The editor's own chrome follows the InterfaceDefault theme role; bold stays caller-side.
for (auto *label : headerLabels) {
QFont headerFont = themeManager->appFont(AppFont::InterfaceDefault);
headerFont.setBold(true);
label->setFont(headerFont);
}
}
void PaletteGridWidget::buildGrid(QWidget *host)
@ -102,7 +114,8 @@ void PaletteGridWidget::buildGrid(QWidget *host)
auto *label = new QLabel(groupHeaders[col], host);
label->setAlignment(Qt::AlignCenter);
label->setToolTip(groupTips[col]);
QFont f = label->font();
// Family comes from the InterfaceDefault theme role; bold stays caller-side.
QFont f = themeManager->appFont(AppFont::InterfaceDefault);
f.setBold(true);
label->setFont(f);
label->setAutoFillBackground(true);
@ -149,7 +162,7 @@ void PaletteGridWidget::buildGrid(QWidget *host)
auto *appHeader = new QLabel(tr("App colors"), host);
appHeader->setToolTip(tr("Application-specific colors layered on top of the Qt palette"));
QFont appHeaderFont = appHeader->font();
QFont appHeaderFont = themeManager->appFont(AppFont::InterfaceDefault);
appHeaderFont.setBold(true);
appHeader->setFont(appHeaderFont);
appHeader->setAutoFillBackground(true);

View file

@ -34,6 +34,10 @@ private:
void changeEvent(QEvent *e);
void refreshChromePalettes();
private slots:
void applyInterfaceDefaultFont();
private:
QMap<QPalette::ColorGroup, QMap<QPalette::ColorRole, ColorButton *>> colorButtons;
QMap<AppColor::Role, ColorButton *> appColorButtons;
QScrollArea *scroll;

View file

@ -1,5 +1,6 @@
#include "quick_setup_panel.h"
#include "../theme_manager.h"
#include "color_button.h"
#include <QApplication>
@ -28,10 +29,15 @@ QuickSetupPanel::QuickSetupPanel(QWidget *parent) : QWidget(parent)
labelLow = new QLabel(this);
labelHigh = new QLabel(this);
QFont small = labelLow->font();
small.setPointSizeF(small.pointSizeF() * 0.82);
labelLow->setFont(small);
labelHigh->setFont(small);
// Family comes from the InterfaceDefault theme role; the *0.82 size stays caller-side.
auto applySmallFont = [this]() {
QFont small = themeManager->appFont(AppFont::InterfaceDefault);
small.setPointSizeF(small.pointSizeF() * 0.82);
labelLow->setFont(small);
labelHigh->setFont(small);
};
applySmallFont();
connect(themeManager, &ThemeManager::fontsChanged, this, applySmallFont);
QPalette dimmed = labelLow->palette();
dimmed.setColor(QPalette::WindowText, qApp->palette().color(QPalette::Mid));
labelLow->setPalette(dimmed);

View file

@ -12,6 +12,7 @@
#include <QFile>
#include <QFileInfo>
#include <QFlags>
#include <QFontDatabase>
#include <QGuiApplication>
#include <QIODevice>
#include <QLatin1Char>
@ -655,11 +656,37 @@ 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: an unset role resolves to the application font, so the result is
// identical to before. The report dialogs that used to hardcode monospace
// ask for it explicitly (report_utils::reportLogFont), and the counter
// painters that used to hardcode Serif ask for it through cardTextFont().
return qApp->font();
}
bool ThemeManager::hasAppFont(AppFont::Role role) const
{
return currentFonts.fonts.contains(role);
}
QFont ThemeManager::cardTextFont() const
{
if (hasAppFont(AppFont::CardText)) {
return appFont(AppFont::CardText);
}
QFont serifFont(QStringLiteral("Serif"));
serifFont.setStyleHint(QFont::Serif);
return serifFont;
}
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();
@ -712,16 +739,7 @@ void ThemeManager::themeChangedSlot()
applyStyleAndPalette(themeName, themeCfg, palette, activeScheme);
// ── Load fonts: shared per theme, no light/dark split ───────────────────
FontConfig fonts = loadFontConfig(dirPath);
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);
}
}
FontConfig fonts = loadDefaultFontConfig(dirPath, themeName);
currentFonts = fonts;
const auto fontIt = currentFonts.fonts.constFind(AppFont::InterfaceDefault);
if (fontIt != currentFonts.fonts.constEnd()) {

View file

@ -150,8 +150,19 @@ 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 (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 The CardText role with its historical Serif fallback. Used by the
* counter painters, which were Serif before the role existed. */
QFont cardTextFont() 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);

View file

@ -1,5 +1,6 @@
#include "art_crop_attribution.h"
#include "../../theme_manager.h"
#include "libcockatrice/card/printing/printing_info.h"
#include <QColor>
@ -35,7 +36,10 @@ QRectF paintArtAttribution(QPainter &painter,
painter.save();
// Family comes from the CardText theme role; the incoming painter size
// stays the basis for the scale factor exactly as before.
QFont font = painter.font();
font.setFamily(themeManager->appFont(AppFont::CardText).family());
font.setPointSizeF(qMax(6.0, font.pointSizeF() * scale));
painter.setFont(font);

View file

@ -1,5 +1,7 @@
#include "card_info_picture_with_text_overlay_widget.h"
#include "../../theme_manager.h"
#include <QBrush>
#include <QChar>
#include <QFont>
@ -43,6 +45,7 @@ CardInfoPictureWithTextOverlayWidget::CardInfoPictureWithTextOverlayWidget(QWidg
fontSize(fontSize), textAlignment(alignment), highlighted(false)
{
this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
connect(themeManager, &ThemeManager::fontsChanged, this, &CardInfoPictureWithTextOverlayWidget::applyCardTextFont);
}
/**
@ -97,6 +100,13 @@ void CardInfoPictureWithTextOverlayWidget::setTextAlignment(const Qt::Alignment
update();
}
void CardInfoPictureWithTextOverlayWidget::applyCardTextFont()
{
// The overlay paint reads the CardText role font at paint time, so a
// theme font change only needs a repaint here.
update();
}
void CardInfoPictureWithTextOverlayWidget::setHighlighted(bool _highlighted)
{
if (highlighted == _highlighted) {
@ -168,8 +178,10 @@ void CardInfoPictureWithTextOverlayWidget::paintEvent(QPaintEvent *event)
return;
}
// Calculate the optimal font size
QFont font = painter.font();
// Calculate the optimal font size. The family comes from the CardText
// theme role; the fontSize member stays the starting size and the
// shrink-to-fit logic below is unchanged.
QFont font = themeManager->appFont(AppFont::CardText);
int optimalFontSize = fontSize; // Start with the user-defined font size
const QFontMetrics baseMetrics(font);
int textWidth = pixmapRect.width();
@ -284,7 +296,7 @@ QSize CardInfoPictureWithTextOverlayWidget::minimumSizeHint() const
const QSize pixmapSize = pixmap.isNull() ? QSize(0, 0) : pixmap.size();
// Get the font metrics for the overlay text
QFont font;
QFont font = themeManager->appFont(AppFont::CardText);
font.setPointSize(fontSize);
const QFontMetrics fontMetrics(font);

View file

@ -47,6 +47,9 @@ protected:
void mousePressEvent(QMouseEvent *event) override;
[[nodiscard]] QSize minimumSizeHint() const override;
private slots:
void applyCardTextFont();
private:
void drawOutlinedText(QPainter &painter,
const QRect &textRect,

View file

@ -1,5 +1,6 @@
#include "resizable_panel.h"
#include "../interface/theme_manager.h"
#include "abstract_analytics_panel_widget.h"
#include "libcockatrice/utility/qt_utils.h"
@ -12,6 +13,7 @@
#include <QDropEvent>
#include <QEvent>
#include <QFlags>
#include <QFont>
#include <QFrame>
#include <QHBoxLayout>
#include <QMimeData>
@ -98,9 +100,17 @@ ResizablePanel::ResizablePanel(const QString &_typeId, AbstractAnalyticsPanelWid
dragButton->setStyleSheet(QString("QPushButton { "
"background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 %1, stop:1 %2); "
"border: none; color: %3; font-size: 10px; }"
"border: none; color: %3; }"
"QPushButton:hover { background: %4; }")
.arg(mid.name(), dark.name(), placeholderText.name(), midLight.name()));
// Family comes from the InterfaceDefault theme role; the 10px size stays caller-side.
auto applyDragFont = [this]() {
QFont dragFont = themeManager->appFont(AppFont::InterfaceDefault);
dragFont.setPixelSize(10);
dragButton->setFont(dragFont);
};
applyDragFont();
connect(themeManager, &ThemeManager::fontsChanged, this, applyDragFont);
resizeHandle->setStyleSheet(QString("QWidget { background: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
"stop:0 %1, stop:1 %2); }")

View file

@ -1,5 +1,7 @@
#include "deck_list_style_proxy.h"
#include "../../theme_manager.h"
#include <QBrush>
#include <QColor>
#include <QFont>
@ -20,7 +22,8 @@ QVariant DeckListStyleProxy::data(const QModelIndex &index, int role) const
bool isCard = src.data(DeckRoles::IsCardRole).toBool();
if (role == Qt::FontRole && !isCard) {
QFont f;
// Family comes from the DeckList theme role; bold stays caller-side.
QFont f = themeManager->appFont(AppFont::DeckList);
f.setBold(true);
return f;
}

View file

@ -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"
@ -7,7 +8,6 @@
#include <QAbstractItemView>
#include <QFont>
#include <QFontDatabase>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QHeaderView>
@ -70,13 +70,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 +124,11 @@ DlgMyReports::DlgMyReports(AbstractClient *_client, QWidget *parent)
refreshList();
}
void DlgMyReports::applyChatLogFont()
{
chatLogEdit->setFont(report_utils::reportLogFont());
}
void DlgMyReports::refreshList()
{
selectedReportIdBeforeRefresh = selectedReportId;

View file

@ -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);

View file

@ -1,12 +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 <QComboBox>
#include <QDialogButtonBox>
#include <QFont>
#include <QFontDatabase>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
@ -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,11 @@ DlgReportUser::DlgReportUser(AbstractClient *_client,
layout->addWidget(buttonBox);
}
void DlgReportUser::applyChatLogFont()
{
chatLogEdit->setFont(report_utils::reportLogFont());
}
void DlgReportUser::actSubmit()
{
const QString description = descriptionEdit->toPlainText().trimmed();

View file

@ -27,6 +27,7 @@ public:
private slots:
void actSubmit();
void reportResponse(const Response &response);
void applyChatLogFont();
private:
static QString categoryLabel(const QString &key);

View file

@ -2,6 +2,7 @@
#include "../deck_share/shared_deck_preview_widget.h"
#include "../general/layout_containers/flow_widget.h"
#include "../interface/theme_manager.h"
#include <QAbstractButton>
#include <QDateTime>
@ -34,10 +35,15 @@ DlgSharedDecksPreview::DlgSharedDecksPreview(QWidget *parent,
// QLabels render AutoText and markup would otherwise be shown as rich text.
auto *titleLabel =
new QLabel(tr("Share: %1").arg((shareName.isEmpty() ? tr("Untitled") : shareName).toHtmlEscaped()), this);
QFont titleFont = titleLabel->font();
titleFont.setBold(true);
titleFont.setPointSize(titleFont.pointSize() + 2);
titleLabel->setFont(titleFont);
// Family comes from the InterfaceDefault theme role; the +2 size and bold stay caller-side.
auto applyTitleFont = [titleLabel]() {
QFont titleFont = themeManager->appFont(AppFont::InterfaceDefault);
titleFont.setBold(true);
titleFont.setPointSize(titleFont.pointSize() + 2);
titleLabel->setFont(titleFont);
};
applyTitleFont();
connect(themeManager, &ThemeManager::fontsChanged, this, applyTitleFont);
mainLayout->addWidget(titleLabel);
if (!serverText.isEmpty()) {

View file

@ -1,9 +1,11 @@
#include "banner_widget.h"
#include "../../../pixel_map_generator.h"
#include "../../../theme_manager.h"
#include <QBrush>
#include <QColor>
#include <QFont>
#include <QHBoxLayout>
#include <QLinearGradient>
#include <QPainter>
@ -28,7 +30,9 @@ BannerWidget::BannerWidget(QWidget *parent, const QString &text, Qt::Orientation
if (transparency > 50) {
textColor = " color: white;";
}
bannerLabel->setStyleSheet("font-size: 24px; font-weight: bold;" + textColor);
bannerLabel->setStyleSheet(textColor);
applyInterfaceDefaultFont();
connect(themeManager, &ThemeManager::fontsChanged, this, &BannerWidget::applyInterfaceDefaultFont);
layout->addWidget(iconLabel);
layout->addWidget(bannerLabel);
@ -56,6 +60,16 @@ void BannerWidget::setText(const QString &text) const
bannerLabel->setText(text);
}
void BannerWidget::applyInterfaceDefaultFont()
{
// Family comes from the InterfaceDefault theme role; the 24px size and
// bold weight previously carried by the stylesheet stay caller-side.
QFont bannerFont = themeManager->appFont(AppFont::InterfaceDefault);
bannerFont.setPixelSize(24);
bannerFont.setWeight(QFont::Bold);
bannerLabel->setFont(bannerFont);
}
void BannerWidget::setClickable(bool _clickable)
{
clickable = _clickable;

View file

@ -48,6 +48,7 @@ signals:
private slots:
void toggleBuddyVisibility() const;
void updateDropdownIconState() const;
void applyInterfaceDefaultFont();
};
#endif // BANNER_WIDGET_H

View file

@ -1,5 +1,7 @@
#include "bar_chart_widget.h"
#include "../../interface/theme_manager.h"
#include <QBrush>
#include <QFlags>
#include <QFont>
@ -146,7 +148,8 @@ void BarChartWidget::paintEvent(QPaintEvent *)
// draw label below bar
QRect labelRect(left + i * (barWidth + spacing), bottom, barWidth, LABEL_H);
QFont f = p.font();
// Family comes from the InterfaceDefault theme role; bold stays caller-side.
QFont f = themeManager->appFont(AppFont::InterfaceDefault);
f.setBold(true);
p.setFont(f);
p.setPen(Qt::black);

View file

@ -1,5 +1,7 @@
#include "segmented_bar_widget.h"
#include "../../interface/theme_manager.h"
#include <QBrush>
#include <QFont>
#include <QLinearGradient>
@ -95,7 +97,8 @@ void SegmentedBarWidget::paintEvent(QPaintEvent *)
// draw label
QRect labelRect(0, h - LABEL_H, w, LABEL_H);
QFont f = p.font();
// Family comes from the InterfaceDefault theme role; bold stays caller-side.
QFont f = themeManager->appFont(AppFont::InterfaceDefault);
f.setBold(true);
p.setFont(f);
p.setPen(Qt::black);

View file

@ -1,5 +1,7 @@
#include "dynamic_font_size_label.h"
#include "../../interface/theme_manager.h"
#include <QFont>
#include <QFontMetricsF>
#include <QObject>
@ -28,9 +30,13 @@ void DynamicFontSizeLabel::paintEvent(QPaintEvent *event)
// QElapsedTimer timer;
// timer.start();
QFont newFont = font();
// Family follows the InterfaceDefault theme role; the fitted point size
// stays computed from the widget geometry as before.
QFont newFont = themeManager->appFont(AppFont::InterfaceDefault);
float fontSize = getWidgetMaximumFontSize(this, this->text());
newFont.setPointSizeF(fontSize);
// Preserve the caller's bold emphasis, which the role font does not carry.
newFont.setBold(font().bold());
setFont(newFont);
// qDebug() << "Font size set to" << fontSize;
@ -40,7 +46,10 @@ void DynamicFontSizeLabel::paintEvent(QPaintEvent *event)
float DynamicFontSizeLabel::getWidgetMaximumFontSize(QWidget *widget, const QString &text)
{
QFont font = widget->font();
// Measure with the InterfaceDefault family so the fit matches the painted font.
QFont font = themeManager->appFont(AppFont::InterfaceDefault);
font.setBold(widget->font().bold());
font.setPointSizeF(widget->font().pointSizeF());
const QRect widgetRect = widget->contentsRect();
const float widgetWidth = widgetRect.width();
const float widgetHeight = widgetRect.height();

View file

@ -1,5 +1,6 @@
#include "dynamic_font_size_push_button.h"
#include "../../interface/theme_manager.h"
#include "dynamic_font_size_label.h"
#include <QBrush>
@ -20,10 +21,12 @@ void DynamicFontSizePushButton::paintEvent(QPaintEvent *event)
// Call the base class paintEvent to preserve any other painting behavior
QPushButton::paintEvent(event);
// Adjust the font size dynamically based on the text
QFont newFont = font();
// Adjust the font size dynamically based on the text. Family follows the
// InterfaceDefault theme role; the fitted size stays computed as before.
QFont newFont = themeManager->appFont(AppFont::InterfaceDefault);
float fontSize = DynamicFontSizeLabel::getWidgetMaximumFontSize(this, this->text());
newFont.setPointSizeF(fontSize);
newFont.setBold(font().bold());
setFont(newFont);
// Get painter for custom painting

View file

@ -1,6 +1,9 @@
#include "home_styled_button.h"
#include "../../theme_manager.h"
#include <QBrush>
#include <QFont>
#include <QFontMetrics>
#include <QPainter>
#include <QPainterPath>
@ -21,6 +24,18 @@ HomeStyledButton::HomeStyledButton(const QString &text, QPair<QColor, QColor> _g
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setMinimumHeight(25);
setStyleSheet(generateButtonStylesheet(gradientColors));
applyInterfaceDefaultFont();
connect(themeManager, &ThemeManager::fontsChanged, this, &HomeStyledButton::applyInterfaceDefaultFont);
}
void HomeStyledButton::applyInterfaceDefaultFont()
{
// Family comes from the InterfaceDefault theme role; the 34px size and
// bold weight previously carried by the stylesheet stay caller-side.
QFont buttonFont = themeManager->appFont(AppFont::InterfaceDefault);
buttonFont.setPixelSize(34);
buttonFont.setWeight(QFont::Bold);
setFont(buttonFont);
}
void HomeStyledButton::updateStylesheet(const QPair<QColor, QColor> &colors)
@ -50,9 +65,6 @@ QString HomeStyledButton::generateButtonStylesheet(const QPair<QColor, QColor> &
return QString(R"(
QPushButton {
font-size: 34px;
font-weight: bold;
font-family: sans-serif, "Segoe UI", "Helvetica Neue";
padding: 30px;
color: white;
border: 2px solid %1;

View file

@ -24,6 +24,9 @@ public:
public slots:
void paintEvent(QPaintEvent *event) override;
private slots:
void applyInterfaceDefaultFont();
private:
QPair<QColor, QColor> gradientColors;
};

View file

@ -263,7 +263,6 @@ QGroupBox *HomeWidget::createButtons()
QGroupBox *box = new QGroupBox(this);
box->setStyleSheet(R"(
QGroupBox {
font-size: 20px;
color: white; /* Title text color */
background: transparent;
}
@ -274,6 +273,14 @@ QGroupBox *HomeWidget::createButtons()
subcontrol-position: top center; /* or top left / right */
}
)");
// Family comes from the InterfaceDefault theme role; the 20px size stays caller-side.
auto applyBoxFont = [box]() {
QFont boxFont = themeManager->appFont(AppFont::InterfaceDefault);
boxFont.setPixelSize(20);
box->setFont(boxFont);
};
applyBoxFont();
connect(themeManager, &ThemeManager::fontsChanged, this, applyBoxFont);
box->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QVBoxLayout *boxLayout = new QVBoxLayout;
boxLayout->setAlignment(Qt::AlignHCenter);
@ -438,7 +445,9 @@ void HomeWidget::paintEvent(QPaintEvent *event)
constexpr int margin = 15;
constexpr qreal attributionMargin = 4.0;
QFont attributionFont = painter.font();
// Family comes from the InterfaceDefault theme role; the 14px sizes and
// bold weights stay caller-side as before.
QFont attributionFont = themeManager->appFont(AppFont::InterfaceDefault);
attributionFont.setPointSize(14);
attributionFont.setBold(true);
painter.setFont(attributionFont);
@ -451,7 +460,7 @@ void HomeWidget::paintEvent(QPaintEvent *event)
// Card name bubble above the attribution (when enabled).
if (!cardName.isEmpty() && SettingsCache::instance().appearance().getHomeTabDisplayCardName()) {
QFont font = painter.font();
QFont font = themeManager->appFont(AppFont::InterfaceDefault);
font.setPointSize(14);
font.setBold(true);
painter.setFont(font);

View file

@ -1,5 +1,6 @@
#include "first_run_wizard.h"
#include "../interface/theme_manager.h"
#include "first_run_wizard_page.h"
#include "pages/account_setup_page.h"
#include "pages/card_database_setup_page.h"
@ -31,10 +32,8 @@ FirstRunWizard::FirstRunWizard(QWidget *parent) : QDialog(parent)
bannerHost = new BannerHost(this);
titleLabel = new QLabel(this);
QFont titleFont = titleLabel->font();
titleFont.setPointSizeF(titleFont.pointSizeF() * 1.4);
titleFont.setBold(true);
titleLabel->setFont(titleFont);
applyInterfaceDefaultFont();
connect(themeManager, &ThemeManager::fontsChanged, this, &FirstRunWizard::applyInterfaceDefaultFont);
subtitleLabel = new QLabel(this);
subtitleLabel->setWordWrap(true);
@ -155,6 +154,16 @@ void FirstRunWizard::updateChrome()
}
}
void FirstRunWizard::applyInterfaceDefaultFont()
{
// Family comes from the InterfaceDefault theme role; the *1.4 size
// multiplier and bold weight stay caller-side as before.
QFont titleFont = themeManager->appFont(AppFont::InterfaceDefault);
titleFont.setPointSizeF(titleFont.pointSizeF() * 1.4);
titleFont.setBold(true);
titleLabel->setFont(titleFont);
}
void FirstRunWizard::goNext()
{
FirstRunWizardPage *page = pages[currentIndex];

View file

@ -55,6 +55,7 @@ private slots:
void goBack();
void skip();
void updateChrome();
void applyInterfaceDefaultFont();
private:
void addPage(FirstRunWizardPage *page);

View file

@ -1,5 +1,6 @@
#include "all_zones_card_amount_widget.h"
#include "../../theme_manager.h"
#include "../general/display/shadow_background_label.h"
#include "card_amount_widget.h"
#include "libcockatrice/card/card_info.h"
@ -67,6 +68,7 @@ AllZonesCardAmountWidget::AllZonesCardAmountWidget(QWidget *parent,
buttonBoxSideboard->setVisible(!isToken);
connect(cardSizeSlider, &QSlider::valueChanged, this, &AllZonesCardAmountWidget::adjustFontSize);
connect(themeManager, &ThemeManager::fontsChanged, this, &AllZonesCardAmountWidget::applyCardTextFont);
QTimer::singleShot(10, this, [this]() { adjustFontSize(this->cardSizeSlider->value()); });
@ -90,8 +92,9 @@ void AllZonesCardAmountWidget::adjustFontSize(int scalePercentage)
int newFontSize = minFontSize + (scalePercentage - basePercentage) * (maxFontSize - minFontSize) / 225;
newFontSize = std::clamp(newFontSize, minFontSize, maxFontSize);
// Update the font labels
QFont zoneLabelFont = zoneLabelMainboard->font();
// Update the font labels. The family comes from the CardText theme
// role; the slider-driven point size stays as before.
QFont zoneLabelFont = themeManager->appFont(AppFont::CardText);
zoneLabelFont.setPointSize(newFontSize);
zoneLabelMainboard->setFont(zoneLabelFont);
zoneLabelSideboard->setFont(zoneLabelFont);
@ -101,6 +104,11 @@ void AllZonesCardAmountWidget::adjustFontSize(int scalePercentage)
repaint();
}
void AllZonesCardAmountWidget::applyCardTextFont()
{
adjustFontSize(cardSizeSlider->value());
}
void AllZonesCardAmountWidget::setAmounts(int mainboardAmount, int sideboardAmount, int tokensboardAmount)
{
buttonBoxMainboard->setAmount(mainboardAmount);

View file

@ -36,6 +36,9 @@ public slots:
void adjustFontSize(int scalePercentage);
void setAmounts(int mainboardAmount, int sideboardAmount, int tokensboardAmount);
private slots:
void applyCardTextFont();
private:
QVBoxLayout *layout;
QSlider *cardSizeSlider;

View file

@ -1,5 +1,6 @@
#include "card_amount_widget.h"
#include "../../theme_manager.h"
#include "../deck_editor/deck_state_manager.h"
#include "../general/display/dynamic_font_size_push_button.h"
#include "deck_list_model.h"
@ -78,6 +79,7 @@ CardAmountWidget::CardAmountWidget(QWidget *parent,
// Connect slider for dynamic font size adjustment
connect(cardSizeSlider, &QSlider::valueChanged, this, &CardAmountWidget::adjustFontSize);
connect(themeManager, &ThemeManager::fontsChanged, this, &CardAmountWidget::applyCardTextFont);
}
int CardAmountWidget::getAmount()
@ -139,8 +141,9 @@ void CardAmountWidget::adjustFontSize(int scalePercentage)
int newFontSize = minFontSize + (scalePercentage - basePercentage) * (maxFontSize - minFontSize) / 225;
newFontSize = std::clamp(newFontSize, minFontSize, maxFontSize);
// Update the font for card count label
QFont cardCountFont = cardCountInZone->font();
// Update the font for card count label. The family comes from the
// CardText theme role; the slider-driven point size stays as before.
QFont cardCountFont = themeManager->appFont(AppFont::CardText);
cardCountFont.setPointSize(newFontSize);
cardCountInZone->setFont(cardCountFont);
@ -151,6 +154,11 @@ void CardAmountWidget::adjustFontSize(int scalePercentage)
repaint();
}
void CardAmountWidget::applyCardTextFont()
{
adjustFontSize(cardSizeSlider->value());
}
/**
* @brief Updates the card count display in the widget.
*/

View file

@ -67,6 +67,7 @@ private slots:
void removePrintingSideboard();
void removePrintingTokensboard();
void adjustFontSize(int scalePercentage);
void applyCardTextFont();
};
#endif // CARD_AMOUNT_WIDGET_H

View file

@ -1,5 +1,8 @@
#include "printing_selector_placeholder_widget.h"
#include "../interface/theme_manager.h"
#include <QFont>
#include <QLabel>
#include <QSizePolicy>
#include <QVBoxLayout>
@ -30,10 +33,12 @@ PrintingSelectorPlaceholderWidget::PrintingSelectorPlaceholderWidget(QWidget *pa
textLabel->setStyleSheet(R"(
QLabel {
color: palette(mid);
font-size: 14px;
padding: 10px;
}
)");
applyInterfaceDefaultFont();
connect(themeManager, &ThemeManager::fontsChanged, this,
&PrintingSelectorPlaceholderWidget::applyInterfaceDefaultFont);
mainLayout->addWidget(imageLabel);
mainLayout->addWidget(textLabel);
@ -44,4 +49,12 @@ PrintingSelectorPlaceholderWidget::PrintingSelectorPlaceholderWidget(QWidget *pa
void PrintingSelectorPlaceholderWidget::retranslateUi()
{
textLabel->setText(tr("Select a card to view its available printings"));
}
void PrintingSelectorPlaceholderWidget::applyInterfaceDefaultFont()
{
// Family comes from the InterfaceDefault theme role; the 14px size stays caller-side.
QFont placeholderFont = themeManager->appFont(AppFont::InterfaceDefault);
placeholderFont.setPixelSize(14);
textLabel->setFont(placeholderFont);
}

View file

@ -14,6 +14,9 @@ class PrintingSelectorPlaceholderWidget : public QWidget
public:
explicit PrintingSelectorPlaceholderWidget(QWidget *parent = nullptr);
private slots:
void applyInterfaceDefaultFont();
private:
QVBoxLayout *mainLayout;
QLabel *imageLabel;

View file

@ -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();

View file

@ -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);

View file

@ -1,6 +1,7 @@
#include "user_info_box.h"
#include "../../interface/pixel_map_generator.h"
#include "../../interface/theme_manager.h"
#include "../../interface/widgets/dialogs/dlg_edit_avatar.h"
#include "../../interface/widgets/dialogs/dlg_edit_password.h"
#include "../../interface/widgets/dialogs/dlg_edit_user.h"
@ -39,10 +40,8 @@
UserInfoBox::UserInfoBox(AbstractClient *_client, bool _editable, QWidget *parent, Qt::WindowFlags flags)
: QWidget(parent, flags), client(_client), editable(_editable)
{
QFont nameFont = nameLabel.font();
nameFont.setBold(true);
nameFont.setPointSizeF(nameFont.pointSizeF() * 1.5);
nameLabel.setFont(nameFont);
applyInterfaceDefaultFont();
connect(themeManager, &ThemeManager::fontsChanged, this, &UserInfoBox::applyInterfaceDefaultFont);
auto *userIconAndNameLayout = new QHBoxLayout;
userIconAndNameLayout->addWidget(&userLevelIcon, 0, Qt::AlignCenter);
@ -92,6 +91,16 @@ UserInfoBox::UserInfoBox(AbstractClient *_client, bool _editable, QWidget *paren
retranslateUi();
}
void UserInfoBox::applyInterfaceDefaultFont()
{
// Family comes from the InterfaceDefault theme role; the *1.5 size
// multiplier and bold weight stay caller-side as before.
QFont nameFont = themeManager->appFont(AppFont::InterfaceDefault);
nameFont.setBold(true);
nameFont.setPointSizeF(nameFont.pointSizeF() * 1.5);
nameLabel.setFont(nameFont);
}
void UserInfoBox::retranslateUi()
{
realNameLabel1.setText(tr("Real Name:"));

View file

@ -48,6 +48,7 @@ private slots:
void processEditResponse(const Response &r);
void processPasswordResponse(const Response &r);
void processAvatarResponse(const Response &r);
void applyInterfaceDefaultFont();
void actEdit();
void actEditInternal(const Response &r);

View file

@ -141,7 +141,8 @@ public:
p->drawEllipse(QRectF(rect.left() + 9, rect.top() + (rect.height() - 8) / 2.0, 8, 8));
// Game title (bold, elided)
QFont tf = option.font;
// Family comes from the InterfaceDefault theme role; bold stays caller-side.
QFont tf = themeManager->appFont(AppFont::InterfaceDefault);
tf.setBold(true);
p->setFont(tf);
p->setPen(pal.color(QPalette::Text));
@ -153,7 +154,7 @@ public:
// Player count
const bool full = game.player_count() >= game.max_players();
p->setFont(option.font);
p->setFont(themeManager->appFont(AppFont::InterfaceDefault));
p->setPen(full ? QColor(249, 115, 22) : pal.color(QPalette::Disabled, QPalette::Text));
p->drawText(QRect(rect.right() - countW - 4, rect.top(), countW, rect.height()),
Qt::AlignVCenter | Qt::AlignRight,
@ -322,7 +323,8 @@ void UserInfoHeaderWidget::paintEvent(QPaintEvent *)
const int tx = ax + AvatarSize + AvatarToTextGap;
const int tw = rect.width() - tx - 8;
QFont nf = font();
// Family comes from the InterfaceDefault theme role; the *1.12 size and bold stay caller-side.
QFont nf = themeManager->appFont(AppFont::InterfaceDefault);
nf.setBold(true);
nf.setPointSizeF(nf.pointSizeF() * 1.12);
p.setFont(nf);
@ -351,7 +353,7 @@ void UserInfoHeaderWidget::paintEvent(QPaintEvent *)
}
if (!badge.text.isEmpty()) {
QFont bf = font();
QFont bf = themeManager->appFont(AppFont::InterfaceDefault);
bf.setPointSizeF(bf.pointSizeF() * 0.70);
bf.setBold(true);
p.setFont(bf);
@ -368,7 +370,8 @@ void UserInfoHeaderWidget::paintEvent(QPaintEvent *)
// The painter font at this point depends on whether a badge was drawn
// (badge font vs username font), so pin an explicit font for the pill.
p.setFont(font());
// Family follows the InterfaceDefault theme role like the rest of the popup chrome.
p.setFont(themeManager->appFont(AppFont::InterfaceDefault));
// Only show the attribution when there is actually art on screen: on a
// cache miss cardArt is null and the pill would float over the plain
@ -397,6 +400,7 @@ UserInfoPopup::UserInfoPopup(TabSupervisor *_ts,
// Restyle the popup chrome when the theme or its color scheme changes.
if (themeManager) {
connect(themeManager, &ThemeManager::themeChanged, this, &UserInfoPopup::applyTheme);
connect(themeManager, &ThemeManager::fontsChanged, this, &UserInfoPopup::applyTheme);
}
}
@ -476,15 +480,24 @@ void UserInfoPopup::applyTheme()
separator->setStyleSheet(QStringLiteral("color:%1; margin: 0 8px;").arg(colorStr(theme.border)));
gamesLabel->setStyleSheet(QStringLiteral("color:%1; font-size:11px; font-weight:bold; background:transparent;")
.arg(colorStr(theme.subText)));
gamesLabel->setStyleSheet(QStringLiteral("color:%1; background:transparent;").arg(colorStr(theme.subText)));
QFont gamesLabelFont = themeManager->appFont(AppFont::InterfaceDefault);
gamesLabelFont.setPixelSize(11);
gamesLabelFont.setWeight(QFont::Bold);
gamesLabel->setFont(gamesLabelFont);
refreshBtn->setStyleSheet(QStringLiteral("QPushButton{color:%1;border:none;font-size:14px;background:transparent;}"
refreshBtn->setStyleSheet(QStringLiteral("QPushButton{color:%1;border:none;background:transparent;}"
"QPushButton:hover{color:%2;}")
.arg(colorStr(theme.subText), colorStr(theme.text)));
QFont refreshFont = themeManager->appFont(AppFont::InterfaceDefault);
refreshFont.setPixelSize(14);
refreshBtn->setFont(refreshFont);
gamesStatus->setStyleSheet(QStringLiteral("color:%1; font-size:11px; padding:10px; background:transparent;")
.arg(colorStr(theme.statusText)));
gamesStatus->setStyleSheet(
QStringLiteral("color:%1; padding:10px; background:transparent;").arg(colorStr(theme.statusText)));
QFont statusFont = themeManager->appFont(AppFont::InterfaceDefault);
statusFont.setPixelSize(11);
gamesStatus->setFont(statusFont);
gamesView->setStyleSheet(QStringLiteral("QListView{background:%1;border:none;}"
"QListView::item:selected{background:%2;}")
@ -492,9 +505,12 @@ void UserInfoPopup::applyTheme()
closeBtn->setStyleSheet(
QStringLiteral("QPushButton{background:%1;color:%2;"
"border:none;border-radius:11px;font-size:10px;}"
"border:none;border-radius:11px;}"
"QPushButton:hover{color:%3;background:%4;}")
.arg(colorStr(theme.closeBg), colorStr(theme.subText), colorStr(theme.text), colorStr(theme.closeHover)));
QFont closeFont = themeManager->appFont(AppFont::InterfaceDefault);
closeFont.setPixelSize(10);
closeBtn->setFont(closeFont);
header->update();
}
@ -509,13 +525,17 @@ static QPushButton *makeBtn(const QString &label, const QString &tip, QWidget *p
b->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
b->setStyleSheet(QStringLiteral("QPushButton{"
" background:%1;color:%2;border:1px solid %3;"
" border-radius:4px;font-size:11px;padding:0 4px;"
" border-radius:4px;padding:0 4px;"
"}"
"QPushButton:hover{background:%4;color:%5;}"
"QPushButton:pressed{background:%6;}"
"QPushButton:disabled{color:%7;border-color:%3;}")
.arg(colorStr(t.buttonBg), colorStr(t.text), colorStr(t.buttonBorder), colorStr(t.buttonHover),
colorStr(t.text), colorStr(t.buttonPressed), colorStr(t.buttonDisabled)));
// Family comes from the InterfaceDefault theme role; the 11px size stays caller-side.
QFont btnFont = themeManager->appFont(AppFont::InterfaceDefault);
btnFont.setPixelSize(11);
b->setFont(btnFont);
return b;
}

View file

@ -1,6 +1,7 @@
#include "user_list_painter.h"
#include "../../interface/pixel_map_generator.h"
#include "../../interface/theme_manager.h"
#include "libcockatrice/protocol/pb/serverinfo_user.pb.h"
#include <QAbstractScrollArea>
@ -292,7 +293,9 @@ void UserListPainter::drawUserName(QPainter *painter,
bool online,
const Style &style)
{
QFont nameFont = option.font;
Q_UNUSED(option);
// Family comes from the InterfaceDefault theme role; bold stays caller-side.
QFont nameFont = themeManager->appFont(AppFont::InterfaceDefault);
nameFont.setBold(true);
painter->setFont(nameFont);
@ -351,7 +354,9 @@ void UserListPainter::drawBadges(QPainter *painter,
return;
}
QFont badgeFont = option.font;
Q_UNUSED(option);
// Family comes from the InterfaceDefault theme role; the *0.68 size and bold stay caller-side.
QFont badgeFont = themeManager->appFont(AppFont::InterfaceDefault);
badgeFont.setPointSizeF(badgeFont.pointSizeF() * 0.68);
badgeFont.setBold(true);
painter->setFont(badgeFont);

View file

@ -1496,7 +1496,7 @@ QTreeWidgetItem *UserListWidget::createSectionItem(Section section)
// They act as collapsible section headers once they have focus.
divider->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
QFont font = userTree->font();
QFont font = themeManager->appFont(AppFont::InterfaceDefault);
font.setBold(true);
divider->setFont(0, font);
// A little taller than a plain text row so the header reads as a section

View file

@ -5,6 +5,7 @@
*/
#include "settings_search_delegate.h"
#include "../interface/theme_manager.h"
#include "settings_search_model.h"
#include <QBrush>
@ -88,7 +89,8 @@ void SettingsSearchDelegate::paint(QPainter *painter,
QRect textRect = contentRect.adjusted(iconOffset, 0, 0, 0);
// Breadcrumb: "Page > Group"
QFont breadcrumbFont = option.font;
// Family comes from the InterfaceDefault theme role; the -1 size and bold stay caller-side.
QFont breadcrumbFont = themeManager->appFont(AppFont::InterfaceDefault);
breadcrumbFont.setPointSize(breadcrumbFont.pointSize() - 1);
breadcrumbFont.setBold(true);
@ -113,7 +115,7 @@ void SettingsSearchDelegate::paint(QPainter *painter,
yPos += 20;
// Setting label
QFont labelFont = option.font;
QFont labelFont = themeManager->appFont(AppFont::InterfaceDefault);
labelFont.setPointSize(labelFont.pointSize() + 1);
labelFont.setBold(isSelected);

View file

@ -1,5 +1,6 @@
#include "archidekt_deck_preview_image_display_widget.h"
#include "../../../../../theme_manager.h"
#include "../../../../general/display/shadow_background_label.h"
#include <QFont>
@ -17,13 +18,9 @@ ArchidektDeckPreviewImageDisplayWidget::ArchidektDeckPreviewImageDisplayWidget(Q
bottomLeftLabel = new ShadowBackgroundLabel(this, "");
bottomRightLabel = new ShadowBackgroundLabel(this, "");
QFont f;
f.setBold(true);
f.setPointSize(16);
topLeftLabel->setFont(f);
topRightLabel->setFont(f);
bottomLeftLabel->setFont(f);
bottomRightLabel->setFont(f);
applyCardTextFont();
connect(themeManager, &ThemeManager::fontsChanged, this,
&ArchidektDeckPreviewImageDisplayWidget::applyCardTextFont);
// Raise so labels appear above image
topLeftLabel->raise();
@ -32,6 +29,18 @@ ArchidektDeckPreviewImageDisplayWidget::ArchidektDeckPreviewImageDisplayWidget(Q
bottomRightLabel->raise();
}
void ArchidektDeckPreviewImageDisplayWidget::applyCardTextFont()
{
// Family comes from the CardText theme role; size and weight stay caller-side as before.
QFont f = themeManager->appFont(AppFont::CardText);
f.setBold(true);
f.setPointSize(16);
topLeftLabel->setFont(f);
topRightLabel->setFont(f);
bottomLeftLabel->setFont(f);
bottomRightLabel->setFont(f);
}
void ArchidektDeckPreviewImageDisplayWidget::setAspectRatio(float ratio)
{
aspectRatio = ratio;

View file

@ -60,6 +60,9 @@ protected:
*/
void resizeEvent(QResizeEvent *event) override;
private slots:
void applyCardTextFont();
private:
float aspectRatio = 1.0f; ///< Aspect ratio to maintain for the preview image
};

View file

@ -1,5 +1,6 @@
#include "edhrec_api_response_card_details_display_widget.h"
#include "../../../../../../theme_manager.h"
#include "../../../../../cards/card_info_picture_widget.h"
#include "../../../../../cards/card_size_widget.h"
#include "../../../../../general/display/background_plate_widget.h"
@ -9,6 +10,7 @@
#include "edhrec_api_response_card_synergy_display_widget.h"
#include "libcockatrice/card/database/card_database_querier.h"
#include <QFont>
#include <QLabel>
#include <QMouseEvent>
#include <QObject>
@ -31,7 +33,9 @@ EdhrecApiResponseCardDetailsDisplayWidget::EdhrecApiResponseCardDetailsDisplayWi
nameLabel = new QLabel(this);
nameLabel->setText(toDisplay.name);
nameLabel->setAlignment(Qt::AlignHCenter);
nameLabel->setStyleSheet("font-size: 20px; font-weight: bold");
applyCardTextFont();
connect(themeManager, &ThemeManager::fontsChanged, this,
&EdhrecApiResponseCardDetailsDisplayWidget::applyCardTextFont);
inclusionDisplayWidget = new EdhrecApiResponseCardInclusionDisplayWidget(this, toDisplay);
@ -93,3 +97,14 @@ void EdhrecApiResponseCardDetailsDisplayWidget::actRequestPageNavigation()
{
emit requestUrl(toDisplay.url);
}
void EdhrecApiResponseCardDetailsDisplayWidget::applyCardTextFont()
{
// Family comes from the CardText theme role; the 20px size and bold
// weight previously carried by the stylesheet stay caller-side. Pixel
// size, not point size: the stylesheet said 20px, and 20pt is ~27px.
QFont cardFont = themeManager->appFont(AppFont::CardText);
cardFont.setPixelSize(20);
cardFont.setWeight(QFont::Bold);
nameLabel->setFont(cardFont);
}

View file

@ -30,6 +30,9 @@ public slots:
signals:
void requestUrl(QString url);
private slots:
void applyCardTextFont();
private:
EdhrecApiResponseCardDetails toDisplay;
QVBoxLayout *layout;

View file

@ -1,5 +1,6 @@
#include "edhrec_api_response_commander_details_display_widget.h"
#include "../../../../../../theme_manager.h"
#include "../../../../../cards/card_info_picture_widget.h"
#include "../../../../../cards/card_size_widget.h"
#include "../../api_response/cards/edhrec_commander_api_response_commander_details.h"
@ -8,6 +9,7 @@
#include "edhrec_commander_api_response_navigation_widget.h"
#include "libcockatrice/card/database/card_database_querier.h"
#include <QFont>
#include <QHBoxLayout>
#include <QLabel>
#include <QObject>
@ -55,15 +57,16 @@ EdhrecCommanderResponseCommanderDetailsDisplayWidget::EdhrecCommanderResponseCom
commanderName = new QLabel(this);
commanderName->setText(commanderDetails.getName());
commanderName->setAlignment(Qt::AlignCenter);
commanderName->setStyleSheet("font-size: 28px; font-weight: bold");
label = new QLabel(this);
label->setAlignment(Qt::AlignCenter);
label->setStyleSheet("font-size: 16px");
salt = new QLabel(this);
salt->setAlignment(Qt::AlignCenter);
salt->setStyleSheet("font-size: 16px");
applyCardTextFont();
connect(themeManager, &ThemeManager::fontsChanged, this,
&EdhrecCommanderResponseCommanderDetailsDisplayWidget::applyCardTextFont);
cardPricesDisplayWidget = new EdhrecApiResponseCardPricesDisplayWidget(this, commanderDetails.getPrices());
@ -90,3 +93,19 @@ void EdhrecCommanderResponseCommanderDetailsDisplayWidget::retranslateUi()
label->setText(commanderDetails.getLabel());
salt->setText(tr("Salt: ") + QString::number(commanderDetails.getSalt()));
}
void EdhrecCommanderResponseCommanderDetailsDisplayWidget::applyCardTextFont()
{
// Family comes from the CardText theme role; the sizes and the bold
// weight previously carried by the stylesheets stay caller-side. Pixel
// sizes, not point sizes: the stylesheets said 28px and 16px.
QFont nameFont = themeManager->appFont(AppFont::CardText);
nameFont.setPixelSize(28);
nameFont.setWeight(QFont::Bold);
commanderName->setFont(nameFont);
QFont detailsFont = themeManager->appFont(AppFont::CardText);
detailsFont.setPixelSize(16);
label->setFont(detailsFont);
salt->setFont(detailsFont);
}

View file

@ -30,6 +30,9 @@ public:
QString baseUrl);
void retranslateUi();
private slots:
void applyCardTextFont();
private:
EdhrecCommanderApiResponseCommanderDetails commanderDetails;
QHBoxLayout *layout;

View file

@ -1,6 +1,9 @@
#include "edhrec_commander_api_response_bracket_navigation_widget.h"
#include "../../interface/theme_manager.h"
#include <QChar>
#include <QFont>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
@ -25,7 +28,7 @@ EdhrecCommanderApiResponseBracketNavigationWidget::EdhrecCommanderApiResponseBra
QString label = option.isEmpty() ? "All" : option.at(0).toUpper() + option.mid(1);
QPushButton *optionButton = new QPushButton(label, this);
optionButton->setMinimumHeight(84);
optionButton->setStyleSheet("font-size: 24px");
optionButton->setStyleSheet(QString());
gameChangerButtons[option] = optionButton;
layout->addWidget(optionButton, 2, i);
connect(optionButton, &QPushButton::clicked, this, [=, this]() {
@ -35,6 +38,10 @@ EdhrecCommanderApiResponseBracketNavigationWidget::EdhrecCommanderApiResponseBra
});
}
applyInterfaceDefaultFont();
connect(themeManager, &ThemeManager::fontsChanged, this,
&EdhrecCommanderApiResponseBracketNavigationWidget::applyInterfaceDefaultFont);
updateOptionButtonSelection(gameChangerButtons, "");
retranslateUi();
@ -94,8 +101,18 @@ void EdhrecCommanderApiResponseBracketNavigationWidget::updateOptionButtonSelect
const QString &selectedKey)
{
for (auto it = buttons.begin(); it != buttons.end(); ++it) {
it.value()->setStyleSheet(it.key() == selectedKey
? "background-color: lightblue; font-weight: bold; font-size: 24px;"
: "font-size: 24px");
const bool selected = (it.key() == selectedKey);
it.value()->setStyleSheet(selected ? QStringLiteral("background-color: lightblue;") : QString());
QFont buttonFont = themeManager->appFont(AppFont::InterfaceDefault);
buttonFont.setPixelSize(24);
buttonFont.setWeight(selected ? QFont::Bold : QFont::Normal);
it.value()->setFont(buttonFont);
}
}
void EdhrecCommanderApiResponseBracketNavigationWidget::applyInterfaceDefaultFont()
{
// Family comes from the InterfaceDefault theme role; the 24px size stays
// caller-side and the selected button keeps its bold emphasis.
updateOptionButtonSelection(gameChangerButtons, selectedGameChanger);
}

View file

@ -37,6 +37,9 @@ private:
QMap<QString, QPushButton *> gameChangerButtons;
void updateOptionButtonSelection(QMap<QString, QPushButton *> &buttons, const QString &selectedKey);
private slots:
void applyInterfaceDefaultFont();
};
#endif // COCKATRICE_EDHREC_COMMANDER_API_RESPONSE_BRACKET_NAVIGATION_WIDGET_H

View file

@ -1,6 +1,9 @@
#include "edhrec_commander_api_response_budget_navigation_widget.h"
#include "../../interface/theme_manager.h"
#include <QChar>
#include <QFont>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
@ -25,7 +28,7 @@ EdhrecCommanderApiResponseBudgetNavigationWidget::EdhrecCommanderApiResponseBudg
QString label = option.isEmpty() ? "Any" : option.at(0).toUpper() + option.mid(1);
QPushButton *btn = new QPushButton(label, this);
btn->setMinimumHeight(84);
btn->setStyleSheet("font-size: 24px");
btn->setStyleSheet(QString());
budgetButtons[option] = btn;
layout->addWidget(btn, 4, i);
connect(btn, &QPushButton::clicked, this, [=, this]() {
@ -35,6 +38,10 @@ EdhrecCommanderApiResponseBudgetNavigationWidget::EdhrecCommanderApiResponseBudg
});
}
applyInterfaceDefaultFont();
connect(themeManager, &ThemeManager::fontsChanged, this,
&EdhrecCommanderApiResponseBudgetNavigationWidget::applyInterfaceDefaultFont);
updateOptionButtonSelection(budgetButtons, "");
retranslateUi();
@ -96,8 +103,18 @@ void EdhrecCommanderApiResponseBudgetNavigationWidget::updateOptionButtonSelecti
const QString &selectedKey)
{
for (auto it = buttons.begin(); it != buttons.end(); ++it) {
it.value()->setStyleSheet(it.key() == selectedKey
? "background-color: lightblue; font-weight: bold; font-size: 24px;"
: "font-size: 24px");
const bool selected = (it.key() == selectedKey);
it.value()->setStyleSheet(selected ? QStringLiteral("background-color: lightblue;") : QString());
QFont buttonFont = themeManager->appFont(AppFont::InterfaceDefault);
buttonFont.setPixelSize(24);
buttonFont.setWeight(selected ? QFont::Bold : QFont::Normal);
it.value()->setFont(buttonFont);
}
}
void EdhrecCommanderApiResponseBudgetNavigationWidget::applyInterfaceDefaultFont()
{
// Family comes from the InterfaceDefault theme role; the 24px size stays
// caller-side and the selected button keeps its bold emphasis.
updateOptionButtonSelection(budgetButtons, selectedBudget);
}

View file

@ -37,6 +37,9 @@ private:
QMap<QString, QPushButton *> budgetButtons;
void updateOptionButtonSelection(QMap<QString, QPushButton *> &buttons, const QString &selectedKey);
private slots:
void applyInterfaceDefaultFont();
};
#endif // COCKATRICE_EDHREC_COMMANDER_API_RESPONSE_BUDGET_NAVIGATION_WIDGET_H

View file

@ -1,9 +1,11 @@
#include "edhrec_commander_api_response_navigation_widget.h"
#include "../../interface/theme_manager.h"
#include "../../tab_edhrec_main.h"
#include "edhrec_commander_api_response_bracket_navigation_widget.h"
#include "edhrec_commander_api_response_budget_navigation_widget.h"
#include <QFont>
#include <QGridLayout>
#include <QObject>
#include <QPushButton>
@ -29,10 +31,14 @@ EdhrecCommanderApiResponseNavigationWidget::EdhrecCommanderApiResponseNavigation
comboPushButton = new QPushButton(this);
comboPushButton->setMinimumHeight(84);
comboPushButton->setStyleSheet("font-size: 24px");
comboPushButton->setStyleSheet(QString());
averageDeckPushButton = new QPushButton(this);
averageDeckPushButton->setMinimumHeight(84);
averageDeckPushButton->setStyleSheet("font-size: 24px");
averageDeckPushButton->setStyleSheet(QString());
applyInterfaceDefaultFont();
connect(themeManager, &ThemeManager::fontsChanged, this,
&EdhrecCommanderApiResponseNavigationWidget::applyInterfaceDefaultFont);
layout->addWidget(comboPushButton, 0, 0, 1, 1);
layout->addWidget(averageDeckPushButton, 0, 1, 1, 1);
@ -68,6 +74,15 @@ void EdhrecCommanderApiResponseNavigationWidget::retranslateUi()
averageDeckPushButton->setText(tr("Average Deck"));
}
void EdhrecCommanderApiResponseNavigationWidget::applyInterfaceDefaultFont()
{
// Family comes from the InterfaceDefault theme role; the 24px size stays caller-side.
QFont navFont = themeManager->appFont(AppFont::InterfaceDefault);
navFont.setPixelSize(24);
comboPushButton->setFont(navFont);
averageDeckPushButton->setFont(navFont);
}
QString EdhrecCommanderApiResponseNavigationWidget::addNavigationOptionsToUrl(QString baseUrl)
{
if (!bracketNavigationWidget->getSelectedGameChanger().isEmpty()) {

View file

@ -35,6 +35,9 @@ public slots:
signals:
void requestUrl(QString url);
private slots:
void applyInterfaceDefaultFont();
private:
QGridLayout *layout;

View file

@ -6,6 +6,7 @@
#include "tab_developer.h"
#include "../interface/theme_manager.h"
#include "libcockatrice/protocol/pb/response.pb.h"
#include <QAbstractItemView>
@ -155,7 +156,8 @@ void TabDeveloper::appendSeparatorRow(const QString &sectionTitle)
const int row = statsTable->rowCount();
statsTable->insertRow(row);
auto *labelItem = new QTableWidgetItem(sectionTitle);
auto font = labelItem->font();
// Family comes from the InterfaceDefault theme role; bold stays caller-side.
QFont font = themeManager->appFont(AppFont::InterfaceDefault);
font.setBold(true);
labelItem->setFont(font);
labelItem->setFlags(labelItem->flags() & ~Qt::ItemIsSelectable);

View file

@ -5,6 +5,7 @@
#include "../../deck_loader/loaded_deck.h"
#include "../cards/card_size_widget.h"
#include "../general/layout_containers/flow_widget.h"
#include "../interface/theme_manager.h"
#include "../visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.h"
#include "../visual_deck_storage/deck_preview/public_deck_preview_widget.h"
#include "../visual_deck_storage/remote_public_decks_model.h"
@ -44,9 +45,14 @@ TabPublicDecks::TabPublicDecks(TabSupervisor *_tabSupervisor, AbstractClient *_c
cardSize = SettingsCache::instance().cardsDisplay().getVisualDeckStorageCardSize();
titleLabel = new QLabel(tr("Public decks of %1").arg(userName.toHtmlEscaped()), this);
QFont titleFont = titleLabel->font();
titleFont.setBold(true);
titleLabel->setFont(titleFont);
// Family comes from the InterfaceDefault theme role; bold stays caller-side.
auto applyTitleFont = [this]() {
QFont titleFont = themeManager->appFont(AppFont::InterfaceDefault);
titleFont.setBold(true);
titleLabel->setFont(titleFont);
};
applyTitleFont();
connect(themeManager, &ThemeManager::fontsChanged, this, applyTitleFont);
auto *headerLayout = new QHBoxLayout;
headerLayout->addWidget(titleLabel);

View file

@ -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"
@ -13,7 +14,6 @@
#include <QDateTime>
#include <QDebug>
#include <QFont>
#include <QFontDatabase>
#include <QGridLayout>
#include <QGroupBox>
#include <QHBoxLayout>
@ -138,13 +138,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 +272,11 @@ TabReport::TabReport(TabSupervisor *_tabSupervisor, AbstractClient *_client) : T
refreshList();
}
void TabReport::applyChatLogFont()
{
chatLogEdit->setFont(report_utils::reportLogFont());
}
void TabReport::retranslateUi()
{
userContextMenu->retranslateUi();

View file

@ -62,6 +62,7 @@ private slots:
void statsResponse(const Response &response);
void reopenReport();
void reopenResponse(const Response &response);
void applyChatLogFont();
private:
int selectedReportId() const;

View file

@ -1,5 +1,6 @@
#include "card_completer_delegate.h"
#include "../../interface/theme_manager.h"
#include "../../pixel_map_generator.h"
#include "../cards/additional_info/mana_cost_widget.h"
#include "libcockatrice/card/database/card_database_querier.h"
@ -181,7 +182,7 @@ void CardCompleterDelegate::drawManaSymbol(QPainter *p, QPoint centre, const QSt
p->setBrush(Qt::NoBrush);
p->drawEllipse(pip.adjusted(1, 1, -1, -1));
QFont f = p->font();
QFont f = themeManager->appFont(AppFont::CardText);
f.setPixelSize(qMax(radius - 1, 7));
f.setBold(true);
@ -429,7 +430,7 @@ void CardCompleterDelegate::paint(QPainter *painter, const QStyleOptionViewItem
const QRect nameRect = showInfoBand ? QRect(textLeft, rect.top() + 2, textWidth, 20)
: QRect(textLeft, rect.top() + 2, textWidth, rect.height() - 4);
QFont f = option.font;
QFont f = themeManager->appFont(AppFont::CardText);
f.setPixelSize(13);
f.setBold(true);
@ -451,7 +452,7 @@ void CardCompleterDelegate::paint(QPainter *painter, const QStyleOptionViewItem
if (showInfoBand) {
const QRect infoRect(textLeft, rect.top() + 22, textWidth, rect.height() - 24);
QFont f = option.font;
QFont f = themeManager->appFont(AppFont::CardText);
f.setPixelSize(10);
painter->setFont(f);

View file

@ -1,5 +1,6 @@
#include "report_utils.h"
#include "../../theme_manager.h"
#include "libcockatrice/protocol/pb/serverinfo_report.pb.h"
#include <QApplication>
@ -7,6 +8,7 @@
#include <QChar>
#include <QColor>
#include <QDateTime>
#include <QFontDatabase>
#include <QPalette>
#include <QSharedPointer>
#include <QTableWidget>
@ -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)

View file

@ -1,6 +1,7 @@
#ifndef REPORT_UTILS_H
#define REPORT_UTILS_H
#include <QFont>
#include <QString>
#include <QtGlobal>
@ -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);

View file

@ -1,5 +1,8 @@
#include "visual_deck_editor_placeholder_widget.h"
#include "../interface/theme_manager.h"
#include <QFont>
#include <QLabel>
#include <QVBoxLayout>
#include <qnamespace.h>
@ -28,10 +31,12 @@ VisualDeckEditorPlaceholderWidget::VisualDeckEditorPlaceholderWidget(QWidget *pa
textLabel->setStyleSheet(R"(
QLabel {
color: palette(mid);
font-size: 14px;
padding: 10px;
}
)");
applyInterfaceDefaultFont();
connect(themeManager, &ThemeManager::fontsChanged, this,
&VisualDeckEditorPlaceholderWidget::applyInterfaceDefaultFont);
mainLayout->addWidget(imageLabel);
mainLayout->addWidget(textLabel);
@ -42,4 +47,12 @@ VisualDeckEditorPlaceholderWidget::VisualDeckEditorPlaceholderWidget(QWidget *pa
void VisualDeckEditorPlaceholderWidget::retranslateUi()
{
textLabel->setText(tr("Add cards using the search bar or database tab to have them appear here"));
}
void VisualDeckEditorPlaceholderWidget::applyInterfaceDefaultFont()
{
// Family comes from the InterfaceDefault theme role; the 14px size stays caller-side.
QFont placeholderFont = themeManager->appFont(AppFont::InterfaceDefault);
placeholderFont.setPixelSize(14);
textLabel->setFont(placeholderFont);
}

View file

@ -15,6 +15,9 @@ public:
explicit VisualDeckEditorPlaceholderWidget(QWidget *parent = nullptr);
void retranslateUi();
private slots:
void applyInterfaceDefaultFont();
private:
QVBoxLayout *mainLayout;
QLabel *imageLabel;

View file

@ -1,5 +1,7 @@
#include "deck_preview_tag_addition_widget.h"
#include "../../interface/theme_manager.h"
#include <QBrush>
#include <QColor>
#include <QFlags>
@ -65,8 +67,9 @@ void DeckPreviewTagAdditionWidget::paintEvent(QPaintEvent *event)
painter.setPen(borderPen);
painter.drawRect(rect().adjusted(0, 0, -1, -1)); // Adjust for pen width
// Calculate font size based on widget height
QFont font = painter.font();
// Calculate font size based on widget height. Family comes from the
// InterfaceDefault theme role; the height-derived size stays as before.
QFont font = themeManager->appFont(AppFont::InterfaceDefault);
int fontSize = std::max(10, height() / 2); // Ensure a minimum font size of 10
font.setPointSize(fontSize);
painter.setFont(font);

View file

@ -1,5 +1,7 @@
#include "deck_preview_tag_display_widget.h"
#include "../../interface/theme_manager.h"
#include <QBrush>
#include <QColor>
#include <QFlags>
@ -117,8 +119,9 @@ void DeckPreviewTagDisplayWidget::paintEvent(QPaintEvent *event)
painter.setPen(borderPen);
painter.drawRect(rect().adjusted(0, 0, -1, -1));
// Calculate font size based on widget height
QFont font = painter.font();
// Calculate font size based on widget height. Family comes from the
// InterfaceDefault theme role; the height-derived size stays as before.
QFont font = themeManager->appFont(AppFont::InterfaceDefault);
int fontSize = std::max(10, height() / 2); // Ensure a minimum font size of 10
font.setPointSize(fontSize);
painter.setFont(font);