aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4engine.cpp5
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp2
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp3
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp2
-rw-r--r--src/qml/qml/qqmlmetaobject.cpp4
-rw-r--r--src/qml/qml/qqmlproperty.cpp9
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp2
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp4
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h146
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp50
10 files changed, 211 insertions, 16 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 41c7a90906..809892dacf 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1850,7 +1850,7 @@ QV4::ReturnedValue ExecutionEngine::fromData(
}
}
- } else {
+ } else if (!(metaType.flags() & QMetaType::IsEnumeration)) {
QV4::Scope scope(this);
if (metaType == QMetaType::fromType<QQmlListReference>()) {
typedef QQmlListReferencePrivate QDLRP;
@@ -1936,9 +1936,8 @@ QV4::ReturnedValue ExecutionEngine::fromData(
// + QObjectList
// + QList<int>
- // Enumeration types can just be treated as integers for now
if (metaType.flags() & QMetaType::IsEnumeration)
- return QV4::Encode(*reinterpret_cast<const int *>(ptr));
+ return fromData(metaType.underlyingType(), ptr, container, property, flags);
return QV4::Encode(newVariantObject(metaType, ptr));
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index e2ebda7d0e..865f2af699 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -131,7 +131,7 @@ static ReturnedValue loadProperty(
return QmlListWrapper::create(v4, object, property.coreIndex(), propMetaType);
// TODO: Check all the builtin types here. See getGadgetProperty() in qqmlvaluetypewrapper.cpp
- switch (property.isEnum() ? QMetaType::Int : propMetaType.id()) {
+ switch (property.isEnum() ? propMetaType.underlyingType().id() : propMetaType.id()) {
case QMetaType::Int: {
int v = 0;
property.readProperty(object, &v);
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index ccea9cac2a..62e21a120c 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -131,7 +131,8 @@ ReturnedValue VariantPrototype::method_valueOf(const FunctionObject *b, const Va
return Encode(v.toBool());
default:
if (QMetaType(v.metaType()).flags() & QMetaType::IsEnumeration)
- return Encode(v.toInt());
+ if (v.metaType().sizeOf() <= qsizetype(sizeof(int)))
+ return Encode(v.toInt());
if (v.canConvert<double>())
return Encode(v.toDouble());
if (v.canConvert<int>())
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index da81244f18..55e21abae2 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -183,7 +183,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
if (!type.isValid())
argCount = 0;
else if (type.flags().testFlag(QMetaType::IsEnumeration))
- storage.append(QMetaType::fromType<int>());
+ storage.append(type.underlyingType());
else
storage.append(type);
}
diff --git a/src/qml/qml/qqmlmetaobject.cpp b/src/qml/qml/qqmlmetaobject.cpp
index d5f1fb3b96..82903f80b2 100644
--- a/src/qml/qml/qqmlmetaobject.cpp
+++ b/src/qml/qml/qqmlmetaobject.cpp
@@ -48,7 +48,7 @@ QMetaType QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteAr
type = _m->method(data.coreIndex()).returnMetaType();
}
if (type.flags().testFlag(QMetaType::IsEnumeration))
- type = QMetaType::fromType<int>();
+ type = type.underlyingType();
if (type.isValid())
return type;
else if (unknownTypeError)
@@ -83,7 +83,7 @@ bool QQmlMetaObject::methodParameterTypes(const QMetaMethod &m, ArgTypeStorage *
QMetaType type = m.parameterMetaType(ii);
// we treat enumerations as int
if (type.flags().testFlag(QMetaType::IsEnumeration))
- type = QMetaType::fromType<int>();
+ type = type.underlyingType();
if (!type.isValid()) {
if (unknownTypeError)
*unknownTypeError = m.parameterTypeName(ii);
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 3c039ba55d..c1f327cd5a 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -1225,14 +1225,9 @@ bool QQmlPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx,
v = QVariant(menum.keyToValue(value.toByteArray(), &ok));
if (!ok)
return false;
- } else if (v.userType() != QMetaType::Int && v.userType() != QMetaType::UInt) {
- int enumMetaTypeId = QMetaType::fromName(
- QByteArray(menum.scope() + QByteArray("::") + menum.name())).id();
- if ((enumMetaTypeId == QMetaType::UnknownType) || (v.userType() != enumMetaTypeId) || !v.constData())
- return false;
- v = QVariant(*reinterpret_cast<const int *>(v.constData()));
}
- v.convert(QMetaType(QMetaType::Int));
+ if (!v.convert(prop.metaType())) // ### TODO: underlyingType might be faster?
+ return false;
}
// the status variable is changed by qt_metacall to indicate what it did
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index be44f1e8c2..b20e1c79b7 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -368,7 +368,7 @@ static ReturnedValue getGadgetProperty(ExecutionEngine *engine,
QMetaObject::ReadProperty, &metaObject, &index);
const int metaTypeId = isEnum
- ? QMetaType::Int
+ ? metaType.underlyingType().id()
: (metaType.flags() & QMetaType::PointerToQObject)
? QMetaType::QObjectStar
: metaType.id();
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index e775eb165c..e65cbee54b 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -149,6 +149,10 @@ void registerTypes()
qmlRegisterTypesAndRevisions<BaseValueType>("ValueTypes", 1);
qmlRegisterTypesAndRevisions<DerivedValueType>("ValueTypes", 1);
qmlRegisterTypesAndRevisions<GetterObject>("Test", 1);
+
+ qmlRegisterNamespaceAndRevisions(&TypedEnums::staticMetaObject, "TypedEnums", 1);
+ qmlRegisterTypesAndRevisions<ObjectWithEnums>("TypedEnums", 1);
+ qmlRegisterTypesAndRevisions<GadgetWithEnums>("TypedEnums", 1);
}
QVariant myCustomVariantTypeConverter(const QString &data)
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 977c274f6c..5f68deefaf 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -2420,5 +2420,151 @@ public:
Q_INVOKABLE quint64 getQTrue() const { return 1; }
};
+namespace TypedEnums {
+Q_NAMESPACE
+QML_ELEMENT
+
+enum E8S : qint8 {
+ E8SA = std::numeric_limits<qint8>::min(),
+ E8SB = -5,
+ E8SC = -1,
+ E8SD = 0,
+ E8SE = 1,
+ E8SF = 5,
+ E8SG = std::numeric_limits<qint8>::max(),
+};
+Q_ENUM_NS(E8S);
+
+enum E8U : quint8 {
+ E8UA = 0,
+ E8UB = 1,
+ E8UC = 5,
+ E8UD = 1 << 7,
+ E8UE = std::numeric_limits<quint8>::max(),
+};
+Q_ENUM_NS(E8U);
+
+enum E16S : qint16 {
+ E16SA = std::numeric_limits<qint16>::min(),
+ E16SB = -5,
+ E16SC = -1,
+ E16SD = 0,
+ E16SE = 1,
+ E16SF = 5,
+ E16SG = std::numeric_limits<qint16>::max(),
+};
+Q_ENUM_NS(E16S);
+
+enum E16U : quint16 {
+ E16UA = 0,
+ E16UB = 1,
+ E16UC = 5,
+ E16UD = 1 << 15,
+ E16UE = std::numeric_limits<quint16>::max(),
+};
+Q_ENUM_NS(E16U);
+
+enum E32S : qint32 {
+ E32SA = std::numeric_limits<qint32>::min(),
+ E32SB = -5,
+ E32SC = -1,
+ E32SD = 0,
+ E32SE = 1,
+ E32SF = 5,
+ E32SG = std::numeric_limits<qint32>::max(),
+};
+Q_ENUM_NS(E32S);
+
+enum E32U : quint32 {
+ E32UA = 0,
+ E32UB = 1,
+ E32UC = 5,
+ E32UD = 1u << 31,
+ E32UE = std::numeric_limits<quint32>::max(),
+};
+Q_ENUM_NS(E32U);
+
+enum E64S : qint64 {
+ E64SA = std::numeric_limits<qint64>::min(),
+ E64SB = -5,
+ E64SC = -1,
+ E64SD = 0,
+ E64SE = 1,
+ E64SF = 5,
+ E64SG = std::numeric_limits<qint64>::max(),
+};
+Q_ENUM_NS(E64S);
+
+enum E64U : quint64 {
+ E64UA = 0,
+ E64UB = 1,
+ E64UC = 5,
+ E64UD = 1ull << 63,
+ E64UE = std::numeric_limits<quint64>::max(),
+};
+Q_ENUM_NS(E64U);
+}
+
+class GadgetWithEnums
+{
+ Q_GADGET
+ QML_VALUE_TYPE(gadgetWithEnums)
+ Q_PROPERTY(TypedEnums::E8S e8s MEMBER m_e8s);
+ Q_PROPERTY(TypedEnums::E8U e8u MEMBER m_e8u);
+ Q_PROPERTY(TypedEnums::E16S e16s MEMBER m_e16s);
+ Q_PROPERTY(TypedEnums::E16U e16u MEMBER m_e16u);
+ Q_PROPERTY(TypedEnums::E32S e32s MEMBER m_e32s);
+ Q_PROPERTY(TypedEnums::E32U e32u MEMBER m_e32u);
+ Q_PROPERTY(TypedEnums::E64S e64s MEMBER m_e64s);
+ Q_PROPERTY(TypedEnums::E64U e64u MEMBER m_e64u);
+public:
+ TypedEnums::E8S m_e8s = {};
+ TypedEnums::E8U m_e8u = {};
+ TypedEnums::E16S m_e16s = {};
+ TypedEnums::E16U m_e16u = {};
+ TypedEnums::E32S m_e32s = {};
+ TypedEnums::E32U m_e32u = {};
+ TypedEnums::E64S m_e64s = {};
+ TypedEnums::E64U m_e64u = {};
+private:
+ friend bool operator==(const GadgetWithEnums &a, const GadgetWithEnums &b)
+ {
+ return a.m_e8s == b.m_e8s && a.m_e8u == b.m_e8u && a.m_e16s == b.m_e16s
+ && a.m_e16u == b.m_e16u && a.m_e32s == b.m_e32s && a.m_e32u == b.m_e32u
+ && a.m_e64s == b.m_e64s && a.m_e64u == b.m_e64u;
+ }
+ friend bool operator!=(const GadgetWithEnums &a, const GadgetWithEnums &b)
+ {
+ return !(a == b);
+ }
+};
+
+class ObjectWithEnums : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(TypedEnums::E8S e8s MEMBER m_e8s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E8U e8u MEMBER m_e8u NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E16S e16s MEMBER m_e16s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E16U e16u MEMBER m_e16u NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E32S e32s MEMBER m_e32s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E32U e32u MEMBER m_e32u NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E64S e64s MEMBER m_e64s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E64U e64u MEMBER m_e64u NOTIFY changed);
+ Q_PROPERTY(GadgetWithEnums g MEMBER m_g NOTIFY changed);
+public:
+ ObjectWithEnums(QObject *parent = nullptr) : QObject(parent) {}
+ TypedEnums::E8S m_e8s = {};
+ TypedEnums::E8U m_e8u = {};
+ TypedEnums::E16S m_e16s = {};
+ TypedEnums::E16U m_e16u = {};
+ TypedEnums::E32S m_e32s = {};
+ TypedEnums::E32U m_e32u = {};
+ TypedEnums::E64S m_e64s = {};
+ TypedEnums::E64U m_e64u = {};
+ GadgetWithEnums m_g;
+Q_SIGNALS:
+ void changed();
+};
#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index ce7e0a1b1c..89f5258819 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -410,6 +410,9 @@ private slots:
void longConversion();
+ void typedEnums_data();
+ void typedEnums();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -7924,6 +7927,53 @@ void tst_qqmllanguage::asValueType()
QCOMPARE(point.y(), 20.0);
}
+void tst_qqmllanguage::typedEnums_data()
+{
+ QTest::addColumn<QString>("property");
+ QTest::addColumn<double>("value");
+ const QMetaObject *mo = &TypedEnums::staticMetaObject;
+ for (int i = 0, end = mo->enumeratorCount(); i != end; ++i) {
+ const QMetaEnum e = mo->enumerator(i);
+ for (int k = 0, end = e.keyCount(); k != end; ++k) {
+ QTest::addRow("%s::%s", e.name(), e.key(k))
+ << QString::fromLatin1(e.name()).toLower()
+ << double(e.value(k));
+ }
+ }
+}
+void tst_qqmllanguage::typedEnums()
+{
+ QFETCH(QString, property);
+ QFETCH(double, value);
+ QQmlEngine e;
+ const QString qml = QLatin1String(R"(
+ import QtQml
+ import TypedEnums
+ ObjectWithEnums {
+ property real input: %2
+ %1: input
+ g.%1: input
+ property real output1: %1
+ property real output2: g.%1
+ }
+ )").arg(property).arg(value, 0, 'f');
+ QQmlComponent c(&engine);
+ c.setData(qml.toUtf8(), QUrl("enums.qml"_L1));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ // TODO: This silently fails for quint32, qint64 and quint64 because QMetaEnum cannot encode
+ // such values either. For the 64bit values we'll also need a better type than double
+ // inside QML.
+ QEXPECT_FAIL("E32U::E32UD", "Not supported", Abort);
+ QEXPECT_FAIL("E32U::E32UE", "Not supported", Abort);
+ QEXPECT_FAIL("E64U::E64UE", "Not supported", Abort);
+
+ QCOMPARE(o->property("output1").toDouble(), value);
+ QCOMPARE(o->property("output2").toDouble(), value);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"