> Hi
>
> I have attached a sample project that displays a problem with Qml. We are
> trying to open a second QmlView and register QObjects with it.
>
> // from main.cpp
>
> QmlView* v = new QmlView();
> v->setUrl(QUrl::fromLocalFile("test1.qml"));
> v->setContentResizable(true);
> v->engine()->rootContext()->setContextProperty("AppObj", new AppObj());
> v->execute();
> v->show();
>
> This works just fine. AppObj has a Q_INVOKABLE function:
>
> Q_INVOKABLE void createSecondView()
> {
> QmlView* v = new QmlView();
> v->setUrl(QUrl::fromLocalFile("test1.qml"));
> v->setContentResizable(true);
> v->engine()->rootContext()->setContextProperty("AppObj", this);
> v->execute();
> v->show();
> }
>
> The second view though no longer has access to "AppObj"'s functions /
> propertys. ( file:test1.qml:11: Unable to assign [undefined] to QString ).
>
> If I change:
> v->engine()->rootContext()->setContextProperty("AppObj", this);
> to
> v->engine()->rootContext()->setContextProperty("AppObj", new AppObj());
>
> the second view works too. The problem is that this behaviour applies to
> all Objects that have been used by the first view already. In production
> AppObj would have a function like MyObject* getObject(QString path); which
> would return the same pointer for the second view as it returned for the
> first, showing the same problem as above ( not accessible at all ).
>
> My guess is that some global registry is used to register new QObjects, but
> if they already exist and are to be used by another QmlView those globals
> are not found / used and no new entry is created for them.
>
> Is there a way to use the same QmlEngine / QmlContext with two QmlViews
> thereby using same javascript instance / circumventing that problem ?

Hi,

This has been fixed recently.  Unfortunately we changed repo just before the 
changes were applied and we are currently blocked by our CI system.  
Hopefully this will clear in the next couple of days (an announcement will 
follow).  In the meantime you could try the attached patch.  This was 
QTBUG-7957, btw.

Regards,
-- 
Martin.
diff --git a/src/declarative/qml/qmlcompiledbindings.cpp b/src/declarative/qml/qmlcompiledbindings.cpp
index d09f7eb..cdea96f 100644
--- a/src/declarative/qml/qmlcompiledbindings.cpp
+++ b/src/declarative/qml/qmlcompiledbindings.cpp
@@ -807,36 +807,6 @@ static QObject *variantToQObject(const QVariant &value, bool *ok)
     }
 }
 
