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  if (!fListOfSignals) return;
477  TQConnectionList *clist = (TQConnectionList*)
478  fListOfSignals->FindObject(signal_name);
479 
480  if (!clist) return; // not found
481  if (!slot_name) { // update list of signal lists
482  fListOfSignals->Remove(clist); // remove and add first
483  fListOfSignals->AddFirst(clist);
484  return;
485  } else { // slot_name != 0 , update signal list
486  TQConnection *con = (TQConnection*) clist->FindObject(slot_name);
487  if (!con) return; // not found
488  clist->Remove(con); // remove and add as first
489  clist->AddFirst(con);
490  }
491 }
492 
493 ////////////////////////////////////////////////////////////////////////////////
494 /// 1. If slot_name = 0 => makes signal defined by the signal_name
495 /// to be the last in the fListOfSignals, this increase the time
496 /// for lookup.
497 /// 2. If slot_name != 0 => makes slot defined by the slot_name
498 /// to be executed last when signal_name is emitted.
499 /// Signal name is not compressed.
500 
501 void TQObject::LowPriority(const char *signal_name, const char *slot_name)
502 {
503  if (!fListOfSignals) return;
504  TQConnectionList *clist = (TQConnectionList*)
505  fListOfSignals->FindObject(signal_name);
506 
507  if (!clist) return;
508  if (!slot_name) {
509  fListOfSignals->Remove(clist); // remove and add first
510  fListOfSignals->AddLast(clist);
511  return;
512  } else { // slot_name != 0 , update signal list
513  TQConnection *con = (TQConnection*) clist->FindObject(slot_name);
514  if (!con) return;
515  clist->Remove(con); // remove and add as last
516  clist->AddLast(con);
517  }
518 }
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 /// Return true if there is any object connected to this signal.
522 /// Only checks for object signals.
523 
524 Bool_t TQObject::HasConnection(const char *signal_name) const
525 {
526  if (!fListOfSignals)
527  return kFALSE;
528 
529  TString signal = CompressName(signal_name);
530 
531  return (fListOfSignals->FindObject(signal) != 0);
532 }
533 
534 ////////////////////////////////////////////////////////////////////////////////
535 /// Return number of signals for this object.
536 /// Only checks for object signals.
537 
539 {
540  if (fListOfSignals)
541  return fListOfSignals->GetSize();
542  return 0;
543 }
544 
545 ////////////////////////////////////////////////////////////////////////////////
546 /// Return number of connections for this object.
547 
549 {
550  if (fListOfConnections)
551  return fListOfConnections->GetSize();
552  return 0;
553 }
554 
555 
556 ////////////////////////////////////////////////////////////////////////////////
557 /// Create connection between sender and receiver.
558 /// Receiver class needs to have a dictionary.
559 
561  const char *signal,
562  TClass *cl,
563  void *receiver,
564  const char *slot)
565 {
566  // sender should be TQObject
567  if (!sender->IsA()->InheritsFrom(TQObject::Class()))
568  return kFALSE;
569 
570  // remove "const" and strip blanks
571  TString signal_name = CompressName(signal);
572  TString slot_name = CompressName(slot);
573 
574  // check consitency of signal/slot methods/args
575  Int_t nsigargs;
576  if ((nsigargs = CheckConnectArgs(sender, sender->IsA(), signal_name, cl, slot_name)) == -1)
577  return kFALSE;
578 
579  if (!sender->fListOfSignals)
580  sender->fListOfSignals = new THashList();
581 
582  TQConnectionList *clist = (TQConnectionList*)
583  sender->fListOfSignals->FindObject(signal_name);
584 
585  if (!clist) {
586  clist = new TQConnectionList(signal_name, nsigargs);
587  sender->fListOfSignals->Add(clist);
588  }
589 
590  TIter next(clist);
591  TQConnection *connection = 0;
592 
593  while ((connection = (TQConnection*)next())) {
594  if (!strcmp(slot_name,connection->GetName()) &&
595  (receiver == connection->GetReceiver())) break;
596  }
597 
598  if (!connection)
599  connection = new TQConnection(cl, receiver, slot_name);
600 
601  // check to prevent multiple entries
602  if (!clist->FindObject(connection)) {
603  clist->Add(connection);
604  if (!connection->FindObject(clist)) connection->Add(clist);
605  sender->Connected(signal_name);
606  }
607 
608  return kTRUE;
609 }
610 
611 ////////////////////////////////////////////////////////////////////////////////
612 /// This method allows to make connection from any object
613 /// of the same class to the receiver object.
614 /// Receiver class needs to have a dictionary.
615 
616 Bool_t TQObject::ConnectToClass(const char *class_name,
617  const char *signal,
618  TClass *cl,
619  void *receiver,
620  const char *slot)
621 {
622  TClass *sender = TClass::GetClass(class_name);
623 
624  // sender class should be TQObject (i.e. TQClass)
625  if (!sender || !sender->IsA()->InheritsFrom(TQObject::Class()))
626  return kFALSE;
627 
628  TList *slist = ((TQClass*)sender)->fListOfSignals;
629  TString signal_name = CompressName(signal);
630  TString slot_name = CompressName(slot);
631 
632  // check consitency of signal/slot methods/args
633  Int_t nsigargs;
634  if ((nsigargs = CheckConnectArgs(0, sender, signal_name, cl, slot_name)) == -1)
635  return kFALSE;
636 
637  if (!slist)
638  ((TQClass*)sender)->fListOfSignals = slist = new THashList();
639 
640  TQConnectionList *clist = (TQConnectionList*) slist->FindObject(signal_name);
641 
642  if (!clist) {
643  clist = new TQConnectionList(signal_name, nsigargs);
644  slist->Add(clist);
645  }
646 
647  TQConnection *connection = 0;
648  TIter next(clist);
649 
650  while ((connection = (TQConnection*)next())) {
651  if (!strcmp(slot_name,connection->GetName()) &&
652  (receiver == connection->GetReceiver())) break;
653  }
654 
655  if (!connection)
656  connection = new TQConnection(cl, receiver, slot_name);
657 
658  // check to prevent multiple entries
659  if (!clist->FindObject(connection)) {
660  clist->Add(connection);
661  if (!connection->FindObject(clist)) connection->Add(clist);
662  ((TQClass*)sender)->Connected(signal_name);
663  }
664 
665  return kTRUE;
666 }
667 
668 ////////////////////////////////////////////////////////////////////////////////
669 /// Create connection between sender and receiver.
670 /// Signal and slot string must have a form:
671 /// "Draw(char*, Option_t* ,Int_t)"
672 /// All blanks and "const" words will be removed,
673 ///
674 /// cl != 0 - class name, it can be class with or
675 /// without dictionary, e.g interpreted class.
676 /// Example:
677 /// ~~~ {.cpp}
678 /// TGButton *myButton;
679 /// TH2F *myHist;
680 ///
681 /// TQObject::Connect(myButton,"Clicked()",
682 /// "TH2F", myHist,"Draw(Option_t*)");
683 /// ~~~
684 /// cl == 0 - corresponds to function (interpereted or global)
685 /// the name of the function is defined by the slot string,
686 /// parameter receiver should be 0.
687 /// Example:
688 /// ~~~ {.cpp}
689 /// TGButton *myButton;
690 /// TH2F *myHist;
691 ///
692 /// TQObject::Connect(myButton,"Clicked()",
693 /// 0, 0,"hsimple()");
694 /// ~~~
695 /// Warning:
696 /// If receiver is class not derived from TQObject and going to be
697 /// deleted, disconnect all connections to this receiver.
698 /// In case of class derived from TQObject it is done automatically.
699 
701  const char *signal,
702  const char *cl,
703  void *receiver,
704  const char *slot)
705 {
706  if (cl) {
707  TClass *rcv_cl = TClass::GetClass(cl);
708  if (rcv_cl) return ConnectToClass(sender, signal, rcv_cl, receiver, slot);
709  }
710 
711  // the following is the case of receiver class without dictionary
712  // e.g. interpreted class or function.
713 
714  // sender should be TQObject
715  if (!sender->IsA()->InheritsFrom(TQObject::Class()))
716  return kFALSE;
717 
718  // remove "const" and strip blanks
719  TString signal_name = CompressName(signal);
720  TString slot_name = CompressName(slot);
721 
722  // check consitency of signal/slot methods/args
723  Int_t nsigargs;
724  if ((nsigargs = CheckConnectArgs(sender, sender->IsA(), signal_name, 0, slot_name)) == -1)
725  return kFALSE;
726 
727  if (!sender->fListOfSignals) sender->fListOfSignals = new THashList();
728 
729  TQConnectionList *clist = (TQConnectionList*)
730  sender->fListOfSignals->FindObject(signal_name);
731 
732  if (!clist) {
733  clist = new TQConnectionList(signal_name, nsigargs);
734  sender->fListOfSignals->Add(clist);
735  }
736 
737  TQConnection *connection = 0;
738  TIter next(clist);
739 
740  while ((connection = (TQConnection*)next())) {
741  if (!strcmp(slot_name,connection->GetName()) &&
742  (receiver == connection->GetReceiver())) break;
743  }
744 
745  if (!connection)
746  connection = new TQConnection(cl, receiver, slot_name);
747 
748  // check to prevent multiple entries
749  if (!clist->FindObject(connection)) {
750  clist->Add(connection);
751  if (!connection->FindObject(clist)) connection->Add(clist);
752  sender->Connected(signal_name);
753  }
754 
755  return kTRUE;
756 }
757 
758 ////////////////////////////////////////////////////////////////////////////////
759 /// This method allows to make a connection from any object
760 /// of the same class to a single slot.
761 /// Signal and slot string must have a form:
762 /// "Draw(char*, Option_t* ,Int_t)"
763 /// All blanks and "const" words will be removed,
764 ///
765 /// cl != 0 - class name, it can be class with or
766 /// without dictionary, e.g interpreted class.
767 /// Example:
768 /// ~~~ {.cpp}
769 /// TGButton *myButton;
770 /// TH2F *myHist;
771 ///
772 /// TQObject::Connect("TGButton", "Clicked()",
773 /// "TH2F", myHist, "Draw(Option_t*)");
774 /// ~~~
775 /// cl == 0 - corresponds to function (interpereted or global)
776 /// the name of the function is defined by the slot string,
777 /// parameter receiver should be 0.
778 /// Example:
779 /// ~~~ {.cpp}
780 /// TGButton *myButton;
781 /// TH2F *myHist;
782 ///
783 /// TQObject::Connect("TGButton", "Clicked()",
784 /// 0, 0, "hsimple()");
785 /// ~~~
786 /// Warning:
787 ///
788 /// If receiver class not derived from TQObject and going to be
789 /// deleted, disconnect all connections to this receiver.
790 /// In case of class derived from TQObject it is done automatically.
791 
792 Bool_t TQObject::Connect(const char *class_name,
793  const char *signal,
794  const char *cl,
795  void *receiver,
796  const char *slot)
797 {
798  if (cl) {
799  TClass *rcv_cl = TClass::GetClass(cl);
800  if (rcv_cl) return ConnectToClass(class_name, signal, rcv_cl, receiver,
801  slot);
802  }
803 
804  // the following is case of receiver class without dictionary
805  // e.g. interpreted class or function.
806 
807  TClass *sender = TClass::GetClass(class_name);
808 
809  // sender class should be TQObject (i.e. TQClass)
810  if (!sender || !sender->IsA()->InheritsFrom(TQObject::Class()))
811  return kFALSE;
812 
813  TList *slist = ((TQClass*)sender)->fListOfSignals;
814 
815  TString signal_name = CompressName(signal);
816  TString slot_name = CompressName(slot);
817 
818  // check consitency of signal/slot methods/args
819  Int_t nsigargs;
820  if ((nsigargs = CheckConnectArgs(0, sender, signal_name, 0, slot_name)) == -1)
821  return kFALSE;
822 
823  if (!slist) {
824  slist = ((TQClass*)sender)->fListOfSignals = new THashList();
825  }
826 
827  TQConnectionList *clist = (TQConnectionList*)
828  slist->FindObject(signal_name);
829 
830  if (!clist) {
831  clist = new TQConnectionList(signal_name, nsigargs);
832  slist->Add(clist);
833  }
834 
835  TQConnection *connection = 0;
836  TIter next(clist);
837 
838  while ((connection = (TQConnection*)next())) {
839  if (!strcmp(slot_name,connection->GetName()) &&
840  (receiver == connection->GetReceiver())) break;
841  }
842 
843  if (!connection)
844  connection = new TQConnection(cl, receiver, slot_name);
845 
846  // check to prevent multiple entries
847  if (!clist->FindObject(connection)) {
848  clist->Add(connection);
849  if (!connection->FindObject(clist)) connection->Add(clist);
850  ((TQClass*)sender)->Connected(signal_name);
851  }
852 
853  return kTRUE;
854 }
855 
856 ////////////////////////////////////////////////////////////////////////////////
857 /// Non-static method is used to connect from the signal
858 /// of this object to the receiver slot.
859 ///
860 /// Warning! No check on consistency of sender/receiver
861 /// classes/methods.
862 ///
863 /// This method makes possible to have connection/signals from
864 /// interpreted class. See also RQ_OBJECT.h.
865 
866 Bool_t TQObject::Connect(const char *signal,
867  const char *receiver_class,
868  void *receiver,
869  const char *slot)
870 {
871  // remove "const" and strip blanks
872  TString signal_name = CompressName(signal);
873  TString slot_name = CompressName(slot);
874 
875  // check consitency of signal/slot methods/args
876  TClass *cl = 0;
877  if (receiver_class)
878  cl = TClass::GetClass(receiver_class);
879  Int_t nsigargs;
880  if ((nsigargs = CheckConnectArgs(this, IsA(), signal_name, cl, slot_name)) == -1)
881  return kFALSE;
882 
884 
885  TQConnectionList *clist = (TQConnectionList*)
886  fListOfSignals->FindObject(signal_name);
887 
888  if (!clist) {
889  clist = new TQConnectionList(signal_name, nsigargs);
890  fListOfSignals->Add(clist);
891  }
892 
893  TIter next(clist);
894  TQConnection *connection = 0;
895 
896  while ((connection = (TQConnection*)next())) {
897  if (!strcmp(slot_name,connection->GetName()) &&
898  (receiver == connection->GetReceiver())) break;
899  }
900 
901  if (!connection)
902  connection = new TQConnection(receiver_class, receiver, slot_name);
903 
904  // check to prevent multiple entries
905  if (!clist->FindObject(connection)) {
906  clist->Add(connection);
907  if (!connection->FindObject(clist)) connection->Add(clist);
908  Connected(signal_name);
909  }
910 
911  return kTRUE;
912 }
913 
914 ////////////////////////////////////////////////////////////////////////////////
915 /// Disconnects signal in object sender from slot_method in
916 /// object receiver. For objects derived from TQObject signal-slot
917 /// connection is removed when either of the objects involved
918 /// are destroyed.
919 ///
920 /// Disconnect() is typically used in three ways, as the following
921 /// examples shows:
922 ///
923 /// - Disconnect everything connected to an object's signals:
924 /// ~~~ {.cpp}
925 /// Disconnect(myObject);
926 /// ~~~
927 /// - Disconnect everything connected to a signal:
928 /// ~~~ {.cpp}
929 /// Disconnect(myObject, "mySignal()");
930 /// ~~~
931 /// - Disconnect a specific receiver:
932 /// ~~~ {.cpp}
933 /// Disconnect(myObject, 0, myReceiver, 0);
934 /// ~~~
935 ///
936 /// 0 may be used as a wildcard in three of the four arguments,
937 /// meaning "any signal", "any receiving object" or
938 /// "any slot in the receiving object", respectively.
939 ///
940 /// The sender has no default and may never be 0
941 /// (you cannot disconnect signals from more than one object).
942 ///
943 /// If signal is 0, it disconnects receiver and slot_method
944 /// from any signal. If not, only the specified signal is
945 /// disconnected.
946 ///
947 /// If receiver is 0, it disconnects anything connected to signal.
948 /// If not, slots in objects other than receiver are not
949 /// disconnected
950 ///
951 /// If slot_method is 0, it disconnects anything that is connected
952 /// to receiver. If not, only slots named slot_method will be
953 /// disconnected, and all other slots are left alone.
954 /// The slot_method must be 0 if receiver is left out, so you
955 /// cannot disconnect a specifically-named slot on all objects.
956 
958  const char *signal,
959  void *receiver,
960  const char *slot)
961 {
962  Bool_t return_value = kFALSE;
963  Bool_t next_return = kFALSE;
964 
965  if (!sender->GetListOfSignals()) return kFALSE;
966 
967  TString signal_name = CompressName(signal);
968  TString slot_name = CompressName(slot);
969 
970  TQConnectionList *slist = 0;
971  TIter next_signal(sender->GetListOfSignals());
972 
973  while ((slist = (TQConnectionList*)next_signal())) {
974  if (!signal || signal_name.IsNull()) { // disconnect all signals
975  next_return = slist->Disconnect(receiver,slot_name);
976  return_value = return_value || next_return;
977 
978  if (slist->IsEmpty()) {
979  sender->GetListOfSignals()->Remove(slist);
980  SafeDelete(slist); // delete empty list
981  }
982  } else if (signal && !strcmp(signal_name,slist->GetName())) {
983  next_return = slist->Disconnect(receiver,slot_name);
984  return_value = return_value || next_return;
985 
986  if (slist->IsEmpty()) {
987  sender->GetListOfSignals()->Remove(slist);
988  SafeDelete(slist); // delete empty list
989  break;
990  }
991  }
992  }
993 
994  if (sender->GetListOfSignals() && sender->GetListOfSignals()->IsEmpty()) {
995  SafeDelete(sender->fListOfSignals);
996  }
997 
998  return return_value;
999 }
1000 
1001 ////////////////////////////////////////////////////////////////////////////////
1002 /// Disconnects "class signal". The class is defined by class_name.
1003 /// See also Connect(class_name,signal,receiver,slot).
1004 
1005 Bool_t TQObject::Disconnect(const char *class_name,
1006  const char *signal,
1007  void *receiver,
1008  const char *slot)
1009 {
1010  TClass *sender = TClass::GetClass(class_name);
1011 
1012  // sender should be TQClass (which derives from TQObject)
1013  if (!sender || !sender->IsA()->InheritsFrom(TQObject::Class()))
1014  return kFALSE;
1015 
1016  TQClass *qcl = (TQClass*)sender; // cast TClass to TQClass
1017  return Disconnect(qcl, signal, receiver, slot);
1018 }
1019 
1020 ////////////////////////////////////////////////////////////////////////////////
1021 /// Disconnects signal of this object from slot of receiver.
1022 /// Equivalent to Disconnect(this, signal, receiver, slot)
1023 
1024 Bool_t TQObject::Disconnect(const char *signal,
1025  void *receiver,
1026  const char *slot)
1027 {
1028  return Disconnect(this, signal, receiver, slot);
1029 }
1030 
1031 ////////////////////////////////////////////////////////////////////////////////
1032 /// Stream an object of class TQObject.
1033 
1034 void TQObject::Streamer(TBuffer &R__b)
1035 {
1036  if (R__b.IsReading()) {
1037  // nothing to read
1038  } else {
1039  // nothing to write
1040  }
1041 }
1042 
1043 ////////////////////////////////////////////////////////////////////////////////
1044 /// Returns true if all signals are blocked.
1045 
1047 {
1048  return fgAllSignalsBlocked;
1049 }
1050 
1051 ////////////////////////////////////////////////////////////////////////////////
1052 /// Block or unblock all signals. Returns the previous block status.
1053 
1055 {
1058  return ret;
1059 }
1060 
1061 ////////////////////////////////////////////////////////////////////////////////
1062 /// Global function which simplifies making connection in interpreted ROOT session
1063 ///
1064 /// ConnectCINT - connects to interpreter(CINT) command
1065 
1066 Bool_t ConnectCINT(TQObject *sender, const char *signal, const char *slot)
1067 {
1068  TString str = "ProcessLine(=";
1069  str += '"';
1070  str += slot;
1071  str += '"';
1072  str += ")";
1073  return TQObject::Connect(sender, signal, "TInterpreter",
1074  gInterpreter, str.Data());
1075 }
m
auto * m
Definition: textangle.C:8
TPMERegexp
Wrapper for PCRE library (Perl Compatible Regular Expressions).
Definition: TPRegexp.h:97
ROOT::Math::IntegOptionsUtil::Print
void Print(std::ostream &os, const OptionType &opt)
Definition: IntegratorOptions.cxx:91
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:1024
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:100
Option_t
const char Option_t
Definition: RtypesCore.h:66
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:578
TList::Delete
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:470
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:560
TMethod.h
TStringToken
Provides iteration through tokens of a given string.
Definition: TPRegexp.h:143
gInterpreter
#define gInterpreter
Definition: TInterpreter.h:560
TBaseClass
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
Int_t
int Int_t
Definition: RtypesCore.h:45
TQClass.h
TVirtualMutex
This class implements a mutex interface.
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
Buffer base class used for serializing objects.
Definition: TBuffer.h:43
TQConnection
TQConnection class is an internal class, used in the object communication mechanism.
Definition: TQConnection.h:37
TList::AddLast
virtual void AddLast(TObject *obj)
Add object at the end of the list.
Definition: TList.cxx:152
TBaseClass::GetClassPointer
TClass * GetClassPointer(Bool_t load=kTRUE)
Get pointer to the base class TClass.
Definition: TBaseClass.cxx:63
TString
Basic string class.
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:1054
b
#define b(i)
Definition: RSha256.hxx:100
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:538
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:4424
TQObject
This is the ROOT implementation of the Qt object communication mechanism (see also http://www....
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
TClass::InheritsFrom
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4835
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
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
THashList
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:34
TClass::GetListOfBases
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3587
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:4379
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:92
TMethod
Each ROOT class (see TClass) has a linked list of methods.
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:1066
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:2932
TQObject::NumberOfConnections
virtual Int_t NumberOfConnections() const
Return number of connections for this object.
Definition: TQObject.cxx:548
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:501
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:866
Cppyy::GetMethod
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
Definition: clingwrapper.cxx:1386
TList::Remove
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:822
TCollection::GetSize
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
TInterpreter.h
TClass
TClass instances represent classes, structs and namespaces in the ROOT type system.
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:1046
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:47
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:524
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
Global functions class (global functions are obtained from CINT).
Definition: TFunction.h:30
TList
A doubly linked list.
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