Hi,
We were able to find the problem. It's a general flaw in the way qml caches
its data. When a new Qobject is introduced to Qml some information about the
registration are stored in QObjectPrivate::declarative_data. These are tied
to the used QmlEngine. If the same object is introduced to another QmlEngine
this data is of course invalid for the new Engine.
To fix this we changed a line in
QmlObjectScriptClass::queryProperty(Qobject*, const Identifier&,
QScriptClass::QueryFlags, QmlContext*)
Befor:
....
if (!obj)
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;
}
}
....
After:
....
if (!obj)
return 0;
QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
QmlPropertyCache *cache = 0;
QmlDeclarativeData *ddata = 0; //QmlDeclarativeData::get(obj); // This
is the "fix"
if (ddata)
cache = ddata->propertyCache;
if (!cache) {
cache = enginePrivate->cache(obj);
if (cache && ddata) { cache->addref(); ddata->propertyCache = cache;
}
}
....
As far as I can see this introduces a slowdown and I'm not certain that this
is the only place that generates problems.
Cheers,
Marcus
On [DATE], "Marcus Tillmanns" <[ADDRESS]> wrote:
> 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 ?
>
> Regards,
> Marcus
>
> _______________________________________________
> Qt4-preview-feedback mailing list
> [email protected]
> http://lists.trolltech.com/mailman/listinfo/qt4-preview-feedback
_______________________________________________
Qt4-preview-feedback mailing list
[email protected]
http://lists.trolltech.com/mailman/listinfo/qt4-preview-feedback