1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
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 QMETAOBJECT_H
6#define QMETAOBJECT_H
7
8#include <QtCore/qobjectdefs.h>
9#include <QtCore/qcompare.h>
10#include <QtCore/qvariant.h>
11
12QT_BEGIN_NAMESPACE
13
14class QUntypedBindable;
15
16#define Q_METAMETHOD_INVOKE_MAX_ARGS 10
17
18class Q_CORE_EXPORT QMetaMethod
19{
20public:
21 constexpr inline QMetaMethod() : mobj(nullptr), data({ .d: nullptr }) {}
22
23 QByteArray methodSignature() const;
24 QByteArray name() const;
25 QByteArrayView nameView() const;
26 const char *typeName() const;
27 int returnType() const;
28 QMetaType returnMetaType() const;
29 int parameterCount() const;
30 int parameterType(int index) const;
31 QMetaType parameterMetaType(int index) const;
32 void getParameterTypes(int *types) const;
33 QList<QByteArray> parameterTypes() const;
34 QByteArray parameterTypeName(int index) const;
35 QList<QByteArray> parameterNames() const;
36 const char *tag() const;
37 enum Access { Private, Protected, Public };
38 Access access() const;
39 enum MethodType { Method, Signal, Slot, Constructor };
40 MethodType methodType() const;
41 enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 };
42 int attributes() const;
43 int methodIndex() const;
44 int relativeMethodIndex() const;
45 int revision() const;
46 bool isConst() const;
47
48 inline const QMetaObject *enclosingMetaObject() const { return mobj; }
49
50#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
51 bool invoke(QObject *object,
52 Qt::ConnectionType connectionType,
53 QGenericReturnArgument returnValue,
54 QGenericArgument val0 = QGenericArgument(nullptr),
55 QGenericArgument val1 = QGenericArgument(),
56 QGenericArgument val2 = QGenericArgument(),
57 QGenericArgument val3 = QGenericArgument(),
58 QGenericArgument val4 = QGenericArgument(),
59 QGenericArgument val5 = QGenericArgument(),
60 QGenericArgument val6 = QGenericArgument(),
61 QGenericArgument val7 = QGenericArgument(),
62 QGenericArgument val8 = QGenericArgument(),
63 QGenericArgument val9 = QGenericArgument()) const;
64 inline bool invoke(QObject *object,
65 QGenericReturnArgument returnValue,
66 QGenericArgument val0 = QGenericArgument(nullptr),
67 QGenericArgument val1 = QGenericArgument(),
68 QGenericArgument val2 = QGenericArgument(),
69 QGenericArgument val3 = QGenericArgument(),
70 QGenericArgument val4 = QGenericArgument(),
71 QGenericArgument val5 = QGenericArgument(),
72 QGenericArgument val6 = QGenericArgument(),
73 QGenericArgument val7 = QGenericArgument(),
74 QGenericArgument val8 = QGenericArgument(),
75 QGenericArgument val9 = QGenericArgument()) const
76 {
77 return invoke(object, connectionType: Qt::AutoConnection, returnValue,
78 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
79 }
80 inline bool invoke(QObject *object,
81 Qt::ConnectionType connectionType,
82 QGenericArgument val0,
83 QGenericArgument val1 = QGenericArgument(),
84 QGenericArgument val2 = QGenericArgument(),
85 QGenericArgument val3 = QGenericArgument(),
86 QGenericArgument val4 = QGenericArgument(),
87 QGenericArgument val5 = QGenericArgument(),
88 QGenericArgument val6 = QGenericArgument(),
89 QGenericArgument val7 = QGenericArgument(),
90 QGenericArgument val8 = QGenericArgument(),
91 QGenericArgument val9 = QGenericArgument()) const
92 {
93 return invoke(object, connectionType, returnValue: QGenericReturnArgument(),
94 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
95 }
96 inline bool invoke(QObject *object,
97 QGenericArgument val0,
98 QGenericArgument val1 = QGenericArgument(),
99 QGenericArgument val2 = QGenericArgument(),
100 QGenericArgument val3 = QGenericArgument(),
101 QGenericArgument val4 = QGenericArgument(),
102 QGenericArgument val5 = QGenericArgument(),
103 QGenericArgument val6 = QGenericArgument(),
104 QGenericArgument val7 = QGenericArgument(),
105 QGenericArgument val8 = QGenericArgument(),
106 QGenericArgument val9 = QGenericArgument()) const
107 {
108 return invoke(object, connectionType: Qt::AutoConnection, returnValue: QGenericReturnArgument(),
109 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
110 }
111 bool invokeOnGadget(void *gadget,
112 QGenericReturnArgument returnValue,
113 QGenericArgument val0 = QGenericArgument(nullptr),
114 QGenericArgument val1 = QGenericArgument(),
115 QGenericArgument val2 = QGenericArgument(),
116 QGenericArgument val3 = QGenericArgument(),
117 QGenericArgument val4 = QGenericArgument(),
118 QGenericArgument val5 = QGenericArgument(),
119 QGenericArgument val6 = QGenericArgument(),
120 QGenericArgument val7 = QGenericArgument(),
121 QGenericArgument val8 = QGenericArgument(),
122 QGenericArgument val9 = QGenericArgument()) const;
123 inline bool invokeOnGadget(void *gadget,
124 QGenericArgument val0,
125 QGenericArgument val1 = QGenericArgument(),
126 QGenericArgument val2 = QGenericArgument(),
127 QGenericArgument val3 = QGenericArgument(),
128 QGenericArgument val4 = QGenericArgument(),
129 QGenericArgument val5 = QGenericArgument(),
130 QGenericArgument val6 = QGenericArgument(),
131 QGenericArgument val7 = QGenericArgument(),
132 QGenericArgument val8 = QGenericArgument(),
133 QGenericArgument val9 = QGenericArgument()) const
134 {
135 return invokeOnGadget(gadget, returnValue: QGenericReturnArgument(),
136 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
137 }
138#endif
139
140 template <typename ReturnArg, typename... Args>
141#ifdef Q_QDOC
142 bool
143#else
144 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
145#endif
146 invoke(QObject *obj, Qt::ConnectionType c, QTemplatedMetaMethodReturnArgument<ReturnArg> r,
147 Args &&... arguments) const
148 {
149 auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...);
150 return invokeImpl(self: *this, target: obj, c, paramCount: h.parameterCount(), parameters: h.parameters.data(),
151 typeNames: h.typeNames.data(), metaTypes: h.metaTypes.data());
152 }
153
154 template <typename... Args>
155#ifdef Q_QDOC
156 bool
157#else
158 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
159#endif
160 invoke(QObject *obj, Qt::ConnectionType c, Args &&... arguments) const
161 {
162 return invoke(obj, c, QTemplatedMetaMethodReturnArgument<void>{}, std::forward<Args>(arguments)...);
163 }
164
165 template <typename ReturnArg, typename... Args>
166#ifdef Q_QDOC
167 bool
168#else
169 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
170#endif
171 invoke(QObject *obj, QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments) const
172 {
173 return invoke(obj, Qt::AutoConnection, r, std::forward<Args>(arguments)...);
174 }
175
176 template <typename... Args>
177#ifdef Q_QDOC
178 bool
179#else
180 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
181#endif
182 invoke(QObject *obj, Args &&... arguments) const
183 {
184 return invoke(obj, Qt::AutoConnection, std::forward<Args>(arguments)...);
185 }
186
187 template <typename ReturnArg, typename... Args>
188#ifdef Q_QDOC
189 bool
190#else
191 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
192#endif
193 invokeOnGadget(void *gadget, QTemplatedMetaMethodReturnArgument<ReturnArg> r, Args &&... arguments) const
194 {
195 auto h = QtPrivate::invokeMethodHelper(r, std::forward<Args>(arguments)...);
196 return invokeImpl(self: *this, target: gadget, Qt::ConnectionType(-1), paramCount: h.parameterCount(),
197 parameters: h.parameters.data(), typeNames: h.typeNames.data(), metaTypes: h.metaTypes.data());
198 }
199
200 template <typename... Args>
201#ifdef Q_QDOC
202 bool
203#else
204 QtPrivate::Invoke::IfNotOldStyleArgs<bool, Args...>
205#endif
206 invokeOnGadget(void *gadget, Args &&... arguments) const
207 {
208 return invokeOnGadget(gadget, QTemplatedMetaMethodReturnArgument<void>{}, std::forward<Args>(arguments)...);
209 }
210
211 inline bool isValid() const { return mobj != nullptr; }
212
213 template <typename PointerToMemberFunction>
214 static inline QMetaMethod fromSignal(PointerToMemberFunction signal)
215 {
216 typedef QtPrivate::FunctionPointer<PointerToMemberFunction> SignalType;
217 static_assert(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
218 "No Q_OBJECT in the class with the signal");
219 return fromSignalImpl(&SignalType::Object::staticMetaObject,
220 reinterpret_cast<void **>(&signal));
221 }
222
223private:
224 static bool invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType, qsizetype paramCount,
225 const void *const *parameters, const char *const *typeNames,
226 const QtPrivate::QMetaTypeInterface *const *metaTypes);
227 static QMetaMethod fromSignalImpl(const QMetaObject *, void **);
228 static QMetaMethod fromRelativeMethodIndex(const QMetaObject *mobj, int index);
229 static QMetaMethod fromRelativeConstructorIndex(const QMetaObject *mobj, int index);
230
231protected:
232 struct Data {
233 enum { Size = 6 };
234
235 uint name() const { return d[0]; }
236 uint argc() const { return d[1]; }
237 uint parameters() const { return d[2]; }
238 uint tag() const { return d[3]; }
239 uint flags() const { return d[4]; }
240 uint metaTypeOffset() const { return d[5]; }
241 bool operator==(const Data &other) const { return d == other.d; }
242
243 const uint *d;
244 };
245private:
246 constexpr QMetaMethod(const QMetaObject *metaObject, const Data &data_)
247 : mobj(metaObject), data(data_)
248 {}
249protected:
250
251 const QMetaObject *mobj;
252 Data data;
253 friend struct QMetaObject;
254 friend struct QMetaObjectPrivate;
255 friend class QObject;
256
257private:
258 friend bool comparesEqual(const QMetaMethod &lhs, const QMetaMethod &rhs) noexcept
259 { return lhs.data == rhs.data; }
260 Q_DECLARE_EQUALITY_COMPARABLE(QMetaMethod)
261};
262Q_DECLARE_TYPEINFO(QMetaMethod, Q_RELOCATABLE_TYPE);
263
264class Q_CORE_EXPORT QMetaEnum
265{
266public:
267 constexpr inline QMetaEnum() : mobj(nullptr), data({ .d: nullptr }) {}
268
269 const char *name() const;
270 const char *enumName() const;
271 QMetaType metaType() const;
272
273 bool isFlag() const;
274 bool isScoped() const;
275 bool is64Bit() const;
276
277 int keyCount() const;
278 const char *key(int index) const;
279 int value(int index) const;
280 std::optional<quint64> value64(int index) const;
281
282 const char *scope() const;
283
284 int keyToValue(const char *key, bool *ok = nullptr) const;
285 int keysToValue(const char *keys, bool *ok = nullptr) const;
286 std::optional<quint64> keyToValue64(const char *key) const;
287 std::optional<quint64> keysToValue64(const char *keys) const;
288#if QT_CORE_REMOVED_SINCE(6, 9)
289 const char *valueToKey(int value) const;
290 QByteArray valueToKeys(int value) const;
291#endif
292 const char *valueToKey(quint64 value) const;
293 QByteArray valueToKeys(quint64 value) const;
294
295 inline const QMetaObject *enclosingMetaObject() const { return mobj; }
296
297 inline bool isValid() const { return name() != nullptr; }
298
299 template<typename T>
300 static QMetaEnum fromType()
301 {
302 static_assert(QtPrivate::IsQEnumHelper<T>::Value,
303 "QMetaEnum::fromType only works with enums declared as "
304 "Q_ENUM, Q_ENUM_NS, Q_FLAG or Q_FLAG_NS");
305 const QMetaObject *metaObject = qt_getEnumMetaObject(T());
306 const char *name = qt_getEnumName(T());
307 return metaObject->enumerator(index: metaObject->indexOfEnumerator(name));
308 }
309
310private:
311 struct Data {
312 enum { Size = 5 };
313 quint32 name() const { return d[0]; }
314 quint32 alias() const { return d[1]; }
315 quint32 flags() const { return d[2]; }
316 qint32 keyCount() const { return static_cast<qint32>(d[3]); }
317 quint32 data() const { return d[4]; }
318 int index(const QMetaObject *mobj) const;
319
320 const uint *d;
321 };
322
323 QMetaEnum(const QMetaObject *mobj, int index);
324 template <typename... Args> quint64 value_helper(uint index, Args...) const noexcept;
325
326 const QMetaObject *mobj;
327 Data data;
328 friend struct QMetaObject;
329 friend struct QMetaObjectPrivate;
330};
331Q_DECLARE_TYPEINFO(QMetaEnum, Q_RELOCATABLE_TYPE);
332
333class Q_CORE_EXPORT QMetaProperty
334{
335public:
336 constexpr QMetaProperty() : mobj(nullptr), data({ .d: nullptr }) {}
337
338 const char *name() const;
339 const char *typeName() const;
340#if QT_DEPRECATED_SINCE(6, 0)
341 QT_WARNING_PUSH
342 QT_WARNING_DISABLE_DEPRECATED
343 QT_DEPRECATED_VERSION_6_0
344 QVariant::Type type() const
345 { int t = userType(); return t >= QMetaType::User ? QVariant::UserType : QVariant::Type(t); }
346 QT_WARNING_POP
347#endif
348 int userType() const { return typeId(); }
349 int typeId() const { return metaType().id(); }
350 QMetaType metaType() const;
351 int propertyIndex() const;
352 int relativePropertyIndex() const;
353
354 bool isReadable() const;
355 bool isWritable() const;
356 bool isResettable() const;
357 bool isDesignable() const;
358 bool isScriptable() const;
359 bool isStored() const;
360 bool isUser() const;
361 bool isConstant() const;
362 bool isFinal() const;
363 bool isRequired() const;
364 bool isBindable() const;
365
366 bool isFlagType() const;
367 bool isEnumType() const;
368 QMetaEnum enumerator() const;
369
370 bool hasNotifySignal() const;
371 QMetaMethod notifySignal() const;
372 int notifySignalIndex() const;
373
374 int revision() const;
375
376 QVariant read(const QObject *obj) const;
377 bool write(QObject *obj, const QVariant &value) const;
378 bool write(QObject *obj, QVariant &&value) const;
379 bool reset(QObject *obj) const;
380
381 QUntypedBindable bindable(QObject *object) const;
382
383 QVariant readOnGadget(const void *gadget) const;
384 bool writeOnGadget(void *gadget, const QVariant &value) const;
385 bool writeOnGadget(void *gadget, QVariant &&value) const;
386 bool resetOnGadget(void *gadget) const;
387
388 bool hasStdCppSet() const;
389 bool isAlias() const;
390 inline bool isValid() const { return isReadable(); }
391 inline const QMetaObject *enclosingMetaObject() const { return mobj; }
392
393private:
394#if QT_DEPRECATED_SINCE(6, 4)
395 QT_DEPRECATED_VERSION_X_6_4("obsolete, simply returns typeId()")
396 int registerPropertyType() const;
397#endif
398
399 struct Data {
400 enum { Size = 5 };
401
402 uint name() const { return d[0]; }
403 uint type() const { return d[1]; }
404 uint flags() const { return d[2]; }
405 uint notifyIndex() const { return d[3]; }
406 uint revision() const { return d[4]; }
407
408 int index(const QMetaObject *mobj) const;
409
410 const uint *d;
411 };
412
413 QMetaProperty(const QMetaObject *mobj, int index);
414 static Data getMetaPropertyData(const QMetaObject *mobj, int index);
415
416 const QMetaObject *mobj;
417 Data data;
418 QMetaEnum menum;
419 friend struct QMetaObject;
420 friend struct QMetaObjectPrivate;
421};
422
423class Q_CORE_EXPORT QMetaClassInfo
424{
425public:
426 constexpr inline QMetaClassInfo() : mobj(nullptr), data({ .d: nullptr }) {}
427 const char *name() const;
428 const char *value() const;
429 inline const QMetaObject *enclosingMetaObject() const { return mobj; }
430
431private:
432 struct Data {
433 enum { Size = 2 };
434
435 uint name() const { return d[0]; }
436 uint value() const { return d[1]; }
437
438 const uint *d;
439 };
440
441 const QMetaObject *mobj;
442 Data data;
443 friend struct QMetaObject;
444};
445Q_DECLARE_TYPEINFO(QMetaClassInfo, Q_RELOCATABLE_TYPE);
446
447QT_END_NAMESPACE
448
449#endif // QMETAOBJECT_H
450

source code of qtbase/src/corelib/kernel/qmetaobject.h