Update to the new smokegenerator.
Annotate for file src/signal-slot/connect.lisp
2010-01-10 tobias 1 (in-package :cl-smoke.qt-impl)
08:52:49 ' 2
' 3 (defgeneric qt:connect (qsignal slot &optional type)
' 4 (:documentation "Connects a signal to a slot."))
' 5
' 6 (defgeneric qt:disconnect (qsignal slot)
' 7 (:documentation "Disconnects a connection."))
' 8
' 9 (defgeneric qt:disconnect-all (qsignal)
' 10 (:documentation "Disconnects all connections of QSIGNAL."))
' 11
' 12 (defun check-argument-types (signal-arguments slot-arguments)
' 13 (assert (= (length signal-arguments) (length slot-arguments)))
' 14 (loop for signal-arg in signal-arguments
' 15 for slot-arg in slot-arguments do
' 16 (if (typep signal-arg 'smoke::smoke-type)
' 17 (assert (smoke-type= signal-arg slot-arg))
' 18 (assert (subtypep signal-arg slot-arg)))))
' 19
' 20 ;;FIXME check argument-types
' 21 (defmethod qt:connect ((qsignal qsignal) (qslot qslot) &optional type)
' 22 (assert (or (slot-boundp (signal-object qsignal) 'argument-types)
' 23 (slot-boundp qslot 'arguments))
' 24 ((slot-value (signal-object qsignal) 'argument-types)
' 25 (slot-value qslot 'arguments))
' 26 "Argument types must be specified for at least on of
' 27 ~A and ~A." qsignal qslot)
' 28 (when (not (slot-boundp (signal-object qsignal) 'argument-types))
' 29 (setf (argument-types (signal-object qsignal))
' 30 (arguments qslot)))
' 31 (when (not (slot-boundp qslot 'arguments))
' 32 (setf (slot-value qslot 'arguments)
' 33 (argument-types (signal-object qsignal))))
' 34 (check-argument-types (argument-types (signal-object qsignal))
' 35 (arguments qslot))
' 36 (unless (connect-id (signal-object qsignal) (id (signal-object qsignal))
' 37 qslot (id qslot)
' 38 type
' 39 (types (arguments qslot)))
' 40 (cerror "Failed to connect ~S to ~S." qsignal qslot)))
' 41
' 42 (defmethod qt:connect ((sender qsignal) (function function) &optional type)
' 43 (let ((slot (make-instance 'qslot
' 44 :arg0 (signal-object sender)
' 45 :argument-types (argument-types (signal-object sender))
' 46 :slot-function function)))
' 47
' 48 (unless (connect-id (signal-object sender) (id (signal-object sender))
' 49 slot (id slot)
' 50 type
' 51 (types (argument-types (signal-object sender))))
' 52 (cerror "Failed to connect the function ~S to the signal ~S."
' 53 function sender))))
' 54
' 55 (defclass qt-signal-slot-name ()
' 56 ((name :initarg :name
' 57 :reader name)))
' 58
' 59 (defclass qt-signal (qt-signal-slot-name)
' 60 ((sender :initarg :sender
' 61 :reader qsender))
' 62 (:documentation "Qt C++ signal."))
' 63
' 64 (defclass qt-slot (qt-signal-slot-name)
' 65 ((receiver :initarg :receiver
' 66 :reader receiver))
' 67 (:documentation "Qt C++ slot."))
' 68
' 69 (defmethod print-object ((qt-signal qt-signal) stream)
' 70 (print-unreadable-object (qt-signal stream :type t :identity t)
' 71 (when (slot-boundp qt-signal 'sender)
' 72 (princ (qsender qt-signal) stream))
' 73 (princ " " stream)
' 74 (when (slot-boundp qt-signal 'name)
' 75 (princ (name qt-signal) stream))))
' 76
' 77 (defgeneric qt:get-slot (receiver name)
' 78 (:documentation "Returns the slot of RECEIVER with NAME.")
' 79 (:method (receiver name)
' 80 (make-instance 'qt-slot :receiver receiver :name name))
' 81 (:method (receiver (function function))
' 82 "Returns a slot for RECEIVER that calls function
' 83 with RECEIVER as the first argument."
' 84 (make-instance 'qslot
' 85 :arg0 receiver
' 86 :slot-function #'(lambda (&rest args)
' 87 (apply function (cxx:parent *this*)
' 88 args)))))
' 89
' 90 (define-compiler-macro qt:get-slot (&whole form receiver name)
' 91 "Normalize the slot name."
' 92 (if (stringp name)
' 93 (let ((normalized-name (cxx:data
' 94 (qt:meta-object.normalized-signature name))))
' 95 (if (string= name normalized-name) ;; Avoid infinite recursion
' 96 form
' 97 `(qt:get-slot ,receiver ,normalized-name)))
' 98 form))
' 99
' 100 (defun qt:get-signal (sender name)
' 101 "Returns the signal NAME of SENDER."
' 102 (make-instance 'qt-signal :sender sender :name name))
' 103
' 104 (define-compiler-macro qt:get-signal (&whole form sender name)
' 105 "Normalize the signal name."
' 106 (if (stringp name)
' 107 (let ((normalized-name (cxx:data
' 108 (qt:meta-object.normalized-signature name))))
' 109 (if (string= name normalized-name) ;; Avoid infinite recursion
' 110 form
' 111 `(qt:get-signal ,sender ,normalized-name)))
' 112 form))
' 113
' 114 (defmethod qt:connect ((qt-signal qt-signal) (qt-slot qt-slot) &optional type)
' 115 (unless (qt:object.connect (qsender qt-signal) (qt:qsignal (name qt-signal))
' 116 (receiver qt-slot) (qt:qslot (name qt-slot))
2009-08-27 tobias 117 (or type qt:+auto-connection+))
2010-01-10 tobias 118 (cerror "Failed to connect ~A ~A to ~A ~A."
08:52:49 ' 119 (qsender qt-signal) (name qt-signal)
' 120 (receiver qt-slot) (name qt-slot))))
' 121
' 122 (defmethod qt:disconnect ((qt-signal qt-signal) (qt-slot qt-slot))
' 123 (unless (qt:object.disconnect (qsender qt-signal) (qt:qsignal (name qt-signal))
' 124 (receiver qt-slot) (qt:qslot (name qt-slot)))
' 125 (cerror "Failed to disconnect ~A ~A from ~A ~A."
' 126 (receiver qt-slot) (name qt-slot)
' 127 (qsender qt-signal) (name qt-signal))))
' 128
' 129 (defmethod qt:disconnect-all ((sender qt:object))
' 130 (unless (qt:object.disconnect sender 0 0 0)
' 131 (cerror "Failed to disconnect everything connected to ~A."
' 132 sender)))
' 133
' 134
' 135 (defmethod qt:connect ((qt-signal qt-signal) (function function) &optional type)
' 136 (let* ((signal-id (find-signal-id (qsender qt-signal) (name qt-signal)))
' 137 (slot (make-instance 'qslot
' 138 :arg0 (qsender qt-signal)
' 139 :slot-function function
' 140 :argument-types
' 141 (method-arguments-type
' 142 (cxx:meta-object (qsender qt-signal))
' 143 signal-id))))
' 144 ;; Ensure that the slot is not gc'ed as long as the QT-SIGNAL
' 145 ;; exists.
' 146 ;;
' 147 ;; FIXME: remove on disconnect.
' 148 ;; This no not critical because the slot
' 149 ;; object is not accessible to the user,
' 150 ;; who thus can not connect it to other
' 151 ;; signals.
' 152 (if (connect-id (qsender qt-signal) signal-id
' 153 slot (id slot)
' 154 type (types (arguments slot)))
' 155 (cxx:connect-notify (qsender qt-signal)
' 156 (name qt-signal))
' 157 (cerror "Ignore" "Failed to connect the signal ~S of ~S to the function ~S."
' 158 (name qt-signal) (qsender qt-signal) function))))
' 159
' 160 (defmethod qt:connect ((qt-signal qt-signal) (slot qslot) &optional type)
' 161 (let ((signal-id (find-signal-id (qsender qt-signal) (name qt-signal))))
' 162 (if (slot-boundp slot 'arguments)
' 163 (check-argument-types (method-arguments-type (cxx:meta-object
' 164 (qsender qt-signal))
' 165 signal-id)
' 166 (arguments slot))
' 167 (setf (slot-value slot 'arguments)
' 168 (method-arguments-type (cxx:meta-object (qsender qt-signal))
' 169 signal-id)))
' 170 (if (connect-id (qsender qt-signal) signal-id
' 171 slot (id slot)
' 172 type (types (arguments slot)))
' 173 (cxx:connect-notify (qsender qt-signal)
' 174 (name qt-signal))
' 175 (cerror "Ignore" "Failed to connect the signal ~S of ~S to the slot ~S."
' 176 (name qt-signal) (qsender qt-signal) slot))))
' 177
' 178 (defmethod qt:connect ((qsignal qsignal) (slot qt-slot) &optional type)
' 179 (let ((slot-id (find-slot-id (receiver slot) (name slot))))
' 180 (if (slot-boundp (signal-object qsignal) 'argument-types)
' 181 (check-argument-types (argument-types (signal-object slot))
' 182 (method-arguments-type (cxx:meta-object
' 183 (receiver slot))
' 184 slot-id))
' 185 (setf (argument-types (signal-object qsignal))
' 186 (method-arguments-type (cxx:meta-object (receiver slot))
' 187 slot-id)))
' 188 (unless (connect-id (signal-object qsignal) (id (signal-object qsignal))
' 189 (receiver slot) slot-id
' 190 type
' 191 (types (argument-types (signal-object qsignal))))
' 192 (cerror "Failed to connect ~S to ~S." qsignal slot))))
' 193
' 194
' 195 (defun connect-id (sender signal-id receiver slot-id type types)
' 196 (qt:meta-object.connect sender signal-id
' 197 receiver slot-id
' 198 (if (null type)
2009-08-27 tobias 199 qt:+auto-connection+
08:37:36 ' 200 type)
2010-01-10 tobias 201 types))
08:52:49 ' 202
' 203 (defun disconnect-id (sender signal-id receiver slot-id)
' 204 (qt:meta-object.disconnect sender signal-id receiver slot-id))