##// END OF EJS Templates
fixed enum handling for static methods calls and added correct support for decorated enum detection...
florianlink -
r41:189c3eb0464d
parent child
Show More
@@ -276,33 +276,6 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const
276 info->setPythonQtClassWrapper(pyobj);
276 info->setPythonQtClassWrapper(pyobj);
277 }
277 }
278
278
279 bool PythonQtPrivate::isEnumType(const QMetaObject* meta, const QByteArray& name) {
280 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
281 if (i!=-1) {
282 return true;
283 } else {
284 // look for scope
285 int scopePos = name.indexOf("::");
286 if (scopePos != -1) {
287 // slit into scope and enum name
288 QByteArray enumScope = name.mid(0,scopePos);
289 QByteArray enumName = name.mid(scopePos+2);
290 if (enumScope == "Qt") {
291 // special qt namespace case
292 return isEnumType(&staticQtMetaObject, enumName);
293 } else {
294 // look for known classes as scope
295 // TODO: Q_GADGETS are not yet handled
296 PythonQtClassInfo* info = _knownClassInfos.value(enumScope);
297 if (info) {
298 return isEnumType(info->metaObject(), enumName);
299 }
300 }
301 }
302 }
303 return false;
304 }
305
306 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
279 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
307 {
280 {
308 if (!obj) {
281 if (!obj) {
@@ -443,10 +443,6 public:
443 //! add a decorator object
443 //! add a decorator object
444 void addDecorators(QObject* o, int decoTypes);
444 void addDecorators(QObject* o, int decoTypes);
445
445
446 //! check if the enum is either part of the \c meta class or contains a scope and is
447 //! an enum of another known metaobject (and as last resort, of the Qt namespace)
448 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
449
450 //! helper method that creates a PythonQtClassWrapper object
446 //! helper method that creates a PythonQtClassWrapper object
451 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package = NULL);
447 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package = NULL);
452
448
@@ -725,3 +725,46 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resul
725 }
725 }
726 return resultPtr;
726 return resultPtr;
727 }
727 }
728
729 bool PythonQtClassInfo::hasEnum(const QByteArray& name, PythonQtClassInfo* localScope)
730 {
731 int scopePos = name.lastIndexOf("::");
732 if (scopePos != -1) {
733 // slit into scope and enum name
734 QByteArray enumScope = name.mid(0,scopePos);
735 QByteArray enumName = name.mid(scopePos+2);
736 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
737 if (info) {
738 return info->hasEnum(enumName);
739 } else{
740 return false;
741 }
742 }
743 if (localScope) {
744 return localScope->hasEnum(name);
745 } else {
746 return false;
747 }
748 }
749
750 bool PythonQtClassInfo::hasEnum(const QByteArray& name)
751 {
752 bool found = false;
753 if (_meta) {
754 found = _meta->indexOfEnumerator(name)!=-1;
755 }
756 if (!found) {
757 // check enums in the class hierachy of CPP classes
758 // look for dynamic decorators in this class and in derived classes
759 QList<QObject*> decoObjects;
760 recursiveCollectDecoratorObjects(decoObjects);
761 foreach(QObject* deco, decoObjects) {
762 found = deco->metaObject()->indexOfEnumerator(name)!=-1;
763 if (found) {
764 break;
765 }
766 }
767 }
768 return found;
769 }
770
@@ -191,7 +191,13 public:
191 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
191 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
192 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
192 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
193
193
194 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
195 static bool hasEnum(const QByteArray& name, PythonQtClassInfo* localScope);
196
194 private:
197 private:
198 //! checks if the enum is part of this class (without any leading scope!)
199 bool hasEnum(const QByteArray& name);
200
195 //! clear all cached members
201 //! clear all cached members
196 void clearCachedMembers();
202 void clearCachedMembers();
197
203
@@ -240,7 +240,7 return Py_None;
240 return object;
240 return object;
241 }
241 }
242
242
243 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, const QMetaObject* meta, void* alreadyAllocatedCPPObject)
243 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* meta, void* alreadyAllocatedCPPObject)
244 {
244 {
245 bool ok;
245 bool ok;
246 void* ptr = NULL;
246 void* ptr = NULL;
@@ -444,7 +444,7 return Py_None;
444 {
444 {
445 if (info.typeId == PythonQtMethodInfo::Unknown) {
445 if (info.typeId == PythonQtMethodInfo::Unknown) {
446 // check for enum case
446 // check for enum case
447 if (meta && PythonQt::priv()->isEnumType(meta, info.name)) {
447 if (PythonQtClassInfo::hasEnum(info.name, meta)) {
448 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
448 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
449 if (ok) {
449 if (ok) {
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
@@ -78,7 +78,7 public:
78 static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data);
78 static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data);
79
79
80 //! convert python object to Qt (according to the given parameter) and if the conversion should be strict, the meta object is passed in for enum resolving
80 //! convert python object to Qt (according to the given parameter) and if the conversion should be strict, the meta object is passed in for enum resolving
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, const QMetaObject* meta, void* alreadyAllocatedCPPObject = NULL);
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* meta, void* alreadyAllocatedCPPObject = NULL);
82
82
83 //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall
83 //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall
84 static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info);
84 static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info);
@@ -145,7 +145,7 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args
145 // we are called from python, try to construct our object
145 // we are called from python, try to construct our object
146 if (self->classInfo()->constructors()) {
146 if (self->classInfo()->constructors()) {
147 void* directCPPPointer = NULL;
147 void* directCPPPointer = NULL;
148 PythonQtSlotFunction_CallImpl(NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 if (PyErr_Occurred()) {
149 if (PyErr_Occurred()) {
150 return -1;
150 return -1;
151 }
151 }
@@ -50,7 +50,7
50 #define PYTHONQT_MAX_ARGS 32
50 #define PYTHONQT_MAX_ARGS 32
51
51
52
52
53 bool PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
53 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
54 {
54 {
55 static unsigned int recursiveEntry = 0;
55 static unsigned int recursiveEntry = 0;
56
56
@@ -82,7 +82,7 bool PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, Python
82 if (returnValueParam.typeId != QMetaType::Void) {
82 if (returnValueParam.typeId != QMetaType::Void) {
83 // extra handling of enum return value
83 // extra handling of enum return value
84 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
84 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
85 returnValueIsEnum = PythonQt::priv()->isEnumType(objectToCall->metaObject(), returnValueParam.name);
85 returnValueIsEnum = PythonQtClassInfo::hasEnum(returnValueParam.name, classInfo);
86 if (returnValueIsEnum) {
86 if (returnValueIsEnum) {
87 // create enum return value
87 // create enum return value
88 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
88 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
@@ -100,7 +100,6 bool PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, Python
100 }
100 }
101 }
101 }
102
102
103 const QMetaObject* meta = objectToCall?objectToCall->metaObject():NULL;
104 bool ok = true;
103 bool ok = true;
105 bool skipFirst = false;
104 bool skipFirst = false;
106 if (info->isInstanceDecorator()) {
105 if (info->isInstanceDecorator()) {
@@ -121,7 +120,7 bool PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, Python
121 for (int i = 2; i<argc && ok; i++) {
120 for (int i = 2; i<argc && ok; i++) {
122 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
121 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
123 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
122 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
124 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, meta);
123 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
125 if (argList[i]==NULL) {
124 if (argList[i]==NULL) {
126 ok = false;
125 ok = false;
127 break;
126 break;
@@ -132,7 +131,7 bool PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, Python
132 for (int i = 1; i<argc && ok; i++) {
131 for (int i = 1; i<argc && ok; i++) {
133 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
132 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
134 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
133 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
135 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, meta);
134 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
136 if (argList[i]==NULL) {
135 if (argList[i]==NULL) {
137 ok = false;
136 ok = false;
138 break;
137 break;
@@ -181,13 +180,13 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw
181 PythonQtSlotInfo* info = f->m_ml;
180 PythonQtSlotInfo* info = f->m_ml;
182 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
181 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
183 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
182 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
184 return PythonQtSlotFunction_CallImpl(self->_obj, info, args, kw, self->_wrappedPtr);
183 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
185 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
184 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
185 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
186 if (info->isClassDecorator()) {
186 if (info->isClassDecorator()) {
187 return PythonQtSlotFunction_CallImpl(NULL, info, args, kw);
187 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
188 } else {
188 } else {
189 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
189 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
190 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
191 Py_ssize_t argc = PyTuple_Size(args);
190 Py_ssize_t argc = PyTuple_Size(args);
192 if (argc>0) {
191 if (argc>0) {
193 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
192 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
@@ -196,7 +195,7 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw
196 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
195 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
197 // strip the first argument...
196 // strip the first argument...
198 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
197 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
199 PyObject* result = PythonQtSlotFunction_CallImpl(self->_obj, info, newargs, kw, self->_wrappedPtr);
198 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
200 Py_DECREF(newargs);
199 Py_DECREF(newargs);
201 return result;
200 return result;
202 } else {
201 } else {
@@ -216,7 +215,7 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw
216 return NULL;
215 return NULL;
217 }
216 }
218
217
219 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
218 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
220 {
219 {
221 int argc = PyTuple_Size(args);
220 int argc = PyTuple_Size(args);
222
221
@@ -237,7 +236,7 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo*
237 bool skipFirst = i->isInstanceDecorator();
236 bool skipFirst = i->isInstanceDecorator();
238 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
237 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
239 PyErr_Clear();
238 PyErr_Clear();
240 ok = PythonQtCallSlot(objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
239 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
241 if (PyErr_Occurred() || ok) break;
240 if (PyErr_Occurred() || ok) break;
242 }
241 }
243 i = i->nextInfo();
242 i = i->nextInfo();
@@ -263,7 +262,7 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo*
263 bool skipFirst = info->isInstanceDecorator();
262 bool skipFirst = info->isInstanceDecorator();
264 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
263 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
265 PyErr_Clear();
264 PyErr_Clear();
266 ok = PythonQtCallSlot(objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
265 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
267 if (!ok && !PyErr_Occurred()) {
266 if (!ok && !PyErr_Occurred()) {
268 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
267 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
269 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
268 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
@@ -62,7 +62,7 PyObject* PythonQtSlotFunction_GetSelf(PyObject *);
62
62
63 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
63 PyObject* PythonQtSlotFunction_Call(PyObject *, PyObject *, PyObject *);
64
64
65 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL, void** directReturnValuePointer=NULL);
65 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, void* firstArg=NULL, void** directReturnValuePointer=NULL);
66
66
67
67
68 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
68 PyObject* PythonQtSlotFunction_New(PythonQtSlotInfo *, PyObject *,
General Comments 0
You need to be logged in to leave comments. Login now