diff options
author | Renato Filho <renato.filho@openbossa.org> | 2011-08-18 17:51:13 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-08 16:54:46 -0300 |
commit | 7b2c4242ad1d86bcc2da43a8482dbd39b3ac988e (patch) | |
tree | affbe074d73898afb10de5ae4685d698c5fb2f70 /PySide/QtCore | |
parent | d00af325c696acc390dd3565be82cd22b3b94658 (diff) |
Implemented GlobalReceiverV2.
A new implementation of GlobalRecever that optmize the signal
connection.
Fixes bug #928.
Reviewer: Marcelo Lira <marcelo.lira@openbossa.org>
Luciano Wolf <luciano.wolf@openbossa.org>
Diffstat (limited to 'PySide/QtCore')
-rw-r--r-- | PySide/QtCore/glue/qobject_connect.cpp | 44 | ||||
-rw-r--r-- | PySide/QtCore/typesystem_core.xml | 20 |
2 files changed, 45 insertions, 19 deletions
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<PyMethodObject*>(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<QObjectWrapper*>(source)->disconnectNotify(signal - 1); + reinterpret_cast<QObjectWrapper*>(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 @@ <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 (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); </inject-code> </modify-function> @@ -1507,6 +1506,19 @@ <modify-argument index="return"> <define-ownership owner="default"/> </modify-argument> + </modify-function> + + <!-- This is not supported due the lack of information durring the call with no arguments, this can cause a memory leak --> + <modify-function signature="disconnect(const char*, const QObject *, const char *)"> + <modify-argument index="1"> + <remove-default-expression /> + </modify-argument> + <modify-argument index="2"> + <remove-default-expression /> + </modify-argument> + <modify-argument index="3"> + <remove-default-expression /> + </modify-argument> </modify-function> </object-type> <object-type name="QAbstractListModel" polymorphic-id-expression="qobject_cast<QAbstractListModel*>(%1)"> |