Support styled menu icons in otherwise unstyled menu items
For a style sheet that defines a rule for the menu icon, but not for the item itself, we ignored the icon rule. Implement a separate rendering path for menu items with an icon. That rule takes precedence over a rule for menu item check indicators, as almost all styles reuse the icon for that. Factor the icon positioning and rendering code out into a private member function that we can reuse. Reduce amount of local variables to make the list of arguments for that member reasonable, the bit checks are cheap enough. Fixes: QTBUG-73966 Pick-to: 6.2 Change-Id: I64b6f5181e35527d0a163d9633a7414b50319829 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
1d48572b4e
commit
1ef8188a08
@ -3555,6 +3555,35 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
|
|||||||
baseStyle()->drawComplexControl(cc, opt, p, w);
|
baseStyle()->drawComplexControl(cc, opt, p, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QStyleSheetStyle::renderMenuItemIcon(const QStyleOptionMenuItem *mi, QPainter *p, const QWidget *w,
|
||||||
|
const QRect &rect, QRenderRule &subRule) const
|
||||||
|
{
|
||||||
|
const QIcon::Mode mode = mi->state & QStyle::State_Enabled
|
||||||
|
? (mi->state & QStyle::State_Selected ? QIcon::Active : QIcon::Normal)
|
||||||
|
: QIcon::Disabled;
|
||||||
|
const bool checked = mi->checkType != QStyleOptionMenuItem::NotCheckable && mi->checked;
|
||||||
|
const QPixmap pixmap(mi->icon.pixmap(pixelMetric(PM_SmallIconSize), mode,
|
||||||
|
checked ? QIcon::On : QIcon::Off));
|
||||||
|
const int pixw = pixmap.width() / pixmap.devicePixelRatio();
|
||||||
|
const int pixh = pixmap.height() / pixmap.devicePixelRatio();
|
||||||
|
QRenderRule iconRule = renderRule(w, mi, PseudoElement_MenuIcon);
|
||||||
|
if (!iconRule.hasGeometry()) {
|
||||||
|
iconRule.geo = new QStyleSheetGeometryData(pixw, pixh, pixw, pixh, -1, -1);
|
||||||
|
} else {
|
||||||
|
iconRule.geo->width = pixw;
|
||||||
|
iconRule.geo->height = pixh;
|
||||||
|
}
|
||||||
|
QRect iconRect = positionRect(w, subRule, iconRule, PseudoElement_MenuIcon, rect, mi->direction);
|
||||||
|
if (mi->direction == Qt::LeftToRight)
|
||||||
|
iconRect.moveLeft(iconRect.left());
|
||||||
|
else
|
||||||
|
iconRect.moveRight(iconRect.right());
|
||||||
|
iconRule.drawRule(p, iconRect);
|
||||||
|
QRect pmr(0, 0, pixw, pixh);
|
||||||
|
pmr.moveCenter(iconRect.center());
|
||||||
|
p->drawPixmap(pmr.topLeft(), pixmap);
|
||||||
|
}
|
||||||
|
|
||||||
void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p,
|
void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p,
|
||||||
const QWidget *w) const
|
const QWidget *w) const
|
||||||
{
|
{
|
||||||
@ -3835,42 +3864,18 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
|
|||||||
}
|
}
|
||||||
mi.palette.setBrush(QPalette::HighlightedText, mi.palette.brush(QPalette::ButtonText));
|
mi.palette.setBrush(QPalette::HighlightedText, mi.palette.brush(QPalette::ButtonText));
|
||||||
|
|
||||||
bool checkable = mi.checkType != QStyleOptionMenuItem::NotCheckable;
|
|
||||||
bool checked = checkable ? mi.checked : false;
|
|
||||||
|
|
||||||
bool dis = !(opt->state & QStyle::State_Enabled),
|
|
||||||
act = opt->state & QStyle::State_Selected;
|
|
||||||
|
|
||||||
int textRectOffset = m->maxIconWidth;
|
int textRectOffset = m->maxIconWidth;
|
||||||
if (!mi.icon.isNull()) {
|
if (!mi.icon.isNull()) {
|
||||||
QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
|
renderMenuItemIcon(&mi, p, w, opt->rect, subRule);
|
||||||
if (act && !dis)
|
|
||||||
mode = QIcon::Active;
|
|
||||||
const QPixmap pixmap(mi.icon.pixmap(pixelMetric(PM_SmallIconSize), mode, checked ? QIcon::On : QIcon::Off));
|
|
||||||
const int pixw = pixmap.width() / pixmap.devicePixelRatio();
|
|
||||||
const int pixh = pixmap.height() / pixmap.devicePixelRatio();
|
|
||||||
QRenderRule iconRule = renderRule(w, opt, PseudoElement_MenuIcon);
|
|
||||||
if (!iconRule.hasGeometry()) {
|
|
||||||
iconRule.geo = new QStyleSheetGeometryData(pixw, pixh, pixw, pixh, -1, -1);
|
|
||||||
} else {
|
|
||||||
iconRule.geo->width = pixw;
|
|
||||||
iconRule.geo->height = pixh;
|
|
||||||
}
|
|
||||||
QRect iconRect = positionRect(w, subRule, iconRule, PseudoElement_MenuIcon, opt->rect, opt->direction);
|
|
||||||
if (opt->direction == Qt::LeftToRight)
|
|
||||||
iconRect.moveLeft(iconRect.left());
|
|
||||||
else
|
|
||||||
iconRect.moveRight(iconRect.right());
|
|
||||||
iconRule.drawRule(p, iconRect);
|
|
||||||
QRect pmr(0, 0, pixw, pixh);
|
|
||||||
pmr.moveCenter(iconRect.center());
|
|
||||||
p->drawPixmap(pmr.topLeft(), pixmap);
|
|
||||||
} else if (mi.menuHasCheckableItems) {
|
} else if (mi.menuHasCheckableItems) {
|
||||||
QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
|
const bool checkable = mi.checkType != QStyleOptionMenuItem::NotCheckable;
|
||||||
|
const bool checked = checkable ? mi.checked : false;
|
||||||
|
|
||||||
|
const QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
|
||||||
const QRect cmRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
|
const QRect cmRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
|
||||||
if (checkable && (subSubRule.hasDrawable() || checked)) {
|
if (checkable && (subSubRule.hasDrawable() || checked)) {
|
||||||
QStyleOptionMenuItem newMi = mi;
|
QStyleOptionMenuItem newMi = mi;
|
||||||
if (!dis)
|
if (opt->state & QStyle::State_Enabled)
|
||||||
newMi.state |= State_Enabled;
|
newMi.state |= State_Enabled;
|
||||||
if (mi.checked)
|
if (mi.checked)
|
||||||
newMi.state |= State_On;
|
newMi.state |= State_On;
|
||||||
@ -3907,6 +3912,17 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
|
|||||||
mi.rect = positionRect(w, subRule, subRule2, PseudoElement_MenuRightArrow, opt->rect, mi.direction);
|
mi.rect = positionRect(w, subRule, subRule2, PseudoElement_MenuRightArrow, opt->rect, mi.direction);
|
||||||
drawPrimitive(arrow, &mi, p, w);
|
drawPrimitive(arrow, &mi, p, w);
|
||||||
}
|
}
|
||||||
|
} else if (!mi.icon.isNull() && hasStyleRule(w, PseudoElement_MenuIcon)) {
|
||||||
|
// we wouldn't be here if the item itself would be styled, so now we only want
|
||||||
|
// the text from the default style, and then draw the icon ourselves.
|
||||||
|
QStyleOptionMenuItem newMi = mi;
|
||||||
|
newMi.icon = {};
|
||||||
|
newMi.checkType = QStyleOptionMenuItem::NotCheckable;
|
||||||
|
if (rule.baseStyleCanDraw() && subRule.baseStyleCanDraw())
|
||||||
|
baseStyle()->drawControl(ce, &newMi, p, w);
|
||||||
|
else
|
||||||
|
ParentStyle::drawControl(ce, &newMi, p, w);
|
||||||
|
renderMenuItemIcon(&mi, p, w, opt->rect, subRule);
|
||||||
} else if (hasStyleRule(w, PseudoElement_MenuCheckMark) || hasStyleRule(w, PseudoElement_MenuRightArrow)) {
|
} else if (hasStyleRule(w, PseudoElement_MenuCheckMark) || hasStyleRule(w, PseudoElement_MenuRightArrow)) {
|
||||||
QWindowsStyle::drawControl(ce, &mi, p, w);
|
QWindowsStyle::drawControl(ce, &mi, p, w);
|
||||||
if (mi.checkType != QStyleOptionMenuItem::NotCheckable && !mi.checked) {
|
if (mi.checkType != QStyleOptionMenuItem::NotCheckable && !mi.checked) {
|
||||||
|
@ -169,6 +169,8 @@ private:
|
|||||||
static bool isNaturalChild(const QObject *obj);
|
static bool isNaturalChild(const QObject *obj);
|
||||||
static QPixmap loadPixmap(const QString &fileName, const QObject *context);
|
static QPixmap loadPixmap(const QString &fileName, const QObject *context);
|
||||||
bool initObject(const QObject *obj) const;
|
bool initObject(const QObject *obj) const;
|
||||||
|
void renderMenuItemIcon(const QStyleOptionMenuItem *mi, QPainter *p, const QWidget *w,
|
||||||
|
const QRect &rect, QRenderRule &subRule) const;
|
||||||
public:
|
public:
|
||||||
static int numinstances;
|
static int numinstances;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user