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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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