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 #include "strlcpy.h"
73 
74 void *gTQSender; // A pointer to the object that sent the last signal.
75  // Getting access to the sender might be practical
76  // when many signals are connected to a single slot.
77 
79 
80 
84 
85 ////////////////////////////////////////////////////////////////////////////////
86 /// Removes "const" words and blanks from full (with prototype)
87 /// method name and resolve any typedefs in the method signature.
88 /// If a null or empty string is passed in, an empty string
89 /// is returned.
90 ///
91 /// Example:
92 /// ~~~ {.cpp}
93 /// CompressName(" Draw(const char *, const char *,
94 /// Option_t * , Int_t , Int_t)");
95 /// ~~~
96 /// returns the string "Draw(char*,char*,char*,int,int)".
97 
98 TString TQObject::CompressName(const char *method_name)
99 {
100  TString res(method_name);
101  if (res.IsNull())
102  return res;
103 
104  {
105  static TVirtualMutex * lock = nullptr;
106  R__LOCKGUARD2(lock);
107 
108  static TPMERegexp *constRe = nullptr, *wspaceRe = nullptr;
109  if (constRe == nullptr) {
110  constRe = new TPMERegexp("(?<=\\(|\\s|,|&|\\*)const(?=\\s|,|\\)|&|\\*)", "go");
111  wspaceRe = new TPMERegexp("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", "go");
112  }
113  constRe ->Substitute(res, "");
114  wspaceRe->Substitute(res, "");
115  }
116 
117  TStringToken methargs(res, "\\(|\\)", kTRUE);
118 
119  methargs.NextToken();
120  res = methargs;
121  res += "(";
122 
123  methargs.NextToken();
124  TStringToken arg(methargs, ",");
125  while (arg.NextToken())
126  {
127  Int_t pri = arg.Length() - 1;
128  Char_t prc = 0;
129  if (arg[pri] == '*' || arg[pri] == '&') {
130  prc = arg[pri];
131  arg.Remove(pri);
132  }
133  TDataType *dt = gROOT->GetType(arg.Data());
134  if (dt) {
135  res += dt->GetFullTypeName();
136  } else {
137  res += arg;
138  }
139  if (prc) res += prc;
140  if (!arg.AtEnd()) res += ",";
141  }
142  res += ")";
143  return res;
144 }
145 
146 namespace {
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 /// Almost the same as TClass::GetMethodWithPrototype().
150 
151 TMethod *GetMethodWithPrototype(TClass *cl, const char *method,
152  const char *proto, Int_t &nargs)
153 {
154  nargs = 0;
155 
156  if (!gInterpreter || cl == nullptr) return nullptr;
157 
158  TMethod *m = cl->GetMethodWithPrototype(method,proto);
159  if (m) nargs = m->GetNargs();
160  return m;
161 }
162 
163 ////////////////////////////////////////////////////////////////////////////////
164 /// Almost the same as TClass::GetMethod().
165 
166 static TMethod *GetMethod(TClass *cl, const char *method, const char *params)
167 {
168  if (!gInterpreter || cl == nullptr) return nullptr;
169  return cl->GetMethod(method,params);
170 }
171 
172 }
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 /// Checking of consistency of sender/receiver methods/arguments.
176 /// Returns -1 on error, otherwise number or arguments of signal function.
177 /// Static method.
178 
180  TClass *sender_class, const char *signal,
181  TClass *receiver_class, const char *slot)
182 {
183  auto len = strlen(signal)+1;
184  char *signal_method = new char[len];
185  if (signal_method) strlcpy(signal_method, signal, len);
186 
187  char *signal_proto;
188  char *tmp;
189 
190  if ((signal_proto = strchr(signal_method,'('))) {
191  // substitute first '(' symbol with '\0'
192  *signal_proto++ = '\0';
193  // substitute last ')' symbol with '\0'
194  if ((tmp = strrchr(signal_proto,')'))) *tmp = '\0';
195  }
196 
197  if (!signal_proto) signal_proto = (char*)""; // avoid zero strings
198 
199  // if delegation object TQObjSender is used get the real sender class
200  if (sender && sender_class == TQObjSender::Class()) {
201  sender_class = TClass::GetClass(sender->GetSenderClassName());
202  if (!sender_class) {
203  ::Error("TQObject::CheckConnectArgs", "for signal/slot consistency\n"
204  "checking need to specify class name as argument to "
205  "RQ_OBJECT macro");
206  delete [] signal_method;
207  return -1;
208  }
209  }
210 
211  Int_t nargs;
212  TMethod *signalMethod = GetMethodWithPrototype(sender_class,
213  signal_method,
214  signal_proto,
215  nargs);
216  if (!signalMethod) {
217  ::Error("TQObject::CheckConnectArgs", "signal %s::%s(%s) does not exist",
218  sender_class->GetName(), signal_method, signal_proto);
219  delete [] signal_method;
220  return -1;
221  }
222  Int_t nsigargs = nargs;
223 
224 #if defined(CHECK_COMMENT_STRING)
225  const char *comment = 0;
226  if (signalMethod != (TMethod *) -1) // -1 in case of interpreted class
227  comment = signalMethod->GetCommentString();
228 
229  if (!comment || !comment[0] || strstr(comment,"*SIGNAL")){
230  ::Error("TQObject::CheckConnectArgs",
231  "signal %s::%s(%s), to declare signal use comment //*SIGNAL*",
232  sender_class->GetName(), signal_method, signal_proto);
233  delete [] signal_method;
234  return -1;
235  }
236 #endif
237 
238  // cleaning
239  delete [] signal_method;
240 
241  auto len2 = strlen(slot)+1;
242  char *slot_method = new char[len2];
243  if (slot_method) strlcpy(slot_method, slot, len2);
244 
245  char *slot_proto;
246  char *slot_params = nullptr;
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 = nullptr;
261  if (!receiver_class) {
262  // case of slot_method is compiled/intrepreted function
263  slotMethod = gROOT->GetGlobalFunction(slot_method,nullptr,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=nullptr, const char *slot_name=nullptr);
320  Int_t GetNargs() const { return fSignalArgs; }
321  void ls(Option_t *option = "") const;
322 };
323 
324 ////////////////////////////////////////////////////////////////////////////////
325 /// Destructor.
326 
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 = nullptr;
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 = nullptr;
396  fListOfConnections = nullptr;
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 = nullptr;
438 
439  qcl = dynamic_cast<TQClass*>(IsA());
440 
441  return qcl ? qcl->fListOfSignals : nullptr; //!!
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  {
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  if (!fListOfSignals) return;
481  fListOfSignals->FindObject(signal_name);
482 
483  if (!clist) return; // not found
484  if (!slot_name) { // update list of signal lists
485  fListOfSignals->Remove(clist); // remove and add first
486  fListOfSignals->AddFirst(clist);
487  return;
488  } else { // slot_name != 0 , update signal list
489  TQConnection *con = (TQConnection*) clist->FindObject(slot_name);
490  if (!con) return; // not found
491  clist->Remove(con); // remove and add as first
492  clist->AddFirst(con);
493  }
494 }
495 
496 ////////////////////////////////////////////////////////////////////////////////
497 /// 1. If slot_name = 0 => makes signal defined by the signal_name
498 /// to be the last in the fListOfSignals, this increase the time
499 /// for lookup.
500 /// 2. If slot_name != 0 => makes slot defined by the slot_name
501 /// to be executed last when signal_name is emitted.
502 /// Signal name is not compressed.
503 
504 void TQObject::LowPriority(const char *signal_name, const char *slot_name)
505 {
506  if (!fListOfSignals) return;
508  fListOfSignals->FindObject(signal_name);
509 
510  if (!clist) return;
511  if (!slot_name) {
512  fListOfSignals->Remove(clist); // remove and add first
513  fListOfSignals->AddLast(clist);
514  return;
515  } else { // slot_name != 0 , update signal list
516  TQConnection *con = (TQConnection*) clist->FindObject(slot_name);
517  if (!con) return;
518  clist->Remove(con); // remove and add as last
519  clist->AddLast(con);
520  }
521 }
522 
523 ////////////////////////////////////////////////////////////////////////////////
524 /// Return true if there is any object connected to this signal.
525 /// Only checks for object signals.
526 
527 Bool_t TQObject::HasConnection(const char *signal_name) const
528 {
529  if (!fListOfSignals)
530  return kFALSE;
531 
532  TString signal = CompressName(signal_name);
533 
534  return (fListOfSignals->FindObject(signal) != nullptr);
535 }
536 
537 ////////////////////////////////////////////////////////////////////////////////
538 /// Return number of signals for this object.
539 /// Only checks for object signals.
540 
542 {
543  if (fListOfSignals)
544  return fListOfSignals->GetSize();
545  return 0;
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////////
549 /// Return number of connections for this object.
550 
552 {
553  if (fListOfConnections)
554  return fListOfConnections->GetSize();
555  return 0;
556 }
557 
558 
559 ////////////////////////////////////////////////////////////////////////////////
560 /// Create connection between sender and receiver.
561 /// Receiver class needs to have a dictionary.
562 
564  const char *signal,
565  TClass *cl,
566  void *receiver,
567  const char *slot)
568 {
569  // sender should be TQObject
570  if (!sender->IsA()->InheritsFrom(TQObject::Class()))
571  return kFALSE;
572 
573  // remove "const" and strip blanks
574  TString signal_name = CompressName(signal);
575  TString slot_name = CompressName(slot);
576 
577  // check consistency of signal/slot methods/args
578  Int_t nsigargs;
579  if ((nsigargs = CheckConnectArgs(sender, sender->IsA(), signal_name, cl, slot_name)) == -1)
580  return kFALSE;
581 
582  if (!sender->fListOfSignals)
583  sender->fListOfSignals = new THashList();
584 
586  sender->fListOfSignals->FindObject(signal_name);
587 
588  if (!clist) {
589  clist = new TQConnectionList(signal_name, nsigargs);
590  sender->fListOfSignals->Add(clist);
591  }
592 
593  TIter next(clist);
594  TQConnection *connection = nullptr;
595 
596  while ((connection = (TQConnection*)next())) {
597  if (!strcmp(slot_name,connection->GetName()) &&
598  (receiver == connection->GetReceiver())) break;
599  }
600 
601  if (!connection)
602  connection = new TQConnection(cl, receiver, slot_name);
603 
604  // check to prevent multiple entries
605  if (!clist->FindObject(connection)) {
606  clist->Add(connection);
607  if (!connection->FindObject(clist)) connection->Add(clist);
608  sender->Connected(signal_name);
609  }
610 
611  return kTRUE;
612 }
613 
614 ////////////////////////////////////////////////////////////////////////////////
615 /// This method allows to make connection from any object
616 /// of the same class to the receiver object.
617 /// Receiver class needs to have a dictionary.
618 
619 Bool_t TQObject::ConnectToClass(const char *class_name,
620  const char *signal,
621  TClass *cl,
622  void *receiver,
623  const char *slot)
624 {
625  TClass *sender = TClass::GetClass(class_name);
626 
627  // sender class should be TQObject (i.e. TQClass)
628  if (!sender || !sender->IsA()->InheritsFrom(TQObject::Class()))
629  return kFALSE;
630 
631  TList *slist = ((TQClass*)sender)->fListOfSignals;
632  TString signal_name = CompressName(signal);
633  TString slot_name = CompressName(slot);
634 
635  // check consistency of signal/slot methods/args
636  Int_t nsigargs;
637  if ((nsigargs = CheckConnectArgs(nullptr, sender, signal_name, cl, slot_name)) == -1)
638  return kFALSE;
639 
640  if (!slist)
641  ((TQClass*)sender)->fListOfSignals = slist = new THashList();
642 
643  TQConnectionList *clist = (TQConnectionList*) slist->FindObject(signal_name);
644 
645  if (!clist) {
646  clist = new TQConnectionList(signal_name, nsigargs);
647  slist->Add(clist);
648  }
649 
650  TQConnection *connection = nullptr;
651  TIter next(clist);
652 
653  while ((connection = (TQConnection*)next())) {
654  if (!strcmp(slot_name,connection->GetName()) &&
655  (receiver == connection->GetReceiver())) break;
656  }
657 
658  if (!connection)
659  connection = new TQConnection(cl, receiver, slot_name);
660 
661  // check to prevent multiple entries
662  if (!clist->FindObject(connection)) {
663  clist->Add(connection);
664  if (!connection->FindObject(clist)) connection->Add(clist);
665  ((TQClass*)sender)->Connected(signal_name);
666  }
667 
668  return kTRUE;
669 }
670 
671 ////////////////////////////////////////////////////////////////////////////////
672 /// Create connection between sender and receiver.
673 /// Signal and slot string must have a form:
674 /// "Draw(char*, Option_t* ,Int_t)"
675 /// All blanks and "const" words will be removed,
676 ///
677 /// cl != 0 - class name, it can be class with or
678 /// without dictionary, e.g interpreted class.
679 /// Example:
680 /// ~~~ {.cpp}
681 /// TGButton *myButton;
682 /// TH2F *myHist;
683 ///
684 /// TQObject::Connect(myButton,"Clicked()",
685 /// "TH2F", myHist,"Draw(Option_t*)");
686 /// ~~~
687 /// cl == 0 - corresponds to function (interpereted or global)
688 /// the name of the function is defined by the slot string,
689 /// parameter receiver should be 0.
690 /// Example:
691 /// ~~~ {.cpp}
692 /// TGButton *myButton;
693 /// TH2F *myHist;
694 ///
695 /// TQObject::Connect(myButton,"Clicked()",
696 /// 0, 0,"hsimple()");
697 /// ~~~
698 /// Warning:
699 /// If receiver is class not derived from TQObject and going to be
700 /// deleted, disconnect all connections to this receiver.
701 /// In case of class derived from TQObject it is done automatically.
702 
704  const char *signal,
705  const char *cl,
706  void *receiver,
707  const char *slot)
708 {
709  if (cl) {
710  TClass *rcv_cl = TClass::GetClass(cl);
711  if (rcv_cl) return ConnectToClass(sender, signal, rcv_cl, receiver, slot);
712  }
713 
714  // the following is the case of receiver class without dictionary
715  // e.g. interpreted class or function.
716 
717  // sender should be TQObject
718  if (!sender->IsA()->InheritsFrom(TQObject::Class()))
719  return kFALSE;
720 
721  // remove "const" and strip blanks
722  TString signal_name = CompressName(signal);
723  TString slot_name = CompressName(slot);
724 
725  // check consistency of signal/slot methods/args
726  Int_t nsigargs;
727  if ((nsigargs = CheckConnectArgs(sender, sender->IsA(), signal_name, nullptr, slot_name)) == -1)
728  return kFALSE;
729 
730  if (!sender->fListOfSignals) sender->fListOfSignals = new THashList();
731 
733  sender->fListOfSignals->FindObject(signal_name);
734 
735  if (!clist) {
736  clist = new TQConnectionList(signal_name, nsigargs);
737  sender->fListOfSignals->Add(clist);
738  }
739 
740  TQConnection *connection = nullptr;
741  TIter next(clist);
742 
743  while ((connection = (TQConnection*)next())) {
744  if (!strcmp(slot_name,connection->GetName()) &&
745  (receiver == connection->GetReceiver())) break;
746  }
747 
748  if (!connection)
749  connection = new TQConnection(cl, receiver, slot_name);
750 
751  // check to prevent multiple entries
752  if (!clist->FindObject(connection)) {
753  clist->Add(connection);
754  if (!connection->FindObject(clist)) connection->Add(clist);
755  sender->Connected(signal_name);
756  }
757 
758  return kTRUE;
759 }
760 
761 ////////////////////////////////////////////////////////////////////////////////
762 /// This method allows to make a connection from any object
763 /// of the same class to a single slot.
764 /// Signal and slot string must have a form:
765 /// "Draw(char*, Option_t* ,Int_t)"
766 /// All blanks and "const" words will be removed,
767 ///
768 /// cl != 0 - class name, it can be class with or
769 /// without dictionary, e.g interpreted class.
770 /// Example:
771 /// ~~~ {.cpp}
772 /// TGButton *myButton;
773 /// TH2F *myHist;
774 ///
775 /// TQObject::Connect("TGButton", "Clicked()",
776 /// "TH2F", myHist, "Draw(Option_t*)");
777 /// ~~~
778 /// cl == 0 - corresponds to function (interpereted or global)
779 /// the name of the function is defined by the slot string,
780 /// parameter receiver should be 0.
781 /// Example:
782 /// ~~~ {.cpp}
783 /// TGButton *myButton;
784 /// TH2F *myHist;
785 ///
786 /// TQObject::Connect("TGButton", "Clicked()",
787 /// 0, 0, "hsimple()");
788 /// ~~~
789 /// Warning:
790 ///
791 /// If receiver class not derived from TQObject and going to be
792 /// deleted, disconnect all connections to this receiver.
793 /// In case of class derived from TQObject it is done automatically.
794 
795 Bool_t TQObject::Connect(const char *class_name,
796  const char *signal,
797  const char *cl,
798  void *receiver,
799  const char *slot)
800 {
801  if (cl) {
802  TClass *rcv_cl = TClass::GetClass(cl);
803  if (rcv_cl) return ConnectToClass(class_name, signal, rcv_cl, receiver,
804  slot);
805  }
806 
807  // the following is case of receiver class without dictionary
808  // e.g. interpreted class or function.
809 
810  TClass *sender = TClass::GetClass(class_name);
811 
812  // sender class should be TQObject (i.e. TQClass)
813  if (!sender || !sender->IsA()->InheritsFrom(TQObject::Class()))
814  return kFALSE;
815 
816  TList *slist = ((TQClass*)sender)->fListOfSignals;
817 
818  TString signal_name = CompressName(signal);
819  TString slot_name = CompressName(slot);
820 
821  // check consistency of signal/slot methods/args
822  Int_t nsigargs;
823  if ((nsigargs = CheckConnectArgs(nullptr, sender, signal_name, nullptr, slot_name)) == -1)
824  return kFALSE;
825 
826  if (!slist) {
827  slist = ((TQClass*)sender)->fListOfSignals = new THashList();
828  }
829 
831  slist->FindObject(signal_name);
832 
833  if (!clist) {
834  clist = new TQConnectionList(signal_name, nsigargs);
835  slist->Add(clist);
836  }
837 
838  TQConnection *connection = nullptr;
839  TIter next(clist);
840 
841  while ((connection = (TQConnection*)next())) {
842  if (!strcmp(slot_name,connection->GetName()) &&
843  (receiver == connection->GetReceiver())) break;
844  }
845 
846  if (!connection)
847  connection = new TQConnection(cl, receiver, slot_name);
848 
849  // check to prevent multiple entries
850  if (!clist->FindObject(connection)) {
851  clist->Add(connection);
852  if (!connection->FindObject(clist)) connection->Add(clist);
853  ((TQClass*)sender)->Connected(signal_name);
854  }
855 
856  return kTRUE;
857 }
858 
859 ////////////////////////////////////////////////////////////////////////////////
860 /// Non-static method is used to connect from the signal
861 /// of this object to the receiver slot.
862 ///
863 /// Warning! No check on consistency of sender/receiver
864 /// classes/methods.
865 ///
866 /// This method makes possible to have connection/signals from
867 /// interpreted class. See also RQ_OBJECT.h.
868 
869 Bool_t TQObject::Connect(const char *signal,
870  const char *receiver_class,
871  void *receiver,
872  const char *slot)
873 {
874  // remove "const" and strip blanks
875  TString signal_name = CompressName(signal);
876  TString slot_name = CompressName(slot);
877 
878  // check consistency of signal/slot methods/args
879  TClass *cl = nullptr;
880  if (receiver_class)
881  cl = TClass::GetClass(receiver_class);
882  Int_t nsigargs;
883  if ((nsigargs = CheckConnectArgs(this, IsA(), signal_name, cl, slot_name)) == -1)
884  return kFALSE;
885 
887 
889  fListOfSignals->FindObject(signal_name);
890 
891  if (!clist) {
892  clist = new TQConnectionList(signal_name, nsigargs);
893  fListOfSignals->Add(clist);
894  }
895 
896  TIter next(clist);
897  TQConnection *connection = nullptr;
898 
899  while ((connection = (TQConnection*)next())) {
900  if (!strcmp(slot_name,connection->GetName()) &&
901  (receiver == connection->GetReceiver())) break;
902  }
903 
904  if (!connection)
905  connection = new TQConnection(receiver_class, receiver, slot_name);
906 
907  // check to prevent multiple entries
908  if (!clist->FindObject(connection)) {
909  clist->Add(connection);
910  if (!connection->FindObject(clist)) connection->Add(clist);
911  Connected(signal_name);
912  }
913 
914  return kTRUE;
915 }
916 
917 ////////////////////////////////////////////////////////////////////////////////
918 /// Disconnects signal in object sender from slot_method in
919 /// object receiver. For objects derived from TQObject signal-slot
920 /// connection is removed when either of the objects involved
921 /// are destroyed.
922 ///
923 /// Disconnect() is typically used in three ways, as the following
924 /// examples shows:
925 ///
926 /// - Disconnect everything connected to an object's signals:
927 /// ~~~ {.cpp}
928 /// Disconnect(myObject);
929 /// ~~~
930 /// - Disconnect everything connected to a signal:
931 /// ~~~ {.cpp}
932 /// Disconnect(myObject, "mySignal()");
933 /// ~~~
934 /// - Disconnect a specific receiver:
935 /// ~~~ {.cpp}
936 /// Disconnect(myObject, 0, myReceiver, 0);
937 /// ~~~
938 ///
939 /// 0 may be used as a wildcard in three of the four arguments,
940 /// meaning "any signal", "any receiving object" or
941 /// "any slot in the receiving object", respectively.
942 ///
943 /// The sender has no default and may never be 0
944 /// (you cannot disconnect signals from more than one object).
945 ///
946 /// If signal is 0, it disconnects receiver and slot_method
947 /// from any signal. If not, only the specified signal is
948 /// disconnected.
949 ///
950 /// If receiver is 0, it disconnects anything connected to signal.
951 /// If not, slots in objects other than receiver are not
952 /// disconnected
953 ///
954 /// If slot_method is 0, it disconnects anything that is connected
955 /// to receiver. If not, only slots named slot_method will be
956 /// disconnected, and all other slots are left alone.
957 /// The slot_method must be 0 if receiver is left out, so you
958 /// cannot disconnect a specifically-named slot on all objects.
959 
961  const char *signal,
962  void *receiver,
963  const char *slot)
964 {
965  Bool_t return_value = kFALSE;
966  Bool_t next_return = kFALSE;
967 
968  if (!sender->GetListOfSignals()) return kFALSE;
969 
970  TString signal_name = CompressName(signal);
971  TString slot_name = CompressName(slot);
972 
973  TQConnectionList *slist = nullptr;
974  TIter next_signal(sender->GetListOfSignals());
975 
976  while ((slist = (TQConnectionList*)next_signal())) {
977  if (!signal || signal_name.IsNull()) { // disconnect all signals
978  next_return = slist->Disconnect(receiver,slot_name);
979  return_value = return_value || next_return;
980 
981  if (slist->IsEmpty()) {
982  sender->GetListOfSignals()->Remove(slist);
983  SafeDelete(slist); // delete empty list
984  }
985  } else if (signal && !strcmp(signal_name,slist->GetName())) {
986  next_return = slist->Disconnect(receiver,slot_name);
987  return_value = return_value || next_return;
988 
989  if (slist->IsEmpty()) {
990  sender->GetListOfSignals()->Remove(slist);
991  SafeDelete(slist); // delete empty list
992  break;
993  }
994  }
995  }
996 
997  if (sender->GetListOfSignals() && sender->GetListOfSignals()->IsEmpty()) {
998  SafeDelete(sender->fListOfSignals);
999  }
1000 
1001  return return_value;
1002 }
1003 
1004 ////////////////////////////////////////////////////////////////////////////////
1005 /// Disconnects "class signal". The class is defined by class_name.
1006 /// See also Connect(class_name,signal,receiver,slot).
1007 
1008 Bool_t TQObject::Disconnect(const char *class_name,
1009  const char *signal,
1010  void *receiver,
1011  const char *slot)
1012 {
1013  TClass *sender = TClass::GetClass(class_name);
1014 
1015  // sender should be TQClass (which derives from TQObject)
1016  if (!sender || !sender->IsA()->InheritsFrom(TQObject::Class()))
1017  return kFALSE;
1018 
1019  TQClass *qcl = (TQClass*)sender; // cast TClass to TQClass
1020  return Disconnect(qcl, signal, receiver, slot);
1021 }
1022 
1023 ////////////////////////////////////////////////////////////////////////////////
1024 /// Disconnects signal of this object from slot of receiver.
1025 /// Equivalent to Disconnect(this, signal, receiver, slot)
1026 
1027 Bool_t TQObject::Disconnect(const char *signal,
1028  void *receiver,
1029  const char *slot)
1030 {
1031  return Disconnect(this, signal, receiver, slot);
1032 }
1033 
1034 ////////////////////////////////////////////////////////////////////////////////
1035 /// Stream an object of class TQObject.
1036 
1037 void TQObject::Streamer(TBuffer &R__b)
1038 {
1039  if (R__b.IsReading()) {
1040  // nothing to read
1041  } else {
1042  // nothing to write
1043  }
1044 }
1045 
1046 ////////////////////////////////////////////////////////////////////////////////
1047 /// Returns true if all signals are blocked.
1048 
1050 {
1051  return fgAllSignalsBlocked;
1052 }
1053 
1054 ////////////////////////////////////////////////////////////////////////////////
1055 /// Block or unblock all signals. Returns the previous block status.
1056 
1058 {
1061  return ret;
1062 }
1063 
1064 ////////////////////////////////////////////////////////////////////////////////
1065 /// Global function which simplifies making connection in interpreted ROOT session
1066 ///
1067 /// ConnectCINT - connects to interpreter(CINT) command
1068 
1069 Bool_t ConnectCINT(TQObject *sender, const char *signal, const char *slot)
1070 {
1071  TString str = "ProcessLine(=";
1072  str += '"';
1073  str += slot;
1074  str += '"';
1075  str += ")";
1076  return TQObject::Connect(sender, signal, "TInterpreter",
1077  gInterpreter, str.Data());
1078 }
m
auto * m
Definition: textangle.C:8
TPMERegexp
Wrapper for PCRE library (Perl Compatible Regular Expressions).
Definition: TPRegexp.h:97
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:1027
kTRUE
const Bool_t kTRUE
Definition: RtypesCore.h:100
TCollection::Print
virtual void Print(Option_t *option="") const
Default print for collections, calls Print(option, 1).
Definition: TCollection.cxx:476
TQObject::CollectClassSignalLists
void CollectClassSignalLists(TList &list, TClass *cls)
Collect class signal lists from class cls and all its base-classes.
Definition: TQObject.cxx:451
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:393
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:563
TMethod.h
TStringToken
Provides iteration through tokens of a given string.
Definition: TPRegexp.h:143
gInterpreter
#define gInterpreter
Definition: TInterpreter.h:560
TQConnectionList
TQConnectionList is the named list of connections, see also TQConnection class.
Definition: TQObject.cxx:309
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:536
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
TCollection::fName
TString fName
Definition: TCollection.h:147
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:1057
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:872
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:541
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:4449
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:527
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:4867
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
TList::FirstLink
virtual TObjLink * FirstLink() const
Definition: TList.h:108
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:3629
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:4404
kFALSE
const Bool_t kFALSE
Definition: RtypesCore.h:101
TMethod
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
TQConnectionList::fSignalArgs
Int_t fSignalArgs
Definition: TQObject.cxx:312
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 consistency of sender/receiver methods/arguments.
Definition: TQObject.cxx:179
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:1069
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:2955
TQObject::NumberOfConnections
virtual Int_t NumberOfConnections() const
Return number of connections for this object.
Definition: TQObject.cxx:551
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:435
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:504
THashList.h
TQConnectionList::GetNargs
Int_t GetNargs() const
Definition: TQObject.cxx:320
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:74
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:975
TQConnectionList::~TQConnectionList
virtual ~TQConnectionList()
Destructor.
Definition: TQObject.cxx:327
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:869
Cppyy::GetMethod
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
Definition: clingwrapper.cxx:1387
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
TQConnectionList::Disconnect
Bool_t Disconnect(void *receiver=nullptr, const char *slot_name=nullptr)
Remove connection from the list.
Definition: TQObject.cxx:344
TList::Add
virtual void Add(TObject *obj)
Definition: TList.h:87
TList::Clear
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:402
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:477
TIter
Definition: TCollection.h:233
TQObject::AreAllSignalsBlocked
static Bool_t AreAllSignalsBlocked()
Returns true if all signals are blocked.
Definition: TQObject.cxx:1049
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:98
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:527
Class
void Class()
Definition: Class.C:29
TCollection::GetName
virtual const char * GetName() const
Return name of this collection.
Definition: TCollection.cxx:351
Char_t
char Char_t
Definition: RtypesCore.h:33
TQObject::~TQObject
virtual ~TQObject()
TQObject Destructor.
Definition: TQObject.cxx:404
TQConnectionList::TQConnectionList
TQConnectionList(const char *name, Int_t nsigargs)
Definition: TQObject.cxx:315
TFunction
Global functions class (global functions are obtained from CINT).
Definition: TFunction.h:30
TList
A doubly linked list.
Definition: TList.h:44
TQConnectionList::ls
void ls(Option_t *option="") const
List signal name and list all connections in this signal list.
Definition: TQObject.cxx:378
gROOT
#define gROOT
Definition: TROOT.h:404
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