Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / ground / gcs / src / shared / scriptwrapper / wrap_helpers.h
blob8c045227f041f84c1154d12e7537663a0a4bb045
1 /**
2 ******************************************************************************
4 * @file wrap_helpers.h
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
7 * @brief
8 * @see The GNU Public License (GPL) Version 3
9 * @defgroup
10 * @{
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
22 * for more details.
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
40 template <class T>
41 struct RemoveConstRef {
42 typedef T Result;
45 template <class T>
46 struct RemoveConstRef<const T &> {
47 typedef T Result;
50 // Template that retrieves a QObject-derived class from a QScriptValue.
52 template <class QObjectDerived>
53 QObjectDerived *qObjectFromScriptValue(const QScriptValue &v)
55 if (!v.isQObject()) {
56 return 0;
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);
72 if (!wrapper) {
73 return 0;
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);
88 Q_ASSERT(wrapped);
89 return wrapped;
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);
131 if (!c) {
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) {
225 return voidRC;
228 ThisWrapped *thisWrapped = wrappedThisFromContext(context, thisWrappedAccessor);
229 ArgumentWrapped *aw = wrappedFromScriptValue(context->argument(0), argumentWrappedAccessor);
230 if (acceptNullArgument || aw) {
231 (thisWrapped->*member)(aw);
233 return voidRC;
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!
261 quint32 i = 0;
263 for (; i1 != i2; ++i1, i++) {
264 Wrapper *wrapper = new Wrapper(*engine, *i1);
265 rc.setProperty(i, *wrapper);
267 return rc;
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)
276 QList<Wrapped *> rc;
278 if (!v.isArray()) {
279 return rc;
282 const quint32 len = v.property(QLatin1String("length")).toUInt32();
283 if (!len) {
284 return rc;
287 for (quint32 i = 0; i < len; i++) {
288 const QScriptValue e = v.property(i);
289 if (e.isQObject()) {
290 QObject *o = e.toQObject();
291 if (Wrapper * wrapper = qobject_cast<Wrapper *>(o)) {
292 rc.push_back((wrapper->*wrappedAccessor)());
296 return rc;
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);
332 Q_ASSERT(p);
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