From fb56a0f2ce34e95d955095c01ecf2943046be85e Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Sun, 22 May 2022 13:51:28 +0200 Subject: [PATCH] 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 Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qsplitter.cpp | 12 +++++- .../widgets/qsplitter/tst_qsplitter.cpp | 43 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp index 7dfc2a04fa2..a954d6ce66e 100644 --- a/src/widgets/widgets/qsplitter.cpp +++ b/src/widgets/widgets/qsplitter.cpp @@ -701,6 +701,11 @@ void QSplitterPrivate::setSizes_helper(const QList &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; } diff --git a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp index edcfdcfca2a..667c6868b71 100644 --- a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp +++ b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp @@ -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("splitterVisible"); + QTest::addColumn("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;