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
qqmldmabstractitemmodeldata_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 QQMLDMABSTRACTITEMMODELDATA_P_H
6#define QQMLDMABSTRACTITEMMODELDATA_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#include <private/qobject_p.h>
22
23QT_BEGIN_NAMESPACE
24
25class VDMAbstractItemModelDataType;
27{
28 Q_OBJECT
29 Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
32
33public:
37 int index, int row, int column);
38
39 int metaCall(QMetaObject::Call call, int id, void **arguments);
40 bool hasModelChildren() const;
41
42 QV4::ReturnedValue get() override;
43 void setValue(const QString &role, const QVariant &value) override;
44 bool resolveIndex(const QQmlAdaptorModel &model, int idx) override;
45
47 const QV4::FunctionObject *b, const QV4::Value *thisObject,
48 const QV4::Value *argv, int argc);
50 const QV4::FunctionObject *b, const QV4::Value *thisObject,
51 const QV4::Value *argv, int argc);
52
54 const QV4::FunctionObject *b, const QV4::Value *thisObject,
55 const QV4::Value *argv, int argc);
57 const QV4::FunctionObject *b, const QV4::Value *thisObject,
58 const QV4::Value *argv, int argc);
59
60 QVariant modelData() const;
61 void setModelData(const QVariant &modelData);
62
63 const VDMAbstractItemModelDataType *type() const { return m_type; }
64
67
68private:
69 QVariant value(int role) const;
70 void setValue(int role, const QVariant &value);
71
72 VDMAbstractItemModelDataType *m_type;
73 QVector<QVariant> m_cachedData;
74};
75
76class VDMAbstractItemModelDataType final
77 : public QQmlRefCounted<VDMAbstractItemModelDataType>
78 , public QQmlAdaptorModel::Accessors
79 , public QAbstractDynamicMetaObject
80{
81public:
82 VDMAbstractItemModelDataType(QQmlAdaptorModel *model)
83 : model(model)
85 , signalOffset(0)
86 {
87 }
88
90 const QVarLengthArray<QQmlGuard<QQmlDMAbstractItemModelData>> &guardedItems,
91 int index, QQmlDelegateModel::DelegateModelAccess access) const
92 {
93 for (const auto &item : guardedItems) {
94 if (item.isNull())
95 continue;
96
97 if (access == QQmlDelegateModel::DelegateModelAccess::ReadWrite) {
98 QQmlDelegateModelReadOnlyMetaObject readOnly(item, index + propertyOffset);
99 QMetaObject::activate(item, index + signalOffset, nullptr);
100 } else {
101 QMetaObject::activate(item, index + signalOffset, nullptr);
102 }
103 }
104 }
105
106 bool notify(
107 const QQmlAdaptorModel &model,
108 const QList<QQmlDelegateModelItem *> &items,
109 int index,
110 int count,
111 const QVector<int> &roles) const override
112 {
113 bool changed = roles.isEmpty() && !watchedRoles.isEmpty();
114 if (!changed && !watchedRoles.isEmpty() && watchedRoleIds.isEmpty()) {
115 QList<int> roleIds;
116 for (const QByteArray &r : watchedRoles) {
117 QHash<QByteArray, int>::const_iterator it = roleNames.find(r);
118 if (it != roleNames.end())
119 roleIds << it.value();
120 }
121 const_cast<VDMAbstractItemModelDataType *>(this)->watchedRoleIds = roleIds;
122 }
123
124 QVarLengthArray<QQmlGuard<QQmlDMAbstractItemModelData>> guardedItems;
125 for (const auto item : items) {
126 Q_ASSERT(qobject_cast<QQmlDMAbstractItemModelData *>(item) == item);
127 const int idx = item->modelIndex();
128 if (idx >= index && idx < index + count)
129 guardedItems.append(static_cast<QQmlDMAbstractItemModelData *>(item));
130 }
131
132 for (int i = 0; i < roles.size(); ++i) {
133 const int role = roles.at(i);
134 if (!changed && watchedRoleIds.contains(role))
135 changed = true;
136
137 int propertyId = propertyRoles.indexOf(role);
138 if (propertyId != -1)
139 notifyItems(guardedItems, propertyId, model.delegateModelAccess);
140 }
141
142 if (roles.isEmpty()) {
143 const int propertyRolesCount = propertyRoles.size();
144 for (int propertyId = 0; propertyId < propertyRolesCount; ++propertyId)
145 notifyItems(guardedItems, propertyId, model.delegateModelAccess);
146 }
147
148 for (const auto &item : std::as_const(guardedItems)) {
149 if (!item.isNull())
150 emit item->modelDataChanged();
151 }
152
153 return changed;
154 }
155
157 QQmlAdaptorModel &,
158 const QList<QByteArray> &oldRoles,
159 const QList<QByteArray> &newRoles) const override
160 {
161 VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
162
163 dataType->watchedRoleIds.clear();
164 for (const QByteArray &oldRole : oldRoles)
165 dataType->watchedRoles.removeOne(oldRole);
166 dataType->watchedRoles += newRoles;
167 }
168
169 static QV4::ReturnedValue get_hasModelChildren(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
170 {
171 QV4::Scope scope(b);
172 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
173 if (!o)
174 RETURN_RESULT(scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object")));
175
176 const QQmlAdaptorModel *const model
177 = static_cast<QQmlDMAbstractItemModelData *>(o->d()->item)->type()->model;
178 if (o->d()->item->modelIndex() >= 0) {
179 if (const QAbstractItemModel *const aim = model->aim())
180 RETURN_RESULT(QV4::Encode(aim->hasChildren(
181 aim->index(o->d()->item->modelIndex(), 0, model->rootIndex))));
182 }
183 RETURN_RESULT(QV4::Encode(false));
184 }
185
186
187 void initializeConstructor(QQmlAdaptorModelEngineData *const data)
188 {
189 QV4::ExecutionEngine *v4 = data->v4;
190 QV4::Scope scope(v4);
191 QV4::ScopedObject proto(scope, v4->newObject());
192 proto->defineAccessorProperty(QStringLiteral("index"), QQmlAdaptorModelEngineData::get_index, nullptr);
193 proto->defineAccessorProperty(QStringLiteral("hasModelChildren"), get_hasModelChildren, nullptr);
194 proto->defineAccessorProperty(QStringLiteral("modelData"),
195 QQmlDMAbstractItemModelData::get_modelData,
196 QQmlDMAbstractItemModelData::set_modelData);
197 QV4::ScopedProperty p(scope);
198
199 typedef QHash<QByteArray, int>::const_iterator iterator;
200 for (iterator it = roleNames.constBegin(), end = roleNames.constEnd(); it != end; ++it) {
201 const qsizetype propertyId = propertyRoles.indexOf(it.value());
202 const QByteArray &propertyName = it.key();
203
204 QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
205 QV4::ScopedFunctionObject g(
206 scope,
207 v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(
208 v4, propertyId, QQmlDMAbstractItemModelData::get_property));
209 QV4::ScopedFunctionObject s(
210 scope,
211 v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(
212 v4, propertyId, QQmlDMAbstractItemModelData::set_property));
213 p->setGetter(g);
214 p->setSetter(s);
215 proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
216 }
217 prototype.set(v4, proto);
218 }
219
220 // QAbstractDynamicMetaObject
221
222 void objectDestroyed(QObject *) override
223 {
224 release();
225 }
226
227 int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) override
228 {
229 return static_cast<QQmlDMAbstractItemModelData *>(object)->metaCall(call, id, arguments);
230 }
231
232 int rowCount(const QQmlAdaptorModel &model) const override
233 {
234 if (const QAbstractItemModel *aim = model.aim())
235 return aim->rowCount(model.rootIndex);
236 return 0;
237 }
238
239 int columnCount(const QQmlAdaptorModel &model) const override
240 {
241 if (const QAbstractItemModel *aim = model.aim())
242 return aim->columnCount(model.rootIndex);
243 return 0;
244 }
245
246 void cleanup(QQmlAdaptorModel &) const override
247 {
248 release();
249 }
250
251 QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
252 {
253 if (!metaObject) {
254 VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
255 dataType->initializeMetaObject(model);
256 }
257
258 if (const QAbstractItemModel *aim = model.aim()) {
259 const QModelIndex modelIndex
260 = aim->index(model.rowAt(index), model.columnAt(index), model.rootIndex);
261
262 const auto it = roleNames.find(role.toUtf8()), end = roleNames.end();
263 if (it != roleNames.end())
264 return modelIndex.data(*it);
265
266 if (role.isEmpty() || role == QLatin1String("modelData")) {
267 if (roleNames.size() == 1)
268 return modelIndex.data(roleNames.begin().value());
269
270 QVariantMap modelData;
271 for (auto jt = roleNames.begin(); jt != end; ++jt)
272 modelData.insert(QString::fromUtf8(jt.key()), modelIndex.data(jt.value()));
273 return modelData;
274 }
275
276 if (role == QLatin1String("hasModelChildren"))
277 return QVariant(aim->hasChildren(modelIndex));
278 }
279 return QVariant();
280 }
281
282 QVariant parentModelIndex(const QQmlAdaptorModel &model) const override
283 {
284 if (const QAbstractItemModel *aim = model.aim())
285 return QVariant::fromValue(aim->parent(model.rootIndex));
286 return QVariant();
287 }
288
289 QVariant modelIndex(const QQmlAdaptorModel &model, int index) const override
290 {
291 if (const QAbstractItemModel *aim = model.aim())
292 return QVariant::fromValue(aim->index(model.rowAt(index), model.columnAt(index),
293 model.rootIndex));
294 return QVariant();
295 }
296
297 bool canFetchMore(const QQmlAdaptorModel &model) const override
298 {
299 if (const QAbstractItemModel *aim = model.aim())
300 return aim->canFetchMore(model.rootIndex);
301 return false;
302 }
303
304 void fetchMore(QQmlAdaptorModel &model) const override
305 {
306 if (QAbstractItemModel *aim = model.aim())
307 aim->fetchMore(model.rootIndex);
308 }
309
311 QQmlAdaptorModel &model,
312 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
313 int index, int row, int column) override
314 {
315 if (!metaObject)
316 initializeMetaObject(model);
317 return new QQmlDMAbstractItemModelData(metaType, this, index, row, column);
318 }
319
320 void initializeMetaObject(const QQmlAdaptorModel &model)
321 {
322 QMetaObjectBuilder builder;
323 QQmlAdaptorModelEngineData::setModelDataType<QQmlDMAbstractItemModelData>(&builder, this);
324
325 const QByteArray propertyType = QByteArrayLiteral("QVariant");
326 const QAbstractItemModel *aim = model.aim();
327 const QHash<int, QByteArray> names = aim ? aim->roleNames() : QHash<int, QByteArray>();
328 for (QHash<int, QByteArray>::const_iterator it = names.begin(), cend = names.end(); it != cend; ++it) {
329 const int propertyId = propertyRoles.size();
330 propertyRoles.append(it.key());
331 roleNames.insert(it.value(), it.key());
332 QQmlAdaptorModelEngineData::addProperty(
333 &builder, propertyId, it.value(), propertyType,
334 model.delegateModelAccess != QQmlDelegateModel::ReadOnly);
335 }
336
337 metaObject.reset(builder.toMetaObject());
338 *static_cast<QMetaObject *>(this) = *metaObject;
339 propertyCache = QQmlPropertyCache::createStandalone(
340 metaObject.data(), model.modelItemRevision);
341 }
342
351};
352
353QT_END_NAMESPACE
354
355#endif // QQMLDMABSTRACTITEMMODELDATA_P_H
int metaCall(QMetaObject::Call call, int id, void **arguments)
static QV4::ReturnedValue get_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
void setValue(const QString &role, const QVariant &value) override
static QV4::ReturnedValue get_property(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
static QV4::ReturnedValue set_property(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
void setModelData(const QVariant &modelData)
bool resolveIndex(const QQmlAdaptorModel &model, int idx) override
static QV4::ReturnedValue set_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
const VDMAbstractItemModelDataType * type() const
QVariant parentModelIndex(const QQmlAdaptorModel &model) const override
void cleanup(QQmlAdaptorModel &) const override
int columnCount(const QQmlAdaptorModel &model) const override
bool notify(const QQmlAdaptorModel &model, const QList< QQmlDelegateModelItem * > &items, int index, int count, const QVector< int > &roles) const override
QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
static QV4::ReturnedValue get_hasModelChildren(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
int rowCount(const QQmlAdaptorModel &model) const override
bool canFetchMore(const QQmlAdaptorModel &model) const override
int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) override
void initializeConstructor(QQmlAdaptorModelEngineData *const data)
VDMAbstractItemModelDataType(QQmlAdaptorModel *model)
void initializeMetaObject(const QQmlAdaptorModel &model)
void fetchMore(QQmlAdaptorModel &model) const override
QVariant modelIndex(const QQmlAdaptorModel &model, int index) const override
void replaceWatchedRoles(QQmlAdaptorModel &, const QList< QByteArray > &oldRoles, const QList< QByteArray > &newRoles) const override
void notifyItems(const QVarLengthArray< QQmlGuard< QQmlDMAbstractItemModelData > > &guardedItems, int index, QQmlDelegateModel::DelegateModelAccess access) const
QQmlDelegateModelItem * createItem(QQmlAdaptorModel &model, const QQmlRefPointer< QQmlDelegateModelItemMetaType > &metaType, int index, int row, int column) override