2 ******************************************************************************
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
8 * @see The GNU Public License (GPL) Version 3
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #ifndef WRAP_HELPERS_H
30 #define WRAP_HELPERS_H
32 #include <QtScript/QScriptEngine>
33 #include <QtScript/QScriptContext>
34 #include <QtScript/QScriptValue>
36 namespace SharedTools
{
37 // Strip a const ref from a type via template specialization trick.
38 // Use for determining function call args
41 struct RemoveConstRef
{
46 struct RemoveConstRef
<const T
&> {
50 // Template that retrieves a QObject-derived class from a QScriptValue.
52 template <class QObjectDerived
>
53 QObjectDerived
*qObjectFromScriptValue(const QScriptValue
&v
)
58 QObject
*o
= v
.toQObject();
59 return qobject_cast
<QObjectDerived
*>(o
);
62 // Template that retrieves a wrapped object from a QScriptValue.
63 // The wrapped object is accessed through an accessor of
64 // the QObject-derived wrapper.
66 template <class Wrapper
, class Wrapped
>
67 Wrapped
*wrappedFromScriptValue(const QScriptValue
&v
,
68 Wrapped
* (Wrapper::*wrappedAccessor
)() const)
70 Wrapper
*wrapper
= qObjectFromScriptValue
<Wrapper
>(v
);
75 return (wrapper
->*wrappedAccessor
)();
78 // Template that retrieves a wrapped object from
79 // a QObject-derived script wrapper object that is set as 'this' in
80 // a script context via accessor.
82 template <class Wrapper
, class Wrapped
>
83 static inline Wrapped
*wrappedThisFromContext(QScriptContext
*context
,
84 Wrapped
* (Wrapper::*wrappedAccessor
)() const)
86 Wrapped
*wrapped
= wrappedFromScriptValue(context
->thisObject(), wrappedAccessor
);
92 // Template that retrieves an object contained in a wrapped object
93 // in a script getter call (namely the interfaces returned by
94 // the core interface accessors). Mangles out the wrapper object from
95 // thisObject(), accesses the wrapped object and returns the contained object.
97 template <class Contained
, class Wrapper
, class Wrapped
>
98 static inline Contained
*containedFromContext(QScriptContext
*context
,
99 Wrapped
* (Wrapper::*wrappedAccessor
)() const,
100 Contained
* (Wrapped::*containedAccessor
)() const)
102 Wrapped
*wrapped
= wrappedThisFromContext(context
, wrappedAccessor
);
104 return (wrapped
->*containedAccessor
)();
107 // Template that retrieves a contained QObject-type object
108 // in a script getter call and creates a new script-object via engine->newQObject().
109 // To be called from a script getter callback.
111 template <class Contained
, class Wrapper
, class Wrapped
>
112 static inline QScriptValue
containedQObjectFromContextToScriptValue(QScriptContext
*context
, QScriptEngine
*engine
,
113 Wrapped
* (Wrapper::*wrappedAccessor
)() const,
114 Contained
* (Wrapped::*containedAccessor
)() const)
116 return engine
->newQObject(containedFromContext(context
, wrappedAccessor
, containedAccessor
));
119 // Template that retrieves a contained Non-QObject-type object
120 // in a script getter call and creates a new script-object by wrapping it into
121 // a new instance of ContainedWrapper (which casts to QScriptValue).
122 // To be called from a script getter callback.
124 template <class ContainedWrapper
, class Contained
, class Wrapper
, class Wrapped
>
125 static inline QScriptValue
wrapContainedFromContextAsScriptValue(QScriptContext
*context
, QScriptEngine
*engine
,
126 Wrapped
* (Wrapper::*wrappedAccessor
)() const,
127 Contained
* (Wrapped::*containedAccessor
)() const)
129 Contained
*c
= containedFromContext(context
, wrappedAccessor
, containedAccessor
);
132 return QScriptValue(engine
, QScriptValue::NullValue
);
135 ContainedWrapper
*cw
= new ContainedWrapper(*engine
, c
);
136 return *cw
; // cast to QScriptValue
139 // Template that retrieves a wrapped object from context (this)
140 // and calls a const-member function with no parameters.
141 // To be called from a script getter callback.
143 template <class Ret
, class Wrapper
, class Wrapped
>
144 static inline QScriptValue
scriptCallConstMember_0(QScriptContext
*context
, QScriptEngine
*engine
,
145 Wrapped
* (Wrapper::*wrappedAccessor
)() const,
146 Ret (Wrapped::*member
)() const)
148 Wrapped
*wrapped
= wrappedThisFromContext(context
, wrappedAccessor
);
150 return engine
->toScriptValue((wrapped
->*member
)());
153 // Ditto for non-const
155 template <class Ret
, class Wrapper
, class Wrapped
>
156 static inline QScriptValue
scriptCallMember_0(QScriptContext
*context
, QScriptEngine
*engine
,
157 Wrapped
* (Wrapper::*wrappedAccessor
)() const,
158 Ret (Wrapped::*member
)())
160 Wrapped
*wrapped
= wrappedThisFromContext(context
, wrappedAccessor
);
162 return engine
->toScriptValue((wrapped
->*member
)());
165 // Template that retrieves a wrapped object from context (this)
166 // and calls a const-member function with 1 parameter on it.
167 // To be called from a script getter callback.
169 template <class Ret
, class Argument
, class Wrapper
, class Wrapped
>
170 static inline QScriptValue
scriptCallConstMember_1(QScriptContext
*context
, QScriptEngine
*engine
,
171 Wrapped
* (Wrapper::*wrappedAccessor
)() const,
172 Ret (Wrapped::*member
)(Argument a1
) const)
174 const int argumentCount
= context
->argumentCount();
176 if (argumentCount
!= 1) {
177 return QScriptValue(engine
, QScriptValue::NullValue
);
180 Wrapped
*wrapped
= wrappedThisFromContext(context
, wrappedAccessor
);
181 // call member. If the argument is a const ref, strip it.
182 typedef typename RemoveConstRef
<Argument
>::Result ArgumentBase
;
183 ArgumentBase a
= qscriptvalue_cast
<ArgumentBase
>(context
->argument(0));
184 return engine
->toScriptValue((wrapped
->*member
)(a
));
187 // Template that retrieves a wrapped object
188 // and calls a member function with 1 parameter on it.
189 // To be called from a script getter callback.
191 template <class Ret
, class Argument
, class Wrapper
, class Wrapped
>
192 static inline QScriptValue
scriptCallMember_1(QScriptContext
*context
, QScriptEngine
*engine
,
193 Wrapped
* (Wrapper::*wrappedAccessor
)() const,
194 Ret (Wrapped::*member
)(Argument a1
))
196 const int argumentCount
= context
->argumentCount();
198 if (argumentCount
!= 1) {
199 return QScriptValue(engine
, QScriptValue::NullValue
);
202 Wrapped
*wrapped
= wrappedThisFromContext(context
, wrappedAccessor
);
203 // call member. If the argument is a const ref, strip it.
204 typedef typename RemoveConstRef
<Argument
>::Result ArgumentBase
;
205 ArgumentBase a
= qscriptvalue_cast
<ArgumentBase
>(context
->argument(0));
206 return engine
->toScriptValue((wrapped
->*member
)(a
));
209 // Template that retrieves a wrapped object
210 // and calls a void member function with 1 parameter that is a wrapper of
211 // of some interface.
212 // Typically used for something like 'setCurrentEditor(Editor*)'
213 // To be called from a script callback.
215 template <class ThisWrapper
, class ThisWrapped
, class ArgumentWrapper
, class ArgumentWrapped
>
216 static QScriptValue
scriptCallVoidMember_Wrapped1(QScriptContext
*context
, QScriptEngine
*engine
,
217 ThisWrapped
* (ThisWrapper::*thisWrappedAccessor
)() const,
218 ArgumentWrapped
*(ArgumentWrapper::*argumentWrappedAccessor
)() const,
219 void (ThisWrapped::*member
)(ArgumentWrapped
*a1
),
220 bool acceptNullArgument
= false)
222 const QScriptValue voidRC
= QScriptValue(engine
, QScriptValue::UndefinedValue
);
224 if (context
->argumentCount() < 1) {
228 ThisWrapped
*thisWrapped
= wrappedThisFromContext(context
, thisWrappedAccessor
);
229 ArgumentWrapped
*aw
= wrappedFromScriptValue(context
->argument(0), argumentWrappedAccessor
);
230 if (acceptNullArgument
|| aw
) {
231 (thisWrapped
->*member
)(aw
);
236 // Macros that define the static functions to call members
238 #define SCRIPT_CALL_CONST_MEMBER_0(funcName, accessor, member) \
239 static QScriptValue funcName(QScriptContext * context, QScriptEngine * engine) \
240 { return SharedTools::scriptCallConstMember_0(context, engine, accessor, member); }
242 #define SCRIPT_CALL_MEMBER_0(funcName, accessor, member) \
243 static QScriptValue funcName(QScriptContext * context, QScriptEngine * engine) \
244 { return SharedTools::scriptCallMember_0(context, engine, accessor, member); }
246 #define SCRIPT_CALL_CONST_MEMBER_1(funcName, accessor, member) \
247 static QScriptValue funcName(QScriptContext * context, QScriptEngine * engine) \
248 { return SharedTools::scriptCallConstMember_1(context, engine, accessor, member); }
250 #define SCRIPT_CALL_MEMBER_1(funcName, accessor, member) \
251 static QScriptValue funcName(QScriptContext * context, QScriptEngine * engine) \
252 { return SharedTools::scriptCallMember_1(context, engine, accessor, member); }
254 // Create a script list of wrapped non-qobjects by wrapping them.
255 // Wrapper must cast to QScriptValue.
257 template <class Wrapper
, class Iterator
>
258 static inline QScriptValue
wrapObjectList(QScriptEngine
*engine
, Iterator i1
, Iterator i2
)
260 QScriptValue rc
= engine
->newArray(i2
- i1
); // Grrr!
263 for (; i1
!= i2
; ++i1
, i
++) {
264 Wrapper
*wrapper
= new Wrapper(*engine
, *i1
);
265 rc
.setProperty(i
, *wrapper
);
270 // Unwrap a list of wrapped objects from a script list.
272 template <class Wrapper
, class Wrapped
>
273 static inline QList
<Wrapped
*> unwrapObjectList(const QScriptValue
&v
,
274 Wrapped
*(Wrapper::*wrappedAccessor
)() const)
282 const quint32 len
= v
.property(QLatin1String("length")).toUInt32();
287 for (quint32 i
= 0; i
< len
; i
++) {
288 const QScriptValue e
= v
.property(i
);
290 QObject
*o
= e
.toQObject();
291 if (Wrapper
* wrapper
= qobject_cast
<Wrapper
*>(o
)) {
292 rc
.push_back((wrapper
->*wrappedAccessor
)());
299 // Traditional registration of a prototype for an interface.
300 // that can be converted via script value casts via Q_DECLARE_METATYPE.
302 template <class Interface
, class Prototype
>
303 static void registerInterfaceWithDefaultPrototype(QScriptEngine
&engine
)
305 Prototype
*protoType
= new Prototype(&engine
);
306 const QScriptValue scriptProtoType
= engine
.newQObject(protoType
);
308 engine
.setDefaultPrototype(qMetaTypeId
<Interface
*>(), scriptProtoType
);
311 // Convert a class derived from QObject to Scriptvalue via engine->newQObject() to make
312 // the signals, slots and properties visible.
313 // To be registered as a magic creation function with qScriptRegisterMetaType().
314 // (see registerQObject()
316 template <class SomeQObject
>
317 static QScriptValue
qObjectToScriptValue(QScriptEngine
*engine
, SomeQObject
*const &qo
)
319 return engine
->newQObject(qo
, QScriptEngine::QtOwnership
, QScriptEngine::ExcludeChildObjects
);
322 // Convert Scriptvalue back to a class derived from QObject via QScriptValue::toQObject()
323 // To be registered as a magic conversion function with qScriptRegisterMetaType().
324 // (see registerQObject)
326 template <class SomeQObject
>
327 static void scriptValueToQObject(const QScriptValue
&sv
, SomeQObject
* &p
)
329 QObject
*qObject
= sv
.toQObject();
331 p
= qobject_cast
<SomeQObject
*>(qObject
);
335 // Register a QObject-derived class which has Q_DECLARE_METATYPE(Ptr*)
336 // with the engine using qObjectToScriptValue/scriptValueToQObject as
337 // conversion functions to make it possible to use for example
338 // Q_PROPERTY(QMainWindow*).
340 template <class SomeQObject
>
341 static void registerQObject(QScriptEngine
*engine
)
343 qScriptRegisterMetaType
<SomeQObject
*>(engine
,
344 qObjectToScriptValue
<SomeQObject
>,
345 scriptValueToQObject
<SomeQObject
>);
347 } // namespace SharedTools
349 #endif // WRAP_HELPERS_H