LibrePCB Developers Documentation
signalslot.h
Go to the documentation of this file.
1/*
2 * LibrePCB - Professional EDA for everyone!
3 * Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
4 * https://librepcb.org/
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifndef LIBREPCB_CORE_SIGNALSLOT_H
21#define LIBREPCB_CORE_SIGNALSLOT_H
22
23/*******************************************************************************
24 * Includes
25 ******************************************************************************/
26#include <QtCore>
27
28#include <functional>
29
30/*******************************************************************************
31 * Namespace / Forward Declarations
32 ******************************************************************************/
33namespace librepcb {
34
35template <typename Tsender, typename... Args>
36class Slot;
37
38/*******************************************************************************
39 * Class Signal
40 ******************************************************************************/
41
64template <typename Tsender, typename... Args>
65class Signal {
66 friend class Slot<Tsender, Args...>;
67
68public:
69 // Constructors / Destructor
70 Signal() = delete;
71 Signal(const Signal& other) = delete;
72
78 explicit Signal(const Tsender& sender) noexcept : mSender(sender) {}
79
85 ~Signal() noexcept {
86 for (auto slot : mSlots) {
87 slot->mSignals.remove(this);
88 }
89 }
90
96 int getSlotCount() const noexcept { return mSlots.count(); }
97
103 void attach(Slot<Tsender, Args...>& slot) const noexcept {
104 slot.mSignals.insert(this);
105 mSlots.insert(&slot);
106 }
107
113 void detach(Slot<Tsender, Args...>& slot) const noexcept {
114 slot.mSignals.remove(this);
115 mSlots.remove(&slot);
116 }
117
123 void notify(Args... args) noexcept {
124 // Note: A "foreach" loop with a Qt container first creates an implicitly
125 // shared copy of the container (see
126 // https://doc.qt.io/qt-5/containers.html#foreach). This is very important
127 // since the callback might modify the container while iterating over it!
128 // With std containers this would be much more complicated (or less
129 // efficient).
130 foreach (const auto& slot, mSlots) {
131 // Check existence of the slot again because we must not call it if it
132 // was detached (i.e. removed from the container) in the meantime.
133 if (mSlots.contains(slot)) {
134 slot->mCallback(mSender, args...);
135 }
136 }
137 }
138
139 // Operator Overloadings
140 Signal& operator=(Signal const& other) = delete;
141
142private:
143 const Tsender& mSender;
144 mutable QSet<Slot<Tsender, Args...>*> mSlots;
145};
146
147/*******************************************************************************
148 * Class Slot
149 ******************************************************************************/
150
169template <typename Tsender, typename... Args>
170class Slot {
171 friend class Signal<Tsender, Args...>;
172
173public:
174 // Constructors / Destructor
175 Slot() = delete;
176 Slot(const Slot& other) = delete;
177
185 explicit Slot(
186 const std::function<void(const Tsender&, Args...)>& callback) noexcept
187 : mCallback(callback) {}
188
197 template <typename T>
198 explicit Slot(T& obj, void (T::*func)(const Tsender&, Args...)) noexcept
199 : mCallback([=, &obj](const Tsender& s, Args... args) {
200 (obj.*func)(s, args...);
201 }) {}
202
208 ~Slot() noexcept { detachAll(); }
209
215 int getSignalCount() const noexcept { return mSignals.count(); }
216
220 void detachAll() noexcept {
221 for (auto signal : mSignals) {
222 signal->mSlots.remove(this);
223 }
224 mSignals.clear();
225 }
226
227 // Operator Overloadings
228 Slot& operator=(Slot const& other) = delete;
229
230private:
232 QSet<const Signal<Tsender, Args...>*> mSignals;
233
235 std::function<void(const Tsender&, Args...)> mCallback;
236};
237
238/*******************************************************************************
239 * End of File
240 ******************************************************************************/
241
242} // namespace librepcb
243
244#endif
The Signal class is used to emit signals on non-QObject derived classes.
Definition: signalslot.h:65
QSet< Slot< Tsender, Args... > * > mSlots
All attached slots.
Definition: signalslot.h:144
void notify(Args... args) noexcept
Notify all attached slots.
Definition: signalslot.h:123
void detach(Slot< Tsender, Args... > &slot) const noexcept
Detach a slot.
Definition: signalslot.h:113
void attach(Slot< Tsender, Args... > &slot) const noexcept
Attach a slot.
Definition: signalslot.h:103
Signal & operator=(Signal const &other)=delete
const Tsender & mSender
Reference to the sender object.
Definition: signalslot.h:143
Signal(const Signal &other)=delete
~Signal() noexcept
Destructor.
Definition: signalslot.h:85
Signal(const Tsender &sender) noexcept
Constructor.
Definition: signalslot.h:78
int getSlotCount() const noexcept
Get the count of registered slots.
Definition: signalslot.h:96
The Slot class is used to receive signals from non-QObject derived classes.
Definition: signalslot.h:170
int getSignalCount() const noexcept
Get the count of registered signals.
Definition: signalslot.h:215
QSet< const Signal< Tsender, Args... > * > mSignals
All signals this slot is attached to.
Definition: signalslot.h:232
std::function< void(const Tsender &, Args...)> mCallback
The registered callback function.
Definition: signalslot.h:235
void detachAll() noexcept
Detach from all signals.
Definition: signalslot.h:220
Slot(const Slot &other)=delete
~Slot() noexcept
Destructor.
Definition: signalslot.h:208
Slot(T &obj, void(T::*func)(const Tsender &, Args...)) noexcept
Constructor.
Definition: signalslot.h:198
Slot & operator=(Slot const &other)=delete
Slot(const std::function< void(const Tsender &, Args...)> &callback) noexcept
Constructor.
Definition: signalslot.h:185
Definition: occmodel.cpp:77