Implemented DynamicMetaObject optiomizations.
Reviewer: Luciano Wolf <luciano.wolf@openbossa.org>
Lauro Neto <lauro.neto@openbossa.org>
This commit is contained in:
parent
9dd8f98e73
commit
ec45601aa1
8 changed files with 144 additions and 51 deletions
|
|
@ -59,11 +59,10 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject
|
||||||
return false;
|
return false;
|
||||||
signal++;
|
signal++;
|
||||||
|
|
||||||
if (!PySide::SignalManager::registerMetaMethod(source, signal, QMetaMethod::Signal))
|
int signalIndex = PySide::SignalManager::registerMetaMethodGetIndex(source, signal, QMetaMethod::Signal);
|
||||||
|
if (signalIndex == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int signalIndex = source->metaObject()->indexOfMethod(signal);
|
|
||||||
|
|
||||||
PySide::SignalManager& signalManager = PySide::SignalManager::instance();
|
PySide::SignalManager& signalManager = PySide::SignalManager::instance();
|
||||||
|
|
||||||
// Extract receiver from callback
|
// 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++.";
|
qWarning() << "You can't add dynamic slots on an object originated from C++.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (usingGlobalReceiver) {
|
|
||||||
signalManager.addGlobalSlot(slot, callback);
|
if (usingGlobalReceiver)
|
||||||
} else {
|
slotIndex = signalManager.addGlobalSlotGetIndex(slot, callback);
|
||||||
if (!PySide::SignalManager::registerMetaMethod(receiver, slot, QMetaMethod::Slot))
|
else
|
||||||
return false;
|
slotIndex = PySide::SignalManager::registerMetaMethodGetIndex(receiver, slot, QMetaMethod::Slot);
|
||||||
}
|
|
||||||
slotIndex = metaObject->indexOfSlot(slot);
|
if (slotIndex == -1)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (QMetaObject::connect(source, signalIndex, receiver, slotIndex, type)) {
|
if (QMetaObject::connect(source, signalIndex, receiver, slotIndex, type)) {
|
||||||
if (usingGlobalReceiver)
|
if (usingGlobalReceiver)
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,10 @@ public:
|
||||||
QList<PropertyData> m_properties;
|
QList<PropertyData> m_properties;
|
||||||
QMap<QByteArray, QByteArray> m_info;
|
QMap<QByteArray, QByteArray> m_info;
|
||||||
QByteArray m_className;
|
QByteArray m_className;
|
||||||
|
bool m_invalid;
|
||||||
|
int m_methodOffset;
|
||||||
|
int m_propertyOffset;
|
||||||
|
int m_count;
|
||||||
|
|
||||||
void updateMetaObject(QMetaObject* metaObj);
|
void updateMetaObject(QMetaObject* metaObj);
|
||||||
void writeMethodsData(const QList<MethodData>& methods, unsigned int** data, QList<QByteArray>* strings, int* prtIndex, int nullIndex, int flags);
|
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)
|
static int registerString(const QByteArray& s, QList<QByteArray>* strings)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (int i = 0; i < strings->count(); ++i) {
|
foreach(QByteArray str, *strings) {
|
||||||
const QString &str = strings->at(i);
|
|
||||||
if (str == s)
|
if (str == s)
|
||||||
return idx;
|
return idx;
|
||||||
idx += str.length() + 1;
|
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 with EMPTY_META_METHOD, used to save some memory
|
||||||
const QByteArray MethodData::m_emptySig(EMPTY_META_METHOD);
|
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;
|
d.extradata = 0;
|
||||||
|
|
||||||
m_d->m_className = QByteArray(type->tp_name).split('.').last();
|
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);
|
parsePythonType(type);
|
||||||
//TODO : fill type userData
|
|
||||||
m_d->updateMetaObject(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject* metaObject)
|
DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject* metaObject)
|
||||||
|
|
@ -301,8 +309,11 @@ DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject*
|
||||||
d.stringdata = 0;
|
d.stringdata = 0;
|
||||||
d.data = 0;
|
d.data = 0;
|
||||||
d.extradata = 0;
|
d.extradata = 0;
|
||||||
|
m_d->m_count = 0;
|
||||||
|
m_d->m_invalid = true;
|
||||||
m_d->m_className = className;
|
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()
|
DynamicQMetaObject::~DynamicQMetaObject()
|
||||||
|
|
@ -312,7 +323,7 @@ DynamicQMetaObject::~DynamicQMetaObject()
|
||||||
delete m_d;
|
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 index = -1;
|
||||||
int counter = 0;
|
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();
|
QList<MethodData>::iterator it = m_d->m_methods.begin();
|
||||||
for (; it != m_d->m_methods.end(); ++it) {
|
for (; it != m_d->m_methods.end(); ++it) {
|
||||||
if ((it->signature() == signature) && (it->methodType() == mtype))
|
if ((it->signature() == signature) && (it->methodType() == mtype))
|
||||||
return;
|
return m_d->m_methodOffset + counter;
|
||||||
else if (*it == blank)
|
else if (*it == blank)
|
||||||
index = counter;
|
index = counter;
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//qDebug() << "FIRST:" << index;
|
||||||
//has blank method
|
//has blank method
|
||||||
if (index != -1)
|
if (index != -1) {
|
||||||
m_d->m_methods[index] = MethodData(mtype, signature, type);
|
m_d->m_methods[index] = MethodData(mtype, signature, type);
|
||||||
else
|
} else {
|
||||||
m_d->m_methods << MethodData(mtype, signature, type);
|
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)
|
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) {
|
for (; it != m_d->m_methods.end(); ++it) {
|
||||||
if ((it->signature() == methodSig) && (it->methodType() == mtype)){
|
if ((it->signature() == methodSig) && (it->methodType() == mtype)){
|
||||||
it->clear();
|
it->clear();
|
||||||
m_d->updateMetaObject(this);
|
m_d->m_invalid = true;
|
||||||
break;
|
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)
|
void DynamicQMetaObject::removeSlot(uint index)
|
||||||
|
|
@ -369,11 +385,11 @@ void DynamicQMetaObject::removeSignal(uint index)
|
||||||
removeMethod(QMetaMethod::Signal, 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);
|
int index = m_d->m_properties.indexOf(propertyName);
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
return;
|
return m_d->m_propertyOffset + index;
|
||||||
|
|
||||||
// retrieve notifyId
|
// retrieve notifyId
|
||||||
int notifyId = -1;
|
int notifyId = -1;
|
||||||
|
|
@ -393,8 +409,10 @@ void DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data)
|
||||||
m_d->m_properties[index] = PropertyData(propertyName, notifyId, property);
|
m_d->m_properties[index] = PropertyData(propertyName, notifyId, property);
|
||||||
} else {
|
} else {
|
||||||
m_d->m_properties << PropertyData(propertyName, notifyId, property);
|
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)
|
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();
|
m_d->m_info[i.key()] = i.value();
|
||||||
++i;
|
++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,
|
void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(const QList<MethodData>& methods,
|
||||||
|
|
@ -530,7 +557,8 @@ void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject
|
||||||
}
|
}
|
||||||
|
|
||||||
//write signals/slots
|
//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())
|
if (m_properties.size())
|
||||||
data[7] = index;
|
data[7] = index;
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,11 @@ public:
|
||||||
~DynamicQMetaObject();
|
~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 removeMethod(QMetaMethod::MethodType mtype, uint index);
|
||||||
void addSignal(const char* signal, const char* type = 0);
|
int addSignal(const char* signal, const char* type = 0);
|
||||||
void addSlot(const char* slot, const char* type = 0);
|
int addSlot(const char* slot, const char* type = 0);
|
||||||
void addProperty(const char* property, PyObject* data);
|
int addProperty(const char* property, PyObject* data);
|
||||||
void addInfo(const char* key, const char* value);
|
void addInfo(const char* key, const char* value);
|
||||||
void addInfo(QMap<QByteArray, QByteArray> info);
|
void addInfo(QMap<QByteArray, QByteArray> info);
|
||||||
|
|
||||||
|
|
@ -51,6 +51,8 @@ public:
|
||||||
void removeSlot(uint index);
|
void removeSlot(uint index);
|
||||||
void removeProperty(uint index);
|
void removeProperty(uint index);
|
||||||
|
|
||||||
|
const QMetaObject* update() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class DynamicQMetaObjectPrivate;
|
class DynamicQMetaObjectPrivate;
|
||||||
DynamicQMetaObjectPrivate* m_d;
|
DynamicQMetaObjectPrivate* m_d;
|
||||||
|
|
@ -58,5 +60,6 @@ private:
|
||||||
void parsePythonType(PyTypeObject* type);
|
void parsePythonType(PyTypeObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,8 @@ GlobalReceiver::GlobalReceiver()
|
||||||
{
|
{
|
||||||
//slot used to be notifyed of object destrouction
|
//slot used to be notifyed of object destrouction
|
||||||
m_metaObject.addSlot(RECEIVER_DESTROYED_SLOT_NAME);
|
m_metaObject.addSlot(RECEIVER_DESTROYED_SLOT_NAME);
|
||||||
|
m_metaObject.update();
|
||||||
|
setObjectName("GLOBAL RECEIVER");
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalReceiver::~GlobalReceiver()
|
GlobalReceiver::~GlobalReceiver()
|
||||||
|
|
@ -198,13 +200,12 @@ void GlobalReceiver::disconnectNotify(QObject* source, int slotId)
|
||||||
|
|
||||||
const QMetaObject* GlobalReceiver::metaObject() const
|
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.addSlot(slot);
|
||||||
int slotId = m_metaObject.indexOfSlot(slot);
|
|
||||||
if (!m_slotReceivers.contains(slotId))
|
if (!m_slotReceivers.contains(slotId))
|
||||||
m_slotReceivers[slotId] = new DynamicSlotData(slotId, callback, this);
|
m_slotReceivers[slotId] = new DynamicSlotData(slotId, callback, this);
|
||||||
|
|
||||||
|
|
@ -219,8 +220,8 @@ void GlobalReceiver::addSlot(const char* slot, PyObject* callback)
|
||||||
if (isShortCircuit)
|
if (isShortCircuit)
|
||||||
m_shortCircuitSlots << slotId;
|
m_shortCircuitSlots << slotId;
|
||||||
|
|
||||||
|
|
||||||
Q_ASSERT(slotId >= QObject::staticMetaObject.methodCount());
|
Q_ASSERT(slotId >= QObject::staticMetaObject.methodCount());
|
||||||
|
return slotId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalReceiver::removeSlot(int 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(call == QMetaObject::InvokeMetaMethod);
|
||||||
Q_ASSERT(id >= QObject::staticMetaObject.methodCount());
|
Q_ASSERT(id >= QObject::staticMetaObject.methodCount());
|
||||||
QMetaMethod slot = m_metaObject.method(id);
|
QMetaMethod slot = metaObject()->method(id);
|
||||||
Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
|
Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
|
||||||
|
|
||||||
if (strcmp(slot.signature(), RECEIVER_DESTROYED_SLOT_NAME) == 0) {
|
if (strcmp(slot.signature(), RECEIVER_DESTROYED_SLOT_NAME) == 0) {
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ public:
|
||||||
~GlobalReceiver();
|
~GlobalReceiver();
|
||||||
int qt_metacall(QMetaObject::Call call, int id, void** args);
|
int qt_metacall(QMetaObject::Call call, int id, void** args);
|
||||||
const QMetaObject* metaObject() const;
|
const QMetaObject* metaObject() const;
|
||||||
void addSlot(const char* slot, PyObject* callback);
|
int addSlot(const char* slot, PyObject* callback);
|
||||||
void removeSlot(int slotId);
|
void removeSlot(int slotId);
|
||||||
void connectNotify(QObject* sender, int slotId);
|
void connectNotify(QObject* sender, int slotId);
|
||||||
void disconnectNotify(QObject* sender, int slotId);
|
void disconnectNotify(QObject* sender, int slotId);
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@ void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base, const s
|
||||||
//create DynamicMetaObject based on python type
|
//create DynamicMetaObject based on python type
|
||||||
TypeUserData* userData = new TypeUserData(reinterpret_cast<PyTypeObject*>(type), base);
|
TypeUserData* userData = new TypeUserData(reinterpret_cast<PyTypeObject*>(type), base);
|
||||||
userData->cppObjSize = cppObjSize;
|
userData->cppObjSize = cppObjSize;
|
||||||
|
userData->mo.update();
|
||||||
Shiboken::ObjectType::setTypeUserData(type, userData, Shiboken::callCppDestructor<TypeUserData>);
|
Shiboken::ObjectType::setTypeUserData(type, userData, Shiboken::callCppDestructor<TypeUserData>);
|
||||||
|
|
||||||
//initialize staticQMetaObject property
|
//initialize staticQMetaObject property
|
||||||
|
|
@ -196,6 +197,7 @@ void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds)
|
||||||
if (PyType_IsSubtype(base, qObjType)) {
|
if (PyType_IsSubtype(base, qObjType)) {
|
||||||
baseMo = reinterpret_cast<QMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(base)));
|
baseMo = reinterpret_cast<QMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(base)));
|
||||||
qobjBase = reinterpret_cast<SbkObjectType*>(base);
|
qobjBase = reinterpret_cast<SbkObjectType*>(base);
|
||||||
|
reinterpret_cast<DynamicQMetaObject*>(baseMo)->update();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -216,9 +218,9 @@ PyObject* getMetaDataFromQObject(QObject* cppSelf, PyObject* self, PyObject* nam
|
||||||
|
|
||||||
if (attr && Property::isPropertyType(attr)) {
|
if (attr && Property::isPropertyType(attr)) {
|
||||||
PyObject *value = Property::getValue(reinterpret_cast<PySideProperty*>(attr), self);
|
PyObject *value = Property::getValue(reinterpret_cast<PySideProperty*>(attr), self);
|
||||||
|
Py_DECREF(attr);
|
||||||
if (!value)
|
if (!value)
|
||||||
return 0;
|
return 0;
|
||||||
Py_DECREF(attr);
|
|
||||||
Py_INCREF(value);
|
Py_INCREF(value);
|
||||||
attr = value;
|
attr = value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include "pysideproperty.h"
|
#include "pysideproperty.h"
|
||||||
#include "pysideproperty_p.h"
|
#include "pysideproperty_p.h"
|
||||||
#include "pyside.h"
|
#include "pyside.h"
|
||||||
|
#include "dynamicqmetaobject.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
@ -46,6 +47,14 @@
|
||||||
|
|
||||||
#define PYTHON_TYPE "PyObject"
|
#define PYTHON_TYPE "PyObject"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static PyObject *metaObjectAttr = 0;
|
||||||
|
static void destroyMetaObject(void* obj)
|
||||||
|
{
|
||||||
|
delete reinterpret_cast<PySide::DynamicQMetaObject*>(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace PySide {
|
namespace PySide {
|
||||||
|
|
||||||
static int callMethod(QObject* object, int id, void** args);
|
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>("object");
|
||||||
TypeResolver::createValueTypeResolver<PyObjectWrapper>("PySide::PyObjectWrapper");
|
TypeResolver::createValueTypeResolver<PyObjectWrapper>("PySide::PyObjectWrapper");
|
||||||
PySide::registerCleanupFunction(clearSignalManager);
|
PySide::registerCleanupFunction(clearSignalManager);
|
||||||
|
|
||||||
|
if (!metaObjectAttr)
|
||||||
|
metaObjectAttr = PyString_FromString("__METAOBJECT__");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SignalManager::clear()
|
void SignalManager::clear()
|
||||||
|
|
@ -225,7 +237,12 @@ void SignalManager::globalReceiverDisconnectNotify(QObject* source, int slotInde
|
||||||
|
|
||||||
void SignalManager::addGlobalSlot(const char* slot, PyObject* callback)
|
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)
|
static bool emitShortCircuitSignal(QObject* source, int signalIndex, PyObject* args)
|
||||||
|
|
@ -412,8 +429,13 @@ static int PySide::callMethod(QObject* object, int id, void** args)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SignalManager::registerMetaMethod(QObject* source, const char* signature, QMetaMethod::MethodType type)
|
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);
|
Q_ASSERT(source);
|
||||||
const QMetaObject* metaObject = source->metaObject();
|
const QMetaObject* metaObject = source->metaObject();
|
||||||
|
|
@ -423,19 +445,51 @@ bool SignalManager::registerMetaMethod(QObject* source, const char* signature, Q
|
||||||
SbkObject* self = Shiboken::BindingManager::instance().retrieveWrapper(source);
|
SbkObject* self = Shiboken::BindingManager::instance().retrieveWrapper(source);
|
||||||
if (!Shiboken::Object::hasCppWrapper(self)) {
|
if (!Shiboken::Object::hasCppWrapper(self)) {
|
||||||
qWarning() << "Invalid Signal signature:" << signature;
|
qWarning() << "Invalid Signal signature:" << signature;
|
||||||
return false;
|
return -1;
|
||||||
} else {
|
} 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)
|
if (type == QMetaMethod::Signal)
|
||||||
dynMetaObj->addSignal(signature);
|
return dmo->addSignal(signature);
|
||||||
else
|
else
|
||||||
dynMetaObj->addSlot(signature);
|
return dmo->addSlot(signature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return methodIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SignalManager::hasConnectionWith(const QObject *object)
|
bool SignalManager::hasConnectionWith(const QObject *object)
|
||||||
{
|
{
|
||||||
return m_d->m_globalReceiver.hasConnectionWith(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,12 +62,17 @@ public:
|
||||||
|
|
||||||
static int qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args);
|
static int qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args);
|
||||||
void addGlobalSlot(const char* slot, PyObject* callback);
|
void addGlobalSlot(const char* slot, PyObject* callback);
|
||||||
|
int addGlobalSlotGetIndex(const char* slot, PyObject* callback);
|
||||||
|
|
||||||
void globalReceiverConnectNotify(QObject *sender, int slotIndex);
|
void globalReceiverConnectNotify(QObject *sender, int slotIndex);
|
||||||
void globalReceiverDisconnectNotify(QObject *sender, int slotIndex);
|
void globalReceiverDisconnectNotify(QObject *sender, int slotIndex);
|
||||||
|
|
||||||
// Used to register a new signal/slot on QMetaobject of source.
|
// Used to register a new signal/slot on QMetaobject of source.
|
||||||
static bool registerMetaMethod(QObject* source, const char* signature, QMetaMethod::MethodType type);
|
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.
|
// Used to discovery if SignalManager was connected with object "destroyed()" signal.
|
||||||
bool hasConnectionWith(const QObject *object);
|
bool hasConnectionWith(const QObject *object);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue