diff options
-rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 19 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljscompiler.cpp | 1 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstyperesolver.cpp | 15 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstyperesolver_p.h | 4 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/dateConversions.qml | 25 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/data/druggeljug.h | 12 | ||||
-rw-r--r-- | tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp | 37 |
8 files changed, 114 insertions, 0 deletions
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index 686338c1a6..8d8a7c9118 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -3100,6 +3100,25 @@ QString QQmlJSCodeGenerator::conversion(const QQmlJSScope::ConstPtr &from, return variable + u".toUtf8()"_s; } + for (const auto &originType : { + m_typeResolver->dateTimeType(), + m_typeResolver->dateType(), + m_typeResolver->timeType()}) { + if (m_typeResolver->equals(from, originType)) { + for (const auto &targetType : { + m_typeResolver->dateTimeType(), + m_typeResolver->dateType(), + m_typeResolver->timeType(), + m_typeResolver->stringType()}) { + if (m_typeResolver->equals(to, targetType)) { + return u"aotContext->engine->coerceValue<%1, %2>(%3)"_s.arg( + originType->internalName(), targetType->internalName(), variable); + } + } + break; + } + } + const auto retrieveFromPrimitive = [&]( const QQmlJSScope::ConstPtr &type, const QString &expression) -> QString { diff --git a/src/qmlcompiler/qqmljscompiler.cpp b/src/qmlcompiler/qqmljscompiler.cpp index 5ee7ec90b6..964c01c1a2 100644 --- a/src/qmlcompiler/qqmljscompiler.cpp +++ b/src/qmlcompiler/qqmljscompiler.cpp @@ -752,6 +752,7 @@ QQmlJSAotFunction QQmlJSAotCompiler::globalCode() const u"QtQml/qqmllist.h"_s, u"QtCore/qdatetime.h"_s, + u"QtCore/qtimezone.h"_s, u"QtCore/qobject.h"_s, u"QtCore/qstring.h"_s, u"QtCore/qstringlist.h"_s, diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index 6999a1e2a3..4495f9fce6 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -36,6 +36,8 @@ QQmlJSTypeResolver::QQmlJSTypeResolver(QQmlJSImporter *importer) m_byteArrayType = builtinTypes.type(u"QByteArray"_s).scope; m_urlType = builtinTypes.type(u"QUrl"_s).scope; m_dateTimeType = builtinTypes.type(u"QDateTime"_s).scope; + m_dateType = builtinTypes.type(u"QDate"_s).scope; + m_timeType = builtinTypes.type(u"QTime"_s).scope; m_variantListType = builtinTypes.type(u"QVariantList"_s).scope; m_varType = builtinTypes.type(u"QVariant"_s).scope; m_jsValueType = builtinTypes.type(u"QJSValue"_s).scope; @@ -710,6 +712,7 @@ QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType( if (isPrimitive(type) || equals(type, m_jsValueType) || equals(type, m_urlType) || equals(type, m_dateTimeType) + || equals(type, m_dateType) || equals(type, m_timeType) || equals(type, m_variantListType) || equals(type, m_varType) || equals(type, m_stringListType) || equals(type, m_emptyListType) || equals(type, m_byteArrayType)) { @@ -948,6 +951,18 @@ bool QQmlJSTypeResolver::canPrimitivelyConvertFromTo( if (equals(from, m_stringType) && equals(to, m_dateTimeType)) return true; + for (const auto &originType : {m_dateTimeType, m_dateType, m_timeType}) { + if (!equals(from, originType)) + continue; + + for (const auto &targetType : {m_dateTimeType, m_dateType, m_timeType, m_stringType}) { + if (equals(to, targetType)) + return true; + } + + break;; + } + if (equals(from, m_nullType) && to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) { return true; diff --git a/src/qmlcompiler/qqmljstyperesolver_p.h b/src/qmlcompiler/qqmljstyperesolver_p.h index 12063075bc..453e06ac52 100644 --- a/src/qmlcompiler/qqmljstyperesolver_p.h +++ b/src/qmlcompiler/qqmljstyperesolver_p.h @@ -53,6 +53,8 @@ public: QQmlJSScope::ConstPtr byteArrayType() const { return m_byteArrayType; } QQmlJSScope::ConstPtr urlType() const { return m_urlType; } QQmlJSScope::ConstPtr dateTimeType() const { return m_dateTimeType; } + QQmlJSScope::ConstPtr dateType() const { return m_dateType; } + QQmlJSScope::ConstPtr timeType() const { return m_timeType; } QQmlJSScope::ConstPtr variantListType() const { return m_variantListType; } QQmlJSScope::ConstPtr varType() const { return m_varType; } QQmlJSScope::ConstPtr jsValueType() const { return m_jsValueType; } @@ -195,6 +197,8 @@ protected: QQmlJSScope::ConstPtr m_byteArrayType; QQmlJSScope::ConstPtr m_urlType; QQmlJSScope::ConstPtr m_dateTimeType; + QQmlJSScope::ConstPtr m_dateType; + QQmlJSScope::ConstPtr m_timeType; QQmlJSScope::ConstPtr m_variantListType; QQmlJSScope::ConstPtr m_varType; QQmlJSScope::ConstPtr m_jsValueType; diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index fa06745d34..e66af303ca 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -79,6 +79,7 @@ set(qml_files conversions2.qml curlygrouped.qml cycleHead.qml + dateConversions.qml deadShoeSize.qml deadStoreLoop.qml dialog.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml b/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml new file mode 100644 index 0000000000..38a34f7487 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml @@ -0,0 +1,25 @@ +pragma Strict +import QtQml +import TestTypes + +QtObject { + property date date: Druggeljug.myDate + property date time: Druggeljug.myTime + + property string dateString: date + property string timeString: time + + function shuffle() { + Druggeljug.myDate = date; + Druggeljug.myTime = time; + + dateString = Druggeljug.myDate; + timeString = Druggeljug.myTime; + } + + function fool() { + var tmp = Druggeljug.myTime; + Druggeljug.myTime = Druggeljug.myDate; + Druggeljug.myDate = tmp; + } +} diff --git a/tests/auto/qml/qmlcppcodegen/data/druggeljug.h b/tests/auto/qml/qmlcppcodegen/data/druggeljug.h index 70553e9b71..04f8301718 100644 --- a/tests/auto/qml/qmlcppcodegen/data/druggeljug.h +++ b/tests/auto/qml/qmlcppcodegen/data/druggeljug.h @@ -2,6 +2,7 @@ #define DRUGGELJUG_H #include <QtCore/qobject.h> +#include <QtCore/qdatetime.h> #include <qqmlregistration.h> #define STORE_FUNCTION(type, name, member, signal) \ @@ -29,6 +30,9 @@ class Druggeljug : public QObject Q_PROPERTY(qint64 myInt64 MEMBER m_myInt64 NOTIFY myInt64Changed FINAL) Q_PROPERTY(quint64 myUint64 MEMBER m_myUint64 NOTIFY myUint64Changed FINAL) + Q_PROPERTY(QTime myTime MEMBER m_myTime NOTIFY myTimeChanged) + Q_PROPERTY(QDate myDate MEMBER m_myDate NOTIFY myDateChanged) + public: Druggeljug(QObject* parent = nullptr) : QObject(parent) {} @@ -43,6 +47,9 @@ public: STORE_FUNCTION(qint64, storeMyInt64, m_myInt64, myInt64Changed) STORE_FUNCTION(quint64, storeMyUint64, m_myUint64, myUint64Changed) + QTime myTime() const { return m_myTime; } + QDate myDate() const { return m_myDate; } + private: int m_myInt = 0; uint m_myUint = 0; @@ -55,6 +62,9 @@ private: qint64 m_myInt64 = 0; quint64 m_myUint64 = 0; + QTime m_myTime = QTime(11, 55, 0); + QDate m_myDate = QDate(2017, 9, 3); + signals: void myIntChanged(int); void myUintChanged(uint); @@ -66,6 +76,8 @@ signals: void myUint32Changed(quint32); void myInt64Changed(qint64); void myUint64Changed(quint64); + void myTimeChanged(); + void myDateChanged(); }; #endif diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 65e882a089..1e88ecd7b7 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -1,5 +1,6 @@ // Copyright (C) 2021 The Qt Company Ltd. +#include "data/druggeljug.h" #include <data/birthdayparty.h> #include <data/cppbaseclass.h> #include <data/enumproblems.h> @@ -160,6 +161,7 @@ private slots: void infinitiesToInt(); void equalityVarAndNonStorable(); void equalityQObjects(); + void dateConversions(); }; void tst_QmlCppCodegen::initTestCase() @@ -3088,6 +3090,41 @@ void tst_QmlCppCodegen::equalityQObjects() QVERIFY(object->property("compareObjectWithNullObject").toBool()); } +void tst_QmlCppCodegen::dateConversions() +{ + QQmlEngine engine; + QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dateConversions.qml"_s)); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> o(c.create()); + + Druggeljug *ref = engine.singletonInstance<Druggeljug *>("TestTypes", "Druggeljug"); + + const QDateTime refDate = engine.coerceValue<QDate, QDateTime>(ref->myDate()); + const QDateTime refTime = engine.coerceValue<QTime, QDateTime>(ref->myTime()); + + QCOMPARE(o->property("date").value<QDateTime>(), refDate); + QCOMPARE(o->property("time").value<QDateTime>(), refTime); + + QCOMPARE(o->property("dateString").toString(), (engine.coerceValue<QDateTime, QString>(refDate))); + QCOMPARE(o->property("timeString").toString(), (engine.coerceValue<QDateTime, QString>(refTime))); + + QMetaObject::invokeMethod(o.data(), "shuffle"); + + QCOMPARE(ref->myDate(), (engine.coerceValue<QDateTime, QDate>(refDate))); + QCOMPARE(ref->myTime(), (engine.coerceValue<QDateTime, QTime>(refTime))); + + const QDate date = ref->myDate(); + const QTime time = ref->myTime(); + + QCOMPARE(o->property("dateString").toString(), (engine.coerceValue<QDate, QString>(date))); + QCOMPARE(o->property("timeString").toString(), (engine.coerceValue<QTime, QString>(time))); + + QMetaObject::invokeMethod(o.data(), "fool"); + + QCOMPARE(ref->myDate(), (engine.coerceValue<QTime, QDate>(time))); + QCOMPARE(ref->myTime(), (engine.coerceValue<QDate, QTime>(date))); +} + QTEST_MAIN(tst_QmlCppCodegen) #include "tst_qmlcppcodegen.moc" |