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