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 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 *extradata; //reserved for future use
436 } d;
437
438private:
439 static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
440 friend class QTimer;
441};
442
443class 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;
450public:
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
469inline void swap(QMetaObject::Connection &lhs, QMetaObject::Connection &rhs) noexcept
470{
471 lhs.swap(rhs);
472}
473
474inline const QMetaObject *QMetaObject::superClass() const
475{ return d.superdata; }
476
477namespace 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
487QT_END_NAMESPACE
488
489#endif // QOBJECTDEFS_H
490