Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 "qmetaobject_p.h"
7#include "qmetatype.h"
8#include "qmetatype_p.h"
9#include "qobject.h"
10#include "qobject_p.h"
11
12#include <qcoreapplication.h>
13#include <qvariant.h>
14
15// qthread(_p).h uses QT_CONFIG(thread) internally and has a dummy
16// interface for the non-thread support case
17#include <qthread.h>
18#include "private/qthread_p.h"
19#if QT_CONFIG(thread)
20#include <qsemaphore.h>
21#endif
22
23// for normalizeTypeInternal
24#include "private/qmetaobject_moc_p.h"
25
26#include <ctype.h>
27#include <memory>
28
30
31using namespace Qt::StringLiterals;
32
120static inline const QMetaObjectPrivate *priv(const uint* data)
121{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
122
123static inline const char *rawStringData(const QMetaObject *mo, int index)
124{
125 Q_ASSERT(priv(mo->d.data)->revision >= 7);
126 uint offset = mo->d.stringdata[2*index];
127 return reinterpret_cast<const char *>(mo->d.stringdata) + offset;
128}
129
131{
132 Q_ASSERT(priv(mo->d.data)->revision >= 7);
133 uint offset = mo->d.stringdata[2*index];
134 uint length = mo->d.stringdata[2*index + 1];
135 const char *string = reinterpret_cast<const char *>(mo->d.stringdata) + offset;
136 return {string, qsizetype(length)};
137}
138
139static inline QByteArray stringData(const QMetaObject *mo, int index)
140{
141 const auto view = stringDataView(mo, index);
142 return QByteArray::fromRawData(view.data(), view.size());
143}
144
146{
147 if (typeInfo & IsUnresolvedType)
148 return stringDataView(mo, typeInfo & TypeNameIndexMask);
149 else
150 return QByteArrayView(QMetaType(typeInfo).name());
151}
152
153static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo)
154{
155 if (!(typeInfo & IsUnresolvedType))
156 return typeInfo;
157 return QMetaType::fromName(rawStringData(mo, typeInfo & TypeNameIndexMask)).id();
158}
159
160static auto parse_scope(QByteArrayView qualifiedKey) noexcept
161{
162 struct R {
163 std::optional<QByteArrayView> scope;
165 };
166 const auto scopePos = qualifiedKey.lastIndexOf("::"_L1);
167 if (scopePos < 0)
168 return R{std::nullopt, qualifiedKey};
169 else
170 return R{qualifiedKey.first(scopePos), qualifiedKey.sliced(scopePos + 2)};
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
338{
339 return stringDataView(m, priv(m->d.data)->className);
340}
341
347const char *QMetaObject::className() const
348{
349 return objectClassName(this).constData();
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 m->d.superdata->className(), m->className());
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 QByteArrayView sourceName = typeNameFromTypeInfo(smeta, sourceTypeInfo);
1022 QByteArrayView 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
1036{
1037 while (self) {
1038 if (objectClassName(self) == name)
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) {
1045 if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name))
1046 return m;
1047 ++e;
1048 }
1049 }
1050 }
1051 self = self->d.superdata;
1052 }
1053 return self;
1054}
1055
1063{
1065}
1066
1068{
1069 using W = QMetaObjectPrivate::Which;
1070 for (auto which : { W::Name, W::Alias }) {
1071 if (int index = indexOfEnumerator(m, name, which); index != -1)
1072 return index;
1073 }
1074 return -1;
1075}
1076
1078{
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 quint32 id = which == Which::Name ? e.data.name() : e.data.alias();
1084 QByteArrayView prop = stringDataView(m, id);
1085 if (name == prop) {
1086 i += m->enumeratorOffset();
1087 return i;
1088 }
1089 }
1090 m = m->d.superdata;
1091 }
1092 return -1;
1093}
1094
1102{
1103 const QMetaObject *m = this;
1104 while (m) {
1105 const QMetaObjectPrivate *d = priv(m->d.data);
1106 for (int i = 0; i < d->propertyCount; ++i) {
1107 const QMetaProperty::Data data = QMetaProperty::getMetaPropertyData(m, i);
1108 const char *prop = rawStringData(m, data.name());
1109 if (strcmp(name, prop) == 0) {
1110 i += m->propertyOffset();
1111 return i;
1112 }
1113 }
1114 m = m->d.superdata;
1115 }
1116
1117 if (priv(this->d.data)->flags & DynamicMetaObject) {
1119 const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
1120
1121 return me->createProperty(name, nullptr);
1122 }
1123
1124 return -1;
1125}
1126
1134{
1135 int i = -1;
1136 const QMetaObject *m = this;
1137 while (m && i < 0) {
1138 for (i = priv(m->d.data)->classInfoCount-1; i >= 0; --i)
1139 if (strcmp(name, rawStringData(m, m->d.data[priv(m->d.data)->classInfoData + 2*i])) == 0) {
1140 i += m->classInfoOffset();
1141 break;
1142 }
1143 m = m->d.superdata;
1144 }
1145 return i;
1146}
1147
1156{
1157 int i = index;
1158 if (i >= 0 && i < priv(d.data)->constructorCount)
1159 return QMetaMethod::fromRelativeConstructorIndex(this, i);
1160 return QMetaMethod();
1161}
1162
1169{
1170 int i = index;
1171 i -= methodOffset();
1172 if (i < 0 && d.superdata)
1173 return d.superdata->method(index);
1174
1175 if (i >= 0 && i < priv(d.data)->methodCount)
1176 return QMetaMethod::fromRelativeMethodIndex(this, i);
1177 return QMetaMethod();
1178}
1179
1186{
1187 int i = index;
1188 i -= enumeratorOffset();
1189 if (i < 0 && d.superdata)
1190 return d.superdata->enumerator(index);
1191
1192 if (i >= 0 && i < priv(d.data)->enumeratorCount)
1193 return QMetaEnum(this, i);
1194 return QMetaEnum();
1195}
1196
1204{
1205 int i = index;
1206 i -= propertyOffset();
1207 if (i < 0 && d.superdata)
1208 return d.superdata->property(index);
1209
1210 if (i >= 0 && i < priv(d.data)->propertyCount)
1211 return QMetaProperty(this, i);
1212 return QMetaProperty();
1213}
1214
1223{
1224 const int propCount = propertyCount();
1225 for (int i = propCount - 1; i >= 0; --i) {
1226 const QMetaProperty prop = property(i);
1227 if (prop.isUser())
1228 return prop;
1229 }
1230 return QMetaProperty();
1231}
1232
1244{
1245 int i = index;
1246 i -= classInfoOffset();
1247 if (i < 0 && d.superdata)
1248 return d.superdata->classInfo(index);
1249
1251 if (i >= 0 && i < priv(d.data)->classInfoCount) {
1252 result.mobj = this;
1253 result.data = { d.data + priv(d.data)->classInfoData + i * QMetaClassInfo::Data::Size };
1254 }
1255 return result;
1256}
1257
1266bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
1267{
1268 const char *s1 = signal;
1269 const char *s2 = method;
1270 while (*s1++ != '(') { } // scan to first '('
1271 while (*s2++ != '(') { }
1272 if (*s2 == ')' || qstrcmp(s1,s2) == 0) // method has no args or
1273 return true; // exact match
1274 const auto s1len = qstrlen(s1);
1275 const auto s2len = qstrlen(s2);
1276 if (s2len < s1len && strncmp(s1,s2,s2len-1)==0 && s1[s2len-1]==',')
1277 return true; // method has less args
1278 return false;
1279}
1280
1289 const QMetaMethod &method)
1290{
1292 QMetaMethodPrivate::get(&signal),
1293 QMetaMethodPrivate::get(&method));
1294}
1295
1296static void qRemoveWhitespace(const char *s, char *d)
1297{
1298 char last = 0;
1299 while (*s && is_space(*s))
1300 s++;
1301 while (*s) {
1302 while (*s && !is_space(*s))
1303 last = *d++ = *s++;
1304 while (*s && is_space(*s))
1305 s++;
1306 if (*s && ((is_ident_char(*s) && is_ident_char(last))
1307 || ((*s == ':') && (last == '<')))) {
1308 last = *d++ = ' ';
1309 }
1310 }
1311 *d = '\0';
1312}
1313
1314static char *qNormalizeType(char *d, int &templdepth, QByteArray &result)
1315{
1316 const char *t = d;
1317 while (*d && (templdepth
1318 || (*d != ',' && *d != ')'))) {
1319 if (*d == '<')
1320 ++templdepth;
1321 if (*d == '>')
1322 --templdepth;
1323 ++d;
1324 }
1325 // "void" should only be removed if this is part of a signature that has
1326 // an explicit void argument; e.g., "void foo(void)" --> "void foo()"
1327 if (strncmp("void)", t, d - t + 1) != 0)
1328 result += normalizeTypeInternal(t, d);
1329
1330 return d;
1331}
1332
1333
1349{
1350 return normalizeTypeInternal(type, type + qstrlen(type));
1351}
1352
1365{
1367 if (!method || !*method)
1368 return result;
1369 int len = int(strlen(method));
1370 QVarLengthArray<char> stackbuf(len + 1);
1371 char *d = stackbuf.data();
1373
1374 result.reserve(len);
1375
1376 int argdepth = 0;
1377 int templdepth = 0;
1378 while (*d) {
1379 if (argdepth == 1) {
1380 d = qNormalizeType(d, templdepth, result);
1381 if (!*d) //most likely an invalid signature.
1382 break;
1383 }
1384 if (*d == '(')
1385 ++argdepth;
1386 if (*d == ')')
1387 --argdepth;
1388 result += *d++;
1389 }
1390
1391 return result;
1392}
1393
1394Q_DECL_COLD_FUNCTION static inline bool
1396 const char *const *names,
1397 const QtPrivate::QMetaTypeInterface * const *metaTypes)
1398{
1399 // now find the candidates we couldn't use
1400 QByteArray candidateMessage;
1401 for (int i = 0; i < meta->methodCount(); ++i) {
1402 const QMetaMethod method = meta->method(i);
1403 if (method.name() == name)
1404 candidateMessage += " " + method.methodSignature() + '\n';
1405 }
1406 if (!candidateMessage.isEmpty()) {
1407 candidateMessage.prepend("\nCandidates are:\n");
1408 candidateMessage.chop(1);
1409 }
1410
1411 QVarLengthArray<char, 512> sig;
1412 for (qsizetype i = 1; i < paramCount; ++i) {
1413 if (names[i])
1414 sig.append(names[i], qstrlen(names[i]));
1415 else
1416 sig.append(metaTypes[i]->name, qstrlen(metaTypes[i]->name));
1417 sig.append(',');
1418 }
1419 if (paramCount != 1)
1420 sig.resize(sig.size() - 1);
1421
1422 qWarning("QMetaObject::invokeMethod: No such method %s::%.*s(%.*s)%.*s",
1423 meta->className(), int(name.size()), name.constData(),
1424 int(sig.size()), sig.constData(),
1425 int(candidateMessage.size()), candidateMessage.constData());
1426 return false;
1427}
1428
1545 const char *member,
1548 QGenericArgument val0,
1549 QGenericArgument val1,
1550 QGenericArgument val2,
1551 QGenericArgument val3,
1552 QGenericArgument val4,
1553 QGenericArgument val5,
1554 QGenericArgument val6,
1555 QGenericArgument val7,
1556 QGenericArgument val8,
1557 QGenericArgument val9)
1558{
1559 if (!obj)
1560 return false;
1561
1562 const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(),
1563 val4.name(), val5.name(), val6.name(), val7.name(), val8.name(),
1564 val9.name()};
1565 const void *parameters[] = {ret.data(), val0.data(), val1.data(), val2.data(), val3.data(),
1566 val4.data(), val5.data(), val6.data(), val7.data(), val8.data(),
1567 val9.data()};
1568 int paramCount;
1569 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
1570 if (qstrlen(typeNames[paramCount]) <= 0)
1571 break;
1572 }
1573 return invokeMethodImpl(obj, member, type, paramCount, parameters, typeNames, nullptr);
1574}
1575
1576bool QMetaObject::invokeMethodImpl(QObject *obj, const char *member, Qt::ConnectionType type,
1577 qsizetype paramCount, const void * const *parameters,
1578 const char * const *typeNames,
1579 const QtPrivate::QMetaTypeInterface * const *metaTypes)
1580{
1581 if (!obj)
1582 return false;
1583
1584 Q_ASSERT(paramCount >= 1); // includes the return type
1585 Q_ASSERT(parameters);
1586 Q_ASSERT(typeNames);
1587
1588 // find the method
1589 QByteArrayView name(member);
1590 if (name.isEmpty())
1591 return false;
1592
1593 const QMetaObject *meta = obj->metaObject();
1594 for ( ; meta; meta = meta->superClass()) {
1595 auto priv = QMetaObjectPrivate::get(meta);
1596 for (int i = 0; i < priv->methodCount; ++i) {
1597 QMetaMethod m = QMetaMethod::fromRelativeMethodIndex(meta, i);
1598 if (m.parameterCount() != (paramCount - 1))
1599 continue;
1600 if (name != stringDataView(meta, m.data.name()))
1601 continue;
1602
1603 // attempt to call
1604 QMetaMethodPrivate::InvokeFailReason r =
1605 QMetaMethodPrivate::invokeImpl(m, obj, type, paramCount, parameters,
1606 typeNames, metaTypes);
1607 if (int(r) <= 0)
1608 return r == QMetaMethodPrivate::InvokeFailReason::None;
1609 }
1610 }
1611
1612 // This method doesn't belong to us; print out a nice warning with candidates.
1613 return printMethodNotFoundWarning(obj->metaObject(), name, paramCount, typeNames, metaTypes);
1614}
1615
1616bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slotObj, Qt::ConnectionType type,
1617 qsizetype parameterCount, const void *const *params, const char *const *names,
1618 const QtPrivate::QMetaTypeInterface * const *metaTypes)
1619{
1620 // We don't need this now but maybe we want it later, or we may be able to
1621 // share more code between the two invokeMethodImpl() overloads:
1622 Q_UNUSED(names);
1623 auto slot = QtPrivate::SlotObjUniquePtr(slotObj);
1624
1625 if (! object) // ### only if the slot requires the object + not queued?
1626 return false;
1627
1628 Qt::HANDLE currentThreadId = QThread::currentThreadId();
1629 QThread *objectThread = object->thread();
1630 bool receiverInSameThread = false;
1631 if (objectThread)
1632 receiverInSameThread = currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
1633
1634 if (type == Qt::AutoConnection)
1635 type = receiverInSameThread ? Qt::DirectConnection : Qt::QueuedConnection;
1636
1637 void **argv = const_cast<void **>(params);
1638 if (type == Qt::DirectConnection) {
1639 slot->call(object, argv);
1640 } else if (type == Qt::QueuedConnection) {
1641 if (argv[0]) {
1642 qWarning("QMetaObject::invokeMethod: Unable to invoke methods with return values in "
1643 "queued connections");
1644 return false;
1645 }
1646 auto event = std::make_unique<QMetaCallEvent>(std::move(slot), nullptr, -1, parameterCount);
1647 void **args = event->args();
1648 QMetaType *types = event->types();
1649
1650 for (int i = 1; i < parameterCount; ++i) {
1651 types[i] = QMetaType(metaTypes[i]);
1652 args[i] = types[i].create(argv[i]);
1653 }
1654
1655 QCoreApplication::postEvent(object, event.release());
1656 } else if (type == Qt::BlockingQueuedConnection) {
1657#if QT_CONFIG(thread)
1658 if (receiverInSameThread)
1659 qWarning("QMetaObject::invokeMethod: Dead lock detected");
1660
1661 QSemaphore semaphore;
1662 QCoreApplication::postEvent(object, new QMetaCallEvent(std::move(slot), nullptr, -1, argv, &semaphore));
1663 semaphore.acquire();
1664#endif // QT_CONFIG(thread)
1665 } else {
1666 qWarning("QMetaObject::invokeMethod: Unknown connection type");
1667 return false;
1668 }
1669 return true;
1670}
1671
1867QMetaMethod QMetaMethod::fromRelativeMethodIndex(const QMetaObject *mobj, int index)
1868{
1869 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->methodCount);
1870 QMetaMethod m;
1871 m.mobj = mobj;
1872 m.data = { mobj->d.data + priv(mobj->d.data)->methodData + index * Data::Size };
1873 return m;
1874}
1875
1876QMetaMethod QMetaMethod::fromRelativeConstructorIndex(const QMetaObject *mobj, int index)
1877{
1878 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->constructorCount);
1879 QMetaMethod m;
1880 m.mobj = mobj;
1881 m.data = { mobj->d.data + priv(mobj->d.data)->constructorData + index * Data::Size };
1882 return m;
1883}
1884
1893QByteArray QMetaMethodPrivate::signature() const
1894{
1895 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1897 result.reserve(256);
1898 result += name();
1899 result += '(';
1900 QList<QByteArray> argTypes = parameterTypes();
1901 for (int i = 0; i < argTypes.size(); ++i) {
1902 if (i)
1903 result += ',';
1904 result += argTypes.at(i);
1905 }
1906 result += ')';
1907 return result;
1908}
1909
1910QByteArray QMetaMethodPrivate::name() const
1911{
1912 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1913 return stringData(mobj, data.name());
1914}
1915
1916int QMetaMethodPrivate::typesDataIndex() const
1917{
1918 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1919 return data.parameters();
1920}
1921
1922const char *QMetaMethodPrivate::rawReturnTypeName() const
1923{
1924 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1925 uint typeInfo = mobj->d.data[typesDataIndex()];
1926 if (typeInfo & IsUnresolvedType)
1927 return rawStringData(mobj, typeInfo & TypeNameIndexMask);
1928 else
1929 return QMetaType(typeInfo).name();
1930}
1931
1932int QMetaMethodPrivate::returnType() const
1933{
1934 return parameterType(-1);
1935}
1936
1937int QMetaMethodPrivate::parameterCount() const
1938{
1939 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1940 return data.argc();
1941}
1942
1943inline void
1944QMetaMethodPrivate::checkMethodMetaTypeConsistency(const QtPrivate::QMetaTypeInterface *iface,
1945 int index) const
1946{
1947 uint typeInfo = parameterTypeInfo(index);
1948 QMetaType mt(iface);
1949 if (iface) {
1950 if ((typeInfo & IsUnresolvedType) == 0)
1951 Q_ASSERT(mt.id() == int(typeInfo & TypeNameIndexMask));
1952 Q_ASSERT(mt.name());
1953 } else {
1954 // The iface can only be null for a parameter if that parameter is a
1955 // const-ref to a forward-declared type. Since primitive types are
1956 // never incomplete, we can assert it's not one of them.
1957
1958#define ASSERT_NOT_PRIMITIVE_TYPE(TYPE, METATYPEID, NAME) \
1959 Q_ASSERT(typeInfo != QMetaType::TYPE);
1961#undef ASSERT_NOT_PRIMITIVE_TYPE
1962 Q_ASSERT(typeInfo != QMetaType::QObjectStar);
1963
1964 // Prior to Qt 6.4 we failed to record void and void*
1965 if (priv(mobj->d.data)->revision >= 11) {
1966 Q_ASSERT(typeInfo != QMetaType::Void);
1967 Q_ASSERT(typeInfo != QMetaType::VoidStar);
1968 }
1969 }
1970}
1971
1972int QMetaMethodPrivate::parametersDataIndex() const
1973{
1974 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1975 return typesDataIndex() + 1;
1976}
1977
1978uint QMetaMethodPrivate::parameterTypeInfo(int index) const
1979{
1980 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1981 return mobj->d.data[parametersDataIndex() + index];
1982}
1983
1984const QtPrivate::QMetaTypeInterface *QMetaMethodPrivate::returnMetaTypeInterface() const
1985{
1986 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1987 if (methodType() == QMetaMethod::Constructor)
1988 return nullptr; // constructors don't have return types
1989
1990 const QtPrivate::QMetaTypeInterface *iface = mobj->d.metaTypes[data.metaTypeOffset()];
1991 checkMethodMetaTypeConsistency(iface, -1);
1992 return iface;
1993}
1994
1995const QtPrivate::QMetaTypeInterface * const *QMetaMethodPrivate::parameterMetaTypeInterfaces() const
1996{
1997 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1998 int offset = (methodType() == QMetaMethod::Constructor ? 0 : 1);
1999 const auto ifaces = &mobj->d.metaTypes[data.metaTypeOffset() + offset];
2000
2001 for (int i = 0; i < parameterCount(); ++i)
2002 checkMethodMetaTypeConsistency(ifaces[i], i);
2003
2004 return ifaces;
2005}
2006
2007int QMetaMethodPrivate::parameterType(int index) const
2008{
2009 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2010 return typeFromTypeInfo(mobj, parameterTypeInfo(index));
2011}
2012
2013void QMetaMethodPrivate::getParameterTypes(int *types) const
2014{
2015 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2016 int dataIndex = parametersDataIndex();
2017 int argc = parameterCount();
2018 for (int i = 0; i < argc; ++i) {
2019 int id = typeFromTypeInfo(mobj, mobj->d.data[dataIndex++]);
2020 *(types++) = id;
2021 }
2022}
2023
2024QByteArray QMetaMethodPrivate::parameterTypeName(int index) const
2025{
2026 int paramsIndex = parametersDataIndex();
2027 return typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + index]).toByteArray();
2028}
2029
2030QList<QByteArray> QMetaMethodPrivate::parameterTypes() const
2031{
2032 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2033 int argc = parameterCount();
2034 QList<QByteArray> list;
2035 list.reserve(argc);
2036 int paramsIndex = parametersDataIndex();
2037 for (int i = 0; i < argc; ++i) {
2038 QByteArrayView name = typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + i]);
2039 list.emplace_back(name.toByteArray());
2040 }
2041 return list;
2042}
2043
2044QList<QByteArray> QMetaMethodPrivate::parameterNames() const
2045{
2046 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2047 int argc = parameterCount();
2048 QList<QByteArray> list;
2049 list.reserve(argc);
2050 int namesIndex = parametersDataIndex() + argc;
2051 for (int i = 0; i < argc; ++i)
2052 list += stringData(mobj, mobj->d.data[namesIndex + i]);
2053 return list;
2054}
2055
2056QByteArray QMetaMethodPrivate::tag() const
2057{
2058 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
2059 return stringData(mobj, data.tag());
2060}
2061
2062int QMetaMethodPrivate::ownMethodIndex() const
2063{
2064 // recompute the methodIndex by reversing the arithmetic in QMetaObject::method()
2065 return ( data.d - mobj->d.data - priv(mobj->d.data)->methodData)/Data::Size;
2066}
2067
2068int QMetaMethodPrivate::ownConstructorMethodIndex() const
2069{
2070 // recompute the methodIndex by reversing the arithmetic in QMetaObject::constructor()
2071 Q_ASSERT(methodType() == Constructor);
2072 return ( data.d - mobj->d.data - priv(mobj->d.data)->constructorData)/Data::Size;
2073}
2074
2084{
2085 if (!mobj)
2086 return QByteArray();
2087 return QMetaMethodPrivate::get(this)->signature();
2088}
2089
2098{
2099 if (!mobj)
2100 return QByteArray();
2101 return QMetaMethodPrivate::get(this)->name();
2102}
2103
2115 {
2116 return returnMetaType().id();
2117}
2118
2126{
2127 if (!mobj || methodType() == QMetaMethod::Constructor)
2128 return QMetaType{};
2129 auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset()]);
2130 if (mt.id() == QMetaType::UnknownType)
2131 return QMetaType(QMetaMethodPrivate::get(this)->returnType());
2132 else
2133 return mt;
2134}
2135
2144{
2145 if (!mobj)
2146 return 0;
2147 return QMetaMethodPrivate::get(this)->parameterCount();
2148}
2149
2161{
2162 return parameterMetaType(index).id();
2163}
2164
2176{
2177 if (!mobj || index < 0)
2178 return {};
2179 auto priv = QMetaMethodPrivate::get(this);
2180 if (index >= priv->parameterCount())
2181 return {};
2182 // + 1 if there exists a return type
2183 auto parameterOffset = index + (methodType() == QMetaMethod::Constructor ? 0 : 1);
2184 auto mt = QMetaType(mobj->d.metaTypes[data.metaTypeOffset() + parameterOffset]);
2185 if (mt.id() == QMetaType::UnknownType)
2186 return QMetaType(QMetaMethodPrivate::get(this)->parameterType(index));
2187 else
2188 return mt;
2189}
2190
2201{
2202 if (!mobj)
2203 return;
2204 QMetaMethodPrivate::get(this)->getParameterTypes(types);
2205}
2206
2212QList<QByteArray> QMetaMethod::parameterTypes() const
2213{
2214 if (!mobj)
2215 return QList<QByteArray>();
2216 return QMetaMethodPrivate::get(this)->parameterTypes();
2217}
2218
2227{
2228 if (!mobj || index < 0 || index >= parameterCount())
2229 return {};
2230 return QMetaMethodPrivate::get(this)->parameterTypeName(index);
2231}
2232
2238QList<QByteArray> QMetaMethod::parameterNames() const
2239{
2240 if (!mobj)
2241 return QList<QByteArray>();
2242 return QMetaMethodPrivate::get(this)->parameterNames();
2243}
2244
2245
2251const char *QMetaMethod::typeName() const
2252{
2253 if (!mobj)
2254 return nullptr;
2255 return QMetaMethodPrivate::get(this)->rawReturnTypeName();
2256}
2257
2282const char *QMetaMethod::tag() const
2283{
2284 if (!mobj)
2285 return nullptr;
2286 return QMetaMethodPrivate::get(this)->tag().constData();
2287}
2288
2289
2294{
2295 if (!mobj)
2296 return false;
2297 return data.flags() >> 4;
2298}
2299
2306{
2307 if (!mobj)
2308 return -1;
2309 return QMetaMethodPrivate::get(this)->ownMethodIndex() + mobj->methodOffset();
2310}
2311
2318{
2319 if (!mobj)
2320 return -1;
2321 return QMetaMethodPrivate::get(this)->ownMethodIndex();
2322}
2323
2324// This method has been around for a while, but the documentation was marked \internal until 5.1
2331{
2332 if (!mobj)
2333 return 0;
2334 if (data.flags() & MethodRevisioned) {
2335 int offset = priv(mobj->d.data)->methodData
2336 + priv(mobj->d.data)->methodCount * Data::Size
2337 + QMetaMethodPrivate::get(this)->ownMethodIndex();
2338 return mobj->d.data[offset];
2339 }
2340 return 0;
2341}
2342
2352{
2353 if (!mobj)
2354 return false;
2355 if (QMetaObjectPrivate::get(mobj)->revision < 10)
2356 return false;
2357 return data.flags() & MethodIsConst;
2358}
2359
2371{
2372 if (!mobj)
2373 return Private;
2374 return (QMetaMethod::Access)(data.flags() & AccessMask);
2375}
2376
2383{
2384 if (!mobj)
2385 return QMetaMethod::Method;
2386 return (QMetaMethod::MethodType)((data.flags() & MethodTypeMask)>>2);
2387}
2388
2409QMetaMethod QMetaMethod::fromSignalImpl(const QMetaObject *metaObject, void **signal)
2410{
2411 int i = -1;
2412 void *args[] = { &i, signal };
2413 for (const QMetaObject *m = metaObject; m; m = m->d.superdata) {
2414 m->static_metacall(QMetaObject::IndexOfMethod, 0, args);
2415 if (i >= 0)
2416 return QMetaMethod::fromRelativeMethodIndex(m, i);
2417 }
2418 return QMetaMethod();
2419}
2420
2534 Qt::ConnectionType connectionType,
2535 QGenericReturnArgument returnValue,
2536 QGenericArgument val0,
2537 QGenericArgument val1,
2538 QGenericArgument val2,
2539 QGenericArgument val3,
2540 QGenericArgument val4,
2541 QGenericArgument val5,
2542 QGenericArgument val6,
2543 QGenericArgument val7,
2544 QGenericArgument val8,
2545 QGenericArgument val9) const
2546{
2547 if (!object || !mobj)
2548 return false;
2549
2550 // check argument count (we don't allow invoking a method if given too few arguments)
2551 const char *typeNames[] = {
2552 returnValue.name(),
2553 val0.name(),
2554 val1.name(),
2555 val2.name(),
2556 val3.name(),
2557 val4.name(),
2558 val5.name(),
2559 val6.name(),
2560 val7.name(),
2561 val8.name(),
2562 val9.name()
2563 };
2564 void *param[] = {
2565 returnValue.data(),
2566 val0.data(),
2567 val1.data(),
2568 val2.data(),
2569 val3.data(),
2570 val4.data(),
2571 val5.data(),
2572 val6.data(),
2573 val7.data(),
2574 val8.data(),
2575 val9.data()
2576 };
2577
2578 int paramCount;
2579 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
2580 if (qstrlen(typeNames[paramCount]) <= 0)
2581 break;
2582 }
2583 return invokeImpl(*this, object, connectionType, paramCount, param, typeNames, nullptr);
2584}
2585
2586bool QMetaMethod::invokeImpl(QMetaMethod self, void *target, Qt::ConnectionType connectionType,
2587 qsizetype paramCount, const void *const *parameters,
2588 const char *const *typeNames,
2589 const QtPrivate::QMetaTypeInterface *const *metaTypes)
2590{
2591 if (!target || !self.mobj)
2592 return false;
2593 QMetaMethodPrivate::InvokeFailReason r =
2594 QMetaMethodPrivate::invokeImpl(self, target, connectionType, paramCount, parameters,
2595 typeNames, metaTypes);
2596 if (Q_LIKELY(r == QMetaMethodPrivate::InvokeFailReason::None))
2597 return true;
2598
2599 if (int(r) >= int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch)) {
2600 int n = int(r) - int(QMetaMethodPrivate::InvokeFailReason::FormalParameterMismatch);
2601 qWarning("QMetaMethod::invoke: cannot convert formal parameter %d from %s in call to %s::%s",
2602 n, typeNames[n + 1] ? typeNames[n + 1] : metaTypes[n + 1]->name,
2603 self.mobj->className(), self.methodSignature().constData());
2604 }
2605 if (r == QMetaMethodPrivate::InvokeFailReason::TooFewArguments) {
2606 qWarning("QMetaMethod::invoke: too few arguments (%d) in call to %s::%s",
2607 int(paramCount), self.mobj->className(), self.methodSignature().constData());
2608 }
2609 return false;
2610}
2611
2613 Qt::ConnectionType connectionType,
2614 qsizetype paramCount, const void *const *parameters,
2615 const char *const *typeNames,
2616 const QtPrivate::QMetaTypeInterface *const *metaTypes) -> InvokeFailReason
2617{
2618 auto object = static_cast<QObject *>(target);
2619 auto priv = QMetaMethodPrivate::get(&self);
2620 constexpr bool MetaTypesAreOptional = QT_VERSION < QT_VERSION_CHECK(7, 0, 0);
2621 auto methodMetaTypes = priv->parameterMetaTypeInterfaces();
2622 auto param = const_cast<void **>(parameters);
2623
2624 Q_ASSERT(priv->mobj);
2625 Q_ASSERT(self.methodType() == Constructor || object);
2626 Q_ASSERT(self.methodType() == Constructor || connectionType == Qt::ConnectionType(-1) ||
2627 priv->mobj->cast(object));
2628 Q_ASSERT(paramCount >= 1); // includes the return type
2629 Q_ASSERT(parameters);
2630 Q_ASSERT(typeNames);
2631 Q_ASSERT(MetaTypesAreOptional || metaTypes);
2632
2633 if ((paramCount - 1) < qsizetype(priv->data.argc()))
2634 return InvokeFailReason::TooFewArguments;
2635
2636 // 0 is the return type, 1 is the first formal parameter
2637 auto checkTypesAreCompatible = [=](int idx) {
2638 uint typeInfo = priv->parameterTypeInfo(idx - 1);
2639 QByteArrayView userTypeName(typeNames[idx] ? typeNames[idx] : metaTypes[idx]->name);
2640
2641 if ((typeInfo & IsUnresolvedType) == 0) {
2642 // this is a built-in type
2643 if (MetaTypesAreOptional && !metaTypes)
2644 return int(typeInfo) == QMetaType::fromName(userTypeName).id();
2645 return int(typeInfo) == metaTypes[idx]->typeId;
2646 }
2647
2648 QByteArrayView methodTypeName = stringDataView(priv->mobj, typeInfo & TypeNameIndexMask);
2649 if ((MetaTypesAreOptional && !metaTypes) || !metaTypes[idx]) {
2650 // compatibility call, compare strings
2651 if (methodTypeName == userTypeName)
2652 return true;
2653
2654 // maybe the user type needs normalization
2655 QByteArray normalized = normalizeTypeInternal(userTypeName.begin(), userTypeName.end());
2656 return methodTypeName == normalized;
2657 }
2658
2659 QMetaType userType(metaTypes[idx]);
2660 Q_ASSERT(userType.isValid());
2661 if (QMetaType(methodMetaTypes[idx - 1]) == userType)
2662 return true;
2663
2664 // if the parameter type was NOT only forward-declared, it MUST have
2665 // matched
2666 if (methodMetaTypes[idx - 1])
2667 return false;
2668
2669 // resolve from the name moc stored for us
2670 QMetaType resolved = QMetaType::fromName(methodTypeName);
2671 return resolved == userType;
2672 };
2673
2674 // force all types to be registered, just in case
2675 for (qsizetype i = 0; metaTypes && i < paramCount; ++i)
2676 QMetaType(metaTypes[i]).registerType();
2677
2678 // check formal parameters first (overload set)
2679 for (qsizetype i = 1; i < paramCount; ++i) {
2680 if (!checkTypesAreCompatible(i))
2681 return InvokeFailReason(int(InvokeFailReason::FormalParameterMismatch) + i - 1);
2682 }
2683
2684 // handle constructors first
2685 if (self.methodType() == Constructor) {
2686 if (object) {
2687 qWarning("QMetaMethod::invokeMethod: cannot call constructor %s on object %p",
2688 self.methodSignature().constData(), object);
2689 return InvokeFailReason::ConstructorCallOnObject;
2690 }
2691
2692 if (!parameters[0]) {
2693 qWarning("QMetaMethod::invokeMethod: constructor call to %s must assign a return type",
2694 self.methodSignature().constData());
2695 return InvokeFailReason::ConstructorCallWithoutResult;
2696 }
2697
2698 if (!MetaTypesAreOptional || metaTypes) {
2699 if (metaTypes[0]->typeId != QMetaType::QObjectStar) {
2700 qWarning("QMetaMethod::invokeMethod: cannot convert QObject* to %s on constructor call %s",
2701 metaTypes[0]->name, self.methodSignature().constData());
2702 return InvokeFailReason::ReturnTypeMismatch;
2703 }
2704 }
2705
2706 int idx = priv->ownConstructorMethodIndex();
2707 if (priv->mobj->static_metacall(QMetaObject::CreateInstance, idx, param) >= 0)
2708 return InvokeFailReason::ConstructorCallFailed;
2709 return {};
2710 }
2711
2712 // regular type - check return type
2713 if (parameters[0]) {
2714 if (!checkTypesAreCompatible(0)) {
2715 const char *retType = typeNames[0] ? typeNames[0] : metaTypes[0]->name;
2716 qWarning("QMetaMethod::invokeMethod: return type mismatch for method %s::%s:"
2717 " cannot convert from %s to %s during invocation",
2718 priv->mobj->className(), priv->methodSignature().constData(),
2719 priv->rawReturnTypeName(), retType);
2720 return InvokeFailReason::ReturnTypeMismatch;
2721 }
2722 }
2723
2724 Qt::HANDLE currentThreadId = nullptr;
2725 QThread *objectThread = nullptr;
2726 auto receiverInSameThread = [&]() {
2727 if (!currentThreadId) {
2728 currentThreadId = QThread::currentThreadId();
2729 objectThread = object->thread();
2730 }
2731 if (objectThread)
2732 return currentThreadId == QThreadData::get2(objectThread)->threadId.loadRelaxed();
2733 return false;
2734 };
2735
2736 // check connection type
2737 if (connectionType == Qt::AutoConnection)
2738 connectionType = receiverInSameThread() ? Qt::DirectConnection : Qt::QueuedConnection;
2739 else if (connectionType == Qt::ConnectionType(-1))
2740 connectionType = Qt::DirectConnection;
2741
2742#if !QT_CONFIG(thread)
2743 if (connectionType == Qt::BlockingQueuedConnection) {
2744 connectionType = Qt::DirectConnection;
2745 }
2746#endif
2747
2748 // invoke!
2749 int idx_relative = priv->ownMethodIndex();
2750 int idx_offset = priv->mobj->methodOffset();
2751 QObjectPrivate::StaticMetaCallFunction callFunction = priv->mobj->d.static_metacall;
2752
2753 if (connectionType == Qt::DirectConnection) {
2754 if (callFunction)
2755 callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
2756 else if (QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, idx_relative + idx_offset, param) >= 0)
2757 return InvokeFailReason::CallViaVirtualFailed;
2758 } else if (connectionType == Qt::QueuedConnection) {
2759 if (parameters[0]) {
2760 qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
2761 "queued connections");
2762 return InvokeFailReason::CouldNotQueueParameter;
2763 }
2764
2765 auto event = std::make_unique<QMetaCallEvent>(idx_offset, idx_relative, callFunction, nullptr, -1, paramCount);
2766 QMetaType *types = event->types();
2767 void **args = event->args();
2768
2769 // fill in the meta types first
2770 for (int i = 1; i < paramCount; ++i) {
2771 types[i] = QMetaType(methodMetaTypes[i - 1]);
2772 if (!types[i].iface() && (!MetaTypesAreOptional || metaTypes))
2773 types[i] = QMetaType(metaTypes[i]);
2774 if (!types[i].iface())
2775 types[i] = priv->parameterMetaType(i - 1);
2776 if (!types[i].iface() && typeNames[i])
2777 types[i] = QMetaType::fromName(typeNames[i]);
2778 if (!types[i].iface()) {
2779 qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
2780 typeNames[i]);
2781 return InvokeFailReason(int(InvokeFailReason::CouldNotQueueParameter) - i);
2782 }
2783 }
2784
2785 // now create copies of our parameters using those meta types
2786 for (int i = 1; i < paramCount; ++i)
2787 args[i] = types[i].create(parameters[i]);
2788
2789 QCoreApplication::postEvent(object, event.release());
2790 } else { // blocking queued connection
2791#if QT_CONFIG(thread)
2792 if (receiverInSameThread()) {
2793 qWarning("QMetaMethod::invoke: Dead lock detected in BlockingQueuedConnection: "
2794 "Receiver is %s(%p)", priv->mobj->className(), object);
2795 return InvokeFailReason::DeadLockDetected;
2796 }
2797
2798 QSemaphore semaphore;
2799 QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
2800 nullptr, -1, param, &semaphore));
2801 semaphore.acquire();
2802#endif // QT_CONFIG(thread)
2803 }
2804 return {};
2805}
2806
2911 QGenericReturnArgument returnValue,
2912 QGenericArgument val0,
2913 QGenericArgument val1,
2914 QGenericArgument val2,
2915 QGenericArgument val3,
2916 QGenericArgument val4,
2917 QGenericArgument val5,
2918 QGenericArgument val6,
2919 QGenericArgument val7,
2920 QGenericArgument val8,
2921 QGenericArgument val9) const
2922{
2923 if (!gadget || !mobj)
2924 return false;
2925
2926 // check return type
2927 if (returnValue.data()) {
2928 const char *retType = typeName();
2929 if (qstrcmp(returnValue.name(), retType) != 0) {
2930 // normalize the return value as well
2932 if (qstrcmp(normalized.constData(), retType) != 0) {
2933 // String comparison failed, try compare the metatype.
2934 int t = returnType();
2936 return false;
2937 }
2938 }
2939 }
2940
2941 // check argument count (we don't allow invoking a method if given too few arguments)
2942 const char *typeNames[] = {
2943 returnValue.name(),
2944 val0.name(),
2945 val1.name(),
2946 val2.name(),
2947 val3.name(),
2948 val4.name(),
2949 val5.name(),
2950 val6.name(),
2951 val7.name(),
2952 val8.name(),
2953 val9.name()
2954 };
2955 int paramCount;
2956 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
2957 if (qstrlen(typeNames[paramCount]) <= 0)
2958 break;
2959 }
2960 if (paramCount <= QMetaMethodPrivate::get(this)->parameterCount())
2961 return false;
2962
2963 // invoke!
2964 void *param[] = {
2965 returnValue.data(),
2966 val0.data(),
2967 val1.data(),
2968 val2.data(),
2969 val3.data(),
2970 val4.data(),
2971 val5.data(),
2972 val6.data(),
2973 val7.data(),
2974 val8.data(),
2975 val9.data()
2976 };
2977 int idx_relative = QMetaMethodPrivate::get(this)->ownMethodIndex();
2978 Q_ASSERT(QMetaObjectPrivate::get(mobj)->revision >= 6);
2979 QObjectPrivate::StaticMetaCallFunction callFunction = mobj->d.static_metacall;
2980 if (!callFunction)
2981 return false;
2982 callFunction(reinterpret_cast<QObject*>(gadget), QMetaObject::InvokeMetaMethod, idx_relative, param);
2983 return true;
2984}
2985
3059const char *QMetaEnum::name() const
3060{
3061 if (!mobj)
3062 return nullptr;
3063 return rawStringData(mobj, data.name());
3064}
3065
3078const char *QMetaEnum::enumName() const
3079{
3080 if (!mobj)
3081 return nullptr;
3082 return rawStringData(mobj, data.alias());
3083}
3084
3098{
3099 if (!mobj)
3100 return {};
3101
3102 const QMetaObjectPrivate *p = priv(mobj->d.data);
3103#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
3104 if (p->revision < 12)
3105 QMetaType();
3106#endif
3107
3108 return QMetaType(mobj->d.metaTypes[data.index(mobj) + p->propertyCount]);
3109}
3110
3117{
3118 if (!mobj)
3119 return 0;
3120 return data.keyCount();
3121}
3122
3128const char *QMetaEnum::key(int index) const
3129{
3130 if (!mobj)
3131 return nullptr;
3132 if (index >= 0 && index < int(data.keyCount()))
3133 return rawStringData(mobj, mobj->d.data[data.data() + 2*index]);
3134 return nullptr;
3135}
3136
3144{
3145 if (!mobj)
3146 return 0;
3147 if (index >= 0 && index < int(data.keyCount()))
3148 return mobj->d.data[data.data() + 2 * index + 1];
3149 return -1;
3150}
3151
3162{
3163 if (!mobj)
3164 return false;
3165 return data.flags() & EnumIsFlag;
3166}
3167
3175{
3176 if (!mobj)
3177 return false;
3178 return data.flags() & EnumIsScoped;
3179}
3180
3189const char *QMetaEnum::scope() const
3190{
3191 return mobj ? mobj->className() : nullptr;
3192}
3193
3194static bool isScopeMatch(QByteArrayView scope, const QMetaEnum *e)
3195{
3197
3198 // Typical use-cases:
3199 // a) Unscoped: namespace N { class C { enum E { F }; }; }; key == "N::C::F"
3200 // b) Scoped: namespace N { class C { enum class E { F }; }; }; key == "N::C::E::F"
3201 if (scope == className)
3202 return true;
3203
3204 // Not using name() because if isFlag() is true, we want the actual name
3205 // of the enum, e.g. "MyFlag", not "MyFlags", e.g.
3206 // enum MyFlag { F1, F2 }; Q_DECLARE_FLAGS(MyFlags, MyFlag);
3208
3209 // Match fully qualified enumerator in unscoped enums, key == "N::C::E::F"
3210 // equivalent to use-case "a" above
3211 const auto sz = className.size();
3212 if (scope.size() == sz + qsizetype(qstrlen("::")) + name.size()
3213 && scope.startsWith(className)
3214 && scope.sliced(sz, 2) == "::"
3215 && scope.sliced(sz + 2) == name)
3216 return true;
3217
3218 return false;
3219}
3220
3232int QMetaEnum::keyToValue(const char *key, bool *ok) const
3233{
3234 if (ok != nullptr)
3235 *ok = false;
3236 if (!mobj || !key)
3237 return -1;
3238
3239 const auto [scope, enumKey] = parse_scope(QLatin1StringView(key));
3240 for (int i = 0; i < int(data.keyCount()); ++i) {
3241 if ((!scope || isScopeMatch(*scope, this))
3242 && enumKey == stringDataView(mobj, mobj->d.data[data.data() + 2 * i])) {
3243 if (ok != nullptr)
3244 *ok = true;
3245 return mobj->d.data[data.data() + 2 * i + 1];
3246 }
3247 }
3248 return -1;
3249}
3250
3259const char *QMetaEnum::valueToKey(int value) const
3260{
3261 if (!mobj)
3262 return nullptr;
3263 for (int i = 0; i < int(data.keyCount()); ++i)
3264 if (value == (int)mobj->d.data[data.data() + 2 * i + 1])
3265 return rawStringData(mobj, mobj->d.data[data.data() + 2 * i]);
3266 return nullptr;
3267}
3268
3269static bool parseEnumFlags(QByteArrayView v, QVarLengthArray<QByteArrayView, 10> &list)
3270{
3271 v = v.trimmed();
3272 if (v.empty()) {
3273 qWarning("QMetaEnum::keysToValue: empty keys string.");
3274 return false;
3275 }
3276
3277 qsizetype sep = v.indexOf('|', 0);
3278 if (sep == 0) {
3279 qWarning("QMetaEnum::keysToValue: malformed keys string, starts with '|', \"%s\"",
3280 v.constData());
3281 return false;
3282 }
3283
3284 if (sep == -1) { // One flag
3285 list.push_back(v);
3286 return true;
3287 }
3288
3289 if (v.endsWith('|')) {
3290 qWarning("QMetaEnum::keysToValue: malformed keys string, ends with '|', \"%s\"",
3291 v.constData());
3292 return false;
3293 }
3294
3295 const auto begin = v.begin();
3296 const auto end = v.end();
3297 auto b = begin;
3298 for (; b != end && sep != -1; sep = v.indexOf('|', sep)) {
3299 list.push_back({b, begin + sep});
3300 ++sep; // Skip over '|'
3301 b = begin + sep;
3302 if (*b == '|') {
3303 qWarning("QMetaEnum::keysToValue: malformed keys string, has two consecutive '|': "
3304 "\"%s\"", v.constData());
3305 return false;
3306 }
3307 }
3308
3309 // The rest of the string
3310 list.push_back({b, end});
3311 return true;
3312}
3313
3324int QMetaEnum::keysToValue(const char *keys, bool *ok) const
3325{
3326 if (ok != nullptr)
3327 *ok = false;
3328 if (!mobj || !keys)
3329 return -1;
3330
3331 auto lookup = [&] (QByteArrayView key) -> std::optional<int> {
3332 for (int i = data.keyCount() - 1; i >= 0; --i) {
3333 if (key == stringDataView(mobj, mobj->d.data[data.data() + 2*i]))
3334 return mobj->d.data[data.data() + 2*i + 1];
3335 }
3336 return std::nullopt;
3337 };
3338
3339 int value = 0;
3340 QVarLengthArray<QByteArrayView, 10> list;
3341 const bool r = parseEnumFlags(QByteArrayView{keys}, list);
3342 if (!r)
3343 return -1;
3344 for (const auto &untrimmed : list) {
3345 const auto parsed = parse_scope(untrimmed.trimmed());
3346 if (parsed.scope && !isScopeMatch(*parsed.scope, this))
3347 return -1; // wrong type name in qualified name
3348 if (auto thisValue = lookup(parsed.key))
3349 value |= *thisValue;
3350 else
3351 return -1; // no such enumerator
3352 }
3353 if (ok != nullptr)
3354 *ok = true;
3355 return value;
3356}
3357
3358namespace
3359{
3360template <typename String, typename Container, typename Separator>
3361void join_reversed(String &s, const Container &c, Separator sep)
3362{
3363 if (c.empty())
3364 return;
3365 qsizetype len = qsizetype(c.size()) - 1; // N - 1 separators
3366 for (auto &e : c)
3367 len += qsizetype(e.size()); // N parts
3368 s.reserve(len);
3369 bool first = true;
3370 for (auto rit = c.rbegin(), rend = c.rend(); rit != rend; ++rit) {
3371 const auto &e = *rit;
3372 if (!first)
3373 s.append(sep);
3374 first = false;
3375 s.append(e.data(), e.size());
3376 }
3377}
3378} // unnamed namespace
3379
3387{
3389 if (!mobj)
3390 return keys;
3391 QVarLengthArray<QByteArrayView, sizeof(int) * CHAR_BIT> parts;
3392 int v = value;
3393 // reverse iterate to ensure values like Qt::Dialog=0x2|Qt::Window are processed first.
3394 for (int i = data.keyCount() - 1; i >= 0; --i) {
3395 int k = mobj->d.data[data.data() + 2 * i + 1];
3396 if ((k != 0 && (v & k) == k) || (k == value)) {
3397 v = v & ~k;
3398 parts.push_back(stringDataView(mobj, mobj->d.data[data.data() + 2 * i]));
3399 }
3400 }
3401 join_reversed(keys, parts, '|');
3402 return keys;
3403}
3404
3408QMetaEnum::QMetaEnum(const QMetaObject *mobj, int index)
3409 : mobj(mobj), data({ mobj->d.data + priv(mobj->d.data)->enumeratorData + index * Data::Size })
3410{
3411 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->enumeratorCount);
3412}
3413
3414int QMetaEnum::Data::index(const QMetaObject *mobj) const
3415{
3416 return (d - mobj->d.data - priv(mobj->d.data)->enumeratorData) / Size;
3417}
3418
3487const char *QMetaProperty::name() const
3488{
3489 if (!mobj)
3490 return nullptr;
3491 return rawStringData(mobj, data.name());
3492}
3493
3499const char *QMetaProperty::typeName() const
3500{
3501 if (!mobj)
3502 return nullptr;
3503 // TODO: can the metatype be invalid for dynamic metaobjects?
3504 if (const auto mt = metaType(); mt.isValid())
3505 return mt.name();
3506 return typeNameFromTypeInfo(mobj, data.type()).constData();
3507}
3508
3546{
3547 if (!mobj)
3548 return {};
3549 return QMetaType(mobj->d.metaTypes[data.index(mobj)]);
3550}
3551
3552int QMetaProperty::Data::index(const QMetaObject *mobj) const
3553{
3554 return (d - mobj->d.data - priv(mobj->d.data)->propertyData) / Size;
3555}
3556
3563{
3564 if (!mobj)
3565 return -1;
3566 return data.index(mobj) + mobj->propertyOffset();
3567}
3568
3575{
3576 if (!mobj)
3577 return -1;
3578 return data.index(mobj);
3579}
3580
3592{
3593 return isEnumType() && menum.isFlag();
3594}
3595
3603{
3604 if (!mobj)
3605 return false;
3606 return (data.flags() & EnumOrFlag) && menum.name();
3607}
3608
3619{
3620 if (!mobj)
3621 return false;
3622 return (data.flags() & StdCppSet);
3623}
3624
3633{
3634 if (!mobj)
3635 return false;
3636 return (data.flags() & Alias);
3637}
3638
3639#if QT_DEPRECATED_SINCE(6, 4)
3648int QMetaProperty::registerPropertyType() const
3649{
3650 return typeId();
3651}
3652#endif
3653
3655 : mobj(mobj),
3656 data(getMetaPropertyData(mobj, index))
3657{
3658 Q_ASSERT(index >= 0 && index < priv(mobj->d.data)->propertyCount);
3659 // The code below here just resolves menum if the property is an enum type:
3661 return;
3662 QByteArrayView enum_name = typeNameFromTypeInfo(mobj, data.type());
3663 menum = mobj->enumerator(QMetaObjectPrivate::indexOfEnumerator(mobj, enum_name));
3664 if (menum.isValid())
3665 return;
3666
3667 QByteArrayView scope_name;
3668 const auto parsed = parse_scope(enum_name);
3669 if (parsed.scope) {
3670 scope_name = *parsed.scope;
3671 enum_name = parsed.key;
3672 } else {
3673 scope_name = objectClassName(mobj);
3674 }
3675
3676 const QMetaObject *scope = nullptr;
3677 if (scope_name == "Qt")
3678 scope = &Qt::staticMetaObject;
3679 else
3680 scope = QMetaObject_findMetaObject(mobj, QByteArrayView(scope_name));
3681
3682 if (scope)
3683 menum = scope->enumerator(QMetaObjectPrivate::indexOfEnumerator(scope, enum_name));
3684}
3685
3690QMetaProperty::Data QMetaProperty::getMetaPropertyData(const QMetaObject *mobj, int index)
3691{
3692 return { mobj->d.data + priv(mobj->d.data)->propertyData + index * Data::Size };
3693}
3694
3702{
3703 return menum;
3704}
3705
3713{
3714 if (!object || !mobj)
3715 return QVariant();
3716
3717 // the status variable is changed by qt_metacall to indicate what it did
3718 // this feature is currently only used by Qt D-Bus and should not be depended
3719 // upon. Don't change it without looking into QDBusAbstractInterface first
3720 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
3721 // changed: result stored directly in value
3722 int status = -1;
3724 void *argv[] = { nullptr, &value, &status };
3725 QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
3726 if (t == QMetaType::fromType<QVariant>()) {
3727 argv[0] = &value;
3728 } else {
3729 value = QVariant(t, nullptr);
3730 argv[0] = value.data();
3731 }
3732 if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall) {
3733 mobj->d.static_metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty, data.index(mobj), argv);
3734 } else {
3736 data.index(mobj) + mobj->propertyOffset(), argv);
3737 }
3738
3739 if (status != -1)
3740 return value;
3741 if (t != QMetaType::fromType<QVariant>() && argv[0] != value.data())
3742 // pointer or reference
3743 return QVariant(t, argv[0]);
3744 return value;
3745}
3746
3761bool QMetaProperty::write(QObject *object, const QVariant &value) const
3762{
3763 if (!object || !isWritable())
3764 return false;
3765 return write(object, QVariant(value));
3766}
3767
3773{
3774 if (!object || !isWritable())
3775 return false;
3776 QMetaType t(mobj->d.metaTypes[data.index(mobj)]);
3777 if (t != QMetaType::fromType<QVariant>() && t != v.metaType()) {
3778 if (isEnumType() && !t.metaObject() && v.metaType().id() == QMetaType::QString) {
3779 // Assigning a string to a property of type Q_ENUMS (instead of Q_ENUM)
3780 bool ok;
3781 if (isFlagType())
3782 v = QVariant(menum.keysToValue(v.toByteArray(), &ok));
3783 else
3784 v = QVariant(menum.keyToValue(v.toByteArray(), &ok));
3785 if (!ok)
3786 return false;
3787 } else if (!v.isValid()) {
3788 if (isResettable())
3789 return reset(object);
3790 v = QVariant(t, nullptr);
3791 } else if (!v.convert(t)) {
3792 return false;
3793 }
3794 }
3795 // the status variable is changed by qt_metacall to indicate what it did
3796 // this feature is currently only used by Qt D-Bus and should not be depended
3797 // upon. Don't change it without looking into QDBusAbstractInterface first
3798 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
3799 // changed: result stored directly in value, return the value of status
3800 int status = -1;
3801 // the flags variable is used by the declarative module to implement
3802 // interception of property writes.
3803 int flags = 0;
3804 void *argv[] = { nullptr, &v, &status, &flags };
3805 if (t == QMetaType::fromType<QVariant>())
3806 argv[0] = &v;
3807 else
3808 argv[0] = v.data();
3809 if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall)
3810 mobj->d.static_metacall(object, QMetaObject::WriteProperty, data.index(mobj), argv);
3811 else
3812 QMetaObject::metacall(object, QMetaObject::WriteProperty, data.index(mobj) + mobj->propertyOffset(), argv);
3813
3814 return status;
3815}
3816
3826{
3827 if (!object || !mobj || !isResettable())
3828 return false;
3829 void *argv[] = { nullptr };
3830 if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall)
3831 mobj->d.static_metacall(object, QMetaObject::ResetProperty, data.index(mobj), argv);
3832 else
3833 QMetaObject::metacall(object, QMetaObject::ResetProperty, data.index(mobj) + mobj->propertyOffset(), argv);
3834 return true;
3835}
3836
3847{
3849 void * argv[1] { &bindable };
3850 mobj->metacall(object, QMetaObject::BindableProperty, data.index(mobj) + mobj->propertyOffset(), argv);
3851 return bindable;
3852}
3861QVariant QMetaProperty::readOnGadget(const void *gadget) const
3862{
3863 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3864 return read(reinterpret_cast<const QObject*>(gadget));
3865}
3866
3875bool QMetaProperty::writeOnGadget(void *gadget, const QVariant &value) const
3876{
3877 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3878 return write(reinterpret_cast<QObject*>(gadget), value);
3879}
3880
3886{
3887 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3888 return write(reinterpret_cast<QObject*>(gadget), std::move(value));
3889}
3890
3901bool QMetaProperty::resetOnGadget(void *gadget) const
3902{
3903 Q_ASSERT(priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall);
3904 return reset(reinterpret_cast<QObject*>(gadget));
3905}
3906
3914{
3915 if (!mobj)
3916 return false;
3917 return data.flags() & Resettable;
3918}
3919
3926{
3927 if (!mobj)
3928 return false;
3929 return data.flags() & Readable;
3930}
3931
3939{
3940 if (!mobj)
3941 return false;
3942 return data.notifyIndex() != uint(-1);
3943}
3944
3954{
3955 int id = notifySignalIndex();
3956 if (id != -1)
3957 return mobj->method(id);
3958 else
3959 return QMetaMethod();
3960}
3961
3971{
3972 if (!mobj || data.notifyIndex() == std::numeric_limits<uint>::max())
3973 return -1;
3974 uint methodIndex = data.notifyIndex();
3975 if (!(methodIndex & IsUnresolvedSignal))
3976 return methodIndex + mobj->methodOffset();
3977 methodIndex &= ~IsUnresolvedSignal;
3978 const QByteArray signalName = stringData(mobj, methodIndex);
3979 const QMetaObject *m = mobj;
3980 // try 0-arg signal
3981 int idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(&m, signalName, 0, nullptr);
3982 if (idx >= 0)
3983 return idx + m->methodOffset();
3984 // try 1-arg signal
3985 QArgumentType argType(typeId());
3986 idx = QMetaObjectPrivate::indexOfMethodRelative<MethodSignal>(&m, signalName, 1, &argType);
3987 if (idx >= 0)
3988 return idx + m->methodOffset();
3989 qWarning("QMetaProperty::notifySignal: cannot find the NOTIFY signal %s in class %s for property '%s'",
3990 signalName.constData(), mobj->className(), name());
3991 return -1;
3992}
3993
3994// This method has been around for a while, but the documentation was marked \internal until 5.1
4002{
4003 if (!mobj)
4004 return 0;
4005 return data.revision();
4006}
4007
4015{
4016 if (!mobj)
4017 return false;
4018 return data.flags() & Writable;
4019}
4020
4028{
4029 if (!mobj)
4030 return false;
4031 return data.flags() & Designable;
4032}
4033
4041{
4042 if (!mobj)
4043 return false;
4044 return data.flags() & Scriptable;
4045}
4046
4058{
4059 if (!mobj)
4060 return false;
4061 return data.flags() & Stored;
4062}
4063
4073{
4074 if (!mobj)
4075 return false;
4076 return data.flags() & User;
4077}
4078
4087{
4088 if (!mobj)
4089 return false;
4090 return data.flags() & Constant;
4091}
4092
4101{
4102 if (!mobj)
4103 return false;
4104 return data.flags() & Final;
4105}
4106
4115{
4116 if (!mobj)
4117 return false;
4118 return data.flags() & Required;
4119}
4120
4131{
4132 if (!mobj)
4133 return false;
4134 return (data.flags() & Bindable);
4135}
4136
4176const char *QMetaClassInfo::name() const
4177{
4178 if (!mobj)
4179 return nullptr;
4180 return rawStringData(mobj, data.name());
4181}
4182
4188const char *QMetaClassInfo::value() const
4189{
4190 if (!mobj)
4191 return nullptr;
4192 return rawStringData(mobj, data.value());
4193}
4194
4289int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
4290{
4291 Q_ASSERT(local_method_index < get(mobj)->methodCount);
4292 while (QMetaMethod::fromRelativeMethodIndex(mobj, local_method_index).data.flags() & MethodCloned) {
4293 Q_ASSERT(local_method_index > 0);
4294 --local_method_index;
4295 }
4296 return local_method_index;
4297}
4298
4304QList<QByteArray> QMetaObjectPrivate::parameterTypeNamesFromSignature(const char *signature)
4305{
4306 QList<QByteArray> list;
4307 while (*signature && *signature != '(')
4308 ++signature;
4309 while (*signature && *signature != ')' && *++signature != ')') {
4310 const char *begin = signature;
4311 int level = 0;
4312 while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
4313 if (*signature == '<')
4314 ++level;
4315 else if (*signature == '>')
4316 --level;
4317 ++signature;
4318 }
4319 list += QByteArray(begin, signature - begin);
4320 }
4321 return list;
4322}
4323
bool startsWith(QByteArrayView other) const noexcept
constexpr QByteArrayView sliced(qsizetype pos) const
constexpr qsizetype size() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
Definition qbytearray.h:409
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
reference emplace_back(Args &&... args)
Definition qlist.h:683
void push_back(parameter_type t)
Definition qlist.h:675
void reserve(qsizetype size)
Definition qlist.h:753
\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...
const QMetaObject * enclosingMetaObject() const
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:19
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:36
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
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:38
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.
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:341
static QMetaType fromName(QByteArrayView name)
Returns a QMetaType matching typeName.
bool isValid() const
@ IsEnumeration
Definition qmetatype.h:407
void registerType() const
Definition qmetatype.h:465
constexpr const char * name() const
Definition qmetatype.h:2680
void(* StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **)
Definition qobject_p.h:108
\inmodule QtCore
Definition qobject.h:103
QThread * thread() const
Returns the thread in which the object lives.
Definition qobject.cpp:1598
\inmodule QtCore
Definition qsemaphore.h:18
void acquire(int n=1)
Tries to acquire n resources guarded by the semaphore.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition qstring.h:1246
static QThreadData * get2(QThread *thread)
Definition qthread_p.h:291
static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION
Definition qthread.h:149
\inmodule QtCore
Definition qproperty.h:679
\inmodule QtCore
Definition qvariant.h:65
QMTI_MUTABLE QBasicAtomicInt typeId
Definition qmetatype.h:281
QString str
[2]
auto signal
auto mo
[7]
QMetaType signature()
Combined button and popup list for selecting options.
constexpr QBindableInterface iface
Definition qproperty.h:666
std::unique_ptr< QSlotObjectBase, QSlotObjectBase::Deleter > SlotObjUniquePtr
void * HANDLE
ConnectionType
@ AutoConnection
@ BlockingQueuedConnection
@ QueuedConnection
@ DirectConnection
QString self
Definition language.cpp:58
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
AudioChannelLayoutTag tag
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)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Size(name)
#define qWarning
Definition qlogging.h:166
return ret
static QByteArrayView objectClassName(const QMetaObject *m)
static QByteArrayView stringDataView(const QMetaObject *mo, int index)
static bool isScopeMatch(QByteArrayView scope, const QMetaEnum *e)
static QByteArray stringData(const QMetaObject *mo, int index)
static void argumentTypesFromString(const char *str, const char *end, QArgumentTypeArray &types)
static char * qNormalizeType(char *d, int &templdepth, QByteArray &result)
static auto parse_scope(QByteArrayView qualifiedKey) noexcept
static const char * rawStringData(const QMetaObject *mo, int index)
static int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo)
static const QMetaObject * QMetaObject_findMetaObject(const QMetaObject *self, QByteArrayView name)
static const QMetaObjectPrivate * priv(const uint *data)
@ MaximumParamCount
static Q_DECL_COLD_FUNCTION bool printMethodNotFoundWarning(const QMetaObject *meta, QByteArrayView name, qsizetype paramCount, const char *const *names, const QtPrivate::QMetaTypeInterface *const *metaTypes)
#define ASSERT_NOT_PRIMITIVE_TYPE(TYPE, METATYPEID, NAME)
static bool parseEnumFlags(QByteArrayView v, QVarLengthArray< QByteArrayView, 10 > &list)
static void qRemoveWhitespace(const char *s, char *d)
static QByteArrayView typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
@ 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
const char * typeName
#define QT_FOR_EACH_STATIC_PRIMITIVE_NON_VOID_TYPE(F)
Definition qmetatype.h:47
GLboolean GLboolean GLboolean b
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]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLenum target
GLbitfield flags
GLuint start
GLenum const GLint * param
GLenum GLuint GLintptr offset
GLenum GLuint GLsizei propCount
GLuint name
GLint first
GLfloat n
void ** params
struct _cl_event * event
GLhandleARB obj
[2]
GLdouble s
[6]
Definition qopenglext.h:235
GLboolean reset
const GLubyte * c
GLuint GLuint * names
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]
GLfloat GLfloat p
[1]
GLenum GLsizei len
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
static constexpr QChar sep
#define s2
#define Q_UNUSED(x)
#define QT_VERSION_CHECK(major, minor, patch)
#define QT_VERSION
unsigned int quint32
Definition qtypes.h:50
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
bool testFlag(MaskType mask, FlagType flag)
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:480
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 int indexOfEnumerator(const QMetaObject *m, QByteArrayView name, Which which)
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)
\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.