diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index dde23da..f2ad6fc 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -915,16 +915,14 @@ void PythonQtPrivate::addDecorators(QObject* o, int decoTypes) QMetaMethod m = o->metaObject()->method(i); if ((m.methodType() == QMetaMethod::Method || m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) { - const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m); + const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL); if (qstrncmp(m.signature(), "new_", 4)==0) { if ((decoTypes & ConstructorDecorator) == 0) continue; - // either it returns a * or a QVariant and the name starts with "new_" - bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant; - if ((info->parameters().at(0).isPointer || isVariantReturn)) { + if (info->parameters().at(0).isPointer) { QByteArray signature = m.signature(); QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4); PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass); - PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator); + PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator); classInfo->addConstructor(newSlot); } } else if (qstrncmp(m.signature(), "delete_", 7)==0) { @@ -932,7 +930,7 @@ void PythonQtPrivate::addDecorators(QObject* o, int decoTypes) QByteArray signature = m.signature(); QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7); PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass); - PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator); + PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator); classInfo->setDestructor(newSlot); } else if (qstrncmp(m.signature(), "static_", 7)==0) { if ((decoTypes & StaticDecorator) == 0) continue; @@ -940,7 +938,7 @@ void PythonQtPrivate::addDecorators(QObject* o, int decoTypes) QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1); nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_')); PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass); - PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator); + PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator); classInfo->addDecoratorSlot(newSlot); } else { if ((decoTypes & InstanceDecorator) == 0) continue; @@ -948,7 +946,7 @@ void PythonQtPrivate::addDecorators(QObject* o, int decoTypes) PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1); if (p.isPointer) { PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name); - PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator); + PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator); classInfo->addDecoratorSlot(newSlot); } } diff --git a/src/PythonQtClassInfo.cpp b/src/PythonQtClassInfo.cpp index 1f4ab0e..358c25d 100644 --- a/src/PythonQtClassInfo.cpp +++ b/src/PythonQtClassInfo.cpp @@ -186,7 +186,7 @@ PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(con // check if same length and same name if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { found = true; - PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator); + PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator); info->setUpcastingOffset(upcastingOffset); //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset; if (tail) { @@ -225,7 +225,7 @@ bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName) // check if same length and same name if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { found = true; - PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i); + PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i); if (tail) { tail->setNextInfo(info); } else { @@ -458,12 +458,9 @@ QStringList PythonQtClassInfo::memberList(bool metaOnly) QMetaMethod m = _meta->method(i); if ((m.methodType() == QMetaMethod::Method || m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) { - QByteArray signa(m.signature()); - if (signa.startsWith("new_")) continue; - if (signa.startsWith("delete_")) continue; - if (signa.startsWith("static_")) continue; - PythonQtSlotInfo slot(m, i); - l << slot.slotName(); + QByteArray signa(m.signature()); + signa = signa.left(signa.indexOf('(')); + l << signa; } } } @@ -586,11 +583,7 @@ QString PythonQtClassInfo::help() QMetaMethod m = _meta->method(i); if ((m.methodType() == QMetaMethod::Method || m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) { - QByteArray signa(m.signature()); - if (signa.startsWith("new_")) continue; - if (signa.startsWith("delete_")) continue; - if (signa.startsWith("static_")) continue; - PythonQtSlotInfo slot(m, i); + PythonQtSlotInfo slot(this, m, i); h += slot.fullSignature()+ "\n"; } } @@ -681,9 +674,14 @@ QObject* PythonQtClassInfo::decorator() _decoratorProvider = (*_decoratorProviderCB)(); if (_decoratorProvider) { _decoratorProvider->setParent(PythonQt::priv()); + // setup enums early, since they might be needed by the constructor decorators: + if (!_enumsCreated) { + createEnumWrappers(); + } PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator); } } + // check if enums need to be created and create them if they are not yet created if (!_enumsCreated) { createEnumWrappers(); } diff --git a/src/PythonQtMethodInfo.cpp b/src/PythonQtMethodInfo.cpp index 1c2f041..91786ee 100644 --- a/src/PythonQtMethodInfo.cpp +++ b/src/PythonQtMethodInfo.cpp @@ -40,12 +40,13 @@ //---------------------------------------------------------------------------------- #include "PythonQtMethodInfo.h" +#include "PythonQtClassInfo.h" #include QHash PythonQtMethodInfo::_cachedSignatures; QHash PythonQtMethodInfo::_parameterNameAliases; -PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta) +PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo) { #ifdef PYTHONQT_DEBUG QByteArray sig(meta.signature()); @@ -65,14 +66,14 @@ PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta) } } -const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal) +const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo) { QByteArray sig(signal.signature()); sig = sig.mid(sig.indexOf('(')); QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig; PythonQtMethodInfo* result = _cachedSignatures.value(fullSig); if (!result) { - result = new PythonQtMethodInfo(signal); + result = new PythonQtMethodInfo(signal, classInfo); _cachedSignatures.insert(fullSig, result); } return result; @@ -83,7 +84,7 @@ const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromMetaObjectA QByteArray sig = QMetaObject::normalizedSignature(signature); int idx = metaObject->indexOfMethod(sig); QMetaMethod meta = metaObject->method(idx); - return PythonQtMethodInfo::getCachedMethodInfo(meta); + return PythonQtMethodInfo::getCachedMethodInfo(meta, NULL); } void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName) diff --git a/src/PythonQtMethodInfo.h b/src/PythonQtMethodInfo.h index 5b74e6e..256f40f 100644 --- a/src/PythonQtMethodInfo.h +++ b/src/PythonQtMethodInfo.h @@ -49,6 +49,8 @@ #include #include +class PythonQtClassInfo; + //! stores information about a specific signal/slot/method class PYTHONQT_EXPORT PythonQtMethodInfo { @@ -68,16 +70,16 @@ public: PythonQtMethodInfo() {}; ~PythonQtMethodInfo() {}; - PythonQtMethodInfo(const QMetaMethod& meta); + PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo); PythonQtMethodInfo(const PythonQtMethodInfo& other) { _parameters = other._parameters; } //! returns the method info of the signature, uses a cache internally to speed up - //! multiple requests for the same method - static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method); + //! multiple requests for the same method, classInfo is passed to allow local enum resolution (if NULL is passed, no local enums are recognized) + static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method, PythonQtClassInfo* classInfo); - //! get the cached method info by finding the meta method on the meta object via its signature + //! get the cached method info by finding the meta method on the meta object via its signature, enums are only supported with leading namespace:: static const PythonQtMethodInfo* getCachedMethodInfoFromMetaObjectAndSignature(const QMetaObject* metaObject, const char* signature); //! cleanup the cache @@ -125,9 +127,9 @@ public: _upcastingOffset = 0; } - PythonQtSlotInfo(const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo() + PythonQtSlotInfo(PythonQtClassInfo* classInfo, const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo() { - const PythonQtMethodInfo* info = getCachedMethodInfo(meta); + const PythonQtMethodInfo* info = getCachedMethodInfo(meta, classInfo); _meta = meta; _parameters = info->parameters(); _slotIndex = slotIndex; diff --git a/src/PythonQtSignalReceiver.cpp b/src/PythonQtSignalReceiver.cpp index b0b9033..860b079 100644 --- a/src/PythonQtSignalReceiver.cpp +++ b/src/PythonQtSignalReceiver.cpp @@ -142,6 +142,17 @@ PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInf PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj) { _obj = obj; + + // fetch the class info for object, since we will need to for correct enum resolution in + // signals + _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject()); + if (!_objClassInfo || !_objClassInfo->isQObject()) { + PythonQt::self()->registerClass(obj->metaObject()); + _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject()); + } + // force decorator/enum creation + _objClassInfo->decorator(); + _slotCount = staticMetaObject.methodOffset(); } @@ -158,7 +169,7 @@ bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* call if (sigId>=0) { // create PythonQtMethodInfo from signal QMetaMethod meta = _obj->metaObject()->method(sigId); - const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta); + const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo); PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable); _targets.append(t); // now connect to ourselves with the new slot id diff --git a/src/PythonQtSignalReceiver.h b/src/PythonQtSignalReceiver.h index 041c4c4..f386ae0 100644 --- a/src/PythonQtSignalReceiver.h +++ b/src/PythonQtSignalReceiver.h @@ -47,6 +47,7 @@ #include "PythonQtObjectPtr.h" class PythonQtMethodInfo; +class PythonQtClassInfo; //! stores information about a signal target /*! copy construction and assignment works fine with the C++ standard behaviour and are thus not implemented @@ -130,6 +131,7 @@ private: int getSignalIndex(const char* signal); QObject* _obj; + PythonQtClassInfo* _objClassInfo; int _slotCount; // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals QList _targets;