diff options
author | Hugo Parente Lima <hugo.pl@gmail.com> | 2011-07-27 19:24:54 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-08 16:54:40 -0300 |
commit | 7a5d2e693bdfde21c58b252e6c0c35def1a64e53 (patch) | |
tree | d520bf43e8b1ba6dd591d87f53535d8c335189c5 | |
parent | aa091e00ef71fb309844de900dd9a8248d62af14 (diff) |
Fix bug 941 - "Signals with QtCore.Qt types as arguments has invalid signatures"
Reviewer: Renato Araújo <renato.filho@openbossa.org>
Luciano Wolf <luciano.wolf@openbossa.org>
-rw-r--r-- | libpyside/pysidesignal.cpp | 53 | ||||
-rw-r--r-- | libpyside/pysidesignal.h | 11 | ||||
-rw-r--r-- | tests/QtGui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/QtGui/bug_941.py | 17 | ||||
-rw-r--r-- | tests/pysidetest/typesystem_pysidetest.xml | 19 |
5 files changed, 84 insertions, 17 deletions
diff --git a/libpyside/pysidesignal.cpp b/libpyside/pysidesignal.cpp index 290ea84bc..782aeb5b7 100644 --- a/libpyside/pysidesignal.cpp +++ b/libpyside/pysidesignal.cpp @@ -731,6 +731,59 @@ PySideSignal* newObject(const char* name, ...) return self; } +template<typename T> +static typename T::value_type join(T t, const char* sep) +{ + typename T::value_type res; + if (!t.size()) + return res; + + typename T::const_iterator it = t.begin(); + typename T::const_iterator end = t.end(); + res += *it; + ++it; + + while (it != end) { + res += sep; + res += *it; + ++it; + } + return res; +} + +void registerSignals(SbkObjectType* pyObj, const QMetaObject* metaObject) +{ + typedef QHash<QByteArray, QList<QByteArray> > SignalSigMap; + SignalSigMap signalsFound; + for(int i = metaObject->methodOffset(), max = metaObject->methodCount(); i < max; ++i) { + QMetaMethod method = metaObject->method(i); + QByteArray methodName(method.signature()); + methodName.chop(methodName.size() - methodName.indexOf('(')); + + if (method.methodType() == QMetaMethod::Signal) + signalsFound[methodName] << join(method.parameterTypes(), ","); + } + + SignalSigMap::Iterator it = signalsFound.begin(); + SignalSigMap::Iterator end = signalsFound.end(); + for (; it != end; ++it) { + PySideSignal* self = PyObject_New(PySideSignal, &PySideSignalType); + self->signalName = strdup(it.key().constData()); + self->signaturesSize = 0; + self->signatures = 0; + self->initialized = 0; + self->homonymousMethod = 0; + + qSort(it.value().begin(), it.value().end()); + SignalSigMap::mapped_type::const_iterator j = it.value().begin(); + SignalSigMap::mapped_type::const_iterator endJ = it.value().end(); + for (; j != endJ; ++j) + appendSignature(self, strdup(j->constData())); + addSignalToWrapper(pyObj, it.key(), self); + Py_DECREF((PyObject*) self); + } +} + PyObject* buildQtCompatible(const char* signature) { diff --git a/libpyside/pysidesignal.h b/libpyside/pysidesignal.h index d0efe16ab..65c2ef39d 100644 --- a/libpyside/pysidesignal.h +++ b/libpyside/pysidesignal.h @@ -57,10 +57,16 @@ PYSIDE_API bool checkType(PyObject* type); * @param name of the Signal to be registered on meta object * @param signatures a list of signatures supported by this signal, ended with a NULL pointer * @return Return a new reference to PyObject* of type PySideSignal + * @deprecated Use registerSignals **/ PYSIDE_API PySideSignal* newObject(const char* name, ...); /** + * Register all C++ signals of a QObject on Python type. + */ +PYSIDE_API void registerSignals(SbkObjectType* pyObj, const QMetaObject* metaObject); + +/** * This function creates a Signal object which stay attached to QObject class based on a list of QMetaMethod * * @param source of the Signal to be registered on meta object @@ -104,10 +110,7 @@ PYSIDE_API const char* getSignature(PySideSignalInstance* signal); PYSIDE_API void updateSourceObject(PyObject* source); /** - * This function is used to retrieve the signal signature - * - * @param self The Signal object - * @return Return the signal signature + * @deprecated Use registerSignals **/ PYSIDE_API void addSignalToWrapper(SbkObjectType* wrapperType, const char* signalName, PySideSignal* signal); diff --git a/tests/QtGui/CMakeLists.txt b/tests/QtGui/CMakeLists.txt index 99e688bfe..9e5b0c3de 100644 --- a/tests/QtGui/CMakeLists.txt +++ b/tests/QtGui/CMakeLists.txt @@ -68,6 +68,7 @@ PYSIDE_TEST(bug_879.py) PYSIDE_TEST(bug_882.py) PYSIDE_TEST(bug_919.py) PYSIDE_TEST(bug_921.py) +PYSIDE_TEST(bug_941.py) PYSIDE_TEST(customproxywidget_test.py) PYSIDE_TEST(deepcopy_test.py) PYSIDE_TEST(event_filter_test.py) diff --git a/tests/QtGui/bug_941.py b/tests/QtGui/bug_941.py new file mode 100644 index 000000000..cdf119012 --- /dev/null +++ b/tests/QtGui/bug_941.py @@ -0,0 +1,17 @@ +import unittest +from PySide.QtCore import * +from PySide.QtGui import * + +def foo(a, b): + pass + +class TestBug941 (unittest.TestCase): + + def testIt(self): + app = QApplication([]) + view = QHeaderView(Qt.Horizontal) + self.assertTrue(view.sortIndicatorChanged.connect(foo)) + view.sortIndicatorChanged.emit(0, Qt.Vertical) # this can't raise an exception! + +if __name__ == '__main__': + unittest.main() diff --git a/tests/pysidetest/typesystem_pysidetest.xml b/tests/pysidetest/typesystem_pysidetest.xml index c63d5e192..88cbf03af 100644 --- a/tests/pysidetest/typesystem_pysidetest.xml +++ b/tests/pysidetest/typesystem_pysidetest.xml @@ -4,30 +4,23 @@ <load-typesystem name="typesystem_gui.xml" generate="no"/> <object-type name="TestObject" /> - <inject-code> + <inject-code position="end"> + Shiboken::TypeResolver::createObjectTypeResolver< ::PySideCPP2::TestObjectWithoutNamespace>("TestObjectWithoutNamespace*"); + Shiboken::TypeResolver::createValueTypeResolver< ::PySideCPP2::PySideLong>("PySideLong"); + Shiboken::TypeResolver::createObjectTypeResolver< ::PySideCPP::TestObjectWithNamespace>("TestObjectWithNamespace*"); + Shiboken::TypeResolver::createValueTypeResolver< ::PySideInt>("PySideInt"); qRegisterMetaType<PySideInt>("PySideInt"); qRegisterMetaType<PySideCPP2::PySideLong>("PySideLong"); </inject-code> <namespace-type name="PySideCPP"> - <object-type name="TestObjectWithNamespace" > - <modify-function signature="emitSignal(PySideCPP::TestObjectWithNamespace*)"> - <modify-argument index="1"> - <replace-type modified-type="TestObjectWithNamespace*"/> - </modify-argument> - </modify-function> - </object-type> + <object-type name="TestObjectWithNamespace" /> </namespace-type> <namespace-type name="PySideCPP2" generate="no"> <enum-type name="Enum1" /> <object-type name="TestObjectWithoutNamespace" > <enum-type name="Enum2" /> - <modify-function signature="emitSignalWithNamespace(PySideCPP2::TestObjectWithoutNamespace*)"> - <modify-argument index="1"> - <replace-type modified-type="PySideCPP2::TestObjectWithoutNamespace*"/> - </modify-argument> - </modify-function> </object-type> </namespace-type> |