diff options
Diffstat (limited to 'doc/src/declarative/scope.qdoc')
-rw-r--r-- | doc/src/declarative/scope.qdoc | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/doc/src/declarative/scope.qdoc b/doc/src/declarative/scope.qdoc new file mode 100644 index 0000000..fc678d1 --- /dev/null +++ b/doc/src/declarative/scope.qdoc @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** 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. +*/ |