aboutsummaryrefslogtreecommitdiffstats
path: root/PySide/QtCore
diff options
context:
space:
mode:
authorRenato Filho <renato.filho@openbossa.org>2010-02-19 17:10:24 -0300
committerRenato Filho <renato.filho@openbossa.org>2010-02-23 16:35:40 -0300
commit75b7afbd63be9b27d3bd964891720e8c16079280 (patch)
treef56e9d83a73bff0119333649521663f5c45aad20 /PySide/QtCore
parentab738e07d2cffc0fc9692ecc3a5f830847b853bb (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.cpp64
-rw-r--r--PySide/QtCore/typesystem_core.xml10
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) &amp;&amp; (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"/>