From a63222bd6a1b680b4da197c496ddd7db931b9eb2 2012-04-30 14:19:58 From: florianlink Date: 2012-04-30 14:19:58 Subject: [PATCH] merged various changes from MeVisLab repository git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@219 ea8d5007-eb21-0410-b261-ccb3ea6e24a9 --- diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index 7e9a69a..f4be0ab 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -78,11 +78,12 @@ void PythonQt::init(int flags, const QByteArray& pythonQtModuleName) PythonQtRegisterToolClassesTemplateConverter(quint64); // TODO: which other POD types should be available for QList etc. - PythonQt::self()->addDecorators(new PythonQtStdDecorators()); - PythonQt_init_QtCoreBuiltin(NULL); PythonQt_init_QtGuiBuiltin(NULL); + PythonQt::self()->addDecorators(new PythonQtStdDecorators()); + PythonQt::self()->registerCPPClass("QMetaObject",0, "QtCore", PythonQtCreateObject); + PythonQtRegisterToolClassesTemplateConverter(QByteArray); PythonQtRegisterToolClassesTemplateConverter(QDate); PythonQtRegisterToolClassesTemplateConverter(QTime); @@ -919,6 +920,13 @@ QStringList PythonQt::introspectObject(PyObject* object, ObjectType type) } Py_DECREF(keys); } + if ((type == Anything) || (type == Variable)) { + if (object->ob_type == &PythonQtClassWrapper_Type) { + PythonQtClassWrapper* o = (PythonQtClassWrapper*)object; + PythonQtClassInfo* info = o->classInfo(); + results += info->propertyList(); + } + } } return results; } @@ -958,7 +966,13 @@ QStringList PythonQt::introspectType(const QString& typeName, ObjectType type) // the last item may be a member, split it away and try again QStringList tmp = typeName.split("."); QString memberName = tmp.takeLast(); - QString typeName = tmp.takeLast(); + QString typeName; + if (tmp.isEmpty()) { + typeName = memberName; + memberName.clear(); + } else { + typeName = tmp.takeLast(); + } PyObject* typeObject = getObjectByType(typeName); if (typeObject) { object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData()); @@ -1690,3 +1704,18 @@ QString PythonQtPrivate::getSignature(PyObject* object) return signature; } + +void PythonQtPrivate::shellClassDeleted( void* shellClass ) +{ + PythonQtInstanceWrapper* wrap = _wrappedObjects.value(shellClass); + if (wrap && wrap->_wrappedPtr) { + // this is a pure C++ wrapper and the shell has gone, so we need + // to set the _wrappedPtr to NULL on the wrapper + wrap->_wrappedPtr = NULL; + // and then we remove the wrapper, since the wrapped class is gone + _wrappedObjects.remove(shellClass); + } + // if the wrapper is a QObject, we do not handle this here, + // it will be handled by the QPointer<> to the QObject, which becomes NULL + // via the QObject destructor. +} \ No newline at end of file diff --git a/src/PythonQt.h b/src/PythonQt.h index a064342..0224f0e 100644 --- a/src/PythonQt.h +++ b/src/PythonQt.h @@ -563,6 +563,9 @@ public: //! remove the wrapper ptr again void removeWrapperPointer(void* obj); + //! called by destructor of shells to allow invalidation of the Python wrapper + void shellClassDeleted(void* shellClass); + //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj); diff --git a/src/PythonQtClassInfo.cpp b/src/PythonQtClassInfo.cpp index 837aeca..2a2b44e 100644 --- a/src/PythonQtClassInfo.cpp +++ b/src/PythonQtClassInfo.cpp @@ -205,46 +205,53 @@ PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(con } tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset); - - return tail; -} -bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName) -{ - bool found = false; - int memberNameLen = static_cast(strlen(memberName)); - PythonQtSlotInfo* tail = NULL; + // now look for slots/signals/methods on this level of the meta object if (_meta) { int numMethods = _meta->methodCount(); - for (int i = 0; i < numMethods; i++) { + // start from methodOffset, to only add slots which are located in this class, + // and not in the parent class, which is traversed recursively later on. + // (if the class in not a QObject, we are working with a script wrapper QObject + // and need to read all slots/signals starting from 0). + int methodOffset = _isQObject?_meta->methodOffset():0; + for (int i = methodOffset; i < numMethods; i++) { QMetaMethod m = _meta->method(i); if (((m.methodType() == QMetaMethod::Method || - m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) + m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) || m.methodType()==QMetaMethod::Signal) { - - const char* sigStart = m.signature(); - // find the first '(' - int offset = findCharOffset(sigStart, '('); - - // check if same length and same name - if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { - found = true; - PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i); - if (tail) { - tail->setNextInfo(info); - } else { - PythonQtMemberInfo newInfo(info); - _cachedMembers.insert(memberName, newInfo); + + const char* sigStart = m.signature(); + // find the first '(' + int offset = findCharOffset(sigStart, '('); + + // check if same length and same name + if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) { + found = true; + PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i); + if (tail) { + tail->setNextInfo(info); + } else { + PythonQtMemberInfo newInfo(info); + memberCache.insert(memberName, newInfo); + } + tail = info; } - tail = info; - } } } } + return tail; +} + +bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName) +{ + bool found = false; + PythonQtSlotInfo* tail = NULL; // look for dynamic decorators in this class and in derived classes + // (do this first to allow overloading of existing slots with generated wrappers, + // e.g. QDialog::accept is overloaded with PythonQtWrapper_QDialog::accept decorator) tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0); - + return found; } @@ -710,22 +717,6 @@ QObject* PythonQtClassInfo::decorator() return _decoratorProvider; } -bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object) -{ - PythonQtMemberInfo info = member("py_hasOwner"); - if (info._type == PythonQtMemberInfo::Slot) { - void* obj = object; - bool result = false; - void* args[2]; - args[0] = &result; - args[1] = &obj; - info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args); - return !result; - } else { - return false; - } -} - void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName) { if (!_polymorphicHandlers.isEmpty()) { diff --git a/src/PythonQtClassInfo.h b/src/PythonQtClassInfo.h index 517d8c7..94f1d9e 100644 --- a/src/PythonQtClassInfo.h +++ b/src/PythonQtClassInfo.h @@ -159,9 +159,6 @@ public: //! add the parent class info of a CPP object void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); } - //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed - bool hasOwnerMethodButNoOwner(void* object); - //! set the associated PythonQtClassWrapper (which handles instance creation of this type) void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; } diff --git a/src/PythonQtConversion.cpp b/src/PythonQtConversion.cpp index c46e6cd..237af03 100644 --- a/src/PythonQtConversion.cpp +++ b/src/PythonQtConversion.cpp @@ -377,11 +377,32 @@ void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& i // a pointer if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar) { + if (obj->ob_type == &PyString_Type) { + // take direct reference to string data + const char* data = PyString_AS_STRING(obj); + PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)data, ptr); + } else { + // convert to string + QString str = PyObjGetString(obj, strict, ok); + if (ok) { + QByteArray bytes; + bytes = str.toUtf8(); + if (ok) { + void* ptr2 = NULL; + PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(bytes), ptr2); + PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr); + } + } + } + } else if (info.typeId == QMetaType::QString) { + // TODO: this is a special case for bad Qt APIs which take a QString*, like QtGui.QFileDialog.getSaveFileName + // In general we would need to decide to either support * args for all basic types (ignoring the fact that the + // result value is not useable in Python), or if all these APIs need to be wrapped manually/differently, like PyQt/PySide do. QString str = PyObjGetString(obj, strict, ok); if (ok) { void* ptr2 = NULL; - PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2); - PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr); + PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(str), ptr2); + PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)((QVariant*)ptr2)->constData(), ptr); } } else if (info.name == "PyObject") { // handle low level PyObject directly @@ -746,7 +767,13 @@ int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) { } else if (val == Py_True) { d = 1; } else { - ok = false; + PyErr_Clear(); + // PyInt_AsLong will try conversion to an int if the object is not an int: + d = PyInt_AsLong(val); + if (PyErr_Occurred()) { + ok = false; + PyErr_Clear(); + } } } else { ok = false; @@ -772,7 +799,13 @@ qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) { } else if (val == Py_True) { d = 1; } else { - ok = false; + PyErr_Clear(); + // PyLong_AsLongLong will try conversion to an int if the object is not an int: + d = PyLong_AsLongLong(val); + if (PyErr_Occurred()) { + ok = false; + PyErr_Clear(); + } } } else { ok = false; @@ -798,7 +831,13 @@ quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) { } else if (val == Py_True) { d = 1; } else { - ok = false; + PyErr_Clear(); + // PyLong_AsLongLong will try conversion to an int if the object is not an int: + d = PyLong_AsLongLong(val); + if (PyErr_Occurred()) { + PyErr_Clear(); + ok = false; + } } } else { ok = false; @@ -821,7 +860,13 @@ double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) { } else if (val == Py_True) { d = 1; } else { - ok = false; + PyErr_Clear(); + // PyFloat_AsDouble will try conversion to a double if the object is not a float: + d = PyFloat_AsDouble(val); + if (PyErr_Occurred()) { + PyErr_Clear(); + ok = false; + } } } else { ok = false; diff --git a/src/PythonQtInstanceWrapper.cpp b/src/PythonQtInstanceWrapper.cpp index 68eda99..96375e3 100644 --- a/src/PythonQtInstanceWrapper.cpp +++ b/src/PythonQtInstanceWrapper.cpp @@ -64,7 +64,7 @@ static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, // we own our qobject, so we delete it now: delete self->_obj; self->_obj = NULL; - if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) { + if (force || self->_ownedByPythonQt) { int type = self->classInfo()->metaTypeId(); if (self->_useQMetaTypeDestroy && type>=0) { // use QMetaType to destroy the object diff --git a/src/PythonQtMethodInfo.cpp b/src/PythonQtMethodInfo.cpp index 9925aea..bb711aa 100644 --- a/src/PythonQtMethodInfo.cpp +++ b/src/PythonQtMethodInfo.cpp @@ -197,6 +197,31 @@ int PythonQtMethodInfo::nameToType(const char* name) _parameterTypeDict.insert("QString", QMetaType::QString); _parameterTypeDict.insert("", QMetaType::Void); _parameterTypeDict.insert("void", QMetaType::Void); + + // GL types + _parameterTypeDict.insert("GLenum", QMetaType::UInt); + _parameterTypeDict.insert("GLboolean", QMetaType::UChar); + _parameterTypeDict.insert("GLbitfield", QMetaType::UInt); + _parameterTypeDict.insert("GLbyte", QMetaType::Char); + _parameterTypeDict.insert("GLubyte", QMetaType::UChar); + _parameterTypeDict.insert("GLshort", QMetaType::Short); + _parameterTypeDict.insert("GLushort", QMetaType::UShort); + _parameterTypeDict.insert("GLint", QMetaType::Int); + _parameterTypeDict.insert("GLuint", QMetaType::UInt); + _parameterTypeDict.insert("GLsizei", QMetaType::UInt); + _parameterTypeDict.insert("GLclampf", QMetaType::Float); + _parameterTypeDict.insert("GLfloat", QMetaType::Float); + _parameterTypeDict.insert("GLclampd", QMetaType::Double); + _parameterTypeDict.insert("GLdouble", QMetaType::Double); + _parameterTypeDict.insert("GLvoid", QMetaType::Void); + if (QT_POINTER_SIZE == 8) { + _parameterTypeDict.insert("qgl_GLintptr", QMetaType::LongLong); + _parameterTypeDict.insert("qgl_GLsizeiptr", QMetaType::LongLong); + } else { + _parameterTypeDict.insert("qgl_GLintptr", QMetaType::Int); + _parameterTypeDict.insert("qgl_GLsizeiptr", QMetaType::Int); + } + // QVariant names _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong); _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong); diff --git a/src/PythonQtSignalReceiver.cpp b/src/PythonQtSignalReceiver.cpp index 1b79f9a..82b208d 100644 --- a/src/PythonQtSignalReceiver.cpp +++ b/src/PythonQtSignalReceiver.cpp @@ -47,6 +47,10 @@ #include #include "funcobject.h" +// use -2 to signal that the variable is uninitialized +int PythonQtSignalReceiver::_destroyedSignal1Id = -2; +int PythonQtSignalReceiver::_destroyedSignal2Id = -2; + void PythonQtSignalTarget::call(void **arguments) const { PyObject* result = call(_callable, methodInfo(), arguments); if (result) { @@ -141,6 +145,16 @@ bool PythonQtSignalTarget::isSame( int signalId, PyObject* callable ) const PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj) { + if (_destroyedSignal1Id == -2) { + // initialize these once + _destroyedSignal1Id = QObject::staticMetaObject.indexOfSignal("destroyed()"); + _destroyedSignal2Id = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); + if (_destroyedSignal1Id == -1 || _destroyedSignal2Id == -1) { + std::cerr << "PythonQt: could not find destroyed signal index, should never happen!" << std::endl; + } + } + + _destroyedSignalCount = 0; _obj = obj; // fetch the class info for object, since we will need to for correct enum resolution in @@ -177,13 +191,22 @@ bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* call _slotCount++; flag = true; + + if (sigId == _destroyedSignal1Id || sigId == _destroyedSignal2Id) { + _destroyedSignalCount++; + if (_destroyedSignalCount==1) { + // make ourself parent of PythonQt, to not get deleted as a child of the QObject we are + // listening to, since we do that manually when we receive the destroyed signal + this->setParent(PythonQt::priv()); + } + } } return flag; } bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable) { - bool found = false; + int foundCount = 0; int sigId = getSignalIndex(signal); if (sigId>=0) { QMutableListIterator i(_targets); @@ -191,7 +214,7 @@ bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* c while (i.hasNext()) { if (i.next().isSame(sigId, callable)) { i.remove(); - found = true; + foundCount++; break; } } @@ -199,17 +222,19 @@ bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* c while (i.hasNext()) { if (i.next().signalId() == sigId) { i.remove(); - found = true; + foundCount++; } } } } - return found; -} - -void PythonQtSignalReceiver::removeSignalHandlers() -{ - _targets.clear(); + if ((foundCount>0) && (sigId == _destroyedSignal1Id) || (sigId == _destroyedSignal2Id)) { + _destroyedSignalCount -= foundCount; + if (_destroyedSignalCount==0) { + // make ourself child of QObject again, to get deleted when the object gets deleted + this->setParent(_obj); + } + } + return foundCount>0; } int PythonQtSignalReceiver::getSignalIndex(const char* signal) @@ -229,11 +254,17 @@ int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **argu QObject::qt_metacall(c, id, arguments); } - bool found = false; foreach(const PythonQtSignalTarget& t, _targets) { if (t.slotId() == id) { - found = true; t.call(arguments); + // if the signal is the last destroyed signal, we delete ourselves + int sigId = t.signalId(); + if ((sigId == _destroyedSignal1Id) || (sigId == _destroyedSignal2Id)) { + _destroyedSignalCount--; + if (_destroyedSignalCount == 0) { + delete this; + } + } break; } } diff --git a/src/PythonQtSignalReceiver.h b/src/PythonQtSignalReceiver.h index 90ef3fc..16682cf 100644 --- a/src/PythonQtSignalReceiver.h +++ b/src/PythonQtSignalReceiver.h @@ -121,9 +121,6 @@ public: //! remove a signal handler for given callable (or all callables on that signal if callable is NULL) bool removeSignalHandler(const char* signal, PyObject* callable = NULL); - //! remove all signal handlers - void removeSignalHandlers(); - //! we implement this method to simulate a number of slots that match the ids in _targets virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments); @@ -134,8 +131,12 @@ private: QObject* _obj; PythonQtClassInfo* _objClassInfo; int _slotCount; + int _destroyedSignalCount; // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals QList _targets; + + static int _destroyedSignal1Id; + static int _destroyedSignal2Id; }; diff --git a/src/PythonQtStdDecorators.cpp b/src/PythonQtStdDecorators.cpp index 7ddca2a..75f0eca 100644 --- a/src/PythonQtStdDecorators.cpp +++ b/src/PythonQtStdDecorators.cpp @@ -66,7 +66,7 @@ bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, P return result; } -bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot) +bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot, Qt::ConnectionType type) { bool r = false; if (sender && receiver) { @@ -85,7 +85,7 @@ bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, Q } else { slotTmp = "1" + slot; } - r = QObject::connect(sender, signalTmp, receiver, slotTmp); + r = QObject::connect(sender, signalTmp, receiver, slotTmp, type); } return r; } @@ -316,3 +316,8 @@ int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, c return 0; } + +const QMetaObject* PythonQtStdDecorators::metaObject( QObject* obj ) +{ + return obj->metaObject(); +} \ No newline at end of file diff --git a/src/PythonQtStdDecorators.h b/src/PythonQtStdDecorators.h index 673274b..290d3e1 100644 --- a/src/PythonQtStdDecorators.h +++ b/src/PythonQtStdDecorators.h @@ -53,6 +53,10 @@ #include #include #include +#include +#include +#include +#include class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject { @@ -60,9 +64,16 @@ class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject public slots: bool connect(QObject* sender, const QByteArray& signal, PyObject* callable); - bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot); + bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot, Qt::ConnectionType type = Qt::AutoConnection); + bool connect(QObject* receiver, QObject* sender, const QByteArray& signal, const QByteArray& slot, Qt::ConnectionType type = Qt::AutoConnection) { return connect(sender, signal, receiver, slot, type); } + bool static_QObject_connect(QObject* sender, const QByteArray& signal, PyObject* callable) { return connect(sender, signal, callable); } + bool static_QObject_connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot, Qt::ConnectionType type = Qt::AutoConnection) { return connect(sender, signal, receiver, slot, type); } bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL); bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot); + bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL) { return disconnect(sender, signal, callable); } + bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot) { return connect(sender, signal, receiver, slot); } + + const QMetaObject* metaObject( QObject* obj ); QObject* parent(QObject* o); void setParent(QObject* o, QObject* parent); @@ -105,5 +116,44 @@ private: int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList& list); }; +class PythonQtWrapper_QMetaObject : public QObject +{ + Q_OBJECT + +public slots: + const char *className(QMetaObject* obj) const { return obj->className(); } + const QMetaObject *superClass(QMetaObject* obj) const { return obj->superClass(); } + + int methodOffset(QMetaObject* obj) const { return obj->methodOffset(); } + int enumeratorOffset(QMetaObject* obj) const { return obj->enumeratorOffset(); } + int propertyOffset(QMetaObject* obj) const { return obj->propertyOffset(); } + int classInfoOffset(QMetaObject* obj) const { return obj->classInfoOffset(); } + + int constructorCount(QMetaObject* obj) const { return obj->constructorCount(); } + int methodCount(QMetaObject* obj) const { return obj->methodCount(); } + int enumeratorCount(QMetaObject* obj) const { return obj->enumeratorCount(); } + int propertyCount(QMetaObject* obj) const { return obj->propertyCount(); } + int classInfoCount(QMetaObject* obj) const { return obj->classInfoCount(); } + + int indexOfConstructor(QMetaObject* obj, const char *constructor) const { return obj->indexOfConstructor(constructor); } + int indexOfMethod(QMetaObject* obj, const char *method) const { return obj->indexOfMethod(method); } + int indexOfSignal(QMetaObject* obj, const char *signal) const { return obj->indexOfSignal(signal); } + int indexOfSlot(QMetaObject* obj, const char *slot) const { return obj->indexOfSlot(slot); } + int indexOfEnumerator(QMetaObject* obj, const char *name) const { return obj->indexOfEnumerator(name); } + int indexOfProperty(QMetaObject* obj, const char *name) const { return obj->indexOfProperty(name); } + int indexOfClassInfo(QMetaObject* obj, const char *name) const { return obj->indexOfClassInfo(name); } + + QMetaMethod constructor(QMetaObject* obj, int index) const { return obj->constructor(index); } + QMetaMethod method(QMetaObject* obj, int index) const { return obj->method(index); } + QMetaEnum enumerator(QMetaObject* obj, int index) const { return obj->enumerator(index); } + QMetaProperty property(QMetaObject* obj, int index) const { return obj->property(index); } + QMetaClassInfo classInfo(QMetaObject* obj, int index) const { return obj->classInfo(index); } + QMetaProperty userProperty(QMetaObject* obj) const { return obj->userProperty(); } + + bool static_QMetaObject_checkConnectArgs(const char *signal, const char *method) { return QMetaObject::checkConnectArgs(signal, method); } + QByteArray static_QMetaObject_normalizedSignature(const char *method) { return QMetaObject::normalizedSignature(method); } + QByteArray static_QMetaObject_normalizedType(const char *type) { return QMetaObject::normalizedType(type); } + +}; #endif