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

Last change on this file since 109 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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