1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtScript module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qscriptclass.h" |
41 | #include "qscriptstring.h" |
42 | |
43 | /*! |
44 | \since 4.4 |
45 | \class QScriptClass |
46 | \inmodule QtScript |
47 | \brief The QScriptClass class provides an interface for defining custom behavior of (a class of) Qt Script objects. |
48 | |
49 | \ingroup script |
50 | |
51 | The QScriptClass class defines an interface for handling various |
52 | aspects of interaction with the Qt Script objects associated with |
53 | the class. Such objects are created by calling |
54 | QScriptEngine::newObject(), passing a pointer to the QScriptClass as |
55 | argument. |
56 | |
57 | By subclassing QScriptClass, you can define precisely how access to |
58 | properties of the objects that use your class is handled. This |
59 | enables a fully dynamic handling of properties, e.g. it's more |
60 | powerful than QScriptEngine::newQObject(). For example, you can use |
61 | QScriptClass to implement array-type objects (i.e. objects that |
62 | handle the \c{length} property, and properties whose names are valid |
63 | array indexes, in a special way), or to implement a "live" |
64 | (runtime-defined) proxy to an underlying object. |
65 | |
66 | If you just need to handle access to a set of properties that are |
67 | known at the time an object is created (i.e. "semi-statically"), you |
68 | might consider using QScriptValue::setProperty() to define |
69 | getter/setter functions for the relevant properties, rather than |
70 | subclassing QScriptClass. |
71 | |
72 | Reimplement queryProperty() to specify which properties are handled |
73 | in a custom way by your script class (i.e. should be |
74 | \b{delegated} to the QScriptClass), and which properties should |
75 | be handled just like normal Qt Script object properties. |
76 | |
77 | Reimplement property() and setProperty() to perform the actual |
78 | access (read or write) to the properties that your class |
79 | handles. Additionally, you can reimplement propertyFlags() to |
80 | specify custom flags for your properties. |
81 | |
82 | Reimplement newIterator() to provide an iterator for objects of your |
83 | custom class. This is only necessary if objects of your class can |
84 | have custom properties that you want to be reported when an object |
85 | is used together with the QScriptValueIterator class, or when an |
86 | object is used in a for-in enumeration statement in a script. |
87 | |
88 | When implementing custom classes of objects, you typically use |
89 | QScriptValue::setData() to store instance-specific data as part of |
90 | object initialization; the data won't be accessible from scripts |
91 | directly, but you can access it in e.g. your reimplementations of |
92 | property() and setProperty() (by calling QScriptValue::data()) to |
93 | perform custom processing. |
94 | |
95 | Reimplement prototype() to provide a custom prototype object for |
96 | your script class. |
97 | |
98 | Reimplement supportsExtension() and extension() if your custom |
99 | script class supports one or more of the extensions specified by the |
100 | Extension enum. |
101 | |
102 | \sa QScriptClassPropertyIterator, QScriptEngine::newObject(), {Defining Custom Script Classes with QScriptClass} |
103 | */ |
104 | |
105 | /*! |
106 | \enum QScriptClass::Extension |
107 | |
108 | This enum specifies the possible extensions to a QScriptClass. |
109 | |
110 | \value Callable Instances of this class can be called as functions. |
111 | |
112 | \value HasInstance Instances of this class implement [[HasInstance]]. |
113 | |
114 | \sa extension() |
115 | */ |
116 | |
117 | /*! |
118 | \enum QScriptClass::QueryFlag |
119 | |
120 | This enum describes flags that are used to query a QScriptClass |
121 | regarding how access to a property should be handled. |
122 | |
123 | \value HandlesReadAccess The QScriptClass handles read access to this property. |
124 | \value HandlesWriteAccess The QScriptClass handles write access to this property. |
125 | |
126 | \sa queryProperty() |
127 | */ |
128 | |
129 | QT_BEGIN_NAMESPACE |
130 | |
131 | class QScriptClassPrivate |
132 | { |
133 | Q_DECLARE_PUBLIC(QScriptClass) |
134 | public: |
135 | QScriptClassPrivate() {} |
136 | virtual ~QScriptClassPrivate() {} |
137 | |
138 | QScriptEngine *engine; |
139 | |
140 | QScriptClass *q_ptr; |
141 | }; |
142 | |
143 | /*! |
144 | Constructs a QScriptClass object to be used in the given \a engine. |
145 | |
146 | The engine does not take ownership of the QScriptClass object. |
147 | */ |
148 | QScriptClass::QScriptClass(QScriptEngine *engine) |
149 | : d_ptr(new QScriptClassPrivate) |
150 | { |
151 | d_ptr->q_ptr = this; |
152 | d_ptr->engine = engine; |
153 | } |
154 | |
155 | /*! |
156 | \internal |
157 | */ |
158 | QScriptClass::QScriptClass(QScriptEngine *engine, QScriptClassPrivate &dd) |
159 | : d_ptr(&dd) |
160 | { |
161 | d_ptr->q_ptr = this; |
162 | d_ptr->engine = engine; |
163 | } |
164 | |
165 | /*! |
166 | Destroys the QScriptClass object. |
167 | |
168 | If a QScriptClass object is deleted before the associated engine(), |
169 | any Qt Script objects using the QScriptClass will be "demoted" to |
170 | normal Qt Script objects. |
171 | */ |
172 | QScriptClass::~QScriptClass() |
173 | { |
174 | } |
175 | |
176 | /*! |
177 | Returns the engine that this QScriptClass is associated with. |
178 | */ |
179 | QScriptEngine *QScriptClass::engine() const |
180 | { |
181 | Q_D(const QScriptClass); |
182 | return d->engine; |
183 | } |
184 | |
185 | /*! |
186 | Returns the object to be used as the prototype of new instances |
187 | of this class (created with QScriptEngine::newObject()). |
188 | |
189 | The default implementation returns an invalid QScriptValue, meaning |
190 | that the standard Object prototype will be used. Reimplement this |
191 | function to provide your own custom prototype. |
192 | |
193 | Typically you initialize your prototype object in the constructor of |
194 | your class, then return it in this function. |
195 | |
196 | See the "Making Use of Prototype-Based Inheritance" section in the |
197 | Qt Script documentation for more information on how prototypes are |
198 | used. |
199 | */ |
200 | QScriptValue QScriptClass::prototype() const |
201 | { |
202 | return QScriptValue(); |
203 | } |
204 | |
205 | /*! |
206 | Returns the name of the script class. |
207 | |
208 | Qt Script uses this name to generate a default string representation |
209 | of objects in case you do not provide a toString function. |
210 | |
211 | The default implementation returns a null string. |
212 | */ |
213 | QString QScriptClass::name() const |
214 | { |
215 | return QString(); |
216 | } |
217 | |
218 | /*! |
219 | Queries this script class for how access to the property with the |
220 | given \a name of the given \a object should be handled. The given \a |
221 | flags specify the aspects of interest. This function should return a |
222 | subset of \a flags to indicate which aspects of property access |
223 | should be further handled by the script class. |
224 | |
225 | For example, if the \a flags contain HandlesReadAccess, and you |
226 | would like your class to handle the reading of the property (through |
227 | the property() function), the returned flags should include |
228 | HandlesReadAccess. If the returned flags do not contain |
229 | HandlesReadAccess, the property will be handled as a normal script |
230 | object property. |
231 | |
232 | You can optionally use the \a id argument to store a value that will |
233 | subsequently be passed on to functions such as property() and |
234 | setProperty(). |
235 | |
236 | The default implementation of this function returns 0. |
237 | |
238 | Note: This function is only called if the given property isn't |
239 | already a normal property of the object. For example, say you |
240 | advertise that you want to handle read access to property \c{foo}, |
241 | but not write access; if \c{foo} is then assigned a value, it will |
242 | become a normal script object property, and subsequently you will no |
243 | longer be queried regarding read access to \c{foo}. |
244 | |
245 | \sa property() |
246 | */ |
247 | QScriptClass::QueryFlags QScriptClass::queryProperty( |
248 | const QScriptValue &object, const QScriptString &name, |
249 | QueryFlags flags, uint *id) |
250 | { |
251 | Q_UNUSED(object); |
252 | Q_UNUSED(name); |
253 | Q_UNUSED(flags); |
254 | Q_UNUSED(id); |
255 | return {}; |
256 | } |
257 | |
258 | /*! |
259 | Returns the value of the property with the given \a name of the given |
260 | \a object. |
261 | |
262 | The \a id argument is only useful if you assigned a value to it in |
263 | queryProperty(). |
264 | |
265 | The default implementation does nothing and returns an invalid QScriptValue. |
266 | |
267 | \sa setProperty(), propertyFlags() |
268 | */ |
269 | QScriptValue QScriptClass::property(const QScriptValue &object, |
270 | const QScriptString &name, uint id) |
271 | { |
272 | Q_UNUSED(object); |
273 | Q_UNUSED(name); |
274 | Q_UNUSED(id); |
275 | return QScriptValue(); |
276 | } |
277 | |
278 | /*! |
279 | Returns the flags of the property with the given \a name of the given |
280 | \a object. |
281 | |
282 | The \a id argument is only useful if you assigned a value to it in |
283 | queryProperty(). |
284 | |
285 | The default implementation returns 0. |
286 | |
287 | \sa property() |
288 | */ |
289 | QScriptValue::PropertyFlags QScriptClass::propertyFlags( |
290 | const QScriptValue &object, const QScriptString &name, uint id) |
291 | { |
292 | Q_UNUSED(object); |
293 | Q_UNUSED(name); |
294 | Q_UNUSED(id); |
295 | return {}; |
296 | } |
297 | |
298 | /*! |
299 | Sets the property with the given \a name of the given \a object to |
300 | the given \a value. |
301 | |
302 | The \a id argument is only useful if you assigned a value to it in |
303 | queryProperty(). |
304 | |
305 | The default implementation does nothing. |
306 | |
307 | An invalid \a value represents a request to remove the property. |
308 | |
309 | \sa property() |
310 | */ |
311 | void QScriptClass::setProperty(QScriptValue &object, const QScriptString &name, |
312 | uint id, const QScriptValue &value) |
313 | { |
314 | Q_UNUSED(object); |
315 | Q_UNUSED(name); |
316 | Q_UNUSED(id); |
317 | Q_UNUSED(value); |
318 | } |
319 | |
320 | /*! |
321 | Returns an iterator for traversing custom properties of the given \a |
322 | object. |
323 | |
324 | The default implementation returns 0, meaning that there are no |
325 | custom properties to traverse. |
326 | |
327 | Reimplement this function if objects of your script class can have |
328 | one or more custom properties (e.g. those reported to be handled by |
329 | queryProperty()) that you want to appear when an object's properties |
330 | are enumerated (e.g. by a for-in statement in a script). |
331 | |
332 | Qt Script takes ownership of the new iterator object. |
333 | |
334 | \sa QScriptValueIterator |
335 | */ |
336 | QScriptClassPropertyIterator *QScriptClass::newIterator(const QScriptValue &object) |
337 | { |
338 | Q_UNUSED(object); |
339 | return 0; |
340 | } |
341 | |
342 | /*! |
343 | Returns true if the QScriptClass supports the given \a extension; |
344 | otherwise, false is returned. By default, no extensions |
345 | are supported. |
346 | |
347 | Reimplement this function to indicate which extensions your custom |
348 | class supports. |
349 | |
350 | \sa extension() |
351 | */ |
352 | bool QScriptClass::supportsExtension(Extension extension) const |
353 | { |
354 | Q_UNUSED(extension); |
355 | return false; |
356 | } |
357 | |
358 | /*! |
359 | This virtual function can be reimplemented in a QScriptClass |
360 | subclass to provide support for extensions. The optional \a argument |
361 | can be provided as input to the \a extension; the result must be |
362 | returned in the form of a QVariant. You can call supportsExtension() |
363 | to check if an extension is supported by the QScriptClass. By |
364 | default, no extensions are supported, and this function returns an |
365 | invalid QVariant. |
366 | |
367 | If you implement the Callable extension, Qt Script will call this |
368 | function when an instance of your class is called as a function |
369 | (e.g. from a script or using QScriptValue::call()). The \a argument |
370 | will contain a pointer to the QScriptContext that represents the |
371 | function call, and you should return a QVariant that holds the |
372 | result of the function call. In the following example the sum of the |
373 | arguments to the script function are added up and returned: |
374 | |
375 | \snippet code/src_script_qscriptclass.cpp 0 |
376 | |
377 | If you implement the HasInstance extension, Qt Script will call this |
378 | function as part of evaluating the \c{instanceof} operator, as |
379 | described in ECMA-262 Section 11.8.6. The \a argument is a |
380 | QScriptValueList containing two items: The first item is the object |
381 | that HasInstance is being applied to (an instance of your class), |
382 | and the second item can be any value. extension() should return true |
383 | if the value delegates behavior to the object, false otherwise. |
384 | |
385 | \sa supportsExtension() |
386 | */ |
387 | QVariant QScriptClass::extension(Extension extension, const QVariant &argument) |
388 | { |
389 | Q_UNUSED(extension); |
390 | Q_UNUSED(argument); |
391 | return QVariant(); |
392 | } |
393 | |
394 | QT_END_NAMESPACE |
395 | |