2.2. Signals and Slots

A simple example using Qt Signals and Slots is as follows:

module Main where

import Qtc.Classes.Qccs
import Qtc.Classes.Gui
import Qtc.ClassTypes.Gui
import Qtc.Core.Base
import Qtc.Gui.Base
import Qtc.Gui.QApplication
import Qtc.Gui.QWidget
import Qtc.Gui.QPushButton
import Qtc.Gui.QAbstractButton
import Qtc.Gui.QMessageBox

type MyQPushButton = QPushButtonSc (CMyQPushButton)
data CMyQPushButton = CMyQPushButton

myQPushButton :: String -> IO (MyQPushButton)
myQPushButton b = qSubClass $ qPushButton b

main :: IO Int
main = do
  qApplication ()
  hello <- myQPushButton "Hello qtHaskell World"
  resize hello (200::Int, 60::Int)
  mb <- qMessageBox hello 
  connectSlot hello "clicked()" hello "click()" $ on_hello_clicked mb
  qshow hello ()
  qApplicationExec ()

on_hello_clicked :: QMessageBox () -> MyQPushButton -> IO ()
on_hello_clicked mb this
  = do
  tt <- text this ()
  setText mb $ "You have clicked " ++ tt
  qshow mb ()

Slots are connected to Signals using the connectSlot statement. This has the general format:

connectSlot signal_object "signal_signature" slot_object "slot_signature" slot_function

Both the signal_object and slot_object must be previously declared Qt objects.

The "signal_signature" and "slot_signature" strings describe the name and parameter types of the signal and slot to be connected. The parameter types must be the same for both strings.

The slot_function is a partial application of a Haskell function of type:

global_Haskell_parameters -> slot_object_type -> slot_parameters

Both the signal and slot can be "built in" signal/slots of their respective Qt classes, or custom signal/slots, in which case there is no need to declare them prior to use in a connectSlot statement. If the slot is a "built in" slot of the Qt slot_object class, no slot_function is required but the connectSlot statement must still be terminated by an empty pair of parentheses.

Signals can be connected to other signals using the connectSignal statement. This has the general format:

connectSignal first_signal_object "first_signal_signature" second_signal_object "second_signal_signature"

In all the above cases the format of signal/slot signature strings is same as for the SIGNAL and SLOT macros used in C++ Qt programs.

If custom signals or slots are required for a class, the class must be subclassed. This is a two stage process. Firstly, create a new shadow type based on the Qt class to be subclassed, then create a constructor (or constructor class) that uses qSubClass to call the constructor of the base class.

In the above example we see how to subclass the Qt class "QPushButton" to create a custom slot "click()". This has the general formula:

type MySubClassType = QBaseClassTypeSc (CMySubClassType)

data CMySubClassType = CMySubClassType

mySubClassType :: p1Type -> p2Type ... -> IO (MySubClassType)

mySubClassType p1 p2 ... = qSubClass $ qBaseClasstype p1 p2 ...

N.B. If a "built-in" signal is connected to a custom slot on a different object, the signal object does not have to be subclassed. This is very useful for menus and menubars where we have many objects of type QAction which can connect their "built-in" signal "triggered()" to custom slots on the main application widget object, without having to be subclassed.