Fixes connecting signal to decorated slot.
Decorated methods on classes derived from QObject are not called when connected to Qt signals because they get a name different from the decorated method. To solve this decorated methods are registered as global slots. An unit test was added. Reviewed by Hugo Parente <hugo.lima@openbossa.org> Reviewed by Renato Araújo <renato.filho@openbossa.org>
This commit is contained in:
parent
5151af6de1
commit
a1cf8f03b2
3 changed files with 54 additions and 3 deletions
|
|
@ -1,9 +1,20 @@
|
||||||
|
static bool isDecorator(PyObject* method, PyObject* self)
|
||||||
|
{
|
||||||
|
Shiboken::AutoDecRef methodName(PyObject_GetAttrString(method, "__name__"));
|
||||||
|
if (!PyObject_HasAttr(self, methodName))
|
||||||
|
return true;
|
||||||
|
Shiboken::AutoDecRef otherMethod(PyObject_GetAttr(self, methodName));
|
||||||
|
return otherMethod.object() != method;
|
||||||
|
}
|
||||||
|
|
||||||
static bool getReceiver(PyObject* callback, QObject** receiver, PyObject** self)
|
static bool getReceiver(PyObject* callback, QObject** receiver, PyObject** self)
|
||||||
{
|
{
|
||||||
|
bool forceGlobalReceiver = false;
|
||||||
if (PyMethod_Check(callback)) {
|
if (PyMethod_Check(callback)) {
|
||||||
*self = PyMethod_GET_SELF(callback);
|
*self = PyMethod_GET_SELF(callback);
|
||||||
if (Shiboken::Converter<QObject*>::checkType(*self))
|
if (Shiboken::Converter<QObject*>::checkType(*self))
|
||||||
*receiver = Shiboken::Converter<QObject*>::toCpp(*self);
|
*receiver = Shiboken::Converter<QObject*>::toCpp(*self);
|
||||||
|
forceGlobalReceiver = isDecorator(callback, *self);
|
||||||
} else if (PyCFunction_Check(callback)) {
|
} else if (PyCFunction_Check(callback)) {
|
||||||
*self = PyCFunction_GET_SELF(callback);
|
*self = PyCFunction_GET_SELF(callback);
|
||||||
if (*self && Shiboken::Converter<QObject*>::checkType(*self))
|
if (*self && Shiboken::Converter<QObject*>::checkType(*self))
|
||||||
|
|
@ -14,7 +25,7 @@ static bool getReceiver(PyObject* callback, QObject** receiver, PyObject** self)
|
||||||
*self = 0;
|
*self = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool usingGlobalReceiver = !*receiver;
|
bool usingGlobalReceiver = !*receiver || forceGlobalReceiver;
|
||||||
if (usingGlobalReceiver) {
|
if (usingGlobalReceiver) {
|
||||||
PySide::SignalManager& signalManager = PySide::SignalManager::instance();
|
PySide::SignalManager& signalManager = PySide::SignalManager::instance();
|
||||||
*receiver = signalManager.globalReceiver();
|
*receiver = signalManager.globalReceiver();
|
||||||
|
|
|
||||||
|
|
@ -72,9 +72,10 @@ target_link_libraries(testbinding
|
||||||
add_dependencies(testbinding pyside QtCore QtGui libpyside pysidetest)
|
add_dependencies(testbinding pyside QtCore QtGui libpyside pysidetest)
|
||||||
|
|
||||||
|
|
||||||
PYSIDE_TEST(homonymoussignalandmethod_test.py)
|
PYSIDE_TEST(decoratedslot_test.py)
|
||||||
PYSIDE_TEST(delegatecreateseditor_test.py)
|
PYSIDE_TEST(delegatecreateseditor_test.py)
|
||||||
|
PYSIDE_TEST(homonymoussignalandmethod_test.py)
|
||||||
|
PYSIDE_TEST(list_signal_test.py)
|
||||||
PYSIDE_TEST(modelview_test.py)
|
PYSIDE_TEST(modelview_test.py)
|
||||||
PYSIDE_TEST(version_test.py)
|
PYSIDE_TEST(version_test.py)
|
||||||
PYSIDE_TEST(list_signal_test.py)
|
|
||||||
|
|
||||||
|
|
|
||||||
39
tests/pysidetest/decoratedslot_test.py
Normal file
39
tests/pysidetest/decoratedslot_test.py
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from PySide.QtCore import QObject
|
||||||
|
from testbinding import TestObject
|
||||||
|
|
||||||
|
class Receiver(QObject):
|
||||||
|
def __init__(self):
|
||||||
|
QObject.__init__(self)
|
||||||
|
self.called = False
|
||||||
|
|
||||||
|
def ReceiverDecorator(func):
|
||||||
|
def decoratedFunction(self, *args, **kw):
|
||||||
|
func(self, *args, **kw)
|
||||||
|
return decoratedFunction
|
||||||
|
|
||||||
|
# This method with the same name of the internal decorated function
|
||||||
|
# is here to test the binding capabilities.
|
||||||
|
def decoratedFunction(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@ReceiverDecorator
|
||||||
|
def slot(self):
|
||||||
|
self.called = True
|
||||||
|
|
||||||
|
|
||||||
|
class DecoratedSlotTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def testCallingOfDecoratedSlot(self):
|
||||||
|
obj = TestObject(0)
|
||||||
|
receiver = Receiver()
|
||||||
|
obj.staticMethodDouble.connect(receiver.slot)
|
||||||
|
obj.emitStaticMethodDoubleSignal()
|
||||||
|
self.assert_(receiver.called)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue