Utils: Move drawCardBg from WelcomePageHelpers to StyleHelper

Conveniently draw smooth rounded rects from anywhere.

Change-Id: Ifb2710c23b88eb21a0bd669882e0ca65dd85114e
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Alessandro Portale
2025-04-15 17:47:26 +02:00
parent 29f4743dd5
commit d9d27c2ba8
6 changed files with 45 additions and 44 deletions

View File

@@ -498,6 +498,25 @@ void StyleHelper::drawPanelBgRect(QPainter *painter, const QRectF &rect, const Q
} }
} }
void StyleHelper::drawCardBg(QPainter *painter, const QRectF &rect,
const QBrush &fill, const QPen &pen, qreal rounding)
{
const qreal strokeWidth = pen.style() == Qt::NoPen ? 0 : pen.widthF();
const qreal strokeShrink = strokeWidth / 2;
const QRectF itemRectAdjusted = rect.adjusted(strokeShrink, strokeShrink,
-strokeShrink, -strokeShrink);
const qreal roundingAdjusted = rounding - strokeShrink;
QPainterPath itemOutlinePath;
itemOutlinePath.addRoundedRect(itemRectAdjusted, roundingAdjusted, roundingAdjusted);
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setBrush(fill);
painter->setPen(pen);
painter->drawPath(itemOutlinePath);
painter->restore();
}
void StyleHelper::menuGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect) void StyleHelper::menuGradient(QPainter *painter, const QRect &spanRect, const QRect &clipRect)
{ {
if (StyleHelper::usePixmapCache()) { if (StyleHelper::usePixmapCache()) {

View File

@@ -5,6 +5,7 @@
#include "utils_global.h" #include "utils_global.h"
#include <QPen>
#include <QStyle> #include <QStyle>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@@ -22,6 +23,7 @@ namespace Utils::StyleHelper {
const unsigned int DEFAULT_BASE_COLOR = 0x666666; const unsigned int DEFAULT_BASE_COLOR = 0x666666;
const int progressFadeAnimationDuration = 600; const int progressFadeAnimationDuration = 600;
constexpr qreal defaultCardBgRounding = 3.75;
constexpr char C_ALIGN_ARROW[] = "alignarrow"; constexpr char C_ALIGN_ARROW[] = "alignarrow";
constexpr char C_DRAW_LEFT_BORDER[] = "drawleftborder"; constexpr char C_DRAW_LEFT_BORDER[] = "drawleftborder";
@@ -140,6 +142,9 @@ QTCREATOR_UTILS_EXPORT void drawMinimalArrow(QStyle::PrimitiveElement element, Q
QTCREATOR_UTILS_EXPORT void drawPanelBgRect(QPainter *painter, const QRectF &rect, QTCREATOR_UTILS_EXPORT void drawPanelBgRect(QPainter *painter, const QRectF &rect,
const QBrush &brush); const QBrush &brush);
QTCREATOR_UTILS_EXPORT void drawCardBg(QPainter *painter, const QRectF &rect, const QBrush &fill,
const QPen &pen = QPen(Qt::NoPen),
qreal rounding = defaultCardBgRounding);
// Gradients used for panels // Gradients used for panels
QTCREATOR_UTILS_EXPORT void horizontalGradient(QPainter *painter, const QRect &spanRect, QTCREATOR_UTILS_EXPORT void horizontalGradient(QPainter *painter, const QRect &spanRect,

View File

@@ -60,25 +60,6 @@ void setBackgroundColor(QWidget *widget, Theme::Color colorRole)
widget->setAutoFillBackground(true); widget->setAutoFillBackground(true);
} }
void drawCardBackground(QPainter *painter, const QRectF &rect,
const QBrush &fill, const QPen &pen, qreal rounding)
{
const qreal strokeWidth = pen.style() == Qt::NoPen ? 0 : pen.widthF();
const qreal strokeShrink = strokeWidth / 2;
const QRectF itemRectAdjusted = rect.adjusted(strokeShrink, strokeShrink,
-strokeShrink, -strokeShrink);
const qreal roundingAdjusted = rounding - strokeShrink;
QPainterPath itemOutlinePath;
itemOutlinePath.addRoundedRect(itemRectAdjusted, roundingAdjusted, roundingAdjusted);
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setBrush(fill);
painter->setPen(pen);
painter->drawPath(itemOutlinePath);
painter->restore();
}
QWidget *createRule(Qt::Orientation orientation, QWidget *parent) QWidget *createRule(Qt::Orientation orientation, QWidget *parent)
{ {
auto rule = new QWidget(parent); auto rule = new QWidget(parent);
@@ -227,7 +208,7 @@ void Button::paintEvent(QPaintEvent *event)
: Theme::Token_Accent_Default)) : Theme::Token_Accent_Default))
: Theme::Token_Foreground_Subtle; : Theme::Token_Foreground_Subtle;
const QBrush fill(creatorColor(color)); const QBrush fill(creatorColor(color));
drawCardBackground(&p, bgR, fill, QPen(Qt::NoPen), brRectRounding); StyleHelper::drawCardBg(&p, bgR, fill, QPen(Qt::NoPen), brRectRounding);
break; break;
} }
case LargeSecondary: case LargeSecondary:
@@ -236,7 +217,7 @@ void Button::paintEvent(QPaintEvent *event)
: Theme::Token_Stroke_Subtle; : Theme::Token_Stroke_Subtle;
const qreal width = hovered ? 2.0 : 1.0; const qreal width = hovered ? 2.0 : 1.0;
const QPen outline(creatorColor(color), width); const QPen outline(creatorColor(color), width);
drawCardBackground(&p, bgR, QBrush(Qt::NoBrush), outline, brRectRounding); StyleHelper::drawCardBg(&p, bgR, QBrush(Qt::NoBrush), outline, brRectRounding);
break; break;
} }
case LargeTertiary: case LargeTertiary:
@@ -247,14 +228,14 @@ void Button::paintEvent(QPaintEvent *event)
: (hovered ? Theme::Token_Foreground_Muted : (hovered ? Theme::Token_Foreground_Muted
: Theme::Token_Foreground_Subtle)) : Theme::Token_Foreground_Subtle))
: Theme::Token_Foreground_Subtle; : Theme::Token_Foreground_Subtle;
drawCardBackground(&p, bgR, creatorColor(bg), creatorColor(border), brRectRounding); StyleHelper::drawCardBg(&p, bgR, creatorColor(bg), creatorColor(border), brRectRounding);
break; break;
} }
case SmallList: { case SmallList: {
if (isChecked() || hovered) { if (isChecked() || hovered) {
const QBrush fill(creatorColor(isChecked() ? Theme::Token_Foreground_Muted const QBrush fill(creatorColor(isChecked() ? Theme::Token_Foreground_Muted
: Theme::Token_Foreground_Subtle)); : Theme::Token_Foreground_Subtle));
drawCardBackground(&p, bgR, fill, QPen(Qt::NoPen), brRectRounding); StyleHelper::drawCardBg(&p, bgR, fill, QPen(Qt::NoPen), brRectRounding);
} }
break; break;
} }
@@ -264,7 +245,7 @@ void Button::paintEvent(QPaintEvent *event)
const QBrush fill(hovered ? creatorColor(Theme::Token_Foreground_Subtle) const QBrush fill(hovered ? creatorColor(Theme::Token_Foreground_Subtle)
: QBrush(Qt::NoBrush)); : QBrush(Qt::NoBrush));
const QPen outline(hovered ? QPen(Qt::NoPen) : creatorColor(Theme::Token_Stroke_Subtle)); const QPen outline(hovered ? QPen(Qt::NoPen) : creatorColor(Theme::Token_Stroke_Subtle));
drawCardBackground(&p, bgR, fill, outline, brRectRounding); StyleHelper::drawCardBg(&p, bgR, fill, outline, brRectRounding);
break; break;
} }
} }
@@ -393,7 +374,7 @@ static void paintCommonBackground(QPainter *p, const QRectF &rect, const QWidget
: Theme::Token_Stroke_Subtle)) : Theme::Token_Stroke_Subtle))
: Theme::Token_Foreground_Subtle; : Theme::Token_Foreground_Subtle;
const QPen pen(creatorColor(c)); const QPen pen(creatorColor(c));
drawCardBackground(p, rect, fill, pen); StyleHelper::drawCardBg(p, rect, fill, pen);
} }
void SearchBox::paintEvent(QPaintEvent *event) void SearchBox::paintEvent(QPaintEvent *event)
@@ -536,7 +517,7 @@ void Switch::paintEvent([[maybe_unused]] QPaintEvent *event)
const QPen outline = checkedEnabled ? QPen(Qt::NoPen) const QPen outline = checkedEnabled ? QPen(Qt::NoPen)
: creatorColor(hovered ? Theme::Token_Stroke_Muted : creatorColor(hovered ? Theme::Token_Stroke_Muted
: Theme::Token_Stroke_Subtle); : Theme::Token_Stroke_Subtle);
drawCardBackground(&p, trackR, fill, outline, trackRounding); StyleHelper::drawCardBg(&p, trackR, fill, outline, trackRounding);
} }
{ // track label { // track label
const QColor color = creatorColor(isEnabled() ? (isChecked() ? Theme::Token_Basic_White const QColor color = creatorColor(isEnabled() ? (isChecked() ? Theme::Token_Basic_White
@@ -550,7 +531,7 @@ void Switch::paintEvent([[maybe_unused]] QPaintEvent *event)
} else { } else {
const QRect offLabelR(trackX + switchTrackS.width() - trackRounding - labelS / 2 - 1, const QRect offLabelR(trackX + switchTrackS.width() - trackRounding - labelS / 2 - 1,
labelY, labelS, labelS); labelY, labelS, labelS);
drawCardBackground(&p, offLabelR, Qt::NoBrush, color, labelS / 2); StyleHelper::drawCardBg(&p, offLabelR, Qt::NoBrush, color, labelS / 2);
} }
} }
{ // knob { // knob
@@ -566,7 +547,7 @@ void Switch::paintEvent([[maybe_unused]] QPaintEvent *event)
: Theme::Token_Foreground_Default); : Theme::Token_Foreground_Default);
const QPen outline = checkedEnabled ? QPen(Qt::NoPen) const QPen outline = checkedEnabled ? QPen(Qt::NoPen)
: creatorColor(Theme::Token_Stroke_Subtle); : creatorColor(Theme::Token_Stroke_Subtle);
drawCardBackground(&p, thumbR, fill, outline, thumbRounding); StyleHelper::drawCardBg(&p, thumbR, fill, outline, thumbRounding);
} }
{ // switch text label { // switch text label
const int switchAndGapWidth = switchTrackS.width() + HGapS; const int switchAndGapWidth = switchTrackS.width() + HGapS;
@@ -1013,7 +994,7 @@ void ListItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
const QColor fill(themeColor(hovered ? cardHoverBackground : cardDefaultBackground)); const QColor fill(themeColor(hovered ? cardHoverBackground : cardDefaultBackground));
const QPen pen(themeColor(hovered ? cardHoverStroke : cardDefaultStroke), itemOutlineWidth); const QPen pen(themeColor(hovered ? cardHoverStroke : cardDefaultStroke), itemOutlineWidth);
WelcomePageHelpers::drawCardBackground(painter, bgR, fill, pen, itemCornerRounding); StyleHelper::drawCardBg(painter, bgR, fill, pen, itemCornerRounding);
const int shiftY = thumbnailAreaR.bottom(); const int shiftY = thumbnailAreaR.bottom();
int offset = 0; int offset = 0;
@@ -1086,8 +1067,8 @@ void ListItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
QPainter maskPainter(&mask); QPainter maskPainter(&mask);
const QRect maskR = bgR.translated(filterMargin, filterMargin) const QRect maskR = bgR.translated(filterMargin, filterMargin)
.adjusted(1, 1, -1, -1); .adjusted(1, 1, -1, -1);
WelcomePageHelpers::drawCardBackground(&maskPainter, maskR, StyleHelper::drawCardBg(&maskPainter, maskR, Qt::white, Qt::NoPen,
Qt::white, Qt::NoPen, itemCornerRounding); itemCornerRounding);
thumbnail.setAlphaChannel(mask); thumbnail.setAlphaChannel(mask);
m_blurredThumbnail = QPixmap::fromImage( m_blurredThumbnail = QPixmap::fromImage(

View File

@@ -58,14 +58,10 @@ public:
}; };
CORE_EXPORT void setBackgroundColor(QWidget *widget, Utils::Theme::Color colorRole); CORE_EXPORT void setBackgroundColor(QWidget *widget, Utils::Theme::Color colorRole);
constexpr qreal defaultCardBackgroundRounding = 3.75;
constexpr Utils::Theme::Color cardDefaultBackground = Utils::Theme::Token_Background_Muted; constexpr Utils::Theme::Color cardDefaultBackground = Utils::Theme::Token_Background_Muted;
constexpr Utils::Theme::Color cardDefaultStroke = Utils::Theme::Token_Stroke_Subtle; constexpr Utils::Theme::Color cardDefaultStroke = Utils::Theme::Token_Stroke_Subtle;
constexpr Utils::Theme::Color cardHoverBackground = Utils::Theme::Token_Background_Subtle; constexpr Utils::Theme::Color cardHoverBackground = Utils::Theme::Token_Background_Subtle;
constexpr Utils::Theme::Color cardHoverStroke = cardDefaultStroke; constexpr Utils::Theme::Color cardHoverStroke = cardDefaultStroke;
CORE_EXPORT void drawCardBackground(QPainter *painter, const QRectF &rect,
const QBrush &fill, const QPen &pen = QPen(Qt::NoPen),
qreal rounding = defaultCardBackgroundRounding);
CORE_EXPORT QWidget *createRule(Qt::Orientation orientation, QWidget *parent = nullptr); CORE_EXPORT QWidget *createRule(Qt::Orientation orientation, QWidget *parent = nullptr);
CORE_EXPORT void applyTf(QLabel *label, const TextFormat &tf, bool singleLine = true); CORE_EXPORT void applyTf(QLabel *label, const TextFormat &tf, bool singleLine = true);

View File

@@ -333,7 +333,7 @@ public:
creatorColor(selected ? Theme::Token_Stroke_Strong creatorColor(selected ? Theme::Token_Stroke_Strong
: hovered ? WelcomePageHelpers::cardHoverStroke : hovered ? WelcomePageHelpers::cardHoverStroke
: WelcomePageHelpers::cardDefaultStroke); : WelcomePageHelpers::cardDefaultStroke);
WelcomePageHelpers::drawCardBackground(painter, bgR, fillColor, strokeColor); StyleHelper::drawCardBg(painter, bgR, fillColor, strokeColor);
} }
render(painter, bgR.topLeft(), {}, QWidget::DrawChildren); render(painter, bgR.topLeft(), {}, QWidget::DrawChildren);
@@ -353,7 +353,8 @@ public:
circleSize, circleSize); circleSize, circleSize);
const QColor fillColor = creatorColor(Theme::Token_Foreground_Muted); const QColor fillColor = creatorColor(Theme::Token_Foreground_Muted);
const QColor strokeColor = creatorColor(Theme::Token_Stroke_Subtle); const QColor strokeColor = creatorColor(Theme::Token_Stroke_Subtle);
drawCardBackground(painter, smallCircle, fillColor, strokeColor, circleSize / 2); StyleHelper::drawCardBg(painter, smallCircle, fillColor, strokeColor,
circleSize / 2);
painter->setFont(countTF.font()); painter->setFont(countTF.font());
painter->setPen(countTF.color()); painter->setPen(countTF.color());
@@ -913,7 +914,7 @@ QPixmap itemIcon(const QModelIndex &index, Size size)
gradient.setStops(gradientStops); gradient.setStops(gradientStops);
if (!isEnabled) if (!isEnabled)
p.setOpacity(iconOpacityDisabled); p.setOpacity(iconOpacityDisabled);
WelcomePageHelpers::drawCardBackground(&p, iconBgR, gradient, Qt::NoPen, iconRectRounding); StyleHelper::drawCardBg(&p, iconBgR, gradient, Qt::NoPen, iconRectRounding);
icon.paint(&p, iconBgR); icon.paint(&p, iconBgR);
return pixmap; return pixmap;
@@ -939,9 +940,8 @@ QPixmap itemBadge(const QModelIndex &index, [[maybe_unused]] Size size)
pixmap.setDevicePixelRatio(dpr); pixmap.setDevicePixelRatio(dpr);
QPainter p(&pixmap); QPainter p(&pixmap);
WelcomePageHelpers::drawCardBackground(&p, badgeR, StyleHelper::drawCardBg(&p, badgeR, creatorColor(Theme::Token_Notification_Neutral_Default),
creatorColor(Theme::Token_Notification_Neutral_Default), Qt::NoPen, iconRectRounding);
Qt::NoPen, iconRectRounding);
p.setFont(font); p.setFont(font);
p.setPen(badgeTF.color()); p.setPen(badgeTF.color());
p.drawText(badgeR, Qt::AlignCenter, badgeText); p.drawText(badgeR, Qt::AlignCenter, badgeText);

