Calculate space requirement of menu items based on widest elements

Since icon, checkmark, text, and shortcut are each rendered aligned
within their own column, we need to take the widest of each element
into account when calculating the size requirement of each item. Otherwise
an item with very long text but no icon will get enough space for the
text, but no space for the icon, resulting in the text running over the
shortcut or edge of the menu.

Fortunately, QStyleOptionMenuItem provides us with the necessary
information.

Fixes: QTBUG-86754
Change-Id: I0cf0e9adfe480d1004106e7475e498e718bf027b
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit c8cb2409477bdc3bc41d6bbdfc5055441cda084f)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2021-06-04 23:03:43 +02:00 committed by Qt Cherry-pick Bot
parent c58d691938
commit 294b50e1f5

View File

@ -5185,18 +5185,19 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
QSize sz(csz);
if (mi->text.contains(QLatin1Char('\t')))
sz.rwidth() += 12; //as in QCommonStyle
bool checkable = mi->checkType != QStyleOptionMenuItem::NotCheckable;
if (!mi->icon.isNull()) {
const int pmSmall = pixelMetric(PM_SmallIconSize);
const QSize pmSize = mi->icon.actualSize(QSize(pmSmall, pmSmall));
sz.rwidth() += pmSize.width() + 4;
} else if (checkable) {
sz.rwidth() += std::max(mi->maxIconWidth, pmSize.width()) + 4;
} else if (mi->menuHasCheckableItems) {
QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
QRect checkmarkRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
sz.rwidth() += std::max(mi->maxIconWidth, checkmarkRect.width()) + 4;
} else {
sz.rwidth() += mi->maxIconWidth;
}
if (subRule.hasFont) {
QFontMetrics fm(subRule.font);
QFontMetrics fm(subRule.font.resolve(mi->font));
const QRect r = fm.boundingRect(QRect(), Qt::TextSingleLine | Qt::TextShowMnemonic, mi->text);
sz = sz.expandedTo(r.size());
}