Fix assert when a VisualDataModels context has been invalidated.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Thu, 23 Aug 2012 04:20:47 +0000 (14:20 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 24 Aug 2012 00:52:30 +0000 (02:52 +0200)
Verify the context is valid before attempting to access its engine. The
context should normally be valid but there is a small window between
a delegate item being released and the DeferredDelete event being
processed when it is not.

Task-number: QTBUG-26949
Change-Id: I79f3affaed8904cbe0974476010b68305666cd29
Reviewed-by: Bea Lam <bea.lam@nokia.com>

src/quick/items/qquickvisualdatamodel.cpp
tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp

index e9ac01d..f98e01e 100644 (file)
@@ -847,6 +847,8 @@ QObject *QQuickVisualDataModelPrivate::object(Compositor::Group group, int index
     if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
         qWarning() << "VisualDataModel::item: index out range" << index << m_compositor.count(group);
         return 0;
+    } else if (!m_context->isValid()) {
+        return 0;
     }
 
     Compositor::iterator it = m_compositor.find(group, index);
@@ -1376,7 +1378,7 @@ void QQuickVisualDataModelPrivate::emitModelUpdated(const QQuickChangeSet &chang
 
 void QQuickVisualDataModelPrivate::emitChanges()
 {
-    if (m_transaction || !m_complete)
+    if (m_transaction || !m_complete || !m_context->isValid())
         return;
 
     m_transaction = true;
@@ -1507,6 +1509,9 @@ QQuickVisualDataModelAttached *QQuickVisualDataModel::qmlAttachedProperties(QObj
 bool QQuickVisualDataModelPrivate::insert(
         Compositor::insert_iterator &before, const v8::Local<v8::Object> &object, int groups)
 {
+    if (!m_context->isValid())
+        return false;
+
     QQuickVisualDataModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, m_context->engine(), -1);
     if (!cacheItem)
         return false;
@@ -2275,7 +2280,9 @@ QQmlV8Handle QQuickVisualDataGroup::get(int index)
         return QQmlV8Handle::fromHandle(v8::Undefined());;
 
     QQuickVisualDataModelPrivate *model = QQuickVisualDataModelPrivate::get(d->model);
-    if (index < 0 || index >= model->m_compositor.count(d->group)) {
+    if (!model->m_context->isValid()) {
+        return QQmlV8Handle::fromHandle(v8::Undefined());
+    } else if (index < 0 || index >= model->m_compositor.count(d->group)) {
         qmlInfo(this) << tr("get: index out of range");
         return QQmlV8Handle::fromHandle(v8::Undefined());
     }
index e55c537..fce746b 100644 (file)
@@ -437,6 +437,7 @@ private slots:
     void asynchronousMove();
     void asynchronousMove_data();
     void asynchronousCancel();
+    void invalidContext();
 
 private:
     template <int N> void groups_verify(
@@ -4206,6 +4207,35 @@ void tst_qquickvisualdatamodel::asynchronousCancel()
     QCOMPARE(controller.incubatingObjectCount(), 0);
 }
 
+void tst_qquickvisualdatamodel::invalidContext()
+{
+    QQmlEngine engine;
+    QaimModel model;
+    for (int i = 0; i < 8; i++)
+        model.addItem("Original item" + QString::number(i), "");
+
+    engine.rootContext()->setContextProperty("myModel", &model);
+
+    QScopedPointer<QQmlContext> context(new QQmlContext(engine.rootContext()));
+
+    QQmlComponent c(&engine, testFileUrl("visualdatamodel.qml"));
+
+
+    QQuickVisualDataModel *visualModel = qobject_cast<QQuickVisualDataModel*>(c.create(context.data()));
+    QVERIFY(visualModel);
+
+    QQuickItem *item = visualModel->item(4, false);
+    QVERIFY(item);
+    visualModel->release(item);
+
+    delete context.take();
+
+    model.insertItem(4, "new item", "");
+
+    item = visualModel->item(4, false);
+    QVERIFY(!item);
+}
+
 QTEST_MAIN(tst_qquickvisualdatamodel)
 
 #include "tst_qquickvisualdatamodel.moc"