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 "TBuffer.h"
62#include "TClass.h"
63#include "TSystem.h"
64#include "TMethod.h"
65#include "TBaseClass.h"
66#include "TDataType.h"
67#include "TInterpreter.h"
68#include "TQClass.h"
69#include "TError.h"
70#include "Riostream.h"
71#include "RQ_OBJECT.h"
72#include "TVirtualMutex.h"
73#include "RConfigure.h"
74
75void *gTQSender; // A pointer to the object that sent the last signal.
76 // Getting access to the sender might be practical
77 // when many signals are connected to a single slot.
78
80
81
85
86////////////////////////////////////////////////////////////////////////////////
87/// Removes "const" words and blanks from full (with prototype)
88/// method name and resolve any typedefs in the method signature.
89/// If a null or empty string is passed in, an empty string
90/// is returned.
91///
92/// Example:
93/// ~~~ {.cpp}
94/// CompressName(" Draw(const char *, const char *,
95/// Option_t * , Int_t , Int_t)");
96/// ~~~
97/// returns the string "Draw(char*,char*,char*,int,int)".
98
99TString TQObject::CompressName(const char *method_name)
100{
101 TString res(method_name);
102 if (res.IsNull())
103 return res;
104
105 {
106 static TVirtualMutex * lock = 0;
107 R__LOCKGUARD2(lock);
108
109 static TPMERegexp *constRe = 0, *wspaceRe = 0;
110 if (constRe == 0) {
111 constRe = new TPMERegexp("(?<=\\(|\\s|,|&|\\*)const(?=\\s|,|\\)|&|\\*)", "go");
112 wspaceRe = new TPMERegexp("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", "go");
113 }
114 constRe ->Substitute(res, "");
115 wspaceRe->Substitute(res, "");
116 }
117
118 TStringToken methargs(res, "\\(|\\)", kTRUE);
119
120 methargs.NextToken();
121 res = methargs;
122 res += "(";
123
124 methargs.NextToken();
125 TStringToken arg(methargs, ",");
126 while (arg.NextToken())
127 {
128 Int_t pri = arg.Length() - 1;
129 Char_t prc = 0;
130 if (arg[pri] == '*' || arg[pri] == '&') {
131 prc = arg[pri];
132 arg.Remove(pri);
133 }
134 TDataType *dt = gROOT->GetType(arg.Data());
135 if (dt) {
136 res += dt->GetFullTypeName();
137 } else {
138 res += arg;
139 }
140 if (prc) res += prc;
141 if (!arg.AtEnd()) res += ",";
142 }
143 res += ")";
144 return res;
145}
146
147namespace {
148
149////////////////////////////////////////////////////////////////////////////////
150/// Almost the same as TClass::GetMethodWithPrototype().
151
152TMethod *GetMethodWithPrototype(TClass *cl, const char *method,
153 const char *proto, Int_t &nargs)
154{
155 nargs = 0;
156
157 if (!gInterpreter || cl == 0) return 0;
158
159 TMethod *m = cl->GetMethodWithPrototype(method,proto);
160 if (m) nargs = m->GetNargs();
161 return m;
162}
163
164////////////////////////////////////////////////////////////////////////////////
165/// Almost the same as TClass::GetMethod().
166
167static TMethod *GetMethod(TClass *cl, const char *method, const char *params)
168{
169 if (!gInterpreter || cl == 0) return 0;
170 return cl->GetMethod(method,params);
171}
172
173}
174
175////////////////////////////////////////////////////////////////////////////////
176/// Checking of consitency of sender/receiver methods/arguments.
177/// Returns -1 on error, otherwise number or arguments of signal function.
178/// Static method.
179
181 TClass *sender_class, const char *signal,
182 TClass *receiver_class, const char *slot)
183{
184 char *signal_method = new char[strlen(signal)+1];
185 if (signal_method) strcpy(signal_method, signal);
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 char *slot_method = new char[strlen(slot)+1];
242 if (slot_method) strcpy(slot_method, slot);
243
244 char *slot_proto;
245 char *slot_params = 0;
246
247 if ((slot_proto = strchr(slot_method,'('))) {
248
249 // substitute first '(' symbol with '\0'
250 *slot_proto++ = '\0';
251
252 // substitute last ')' symbol with '\0'
253 if ((tmp = strrchr(slot_proto,')'))) *tmp = '\0';
254 }
255
256 if (!slot_proto) slot_proto = (char*)""; // avoid zero strings
257 if ((slot_params = strchr(slot_proto,'='))) *slot_params = ' ';
258
259 TFunction *slotMethod = 0;
260 if (!receiver_class) {
261 // case of slot_method is compiled/intrepreted function
262 slotMethod = gROOT->GetGlobalFunction(slot_method,0,kFALSE);
263 } else {
264 slotMethod = !slot_params ?
265 GetMethodWithPrototype(receiver_class,
266 slot_method,
267 slot_proto,
268 nargs) :
269 GetMethod(receiver_class,
270 slot_method, slot_params);
271 }
272
273 if (!slotMethod) {
274 if (!slot_params) {
275 ::Error("TQObject::CheckConnectArgs", "slot %s(%s) does not exist",
276 receiver_class ? Form("%s::%s", receiver_class->GetName(),
277 slot_method) : slot_method, slot_proto);
278 } else {
279 ::Error("TQObject::CheckConnectArgs", "slot %s(%s) does not exist",
280 receiver_class ? Form("%s::%s", receiver_class->GetName(),
281 slot_method) : slot_method, slot_params);
282 }
283 delete [] slot_method;
284 return -1;
285 }
286
287#if defined(CHECK_ARGS_NUMBER)
288 if (slotMethod != (TMethod *) -1 && slotMethod->GetNargsOpt() >= 0 &&
289 nsigargs < (slotMethod->GetNargs() - slotMethod->GetNargsOpt())) {
290 ::Error("TQObject::CheckConnectArgs",
291 "inconsistency in numbers of arguments");
292 delete [] slot_method;
293 return -1;
294 }
295#endif
296
297 // cleaning
298 delete [] slot_method;
299
300 return nsigargs;
301}
302
303/** \class TQConnectionList
304 TQConnectionList is the named list of connections,
305 see also TQConnection class.
306*/
307
308class TQConnectionList : public TList {
309
310private:
311 Int_t fSignalArgs; // number of arguments in signal function
312
313public:
314 TQConnectionList(const char *name, Int_t nsigargs) : TList()
315 { fName = name; fSignalArgs = nsigargs; }
316 virtual ~TQConnectionList();
317
318 Bool_t Disconnect(void *receiver=0, const char *slot_name=0);
319 Int_t GetNargs() const { return fSignalArgs; }
320 void ls(Option_t *option = "") const;
321};
322
323////////////////////////////////////////////////////////////////////////////////
324/// Destructor.
325
326TQConnectionList::~TQConnectionList()
327{
328 TIter next(this);
329 TQConnection *connection;
330
331 while ((connection = (TQConnection*)next())) {
332 // remove this from feed back reference list
333 connection->Remove(this);
334 if (connection->IsEmpty()) delete connection;
335 }
336 Clear("nodelete");
337}
338
339////////////////////////////////////////////////////////////////////////////////
340/// Remove connection from the list. For more info see
341/// TQObject::Disconnect()
342
343Bool_t TQConnectionList::Disconnect(void *receiver, const char *slot_name)
344{
345 TQConnection *connection = 0;
346 Bool_t return_value = kFALSE;
347
348 TObjLink *lnk = FirstLink();
349 TObjLink *savlnk; // savlnk is used when link is deleted
350
351 while (lnk) {
352 connection = (TQConnection*)lnk->GetObject();
353 const char *name = connection->GetName();
354 void *obj = connection->GetReceiver();
355
356 if (!slot_name || !slot_name[0]
357 || !strcmp(name,slot_name)) {
358
359 if (!receiver || (receiver == obj)) {
360 return_value = kTRUE;
361 savlnk = lnk->Next(); // keep next link ..
362 Remove(lnk);
363 lnk = savlnk; // current link == saved ...
364 connection->Remove(this); // remove back reference
365 if (connection->IsEmpty()) SafeDelete(connection);
366 continue; // .. continue from saved link
367 }
368 }
369 lnk = lnk->Next();
370 }
371 return return_value;
372}
373
374////////////////////////////////////////////////////////////////////////////////
375/// List signal name and list all connections in this signal list.
376
377void TQConnectionList::ls(Option_t *option) const
378{
379 std::cout << "TQConnectionList:" << "\t" << GetName() << std::endl;
380 ((TQConnectionList*)this)->R__FOR_EACH(TQConnection,Print)(option);
381}
382
383
384////////////////////////////////////////////////////////////////////////////////
385/// TQObject Constructor.
386/// Comment:
387/// - In order to minimize memory allocation fListOfSignals and
388/// fListOfConnections are allocated only if it is neccesary
389/// - When fListOfSignals/fListOfConnections are empty they will
390/// be deleted
391
393{
394 fListOfSignals = 0;
397}
398
399////////////////////////////////////////////////////////////////////////////////
400/// TQObject Destructor.
401/// - delete all connections and signal list
402
404{
405 if (!gROOT) return;
406
407 Destroyed(); // emit "Destroyed()" signal
408
409 if (fListOfSignals) {
411 SafeDelete(fListOfSignals); // delete list of signals
412 }
413
414 // loop over all connections and remove references to this object
415 if (fListOfConnections) {
416 TIter next_connection(fListOfConnections);
417 TQConnection *connection;
418
419 while ((connection = (TQConnection*)next_connection())) {
420 TIter next_list(connection);
421 TQConnectionList *list;
422 while ((list = (TQConnectionList*)next_list())) {
423 list->Remove(connection);
424 if (list->IsEmpty()) SafeDelete(list);
425 }
426 }
428 }
429}
430
431////////////////////////////////////////////////////////////////////////////////
432/// Returns pointer to list of signals of this class.
433
435{
436 TQClass *qcl = 0;
437
438 qcl = dynamic_cast<TQClass*>(IsA());
439
440 return qcl ? qcl->fListOfSignals : 0; //!!
441}
442
443////////////////////////////////////////////////////////////////////////////////
444/// Collect class signal lists from class cls and all its
445/// base-classes.
446///
447/// The recursive traversal is not performed for classes not
448/// deriving from TQClass.
449
451{
452 TQClass *qcl = dynamic_cast<TQClass*>(cls);
453 if (qcl)
454 {
455 if (qcl->fListOfSignals)
456 list.Add(qcl->fListOfSignals);
457
458 // Descend into base-classes.
459 TIter next_base_class(cls->GetListOfBases());
460 TBaseClass *base;
461 while ((base = (TBaseClass*) next_base_class()))
462 {
464 }
465 }
466}
467
468////////////////////////////////////////////////////////////////////////////////
469/// 1. If slot_name = 0 => makes signal defined by the signal_name
470/// to be the first in the fListOfSignals, this decreases
471/// the time for lookup.
472/// 2. If slot_name != 0 => makes slot defined by the slot_name
473/// to be executed first when signal_name is emitted.
474/// Signal name is not compressed.
475
476void TQObject::HighPriority(const char *signal_name, const char *slot_name)
477{
478 TQConnectionList *clist = (TQConnectionList*)
479 fListOfSignals->FindObject(signal_name);
480
481 if (!clist) return; // not found
482 if (!slot_name) { // update list of signal lists
483 fListOfSignals->Remove(clist); // remove and add first
484 fListOfSignals->AddFirst(clist);
485 return;
486 } else { // slot_name != 0 , update signal list
487 TQConnection *con = (TQConnection*) clist->FindObject(slot_name);
488 if (!con) return; // not found
489 clist->Remove(con); // remove and add as first
490 clist->AddFirst(con);
491 }
492}
493
494////////////////////////////////////////////////////////////////////////////////
495/// 1. If slot_name = 0 => makes signal defined by the signal_name
496/// to be the last in the fListOfSignals, this increase the time
497/// for lookup.
498/// 2. If slot_name != 0 => makes slot defined by the slot_name
499/// to be executed last when signal_name is emitted.
500/// Signal name is not compressed.
501
502void TQObject::LowPriority(const char *signal_name, const char *slot_name)
503{
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
524Bool_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{
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
616Bool_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
792Bool_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
866Bool_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
1005Bool_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
1024Bool_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
1034void 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
1066Bool_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}
void Class()
Definition: Class.C:29
#define SafeDelete(p)
Definition: RConfig.hxx:543
#define b(i)
Definition: RSha256.hxx:100
int Int_t
Definition: RtypesCore.h:43
char Char_t
Definition: RtypesCore.h:31
const Bool_t kFALSE
Definition: RtypesCore.h:90
bool Bool_t
Definition: RtypesCore.h:61
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
void Error(const char *location, const char *msgfmt,...)
char name[80]
Definition: TGX11.cxx:109
#define gInterpreter
Definition: TInterpreter.h:556
void * gTQSender
Definition: TQObject.cxx:75
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
#define ClassImpQ(name)
Definition: TQObject.h:282
#define gROOT
Definition: TROOT.h:406
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:80
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:4381
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:4426
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3611
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4844
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:2937
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:821
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition: TList.cxx:99
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:577
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:469
virtual void AddLast(TObject *obj)
Add object at the end of the list.
Definition: TList.cxx:151
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:180
virtual Int_t NumberOfConnections() const
Return number of connections for this object.
Definition: TQObject.cxx:548
TQObject()
TQObject Constructor.
Definition: TQObject.cxx:392
void CollectClassSignalLists(TList &list, TClass *cls)
Collect class signal lists from class cls and all its base-classes.
Definition: TQObject.cxx:450
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:1054
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:99
TList * GetListOfClassSignals() const
Returns pointer to list of signals of this class.
Definition: TQObject.cxx:434
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:538
virtual void Destroyed()
Definition: TQObject.h:196
virtual ~TQObject()
TQObject Destructor.
Definition: TQObject.cxx:403
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:866
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
virtual Bool_t HasConnection(const char *signal_name) const
Return true if there is any object connected to this signal.
Definition: TQObject.cxx:524
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
static Bool_t AreAllSignalsBlocked()
Returns true if all signals are blocked.
Definition: TQObject.cxx:1046
virtual void LowPriority(const char *signal_name, const char *slot_name=0)
Definition: TQObject.cxx:502
virtual void Connected(const char *)
Definition: TQObject.h:193
virtual void HighPriority(const char *signal_name, const char *slot_name=0)
Definition: TQObject.cxx:476
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
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
void Print(std::ostream &os, const OptionType &opt)
static const std::string comment("comment")
auto * m
Definition: textangle.C:8