1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qmetaobject.h"
43 #include "qmetatype.h"
46 #include <qcoreapplication.h>
47 #include <qcoreevent.h>
48 #include <qdatastream.h>
49 #include <qstringlist.h>
51 #include <qvarlengtharray.h>
55 #include <qsemaphore.h>
57 #include "private/qobject_p.h"
58 #include "private/qmetaobject_p.h"
60 // for normalizeTypeInternal
61 #include "private/qmetaobject_moc_p.h"
70 \brief The QMetaObject class contains meta-information about Qt
75 The Qt \l{Meta-Object System} in Qt is responsible for the
76 signals and slots inter-object communication mechanism, runtime
77 type information, and the Qt property system. A single
78 QMetaObject instance is created for each QObject subclass that is
79 used in an application, and this instance stores all the
80 meta-information for the QObject subclass. This object is
81 available as QObject::metaObject().
83 This class is not normally required for application programming,
84 but it is useful if you write meta-applications, such as scripting
85 engines or GUI builders.
87 The functions you are most likely to find useful are these:
89 \o className() returns the name of a class.
90 \o superClass() returns the superclass's meta-object.
91 \o method() and methodCount() provide information
92 about a class's meta-methods (signals, slots and other
93 \l{Q_INVOKABLE}{invokable} member functions).
94 \o enumerator() and enumeratorCount() and provide information about
95 a class's enumerators.
96 \o propertyCount() and property() provide information about a
98 \o constructor() and constructorCount() provide information
99 about a class's meta-constructors.
102 The index functions indexOfConstructor(), indexOfMethod(),
103 indexOfEnumerator(), and indexOfProperty() map names of constructors,
104 member functions, enumerators, or properties to indexes in the
105 meta-object. For example, Qt uses indexOfMethod() internally when you
106 connect a signal to a slot.
108 Classes can also have a list of \e{name}--\e{value} pairs of
109 additional class information, stored in QMetaClassInfo objects.
110 The number of pairs is returned by classInfoCount(), single pairs
111 are returned by classInfo(), and you can search for pairs with
114 \sa QMetaClassInfo, QMetaEnum, QMetaMethod, QMetaProperty, QMetaType,
119 \enum QMetaObject::Call
128 \value QueryPropertyDesignable
129 \value QueryPropertyScriptable
130 \value QueryPropertyStored
131 \value QueryPropertyEditable
132 \value QueryPropertyUser
133 \value CreateInstance
137 \enum QMetaMethod::Access
139 This enum describes the access level of a method, following the conventions used in C++.
146 static inline const QMetaObjectPrivate *priv(const uint* data)
147 { return reinterpret_cast<const QMetaObjectPrivate*>(data); }
149 static inline const QByteArrayData &stringData(const QMetaObject *mo, int index)
151 Q_ASSERT(priv(mo->d.data)->revision >= 7);
152 const QByteArrayData &data = mo->d.stringdata[index];
153 Q_ASSERT(data.ref.isStatic());
154 Q_ASSERT(data.alloc == 0);
155 Q_ASSERT(data.capacityReserved == 0);
156 Q_ASSERT(data.size >= 0);
160 static inline QByteArray toByteArray(const QByteArrayData &d)
162 return QByteArray(reinterpret_cast<const QStaticByteArrayData<0> &>(d));
165 static inline const char *legacyString(const QMetaObject *mo, int index)
167 Q_ASSERT(priv(mo->d.data)->revision <= 6);
168 return reinterpret_cast<const char *>(mo->d.stringdata) + index;
171 static inline const char *rawStringData(const QMetaObject *mo, int index)
173 if (priv(mo->d.data)->revision >= 7)
174 return stringData(mo, index).data();
176 return legacyString(mo, index);
179 static inline int stringSize(const QMetaObject *mo, int index)
181 if (priv(mo->d.data)->revision >= 7)
182 return stringData(mo, index).size;
184 return qstrlen(legacyString(mo, index));
187 static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
189 if (typeInfo & IsUnresolvedType) {
190 return toByteArray(stringData(mo, typeInfo & TypeNameIndexMask));
192 // ### Use the QMetaType::typeName() that returns QByteArray
193 const char *t = QMetaType::typeName(typeInfo);
194 return QByteArray::fromRawData(t, qstrlen(t));
198 static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo)
200 return typeNameFromTypeInfo(mo, typeInfo).constData();
203 static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo)
205 if (!(typeInfo & IsUnresolvedType))
207 return QMetaType::type(toByteArray(stringData(mo, typeInfo & TypeNameIndexMask)));
210 class QMetaMethodPrivate : public QMetaMethod
213 static const QMetaMethodPrivate *get(const QMetaMethod *q)
214 { return static_cast<const QMetaMethodPrivate *>(q); }
216 inline QByteArray signature() const;
217 inline QByteArray name() const;
218 inline int typesDataIndex() const;
219 inline const char *rawReturnTypeName() const;
220 inline int returnType() const;
221 inline int parameterCount() const;
222 inline int parametersDataIndex() const;
223 inline uint parameterTypeInfo(int index) const;
224 inline int parameterType(int index) const;
225 inline void getParameterTypes(int *types) const;
226 inline QList<QByteArray> parameterTypes() const;
227 inline QList<QByteArray> parameterNames() const;
228 inline QByteArray tag() const;
231 QMetaMethodPrivate();
237 Constructs a new instance of this class. You can pass up to ten arguments
238 (\a val0, \a val1, \a val2, \a val3, \a val4, \a val5, \a val6, \a val7,
239 \a val8, and \a val9) to the constructor. Returns the new object, or 0 if
240 no suitable constructor is available.
242 Note that only constructors that are declared with the Q_INVOKABLE
243 modifier are made available through the meta-object system.
245 \sa Q_ARG(), constructor()
247 QObject *QMetaObject::newInstance(QGenericArgument val0,
248 QGenericArgument val1,
249 QGenericArgument val2,
250 QGenericArgument val3,
251 QGenericArgument val4,
252 QGenericArgument val5,
253 QGenericArgument val6,
254 QGenericArgument val7,
255 QGenericArgument val8,
256 QGenericArgument val9) const
258 QByteArray constructorName = className();
260 int idx = constructorName.lastIndexOf(':');
262 constructorName.remove(0, idx+1); // remove qualified part
264 QVarLengthArray<char, 512> sig;
265 sig.append(constructorName.constData(), constructorName.length());
268 enum { MaximumParamCount = 10 };
269 const char *typeNames[] = {val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
270 val5.name(), val6.name(), val7.name(), val8.name(), val9.name()};
273 for (paramCount = 0; paramCount < MaximumParamCount; ++paramCount) {
274 int len = qstrlen(typeNames[paramCount]);
277 sig.append(typeNames[paramCount], len);
281 sig.append(')'); // no parameters
283 sig[sig.size() - 1] = ')';
286 int idx = indexOfConstructor(sig.constData());
288 QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
289 idx = indexOfConstructor(norm.constData());
294 QVariant ret(QMetaType::QObjectStar, (void*)0);
295 void *param[] = {ret.data(), val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
296 val5.data(), val6.data(), val7.data(), val8.data(), val9.data()};
298 if (static_metacall(CreateInstance, idx, param) >= 0)
300 return *reinterpret_cast<QObject**>(param[0]);
306 int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
308 const QMetaObjectExtraData *extra = reinterpret_cast<const QMetaObjectExtraData *>(d.extradata);
309 if (priv(d.data)->revision >= 6) {
310 if (!extra || !extra->static_metacall)
312 extra->static_metacall(0, cl, idx, argv);
314 } else if (priv(d.data)->revision >= 2) {
315 if (!extra || !extra->static_metacall)
317 typedef int (*OldMetacall)(QMetaObject::Call, int, void **);
318 OldMetacall o = reinterpret_cast<OldMetacall>(extra->static_metacall);
319 return o(cl, idx, argv);
327 int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
329 if (QMetaObject *mo = object->d_ptr->metaObject)
330 return static_cast<QAbstractDynamicMetaObject*>(mo)->metaCall(cl, idx, argv);
332 return object->qt_metacall(cl, idx, argv);
336 Returns the class name.
340 const char *QMetaObject::className() const
342 return rawStringData(this, 0);
346 \fn QMetaObject *QMetaObject::superClass() const
348 Returns the meta-object of the superclass, or 0 if there is no
357 Returns \a obj if object \a obj inherits from this
358 meta-object; otherwise returns 0.
360 QObject *QMetaObject::cast(QObject *obj) const
363 const QMetaObject *m = obj->metaObject();
367 } while ((m = m->d.superdata));
375 Returns \a obj if object \a obj inherits from this
376 meta-object; otherwise returns 0.
378 const QObject *QMetaObject::cast(const QObject *obj) const
381 const QMetaObject *m = obj->metaObject();
385 } while ((m = m->d.superdata));
390 #ifndef QT_NO_TRANSLATION
394 QString QMetaObject::tr(const char *s, const char *c, int n) const
396 return QCoreApplication::translate(rawStringData(this, 0), s, c, QCoreApplication::CodecForTr, n);
402 QString QMetaObject::trUtf8(const char *s, const char *c, int n) const
404 return QCoreApplication::translate(rawStringData(this, 0), s, c, QCoreApplication::UnicodeUTF8, n);
406 #endif // QT_NO_TRANSLATION
409 Returns the method offset for this class; i.e. the index position
410 of this class's first member function.
412 The offset is the sum of all the methods in the class's
413 superclasses (which is always positive since QObject has the
414 deleteLater() slot and a destroyed() signal).
416 \sa method(), methodCount(), indexOfMethod()
418 int QMetaObject::methodOffset() const
421 const QMetaObject *m = d.superdata;
423 offset += priv(m->d.data)->methodCount;
431 Returns the enumerator offset for this class; i.e. the index
432 position of this class's first enumerator.
434 If the class has no superclasses with enumerators, the offset is
435 0; otherwise the offset is the sum of all the enumerators in the
436 class's superclasses.
438 \sa enumerator(), enumeratorCount(), indexOfEnumerator()
440 int QMetaObject::enumeratorOffset() const
443 const QMetaObject *m = d.superdata;
445 offset += priv(m->d.data)->enumeratorCount;
452 Returns the property offset for this class; i.e. the index
453 position of this class's first property.
455 The offset is the sum of all the properties in the class's
456 superclasses (which is always positive since QObject has the
459 \sa property(), propertyCount(), indexOfProperty()
461 int QMetaObject::propertyOffset() const
464 const QMetaObject *m = d.superdata;
466 offset += priv(m->d.data)->propertyCount;
473 Returns the class information offset for this class; i.e. the
474 index position of this class's first class information item.
476 If the class has no superclasses with class information, the
477 offset is 0; otherwise the offset is the sum of all the class
478 information items in the class's superclasses.
480 \sa classInfo(), classInfoCount(), indexOfClassInfo()
482 int QMetaObject::classInfoOffset() const
485 const QMetaObject *m = d.superdata;
487 offset += priv(m->d.data)->classInfoCount;
496 Returns the number of constructors in this class.
498 \sa constructor(), indexOfConstructor()
500 int QMetaObject::constructorCount() const
502 if (priv(d.data)->revision < 2)
504 return priv(d.data)->constructorCount;
508 Returns the number of methods in this class, including the number of
509 properties provided by each base class. These include signals and slots
510 as well as normal member functions.
512 Use code like the following to obtain a QStringList containing the methods
513 specific to a given class:
515 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp methodCount
517 \sa method(), methodOffset(), indexOfMethod()
519 int QMetaObject::methodCount() const
521 int n = priv(d.data)->methodCount;
522 const QMetaObject *m = d.superdata;
524 n += priv(m->d.data)->methodCount;
531 Returns the number of enumerators in this class.
533 \sa enumerator(), enumeratorOffset(), indexOfEnumerator()
535 int QMetaObject::enumeratorCount() const
537 int n = priv(d.data)->enumeratorCount;
538 const QMetaObject *m = d.superdata;
540 n += priv(m->d.data)->enumeratorCount;
547 Returns the number of properties in this class, including the number of
548 properties provided by each base class.
550 Use code like the following to obtain a QStringList containing the properties
551 specific to a given class:
553 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp propertyCount
555 \sa property(), propertyOffset(), indexOfProperty()
557 int QMetaObject::propertyCount() const
559 int n = priv(d.data)->propertyCount;
560 const QMetaObject *m = d.superdata;
562 n += priv(m->d.data)->propertyCount;
569 Returns the number of items of class information in this class.
571 \sa classInfo(), classInfoOffset(), indexOfClassInfo()
573 int QMetaObject::classInfoCount() const
575 int n = priv(d.data)->classInfoCount;
576 const QMetaObject *m = d.superdata;
578 n += priv(m->d.data)->classInfoCount;
584 // Returns true if the method defined by the given meta-object&handle
585 // matches the given name, argument count and argument types, otherwise
587 static bool methodMatch(const QMetaObject *m, int handle,
588 const QByteArray &name, int argc,
589 const QArgumentType *types)
591 Q_ASSERT(priv(m->d.data)->revision >= 7);
592 if (int(m->d.data[handle + 1]) != argc)
595 if (toByteArray(stringData(m, m->d.data[handle])) != name)
598 int paramsIndex = m->d.data[handle + 2] + 1;
599 for (int i = 0; i < argc; ++i) {
600 uint typeInfo = m->d.data[paramsIndex + i];
601 if (types[i].type()) {
602 if (types[i].type() != typeFromTypeInfo(m, typeInfo))
605 if (types[i].name() != typeNameFromTypeInfo(m, typeInfo))
615 * helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within
617 * \a MethodType might be MethodSignal or MethodSlot, or 0 to match everything.
618 * \a normalizeStringData set to true if we should do a second pass for old moc generated files normalizing all the symbols.
620 template<int MethodType>
621 static inline int indexOfMethodRelative(const QMetaObject **baseObject,
623 bool normalizeStringData)
625 QByteArray methodName;
626 QArgumentTypeArray methodArgumentTypes;
627 for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {
628 int i = (MethodType == MethodSignal && priv(m->d.data)->revision >= 4)
629 ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1);
630 const int end = (MethodType == MethodSlot && priv(m->d.data)->revision >= 4)
631 ? (priv(m->d.data)->signalCount) : 0;
632 if (!normalizeStringData) {
633 for (; i >= end; --i) {
634 if (priv(m->d.data)->revision >= 7) {
635 if (methodName.isEmpty())
636 methodName = QMetaObjectPrivate::decodeMethodSignature(method, methodArgumentTypes);
637 int handle = priv(m->d.data)->methodData + 5*i;
638 if (methodMatch(m, handle, methodName, methodArgumentTypes.size(),
639 methodArgumentTypes.constData())) {
644 const char *stringdata = legacyString(m, m->d.data[priv(m->d.data)->methodData + 5*i]);
645 if (method[0] == stringdata[0] && strcmp(method + 1, stringdata + 1) == 0) {
651 } else if (priv(m->d.data)->revision < 5) {
652 for (; i >= end; --i) {
653 const char *stringdata = legacyString(m, m->d.data[priv(m->d.data)->methodData + 5 * i]);
654 const QByteArray normalizedSignature = QMetaObject::normalizedSignature(stringdata);
655 if (normalizedSignature == method) {
666 * helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within
668 * \a MethodType might be MethodSignal or MethodSlot, or 0 to match everything.
670 template<int MethodType>
671 static inline int indexOfMethodRelative(const QMetaObject **baseObject,
672 const QByteArray &name, int argc,
673 const QArgumentType *types)
675 for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {
676 Q_ASSERT(priv(m->d.data)->revision >= 7);
677 int i = (MethodType == MethodSignal)
678 ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1);
679 const int end = (MethodType == MethodSlot)
680 ? (priv(m->d.data)->signalCount) : 0;
682 for (; i >= end; --i) {
683 int handle = priv(m->d.data)->methodData + 5*i;
684 if (methodMatch(m, handle, name, argc, types)) {
697 Finds \a constructor and returns its index; otherwise returns -1.
699 Note that the \a constructor has to be in normalized form, as returned
700 by normalizedSignature().
702 \sa constructor(), constructorCount(), normalizedSignature()
704 int QMetaObject::indexOfConstructor(const char *constructor) const
706 if (priv(d.data)->revision < 2)
708 else if (priv(d.data)->revision >= 7) {
709 QArgumentTypeArray types;
710 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(constructor, types);
711 return QMetaObjectPrivate::indexOfConstructor(this, name, types.size(), types.constData());
713 for (int i = priv(d.data)->constructorCount-1; i >= 0; --i) {
714 const char *data = legacyString(this, d.data[priv(d.data)->constructorData + 5*i]);
715 if (data[0] == constructor[0] && strcmp(constructor + 1, data + 1) == 0) {
724 Finds \a method and returns its index; otherwise returns -1.
726 Note that the \a method has to be in normalized form, as returned
727 by normalizedSignature().
729 \sa method(), methodCount(), methodOffset(), normalizedSignature()
731 int QMetaObject::indexOfMethod(const char *method) const
733 const QMetaObject *m = this;
735 if (priv(m->d.data)->revision >= 7) {
736 QArgumentTypeArray types;
737 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(method, types);
738 i = indexOfMethodRelative<0>(&m, name, types.size(), types.constData());
740 i = indexOfMethodRelative<0>(&m, method, false);
743 i = indexOfMethodRelative<0>(&m, method, true);
747 i += m->methodOffset();
751 // Parses a string of comma-separated types into QArgumentTypes.
752 static void argumentTypesFromString(const char *str, const char *end,
753 QArgumentTypeArray &types)
755 Q_ASSERT(str <= end);
757 if (!types.isEmpty())
759 const char *begin = str;
761 while (str != end && (level > 0 || *str != ',')) {
764 else if (*str == '>')
768 types += QArgumentType(QByteArray(begin, str - begin));
772 // Given a method \a signature (e.g. "foo(int,double)"), this function
773 // populates the argument \a types array and returns the method name.
774 QByteArray QMetaObjectPrivate::decodeMethodSignature(
775 const char *signature, QArgumentTypeArray &types)
777 const char *lparens = strchr(signature, '(');
780 const char *rparens = strchr(lparens + 1, ')');
781 if (!rparens || *(rparens+1))
783 int nameLength = lparens - signature;
784 argumentTypesFromString(lparens + 1, rparens, types);
785 return QByteArray::fromRawData(signature, nameLength);
789 Finds \a signal and returns its index; otherwise returns -1.
791 This is the same as indexOfMethod(), except that it will return
792 -1 if the method exists but isn't a signal.
794 Note that the \a signal has to be in normalized form, as returned
795 by normalizedSignature().
797 \sa indexOfMethod(), normalizedSignature(), method(), methodCount(), methodOffset()
799 int QMetaObject::indexOfSignal(const char *signal) const
801 const QMetaObject *m = this;
803 if (priv(m->d.data)->revision >= 7) {
804 QArgumentTypeArray types;
805 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(signal, types);
806 i = QMetaObjectPrivate::indexOfSignalRelative(&m, name, types.size(), types.constData());
808 i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, false);
811 i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, true);
815 i += m->methodOffset();
821 Same as QMetaObject::indexOfSignal, but the result is the local offset to the base object.
823 \a baseObject will be adjusted to the enclosing QMetaObject, or 0 if the signal is not found
825 int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
827 bool normalizeStringData)
829 int i = indexOfMethodRelative<MethodSignal>(baseObject, signal, normalizeStringData);
831 const QMetaObject *m = *baseObject;
832 if (i >= 0 && m && m->d.superdata) {
833 int conflict = m->d.superdata->indexOfMethod(signal);
835 qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
836 signal, rawStringData(m->d.superdata, 0), rawStringData(m, 0));
843 Same as QMetaObject::indexOfSignal, but the result is the local offset to the base object.
845 \a baseObject will be adjusted to the enclosing QMetaObject, or 0 if the signal is not found
847 int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
848 const QByteArray &name, int argc,
849 const QArgumentType *types)
851 int i = indexOfMethodRelative<MethodSignal>(baseObject, name, argc, types);
853 const QMetaObject *m = *baseObject;
854 if (i >= 0 && m && m->d.superdata) {
855 int conflict = indexOfMethod(m->d.superdata, name, argc, types);
857 QMetaMethod conflictMethod = m->d.superdata->method(conflict);
858 qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
859 conflictMethod.methodSignature().constData(),
860 rawStringData(m->d.superdata, 0), rawStringData(m, 0));
868 Finds \a slot and returns its index; otherwise returns -1.
870 This is the same as indexOfMethod(), except that it will return
871 -1 if the method exists but isn't a slot.
873 \sa indexOfMethod(), method(), methodCount(), methodOffset()
875 int QMetaObject::indexOfSlot(const char *slot) const
877 const QMetaObject *m = this;
879 if (priv(m->d.data)->revision >= 7) {
880 QArgumentTypeArray types;
881 QByteArray name = QMetaObjectPrivate::decodeMethodSignature(slot, types);
882 i = QMetaObjectPrivate::indexOfSlotRelative(&m, name, types.size(), types.constData());
884 i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, false);
886 i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, true);
889 i += m->methodOffset();
893 // same as indexOfSignalRelative but for slots.
894 int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m,
896 bool normalizeStringData)
898 return indexOfMethodRelative<MethodSlot>(m, slot, normalizeStringData);
901 // same as indexOfSignalRelative but for slots.
902 int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m,
903 const QByteArray &name, int argc,
904 const QArgumentType *types)
906 return indexOfMethodRelative<MethodSlot>(m, name, argc, types);
909 int QMetaObjectPrivate::indexOfSignal(const QMetaObject *m, const QByteArray &name,
910 int argc, const QArgumentType *types)
912 int i = indexOfSignalRelative(&m, name, argc, types);
914 i += m->methodOffset();
918 int QMetaObjectPrivate::indexOfSlot(const QMetaObject *m, const QByteArray &name,
919 int argc, const QArgumentType *types)
921 int i = indexOfSlotRelative(&m, name, argc, types);
923 i += m->methodOffset();
927 int QMetaObjectPrivate::indexOfMethod(const QMetaObject *m, const QByteArray &name,
928 int argc, const QArgumentType *types)
930 int i = indexOfMethodRelative<0>(&m, name, argc, types);
932 i += m->methodOffset();
936 int QMetaObjectPrivate::indexOfConstructor(const QMetaObject *m, const QByteArray &name,
937 int argc, const QArgumentType *types)
939 for (int i = priv(m->d.data)->constructorCount-1; i >= 0; --i) {
940 int handle = priv(m->d.data)->constructorData + 5*i;
941 if (methodMatch(m, handle, name, argc, types))
950 Returns true if the \a signalTypes and \a methodTypes are
951 compatible; otherwise returns false.
953 bool QMetaObjectPrivate::checkConnectArgs(int signalArgc, const QArgumentType *signalTypes,
954 int methodArgc, const QArgumentType *methodTypes)
956 if (signalArgc < methodArgc)
958 for (int i = 0; i < methodArgc; ++i) {
959 if (signalTypes[i] != methodTypes[i])
968 Returns true if the \a signal and \a method arguments are
969 compatible; otherwise returns false.
971 bool QMetaObjectPrivate::checkConnectArgs(const QMetaMethodPrivate *signal,
972 const QMetaMethodPrivate *method)
974 if (signal->methodType() != QMetaMethod::Signal)
976 if (signal->parameterCount() < method->parameterCount())
978 const QMetaObject *smeta = signal->enclosingMetaObject();
979 const QMetaObject *rmeta = method->enclosingMetaObject();
980 for (int i = 0; i < method->parameterCount(); ++i) {
981 uint sourceTypeInfo = signal->parameterTypeInfo(i);
982 uint targetTypeInfo = method->parameterTypeInfo(i);
983 if ((sourceTypeInfo & IsUnresolvedType)
984 || (targetTypeInfo & IsUnresolvedType)) {
985 QByteArray sourceName = typeNameFromTypeInfo(smeta, sourceTypeInfo);
986 QByteArray targetName = typeNameFromTypeInfo(rmeta, targetTypeInfo);
987 if (sourceName != targetName)
990 int sourceType = typeFromTypeInfo(smeta, sourceTypeInfo);
991 int targetType = typeFromTypeInfo(rmeta, targetTypeInfo);
992 if (sourceType != targetType)
999 static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
1002 if (strcmp(rawStringData(self, 0), name) == 0)
1004 if (self->d.extradata) {
1005 const QMetaObject **e;
1006 if (priv(self->d.data)->revision < 2) {
1007 e = (const QMetaObject**)(self->d.extradata);
1010 const QMetaObjectExtraData *extra = (const QMetaObjectExtraData*)(self->d.extradata);
1015 if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name))
1021 self = self->d.superdata;
1027 Finds enumerator \a name and returns its index; otherwise returns
1030 \sa enumerator(), enumeratorCount(), enumeratorOffset()
1032 int QMetaObject::indexOfEnumerator(const char *name) const
1034 const QMetaObject *m = this;
1036 const QMetaObjectPrivate *d = priv(m->d.data);
1037 for (int i = d->enumeratorCount - 1; i >= 0; --i) {
1038 const char *prop = rawStringData(m, m->d.data[d->enumeratorData + 4*i]);
1039 if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
1040 i += m->enumeratorOffset();
1050 Finds property \a name and returns its index; otherwise returns
1053 \sa property(), propertyCount(), propertyOffset()
1055 int QMetaObject::indexOfProperty(const char *name) const
1057 const QMetaObject *m = this;
1059 const QMetaObjectPrivate *d = priv(m->d.data);
1060 for (int i = d->propertyCount-1; i >= 0; --i) {
1061 const char *prop = rawStringData(m, m->d.data[d->propertyData + 3*i]);
1062 if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
1063 i += m->propertyOffset();
1070 if (priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)) {
1071 QAbstractDynamicMetaObject *me =
1072 const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
1074 return me->createProperty(name, 0);
1081 Finds class information item \a name and returns its index;
1082 otherwise returns -1.
1084 \sa classInfo(), classInfoCount(), classInfoOffset()
1086 int QMetaObject::indexOfClassInfo(const char *name) const
1089 const QMetaObject *m = this;
1090 while (m && i < 0) {
1091 for (i = priv(m->d.data)->classInfoCount-1; i >= 0; --i)
1092 if (strcmp(name, rawStringData(m, m->d.data[priv(m->d.data)->classInfoData + 2*i])) == 0) {
1093 i += m->classInfoOffset();
1104 Returns the meta-data for the constructor with the given \a index.
1106 \sa constructorCount(), newInstance()
1108 QMetaMethod QMetaObject::constructor(int index) const
1112 if (priv(d.data)->revision >= 2 && i >= 0 && i < priv(d.data)->constructorCount) {
1114 result.handle = priv(d.data)->constructorData + 5*i;
1120 Returns the meta-data for the method with the given \a index.
1122 \sa methodCount(), methodOffset(), indexOfMethod()
1124 QMetaMethod QMetaObject::method(int index) const
1127 i -= methodOffset();
1128 if (i < 0 && d.superdata)
1129 return d.superdata->method(index);
1132 if (i >= 0 && i < priv(d.data)->methodCount) {
1134 result.handle = priv(d.data)->methodData + 5*i;
1140 Returns the meta-data for the enumerator with the given \a index.
1142 \sa enumeratorCount(), enumeratorOffset(), indexOfEnumerator()
1144 QMetaEnum QMetaObject::enumerator(int index) const
1147 i -= enumeratorOffset();
1148 if (i < 0 && d.superdata)
1149 return d.superdata->enumerator(index);
1152 if (i >= 0 && i < priv(d.data)->enumeratorCount) {
1154 result.handle = priv(d.data)->enumeratorData + 4*i;
1160 Returns the meta-data for the property with the given \a index.
1161 If no such property exists, a null QMetaProperty is returned.
1163 \sa propertyCount(), propertyOffset(), indexOfProperty()
1165 QMetaProperty QMetaObject::property(int index) const
1168 i -= propertyOffset();
1169 if (i < 0 && d.superdata)
1170 return d.superdata->property(index);
1172 QMetaProperty result;
1173 if (i >= 0 && i < priv(d.data)->propertyCount) {
1174 int handle = priv(d.data)->propertyData + 3*i;
1175 int flags = d.data[handle + 2];
1177 result.handle = handle;
1180 if (flags & EnumOrFlag) {
1182 if (priv(d.data)->revision >= 7)
1183 type = rawTypeNameFromTypeInfo(this, d.data[handle + 1]);
1185 type = legacyString(this, d.data[handle + 1]);
1186 result.menum = enumerator(indexOfEnumerator(type));
1187 if (!result.menum.isValid()) {
1188 const char *enum_name = type;
1189 const char *scope_name = rawStringData(this, 0);
1190 char *scope_buffer = 0;
1192 const char *colon = strrchr(enum_name, ':');
1193 // ':' will always appear in pairs
1194 Q_ASSERT(colon <= enum_name || *(colon-1) == ':');
1195 if (colon > enum_name) {
1196 int len = colon-enum_name-1;
1197 scope_buffer = (char *)malloc(len+1);
1198 qMemCopy(scope_buffer, enum_name, len);
1199 scope_buffer[len] = '\0';
1200 scope_name = scope_buffer;
1201 enum_name = colon+1;
1204 const QMetaObject *scope = 0;
1205 if (qstrcmp(scope_name, "Qt") == 0)
1206 scope = &QObject::staticQtMetaObject;
1208 scope = QMetaObject_findMetaObject(this, scope_name);
1210 result.menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
1222 Returns the property that has the \c USER flag set to true.
1224 \sa QMetaProperty::isUser()
1226 QMetaProperty QMetaObject::userProperty() const
1228 const int propCount = propertyCount();
1229 for (int i = propCount - 1; i >= 0; --i) {
1230 const QMetaProperty prop = property(i);
1234 return QMetaProperty();
1238 Returns the meta-data for the item of class information with the
1243 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 0
1245 \sa classInfoCount(), classInfoOffset(), indexOfClassInfo()
1247 QMetaClassInfo QMetaObject::classInfo(int index) const
1250 i -= classInfoOffset();
1251 if (i < 0 && d.superdata)
1252 return d.superdata->classInfo(index);
1254 QMetaClassInfo result;
1255 if (i >= 0 && i < priv(d.data)->classInfoCount) {
1257 result.handle = priv(d.data)->classInfoData + 2*i;
1263 Returns true if the \a signal and \a method arguments are
1264 compatible; otherwise returns false.
1266 Both \a signal and \a method are expected to be normalized.
1268 \sa normalizedSignature()
1270 bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
1272 const char *s1 = signal;
1273 const char *s2 = method;
1274 while (*s1++ != '(') { } // scan to first '('
1275 while (*s2++ != '(') { }
1276 if (*s2 == ')' || qstrcmp(s1,s2) == 0) // method has no args or
1277 return true; // exact match
1278 int s1len = qstrlen(s1);
1279 int s2len = qstrlen(s2);
1280 if (s2len < s1len && strncmp(s1,s2,s2len-1)==0 && s1[s2len-1]==',')
1281 return true; // method has less args
1289 Returns true if the \a signal and \a method arguments are
1290 compatible; otherwise returns false.
1292 bool QMetaObject::checkConnectArgs(const QMetaMethod &signal,
1293 const QMetaMethod &method)
1295 return QMetaObjectPrivate::checkConnectArgs(
1296 QMetaMethodPrivate::get(&signal),
1297 QMetaMethodPrivate::get(&method));
1300 static void qRemoveWhitespace(const char *s, char *d)
1303 while (*s && is_space(*s))
1306 while (*s && !is_space(*s))
1308 while (*s && is_space(*s))
1310 if (*s && ((is_ident_char(*s) && is_ident_char(last))
1311 || ((*s == ':') && (last == '<')))) {
1318 static char *qNormalizeType(char *d, int &templdepth, QByteArray &result)
1321 while (*d && (templdepth
1322 || (*d != ',' && *d != ')'))) {
1329 if (strncmp("void", t, d - t) != 0)
1330 result += normalizeTypeInternal(t, d);
1339 Normalizes a \a type.
1341 See QMetaObject::normalizedSignature() for a description on how
1346 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 1
1348 \sa normalizedSignature()
1350 QByteArray QMetaObject::normalizedType(const char *type)
1354 if (!type || !*type)
1357 QVarLengthArray<char> stackbuf(qstrlen(type) + 1);
1358 qRemoveWhitespace(type, stackbuf.data());
1360 qNormalizeType(stackbuf.data(), templdepth, result);
1366 Normalizes the signature of the given \a method.
1368 Qt uses normalized signatures to decide whether two given signals
1369 and slots are compatible. Normalization reduces whitespace to a
1370 minimum, moves 'const' to the front where appropriate, removes
1371 'const' from value types and replaces const references with
1374 \sa checkConnectArgs(), normalizedType()
1376 QByteArray QMetaObject::normalizedSignature(const char *method)
1379 if (!method || !*method)
1381 int len = int(strlen(method));
1382 QVarLengthArray<char> stackbuf(len + 1);
1383 char *d = stackbuf.data();
1384 qRemoveWhitespace(method, d);
1386 result.reserve(len);
1391 if (argdepth == 1) {
1392 d = qNormalizeType(d, templdepth, result);
1393 if (!*d) //most likely an invalid signature.
1406 enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
1409 Invokes the \a member (a signal or a slot name) on the object \a
1410 obj. Returns true if the member could be invoked. Returns false
1411 if there is no such member or the parameters did not match.
1413 The invocation can be either synchronous or asynchronous,
1414 depending on \a type:
1417 \o If \a type is Qt::DirectConnection, the member will be invoked immediately.
1419 \o If \a type is Qt::QueuedConnection,
1420 a QEvent will be sent and the member is invoked as soon as the application
1421 enters the main event loop.
1423 \o If \a type is Qt::BlockingQueuedConnection, the method will be invoked in
1424 the same way as for Qt::QueuedConnection, except that the current thread
1425 will block until the event is delivered. Using this connection type to
1426 communicate between objects in the same thread will lead to deadlocks.
1428 \o If \a type is Qt::AutoConnection, the member is invoked
1429 synchronously if \a obj lives in the same thread as the
1430 caller; otherwise it will invoke the member asynchronously.
1433 The return value of the \a member function call is placed in \a
1434 ret. If the invocation is asynchronous, the return value cannot
1435 be evaluated. You can pass up to ten arguments (\a val0, \a val1,
1436 \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
1437 and \a val9) to the \a member function.
1439 QGenericArgument and QGenericReturnArgument are internal
1440 helper classes. Because signals and slots can be dynamically
1441 invoked, you must enclose the arguments using the Q_ARG() and
1442 Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
1443 const reference of that type; Q_RETURN_ARG() takes a type name
1444 and a non-const reference.
1446 You only need to pass the name of the signal or slot to this function,
1447 not the entire signature. For example, to asynchronously invoke
1448 the \l{QPushButton::animateClick()}{animateClick()} slot on a
1449 QPushButton, use the following code:
1451 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 2
1453 With asynchronous method invocations, the parameters must be of
1454 types that are known to Qt's meta-object system, because Qt needs
1455 to copy the arguments to store them in an event behind the
1456 scenes. If you try to use a queued connection and get the error
1459 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 3
1461 call qRegisterMetaType() to register the data type before you
1462 call invokeMethod().
1464 To synchronously invoke the \c compute(QString, int, double) slot on
1465 some arbitrary object \c obj retrieve its return value:
1467 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 4
1469 If the "compute" slot does not take exactly one QString, one int
1470 and one double in the specified order, the call will fail.
1472 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaMethod::invoke()
1474 bool QMetaObject::invokeMethod(QObject *obj,
1476 Qt::ConnectionType type,
1477 QGenericReturnArgument ret,
1478 QGenericArgument val0,
1479 QGenericArgument val1,
1480 QGenericArgument val2,
1481 QGenericArgument val3,
1482 QGenericArgument val4,
1483 QGenericArgument val5,
1484 QGenericArgument val6,
1485 QGenericArgument val7,
1486 QGenericArgument val8,
1487 QGenericArgument val9)
1492 QVarLengthArray<char, 512> sig;
1493 int len = qstrlen(member);
1496 sig.append(member, len);
1499 const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(),
1500 val4.name(), val5.name(), val6.name(), val7.name(), val8.name(),
1504 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
1505 len = qstrlen(typeNames[paramCount]);
1508 sig.append(typeNames[paramCount], len);
1511 if (paramCount == 1)
1512 sig.append(')'); // no parameters
1514 sig[sig.size() - 1] = ')';
1517 const QMetaObject *meta = obj->metaObject();
1518 int idx = meta->indexOfMethod(sig.constData());
1520 QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
1521 idx = meta->indexOfMethod(norm.constData());
1524 if (idx < 0 || idx >= meta->methodCount()) {
1525 qWarning("QMetaObject::invokeMethod: No such method %s::%s",
1526 meta->className(), sig.constData());
1529 QMetaMethod method = meta->method(idx);
1530 return method.invoke(obj, type, ret,
1531 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
1534 /*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
1535 QGenericReturnArgument ret,
1536 QGenericArgument val0 = QGenericArgument(0),
1537 QGenericArgument val1 = QGenericArgument(),
1538 QGenericArgument val2 = QGenericArgument(),
1539 QGenericArgument val3 = QGenericArgument(),
1540 QGenericArgument val4 = QGenericArgument(),
1541 QGenericArgument val5 = QGenericArgument(),
1542 QGenericArgument val6 = QGenericArgument(),
1543 QGenericArgument val7 = QGenericArgument(),
1544 QGenericArgument val8 = QGenericArgument(),
1545 QGenericArgument val9 = QGenericArgument());
1546 \overload invokeMethod()
1548 This overload always invokes the member using the connection type Qt::AutoConnection.
1551 /*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
1552 Qt::ConnectionType type,
1553 QGenericArgument val0 = QGenericArgument(0),
1554 QGenericArgument val1 = QGenericArgument(),
1555 QGenericArgument val2 = QGenericArgument(),
1556 QGenericArgument val3 = QGenericArgument(),
1557 QGenericArgument val4 = QGenericArgument(),
1558 QGenericArgument val5 = QGenericArgument(),
1559 QGenericArgument val6 = QGenericArgument(),
1560 QGenericArgument val7 = QGenericArgument(),
1561 QGenericArgument val8 = QGenericArgument(),
1562 QGenericArgument val9 = QGenericArgument())
1564 \overload invokeMethod()
1566 This overload can be used if the return value of the member is of no interest.
1570 \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
1571 QGenericArgument val0 = QGenericArgument(0),
1572 QGenericArgument val1 = QGenericArgument(),
1573 QGenericArgument val2 = QGenericArgument(),
1574 QGenericArgument val3 = QGenericArgument(),
1575 QGenericArgument val4 = QGenericArgument(),
1576 QGenericArgument val5 = QGenericArgument(),
1577 QGenericArgument val6 = QGenericArgument(),
1578 QGenericArgument val7 = QGenericArgument(),
1579 QGenericArgument val8 = QGenericArgument(),
1580 QGenericArgument val9 = QGenericArgument())
1582 \overload invokeMethod()
1584 This overload invokes the member using the connection type Qt::AutoConnection and
1585 ignores return values.
1591 \brief The QMetaMethod class provides meta-data about a member
1594 \ingroup objectmodel
1596 A QMetaMethod has a methodType(), a methodSignature(), a list of
1597 parameterTypes() and parameterNames(), a return typeName(), a
1598 tag(), and an access() specifier. You can use invoke() to invoke
1599 the method on an arbitrary QObject.
1601 \sa QMetaObject, QMetaEnum, QMetaProperty, {Qt's Property System}
1605 \enum QMetaMethod::Attributes
1609 \value Compatibility
1615 \fn bool QMetaMethod::isValid() const
1618 Returns true if this method is valid (can be introspected and
1619 invoked), otherwise returns false.
1623 \fn const QMetaObject *QMetaMethod::enclosingMetaObject() const
1628 \enum QMetaMethod::MethodType
1630 \value Method The function is a plain member function.
1631 \value Signal The function is a signal.
1632 \value Slot The function is a slot.
1633 \value Constructor The function is a constructor.
1637 \fn QMetaMethod::QMetaMethod()
1641 QByteArray QMetaMethodPrivate::signature() const
1643 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1645 result.reserve(256);
1648 QList<QByteArray> argTypes = parameterTypes();
1649 for (int i = 0; i < argTypes.size(); ++i) {
1652 result += argTypes.at(i);
1658 QByteArray QMetaMethodPrivate::name() const
1660 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1661 return toByteArray(stringData(mobj, mobj->d.data[handle]));
1664 int QMetaMethodPrivate::typesDataIndex() const
1666 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1667 return mobj->d.data[handle + 2];
1670 const char *QMetaMethodPrivate::rawReturnTypeName() const
1672 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1673 uint typeInfo = mobj->d.data[typesDataIndex()];
1674 if (typeInfo & IsUnresolvedType)
1675 return rawStringData(mobj, typeInfo & TypeNameIndexMask);
1677 if (typeInfo == QMetaType::Void) {
1678 // QMetaMethod::typeName() is documented to return an empty string
1679 // if the return type is void, but QMetaType::typeName() returns
1683 return QMetaType::typeName(typeInfo);
1687 int QMetaMethodPrivate::returnType() const
1689 return parameterType(-1);
1692 int QMetaMethodPrivate::parameterCount() const
1694 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1695 return mobj->d.data[handle + 1];
1698 int QMetaMethodPrivate::parametersDataIndex() const
1700 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1701 return typesDataIndex() + 1;
1704 uint QMetaMethodPrivate::parameterTypeInfo(int index) const
1706 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1707 return mobj->d.data[parametersDataIndex() + index];
1710 int QMetaMethodPrivate::parameterType(int index) const
1712 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1713 return typeFromTypeInfo(mobj, parameterTypeInfo(index));
1716 void QMetaMethodPrivate::getParameterTypes(int *types) const
1718 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1719 int dataIndex = parametersDataIndex();
1720 int argc = parameterCount();
1721 for (int i = 0; i < argc; ++i) {
1722 int id = typeFromTypeInfo(mobj, mobj->d.data[dataIndex++]);
1727 QList<QByteArray> QMetaMethodPrivate::parameterTypes() const
1729 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1730 QList<QByteArray> list;
1731 int argc = parameterCount();
1732 int paramsIndex = parametersDataIndex();
1733 for (int i = 0; i < argc; ++i)
1734 list += typeNameFromTypeInfo(mobj, mobj->d.data[paramsIndex + i]);
1738 QList<QByteArray> QMetaMethodPrivate::parameterNames() const
1740 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1741 QList<QByteArray> list;
1742 int argc = parameterCount();
1743 int namesIndex = parametersDataIndex() + argc;
1744 for (int i = 0; i < argc; ++i)
1745 list += toByteArray(stringData(mobj, mobj->d.data[namesIndex + i]));
1749 QByteArray QMetaMethodPrivate::tag() const
1751 Q_ASSERT(priv(mobj->d.data)->revision >= 7);
1752 return toByteArray(stringData(mobj, mobj->d.data[handle + 3]));
1758 Returns the signature of this method (e.g.,
1759 \c{setValue(double)}).
1761 \sa parameterTypes(), parameterNames()
1763 QByteArray QMetaMethod::methodSignature() const
1766 return QByteArray();
1767 if (priv(mobj->d.data)->revision >= 7) {
1768 return QMetaMethodPrivate::get(this)->signature();
1770 const char *sig = rawStringData(mobj, mobj->d.data[handle]);
1771 return QByteArray::fromRawData(sig, qstrlen(sig));
1778 Returns the name of this method.
1780 \sa methodSignature(), parameterCount()
1782 QByteArray QMetaMethod::name() const
1785 return QByteArray();
1786 return QMetaMethodPrivate::get(this)->name();
1792 Returns the return type of this method.
1794 The return value is one of the types that are registered
1795 with QMetaType, or QMetaType::UnknownType if the type is not registered.
1797 \sa parameterType(), QMetaType, typeName()
1799 int QMetaMethod::returnType() const
1802 return QMetaType::UnknownType;
1803 return QMetaMethodPrivate::get(this)->returnType();
1809 Returns the number of parameters of this method.
1811 \sa parameterType(), parameterNames()
1813 int QMetaMethod::parameterCount() const
1817 return QMetaMethodPrivate::get(this)->parameterCount();
1823 Returns the type of the parameter at the given \a index.
1825 The return value is one of the types that are registered
1826 with QMetaType, or QMetaType::UnknownType if the type is not registered.
1828 \sa parameterCount(), returnType(), QMetaType
1830 int QMetaMethod::parameterType(int index) const
1832 if (!mobj || index < 0)
1833 return QMetaType::UnknownType;
1834 if (index >= QMetaMethodPrivate::get(this)->parameterCount())
1835 return QMetaType::UnknownType;
1836 return QMetaMethodPrivate::get(this)->parameterType(index);
1843 Gets the parameter \a types of this method. The storage
1844 for \a types must be able to hold parameterCount() items.
1846 \sa parameterCount(), returnType(), parameterType()
1848 void QMetaMethod::getParameterTypes(int *types) const
1852 QMetaMethodPrivate::get(this)->getParameterTypes(types);
1856 Returns a list of parameter types.
1858 \sa parameterNames(), methodSignature()
1860 QList<QByteArray> QMetaMethod::parameterTypes() const
1863 return QList<QByteArray>();
1864 if (priv(mobj->d.data)->revision >= 7) {
1865 return QMetaMethodPrivate::get(this)->parameterTypes();
1867 return QMetaObjectPrivate::parameterTypeNamesFromSignature(
1868 legacyString(mobj, mobj->d.data[handle]));
1873 Returns a list of parameter names.
1875 \sa parameterTypes(), methodSignature()
1877 QList<QByteArray> QMetaMethod::parameterNames() const
1879 QList<QByteArray> list;
1882 if (priv(mobj->d.data)->revision >= 7) {
1883 return QMetaMethodPrivate::get(this)->parameterNames();
1885 const char *names = rawStringData(mobj, mobj->d.data[handle + 1]);
1887 // do we have one or zero arguments?
1888 const char *signature = rawStringData(mobj, mobj->d.data[handle]);
1889 while (*signature && *signature != '(')
1891 if (*++signature != ')')
1892 list += QByteArray();
1896 const char *begin = ++names;
1897 while (*names && *names != ',')
1899 list += QByteArray(begin, names - begin);
1908 Returns the return type name of this method, or an empty string if the
1909 return type is \e void.
1911 const char *QMetaMethod::typeName() const
1915 if (priv(mobj->d.data)->revision >= 7)
1916 return QMetaMethodPrivate::get(this)->rawReturnTypeName();
1918 return legacyString(mobj, mobj->d.data[handle + 2]);
1922 Returns the tag associated with this method.
1924 Tags are special macros recognized by \c moc that make it
1925 possible to add extra information about a method.
1927 Tag information can be added in the following
1928 way in the function declaration:
1931 #define THISISTESTTAG // tag text
1934 THISISTESTTAG void testFunc();
1937 and the information can be accessed by using:
1943 int functionIndex = win.metaObject()->indexOfSlot("testFunc()");
1944 QMetaMethod mm = metaObject()->method(functionIndex);
1945 qDebug() << mm.tag(); // prints THISISTESTTAG
1949 \c moc doesn't support any special tags.
1951 const char *QMetaMethod::tag() const
1955 if (priv(mobj->d.data)->revision >= 7)
1956 return QMetaMethodPrivate::get(this)->tag().constData();
1958 return legacyString(mobj, mobj->d.data[handle + 3]);
1963 int QMetaMethod::attributes() const
1967 return ((mobj->d.data[handle + 4])>>4);
1973 Returns this method's index.
1975 int QMetaMethod::methodIndex() const
1979 return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
1985 Returns the method revision if one was
1986 specified by Q_REVISION, otherwise returns 0.
1988 int QMetaMethod::revision() const
1992 if ((QMetaMethod::Access)(mobj->d.data[handle + 4] & MethodRevisioned)) {
1993 int offset = priv(mobj->d.data)->methodData
1994 + priv(mobj->d.data)->methodCount * 5
1995 + (handle - priv(mobj->d.data)->methodData) / 5;
1996 return mobj->d.data[offset];
2002 Returns the access specification of this method (private,
2003 protected, or public).
2005 Signals are always protected, meaning that you can only emit them
2006 from the class or from a subclass.
2010 QMetaMethod::Access QMetaMethod::access() const
2014 return (QMetaMethod::Access)(mobj->d.data[handle + 4] & AccessMask);
2018 Returns the type of this method (signal, slot, or method).
2022 QMetaMethod::MethodType QMetaMethod::methodType() const
2025 return QMetaMethod::Method;
2026 return (QMetaMethod::MethodType)((mobj->d.data[handle + 4] & MethodTypeMask)>>2);
2030 Invokes this method on the object \a object. Returns true if the member could be invoked.
2031 Returns false if there is no such member or the parameters did not match.
2033 The invocation can be either synchronous or asynchronous, depending on the
2037 \o If \a connectionType is Qt::DirectConnection, the member will be invoked immediately.
2039 \o If \a connectionType is Qt::QueuedConnection,
2040 a QEvent will be posted and the member is invoked as soon as the application
2041 enters the main event loop.
2043 \o If \a connectionType is Qt::AutoConnection, the member is invoked
2044 synchronously if \a object lives in the same thread as the
2045 caller; otherwise it will invoke the member asynchronously.
2048 The return value of this method call is placed in \a
2049 returnValue. If the invocation is asynchronous, the return value cannot
2050 be evaluated. You can pass up to ten arguments (\a val0, \a val1,
2051 \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
2052 and \a val9) to this method call.
2054 QGenericArgument and QGenericReturnArgument are internal
2055 helper classes. Because signals and slots can be dynamically
2056 invoked, you must enclose the arguments using the Q_ARG() and
2057 Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
2058 const reference of that type; Q_RETURN_ARG() takes a type name
2059 and a non-const reference.
2061 To asynchronously invoke the
2062 \l{QPushButton::animateClick()}{animateClick()} slot on a
2065 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 6
2067 With asynchronous method invocations, the parameters must be of
2068 types that are known to Qt's meta-object system, because Qt needs
2069 to copy the arguments to store them in an event behind the
2070 scenes. If you try to use a queued connection and get the error
2073 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 7
2075 call qRegisterMetaType() to register the data type before you
2076 call QMetaMethod::invoke().
2078 To synchronously invoke the \c compute(QString, int, double) slot on
2079 some arbitrary object \c obj retrieve its return value:
2081 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 8
2083 QMetaObject::normalizedSignature() is used here to ensure that the format
2084 of the signature is what invoke() expects. E.g. extra whitespace is
2087 If the "compute" slot does not take exactly one QString, one int
2088 and one double in the specified order, the call will fail.
2090 \warning this method will not test the validity of the arguments: \a object
2091 must be an instance of the class of the QMetaObject of which this QMetaMethod
2092 has been constructed with. The arguments must have the same type as the ones
2093 expected by the method, else, the behaviour is undefined.
2095 \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
2097 bool QMetaMethod::invoke(QObject *object,
2098 Qt::ConnectionType connectionType,
2099 QGenericReturnArgument returnValue,
2100 QGenericArgument val0,
2101 QGenericArgument val1,
2102 QGenericArgument val2,
2103 QGenericArgument val3,
2104 QGenericArgument val4,
2105 QGenericArgument val5,
2106 QGenericArgument val6,
2107 QGenericArgument val7,
2108 QGenericArgument val8,
2109 QGenericArgument val9) const
2111 if (!object || !mobj)
2114 Q_ASSERT(mobj->cast(object));
2116 // check return type
2117 if (returnValue.data()) {
2118 const char *retType = typeName();
2119 if (qstrcmp(returnValue.name(), retType) != 0) {
2120 // normalize the return value as well
2121 // the trick here is to make a function signature out of the return type
2122 // so that we can call normalizedSignature() and avoid duplicating code
2123 QByteArray unnormalized;
2124 int len = qstrlen(returnValue.name());
2126 unnormalized.reserve(len + 3);
2127 unnormalized = "_("; // the function is called "_"
2128 unnormalized.append(returnValue.name());
2129 unnormalized.append(')');
2131 QByteArray normalized = QMetaObject::normalizedSignature(unnormalized.constData());
2132 normalized.truncate(normalized.length() - 1); // drop the ending ')'
2134 if (qstrcmp(normalized.constData() + 2, retType) != 0)
2139 // check argument count (we don't allow invoking a method if given too few arguments)
2140 const char *typeNames[] = {
2154 for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
2155 if (qstrlen(typeNames[paramCount]) <= 0)
2158 int metaMethodArgumentCount = 0;
2159 if (priv(mobj->d.data)->revision >= 7) {
2160 metaMethodArgumentCount = QMetaMethodPrivate::get(this)->parameterCount();
2162 // based on QMetaObject::parameterNames()
2163 const char *names = rawStringData(mobj, mobj->d.data[handle + 1]);
2165 // do we have one or zero arguments?
2166 const char *signature = rawStringData(mobj, mobj->d.data[handle]);
2167 while (*signature && *signature != '(')
2169 if (*++signature != ')')
2170 ++metaMethodArgumentCount;
2175 while (*names && *names != ',')
2177 ++metaMethodArgumentCount;
2181 if (paramCount <= metaMethodArgumentCount)
2184 // check connection type
2185 QThread *currentThread = QThread::currentThread();
2186 QThread *objectThread = object->thread();
2187 if (connectionType == Qt::AutoConnection) {
2188 connectionType = currentThread == objectThread
2189 ? Qt::DirectConnection
2190 : Qt::QueuedConnection;
2194 if (connectionType == Qt::BlockingQueuedConnection) {
2195 connectionType = Qt::DirectConnection;
2213 // recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
2214 int idx_relative = ((handle - priv(mobj->d.data)->methodData) / 5);
2215 int idx_offset = mobj->methodOffset();
2216 QObjectPrivate::StaticMetaCallFunction callFunction =
2217 (QMetaObjectPrivate::get(mobj)->revision >= 6 && mobj->d.extradata)
2218 ? reinterpret_cast<const QMetaObjectExtraData *>(mobj->d.extradata)->static_metacall : 0;
2220 if (connectionType == Qt::DirectConnection) {
2222 callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
2225 return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, idx_relative + idx_offset, param) < 0;
2227 } else if (connectionType == Qt::QueuedConnection) {
2228 if (returnValue.data()) {
2229 qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
2230 "queued connections");
2234 int nargs = 1; // include return type
2235 void **args = (void **) malloc(paramCount * sizeof(void *));
2237 int *types = (int *) malloc(paramCount * sizeof(int));
2239 types[0] = 0; // return type
2242 for (int i = 1; i < paramCount; ++i) {
2243 types[i] = QMetaType::type(typeNames[i]);
2244 if (types[i] != QMetaType::UnknownType) {
2245 args[i] = QMetaType::create(types[i], param[i]);
2247 } else if (param[i]) {
2248 qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
2250 for (int x = 1; x < i; ++x) {
2251 if (types[x] && args[x])
2252 QMetaType::destroy(types[x], args[x]);
2260 QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
2261 0, -1, nargs, types, args));
2262 } else { // blocking queued connection
2263 #ifndef QT_NO_THREAD
2264 if (currentThread == objectThread) {
2265 qWarning("QMetaMethod::invoke: Dead lock detected in "
2266 "BlockingQueuedConnection: Receiver is %s(%p)",
2267 mobj->className(), object);
2270 QSemaphore semaphore;
2271 QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
2272 0, -1, 0, 0, param, &semaphore));
2273 semaphore.acquire();
2274 #endif // QT_NO_THREAD
2279 /*! \fn bool QMetaMethod::invoke(QObject *object,
2280 QGenericReturnArgument returnValue,
2281 QGenericArgument val0 = QGenericArgument(0),
2282 QGenericArgument val1 = QGenericArgument(),
2283 QGenericArgument val2 = QGenericArgument(),
2284 QGenericArgument val3 = QGenericArgument(),
2285 QGenericArgument val4 = QGenericArgument(),
2286 QGenericArgument val5 = QGenericArgument(),
2287 QGenericArgument val6 = QGenericArgument(),
2288 QGenericArgument val7 = QGenericArgument(),
2289 QGenericArgument val8 = QGenericArgument(),
2290 QGenericArgument val9 = QGenericArgument()) const
2293 This overload always invokes this method using the connection type Qt::AutoConnection.
2296 /*! \fn bool QMetaMethod::invoke(QObject *object,
2297 Qt::ConnectionType connectionType,
2298 QGenericArgument val0 = QGenericArgument(0),
2299 QGenericArgument val1 = QGenericArgument(),
2300 QGenericArgument val2 = QGenericArgument(),
2301 QGenericArgument val3 = QGenericArgument(),
2302 QGenericArgument val4 = QGenericArgument(),
2303 QGenericArgument val5 = QGenericArgument(),
2304 QGenericArgument val6 = QGenericArgument(),
2305 QGenericArgument val7 = QGenericArgument(),
2306 QGenericArgument val8 = QGenericArgument(),
2307 QGenericArgument val9 = QGenericArgument()) const
2311 This overload can be used if the return value of the member is of no interest.
2315 \fn bool QMetaMethod::invoke(QObject *object,
2316 QGenericArgument val0 = QGenericArgument(0),
2317 QGenericArgument val1 = QGenericArgument(),
2318 QGenericArgument val2 = QGenericArgument(),
2319 QGenericArgument val3 = QGenericArgument(),
2320 QGenericArgument val4 = QGenericArgument(),
2321 QGenericArgument val5 = QGenericArgument(),
2322 QGenericArgument val6 = QGenericArgument(),
2323 QGenericArgument val7 = QGenericArgument(),
2324 QGenericArgument val8 = QGenericArgument(),
2325 QGenericArgument val9 = QGenericArgument()) const
2329 This overload invokes this method using the
2330 connection type Qt::AutoConnection and ignores return values.
2335 \brief The QMetaEnum class provides meta-data about an enumerator.
2337 \ingroup objectmodel
2339 Use name() for the enumerator's name. The enumerator's keys (names
2340 of each enumerated item) are returned by key(); use keyCount() to find
2341 the number of keys. isFlag() returns whether the enumerator is
2342 meant to be used as a flag, meaning that its values can be combined
2343 using the OR operator.
2345 The conversion functions keyToValue(), valueToKey(), keysToValue(),
2346 and valueToKeys() allow conversion between the integer
2347 representation of an enumeration or set value and its literal
2348 representation. The scope() function returns the class scope this
2349 enumerator was declared in.
2351 \sa QMetaObject, QMetaMethod, QMetaProperty
2355 \fn bool QMetaEnum::isValid() const
2357 Returns true if this enum is valid (has a name); otherwise returns
2364 \fn const QMetaObject *QMetaEnum::enclosingMetaObject() const
2370 \fn QMetaEnum::QMetaEnum()
2375 Returns the name of the enumerator (without the scope).
2377 For example, the Qt::AlignmentFlag enumeration has \c
2378 AlignmentFlag as the name and \l Qt as the scope.
2380 \sa isValid(), scope()
2382 const char *QMetaEnum::name() const
2386 return rawStringData(mobj, mobj->d.data[handle]);
2390 Returns the number of keys.
2394 int QMetaEnum::keyCount() const
2398 return mobj->d.data[handle + 2];
2403 Returns the key with the given \a index, or 0 if no such key exists.
2405 \sa keyCount(), value(), valueToKey()
2407 const char *QMetaEnum::key(int index) const
2411 int count = mobj->d.data[handle + 2];
2412 int data = mobj->d.data[handle + 3];
2413 if (index >= 0 && index < count)
2414 return rawStringData(mobj, mobj->d.data[data + 2*index]);
2419 Returns the value with the given \a index; or returns -1 if there
2422 \sa keyCount(), key(), keyToValue()
2424 int QMetaEnum::value(int index) const
2428 int count = mobj->d.data[handle + 2];
2429 int data = mobj->d.data[handle + 3];
2430 if (index >= 0 && index < count)
2431 return mobj->d.data[data + 2*index + 1];
2437 Returns true if this enumerator is used as a flag; otherwise returns
2440 When used as flags, enumerators can be combined using the OR
2443 \sa keysToValue(), valueToKeys()
2445 bool QMetaEnum::isFlag() const
2447 return mobj && mobj->d.data[handle + 1];
2452 Returns the scope this enumerator was declared in.
2454 For example, the Qt::AlignmentFlag enumeration has \c Qt as
2455 the scope and \c AlignmentFlag as the name.
2459 const char *QMetaEnum::scope() const
2461 return mobj?rawStringData(mobj, 0) : 0;
2465 Returns the integer value of the given enumeration \a key, or -1
2466 if \a key is not defined.
2468 If \a key is not defined, *\a{ok} is set to false; otherwise
2469 *\a{ok} is set to true.
2471 For flag types, use keysToValue().
2473 \sa valueToKey(), isFlag(), keysToValue()
2475 int QMetaEnum::keyToValue(const char *key, bool *ok) const
2482 const char *qualified_key = key;
2483 const char *s = key + qstrlen(key);
2484 while (s > key && *s != ':')
2486 if (s > key && *(s-1)==':') {
2487 scope = s - key - 1;
2490 int count = mobj->d.data[handle + 2];
2491 int data = mobj->d.data[handle + 3];
2492 for (int i = 0; i < count; ++i) {
2493 if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key, rawStringData(mobj, 0), scope) == 0))
2494 && strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
2497 return mobj->d.data[data + 2*i + 1];
2504 Returns the string that is used as the name of the given
2505 enumeration \a value, or 0 if \a value is not defined.
2507 For flag types, use valueToKeys().
2509 \sa isFlag(), valueToKeys()
2511 const char* QMetaEnum::valueToKey(int value) const
2515 int count = mobj->d.data[handle + 2];
2516 int data = mobj->d.data[handle + 3];
2517 for (int i = 0; i < count; ++i)
2518 if (value == (int)mobj->d.data[data + 2*i + 1])
2519 return rawStringData(mobj, mobj->d.data[data + 2*i]);
2524 Returns the value derived from combining together the values of
2525 the \a keys using the OR operator, or -1 if \a keys is not
2526 defined. Note that the strings in \a keys must be '|'-separated.
2528 If \a key is not defined, *\a{ok} is set to false; otherwise
2529 *\a{ok} is set to true.
2531 \sa isFlag(), valueToKey(), valueToKeys()
2533 int QMetaEnum::keysToValue(const char *keys, bool *ok) const
2541 QStringList l = QString::fromLatin1(keys).split(QLatin1Char('|'));
2544 //#### TODO write proper code, do not use QStringList
2546 int count = mobj->d.data[handle + 2];
2547 int data = mobj->d.data[handle + 3];
2548 for (int li = 0; li < l.size(); ++li) {
2549 QString trimmed = l.at(li).trimmed();
2550 QByteArray qualified_key = trimmed.toLatin1();
2551 const char *key = qualified_key.constData();
2553 const char *s = key + qstrlen(key);
2554 while (s > key && *s != ':')
2556 if (s > key && *(s-1)==':') {
2557 scope = s - key - 1;
2561 for (i = count-1; i >= 0; --i)
2562 if ((!scope || (stringSize(mobj, 0) == int(scope) && strncmp(qualified_key.constData(), rawStringData(mobj, 0), scope) == 0))
2563 && strcmp(key, rawStringData(mobj, mobj->d.data[data + 2*i])) == 0) {
2564 value |= mobj->d.data[data + 2*i + 1];
2577 Returns a byte array of '|'-separated keys that represents the
2580 \sa isFlag(), valueToKey(), keysToValue()
2582 QByteArray QMetaEnum::valueToKeys(int value) const
2587 int count = mobj->d.data[handle + 2];
2588 int data = mobj->d.data[handle + 3];
2590 for(int i = 0; i < count; i++) {
2591 int k = mobj->d.data[data + 2*i + 1];
2592 if ((k != 0 && (v & k) == k ) || (k == value)) {
2594 if (!keys.isEmpty())
2596 if (priv(mobj->d.data)->revision >= 7)
2597 keys += toByteArray(stringData(mobj, mobj->d.data[data + 2*i]));
2599 keys += legacyString(mobj, mobj->d.data[data + 2*i]);
2605 static QByteArray qualifiedName(const QMetaEnum &e)
2607 return QByteArray(e.scope()) + "::" + e.name();
2611 \class QMetaProperty
2612 \brief The QMetaProperty class provides meta-data about a property.
2614 \ingroup objectmodel
2616 Property meta-data is obtained from an object's meta-object. See
2617 QMetaObject::property() and QMetaObject::propertyCount() for
2620 \section1 Property Meta-Data
2622 A property has a name() and a type(), as well as various
2623 attributes that specify its behavior: isReadable(), isWritable(),
2624 isDesignable(), isScriptable(), and isStored().
2626 If the property is an enumeration, isEnumType() returns true; if the
2627 property is an enumeration that is also a flag (i.e. its values
2628 can be combined using the OR operator), isEnumType() and
2629 isFlagType() both return true. The enumerator for these types is
2630 available from enumerator().
2632 The property's values are set and retrieved with read(), write(),
2633 and reset(); they can also be changed through QObject's set and get
2634 functions. See QObject::setProperty() and QObject::property() for
2637 \section1 Copying and Assignment
2639 QMetaProperty objects can be copied by value. However, each copy will
2640 refer to the same underlying property meta-data.
2642 \sa QMetaObject, QMetaEnum, QMetaMethod, {Qt's Property System}
2646 \fn bool QMetaProperty::isValid() const
2648 Returns true if this property is valid (readable); otherwise
2655 \fn const QMetaObject *QMetaProperty::enclosingMetaObject() const
2662 QMetaProperty::QMetaProperty()
2663 : mobj(0), handle(0), idx(0)
2669 Returns this property's name.
2671 \sa type(), typeName()
2673 const char *QMetaProperty::name() const
2677 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2678 return rawStringData(mobj, mobj->d.data[handle]);
2682 Returns the name of this property's type.
2686 const char *QMetaProperty::typeName() const
2690 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2691 if (priv(mobj->d.data)->revision >= 7)
2692 return rawTypeNameFromTypeInfo(mobj, mobj->d.data[handle + 1]);
2694 return legacyString(mobj, mobj->d.data[handle + 1]);
2698 Returns this property's type. The return value is one
2699 of the values of the QVariant::Type enumeration.
2701 \sa userType(), typeName(), name()
2703 QVariant::Type QMetaProperty::type() const
2706 return QVariant::Invalid;
2707 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2710 if (priv(mobj->d.data)->revision >= 7) {
2711 type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]);
2712 if (type >= QMetaType::User)
2713 return QVariant::UserType;
2715 uint flags = mobj->d.data[handle + 2];
2718 if (type != QMetaType::UnknownType)
2719 return QVariant::Type(type);
2721 int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
2722 if (enumMetaTypeId == QMetaType::UnknownType)
2723 return QVariant::Int;
2725 #ifdef QT_COORD_TYPE
2726 // qreal metatype must be resolved at runtime.
2727 if (strcmp(typeName(), "qreal") == 0)
2728 return QVariant::Type(qMetaTypeId<qreal>());
2731 return QVariant::UserType;
2737 Returns this property's user type. The return value is one
2738 of the values that are registered with QMetaType, or QMetaType::UnknownType if
2739 the type is not registered.
2741 \sa type(), QMetaType, typeName()
2743 int QMetaProperty::userType() const
2746 return QMetaType::UnknownType;
2747 if (priv(mobj->d.data)->revision >= 7) {
2748 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2749 int type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]);
2750 if (type != QMetaType::UnknownType)
2753 QVariant::Type tp = type();
2754 if (tp != QVariant::UserType)
2758 int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
2759 if (enumMetaTypeId == QMetaType::UnknownType)
2760 return QVariant::Int; // Match behavior of QMetaType::type()
2761 return enumMetaTypeId;
2763 return QMetaType::type(typeName());
2769 Returns this property's index.
2771 int QMetaProperty::propertyIndex() const
2775 return idx + mobj->propertyOffset();
2779 Returns true if the property's type is an enumeration value that
2780 is used as a flag; otherwise returns false.
2782 Flags can be combined using the OR operator. A flag type is
2783 implicitly also an enum type.
2785 \sa isEnumType(), enumerator(), QMetaEnum::isFlag()
2788 bool QMetaProperty::isFlagType() const
2790 return isEnumType() && menum.isFlag();
2794 Returns true if the property's type is an enumeration value;
2795 otherwise returns false.
2797 \sa enumerator(), isFlagType()
2799 bool QMetaProperty::isEnumType() const
2803 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2804 int flags = mobj->d.data[handle + 2];
2805 return (flags & EnumOrFlag) && menum.name();
2811 Returns true if the property has a C++ setter function that
2812 follows Qt's standard "name" / "setName" pattern. Designer and uic
2813 query hasStdCppSet() in order to avoid expensive
2814 QObject::setProperty() calls. All properties in Qt [should] follow
2817 bool QMetaProperty::hasStdCppSet() const
2821 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2822 int flags = mobj->d.data[handle + 2];
2823 return (flags & StdCppSet);
2827 Returns the enumerator if this property's type is an enumerator
2828 type; otherwise the returned value is undefined.
2830 \sa isEnumType(), isFlagType()
2832 QMetaEnum QMetaProperty::enumerator() const
2838 Reads the property's value from the given \a object. Returns the value
2839 if it was able to read it; otherwise returns an invalid variant.
2841 \sa write(), reset(), isReadable()
2843 QVariant QMetaProperty::read(const QObject *object) const
2845 if (!object || !mobj)
2848 uint t = QVariant::Int;
2851 try to create a QVariant that can be converted to this enum
2852 type (only works if the enum has already been registered
2855 int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
2856 if (enumMetaTypeId != QMetaType::UnknownType)
2859 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2860 const char *typeName = 0;
2861 if (priv(mobj->d.data)->revision >= 7) {
2862 uint typeInfo = mobj->d.data[handle + 1];
2863 if (!(typeInfo & IsUnresolvedType))
2866 typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask);
2867 t = QMetaType::type(typeName);
2870 uint flags = mobj->d.data[handle + 2];
2872 if (t == QMetaType::UnknownType) {
2873 typeName = legacyString(mobj, mobj->d.data[handle + 1]);
2874 t = QMetaType::type(typeName);
2875 if (t == QMetaType::UnknownType)
2876 t = QVariant::nameToType(typeName);
2879 if (t == QMetaType::UnknownType) {
2880 qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name());
2885 // the status variable is changed by qt_metacall to indicate what it did
2886 // this feature is currently only used by QtDBus and should not be depended
2887 // upon. Don't change it without looking into QDBusAbstractInterface first
2888 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
2889 // changed: result stored directly in value
2892 void *argv[] = { 0, &value, &status };
2893 if (t == QMetaType::QVariant) {
2896 value = QVariant(t, (void*)0);
2897 argv[0] = value.data();
2899 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty,
2900 idx + mobj->propertyOffset(), argv);
2904 if (t != QMetaType::QVariant && argv[0] != value.data())
2905 // pointer or reference
2906 return QVariant((QVariant::Type)t, argv[0]);
2911 Writes \a value as the property's value to the given \a object. Returns
2912 true if the write succeeded; otherwise returns false.
2914 \sa read(), reset(), isWritable()
2916 bool QMetaProperty::write(QObject *object, const QVariant &value) const
2918 if (!object || !isWritable())
2922 uint t = QVariant::Invalid;
2924 if (v.type() == QVariant::String) {
2927 v = QVariant(menum.keysToValue(value.toByteArray(), &ok));
2929 v = QVariant(menum.keyToValue(value.toByteArray(), &ok));
2932 } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
2933 int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
2934 if ((enumMetaTypeId == QMetaType::UnknownType) || (v.userType() != enumMetaTypeId) || !v.constData())
2936 v = QVariant(*reinterpret_cast<const int *>(v.constData()));
2938 v.convert(QVariant::Int);
2940 int handle = priv(mobj->d.data)->propertyData + 3*idx;
2941 const char *typeName = 0;
2942 if (priv(mobj->d.data)->revision >= 7) {
2943 uint typeInfo = mobj->d.data[handle + 1];
2944 if (!(typeInfo & IsUnresolvedType))
2947 typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask);
2948 t = QMetaType::type(typeName);
2951 uint flags = mobj->d.data[handle + 2];
2953 typeName = legacyString(mobj, mobj->d.data[handle + 1]);
2955 if (t == QMetaType::UnknownType) {
2956 const char *typeName = rawStringData(mobj, mobj->d.data[handle + 1]);
2957 const char *vtypeName = value.typeName();
2958 if (vtypeName && strcmp(typeName, vtypeName) == 0)
2959 t = value.userType();
2961 t = QVariant::nameToType(typeName);
2963 if (t == QVariant::Invalid)
2965 if (t != QMetaType::QVariant && t != (uint)value.userType() && (t < QMetaType::User && !v.convert((QVariant::Type)t)))
2969 // the status variable is changed by qt_metacall to indicate what it did
2970 // this feature is currently only used by QtDBus and should not be depended
2971 // upon. Don't change it without looking into QDBusAbstractInterface first
2972 // -1 (unchanged): normal qt_metacall, result stored in argv[0]
2973 // changed: result stored directly in value, return the value of status
2975 // the flags variable is used by the declarative module to implement
2976 // interception of property writes.
2978 void *argv[] = { 0, &v, &status, &flags };
2979 if (t == QMetaType::QVariant)
2983 QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
2988 Resets the property for the given \a object with a reset method.
2989 Returns true if the reset worked; otherwise returns false.
2991 Reset methods are optional; only a few properties support them.
2995 bool QMetaProperty::reset(QObject *object) const
2997 if (!object || !mobj || !isResettable())
2999 void *argv[] = { 0 };
3000 QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
3005 Returns true if this property can be reset to a default value; otherwise
3010 bool QMetaProperty::isResettable() const
3014 int flags = mobj->d.data[handle + 2];
3015 return flags & Resettable;
3019 Returns true if this property is readable; otherwise returns false.
3021 \sa isWritable(), read(), isValid()
3023 bool QMetaProperty::isReadable() const
3027 int flags = mobj->d.data[handle + 2];
3028 return flags & Readable;
3032 Returns true if this property has a corresponding change notify signal;
3033 otherwise returns false.
3037 bool QMetaProperty::hasNotifySignal() const
3041 int flags = mobj->d.data[handle + 2];
3042 return flags & Notify;
3048 Returns the QMetaMethod instance of the property change notifying signal if
3049 one was specified, otherwise returns an invalid QMetaMethod.
3051 \sa hasNotifySignal()
3053 QMetaMethod QMetaProperty::notifySignal() const
3055 int id = notifySignalIndex();
3057 return mobj->method(id);
3059 return QMetaMethod();
3065 Returns the index of the property change notifying signal if one was
3066 specified, otherwise returns -1.
3068 \sa hasNotifySignal()
3070 int QMetaProperty::notifySignalIndex() const
3072 if (hasNotifySignal()) {
3073 int offset = priv(mobj->d.data)->propertyData +
3074 priv(mobj->d.data)->propertyCount * 3 + idx;
3075 return mobj->d.data[offset] + mobj->methodOffset();
3084 Returns the property revision if one was
3085 specified by REVISION, otherwise returns 0.
3087 int QMetaProperty::revision() const
3091 int flags = mobj->d.data[handle + 2];
3092 if (flags & Revisioned) {
3093 int offset = priv(mobj->d.data)->propertyData +
3094 priv(mobj->d.data)->propertyCount * 3 + idx;
3095 // Revision data is placed after NOTIFY data, if present.
3096 // Iterate through properties to discover whether we have NOTIFY signals.
3097 for (int i = 0; i < priv(mobj->d.data)->propertyCount; ++i) {
3098 int handle = priv(mobj->d.data)->propertyData + 3*i;
3099 if (mobj->d.data[handle + 2] & Notify) {
3100 offset += priv(mobj->d.data)->propertyCount;
3104 return mobj->d.data[offset];
3111 Returns true if this property is writable; otherwise returns
3114 \sa isReadable(), write()
3116 bool QMetaProperty::isWritable() const
3120 int flags = mobj->d.data[handle + 2];
3121 return flags & Writable;
3126 Returns true if this property is designable for the given \a object;
3127 otherwise returns false.
3129 If no \a object is given, the function returns false if the
3130 \c{Q_PROPERTY()}'s \c DESIGNABLE attribute is false; otherwise
3131 returns true (if the attribute is true or is a function or expression).
3133 \sa isScriptable(), isStored()
3135 bool QMetaProperty::isDesignable(const QObject *object) const
3139 int flags = mobj->d.data[handle + 2];
3140 bool b = flags & Designable;
3142 void *argv[] = { &b };
3143 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable,
3144 idx + mobj->propertyOffset(), argv);
3152 Returns true if the property is scriptable for the given \a object;
3153 otherwise returns false.
3155 If no \a object is given, the function returns false if the
3156 \c{Q_PROPERTY()}'s \c SCRIPTABLE attribute is false; otherwise returns
3157 true (if the attribute is true or is a function or expression).
3159 \sa isDesignable(), isStored()
3161 bool QMetaProperty::isScriptable(const QObject *object) const
3165 int flags = mobj->d.data[handle + 2];
3166 bool b = flags & Scriptable;
3168 void *argv[] = { &b };
3169 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable,
3170 idx + mobj->propertyOffset(), argv);
3176 Returns true if the property is stored for \a object; otherwise returns
3179 If no \a object is given, the function returns false if the
3180 \c{Q_PROPERTY()}'s \c STORED attribute is false; otherwise returns
3181 true (if the attribute is true or is a function or expression).
3183 \sa isDesignable(), isScriptable()
3185 bool QMetaProperty::isStored(const QObject *object) const
3189 int flags = mobj->d.data[handle + 2];
3190 bool b = flags & Stored;
3192 void *argv[] = { &b };
3193 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored,
3194 idx + mobj->propertyOffset(), argv);
3200 Returns true if this property is designated as the \c USER
3201 property, i.e., the one that the user can edit for \a object or
3202 that is significant in some other way. Otherwise it returns
3203 false. e.g., the \c text property is the \c USER editable property
3206 If \a object is null, the function returns false if the \c
3207 {Q_PROPERTY()}'s \c USER attribute is false. Otherwise it returns
3210 \sa QMetaObject::userProperty(), isDesignable(), isScriptable()
3212 bool QMetaProperty::isUser(const QObject *object) const
3216 int flags = mobj->d.data[handle + 2];
3217 bool b = flags & User;
3219 void *argv[] = { &b };
3220 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser,
3221 idx + mobj->propertyOffset(), argv);
3228 Returns true if the property is constant; otherwise returns false.
3230 A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute
3233 bool QMetaProperty::isConstant() const
3237 int flags = mobj->d.data[handle + 2];
3238 return flags & Constant;
3243 Returns true if the property is final; otherwise returns false.
3245 A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute
3248 bool QMetaProperty::isFinal() const
3252 int flags = mobj->d.data[handle + 2];
3253 return flags & Final;
3259 Returns true if the property is editable for the given \a object;
3260 otherwise returns false.
3262 If no \a object is given, the function returns false if the
3263 \c{Q_PROPERTY()}'s \c EDITABLE attribute is false; otherwise returns
3264 true (if the attribute is true or is a function or expression).
3266 \sa isDesignable(), isScriptable(), isStored()
3268 bool QMetaProperty::isEditable(const QObject *object) const
3272 int flags = mobj->d.data[handle + 2];
3273 bool b = flags & Editable;
3275 void *argv[] = { &b };
3276 QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable,
3277 idx + mobj->propertyOffset(), argv);
3283 \class QMetaClassInfo
3285 \brief The QMetaClassInfo class provides additional information
3288 \ingroup objectmodel
3290 Class information items are simple \e{name}--\e{value} pairs that
3291 are specified using Q_CLASSINFO() in the source code. The
3292 information can be retrieved using name() and value(). For example:
3294 \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 5
3296 This mechanism is free for you to use in your Qt applications. Qt
3297 doesn't use it for any of its classes.
3304 \fn QMetaClassInfo::QMetaClassInfo()
3309 \fn const QMetaObject *QMetaClassInfo::enclosingMetaObject() const
3314 Returns the name of this item.
3318 const char *QMetaClassInfo::name() const
3322 return rawStringData(mobj, mobj->d.data[handle]);
3326 Returns the value of this item.
3330 const char* QMetaClassInfo::value() const
3334 return rawStringData(mobj, mobj->d.data[handle + 1]);
3338 \macro QGenericArgument Q_ARG(Type, const Type &value)
3339 \relates QMetaObject
3341 This macro takes a \a Type and a \a value of that type and
3342 returns a \l QGenericArgument object that can be passed to
3343 QMetaObject::invokeMethod().
3349 \macro QGenericReturnArgument Q_RETURN_ARG(Type, Type &value)
3350 \relates QMetaObject
3352 This macro takes a \a Type and a non-const reference to a \a
3353 value of that type and returns a QGenericReturnArgument object
3354 that can be passed to QMetaObject::invokeMethod().
3360 \class QGenericArgument
3362 \brief The QGenericArgument class is an internal helper class for
3363 marshalling arguments.
3365 This class should never be used directly. Please use the \l Q_ARG()
3368 \sa Q_ARG(), QMetaObject::invokeMethod(), QGenericReturnArgument
3372 \fn QGenericArgument::QGenericArgument(const char *name, const void *data)
3374 Constructs a QGenericArgument object with the given \a name and \a data.
3378 \fn QGenericArgument::data () const
3380 Returns the data set in the constructor.
3384 \fn QGenericArgument::name () const
3386 Returns the name set in the constructor.
3390 \class QGenericReturnArgument
3392 \brief The QGenericReturnArgument class is an internal helper class for
3393 marshalling arguments.
3395 This class should never be used directly. Please use the
3396 Q_RETURN_ARG() macro instead.
3398 \sa Q_RETURN_ARG(), QMetaObject::invokeMethod(), QGenericArgument
3402 \fn QGenericReturnArgument::QGenericReturnArgument(const char *name, void *data)
3404 Constructs a QGenericReturnArgument object with the given \a name
3409 If the local_method_index is a cloned method, return the index of the original.
3411 Example: if the index of "destroyed()" is passed, the index of "destroyed(QObject*)" is returned
3413 int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
3415 Q_ASSERT(local_method_index < get(mobj)->methodCount);
3416 int handle = get(mobj)->methodData + 5 * local_method_index;
3417 while (mobj->d.data[handle + 4] & MethodCloned) {
3418 Q_ASSERT(local_method_index > 0);
3420 local_method_index--;
3422 return local_method_index;
3428 Returns the parameter type names extracted from the given \a signature.
3430 QList<QByteArray> QMetaObjectPrivate::parameterTypeNamesFromSignature(const char *signature)
3432 QList<QByteArray> list;
3433 while (*signature && *signature != '(')
3435 while (*signature && *signature != ')' && *++signature != ')') {
3436 const char *begin = signature;
3438 while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
3439 if (*signature == '<')
3441 else if (*signature == '>')
3445 list += QByteArray(begin, signature - begin);