aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Parente Lima <hugo.pl@gmail.com>2011-07-27 19:24:54 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:54:40 -0300
commit7a5d2e693bdfde21c58b252e6c0c35def1a64e53 (patch)
treed520bf43e8b1ba6dd591d87f53535d8c335189c5
parentaa091e00ef71fb309844de900dd9a8248d62af14 (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.cpp53
-rw-r--r--libpyside/pysidesignal.h11
-rw-r--r--tests/QtGui/CMakeLists.txt1
-rw-r--r--tests/QtGui/bug_941.py17
-rw-r--r--tests/pysidetest/typesystem_pysidetest.xml19
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&lt; ::PySideCPP2::TestObjectWithoutNamespace>("TestObjectWithoutNamespace*");
+ Shiboken::TypeResolver::createValueTypeResolver&lt; ::PySideCPP2::PySideLong>("PySideLong");
+ Shiboken::TypeResolver::createObjectTypeResolver&lt; ::PySideCPP::TestObjectWithNamespace>("TestObjectWithNamespace*");
+ Shiboken::TypeResolver::createValueTypeResolver&lt; ::PySideInt>("PySideInt");
qRegisterMetaType&lt;PySideInt>("PySideInt");
qRegisterMetaType&lt;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>