diff options
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 28 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 13 | ||||
-rw-r--r-- | src/qml/types/qqmlitemmodels.qdoc | 17 | ||||
-rw-r--r-- | src/qml/types/qqmlmodelindexvaluetype_p.h | 13 | ||||
-rw-r--r-- | tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml | 27 | ||||
-rw-r--r-- | tests/auto/qml/qqmlitemmodels/testtypes.h | 42 | ||||
-rw-r--r-- | tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp | 36 |
7 files changed, 128 insertions, 48 deletions
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index a7e3b22cd2..f7adf6eb18 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -41,6 +41,9 @@ #include <private/qv4scopedvalue_p.h> #include "qv4runtime_p.h" #include "qv4objectiterator_p.h" +#include <private/qqmlvaluetypewrapper_p.h> +#include <private/qqmlmodelindexvaluetype_p.h> +#include <QtCore/qabstractitemmodel.h> #include <algorithm> @@ -71,7 +74,8 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description F(bool, Bool, QList<bool>, false) \ F(QString, String, QList<QString>, QString()) \ F(QString, QString, QStringList, QString()) \ - F(QUrl, Url, QList<QUrl>, QUrl()) + F(QUrl, Url, QList<QUrl>, QUrl()) \ + F(QModelIndex, QModelIndex, QModelIndexList, QModelIndex()) static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, const QString &element) { @@ -88,6 +92,12 @@ static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, co return engine->newString(element.toString())->asReturnedValue(); } +static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, const QModelIndex &element) +{ + const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(QMetaType::QModelIndex); + return QV4::QQmlValueTypeWrapper::create(engine, QVariant(element), vtmo, QMetaType::QModelIndex); +} + static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *, qreal element) { return QV4::Encode(element); @@ -113,6 +123,11 @@ static QString convertElementToString(const QUrl &element) return element.toString(); } +static QString convertElementToString(const QModelIndex &element) +{ + return reinterpret_cast<const QQmlModelIndexValueType *>(&element)->toString(); +} + static QString convertElementToString(qreal element) { QString qstr; @@ -145,6 +160,14 @@ template <> QUrl convertValueToElement(const Value &value) return QUrl(value.toQString()); } +template <> QModelIndex convertValueToElement(const Value &value) +{ + const QQmlValueTypeWrapper *v = value_cast<QQmlValueTypeWrapper>(value); + if (v) + return v->toVariant().toModelIndex(); + return QModelIndex(); +} + template <> qreal convertValueToElement(const Value &value) { return value.toNumber(); @@ -541,6 +564,9 @@ DEFINE_OBJECT_VTABLE(QQmlIntList); typedef QQmlSequence<QList<QUrl> > QQmlUrlList; template<> DEFINE_OBJECT_VTABLE(QQmlUrlList); +typedef QQmlSequence<QModelIndexList> QQmlQModelIndexList; +template<> +DEFINE_OBJECT_VTABLE(QQmlQModelIndexList); typedef QQmlSequence<QList<bool> > QQmlBoolList; template<> DEFINE_OBJECT_VTABLE(QQmlBoolList); diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index 2b3f78b676..6711ad2de9 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -64,7 +64,6 @@ QQmlValueTypeFactoryImpl::QQmlValueTypeFactoryImpl() valueTypes[ii] = 0; // See types wrapped in qqmlmodelindexvaluetype_p.h - qRegisterMetaType<QModelIndexList>(); qRegisterMetaType<QItemSelectionRange>(); qRegisterMetaType<QItemSelection>(); } @@ -112,18 +111,16 @@ const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t) case QVariant::PersistentModelIndex: return &QQmlPersistentModelIndexValueType::staticMetaObject; default: + if (t == qMetaTypeId<QItemSelectionRange>()) + return &QQmlItemSelectionRangeValueType::staticMetaObject; + if (t == qMetaTypeId<QItemSelection>()) + return &QQmlItemSelectionValueType::staticMetaObject; + if (const QMetaObject *mo = QQml_valueTypeProvider()->metaObjectForMetaType(t)) return mo; break; } - if (t == qMetaTypeId<QModelIndexList>()) - return &QQmlModelIndexListValueType::staticMetaObject; - else if (t == qMetaTypeId<QItemSelectionRange>()) - return &QQmlItemSelectionRangeValueType::staticMetaObject; - else if (t == qMetaTypeId<QItemSelection>()) - return &QQmlItemSelectionValueType::staticMetaObject; - QMetaType metaType(t); if (metaType.flags() & QMetaType::IsGadget) return metaType.metaObject(); diff --git a/src/qml/types/qqmlitemmodels.qdoc b/src/qml/types/qqmlitemmodels.qdoc index 25c9321115..70059b07c6 100644 --- a/src/qml/types/qqmlitemmodels.qdoc +++ b/src/qml/types/qqmlitemmodels.qdoc @@ -60,6 +60,17 @@ should not store any QModelIndex. You can, however, store QPersistentModelIndexes in a safe way. + \section1 QModelIndexList + + \l QModelIndexList is exposed in QML as a JavaScript array. Conversions are + automatically made from and to C++. In fact, any JavaScript array can be + converted back to QModelIndexList, with non-QModelIndex objects replaced by + invalid QModelIndexes. + + \note QModelIndex to QPersistentModelIndex conversion happens when accessing + the array elements because any QModelIndexList property retains reference + semantics when exposed this way. + \section1 \l QItemSelectionRange \list @@ -87,10 +98,10 @@ \li QItemSelectionRange \b{intersected}(QItemSelectionRange other) \endlist - \section1 \l QModelIndexList and \l QItemSelection + \section1 QItemSelection - Both \l QModelIndexList and \l QItemSelection expose the following properties - and functions as part of their \l QList API: + \l QItemSelection exposes the following properties and functions as part of + its \l QList API: \list \li \b length : int diff --git a/src/qml/types/qqmlmodelindexvaluetype_p.h b/src/qml/types/qqmlmodelindexvaluetype_p.h index 0e655ab3d7..e36f7a0d1e 100644 --- a/src/qml/types/qqmlmodelindexvaluetype_p.h +++ b/src/qml/types/qqmlmodelindexvaluetype_p.h @@ -175,19 +175,6 @@ QString q_listToString(const QList<T> &list, const QLatin1String &typeName) Q_INVOKABLE void removeAt(int i) { v.removeAt(i); } \ int length() const { return v.length(); } -struct QQmlModelIndexListValueType -{ - QModelIndexList v; - - Q_GADGET - -public: - Q_INVOKABLE QString toString() - { return q_listToString<QQmlModelIndexValueType>(v, QLatin1String("")); } - - QLISTVALUETYPE_QML_API(QModelIndex) -}; - struct QQmlItemSelectionValueType { QItemSelection v; diff --git a/tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml b/tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml index 44393392d3..389c5daaf5 100644 --- a/tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml +++ b/tests/auto/qml/qqmlitemmodels/data/modelindexlist.qml @@ -1,21 +1,30 @@ import Test 1.0 ItemModelsTest { - property var modelIndexList property int count + property var modelIndexListCopy + property var modelIndexListRead + property var modelIndexListBinding: modelIndexList + property bool varPropIsArray + property bool varIsArray + property bool propIsArray onModelChanged: { - modelIndexList = createModelIndexList() - modelIndexList.prepend(model.index(0, 0)) - modelIndexList.append(model.index(1, 1)) + var jsModelIndexList = [] for (var i = 0; i < 3; i++) - modelIndexList.insert(i, model.index(2 + i, 2 + i)) + jsModelIndexList.push(model.index(2 + i, 2 + i)) + jsModelIndexList.push("Hi Bronsky!") + modelIndex = jsModelIndexList[0] count = modelIndexList.length - modelIndex = modelIndexList.at(0) + propIsArray = modelIndexList instanceof Array + modelIndexList = jsModelIndexList + modelIndexListRead = modelIndexList - modelIndexList.removeAt(3) - modelIndexList.removeFirst() - modelIndexList.removeLast() + modelIndexListCopy = someModelIndexList() + varPropIsArray = modelIndexListCopy instanceof Array + + jsModelIndexList = someModelIndexList() + varIsArray = jsModelIndexList instanceof Array } } diff --git a/tests/auto/qml/qqmlitemmodels/testtypes.h b/tests/auto/qml/qqmlitemmodels/testtypes.h index 5345609cd3..d61064fcad 100644 --- a/tests/auto/qml/qqmlitemmodels/testtypes.h +++ b/tests/auto/qml/qqmlitemmodels/testtypes.h @@ -45,8 +45,15 @@ class ItemModelsTest : public QObject Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(QModelIndex modelIndex READ modelIndex WRITE setModelIndex NOTIFY changed) Q_PROPERTY(QPersistentModelIndex persistentModelIndex READ persistentModelIndex WRITE setPersistentModelIndex NOTIFY changed) + Q_PROPERTY(QModelIndexList modelIndexList READ modelIndexList WRITE setModelIndexList NOTIFY changed) public: + ItemModelsTest(QObject *parent = 0) + : QObject(parent) + , m_model(0) + { + } + QModelIndex modelIndex() const { return m_modelIndex; @@ -57,6 +64,26 @@ public: return m_persistentModelIndex; } + QModelIndexList modelIndexList() + { + static bool firstTime = true; + if (firstTime && m_model && m_modelIndexList.isEmpty()) { + firstTime = false; + for (int i = 0; i < m_model->rowCount(); i++) + m_modelIndexList << m_model->index(i, 0); + } + return m_modelIndexList; + } + + Q_INVOKABLE QModelIndexList someModelIndexList() const + { + QModelIndexList list; + if (m_model) + for (int i = 0; i < m_model->rowCount(); i++) + list << m_model->index(i, 0); + return list; + } + void emitChanged() { emit changed(); @@ -82,11 +109,6 @@ public: return QModelIndex(); } - Q_INVOKABLE QModelIndexList createModelIndexList() const - { - return QModelIndexList(); - } - Q_INVOKABLE QItemSelectionRange createItemSelectionRange(const QModelIndex &tl, const QModelIndex &br) const { return QItemSelectionRange(tl, br); @@ -130,6 +152,15 @@ public slots: emit modelChanged(arg); } + void setModelIndexList(QModelIndexList arg) + { + if (m_modelIndexList == arg) + return; + + m_modelIndexList = arg; + emit changed(); + } + signals: void changed(); @@ -142,6 +173,7 @@ private: QModelIndex m_modelIndex; QPersistentModelIndex m_persistentModelIndex; QAbstractItemModel *m_model; + QModelIndexList m_modelIndexList; }; #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp b/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp index 84e8011685..cd00593ee6 100644 --- a/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp +++ b/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp @@ -198,17 +198,35 @@ void tst_qqmlitemmodels::modelIndexList() { INIT_TEST_OBJECT("modelindexlist.qml", object); TestModel model(10, 10); + model.fetchMore(QModelIndex()); object->setModel(&model); - QCOMPARE(object->property("count").toInt(), 5); - - QVariant milVariant = object->property("modelIndexList"); - QCOMPARE(milVariant.userType(), qMetaTypeId<QModelIndexList>()); - - const QModelIndexList &mil = milVariant.value<QModelIndexList>(); - QCOMPARE(mil.count(), 2); - QCOMPARE(mil.at(0), model.index(3, 3)); - QCOMPARE(mil.at(1), model.index(4, 4)); + QVERIFY(object->property("propIsArray").toBool()); + QVERIFY(object->property("varPropIsArray").toBool()); + QVERIFY(object->property("varIsArray").toBool()); + + QCOMPARE(object->property("count").toInt(), 10); + const QModelIndexList &mil = object->modelIndexList(); + QCOMPARE(mil.count(), 4); + for (int i = 0; i < 3; i++) + QCOMPARE(mil.at(i), model.index(2 + i, 2 + i)); + QCOMPARE(mil.at(3), QModelIndex()); // The string inserted at the end should result in an invalid index + QCOMPARE(mil.at(0), object->modelIndex()); + + QVariant cppMILVariant = object->property("modelIndexListCopy"); + QCOMPARE(cppMILVariant.userType(), qMetaTypeId<QModelIndexList>()); + QModelIndexList someMIL = object->someModelIndexList(); + QCOMPARE(cppMILVariant.value<QModelIndexList>(), someMIL); + + const char *propNames[] = { "modelIndexListRead", "modelIndexListBinding", 0 }; + for (const char **name = propNames; *name; name++) { + QVariant milVariant = object->property(*name); + QCOMPARE(milVariant.userType(), qMetaTypeId<QModelIndexList>()); + + const QModelIndexList &milProp = milVariant.value<QModelIndexList>(); + QCOMPARE(milProp.count(), mil.count()); + QCOMPARE(milProp, mil); + } } #undef INIT_TEST_OBJECT |