aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmllistwrapper.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-11-25 14:49:07 +0100
committerUlf Hermann <ulf.hermann@qt.io>2020-01-15 14:09:19 +0100
commit5a4ffa0de0ecc666a514ef60f0149a76d25b040d (patch)
tree5f9671c1c85b52bfdd051598e2c524ead98b0160 /src/qml/qml/qqmllistwrapper.cpp
parentd9a02d5c834b57f0da781c7dcf8d74e3b4ce1314 (diff)
QQmlListProperty: Add replace and removeLast functions
This allows us to implement QmlListWrapper::virtualPut(). Also, the additional functions make the list properties useful in other contexts. Fixes: QTBUG-79263 Change-Id: I528bc69222ca7743f0fc3697c3aed2a3468b4d87 Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqmllistwrapper.cpp')
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp82
1 files changed, 71 insertions, 11 deletions
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 5349572921..e5c1cb04a9 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -119,11 +119,13 @@ ReturnedValue QmlListWrapper::virtualGet(const Managed *m, PropertyKey id, const
if (hasProperty)
*hasProperty = false;
return Value::undefinedValue().asReturnedValue();
- } else if (id.isString()) {
- if (id == v4->id_length()->propertyKey() && !w->d()->object.isNull()) {
- quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
- return Value::fromUInt32(count).asReturnedValue();
- }
+ }
+
+ if (id.isString() && id == v4->id_length()->propertyKey()) {
+ if (hasProperty)
+ *hasProperty = true;
+ quint32 count = w->d()->property().count ? w->d()->property().count(&w->d()->property()) : 0;
+ return Value::fromUInt32(count).asReturnedValue();
}
return Object::virtualGet(m, id, receiver, hasProperty);
@@ -131,12 +133,70 @@ ReturnedValue QmlListWrapper::virtualGet(const Managed *m, PropertyKey id, const
bool QmlListWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
{
- // doesn't do anything. Should we throw?
- Q_UNUSED(m);
- Q_UNUSED(id);
- Q_UNUSED(value);
- Q_UNUSED(receiver);
- return false;
+ Q_ASSERT(m->as<QmlListWrapper>());
+
+ const auto *w = static_cast<const QmlListWrapper *>(m);
+ QV4::ExecutionEngine *v4 = w->engine();
+
+ QQmlListProperty<QObject> *prop = &(w->d()->property());
+
+ if (id.isArrayIndex()) {
+ if (!prop->count || !prop->replace)
+ return false;
+
+ const uint index = id.asArrayIndex();
+ const int count = prop->count(prop);
+ if (count < 0 || index >= uint(count))
+ return false;
+
+ QV4::Scope scope(v4);
+ QV4::ScopedObject so(scope, value.toObject(scope.engine));
+ if (auto *wrapper = so->as<QV4::QObjectWrapper>()) {
+ prop->replace(prop, index, wrapper->object());
+ return true;
+ }
+
+ return false;
+ }
+
+ if (id.isString() && id == v4->id_length()->propertyKey()) {
+ if (!prop->count)
+ return false;
+
+ const quint32 count = prop->count(prop);
+
+ bool ok = false;
+ const uint newLength = value.asArrayLength(&ok);
+ if (!ok)
+ return false;
+
+ if (newLength == 0) {
+ if (!prop->clear)
+ return false;
+ prop->clear(prop);
+ return true;
+ }
+
+ if (newLength < count) {
+ if (!prop->removeLast)
+ return false;
+
+ for (uint i = newLength; i < count; ++i)
+ prop->removeLast(prop);
+
+ return true;
+ }
+
+ if (!prop->append)
+ return false;
+
+ for (uint i = count; i < newLength; ++i)
+ prop->append(prop, nullptr);
+
+ return true;
+ }
+
+ return Object::virtualPut(m, id, value, receiver);
}
struct QmlListWrapperOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator