1// Copyright (C) 2016 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
4#ifndef QQMLDATAMODEL_P_P_H
5#define QQMLDATAMODEL_P_P_H
6
7#include "qqmldelegatemodel_p.h"
8#include <private/qv4qobjectwrapper_p.h>
9
10#include <QtQml/qqmlcontext.h>
11#include <QtQml/qqmlincubator.h>
12
13#include <private/qqmladaptormodel_p.h>
14#include <private/qqmlopenmetaobject_p.h>
15
16#include <QtCore/qloggingcategory.h>
17#include <QtCore/qpointer.h>
18
19//
20// W A R N I N G
21// -------------
22//
23// This file is not part of the Qt API. It exists purely as an
24// implementation detail. This header file may change from version to
25// version without notice, or even be removed.
26//
27// We mean it.
28//
29
30QT_REQUIRE_CONFIG(qml_delegate_model);
31
32QT_BEGIN_NAMESPACE
33
34Q_DECLARE_LOGGING_CATEGORY(lcItemViewDelegateRecycling)
35
36typedef QQmlListCompositor Compositor;
37
38class QQmlDelegateModelAttachedMetaObject;
39class QQmlAbstractDelegateComponent;
40
41class Q_QMLMODELS_EXPORT QQmlDelegateModelItemMetaType final
42 : public QQmlRefCounted<QQmlDelegateModelItemMetaType>
43{
44public:
45 QQmlDelegateModelItemMetaType(QV4::ExecutionEngine *engine, QQmlDelegateModel *model, const QStringList &groupNames);
46 ~QQmlDelegateModelItemMetaType();
47
48 void initializeMetaObject();
49 void initializePrototype();
50
51 int parseGroups(const QStringList &groupNames) const;
52 int parseGroups(const QV4::Value &groupNames) const;
53
54 QPointer<QQmlDelegateModel> model;
55 const int groupCount;
56 QV4::ExecutionEngine * const v4Engine;
57 QQmlDelegateModelAttachedMetaObject *metaObject;
58 const QStringList groupNames;
59 QV4::PersistentValue modelItemProto;
60};
61
62class QQmlAdaptorModel;
63class QQDMIncubationTask;
64
65class QQmlDelegateModelItem : public QObject
66{
67 Q_OBJECT
68 Q_PROPERTY(int index READ modelIndex NOTIFY modelIndexChanged)
69 Q_PROPERTY(int row READ modelRow NOTIFY rowChanged REVISION(2, 12))
70 Q_PROPERTY(int column READ modelColumn NOTIFY columnChanged REVISION(2, 12))
71 Q_PROPERTY(QObject *model READ modelObject CONSTANT)
72public:
73 QQmlDelegateModelItem(const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
74 QQmlAdaptorModel::Accessors *accessor, int modelIndex,
75 int row, int column);
76 ~QQmlDelegateModelItem();
77
78 void referenceObject() { ++objectRef; }
79 bool releaseObject()
80 {
81 Q_ASSERT(objectRef > 0);
82 return --objectRef == 0 && !(groups & Compositor::PersistedFlag);
83 }
84 bool isObjectReferenced() const { return objectRef != 0 || (groups & Compositor::PersistedFlag); }
85 void childContextObjectDestroyed(QObject *childContextObject);
86
87 bool isReferenced() const {
88 return scriptRef
89 || incubationTask
90 || ((groups & Compositor::UnresolvedFlag) && (groups & Compositor::GroupMask));
91 }
92
93 void Dispose();
94
95 QObject *modelObject() { return this; }
96
97 void destroyObject();
98
99 static QQmlDelegateModelItem *dataForObject(QObject *object);
100
101 int groupIndex(Compositor::Group group);
102
103 int modelRow() const { return row; }
104 int modelColumn() const { return column; }
105 int modelIndex() const { return index; }
106 virtual void setModelIndex(int idx, int newRow, int newColumn, bool alwaysEmit = false);
107
108 virtual QV4::ReturnedValue get() { return QV4::QObjectWrapper::wrap(engine: v4, object: this); }
109
110 virtual void setValue(const QString &role, const QVariant &value) { Q_UNUSED(role); Q_UNUSED(value); }
111 virtual bool resolveIndex(const QQmlAdaptorModel &, int) { return false; }
112
113 static QV4::ReturnedValue get_model(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
114 static QV4::ReturnedValue get_groups(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
115 static QV4::ReturnedValue set_groups(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
116 static QV4::ReturnedValue get_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &);
117 static QV4::ReturnedValue set_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg);
118 static QV4::ReturnedValue get_index(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg);
119
120 QV4::ExecutionEngine *v4;
121 QQmlRefPointer<QQmlDelegateModelItemMetaType> const metaType;
122 QQmlRefPointer<QQmlContextData> contextData;
123 QPointer<QObject> object;
124 QPointer<QQmlDelegateModelAttached> attached;
125 QQDMIncubationTask *incubationTask;
126 QQmlComponent *delegate;
127 int poolTime;
128 int objectRef;
129 int scriptRef;
130 int groups;
131 int index;
132
133Q_SIGNALS:
134 void modelIndexChanged();
135 Q_REVISION(2, 12) void rowChanged();
136 Q_REVISION(2, 12) void columnChanged();
137
138protected:
139 void objectDestroyed(QObject *);
140 int row;
141 int column;
142};
143
144namespace QV4 {
145namespace Heap {
146struct QQmlDelegateModelItemObject : Object {
147 inline void init(QQmlDelegateModelItem *item);
148 void destroy();
149 QQmlDelegateModelItem *item;
150};
151
152}
153}
154
155struct QQmlDelegateModelItemObject : QV4::Object
156{
157 V4_OBJECT2(QQmlDelegateModelItemObject, QV4::Object)
158 V4_NEEDS_DESTROY
159};
160
161void QV4::Heap::QQmlDelegateModelItemObject::init(QQmlDelegateModelItem *item)
162{
163 Object::init();
164 this->item = item;
165}
166
167class QQmlReusableDelegateModelItemsPool
168{
169public:
170 void insertItem(QQmlDelegateModelItem *modelItem);
171 QQmlDelegateModelItem *takeItem(const QQmlComponent *delegate, int newIndexHint);
172 void reuseItem(QQmlDelegateModelItem *item, int newModelIndex);
173 void drain(int maxPoolTime, std::function<void(QQmlDelegateModelItem *cacheItem)> releaseItem);
174 int size() { return m_reusableItemsPool.size(); }
175
176private:
177 QList<QQmlDelegateModelItem *> m_reusableItemsPool;
178};
179
180class QQmlDelegateModelPrivate;
181class QQDMIncubationTask : public QQmlIncubator
182{
183public:
184 QQDMIncubationTask(QQmlDelegateModelPrivate *l, IncubationMode mode)
185 : QQmlIncubator(mode)
186 , incubating(nullptr)
187 , vdm(l) {}
188
189 void initializeRequiredProperties(QQmlDelegateModelItem *modelItemToIncubate, QObject* object);
190 void statusChanged(Status) override;
191 void setInitialState(QObject *) override;
192
193 QQmlDelegateModelItem *incubating = nullptr;
194 QQmlDelegateModelPrivate *vdm = nullptr;
195 QQmlRefPointer<QQmlContextData> proxyContext;
196 QPointer<QObject> proxiedObject = nullptr; // the proxied object might disapear, so we use a QPointer instead of a raw one
197 int index[QQmlListCompositor::MaximumGroupCount];
198};
199
200
201class QQmlDelegateModelGroupEmitter
202{
203public:
204 virtual ~QQmlDelegateModelGroupEmitter() {}
205 virtual void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) = 0;
206 virtual void createdPackage(int, QQuickPackage *) {}
207 virtual void initPackage(int, QQuickPackage *) {}
208 virtual void destroyingPackage(QQuickPackage *) {}
209
210 QIntrusiveListNode emitterNode;
211};
212
213typedef QIntrusiveList<QQmlDelegateModelGroupEmitter, &QQmlDelegateModelGroupEmitter::emitterNode> QQmlDelegateModelGroupEmitterList;
214
215class QQmlDelegateModelGroupPrivate : public QObjectPrivate
216{
217public:
218 Q_DECLARE_PUBLIC(QQmlDelegateModelGroup)
219
220 QQmlDelegateModelGroupPrivate() : group(Compositor::Cache), defaultInclude(false) {}
221
222 static QQmlDelegateModelGroupPrivate *get(QQmlDelegateModelGroup *group) {
223 return static_cast<QQmlDelegateModelGroupPrivate *>(QObjectPrivate::get(o: group)); }
224
225 void setModel(QQmlDelegateModel *model, Compositor::Group group);
226 bool isChangedConnected();
227 void emitChanges(QV4::ExecutionEngine *engine);
228 void emitModelUpdated(bool reset);
229
230 void createdPackage(int index, QQuickPackage *package);
231 void initPackage(int index, QQuickPackage *package);
232 void destroyingPackage(QQuickPackage *package);
233
234 bool parseIndex(const QV4::Value &value, int *index, Compositor::Group *group) const;
235 bool parseGroupArgs(
236 QQmlV4FunctionPtr args, Compositor::Group *group, int *index, int *count, int *groups) const;
237
238 Compositor::Group group;
239 QPointer<QQmlDelegateModel> model;
240 QQmlDelegateModelGroupEmitterList emitters;
241 QQmlChangeSet changeSet;
242 QString name;
243 bool defaultInclude;
244};
245
246class QQmlDelegateModelParts;
247
248class QQmlDelegateModelPrivate : public QObjectPrivate, public QQmlDelegateModelGroupEmitter
249{
250 Q_DECLARE_PUBLIC(QQmlDelegateModel)
251public:
252 QQmlDelegateModelPrivate(QQmlContext *);
253 ~QQmlDelegateModelPrivate();
254
255 static QQmlDelegateModelPrivate *get(QQmlDelegateModel *m) {
256 return static_cast<QQmlDelegateModelPrivate *>(QObjectPrivate::get(o: m));
257 }
258
259 void init();
260 void connectModel(QQmlAdaptorModel *model);
261 void connectToAbstractItemModel();
262 void disconnectFromAbstractItemModel();
263
264 void requestMoreIfNecessary();
265 QObject *object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode);
266 QQmlDelegateModel::ReleaseFlags release(QObject *object, QQmlInstanceModel::ReusableFlag reusable = QQmlInstanceModel::NotReusable);
267 QVariant variantValue(Compositor::Group group, int index, const QString &name);
268 void emitCreatedPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package);
269 void emitInitPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package);
270 void emitCreatedItem(QQDMIncubationTask *incubationTask, QObject *item) {
271 Q_EMIT q_func()->createdItem(index: incubationTask->index[m_compositorGroup], object: item); }
272 void emitInitItem(QQDMIncubationTask *incubationTask, QObject *item) {
273 Q_EMIT q_func()->initItem(index: incubationTask->index[m_compositorGroup], object: item); }
274 void emitDestroyingPackage(QQuickPackage *package);
275 void emitDestroyingItem(QObject *item) { Q_EMIT q_func()->destroyingItem(object: item); }
276 void addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it);
277 void removeCacheItem(QQmlDelegateModelItem *cacheItem);
278 void destroyCacheItem(QQmlDelegateModelItem *cacheItem);
279 void updateFilterGroup();
280
281 void reuseItem(QQmlDelegateModelItem *item, int newModelIndex, int newGroups);
282 void drainReusableItemsPool(int maxPoolTime);
283 QQmlComponent *resolveDelegate(int index);
284
285 void addGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
286 void removeGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
287 void setGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
288
289 void itemsInserted(
290 const QVector<Compositor::Insert> &inserts,
291 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
292 QHash<int, QList<QQmlDelegateModelItem *> > *movedItems = nullptr);
293 void itemsInserted(const QVector<Compositor::Insert> &inserts);
294 void itemsRemoved(
295 const QVector<Compositor::Remove> &removes,
296 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
297 QHash<int, QList<QQmlDelegateModelItem *> > *movedItems = nullptr);
298 void itemsRemoved(const QVector<Compositor::Remove> &removes);
299 void itemsMoved(
300 const QVector<Compositor::Remove> &removes, const QVector<Compositor::Insert> &inserts);
301 void itemsChanged(const QVector<Compositor::Change> &changes);
302 void emitChanges();
303 void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override;
304 void delegateChanged(bool add = true, bool remove = true);
305
306 enum class InsertionResult {
307 Success,
308 Error,
309 Retry
310 };
311 InsertionResult insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups);
312
313 int adaptorModelCount() const;
314
315 static void group_append(QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group);
316 static qsizetype group_count(QQmlListProperty<QQmlDelegateModelGroup> *property);
317 static QQmlDelegateModelGroup *group_at(QQmlListProperty<QQmlDelegateModelGroup> *property, qsizetype index);
318
319 void releaseIncubator(QQDMIncubationTask *incubationTask);
320 void incubatorStatusChanged(QQDMIncubationTask *incubationTask, QQmlIncubator::Status status);
321 void setInitialState(QQDMIncubationTask *incubationTask, QObject *o);
322
323 QQmlAdaptorModel m_adaptorModel;
324 QQmlListCompositor m_compositor;
325 QQmlStrongJSQObjectReference<QQmlComponent> m_delegate;
326 QQmlAbstractDelegateComponent *m_delegateChooser;
327 QMetaObject::Connection m_delegateChooserChanged;
328 QQmlDelegateModelItemMetaType *m_cacheMetaType;
329 QPointer<QQmlContext> m_context;
330 QQmlDelegateModelParts *m_parts;
331 QQmlDelegateModelGroupEmitterList m_pendingParts;
332
333 QList<QQmlDelegateModelItem *> m_cache;
334 QQmlReusableDelegateModelItemsPool m_reusableItemsPool;
335 QList<QQDMIncubationTask *> m_finishedIncubating;
336 QList<QByteArray> m_watchedRoles;
337
338 QString m_filterGroup;
339
340 int m_count;
341 int m_groupCount;
342
343 QQmlListCompositor::Group m_compositorGroup;
344 bool m_complete : 1;
345 bool m_delegateValidated : 1;
346 bool m_reset : 1;
347 bool m_transaction : 1;
348 bool m_incubatorCleanupScheduled : 1;
349 bool m_waitingToFetchMore : 1;
350
351 union {
352 struct {
353 QQmlDelegateModelGroup *m_cacheItems;
354 QQmlDelegateModelGroup *m_items;
355 QQmlDelegateModelGroup *m_persistedItems;
356 };
357 QQmlDelegateModelGroup *m_groups[Compositor::MaximumGroupCount];
358 };
359};
360
361class QQmlPartsModel : public QQmlInstanceModel, public QQmlDelegateModelGroupEmitter
362{
363 Q_OBJECT
364 Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup FINAL)
365public:
366 QQmlPartsModel(QQmlDelegateModel *model, const QString &part, QObject *parent = nullptr);
367 ~QQmlPartsModel();
368
369 QString filterGroup() const;
370 void setFilterGroup(const QString &group);
371 void resetFilterGroup();
372 void updateFilterGroup();
373 void updateFilterGroup(Compositor::Group group, const QQmlChangeSet &changeSet);
374
375 int count() const override;
376 bool isValid() const override;
377 QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
378 ReleaseFlags release(QObject *item, ReusableFlag reusable = NotReusable) override;
379 QVariant variantValue(int index, const QString &role) override;
380 QList<QByteArray> watchedRoles() const { return m_watchedRoles; }
381 void setWatchedRoles(const QList<QByteArray> &roles) override;
382 QQmlIncubator::Status incubationStatus(int index) override;
383
384 int indexOf(QObject *item, QObject *objectContext) const override;
385
386 void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override;
387
388 void createdPackage(int index, QQuickPackage *package) override;
389 void initPackage(int index, QQuickPackage *package) override;
390 void destroyingPackage(QQuickPackage *package) override;
391
392Q_SIGNALS:
393 void filterGroupChanged();
394
395private:
396 QQmlDelegateModel *m_model;
397 QMultiHash<QObject *, QQuickPackage *> m_packaged;
398 QString m_part;
399 QString m_filterGroup;
400 QList<QByteArray> m_watchedRoles;
401 QVector<int> m_pendingPackageInitializations; // vector holds model indices
402 Compositor::Group m_compositorGroup;
403 bool m_inheritGroup;
404 bool m_modelUpdatePending = true;
405};
406
407class QMetaPropertyBuilder;
408
409class QQmlDelegateModelPartsMetaObject : public QQmlOpenMetaObject
410{
411public:
412 QQmlDelegateModelPartsMetaObject(QObject *parent)
413 : QQmlOpenMetaObject(parent) {}
414
415 void propertyCreated(int, QMetaPropertyBuilder &) override;
416 QVariant initialValue(int) override;
417};
418
419class QQmlDelegateModelParts : public QObject
420{
421Q_OBJECT
422public:
423 QQmlDelegateModelParts(QQmlDelegateModel *parent);
424
425 QQmlDelegateModel *model;
426 QList<QQmlPartsModel *> models;
427};
428
429class QQmlDelegateModelAttachedMetaObject final
430 : public QAbstractDynamicMetaObject,
431 public QQmlRefCounted<QQmlDelegateModelAttachedMetaObject>
432{
433public:
434 QQmlDelegateModelAttachedMetaObject(
435 QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject);
436 ~QQmlDelegateModelAttachedMetaObject();
437
438 void objectDestroyed(QObject *) override;
439 int metaCall(QObject *, QMetaObject::Call, int _id, void **) override;
440
441private:
442 QQmlDelegateModelItemMetaType * const metaType;
443 QMetaObject * const metaObject;
444 const int memberPropertyOffset;
445 const int indexPropertyOffset;
446};
447
448QT_END_NAMESPACE
449
450#endif
451

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/src/qmlmodels/qqmldelegatemodel_p_p.h