Cockatrice/cockatrice/src/interface/widgets/general/home_styled_button.cpp
Lukas Brübach 28c200e950 [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-03 18:22:39 +01:00

125 lines
4.4 KiB
C++

#include "home_styled_button.h"
#include "../../theme_manager.h"
#include <QBrush>
#include <QFont>
#include <QFontMetrics>
#include <QPainter>
#include <QPainterPath>
#include <QPen>
#include <QPointF>
#include <QSize>
#include <QSizePolicy>
#include <QStyle>
#include <QStyleOptionButton>
#include <QtGlobal>
#include <qnamespace.h>
class QWidget;
HomeStyledButton::HomeStyledButton(const QString &text, QPair<QColor, QColor> _gradientColors, QWidget *parent)
: QPushButton(text, parent), gradientColors(_gradientColors)
{
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)
{
gradientColors = colors;
setStyleSheet(generateButtonStylesheet(gradientColors));
}
QString HomeStyledButton::generateButtonStylesheet(const QPair<QColor, QColor> &colors)
{
QColor baseGradientStart = colors.first;
QColor baseGradientEnd = colors.second;
QColor hoverGradientStart = baseGradientStart.lighter(120); // 20% lighter
QColor hoverGradientEnd = baseGradientEnd.lighter(120);
QColor pressedGradientStart = baseGradientStart.darker(130); // 30% darker
QColor pressedGradientEnd = baseGradientEnd.darker(130);
// Disabled: more gray, less saturated
QColor disabledGradientStart = baseGradientStart.toHsv();
disabledGradientStart.setHsv(disabledGradientStart.hue(), disabledGradientStart.saturation() * 0.2,
disabledGradientStart.value() * 0.6);
QColor disabledGradientEnd = baseGradientEnd.toHsv();
disabledGradientEnd.setHsv(disabledGradientEnd.hue(), disabledGradientEnd.saturation() * 0.2,
disabledGradientEnd.value() * 0.6);
return QString(R"(
QPushButton {
padding: 30px;
color: white;
border: 2px solid %1;
border-radius: 20px;
background: qlineargradient(x1:0, y1:1, x2:0, y2:0,
stop:0 %2, stop:1 %3);
}
QPushButton:hover {
background: qlineargradient(x1:0, y1:1, x2:0, y2:0,
stop:0 %4, stop:1 %5);
}
QPushButton:pressed {
background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 %6, stop:1 %7);
}
QPushButton:disabled {
color: #aaaaaa;
border: 2px solid #888888;
background: qlineargradient(x1:0, y1:1, x2:0, y2:0,
stop:0 %8, stop:1 %9);
}
)")
.arg(baseGradientStart.name())
.arg(baseGradientStart.name())
.arg(baseGradientEnd.name())
.arg(hoverGradientStart.name())
.arg(hoverGradientEnd.name())
.arg(pressedGradientStart.name())
.arg(pressedGradientEnd.name())
.arg(disabledGradientStart.name())
.arg(disabledGradientEnd.name());
}
void HomeStyledButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event); // Event is just used for update clipping, we redraw the whole widget.
QStyleOptionButton opt;
initStyleOption(&opt);
opt.text.clear(); // prevent style from drawing text
QPainter painter(this);
style()->drawControl(QStyle::CE_PushButton, &opt, &painter, this);
// Draw white text with a black outline
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::TextAntialiasing);
QFontMetrics fm(font());
QSize textSize = fm.size(Qt::TextSingleLine, text());
QPointF center((width() - textSize.width()) / 2.0, (height() + textSize.height() / 2.0) / 2.0);
QPainterPath path;
path.addText(center, font(), text());
QPen pen(Qt::black, 4.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter.strokePath(path, pen);
painter.fillPath(path, Qt::white);
}