Logo ROOT   6.14/05
Reference Guide
TQObject.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id: 5d6810ad46b864564f576f88aa9b154789d91d48 $
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 /** \class TQObject
13 \ingroup Base
14 
15 This is the ROOT implementation of the Qt object communication
16 mechanism (see also http://www.troll.no/qt/metaobjects.html)
17 
18 Signals and slots are used for communication between objects.
19 When an object has changed in some way that might be interesting
20 for the outside world, it emits a signal to tell whoever is
21 listening. All slots that are connected to this signal will be
22 activated (called). It is even possible to connect a signal
23 directly to another signal (this will emit the second signal
24 immediately whenever the first is emitted.) There is no limitation
25 on the number of slots that can be connected to a signal.
26 The slots will be activated in the order they were connected
27 to the signal. This mechanism allows objects to be easily reused,
28 because the object that emits a signal does not need to know
29 to which objects the signals are connected.
30 Together, signals and slots make up a powerfull component
31 programming mechanism.
32 
33 ### Signals
34 
35 ~~~ {.cpp}
36  Destroyed()
37 ~~~
38 Signal emitted when object is destroyed.
39 This signal could be connected to some garbage-collector object.
40 
41 ~~~ {.cpp}
42  ChangedBy(const char *method_name)
43 ~~~
44 This signal is emitted when some important data members of
45 the object were changed. method_name parameter can be used
46 as an identifier of the modifier method.
47 
48 ~~~ {.cpp}
49  Message(const char *msg)
50 ~~~
51 
52 General purpose message signal
53 */
54 
55 #include "Varargs.h"
56 #include "TQObject.h"
57 #include "TQConnection.h"
58 #include "THashList.h"
59 #include "TPRegexp.h"
60 #include "TROOT.h"
61 #include "TClass.h"
62 #include "TSystem.h"
63 #include "TMethod.h"
64 #include "TBaseClass.h"
65 #include "TDataType.h"
66 #include "TInterpreter.h"
67 #include "TQClass.h"
68 #include "TError.h"
69 #include "Riostream.h"
70 #include "RQ_OBJECT.h"
71 #include "TVirtualMutex.h"
72 #include "Varargs.h"
73 #include "TInterpreter.h"
74 #include "RConfigure.h"
75 
76 void *gTQSender; // A pointer to the object that sent the last signal.
77  // Getting access to the sender might be practical
78  // when many signals are connected to a single slot.
79 
81 
82 
86 
87 ////////////////////////////////////////////////////////////////////////////////
88 /// Removes "const" words and blanks from full (with prototype)
89 /// method name and resolve any typedefs in the method signature.
90 /// If a null or empty string is passed in, an empty string
91 /// is returned.
92 ///
93 /// Example:
94 /// ~~~ {.cpp}
95 /// CompressName(" Draw(const char *, const char *,
96 /// Option_t * , Int_t , Int_t)");
97 /// ~~~
98 /// returns the string "Draw(char*,char*,char*,int,int)".
99 
100 TString TQObject::CompressName(const char *method_name)
101 {
102  TString res(method_name);
103  if (res.IsNull())
104  return res;
105 
106  {
107  static TVirtualMutex * lock = 0;
108  R__LOCKGUARD2(lock);
109 
110  static TPMERegexp *constRe = 0, *wspaceRe = 0;
111  if (constRe == 0) {
112  constRe = new TPMERegexp("(?<=\\(|\\s|,|&|\\*)const(?=\\s|,|\\)|&|\\*)", "go");
113  wspaceRe = new TPMERegexp("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", "go");
114  }
115  constRe ->Substitute(res, "");
116  wspaceRe->Substitute(res, "");
117  }
118 
119  TStringToken methargs(res, "\\(|\\)", kTRUE);
120 
121  methargs.NextToken();
122  res = methargs;
123  res += "(";
124 
125  methargs.NextToken();
126  TStringToken arg(methargs, ",");
127  while (arg.NextToken())
128  {
129  Int_t pri = arg.Length() - 1;
130  Char_t prc = 0;
131  if (arg[pri] == '*' || arg[pri] == '&') {
132  prc = arg[pri];
133  arg.Remove(pri);
134  }
135  TDataType *dt = gROOT->GetType(arg.Data());
136  if (dt) {
137  res += dt->GetFullTypeName();
138  } else {
139  res += arg;
140  }
141  if (prc) res += prc;
142  if (!arg.AtEnd()) res += ",";
143  }
144  res += ")";
145  return res;
146 }
147 
148 namespace {
149 
150 ////////////////////////////////////////////////////////////////////////////////
151 /// Almost the same as TClass::GetMethodWithPrototype().
152 
153 TMethod *GetMethodWithPrototype(TClass *cl, const char *method,
154  const char *proto, Int_t &nargs)
155 {
156  nargs = 0;
157 
158  if (!gInterpreter || cl == 0) return 0;
159 
160  TMethod *m = cl->GetMethodWithPrototype(method,proto);
161  if (m) nargs = m->GetNargs();
162  return m;
163 }
164 
165 ////////////////////////////////////////////////////////////////////////////////
166 /// Almost the same as TClass::GetMethod().
167 
168 static TMethod *GetMethod(TClass *cl, const char *method, const char *params)
169 {
170  if (!gInterpreter || cl == 0) return 0;
171  return cl->GetMethod(method,params);
172 }
173 
174 }
175 
176 ////////////////////////////////////////////////////////////////////////////////
177 /// Checking of consitency of sender/receiver methods/arguments.
178 /// Returns -1 on error, otherwise number or arguments of signal function.
179 /// Static method.
180 
182  TClass *sender_class, const char *signal,
183  TClass *receiver_class, const char *slot)
184 {
185  char *signal_method = new char[strlen(signal)+1];
186  if (signal_method) strcpy(signal_method, signal);
187 
188  char *signal_proto;
189  char *tmp;
190 
191  if ((signal_proto = strchr(signal_method,'('))) {
192  // substitute first '(' symbol with '\0'
193  *signal_proto++ = '\0';
194  // substitute last ')' symbol with '\0'
195  if ((tmp = strrchr(signal_proto,')'))) *tmp = '\0';
196  }
197 
198  if (!signal_proto) signal_proto = (char*)""; // avoid zero strings
199 
200  // if delegation object TQObjSender is used get the real sender class
201  if (sender && sender_class == TQObjSender::Class()) {
202  sender_class = TClass::GetClass(sender->GetSenderClassName());
203  if (!sender_class) {
204  ::Error("TQObject::CheckConnectArgs", "for signal/slot consistency\n"
205  "checking need to specify class name as argument to "
206  "RQ_OBJECT macro");
207  delete [] signal_method;
208  return -1;
209  }
210  }
211 
212  Int_t nargs;
213  TMethod *signalMethod = GetMethodWithPrototype(sender_class,
214  signal_method,
215  signal_proto,
216  nargs);
217  if (!signalMethod) {
218  ::Error("TQObject::CheckConnectArgs", "signal %s::%s(%s) does not exist",
219  sender_class->GetName(), signal_method, signal_proto);
220  delete [] signal_method;
221  return -1;
222  }
223  Int_t nsigargs = nargs;
224 
225 #if defined(CHECK_COMMENT_STRING)
226  const char *comment = 0;
227  if (signalMethod != (TMethod *) -1) // -1 in case of interpreted class
228  comment = signalMethod->GetCommentString();
229 
230  if (!comment || !comment[0] || strstr(comment,"*SIGNAL")){
231  ::Error("TQObject::CheckConnectArgs",
232  "signal %s::%s(%s), to declare signal use comment //*SIGNAL*",
233  sender_class->GetName(), signal_method, signal_proto);
234  delete [] signal_method;
235  return -1;
236  }
237 #endif
238 
239  // cleaning
240  delete [] signal_method;
241 
242  char *slot_method = new char[strlen(slot)+1];
243  if (slot_method) strcpy(slot_method, slot);
244 
245  char *slot_proto;
246  char *slot_params = 0;
247 
248  if ((slot_proto = strchr(slot_method,'('))) {
249 
250  // substitute first '(' symbol with '\0'
251  *slot_proto++ = '\0';
252 
253  // substitute last ')' symbol with '\0'
254  if ((tmp = strrchr(slot_proto,')'))) *tmp = '\0';
255  }
256 
257  if (!slot_proto) slot_proto = (char*)""; // avoid zero strings
258  if ((slot_params = strchr(slot_proto,'='))) *slot_params = ' ';
259 
260  TFunction *slotMethod = 0;
261  if (!receiver_class) {
262  // case of slot_method is compiled/intrepreted function
263  slotMethod = gROOT->GetGlobalFunction(slot_method,0,kFALSE);
264  } else {
265  slotMethod = !slot_params ?
266  GetMethodWithPrototype(receiver_class,
267  slot_method,
268  slot_proto,
269  nargs) :
270  GetMethod(receiver_class,
271  slot_method, slot_params);
272  }
273 
274  if (!slotMethod) {
275  if (!slot_params) {
276  ::Error("TQObject::CheckConnectArgs", "slot %s(%s) does not exist",
277  receiver_class ? Form("%s::%s", receiver_class->GetName(),
278  slot_method) : slot_method, slot_proto);
279  } else {
280  ::Error("TQObject::CheckConnectArgs", "slot %s(%s) does not exist",
281  receiver_class ? Form("%s::%s", receiver_class->GetName(),
282  slot_method) : slot_method, slot_params);
283  }
284  delete [] slot_method;
285  return -1;
286  }
287 
288 #if defined(CHECK_ARGS_NUMBER)
289  if (slotMethod != (TMethod *) -1 && slotMethod->GetNargsOpt() >= 0 &&
290  nsigargs < (slotMethod->GetNargs() - slotMethod->GetNargsOpt())) {
291  ::Error("TQObject::CheckConnectArgs",
292  "inconsistency in numbers of arguments");
293  delete [] slot_method;
294  return -1;
295  }
296 #endif
297 
298  // cleaning
299  delete [] slot_method;
300 
301  return nsigargs;
302 }
303 
304 /** \class TQConnectionList
305  TQConnectionList is the named list of connections,
306  see also TQConnection class.
307 */
308 
309 class TQConnectionList : public TList {
310 
311 private:
312  Int_t fSignalArgs; // number of arguments in signal function
313 
314 public:
315  TQConnectionList(const char *name, Int_t nsigargs) : TList()
316  { fName = name; fSignalArgs = nsigargs; }
317  virtual ~TQConnectionList();
318 
319  Bool_t Disconnect(void *receiver=0, const char *slot_name=0);
320  Int_t GetNargs() const { return fSignalArgs; }
321  void ls(Option_t *option = "") const;
322 };
323 
324 ////////////////////////////////////////////////////////////////////////////////
325 /// Destructor.
326 
327 TQConnectionList::~TQConnectionList()
328 {
329  TIter next(this);
330  TQConnection *connection;
331 
332  while ((connection = (TQConnection*)next())) {
333  // remove this from feed back reference list
334  connection->Remove(this);
335  if (connection->IsEmpty()) delete connection;
336  }
337  Clear("nodelete");
338 }
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 /// Remove connection from the list. For more info see
342 /// TQObject::Disconnect()
343 
344 Bool_t TQConnectionList::Disconnect(void *receiver, const char *slot_name)
345 {
346  TQConnection *connection = 0;
347  Bool_t return_value = kFALSE;
348 
349  TObjLink *lnk = FirstLink();
350  TObjLink *savlnk; // savlnk is used when link is deleted
351 
352  while (lnk) {
353  connection = (TQConnection*)lnk->GetObject();
354  const char *name = connection->GetName();
355  void *obj = connection->GetReceiver();
356 
357  if (!slot_name || !slot_name[0]
358  || !strcmp(name,slot_name)) {
359 
360  if (!receiver || (receiver == obj)) {
361  return_value = kTRUE;
362  savlnk = lnk->Next(); // keep next link ..
363  Remove(lnk);
364  lnk = savlnk; // current link == saved ...
365  connection->Remove(this); // remove back reference
366  if (connection->IsEmpty()) SafeDelete(connection);
367  continue; // .. continue from saved link
368  }
369  }
370  lnk = lnk->Next();
371  }
372  return return_value;
373 }
374 
375 ////////////////////////////////////////////////////////////////////////////////
376 /// List signal name and list all connections in this signal list.
377 
378 void TQConnectionList::ls(Option_t *option) const
379 {
380  std::cout << "TQConnectionList:" << "\t" << GetName() << std::endl;
381  ((TQConnectionList*)this)->R__FOR_EACH(TQConnection,Print)(option);
382 }
383 
384 
385 ////////////////////////////////////////////////////////////////////////////////
386 /// TQObject Constructor.
387 /// Comment:
388 /// - In order to minimize memory allocation fListOfSignals and
389 /// fListOfConnections are allocated only if it is neccesary
390 /// - When fListOfSignals/fListOfConnections are empty they will
391 /// be deleted
392 
394 {
395  fListOfSignals = 0;
396  fListOfConnections = 0;
398 }
399 
400 ////////////////////////////////////////////////////////////////////////////////
401 /// TQObject Destructor.
402 /// - delete all connections and signal list
403 
405 {
406  if (!gROOT) return;
407 
408  Destroyed(); // emit "Destroyed()" signal
409 
410  if (fListOfSignals) {
412  SafeDelete(fListOfSignals); // delete list of signals
413  }
414 
415  // loop over all connections and remove references to this object
416  if (fListOfConnections) {
417  TIter next_connection(fListOfConnections);
418  TQConnection *connection;
419 
420  while ((connection = (TQConnection*)next_connection())) {
421  TIter next_list(connection);
422  TQConnectionList *list;
423  while ((list = (TQConnectionList*)next_list())) {
424  list->Remove(connection);
425  if (list->IsEmpty()) SafeDelete(list);
426  }
427  }
429  }
430 }
431 
432 ////////////////////////////////////////////////////////////////////////////////
433 /// Returns pointer to list of signals of this class.
434 
436 {
437  TQClass *qcl = 0;
438 
439  qcl = dynamic_cast<TQClass*>(IsA());
440 
441  return qcl ? qcl->fListOfSignals : 0; //!!
442 }
443 
444 ////////////////////////////////////////////////////////////////////////////////
445 /// Collect class signal lists from class cls and all its
446 /// base-classes.
447 ///
448 /// The recursive traversal is not performed for classes not
449 /// deriving from TQClass.
450 
452 {
453  TQClass *qcl = dynamic_cast<TQClass*>(cls);
454  if (qcl)
455  {
456  if (qcl->fListOfSignals)
457  list.Add(qcl->fListOfSignals);
458 
459  // Descend into base-classes.
460  TIter next_base_class(cls->GetListOfBases());
461  TBaseClass *base;
462  while ((base = (TBaseClass*) next_base_class()))
463  {
464  CollectClassSignalLists(list, base->GetClassPointer());
465  }
466  }
467 }
468 
469 ////////////////////////////////////////////////////////////////////////////////
470 /// 1. If slot_name = 0 => makes signal defined by the signal_name
471 /// to be the first in the fListOfSignals, this decreases
472 /// the time for lookup.
473 /// 2. If slot_name != 0 => makes slot defined by the slot_name
474 /// to be executed first when signal_name is emitted.
475 /// Signal name is not compressed.
476 
477 void TQObject::HighPriority(const char *signal_name, const char *slot_name)
478 {
479  TQConnectionList *clist = (TQConnectionList*)
480  fListOfSignals->FindObject(signal_name);
481 
482  if (!clist) return; // not found
483  if (!slot_name) { // update list of signal lists
484  fListOfSignals->Remove(clist); // remove and add first
485  fListOfSignals->AddFirst(clist);
486  return;
487  } else { // slot_name != 0 , update signal list
488  TQConnection *con = (TQConnection*) clist->FindObject(slot_name);
489  if (!con) return; // not found
490  clist->Remove(con); // remove and add as first
491  clist->AddFirst(con);
492  }
493 }
494 
495 ////////////////////////////////////////////////////////////////////////////////
496 /// 1. If slot_name = 0 => makes signal defined by the signal_name
497 /// to be the last in the fListOfSignals, this increase the time
498 /// for lookup.
499 /// 2. If slot_name != 0 => makes slot defined by the slot_name
500 /// to be executed last when signal_name is emitted.
501 /// Signal name is not compressed.
502 
503 void TQObject::LowPriority(const char *signal_name, const char *slot_name)
504 {
505  TQConnectionList *clist = (TQConnectionList*)
506  fListOfSignals->FindObject(signal_name);
507 
508  if (!clist) return;
509  if (!slot_name) {
510  fListOfSignals->Remove(clist); // remove and add first
511  fListOfSignals->AddLast(clist);
512  return;
513  } else { // slot_name != 0 , update signal list
514  TQConnection *con = (TQConnection*) clist->FindObject(slot_name);
515  if (!con) return;
516  clist->Remove(con); // remove and add as last
517  clist->AddLast(con);
518  }
519 }
520 
521 ////////////////////////////////////////////////////////////////////////////////
522 /// Return true if there is any object connected to this signal.
523 /// Only checks for object signals.
524 
525 Bool_t TQObject::HasConnection(const char *signal_name) const
526 {
527  if (!fListOfSignals)
528  return kFALSE;
529 
530  TString signal = CompressName(signal_name);
531 
532  return (fListOfSignals->FindObject(signal) != 0);
533 }
534 
535 ////////////////////////////////////////////////////////////////////////////////
536 /// Return number of signals for this object.
537 /// Only checks for object signals.
538 
540 {
541  if (fListOfSignals)
542  return fListOfSignals->GetSize();
543  return 0;
544 }
545 
546 ////////////////////////////////////////////////////////////////////////////////
547 /// Return number of connections for this object.
548 
550 {
551  if (fListOfConnections)
552  return fListOfConnections->GetSize();
553  return 0;
554 }
555 
556 
557 ////////////////////////////////////////////////////////////////////////////////
558 /// Create connection between sender and receiver.
559 /// Receiver class needs to have a dictionary.
560 
562  const char *signal,
563  TClass *cl,
564  void *receiver,
565  const char *slot)
566 {
567  // sender should be TQObject
568  if (!sender->IsA()->InheritsFrom(TQObject::Class()))
569  return kFALSE;
570 
571  // remove "const" and strip blanks
572  TString signal_name = CompressName(signal);
573  TString slot_name = CompressName(slot);
574 
575  // check consitency of signal/slot methods/args
576  Int_t nsigargs;
577  if ((nsigargs = CheckConnectArgs(sender, sender->IsA(), signal_name, cl, slot_name)) == -1)
578  return kFALSE;
579 
580  if (!sender->fListOfSignals)
581  sender->fListOfSignals = new THashList();
582 
583  TQConnectionList *clist = (TQConnectionList*)
584  sender->fListOfSignals->FindObject(signal_name);
585 
586  if (!clist) {
587  clist = new TQConnectionList(signal_name, nsigargs);
588  sender->fListOfSignals->Add(clist);
589  }
590 
591  TIter next(clist);
592  TQConnection *connection = 0;
593 
594  while ((connection = (TQConnection*)next())) {
595  if (!strcmp(slot_name,connection->GetName()) &&
596  (receiver == connection->GetReceiver())) break;
597  }
598 
599  if (!connection)
600  connection = new TQConnection(cl, receiver, slot_name);
601 
602  // check to prevent multiple entries
603  if (!clist->FindObject(connection)) {
604  clist->Add(connection);
605  if (!connection->FindObject(clist)) connection->Add(clist);
606  sender->Connected(signal_name);
607  }
608 
609  return kTRUE;
610 }
611 
612 ////////////////////////////////////////////////////////////////////////////////
613 /// This method allows to make connection from any object
614 /// of the same class to the receiver object.
615 /// Receiver class needs to have a dictionary.
616 
617 Bool_t TQObject::ConnectToClass(const char *class_name,
618  const char *signal,
619  TClass *cl,
620  void *receiver,
621  const char *slot)
622 {
623  TClass *sender = TClass::GetClass(class_name);
624 
625  // sender class should be TQObject (i.e. TQClass)
626  if (!sender || !sender->IsA()->InheritsFrom(TQObject::Class()))
627  return kFALSE;
628 
629  TList *slist = ((TQClass*)sender)->fListOfSignals;
630  TString signal_name = CompressName(signal);
631  TString slot_name = CompressName(slot);
632 
633  // check consitency of signal/slot methods/args
634  Int_t nsigargs;
635  if ((nsigargs = CheckConnectArgs(0, sender, signal_name, cl, slot_name)) == -1)
636  return kFALSE;
637 
638  if (!slist)
639  ((TQClass*)sender)->fListOfSignals = slist = new THashList();
640 
641  TQConnectionList *clist = (TQConnectionList*) slist->FindObject(signal_name);
642 
643  if (!clist) {
644  clist = new TQConnectionList(signal_name, nsigargs);
645  slist->Add(clist);
646  }
647 
648  TQConnection *connection = 0;
649  TIter next(clist);
650 
651  while ((connection = (TQConnection*)next())) {
652  if (!strcmp(slot_name,connection->GetName()) &&
653  (receiver == connection->GetReceiver())) break;
654  }
655 
656  if (!connection)
657  connection = new TQConnection(cl, receiver, slot_name);
658 
659  // check to prevent multiple entries
660  if (!clist->FindObject(connection)) {
661  clist->Add(connection);
662  if (!connection->FindObject(clist)) connection->Add(clist);
663  ((TQClass*)sender)->Connected(signal_name);
664  }
665 
666  return kTRUE;
667 }
668 
669 ////////////////////////////////////////////////////////////////////////////////
670 /// Create connection between sender and receiver.
671 /// Signal and slot string must have a form:
672 /// "Draw(char*, Option_t* ,Int_t)"
673 /// All blanks and "const" words will be removed,
674 ///
675 /// cl != 0 - class name, it can be class with or
676 /// without dictionary, e.g interpreted class.
677 /// Example:
678 /// ~~~ {.cpp}
679 /// TGButton *myButton;
680 /// TH2F *myHist;
681 ///
682 /// TQObject::Connect(myButton,"Clicked()",
683 /// "TH2F", myHist,"Draw(Option_t*)");
684 /// ~~~
685 /// cl == 0 - corresponds to function (interpereted or global)
686 /// the name of the function is defined by the slot string,
687 /// parameter receiver should be 0.
688 /// Example:
689 /// ~~~ {.cpp}
690 /// TGButton *myButton;
691 /// TH2F *myHist;
692 ///
693 /// TQObject::Connect(myButton,"Clicked()",
694 /// 0, 0,"hsimple()");
695 /// ~~~
696 /// Warning:
697 /// If receiver is class not derived from TQObject and going to be
698 /// deleted, disconnect all connections to this receiver.
699 /// In case of class derived from TQObject it is done automatically.
700 
702  const char *signal,
703  const char *cl,
704  void *receiver,
705  const char *slot)
706 {
707  if (cl) {
708  TClass *rcv_cl = TClass::GetClass(cl);
709  if (rcv_cl) return ConnectToClass(sender, signal, rcv_cl, receiver, slot);
710  }
711 
712  // the following is the case of receiver class without dictionary
713  // e.g. interpreted class or function.
714 
715  // sender should be TQObject
716  if (!sender->IsA()->InheritsFrom(TQObject::Class()))
717  return kFALSE;
718 
719  // remove "const" and strip blanks
720  TString signal_name = CompressName(signal);
721  TString slot_name = CompressName(slot);
722 
723  // check consitency of signal/slot methods/args
724  Int_t nsigargs;
725  if ((nsigargs = CheckConnectArgs(sender, sender->IsA(), signal_name, 0, slot_name)) == -1)
726  return kFALSE;
727 
728  if (!sender->fListOfSignals) sender->fListOfSignals = new THashList();
729 
730  TQConnectionList *clist = (TQConnectionList*)
731  sender->fListOfSignals->FindObject(signal_name);
732 
733  if (!clist) {
734  clist = new TQConnectionList(signal_name, nsigargs);
735  sender->fListOfSignals->Add(clist);
736  }
737 
738  TQConnection *connection = 0;
739  TIter next(clist);
740 
741  while ((connection = (TQConnection*)next())) {
742  if (!strcmp(slot_name,connection->GetName()) &&
743  (receiver == connection->GetReceiver())) break;
744  }
745 
746  if (!connection)
747  connection = new TQConnection(cl, receiver, slot_name);
748 
749  // check to prevent multiple entries
750  if (!clist->FindObject(connection)) {
751  clist->Add(connection);
752  if (!connection->FindObject(clist)) connection->Add(clist);
753  sender->Connected(signal_name);
754  }
755 
756  return kTRUE;
757 }
758 
759 ////////////////////////////////////////////////////////////////////////////////
760 /// This method allows to make a connection from any object
761 /// of the same class to a single slot.
762 /// Signal and slot string must have a form:
763 /// "Draw(char*, Option_t* ,Int_t)"
764 /// All blanks and "const" words will be removed,
765 ///
766 /// cl != 0 - class name, it can be class with or
767 /// without dictionary, e.g interpreted class.
768 /// Example:
769 /// ~~~ {.cpp}
770 /// TGButton *myButton;
771 /// TH2F *myHist;
772 ///
773 /// TQObject::Connect("TGButton", "Clicked()",
774 /// "TH2F", myHist, "Draw(Option_t*)");
775 /// ~~~
776 /// cl == 0 - corresponds to function (interpereted or global)
777 /// the name of the function is defined by the slot string,
778 /// parameter receiver should be 0.
779 /// Example:
780 /// ~~~ {.cpp}
781 /// TGButton *myButton;
782 /// TH2F *myHist;
783 ///
784 /// TQObject::Connect("TGButton", "Clicked()",
785 /// 0, 0, "hsimple()");
786 /// ~~~
787 /// Warning:
788 ///
789 /// If receiver class not derived from TQObject and going to be
790 /// deleted, disconnect all connections to this receiver.
791 /// In case of class derived from TQObject it is done automatically.
792 
793 Bool_t TQObject::Connect(const char *class_name,
794  const char *signal,
795  const char *cl,
796  void *receiver,
797  const char *slot)
798 {
799  if (cl) {
800  TClass *rcv_cl = TClass::GetClass(cl);
801  if (rcv_cl) return ConnectToClass(class_name, signal, rcv_cl, receiver,
802  slot);
803  }
804 
805  // the following is case of receiver class without dictionary
806  // e.g. interpreted class or function.
807 
808  TClass *sender = TClass::GetClass(class_name);
809 
810  // sender class should be TQObject (i.e. TQClass)
811  if (!sender || !sender->IsA()->InheritsFrom(TQObject::Class()))
812  return kFALSE;
813 
814  TList *slist = ((TQClass*)sender)->fListOfSignals;
815 
816  TString signal_name = CompressName(signal);
817  TString slot_name = CompressName(slot);
818 
819  // check consitency of signal/slot methods/args
820  Int_t nsigargs;
821  if ((nsigargs = CheckConnectArgs(0, sender, signal_name, 0, slot_name)) == -1)
822  return kFALSE;
823 
824  if (!slist) {
825  slist = ((TQClass*)sender)->fListOfSignals = new THashList();
826  }
827 
828  TQConnectionList *clist = (TQConnectionList*)
829  slist->FindObject(signal_name);
830 
831  if (!clist) {
832  clist = new TQConnectionList(signal_name, nsigargs);
833  slist->Add(clist);
834  }
835 
836  TQConnection *connection = 0;
837  TIter next(clist);
838 
839  while ((connection = (TQConnection*)next())) {
840  if (!strcmp(slot_name,connection->GetName()) &&
841  (receiver == connection->GetReceiver())) break;
842  }
843 
844  if (!connection)
845  connection = new TQConnection(cl, receiver, slot_name);
846 
847  // check to prevent multiple entries
848  if (!clist->FindObject(connection)) {
849  clist->Add(connection);
850  if (!connection->FindObject(clist)) connection->Add(clist);
851  ((TQClass*)sender)->Connected(signal_name);
852  }
853 
854  return kTRUE;
855 }
856 
857 ////////////////////////////////////////////////////////////////////////////////
858 /// Non-static method is used to connect from the signal
859 /// of this object to the receiver slot.
860 ///
861 /// Warning! No check on consistency of sender/receiver
862 /// classes/methods.
863 ///
864 /// This method makes possible to have connection/signals from
865 /// interpreted class. See also RQ_OBJECT.h.
866 
868  const char *receiver_class,
869  void *receiver,
870  const char *slot)
871 {
872  // remove "const" and strip blanks
873  TString signal_name = CompressName(signal);
874  TString slot_name = CompressName(slot);
875 
876  // check consitency of signal/slot methods/args
877  TClass *cl = 0;
878  if (receiver_class)
879  cl = TClass::GetClass(receiver_class);
880  Int_t nsigargs;
881  if ((nsigargs = CheckConnectArgs(this, IsA(), signal_name, cl, slot_name)) == -1)
882  return kFALSE;
883 
885 
886  TQConnectionList *clist = (TQConnectionList*)
887  fListOfSignals->FindObject(signal_name);
888 
889  if (!clist) {
890  clist = new TQConnectionList(signal_name, nsigargs);
891  fListOfSignals->Add(clist);
892  }
893 
894  TIter next(clist);
895  TQConnection *connection = 0;
896 
897  while ((connection = (TQConnection*)next())) {
898  if (!strcmp(slot_name,connection->GetName()) &&
899  (receiver == connection->GetReceiver())) break;
900  }
901 
902  if (!connection)
903  connection = new TQConnection(receiver_class, receiver, slot_name);
904 
905  // check to prevent multiple entries
906  if (!clist->FindObject(connection)) {
907  clist->Add(connection);
908  if (!connection->FindObject(clist)) connection->Add(clist);
909  Connected(signal_name);
910  }
911 
912  return kTRUE;
913 }
914 
915 ////////////////////////////////////////////////////////////////////////////////
916 /// Disconnects signal in object sender from slot_method in
917 /// object receiver. For objects derived from TQObject signal-slot
918 /// connection is removed when either of the objects involved
919 /// are destroyed.
920 ///
921 /// Disconnect() is typically used in three ways, as the following
922 /// examples shows:
923 ///
924 /// - Disconnect everything connected to an object's signals:
925 /// ~~~ {.cpp}
926 /// Disconnect(myObject);
927 /// ~~~
928 /// - Disconnect everything connected to a signal:
929 /// ~~~ {.cpp}
930 /// Disconnect(myObject, "mySignal()");
931 /// ~~~
932 /// - Disconnect a specific receiver:
933 /// ~~~ {.cpp}
934 /// Disconnect(myObject, 0, myReceiver, 0);
935 /// ~~~
936 ///
937 /// 0 may be used as a wildcard in three of the four arguments,
938 /// meaning "any signal", "any receiving object" or
939 /// "any slot in the receiving object", respectively.
940 ///
941 /// The sender has no default and may never be 0
942 /// (you cannot disconnect signals from more than one object).
943 ///
944 /// If signal is 0, it disconnects receiver and slot_method
945 /// from any signal. If not, only the specified signal is
946 /// disconnected.
947 ///
948 /// If receiver is 0, it disconnects anything connected to signal.
949 /// If not, slots in objects other than receiver are not
950 /// disconnected
951 ///
952 /// If slot_method is 0, it disconnects anything that is connected
953 /// to receiver. If not, only slots named slot_method will be
954 /// disconnected, and all other slots are left alone.
955 /// The slot_method must be 0 if receiver is left out, so you
956 /// cannot disconnect a specifically-named slot on all objects.
957 
959  const char *signal,
960  void *receiver,
961  const char *slot)
962 {
963  Bool_t return_value = kFALSE;
964  Bool_t next_return = kFALSE;
965 
966  if (!sender->GetListOfSignals()) return kFALSE;
967 
968  TString signal_name = CompressName(signal);
969  TString slot_name = CompressName(slot);
970 
971  TQConnectionList *slist = 0;
972  TIter next_signal(sender->GetListOfSignals());
973 
974  while ((slist = (TQConnectionList*)next_signal())) {
975  if (!signal || signal_name.IsNull()) { // disconnect all signals
976  next_return = slist->Disconnect(receiver,slot_name);
977  return_value = return_value || next_return;
978 
979  if (slist->IsEmpty()) {
980  sender->GetListOfSignals()->Remove(slist);
981  SafeDelete(slist); // delete empty list
982  }
983  } else if (signal && !strcmp(signal_name,slist->GetName())) {
984  next_return = slist->Disconnect(receiver,slot_name);
985  return_value = return_value || next_return;
986 
987  if (slist->IsEmpty()) {
988  sender->GetListOfSignals()->Remove(slist);
989  SafeDelete(slist); // delete empty list
990  break;
991  }
992  }
993  }
994 
995  if (sender->GetListOfSignals() && sender->GetListOfSignals()->IsEmpty()) {
996  SafeDelete(sender->fListOfSignals);
997  }
998 
999  return return_value;
1000 }
1001 
1002 ////////////////////////////////////////////////////////////////////////////////
1003 /// Disconnects "class signal". The class is defined by class_name.
1004 /// See also Connect(class_name,signal,receiver,slot).
1005 
1006 Bool_t TQObject::Disconnect(const char *class_name,
1007  const char *signal,
1008  void *receiver,
1009  const char *slot)
1010 {
1011  TClass *sender = TClass::GetClass(class_name);
1012 
1013  // sender should be TQClass (which derives from TQObject)
1014  if (!sender->IsA()->InheritsFrom(TQObject::Class()))
1015  return kFALSE;
1016 
1017  TQClass *qcl = (TQClass*)sender; // cast TClass to TQClass
1018  return Disconnect(qcl, signal, receiver, slot);
1019 }
1020 
1021 ////////////////////////////////////////////////////////////////////////////////
1022 /// Disconnects signal of this object from slot of receiver.
1023 /// Equivalent to Disconnect(this, signal, receiver, slot)
1024 
1026  void *receiver,
1027  const char *slot)
1028 {
1029  return Disconnect(this, signal, receiver, slot);
1030 }
1031 
1032 ////////////////////////////////////////////////////////////////////////////////
1033 /// Stream an object of class TQObject.
1034 
1035 void TQObject::Streamer(TBuffer &R__b)
1036 {
1037  if (R__b.IsReading()) {
1038  // nothing to read
1039  } else {
1040  // nothing to write
1041  }
1042 }
1043 
1044 ////////////////////////////////////////////////////////////////////////////////
1045 /// Returns true if all signals are blocked.
1046 
1048 {
1049  return fgAllSignalsBlocked;
1050 }
1051 
1052 ////////////////////////////////////////////////////////////////////////////////
1053 /// Block or unblock all signals. Returns the previous block status.
1054 
1056 {
1059  return ret;
1060 }
1061 
1062 ////////////////////////////////////////////////////////////////////////////////
1063 /// Global function which simplifies making connection in interpreted ROOT session
1064 ///
1065 /// ConnectCINT - connects to interpreter(CINT) command
1066 
1067 Bool_t ConnectCINT(TQObject *sender, const char *signal, const char *slot)
1068 {
1069  TString str = "ProcessLine(=";
1070  str += '"';
1071  str += slot;
1072  str += '"';
1073  str += ")";
1074  return TQObject::Connect(sender, signal, "TInterpreter",
1075  gInterpreter, str.Data());
1076 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:145
Bool_t IsReading() const
Definition: TBuffer.h:83
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3507
static Bool_t BlockAllSignals(Bool_t b)
Block or unblock all signals. Returns the previous block status.
Definition: TQObject.cxx:1055
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
TQObject()
TQObject Constructor.
Definition: TQObject.cxx:393
auto * m
Definition: textangle.C:8
static Int_t CheckConnectArgs(TQObject *sender, TClass *sender_class, const char *signal, TClass *receiver_class, const char *slot)
Checking of consitency of sender/receiver methods/arguments.
Definition: TQObject.cxx:181
virtual const char * GetSenderClassName() const
Definition: TQObject.h:59
Bool_t ConnectCINT(TQObject *sender, const char *signal, const char *slot)
Global function which simplifies making connection in interpreted ROOT session.
Definition: TQObject.cxx:1067
const char Option_t
Definition: RtypesCore.h:62
TList * fListOfSignals
Definition: TQObject.h:52
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition: TList.cxx:97
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
This is the ROOT implementation of the Qt object communication mechanism (see also http://www...
Definition: TQObject.h:49
This class implements a mutex interface.
Definition: TVirtualMutex.h:34
#define gROOT
Definition: TROOT.h:410
Basic string class.
Definition: TString.h:131
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
#define gInterpreter
Definition: TInterpreter.h:527
virtual void AddLast(TObject *obj)
Add object at the end of the list.
Definition: TList.cxx:149
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
void * GetReceiver() const
Definition: TQConnection.h:90
void Class()
Definition: Class.C:29
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:34
Provides iteration through tokens of a given string.
Definition: TPRegexp.h:143
virtual const char * GetCommentString()
Returns a comment string from the class declaration.
Definition: TMethod.cxx:105
TList * GetListOfClassSignals() const
Returns pointer to list of signals of this class.
Definition: TQObject.cxx:435
void Error(const char *location, const char *msgfmt,...)
TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
Definition: Cppyy.cxx:727
A doubly linked list.
Definition: TList.h:44
TList * fListOfConnections
list of signals from this object
Definition: TQObject.h:53
Bool_t Connect(const char *signal, const char *receiver_class, void *receiver, const char *slot)
Non-static method is used to connect from the signal of this object to the receiver slot...
Definition: TQObject.cxx:867
static Bool_t fgAllSignalsBlocked
flag used for suppression of signals
Definition: TQObject.h:56
Int_t GetNargs() const
Number of function arguments.
Definition: TFunction.cxx:164
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
TQConnection class is an internal class, used in the object communication mechanism.
Definition: TQConnection.h:37
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
virtual Int_t NumberOfSignals() const
Return number of signals for this object.
Definition: TQObject.cxx:539
static Bool_t ConnectToClass(TQObject *sender, const char *signal, TClass *receiver_class, void *receiver, const char *slot)
Create connection between sender and receiver.
Definition: TQObject.cxx:561
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:405
virtual Int_t NumberOfConnections() const
Return number of connections for this object.
Definition: TQObject.cxx:549
Bool_t AtEnd() const
Definition: TPRegexp.h:156
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
void * gTQSender
Definition: TQObject.cxx:76
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4688
virtual ~TQObject()
TQObject Destructor.
Definition: TQObject.cxx:404
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
Bool_t fSignalsBlocked
list of connections to this object
Definition: TQObject.h:54
#define R__LOCKGUARD2(mutex)
const Bool_t kFALSE
Definition: RtypesCore.h:88
#define SafeDelete(p)
Definition: RConfig.h:529
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
virtual void Destroyed()
Definition: TQObject.h:197
virtual Bool_t IsEmpty() const
Definition: TCollection.h:186
void Print(std::ostream &os, const OptionType &opt)
static Bool_t AreAllSignalsBlocked()
Returns true if all signals are blocked.
Definition: TQObject.cxx:1047
TMethod * GetMethod(const char *method, const char *params, Bool_t objectIsConst=kFALSE)
Find the best method (if there is one) matching the parameters.
Definition: TClass.cxx:4232
Bool_t Disconnect(const char *signal=0, void *receiver=0, const char *slot=0)
Disconnects signal of this object from slot of receiver.
Definition: TQObject.cxx:1025
virtual Bool_t HasConnection(const char *signal_name) const
Return true if there is any object connected to this signal.
Definition: TQObject.cxx:525
Bool_t NextToken()
Get the next token, it is stored in this TString.
Definition: TPRegexp.cxx:977
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2887
const char * GetName() const override
Returns name of connection (aka name of slot)
TList * GetListOfSignals() const
Definition: TQObject.h:89
Bool_t IsNull() const
Definition: TString.h:402
Global functions class (global functions are obtained from CINT).
Definition: TFunction.h:28
char Char_t
Definition: RtypesCore.h:29
virtual void Connected(const char *)
Definition: TQObject.h:194
const char * GetFullTypeName() const
Get full type description of typedef, e,g.: "class TDirectory*".
Definition: TDataType.cxx:175
#define ClassImpQ(name)
Definition: TQObject.h:283
virtual void Add(TObject *obj)
Definition: TList.h:87
Wrapper for PCRE library (Perl Compatible Regular Expressions).
Definition: TPRegexp.h:97
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
static TString CompressName(const char *method_name)
Removes "const" words and blanks from full (with prototype) method name and resolve any typedefs in t...
Definition: TQObject.cxx:100
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
const char * proto
Definition: civetweb.c:15049
virtual void LowPriority(const char *signal_name, const char *slot_name=0)
Definition: TQObject.cxx:503
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
Int_t Substitute(TString &s, const TString &r, Bool_t doDollarSubst=kTRUE)
Substitute matching part of s with r, dollar back-ref substitution is performed if doDollarSubst is t...
Definition: TPRegexp.cxx:874
TMethod * GetMethodWithPrototype(const char *method, const char *proto, Bool_t objectIsConst=kFALSE, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
Find the method with a given prototype.
Definition: TClass.cxx:4277
void CollectClassSignalLists(TList &list, TClass *cls)
Collect class signal lists from class cls and all its base-classes.
Definition: TQObject.cxx:451
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t GetNargsOpt() const
Number of function optional (default) arguments.
Definition: TFunction.cxx:174
char name[80]
Definition: TGX11.cxx:109
virtual void HighPriority(const char *signal_name, const char *slot_name=0)
Definition: TQObject.cxx:477
const char * Data() const
Definition: TString.h:364