1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // Copyright (C) 2019 Intel Corporation. |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QOBJECTDEFS_H |
6 | #define QOBJECTDEFS_H |
7 | |
8 | #if defined(__OBJC__) && !defined(__cplusplus) |
9 | # warning "File built in Objective-C mode (.m), but using Qt requires Objective-C++ (.mm)" |
10 | #endif |
11 | |
12 | #include <QtCore/qnamespace.h> |
13 | #include <QtCore/qobjectdefs_impl.h> |
14 | #include <QtCore/qtcoreexports.h> |
15 | #include <QtCore/qtmetamacros.h> |
16 | |
17 | QT_BEGIN_NAMESPACE |
18 | |
19 | class QByteArray; |
20 | struct QArrayData; |
21 | |
22 | class QString; |
23 | |
24 | #ifndef QT_NO_META_MACROS |
25 | // macro for onaming members |
26 | #ifdef METHOD |
27 | #undef METHOD |
28 | #endif |
29 | #ifdef SLOT |
30 | #undef SLOT |
31 | #endif |
32 | #ifdef SIGNAL |
33 | #undef SIGNAL |
34 | #endif |
35 | #endif // QT_NO_META_MACROS |
36 | |
37 | Q_CORE_EXPORT const char *qFlagLocation(const char *method); |
38 | |
39 | #ifndef QT_NO_META_MACROS |
40 | # define QMETHOD_CODE 0 // member type codes |
41 | # define QSLOT_CODE 1 |
42 | # define QSIGNAL_CODE 2 |
43 | # define QT_PREFIX_CODE(code, a) QT_STRINGIFY(code) #a |
44 | # define QT_STRINGIFY_METHOD(a) QT_PREFIX_CODE(QMETHOD_CODE, a) |
45 | # define QT_STRINGIFY_SLOT(a) QT_PREFIX_CODE(QSLOT_CODE, a) |
46 | # define QT_STRINGIFY_SIGNAL(a) QT_PREFIX_CODE(QSIGNAL_CODE, a) |
47 | # ifndef QT_NO_DEBUG |
48 | # define QLOCATION "\0" __FILE__ ":" QT_STRINGIFY(__LINE__) |
49 | # ifndef QT_NO_KEYWORDS |
50 | # define METHOD(a) qFlagLocation(QT_STRINGIFY_METHOD(a) QLOCATION) |
51 | # endif |
52 | # define SLOT(a) qFlagLocation(QT_STRINGIFY_SLOT(a) QLOCATION) |
53 | # define SIGNAL(a) qFlagLocation(QT_STRINGIFY_SIGNAL(a) QLOCATION) |
54 | # else |
55 | # ifndef QT_NO_KEYWORDS |
56 | # define METHOD(a) QT_STRINGIFY_METHOD(a) |
57 | # endif |
58 | # define SLOT(a) QT_STRINGIFY_SLOT(a) |
59 | # define SIGNAL(a) QT_STRINGIFY_SIGNAL(a) |
60 | # endif |
61 | #endif // QT_NO_META_MACROS |
62 | |
63 | #define Q_ARG(Type, data) QtPrivate::Invoke::argument<Type>(QT_STRINGIFY(Type), data) |
64 | #define Q_RETURN_ARG(Type, data) QtPrivate::Invoke::returnArgument<Type>(QT_STRINGIFY(Type), data) |
65 | |
66 | class QObject; |
67 | class QMetaMethod; |
68 | class QMetaEnum; |
69 | class QMetaProperty; |
70 | class QMetaClassInfo; |
71 | |
72 | namespace QtPrivate { |
73 | class QMetaTypeInterface; |
74 | template<typename T> constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType(); |
75 | } |
76 | |
77 | struct QMethodRawArguments |
78 | { |
79 | void **arguments; |
80 | }; |
81 | |
82 | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) |
83 | class Q_CORE_EXPORT QGenericArgument |
84 | { |
85 | public: |
86 | inline QGenericArgument(const char *aName = nullptr, const void *aData = nullptr) |
87 | : _data(aData), _name(aName) {} |
88 | inline void *data() const { return const_cast<void *>(_data); } |
89 | inline const char *name() const { return _name; } |
90 | |
91 | private: |
92 | const void *_data; |
93 | const char *_name; |
94 | }; |
95 | |
96 | class Q_CORE_EXPORT QGenericReturnArgument: public QGenericArgument |
97 | { |
98 | public: |
99 | inline QGenericReturnArgument(const char *aName = nullptr, void *aData = nullptr) |
100 | : QGenericArgument(aName, aData) |
101 | {} |
102 | }; |
103 | |
104 | template <class T> |
105 | class QArgument: public QGenericArgument |
106 | { |
107 | public: |
108 | inline QArgument(const char *aName, const T &aData) |
109 | : QGenericArgument(aName, static_cast<const void *>(&aData)) |
110 | {} |
111 | }; |
112 | template <class T> |
113 | class QArgument<T &>: public QGenericArgument |
114 | { |
115 | public: |
116 | inline QArgument(const char *aName, T &aData) |
117 | : QGenericArgument(aName, static_cast<const void *>(&aData)) |
118 | {} |
119 | }; |
120 | |
121 | |
122 | template <typename T> |
123 | class QReturnArgument: public QGenericReturnArgument |
124 | { |
125 | public: |
126 | inline QReturnArgument(const char *aName, T &aData) |
127 | : QGenericReturnArgument(aName, static_cast<void *>(&aData)) |
128 | {} |
129 | }; |
130 | #endif |
131 | |
132 | struct QMetaMethodArgument |
133 | { |
134 | const QtPrivate::QMetaTypeInterface *metaType; |
135 | const char *name; |
136 | const void *data; |
137 | }; |
138 | |
139 | struct QMetaMethodReturnArgument |
140 | { |
141 | const QtPrivate::QMetaTypeInterface *metaType; |
142 | const char *name; |
143 | void *data; |
144 | }; |
145 | |
146 | template <typename T> |
147 | struct QTemplatedMetaMethodReturnArgument : QMetaMethodReturnArgument |
148 | { |
149 | using Type = T; |
150 | }; |
151 | |
152 | namespace QtPrivate { |
153 | namespace Invoke { |
154 | #if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) |
155 | template <typename... Args> |
156 | using AreOldStyleArgs = std::disjunction<std::is_base_of<QGenericArgument, Args>...>; |
157 | |
158 | template <typename T, typename... Args> using IfNotOldStyleArgs = |
159 | std::enable_if_t<!AreOldStyleArgs<Args...>::value, T>; |
160 | #else |
161 | template <typename T, typename... Args> using IfNotOldStyleArgs = T; |
162 | #endif |
163 | |
164 | template <typename T> inline QMetaMethodArgument argument(const char *name, const T &t) |
165 | { |
166 | if constexpr ((std::is_lvalue_reference_v<T> && std::is_const_v<std::remove_reference_t<T>>) || |
167 | !std::is_reference_v<T>) { |
168 | return { qMetaTypeInterfaceForType<T>(), name, std::addressof(t) }; |
169 | } else { |
170 | return { nullptr, name, std::addressof(t) }; |
171 | } |
172 | } |
173 | |
174 | template <typename T> |
175 | inline QTemplatedMetaMethodReturnArgument<T> returnArgument(const char *name, T &t) |
176 | { |
177 | return { qMetaTypeInterfaceForType<T>(), name, std::addressof(t) }; |
178 | } |
179 | |
180 | template <typename T> inline const char *typenameHelper(const T &) |
181 | { |
182 | return nullptr; |
183 | } |
184 | template <typename T> inline const void *dataHelper(const T &t) |
185 | { |
186 | return std::addressof(t); |
187 | } |
188 | template <typename T> inline const QMetaTypeInterface *metaTypeHelper(const T &) |
189 | { |
190 | return qMetaTypeInterfaceForType<T>(); |
191 | } |
192 | |
193 | inline const char *typenameHelper(QMetaMethodArgument a) |
194 | { return a.name; } |
195 | inline const void *dataHelper(QMetaMethodArgument a) |
196 | { return a.data; } |
197 | inline const QMetaTypeInterface *metaTypeHelper(QMetaMethodArgument a) |
198 | { return a.metaType; } |
199 | |
200 | inline const char *typenameHelper(const char *) = delete; |
201 | template <typename T> inline const void *dataHelper(const char *) = delete; |
202 | inline const QMetaTypeInterface *metaTypeHelper(const char *) = delete; |
203 | inline const char *typenameHelper(const char16_t *) = delete; |
204 | template <typename T> inline const void *dataHelper(const char16_t *) = delete; |
205 | inline const QMetaTypeInterface *metaTypeHelper(const char16_t *) = delete; |
206 | |
207 | } // namespace QtPrivate::Invoke |
208 | |
209 | template <typename... Args> inline auto invokeMethodHelper(QMetaMethodReturnArgument r, const Args &... arguments) |
210 | { |
211 | std::array params = { const_cast<const void *>(r.data), Invoke::dataHelper(arguments)... }; |
212 | std::array names = { r.name, Invoke::typenameHelper(arguments)... }; |
213 | std::array types = { r.metaType, Invoke::metaTypeHelper(arguments)... }; |
214 | static_assert(params.size() == types.size()); |
215 | static_assert(params.size() == names.size()); |
216 | |
217 | struct R { |
218 | decltype(params) parameters; |
219 | decltype(names) typeNames; |
220 | decltype(types) metaTypes; |
221 | constexpr qsizetype parameterCount() const { return qsizetype(parameters.size()); } |
222 | }; |
223 | return R { params, names, types }; |
224 | } |
225 | } // namespace QtPrivate |
226 | |
227 | template <typename T> void qReturnArg(const T &&) = delete; |
228 | template <typename T> inline QTemplatedMetaMethodReturnArgument<T> qReturnArg(T &data) |
229 | { |
230 | return QtPrivate::Invoke::returnArgument(nullptr, data); |
231 | } |
232 | |
233 | struct Q_CORE_EXPORT QMetaObject |
234 | { |
235 | class Connection; |
236 | const char *className() const; |
237 | const QMetaObject *superClass() const; |
238 | |
239 | bool inherits(const QMetaObject *metaObject) const noexcept; |
240 | QObject *cast(QObject *obj) const |
241 | { return const_cast<QObject *>(cast(obj: const_cast<const QObject *>(obj))); } |
242 | const QObject *cast(const QObject *obj) const; |
243 | |
244 | #if !defined(QT_NO_TRANSLATION) || defined(Q_QDOC) |
245 | QString tr(const char *s, const char *c, int n = -1) const; |
246 | #endif // QT_NO_TRANSLATION |
247 | |
248 | QMetaType metaType() const; |
249 | |
250 | int methodOffset() const; |
251 | int enumeratorOffset() const; |
252 | int propertyOffset() const; |
253 | int classInfoOffset() const; |
254 | |
255 | int constructorCount() const; |
256 | int methodCount() const; |
257 | int enumeratorCount() const; |
258 | int propertyCount() const; |
259 | int classInfoCount() const; |
260 | |
261 | int indexOfConstructor(const char *constructor) const; |
262 | int indexOfMethod(const char *method) const; |
263 | int indexOfSignal(const char *signal) const; |
264 | int indexOfSlot(const char *slot) const; |
265 | int indexOfEnumerator(const char *name) const; |
266 | |
267 | int indexOfProperty(const char *name) const; |
268 | int indexOfClassInfo(const char *name) const; |
269 | |
270 | QMetaMethod constructor(int index) const; |
271 | QMetaMethod method(int index) const; |
272 | QMetaEnum enumerator(int index) const; |
273 | QMetaProperty property(int index) const; |
274 | QMetaClassInfo classInfo(int index) const; |
275 | QMetaProperty userProperty() const; |
276 | |
277 | static bool checkConnectArgs(const char *signal, const char *method); |
278 | static bool checkConnectArgs(const QMetaMethod &signal, |
279 | const QMetaMethod &method); |
280 | static QByteArray normalizedSignature(const char *method); |
281 | static QByteArray normalizedType(const char *type); |
282 | |
283 | // internal index-based connect |
284 | static Connection connect(const QObject *sender, int signal_index, |
285 | const QObject *receiver, int method_index, |
286 | int type = 0, int *types = nullptr); |
287 | // internal index-based disconnect |
288 | static bool disconnect(const QObject *sender, int signal_index, |
289 | const QObject *receiver, int method_index); |
290 | static bool disconnectOne(const QObject *sender, int signal_index, |
291 | const QObject *receiver, int method_index); |
292 | // internal slot-name based connect |
293 | static void connectSlotsByName(QObject *o); |
294 | |
295 | // internal index-based signal activation |
296 | static void activate(QObject *sender, int signal_index, void **argv); |
297 | static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); |
298 | static void activate(QObject *sender, int signal_offset, int local_signal_index, void **argv); |
299 | |
300 | #if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) |
301 | static bool invokeMethod(QObject *obj, const char *member, |
302 | Qt::ConnectionType, |
303 | QGenericReturnArgument ret, |
304 | QGenericArgument val0 = QGenericArgument(nullptr), |
305 | QGenericArgument val1 = QGenericArgument(), |
306 | QGenericArgument val2 = QGenericArgument(), |
307 | QGenericArgument val3 = QGenericArgument(), |
308 | QGenericArgument val4 = QGenericArgument(), |
309 | QGenericArgument val5 = QGenericArgument(), |
310 | QGenericArgument val6 = QGenericArgument(), |
311 | QGenericArgument val7 = QGenericArgument(), |
312 | QGenericArgument val8 = QGenericArgument(), |
313 | QGenericArgument val9 = QGenericArgument()); |
314 | |
315 | static inline bool invokeMethod(QObject *obj, const char *member, |
316 | QGenericReturnArgument ret, |
317 | QGenericArgument val0 = QGenericArgument(nullptr), |
318 | QGenericArgument val1 = QGenericArgument(), |
319 | QGenericArgument val2 = QGenericArgument(), |
320 | QGenericArgument val3 = QGenericArgument(), |
321 | QGenericArgument val4 = QGenericArgument(), |
322 | QGenericArgument val5 = QGenericArgument(), |
323 | QGenericArgument val6 = QGenericArgument(), |
324 | QGenericArgument val7 = QGenericArgument(), |
325 | QGenericArgument val8 = QGenericArgument(), |
326 | QGenericArgument val9 = QGenericArgument()) |
327 | { |
328 | return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3, |
329 | val4, val5, val6, val7, val8, val9); |
330 | } |
331 | |
332 | static inline bool invokeMethod(QObject *obj, const char *member, |
333 | Qt::ConnectionType type, |
334 | QGenericArgument val0, |
335 | QGenericArgument val1 = QGenericArgument(), |
336 | QGenericArgument val2 = QGenericArgument(), |
337 | QGenericArgument val3 = QGenericArgument(), |
338 | QGenericArgument val4 = QGenericArgument(), |
339 | QGenericArgument val5 = QGenericArgument(), |
340 | QGenericArgument val6 = QGenericArgument(), |
341 | QGenericArgument val7 = QGenericArgument(), |
342 | QGenericArgument val8 = QGenericArgument(), |
343 | QGenericArgument val9 = QGenericArgument()) |
344 | { |
345 | return invokeMethod(obj, member, type, ret: QGenericReturnArgument(), val0, val1, val2, |
346 | val3, val4, val5, val6, val7, val8, val9); |
347 | } |
348 | |
349 | static inline bool invokeMethod(QObject *obj, const char *member, |
350 | QGenericArgument val0, |
351 | QGenericArgument val1 = QGenericArgument(), |
352 | QGenericArgument val2 = QGenericArgument(), |
353 | QGenericArgument val3 = QGenericArgument(), |
354 | QGenericArgument val4 = QGenericArgument(), |
355 | QGenericArgument val5 = QGenericArgument(), |
356 | QGenericArgument val6 = QGenericArgument(), |
357 | QGenericArgument val7 = QGenericArgument(), |
358 | QGenericArgument val8 = QGenericArgument(), |
359 | QGenericArgument val9 = QGenericArgument()) |
360 | { |
361 | return invokeMethod(obj, member, Qt::AutoConnection, ret: QGenericReturnArgument(), val0, |
362 | val1, val2, val3, val4, val5, val6, val7, val8, val9); |
363 | } |
364 | #endif // Qt < 7.0 |
365 | |
366 | template <typename ReturnArg, typename... Args> static |
367 | #ifdef Q_QDOC |
368 | bool |
369 | #else |
370 | QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...> |
371 | #endif |
372 | invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c, |
373 | QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments) |
374 | { |
375 | auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...); |
376 | return invokeMethodImpl(obj, member, c, h.parameterCount(), h.parameters.data(), |
377 | h.typeNames.data(), h.metaTypes.data()); |
378 | } |
379 | |
380 | template <typename... Args> static |
381 | #ifdef Q_QDOC |
382 | bool |
383 | #else |
384 | QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...> |
385 | #endif |
386 | invokeMethod(QObject *obj, const char *member, Qt::ConnectionType c, Args &&... arguments) |
387 | { |
388 | QTemplatedMetaMethodReturnArgument<void> r = {}; |
389 | return invokeMethod(obj, member, c, r, std::forward<Args>(arguments)...); |
390 | } |
391 | |
392 | template <typename ReturnArg, typename... Args> static |
393 | #ifdef Q_QDOC |
394 | bool |
395 | #else |
396 | QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...> |
397 | #endif |
398 | invokeMethod(QObject *obj, const char *member, QTemplatedMetaMethodReturnArgument<ReturnArg> r, |
399 | Args &&... arguments) |
400 | { |
401 | return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...); |
402 | } |
403 | |
404 | template <typename... Args> static |
405 | #ifdef Q_QDOC |
406 | bool |
407 | #else |
408 | QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...> |
409 | #endif |
410 | invokeMethod(QObject *obj, const char *member, Args &&... arguments) |
411 | { |
412 | QTemplatedMetaMethodReturnArgument<void> r = {}; |
413 | return invokeMethod(obj, member, Qt::AutoConnection, r, std::forward<Args>(arguments)...); |
414 | } |
415 | |
416 | #ifdef Q_QDOC |
417 | template<typename Functor, typename FunctorReturnType> |
418 | static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr); |
419 | template<typename Functor, typename FunctorReturnType> |
420 | static bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret); |
421 | |
422 | template<typename Functor, typename FunctorReturnType, typename... Args> |
423 | static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments); |
424 | template<typename Functor, typename FunctorReturnType, typename... Args> |
425 | static bool invokeMethod(QObject *context, Functor &&function, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments); |
426 | template<typename Functor, typename... Args> |
427 | static bool invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, Args &&...arguments); |
428 | template<typename Functor, typename... Args> |
429 | static bool invokeMethod(QObject *context, Functor &&function, Args &&...arguments); |
430 | #else |
431 | template <typename Func> |
432 | static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, |
433 | QtPrivate::Invoke::AreOldStyleArgs<Func>>, |
434 | bool> |
435 | invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, |
436 | Func &&function, Qt::ConnectionType type, |
437 | typename QtPrivate::Callable<Func>::ReturnType *ret) |
438 | { |
439 | using R = typename QtPrivate::Callable<Func>::ReturnType; |
440 | const auto getReturnArg = [ret]() -> QTemplatedMetaMethodReturnArgument<R> { |
441 | if constexpr (std::is_void_v<R>) |
442 | return {}; |
443 | else |
444 | return ret ? qReturnArg(*ret) : QTemplatedMetaMethodReturnArgument<R>{}; |
445 | }; |
446 | return invokeMethod(object, std::forward<Func>(function), type, getReturnArg()); |
447 | } |
448 | template <typename Func> |
449 | static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, |
450 | QtPrivate::Invoke::AreOldStyleArgs<Func>>, |
451 | bool> |
452 | invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, |
453 | Func &&function, typename QtPrivate::Callable<Func>::ReturnType *ret) |
454 | { |
455 | return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, ret); |
456 | } |
457 | |
458 | template <typename Func, typename... Args> |
459 | static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, |
460 | QtPrivate::Invoke::AreOldStyleArgs<Args...>>, |
461 | bool> |
462 | invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, |
463 | Func &&function, Qt::ConnectionType type, |
464 | QTemplatedMetaMethodReturnArgument< |
465 | typename QtPrivate::Callable<Func, Args...>::ReturnType> |
466 | ret, |
467 | Args &&...args) |
468 | { |
469 | return invokeMethodCallableHelper(object, std::forward<Func>(function), type, ret, |
470 | std::forward<Args>(args)...); |
471 | } |
472 | |
473 | template <typename Func, typename... Args> |
474 | static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, |
475 | QtPrivate::Invoke::AreOldStyleArgs<Args...>>, |
476 | bool> |
477 | invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, |
478 | Func &&function, Qt::ConnectionType type, Args &&...args) |
479 | { |
480 | using R = typename QtPrivate::Callable<Func, Args...>::ReturnType; |
481 | QTemplatedMetaMethodReturnArgument<R> r{ QtPrivate::qMetaTypeInterfaceForType<R>(), nullptr, |
482 | nullptr }; |
483 | return invokeMethod(object, std::forward<Func>(function), type, r, |
484 | std::forward<Args>(args)...); |
485 | } |
486 | |
487 | template <typename Func, typename... Args> |
488 | static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, |
489 | QtPrivate::Invoke::AreOldStyleArgs<Args...>>, |
490 | bool> |
491 | invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, |
492 | Func &&function, |
493 | QTemplatedMetaMethodReturnArgument< |
494 | typename QtPrivate::Callable<Func, Args...>::ReturnType> |
495 | ret, |
496 | Args &&...args) |
497 | { |
498 | return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, ret, |
499 | std::forward<Args>(args)...); |
500 | } |
501 | |
502 | template <typename Func, typename... Args> |
503 | static std::enable_if_t<!std::disjunction_v<std::is_convertible<Func, const char *>, |
504 | QtPrivate::Invoke::AreOldStyleArgs<Args...>>, |
505 | bool> |
506 | invokeMethod(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, |
507 | Func &&function, Args &&...args) |
508 | { |
509 | using R = typename QtPrivate::Callable<Func, Args...>::ReturnType; |
510 | QTemplatedMetaMethodReturnArgument<R> r{ QtPrivate::qMetaTypeInterfaceForType<R>(), nullptr, |
511 | nullptr }; |
512 | return invokeMethod(object, std::forward<Func>(function), Qt::AutoConnection, r, |
513 | std::forward<Args>(args)...); |
514 | } |
515 | |
516 | #endif |
517 | |
518 | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) |
519 | QObject *newInstance(QGenericArgument val0, |
520 | QGenericArgument val1 = QGenericArgument(), |
521 | QGenericArgument val2 = QGenericArgument(), |
522 | QGenericArgument val3 = QGenericArgument(), |
523 | QGenericArgument val4 = QGenericArgument(), |
524 | QGenericArgument val5 = QGenericArgument(), |
525 | QGenericArgument val6 = QGenericArgument(), |
526 | QGenericArgument val7 = QGenericArgument(), |
527 | QGenericArgument val8 = QGenericArgument(), |
528 | QGenericArgument val9 = QGenericArgument()) const; |
529 | #endif |
530 | |
531 | template <typename... Args> |
532 | #ifdef Q_QDOC |
533 | QObject * |
534 | #else |
535 | QtPrivate::Invoke::IfNotOldStyleArgs<QObject *, Args...> |
536 | #endif |
537 | newInstance(Args &&... arguments) const |
538 | { |
539 | auto h = QtPrivate::invokeMethodHelper(QMetaMethodReturnArgument{}, std::forward<Args>(arguments)...); |
540 | return newInstanceImpl(mobj: this, parameterCount: h.parameterCount(), parameters: h.parameters.data(), |
541 | typeNames: h.typeNames.data(), metaTypes: h.metaTypes.data()); |
542 | } |
543 | |
544 | enum Call { |
545 | InvokeMetaMethod, |
546 | ReadProperty, |
547 | WriteProperty, |
548 | ResetProperty, |
549 | CreateInstance, |
550 | IndexOfMethod, |
551 | RegisterPropertyMetaType, |
552 | RegisterMethodArgumentMetaType, |
553 | BindableProperty, |
554 | CustomCall, |
555 | ConstructInPlace, |
556 | }; |
557 | |
558 | int static_metacall(Call, int, void **) const; |
559 | static int metacall(QObject *, Call, int, void **); |
560 | |
561 | template <const QMetaObject &MO> static constexpr const QMetaObject *staticMetaObject() |
562 | { |
563 | return &MO; |
564 | } |
565 | |
566 | struct SuperData { |
567 | using Getter = const QMetaObject *(*)(); |
568 | const QMetaObject *direct; |
569 | SuperData() = default; |
570 | constexpr SuperData(std::nullptr_t) : direct(nullptr) {} |
571 | constexpr SuperData(const QMetaObject *mo) : direct(mo) {} |
572 | |
573 | constexpr const QMetaObject *operator->() const { return operator const QMetaObject *(); } |
574 | |
575 | #ifdef QT_NO_DATA_RELOCATION |
576 | Getter indirect = nullptr; |
577 | constexpr SuperData(Getter g) : direct(nullptr), indirect(g) {} |
578 | constexpr operator const QMetaObject *() const |
579 | { return indirect ? indirect() : direct; } |
580 | template <const QMetaObject &MO> static constexpr SuperData link() |
581 | { return SuperData(QMetaObject::staticMetaObject<MO>); } |
582 | #else |
583 | constexpr SuperData(Getter g) : direct(g()) {} |
584 | constexpr operator const QMetaObject *() const |
585 | { return direct; } |
586 | template <const QMetaObject &MO> static constexpr SuperData link() |
587 | { return SuperData(QMetaObject::staticMetaObject<MO>()); } |
588 | #endif |
589 | }; |
590 | |
591 | struct Data { // private data |
592 | SuperData superdata; |
593 | const uint *stringdata; |
594 | const uint *data; |
595 | typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); |
596 | StaticMetacallFunction static_metacall; |
597 | const SuperData *relatedMetaObjects; |
598 | const QtPrivate::QMetaTypeInterface *const *metaTypes; |
599 | void *; //reserved for future use |
600 | } d; |
601 | |
602 | private: |
603 | // Just need to have this here with a separate name so the other inline |
604 | // functions can call this without any ambiguity |
605 | template <typename Func, typename... Args> |
606 | static bool |
607 | invokeMethodCallableHelper(typename QtPrivate::ContextTypeForFunctor<Func>::ContextType *object, |
608 | Func &&function, Qt::ConnectionType type, const QMetaMethodReturnArgument &ret, |
609 | Args &&...args) |
610 | { |
611 | using Callable = QtPrivate::Callable<Func, Args...>; |
612 | using ExpectedArguments = typename Callable::Arguments; |
613 | static_assert(sizeof...(Args) <= ExpectedArguments::size, "Too many arguments" ); |
614 | using ActualArguments = QtPrivate::List<Args...>; |
615 | static_assert(QtPrivate::CheckCompatibleArguments<ActualArguments, |
616 | ExpectedArguments>::value, |
617 | "Incompatible arguments" ); |
618 | |
619 | auto h = QtPrivate::invokeMethodHelper(ret, std::forward<Args>(args)...); |
620 | |
621 | // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) |
622 | auto callable = new QtPrivate::QCallableObject<std::decay_t<Func>, ActualArguments, |
623 | typename Callable::ReturnType>(std::forward<Func>(function)); |
624 | return invokeMethodImpl(object, callable, type, h.parameterCount(), h.parameters.data(), |
625 | h.typeNames.data(), h.metaTypes.data()); |
626 | } |
627 | |
628 | static bool invokeMethodImpl(QObject *object, const char *member, Qt::ConnectionType type, |
629 | qsizetype parameterCount, const void *const *parameters, const char *const *names, |
630 | const QtPrivate::QMetaTypeInterface * const *metaTypes); |
631 | static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slotObj, |
632 | Qt::ConnectionType type, qsizetype parameterCount, |
633 | const void *const *params, const char *const *names, |
634 | const QtPrivate::QMetaTypeInterface *const *metaTypes); |
635 | #if QT_CORE_REMOVED_SINCE(6, 7) |
636 | static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret); |
637 | #endif |
638 | static QObject *newInstanceImpl(const QMetaObject *mobj, qsizetype parameterCount, |
639 | const void **parameters, const char **typeNames, |
640 | const QtPrivate::QMetaTypeInterface **metaTypes); |
641 | friend class QTimer; |
642 | }; |
643 | |
644 | class Q_CORE_EXPORT QMetaObject::Connection { |
645 | void *d_ptr; //QObjectPrivate::Connection* |
646 | explicit Connection(void *data) : d_ptr(data) { } |
647 | friend class QObject; |
648 | friend class QObjectPrivate; |
649 | friend struct QMetaObject; |
650 | bool isConnected_helper() const; |
651 | public: |
652 | ~Connection(); |
653 | Connection(); |
654 | Connection(const Connection &other); |
655 | Connection &operator=(const Connection &other); |
656 | #ifdef Q_QDOC |
657 | operator bool() const; |
658 | #else |
659 | // still using the restricted bool trick here, in order to support |
660 | // code using copy-init (e.g. `bool ok = connect(...)`) |
661 | typedef void *Connection::*RestrictedBool; |
662 | operator RestrictedBool() const { return d_ptr && isConnected_helper() ? &Connection::d_ptr : nullptr; } |
663 | #endif |
664 | |
665 | Connection(Connection &&other) noexcept : d_ptr(std::exchange(obj&: other.d_ptr, new_val: nullptr)) {} |
666 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Connection) |
667 | void swap(Connection &other) noexcept { qt_ptr_swap(lhs&: d_ptr, rhs&: other.d_ptr); } |
668 | }; |
669 | |
670 | inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept |
671 | { |
672 | lhs.swap(other&: rhs); |
673 | } |
674 | |
675 | inline const QMetaObject *QMetaObject::superClass() const |
676 | { return d.superdata; } |
677 | |
678 | namespace QtPrivate { |
679 | // Trait that tells if a QObject has a Q_OBJECT macro |
680 | template <typename Object> struct HasQ_OBJECT_Macro { |
681 | template <typename T> |
682 | static char test(int (T::*)(QMetaObject::Call, int, void **)); |
683 | static int test(int (Object::*)(QMetaObject::Call, int, void **)); |
684 | enum { Value = sizeof(test(&Object::qt_metacall)) == sizeof(int) }; |
685 | }; |
686 | } |
687 | |
688 | QT_END_NAMESPACE |
689 | |
690 | #endif // QOBJECTDEFS_H |
691 | |