From fc0bf5a9fd077da6e5d0943d1edae0140ea23a10 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 25 Jun 2025 15:55:35 +0200 Subject: [PATCH] Templates: Disconnect menu bar items when clearing Otherwise we get change notifications for half-dead change listeners and subsequent crashes. Pick-to: 6.10 6.9 6.8 6.5 Task-number: QTBUG-137554 Change-Id: I194ca0f8c3a540b1bfc41fa969d0cd3b9e6c24e4 Reviewed-by: Fabian Kosmale --- src/quicktemplates/qquickmenubar.cpp | 3 +- .../qquickmenubar/data/clearMenus.qml | 35 +++++++++++++++++++ .../qquickmenubar/tst_qquickmenubar.cpp | 11 ++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 tests/auto/quickcontrols/qquickmenubar/data/clearMenus.qml diff --git a/src/quicktemplates/qquickmenubar.cpp b/src/quicktemplates/qquickmenubar.cpp index 361eaccc1b..3320fe85bb 100644 --- a/src/quicktemplates/qquickmenubar.cpp +++ b/src/quicktemplates/qquickmenubar.cpp @@ -339,7 +339,8 @@ QQuickMenu *QQuickMenuBarPrivate::menus_at(QQmlListProperty *prop, q void QQuickMenuBarPrivate::menus_clear(QQmlListProperty *prop) { QQuickMenuBar *menuBar = static_cast(prop->object); - QQuickMenuBarPrivate::get(menuBar)->contentModel->clear(); + for (int count = menuBar->count(); count > 0; count = menuBar->count()) + menuBar->takeMenu(count - 1); } QPalette QQuickMenuBarPrivate::defaultPalette() const diff --git a/tests/auto/quickcontrols/qquickmenubar/data/clearMenus.qml b/tests/auto/quickcontrols/qquickmenubar/data/clearMenus.qml new file mode 100644 index 0000000000..6844902fb6 --- /dev/null +++ b/tests/auto/quickcontrols/qquickmenubar/data/clearMenus.qml @@ -0,0 +1,35 @@ +import QtQuick +import QtQuick.Templates + +Item { + property int v: 0 + + MenuBar { + id: menuBar + Menu {} + } + + Instantiator { + id: instantiator + + delegate: Menu {} + + onObjectAdded: (index, object) => { + menuBar.menus.push(object) + } + + onObjectRemoved: (index, object) => { + menuBar.menus.length = 0; + } + } + + Timer { + running: v < 2 + interval: 1 + repeat: true + + onTriggered: { + instantiator.model = (++v % 2) ? 0 : 2 + } + } +} diff --git a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp index a6108fb427..dcdefb8d83 100644 --- a/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp +++ b/tests/auto/quickcontrols/qquickmenubar/tst_qquickmenubar.cpp @@ -82,6 +82,7 @@ private slots: void panMenuBar_data(); void panMenuBar(); void dontDeleteDelegates(); + void clearMenus(); private: bool nativeMenuBarSupported = false; @@ -1896,6 +1897,16 @@ void tst_qquickmenubar::dontDeleteDelegates() QVERIFY(delegateComponent2); } +void tst_qquickmenubar::clearMenus() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("clearMenus.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer o(c.create()); + QVERIFY(!o.isNull()); + QTRY_COMPARE(o->property("v").toInt(), 2); +} + QTEST_QUICKCONTROLS_MAIN(tst_qquickmenubar) #include "tst_qquickmenubar.moc"