Fcitx
connectableobject.h
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2016-2016 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #ifndef _FCITX_UTILS_CONNECTABLEOBJECT_H_
8 #define _FCITX_UTILS_CONNECTABLEOBJECT_H_
9 
10 #include <functional>
11 #include <memory>
12 #include <string>
13 #include <utility>
14 #include <fcitx-utils/fcitxutils_export.h>
15 #include <fcitx-utils/macros.h>
16 #include <fcitx-utils/metastring.h>
17 #include <fcitx-utils/signals.h>
18 
19 /// \addtogroup FcitxUtils
20 /// \{
21 /// \file
22 /// \brief Utilities to enable use object with signal.
23 
24 /// \brief Declare signal by type.
25 #define FCITX_DECLARE_SIGNAL(CLASS_NAME, NAME, ...) \
26  struct NAME { \
27  using signalType = __VA_ARGS__; \
28  using signature = fcitxMakeMetaString(#CLASS_NAME "::" #NAME); \
29  }
30 
31 /// \brief Declare a signal.
32 #define FCITX_DEFINE_SIGNAL(CLASS_NAME, NAME) \
33  ::fcitx::SignalAdaptor<CLASS_NAME::NAME> CLASS_NAME##NAME##Adaptor { this }
34 
35 /// \brief Declare a signal in pimpl class.
36 #define FCITX_DEFINE_SIGNAL_PRIVATE(CLASS_NAME, NAME) \
37  ::fcitx::SignalAdaptor<CLASS_NAME::NAME> CLASS_NAME##NAME##Adaptor { q_ptr }
38 
39 namespace fcitx {
40 
41 class ConnectableObject;
42 
43 /// \brief Helper class to register class.
44 template <typename T, typename Combiner = LastValue<typename std::function<
45  typename T::signalType>::result_type>>
47 public:
49  ~SignalAdaptor();
50 
51 private:
52  ConnectableObject *self;
53 };
54 
56 
57 /// \brief Base class for all object supports connection.
58 class FCITXUTILS_EXPORT ConnectableObject {
59  template <typename T, typename Combiner>
60  friend class SignalAdaptor;
61 
62 public:
64  virtual ~ConnectableObject();
65 
66  template <typename SignalType, typename F>
67  Connection connect(F &&func) {
68  auto signal = findSignal(SignalType::signature::data());
69  if (signal) {
70  return static_cast<Signal<typename SignalType::signalType> *>(
71  signal)
72  ->connect(std::forward<F>(func));
73  }
74  return {};
75  }
76 
77  template <typename SignalType>
78  void disconnectAll() {
79  auto signal = findSignal(SignalType::signature::data());
80  static_cast<Signal<typename SignalType::signalType> *>(signal)
81  ->disconnectAll();
82  }
83 
85 
86 protected:
87  /// \brief Allow user to notify the destroy event earlier.
88  /// Due the C++ destructor calling order, the subclass is not "subclass"
89  /// anymore at the time when parent destructor is called. This protected
90  /// function allow user to notify the destruction of objects when they are
91  /// still the original type.
92  void destroy();
93 
94  template <typename SignalType, typename... Args>
95  auto emit(Args &&...args) {
96  return std::as_const(*this).emit<SignalType>(
97  std::forward<Args>(args)...);
98  }
99 
100  template <typename SignalType, typename... Args>
101  auto emit(Args &&...args) const {
102  auto signal = findSignal(SignalType::signature::data());
103  return (*static_cast<Signal<typename SignalType::signalType> *>(
104  signal))(std::forward<Args>(args)...);
105  }
106 
107  template <typename SignalType,
108  typename Combiner = LastValue<typename std::function<
109  typename SignalType::signalType>::result_type>>
110  void registerSignal() {
111  _registerSignal(
112  SignalType::signature::data(),
113  std::make_unique<
115  }
116 
117  template <typename SignalType>
118  void unregisterSignal() {
119  _unregisterSignal(SignalType::signature::data());
120  }
121 
122 private:
123  void _registerSignal(std::string name, std::unique_ptr<SignalBase> signal);
124  void _unregisterSignal(const std::string &name);
125  // FIXME: remove non-const variant when we can break ABI.
126  SignalBase *findSignal(const std::string &name);
127  SignalBase *findSignal(const std::string &name) const;
128 
129  std::unique_ptr<ConnectableObjectPrivate> d_ptr;
130  FCITX_DECLARE_PRIVATE(ConnectableObject);
131 };
132 
133 template <typename T, typename Combiner>
135  self->registerSignal<T, Combiner>();
136 }
137 
138 template <typename T, typename Combiner>
140  self->unregisterSignal<T>();
141 }
142 
143 /// \brief Short hand for destroyed signal.
145 } // namespace fcitx
146 
147 #endif // _FCITX_UTILS_CONNECTABLEOBJECT_H_
Base class for all object supports connection.
#define FCITX_DECLARE_SIGNAL(CLASS_NAME, NAME,...)
Declare signal by type.
Definition: action.cpp:17
Helper class to register class.
A connection instance.
Definition: signals.h:60
Class to represent a signal. May be used like a functor.
Definition: signals.h:126
A signal-slot implemention.
Combiner that return the last value.
Definition: signals.h:29
Static string based on template argument.