5#ifndef QQMLDATAMODEL_P_P_H
6#define QQMLDATAMODEL_P_P_H
9#include <private/qv4qobjectwrapper_p.h>
11#include <QtQml/qqmlcontext.h>
12#include <QtQml/qqmlincubator.h>
14#include <private/qqmladaptormodel_p.h>
15#include <private/qqmlopenmetaobject_p.h>
17#include <QtCore/qloggingcategory.h>
18#include <QtCore/qpointer.h>
39class QQmlDelegateModelAttachedMetaObject;
40class QQmlAbstractDelegateComponent;
41class QQmlTableInstanceModel;
43class Q_QMLMODELS_EXPORT QQmlDelegateModelItemMetaType final
44 :
public QQmlRefCounted<QQmlDelegateModelItemMetaType>
47 enum class ModelKind : quint8 {
53 QQmlDelegateModelItemMetaType(
54 QV4::ExecutionEngine *engine, QQmlDelegateModel *model,
const QStringList &groupNames);
55 QQmlDelegateModelItemMetaType(
56 QV4::ExecutionEngine *engine, QQmlTableInstanceModel *model);
57 ~QQmlDelegateModelItemMetaType();
59 void initializeAttachedMetaObject();
60 void initializePrototype();
62 int parseGroups(
const QStringList &groupNames)
const;
63 int parseGroups(
const QV4::Value &groupNames)
const;
65 QQmlDelegateModel *delegateModel()
const
67 return modelKind == ModelKind::DelegateModel
68 ?
static_cast<QQmlDelegateModel *>(model.get())
72 qsizetype groupCount()
const {
return groupNames.size(); }
74 void emitModelChanged()
const;
76 QPointer<QQmlInstanceModel> model;
77 QV4::ExecutionEngine *
const v4Engine;
78 QQmlRefPointer<QQmlDelegateModelAttachedMetaObject> attachedMetaObject;
79 const QStringList groupNames;
80 QV4::PersistentValue modelItemProto;
81 ModelKind modelKind = ModelKind::InstanceModel;
84class QQmlAdaptorModel;
90 Q_PROPERTY(
int index READ modelIndex NOTIFY modelIndexChanged)
91 Q_PROPERTY(
int row READ modelRow NOTIFY rowChanged REVISION(2, 12))
92 Q_PROPERTY(
int column READ modelColumn NOTIFY columnChanged REVISION(2, 12))
93 Q_PROPERTY(QObject *model READ modelObject CONSTANT)
95 struct ObjectReference
97 Q_DISABLE_COPY_MOVE(ObjectReference)
99 ObjectReference(QQmlDelegateModelItem *item) : item(item)
101 ++item->m_objectStrongRef;
106 Q_ASSERT(item->m_objectStrongRef > 0);
107 --item->m_objectStrongRef;
110 QQmlDelegateModelItem *item =
nullptr;
113 struct ObjectSpanReference
115 Q_DISABLE_COPY_MOVE(ObjectSpanReference)
117 ObjectSpanReference(QSpan<QQmlDelegateModelItem *
const> span) : items(std::move(span))
119 for (QQmlDelegateModelItem *item : items)
120 ++item->m_objectStrongRef;
123 ~ObjectSpanReference()
125 for (QQmlDelegateModelItem *item : items) {
126 Q_ASSERT(item->m_objectStrongRef > 0);
127 --item->m_objectStrongRef;
132 const QSpan<QQmlDelegateModelItem *
const> items;
135 struct ScriptReference
137 Q_DISABLE_COPY_MOVE(ScriptReference)
139 ScriptReference(QQmlDelegateModelItem *item) : item(item) { item->referenceSript(); }
140 ~ScriptReference() { item->releaseScript(); }
142 QQmlDelegateModelItem *data()
const {
return item; }
144 QQmlDelegateModelItem *item =
nullptr;
147 QQmlDelegateModelItem(
const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
148 QQmlAdaptorModel::Accessors *accessor,
int modelIndex,
149 int row,
int column);
150 ~QQmlDelegateModelItem();
152 [[nodiscard]] QObject *referenceObjectWeak()
159 bool releaseObjectWeak()
161 if (m_objectWeakRef > 0)
163 return !isObjectReferenced();
165 void clearObjectWeakReferences()
170 bool isObjectReferenced()
const
172 return m_objectWeakRef != 0
173 || m_objectStrongRef != 0
174 || (m_groups & Compositor::PersistedFlag);
176 void childContextObjectDestroyed(QObject *childContextObject);
178 bool isScriptReferenced()
const {
181 || ((m_groups & Compositor::UnresolvedFlag) && (m_groups & Compositor::GroupMask));
186 QObject *modelObject() {
return this; }
188 void destroyObject();
189 void destroyObjectLater();
191 static QQmlDelegateModelItem *dataForObject(QObject *object);
193 int groupIndex(Compositor::Group group);
195 int modelRow()
const {
return m_row; }
196 int modelColumn()
const {
return m_column; }
197 int modelIndex()
const {
return m_index; }
198 bool hasValidModelIndex()
const {
return m_index >= 0; }
199 virtual void setModelIndex(
int idx,
int newRow,
int newColumn,
bool alwaysEmit =
false);
200 void setPersistentModelIndex(
const QPersistentModelIndex &index) { m_persistentIndex = index; }
201 QPersistentModelIndex persistentModelIndex()
const {
return m_persistentIndex; }
203 bool usesStructuredModelData()
const {
return m_useStructuredModelData; }
205 virtual QV4::ReturnedValue get() {
return QV4::QObjectWrapper::wrap(m_metaType->v4Engine,
this); }
207 virtual void setValue(
const QString &role,
const QVariant &value) { Q_UNUSED(role); Q_UNUSED(value); }
208 virtual bool resolveIndex(
const QQmlAdaptorModel &,
int) {
return false; }
209 virtual QQmlRefPointer<QQmlContextData> initProxy() {
return m_contextData; }
211 static QV4::ReturnedValue get_model(
const QV4::FunctionObject *,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc);
212 static QV4::ReturnedValue get_groups(
const QV4::FunctionObject *,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc);
213 static QV4::ReturnedValue set_groups(
const QV4::FunctionObject *,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc);
214 static QV4::ReturnedValue get_member(QQmlDelegateModelItem *thisItem, uint flag,
const QV4::Value &);
215 static QV4::ReturnedValue set_member(QQmlDelegateModelItem *thisItem, uint flag,
const QV4::Value &arg);
216 static QV4::ReturnedValue get_index(QQmlDelegateModelItem *thisItem, uint flag,
const QV4::Value &arg);
219 QQmlDelegateModelAttached *attached()
const
224 QQmlData *ddata = QQmlData::get(m_object);
225 if (!ddata || !ddata->hasExtendedData())
228 return static_cast<QQmlDelegateModelAttached *>(
229 ddata->attachedProperties()->value(
230 QQmlPrivate::attachedPropertiesFunc<QQmlDelegateModel>()));
233 void disableStructuredModelData() { m_useStructuredModelData =
false; }
235 QDynamicMetaObjectData *exchangeMetaObject(QDynamicMetaObjectData *metaObject)
237 return std::exchange(d_ptr->metaObject, metaObject);
240 QQDMIncubationTask *incubationTask()
const {
return m_incubationTask; }
241 void clearIncubationTask() { m_incubationTask =
nullptr; }
242 void setIncubationTask(QQDMIncubationTask *incubationTask)
244 Q_ASSERT(!m_incubationTask);
245 Q_ASSERT(incubationTask);
246 m_incubationTask = incubationTask;
249 quint16 objectStrongRef()
const {
return m_objectStrongRef; }
250 quint16 objectWeakRef()
const {
return m_objectWeakRef; }
251 quint16 scriptRef()
const {
return m_scriptRef; }
253 QObject *object()
const {
return m_object; }
254 void setObject(QObject *object) {
260 QQmlComponent *delegate()
const {
return m_delegate; }
261 void setDelegate(QQmlComponent *delegate) { m_delegate = delegate; }
263 const QQmlRefPointer<QQmlContextData> &contextData()
const {
return m_contextData; }
264 void setContextData(
const QQmlRefPointer<QQmlContextData> &contextData)
266 m_contextData = contextData;
269 int groups()
const {
return m_groups; }
270 void setGroups(
int groups) { m_groups = groups; }
271 void addGroups(
int groups) { m_groups |= groups; }
272 void removeGroups(
int groups) { m_groups &= ~groups; }
273 void clearGroups() { m_groups = 0; }
275 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType()
const {
return m_metaType; }
278 void modelIndexChanged();
279 Q_REVISION(2, 12)
void rowChanged();
280 Q_REVISION(2, 12)
void columnChanged();
283 void objectDestroyed(QObject *);
285 void referenceSript() { ++m_scriptRef; }
288 Q_ASSERT(m_scriptRef > 0);
289 return --m_scriptRef == 0;
292 QQmlRefPointer<QQmlDelegateModelItemMetaType> m_metaType;
293 QQmlRefPointer<QQmlContextData> m_contextData;
294 QPointer<QObject> m_object;
295 QQDMIncubationTask *m_incubationTask =
nullptr;
296 QQmlComponent *m_delegate =
nullptr;
305 quint16 m_objectStrongRef = 0;
312 quint16 m_objectWeakRef = 0;
324 quint16 m_scriptRef = 0;
326 bool m_useStructuredModelData =
true;
327 QPersistentModelIndex m_persistentIndex;
333 inline void init(QQmlDelegateModelItem *item);
339 QQmlDelegateModelItem *
item()
const {
340 return reinterpret_cast<
const QQmlDelegateModelItem::ScriptReference *>(&ref)->data();
356 new (ref) QQmlDelegateModelItem::ScriptReference(modelItem);
362 bool insertItem(QQmlDelegateModelItem *modelItem);
363 QQmlDelegateModelItem *
takeItem(
const QQmlComponent *delegate,
int newIndexHint);
364 void reuseItem(QQmlDelegateModelItem *item,
int newModelIndex);
365 void drain(
int maxPoolTime, std::function<
void(QQmlDelegateModelItem *cacheItem)> releaseItem);
368 Q_ASSERT(m_reusableItemsPool.size() <= MaxSize);
369 return int(m_reusableItemsPool.size());
375 QQmlDelegateModelItem *item =
nullptr;
379 static constexpr size_t MaxSize = size_t(std::numeric_limits<
int>::max());
381 std::vector<PoolItem> m_reusableItemsPool;
384template<
typename Target>
428 QDynamicMetaObjectData *original =
nullptr;
429 int readOnlyProperty = -1;
442 QQmlDelegateModelItem *modelItemToIncubate, QObject* object,
443 QQmlDelegateModel::DelegateModelAccess access);
472 Q_DECLARE_PUBLIC(QQmlDelegateModelGroup)
485 void initPackage(
int index, QQuickPackage *package);
488 bool parseIndex(
const QV4::Value &value,
int *index, Compositor::Group *group)
const;
490 QQmlV4FunctionPtr args, Compositor::Group *group,
int *index,
int *count,
int *groups)
const;
504 Q_DECLARE_PUBLIC(QQmlDelegateModel)
510 return static_cast<QQmlDelegateModelPrivate *>(QObjectPrivate::get(m));
519 QObject *
object(Compositor::Group group,
int index, QQmlIncubator::IncubationMode incubationMode);
525 Q_EMIT q_func()->createdItem(incubationTask->index[m_compositorGroup], item); }
527 Q_EMIT q_func()->initItem(incubationTask->index[m_compositorGroup], item); }
530 void addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it);
535 void reuseItem(QQmlDelegateModelItem *item,
int newModelIndex,
int newGroups);
539 void addGroups(Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags);
540 void removeGroups(Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags);
541 void setGroups(Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags);
544 const QList<Compositor::Insert> &inserts,
545 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
546 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems =
nullptr);
547 void itemsInserted(
const QList<Compositor::Insert> &inserts);
549 const QList<Compositor::Remove> &removes,
550 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
551 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems =
nullptr);
552 void itemsRemoved(
const QList<Compositor::Remove> &removes);
554 const QList<Compositor::Remove> &removes,
const QList<Compositor::Insert> &inserts);
555 void itemsChanged(
const QList<Compositor::Change> &changes);
569 static void group_append(QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group);
571 static QQmlDelegateModelGroup *
group_at(QQmlListProperty<QQmlDelegateModelGroup> *property, qsizetype index);
611 QQmlDelegateModelGroup *
m_groups[Compositor::MaximumGroupCount];
618 Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup FINAL)
638 int indexOf(QObject *item, QObject *objectContext)
const override;
643 void initPackage(
int index, QQuickPackage *package)
override;
650 QQmlDelegateModel *m_model;
651 QMultiHash<QObject *, QQuickPackage *> m_packaged;
653 QString m_filterGroup;
654 QList<QByteArray> m_watchedRoles;
655 QList<
int> m_pendingPackageInitializations;
656 Compositor::Group m_compositorGroup;
658 bool m_modelUpdatePending =
true;
661class QMetaPropertyBuilder;
683class QQmlDelegateModelAttachedMetaObject
final
684 :
public QAbstractDynamicMetaObject,
685 public QQmlRefCounted<QQmlDelegateModelAttachedMetaObject>
689 QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject);
696 QQmlDelegateModelItemMetaType *
const metaType;
697 QMetaObject *
const metaObject;
698 const int memberPropertyOffset;
699 const int indexPropertyOffset;
void initializeRequiredProperties(QQmlDelegateModelItem *modelItemToIncubate, QObject *object, QQmlDelegateModel::DelegateModelAccess access)
QPointer< QObject > proxiedObject
QQmlRefPointer< QQmlContextData > proxyContext
void statusChanged(Status) override
Called when the status of the incubator changes.
void setInitialState(QObject *) override
Called after the object is first created, but before complex property bindings are evaluated and,...
int index[QQmlListCompositor::MaximumGroupCount]
QQmlDelegateModelItem * incubating
QQDMIncubationTask(QQmlDelegateModelPrivate *l, IncubationMode mode)
QQmlDelegateModelPrivate * vdm
QQmlDelegateModelAttached(QQmlDelegateModelItem *cacheItem, QObject *parent)
void setInItems(bool inItems)
void setGroups(const QStringList &groups)
bool isUnresolved() const
\qmlattachedproperty bool QtQml.Models::DelegateModel::isUnresolved
void emitChanges()
\qmlattachedproperty bool QtQml.Models::DelegateModel::inItems
void setInPersistedItems(bool inPersisted)
~QQmlDelegateModelAttached()
QQmlDelegateModel * model() const
\qmlattachedproperty model QtQml.Models::DelegateModel::model
QStringList groups() const
\qmlattachedproperty list<string> QtQml.Models::DelegateModel::groups
int persistedItemsIndex() const
QQmlDelegateModelItem * m_cacheItem
bool inPersistedItems() const
~QQmlDelegateModelEngineData()
QV4::PersistentValue changeProto
QV4::ReturnedValue array(QV4::ExecutionEngine *engine, const QList< QQmlChangeSet::Change > &changes)
QQmlDelegateModelEngineData(QV4::ExecutionEngine *v4)
virtual void initPackage(int, QQuickPackage *)
virtual void destroyingPackage(QQuickPackage *)
virtual ~QQmlDelegateModelGroupEmitter()
virtual void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset)=0
virtual void createdPackage(int, QQuickPackage *)
QIntrusiveListNode emitterNode
bool parseIndex(const QV4::Value &value, int *index, Compositor::Group *group) const
void createdPackage(int index, QQuickPackage *package)
QPointer< QQmlDelegateModel > model
bool parseGroupArgs(QQmlV4FunctionPtr args, Compositor::Group *group, int *index, int *count, int *groups) const
bool isChangedConnected()
void initPackage(int index, QQuickPackage *package)
void emitModelUpdated(bool reset)
QQmlDelegateModelGroupEmitterList emitters
void destroyingPackage(QQuickPackage *package)
void emitChanges(QV4::ExecutionEngine *engine)
QList< QQmlPartsModel * > models
QQmlDelegateModel * model
void setInitialState(QQDMIncubationTask *incubationTask, QObject *o)
void removeCacheItem(QQmlDelegateModelItem *cacheItem)
QVariant variantValue(Compositor::Group group, int index, const QString &name)
bool m_incubatorCleanupScheduled
void emitCreatedPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package)
QList< QQDMIncubationTask * > m_finishedIncubating
void connectModel(QQmlAdaptorModel *model)
QList< QQmlDelegateModelItem * > m_cache
void itemsMoved(const QList< Compositor::Remove > &removes, const QList< Compositor::Insert > &inserts)
QQmlDelegateModelParts * m_parts
static qsizetype group_count(QQmlListProperty< QQmlDelegateModelGroup > *property)
QList< QByteArray > m_watchedRoles
QQmlAbstractDelegateComponent * m_delegateChooser
QPointer< QQmlContext > m_context
void itemsInserted(const QList< Compositor::Insert > &inserts)
void emitCreatedItem(QQDMIncubationTask *incubationTask, QObject *item)
void emitInitItem(QQDMIncubationTask *incubationTask, QObject *item)
static void group_append(QQmlListProperty< QQmlDelegateModelGroup > *property, QQmlDelegateModelGroup *group)
QQmlStrongJSQObjectReference< QQmlComponent > m_delegate
void emitDestroyingItem(QObject *item)
void addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it)
QQmlRefPointer< QQmlDelegateModelItemMetaType > m_cacheMetaType
void reuseItem(QQmlDelegateModelItem *item, int newModelIndex, int newGroups)
void drainReusableItemsPool(int maxPoolTime)
QQmlDelegateModelGroup * m_persistedItems
static QQmlDelegateModelGroup * group_at(QQmlListProperty< QQmlDelegateModelGroup > *property, qsizetype index)
void itemsRemoved(const QList< Compositor::Remove > &removes, QVarLengthArray< QList< QQmlChangeSet::Change >, Compositor::MaximumGroupCount > *translatedRemoves, QHash< int, QList< QQmlDelegateModelItem * > > *movedItems=nullptr)
QQmlDelegateModelGroupEmitterList m_pendingParts
void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override
QQmlDelegateModelGroup * m_cacheItems
QObject * object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode)
void destroyCacheItem(QQmlDelegateModelItem *cacheItem)
void itemsRemoved(const QList< Compositor::Remove > &removes)
void connectToAbstractItemModel()
int adaptorModelCount() const
InsertionResult insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups)
void setGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
void delegateChanged(bool add=true, bool remove=true)
QQmlListCompositor m_compositor
QQmlDelegateModelGroup * m_items
void releaseIncubator(QQDMIncubationTask *incubationTask)
bool m_waitingToFetchMore
void itemsInserted(const QList< Compositor::Insert > &inserts, QVarLengthArray< QList< QQmlChangeSet::Change >, Compositor::MaximumGroupCount > *translatedInserts, QHash< int, QList< QQmlDelegateModelItem * > > *movedItems=nullptr)
void incubatorStatusChanged(QQDMIncubationTask *incubationTask, QQmlIncubator::Status status)
void emitInitPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package)
void addGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
void emitDestroyingPackage(QQuickPackage *package)
void requestMoreIfNecessary()
QQmlComponent * resolveDelegate(int index)
QMetaObject::Connection m_delegateChooserChanged
QQmlDelegateModelGroup * m_groups[Compositor::MaximumGroupCount]
void removeGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
void itemsChanged(const QList< Compositor::Change > &changes)
void disconnectFromAbstractItemModel()
QQmlReusableDelegateModelItemsPool m_reusableItemsPool
QQmlAdaptorModel m_adaptorModel
~QQmlDelegateModelPrivate()
QQmlListCompositor::Group m_compositorGroup
static QQmlDelegateModelPrivate * get(QQmlDelegateModel *m)
void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override
QVariant variantValue(int index, const QString &role) override
int count() const override
QObject * object(int index, QQmlIncubator::IncubationMode incubationMode=QQmlIncubator::AsynchronousIfNested) override
QList< QByteArray > watchedRoles() const
void updateFilterGroup(Compositor::Group group, const QQmlChangeSet &changeSet)
void setFilterGroup(const QString &group)
QQmlIncubator::Status incubationStatus(int index) override
int indexOf(QObject *item, QObject *objectContext) const override
void destroyingPackage(QQuickPackage *package) override
void setWatchedRoles(const QList< QByteArray > &roles) override
ReleaseFlags release(QObject *item, ReusableFlag reusable=NotReusable) override
void createdPackage(int index, QQuickPackage *package) override
void initPackage(int index, QQuickPackage *package) override
QString filterGroup() const
bool isValid() const override
bool insertItem(QQmlDelegateModelItem *modelItem)
void reuseItem(QQmlDelegateModelItem *item, int newModelIndex)
void drain(int maxPoolTime, std::function< void(QQmlDelegateModelItem *cacheItem)> releaseItem)
QQmlDelegateModelItem * takeItem(const QQmlComponent *delegate, int newIndexHint)
Combined button and popup list for selecting options.
QT_REQUIRE_CONFIG(animation)
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQIORing)
QT_REQUIRE_CONFIG(qml_delegate_model)
static bool isDoneIncubating(QQmlIncubator::Status status)
DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChange)
DEFINE_OBJECT_VTABLE(QV4::DelegateModelGroupFunction)
DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject)
static void incrementIndexes(QQmlDelegateModelItem *cacheItem, int count, const int *deltas)
DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChangeArray)
QQmlDelegateModelGroupEmitterList::iterator GroupEmitterListIt
QIntrusiveList< QQmlDelegateModelGroupEmitter, &QQmlDelegateModelGroupEmitter::emitterNode > QQmlDelegateModelGroupEmitterList
QT_BEGIN_NAMESPACE typedef QQmlListCompositor Compositor
void init(ExecutionEngine *engine, uint flag, QV4::ReturnedValue(*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
QV4::ReturnedValue(* code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg)
void init(const QList< QQmlChangeSet::Change > &changes)
QList< QQmlChangeSet::Change > * changes
QQmlChangeSet::ChangeData change
QQmlDelegateModelItem * item() const
void init(QQmlDelegateModelItem *item)
std::byte ref[sizeof(QQmlDelegateModelItem::ScriptReference)]