##// 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 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 for (int j=0; j < e.keyCount(); j++) {
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 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 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->hasEnum(enumName);
770 return info->findEnumWrapper(enumName);
763 771 } else{
764 return false;
772 return NULL;
765 773 }
766 774 }
767 775 if (localScope) {
768 return localScope->hasEnum(name);
776 return localScope->findEnumWrapper(name);
769 777 } else {
770 return false;
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 bool hasEnum(const QByteArray& name, PythonQtClassInfo* localScope);
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* meta, void* alreadyAllocatedCPPObject)
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 return ptr;
452 } else {
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, the meta object is passed in for enum resolving
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* meta, void* alreadyAllocatedCPPObject = NULL);
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 (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 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 int len = name.length();
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 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
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.typeId == PythonQtMethodInfo::Unknown) {
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