How to "hook" to existing signal?
I would like to connect to a widget's signal. When signal is emitted I need to do some processing and then envoke the orignal slot to which this signal was connected in the first place.
So, if the widget is a button I have a wrapper like the one below. My questions are in the comments. And the general question - is that approach correct at all? May be there is something else already provided by Qt?
Code:
class objBtnHook
{
public:
{
// how to store connected slot that is currently connected to the "clicked" signal?
QObject::disconnect (btn,
SIGNAL(clicked
()),
0,
0);
QObject::connect(btn,
SIGNAL(clicked
()),
this,
SLOT(hookedclicked
()) );
}
private slots:
void hookedclicked()
{
// do some processing
// invoke original slot - how? with QMetaObject::invokeMethod?
}
}
Re: How to "hook" to existing signal?
Is it important to you that your slot is called before the "original" slot is?
Otherwise you can simply connect clicked() to your slot and both slots will be executed (in arbitrary order)
Re: How to "hook" to existing signal?
Yes, it is the core of the problem. "My" slot should be called first in order to do validation. The idea behind that requirement is that every user action (click on the button) should be validated relative to the currently running threads.
Re: How to "hook" to existing signal?
may be this is little newbie approach but here it is..
do not disconnect anything.
use a bool global flag which will become true at the end of hooked function.
check for that flag to become true in a event loop upon the entry of the original slot
make that flag false again at the end of original slot.
:)
Re: How to "hook" to existing signal?
A wild & crazy idea: yank the original button out of the layout and replace it with your own copy of it. The clicked signal of the copied button is connected to your slot, and the last thing that slot does is to "emit chain()", where the chain-signal is connected to the clicked-signal of the original button...
Re: How to "hook" to existing signal?
In your situation, is it possible that more than one slot is connected to the signal you want to intercept?
Re: How to "hook" to existing signal?
No, in my case each button has only one "original" slot connected to it.
Let me explain what the underlying issue is - may be there is a solution that Qt supports in "out-of-the-box" manner.
I have a dialog with several tabs on it. Each tab hosts a widget of different kind. Each tab widget represents a view into a separate thread. These threads are separated from each other in terms of implementation, they are connected only by application logic (synchronization mutexes). These views, i.e widgets, have this in common - they all have several buttons that control their respective threads and also provide the user with ability to view underlying thread-specific data.
So, what I am trying to do is to have a "action synchronizer" instance in each of the widgets. This synchronizer is intialized with all widget buttons that user can click on. When user clicks one of these buttons the synchronizer inspects the state of threads and makes a decision if this click is currently allowed or not.
This is generic functionality, I don' have to repeat it in every slot. So, I am creating synchronizer instance and populate it with all widget buttons. Now I have to "hook up" to the current signal-slot connection of the button. And - oops! - I don't see the way to do it.
Re: How to "hook" to existing signal?
Quote:
Originally Posted by
QPlace
No, in my case each button has only one "original" slot connected to it.
So maybe it shouldn't be a signal-slot connection in the first place? Maybe you should use events or something?
Quote:
So, what I am trying to do is to have a "action synchronizer" instance in each of the widgets. This synchronizer is intialized with all widget buttons that user can click on. When user clicks one of these buttons the synchronizer inspects the state of threads and makes a decision if this click is currently allowed or not.
This is generic functionality, I don' have to repeat it in every slot. So, I am creating synchronizer instance and populate it with all widget buttons. Now I have to "hook up" to the current signal-slot connection of the button. And - oops! - I don't see the way to do it.
So why don't you connect the clicked() signal of each of the buttons to a slot in your synchronizer class and emit some signal from the slot if it is allowed, or don't emit it if it is not? Then you can connect your true functionality to that signal(s) and act accordingly.
Re: How to "hook" to existing signal?
Thank you, the second option that you suggested is a possibility.
The important thing that I am taking out of this discussion is that there is no easy way to "hook" into existing "signal-slot" connection.
Re: How to "hook" to existing signal?
Actually there is, but that's only a "peek-only" solution, you can't modify anything.
Re: How to "hook" to existing signal?
Would you mind to show how to peek into the signal-slot connection?
Originally I wanted to store existing slot somewhere, but soon realized that it will be like storing pointer-to-member function without the actual instance, which I believe is impossible.
May it is possible, using Qt, to peek into signal-slot connection and store it somewhere for later restoration? (dreaming :) )
Re: How to "hook" to existing signal?
Quote:
Originally Posted by
QPlace
Would you mind to show how to peek into the signal-slot connection?
QSignalSpy.
Quote:
May it is possible, using Qt, to peek into signal-slot connection and store it somewhere for later restoration? (dreaming :) )
If you subclass the object, you can provide your own implementation of qt_metacall() and there you can do whatever you want. But of course that's not possible for already instantiated objects of already existing classes.
I still think you are trying to implement a wrong approach here.