From 7b2c4242ad1d86bcc2da43a8482dbd39b3ac988e Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Thu, 18 Aug 2011 17:51:13 -0300 Subject: Implemented GlobalReceiverV2. A new implementation of GlobalRecever that optmize the signal connection. Fixes bug #928. Reviewer: Marcelo Lira Luciano Wolf --- PySide/QtCore/glue/qobject_connect.cpp | 44 +++-- PySide/QtCore/typesystem_core.xml | 20 ++- libpyside/CMakeLists.txt | 1 + libpyside/globalreceiver.cpp | 1 + libpyside/globalreceiver.h | 1 + libpyside/globalreceiverv2.cpp | 308 +++++++++++++++++++++++++++++++++ libpyside/globalreceiverv2.h | 131 ++++++++++++++ libpyside/signalmanager.cpp | 66 +++++++ libpyside/signalmanager.h | 25 ++- 9 files changed, 570 insertions(+), 27 deletions(-) create mode 100644 libpyside/globalreceiverv2.cpp create mode 100644 libpyside/globalreceiverv2.h diff --git a/PySide/QtCore/glue/qobject_connect.cpp b/PySide/QtCore/glue/qobject_connect.cpp index 3296c2e89..30e0b9aa3 100644 --- a/PySide/QtCore/glue/qobject_connect.cpp +++ b/PySide/QtCore/glue/qobject_connect.cpp @@ -8,7 +8,7 @@ static bool isDecorator(PyObject* method, PyObject* self) reinterpret_cast(method)->im_func; } -static bool getReceiver(PyObject* callback, QObject** receiver, PyObject** self) +static bool getReceiver(QObject *source, PyObject* callback, QObject** receiver, PyObject** self) { bool forceGlobalReceiver = false; if (PyMethod_Check(callback)) { @@ -29,7 +29,7 @@ static bool getReceiver(PyObject* callback, QObject** receiver, PyObject** self) bool usingGlobalReceiver = !*receiver || forceGlobalReceiver; if (usingGlobalReceiver) { PySide::SignalManager& signalManager = PySide::SignalManager::instance(); - *receiver = signalManager.globalReceiver(); + *receiver = signalManager.globalReceiver(source, callback); } return usingGlobalReceiver; @@ -68,7 +68,7 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject // Extract receiver from callback QObject* receiver = 0; PyObject* self = 0; - bool usingGlobalReceiver = getReceiver(callback, &receiver, &self); + bool usingGlobalReceiver = getReceiver(source, callback, &receiver, &self); if (receiver == 0 && self == 0) return false; @@ -79,20 +79,27 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject if (slotIndex == -1) { if (!usingGlobalReceiver && self && !Shiboken::Object::hasCppWrapper((SbkObject*)self)) { qWarning() << "You can't add dynamic slots on an object originated from C++."; + if (usingGlobalReceiver) + signalManager.releaseGlobalReceiver(source, receiver); + return false; } if (usingGlobalReceiver) - slotIndex = signalManager.addGlobalSlotGetIndex(slot, callback); + slotIndex = signalManager.globalReceiverSlotIndex(receiver, slot); else slotIndex = PySide::SignalManager::registerMetaMethodGetIndex(receiver, slot, QMetaMethod::Slot); - if (slotIndex == -1) + if (slotIndex == -1) { + if (usingGlobalReceiver) + signalManager.releaseGlobalReceiver(source, receiver); + return false; + } } if (QMetaObject::connect(source, signalIndex, receiver, slotIndex, type)) { if (usingGlobalReceiver) - signalManager.globalReceiverConnectNotify(source, slotIndex); + signalManager.notifyGlobalReceiver(receiver); #ifndef AVOID_PROTECTED_HACK source->connectNotify(signal - 1); #else @@ -103,6 +110,10 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject return true; } + + if (usingGlobalReceiver) + signalManager.releaseGlobalReceiver(source, receiver); + return false; } @@ -117,27 +128,30 @@ static bool qobjectDisconnectCallback(QObject* source, const char* signal, PyObj // Extract receiver from callback QObject* receiver = 0; PyObject* self = 0; - bool usingGlobalReceiver = getReceiver(callback, &receiver, &self); + bool usingGlobalReceiver = getReceiver(NULL, callback, &receiver, &self); if (receiver == 0 && self == 0) return false; const QMetaObject* metaObject = receiver->metaObject(); + int signalIndex = source->metaObject()->indexOfSignal(++signal); + int slotIndex = -1; + const QByteArray callbackSig = PySide::Signal::getCallbackSignature(signal, receiver, callback, usingGlobalReceiver).toAscii(); QByteArray qtSlotName(callbackSig); - qtSlotName = qtSlotName.prepend('1'); - if (QObject::disconnect(source, signal, receiver, qtSlotName.constData())) { - if (usingGlobalReceiver) { - int slotIndex = metaObject->indexOfSlot(callbackSig.constData()); - signalManager.globalReceiverDisconnectNotify(source, slotIndex); + slotIndex = metaObject->indexOfSlot(qtSlotName); + + if (QMetaObject::disconnectOne(source, signalIndex, receiver, slotIndex)) { + if (usingGlobalReceiver) + signalManager.releaseGlobalReceiver(source, receiver); + #ifndef AVOID_PROTECTED_HACK - source->disconnectNotify(signal - 1); + source->disconnectNotify(qtSlotName); #else // Need to cast to QObjectWrapper* and call the public version of // connectNotify when avoiding the protected hack. - reinterpret_cast(source)->disconnectNotify(signal - 1); + reinterpret_cast(source)->disconnectNotify(qtSlotName); #endif - } return true; } return false; diff --git a/PySide/QtCore/typesystem_core.xml b/PySide/QtCore/typesystem_core.xml index ecbe25059..83f69dffc 100644 --- a/PySide/QtCore/typesystem_core.xml +++ b/PySide/QtCore/typesystem_core.xml @@ -1489,10 +1489,9 @@ // Avoid return +1 because SignalManager connect to "destroyed()" signal to control object timelife int ret = %CPPSELF.%FUNCTION_NAME(%1); - if (ret > 0 && ((strcmp(%1, SIGNAL(destroyed())) == 0) || (strcmp(%1, SIGNAL(destroyed(QObject*))) == 0))) { - if (PySide::SignalManager::instance().hasConnectionWith(%CPPSELF)) - ret--; - } + if (ret > 0 && ((strcmp(%1, SIGNAL(destroyed())) == 0) || (strcmp(%1, SIGNAL(destroyed(QObject*))) == 0))) + ret -= PySide::SignalManager::instance().countConnectionsWith(%CPPSELF); + %PYARG_0 = %CONVERTTOPYTHON[int](ret); @@ -1507,6 +1506,19 @@ + + + + + + + + + + + + + diff --git a/libpyside/CMakeLists.txt b/libpyside/CMakeLists.txt index e05a8cd7e..219294509 100644 --- a/libpyside/CMakeLists.txt +++ b/libpyside/CMakeLists.txt @@ -8,6 +8,7 @@ set(libpyside_SRC destroylistener.cpp signalmanager.cpp globalreceiver.cpp + globalreceiverv2.cpp pysideclassinfo.cpp pysidemetafunction.cpp pysidesignal.cpp diff --git a/libpyside/globalreceiver.cpp b/libpyside/globalreceiver.cpp index 435e22aa0..17f0090f7 100644 --- a/libpyside/globalreceiver.cpp +++ b/libpyside/globalreceiver.cpp @@ -297,3 +297,4 @@ int GlobalReceiver::qt_metacall(QMetaObject::Call call, int id, void** args) return -1; } + diff --git a/libpyside/globalreceiver.h b/libpyside/globalreceiver.h index 76c1246d6..4eb2b9af9 100644 --- a/libpyside/globalreceiver.h +++ b/libpyside/globalreceiver.h @@ -56,3 +56,4 @@ private: } #endif + diff --git a/libpyside/globalreceiverv2.cpp b/libpyside/globalreceiverv2.cpp new file mode 100644 index 000000000..c31a9d2f6 --- /dev/null +++ b/libpyside/globalreceiverv2.cpp @@ -0,0 +1,308 @@ +/* +* This file is part of the PySide project. +* +* Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). +* +* Contact: PySide team +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "globalreceiverv2.h" +#include "dynamicqmetaobject_p.h" +#include "pysideweakref.h" + +#include +#include +#include +#include +#include +#include + +#include "typeresolver.h" +#include "signalmanager.h" + +#define RECEIVER_DESTROYED_SLOT_NAME "__receiverDestroyed__(QObject*)" + +namespace +{ + static int DESTROY_SIGNAL_ID = 0; + static int DESTROY_SLOT_ID = 0; +} + +namespace PySide +{ +class DynamicSlotDataV2 +{ + public: + DynamicSlotDataV2(PyObject* callback, GlobalReceiverV2* parent); + ~DynamicSlotDataV2(); + + int addSlot(const char* signature); + int id(const char* signature) const; + PyObject* call(PyObject* args); + QByteArray hash() const; + void notify(); + + static void onCallbackDestroyed(void* data); + static QByteArray hash(PyObject *callback); + + + private: + bool m_isMethod; + PyObject* m_callback; + PyObject* m_pythonSelf; + PyObject* m_pyClass; + PyObject* m_weakRef; + QMap m_signatures; + GlobalReceiverV2* m_parent; + QByteArray m_hash; +}; + +} + +using namespace PySide; + +DynamicSlotDataV2::DynamicSlotDataV2(PyObject* callback, GlobalReceiverV2* parent) + : m_pythonSelf(0), m_pyClass(0), m_weakRef(0), m_parent(parent) +{ + m_isMethod = PyMethod_Check(callback); + if (m_isMethod) { + //Can not store calback pointe because this will be destroyed at the end of the scope + //To avoid increment intance reference keep the callback information + m_callback = PyMethod_GET_FUNCTION(callback); + m_pyClass = PyMethod_GET_CLASS(callback); + m_pythonSelf = PyMethod_GET_SELF(callback); + + //monitor class from method lifetime + m_weakRef = WeakRef::create(m_pythonSelf, DynamicSlotDataV2::onCallbackDestroyed, this); + + m_hash = QByteArray::number((qlonglong)PyObject_Hash(m_callback)) + + QByteArray::number((qlonglong)PyObject_Hash(m_pythonSelf)); + + } else { + m_callback = callback; + Py_INCREF(m_callback); + + m_hash = QByteArray::number((qlonglong)PyObject_Hash(m_callback)); + } +} + +QByteArray DynamicSlotDataV2::hash() const +{ + return m_hash; +} + +QByteArray DynamicSlotDataV2::hash(PyObject* callback) +{ + Shiboken::GilState gil; + if (PyMethod_Check(callback)) + return QByteArray::number((qlonglong)PyObject_Hash(PyMethod_GET_FUNCTION(callback))) + + QByteArray::number((qlonglong)PyObject_Hash(PyMethod_GET_SELF(callback))); + else + return QByteArray::number((qlonglong)PyObject_Hash(callback)); +} + +PyObject* DynamicSlotDataV2::call(PyObject* args) +{ + PyObject* callback = m_callback; + + //create a callback based on method data + if (m_isMethod) + callback = PyMethod_New(m_callback, m_pythonSelf, m_pyClass); + + PyObject* result = PyObject_CallObject(callback, args); + + if (m_isMethod) + Py_DECREF(callback); + + return result; +} + +int DynamicSlotDataV2::id(const char* signature) const +{ + if (m_signatures.contains(signature)) + return m_signatures[signature]; + return -1; +} + +int DynamicSlotDataV2::addSlot(const char* signature) +{ + int index = id(signature); + if (index == -1) { + DynamicQMetaObject *dmo = const_cast(reinterpret_cast(m_parent->metaObject())); + index = m_signatures[signature] = dmo->addSlot(signature); + } + return index; +} + +void DynamicSlotDataV2::onCallbackDestroyed(void *data) +{ + DynamicSlotDataV2* self = reinterpret_cast(data); + self->m_weakRef = 0; + delete self->m_parent; +} + +DynamicSlotDataV2::~DynamicSlotDataV2() +{ + Shiboken::GilState gil; + + Py_XDECREF(m_weakRef); + m_weakRef = 0; + + if (!m_isMethod) + Py_DECREF(m_callback); +} + +GlobalReceiverV2::GlobalReceiverV2(PyObject *callback, SharedMap map) + : QObject(0), m_metaObject(GLOBAL_RECEIVER_CLASS_NAME, &QObject::staticMetaObject), m_sharedMap(map) +{ + m_data = new DynamicSlotDataV2(callback, this); + m_metaObject.addSlot(RECEIVER_DESTROYED_SLOT_NAME); + m_metaObject.update(); + m_refs.append(NULL); + + + if (DESTROY_SIGNAL_ID == 0) + DESTROY_SIGNAL_ID = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); + + if (DESTROY_SLOT_ID == 0) + DESTROY_SLOT_ID = m_metaObject.indexOfSlot(RECEIVER_DESTROYED_SLOT_NAME); + + +} + +GlobalReceiverV2::~GlobalReceiverV2() +{ + m_refs.clear(); + //Remove itself from map + m_sharedMap->remove(m_data->hash()); + delete m_data; +} + +int GlobalReceiverV2::addSlot(const char* signature) +{ + return m_data->addSlot(signature); +} + +void GlobalReceiverV2::incRef(const QObject* link) +{ + if (link) { + if (!m_refs.contains(link)) { + if (QMetaObject::connect(link, DESTROY_SIGNAL_ID, this, DESTROY_SLOT_ID)) + m_refs.append(link); + else + Q_ASSERT(false); + } else { + m_refs.append(link); + } + } else { + m_refs.append(NULL); + } +} + +void GlobalReceiverV2::decRef(const QObject* link) +{ + if (m_refs.size() <= 0) + return; + + + m_refs.removeOne(link); + if (link) { + if (!m_refs.contains(link)) { + bool result = QMetaObject::disconnect(link, DESTROY_SIGNAL_ID, this, DESTROY_SLOT_ID); + Q_ASSERT(result); + if (!result) + return; + } + } + + if (m_refs.size() == 0) + delete this; + +} + +int GlobalReceiverV2::refCount(const QObject* link) const +{ + if (link) + return m_refs.count(link); + + return m_refs.size(); +} + +void GlobalReceiverV2::notify() +{ + QSet objs = QSet::fromList(m_refs); + foreach(const QObject* o, objs) { + QMetaObject::disconnect(o, DESTROY_SIGNAL_ID, this, DESTROY_SLOT_ID); + QMetaObject::connect(o, DESTROY_SIGNAL_ID, this, DESTROY_SLOT_ID); + } +} + +QByteArray GlobalReceiverV2::hash() const +{ + return m_data->hash(); +} + +QByteArray GlobalReceiverV2::hash(PyObject* callback) +{ + return DynamicSlotDataV2::hash(callback); +} + +const QMetaObject* GlobalReceiverV2::metaObject() const +{ + return m_metaObject.update(); +} + +int GlobalReceiverV2::qt_metacall(QMetaObject::Call call, int id, void** args) +{ + Q_ASSERT(call == QMetaObject::InvokeMetaMethod); + Q_ASSERT(id >= QObject::staticMetaObject.methodCount()); + + QMetaMethod slot = metaObject()->method(id); + Q_ASSERT(slot.methodType() == QMetaMethod::Slot); + + if (id == DESTROY_SLOT_ID) { + if (m_refs.size() == 0) + return -1; + QObject *obj = *(QObject**)args[1]; + incRef(); //keep the object live (safe ref) + m_refs.removeAll(obj); // remove all refs to this object + decRef(); //remove the safe ref + } else { + Shiboken::GilState gil; + PyObject* retval = 0; + + bool isShortCurt = (strstr(slot.signature(), "(") == 0); + if (isShortCurt) { + retval = m_data->call(reinterpret_cast(args[1])); + } else { + QList paramTypes = slot.parameterTypes(); + Shiboken::AutoDecRef preparedArgs(PyTuple_New(paramTypes.count())); + for (int i = 0, max = paramTypes.count(); i < max; ++i) { + PyObject* arg = Shiboken::TypeResolver::get(paramTypes[i].constData())->toPython(args[i+1]); // Do not increment the reference + PyTuple_SET_ITEM(preparedArgs.object(), i, arg); + } + retval = m_data->call(preparedArgs); + } + + if (!retval) + PyErr_Print(); + else + Py_DECREF(retval); + } + + return -1; +} diff --git a/libpyside/globalreceiverv2.h b/libpyside/globalreceiverv2.h new file mode 100644 index 000000000..28f470306 --- /dev/null +++ b/libpyside/globalreceiverv2.h @@ -0,0 +1,131 @@ +/* +* This file is part of the PySide project. +* +* Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). +* +* Contact: PySide team +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GLOBALRECEIVER_V2_H +#define GLOBALRECEIVER_V2_H + +#include +#include +#include +#include +#include +#include +#include + +#include "dynamicqmetaobject.h" + +namespace PySide +{ + +class DynamicSlotDataV2; +class GlobalReceiverV2; + +typedef QSharedPointer< QMap > SharedMap; + +/** + * A class used to make the link between the C++ Signal/Slot and Python callback + * This class is used internally by SignalManager + **/ + +class GlobalReceiverV2 : public QObject +{ +public: + /** + * Create a GlobalReceiver object that will call 'callback' argumentent + * + * @param callback A Python callable object (can be a method or not) + * @param ma A SharedPointer used on Signal manager that contains all instaces of GlobalReceiver + **/ + GlobalReceiverV2(PyObject *callback, SharedMap map); + + /** + * Destructor + **/ + ~GlobalReceiverV2(); + + /** + * Reimplemented function from QObject + **/ + int qt_metacall(QMetaObject::Call call, int id, void** args); + const QMetaObject* metaObject() const; + + /** + * Add a extra slot to this object + * + * @param signature The signature of the slot to be added + * @return The index of this slot on metaobject + **/ + int addSlot(const char* signature); + + /** + * Notify to GlobalReceiver about when a new connection was made + **/ + void notify(); + + /** + * Used to increment the reference of the GlobalReceiver object + * + * @param link This is a optional paramenter used to link the ref to some QObject life + **/ + void incRef(const QObject* link = 0); + + /** + * Used to decrement the reference of the GlobalReceiver object + * + * @param link This is a optional paramenter used to dismiss the link ref to some QObject + **/ + void decRef(const QObject* link = 0); + + /* + * Return the count of refs which the GlobalReceiver has + * + * @param link If any QObject was passed, the function return the number of references relative to this 'link' object + * @return The number of references + **/ + int refCount(const QObject* link) const; + + /** + * Use to retrive the unique hash of this GlobalReceiver object + * + * @return a string with a unique id based on GlobalReceiver contents + **/ + QByteArray hash() const; + + /** + * Use to retrive the unique hash of the PyObject based on GlobalReceiver rules + * + * @param callback The Python callable object used to calculate the id + * @return a string with a unique id based on GlobalReceiver contents + **/ + static QByteArray hash(PyObject* callback); + +private: + DynamicQMetaObject m_metaObject; + DynamicSlotDataV2 *m_data; + QList m_refs; + int m_ref; + SharedMap m_sharedMap; +}; + +} + +#endif diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp index b7b9b3d93..c0dffd431 100644 --- a/libpyside/signalmanager.cpp +++ b/libpyside/signalmanager.cpp @@ -43,6 +43,7 @@ #endif #define PYSIDE_SLOT '1' #define PYSIDE_SIGNAL '2' +#include "globalreceiverv2.h" #include "globalreceiver.h" #define PYTHON_TYPE "PyObject" @@ -177,7 +178,26 @@ using namespace PySide; struct SignalManager::SignalManagerPrivate { + SharedMap m_globalReceivers; + + //Deprecated GlobalReceiver m_globalReceiver; + + SignalManagerPrivate() + { + m_globalReceivers = SharedMap( new QMap() ); + } + + ~SignalManagerPrivate() + { + if (!m_globalReceivers.isNull()) { + QList values = m_globalReceivers->values(); + m_globalReceivers->clear(); + if (values.size()) { + qDeleteAll(values); + } + } + } }; static void clearSignalManager() @@ -245,6 +265,50 @@ int SignalManager::addGlobalSlotGetIndex(const char* slot, PyObject* callback) return m_d->m_globalReceiver.addSlot(slot, callback); } +QObject* SignalManager::globalReceiver(QObject *sender, PyObject *callback) +{ + SharedMap globalReceivers = m_d->m_globalReceivers; + QByteArray hash = GlobalReceiverV2::hash(callback); + GlobalReceiverV2* gr = 0; + if (!globalReceivers->contains(hash) && sender) { + gr = (*globalReceivers)[hash] = new GlobalReceiverV2(callback, globalReceivers); + gr->incRef(sender); // create a link reference + gr->decRef(); // remove extra reference + } else { + gr = (*globalReceivers)[hash]; + if (sender) + gr->incRef(sender); + } + + return reinterpret_cast(gr); +} + +int SignalManager::countConnectionsWith(const QObject *object) +{ + int count = 0; + foreach(GlobalReceiverV2* g, m_d->m_globalReceivers->values()) { + if (g->refCount(object)) + count++; + } + return count; +} + +void SignalManager::notifyGlobalReceiver(QObject* receiver) +{ + reinterpret_cast(receiver)->notify(); +} + +void SignalManager::releaseGlobalReceiver(const QObject* source, QObject* receiver) +{ + GlobalReceiverV2* gr = reinterpret_cast(receiver); + gr->decRef(source); +} + +int SignalManager::globalReceiverSlotIndex(QObject* receiver, const char* signature) const +{ + return reinterpret_cast(receiver)->addSlot(signature); +} + static bool emitShortCircuitSignal(QObject* source, int signalIndex, PyObject* args) { void* signalArgs[2] = {0, args}; @@ -480,6 +544,7 @@ bool SignalManager::hasConnectionWith(const QObject *object) return m_d->m_globalReceiver.hasConnectionWith(object); } + const QMetaObject* SignalManager::retriveMetaObject(PyObject *self) { Shiboken::GilState gil; @@ -498,3 +563,4 @@ const QMetaObject* SignalManager::retriveMetaObject(PyObject *self) return mo; } + diff --git a/libpyside/signalmanager.h b/libpyside/signalmanager.h index b1b798600..1c8ecfc2e 100644 --- a/libpyside/signalmanager.h +++ b/libpyside/signalmanager.h @@ -57,15 +57,14 @@ class PYSIDE_API SignalManager { public: static SignalManager& instance(); - QObject* globalReceiver(); - bool emitSignal(QObject* source, const char* signal, PyObject* args); - 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); + QObject* globalReceiver(QObject* sender, PyObject* callback); + void releaseGlobalReceiver(const QObject* sender, QObject* receiver); + int globalReceiverSlotIndex(QObject* sender, const char* slotSignature) const; + void notifyGlobalReceiver(QObject* receiver); - void globalReceiverConnectNotify(QObject *sender, int slotIndex); - void globalReceiverDisconnectNotify(QObject *sender, int slotIndex); + bool emitSignal(QObject* source, const char* signal, PyObject* args); + static int qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args); // Used to register a new signal/slot on QMetaobject of source. static bool registerMetaMethod(QObject* source, const char* signature, QMetaMethod::MethodType type); @@ -75,10 +74,20 @@ public: static const QMetaObject* retriveMetaObject(PyObject* self); // Used to discovery if SignalManager was connected with object "destroyed()" signal. - bool hasConnectionWith(const QObject *object); + int countConnectionsWith(const QObject *object); // Disconnect all signals managed by Globalreceiver void clear(); + + + PYSIDE_DEPRECATED(QObject* globalReceiver()); + PYSIDE_DEPRECATED(void addGlobalSlot(const char* slot, PyObject* callback)); + PYSIDE_DEPRECATED(int addGlobalSlotGetIndex(const char* slot, PyObject* callback)); + + PYSIDE_DEPRECATED(void globalReceiverConnectNotify(QObject *sender, int slotIndex)); + PYSIDE_DEPRECATED(void globalReceiverDisconnectNotify(QObject *sender, int slotIndex)); + PYSIDE_DEPRECATED(bool hasConnectionWith(const QObject *object)); + private: struct SignalManagerPrivate; SignalManagerPrivate* m_d; -- cgit v1.2.3