7#include <QtQml/qqmlinfo.h>
9#include <private/qabstractitemmodel_p.h>
10#include <private/qcoreapplication_p.h>
11#include <private/qjsvalue_p.h>
12#include <private/qmetaobjectbuilder_p.h>
13#include <private/qqmlabstractdelegatecomponent_p.h>
14#include <private/qqmladaptormodel_p.h>
15#include <private/qqmlanybinding_p.h>
16#include <private/qqmlchangeset_p.h>
17#include <private/qqmlcomponent_p.h>
18#include <private/qqmlengine_p.h>
19#include <private/qqmlpropertytopropertybinding_p.h>
20#include <private/qqmltableinstancemodel_p.h>
21#include <private/qquickpackage_p.h>
22#include <private/qv4functionobject_p.h>
23#include <private/qv4objectiterator_p.h>
24#include <private/qv4value_p.h>
28Q_LOGGING_CATEGORY(lcItemViewDelegateRecycling,
"qt.qml.delegatemodel.recycling")
30class QQmlDelegateModelItem;
37 void init(ExecutionEngine *engine, uint flag, QV4::ReturnedValue (*code)(
QQmlDelegateModelItem *item, uint flag,
const QV4::Value &arg));
44 void init() { Object::init(); }
50 void init(
const QVector<QQmlChangeSet::Change> &changes);
87 QV4::ExecutionEngine *engine, uint flag,
90 QV4::Heap::FunctionObject::init(engine, QStringLiteral(
"DelegateModelGroupFunction"));
108 const QVector<QQmlChangeSet::Change> &changes);
118 prop.setWritable(
false);
125 parts->model, QString::fromUtf8(name(id)), parts);
126 parts->models.append(m);
127 return QVariant::fromValue(
static_cast<QObject *>(m));
131: QObject(parent), model(parent)
133 new QQmlDelegateModelPartsMetaObject(
this);
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
166 , m_filterGroup(QStringLiteral(
"items"))
168 , m_groupCount(Compositor::MinimumGroupCount)
169 , m_compositorGroup(Compositor::Cache)
176 , m_cacheItems(
nullptr)
178 , m_persistedItems(
nullptr)
184 qDeleteAll(m_finishedIncubating);
195 return m_adaptorModel.rowCount();
200 Q_Q(QQmlDelegateModel);
201 if (!m_waitingToFetchMore && m_adaptorModel.canFetchMore()) {
203 QCoreApplication::postEvent(q,
new QEvent(QEvent::UpdateRequest));
209 Q_Q(QQmlDelegateModel);
210 m_compositor.setRemoveGroups(Compositor::GroupMask & ~Compositor::PersistedFlag);
212 m_items =
new QQmlDelegateModelGroup(QStringLiteral(
"items"), q, Compositor::Default, q);
213 m_items->setDefaultInclude(
true);
214 m_persistedItems =
new QQmlDelegateModelGroup(QStringLiteral(
"persistedItems"), q, Compositor::Persisted, q);
215 QQmlDelegateModelGroupPrivate::get(m_items)->emitters.insert(
this);
218QQmlDelegateModel::QQmlDelegateModel()
219 : QQmlDelegateModel(
nullptr,
nullptr)
223QQmlDelegateModel::QQmlDelegateModel(QQmlContext *ctxt, QObject *parent)
224: QQmlInstanceModel(*(
new QQmlDelegateModelPrivate(ctxt)), parent)
226 Q_D(QQmlDelegateModel);
230QQmlDelegateModel::~QQmlDelegateModel()
232 Q_D(QQmlDelegateModel);
233 d->disconnectFromAbstractItemModel();
234 d->m_adaptorModel.setObject(
nullptr);
236 for (QQmlDelegateModelItem *cacheItem : std::as_const(d->m_cache)) {
237 if (cacheItem->object) {
238 delete cacheItem->object;
240 cacheItem->object =
nullptr;
241 cacheItem->contextData.reset();
242 cacheItem->scriptRef -= 1;
243 }
else if (cacheItem->incubationTask) {
246 cacheItem->scriptRef -= 1;
249 cacheItem->groups &= ~Compositor::UnresolvedFlag;
250 cacheItem->objectRef = 0;
252 if (cacheItem->incubationTask) {
253 d->releaseIncubator(cacheItem->incubationTask);
254 cacheItem->incubationTask->vdm =
nullptr;
255 cacheItem->incubationTask =
nullptr;
258 if (!cacheItem->isReferenced())
264void QQmlDelegateModel::classBegin()
266 Q_D(QQmlDelegateModel);
268 d->m_context = qmlContext(
this);
271void QQmlDelegateModel::componentComplete()
273 Q_D(QQmlDelegateModel);
274 d->m_complete =
true;
276 int defaultGroups = 0;
277 QStringList groupNames;
278 groupNames.append(QStringLiteral(
"items"));
279 groupNames.append(QStringLiteral(
"persistedItems"));
280 if (QQmlDelegateModelGroupPrivate::get(d->m_items)->defaultInclude)
281 defaultGroups |= Compositor::DefaultFlag;
282 if (QQmlDelegateModelGroupPrivate::get(d->m_persistedItems)->defaultInclude)
283 defaultGroups |= Compositor::PersistedFlag;
284 for (
int i = Compositor::MinimumGroupCount; i < d->m_groupCount; ++i) {
285 QString name = d->m_groups[i]->name();
286 if (name.isEmpty()) {
287 d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
290 }
else if (name.at(0).isUpper()) {
291 qmlWarning(d->m_groups[i]) << QQmlDelegateModelGroup::tr(
"Group names must start with a lower case letter");
292 d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
296 groupNames.append(name);
298 QQmlDelegateModelGroupPrivate *group = QQmlDelegateModelGroupPrivate::get(d->m_groups[i]);
299 group->setModel(
this, Compositor::Group(i));
300 if (group->defaultInclude)
301 defaultGroups |= (1 << i);
305 d->m_cacheMetaType = QQml::makeRefPointer<QQmlDelegateModelItemMetaType>(
306 d->m_context->engine()->handle(),
this, groupNames);
308 d->m_compositor.setGroupCount(d->m_groupCount);
309 d->m_compositor.setDefaultGroups(defaultGroups);
310 d->updateFilterGroup();
312 while (!d->m_pendingParts.isEmpty())
313 static_cast<QQmlPartsModel *>(d->m_pendingParts.first())->updateFilterGroup();
315 QVector<Compositor::Insert> inserts;
316 d->m_count = d->adaptorModelCount();
317 d->m_compositor.append(
321 defaultGroups | Compositor::AppendFlag | Compositor::PrependFlag,
323 d->itemsInserted(inserts);
325 d->requestMoreIfNecessary();
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343QVariant QQmlDelegateModel::model()
const
345 Q_D(
const QQmlDelegateModel);
346 return d->m_adaptorModel.model();
351 Q_Q(QQmlDelegateModel);
352 if (!m_adaptorModel.adaptsAim())
355 auto aim = m_adaptorModel.aim();
357 QObject::connect(aim, &QAbstractItemModel::rowsInserted, q, &QQmlDelegateModel::_q_rowsInserted);
358 QObject::connect(aim, &QAbstractItemModel::rowsRemoved, q, &QQmlDelegateModel::_q_rowsRemoved);
359 QObject::connect(aim, &QAbstractItemModel::rowsAboutToBeRemoved, q, &QQmlDelegateModel::_q_rowsAboutToBeRemoved);
360 QObject::connect(aim, &QAbstractItemModel::columnsInserted, q, &QQmlDelegateModel::_q_columnsInserted);
361 QObject::connect(aim, &QAbstractItemModel::columnsRemoved, q, &QQmlDelegateModel::_q_columnsRemoved);
362 QObject::connect(aim, &QAbstractItemModel::columnsMoved, q, &QQmlDelegateModel::_q_columnsMoved);
363 QObject::connect(aim, &QAbstractItemModel::dataChanged, q, &QQmlDelegateModel::_q_dataChanged);
364 QObject::connect(aim, &QAbstractItemModel::rowsMoved, q, &QQmlDelegateModel::_q_rowsMoved);
365 QObject::connect(aim, &QAbstractItemModel::modelAboutToBeReset, q, &QQmlDelegateModel::_q_modelAboutToBeReset);
366 QObject::connect(aim, &QAbstractItemModel::layoutChanged, q, &QQmlDelegateModel::_q_layoutChanged);
371 Q_Q(QQmlDelegateModel);
372 if (!m_adaptorModel.adaptsAim())
375 auto aim = m_adaptorModel.aim();
377 QObject::disconnect(aim, &QAbstractItemModel::rowsInserted, q, &QQmlDelegateModel::_q_rowsInserted);
378 QObject::disconnect(aim, &QAbstractItemModel::rowsAboutToBeRemoved, q, &QQmlDelegateModel::_q_rowsAboutToBeRemoved);
379 QObject::disconnect(aim, &QAbstractItemModel::rowsRemoved, q, &QQmlDelegateModel::_q_rowsRemoved);
380 QObject::disconnect(aim, &QAbstractItemModel::columnsInserted, q, &QQmlDelegateModel::_q_columnsInserted);
381 QObject::disconnect(aim, &QAbstractItemModel::columnsRemoved, q, &QQmlDelegateModel::_q_columnsRemoved);
382 QObject::disconnect(aim, &QAbstractItemModel::columnsMoved, q, &QQmlDelegateModel::_q_columnsMoved);
383 QObject::disconnect(aim, &QAbstractItemModel::dataChanged, q, &QQmlDelegateModel::_q_dataChanged);
384 QObject::disconnect(aim, &QAbstractItemModel::rowsMoved, q, &QQmlDelegateModel::_q_rowsMoved);
385 QObject::disconnect(aim, &QAbstractItemModel::modelAboutToBeReset, q, &QQmlDelegateModel::_q_modelAboutToBeReset);
386 QObject::disconnect(aim, &QAbstractItemModel::layoutChanged, q, &QQmlDelegateModel::_q_layoutChanged);
389void QQmlDelegateModel::setModel(
const QVariant &model)
391 Q_D(QQmlDelegateModel);
393 if (d->m_adaptorModel.model() == model)
397 _q_itemsRemoved(0, d->m_count);
399 d->disconnectFromAbstractItemModel();
400 d->m_adaptorModel.setModel(model);
401 d->connectToAbstractItemModel();
403 d->m_adaptorModel.replaceWatchedRoles(QList<QByteArray>(), d->m_watchedRoles);
404 for (
int i = 0; d->m_parts && i < d->m_parts->models.size(); ++i) {
405 d->m_adaptorModel.replaceWatchedRoles(
406 QList<QByteArray>(), d->m_parts->models.at(i)->watchedRoles());
410 _q_itemsInserted(0, d->adaptorModelCount());
411 d->requestMoreIfNecessary();
422 if (d->m_adaptorModel.adaptsAim()) {
423 auto *aim = d->m_adaptorModel.aim();
424 auto *aimPrivate = QAbstractItemModelPrivate::get(aim);
425 if (aimPrivate->resetting)
426 QObject::connect(aim, &QAbstractItemModel::modelReset,
this, &QQmlDelegateModel::handleModelReset, Qt::SingleShotConnection);
433
434
435
436
437
438
439QQmlComponent *QQmlDelegateModel::delegate()
const
441 Q_D(
const QQmlDelegateModel);
442 return d->m_delegate;
445void QQmlDelegateModel::setDelegate(QQmlComponent *delegate)
447 Q_D(QQmlDelegateModel);
448 if (d->m_transaction) {
449 qmlWarning(
this) << tr(
"The delegate of a DelegateModel cannot be changed within onUpdated.");
452 if (d->m_delegate == delegate)
455 _q_itemsRemoved(0, d->m_count);
456 d->m_delegate.setObject(delegate,
this);
457 d->m_delegateValidated =
false;
458 if (d->m_delegateChooser)
459 QObject::disconnect(d->m_delegateChooserChanged);
461 d->m_delegateChooser =
nullptr;
463 QQmlAbstractDelegateComponent *adc =
464 qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
466 d->m_delegateChooser = adc;
467 d->m_delegateChooserChanged = connect(adc, &QQmlAbstractDelegateComponent::delegateChanged,
this,
468 [d](){ d->delegateChanged(); });
472 _q_itemsInserted(0, d->adaptorModelCount());
473 d->requestMoreIfNecessary();
475 emit delegateChanged();
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506QVariant QQmlDelegateModel::rootIndex()
const
508 Q_D(
const QQmlDelegateModel);
509 return QVariant::fromValue(QModelIndex(d->m_adaptorModel.rootIndex));
512void QQmlDelegateModel::setRootIndex(
const QVariant &root)
514 Q_D(QQmlDelegateModel);
516 QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
517 const bool changed = d->m_adaptorModel.rootIndex != modelIndex;
518 if (changed || !d->m_adaptorModel.isValid()) {
519 const int oldCount = d->m_count;
520 d->m_adaptorModel.rootIndex = modelIndex;
521 if (!d->m_adaptorModel.isValid() && d->m_adaptorModel.aim()) {
523 d->disconnectFromAbstractItemModel();
524 d->m_adaptorModel.setModel(d->m_adaptorModel.list.list());
525 d->connectToAbstractItemModel();
527 if (d->m_adaptorModel.canFetchMore())
528 d->m_adaptorModel.fetchMore();
530 const int newCount = d->adaptorModelCount();
532 _q_itemsRemoved(0, oldCount);
534 _q_itemsInserted(0, newCount);
537 emit rootIndexChanged();
542
543
544
545
546QQmlDelegateModel::DelegateModelAccess QQmlDelegateModel::delegateModelAccess()
const
548 Q_D(
const QQmlDelegateModel);
549 return d->m_adaptorModel.delegateModelAccess;
552void QQmlDelegateModel::setDelegateModelAccess(
553 QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
555 Q_D(QQmlDelegateModel);
556 if (d->m_adaptorModel.delegateModelAccess == delegateModelAccess)
559 if (d->m_transaction) {
560 qmlWarning(
this) << tr(
"The delegateModelAccess of a DelegateModel "
561 "cannot be changed within onUpdated.");
566 _q_itemsRemoved(0, d->m_count);
567 d->m_adaptorModel.delegateModelAccess = delegateModelAccess;
568 _q_itemsInserted(0, d->adaptorModelCount());
569 d->requestMoreIfNecessary();
571 d->m_adaptorModel.delegateModelAccess = delegateModelAccess;
574 emit delegateModelAccessChanged();
578
579
580
581
582
583
584
585
586
587
588
589QVariant QQmlDelegateModel::modelIndex(
int idx)
const
591 Q_D(
const QQmlDelegateModel);
592 return d->m_adaptorModel.modelIndex(idx);
596
597
598
599
600
601
602
603
604
605
606
607QVariant QQmlDelegateModel::parentModelIndex()
const
609 Q_D(
const QQmlDelegateModel);
610 return d->m_adaptorModel.parentModelIndex();
614
615
617int QQmlDelegateModel::count()
const
619 Q_D(
const QQmlDelegateModel);
622 return d->m_compositor.count(d->m_compositorGroup);
628 return QQmlDelegateModel::ReleaseFlags{};
632 return QQmlDelegateModel::ReleaseFlags{};
634 if (!cacheItem->releaseObject())
635 return QQmlDelegateModel::Referenced;
637 if (reusableFlag == QQmlInstanceModel::Reusable && m_reusableItemsPool.insertItem(cacheItem)) {
639 emit q_func()->itemPooled(cacheItem->modelIndex(), cacheItem->object);
640 return QQmlInstanceModel::Pooled;
644 return QQmlInstanceModel::Destroyed;
649 emitDestroyingItem(cacheItem->object);
659
660
661QQmlDelegateModel::ReleaseFlags QQmlDelegateModel::release(QObject *item, QQmlInstanceModel::ReusableFlag reusableFlag)
663 Q_D(QQmlDelegateModel);
664 QQmlInstanceModel::ReleaseFlags stat = d->release(item, reusableFlag);
669void QQmlDelegateModel::cancel(
int index)
671 Q_D(QQmlDelegateModel);
672 if (index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
673 qWarning() <<
"DelegateModel::cancel: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
677 Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
678 QQmlDelegateModelItem *cacheItem = it->inCache() ? d->m_cache.at(it.cacheIndex()) : 0;
680 if (cacheItem->incubationTask && !cacheItem->isObjectReferenced()) {
681 d->releaseIncubator(cacheItem->incubationTask);
682 cacheItem->incubationTask =
nullptr;
684 if (cacheItem->object) {
685 QObject *object = cacheItem->object;
686 cacheItem->destroyObject();
687 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
688 d->emitDestroyingPackage(package);
690 d->emitDestroyingItem(object);
693 cacheItem->scriptRef -= 1;
695 if (!cacheItem->isReferenced()) {
696 d->m_compositor.clearFlags(
697 Compositor::Cache, it.cacheIndex(), 1, Compositor::CacheFlag);
698 d->m_cache.removeAt(it.cacheIndex());
700 Q_ASSERT(d->m_cache.size() == d->m_compositor.count(Compositor::Cache));
706 QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group)
711 if (d->m_groupCount == Compositor::MaximumGroupCount) {
712 qmlWarning(d->q_func()) << QQmlDelegateModel::tr(
"The maximum number of supported DelegateModelGroups is 8");
720 QQmlListProperty<QQmlDelegateModelGroup> *property)
727 QQmlListProperty<QQmlDelegateModelGroup> *property, qsizetype index)
731 ? d->m_groups[index + 1]
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
763QQmlListProperty<QQmlDelegateModelGroup> QQmlDelegateModel::groups()
765 Q_D(QQmlDelegateModel);
766 return QQmlListProperty<QQmlDelegateModelGroup>(
769 QQmlDelegateModelPrivate::group_append,
770 QQmlDelegateModelPrivate::group_count,
771 QQmlDelegateModelPrivate::group_at,
772 nullptr,
nullptr,
nullptr);
776
777
778
779
781QQmlDelegateModelGroup *QQmlDelegateModel::items()
783 Q_D(QQmlDelegateModel);
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
804QQmlDelegateModelGroup *QQmlDelegateModel::persistedItems()
806 Q_D(QQmlDelegateModel);
807 return d->m_persistedItems;
811
812
813
814
815
816
817
818
820QString QQmlDelegateModel::filterGroup()
const
822 Q_D(
const QQmlDelegateModel);
823 return d->m_filterGroup;
826void QQmlDelegateModel::setFilterGroup(
const QString &group)
828 Q_D(QQmlDelegateModel);
830 if (d->m_transaction) {
831 qmlWarning(
this) << tr(
"The group of a DelegateModel cannot be changed within onChanged");
835 if (d->m_filterGroup != group) {
836 d->m_filterGroup = group;
837 d->updateFilterGroup();
838 emit filterGroupChanged();
842void QQmlDelegateModel::resetFilterGroup()
844 setFilterGroup(QStringLiteral(
"items"));
849 Q_Q(QQmlDelegateModel);
850 if (!m_cacheMetaType)
853 QQmlListCompositor::Group previousGroup = m_compositorGroup;
854 m_compositorGroup = Compositor::Default;
856 if (m_filterGroup == m_cacheMetaType->groupNames.at(i - 1)) {
857 m_compositorGroup = Compositor::Group(i);
862 QQmlDelegateModelGroupPrivate::get(m_groups[m_compositorGroup])->emitters.insert(
this);
863 if (m_compositorGroup != previousGroup) {
864 QVector<QQmlChangeSet::Change> removes;
865 QVector<QQmlChangeSet::Change> inserts;
866 m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
868 QQmlChangeSet changeSet;
869 changeSet.move(removes, inserts);
870 emit q->modelUpdated(changeSet,
false);
872 if (changeSet.difference() != 0)
873 emit q->countChanged();
876 auto partsCopy =
m_parts->models;
877 for (QQmlPartsModel *model : std::as_const(partsCopy))
878 model->updateFilterGroup(m_compositorGroup, changeSet);
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
911QObject *QQmlDelegateModel::parts()
913 Q_D(QQmlDelegateModel);
915 d->m_parts =
new QQmlDelegateModelParts(
this);
919const QAbstractItemModel *QQmlDelegateModel::abstractItemModel()
const
921 Q_D(
const QQmlDelegateModel);
922 return d->m_adaptorModel.adaptsAim() ? d->m_adaptorModel.aim() :
nullptr;
927 for (
int i = 1; i < m_groupCount; ++i)
928 QQmlDelegateModelGroupPrivate::get(m_groups[i])->createdPackage(incubationTask->index[i], package);
933 for (
int i = 1; i < m_groupCount; ++i)
934 QQmlDelegateModelGroupPrivate::get(m_groups[i])->initPackage(incubationTask->index[i], package);
939 for (
int i = 1; i < m_groupCount; ++i)
940 QQmlDelegateModelGroupPrivate::get(m_groups[i])->destroyingPackage(package);
945 return status == QQmlIncubator::Ready || status == QQmlIncubator::Error;
1008 QObject *targetObject =
nullptr;
1009 RequiredProperties *requiredProperties =
nullptr;
1016 QQmlDelegateModel::DelegateModelAccess access)
1020 QQmlData *d = QQmlData::get(object);
1021 if (
auto contextData = d ? d->context :
nullptr)
1022 contextData->setExtraObject(modelItemToIncubate);
1024 Q_ASSERT(modelItemToIncubate->delegate);
1025 const bool isBound = QQmlComponentPrivate::get(modelItemToIncubate->delegate)->isBound();
1027 auto incubatorPriv = QQmlIncubatorPrivate::get(
this);
1028 if (incubatorPriv->hadTopLevelRequiredProperties()) {
1034 incubating->contextData->setContextObject(
nullptr);
1037 proxyContext->setContextObject(
nullptr);
1043 const QMetaObject *qmlMetaObject = modelItemToIncubate->metaObject();
1045 RequiredProperties *requiredProperties = incubatorPriv->requiredProperties();
1046 if (requiredProperties->empty())
1050 QQmlEnginePrivate::get(incubatorPriv->enginePriv),
1051 object, requiredProperties, access);
1061 initializer(qmlMetaObject, modelItemToIncubate);
1063 auto delegateModelItemSubclassMO = qmlMetaObject->superClass();
1064 initializer(delegateModelItemSubclassMO, modelItemToIncubate);
1066 while (strcmp(delegateModelItemSubclassMO->className(),
1067 modelItemToIncubate->staticMetaObject.className())) {
1068 delegateModelItemSubclassMO = delegateModelItemSubclassMO->superClass();
1069 initializer(delegateModelItemSubclassMO, modelItemToIncubate);
1073 initializer(proxiedObject->metaObject(), proxiedObject.data());
1081 modelItemToIncubate->contextData->setContextObject(modelItemToIncubate);
1083 proxyContext->setContextObject(proxiedObject);
1090 modelItemToIncubate->metaObject();
1097 vdm->incubatorStatusChanged(
this, status);
1098 }
else if (isDoneIncubating(status)) {
1111 Q_Q(QQmlDelegateModel);
1112 if (!incubationTask->isError())
1113 incubationTask->clear();
1114 m_finishedIncubating.append(incubationTask);
1117 QCoreApplication::postEvent(q,
new QEvent(QEvent::User));
1123 Q_ASSERT(item->object);
1132 const bool alwaysEmit =
true;
1138 auto const updateAllRoles = QVector<
int>();
1139 m_adaptorModel.notify(itemAsList, newModelIndex, 1, updateAllRoles);
1142 qmlAttachedPropertiesObject<QQmlDelegateModel>(item->object,
false))) {
1152 emit q_func()->itemReused(newModelIndex, item->object);
1157 m_reusableItemsPool.drain(maxPoolTime, [
this](QQmlDelegateModelItem *cacheItem){ destroyCacheItem(cacheItem); });
1160void QQmlDelegateModel::drainReusableItemsPool(
int maxPoolTime)
1162 d_func()->drainReusableItemsPool(maxPoolTime);
1165int QQmlDelegateModel::poolSize()
1167 return d_func()->m_reusableItemsPool.size();
1172 if (!m_delegateChooser)
1175 QQmlComponent *delegate =
nullptr;
1179 delegate = chooser->delegate(&m_adaptorModel, index);
1180 chooser = qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
1188 m_cache.insert(it.cacheIndex(), item);
1189 m_compositor.setFlags(it, 1, Compositor::CacheFlag);
1190 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1195 int cidx = m_cache.lastIndexOf(cacheItem);
1197 m_compositor.clearFlags(Compositor::Cache, cidx, 1, Compositor::CacheFlag);
1198 m_cache.removeAt(cidx);
1200 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1205 if (!isDoneIncubating(status))
1208 const QList<QQmlError> incubationTaskErrors = incubationTask->errors();
1215 if (status == QQmlIncubator::Ready) {
1217 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
1220 emitCreatedItem(incubationTask, cacheItem->object);
1222 }
else if (status == QQmlIncubator::Error) {
1223 qmlInfo(m_delegate, incubationTaskErrors + m_delegate->errors()) <<
"Cannot create delegate";
1227 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
1230 emitDestroyingItem(cacheItem->object);
1231 delete cacheItem->object;
1232 cacheItem->object =
nullptr;
1234 cacheItem->contextData.reset();
1245 vdm->setInitialState(
this, o);
1256 incubationTask->initializeRequiredProperties(
1257 incubationTask->incubating, o, m_adaptorModel.delegateModelAccess);
1258 cacheItem->object = o;
1260 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
1263 emitInitItem(incubationTask, cacheItem->object);
1268 if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
1269 qWarning() <<
"DelegateModel::item: index out range" << index << m_compositor.count(group);
1271 }
else if (!m_context || !m_context->isValid()) {
1275 Compositor::iterator it = m_compositor.find(group, index);
1276 const auto flags = it->flags;
1277 const auto modelIndex = it.modelIndex();
1281 if (!cacheItem || !cacheItem->delegate) {
1282 QQmlComponent *delegate = resolveDelegate(modelIndex);
1287 cacheItem = m_reusableItemsPool.takeItem(delegate, index);
1292 addCacheItem(cacheItem, it);
1296 if (index == m_compositor.count(group) - 1)
1298 return cacheItem->object;
1302 cacheItem = m_adaptorModel.createItem(m_cacheMetaType, modelIndex);
1307 addCacheItem(cacheItem, it);
1310 cacheItem->delegate = delegate;
1319 bool sync = (incubationMode == QQmlIncubator::Synchronous || incubationMode == QQmlIncubator::AsynchronousIfNested);
1320 if (sync && cacheItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous) {
1324 }
else if (!cacheItem->object) {
1325 QQmlContext *creationContext = cacheItem->delegate->creationContext();
1336 const QQmlRefPointer<QQmlContextData> componentContext
1337 = QQmlContextData::get(creationContext ? creationContext : m_context.data());
1338 QQmlComponentPrivate *cp = QQmlComponentPrivate::get(cacheItem->delegate);
1340 if (cp->isBound()) {
1341 cacheItem->contextData = componentContext;
1345 if (m_adaptorModel.hasProxyObject())
1346 cacheItem->initProxy();
1349 cacheItem->incubationTask,
1350 cacheItem->delegate,
1351 m_context->engine(),
1353 QQmlContextData::get(m_context));
1355 QQmlRefPointer<QQmlContextData> ctxt
1356 = QQmlContextData::createRefCounted(componentContext);
1357 ctxt->setContextObject(cacheItem);
1358 cacheItem->contextData = ctxt;
1362 if (m_adaptorModel.hasProxyObject()) {
1363 if (m_adaptorModel.delegateModelAccess == QQmlDelegateModel::ReadOnly)
1364 cacheItem->initProxy();
1366 ctxt = cacheItem->initProxy();
1370 cacheItem->incubationTask,
1371 cacheItem->delegate,
1372 m_context->engine(),
1374 QQmlContextData::get(m_context));
1378 if (index == m_compositor.count(group) - 1)
1383 if (cacheItem->object && (!cacheItem->incubationTask || isDoneIncubating(cacheItem->incubationTask->status())))
1384 return cacheItem->object;
1398
1399
1400
1401
1402
1403
1404
1405QObject *QQmlDelegateModel::object(
int index, QQmlIncubator::IncubationMode incubationMode)
1407 Q_D(QQmlDelegateModel);
1408 if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
1409 qWarning() <<
"DelegateModel::item: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
1413 return d->object(d->m_compositorGroup, index, incubationMode);
1416QQmlIncubator::Status QQmlDelegateModel::incubationStatus(
int index)
1418 Q_D(QQmlDelegateModel);
1419 if (d->m_compositor.count(d->m_compositorGroup) <= index)
1420 return QQmlIncubator::Null;
1421 Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
1423 return QQmlIncubator::Null;
1425 if (
auto incubationTask = d->m_cache.at(it.cacheIndex())->incubationTask)
1426 return incubationTask->status();
1428 return QQmlIncubator::Ready;
1433 Compositor::iterator it = m_compositor.find(group, index);
1434 if (QQmlAdaptorModel *model = it.list<QQmlAdaptorModel>()) {
1435 QString role = name;
1436 int dot = name.indexOf(QLatin1Char(
'.'));
1438 role = name.left(dot);
1439 QVariant value = model->value(it.modelIndex(), role);
1441 const int from = dot + 1;
1442 dot = name.indexOf(QLatin1Char(
'.'), from);
1443 QStringView propertyName = QStringView{name}.mid(from, dot - from);
1444 if (QObject *obj = qvariant_cast<QObject*>(value)) {
1445 value = obj->property(propertyName.toUtf8());
1446 }
else if (
const QMetaObject *metaObject = QQmlMetaType::metaObjectForValueType(value.metaType())) {
1448 const int propertyIndex = metaObject->indexOfProperty(propertyName.toUtf8());
1449 if (propertyIndex >= 0)
1450 value = metaObject->property(propertyIndex).readOnGadget(value.constData());
1460QVariant QQmlDelegateModel::variantValue(
int index,
const QString &role)
1462 Q_D(QQmlDelegateModel);
1463 return d->variantValue(d->m_compositorGroup, index, role);
1466int QQmlDelegateModel::indexOf(QObject *item, QObject *)
const
1468 Q_D(
const QQmlDelegateModel);
1469 if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(item))
1470 return cacheItem->groupIndex(d->m_compositorGroup);
1474void QQmlDelegateModel::setWatchedRoles(
const QList<QByteArray> &roles)
1476 Q_D(QQmlDelegateModel);
1477 d->m_adaptorModel.replaceWatchedRoles(d->m_watchedRoles, roles);
1478 d->m_watchedRoles = roles;
1482 Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags)
1484 QVector<Compositor::Insert> inserts;
1485 m_compositor.setFlags(from, count, group, groupFlags, &inserts);
1486 itemsInserted(inserts);
1491 Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags)
1493 QVector<Compositor::Remove> removes;
1494 m_compositor.clearFlags(from, count, group, groupFlags, &removes);
1495 itemsRemoved(removes);
1500 Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags)
1502 QVector<Compositor::Remove> removes;
1503 QVector<Compositor::Insert> inserts;
1505 m_compositor.setFlags(from, count, group, groupFlags, &inserts);
1506 itemsInserted(inserts);
1507 const int removeFlags = ~groupFlags & Compositor::GroupMask;
1509 from = m_compositor.find(from.group, from.index[from.group]);
1510 m_compositor.clearFlags(from, count, group, removeFlags, &removes);
1511 itemsRemoved(removes);
1515bool QQmlDelegateModel::event(QEvent *e)
1517 Q_D(QQmlDelegateModel);
1518 if (e->type() == QEvent::UpdateRequest) {
1519 d->m_waitingToFetchMore =
false;
1520 d->m_adaptorModel.fetchMore();
1521 }
else if (e->type() == QEvent::User) {
1522 d->m_incubatorCleanupScheduled =
false;
1523 qDeleteAll(d->m_finishedIncubating);
1524 d->m_finishedIncubating.clear();
1526 return QQmlInstanceModel::event(e);
1534 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedChanges(m_groupCount);
1536 for (
const Compositor::Change &change : changes) {
1537 for (
int i = 1; i < m_groupCount; ++i) {
1538 if (change.inGroup(i)) {
1539 translatedChanges[i].append(QQmlChangeSet::Change(change.index[i], change.count));
1544 for (
int i = 1; i < m_groupCount; ++i)
1545 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.change(translatedChanges.at(i));
1548void QQmlDelegateModel::_q_itemsChanged(
int index,
int count,
const QVector<
int> &roles)
1550 Q_D(QQmlDelegateModel);
1551 if (count <= 0 || !d->m_complete)
1554 if (d->m_adaptorModel.notify(d->m_cache, index, count, roles)) {
1555 QVector<Compositor::Change> changes;
1556 d->m_compositor.listItemsChanged(&d->m_adaptorModel, index, count, &changes);
1557 d->itemsChanged(changes);
1560 const bool needToCheckDelegateChoiceInvalidation = d->m_delegateChooser && !roles.isEmpty();
1561 if (!needToCheckDelegateChoiceInvalidation)
1566 if (!d->m_adaptorModel.adaptsAim())
1569 const auto aim = d->m_adaptorModel.aim();
1570 const auto choiceRole = d->m_delegateChooser->role().toUtf8();
1571 const auto &roleNames = aim->roleNames();
1572 auto it = std::find_if(roles.begin(), roles.end(), [&](
int role) {
1573 return roleNames[role] == choiceRole;
1575 if (it == roles.end())
1581
1582
1583
1584 QVector<Compositor::Remove> removes;
1585 QVector<Compositor::Insert> inserts;
1586 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, index, count, &removes);
1587 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1588 for (QQmlDelegateModelItem *item : cache)
1589 item->referenceObject();
1590 for (
const auto& removed: removes) {
1591 if (!d->m_cache.isSharedWith(cache))
1593 QQmlDelegateModelItem *item = cache.value(removed.cacheIndex(),
nullptr);
1594 if (!d->m_cache.contains(item))
1596 if (item->modelIndex() != -1)
1597 item->setModelIndex(-1, -1, -1);
1599 for (QQmlDelegateModelItem *item : cache)
1600 item->releaseObject();
1601 d->m_compositor.listItemsInserted(&d->m_adaptorModel, index, count, &inserts);
1602 d->itemsMoved(removes, inserts);
1609 for (
int i = 1; i < count; ++i)
1610 incubationTask->index[i] += deltas[i];
1613 for (
int i = 1; i < qMin<
int>(count, Compositor::MaximumGroupCount); ++i)
1614 attached->m_currentIndex[i] += deltas[i];
1619 const QVector<Compositor::Insert> &inserts,
1620 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
1621 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems)
1625 int inserted[Compositor::MaximumGroupCount];
1629 for (
const Compositor::Insert &insert : inserts) {
1630 for (; cacheIndex < insert.cacheIndex(); ++cacheIndex)
1631 incrementIndexes(m_cache.at(cacheIndex), m_groupCount, inserted);
1633 for (
int i = 1; i < m_groupCount; ++i) {
1634 if (insert.inGroup(i)) {
1635 (*translatedInserts)[i].append(
1636 QQmlChangeSet::Change(insert.index[i], insert.count, insert.moveId));
1637 inserted[i] += insert.count;
1641 if (!insert.inCache())
1644 if (movedItems && insert.isMove()) {
1645 QList<QQmlDelegateModelItem *> items = movedItems->take(insert.moveId);
1646 Q_ASSERT(items.size() == insert.count);
1647 m_cache = m_cache.mid(0, insert.cacheIndex())
1648 + items + m_cache.mid(insert.cacheIndex());
1650 if (insert.inGroup()) {
1651 for (
int offset = 0; cacheIndex < insert.cacheIndex() + insert.count;
1652 ++cacheIndex, ++offset) {
1653 QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
1654 cacheItem->groups |= insert.flags & Compositor::GroupMask;
1656 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
1657 for (
int i = 1; i < m_groupCount; ++i)
1658 incubationTask->index[i] = cacheItem->groups & (1 << i)
1659 ? insert.index[i] + offset
1662 if (QQmlDelegateModelAttached *attached = cacheItem->attached()) {
1663 for (
int i = 1; i < m_groupCount; ++i)
1664 attached->m_currentIndex[i] = cacheItem->groups & (1 << i)
1665 ? insert.index[i] + offset
1670 cacheIndex = insert.cacheIndex() + insert.count;
1673 for (
const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.size(); ++cacheIndex)
1674 incrementIndexes(cache.at(cacheIndex),
m_groupCount, inserted);
1679 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
1680 itemsInserted(inserts, &translatedInserts);
1681 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1685 for (
int i = 1; i < m_groupCount; ++i)
1686 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(translatedInserts.at(i));
1689void QQmlDelegateModel::_q_itemsInserted(
int index,
int count)
1692 Q_D(QQmlDelegateModel);
1693 if (count <= 0 || !d->m_complete)
1696 d->m_count += count;
1698 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1699 for (
int i = 0, c = cache.size(); i < c; ++i) {
1700 QQmlDelegateModelItem *item = cache.at(i);
1703 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
1706 if (item->modelIndex() >= index) {
1707 const int newIndex = item->modelIndex() + count;
1708 const int row = newIndex;
1709 const int column = 0;
1710 item->setModelIndex(newIndex, row, column);
1714 QVector<Compositor::Insert> inserts;
1715 d->m_compositor.listItemsInserted(&d->m_adaptorModel, index, count, &inserts);
1716 d->itemsInserted(inserts);
1728 const QVector<Compositor::Remove> &removes,
1729 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
1730 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems)
1733 int removedCache = 0;
1735 int removed[Compositor::MaximumGroupCount];
1739 for (
const Compositor::Remove &remove : removes) {
1740 for (; cacheIndex < remove.cacheIndex() && cacheIndex < m_cache.size(); ++cacheIndex)
1741 incrementIndexes(m_cache.at(cacheIndex), m_groupCount, removed);
1743 for (
int i = 1; i < m_groupCount; ++i) {
1744 if (remove.inGroup(i)) {
1745 (*translatedRemoves)[i].append(
1746 QQmlChangeSet::Change(remove.index[i], remove.count, remove.moveId));
1747 removed[i] -= remove.count;
1751 if (!remove.inCache())
1754 if (movedItems && remove.isMove()) {
1755 movedItems->insert(remove.moveId, m_cache.mid(remove.cacheIndex(), remove.count));
1756 QList<QQmlDelegateModelItem *>::const_iterator begin = m_cache.constBegin() + remove.cacheIndex();
1757 QList<QQmlDelegateModelItem *>::const_iterator end = begin + remove.count;
1758 m_cache.erase(begin, end);
1760 for (; cacheIndex < remove.cacheIndex() + remove.count - removedCache; ++cacheIndex) {
1761 QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
1762 if (remove.inGroup(Compositor::Persisted) && cacheItem->objectRef == 0 && cacheItem->object) {
1763 QObject *object = cacheItem->object;
1764 cacheItem->destroyObject();
1765 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
1766 emitDestroyingPackage(package);
1768 emitDestroyingItem(object);
1769 cacheItem->scriptRef -= 1;
1771 if (!cacheItem->isReferenced() && !remove.inGroup(Compositor::Persisted)) {
1772 m_compositor.clearFlags(Compositor::Cache, cacheIndex, 1, Compositor::CacheFlag);
1773 m_cache.removeAt(cacheIndex);
1777 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1778 }
else if (remove.groups() == cacheItem->groups) {
1779 cacheItem->groups = 0;
1780 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
1781 for (
int i = 1; i < m_groupCount; ++i)
1782 incubationTask->index[i] = -1;
1784 if (QQmlDelegateModelAttached *attached = cacheItem->attached()) {
1785 for (
int i = 1; i < m_groupCount; ++i)
1786 attached->m_currentIndex[i] = -1;
1789 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
1790 if (!cacheItem->isObjectReferenced()) {
1791 releaseIncubator(cacheItem->incubationTask);
1792 cacheItem->incubationTask =
nullptr;
1793 if (cacheItem->object) {
1794 QObject *object = cacheItem->object;
1795 cacheItem->destroyObject();
1796 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
1797 emitDestroyingPackage(package);
1799 emitDestroyingItem(object);
1801 cacheItem->scriptRef -= 1;
1803 for (
int i = 1; i < m_groupCount; ++i) {
1804 if (remove.inGroup(i))
1805 incubationTask->index[i] = remove.index[i];
1809 if (QQmlDelegateModelAttached *attached = cacheItem->attached()) {
1810 for (
int i = 1; i < m_groupCount; ++i) {
1811 if (remove.inGroup(i))
1812 attached->m_currentIndex[i] = remove.index[i];
1815 cacheItem->groups &= ~remove.flags;
1821 for (
const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.size(); ++cacheIndex)
1822 incrementIndexes(cache.at(cacheIndex),
m_groupCount, removed);
1827 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
1828 itemsRemoved(removes, &translatedRemoves);
1829 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1833 for (
int i = 1; i < m_groupCount; ++i)
1834 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(translatedRemoves.at(i));
1837void QQmlDelegateModel::_q_itemsRemoved(
int index,
int count)
1839 Q_D(QQmlDelegateModel);
1840 if (count <= 0|| !d->m_complete)
1843 d->m_count -= count;
1844 Q_ASSERT(d->m_count >= 0);
1845 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1847 for (QQmlDelegateModelItem *item : cache)
1848 item->referenceObject();
1850 for (
int i = 0, c = cache.size(); i < c; ++i) {
1851 QQmlDelegateModelItem *item = cache.at(i);
1854 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
1857 if (item->modelIndex() >= index + count) {
1858 const int newIndex = item->modelIndex() - count;
1859 const int row = newIndex;
1860 const int column = 0;
1861 item->setModelIndex(newIndex, row, column);
1862 }
else if (item->modelIndex() >= index) {
1863 item->setModelIndex(-1, -1, -1);
1867 for (QQmlDelegateModelItem *item : cache)
1868 item->releaseObject();
1870 QVector<Compositor::Remove> removes;
1871 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, index, count, &removes);
1872 d->itemsRemoved(removes);
1878 const QVector<Compositor::Remove> &removes,
const QVector<Compositor::Insert> &inserts)
1880 QHash<
int, QList<QQmlDelegateModelItem *> > movedItems;
1882 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
1883 itemsRemoved(removes, &translatedRemoves, &movedItems);
1885 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
1886 itemsInserted(inserts, &translatedInserts, &movedItems);
1887 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1888 Q_ASSERT(movedItems.isEmpty());
1893 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.move(
1894 translatedRemoves.at(i),
1895 translatedInserts.at(i));
1899void QQmlDelegateModel::_q_itemsMoved(
int from,
int to,
int count)
1901 Q_D(QQmlDelegateModel);
1902 if (count <= 0 || !d->m_complete)
1905 const int minimum = qMin(from, to);
1906 const int maximum = qMax(from, to) + count;
1907 const int difference = from > to ? count : -count;
1909 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1910 for (
int i = 0, c = cache.size(); i < c; ++i) {
1911 QQmlDelegateModelItem *item = cache.at(i);
1914 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
1917 if (item->modelIndex() >= from && item->modelIndex() < from + count) {
1918 const int newIndex = item->modelIndex() - from + to;
1919 const int row = newIndex;
1920 const int column = 0;
1921 item->setModelIndex(newIndex, row, column);
1922 }
else if (item->modelIndex() >= minimum && item->modelIndex() < maximum) {
1923 const int newIndex = item->modelIndex() + difference;
1924 const int row = newIndex;
1925 const int column = 0;
1926 item->setModelIndex(newIndex, row, column);
1930 QVector<Compositor::Remove> removes;
1931 QVector<Compositor::Insert> inserts;
1932 d->m_compositor.listItemsMoved(&d->m_adaptorModel, from, to, count, &removes, &inserts);
1933 d->itemsMoved(removes, inserts);
1939 Q_Q(QQmlDelegateModel);
1940 emit q->modelUpdated(changeSet, reset);
1941 if (changeSet.difference() != 0)
1942 emit q->countChanged();
1947 Q_Q(QQmlDelegateModel);
1952 qmlWarning(q) << QQmlDelegateModel::tr(
"The delegates of a DelegateModel cannot be changed within onUpdated.");
1958 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(
1959 0, m_compositor.count(Compositor::Group(i)));
1964 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(
1965 0, m_compositor.count(Compositor::Group(i)));
1973 if (m_transaction || !m_complete || !m_context || !m_context->isValid())
1977 QV4::ExecutionEngine *engine = m_context->engine()->handle();
1978 for (
int i = 1; i < m_groupCount; ++i)
1979 QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitChanges(engine);
1984 for (
int i = 1; i < m_groupCount; ++i)
1985 QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset);
1988 QVarLengthArray<QPointer<QQmlDelegateModelAttached>> attachedObjects;
1989 attachedObjects.reserve(m_cache.length());
1990 for (
const QQmlDelegateModelItem *cacheItem : std::as_const(m_cache))
1991 attachedObjects.append(cacheItem->attached());
1993 for (
const QPointer<QQmlDelegateModelAttached> &attached : std::as_const(attachedObjects)) {
1994 if (attached && attached->m_cacheItem)
1995 attached->emitChanges();
1999void QQmlDelegateModel::_q_modelAboutToBeReset()
2001 Q_D(QQmlDelegateModel);
2002 if (!d->m_adaptorModel.adaptsAim())
2004 auto aim = d->m_adaptorModel.aim();
2005 auto oldRoleNames = aim->roleNames();
2008 QObject::connect(aim, &QAbstractItemModel::modelReset,
this, [
this, d, oldRoleNames, aim](){
2009 if (!d->m_adaptorModel.adaptsAim() || d->m_adaptorModel.aim() != aim)
2011 if (oldRoleNames == aim->roleNames()) {
2017 QVariant m = model();
2018 setModel(QVariant());
2024 }, Qt::SingleShotConnection);
2027void QQmlDelegateModel::handleModelReset()
2029 Q_D(QQmlDelegateModel);
2033 int oldCount = d->m_count;
2034 d->m_adaptorModel.rootIndex = QModelIndex();
2036 if (d->m_complete) {
2037 d->m_count = d->adaptorModelCount();
2039 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
2040 for (QQmlDelegateModelItem *item : cache)
2041 item->referenceObject();
2043 for (
int i = 0, c = cache.size(); i < c; ++i) {
2044 QQmlDelegateModelItem *item = cache.at(i);
2047 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
2050 if (item->modelIndex() != -1)
2051 item->setModelIndex(-1, -1, -1);
2054 for (QQmlDelegateModelItem *item : cache)
2055 item->releaseObject();
2056 QVector<Compositor::Remove> removes;
2057 QVector<Compositor::Insert> inserts;
2059 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
2061 d->m_compositor.listItemsInserted(&d->m_adaptorModel, 0, d->m_count, &inserts);
2062 d->itemsMoved(removes, inserts);
2065 if (d->m_adaptorModel.canFetchMore())
2066 d->m_adaptorModel.fetchMore();
2070 emit rootIndexChanged();
2073void QQmlDelegateModel::_q_rowsInserted(
const QModelIndex &parent,
int begin,
int end)
2075 Q_D(QQmlDelegateModel);
2076 if (parent == d->m_adaptorModel.rootIndex)
2077 _q_itemsInserted(begin, end - begin + 1);
2080void QQmlDelegateModel::_q_rowsAboutToBeRemoved(
const QModelIndex &parent,
int begin,
int end)
2082 Q_D(QQmlDelegateModel);
2083 if (!d->m_adaptorModel.rootIndex.isValid())
2085 const QModelIndex index = d->m_adaptorModel.rootIndex;
2086 if (index.parent() == parent && index.row() >= begin && index.row() <= end) {
2087 const int oldCount = d->m_count;
2089 d->disconnectFromAbstractItemModel();
2090 d->m_adaptorModel.invalidateModel();
2092 if (d->m_complete && oldCount > 0) {
2093 QVector<Compositor::Remove> removes;
2094 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
2095 d->itemsRemoved(removes);
2101void QQmlDelegateModel::_q_rowsRemoved(
const QModelIndex &parent,
int begin,
int end)
2103 Q_D(QQmlDelegateModel);
2104 if (parent == d->m_adaptorModel.rootIndex)
2105 _q_itemsRemoved(begin, end - begin + 1);
2108void QQmlDelegateModel::_q_rowsMoved(
2109 const QModelIndex &sourceParent,
int sourceStart,
int sourceEnd,
2110 const QModelIndex &destinationParent,
int destinationRow)
2112 Q_D(QQmlDelegateModel);
2113 const int count = sourceEnd - sourceStart + 1;
2114 if (destinationParent == d->m_adaptorModel.rootIndex && sourceParent == d->m_adaptorModel.rootIndex) {
2115 _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow - count, count);
2116 }
else if (sourceParent == d->m_adaptorModel.rootIndex) {
2117 _q_itemsRemoved(sourceStart, count);
2118 }
else if (destinationParent == d->m_adaptorModel.rootIndex) {
2119 _q_itemsInserted(destinationRow, count);
2123void QQmlDelegateModel::_q_columnsInserted(
const QModelIndex &parent,
int begin,
int end)
2125 Q_D(QQmlDelegateModel);
2127 if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
2129 _q_itemsChanged(0, d->m_count, QVector<
int>());
2133void QQmlDelegateModel::_q_columnsRemoved(
const QModelIndex &parent,
int begin,
int end)
2135 Q_D(QQmlDelegateModel);
2137 if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
2139 _q_itemsChanged(0, d->m_count, QVector<
int>());
2143void QQmlDelegateModel::_q_columnsMoved(
const QModelIndex &parent,
int start,
int end,
2144 const QModelIndex &destination,
int column)
2146 Q_D(QQmlDelegateModel);
2148 if ((parent == d->m_adaptorModel.rootIndex && start == 0)
2149 || (destination == d->m_adaptorModel.rootIndex && column == 0)) {
2151 _q_itemsChanged(0, d->m_count, QVector<
int>());
2155void QQmlDelegateModel::_q_dataChanged(
const QModelIndex &begin,
const QModelIndex &end,
const QVector<
int> &roles)
2157 Q_D(QQmlDelegateModel);
2158 if (begin.parent() == d->m_adaptorModel.rootIndex)
2159 _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, roles);
2162bool QQmlDelegateModel::isDescendantOf(
const QPersistentModelIndex& desc,
const QList< QPersistentModelIndex >& parents)
const
2164 for (
int i = 0, c = parents.size(); i < c; ++i) {
2165 for (QPersistentModelIndex parent = desc; parent.isValid(); parent = parent.parent()) {
2166 if (parent == parents[i])
2174void QQmlDelegateModel::_q_layoutChanged(
const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
2176 Q_D(QQmlDelegateModel);
2180 if (hint == QAbstractItemModel::VerticalSortHint) {
2181 if (!parents.isEmpty() && d->m_adaptorModel.rootIndex.isValid() && !isDescendantOf(d->m_adaptorModel.rootIndex, parents)) {
2186 _q_itemsChanged(0, d->m_count, QVector<
int>());
2188 }
else if (hint == QAbstractItemModel::HorizontalSortHint) {
2196QQmlDelegateModelAttached *QQmlDelegateModel::qmlAttachedProperties(QObject *obj)
2198 if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(obj))
2199 return new QQmlDelegateModelAttached(cacheItem, obj);
2200 return new QQmlDelegateModelAttached(obj);
2206 if (!m_context || !m_context->isValid())
2212 if (!object.isObject())
2215 QV4::ExecutionEngine *v4 = object.as<QV4::Object>()->engine();
2216 QV4::Scope scope(v4);
2217 QV4::ScopedObject o(scope, object);
2221 QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
2222 QV4::ScopedValue propertyName(scope);
2223 QV4::ScopedValue v(scope);
2224 const auto oldCache = m_cache;
2226 propertyName = it.nextPropertyNameAsString(v);
2227 if (propertyName->isNull())
2229 cacheItem->setValue(
2230 propertyName->toQStringNoThrow(),
2231 QV4::ExecutionEngine::toVariant(v, QMetaType {}));
2233 const bool cacheModified = !m_cache.isSharedWith(oldCache);
2237 cacheItem->groups = groups | Compositor::UnresolvedFlag | Compositor::CacheFlag;
2240 itemsInserted(QVector<Compositor::Insert>(1, Compositor::Insert(before, 1, cacheItem->groups & ~Compositor::CacheFlag)));
2242 m_cache.insert(before.cacheIndex(), cacheItem);
2243 m_compositor.insert(before,
nullptr, 0, 1, cacheItem->groups);
2250QQmlDelegateModelItemMetaType::QQmlDelegateModelItemMetaType(
2251 QV4::ExecutionEngine *engine, QQmlDelegateModel *model,
const QStringList &groupNames)
2254 , groupNames(groupNames)
2255 , modelKind(ModelKind::DelegateModel)
2259QQmlDelegateModelItemMetaType::QQmlDelegateModelItemMetaType(
2260 QV4::ExecutionEngine *engine, QQmlTableInstanceModel *model)
2263 , modelKind(ModelKind::TableInstanceModel)
2267QQmlDelegateModelItemMetaType::~QQmlDelegateModelItemMetaType() =
default;
2269void QQmlDelegateModelItemMetaType::emitModelChanged()
const
2271 switch (modelKind) {
2272 case ModelKind::InstanceModel:
2274 case ModelKind::DelegateModel:
2275 emit
static_cast<QQmlDelegateModel *>(model.data())->modelChanged();
2277 case ModelKind::TableInstanceModel:
2278 emit
static_cast<QQmlTableInstanceModel *>(model.data())->modelChanged();
2283void QQmlDelegateModelItemMetaType::initializeAttachedMetaObject()
2285 QMetaObjectBuilder builder;
2286 builder.setFlags(DynamicMetaObject);
2287 builder.setClassName(QQmlDelegateModelAttached::staticMetaObject.className());
2288 builder.setSuperClass(&QQmlDelegateModelAttached::staticMetaObject);
2291 for (qsizetype i = 0, end = groupCount(); i < end; ++i, ++notifierId) {
2292 QString propertyName = QLatin1String(
"in") + groupNames.at(i);
2293 propertyName.replace(2, 1, propertyName.at(2).toUpper());
2294 builder.addSignal(
"__" + propertyName.toUtf8() +
"Changed()");
2295 QMetaPropertyBuilder propertyBuilder = builder.addProperty(
2296 propertyName.toUtf8(),
"bool", notifierId);
2297 propertyBuilder.setWritable(
true);
2299 for (qsizetype i = 0, end = groupCount(); i < end; ++i, ++notifierId) {
2300 const QString propertyName = groupNames.at(i) + QLatin1String(
"Index");
2301 builder.addSignal(
"__" + propertyName.toUtf8() +
"Changed()");
2302 QMetaPropertyBuilder propertyBuilder = builder.addProperty(
2303 propertyName.toUtf8(),
"int", notifierId);
2304 propertyBuilder.setWritable(
true);
2307 attachedMetaObject = QQml::makeRefPointer<QQmlDelegateModelAttachedMetaObject>(
2308 this, builder.toMetaObject());
2311void QQmlDelegateModelItemMetaType::initializePrototype()
2313 QV4::Scope scope(v4Engine);
2315 QV4::ScopedObject proto(scope, v4Engine->newObject());
2316 proto->defineAccessorProperty(QStringLiteral(
"model"), QQmlDelegateModelItem::get_model,
nullptr);
2317 proto->defineAccessorProperty(QStringLiteral(
"groups"), QQmlDelegateModelItem::get_groups, QQmlDelegateModelItem::set_groups);
2318 QV4::ScopedString s(scope);
2319 QV4::ScopedProperty p(scope);
2321 s = v4Engine->newString(QStringLiteral(
"isUnresolved"));
2322 QV4::ScopedFunctionObject f(scope);
2323 QV4::ExecutionEngine *engine = scope.engine;
2324 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, 30, QQmlDelegateModelItem::get_member)));
2325 p->setSetter(
nullptr);
2326 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2328 s = v4Engine->newString(QStringLiteral(
"inItems"));
2329 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)));
2330 p->setSetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)));
2331 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2333 s = v4Engine->newString(QStringLiteral(
"inPersistedItems"));
2334 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)));
2335 p->setSetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)));
2336 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2338 s = v4Engine->newString(QStringLiteral(
"itemsIndex"));
2339 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)));
2340 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2342 s = v4Engine->newString(QStringLiteral(
"persistedItemsIndex"));
2343 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)));
2344 p->setSetter(
nullptr);
2345 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2347 for (qsizetype i = 2, end = groupCount(); i < end; ++i) {
2348 QString propertyName = QLatin1String(
"in") + groupNames.at(i);
2349 propertyName.replace(2, 1, propertyName.at(2).toUpper());
2350 s = v4Engine->newString(propertyName);
2351 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, i + 1, QQmlDelegateModelItem::get_member)));
2352 p->setSetter((f = QV4::DelegateModelGroupFunction::create(engine, i + 1, QQmlDelegateModelItem::set_member)));
2353 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2355 for (qsizetype i = 2, end = groupCount(); i < end; ++i) {
2356 const QString propertyName = groupNames.at(i) + QLatin1String(
"Index");
2357 s = v4Engine->newString(propertyName);
2358 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, i + 1, QQmlDelegateModelItem::get_index)));
2359 p->setSetter(
nullptr);
2360 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2362 modelItemProto.set(v4Engine, proto);
2365int QQmlDelegateModelItemMetaType::parseGroups(
const QStringList &groups)
const
2368 for (
const QString &groupName : groups) {
2369 int index = groupNames.indexOf(groupName);
2371 groupFlags |= 2 << index;
2376int QQmlDelegateModelItemMetaType::parseGroups(
const QV4::Value &groups)
const
2379 QV4::Scope scope(v4Engine);
2381 QV4::ScopedString s(scope, groups);
2383 const QString groupName = s->toQString();
2384 int index = groupNames.indexOf(groupName);
2386 groupFlags |= 2 << index;
2390 QV4::ScopedArrayObject array(scope, groups);
2392 QV4::ScopedValue v(scope);
2393 uint arrayLength = array->getLength();
2394 for (uint i = 0; i < arrayLength; ++i) {
2396 const QString groupName = v->toQString();
2397 int index = groupNames.indexOf(groupName);
2399 groupFlags |= 2 << index;
2405QV4::ReturnedValue
QQmlDelegateModelItem::get_model(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *,
int)
2407 QV4::Scope scope(b);
2408 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
2410 return b->engine()->throwTypeError(QStringLiteral(
"Not a valid DelegateModel object"));
2411 if (!o->d()->item->metaType->model)
2414 return o->d()->item->get();
2417QV4::ReturnedValue
QQmlDelegateModelItem::get_groups(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *,
int)
2419 QV4::Scope scope(b);
2420 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
2422 return scope.engine->throwTypeError(QStringLiteral(
"Not a valid DelegateModel object"));
2426 const auto &metaType = item->metaType;
2427 for (qsizetype i = 0, end = metaType->groupCount(); i < end; ++i) {
2428 if (item->groups & (1 << (i + 1)))
2429 groups.append(metaType->groupNames.at(i));
2432 return scope.engine->fromVariant(groups);
2435QV4::ReturnedValue
QQmlDelegateModelItem::set_groups(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
2437 QV4::Scope scope(b);
2438 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
2440 return scope.engine->throwTypeError(QStringLiteral(
"Not a valid DelegateModel object"));
2445 QQmlDelegateModel *delegateModel = o->d()->item->metaType->delegateModel();
2450 const int groupFlags = model->m_cacheMetaType->parseGroups(argv[0]);
2451 const int cacheIndex = model->m_cache.indexOf(o->d()->item);
2452 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2453 model->setGroups(it, 1, Compositor::Cache, groupFlags);
2454 return QV4::Encode::undefined();
2459 return QV4::Encode(
bool(thisItem->groups & (1 << flag)));
2464 bool member = arg.toBoolean();
2465 uint groupFlag = (1 << flag);
2466 if (member == ((cacheItem->groups & groupFlag) != 0))
2467 return QV4::Encode::undefined();
2469 QQmlDelegateModel *delegateModel = cacheItem->metaType->delegateModel();
2471 return QV4::Encode::undefined();
2474 const int cacheIndex = model->m_cache.indexOf(cacheItem);
2475 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2477 model->addGroups(it, 1, Compositor::Cache, groupFlag);
2479 model->removeGroups(it, 1, Compositor::Cache, groupFlag);
2480 return QV4::Encode::undefined();
2485 return QV4::Encode((
int)thisItem->groupIndex(Compositor::Group(flag)));
2493 for (QQmlRefPointer<QQmlContextData> ctxt = contextData->childContexts(); ctxt;
2494 ctxt = ctxt->nextChild()) {
2495 ctxt->deepClearContextObject(childContextObject);
2512 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
2513 QQmlAdaptorModel::Accessors *accessor,
2514 int modelIndex,
int row,
int column)
2515 : metaType(metaType)
2520 if (accessor->propertyCache) {
2528 QQmlData::get(
this,
true)->propertyCache = accessor->propertyCache;
2539 if (QQmlDelegateModel *delegateModel = metaType->delegateModel())
2540 QQmlDelegateModelPrivate::get(delegateModel)->releaseIncubator(incubationTask);
2552 if (QQmlDelegateModel *delegateModel = metaType->delegateModel())
2553 QQmlDelegateModelPrivate::get(delegateModel)->removeCacheItem(
this);
2560 const int prevIndex = index;
2561 const int prevRow = row;
2562 const int prevColumn = column;
2568 if (idx != prevIndex || alwaysEmit)
2569 emit modelIndexChanged();
2570 if (row != prevRow || alwaysEmit)
2572 if (column != prevColumn || alwaysEmit)
2573 emit columnChanged();
2579 Q_ASSERT(contextData);
2581 QQmlData *data = QQmlData::get(object);
2583 if (data->ownContext) {
2584 data->ownContext->clearContext();
2585 data->ownContext->deepClearContextObject(object);
2586 data->ownContext.reset();
2587 data->context =
nullptr;
2590
2591
2592
2593
2594
2595
2596 if (Q_UNLIKELY(
static_cast<QCoreApplicationPrivate *>(QCoreApplicationPrivate::get(QCoreApplication::instance()))->aboutToQuitEmitted)) {
2597 if (object->parent() ==
nullptr)
2598 object->setParent(QCoreApplication::instance());
2600 object->deleteLater();
2605 contextData.reset();
2611 QQmlData *d = QQmlData::get(object);
2615 QQmlRefPointer<QQmlContextData> context = d->context;
2616 if (!context || !context->isValid())
2619 if (QObject *extraObject = context->extraObject())
2620 return qobject_cast<QQmlDelegateModelItem *>(extraObject);
2622 for (context = context->parent(); context; context = context->parent()) {
2623 if (QObject *extraObject = context->extraObject())
2624 return qobject_cast<QQmlDelegateModelItem *>(extraObject);
2626 context->contextObject())) {
2635 if (QQmlDelegateModel *delegateModel = metaType->delegateModel()) {
2637 return model->m_compositor.find(Compositor::Cache, model->m_cache.indexOf(
this)).index[group];
2645 QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject)
2655 *
static_cast<QMetaObject *>(
this) = *metaObject;
2668int QQmlDelegateModelAttachedMetaObject::
metaCall(QObject *object, QMetaObject::Call call,
int _id,
void **arguments)
2671 if (call == QMetaObject::ReadProperty) {
2672 if (_id >= indexPropertyOffset) {
2673 Compositor::Group group = Compositor::Group(_id - indexPropertyOffset + 1);
2674 *
static_cast<
int *>(arguments[0]) = attached->m_currentIndex[group];
2676 }
else if (_id >= memberPropertyOffset) {
2677 Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
2681 }
else if (call == QMetaObject::WriteProperty) {
2682 if (_id >= memberPropertyOffset) {
2683 QQmlDelegateModel *delegateModel = metaType->delegateModel();
2687 Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
2688 const int groupFlag = 1 << group;
2690 if (member && !*
static_cast<
bool *>(arguments[0])) {
2691 Compositor::iterator it = model->m_compositor.find(
2692 group, attached->m_currentIndex[group]);
2693 model->removeGroups(it, 1, group, groupFlag);
2694 }
else if (!member && *
static_cast<
bool *>(arguments[0])) {
2695 for (qsizetype i = 1, end = metaType->groupCount(); i <= end; ++i) {
2696 if (attached->m_cacheItem->groups & (1 << i)) {
2697 Compositor::iterator it = model->m_compositor.find(
2698 Compositor::Group(i), attached->m_currentIndex[i]);
2699 model->addGroups(it, 1, Compositor::Group(i), groupFlag);
2707 return attached->qt_metacall(call, _id, arguments);
2714 QQml_setParent_noEvent(
this, parent);
2722 QQml_setParent_noEvent(
this, parent);
2725 std::copy(std::begin(m_currentIndex), std::end(m_currentIndex), std::begin(m_previousIndex));
2727 if (!cacheItem->metaType->attachedMetaObject)
2728 cacheItem->metaType->initializeAttachedMetaObject();
2730 QObjectPrivate::get(
this)->metaObject = cacheItem->metaType->attachedMetaObject.data();
2731 cacheItem->metaType->attachedMetaObject->addref();
2740 for (qsizetype i = 1, end = metaType->groupCount(); i <= end; ++i)
2741 m_currentIndex[i] = incubationTask->index[i];
2742 }
else if (QQmlDelegateModel *delegateModel = metaType->delegateModel()) {
2744 Compositor::iterator it = model->m_compositor.find(
2745 Compositor::Cache, model->m_cache.indexOf(m_cacheItem));
2746 for (qsizetype i = 1, end = metaType->groupCount(); i <= end; ++i)
2747 m_currentIndex[i] = it.index[i];
2753 setInGroup(QQmlListCompositor::Persisted, inPersisted);
2760 const uint groupFlag = (1 << QQmlListCompositor::Persisted);
2768 return m_cacheItem->groupIndex(QQmlListCompositor::Persisted);
2776 QQmlDelegateModel *delegateModel = m_cacheItem->metaType->delegateModel();
2781 const uint groupFlag = (1 << group);
2785 const int cacheIndex = model->m_cache.indexOf(
m_cacheItem);
2786 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2788 model->addGroups(it, 1, Compositor::Cache, groupFlag);
2790 model->removeGroups(it, 1, Compositor::Cache, groupFlag);
2796 setInGroup(QQmlListCompositor::Default, inItems);
2803 const uint groupFlag = (1 << QQmlListCompositor::Default);
2811 return m_cacheItem->groupIndex(QQmlListCompositor::Default);
2815
2816
2817
2818
2819
2820
2828
2829
2830
2831
2832
2833
2842 for (qsizetype i = 0, end = metaType->groupCount(); i < end; ++i) {
2843 if (m_cacheItem->groups & (1 << (i + 1)))
2844 groups.append(metaType->groupNames.at(i));
2854 QQmlDelegateModel *delegateModel = m_cacheItem->metaType->delegateModel();
2859 const int groupFlags = model->m_cacheMetaType->parseGroups(groups);
2860 const int cacheIndex = model->m_cache.indexOf(
m_cacheItem);
2861 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2862 model->setGroups(it, 1, Compositor::Cache, groupFlags);
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2882 return m_cacheItem->groups & Compositor::UnresolvedFlag;
2886
2887
2888
2889
2890
2891
2892
2893
2894
2897
2898
2899
2900
2901
2902
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2918
2919
2920
2921
2922
2923
2930 int indexChanges = 0;
2931 const qsizetype groupCount =
m_cacheItem->metaType->groupCount();
2932 for (qsizetype i = 1; i <= groupCount; ++i) {
2933 if (m_previousIndex[i] != m_currentIndex[i]) {
2934 m_previousIndex[i] = m_currentIndex[i];
2935 indexChanges |= (1 << i);
2943 const QMetaObject *meta = metaObject();
2944 for (qsizetype i = 1; i <= groupCount; ++i, ++notifierId) {
2945 if (groupChanges & (1 << i))
2946 QMetaObject::activate(
this, meta, notifierId,
nullptr);
2948 for (qsizetype i = 1; i <= groupCount; ++i, ++notifierId) {
2949 if (indexChanges & (1 << i))
2950 QMetaObject::activate(
this, meta, notifierId,
nullptr);
2954 emit groupsChanged();
2968 Q_Q(QQmlDelegateModelGroup);
2969 IS_SIGNAL_CONNECTED(q, QQmlDelegateModelGroup, changed, (
const QJSValue &,
const QJSValue &));
2974 Q_Q(QQmlDelegateModelGroup);
2975 if (isChangedConnected() && !changeSet.isEmpty()) {
2976 emit q->changed(QJSValuePrivate::fromReturnedValue(
2977 qdmEngineData(v4)->array(v4, changeSet.removes())),
2978 QJSValuePrivate::fromReturnedValue(
2979 qdmEngineData(v4)->array(v4, changeSet.inserts())));
2981 if (changeSet.difference() != 0)
2982 emit q->countChanged();
2987 for (QQmlDelegateModelGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
2988 it->emitModelUpdated(changeSet, reset);
2997 it->createdPackage(index, package);
3003 it->initPackage(index, package);
3009 it->destroyingPackage(package);
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048QQmlDelegateModelGroup::QQmlDelegateModelGroup(QObject *parent)
3049 : QObject(*
new QQmlDelegateModelGroupPrivate, parent)
3053QQmlDelegateModelGroup::QQmlDelegateModelGroup(
3054 const QString &name, QQmlDelegateModel *model,
int index, QObject *parent)
3055 : QQmlDelegateModelGroup(parent)
3057 Q_D(QQmlDelegateModelGroup);
3059 d->setModel(model, Compositor::Group(index));
3062QQmlDelegateModelGroup::~QQmlDelegateModelGroup() =
default;
3065
3066
3067
3068
3069
3070
3072QString QQmlDelegateModelGroup::name()
const
3074 Q_D(
const QQmlDelegateModelGroup);
3078void QQmlDelegateModelGroup::setName(
const QString &name)
3080 Q_D(QQmlDelegateModelGroup);
3083 if (d->name != name) {
3090
3091
3092
3093
3095int QQmlDelegateModelGroup::count()
const
3097 Q_D(
const QQmlDelegateModelGroup);
3100 return QQmlDelegateModelPrivate::get(d->model)->m_compositor.count(d->group);
3104
3105
3106
3107
3109bool QQmlDelegateModelGroup::defaultInclude()
const
3111 Q_D(
const QQmlDelegateModelGroup);
3112 return d->defaultInclude;
3115void QQmlDelegateModelGroup::setDefaultInclude(
bool include)
3117 Q_D(QQmlDelegateModelGroup);
3118 if (d->defaultInclude != include) {
3119 d->defaultInclude = include;
3123 QQmlDelegateModelPrivate::get(d->model)->m_compositor.setDefaultGroup(d->group);
3125 QQmlDelegateModelPrivate::get(d->model)->m_compositor.clearDefaultGroup(d->group);
3127 emit defaultIncludeChanged();
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3155QJSValue QQmlDelegateModelGroup::get(
int index)
3157 Q_D(QQmlDelegateModelGroup);
3161 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3162 if (!model->m_context || !model->m_context->isValid()) {
3164 }
else if (index < 0 || index >= model->m_compositor.count(d->group)) {
3165 qmlWarning(
this) << tr(
"get: index out of range");
3169 Compositor::iterator it = model->m_compositor.find(d->group, index);
3170 QQmlDelegateModelItem *cacheItem = it->inCache()
3171 ? model->m_cache.at(it.cacheIndex())
3175 cacheItem = model->m_adaptorModel.createItem(
3176 model->m_cacheMetaType, it.modelIndex());
3179 cacheItem->groups = it->flags;
3181 model->m_cache.insert(it.cacheIndex(), cacheItem);
3182 model->m_compositor.setFlags(it, 1, Compositor::CacheFlag);
3185 if (model->m_cacheMetaType->modelItemProto.isUndefined())
3186 model->m_cacheMetaType->initializePrototype();
3187 QV4::ExecutionEngine *v4 = model->m_cacheMetaType->v4Engine;
3188 QV4::Scope scope(v4);
3189 ++cacheItem->scriptRef;
3190 QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(cacheItem));
3191 QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
3192 o->setPrototypeOf(p);
3194 return QJSValuePrivate::fromReturnedValue(o->asReturnedValue());
3199 if (value.isNumber()) {
3200 *index = value.toInt32();
3204 if (!value.isObject())
3207 QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine();
3208 QV4::Scope scope(v4);
3209 QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
3213 if (QQmlDelegateModel *delegateModel = cacheItem->metaType->delegateModel()) {
3214 *index = QQmlDelegateModelPrivate::get(delegateModel)->m_cache.indexOf(cacheItem);
3215 *group = Compositor::Cache;
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3239void QQmlDelegateModelGroup::insert(QQmlV4FunctionPtr args)
3241 Q_D(QQmlDelegateModelGroup);
3242 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3244 int index = model->m_compositor.count(d->group);
3245 Compositor::Group group = d->group;
3247 if (args->length() == 0)
3251 QV4::Scope scope(args->v4engine());
3252 QV4::ScopedValue v(scope, (*args)[i]);
3253 if (d->parseIndex(v, &index, &group)) {
3254 if (index < 0 || index > model->m_compositor.count(group)) {
3255 qmlWarning(
this) << tr(
"insert: index out of range");
3258 if (++i == args->length())
3263 if (v->as<QV4::ArrayObject>())
3266 int groups = 1 << d->group;
3267 if (++i < args->length()) {
3268 QV4::ScopedValue val(scope, (*args)[i]);
3269 groups |= model->m_cacheMetaType->parseGroups(val);
3272 if (v->as<QV4::Object>()) {
3273 auto insertionResult = QQmlDelegateModelPrivate::InsertionResult::Retry;
3275 Compositor::insert_iterator before = index < model->m_compositor.count(group)
3276 ? model->m_compositor.findInsertPosition(group, index)
3277 : model->m_compositor.end();
3278 insertionResult = model->insert(before, v, groups);
3279 }
while (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Retry);
3280 if (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Success)
3281 model->emitChanges();
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3302void QQmlDelegateModelGroup::create(QQmlV4FunctionPtr args)
3304 Q_D(QQmlDelegateModelGroup);
3308 if (args->length() == 0)
3311 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3313 int index = model->m_compositor.count(d->group);
3314 Compositor::Group group = d->group;
3317 QV4::Scope scope(args->v4engine());
3318 QV4::ScopedValue v(scope, (*args)[i]);
3319 if (d->parseIndex(v, &index, &group))
3322 if (i < args->length() && index >= 0 && index <= model->m_compositor.count(group)) {
3324 if (v->as<QV4::Object>()) {
3325 int groups = 1 << d->group;
3326 if (++i < args->length()) {
3327 QV4::ScopedValue val(scope, (*args)[i]);
3328 groups |= model->m_cacheMetaType->parseGroups(val);
3331 auto insertionResult = QQmlDelegateModelPrivate::InsertionResult::Retry;
3333 Compositor::insert_iterator before = index < model->m_compositor.count(group)
3334 ? model->m_compositor.findInsertPosition(group, index)
3335 : model->m_compositor.end();
3337 index = before.index[d->group];
3340 insertionResult = model->insert(before, v, groups);
3341 }
while (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Retry);
3342 if (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Error)
3346 if (index < 0 || index >= model->m_compositor.count(group)) {
3347 qmlWarning(
this) << tr(
"create: index out of range");
3351 QObject *object = model->object(group, index, QQmlIncubator::AsynchronousIfNested);
3353 QVector<Compositor::Insert> inserts;
3354 Compositor::iterator it = model->m_compositor.find(group, index);
3355 model->m_compositor.setFlags(it, 1, d->group, Compositor::PersistedFlag, &inserts);
3356 model->itemsInserted(inserts);
3357 model->m_cache.at(it.cacheIndex())->releaseObject();
3360 args->setReturnValue(QV4::QObjectWrapper::wrap(args->v4engine(), object));
3361 model->emitChanges();
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380void QQmlDelegateModelGroup::resolve(QQmlV4FunctionPtr args)
3382 Q_D(QQmlDelegateModelGroup);
3386 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3388 if (args->length() < 2)
3393 Compositor::Group fromGroup = d->group;
3394 Compositor::Group toGroup = d->group;
3396 QV4::Scope scope(args->v4engine());
3397 QV4::ScopedValue v(scope, (*args)[0]);
3398 if (d->parseIndex(v, &from, &fromGroup)) {
3399 if (from < 0 || from >= model->m_compositor.count(fromGroup)) {
3400 qmlWarning(
this) << tr(
"resolve: from index out of range");
3404 qmlWarning(
this) << tr(
"resolve: from index invalid");
3409 if (d->parseIndex(v, &to, &toGroup)) {
3410 if (to < 0 || to >= model->m_compositor.count(toGroup)) {
3411 qmlWarning(
this) << tr(
"resolve: to index out of range");
3415 qmlWarning(
this) << tr(
"resolve: to index invalid");
3419 Compositor::iterator fromIt = model->m_compositor.find(fromGroup, from);
3420 Compositor::iterator toIt = model->m_compositor.find(toGroup, to);
3422 if (!fromIt->isUnresolved()) {
3423 qmlWarning(
this) << tr(
"resolve: from is not an unresolved item");
3427 qmlWarning(
this) << tr(
"resolve: to is not a model item");
3431 const int unresolvedFlags = fromIt->flags;
3432 const int resolvedFlags = toIt->flags;
3433 const int resolvedIndex = toIt.modelIndex();
3434 void *
const resolvedList = toIt->list;
3436 QQmlDelegateModelItem *cacheItem = model->m_cache.at(fromIt.cacheIndex());
3437 cacheItem->groups &= ~Compositor::UnresolvedFlag;
3439 if (toIt.cacheIndex() > fromIt.cacheIndex())
3440 toIt.decrementIndexes(1, unresolvedFlags);
3441 if (!toIt->inGroup(fromGroup) || toIt.index[fromGroup] > from)
3445 QVector<Compositor::Remove>(1, Compositor::Remove(fromIt, 1, unresolvedFlags, 0)),
3446 QVector<Compositor::Insert>(1, Compositor::Insert(toIt, 1, unresolvedFlags, 0)));
3447 model->itemsInserted(
3448 QVector<Compositor::Insert>(1, Compositor::Insert(toIt, 1, (resolvedFlags & ~unresolvedFlags) | Compositor::CacheFlag)));
3449 toIt.incrementIndexes(1, resolvedFlags | unresolvedFlags);
3450 model->itemsRemoved(QVector<Compositor::Remove>(1, Compositor::Remove(toIt, 1, resolvedFlags)));
3452 model->m_compositor.setFlags(toGroup, to, 1, unresolvedFlags & ~Compositor::UnresolvedFlag);
3453 model->m_compositor.clearFlags(fromGroup, from, 1, unresolvedFlags);
3455 if (resolvedFlags & Compositor::CacheFlag)
3456 model->m_compositor.insert(
3457 Compositor::Cache, toIt.cacheIndex(), resolvedList,
3458 resolvedIndex, 1, Compositor::CacheFlag);
3460 Q_ASSERT(model->m_cache.size() == model->m_compositor.count(Compositor::Cache));
3462 if (!cacheItem->isReferenced()) {
3463 Q_ASSERT(toIt.cacheIndex() == model->m_cache.indexOf(cacheItem));
3464 model->m_cache.removeAt(toIt.cacheIndex());
3465 model->m_compositor.clearFlags(
3466 Compositor::Cache, toIt.cacheIndex(), 1, Compositor::CacheFlag);
3468 Q_ASSERT(model->m_cache.size() == model->m_compositor.count(Compositor::Cache));
3470 cacheItem->resolveIndex(model->m_adaptorModel, resolvedIndex);
3471 if (QQmlDelegateModelAttached *attached = cacheItem->attached())
3472 attached->emitUnresolvedChanged();
3475 model->emitChanges();
3479
3480
3481
3482
3484void QQmlDelegateModelGroup::remove(QQmlV4FunctionPtr args)
3486 Q_D(QQmlDelegateModelGroup);
3489 Compositor::Group group = d->group;
3493 if (args->length() == 0)
3497 QV4::Scope scope(args->v4engine());
3498 QV4::ScopedValue v(scope, (*args)[0]);
3499 if (!d->parseIndex(v, &index, &group)) {
3500 qmlWarning(
this) << tr(
"remove: invalid index");
3504 if (++i < args->length()) {
3507 count = v->toInt32();
3510 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3511 if (index < 0 || index >= model->m_compositor.count(group)) {
3512 qmlWarning(
this) << tr(
"remove: index out of range");
3513 }
else if (count != 0) {
3514 Compositor::iterator it = model->m_compositor.find(group, index);
3515 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3516 qmlWarning(
this) << tr(
"remove: invalid count");
3518 model->removeGroups(it, count, d->group, 1 << d->group);
3524 QQmlV4FunctionPtr args, Compositor::Group *group,
int *index,
int *count,
int *groups)
const
3526 if (!model || !QQmlDelegateModelPrivate::get(model)->m_cacheMetaType)
3529 if (args->length() < 2)
3533 QV4::Scope scope(args->v4engine());
3534 QV4::ScopedValue v(scope, (*args)[i]);
3535 if (!parseIndex(v, index, group))
3539 if (v->isNumber()) {
3540 *count = v->toInt32();
3542 if (++i == args->length())
3547 *groups = QQmlDelegateModelPrivate::get(model)->m_cacheMetaType->parseGroups(v);
3553
3554
3555
3556
3558void QQmlDelegateModelGroup::addGroups(QQmlV4FunctionPtr args)
3560 Q_D(QQmlDelegateModelGroup);
3561 Compositor::Group group = d->group;
3566 if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
3569 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3570 if (index < 0 || index >= model->m_compositor.count(group)) {
3571 qmlWarning(
this) << tr(
"addGroups: index out of range");
3572 }
else if (count != 0) {
3573 Compositor::iterator it = model->m_compositor.find(group, index);
3574 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3575 qmlWarning(
this) << tr(
"addGroups: invalid count");
3577 model->addGroups(it, count, d->group, groups);
3583
3584
3585
3586
3588void QQmlDelegateModelGroup::removeGroups(QQmlV4FunctionPtr args)
3590 Q_D(QQmlDelegateModelGroup);
3591 Compositor::Group group = d->group;
3596 if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
3599 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3600 if (index < 0 || index >= model->m_compositor.count(group)) {
3601 qmlWarning(
this) << tr(
"removeGroups: index out of range");
3602 }
else if (count != 0) {
3603 Compositor::iterator it = model->m_compositor.find(group, index);
3604 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3605 qmlWarning(
this) << tr(
"removeGroups: invalid count");
3607 model->removeGroups(it, count, d->group, groups);
3613
3614
3615
3616
3617
3619void QQmlDelegateModelGroup::setGroups(QQmlV4FunctionPtr args)
3621 Q_D(QQmlDelegateModelGroup);
3622 Compositor::Group group = d->group;
3627 if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
3630 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3631 if (index < 0 || index >= model->m_compositor.count(group)) {
3632 qmlWarning(
this) << tr(
"setGroups: index out of range");
3633 }
else if (count != 0) {
3634 Compositor::iterator it = model->m_compositor.find(group, index);
3635 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3636 qmlWarning(
this) << tr(
"setGroups: invalid count");
3638 model->setGroups(it, count, d->group, groups);
3644
3645
3646
3647
3648
3649
3650
3651
3652
3654void QQmlDelegateModelGroup::move(QQmlV4FunctionPtr args)
3656 Q_D(QQmlDelegateModelGroup);
3658 if (args->length() < 2)
3661 Compositor::Group fromGroup = d->group;
3662 Compositor::Group toGroup = d->group;
3667 QV4::Scope scope(args->v4engine());
3668 QV4::ScopedValue v(scope, (*args)[0]);
3669 if (!d->parseIndex(v, &from, &fromGroup)) {
3670 qmlWarning(
this) << tr(
"move: invalid from index");
3675 if (!d->parseIndex(v, &to, &toGroup)) {
3676 qmlWarning(
this) << tr(
"move: invalid to index");
3680 if (args->length() > 2) {
3683 count = v->toInt32();
3686 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3689 qmlWarning(
this) << tr(
"move: invalid count");
3690 }
else if (from < 0 || from + count > model->m_compositor.count(fromGroup)) {
3691 qmlWarning(
this) << tr(
"move: from index out of range");
3692 }
else if (!model->m_compositor.verifyMoveTo(fromGroup, from, toGroup, to, count, d->group)) {
3693 qmlWarning(
this) << tr(
"move: to index out of range");
3694 }
else if (count > 0) {
3695 QVector<Compositor::Remove> removes;
3696 QVector<Compositor::Insert> inserts;
3698 model->m_compositor.move(fromGroup, from, toGroup, to, count, d->group, &removes, &inserts);
3699 model->itemsMoved(removes, inserts);
3700 model->emitChanges();
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3719QQmlPartsModel::QQmlPartsModel(QQmlDelegateModel *model,
const QString &part, QObject *parent)
3720 : QQmlInstanceModel(*
new QObjectPrivate, parent)
3723 , m_compositorGroup(Compositor::Cache)
3724 , m_inheritGroup(
true)
3727 if (d->m_cacheMetaType) {
3728 QQmlDelegateModelGroupPrivate::get(d->m_groups[1])->emitters.insert(
this);
3729 m_compositorGroup = Compositor::Default;
3742 return m_model->filterGroup();
3743 return m_filterGroup;
3748 if (QQmlDelegateModelPrivate::get(m_model)->m_transaction) {
3749 qmlWarning(
this) << tr(
"The group of a DelegateModel cannot be changed within onChanged");
3753 if (m_filterGroup != group || m_inheritGroup) {
3754 m_filterGroup = group;
3755 m_inheritGroup =
false;
3758 emit filterGroupChanged();
3764 if (!m_inheritGroup) {
3765 m_inheritGroup =
true;
3767 emit filterGroupChanged();
3774 if (!model->m_cacheMetaType)
3777 if (m_inheritGroup) {
3778 if (m_filterGroup == model->m_filterGroup)
3780 m_filterGroup = model->m_filterGroup;
3783 QQmlListCompositor::Group previousGroup = m_compositorGroup;
3784 m_compositorGroup = Compositor::Default;
3785 QQmlDelegateModelGroupPrivate::get(model->m_groups[Compositor::Default])->emitters.insert(
this);
3787 if (m_filterGroup == model->m_cacheMetaType->groupNames.at(i - 1)) {
3788 m_compositorGroup = Compositor::Group(i);
3793 QQmlDelegateModelGroupPrivate::get(model->m_groups[m_compositorGroup])->emitters.insert(
this);
3794 if (m_compositorGroup != previousGroup) {
3795 QVector<QQmlChangeSet::Change> removes;
3796 QVector<QQmlChangeSet::Change> inserts;
3797 model->m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
3799 QQmlChangeSet changeSet;
3800 changeSet.move(removes, inserts);
3801 if (!changeSet.isEmpty())
3802 emit modelUpdated(changeSet,
false);
3804 if (changeSet.difference() != 0)
3805 emit countChanged();
3810 Compositor::Group group,
const QQmlChangeSet &changeSet)
3812 if (!m_inheritGroup)
3815 m_compositorGroup = group;
3816 QQmlDelegateModelGroupPrivate::get(QQmlDelegateModelPrivate::get(m_model)->m_groups[m_compositorGroup])->emitters.insert(
this);
3818 if (!changeSet.isEmpty())
3819 emit modelUpdated(changeSet,
false);
3821 if (changeSet.difference() != 0)
3822 emit countChanged();
3824 emit filterGroupChanged();
3830 return model->m_delegate
3831 ? model->m_compositor.count(m_compositorGroup)
3837 return m_model->isValid();
3844 if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup)) {
3845 qWarning() <<
"DelegateModel::item: index out range" << index << model->m_compositor.count(m_compositorGroup);
3849 QObject *object = model->object(m_compositorGroup, index, incubationMode);
3851 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) {
3852 QObject *part = package->part(m_part);
3855 m_packaged.insert(part, package);
3859 model->release(object);
3862 qmlWarning(model->m_delegate) << tr(
"Delegate component must be Package type.");
3871 QQmlInstanceModel::ReleaseFlags flags;
3873 auto it = m_packaged.find(item);
3874 if (it != m_packaged.end()) {
3875 QQuickPackage *package = *it;
3877 flags = model->release(package);
3878 m_packaged.erase(it);
3879 if (!m_packaged.contains(item))
3880 flags &= ~Referenced;
3881 if (flags & Destroyed)
3882 QQmlDelegateModelPrivate::get(m_model)->emitDestroyingPackage(package);
3889 return QQmlDelegateModelPrivate::get(m_model)->variantValue(m_compositorGroup, index, role);
3895 model->m_adaptorModel.replaceWatchedRoles(m_watchedRoles, roles);
3896 m_watchedRoles = roles;
3902 Compositor::iterator it = model->m_compositor.find(model->m_compositorGroup, index);
3904 return QQmlIncubator::Null;
3906 if (
auto incubationTask = model->m_cache.at(it.cacheIndex())->incubationTask)
3907 return incubationTask->status();
3909 return QQmlIncubator::Ready;
3914 auto it = m_packaged.find(item);
3915 if (it != m_packaged.end()) {
3916 if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(*it))
3917 return cacheItem->groupIndex(m_compositorGroup);
3924 emit createdItem(index, package->part(m_part));
3929 if (m_modelUpdatePending)
3930 m_pendingPackageInitializations << index;
3932 emit initItem(index, package->part(m_part));
3937 QObject *item = package->part(m_part);
3938 Q_ASSERT(!m_packaged.contains(item));
3939 emit destroyingItem(item);
3944 m_modelUpdatePending =
false;
3945 emit modelUpdated(changeSet, reset);
3946 if (changeSet.difference() != 0)
3947 emit countChanged();
3950 QVector<
int> pendingPackageInitializations;
3951 qSwap(pendingPackageInitializations, m_pendingPackageInitializations);
3952 for (
int index : pendingPackageInitializations) {
3953 if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup))
3955 QObject *object = model->object(m_compositorGroup, index, QQmlIncubator::Asynchronous);
3956 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
3957 emit initItem(index, package->part(m_part));
3958 model->release(object);
3965 if (Q_UNLIKELY(m_reusableItemsPool.size() == QQmlReusableDelegateModelItemsPool::MaxSize))
3968 Q_ASSERT(m_reusableItemsPool.size() < QQmlReusableDelegateModelItemsPool::MaxSize);
4014 Q_ASSERT(modelItem->object);
4015 Q_ASSERT(modelItem->delegate);
4017 m_reusableItemsPool.push_back({modelItem, 0});
4019 qCDebug(lcItemViewDelegateRecycling)
4020 <<
"item:" << modelItem
4021 <<
"delegate:" << modelItem->delegate
4022 <<
"index:" << modelItem->modelIndex()
4023 <<
"row:" << modelItem->modelRow()
4024 <<
"column:" << modelItem->modelColumn()
4025 <<
"pool size:" << m_reusableItemsPool.size();
4034 for (
auto it = m_reusableItemsPool.cbegin(); it != m_reusableItemsPool.cend(); ++it) {
4036 if (modelItem->delegate != delegate)
4038 m_reusableItemsPool.erase(it);
4040 qCDebug(lcItemViewDelegateRecycling)
4041 <<
"item:" << modelItem
4042 <<
"delegate:" << delegate
4043 <<
"old index:" << modelItem->modelIndex()
4044 <<
"old row:" << modelItem->modelRow()
4045 <<
"old column:" << modelItem->modelColumn()
4046 <<
"new index:" << newIndexHint
4047 <<
"pool size:" << m_reusableItemsPool.size();
4052 qCDebug(lcItemViewDelegateRecycling)
4053 <<
"no available item for delegate:" << delegate
4054 <<
"new index:" << newIndexHint
4055 <<
"pool size:" << m_reusableItemsPool.size();
4068 qCDebug(lcItemViewDelegateRecycling) <<
"pool size before drain:" << m_reusableItemsPool.size();
4070 for (
auto it = m_reusableItemsPool.begin(); it != m_reusableItemsPool.end();) {
4071 if (++(it->poolTime) <= maxPoolTime) {
4074 releaseItem(it->item);
4075 it = m_reusableItemsPool.erase(it);
4079 qCDebug(lcItemViewDelegateRecycling) <<
"pool size after drain:" << m_reusableItemsPool.size();
4175 this->changes =
new QVector<QQmlChangeSet::Change>(changes);
4176 QV4::Scope scope(internalClass->engine);
4177 QV4::ScopedObject o(scope,
this);
4178 o->setArrayType(QV4::Heap::ArrayData::Custom);
4185 QV4::Scope scope(v4);
4187 QV4::ScopedObject proto(scope, v4->newObject());
4188 proto->defineAccessorProperty(QStringLiteral(
"index"), QQmlDelegateModelGroupChange::method_get_index,
nullptr);
4189 proto->defineAccessorProperty(QStringLiteral(
"count"), QQmlDelegateModelGroupChange::method_get_count,
nullptr);
4190 proto->defineAccessorProperty(QStringLiteral(
"moveId"), QQmlDelegateModelGroupChange::method_get_moveId,
nullptr);
4191 changeProto.set(v4, proto);
4199 const QVector<QQmlChangeSet::Change> &changes)
4201 QV4::Scope scope(v4);
4202 QV4::ScopedObject o(scope, QQmlDelegateModelGroupChangeArray::create(v4, changes));
4203 return o.asReturnedValue();
4208#include "moc_qqmldelegatemodel_p_p.cpp"
4210#include "moc_qqmldelegatemodel_p.cpp"
void initializeRequiredProperties(QQmlDelegateModelItem *modelItemToIncubate, QObject *object, QQmlDelegateModel::DelegateModelAccess access)
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,...
QQmlDelegateModelItem * incubating
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 stringlist QtQml.Models::DelegateModel::groups
int persistedItemsIndex() const
QQmlDelegateModelItem * m_cacheItem
bool inPersistedItems() const
~QQmlDelegateModelEngineData()
QV4::PersistentValue changeProto
QV4::ReturnedValue array(QV4::ExecutionEngine *engine, const QVector< QQmlChangeSet::Change > &changes)
QQmlDelegateModelEngineData(QV4::ExecutionEngine *v4)
virtual void initPackage(int, QQuickPackage *)
virtual void destroyingPackage(QQuickPackage *)
virtual ~QQmlDelegateModelGroupEmitter()
virtual void createdPackage(int, QQuickPackage *)
bool parseIndex(const QV4::Value &value, int *index, Compositor::Group *group) const
void createdPackage(int index, QQuickPackage *package)
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)
void disableStructuredModelData()
QQDMIncubationTask * incubationTask
void childContextObjectDestroyed(QObject *childContextObject)
int groupIndex(Compositor::Group group)
bool isReferenced() const
virtual void setModelIndex(int idx, int newRow, int newColumn, bool alwaysEmit=false)
bool isObjectReferenced() const
QQmlDelegateModelAttached * attached() const
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)
QQmlDelegateModelParts * m_parts
QQmlAbstractDelegateComponent * m_delegateChooser
void itemsRemoved(const QVector< Compositor::Remove > &removes)
void addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it)
void reuseItem(QQmlDelegateModelItem *item, int newModelIndex, int newGroups)
void drainReusableItemsPool(int maxPoolTime)
QQmlDelegateModelGroupEmitterList m_pendingParts
void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override
QObject * object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode)
void destroyCacheItem(QQmlDelegateModelItem *cacheItem)
void connectToAbstractItemModel()
int adaptorModelCount() const
InsertionResult insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups)
void itemsRemoved(const QVector< Compositor::Remove > &removes, QVarLengthArray< QVector< QQmlChangeSet::Change >, Compositor::MaximumGroupCount > *translatedRemoves, QHash< int, QList< QQmlDelegateModelItem * > > *movedItems=nullptr)
void setGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
void itemsInserted(const QVector< Compositor::Insert > &inserts, QVarLengthArray< QVector< QQmlChangeSet::Change >, Compositor::MaximumGroupCount > *translatedInserts, QHash< int, QList< QQmlDelegateModelItem * > > *movedItems=nullptr)
void delegateChanged(bool add=true, bool remove=true)
void releaseIncubator(QQDMIncubationTask *incubationTask)
bool m_waitingToFetchMore
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)
void itemsChanged(const QVector< Compositor::Change > &changes)
void removeGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
void itemsInserted(const QVector< Compositor::Insert > &inserts)
void disconnectFromAbstractItemModel()
void itemsMoved(const QVector< Compositor::Remove > &removes, const QVector< Compositor::Insert > &inserts)
~QQmlDelegateModelPrivate()
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
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 drain(int maxPoolTime, std::function< void(QQmlDelegateModelItem *cacheItem)> releaseItem)
QQmlDelegateModelItem * takeItem(const QQmlComponent *delegate, int newIndexHint)
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
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 QVector< QQmlChangeSet::Change > &changes)
QVector< QQmlChangeSet::Change > * changes
QQmlChangeSet::ChangeData change
QQmlDelegateModelItem * item