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 QList<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 QList<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 QQmlDelegateModelItem *item = o->d()->item();
177 const QQmlAdaptorModel *const model
178 = static_cast<QQmlDMAbstractItemModelData *>(item)->type()->model;
179 if (item->modelIndex() >= 0) {
180 if (const QAbstractItemModel *const aim = model->aim())
181 RETURN_RESULT(QV4::Encode(aim->hasChildren(
182 aim->index(item->modelIndex(), 0, model->rootIndex))));
183 }
184 RETURN_RESULT(QV4::Encode(false));
185 }
186
187
188 void initializeConstructor(QQmlAdaptorModelEngineData *const data)
189 {
190 QV4::ExecutionEngine *v4 = data->v4;
191 QV4::Scope scope(v4);
192 QV4::ScopedObject proto(scope, v4->newObject());
193 proto->defineAccessorProperty(QStringLiteral("index"), QQmlAdaptorModelEngineData::get_index, nullptr);
194 proto->defineAccessorProperty(QStringLiteral("hasModelChildren"), get_hasModelChildren, nullptr);
195 proto->defineAccessorProperty(QStringLiteral("modelData"),
196 QQmlDMAbstractItemModelData::get_modelData,
197 QQmlDMAbstractItemModelData::set_modelData);
198 QV4::ScopedProperty p(scope);
199
200 typedef QHash<QByteArray, int>::const_iterator iterator;
201 for (iterator it = roleNames.constBegin(), end = roleNames.constEnd(); it != end; ++it) {
202 const qsizetype propertyId = propertyRoles.indexOf(it.value());
203 const QByteArray &propertyName = it.key();
204
205 QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
206 QV4::ScopedFunctionObject g(
207 scope,
208 v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(
209 v4, propertyId, QQmlDMAbstractItemModelData::get_property));
210 QV4::ScopedFunctionObject s(
211 scope,
212 v4->memoryManager->allocate<QV4::IndexedBuiltinFunction>(
213 v4, propertyId, QQmlDMAbstractItemModelData::set_property));
214 p->setGetter(g);
215 p->setSetter(s);
216 proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
217 }
218 prototype.set(v4, proto);
219 }
220
221 // QAbstractDynamicMetaObject
222
223 void objectDestroyed(QObject *) override
224 {
225 release();
226 }
227
228 int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) override
229 {
230 return static_cast<QQmlDMAbstractItemModelData *>(object)->metaCall(call, id, arguments);
231 }
232
233 int rowCount(const QQmlAdaptorModel &model) const override
234 {
235 if (const QAbstractItemModel *aim = model.aim())
236 return aim->rowCount(model.rootIndex);
237 return 0;
238 }
239
240 int columnCount(const QQmlAdaptorModel &model) const override
241 {
242 if (const QAbstractItemModel *aim = model.aim())
243 return aim->columnCount(model.rootIndex);
244 return 0;
245 }
246
247 void cleanup(QQmlAdaptorModel &) const override
248 {
249 release();
250 }
251
252 QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
253 {
254 if (!metaObject) {
255 VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this);
256 dataType->initializeMetaObject(model);
257 }
258
259 if (const QAbstractItemModel *aim = model.aim()) {
260 const QModelIndex modelIndex
261 = aim->index(model.rowAt(index), model.columnAt(index), model.rootIndex);
262
263 const auto it = roleNames.find(role.toUtf8()), end = roleNames.end();
264 if (it != roleNames.end())
265 return modelIndex.data(*it);
266
267 if (role.isEmpty() || role == QLatin1String("modelData")) {
268 if (roleNames.size() == 1)
269 return modelIndex.data(roleNames.begin().value());
270
271 QVariantMap modelData;
272 for (auto jt = roleNames.begin(); jt != end; ++jt)
273 modelData.insert(QString::fromUtf8(jt.key()), modelIndex.data(jt.value()));
274 return modelData;
275 }
276
277 if (role == QLatin1String("hasModelChildren"))
278 return QVariant(aim->hasChildren(modelIndex));
279 }
280 return QVariant();
281 }
282
283 QVariant parentModelIndex(const QQmlAdaptorModel &model) const override
284 {
285 if (const QAbstractItemModel *aim = model.aim())
286 return QVariant::fromValue(aim->parent(model.rootIndex));
287 return QVariant();
288 }
289
290 QVariant modelIndex(const QQmlAdaptorModel &model, int index) const override
291 {
292 if (const QAbstractItemModel *aim = model.aim())
293 return QVariant::fromValue(aim->index(model.rowAt(index), model.columnAt(index),
294 model.rootIndex));
295 return QVariant();
296 }
297
298 bool canFetchMore(const QQmlAdaptorModel &model) const override
299 {
300 if (const QAbstractItemModel *aim = model.aim())
301 return aim->canFetchMore(model.rootIndex);
302 return false;
303 }
304
305 void fetchMore(QQmlAdaptorModel &model) const override
306 {
307 if (QAbstractItemModel *aim = model.aim())
308 aim->fetchMore(model.rootIndex);
309 }
310
312 QQmlAdaptorModel &model,
313 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
314 int index, int row, int column) override
315 {
316 if (!metaObject)
317 initializeMetaObject(model);
318 return new QQmlDMAbstractItemModelData(metaType, this, index, row, column);
319 }
320
321 void initializeMetaObject(const QQmlAdaptorModel &model)
322 {
323 QMetaObjectBuilder builder;
324 QQmlAdaptorModelEngineData::setModelDataType<QQmlDMAbstractItemModelData>(&builder, this);
325
326 const QByteArray propertyType = QByteArrayLiteral("QVariant");
327 const QAbstractItemModel *aim = model.aim();
328 const QHash<int, QByteArray> names = aim ? aim->roleNames() : QHash<int, QByteArray>();
329 for (QHash<int, QByteArray>::const_iterator it = names.begin(), cend = names.end(); it != cend; ++it) {
330 const int propertyId = propertyRoles.size();
331 propertyRoles.append(it.key());
332 roleNames.insert(it.value(), it.key());
333 QQmlAdaptorModelEngineData::addProperty(
334 &builder, propertyId, it.value(), propertyType,
335 model.delegateModelAccess != QQmlDelegateModel::ReadOnly);
336 }
337
338 metaObject.reset(builder.toMetaObject());
339 *static_cast<QMetaObject *>(this) = *metaObject;
340 propertyCache = QQmlPropertyCache::createStandalone(
341 metaObject.data(), model.modelItemRevision);
342 }
343
352};
353
354QT_END_NAMESPACE
355
356#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
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 notify(const QQmlAdaptorModel &model, const QList< QQmlDelegateModelItem * > &items, int index, int count, const QList< int > &roles) 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