[PyQt] Fwd: Re: disconnect all slots in QObject

Baz Walter bazwal at ftml.net
Fri Nov 11 03:37:02 GMT 2016


-------- Forwarded Message --------
Subject: Re: [PyQt] disconnect all slots in QObject
Date: Fri, 11 Nov 2016 03:30:26 +0000
From: oliver <oliver.schoenborn at gmail.com>
To: Baz Walter <bazwal at ftml.net>

It would be something like this but I must say I don't like the O(N x M)
complexity that result from the fact the connections are not stored
anywhere:

def disconnect_all_slots(emitter: QObject, receiver: QObject):
     def methods(obj: QObject, meth_type: int):
         meta_object = obj.metaObject()
         for i in range(meta_object.methodCount()):
             method = meta_object.method(i)
             if method.methodType() == meth_type:
                 meth_name = bytes(method.name()).decode()
                 yield getattr(obj, meth_name)

     from PyQt5.QtCore import QMetaMethod
     disconnections = {}
     for signal in methods(emitter, QMetaMethod.Signal):
         for slot in methods(receiver, QMetaMethod.Slot):
             try:
                 signal.disconnect(slot)
                 disconnections.setdefault(signal, []).append(slot)
             except:
                 # there was no connection, move on to next slot
                 pass

     print('disconnected', disconnections)

If connections were stored, you could just loop over all connections that
have emitter on one side and reciever on the other, would be very fast.
I'll have to accept the error-prone approach of having receiver disconnect
from all signals that have likely been connected (a maintenance headache).

On Thu, 10 Nov 2016 at 21:29 oliver <oliver.schoenborn at gmail.com> wrote:

> Thanks for your reply. However these 2 capabilities, although useful, are
> not the same as asking how to do "emitter.disconnect(receiver)" which in
> C++ would automatically loop over all signals of emitter, and for each one,
> would call disconnect(receiver). I suppose I could create a helper function
> that does this, using the metaObject().method(i) with type=Signal, but
> since this is in Qt I thought there was a good chance I'd be
> re-implementing the wheel in PyQt, but that's not the case from what you
> are saying.
> Oliver
>
> On Thu, 10 Nov 2016 at 21:17 Baz Walter <bazwal at ftml.net> wrote:
>
> On 11/11/16 00:06, oliver wrote:
> > The Qt docs at http://doc.qt.io/qt-5/qobject.html#disconnect-2 suggest
> that
> > it is possible to disconnect all signals of an emitter from all slots of
> a
> > specific receiver (because the method name can be null). In Python, the
> > following should therefore work, but it doesn't:
> >
> > from PyQt5.QtCore import QObject, pyqtSignal
> >
> > class Foo(QObject):
> >     def slot1(self):
> >         print('slot1')
> >
> > class Emitter(QObject):
> >     sig_test = pyqtSignal()
> >
> > foo = Foo()
> > emitter = Emitter()
> > con = emitter.sig_test.connect(foo.slot1)
> > emitter.disconnect(foo)  # TypeError: too many arguments
> >
> > QObject.disconnect() takes no arguments. Is the equivalent functionality
> > somewhere else in PyQt? Also, the C++ docs indicate that connecting a
> > signal to a slot returns a QMetaObject::Connection object; nothing is
> > returned from connect(), so same question there.
>
> PyQt5 has it's own syntax for connecting signals, so much of the C++ API
> documentation on that topic is not relevant.
>
> The main exception is the no-argument overload of QObject.disconnect(),
> which disconnects *all* the signals of an object.
>
> Otherwise, the equivalent functionality is to be found on the bound pyqt
> signal object itself. So to disconnect all slots from a specific signal,
> you would do this:
>
>      emitter.sig_test.disconnect()
>
> and to disconnect a specific slot from a signal:
>
>      emitter.sig_test.disconnect(foo.slot1)
>
> If you want more details, read this:
>
>      http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html
>
> --
> Regards
> Baz Walter
>
> --
> Oliver
>
-- 
Oliver



More information about the PyQt mailing list