PDA

View Full Version : Querying signal/slot state at runtime



lxman
7th March 2011, 12:36
Is there a way to query the state of the signal/slot connections at runtime? i.e. if I am an instantiated instance of class A (inherited from QObject, of course), can I go look somewhere to see which objects are currently connected to my signal B()? I am looking at QMetaObject, but it only seems to list the signals and slots that I have available, not what their current state of connection is.

wysota
7th March 2011, 13:02
There is no way to do that. You can only use QObject::connectNotify() and QObject::disconnectNotify().

squidge
7th March 2011, 13:24
If some type of signal generation is time intensive and you only want to do the work and produce the signal if something is connected to it, then you can also use QObject::receivers() as far as I'm aware rather than keeping a count yourself.

wysota
7th March 2011, 13:33
The problem with the receivers() method is that it is probably unreliable in the sense that its result is not trustworthy. You can query for receivers and immediately after this method returns a connection can be made to the object in another thread before any more code has a chance to run.

lxman
7th March 2011, 13:42
squidge:

Yes, that does look like it will accomplish what I am looking for. Basically I just need to query if a particular signal has anyone connected to it at all at a particular time. I'm not interested in an itemized object list.

wysota:

I am sitting here right now experimenting with connectNotify and disconnectNotify. The connectNotify events are coming through nicely. The disconnectNotify, however, does not seem to work as I expect. When I connect object B to object A and then destroy object B, object A is not receiving a disconnectNotify. I also tried an explicit disconnect(SIGNAL) call in object B just before destroying it, and object A is still not receiving a disconnectNotify.

Any working examples available to help me see if I am doing something wrong?

wysota
7th March 2011, 13:50
disconnectNotify() will not be called if an object is destroyed without prior disconnection. Unfortunately receivers() will not help you in some cases either. What exactly do you need this functionality for?

lxman
7th March 2011, 14:03
I am writing a graphics drawing program, and I want to be able to dynamically "parent" objects to one another. Parenting in my case involves connecting a particular signal on the "parent" to a slot on the "child," not using the setParent() method as might seem more intuitive. I wish to set the constraint that if an object is already a "child", that object cannot have two "parent"s (i.e. there can't be two "parents" hooked to the "child"s slot). As well, if an object is already a "child," that object is then not allowed to "parent" other objects.

I could set up some sort of manager class to track all of this with my dynamically created/destroyed objects, but as I am only connecting one slot to one signal to accomplish my "parenting," it seems more direct to me to be able to just query the current signal/slot connection state on that particular signal/slot.

qlands
7th March 2011, 14:20
Hi,

I don't think you need to go that far. If setParent() does not work for you. You can also have a public member QGraphicsItem *myparent started in 0; You can dynamically set myparent to the parent. If parent is not assigned means that the object has no parent. With this you can control that a child cannot have two parents.

In terms of signals if you parent the object you can connect a signal from the parent to the child and viceversa.

lxman
7th March 2011, 23:24
Yes, qlands, that may fit. I didn't understand one thing though.


You can also have a public member QGraphicsItem *myparent started in 0

What do you mean by "started in 0"?

qlands
8th March 2011, 06:32
I mean that you can have a public member in your child


public:
MyParentClass *myparent; //In this case I'm asuming MyParentClass is a subclass of any QGraphicsItem


and in the constructor of the child you have:



myparent = 0;


then you can check when parenting the child:


if (!myparent) //Only if my parent is 0 which mean that it does not have a parent
{
myparent = mynewparent;
}

lxman
8th March 2011, 07:03
Oh, okay, I understand now. I think this idea is the basic one I am going to go with. The actual implementation is going to be quite a bit more complex, but the direction looks good to me.

Thanks to all for giving me the suggestions.

wysota
8th March 2011, 07:49
I am writing a graphics drawing program, and I want to be able to dynamically "parent" objects to one another. Parenting in my case involves connecting a particular signal on the "parent" to a slot on the "child," not using the setParent() method as might seem more intuitive. I wish to set the constraint that if an object is already a "child", that object cannot have two "parent"s (i.e. there can't be two "parents" hooked to the "child"s slot). As well, if an object is already a "child," that object is then not allowed to "parent" other objects.

I could set up some sort of manager class to track all of this with my dynamically created/destroyed objects, but as I am only connecting one slot to one signal to accomplish my "parenting," it seems more direct to me to be able to just query the current signal/slot connection state on that particular signal/slot.

You don't need signals in this case. You can call the method directly as the child and the parent know about each other:

void Parent::someMethod() {
// ...
foreach(Child *chld, m_children) chld->someOtherMethod();
// ...
}

Using signals makes sense when objects do not know about each other's existence.