-QmlPropertyCache::Data *
-QmlCompiledBindingsPrivate::findproperty(QObject *obj, 
-                                         const QScriptDeclarativeClass::Identifier &name,
-                                         QmlEnginePrivate *enginePriv,
-                                         QmlPropertyCache::Data &local)
-{
-    QmlPropertyCache *cache = 0;
-    QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
-    if (ddata)
-        cache = ddata->propertyCache;
-    if (!cache) {
-        cache = enginePriv->cache(obj);
-        if (cache && ddata) { cache->addref(); ddata->propertyCache = cache; }
-    }
-
-    QmlPropertyCache::Data *property = 0;
-
-    if (cache) {
-        property = cache->property(name);
-    } else {
-        qWarning() << "QmlBindingVME: Slow search" << enginePriv->objectClass->toString(name);
-        local = QmlPropertyCache::create(obj->metaObject(),  
-                                         enginePriv->objectClass->toString(name));
-        if (local.isValid())
-            property = &local;
-    }
-
-    return property;
-}
-
 bool QmlCompiledBindingsPrivate::findproperty(QObject *obj, Register *output, 
                                               QmlEnginePrivate *enginePriv,
                                               int subIdx, const QScriptDeclarativeClass::Identifier &name,
@@ -848,7 +818,8 @@ bool QmlCompiledBindingsPrivate::findproperty(QObject *obj, Register *output,
     }
 
     QmlPropertyCache::Data local;
-    QmlPropertyCache::Data *property = findproperty(obj, name, enginePriv, local);
+    QmlPropertyCache::Data *property = 
+        QmlPropertyCache::property(QmlEnginePrivate::get(enginePriv), obj, name, local);
 
     if (property) {
         if (subIdx != -1)
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index 0eb497d..4c6dc6f 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -461,16 +461,13 @@ QVariant QmlContext::contextProperty(const QString &name) const
         QByteArray utf8Name = name.toUtf8();
         for (int ii = d->defaultObjects.count() - 1; ii >= 0; --ii) {
             QObject *obj = d->defaultObjects.at(ii);
-            QmlDeclarativeData *data = QmlDeclarativeData::get(obj);
-            if (data && data->propertyCache) {
-                QmlPropertyCache::Data *property = data->propertyCache->property(name);
-                if (property)
-                    value = obj->metaObject()->property(property->coreIndex).read(obj);
-            } else {
-                value = obj->property(utf8Name);
-            }
-            if (value.isValid())
+            QmlPropertyCache::Data local;
+            QmlPropertyCache::Data *property = QmlPropertyCache::property(d->engine, obj, name, local);
+
+            if (property) {
+                value = obj->metaObject()->property(property->coreIndex).read(obj);
                 break;
+            }
         }
         if (!value.isValid() && parentContext())
             value = parentContext()->contextProperty(name);
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 6aa5d69..8349090 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -309,6 +309,7 @@ public:
     static QmlEngine *getEngine(QScriptEngine *e) { return static_cast<QmlScriptEngine*>(e)->p->q_func(); }
     static QmlEnginePrivate *get(QmlEngine *e) { return e->d_func(); }
     static QmlEnginePrivate *get(QScriptEngine *e) { return static_cast<QmlScriptEngine*>(e)->p; }
+    static QmlEngine *get(QmlEnginePrivate *p) { return p->q_func(); }
     QmlContext *getContext(QScriptContext *);
 };
 
diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp
index 0603a9c..09c936e 100644
--- a/src/declarative/qml/qmlmetaproperty.cpp
+++ b/src/declarative/qml/qmlmetaproperty.cpp
@@ -188,24 +188,11 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name)
     } 
 
     // Property
