libQuotient
A Qt library for building matrix clients
Loading...
Searching...
No Matches
qt_connection_util.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2019 Kitsune Ral <kitsune-ral@users.sf.net>
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include <QtCore/QObject>
7#include <QtCore/QPointer>
8
9namespace Quotient {
10
11//! \brief Create a connection that self-disconnects when its slot returns true
12//!
13//! The "slot" signature accepted by connectUntil() is different from normal Qt slots in that its
14//! return value must be bool, not void. Also, as of this writing, connectUntil() doesn't accept
15//! member function pointers for slots as QObject::connect or Quotient::connectSingleShot do; if
16//! you want to use a member function of the context object you should pass a lambda or bind
17//! the context to the member function with std::bind_front before passing it to connectUntil().
18//! \return whether the connection should be dropped; false means that the
19//! connection remains; upon returning true, the slot is disconnected
20//! from the signal.
21template <typename SmartSlotT>
22inline auto connectUntil(auto* sender, auto signal, QObject* context, SmartSlotT&& smartSlot,
23 Qt::ConnectionType connType = Qt::AutoConnection)
24{
25 auto* cHolder = new QObject(context);
26 // Apart from checking the "smart slot" return type, the 'requires' clause below prevents Qt
27 // from eagerly trying to fill the lambda with more arguments than the "smart slot" can take
28 return QObject::connect(
29 sender, signal, cHolder,
30 [sl = std::forward<SmartSlotT>(smartSlot), cHolder]<typename... Ts>
31 requires std::invocable<SmartSlotT, Ts...>
32 (const Ts&... args) mutable {
33 static_assert(std::is_same_v<decltype(sl(args...)), bool>);
34 if (sl(args...))
35 delete cHolder; // break the connection
36 },
37 connType);
38}
39
40//! Create a connection that self-disconnects after triggering on the signal
41template <typename ContextT, typename SlotT>
42[[deprecated("Use QObject::connect() with Qt::SingleShotConnection, or QtFuture::connect()")]] //
43inline auto connectSingleShot(auto* sender, auto signal, ContextT* context, SlotT slot,
44 Qt::ConnectionType connType = Qt::AutoConnection)
45{
46 return QObject::connect(sender, signal, context, slot,
47 Qt::ConnectionType(connType | Qt::SingleShotConnection));
48}
49
50/*! \brief A guard pointer that disconnects an interested object upon destruction
51 *
52 * It's almost QPointer<> except that you have to initialise it with one
53 * more additional parameter - a pointer to a QObject that will be
54 * disconnected from signals of the underlying pointer upon the guard's
55 * destruction. Note that destructing the guard doesn't destruct either QObject.
56 */
57template <typename T>
58class ConnectionsGuard : public QPointer<T> {
59public:
60 ConnectionsGuard(T* publisher, QObject* subscriber)
62 {}
64 {
65 if (*this)
66 (*this)->disconnect(subscriber);
67 }
71 using QPointer<T>::operator=;
72
73private:
74 QObject* subscriber;
75};
76
77} // namespace Quotient
A guard pointer that disconnects an interested object upon destruction.
ConnectionsGuard(ConnectionsGuard &&)=default
ConnectionsGuard(T *publisher, QObject *subscriber)
ConnectionsGuard & operator=(ConnectionsGuard &&)=default
auto connectSingleShot(auto *sender, auto signal, ContextT *context, SlotT slot, Qt::ConnectionType connType=Qt::AutoConnection)
Create a connection that self-disconnects after triggering on the signal.
auto connectUntil(auto *sender, auto signal, QObject *context, SmartSlotT &&smartSlot, Qt::ConnectionType connType=Qt::AutoConnection)
Create a connection that self-disconnects when its slot returns true.