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
qqmldmobjectdata_p.h
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#ifndef QQMLDMOBJECTDATA_P_H
6#define QQMLDMOBJECTDATA_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqmladaptormodelenginedata_p.h>
20#include <private/qqmldelegatemodel_p_p.h>
21
22#include <private/qobject_p.h>
23#include <QtCore/qpointer.h>
24
25QT_BEGIN_NAMESPACE
26
27class VDMObjectDelegateDataType;
29{
30 Q_OBJECT
31 Q_PROPERTY(QObject *modelData READ modelData NOTIFY modelDataChanged)
33public:
37 int index, int row, int column,
39
40 void setModelData(QObject *modelData)
41 {
42 if (modelData == m_modelData)
43 return;
44
45 m_modelData = modelData;
46 emit modelDataChanged();
47 }
48
49 QObject *modelData() const { return m_modelData; }
51
54
55private:
56 QPointer<QObject> m_modelData;
57};
58
59class VDMObjectDelegateDataType final
60 : public QQmlRefCounted<VDMObjectDelegateDataType>,
61 public QQmlAdaptorModel::Accessors
62{
63public:
67 int signalOffset = 0;
68 bool shared = false;
69
70 VDMObjectDelegateDataType(QQmlAdaptorModel *model)
71 : model(model)
72 , shared(true)
73 {
74 }
75
76 VDMObjectDelegateDataType(const VDMObjectDelegateDataType &type)
84 {
85 builder.setFlags(MetaObjectFlag::DynamicMetaObject);
86 }
87
88 int rowCount(const QQmlAdaptorModel &model) const override
89 {
90 return model.list.count();
91 }
92
93 int columnCount(const QQmlAdaptorModel &) const override
94 {
95 return 1;
96 }
97
98 QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
99 {
100 if (QObject *object = model.list.at(index).value<QObject *>())
101 return object->property(role.toUtf8());
102 return QVariant();
103 }
104
106 QQmlAdaptorModel &model,
107 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
108 int index, int row, int column) override
109 {
110 if (!metaObject)
112 return index >= 0 && index < model.list.count()
113 ? new QQmlDMObjectData(metaType, this, index, row, column, qvariant_cast<QObject *>(model.list.at(index)))
114 : nullptr;
115 }
116
118 {
119 QQmlAdaptorModelEngineData::setModelDataType<QQmlDMObjectData>(&builder, this);
120
121 metaObject.reset(builder.toMetaObject());
122 // Note: ATM we cannot create a shared property cache for this class, since each model
123 // object can have different properties. And to make those properties available to the
124 // delegate, QQmlDMObjectData makes use of a QAbstractDynamicMetaObject subclass
125 // (QQmlDMObjectDataMetaObject), which we cannot represent in a QQmlPropertyCache.
126 // By not having a shared property cache, revisioned properties in QQmlDelegateModelItem
127 // will always be available to the delegate, regardless of the import version.
128 }
129
130 void cleanup(QQmlAdaptorModel &) const override
131 {
132 release();
133 }
134
135 bool notify(const QQmlAdaptorModel &model, const QList<QQmlDelegateModelItem *> &items, int index, int count, const QList<int> &) const override
136 {
137 for (auto modelItem : items) {
138 const int modelItemIndex = modelItem->modelIndex();
139 if (modelItemIndex < index || modelItemIndex >= index + count)
140 continue;
141
142 auto objectModelItem = static_cast<QQmlDMObjectData *>(modelItem);
143 QObject *updatedModelData = qvariant_cast<QObject *>(
144 model.list.at(objectModelItem->modelIndex()));
145 objectModelItem->setModelData(updatedModelData);
146 }
147 return true;
148 }
149};
150
152{
153public:
154 QQmlDMObjectDataMetaObject(QQmlDMObjectData *data, VDMObjectDelegateDataType *type)
155 : m_data(data)
156 , m_type(type)
157 {
158 QObjectPrivate *op = QObjectPrivate::get(m_data);
159 *static_cast<QMetaObject *>(this) = *type->metaObject;
160 op->metaObject = this;
161 m_type->addref();
162 }
163
165 {
166 m_type->release();
167 }
168
169 int metaCall(QObject *o, QMetaObject::Call call, int id, void **arguments) override
170 {
171 Q_ASSERT(o == m_data);
172 Q_UNUSED(o);
173
174 static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
175 if (id >= m_type->propertyOffset
176 && (call == QMetaObject::ReadProperty
177 || call == QMetaObject::WriteProperty
178 || call == QMetaObject::ResetProperty)) {
179 if (QObject *modelData = m_data->modelData()) {
180 QMetaObject::metacall(
181 modelData, call, id - m_type->propertyOffset + objectPropertyOffset,
182 arguments);
183 }
184 return -1;
185 } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
186 QMetaObject::activate(m_data, this, id - m_type->signalOffset, nullptr);
187 return -1;
188 } else {
189 return m_data->qt_metacall(call, id, arguments);
190 }
191 }
192
193 int createProperty(const char *name, const char *) override
194 {
195 QObject *modelData = m_data->modelData();
196 if (!modelData)
197 return -1;
198 const QMetaObject *metaObject = modelData->metaObject();
199 static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
200
201 const int previousPropertyCount = propertyCount() - propertyOffset();
202 int propertyIndex = metaObject->indexOfProperty(name);
203 if (propertyIndex == -1)
204 return -1;
205 if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount())
206 return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
207
208 if (m_type->shared) {
209 VDMObjectDelegateDataType *type = m_type;
210 m_type = new VDMObjectDelegateDataType(*m_type);
211 type->release();
212 }
213
214 const int previousMethodCount = methodCount();
215 int notifierId = previousMethodCount - methodOffset();
216 for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - objectPropertyOffset; ++propertyId) {
217 QMetaProperty property = metaObject->property(propertyId + objectPropertyOffset);
218 QMetaPropertyBuilder propertyBuilder;
219 if (property.hasNotifySignal()) {
220 m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
221 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
222 ++notifierId;
223 } else {
224 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
225 }
226 const bool modelWritable = m_type->model->delegateModelAccess != QQmlDelegateModel::ReadOnly;
227 propertyBuilder.setWritable(modelWritable && property.isWritable());
228 propertyBuilder.setResettable(modelWritable && property.isResettable());
229 propertyBuilder.setConstant(property.isConstant());
230 }
231
232 m_type->metaObject.reset(m_type->builder.toMetaObject());
233 *static_cast<QMetaObject *>(this) = *m_type->metaObject;
234
235 notifierId = previousMethodCount;
236 for (int i = previousPropertyCount; i < metaObject->propertyCount() - objectPropertyOffset; ++i) {
237 QMetaProperty property = metaObject->property(i + objectPropertyOffset);
238 if (property.hasNotifySignal()) {
239 QQmlPropertyPrivate::connect(
240 modelData, property.notifySignalIndex(), m_data, notifierId);
241 ++notifierId;
242 }
243 }
244 return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
245 }
246
248 VDMObjectDelegateDataType *m_type;
249};
250
251QT_END_NAMESPACE
252
253#endif // QQMLDMOBJECTDATA_P_H
int metaCall(QObject *o, QMetaObject::Call call, int id, void **arguments) override
QQmlDMObjectDataMetaObject(QQmlDMObjectData *data, VDMObjectDelegateDataType *type)
int createProperty(const char *name, const char *) override
VDMObjectDelegateDataType * m_type
QObject * modelData() const
void setModelData(QObject *modelData)
QQmlRefPointer< QQmlContextData > initProxy() final
int rowCount(const QQmlAdaptorModel &model) const override
QQmlDelegateModelItem * createItem(QQmlAdaptorModel &model, const QQmlRefPointer< QQmlDelegateModelItemMetaType > &metaType, int index, int row, int column) override
VDMObjectDelegateDataType(QQmlAdaptorModel *model)
VDMObjectDelegateDataType(const VDMObjectDelegateDataType &type)
int columnCount(const QQmlAdaptorModel &) const override
bool notify(const QQmlAdaptorModel &model, const QList< QQmlDelegateModelItem * > &items, int index, int count, const QList< int > &) const override
QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
void cleanup(QQmlAdaptorModel &) const override