diff options
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 112 |
1 files changed, 69 insertions, 43 deletions
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 0388215630..f91ba78932 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -889,28 +889,63 @@ struct StaticQtMetaObject : public QObject { return &staticQtMetaObject; } }; -static int EnumType(const QMetaObject *metaobj, const QByteArray &str, int type) +static bool isNamedEnumerator(const QMetaObject *metaObj, const QByteArray &scopedName) { QByteArray scope; QByteArray name; - int scopeIdx = str.lastIndexOf("::"); + int scopeIdx = scopedName.lastIndexOf("::"); if (scopeIdx != -1) { - scope = str.left(scopeIdx); - name = str.mid(scopeIdx + 2); + scope = scopedName.left(scopeIdx); + name = scopedName.mid(scopeIdx + 2); } else { - name = str; + name = scopedName; } const QMetaObject *meta; if (scope == "Qt") meta = StaticQtMetaObject::get(); else - meta = metaobj; + meta = metaObj; for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { QMetaEnum m = meta->enumerator(i); if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) - return QVariant::Int; + return true; } - return type; + return false; +} + +static bool passTypeAsInt(int type) +{ + // We should not encounter the unknown type here. + // In order to check that we need extra information. + Q_ASSERT(type != QMetaType::UnknownType); + + const QMetaType::TypeFlags flags = QMetaType::typeFlags(type); + + // Cast enumerations to int. + if (flags & QMetaType::IsEnumeration) + return true; + + // Qt builtins can be handled as they are. + if (type < int(QMetaType::User)) + return false; + + // Pointers to QObjects and QGadgets can be handled as they are. + if (flags & (QMetaType::PointerToQObject | QMetaType::PointerToGadget)) + return false; + + // If it wasn't declared as metatype, better don't touch it. + if (!(flags & QMetaType::WasDeclaredAsMetaType)) + return false; + + // If it needs construction or destruction (that is, it is a structured type), + // pass as original type. + if (flags & (QMetaType::NeedsConstruction | QMetaType::NeedsDestruction)) + return false; + + // A single value that's not a pointer to a QObject or QGadget, not a builtin type, was declared + // as meta type, but we don't know it as an enumeration (although it probably is one). + // Pass as int if it fits into an int. + return QMetaType::sizeOf(type) <= int(sizeof(int)); } QQmlPropertyCacheMethodArguments *QQmlPropertyCache::createArgumentsObject(int argc, const QList<QByteArray> &names) @@ -1614,18 +1649,13 @@ int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *u propTypeName = m.typeName(); } - QMetaType::TypeFlags flags = QMetaType::typeFlags(type); - if (flags & QMetaType::IsEnumeration) { - type = QVariant::Int; - } else if (type == QMetaType::UnknownType || - (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) && - type != qMetaTypeId<QJSValue>())) { - //the UserType clause is to catch registered QFlags - type = EnumType(metaObject(), propTypeName, type); - } - if (type == QMetaType::UnknownType) { - if (unknownTypeError) *unknownTypeError = propTypeName; + if (isNamedEnumerator(metaObject(), propTypeName)) + type = QVariant::Int; + else if (unknownTypeError) + *unknownTypeError = propTypeName; + } else if (passTypeAsInt(type)) { + type = QVariant::Int; } return type; @@ -1665,20 +1695,18 @@ int *QQmlMetaObject::methodParameterTypes(int index, ArgTypeStorage *argStorage, for (int ii = 0; ii < argc; ++ii) { int type = m.parameterType(ii); - QMetaType::TypeFlags flags = QMetaType::typeFlags(type); - if (flags & QMetaType::IsEnumeration) - type = QVariant::Int; - else if (type == QMetaType::UnknownType || - (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) && - type != qMetaTypeId<QJSValue>())) { - //the UserType clause is to catch registered QFlags + if (type == QMetaType::UnknownType) { if (argTypeNames.isEmpty()) argTypeNames = m.parameterTypes(); - type = EnumType(metaObject, argTypeNames.at(ii), type); - } - if (type == QMetaType::UnknownType) { - if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); - return nullptr; + if (isNamedEnumerator(metaObject, argTypeNames.at(ii))) { + type = QVariant::Int; + } else { + if (unknownTypeError) + *unknownTypeError = argTypeNames.at(ii); + return nullptr; + } + } else if (passTypeAsInt(type)) { + type = QVariant::Int; } args->arguments[ii + 1] = type; } @@ -1704,20 +1732,18 @@ int *QQmlMetaObject::methodParameterTypes(const QMetaMethod &m, ArgTypeStorage * for (int ii = 0; ii < argc; ++ii) { int type = m.parameterType(ii); - QMetaType::TypeFlags flags = QMetaType::typeFlags(type); - if (flags & QMetaType::IsEnumeration) - type = QVariant::Int; - else if (type == QMetaType::UnknownType || - (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) && - type != qMetaTypeId<QJSValue>())) { - //the UserType clause is to catch registered QFlags) + if (type == QMetaType::UnknownType) { if (argTypeNames.isEmpty()) argTypeNames = m.parameterTypes(); - type = EnumType(_m.asT2(), argTypeNames.at(ii), type); - } - if (type == QMetaType::UnknownType) { - if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); - return nullptr; + if (isNamedEnumerator(_m.asT2(), argTypeNames.at(ii))) { + type = QVariant::Int; + } else { + if (unknownTypeError) + *unknownTypeError = argTypeNames.at(ii); + return nullptr; + } + } else if (passTypeAsInt(type)) { + type = QVariant::Int; } argStorage->operator[](ii + 1) = type; } |