Skip to content

Commit 04b7fc2

Browse files
committed
Windows11Style: adjust QPushButton geometry
Provide PM_ButtonMargin and PM_MenuButtonIndicator values for the windows11 style so the base style calculates the size correctly. Also don't try to calculate values for rtl - simply use visualRect() instead. Use QIcon::paint() instead trying to figure out the correct position and rect for the icon by ourself. Pick-to: 6.10 6.9 Fixes: QTBUG-140145 Change-Id: I2da9f67ae83ec0e57c4587363e75d66cfa6555e4 Reviewed-by: Wladimir Leuschner <[email protected]>
1 parent d2c2dca commit 04b7fc2

File tree

1 file changed

+67
-63
lines changed

1 file changed

+67
-63
lines changed

src/plugins/styles/modernwindows/qwindows11style.cpp

Lines changed: 67 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ using namespace Qt::StringLiterals;
4444

4545
static constexpr int topLevelRoundingRadius = 8; //Radius for toplevel items like popups for round corners
4646
static constexpr int secondLevelRoundingRadius = 4; //Radius for second level items like hovered menu item round corners
47-
47+
static constexpr int contentItemHMargin = 4; // margin between content items (e.g. text and icon)
48+
static constexpr int contentHMargin = 2 * 3; // margin between rounded border and content (= rounded border margin * 3)
4849
namespace StyleOptionHelper
4950
{
5051
inline bool isChecked(const QStyleOption *option)
@@ -1421,80 +1422,57 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
14211422
break;
14221423
#endif // QT_CONFIG(progressbar)
14231424
case CE_PushButtonLabel:
1424-
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1425-
QRect textRect = btn->rect;
1425+
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
1426+
using namespace StyleOptionHelper;
1427+
const bool isEnabled = !isDisabled(option);
14261428

1427-
int tf = Qt::AlignVCenter|Qt::TextShowMnemonic;
1429+
QRect textRect = btn->rect.marginsRemoved(QMargins(contentHMargin, 0, contentHMargin, 0));
1430+
int tf = Qt::AlignCenter | Qt::TextShowMnemonic;
14281431
if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget))
14291432
tf |= Qt::TextHideMnemonic;
14301433

14311434
if (btn->features & QStyleOptionButton::HasMenu) {
1432-
int indicatorSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
1433-
QLineF menuSplitter;
1434-
QRectF indicatorRect;
1435-
painter->save();
1436-
painter->setFont(d->assetFont);
1435+
QPainterStateGuard psg(painter);
14371436

1438-
if (btn->direction == Qt::LeftToRight) {
1439-
indicatorRect = QRect(textRect.x() + textRect.width() - indicatorSize - 4, textRect.y(),2 * 4 + indicatorSize, textRect.height());
1440-
indicatorRect.adjust(0.5,-0.5,0.5,0.5);
1441-
menuSplitter = QLineF(indicatorRect.topLeft(),indicatorRect.bottomLeft());
1442-
textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
1443-
} else {
1444-
indicatorRect = QRect(textRect.x(), textRect.y(), textRect.x() + indicatorSize + 4, textRect.height());
1445-
indicatorRect.adjust(-0.5,-0.5,-0.5,0.5);
1446-
menuSplitter = QLineF(indicatorRect.topRight(),indicatorRect.bottomRight());
1447-
textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
1448-
}
1449-
painter->drawText(indicatorRect, Qt::AlignCenter, ChevronDownMed);
1450-
painter->setPen(WINUI3Colors[colorSchemeIndex][controlStrokePrimary]);
1451-
painter->drawLine(menuSplitter);
1452-
painter->restore();
1437+
const auto indSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
1438+
const auto indRect = QRect(btn->rect.right() - indSize - contentItemHMargin, textRect.top(),
1439+
indSize + contentItemHMargin, btn->rect.height());
1440+
const auto vindRect = visualRect(btn->direction, btn->rect, indRect);
1441+
textRect.setWidth(textRect.width() - indSize);
1442+
1443+
int fontSize = painter->font().pointSize();
1444+
QFont f(d->assetFont);
1445+
f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller
1446+
painter->setFont(f);
1447+
QColor penColor = option->palette.color(isEnabled ? QPalette::Active : QPalette::Disabled,
1448+
QPalette::Text);
1449+
if (isEnabled)
1450+
penColor.setAlpha(percentToAlpha(60.63)); // fillColorTextSecondary
1451+
painter->setPen(penColor);
1452+
painter->drawText(vindRect, Qt::AlignCenter, ChevronDownMed);
14531453
}
14541454
if (!btn->icon.isNull()) {
14551455
//Center both icon and text
1456-
QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
1456+
QIcon::Mode mode = isEnabled ? QIcon::Normal : QIcon::Disabled;
14571457
if (mode == QIcon::Normal && btn->state & State_HasFocus)
14581458
mode = QIcon::Active;
1459-
QIcon::State state = QIcon::Off;
1460-
if (btn->state & State_On)
1461-
state = QIcon::On;
1462-
1463-
QPixmap pixmap = btn->icon.pixmap(btn->iconSize, painter->device()->devicePixelRatio(), mode, state);
1464-
int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
1465-
int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
1466-
int labelWidth = pixmapWidth;
1467-
int labelHeight = pixmapHeight;
1468-
int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
1469-
if (!btn->text.isEmpty()) {
1470-
int textWidth = btn->fontMetrics.boundingRect(option->rect, tf, btn->text).width();
1471-
labelWidth += (textWidth + iconSpacing);
1472-
}
1473-
1474-
QRect iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
1475-
textRect.y() + (textRect.height() - labelHeight) / 2,
1476-
pixmapWidth, pixmapHeight);
1459+
QIcon::State state = isChecked(btn) ? QIcon::On : QIcon::Off;
14771460

