diff options
Diffstat (limited to 'src/corelib/kernel/qmetaobject.cpp')
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 236 |
1 files changed, 92 insertions, 144 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 62e626b187..7429f5a323 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -154,20 +154,29 @@ QT_BEGIN_NAMESPACE static inline const QMetaObjectPrivate *priv(const uint* data) { return reinterpret_cast<const QMetaObjectPrivate*>(data); } +static inline const char *rawStringData(const QMetaObject *mo, int index) +{ + Q_ASSERT(priv(mo->d.data)->revision >= 7); + uint offset = mo->d.stringdata[2*index]; + return reinterpret_cast<const char *>(mo->d.stringdata) + offset; +} + static inline const QByteArray stringData(const QMetaObject *mo, int index) { Q_ASSERT(priv(mo->d.data)->revision >= 7); - const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo->d.stringdata[index]) }; - Q_ASSERT(data.ptr->ref.isStatic()); - Q_ASSERT(data.ptr->alloc == 0); - Q_ASSERT(data.ptr->capacityReserved == 0); - Q_ASSERT(data.ptr->size >= 0); - return data; + uint offset = mo->d.stringdata[2*index]; + uint length = mo->d.stringdata[2*index + 1]; + const char *string = reinterpret_cast<const char *>(mo->d.stringdata) + offset; + return QByteArray::fromRawData(string, length); } -static inline const char *rawStringData(const QMetaObject *mo, int index) +static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo) { - return stringData(mo, index).data(); + if (typeInfo & IsUnresolvedType) { + return rawStringData(mo, typeInfo & TypeNameIndexMask); + } else { + return QMetaType::typeName(typeInfo); + } } static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo) @@ -181,16 +190,11 @@ static inline QByteArray typeNameFromTypeInfo(const QMetaObject *mo, uint typeIn } } -static inline const char *rawTypeNameFromTypeInfo(const QMetaObject *mo, uint typeInfo) -{ - return typeNameFromTypeInfo(mo, typeInfo).constData(); -} - static inline int typeFromTypeInfo(const QMetaObject *mo, uint typeInfo) { if (!(typeInfo & IsUnresolvedType)) return typeInfo; - return QMetaType::type(stringData(mo, typeInfo & TypeNameIndexMask)); + return QMetaType::type(rawStringData(mo, typeInfo & TypeNameIndexMask)); } class QMetaMethodPrivate : public QMetaMethod @@ -577,7 +581,7 @@ static bool methodMatch(const QMetaObject *m, int handle, if (int(m->d.data[handle + 1]) != argc) return false; - if (stringData(m, m->d.data[handle]) != name) + if (rawStringData(m, m->d.data[handle]) != name) return false; int paramsIndex = m->d.data[handle + 2] + 1; @@ -682,7 +686,9 @@ static void argumentTypesFromString(const char *str, const char *end, --level; ++str; } - types += QArgumentType(QByteArray(begin, str - begin)); + QByteArray argType(begin, str - begin); + argType.replace("QList<", "QVector<"); + types += QArgumentType(std::move(argType)); } } @@ -1161,7 +1167,7 @@ QMetaProperty QMetaObject::property(int index) const const QMetaObject *scope = nullptr; if (qstrcmp(scope_name, "Qt") == 0) - scope = &QObject::staticQtMetaObject; + scope = &Qt::staticMetaObject; else scope = QMetaObject_findMetaObject(this, scope_name); if (scope) @@ -1309,17 +1315,7 @@ static char *qNormalizeType(char *d, int &templdepth, QByteArray &result) */ QByteArray QMetaObject::normalizedType(const char *type) { - QByteArray result; - - if (!type || !*type) - return result; - - QVarLengthArray<char> stackbuf(qstrlen(type) + 1); - qRemoveWhitespace(type, stackbuf.data()); - int templdepth = 0; - qNormalizeType(stackbuf.data(), templdepth, result); - - return result; + return normalizeTypeInternal(type, type + qstrlen(type)); } /*! @@ -2837,10 +2833,6 @@ QByteArray QMetaEnum::valueToKeys(int value) const The enum needs to be declared with Q_ENUM. */ -static QByteArray qualifiedName(const QMetaEnum &e) -{ - return QByteArray(e.scope()) + "::" + e.name(); -} /*! \class QMetaProperty @@ -2931,65 +2923,45 @@ const char *QMetaProperty::typeName() const Returns this property's type. The return value is one of the values of the QVariant::Type enumeration. - \sa userType(), typeName(), name() + \sa userType(), typeName(), name(), metaType() */ QVariant::Type QMetaProperty::type() const { - if (!mobj) - return QVariant::Invalid; - int handle = priv(mobj->d.data)->propertyData + 3*idx; - - Q_ASSERT(priv(mobj->d.data)->revision >= 7); - uint type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]); + uint type = userType(); if (type >= QMetaType::User) return QVariant::UserType; - if (type != QMetaType::UnknownType) - return QVariant::Type(type); - if (isEnumType()) { - int enumMetaTypeId = QMetaType::type(qualifiedName(menum)); - if (enumMetaTypeId == QMetaType::UnknownType) - return QVariant::Int; - } -#ifdef QT_COORD_TYPE - // qreal metatype must be resolved at runtime. - if (strcmp(typeName(), "qreal") == 0) - return QVariant::Type(qMetaTypeId<qreal>()); -#endif - - return QVariant::UserType; + return QVariant::Type(type); } /*! \since 4.2 Returns this property's user type. The return value is one - of the values that are registered with QMetaType, or QMetaType::UnknownType if - the type is not registered. + of the values that are registered with QMetaType. + + This is equivalent to metaType().id() - \sa type(), QMetaType, typeName() + \sa type(), QMetaType, typeName(), metaType() */ int QMetaProperty::userType() const { if (!mobj) return QMetaType::UnknownType; - Q_ASSERT(priv(mobj->d.data)->revision >= 7); - int handle = priv(mobj->d.data)->propertyData + 3*idx; - int type = typeFromTypeInfo(mobj, mobj->d.data[handle + 1]); - if (type != QMetaType::UnknownType) - return type; - if (isEnumType()) { - type = QMetaType::type(qualifiedName(menum)); - if (type == QMetaType::UnknownType) { - type = registerPropertyType(); - if (type == QMetaType::UnknownType) - return QMetaType::Int; // Match behavior of QMetaType::type() - } - return type; - } - type = QMetaType::type(typeName()); - if (type != QMetaType::UnknownType) - return type; - return registerPropertyType(); + return QMetaType(mobj->d.metaTypes[idx]).id(); +} + +/*! + \since 6.0 + + Returns this property's QMetaType. + + \sa QMetaType + */ +QMetaType QMetaProperty::metaType() const +{ + if (!mobj) + return {}; + return QMetaType(mobj->d.metaTypes[idx]); } /*! @@ -3100,37 +3072,6 @@ QVariant QMetaProperty::read(const QObject *object) const if (!object || !mobj) return QVariant(); - uint t = QMetaType::Int; - if (isEnumType()) { - /* - try to create a QVariant that can be converted to this enum - type (only works if the enum has already been registered - with QMetaType) - */ - int enumMetaTypeId = QMetaType::type(qualifiedName(menum)); - if (enumMetaTypeId != QMetaType::UnknownType) - t = enumMetaTypeId; - } else { - int handle = priv(mobj->d.data)->propertyData + 3*idx; - const char *typeName = nullptr; - Q_ASSERT(priv(mobj->d.data)->revision >= 7); - uint typeInfo = mobj->d.data[handle + 1]; - if (!(typeInfo & IsUnresolvedType)) - t = typeInfo; - else { - typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask); - t = QMetaType::type(typeName); - } - if (t == QMetaType::UnknownType) { - // Try to register the type and try again before reporting an error. - t = registerPropertyType(); - if (t == QMetaType::UnknownType) { - qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name()); - return QVariant(); - } - } - } - // the status variable is changed by qt_metacall to indicate what it did // this feature is currently only used by Qt D-Bus and should not be depended // upon. Don't change it without looking into QDBusAbstractInterface first @@ -3139,10 +3080,11 @@ QVariant QMetaProperty::read(const QObject *object) const int status = -1; QVariant value; void *argv[] = { nullptr, &value, &status }; - if (t == QMetaType::QVariant) { + QMetaType t(mobj->d.metaTypes[idx]); + if (t == QMetaType::fromType<QVariant>()) { argv[0] = &value; } else { - value = QVariant(t, (void*)nullptr); + value = QVariant(t, nullptr); argv[0] = value.data(); } if (priv(mobj->d.data)->flags & PropertyAccessInStaticMetaCall && mobj->d.static_metacall) { @@ -3154,9 +3096,9 @@ QVariant QMetaProperty::read(const QObject *object) const if (status != -1) return value; - if (t != QMetaType::QVariant && argv[0] != value.data()) + if (t != QMetaType::fromType<QVariant>() && argv[0] != value.data()) // pointer or reference - return QVariant((QVariant::Type)t, argv[0]); + return QVariant(t, argv[0]); return value; } @@ -3177,9 +3119,10 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const return false; QVariant v = value; - uint t = QMetaType::UnknownType; - if (isEnumType()) { - if (v.userType() == QMetaType::QString) { + QMetaType t(mobj->d.metaTypes[idx]); + if (t != QMetaType::fromType<QVariant>() && t != v.metaType()) { + if (isEnumType() && !t.metaObject() && v.userType() == QMetaType::QString) { + // Assigning a string to a property of type Q_ENUMS (instead of Q_ENUM) bool ok; if (isFlagType()) v = QVariant(menum.keysToValue(value.toByteArray(), &ok)); @@ -3187,39 +3130,14 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const v = QVariant(menum.keyToValue(value.toByteArray(), &ok)); if (!ok) return false; - } else if (v.userType() != QMetaType::Int && v.userType() != QMetaType::UInt) { - int enumMetaTypeId = QMetaType::type(qualifiedName(menum)); - if ((enumMetaTypeId == QMetaType::UnknownType) || (v.userType() != enumMetaTypeId) || !v.constData()) - return false; - v = QVariant(*reinterpret_cast<const int *>(v.constData())); - } - v.convert(QMetaType::Int); - } else { - int handle = priv(mobj->d.data)->propertyData + 3*idx; - const char *typeName = nullptr; - Q_ASSERT(priv(mobj->d.data)->revision >= 7); - uint typeInfo = mobj->d.data[handle + 1]; - if (!(typeInfo & IsUnresolvedType)) - t = typeInfo; - else { - typeName = rawStringData(mobj, typeInfo & TypeNameIndexMask); - t = QMetaType::type(typeName); - if (t == QMetaType::UnknownType) - t = registerPropertyType(); - if (t == QMetaType::UnknownType) - return false; - } - if (t != QMetaType::QVariant && int(t) != value.userType()) { - if (!value.isValid()) { - if (isResettable()) - return reset(object); - v = QVariant(t, nullptr); - } else if (!v.convert(t)) { - return false; - } + } else if (!value.isValid()) { + if (isResettable()) + return reset(object); + v = QVariant(t, nullptr); + } else if (!v.convert(t.id())) { + return false; } } - // the status variable is changed by qt_metacall to indicate what it did // this feature is currently only used by Qt D-Bus and should not be depended // upon. Don't change it without looking into QDBusAbstractInterface first @@ -3230,7 +3148,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const // interception of property writes. int flags = 0; void *argv[] = { nullptr, &v, &status, &flags }; - if (t == QMetaType::QVariant) + if (t == QMetaType::fromType<QVariant>()) argv[0] = &v; else argv[0] = v.data(); @@ -3588,6 +3506,21 @@ bool QMetaProperty::isRequired() const } /*! + \since 6.0 + Returns \c true if the property is implemented using a QProperty member; otherwise returns \c false. + + This can be used to detect the availability of QProperty related meta-call types ahead of + performing the call itself. +*/ +bool QMetaProperty::isQProperty() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & IsQProperty; +} + +/*! \obsolete Returns \c true if the property is editable for the given \a object; @@ -3672,6 +3605,21 @@ const char* QMetaClassInfo::value() const } /*! + \class QMethodRawArguments + \internal + + A wrapper class for the void ** arguments array used by the meta + object system. If a slot uses a single argument of this type, + the meta object system will pass the raw arguments array directly + to the slot and set the arguments count in the slot description to + zero, so that any signal can connect to it. + + This is used internally to implement signal relay functionality in + our state machine and dbus. +*/ + + +/*! \macro QGenericArgument Q_ARG(Type, const Type &value) \relates QMetaObject |