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

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