@@ -915,16 +915,14 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); | |
|
918 | const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL); | |
|
919 | 919 | if (qstrncmp(m.signature(), "new_", 4)==0) { |
|
920 | 920 | if ((decoTypes & ConstructorDecorator) == 0) continue; |
|
921 | // either it returns a * or a QVariant and the name starts with "new_" | |
|
922 | bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant; | |
|
923 | if ((info->parameters().at(0).isPointer || isVariantReturn)) { | |
|
921 | if (info->parameters().at(0).isPointer) { | |
|
924 | 922 | QByteArray signature = m.signature(); |
|
925 | 923 | QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4); |
|
926 | 924 | PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass); |
|
927 | PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator); | |
|
925 | PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator); | |
|
928 | 926 | classInfo->addConstructor(newSlot); |
|
929 | 927 | } |
|
930 | 928 | } else if (qstrncmp(m.signature(), "delete_", 7)==0) { |
@@ -932,7 +930,7 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes) | |||
|
932 | 930 | QByteArray signature = m.signature(); |
|
933 | 931 | QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7); |
|
934 | 932 | PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass); |
|
935 | PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator); | |
|
933 | PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator); | |
|
936 | 934 | classInfo->setDestructor(newSlot); |
|
937 | 935 | } else if (qstrncmp(m.signature(), "static_", 7)==0) { |
|
938 | 936 | if ((decoTypes & StaticDecorator) == 0) continue; |
@@ -940,7 +938,7 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes) | |||
|
940 | 938 | QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1); |
|
941 | 939 | nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_')); |
|
942 | 940 | PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass); |
|
943 | PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator); | |
|
941 | PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator); | |
|
944 | 942 | classInfo->addDecoratorSlot(newSlot); |
|
945 | 943 | } else { |
|
946 | 944 | if ((decoTypes & InstanceDecorator) == 0) continue; |
@@ -948,7 +946,7 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes) | |||
|
948 | 946 | PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1); |
|
949 | 947 | if (p.isPointer) { |
|
950 | 948 | PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name); |
|
951 | PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator); | |
|
949 | PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator); | |
|
952 | 950 | classInfo->addDecoratorSlot(newSlot); |
|
953 | 951 | } |
|
954 | 952 | } |
@@ -186,7 +186,7 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(con | |||
|
186 | 186 | // check if same length and same name |
|
187 | 187 | if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { |
|
188 | 188 | found = true; |
|
189 | PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator); | |
|
189 | PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator); | |
|
190 | 190 | info->setUpcastingOffset(upcastingOffset); |
|
191 | 191 | //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset; |
|
192 | 192 | if (tail) { |
@@ -225,7 +225,7 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName) | |||
|
225 | 225 | // check if same length and same name |
|
226 | 226 | if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { |
|
227 | 227 | found = true; |
|
228 | PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i); | |
|
228 | PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i); | |
|
229 | 229 | if (tail) { |
|
230 | 230 | tail->setNextInfo(info); |
|
231 | 231 | } else { |
@@ -458,12 +458,9 QStringList PythonQtClassInfo::memberList(bool metaOnly) | |||
|
458 | 458 | QMetaMethod m = _meta->method(i); |
|
459 | 459 | if ((m.methodType() == QMetaMethod::Method || |
|
460 | 460 | m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) { |
|
461 |
QByteArray signa(m.signature()); |
|
|
462 | if (signa.startsWith("new_")) continue; | |
|
463 | if (signa.startsWith("delete_")) continue; | |
|
464 | if (signa.startsWith("static_")) continue; | |
|
465 | PythonQtSlotInfo slot(m, i); | |
|
466 | l << slot.slotName(); | |
|
461 | QByteArray signa(m.signature()); | |
|
462 | signa = signa.left(signa.indexOf('(')); | |
|
463 | l << signa; | |
|
467 | 464 | } |
|
468 | 465 | } |
|
469 | 466 | } |
@@ -586,11 +583,7 QString PythonQtClassInfo::help() | |||
|
586 | 583 | QMetaMethod m = _meta->method(i); |
|
587 | 584 | if ((m.methodType() == QMetaMethod::Method || |
|
588 | 585 | m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) { |
|
589 | QByteArray signa(m.signature()); | |
|
590 | if (signa.startsWith("new_")) continue; | |
|
591 | if (signa.startsWith("delete_")) continue; | |
|
592 | if (signa.startsWith("static_")) continue; | |
|
593 | PythonQtSlotInfo slot(m, i); | |
|
586 | PythonQtSlotInfo slot(this, m, i); | |
|
594 | 587 | h += slot.fullSignature()+ "\n"; |
|
595 | 588 | } |
|
596 | 589 | } |
@@ -681,9 +674,14 QObject* PythonQtClassInfo::decorator() | |||
|
681 | 674 | _decoratorProvider = (*_decoratorProviderCB)(); |
|
682 | 675 | if (_decoratorProvider) { |
|
683 | 676 | _decoratorProvider->setParent(PythonQt::priv()); |
|
677 | // setup enums early, since they might be needed by the constructor decorators: | |
|
678 | if (!_enumsCreated) { | |
|
679 | createEnumWrappers(); | |
|
680 | } | |
|
684 | 681 | PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator); |
|
685 | 682 | } |
|
686 | 683 | } |
|
684 | // check if enums need to be created and create them if they are not yet created | |
|
687 | 685 | if (!_enumsCreated) { |
|
688 | 686 | createEnumWrappers(); |
|
689 | 687 | } |
@@ -40,12 +40,13 | |||
|
40 | 40 | //---------------------------------------------------------------------------------- |
|
41 | 41 | |
|
42 | 42 | #include "PythonQtMethodInfo.h" |
|
43 | #include "PythonQtClassInfo.h" | |
|
43 | 44 | #include <iostream> |
|
44 | 45 | |
|
45 | 46 | QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures; |
|
46 | 47 | QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases; |
|
47 | 48 | |
|
48 | PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta) | |
|
49 | PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo) | |
|
49 | 50 | { |
|
50 | 51 | #ifdef PYTHONQT_DEBUG |
|
51 | 52 | QByteArray sig(meta.signature()); |
@@ -65,14 +66,14 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta) | |||
|
65 | 66 | } |
|
66 | 67 | } |
|
67 | 68 | |
|
68 | const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal) | |
|
69 | const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo) | |
|
69 | 70 | { |
|
70 | 71 | QByteArray sig(signal.signature()); |
|
71 | 72 | sig = sig.mid(sig.indexOf('(')); |
|
72 | 73 | QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig; |
|
73 | 74 | PythonQtMethodInfo* result = _cachedSignatures.value(fullSig); |
|
74 | 75 | if (!result) { |
|
75 | result = new PythonQtMethodInfo(signal); | |
|
76 | result = new PythonQtMethodInfo(signal, classInfo); | |
|
76 | 77 | _cachedSignatures.insert(fullSig, result); |
|
77 | 78 | } |
|
78 | 79 | return result; |
@@ -83,7 +84,7 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromMetaObjectA | |||
|
83 | 84 | QByteArray sig = QMetaObject::normalizedSignature(signature); |
|
84 | 85 | int idx = metaObject->indexOfMethod(sig); |
|
85 | 86 | QMetaMethod meta = metaObject->method(idx); |
|
86 | return PythonQtMethodInfo::getCachedMethodInfo(meta); | |
|
87 | return PythonQtMethodInfo::getCachedMethodInfo(meta, NULL); | |
|
87 | 88 | } |
|
88 | 89 | |
|
89 | 90 | void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName) |
@@ -49,6 +49,8 | |||
|
49 | 49 | #include <QList> |
|
50 | 50 | #include <QMetaMethod> |
|
51 | 51 | |
|
52 | class PythonQtClassInfo; | |
|
53 | ||
|
52 | 54 | //! stores information about a specific signal/slot/method |
|
53 | 55 | class PYTHONQT_EXPORT PythonQtMethodInfo |
|
54 | 56 | { |
@@ -68,16 +70,16 public: | |||
|
68 | 70 | |
|
69 | 71 | PythonQtMethodInfo() {}; |
|
70 | 72 | ~PythonQtMethodInfo() {}; |
|
71 | PythonQtMethodInfo(const QMetaMethod& meta); | |
|
73 | PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo); | |
|
72 | 74 | PythonQtMethodInfo(const PythonQtMethodInfo& other) { |
|
73 | 75 | _parameters = other._parameters; |
|
74 | 76 | } |
|
75 | 77 | |
|
76 | 78 | //! returns the method info of the signature, uses a cache internally to speed up |
|
77 | //! multiple requests for the same method | |
|
78 | static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method); | |
|
79 | //! multiple requests for the same method, classInfo is passed to allow local enum resolution (if NULL is passed, no local enums are recognized) | |
|
80 | static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method, PythonQtClassInfo* classInfo); | |
|
79 | 81 | |
|
80 | //! get the cached method info by finding the meta method on the meta object via its signature | |
|
82 | //! get the cached method info by finding the meta method on the meta object via its signature, enums are only supported with leading namespace:: | |
|
81 | 83 | static const PythonQtMethodInfo* getCachedMethodInfoFromMetaObjectAndSignature(const QMetaObject* metaObject, const char* signature); |
|
82 | 84 | |
|
83 | 85 | //! cleanup the cache |
@@ -125,9 +127,9 public: | |||
|
125 | 127 | _upcastingOffset = 0; |
|
126 | 128 | } |
|
127 | 129 | |
|
128 | PythonQtSlotInfo(const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo() | |
|
130 | PythonQtSlotInfo(PythonQtClassInfo* classInfo, const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo() | |
|
129 | 131 | { |
|
130 | const PythonQtMethodInfo* info = getCachedMethodInfo(meta); | |
|
132 | const PythonQtMethodInfo* info = getCachedMethodInfo(meta, classInfo); | |
|
131 | 133 | _meta = meta; |
|
132 | 134 | _parameters = info->parameters(); |
|
133 | 135 | _slotIndex = slotIndex; |
@@ -142,6 +142,17 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInf | |||
|
142 | 142 | PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj) |
|
143 | 143 | { |
|
144 | 144 | _obj = obj; |
|
145 | ||
|
146 | // fetch the class info for object, since we will need to for correct enum resolution in | |
|
147 | // signals | |
|
148 | _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject()); | |
|
149 | if (!_objClassInfo || !_objClassInfo->isQObject()) { | |
|
150 | PythonQt::self()->registerClass(obj->metaObject()); | |
|
151 | _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject()); | |
|
152 | } | |
|
153 | // force decorator/enum creation | |
|
154 | _objClassInfo->decorator(); | |
|
155 | ||
|
145 | 156 | _slotCount = staticMetaObject.methodOffset(); |
|
146 | 157 | } |
|
147 | 158 | |
@@ -158,7 +169,7 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* call | |||
|
158 | 169 | if (sigId>=0) { |
|
159 | 170 | // create PythonQtMethodInfo from signal |
|
160 | 171 | QMetaMethod meta = _obj->metaObject()->method(sigId); |
|
161 | const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta); | |
|
172 | const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo); | |
|
162 | 173 | PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable); |
|
163 | 174 | _targets.append(t); |
|
164 | 175 | // now connect to ourselves with the new slot id |
@@ -47,6 +47,7 | |||
|
47 | 47 | #include "PythonQtObjectPtr.h" |
|
48 | 48 | |
|
49 | 49 | class PythonQtMethodInfo; |
|
50 | class PythonQtClassInfo; | |
|
50 | 51 | |
|
51 | 52 | //! stores information about a signal target |
|
52 | 53 | /*! copy construction and assignment works fine with the C++ standard behaviour and are thus not implemented |
@@ -130,6 +131,7 private: | |||
|
130 | 131 | int getSignalIndex(const char* signal); |
|
131 | 132 | |
|
132 | 133 | QObject* _obj; |
|
134 | PythonQtClassInfo* _objClassInfo; | |
|
133 | 135 | int _slotCount; |
|
134 | 136 | // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals |
|
135 | 137 | QList<PythonQtSignalTarget> _targets; |
General Comments 0
You need to be logged in to leave comments.
Login now