1478-
iconRect = visualRect(btn->direction, textRect, iconRect);
1461+
int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
14791462

1480-
if (btn->direction == Qt::RightToLeft) {
1481-
tf |= Qt::AlignRight;
1482-
textRect.setRight(iconRect.left() - iconSpacing / 2);
1483-
} else {
1484-
tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead
1485-
textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing / 2);
1486-
}
1463+
QRect iconRect = QRect(textRect.x(), textRect.y(), btn->iconSize.width(), textRect.height());
1464+
QRect vIconRect = visualRect(btn->direction, btn->rect, iconRect);
1465+
textRect.setLeft(textRect.left() + iconRect.width() + iconSpacing);
14871466

1488-
if (btn->state & (State_On | State_Sunken))
1489-
iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget),
1490-
proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
1491-
painter->drawPixmap(iconRect, pixmap);
1492-
} else {
1493-
tf |= Qt::AlignHCenter;
1467+
if (isChecked(btn) || isPressed(btn))
1468+
vIconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget),
1469+
proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
1470+
btn->icon.paint(painter, vIconRect, Qt::AlignCenter, mode, state);
14941471
}
14951472

1473+
auto vTextRect = visualRect(btn->direction, btn->rect, textRect);
14961474
painter->setPen(controlTextColor(option));
1497-
proxy()->drawItemText(painter, textRect, tf, option->palette,btn->state & State_Enabled, btn->text);
1475+
proxy()->drawItemText(painter, vTextRect, tf, option->palette, isEnabled, btn->text);
14981476
}
14991477
break;
15001478
case CE_PushButtonBevel:
@@ -1524,8 +1502,6 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
15241502

15251503
painter->setPen(defaultButton ? WINUI3Colors[colorSchemeIndex][controlStrokeOnAccentSecondary]
15261504
: WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]);
1527-
if (flags & State_Raised)
1528-
painter->drawLine(rect.bottomLeft() + QPointF(4.0,0.0), rect.bottomRight() + QPointF(-4,0.0));
15291505
}
15301506
}
15311507
break;
@@ -1929,6 +1905,11 @@ QRect QWindows11Style::subElementRect(QStyle::SubElement element, const QStyleOp
19291905
case QStyle::SE_HeaderArrow:
19301906
ret = QCommonStyle::subElementRect(element, option, widget);
19311907
break;
1908+
case SE_PushButtonContents: {
1909+
int border = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
1910+
ret = option->rect.marginsRemoved(QMargins(border, border, border, border));
1911+
break;
1912+
}
19321913
default:
19331914
ret = QWindowsVistaStyle::subElementRect(element, option, widget);
19341915
}
@@ -2191,11 +2172,13 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o
21912172
if (size.width() == 0)
21922173
contentSize.rwidth() += 2;
21932174
break;
2194-
case CT_PushButton:
2175+
case CT_PushButton: {
21952176
contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
2196-
contentSize.rwidth() += 2 * 2; // the CE_PushButtonBevel draws a rounded rect with
2197-
// QMargins(2, 2, 2, 2) removed
2177+
// we want our own horizontal spacing
2178+
const int oldMargin = proxy()->pixelMetric(PM_ButtonMargin, option, widget);
2179+
contentSize.rwidth() += 2 * contentHMargin - oldMargin;
21982180
break;
2181+
}
21992182
default:
22002183
contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
22012184
break;
@@ -2210,6 +2193,7 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o
22102193
*/
22112194
int QWindows11Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
22122195
{
2196+
Q_D(const QWindows11Style);
22132197
int res = 0;
22142198

22152199
switch (metric) {
@@ -2245,6 +2229,26 @@ int QWindows11Style::pixelMetric(PixelMetric metric, const QStyleOption *option,
22452229
case QStyle::PM_SubMenuOverlap:
22462230
res = -1;
22472231
break;
2232+
case PM_MenuButtonIndicator: {
2233+
res = contentItemHMargin;
2234+
if (widget) {
2235+
const int fontSize = widget->font().pointSize();
2236+
QFont f(d->assetFont);
2237+
f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller
2238+
QFontMetrics fm(f);
2239+
res += fm.horizontalAdvance(ChevronDownMed);
2240+
} else {
2241+
res += 12;
2242+
}
2243+
break;
2244+
}
2245+
case PM_DefaultFrameWidth:
2246+
res = 2;
2247+
break;
2248+
case PM_ButtonShiftHorizontal:
2249+
case PM_ButtonShiftVertical:
2250+
res = 0;
2251+
break;
22482252
default:
22492253
res = QWindowsVistaStyle::pixelMetric(metric, option, widget);
22502254
}

0 commit comments

Comments
 (0)