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);
201 bool usesStructuredModelData()
const {
return m_useStructuredModelData; }
203 virtual QV4::ReturnedValue get() {
return QV4::QObjectWrapper::wrap(m_metaType->v4Engine,
this); }
205 virtual void setValue(
const QString &role,
const QVariant &value) { Q_UNUSED(role); Q_UNUSED(value); }
206 virtual bool resolveIndex(
const QQmlAdaptorModel &,
int) {
return false; }
207 virtual QQmlRefPointer<QQmlContextData> initProxy() {
return m_contextData; }
209 static QV4::ReturnedValue get_model(
const QV4::FunctionObject *,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc);
210 static QV4::ReturnedValue get_groups(
const QV4::FunctionObject *,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc);
211 static QV4::ReturnedValue set_groups(
const QV4::FunctionObject *,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc);
212 static QV4::ReturnedValue get_member(QQmlDelegateModelItem *thisItem, uint flag,
const QV4::Value &);
213 static QV4::ReturnedValue set_member(QQmlDelegateModelItem *thisItem, uint flag,
const QV4::Value &arg);
214 static QV4::ReturnedValue get_index(QQmlDelegateModelItem *thisItem, uint flag,
const QV4::Value &arg);
217 QQmlDelegateModelAttached *attached()
const
222 QQmlData *ddata = QQmlData::get(m_object);
223 if (!ddata || !ddata->hasExtendedData())
226 return static_cast<QQmlDelegateModelAttached *>(
227 ddata->attachedProperties()->value(
228 QQmlPrivate::attachedPropertiesFunc<QQmlDelegateModel>()));
231 void disableStructuredModelData() { m_useStructuredModelData =
false; }
233 QDynamicMetaObjectData *exchangeMetaObject(QDynamicMetaObjectData *metaObject)
235 return std::exchange(d_ptr->metaObject, metaObject);
238 QQDMIncubationTask *incubationTask()
const {
return m_incubationTask; }
239 void clearIncubationTask() { m_incubationTask =
nullptr; }
240 void setIncubationTask(QQDMIncubationTask *incubationTask)
242 Q_ASSERT(!m_incubationTask);
243 Q_ASSERT(incubationTask);
244 m_incubationTask = incubationTask;
247 quint16 objectStrongRef()
const {
return m_objectStrongRef; }
248 quint16 objectWeakRef()
const {
return m_objectWeakRef; }
249 quint16 scriptRef()
const {
return m_scriptRef; }
251 QObject *object()
const {
return m_object; }
252 void setObject(QObject *object) {
258 QQmlComponent *delegate()
const {
return m_delegate; }
259 void setDelegate(QQmlComponent *delegate) { m_delegate = delegate; }
261 const QQmlRefPointer<QQmlContextData> &contextData()
const {
return m_contextData; }
262 void setContextData(
const QQmlRefPointer<QQmlContextData> &contextData)
264 m_contextData = contextData;
267 int groups()
const {
return m_groups; }
268 void setGroups(
int groups) { m_groups = groups; }
269 void addGroups(
int groups) { m_groups |= groups; }
270 void removeGroups(
int groups) { m_groups &= ~groups; }
271 void clearGroups() { m_groups = 0; }
273 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType()
const {
return m_metaType; }
276 void modelIndexChanged();
277 Q_REVISION(2, 12)
void rowChanged();
278 Q_REVISION(2, 12)
void columnChanged();
281 void objectDestroyed(QObject *);
283 void referenceSript() { ++m_scriptRef; }
286 Q_ASSERT(m_scriptRef > 0);
287 return --m_scriptRef == 0;
290 QQmlRefPointer<QQmlDelegateModelItemMetaType> m_metaType;
291 QQmlRefPointer<QQmlContextData> m_contextData;
292 QPointer<QObject> m_object;
293 QQDMIncubationTask *m_incubationTask =
nullptr;
294 QQmlComponent *m_delegate =
nullptr;
303 quint16 m_objectStrongRef = 0;
310 quint16 m_objectWeakRef = 0;
322 quint16 m_scriptRef = 0;
324 bool m_useStructuredModelData =
true;
330 inline void init(QQmlDelegateModelItem *item);
336 QQmlDelegateModelItem *
item()
const {
337 return reinterpret_cast<
const QQmlDelegateModelItem::ScriptReference *>(&ref)->data();
353 new (ref) QQmlDelegateModelItem::ScriptReference(modelItem);
359 bool insertItem(QQmlDelegateModelItem *modelItem);
360 QQmlDelegateModelItem *
takeItem(
const QQmlComponent *delegate,
int newIndexHint);
361 void reuseItem(QQmlDelegateModelItem *item,
int newModelIndex);
362 void drain(
int maxPoolTime, std::function<
void(QQmlDelegateModelItem *cacheItem)> releaseItem);
365 Q_ASSERT(m_reusableItemsPool.size() <= MaxSize);
366 return int(m_reusableItemsPool.size());
372 QQmlDelegateModelItem *item =
nullptr;
376 static constexpr size_t MaxSize = size_t(std::numeric_limits<
int>::max());
378 std::vector<PoolItem> m_reusableItemsPool;
381template<
typename Target>
425 QDynamicMetaObjectData *original =
nullptr;
426 int readOnlyProperty = -1;
439 QQmlDelegateModelItem *modelItemToIncubate, QObject* object,
440 QQmlDelegateModel::DelegateModelAccess access);
469 Q_DECLARE_PUBLIC(QQmlDelegateModelGroup)
482 void initPackage(
int index, QQuickPackage *package);
485 bool parseIndex(
const QV4::Value &value,
int *index, Compositor::Group *group)
const;
487 QQmlV4FunctionPtr args, Compositor::Group *group,
int *index,
int *count,
int *groups)
const;
501 Q_DECLARE_PUBLIC(QQmlDelegateModel)
507 return static_cast<QQmlDelegateModelPrivate *>(QObjectPrivate::get(m));
516 QObject *
object(Compositor::Group group,
int index, QQmlIncubator::IncubationMode incubationMode);
522 Q_EMIT q_func()->createdItem(incubationTask->index[m_compositorGroup], item); }
524 Q_EMIT q_func()->initItem(incubationTask->index[m_compositorGroup], item); }
527 void addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it);
532 void reuseItem(QQmlDelegateModelItem *item,
int newModelIndex,
int newGroups);
536 void addGroups(Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags);
537 void removeGroups(Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags);
538 void setGroups(Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags);
541 const QList<Compositor::Insert> &inserts,
542 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
543 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems =
nullptr);
544 void itemsInserted(
const QList<Compositor::Insert> &inserts);
546 const QList<Compositor::Remove> &removes,
547 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
548 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems =
nullptr);
549 void itemsRemoved(
const QList<Compositor::Remove> &removes);
551 const QList<Compositor::Remove> &removes,
const QList<Compositor::Insert> &inserts);
552 void itemsChanged(
const QList<Compositor::Change> &changes);
566 static void group_append(QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group);
568 static QQmlDelegateModelGroup *
group_at(QQmlListProperty<QQmlDelegateModelGroup> *property, qsizetype index);
608 QQmlDelegateModelGroup *
m_groups[Compositor::MaximumGroupCount];
615 Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup FINAL)
635 int indexOf(QObject *item, QObject *objectContext)
const override;
640 void initPackage(
int index, QQuickPackage *package)
override;
647 QQmlDelegateModel *m_model;
648 QMultiHash<QObject *, QQuickPackage *> m_packaged;
650 QString m_filterGroup;
651 QList<QByteArray> m_watchedRoles;
652 QList<
int> m_pendingPackageInitializations;
653 Compositor::Group m_compositorGroup;
655 bool m_modelUpdatePending =
true;
658class QMetaPropertyBuilder;
680class QQmlDelegateModelAttachedMetaObject
final
681 :
public QAbstractDynamicMetaObject,
682 public QQmlRefCounted<QQmlDelegateModelAttachedMetaObject>
686 QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject);
693 QQmlDelegateModelItemMetaType *
const metaType;
694 QMetaObject *
const metaObject;
695 const int memberPropertyOffset;
696 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)]