From 25ece74bfe8de716d437c7266b22e93ae9cd37a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Tue, 14 Feb 2023 11:43:23 +0100 Subject: [PATCH] Fix QStatusBar::removeWidget to hide the right widget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `QStatusBar::removeWidget` was hiding the wrong widget (the next one), since the `removeAt` call changed the item that the `item` variable is referencing. This fixes a regression in Qt 6.3.0 (7166a82844500238a4dad91857384479c7). Change-Id: I9977b47e6208f8d451ff1037bcb9f4e8414cb431 Reviewed-by: Volker Hilsheimer Reviewed-by: Thorbjørn Lindeijer (cherry picked from commit 3e7226f10702828eaaf2fa939efc2ac476e8a2b4) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/widgets/qstatusbar.cpp | 15 ++----- .../widgets/qstatusbar/tst_qstatusbar.cpp | 44 +++++++++++++++++++ 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/widgets/widgets/qstatusbar.cpp b/src/widgets/widgets/qstatusbar.cpp index 9a9879a48d4..2cd3ac3036d 100644 --- a/src/widgets/widgets/qstatusbar.cpp +++ b/src/widgets/widgets/qstatusbar.cpp @@ -355,19 +355,10 @@ void QStatusBar::removeWidget(QWidget *widget) return; Q_D(QStatusBar); - bool found = false; - for (int i = 0; i < d->items.size(); ++i) { - const auto &item = d->items.at(i); - if (item.widget == widget) { - d->items.removeAt(i); - item.widget->hide(); - found = true; - break; - } - } - - if (found) + if (d->items.removeIf([widget](const auto &item) { return item.widget == widget; })) { + widget->hide(); reformat(); + } #if defined(QT_DEBUG) else qDebug("QStatusBar::removeWidget(): Widget not found."); diff --git a/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp b/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp index 418dd1c0f93..15007e8a905 100644 --- a/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp +++ b/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp @@ -23,6 +23,7 @@ private slots: void tempMessage(); void insertWidget(); void insertPermanentWidget(); + void removeWidget(); void setSizeGripEnabled(); void task194017_hiddenWidget(); void QTBUG4334_hiddenOnMaximizedWindow(); @@ -104,6 +105,49 @@ void tst_QStatusBar::insertPermanentWidget() QCOMPARE(sb.insertPermanentWidget(1, new QLabel("foo")), 6); } +void tst_QStatusBar::removeWidget() +{ + QStatusBar sb; + std::vector> widgets; + std::vector states; + for (int i = 0; i < 10; ++i) { + const QString text = i > 5 ? QString("p_%1").arg(i) : QString::number(i); + widgets.push_back(std::make_unique(text)); + states.push_back(true); + } + + for (auto &&widget : widgets) { + if (widget->text().startsWith("p_")) + sb.addPermanentWidget(widget.get()); + else + sb.addWidget(widget.get()); + } + sb.show(); + QVERIFY(QTest::qWaitForWindowExposed(&sb)); + + auto checkStates = [&]{ + for (size_t index = 0; index < std::size(widgets); ++index) { + if (widgets.at(index)->isVisible() != states.at(index)) { + qCritical("Mismatch for widget at index %zu\n" + "\tActual : %s\n" + "\tExpected: %s", + index, widgets.at(index)->isVisible() ? "true" : "false", + states.at(index) ? "true" : "false"); + return false; + } + } + return true; + }; + + QVERIFY(checkStates()); + // remove every widget except the first to trigger unstable reference + for (size_t i = 2; i < std::size(widgets); ++i) { + sb.removeWidget(widgets[i].get()); + states[i] = false; + QVERIFY2(checkStates(), qPrintable(QString("Failure at index %1").arg(i))); + } +} + void tst_QStatusBar::setSizeGripEnabled() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))