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/*! \brief A guard pointer that disconnects an interested object upon destruction
41 *
42 * It's almost QPointer<> except that you have to initialise it with one
43 * more additional parameter - a pointer to a QObject that will be
44 * disconnected from signals of the underlying pointer upon the guard's
45 * destruction. Note that destructing the guard doesn't destruct either QObject.
46 */
47template <typename T>
48class ConnectionsGuard : public QPointer<T> {
49public:
50 ConnectionsGuard(T* publisher, QObject* subscriber)
52 {}
54 {
55 if (*this)
56 (*this)->disconnect(subscriber);
57 }
61 using QPointer<T>::operator=;
62
63private:
64 QObject* subscriber;
65};
66
67} // 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 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.