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 | QMetaType metaType() const; |
177 | |
178 | int methodOffset() const; |
179 | int enumeratorOffset() const; |
180 | int propertyOffset() const; |
181 | int classInfoOffset() const; |
182 | |
183 | int constructorCount() const; |
184 | int methodCount() const; |
185 | int enumeratorCount() const; |
186 | int propertyCount() const; |
187 | int classInfoCount() const; |
188 | |
189 | int indexOfConstructor(const char *constructor) const; |
190 | int indexOfMethod(const char *method) const; |
191 | int indexOfSignal(const char *signal) const; |
192 | int indexOfSlot(const char *slot) const; |
193 | int indexOfEnumerator(const char *name) const; |
194 | int indexOfProperty(const char *name) const; |
195 | int indexOfClassInfo(const char *name) const; |
196 | |
197 | QMetaMethod constructor(int index) const; |
198 | QMetaMethod method(int index) const; |
199 | QMetaEnum enumerator(int index) const; |
200 | QMetaProperty property(int index) const; |
201 | QMetaClassInfo classInfo(int index) const; |
202 | QMetaProperty userProperty() const; |
203 | |
204 | static bool checkConnectArgs(const char *signal, const char *method); |
205 | static bool checkConnectArgs(const QMetaMethod &signal, |
206 | const QMetaMethod &method); |
207 | static QByteArray normalizedSignature(const char *method); |
208 | static QByteArray normalizedType(const char *type); |
209 | |
210 | // internal index-based connect |
211 | static Connection connect(const QObject *sender, int signal_index, |
212 | const QObject *receiver, int method_index, |
213 | int type = 0, int *types = nullptr); |
214 | // internal index-based disconnect |
215 | static bool disconnect(const QObject *sender, int signal_index, |
216 | const QObject *receiver, int method_index); |
217 | static bool disconnectOne(const QObject *sender, int signal_index, |
218 | const QObject *receiver, int method_index); |
219 | // internal slot-name based connect |
220 | static void connectSlotsByName(QObject *o); |
221 | |
222 | // internal index-based signal activation |
223 | static void activate(QObject *sender, int signal_index, void **argv); |
224 | static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); |
225 | static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv); |
226 | |
227 | static bool invokeMethod(QObject *obj, const char *member, |
228 | Qt::ConnectionType, |
229 | QGenericReturnArgument ret, |
230 | QGenericArgument val0 = QGenericArgument(nullptr), |
231 | QGenericArgument val1 = QGenericArgument(), |
232 | QGenericArgument val2 = QGenericArgument(), |
233 | QGenericArgument val3 = QGenericArgument(), |
234 | QGenericArgument val4 = QGenericArgument(), |
235 | QGenericArgument val5 = QGenericArgument(), |
236 | QGenericArgument val6 = QGenericArgument(), |
237 | QGenericArgument val7 = QGenericArgument(), |
238 | QGenericArgument val8 = QGenericArgument(), |
239 | QGenericArgument val9 = QGenericArgument()); |
240 | |
241 | static inline bool invokeMethod(QObject *obj, const char *member, |
242 | QGenericReturnArgument ret, |
243 | QGenericArgument val0 = QGenericArgument(nullptr), |
244 | QGenericArgument val1 = QGenericArgument(), |
245 | QGenericArgument val2 = QGenericArgument(), |
246 | QGenericArgument val3 = QGenericArgument(), |
247 | QGenericArgument val4 = QGenericArgument(), |
248 | QGenericArgument val5 = QGenericArgument(), |
249 | QGenericArgument val6 = QGenericArgument(), |
250 | QGenericArgument val7 = QGenericArgument(), |
251 | QGenericArgument val8 = QGenericArgument(), |
252 | QGenericArgument val9 = QGenericArgument()) |
253 | { |
254 | return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3, |
255 | val4, val5, val6, val7, val8, val9); |
256 | } |
257 | |
258 | static inline bool invokeMethod(QObject *obj, const char *member, |
259 | Qt::ConnectionType type, |
260 | QGenericArgument val0 = QGenericArgument(nullptr), |
261 | QGenericArgument val1 = QGenericArgument(), |
262 | QGenericArgument val2 = QGenericArgument(), |
263 | QGenericArgument val3 = QGenericArgument(), |
264 | QGenericArgument val4 = QGenericArgument(), |
265 | QGenericArgument val5 = QGenericArgument(), |
266 | QGenericArgument val6 = QGenericArgument(), |
267 | QGenericArgument val7 = QGenericArgument(), |
268 | QGenericArgument val8 = QGenericArgument(), |
269 | QGenericArgument val9 = QGenericArgument()) |
270 | { |
271 | return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2, |
272 | val3, val4, val5, val6, val7, val8, val9); |
273 | } |
274 | |
275 | static inline bool invokeMethod(QObject *obj, const char *member, |
276 | QGenericArgument val0 = QGenericArgument(nullptr), |
277 | QGenericArgument val1 = QGenericArgument(), |
278 | QGenericArgument val2 = QGenericArgument(), |
279 | QGenericArgument val3 = QGenericArgument(), |
280 | QGenericArgument val4 = QGenericArgument(), |
281 | QGenericArgument val5 = QGenericArgument(), |
282 | QGenericArgument val6 = QGenericArgument(), |
283 | QGenericArgument val7 = QGenericArgument(), |
284 | QGenericArgument val8 = QGenericArgument(), |
285 | QGenericArgument val9 = QGenericArgument()) |
286 | { |
287 | return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0, |
288 | val1, val2, val3, val4, val5, val6, val7, val8, val9); |
289 | } |
290 | |
291 | #ifdef Q_CLANG_QDOC |
292 | template<typename Functor, typename FunctorReturnType> |
293 | static bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr); |
294 | template<typename Functor, typename FunctorReturnType> |
295 | static bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret); |
296 | #else |
297 | |
298 | // invokeMethod() for member function pointer |
299 | template <typename Func> |
300 | static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
301 | && !std::is_convertible<Func, const char*>::value |
302 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
303 | invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, |
304 | Func function, |
305 | Qt::ConnectionType type = Qt::AutoConnection, |
306 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) |
307 | { |
308 | return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), type, ret); |
309 | } |
310 | |
311 | template <typename Func> |
312 | static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
313 | && !std::is_convertible<Func, const char*>::value |
314 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
315 | invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object, |
316 | Func function, |
317 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) |
318 | { |
319 | return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), Qt::AutoConnection, ret); |
320 | } |
321 | |
322 | // invokeMethod() for function pointer (not member) |
323 | template <typename Func> |
324 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
325 | && !std::is_convertible<Func, const char*>::value |
326 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
327 | invokeMethod(QObject *context, Func function, |
328 | Qt::ConnectionType type = Qt::AutoConnection, |
329 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr) |
330 | { |
331 | return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), type, ret); |
332 | } |
333 | |
334 | template <typename Func> |
335 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
336 | && !std::is_convertible<Func, const char*>::value |
337 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type |
338 | invokeMethod(QObject *context, Func function, |
339 | typename QtPrivate::FunctionPointer<Func>::ReturnType *ret) |
340 | { |
341 | return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), Qt::AutoConnection, ret); |
342 | } |
343 | |
344 | // invokeMethod() for Functor |
345 | template <typename Func> |
346 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
347 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 |
348 | && !std::is_convertible<Func, const char*>::value, bool>::type |
349 | invokeMethod(QObject *context, Func function, |
350 | Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr) |
351 | { |
352 | return invokeMethodImpl(context, |
353 | new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), |
354 | type, |
355 | ret); |
356 | } |
357 | |
358 | template <typename Func> |
359 | static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction |
360 | && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1 |
361 | && !std::is_convertible<Func, const char*>::value, bool>::type |
362 | invokeMethod(QObject *context, Func function, decltype(function()) *ret) |
363 | { |
364 | return invokeMethodImpl(context, |
365 | new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)), |
366 | Qt::AutoConnection, |
367 | ret); |
368 | } |
369 | |
370 | #endif |
371 | |
372 | QObject *newInstance(QGenericArgument val0 = QGenericArgument(nullptr), |
373 | QGenericArgument val1 = QGenericArgument(), |
374 | QGenericArgument val2 = QGenericArgument(), |
375 | QGenericArgument val3 = QGenericArgument(), |
376 | QGenericArgument val4 = QGenericArgument(), |
377 | QGenericArgument val5 = QGenericArgument(), |
378 | QGenericArgument val6 = QGenericArgument(), |
379 | QGenericArgument val7 = QGenericArgument(), |
380 | QGenericArgument val8 = QGenericArgument(), |
381 | QGenericArgument val9 = QGenericArgument()) const; |
382 | |
383 | enum Call { |
384 | InvokeMetaMethod, |
385 | ReadProperty, |
386 | WriteProperty, |
387 | ResetProperty, |
388 | CreateInstance, |
389 | IndexOfMethod, |
390 | RegisterPropertyMetaType, |
391 | RegisterMethodArgumentMetaType, |
392 | BindableProperty |
393 | }; |
394 | |
395 | int static_metacall(Call, int, void **) const; |
396 | static int metacall(QObject *, Call, int, void **); |
397 | |
398 | template <const QMetaObject &MO> static constexpr const QMetaObject *staticMetaObject() |
399 | { |
400 | return &MO; |
401 | } |
402 | |
403 | struct SuperData { |
404 | const QMetaObject *direct; |
405 | SuperData() = default; |
406 | constexpr SuperData(std::nullptr_t) : direct(nullptr) {} |
407 | constexpr SuperData(const QMetaObject *mo) : direct(mo) {} |
408 | |
409 | constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); } |
410 | |
411 | #ifdef QT_NO_DATA_RELOCATION |
412 | using Getter = const QMetaObject *(*)(); |
413 | Getter indirect = nullptr; |
414 | constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {} |
415 | constexpr operator const QMetaObject *() const |
416 | { return indirect ? indirect() : direct; } |
417 | template <const QMetaObject &MO> static constexpr SuperData link() |
418 | { return SuperData(QMetaObject::staticMetaObject<MO>); } |
419 | #else |
420 | constexpr operator const QMetaObject *() const |
421 | { return direct; } |
422 | template <const QMetaObject &MO> static constexpr SuperData link() |
423 | { return SuperData(QMetaObject::staticMetaObject<MO>()); } |
424 | #endif |
425 | }; |
426 | |
427 | struct Data { // private data |
428 | SuperData superdata; |
429 | const uint *stringdata; |
430 | const uint *data; |
431 | typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); |
432 | StaticMetacallFunction static_metacall; |
433 | const SuperData *relatedMetaObjects; |
434 | const QtPrivate::QMetaTypeInterface *const *metaTypes; |
435 | void *; //reserved for future use |
436 | } d; |
437 | |
438 | private: |
439 | static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret); |
440 | friend class QTimer; |
441 | }; |
442 | |
443 | class Q_CORE_EXPORT QMetaObject::Connection { |
444 | void *d_ptr; //QObjectPrivate::Connection* |
445 | explicit Connection(void *data) : d_ptr(data) { } |
446 | friend class QObject; |
447 | friend class QObjectPrivate; |
448 | friend struct QMetaObject; |
449 | bool isConnected_helper() const; |
450 | public: |
451 | ~Connection(); |
452 | Connection(); |
453 | Connection(const Connection &other); |
454 | Connection &operator=(const Connection &other); |
455 | #ifdef Q_QDOC |
456 | operator bool() const; |
457 | #else |
458 | // still using the restricted bool trick here, in order to support |
459 | // code using copy-init (e.g. `bool ok = connect(...)`) |
460 | typedef void *Connection::*RestrictedBool; |
461 | operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; } |
462 | #endif |
463 | |
464 | Connection(Connection &&other) noexcept : d_ptr(qExchange(other.d_ptr, nullptr)) {} |
465 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection) |
466 | void swap(Connection &other) noexcept { qSwap(d_ptr, other.d_ptr); } |
467 | }; |
468 | |
469 | inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept |
470 | { |
471 | lhs.swap(rhs); |
472 | } |
473 | |
474 | inline const QMetaObject *QMetaObject::superClass() const |
475 | { return d.superdata; } |
476 | |
477 | namespace QtPrivate { |
478 | /* Trait that tells is a the Object has a Q_OBJECT macro */ |
479 | template <typename Object> struct HasQ_OBJECT_Macro { |
480 | template <typename T> |
481 | static char test(int (T::*)(QMetaObject::Call, int, void **)); |
482 | static int test(int (Object::*)(QMetaObject::Call, int, void **)); |
483 | enum { Value = sizeof(test(&Object::qt_metacall)) == sizeof(int) }; |
484 | }; |
485 | } |
486 | |
487 | QT_END_NAMESPACE |
488 | |
489 | #endif // QOBJECTDEFS_H |
490 | |