swift
slot.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2016 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_SLOT_H
7 #define SWIFT_MISC_SLOT_H
8 
9 #include <atomic>
10 #include <functional>
11 #include <future>
12 #include <memory>
13 
14 #include <QObject>
15 #include <QPointer>
16 #include <QTimer>
17 #include <QtGlobal>
18 
19 #include "misc/invoke.h"
20 
21 namespace swift::misc
22 {
26  template <typename T, typename U, typename F, typename G>
27  QMetaObject::Connection connectOnce(T *sender, F signal, U *receiver, G &&slot,
28  Qt::ConnectionType type = Qt::AutoConnection)
29  {
30  std::promise<QMetaObject::Connection> promise;
31  auto called = std::make_shared<std::atomic_flag>();
32  called->clear();
33  auto wrapper = [receiver, called, connection = promise.get_future().share(),
34  slot = std::forward<G>(slot)](auto &&...args) {
35  if (called->test_and_set()) { return; }
36  QObject::disconnect(connection.get());
37  private_ns::invokeSlot(slot, receiver, std::forward<decltype(args)>(args)...);
38  };
39  auto connection = QObject::connect(sender, signal, receiver, std::move(wrapper), type);
40  promise.set_value(connection);
41  return connection;
42  }
43 
48  template <typename T, typename F, typename G>
49  QMetaObject::Connection connectOnce(T *sender, F signal, G &&slot)
50  {
51  static_assert(!std::is_member_pointer_v<std::decay_t<G>>,
52  "If slot is a pointer to member, a receiver must be supplied");
53  return connectOnce(sender, signal, sender, std::forward<G>(slot));
54  }
55 
61  template <typename F>
62  class CSlot;
63 
68  template <typename R, typename... Args>
69  class CSlot<R(Args...)>
70  {
71  public:
73  CSlot() {}
74 
76  template <typename T, typename U>
77  CSlot(T *object, R (U::*function)(Args...))
78  : m_object(object), m_function([=](Args... args) { return (object->*function)(args...); })
79  {
80  Q_ASSERT_X(object, Q_FUNC_INFO, "Need object");
81  }
82 
84  template <typename T>
85  CSlot(T *object, std::function<R(Args...)> function) : m_object(object), m_function(function)
86  {}
87 
89  R operator()(Args... args) const
90  {
91  Q_ASSERT_X(m_function, Q_FUNC_INFO, "Empty CSlot was called");
92  return m_function(args...);
93  }
94 
96  bool singleShot(Args... args) const
97  {
98  // does NOT return the values of m_function!
99  if (!m_object || !m_function) { return false; }
100  QTimer::singleShot(0, m_object.data(), std::bind(*this, std::forward<Args>(args)...));
101  return true;
102  }
103 
106  QObject *object() const { return m_object.data(); }
107 
110  void setObject(QObject *object)
111  {
112  Q_ASSERT_X(hasNullObject(), Q_FUNC_INFO, "Can only set, not change the object");
113  m_object = object;
114  }
115 
117  operator bool() const { return !this->isEmpty() && !this->hasNullObject(); }
118 
120  bool operator!() const { return this->isEmpty() || this->hasNullObject(); }
121 
123  bool isEmpty() const { return !m_function; }
124 
126  bool hasNullObject() const { return m_object.isNull(); }
127 
128  private:
129  QPointer<QObject> m_object;
130  std::function<R(Args...)> m_function;
131  };
132 } // namespace swift::misc
133 
134 #endif // SWIFT_MISC_SLOT_H
R operator()(Args... args) const
Call the slot. The behaviour is undefined if the slot is empty.
Definition: slot.h:89
bool hasNullObject() const
True if the object is null.
Definition: slot.h:126
CSlot(T *object, std::function< R(Args...)> function)
Construct a slot from the given object passing a function and a object.
Definition: slot.h:85
QObject * object() const
Returns the object which the slot belongs to. Use this as the third argument to QObject::connect to e...
Definition: slot.h:106
bool operator!() const
True if the slot is empty or object is null, false if it can be called.
Definition: slot.h:120
bool isEmpty() const
True if the slot is empty, false if it can be called.
Definition: slot.h:123
CSlot()
Construct an empty slot.
Definition: slot.h:73
CSlot(T *object, R(U::*function)(Args...))
Construct a slot from the given member function of the given object.
Definition: slot.h:77
void setObject(QObject *object)
Set the object which the slot belongs to. Use this as the third argument to QObject::connect to ensur...
Definition: slot.h:110
bool singleShot(Args... args) const
Call function "de-coupled" in original thread.
Definition: slot.h:96
Callable wrapper for a member function with function signature F.
Definition: slot.h:62
Free functions in swift::misc.
QMetaObject::Connection connectOnce(T *sender, F signal, U *receiver, G &&slot, Qt::ConnectionType type=Qt::AutoConnection)
Wrapper around QObject::connect which disconnects after the signal has been emitted once.
Definition: slot.h:27
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...
Definition: threadutils.h:30