1#############################################################################
2##
3## Copyright (C) 2016 The Qt Company Ltd.
4## Contact: https://www.qt.io/licensing/
5##
6## This file is part of the test suite of Qt for Python.
7##
8## $QT_BEGIN_LICENSE:GPL-EXCEPT$
9## Commercial License Usage
10## Licensees holding valid commercial Qt licenses may use this file in
11## accordance with the commercial license agreement provided with the
12## Software or, alternatively, in accordance with the terms contained in
13## a written agreement between you and The Qt Company. For licensing terms
14## and conditions see https://www.qt.io/terms-conditions. For further
15## information use the contact form at https://www.qt.io/contact-us.
16##
17## GNU General Public License Usage
18## Alternatively, this file may be used under the terms of the GNU
19## General Public License version 3 as published by the Free Software
20## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21## included in the packaging of this file. Please review the following
22## information to ensure the GNU General Public License requirements will
23## be met: https://www.gnu.org/licenses/gpl-3.0.html.
24##
25## $QT_END_LICENSE$
26##
27#############################################################################
28
29import os
30import sys
31import unittest
32
33sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
34from init_paths import init_test_paths
35init_test_paths(False)
36
37from PySide2.QtCore import QObject, SIGNAL, SLOT, Qt
38
39try:
40    from PySide2.QtWidgets import QSpinBox, QApplication, QWidget
41    hasQtGui = True
42except ImportError:
43    hasQtGui = False
44
45from helper.usesqapplication import UsesQApplication
46
47class Dummy(QObject):
48    """Dummy class used in this test."""
49    def __init__(self, parent=None):
50        QObject.__init__(self, parent)
51
52    def callDummy(self):
53        self.emit(SIGNAL("dummy(PyObject)"), "PyObject")
54
55    def callDummy2(self):
56        lst = []
57        lst.append("item1")
58        lst.append("item2")
59        lst.append("item3")
60        self.emit(SIGNAL("dummy2(PyObject, PyObject)"), "PyObject0", lst)
61
62
63class PyObjectType(UsesQApplication):
64    def mySlot(self, arg):
65        self.assertEqual(arg, "PyObject")
66        self.called = True
67        self.callCount += 1
68
69    def mySlot2(self, arg0, arg1):
70        self.assertEqual(arg0, "PyObject0")
71        self.assertEqual(arg1[0], "item1")
72        self.assertEqual(arg1[1], "item2")
73        self.assertEqual(arg1[2], "item3")
74        self.callCount += 1
75        if self.running:
76            self.app.quit()
77
78    def setUp(self):
79        super(PyObjectType, self).setUp()
80        self.callCount = 0
81        self.running = False
82
83    def testWithOneArg(self):
84        o = Dummy()
85        o.connect(SIGNAL("dummy(PyObject)"), self.mySlot)
86        o.callDummy()
87        self.assertEqual(self.callCount, 1)
88
89    def testWithTwoArg(self):
90        o = Dummy()
91        o.connect(SIGNAL("dummy2(PyObject,PyObject)"), self.mySlot2)
92        o.callDummy2()
93        self.assertEqual(self.callCount, 1)
94
95    def testAsyncSignal(self):
96        self.called = False
97        self.running = True
98        o = Dummy()
99        o.connect(SIGNAL("dummy2(PyObject,PyObject)"), self.mySlot2, Qt.QueuedConnection)
100        o.callDummy2()
101        self.app.exec_()
102        self.assertEqual(self.callCount, 1)
103
104    def testTwice(self):
105        self.called = False
106        self.running = True
107        o = Dummy()
108        o.connect(SIGNAL("dummy2(PyObject,PyObject)"), self.mySlot2, Qt.QueuedConnection)
109        o.callDummy2()
110        o.callDummy2()
111        self.app.exec_()
112        self.assertEqual(self.callCount, 2)
113
114class PythonSigSlot(unittest.TestCase):
115    def setUp(self):
116        self.called = False
117
118    def tearDown(self):
119        try:
120            del self.args
121        except:
122            pass
123
124    def callback(self, *args):
125        if tuple(self.args) == args:
126            self.called = True
127
128    def testNoArgs(self):
129        """Python signal and slots without arguments"""
130        obj1 = Dummy()
131
132        QObject.connect(obj1, SIGNAL('foo()'), self.callback)
133        self.args = tuple()
134        obj1.emit(SIGNAL('foo()'), *self.args)
135
136        self.assertTrue(self.called)
137
138    def testWithArgs(self):
139        """Python signal and slots with integer arguments"""
140        obj1 = Dummy()
141
142        QObject.connect(obj1, SIGNAL('foo(int)'), self.callback)
143        self.args = (42,)
144        obj1.emit(SIGNAL('foo(int)'), *self.args)
145
146        self.assertTrue(self.called)
147
148
149    def testDisconnect(self):
150        obj1 = Dummy()
151
152        QObject.connect(obj1, SIGNAL('foo(int)'), self.callback)
153        QObject.disconnect(obj1, SIGNAL('foo(int)'), self.callback)
154
155        self.args = (42, )
156        obj1.emit(SIGNAL('foo(int)'), *self.args)
157
158        self.assertTrue(not self.called)
159
160
161if hasQtGui:
162    class SpinBoxPySignal(UsesQApplication):
163        """Tests the connection of python signals to QSpinBox qt slots."""
164
165        def setUp(self):
166            super(SpinBoxPySignal, self).setUp()
167            self.obj = Dummy()
168            self.spin = QSpinBox()
169            self.spin.setValue(0)
170
171        def tearDown(self):
172            super(SpinBoxPySignal, self).tearDown()
173            del self.obj
174            del self.spin
175
176        def testValueChanged(self):
177            """Emission of a python signal to QSpinBox setValue(int)"""
178            QObject.connect(self.obj, SIGNAL('dummy(int)'), self.spin, SLOT('setValue(int)'))
179            self.assertEqual(self.spin.value(), 0)
180
181            self.obj.emit(SIGNAL('dummy(int)'), 4)
182            self.assertEqual(self.spin.value(), 4)
183
184        def testValueChangedMultiple(self):
185            """Multiple emissions of a python signal to QSpinBox setValue(int)"""
186            QObject.connect(self.obj, SIGNAL('dummy(int)'), self.spin, SLOT('setValue(int)'))
187            self.assertEqual(self.spin.value(), 0)
188
189            self.obj.emit(SIGNAL('dummy(int)'), 4)
190            self.assertEqual(self.spin.value(), 4)
191
192            self.obj.emit(SIGNAL('dummy(int)'), 77)
193            self.assertEqual(self.spin.value(), 77)
194
195
196if hasQtGui:
197    class WidgetPySignal(UsesQApplication):
198        """Tests the connection of python signals to QWidget qt slots."""
199
200        def setUp(self):
201            super(WidgetPySignal, self).setUp()
202            self.obj = Dummy()
203            self.widget = QWidget()
204
205        def tearDown(self):
206            super(WidgetPySignal, self).tearDown()
207            del self.obj
208            del self.widget
209
210        def testShow(self):
211            """Emission of a python signal to QWidget slot show()"""
212            self.widget.hide()
213
214            QObject.connect(self.obj, SIGNAL('dummy()'), self.widget, SLOT('show()'))
215            self.assertTrue(not self.widget.isVisible())
216
217            self.obj.emit(SIGNAL('dummy()'))
218            self.assertTrue(self.widget.isVisible())
219
220if __name__ == '__main__':
221    unittest.main()
222