Forward signals from child to parent
-
Hello
If I have three classes :Animal -> Dog -> Terrier
Where the dog is a child of animal and the terrier a child of dog.
How can I forward all the signals of terrier to animal? Kinda like an exception handler where the exception isn't caught, but flows "downwards". Thanks!
-R
-
Hi,
Funny question btw. usually when funtions need to be "forwarded" the class has virtual functions to overwrite functions. You might be able to overload functions in your main class (so making the slots yourself in the top most class. That might do the trick. Never tried it, never tested it ;-)
Otherwise in the constructor of your child, connect the signal to a slot of the parent. The signal will then be cascaded down the line.
Hope this gives you some idea.
Greetz -
Maybe this method is not practical, but have it a try though.
Create a signal for "terrier" and a signal for "dog".
Create a slot for "terrier" and a slot for "animal".Now, connect "terrier's" signal to "dog's" slot. After "dog" receives the signal, connect "dog's" signal to "animal's" slot. Trying to illustrate this:
Animal ........... Dog ........... Terrier
........................ slot <------- signal
slot <-------- signal
I tried this one but I think this is impractical so I limited all my coding into "no grandchilds" way. Hope it helps.
btw: got problem formatting my "drawing", so I edited it again.
-
I think you are looking at this from the wrong perspective ;-)
Signals are used for communication between different objects (instances). If the class "Terrier" inherits from "Dog" and the class "Dog" inherits from "Animal", then this means that each instance (object) of type "Terrier" also is a "Dog" and also is an "Animal" (just like and each instance of "Dog" also is an "Animal"). It's not like they are different objects! They are one and the same object. From an instance of a derived class (e.g. "Terrier") you can call functions of the super class (e.g. "Dog" or "Animal") directly, no signals are needed for this!
If "Terrier" receives a signal, it obviously must implement some slot for this purpose! Did "Dog" or "Animal" have that slot too and "Terrier" overwrote it? If so and if we assume that the slot is called someSlot(), then "Terrier" can simply call the slot of its super-calss via Dog::someSlot() or Animal::someSlot(), respectively, from its own slot function. Otherwise, if someSlot() was new in the "Terrier" class, you can't forward the signal anyway. Instead simply call whatever function of the super class that you need to be called from Terrier's slot function.
@void Terrier::someSlot()
{
if(/some condition is met/)
{
Dog::someSlot(); //Let super-class handle the signal ;-)
}
}@ -
Thank you for your replies so far.
MuldeR: Sorry for giving a bit confusing example, I understand that it gives the impression of inheritance being used (typical text book inheritance relationship), but this wasn't my case. Instead I did mean a case where there is a parent child relationship.
A: Baseclass
B: child of A
C: child of BProblem:
C: emits signal -> "flows" down to slot in ACode_ReaQtor: This is a possibility, and the pattern I've been using previously. However as you also mentioned, it's not too practical. Especially if we add a couple of more levels of children and want to pass the signal to the base class. What I'm looking for is a functionality like exception handling where the signal "is forwarded to the parent", though I don't know if such exists...
- R
-
If you really have separate objects (instances) with "parent child relationship", you can do it like Qt does it with Widgets, for example: The constructor of the child object gets a pointer to its parent object. Child object will remember that pointer (in some member variable), so whenever it needs to call a function of the parent object - which might or might not be the reaction to a signal that the child received - it can use that pointer. Of course, instead of remembering the pointer (or in addition to that) the child may connect some of its signals to some of the parents slots - in the child's constructor. Then the child simply uses emit, as usual.
@Terrier::Terrier(Dog *parent = NULL)
{
m_parent = parent ;
}void Terrier::someSlot()
{
if(/some condition is met/)
{
if(parent) m_parent->doSomething(); //Let parent object handle the signal ;-)
}
}@Alternative:
@Terrier::Terrier(Dog *parent = NULL)
{
if(parent) connect(this, SIGNAL(someSignal()), parent, SLOT(someSlot()));
}void Terrier::someSlot()
{
if(/some condition is met/)
{
emit someSignal(); //Let someone else (maybe parent) handle it ;-)
}
}@ -
[quote author="ThaRez" date="1352561808"]What I'm looking for is a functionality like exception handling where the signal "is forwarded to the parent", though I don't know if such exists...[/quote]
Hi ThaRez, I never heard of any exception handling in Qt (I encountered exception handling only in C#). Maybe there is... Inform me if there is any.
BTW, I found another solution to you problem and I tested it. Sticking to your naming convention...
"Animal -> Dog -> Terrier"Create a signal for "Terrier", lets say "someSignal()"... then create a slot for "Animal", "someSlot()".
Of course, you will start by adding "Terrier" to the class "Dog":
@public:
Terrier *terrier;@Then "Dog" in the class "Animal":
@public:
Dog *dog;@In class "Animal", you can do this.
@QObject::connect(dog->terrier,SIGNAL(someSignal()),this,SLOT(someSlot()));@The clue here is @dog->terrier@
I never tried adding another class down the line. Maybe I am too preoccupied by the time. Please confirm my codes. Thanks