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 == object)
43 return;
44
45 object = modelData;
46 emit modelDataChanged();
47 }
48
49 QObject *modelData() const { return object; }
51
53
56};
57
58class VDMObjectDelegateDataType final
59 : public QQmlRefCounted<VDMObjectDelegateDataType>,
60 public QQmlAdaptorModel::Accessors
61{
62public:
66 int signalOffset = 0;
67 bool shared = false;
68
69 VDMObjectDelegateDataType(QQmlAdaptorModel *model)
70 : model(model)
71 , shared(true)
72 {
73 }
74
75 VDMObjectDelegateDataType(const VDMObjectDelegateDataType &type)
83 {
84 builder.setFlags(MetaObjectFlag::DynamicMetaObject);
85 }
86
87 int rowCount(const QQmlAdaptorModel &model) const override
88 {
89 return model.list.count();
90 }
91
92 int columnCount(const QQmlAdaptorModel &) const override
93 {
94 return 1;
95 }
96
97 QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
98 {
99 if (QObject *object = model.list.at(index).value<QObject *>())
100 return object->property(role.toUtf8());
101 return QVariant();
102 }
103
105 QQmlAdaptorModel &model,
106 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
107 int index, int row, int column) override
108 {
109 if (!metaObject)
111 return index >= 0 && index < model.list.count()
112 ? new QQmlDMObjectData(metaType, this, index, row, column, qvariant_cast<QObject *>(model.list.at(index)))
113 : nullptr;
114 }
115
117 {
118 QQmlAdaptorModelEngineData::setModelDataType<QQmlDMObjectData>(&builder, this);
119
120 metaObject.reset(builder.toMetaObject());
121 // Note: ATM we cannot create a shared property cache for this class, since each model
122 // object can have different properties. And to make those properties available to the
123 // delegate, QQmlDMObjectData makes use of a QAbstractDynamicMetaObject subclass
124 // (QQmlDMObjectDataMetaObject), which we cannot represent in a QQmlPropertyCache.
125 // By not having a shared property cache, revisioned properties in QQmlDelegateModelItem
126 // will always be available to the delegate, regardless of the import version.
127 }
128
129 void cleanup(QQmlAdaptorModel &) const override
130 {
131 release();
132 }
133
134 bool notify(const QQmlAdaptorModel &model, const QList<QQmlDelegateModelItem *> &items, int index, int count, const QVector<int> &) const override
135 {
136 for (auto modelItem : items) {
137 const int modelItemIndex = modelItem->modelIndex();
138 if (modelItemIndex < index || modelItemIndex >= index + count)
139 continue;
140
141 auto objectModelItem = static_cast<QQmlDMObjectData *>(modelItem);
142 QObject *updatedModelData = qvariant_cast<QObject *>(
143 model.list.at(objectModelItem->modelIndex()));
144 objectModelItem->setModelData(updatedModelData);
145 }
146 return true;
147 }
148};
149
151{
152public:
153 QQmlDMObjectDataMetaObject(QQmlDMObjectData *data, VDMObjectDelegateDataType *type)
154 : m_data(data)
155 , m_type(type)
156 {
157 QObjectPrivate *op = QObjectPrivate::get(m_data);
158 *static_cast<QMetaObject *>(this) = *type->metaObject;
159 op->metaObject = this;
160 m_type->addref();
161 }
162
164 {
165 m_type->release();
166 }
167
168 int metaCall(QObject *o, QMetaObject::Call call, int id, void **arguments) override
169 {
170 Q_ASSERT(o == m_data);
171 Q_UNUSED(o);
172
173 static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
174 if (id >= m_type->propertyOffset
175 && (call == QMetaObject::ReadProperty
176 || call == QMetaObject::WriteProperty
177 || call == QMetaObject::ResetProperty)) {
178 if (m_data->object)
179 QMetaObject::metacall(m_data->object, call, id - m_type->propertyOffset + objectPropertyOffset, arguments);
180 return -1;
181 } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
182 QMetaObject::activate(m_data, this, id - m_type->signalOffset, nullptr);
183 return -1;
184 } else {
185 return m_data->qt_metacall(call, id, arguments);
186 }
187 }
188
189 int createProperty(const char *name, const char *) override
190 {
191 if (!m_data->object)
192 return -1;
193 const QMetaObject *metaObject = m_data->object->metaObject();
194 static const int objectPropertyOffset = QObject::staticMetaObject.propertyCount();
195
196 const int previousPropertyCount = propertyCount() - propertyOffset();
197 int propertyIndex = metaObject->indexOfProperty(name);
198 if (propertyIndex == -1)
199 return -1;
200 if (previousPropertyCount + objectPropertyOffset == metaObject->propertyCount())
201 return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
202
203 if (m_type->shared) {
204 VDMObjectDelegateDataType *type = m_type;
205 m_type = new VDMObjectDelegateDataType(*m_type);
206 type->release();
207 }
208
209 const int previousMethodCount = methodCount();
210 int notifierId = previousMethodCount - methodOffset();
211 for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - objectPropertyOffset; ++propertyId) {
212 QMetaProperty property = metaObject->property(propertyId + objectPropertyOffset);
213 QMetaPropertyBuilder propertyBuilder;
214 if (property.hasNotifySignal()) {
215 m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
216 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
217 ++notifierId;
218 } else {
219 propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
220 }
221 const bool modelWritable = m_type->model->delegateModelAccess != QQmlDelegateModel::ReadOnly;
222 propertyBuilder.setWritable(modelWritable && property.isWritable());
223 propertyBuilder.setResettable(modelWritable && property.isResettable());
224 propertyBuilder.setConstant(property.isConstant());
225 }
226
227 m_type->metaObject.reset(m_type->builder.toMetaObject());
228 *static_cast<QMetaObject *>(this) = *m_type->metaObject;
229
230 notifierId = previousMethodCount;
231 for (int i = previousPropertyCount; i < metaObject->propertyCount() - objectPropertyOffset; ++i) {
232 QMetaProperty property = metaObject->property(i + objectPropertyOffset);
233 if (property.hasNotifySignal()) {
234 QQmlPropertyPrivate::connect(
235 m_data->object, property.notifySignalIndex(), m_data, notifierId);
236 ++notifierId;
237 }
238 }
239 return propertyIndex + m_type->propertyOffset - objectPropertyOffset;
240 }
241
243 VDMObjectDelegateDataType *m_type;
244};
245
246QT_END_NAMESPACE
247
248#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)
QPointer< QObject > object
QQmlRefPointer< QQmlContextData > initProxy() final
bool notify(const QQmlAdaptorModel &model, const QList< QQmlDelegateModelItem * > &items, int index, int count, const QVector< int > &) const override
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
QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
void cleanup(QQmlAdaptorModel &) const override