diff options
author | Renato Filho <renato.filho@openbossa.org> | 2010-02-19 17:10:24 -0300 |
---|---|---|
committer | Renato Filho <renato.filho@openbossa.org> | 2010-02-23 16:35:40 -0300 |
commit | 75b7afbd63be9b27d3bd964891720e8c16079280 (patch) | |
tree | f56e9d83a73bff0119333649521663f5c45aad20 /PySide/QtCore | |
parent | ab738e07d2cffc0fc9692ecc3a5f830847b853bb (diff) |
Fixed memory leak on callbacks used on signal connection.
Now using the 'destroyed()' signal the reference is cleaned after source
object destroyed.
Diffstat (limited to 'PySide/QtCore')
-rw-r--r-- | PySide/QtCore/glue/qobject_connect.cpp | 64 | ||||
-rw-r--r-- | PySide/QtCore/typesystem_core.xml | 10 |
2 files changed, 45 insertions, 29 deletions
diff --git a/PySide/QtCore/glue/qobject_connect.cpp b/PySide/QtCore/glue/qobject_connect.cpp index a8c856349..1b28ee0a8 100644 --- a/PySide/QtCore/glue/qobject_connect.cpp +++ b/PySide/QtCore/glue/qobject_connect.cpp @@ -1,3 +1,29 @@ +static bool getReceiver(PyObject *callback, QObject **receiver, PyObject **self) +{ + if (PyMethod_Check(callback)) { + *self = PyMethod_GET_SELF(callback); + if (SbkQObject_Check(*self)) + *receiver = SbkQObject_cptr(*self); + } else if (PyCFunction_Check(callback)) { + *self = PyCFunction_GET_SELF(callback); + if (*self && SbkQObject_Check(*self)) + *receiver = SbkQObject_cptr(*self); + } else if (!PyFunction_Check(callback)) { + *receiver = 0; + *self = 0; + qWarning() << "Invalid callback object."; + return false; + } + + bool usingGlobalReceiver = !*receiver; + if (usingGlobalReceiver) { + PySide::SignalManager& signalManager = PySide::SignalManager::instance(); + *receiver = signalManager.globalReceiver(); + } + + return usingGlobalReceiver; +} + static bool qobjectConnect(QObject* source, const char* signal, QObject* receiver, const char* slot, Qt::ConnectionType type) { if (!PySide::checkSignal(signal)) @@ -24,25 +50,11 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject PySide::SignalManager& signalManager = PySide::SignalManager::instance(); // Extract receiver from callback - bool usingGlobalReceiver; QObject* receiver = 0; PyObject* self = 0; - if (PyMethod_Check(callback)) { - self = PyMethod_GET_SELF(callback); - if (SbkQObject_Check(self)) - receiver = SbkQObject_cptr(self); - } else if (PyCFunction_Check(callback)) { - self = PyCFunction_GET_SELF(callback); - if (self && SbkQObject_Check(self)) - receiver = SbkQObject_cptr(self); - } else if (!PyFunction_Check(callback)) { - qWarning() << "Invalid callback object."; + bool usingGlobalReceiver = getReceiver(callback, &receiver, &self); + if (receiver == 0 and self == 0) return false; - } - - usingGlobalReceiver = !receiver; - if (usingGlobalReceiver) - receiver = signalManager.globalReceiver(); const QMetaObject* metaObject = receiver->metaObject(); const QByteArray callbackSig = PySide::getCallbackSignature(signal, callback, usingGlobalReceiver).toAscii(); @@ -66,10 +78,10 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject #ifndef AVOID_PROTECTED_HACK source->connectNotify(signal); #else - reinterpret_cast<QObjectWrapper*>(source)->connectNotify_protected(signal); + reinterpret_cast<QObjectWrapper*>(source)->connectNotify_protected(source, signal); #endif if (usingGlobalReceiver) - signalManager.globalReceiverConnectNotify(slotIndex); + signalManager.globalReceiverConnectNotify(source, slotIndex); return true; } @@ -85,17 +97,11 @@ static bool qobjectDisconnectCallback(QObject* source, const char* signal, PyObj PySide::SignalManager& signalManager = PySide::SignalManager::instance(); // Extract receiver from callback - bool usingGlobalReceiver; QObject* receiver = 0; - PyObject* self; - if (PyMethod_Check(callback)) { - self = PyMethod_GET_SELF(callback); - if (SbkQObject_Check(self)) - receiver = SbkQObject_cptr(self); - } - usingGlobalReceiver = !receiver; - if (usingGlobalReceiver) - receiver = signalManager.globalReceiver(); + PyObject* self = 0; + bool usingGlobalReceiver = getReceiver(callback, &receiver, &self); + if (receiver == 0 and self == 0) + return false; const QMetaObject* metaObject = receiver->metaObject(); const QByteArray callbackSig = PySide::getCallbackSignature(signal, callback, usingGlobalReceiver).toAscii(); @@ -105,7 +111,7 @@ static bool qobjectDisconnectCallback(QObject* source, const char* signal, PyObj if (QObject::disconnect(source, signal, receiver, qtSlotName.constData())) { if (usingGlobalReceiver) { int slotIndex = metaObject->indexOfSlot(callbackSig.constData()); - signalManager.globalReceiverDisconnectNotify(slotIndex); + signalManager.globalReceiverDisconnectNotify(source, slotIndex); } return true; } diff --git a/PySide/QtCore/typesystem_core.xml b/PySide/QtCore/typesystem_core.xml index fdfeb3739..212e19226 100644 --- a/PySide/QtCore/typesystem_core.xml +++ b/PySide/QtCore/typesystem_core.xml @@ -1631,6 +1631,16 @@ </inject-code> </add-function> + <modify-function signature="receivers(const char*) const"> + <inject-code class="target" position="beginning"> + //Avoid return +1 because SignalManager connect to "destroyed()" signal to control object timelife + int ret = %CPPSELF.%FUNCTION_NAME(%1); + if ((strcmp(%1, SIGNAL(destroyed())) == 0) && (PySide::SignalManager::instance().hasConnectionWith(%CPPSELF))) + ret--; + %PYARG_0 = %CONVERTTOPYTHON[int](ret); + </inject-code> + </modify-function> + <modify-function signature="sender() const"> <modify-argument index="return"> <define-ownership owner="target"/> |