diff options
Diffstat (limited to 'src/qml/qml/qqmlcontext.cpp')
-rw-r--r-- | src/qml/qml/qqmlcontext.cpp | 129 |
1 files changed, 59 insertions, 70 deletions
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index a43bded441..cf6736deb9 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -23,30 +23,44 @@ QT_BEGIN_NAMESPACE \brief The QQmlContext class defines a context within a QML engine. \inmodule QtQml - Contexts allow data to be exposed to the QML components instantiated by the - QML engine. + Contexts hold the objects identified by \e id in a QML document. You + can use \l{nameForObject()} and \l{objectForName()} to retrieve them. - Each QQmlContext contains a set of properties, distinct from its QObject - properties, that allow data to be explicitly bound to a context by name. The - context properties are defined and updated by calling - QQmlContext::setContextProperty(). The following example shows a Qt model - being bound to a context and then accessed from a QML file. + \note It is the responsibility of the creator to delete any QQmlContext it + constructs. If a QQmlContext is no longer needed, it must be destroyed + explicitly. The simplest way to ensure this is to give the QQmlContext a + \l{QObject::setParent()}{parent}. - \code - QQmlEngine engine; - QStringListModel modelData; - QQmlContext *context = new QQmlContext(engine.rootContext()); - context->setContextProperty("myModel", &modelData); + \section2 The Context Hierarchy - QQmlComponent component(&engine); - component.setData("import QtQuick 2.0; ListView { model: myModel }", QUrl()); - QObject *window = component.create(context); - \endcode + Contexts form a hierarchy. The root of this hierarchy is the QML engine's + \l {QQmlEngine::rootContext()}{root context}. Each QML component creates its + own context when instantiated and some QML elements create extra contexts + for themselves. - \note It is the responsibility of the creator to delete any QQmlContext it - constructs. If the \c context object in the example is no longer needed when the - \c window component instance is destroyed, the \c context must be destroyed explicitly. - The simplest way to ensure this is to set \c window as the parent of \c context. + While QML objects instantiated in a context are not strictly owned by that + context, their bindings are. If a context is destroyed, the property bindings of + outstanding QML objects will stop evaluating. + + \section2 Context Properties + + Contexts also allow data to be exposed to the QML components instantiated + by the QML engine. Such data is invisible to any tooling, including the + \l{Qt Quick Compiler} and to future readers of the QML documents in + question. It will only be exposed if the QML component is instantiated in + the specific C++ context you are envisioning. In other places, different + context data may be exposed instead. + + Instead of using the QML context to expose data to your QML components, you + should either create additional object properties to hold the data or use + \l{QML_SINGLETON}{singletons}. See + \l{qtqml-cppintegration-exposecppstate.html}{Exposing C++ State to QML} for + a detailed explanation. + + Each QQmlContext contains a set of properties, distinct from its QObject + properties, that allow data to be explicitly bound to a context by name. The + context properties can be defined and updated by calling + QQmlContext::setContextProperty(). To simplify binding and maintaining larger data sets, a context object can be set on a QQmlContext. All the properties of the context object are available @@ -55,59 +69,17 @@ QT_BEGIN_NAMESPACE detected through the property's notify signal. Setting a context object is both faster and easier than manually adding and maintaining context property values. - The following example has the same effect as the previous one, but it uses a context - object. - - \code - class MyDataSet : public QObject { - // ... - Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged) - // ... - }; - - MyDataSet myDataSet; - QQmlEngine engine; - QQmlContext *context = new QQmlContext(engine.rootContext()); - context->setContextObject(&myDataSet); - - QQmlComponent component(&engine); - component.setData("import QtQuick 2.0; ListView { model: myModel }", QUrl()); - component.create(context); - \endcode - All properties added explicitly by QQmlContext::setContextProperty() take precedence over the context object's properties. - \section2 The Context Hierarchy - - Contexts form a hierarchy. The root of this hierarchy is the QML engine's - \l {QQmlEngine::rootContext()}{root context}. Child contexts inherit - the context properties of their parents; if a child context sets a context property - that already exists in its parent, the new context property overrides that of the - parent. - - The following example defines two contexts - \c context1 and \c context2. The - second context overrides the "b" context property inherited from the first with a - new value. - - \code - QQmlEngine engine; - QQmlContext *context1 = new QQmlContext(engine.rootContext()); - QQmlContext *context2 = new QQmlContext(context1); - - context1->setContextProperty("a", 9001); - context1->setContextProperty("b", 9001); - - context2->setContextProperty("b", 42); - \endcode - - While QML objects instantiated in a context are not strictly owned by that - context, their bindings are. If a context is destroyed, the property bindings of - outstanding QML objects will stop evaluating. + Child contexts inherit the context properties of their parents; if a child + context sets a context property that already exists in its parent, the new + context property overrides that of the parent. - \warning Setting the context object or adding new context properties after an object - has been created in that context is an expensive operation (essentially forcing all bindings - to reevaluate). Thus whenever possible you should complete "setup" of the context + \warning Setting the context object or adding new context properties after + an object has been created in that context is an expensive operation + (essentially forcing all bindings to re-evaluate). Thus, if you need to use + context properties, you should at least complete the "setup" of the context before using it to create any objects. \sa {qtqml-cppintegration-exposecppattributes.html}{Exposing Attributes of C++ Types to QML} @@ -208,6 +180,9 @@ QObject *QQmlContext::contextObject() const /*! Set the context \a object. + + \note You should not use context objects to inject values into your QML + components. Use singletons or regular object properties instead. */ void QQmlContext::setContextObject(QObject *object) { @@ -231,6 +206,9 @@ void QQmlContext::setContextObject(QObject *object) /*! Set a the \a value of the \a name property on this context. + + \note You should not use context properties to inject values into your QML + components. Use singletons or regular object properties instead. */ void QQmlContext::setContextProperty(const QString &name, const QVariant &value) { @@ -250,6 +228,11 @@ void QQmlContext::setContextProperty(const QString &name, const QVariant &value) return; } + if (bool isNumber = false; name.toUInt(&isNumber), isNumber) { + qWarning("QQmlContext: Using numbers as context properties will be disallowed in a future Qt version."); + QT7_ONLY(return;) + } + int idx = data->propertyIndex(name); if (idx == -1) { data->addPropertyNameAndIndex(name, data->numIdValues() + d->numPropertyValues()); @@ -271,6 +254,9 @@ void QQmlContext::setContextProperty(const QString &name, const QVariant &value) Set the \a value of the \a name property on this context. QQmlContext does \b not take ownership of \a value. + + \note You should not use context properties to inject values into your QML + components. Use singletons or regular object properties instead. */ void QQmlContext::setContextProperty(const QString &name, QObject *value) { @@ -286,6 +272,9 @@ void QQmlContext::setContextProperty(const QString &name, QObject *value) refreshing expressions, and is therefore recommended instead of calling \l setContextProperty() for each individual property. + \note You should not use context properties to inject values into your QML + components. Use singletons or regular object properties instead. + \sa QQmlContext::setContextProperty() */ void QQmlContext::setContextProperties(const QList<PropertyPair> &properties) @@ -464,7 +453,7 @@ QJSValue QQmlContext::importedScript(const QString &name) const { Q_D(const QQmlContext); - QQmlTypeNameCache::Result r = d->m_data->imports()->query(name); + QQmlTypeNameCache::Result r = d->m_data->imports()->query(name, QQmlTypeLoader::get(engine())); QV4::Scope scope(engine()->handle()); QV4::ScopedObject scripts(scope, d->m_data->importedScripts().valueRef()); return scripts ? QJSValuePrivate::fromReturnedValue(scripts->get(r.scriptIndex)) |