1 /**
2  * @file scim_signals.h
3  * @brief C++ signal interface.
4  *
5  * Provides a set of signal class templates you can use to create signals
6  * that can pass up to 6 arguments to signal handlers connected via the
7  * slot interface (see scim_slot.h). The signal classes are named Signal0
8  * to Signal6, where 0 to 6 specifies the number of arguments that can be
9  * passed to a slot.
10  *
11  * Most code of this file are came from Inti project.
12  */
13 
14 /*
15  * Smart Common Input Method
16  *
17  * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
18  * Copyright (c) 2002 The Inti Development Team.
19  * Copyright (c) 2000 Red Hat, Inc.
20  * Copyright 1999, Karl Einar Nelson
21  *
22  *
23  * This library is free software; you can redistribute it and/or
24  * modify it under the terms of the GNU Lesser General Public
25  * License as published by the Free Software Foundation; either
26  * version 2 of the License, or (at your option) any later version.
27  *
28  * This library is distributed in the hope that it will be useful,
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31  * GNU Lesser General Public License for more details.
32  *
33  * You should have received a copy of the GNU Lesser General Public
34  * License along with this program; if not, write to the
35  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
36  * Boston, MA  02111-1307  USA
37  *
38  * $Id: scim_signals.h,v 1.12 2005/01/30 13:24:13 suzhe Exp $
39  */
40 
41 #ifndef __SCIM_SIGNALS_H
42 #define __SCIM_SIGNALS_H
43 
44 namespace scim {
45 
46 /**
47  * @addtogroup SignalSlot
48  * @{
49  */
50 
51 class Signal;
52 
53 //! @class SlotNode
54 //! @brief A node class for managing slots connected to scim::Signal's.
55 
56 class SlotNode : public Node
57 {
58     friend class Signal;
59 
60     SlotNode(Slot *slot);
61     ~SlotNode();
62 
63     bool is_blocked;
64 
65 public:
blocked()66     bool blocked() const { return is_blocked; }
67     //!< Returns true if the slot is blocked.
68 
69     virtual void block();
70     //!< Block signal emission to the slot until unblock is called.
71 
72     virtual void unblock();
73     //!< Unblock the slot so signal emmissions can be received.
74 
75     virtual void disconnect();
76     //!< Disconnect the slot. The slot will no longer recieve signal emissions.
77 };
78 
79 // DefaultMarshal class (from marshal.h, libsigc++)
80 
81 template <typename R>
82 class DefaultMarshal
83 {
84 public:
85     typedef R OutType;
86     typedef R InType;
87 
88 private:
89     OutType value_;
90 
91 public:
DefaultMarshal()92     DefaultMarshal() :value_() {}
93 
value()94     OutType& value() { return value_; }
95 
96     // Return true to stop emission.
marshal(const InType & newval)97     bool marshal(const InType & newval)
98     {
99         value_ = newval;
100         return false;
101     }
102 };
103 
104 // Marshal specialization
105 template <>
106 class DefaultMarshal <bool>
107 {
108 public:
109     typedef bool OutType;
110     typedef bool InType;
111 
112 private:
113     OutType value_;
114 
115 public:
DefaultMarshal()116     DefaultMarshal() :value_(false) {}
117 
value()118     OutType& value() { return value_; }
119 
120     // Return true to stop emission.
marshal(const InType & newval)121     bool marshal(const InType & newval)
122     {
123         value_ = newval;
124         return false;
125     }
126 };
127 
128 //! @class Signal
129 //! @brief Base class for the C++ signal interface.
130 
131 class Signal
132 {
133     Signal(const Signal&);
134     Signal& operator=(const Signal&);
135 
136 protected:
137     typedef std::vector< Pointer<SlotNode> > ConnectionList;
138     //!< ConnectionList type.
139 
140     ConnectionList connection_list;
141     //!< A list of all the slots connected to the signal.
142 
143 public:
144     Signal();
145     //!< Constructor.
146 
147     virtual ~Signal();
148     //!< Destructor.
149 
150     SlotNode* connect(Slot *slot);
151     //!< Creates a new SlotNode for slot and adds it to the <EM>connection_list</EM>.
152 };
153 
154 //! @class Signal0
155 //! @brief A template for a signal passing no arguments and returning a value of type R.
156 
157 template<typename R, typename Marshal = class DefaultMarshal<R> >
158 class Signal0 : public Signal
159 {
160     typedef Signal0<R> Self;
161 
callback(void * data)162     static R callback(void *data)
163     {
164         Self *s = static_cast<Self*>(data);
165         return s->emit();
166     }
167 
168 public:
169     typedef Slot0<R> SlotType;
170     //!< Function signature for handlers connecting the signal.
171 
connect(SlotType * slot)172     Connection connect(SlotType *slot)
173     {
174         return Signal::connect(slot);
175     }
176     //!< Connect a slot to the signal.
177     //!< @param slot - a slot of type Slot0<R>.
178     //!< @return a connection object.
179     //!<
180     //!< <BR>The returned connection object can be used alter or change the connection.
181 
slot()182     SlotType* slot()
183     {
184         return new SignalSlot0<Self, R>(this, &callback);
185     }
186     //!< Returns a slot for this signal.
187     //!< @return a new slot of type Slot0<R>.
188     //!<
189     //!< <BR>The returned slot can be passed to another signal allowing the
190     //!< other signal to call this signal when it gets emitted.
191 
emit()192     R emit()
193     {
194         Marshal m;
195         ConnectionList::iterator i = connection_list.begin();
196         while (i != connection_list.end())
197         {
198             if (!(*i)->blocked())
199             {
200                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
201                 if (slot && m.marshal(slot->call()))
202                     break;
203             }
204             ++i;
205         }
206         return m.value();
207     }
208     //!< Emit the signal.
209     //!< @return the value returned by the signal handler.
210     //!<
211     //!< <BR>Calls every slot connected to this signal, in order of connection.
212 
operator()213     R operator()()
214     {
215         return emit();
216     }
217     //!< Function operator; calls emit().
218 };
219 
220 // Signal0 partially specialized for void return
221 
222 template<typename IgnoreMarshal>
223 class Signal0<void, IgnoreMarshal> : public Signal
224 {
225     typedef Signal0<void, IgnoreMarshal> Self;
226 
callback(void * data)227     static void callback(void *data)
228     {
229         Self *s = static_cast<Self*>(data);
230         s->emit();
231     }
232 
233 public:
234     typedef Slot0<void> SlotType;
235 
connect(SlotType * slot)236     Connection connect(SlotType *slot)
237     {
238         return Signal::connect(slot);
239     }
240 
slot()241     SlotType* slot()
242     {
243         return new SignalSlot0<Self, void>(this, &callback);
244     }
245 
emit()246     void emit()
247     {
248         ConnectionList::iterator i = connection_list.begin();
249         while (i != connection_list.end())
250         {
251             if (!(*i)->blocked())
252             {
253                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
254                 if (slot) slot->call();
255             }
256             ++i;
257         }
258     }
259 
operator()260     void operator()()
261     {
262         emit();
263     }
264 };
265 
266 //! @class Signal1
267 //! @brief A template for a signal passing one argument of type P1 and returning a value of type R.
268 
269 template<typename R, typename P1, typename Marshal = class DefaultMarshal<R> >
270 class Signal1 : public Signal
271 {
272     typedef Signal1<R, P1> Self;
273 
callback(void * data,P1 p1)274     static R callback(void *data, P1 p1)
275     {
276         Self *s = static_cast<Self*>(data);
277         return s->emit(p1);
278     }
279 
280 public:
281     typedef Slot1<R, P1> SlotType;
282     //!< Function signature for handlers connecting to the signal.
283 
connect(SlotType * slot)284     Connection connect(SlotType *slot)
285     {
286         return Signal::connect(slot);
287     }
288     //!< Connect a slot to the signal.
289     //!< @param slot - a slot of type Slot1<R, P1>.
290     //!< @return a connection object.
291     //!<
292     //!< <BR>The returned connection object can be used alter or change the connection.
293 
slot()294     SlotType* slot()
295     {
296         return new SignalSlot1<Self, R, P1>(this, &callback);
297     }
298     //!< Returns a slot for this signal.
299     //!< @return a new slot of type Slot1<R, P1>.
300     //!<
301     //!< <BR>The returned slot can be passed to another signal allowing the
302     //!< other signal to call this signal when it gets emitted.
303 
emit(P1 p1)304     R emit(P1 p1)
305     {
306         Marshal m;
307         ConnectionList::iterator i = connection_list.begin();
308         while (i != connection_list.end())
309         {
310             if (!(*i)->blocked())
311             {
312                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
313                 if (slot && m.marshal(slot->call(p1)))
314                     break;
315             }
316             ++i;
317         }
318         return m.value();
319     }
320     //!< Emit the signal.
321     //!< @param p1 - passes p1 to the signal handler.
322     //!< @return the value returned by the signal handler.
323     //!<
324     //!< <BR>Calls every slot connected to this signal, in order of connection.
325 
operator()326     R operator()(P1 p1)
327     {
328         return emit(p1);
329     }
330     //!< Function operator; calls emit().
331 };
332 
333 // Signal1 partially specialized for void return
334 
335 template<typename P1, typename IgnoreMarshal>
336 class Signal1<void, P1, IgnoreMarshal> : public Signal
337 {
338     typedef Signal1<void, P1, IgnoreMarshal> Self;
339 
callback(void * data,P1 p1)340     static void callback(void *data, P1 p1)
341     {
342         Self *s = static_cast<Self*>(data);
343         s->emit(p1);
344     }
345 
346 public:
347     typedef Slot1<void, P1> SlotType;
348 
connect(SlotType * slot)349     Connection connect(SlotType *slot)
350     {
351         return Signal::connect(slot);
352     }
353 
slot()354     SlotType* slot()
355     {
356         return new SignalSlot1<Self, void, P1>(this, &callback);
357     }
358 
emit(P1 p1)359     void emit(P1 p1)
360     {
361         ConnectionList::iterator i = connection_list.begin();
362         while (i != connection_list.end())
363         {
364             if (!(*i)->blocked())
365             {
366                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
367                 if (slot) slot->call(p1);
368             }
369             ++i;
370         }
371     }
372 
operator()373     void operator()(P1 p1)
374     {
375         emit(p1);
376     }
377 };
378 
379 //! @class Signal2
380 //! @brief A template for a signal passing two arguments of type P1 and P2,
381 //! and returning a value of type R.
382 
383 template<typename R, typename P1, typename P2, typename Marshal = class DefaultMarshal<R> >
384 class Signal2 : public Signal
385 {
386     typedef Signal2<R, P1, P2> Self;
387 
callback(void * data,P1 p1,P2 p2)388     static R callback(void *data, P1 p1, P2 p2)
389     {
390         Self *s = static_cast<Self*>(data);
391         return s->emit(p1, p2);
392     }
393 
394 public:
395     typedef Slot2<R, P1, P2> SlotType;
396     //!< Function signature for handlers connecting to the signal.
397 
connect(SlotType * slot)398     Connection connect(SlotType *slot)
399     {
400         return Signal::connect(slot);
401     }
402     //!< Connect a slot to the signal.
403     //!< @param slot - a slot of type Slot2<R, P1, P2>.
404     //!< @return a connection object.
405     //!<
406     //!< <BR>The returned connection object can be used alter or change the connection.
407 
slot()408     SlotType* slot()
409     {
410         return new SignalSlot2<Self, R, P1, P2>(this, &callback);
411     }
412     //!< Returns a slot for this signal.
413     //!< @return a new slot of type Slot2<R, P1, P2>.
414     //!<
415     //!< <BR>The returned slot can be passed to another signal allowing the
416     //!< other signal to call this signal when it gets emitted.
417 
emit(P1 p1,P2 p2)418     R emit(P1 p1, P2 p2)
419     {
420         Marshal m;
421         ConnectionList::iterator i = connection_list.begin();
422         while (i != connection_list.end())
423         {
424             if (!(*i)->blocked())
425             {
426                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
427                 if (slot && m.marshal(slot->call(p1, p2)))
428                     break;
429             }
430             ++i;
431         }
432         return m.value();
433     }
434     //!< Emit the signal.
435     //!< @param p1 - passes p1 to the signal handler.
436     //!< @param p2 - passes p2 to the signal handler.
437     //!< @return the value returned by the signal handler.
438     //!<
439     //!< <BR>Calls every slot connected to this signal, in order of connection.
440 
operator()441     R operator()(P1 p1, P2 p2)
442     {
443         return emit(p1, p2);
444     }
445     //!< Function operator; calls emit().
446 };
447 
448 // Signal2 partially specialized for void return
449 
450 template<typename P1, typename P2, typename IgnoreMarshal>
451 class Signal2<void, P1, P2, IgnoreMarshal> : public Signal
452 {
453     typedef Signal2<void, P1, P2, IgnoreMarshal> Self;
454 
callback(void * data,P1 p1,P2 p2)455     static void callback(void *data, P1 p1, P2 p2)
456     {
457         Self *s = static_cast<Self*>(data);
458         s->emit(p1, p2);
459     }
460 
461 public:
462     typedef Slot2<void, P1, P2> SlotType;
463 
connect(SlotType * slot)464     Connection connect(SlotType *slot)
465     {
466         return Signal::connect(slot);
467     }
468 
slot()469     SlotType* slot()
470     {
471         return new SignalSlot2<Self, void, P1, P2>(this, &callback);
472     }
473 
emit(P1 p1,P2 p2)474     void emit(P1 p1, P2 p2)
475     {
476         ConnectionList::iterator i = connection_list.begin();
477         while (i != connection_list.end())
478         {
479             if (!(*i)->blocked())
480             {
481                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
482                 if (slot) slot->call(p1, p2);
483             }
484             ++i;
485         }
486     }
487 
operator()488     void operator()(P1 p1, P2 p2)
489     {
490         emit(p1, p2);
491     }
492 };
493 
494 //! @class Signal3
495 //! @brief A template for a signal passing three arguments of type P1, P2 and P3,
496 //! and returning a value of type R.
497 
498 template<typename R, typename P1, typename P2, typename P3, typename Marshal = class DefaultMarshal<R> >
499 class Signal3 : public Signal
500 {
501     typedef Signal3<R, P1, P2, P3> Self;
502 
callback(void * data,P1 p1,P2 p2,P3 p3)503     static R callback(void *data, P1 p1, P2 p2, P3 p3)
504     {
505         Self *s = static_cast<Self*>(data);
506         return s->emit(p1, p2, p3);
507     }
508 
509 public:
510     typedef Slot3<R, P1, P2, P3> SlotType;
511     //!< Function signature for handlers connecting to the signal.
512 
connect(SlotType * slot)513     Connection connect(SlotType *slot)
514     {
515         return Signal::connect(slot);
516     }
517     //!< Connect a slot to the signal.
518     //!< @param slot - a slot of type Slot3<R, P1, P2, P3>.
519     //!< @return a connection object.
520     //!<
521     //!< <BR>The returned connection object can be used alter or change the connection.
522 
slot()523     SlotType* slot()
524     {
525         return new SignalSlot3<Self, R, P1, P2, P3>(this, &callback);
526     }
527     //!< Returns a slot for this signal.
528     //!< @return a new slot of type Slot3<R, P1, P2, P3>.
529     //!<
530     //!< <BR>The returned slot can be passed to another signal allowing the
531     //!< other signal to call this signal when it gets emitted.
532 
emit(P1 p1,P2 p2,P3 p3)533     R emit(P1 p1, P2 p2, P3 p3)
534     {
535         Marshal m;
536         ConnectionList::iterator i = connection_list.begin();
537         while (i != connection_list.end())
538         {
539             if (!(*i)->blocked())
540             {
541                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
542                 if (slot && m.marshal(slot->call(p1, p2, p3)))
543                     break;
544             }
545             ++i;
546         }
547         return m.value();
548     }
549     //!< Emit the signal.
550     //!< @param p1 - passes p1 to the signal handler.
551     //!< @param p2 - passes p2 to the signal handler.
552     //!< @param p3 - passes p3 to the signal handler.
553     //!< @return the value returned by the signal handler.
554     //!<
555     //!< <BR>Calls every slot connected to this signal, in order of connection.
556 
operator()557     R operator()(P1 p1, P2 p2, P3 p3)
558     {
559         return emit(p1, p2, p3);
560     }
561     //!< Function operator; calls emit().
562 };
563 
564 // Signal3 partially specialized for void return
565 
566 template<typename P1, typename P2, typename P3, typename IgnoreMarshal>
567 class Signal3<void, P1, P2, P3, IgnoreMarshal> : public Signal
568 {
569     typedef Signal3<void, P1, P2, P3, IgnoreMarshal> Self;
570 
callback(void * data,P1 p1,P2 p2,P3 p3)571     static void callback(void *data, P1 p1, P2 p2, P3 p3)
572     {
573         Self *s = static_cast<Self*>(data);
574         s->emit(p1, p2, p3);
575     }
576 
577 public:
578     typedef Slot3<void, P1, P2, P3> SlotType;
579 
connect(SlotType * slot)580     Connection connect(SlotType *slot)
581     {
582         return Signal::connect(slot);
583     }
584 
slot()585     SlotType* slot()
586     {
587         return new SignalSlot3<Self, void, P1, P2, P3>(this, &callback);
588     }
589 
emit(P1 p1,P2 p2,P3 p3)590     void emit(P1 p1, P2 p2, P3 p3)
591     {
592         ConnectionList::iterator i = connection_list.begin();
593         while (i != connection_list.end())
594         {
595             if (!(*i)->blocked())
596             {
597                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
598                 if (slot) slot->call(p1, p2, p3);
599             }
600             ++i;
601         }
602     }
603 
operator()604     void operator()(P1 p1, P2 p2, P3 p3)
605     {
606         emit(p1, p2, p3);
607     }
608 };
609 
610 //! @class Signal4
611 //! @brief A template for a signal passing four arguments of type P1, P2, P3 and P4,
612 //! and returning a value of type R.
613 
614 template<typename R, typename P1, typename P2, typename P3, typename P4, typename Marshal = class DefaultMarshal<R> >
615 class Signal4 : public Signal
616 {
617     typedef Signal4<R, P1, P2, P3, P4> Self;
618 
callback(void * data,P1 p1,P2 p2,P3 p3,P4 p4)619     static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4)
620     {
621         Self *s = static_cast<Self*>(data);
622         return s->emit(p1, p2, p3, p4);
623     }
624 
625 public:
626     typedef Slot4<R, P1, P2, P3, P4> SlotType;
627     //!< Function signature for handlers connecting to the signal.
628 
connect(SlotType * slot)629     Connection connect(SlotType *slot)
630     {
631         return Signal::connect(slot);
632     }
633     //!< Connect a slot to the signal.
634     //!< @param slot - a slot of type Slot4<R, P1, P2, P3, P4>.
635     //!< @return a connection object.
636     //!<
637     //!< <BR>The returned connection object can be used alter or change the connection.
638 
slot()639     SlotType* slot()
640     {
641         return new SignalSlot4<Self, R, P1, P2, P3, P4>(this, &callback);
642     }
643     //!< Returns a slot for this signal.
644     //!< @return a new slot of type Slot4<R, P1, P2, P3, P4>.
645     //!<
646     //!< <BR>The returned slot can be passed to another signal allowing the
647     //!< other signal to call this signal when it gets emitted.
648 
emit(P1 p1,P2 p2,P3 p3,P4 p4)649     R emit(P1 p1, P2 p2, P3 p3, P4 p4)
650     {
651         Marshal m;
652         ConnectionList::iterator i = connection_list.begin();
653         while (i != connection_list.end())
654         {
655             if (!(*i)->blocked())
656             {
657                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
658                 if (slot && m.marshal(slot->call(p1, p2, p3, p4)))
659                     break;
660             }
661             ++i;
662         }
663         return m.value();
664     }
665     //!< Emit the signal.
666     //!< @param p1 - passes p1 to the signal handler.
667     //!< @param p2 - passes p2 to the signal handler.
668     //!< @param p3 - passes p3 to the signal handler.
669     //!< @param p4 - passes p4 to the signal handler.
670     //!< @return the value returned by the signal handler.
671     //!<
672     //!< <BR>Calls every slot connected to this signal, in order of connection.
673 
operator()674     R operator()(P1 p1, P2 p2, P3 p3, P4 p4)
675     {
676         return emit(p1, p2, p3, p4);
677     }
678     //!< Function operator; calls emit().
679 };
680 
681 // Signal4 partially specialized for void return
682 
683 template<typename P1, typename P2, typename P3, typename P4, typename IgnoreMarshal>
684 class Signal4<void, P1, P2, P3, P4, IgnoreMarshal> : public Signal
685 {
686     typedef Signal4<void, P1, P2, P3, P4, IgnoreMarshal> Self;
687 
callback(void * data,P1 p1,P2 p2,P3 p3,P4 p4)688     static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4)
689     {
690         Self *s = static_cast<Self*>(data);
691         s->emit(p1, p2, p3, p4);
692     }
693 
694 public:
695     typedef Slot4<void, P1, P2, P3, P4> SlotType;
696 
connect(SlotType * slot)697     Connection connect(SlotType *slot)
698     {
699         return Signal::connect(slot);
700     }
701 
slot()702     SlotType* slot()
703     {
704         return new SignalSlot4<Self, void, P1, P2, P3, P4>(this, &callback);
705     }
706 
emit(P1 p1,P2 p2,P3 p3,P4 p4)707     void emit(P1 p1, P2 p2, P3 p3, P4 p4)
708     {
709         ConnectionList::iterator i = connection_list.begin();
710         while (i != connection_list.end())
711         {
712             if (!(*i)->blocked())
713             {
714                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
715                 if (slot) slot->call(p1, p2, p3, p4);
716             }
717             ++i;
718         }
719     }
720 
operator()721     void operator()(P1 p1, P2 p2, P3 p3, P4 p4)
722     {
723         emit(p1, p2, p3, p4);
724     }
725 };
726 
727 //! @class Signal5
728 //! @brief A template for a signal passing five arguments of type P1, P2, P3, P4 and P5,
729 //! and returning a value of type R.
730 
731 template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename Marshal = class DefaultMarshal<R> >
732 class Signal5 : public Signal
733 {
734     typedef Signal5<R, P1, P2, P3, P4, P5> Self;
735 
callback(void * data,P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)736     static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
737     {
738         Self *s = static_cast<Self*>(data);
739         return s->emit(p1, p2, p3, p4, p5);
740     }
741 
742 public:
743     typedef Slot5<R, P1, P2, P3, P4, P5> SlotType;
744     //!< Function signature for handlers connecting to the signal.
745 
connect(SlotType * slot)746     Connection connect(SlotType *slot)
747     {
748         return Signal::connect(slot);
749     }
750     //!< Connect a slot to the signal.
751     //!< @param slot - a slot of type Slot5<R, P1, P2, P3, P4, P5>.
752     //!< @return a connection object.
753     //!<
754     //!< <BR>The returned connection object can be used alter or change the connection.
755 
slot()756     SlotType* slot()
757     {
758         return new SignalSlot5<Self, R, P1, P2, P3, P4, P5>(this, &callback);
759     }
760     //!< Returns a slot for this signal.
761     //!< @return a new slot of type Slot5<R, P1, P2, P3, P4, P5>.
762     //!<
763     //!< <BR>The returned slot can be passed to another signal allowing the
764     //!< other signal to call this signal when it gets emitted.
765 
emit(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)766     R emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
767     {
768         Marshal m;
769         ConnectionList::iterator i = connection_list.begin();
770         while (i != connection_list.end())
771         {
772             if (!(*i)->blocked())
773             {
774                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
775                 if (slot && m.marshal(slot->call(p1, p2, p3, p4, p5)))
776                     break;
777             }
778             ++i;
779         }
780         return m.value();
781     }
782     //!< Emit the signal.
783     //!< @param p1 - passes p1 to the signal handler.
784     //!< @param p2 - passes p2 to the signal handler.
785     //!< @param p3 - passes p3 to the signal handler.
786     //!< @param p4 - passes p4 to the signal handler.
787     //!< @param p5 - passes p5 to the signal handler.
788     //!< @return the value returned by the signal handler.
789     //!<
790     //!< <BR>Calls every slot connected to this signal, in order of connection.
791 
operator()792     R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
793     {
794         return emit(p1, p2, p3, p4, p5);
795     }
796     //!< Function operator; calls emit().
797 };
798 
799 // Signal5 partially specialized for void return
800 
801 template<typename P1, typename P2, typename P3, typename P4, typename P5, typename IgnoreMarshal>
802 class Signal5<void, P1, P2, P3, P4, P5, IgnoreMarshal> : public Signal
803 {
804     typedef Signal5<void, P1, P2, P3, P4, P5, IgnoreMarshal> Self;
805 
callback(void * data,P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)806     static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
807     {
808         Self *s = static_cast<Self*>(data);
809         s->emit(p1, p2, p3, p4, p5);
810     }
811 
812 public:
813     typedef Slot5<void, P1, P2, P3, P4, P5> SlotType;
814 
connect(SlotType * slot)815     Connection connect(SlotType *slot)
816     {
817         return Signal::connect(slot);
818     }
819 
slot()820     SlotType* slot()
821     {
822         return new SignalSlot5<Self, void, P1, P2, P3, P4, P5>(this, &callback);
823     }
824 
emit(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5)825     void emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
826     {
827         ConnectionList::iterator i = connection_list.begin();
828         while (i != connection_list.end())
829         {
830             if (!(*i)->blocked())
831             {
832                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
833                 if (slot) slot->call(p1, p2, p3, p4, p5);
834             }
835             ++i;
836         }
837     }
838 
operator()839     void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
840     {
841         emit(p1, p2, p3, p4, p5);
842     }
843 };
844 
845 //! @class Signal6
846 //! @brief A template for a signal passing six arguments of type P1, P2, P3, P4, P5 and P6,
847 //! and returning a value of type R.
848 
849 template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename Marshal = class DefaultMarshal<R> >
850 class Signal6 : public Signal
851 {
852     typedef Signal6<R, P1, P2, P3, P4, P5, P6> Self;
853 
callback(void * data,P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6)854     static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
855     {
856         Self *s = static_cast<Self*>(data);
857         return s->emit(p1, p2, p3, p4, p5, p6);
858     }
859 
860 public:
861     typedef Slot6<R, P1, P2, P3, P4, P5, P6> SlotType;
862     //!< Function signature for handlers connecting to the signal.
863 
connect(SlotType * slot)864     Connection connect(SlotType *slot)
865     {
866         return Signal::connect(slot);
867     }
868     //!< Connect a slot to the signal.
869     //!< @param slot - a slot of type Slot6<R, P1, P2, P3, P4, P5, P6>.
870     //!< @return a connection object.
871     //!<
872     //!< <BR>The returned connection object can be used alter or change the connection.
873 
slot()874     SlotType* slot()
875     {
876         return new SignalSlot6<Self, R, P1, P2, P3, P4, P5, P6>(this, &callback);
877     }
878     //!< Returns a slot for this signal.
879     //!< @return a new slot of type Slot6<R, P1, P2, P3, P4, P5, P6>.
880     //!<
881     //!< <BR>The returned slot can be passed to another signal allowing the
882     //!< other signal to call this signal when it gets emitted.
883 
emit(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6)884     R emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
885     {
886         Marshal m;
887         ConnectionList::iterator i = connection_list.begin();
888         while (i != connection_list.end())
889         {
890             if (!(*i)->blocked())
891             {
892                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
893                 if (slot && m.marshal(slot->call(p1, p2, p3, p4, p5, p6)))
894                     break;
895             }
896             ++i;
897         }
898         return m.value();
899     }
900     //!< Emit the signal.
901     //!< @param p1 - passes p1 to the signal handler.
902     //!< @param p2 - passes p2 to the signal handler.
903     //!< @param p3 - passes p3 to the signal handler.
904     //!< @param p4 - passes p4 to the signal handler.
905     //!< @param p5 - passes p5 to the signal handler.
906     //!< @param p6 - passes p6 to the signal handler.
907     //!< @return the value returned by the signal handler.
908     //!<
909     //!< <BR>Calls every slot connected to this signal, in order of connection.
910 
operator()911     R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
912     {
913         return emit(p1, p2, p3, p4, p5, p6);
914     }
915     //!< Function operator; calls emit().
916 };
917 
918 /*  Signal6 partially specialized for void return
919  */
920 
921 template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename IgnoreMarshal>
922 class Signal6<void, P1, P2, P3, P4, P5, P6, IgnoreMarshal> : public Signal
923 {
924     typedef Signal6<void, P1, P2, P3, P4, P5, P6, IgnoreMarshal> Self;
925 
callback(void * data,P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6)926     static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
927     {
928         Self *s = static_cast<Self*>(data);
929         s->emit(p1, p2, p3, p4, p5, p6);
930     }
931 
932 public:
933     typedef Slot6<void, P1, P2, P3, P4, P5, P6> SlotType;
934 
connect(SlotType * slot)935     Connection connect(SlotType *slot)
936     {
937         return Signal::connect(slot);
938     }
939 
slot()940     SlotType* slot()
941     {
942         return new SignalSlot6<Self, void, P1, P2, P3, P4, P5, P6>(this, &callback);
943     }
944 
emit(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6)945     void emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
946     {
947         ConnectionList::iterator i = connection_list.begin();
948         while (i != connection_list.end())
949         {
950             if (!(*i)->blocked())
951             {
952                 SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
953                 if (slot) slot->call(p1, p2, p3, p4, p5, p6);
954             }
955             ++i;
956         }
957     }
958 
operator()959     void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
960     {
961         emit(p1, p2, p3, p4, p5, p6);
962     }
963 };
964 
965 /** @} */
966 
967 } // namespace scim
968 
969 #endif //__SCIM_SIGNALS_H
970 
971 /*
972 vi:ts=4:nowrap:ai:expandtab
973 */
974 
975