aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlpropertycache.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2018-11-02 15:53:02 +0100
committerUlf Hermann <ulf.hermann@qt.io>2018-11-19 08:25:32 +0000
commit3e9b752bf4114b2b06e2f8f65aad67606dfc0215 (patch)
treec5ab9351ad3bce5e66ce9429948dd00a1986dd01 /src/qml/qml/qqmlpropertycache.cpp
parent75937c9da7910ce41b4b3207d66d844ed9624df8 (diff)
QML: Use all available type information to find enum types
Using the metatype system we can identify most enumeration types statically, without lookup by name. Only if we get UnknownType we have to do a name based lookup. As the name based lookup only checks enums that either belong to the global Qt namespace or the surrounding class, the type based lookup gives better results. Task-number: QTBUG-58454 Change-Id: Id6bd748f37838249defb4c5b2a7628eadc1a8341 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlpropertycache.cpp')
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp112
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;
}