QQuickItem::~QQuickItem()
{
Q_D(QQuickItem);
+ d->inDestructor = true;
if (d->windowRefCount > 1)
d->windowRefCount = 1; // Make sure window is set to null in next call to derefWindow().
const bool wasVisible = isVisible();
op->removeChild(this);
- if (wasVisible) {
+ if (wasVisible && !op->inDestructor)
emit oldParentItem->visibleChildrenChanged();
- }
} else if (d->window) {
QQuickWindowPrivate::get(d->window)->parentlessItems.remove(this);
}
d->itemChange(ItemParentHasChanged, d->parentItem);
- emit parentChanged(d->parentItem);
- if (isVisible() && d->parentItem)
+ if (!d->inDestructor)
+ emit parentChanged(d->parentItem);
+ if (isVisible() && d->parentItem && !QQuickItemPrivate::get(d->parentItem)->inDestructor)
emit d->parentItem->visibleChildrenChanged();
}
itemChange(QQuickItem::ItemChildRemovedChange, child);
- emit q->childrenChanged();
+ if (!inDestructor)
+ emit q->childrenChanged();
}
void QQuickItemPrivate::refWindow(QQuickWindow *c)
, touchEnabled(false)
#endif
, hasCursorHandler(false)
+ , inDestructor(false)
, dirtyAttributes(0)
, nextDirtyItem(nullptr)
, prevDirtyItem(nullptr)
QAccessible::updateAccessibility(&ev);
}
#endif
- emit q->visibleChanged();
- if (childVisibilityChanged)
- emit q->visibleChildrenChanged();
+ if (!inDestructor) {
+ emit q->visibleChanged();
+ if (childVisibilityChanged)
+ emit q->visibleChildrenChanged();
+ }
return true; // effective visibility DID change
}
void grab();
+ void signalsOnDestruction();
+
private:
QQmlEngine engine;
bool qt_tab_all_widgets() {
QVERIFY(!sub2.isAncestorOf(&sub2));
}
+/*
+ Items that are getting destroyed should not emit property change notifications.
+*/
+void tst_QQuickItem::signalsOnDestruction()
+{
+ QQuickWindow window;
+ window.show();
+
+ // visual children, but not QObject children
+ std::unique_ptr<QQuickItem> parent(new QQuickItem(window.contentItem()));
+ std::unique_ptr<QQuickItem> child(new QQuickItem);
+ std::unique_ptr<QQuickItem> grandChild(new QQuickItem);
+
+ QSignalSpy childrenSpy(parent.get(), &QQuickItem::childrenChanged);
+ QSignalSpy visibleChildrenSpy(parent.get(), &QQuickItem::visibleChildrenChanged);
+ QSignalSpy childParentSpy(child.get(), &QQuickItem::parentChanged);
+ QSignalSpy childChildrenSpy(child.get(), &QQuickItem::childrenChanged);
+ QSignalSpy childVisibleChildrenSpy(child.get(), &QQuickItem::visibleChanged);
+ QSignalSpy grandChildParentSpy(grandChild.get(), &QQuickItem::parentChanged);
+
+ child->setParentItem(parent.get());
+ QCOMPARE(childrenSpy.count(), 1);
+ QCOMPARE(visibleChildrenSpy.count(), 1);
+ QCOMPARE(childParentSpy.count(), 1);
+ QCOMPARE(childChildrenSpy.count(), 0);
+ QCOMPARE(childVisibleChildrenSpy.count(), 0);
+
+ grandChild->setParentItem(child.get());
+ QCOMPARE(childrenSpy.count(), 1);
+ QCOMPARE(visibleChildrenSpy.count(), 1);
+ QCOMPARE(childParentSpy.count(), 1);
+ QCOMPARE(childChildrenSpy.count(), 1);
+ QCOMPARE(childVisibleChildrenSpy.count(), 0);
+ QCOMPARE(grandChildParentSpy.count(), 1);
+
+ parent.reset();
+
+ QVERIFY(!child->parentItem());
+ QVERIFY(grandChild->parentItem());
+ QCOMPARE(childrenSpy.count(), 1);
+ QCOMPARE(visibleChildrenSpy.count(), 1);
+ QCOMPARE(childParentSpy.count(), 2);
+ QCOMPARE(grandChildParentSpy.count(), 1);
+}
+
+
QTEST_MAIN(tst_QQuickItem)
#include "tst_qquickitem.moc"