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 deleteLater() slot and a 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 name() 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
1791 Swaps this Connection instance with \a other. This operation is very fast
1792 and never fails.
1793*/
1794
1795/*!
1796 \class QMetaMethod
1797 \inmodule QtCore
1798
1799 \brief The QMetaMethod class provides meta-data about a member
1800 function.
1801
1802 \ingroup objectmodel
1803 \compares equality
1804
1805 A QMetaMethod has a methodType(), a methodSignature(), a list of
1806 parameterTypes() and parameterNames(), a return typeName(), a
1807 tag(), and an access() specifier. You can use invoke() to invoke
1808 the method on an arbitrary QObject.
1809
1810 \sa QMetaObject, QMetaEnum, QMetaProperty, {Qt's Property System}
1811*/
1812
1813/*!
1814 \enum QMetaMethod::Attributes
1815
1816 \internal
1817
1818 \value Compatibility
1819 \value Cloned
1820 \value Scriptable
1821*/
1822
1823/*!
1824 \fn bool QMetaMethod::isValid() const
1825 \since 5.0
1826
1827 Returns \c true if this method is valid (can be introspected and
1828 invoked), otherwise returns \c false.
1829*/
1830
1831/*! \fn bool QMetaMethod::operator==(const QMetaMethod &lhs, const QMetaMethod &rhs)
1832 \since 5.0
1833 \overload
1834
1835 Returns \c true if method \a lhs is equal to method \a rhs,
1836 otherwise returns \c false.
1837*/
1838
1839/*! \fn bool QMetaMethod::operator!=(const QMetaMethod &lhs, const QMetaMethod &rhs)
1840 \since 5.0
1841 \overload
1842
1843 Returns \c true if method \a lhs is not equal to method \a rhs,
1844 otherwise returns \c false.
1845*/
1846
1847/*!
1848 \fn const QMetaObject *QMetaMethod::enclosingMetaObject() const
1849 \internal
1850*/
1851
1852/*!
1853 \enum QMetaMethod::MethodType
1854
1855 \value Method The function is a plain member function.
1856 \value Signal The function is a signal.
1857 \value Slot The function is a slot.
1858 \value Constructor The function is a constructor.
1859*/
1860
1861/*!
1862 \fn QMetaMethod::QMetaMethod()
1863 \internal
1864*/
1865
1866/*!
1867 \internal
1868*/
1869QMetaMethod QMetaMethod::fromRelativeMethodIndex(const QMetaObject *mobj, int index)
1870{
1871 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->methodCount);
1872 QMetaMethod m;
1873 m.mobj = mobj;
1874 m.data = { .d: mobj->d.data + priv(data: mobj->d.data)->methodData + index * Data::Size };
1875 return m;
1876}
1877
1878QMetaMethod QMetaMethod::fromRelativeConstructorIndex(const QMetaObject *mobj, int index)
1879{
1880 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->constructorCount);
1881 QMetaMethod m;
1882 m.mobj = mobj;
1883 m.data = { .d: mobj->d.data + priv(data: mobj->d.data)->constructorData + index * Data::Size };
1884 return m;
1885}
1886
1887/*!
1888 \macro Q_METAMETHOD_INVOKE_MAX_ARGS
1889 \relates QMetaMethod
1890
1891 Equals maximum number of arguments available for
1892 execution of the method via QMetaMethod::invoke()
1893 */
1894
1895QByteArray QMetaMethodPrivate::signature() const
1896{
1897 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1898 QByteArray result;
1899 result.reserve(asize: 256);
1900 result += name();
1901 result += '(';
1902 QList<QByteArray> argTypes = parameterTypes();
1903 for (int i = 0; i < argTypes.size(); ++i) {
1904 if (i)
1905 result += ',';
1906 result += argTypes.at(i);
1907 }
1908 result += ')';
1909 return result;
1910}
1911
1912QByteArray QMetaMethodPrivate::name() const
1913{
1914 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1915 return stringData(mo: mobj, index: data.name());
1916}
1917
1918int QMetaMethodPrivate::typesDataIndex() const
1919{
1920 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1921 return data.parameters();
1922}
1923
1924const char *QMetaMethodPrivate::rawReturnTypeName() const
1925{
1926 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1927 uint typeInfo = mobj->d.data[typesDataIndex()];
1928 if (typeInfo & IsUnresolvedType)
1929 return rawStringData(mo: mobj, index: typeInfo & TypeNameIndexMask);
1930 else
1931 return QMetaType(typeInfo).name();
1932}
1933
1934int QMetaMethodPrivate::returnType() const
1935{
1936 return parameterType(index: -1);
1937}
1938
1939int QMetaMethodPrivate::parameterCount() const
1940{
1941 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1942 return data.argc();
1943}
1944
1945inline void
1946QMetaMethodPrivate::checkMethodMetaTypeConsistency(const QtPrivate::QMetaTypeInterface *iface,
1947 int index) const
1948{
1949 uint typeInfo = parameterTypeInfo(index);
1950 QMetaType mt(iface);
1951 if (iface) {
1952 if ((typeInfo & IsUnresolvedType) == 0)
1953 Q_ASSERT(mt.id() == int(typeInfo & TypeNameIndexMask));
1954 Q_ASSERT(mt.name());
1955 } else {
1956 // The iface can only be null for a parameter if that parameter is a
1957 // const-ref to a forward-declared type. Since primitive types are
1958 // never incomplete, we can assert it's not one of them.
1959
1960#define ASSERT_NOT_PRIMITIVE_TYPE(TYPE, METATYPEID, NAME) \
1961 Q_ASSERT(typeInfo != QMetaType::TYPE);
1962 QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(ASSERT_NOT_PRIMITIVE_TYPE)
1963#undef ASSERT_NOT_PRIMITIVE_TYPE
1964 Q_ASSERT(typeInfo != QMetaType::QObjectStar);
1965
1966 // Prior to Qt 6.4 we failed to record void and void*
1967 if (priv(data: mobj->d.data)->revision >= 11) {
1968 Q_ASSERT(typeInfo != QMetaType::Void);
1969 Q_ASSERT(typeInfo != QMetaType::VoidStar);
1970 }
1971 }
1972}
1973
1974int QMetaMethodPrivate::parametersDataIndex() const
1975{
1976 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1977 return typesDataIndex() + 1;
1978}
1979
1980uint QMetaMethodPrivate::parameterTypeInfo(int index) const
1981{
1982 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1983 return mobj->d.data[parametersDataIndex() + index];
1984}
1985
1986const QtPrivate::QMetaTypeInterface *QMetaMethodPrivate::returnMetaTypeInterface() const
1987{
1988 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1989 if (methodType() == QMetaMethod::Constructor)
1990 return nullptr; // constructors don't have return types
1991
1992 const QtPrivate::QMetaTypeInterface *iface = mobj->d.metaTypes[data.metaTypeOffset()];
1993 checkMethodMetaTypeConsistency(iface, index: -1);
1994 return iface;
1995}
1996
1997const QtPrivate::QMetaTypeInterface * const *QMetaMethodPrivate::parameterMetaTypeInterfaces() const
1998{
1999 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2000 int offset = (methodType() == QMetaMethod::Constructor ? 0 : 1);
2001 const auto ifaces = &mobj->d.metaTypes[data.metaTypeOffset() + offset];
2002
2003 for (int i = 0; i < parameterCount(); ++i)
2004 checkMethodMetaTypeConsistency(iface: ifaces[i], index: i);
2005
2006 return ifaces;
2007}
2008
2009int QMetaMethodPrivate::parameterType(int index) const
2010{
2011 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2012 return typeFromTypeInfo(mo: mobj, typeInfo: parameterTypeInfo(index));
2013}
2014
2015void QMetaMethodPrivate::getParameterTypes(int *types) const
2016{
2017 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2018 int dataIndex = parametersDataIndex();
2019 int argc = parameterCount();
2020 for (int i = 0; i < argc; ++i) {
2021 int id = typeFromTypeInfo(mo: mobj, typeInfo: mobj->d.data[dataIndex++]);
2022 *(types++) = id;
2023 }
2024}
2025
2026QByteArray QMetaMethodPrivate::parameterTypeName(int index) const
2027{
2028 int paramsIndex = parametersDataIndex();
2029 return typeNameFromTypeInfo(mo: mobj, typeInfo: mobj->d.data[paramsIndex + index]).toByteArray();
2030}
2031
2032QList<QByteArray> QMetaMethodPrivate::parameterTypes() const
2033{
2034 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2035 int argc = parameterCount();
2036 QList<QByteArray> list;
2037 list.reserve(asize: argc);
2038 int paramsIndex = parametersDataIndex();
2039 for (int i = 0; i < argc; ++i) {
2040 QByteArrayView name = typeNameFromTypeInfo(mo: mobj, typeInfo: mobj->d.data[paramsIndex + i]);
2041 list.emplace_back(args: name.toByteArray());
2042 }
2043 return list;
2044}
2045
2046QList<QByteArray> QMetaMethodPrivate::parameterNames() const
2047{
2048 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2049 int argc = parameterCount();
2050 QList<QByteArray> list;
2051 list.reserve(asize: argc);
2052 int namesIndex = parametersDataIndex() + argc;
2053 for (int i = 0; i < argc; ++i)
2054 list += stringData(mo: mobj, index: mobj->d.data[namesIndex + i]);
2055 return list;
2056}
2057
2058QByteArray QMetaMethodPrivate::tag() const
2059{
2060 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2061 return stringData(mo: mobj, index: data.tag());
2062}
2063
2064int QMetaMethodPrivate::ownMethodIndex() const
2065{
2066 // recompute the methodIndex by reversing the arithmetic in QMetaObject::method()
2067 return ( data.d - mobj->d.data - priv(data: mobj->d.data)->methodData)/Data::Size;
2068}
2069
2070int QMetaMethodPrivate::ownConstructorMethodIndex() const
2071{
2072 // recompute the methodIndex by reversing the arithmetic in QMetaObject::constructor()
2073 Q_ASSERT(methodType() == Constructor);
2074 return ( data.d - mobj->d.data - priv(data: mobj->d.data)->constructorData)/Data::Size;
2075}
2076
2077/*!
2078 \since 5.0
2079
2080 Returns the signature of this method (e.g.,
2081 \c{setValue(double)}).
2082
2083 \sa parameterTypes(), parameterNames()
2084*/
2085QByteArray QMetaMethod::methodSignature() const
2086{
2087 if (!mobj)
2088 return QByteArray();
2089 return QMetaMethodPrivate::get(q: this)->signature();
2090}
2091
2092/*!
2093 \since 5.0
2094
2095 Returns the name of this method.
2096
2097 \sa methodSignature(), parameterCount()
2098*/
2099QByteArray QMetaMethod::name() const
2100{
2101 if (!mobj)
2102 return QByteArray();
2103 return QMetaMethodPrivate::get(q: this)->name();
2104}
2105
2106/*!
2107 \since 5.0
2108
2109 Returns the return type of this method.
2110
2111 The return value is one of the types that are registered
2112 with QMetaType, or QMetaType::UnknownType if the type is not registered.
2113
2114 \sa parameterType(), QMetaType, typeName(), returnMetaType()
2115*/
2116int QMetaMethod::returnType() const
2117 {
2118 return returnMetaType().id();
2119}
2120
2121/*!
2122 \since 6.0
2123
2124 Returns the return type of this method.
2125 \sa parameterMetaType(), QMetaType, typeName()
2126*/
2127QMetaType QMetaMethod::returnMetaType() const
2128{
2129 if (!mobj || methodType() == QMetaMethod::Constructor)
2130 return QMetaType{};
2131 auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset()]);
2132 if (mt.id() == QMetaType::UnknownType)
2133 return QMetaType(QMetaMethodPrivate::get(q: this)->returnType());
2134 else
2135 return mt;
2136}
2137
2138/*!
2139 \since 5.0
2140
2141 Returns the number of parameters of this method.
2142
2143 \sa parameterType(), parameterNames()
2144*/
2145int QMetaMethod::parameterCount() const
2146{
2147 if (!mobj)
2148 return 0;
2149 return QMetaMethodPrivate::get(q: this)->parameterCount();
2150}
2151
2152/*!
2153 \since 5.0
2154
2155 Returns the type of the parameter at the given \a index.
2156
2157 The return value is one of the types that are registered
2158 with QMetaType, or QMetaType::UnknownType if the type is not registered.
2159
2160 \sa parameterCount(), parameterMetaType(), returnType(), QMetaType
2161*/
2162int QMetaMethod::parameterType(int index) const
2163{
2164 return parameterMetaType(index).id();
2165}
2166
2167/*!
2168 \since 6.0
2169
2170 Returns the metatype of the parameter at the given \a index.
2171
2172 If the \a index is smaller than zero or larger than
2173 parameterCount(), an invalid QMetaType is returned.
2174
2175 \sa parameterCount(), returnMetaType(), QMetaType
2176*/
2177QMetaType QMetaMethod::parameterMetaType(int index) const
2178{
2179 if (!mobj || index < 0)
2180 return {};
2181 auto priv = QMetaMethodPrivate::get(q: this);
2182 if (index >= priv->parameterCount())
2183 return {};
2184 // + 1 if there exists a return type
2185 auto parameterOffset = index + (methodType() == QMetaMethod::Constructor ? 0 : 1);
2186 auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset() + parameterOffset]);
2187 if (mt.id() == QMetaType::UnknownType)
2188 return QMetaType(QMetaMethodPrivate::get(q: this)->parameterType(index));
2189 else
2190 return mt;
2191}
2192
2193/*!
2194 \since 5.0
2195 \internal
2196
2197 Gets the parameter \a types of this method. The storage
2198 for \a types must be able to hold parameterCount() items.
2199
2200 \sa parameterCount(), returnType(), parameterType()
2201*/
2202void QMetaMethod::getParameterTypes(int *types) const
2203{
2204 if (!mobj)
2205 return;
2206 QMetaMethodPrivate::get(q: this)->getParameterTypes(types);
2207}
2208
2209/*!
2210 Returns a list of parameter types.
2211
2212 \sa parameterNames(), methodSignature()
2213*/
2214QList<QByteArray> QMetaMethod::parameterTypes() const
2215{
2216 if (!mobj)
2217 return QList<QByteArray>();
2218 return QMetaMethodPrivate::get(q: this)->parameterTypes();
2219}
2220
2221/*!
2222 \since 6.0
2223 Returns the name of the type at position \a index
2224 If there is no parameter at \a index, returns an empty QByteArray
2225
2226 \sa parameterNames()
2227 */
2228QByteArray QMetaMethod::parameterTypeName(int index) const
2229{
2230 if (!mobj || index < 0 || index >= parameterCount())
2231 return {};
2232 return QMetaMethodPrivate::get(q: this)->parameterTypeName(index);
2233}
2234
2235/*!
2236 Returns a list of parameter names.
2237
2238 \sa parameterTypes(), methodSignature()
2239*/
2240QList<QByteArray> QMetaMethod::parameterNames() const
2241{
2242 if (!mobj)
2243 return QList<QByteArray>();
2244 return QMetaMethodPrivate::get(q: this)->parameterNames();
2245}
2246
2247
2248/*!
2249 Returns the return type name of this method.
2250
2251 \sa returnType(), QMetaType::type()
2252*/
2253const char *QMetaMethod::typeName() const
2254{
2255 if (!mobj)
2256 return nullptr;
2257 return QMetaMethodPrivate::get(q: this)->rawReturnTypeName();
2258}
2259
2260/*!
2261 Returns the tag associated with this method.
2262
2263 Tags are special macros recognized by \c moc that make it
2264 possible to add extra information about a method.
2265
2266 Tag information can be added in the following
2267 way in the function declaration:
2268
2269 \snippet code/src_corelib_kernel_qmetaobject.cpp 10
2270
2271 and the information can be accessed by using:
2272
2273 \snippet code/src_corelib_kernel_qmetaobject.cpp 11
2274
2275 For the moment, \c moc will extract and record all tags, but it will not
2276 handle any of them specially. You can use the tags to annotate your methods
2277 differently, and treat them according to the specific needs of your
2278 application.
2279
2280 \note \c moc expands preprocessor macros, so it is necessary
2281 to surround the definition with \c #ifndef \c Q_MOC_RUN, as shown in the
2282 example above.
2283*/
2284const char *QMetaMethod::tag() const
2285{
2286 if (!mobj)
2287 return nullptr;
2288 return QMetaMethodPrivate::get(q: this)->tag().constData();
2289}
2290
2291
2292/*!
2293 \internal
2294 */
2295int QMetaMethod::attributes() const
2296{
2297 if (!mobj)
2298 return false;
2299 return data.flags() >> 4;
2300}
2301
2302/*!
2303 \since 4.6
2304
2305 Returns this method's index.
2306*/
2307int QMetaMethod::methodIndex() const
2308{
2309 if (!mobj)
2310 return -1;
2311 return QMetaMethodPrivate::get(q: this)->ownMethodIndex() + mobj->methodOffset();
2312}
2313
2314/*!
2315 \since 6.0
2316
2317 Returns this method's local index inside.
2318*/
2319int QMetaMethod::relativeMethodIndex() const
2320{
2321 if (!mobj)
2322 return -1;
2323 return QMetaMethodPrivate::get(q: this)->ownMethodIndex();
2324}
2325
2326// This method has been around for a while, but the documentation was marked \internal until 5.1
2327/*!
2328 \since 5.1
2329 Returns the method revision if one was specified by Q_REVISION, otherwise
2330 returns 0. Since Qt 6.0, non-zero values are encoded and can be decoded
2331 using QTypeRevision::fromEncodedVersion().
2332 */
2333int QMetaMethod::revision() const
2334{
2335 if (!mobj)
2336 return 0;
2337 if (data.flags() & MethodRevisioned) {
2338 int offset = priv(data: mobj->d.data)->methodData
2339 + priv(data: mobj->d.data)->methodCount * Data::Size
2340 + QMetaMethodPrivate::get(q: this)->ownMethodIndex();
2341 return mobj->d.data[offset];
2342 }
2343 return 0;
2344}
2345
2346/*!
2347 \since 6.2
2348
2349 Returns whether the method is const qualified.
2350
2351 \note This method might erroneously return \c false for a const method
2352 if it belongs to a library compiled against an older version of Qt.
2353 */
2354bool QMetaMethod::isConst() const
2355{
2356 if (!mobj)
2357 return false;
2358 if (QMetaObjectPrivate::get(metaobject: mobj)->revision < 10)
2359 return false;
2360 return data.flags() & MethodIsConst;
2361}
2362
2363/*!
2364 Returns the access specification of this method (private,
2365 protected, or public).
2366
2367 \note Signals are always public, but you should regard that as an
2368 implementation detail. It is almost always a bad idea to emit a signal from
2369 outside its class.
2370
2371 \sa methodType()
2372*/
2373QMetaMethod::Access QMetaMethod::access() const
2374{
2375 if (!mobj)
2376 return Private;
2377 return (QMetaMethod::Access)(data.flags() & AccessMask);
2378}
2379
2380/*!
2381 Returns the type of this method (signal, slot, or method).
2382
2383 \sa access()
2384*/
2385QMetaMethod::MethodType QMetaMethod::methodType() const
2386{
2387 if (!mobj)
2388 return QMetaMethod::Method;
2389 return (QMetaMethod::MethodType)((data.flags() & MethodTypeMask)>>2);
2390}
2391
2392/*!
2393 \fn template <typename PointerToMemberFunction> QMetaMethod QMetaMethod::fromSignal(PointerToMemberFunction signal)
2394 \since 5.0
2395
2396 Returns the meta-method that corresponds to the given \a signal, or an
2397 invalid QMetaMethod if \a signal is \c{nullptr} or not a signal of the class.
2398
2399 Example:
2400
2401 \snippet code/src_corelib_kernel_qmetaobject.cpp 9
2402*/
2403
2404/*!
2405 \internal
2406
2407 Implementation of the fromSignal() function.
2408
2409 \a metaObject is the class's meta-object
2410 \a signal is a pointer to a pointer to a member signal of the class
2411*/
2412QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **signal)
2413{
2414 int i = -1;
2415 void *args[] = { &i, signal };
2416 for (const QMetaObject *m = metaObject; m; m = m->d.superdata) {
2417 m->static_metacall(cl: QMetaObject::IndexOfMethod, idx: 0, argv: args);
2418 if (i >= 0)
2419 return QMetaMethod::fromRelativeMethodIndex(mobj: m, index: i);
2420 }
2421 return QMetaMethod();
2422}
2423
2424/*!
2425 \fn template <typename ReturnArg, typename... Args> bool QMetaMethod::invoke(QObject *obj, Qt::ConnectionType type, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... arguments) const
2426 \fn template <typename... Args> bool QMetaMethod::invoke(QObject *obj, Qt::ConnectionType type, Args &&... arguments) const
2427 \fn template <typename ReturnArg, typename... Args> bool QMetaMethod::invoke(QObject *obj, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... arguments) const
2428 \fn template <typename... Args> bool QMetaMethod::invoke(QObject *obj, Args &&... arguments) const
2429 \since 6.5
2430
2431 Invokes this method on the object \a object. Returns \c true if the member could be invoked.
2432 Returns \c false if there is no such member or the parameters did not match.
2433
2434 For the overloads with a QTemplatedMetaMethodReturnArgument parameter, the
2435 return value of the \a member function call is placed in \a ret. For the
2436 overloads without such a member, the return value of the called function
2437 (if any) will be discarded. QTemplatedMetaMethodReturnArgument is an
2438 internal type you should not use directly. Instead, use the qReturnArg()
2439 function.
2440
2441 The overloads with a Qt::ConnectionType \a type parameter allow explicitly
2442 selecting whether the invocation will be synchronous or not:
2443
2444 \list
2445 \li If \a type is Qt::DirectConnection, the member will be invoked immediately
2446 in the current thread.
2447
2448 \li If \a type is Qt::QueuedConnection, a QEvent will be sent and the
2449 member is invoked as soon as the application enters the event loop in the
2450 thread the \a obj was created in or was moved to.
2451
2452 \li If \a type is Qt::BlockingQueuedConnection, the method will be invoked in
2453 the same way as for Qt::QueuedConnection, except that the current thread
2454 will block until the event is delivered. Using this connection type to
2455 communicate between objects in the same thread will lead to deadlocks.
2456
2457 \li If \a type is Qt::AutoConnection, the member is invoked synchronously
2458 if \a obj lives in the same thread as the caller; otherwise it will invoke
2459 the member asynchronously. This is the behavior of the overloads that do
2460 not have the \a type parameter.
2461 \endlist
2462
2463 To asynchronously invoke the
2464 \l{QPushButton::animateClick()}{animateClick()} slot on a
2465 QPushButton:
2466
2467 \snippet code/src_corelib_kernel_qmetaobject.cpp 6
2468
2469 With asynchronous method invocations, the parameters must be copyable
2470 types, because Qt needs to copy the arguments to store them in an event
2471 behind the scenes. Since Qt 6.5, this function automatically registers the
2472 types being used; however, as a side-effect, it is not possible to make
2473 calls using types that are only forward-declared. Additionally, it is not
2474 possible to make asynchronous calls that use references to
2475 non-const-qualified types as parameters either.
2476
2477 To synchronously invoke the \c compute(QString, int, double) slot on
2478 some arbitrary object \c obj retrieve its return value:
2479
2480 \snippet code/src_corelib_kernel_qmetaobject.cpp invoke-no-macro
2481
2482 If the "compute" slot does not take exactly one \l QString, one \c int, and
2483 one \c double in the specified order, the call will fail. Note how it was
2484 necessary to be explicit about the type of the QString, as the character
2485 literal is not exactly the right type to match. If the method instead took
2486 a \l QByteArray, a \l qint64, and a \c{long double}, the call would need to be
2487 written as:
2488
2489 \snippet code/src_corelib_kernel_qmetaobject.cpp invoke-no-macro-other-types
2490
2491 The same call can be executed using the Q_ARG() and Q_RETURN_ARG() macros,
2492 as in:
2493
2494 \snippet code/src_corelib_kernel_qmetaobject.cpp 8
2495
2496 \warning this method will not test the validity of the arguments: \a object
2497 must be an instance of the class of the QMetaObject of which this QMetaMethod
2498 has been constructed with.
2499
2500 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
2501*/
2502
2503/*!
2504 \obsolete [6.5] Please use the variadic overload of this function
2505
2506 Invokes this method on the object \a object. Returns \c true if the member could be invoked.
2507 Returns \c false if there is no such member or the parameters did not match.
2508
2509 See the variadic invokeMethod() function for more information. This
2510 function should behave the same way as that one, with the following
2511 limitations:
2512
2513 \list
2514 \li The number of parameters is limited to 10.
2515 \li Parameter names may need to be an exact string match.
2516 \li Meta types are not automatically registered.
2517 \endlist
2518
2519 With asynchronous method invocations, the parameters must be of
2520 types that are known to Qt's meta-object system, because Qt needs
2521 to copy the arguments to store them in an event behind the
2522 scenes. If you try to use a queued connection and get the error
2523 message
2524
2525 \snippet code/src_corelib_kernel_qmetaobject.cpp 7
2526
2527 call qRegisterMetaType() to register the data type before you
2528 call QMetaMethod::invoke().
2529
2530 \warning In addition to the limitations of the variadic invoke() overload,
2531 the arguments must have the same type as the ones expected by the method,
2532 else, the behavior is undefined.
2533
2534 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
2535*/
2536bool QMetaMethod::invoke(QObject *object,
2537 Qt::ConnectionType connectionType,
2538 QGenericReturnArgument returnValue,
2539 QGenericArgument val0,
2540 QGenericArgument val1,
2541 QGenericArgument val2,
2542 QGenericArgument val3,
2543 QGenericArgument val4,
2544 QGenericArgument val5,
2545 QGenericArgument val6,
2546 QGenericArgument val7,
2547 QGenericArgument val8,
2548 QGenericArgument val9) const
2549{
2550 if (!object || !mobj)
2551 return false;
2552
2553 // check argument count (we don't allow invoking a method if given too few arguments)
2554 const char *typeNames[] = {
2555 returnValue.name(),
2556 val0.name(),
2557 val1.name(),
2558 val2.name(),
2559 val3.name(),
2560 val4.name(),
2561 val5.name(),
2562 val6.name(),
2563 val7.name(),
2564 val8.name(),
2565 val9.name()
2566 };
2567 void *param[] = {
2568 returnValue.data(),
2569 val0.data(),
2570 val1.data(),
2571 val2.data(),
2572 val3.data(),
2573 val4.data(),
2574 val5.data(),
2575 val6.data(),
2576 val7.data(),
2577 val8.data(),
2578 val9.data()
2579 };
2580
2581 int paramCount;
2582 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
2583 if (qstrlen(str: typeNames[paramCount]) <= 0)
2584 break;
2585 }
2586 return invokeImpl(self: *this, target: object, connectionType, paramCount, parameters: param, typeNames, metaTypes: nullptr);
2587}
2588
2589bool QMetaMethod::invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType connectionType,
2590 qsizetype paramCount, const void *const *parameters,
2591 const char *const *typeNames,
2592 const QtPrivate::QMetaTypeInterface *const *metaTypes)
2593{
2594 if (!target || !self.mobj)
2595 return false;
2596 QMetaMethodPrivate::InvokeFailReason r =
2597 QMetaMethodPrivate::invokeImpl(self, target, connectionType, paramCount, parameters,
2598 typeNames, metaTypes);
2599 if (Q_LIKELY(r == QMetaMethodPrivate::InvokeFailReason::None))
2600 return true;
2601
2602 if (int(r) >= int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch)) {
2603 int n = int(r) - int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch);
2604 qWarning(msg: "QMetaMethod::invoke: cannot convert formal parameter %d from %s in call to %s::%s",
2605 n, typeNames[n + 1] ? typeNames[n + 1] : metaTypes[n + 1]->name,
2606 self.mobj->className(), self.methodSignature().constData());
2607 }
2608 if (r == QMetaMethodPrivate::InvokeFailReason::TooFewArguments) {
2609 qWarning(msg: "QMetaMethod::invoke: too few arguments (%d) in call to %s::%s",
2610 int(paramCount), self.mobj->className(), self.methodSignature().constData());
2611 }
2612 return false;
2613}
2614
2615auto QMetaMethodInvoker::invokeImpl(QMetaMethod self, void *target,
2616 Qt::ConnectionType connectionType,
2617 qsizetype paramCount, const void *const *parameters,
2618 const char *const *typeNames,
2619 const QtPrivate::QMetaTypeInterface *const *metaTypes) -> InvokeFailReason
2620{
2621 auto object = static_cast<QObject *>(target);
2622 auto priv = QMetaMethodPrivate::get(q: &self);
2623 constexpr bool MetaTypesAreOptional = QT_VERSION < QT_VERSION_CHECK(7, 0, 0);
2624 auto methodMetaTypes = priv->parameterMetaTypeInterfaces();
2625 auto param = const_cast<void **>(parameters);
2626
2627 Q_ASSERT(priv->mobj);
2628 Q_ASSERT(self.methodType() == Constructor || object);
2629 Q_ASSERT(self.methodType() == Constructor || connectionType == Qt::ConnectionType(-1) ||
2630 priv->mobj->cast(object));
2631 Q_ASSERT(paramCount >= 1); // includes the return type
2632 Q_ASSERT(parameters);
2633 Q_ASSERT(typeNames);
2634 Q_ASSERT(MetaTypesAreOptional || metaTypes);
2635
2636 if ((paramCount - 1) < qsizetype(priv->data.argc()))
2637 return InvokeFailReason::TooFewArguments;
2638
2639 // 0 is the return type, 1 is the first formal parameter
2640 auto checkTypesAreCompatible = [=](int idx) {
2641 uint typeInfo = priv->parameterTypeInfo(index: idx - 1);
2642 QByteArrayView userTypeName(typeNames[idx] ? typeNames[idx] : metaTypes[idx]->name);
2643
2644 if ((typeInfo & IsUnresolvedType) == 0) {
2645 // this is a built-in type
2646 if (MetaTypesAreOptional && !metaTypes)
2647 return int(typeInfo) == QMetaType::fromName(name: userTypeName).id();
2648 return int(typeInfo) == metaTypes[idx]->typeId;
2649 }
2650
2651 QByteArrayView methodTypeName = stringDataView(mo: priv->mobj, index: typeInfo & TypeNameIndexMask);
2652 if ((MetaTypesAreOptional && !metaTypes) || !metaTypes[idx]) {
2653 // compatibility call, compare strings
2654 if (methodTypeName == userTypeName)
2655 return true;
2656
2657 // maybe the user type needs normalization
2658 QByteArray normalized = normalizeTypeInternal(t: userTypeName.begin(), e: userTypeName.end());
2659 return methodTypeName == normalized;
2660 }
2661
2662 QMetaType userType(metaTypes[idx]);
2663 Q_ASSERT(userType.isValid());
2664 if (QMetaType(methodMetaTypes[idx - 1]) == userType)
2665 return true;
2666
2667 // if the parameter type was NOT only forward-declared, it MUST have
2668 // matched
2669 if (methodMetaTypes[idx - 1])
2670 return false;
2671
2672 // resolve from the name moc stored for us
2673 QMetaType resolved = QMetaType::fromName(name: methodTypeName);
2674 return resolved == userType;
2675 };
2676
2677 // force all types to be registered, just in case
2678 for (qsizetype i = 0; metaTypes && i < paramCount; ++i)
2679 QMetaType(metaTypes[i]).registerType();
2680
2681 // check formal parameters first (overload set)
2682 for (qsizetype i = 1; i < paramCount; ++i) {
2683 if (!checkTypesAreCompatible(i))
2684 return InvokeFailReason(int(InvokeFailReason::FormalParameterMismatch) + i - 1);
2685 }
2686
2687 // handle constructors first
2688 if (self.methodType() == Constructor) {
2689 if (object) {
2690 qWarning(msg: "QMetaMethod::invokeMethod: cannot call constructor %s on object %p",
2691 self.methodSignature().constData(), object);
2692 return InvokeFailReason::ConstructorCallOnObject;
2693 }
2694
2695 if (!parameters[0]) {
2696 qWarning(msg: "QMetaMethod::invokeMethod: constructor call to %s must assign a return type",
2697 self.methodSignature().constData());
2698 return InvokeFailReason::ConstructorCallWithoutResult;
2699 }
2700
2701 if (!MetaTypesAreOptional || metaTypes) {
2702 if (metaTypes[0]->typeId != QMetaType::QObjectStar) {
2703 qWarning(msg: "QMetaMethod::invokeMethod: cannot convert QObject* to %s on constructor call %s",
2704 metaTypes[0]->name, self.methodSignature().constData());
2705 return InvokeFailReason::ReturnTypeMismatch;
2706 }
2707 }
2708
2709 int idx = priv->ownConstructorMethodIndex();
2710 if (priv->mobj->static_metacall(cl: QMetaObject::CreateInstance, idx, argv: param) >= 0)
2711 return InvokeFailReason::ConstructorCallFailed;
2712 return {};
2713 }
2714
2715 // regular type - check return type
2716 if (parameters[0]) {
2717 if (!checkTypesAreCompatible(0)) {
2718 const char *retType = typeNames[0] ? typeNames[0] : metaTypes[0]->name;
2719 qWarning(msg: "QMetaMethod::invokeMethod: return type mismatch for method %s::%s:"
2720 " cannot convert from %s to %s during invocation",
2721 priv->mobj->className(), priv->methodSignature().constData(),
2722 priv->rawReturnTypeName(), retType);
2723 return InvokeFailReason::ReturnTypeMismatch;
2724 }
2725 }
2726
2727 Qt::HANDLE currentThreadId = nullptr;
2728 QThread *objectThread = nullptr;
2729 auto receiverInSameThread = [&]() {
2730 if (!currentThreadId) {
2731 currentThreadId = QThread::currentThreadId();
2732 objectThread = object->thread();
2733 }
2734 if (objectThread)
2735 return currentThreadId == QThreadData::get2(thread: objectThread)->threadId.loadRelaxed();
2736 return false;
2737 };
2738
2739 // check connection type
2740 if (connectionType == Qt::AutoConnection)
2741 connectionType = receiverInSameThread() ? Qt::DirectConnection : Qt::QueuedConnection;
2742 else if (connectionType == Qt::ConnectionType(-1))
2743 connectionType = Qt::DirectConnection;
2744
2745#if !QT_CONFIG(thread)
2746 if (connectionType == Qt::BlockingQueuedConnection) {
2747 connectionType = Qt::DirectConnection;
2748 }
2749#endif
2750
2751 // invoke!
2752 int idx_relative = priv->ownMethodIndex();
2753 int idx_offset = priv->mobj->methodOffset();
2754 QObjectPrivate::StaticMetaCallFunction callFunction = priv->mobj->d.static_metacall;
2755
2756 if (connectionType == Qt::DirectConnection) {
2757 if (callFunction)
2758 callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
2759 else if (QMetaObject::metacall(object, cl: QMetaObject::InvokeMetaMethod, idx: idx_relative + idx_offset, argv: param) >= 0)
2760 return InvokeFailReason::CallViaVirtualFailed;
2761 } else if (connectionType == Qt::QueuedConnection) {
2762 if (parameters[0]) {
2763 qWarning(msg: "QMetaMethod::invoke: Unable to invoke methods with return values in "
2764 "queued connections");
2765 return InvokeFailReason::CouldNotQueueParameter;
2766 }
2767
2768 auto event = std::make_unique<QMetaCallEvent>(args&: idx_offset, args&: idx_relative, args&: callFunction, args: nullptr, args: -1, args&: paramCount);
2769 QMetaType *types = event->types();
2770 void **args = event->args();
2771
2772 // fill in the meta types first
2773 for (int i = 1; i < paramCount; ++i) {
2774 types[i] = QMetaType(methodMetaTypes[i - 1]);
2775 if (!types[i].iface() && (!MetaTypesAreOptional || metaTypes))
2776 types[i] = QMetaType(metaTypes[i]);
2777 if (!types[i].iface())
2778 types[i] = priv->parameterMetaType(index: i - 1);
2779 if (!types[i].iface() && typeNames[i])
2780 types[i] = QMetaType::fromName(name: typeNames[i]);
2781 if (!types[i].iface()) {
2782 qWarning(msg: "QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
2783 typeNames[i]);
2784 return InvokeFailReason(int(InvokeFailReason::CouldNotQueueParameter) - i);
2785 }
2786 }
2787
2788 // now create copies of our parameters using those meta types
2789 for (int i = 1; i < paramCount; ++i)
2790 args[i] = types[i].create(copy: parameters[i]);
2791
2792 QCoreApplication::postEvent(receiver: object, event: event.release());
2793 } else { // blocking queued connection
2794#if QT_CONFIG(thread)
2795 if (receiverInSameThread()) {
2796 qWarning(msg: "QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: "
2797 "Receiver is %s(%p)", priv->mobj->className(), object);
2798 return InvokeFailReason::DeadLockDetected;
2799 }
2800
2801 QSemaphore semaphore;
2802 QCoreApplication::postEvent(receiver: object, event: new QMetaCallEvent(idx_offset, idx_relative, callFunction,
2803 nullptr, -1, param, &semaphore));
2804 semaphore.acquire();
2805#endif // QT_CONFIG(thread)
2806 }
2807 return {};
2808}
2809
2810/*! \fn bool QMetaMethod::invoke(QObject *object,
2811 QGenericReturnArgument returnValue,
2812 QGenericArgument val0 = QGenericArgument(0),
2813 QGenericArgument val1 = QGenericArgument(),
2814 QGenericArgument val2 = QGenericArgument(),
2815 QGenericArgument val3 = QGenericArgument(),
2816 QGenericArgument val4 = QGenericArgument(),
2817 QGenericArgument val5 = QGenericArgument(),
2818 QGenericArgument val6 = QGenericArgument(),
2819 QGenericArgument val7 = QGenericArgument(),
2820 QGenericArgument val8 = QGenericArgument(),
2821 QGenericArgument val9 = QGenericArgument()) const
2822 \obsolete [6.5] Please use the variadic overload of this function
2823 \overload invoke()
2824
2825 This overload always invokes this method using the connection type Qt::AutoConnection.
2826*/
2827
2828/*! \fn bool QMetaMethod::invoke(QObject *object,
2829 Qt::ConnectionType connectionType,
2830 QGenericArgument val0 = QGenericArgument(0),
2831 QGenericArgument val1 = QGenericArgument(),
2832 QGenericArgument val2 = QGenericArgument(),
2833 QGenericArgument val3 = QGenericArgument(),
2834 QGenericArgument val4 = QGenericArgument(),
2835 QGenericArgument val5 = QGenericArgument(),
2836 QGenericArgument val6 = QGenericArgument(),
2837 QGenericArgument val7 = QGenericArgument(),
2838 QGenericArgument val8 = QGenericArgument(),
2839 QGenericArgument val9 = QGenericArgument()) const
2840 \obsolete [6.5] Please use the variadic overload of this function
2841 \overload invoke()
2842
2843 This overload can be used if the return value of the member is of no interest.
2844*/
2845
2846/*!
2847 \fn bool QMetaMethod::invoke(QObject *object,
2848 QGenericArgument val0 = QGenericArgument(0),
2849 QGenericArgument val1 = QGenericArgument(),
2850 QGenericArgument val2 = QGenericArgument(),
2851 QGenericArgument val3 = QGenericArgument(),
2852 QGenericArgument val4 = QGenericArgument(),
2853 QGenericArgument val5 = QGenericArgument(),
2854 QGenericArgument val6 = QGenericArgument(),
2855 QGenericArgument val7 = QGenericArgument(),
2856 QGenericArgument val8 = QGenericArgument(),
2857 QGenericArgument val9 = QGenericArgument()) const
2858 \obsolete [6.5] Please use the variadic overload of this function
2859 \overload invoke()
2860
2861 This overload invokes this method using the
2862 connection type Qt::AutoConnection and ignores return values.
2863*/
2864
2865/*!
2866 \fn template <typename ReturnArg, typename... Args> bool QMetaMethod::invokeOnGadget(void *gadget, QTemplatedMetaMethodReturnArgument<ReturnArg> ret, Args &&... arguments) const
2867 \fn template <typename... Args> bool QMetaMethod::invokeOnGadget(void *gadget, Args &&... arguments) const
2868 \since 6.5
2869
2870 Invokes this method on a Q_GADGET. Returns \c true if the member could be invoked.
2871 Returns \c false if there is no such member or the parameters did not match.
2872
2873 The pointer \a gadget must point to an instance of the gadget class.
2874
2875 The invocation is always synchronous.
2876
2877 For the overload with a QTemplatedMetaMethodReturnArgument parameter, the
2878 return value of the \a member function call is placed in \a ret. For the
2879 overload without it, the return value of the called function (if any) will
2880 be discarded. QTemplatedMetaMethodReturnArgument is an internal type you
2881 should not use directly. Instead, use the qReturnArg() function.
2882
2883 \warning this method will not test the validity of the arguments: \a gadget
2884 must be an instance of the class of the QMetaObject of which this QMetaMethod
2885 has been constructed with.
2886
2887 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
2888*/
2889
2890/*!
2891 \since 5.5
2892 \obsolete [6.5] Please use the variadic overload of this function
2893
2894 Invokes this method on a Q_GADGET. Returns \c true if the member could be invoked.
2895 Returns \c false if there is no such member or the parameters did not match.
2896
2897 See the variadic invokeMethod() function for more information. This
2898 function should behave the same way as that one, with the following
2899 limitations:
2900
2901 \list
2902 \li The number of parameters is limited to 10.
2903 \li Parameter names may need to be an exact string match.
2904 \li Meta types are not automatically registered.
2905 \endlist
2906
2907 \warning In addition to the limitations of the variadic invoke() overload,
2908 the arguments must have the same type as the ones expected by the method,
2909 else, the behavior is undefined.
2910
2911 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
2912*/
2913bool QMetaMethod::invokeOnGadget(void *gadget,
2914 QGenericReturnArgument returnValue,
2915 QGenericArgument val0,
2916 QGenericArgument val1,
2917 QGenericArgument val2,
2918 QGenericArgument val3,
2919 QGenericArgument val4,
2920 QGenericArgument val5,
2921 QGenericArgument val6,
2922 QGenericArgument val7,
2923 QGenericArgument val8,
2924 QGenericArgument val9) const
2925{
2926 if (!gadget || !mobj)
2927 return false;
2928
2929 // check return type
2930 if (returnValue.data()) {
2931 const char *retType = typeName();
2932 if (qstrcmp(str1: returnValue.name(), str2: retType) != 0) {
2933 // normalize the return value as well
2934 QByteArray normalized = QMetaObject::normalizedType(type: returnValue.name());
2935 if (qstrcmp(str1: normalized.constData(), str2: retType) != 0) {
2936 // String comparison failed, try compare the metatype.
2937 int t = returnType();
2938 if (t == QMetaType::UnknownType || t != QMetaType::fromName(name: normalized).id())
2939 return false;
2940 }
2941 }
2942 }
2943
2944 // check argument count (we don't allow invoking a method if given too few arguments)
2945 const char *typeNames[] = {
2946 returnValue.name(),
2947 val0.name(),
2948 val1.name(),
2949 val2.name(),
2950 val3.name(),
2951 val4.name(),
2952 val5.name(),
2953 val6.name(),
2954 val7.name(),
2955 val8.name(),
2956 val9.name()
2957 };
2958 int paramCount;
2959 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
2960 if (qstrlen(str: typeNames[paramCount]) <= 0)
2961 break;
2962 }
2963 if (paramCount <= QMetaMethodPrivate::get(q: this)->parameterCount())
2964 return false;
2965
2966 // invoke!
2967 void *param[] = {
2968 returnValue.data(),
2969 val0.data(),
2970 val1.data(),
2971 val2.data(),
2972 val3.data(),
2973 val4.data(),
2974 val5.data(),
2975 val6.data(),
2976 val7.data(),
2977 val8.data(),
2978 val9.data()
2979 };
2980 int idx_relative = QMetaMethodPrivate::get(q: this)->ownMethodIndex();
2981 Q_ASSERT(QMetaObjectPrivate::get(mobj)->revision >= 6);
2982 QObjectPrivate::StaticMetaCallFunction callFunction = mobj->d.static_metacall;
2983 if (!callFunction)
2984 return false;
2985 callFunction(reinterpret_cast<QObject*>(gadget), QMetaObject::InvokeMetaMethod, idx_relative, param);
2986 return true;
2987}
2988
2989/*!
2990 \fn bool QMetaMethod::invokeOnGadget(void *gadget,
2991 QGenericArgument val0 = QGenericArgument(0),
2992 QGenericArgument val1 = QGenericArgument(),
2993 QGenericArgument val2 = QGenericArgument(),
2994 QGenericArgument val3 = QGenericArgument(),
2995 QGenericArgument val4 = QGenericArgument(),
2996 QGenericArgument val5 = QGenericArgument(),
2997 QGenericArgument val6 = QGenericArgument(),
2998 QGenericArgument val7 = QGenericArgument(),
2999 QGenericArgument val8 = QGenericArgument(),
3000 QGenericArgument val9 = QGenericArgument()) const
3001
3002 \overload
3003 \obsolete [6.5] Please use the variadic overload of this function
3004 \since 5.5
3005
3006 This overload invokes this method for a \a gadget and ignores return values.
3007*/
3008
3009/*!
3010 \class QMetaEnum
3011 \inmodule QtCore
3012 \brief The QMetaEnum class provides meta-data about an enumerator.
3013
3014 \ingroup objectmodel
3015
3016 Use name() for the enumerator's name. The enumerator's keys (names
3017 of each enumerated item) are returned by key(); use keyCount() to find
3018 the number of keys. isFlag() returns whether the enumerator is
3019 meant to be used as a flag, meaning that its values can be combined
3020 using the OR operator.
3021
3022 The conversion functions keyToValue(), valueToKey(), keysToValue(),
3023 and valueToKeys() allow conversion between the integer
3024 representation of an enumeration or set value and its literal
3025 representation. The scope() function returns the class scope this
3026 enumerator was declared in.
3027
3028 \sa QMetaObject, QMetaMethod, QMetaProperty
3029*/
3030
3031/*!
3032 \fn bool QMetaEnum::isValid() const
3033
3034 Returns \c true if this enum is valid (has a name); otherwise returns
3035 false.
3036
3037 \sa name()
3038*/
3039
3040/*!
3041 \fn const QMetaObject *QMetaEnum::enclosingMetaObject() const
3042 \internal
3043*/
3044
3045
3046/*!
3047 \fn QMetaEnum::QMetaEnum()
3048 \internal
3049*/
3050
3051/*!
3052 Returns the name of the type (without the scope).
3053
3054 For example, the Qt::Key enumeration has \c
3055 Key as the type name and \l Qt as the scope.
3056
3057 For flags this returns the name of the flag type, not the
3058 name of the enum type.
3059
3060 \sa isValid(), scope(), enumName()
3061*/
3062const char *QMetaEnum::name() const
3063{
3064 if (!mobj)
3065 return nullptr;
3066 return rawStringData(mo: mobj, index: data.name());
3067}
3068
3069/*!
3070 Returns the enum name of the flag (without the scope).
3071
3072 For example, the Qt::AlignmentFlag flag has \c
3073 AlignmentFlag as the enum name, but \c Alignment as the type name.
3074 Non flag enums has the same type and enum names.
3075
3076 Enum names have the same scope as the type name.
3077
3078 \since 5.12
3079 \sa isValid(), name()
3080*/
3081const char *QMetaEnum::enumName() const
3082{
3083 if (!mobj)
3084 return nullptr;
3085 return rawStringData(mo: mobj, index: data.alias());
3086}
3087
3088/*!
3089 Returns the meta type of the enum.
3090
3091 If the QMetaObject that this enum is part of was generated with Qt 6.5 or
3092 earlier, this will be an invalid meta type.
3093
3094 \note This is the meta type of the enum itself, not of its underlying
3095 integral type. You can retrieve the meta type of the underlying type of the
3096 enum using \l{QMetaType::underlyingType()}.
3097
3098 \since 6.6
3099*/
3100QMetaType QMetaEnum::metaType() const
3101{
3102 if (!mobj)
3103 return {};
3104
3105 const QMetaObjectPrivate *p = priv(data: mobj->d.data);
3106#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
3107 if (p->revision < 12)
3108 QMetaType();
3109#endif
3110
3111 return QMetaType(mobj->d.metaTypes[data.index(mobj) + p->propertyCount]);
3112}
3113
3114/*!
3115 Returns the number of keys.
3116
3117 \sa key()
3118*/
3119int QMetaEnum::keyCount() const
3120{
3121 if (!mobj)
3122 return 0;
3123 return data.keyCount();
3124}
3125
3126/*!
3127 Returns the key with the given \a index, or \nullptr if no such key exists.
3128
3129 \sa keyCount(), value(), valueToKey()
3130*/
3131const char *QMetaEnum::key(int index) const
3132{
3133 if (!mobj)
3134 return nullptr;
3135 if (index >= 0 && index < int(data.keyCount()))
3136 return rawStringData(mo: mobj, index: mobj->d.data[data.data() + 2*index]);
3137 return nullptr;
3138}
3139
3140/*!
3141 Returns the value with the given \a index; or returns -1 if there
3142 is no such value.
3143
3144 \sa keyCount(), key(), keyToValue()
3145*/
3146int QMetaEnum::value(int index) const
3147{
3148 if (!mobj)
3149 return 0;
3150 if (index >= 0 && index < int(data.keyCount()))
3151 return mobj->d.data[data.data() + 2 * index + 1];
3152 return -1;
3153}
3154
3155/*!
3156 Returns \c true if this enumerator is used as a flag; otherwise returns
3157 false.
3158
3159 When used as flags, enumerators can be combined using the OR
3160 operator.
3161
3162 \sa keysToValue(), valueToKeys()
3163*/
3164bool QMetaEnum::isFlag() const
3165{
3166 if (!mobj)
3167 return false;
3168 return data.flags() & EnumIsFlag;
3169}
3170
3171/*!
3172 \since 5.8
3173
3174 Returns \c true if this enumerator is declared as a C++11 enum class;
3175 otherwise returns false.
3176*/
3177bool QMetaEnum::isScoped() const
3178{
3179 if (!mobj)
3180 return false;
3181 return data.flags() & EnumIsScoped;
3182}
3183
3184/*!
3185 Returns the scope this enumerator was declared in.
3186
3187 For example, the Qt::AlignmentFlag enumeration has \c Qt as
3188 the scope and \c AlignmentFlag as the name.
3189
3190 \sa name()
3191*/
3192const char *QMetaEnum::scope() const
3193{
3194 return mobj ? mobj->className() : nullptr;
3195}
3196
3197static bool isScopeMatch(QByteArrayView scope, const QMetaEnum *e)
3198{
3199 const QByteArrayView className = e->enclosingMetaObject()->className();
3200
3201 // Typical use-cases:
3202 // a) Unscoped: namespace N { class C { enum E { F }; }; }; key == "N::C::F"
3203 // b) Scoped: namespace N { class C { enum class E { F }; }; }; key == "N::C::E::F"
3204 if (scope == className)
3205 return true;
3206
3207 // Not using name() because if isFlag() is true, we want the actual name
3208 // of the enum, e.g. "MyFlag", not "MyFlags", e.g.
3209 // enum MyFlag { F1, F2 }; Q_DECLARE_FLAGS(MyFlags, MyFlag);
3210 QByteArrayView name = e->enumName();
3211
3212 // Match fully qualified enumerator in unscoped enums, key == "N::C::E::F"
3213 // equivalent to use-case "a" above
3214 const auto sz = className.size();
3215 if (scope.size() == sz + qsizetype(qstrlen(str: "::")) + name.size()
3216 && scope.startsWith(other: className)
3217 && scope.sliced(pos: sz, n: 2) == "::"
3218 && scope.sliced(pos: sz + 2) == name)
3219 return true;
3220
3221 return false;
3222}
3223
3224/*!
3225 Returns the integer value of the given enumeration \a key, or -1
3226 if \a key is not defined.
3227
3228 If \a key is not defined, *\a{ok} is set to false; otherwise
3229 *\a{ok} is set to true.
3230
3231 For flag types, use keysToValue().
3232
3233 \sa valueToKey(), isFlag(), keysToValue()
3234*/
3235int QMetaEnum::keyToValue(const char *key, bool *ok) const
3236{
3237 if (ok != nullptr)
3238 *ok = false;
3239 if (!mobj || !key)
3240 return -1;
3241
3242 const auto [scope, enumKey] = parse_scope(qualifiedKey: QLatin1StringView(key));
3243 for (int i = 0; i < int(data.keyCount()); ++i) {
3244 if ((!scope || isScopeMatch(scope: *scope, e: this))
3245 && enumKey == stringDataView(mo: mobj, index: mobj->d.data[data.data() + 2 * i])) {
3246 if (ok != nullptr)
3247 *ok = true;
3248 return mobj->d.data[data.data() + 2 * i + 1];
3249 }
3250 }
3251 return -1;
3252}
3253
3254/*!
3255 Returns the string that is used as the name of the given
3256 enumeration \a value, or \nullptr if \a value is not defined.
3257
3258 For flag types, use valueToKeys().
3259
3260 \sa isFlag(), valueToKeys()
3261*/
3262const char *QMetaEnum::valueToKey(int value) const
3263{
3264 if (!mobj)
3265 return nullptr;
3266 for (int i = 0; i < int(data.keyCount()); ++i)
3267 if (value == (int)mobj->d.data[data.data() + 2 * i + 1])
3268 return rawStringData(mo: mobj, index: mobj->d.data[data.data() + 2 * i]);
3269 return nullptr;
3270}
3271
3272static bool parseEnumFlags(QByteArrayView v, QVarLengthArray<QByteArrayView, 10> &list)
3273{
3274 v = v.trimmed();
3275 if (v.empty()) {
3276 qWarning(msg: "QMetaEnum::keysToValue: empty keys string.");
3277 return false;
3278 }
3279
3280 qsizetype sep = v.indexOf(ch: '|', from: 0);
3281 if (sep == 0) {
3282 qWarning(msg: "QMetaEnum::keysToValue: malformed keys string, starts with '|', \"%s\"",
3283 v.constData());
3284 return false;
3285 }
3286
3287 if (sep == -1) { // One flag
3288 list.push_back(t: v);
3289 return true;
3290 }
3291
3292 if (v.endsWith(c: '|')) {
3293 qWarning(msg: "QMetaEnum::keysToValue: malformed keys string, ends with '|', \"%s\"",
3294 v.constData());
3295 return false;
3296 }
3297
3298 const auto begin = v.begin();
3299 const auto end = v.end();
3300 auto b = begin;
3301 for (; b != end && sep != -1; sep = v.indexOf(ch: '|', from: sep)) {
3302 list.push_back(t: {b, begin + sep});
3303 ++sep; // Skip over '|'
3304 b = begin + sep;
3305 if (*b == '|') {
3306 qWarning(msg: "QMetaEnum::keysToValue: malformed keys string, has two consecutive '|': "
3307 "\"%s\"", v.constData());
3308 return false;
3309 }
3310 }
3311
3312 // The rest of the string
3313 list.push_back(t: {b, end});
3314 return true;
3315}
3316
3317/*!
3318 Returns the value derived from combining together the values of
3319 the \a keys using the OR operator, or -1 if \a keys is not
3320 defined. Note that the strings in \a keys must be '|'-separated.
3321
3322 If \a keys is not defined, *\a{ok} is set to false; otherwise
3323 *\a{ok} is set to true.
3324
3325 \sa isFlag(), valueToKey(), valueToKeys()
3326*/
3327int QMetaEnum::keysToValue(const char *keys, bool *ok) const
3328{
3329 if (ok != nullptr)
3330 *ok = false;
3331 if (!mobj || !keys)
3332 return -1;
3333
3334 auto lookup = [&] (QByteArrayView key) -> std::optional<int> {
3335 for (int i = data.keyCount() - 1; i >= 0; --i) {
3336 if (key == stringDataView(mo: mobj, index: mobj->d.data[data.data() + 2*i]))
3337 return mobj->d.data[data.data() + 2*i + 1];
3338 }
3339 return std::nullopt;
3340 };
3341
3342 int value = 0;
3343 QVarLengthArray<QByteArrayView, 10> list;
3344 const bool r = parseEnumFlags(v: QByteArrayView{keys}, list);
3345 if (!r)
3346 return -1;
3347 for (const auto &untrimmed : list) {
3348 const auto parsed = parse_scope(qualifiedKey: untrimmed.trimmed());
3349 if (parsed.scope && !isScopeMatch(scope: *parsed.scope, e: this))
3350 return -1; // wrong type name in qualified name
3351 if (auto thisValue = lookup(parsed.key))
3352 value |= *thisValue;
3353 else
3354 return -1; // no such enumerator
3355 }
3356 if (ok != nullptr)
3357 *ok = true;
3358 return value;
3359}
3360
3361namespace
3362{
3363template <typename String, typename Container, typename Separator>
3364void join_reversed(String &s, const Container &c, Separator sep)
3365{
3366 if (c.empty())
3367 return;
3368 qsizetype len = qsizetype(c.size()) - 1; // N - 1 separators
3369 for (auto &e : c)
3370 len += qsizetype(e.size()); // N parts
3371 s.reserve(len);
3372 bool first = true;
3373 for (auto rit = c.rbegin(), rend = c.rend(); rit != rend; ++rit) {
3374 const auto &e = *rit;
3375 if (!first)
3376 s.append(sep);
3377 first = false;
3378 s.append(e.data(), e.size());
3379 }
3380}
3381} // unnamed namespace
3382
3383/*!
3384 Returns a byte array of '|'-separated keys that represents the
3385 given \a value.
3386
3387 \sa isFlag(), valueToKey(), keysToValue()
3388*/
3389QByteArray QMetaEnum::valueToKeys(int value) const
3390{
3391 QByteArray keys;
3392 if (!mobj)
3393 return keys;
3394 QVarLengthArray<QByteArrayView, sizeof(int) * CHAR_BIT> parts;
3395 int v = value;
3396 // reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
3397 for (int i = data.keyCount() - 1; i >= 0; --i) {
3398 int k = mobj->d.data[data.data() + 2 * i + 1];
3399 if ((k != 0 && (v & k) == k) || (k == value)) {
3400 v = v & ~k;
3401 parts.push_back(t: stringDataView(mo: mobj, index: mobj->d.data[data.data() + 2 * i]));
3402 }
3403 }
3404 join_reversed(s&: keys, c: parts, sep: '|');
3405 return keys;
3406}
3407
3408/*!
3409 \internal
3410 */
3411QMetaEnum::QMetaEnum(const QMetaObject *mobj, int index)
3412 : mobj(mobj), data({ .d: mobj->d.data + priv(data: mobj->d.data)->enumeratorData + index * Data::Size })
3413{
3414 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->enumeratorCount);
3415}
3416
3417int QMetaEnum::Data::index(const QMetaObject *mobj) const
3418{
3419 return (d - mobj->d.data - priv(data: mobj->d.data)->enumeratorData) / Size;
3420}
3421
3422/*!
3423 \fn template<typename T> QMetaEnum QMetaEnum::fromType()
3424 \since 5.5
3425
3426 Returns the QMetaEnum corresponding to the type in the template parameter.
3427 The enum needs to be declared with Q_ENUM.
3428*/
3429
3430/*!
3431 \class QMetaProperty
3432 \inmodule QtCore
3433 \brief The QMetaProperty class provides meta-data about a property.
3434
3435 \ingroup objectmodel
3436
3437 Property meta-data is obtained from an object's meta-object. See
3438 QMetaObject::property() and QMetaObject::propertyCount() for
3439 details.
3440
3441 \section1 Property Meta-Data
3442
3443 A property has a name() and a type(), as well as various
3444 attributes that specify its behavior: isReadable(), isWritable(),
3445 isDesignable(), isScriptable(), revision(), and isStored().
3446
3447 If the property is an enumeration, isEnumType() returns \c true; if the
3448 property is an enumeration that is also a flag (i.e. its values
3449 can be combined using the OR operator), isEnumType() and
3450 isFlagType() both return true. The enumerator for these types is
3451 available from enumerator().
3452
3453 The property's values are set and retrieved with read(), write(),
3454 and reset(); they can also be changed through QObject's set and get
3455 functions. See QObject::setProperty() and QObject::property() for
3456 details.
3457
3458 \section1 Copying and Assignment
3459
3460 QMetaProperty objects can be copied by value. However, each copy will
3461 refer to the same underlying property meta-data.
3462
3463 \sa QMetaObject, QMetaEnum, QMetaMethod, {Qt's Property System}
3464*/
3465
3466/*!
3467 \fn bool QMetaProperty::isValid() const
3468
3469 Returns \c true if this property is valid (readable); otherwise
3470 returns \c false.
3471
3472 \sa isReadable()
3473*/
3474
3475/*!
3476 \fn const QMetaObject *QMetaProperty::enclosingMetaObject() const
3477 \internal
3478*/
3479
3480/*!
3481 \fn QMetaProperty::QMetaProperty()
3482 \internal
3483*/
3484
3485/*!
3486 Returns this property's name.
3487
3488 \sa type(), typeName()
3489*/
3490const char *QMetaProperty::name() const
3491{
3492 if (!mobj)
3493 return nullptr;
3494 return rawStringData(mo: mobj, index: data.name());
3495}
3496
3497/*!
3498 Returns the name of this property's type.
3499
3500 \sa type(), name()
3501*/
3502const char *QMetaProperty::typeName() const
3503{
3504 if (!mobj)
3505 return nullptr;
3506 // TODO: can the metatype be invalid for dynamic metaobjects?
3507 if (const auto mt = metaType(); mt.isValid())
3508 return mt.name();
3509 return typeNameFromTypeInfo(mo: mobj, typeInfo: data.type()).constData();
3510}
3511
3512/*! \fn QVariant::Type QMetaProperty::type() const
3513 \deprecated
3514
3515 Returns this property's type. The return value is one
3516 of the values of the QVariant::Type enumeration.
3517
3518 \sa typeName(), name(), metaType()
3519*/
3520
3521/*! \fn int QMetaProperty::userType() const
3522 \since 4.2
3523
3524 Returns this property's user type. The return value is one
3525 of the values that are registered with QMetaType.
3526
3527 This is equivalent to metaType().id()
3528
3529 \sa type(), QMetaType, typeName(), metaType()
3530 */
3531
3532/*! \fn int QMetaProperty::typeId() const
3533 \since 6.0
3534
3535 Returns the storage type of the property. This is
3536 the same as metaType().id().
3537
3538 \sa QMetaType, typeName(), metaType()
3539 */
3540
3541/*!
3542 \since 6.0
3543
3544 Returns this property's QMetaType.
3545
3546 \sa QMetaType
3547 */
3548QMetaType QMetaProperty::metaType() const
3549{
3550 if (!mobj)
3551 return {};
3552 return QMetaType(mobj->d.metaTypes[data.index(mobj)]);
3553}
3554
3555int QMetaProperty::Data::index(const QMetaObject *mobj) const
3556{
3557 return (d - mobj->d.data - priv(data: mobj->d.data)->propertyData) / Size;
3558}
3559
3560/*!
3561 \since 4.6
3562
3563 Returns this property's index.
3564*/
3565int QMetaProperty::propertyIndex() const
3566{
3567 if (!mobj)
3568 return -1;
3569 return data.index(mobj) + mobj->propertyOffset();
3570}
3571
3572/*!
3573 \since 5.14
3574
3575 Returns this property's index relative within the enclosing meta object.
3576*/
3577int QMetaProperty::relativePropertyIndex() const
3578{
3579 if (!mobj)
3580 return -1;
3581 return data.index(mobj);
3582}
3583
3584/*!
3585 Returns \c true if the property's type is an enumeration value that
3586 is used as a flag; otherwise returns \c false.
3587
3588 Flags can be combined using the OR operator. A flag type is
3589 implicitly also an enum type.
3590
3591 \sa isEnumType(), enumerator(), QMetaEnum::isFlag()
3592*/
3593
3594bool QMetaProperty::isFlagType() const
3595{
3596 return isEnumType() && menum.isFlag();
3597}
3598
3599/*!
3600 Returns \c true if the property's type is an enumeration value;
3601 otherwise returns \c false.
3602
3603 \sa enumerator(), isFlagType()
3604*/
3605bool QMetaProperty::isEnumType() const
3606{
3607 if (!mobj)
3608 return false;
3609 return (data.flags() & EnumOrFlag) && menum.name();
3610}
3611
3612/*!
3613 \internal
3614
3615 Returns \c true if the property has a C++ setter function that
3616 follows Qt's standard "name" / "setName" pattern. Designer and uic
3617 query hasStdCppSet() in order to avoid expensive
3618 QObject::setProperty() calls. All properties in Qt [should] follow
3619 this pattern.
3620*/
3621bool QMetaProperty::hasStdCppSet() const
3622{
3623 if (!mobj)
3624 return false;
3625 return (data.flags() & StdCppSet);
3626}
3627
3628/*!
3629 \internal
3630
3631 Returns \c true if the property is an alias.
3632 This is for instance true for a property declared in QML
3633 as 'property alias'.
3634*/
3635bool QMetaProperty::isAlias() const
3636{
3637 if (!mobj)
3638 return false;
3639 return (data.flags() & Alias);
3640}
3641
3642#if QT_DEPRECATED_SINCE(6, 4)
3643/*!
3644 \internal
3645 Historically:
3646 Executes metacall with QMetaObject::RegisterPropertyMetaType flag.
3647 Returns id of registered type or QMetaType::UnknownType if a type
3648 could not be registered for any reason.
3649 Obsolete since Qt 6
3650*/
3651int QMetaProperty::registerPropertyType() const
3652{
3653 return typeId();
3654}
3655#endif
3656
3657QMetaProperty::QMetaProperty(const QMetaObject *mobj, int index)
3658 : mobj(mobj),
3659 data(getMetaPropertyData(mobj, index))
3660{
3661 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->propertyCount);
3662 // The code below here just resolves menum if the property is an enum type:
3663 if (!(data.flags() & EnumOrFlag) || !metaType().flags().testFlag(flag: QMetaType::IsEnumeration))
3664 return;
3665 QByteArrayView enum_name = typeNameFromTypeInfo(mo: mobj, typeInfo: data.type());
3666 menum = mobj->enumerator(index: QMetaObjectPrivate::indexOfEnumerator(m: mobj, name: enum_name));
3667 if (menum.isValid())
3668 return;
3669
3670 QByteArrayView scope_name;
3671 const auto parsed = parse_scope(qualifiedKey: enum_name);
3672 if (parsed.scope) {
3673 scope_name = *parsed.scope;
3674 enum_name = parsed.key;
3675 } else {
3676 scope_name = objectClassName(m: mobj);
3677 }
3678
3679 const QMetaObject *scope = nullptr;
3680 if (scope_name == "Qt")
3681 scope = &Qt::staticMetaObject;
3682 else
3683 scope = QMetaObject_findMetaObject(self: mobj, name: QByteArrayView(scope_name));
3684
3685 if (scope)
3686 menum = scope->enumerator(index: QMetaObjectPrivate::indexOfEnumerator(m: scope, name: enum_name));
3687}
3688
3689/*!
3690 \internal
3691 Constructs the \c QMetaProperty::Data for the \a index th property of \a mobj
3692 */
3693QMetaProperty::Data QMetaProperty::getMetaPropertyData(const QMetaObject *mobj, int index)
3694{
3695 return { .d: mobj->d.data + priv(data: mobj->d.data)->propertyData + index * Data::Size };
3696}
3697
3698/*!
3699 Returns the enumerator if this property's type is an enumerator
3700 type; otherwise the returned value is undefined.
3701
3702 \sa isEnumType(), isFlagType()
3703*/
3704QMetaEnum QMetaProperty::enumerator() const
3705{
3706 return menum;
3707}
3708
3709/*!
3710 Reads the property's value from the given \a object. Returns the value
3711 if it was able to read it; otherwise returns an invalid variant.
3712
3713 \sa write(), reset(), isReadable()
3714*/
3715QVariant QMetaProperty::read(const QObject *object) const
3716{
3717 if (!object || !mobj)
3718 return QVariant();
3719
3720 // the status variable is changed by qt_metacall to indicate what it did
3721 // this feature is currently only used by Qt D-Bus and should not be depended
3722 // upon. Don't change it without looking into QDBusAbstractInterface first
3723 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
3724 // changed: result stored directly in value
3725 int status = -1;
3726 QVariant value;
3727 void *argv[] = { nullptr, &value, &status };
3728 QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
3729 if (t == QMetaType::fromType<QVariant>()) {
3730 argv[0] = &value;
3731 } else {
3732 value = QVariant(t, nullptr);
3733 argv[0] = value.data();
3734 }
3735 if (priv(data: mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall) {
3736 mobj->d.static_metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty, data.index(mobj), argv);
3737 } else {
3738 QMetaObject::metacall(object: const_cast<QObject*>(object), cl: QMetaObject::ReadProperty,
3739 idx: data.index(mobj) + mobj->propertyOffset(), argv);
3740 }
3741
3742 if (status != -1)
3743 return value;
3744 if (t != QMetaType::fromType<QVariant>() && argv[0] != value.data())
3745 // pointer or reference
3746 return QVariant(t, argv[0]);
3747 return value;
3748}
3749
3750/*!
3751 Writes \a value as the property's value to the given \a object. Returns
3752 true if the write succeeded; otherwise returns \c false.
3753
3754 If \a value is not of the same type as the property, a conversion
3755 is attempted. An empty QVariant() is equivalent to a call to reset()
3756 if this property is resettable, or setting a default-constructed object
3757 otherwise.
3758
3759 \note This function internally makes a copy of \a value. Prefer to use the
3760 rvalue overload when possible.
3761
3762 \sa read(), reset(), isWritable()
3763*/
3764bool QMetaProperty::write(QObject *object, const QVariant &value) const
3765{
3766 if (!object || !isWritable())
3767 return false;
3768 return write(obj: object, value: QVariant(value));
3769}
3770
3771/*!
3772 \overload
3773 \since 6.6
3774*/
3775bool QMetaProperty::write(QObject *object, QVariant &&v) const
3776{
3777 if (!object || !isWritable())
3778 return false;
3779 QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
3780 if (t != QMetaType::fromType<QVariant>() && t != v.metaType()) {
3781 if (isEnumType() && !t.metaObject() && v.metaType() == QMetaType::fromType<QString>()) {
3782 // Assigning a string to a property of type Q_ENUMS (instead of Q_ENUM)
3783 // means the QMetaType has no associated QMetaObject, so it can't
3784 // do the conversion (see qmetatype.cpp:convertToEnum()).
3785 bool ok;
3786 if (isFlagType())
3787 v = QVariant(menum.keysToValue(keys: v.toByteArray(), ok: &ok));
3788 else
3789 v = QVariant(menum.keyToValue(key: v.toByteArray(), ok: &ok));
3790 if (!ok)
3791 return false;
3792 }
3793 if (!v.isValid()) {
3794 if (isResettable())
3795 return reset(obj: object);
3796 v = QVariant(t, nullptr);
3797 } else if (!v.convert(type: t)) {
3798 return false;
3799 }
3800 }
3801 // the status variable is changed by qt_metacall to indicate what it did
3802 // this feature is currently only used by Qt D-Bus and should not be depended
3803 // upon. Don't change it without looking into QDBusAbstractInterface first
3804 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
3805 // changed: result stored directly in value, return the value of status
3806 int status = -1;
3807 // the flags variable is used by the declarative module to implement
3808 // interception of property writes.
3809 int flags = 0;
3810 void *argv[] = { nullptr, &v, &status, &flags };
3811 if (t == QMetaType::fromType<QVariant>())
3812 argv[0] = &v;
3813 else
3814 argv[0] = v.data();
3815 if (priv(data: mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall)
3816 mobj->d.static_metacall(object, QMetaObject::WriteProperty, data.index(mobj), argv);
3817 else
3818 QMetaObject::metacall(object, cl: QMetaObject::WriteProperty, idx: data.index(mobj) + mobj->propertyOffset(), argv);
3819
3820 return status;
3821}
3822
3823/*!
3824 Resets the property for the given \a object with a reset method.
3825 Returns \c true if the reset worked; otherwise returns \c false.
3826
3827 Reset methods are optional; only a few properties support them.
3828
3829 \sa read(), write()
3830*/
3831bool QMetaProperty::reset(QObject *object) const
3832{
3833 if (!object || !mobj || !isResettable())
3834 return false;
3835 void *argv[] = { nullptr };
3836 if (priv(data: mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall)
3837 mobj->d.static_metacall(object, QMetaObject::ResetProperty, data.index(mobj), argv);
3838 else
3839 QMetaObject::metacall(object, cl: QMetaObject::ResetProperty, idx: data.index(mobj) + mobj->propertyOffset(), argv);
3840 return true;
3841}
3842
3843/*!
3844 \since 6.0
3845 Returns the bindable interface for the property on a given \a object.
3846
3847 If the property doesn't support bindings, the returned interface will be
3848 invalid.
3849
3850 \sa QObjectBindableProperty, QProperty, isBindable()
3851*/
3852QUntypedBindable QMetaProperty::bindable(QObject *object) const
3853{
3854 QUntypedBindable bindable;
3855 void * argv[1] { &bindable };
3856 mobj->metacall(object, cl: QMetaObject::BindableProperty, idx: data.index(mobj) + mobj->propertyOffset(), argv);
3857 return bindable;
3858}
3859/*!
3860 \since 5.5
3861
3862 Reads the property's value from the given \a gadget. Returns the value
3863 if it was able to read it; otherwise returns an invalid variant.
3864
3865 This function should only be used if this is a property of a Q_GADGET
3866*/
3867QVariant QMetaProperty::readOnGadget(const void *gadget) const
3868{
3869 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3870 return read(object: reinterpret_cast<const QObject*>(gadget));
3871}
3872
3873/*!
3874 \since 5.5
3875
3876 Writes \a value as the property's value to the given \a gadget. Returns
3877 true if the write succeeded; otherwise returns \c false.
3878
3879 This function should only be used if this is a property of a Q_GADGET
3880*/
3881bool QMetaProperty::writeOnGadget(void *gadget, const QVariant &value) const
3882{
3883 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3884 return write(object: reinterpret_cast<QObject*>(gadget), value);
3885}
3886
3887/*!
3888 \overload
3889 \since 6.6
3890*/
3891bool QMetaProperty::writeOnGadget(void *gadget, QVariant &&value) const
3892{
3893 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3894 return write(object: reinterpret_cast<QObject*>(gadget), v: std::move(value));
3895}
3896
3897/*!
3898 \since 5.5
3899
3900 Resets the property for the given \a gadget with a reset method.
3901 Returns \c true if the reset worked; otherwise returns \c false.
3902
3903 Reset methods are optional; only a few properties support them.
3904
3905 This function should only be used if this is a property of a Q_GADGET
3906*/
3907bool QMetaProperty::resetOnGadget(void *gadget) const
3908{
3909 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3910 return reset(object: reinterpret_cast<QObject*>(gadget));
3911}
3912
3913/*!
3914 Returns \c true if this property can be reset to a default value; otherwise
3915 returns \c false.
3916
3917 \sa reset()
3918*/
3919bool QMetaProperty::isResettable() const
3920{
3921 if (!mobj)
3922 return false;
3923 return data.flags() & Resettable;
3924}
3925
3926/*!
3927 Returns \c true if this property is readable; otherwise returns \c false.
3928
3929 \sa isWritable(), read(), isValid()
3930 */
3931bool QMetaProperty::isReadable() const
3932{
3933 if (!mobj)
3934 return false;
3935 return data.flags() & Readable;
3936}
3937
3938/*!
3939 Returns \c true if this property has a corresponding change notify signal;
3940 otherwise returns \c false.
3941
3942 \sa notifySignal()
3943 */
3944bool QMetaProperty::hasNotifySignal() const
3945{
3946 if (!mobj)
3947 return false;
3948 return data.notifyIndex() != uint(-1);
3949}
3950
3951/*!
3952 \since 4.5
3953
3954 Returns the QMetaMethod instance of the property change notifying signal if
3955 one was specified, otherwise returns an invalid QMetaMethod.
3956
3957 \sa hasNotifySignal()
3958 */
3959QMetaMethod QMetaProperty::notifySignal() const
3960{
3961 int id = notifySignalIndex();
3962 if (id != -1)
3963 return mobj->method(index: id);
3964 else
3965 return QMetaMethod();
3966}
3967
3968/*!
3969 \since 4.6
3970
3971 Returns the index of the property change notifying signal if one was
3972 specified, otherwise returns -1.
3973
3974 \sa hasNotifySignal()
3975 */
3976int QMetaProperty::notifySignalIndex() const
3977{
3978 if (!mobj || data.notifyIndex() == std::numeric_limits<uint>::max())
3979 return -1;
3980 uint methodIndex = data.notifyIndex();
3981 if (!(methodIndex & IsUnresolvedSignal))
3982 return methodIndex + mobj->methodOffset();
3983 methodIndex &= ~IsUnresolvedSignal;
3984 const QByteArray signalName = stringData(mo: mobj, index: methodIndex);
3985 const QMetaObject *m = mobj;
3986 // try 0-arg signal
3987 int idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(baseObject: &m, name: signalName, argc: 0, types: nullptr);
3988 if (idx >= 0)
3989 return idx + m->methodOffset();
3990 // try 1-arg signal
3991 QArgumentType argType(typeId());
3992 idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(baseObject: &m, name: signalName, argc: 1, types: &argType);
3993 if (idx >= 0)
3994 return idx + m->methodOffset();
3995 qWarning(msg: "QMetaProperty::notifySignal: cannot find the NOTIFY signal %s in class %s for property '%s'",
3996 signalName.constData(), mobj->className(), name());
3997 return -1;
3998}
3999
4000// This method has been around for a while, but the documentation was marked \internal until 5.1
4001/*!
4002 \since 5.1
4003
4004 Returns the property revision if one was specified by Q_REVISION, otherwise
4005 returns 0. Since Qt 6.0, non-zero values are encoded and can be decoded
4006 using QTypeRevision::fromEncodedVersion().
4007 */
4008int QMetaProperty::revision() const
4009{
4010 if (!mobj)
4011 return 0;
4012 return data.revision();
4013}
4014
4015/*!
4016 Returns \c true if this property is writable; otherwise returns
4017 false.
4018
4019 \sa isReadable(), write()
4020 */
4021bool QMetaProperty::isWritable() const
4022{
4023 if (!mobj)
4024 return false;
4025 return data.flags() & Writable;
4026}
4027
4028/*!
4029 Returns \c false if the \c{Q_PROPERTY()}'s \c DESIGNABLE attribute
4030 is false; otherwise returns \c true.
4031
4032 \sa isScriptable(), isStored()
4033*/
4034bool QMetaProperty::isDesignable() const
4035{
4036 if (!mobj)
4037 return false;
4038 return data.flags() & Designable;
4039}
4040
4041/*!
4042 Returns \c false if the \c{Q_PROPERTY()}'s \c SCRIPTABLE attribute
4043 is false; otherwise returns true.
4044
4045 \sa isDesignable(), isStored()
4046*/
4047bool QMetaProperty::isScriptable() const
4048{
4049 if (!mobj)
4050 return false;
4051 return data.flags() & Scriptable;
4052}
4053
4054/*!
4055 Returns \c true if the property is stored; otherwise returns
4056 false.
4057
4058 The function returns \c false if the
4059 \c{Q_PROPERTY()}'s \c STORED attribute is false; otherwise returns
4060 true.
4061
4062 \sa isDesignable(), isScriptable()
4063*/
4064bool QMetaProperty::isStored() const
4065{
4066 if (!mobj)
4067 return false;
4068 return data.flags() & Stored;
4069}
4070
4071/*!
4072 Returns \c false if the \c {Q_PROPERTY()}'s \c USER attribute is false.
4073 Otherwise it returns true, indicating the property is designated as the
4074 \c USER property, i.e., the one that the user can edit or
4075 that is significant in some other way.
4076
4077 \sa QMetaObject::userProperty(), isDesignable(), isScriptable()
4078*/
4079bool QMetaProperty::isUser() const
4080{
4081 if (!mobj)
4082 return false;
4083 return data.flags() & User;
4084}
4085
4086/*!
4087 \since 4.6
4088 Returns \c true if the property is constant; otherwise returns \c false.
4089
4090 A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute
4091 is set.
4092*/
4093bool QMetaProperty::isConstant() const
4094{
4095 if (!mobj)
4096 return false;
4097 return data.flags() & Constant;
4098}
4099
4100/*!
4101 \since 4.6
4102 Returns \c true if the property is final; otherwise returns \c false.
4103
4104 A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute
4105 is set.
4106*/
4107bool QMetaProperty::isFinal() const
4108{
4109 if (!mobj)
4110 return false;
4111 return data.flags() & Final;
4112}
4113
4114/*!
4115 \since 5.15
4116 Returns \c true if the property is required; otherwise returns \c false.
4117
4118 A property is final if the \c{Q_PROPERTY()}'s \c REQUIRED attribute
4119 is set.
4120*/
4121bool QMetaProperty::isRequired() const
4122{
4123 if (!mobj)
4124 return false;
4125 return data.flags() & Required;
4126}
4127
4128/*!
4129 \since 6.0
4130 Returns \c true if the \c{Q_PROPERTY()} exposes binding functionality; otherwise returns false.
4131
4132 This implies that you can create bindings that use this property as a dependency or install QPropertyObserver
4133 objects on this property. Unless the property is readonly, you can also set a binding on this property.
4134
4135 \sa QProperty, isWritable(), bindable()
4136*/
4137bool QMetaProperty::isBindable() const
4138{
4139 if (!mobj)
4140 return false;
4141 return (data.flags() & Bindable);
4142}
4143
4144/*!
4145 \class QMetaClassInfo
4146 \inmodule QtCore
4147
4148 \brief The QMetaClassInfo class provides additional information
4149 about a class.
4150
4151 \ingroup objectmodel
4152
4153 Class information items are simple \e{name}--\e{value} pairs that
4154 are specified using Q_CLASSINFO() in the source code. The
4155 information can be retrieved using name() and value(). For example:
4156
4157 \snippet code/src_corelib_kernel_qmetaobject.cpp 5
4158
4159 This mechanism is free for you to use in your Qt applications.
4160
4161 \note It's also used by the \l[ActiveQt]{Active Qt},
4162 \l[QtDBus]{Qt D-Bus}, \l[QtQml]{Qt Qml}, and \l{Qt Remote Objects}
4163 modules. Some keys might be set when using these modules.
4164
4165 \sa QMetaObject
4166*/
4167
4168/*!
4169 \fn QMetaClassInfo::QMetaClassInfo()
4170 \internal
4171*/
4172
4173/*!
4174 \fn const QMetaObject *QMetaClassInfo::enclosingMetaObject() const
4175 \internal
4176*/
4177
4178/*!
4179 Returns the name of this item.
4180
4181 \sa value()
4182*/
4183const char *QMetaClassInfo::name() const
4184{
4185 if (!mobj)
4186 return nullptr;
4187 return rawStringData(mo: mobj, index: data.name());
4188}
4189
4190/*!
4191 Returns the value of this item.
4192
4193 \sa name()
4194*/
4195const char *QMetaClassInfo::value() const
4196{
4197 if (!mobj)
4198 return nullptr;
4199 return rawStringData(mo: mobj, index: data.value());
4200}
4201
4202/*!
4203 \class QMethodRawArguments
4204 \internal
4205
4206 A wrapper class for the void ** arguments array used by the meta
4207 object system. If a slot uses a single argument of this type,
4208 the meta object system will pass the raw arguments array directly
4209 to the slot and set the arguments count in the slot description to
4210 zero, so that any signal can connect to it.
4211
4212 This is used internally to implement signal relay functionality in
4213 our state machine and dbus.
4214*/
4215
4216/*!
4217 \macro QMetaMethodArgument Q_ARG(Type, const Type &value)
4218 \relates QMetaObject
4219
4220 This macro takes a \a Type and a \a value of that type and
4221 returns a QMetaMethodArgument, which can be passed to the template
4222 QMetaObject::invokeMethod() with the \c {Args &&...} arguments.
4223
4224 \sa Q_RETURN_ARG()
4225*/
4226
4227/*!
4228 \macro QMetaMethodReturnArgument Q_RETURN_ARG(Type, Type &value)
4229 \relates QMetaObject
4230
4231 This macro takes a \a Type and a non-const reference to a \a
4232 value of that type and returns a QMetaMethodReturnArgument, which can be
4233 passed to the template QMetaObject::invokeMethod() with the \c {Args &&...}
4234 arguments.
4235
4236 \sa Q_ARG()
4237*/
4238
4239/*!
4240 \class QGenericArgument
4241 \inmodule QtCore
4242
4243 \brief The QGenericArgument class is an internal helper class for
4244 marshalling arguments.
4245
4246 This class should never be used directly. Please use the \l Q_ARG()
4247 macro instead.
4248
4249 \sa Q_ARG(), QMetaObject::invokeMethod(), QGenericReturnArgument
4250*/
4251
4252/*!
4253 \fn QGenericArgument::QGenericArgument(const char *name, const void *data)
4254
4255 Constructs a QGenericArgument object with the given \a name and \a data.
4256*/
4257
4258/*!
4259 \fn QGenericArgument::data () const
4260
4261 Returns the data set in the constructor.
4262*/
4263
4264/*!
4265 \fn QGenericArgument::name () const
4266
4267 Returns the name set in the constructor.
4268*/
4269
4270/*!
4271 \class QGenericReturnArgument
4272 \inmodule QtCore
4273
4274 \brief The QGenericReturnArgument class is an internal helper class for
4275 marshalling arguments.
4276
4277 This class should never be used directly. Please use the
4278 Q_RETURN_ARG() macro instead.
4279
4280 \sa Q_RETURN_ARG(), QMetaObject::invokeMethod(), QGenericArgument
4281*/
4282
4283/*!
4284 \fn QGenericReturnArgument::QGenericReturnArgument(const char *name, void *data)
4285
4286 Constructs a QGenericReturnArgument object with the given \a name
4287 and \a data.
4288*/
4289
4290/*!
4291 \internal
4292 If the local_method_index is a cloned method, return the index of the original.
4293
4294 Example: if the index of "destroyed()" is passed, the index of "destroyed(QObject*)" is returned
4295 */
4296int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
4297{
4298 Q_ASSERT(local_method_index < get(mobj)->methodCount);
4299 while (QMetaMethod::fromRelativeMethodIndex(mobj, index: local_method_index).data.flags() & MethodCloned) {
4300 Q_ASSERT(local_method_index > 0);
4301 --local_method_index;
4302 }
4303 return local_method_index;
4304}
4305
4306/*!
4307 \internal
4308
4309 Returns the parameter type names extracted from the given \a signature.
4310*/
4311QList<QByteArray> QMetaObjectPrivate::parameterTypeNamesFromSignature(const char *signature)
4312{
4313 QList<QByteArray> list;
4314 while (*signature && *signature != '(')
4315 ++signature;
4316 while (*signature && *signature != ')' && *++signature != ')') {
4317 const char *begin = signature;
4318 int level = 0;
4319 while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
4320 if (*signature == '<')
4321 ++level;
4322 else if (*signature == '>')
4323 --level;
4324 ++signature;
4325 }
4326 list += QByteArray(begin, signature - begin);
4327 }
4328 return list;
4329}
4330
4331QT_END_NAMESPACE
4332

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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