1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2020 The Qt Company Ltd. |
4 | ** Copyright (C) 2019 Intel Corporation. |
5 | ** Contact: https://www.qt.io/licensing/ |
6 | ** |
7 | ** This file is part of the QtCore module of the Qt Toolkit. |
8 | ** |
9 | ** $QT_BEGIN_LICENSE:LGPL$ |
10 | ** Commercial License Usage |
11 | ** Licensees holding valid commercial Qt licenses may use this file in |
12 | ** accordance with the commercial license agreement provided with the |
13 | ** Software or, alternatively, in accordance with the terms contained in |
14 | ** a written agreement between you and The Qt Company. For licensing terms |
15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
16 | ** information use the contact form at https://www.qt.io/contact-us. |
17 | ** |
18 | ** GNU Lesser General Public License Usage |
19 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
20 | ** General Public License version 3 as published by the Free Software |
21 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
22 | ** packaging of this file. Please review the following information to |
23 | ** ensure the GNU Lesser General Public License version 3 requirements |
24 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
25 | ** |
26 | ** GNU General Public License Usage |
27 | ** Alternatively, this file may be used under the terms of the GNU |
28 | ** General Public License version 2.0 or (at your option) the GNU General |
29 | ** Public license version 3 or any later version approved by the KDE Free |
30 | ** Qt Foundation. The licenses are as published by the Free Software |
31 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
32 | ** included in the packaging of this file. Please review the following |
33 | ** information to ensure the GNU General Public License requirements will |
34 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
35 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
36 | ** |
37 | ** $QT_END_LICENSE$ |
38 | ** |
39 | ****************************************************************************/ |
40 | |
41 | #ifndef QOBJECTDEFS_H |
42 | #define QOBJECTDEFS_H |
43 | |
44 | #if defined(__OBJC__) && !defined(__cplusplus) |
45 | # warning "File built in Objective-C mode (.m), but using Qt requires Objective-C++ (.mm)" |
46 | #endif |
47 | |
48 | #include <QtCore/qnamespace.h> |
49 | #include <QtCore/qobjectdefs_impl.h> |
50 | #include <QtCore/qtmetamacros.h> |
51 | |
52 | QT_BEGIN_NAMESPACE |
53 | |
54 | class QByteArray; |
55 | struct QArrayData; |
56 | |
57 | class QString; |
58 | |
59 | #ifndef QT_NO_META_MACROS |
60 | // macro for onaming members |
61 | #ifdef METHOD |
62 | #undef METHOD |
63 | #endif |
64 | #ifdef SLOT |
65 | #undef SLOT |
66 | #endif |
67 | #ifdef SIGNAL |
68 | #undef SIGNAL |
69 | #endif |
70 | #endif // QT_NO_META_MACROS |
71 | |
72 | Q_CORE_EXPORT const char *qFlagLocation(const char *method); |
73 | |
74 | #ifndef QT_NO_META_MACROS |
75 | #ifndef QT_NO_DEBUG |
76 | # define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__) |
77 | # ifndef QT_NO_KEYWORDS |
78 | # define METHOD(a) qFlagLocation("0"#a QLOCATION) |
79 | # endif |
80 | # define SLOT(a) qFlagLocation("1"#a QLOCATION) |
81 | # define SIGNAL(a) qFlagLocation("2"#a QLOCATION) |
82 | #else |
83 | # ifndef QT_NO_KEYWORDS |
84 | # define METHOD(a) "0"#a |
85 | # endif |
86 | # define SLOT(a) "1"#a |
87 | # define SIGNAL(a) "2"#a |
88 | #endif |
89 | |
90 | #define QMETHOD_CODE 0 // member type codes |
91 | #define QSLOT_CODE 1 |
92 | #define QSIGNAL_CODE 2 |
93 | #endif // QT_NO_META_MACROS |
94 | |
95 | #define Q_ARG(type, data) QArgument<type >(#type, data) |
96 | #define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data) |
97 | |
98 | class QObject; |
99 | class QMetaMethod; |
100 | class QMetaEnum; |
101 | class QMetaProperty; |
102 | class QMetaClassInfo; |
103 | |
104 | namespace QtPrivate { |
105 | class QMetaTypeInterface; |
106 | } |
107 | |
108 | struct QMethodRawArguments |
109 | { |
110 | void **arguments; |
111 | }; |
112 | |
113 | class Q_CORE_EXPORT QGenericArgument |
114 | { |
115 | public: |
116 | inline QGenericArgument(const char *aName = nullptr, const void *aData = nullptr) |
117 | : _data(aData), _name(aName) {} |
118 | inline void *data() const { return const_cast<void *>(_data); } |
119 | inline const char *name() const { return _name; } |
120 | |
121 | private: |
122 | const void *_data; |
123 | const char *_name; |
124 | }; |
125 | |
126 | class Q_CORE_EXPORT QGenericReturnArgument: public QGenericArgument |
127 | { |
128 | public: |
129 | inline QGenericReturnArgument(const char *aName = nullptr, void *aData = nullptr) |
130 | : QGenericArgument(aName, aData) |
131 | {} |
132 | }; |
133 | |
134 | template <class T> |
135 | class QArgument: public QGenericArgument |
136 | { |
137 | public: |
138 | inline QArgument(const char *aName, const T &aData) |
139 | : QGenericArgument(aName, static_cast<const void *>(&aData)) |
140 | {} |
141 | }; |
142 | template <class T> |
143 | class QArgument<T &>: public QGenericArgument |
144 | { |
145 | public: |
146 | inline QArgument(const char *aName, T &aData) |
147 | : QGenericArgument(aName, static_cast<const void *>(&aData)) |
148 | {} |
149 | }; |
150 | |
151 | |
152 | template <typename T> |
153 | class QReturnArgument: public QGenericReturnArgument |
154 | { |
155 | public: |
156 | inline QReturnArgument(const char *aName, T &aData) |
157 | : QGenericReturnArgument(aName, static_cast<void *>(&aData)) |
158 | {} |
159 | }; |
160 | |
161 | struct Q_CORE_EXPORT QMetaObject |
162 | { |
163 | class Connection; |
164 | const char *className() const; |
165 | const QMetaObject *superClass() const; |
166 | |
167 | bool inherits(const QMetaObject *metaObject) const noexcept; |
168 | QObject *cast(QObject *obj) const |
169 | { return const_cast<QObject *>(cast(const_cast<const QObject *>(obj))); } |
170 | const QObject *cast(const QObject *obj) const; |
171 | |
172 | #if !defined(QT_NO_TRANSLATION) || defined(Q_CLANG_QDOC) |
173 | QString tr(const char *s, const char *c, int n = -1) const; |
174 | #endif // QT_NO_TRANSLATION |
175 | |
176 | int methodOffset() const; |
177 | int enumeratorOffset() const; |
178 | int propertyOffset() const; |
179 | int classInfoOffset() const; |
180 | |
181 | int constructorCount() const; |
182 | int methodCount() const; |
183 | int enumeratorCount() const; |
184 | int propertyCount() const; |
185 | int classInfoCount() const; |
186 | |
187 | int indexOfConstructor(const char *constructor) const; |
188 | int indexOfMethod(const char *method) const; |
189 | int indexOfSignal(const char *signal) const; |
190 | int indexOfSlot(const char *slot) const; |
191 | int indexOfEnumerator(const char *name) const; |
192 | int indexOfProperty(const char *name) const; |
193 | int indexOfClassInfo(const char *name) const; |
194 | |
195 | QMetaMethod constructor(int index) const; |
196 | QMetaMethod method(int index) const; |
197 | QMetaEnum enumerator(int index) const; |
198 | QMetaProperty property(int index) const; |
199 | QMetaClassInfo classInfo(int index) const; |
200 | QMetaProperty userProperty() const; |
201 | |
202 | static bool checkConnectArgs(const char *signal, const char *method); |
203 | static bool checkConnectArgs(const QMetaMethod &signal, |
204 | const QMetaMethod &method); |
205 | static QByteArray normalizedSignature(const char *method); |
206 | static QByteArray normalizedType(const char *type); |
207 | |
208 | // internal index-based connect |
209 | static Connection connect(const QObject *sender, int signal_index, |
210 | const QObject *receiver, int method_index, |
211 | int type = 0, int *types = nullptr); |
212 | // internal index-based disconnect |
213 | static bool disconnect(const QObject *sender, int signal_index, |
214 | const QObject *receiver, int method_index); |
215 | static bool disconnectOne(const QObject *sender, int signal_index, |
216 | const QObject *receiver, int method_index); |
217 | // internal slot-name based connect |
218 | static void connectSlotsByName(QObject *o); |
219 | |
220 | // internal index-based signal activation |
221 | static void activate(QObject *sender, int signal_index, void **argv); |
222 | static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); |
223 | static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv); |
224 | |
225 | static bool invokeMethod(QObject *obj, const char *member, |
226 | Qt::ConnectionType, |
227 | QGenericReturnArgument ret, |
228 | QGenericArgument val0 = QGenericArgument(nullptr), |
229 | QGenericArgument val1 = QGenericArgument(), |
230 | QGenericArgument val2 = QGenericArgument(), |
231 | QGenericArgument val3 = QGenericArgument(), |
232 | QGenericArgument val4 = QGenericArgument(), |
233 | QGenericArgument val5 = QGenericArgument(), |
234 | QGenericArgument val6 = QGenericArgument(), |
235 | QGenericArgument val7 = QGenericArgument(), |
236 | QGenericArgument val8 = QGenericArgument(), |
237 | QGenericArgument val9 = QGenericArgument()); |
238 | |
239 | static inline bool invokeMethod(QObject *obj, const char *member, |
240 | QGenericReturnArgument ret, |
241 | QGenericArgument val0 = QGenericArgument(nullptr), |
242 | QGenericArgument val1 = QGenericArgument(), |
243 | QGenericArgument val2 = QGenericArgument(), |
244 | QGenericArgument val3 = QGenericArgument(), |
245 | QGenericArgument val4 = QGenericArgument(), |
246 | QGenericArgument val5 = QGenericArgument(), |
247 | QGenericArgument val6 = QGenericArgument(), |
248 | QGenericArgument val7 = QGenericArgument(), |
249 | QGenericArgument val8 = QGenericArgument(), |
250 | QGenericArgument val9 = QGenericArgument()) |
251 | { |
252 | return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3, |
253 | val4, val5, val6, val7, val8, val9); |
254 | } |
255 | |
256 | static inline bool invokeMethod(QObject *obj, const char *member, |
257 | Qt::ConnectionType type, |
258 | QGenericArgument val0 = QGenericArgument(nullptr), |
259 | QGenericArgument val1 = QGenericArgument(), |
260 | QGenericArgument val2 = QGenericArgument(), |
261 | QGenericArgument val3 = QGenericArgument(), |
262 | QGenericArgument val4 = QGenericArgument(), |
263 | QGenericArgument val5 = QGenericArgument(), |
264 | QGenericArgument val6 = QGenericArgument(), |
265 | QGenericArgument val7 = QGenericArgument(), |
266 | QGenericArgument val8 = QGenericArgument(), |
267 | QGenericArgument val9 = QGenericArgument()) |
268 | { |
269 | return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2, |
270 | val3, val4, val5, val6, val7, val8, val9); |
271 | } |
272 | |
273 | static inline bool invokeMethod(QObject *obj, const char *member, |
274 | QGenericArgument val0 = QGenericArgument(nullptr), |
275 | QGenericArgument val1 = QGenericArgument(), |
276 | QGenericArgument val2 = QGenericArgument(), |
277 | QGenericArgument val3 = QGenericArgument(), |
278 | QGenericArgument val4 = QGenericArgument(), |
279 | QGenericArgument val5 = QGenericArgument(), |
280 | QGenericArgument val6 = QGenericArgument(), |
281 | QGenericArgument val7 = QGenericArgument(), |
282 | QGenericArgument val8 = QGenericArgument(), |
283 | QGenericArgument val9 = QGenericArgument()) |
284 | { |
285 | return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0, |
286 | val1, val2, val3, val4, val5, val6, val7, val8, val9); |
287 | } |
288 | |
289 | #ifdef Q_CLANG_QDOC |
290 | template<typename Functor, typename FunctorReturnType> |
291 | static bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr); |
292 | template<typename Functor, typename FunctorReturnType> |
293 | static bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret); |
294 | #else |
295 | |
296 | // invokeMethod() for member function pointer |
297 | template <typename Func> |
298 | static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
299 | && !std::is_convertible<Func, const char*>::value |
300 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
301 | invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, |
302 | Func function, |
303 | Qt::ConnectionType type = Qt::AutoConnection, |
304 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) |
305 | { |
306 | return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), type, ret); |
307 | } |
308 | |
309 | template <typename Func> |
310 | static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
311 | && !std::is_convertible<Func, const char*>::value |
312 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
313 | invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, |
314 | Func function, |
315 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) |
316 | { |
317 | return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), Qt::AutoConnection, ret); |
318 | } |
319 | |
320 | // invokeMethod() for function pointer (not member) |
321 | template <typename Func> |
322 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
323 | && !std::is_convertible<Func, const char*>::value |
324 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
325 | invokeMethod(QObject *context, Func function, |
326 | Qt::ConnectionType type = Qt::AutoConnection, |
327 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) |
328 | { |
329 | return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), type, ret); |
330 | } |
331 | |
332 | template <typename Func> |
333 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
334 | && !std::is_convertible<Func, const char*>::value |
335 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
336 | invokeMethod(QObject *context, Func function, |
337 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) |
338 | { |
339 | return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), Qt::AutoConnection, ret); |
340 | } |
341 | |
342 | // invokeMethod() for Functor |
343 | template <typename Func> |
344 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
345 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 |
346 | && !std::is_convertible<Func, const char*>::value, bool>::type |
347 | invokeMethod(QObject *context, Func function, |
348 | Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr) |
349 | { |
350 | return invokeMethodImpl(context, |
351 | new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), |
352 | type, |
353 | ret); |
354 | } |
355 | |
356 | template <typename Func> |
357 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
358 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 |
359 | && !std::is_convertible<Func, const char*>::value, bool>::type |
360 | invokeMethod(QObject *context, Func function, decltype(function()) *ret) |
361 | { |
362 | return invokeMethodImpl(context, |
363 | new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), |
364 | Qt::AutoConnection, |
365 | ret); |
366 | } |
367 | |
368 | #endif |
369 | |
370 | QObject *newInstance(QGenericArgument val0 = QGenericArgument(nullptr), |
371 | QGenericArgument val1 = QGenericArgument(), |
372 | QGenericArgument val2 = QGenericArgument(), |
373 | QGenericArgument val3 = QGenericArgument(), |
374 | QGenericArgument val4 = QGenericArgument(), |
375 | QGenericArgument val5 = QGenericArgument(), |
376 | QGenericArgument val6 = QGenericArgument(), |
377 | QGenericArgument val7 = QGenericArgument(), |
378 | QGenericArgument val8 = QGenericArgument(), |
379 | QGenericArgument val9 = QGenericArgument()) const; |
380 | |
381 | enum Call { |
382 | InvokeMetaMethod, |
383 | ReadProperty, |
384 | WriteProperty, |
385 | ResetProperty, |
386 | CreateInstance, |
387 | IndexOfMethod, |
388 | RegisterPropertyMetaType, |
389 | RegisterMethodArgumentMetaType, |
390 | BindableProperty |
391 | }; |
392 | |
393 | int static_metacall(Call, int, void **) const; |
394 | static int metacall(QObject *, Call, int, void **); |
395 | |
396 | template <const QMetaObject &MO> static constexpr const QMetaObject *staticMetaObject() |
397 | { |
398 | return &MO; |
399 | } |
400 | |
401 | struct SuperData { |
402 | const QMetaObject *direct; |
403 | SuperData() = default; |
404 | constexpr SuperData(std::nullptr_t) : direct(nullptr) {} |
405 | constexpr SuperData(const QMetaObject *mo) : direct(mo) {} |
406 | |
407 | constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); } |
408 | |
409 | #ifdef QT_NO_DATA_RELOCATION |
410 | using Getter = const QMetaObject *(*)(); |
411 | Getter indirect = nullptr; |
412 | constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {} |
413 | constexpr operator const QMetaObject *() const |
414 | { return indirect ? indirect() : direct; } |
415 | template <const QMetaObject &MO> static constexpr SuperData link() |
416 | { return SuperData(QMetaObject::staticMetaObject<MO>); } |
417 | #else |
418 | constexpr operator const QMetaObject *() const |
419 | { return direct; } |
420 | template <const QMetaObject &MO> static constexpr SuperData link() |
421 | { return SuperData(QMetaObject::staticMetaObject<MO>()); } |
422 | #endif |
423 | }; |
424 | |
425 | struct Data { // private data |
426 | SuperData superdata; |
427 | const uint *stringdata; |
428 | const uint *data; |
429 | typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); |
430 | StaticMetacallFunction static_metacall; |
431 | const SuperData *relatedMetaObjects; |
432 | const QtPrivate::QMetaTypeInterface *const *metaTypes; |
433 | void *; //reserved for future use |
434 | } d; |
435 | |
436 | private: |
437 | static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret); |
438 | friend class QTimer; |
439 | }; |
440 | |
441 | class Q_CORE_EXPORT QMetaObject::Connection { |
442 | void *d_ptr; //QObjectPrivate::Connection* |
443 | explicit Connection(void *data) : d_ptr(data) { } |
444 | friend class QObject; |
445 | friend class QObjectPrivate; |
446 | friend struct QMetaObject; |
447 | bool isConnected_helper() const; |
448 | public: |
449 | ~Connection(); |
450 | Connection(); |
451 | Connection(const Connection &other); |
452 | Connection &operator=(const Connection &other); |
453 | #ifdef Q_QDOC |
454 | operator bool() const; |
455 | #else |
456 | // still using the restricted bool trick here, in order to support |
457 | // code using copy-init (e.g. `bool ok = connect(...)`) |
458 | typedef void *Connection::*RestrictedBool; |
459 | operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; } |
460 | #endif |
461 | |
462 | Connection(Connection &&o) noexcept : d_ptr(qExchange(o.d_ptr, nullptr)) {} |
463 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection) |
464 | void swap(Connection &o) noexcept { qSwap(d_ptr, o.d_ptr); } |
465 | }; |
466 | |
467 | inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept |
468 | { |
469 | lhs.swap(rhs); |
470 | } |
471 | |
472 | inline const QMetaObject *QMetaObject::superClass() const |
473 | { return d.superdata; } |
474 | |
475 | namespace QtPrivate { |
476 | /* Trait that tells is a the Object has a Q_OBJECT macro */ |
477 | template <typename Object> struct HasQ_OBJECT_Macro { |
478 | template <typename T> |
479 | static char test(int (T::*)(QMetaObject::Call, int, void **)); |
480 | static int test(int (Object::*)(QMetaObject::Call, int, void **)); |
481 | enum { Value = sizeof(test(&Object::qt_metacall)) == sizeof(int) }; |
482 | }; |
483 | } |
484 | |
485 | QT_END_NAMESPACE |
486 | |
487 | #endif // QOBJECTDEFS_H |
488 | |