aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlmodels/qqmladaptormodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmlmodels/qqmladaptormodel.cpp')
-rw-r--r--src/qmlmodels/qqmladaptormodel.cpp963
1 files changed, 8 insertions, 955 deletions
diff --git a/src/qmlmodels/qqmladaptormodel.cpp b/src/qmlmodels/qqmladaptormodel.cpp
index dd08f91c61..f72a5e6b16 100644
--- a/src/qmlmodels/qqmladaptormodel.cpp
+++ b/src/qmlmodels/qqmladaptormodel.cpp
@@ -3,949 +3,19 @@
#include "qqmladaptormodel_p.h"
-#include <private/qqmldelegatemodel_p_p.h>
-#include <private/qmetaobjectbuilder_p.h>
-#include <private/qqmlproperty_p.h>
-
-#include <private/qv4value_p.h>
-#include <private/qv4functionobject_p.h>
+#include <private/qqmldmabstractitemmodeldata_p.h>
+#include <private/qqmldmlistaccessordata_p.h>
+#include <private/qqmldmobjectdata_p.h>
QT_BEGIN_NAMESPACE
-class QQmlAdaptorModelEngineData : public QV4::ExecutionEngine::Deletable
-{
-public:
- QQmlAdaptorModelEngineData(QV4::ExecutionEngine *v4);
- ~QQmlAdaptorModelEngineData();
-
- QV4::ExecutionEngine *v4;
- QV4::PersistentValue listItemProto;
-};
-
-V4_DEFINE_EXTENSION(QQmlAdaptorModelEngineData, engineData)
-
-static QV4::ReturnedValue get_index(const QV4::FunctionObject *f, const QV4::Value *thisObject, const QV4::Value *, int)
-{
- QV4::Scope scope(f);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- RETURN_RESULT(scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object")));
-
- RETURN_RESULT(QV4::Encode(o->d()->item->index));
-}
-
-template <typename T, typename M> static void setModelDataType(QMetaObjectBuilder *builder, M *metaType)
-{
- builder->setFlags(MetaObjectFlag::DynamicMetaObject);
- builder->setClassName(T::staticMetaObject.className());
- builder->setSuperClass(&T::staticMetaObject);
- metaType->propertyOffset = T::staticMetaObject.propertyCount();
- metaType->signalOffset = T::staticMetaObject.methodCount();
-}
-
-static void addProperty(QMetaObjectBuilder *builder, int propertyId, const QByteArray &propertyName, const QByteArray &propertyType)
-{
- builder->addSignal("__" + QByteArray::number(propertyId) + "()");
- QMetaPropertyBuilder property = builder->addProperty(
- propertyName, propertyType, propertyId);
- property.setWritable(true);
-}
-
-class VDMModelDelegateDataType;
-
-class QQmlDMCachedModelData : public QQmlDelegateModelItem
-{
-public:
- QQmlDMCachedModelData(
- const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
- VDMModelDelegateDataType *dataType,
- int index, int row, int column);
-
- int metaCall(QMetaObject::Call call, int id, void **arguments);
-
- virtual QVariant value(int role) const = 0;
- virtual void setValue(int role, const QVariant &value) = 0;
-
- void setValue(const QString &role, const QVariant &value) override;
- bool resolveIndex(const QQmlAdaptorModel &model, int idx) override;
-
- static QV4::ReturnedValue get_property(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
- static QV4::ReturnedValue set_property(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
-
- VDMModelDelegateDataType *type;
- QVector<QVariant> cachedData;
-};
-
-class VDMModelDelegateDataType
- : public QQmlRefCount
- , public QQmlAdaptorModel::Accessors
- , public QAbstractDynamicMetaObject
-{
-public:
- VDMModelDelegateDataType(QQmlAdaptorModel *model)
- : model(model)
- , propertyOffset(0)
- , signalOffset(0)
- , hasModelData(false)
- {
- }
-
- bool notify(
- const QQmlAdaptorModel &,
- const QList<QQmlDelegateModelItem *> &items,
- int index,
- int count,
- const QVector<int> &roles) const override
- {
- bool changed = roles.isEmpty() && !watchedRoles.isEmpty();
- if (!changed && !watchedRoles.isEmpty() && watchedRoleIds.isEmpty()) {
- QList<int> roleIds;
- for (const QByteArray &r : watchedRoles) {
- QHash<QByteArray, int>::const_iterator it = roleNames.find(r);
- if (it != roleNames.end())
- roleIds << it.value();
- }
- const_cast<VDMModelDelegateDataType *>(this)->watchedRoleIds = roleIds;
- }
-
- QVector<int> signalIndexes;
- for (int i = 0; i < roles.size(); ++i) {
- const int role = roles.at(i);
- if (!changed && watchedRoleIds.contains(role))
- changed = true;
-
- int propertyId = propertyRoles.indexOf(role);
- if (propertyId != -1)
- signalIndexes.append(propertyId + signalOffset);
- }
- if (roles.isEmpty()) {
- const int propertyRolesCount = propertyRoles.size();
- signalIndexes.reserve(propertyRolesCount);
- for (int propertyId = 0; propertyId < propertyRolesCount; ++propertyId)
- signalIndexes.append(propertyId + signalOffset);
- }
-
- QVarLengthArray<QQmlGuard<QQmlDelegateModelItem>> guardedItems;
- for (const auto item : items)
- guardedItems.append(item);
-
- for (const auto &item : std::as_const(guardedItems)) {
- if (item.isNull())
- continue;
-
- const int idx = item->modelIndex();
- if (idx >= index && idx < index + count) {
- for (int i = 0; i < signalIndexes.size(); ++i)
- QMetaObject::activate(item, signalIndexes.at(i), nullptr);
- }
- }
- return changed;
- }
-
- void replaceWatchedRoles(
- QQmlAdaptorModel &,
- const QList<QByteArray> &oldRoles,
- const QList<QByteArray> &newRoles) const override
- {
- VDMModelDelegateDataType *dataType = const_cast<VDMModelDelegateDataType *>(this);
-
- dataType->watchedRoleIds.clear();
- for (const QByteArray &oldRole : oldRoles)
- dataType->watchedRoles.removeOne(oldRole);
- dataType->watchedRoles += newRoles;
- }
-
- static QV4::ReturnedValue get_hasModelChildren(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
- {
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- RETURN_RESULT(scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object")));
-
- const QQmlAdaptorModel *const model = static_cast<QQmlDMCachedModelData *>(o->d()->item)->type->model;
- if (o->d()->item->index >= 0) {
- if (const QAbstractItemModel *const aim = model->aim())
- RETURN_RESULT(QV4::Encode(aim->hasChildren(aim->index(o->d()->item->index, 0, model->rootIndex))));
- }
- RETURN_RESULT(QV4::Encode(false));
- }
-
-
- void initializeConstructor(QQmlAdaptorModelEngineData *const data)
- {
- QV4::ExecutionEngine *v4 = data->v4;
- QV4::Scope scope(v4);
- QV4::ScopedObject proto(scope, v4->newObject());
- proto->defineAccessorProperty(QStringLiteral("index"), get_index, nullptr);
- proto->defineAccessorProperty(QStringLiteral("hasModelChildren"), get_hasModelChildren, nullptr);
- QV4::ScopedProperty p(scope);
-
- typedef QHash<QByteArray, int>::const_iterator iterator;
- for (iterator it = roleNames.constBegin(), end = roleNames.constEnd(); it != end; ++it) {
- const int propertyId = propertyRoles.indexOf(it.value());
- const QByteArray &propertyName = it.key();
-
- QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
- QV4::ExecutionContext *global = v4->rootContext();
- QV4::ScopedFunctionObject g(scope, v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
- QV4::ScopedFunctionObject s(scope, v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
- p->setGetter(g);
- p->setSetter(s);
- proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
- }
- prototype.set(v4, proto);
- }
-
- // QAbstractDynamicMetaObject
-
- void objectDestroyed(QObject *) override
- {
- release();
- }
-
- int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) override
- {
- return static_cast<QQmlDMCachedModelData *>(object)->metaCall(call, id, arguments);
- }
-
- QV4::PersistentValue prototype;
- QList<int> propertyRoles;
- QList<int> watchedRoleIds;
- QList<QByteArray> watchedRoles;
- QHash<QByteArray, int> roleNames;
- QQmlAdaptorModel *model;
- int propertyOffset;
- int signalOffset;
- bool hasModelData;
-};
-
-QQmlDMCachedModelData::QQmlDMCachedModelData(
- const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
- VDMModelDelegateDataType *dataType, int index, int row, int column)
- : QQmlDelegateModelItem(metaType, dataType, index, row, column)
- , type(dataType)
-{
- if (index == -1)
- cachedData.resize(type->hasModelData ? 1 : type->propertyRoles.size());
-
- QObjectPrivate::get(this)->metaObject = type;
-
- type->addref();
-}
-
-int QQmlDMCachedModelData::metaCall(QMetaObject::Call call, int id, void **arguments)
-{
- if (call == QMetaObject::ReadProperty && id >= type->propertyOffset) {
- const int propertyIndex = id - type->propertyOffset;
- if (index == -1) {
- if (!cachedData.isEmpty()) {
- *static_cast<QVariant *>(arguments[0]) = cachedData.at(
- type->hasModelData ? 0 : propertyIndex);
- }
- } else if (*type->model) {
- *static_cast<QVariant *>(arguments[0]) = value(type->propertyRoles.at(propertyIndex));
- }
- return -1;
- } else if (call == QMetaObject::WriteProperty && id >= type->propertyOffset) {
- const int propertyIndex = id - type->propertyOffset;
- if (index == -1) {
- const QMetaObject *meta = metaObject();
- if (cachedData.size() > 1) {
- cachedData[propertyIndex] = *static_cast<QVariant *>(arguments[0]);
- QMetaObject::activate(this, meta, propertyIndex, nullptr);
- } else if (cachedData.size() == 1) {
- cachedData[0] = *static_cast<QVariant *>(arguments[0]);
- QMetaObject::activate(this, meta, 0, nullptr);
- QMetaObject::activate(this, meta, 1, nullptr);
- }
- } else if (*type->model) {
- setValue(type->propertyRoles.at(propertyIndex), *static_cast<QVariant *>(arguments[0]));
- }
- return -1;
- } else {
- return qt_metacall(call, id, arguments);
- }
-}
-
-void QQmlDMCachedModelData::setValue(const QString &role, const QVariant &value)
-{
- QHash<QByteArray, int>::iterator it = type->roleNames.find(role.toUtf8());
- if (it != type->roleNames.end()) {
- for (int i = 0; i < type->propertyRoles.size(); ++i) {
- if (type->propertyRoles.at(i) == *it) {
- cachedData[i] = value;
- return;
- }
- }
- }
-}
-
-bool QQmlDMCachedModelData::resolveIndex(const QQmlAdaptorModel &adaptorModel, int idx)
-{
- if (index == -1) {
- Q_ASSERT(idx >= 0);
- cachedData.clear();
- setModelIndex(idx, adaptorModel.rowAt(idx), adaptorModel.columnAt(idx));
- const QMetaObject *meta = metaObject();
- const int propertyCount = type->propertyRoles.size();
- for (int i = 0; i < propertyCount; ++i)
- QMetaObject::activate(this, meta, i, nullptr);
- return true;
- } else {
- return false;
- }
-}
-
-QV4::ReturnedValue QQmlDMCachedModelData::get_property(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- uint propertyId = static_cast<const QV4::IndexedBuiltinFunction *>(b)->d()->index;
-
- QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->d()->item);
- if (o->d()->item->index == -1) {
- if (!modelData->cachedData.isEmpty()) {
- return scope.engine->fromVariant(
- modelData->cachedData.at(modelData->type->hasModelData ? 0 : propertyId));
- }
- } else if (*modelData->type->model) {
- return scope.engine->fromVariant(
- modelData->value(modelData->type->propertyRoles.at(propertyId)));
- }
- return QV4::Encode::undefined();
-}
-
-QV4::ReturnedValue QQmlDMCachedModelData::set_property(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
- if (!argc)
- return scope.engine->throwTypeError();
-
- uint propertyId = static_cast<const QV4::IndexedBuiltinFunction *>(b)->d()->index;
-
- if (o->d()->item->index == -1) {
- QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->d()->item);
- if (!modelData->cachedData.isEmpty()) {
- if (modelData->cachedData.size() > 1) {
- modelData->cachedData[propertyId]
- = QV4::ExecutionEngine::toVariant(argv[0], QMetaType {});
- QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), propertyId, nullptr);
- } else if (modelData->cachedData.size() == 1) {
- modelData->cachedData[0] = QV4::ExecutionEngine::toVariant(argv[0], QMetaType {});
- QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), 0, nullptr);
- QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), 1, nullptr);
- }
- }
- }
- return QV4::Encode::undefined();
-}
-
-//-----------------------------------------------------------------
-// QAbstractItemModel
-//-----------------------------------------------------------------
-
-class QQmlDMAbstractItemModelData : public QQmlDMCachedModelData
-{
- Q_OBJECT
- Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
-
-public:
- QQmlDMAbstractItemModelData(
- const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
- VDMModelDelegateDataType *dataType,
- int index, int row, int column)
- : QQmlDMCachedModelData(metaType, dataType, index, row, column)
- {
- }
-
- bool hasModelChildren() const
- {
- if (index >= 0) {
- if (const QAbstractItemModel *const model = type->model->aim())
- return model->hasChildren(model->index(row, column, type->model->rootIndex));
- }
- return false;
- }
-
- QVariant value(int role) const override
- {
- if (const QAbstractItemModel *aim = type->model->aim())
- return aim->index(row, column, type->model->rootIndex).data(role);
- return QVariant();
- }
-
- void setValue(int role, const QVariant &value) override
- {
- if (QAbstractItemModel *aim = type->model->aim())
- aim->setData(aim->index(row, column, type->model->rootIndex), value, role);
- }
-
- QV4::ReturnedValue get() override
- {
- if (type->prototype.isUndefined()) {
- QQmlAdaptorModelEngineData * const data = engineData(v4);
- type->initializeConstructor(data);
- }
- QV4::Scope scope(v4);
- QV4::ScopedObject proto(scope, type->prototype.value());
- QV4::ScopedObject o(scope, proto->engine()->memoryManager->allocate<QQmlDelegateModelItemObject>(this));
- o->setPrototypeOf(proto);
- ++scriptRef;
- return o.asReturnedValue();
- }
-};
-
-class VDMAbstractItemModelDataType : public VDMModelDelegateDataType
-{
-public:
- VDMAbstractItemModelDataType(QQmlAdaptorModel *model)
- : VDMModelDelegateDataType(model)
- {
- }
-
- int rowCount(const QQmlAdaptorModel &model) const override
- {
- if (const QAbstractItemModel *aim = model.aim())
- return aim->rowCount(model.rootIndex);
- return 0;
- }
-
- int columnCount(const QQmlAdaptorModel &model) const override
- {
- if (const QAbstractItemModel *aim = model.aim())
- return aim->columnCount(model.rootIndex);
- return 0;
- }
-
- void cleanup(QQmlAdaptorModel &) const override
- {
- release();
- }
-
- QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
- {
- if (!metaObject) {
- VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
- dataType->initializeMetaType(model);
- }
-
- if (const QAbstractItemModel *aim = model.aim()) {
- QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8());
- if (it != roleNames.end()) {
- return aim->index(model.rowAt(index), model.columnAt(index),
- model.rootIndex).data(*it);
- } else if (role == QLatin1String("hasModelChildren")) {
- return QVariant(aim->hasChildren(aim->index(model.rowAt(index),
- model.columnAt(index),
- model.rootIndex)));
- }
- }
- return QVariant();
- }
-
- QVariant parentModelIndex(const QQmlAdaptorModel &model) const override
- {
- if (const QAbstractItemModel *aim = model.aim())
- return QVariant::fromValue(aim->parent(model.rootIndex));
- return QVariant();
- }
-
- QVariant modelIndex(const QQmlAdaptorModel &model, int index) const override
- {
- if (const QAbstractItemModel *aim = model.aim())
- return QVariant::fromValue(aim->index(model.rowAt(index), model.columnAt(index),
- model.rootIndex));
- return QVariant();
- }
-
- bool canFetchMore(const QQmlAdaptorModel &model) const override
- {
- if (const QAbstractItemModel *aim = model.aim())
- return aim->canFetchMore(model.rootIndex);
- return false;
- }
-
- void fetchMore(QQmlAdaptorModel &model) const override
- {
- if (QAbstractItemModel *aim = model.aim())
- aim->fetchMore(model.rootIndex);
- }
-
- QQmlDelegateModelItem *createItem(
- QQmlAdaptorModel &model,
- const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
- int index, int row, int column) const override
- {
- VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
- if (!metaObject)
- dataType->initializeMetaType(model);
- return new QQmlDMAbstractItemModelData(metaType, dataType, index, row, column);
- }
-
- void initializeMetaType(const QQmlAdaptorModel &model)
- {
- QMetaObjectBuilder builder;
- setModelDataType<QQmlDMAbstractItemModelData>(&builder, this);
-
- const QByteArray propertyType = QByteArrayLiteral("QVariant");
- const QAbstractItemModel *aim = model.aim();
- const QHash<int, QByteArray> names = aim ? aim->roleNames() : QHash<int, QByteArray>();
- for (QHash<int, QByteArray>::const_iterator it = names.begin(), cend = names.end(); it != cend; ++it) {
- const int propertyId = propertyRoles.size();
- propertyRoles.append(it.key());
- roleNames.insert(it.value(), it.key());
- addProperty(&builder, propertyId, it.value(), propertyType);
- }
- if (propertyRoles.size() == 1) {
- hasModelData = true;
- const int role = names.begin().key();
- const QByteArray propertyName = QByteArrayLiteral("modelData");
-
- propertyRoles.append(role);
- roleNames.insert(propertyName, role);
- addProperty(&builder, 1, propertyName, propertyType);
- }
-
- metaObject.reset(builder.toMetaObject());
- *static_cast<QMetaObject *>(this) = *metaObject;
- propertyCache = QQmlPropertyCache::createStandalone(
- metaObject.data(), model.modelItemRevision);
- }
-};
-
-//-----------------------------------------------------------------
-// QQmlListAccessor
-//-----------------------------------------------------------------
-
-class QQmlDMListAccessorData : public QQmlDelegateModelItem
-{
- Q_OBJECT
- Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
-public:
- QQmlDMListAccessorData(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
- QQmlAdaptorModel::Accessors *accessor,
- int index, int row, int column, const QVariant &value)
- : QQmlDelegateModelItem(metaType, accessor, index, row, column)
- , cachedData(value)
- {
- }
-
- QVariant modelData() const
- {
- return cachedData;
- }
-
- void setModelData(const QVariant &data)
- {
- if (data == cachedData)
- return;
-
- cachedData = data;
- emit modelDataChanged();
- }
-
- static QV4::ReturnedValue get_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
- {
- QV4::ExecutionEngine *v4 = b->engine();
- const QQmlDelegateModelItemObject *o = thisObject->as<QQmlDelegateModelItemObject>();
- if (!o)
- return v4->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- return v4->fromVariant(static_cast<QQmlDMListAccessorData *>(o->d()->item)->cachedData);
- }
-
- static QV4::ReturnedValue set_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
- {
- QV4::ExecutionEngine *v4 = b->engine();
- const QQmlDelegateModelItemObject *o = thisObject->as<QQmlDelegateModelItemObject>();
- if (!o)
- return v4->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
- if (!argc)
- return v4->throwTypeError();
-
- static_cast<QQmlDMListAccessorData *>(o->d()->item)->setModelData(
- QV4::ExecutionEngine::toVariant(argv[0], QMetaType {}));
- return QV4::Encode::undefined();
- }
-
- QV4::ReturnedValue get() override
- {
- QQmlAdaptorModelEngineData *data = engineData(v4);
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(this));
- QV4::ScopedObject p(scope, data->listItemProto.value());
- o->setPrototypeOf(p);
- ++scriptRef;
- return o.asReturnedValue();
- }
-
- void setValue(const QString &role, const QVariant &value) override
- {
- if (role == QLatin1String("modelData"))
- cachedData = value;
- }
-
- bool resolveIndex(const QQmlAdaptorModel &model, int idx) override
- {
- if (index == -1) {
- index = idx;
- cachedData = model.list.at(idx);
- emit modelIndexChanged();
- emit modelDataChanged();
- return true;
- } else {
- return false;
- }
- }
-
-
-Q_SIGNALS:
- void modelDataChanged();
-
-private:
- QVariant cachedData;
-};
-
-
-class VDMListDelegateDataType : public QQmlRefCount, public QQmlAdaptorModel::Accessors
-{
-public:
- VDMListDelegateDataType()
- : QQmlRefCount()
- , QQmlAdaptorModel::Accessors()
- {}
-
- void cleanup(QQmlAdaptorModel &) const override
- {
- const_cast<VDMListDelegateDataType *>(this)->release();
- }
-
- int rowCount(const QQmlAdaptorModel &model) const override
- {
- return model.list.count();
- }
-
- int columnCount(const QQmlAdaptorModel &) const override
- {
- return 1;
- }
-
- QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
- {
- const QVariant entry = model.list.at(index);
- if (role == QLatin1String("modelData"))
- return entry;
-
- const QMetaType type = entry.metaType();
- if (type == QMetaType::fromType<QVariantMap>())
- return entry.toMap().value(role);
-
- if (type == QMetaType::fromType<QVariantHash>())
- return entry.toHash().value(role);
-
- const QMetaType::TypeFlags typeFlags = type.flags();
- if (typeFlags & QMetaType::PointerToQObject)
- return entry.value<QObject *>()->property(role.toUtf8());
-
- const QMetaObject *metaObject = type.metaObject();
- if (!metaObject) {
- // NB: This acquires the lock on QQmlMetaTypeData. If we had a QQmlEngine here,
- // we could use QQmlGadgetPtrWrapper::instance() to avoid this.
- if (const QQmlValueType *valueType = QQmlMetaType::valueType(type))
- metaObject = valueType->staticMetaObject();
- else
- return QVariant();
- }
-
- const int propertyIndex = metaObject->indexOfProperty(role.toUtf8());
- return metaObject->property(propertyIndex).readOnGadget(entry.constData());
- }
-
- QQmlDelegateModelItem *createItem(
- QQmlAdaptorModel &model,
- const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
- int index, int row, int column) const override
- {
- VDMListDelegateDataType *dataType = const_cast<VDMListDelegateDataType *>(this);
- if (!propertyCache) {
- dataType->propertyCache = QQmlPropertyCache::createStandalone(
- &QQmlDMListAccessorData::staticMetaObject, model.modelItemRevision);
- }
-
- return new QQmlDMListAccessorData(
- metaType,
- dataType,
- index, row, column,
- index >= 0 && index < model.list.count() ? model.list.at(index) : QVariant());
- }
-
- bool notify(const QQmlAdaptorModel &model, const QList<QQmlDelegateModelItem *> &items, int index, int count, const QVector<int> &) const override
- {
- for (auto modelItem : items) {
- const int modelItemIndex = modelItem->index;
- if (modelItemIndex < index || modelItemIndex >= index + count)
- continue;
-
- auto listModelItem = static_cast<QQmlDMListAccessorData *>(modelItem);
- QVariant updatedModelData = model.list.at(listModelItem->index);
- listModelItem->setModelData(updatedModelData);
- }
- return true;
- }
-};
-
-//-----------------------------------------------------------------
-// QObject
-//-----------------------------------------------------------------
-
-class VDMObjectDelegateDataType;
-class QQmlDMObjectData : public QQmlDelegateModelItem, public QQmlAdaptorModelProxyInterface
-{
- Q_OBJECT
- Q_PROPERTY(QObject *modelData READ modelData NOTIFY modelDataChanged)
- Q_INTERFACES(QQmlAdaptorModelProxyInterface)
-public:
- QQmlDMObjectData(
- const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
- VDMObjectDelegateDataType *dataType,
- int index, int row, int column,
- QObject *object);
-
- void setModelData(QObject *modelData)
- {
- if (modelData == object)
- return;
-
- object = modelData;
- emit modelDataChanged();
- }
-
- QObject *modelData() const { return object; }
- QObject *proxiedObject() override { return object; }
-
- QPointer<QObject> object;
-
-Q_SIGNALS:
- void modelDataChanged();
-};
-
-class VDMObjectDelegateDataType : public QQmlRefCount, public QQmlAdaptorModel::Accessors
-{
-public:
- int propertyOffset;
- int signalOffset;
- bool shared;
- QMetaObjectBuilder builder;
-
- VDMObjectDelegateDataType()
- : propertyOffset(0)
- , signalOffset(0)
- , shared(true)
- {
- }
-
- VDMObjectDelegateDataType(const VDMObjectDelegateDataType &type)
- : QQmlRefCount()
- , QQmlAdaptorModel::Accessors()
- , propertyOffset(type.propertyOffset)
- , signalOffset(type.signalOffset)
- , shared(false)
- , builder(type.metaObject.data(), QMetaObjectBuilder::Properties
- | QMetaObjectBuilder::Signals
- | QMetaObjectBuilder::SuperClass
- | QMetaObjectBuilder::ClassName)
- {
- builder.setFlags(MetaObjectFlag::DynamicMetaObject);
- }
-
- int rowCount(const QQmlAdaptorModel &model) const override
- {
- return model.list.count();
- }
-
- int columnCount(const QQmlAdaptorModel &) const override
- {
- return 1;
- }
-
- QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
- {
- if (QObject *object = model.list.at(index).value<QObject *>())
- return object->property(role.toUtf8());
- return QVariant();
- }
-
- QQmlDelegateModelItem *createItem(
- QQmlAdaptorModel &model,
- const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
- int index, int row, int column) const override
- {
- VDMObjectDelegateDataType *dataType = const_cast<VDMObjectDelegateDataType *>(this);
- if (!metaObject)
- dataType->initializeMetaType(model);
- return index >= 0 && index < model.list.count()
- ? new QQmlDMObjectData(metaType, dataType, index, row, column, qvariant_cast<QObject *>(model.list.at(index)))
- : nullptr;
- }
-
- void initializeMetaType(QQmlAdaptorModel &model)
- {
- Q_UNUSED(model);
- setModelDataType<QQmlDMObjectData>(&builder, this);
-
- metaObject.reset(builder.toMetaObject());
- // Note: ATM we cannot create a shared property cache for this class, since each model
- // object can have different properties. And to make those properties available to the
- // delegate, QQmlDMObjectData makes use of a QAbstractDynamicMetaObject subclass
- // (QQmlDMObjectDataMetaObject), which we cannot represent in a QQmlPropertyCache.
- // By not having a shared property cache, revisioned properties in QQmlDelegateModelItem
- // will always be available to the delegate, regardless of the import version.
- }
-
- void cleanup(QQmlAdaptorModel &) const override
- {
- const_cast<VDMObjectDelegateDataType *>(this)->release();
- }
-
- bool notify(const QQmlAdaptorModel &model, const QList<QQmlDelegateModelItem *> &items, int index, int count, const QVector<int> &) const override
- {
- for (auto modelItem : items) {
- const int modelItemIndex = modelItem->index;
- if (modelItemIndex < index || modelItemIndex >= index + count)
- continue;
-
- auto objectModelItem = static_cast<QQmlDMObjectData *>(modelItem);
- QObject *updatedModelData = qvariant_cast<QObject *>(model.list.at(objectModelItem->index));
- objectModelItem->setModelData(updatedModelData);
- }
- return true;
- }
-};
-
-class QQmlDMObjectDataMetaObject : public QAbstractDynamicMetaObject
-{
-public:
- QQmlDMObjectDataMetaObject(QQmlDMObjectData *data, VDMObjectDelegateDataType *type)
- : m_data(data)
- , m_type(type)
- {
- QObjectPrivate *op = QObjectPrivate::get(m_data);
- *static_cast<QMetaObject *>(this) = *type->metaObject;
- op->metaObject = this;
- m_type->addref();
- }
-
- ~QQmlDMObjectDataMetaObject()
- {
- m_type->release();
- }
-
- int metaCall(QObject *o, QMetaObject::Call call, int id, void **arguments) override
- {
- Q_ASSERT(o == m_data);
- Q_UNUSED(o);
-
- static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
- if (id >= m_type->propertyOffset
- && (call == QMetaObject::ReadProperty
- || call == QMetaObject::WriteProperty
- || call == QMetaObject::ResetProperty)) {
- if (m_data->object)
- QMetaObject::metacall(m_data->object, call, id - m_type->propertyOffset + objectPropertyOffset, arguments);
- return -1;
- } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
- QMetaObject::activate(m_data, this, id - m_type->signalOffset, nullptr);
- return -1;
- } else {
- return m_data->qt_metacall(call, id, arguments);
- }
- }
-
- int createProperty(const char *name, const char *) override
- {
- if (!m_data->object)
- return -1;
- const QMetaObject *metaObject = m_data->object->metaObject();
- static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
-
- const int previousPropertyCount = propertyCount() - propertyOffset();
- int propertyIndex = metaObject->indexOfProperty(name);
- if (propertyIndex == -1)
- return -1;
- if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount())
- return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
-
- if (m_type->shared) {
- VDMObjectDelegateDataType *type = m_type;
- m_type = new VDMObjectDelegateDataType(*m_type);
- type->release();
- }
-
- const int previousMethodCount = methodCount();
- int notifierId = previousMethodCount - methodOffset();
- for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - objectPropertyOffset; ++propertyId) {
- QMetaProperty property = metaObject->property(propertyId + objectPropertyOffset);
- QMetaPropertyBuilder propertyBuilder;
- if (property.hasNotifySignal()) {
- m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
- propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
- ++notifierId;
- } else {
- propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
- }
- propertyBuilder.setWritable(property.isWritable());
- propertyBuilder.setResettable(property.isResettable());
- propertyBuilder.setConstant(property.isConstant());
- }
-
- m_type->metaObject.reset(m_type->builder.toMetaObject());
- *static_cast<QMetaObject *>(this) = *m_type->metaObject;
-
- notifierId = previousMethodCount;
- for (int i = previousPropertyCount; i < metaObject->propertyCount() - objectPropertyOffset; ++i) {
- QMetaProperty property = metaObject->property(i + objectPropertyOffset);
- if (property.hasNotifySignal()) {
- QQmlPropertyPrivate::connect(
- m_data->object, property.notifySignalIndex(), m_data, notifierId);
- ++notifierId;
- }
- }
- return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
- }
-
- QQmlDMObjectData *m_data;
- VDMObjectDelegateDataType *m_type;
-};
-
-QQmlDMObjectData::QQmlDMObjectData(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
- VDMObjectDelegateDataType *dataType,
- int index, int row, int column,
- QObject *object)
- : QQmlDelegateModelItem(metaType, dataType, index, row, column)
- , object(object)
-{
- new QQmlDMObjectDataMetaObject(this, dataType);
-}
-
-//-----------------------------------------------------------------
-// QQmlAdaptorModel
-//-----------------------------------------------------------------
-
-static const QQmlAdaptorModel::Accessors qt_vdm_null_accessors;
-
QQmlAdaptorModel::Accessors::~Accessors()
{
}
QQmlAdaptorModel::QQmlAdaptorModel()
: QQmlGuard<QObject>(QQmlAdaptorModel::objectDestroyedImpl, nullptr)
- , accessors(&qt_vdm_null_accessors)
+ , accessors(&m_nullAccessors)
{
}
@@ -983,24 +53,24 @@ void QQmlAdaptorModel::setModel(const QVariant &variant)
} else if (list.type() != QQmlListAccessor::Invalid
&& list.type() != QQmlListAccessor::Instance) { // Null QObject
setObject(nullptr);
- accessors = new VDMListDelegateDataType;
+ accessors = new VDMListDelegateDataType(this);
} else {
setObject(nullptr);
- accessors = &qt_vdm_null_accessors;
+ accessors = &m_nullAccessors;
}
}
void QQmlAdaptorModel::invalidateModel()
{
accessors->cleanup(*this);
- accessors = &qt_vdm_null_accessors;
+ accessors = &m_nullAccessors;
// Don't clear the model object as we still need the guard to clear the list variant if the
// object is destroyed.
}
bool QQmlAdaptorModel::isValid() const
{
- return accessors != &qt_vdm_null_accessors;
+ return accessors != &m_nullAccessors;
}
int QQmlAdaptorModel::count() const
@@ -1046,21 +116,4 @@ void QQmlAdaptorModel::objectDestroyedImpl(QQmlGuardImpl *guard)
This->setModel(QVariant());
}
-QQmlAdaptorModelEngineData::QQmlAdaptorModelEngineData(QV4::ExecutionEngine *v4)
- : v4(v4)
-{
- QV4::Scope scope(v4);
- QV4::ScopedObject proto(scope, v4->newObject());
- proto->defineAccessorProperty(QStringLiteral("index"), get_index, nullptr);
- proto->defineAccessorProperty(QStringLiteral("modelData"),
- QQmlDMListAccessorData::get_modelData, QQmlDMListAccessorData::set_modelData);
- listItemProto.set(v4, proto);
-}
-
-QQmlAdaptorModelEngineData::~QQmlAdaptorModelEngineData()
-{
-}
-
QT_END_NAMESPACE
-
-#include <qqmladaptormodel.moc>