[Fonts] Keep the DeckList fallback on the application font

DeckList is read by the deck editor headers, the filter tree and the deck
view too, not only by the two surfaces that hardcoded Serif. Resolving the
unset role to Serif in appFont() made every user without a fonts.toml see
Serif outside the deck list.

- appFont(DeckList) falls back to the application font again.
- ThemeManager::deckListFont() resolves the role and keeps the Serif
  fallback for the two historical sites: the deck view zone headers and
  the printed deck list.
- DeckView no longer repaints its viewport on fontsChanged; touching the
  scene items already schedules the repaint in every attached view.
This commit is contained in:
Lukas Brübach 2026-11-01 17:23:51 +01:00
parent 239642b8a0
commit 86fbf5032e
4 changed files with 31 additions and 20 deletions

View file

@ -241,8 +241,7 @@ void DeckViewCardContainer::paint(QPainter *painter, const QStyleOptionGraphicsI
painter->setPen(QColor(Qt::white));
// Family comes from the DeckList theme role; pixel sizes/weights unchanged.
QFont f = themeManager->appFont(AppFont::DeckList);
f.setStyleHint(QFont::Serif);
QFont f = themeManager->deckListFont();
f.setPixelSize(24);
f.setWeight(QFont::Bold);
painter->setFont(f);
@ -294,8 +293,7 @@ QList<QPair<int, int>> DeckViewCardContainer::getRowsAndCols() const
int DeckViewCardContainer::getCardTypeTextWidth() const
{
// Family comes from the DeckList theme role; pixel size/weight unchanged.
QFont f = themeManager->appFont(AppFont::DeckList);
f.setStyleHint(QFont::Serif);
QFont f = themeManager->deckListFont();
f.setPixelSize(16);
f.setWeight(QFont::Bold);
QFontMetrics fm(f);
@ -588,9 +586,6 @@ DeckView::DeckView(QWidget *parent) : QGraphicsView(parent)
connect(deckViewScene, &DeckViewScene::sceneRectChanged, this, &DeckView::updateSceneRect);
connect(deckViewScene, &DeckViewScene::newCardAdded, this, &DeckView::newCardAdded);
connect(deckViewScene, &DeckViewScene::sideboardPlanChanged, this, &DeckView::sideboardPlanChanged);
// The scene already touches its items on fontsChanged; repaint the
// viewport here so the new DeckList family shows without interaction.
connect(themeManager, &ThemeManager::fontsChanged, this, [this] { viewport()->update(); });
}
void DeckView::resizeEvent(QResizeEvent *event)

View file

@ -581,7 +581,7 @@ void DeckLoader::printDeckListNode(QTextCursor *cursor, const InnerDecklistNode
QTextBlockFormat blockFormat;
QTextCharFormat charFormat;
// Family comes from the DeckList theme role; sizes/weights unchanged.
charFormat.setFontFamilies({themeManager->appFont(AppFont::DeckList).family()});
charFormat.setFontFamilies({themeManager->deckListFont().family()});
charFormat.setFontPointSize(11);
charFormat.setFontWeight(QFont::Bold);
cursor->insertBlock(blockFormat, charFormat);
@ -595,7 +595,7 @@ void DeckLoader::printDeckListNode(QTextCursor *cursor, const InnerDecklistNode
const AbstractDecklistCardNode *card = cards[i];
QTextCharFormat cellCharFormat;
cellCharFormat.setFontFamilies({themeManager->appFont(AppFont::DeckList).family()});
cellCharFormat.setFontFamilies({themeManager->deckListFont().family()});
cellCharFormat.setFontPointSize(9);
QTextTableCell cell = table->cellAt(i, 0);
@ -617,7 +617,7 @@ void DeckLoader::printDeckListNode(QTextCursor *cursor, const InnerDecklistNode
QTextBlockFormat blockFormat;
QTextCharFormat charFormat;
charFormat.setFontFamilies({themeManager->appFont(AppFont::DeckList).family()});
charFormat.setFontFamilies({themeManager->deckListFont().family()});
charFormat.setFontPointSize(14);
charFormat.setFontWeight(QFont::Bold);
@ -649,15 +649,14 @@ void DeckLoader::printDeckList(QPrinter *printer, const DeckList &deckList)
// Print output is a one-shot snapshot and intentionally does not subscribe
// to fontsChanged (there is no live view to repaint); reprinting picks up
// the current role font.
QFont font = themeManager->appFont(AppFont::DeckList);
font.setStyleHint(QFont::Serif);
QFont font = themeManager->deckListFont();
doc.setDefaultFont(font);
QTextCursor cursor(&doc);
QTextBlockFormat headerBlockFormat;
QTextCharFormat headerCharFormat;
headerCharFormat.setFontFamilies({themeManager->appFont(AppFont::DeckList).family()});
headerCharFormat.setFontFamilies({themeManager->deckListFont().family()});
headerCharFormat.setFontPointSize(16);
headerCharFormat.setFontWeight(QFont::Bold);

View file

@ -657,10 +657,12 @@ QFont ThemeManager::appFont(AppFont::Role role) const
}
// Role fallbacks preserve the pre-theme defaults when no fonts.toml is
// present: chat logs rendered monospace (matching the report dialogs),
// card text and deck lists from a serif basis (deck_view.cpp and
// deck_loader.cpp previously hardcoded "Serif"), everything else from the
// app font. Only the family basis is fixed here; sizes stay caller-side.
// present: chat logs rendered monospace (matching the report dialogs) and
// every other role resolves to the app font. The surfaces that hardcoded a
// different family ask for it explicitly: counter painters through
// cardTextFont(), the deck view headers and printed deck list through
// deckListFont(). Only the family basis is fixed there; sizes stay
// caller-side.
if (role == AppFont::ChatLog) {
// ChatView never set a font before the theme role existed, so an unset
// ChatLog must keep resolving to the application font. The report
@ -690,6 +692,16 @@ QFont ThemeManager::cardTextFont() const
return serifFont;
}
QFont ThemeManager::deckListFont() const
{
if (hasAppFont(AppFont::DeckList)) {
return appFont(AppFont::DeckList);
}
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

View file

@ -150,15 +150,20 @@ 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 a per-role fallback (monospace for
* ChatLog, serif basis for CardText and DeckList, the application
* font for the remaining roles). */
* value when present, otherwise the application font. Roles that
* had a historical hardcoded family ask for it through
* cardTextFont() and deckListFont() instead. */
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 The DeckList role with its historical Serif fallback. Used by the
* two surfaces that hardcoded Serif before the role existed (the
* deck view zone headers and the printed deck list); every other
* DeckList reader falls back to the application font. */
QFont deckListFont() 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()