00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef QTSCRIPTEXTENSIONS_GLOBAL_H
00039 #define QTSCRIPTEXTENSIONS_GLOBAL_H
00040
00041 #include <QtCore/QSharedData>
00042
00043 #define DECLARE_SELF(Class, __fn__) \
00044 Class* self = qscriptvalue_cast<Class*>(ctx->thisObject()); \
00045 if (!self) { \
00046 return ctx->throwError(QScriptContext::TypeError, \
00047 QString::fromLatin1("%0.prototype.%1: this object is not a %0") \
00048 .arg(#Class).arg(#__fn__)); \
00049 }
00050
00051 #define DECLARE_SELF2(Class, __fn__, __ret__) \
00052 Class* self = qscriptvalue_cast<Class*>(thisObject()); \
00053 if (!self) { \
00054 context()->throwError(QScriptContext::TypeError, \
00055 QString::fromLatin1("%0.prototype.%1: this object is not a %0") \
00056 .arg(#Class).arg(#__fn__)); \
00057 return __ret__; \
00058 }
00059
00060
00061
00062 #define ADD_METHOD(__p__, __f__) \
00063 __p__.setProperty(#__f__, __p__.engine()->newFunction(__f__))
00064
00065 #define ADD_GET_METHOD(__p__, __get__) \
00066 ADD_METHOD(__p__, __get__)
00067
00068 #define ADD_GET_SET_METHODS(__p__, __get__, __set__) \
00069 do { \
00070 ADD_METHOD(__p__, __get__); \
00071 ADD_METHOD(__p__, __set__); \
00072 } while (0);
00073
00074 #define ADD_CTOR_FUNCTION(__c__, __f__) ADD_METHOD(__c__, __f__)
00075
00076 #define ADD_ENUM_VALUE(__c__, __ns__, __v__) \
00077 __c__.setProperty(#__v__, QScriptValue(__c__.engine(), __ns__::__v__))
00078
00079
00080 #define BEGIN_DECLARE_METHOD(Class, __mtd__) \
00081 static QScriptValue __mtd__(QScriptContext *ctx, QScriptEngine *eng) \
00082 { \
00083 DECLARE_SELF(Class, __mtd__);
00084
00085 #define END_DECLARE_METHOD \
00086 }
00087
00088
00089 #define DECLARE_GET_METHOD(Class, __get__) \
00090 BEGIN_DECLARE_METHOD(Class, __get__) { \
00091 return qScriptValueFromValue(eng, self->__get__()); \
00092 } END_DECLARE_METHOD
00093
00094 #define DECLARE_SET_METHOD(Class, T, __set__) \
00095 BEGIN_DECLARE_METHOD(Class, __set__) { \
00096 self->__set__(qscriptvalue_cast<T>(ctx->argument(0))); \
00097 return eng->undefinedValue(); \
00098 } END_DECLARE_METHOD
00099
00100 #define DECLARE_GET_SET_METHODS(Class, T, __get__, __set__) \
00101 DECLARE_GET_METHOD(Class, __get__) \
00102 DECLARE_SET_METHOD(Class, T, __set__)
00103
00104
00105
00106 #define DECLARE_SIMPLE_GET_METHOD(Class, __get__) \
00107 BEGIN_DECLARE_METHOD(Class, __get__) { \
00108 return QScriptValue(eng, self->__get__()); \
00109 } END_DECLARE_METHOD
00110
00111 #define DECLARE_SIMPLE_SET_METHOD(Class, ToType, __set__) \
00112 BEGIN_DECLARE_METHOD(Class, __set__) { \
00113 self->__set__(ctx->argument(0).ToType()); \
00114 return eng->undefinedValue(); \
00115 } END_DECLARE_METHOD
00116
00117 #define DECLARE_BOOLEAN_GET_METHOD(Class, __set__) \
00118 DECLARE_SIMPLE_GET_METHOD(Class, __set__)
00119 #define DECLARE_BOOLEAN_SET_METHOD(Class, __set__) \
00120 DECLARE_SIMPLE_SET_METHOD(Class, toBoolean, __set__)
00121
00122 #define DECLARE_INT_GET_METHOD(Class, __set__) \
00123 DECLARE_SIMPLE_GET_METHOD(Class, __set__)
00124 #define DECLARE_INT_SET_METHOD(Class, __set__) \
00125 DECLARE_SIMPLE_SET_METHOD(Class, toInt32, __set__)
00126
00127 #define DECLARE_NUMBER_GET_METHOD(Class, __set__) \
00128 DECLARE_SIMPLE_GET_METHOD(Class, __set__)
00129 #define DECLARE_NUMBER_SET_METHOD(Class, __set__) \
00130 DECLARE_SIMPLE_SET_METHOD(Class, toNumber, __set__)
00131
00132 #define DECLARE_STRING_GET_METHOD(Class, __set__) \
00133 DECLARE_SIMPLE_GET_METHOD(Class, __set__)
00134 #define DECLARE_STRING_SET_METHOD(Class, __set__) \
00135 DECLARE_SIMPLE_SET_METHOD(Class, toString, __set__)
00136
00137 #define DECLARE_QOBJECT_GET_METHOD(Class, __get__) \
00138 BEGIN_DECLARE_METHOD(Class, __get__) { \
00139 return eng->newQObject(self->__get__()); \
00140 } END_DECLARE_METHOD
00141 #define DECLARE_QOBJECT_SET_METHOD(Class, __set__) \
00142 DECLARE_SIMPLE_SET_METHOD(Class, toQObject, __set__)
00143
00144 #define DECLARE_BOOLEAN_GET_SET_METHODS(Class, __get__, __set__) \
00145 DECLARE_BOOLEAN_GET_METHOD(Class, __get__) \
00146 DECLARE_BOOLEAN_SET_METHOD(Class, __set__)
00147
00148 #define DECLARE_NUMBER_GET_SET_METHODS(Class, __get__, __set__) \
00149 DECLARE_NUMBER_GET_METHOD(Class, __get__) \
00150 DECLARE_NUMBER_SET_METHOD(Class, __set__)
00151
00152 #define DECLARE_INT_GET_SET_METHODS(Class, __get__, __set__) \
00153 DECLARE_INT_GET_METHOD(Class, __get__) \
00154 DECLARE_INT_SET_METHOD(Class, __set__)
00155
00156 #define DECLARE_STRING_GET_SET_METHODS(Class, __get__, __set__) \
00157 DECLARE_STRING_GET_METHOD(Class, __get__) \
00158 DECLARE_STRING_SET_METHOD(Class, __set__)
00159
00160 #define DECLARE_QOBJECT_GET_SET_METHODS(Class, __get__, __set__) \
00161 DECLARE_QOBJECT_GET_METHOD(Class, __get__) \
00162 DECLARE_QOBJECT_SET_METHOD(Class, __set__)
00163
00164
00165 #define DECLARE_VOID_METHOD(Class, __fun__) \
00166 BEGIN_DECLARE_METHOD(Class, __fun__) { \
00167 self->__fun__(); \
00168 return eng->undefinedValue(); \
00169 } END_DECLARE_METHOD
00170
00171 #define DECLARE_VOID_NUMBER_METHOD(Class, __fun__) \
00172 BEGIN_DECLARE_METHOD(Class, __fun__) { \
00173 self->__fun__(ctx->argument(0).toNumber()); \
00174 return eng->undefinedValue(); \
00175 } END_DECLARE_METHOD
00176
00177 #define DECLARE_VOID_NUMBER_NUMBER_METHOD(Class, __fun__) \
00178 BEGIN_DECLARE_METHOD(Class, __fun__) { \
00179 self->__fun__(ctx->argument(0).toNumber(), ctx->argument(1).toNumber()); \
00180 return eng->undefinedValue(); \
00181 } END_DECLARE_METHOD
00182
00183 #define DECLARE_VOID_QUAD_NUMBER_METHOD(Class, __fun__) \
00184 BEGIN_DECLARE_METHOD(Class, __fun__) { \
00185 self->__fun__(ctx->argument(0).toNumber(), ctx->argument(1).toNumber(), ctx->argument(2).toNumber(), ctx->argument(3).toNumber()); \
00186 return eng->undefinedValue(); \
00187 } END_DECLARE_METHOD
00188
00189 #define DECLARE_VOID_1ARG_METHOD(Class, ArgType, __fun__) \
00190 BEGIN_DECLARE_METHOD(Class, __fun__) { \
00191 self->__fun__(qscriptvalue_cast<ArgType>(ctx->argument(0))); \
00192 return eng->undefinedValue(); \
00193 } END_DECLARE_METHOD
00194
00195 #define DECLARE_BOOLEAN_1ARG_METHOD(Class, ArgType, __fun__) \
00196 BEGIN_DECLARE_METHOD(Class, __fun__) { \
00197 return QScriptValue(eng, self->__fun__(qscriptvalue_cast<ArgType>(ctx->argument(0)))); \
00198 } END_DECLARE_METHOD
00199
00200
00201 #define DECLARE_POINTER_METATYPE(T) \
00202 Q_DECLARE_METATYPE(T*) \
00203 Q_DECLARE_METATYPE(QScript::Pointer<T>::wrapped_pointer_type)
00204
00205 namespace QScript
00206 {
00207
00208 enum {
00209 UserOwnership = 1
00210 };
00211
00212 template <typename T>
00213 class Pointer : public QSharedData
00214 {
00215 public:
00216 typedef T* pointer_type;
00217 typedef QExplicitlySharedDataPointer<Pointer<T> > wrapped_pointer_type;
00218
00219 ~Pointer()
00220 {
00221 if (!(m_flags & UserOwnership))
00222 delete m_value;
00223 }
00224
00225 operator T*()
00226 {
00227 return m_value;
00228 }
00229
00230 operator const T*() const
00231 {
00232 return m_value;
00233 }
00234
00235 static wrapped_pointer_type create(T *value, uint flags = 0)
00236 {
00237 return wrapped_pointer_type(new Pointer(value, flags));
00238 }
00239
00240 static QScriptValue toScriptValue(QScriptEngine *engine, T* const &source)
00241 {
00242 if (!source)
00243 return engine->nullValue();
00244 return engine->newVariant(qVariantFromValue(source));
00245 }
00246
00247 static void fromScriptValue(const QScriptValue &value, T* &target)
00248 {
00249 if (value.isVariant()) {
00250 QVariant var = value.toVariant();
00251 if (qVariantCanConvert<T*>(var)) {
00252 target = qvariant_cast<T*>(var);
00253 } else if (qVariantCanConvert<wrapped_pointer_type>(var)) {
00254 target = qvariant_cast<wrapped_pointer_type>(var)->operator T*();
00255 } else {
00256
00257 target = 0;
00258 int type = qMetaTypeId<T*>();
00259 int pointerType = qMetaTypeId<wrapped_pointer_type>();
00260 QScriptValue proto = value.prototype();
00261 while (proto.isObject() && proto.isVariant()) {
00262 int protoType = proto.toVariant().userType();
00263 if ((type == protoType) || (pointerType == protoType)) {
00264 QByteArray name = QMetaType::typeName(var.userType());
00265 if (name.startsWith("QScript::Pointer<")) {
00266 target = (*reinterpret_cast<wrapped_pointer_type*>(var.data()))->operator T*();
00267 break;
00268 } else {
00269 target = static_cast<T*>(var.data());
00270 break;
00271 }
00272 }
00273 proto = proto.prototype();
00274 }
00275 }
00276 } else if (value.isQObject()) {
00277 QObject *qobj = value.toQObject();
00278 QByteArray typeName = QMetaType::typeName(qMetaTypeId<T*>());
00279 target = reinterpret_cast<T*>(qobj->qt_metacast(typeName.left(typeName.size()-1)));
00280 } else {
00281 target = 0;
00282 }
00283 }
00284
00285 uint flags() const
00286 { return m_flags; }
00287 void setFlags(uint flags)
00288 { m_flags = flags; }
00289 void unsetFlags(uint flags)
00290 { m_flags &= ~flags; }
00291
00292 protected:
00293 Pointer(T* value, uint flags)
00294 : m_flags(flags), m_value(value)
00295 {}
00296
00297 private:
00298 uint m_flags;
00299 T* m_value;
00300 };
00301
00302 template <typename T>
00303 int registerPointerMetaType(
00304 QScriptEngine *eng,
00305 const QScriptValue &prototype = QScriptValue(),
00306 T * = 0
00307 )
00308 {
00309 QScriptValue (*mf)(QScriptEngine *, T* const &) = Pointer<T>::toScriptValue;
00310 void (*df)(const QScriptValue &, T* &) = Pointer<T>::fromScriptValue;
00311 const int id = qMetaTypeId<T*>();
00312 qScriptRegisterMetaType_helper(
00313 eng, id, reinterpret_cast<QScriptEngine::MarshalFunction>(mf),
00314 reinterpret_cast<QScriptEngine::DemarshalFunction>(df),
00315 prototype);
00316 eng->setDefaultPrototype(qMetaTypeId<typename Pointer<T>::wrapped_pointer_type>(), prototype);
00317 return id;
00318 }
00319
00320 inline void maybeReleaseOwnership(const QScriptValue &value)
00321 {
00322 if (value.isVariant()) {
00323 QVariant var = value.toVariant();
00324 QByteArray name = QMetaType::typeName(var.userType());
00325 if (name.startsWith("QScript::Pointer<"))
00326 (*reinterpret_cast<Pointer<void*>::wrapped_pointer_type *>(var.data()))->setFlags(UserOwnership);
00327 }
00328 }
00329
00330 inline void maybeTakeOwnership(const QScriptValue &value)
00331 {
00332 if (value.isVariant()) {
00333 QVariant var = value.toVariant();
00334 QByteArray name = QMetaType::typeName(var.userType());
00335 if (name.startsWith("QScript::Pointer<"))
00336 (*reinterpret_cast<Pointer<void*>::wrapped_pointer_type *>(var.data()))->unsetFlags(UserOwnership);
00337 }
00338 }
00339
00340 template <class T>
00341 inline QScriptValue wrapPointer(QScriptEngine *eng, T *ptr, uint flags = 0)
00342 {
00343 return eng->newVariant(qVariantFromValue(Pointer<T>::create(ptr, flags)));
00344 }
00345
00346 }
00347
00348 #ifdef QGRAPHICSITEM_H
00349
00350 namespace QScript {
00351
00352 template <class T>
00353 inline QScriptValue wrapGVPointer(QScriptEngine *eng, T *item)
00354 {
00355 uint flags = item->parentItem() ? UserOwnership : 0;
00356 return wrapPointer<T>(eng, item, flags);
00357 }
00358
00359 }
00360
00361 #endif // QGRAPHICSITEM_H
00362
00363 #endif // QTSCRIPTEXTENSIONS_GLOBAL_H