(With \"signal handler\" I mean slots, not handlers for POSIX signals.)
I need to \"connect\" (probably not using QObject::connect
directly)
I was looking for a generic signal handler for the same reason, i.e. forwarding signal calls via RPC. There is a very interesting and detailed description of the QObject-QMetaObject magic in a QtDevDays presentation. In particular, they also describe the desire to inspect generic signals for debugging or interfacing with scripting languages - so this is a perfect read.
Long story short: Your solution was to modify qt_static_metacall
in the moc code. (Now in Qt5?) The same thing can be achieved by subclassing your QObject based class and overriding qt_metacall
, for example:
class QRpcService : public QRpcServiceBase
{
public:
explicit QRpcService(QTcpServer* server, QObject *parent = 0);
virtual ~QRpcService();
virtual int qt_metacall(QMetaObject::Call, int, void**);
private:
static int s_id_handleRegisteredObjectSignal;
};
The magic capture-all-slot is just a dummy method defined in the base class (here void handleRegisteredObjectSignal()
) that takes nothing and does nothing. I query its meta-method-id in the constructor and store it as static int
to avoid searching for it every time.
Within this custom metacall handler you intercept the calls to your magic-capture-all slot and inspect the sender object and signal. This provides all the type information required to convert the void**
arguments to a QVariant list
int QRpcService::qt_metacall(QMetaObject::Call c, int id, void **a)
{
// only handle calls to handleRegisteredObjectSignal
// let parent qt_metacall do the rest
if (id != QRpcService::s_id_handleRegisteredObjectSignal)
return QRpcServiceBase::qt_metacall(c, id, a);
// inspect sender and signal
QObject* o = sender();
QMetaMethod signal = o->metaObject()->method(senderSignalIndex());
QString signal_name(signal.name());
// convert signal args to QVariantList
QVariantList args;
for (int i = 0; i < signal.parameterCount(); ++i)
args << QVariant(signal.parameterType(i), a[i+1]);
// ...
// do whatever you want with the signal name and arguments
// (inspect, send via RPC, push to scripting environment, etc.)
// ...
return -1;
}
I just handled everything within this method, but you could also re-emit all the information that was gathered in another signal and attach to that at runtime.
If anyone is interested, I also set up a repository with my solution here.