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