Don't hide a widget that is swapped into a hidden splitter

When replacing a widget in a hidden splitter, then we only need to keep
the new widget hidden if the previous widget was hidden.

If the new widget is not explicitly hidden, and the splitter is already
visible, then we need to explicitly show the new widget.

Augment test case; the existing test cases already cover swapping out a
collapsed or hidden widget.

Fixes: QTBUG-102134
Pick-to: 6.3 6.2
Change-Id: I9b60711a5c1cab79777ce4183783114a16ac3394
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
Volker Hilsheimer 2022-05-22 13:51:28 +02:00
parent 80996d2e5d
commit fb56a0f2ce
2 changed files with 53 additions and 2 deletions

View File

@ -701,6 +701,11 @@ void QSplitterPrivate::setSizes_helper(const QList<int> &sizes, bool clampNegati
doResize();
}
/*
Used by various methods inserting a widget to find out if we need to show the widget
explicitly, which we have to if the splitter is already visible, and if the widget hasn't
been explicitly hidden before inserting it.
*/
bool QSplitterPrivate::shouldShowWidget(const QWidget *w) const
{
Q_Q(const QSplitter);
@ -1144,7 +1149,7 @@ QWidget *QSplitter::replaceWidget(int index, QWidget *widget)
QBoolBlocker b(d->blockChildAdd);
const QRect geom = current->geometry();
const bool shouldShow = d->shouldShowWidget(current);
const bool wasHidden = current->isHidden();
s->widget = widget;
current->setParent(nullptr);
@ -1154,7 +1159,10 @@ QWidget *QSplitter::replaceWidget(int index, QWidget *widget)
// should not change. Only set the geometry on the new widget
widget->setGeometry(geom);
widget->lower();
widget->setVisible(shouldShow);
if (wasHidden)
widget->hide();
else if (d->shouldShowWidget(widget))
widget->show();
return current;
}

View File

@ -58,6 +58,8 @@ private slots:
void replaceWidget();
void replaceWidgetWithSplitterChild_data();
void replaceWidgetWithSplitterChild();
void replaceWidgetWhileHidden_data();
void replaceWidgetWhileHidden();
void handleMinimumWidth();
// task-specific tests below me:
@ -829,6 +831,47 @@ void tst_QSplitter::replaceWidgetWithSplitterChild()
}
}
void tst_QSplitter::replaceWidgetWhileHidden_data()
{
QTest::addColumn<bool>("splitterVisible");
QTest::addColumn<bool>("widgetVisible");
QTest::addRow("visibleToVisible") << true << true;
QTest::addRow("hiddenToVisible") << true << false;
QTest::addRow("visibleToHidden") << false << true;
QTest::addRow("hiddenToHidden") << false << false;
}
void tst_QSplitter::replaceWidgetWhileHidden()
{
QFETCH(bool, splitterVisible);
QFETCH(bool, widgetVisible);
MyFriendlySplitter splitter;
splitter.addWidget(new QLabel("One"));
splitter.addWidget(new QLabel("Two"));
if (splitterVisible) {
splitter.show();
QVERIFY(QTest::qWaitForWindowExposed(&splitter));
}
QWidget *newWidget = new QLabel("Three");
if (!widgetVisible)
newWidget->hide();
const bool wasExplicitHide = !widgetVisible && newWidget->testAttribute(Qt::WA_WState_ExplicitShowHide);
splitter.replaceWidget(1, newWidget);
QCOMPARE(!widgetVisible && newWidget->testAttribute(Qt::WA_WState_ExplicitShowHide), wasExplicitHide);
if (!splitterVisible) {
splitter.show();
QVERIFY(QTest::qWaitForWindowExposed(&splitter));
}
QCOMPARE(widgetVisible, newWidget->isVisible());
}
void tst_QSplitter::handleMinimumWidth()
{
MyFriendlySplitter split;