View File

@@ -228,7 +228,7 @@ static void drawBackgroundRect(QPainter *painter, const QRectF &rect, bool hover
const QColor fill(creatorColor(hovered ? cardHoverBackground : cardDefaultBackground)); const QColor fill(creatorColor(hovered ? cardHoverBackground : cardDefaultBackground));
const QPen pen(creatorColor(hovered ? cardHoverStroke : cardDefaultStroke)); const QPen pen(creatorColor(hovered ? cardHoverStroke : cardDefaultStroke));
WelcomePageHelpers::drawCardBackground(painter, rect, fill, pen, defaultCardBackgroundRounding); StyleHelper::drawCardBg(painter, rect, fill, pen, StyleHelper::defaultCardBgRounding);
} }
class BaseDelegate : public QAbstractItemDelegate class BaseDelegate : public QAbstractItemDelegate
@@ -281,8 +281,8 @@ public:
void paintEvent([[maybe_unused]] QPaintEvent *event) override void paintEvent([[maybe_unused]] QPaintEvent *event) override
{ {
QPainter painter(this); QPainter painter(this);
const QRect bgR = rect().adjusted(-defaultCardBackgroundRounding, 0, const QRect bgR = rect().adjusted(-StyleHelper::defaultCardBgRounding, 0, 0,
0, isChecked() ? defaultCardBackgroundRounding : 0); isChecked() ? StyleHelper::defaultCardBgRounding : 0);
drawBackgroundRect(&painter, bgR, underMouse()); drawBackgroundRect(&painter, bgR, underMouse());
static const QPixmap arrowDown = static const QPixmap arrowDown =