Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 "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
73void *gTQSender; // A pointer to the object that sent the last signal.
74 // Getting access to the sender might be practical
75 // when many signals are connected to a single slot.
76
78
79
83
84////////////////////////////////////////////////////////////////////////////////
85/// Removes "const" words and blanks from full (with prototype)
86/// method name and resolve any typedefs in the method signature.
87/// If a null or empty string is passed in, an empty string
88/// is returned.
89///
90/// Example:
91/// ~~~ {.cpp}
92/// CompressName(" Draw(const char *, const char *,
93/// Option_t * , Int_t , Int_t)");
94/// ~~~
95/// returns the string "Draw(char*,char*,char*,int,int)".
96
97TString TQObject::CompressName(const char *method_name)
98{
99 TString res(method_name);
100 if (res.IsNull())
101 return res;
102
103 {
104 static TVirtualMutex * lock = 0;
105 R__LOCKGUARD2(lock);
106
107 static TPMERegexp *constRe = 0, *wspaceRe = 0;
108 if (constRe == 0) {
109 constRe = new TPMERegexp("(?<=\\(|\\s|,|&|\\*)const(?=\\s|,|\\)|&|\\*)", "go");
110 wspaceRe = new TPMERegexp("\\s+(?=([^\"]*\"[^\"]*\")*[^\"]*$)", "go");
111 }
112 constRe ->Substitute(res, "");
113 wspaceRe->Substitute(res, "");
114 }
115
116 TStringToken methargs(res, "\\(|\\)", kTRUE);
117
118 methargs.NextToken();
119 res = methargs;
120 res += "(";
121
122 methargs.NextToken();
123 TStringToken arg(methargs, ",");
124 while (arg.NextToken())
125 {
126 Int_t pri = arg.Length() - 1;
127 Char_t prc = 0;
128 if (arg[pri] == '*' || arg[pri] == '&') {
129 prc = arg[pri];
130 arg.Remove(pri);
131 }
132 TDataType *dt = gROOT->GetType(arg.Data());
133 if (dt) {
134 res += dt->GetFullTypeName();
135 } else {
136 res += arg;
137 }
138 if (prc) res += prc;
139 if (!arg.AtEnd()) res += ",";
140 }
141 res += ")";
142 return res;
143}
144
145namespace {
146
147////////////////////////////////////////////////////////////////////////////////
148/// Almost the same as TClass::GetMethodWithPrototype().
149
150TMethod *GetMethodWithPrototype(TClass *cl, const char *method,
151 const char *proto, Int_t &nargs)
152{
153 nargs = 0;
154
155 if (!gInterpreter || cl == 0) return 0;
156
157 TMethod *m = cl->GetMethodWithPrototype(method,proto);
158 if (m) nargs = m->GetNargs();
159 return m;
160}
161
162////////////////////////////////////////////////////////////////////////////////
163/// Almost the same as TClass::GetMethod().
164
165static TMethod *GetMethod(TClass *cl, const char *method, const char *params)
166{
167 if (!gInterpreter || cl == 0) return 0;
168 return cl->GetMethod(method,params);
169}
170
171}
172
173////////////////////////////////////////////////////////////////////////////////
174/// Checking of consistency of sender/receiver methods/arguments.
175/// Returns -1 on error, otherwise number or arguments of signal function.
176/// Static method.
177
179 TClass *sender_class, const char *signal,
180 TClass *receiver_class, const char *slot)
181{
182 char *signal_method = new char[strlen(signal)+1];
183 if (signal_method) strcpy(signal_method, signal);
184
185 char *signal_proto;
186 char *tmp;
187
188 if ((signal_proto = strchr(signal_method,'('))) {
189 // substitute first '(' symbol with '\0'
190 *signal_proto++ = '\0';
191 // substitute last ')' symbol with '\0'
192 if ((tmp = strrchr(signal_proto,')'))) *tmp = '\0';
193 }
194
195 if (!signal_proto) signal_proto = (char*)""; // avoid zero strings
196
197 // if delegation object TQObjSender is used get the real sender class
198 if (sender && sender_class == TQObjSender::Class()) {
199 sender_class = TClass::GetClass(sender->GetSenderClassName());
200 if (!sender_class) {
201 ::Error("TQObject::CheckConnectArgs", "for signal/slot consistency\n"
202 "checking need to specify class name as argument to "
203 "RQ_OBJECT macro");
204 delete [] signal_method;
205 return -1;
206 }
207 }
208
209 Int_t nargs;
210 TMethod *signalMethod = GetMethodWithPrototype(sender_class,
211 signal_method,
212 signal_proto,
213 nargs);
214 if (!signalMethod) {
215 ::Error("TQObject::CheckConnectArgs", "signal %s::%s(%s) does not exist",
216 sender_class->GetName(), signal_method, signal_proto);
217 delete [] signal_method;
218 return -1;
219 }
220 Int_t nsigargs = nargs;
221
222#if defined(CHECK_COMMENT_STRING)
223 const char *comment = 0;
224 if (signalMethod != (TMethod *) -1) // -1 in case of interpreted class
225 comment = signalMethod->GetCommentString();
226
227 if (!comment || !comment[0] || strstr(comment,"*SIGNAL")){
228 ::Error("TQObject::CheckConnectArgs",
229 "signal %s::%s(%s), to declare signal use comment //*SIGNAL*",
230 sender_class->GetName(), signal_method, signal_proto);
231 delete [] signal_method;
232 return -1;
233 }
234#endif
235
236 // cleaning
237 delete [] signal_method;
238
239 char *slot_method = new char[strlen(slot)+1];
240 if (slot_method) strcpy(slot_method, slot);
241
242 char *slot_proto;
243 char *slot_params = 0;
244
245 if ((slot_proto = strchr(slot_method,'('))) {
246
247 // substitute first '(' symbol with '\0'
248 *slot_proto++ = '\0';
249
250 // substitute last ')' symbol with '\0'
251 if ((tmp = strrchr(slot_proto,')'))) *tmp = '\0';
252 }
253
254 if (!slot_proto) slot_proto = (char*)""; // avoid zero strings
255 if ((slot_params = strchr(slot_proto,'='))) *slot_params = ' ';
256
257 TFunction *slotMethod = 0;
258 if (!receiver_class) {
259 // case of slot_method is compiled/intrepreted function
260 slotMethod = gROOT->GetGlobalFunction(slot_method,0,kFALSE);
261 } else {
262 slotMethod = !slot_params ?
263 GetMethodWithPrototype(receiver_class,
264 slot_method,
265 slot_proto,
266 nargs) :
267 GetMethod(receiver_class,
268 slot_method, slot_params);
269 }
270
271 if (!slotMethod) {
272 if (!slot_params) {
273 ::Error("TQObject::CheckConnectArgs", "slot %s(%s) does not exist",
274 receiver_class ? Form("%s::%s", receiver_class->GetName(),
275 slot_method) : slot_method, slot_proto);
276 } else {
277 ::Error("TQObject::CheckConnectArgs", "slot %s(%s) does not exist",
278 receiver_class ? Form("%s::%s", receiver_class->GetName(),
279 slot_method) : slot_method, slot_params);
280 }
281 delete [] slot_method;
282 return -1;
283 }
284
285#if defined(CHECK_ARGS_NUMBER)
286 if (slotMethod != (TMethod *) -1 && slotMethod->GetNargsOpt() >= 0 &&
287 nsigargs < (slotMethod->GetNargs() - slotMethod->GetNargsOpt())) {
288 ::Error("TQObject::CheckConnectArgs",
289 "inconsistency in numbers of arguments");
290 delete [] slot_method;
291 return -1;
292 }
293#endif
294
295 // cleaning
296 delete [] slot_method;
297
298 return nsigargs;
299}
300
301/** \class TQConnectionList
302 TQConnectionList is the named list of connections,
303 see also TQConnection class.
304*/
305
306class TQConnectionList : public TList {
307
308private:
309 Int_t fSignalArgs; // number of arguments in signal function
310
311public:
312 TQConnectionList(const char *name, Int_t nsigargs) : TList()
313 { fName = name; fSignalArgs = nsigargs; }
314 virtual ~TQConnectionList();
315
316 Bool_t Disconnect(void *receiver=0, const char *slot_name=0);
317 Int_t GetNargs() const { return fSignalArgs; }
318 void ls(Option_t *option = "") const;
319};
320
321////////////////////////////////////////////////////////////////////////////////
322/// Destructor.
323
324TQConnectionList::~TQConnectionList()
325{
326 TIter next(this);
327 TQConnection *connection;
328
329 while ((connection = (TQConnection*)next())) {
330 // remove this from feed back reference list
331 connection->Remove(this);
332 if (connection->IsEmpty()) delete connection;
333 }
334 Clear("nodelete");
335}
336
337////////////////////////////////////////////////////////////////////////////////
338/// Remove connection from the list. For more info see
339/// TQObject::Disconnect()
340
341Bool_t TQConnectionList::Disconnect(void *receiver, const char *slot_name)
342{
343 TQConnection *connection = 0;
344 Bool_t return_value = kFALSE;
345
346 TObjLink *lnk = FirstLink();
347 TObjLink *savlnk; // savlnk is used when link is deleted
348
349 while (lnk) {
350 connection = (TQConnection*)lnk->GetObject();
351 const char *name = connection->GetName();
352 void *obj = connection->GetReceiver();
353
354 if (!slot_name || !slot_name[0]
355 || !strcmp(name,slot_name)) {
356
357 if (!receiver || (receiver == obj)) {
358 return_value = kTRUE;
359 savlnk = lnk->Next(); // keep next link ..
360 Remove(lnk);
361 lnk = savlnk; // current link == saved ...
362 connection->Remove(this); // remove back reference
363 if (connection->IsEmpty()) SafeDelete(connection);
364 continue; // .. continue from saved link
365 }
366 }
367 lnk = lnk->Next();
368 }
369 return return_value;
370}
371
372////////////////////////////////////////////////////////////////////////////////
373/// List signal name and list all connections in this signal list.
374
375void TQConnectionList::ls(Option_t *option) const
376{
377 std::cout << "TQConnectionList:" << "\t" << GetName() << std::endl;
378 ((TQConnectionList*)this)->R__FOR_EACH(TQConnection,Print)(option);
379}
380
381
382////////////////////////////////////////////////////////////////////////////////
383/// TQObject Constructor.
384/// Comment:
385/// - In order to minimize memory allocation fListOfSignals and
386/// fListOfConnections are allocated only if it is neccesary
387/// - When fListOfSignals/fListOfConnections are empty they will
388/// be deleted
389
391{
392 fListOfSignals = 0;
395}
396
397////////////////////////////////////////////////////////////////////////////////
398/// TQObject Destructor.
399/// - delete all connections and signal list
400
402{
403 if (!gROOT) return;
404
405 Destroyed(); // emit "Destroyed()" signal
406
407 if (fListOfSignals) {
409 SafeDelete(fListOfSignals); // delete list of signals
410 }
411
412 // loop over all connections and remove references to this object
413 if (fListOfConnections) {
414 TIter next_connection(fListOfConnections);
415 TQConnection *connection;
416
417 while ((connection = (TQConnection*)next_connection())) {
418 TIter next_list(connection);
419 TQConnectionList *list;
420 while ((list = (TQConnectionList*)next_list())) {
421 list->Remove(connection);
422 if (list->IsEmpty()) SafeDelete(list);
423 }
424 }
426 }
427}
428
429////////////////////////////////////////////////////////////////////////////////
430/// Returns pointer to list of signals of this class.
431
433{
434 TQClass *qcl = 0;
435
436 qcl = dynamic_cast<TQClass*>(IsA());
437
438 return qcl ? qcl->fListOfSignals : 0; //!!
439}
440
441////////////////////////////////////////////////////////////////////////////////
442/// Collect class signal lists from class cls and all its
443/// base-classes.
444///
445/// The recursive traversal is not performed for classes not
446/// deriving from TQClass.
447
449{
450 TQClass *qcl = dynamic_cast<TQClass*>(cls);
451 if (qcl)
452 {
453 if (qcl->fListOfSignals)
454 list.Add(qcl->fListOfSignals);
455
456 // Descend into base-classes.
457 TIter next_base_class(cls->GetListOfBases());
458 TBaseClass *base;
459 while ((base = (TBaseClass*) next_base_class()))
460 {
462 }
463 }
464}
465
466////////////////////////////////////////////////////////////////////////////////
467/// 1. If slot_name = 0 => makes signal defined by the signal_name
468/// to be the first in the fListOfSignals, this decreases
469/// the time for lookup.
470/// 2. If slot_name != 0 => makes slot defined by the slot_name
471/// to be executed first when signal_name is emitted.
472/// Signal name is not compressed.
473
474void TQObject::HighPriority(const char *signal_name, const char *slot_name)
475{
476 if (!fListOfSignals) return;
477 TQConnectionList *clist = (TQConnectionList*)
478 fListOfSignals->FindObject(signal_name);
479
480 if (!clist) return; // not found
481 if (!slot_name) { // update list of signal lists
482 fListOfSignals->Remove(clist); // remove and add first
483 fListOfSignals->AddFirst(clist);
484 return;
485 } else { // slot_name != 0 , update signal list
486 TQConnection *con = (TQConnection*) clist->FindObject(slot_name);
487 if (!con) return; // not found
488 clist->Remove(con); // remove and add as first
489 clist->AddFirst(con);
490 }
491}
492
493////////////////////////////////////////////////////////////////////////////////
494/// 1. If slot_name = 0 => makes signal defined by the signal_name
495/// to be the last in the fListOfSignals, this increase the time
496/// for lookup.
497/// 2. If slot_name != 0 => makes slot defined by the slot_name
498/// to be executed last when signal_name is emitted.
499/// Signal name is not compressed.
500
501void TQObject::LowPriority(const char *signal_name, const char *slot_name)
502{
503 if (!fListOfSignals) return;
504 TQConnectionList *clist = (TQConnectionList*)
505 fListOfSignals->FindObject(signal_name);
506
507 if (!clist) return;
508 if (!slot_name) {
509 fListOfSignals->Remove(clist); // remove and add first
510 fListOfSignals->AddLast(clist);
511 return;
512 } else { // slot_name != 0 , update signal list
513 TQConnection *con = (TQConnection*) clist->FindObject(slot_name);
514 if (!con) return;
515 clist->Remove(con); // remove and add as last
516 clist->AddLast(con);
517 }
518}
519
520////////////////////////////////////////////////////////////////////////////////
521/// Return true if there is any object connected to this signal.
522/// Only checks for object signals.
523
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 consistency 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 consistency 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 consistency 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 consistency 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 consistency 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}
#define SafeDelete(p)
Definition RConfig.hxx:547
#define b(i)
Definition RSha256.hxx:100
int Int_t
Definition RtypesCore.h:45
char Char_t
Definition RtypesCore.h:37
const Bool_t kFALSE
Definition RtypesCore.h:92
bool Bool_t
Definition RtypesCore.h:63
const Bool_t kTRUE
Definition RtypesCore.h:91
const char Option_t
Definition RtypesCore.h:66
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:187
char name[80]
Definition TGX11.cxx:110
#define gInterpreter
void * gTQSender
Definition TQObject.cxx:73
Bool_t ConnectCINT(TQObject *sender, const char *signal, const char *slot)
Global function which simplifies making connection in interpreted ROOT session.
#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.
Buffer base class used for serializing objects.
Definition TBuffer.h:43
Bool_t IsReading() const
Definition TBuffer.h:86
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:4388
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:4433
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3613
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4851
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:2957
virtual void ls(Option_t *option="") const
List (ls) all objects in this collection.
TString fName
virtual Bool_t IsEmpty() const
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Basic data type descriptor (datatype information is obtained from CINT).
Definition TDataType.h:44
Int_t GetType() const
Definition TDataType.h:68
const char * GetFullTypeName() const
Get full type description of typedef, e,g.: "class TDirectory*".
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
Int_t GetNargsOpt() const
Number of function optional (default) arguments.
Int_t GetNargs() const
Number of function arguments.
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:822
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition TList.cxx:100
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition TList.cxx:578
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
virtual void AddLast(TObject *obj)
Add object at the end of the list.
Definition TList.cxx:152
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:107
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.
void * GetReceiver() const
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 consistency of sender/receiver methods/arguments.
Definition TQObject.cxx:178
virtual Int_t NumberOfConnections() const
Return number of connections for this object.
Definition TQObject.cxx:548
TQObject()
TQObject Constructor.
Definition TQObject.cxx:390
void CollectClassSignalLists(TList &list, TClass *cls)
Collect class signal lists from class cls and all its base-classes.
Definition TQObject.cxx:448
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.
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:97
TList * GetListOfClassSignals() const
Returns pointer to list of signals of this class.
Definition TQObject.cxx:432
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:401
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.
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.
virtual void LowPriority(const char *signal_name, const char *slot_name=0)
Definition TQObject.cxx:501
virtual void Connected(const char *)
Definition TQObject.h:193
virtual void HighPriority(const char *signal_name, const char *slot_name=0)
Definition TQObject.cxx:474
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:136
Ssiz_t Length() const
Definition TString.h:410
const char * Data() const
Definition TString.h:369
Bool_t IsNull() const
Definition TString.h:407
TString & Remove(Ssiz_t pos)
Definition TString.h:673
This class implements a mutex interface.
RPY_EXPORTED TCppMethod_t GetMethod(TCppScope_t scope, TCppIndex_t imeth)
auto * m
Definition textangle.C:8