Implemented staticMetaObject property for QObjects.

This commit is contained in:
Renato Filho 2011-07-06 15:39:48 -03:00
commit c9e2c1ad8a
4 changed files with 87 additions and 62 deletions

View file

@ -41,6 +41,7 @@
#include <cctype>
#include <QStack>
#include <QCoreApplication>
#include <QDebug>
static QStack<PySide::CleanupFunction> cleanupFunctionList;
@ -125,6 +126,7 @@ static void destructionVisitor(SbkObject* pyObj, void* data)
Py_END_ALLOW_THREADS
}
}
};
void destroyQCoreApplication()
@ -148,9 +150,15 @@ void destroyQCoreApplication()
void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base)
{
QByteArray typeName = QByteArray(type->super.ht_type.tp_name).split('.').last();
DynamicQMetaObject* mo = new PySide::DynamicQMetaObject(typeName, base);
Shiboken::ObjectType::setTypeUserData(type, mo, &Shiboken::callCppDestructor<DynamicQMetaObject>);
//create DynamicMetaObject based on python type
DynamicQMetaObject* mo = new PySide::DynamicQMetaObject(reinterpret_cast<PyTypeObject*>(type), base);
Shiboken::ObjectType::setTypeUserData(type, mo, Shiboken::callCppDestructor<DynamicQMetaObject>);
//initialize staticQMetaObject property
PyObject* pyMetaObject = Shiboken::TypeResolver::get("QMetaObject*")->toPython(&mo);
PyObject_SetAttrString(reinterpret_cast<PyObject*>(type), "staticMetaObject", pyMetaObject);
Py_DECREF(pyMetaObject);
}
void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds)
@ -166,10 +174,6 @@ void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds)
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;
}
}
@ -178,58 +182,7 @@ void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds)
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 (Property::checkType(value)) {
// Leave the properties to be register after signals because they may depend on notify signals
properties << PropPair(PyString_AS_STRING(key), value);
} else if (Signal::checkType(value)) { // 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);
initDynamicMetaObject(type, baseMo);
}
PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* name)