Skip to content

Latest commit

 

History

History
60 lines (49 loc) · 3.38 KB

README.md

File metadata and controls

60 lines (49 loc) · 3.38 KB

once

Sometimes you want to connect a slot or a functor to a Qt signal and only have it be called once. Adding the necessary logic to enable this can mess up the code unnecessarily, especially with lambdas, since a connection handle is needed to disconnect them.

This tiny framework provides connect functions argument-compatible with the QObject::connect series that will call the slot or functor only once. The logic is simple:

  • Create a pointer that will store the connection handle returned from QObject::connect
  • Capture this pointer in a wrapper function
  • Connect the passed signal to call the wrapper function
  • Disconnect the connection inside the wrapper function and then call the passed functor or slot

Although the fire-once-only logic is simple, additional logic and template code is needed since Once::connect needs to work like QObject::connect: accept all kinds of functors, lambda and slots and conveniently discard superfluous signal arguments. The implementation allows perfect forwarding of arguments and, although it can probably be simplified, should work just as QObject::connect does.

Methods

The following methods are available. Note that the function signature is simplified for readability. Remember that a slot also can be a signal.

/* Call functor when signal is emitted from sender and disconnect it
   immediately afterwards */
QMetaObject::Connection Once::connect(const QObject *sender, Signal signal,
      Functor functor)

/* Call functor when signal is emitted from sender in the given context, using
   the given connection type. Disconnect functor immediately afterwards. */
QMetaObject::Connection Once::connect(const QObject *sender, Signal signal,
      const QObject *context, Functor functor, Qt::ConnectionType type =
      Qt::AutoConnection)

/* Call functor when signal is emitted from sender and disconnect it after N
   calls, specified by callCount. */
QMetaObject::Connection Once::connect(const QObject *sender, Signal signal, int
      callCount, Functor functor)

/* Call functor when signal is emitted from sender in the given context, using
   the given connection type. Disconnect functor after N calls, specified by
   callCount. */
QMetaObject::Connection Once::connect(const QObject *sender, Signal signal, int
      callCount, const QObject *context, Functor functor, Qt::ConnectionType
      type = Qt::AutoConnection)

/* Call member function when signal is emitted from sender (in the context of
   receiver), using the given connection type. Disconnect the slot immediately
   afterwards. */
QMetaObject::Connection Once::connect(const QObject *sender, Signal signal,
      const QObject *receiver, Slot slot, Qt::ConnectionType type =
      Qt::AutoConnection)

/* Call member function when signal is emitted from sender (in the context of
   receiver), using the given connection type. Disconnect the slot after N
   calls, specified by callCount. */
QMetaObject::Connection Once::connect(const QObject *sender, Signal signal, int
      callCount, const QObject *receiver, Slot slot, Qt::ConnectionType type =
      Qt::AutoConnection)

How to use

Include once.h in your project and use a compiler that supports C++11 (or higher). Use Once::connect as you would use QObject::connect. If you need to disconnect the slot/functor/signal, disconnect the returned QMetaObject::Connection with static bool QObject::disconnect(const QMetaObject::Connection &connection).