There is a function QObject::sender()
, than, when invoked in a slot, provides the QObject*
pointer to the sending object.
It's behaviour is far less useful if you have the following structure.
class A : public QObject { Q_OBJECT
...
signals:
void foo();
};
class B : public QObject { Q_OBJECT
...
signals:
void foo();
};
class C : public QObject { Q_OBJECT
...
public slots:
void bar() { qDebug() << sender(); }
};
A a;
B b;
C c;
connect(&A, SIGNAL(foo()), &B, SIGNAL(foo()));
connect(&B, SIGNAL(foo()), &C, SLOT(bar()));
A::whatever() { emit foo(); }
C::bar()
indicates B
as the emitter. How can I get the original emitting object, without dealing with all the relays?
Unfortunately QObject::sender()
is protected
so this naive approach in C::bar()
wouldn't compile (not sure if it ever could work, but that's my only idea to traverse the sender()
backwards):
QObject *ptr = this;
while ((ptr = ptr->sender()) != NULL)
qDebug() << ptr->objectName();
To answer some of the questions raised in comments:
A
- custom widget (lots of dynamically created ones) (holding some data, pointers, whatnot)B
- custom top-level UI element (member of theQStackedWidget
, handles some UI responsibilities)C
- (in practice,C1
,C2
,C3
) - work that needs to be performed (using common state, such as DSP queue) on data stored in As.
Ultimately, A
needs to know very little about C
s (or even if anything cares about it's signals). B
is where the UI aggregation takes place (also the top-level UI calls C
s to set DSP parameters etc). C
s need to know if sender()
is qobject_cast
'able to IA
interface.
It can be reworked to something along the lines of:
class A : public QObject { Q_OBJECT
...
signals:
void foo(QObject*);
};
class B : public QObject { Q_OBJECT
...
signals:
void foo(QObject*);
};
class C : public QObject { Q_OBJECT
...
public slots:
void bar(QObject* mySender) { qDebug() << mySender; }
};
A a;
B b;
C c;
connect(&A, SIGNAL(foo(QObject*)), &B, SIGNAL(foo(QObject*)));
connect(&B, SIGNAL(foo(QObject*)), &C, SLOT(bar(QObject*)));
A::whatever() { emit foo(this); }