aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Filho <renato.filho@openbossa.org>2011-07-21 17:57:17 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:54:38 -0300
commitec45601aa14400b3d3e13f3f326e57d534da6ad2 (patch)
tree6ebaa966bc6518e85408a1807e5741690622f87a
parent9dd8f98e736dc70ae4f1a78f13ee643a63aa2e47 (diff)
Implemented DynamicMetaObject optiomizations.
Reviewer: Luciano Wolf <luciano.wolf@openbossa.org> Lauro Neto <lauro.neto@openbossa.org>
-rw-r--r--PySide/QtCore/glue/qobject_connect.cpp20
-rw-r--r--libpyside/dynamicqmetaobject.cpp72
-rw-r--r--libpyside/dynamicqmetaobject.h11
-rw-r--r--libpyside/globalreceiver.cpp13
-rw-r--r--libpyside/globalreceiver.h2
-rw-r--r--libpyside/pyside.cpp4
-rw-r--r--libpyside/signalmanager.cpp68
-rw-r--r--libpyside/signalmanager.h5
8 files changed, 144 insertions, 51 deletions
diff --git a/PySide/QtCore/glue/qobject_connect.cpp b/PySide/QtCore/glue/qobject_connect.cpp
index 91a272c3c..3296c2e89 100644
--- a/PySide/QtCore/glue/qobject_connect.cpp
+++ b/PySide/QtCore/glue/qobject_connect.cpp
@@ -59,11 +59,10 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject
return false;
signal++;
- if (!PySide::SignalManager::registerMetaMethod(source, signal, QMetaMethod::Signal))
+ int signalIndex = PySide::SignalManager::registerMetaMethodGetIndex(source, signal, QMetaMethod::Signal);
+ if (signalIndex == -1)
return false;
- int signalIndex = source->metaObject()->indexOfMethod(signal);
-
PySide::SignalManager& signalManager = PySide::SignalManager::instance();
// Extract receiver from callback
@@ -82,13 +81,14 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject
qWarning() << "You can't add dynamic slots on an object originated from C++.";
return false;
}
- if (usingGlobalReceiver) {
- signalManager.addGlobalSlot(slot, callback);
- } else {
- if (!PySide::SignalManager::registerMetaMethod(receiver, slot, QMetaMethod::Slot))
- return false;
- }
- slotIndex = metaObject->indexOfSlot(slot);
+
+ if (usingGlobalReceiver)
+ slotIndex = signalManager.addGlobalSlotGetIndex(slot, callback);
+ else
+ slotIndex = PySide::SignalManager::registerMetaMethodGetIndex(receiver, slot, QMetaMethod::Slot);
+
+ if (slotIndex == -1)
+ return false;
}
if (QMetaObject::connect(source, signalIndex, receiver, slotIndex, type)) {
if (usingGlobalReceiver)
diff --git a/libpyside/dynamicqmetaobject.cpp b/libpyside/dynamicqmetaobject.cpp
index 205c7286e..dfc8ce281 100644
--- a/libpyside/dynamicqmetaobject.cpp
+++ b/libpyside/dynamicqmetaobject.cpp
@@ -87,6 +87,10 @@ public:
QList<PropertyData> m_properties;
QMap<QByteArray, QByteArray> m_info;
QByteArray m_className;
+ bool m_invalid;
+ int m_methodOffset;
+ int m_propertyOffset;
+ int m_count;
void updateMetaObject(QMetaObject* metaObj);
void writeMethodsData(const QList<MethodData>& methods, unsigned int** data, QList<QByteArray>* strings, int* prtIndex, int nullIndex, int flags);
@@ -95,8 +99,7 @@ public:
static int registerString(const QByteArray& s, QList<QByteArray>* strings)
{
int idx = 0;
- for (int i = 0; i < strings->count(); ++i) {
- const QString &str = strings->at(i);
+ foreach(QByteArray str, *strings) {
if (str == s)
return idx;
idx += str.length() + 1;
@@ -197,11 +200,13 @@ uint PropertyData::flags() const
// const QByteArray with EMPTY_META_METHOD, used to save some memory
const QByteArray MethodData::m_emptySig(EMPTY_META_METHOD);
-MethodData::MethodData() : m_signature(m_emptySig)
+MethodData::MethodData()
+ : m_signature(m_emptySig)
{
}
-MethodData::MethodData(QMetaMethod::MethodType mtype, const char* signature, const char* type) : m_signature(signature), m_type(type), m_mtype(mtype)
+MethodData::MethodData(QMetaMethod::MethodType mtype, const char* signature, const char* type)
+ : m_signature(signature), m_type(type), m_mtype(mtype)
{
}
@@ -289,9 +294,12 @@ DynamicQMetaObject::DynamicQMetaObject(PyTypeObject* type, const QMetaObject* ba
d.extradata = 0;
m_d->m_className = QByteArray(type->tp_name).split('.').last();
+ m_d->m_invalid = true;
+ m_d->m_methodOffset = base->methodCount() - 1;
+ m_d->m_propertyOffset = base->propertyCount() - 1;
+ m_d->m_count = 0;
+ //qDebug() << "CREATED: " << m_d->m_className << "OFFSET:" << base->methodOffset() << "COUNT" << base->methodCount();
parsePythonType(type);
- //TODO : fill type userData
- m_d->updateMetaObject(this);
}
DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject* metaObject)
@@ -301,8 +309,11 @@ DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject*
d.stringdata = 0;
d.data = 0;
d.extradata = 0;
+ m_d->m_count = 0;
+ m_d->m_invalid = true;
m_d->m_className = className;
- m_d->updateMetaObject(this);
+ m_d->m_methodOffset = metaObject->methodCount() - 1;
+ m_d->m_propertyOffset = metaObject->propertyCount() - 1;
}
DynamicQMetaObject::~DynamicQMetaObject()
@@ -312,7 +323,7 @@ DynamicQMetaObject::~DynamicQMetaObject()
delete m_d;
}
-void DynamicQMetaObject::addMethod(QMetaMethod::MethodType mtype, const char* signature, const char* type)
+int DynamicQMetaObject::addMethod(QMetaMethod::MethodType mtype, const char* signature, const char* type)
{
int index = -1;
int counter = 0;
@@ -321,19 +332,24 @@ void DynamicQMetaObject::addMethod(QMetaMethod::MethodType mtype, const char* si
QList<MethodData>::iterator it = m_d->m_methods.begin();
for (; it != m_d->m_methods.end(); ++it) {
if ((it->signature() == signature) && (it->methodType() == mtype))
- return;
+ return m_d->m_methodOffset + counter;
else if (*it == blank)
index = counter;
counter++;
}
+ //qDebug() << "FIRST:" << index;
//has blank method
- if (index != -1)
+ if (index != -1) {
m_d->m_methods[index] = MethodData(mtype, signature, type);
- else
+ } else {
m_d->m_methods << MethodData(mtype, signature, type);
+ index = m_d->m_methods.size();
+ }
- m_d->updateMetaObject(this);
+ m_d->m_invalid = true;
+ return m_d->m_methodOffset + index;
+ //qDebug() << "RESULTS(" << signature << "): " << result << "/" << indexOfMethod(signature) << "/" << m_d->m_methods.size() << "/" << m_d->m_methodOffset << (void*)this;
}
void DynamicQMetaObject::removeMethod(QMetaMethod::MethodType mtype, uint index)
@@ -343,20 +359,20 @@ void DynamicQMetaObject::removeMethod(QMetaMethod::MethodType mtype, uint index)
for (; it != m_d->m_methods.end(); ++it) {
if ((it->signature() == methodSig) && (it->methodType() == mtype)){
it->clear();
- m_d->updateMetaObject(this);
+ m_d->m_invalid = true;
break;
}
}
}
-void DynamicQMetaObject::addSignal(const char* signal, const char* type)
+int DynamicQMetaObject::addSignal(const char* signal, const char* type)
{
- addMethod(QMetaMethod::Signal, signal, type);
+ return addMethod(QMetaMethod::Signal, signal, type);
}
-void DynamicQMetaObject::addSlot(const char* slot, const char* type)
+int DynamicQMetaObject::addSlot(const char* slot, const char* type)
{
- addMethod(QMetaMethod::Slot, slot, type);
+ return addMethod(QMetaMethod::Slot, slot, type);
}
void DynamicQMetaObject::removeSlot(uint index)
@@ -369,11 +385,11 @@ void DynamicQMetaObject::removeSignal(uint index)
removeMethod(QMetaMethod::Signal, index);
}
-void DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data)
+int DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data)
{
int index = m_d->m_properties.indexOf(propertyName);
if (index != -1)
- return;
+ return m_d->m_propertyOffset + index;
// retrieve notifyId
int notifyId = -1;
@@ -393,8 +409,10 @@ void DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data)
m_d->m_properties[index] = PropertyData(propertyName, notifyId, property);
} else {
m_d->m_properties << PropertyData(propertyName, notifyId, property);
+ index = m_d->m_properties.size();
}
- m_d->updateMetaObject(this);
+ m_d->m_invalid = true;
+ return m_d->m_propertyOffset + index;
}
void DynamicQMetaObject::addInfo(const char* key, const char* value)
@@ -409,7 +427,16 @@ void DynamicQMetaObject::addInfo(QMap<QByteArray, QByteArray> info)
m_d->m_info[i.key()] = i.value();
++i;
}
- m_d->updateMetaObject(this);
+ m_d->m_invalid = true;
+}
+
+const QMetaObject* DynamicQMetaObject::update() const
+{
+ if (m_d->m_invalid) {
+ m_d->updateMetaObject(const_cast<DynamicQMetaObject*>(this));
+ m_d->m_invalid = false;
+ }
+ return this;
}
void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(const QList<MethodData>& methods,
@@ -530,7 +557,8 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject
}
//write signals/slots
- writeMethodsData(m_methods, &data, &strings, &index, NULL_INDEX, AccessPublic);
+ if (n_methods)
+ writeMethodsData(m_methods, &data, &strings, &index, NULL_INDEX, AccessPublic);
if (m_properties.size())
data[7] = index;
diff --git a/libpyside/dynamicqmetaobject.h b/libpyside/dynamicqmetaobject.h
index f95070c28..3ebaf1d08 100644
--- a/libpyside/dynamicqmetaobject.h
+++ b/libpyside/dynamicqmetaobject.h
@@ -39,11 +39,11 @@ public:
~DynamicQMetaObject();
- void addMethod(QMetaMethod::MethodType mtype, const char* signature, const char* type);
+ int addMethod(QMetaMethod::MethodType mtype, const char* signature, const char* type);
void removeMethod(QMetaMethod::MethodType mtype, uint index);
- void addSignal(const char* signal, const char* type = 0);
- void addSlot(const char* slot, const char* type = 0);
- void addProperty(const char* property, PyObject* data);
+ int addSignal(const char* signal, const char* type = 0);
+ int addSlot(const char* slot, const char* type = 0);
+ int addProperty(const char* property, PyObject* data);
void addInfo(const char* key, const char* value);
void addInfo(QMap<QByteArray, QByteArray> info);
@@ -51,6 +51,8 @@ public:
void removeSlot(uint index);
void removeProperty(uint index);
+ const QMetaObject* update() const;
+
private:
class DynamicQMetaObjectPrivate;
DynamicQMetaObjectPrivate* m_d;
@@ -58,5 +60,6 @@ private:
void parsePythonType(PyTypeObject* type);
};
+
}
#endif
diff --git a/libpyside/globalreceiver.cpp b/libpyside/globalreceiver.cpp
index 89902126c..435e22aa0 100644
--- a/libpyside/globalreceiver.cpp
+++ b/libpyside/globalreceiver.cpp
@@ -162,6 +162,8 @@ GlobalReceiver::GlobalReceiver()
{
//slot used to be notifyed of object destrouction
m_metaObject.addSlot(RECEIVER_DESTROYED_SLOT_NAME);
+ m_metaObject.update();
+ setObjectName("GLOBAL RECEIVER");
}
GlobalReceiver::~GlobalReceiver()
@@ -198,13 +200,12 @@ void GlobalReceiver::disconnectNotify(QObject* source, int slotId)
const QMetaObject* GlobalReceiver::metaObject() const
{
- return &m_metaObject;
+ return m_metaObject.update();
}
-void GlobalReceiver::addSlot(const char* slot, PyObject* callback)
+int GlobalReceiver::addSlot(const char* slot, PyObject* callback)
{
- m_metaObject.addSlot(slot);
- int slotId = m_metaObject.indexOfSlot(slot);
+ int slotId = m_metaObject.addSlot(slot);
if (!m_slotReceivers.contains(slotId))
m_slotReceivers[slotId] = new DynamicSlotData(slotId, callback, this);
@@ -219,8 +220,8 @@ void GlobalReceiver::addSlot(const char* slot, PyObject* callback)
if (isShortCircuit)
m_shortCircuitSlots << slotId;
-
Q_ASSERT(slotId >= QObject::staticMetaObject.methodCount());
+ return slotId;
}
void GlobalReceiver::removeSlot(int slotId)
@@ -248,7 +249,7 @@ int GlobalReceiver::qt_metacall(QMetaObject::Call call, int id, void** args)
{
Q_ASSERT(call == QMetaObject::InvokeMetaMethod);
Q_ASSERT(id >= QObject::staticMetaObject.methodCount());
- QMetaMethod slot = m_metaObject.method(id);
+ QMetaMethod slot = metaObject()->method(id);
Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
if (strcmp(slot.signature(), RECEIVER_DESTROYED_SLOT_NAME) == 0) {
diff --git a/libpyside/globalreceiver.h b/libpyside/globalreceiver.h
index 616d8d3a4..76c1246d6 100644
--- a/libpyside/globalreceiver.h
+++ b/libpyside/globalreceiver.h
@@ -41,7 +41,7 @@ public:
~GlobalReceiver();
int qt_metacall(QMetaObject::Call call, int id, void** args);
const QMetaObject* metaObject() const;
- void addSlot(const char* slot, PyObject* callback);
+ int addSlot(const char* slot, PyObject* callback);
void removeSlot(int slotId);
void connectNotify(QObject* sender, int slotId);
void disconnectNotify(QObject* sender, int slotId);
diff --git a/libpyside/pyside.cpp b/libpyside/pyside.cpp
index 325e27402..45ada8f47 100644
--- a/libpyside/pyside.cpp
+++ b/libpyside/pyside.cpp
@@ -168,6 +168,7 @@ void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base, const s
//create DynamicMetaObject based on python type
TypeUserData* userData = new TypeUserData(reinterpret_cast<PyTypeObject*>(type), base);
userData->cppObjSize = cppObjSize;
+ userData->mo.update();
Shiboken::ObjectType::setTypeUserData(type, userData, Shiboken::callCppDestructor<TypeUserData>);
//initialize staticQMetaObject property
@@ -196,6 +197,7 @@ void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds)
if (PyType_IsSubtype(base, qObjType)) {
baseMo = reinterpret_cast<QMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(base)));
qobjBase = reinterpret_cast<SbkObjectType*>(base);
+ reinterpret_cast<DynamicQMetaObject*>(baseMo)->update();
break;
}
}
@@ -216,9 +218,9 @@ PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* nam
if (attr && Property::isPropertyType(attr)) {
PyObject *value = Property::getValue(reinterpret_cast<PySideProperty*>(attr), self);
+ Py_DECREF(attr);
if (!value)
return 0;
- Py_DECREF(attr);
Py_INCREF(value);
attr = value;
}
diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp
index bbbc1d3f0..b24d0b97e 100644
--- a/libpyside/signalmanager.cpp
+++ b/libpyside/signalmanager.cpp
@@ -25,6 +25,7 @@
#include "pysideproperty.h"
#include "pysideproperty_p.h"
#include "pyside.h"
+#include "dynamicqmetaobject.h"
#include <QHash>
#include <QStringList>
@@ -46,6 +47,14 @@
#define PYTHON_TYPE "PyObject"
+namespace {
+ static PyObject *metaObjectAttr = 0;
+ static void destroyMetaObject(void* obj)
+ {
+ delete reinterpret_cast<PySide::DynamicQMetaObject*>(obj);
+ }
+}
+
namespace PySide {
static int callMethod(QObject* object, int id, void** args);
@@ -189,6 +198,9 @@ SignalManager::SignalManager() : m_d(new SignalManagerPrivate)
TypeResolver::createValueTypeResolver<PyObjectWrapper>("object");
TypeResolver::createValueTypeResolver<PyObjectWrapper>("PySide::PyObjectWrapper");
PySide::registerCleanupFunction(clearSignalManager);
+
+ if (!metaObjectAttr)
+ metaObjectAttr = PyString_FromString("__METAOBJECT__");
}
void SignalManager::clear()
@@ -225,7 +237,12 @@ void SignalManager::globalReceiverDisconnectNotify(QObject* source, int slotInde
void SignalManager::addGlobalSlot(const char* slot, PyObject* callback)
{
- m_d->m_globalReceiver.addSlot(slot, callback);
+ addGlobalSlotGetIndex(slot, callback);
+}
+
+int SignalManager::addGlobalSlotGetIndex(const char* slot, PyObject* callback)
+{
+ return m_d->m_globalReceiver.addSlot(slot, callback);
}
static bool emitShortCircuitSignal(QObject* source, int signalIndex, PyObject* args)
@@ -412,9 +429,14 @@ static int PySide::callMethod(QObject* object, int id, void** args)
}
return -1;
}
-
bool SignalManager::registerMetaMethod(QObject* source, const char* signature, QMetaMethod::MethodType type)
{
+ int ret = registerMetaMethodGetIndex(source, signature, type);
+ return (ret != -1);
+}
+
+int SignalManager::registerMetaMethodGetIndex(QObject* source, const char* signature, QMetaMethod::MethodType type)
+{
Q_ASSERT(source);
const QMetaObject* metaObject = source->metaObject();
int methodIndex = metaObject->indexOfMethod(signature);
@@ -423,19 +445,51 @@ bool SignalManager::registerMetaMethod(QObject* source, const char* signature, Q
SbkObject* self = Shiboken::BindingManager::instance().retrieveWrapper(source);
if (!Shiboken::Object::hasCppWrapper(self)) {
qWarning() << "Invalid Signal signature:" << signature;
- return false;
+ return -1;
} else {
- PySide::DynamicQMetaObject* dynMetaObj = reinterpret_cast<PySide::DynamicQMetaObject*>(const_cast<QMetaObject*>(metaObject));
+ DynamicQMetaObject *dmo = 0;
+ PyObject *pySelf = reinterpret_cast<PyObject*>(self);
+ PyObject* dict = self->ob_dict;
+
+ // Create a instance meta object
+ if (!dict || !PyDict_Contains(dict, metaObjectAttr)) {
+ dmo = new DynamicQMetaObject(pySelf->ob_type, metaObject);
+ PyObject *pyDmo = PyCObject_FromVoidPtr(dmo, destroyMetaObject);
+ PyObject_SetAttr(pySelf, metaObjectAttr, pyDmo);
+ Py_DECREF(pyDmo);
+ } else {
+ dmo = reinterpret_cast<DynamicQMetaObject*>(const_cast<QMetaObject*>(metaObject));
+ }
+
if (type == QMetaMethod::Signal)
- dynMetaObj->addSignal(signature);
+ return dmo->addSignal(signature);
else
- dynMetaObj->addSlot(signature);
+ return dmo->addSlot(signature);
}
}
- return true;
+ return methodIndex;
}
bool SignalManager::hasConnectionWith(const QObject *object)
{
return m_d->m_globalReceiver.hasConnectionWith(object);
}
+
+const QMetaObject* SignalManager::retriveMetaObject(PyObject *self)
+{
+ Shiboken::GilState gil;
+ DynamicQMetaObject *mo = 0;
+ Q_ASSERT(self);
+
+ PyObject* dict = reinterpret_cast<SbkObject*>(self)->ob_dict;
+ if (dict && PyDict_Contains(dict, metaObjectAttr)) {
+ PyObject *pyMo = PyDict_GetItem(dict, metaObjectAttr);
+ mo = reinterpret_cast<DynamicQMetaObject*>(PyCObject_AsVoidPtr(pyMo));
+ } else {
+ mo = reinterpret_cast<DynamicQMetaObject*>(Shiboken::Object::getTypeUserData(reinterpret_cast<SbkObject*>(self)));
+ }
+
+ mo->update();
+ return mo;
+}
+
diff --git a/libpyside/signalmanager.h b/libpyside/signalmanager.h
index 5ea1366f0..b1b798600 100644
--- a/libpyside/signalmanager.h
+++ b/libpyside/signalmanager.h
@@ -62,12 +62,17 @@ public:
static int qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args);
void addGlobalSlot(const char* slot, PyObject* callback);
+ int addGlobalSlotGetIndex(const char* slot, PyObject* callback);
void globalReceiverConnectNotify(QObject *sender, int slotIndex);
void globalReceiverDisconnectNotify(QObject *sender, int slotIndex);
// Used to register a new signal/slot on QMetaobject of source.
static bool registerMetaMethod(QObject* source, const char* signature, QMetaMethod::MethodType type);
+ static int registerMetaMethodGetIndex(QObject* source, const char* signature, QMetaMethod::MethodType type);
+
+ // used to discovery metaobject
+ static const QMetaObject* retriveMetaObject(PyObject* self);
// Used to discovery if SignalManager was connected with object "destroyed()" signal.
bool hasConnectionWith(const QObject *object);