QTabBar: don't make current tab visible while tab bar is invisible

When changing the current index while the tab bar is not visible,
calculating the necessary scroll offset might result in wrong results if
the tab bar still has an old size. When the tab bar then gets shown and
resized, the scroll wouldn't be corrected, potentially leaving tabs
unnecessarily scrolled out.

We don't need to make the current index visible if the tab bar itself is
not visible, it's enough to flag the layout as dirty so that the next
show event (which either way makes the then current index visible)
triggers a laying out of the tab bar tabs.

Amends e851d4c06154bf02b23030ff1f7024a8b9edf874.

Fixes: QTBUG-115109
Task-number: QTBUG-113140
Pick-to: 6.6 6.5
Change-Id: I3d8633f9f8b907a36190123839a6104a17bfe138
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
This commit is contained in:
Volker Hilsheimer 2023-08-16 20:28:31 +02:00
parent 6e9f989eb6
commit 3965d52ad5
2 changed files with 34 additions and 1 deletions

View File

@ -1413,7 +1413,10 @@ void QTabBar::setCurrentIndex(int index)
if (tabRect(index).size() != tabSizeHint(index))
d->layoutTabs();
update();
d->makeVisible(index);
if (!isVisible())
d->layoutDirty = true;
else
d->makeVisible(index);
if (d->validIndex(oldIndex)) {
tab->lastTab = oldIndex;
d->layoutTab(oldIndex);

View File

@ -99,6 +99,7 @@ private slots:
void resizeKeepsScroll_data();
void resizeKeepsScroll();
void changeTabTextKeepsScroll();
void settingCurrentTabBeforeShowDoesntScroll();
private:
void checkPositions(const TabBar &tabbar, const QList<int> &positions);
@ -1452,5 +1453,34 @@ void tst_QTabBar::changeTabTextKeepsScroll()
QCOMPARE(getScrollOffset(), scrollOffset);
}
void tst_QTabBar::settingCurrentTabBeforeShowDoesntScroll()
{
QTabBar tabBar;
TabBarScrollingProxyStyle proxyStyle;
tabBar.setStyle(&proxyStyle);
for (int i = 0; i < 6; ++i)
tabBar.addTab(u"Tab Number %1"_s.arg(i));
const auto getScrollOffset = [&]() -> int {
return static_cast<QTabBarPrivate *>(QObjectPrivate::get(&tabBar))->scrollOffset;
};
tabBar.setCurrentIndex(5);
// changing the current index while the tab bar isn't visible shouldn't scroll yet
QCOMPARE(getScrollOffset(), 0);
// now show the tab bar with a size that's too small to fit the current index
const QSize fullSize = tabBar.sizeHint();
tabBar.resize(fullSize.width() / 2, fullSize.height());
tabBar.show();
QVERIFY(QTest::qWaitForWindowExposed(&tabBar));
// this should scroll
QCOMPARE_GT(getScrollOffset(), 0);
}
QTEST_MAIN(tst_QTabBar)
#include "tst_qtabbar.moc"