/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the either Technology Preview License Agreement or the ** Beta Release License Agreement. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain ** additional rights. These rights are described in the Nokia Qt LGPL ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \page qmlscope.html \title QML Scope \l {Property Binding}s and \l {ECMAScript Blocks} are executed in a scope chain automatically established by QML when constructing a component instance. QML is a \e {dynamically scoped} language. Different object instances instantiated from the same component can exist in different scope chains. \image qml-scope.png \section1 ECMAScript Variable object Each binding and script block has its own distinct ECMAScript variable object where local variables are stored. That is, local variables from different bindings and script blocks never conflict. \section1 Element Type Names Bindings or script blocks use element type names when accessing \l {Attached Properties} or enumeration values. The set of available element names is defined by the import list of the \l {QML Documents}{QML Document} in which the the binding or script block is defined. These two examples show how to access attached properties and enumeration values with different types of import statements. \table \row \o \code import Qt 4.6 Text { id: root scale: root.PathView.scale horizontalAlignment: Text.AlignLeft } \endcode \o \code import Qt 4.6 as MyQt Text { id: root scale: root.MyQt.PathView.scale horizontalAlignment: MyQt.Text.AlignLeft } \endcode \endtable \section1 QML Local Scope Most variables references are resolved in the local scope. The local scope is controlled by the QML component in which the binding or script block was declarated. The following example shows three different bindings, and the component that dictates their local scope. \table \row \o \code // main.qml import Qt 4.6 Rectangle { // Local scope component for binding 1 id: root property string text Button { text: root.text // binding 1 } ListView { delegate: Component { // Local scope component for binding 2 Rectangle { width: ListView.view.width // binding 2 } } } } \endcode \o \code // Button.qml import Qt 4.6 Rectangle { // Local scope component for binding 3 id: root property string text Text { text: root.text // binding 3 } } \endcode \endtable Inside the local scope, four "sub-scopes" exist. Each "sub-scope" is searched in order when resolving a name - names in a higher "sub-scopes" shadow those in lower sub-scopes. \section2 IDs IDs present in the component take precendence over other names. The QML engine enforces uniqueness of IDs within a component, so their names cannot conflict with one another. This is an example of using IDs within bindings. \code Item { id: root width: nested.width Item { id: nested height: root.height } } \endcode \section2 Script Methods Methods declared in script blocks are searched immediately after IDs. In the case of multiple script blocks in the one component, the blocks are searched in the order in which they were declared - the nesting of script blocks within a component is not significant for name resolution. In the following example, \c {Method 1} shadows \c {Method 2} for the bindings, but not for \c {Method 3}. \code Item { Script { function getValue() { return 10; } // Method 1 } Rectangle { Script { function getValue() { return 11; } // Method 2 function getValue2() { return getValue(); } // Method 3 } x: getValue() // Resolves to Method 1, set to 10 y: getValue2() // Resolves to Method 3, set to 11 } } \endcode \section2 Scope Object A scope object is associated with each binding and script block. Properties and methods of the scope object appear in the scope chain, immediately after \l {Script Methods}. In bindings and script blocks established explicitly in \l {QML Documents}, the scope object is always the element containing the binding or script block. The following example shows two bindings, one using grouped properties, and the corresponding scope object. These two bindings use the scope object to resolve variable references - \c height is a property on \l Rectangle, and \c parent is a property on \l Text. \code Item { // Scope object for Script block 1 Script { // Script block 1 function calculateValue() { ... } } Rectangle { // Scope object for Binding 1 and Script block 2 Script { // Script block 2 function calculateColor() { ... } } width: height * 2 // Binding 1 } Text { // Scope object for Binding 2 font.pixelSize: parent.height * 0.7 // binding 2 } } \endcode One notable characteristic of the scope object is its interaction with \l {Attached Properties}. As attached properties exist on all objects, an attached property reference that is not explicitly prefixed by an id will \e always resolve to the attached property on the scope object. In the following example, \c {Binding 1} will resolve to the attached properties of the \l Rectangle element, as intended. However, due to the property search of the scope object, \c {Binding 2} will resolve to the attached properties of the \l Text element, which is probably not what was intended. This code can be corrected, by replacing \c {Binding 2} with this explicit element reference \c {root.ListView.view.width}. \code import Qt 4.6 ListView { delegate: Rectangle { id: root width: ListView.view.width // Binding 1 Text { text: contactName width: ListView.view.width // Binding 2 } } } \endcode \e TODO \list \o scope object for PropertyChanges \endlist \section2 Root Object Properties and methods on the local scope component's root object appear in the scope chain immediately after the \l {Scope Object}. If the scope object and root object are the same, this step has no effect. This example uses the root object to easily propagate data throughout the component. \code Item { property string description property int fontSize Text { text: description font.pixelSize: fontSize } } \endcode \section1 QML Component chain When a QML component is instantiated it is given a parent component instance. The parent component instance is immutable - it is not effected, for example, by changes in the instance's visual parent (in the case of visual elements). Should name resolution fail within the \l {QML Local Scope}, this parent chain is searched. For each component instance in the chain, the following are examined: \list 1 \o IDs \o Script Methods \o Root Object \endlist This list is a sub-set of that in the \l {QML Local Scope}. Sub-components used within a component have their parent component instance set to the component instance that created them. In the following example, the two \c Button instances have the \c main.qml instance as their parent component instance. If the \c Button type was used from within another QML file, it may have a difference parent component instance, and consequently the \c buttonClicked() method may resolve differently. \table \row \o \code // main.qml Item { function buttonClicked(var data) { print(data + " clicked"); } Button { text: "Button1" } Button { text: "Button2" } } \endcode \o \code // Button.qml Rectangle { id: root property string text width: 80 height: 30 Text { anchors.centerIn: parent text: root.text } MouseRegion { anchors.fill: parent onClicked: buttonClicked(text) } } \endcode \endtable The code above discourages the re-use of the \c Button component, as it has a hard dependency on the environment in which it is used. Tightly coupling two types together like this should only be used when the components are within the same module, and the author controls the implementations of both. In the following example, the \l ListView sets the parent component instance of each of its delegates to its own component instance. In this way, the main component can easily pass data into the \l ListView delegates. \code Item { property color delegateColor: "red" ListView { delegate: Component { Rectangle { color: delegateColor } } } } \endcode \section1 QmlContext chain The \l QmlContext chain allows C++ applications to pass data into QML applications. \l QmlComponent object instances created from C++ are passed a \l QmlContext in which they are created. Variables defined in this context appear in the scope chain. Each QmlContext also defines a parent context. Variables in child QmlContext's shadow those in its parent. Consider the following QmlContext tree. \image qml-context-tree.png The value of \c background in \c {Context 1} would be used if it was instantiated in \c {Context 1}, where as the value of the \c background in the root context would be used if the component instance was instantiated in \c {Context 2}. \code import Qt 4.6 Rectangle { id: myRect width: 100; height: 100 color: background } \endcode \section1 QML Global Object The \l {QML Global Object} contains all the properties of the ECMAScript global object, plus some QML specific extensions. */