diff options
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/qml/qqmlopenmetaobject.cpp | 74 | ||||
-rw-r--r-- | src/qml/qml/qqmlopenmetaobject_p.h | 3 | ||||
-rw-r--r-- | src/qml/util/qqmlpropertymap.cpp | 30 | ||||
-rw-r--r-- | src/qml/util/qqmlpropertymap.h | 1 |
4 files changed, 94 insertions, 14 deletions
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp index 5b0d306c0e..5319700d85 100644 --- a/src/qml/qml/qqmlopenmetaobject.cpp +++ b/src/qml/qml/qqmlopenmetaobject.cpp @@ -236,11 +236,21 @@ public: return data[idx].valueSet; } + void dropPropertyCache() { + if (QQmlData *ddata = QQmlData::get(object, /*create*/false)) { + if (ddata->propertyCache) { + ddata->propertyCache->release(); + ddata->propertyCache = nullptr; + } + } + } + QQmlOpenMetaObject *q; QAbstractDynamicMetaObject *parent = nullptr; QVector<Property> data; QObject *object; QQmlRefPointer<QQmlOpenMetaObjectType> type; + QVector<QByteArray> *deferredPropertyNames = nullptr; bool autoCreate; bool cacheProperties = false; }; @@ -322,6 +332,16 @@ QAbstractDynamicMetaObject *QQmlOpenMetaObject::parent() const return d->parent; } +bool QQmlOpenMetaObject::checkedSetValue(int index, const QVariant &value, bool force) +{ + if (!force && d->propertyValue(index) == value) + return false; + + d->setPropertyValue(index, value); + activate(d->object, index + d->type->d->signalOffset, nullptr); + return true; +} + QVariant QQmlOpenMetaObject::value(int id) const { return d->propertyValue(id); @@ -361,16 +381,43 @@ bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val, b id = *iter; } - if (id >= 0) { - if (!force && d->propertyValue(id) == val) - return false; + if (id >= 0) + return checkedSetValue(id, val, force); + + return false; +} - d->setPropertyValue(id, val); - activate(d->object, id + d->type->d->signalOffset, nullptr); - return true; +void QQmlOpenMetaObject::setValues(const QHash<QByteArray, QVariant> &values, bool force) +{ + QVector<QByteArray> missingProperties; + d->deferredPropertyNames = &missingProperties; + const auto &names = d->type->d->names; + + for (auto valueIt = values.begin(), end = values.end(); valueIt != end; ++valueIt) { + const auto nameIt = names.constFind(valueIt.key()); + if (nameIt == names.constEnd()) { + const int id = createProperty(valueIt.key(), "") - d->type->d->propertyOffset; + + // If id >= 0 some override of createProperty() created it. Then set it. + // Else it either ends up in missingProperties and we create it later + // or it cannot be created. + + if (id >= 0) + checkedSetValue(id, valueIt.value(), force); + } else { + checkedSetValue(*nameIt, valueIt.value(), force); + } } - return false; + d->deferredPropertyNames = nullptr; + if (missingProperties.isEmpty()) + return; + + d->type->createProperties(missingProperties); + d->dropPropertyCache(); + + for (const QByteArray &name : qAsConst(missingProperties)) + checkedSetValue(names[name], values[name], force); } // returns true if this value has been initialized by a call to either value() or setValue() @@ -403,15 +450,14 @@ void QQmlOpenMetaObject::setCached(bool c) int QQmlOpenMetaObject::createProperty(const char *name, const char *) { if (d->autoCreate) { - int result = d->type->createProperty(name); - - if (QQmlData *ddata = QQmlData::get(d->object, /*create*/false)) { - if (ddata->propertyCache) { - ddata->propertyCache->release(); - ddata->propertyCache = nullptr; - } + if (d->deferredPropertyNames) { + // Defer the creation of new properties. See setValues(QHash<QByteArray, QVariant>) + d->deferredPropertyNames->append(name); + return -1; } + const int result = d->type->createProperty(name); + d->dropPropertyCache(); return result; } else return -1; diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h index 168a2a6f7f..441556a079 100644 --- a/src/qml/qml/qqmlopenmetaobject_p.h +++ b/src/qml/qml/qqmlopenmetaobject_p.h @@ -101,6 +101,7 @@ public: QVariant value(const QByteArray &) const; bool setValue(const QByteArray &, const QVariant &, bool force = false); + void setValues(const QHash<QByteArray, QVariant> &, bool force = false); QVariant value(int) const; void setValue(int, const QVariant &); QVariant &valueRef(const QByteArray &); @@ -132,6 +133,8 @@ protected: QAbstractDynamicMetaObject *parent() const; + bool checkedSetValue(int index, const QVariant &value, bool force); + private: QQmlOpenMetaObjectPrivate *d; friend class QQmlOpenMetaObjectType; diff --git a/src/qml/util/qqmlpropertymap.cpp b/src/qml/util/qqmlpropertymap.cpp index e5fa66aded..e38cf3a2a9 100644 --- a/src/qml/util/qqmlpropertymap.cpp +++ b/src/qml/util/qqmlpropertymap.cpp @@ -234,6 +234,36 @@ void QQmlPropertyMap::insert(const QString &key, const QVariant &value) } /*! + \since 6.1 + + Inserts the \a values into the QQmlPropertyMap. + + Keys that don't exist are automatically created. + + This method is substantially faster than calling \c{insert(key, value)} + many times in a row. +*/ +void QQmlPropertyMap::insert(const QVariantHash &values) +{ + Q_D(QQmlPropertyMap); + + QHash<QByteArray, QVariant> checkedValues; + for (auto it = values.begin(), end = values.end(); it != end; ++it) { + const QString &key = it.key(); + if (!d->validKeyName(key)) { + qWarning() << "Creating property with name" + << key + << "is not permitted, conflicts with internal symbols."; + return; + } + + checkedValues.insert(key.toUtf8(), it.value()); + } + d->mo->setValues(checkedValues); + +} + +/*! Returns the list of keys. Keys that have been cleared will still appear in this list, even though their diff --git a/src/qml/util/qqmlpropertymap.h b/src/qml/util/qqmlpropertymap.h index d948989833..556754c021 100644 --- a/src/qml/util/qqmlpropertymap.h +++ b/src/qml/util/qqmlpropertymap.h @@ -60,6 +60,7 @@ public: QVariant value(const QString &key) const; void insert(const QString &key, const QVariant &value); + void insert(const QVariantHash &values); void clear(const QString &key); Q_INVOKABLE QStringList keys() const; |