Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmldmlistaccessordata.cpp
Go to the documentation of this file.
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// Qt-Security score:significant
4
5#include <private/qqmldmlistaccessordata_p.h>
6
7QT_BEGIN_NAMESPACE
8
9QQmlDMListAccessorData::QQmlDMListAccessorData(
10 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
11 VDMListDelegateDataType *dataType,
12 int index, int row, int column, const QVariant &value)
13 : QQmlDelegateModelItem(metaType, dataType, index, row, column)
14 , cachedData(value)
15{
16 QObjectPrivate::get(this)->metaObject = dataType;
17 dataType->addref();
18}
19
20QQmlDMListAccessorData::~QQmlDMListAccessorData()
21{
22 QObjectPrivate *d = QObjectPrivate::get(this);
23 static_cast<VDMListDelegateDataType *>(d->metaObject)->release();
24 d->metaObject = nullptr;
25}
26
27void QQmlDMListAccessorData::setModelData(const QVariant &data) {
28 if (data == cachedData)
29 return;
30
31 cachedData = data;
32 cachedDataClean = false;
33 static_cast<const VDMListDelegateDataType *>(QObjectPrivate::get(this)->metaObject)
34 ->emitAllSignals(this);
35}
36
37void QQmlDMListAccessorData::setValue(const QString &role, const QVariant &value)
38{
39 // Used only for initialization of the cached data. Does not have to emit change signals.
40 Q_ASSERT(!cachedDataClean);
41
42 if (role == QLatin1String("modelData") || role.isEmpty())
43 cachedData = value;
44 else
45 VDMListDelegateDataType::setValue(&cachedData, role, value);
46}
47
48bool QQmlDMListAccessorData::resolveIndex(const QQmlAdaptorModel &model, int idx)
49{
50 if (index == -1) {
51 index = idx;
52 setModelData(model.list.at(idx));
53 emit modelIndexChanged();
54 return true;
55 } else {
56 return false;
57 }
58}
59
60void VDMListDelegateDataType::emitAllSignals(QQmlDMListAccessorData *accessor) const
61{
62 for (int i = propertyOffset, end = propertyCount(); i != end; ++i)
63 QMetaObject::activate(accessor, this, i - propertyOffset, nullptr);
64 emit accessor->modelDataChanged();
65}
66
67int VDMListDelegateDataType::metaCall(
68 QObject *object, QMetaObject::Call call, int id, void **arguments)
69{
70 Q_ASSERT(qobject_cast<QQmlDMListAccessorData *>(object));
71 QQmlDMListAccessorData *accessor = static_cast<QQmlDMListAccessorData *>(object);
72
73 switch (call) {
74 case QMetaObject::ReadProperty: {
75 if (id < propertyOffset)
76 break;
77
78 QVariant *result = static_cast<QVariant *>(arguments[0]);
79 const QByteArray name = property(id).name();
80 const QVariant data = accessor->index == -1
81 ? accessor->modelData()
82 : model->list.at(accessor->index);
83 *result = value(&data, name);
84 return -1;
85 }
86 case QMetaObject::WriteProperty: {
87 if (id < propertyOffset)
88 break;
89
90 const QVariant &argument = *static_cast<QVariant *>(arguments[0]);
91 const QByteArray name = property(id).name();
92 QVariant data = accessor->index == -1
93 ? accessor->modelData()
94 : model->list.at(accessor->index);
95 if (argument == value(&data, name))
96 return -1;
97 setValue(&data, name, argument);
98 if (accessor->index == -1) {
99 accessor->cachedData = data;
100 accessor->cachedDataClean = false;
101 } else {
102 model->list.set(accessor->index, data);
103 accessor->metaType->emitModelChanged();
104 }
105 QMetaObject::activate(accessor, this, id - propertyOffset, nullptr);
106 emit accessor->modelDataChanged();
107 return -1;
108 }
109 default:
110 break;
111 }
112
113 return accessor->qt_metacall(call, id, arguments);
114}
115
116int VDMListDelegateDataType::createProperty(const char *name, const char *)
117{
118 const int propertyIndex = propertyCount() - propertyOffset;
119
120 // We use QVariant because the types may be different in the different objects.
121 QQmlAdaptorModelEngineData::addProperty(
122 &builder, propertyIndex, name, QByteArrayLiteral("QVariant"),
123 model->delegateModelAccess != QQmlDelegateModel::ReadOnly);
124
125 metaObject.reset(builder.toMetaObject());
126 *static_cast<QMetaObject *>(this) = *metaObject;
127 return propertyIndex + propertyOffset;
128}
129
130#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
131const QMetaObject *VDMListDelegateDataType::toDynamicMetaObject(QObject *object) const
132#else
133QMetaObject *VDMListDelegateDataType::toDynamicMetaObject(QObject *object)
134#endif
135{
136 QQmlDMListAccessorData *data = static_cast<QQmlDMListAccessorData *>(object);
137 if (!data->useStructuredModelData) {
138 // We cannot produce structured modelData. There should be a propertyCache so that row and
139 // column are hidden. We shall also return the static metaObject in that case.
140
141 if (!propertyCache) {
142 propertyCache = QQmlPropertyCache::createStandalone(
143 &QQmlDMListAccessorData::staticMetaObject, model->modelItemRevision);
144 if (QQmlData *ddata = QQmlData::get(object, true))
145 ddata->propertyCache = propertyCache;
146 }
147
148#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
149 return &QQmlDMListAccessorData::staticMetaObject;
150#else
151 return const_cast<QMetaObject *>(&QQmlDMListAccessorData::staticMetaObject);
152#endif
153 }
154
155 // If the context object is not the model object, we are using required properties.
156 // In that case, create any extra properties.
157 if (!data->cachedDataClean) {
158 createMissingProperties(&data->cachedData);
159 data->cachedDataClean = true;
160 }
161 return this;
162}
163
164QT_END_NAMESPACE