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