5

I would like to generically and temporarily block the signals between two QObjects without modifying the other signals/slots behavior, and without knowing their contexts.

Something like QObject::blockSignals(bool), but only acting between two QObjects.

That is, implementing the following SignalBlocker::blockSignals(bool) function:

class SignalBlocker {

public:
  SignalBlocker(QObject *sender, QObject *receiver) :
    mSender(sender), mReceiver(receiver) {}
  void blockSignals(bool block);

private:
  QObject *mSender, *mReceiver;
}

It would be possible by disconneting and re-connecting the objects, but first the list of signals/slots would have to be stored. Introspection methods don't seem to be powerful enough to achieve this (I looked at QMetaObject and QSignalSpy without success).

Nicolas Holthaus
  • 7,763
  • 4
  • 42
  • 97
FabienRohrer
  • 1,794
  • 2
  • 15
  • 26

3 Answers3

11

QT have no capabilities to disable signal-slot pair only. Try this workaround:

struct SignalDisabler
{
    SignalDisabler(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
        : sender(sender)
        , signal(signal)
        , receiver(receiver)
        , member(member)
    {
        QObject::disconnect(sender, signal, receiver, member);
    }

    ~SignalDisabler()
    {
        QObject::connect(sender, signal, receiver, member);
    }

    const QObject *sender;
    const char *signal;
    const QObject *receiver;
    const char *member;
};
Oleg
  • 125
  • 1
  • 6
3

since you want that the sender and the reciever will not send signals within that scope, i would just try to use blockSignals(bool)

class SignalBlocker{
public:
SignalBlocker(QObject* obj)
{
   _o = obj;
   _o->blockSignals(true);
}
~SignalBlocker()
{
   _o->blockSignals(false);
}
private:
   QObject* _o;
};

and now just use

SignalBlocker sb1(sender);
SignalBlocker sb2(reciever);
//...
Nicolas Holthaus
  • 7,763
  • 4
  • 42
  • 97
Zaiborg
  • 2,492
  • 19
  • 28
  • Unfortunately, this still doesn't solve my problem, because sender and receiver are in this case completely blocked (they cannot send messages to a third QObject, while this is what I need). – FabienRohrer Apr 03 '13 at 08:17
  • maybe its possible to create a class like `SignalBlocker` and give the objects a template function pointer of what you want to block ... so it would be blocking just the signal you want – Zaiborg Apr 03 '13 at 11:43
0

You can use disconnect(sender, 0, receiver, 0); to disconnect all sender's signals from all receiver's slots.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
SpongeBobFan
  • 964
  • 5
  • 13
  • Indeed, but I would like to be able to retrieve the same state as before the disconnection when reconnecting the Object. So before the disconnection, I should list all the signals/slots connections between the sender and the receiver (and this is the point I'm unable to do). – FabienRohrer Mar 26 '13 at 10:25
  • Try to use something like `void QObject::connectNotify ( const char * signal ) [virtual protected]` or `void QObject::disconnectNotify ( const char * signal ) [virtual protected]` to get a list of connected/disconnected signals, but I don't think you're doing right things. Why do you need that? – SpongeBobFan Mar 26 '13 at 10:29