Stylesheet: Fix tab layout when tab has a font and icons

Amends e3b2b12a912361af309302a4b1fc27c2206322af, which made the
style sheet calculate the font-dependent text size, but didn't
add the space needed for the close button or a tab icon.

QTabBar's layout code already adds the space needed for icons
and margins to the size; so instead of overwriting that size,
subtract the size needed by the normal font, and then add the
size needed for the font form the style rule, considering both
vertical and horizontal tab bars.

Fix the test case to style only one tab rather than the entire
tab bar, otherwise the font is applied to the entire tab bar,
and not just to a specific tab, which is the style sheet style
code in question.

Pick-to: 6.2 6.3
Task-number: QTBUG-6905
Change-Id: Ieed0ba146a32e81229419adecaf41f467cfd5959
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Volker Hilsheimer 2022-01-21 15:13:19 +01:00
parent 0b7b3a069e
commit 55433f90af
2 changed files with 61 additions and 20 deletions

View File

@ -5414,13 +5414,25 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
if (subRule.hasBox() || !subRule.hasNativeBorder())
sz = csz + QSize(vertical ? 0 : spaceForIcon, vertical ? spaceForIcon : 0);
if (subRule.hasFont) {
QFont ruleFont = subRule.font.resolve(w->font());
QFontMetrics fm(ruleFont);
const QSize textSize = fm.size(Qt::TextShowMnemonic, text)
+ QSize(pixelMetric(PM_TabBarTabHSpace, opt, w),
pixelMetric(PM_TabBarTabVSpace, opt, w));
sz = sz.expandedTo(vertical ? textSize.transposed() : textSize);
// first we remove the space needed for the text using the default font
const QSize oldTextSize = opt->fontMetrics.size(Qt::TextShowMnemonic, text);
(vertical ? sz.rheight() : sz.rwidth()) -= oldTextSize.width();
// then we add the space needed when using the rule font to the relevant
// dimension, and constraint the other dimension to the maximum to make
// sure we don't grow, but also don't clip icons or buttons.
const QFont ruleFont = subRule.font.resolve(w->font());
const QFontMetrics fm(ruleFont);
const QSize textSize = fm.size(Qt::TextShowMnemonic, text);
if (vertical) {
sz.rheight() += textSize.width();
sz.rwidth() = qMax(textSize.height(), sz.width());
} else {
sz.rwidth() += textSize.width();
sz.rheight() = qMax(textSize.height(), sz.height());
}
}
return subRule.boxSize(subRule.adjustSize(sz));
}
sz = subRule.adjustSize(csz);

View File

@ -1220,20 +1220,31 @@ void tst_QStyleSheetStyle::tabAlignment()
void tst_QStyleSheetStyle::tabFont_data()
{
QTest::addColumn<int>("pixelSize");
QTest::addColumn<QFont>("tabFont");
QTest::addColumn<QTabWidget::TabPosition>("tabPosition");
QTest::addColumn<bool>("closable");
QTest::newRow("medium, horizontal") << 24 << QTabWidget::North;
QTest::newRow("large, vertical") << 36 << QTabWidget::West;
QFont medium;
medium.setPixelSize(24);
QFont large;
large.setPixelSize(36);
QFont bold;
bold.setBold(true);
QTest::newRow("medium, horizontal") << medium << QTabWidget::North << false;
QTest::newRow("large, vertical") << large << QTabWidget::West << false;
QTest::newRow("bold, horizontal, closable") << bold << QTabWidget::North << true;
QTest::newRow("bold, vertical, closable") << bold << QTabWidget::West << true;
}
#include <QApplication>
void tst_QStyleSheetStyle::tabFont()
{
QFETCH(int, pixelSize);
QFETCH(QFont, tabFont);
QFETCH(QTabWidget::TabPosition, tabPosition);
QFETCH(bool, closable);
const bool vertical = tabPosition == QTabWidget::West || tabPosition == QTabWidget::East;
const QString tab0Text("Tab title");
const QString tab1Text("Very Long Tab title");
// macOS style centers tabs and messes up the test
QWindowsStyle windowsStyle;
@ -1242,18 +1253,22 @@ void tst_QStyleSheetStyle::tabFont()
topLevel.setWindowTitle(QTest::currentTestFunction());
QTabWidget tabWidget;
tabWidget.setStyle(&windowsStyle);
tabWidget.addTab(new QWidget,"Tab title");
tabWidget.setTabPosition(tabPosition);
tabWidget.addTab(new QWidget, tab0Text);
tabWidget.addTab(new QWidget, tab1Text);
QTabWidget styledWidget;
styledWidget.setStyle(&windowsStyle);
styledWidget.setTabPosition(tabPosition);
styledWidget.addTab(new QWidget,"Tab title");
styledWidget.addTab(new QWidget, tab0Text);
styledWidget.addTab(new QWidget, tab1Text);
QTabBar *bar = tabWidget.tabBar();
QTabBar *styledBar = styledWidget.tabBar();
QVERIFY(bar && styledBar);
bar->setStyle(&windowsStyle);
bar->setTabsClosable(closable);
styledBar->setStyle(&windowsStyle);
styledBar->setTabsClosable(closable);
QBoxLayout box(vertical ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom);
box.addWidget(&tabWidget);
@ -1265,22 +1280,36 @@ void tst_QStyleSheetStyle::tabFont()
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
const QFont defaultFont = tabWidget.font();
if (QFontMetrics(defaultFont).size(Qt::TextShowMnemonic, tab0Text).width() >=
QFontMetrics(tabFont).size(Qt::TextShowMnemonic, tab0Text).width()) {
QSKIP("The used font is not larger when bold");
}
const QRect defaultRect = bar->tabRect(0);
QCOMPARE(styledBar->tabRect(0), defaultRect);
QFont font;
font.setPointSize(pixelSize);
tabWidget.setFont(font);
tabWidget.setFont(tabFont);
const QRect rectWithFont = bar->tabRect(0);
if (vertical)
QVERIFY(rectWithFont.height() > defaultRect.height());
else
QVERIFY(rectWithFont.width() > defaultRect.width());
styledWidget.setStyleSheet(QString("QTabBar { font-size: %1pt; }").arg(pixelSize));
QString styleSheet = "QTabBar::tab:first {";
if (tabFont.pixelSize() != -1)
styleSheet += QString(" font-size: %1px;").arg(tabFont.pixelSize());
if (tabFont.bold())
styleSheet += " font-weight: bold;";
styleSheet += "}";
styledWidget.setStyleSheet(styleSheet);
const QRect rectWithStyle = styledBar->tabRect(0);
QCOMPARE(rectWithStyle.size(), rectWithFont.size());
if (vertical)
QCOMPARE(rectWithStyle.height(), rectWithFont.height());
else
QCOMPARE(rectWithStyle.width(), rectWithFont.width());
}
void tst_QStyleSheetStyle::attributesList()