QQuickListView: Do not re-parent existing contexts

If we're not creating a new context, we should not re-parent it.
Otherwise it gets deleted in unexpected moments.

Amends commit 471c909a68.

Pick-to: 6.5 6.6
Fixes: QTBUG-115106
Change-Id: Ib51d80dda07096587c64ac2262d115ea08855cd2
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Ulf Hermann 2023-07-10 12:22:14 +02:00
parent 4e69f2468a
commit 20f608651b
3 changed files with 95 additions and 1 deletions

View File

@ -1094,7 +1094,8 @@ QQuickItem * QQuickListViewPrivate::getSectionItem(const QString &section)
} else if (!reuseExistingContext) {
context->setContextProperty(QLatin1String("section"), section);
}
QQml_setParent_noEvent(context, nobj);
if (!reuseExistingContext)
QQml_setParent_noEvent(context, nobj);
sectionItem = qobject_cast<QQuickItem *>(nobj);
if (!sectionItem) {
delete nobj;

View File

@ -0,0 +1,75 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Window
Item {
id: win
height: 640
width: 480
property string currentModel: 'foo'
function toggle() : Item {
var ret = listView.itemAtIndex(0);
win.currentModel = win.currentModel === 'foo' ? 'bar' : 'foo'
switch (win.currentModel) {
case 'foo':
if (listView.model) {
listView.model.destroy()
}
listView.model = fooModelComponent.createObject(win)
break
case 'bar':
if (listView.model) {
listView.model.destroy()
}
listView.model = barModelComponent.createObject(win)
break
}
return ret;
}
Component {
id: fooModelComponent
ListModel {
ListElement { textValue: "foo1" }
}
}
Component {
id: barModelComponent
ListModel {
ListElement { textValue: "bar1" }
}
}
ListView {
states: [
State {
when: win.currentModel === 'bar'
PropertyChanges {
listView.section.property: 'sectionProp'
}
}
]
id: listView
model: fooModelComponent.createObject(win)
anchors.fill: parent
section.delegate: Text {
required property string section
text: section
}
delegate: Text {
id: delg
text: delg.textValue
required property string textValue
}
}
}

View File

@ -56,6 +56,8 @@ private slots:
void sectionGeometryChange();
void areaZeroviewDoesNotNeedlesslyPopulateWholeModel();
void delegateContextHandling();
private:
void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to);
QScopedPointer<QPointingDevice> touchDevice = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
@ -1022,6 +1024,22 @@ void tst_QQuickListView2::areaZeroviewDoesNotNeedlesslyPopulateWholeModel()
QVERIFY(delegateCreationCounter() < 100);
}
void tst_QQuickListView2::delegateContextHandling()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("delegateContextHandling.qml"));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
std::unique_ptr<QObject> o(c.create());
QVERIFY(o);
for (int i = 0; i < 10; ++i) {
QQuickItem *delegate = nullptr;
QMetaObject::invokeMethod(o.get(), "toggle", Q_RETURN_ARG(QQuickItem *, delegate));
QVERIFY(delegate);
}
}
QTEST_MAIN(tst_QQuickListView2)
#include "tst_qquicklistview2.moc"