aboutsummaryrefslogtreecommitdiffstats
path: root/libpyside
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2010-12-03 17:04:37 -0200
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:47:56 -0300
commit8fb60373627f5d9978df2b9f38d0180f5897477a (patch)
treedbc18e59d3fc6e82a535bac4a5a82e72c47a38d5 /libpyside
parenta29f511f6ded054550feea317f089ac77b6b4994 (diff)
Set the object meta object at the declaration time, not instanciation time.
Diffstat (limited to 'libpyside')
-rw-r--r--libpyside/dynamicqmetaobject.cpp58
-rw-r--r--libpyside/dynamicqmetaobject.h5
-rw-r--r--libpyside/pyside.cpp91
-rw-r--r--libpyside/pyside.h4
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);