diff options
author | Glenn Watson <glenn.watson@nokia.com> | 2012-06-26 14:52:27 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-06-26 23:28:55 +0200 |
commit | fb5c74a07dac7deedb9ab3b8b4390941e5dd0762 (patch) | |
tree | 191f686acfa82176cda48207909b9643e11a36a7 | |
parent | fe73fabad96f443247c6334b2c1b6ef59401c2c8 (diff) |
Support JS Date object in ListModel with static roles.
ListModel uses static roles by default for performance reasons. Add
JS Date object to list of supported types in this mode, via implicit
conversion to QDateTime.
Task-number: QTBUG-24456
Change-Id: Ifaa1a8d16290e87b61239ed351a949d66a02990c
Reviewed-by: Martin Jones <martin.jones@nokia.com>
-rw-r--r-- | src/qml/qml/qquicklistmodel.cpp | 75 | ||||
-rw-r--r-- | src/qml/qml/qquicklistmodel_p_p.h | 4 | ||||
-rw-r--r-- | tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp | 36 |
3 files changed, 112 insertions, 3 deletions
diff --git a/src/qml/qml/qquicklistmodel.cpp b/src/qml/qml/qquicklistmodel.cpp index 03f9e3a790..e865d847a8 100644 --- a/src/qml/qml/qquicklistmodel.cpp +++ b/src/qml/qml/qquicklistmodel.cpp @@ -78,7 +78,7 @@ static bool isMemoryUsed(const char *mem) static QString roleTypeName(ListLayout::Role::DataType t) { QString result; - const char *roleTypeNames[] = { "String", "Number", "Bool", "List", "QObject", "VariantMap" }; + const char *roleTypeNames[] = { "String", "Number", "Bool", "List", "QObject", "VariantMap", "DateTime" }; if (t > ListLayout::Role::Invalid && t < ListLayout::Role::MaxDataType) result = QString::fromLatin1(roleTypeNames[t]); @@ -119,8 +119,8 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(v8::Handle<v8::String> key, const ListLayout::Role &ListLayout::createRole(const QString &key, ListLayout::Role::DataType type) { - const int dataSizes[] = { sizeof(QString), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QQmlGuard<QObject>), sizeof(QVariantMap) }; - const int dataAlignments[] = { sizeof(QString), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QObject *), sizeof(QVariantMap) }; + const int dataSizes[] = { sizeof(QString), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QQmlGuard<QObject>), sizeof(QVariantMap), sizeof(QDateTime) }; + const int dataAlignments[] = { sizeof(QString), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QObject *), sizeof(QVariantMap), sizeof(QDateTime) }; Role *r = new Role; r->name = key; @@ -448,6 +448,10 @@ void ListModel::set(int elementIndex, v8::Handle<v8::Object> object, QList<int> } else if (propertyValue->IsBoolean()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool); roleIndex = e->setBoolProperty(r, propertyValue->BooleanValue()); + } else if (propertyValue->IsDate()) { + const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime); + QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(propertyValue)->NumberValue()); + roleIndex = e->setDateTimeProperty(r, dt); } else if (propertyValue->IsObject()) { QV8ObjectResource *r = (QV8ObjectResource *) propertyValue->ToObject()->GetExternalResource(); if (r && r->resourceType() == QV8ObjectResource::QObjectType) { @@ -520,6 +524,12 @@ void ListModel::set(int elementIndex, v8::Handle<v8::Object> object, QV8Engine * if (r.type == ListLayout::Role::Bool) { e->setBoolPropertyFast(r, propertyValue->BooleanValue()); } + } else if (propertyValue->IsDate()) { + const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime); + if (r.type == ListLayout::Role::DateTime) { + QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(propertyValue)->NumberValue()); + e->setDateTimePropertyFast(r, dt); + } } else if (propertyValue->IsObject()) { QV8ObjectResource *r = (QV8ObjectResource *) propertyValue->ToObject()->GetExternalResource(); if (r && r->resourceType() == QV8ObjectResource::QObjectType) { @@ -651,6 +661,17 @@ QVariantMap *ListElement::getVariantMapProperty(const ListLayout::Role &role) return map; } +QDateTime *ListElement::getDateTimeProperty(const ListLayout::Role &role) +{ + QDateTime *dt = 0; + + char *mem = getPropertyMemory(role); + if (isMemoryUsed<QDateTime>(mem)) + dt = reinterpret_cast<QDateTime *>(mem); + + return dt; +} + QQmlGuard<QObject> *ListElement::getGuardProperty(const ListLayout::Role &role) { char *mem = getPropertyMemory(role); @@ -736,6 +757,14 @@ QVariant ListElement::getProperty(const ListLayout::Role &role, const QQuickList } } break; + case ListLayout::Role::DateTime: + { + if (isMemoryUsed<QDateTime>(mem)) { + QDateTime *dt = reinterpret_cast<QDateTime *>(mem); + data = *dt; + } + } + break; default: break; } @@ -881,6 +910,23 @@ int ListElement::setVariantMapProperty(const ListLayout::Role &role, QVariantMap return roleIndex; } +int ListElement::setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt) +{ + int roleIndex = -1; + + if (role.type == ListLayout::Role::DateTime) { + char *mem = getPropertyMemory(role); + if (isMemoryUsed<QDateTime>(mem)) { + QDateTime *dt = reinterpret_cast<QDateTime *>(mem); + dt->~QDateTime(); + } + new (mem) QDateTime(dt); + roleIndex = role.index; + } + + return roleIndex; +} + void ListElement::setStringPropertyFast(const ListLayout::Role &role, const QString &s) { char *mem = getPropertyMemory(role); @@ -921,6 +967,12 @@ void ListElement::setVariantMapFast(const ListLayout::Role &role, v8::Handle<v8: *map = eng->variantMapFromJS(o); } +void ListElement::setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt) +{ + char *mem = getPropertyMemory(role); + new (mem) QDateTime(dt); +} + void ListElement::clearProperty(const ListLayout::Role &role) { switch (role.type) { @@ -939,6 +991,9 @@ void ListElement::clearProperty(const ListLayout::Role &role) case ListLayout::Role::QObject: setQObjectProperty(role, 0); break; + case ListLayout::Role::DateTime: + setDateTimeProperty(role, QDateTime()); + break; case ListLayout::Role::VariantMap: setVariantMapProperty(role, 0); break; @@ -998,6 +1053,7 @@ void ListElement::sync(ListElement *src, ListLayout *srcLayout, ListElement *tar case ListLayout::Role::String: case ListLayout::Role::Number: case ListLayout::Role::Bool: + case ListLayout::Role::DateTime: { QVariant v = src->getProperty(srcRole, 0, 0); target->setVariantProperty(targetRole, v); @@ -1052,6 +1108,13 @@ void ListElement::destroy(ListLayout *layout) map->~QMap(); } break; + case ListLayout::Role::DateTime: + { + QDateTime *dt = getDateTimeProperty(r); + if (dt) + dt->~QDateTime(); + } + break; default: // other types don't need explicit cleanup. break; @@ -1088,6 +1151,9 @@ int ListElement::setVariantProperty(const ListLayout::Role &role, const QVariant roleIndex = setVariantMapProperty(role, &map); } break; + case ListLayout::Role::DateTime: + roleIndex = setDateTimeProperty(role, d.toDateTime()); + break; default: break; } @@ -1124,6 +1190,9 @@ int ListElement::setJsProperty(const ListLayout::Role &role, v8::Handle<v8::Valu } } else if (d->IsBoolean()) { roleIndex = setBoolProperty(role, d->BooleanValue()); + } else if (d->IsDate()) { + QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(d)->NumberValue()); + roleIndex = setDateTimeProperty(role, dt); } else if (d->IsObject()) { QV8ObjectResource *r = (QV8ObjectResource *) d->ToObject()->GetExternalResource(); if (role.type == ListLayout::Role::QObject && r && r->resourceType() == QV8ObjectResource::QObjectType) { diff --git a/src/qml/qml/qquicklistmodel_p_p.h b/src/qml/qml/qquicklistmodel_p_p.h index f9256c9f0a..a006721f9c 100644 --- a/src/qml/qml/qquicklistmodel_p_p.h +++ b/src/qml/qml/qquicklistmodel_p_p.h @@ -197,6 +197,7 @@ public: List, QObject, VariantMap, + DateTime, MaxDataType }; @@ -260,6 +261,7 @@ private: int setQObjectProperty(const ListLayout::Role &role, QObject *o); int setVariantMapProperty(const ListLayout::Role &role, v8::Handle<v8::Object> o, QV8Engine *eng); int setVariantMapProperty(const ListLayout::Role &role, QVariantMap *m); + int setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt); void setStringPropertyFast(const ListLayout::Role &role, const QString &s); void setDoublePropertyFast(const ListLayout::Role &role, double n); @@ -267,6 +269,7 @@ private: void setQObjectPropertyFast(const ListLayout::Role &role, QObject *o); void setListPropertyFast(const ListLayout::Role &role, ListModel *m); void setVariantMapFast(const ListLayout::Role &role, v8::Handle<v8::Object> o, QV8Engine *eng); + void setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt); void clearProperty(const ListLayout::Role &role); @@ -276,6 +279,7 @@ private: QObject *getQObjectProperty(const ListLayout::Role &role); QQmlGuard<QObject> *getGuardProperty(const ListLayout::Role &role); QVariantMap *getVariantMapProperty(const ListLayout::Role &role); + QDateTime *getDateTimeProperty(const ListLayout::Role &role); inline char *getPropertyMemory(const ListLayout::Role &role); diff --git a/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp b/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp index e94fe81024..e4045ebe88 100644 --- a/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp +++ b/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp @@ -125,6 +125,8 @@ private slots: void string_to_list_crash(); void empty_element_warning(); void empty_element_warning_data(); + void datetime(); + void datetime_data(); }; bool tst_qquicklistmodel::compareVariantList(const QVariantList &testList, QVariant object) @@ -1226,6 +1228,40 @@ void tst_qquicklistmodel::empty_element_warning() delete obj; } +void tst_qquicklistmodel::datetime_data() +{ + QTest::addColumn<QString>("qml"); + QTest::addColumn<QDateTime>("expected"); + + QDateTime dt; + QDateTime dt0(QDate(1900, 1, 2), QTime( 8, 14)); + QDateTime dt1(QDate(2000, 11, 22), QTime(10, 45)); + + QTest::newRow("dt0") << "{append({'date':dt0});get(0).date}" << dt0; + QTest::newRow("dt1") << "{append({'date':dt0});get(0).date=dt1;get(0).date}" << dt1; + QTest::newRow("dt2") << "{append({'date':dt0});set(0,{'date':dt1});get(0).date}" << dt1; + QTest::newRow("dt3") << "{append({'date':dt0});get(0).date=undefined;get(0).date}" << dt; +} + +void tst_qquicklistmodel::datetime() +{ + QFETCH(QString, qml); + QFETCH(QDateTime, expected); + + QQmlEngine engine; + QQuickListModel model; + QQmlEngine::setContextForObject(&model,engine.rootContext()); + QDateTime dt0(QDate(1900, 1, 2), QTime( 8, 14)); + QDateTime dt1(QDate(2000, 11, 22), QTime(10, 45)); + engine.rootContext()->setContextProperty("dt0", dt0); + engine.rootContext()->setContextProperty("dt1", dt1); + engine.rootContext()->setContextObject(&model); + QQmlExpression e(engine.rootContext(), &model, qml); + QVariant result = e.evaluate(); + QDateTime dtResult = result.toDateTime(); + QVERIFY(expected == dtResult); +} + QTEST_MAIN(tst_qquicklistmodel) #include "tst_qquicklistmodel.moc" |