Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TQObject.h
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Valeriy Onuchin & Fons Rademakers 15/10/2000
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #ifndef ROOT_TQObject
13 #define ROOT_TQObject
14 
15 //////////////////////////////////////////////////////////////////////////
16 // //
17 // This is the ROOT implementation of the Qt object communication //
18 // mechanism (see also http://www.troll.no/qt/metaobjects.html) //
19 // //
20 // Signals and slots are used for communication between objects. //
21 // When an object has changed in some way that might be interesting //
22 // for the outside world, it emits a signal to tell whoever is //
23 // listening. All slots that are connected to this signal will be //
24 // activated (called). It is even possible to connect a signal //
25 // directly to another signal (this will emit the second signal //
26 // immediately whenever the first is emitted.) There is no limitation //
27 // on the number of slots that can be connected to a signal. //
28 // The slots will be activated in the order they were connected //
29 // to the signal. This mechanism allows objects to be easily reused, //
30 // because the object that emits a signal does not need to know //
31 // to what the signals are connected to. //
32 // Together, signals and slots make up a powerfull component //
33 // programming mechanism. //
34 // //
35 // This implementation is provided by //
36 // Valeriy Onuchin (onuchin@sirius.ihep.su). //
37 // //
38 //////////////////////////////////////////////////////////////////////////
39 
40 #include "TList.h"
41 #include "TString.h"
42 #include "TVirtualQConnection.h"
43 
44 class TClass;
45 
46 R__EXTERN void *gTQSender; // the latest sender object
47 
48 class TQObject {
49 
50 protected:
51  TList *fListOfSignals; //! list of signals from this object
52  TList *fListOfConnections; //! list of connections to this object
53  Bool_t fSignalsBlocked; //! flag used for suppression of signals
54 
55  static Bool_t fgAllSignalsBlocked; // flag used for suppression of all signals
56 
57  virtual void *GetSender() { return this; }
58  virtual const char *GetSenderClassName() const { return ""; }
59 
60 
61  static Bool_t ConnectToClass(TQObject *sender,
62  const char *signal,
63  TClass *receiver_class,
64  void *receiver,
65  const char *slot);
66 
67  static Bool_t ConnectToClass(const char *sender_class,
68  const char *signal,
69  TClass *receiver_class,
70  void *receiver,
71  const char *slot);
72 
73  static Int_t CheckConnectArgs(TQObject *sender,
74  TClass *sender_class, const char *signal,
75  TClass *receiver_class, const char *slot);
76 
77  static TString CompressName(const char *method_name);
78 
79 private:
80  TQObject(const TQObject& tqo); // not implemented
81  TQObject& operator=(const TQObject& tqo); // not implemented
82 
83 public:
84  TQObject();
85  virtual ~TQObject();
86 
87  TList *GetListOfClassSignals() const;
88  TList *GetListOfSignals() const { return fListOfSignals; }
89  TList *GetListOfConnections() const { return fListOfConnections; }
90 
91  Bool_t AreSignalsBlocked() const { return fSignalsBlocked; }
92  Bool_t BlockSignals(Bool_t b)
93  { Bool_t ret = fSignalsBlocked; fSignalsBlocked = b; return ret; }
94 
95  void CollectClassSignalLists(TList& list, TClass* cls);
96 
97  ///////////////////////////////////////////////////////////////////////////////
98  /// Emit a signal with a varying number of arguments.
99  ///
100  template <typename... T> void EmitVA(const char *signal_name, Int_t /* nargs */, const T&... params)
101  {
102  // Activate signal with variable argument list.
103  // For internal use and for var arg EmitVA() in RQ_OBJECT.h.
104 
105  if (fSignalsBlocked || AreAllSignalsBlocked())
106  return;
107 
108  TList classSigLists;
109  CollectClassSignalLists(classSigLists, IsA());
110 
111  if (classSigLists.IsEmpty() && !fListOfSignals)
112  return;
113 
114  TString signal = CompressName(signal_name);
115 
116  TVirtualQConnection *connection = 0;
117 
118  // execute class signals
119  TList *sigList;
120  TIter nextSigList(&classSigLists);
121  while ((sigList = (TList*) nextSigList())) {
122  TIter nextcl((TList*) sigList->FindObject(signal));
123  while ((connection = static_cast<TVirtualQConnection*>(nextcl()))) {
124  gTQSender = GetSender();
125  connection->SetArgs(params...);
126  connection->SendSignal();
127  }
128  }
129  if (!fListOfSignals)
130  return;
131 
132  // execute object signals
133  TIter next((TList*) fListOfSignals->FindObject(signal));
134  while (fListOfSignals && (connection = static_cast<TVirtualQConnection*>(next()))) {
135  gTQSender = GetSender();
136  connection->SetArgs(params...);
137  connection->SendSignal();
138  }
139  }
140 
141  ////////////////////////////////////////////////////////////////////////////////
142  /// Activate signal with single parameter.
143  /// Example:
144  /// ~~~ {.cpp}
145  /// theButton->Emit("Progress(Long64_t)",processed)
146  /// ~~~
147  ///
148  /// If we call Emit with an array of the parameters, they should be converted
149  /// to long type.
150  /// Example:
151  /// ~~~ {.cpp}
152  /// TQObject *processor; // data processor
153  /// TH1F *hist; // filled with processor results
154  ///
155  /// processor->Connect("Evaluated(Float_t,Float_t)",
156  /// "TH1F",hist,"Fill12(Axis_t,Axis_t)");
157  ///
158  /// Long_t args[2];
159  /// args[0] = (Long_t)processor->GetValue(1);
160  /// args[1] = (Long_t)processor->GetValue(2);
161  ///
162  /// processor->Emit("Evaluated(Float_t,Float_t)",args);
163  /// ~~~
164  template <typename T> void Emit(const char *signal, const T& arg) {
165  Int_t placeholder = 0;
166  EmitVA(signal, placeholder, arg);
167  }
168 
169  ////////////////////////////////////////////////////////////////////////////////
170  /// Acitvate signal without args.
171  /// Example:
172  /// theButton->Emit("Clicked()");
173  void Emit(const char *signal) { EmitVA(signal, (Int_t) 0); }
174 
175  Bool_t Connect(const char *signal,
176  const char *receiver_class,
177  void *receiver,
178  const char *slot);
179 
180  Bool_t Disconnect(const char *signal = 0,
181  void *receiver = 0,
182  const char *slot = 0);
183 
184  virtual void HighPriority(const char *signal_name,
185  const char *slot_name = 0);
186 
187  virtual void LowPriority(const char *signal_name,
188  const char *slot_name = 0);
189 
190  virtual Bool_t HasConnection(const char *signal_name) const;
191  virtual Int_t NumberOfSignals() const;
192  virtual Int_t NumberOfConnections() const;
193  virtual void Connected(const char * /*signal_name*/) { }
194  virtual void Disconnected(const char * /*signal_name*/) { }
195 
196  virtual void Destroyed()
197  { Emit("Destroyed()"); } // *SIGNAL*
198  virtual void ChangedBy(const char *method)
199  { Emit("ChangedBy(char*)", method); } // *SIGNAL*
200  virtual void Message(const char *msg)
201  { Emit("Message(char*)", msg); } // *SIGNAL*
202 
203  static Bool_t Connect(TQObject *sender,
204  const char *signal,
205  const char *receiver_class,
206  void *receiver,
207  const char *slot);
208 
209  static Bool_t Connect(const char *sender_class,
210  const char *signal,
211  const char *receiver_class,
212  void *receiver,
213  const char *slot);
214 
215  static Bool_t Disconnect(TQObject *sender,
216  const char *signal = 0,
217  void *receiver = 0,
218  const char *slot = 0);
219 
220  static Bool_t Disconnect(const char *class_name,
221  const char *signal,
222  void *receiver = 0,
223  const char *slot = 0);
224 
225  static Bool_t AreAllSignalsBlocked();
226  static Bool_t BlockAllSignals(Bool_t b);
227 
228  ClassDef(TQObject,1) //Base class for object communication mechanism
229 };
230 
231 
232 class TQObjSender : public TQObject {
233 
234 protected:
235  void *fSender; //delegation object
236  TString fSenderClass; //class name of delegation object
237 
238  virtual void *GetSender() { return fSender; }
239  virtual const char *GetSenderClassName() const { return fSenderClass; }
240 
241 private:
242  TQObjSender(const TQObjSender&); // not implemented
243  TQObjSender& operator=(const TQObjSender&); // not implemented
244 
245 public:
246  TQObjSender() : TQObject(), fSender(0), fSenderClass() { }
247  virtual ~TQObjSender() { Disconnect(); }
248 
249  virtual void SetSender(void *sender) { fSender = sender; }
250  void SetSenderClassName(const char *sclass = "") { fSenderClass = sclass; }
251 
252  ClassDef(TQObjSender,0) //Used to "delegate" TQObject functionality
253  //to interpreted classes, see also RQ_OBJECT.h
254 };
255 
256 
257 
258 // Global function which simplifies making connections in interpreted
259 // ROOT session
260 //
261 // ConnectCINT - connects to interpreter(CINT) command
262 
263 extern Bool_t ConnectCINT(TQObject *sender, const char *signal,
264  const char *slot);
265 
266 #ifdef G__DICTIONARY
267 // This include makes it possible to have a single connection
268 // from all objects of the same class but is only needed in
269 // the dictionary.
270 #include "TQClass.h"
271 #endif
272 
273 
274 //---- ClassImpQ macro ----------------------------------------------
275 //
276 // This macro used to correspond to the ClassImp macro and should be used
277 // for classes derived from TQObject instead of the ClassImp macro.
278 // This macro makes it possible to have a single connection from
279 // all objects of the same class.
280 // *** It is now obsolete ***
281 
282 #define ClassImpQ(name) \
283  ClassImp(name)
284 
285 #endif