##// END OF EJS Templates
cache enumWrappers in method infos and make use of the extra information for better enum overloading...
florianlink -
r55:83868d7a7982
parent child
Show More
@@ -915,9 +915,9 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
915 QMetaMethod m = o->metaObject()->method(i);
915 QMetaMethod m = o->metaObject()->method(i);
916 if ((m.methodType() == QMetaMethod::Method ||
916 if ((m.methodType() == QMetaMethod::Method ||
917 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
917 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
918 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
919 if (qstrncmp(m.signature(), "new_", 4)==0) {
918 if (qstrncmp(m.signature(), "new_", 4)==0) {
920 if ((decoTypes & ConstructorDecorator) == 0) continue;
919 if ((decoTypes & ConstructorDecorator) == 0) continue;
920 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
921 if (info->parameters().at(0).isPointer) {
921 if (info->parameters().at(0).isPointer) {
922 QByteArray signature = m.signature();
922 QByteArray signature = m.signature();
923 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
923 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
@@ -942,6 +942,7 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
942 classInfo->addDecoratorSlot(newSlot);
942 classInfo->addDecoratorSlot(newSlot);
943 } else {
943 } else {
944 if ((decoTypes & InstanceDecorator) == 0) continue;
944 if ((decoTypes & InstanceDecorator) == 0) continue;
945 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
945 if (info->parameters().count()>1) {
946 if (info->parameters().count()>1) {
946 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
947 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
947 if (p.isPointer) {
948 if (p.isPointer) {
@@ -251,6 +251,9 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char*
251 int enumCount = meta->enumeratorCount();
251 int enumCount = meta->enumeratorCount();
252 for (int i=0;i<enumCount; i++) {
252 for (int i=0;i<enumCount; i++) {
253 QMetaEnum e = meta->enumerator(i);
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 for (int j=0; j < e.keyCount(); j++) {
257 for (int j=0; j < e.keyCount(); j++) {
255 if (qstrcmp(e.key(j), memberName)==0) {
258 if (qstrcmp(e.key(j), memberName)==0) {
256 PyObject* enumType = findEnumWrapper(e.name());
259 PyObject* enumType = findEnumWrapper(e.name());
@@ -490,6 +493,9 QStringList PythonQtClassInfo::memberList(bool metaOnly)
490 for (int i = 0; i<meta->enumeratorCount(); i++) {
493 for (int i = 0; i<meta->enumeratorCount(); i++) {
491 QMetaEnum e = meta->enumerator(i);
494 QMetaEnum e = meta->enumerator(i);
492 l << e.name();
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 for (int j=0; j < e.keyCount(); j++) {
499 for (int j=0; j < e.keyCount(); j++) {
494 l << QString(e.key(j));
500 l << QString(e.key(j));
495 }
501 }
@@ -750,46 +756,27 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resul
750 return resultPtr;
756 return resultPtr;
751 }
757 }
752
758
753 bool PythonQtClassInfo::hasEnum(const QByteArray& name, PythonQtClassInfo* localScope)
759 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool& isLocalEnum)
754 {
760 {
761 isLocalEnum = true;
755 int scopePos = name.lastIndexOf("::");
762 int scopePos = name.lastIndexOf("::");
756 if (scopePos != -1) {
763 if (scopePos != -1) {
764 isLocalEnum = false;
757 // slit into scope and enum name
765 // slit into scope and enum name
758 QByteArray enumScope = name.mid(0,scopePos);
766 QByteArray enumScope = name.mid(0,scopePos);
759 QByteArray enumName = name.mid(scopePos+2);
767 QByteArray enumName = name.mid(scopePos+2);
760 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
768 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
761 if (info) {
769 if (info) {
762 return info->hasEnum(enumName);
770 return info->findEnumWrapper(enumName);
763 } else{
771 } else{
764 return false;
772 return NULL;
765 }
773 }
766 }
774 }
767 if (localScope) {
775 if (localScope) {
768 return localScope->hasEnum(name);
776 return localScope->findEnumWrapper(name);
769 } else {
777 } else {
770 return false;
778 return NULL;
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 }
791 }
779 }
792 return found;
793 }
780 }
794
781
795 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
782 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
@@ -195,16 +195,13 public:
195 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
195 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
196
196
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
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 bool hasEnum(const QByteArray& name, PythonQtClassInfo* localScope);
198 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool& isLocalEnum);
199
199
200 private:
200 private:
201 void createEnumWrappers();
201 void createEnumWrappers();
202 void createEnumWrappers(const QMetaObject* meta);
202 void createEnumWrappers(const QMetaObject* meta);
203 PyObject* findEnumWrapper(const char* name);
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 //! clear all cached members
205 //! clear all cached members
209 void clearCachedMembers();
206 void clearCachedMembers();
210
207
@@ -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, PythonQtClassInfo* meta, void* alreadyAllocatedCPPObject)
243 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
244 {
244 {
245 bool ok;
245 bool ok;
246 void* ptr = NULL;
246 void* ptr = NULL;
@@ -442,10 +442,17 return Py_None;
442 break;
442 break;
443 default:
443 default:
444 {
444 {
445 if (info.typeId == PythonQtMethodInfo::Unknown) {
446 // check for enum case
445 // check for enum case
447 if (PythonQtClassInfo::hasEnum(info.name, meta)) {
446 if (info.enumWrapper) {
448 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
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 }
449 if (ok) {
456 if (ok) {
450 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
457 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
451 return ptr;
458 return ptr;
@@ -453,7 +460,7 return Py_None;
453 return NULL;
460 return NULL;
454 }
461 }
455 }
462 }
456 }
463
457 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
464 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
458 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
465 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
459 if (info.name.startsWith("QList<")) {
466 if (info.name.startsWith("QList<")) {
@@ -77,8 +77,8 public:
77 //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object,
77 //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object,
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 (classInfo is currently not used anymore)
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* meta, void* alreadyAllocatedCPPObject = NULL);
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, 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);
@@ -114,7 +114,7 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
114 self->ob_type->tp_free((PyObject*)self);
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 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 PythonQtInstanceWrapper *self;
120 PythonQtInstanceWrapper *self;
@@ -415,7 +415,7 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
415 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
415 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
416 }
416 }
417 } else {
417 } else {
418 return PyString_FromFormat("%s (QObject %p)", typeName, wrapper->classInfo()->className(), qobj);
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 #endif
56 #endif
57
57
58 ParameterInfo type;
58 ParameterInfo type;
59 fillParameterInfo(type, QByteArray(meta.typeName()));
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
60 _parameters.append(type);
60 _parameters.append(type);
61 QByteArray name;
61 QByteArray name;
62 QList<QByteArray> names = meta.parameterTypes();
62 QList<QByteArray> names = meta.parameterTypes();
63 foreach (name, names) {
63 foreach (name, names) {
64 fillParameterInfo(type, name);
64 fillParameterInfo(type, name, classInfo);
65 _parameters.append(type);
65 _parameters.append(type);
66 }
66 }
67 }
67 }
@@ -87,10 +87,12 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromMetaObjectA
87 return PythonQtMethodInfo::getCachedMethodInfo(meta, NULL);
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 QByteArray name = orgName;
92 QByteArray name = orgName;
93
93
94 type.enumWrapper = NULL;
95
94 int len = name.length();
96 int len = name.length();
95 if (len>0) {
97 if (len>0) {
96 if (strncmp(name.constData(), "const ", 6)==0) {
98 if (strncmp(name.constData(), "const ", 6)==0) {
@@ -129,6 +131,12 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray
129 }
131 }
130 }
132 }
131 type.name = name;
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 } else {
140 } else {
133 type.typeId = QMetaType::Void;
141 type.typeId = QMetaType::Void;
134 type.isPointer = false;
142 type.isPointer = false;
@@ -50,6 +50,8
50 #include <QMetaMethod>
50 #include <QMetaMethod>
51
51
52 class PythonQtClassInfo;
52 class PythonQtClassInfo;
53 struct _object;
54 typedef struct _object PyObject;
53
55
54 //! stores information about a specific signal/slot/method
56 //! stores information about a specific signal/slot/method
55 class PYTHONQT_EXPORT PythonQtMethodInfo
57 class PYTHONQT_EXPORT PythonQtMethodInfo
@@ -62,8 +64,9 public:
62
64
63 //! stores the QVariant id (if available) and the name of the type
65 //! stores the QVariant id (if available) and the name of the type
64 struct ParameterInfo {
66 struct ParameterInfo {
65 int typeId; // a mixture from QMetaType and ParameterType
66 QByteArray name;
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 bool isPointer;
70 bool isPointer;
68 bool isConst;
71 bool isConst;
69 };
72 };
@@ -98,7 +101,7 public:
98 static void addParameterTypeAlias(const QByteArray& alias, const QByteArray& name);
101 static void addParameterTypeAlias(const QByteArray& alias, const QByteArray& name);
99
102
100 protected:
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 static QHash<QByteArray, int> _parameterTypeDict;
106 static QHash<QByteArray, int> _parameterTypeDict;
104 static QHash<QByteArray, QByteArray> _parameterNameAliases;
107 static QHash<QByteArray, QByteArray> _parameterNameAliases;
@@ -74,7 +74,6 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObj
74 int argc = info->parameterCount();
74 int argc = info->parameterCount();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
76
76
77 bool returnValueIsEnum = false;
78 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
77 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
79 // set return argument to NULL
78 // set return argument to NULL
80 argList[0] = NULL;
79 argList[0] = NULL;
@@ -119,17 +118,16 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObj
119 }
118 }
120
119
121 if (ok) {
120 if (ok) {
121 bool returnValueIsEnum = false;
122
122 // parameters are ok, now create the qt return value which is assigned to by metacall
123 // parameters are ok, now create the qt return value which is assigned to by metacall
123 if (returnValueParam.typeId != QMetaType::Void) {
124 if (returnValueParam.typeId != QMetaType::Void) {
124 // extra handling of enum return value
125 // extra handling of enum return value
125 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
126 if (!returnValueParam.isPointer && returnValueParam.enumWrapper) {
126 returnValueIsEnum = PythonQtClassInfo::hasEnum(returnValueParam.name, classInfo);
127 if (returnValueIsEnum) {
128 // create enum return value
127 // create enum return value
129 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
128 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
130 }
129 returnValueIsEnum = true;
131 }
130 } else {
132 if (argList[0]==NULL) {
133 // create empty default value for the return value
131 // create empty default value for the return value
134 if (!directReturnValuePointer) {
132 if (!directReturnValuePointer) {
135 // create empty default value for the return value
133 // create empty default value for the return value
General Comments 0
You need to be logged in to leave comments. Login now