aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/types
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-08-02 15:44:12 +0200
committerLars Knoll <lars.knoll@qt.io>2018-08-02 20:25:41 +0000
commit0754f55287f4652382332bce42cd8c7d27846ef1 (patch)
tree490bbd3c5d66586a1427ba21dde76b2af65230dc /src/qml/types
parent57640959320c87850315eae44c783803d113dc85 (diff)
Introduce a new mechanism to iterate over object properties
The old advanceIterator schema was extremely ugly and in addition not flexible enough to support the requirements for Proxy.ownKeys and some of the methods in Object Implemented a new scheme through a OwnPropertyKeys method in the Object VTable that creates and returns an iterator object. Ported QJSValueIterator and for-in to use the new mechanism. There's still many places where we use the old ObjectIterator (that relies on advanceIterator). Those will be ported in subsequent commits. Change-Id: I091a9bea9ff6b2b63630cc336814700757a718be Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/types')
-rw-r--r--src/qml/types/qqmllistmodel.cpp38
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h3
2 files changed, 41 insertions, 0 deletions
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 1b64a38bd6..c6597b49f3 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -1633,6 +1633,44 @@ void ModelObject::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *
QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attributes);
}
+struct ModelObjectOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
+{
+ int roleNameIndex = 0;
+ ~ModelObjectOwnPropertyKeyIterator() override = default;
+ PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+
+};
+
+PropertyKey ModelObjectOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
+{
+ const ModelObject *that = static_cast<const ModelObject *>(o);
+
+ ExecutionEngine *v4 = that->engine();
+ if (roleNameIndex < that->listModel()->roleCount()) {
+ Scope scope(that->engine());
+ const ListLayout::Role &role = that->listModel()->getExistingRole(roleNameIndex);
+ ++roleNameIndex;
+ ScopedString roleName(scope, v4->newString(role.name));
+ if (attrs)
+ *attrs = QV4::Attr_Data;
+ if (pd) {
+ QVariant value = that->d()->m_model->data(that->d()->elementIndex(), role.index);
+ pd->value = v4->fromVariant(value);
+ }
+ return roleName->toPropertyKey();
+ }
+
+ // Fall back to QV4::Object as opposed to QV4::QObjectWrapper otherwise it will add
+ // unnecessary entries that relate to the roles used. These just create extra work
+ // later on as they will just be ignored.
+ return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
+}
+
+OwnPropertyKeyIterator *ModelObject::virtualOwnPropertyKeys(const Object *)
+{
+ return new ModelObjectOwnPropertyKeyIterator;
+}
+
DEFINE_OBJECT_VTABLE(ModelObject);
} // namespace QV4
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index e4a850e8a5..dbd0b0a2a2 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -176,10 +176,13 @@ struct ModelObject : public QObjectWrapper
V4_OBJECT2(ModelObject, QObjectWrapper)
V4_NEEDS_DESTROY
+ ListModel *listModel() const { return d()->m_model->m_listModel; }
+
protected:
static bool virtualPut(Managed *m, PropertyKey id, const Value& value, Value *receiver);
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
static void virtualAdvanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+ static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m);
};
} // namespace QV4