diff options
author | Hugo Parente Lima <hugo.pl@gmail.com> | 2010-12-03 17:04:37 -0200 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-08 16:47:56 -0300 |
commit | 8fb60373627f5d9978df2b9f38d0180f5897477a (patch) | |
tree | dbc18e59d3fc6e82a535bac4a5a82e72c47a38d5 /libpyside | |
parent | a29f511f6ded054550feea317f089ac77b6b4994 (diff) |
Set the object meta object at the declaration time, not instanciation time.
Diffstat (limited to 'libpyside')
-rw-r--r-- | libpyside/dynamicqmetaobject.cpp | 58 | ||||
-rw-r--r-- | libpyside/dynamicqmetaobject.h | 5 | ||||
-rw-r--r-- | libpyside/pyside.cpp | 91 | ||||
-rw-r--r-- | libpyside/pyside.h | 4 |
4 files changed, 96 insertions, 62 deletions
diff --git a/libpyside/dynamicqmetaobject.cpp b/libpyside/dynamicqmetaobject.cpp index 345493286..1f6ff85a0 100644 --- a/libpyside/dynamicqmetaobject.cpp +++ b/libpyside/dynamicqmetaobject.cpp @@ -386,64 +386,6 @@ void DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data) m_d->updateMetaObject(this); } - -DynamicQMetaObject* DynamicQMetaObject::createBasedOn(PyObject* pyObj, PyTypeObject* type, const QMetaObject* base) -{ - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - - QString className(type->tp_name); - className = className.mid(className.lastIndexOf('.')+1); - DynamicQMetaObject *mo = new PySide::DynamicQMetaObject(className.toAscii(), base); - - QList<PyObject*> properties; - - while (PyDict_Next(type->tp_dict, &pos, &key, &value)) { - - //Leave the properties to be register after signals because of notify object - if (value->ob_type == &PySidePropertyType) - properties.append(key); - - //Register signals - if (value->ob_type == &PySideSignalType) { - PyObject *attr = PyObject_GetAttr(pyObj, key); - PySideSignalInstance *data = reinterpret_cast<PySideSignalInstance*>(attr); - while(data) { - int index = base->indexOfSignal(data->d->signature); - if (index == -1) - mo->addSignal(data->d->signature); - data = reinterpret_cast<PySideSignalInstance*>(data->d->next); - } - } - - if (!PyFunction_Check(value)) - continue; - - //Register Slots - if (PyObject_HasAttrString(value, PYSIDE_SLOT_LIST_ATTR)) { - PyObject *signature_list = PyObject_GetAttrString(value, PYSIDE_SLOT_LIST_ATTR); - for(Py_ssize_t i = 0, i_max = PyList_Size(signature_list); i < i_max; i++) { - PyObject *signature = PyList_GET_ITEM(signature_list, i); - QString sig(PyString_AsString(signature)); - //slot the slot type and signature - QStringList slotInfo = sig.split(" ", QString::SkipEmptyParts); - int index = base->indexOfSlot(qPrintable(slotInfo[1])); - if (index == -1) - mo->addSlot(slotInfo[1].toAscii(), slotInfo[0].toAscii()); - } - } - } - - //Register properties - foreach(PyObject* key, properties) { - PyObject* value = PyDict_GetItem(type->tp_dict, key); - mo->addProperty(PyString_AsString(key), value); - } - - return mo; -} - void DynamicQMetaObject::removeSignal(uint index) { //Current Qt implementation does not support runtime remove signal diff --git a/libpyside/dynamicqmetaobject.h b/libpyside/dynamicqmetaobject.h index 8bd02824d..7f64a6cf9 100644 --- a/libpyside/dynamicqmetaobject.h +++ b/libpyside/dynamicqmetaobject.h @@ -30,7 +30,7 @@ namespace PySide { -class PYSIDE_API DynamicQMetaObject : public QMetaObject +class DynamicQMetaObject : public QMetaObject { public: DynamicQMetaObject(const char* className, const QMetaObject* metaObject); @@ -44,9 +44,6 @@ public: void removeSlot(uint index); void removeProperty(uint index); - //Retrieve Python metadata to create QMetaObject (class name, signals, slot) - static DynamicQMetaObject* createBasedOn(PyObject* obj, PyTypeObject* type, const QMetaObject* base); - private: class DynamicQMetaObjectPrivate; DynamicQMetaObjectPrivate* m_d; diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp index 81e5d6501..79b4f4caa 100644 --- a/libpyside/pyside.cpp +++ b/libpyside/pyside.cpp @@ -28,6 +28,7 @@ #include "pysidesignal_p.h" #include "pysideslot_p.h" #include "pysidemetafunction_p.h" +#include "dynamicqmetaobject.h" #include <basewrapper.h> #include <conversions.h> @@ -134,5 +135,95 @@ void destroyQCoreApplication() delete app; } +void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base) +{ + const char* typeName = type->super.ht_type.tp_name; + int len = strlen(typeName); + for (int i = len-1; i >= 0; --i) + if (typeName[i] == '.') + typeName += i + 1; + DynamicQMetaObject* mo = new PySide::DynamicQMetaObject(typeName, base); + Shiboken::ObjectType::setTypeUserData(type, mo, &Shiboken::callCppDestructor<DynamicQMetaObject>); +} + +void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds) +{ + PyTypeObject* qObjType = Shiboken::TypeResolver::get("QObject*")->pythonType(); + QByteArray className(PyString_AS_STRING(PyTuple_GET_ITEM(args, 0))); + + PyObject* bases = PyTuple_GET_ITEM(args, 1); + int numBases = PyTuple_GET_SIZE(args); + QMetaObject* baseMo = 0; + + for (int i = 0; i < numBases; ++i) { + PyTypeObject* base = reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(bases, i)); + if (PyType_IsSubtype(base, qObjType)) { + baseMo = reinterpret_cast<QMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(base))); + // If it's a class like QObject, QWidget, etc, use the original QMetaObject instead of the dynamic one + // IMO this if is a bug, however it keeps the current behaviour. + if (!Shiboken::ObjectType::isUserType(base)) + baseMo = const_cast<QMetaObject*>(baseMo->d.superdata); + break; + } + } + if (!baseMo) { + qWarning("Sub class of QObject not inheriting QObject!? Crash will happen when using %s.", className.constData()); + return; + } + + DynamicQMetaObject* mo = new PySide::DynamicQMetaObject(className.constData(), baseMo); + + Shiboken::ObjectType::setTypeUserData(type, mo, &Shiboken::callCppDestructor<DynamicQMetaObject>); + + PyObject* attrs = PyTuple_GET_ITEM(args, 2); + PyObject* key; + PyObject* value; + Py_ssize_t pos = 0; + + typedef std::pair<const char*, PyObject*> PropPair; + QList<PropPair> properties; + + Shiboken::AutoDecRef slotAttrName(PyString_FromString(PYSIDE_SLOT_LIST_ATTR)); + + while (PyDict_Next(attrs, &pos, &key, &value)) { + if (value->ob_type == &PySidePropertyType) { + // Leave the properties to be register after signals because they may depend on notify signals + properties << PropPair(PyString_AS_STRING(key), value); + } else if (value->ob_type == &PySideSignalType) { // Register signals + PySideSignal* data = reinterpret_cast<PySideSignal*>(value); + const char* signalName = PyString_AS_STRING(key); + data->signalName = strdup(signalName); + QByteArray sig; + sig.reserve(128); + for (int i = 0; i < data->signaturesSize; ++i) { + sig = signalName; + sig += '('; + if (data->signatures[i]) + sig += data->signatures[i]; + sig += ')'; + if (baseMo->indexOfSignal(sig) == -1) + mo->addSignal(sig); + } + } else if (PyFunction_Check(value)) { // Register slots + if (PyObject_HasAttr(value, slotAttrName)) { + PyObject* signatureList = PyObject_GetAttr(value, slotAttrName); + for(Py_ssize_t i = 0, i_max = PyList_Size(signatureList); i < i_max; ++i) { + PyObject* signature = PyList_GET_ITEM(signatureList, i); + QByteArray sig(PyString_AS_STRING(signature)); + //slot the slot type and signature + QList<QByteArray> slotInfo = sig.split(' '); + int index = baseMo->indexOfSlot(slotInfo[1]); + if (index == -1) + mo->addSlot(slotInfo[1], slotInfo[0]); + } + } + } + } + + // Register properties + foreach (PropPair propPair, properties) + mo->addProperty(propPair.first, propPair.second); +} + } //namespace PySide diff --git a/libpyside/pyside.h b/libpyside/pyside.h index fe9ce3a6e..d84040d55 100644 --- a/libpyside/pyside.h +++ b/libpyside/pyside.h @@ -29,6 +29,8 @@ #include <QHash> #include <QList> +class SbkObjectType; + namespace PySide { @@ -75,6 +77,8 @@ template<typename T> struct initQtMetaType<T, false> { }; +PYSIDE_API void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base); +PYSIDE_API void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds); typedef void (*CleanupFunction)(void); |