summaryrefslogtreecommitdiffstats
path: root/doc/src/declarative/scope.qdoc
blob: ef30f94cd7bda0788c0a8a7c2528b14890cdd189 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
/****************************************************************************
**
** 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

\tableofcontents

\l {Property Binding}s and \l {ECMAScript Blocks} are executed in a scope chain automatically 
established by QML when a component instance is constructed.  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 defined.  The following example shows
three different bindings, and the component that dictates each 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 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.

Here 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 affected, 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}.

A sub-component's parent component instance is set to the component that created it.
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.
*/