source: trunk/doc/src/porting/porting-qsa.qdoc

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 19.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:FDL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in a
14** written agreement between you and Nokia.
15**
16** GNU Free Documentation License
17** Alternatively, this file may be used under the terms of the GNU Free
18** Documentation License version 1.3 as published by the Free Software
19** Foundation and appearing in the file included in the packaging of this
20** file.
21**
22** If you have questions regarding the use of this file, please contact
23** Nokia at qt-info@nokia.com.
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29 \title Moving from QSA to Qt Script
30 \page porting-qsa.html
31 \ingroup porting
32
33 The purpose of this document is to map the differences between Qt
34 Script for Applications (QSA) and Qt Script, the ECMAScript compatible
35 engine supplied with Qt 4.3. This document is not supposed to be a
36 complete function by function porting guide, but will cover the most
37 obvious aspects.
38
39 First of all it is important to realize that Qt Script is only an
40 interpreter, it does not provide an editor, completion or script project
41 management, like QSA does. Qt Script however does provides almost full
42 compliance with the ECMAScript standard and performs significantly
43 better than the script engine provided by QSA.
44
45 \tableofcontents
46
47 \section1 The Scripting Language
48
49 The scripting language used in QSA, from here on referred to as QSA,
50 was derived from ECMAScript 3.0 and 4.0 and is a hybrid of these
51 standards. Most of the run-time logic, such as classes and scoping
52 rules, is based on the ECMAScript 4.0 proposal, while the library
53 implementation is based on the ECMAScript 3.0 standard.
54 Qt Script on the other hand is solely based on the ECMAScript 3.0
55 standard. Though the languages look identical at first glance,
56 there are a few differences that we'll cover in the sections below.
57
58
59 \section2 Classes vs. Objects and Properties
60
61 QSA implements classes and inheritance much in a familiar way to users
62 of other object oriented languages, like C++ and Java. However, the
63 ECMAScript 3.0 standard defines that everything is an object, and objects
64 can have named properties. For instance to create an point object with
65 the properties x and y one would write the following Qt Script code:
66
67 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 0
68
69 The object \c point in this case is constructed as a plain object and
70 we assign two properties, \c x and \c y, to it with the values 12 and
71 35. The \c point object is assigned to the "Global Object" as the
72 named property \c{point}. The global object can be considered the
73 global namespace of the script engine. Similarly, global functions are
74 named properties of the global object; for example:
75
76 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 1
77
78 An equivalent construction that illustrates that the function is a
79 property of the global object is the following assignment:
80
81 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 2
82
83 Since functions are objects, they can be assigned to objects as
84 properties, becoming member functions:
85
86 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 3
87
88 In the code above, we see the first subtle difference between
89 QSA and Qt Script. In QSA one would write the point class like this:
90
91 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 4
92
93 where in the \c manhattanLength() function we access \c x and \c y
94 directly because, when the function is called, the \c this object is
95 implicitly part of the current scope, as in C++. In Qt Script,
96 however, this is not the case, and we need to explicitly access
97 the \c x and \c y values via \c{this}.
98
99 All the code above runs with QSA except the assignment of a function
100 to \c{point.manhattanLength}, which we repeat here for clarity:
101
102 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 5
103
104 This is because, in QSA, the value of \c this is decided based on
105 the location of the declaration of the function it is used in. In the
106 code above, the function is assigned to an object, but it is declared
107 in the global scope, hence there will be no valid \c this value.
108 In Qt Script, the value of \c this is decided at run-time,
109 hence you could have assigned the \c manhattanLength() function to any
110 object that had \c x and \c y values.
111
112
113 \section2 Constructors
114
115 In the code above, we use a rather awkward method for constructing
116 the objects, by first instantiating them, then manually
117 assigning properties to them. In QSA, the proper way to solve this
118 is to implement a constructor in the class:
119
120 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 6
121
122 The equivalent in Qt Script is to create a constructor function:
123
124 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 7
125
126 As we can see, the constructor is just a normal function. What is
127 special with is how we call it, namely prefixed with the \c new
128 keyword. This will create a new object and call the \c Car()
129 function with the newly created object as the \c this pointer.
130 So, in a sense, it is equivalent to:
131
132 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 8
133
134 This is similar to the manhattenLength() example above. Again, the
135 main difference between QSA and Qt Script is that one has to
136 explicitly use the keyword \c this to access the members and that
137 instead of declaring the variable, \c regNumber, we just extend the
138 \c this object with the property.
139
140
141 \section2 Member Functions and Prototypes
142
143 As we saw above, one way of creating member functions of a Qt Script
144 object is to assign the member function to the object as a property
145 and use the \c this object inside the functions. So, if we add a
146 \c toString function to the \c Car class
147
148 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 9
149
150 one could write this in Qt Script as:
151
152 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 10
153
154 In QSA, the member functions were part of the class declaration,
155 and were therefore shared between all instances of a given class.
156 In Qt Script, each instance has a instance member for each function.
157 This means that more memory is used when multiple instances are used.
158 Qt Script uses prototypes to remedy this.
159
160 The basic prototype-based inheritance mechanism works as follows.
161 Each Qt Script object has an internal link to another object, its
162 prototype. When a property is looked up in an object, and the object
163 itself does not have the property, the interpreter searches for the
164 property in the prototype object instead; if the prototype has the
165 property then that property is returned. If the prototype object does
166 not have the property, the interpreter searches for the property in
167 the prototype of the prototype object, and so on.
168
169 This chain of objects constitutes a prototype chain. The chain of
170 prototype objects is followed until the property is found or the end
171 of the chain is reached.
172
173 To make the \c toString() function part of the prototype, we write
174 code like this:
175
176 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 11
177
178 Here, we made the \c toString() function part of the prototype so
179 that, when we call \c{car.toString()} it will be resolved via the
180 internal prototype object of the car object. Note, however, that the
181 \c this object is still the original object that the function was
182 called on, namely \c{car}.
183
184
185 \section2 Inheritance
186
187 Now that we've seen how to use prototypes to create a "class" members
188 in Qt Script, let's see how we can use prototypes to create
189 polymorphism. In QSA you would write
190
191 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 12
192
193 With Qt Script, we acheive the same effect by creating a prototype
194 chain. The default prototype of an object is a plain \c Object
195 without any special members, but it is possible to replace this
196 object with another prototype object.
197
198 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 13
199
200 In the code above, we have a constructor, \c{GasolineCar}, which
201 calls the "base class" implementation of the constructor to
202 initialize the \c this object with the property \c{regNumber},
203 based on the values passed in the constructor. The interesting line
204 in this case is the line after the constructor where we change the
205 default prototype for \c GasolineCar to be an instance of type
206 \c{Car}. This means that all members available in a \c Car object
207 are now available in all \c GasolineCar objects. In the last line,
208 we replace the \c toString() function in the prototype with our own,
209 thus overriding the \c toString() for all instances of
210 \c{GasolineCar}.
211
212
213 \section2 Static Members
214
215 QSA allowed users to declare static members in classes, and these
216 could be accessed both through instances of the class and through
217 the class itself. For example, the following variable is accessed
218 through the \c Car class:
219
220 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 14
221
222 The equivalent in Qt Script is to assign variables that should appear
223 as static members as properties of the constructor function. For
224 example:
225
226 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 15
227
228 Note that in QSA, static member variables were also accessible in
229 instances of the given class. In Qt Script, with the approach
230 illustrated above, the variable is a member of the constructor
231 object only, and thus only accessible through \c{Car.globalCount}.
232
233
234 \section1 The Built-in Functions and Library
235
236 The built-in functions in QSA are based on those defined in the
237 ECMAScript 3.0 standard, the same standard used for Qt Script, but
238 QSA adds some extensions to this, specifically for the \c String
239 and \c RegExp types. QSA also lacked some functions from the
240 standard, most notably the \c Date type. Below we list all the
241 differences. All changes made to Qt Script are to increase
242 compliance with ECMAScript 3.0.
243
244 \table
245 \header \o QSA Function \o Notes about Equivalent Qt Script Functions
246 \row \o eval()
247 \o The eval function in QSA opened a new scope for code being
248 executed in the eval function, so locally declared variables were not
249 accessible outside. In Qt Script, the eval() function shares the
250 current scope, making locally declared variables accessible outside
251 the eval() call.
252
253 \row \o debug()
254 \o This function is not available in Qt Script. Use print() instead.
255
256 \row \o connect()
257 \o QSA had closures, meaning that a member function
258 reference implicitly contained its \c this object. Qt Script does not
259 support this. See the Qt Script documentation for details on using the
260 connect function.
261
262 \row \o String.arg()
263 \o This function is not available in Qt Script. Use replace() or concat() instead.
264
265 \row \o String.argDec()
266 \o This function is not available in Qt Script. Use replace() or concat() instead.
267
268 \row \o String.argInt()
269 \o This function is not available in Qt Script. Use replace() or concat() instead.
270
271 \row \o String.argStr()
272 \o This function is not available in Qt Script. Use replace() or concat() instead.
273
274 \row \o String.endsWith()
275 \o This function is not available in Qt Script. Use lastIndexOf() instead.
276
277 \row \o String.find()
278 \o This function is not available in Qt Script. Use indexOf() instead.
279
280 \row \o String.findRev()
281 \o This function is not available in Qt Script. Use lastIndexOf() and length instead.
282
283 \row \o String.isEmpty()
284 \o This function is not available in Qt Script. Use length == 0 instead.
285
286 \row \o String.left()
287 \o This function is not available in Qt Script. Use substring() instead.
288
289 \row \o String.lower()
290 \o This function is not available in Qt Script. Use toLowerCase() instead.
291
292 \row \o String.mid()
293 \o This function is not available in Qt Script. Use substring() instead.
294
295 \row \o String.right()
296 \o This function is not available in Qt Script. Use substring() instead.
297
298 \row \o String.searchRev()
299 \o This function is not available in Qt Script. Use search() / match() instead.
300
301 \row \o String.startsWith()
302 \o This function is not available in Qt Script. Use indexOf() == 0 instead.
303
304 \row \o String.upper()
305 \o This function is not available in Qt Script. Use toUpperCase() instead.
306
307 \row \o RegExp.valid
308 \o This property is not available in Qt Script because it is not
309 required; a \c SyntaxError exception is thrown for bad \c RegExp objects.
310
311 \row \o RegExp.empty
312 \o This property is not available in Qt Script. Use \c{toString().length == 0} instead.
313
314 \row \o RegExp.matchedLength
315 \o This property is not available in Qt Script. RegExp.exec() returns an
316 array whose size is the matched length.
317
318 \row \o RegExp.capturedTexts
319 \o This property is not available in Qt Script. RegExp.exec() returns an
320 array of captured texts.
321
322 \row \o RegExp.search()
323 \o This function is not available in Qt Script. Use RegExp.exec() instead.
324
325 \row \o RegExp.searchRev()
326 \o This function is not available in Qt Script. Use RegExp.exec() or
327 String.search()/match() instead.
328
329 \row \o RegExp.exactMatch()
330 \o This function is not available in Qt Script. Use RegExp.exec() instead.
331
332 \row \o RegExp.pos()
333 \o This function is not available in Qt Script. Use String.match() instead.
334
335 \row \o RegExp.cap()
336 \o This function is not available in Qt Script. RegExp.exec() returns an
337 array of captured texts.
338 \endtable
339
340 QSA also defined some internal Qt API which is not present in Qt
341 Script. The types provided by QSA which are not provided by Qt Script are:
342
343 \list
344 \o Rect
345 \o Point
346 \o Size
347 \o Color
348 \o Palette
349 \o ColorGroup
350 \o Font
351 \o Pixmap
352 \o ByteArray
353 \endlist
354
355
356 \section1 The C++ API of QSA vs Qt Script
357
358 QSA is more than just a scripting engine. It provides project
359 management, an editor with completion and a minimalistic IDE to edit
360 scriptable projects. Qt Script on the other hand is just a scripting
361 engine. This means that equivalents to the classes \c QSEditor,
362 \c QSScript, \c QSProject and \c QSWorkbench do not exist in Qt Script.
363 QSA also provides some extension APIs through the \c QSUtilFactory and
364 \c QSInputDialogFactory. There is also no equivalent to these classes
365 in the Qt Script API.
366
367
368 \section2 Making QObjects Accessible from Scripts
369
370 There are two different ways of making \l{QObject}s accessible from
371 scripts in QSA. The first method is via the
372 \c QSInterpreter::addTransientObject() and \c QSProject::addObject()
373 functions. In this case objects are added to the global namespace of
374 the interpreter using their object names as the names of the
375 variables.
376
377 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 16
378
379 The code above adds the button to the global namespace under the name
380 "button". One obvious limitation here is that there is potential for
381 either unnamed \l{QObject}s or objects whose names conflict. Qt Script
382 provides a more flexible way of adding QObjects to the scripting
383 environment.
384
385 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 17
386
387 In the code above we create a QPushButton and wrap it in a script
388 value using the function, QScriptEngine::newQObject(). This gives us
389 a script value that we put into the global object using the name
390 "button". The concept of objects and properties discussed above is
391 quite visible here in the public C++ API as well. We have no
392 dependency on the object's name and we can also resolve name conflicts
393 more gracefully. Here, we operate directly on QScriptValue objects.
394 This is the actual object that is being passed around inside
395 the script engine, so we actually have low-level access to the
396 internal script data structures, far beyond that which is possible
397 in QSA. Properties, signals and slots of the QObject are accessible
398 to the scripter in Qt Script, just like in QSA.
399
400 The other way to expose \l{QObject}s in QSA was to create a
401 \c QSObjectFactory that made it possible to instantiate QObjects from
402 scripts.
403
404 Below is listed some code from the filter example in the QSA
405 package.
406
407 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 18
408
409 The equivalent in Qt Script is written in much the same way as
410 constructors are written in scripts. We register a callback C++
411 function under the name "ImageSource" in the global namespace and
412 return the QObject from this function:
413
414 \snippet doc/src/snippets/code/doc_src_porting-qsa.qdoc 19
415
416 In the Qt Script case we use the same approach that we use to expose
417 a QObject, namely via QScriptEngine::newQObject(). This function also
418 has the benefit that it is possible to specify if the QObject should
419 expose properties and slots of its base class. It is also possible to
420 specify custom ownership rules.
421
422 The reader might question why we don't add the constructor function
423 directly into the namespace, but create a meta-object script value for
424 it in addition. The plain function would certainly be good enough,
425 but by creating a QMetaObject based constructor we get the enums on
426 QPushButton for free in the QPushButton function object. Exposing
427 enums in QSA is rather painful in comparison.
428
429 If we want to add more "static" data to the QPushButton type in Qt
430 Script, we're free to add properties, similar to how we did for
431 the script. It is also possible to add custom functions to a Qt Script
432 QPushButton instance by setting more properties on it, such as making
433 the \l{QPushButton::}{setText()} C++ function available. It is also
434 possible to acheive this by installing a custom prototype, and be
435 memory efficient, as discussed in the script example above.
436
437
438 \section2 Accessing Non-QObjects
439
440 In QSA, it was possible to expose non-QObjects to QSA by wrapping them
441 in a QObject and using either \c QSWrapperFactory or \c QSObjectFactory
442 to expose them. Deciding when to use each of these classes could be
443 confusing, as one was used for script based construction and the other
444 for wrapping function parameters and return values, but in essence they
445 did exactly the same thing.
446
447 In Qt Script, providing access to QObjects and non-QObjects is done in
448 the same way as shown above, by creating a constructor function, and
449 by adding properties or a custom prototype to the constructed object.
450
451
452 \section2 Data Mapping
453
454 QSA supported a hardcoded set of type mappings which covered most
455 of the QVariant types, QObjects and primitives. For more complex type
456 signatures, such as the template-based tool classes, it had rather
457 limited support. Qt Script is significantly better at type mapping
458 and will convert lists of template types into arrays of the
459 appropriate types, given that all the types are declared to the
460 meta-type system.
461*/
Note: See TracBrowser for help on using the repository browser.