1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#ifndef EVENT_H
6#define EVENT_H
7
8#include "framework/framework_global.h"
9
10#include <QString>
11#include <QVector>
12#include <QVariant>
13#include <QSharedData>
14
15DPF_BEGIN_NAMESPACE
16
17class EventPrivate;
18
19/**
20 * @brief The Event class
21 * 事件数据源,只能当做类使用不可继承
22 * 禁止被继承
23 */
24class Event final
25{
26 EventPrivate *d;
27 friend Q_CORE_EXPORT QDebug operator <<(QDebug, const Event &);
28
29public:
30 Event();
31 explicit Event(const QString &topic);
32 explicit Event(const Event& event);
33 ~Event();
34 Event &operator =(const Event &);
35
36 void setTopic(const QString &topic);
37 QString topic() const;
38
39 void setData(const QVariant &data);
40 QVariant data() const;
41
42 void setProperty(const QString& key, const QVariant value);
43 QVariant property(const QString &key) const;
44};
45
46QT_BEGIN_NAMESPACE
47#ifndef QT_NO_DEBUG_STREAM
48Q_CORE_EXPORT QDebug operator <<(QDebug, const DPF_NAMESPACE::Event &);
49#endif //QT_NO_DEBUG_STREAM
50QT_END_NAMESPACE
51
52struct EventInterface : std::function<void(const QVector<QVariant> &)>
53{
54 QString name;
55 QVector<QString> pKeys;
56 typedef QVariant Arg;
57 typedef const QVariant cArg;
58 typedef QVector<QVariant> Args;
59 EventInterface() = delete;
60
61 EventInterface(const QString &name, const QVector<QString> &keys,
62 const std::function<void(const QVector<QVariant>&)> &func)
63 : std::function<void (const QVector<QVariant> &)> (func), name(name), pKeys(keys) {}
64
65 void operator()(const Args &as) const {
66 return std::function<void(const QVector<QVariant> &)>::operator()(as);
67 }
68
69 void operator()() const { operator()(Args{}); }
70
71 template<class T0>
72 void operator()(const T0 &v0) const { operator()(Args{ Arg::fromValue<T0>(v0) }); }
73
74 template<class T0, class T1>
75 void operator()(const T0 &v0, const T1 &v1) const {
76 operator()(Args{ Arg::fromValue<T0>(v0), Arg::fromValue<T1>(v1) });
77 }
78
79 template<class T0, class T1, class T2>
80 void operator()(const T0 &v0, const T1 &v1, const T2 &v2) const {
81 operator()(Args{
82 Arg::fromValue<T0>(v0), Arg::fromValue<T1>(v1),
83 Arg::fromValue<T2>(v2)
84 });
85 }
86
87 template<class T0, class T1, class T2, class T3>
88 void operator()(const T0 &v0, const T1 &v1, const T2 &v2, const T3 &v3) const {
89 operator()(Args{
90 Arg::fromValue<T0>(v0), Arg::fromValue<T1>(v1),
91 Arg::fromValue<T2>(v2), Arg::fromValue<T3>(v3)
92 });
93 }
94
95 template<class T0, class T1, class T2, class T3, class T4>
96 void operator()(const T0 &v0, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) const {
97 operator()(Args{
98 Arg::fromValue<T0>(v0), Arg::fromValue<T1>(v1),
99 Arg::fromValue<T2>(v2), Arg::fromValue<T3>(v3),
100 Arg::fromValue<T4>(v4)
101 });
102 }
103
104 template<class T0, class T1, class T2, class T3, class T4, class T5>
105 void operator()(const T0 &v0, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4,
106 const T5 &v5) const {
107 operator()(Args{
108 Arg::fromValue<T0>(v0), Arg::fromValue<T1>(v1),
109 Arg::fromValue<T2>(v2), Arg::fromValue<T3>(v3),
110 Arg::fromValue<T4>(v4), Arg::fromValue<T5>(v5)
111 });
112 }
113
114 template<class T0, class T1, class T2, class T3, class T4, class T5, class T6>
115 void operator()(const T0 &v0, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4,
116 const T5 &v5, const T6 &v6) const {
117 operator()(Args{
118 Arg::fromValue<T0>(v0), Arg::fromValue<T1>(v1),
119 Arg::fromValue<T2>(v2), Arg::fromValue<T3>(v3),
120 Arg::fromValue<T4>(v4), Arg::fromValue<T5>(v5),
121 Arg::fromValue<T6>(v6)
122 });
123 }
124
125 template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
126 void operator()(const T0 &v0, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4,
127 const T5 &v5, const T6 &v6, const T7 &v7) const {
128 operator()(Args{
129 Arg::fromValue<T0>(v0), Arg::fromValue<T1>(v1),
130 Arg::fromValue<T2>(v2), Arg::fromValue<T3>(v3),
131 Arg::fromValue<T4>(v4), Arg::fromValue<T5>(v5),
132 Arg::fromValue<T6>(v6), Arg::fromValue<T7>(v7)
133 });
134 }
135
136 template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
137 void operator()(const T0 &v0, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4,
138 const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8) const{
139 operator()(Args{
140 Arg::fromValue<T0>(v0), Arg::fromValue<T1>(v1),
141 Arg::fromValue<T2>(v2), Arg::fromValue<T3>(v3),
142 Arg::fromValue<T4>(v4), Arg::fromValue<T5>(v5),
143 Arg::fromValue<T6>(v6), Arg::fromValue<T7>(v7),
144 Arg::fromValue<T8>(v8),
145 });
146 }
147
148 template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
149 void operator()(const T0 &v0, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4,
150 const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8, const T9 &v9) const {
151 operator()(Args{
152 Arg::fromValue<T0>(v0), Arg::fromValue<T1>(v1),
153 Arg::fromValue<T2>(v2), Arg::fromValue<T3>(v3),
154 Arg::fromValue<T4>(v4), Arg::fromValue<T5>(v5),
155 Arg::fromValue<T6>(v6), Arg::fromValue<T7>(v7),
156 Arg::fromValue<T8>(v8), Arg::fromValue<T9>(v9)
157 });
158 }
159};
160
161/**
162 * @brief The OPI_OBJECT macro
163 * Declare and define topic scope
164 *
165 * @brief The OPI_INTERFACE macro
166 * Declare and define call event interface
167 *
168 * @details
169 * Usage:
170 * Call mode:
171 * The interface implemented by the functor will be encapsulated for the time sending interface,
172 * for send event package:
173 * Event {
174 * topic : "collaborators"
175 * data : "openRepos"
176 * property { "workspace": "/usr/home/test" }
177 * };
178 * Usage:
179 *
180 * First: The receiver of eventHandler needs to be implemented in the plugin,
181 * abstract interface file in eventhandler.h/.cpp
182 *
183 * Second: Decl from send event interface to any file. (If you are cross plug-in event call,
184 * I recommend you define it in the header file that can be referenced by multiple plug-ins.)
185 * @code
186 * OPI_OBJECT(collaborators,
187 * OPI_INTERFACE(openRepos, "workspace")
188 * )
189 * @endcode
190 *
191 * Third: call event:
192 * @code
193 * collaborators.openRepos("/usr/home/test");
194 * @endcode
195 *
196 */
197#define OPI_ASKEEP(pKeys, pVals) if (pKeys.size() != pVals.size()) { qCritical() << "Key value pair length mismatch"; abort(); }
198#define OPI_OBJECT(t, logics) inline const struct { const QString topic{#t} ; logics }t;
199#define OPI_INTERFACE(d, ...) const dpf::EventInterface d { #d, {__VA_ARGS__} , [=](const QVector<QVariant> &args) -> void {\
200 OPI_ASKEEP(d.pKeys, args);\
201 dpf::Event event(topic); event.setData(#d);\
202 for ( int idx = 0; idx < d.pKeys.size(); idx ++) { event.setProperty(d.pKeys[idx], args[idx]); }\
203 dpf::EventCallProxy::instance().pubEvent(event);\
204 }};
205
206DPF_END_NAMESPACE
207
208#endif // EVENT_H
209