Fix bug 1019 - "Overriding QWidget.show or QWidget.hide do not work"
Reviewer: Luciano Wolf <luciano.wolf@openbossa.org>
Marcelo Lira <marcelo.lira@openbossa.org>
This commit is contained in:
parent
b7f593d99e
commit
0e8b50c9b0
3 changed files with 53 additions and 10 deletions
|
|
@ -8,7 +8,7 @@ static bool isDecorator(PyObject* method, PyObject* self)
|
||||||
reinterpret_cast<PyMethodObject*>(method)->im_func;
|
reinterpret_cast<PyMethodObject*>(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;
|
bool forceGlobalReceiver = false;
|
||||||
if (PyMethod_Check(callback)) {
|
if (PyMethod_Check(callback)) {
|
||||||
|
|
@ -27,9 +27,20 @@ static bool getReceiver(QObject *source, PyObject* callback, QObject** receiver,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usingGlobalReceiver = !*receiver || forceGlobalReceiver;
|
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) {
|
if (usingGlobalReceiver) {
|
||||||
PySide::SignalManager& signalManager = PySide::SignalManager::instance();
|
PySide::SignalManager& signalManager = PySide::SignalManager::instance();
|
||||||
*receiver = signalManager.globalReceiver(source, callback);
|
*receiver = signalManager.globalReceiver(source, callback);
|
||||||
|
*callbackSig = PySide::Signal::getCallbackSignature(signal, *receiver, callback, usingGlobalReceiver).toAscii();
|
||||||
}
|
}
|
||||||
|
|
||||||
return usingGlobalReceiver;
|
return usingGlobalReceiver;
|
||||||
|
|
@ -68,14 +79,15 @@ static bool qobjectConnectCallback(QObject* source, const char* signal, PyObject
|
||||||
// Extract receiver from callback
|
// Extract receiver from callback
|
||||||
QObject* receiver = 0;
|
QObject* receiver = 0;
|
||||||
PyObject* self = 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)
|
if (receiver == 0 && self == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QMetaObject* metaObject = receiver->metaObject();
|
const QMetaObject* metaObject = receiver->metaObject();
|
||||||
const QByteArray callbackSig = PySide::Signal::getCallbackSignature(signal, receiver, callback, usingGlobalReceiver).toAscii();
|
|
||||||
const char* slot = callbackSig.constData();
|
const char* slot = callbackSig.constData();
|
||||||
int slotIndex = metaObject->indexOfSlot(slot);
|
int slotIndex = metaObject->indexOfSlot(slot);
|
||||||
|
|
||||||
if (slotIndex == -1) {
|
if (slotIndex == -1) {
|
||||||
if (!usingGlobalReceiver && self && !Shiboken::Object::hasCppWrapper((SbkObject*)self)) {
|
if (!usingGlobalReceiver && self && !Shiboken::Object::hasCppWrapper((SbkObject*)self)) {
|
||||||
qWarning() << "You can't add dynamic slots on an object originated from C++.";
|
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
|
// Extract receiver from callback
|
||||||
QObject* receiver = 0;
|
QObject* receiver = 0;
|
||||||
PyObject* self = 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)
|
if (receiver == 0 && self == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -136,21 +149,18 @@ static bool qobjectDisconnectCallback(QObject* source, const char* signal, PyObj
|
||||||
int signalIndex = source->metaObject()->indexOfSignal(++signal);
|
int signalIndex = source->metaObject()->indexOfSignal(++signal);
|
||||||
int slotIndex = -1;
|
int slotIndex = -1;
|
||||||
|
|
||||||
const QByteArray callbackSig = PySide::Signal::getCallbackSignature(signal, receiver, callback, usingGlobalReceiver).toAscii();
|
slotIndex = metaObject->indexOfSlot(callbackSig);
|
||||||
QByteArray qtSlotName(callbackSig);
|
|
||||||
|
|
||||||
slotIndex = metaObject->indexOfSlot(qtSlotName);
|
|
||||||
|
|
||||||
if (QMetaObject::disconnectOne(source, signalIndex, receiver, slotIndex)) {
|
if (QMetaObject::disconnectOne(source, signalIndex, receiver, slotIndex)) {
|
||||||
if (usingGlobalReceiver)
|
if (usingGlobalReceiver)
|
||||||
signalManager.releaseGlobalReceiver(source, receiver);
|
signalManager.releaseGlobalReceiver(source, receiver);
|
||||||
|
|
||||||
#ifndef AVOID_PROTECTED_HACK
|
#ifndef AVOID_PROTECTED_HACK
|
||||||
source->disconnectNotify(qtSlotName);
|
source->disconnectNotify(callbackSig);
|
||||||
#else
|
#else
|
||||||
// Need to cast to QObjectWrapper* and call the public version of
|
// Need to cast to QObjectWrapper* and call the public version of
|
||||||
// connectNotify when avoiding the protected hack.
|
// connectNotify when avoiding the protected hack.
|
||||||
reinterpret_cast<QObjectWrapper*>(source)->disconnectNotify(qtSlotName);
|
reinterpret_cast<QObjectWrapper*>(source)->disconnectNotify(callbackSig);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ PYSIDE_TEST(bug_938.py)
|
||||||
PYSIDE_TEST(bug_953.py)
|
PYSIDE_TEST(bug_953.py)
|
||||||
PYSIDE_TEST(bug_987.py)
|
PYSIDE_TEST(bug_987.py)
|
||||||
PYSIDE_TEST(bug_994.py)
|
PYSIDE_TEST(bug_994.py)
|
||||||
|
PYSIDE_TEST(bug_1019.py)
|
||||||
PYSIDE_TEST(blocking_signals_test.py)
|
PYSIDE_TEST(blocking_signals_test.py)
|
||||||
PYSIDE_TEST(classinfo_test.py)
|
PYSIDE_TEST(classinfo_test.py)
|
||||||
PYSIDE_TEST(child_event_test.py)
|
PYSIDE_TEST(child_event_test.py)
|
||||||
|
|
|
||||||
32
tests/QtCore/bug_1019.py
Normal file
32
tests/QtCore/bug_1019.py
Normal file
|
|
@ -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()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue