From 0e8b50c9b0bf48f068e35586830e2f98a56890d4 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 19 Oct 2011 16:59:36 -0200 Subject: Fix bug 1019 - "Overriding QWidget.show or QWidget.hide do not work" Reviewer: Luciano Wolf Marcelo Lira --- PySide/QtCore/glue/qobject_connect.cpp | 30 ++++++++++++++++++++---------- tests/QtCore/CMakeLists.txt | 1 + tests/QtCore/bug_1019.py | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 tests/QtCore/bug_1019.py diff --git a/PySide/QtCore/glue/qobject_connect.cpp b/PySide/QtCore/glue/qobject_connect.cpp index 30e0b9aa3..b46cbcfbc 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(QObject *source, PyObject* callback, QObject** receiver, PyObject** self) +static bool getReceiver(QObject *source, const char* signal, PyObject* callback, QObject** receiver, PyObject** self, QByteArray* callbackSig) { bool forceGlobalReceiver = false; if (PyMethod_Check(callback)) { @@ -27,9 +27,20 @@ static bool getReceiver(QObject *source, PyObject* callback, QObject** receiver, } bool usingGlobalReceiver = !*receiver || forceGlobalReceiver; + + // Check if this callback is a overwrite of a non-virtual Qt slot. + if (!usingGlobalReceiver && receiver && self) { + *callbackSig = PySide::Signal::getCallbackSignature(signal, *receiver, callback, usingGlobalReceiver).toAscii(); + const QMetaObject* metaObject = (*receiver)->metaObject(); + int slotIndex = metaObject->indexOfSlot(callbackSig->constData()); + if (slotIndex != -1 && slotIndex < metaObject->methodOffset() && PyMethod_Check(callback)) + usingGlobalReceiver = true; + } + if (usingGlobalReceiver) { PySide::SignalManager& signalManager = PySide::SignalManager::instance(); *receiver = signalManager.globalReceiver(source, callback); + *callbackSig = PySide::Signal::getCallbackSignature(signal, *receiver, callback, usingGlobalReceiver).toAscii(); } return usingGlobalReceiver; @@ -68,14 +79,15 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject // Extract receiver from callback QObject* receiver = 0; PyObject* self = 0; - bool usingGlobalReceiver = getReceiver(source, callback, &receiver, &self); + QByteArray callbackSig; + bool usingGlobalReceiver = getReceiver(source, signal, callback, &receiver, &self, &callbackSig); if (receiver == 0 && self == 0) return false; const QMetaObject* metaObject = receiver->metaObject(); - const QByteArray callbackSig = PySide::Signal::getCallbackSignature(signal, receiver, callback, usingGlobalReceiver).toAscii(); const char* slot = callbackSig.constData(); int slotIndex = metaObject->indexOfSlot(slot); + if (slotIndex == -1) { if (!usingGlobalReceiver && self && !Shiboken::Object::hasCppWrapper((SbkObject*)self)) { qWarning() << "You can't add dynamic slots on an object originated from C++."; @@ -128,7 +140,8 @@ static bool qobjectDisconnectCallback(QObject* source, const char* signal, PyObj // Extract receiver from callback QObject* receiver = 0; PyObject* self = 0; - bool usingGlobalReceiver = getReceiver(NULL, callback, &receiver, &self); + QByteArray callbackSig; + bool usingGlobalReceiver = getReceiver(NULL, signal, callback, &receiver, &self, &callbackSig); if (receiver == 0 && self == 0) return false; @@ -136,21 +149,18 @@ static bool qobjectDisconnectCallback(QObject* source, const char* signal, PyObj int signalIndex = source->metaObject()->indexOfSignal(++signal); int slotIndex = -1; - const QByteArray callbackSig = PySide::Signal::getCallbackSignature(signal, receiver, callback, usingGlobalReceiver).toAscii(); - QByteArray qtSlotName(callbackSig); - - slotIndex = metaObject->indexOfSlot(qtSlotName); + slotIndex = metaObject->indexOfSlot(callbackSig); if (QMetaObject::disconnectOne(source, signalIndex, receiver, slotIndex)) { if (usingGlobalReceiver) signalManager.releaseGlobalReceiver(source, receiver); #ifndef AVOID_PROTECTED_HACK - source->disconnectNotify(qtSlotName); + source->disconnectNotify(callbackSig); #else // Need to cast to QObjectWrapper* and call the public version of // connectNotify when avoiding the protected hack. - reinterpret_cast(source)->disconnectNotify(qtSlotName); + reinterpret_cast(source)->disconnectNotify(callbackSig); #endif return true; } diff --git a/tests/QtCore/CMakeLists.txt b/tests/QtCore/CMakeLists.txt index 398746d75..cdd260e0e 100644 --- a/tests/QtCore/CMakeLists.txt +++ b/tests/QtCore/CMakeLists.txt @@ -23,6 +23,7 @@ PYSIDE_TEST(bug_938.py) PYSIDE_TEST(bug_953.py) PYSIDE_TEST(bug_987.py) PYSIDE_TEST(bug_994.py) +PYSIDE_TEST(bug_1019.py) PYSIDE_TEST(blocking_signals_test.py) PYSIDE_TEST(classinfo_test.py) PYSIDE_TEST(child_event_test.py) diff --git a/tests/QtCore/bug_1019.py b/tests/QtCore/bug_1019.py new file mode 100644 index 000000000..b7f1f68f7 --- /dev/null +++ b/tests/QtCore/bug_1019.py @@ -0,0 +1,32 @@ +import unittest +from PySide.QtCore import * + +class MyTimer (QTimer): + def __init__(self): + QTimer.__init__(self) + self.startCalled = False + + @Slot() + def slotUsedToIncreaseMethodOffset(self): + pass + +class MyTimer2 (MyTimer): + + @Slot() + def slotUsedToIncreaseMethodOffset2(self): + pass + + def start(self): + self.startCalled = True + QCoreApplication.instance().quit() + +class TestBug1019 (unittest.TestCase): + def testIt(self): + app = QCoreApplication([]) + t = MyTimer2() + QTimer.singleShot(0, t.start) + app.exec_() + self.assertTrue(t.startCalled) + +if __name__ == "__main__": + unittest.main() -- cgit v1.2.3