Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qmetaobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qmetaobject.h"
6#include "qmetatype.h"
7#include "qobject.h"
8#include "qmetaobject_p.h"
9#include "qmetatype_p.h"
10
11#include <qcoreapplication.h>
12#include <qcoreevent.h>
13#include <qdatastream.h>
14#include <qstringlist.h>
15#include <qthread.h>
16#include <qvariant.h>
17#include <qdebug.h>
18#if QT_CONFIG(thread)
19#include <qsemaphore.h>
20#endif
21
22#include "private/qobject_p.h"
23#include "private/qmetaobject_p.h"
24#include "private/qthread_p.h"
25
26// for normalizeTypeInternal
27#include "private/qmetaobject_moc_p.h"
28
29#include <ctype.h>
30#include <memory>
31
33
34using namespace Qt::StringLiterals;
35
123static inline const QMetaObjectPrivate *priv(const uint* data)
124{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
125
126static inline const char *rawStringData(const QMetaObject *mo, int index)
127{
128 Q_ASSERT(priv(mo->d.data)->revision >= 7);
129 uint offset = mo->d.stringdata[2*index];
130 return reinterpret_cast<const char *>(mo->d.stringdata) + offset;
131}
132
134{
135 Q_ASSERT(priv(mo->d.data)->revision >= 7);
136 uint offset = mo->d.stringdata[2*index];
137 uint length = mo->d.stringdata[2*index + 1];
138 const char *string = reinterpret_cast<const char *>(mo->d.stringdata) + offset;
139 return {string, qsizetype(length)};
140}
141
142static inline QByteArray stringData(const QMetaObject *mo, int index)
143{
144 const auto view = stringDataView(mo, index);
145 return QByteArray::fromRawData(view.data(), view.size());
146}
147
148static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
149{
150 if (typeInfo & IsUnresolvedType) {
151 return rawStringData(mo, typeInfo & TypeNameIndexMask);
152 } else {
153 return QMetaType(typeInfo).name();
154 }
155}
156
157static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
158{
159 if (typeInfo & IsUnresolvedType) {
160 return stringData(mo, typeInfo & TypeNameIndexMask);
161 } else {
162 return QMetaType(typeInfo).name();
163 }
164}
165
166static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo)
167{
168 if (!(typeInfo & IsUnresolvedType))
169 return typeInfo;
171}
172
173namespace {
174class QMetaMethodPrivate : public QMetaMethodInvoker
175{
176public:
177 static const QMetaMethodPrivate *get(const QMetaMethod *q)
178 { return static_cast<const QMetaMethodPrivate *>(q); }
179
180 inline QByteArray signature() const;
181 inline QByteArray name() const;
182 inline int typesDataIndex() const;
183 inline const char *rawReturnTypeName() const;
184 inline int returnType() const;
185 inline int parameterCount() const;
186 inline int parametersDataIndex() const;
187 inline uint parameterTypeInfo(int index) const;
188 inline int parameterType(int index) const;
189 inline void getParameterTypes(int *types) const;
190 inline const QtPrivate::QMetaTypeInterface *returnMetaTypeInterface() const;
191 inline const QtPrivate::QMetaTypeInterface *const *parameterMetaTypeInterfaces() const;
192 inline QByteArray parameterTypeName(int index) const;
193 inline QList<QByteArray> parameterTypes() const;
194 inline QList<QByteArray> parameterNames() const;
195 inline QByteArray tag() const;
196 inline int ownMethodIndex() const;
197 inline int ownConstructorMethodIndex() const;
198
199private:
200 void checkMethodMetaTypeConsistency(const QtPrivate::QMetaTypeInterface *iface, int index) const;
201 QMetaMethodPrivate();
202};
203} // unnamed namespace
204
205enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
206
207#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
223 QGenericArgument val1,
224 QGenericArgument val2,
225 QGenericArgument val3,
226 QGenericArgument val4,
227 QGenericArgument val5,
228 QGenericArgument val6,
229 QGenericArgument val7,
230 QGenericArgument val8,
231 QGenericArgument val9) const
232{
233 const char *typeNames[] = {
234 nullptr,
235 val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
236 val5.name(), val6.name(), val7.name(), val8.name(), val9.name()
237 };
238 const void *parameters[] = {
239 nullptr,
240 val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
241 val5.data(), val6.data(), val7.data(), val8.data(), val9.data()
242 };
243
244 int paramCount;
245 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
246 int len = int(qstrlen(typeNames[paramCount]));
247 if (len <= 0)
248 break;
249 }
250
251 return newInstanceImpl(this, paramCount, parameters, typeNames, nullptr);
252}
253#endif
254
270QObject *QMetaObject::newInstanceImpl(const QMetaObject *mobj, qsizetype paramCount,
271 const void **parameters, const char **typeNames,
272 const QtPrivate::QMetaTypeInterface **metaTypes)
273{
274 if (!mobj->inherits(&QObject::staticMetaObject)) {
275 qWarning("QMetaObject::newInstance: type %s does not inherit QObject", mobj->className());
276 return nullptr;
277 }
278
280#if Q_CC_GNU >= 1200
281QT_WARNING_DISABLE_GCC("-Wdangling-pointer")
282#endif
283
284 // set the return type
285 QObject *returnValue = nullptr;
286 QMetaType returnValueMetaType = QMetaType::fromType<decltype(returnValue)>();
287 parameters[0] = &returnValue;
288 typeNames[0] = returnValueMetaType.name();
289 if (metaTypes)
290 metaTypes[0] = returnValueMetaType.iface();
291
293
294 // find the constructor
295 auto priv = QMetaObjectPrivate::get(mobj);
296 for (int i = 0; i < priv->constructorCount; ++i) {
297 QMetaMethod m = QMetaMethod::fromRelativeConstructorIndex(mobj, i);
298 if (m.parameterCount() != (paramCount - 1))
299 continue;
300
301 // attempt to call
302 QMetaMethodPrivate::InvokeFailReason r =
303 QMetaMethodPrivate::invokeImpl(m, nullptr, Qt::DirectConnection, paramCount,
304 parameters, typeNames, metaTypes);
305 if (r == QMetaMethodPrivate::InvokeFailReason::None)
306 return returnValue;
307 if (int(r) < 0)
308 return nullptr;
309 }
310
311 return returnValue;
312}
313
317int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
318{
319 Q_ASSERT(priv(d.data)->revision >= 6);
320 if (!d.static_metacall)
321 return 0;
322 d.static_metacall(nullptr, cl, idx, argv);
323 return -1;
324}
325
329int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
330{
331 if (object->d_ptr->metaObject)
332 return object->d_ptr->metaObject->metaCall(object, cl, idx, argv);
333 else
334 return object->qt_metacall(cl, idx, argv);
335}
336
337static inline const char *objectClassName(const QMetaObject *m)
338{
339 return rawStringData(m, priv(m->d.data)->className);
340}
341
347const char *QMetaObject::className() const
348{
349 return objectClassName(this);
350}
351
370{
371 const QMetaObject *m = this;
372 do {
373 if (metaObject == m)
374 return true;
375 } while ((m = m->d.superdata));
376 return false;
377}
378
394{
395 return (obj && obj->metaObject()->inherits(this)) ? obj : nullptr;
396}
397
398#ifndef QT_NO_TRANSLATION
402QString QMetaObject::tr(const char *s, const char *c, int n) const
403{
405}
406#endif // QT_NO_TRANSLATION
407
414{
415
416 const QMetaObjectPrivate *d = priv(this->d.data);
417 if (d->revision < 10) {
418 // before revision 10, we did not store the metatype in the metatype array
420 } else {
421 /* in the metatype array, we store
422
423 | index | data |
424 |----------------------------------------------------------------------|
425 | 0 | QMetaType(property0) |
426 | ... | ... |
427 | propertyCount - 1 | QMetaType(propertyCount - 1) |
428 | propertyCount | QMetaType(enumerator0) |
429 | ... | ... |
430 | propertyCount + enumeratorCount - 1 | QMetaType(enumeratorCount - 1) |
431 | propertyCount + enumeratorCount | QMetaType(class) |
432
433 */
434#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
435 // Before revision 12 we only stored metatypes for enums if they showed
436 // up as types of properties or method arguments or return values.
437 // From revision 12 on, we always store them in a predictable place.
438 const qsizetype offset = d->revision < 12
439 ? d->propertyCount
440 : d->propertyCount + d->enumeratorCount;
441#else
442 const qsizetype offset = d->propertyCount + d->enumeratorCount;
443#endif
444
445 auto iface = this->d.metaTypes[offset];
446 if (iface && QtMetaTypePrivate::isInterfaceFor<void>(iface))
447 return QMetaType(); // return invalid meta-type for namespaces
448 if (iface)
449 return QMetaType(iface);
450 else // in case of a dynamic metaobject, we might have no metatype stored
451 return QMetaType::fromName(className()); // try lookup by name in that case
452 }
453}
454
466{
467 int offset = 0;
468 const QMetaObject *m = d.superdata;
469 while (m) {
470 offset += priv(m->d.data)->methodCount;
471 m = m->d.superdata;
472 }
473 return offset;
474}
475
476
488{
489 int offset = 0;
490 const QMetaObject *m = d.superdata;
491 while (m) {
492 offset += priv(m->d.data)->enumeratorCount;
493 m = m->d.superdata;
494 }
495 return offset;
496}
497
509{
510 int offset = 0;
511 const QMetaObject *m = d.superdata;
512 while (m) {
513 offset += priv(m->d.data)->propertyCount;
514 m = m->d.superdata;
515 }
516 return offset;
517}
518
530{
531 int offset = 0;
532 const QMetaObject *m = d.superdata;
533 while (m) {
534 offset += priv(m->d.data)->classInfoCount;
535 m = m->d.superdata;
536 }
537 return offset;
538}
539
548{
549 Q_ASSERT(priv(d.data)->revision >= 2);
550 return priv(d.data)->constructorCount;
551}
552
566{
567 int n = priv(d.data)->methodCount;
568 const QMetaObject *m = d.superdata;
569 while (m) {
570 n += priv(m->d.data)->methodCount;
571 m = m->d.superdata;
572 }
573 return n;
574}
575
582{
583 int n = priv(d.data)->enumeratorCount;
584 const QMetaObject *m = d.superdata;
585 while (m) {
586 n += priv(m->d.data)->enumeratorCount;
587 m = m->d.superdata;
588 }
589 return n;
590}
591
604{
605 int n = priv(d.data)->propertyCount;
606 const QMetaObject *m = d.superdata;
607 while (m) {
608 n += priv(m->d.data)->propertyCount;
609 m = m->d.superdata;
610 }
611 return n;
612}
613
620{
621 int n = priv(d.data)->classInfoCount;
622 const QMetaObject *m = d.superdata;
623 while (m) {
624 n += priv(m->d.data)->classInfoCount;
625 m = m->d.superdata;
626 }
627 return n;
628}
629
630// Returns \c true if the method defined by the given meta-object&meta-method
631// matches the given name, argument count and argument types, otherwise
632// returns \c false.
634 const QByteArray &name, int argc,
635 const QArgumentType *types)
636{
637 const QMetaMethod::Data &data = method.data;
638 auto priv = QMetaMethodPrivate::get(&method);
639 if (priv->parameterCount() != argc)
640 return false;
641
642 if (stringData(m, data.name()) != name)
643 return false;
644
645 const QtPrivate::QMetaTypeInterface * const *ifaces = priv->parameterMetaTypeInterfaces();
646 int paramsIndex = data.parameters() + 1;
647 for (int i = 0; i < argc; ++i) {
648 uint typeInfo = m->d.data[paramsIndex + i];
649 if (int id = types[i].type()) {
650 if (id == QMetaType(ifaces[i]).id())
651 continue;
652 if (id != typeFromTypeInfo(m, typeInfo))
653 return false;
654 } else {
655 if (types[i].name() == QMetaType(ifaces[i]).name())
656 continue;
657 if (types[i].name() != typeNameFromTypeInfo(m, typeInfo))
658 return false;
659 }
660 }
661
662 return true;
663}
664
670{
671 for (const QMetaObject *currentObject = baseObject; currentObject; currentObject = currentObject->superClass()) {
672 const int start = priv(currentObject->d.data)->methodCount - 1;
673 const int end = 0;
674 for (int i = start; i >= end; --i) {
675 auto candidate = QMetaMethod::fromRelativeMethodIndex(currentObject, i);
676 if (name == candidate.name())
677 return candidate;
678 }
679 }
680 return QMetaMethod{};
681}
682
689template<int MethodType>
691 const QByteArray &name, int argc,
692 const QArgumentType *types)
693{
694 for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {
695 Q_ASSERT(priv(m->d.data)->revision >= 7);
696 int i = (MethodType == MethodSignal)
697 ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1);
698 const int end = (MethodType == MethodSlot)
699 ? (priv(m->d.data)->signalCount) : 0;
700
701 for (; i >= end; --i) {
702 auto data = QMetaMethod::fromRelativeMethodIndex(m, i);
703 if (methodMatch(m, data, name, argc, types)) {
704 *baseObject = m;
705 return i;
706 }
707 }
708 }
709 return -1;
710}
711
712
723int QMetaObject::indexOfConstructor(const char *constructor) const
724{
725 Q_ASSERT(priv(d.data)->revision >= 7);
728 return QMetaObjectPrivate::indexOfConstructor(this, name, types.size(), types.constData());
729}
730
739int QMetaObject::indexOfMethod(const char *method) const
740{
741 const QMetaObject *m = this;
742 int i;
743 Q_ASSERT(priv(m->d.data)->revision >= 7);
746 i = QMetaObjectPrivate::indexOfMethodRelative<0>(&m, name, types.size(), types.constData());
747 if (i >= 0)
748 i += m->methodOffset();
749 return i;
750}
751
752// Parses a string of comma-separated types into QArgumentTypes.
753// No normalization of the type names is performed.
754static void argumentTypesFromString(const char *str, const char *end,
756{
757 Q_ASSERT(str <= end);
758 while (str != end) {
759 if (!types.isEmpty())
760 ++str; // Skip comma
761 const char *begin = str;
762 int level = 0;
763 while (str != end && (level > 0 || *str != ',')) {
764 if (*str == '<')
765 ++level;
766 else if (*str == '>')
767 --level;
768 ++str;
769 }
770 QByteArray argType(begin, str - begin);
771 argType.replace("QVector<", "QList<");
772 types += QArgumentType(std::move(argType));
773 }
774}
775
776// Given a method \a signature (e.g. "foo(int,double)"), this function
777// populates the argument \a types array and returns the method name.
779 const char *signature, QArgumentTypeArray &types)
780{
781 Q_ASSERT(signature != nullptr);
782 const char *lparens = strchr(signature, '(');
783 if (!lparens)
784 return QByteArray();
785 const char *rparens = strrchr(lparens + 1, ')');
786 if (!rparens || *(rparens+1))
787 return QByteArray();
788 int nameLength = lparens - signature;
789 argumentTypesFromString(lparens + 1, rparens, types);
790 return QByteArray::fromRawData(signature, nameLength);
791}
792
804int QMetaObject::indexOfSignal(const char *signal) const
805{
806 const QMetaObject *m = this;
807 int i;
808 Q_ASSERT(priv(m->d.data)->revision >= 7);
812 if (i >= 0)
813 i += m->methodOffset();
814 return i;
815}
816
824 const QByteArray &name, int argc,
825 const QArgumentType *types)
826{
827 int i = indexOfMethodRelative<MethodSignal>(baseObject, name, argc, types);
828#ifndef QT_NO_DEBUG
829 const QMetaObject *m = *baseObject;
830 if (i >= 0 && m && m->d.superdata) {
831 int conflict = indexOfMethod(m->d.superdata, name, argc, types);
832 if (conflict >= 0) {
833 QMetaMethod conflictMethod = m->d.superdata->method(conflict);
834 qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
835 conflictMethod.methodSignature().constData(),
836 objectClassName(m->d.superdata), objectClassName(m));
837 }
838 }
839 #endif
840 return i;
841}
842
851int QMetaObject::indexOfSlot(const char *slot) const
852{
853 const QMetaObject *m = this;
854 int i;
855 Q_ASSERT(priv(m->d.data)->revision >= 7);
858 i = QMetaObjectPrivate::indexOfSlotRelative(&m, name, types.size(), types.constData());
859 if (i >= 0)
860 i += m->methodOffset();
861 return i;
862}
863
864// same as indexOfSignalRelative but for slots.
866 const QByteArray &name, int argc,
867 const QArgumentType *types)
868{
869 return indexOfMethodRelative<MethodSlot>(m, name, argc, types);
870}
871
873 int argc, const QArgumentType *types)
874{
875 int i = indexOfSignalRelative(&m, name, argc, types);
876 if (i >= 0)
877 i += m->methodOffset();
878 return i;
879}
880
882 int argc, const QArgumentType *types)
883{
884 int i = indexOfSlotRelative(&m, name, argc, types);
885 if (i >= 0)
886 i += m->methodOffset();
887 return i;
888}
889
891 int argc, const QArgumentType *types)
892{
893 int i = indexOfMethodRelative<0>(&m, name, argc, types);
894 if (i >= 0)
895 i += m->methodOffset();
896 return i;
897}
898
900 int argc, const QArgumentType *types)
901{
902 for (int i = priv(m->d.data)->constructorCount-1; i >= 0; --i) {
903 const QMetaMethod method = QMetaMethod::fromRelativeConstructorIndex(m, i);
904 if (methodMatch(m, method, name, argc, types))
905 return i;
906 }
907 return -1;
908}
909
933{
934 Q_ASSERT(m != nullptr);
935 int n = priv(m->d.data)->signalCount;
936 for (m = m->d.superdata; m; m = m->d.superdata)
937 n += priv(m->d.data)->signalCount;
938 return n;
939}
940
951{
952 if (!m.mobj)
953 return -1;
954 return QMetaMethodPrivate::get(&m)->ownMethodIndex() + signalOffset(m.mobj);
955}
956
967{
968 if (signal_index < 0)
969 return QMetaMethod();
970
971 Q_ASSERT(m != nullptr);
972 int i = signal_index;
973 i -= signalOffset(m);
974 if (i < 0 && m->d.superdata)
975 return signal(m->d.superdata, signal_index);
976
977
978 if (i >= 0 && i < priv(m->d.data)->signalCount)
979 return QMetaMethod::fromRelativeMethodIndex(m, i);
980 return QMetaMethod();
981}
982
989bool QMetaObjectPrivate::checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
990 int methodArgc, const QArgumentType *methodTypes)
991{
992 if (signalArgc < methodArgc)
993 return false;
994 for (int i = 0; i < methodArgc; ++i) {
995 if (signalTypes[i] != methodTypes[i])
996 return false;
997 }
998 return true;
999}
1000
1007bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
1008 const QMetaMethodPrivate *method)
1009{
1010 if (signal->methodType() != QMetaMethod::Signal)
1011 return false;
1012 if (signal->parameterCount() < method->parameterCount())
1013 return false;
1014 const QMetaObject *smeta = signal->enclosingMetaObject();
1015 const QMetaObject *rmeta = method->enclosingMetaObject();
1016 for (int i = 0; i < method->parameterCount(); ++i) {
1017 uint sourceTypeInfo = signal->parameterTypeInfo(i);
1018 uint targetTypeInfo = method->parameterTypeInfo(i);
1019 if ((sourceTypeInfo & IsUnresolvedType)
1020 || (targetTypeInfo & IsUnresolvedType)) {
1021 QByteArray sourceName = typeNameFromTypeInfo(smeta, sourceTypeInfo);
1022 QByteArray targetName = typeNameFromTypeInfo(rmeta, targetTypeInfo);
1023 if (sourceName != targetName)
1024 return false;
1025 } else {
1026 int sourceType = typeFromTypeInfo(smeta, sourceTypeInfo);
1027 int targetType = typeFromTypeInfo(rmeta, targetTypeInfo);
1028 if (sourceType != targetType)
1029 return false;
1030 }
1031 }
1032 return true;
1033}
1034
1035static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
1036{
1037 while (self) {
1038 if (strcmp(objectClassName(self), name) == 0)
1039 return self;
1040 if (self->d.relatedMetaObjects) {
1041 Q_ASSERT(priv(self->d.data)->revision >= 2);
1042 const auto *e = self->d.relatedMetaObjects;
1043 if (e) {
1044 while (*e) {
1046 return m;
1047 ++e;
1048 }
1049 }
1050 }
1051 self = self->d.superdata;
1052 }
1053 return self;
1054}
1055
1063{
1064 const QMetaObject *m = this;
1065 while (m) {
1066 const QMetaObjectPrivate *d = priv(m->d.data);
1067 for (int i = 0; i < d->enumeratorCount; ++i) {
1068 const QMetaEnum e(m, i);
1069 const char *prop = rawStringData(m, e.data.name());
1070 if (strcmp(name, prop) == 0) {
1071 i += m->enumeratorOffset();
1072 return i;
1073 }
1074 }
1075 m = m->d.superdata;
1076 }
1077 // Check alias names:
1078 m = this;
1079 while (m) {
1080 const QMetaObjectPrivate *d = priv(m->d.data);
1081 for (int i = 0; i < d->enumeratorCount; ++i) {
1082 const QMetaEnum e(m, i);
1083 const char *prop = rawStringData(m, e.data.alias());
1084 if (strcmp(name, prop) == 0) {
1085 i += m->enumeratorOffset();
1086 return i;
1087 }
1088 }
1089 m = m->d.superdata;
1090 }
1091 return -1;
1092}
1093
1101{
1102 const QMetaObject *m = this;
1103 while (m) {
1104 const QMetaObjectPrivate *d = priv(m->d.data);
1105 for (int i = 0; i < d->propertyCount; ++i) {
1106 const QMetaProperty::Data data = QMetaProperty::getMetaPropertyData(m, i);
1107 const char *prop = rawStringData(m, data.name());
1108 if (strcmp(name, prop) == 0) {
1109 i += m->propertyOffset();
1110 return i;
1111 }
1112 }
1113 m = m->d.superdata;
1114 }
1115
1116 if (priv(this->d.data)->flags & DynamicMetaObject) {
1118 const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
1119
1120 return me->createProperty(name, nullptr);
1121 }
1122
1123 return -1;
1124}
1125
1133{
1134 int i = -1;
1135 const QMetaObject *m = this;
1136 while (m && i < 0) {
1137 for (i = priv(m->d.data)->classInfoCount-1; i >= 0; --i)
1138 if (strcmp(name, rawStringData(m, m->d.data[priv(m->d.data)->classInfoData + 2*i])) == 0) {
1139 i += m->classInfoOffset();
1140 break;
1141 }
1142 m = m->d.superdata;
1143 }
1144 return i;
1145}
1146
1155{
1156 int i = index;
1157 if (i >= 0 && i < priv(d.data)->constructorCount)
1158 return QMetaMethod::fromRelativeConstructorIndex(this, i);
1159 return QMetaMethod();
1160}
1161
1168{
1169 int i = index;
1170 i -= methodOffset();
1171 if (i < 0 && d.superdata)
1172 return d.superdata->method(index);
1173
1174 if (i >= 0 && i < priv(d.data)->methodCount)
1175 return QMetaMethod::fromRelativeMethodIndex(this, i);
1176 return QMetaMethod();
1177}
1178
1185{
1186 int i = index;
1187 i -= enumeratorOffset();
1188 if (i < 0 && d.superdata)
1189 return d.superdata->enumerator(index);
1190
1191 if (i >= 0 && i < priv(d.data)->enumeratorCount)
1192 return QMetaEnum(this, i);
1193 return QMetaEnum();
1194}
1195
1203{
1204 int i = index;
1205 i -= propertyOffset();
1206 if (i < 0 && d.superdata)
1207 return d.superdata->property(index);
1208
1209 if (i >= 0 && i < priv(d.data)->propertyCount)
1210 return QMetaProperty(this, i);
1211 return QMetaProperty();
1212}
1213
1222{
1223 const int propCount = propertyCount();
1224 for (int i = propCount - 1; i >= 0; --i) {
1225 const QMetaProperty prop = property(i);
1226 if (prop.isUser())
1227 return prop;
1228 }
1229 return QMetaProperty();
1230}
1231
1243{
1244 int i = index;
1245 i -= classInfoOffset();
1246 if (i < 0 && d.superdata)
1247 return d.superdata->classInfo(index);
1248
1250 if (i >= 0 && i < priv(d.data)->classInfoCount) {
1251 result.mobj = this;
1252 result.data = { d.data + priv(d.data)->classInfoData + i * QMetaClassInfo::Data::Size };
1253 }
1254 return result;
1255}
1256
1265bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
1266{
1267 const char *s1 = signal;
1268 const char *s2 = method;
1269 while (*s1++ != '(') { } // scan to first '('
1270 while (*s2++ != '(') { }
1271 if (*s2 == ')' || qstrcmp(s1,s2) == 0) // method has no args or
1272 return true; // exact match
1273 const auto s1len = qstrlen(s1);
1274 const auto s2len = qstrlen(s2);
1275 if (s2len < s1len && strncmp(s1,s2,s2len-1)==0 && s1[s2len-1]==',')
1276 return true; // method has less args
1277 return false;
1278}
1279
1288 const QMetaMethod &method)
1289{
1291 QMetaMethodPrivate::get(&signal),
1292 QMetaMethodPrivate::get(&method));
1293}
1294
1295static void qRemoveWhitespace(const char *s, char *d)
1296{
1297 char last = 0;
1298 while (*s && is_space(*s))
1299 s++;
1300 while (*s) {
1301 while (*s && !is_space(*s))
1302 last = *d++ = *s++;
1303 while (*s && is_space(*s))
1304 s++;
1305 if (*s && ((is_ident_char(*s) && is_ident_char(last))
1306 || ((*s == ':') && (last == '<')))) {
1307 last = *d++ = ' ';
1308 }
1309 }
1310 *d = '\0';
1311}
1312
1313static char *qNormalizeType(char *d, int &templdepth, QByteArray &result)
1314{
1315 const char *t = d;
1316 while (*d && (templdepth
1317 || (*d != ',' && *d != ')'))) {
1318 if (*d == '<')
1319 ++templdepth;
1320 if (*d == '>')
1321 --templdepth;
1322 ++d;
1323 }
1324 // "void" should only be removed if this is part of a signature that has
1325 // an explicit void argument; e.g., "void foo(void)" --> "void foo()"
1326 if (strncmp("void)", t, d - t + 1) != 0)
1327 result += normalizeTypeInternal(t, d);
1328
1329 return d;
1330}
1331
1332
1348{
1349 return normalizeTypeInternal(type, type + qstrlen(type));
1350}
1351
1364{
1366 if (!method || !*method)
1367 return result;
1368 int len = int(strlen(method));
1369 QVarLengthArray<char> stackbuf(len + 1);
1370 char *d = stackbuf.data();
1372
1373 result.reserve(len);
1374
1375 int argdepth = 0;
1376 int templdepth = 0;
1377 while (*d) {
1378 if (argdepth == 1) {
1379 d = qNormalizeType(d, templdepth, result);
1380 if (!*d) //most likely an invalid signature.
1381 break;
1382 }
1383 if (*d == '(')
1384 ++argdepth;
1385 if (*d == ')')
1386 --argdepth;
1387 result += *d++;
1388 }
1389
1390 return result;
1391}
1392
1393Q_DECL_COLD_FUNCTION static inline bool
1395 const char *const *names,
1396 const QtPrivate::QMetaTypeInterface * const *metaTypes)
1397{
1398 // now find the candidates we couldn't use
1399 QByteArray candidateMessage;
1400 for (int i = 0; i < meta->methodCount(); ++i) {
1401 const QMetaMethod method = meta->method(i);
1402 if (method.name() == QByteArrayView(name))
1403 candidateMessage += " " + method.methodSignature() + '\n';
1404 }
1405 if (!candidateMessage.isEmpty()) {
1406 candidateMessage.prepend("\nCandidates are:\n");
1407 candidateMessage.chop(1);
1408 }
1409
1411 for (qsizetype i = 1; i < paramCount; ++i) {
1412 if (names[i])
1413 sig.append(names[i], qstrlen(names[i]));
1414 else
1415 sig.append(metaTypes[i]->name, qstrlen(metaTypes[i]->name));
1416 sig.append(',');
1417 }
1418 if (paramCount != 1)
1419 sig.resize(sig.size() - 1);
1420
1421 qWarning("QMetaObject::invokeMethod: No such method %s::%.*s(%.*s)%.*s",
1422 meta->className(), int(name.size()), name.constData(),
1423 int(sig.size()), sig.constData(),
1424 int(candidateMessage.size()), candidateMessage.constData());
1425 return false;
1426}
1427
1543 const char *member,
1546 QGenericArgument val0,
1547 QGenericArgument val1,
1548 QGenericArgument val2,
1549 QGenericArgument val3,
1550 QGenericArgument val4,
1551 QGenericArgument val5,
1552 QGenericArgument val6,
1553 QGenericArgument val7,
1554 QGenericArgument val8,
1555 QGenericArgument val9)
1556{
1557 if (!obj)
1558 return false;
1559
1560 const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(),
1561 val4.name(), val5.name(), val6.name(), val7.name(), val8.name(),
1562 val9.name()};
1563 const void *parameters[] = {ret.data(), val0.data(), val1.data(), val2.data(), val3.data(),
1564 val4.data(), val5.data(), val6.data(), val7.data(), val8.data(),
1565 val9.data()};
1566 int paramCount;
1567 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
1568 if (qstrlen(typeNames[paramCount]) <= 0)
1569 break;
1570 }
1571 return invokeMethodImpl(obj, member, type, paramCount, parameters, typeNames, nullptr);
1572}
1573
1574bool QMetaObject::invokeMethodImpl(QObject *obj, const char *member, Qt::ConnectionType type,
1575 qsizetype paramCount, const void * const *parameters,
1576 const char * const *typeNames,
1577 const QtPrivate::QMetaTypeInterface * const *metaTypes)
1578{
1579 if (!obj)
1580 return false;
1581
1582 Q_ASSERT(paramCount >= 1); // includes the return type
1583 Q_ASSERT(parameters);
1584 Q_ASSERT(typeNames);
1585
1586 // find the method
1587 QLatin1StringView name(member);
1588 if (name.isEmpty())
1589 return false;
1590
1591 const QMetaObject *meta = obj->metaObject();
1592 for ( ; meta; meta = meta->superClass()) {
1593 auto priv = QMetaObjectPrivate::get(meta);
1594 for (int i = 0; i < priv->methodCount; ++i) {
1595 QMetaMethod m = QMetaMethod::fromRelativeMethodIndex(meta, i);
1596 if (m.parameterCount() != (paramCount - 1))
1597 continue;
1598 if (name != stringDataView(meta, m.data.name()))
1599 continue;
1600
1601 // attempt to call
1602 QMetaMethodPrivate::InvokeFailReason r =
1603 QMetaMethodPrivate::invokeImpl(m, obj, type, paramCount, parameters,
1604 typeNames, metaTypes);
1605 if (int(r) <= 0)
1606 return r == QMetaMethodPrivate::InvokeFailReason::None;
1607 }
1608 }
1609
1610 // This method doesn't belong to us; print out a nice warning with candidates.
1611 return printMethodNotFoundWarning(obj->metaObject(), name, paramCount, typeNames, metaTypes);
1612}
1613
1614bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret)
1615{
1616 auto slotGuard = qScopeGuard([slot] { slot->destroyIfLastRef(); });
1617
1618 if (! object)
1619 return false;
1620
1621 Qt::HANDLE currentThreadId = QThread::currentThreadId();
1622 QThread *objectThread = object->thread();
1623 bool receiverInSameThread = false;
1624 if (objectThread)
1625 receiverInSameThread = currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
1626
1627 if (type == Qt::AutoConnection)
1628 type = receiverInSameThread ? Qt::DirectConnection : Qt::QueuedConnection;
1629
1630 void *argv[] = { ret };
1631
1632 if (type == Qt::DirectConnection) {
1633 slot->call(object, argv);
1634 } else if (type == Qt::QueuedConnection) {
1635 if (argv[0]) {
1636 qWarning("QMetaObject::invokeMethod: Unable to invoke methods with return values in "
1637 "queued connections");
1638 return false;
1639 }
1640
1641 QCoreApplication::postEvent(object, new QMetaCallEvent(slot, nullptr, -1, 1));
1642 } else if (type == Qt::BlockingQueuedConnection) {
1643#if QT_CONFIG(thread)
1644 if (receiverInSameThread)
1645 qWarning("QMetaObject::invokeMethod: Dead lock detected");
1646
1647 QSemaphore semaphore;
1648 QCoreApplication::postEvent(object, new QMetaCallEvent(slot, nullptr, -1, argv, &semaphore));
1649 semaphore.acquire();
1650#endif // QT_CONFIG(thread)
1651 } else {
1652 qWarning("QMetaObject::invokeMethod: Unknown connection type");
1653 return false;
1654 }
1655 return true;
1656}
1657
1827QMetaMethod QMetaMethod::fromRelativeMethodIndex(const QMetaObject *mobj, int index)
1828{
1829 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->methodCount);
1830 QMetaMethod m;
1831 m.mobj = mobj;
1832 m.data = { mobj->d.data + priv(mobj->d.data)->methodData + index * Data::Size };
1833 return m;
1834}
1835
1836QMetaMethod QMetaMethod::fromRelativeConstructorIndex(const QMetaObject *mobj, int index)
1837{
1839 QMetaMethod m;
1840 m.mobj = mobj;
1841 m.data = { mobj->d.data + priv(mobj->d.data)->constructorData + index * Data::Size };
1842 return m;
1843}
1844
1853QByteArray QMetaMethodPrivate::signature() const
1854{
1855 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1857 result.reserve(256);
1858 result += name();
1859 result += '(';
1860 QList<QByteArray> argTypes = parameterTypes();
1861 for (int i = 0; i < argTypes.size(); ++i) {
1862 if (i)
1863 result += ',';
1864 result += argTypes.at(i);
1865 }
1866 result += ')';
1867 return result;
1868}
1869
1870QByteArray QMetaMethodPrivate::name() const
1871{
1872 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1873 return stringData(mobj, data.name());
1874}
1875
1876int QMetaMethodPrivate::typesDataIndex() const
1877{
1878 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1879 return data.parameters();
1880}
1881
1882const char *QMetaMethodPrivate::rawReturnTypeName() const
1883{
1884 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1885 uint typeInfo = mobj->d.data[typesDataIndex()];
1886 if (typeInfo & IsUnresolvedType)
1887 return rawStringData(mobj, typeInfo & TypeNameIndexMask);
1888 else
1889 return QMetaType(typeInfo).name();
1890}
1891
1892int QMetaMethodPrivate::returnType() const
1893{
1894 return parameterType(-1);
1895}
1896
1897int QMetaMethodPrivate::parameterCount() const
1898{
1899 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1900 return data.argc();
1901}
1902
1903inline void
1904QMetaMethodPrivate::checkMethodMetaTypeConsistency(const QtPrivate::QMetaTypeInterface *iface,
1905 int index) const
1906{
1907 uint typeInfo = parameterTypeInfo(index);
1908 QMetaType mt(iface);
1909 if (iface) {
1910 if ((typeInfo & IsUnresolvedType) == 0)
1911 Q_ASSERT(mt.id() == int(typeInfo & TypeNameIndexMask));
1912 Q_ASSERT(mt.name());
1913 } else {
1914 // The iface can only be null for a parameter if that parameter is a
1915 // const-ref to a forward-declared type. Since primitive types are
1916 // never incomplete, we can assert it's not one of them.
1917
1918#define ASSERT_NOT_PRIMITIVE_TYPE(TYPE, METATYPEID, NAME) \
1919 Q_ASSERT(typeInfo != QMetaType::TYPE);
1921#undef ASSERT_NOT_PRIMITIVE_TYPE
1922 Q_ASSERT(typeInfo != QMetaType::QObjectStar);
1923
1924 // Prior to Qt 6.4 we failed to record void and void*
1925 if (priv(mobj->d.data)->revision >= 11) {
1926 Q_ASSERT(typeInfo != QMetaType::Void);
1927 Q_ASSERT(typeInfo != QMetaType::VoidStar);
1928 }
1929 }
1930}
1931
1932int QMetaMethodPrivate::parametersDataIndex() const
1933{
1934 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1935 return typesDataIndex() + 1;
1936}
1937
1938uint QMetaMethodPrivate::parameterTypeInfo(int index) const
1939{
1940 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1941 return mobj->d.data[parametersDataIndex() + index];
1942}
1943
1944const QtPrivate::QMetaTypeInterface *QMetaMethodPrivate::returnMetaTypeInterface() const
1945{
1946 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1947 if (methodType() == QMetaMethod::Constructor)
1948 return nullptr; // constructors don't have return types
1949
1950 const QtPrivate::QMetaTypeInterface *iface = mobj->d.metaTypes[data.metaTypeOffset()];
1951 checkMethodMetaTypeConsistency(iface, -1);
1952 return iface;
1953}
1954
1955const QtPrivate::QMetaTypeInterface * const *QMetaMethodPrivate::parameterMetaTypeInterfaces() const
1956{
1957 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1958 int offset = (methodType() == QMetaMethod::Constructor ? 0 : 1);
1959 const auto ifaces = &mobj->d.metaTypes[data.metaTypeOffset() + offset];
1960
1961 for (int i = 0; i < parameterCount(); ++i)
1962 checkMethodMetaTypeConsistency(ifaces[i], i);
1963
1964 return ifaces;
1965}
1966
1967int QMetaMethodPrivate::parameterType(int index) const
1968{
1969 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1970 return typeFromTypeInfo(mobj, parameterTypeInfo(index));
1971}
1972
1973void QMetaMethodPrivate::getParameterTypes(int *types) const
1974{
1975 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1976 int dataIndex = parametersDataIndex();
1977 int argc = parameterCount();
1978 for (int i = 0; i < argc; ++i) {
1979 int id = typeFromTypeInfo(mobj, mobj->d.data[dataIndex++]);
1980 *(types++) = id;
1981 }
1982}
1983
1984QByteArray QMetaMethodPrivate::parameterTypeName(int index) const
1985{
1986 int paramsIndex = parametersDataIndex();
1987 return typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + index]);
1988}
1989
1990QList<QByteArray> QMetaMethodPrivate::parameterTypes() const
1991{
1992 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1993 int argc = parameterCount();
1995 list.reserve(argc);
1996 int paramsIndex = parametersDataIndex();
1997 for (int i = 0; i < argc; ++i)
1998 list += typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + i]);
1999 return list;
2000}
2001
2002QList<QByteArray> QMetaMethodPrivate::parameterNames() const
2003{
2004 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2005 int argc = parameterCount();
2007 list.reserve(argc);
2008 int namesIndex = parametersDataIndex() + argc;
2009 for (int i = 0; i < argc; ++i)
2010 list += stringData(mobj, mobj->d.data[namesIndex + i]);
2011 return list;
2012}
2013
2014QByteArray QMetaMethodPrivate::tag() const
2015{
2016 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2017 return stringData(mobj, data.tag());
2018}
2019
2020int QMetaMethodPrivate::ownMethodIndex() const
2021{
2022 // recompute the methodIndex by reversing the arithmetic in QMetaObject::method()
2023 return ( data.d - mobj->d.data - priv(mobj->d.data)->methodData)/Data::Size;
2024}
2025
2026int QMetaMethodPrivate::ownConstructorMethodIndex() const
2027{
2028 // recompute the methodIndex by reversing the arithmetic in QMetaObject::constructor()
2029 Q_ASSERT(methodType() == Constructor);
2030 return ( data.d - mobj->d.data - priv(mobj->d.data)->constructorData)/Data::Size;
2031}
2032
2042{
2043 if (!mobj)
2044 return QByteArray();
2045 return QMetaMethodPrivate::get(this)->signature();
2046}
2047
2056{
2057 if (!mobj)
2058 return QByteArray();
2059 return QMetaMethodPrivate::get(this)->name();
2060}
2061
2073 {
2074 return returnMetaType().id();
2075}
2076
2084{
2086 return QMetaType{};
2087 auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset()]);
2088 if (mt.id() == QMetaType::UnknownType)
2089 return QMetaType(QMetaMethodPrivate::get(this)->returnType());
2090 else
2091 return mt;
2092}
2093
2102{
2103 if (!mobj)
2104 return 0;
2105 return QMetaMethodPrivate::get(this)->parameterCount();
2106}
2107
2119{
2120 return parameterMetaType(index).id();
2121}
2122
2134{
2135 if (!mobj || index < 0)
2136 return {};
2137 auto priv = QMetaMethodPrivate::get(this);
2138 if (index >= priv->parameterCount())
2139 return {};
2140 // + 1 if there exists a return type
2141 auto parameterOffset = index + (methodType() == QMetaMethod::Constructor ? 0 : 1);
2142 auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset() + parameterOffset]);
2143 if (mt.id() == QMetaType::UnknownType)
2144 return QMetaType(QMetaMethodPrivate::get(this)->parameterType(index));
2145 else
2146 return mt;
2147}
2148
2159{
2160 if (!mobj)
2161 return;
2162 QMetaMethodPrivate::get(this)->getParameterTypes(types);
2163}
2164
2171{
2172 if (!mobj)
2173 return QList<QByteArray>();
2174 return QMetaMethodPrivate::get(this)->parameterTypes();
2175}
2176
2185{
2186 if (!mobj || index < 0 || index >= parameterCount())
2187 return {};
2188 return QMetaMethodPrivate::get(this)->parameterTypeName(index);
2189}
2190
2197{
2198 if (!mobj)
2199 return QList<QByteArray>();
2200 return QMetaMethodPrivate::get(this)->parameterNames();
2201}
2202
2203
2209const char *QMetaMethod::typeName() const
2210{
2211 if (!mobj)
2212 return nullptr;
2213 return QMetaMethodPrivate::get(this)->rawReturnTypeName();
2214}
2215
2241const char *QMetaMethod::tag() const
2242{
2243 if (!mobj)
2244 return nullptr;
2245 return QMetaMethodPrivate::get(this)->tag().constData();
2246}
2247
2248
2253{
2254 if (!mobj)
2255 return false;
2256 return data.flags() >> 4;
2257}
2258
2265{
2266 if (!mobj)
2267 return -1;
2268 return QMetaMethodPrivate::get(this)->ownMethodIndex() + mobj->methodOffset();
2269}
2270
2277{
2278 if (!mobj)
2279 return -1;
2280 return QMetaMethodPrivate::get(this)->ownMethodIndex();
2281}
2282
2283// This method has been around for a while, but the documentation was marked \internal until 5.1
2290{
2291 if (!mobj)
2292 return 0;
2293 if (data.flags() & MethodRevisioned) {
2294 int offset = priv(mobj->d.data)->methodData
2296 + QMetaMethodPrivate::get(this)->ownMethodIndex();
2297 return mobj->d.data[offset];
2298 }
2299 return 0;
2300}
2301
2311{
2312 if (!mobj)
2313 return false;
2315 return false;
2316 return data.flags() & MethodIsConst;
2317}
2318
2330{
2331 if (!mobj)
2332 return Private;
2333 return (QMetaMethod::Access)(data.flags() & AccessMask);
2334}
2335
2342{
2343 if (!mobj)
2344 return QMetaMethod::Method;
2345 return (QMetaMethod::MethodType)((data.flags() & MethodTypeMask)>>2);
2346}
2347
2368QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **signal)
2369{
2370 int i = -1;
2371 void *args[] = { &i, signal };
2372 for (const QMetaObject *m = metaObject; m; m = m->d.superdata) {
2373 m->static_metacall(QMetaObject::IndexOfMethod, 0, args);
2374 if (i >= 0)
2375 return QMetaMethod::fromRelativeMethodIndex(m, i);
2376 }
2377 return QMetaMethod();
2378}
2379
2492 Qt::ConnectionType connectionType,
2493 QGenericReturnArgument returnValue,
2494 QGenericArgument val0,
2495 QGenericArgument val1,
2496 QGenericArgument val2,
2497 QGenericArgument val3,
2498 QGenericArgument val4,
2499 QGenericArgument val5,
2500 QGenericArgument val6,
2501 QGenericArgument val7,
2502 QGenericArgument val8,
2503 QGenericArgument val9) const
2504{
2505 if (!object || !mobj)
2506 return false;
2507
2508 // check argument count (we don't allow invoking a method if given too few arguments)
2509 const char *typeNames[] = {
2510 returnValue.name(),
2511 val0.name(),
2512 val1.name(),
2513 val2.name(),
2514 val3.name(),
2515 val4.name(),
2516 val5.name(),
2517 val6.name(),
2518 val7.name(),
2519 val8.name(),
2520 val9.name()
2521 };
2522 void *param[] = {
2523 returnValue.data(),
2524 val0.data(),
2525 val1.data(),
2526 val2.data(),
2527 val3.data(),
2528 val4.data(),
2529 val5.data(),
2530 val6.data(),
2531 val7.data(),
2532 val8.data(),
2533 val9.data()
2534 };
2535
2536 int paramCount;
2537 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
2538 if (qstrlen(typeNames[paramCount]) <= 0)
2539 break;
2540 }
2541 return invokeImpl(*this, object, connectionType, paramCount, param, typeNames, nullptr);
2542}
2543
2544bool QMetaMethod::invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType connectionType,
2545 qsizetype paramCount, const void *const *parameters,
2546 const char *const *typeNames,
2547 const QtPrivate::QMetaTypeInterface *const *metaTypes)
2548{
2549 if (!target || !self.mobj)
2550 return false;
2551 QMetaMethodPrivate::InvokeFailReason r =
2552 QMetaMethodPrivate::invokeImpl(self, target, connectionType, paramCount, parameters,
2553 typeNames, metaTypes);
2554 if (Q_LIKELY(r == QMetaMethodPrivate::InvokeFailReason::None))
2555 return true;
2556
2557 if (int(r) >= int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch)) {
2558 int n = int(r) - int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch);
2559 qWarning("QMetaMethod::invoke: cannot convert formal parameter %d from %s in call to %s::%s",
2560 n, typeNames[n + 1] ? typeNames[n + 1] : metaTypes[n + 1]->name,
2561 self.mobj->className(), self.methodSignature().constData());
2562 }
2563 if (r == QMetaMethodPrivate::InvokeFailReason::TooFewArguments) {
2564 qWarning("QMetaMethod::invoke: too few arguments (%d) in call to %s::%s",
2565 int(paramCount), self.mobj->className(), self.methodSignature().constData());
2566 }
2567 return false;
2568}
2569
2571 Qt::ConnectionType connectionType,
2572 qsizetype paramCount, const void *const *parameters,
2573 const char *const *typeNames,
2574 const QtPrivate::QMetaTypeInterface *const *metaTypes) -> InvokeFailReason
2575{
2576 auto object = static_cast<QObject *>(target);
2577 auto priv = QMetaMethodPrivate::get(&self);
2578 constexpr bool MetaTypesAreOptional = QT_VERSION < QT_VERSION_CHECK(7, 0, 0);
2579 auto methodMetaTypes = priv->parameterMetaTypeInterfaces();
2580 auto param = const_cast<void **>(parameters);
2581
2582 Q_ASSERT(priv->mobj);
2583 Q_ASSERT(self.methodType() == Constructor || object);
2584 Q_ASSERT(self.methodType() == Constructor || connectionType == Qt::ConnectionType(-1) ||
2585 priv->mobj->cast(object));
2586 Q_ASSERT(paramCount >= 1); // includes the return type
2587 Q_ASSERT(parameters);
2588 Q_ASSERT(typeNames);
2589 Q_ASSERT(MetaTypesAreOptional || metaTypes);
2590
2591 if ((paramCount - 1) < qsizetype(priv->data.argc()))
2592 return InvokeFailReason::TooFewArguments;
2593
2594 // 0 is the return type, 1 is the first formal parameter
2595 auto checkTypesAreCompatible = [=](int idx) {
2596 uint typeInfo = priv->parameterTypeInfo(idx - 1);
2597 QLatin1StringView userTypeName(typeNames[idx] ? typeNames[idx] : metaTypes[idx]->name);
2598
2599 if ((typeInfo & IsUnresolvedType) == 0) {
2600 // this is a built-in type
2601 if (MetaTypesAreOptional && !metaTypes)
2602 return int(typeInfo) == QMetaType::fromName(userTypeName).id();
2603 return int(typeInfo) == metaTypes[idx]->typeId;
2604 }
2605
2606 QLatin1StringView methodTypeName = stringDataView(priv->mobj, typeInfo & TypeNameIndexMask);
2607 if ((MetaTypesAreOptional && !metaTypes) || !metaTypes[idx]) {
2608 // compatibility call, compare strings
2609 if (methodTypeName == userTypeName)
2610 return true;
2611
2612 // maybe the user type needs normalization
2613 QByteArray normalized = normalizeTypeInternal(userTypeName.begin(), userTypeName.end());
2614 return methodTypeName == QLatin1StringView(normalized);
2615 }
2616
2617 QMetaType userType(metaTypes[idx]);
2618 Q_ASSERT(userType.isValid());
2619 if (QMetaType(methodMetaTypes[idx - 1]) == userType)
2620 return true;
2621
2622 // if the parameter type was NOT only forward-declared, it MUST have
2623 // matched
2624 if (methodMetaTypes[idx - 1])
2625 return false;
2626
2627 // resolve from the name moc stored for us
2628 QMetaType resolved = QMetaType::fromName(methodTypeName);
2629 return resolved == userType;
2630 };
2631
2632 // force all types to be registered, just in case
2633 for (qsizetype i = 0; metaTypes && i < paramCount; ++i)
2634 QMetaType(metaTypes[i]).registerType();
2635
2636 // check formal parameters first (overload set)
2637 for (qsizetype i = 1; i < paramCount; ++i) {
2638 if (!checkTypesAreCompatible(i))
2639 return InvokeFailReason(int(InvokeFailReason::FormalParameterMismatch) + i - 1);
2640 }
2641
2642 // handle constructors first
2643 if (self.methodType() == Constructor) {
2644 if (object) {
2645 qWarning("QMetaMethod::invokeMethod: cannot call constructor %s on object %p",
2646 self.methodSignature().constData(), object);
2647 return InvokeFailReason::ConstructorCallOnObject;
2648 }
2649
2650 if (!parameters[0]) {
2651 qWarning("QMetaMethod::invokeMethod: constructor call to %s must assign a return type",
2652 self.methodSignature().constData());
2653 return InvokeFailReason::ConstructorCallWithoutResult;
2654 }
2655
2656 if (!MetaTypesAreOptional || metaTypes) {
2657 if (metaTypes[0]->typeId != QMetaType::QObjectStar) {
2658 qWarning("QMetaMethod::invokeMethod: cannot convert QObject* to %s on constructor call %s",
2659 metaTypes[0]->name, self.methodSignature().constData());
2660 return InvokeFailReason::ReturnTypeMismatch;
2661 }
2662 }
2663
2664 int idx = priv->ownConstructorMethodIndex();
2665 if (priv->mobj->static_metacall(QMetaObject::CreateInstance, idx, param) >= 0)
2666 return InvokeFailReason::ConstructorCallFailed;
2667 return {};
2668 }
2669
2670 // regular type - check return type
2671 if (parameters[0]) {
2672 if (!checkTypesAreCompatible(0)) {
2673 const char *retType = typeNames[0] ? typeNames[0] : metaTypes[0]->name;
2674 qWarning("QMetaMethod::invokeMethod: return type mismatch for method %s::%s:"
2675 " cannot convert from %s to %s during invocation",
2676 priv->mobj->className(), priv->methodSignature().constData(),
2677 priv->rawReturnTypeName(), retType);
2678 return InvokeFailReason::ReturnTypeMismatch;
2679 }
2680 }
2681
2682 Qt::HANDLE currentThreadId = nullptr;
2683 QThread *objectThread = nullptr;
2684 auto receiverInSameThread = [&]() {
2685 if (!currentThreadId) {
2686 currentThreadId = QThread::currentThreadId();
2687 objectThread = object->thread();
2688 }
2689 if (objectThread)
2690 return currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
2691 return false;
2692 };
2693
2694 // check connection type
2695 if (connectionType == Qt::AutoConnection)
2696 connectionType = receiverInSameThread() ? Qt::DirectConnection : Qt::QueuedConnection;
2697 else if (connectionType == Qt::ConnectionType(-1))
2698 connectionType = Qt::DirectConnection;
2699
2700#if !QT_CONFIG(thread)
2701 if (connectionType == Qt::BlockingQueuedConnection) {
2702 connectionType = Qt::DirectConnection;
2703 }
2704#endif
2705
2706 // invoke!
2707 int idx_relative = priv->ownMethodIndex();
2708 int idx_offset = priv->mobj->methodOffset();
2709 QObjectPrivate::StaticMetaCallFunction callFunction = priv->mobj->d.static_metacall;
2710
2711 if (connectionType == Qt::DirectConnection) {
2712 if (callFunction)
2713 callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
2714 else if (QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, idx_relative + idx_offset, param) >= 0)
2715 return InvokeFailReason::CallViaVirtualFailed;
2716 } else if (connectionType == Qt::QueuedConnection) {
2717 if (parameters[0]) {
2718 qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
2719 "queued connections");
2720 return InvokeFailReason::CouldNotQueueParameter;
2721 }
2722
2723 auto event = std::make_unique<QMetaCallEvent>(idx_offset, idx_relative, callFunction, nullptr, -1, paramCount);
2724 QMetaType *types = event->types();
2725 void **args = event->args();
2726
2727 // fill in the meta types first
2728 for (int i = 1; i < paramCount; ++i) {
2729 types[i] = QMetaType(methodMetaTypes[i - 1]);
2730 if (!types[i].iface() && (!MetaTypesAreOptional || metaTypes))
2731 types[i] = QMetaType(metaTypes[i]);
2732 if (!types[i].iface())
2733 types[i] = priv->parameterMetaType(i - 1);
2734 if (!types[i].iface() && typeNames[i])
2735 types[i] = QMetaType::fromName(typeNames[i]);
2736 if (!types[i].iface()) {
2737 qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
2738 typeNames[i]);
2739 return InvokeFailReason(int(InvokeFailReason::CouldNotQueueParameter) - i);
2740 }
2741 }
2742
2743 // now create copies of our parameters using those meta types
2744 for (int i = 1; i < paramCount; ++i)
2745 args[i] = types[i].create(parameters[i]);
2746
2747 QCoreApplication::postEvent(object, event.release());
2748 } else { // blocking queued connection
2749#if QT_CONFIG(thread)
2750 if (receiverInSameThread()) {
2751 qWarning("QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: "
2752 "Receiver is %s(%p)", priv->mobj->className(), object);
2753 return InvokeFailReason::DeadLockDetected;
2754 }
2755
2756 QSemaphore semaphore;
2757 QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
2758 nullptr, -1, param, &semaphore));
2759 semaphore.acquire();
2760#endif // QT_CONFIG(thread)
2761 }
2762 return {};
2763}
2764
2869 QGenericReturnArgument returnValue,
2870 QGenericArgument val0,
2871 QGenericArgument val1,
2872 QGenericArgument val2,
2873 QGenericArgument val3,
2874 QGenericArgument val4,
2875 QGenericArgument val5,
2876 QGenericArgument val6,
2877 QGenericArgument val7,
2878 QGenericArgument val8,
2879 QGenericArgument val9) const
2880{
2881 if (!gadget || !mobj)
2882 return false;
2883
2884 // check return type
2885 if (returnValue.data()) {
2886 const char *retType = typeName();
2887 if (qstrcmp(returnValue.name(), retType) != 0) {
2888 // normalize the return value as well
2890 if (qstrcmp(normalized.constData(), retType) != 0) {
2891 // String comparison failed, try compare the metatype.
2892 int t = returnType();
2894 return false;
2895 }
2896 }
2897 }
2898
2899 // check argument count (we don't allow invoking a method if given too few arguments)
2900 const char *typeNames[] = {
2901 returnValue.name(),
2902 val0.name(),
2903 val1.name(),
2904 val2.name(),
2905 val3.name(),
2906 val4.name(),
2907 val5.name(),
2908 val6.name(),
2909 val7.name(),
2910 val8.name(),
2911 val9.name()
2912 };
2913 int paramCount;
2914 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
2915 if (qstrlen(typeNames[paramCount]) <= 0)
2916 break;
2917 }
2918 if (paramCount <= QMetaMethodPrivate::get(this)->parameterCount())
2919 return false;
2920
2921 // invoke!
2922 void *param[] = {
2923 returnValue.data(),
2924 val0.data(),
2925 val1.data(),
2926 val2.data(),
2927 val3.data(),
2928 val4.data(),
2929 val5.data(),
2930 val6.data(),
2931 val7.data(),
2932 val8.data(),
2933 val9.data()
2934 };
2935 int idx_relative = QMetaMethodPrivate::get(this)->ownMethodIndex();
2938 if (!callFunction)
2939 return false;
2940 callFunction(reinterpret_cast<QObject*>(gadget), QMetaObject::InvokeMetaMethod, idx_relative, param);
2941 return true;
2942}
2943
3017const char *QMetaEnum::name() const
3018{
3019 if (!mobj)
3020 return nullptr;
3021 return rawStringData(mobj, data.name());
3022}
3023
3036const char *QMetaEnum::enumName() const
3037{
3038 if (!mobj)
3039 return nullptr;
3040 return rawStringData(mobj, data.alias());
3041}
3042
3057{
3058 if (!mobj)
3059 return {};
3060
3061 const QMetaObjectPrivate *p = priv(mobj->d.data);
3062#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
3063 if (p->revision < 12)
3064 QMetaType();
3065#endif
3066
3067 return QMetaType(mobj->d.metaTypes[data.index(mobj) + p->propertyCount]);
3068}
3069
3076{
3077 if (!mobj)
3078 return 0;
3079 return data.keyCount();
3080}
3081
3087const char *QMetaEnum::key(int index) const
3088{
3089 if (!mobj)
3090 return nullptr;
3091 if (index >= 0 && index < int(data.keyCount()))
3092 return rawStringData(mobj, mobj->d.data[data.data() + 2*index]);
3093 return nullptr;
3094}
3095
3103{
3104 if (!mobj)
3105 return 0;
3106 if (index >= 0 && index < int(data.keyCount()))
3107 return mobj->d.data[data.data() + 2 * index + 1];
3108 return -1;
3109}
3110
3121{
3122 if (!mobj)
3123 return false;
3124 return data.flags() & EnumIsFlag;
3125}
3126
3134{
3135 if (!mobj)
3136 return false;
3137 return data.flags() & EnumIsScoped;
3138}
3139
3148const char *QMetaEnum::scope() const
3149{
3150 return mobj ? objectClassName(mobj) : nullptr;
3151}
3152
3164int QMetaEnum::keyToValue(const char *key, bool *ok) const
3165{
3166 if (ok != nullptr)
3167 *ok = false;
3168 if (!mobj || !key)
3169 return -1;
3170 uint scope = 0;
3171 const char *qualified_key = key;
3172 const char *s = key + qstrlen(key);
3173 while (s > key && *s != ':')
3174 --s;
3175 if (s > key && *(s - 1) == ':') {
3176 scope = s - key - 1;
3177 key += scope + 2;
3178 }
3179 for (int i = 0; i < int(data.keyCount()); ++i) {
3180 const QByteArray className = stringData(mobj, priv(mobj->d.data)->className);
3181 if ((!scope || (className.size() == int(scope) && strncmp(qualified_key, className.constData(), scope) == 0))
3182 && strcmp(key, rawStringData(mobj, mobj->d.data[data.data() + 2*i])) == 0) {
3183 if (ok != nullptr)
3184 *ok = true;
3185 return mobj->d.data[data.data() + 2 * i + 1];
3186 }
3187 }
3188 return -1;
3189}
3190
3199const char *QMetaEnum::valueToKey(int value) const
3200{
3201 if (!mobj)
3202 return nullptr;
3203 for (int i = 0; i < int(data.keyCount()); ++i)
3204 if (value == (int)mobj->d.data[data.data() + 2 * i + 1])
3205 return rawStringData(mobj, mobj->d.data[data.data() + 2 * i]);
3206 return nullptr;
3207}
3208
3209static auto parse_scope(QLatin1StringView qualifiedKey) noexcept
3210{
3211 struct R {
3212 std::optional<QLatin1StringView> scope;
3214 };
3215 const auto scopePos = qualifiedKey.lastIndexOf("::"_L1);
3216 if (scopePos < 0)
3217 return R{std::nullopt, qualifiedKey};
3218 else
3219 return R{qualifiedKey.first(scopePos), qualifiedKey.sliced(scopePos + 2)};
3220}
3221
3232int QMetaEnum::keysToValue(const char *keys, bool *ok) const
3233{
3234 if (ok != nullptr)
3235 *ok = false;
3236 if (!mobj || !keys)
3237 return -1;
3238
3239 auto lookup = [&] (QLatin1StringView key) -> std::optional<int> {
3240 for (int i = data.keyCount() - 1; i >= 0; --i) {
3241 if (key == stringDataView(mobj, mobj->d.data[data.data() + 2*i]))
3242 return mobj->d.data[data.data() + 2*i + 1];
3243 }
3244 return std::nullopt;
3245 };
3246 auto className = [&] { return stringDataView(mobj, priv(mobj->d.data)->className); };
3247
3248 int value = 0;
3249 for (const QLatin1StringView &untrimmed : qTokenize(QLatin1StringView{keys}, u'|')) {
3250 const auto parsed = parse_scope(untrimmed.trimmed());
3251 if (parsed.scope && *parsed.scope != className())
3252 return -1; // wrong type name in qualified name
3253 if (auto thisValue = lookup(parsed.key))
3254 value |= *thisValue;
3255 else
3256 return -1; // no such enumerator
3257 }
3258 if (ok != nullptr)
3259 *ok = true;
3260 return value;
3261}
3262
3263namespace
3264{
3265template <typename String, typename Container, typename Separator>
3266void join_reversed(String &s, const Container &c, Separator sep)
3267{
3268 if (c.empty())
3269 return;
3270 qsizetype len = qsizetype(c.size()) - 1; // N - 1 separators
3271 for (auto &e : c)
3272 len += qsizetype(e.size()); // N parts
3273 s.reserve(len);
3274 bool first = true;
3275 for (auto rit = c.rbegin(), rend = c.rend(); rit != rend; ++rit) {
3276 const auto &e = *rit;
3277 if (!first)
3278 s.append(sep);
3279 first = false;
3280 s.append(e.data(), e.size());
3281 }
3282}
3283} // unnamed namespace
3284
3292{
3294 if (!mobj)
3295 return keys;
3296 QVarLengthArray<QLatin1StringView, sizeof(int) * CHAR_BIT> parts;
3297 int v = value;
3298 // reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
3299 for (int i = data.keyCount() - 1; i >= 0; --i) {
3300 int k = mobj->d.data[data.data() + 2 * i + 1];
3301 if ((k != 0 && (v & k) == k) || (k == value)) {
3302 v = v & ~k;
3303 parts.push_back(stringDataView(mobj, mobj->d.data[data.data() + 2 * i]));
3304 }
3305 }
3306 join_reversed(keys, parts, '|');
3307 return keys;
3308}
3309
3313QMetaEnum::QMetaEnum(const QMetaObject *mobj, int index)
3314 : mobj(mobj), data({ mobj->d.data + priv(mobj->d.data)->enumeratorData + index * Data::Size })
3315{
3316 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->enumeratorCount);
3317}
3318
3319int QMetaEnum::Data::index(const QMetaObject *mobj) const
3320{
3321 return (d - mobj->d.data - priv(mobj->d.data)->enumeratorData) / Size;
3322}
3323
3392const char *QMetaProperty::name() const
3393{
3394 if (!mobj)
3395 return nullptr;
3396 return rawStringData(mobj, data.name());
3397}
3398
3404const char *QMetaProperty::typeName() const
3405{
3406 if (!mobj)
3407 return nullptr;
3408 // TODO: can the metatype be invalid for dynamic metaobjects?
3409 if (const auto mt = metaType(); mt.isValid())
3410 return mt.name();
3411 return rawTypeNameFromTypeInfo(mobj, data.type());
3412}
3413
3451{
3452 if (!mobj)
3453 return {};
3454 return QMetaType(mobj->d.metaTypes[data.index(mobj)]);
3455}
3456
3457int QMetaProperty::Data::index(const QMetaObject *mobj) const
3458{
3459 return (d - mobj->d.data - priv(mobj->d.data)->propertyData) / Size;
3460}
3461
3468{
3469 if (!mobj)
3470 return -1;
3471 return data.index(mobj) + mobj->propertyOffset();
3472}
3473
3480{
3481 if (!mobj)
3482 return -1;
3483 return data.index(mobj);
3484}
3485
3497{
3498 return isEnumType() && menum.isFlag();
3499}
3500
3508{
3509 if (!mobj)
3510 return false;
3511 return (data.flags() & EnumOrFlag) && menum.name();
3512}
3513
3524{
3525 if (!mobj)
3526 return false;
3527 return (data.flags() & StdCppSet);
3528}
3529
3538{
3539 if (!mobj)
3540 return false;
3541 return (data.flags() & Alias);
3542}
3543
3544#if QT_DEPRECATED_SINCE(6, 4)
3553int QMetaProperty::registerPropertyType() const
3554{
3555 return typeId();
3556}
3557#endif
3558
3560 : mobj(mobj),
3561 data(getMetaPropertyData(mobj, index))
3562{
3563 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->propertyCount);
3564
3565 if (!(data.flags() & EnumOrFlag))
3566 return;
3567 const char *type = rawTypeNameFromTypeInfo(mobj, data.type());
3568 menum = mobj->enumerator(mobj->indexOfEnumerator(type));
3569 if (menum.isValid())
3570 return;
3571 const char *enum_name = type;
3572 const char *scope_name = objectClassName(mobj);
3573 char *scope_buffer = nullptr;
3574
3575 const char *colon = strrchr(enum_name, ':');
3576 // ':' will always appear in pairs
3577 Q_ASSERT(colon <= enum_name || *(colon - 1) == ':');
3578 if (colon > enum_name) {
3579 int len = colon - enum_name - 1;
3580 scope_buffer = (char *)malloc(len + 1);
3581 memcpy(scope_buffer, enum_name, len);
3582 scope_buffer[len] = '\0';
3583 scope_name = scope_buffer;
3584 enum_name = colon + 1;
3585 }
3586
3587 const QMetaObject *scope = nullptr;
3588 if (qstrcmp(scope_name, "Qt") == 0)
3589 scope = &Qt::staticMetaObject;
3590 else
3591 scope = QMetaObject_findMetaObject(mobj, scope_name);
3592 if (scope)
3593 menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
3594 if (scope_buffer)
3595 free(scope_buffer);
3596}
3597
3602QMetaProperty::Data QMetaProperty::getMetaPropertyData(const QMetaObject *mobj, int index)
3603{
3604 return { mobj->d.data + priv(mobj->d.data)->propertyData + index * Data::Size };
3605}
3606
3614{
3615 return menum;
3616}
3617
3625{
3626 if (!object || !mobj)
3627 return QVariant();
3628
3629 // the status variable is changed by qt_metacall to indicate what it did
3630 // this feature is currently only used by Qt D-Bus and should not be depended
3631 // upon. Don't change it without looking into QDBusAbstractInterface first
3632 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
3633 // changed: result stored directly in value
3634 int status = -1;
3636 void *argv[] = { nullptr, &value, &status };
3637 QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
3638 if (t == QMetaType::fromType<QVariant>()) {
3639 argv[0] = &value;
3640 } else {
3641 value = QVariant(t, nullptr);
3642 argv[0] = value.data();
3643 }
3645 mobj->d.static_metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty, data.index(mobj), argv);
3646 } else {
3648 data.index(mobj) + mobj->propertyOffset(), argv);
3649 }
3650
3651 if (status != -1)
3652 return value;
3653 if (t != QMetaType::fromType<QVariant>() && argv[0] != value.data())
3654 // pointer or reference
3655 return QVariant(t, argv[0]);
3656 return value;
3657}
3658
3673bool QMetaProperty::write(QObject *object, const QVariant &value) const
3674{
3675 if (!object || !isWritable())
3676 return false;
3677 return write(object, QVariant(value));
3678}
3679
3685{
3686 if (!object || !isWritable())
3687 return false;
3688 QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
3689 if (t != QMetaType::fromType<QVariant>() && t != v.metaType()) {
3690 if (isEnumType() && !t.metaObject() && v.metaType().id() == QMetaType::QString) {
3691 // Assigning a string to a property of type Q_ENUMS (instead of Q_ENUM)
3692 bool ok;
3693 if (isFlagType())
3694 v = QVariant(menum.keysToValue(v.toByteArray(), &ok));
3695 else
3696 v = QVariant(menum.keyToValue(v.toByteArray(), &ok));
3697 if (!ok)
3698 return false;
3699 } else if (!v.isValid()) {
3700 if (isResettable())
3701 return reset(object);
3702 v = QVariant(t, nullptr);
3703 } else if (!v.convert(t)) {
3704 return false;
3705 }
3706 }
3707 // the status variable is changed by qt_metacall to indicate what it did
3708 // this feature is currently only used by Qt D-Bus and should not be depended
3709 // upon. Don't change it without looking into QDBusAbstractInterface first
3710 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
3711 // changed: result stored directly in value, return the value of status
3712 int status = -1;
3713 // the flags variable is used by the declarative module to implement
3714 // interception of property writes.
3715 int flags = 0;
3716 void *argv[] = { nullptr, &v, &status, &flags };
3717 if (t == QMetaType::fromType<QVariant>())
3718 argv[0] = &v;
3719 else
3720 argv[0] = v.data();
3722 mobj->d.static_metacall(object, QMetaObject::WriteProperty, data.index(mobj), argv);
3723 else
3724 QMetaObject::metacall(object, QMetaObject::WriteProperty, data.index(mobj) + mobj->propertyOffset(), argv);
3725
3726 return status;
3727}
3728
3738{
3739 if (!object || !mobj || !isResettable())
3740 return false;
3741 void *argv[] = { nullptr };
3743 mobj->d.static_metacall(object, QMetaObject::ResetProperty, data.index(mobj), argv);
3744 else
3745 QMetaObject::metacall(object, QMetaObject::ResetProperty, data.index(mobj) + mobj->propertyOffset(), argv);
3746 return true;
3747}
3748
3759{
3761 void * argv[1] { &bindable };
3762 mobj->metacall(object, QMetaObject::BindableProperty, data.index(mobj) + mobj->propertyOffset(), argv);
3763 return bindable;
3764}
3773QVariant QMetaProperty::readOnGadget(const void *gadget) const
3774{
3776 return read(reinterpret_cast<const QObject*>(gadget));
3777}
3778
3787bool QMetaProperty::writeOnGadget(void *gadget, const QVariant &value) const
3788{
3790 return write(reinterpret_cast<QObject*>(gadget), value);
3791}
3792
3798{
3800 return write(reinterpret_cast<QObject*>(gadget), std::move(value));
3801}
3802
3813bool QMetaProperty::resetOnGadget(void *gadget) const
3814{
3816 return reset(reinterpret_cast<QObject*>(gadget));
3817}
3818
3826{
3827 if (!mobj)
3828 return false;
3829 return data.flags() & Resettable;
3830}
3831
3838{
3839 if (!mobj)
3840 return false;
3841 return data.flags() & Readable;
3842}
3843
3851{
3852 if (!mobj)
3853 return false;
3854 return data.notifyIndex() != uint(-1);
3855}
3856
3866{
3867 int id = notifySignalIndex();
3868 if (id != -1)
3869 return mobj->method(id);
3870 else
3871 return QMetaMethod();
3872}
3873
3883{
3884 if (!mobj || data.notifyIndex() == std::numeric_limits<uint>::max())
3885 return -1;
3886 uint methodIndex = data.notifyIndex();
3887 if (methodIndex & IsUnresolvedSignal) {
3888 methodIndex &= ~IsUnresolvedSignal;
3889 const QByteArray signalName = stringData(mobj, methodIndex);
3890 const QMetaObject *m = mobj;
3891 const int idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(&m, signalName, 0, nullptr);
3892 if (idx >= 0) {
3893 return idx + m->methodOffset();
3894 } else {
3895 qWarning("QMetaProperty::notifySignal: cannot find the NOTIFY signal %s in class %s for property '%s'",
3896 signalName.constData(), objectClassName(mobj), name());
3897 return -1;
3898 }
3899 }
3900 return methodIndex + mobj->methodOffset();
3901}
3902
3903// This method has been around for a while, but the documentation was marked \internal until 5.1
3911{
3912 if (!mobj)
3913 return 0;
3914 return data.revision();
3915}
3916
3924{
3925 if (!mobj)
3926 return false;
3927 return data.flags() & Writable;
3928}
3929
3937{
3938 if (!mobj)
3939 return false;
3940 return data.flags() & Designable;
3941}
3942
3950{
3951 if (!mobj)
3952 return false;
3953 return data.flags() & Scriptable;
3954}
3955
3967{
3968 if (!mobj)
3969 return false;
3970 return data.flags() & Stored;
3971}
3972
3982{
3983 if (!mobj)
3984 return false;
3985 return data.flags() & User;
3986}
3987
3996{
3997 if (!mobj)
3998 return false;
3999 return data.flags() & Constant;
4000}
4001
4010{
4011 if (!mobj)
4012 return false;
4013 return data.flags() & Final;
4014}
4015
4024{
4025 if (!mobj)
4026 return false;
4027 return data.flags() & Required;
4028}
4029
4040{
4041 if (!mobj)
4042 return false;
4043 return (data.flags() & Bindable);
4044}
4045
4082const char *QMetaClassInfo::name() const
4083{
4084 if (!mobj)
4085 return nullptr;
4086 return rawStringData(mobj, data.name());
4087}
4088
4094const char *QMetaClassInfo::value() const
4095{
4096 if (!mobj)
4097 return nullptr;
4098 return rawStringData(mobj, data.value());
4099}
4100
4195int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
4196{
4197 Q_ASSERT(local_method_index < get(mobj)->methodCount);
4198 while (QMetaMethod::fromRelativeMethodIndex(mobj, local_method_index).data.flags() & MethodCloned) {
4199 Q_ASSERT(local_method_index > 0);
4200 --local_method_index;
4201 }
4202 return local_method_index;
4203}
4204
4211{
4213 while (*signature && *signature != '(')
4214 ++signature;
4215 while (*signature && *signature != ')' && *++signature != ')') {
4216 const char *begin = signature;
4217 int level = 0;
4218 while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
4219 if (*signature == '<')
4220 ++level;
4221 else if (*signature == '>')
4222 --level;
4223 ++signature;
4224 }
4225 list += QByteArray(begin, signature - begin);
4226 }
4227 return list;
4228}
4229
Type loadRelaxed() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
QByteArray & prepend(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qbytearray.h:216
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
void chop(qsizetype n)
Removes n bytes from the end of the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:394
QByteArray & replace(qsizetype index, qsizetype len, const char *s, qsizetype alen)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qbytearray.h:275
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
\macro QMetaMethodArgument Q_ARG(Type, const Type &value)
\inmodule QtCore
constexpr const_iterator end() const noexcept
constexpr const_iterator begin() const noexcept
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void reserve(qsizetype size)
Definition qlist.h:746
\inmodule QtCore
const char * name() const
Returns the name of this item.
const char * value() const
Returns the value of this item.
\inmodule QtCore
const char * valueToKey(int value) const
Returns the string that is used as the name of the given enumeration value, or \nullptr if value is n...
int value(int index) const
Returns the value with the given index; or returns -1 if there is no such value.
bool isFlag() const
Returns true if this enumerator is used as a flag; otherwise returns false.
const char * name() const
Returns the name of the type (without the scope).
int keysToValue(const char *keys, bool *ok=nullptr) const
Returns the value derived from combining together the values of the keys using the OR operator,...
const char * key(int index) const
Returns the key with the given index, or \nullptr if no such key exists.
constexpr QMetaEnum()
QByteArray valueToKeys(int value) const
Returns a byte array of '|'-separated keys that represents the given value.
int keyCount() const
Returns the number of keys.
QMetaType metaType() const
Returns the meta type of the enum.
bool isScoped() const
int keyToValue(const char *key, bool *ok=nullptr) const
Returns the integer value of the given enumeration key, or -1 if key is not defined.
const char * enumName() const
Returns the enum name of the flag (without the scope).
const char * scope() const
Returns the scope this enumerator was declared in.
bool isValid() const
Returns true if this enum is valid (has a name); otherwise returns false.
static InvokeFailReason Q_CORE_EXPORT invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType, qsizetype paramCount, const void *const *parameters, const char *const *typeNames, const QtPrivate::QMetaTypeInterface *const *metaTypes)
\inmodule QtCore
Definition qmetaobject.h:18
int relativeMethodIndex() const
bool isConst() const
Access
This enum describes the access level of a method, following the conventions used in C++.
Definition qmetaobject.h:35
bool invoke(QObject *object, Qt::ConnectionType connectionType, QGenericReturnArgument returnValue, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument()) const
\obsolete [6.5] Please use the variadic overload of this function
QByteArray signature() const
\macro Q_METAMETHOD_INVOKE_MAX_ARGS
const QMetaObject * mobj
Access access() const
Returns the access specification of this method (private, protected, or public).
const char * typeName() const
Returns the return type name of this method.
int parameterCount() const
QMetaType returnMetaType() const
int methodIndex() const
MethodType
\value Method The function is a plain member function.
Definition qmetaobject.h:37
bool invokeOnGadget(void *gadget, QGenericReturnArgument returnValue, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument()) const
int parameterType(int index) const
int returnType() const
QList< QByteArray > parameterTypes() const
Returns a list of parameter types.
const char * tag() const
Returns the tag associated with this method.
constexpr QMetaMethod()
Definition qmetaobject.h:20
int revision() const
int attributes() const
void getParameterTypes(int *types) const
QByteArray methodSignature() const
MethodType methodType() const
Returns the type of this method (signal, slot, or method).
QMetaType parameterMetaType(int index) const
QByteArray name() const
QByteArray parameterTypeName(int index) const
QList< QByteArray > parameterNames() const
Returns a list of parameter names.
\inmodule QtCore
bool hasStdCppSet() const
int revision() const
QVariant readOnGadget(const void *gadget) const
bool isUser() const
Returns false if the {Q_PROPERTY()}'s USER attribute is false.
const char * typeName() const
Returns the name of this property's type.
bool isStored() const
Returns true if the property is stored; otherwise returns false.
bool isScriptable() const
Returns false if the {Q_PROPERTY()}'s SCRIPTABLE attribute is false; otherwise returns true.
bool writeOnGadget(void *gadget, const QVariant &value) const
bool isBindable() const
bool write(QObject *obj, const QVariant &value) const
Writes value as the property's value to the given object.
QMetaType metaType() const
QVariant read(const QObject *obj) const
Reads the property's value from the given object.
bool isDesignable() const
Returns false if the {Q_PROPERTY()}'s DESIGNABLE attribute is false; otherwise returns true.
QMetaMethod notifySignal() const
bool reset(QObject *obj) const
Resets the property for the given object with a reset method.
int typeId() const
bool isWritable() const
Returns true if this property is writable; otherwise returns false.
bool isConstant() const
bool isResettable() const
Returns true if this property can be reset to a default value; otherwise returns false.
QMetaEnum enumerator() const
Returns the enumerator if this property's type is an enumerator type; otherwise the returned value is...
bool isFinal() const
int notifySignalIndex() const
constexpr QMetaProperty()
bool isEnumType() const
Returns true if the property's type is an enumeration value; otherwise returns false.
bool isAlias() const
bool resetOnGadget(void *gadget) const
int propertyIndex() const
const char * name() const
Returns this property's name.
int relativePropertyIndex() const
bool isFlagType() const
Returns true if the property's type is an enumeration value that is used as a flag; otherwise returns...
bool isReadable() const
Returns true if this property is readable; otherwise returns false.
QUntypedBindable bindable(QObject *object) const
bool hasNotifySignal() const
Returns true if this property has a corresponding change notify signal; otherwise returns false.
bool isRequired() const
\inmodule QtCore
Definition qmetatype.h:320
const QtPrivate::QMetaTypeInterface * iface() const
Definition qmetatype.h:750
static QMetaType fromName(QByteArrayView name)
Returns a QMetaType matching typeName.
bool isValid() const
int id(int=0) const
Definition qmetatype.h:454
void registerType() const
Definition qmetatype.h:444
constexpr const char * name() const
Definition qmetatype.h:2650
void(* StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **)
Definition qobject_p.h:108
\inmodule QtCore
Definition qobject.h:90
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1561
\inmodule QtCore
Definition qsemaphore.h:16
void acquire(int n=1)
Tries to acquire n resources guarded by the semaphore.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition qstring.h:1101
QAtomicPointer< void > threadId
Definition qthread_p.h:323
static QThreadData * get2(QThread *thread)
Definition qthread_p.h:290
static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION
Definition qthread.h:154
\inmodule QtCore
Definition qproperty.h:677
constexpr size_type size() const noexcept
void resize(qsizetype sz)
void append(const T &t)
const T * constData() const
T * data() noexcept
\inmodule QtCore
Definition qvariant.h:64
QMTI_MUTABLE QBasicAtomicInt typeId
Definition qmetatype.h:260
void call(QObject *r, void **a)
QString str
[2]
double e
auto signal
auto mo
[7]
Combined button and popup list for selecting options.
constexpr QBindableInterface iface
Definition qproperty.h:664
void * HANDLE
ConnectionType
@ AutoConnection
@ BlockingQueuedConnection
@ QueuedConnection
@ DirectConnection
QString self
Definition language.cpp:57
size_t qstrlen(const char *str)
Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2)
#define QT_WARNING_POP
#define Q_LIKELY(x)
#define Q_DECL_COLD_FUNCTION
#define QT_WARNING_DISABLE_GCC(text)
#define QT_WARNING_PUSH
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
static QDBusError::ErrorType get(const char *name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Size(name)
#define qWarning
Definition qlogging.h:162
return ret
static QLatin1StringView stringDataView(const QMetaObject *mo, int index)
static QByteArray stringData(const QMetaObject *mo, int index)
static void argumentTypesFromString(const char *str, const char *end, QArgumentTypeArray &types)
static auto parse_scope(QLatin1StringView qualifiedKey) noexcept
static char * qNormalizeType(char *d, int &templdepth, QByteArray &result)
static const QMetaObject * QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
static Q_DECL_COLD_FUNCTION bool printMethodNotFoundWarning(const QMetaObject *meta, QLatin1StringView name, qsizetype paramCount, const char *const *names, const QtPrivate::QMetaTypeInterface *const *metaTypes)
static const char * rawStringData(const QMetaObject *mo, int index)
static int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo)
static const char * objectClassName(const QMetaObject *m)
static const char * rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
static const QMetaObjectPrivate * priv(const uint *data)
static QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
@ MaximumParamCount
#define ASSERT_NOT_PRIMITIVE_TYPE(TYPE, METATYPEID, NAME)
static void qRemoveWhitespace(const char *s, char *d)
@ DynamicMetaObject
@ PropertyAccessInStaticMetaCall
static bool is_ident_char(char s)
static bool is_space(char s)
@ MethodSignal
@ MethodSlot
@ MethodCloned
@ MethodTypeMask
@ MethodIsConst
@ AccessMask
@ MethodRevisioned
@ EnumIsScoped
@ EnumIsFlag
@ Readable
@ StdCppSet
@ Bindable
@ Alias
@ Stored
@ Designable
@ Resettable
@ Scriptable
@ Required
@ Constant
@ Final
@ EnumOrFlag
@ Writable
@ User
@ IsUnresolvedSignal
@ IsUnresolvedType
@ TypeNameIndexMask
#define QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F)
Definition qmetatype.h:47
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLenum GLuint GLint level
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLsizei GLenum GLenum * types
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLenum GLuint GLenum GLsizei length
GLuint object
[3]
GLenum type
GLenum target
GLbitfield flags
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLenum const GLint * param
GLenum GLuint GLintptr offset
GLenum GLuint GLsizei propCount
GLuint name
GLint first
GLfloat n
struct _cl_event * event
GLhandleARB obj
[2]
GLboolean reset
const GLubyte * c
GLuint GLuint * names
GLenum GLsizei len
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLint GLenum GLboolean normalized
Definition qopenglext.h:752
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
static constexpr QChar sep
constexpr auto qTokenize(Haystack &&h, Needle &&n, Flags...flags) noexcept(QtPrivate::Tok::is_nothrow_constructible_from< Haystack, Needle >::value) -> decltype(QtPrivate::Tok::TokenizerResult< Haystack, Needle >{std::forward< Haystack >(h), std::forward< Needle >(n), flags...})
#define s2
#define QT_VERSION_CHECK(major, minor, patch)
#define QT_VERSION
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned int uint
Definition qtypes.h:29
const char property[13]
Definition qwizard.cpp:101
const char className[16]
[1]
Definition qwizard.cpp:100
QList< int > list
[14]
QStringList keys
obj metaObject() -> className()
QQuickView * view
[0]
view create()
QJSValueList args
virtual int createProperty(const char *, const char *)
Definition qobject_p.h:464
static int signalOffset(const QMetaObject *m)
static int indexOfSlot(const QMetaObject *m, const QByteArray &name, int argc, const QArgumentType *types)
static QList< QByteArray > parameterTypeNamesFromSignature(const char *signature)
static int indexOfConstructor(const QMetaObject *m, const QByteArray &name, int argc, const QArgumentType *types)
static Q_CORE_EXPORT QMetaMethod firstMethod(const QMetaObject *baseObject, QByteArrayView name)
static Q_CORE_EXPORT QMetaMethod signal(const QMetaObject *m, int signal_index)
static int indexOfMethod(const QMetaObject *m, const QByteArray &name, int argc, const QArgumentType *types)
static QByteArray decodeMethodSignature(const char *signature, QArgumentTypeArray &types)
static bool methodMatch(const QMetaObject *m, const QMetaMethod &method, const QByteArray &name, int argc, const QArgumentType *types)
static int indexOfSignal(const QMetaObject *m, const QByteArray &name, int argc, const QArgumentType *types)
static Q_CORE_EXPORT int absoluteSignalCount(const QMetaObject *m)
static const QMetaObjectPrivate * get(const QMetaObject *metaobject)
static int indexOfSignalRelative(const QMetaObject **baseObject, const QByteArray &name, int argc, const QArgumentType *types)
static int indexOfMethodRelative(const QMetaObject **baseObject, const QByteArray &name, int argc, const QArgumentType *types)
static int originalClone(const QMetaObject *obj, int local_method_index)
static Q_CORE_EXPORT int signalIndex(const QMetaMethod &m)
static bool checkConnectArgs(int signalArgc, const QArgumentType *signalTypes, int methodArgc, const QArgumentType *methodTypes)
static int indexOfSlotRelative(const QMetaObject **m, const QByteArray &name, int argc, const QArgumentType *types)
const uint * data
StaticMetacallFunction static_metacall
const QtPrivate::QMetaTypeInterface *const * metaTypes
SuperData superdata
\inmodule QtCore
int propertyCount() const
Returns the number of properties in this class, including the number of properties provided by each b...
QMetaClassInfo classInfo(int index) const
Returns the meta-data for the item of class information with the given index.
QMetaProperty property(int index) const
Returns the meta-data for the property with the given index.
const char * className() const
Returns the class name.
int indexOfSignal(const char *signal) const
Finds signal and returns its index; otherwise returns -1.
QMetaProperty userProperty() const
int indexOfConstructor(const char *constructor) const
int indexOfSlot(const char *slot) const
Finds slot and returns its index; otherwise returns -1.
int indexOfClassInfo(const char *name) const
Finds class information item name and returns its index; otherwise returns -1.
int indexOfEnumerator(const char *name) const
Finds enumerator name and returns its index; otherwise returns -1.
static int metacall(QObject *, Call, int, void **)
QtPrivate::Invoke::IfNotOldStyleArgs< QObject *, Args... > newInstance(Args &&... arguments) const
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
static QByteArray normalizedSignature(const char *method)
Normalizes the signature of the given method.
QObject * cast(QObject *obj) const
QMetaType metaType() const
QString tr(const char *s, const char *c, int n=-1) const
int enumeratorOffset() const
Returns the enumerator offset for this class; i.e.
int methodCount() const
Returns the number of methods in this class, including the number of methods provided by each base cl...
QMetaEnum enumerator(int index) const
Returns the meta-data for the enumerator with the given index.
int classInfoCount() const
Returns the number of items of class information in this class.
QMetaMethod constructor(int index) const
int static_metacall(Call, int, void **) const
int indexOfMethod(const char *method) const
Finds method and returns its index; otherwise returns -1.
int indexOfProperty(const char *name) const
Finds property name and returns its index; otherwise returns -1.
int methodOffset() const
Returns the method offset for this class; i.e.
const QMetaObject * superClass() const
Returns the meta-object of the superclass, or \nullptr if there is no such object.
struct QMetaObject::Data d
bool inherits(const QMetaObject *metaObject) const noexcept
Returns true if the class described by this QMetaObject inherits the type described by metaObject; ot...
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.
int constructorCount() const
static QByteArray normalizedType(const char *type)
static bool checkConnectArgs(const char *signal, const char *method)
Returns true if the signal and method arguments are compatible; otherwise returns false.
int propertyOffset() const
Returns the property offset for this class; i.e.
int enumeratorCount() const
Returns the number of enumerators in this class.
int classInfoOffset() const
Returns the class information offset for this class; i.e.