-    QmlPropertyCache *cache = 0;
-    QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
-    if (ddata)
-        cache = ddata->propertyCache;
-    if (!cache)
-        cache = enginePrivate?enginePrivate->cache(obj):0;
-
-    if (cache) {
-        QmlPropertyCache::Data *data = cache->property(name);
-
-        if (data && !(data->flags & QmlPropertyCache::Data::IsFunction)) 
-            core = *data;
-
-    } else {
-        // No cache available
-        QMetaProperty p = QmlMetaType::property(obj, name.toUtf8().constData());
-        core.load(p);
-    }
+    QmlPropertyCache::Data local;
+    QmlPropertyCache::Data *property = 
+        QmlPropertyCache::property(context?context->engine():0, obj, name, local);
+    if (property && !(property->flags & QmlPropertyCache::Data::IsFunction)) 
+        core = *property;
 }
 
 /*!
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
index 4ff4746..7bbb7df 100644
--- a/src/declarative/qml/qmlobjectscriptclass.cpp
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -144,23 +144,7 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
         return 0;
 
     QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
-
-    QmlPropertyCache *cache = 0;
-    QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
-    if (ddata)
-        cache = ddata->propertyCache;
-    if (!cache) {
-        cache = enginePrivate->cache(obj);
-        if (cache && ddata) { cache->addref(); ddata->propertyCache = cache; }
-    }
-
-    if (cache) {
-        lastData = cache->property(name);
-    } else {
-        local = QmlPropertyCache::create(obj->metaObject(), toString(name));
-        if (local.isValid())
-            lastData = &local;
-    }
+    lastData = QmlPropertyCache::property(engine, obj, name, local);
 
     if (lastData)
         return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; 
diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp
index 51753b8..04cffe1 100644
--- a/src/declarative/qml/qmlpropertycache.cpp
+++ b/src/declarative/qml/qmlpropertycache.cpp
@@ -352,4 +352,64 @@ QStringList QmlPropertyCache::propertyNames() const
     return stringCache.keys();
 }
 
+QmlPropertyCache::Data *QmlPropertyCache::property(QmlEngine *engine, QObject *obj, 
+                                                   const QScriptDeclarativeClass::Identifier &name, Data &local)
+{
+    QmlPropertyCache::Data *rv = 0;
+
+    QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
+
+    QmlPropertyCache *cache = 0;
+    QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+    if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine)
+        cache = ddata->propertyCache;
+    if (!cache) {
+        cache = enginePrivate->cache(obj);
+        if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
+    }
+
+    if (cache) {
+        rv = cache->property(name);
+    } else {
+        local = QmlPropertyCache::create(obj->metaObject(), enginePrivate->objectClass->toString(name));
+        if (local.isValid())
+            rv = &local;
+    }
+
+    return rv;
+}
+
+QmlPropertyCache::Data *QmlPropertyCache::property(QmlEngine *engine, QObject *obj, 
+                                                   const QString &name, Data &local)
+{
+    QmlPropertyCache::Data *rv = 0;
+
+    if (!engine) {
+        local = QmlPropertyCache::create(obj->metaObject(), name);
+        if (local.isValid())
+            rv = &local;
+    } else {
+        QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
+
+        QmlPropertyCache *cache = 0;
+        QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
+        if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine)
+            cache = ddata->propertyCache;
+        if (!cache) {
+            cache = enginePrivate->cache(obj);
+            if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
+        }
+
+        if (cache) {
+            rv = cache->property(name);
+        } else {
+            local = QmlPropertyCache::create(obj->metaObject(), name);
+            if (local.isValid())
+                rv = &local;
+        }
+    }
+
+    return rv;
+}
+
 QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h
index 8d54e35..efc4643 100644
--- a/src/declarative/qml/qmlpropertycache_p.h
+++ b/src/declarative/qml/qmlpropertycache_p.h
@@ -132,6 +132,9 @@ public:
     Data *property(int) const;
     QStringList propertyNames() const;
 
+    inline QmlEngine *qmlEngine() const;
+    static Data *property(QmlEngine *, QObject *, const QScriptDeclarativeClass::Identifier &, Data &);
+    static Data *property(QmlEngine *, QObject *, const QString &, Data &);
 protected:
     virtual void clear();
 
@@ -181,6 +184,11 @@ bool QmlPropertyCache::ValueTypeData::operator==(const ValueTypeData &o)
            valueTypePropType == o.valueTypePropType; 
 }
 
+QmlEngine *QmlPropertyCache::qmlEngine() const
+{
+    return engine;
+}
+
 QT_END_NAMESPACE
 
 #endif // QMLPROPERTYCACHE_P_H
diff --git a/tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml b/tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml
new file mode 100644
index 0000000..7da09e4
--- /dev/null
+++ b/tests/auto/declarative/qmlecmascript/data/multiEngineObject.qml
@@ -0,0 +1,5 @@
+import Qt 4.6
+
+QtObject {
+    property string test: thing.stringProperty
+}
diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
index c41e248..1ba9a52 100644
--- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
+++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp
@@ -119,6 +119,7 @@ private slots:
     void jsObject();
     void undefinedResetsProperty();
     void listToVariant();
+    void multiEngineObject();
 
     void bug1();
 
@@ -1610,7 +1611,30 @@ void tst_qmlecmascript::listToVariant()
     QCOMPARE(object->property("test"), QVariant::fromValue(container.children()));
 
     delete object;
+}
+
+// QTBUG-7957
+void tst_qmlecmascript::multiEngineObject()
+{
+    MyQmlObject obj;
+    obj.setStringProperty("Howdy planet");
+
+    QmlEngine e1;
+    e1.rootContext()->setContextProperty("thing", &obj);
+    QmlComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
+
+    QmlEngine e2;
+    e2.rootContext()->setContextProperty("thing", &obj);
+    QmlComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
+
+    QObject *o1 = c1.create();
+    QObject *o2 = c2.create();
+
+    QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
+    QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
 
+    delete o2;
+    delete o1;
 }
 
 QTEST_MAIN(tst_qmlecmascript)
_______________________________________________
Qt4-preview-feedback mailing list
[email protected]
http://lists.trolltech.com/mailman/listinfo/qt4-preview-feedback

Reply via email to