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 (hasValidModelIndex())
51 return false;
52
53 setModelIndex(idx, modelRow(), modelColumn());
54 setModelData(model.list.at(idx));
55 emit modelIndexChanged();
56 return true;
57}
58
59void VDMListDelegateDataType::emitAllSignals(QQmlDMListAccessorData *accessor) const
60{
61 for (int i = propertyOffset, end = propertyCount(); i != end; ++i)
62 QMetaObject::activate(accessor, this, i - propertyOffset, 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(id).name();
79 const QVariant data = accessor->hasValidModelIndex()
80 ? model->list.at(accessor->modelIndex())
81 : accessor->modelData();
82 *result = value(&data, 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(id).name();
91 QVariant data = accessor->hasValidModelIndex()
92 ? model->list.at(accessor->modelIndex())
93 : accessor->modelData();
94 if (argument == value(&data, name))
95 return -1;
96 setValue(&data, name, argument);
97 if (accessor->hasValidModelIndex()) {
98 model->list.set(accessor->modelIndex(), data);
99 accessor->metaType()->emitModelChanged();
100 } else {
101 accessor->cachedData = data;
102 accessor->cachedDataClean = false;
103 }
104 QMetaObject::activate(accessor, this, id - propertyOffset, nullptr);
105 emit accessor->modelDataChanged();
106 return -1;
107 }
108 default:
109 break;
110 }
111
112 return accessor->qt_metacall(call, id, arguments);
113}
114
115int VDMListDelegateDataType::createProperty(const char *name, const char *)
116{
117 const int propertyIndex = propertyCount() - propertyOffset;
118
119 // We use QVariant because the types may be different in the different objects.
120 QQmlAdaptorModelEngineData::addProperty(
121 &builder, propertyIndex, name, QByteArrayLiteral("QVariant"),
122 model->delegateModelAccess != QQmlDelegateModel::ReadOnly);
123
124 metaObject.reset(builder.toMetaObject());
125 *static_cast<QMetaObject *>(this) = *metaObject;
126 return propertyIndex + propertyOffset;
127}
128
129#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
130const QMetaObject *VDMListDelegateDataType::toDynamicMetaObject(QObject *object) const
131#else
132QMetaObject *VDMListDelegateDataType::toDynamicMetaObject(QObject *object)
133#endif
134{
135 QQmlDMListAccessorData *data = static_cast<QQmlDMListAccessorData *>(object);
136 if (!data->usesStructuredModelData()) {
137 // We cannot produce structured modelData. There should be a propertyCache so that row and
138 // column are hidden. We shall also return the static metaObject in that case.
139
140 if (!propertyCache) {
141 propertyCache = QQmlPropertyCache::createStandalone(
142 &QQmlDMListAccessorData::staticMetaObject, model->modelItemRevision);
143 if (QQmlData *ddata = QQmlData::get(object, true))
144 ddata->propertyCache = propertyCache;
145 }
146
147#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
148 return &QQmlDMListAccessorData::staticMetaObject;
149#else
150 return const_cast<QMetaObject *>(&QQmlDMListAccessorData::staticMetaObject);
151#endif
152 }
153
154 // If the context object is not the model object, we are using required properties.
155 // In that case, create any extra properties.
156 if (!data->cachedDataClean) {
157 createMissingProperties(&data->cachedData);
158 data->cachedDataClean = true;
159 }
160 return this;
161}
162
163QT_END_NAMESPACE