1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <private/qqmldmlistaccessordata_p.h>
5
6QT_BEGIN_NAMESPACE
7
8QQmlDMListAccessorData::QQmlDMListAccessorData(
9 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
10 VDMListDelegateDataType *dataType,
11 int index, int row, int column, const QVariant &value)
12 : QQmlDelegateModelItem(metaType, dataType, index, row, column)
13 , cachedData(value)
14{
15 QObjectPrivate::get(o: this)->metaObject = dataType;
16 dataType->addref();
17}
18
19void QQmlDMListAccessorData::setModelData(const QVariant &data) {
20 if (data == cachedData)
21 return;
22
23 cachedData = data;
24 static_cast<const VDMListDelegateDataType *>(QObjectPrivate::get(o: this)->metaObject)
25 ->emitAllSignals(accessor: this);
26}
27
28void QQmlDMListAccessorData::setValue(const QString &role, const QVariant &value)
29{
30 // Used only for initialization of the cached data. Does not have to emit change signals.
31 if (role == QLatin1String("modelData") || role.isEmpty())
32 cachedData = value;
33 else
34 VDMListDelegateDataType::setValue(row: &cachedData, role, value);
35}
36
37bool QQmlDMListAccessorData::resolveIndex(const QQmlAdaptorModel &model, int idx)
38{
39 if (index == -1) {
40 index = idx;
41 setModelData(model.list.at(idx));
42 emit modelIndexChanged();
43 return true;
44 } else {
45 return false;
46 }
47}
48
49void VDMListDelegateDataType::emitAllSignals(QQmlDMListAccessorData *accessor) const
50{
51 for (int i = propertyOffset, end = propertyCount(); i != end; ++i)
52 QMetaObject::activate(sender: accessor, this, local_signal_index: i - propertyOffset, argv: nullptr);
53 emit accessor->modelDataChanged();
54}
55
56int VDMListDelegateDataType::metaCall(
57 QObject *object, QMetaObject::Call call, int id, void **arguments)
58{
59 Q_ASSERT(qobject_cast<QQmlDMListAccessorData *>(object));
60 QQmlDMListAccessorData *accessor = static_cast<QQmlDMListAccessorData *>(object);
61
62 switch (call) {
63 case QMetaObject::ReadProperty: {
64 if (id < propertyOffset)
65 break;
66
67 QVariant *result = static_cast<QVariant *>(arguments[0]);
68 const QByteArray name = property(index: id).name();
69 const QVariant data = accessor->index == -1
70 ? accessor->modelData()
71 : model->list.at(accessor->index);
72 *result = value(row: &data, role: name);
73 return -1;
74 }
75 case QMetaObject::WriteProperty: {
76 if (id < propertyOffset)
77 break;
78
79 const QVariant &argument = *static_cast<QVariant *>(arguments[0]);
80 const QByteArray name = property(index: id).name();
81 QVariant data = accessor->index == -1
82 ? accessor->modelData()
83 : model->list.at(accessor->index);
84 if (argument == value(row: &data, role: name))
85 return -1;
86 setValue(row: &data, role: name, value: argument);
87 if (accessor->index == -1)
88 accessor->cachedData = data;
89 else
90 model->list.set(accessor->index, data);
91 QMetaObject::activate(sender: accessor, this, local_signal_index: id - propertyOffset, argv: nullptr);
92 emit accessor->modelDataChanged();
93 return -1;
94 }
95 default:
96 break;
97 }
98
99 return accessor->qt_metacall(call, id, arguments);
100}
101
102int VDMListDelegateDataType::createProperty(const char *name, const char *)
103{
104 const int propertyIndex = propertyCount() - propertyOffset;
105
106 // We use QVariant because the types may be different in the different objects.
107 QQmlAdaptorModelEngineData::addProperty(
108 builder: &builder, propertyId: propertyIndex, propertyName: name, QByteArrayLiteral("QVariant"));
109
110 metaObject.reset(other: builder.toMetaObject());
111 *static_cast<QMetaObject *>(this) = *metaObject;
112 return propertyIndex + propertyOffset;
113}
114
115QMetaObject *VDMListDelegateDataType::toDynamicMetaObject(QObject *object)
116{
117 if (const QQmlRefPointer<QQmlContextData> &contextData
118 = static_cast<QQmlDMListAccessorData *>(object)->contextData) {
119 if (contextData->contextObject() == object) {
120 // We are using context properties. There should be a propertyCache so that row and
121 // column are hidden. We shall also return the static metaObject in that case.
122
123 if (!propertyCache) {
124 propertyCache = QQmlPropertyCache::createStandalone(
125 &QQmlDMListAccessorData::staticMetaObject, metaObjectRevision: model->modelItemRevision);
126 if (QQmlData *ddata = QQmlData::get(object, create: true))
127 ddata->propertyCache = propertyCache;
128 }
129
130 // ### Qt 7: Return const from toDynamicMetaObject() and drop the const_cast.
131 return const_cast<QMetaObject *>(&QQmlDMListAccessorData::staticMetaObject);
132 }
133 }
134
135 // If the context object is not the model object, we are using required properties.
136 // In that case, allow the creation of extra properties.
137 return this;
138}
139
140QT_END_NAMESPACE
141

source code of qtdeclarative/src/qmlmodels/qqmldmlistaccessordata.cpp