diff options
-rw-r--r-- | libpyside/signalmanager.cpp | 50 | ||||
-rw-r--r-- | tests/signals/pysignal_test.py | 16 |
2 files changed, 66 insertions, 0 deletions
diff --git a/libpyside/signalmanager.cpp b/libpyside/signalmanager.cpp index 2640e1e51..7d10f77f4 100644 --- a/libpyside/signalmanager.cpp +++ b/libpyside/signalmanager.cpp @@ -43,6 +43,7 @@ #include <limits> #include <typeresolver.h> #include <basewrapper.h> +#include <conversions.h> #if QSLOT_CODE != 1 || QSIGNAL_CODE != 2 #error QSLOT_CODE and/or QSIGNAL_CODE changed! change the hardcoded stuff to the correct value! @@ -51,6 +52,44 @@ #define PYSIDE_SIGNAL '2' #include "globalreceiver.h" +#define PYTHON_TYPE "PyObject" + + +// Use this to wrap PyObject during the Signal/Slot handling +struct PyObjectWrapper +{ + PyObject* m_me; + PyObjectWrapper(PyObject* me) : m_me(me) {} + PyObjectWrapper() : m_me(Py_None) {} + operator PyObject*() const { return m_me; } +}; + +Q_DECLARE_METATYPE(PyObjectWrapper) + +namespace Shiboken { + +template<> +struct Converter<PyObjectWrapper> +{ + static PyObjectWrapper toCpp(PyObject* obj) + { + return PyObjectWrapper(obj); + } + + static PyObject* toPython(void* obj) + { + return toPython(*reinterpret_cast<PyObjectWrapper*>(obj)); + } + + static PyObject* toPython(const PyObjectWrapper& obj) + { + return obj; + } +}; + +}; + + using namespace PySide; bool PySide::isSignal(const char* signal) @@ -157,6 +196,11 @@ SignalManager::SignalManager() : m_d(new SignalManagerPrivate) { // Register Qt primitive typedefs used on signals. using namespace Shiboken; + + // Register PyObject type to use in queued signal and slot connections + qRegisterMetaType<PyObjectWrapper>(PYTHON_TYPE); + + TypeResolver::createValueTypeResolver<PyObjectWrapper>(PYTHON_TYPE); TypeResolver::createValueTypeResolver<qint8>("qint8"); TypeResolver::createValueTypeResolver<qint16>("qint16"); TypeResolver::createValueTypeResolver<qint32>("qint32"); @@ -228,11 +272,15 @@ static bool emitNormalSignal(QObject* source, int signalIndex, const char* signa for (int i = 0; i < argsGiven; ++i) signalArgs[i+1] = Shiboken::TypeResolver::get(qPrintable(argTypes[i]))->toCpp(PySequence_GetItem(args, i)); + QMetaObject::activate(source, signalIndex, signalArgs); + // FIXME: This will cause troubles with non-direct connections. for (int i = 0; i < argsGiven; ++i) Shiboken::TypeResolver::get(qPrintable(argTypes[i]))->deleteObject(signalArgs[i+1]); + delete[] signalArgs; + return true; } @@ -272,8 +320,10 @@ int PySide::SignalManager::qt_metacall(QObject* object, QMetaObject::Call call, } else { // call python slot Shiboken::GilState gil; + QList<QByteArray> paramTypes = method.parameterTypes(); PyObject* self = Shiboken::BindingManager::instance().retrieveWrapper(object); + Shiboken::AutoDecRef preparedArgs(PyTuple_New(paramTypes.count())); for (int i = 0, max = paramTypes.count(); i < max; ++i) { diff --git a/tests/signals/pysignal_test.py b/tests/signals/pysignal_test.py index 5f7fc85a2..5d4b09feb 100644 --- a/tests/signals/pysignal_test.py +++ b/tests/signals/pysignal_test.py @@ -15,6 +15,22 @@ class Dummy(QObject): def __init__(self, parent=None): QObject.__init__(self, parent) + def callDummy(self): + self.emit(SIGNAL("dummy(PyObject)"), "PyObject") + + +class PyObjectType(unittest.TestCase): + def mySlot(self, arg): + self.assertEqual(arg, "PyObject") + self.called = True + + def testType(self): + self.called = False + o = Dummy() + o.connect(SIGNAL("dummy(PyObject)"), self.mySlot) + o.callDummy() + self.assert_(self.called) + class PythonSigSlot(unittest.TestCase): def setUp(self): self.called = False |