from pyqthelper import PyQtHelper, extractSignature, isSignal
import unittest
from PyQt4.QtCore import SIGNAL, SLOT, pyqtSignature, QObject


class Receiver(PyQtHelper):
    def __init__(self):
        PyQtHelper.__init__(self)
        self.reset()

    def reset(self):
        self.received = {"simple()": 0, "signed(int)": 0}

    def simpleSlot(self):
        self.received["simple()"] += 1

    @pyqtSignature("int")
    def signedSlot(self, value):
        self.received["signed(int)"] += 1

    def assertSignalReceived(self, signal, times=None):
        if times is None:
            if not self.received[signal]:
                raise AssertionError("signal '%s' did not arrive" % signal)
        else:
            if not self.received[signal] == times:
                raise AssertionError("signal '%s' should have been received "
                        "%i time(s), but got it %i time(s)" %
                        (signal, times, self.received[signal]))

    def assertSignalNotReceived(self, signal):
        if self.received[signal]:
            raise AssertionError("signal '%s' should not have been received" % 
                    signal)


class Emitter(PyQtHelper):
    def send(self):
        self.emit(SIGNAL("simple()"))
        self.emit(SIGNAL("signed(int)"), 1)


class PyQtHelperTests(unittest.TestCase):
    def testExtractSignature(self):
        signal = SIGNAL("signal(int, int)")
        self.assertEqual(extractSignature(signal), "int,int")

    def testIsSignal(self):
        def func():
            pass
        self.assert_(isSignal(SIGNAL("")))
        self.assert_(not isSignal(SLOT("")))
        self.assert_(not isSignal(func))

    def testConnectionMethods(self):
        emitter = Emitter()
        repeater = PyQtHelper()
        receiver = Receiver()
        receiver2 = Receiver()
        
        # First see if connection works (with both signed and simple signals)
        receiver.reset()
        receiver2.reset()
        receiver.connect(emitter, SIGNAL("simple()"), receiver.simpleSlot)
        receiver.connect(emitter, SIGNAL("signed(int)"), receiver.signedSlot)
        emitter.send()
        receiver.assertSignalReceived("simple()")
        receiver.assertSignalReceived("signed(int)")

        # Try selective disconnectAll
        receiver.reset()
        receiver2.reset()
        receiver.connect(emitter, SIGNAL("simple()"), receiver2.simpleSlot)
        PyQtHelper.disconnectAll(emitter, receiver)
        emitter.send()
        receiver2.assertSignalReceived("simple()")
        receiver.assertSignalNotReceived("simple()")
        receiver.assertSignalNotReceived("signed(int)")

        # Try to disconnect everything
        receiver.reset()
        receiver2.reset()
        PyQtHelper.disconnectAll(emitter)
        emitter.send()
        receiver2.assertSignalNotReceived("simple()")
        receiver.assertSignalNotReceived("simple()")
        receiver.assertSignalNotReceived("signed(int)")

        # And finally try a simple disconnect
        receiver.reset()
        receiver2.reset()
        receiver.connect(emitter, SIGNAL("simple()"), receiver.simpleSlot)
        receiver.connect(emitter, SIGNAL("simple()"), receiver2.simpleSlot)
        PyQtHelper.disconnect(emitter, SIGNAL("simple()"), receiver.simpleSlot)
        emitter.send()
        receiver.assertSignalNotReceived("simple()")
        receiver2.assertSignalReceived("simple()")

        # Try SIGNAL to SIGNAL connection and disconnection
        receiver.reset()
        PyQtHelper.disconnectAll(emitter)
        repeater.connect(emitter, SIGNAL("simple()"), SIGNAL("simple()"))
        receiver.connect(repeater, SIGNAL("simple()"), receiver.simpleSlot)
        emitter.send()
        receiver.assertSignalReceived("simple()")
        repeater.disconnect(emitter, SIGNAL("simple()"), SIGNAL("simple()"))
        receiver.reset()
        emitter.send()
        receiver.assertSignalNotReceived("simple()")

    def testMultipleConnections(self):
        def testSignalToSlot(cls):
            emitter = Emitter()
            repeater = PyQtHelper()
            receiver = Receiver()

            receiver.connect(emitter, SIGNAL("simple()"), receiver.simpleSlot)
            receiver.connect(emitter, SIGNAL("simple()"), receiver.simpleSlot)
            emitter.send()
            receiver.assertSignalReceived("simple()", 2)

            receiver.reset()
            cls.disconnect(emitter, SIGNAL("simple()"), receiver.simpleSlot)
            emitter.send()
            receiver.assertSignalReceived("simple()", 1)

        def testSignalToSignal():
            emitter = Emitter()
            repeater = PyQtHelper()
            receiver = Receiver()

            receiver.reset()
            repeater.connect(emitter, SIGNAL("simple()"), SIGNAL("simple()"))
            repeater.connect(emitter, SIGNAL("simple()"), SIGNAL("simple()"))
            receiver.connect(repeater, SIGNAL("simple()"), receiver.simpleSlot)
            emitter.send()
            receiver.assertSignalReceived("simple()", 2)

            receiver.reset()
            PyQtHelper.disconnect(emitter, SIGNAL("simple()"),
                    SIGNAL("simple()"))
            emitter.send()
            receiver.assertSignalReceived("simple()", 1)

        # QObject and PyQtHelper should behave the same
        testSignalToSlot(QObject)
        testSignalToSlot(PyQtHelper)
        testSignalToSignal()


suite = unittest.makeSuite(PyQtHelperTests)
