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
52QT_BEGIN_NAMESPACE
53
54class QByteArray;
55struct QArrayData;
56
57class 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
72Q_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
98class QObject;
99class QMetaMethod;
100class QMetaEnum;
101class QMetaProperty;
102class QMetaClassInfo;
103
104namespace QtPrivate {
105class QMetaTypeInterface;
106}
107
108struct QMethodRawArguments
109{
110 void **arguments;
111};
112
113class Q_CORE_EXPORT QGenericArgument
114{
115public:
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
121private:
122 const void *_data;
123 const char *_name;
124};
125
126class Q_CORE_EXPORT QGenericReturnArgument: public QGenericArgument
127{
128public:
129 inline QGenericReturnArgument(const char *aName = nullptr, void *aData = nullptr)
130 : QGenericArgument(aName, aData)
131 {}
132};
133
134template <class T>
135class QArgument: public QGenericArgument
136{
137public:
138 inline QArgument(const char *aName, const T &aData)
139 : QGenericArgument(aName, static_cast<const void *>(&aData))
140 {}
141};
142template <class T>
143class QArgument<T &>: public QGenericArgument
144{
145public:
146 inline QArgument(const char *aName, T &aData)
147 : QGenericArgument(aName, static_cast<const void *>(&aData))
148 {}
149};
150
151
152template <typename T>
153class QReturnArgument: public QGenericReturnArgument
154{
155public:
156 inline QReturnArgument(const char *aName, T &aData)
157 : QGenericReturnArgument(aName, static_cast<void *>(&aData))
158 {}
159};
160
161struct 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 *extradata; //reserved for future use
434 } d;
435
436private:
437 static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
438 friend class QTimer;
439};
440
441class 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;
448public:
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
467inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept
468{
469 lhs.swap(rhs);
470}
471
472inline const QMetaObject *QMetaObject::superClass() const
473{ return d.superdata; }
474
475namespace 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
485QT_END_NAMESPACE
486
487#endif // QOBJECTDEFS_H
488