diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index 9b355c8..841efcf 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -431,6 +431,14 @@ PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtCla return result; } +PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue) +{ + PyObject* args = Py_BuildValue("(i)", enumValue); + PyObject* result = PyObject_Call(enumType, args, NULL); + Py_DECREF(args); + return result; +} + PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) { PyObject* result; diff --git a/src/PythonQt.h b/src/PythonQt.h index 5413578..eca607b 100644 --- a/src/PythonQt.h +++ b/src/PythonQt.h @@ -443,11 +443,14 @@ public: //! add a decorator object void addDecorators(QObject* o, int decoTypes); - //! helper method that creates a PythonQtClassWrapper object + //! helper method that creates a PythonQtClassWrapper object (returns a new reference) PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package = NULL); - //! helper that creates a new int derived class that represents the enum of the given name - PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject); + //! create a new instance of the given enum type with given value (returns a new reference) + static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue); + + //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference) + static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject); //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL); diff --git a/src/PythonQtClassInfo.cpp b/src/PythonQtClassInfo.cpp index 681f57b..98c3756 100644 --- a/src/PythonQtClassInfo.cpp +++ b/src/PythonQtClassInfo.cpp @@ -258,11 +258,8 @@ bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* if (qstrcmp(e.key(j), memberName)==0) { PyObject* enumType = findEnumWrapper(e.name()); if (enumType) { - PyObject* args = Py_BuildValue("(i)", e.value(j)); - PyObject* enumValue = PyObject_Call(enumType, args, NULL); - Py_DECREF(args); PythonQtObjectPtr enumValuePtr; - enumValuePtr.setNewRef(enumValue); + enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j))); PythonQtMemberInfo newInfo(enumValuePtr); _cachedMembers.insert(memberName, newInfo); #ifdef PYTHONQT_DEBUG @@ -784,7 +781,7 @@ void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta) for (int i = meta->enumeratorOffset();ienumeratorCount();i++) { QMetaEnum e = meta->enumerator(i); PythonQtObjectPtr p; - p.setNewRef(PythonQt::priv()->createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper)); + p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper)); _enumWrappers.append(p); } } @@ -806,6 +803,10 @@ void PythonQtClassInfo::createEnumWrappers() } PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) { + // force enum creation + if (!_enumsCreated) { + createEnumWrappers(); + } foreach(const PythonQtObjectPtr& p, _enumWrappers) { const char* className = ((PyTypeObject*)p.object())->tp_name; if (qstrcmp(className, name)==0) { diff --git a/src/PythonQtConversion.cpp b/src/PythonQtConversion.cpp index fcc1d0b..5ed7e40 100644 --- a/src/PythonQtConversion.cpp +++ b/src/PythonQtConversion.cpp @@ -60,6 +60,17 @@ PyObject* PythonQtConv::GetPyBool(bool val) } PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) { + // is it an enum value? + if (info.enumWrapper) { + if (!info.isPointer) { + return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data)); + } else { + // we do not support pointers to enums (who needs them?) + Py_INCREF(Py_None); + return Py_None; + } + } + if (info.typeId == QMetaType::Void) { Py_INCREF(Py_None); return Py_None; @@ -175,6 +186,9 @@ return Py_None; void* ptr = NULL; if (info.isPointer) { PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr); + } else if (info.enumWrapper) { + // create enum return value + PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr); } else { switch (info.typeId) { case QMetaType::Char: diff --git a/src/PythonQtSlot.cpp b/src/PythonQtSlot.cpp index 0e8d1c9..6d63f47 100644 --- a/src/PythonQtSlot.cpp +++ b/src/PythonQtSlot.cpp @@ -118,38 +118,29 @@ bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObj } if (ok) { - bool returnValueIsEnum = false; - // parameters are ok, now create the qt return value which is assigned to by metacall if (returnValueParam.typeId != QMetaType::Void) { - // extra handling of enum return value - if (!returnValueParam.isPointer && returnValueParam.enumWrapper) { - // create enum return value - PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]); - returnValueIsEnum = true; - } else { + // create empty default value for the return value + if (!directReturnValuePointer) { // create empty default value for the return value - if (!directReturnValuePointer) { - // create empty default value for the return value - argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam); - if (argList[0]==NULL) { - // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and - // pass its internal pointer - PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name); - if (info && info->pythonQtClassWrapper()) { - PyObject* emptyTuple = PyTuple_New(0); - // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments - result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL); - if (result) { - argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr; - } - Py_DECREF(emptyTuple); - } - } - } else { - // we can use our pointer directly! - argList[0] = directReturnValuePointer; + argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam); + if (argList[0]==NULL) { + // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and + // pass its internal pointer + PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name); + if (info && info->pythonQtClassWrapper()) { + PyObject* emptyTuple = PyTuple_New(0); + // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments + result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL); + if (result) { + argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr; + } + Py_DECREF(emptyTuple); + } } + } else { + // we can use our pointer directly! + argList[0] = directReturnValuePointer; } } @@ -161,13 +152,9 @@ bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObj if (directReturnValuePointer) { result = NULL; } else { - if (!returnValueIsEnum) { - // the resulting object maybe present already, because we created it above at 1)... - if (!result) { - result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]); - } - } else { - result = PyInt_FromLong(*((unsigned int*)argList[0])); + // the resulting object maybe present already, because we created it above at 1)... + if (!result) { + result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]); } } } else {