1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2015 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#include "qmetaobject.h"
6#include "qmetaobject_p.h"
7#include "qmetatype.h"
8#include "qmetatype_p.h"
9#include "qobject.h"
10#include "qobject_p.h"
11
12#include <qcoreapplication.h>
13#include <qvariant.h>
14
15// qthread(_p).h uses QT_CONFIG(thread) internally and has a dummy
16// interface for the non-thread support case
17#include <qthread.h>
18#include "private/qthread_p.h"
19#if QT_CONFIG(thread)
20#include <qsemaphore.h>
21#endif
22
23// for normalizeTypeInternal
24#include "private/qmetaobject_moc_p.h"
25
26#include <ctype.h>
27#include <memory>
28
29QT_BEGIN_NAMESPACE
30
31using namespace Qt::StringLiterals;
32
33/*!
34 \class QMetaObject
35 \inmodule QtCore
36
37 \brief The QMetaObject class contains meta-information about Qt
38 objects.
39
40 \ingroup objectmodel
41
42 The Qt \l{Meta-Object System} in Qt is responsible for the
43 signals and slots inter-object communication mechanism, runtime
44 type information, and the Qt property system. A single
45 QMetaObject instance is created for each QObject subclass that is
46 used in an application, and this instance stores all the
47 meta-information for the QObject subclass. This object is
48 available as QObject::metaObject().
49
50 This class is not normally required for application programming,
51 but it is useful if you write meta-applications, such as scripting
52 engines or GUI builders.
53
54 The functions you are most likely to find useful are these:
55 \list
56 \li className() returns the name of a class.
57 \li superClass() returns the superclass's meta-object.
58 \li method() and methodCount() provide information
59 about a class's meta-methods (signals, slots and other
60 \l{Q_INVOKABLE}{invokable} member functions).
61 \li enumerator() and enumeratorCount() and provide information about
62 a class's enumerators.
63 \li propertyCount() and property() provide information about a
64 class's properties.
65 \li constructor() and constructorCount() provide information
66 about a class's meta-constructors.
67 \endlist
68
69 The index functions indexOfConstructor(), indexOfMethod(),
70 indexOfEnumerator(), and indexOfProperty() map names of constructors,
71 member functions, enumerators, or properties to indexes in the
72 meta-object. For example, Qt uses indexOfMethod() internally when you
73 connect a signal to a slot.
74
75 Classes can also have a list of \e{name}--\e{value} pairs of
76 additional class information, stored in QMetaClassInfo objects.
77 The number of pairs is returned by classInfoCount(), single pairs
78 are returned by classInfo(), and you can search for pairs with
79 indexOfClassInfo().
80
81 \note Operations that use the meta object system are generally thread-
82 safe, as QMetaObjects are typically static read-only instances
83 generated at compile time. However, if meta objects are dynamically
84 modified by the application (for instance, when using QQmlPropertyMap),
85 then the application has to explicitly synchronize access to the
86 respective meta object.
87
88 \sa QMetaClassInfo, QMetaEnum, QMetaMethod, QMetaProperty, QMetaType,
89 {Meta-Object System}
90*/
91
92/*!
93 \enum QMetaObject::Call
94
95 \internal
96
97 \value InvokeMetaMethod
98 \value ReadProperty
99 \value WriteProperty
100 \value ResetProperty
101 \value CreateInstance
102 \value IndexOfMethod
103 \value RegisterPropertyMetaType
104 \value RegisterMethodArgumentMetaType
105 \value BindableProperty
106 \value CustomCall
107 \value ConstructInPlace
108*/
109
110/*!
111 \enum QMetaMethod::Access
112
113 This enum describes the access level of a method, following the conventions used in C++.
114
115 \value Private
116 \value Protected
117 \value Public
118*/
119
120static inline const QMetaObjectPrivate *priv(const uint* data)
121{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
122
123static inline const char *rawStringData(const QMetaObject *mo, int index)
124{
125 Q_ASSERT(priv(mo->d.data)->revision >= 7);
126 uint offset = mo->d.stringdata[2*index];
127 return reinterpret_cast<const char *>(mo->d.stringdata) + offset;
128}
129
130static inline QByteArrayView stringDataView(const QMetaObject *mo, int index)
131{
132 Q_ASSERT(priv(mo->d.data)->revision >= 7);
133 uint offset = mo->d.stringdata[2*index];
134 uint length = mo->d.stringdata[2*index + 1];
135 const char *string = reinterpret_cast<const char *>(mo->d.stringdata) + offset;
136 return {string, qsizetype(length)};
137}
138
139static inline QByteArray stringData(const QMetaObject *mo, int index)
140{
141 const auto view = stringDataView(mo, index);
142 return QByteArray::fromRawData(data: view.data(), size: view.size());
143}
144
145static inline QByteArrayView typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
146{
147 if (typeInfo & IsUnresolvedType)
148 return stringDataView(mo, index: typeInfo & TypeNameIndexMask);
149 else
150 return QByteArrayView(QMetaType(typeInfo).name());
151}
152
153static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo)
154{
155 if (!(typeInfo & IsUnresolvedType))
156 return typeInfo;
157 return QMetaType::fromName(name: rawStringData(mo, index: typeInfo & TypeNameIndexMask)).id();
158}
159
160static auto parse_scope(QByteArrayView qualifiedKey) noexcept
161{
162 struct R {
163 std::optional<QByteArrayView> scope;
164 QByteArrayView key;
165 };
166 if (qualifiedKey.startsWith(other: "QFlags<") && qualifiedKey.endsWith(c: '>'))
167 qualifiedKey.slice(pos: 7, n: qualifiedKey.length() - 8);
168 const auto scopePos = qualifiedKey.lastIndexOf(a: "::"_L1);
169 if (scopePos < 0)
170 return R{.scope: std::nullopt, .key: qualifiedKey};
171 else
172 return R{.scope: qualifiedKey.first(n: scopePos), .key: qualifiedKey.sliced(pos: scopePos + 2)};
173}
174
175namespace {
176class QMetaMethodPrivate : public QMetaMethodInvoker
177{
178public:
179 static const QMetaMethodPrivate *get(const QMetaMethod *q)
180 { return static_cast<const QMetaMethodPrivate *>(q); }
181
182 inline QByteArray signature() const;
183 inline QByteArray name() const;
184 inline int typesDataIndex() const;
185 inline const char *rawReturnTypeName() const;
186 inline int returnType() const;
187 inline int parameterCount() const;
188 inline int parametersDataIndex() const;
189 inline uint parameterTypeInfo(int index) const;
190 inline int parameterType(int index) const;
191 inline void getParameterTypes(int *types) const;
192 inline const QtPrivate::QMetaTypeInterface *returnMetaTypeInterface() const;
193 inline const QtPrivate::QMetaTypeInterface *const *parameterMetaTypeInterfaces() const;
194 inline QByteArray parameterTypeName(int index) const;
195 inline QList<QByteArray> parameterTypes() const;
196 inline QList<QByteArray> parameterNames() const;
197 inline QByteArray tag() const;
198 inline int ownMethodIndex() const;
199 inline int ownConstructorMethodIndex() const;
200
201private:
202 void checkMethodMetaTypeConsistency(const QtPrivate::QMetaTypeInterface *iface, int index) const;
203 QMetaMethodPrivate();
204};
205} // unnamed namespace
206
207enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
208
209#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
210/*!
211 \since 4.5
212 \obsolete [6.5] Please use the variadic overload of this function
213
214 Constructs a new instance of this class. You can pass up to ten arguments
215 (\a val0, \a val1, \a val2, \a val3, \a val4, \a val5, \a val6, \a val7,
216 \a val8, and \a val9) to the constructor. Returns the new object, or
217 \nullptr if no suitable constructor is available.
218
219 Note that only constructors that are declared with the Q_INVOKABLE
220 modifier are made available through the meta-object system.
221
222 \sa Q_ARG(), constructor()
223*/
224QObject *QMetaObject::newInstance(QGenericArgument val0,
225 QGenericArgument val1,
226 QGenericArgument val2,
227 QGenericArgument val3,
228 QGenericArgument val4,
229 QGenericArgument val5,
230 QGenericArgument val6,
231 QGenericArgument val7,
232 QGenericArgument val8,
233 QGenericArgument val9) const
234{
235 const char *typeNames[] = {
236 nullptr,
237 val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
238 val5.name(), val6.name(), val7.name(), val8.name(), val9.name()
239 };
240 const void *parameters[] = {
241 nullptr,
242 val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
243 val5.data(), val6.data(), val7.data(), val8.data(), val9.data()
244 };
245
246 int paramCount;
247 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
248 int len = int(qstrlen(str: typeNames[paramCount]));
249 if (len <= 0)
250 break;
251 }
252
253 return newInstanceImpl(mobj: this, parameterCount: paramCount, parameters, typeNames, metaTypes: nullptr);
254}
255#endif
256
257/*!
258 \fn template <typename... Args> QObject *QMetaObject::newInstance(Args &&... arguments) const
259 \since 6.5
260
261 Constructs a new instance of this class and returns the new object, or
262 \nullptr if no suitable constructor is available. The types of the
263 arguments \a arguments will be used to find a matching constructor, and then
264 forwarded to it the same way signal-slot connections do.
265
266 Note that only constructors that are declared with the Q_INVOKABLE
267 modifier are made available through the meta-object system.
268
269 \sa constructor()
270*/
271
272QObject *QMetaObject::newInstanceImpl(const QMetaObject *mobj, qsizetype paramCount,
273 const void **parameters, const char **typeNames,
274 const QtPrivate::QMetaTypeInterface **metaTypes)
275{
276 if (!mobj->inherits(metaObject: &QObject::staticMetaObject)) {
277 qWarning(msg: "QMetaObject::newInstance: type %s does not inherit QObject", mobj->className());
278 return nullptr;
279 }
280
281QT_WARNING_PUSH
282#if Q_CC_GNU >= 1200
283QT_WARNING_DISABLE_GCC("-Wdangling-pointer")
284#endif
285
286 // set the return type
287 QObject *returnValue = nullptr;
288 QMetaType returnValueMetaType = QMetaType::fromType<decltype(returnValue)>();
289 parameters[0] = &returnValue;
290 typeNames[0] = returnValueMetaType.name();
291 if (metaTypes)
292 metaTypes[0] = returnValueMetaType.iface();
293
294QT_WARNING_POP
295
296 // find the constructor
297 auto priv = QMetaObjectPrivate::get(metaobject: mobj);
298 for (int i = 0; i < priv->constructorCount; ++i) {
299 QMetaMethod m = QMetaMethod::fromRelativeConstructorIndex(mobj, index: i);
300 if (m.parameterCount() != (paramCount - 1))
301 continue;
302
303 // attempt to call
304 QMetaMethodPrivate::InvokeFailReason r =
305 QMetaMethodPrivate::invokeImpl(self: m, target: nullptr, Qt::DirectConnection, paramCount,
306 parameters, typeNames, metaTypes);
307 if (r == QMetaMethodPrivate::InvokeFailReason::None)
308 return returnValue;
309 if (int(r) < 0)
310 return nullptr;
311 }
312
313 return returnValue;
314}
315
316/*!
317 \internal
318*/
319int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
320{
321 Q_ASSERT(priv(d.data)->revision >= 6);
322 if (!d.static_metacall)
323 return 0;
324 d.static_metacall(nullptr, cl, idx, argv);
325 return -1;
326}
327
328/*!
329 \internal
330*/
331int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
332{
333 if (object->d_ptr->metaObject)
334 return object->d_ptr->metaObject->metaCall(object, cl, id: idx, argv);
335 else
336 return object->qt_metacall(cl, idx, argv);
337}
338
339static inline QByteArrayView objectClassName(const QMetaObject *m)
340{
341 return stringDataView(mo: m, index: priv(data: m->d.data)->className);
342}
343
344/*!
345 Returns the class name.
346
347 \sa superClass()
348*/
349const char *QMetaObject::className() const
350{
351 return objectClassName(m: this).constData();
352}
353
354/*!
355 \fn QMetaObject *QMetaObject::superClass() const
356
357 Returns the meta-object of the superclass, or \nullptr if there is
358 no such object.
359
360 \sa className()
361*/
362
363/*!
364 Returns \c true if the class described by this QMetaObject inherits
365 the type described by \a metaObject; otherwise returns false.
366
367 A type is considered to inherit itself.
368
369 \since 5.7
370*/
371bool QMetaObject::inherits(const QMetaObject *metaObject) const noexcept
372{
373 const QMetaObject *m = this;
374 do {
375 if (metaObject == m)
376 return true;
377 } while ((m = m->d.superdata));
378 return false;
379}
380
381/*!
382 \fn QObject *QMetaObject::cast(QObject *obj) const
383 \internal
384
385 Returns \a obj if object \a obj inherits from this
386 meta-object; otherwise returns \nullptr.
387*/
388
389/*!
390 \internal
391
392 Returns \a obj if object \a obj inherits from this
393 meta-object; otherwise returns \nullptr.
394*/
395const QObject *QMetaObject::cast(const QObject *obj) const
396{
397 return (obj && obj->metaObject()->inherits(metaObject: this)) ? obj : nullptr;
398}
399
400#ifndef QT_NO_TRANSLATION
401/*!
402 \internal
403*/
404QString QMetaObject::tr(const char *s, const char *c, int n) const
405{
406 return QCoreApplication::translate(context: className(), key: s, disambiguation: c, n);
407}
408#endif // QT_NO_TRANSLATION
409
410/*!
411 \since 6.2
412 Returns the metatype corresponding to this metaobject.
413 If the metaobject originates from a namespace, an invalid metatype is returned.
414 */
415QMetaType QMetaObject::metaType() const
416{
417
418 const QMetaObjectPrivate *d = priv(data: this->d.data);
419 if (d->revision < 10) {
420 // before revision 10, we did not store the metatype in the metatype array
421 return QMetaType::fromName(name: className());
422 } else {
423 /* in the metatype array, we store
424
425 | index | data |
426 |----------------------------------------------------------------------|
427 | 0 | QMetaType(property0) |
428 | ... | ... |
429 | propertyCount - 1 | QMetaType(propertyCount - 1) |
430 | propertyCount | QMetaType(enumerator0) |
431 | ... | ... |
432 | propertyCount + enumeratorCount - 1 | QMetaType(enumeratorCount - 1) |
433 | propertyCount + enumeratorCount | QMetaType(class) |
434
435 */
436#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
437 // Before revision 12 we only stored metatypes for enums if they showed
438 // up as types of properties or method arguments or return values.
439 // From revision 12 on, we always store them in a predictable place.
440 const qsizetype offset = d->revision < 12
441 ? d->propertyCount
442 : d->propertyCount + d->enumeratorCount;
443#else
444 const qsizetype offset = d->propertyCount + d->enumeratorCount;
445#endif
446
447 auto iface = this->d.metaTypes[offset];
448 if (iface && QtMetaTypePrivate::isInterfaceFor<void>(iface))
449 return QMetaType(); // return invalid meta-type for namespaces
450 if (iface)
451 return QMetaType(iface);
452 else // in case of a dynamic metaobject, we might have no metatype stored
453 return QMetaType::fromName(name: className()); // try lookup by name in that case
454 }
455}
456
457/*!
458 Returns the method offset for this class; i.e. the index position
459 of this class's first member function.
460
461 The offset is the sum of all the methods in the class's
462 superclasses (which is always positive since QObject has the
463 \l{QObject::}{deleteLater()} slot and a \l{QObject::}{destroyed()} signal).
464
465 \sa method(), methodCount(), indexOfMethod()
466*/
467int QMetaObject::methodOffset() const
468{
469 int offset = 0;
470 const QMetaObject *m = d.superdata;
471 while (m) {
472 offset += priv(data: m->d.data)->methodCount;
473 m = m->d.superdata;
474 }
475 return offset;
476}
477
478
479/*!
480 Returns the enumerator offset for this class; i.e. the index
481 position of this class's first enumerator.
482
483 If the class has no superclasses with enumerators, the offset is
484 0; otherwise the offset is the sum of all the enumerators in the
485 class's superclasses.
486
487 \sa enumerator(), enumeratorCount(), indexOfEnumerator()
488*/
489int QMetaObject::enumeratorOffset() const
490{
491 int offset = 0;
492 const QMetaObject *m = d.superdata;
493 while (m) {
494 offset += priv(data: m->d.data)->enumeratorCount;
495 m = m->d.superdata;
496 }
497 return offset;
498}
499
500/*!
501 Returns the property offset for this class; i.e. the index
502 position of this class's first property.
503
504 The offset is the sum of all the properties in the class's
505 superclasses (which is always positive since QObject has the
506 \l{QObject::}{objectName} property).
507
508 \sa property(), propertyCount(), indexOfProperty()
509*/
510int QMetaObject::propertyOffset() const
511{
512 int offset = 0;
513 const QMetaObject *m = d.superdata;
514 while (m) {
515 offset += priv(data: m->d.data)->propertyCount;
516 m = m->d.superdata;
517 }
518 return offset;
519}
520
521/*!
522 Returns the class information offset for this class; i.e. the
523 index position of this class's first class information item.
524
525 If the class has no superclasses with class information, the
526 offset is 0; otherwise the offset is the sum of all the class
527 information items in the class's superclasses.
528
529 \sa classInfo(), classInfoCount(), indexOfClassInfo()
530*/
531int QMetaObject::classInfoOffset() const
532{
533 int offset = 0;
534 const QMetaObject *m = d.superdata;
535 while (m) {
536 offset += priv(data: m->d.data)->classInfoCount;
537 m = m->d.superdata;
538 }
539 return offset;
540}
541
542/*!
543 \since 4.5
544
545 Returns the number of constructors in this class.
546
547 \sa constructor(), indexOfConstructor()
548*/
549int QMetaObject::constructorCount() const
550{
551 Q_ASSERT(priv(d.data)->revision >= 2);
552 return priv(data: d.data)->constructorCount;
553}
554
555/*!
556 Returns the number of methods in this class, including the number of
557 methods provided by each base class. These include signals and slots
558 as well as normal member functions.
559
560 Use code like the following to obtain a QStringList containing the methods
561 specific to a given class:
562
563 \snippet code/src_corelib_kernel_qmetaobject.cpp methodCount
564
565 \sa method(), methodOffset(), indexOfMethod()
566*/
567int QMetaObject::methodCount() const
568{
569 int n = priv(data: d.data)->methodCount;
570 const QMetaObject *m = d.superdata;
571 while (m) {
572 n += priv(data: m->d.data)->methodCount;
573 m = m->d.superdata;
574 }
575 return n;
576}
577
578/*!
579 Returns the number of enumerators in this class.
580
581 \sa enumerator(), enumeratorOffset(), indexOfEnumerator()
582*/
583int QMetaObject::enumeratorCount() const
584{
585 int n = priv(data: d.data)->enumeratorCount;
586 const QMetaObject *m = d.superdata;
587 while (m) {
588 n += priv(data: m->d.data)->enumeratorCount;
589 m = m->d.superdata;
590 }
591 return n;
592}
593
594/*!
595 Returns the number of properties in this class, including the number of
596 properties provided by each base class.
597
598 Use code like the following to obtain a QStringList containing the properties
599 specific to a given class:
600
601 \snippet code/src_corelib_kernel_qmetaobject.cpp propertyCount
602
603 \sa property(), propertyOffset(), indexOfProperty()
604*/
605int QMetaObject::propertyCount() const
606{
607 int n = priv(data: d.data)->propertyCount;
608 const QMetaObject *m = d.superdata;
609 while (m) {
610 n += priv(data: m->d.data)->propertyCount;
611 m = m->d.superdata;
612 }
613 return n;
614}
615
616/*!
617 Returns the number of items of class information in this class.
618
619 \sa classInfo(), classInfoOffset(), indexOfClassInfo()
620*/
621int QMetaObject::classInfoCount() const
622{
623 int n = priv(data: d.data)->classInfoCount;
624 const QMetaObject *m = d.superdata;
625 while (m) {
626 n += priv(data: m->d.data)->classInfoCount;
627 m = m->d.superdata;
628 }
629 return n;
630}
631
632// Returns \c true if the method defined by the given meta-object&meta-method
633// matches the given name, argument count and argument types, otherwise
634// returns \c false.
635bool QMetaObjectPrivate::methodMatch(const QMetaObject *m, const QMetaMethod &method,
636 const QByteArray &name, int argc,
637 const QArgumentType *types)
638{
639 const QMetaMethod::Data &data = method.data;
640 auto priv = QMetaMethodPrivate::get(q: &method);
641 if (priv->parameterCount() != argc)
642 return false;
643
644 if (stringData(mo: m, index: data.name()) != name)
645 return false;
646
647 const QtPrivate::QMetaTypeInterface * const *ifaces = priv->parameterMetaTypeInterfaces();
648 int paramsIndex = data.parameters() + 1;
649 for (int i = 0; i < argc; ++i) {
650 uint typeInfo = m->d.data[paramsIndex + i];
651 if (int id = types[i].type()) {
652 if (id == QMetaType(ifaces[i]).id())
653 continue;
654 if (id != typeFromTypeInfo(mo: m, typeInfo))
655 return false;
656 } else {
657 if (types[i].name() == QMetaType(ifaces[i]).name())
658 continue;
659 if (types[i].name() != typeNameFromTypeInfo(mo: m, typeInfo))
660 return false;
661 }
662 }
663
664 return true;
665}
666
667/*!
668 \internal
669 Returns the first method with name \a name found in \a baseObject
670 */
671QMetaMethod QMetaObjectPrivate::firstMethod(const QMetaObject *baseObject, QByteArrayView name)
672{
673 for (const QMetaObject *currentObject = baseObject; currentObject; currentObject = currentObject->superClass()) {
674 const int start = priv(data: currentObject->d.data)->methodCount - 1;
675 const int end = 0;
676 for (int i = start; i >= end; --i) {
677 auto candidate = QMetaMethod::fromRelativeMethodIndex(mobj: currentObject, index: i);
678 if (name == candidate.name())
679 return candidate;
680 }
681 }
682 return QMetaMethod{};
683}
684
685/**
686* \internal
687* helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within
688* the baseObject
689* \a MethodType might be MethodSignal or MethodSlot, or \nullptr to match everything.
690*/
691template<int MethodType>
692inline int QMetaObjectPrivate::indexOfMethodRelative(const QMetaObject **baseObject,
693 const QByteArray &name, int argc,
694 const QArgumentType *types)
695{
696 for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {
697 Q_ASSERT(priv(m->d.data)->revision >= 7);
698 int i = (MethodType == MethodSignal)
699 ? (priv(data: m->d.data)->signalCount - 1) : (priv(data: m->d.data)->methodCount - 1);
700 const int end = (MethodType == MethodSlot)
701 ? (priv(data: m->d.data)->signalCount) : 0;
702
703 for (; i >= end; --i) {
704 auto data = QMetaMethod::fromRelativeMethodIndex(mobj: m, index: i);
705 if (methodMatch(m, method: data, name, argc, types)) {
706 *baseObject = m;
707 return i;
708 }
709 }
710 }
711 return -1;
712}
713
714
715/*!
716 \since 4.5
717
718 Finds \a constructor and returns its index; otherwise returns -1.
719
720 Note that the \a constructor has to be in normalized form, as returned
721 by normalizedSignature().
722
723 \sa constructor(), constructorCount(), normalizedSignature()
724*/
725int QMetaObject::indexOfConstructor(const char *constructor) const
726{
727 Q_ASSERT(priv(d.data)->revision >= 7);
728 QArgumentTypeArray types;
729 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signature: constructor, types);
730 return QMetaObjectPrivate::indexOfConstructor(m: this, name, argc: types.size(), types: types.constData());
731}
732
733/*!
734 Finds \a method and returns its index; otherwise returns -1.
735
736 Note that the \a method has to be in normalized form, as returned
737 by normalizedSignature().
738
739 \sa method(), methodCount(), methodOffset(), normalizedSignature()
740*/
741int QMetaObject::indexOfMethod(const char *method) const
742{
743 const QMetaObject *m = this;
744 int i;
745 Q_ASSERT(priv(m->d.data)->revision >= 7);
746 QArgumentTypeArray types;
747 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signature: method, types);
748 i = QMetaObjectPrivate::indexOfMethodRelative<0>(baseObject: &m, name, argc: types.size(), types: types.constData());
749 if (i >= 0)
750 i += m->methodOffset();
751 return i;
752}
753
754// Parses a string of comma-separated types into QArgumentTypes.
755// No normalization of the type names is performed.
756static void argumentTypesFromString(const char *str, const char *end,
757 QArgumentTypeArray &types)
758{
759 Q_ASSERT(str <= end);
760 while (str != end) {
761 if (!types.isEmpty())
762 ++str; // Skip comma
763 const char *begin = str;
764 int level = 0;
765 while (str != end && (level > 0 || *str != ',')) {
766 if (*str == '<')
767 ++level;
768 else if (*str == '>')
769 --level;
770 ++str;
771 }
772 QByteArray argType(begin, str - begin);
773 argType.replace(before: "QVector<", after: "QList<");
774 types += QArgumentType(std::move(argType));
775 }
776}
777
778// Given a method \a signature (e.g. "foo(int,double)"), this function
779// populates the argument \a types array and returns the method name.
780QByteArray QMetaObjectPrivate::decodeMethodSignature(
781 const char *signature, QArgumentTypeArray &types)
782{
783 Q_ASSERT(signature != nullptr);
784 const char *lparens = strchr(s: signature, c: '(');
785 if (!lparens)
786 return QByteArray();
787 const char *rparens = strrchr(s: lparens + 1, c: ')');
788 if (!rparens || *(rparens+1))
789 return QByteArray();
790 int nameLength = lparens - signature;
791 argumentTypesFromString(str: lparens + 1, end: rparens, types);
792 return QByteArray::fromRawData(data: signature, size: nameLength);
793}
794
795/*!
796 Finds \a signal and returns its index; otherwise returns -1.
797
798 This is the same as indexOfMethod(), except that it will return
799 -1 if the method exists but isn't a signal.
800
801 Note that the \a signal has to be in normalized form, as returned
802 by normalizedSignature().
803
804 \sa indexOfMethod(), normalizedSignature(), method(), methodCount(), methodOffset()
805*/
806int QMetaObject::indexOfSignal(const char *signal) const
807{
808 const QMetaObject *m = this;
809 int i;
810 Q_ASSERT(priv(m->d.data)->revision >= 7);
811 QArgumentTypeArray types;
812 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signature: signal, types);
813 i = QMetaObjectPrivate::indexOfSignalRelative(baseObject: &m, name, argc: types.size(), types: types.constData());
814 if (i >= 0)
815 i += m->methodOffset();
816 return i;
817}
818
819/*!
820 \internal
821 Same as QMetaObject::indexOfSignal, but the result is the local offset to the base object.
822
823 \a baseObject will be adjusted to the enclosing QMetaObject, or \nullptr if the signal is not found
824*/
825int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
826 const QByteArray &name, int argc,
827 const QArgumentType *types)
828{
829 int i = indexOfMethodRelative<MethodSignal>(baseObject, name, argc, types);
830#ifndef QT_NO_DEBUG
831 const QMetaObject *m = *baseObject;
832 if (i >= 0 && m && m->d.superdata) {
833 int conflict = indexOfMethod(m: m->d.superdata, name, argc, types);
834 if (conflict >= 0) {
835 QMetaMethod conflictMethod = m->d.superdata->method(index: conflict);
836 qWarning(msg: "QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
837 conflictMethod.methodSignature().constData(),
838 m->d.superdata->className(), m->className());
839 }
840 }
841 #endif
842 return i;
843}
844
845/*!
846 Finds \a slot and returns its index; otherwise returns -1.
847
848 This is the same as indexOfMethod(), except that it will return
849 -1 if the method exists but isn't a slot.
850
851 \sa indexOfMethod(), method(), methodCount(), methodOffset()
852*/
853int QMetaObject::indexOfSlot(const char *slot) const
854{
855 const QMetaObject *m = this;
856 int i;
857 Q_ASSERT(priv(m->d.data)->revision >= 7);
858 QArgumentTypeArray types;
859 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signature: slot, types);
860 i = QMetaObjectPrivate::indexOfSlotRelative(m: &m, name, argc: types.size(), types: types.constData());
861 if (i >= 0)
862 i += m->methodOffset();
863 return i;
864}
865
866// same as indexOfSignalRelative but for slots.
867int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m,
868 const QByteArray &name, int argc,
869 const QArgumentType *types)
870{
871 return indexOfMethodRelative<MethodSlot>(baseObject: m, name, argc, types);
872}
873
874int QMetaObjectPrivate::indexOfSignal(const QMetaObject *m, const QByteArray &name,
875 int argc, const QArgumentType *types)
876{
877 int i = indexOfSignalRelative(baseObject: &m, name, argc, types);
878 if (i >= 0)
879 i += m->methodOffset();
880 return i;
881}
882
883int QMetaObjectPrivate::indexOfSlot(const QMetaObject *m, const QByteArray &name,
884 int argc, const QArgumentType *types)
885{
886 int i = indexOfSlotRelative(m: &m, name, argc, types);
887 if (i >= 0)
888 i += m->methodOffset();
889 return i;
890}
891
892int QMetaObjectPrivate::indexOfMethod(const QMetaObject *m, const QByteArray &name,
893 int argc, const QArgumentType *types)
894{
895 int i = indexOfMethodRelative<0>(baseObject: &m, name, argc, types);
896 if (i >= 0)
897 i += m->methodOffset();
898 return i;
899}
900
901int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArray &name,
902 int argc, const QArgumentType *types)
903{
904 for (int i = priv(data: m->d.data)->constructorCount-1; i >= 0; --i) {
905 const QMetaMethod method = QMetaMethod::fromRelativeConstructorIndex(mobj: m, index: i);
906 if (methodMatch(m, method, name, argc, types))
907 return i;
908 }
909 return -1;
910}
911
912/*!
913 \fn int QMetaObjectPrivate::signalOffset(const QMetaObject *m)
914 \internal
915 \since 5.0
916
917 Returns the signal offset for the class \a m; i.e., the index position
918 of the class's first signal.
919
920 Similar to QMetaObject::methodOffset(), but non-signal methods are
921 excluded.
922*/
923
924/*!
925 \internal
926 \since 5.0
927
928 Returns the number of signals for the class \a m, including the signals
929 for the base class.
930
931 Similar to QMetaObject::methodCount(), but non-signal methods are
932 excluded.
933*/
934int QMetaObjectPrivate::absoluteSignalCount(const QMetaObject *m)
935{
936 Q_ASSERT(m != nullptr);
937 int n = priv(data: m->d.data)->signalCount;
938 for (m = m->d.superdata; m; m = m->d.superdata)
939 n += priv(data: m->d.data)->signalCount;
940 return n;
941}
942
943/*!
944 \internal
945 \since 5.0
946
947 Returns the index of the signal method \a m.
948
949 Similar to QMetaMethod::methodIndex(), but non-signal methods are
950 excluded.
951*/
952int QMetaObjectPrivate::signalIndex(const QMetaMethod &m)
953{
954 if (!m.mobj)
955 return -1;
956 return QMetaMethodPrivate::get(q: &m)->ownMethodIndex() + signalOffset(m: m.mobj);
957}
958
959/*!
960 \internal
961 \since 5.0
962
963 Returns the signal for the given meta-object \a m at \a signal_index.
964
965 It it different from QMetaObject::method(); the index should not include
966 non-signal methods.
967*/
968QMetaMethod QMetaObjectPrivate::signal(const QMetaObject *m, int signal_index)
969{
970 if (signal_index < 0)
971 return QMetaMethod();
972
973 Q_ASSERT(m != nullptr);
974 int i = signal_index;
975 i -= signalOffset(m);
976 if (i < 0 && m->d.superdata)
977 return signal(m: m->d.superdata, signal_index);
978
979
980 if (i >= 0 && i < priv(data: m->d.data)->signalCount)
981 return QMetaMethod::fromRelativeMethodIndex(mobj: m, index: i);
982 return QMetaMethod();
983}
984
985/*!
986 \internal
987
988 Returns \c true if the \a signalTypes and \a methodTypes are
989 compatible; otherwise returns \c false.
990*/
991bool QMetaObjectPrivate::checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
992 int methodArgc, const QArgumentType *methodTypes)
993{
994 if (signalArgc < methodArgc)
995 return false;
996 for (int i = 0; i < methodArgc; ++i) {
997 if (signalTypes[i] != methodTypes[i])
998 return false;
999 }
1000 return true;
1001}
1002
1003/*!
1004 \internal
1005
1006 Returns \c true if the \a signal and \a method arguments are
1007 compatible; otherwise returns \c false.
1008*/
1009bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
1010 const QMetaMethodPrivate *method)
1011{
1012 if (signal->methodType() != QMetaMethod::Signal)
1013 return false;
1014 if (signal->parameterCount() < method->parameterCount())
1015 return false;
1016 const QMetaObject *smeta = signal->enclosingMetaObject();
1017 const QMetaObject *rmeta = method->enclosingMetaObject();
1018 for (int i = 0; i < method->parameterCount(); ++i) {
1019 uint sourceTypeInfo = signal->parameterTypeInfo(index: i);
1020 uint targetTypeInfo = method->parameterTypeInfo(index: i);
1021 if ((sourceTypeInfo & IsUnresolvedType)
1022 || (targetTypeInfo & IsUnresolvedType)) {
1023 QByteArrayView sourceName = typeNameFromTypeInfo(mo: smeta, typeInfo: sourceTypeInfo);
1024 QByteArrayView targetName = typeNameFromTypeInfo(mo: rmeta, typeInfo: targetTypeInfo);
1025 if (sourceName != targetName)
1026 return false;
1027 } else {
1028 int sourceType = typeFromTypeInfo(mo: smeta, typeInfo: sourceTypeInfo);
1029 int targetType = typeFromTypeInfo(mo: rmeta, typeInfo: targetTypeInfo);
1030 if (sourceType != targetType)
1031 return false;
1032 }
1033 }
1034 return true;
1035}
1036
1037static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, QByteArrayView name)
1038{
1039 while (self) {
1040 if (objectClassName(m: self) == name)
1041 return self;
1042 if (self->d.relatedMetaObjects) {
1043 Q_ASSERT(priv(self->d.data)->revision >= 2);
1044 const auto *e = self->d.relatedMetaObjects;
1045 if (e) {
1046 while (*e) {
1047 if (const QMetaObject *m =QMetaObject_findMetaObject(self: (*e), name))
1048 return m;
1049 ++e;
1050 }
1051 }
1052 }
1053 self = self->d.superdata;
1054 }
1055 return self;
1056}
1057
1058/*!
1059 Finds enumerator \a name and returns its index; otherwise returns
1060 -1.
1061
1062 \sa enumerator(), enumeratorCount(), enumeratorOffset()
1063*/
1064int QMetaObject::indexOfEnumerator(const char *name) const
1065{
1066 return QMetaObjectPrivate::indexOfEnumerator(m: this, name);
1067}
1068
1069int QMetaObjectPrivate::indexOfEnumerator(const QMetaObject *m, QByteArrayView name)
1070{
1071 using W = QMetaObjectPrivate::Which;
1072 for (auto which : { W::Name, W::Alias }) {
1073 if (int index = indexOfEnumerator(m, name, which); index != -1)
1074 return index;
1075 }
1076 return -1;
1077}
1078
1079int QMetaObjectPrivate::indexOfEnumerator(const QMetaObject *m, QByteArrayView name, Which which)
1080{
1081 while (m) {
1082 const QMetaObjectPrivate *d = priv(data: m->d.data);
1083 for (int i = 0; i < d->enumeratorCount; ++i) {
1084 const QMetaEnum e(m, i);
1085 const quint32 id = which == Which::Name ? e.data.name() : e.data.alias();
1086 QByteArrayView prop = stringDataView(mo: m, index: id);
1087 if (name == prop) {
1088 i += m->enumeratorOffset();
1089 return i;
1090 }
1091 }
1092 m = m->d.superdata;
1093 }
1094 return -1;
1095}
1096
1097/*!
1098 Finds property \a name and returns its index; otherwise returns
1099 -1.
1100
1101 \sa property(), propertyCount(), propertyOffset()
1102*/
1103int QMetaObject::indexOfProperty(const char *name) const
1104{
1105 const QMetaObject *m = this;
1106 while (m) {
1107 const QMetaObjectPrivate *d = priv(data: m->d.data);
1108 for (int i = 0; i < d->propertyCount; ++i) {
1109 const QMetaProperty::Data data = QMetaProperty::getMetaPropertyData(mobj: m, index: i);
1110 const char *prop = rawStringData(mo: m, index: data.name());
1111 if (strcmp(s1: name, s2: prop) == 0) {
1112 i += m->propertyOffset();
1113 return i;
1114 }
1115 }
1116 m = m->d.superdata;
1117 }
1118
1119 if (priv(data: this->d.data)->flags & DynamicMetaObject) {
1120 QAbstractDynamicMetaObject *me =
1121 const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
1122
1123 return me->createProperty(name, nullptr);
1124 }
1125
1126 return -1;
1127}
1128
1129/*!
1130 Finds class information item \a name and returns its index;
1131 otherwise returns -1.
1132
1133 \sa classInfo(), classInfoCount(), classInfoOffset()
1134*/
1135int QMetaObject::indexOfClassInfo(const char *name) const
1136{
1137 int i = -1;
1138 const QMetaObject *m = this;
1139 while (m && i < 0) {
1140 for (i = priv(data: m->d.data)->classInfoCount-1; i >= 0; --i)
1141 if (strcmp(s1: name, s2: rawStringData(mo: m, index: m->d.data[priv(data: m->d.data)->classInfoData + 2*i])) == 0) {
1142 i += m->classInfoOffset();
1143 break;
1144 }
1145 m = m->d.superdata;
1146 }
1147 return i;
1148}
1149
1150/*!
1151 \since 4.5
1152
1153 Returns the meta-data for the constructor with the given \a index.
1154
1155 \sa constructorCount(), newInstance()
1156*/
1157QMetaMethod QMetaObject::constructor(int index) const
1158{
1159 int i = index;
1160 if (i >= 0 && i < priv(data: d.data)->constructorCount)
1161 return QMetaMethod::fromRelativeConstructorIndex(mobj: this, index: i);
1162 return QMetaMethod();
1163}
1164
1165/*!
1166 Returns the meta-data for the method with the given \a index.
1167
1168 \sa methodCount(), methodOffset(), indexOfMethod()
1169*/
1170QMetaMethod QMetaObject::method(int index) const
1171{
1172 int i = index;
1173 i -= methodOffset();
1174 if (i < 0 && d.superdata)
1175 return d.superdata->method(index);
1176
1177 if (i >= 0 && i < priv(data: d.data)->methodCount)
1178 return QMetaMethod::fromRelativeMethodIndex(mobj: this, index: i);
1179 return QMetaMethod();
1180}
1181
1182/*!
1183 Returns the meta-data for the enumerator with the given \a index.
1184
1185 \sa enumeratorCount(), enumeratorOffset(), indexOfEnumerator()
1186*/
1187QMetaEnum QMetaObject::enumerator(int index) const
1188{
1189 int i = index;
1190 i -= enumeratorOffset();
1191 if (i < 0 && d.superdata)
1192 return d.superdata->enumerator(index);
1193
1194 if (i >= 0 && i < priv(data: d.data)->enumeratorCount)
1195 return QMetaEnum(this, i);
1196 return QMetaEnum();
1197}
1198
1199/*!
1200 Returns the meta-data for the property with the given \a index.
1201 If no such property exists, a null QMetaProperty is returned.
1202
1203 \sa propertyCount(), propertyOffset(), indexOfProperty()
1204*/
1205QMetaProperty QMetaObject::property(int index) const
1206{
1207 int i = index;
1208 i -= propertyOffset();
1209 if (i < 0 && d.superdata)
1210 return d.superdata->property(index);
1211
1212 if (i >= 0 && i < priv(data: d.data)->propertyCount)
1213 return QMetaProperty(this, i);
1214 return QMetaProperty();
1215}
1216
1217/*!
1218 \since 4.2
1219
1220 Returns the property that has the \c USER flag set to true.
1221
1222 \sa QMetaProperty::isUser()
1223*/
1224QMetaProperty QMetaObject::userProperty() const
1225{
1226 const int propCount = propertyCount();
1227 for (int i = propCount - 1; i >= 0; --i) {
1228 const QMetaProperty prop = property(index: i);
1229 if (prop.isUser())
1230 return prop;
1231 }
1232 return QMetaProperty();
1233}
1234
1235/*!
1236 Returns the meta-data for the item of class information with the
1237 given \a index.
1238
1239 Example:
1240
1241 \snippet code/src_corelib_kernel_qmetaobject.cpp 0
1242
1243 \sa classInfoCount(), classInfoOffset(), indexOfClassInfo()
1244 */
1245QMetaClassInfo QMetaObject::classInfo(int index) const
1246{
1247 int i = index;
1248 i -= classInfoOffset();
1249 if (i < 0 && d.superdata)
1250 return d.superdata->classInfo(index);
1251
1252 QMetaClassInfo result;
1253 if (i >= 0 && i < priv(data: d.data)->classInfoCount) {
1254 result.mobj = this;
1255 result.data = { .d: d.data + priv(data: d.data)->classInfoData + i * QMetaClassInfo::Data::Size };
1256 }
1257 return result;
1258}
1259
1260/*!
1261 Returns \c true if the \a signal and \a method arguments are
1262 compatible; otherwise returns \c false.
1263
1264 Both \a signal and \a method are expected to be normalized.
1265
1266 \sa normalizedSignature()
1267*/
1268bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
1269{
1270 const char *s1 = signal;
1271 const char *s2 = method;
1272 while (*s1++ != '(') { } // scan to first '('
1273 while (*s2++ != '(') { }
1274 if (*s2 == ')' || qstrcmp(str1: s1,str2: s2) == 0) // method has no args or
1275 return true; // exact match
1276 const auto s1len = qstrlen(str: s1);
1277 const auto s2len = qstrlen(str: s2);
1278 if (s2len < s1len && strncmp(s1: s1,s2: s2,n: s2len-1)==0 && s1[s2len-1]==',')
1279 return true; // method has less args
1280 return false;
1281}
1282
1283/*!
1284 \since 5.0
1285 \overload
1286
1287 Returns \c true if the \a signal and \a method arguments are
1288 compatible; otherwise returns \c false.
1289*/
1290bool QMetaObject::checkConnectArgs(const QMetaMethod &signal,
1291 const QMetaMethod &method)
1292{
1293 return QMetaObjectPrivate::checkConnectArgs(
1294 signal: QMetaMethodPrivate::get(q: &signal),
1295 method: QMetaMethodPrivate::get(q: &method));
1296}
1297
1298static void qRemoveWhitespace(const char *s, char *d)
1299{
1300 char last = 0;
1301 while (*s && is_space(s: *s))
1302 s++;
1303 while (*s) {
1304 while (*s && !is_space(s: *s))
1305 last = *d++ = *s++;
1306 while (*s && is_space(s: *s))
1307 s++;
1308 if (*s && ((is_ident_char(s: *s) && is_ident_char(s: last))
1309 || ((*s == ':') && (last == '<')))) {
1310 last = *d++ = ' ';
1311 }
1312 }
1313 *d = '\0';
1314}
1315
1316static char *qNormalizeType(char *d, int &templdepth, QByteArray &result)
1317{
1318 const char *t = d;
1319 while (*d && (templdepth
1320 || (*d != ',' && *d != ')'))) {
1321 if (*d == '<')
1322 ++templdepth;
1323 if (*d == '>')
1324 --templdepth;
1325 ++d;
1326 }
1327 // "void" should only be removed if this is part of a signature that has
1328 // an explicit void argument; e.g., "void foo(void)" --> "void foo()"
1329 if (strncmp(s1: "void)", s2: t, n: d - t + 1) != 0)
1330 result += normalizeTypeInternal(t, e: d);
1331
1332 return d;
1333}
1334
1335
1336/*!
1337 \since 4.2
1338
1339 Normalizes a \a type.
1340
1341 See QMetaObject::normalizedSignature() for a description on how
1342 Qt normalizes.
1343
1344 Example:
1345
1346 \snippet code/src_corelib_kernel_qmetaobject.cpp 1
1347
1348 \sa normalizedSignature()
1349 */
1350QByteArray QMetaObject::normalizedType(const char *type)
1351{
1352 return normalizeTypeInternal(t: type, e: type + qstrlen(str: type));
1353}
1354
1355/*!
1356 Normalizes the signature of the given \a method.
1357
1358 Qt uses normalized signatures to decide whether two given signals
1359 and slots are compatible. Normalization reduces whitespace to a
1360 minimum, moves 'const' to the front where appropriate, removes
1361 'const' from value types and replaces const references with
1362 values.
1363
1364 \sa checkConnectArgs(), normalizedType()
1365 */
1366QByteArray QMetaObject::normalizedSignature(const char *method)
1367{
1368 QByteArray result;
1369 if (!method || !*method)
1370 return result;
1371 int len = int(strlen(s: method));
1372 QVarLengthArray<char> stackbuf(len + 1);
1373 char *d = stackbuf.data();
1374 qRemoveWhitespace(s: method, d);
1375
1376 result.reserve(asize: len);
1377
1378 int argdepth = 0;
1379 int templdepth = 0;
1380 while (*d) {
1381 if (argdepth == 1) {
1382 d = qNormalizeType(d, templdepth, result);
1383 if (!*d) //most likely an invalid signature.
1384 break;
1385 }
1386 if (*d == '(')
1387 ++argdepth;
1388 if (*d == ')')
1389 --argdepth;
1390 result += *d++;
1391 }
1392
1393 return result;
1394}
1395
1396Q_DECL_COLD_FUNCTION static inline bool
1397printMethodNotFoundWarning(const QMetaObject *meta, QByteArrayView name, qsizetype paramCount,
1398 const char *const *names,
1399 const QtPrivate::QMetaTypeInterface * const *metaTypes)
1400{
1401 // now find the candidates we couldn't use
1402 QByteArray candidateMessage;
1403 for (int i = 0; i < meta->methodCount(); ++i) {
1404 const QMetaMethod method = meta->method(index: i);
1405 if (method.name() == name)
1406 candidateMessage += " " + method.methodSignature() + '\n';
1407 }
1408 if (!candidateMessage.isEmpty()) {
1409 candidateMessage.prepend(s: "\nCandidates are:\n");
1410 candidateMessage.chop(n: 1);
1411 }
1412
1413 QVarLengthArray<char, 512> sig;
1414 for (qsizetype i = 1; i < paramCount; ++i) {
1415 if (names[i])
1416 sig.append(buf: names[i], sz: qstrlen(str: names[i]));
1417 else
1418 sig.append(buf: metaTypes[i]->name, sz: qstrlen(str: metaTypes[i]->name));
1419 sig.append(t: ',');
1420 }
1421 if (paramCount != 1)
1422 sig.resize(sz: sig.size() - 1);
1423
1424 qWarning(msg: "QMetaObject::invokeMethod: No such method %s::%.*s(%.*s)%.*s",
1425 meta->className(), int(name.size()), name.constData(),
1426 int(sig.size()), sig.constData(),
1427 int(candidateMessage.size()), candidateMessage.constData());
1428 return false;
1429}
1430
1431/*!
1432 \fn template <typename ReturnArg, typename... Args> bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... args)
1433 \fn template <typename ReturnArg, typename... Args> bool QMetaObject::invokeMethod(QObject *obj, const char *member, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... args)
1434 \fn template <typename... Args> bool QMetaObject::invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, Args &&... args)
1435 \fn template <typename... Args> bool QMetaObject::invokeMethod(QObject *obj, const char *member, Args &&... args)
1436 \since 6.5
1437 \threadsafe
1438
1439 Invokes the \a member (a signal or a slot name) on the object \a
1440 obj. Returns \c true if the member could be invoked. Returns \c false
1441 if there is no such member or the parameters did not match.
1442
1443 For the overloads with a QTemplatedMetaMethodReturnArgument parameter, the
1444 return value of the \a member function call is placed in \a ret. For the
1445 overloads without such a member, the return value of the called function
1446 (if any) will be discarded. QTemplatedMetaMethodReturnArgument is an
1447 internal type you should not use directly. Instead, use the qReturnArg()
1448 function.
1449
1450 The overloads with a Qt::ConnectionType \a type parameter allow explicitly
1451 selecting whether the invocation will be synchronous or not:
1452
1453 \list
1454 \li If \a type is Qt::DirectConnection, the member will be invoked immediately
1455 in the current thread.
1456
1457 \li If \a type is Qt::QueuedConnection, a QEvent will be sent and the
1458 member is invoked as soon as the application enters the event loop in the
1459 thread that the \a obj was created in or was moved to.
1460
1461 \li If \a type is Qt::BlockingQueuedConnection, the method will be invoked in
1462 the same way as for Qt::QueuedConnection, except that the current thread
1463 will block until the event is delivered. Using this connection type to
1464 communicate between objects in the same thread will lead to deadlocks.
1465
1466 \li If \a type is Qt::AutoConnection, the member is invoked synchronously
1467 if \a obj lives in the same thread as the caller; otherwise it will invoke
1468 the member asynchronously. This is the behavior of the overloads that do
1469 not have the \a type parameter.
1470 \endlist
1471
1472 You only need to pass the name of the signal or slot to this function,
1473 not the entire signature. For example, to asynchronously invoke
1474 the \l{QThread::quit()}{quit()} slot on a
1475 QThread, use the following code:
1476
1477 \snippet code/src_corelib_kernel_qmetaobject.cpp 2
1478
1479 With asynchronous method invocations, the parameters must be copyable
1480 types, because Qt needs to copy the arguments to store them in an event
1481 behind the scenes. Since Qt 6.5, this function automatically registers the
1482 types being used; however, as a side-effect, it is not possible to make
1483 calls using types that are only forward-declared. Additionally, it is not
1484 possible to make asynchronous calls that use references to
1485 non-const-qualified types as parameters either.
1486
1487 To synchronously invoke the \c compute(QString, int, double) slot on
1488 some arbitrary object \c obj retrieve its return value:
1489
1490 \snippet code/src_corelib_kernel_qmetaobject.cpp invokemethod-no-macro
1491
1492 If the "compute" slot does not take exactly one \l QString, one \c int, and
1493 one \c double in the specified order, the call will fail. Note how it was
1494 necessary to be explicit about the type of the QString, as the character
1495 literal is not exactly the right type to match. If the method instead took
1496 a \l QStringView, a \l qsizetype, and a \c float, the call would need to be
1497 written as:
1498
1499 \snippet code/src_corelib_kernel_qmetaobject.cpp invokemethod-no-macro-other-types
1500
1501 The same call can be executed using the Q_ARG() and Q_RETURN_ARG() macros,
1502 as in:
1503
1504 \snippet code/src_corelib_kernel_qmetaobject.cpp 4
1505
1506 The macros are kept for compatibility with Qt 6.4 and earlier versions, and
1507 can be freely mixed with parameters that do not use the macro. They may be
1508 necessary in rare situations when calling a method that used a typedef to
1509 forward-declared type as a parameter or the return type.
1510
1511 \sa Q_ARG(), Q_RETURN_ARG(), QMetaMethod::invoke()
1512*/
1513
1514/*!
1515 \threadsafe
1516 \overload
1517 \obsolete [6.5] Please use the variadic overload of this function
1518
1519 Invokes the \a member (a signal or a slot name) on the object \a
1520 obj. Returns \c true if the member could be invoked. Returns \c false
1521 if there is no such member or the parameters did not match.
1522
1523 See the variadic invokeMethod() function for more information. This
1524 function should behave the same way as that one, with the following
1525 limitations:
1526
1527 \list
1528 \li The number of parameters is limited to 10.
1529 \li Parameter names may need to be an exact string match.
1530 \li Meta types are not automatically registered.
1531 \endlist
1532
1533 With asynchronous method invocations, the parameters must be of
1534 types that are already known to Qt's meta-object system, because Qt needs
1535 to copy the arguments to store them in an event behind the
1536 scenes. If you try to use a queued connection and get the error
1537 message
1538
1539 \snippet code/src_corelib_kernel_qmetaobject.cpp 3
1540
1541 call qRegisterMetaType() to register the data type before you
1542 call invokeMethod().
1543
1544 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaMethod::invoke()
1545*/
1546bool QMetaObject::invokeMethod(QObject *obj,
1547 const char *member,
1548 Qt::ConnectionType type,
1549 QGenericReturnArgument ret,
1550 QGenericArgument val0,
1551 QGenericArgument val1,
1552 QGenericArgument val2,
1553 QGenericArgument val3,
1554 QGenericArgument val4,
1555 QGenericArgument val5,
1556 QGenericArgument val6,
1557 QGenericArgument val7,
1558 QGenericArgument val8,
1559 QGenericArgument val9)
1560{
1561 if (!obj)
1562 return false;
1563
1564 const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(),
1565 val4.name(), val5.name(), val6.name(), val7.name(), val8.name(),
1566 val9.name()};
1567 const void *parameters[] = {ret.data(), val0.data(), val1.data(), val2.data(), val3.data(),
1568 val4.data(), val5.data(), val6.data(), val7.data(), val8.data(),
1569 val9.data()};
1570 int paramCount;
1571 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
1572 if (qstrlen(str: typeNames[paramCount]) <= 0)
1573 break;
1574 }
1575 return invokeMethodImpl(object: obj, member, type, parameterCount: paramCount, parameters, names: typeNames, metaTypes: nullptr);
1576}
1577
1578bool QMetaObject::invokeMethodImpl(QObject *obj, const char *member, Qt::ConnectionType type,
1579 qsizetype paramCount, const void * const *parameters,
1580 const char * const *typeNames,
1581 const QtPrivate::QMetaTypeInterface * const *metaTypes)
1582{
1583 if (!obj)
1584 return false;
1585
1586 Q_ASSERT(paramCount >= 1); // includes the return type
1587 Q_ASSERT(parameters);
1588 Q_ASSERT(typeNames);
1589
1590 // find the method
1591 QByteArrayView name(member);
1592 if (name.isEmpty())
1593 return false;
1594
1595 const QMetaObject *meta = obj->metaObject();
1596 for ( ; meta; meta = meta->superClass()) {
1597 auto priv = QMetaObjectPrivate::get(metaobject: meta);
1598 for (int i = 0; i < priv->methodCount; ++i) {
1599 QMetaMethod m = QMetaMethod::fromRelativeMethodIndex(mobj: meta, index: i);
1600 if (m.parameterCount() != (paramCount - 1))
1601 continue;
1602 if (name != stringDataView(mo: meta, index: m.data.name()))
1603 continue;
1604
1605 // attempt to call
1606 QMetaMethodPrivate::InvokeFailReason r =
1607 QMetaMethodPrivate::invokeImpl(self: m, target: obj, type, paramCount, parameters,
1608 typeNames, metaTypes);
1609 if (int(r) <= 0)
1610 return r == QMetaMethodPrivate::InvokeFailReason::None;
1611 }
1612 }
1613
1614 // This method doesn't belong to us; print out a nice warning with candidates.
1615 return printMethodNotFoundWarning(meta: obj->metaObject(), name, paramCount, names: typeNames, metaTypes);
1616}
1617
1618bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
1619 qsizetype parameterCount, const void *const *params, const char *const *names,
1620 const QtPrivate::QMetaTypeInterface * const *metaTypes)
1621{
1622 // We don't need this now but maybe we want it later, or we may be able to
1623 // share more code between the two invokeMethodImpl() overloads:
1624 Q_UNUSED(names);
1625 auto slot = QtPrivate::SlotObjUniquePtr(slotObj);
1626
1627 if (! object) // ### only if the slot requires the object + not queued?
1628 return false;
1629
1630 Qt::HANDLE currentThreadId = QThread::currentThreadId();
1631 QThread *objectThread = object->thread();
1632 bool receiverInSameThread = false;
1633 if (objectThread)
1634 receiverInSameThread = currentThreadId == QThreadData::get2(thread: objectThread)->threadId.loadRelaxed();
1635
1636 if (type == Qt::AutoConnection)
1637 type = receiverInSameThread ? Qt::DirectConnection : Qt::QueuedConnection;
1638
1639 void **argv = const_cast<void **>(params);
1640 if (type == Qt::DirectConnection) {
1641 slot->call(r: object, a: argv);
1642 } else if (type == Qt::QueuedConnection) {
1643 if (argv[0]) {
1644 qWarning(msg: "QMetaObject::invokeMethod: Unable to invoke methods with return values in "
1645 "queued connections");
1646 return false;
1647 }
1648 auto event = std::make_unique<QMetaCallEvent>(args: std::move(slot), args: nullptr, args: -1, args&: parameterCount);
1649 void **args = event->args();
1650 QMetaType *types = event->types();
1651
1652 for (int i = 1; i < parameterCount; ++i) {
1653 types[i] = QMetaType(metaTypes[i]);
1654 args[i] = types[i].create(copy: argv[i]);
1655 }
1656
1657 QCoreApplication::postEvent(receiver: object, event: event.release());
1658 } else if (type == Qt::BlockingQueuedConnection) {
1659#if QT_CONFIG(thread)
1660 if (receiverInSameThread)
1661 qWarning(msg: "QMetaObject::invokeMethod: Dead lock detected");
1662
1663 QSemaphore semaphore;
1664 QCoreApplication::postEvent(receiver: object, event: new QMetaCallEvent(std::move(slot), nullptr, -1, argv, &semaphore));
1665 semaphore.acquire();
1666#endif // QT_CONFIG(thread)
1667 } else {
1668 qWarning(msg: "QMetaObject::invokeMethod: Unknown connection type");
1669 return false;
1670 }
1671 return true;
1672}
1673
1674/*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
1675 QGenericReturnArgument ret,
1676 QGenericArgument val0 = QGenericArgument(0),
1677 QGenericArgument val1 = QGenericArgument(),
1678 QGenericArgument val2 = QGenericArgument(),
1679 QGenericArgument val3 = QGenericArgument(),
1680 QGenericArgument val4 = QGenericArgument(),
1681 QGenericArgument val5 = QGenericArgument(),
1682 QGenericArgument val6 = QGenericArgument(),
1683 QGenericArgument val7 = QGenericArgument(),
1684 QGenericArgument val8 = QGenericArgument(),
1685 QGenericArgument val9 = QGenericArgument());
1686 \threadsafe
1687 \obsolete [6.5] Please use the variadic overload of this function.
1688 \overload invokeMethod()
1689
1690 This overload always invokes the member using the connection type Qt::AutoConnection.
1691*/
1692
1693/*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
1694 Qt::ConnectionType type,
1695 QGenericArgument val0 = QGenericArgument(0),
1696 QGenericArgument val1 = QGenericArgument(),
1697 QGenericArgument val2 = QGenericArgument(),
1698 QGenericArgument val3 = QGenericArgument(),
1699 QGenericArgument val4 = QGenericArgument(),
1700 QGenericArgument val5 = QGenericArgument(),
1701 QGenericArgument val6 = QGenericArgument(),
1702 QGenericArgument val7 = QGenericArgument(),
1703 QGenericArgument val8 = QGenericArgument(),
1704 QGenericArgument val9 = QGenericArgument())
1705
1706 \threadsafe
1707 \obsolete [6.5] Please use the variadic overload of this function.
1708 \overload invokeMethod()
1709
1710 This overload can be used if the return value of the member is of no interest.
1711*/
1712
1713/*!
1714 \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
1715 QGenericArgument val0 = QGenericArgument(0),
1716 QGenericArgument val1 = QGenericArgument(),
1717 QGenericArgument val2 = QGenericArgument(),
1718 QGenericArgument val3 = QGenericArgument(),
1719 QGenericArgument val4 = QGenericArgument(),
1720 QGenericArgument val5 = QGenericArgument(),
1721 QGenericArgument val6 = QGenericArgument(),
1722 QGenericArgument val7 = QGenericArgument(),
1723 QGenericArgument val8 = QGenericArgument(),
1724 QGenericArgument val9 = QGenericArgument())
1725
1726 \threadsafe
1727 \obsolete [6.5] Please use the variadic overload of this function.
1728 \overload invokeMethod()
1729
1730 This overload invokes the member using the connection type Qt::AutoConnection and
1731 ignores return values.
1732*/
1733
1734/*!
1735 \fn template<typename Functor, typename FunctorReturnType> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, FunctorReturnType *ret)
1736 \fn template<typename Functor, typename FunctorReturnType> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
1737
1738 \since 5.10
1739 \threadsafe
1740
1741 Invokes the \a function in the event loop of \a context. \a function can be a functor
1742 or a pointer to a member function. Returns \c true if the function could be invoked.
1743 Returns \c false if there is no such function or the parameters did not match.
1744 The return value of the function call is placed in \a ret.
1745
1746 If \a type is set, then the function is invoked using that connection type. Otherwise,
1747 Qt::AutoConnection will be used.
1748*/
1749
1750/*!
1751 \fn template<typename Functor, typename FunctorReturnType, typename... Args> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments)
1752 \fn template<typename Functor, typename FunctorReturnType, typename... Args> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, QTemplatedMetaMethodReturnArgument<FunctorReturnType> ret, Args &&...arguments)
1753 \fn template<typename Functor, typename... Args> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, Qt::ConnectionType type, Args &&...arguments)
1754 \fn template<typename Functor, typename... Args> bool QMetaObject::invokeMethod(QObject *context, Functor &&function, Args &&...arguments)
1755
1756 \since 6.7
1757 \threadsafe
1758
1759 Invokes the \a function with \a arguments in the event loop of \a context.
1760 \a function can be a functor or a pointer to a member function. Returns
1761 \c true if the function could be invoked. The return value of the
1762 function call is placed in \a ret. The object used for the \a ret argument
1763 should be obtained by passing your object to qReturnArg(). For example:
1764
1765 \badcode
1766 MyClass *obj = ...;
1767 int result = 0;
1768 QMetaObject::invokeMethod(obj, &MyClass::myMethod, qReturnArg(result), parameter);
1769 \endcode
1770
1771 If \a type is set, then the function is invoked using that connection type.
1772 Otherwise, Qt::AutoConnection will be used.
1773*/
1774
1775/*!
1776 \fn QMetaObject::Connection &QMetaObject::Connection::operator=(Connection &&other)
1777
1778 Move-assigns \a other to this object, and returns a reference.
1779*/
1780/*!
1781 \fn QMetaObject::Connection::Connection(Connection &&o)
1782
1783 Move-constructs a Connection instance, making it point to the same object
1784 that \a o was pointing to.
1785*/
1786
1787/*!
1788 \fn QMetaObject::Connection::swap(Connection &other)
1789 \since 5.15
1790 \memberswap{Connection instance}
1791*/
1792
1793/*!
1794 \class QMetaMethod
1795 \inmodule QtCore
1796
1797 \brief The QMetaMethod class provides meta-data about a member
1798 function.
1799
1800 \ingroup objectmodel
1801 \compares equality
1802
1803 A QMetaMethod has a methodType(), a methodSignature(), a list of
1804 parameterTypes() and parameterNames(), a return typeName(), a
1805 tag(), and an access() specifier. You can use invoke() to invoke
1806 the method on an arbitrary QObject.
1807
1808 \sa QMetaObject, QMetaEnum, QMetaProperty, {Qt's Property System}
1809*/
1810
1811/*!
1812 \enum QMetaMethod::Attributes
1813
1814 \internal
1815
1816 \value Compatibility
1817 \value Cloned
1818 \value Scriptable
1819*/
1820
1821/*!
1822 \fn bool QMetaMethod::isValid() const
1823 \since 5.0
1824
1825 Returns \c true if this method is valid (can be introspected and
1826 invoked), otherwise returns \c false.
1827*/
1828
1829/*! \fn bool QMetaMethod::operator==(const QMetaMethod &lhs, const QMetaMethod &rhs)
1830 \since 5.0
1831 \overload
1832
1833 Returns \c true if method \a lhs is equal to method \a rhs,
1834 otherwise returns \c false.
1835*/
1836
1837/*! \fn bool QMetaMethod::operator!=(const QMetaMethod &lhs, const QMetaMethod &rhs)
1838 \since 5.0
1839 \overload
1840
1841 Returns \c true if method \a lhs is not equal to method \a rhs,
1842 otherwise returns \c false.
1843*/
1844
1845/*!
1846 \fn const QMetaObject *QMetaMethod::enclosingMetaObject() const
1847 \internal
1848*/
1849
1850/*!
1851 \enum QMetaMethod::MethodType
1852
1853 \value Method The function is a plain member function.
1854 \value Signal The function is a signal.
1855 \value Slot The function is a slot.
1856 \value Constructor The function is a constructor.
1857*/
1858
1859/*!
1860 \fn QMetaMethod::QMetaMethod()
1861 \internal
1862*/
1863
1864/*!
1865 \internal
1866*/
1867QMetaMethod QMetaMethod::fromRelativeMethodIndex(const QMetaObject *mobj, int index)
1868{
1869 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->methodCount);
1870 QMetaMethod m;
1871 m.mobj = mobj;
1872 m.data = { .d: mobj->d.data + priv(data: mobj->d.data)->methodData + index * Data::Size };
1873 return m;
1874}
1875
1876QMetaMethod QMetaMethod::fromRelativeConstructorIndex(const QMetaObject *mobj, int index)
1877{
1878 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->constructorCount);
1879 QMetaMethod m;
1880 m.mobj = mobj;
1881 m.data = { .d: mobj->d.data + priv(data: mobj->d.data)->constructorData + index * Data::Size };
1882 return m;
1883}
1884
1885/*!
1886 \macro Q_METAMETHOD_INVOKE_MAX_ARGS
1887 \relates QMetaMethod
1888
1889 Equals maximum number of arguments available for
1890 execution of the method via QMetaMethod::invoke()
1891 */
1892
1893QByteArray QMetaMethodPrivate::signature() const
1894{
1895 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1896 QByteArray result;
1897 result.reserve(asize: 256);
1898 result += name();
1899 result += '(';
1900 QList<QByteArray> argTypes = parameterTypes();
1901 for (int i = 0; i < argTypes.size(); ++i) {
1902 if (i)
1903 result += ',';
1904 result += argTypes.at(i);
1905 }
1906 result += ')';
1907 return result;
1908}
1909
1910QByteArray QMetaMethodPrivate::name() const
1911{
1912 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1913 return stringData(mo: mobj, index: data.name());
1914}
1915
1916int QMetaMethodPrivate::typesDataIndex() const
1917{
1918 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1919 return data.parameters();
1920}
1921
1922const char *QMetaMethodPrivate::rawReturnTypeName() const
1923{
1924 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1925 uint typeInfo = mobj->d.data[typesDataIndex()];
1926 if (typeInfo & IsUnresolvedType)
1927 return rawStringData(mo: mobj, index: typeInfo & TypeNameIndexMask);
1928 else
1929 return QMetaType(typeInfo).name();
1930}
1931
1932int QMetaMethodPrivate::returnType() const
1933{
1934 return parameterType(index: -1);
1935}
1936
1937int QMetaMethodPrivate::parameterCount() const
1938{
1939 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1940 return data.argc();
1941}
1942
1943inline void
1944QMetaMethodPrivate::checkMethodMetaTypeConsistency(const QtPrivate::QMetaTypeInterface *iface,
1945 int index) const
1946{
1947 uint typeInfo = parameterTypeInfo(index);
1948 QMetaType mt(iface);
1949 if (iface) {
1950 if ((typeInfo & IsUnresolvedType) == 0)
1951 Q_ASSERT(mt.id() == int(typeInfo & TypeNameIndexMask));
1952 Q_ASSERT(mt.name());
1953 } else {
1954 // The iface can only be null for a parameter if that parameter is a
1955 // const-ref to a forward-declared type. Since primitive types are
1956 // never incomplete, we can assert it's not one of them.
1957
1958#define ASSERT_NOT_PRIMITIVE_TYPE(TYPE, METATYPEID, NAME) \
1959 Q_ASSERT(typeInfo != QMetaType::TYPE);
1960 QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(ASSERT_NOT_PRIMITIVE_TYPE)
1961#undef ASSERT_NOT_PRIMITIVE_TYPE
1962 Q_ASSERT(typeInfo != QMetaType::QObjectStar);
1963
1964 // Prior to Qt 6.4 we failed to record void and void*
1965 if (priv(data: mobj->d.data)->revision >= 11) {
1966 Q_ASSERT(typeInfo != QMetaType::Void);
1967 Q_ASSERT(typeInfo != QMetaType::VoidStar);
1968 }
1969 }
1970}
1971
1972int QMetaMethodPrivate::parametersDataIndex() const
1973{
1974 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1975 return typesDataIndex() + 1;
1976}
1977
1978uint QMetaMethodPrivate::parameterTypeInfo(int index) const
1979{
1980 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1981 return mobj->d.data[parametersDataIndex() + index];
1982}
1983
1984const QtPrivate::QMetaTypeInterface *QMetaMethodPrivate::returnMetaTypeInterface() const
1985{
1986 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1987 if (methodType() == QMetaMethod::Constructor)
1988 return nullptr; // constructors don't have return types
1989
1990 const QtPrivate::QMetaTypeInterface *iface = mobj->d.metaTypes[data.metaTypeOffset()];
1991 checkMethodMetaTypeConsistency(iface, index: -1);
1992 return iface;
1993}
1994
1995const QtPrivate::QMetaTypeInterface * const *QMetaMethodPrivate::parameterMetaTypeInterfaces() const
1996{
1997 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1998 int offset = (methodType() == QMetaMethod::Constructor ? 0 : 1);
1999 const auto ifaces = &mobj->d.metaTypes[data.metaTypeOffset() + offset];
2000
2001 for (int i = 0; i < parameterCount(); ++i)
2002 checkMethodMetaTypeConsistency(iface: ifaces[i], index: i);
2003
2004 return ifaces;
2005}
2006
2007int QMetaMethodPrivate::parameterType(int index) const
2008{
2009 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2010 return typeFromTypeInfo(mo: mobj, typeInfo: parameterTypeInfo(index));
2011}
2012
2013void QMetaMethodPrivate::getParameterTypes(int *types) const
2014{
2015 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2016 int dataIndex = parametersDataIndex();
2017 int argc = parameterCount();
2018 for (int i = 0; i < argc; ++i) {
2019 int id = typeFromTypeInfo(mo: mobj, typeInfo: mobj->d.data[dataIndex++]);
2020 *(types++) = id;
2021 }
2022}
2023
2024QByteArray QMetaMethodPrivate::parameterTypeName(int index) const
2025{
2026 int paramsIndex = parametersDataIndex();
2027 return typeNameFromTypeInfo(mo: mobj, typeInfo: mobj->d.data[paramsIndex + index]).toByteArray();
2028}
2029
2030QList<QByteArray> QMetaMethodPrivate::parameterTypes() const
2031{
2032 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2033 int argc = parameterCount();
2034 QList<QByteArray> list;
2035 list.reserve(asize: argc);
2036 int paramsIndex = parametersDataIndex();
2037 for (int i = 0; i < argc; ++i) {
2038 QByteArrayView name = typeNameFromTypeInfo(mo: mobj, typeInfo: mobj->d.data[paramsIndex + i]);
2039 list.emplace_back(args: name.toByteArray());
2040 }
2041 return list;
2042}
2043
2044QList<QByteArray> QMetaMethodPrivate::parameterNames() const
2045{
2046 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2047 int argc = parameterCount();
2048 QList<QByteArray> list;
2049 list.reserve(asize: argc);
2050 int namesIndex = parametersDataIndex() + argc;
2051 for (int i = 0; i < argc; ++i)
2052 list += stringData(mo: mobj, index: mobj->d.data[namesIndex + i]);
2053 return list;
2054}
2055
2056QByteArray QMetaMethodPrivate::tag() const
2057{
2058 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2059 return stringData(mo: mobj, index: data.tag());
2060}
2061
2062int QMetaMethodPrivate::ownMethodIndex() const
2063{
2064 // recompute the methodIndex by reversing the arithmetic in QMetaObject::method()
2065 return ( data.d - mobj->d.data - priv(data: mobj->d.data)->methodData)/Data::Size;
2066}
2067
2068int QMetaMethodPrivate::ownConstructorMethodIndex() const
2069{
2070 // recompute the methodIndex by reversing the arithmetic in QMetaObject::constructor()
2071 Q_ASSERT(methodType() == Constructor);
2072 return ( data.d - mobj->d.data - priv(data: mobj->d.data)->constructorData)/Data::Size;
2073}
2074
2075/*!
2076 \since 5.0
2077
2078 Returns the signature of this method (e.g.,
2079 \c{setValue(double)}).
2080
2081 \sa parameterTypes(), parameterNames()
2082*/
2083QByteArray QMetaMethod::methodSignature() const
2084{
2085 if (!mobj)
2086 return QByteArray();
2087 return QMetaMethodPrivate::get(q: this)->signature();
2088}
2089
2090/*!
2091 \since 5.0
2092
2093 Returns the name of this method.
2094
2095 \sa methodSignature(), parameterCount()
2096*/
2097QByteArray QMetaMethod::name() const
2098{
2099 if (!mobj)
2100 return QByteArray();
2101 return QMetaMethodPrivate::get(q: this)->name();
2102}
2103
2104/*!
2105 \since 5.0
2106
2107 Returns the return type of this method.
2108
2109 The return value is one of the types that are registered
2110 with QMetaType, or QMetaType::UnknownType if the type is not registered.
2111
2112 \sa parameterType(), QMetaType, typeName(), returnMetaType()
2113*/
2114int QMetaMethod::returnType() const
2115 {
2116 return returnMetaType().id();
2117}
2118
2119/*!
2120 \since 6.0
2121
2122 Returns the return type of this method.
2123 \sa parameterMetaType(), QMetaType, typeName()
2124*/
2125QMetaType QMetaMethod::returnMetaType() const
2126{
2127 if (!mobj || methodType() == QMetaMethod::Constructor)
2128 return QMetaType{};
2129 auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset()]);
2130 if (mt.id() == QMetaType::UnknownType)
2131 return QMetaType(QMetaMethodPrivate::get(q: this)->returnType());
2132 else
2133 return mt;
2134}
2135
2136/*!
2137 \since 5.0
2138
2139 Returns the number of parameters of this method.
2140
2141 \sa parameterType(), parameterNames()
2142*/
2143int QMetaMethod::parameterCount() const
2144{
2145 if (!mobj)
2146 return 0;
2147 return QMetaMethodPrivate::get(q: this)->parameterCount();
2148}
2149
2150/*!
2151 \since 5.0
2152
2153 Returns the type of the parameter at the given \a index.
2154
2155 The return value is one of the types that are registered
2156 with QMetaType, or QMetaType::UnknownType if the type is not registered.
2157
2158 \sa parameterCount(), parameterMetaType(), returnType(), QMetaType
2159*/
2160int QMetaMethod::parameterType(int index) const
2161{
2162 return parameterMetaType(index).id();
2163}
2164
2165/*!
2166 \since 6.0
2167
2168 Returns the metatype of the parameter at the given \a index.
2169
2170 If the \a index is smaller than zero or larger than
2171 parameterCount(), an invalid QMetaType is returned.
2172
2173 \sa parameterCount(), returnMetaType(), QMetaType
2174*/
2175QMetaType QMetaMethod::parameterMetaType(int index) const
2176{
2177 if (!mobj || index < 0)
2178 return {};
2179 auto priv = QMetaMethodPrivate::get(q: this);
2180 if (index >= priv->parameterCount())
2181 return {};
2182 // + 1 if there exists a return type
2183 auto parameterOffset = index + (methodType() == QMetaMethod::Constructor ? 0 : 1);
2184 auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset() + parameterOffset]);
2185 if (mt.id() == QMetaType::UnknownType)
2186 return QMetaType(QMetaMethodPrivate::get(q: this)->parameterType(index));
2187 else
2188 return mt;
2189}
2190
2191/*!
2192 \since 5.0
2193 \internal
2194
2195 Gets the parameter \a types of this method. The storage
2196 for \a types must be able to hold parameterCount() items.
2197
2198 \sa parameterCount(), returnType(), parameterType()
2199*/
2200void QMetaMethod::getParameterTypes(int *types) const
2201{
2202 if (!mobj)
2203 return;
2204 QMetaMethodPrivate::get(q: this)->getParameterTypes(types);
2205}
2206
2207/*!
2208 Returns a list of parameter types.
2209
2210 \sa parameterNames(), methodSignature()
2211*/
2212QList<QByteArray> QMetaMethod::parameterTypes() const
2213{
2214 if (!mobj)
2215 return QList<QByteArray>();
2216 return QMetaMethodPrivate::get(q: this)->parameterTypes();
2217}
2218
2219/*!
2220 \since 6.0
2221 Returns the name of the type at position \a index
2222 If there is no parameter at \a index, returns an empty QByteArray
2223
2224 \sa parameterNames()
2225 */
2226QByteArray QMetaMethod::parameterTypeName(int index) const
2227{
2228 if (!mobj || index < 0 || index >= parameterCount())
2229 return {};
2230 return QMetaMethodPrivate::get(q: this)->parameterTypeName(index);
2231}
2232
2233/*!
2234 Returns a list of parameter names.
2235
2236 \sa parameterTypes(), methodSignature()
2237*/
2238QList<QByteArray> QMetaMethod::parameterNames() const
2239{
2240 if (!mobj)
2241 return QList<QByteArray>();
2242 return QMetaMethodPrivate::get(q: this)->parameterNames();
2243}
2244
2245
2246/*!
2247 Returns the return type name of this method.
2248
2249 \sa returnType(), QMetaType::type()
2250*/
2251const char *QMetaMethod::typeName() const
2252{
2253 if (!mobj)
2254 return nullptr;
2255 return QMetaMethodPrivate::get(q: this)->rawReturnTypeName();
2256}
2257
2258/*!
2259 Returns the tag associated with this method.
2260
2261 Tags are special macros recognized by \c moc that make it
2262 possible to add extra information about a method.
2263
2264 Tag information can be added in the following
2265 way in the function declaration:
2266
2267 \snippet code/src_corelib_kernel_qmetaobject.cpp 10
2268
2269 and the information can be accessed by using:
2270
2271 \snippet code/src_corelib_kernel_qmetaobject.cpp 11
2272
2273 For the moment, \c moc will extract and record all tags, but it will not
2274 handle any of them specially. You can use the tags to annotate your methods
2275 differently, and treat them according to the specific needs of your
2276 application.
2277
2278 \note \c moc expands preprocessor macros, so it is necessary
2279 to surround the definition with \c #ifndef \c Q_MOC_RUN, as shown in the
2280 example above.
2281*/
2282const char *QMetaMethod::tag() const
2283{
2284 if (!mobj)
2285 return nullptr;
2286 return QMetaMethodPrivate::get(q: this)->tag().constData();
2287}
2288
2289
2290/*!
2291 \internal
2292 */
2293int QMetaMethod::attributes() const
2294{
2295 if (!mobj)
2296 return false;
2297 return data.flags() >> 4;
2298}
2299
2300/*!
2301 \since 4.6
2302
2303 Returns this method's index.
2304*/
2305int QMetaMethod::methodIndex() const
2306{
2307 if (!mobj)
2308 return -1;
2309 return QMetaMethodPrivate::get(q: this)->ownMethodIndex() + mobj->methodOffset();
2310}
2311
2312/*!
2313 \since 6.0
2314
2315 Returns this method's local index inside.
2316*/
2317int QMetaMethod::relativeMethodIndex() const
2318{
2319 if (!mobj)
2320 return -1;
2321 return QMetaMethodPrivate::get(q: this)->ownMethodIndex();
2322}
2323
2324// This method has been around for a while, but the documentation was marked \internal until 5.1
2325/*!
2326 \since 5.1
2327 Returns the method revision if one was specified by Q_REVISION, otherwise
2328 returns 0. Since Qt 6.0, non-zero values are encoded and can be decoded
2329 using QTypeRevision::fromEncodedVersion().
2330 */
2331int QMetaMethod::revision() const
2332{
2333 if (!mobj)
2334 return 0;
2335 if (data.flags() & MethodRevisioned) {
2336 int offset = priv(data: mobj->d.data)->methodData
2337 + priv(data: mobj->d.data)->methodCount * Data::Size
2338 + QMetaMethodPrivate::get(q: this)->ownMethodIndex();
2339 return mobj->d.data[offset];
2340 }
2341 return 0;
2342}
2343
2344/*!
2345 \since 6.2
2346
2347 Returns whether the method is const qualified.
2348
2349 \note This method might erroneously return \c false for a const method
2350 if it belongs to a library compiled against an older version of Qt.
2351 */
2352bool QMetaMethod::isConst() const
2353{
2354 if (!mobj)
2355 return false;
2356 if (QMetaObjectPrivate::get(metaobject: mobj)->revision < 10)
2357 return false;
2358 return data.flags() & MethodIsConst;
2359}
2360
2361/*!
2362 Returns the access specification of this method (private,
2363 protected, or public).
2364
2365 \note Signals are always public, but you should regard that as an
2366 implementation detail. It is almost always a bad idea to emit a signal from
2367 outside its class.
2368
2369 \sa methodType()
2370*/
2371QMetaMethod::Access QMetaMethod::access() const
2372{
2373 if (!mobj)
2374 return Private;
2375 return (QMetaMethod::Access)(data.flags() & AccessMask);
2376}
2377
2378/*!
2379 Returns the type of this method (signal, slot, or method).
2380
2381 \sa access()
2382*/
2383QMetaMethod::MethodType QMetaMethod::methodType() const
2384{
2385 if (!mobj)
2386 return QMetaMethod::Method;
2387 return (QMetaMethod::MethodType)((data.flags() & MethodTypeMask)>>2);
2388}
2389
2390/*!
2391 \fn template <typename PointerToMemberFunction> QMetaMethod QMetaMethod::fromSignal(PointerToMemberFunction signal)
2392 \since 5.0
2393
2394 Returns the meta-method that corresponds to the given \a signal, or an
2395 invalid QMetaMethod if \a signal is \c{nullptr} or not a signal of the class.
2396
2397 Example:
2398
2399 \snippet code/src_corelib_kernel_qmetaobject.cpp 9
2400*/
2401
2402/*!
2403 \internal
2404
2405 Implementation of the fromSignal() function.
2406
2407 \a metaObject is the class's meta-object
2408 \a signal is a pointer to a pointer to a member signal of the class
2409*/
2410QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **signal)
2411{
2412 int i = -1;
2413 void *args[] = { &i, signal };
2414 for (const QMetaObject *m = metaObject; m; m = m->d.superdata) {
2415 m->static_metacall(cl: QMetaObject::IndexOfMethod, idx: 0, argv: args);
2416 if (i >= 0)
2417 return QMetaMethod::fromRelativeMethodIndex(mobj: m, index: i);
2418 }
2419 return QMetaMethod();
2420}
2421
2422/*!
2423 \fn template <typename ReturnArg, typename... Args> bool QMetaMethod::invoke(QObject *obj, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... arguments) const
2424 \fn template <typename... Args> bool QMetaMethod::invoke(QObject *obj, Qt::ConnectionType type, Args &&... arguments) const
2425 \fn template <typename ReturnArg, typename... Args> bool QMetaMethod::invoke(QObject *obj, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... arguments) const
2426 \fn template <typename... Args> bool QMetaMethod::invoke(QObject *obj, Args &&... arguments) const
2427 \since 6.5
2428
2429 Invokes this method on the object \a object. Returns \c true if the member could be invoked.
2430 Returns \c false if there is no such member or the parameters did not match.
2431
2432 For the overloads with a QTemplatedMetaMethodReturnArgument parameter, the
2433 return value of the \a member function call is placed in \a ret. For the
2434 overloads without such a member, the return value of the called function
2435 (if any) will be discarded. QTemplatedMetaMethodReturnArgument is an
2436 internal type you should not use directly. Instead, use the qReturnArg()
2437 function.
2438
2439 The overloads with a Qt::ConnectionType \a type parameter allow explicitly
2440 selecting whether the invocation will be synchronous or not:
2441
2442 \list
2443 \li If \a type is Qt::DirectConnection, the member will be invoked immediately
2444 in the current thread.
2445
2446 \li If \a type is Qt::QueuedConnection, a QEvent will be sent and the
2447 member is invoked as soon as the application enters the event loop in the
2448 thread the \a obj was created in or was moved to.
2449
2450 \li If \a type is Qt::BlockingQueuedConnection, the method will be invoked in
2451 the same way as for Qt::QueuedConnection, except that the current thread
2452 will block until the event is delivered. Using this connection type to
2453 communicate between objects in the same thread will lead to deadlocks.
2454
2455 \li If \a type is Qt::AutoConnection, the member is invoked synchronously
2456 if \a obj lives in the same thread as the caller; otherwise it will invoke
2457 the member asynchronously. This is the behavior of the overloads that do
2458 not have the \a type parameter.
2459 \endlist
2460
2461 To asynchronously invoke the
2462 \l{QPushButton::animateClick()}{animateClick()} slot on a
2463 QPushButton:
2464
2465 \snippet code/src_corelib_kernel_qmetaobject.cpp 6
2466
2467 With asynchronous method invocations, the parameters must be copyable
2468 types, because Qt needs to copy the arguments to store them in an event
2469 behind the scenes. Since Qt 6.5, this function automatically registers the
2470 types being used; however, as a side-effect, it is not possible to make
2471 calls using types that are only forward-declared. Additionally, it is not
2472 possible to make asynchronous calls that use references to
2473 non-const-qualified types as parameters either.
2474
2475 To synchronously invoke the \c compute(QString, int, double) slot on
2476 some arbitrary object \c obj retrieve its return value:
2477
2478 \snippet code/src_corelib_kernel_qmetaobject.cpp invoke-no-macro
2479
2480 If the "compute" slot does not take exactly one \l QString, one \c int, and
2481 one \c double in the specified order, the call will fail. Note how it was
2482 necessary to be explicit about the type of the QString, as the character
2483 literal is not exactly the right type to match. If the method instead took
2484 a \l QByteArray, a \l qint64, and a \c{long double}, the call would need to be
2485 written as:
2486
2487 \snippet code/src_corelib_kernel_qmetaobject.cpp invoke-no-macro-other-types
2488
2489 The same call can be executed using the Q_ARG() and Q_RETURN_ARG() macros,
2490 as in:
2491
2492 \snippet code/src_corelib_kernel_qmetaobject.cpp 8
2493
2494 \warning this method will not test the validity of the arguments: \a object
2495 must be an instance of the class of the QMetaObject of which this QMetaMethod
2496 has been constructed with.
2497
2498 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
2499*/
2500
2501/*!
2502 \obsolete [6.5] Please use the variadic overload of this function
2503
2504 Invokes this method on the object \a object. Returns \c true if the member could be invoked.
2505 Returns \c false if there is no such member or the parameters did not match.
2506
2507 See the variadic invokeMethod() function for more information. This
2508 function should behave the same way as that one, with the following
2509 limitations:
2510
2511 \list
2512 \li The number of parameters is limited to 10.
2513 \li Parameter names may need to be an exact string match.
2514 \li Meta types are not automatically registered.
2515 \endlist
2516
2517 With asynchronous method invocations, the parameters must be of
2518 types that are known to Qt's meta-object system, because Qt needs
2519 to copy the arguments to store them in an event behind the
2520 scenes. If you try to use a queued connection and get the error
2521 message
2522
2523 \snippet code/src_corelib_kernel_qmetaobject.cpp 7
2524
2525 call qRegisterMetaType() to register the data type before you
2526 call QMetaMethod::invoke().
2527
2528 \warning In addition to the limitations of the variadic invoke() overload,
2529 the arguments must have the same type as the ones expected by the method,
2530 else, the behavior is undefined.
2531
2532 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
2533*/
2534bool QMetaMethod::invoke(QObject *object,
2535 Qt::ConnectionType connectionType,
2536 QGenericReturnArgument returnValue,
2537 QGenericArgument val0,
2538 QGenericArgument val1,
2539 QGenericArgument val2,
2540 QGenericArgument val3,
2541 QGenericArgument val4,
2542 QGenericArgument val5,
2543 QGenericArgument val6,
2544 QGenericArgument val7,
2545 QGenericArgument val8,
2546 QGenericArgument val9) const
2547{
2548 if (!object || !mobj)
2549 return false;
2550
2551 // check argument count (we don't allow invoking a method if given too few arguments)
2552 const char *typeNames[] = {
2553 returnValue.name(),
2554 val0.name(),
2555 val1.name(),
2556 val2.name(),
2557 val3.name(),
2558 val4.name(),
2559 val5.name(),
2560 val6.name(),
2561 val7.name(),
2562 val8.name(),
2563 val9.name()
2564 };
2565 void *param[] = {
2566 returnValue.data(),
2567 val0.data(),
2568 val1.data(),
2569 val2.data(),
2570 val3.data(),
2571 val4.data(),
2572 val5.data(),
2573 val6.data(),
2574 val7.data(),
2575 val8.data(),
2576 val9.data()
2577 };
2578
2579 int paramCount;
2580 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
2581 if (qstrlen(str: typeNames[paramCount]) <= 0)
2582 break;
2583 }
2584 return invokeImpl(self: *this, target: object, connectionType, paramCount, parameters: param, typeNames, metaTypes: nullptr);
2585}
2586
2587bool QMetaMethod::invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType connectionType,
2588 qsizetype paramCount, const void *const *parameters,
2589 const char *const *typeNames,
2590 const QtPrivate::QMetaTypeInterface *const *metaTypes)
2591{
2592 if (!target || !self.mobj)
2593 return false;
2594 QMetaMethodPrivate::InvokeFailReason r =
2595 QMetaMethodPrivate::invokeImpl(self, target, connectionType, paramCount, parameters,
2596 typeNames, metaTypes);
2597 if (Q_LIKELY(r == QMetaMethodPrivate::InvokeFailReason::None))
2598 return true;
2599
2600 if (int(r) >= int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch)) {
2601 int n = int(r) - int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch);
2602 qWarning(msg: "QMetaMethod::invoke: cannot convert formal parameter %d from %s in call to %s::%s",
2603 n, typeNames[n + 1] ? typeNames[n + 1] : metaTypes[n + 1]->name,
2604 self.mobj->className(), self.methodSignature().constData());
2605 }
2606 if (r == QMetaMethodPrivate::InvokeFailReason::TooFewArguments) {
2607 qWarning(msg: "QMetaMethod::invoke: too few arguments (%d) in call to %s::%s",
2608 int(paramCount), self.mobj->className(), self.methodSignature().constData());
2609 }
2610 return false;
2611}
2612
2613auto QMetaMethodInvoker::invokeImpl(QMetaMethod self, void *target,
2614 Qt::ConnectionType connectionType,
2615 qsizetype paramCount, const void *const *parameters,
2616 const char *const *typeNames,
2617 const QtPrivate::QMetaTypeInterface *const *metaTypes) -> InvokeFailReason
2618{
2619 auto object = static_cast<QObject *>(target);
2620 auto priv = QMetaMethodPrivate::get(q: &self);
2621 constexpr bool MetaTypesAreOptional = QT_VERSION < QT_VERSION_CHECK(7, 0, 0);
2622 auto methodMetaTypes = priv->parameterMetaTypeInterfaces();
2623 auto param = const_cast<void **>(parameters);
2624
2625 Q_ASSERT(priv->mobj);
2626 Q_ASSERT(self.methodType() == Constructor || object);
2627 Q_ASSERT(self.methodType() == Constructor || connectionType == Qt::ConnectionType(-1) ||
2628 priv->mobj->cast(object));
2629 Q_ASSERT(paramCount >= 1); // includes the return type
2630 Q_ASSERT(parameters);
2631 Q_ASSERT(typeNames);
2632 Q_ASSERT(MetaTypesAreOptional || metaTypes);
2633
2634 if ((paramCount - 1) < qsizetype(priv->data.argc()))
2635 return InvokeFailReason::TooFewArguments;
2636
2637 // 0 is the return type, 1 is the first formal parameter
2638 auto checkTypesAreCompatible = [=](int idx) {
2639 uint typeInfo = priv->parameterTypeInfo(index: idx - 1);
2640 QByteArrayView userTypeName(typeNames[idx] ? typeNames[idx] : metaTypes[idx]->name);
2641
2642 if ((typeInfo & IsUnresolvedType) == 0) {
2643 // this is a built-in type
2644 if (MetaTypesAreOptional && !metaTypes)
2645 return int(typeInfo) == QMetaType::fromName(name: userTypeName).id();
2646 return int(typeInfo) == metaTypes[idx]->typeId;
2647 }
2648
2649 QByteArrayView methodTypeName = stringDataView(mo: priv->mobj, index: typeInfo & TypeNameIndexMask);
2650 if ((MetaTypesAreOptional && !metaTypes) || !metaTypes[idx]) {
2651 // compatibility call, compare strings
2652 if (methodTypeName == userTypeName)
2653 return true;
2654
2655 // maybe the user type needs normalization
2656 QByteArray normalized = normalizeTypeInternal(t: userTypeName.begin(), e: userTypeName.end());
2657 return methodTypeName == normalized;
2658 }
2659
2660 QMetaType userType(metaTypes[idx]);
2661 Q_ASSERT(userType.isValid());
2662 if (QMetaType(methodMetaTypes[idx - 1]) == userType)
2663 return true;
2664
2665 // if the parameter type was NOT only forward-declared, it MUST have
2666 // matched
2667 if (methodMetaTypes[idx - 1])
2668 return false;
2669
2670 // resolve from the name moc stored for us
2671 QMetaType resolved = QMetaType::fromName(name: methodTypeName);
2672 return resolved == userType;
2673 };
2674
2675 // force all types to be registered, just in case
2676 for (qsizetype i = 0; metaTypes && i < paramCount; ++i)
2677 QMetaType(metaTypes[i]).registerType();
2678
2679 // check formal parameters first (overload set)
2680 for (qsizetype i = 1; i < paramCount; ++i) {
2681 if (!checkTypesAreCompatible(i))
2682 return InvokeFailReason(int(InvokeFailReason::FormalParameterMismatch) + i - 1);
2683 }
2684
2685 // handle constructors first
2686 if (self.methodType() == Constructor) {
2687 if (object) {
2688 qWarning(msg: "QMetaMethod::invokeMethod: cannot call constructor %s on object %p",
2689 self.methodSignature().constData(), object);
2690 return InvokeFailReason::ConstructorCallOnObject;
2691 }
2692
2693 if (!parameters[0]) {
2694 qWarning(msg: "QMetaMethod::invokeMethod: constructor call to %s must assign a return type",
2695 self.methodSignature().constData());
2696 return InvokeFailReason::ConstructorCallWithoutResult;
2697 }
2698
2699 if (!MetaTypesAreOptional || metaTypes) {
2700 if (metaTypes[0]->typeId != QMetaType::QObjectStar) {
2701 qWarning(msg: "QMetaMethod::invokeMethod: cannot convert QObject* to %s on constructor call %s",
2702 metaTypes[0]->name, self.methodSignature().constData());
2703 return InvokeFailReason::ReturnTypeMismatch;
2704 }
2705 }
2706
2707 int idx = priv->ownConstructorMethodIndex();
2708 if (priv->mobj->static_metacall(cl: QMetaObject::CreateInstance, idx, argv: param) >= 0)
2709 return InvokeFailReason::ConstructorCallFailed;
2710 return {};
2711 }
2712
2713 // regular type - check return type
2714 if (parameters[0]) {
2715 if (!checkTypesAreCompatible(0)) {
2716 const char *retType = typeNames[0] ? typeNames[0] : metaTypes[0]->name;
2717 qWarning(msg: "QMetaMethod::invokeMethod: return type mismatch for method %s::%s:"
2718 " cannot convert from %s to %s during invocation",
2719 priv->mobj->className(), priv->methodSignature().constData(),
2720 priv->rawReturnTypeName(), retType);
2721 return InvokeFailReason::ReturnTypeMismatch;
2722 }
2723 }
2724
2725 Qt::HANDLE currentThreadId = nullptr;
2726 QThread *objectThread = nullptr;
2727 auto receiverInSameThread = [&]() {
2728 if (!currentThreadId) {
2729 currentThreadId = QThread::currentThreadId();
2730 objectThread = object->thread();
2731 }
2732 if (objectThread)
2733 return currentThreadId == QThreadData::get2(thread: objectThread)->threadId.loadRelaxed();
2734 return false;
2735 };
2736
2737 // check connection type
2738 if (connectionType == Qt::AutoConnection)
2739 connectionType = receiverInSameThread() ? Qt::DirectConnection : Qt::QueuedConnection;
2740 else if (connectionType == Qt::ConnectionType(-1))
2741 connectionType = Qt::DirectConnection;
2742
2743#if !QT_CONFIG(thread)
2744 if (connectionType == Qt::BlockingQueuedConnection) {
2745 connectionType = Qt::DirectConnection;
2746 }
2747#endif
2748
2749 // invoke!
2750 int idx_relative = priv->ownMethodIndex();
2751 int idx_offset = priv->mobj->methodOffset();
2752 QObjectPrivate::StaticMetaCallFunction callFunction = priv->mobj->d.static_metacall;
2753
2754 if (connectionType == Qt::DirectConnection) {
2755 if (callFunction)
2756 callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
2757 else if (QMetaObject::metacall(object, cl: QMetaObject::InvokeMetaMethod, idx: idx_relative + idx_offset, argv: param) >= 0)
2758 return InvokeFailReason::CallViaVirtualFailed;
2759 } else if (connectionType == Qt::QueuedConnection) {
2760 if (parameters[0]) {
2761 qWarning(msg: "QMetaMethod::invoke: Unable to invoke methods with return values in "
2762 "queued connections");
2763 return InvokeFailReason::CouldNotQueueParameter;
2764 }
2765
2766 auto event = std::make_unique<QMetaCallEvent>(args&: idx_offset, args&: idx_relative, args&: callFunction, args: nullptr, args: -1, args&: paramCount);
2767 QMetaType *types = event->types();
2768 void **args = event->args();
2769
2770 // fill in the meta types first
2771 for (int i = 1; i < paramCount; ++i) {
2772 types[i] = QMetaType(methodMetaTypes[i - 1]);
2773 if (!types[i].iface() && (!MetaTypesAreOptional || metaTypes))
2774 types[i] = QMetaType(metaTypes[i]);
2775 if (!types[i].iface())
2776 types[i] = priv->parameterMetaType(index: i - 1);
2777 if (!types[i].iface() && typeNames[i])
2778 types[i] = QMetaType::fromName(name: typeNames[i]);
2779 if (!types[i].iface()) {
2780 qWarning(msg: "QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
2781 typeNames[i]);
2782 return InvokeFailReason(int(InvokeFailReason::CouldNotQueueParameter) - i);
2783 }
2784 }
2785
2786 // now create copies of our parameters using those meta types
2787 for (int i = 1; i < paramCount; ++i)
2788 args[i] = types[i].create(copy: parameters[i]);
2789
2790 QCoreApplication::postEvent(receiver: object, event: event.release());
2791 } else { // blocking queued connection
2792#if QT_CONFIG(thread)
2793 if (receiverInSameThread()) {
2794 qWarning(msg: "QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: "
2795 "Receiver is %s(%p)", priv->mobj->className(), object);
2796 return InvokeFailReason::DeadLockDetected;
2797 }
2798
2799 QSemaphore semaphore;
2800 QCoreApplication::postEvent(receiver: object, event: new QMetaCallEvent(idx_offset, idx_relative, callFunction,
2801 nullptr, -1, param, &semaphore));
2802 semaphore.acquire();
2803#endif // QT_CONFIG(thread)
2804 }
2805 return {};
2806}
2807
2808/*! \fn bool QMetaMethod::invoke(QObject *object,
2809 QGenericReturnArgument returnValue,
2810 QGenericArgument val0 = QGenericArgument(0),
2811 QGenericArgument val1 = QGenericArgument(),
2812 QGenericArgument val2 = QGenericArgument(),
2813 QGenericArgument val3 = QGenericArgument(),
2814 QGenericArgument val4 = QGenericArgument(),
2815 QGenericArgument val5 = QGenericArgument(),
2816 QGenericArgument val6 = QGenericArgument(),
2817 QGenericArgument val7 = QGenericArgument(),
2818 QGenericArgument val8 = QGenericArgument(),
2819 QGenericArgument val9 = QGenericArgument()) const
2820 \obsolete [6.5] Please use the variadic overload of this function
2821 \overload invoke()
2822
2823 This overload always invokes this method using the connection type Qt::AutoConnection.
2824*/
2825
2826/*! \fn bool QMetaMethod::invoke(QObject *object,
2827 Qt::ConnectionType connectionType,
2828 QGenericArgument val0 = QGenericArgument(0),
2829 QGenericArgument val1 = QGenericArgument(),
2830 QGenericArgument val2 = QGenericArgument(),
2831 QGenericArgument val3 = QGenericArgument(),
2832 QGenericArgument val4 = QGenericArgument(),
2833 QGenericArgument val5 = QGenericArgument(),
2834 QGenericArgument val6 = QGenericArgument(),
2835 QGenericArgument val7 = QGenericArgument(),
2836 QGenericArgument val8 = QGenericArgument(),
2837 QGenericArgument val9 = QGenericArgument()) const
2838 \obsolete [6.5] Please use the variadic overload of this function
2839 \overload invoke()
2840
2841 This overload can be used if the return value of the member is of no interest.
2842*/
2843
2844/*!
2845 \fn bool QMetaMethod::invoke(QObject *object,
2846 QGenericArgument val0 = QGenericArgument(0),
2847 QGenericArgument val1 = QGenericArgument(),
2848 QGenericArgument val2 = QGenericArgument(),
2849 QGenericArgument val3 = QGenericArgument(),
2850 QGenericArgument val4 = QGenericArgument(),
2851 QGenericArgument val5 = QGenericArgument(),
2852 QGenericArgument val6 = QGenericArgument(),
2853 QGenericArgument val7 = QGenericArgument(),
2854 QGenericArgument val8 = QGenericArgument(),
2855 QGenericArgument val9 = QGenericArgument()) const
2856 \obsolete [6.5] Please use the variadic overload of this function
2857 \overload invoke()
2858
2859 This overload invokes this method using the
2860 connection type Qt::AutoConnection and ignores return values.
2861*/
2862
2863/*!
2864 \fn template <typename ReturnArg, typename... Args> bool QMetaMethod::invokeOnGadget(void *gadget, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... arguments) const
2865 \fn template <typename... Args> bool QMetaMethod::invokeOnGadget(void *gadget, Args &&... arguments) const
2866 \since 6.5
2867
2868 Invokes this method on a Q_GADGET. Returns \c true if the member could be invoked.
2869 Returns \c false if there is no such member or the parameters did not match.
2870
2871 The pointer \a gadget must point to an instance of the gadget class.
2872
2873 The invocation is always synchronous.
2874
2875 For the overload with a QTemplatedMetaMethodReturnArgument parameter, the
2876 return value of the \a member function call is placed in \a ret. For the
2877 overload without it, the return value of the called function (if any) will
2878 be discarded. QTemplatedMetaMethodReturnArgument is an internal type you
2879 should not use directly. Instead, use the qReturnArg() function.
2880
2881 \warning this method will not test the validity of the arguments: \a gadget
2882 must be an instance of the class of the QMetaObject of which this QMetaMethod
2883 has been constructed with.
2884
2885 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
2886*/
2887
2888/*!
2889 \since 5.5
2890 \obsolete [6.5] Please use the variadic overload of this function
2891
2892 Invokes this method on a Q_GADGET. Returns \c true if the member could be invoked.
2893 Returns \c false if there is no such member or the parameters did not match.
2894
2895 See the variadic invokeMethod() function for more information. This
2896 function should behave the same way as that one, with the following
2897 limitations:
2898
2899 \list
2900 \li The number of parameters is limited to 10.
2901 \li Parameter names may need to be an exact string match.
2902 \li Meta types are not automatically registered.
2903 \endlist
2904
2905 \warning In addition to the limitations of the variadic invoke() overload,
2906 the arguments must have the same type as the ones expected by the method,
2907 else, the behavior is undefined.
2908
2909 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
2910*/
2911bool QMetaMethod::invokeOnGadget(void *gadget,
2912 QGenericReturnArgument returnValue,
2913 QGenericArgument val0,
2914 QGenericArgument val1,
2915 QGenericArgument val2,
2916 QGenericArgument val3,
2917 QGenericArgument val4,
2918 QGenericArgument val5,
2919 QGenericArgument val6,
2920 QGenericArgument val7,
2921 QGenericArgument val8,
2922 QGenericArgument val9) const
2923{
2924 if (!gadget || !mobj)
2925 return false;
2926
2927 // check return type
2928 if (returnValue.data()) {
2929 const char *retType = typeName();
2930 if (qstrcmp(str1: returnValue.name(), str2: retType) != 0) {
2931 // normalize the return value as well
2932 QByteArray normalized = QMetaObject::normalizedType(type: returnValue.name());
2933 if (qstrcmp(str1: normalized.constData(), str2: retType) != 0) {
2934 // String comparison failed, try compare the metatype.
2935 int t = returnType();
2936 if (t == QMetaType::UnknownType || t != QMetaType::fromName(name: normalized).id())
2937 return false;
2938 }
2939 }
2940 }
2941
2942 // check argument count (we don't allow invoking a method if given too few arguments)
2943 const char *typeNames[] = {
2944 returnValue.name(),
2945 val0.name(),
2946 val1.name(),
2947 val2.name(),
2948 val3.name(),
2949 val4.name(),
2950 val5.name(),
2951 val6.name(),
2952 val7.name(),
2953 val8.name(),
2954 val9.name()
2955 };
2956 int paramCount;
2957 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
2958 if (qstrlen(str: typeNames[paramCount]) <= 0)
2959 break;
2960 }
2961 if (paramCount <= QMetaMethodPrivate::get(q: this)->parameterCount())
2962 return false;
2963
2964 // invoke!
2965 void *param[] = {
2966 returnValue.data(),
2967 val0.data(),
2968 val1.data(),
2969 val2.data(),
2970 val3.data(),
2971 val4.data(),
2972 val5.data(),
2973 val6.data(),
2974 val7.data(),
2975 val8.data(),
2976 val9.data()
2977 };
2978 int idx_relative = QMetaMethodPrivate::get(q: this)->ownMethodIndex();
2979 Q_ASSERT(QMetaObjectPrivate::get(mobj)->revision >= 6);
2980 QObjectPrivate::StaticMetaCallFunction callFunction = mobj->d.static_metacall;
2981 if (!callFunction)
2982 return false;
2983 callFunction(reinterpret_cast<QObject*>(gadget), QMetaObject::InvokeMetaMethod, idx_relative, param);
2984 return true;
2985}
2986
2987/*!
2988 \fn bool QMetaMethod::invokeOnGadget(void *gadget,
2989 QGenericArgument val0 = QGenericArgument(0),
2990 QGenericArgument val1 = QGenericArgument(),
2991 QGenericArgument val2 = QGenericArgument(),
2992 QGenericArgument val3 = QGenericArgument(),
2993 QGenericArgument val4 = QGenericArgument(),
2994 QGenericArgument val5 = QGenericArgument(),
2995 QGenericArgument val6 = QGenericArgument(),
2996 QGenericArgument val7 = QGenericArgument(),
2997 QGenericArgument val8 = QGenericArgument(),
2998 QGenericArgument val9 = QGenericArgument()) const
2999
3000 \overload
3001 \obsolete [6.5] Please use the variadic overload of this function
3002 \since 5.5
3003
3004 This overload invokes this method for a \a gadget and ignores return values.
3005*/
3006
3007/*!
3008 \class QMetaEnum
3009 \inmodule QtCore
3010 \brief The QMetaEnum class provides meta-data about an enumerator.
3011
3012 \ingroup objectmodel
3013
3014 Use name() for the enumerator's name. The enumerator's keys (names
3015 of each enumerated item) are returned by key(); use keyCount() to find
3016 the number of keys. isFlag() returns whether the enumerator is
3017 meant to be used as a flag, meaning that its values can be combined
3018 using the OR operator.
3019
3020 The conversion functions keyToValue(), valueToKey(), keysToValue(),
3021 and valueToKeys() allow conversion between the integer
3022 representation of an enumeration or set value and its literal
3023 representation. The scope() function returns the class scope this
3024 enumerator was declared in.
3025
3026 \sa QMetaObject, QMetaMethod, QMetaProperty
3027*/
3028
3029/*!
3030 \fn bool QMetaEnum::isValid() const
3031
3032 Returns \c true if this enum is valid (has a name); otherwise returns
3033 false.
3034
3035 \sa name()
3036*/
3037
3038/*!
3039 \fn const QMetaObject *QMetaEnum::enclosingMetaObject() const
3040 \internal
3041*/
3042
3043
3044/*!
3045 \fn QMetaEnum::QMetaEnum()
3046 \internal
3047*/
3048
3049/*!
3050 Returns the name of the type (without the scope).
3051
3052 For example, the Qt::Key enumeration has \c
3053 Key as the type name and \l Qt as the scope.
3054
3055 For flags this returns the name of the flag type, not the
3056 name of the enum type.
3057
3058 \sa isValid(), scope(), enumName()
3059*/
3060const char *QMetaEnum::name() const
3061{
3062 if (!mobj)
3063 return nullptr;
3064 return rawStringData(mo: mobj, index: data.name());
3065}
3066
3067/*!
3068 Returns the enum name of the flag (without the scope).
3069
3070 For example, the Qt::AlignmentFlag flag has \c
3071 AlignmentFlag as the enum name, but \c Alignment as the type name.
3072 Non flag enums has the same type and enum names.
3073
3074 Enum names have the same scope as the type name.
3075
3076 \since 5.12
3077 \sa isValid(), name()
3078*/
3079const char *QMetaEnum::enumName() const
3080{
3081 if (!mobj)
3082 return nullptr;
3083 return rawStringData(mo: mobj, index: data.alias());
3084}
3085
3086/*!
3087 Returns the meta type of the enum.
3088
3089 If the QMetaObject that this enum is part of was generated with Qt 6.5 or
3090 earlier, this will be an invalid meta type.
3091
3092 \note This is the meta type of the enum itself, not of its underlying
3093 integral type. You can retrieve the meta type of the underlying type of the
3094 enum using \l{QMetaType::underlyingType()}.
3095
3096 \since 6.6
3097*/
3098QMetaType QMetaEnum::metaType() const
3099{
3100 if (!mobj)
3101 return {};
3102
3103 const QMetaObjectPrivate *p = priv(data: mobj->d.data);
3104#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
3105 if (p->revision < 12)
3106 QMetaType();
3107#endif
3108
3109 return QMetaType(mobj->d.metaTypes[data.index(mobj) + p->propertyCount]);
3110}
3111
3112/*!
3113 Returns the number of keys.
3114
3115 \sa key()
3116*/
3117int QMetaEnum::keyCount() const
3118{
3119 if (!mobj)
3120 return 0;
3121 return data.keyCount();
3122}
3123
3124/*!
3125 Returns the key with the given \a index, or \nullptr if no such key exists.
3126
3127 \sa keyCount(), value(), valueToKey()
3128*/
3129const char *QMetaEnum::key(int index) const
3130{
3131 if (!mobj)
3132 return nullptr;
3133 if (index >= 0 && index < int(data.keyCount()))
3134 return rawStringData(mo: mobj, index: mobj->d.data[data.data() + 2*index]);
3135 return nullptr;
3136}
3137
3138/*!
3139 Returns the value with the given \a index; or returns -1 if there
3140 is no such value.
3141
3142 \sa keyCount(), key(), keyToValue()
3143*/
3144int QMetaEnum::value(int index) const
3145{
3146 if (!mobj)
3147 return 0;
3148 if (index >= 0 && index < int(data.keyCount()))
3149 return mobj->d.data[data.data() + 2 * index + 1];
3150 return -1;
3151}
3152
3153/*!
3154 Returns \c true if this enumerator is used as a flag; otherwise returns
3155 false.
3156
3157 When used as flags, enumerators can be combined using the OR
3158 operator.
3159
3160 \sa keysToValue(), valueToKeys()
3161*/
3162bool QMetaEnum::isFlag() const
3163{
3164 if (!mobj)
3165 return false;
3166 return data.flags() & EnumIsFlag;
3167}
3168
3169/*!
3170 \since 5.8
3171
3172 Returns \c true if this enumerator is declared as a C++11 enum class;
3173 otherwise returns false.
3174*/
3175bool QMetaEnum::isScoped() const
3176{
3177 if (!mobj)
3178 return false;
3179 return data.flags() & EnumIsScoped;
3180}
3181
3182/*!
3183 Returns the scope this enumerator was declared in.
3184
3185 For example, the Qt::AlignmentFlag enumeration has \c Qt as
3186 the scope and \c AlignmentFlag as the name.
3187
3188 \sa name()
3189*/
3190const char *QMetaEnum::scope() const
3191{
3192 return mobj ? mobj->className() : nullptr;
3193}
3194
3195static bool isScopeMatch(QByteArrayView scope, const QMetaEnum *e)
3196{
3197 const QByteArrayView className = e->enclosingMetaObject()->className();
3198
3199 // Typical use-cases:
3200 // a) Unscoped: namespace N { class C { enum E { F }; }; }; key == "N::C::F"
3201 // b) Scoped: namespace N { class C { enum class E { F }; }; }; key == "N::C::E::F"
3202 if (scope == className)
3203 return true;
3204
3205 // Not using name() because if isFlag() is true, we want the actual name
3206 // of the enum, e.g. "MyFlag", not "MyFlags", e.g.
3207 // enum MyFlag { F1, F2 }; Q_DECLARE_FLAGS(MyFlags, MyFlag);
3208 QByteArrayView name = e->enumName();
3209
3210 // Match fully qualified enumerator in unscoped enums, key == "N::C::E::F"
3211 // equivalent to use-case "a" above
3212 const auto sz = className.size();
3213 if (scope.size() == sz + qsizetype(qstrlen(str: "::")) + name.size()
3214 && scope.startsWith(other: className)
3215 && scope.sliced(pos: sz, n: 2) == "::"
3216 && scope.sliced(pos: sz + 2) == name)
3217 return true;
3218
3219 return false;
3220}
3221
3222/*!
3223 Returns the integer value of the given enumeration \a key, or -1
3224 if \a key is not defined.
3225
3226 If \a key is not defined, *\a{ok} is set to false; otherwise
3227 *\a{ok} is set to true.
3228
3229 For flag types, use keysToValue().
3230
3231 \sa valueToKey(), isFlag(), keysToValue()
3232*/
3233int QMetaEnum::keyToValue(const char *key, bool *ok) const
3234{
3235 if (ok != nullptr)
3236 *ok = false;
3237 if (!mobj || !key)
3238 return -1;
3239
3240 const auto [scope, enumKey] = parse_scope(qualifiedKey: QLatin1StringView(key));
3241 for (int i = 0; i < int(data.keyCount()); ++i) {
3242 if ((!scope || isScopeMatch(scope: *scope, e: this))
3243 && enumKey == stringDataView(mo: mobj, index: mobj->d.data[data.data() + 2 * i])) {
3244 if (ok != nullptr)
3245 *ok = true;
3246 return mobj->d.data[data.data() + 2 * i + 1];
3247 }
3248 }
3249 return -1;
3250}
3251
3252/*!
3253 Returns the string that is used as the name of the given
3254 enumeration \a value, or \nullptr if \a value is not defined.
3255
3256 For flag types, use valueToKeys().
3257
3258 \sa isFlag(), valueToKeys()
3259*/
3260const char *QMetaEnum::valueToKey(int value) const
3261{
3262 if (!mobj)
3263 return nullptr;
3264 for (int i = 0; i < int(data.keyCount()); ++i)
3265 if (value == (int)mobj->d.data[data.data() + 2 * i + 1])
3266 return rawStringData(mo: mobj, index: mobj->d.data[data.data() + 2 * i]);
3267 return nullptr;
3268}
3269
3270static bool parseEnumFlags(QByteArrayView v, QVarLengthArray<QByteArrayView, 10> &list)
3271{
3272 v = v.trimmed();
3273 if (v.empty()) {
3274 qWarning(msg: "QMetaEnum::keysToValue: empty keys string.");
3275 return false;
3276 }
3277
3278 qsizetype sep = v.indexOf(ch: '|', from: 0);
3279 if (sep == 0) {
3280 qWarning(msg: "QMetaEnum::keysToValue: malformed keys string, starts with '|', \"%s\"",
3281 v.constData());
3282 return false;
3283 }
3284
3285 if (sep == -1) { // One flag
3286 list.push_back(t: v);
3287 return true;
3288 }
3289
3290 if (v.endsWith(c: '|')) {
3291 qWarning(msg: "QMetaEnum::keysToValue: malformed keys string, ends with '|', \"%s\"",
3292 v.constData());
3293 return false;
3294 }
3295
3296 const auto begin = v.begin();
3297 const auto end = v.end();
3298 auto b = begin;
3299 for (; b != end && sep != -1; sep = v.indexOf(ch: '|', from: sep)) {
3300 list.push_back(t: {b, begin + sep});
3301 ++sep; // Skip over '|'
3302 b = begin + sep;
3303 if (*b == '|') {
3304 qWarning(msg: "QMetaEnum::keysToValue: malformed keys string, has two consecutive '|': "
3305 "\"%s\"", v.constData());
3306 return false;
3307 }
3308 }
3309
3310 // The rest of the string
3311 list.push_back(t: {b, end});
3312 return true;
3313}
3314
3315/*!
3316 Returns the value derived from combining together the values of
3317 the \a keys using the OR operator, or -1 if \a keys is not
3318 defined. Note that the strings in \a keys must be '|'-separated.
3319
3320 If \a keys is not defined, *\a{ok} is set to false; otherwise
3321 *\a{ok} is set to true.
3322
3323 \sa isFlag(), valueToKey(), valueToKeys()
3324*/
3325int QMetaEnum::keysToValue(const char *keys, bool *ok) const
3326{
3327 if (ok != nullptr)
3328 *ok = false;
3329 if (!mobj || !keys)
3330 return -1;
3331
3332 auto lookup = [&] (QByteArrayView key) -> std::optional<int> {
3333 for (int i = data.keyCount() - 1; i >= 0; --i) {
3334 if (key == stringDataView(mo: mobj, index: mobj->d.data[data.data() + 2*i]))
3335 return mobj->d.data[data.data() + 2*i + 1];
3336 }
3337 return std::nullopt;
3338 };
3339
3340 int value = 0;
3341 QVarLengthArray<QByteArrayView, 10> list;
3342 const bool r = parseEnumFlags(v: QByteArrayView{keys}, list);
3343 if (!r)
3344 return -1;
3345 for (const auto &untrimmed : list) {
3346 const auto parsed = parse_scope(qualifiedKey: untrimmed.trimmed());
3347 if (parsed.scope && !isScopeMatch(scope: *parsed.scope, e: this))
3348 return -1; // wrong type name in qualified name
3349 if (auto thisValue = lookup(parsed.key))
3350 value |= *thisValue;
3351 else
3352 return -1; // no such enumerator
3353 }
3354 if (ok != nullptr)
3355 *ok = true;
3356 return value;
3357}
3358
3359namespace
3360{
3361template <typename String, typename Container, typename Separator>
3362void join_reversed(String &s, const Container &c, Separator sep)
3363{
3364 if (c.empty())
3365 return;
3366 qsizetype len = qsizetype(c.size()) - 1; // N - 1 separators
3367 for (auto &e : c)
3368 len += qsizetype(e.size()); // N parts
3369 s.reserve(len);
3370 bool first = true;
3371 for (auto rit = c.rbegin(), rend = c.rend(); rit != rend; ++rit) {
3372 const auto &e = *rit;
3373 if (!first)
3374 s.append(sep);
3375 first = false;
3376 s.append(e.data(), e.size());
3377 }
3378}
3379} // unnamed namespace
3380
3381/*!
3382 Returns a byte array of '|'-separated keys that represents the
3383 given \a value.
3384
3385 \sa isFlag(), valueToKey(), keysToValue()
3386*/
3387QByteArray QMetaEnum::valueToKeys(int value) const
3388{
3389 QByteArray keys;
3390 if (!mobj)
3391 return keys;
3392 QVarLengthArray<QByteArrayView, sizeof(int) * CHAR_BIT> parts;
3393 int v = value;
3394 // reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
3395 for (int i = data.keyCount() - 1; i >= 0; --i) {
3396 int k = mobj->d.data[data.data() + 2 * i + 1];
3397 if ((k != 0 && (v & k) == k) || (k == value)) {
3398 v = v & ~k;
3399 parts.push_back(t: stringDataView(mo: mobj, index: mobj->d.data[data.data() + 2 * i]));
3400 }
3401 }
3402 join_reversed(s&: keys, c: parts, sep: '|');
3403 return keys;
3404}
3405
3406/*!
3407 \internal
3408 */
3409QMetaEnum::QMetaEnum(const QMetaObject *mobj, int index)
3410 : mobj(mobj), data({ .d: mobj->d.data + priv(data: mobj->d.data)->enumeratorData + index * Data::Size })
3411{
3412 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->enumeratorCount);
3413}
3414
3415int QMetaEnum::Data::index(const QMetaObject *mobj) const
3416{
3417 return (d - mobj->d.data - priv(data: mobj->d.data)->enumeratorData) / Size;
3418}
3419
3420/*!
3421 \fn template<typename T> QMetaEnum QMetaEnum::fromType()
3422 \since 5.5
3423
3424 Returns the QMetaEnum corresponding to the type in the template parameter.
3425 The enum needs to be declared with Q_ENUM.
3426*/
3427
3428/*!
3429 \class QMetaProperty
3430 \inmodule QtCore
3431 \brief The QMetaProperty class provides meta-data about a property.
3432
3433 \ingroup objectmodel
3434
3435 Property meta-data is obtained from an object's meta-object. See
3436 QMetaObject::property() and QMetaObject::propertyCount() for
3437 details.
3438
3439 \section1 Property Meta-Data
3440
3441 A property has a name() and a metaType(), as well as various
3442 attributes that specify its behavior: isReadable(), isWritable(),
3443 isDesignable(), isScriptable(), revision(), and isStored().
3444
3445 If the property is an enumeration, isEnumType() returns \c true; if the
3446 property is an enumeration that is also a flag (i.e. its values
3447 can be combined using the OR operator), isEnumType() and
3448 isFlagType() both return true. The enumerator for these types is
3449 available from enumerator().
3450
3451 The property's values are set and retrieved with read(), write(),
3452 and reset(); they can also be changed through QObject's set and get
3453 functions. See QObject::setProperty() and QObject::property() for
3454 details.
3455
3456 \section1 Copying and Assignment
3457
3458 QMetaProperty objects can be copied by value. However, each copy will
3459 refer to the same underlying property meta-data.
3460
3461 \sa QMetaObject, QMetaEnum, QMetaMethod, {Qt's Property System}
3462*/
3463
3464/*!
3465 \fn bool QMetaProperty::isValid() const
3466
3467 Returns \c true if this property is valid (readable); otherwise
3468 returns \c false.
3469
3470 \sa isReadable()
3471*/
3472
3473/*!
3474 \fn const QMetaObject *QMetaProperty::enclosingMetaObject() const
3475 \internal
3476*/
3477
3478/*!
3479 \fn QMetaProperty::QMetaProperty()
3480 \internal
3481*/
3482
3483/*!
3484 Returns this property's name.
3485
3486 \sa type(), typeName()
3487*/
3488const char *QMetaProperty::name() const
3489{
3490 if (!mobj)
3491 return nullptr;
3492 return rawStringData(mo: mobj, index: data.name());
3493}
3494
3495/*!
3496 Returns the name of this property's type.
3497
3498 \sa type(), name()
3499*/
3500const char *QMetaProperty::typeName() const
3501{
3502 if (!mobj)
3503 return nullptr;
3504 // TODO: can the metatype be invalid for dynamic metaobjects?
3505 if (const auto mt = metaType(); mt.isValid())
3506 return mt.name();
3507 return typeNameFromTypeInfo(mo: mobj, typeInfo: data.type()).constData();
3508}
3509
3510/*! \fn QVariant::Type QMetaProperty::type() const
3511 \deprecated
3512
3513 Returns this property's type. The return value is one
3514 of the values of the QVariant::Type enumeration.
3515
3516 \sa typeName(), name(), metaType()
3517*/
3518
3519/*! \fn int QMetaProperty::userType() const
3520 \since 4.2
3521
3522 Returns this property's user type. The return value is one
3523 of the values that are registered with QMetaType.
3524
3525 This is equivalent to metaType().id()
3526
3527 \sa type(), QMetaType, typeName(), metaType()
3528 */
3529
3530/*! \fn int QMetaProperty::typeId() const
3531 \since 6.0
3532
3533 Returns the storage type of the property. This is
3534 the same as metaType().id().
3535
3536 \sa QMetaType, typeName(), metaType()
3537 */
3538
3539/*!
3540 \since 6.0
3541
3542 Returns this property's QMetaType.
3543
3544 \sa QMetaType
3545 */
3546QMetaType QMetaProperty::metaType() const
3547{
3548 if (!mobj)
3549 return {};
3550 return QMetaType(mobj->d.metaTypes[data.index(mobj)]);
3551}
3552
3553int QMetaProperty::Data::index(const QMetaObject *mobj) const
3554{
3555 return (d - mobj->d.data - priv(data: mobj->d.data)->propertyData) / Size;
3556}
3557
3558/*!
3559 \since 4.6
3560
3561 Returns this property's index.
3562*/
3563int QMetaProperty::propertyIndex() const
3564{
3565 if (!mobj)
3566 return -1;
3567 return data.index(mobj) + mobj->propertyOffset();
3568}
3569
3570/*!
3571 \since 5.14
3572
3573 Returns this property's index relative within the enclosing meta object.
3574*/
3575int QMetaProperty::relativePropertyIndex() const
3576{
3577 if (!mobj)
3578 return -1;
3579 return data.index(mobj);
3580}
3581
3582/*!
3583 Returns \c true if the property's type is an enumeration value that
3584 is used as a flag; otherwise returns \c false.
3585
3586 Flags can be combined using the OR operator. A flag type is
3587 implicitly also an enum type.
3588
3589 \sa isEnumType(), enumerator(), QMetaEnum::isFlag()
3590*/
3591
3592bool QMetaProperty::isFlagType() const
3593{
3594 return isEnumType() && menum.isFlag();
3595}
3596
3597/*!
3598 Returns \c true if the property's type is an enumeration value;
3599 otherwise returns \c false.
3600
3601 \sa enumerator(), isFlagType()
3602*/
3603bool QMetaProperty::isEnumType() const
3604{
3605 if (!mobj)
3606 return false;
3607 return (data.flags() & EnumOrFlag) && menum.name();
3608}
3609
3610/*!
3611 \internal
3612
3613 Returns \c true if the property has a C++ setter function that
3614 follows Qt's standard "name" / "setName" pattern. Designer and uic
3615 query hasStdCppSet() in order to avoid expensive
3616 QObject::setProperty() calls. All properties in Qt [should] follow
3617 this pattern.
3618*/
3619bool QMetaProperty::hasStdCppSet() const
3620{
3621 if (!mobj)
3622 return false;
3623 return (data.flags() & StdCppSet);
3624}
3625
3626/*!
3627 \internal
3628
3629 Returns \c true if the property is an alias.
3630 This is for instance true for a property declared in QML
3631 as 'property alias'.
3632*/
3633bool QMetaProperty::isAlias() const
3634{
3635 if (!mobj)
3636 return false;
3637 return (data.flags() & Alias);
3638}
3639
3640#if QT_DEPRECATED_SINCE(6, 4)
3641/*!
3642 \internal
3643 Historically:
3644 Executes metacall with QMetaObject::RegisterPropertyMetaType flag.
3645 Returns id of registered type or QMetaType::UnknownType if a type
3646 could not be registered for any reason.
3647 Obsolete since Qt 6
3648*/
3649int QMetaProperty::registerPropertyType() const
3650{
3651 return typeId();
3652}
3653#endif
3654
3655QMetaProperty::QMetaProperty(const QMetaObject *mobj, int index)
3656 : mobj(mobj),
3657 data(getMetaPropertyData(mobj, index))
3658{
3659 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->propertyCount);
3660 // The code below here just resolves menum if the property is an enum type:
3661 if (!(data.flags() & EnumOrFlag) || !metaType().flags().testFlag(flag: QMetaType::IsEnumeration))
3662 return;
3663 QByteArrayView enum_name = typeNameFromTypeInfo(mo: mobj, typeInfo: data.type());
3664 menum = mobj->enumerator(index: QMetaObjectPrivate::indexOfEnumerator(m: mobj, name: enum_name));
3665 if (menum.isValid())
3666 return;
3667
3668 QByteArrayView scope_name;
3669 const auto parsed = parse_scope(qualifiedKey: enum_name);
3670 if (parsed.scope) {
3671 scope_name = *parsed.scope;
3672 enum_name = parsed.key;
3673 } else {
3674 scope_name = objectClassName(m: mobj);
3675 }
3676
3677 const QMetaObject *scope = nullptr;
3678 if (scope_name == "Qt")
3679 scope = &Qt::staticMetaObject;
3680 else
3681 scope = QMetaObject_findMetaObject(self: mobj, name: QByteArrayView(scope_name));
3682
3683 if (scope)
3684 menum = scope->enumerator(index: QMetaObjectPrivate::indexOfEnumerator(m: scope, name: enum_name));
3685}
3686
3687/*!
3688 \internal
3689 Constructs the \c QMetaProperty::Data for the \a index th property of \a mobj
3690 */
3691QMetaProperty::Data QMetaProperty::getMetaPropertyData(const QMetaObject *mobj, int index)
3692{
3693 return { .d: mobj->d.data + priv(data: mobj->d.data)->propertyData + index * Data::Size };
3694}
3695
3696/*!
3697 Returns the enumerator if this property's type is an enumerator
3698 type; otherwise the returned value is undefined.
3699
3700 \sa isEnumType(), isFlagType()
3701*/
3702QMetaEnum QMetaProperty::enumerator() const
3703{
3704 return menum;
3705}
3706
3707/*!
3708 Reads the property's value from the given \a object. Returns the value
3709 if it was able to read it; otherwise returns an invalid variant.
3710
3711 \sa write(), reset(), isReadable()
3712*/
3713QVariant QMetaProperty::read(const QObject *object) const
3714{
3715 if (!object || !mobj)
3716 return QVariant();
3717
3718 // the status variable is changed by qt_metacall to indicate what it did
3719 // this feature is currently only used by Qt D-Bus and should not be depended
3720 // upon. Don't change it without looking into QDBusAbstractInterface first
3721 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
3722 // changed: result stored directly in value
3723 int status = -1;
3724 QVariant value;
3725 void *argv[] = { nullptr, &value, &status };
3726 QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
3727 if (t == QMetaType::fromType<QVariant>()) {
3728 argv[0] = &value;
3729 } else {
3730 value = QVariant(t, nullptr);
3731 argv[0] = value.data();
3732 }
3733 if (priv(data: mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall) {
3734 mobj->d.static_metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty, data.index(mobj), argv);
3735 } else {
3736 QMetaObject::metacall(object: const_cast<QObject*>(object), cl: QMetaObject::ReadProperty,
3737 idx: data.index(mobj) + mobj->propertyOffset(), argv);
3738 }
3739
3740 if (status != -1)
3741 return value;
3742 if (t != QMetaType::fromType<QVariant>() && argv[0] != value.data())
3743 // pointer or reference
3744 return QVariant(t, argv[0]);
3745 return value;
3746}
3747
3748/*!
3749 Writes \a value as the property's value to the given \a object. Returns
3750 true if the write succeeded; otherwise returns \c false.
3751
3752 If \a value is not of the same type as the property, a conversion
3753 is attempted. An empty QVariant() is equivalent to a call to reset()
3754 if this property is resettable, or setting a default-constructed object
3755 otherwise.
3756
3757 \note This function internally makes a copy of \a value. Prefer to use the
3758 rvalue overload when possible.
3759
3760 \sa read(), reset(), isWritable()
3761*/
3762bool QMetaProperty::write(QObject *object, const QVariant &value) const
3763{
3764 if (!object || !isWritable())
3765 return false;
3766 return write(obj: object, value: QVariant(value));
3767}
3768
3769/*!
3770 \overload
3771 \since 6.6
3772*/
3773bool QMetaProperty::write(QObject *object, QVariant &&v) const
3774{
3775 if (!object || !isWritable())
3776 return false;
3777 QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
3778 if (t != QMetaType::fromType<QVariant>() && t != v.metaType()) {
3779 if (isEnumType() && !t.metaObject() && v.metaType() == QMetaType::fromType<QString>()) {
3780 // Assigning a string to a property of type Q_ENUMS (instead of Q_ENUM)
3781 // means the QMetaType has no associated QMetaObject, so it can't
3782 // do the conversion (see qmetatype.cpp:convertToEnum()).
3783 bool ok;
3784 if (isFlagType())
3785 v = QVariant(menum.keysToValue(keys: v.toByteArray(), ok: &ok));
3786 else
3787 v = QVariant(menum.keyToValue(key: v.toByteArray(), ok: &ok));
3788 if (!ok)
3789 return false;
3790 }
3791 if (!v.isValid()) {
3792 if (isResettable())
3793 return reset(obj: object);
3794 v = QVariant(t, nullptr);
3795 } else if (!v.convert(type: t)) {
3796 return false;
3797 }
3798 }
3799 // the status variable is changed by qt_metacall to indicate what it did
3800 // this feature is currently only used by Qt D-Bus and should not be depended
3801 // upon. Don't change it without looking into QDBusAbstractInterface first
3802 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
3803 // changed: result stored directly in value, return the value of status
3804 int status = -1;
3805 // the flags variable is used by the declarative module to implement
3806 // interception of property writes.
3807 int flags = 0;
3808 void *argv[] = { nullptr, &v, &status, &flags };
3809 if (t == QMetaType::fromType<QVariant>())
3810 argv[0] = &v;
3811 else
3812 argv[0] = v.data();
3813 if (priv(data: mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall)
3814 mobj->d.static_metacall(object, QMetaObject::WriteProperty, data.index(mobj), argv);
3815 else
3816 QMetaObject::metacall(object, cl: QMetaObject::WriteProperty, idx: data.index(mobj) + mobj->propertyOffset(), argv);
3817
3818 return status;
3819}
3820
3821/*!
3822 Resets the property for the given \a object with a reset method.
3823 Returns \c true if the reset worked; otherwise returns \c false.
3824
3825 Reset methods are optional; only a few properties support them.
3826
3827 \sa read(), write()
3828*/
3829bool QMetaProperty::reset(QObject *object) const
3830{
3831 if (!object || !mobj || !isResettable())
3832 return false;
3833 void *argv[] = { nullptr };
3834 if (priv(data: mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall)
3835 mobj->d.static_metacall(object, QMetaObject::ResetProperty, data.index(mobj), argv);
3836 else
3837 QMetaObject::metacall(object, cl: QMetaObject::ResetProperty, idx: data.index(mobj) + mobj->propertyOffset(), argv);
3838 return true;
3839}
3840
3841/*!
3842 \since 6.0
3843 Returns the bindable interface for the property on a given \a object.
3844
3845 If the property doesn't support bindings, the returned interface will be
3846 invalid.
3847
3848 \sa QObjectBindableProperty, QProperty, isBindable()
3849*/
3850QUntypedBindable QMetaProperty::bindable(QObject *object) const
3851{
3852 QUntypedBindable bindable;
3853 void * argv[1] { &bindable };
3854 mobj->metacall(object, cl: QMetaObject::BindableProperty, idx: data.index(mobj) + mobj->propertyOffset(), argv);
3855 return bindable;
3856}
3857/*!
3858 \since 5.5
3859
3860 Reads the property's value from the given \a gadget. Returns the value
3861 if it was able to read it; otherwise returns an invalid variant.
3862
3863 This function should only be used if this is a property of a Q_GADGET
3864*/
3865QVariant QMetaProperty::readOnGadget(const void *gadget) const
3866{
3867 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3868 return read(object: reinterpret_cast<const QObject*>(gadget));
3869}
3870
3871/*!
3872 \since 5.5
3873
3874 Writes \a value as the property's value to the given \a gadget. Returns
3875 true if the write succeeded; otherwise returns \c false.
3876
3877 This function should only be used if this is a property of a Q_GADGET
3878*/
3879bool QMetaProperty::writeOnGadget(void *gadget, const QVariant &value) const
3880{
3881 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3882 return write(object: reinterpret_cast<QObject*>(gadget), value);
3883}
3884
3885/*!
3886 \overload
3887 \since 6.6
3888*/
3889bool QMetaProperty::writeOnGadget(void *gadget, QVariant &&value) const
3890{
3891 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3892 return write(object: reinterpret_cast<QObject*>(gadget), v: std::move(value));
3893}
3894
3895/*!
3896 \since 5.5
3897
3898 Resets the property for the given \a gadget with a reset method.
3899 Returns \c true if the reset worked; otherwise returns \c false.
3900
3901 Reset methods are optional; only a few properties support them.
3902
3903 This function should only be used if this is a property of a Q_GADGET
3904*/
3905bool QMetaProperty::resetOnGadget(void *gadget) const
3906{
3907 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3908 return reset(object: reinterpret_cast<QObject*>(gadget));
3909}
3910
3911/*!
3912 Returns \c true if this property can be reset to a default value; otherwise
3913 returns \c false.
3914
3915 \sa reset()
3916*/
3917bool QMetaProperty::isResettable() const
3918{
3919 if (!mobj)
3920 return false;
3921 return data.flags() & Resettable;
3922}
3923
3924/*!
3925 Returns \c true if this property is readable; otherwise returns \c false.
3926
3927 \sa isWritable(), read(), isValid()
3928 */
3929bool QMetaProperty::isReadable() const
3930{
3931 if (!mobj)
3932 return false;
3933 return data.flags() & Readable;
3934}
3935
3936/*!
3937 Returns \c true if this property has a corresponding change notify signal;
3938 otherwise returns \c false.
3939
3940 \sa notifySignal()
3941 */
3942bool QMetaProperty::hasNotifySignal() const
3943{
3944 if (!mobj)
3945 return false;
3946 return data.notifyIndex() != uint(-1);
3947}
3948
3949/*!
3950 \since 4.5
3951
3952 Returns the QMetaMethod instance of the property change notifying signal if
3953 one was specified, otherwise returns an invalid QMetaMethod.
3954
3955 \sa hasNotifySignal()
3956 */
3957QMetaMethod QMetaProperty::notifySignal() const
3958{
3959 int id = notifySignalIndex();
3960 if (id != -1)
3961 return mobj->method(index: id);
3962 else
3963 return QMetaMethod();
3964}
3965
3966/*!
3967 \since 4.6
3968
3969 Returns the index of the property change notifying signal if one was
3970 specified, otherwise returns -1.
3971
3972 \sa hasNotifySignal()
3973 */
3974int QMetaProperty::notifySignalIndex() const
3975{
3976 if (!mobj || data.notifyIndex() == std::numeric_limits<uint>::max())
3977 return -1;
3978 uint methodIndex = data.notifyIndex();
3979 if (!(methodIndex & IsUnresolvedSignal))
3980 return methodIndex + mobj->methodOffset();
3981 methodIndex &= ~IsUnresolvedSignal;
3982 const QByteArray signalName = stringData(mo: mobj, index: methodIndex);
3983 const QMetaObject *m = mobj;
3984 // try 0-arg signal
3985 int idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(baseObject: &m, name: signalName, argc: 0, types: nullptr);
3986 if (idx >= 0)
3987 return idx + m->methodOffset();
3988 // try 1-arg signal
3989 QArgumentType argType(typeId());
3990 idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(baseObject: &m, name: signalName, argc: 1, types: &argType);
3991 if (idx >= 0)
3992 return idx + m->methodOffset();
3993 qWarning(msg: "QMetaProperty::notifySignal: cannot find the NOTIFY signal %s in class %s for property '%s'",
3994 signalName.constData(), mobj->className(), name());
3995 return -1;
3996}
3997
3998// This method has been around for a while, but the documentation was marked \internal until 5.1
3999/*!
4000 \since 5.1
4001
4002 Returns the property revision if one was specified by Q_REVISION, otherwise
4003 returns 0. Since Qt 6.0, non-zero values are encoded and can be decoded
4004 using QTypeRevision::fromEncodedVersion().
4005 */
4006int QMetaProperty::revision() const
4007{
4008 if (!mobj)
4009 return 0;
4010 return data.revision();
4011}
4012
4013/*!
4014 Returns \c true if this property is writable; otherwise returns
4015 false.
4016
4017 \sa isReadable(), write()
4018 */
4019bool QMetaProperty::isWritable() const
4020{
4021 if (!mobj)
4022 return false;
4023 return data.flags() & Writable;
4024}
4025
4026/*!
4027 Returns \c false if the \c{Q_PROPERTY()}'s \c DESIGNABLE attribute
4028 is false; otherwise returns \c true.
4029
4030 \sa isScriptable(), isStored()
4031*/
4032bool QMetaProperty::isDesignable() const
4033{
4034 if (!mobj)
4035 return false;
4036 return data.flags() & Designable;
4037}
4038
4039/*!
4040 Returns \c false if the \c{Q_PROPERTY()}'s \c SCRIPTABLE attribute
4041 is false; otherwise returns true.
4042
4043 \sa isDesignable(), isStored()
4044*/
4045bool QMetaProperty::isScriptable() const
4046{
4047 if (!mobj)
4048 return false;
4049 return data.flags() & Scriptable;
4050}
4051
4052/*!
4053 Returns \c true if the property is stored; otherwise returns
4054 false.
4055
4056 The function returns \c false if the
4057 \c{Q_PROPERTY()}'s \c STORED attribute is false; otherwise returns
4058 true.
4059
4060 \sa isDesignable(), isScriptable()
4061*/
4062bool QMetaProperty::isStored() const
4063{
4064 if (!mobj)
4065 return false;
4066 return data.flags() & Stored;
4067}
4068
4069/*!
4070 Returns \c false if the \c {Q_PROPERTY()}'s \c USER attribute is false.
4071 Otherwise it returns true, indicating the property is designated as the
4072 \c USER property, i.e., the one that the user can edit or
4073 that is significant in some other way.
4074
4075 \sa QMetaObject::userProperty(), isDesignable(), isScriptable()
4076*/
4077bool QMetaProperty::isUser() const
4078{
4079 if (!mobj)
4080 return false;
4081 return data.flags() & User;
4082}
4083
4084/*!
4085 \since 4.6
4086 Returns \c true if the property is constant; otherwise returns \c false.
4087
4088 A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute
4089 is set.
4090*/
4091bool QMetaProperty::isConstant() const
4092{
4093 if (!mobj)
4094 return false;
4095 return data.flags() & Constant;
4096}
4097
4098/*!
4099 \since 4.6
4100 Returns \c true if the property is final; otherwise returns \c false.
4101
4102 A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute
4103 is set.
4104*/
4105bool QMetaProperty::isFinal() const
4106{
4107 if (!mobj)
4108 return false;
4109 return data.flags() & Final;
4110}
4111
4112/*!
4113 \since 5.15
4114 Returns \c true if the property is required; otherwise returns \c false.
4115
4116 A property is final if the \c{Q_PROPERTY()}'s \c REQUIRED attribute
4117 is set.
4118*/
4119bool QMetaProperty::isRequired() const
4120{
4121 if (!mobj)
4122 return false;
4123 return data.flags() & Required;
4124}
4125
4126/*!
4127 \since 6.0
4128 Returns \c true if the \c{Q_PROPERTY()} exposes binding functionality; otherwise returns false.
4129
4130 This implies that you can create bindings that use this property as a dependency or install QPropertyObserver
4131 objects on this property. Unless the property is readonly, you can also set a binding on this property.
4132
4133 \sa QProperty, isWritable(), bindable()
4134*/
4135bool QMetaProperty::isBindable() const
4136{
4137 if (!mobj)
4138 return false;
4139 return (data.flags() & Bindable);
4140}
4141
4142/*!
4143 \class QMetaClassInfo
4144 \inmodule QtCore
4145
4146 \brief The QMetaClassInfo class provides additional information
4147 about a class.
4148
4149 \ingroup objectmodel
4150
4151 Class information items are simple \e{name}--\e{value} pairs that
4152 are specified using Q_CLASSINFO() in the source code. The
4153 information can be retrieved using name() and value(). For example:
4154
4155 \snippet code/src_corelib_kernel_qmetaobject.cpp 5
4156
4157 This mechanism is free for you to use in your Qt applications.
4158
4159 \note It's also used by the \l[ActiveQt]{Active Qt},
4160 \l[QtDBus]{Qt D-Bus}, \l[QtQml]{Qt Qml}, and \l{Qt Remote Objects}
4161 modules. Some keys might be set when using these modules.
4162
4163 \sa QMetaObject
4164*/
4165
4166/*!
4167 \fn QMetaClassInfo::QMetaClassInfo()
4168 \internal
4169*/
4170
4171/*!
4172 \fn const QMetaObject *QMetaClassInfo::enclosingMetaObject() const
4173 \internal
4174*/
4175
4176/*!
4177 Returns the name of this item.
4178
4179 \sa value()
4180*/
4181const char *QMetaClassInfo::name() const
4182{
4183 if (!mobj)
4184 return nullptr;
4185 return rawStringData(mo: mobj, index: data.name());
4186}
4187
4188/*!
4189 Returns the value of this item.
4190
4191 \sa name()
4192*/
4193const char *QMetaClassInfo::value() const
4194{
4195 if (!mobj)
4196 return nullptr;
4197 return rawStringData(mo: mobj, index: data.value());
4198}
4199
4200/*!
4201 \class QMethodRawArguments
4202 \internal
4203
4204 A wrapper class for the void ** arguments array used by the meta
4205 object system. If a slot uses a single argument of this type,
4206 the meta object system will pass the raw arguments array directly
4207 to the slot and set the arguments count in the slot description to
4208 zero, so that any signal can connect to it.
4209
4210 This is used internally to implement signal relay functionality in
4211 our state machine and dbus.
4212*/
4213
4214/*!
4215 \macro QMetaMethodArgument Q_ARG(Type, const Type &value)
4216 \relates QMetaObject
4217
4218 This macro takes a \a Type and a \a value of that type and
4219 returns a QMetaMethodArgument, which can be passed to the template
4220 QMetaObject::invokeMethod() with the \c {Args &&...} arguments.
4221
4222 \sa Q_RETURN_ARG()
4223*/
4224
4225/*!
4226 \macro QMetaMethodReturnArgument Q_RETURN_ARG(Type, Type &value)
4227 \relates QMetaObject
4228
4229 This macro takes a \a Type and a non-const reference to a \a
4230 value of that type and returns a QMetaMethodReturnArgument, which can be
4231 passed to the template QMetaObject::invokeMethod() with the \c {Args &&...}
4232 arguments.
4233
4234 \sa Q_ARG()
4235*/
4236
4237/*!
4238 \class QGenericArgument
4239 \inmodule QtCore
4240
4241 \brief The QGenericArgument class is an internal helper class for
4242 marshalling arguments.
4243
4244 This class should never be used directly. Please use the \l Q_ARG()
4245 macro instead.
4246
4247 \sa Q_ARG(), QMetaObject::invokeMethod(), QGenericReturnArgument
4248*/
4249
4250/*!
4251 \fn QGenericArgument::QGenericArgument(const char *name, const void *data)
4252
4253 Constructs a QGenericArgument object with the given \a name and \a data.
4254*/
4255
4256/*!
4257 \fn QGenericArgument::data () const
4258
4259 Returns the data set in the constructor.
4260*/
4261
4262/*!
4263 \fn QGenericArgument::name () const
4264
4265 Returns the name set in the constructor.
4266*/
4267
4268/*!
4269 \class QGenericReturnArgument
4270 \inmodule QtCore
4271
4272 \brief The QGenericReturnArgument class is an internal helper class for
4273 marshalling arguments.
4274
4275 This class should never be used directly. Please use the
4276 Q_RETURN_ARG() macro instead.
4277
4278 \sa Q_RETURN_ARG(), QMetaObject::invokeMethod(), QGenericArgument
4279*/
4280
4281/*!
4282 \fn QGenericReturnArgument::QGenericReturnArgument(const char *name, void *data)
4283
4284 Constructs a QGenericReturnArgument object with the given \a name
4285 and \a data.
4286*/
4287
4288/*!
4289 \internal
4290 If the local_method_index is a cloned method, return the index of the original.
4291
4292 Example: if the index of "destroyed()" is passed, the index of "destroyed(QObject*)" is returned
4293 */
4294int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
4295{
4296 Q_ASSERT(local_method_index < get(mobj)->methodCount);
4297 while (QMetaMethod::fromRelativeMethodIndex(mobj, index: local_method_index).data.flags() & MethodCloned) {
4298 Q_ASSERT(local_method_index > 0);
4299 --local_method_index;
4300 }
4301 return local_method_index;
4302}
4303
4304/*!
4305 \internal
4306
4307 Returns the parameter type names extracted from the given \a signature.
4308*/
4309QList<QByteArray> QMetaObjectPrivate::parameterTypeNamesFromSignature(const char *signature)
4310{
4311 QList<QByteArray> list;
4312 while (*signature && *signature != '(')
4313 ++signature;
4314 while (*signature && *signature != ')' && *++signature != ')') {
4315 const char *begin = signature;
4316 int level = 0;
4317 while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
4318 if (*signature == '<')
4319 ++level;
4320 else if (*signature == '>')
4321 --level;
4322 ++signature;
4323 }
4324 list += QByteArray(begin, signature - begin);
4325 }
4326 return list;
4327}
4328
4329QT_END_NAMESPACE
4330

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