[Fonts] Restore DeckList Serif default and live-update all role readers (#7541)

* [Fonts] Restore DeckList Serif default and live-update all role readers

* [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.

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2026-11-04 07:57:55 +01:00 • committed by GitHub
parent 13e7a3baaf
commit a791389c6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 140 additions and 18 deletions

View file

@ -10,6 +10,16 @@
#include <libcockatrice/models/deck_list/deck_list_model.h>
#include <qnamespace.h>
DeckListStyleProxy::DeckListStyleProxy(QObject *parent) : QIdentityProxyModel(parent)
{
// FontRole data reads the DeckList role live; rebroadcast so attached
// views re-query instead of waiting for an incidental repaint.
connect(themeManager, &ThemeManager::fontsChanged, this, [this] {
emit layoutAboutToBeChanged();
emit layoutChanged();
});
}
QVariant DeckListStyleProxy::data(const QModelIndex &index, int role) const
{
QModelIndex src = mapToSource(index);

View file

@ -8,7 +8,7 @@ class DeckListStyleProxy : public QIdentityProxyModel
{
Q_OBJECT
public:
using QIdentityProxyModel::QIdentityProxyModel;
explicit DeckListStyleProxy(QObject *parent = nullptr);
[[nodiscard]] QVariant data(const QModelIndex &index, int role) const override;
};

View file

@ -7,6 +7,7 @@
#include "../../../client/settings/cache_settings.h"
#include "../../pixel_map_generator.h"
#include "../interface/theme_manager.h"
#include "../settings_page/abstract_settings_page.h"
#include "../settings_page/appearance_settings_page.h"
#include "../settings_page/deck_editor_settings_page.h"
@ -203,6 +204,10 @@ void SettingsView::setupUi()
searchDelegate->setPageIcons(icons);
searchResultsView->viewport()->update();
});
// The search delegate reads the InterfaceDefault role at paint time, so a
// font change only needs a repaint, mirroring the theme change above.
connect(themeManager, &ThemeManager::fontsChanged, searchResultsView,
[this] { searchResultsView->viewport()->update(); });
// Build search index after pages are created
buildSearchIndex();

View file

@ -21,6 +21,10 @@
BarChartWidget::BarChartWidget(QWidget *parent) : QWidget(parent)
{
setMouseTracking(true);
// Labels read the InterfaceDefault role at paint time, so a font change
// only needs a repaint.
connect(themeManager, &ThemeManager::fontsChanged, this, [this] { update(); });
}
void BarChartWidget::setBars(const QVector<BarData> &newBars)

View file

@ -24,6 +24,10 @@ SegmentedBarWidget::SegmentedBarWidget(QString label, QVector<Segment> segments,
setMinimumWidth(36);
setMaximumWidth(50);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
// The label reads the InterfaceDefault role at paint time, so a font
// change only needs a repaint.
connect(themeManager, &ThemeManager::fontsChanged, this, [this] { update(); });
}
QSize SegmentedBarWidget::sizeHint() const

View file

@ -519,6 +519,19 @@ UserListWidget::UserListWidget(TabSupervisor *_tabSupervisor,
userTree->viewport()->update();
userTree->update();
});
// Divider headers store their font on the item, so re-apply the role
// family here; the painter reads the role live and needs only the
// repaint below.
connect(themeManager, &ThemeManager::fontsChanged, this, [this] {
QFont dividerFont = themeManager->appFont(AppFont::InterfaceDefault);
dividerFont.setBold(true);
for (auto it = sectionItems.constBegin(); it != sectionItems.constEnd(); ++it) {
it.value()->setFont(0, dividerFont);
it.value()->setSizeHint(0, QSize(0, QFontMetrics(dividerFont).height() + 16));
}
userTree->viewport()->update();
userTree->update();
});
}
QVBoxLayout *vbox = new QVBoxLayout;

View file

@ -101,6 +101,20 @@ TabDeveloper::TabDeveloper(TabSupervisor *_tabSupervisor, AbstractClient *_clien
central->setLayout(mainLayout);
setCentralWidget(central);
// Separator rows store their font on the item; re-apply the role family on
// font changes (value cells keep the default font and need only a repaint).
connect(themeManager, &ThemeManager::fontsChanged, this, [this] {
QFont separatorFont = themeManager->appFont(AppFont::InterfaceDefault);
separatorFont.setBold(true);
for (int row = 0; row < statsTable->rowCount(); ++row) {
auto *labelItem = statsTable->item(row, 0);
if (labelItem && !(labelItem->flags() & Qt::ItemIsSelectable)) {
labelItem->setFont(separatorFont);
}
}
statsTable->viewport()->update();
});
retranslateUi();
}

View file

@ -51,7 +51,12 @@ TabPublicDecks::TabPublicDecks(TabSupervisor *_tabSupervisor, AbstractClient *_c
titleLabel->setFont(QtUtils::boldFont(themeManager->appFont(AppFont::InterfaceDefault)));
};
applyTitleFont();
connect(themeManager, &ThemeManager::fontsChanged, this, applyTitleFont);
connect(themeManager, &ThemeManager::fontsChanged, this, [this, applyTitleFont] {
applyTitleFont();
// Preview cells paint with the live role font; repaint the grid so the
// new family shows without waiting for a scroll or hover.
flowWidget->update();
});
auto *headerLayout = new QHBoxLayout;
headerLayout->addWidget(titleLabel);

View file

@ -1,5 +1,6 @@
#include "card_completer_styler.h"
#include "../../interface/theme_manager.h"
#include "../cards/card_info_picture_enlarged_widget.h"
#include "card_completer_delegate.h"
#include "libcockatrice/card/database/card_database_querier.h"
@ -73,6 +74,10 @@ CardCompleterStyler::CardCompleterStyler(QCompleter *completer, QObject *parent)
popup->viewport()->setMouseTracking(true);
// The delegate reads the CardText role at paint time, so a font change
// only needs a repaint of the popup.
connect(themeManager, &ThemeManager::fontsChanged, popup, [popup] { popup->viewport()->update(); });
popup->installEventFilter(this);
popup->viewport()->installEventFilter(this);

View file

@ -28,6 +28,10 @@ DeckPreviewTagAdditionWidget::DeckPreviewTagAdditionWidget(QWidget *_parent, QSt
// Adjust widget size
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
// The tag text reads the InterfaceDefault role at paint time, so a font
// change only needs a repaint.
connect(themeManager, &ThemeManager::fontsChanged, this, [this] { update(); });
}
QSize DeckPreviewTagAdditionWidget::sizeHint() const

View file

@ -43,6 +43,10 @@ DeckPreviewTagDisplayWidget::DeckPreviewTagDisplayWidget(QWidget *parent, const
// Adjust widget size
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
// The tag text reads the InterfaceDefault role at paint time, so a font
// change only needs a repaint.
connect(themeManager, &ThemeManager::fontsChanged, this, [this] { update(); });
// Connect close button to the remove signal
// connect(closeButton, &QPushButton::clicked, this, &DeckPreviewTagDisplayWidget::tagClosed);
}