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