QTabBar: take a style sheet's font into account when laying out tabs
If a tab has a font assigned to it through a style sheet, then take the font size into account when calculating the contents rectangle. Add a test, which hardcodes the windows style to avoid flaky behavior when e.g. macOS lays tabs out in the center. Fixes: QTBUG-92988 Change-Id: Ifb0ac97db7647cc25367972737be8878e50f6040 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> (cherry picked from commit e3b2b12a912361af309302a4b1fc27c2206322af) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
b721079032
commit
ca4d48595b
@ -5220,15 +5220,26 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
|
|||||||
#if QT_CONFIG(tabbar)
|
#if QT_CONFIG(tabbar)
|
||||||
case CT_TabBarTab: {
|
case CT_TabBarTab: {
|
||||||
QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab);
|
QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab);
|
||||||
if (subRule.hasBox() || !subRule.hasNativeBorder()) {
|
if (subRule.hasBox() || !subRule.hasNativeBorder() || subRule.hasFont) {
|
||||||
int spaceForIcon = 0;
|
int spaceForIcon = 0;
|
||||||
bool vertical = false;
|
bool vertical = false;
|
||||||
|
QString text;
|
||||||
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
|
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
|
||||||
if (!tab->icon.isNull())
|
if (!tab->icon.isNull())
|
||||||
spaceForIcon = 6 /* icon offset */ + 4 /* spacing */ + 2 /* magic */; // ###: hardcoded to match with common style
|
spaceForIcon = 6 /* icon offset */ + 4 /* spacing */ + 2 /* magic */; // ###: hardcoded to match with common style
|
||||||
vertical = verticalTabs(tab->shape);
|
vertical = verticalTabs(tab->shape);
|
||||||
|
text = tab->text;
|
||||||
|
}
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
sz = csz + QSize(vertical ? 0 : spaceForIcon, vertical ? spaceForIcon : 0);
|
|
||||||
return subRule.boxSize(subRule.adjustSize(sz));
|
return subRule.boxSize(subRule.adjustSize(sz));
|
||||||
}
|
}
|
||||||
sz = subRule.adjustSize(csz);
|
sz = subRule.adjustSize(csz);
|
||||||
@ -6058,13 +6069,17 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c
|
|||||||
case SE_TabBarTabLeftButton:
|
case SE_TabBarTabLeftButton:
|
||||||
case SE_TabBarTabRightButton: {
|
case SE_TabBarTabRightButton: {
|
||||||
QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab);
|
QRenderRule subRule = renderRule(w, opt, PseudoElement_TabBarTab);
|
||||||
if (subRule.hasBox() || !subRule.hasNativeBorder()) {
|
if (subRule.hasBox() || !subRule.hasNativeBorder() || subRule.hasFont) {
|
||||||
if (se == SE_TabBarTabText) {
|
if (se == SE_TabBarTabText) {
|
||||||
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
|
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
|
||||||
const QTabBar *bar = qobject_cast<const QTabBar *>(w);
|
const QTabBar *bar = qobject_cast<const QTabBar *>(w);
|
||||||
const QRect optRect = bar && tab->tabIndex != -1 ? bar->tabRect(tab->tabIndex) : opt->rect;
|
const QRect optRect = bar && tab->tabIndex != -1 ? bar->tabRect(tab->tabIndex) : opt->rect;
|
||||||
const QRect r = positionRect(w, subRule, PseudoElement_TabBarTab, optRect, opt->direction);
|
const QRect r = positionRect(w, subRule, PseudoElement_TabBarTab, optRect, opt->direction);
|
||||||
QStyleOptionTab tabCopy(*tab);
|
QStyleOptionTab tabCopy(*tab);
|
||||||
|
if (subRule.hasFont) {
|
||||||
|
const QFont ruleFont = w ? subRule.font.resolve(w->font()) : subRule.font;
|
||||||
|
tabCopy.fontMetrics = QFontMetrics(ruleFont);
|
||||||
|
}
|
||||||
tabCopy.rect = subRule.contentsRect(r);
|
tabCopy.rect = subRule.contentsRect(r);
|
||||||
return ParentStyle::subElementRect(se, &tabCopy, w);
|
return ParentStyle::subElementRect(se, &tabCopy, w);
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,8 @@ private slots:
|
|||||||
#endif
|
#endif
|
||||||
void background();
|
void background();
|
||||||
void tabAlignment();
|
void tabAlignment();
|
||||||
|
void tabFont_data();
|
||||||
|
void tabFont();
|
||||||
void attributesList();
|
void attributesList();
|
||||||
void minmaxSizes();
|
void minmaxSizes();
|
||||||
void task206238_twice();
|
void task206238_twice();
|
||||||
@ -1179,6 +1181,71 @@ void tst_QStyleSheetStyle::tabAlignment()
|
|||||||
QVERIFY(bar->geometry().top() > 100);
|
QVERIFY(bar->geometry().top() > 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QStyleSheetStyle::tabFont_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<int>("pixelSize");
|
||||||
|
QTest::addColumn<QTabWidget::TabPosition>("tabPosition");
|
||||||
|
|
||||||
|
QTest::newRow("medium, horizontal") << 24 << QTabWidget::North;
|
||||||
|
QTest::newRow("large, vertical") << 36 << QTabWidget::West;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
void tst_QStyleSheetStyle::tabFont()
|
||||||
|
{
|
||||||
|
QFETCH(int, pixelSize);
|
||||||
|
QFETCH(QTabWidget::TabPosition, tabPosition);
|
||||||
|
const bool vertical = tabPosition == QTabWidget::West || tabPosition == QTabWidget::East;
|
||||||
|
|
||||||
|
// macOS style centers tabs and messes up the test
|
||||||
|
QWindowsStyle windowsStyle;
|
||||||
|
QWidget topLevel;
|
||||||
|
topLevel.setStyle(&windowsStyle);
|
||||||
|
topLevel.setWindowTitle(QTest::currentTestFunction());
|
||||||
|
QTabWidget tabWidget;
|
||||||
|
tabWidget.setStyle(&windowsStyle);
|
||||||
|
tabWidget.addTab(new QWidget,"Tab title");
|
||||||
|
tabWidget.setTabPosition(tabPosition);
|
||||||
|
QTabWidget styledWidget;
|
||||||
|
styledWidget.setStyle(&windowsStyle);
|
||||||
|
styledWidget.setTabPosition(tabPosition);
|
||||||
|
styledWidget.addTab(new QWidget,"Tab title");
|
||||||
|
|
||||||
|
QTabBar *bar = tabWidget.tabBar();
|
||||||
|
QTabBar *styledBar = styledWidget.tabBar();
|
||||||
|
QVERIFY(bar && styledBar);
|
||||||
|
bar->setStyle(&windowsStyle);
|
||||||
|
styledBar->setStyle(&windowsStyle);
|
||||||
|
|
||||||
|
QBoxLayout box(vertical ? QBoxLayout::LeftToRight : QBoxLayout::TopToBottom);
|
||||||
|
box.addWidget(&tabWidget);
|
||||||
|
box.addWidget(&styledWidget);
|
||||||
|
topLevel.setLayout(&box);
|
||||||
|
|
||||||
|
topLevel.resize(600, 600);
|
||||||
|
centerOnScreen(&topLevel);
|
||||||
|
topLevel.show();
|
||||||
|
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
|
||||||
|
|
||||||
|
const QRect defaultRect = bar->tabRect(0);
|
||||||
|
QCOMPARE(styledBar->tabRect(0), defaultRect);
|
||||||
|
|
||||||
|
QFont font;
|
||||||
|
font.setPointSize(pixelSize);
|
||||||
|
tabWidget.setFont(font);
|
||||||
|
|
||||||
|
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));
|
||||||
|
const QRect rectWithStyle = styledBar->tabRect(0);
|
||||||
|
QCOMPARE(rectWithStyle.size(), rectWithFont.size());
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QStyleSheetStyle::attributesList()
|
void tst_QStyleSheetStyle::attributesList()
|
||||||
{
|
{
|
||||||
const QColor blue(Qt::blue);
|
const QColor blue(Qt::blue);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user