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