@@ -915,9 +915,9 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes) | |||
|
915 | 915 | QMetaMethod m = o->metaObject()->method(i); |
|
916 | 916 | if ((m.methodType() == QMetaMethod::Method || |
|
917 | 917 | m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) { |
|
918 | const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL); | |
|
919 | 918 | if (qstrncmp(m.signature(), "new_", 4)==0) { |
|
920 | 919 | if ((decoTypes & ConstructorDecorator) == 0) continue; |
|
920 | const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL); | |
|
921 | 921 | if (info->parameters().at(0).isPointer) { |
|
922 | 922 | QByteArray signature = m.signature(); |
|
923 | 923 | QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4); |
@@ -942,6 +942,7 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes) | |||
|
942 | 942 | classInfo->addDecoratorSlot(newSlot); |
|
943 | 943 | } else { |
|
944 | 944 | if ((decoTypes & InstanceDecorator) == 0) continue; |
|
945 | const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL); | |
|
945 | 946 | if (info->parameters().count()>1) { |
|
946 | 947 | PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1); |
|
947 | 948 | if (p.isPointer) { |
@@ -251,6 +251,9 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* | |||
|
251 | 251 | int enumCount = meta->enumeratorCount(); |
|
252 | 252 | for (int i=0;i<enumCount; i++) { |
|
253 | 253 | QMetaEnum e = meta->enumerator(i); |
|
254 | // we do not want flags, they will cause our values to appear two times | |
|
255 | if (e.isFlag()) continue; | |
|
256 | ||
|
254 | 257 |
|
|
255 | 258 | if (qstrcmp(e.key(j), memberName)==0) { |
|
256 | 259 | PyObject* enumType = findEnumWrapper(e.name()); |
@@ -490,6 +493,9 QStringList PythonQtClassInfo::memberList(bool metaOnly) | |||
|
490 | 493 | for (int i = 0; i<meta->enumeratorCount(); i++) { |
|
491 | 494 | QMetaEnum e = meta->enumerator(i); |
|
492 | 495 | l << e.name(); |
|
496 | // we do not want flags, they will cause our values to appear two times | |
|
497 | if (e.isFlag()) continue; | |
|
498 | ||
|
493 | 499 | for (int j=0; j < e.keyCount(); j++) { |
|
494 | 500 | l << QString(e.key(j)); |
|
495 | 501 | } |
@@ -750,46 +756,27 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resul | |||
|
750 | 756 | return resultPtr; |
|
751 | 757 | } |
|
752 | 758 | |
|
753 |
|
|
|
759 | PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool& isLocalEnum) | |
|
754 | 760 | { |
|
761 | isLocalEnum = true; | |
|
755 | 762 | int scopePos = name.lastIndexOf("::"); |
|
756 | 763 | if (scopePos != -1) { |
|
764 | isLocalEnum = false; | |
|
757 | 765 | // slit into scope and enum name |
|
758 | 766 | QByteArray enumScope = name.mid(0,scopePos); |
|
759 | 767 | QByteArray enumName = name.mid(scopePos+2); |
|
760 | 768 | PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope); |
|
761 | 769 | if (info) { |
|
762 |
return info-> |
|
|
770 | return info->findEnumWrapper(enumName); | |
|
763 | 771 | } else{ |
|
764 |
return |
|
|
772 | return NULL; | |
|
765 | 773 | } |
|
766 | 774 | } |
|
767 | 775 | if (localScope) { |
|
768 |
return localScope-> |
|
|
776 | return localScope->findEnumWrapper(name); | |
|
769 | 777 | } else { |
|
770 |
return |
|
|
771 | } | |
|
772 | } | |
|
773 | ||
|
774 | bool PythonQtClassInfo::hasEnum(const QByteArray& name) | |
|
775 | { | |
|
776 | bool found = false; | |
|
777 | if (_meta) { | |
|
778 | found = _meta->indexOfEnumerator(name)!=-1; | |
|
779 | } | |
|
780 | if (!found) { | |
|
781 | // check enums in the class hierachy of CPP classes | |
|
782 | // look for dynamic decorators in this class and in derived classes | |
|
783 | QList<QObject*> decoObjects; | |
|
784 | recursiveCollectDecoratorObjects(decoObjects); | |
|
785 | foreach(QObject* deco, decoObjects) { | |
|
786 | found = deco->metaObject()->indexOfEnumerator(name)!=-1; | |
|
787 | if (found) { | |
|
788 | break; | |
|
789 | } | |
|
790 | } | |
|
778 | return NULL; | |
|
791 | 779 | } |
|
792 | return found; | |
|
793 | 780 | } |
|
794 | 781 | |
|
795 | 782 | void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta) |
@@ -195,16 +195,13 public: | |||
|
195 | 195 | void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo); |
|
196 | 196 | |
|
197 | 197 | //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum |
|
198 |
static |
|
|
198 | static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool& isLocalEnum); | |
|
199 | 199 | |
|
200 | 200 | private: |
|
201 | 201 | void createEnumWrappers(); |
|
202 | 202 | void createEnumWrappers(const QMetaObject* meta); |
|
203 | 203 | PyObject* findEnumWrapper(const char* name); |
|
204 | 204 | |
|
205 | //! checks if the enum is part of this class (without any leading scope!) | |
|
206 | bool hasEnum(const QByteArray& name); | |
|
207 | ||
|
208 | 205 | //! clear all cached members |
|
209 | 206 | void clearCachedMembers(); |
|
210 | 207 |
@@ -240,7 +240,7 return Py_None; | |||
|
240 | 240 | return object; |
|
241 | 241 | } |
|
242 | 242 | |
|
243 |
void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* |
|
|
243 | void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject) | |
|
244 | 244 | { |
|
245 | 245 | bool ok; |
|
246 | 246 | void* ptr = NULL; |
@@ -442,18 +442,25 return Py_None; | |||
|
442 | 442 | break; |
|
443 | 443 | default: |
|
444 | 444 | { |
|
445 | if (info.typeId == PythonQtMethodInfo::Unknown) { | |
|
446 | // check for enum case | |
|
447 | if (PythonQtClassInfo::hasEnum(info.name, meta)) { | |
|
448 | unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok); | |
|
449 | if (ok) { | |
|
450 | PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr); | |
|
451 |
|
|
|
452 |
|
|
|
453 | return NULL; | |
|
454 | } | |
|
445 | // check for enum case | |
|
446 | if (info.enumWrapper) { | |
|
447 | unsigned int val; | |
|
448 | if ((PyObject*)obj->ob_type == info.enumWrapper) { | |
|
449 | // we have a direct enum type match: | |
|
450 | val = PyInt_AS_LONG(obj); | |
|
451 | ok = true; | |
|
452 | } else { | |
|
453 | // we try to get an integer, and in strict mode, it may not be a derived int class, so that no other enum can be taken as an int | |
|
454 | val = (unsigned int)PyObjGetLongLong(obj, strict, ok); | |
|
455 | } | |
|
456 | if (ok) { | |
|
457 | PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr); | |
|
458 | return ptr; | |
|
459 | } else { | |
|
460 | return NULL; | |
|
455 | 461 | } |
|
456 | 462 | } |
|
463 | ||
|
457 | 464 | if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) { |
|
458 | 465 | // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant |
|
459 | 466 | if (info.name.startsWith("QList<")) { |
@@ -77,8 +77,8 public: | |||
|
77 | 77 | //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object, |
|
78 | 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 |
|
|
81 |
static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* |
|
|
80 | //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore) | |
|
81 | static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL); | |
|
82 | 82 | |
|
83 | 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 | 84 | static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info); |
@@ -114,7 +114,7 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self) | |||
|
114 | 114 | self->ob_type->tp_free((PyObject*)self); |
|
115 | 115 | } |
|
116 | 116 | |
|
117 | static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * args, PyObject * /*kwds*/) | |
|
117 | static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/) | |
|
118 | 118 | { |
|
119 | 119 | //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type; |
|
120 | 120 | PythonQtInstanceWrapper *self; |
@@ -415,7 +415,7 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj) | |||
|
415 | 415 | return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr); |
|
416 | 416 | } |
|
417 | 417 | } else { |
|
418 |
return PyString_FromFormat("%s ( |
|
|
418 | return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj); | |
|
419 | 419 | } |
|
420 | 420 | } |
|
421 | 421 |
@@ -56,12 +56,12 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInf | |||
|
56 | 56 | #endif |
|
57 | 57 | |
|
58 | 58 | ParameterInfo type; |
|
59 | fillParameterInfo(type, QByteArray(meta.typeName())); | |
|
59 | fillParameterInfo(type, QByteArray(meta.typeName()), classInfo); | |
|
60 | 60 | _parameters.append(type); |
|
61 | 61 | QByteArray name; |
|
62 | 62 | QList<QByteArray> names = meta.parameterTypes(); |
|
63 | 63 | foreach (name, names) { |
|
64 | fillParameterInfo(type, name); | |
|
64 | fillParameterInfo(type, name, classInfo); | |
|
65 | 65 | _parameters.append(type); |
|
66 | 66 | } |
|
67 | 67 | } |
@@ -87,10 +87,12 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromMetaObjectA | |||
|
87 | 87 | return PythonQtMethodInfo::getCachedMethodInfo(meta, NULL); |
|
88 | 88 | } |
|
89 | 89 | |
|
90 | void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName) | |
|
90 | void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo) | |
|
91 | 91 | { |
|
92 | 92 | QByteArray name = orgName; |
|
93 | 93 | |
|
94 | type.enumWrapper = NULL; | |
|
95 | ||
|
94 | 96 |
|
|
95 | 97 | if (len>0) { |
|
96 | 98 | if (strncmp(name.constData(), "const ", 6)==0) { |
@@ -129,6 +131,12 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray | |||
|
129 | 131 | } |
|
130 | 132 | } |
|
131 | 133 | type.name = name; |
|
134 | ||
|
135 | if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) { | |
|
136 | bool isLocalEnum; | |
|
137 | // TODOXXX: make use of this flag! | |
|
138 | type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, isLocalEnum); | |
|
139 | } | |
|
132 | 140 | } else { |
|
133 | 141 | type.typeId = QMetaType::Void; |
|
134 | 142 | type.isPointer = false; |
@@ -50,6 +50,8 | |||
|
50 | 50 | #include <QMetaMethod> |
|
51 | 51 | |
|
52 | 52 | class PythonQtClassInfo; |
|
53 | struct _object; | |
|
54 | typedef struct _object PyObject; | |
|
53 | 55 | |
|
54 | 56 | //! stores information about a specific signal/slot/method |
|
55 | 57 | class PYTHONQT_EXPORT PythonQtMethodInfo |
@@ -62,8 +64,9 public: | |||
|
62 | 64 | |
|
63 | 65 | //! stores the QVariant id (if available) and the name of the type |
|
64 | 66 | struct ParameterInfo { |
|
65 | int typeId; // a mixture from QMetaType and ParameterType | |
|
66 | 67 | QByteArray name; |
|
68 | PyObject* enumWrapper; // if it is an enum, a pointer to the enum wrapper | |
|
69 | int typeId; // a mixture from QMetaType and ParameterType | |
|
67 | 70 | bool isPointer; |
|
68 | 71 | bool isConst; |
|
69 | 72 | }; |
@@ -98,7 +101,7 public: | |||
|
98 | 101 | static void addParameterTypeAlias(const QByteArray& alias, const QByteArray& name); |
|
99 | 102 | |
|
100 | 103 | protected: |
|
101 | static void fillParameterInfo(ParameterInfo& type, const QByteArray& name); | |
|
104 | static void fillParameterInfo(ParameterInfo& type, const QByteArray& name, PythonQtClassInfo* classInfo); | |
|
102 | 105 | |
|
103 | 106 | static QHash<QByteArray, int> _parameterTypeDict; |
|
104 | 107 | static QHash<QByteArray, QByteArray> _parameterNameAliases; |
@@ -74,7 +74,6 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObj | |||
|
74 | 74 | int argc = info->parameterCount(); |
|
75 | 75 | const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters(); |
|
76 | 76 | |
|
77 | bool returnValueIsEnum = false; | |
|
78 | 77 |
|
|
79 | 78 | // set return argument to NULL |
|
80 | 79 | argList[0] = NULL; |
@@ -119,17 +118,16 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObj | |||
|
119 | 118 | } |
|
120 | 119 | |
|
121 | 120 | if (ok) { |
|
121 | bool returnValueIsEnum = false; | |
|
122 | ||
|
122 | 123 | // parameters are ok, now create the qt return value which is assigned to by metacall |
|
123 | 124 | if (returnValueParam.typeId != QMetaType::Void) { |
|
124 | 125 | // extra handling of enum return value |
|
125 |
if (!returnValueParam.isPointer && returnValueParam. |
|
|
126 | returnValueIsEnum = PythonQtClassInfo::hasEnum(returnValueParam.name, classInfo); | |
|
127 | if (returnValueIsEnum) { | |
|
128 | // create enum return value | |
|
129 | PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]); | |
|
130 | } | |
|
131 | } | |
|
132 | if (argList[0]==NULL) { | |
|
126 | if (!returnValueParam.isPointer && returnValueParam.enumWrapper) { | |
|
127 | // create enum return value | |
|
128 | PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]); | |
|
129 | returnValueIsEnum = true; | |
|
130 | } else { | |
|
133 | 131 | // create empty default value for the return value |
|
134 | 132 | if (!directReturnValuePointer) { |
|
135 | 133 | // create empty default value for the return value |
General Comments 0
You need to be logged in to leave comments.
Login now