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
546
547QQmlDelegateModel::DelegateModelAccess QQmlDelegateModel::delegateModelAccess()
const
549 Q_D(
const QQmlDelegateModel);
550 return d->m_adaptorModel.delegateModelAccess;
553void QQmlDelegateModel::setDelegateModelAccess(
554 QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
556 Q_D(QQmlDelegateModel);
557 if (d->m_adaptorModel.delegateModelAccess == delegateModelAccess)
560 if (d->m_transaction) {
561 qmlWarning(
this) << tr(
"The delegateModelAccess of a DelegateModel "
562 "cannot be changed within onUpdated.");
567 _q_itemsRemoved(0, d->m_count);
568 d->m_adaptorModel.delegateModelAccess = delegateModelAccess;
569 _q_itemsInserted(0, d->adaptorModelCount());
570 d->requestMoreIfNecessary();
572 d->m_adaptorModel.delegateModelAccess = delegateModelAccess;
575 emit delegateModelAccessChanged();
579
580
581
582
583
584
585
586
587
588
589
590QVariant QQmlDelegateModel::modelIndex(
int idx)
const
592 Q_D(
const QQmlDelegateModel);
593 return d->m_adaptorModel.modelIndex(idx);
597
598
599
600
601
602
603
604
605
606
607
608QVariant QQmlDelegateModel::parentModelIndex()
const
610 Q_D(
const QQmlDelegateModel);
611 return d->m_adaptorModel.parentModelIndex();
615
616
618int QQmlDelegateModel::count()
const
620 Q_D(
const QQmlDelegateModel);
623 return d->m_compositor.count(d->m_compositorGroup);
629 return QQmlDelegateModel::ReleaseFlags{};
633 return QQmlDelegateModel::ReleaseFlags{};
635 if (!cacheItem->releaseObject())
636 return QQmlDelegateModel::Referenced;
638 if (reusableFlag == QQmlInstanceModel::Reusable && m_reusableItemsPool.insertItem(cacheItem)) {
640 emit q_func()->itemPooled(cacheItem->modelIndex(), cacheItem->object);
641 return QQmlInstanceModel::Pooled;
645 return QQmlInstanceModel::Destroyed;
650 if (QObject *object = cacheItem->object) {
651 emitDestroyingItem(object);
663
664
665QQmlDelegateModel::ReleaseFlags QQmlDelegateModel::release(QObject *item, QQmlInstanceModel::ReusableFlag reusableFlag)
667 Q_D(QQmlDelegateModel);
668 QQmlInstanceModel::ReleaseFlags stat = d->release(item, reusableFlag);
673void QQmlDelegateModel::cancel(
int index)
675 Q_D(QQmlDelegateModel);
676 if (index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
677 qWarning() <<
"DelegateModel::cancel: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
681 Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
682 QQmlDelegateModelItem *cacheItem = it->inCache() ? d->m_cache.at(it.cacheIndex()) : 0;
684 if (cacheItem->incubationTask && !cacheItem->isObjectReferenced()) {
685 d->releaseIncubator(cacheItem->incubationTask);
686 cacheItem->incubationTask =
nullptr;
688 if (cacheItem->object) {
689 QObject *object = cacheItem->object;
690 cacheItem->destroyObject();
691 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
692 d->emitDestroyingPackage(package);
694 d->emitDestroyingItem(object);
697 cacheItem->scriptRef -= 1;
699 if (!cacheItem->isReferenced()) {
700 d->m_compositor.clearFlags(
701 Compositor::Cache, it.cacheIndex(), 1, Compositor::CacheFlag);
702 d->m_cache.removeAt(it.cacheIndex());
704 Q_ASSERT(d->m_cache.size() == d->m_compositor.count(Compositor::Cache));
710 QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group)
715 if (d->m_groupCount == Compositor::MaximumGroupCount) {
716 qmlWarning(d->q_func()) << QQmlDelegateModel::tr(
"The maximum number of supported DelegateModelGroups is 8");
724 QQmlListProperty<QQmlDelegateModelGroup> *property)
731 QQmlListProperty<QQmlDelegateModelGroup> *property, qsizetype index)
735 ? d->m_groups[index + 1]
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
767QQmlListProperty<QQmlDelegateModelGroup> QQmlDelegateModel::groups()
769 Q_D(QQmlDelegateModel);
770 return QQmlListProperty<QQmlDelegateModelGroup>(
773 QQmlDelegateModelPrivate::group_append,
774 QQmlDelegateModelPrivate::group_count,
775 QQmlDelegateModelPrivate::group_at,
776 nullptr,
nullptr,
nullptr);
780
781
782
783
785QQmlDelegateModelGroup *QQmlDelegateModel::items()
787 Q_D(QQmlDelegateModel);
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
808QQmlDelegateModelGroup *QQmlDelegateModel::persistedItems()
810 Q_D(QQmlDelegateModel);
811 return d->m_persistedItems;
815
816
817
818
819
820
821
822
824QString QQmlDelegateModel::filterGroup()
const
826 Q_D(
const QQmlDelegateModel);
827 return d->m_filterGroup;
830void QQmlDelegateModel::setFilterGroup(
const QString &group)
832 Q_D(QQmlDelegateModel);
834 if (d->m_transaction) {
835 qmlWarning(
this) << tr(
"The group of a DelegateModel cannot be changed within onChanged");
839 if (d->m_filterGroup != group) {
840 d->m_filterGroup = group;
841 d->updateFilterGroup();
842 emit filterGroupChanged();
846void QQmlDelegateModel::resetFilterGroup()
848 setFilterGroup(QStringLiteral(
"items"));
853 Q_Q(QQmlDelegateModel);
854 if (!m_cacheMetaType)
857 QQmlListCompositor::Group previousGroup = m_compositorGroup;
858 m_compositorGroup = Compositor::Default;
860 if (m_filterGroup == m_cacheMetaType->groupNames.at(i - 1)) {
861 m_compositorGroup = Compositor::Group(i);
866 QQmlDelegateModelGroupPrivate::get(m_groups[m_compositorGroup])->emitters.insert(
this);
867 if (m_compositorGroup != previousGroup) {
868 QVector<QQmlChangeSet::Change> removes;
869 QVector<QQmlChangeSet::Change> inserts;
870 m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
872 QQmlChangeSet changeSet;
873 changeSet.move(removes, inserts);
874 emit q->modelUpdated(changeSet,
false);
876 if (changeSet.difference() != 0)
877 emit q->countChanged();
880 auto partsCopy =
m_parts->models;
881 for (QQmlPartsModel *model : std::as_const(partsCopy))
882 model->updateFilterGroup(m_compositorGroup, changeSet);
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
915QObject *QQmlDelegateModel::parts()
917 Q_D(QQmlDelegateModel);
919 d->m_parts =
new QQmlDelegateModelParts(
this);
923const QAbstractItemModel *QQmlDelegateModel::abstractItemModel()
const
925 Q_D(
const QQmlDelegateModel);
926 return d->m_adaptorModel.adaptsAim() ? d->m_adaptorModel.aim() :
nullptr;
931 for (
int i = 1; i < m_groupCount; ++i)
932 QQmlDelegateModelGroupPrivate::get(m_groups[i])->createdPackage(incubationTask->index[i], package);
937 for (
int i = 1; i < m_groupCount; ++i)
938 QQmlDelegateModelGroupPrivate::get(m_groups[i])->initPackage(incubationTask->index[i], package);
943 for (
int i = 1; i < m_groupCount; ++i)
944 QQmlDelegateModelGroupPrivate::get(m_groups[i])->destroyingPackage(package);
949 return status == QQmlIncubator::Ready || status == QQmlIncubator::Error;
1012 QObject *targetObject =
nullptr;
1013 RequiredProperties *requiredProperties =
nullptr;
1020 QQmlDelegateModel::DelegateModelAccess access)
1024 QQmlData *d = QQmlData::get(object);
1025 if (
auto contextData = d ? d->context :
nullptr)
1026 contextData->setExtraObject(modelItemToIncubate);
1028 Q_ASSERT(modelItemToIncubate->delegate);
1029 const bool isBound = QQmlComponentPrivate::get(modelItemToIncubate->delegate)->isBound();
1031 auto incubatorPriv = QQmlIncubatorPrivate::get(
this);
1032 if (incubatorPriv->hadTopLevelRequiredProperties()) {
1038 incubating->contextData->setContextObject(
nullptr);
1041 proxyContext->setContextObject(
nullptr);
1047 const QMetaObject *qmlMetaObject = modelItemToIncubate->metaObject();
1049 RequiredProperties *requiredProperties = incubatorPriv->requiredProperties();
1050 if (requiredProperties->empty())
1054 QQmlEnginePrivate::get(incubatorPriv->enginePriv),
1055 object, requiredProperties, access);
1065 initializer(qmlMetaObject, modelItemToIncubate);
1067 auto delegateModelItemSubclassMO = qmlMetaObject->superClass();
1068 initializer(delegateModelItemSubclassMO, modelItemToIncubate);
1070 while (strcmp(delegateModelItemSubclassMO->className(),
1071 modelItemToIncubate->staticMetaObject.className())) {
1072 delegateModelItemSubclassMO = delegateModelItemSubclassMO->superClass();
1073 initializer(delegateModelItemSubclassMO, modelItemToIncubate);
1077 initializer(proxiedObject->metaObject(), proxiedObject.data());
1085 modelItemToIncubate->contextData->setContextObject(modelItemToIncubate);
1087 proxyContext->setContextObject(proxiedObject);
1094 modelItemToIncubate->metaObject();
1101 vdm->incubatorStatusChanged(
this, status);
1102 }
else if (isDoneIncubating(status)) {
1115 Q_Q(QQmlDelegateModel);
1116 if (!incubationTask->isError())
1117 incubationTask->clear();
1118 m_finishedIncubating.append(incubationTask);
1121 QCoreApplication::postEvent(q,
new QEvent(QEvent::User));
1127 Q_ASSERT(item->object);
1136 const bool alwaysEmit =
true;
1142 auto const updateAllRoles = QVector<
int>();
1143 m_adaptorModel.notify(itemAsList, newModelIndex, 1, updateAllRoles);
1146 qmlAttachedPropertiesObject<QQmlDelegateModel>(item->object,
false))) {
1156 emit q_func()->itemReused(newModelIndex, item->object);
1161 m_reusableItemsPool.drain(maxPoolTime, [
this](QQmlDelegateModelItem *cacheItem){ destroyCacheItem(cacheItem); });
1164void QQmlDelegateModel::drainReusableItemsPool(
int maxPoolTime)
1166 d_func()->drainReusableItemsPool(maxPoolTime);
1169int QQmlDelegateModel::poolSize()
1171 return d_func()->m_reusableItemsPool.size();
1176 if (!m_delegateChooser)
1179 QQmlComponent *delegate =
nullptr;
1183 delegate = chooser->delegate(&m_adaptorModel, index);
1184 chooser = qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
1192 m_cache.insert(it.cacheIndex(), item);
1193 m_compositor.setFlags(it, 1, Compositor::CacheFlag);
1194 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1199 int cidx = m_cache.lastIndexOf(cacheItem);
1201 m_compositor.clearFlags(Compositor::Cache, cidx, 1, Compositor::CacheFlag);
1202 m_cache.removeAt(cidx);
1204 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1209 if (!isDoneIncubating(status))
1212 const QList<QQmlError> incubationTaskErrors = incubationTask->errors();
1219 if (status == QQmlIncubator::Ready) {
1221 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
1224 emitCreatedItem(incubationTask, cacheItem->object);
1226 }
else if (status == QQmlIncubator::Error) {
1227 qmlInfo(m_delegate, incubationTaskErrors + m_delegate->errors()) <<
"Cannot create delegate";
1231 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
1234 emitDestroyingItem(cacheItem->object);
1235 delete cacheItem->object;
1236 cacheItem->object =
nullptr;
1238 cacheItem->contextData.reset();
1249 vdm->setInitialState(
this, o);
1260 incubationTask->initializeRequiredProperties(
1261 incubationTask->incubating, o, m_adaptorModel.delegateModelAccess);
1262 cacheItem->object = o;
1264 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
1267 emitInitItem(incubationTask, cacheItem->object);
1272 if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
1273 qWarning() <<
"DelegateModel::item: index out range" << index << m_compositor.count(group);
1275 }
else if (!m_context || !m_context->isValid()) {
1279 Compositor::iterator it = m_compositor.find(group, index);
1280 const auto flags = it->flags;
1281 const auto modelIndex = it.modelIndex();
1285 if (!cacheItem || !cacheItem->delegate) {
1286 QQmlComponent *delegate = resolveDelegate(modelIndex);
1291 cacheItem = m_reusableItemsPool.takeItem(delegate, index);
1296 addCacheItem(cacheItem, it);
1300 if (index == m_compositor.count(group) - 1)
1302 return cacheItem->object;
1306 cacheItem = m_adaptorModel.createItem(m_cacheMetaType, modelIndex);
1311 addCacheItem(cacheItem, it);
1314 cacheItem->delegate = delegate;
1323 bool sync = (incubationMode == QQmlIncubator::Synchronous || incubationMode == QQmlIncubator::AsynchronousIfNested);
1324 if (sync && cacheItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous) {
1328 }
else if (!cacheItem->object) {
1329 QQmlContext *creationContext = cacheItem->delegate->creationContext();
1340 const QQmlRefPointer<QQmlContextData> componentContext
1341 = QQmlContextData::get(creationContext ? creationContext : m_context.data());
1342 QQmlComponentPrivate *cp = QQmlComponentPrivate::get(cacheItem->delegate);
1344 if (cp->isBound()) {
1345 cacheItem->contextData = componentContext;
1349 if (m_adaptorModel.hasProxyObject())
1350 cacheItem->initProxy();
1353 cacheItem->incubationTask,
1354 cacheItem->delegate,
1355 m_context->engine(),
1357 QQmlContextData::get(m_context));
1359 QQmlRefPointer<QQmlContextData> ctxt
1360 = QQmlContextData::createRefCounted(componentContext);
1361 ctxt->setContextObject(cacheItem);
1362 cacheItem->contextData = ctxt;
1366 if (m_adaptorModel.hasProxyObject()) {
1367 if (m_adaptorModel.delegateModelAccess == QQmlDelegateModel::ReadOnly)
1368 cacheItem->initProxy();
1370 ctxt = cacheItem->initProxy();
1374 cacheItem->incubationTask,
1375 cacheItem->delegate,
1376 m_context->engine(),
1378 QQmlContextData::get(m_context));
1382 if (index == m_compositor.count(group) - 1)
1387 if (cacheItem->object && (!cacheItem->incubationTask || isDoneIncubating(cacheItem->incubationTask->status())))
1388 return cacheItem->object;
1402
1403
1404
1405
1406
1407
1408
1409QObject *QQmlDelegateModel::object(
int index, QQmlIncubator::IncubationMode incubationMode)
1411 Q_D(QQmlDelegateModel);
1412 if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
1413 qWarning() <<
"DelegateModel::item: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
1417 return d->object(d->m_compositorGroup, index, incubationMode);
1420QQmlIncubator::Status QQmlDelegateModel::incubationStatus(
int index)
1422 Q_D(QQmlDelegateModel);
1423 if (d->m_compositor.count(d->m_compositorGroup) <= index)
1424 return QQmlIncubator::Null;
1425 Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
1427 return QQmlIncubator::Null;
1429 if (
auto incubationTask = d->m_cache.at(it.cacheIndex())->incubationTask)
1430 return incubationTask->status();
1432 return QQmlIncubator::Ready;
1437 Compositor::iterator it = m_compositor.find(group, index);
1438 if (QQmlAdaptorModel *model = it.list<QQmlAdaptorModel>()) {
1439 QString role = name;
1440 int dot = name.indexOf(QLatin1Char(
'.'));
1442 role = name.left(dot);
1443 QVariant value = model->value(it.modelIndex(), role);
1445 const int from = dot + 1;
1446 dot = name.indexOf(QLatin1Char(
'.'), from);
1447 QStringView propertyName = QStringView{name}.mid(from, dot - from);
1448 if (QObject *obj = qvariant_cast<QObject*>(value)) {
1449 value = obj->property(propertyName.toUtf8());
1450 }
else if (
const QMetaObject *metaObject = QQmlMetaType::metaObjectForValueType(value.metaType())) {
1452 const int propertyIndex = metaObject->indexOfProperty(propertyName.toUtf8());
1453 if (propertyIndex >= 0)
1454 value = metaObject->property(propertyIndex).readOnGadget(value.constData());
1464QVariant QQmlDelegateModel::variantValue(
int index,
const QString &role)
1466 Q_D(QQmlDelegateModel);
1467 return d->variantValue(d->m_compositorGroup, index, role);
1470int QQmlDelegateModel::indexOf(QObject *item, QObject *)
const
1472 Q_D(
const QQmlDelegateModel);
1473 if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(item))
1474 return cacheItem->groupIndex(d->m_compositorGroup);
1478void QQmlDelegateModel::setWatchedRoles(
const QList<QByteArray> &roles)
1480 Q_D(QQmlDelegateModel);
1481 d->m_adaptorModel.replaceWatchedRoles(d->m_watchedRoles, roles);
1482 d->m_watchedRoles = roles;
1486 Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags)
1488 QVector<Compositor::Insert> inserts;
1489 m_compositor.setFlags(from, count, group, groupFlags, &inserts);
1490 itemsInserted(inserts);
1495 Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags)
1497 QVector<Compositor::Remove> removes;
1498 m_compositor.clearFlags(from, count, group, groupFlags, &removes);
1499 itemsRemoved(removes);
1504 Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags)
1506 QVector<Compositor::Remove> removes;
1507 QVector<Compositor::Insert> inserts;
1509 m_compositor.setFlags(from, count, group, groupFlags, &inserts);
1510 itemsInserted(inserts);
1511 const int removeFlags = ~groupFlags & Compositor::GroupMask;
1513 from = m_compositor.find(from.group, from.index[from.group]);
1514 m_compositor.clearFlags(from, count, group, removeFlags, &removes);
1515 itemsRemoved(removes);
1519bool QQmlDelegateModel::event(QEvent *e)
1521 Q_D(QQmlDelegateModel);
1522 if (e->type() == QEvent::UpdateRequest) {
1523 d->m_waitingToFetchMore =
false;
1524 d->m_adaptorModel.fetchMore();
1525 }
else if (e->type() == QEvent::User) {
1526 d->m_incubatorCleanupScheduled =
false;
1527 qDeleteAll(d->m_finishedIncubating);
1528 d->m_finishedIncubating.clear();
1530 return QQmlInstanceModel::event(e);
1538 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedChanges(m_groupCount);
1540 for (
const Compositor::Change &change : changes) {
1541 for (
int i = 1; i < m_groupCount; ++i) {
1542 if (change.inGroup(i)) {
1543 translatedChanges[i].append(QQmlChangeSet::Change(change.index[i], change.count));
1548 for (
int i = 1; i < m_groupCount; ++i)
1549 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.change(translatedChanges.at(i));
1552void QQmlDelegateModel::_q_itemsChanged(
int index,
int count,
const QVector<
int> &roles)
1554 Q_D(QQmlDelegateModel);
1555 if (count <= 0 || !d->m_complete)
1558 if (d->m_adaptorModel.notify(d->m_cache, index, count, roles)) {
1559 QVector<Compositor::Change> changes;
1560 d->m_compositor.listItemsChanged(&d->m_adaptorModel, index, count, &changes);
1561 d->itemsChanged(changes);
1564 const bool needToCheckDelegateChoiceInvalidation = d->m_delegateChooser && !roles.isEmpty();
1565 if (!needToCheckDelegateChoiceInvalidation)
1570 if (!d->m_adaptorModel.adaptsAim())
1573 const auto aim = d->m_adaptorModel.aim();
1574 const auto choiceRole = d->m_delegateChooser->role().toUtf8();
1575 const auto &roleNames = aim->roleNames();
1576 auto it = std::find_if(roles.begin(), roles.end(), [&](
int role) {
1577 return roleNames[role] == choiceRole;
1579 if (it == roles.end())
1585
1586
1587
1588 QVector<Compositor::Remove> removes;
1589 QVector<Compositor::Insert> inserts;
1590 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, index, count, &removes);
1591 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1592 for (QQmlDelegateModelItem *item : cache)
1593 item->referenceObject();
1594 for (
const auto& removed: removes) {
1595 if (!d->m_cache.isSharedWith(cache))
1597 QQmlDelegateModelItem *item = cache.value(removed.cacheIndex(),
nullptr);
1598 if (!d->m_cache.contains(item))
1600 if (item->modelIndex() != -1)
1601 item->setModelIndex(-1, -1, -1);
1603 for (QQmlDelegateModelItem *item : cache)
1604 item->releaseObject();
1605 d->m_compositor.listItemsInserted(&d->m_adaptorModel, index, count, &inserts);
1606 d->itemsMoved(removes, inserts);
1613 for (
int i = 1; i < count; ++i)
1614 incubationTask->index[i] += deltas[i];
1617 for (
int i = 1; i < qMin<
int>(count, Compositor::MaximumGroupCount); ++i)
1618 attached->m_currentIndex[i] += deltas[i];
1623 const QVector<Compositor::Insert> &inserts,
1624 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
1625 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems)
1629 int inserted[Compositor::MaximumGroupCount];
1633 for (
const Compositor::Insert &insert : inserts) {
1634 for (; cacheIndex < insert.cacheIndex(); ++cacheIndex)
1635 incrementIndexes(m_cache.at(cacheIndex), m_groupCount, inserted);
1637 for (
int i = 1; i < m_groupCount; ++i) {
1638 if (insert.inGroup(i)) {
1639 (*translatedInserts)[i].append(
1640 QQmlChangeSet::Change(insert.index[i], insert.count, insert.moveId));
1641 inserted[i] += insert.count;
1645 if (!insert.inCache())
1648 if (movedItems && insert.isMove()) {
1649 QList<QQmlDelegateModelItem *> items = movedItems->take(insert.moveId);
1650 Q_ASSERT(items.size() == insert.count);
1651 m_cache = m_cache.mid(0, insert.cacheIndex())
1652 + items + m_cache.mid(insert.cacheIndex());
1654 if (insert.inGroup()) {
1655 for (
int offset = 0; cacheIndex < insert.cacheIndex() + insert.count;
1656 ++cacheIndex, ++offset) {
1657 QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
1658 cacheItem->groups |= insert.flags & Compositor::GroupMask;
1660 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
1661 for (
int i = 1; i < m_groupCount; ++i)
1662 incubationTask->index[i] = cacheItem->groups & (1 << i)
1663 ? insert.index[i] + offset
1666 if (QQmlDelegateModelAttached *attached = cacheItem->attached()) {
1667 for (
int i = 1; i < m_groupCount; ++i)
1668 attached->m_currentIndex[i] = cacheItem->groups & (1 << i)
1669 ? insert.index[i] + offset
1674 cacheIndex = insert.cacheIndex() + insert.count;
1677 for (
const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.size(); ++cacheIndex)
1678 incrementIndexes(cache.at(cacheIndex),
m_groupCount, inserted);
1683 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
1684 itemsInserted(inserts, &translatedInserts);
1685 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1689 for (
int i = 1; i < m_groupCount; ++i)
1690 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(translatedInserts.at(i));
1693void QQmlDelegateModel::_q_itemsInserted(
int index,
int count)
1696 Q_D(QQmlDelegateModel);
1697 if (count <= 0 || !d->m_complete)
1700 d->m_count += count;
1702 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1703 for (
int i = 0, c = cache.size(); i < c; ++i) {
1704 QQmlDelegateModelItem *item = cache.at(i);
1707 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
1710 if (item->modelIndex() >= index) {
1711 const int newIndex = item->modelIndex() + count;
1712 const int row = newIndex;
1713 const int column = 0;
1714 item->setModelIndex(newIndex, row, column);
1718 QVector<Compositor::Insert> inserts;
1719 d->m_compositor.listItemsInserted(&d->m_adaptorModel, index, count, &inserts);
1720 d->itemsInserted(inserts);
1732 const QVector<Compositor::Remove> &removes,
1733 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
1734 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems)
1737 int removedCache = 0;
1739 int removed[Compositor::MaximumGroupCount];
1743 for (
const Compositor::Remove &remove : removes) {
1744 for (; cacheIndex < remove.cacheIndex() && cacheIndex < m_cache.size(); ++cacheIndex)
1745 incrementIndexes(m_cache.at(cacheIndex), m_groupCount, removed);
1747 for (
int i = 1; i < m_groupCount; ++i) {
1748 if (remove.inGroup(i)) {
1749 (*translatedRemoves)[i].append(
1750 QQmlChangeSet::Change(remove.index[i], remove.count, remove.moveId));
1751 removed[i] -= remove.count;
1755 if (!remove.inCache())
1758 if (movedItems && remove.isMove()) {
1759 movedItems->insert(remove.moveId, m_cache.mid(remove.cacheIndex(), remove.count));
1760 QList<QQmlDelegateModelItem *>::const_iterator begin = m_cache.constBegin() + remove.cacheIndex();
1761 QList<QQmlDelegateModelItem *>::const_iterator end = begin + remove.count;
1762 m_cache.erase(begin, end);
1764 for (; cacheIndex < remove.cacheIndex() + remove.count - removedCache; ++cacheIndex) {
1765 QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
1766 if (remove.inGroup(Compositor::Persisted) && cacheItem->objectRef == 0 && cacheItem->object) {
1767 QObject *object = cacheItem->object;
1768 cacheItem->destroyObject();
1769 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
1770 emitDestroyingPackage(package);
1772 emitDestroyingItem(object);
1773 cacheItem->scriptRef -= 1;
1775 if (!cacheItem->isReferenced() && !remove.inGroup(Compositor::Persisted)) {
1776 m_compositor.clearFlags(Compositor::Cache, cacheIndex, 1, Compositor::CacheFlag);
1777 m_cache.removeAt(cacheIndex);
1781 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1782 }
else if (remove.groups() == cacheItem->groups) {
1783 cacheItem->groups = 0;
1784 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
1785 for (
int i = 1; i < m_groupCount; ++i)
1786 incubationTask->index[i] = -1;
1788 if (QQmlDelegateModelAttached *attached = cacheItem->attached()) {
1789 for (
int i = 1; i < m_groupCount; ++i)
1790 attached->m_currentIndex[i] = -1;
1793 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
1794 if (!cacheItem->isObjectReferenced()) {
1795 releaseIncubator(cacheItem->incubationTask);
1796 cacheItem->incubationTask =
nullptr;
1797 if (cacheItem->object) {
1798 QObject *object = cacheItem->object;
1799 cacheItem->destroyObject();
1800 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
1801 emitDestroyingPackage(package);
1803 emitDestroyingItem(object);
1805 cacheItem->scriptRef -= 1;
1807 for (
int i = 1; i < m_groupCount; ++i) {
1808 if (remove.inGroup(i))
1809 incubationTask->index[i] = remove.index[i];
1813 if (QQmlDelegateModelAttached *attached = cacheItem->attached()) {
1814 for (
int i = 1; i < m_groupCount; ++i) {
1815 if (remove.inGroup(i))
1816 attached->m_currentIndex[i] = remove.index[i];
1819 cacheItem->groups &= ~remove.flags;
1825 for (
const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.size(); ++cacheIndex)
1826 incrementIndexes(cache.at(cacheIndex),
m_groupCount, removed);
1831 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
1832 itemsRemoved(removes, &translatedRemoves);
1833 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1837 for (
int i = 1; i < m_groupCount; ++i)
1838 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(translatedRemoves.at(i));
1841void QQmlDelegateModel::_q_itemsRemoved(
int index,
int count)
1843 Q_D(QQmlDelegateModel);
1844 if (count <= 0|| !d->m_complete)
1847 d->m_count -= count;
1848 Q_ASSERT(d->m_count >= 0);
1849 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1851 for (QQmlDelegateModelItem *item : cache)
1852 item->referenceObject();
1854 for (
int i = 0, c = cache.size(); i < c; ++i) {
1855 QQmlDelegateModelItem *item = cache.at(i);
1858 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
1861 if (item->modelIndex() >= index + count) {
1862 const int newIndex = item->modelIndex() - count;
1863 const int row = newIndex;
1864 const int column = 0;
1865 item->setModelIndex(newIndex, row, column);
1866 }
else if (item->modelIndex() >= index) {
1867 item->setModelIndex(-1, -1, -1);
1871 for (QQmlDelegateModelItem *item : cache)
1872 item->releaseObject();
1874 QVector<Compositor::Remove> removes;
1875 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, index, count, &removes);
1876 d->itemsRemoved(removes);
1882 const QVector<Compositor::Remove> &removes,
const QVector<Compositor::Insert> &inserts)
1884 QHash<
int, QList<QQmlDelegateModelItem *> > movedItems;
1886 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
1887 itemsRemoved(removes, &translatedRemoves, &movedItems);
1889 QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
1890 itemsInserted(inserts, &translatedInserts, &movedItems);
1891 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1892 Q_ASSERT(movedItems.isEmpty());
1897 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.move(
1898 translatedRemoves.at(i),
1899 translatedInserts.at(i));
1903void QQmlDelegateModel::_q_itemsMoved(
int from,
int to,
int count)
1905 Q_D(QQmlDelegateModel);
1906 if (count <= 0 || !d->m_complete)
1909 const int minimum = qMin(from, to);
1910 const int maximum = qMax(from, to) + count;
1911 const int difference = from > to ? count : -count;
1913 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1914 for (
int i = 0, c = cache.size(); i < c; ++i) {
1915 QQmlDelegateModelItem *item = cache.at(i);
1918 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
1921 if (item->modelIndex() >= from && item->modelIndex() < from + count) {
1922 const int newIndex = item->modelIndex() - from + to;
1923 const int row = newIndex;
1924 const int column = 0;
1925 item->setModelIndex(newIndex, row, column);
1926 }
else if (item->modelIndex() >= minimum && item->modelIndex() < maximum) {
1927 const int newIndex = item->modelIndex() + difference;
1928 const int row = newIndex;
1929 const int column = 0;
1930 item->setModelIndex(newIndex, row, column);
1934 QVector<Compositor::Remove> removes;
1935 QVector<Compositor::Insert> inserts;
1936 d->m_compositor.listItemsMoved(&d->m_adaptorModel, from, to, count, &removes, &inserts);
1937 d->itemsMoved(removes, inserts);
1943 Q_Q(QQmlDelegateModel);
1944 emit q->modelUpdated(changeSet, reset);
1945 if (changeSet.difference() != 0)
1946 emit q->countChanged();
1951 Q_Q(QQmlDelegateModel);
1956 qmlWarning(q) << QQmlDelegateModel::tr(
"The delegates of a DelegateModel cannot be changed within onUpdated.");
1962 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(
1963 0, m_compositor.count(Compositor::Group(i)));
1968 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(
1969 0, m_compositor.count(Compositor::Group(i)));
1977 if (m_transaction || !m_complete || !m_context || !m_context->isValid())
1981 QV4::ExecutionEngine *engine = m_context->engine()->handle();
1982 for (
int i = 1; i < m_groupCount; ++i)
1983 QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitChanges(engine);
1988 for (
int i = 1; i < m_groupCount; ++i)
1989 QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset);
1992 QVarLengthArray<QPointer<QQmlDelegateModelAttached>> attachedObjects;
1993 attachedObjects.reserve(m_cache.length());
1994 for (
const QQmlDelegateModelItem *cacheItem : std::as_const(m_cache))
1995 attachedObjects.append(cacheItem->attached());
1997 for (
const QPointer<QQmlDelegateModelAttached> &attached : std::as_const(attachedObjects)) {
1998 if (attached && attached->m_cacheItem)
1999 attached->emitChanges();
2003void QQmlDelegateModel::_q_modelAboutToBeReset()
2005 Q_D(QQmlDelegateModel);
2006 if (!d->m_adaptorModel.adaptsAim())
2008 auto aim = d->m_adaptorModel.aim();
2009 auto oldRoleNames = aim->roleNames();
2012 QObject::connect(aim, &QAbstractItemModel::modelReset,
this, [
this, d, oldRoleNames, aim](){
2013 if (!d->m_adaptorModel.adaptsAim() || d->m_adaptorModel.aim() != aim)
2015 if (oldRoleNames == aim->roleNames()) {
2021 QVariant m = model();
2022 setModel(QVariant());
2028 }, Qt::SingleShotConnection);
2031void QQmlDelegateModel::handleModelReset()
2033 Q_D(QQmlDelegateModel);
2037 int oldCount = d->m_count;
2038 d->m_adaptorModel.rootIndex = QModelIndex();
2040 if (d->m_complete) {
2041 d->m_count = d->adaptorModelCount();
2043 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
2044 for (QQmlDelegateModelItem *item : cache)
2045 item->referenceObject();
2047 for (
int i = 0, c = cache.size(); i < c; ++i) {
2048 QQmlDelegateModelItem *item = cache.at(i);
2051 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
2054 if (item->modelIndex() != -1)
2055 item->setModelIndex(-1, -1, -1);
2058 for (QQmlDelegateModelItem *item : cache)
2059 item->releaseObject();
2060 QVector<Compositor::Remove> removes;
2061 QVector<Compositor::Insert> inserts;
2063 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
2065 d->m_compositor.listItemsInserted(&d->m_adaptorModel, 0, d->m_count, &inserts);
2066 d->itemsMoved(removes, inserts);
2069 if (d->m_adaptorModel.canFetchMore())
2070 d->m_adaptorModel.fetchMore();
2074 emit rootIndexChanged();
2077void QQmlDelegateModel::_q_rowsInserted(
const QModelIndex &parent,
int begin,
int end)
2079 Q_D(QQmlDelegateModel);
2080 if (parent == d->m_adaptorModel.rootIndex)
2081 _q_itemsInserted(begin, end - begin + 1);
2084void QQmlDelegateModel::_q_rowsAboutToBeRemoved(
const QModelIndex &parent,
int begin,
int end)
2086 Q_D(QQmlDelegateModel);
2087 if (!d->m_adaptorModel.rootIndex.isValid())
2089 const QModelIndex index = d->m_adaptorModel.rootIndex;
2090 if (index.parent() == parent && index.row() >= begin && index.row() <= end) {
2091 const int oldCount = d->m_count;
2093 d->disconnectFromAbstractItemModel();
2094 d->m_adaptorModel.invalidateModel();
2096 if (d->m_complete && oldCount > 0) {
2097 QVector<Compositor::Remove> removes;
2098 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
2099 d->itemsRemoved(removes);
2105void QQmlDelegateModel::_q_rowsRemoved(
const QModelIndex &parent,
int begin,
int end)
2107 Q_D(QQmlDelegateModel);
2108 if (parent == d->m_adaptorModel.rootIndex)
2109 _q_itemsRemoved(begin, end - begin + 1);
2112void QQmlDelegateModel::_q_rowsMoved(
2113 const QModelIndex &sourceParent,
int sourceStart,
int sourceEnd,
2114 const QModelIndex &destinationParent,
int destinationRow)
2116 Q_D(QQmlDelegateModel);
2117 const int count = sourceEnd - sourceStart + 1;
2118 if (destinationParent == d->m_adaptorModel.rootIndex && sourceParent == d->m_adaptorModel.rootIndex) {
2119 _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow - count, count);
2120 }
else if (sourceParent == d->m_adaptorModel.rootIndex) {
2121 _q_itemsRemoved(sourceStart, count);
2122 }
else if (destinationParent == d->m_adaptorModel.rootIndex) {
2123 _q_itemsInserted(destinationRow, count);
2127void QQmlDelegateModel::_q_columnsInserted(
const QModelIndex &parent,
int begin,
int end)
2129 Q_D(QQmlDelegateModel);
2131 if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
2133 _q_itemsChanged(0, d->m_count, QVector<
int>());
2137void QQmlDelegateModel::_q_columnsRemoved(
const QModelIndex &parent,
int begin,
int end)
2139 Q_D(QQmlDelegateModel);
2141 if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
2143 _q_itemsChanged(0, d->m_count, QVector<
int>());
2147void QQmlDelegateModel::_q_columnsMoved(
const QModelIndex &parent,
int start,
int end,
2148 const QModelIndex &destination,
int column)
2150 Q_D(QQmlDelegateModel);
2152 if ((parent == d->m_adaptorModel.rootIndex && start == 0)
2153 || (destination == d->m_adaptorModel.rootIndex && column == 0)) {
2155 _q_itemsChanged(0, d->m_count, QVector<
int>());
2159void QQmlDelegateModel::_q_dataChanged(
const QModelIndex &begin,
const QModelIndex &end,
const QVector<
int> &roles)
2161 Q_D(QQmlDelegateModel);
2162 if (begin.parent() == d->m_adaptorModel.rootIndex)
2163 _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, roles);
2166bool QQmlDelegateModel::isDescendantOf(
const QPersistentModelIndex& desc,
const QList< QPersistentModelIndex >& parents)
const
2168 for (
int i = 0, c = parents.size(); i < c; ++i) {
2169 for (QPersistentModelIndex parent = desc; parent.isValid(); parent = parent.parent()) {
2170 if (parent == parents[i])
2178void QQmlDelegateModel::_q_layoutChanged(
const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
2180 Q_D(QQmlDelegateModel);
2184 if (hint == QAbstractItemModel::VerticalSortHint) {
2185 if (!parents.isEmpty() && d->m_adaptorModel.rootIndex.isValid() && !isDescendantOf(d->m_adaptorModel.rootIndex, parents)) {
2190 _q_itemsChanged(0, d->m_count, QVector<
int>());
2192 }
else if (hint == QAbstractItemModel::HorizontalSortHint) {
2200QQmlDelegateModelAttached *QQmlDelegateModel::qmlAttachedProperties(QObject *obj)
2202 if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(obj))
2203 return new QQmlDelegateModelAttached(cacheItem, obj);
2204 return new QQmlDelegateModelAttached(obj);
2210 if (!m_context || !m_context->isValid())
2216 if (!object.isObject())
2219 QV4::ExecutionEngine *v4 = object.as<QV4::Object>()->engine();
2220 QV4::Scope scope(v4);
2221 QV4::ScopedObject o(scope, object);
2225 QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
2226 QV4::ScopedValue propertyName(scope);
2227 QV4::ScopedValue v(scope);
2228 const auto oldCache = m_cache;
2230 propertyName = it.nextPropertyNameAsString(v);
2231 if (propertyName->isNull())
2233 cacheItem->setValue(
2234 propertyName->toQStringNoThrow(),
2235 QV4::ExecutionEngine::toVariant(v, QMetaType {}));
2237 const bool cacheModified = !m_cache.isSharedWith(oldCache);
2241 cacheItem->groups = groups | Compositor::UnresolvedFlag | Compositor::CacheFlag;
2244 itemsInserted(QVector<Compositor::Insert>(1, Compositor::Insert(before, 1, cacheItem->groups & ~Compositor::CacheFlag)));
2246 m_cache.insert(before.cacheIndex(), cacheItem);
2247 m_compositor.insert(before,
nullptr, 0, 1, cacheItem->groups);
2254QQmlDelegateModelItemMetaType::QQmlDelegateModelItemMetaType(
2255 QV4::ExecutionEngine *engine, QQmlDelegateModel *model,
const QStringList &groupNames)
2258 , groupNames(groupNames)
2259 , modelKind(ModelKind::DelegateModel)
2263QQmlDelegateModelItemMetaType::QQmlDelegateModelItemMetaType(
2264 QV4::ExecutionEngine *engine, QQmlTableInstanceModel *model)
2267 , modelKind(ModelKind::TableInstanceModel)
2271QQmlDelegateModelItemMetaType::~QQmlDelegateModelItemMetaType() =
default;
2273void QQmlDelegateModelItemMetaType::emitModelChanged()
const
2275 switch (modelKind) {
2276 case ModelKind::InstanceModel:
2278 case ModelKind::DelegateModel:
2279 emit
static_cast<QQmlDelegateModel *>(model.data())->modelChanged();
2281 case ModelKind::TableInstanceModel:
2282 emit
static_cast<QQmlTableInstanceModel *>(model.data())->modelChanged();
2287void QQmlDelegateModelItemMetaType::initializeAttachedMetaObject()
2289 QMetaObjectBuilder builder;
2290 builder.setFlags(DynamicMetaObject);
2291 builder.setClassName(QQmlDelegateModelAttached::staticMetaObject.className());
2292 builder.setSuperClass(&QQmlDelegateModelAttached::staticMetaObject);
2295 for (qsizetype i = 0, end = groupCount(); i < end; ++i, ++notifierId) {
2296 QString propertyName = QLatin1String(
"in") + groupNames.at(i);
2297 propertyName.replace(2, 1, propertyName.at(2).toUpper());
2298 builder.addSignal(
"__" + propertyName.toUtf8() +
"Changed()");
2299 QMetaPropertyBuilder propertyBuilder = builder.addProperty(
2300 propertyName.toUtf8(),
"bool", notifierId);
2301 propertyBuilder.setWritable(
true);
2303 for (qsizetype i = 0, end = groupCount(); i < end; ++i, ++notifierId) {
2304 const QString propertyName = groupNames.at(i) + QLatin1String(
"Index");
2305 builder.addSignal(
"__" + propertyName.toUtf8() +
"Changed()");
2306 QMetaPropertyBuilder propertyBuilder = builder.addProperty(
2307 propertyName.toUtf8(),
"int", notifierId);
2308 propertyBuilder.setWritable(
true);
2311 attachedMetaObject = QQml::makeRefPointer<QQmlDelegateModelAttachedMetaObject>(
2312 this, builder.toMetaObject());
2315void QQmlDelegateModelItemMetaType::initializePrototype()
2317 QV4::Scope scope(v4Engine);
2319 QV4::ScopedObject proto(scope, v4Engine->newObject());
2320 proto->defineAccessorProperty(QStringLiteral(
"model"), QQmlDelegateModelItem::get_model,
nullptr);
2321 proto->defineAccessorProperty(QStringLiteral(
"groups"), QQmlDelegateModelItem::get_groups, QQmlDelegateModelItem::set_groups);
2322 QV4::ScopedString s(scope);
2323 QV4::ScopedProperty p(scope);
2325 s = v4Engine->newString(QStringLiteral(
"isUnresolved"));
2326 QV4::ScopedFunctionObject f(scope);
2327 QV4::ExecutionEngine *engine = scope.engine;
2328 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, 30, QQmlDelegateModelItem::get_member)));
2329 p->setSetter(
nullptr);
2330 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2332 s = v4Engine->newString(QStringLiteral(
"inItems"));
2333 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)));
2334 p->setSetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)));
2335 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2337 s = v4Engine->newString(QStringLiteral(
"inPersistedItems"));
2338 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)));
2339 p->setSetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)));
2340 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2342 s = v4Engine->newString(QStringLiteral(
"itemsIndex"));
2343 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)));
2344 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2346 s = v4Engine->newString(QStringLiteral(
"persistedItemsIndex"));
2347 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)));
2348 p->setSetter(
nullptr);
2349 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2351 for (qsizetype i = 2, end = groupCount(); i < end; ++i) {
2352 QString propertyName = QLatin1String(
"in") + groupNames.at(i);
2353 propertyName.replace(2, 1, propertyName.at(2).toUpper());
2354 s = v4Engine->newString(propertyName);
2355 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, i + 1, QQmlDelegateModelItem::get_member)));
2356 p->setSetter((f = QV4::DelegateModelGroupFunction::create(engine, i + 1, QQmlDelegateModelItem::set_member)));
2357 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2359 for (qsizetype i = 2, end = groupCount(); i < end; ++i) {
2360 const QString propertyName = groupNames.at(i) + QLatin1String(
"Index");
2361 s = v4Engine->newString(propertyName);
2362 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, i + 1, QQmlDelegateModelItem::get_index)));
2363 p->setSetter(
nullptr);
2364 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2366 modelItemProto.set(v4Engine, proto);
2369int QQmlDelegateModelItemMetaType::parseGroups(
const QStringList &groups)
const
2372 for (
const QString &groupName : groups) {
2373 int index = groupNames.indexOf(groupName);
2375 groupFlags |= 2 << index;
2380int QQmlDelegateModelItemMetaType::parseGroups(
const QV4::Value &groups)
const
2383 QV4::Scope scope(v4Engine);
2385 QV4::ScopedString s(scope, groups);
2387 const QString groupName = s->toQString();
2388 int index = groupNames.indexOf(groupName);
2390 groupFlags |= 2 << index;
2394 QV4::ScopedArrayObject array(scope, groups);
2396 QV4::ScopedValue v(scope);
2397 uint arrayLength = array->getLength();
2398 for (uint i = 0; i < arrayLength; ++i) {
2400 const QString groupName = v->toQString();
2401 int index = groupNames.indexOf(groupName);
2403 groupFlags |= 2 << index;
2409QV4::ReturnedValue
QQmlDelegateModelItem::get_model(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *,
int)
2411 QV4::Scope scope(b);
2412 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
2414 return b->engine()->throwTypeError(QStringLiteral(
"Not a valid DelegateModel object"));
2415 if (!o->d()->item->metaType->model)
2418 return o->d()->item->get();
2421QV4::ReturnedValue
QQmlDelegateModelItem::get_groups(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *,
int)
2423 QV4::Scope scope(b);
2424 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
2426 return scope.engine->throwTypeError(QStringLiteral(
"Not a valid DelegateModel object"));
2430 const auto &metaType = item->metaType;
2431 for (qsizetype i = 0, end = metaType->groupCount(); i < end; ++i) {
2432 if (item->groups & (1 << (i + 1)))
2433 groups.append(metaType->groupNames.at(i));
2436 return scope.engine->fromVariant(groups);
2439QV4::ReturnedValue
QQmlDelegateModelItem::set_groups(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
2441 QV4::Scope scope(b);
2442 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
2444 return scope.engine->throwTypeError(QStringLiteral(
"Not a valid DelegateModel object"));
2449 QQmlDelegateModel *delegateModel = o->d()->item->metaType->delegateModel();
2454 const int groupFlags = model->m_cacheMetaType->parseGroups(argv[0]);
2455 const int cacheIndex = model->m_cache.indexOf(o->d()->item);
2456 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2457 model->setGroups(it, 1, Compositor::Cache, groupFlags);
2458 return QV4::Encode::undefined();
2463 return QV4::Encode(
bool(thisItem->groups & (1 << flag)));
2468 bool member = arg.toBoolean();
2469 uint groupFlag = (1 << flag);
2470 if (member == ((cacheItem->groups & groupFlag) != 0))
2471 return QV4::Encode::undefined();
2473 QQmlDelegateModel *delegateModel = cacheItem->metaType->delegateModel();
2475 return QV4::Encode::undefined();
2478 const int cacheIndex = model->m_cache.indexOf(cacheItem);
2479 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2481 model->addGroups(it, 1, Compositor::Cache, groupFlag);
2483 model->removeGroups(it, 1, Compositor::Cache, groupFlag);
2484 return QV4::Encode::undefined();
2489 return QV4::Encode((
int)thisItem->groupIndex(Compositor::Group(flag)));
2497 for (QQmlRefPointer<QQmlContextData> ctxt = contextData->childContexts(); ctxt;
2498 ctxt = ctxt->nextChild()) {
2499 ctxt->deepClearContextObject(childContextObject);
2516 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
2517 QQmlAdaptorModel::Accessors *accessor,
2518 int modelIndex,
int row,
int column)
2519 : metaType(metaType)
2524 if (accessor->propertyCache) {
2532 QQmlData::get(
this,
true)->propertyCache = accessor->propertyCache;
2543 if (QQmlDelegateModel *delegateModel = metaType->delegateModel())
2544 QQmlDelegateModelPrivate::get(delegateModel)->releaseIncubator(incubationTask);
2556 if (QQmlDelegateModel *delegateModel = metaType->delegateModel())
2557 QQmlDelegateModelPrivate::get(delegateModel)->removeCacheItem(
this);
2564 const int prevIndex = index;
2565 const int prevRow = row;
2566 const int prevColumn = column;
2572 if (idx != prevIndex || alwaysEmit)
2573 emit modelIndexChanged();
2574 if (row != prevRow || alwaysEmit)
2576 if (column != prevColumn || alwaysEmit)
2577 emit columnChanged();
2583 Q_ASSERT(contextData);
2585 QQmlData *data = QQmlData::get(object);
2587 if (data->ownContext) {
2588 data->ownContext->clearContext();
2589 data->ownContext->deepClearContextObject(object);
2590 data->ownContext.reset();
2591 data->context =
nullptr;
2594
2595
2596
2597
2598
2599
2600 if (Q_UNLIKELY(
static_cast<QCoreApplicationPrivate *>(QCoreApplicationPrivate::get(QCoreApplication::instance()))->aboutToQuitEmitted)) {
2601 if (object->parent() ==
nullptr)
2602 object->setParent(QCoreApplication::instance());
2604 object->deleteLater();
2609 contextData.reset();
2615 QQmlData *d = QQmlData::get(object);
2619 QQmlRefPointer<QQmlContextData> context = d->context;
2620 if (!context || !context->isValid())
2623 if (QObject *extraObject = context->extraObject())
2624 return qobject_cast<QQmlDelegateModelItem *>(extraObject);
2626 for (context = context->parent(); context; context = context->parent()) {
2627 if (QObject *extraObject = context->extraObject())
2628 return qobject_cast<QQmlDelegateModelItem *>(extraObject);
2630 context->contextObject())) {
2639 if (QQmlDelegateModel *delegateModel = metaType->delegateModel()) {
2641 return model->m_compositor.find(Compositor::Cache, model->m_cache.indexOf(
this)).index[group];
2649 QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject)
2659 *
static_cast<QMetaObject *>(
this) = *metaObject;
2672int QQmlDelegateModelAttachedMetaObject::
metaCall(QObject *object, QMetaObject::Call call,
int _id,
void **arguments)
2675 if (call == QMetaObject::ReadProperty) {
2676 if (_id >= indexPropertyOffset) {
2677 Compositor::Group group = Compositor::Group(_id - indexPropertyOffset + 1);
2678 *
static_cast<
int *>(arguments[0]) = attached->m_currentIndex[group];
2680 }
else if (_id >= memberPropertyOffset) {
2681 Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
2685 }
else if (call == QMetaObject::WriteProperty) {
2686 if (_id >= memberPropertyOffset) {
2687 QQmlDelegateModel *delegateModel = metaType->delegateModel();
2691 Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
2692 const int groupFlag = 1 << group;
2694 if (member && !*
static_cast<
bool *>(arguments[0])) {
2695 Compositor::iterator it = model->m_compositor.find(
2696 group, attached->m_currentIndex[group]);
2697 model->removeGroups(it, 1, group, groupFlag);
2698 }
else if (!member && *
static_cast<
bool *>(arguments[0])) {
2699 for (qsizetype i = 1, end = metaType->groupCount(); i <= end; ++i) {
2700 if (attached->m_cacheItem->groups & (1 << i)) {
2701 Compositor::iterator it = model->m_compositor.find(
2702 Compositor::Group(i), attached->m_currentIndex[i]);
2703 model->addGroups(it, 1, Compositor::Group(i), groupFlag);
2711 return attached->qt_metacall(call, _id, arguments);
2718 QQml_setParent_noEvent(
this, parent);
2726 QQml_setParent_noEvent(
this, parent);
2729 std::copy(std::begin(m_currentIndex), std::end(m_currentIndex), std::begin(m_previousIndex));
2731 if (!cacheItem->metaType->attachedMetaObject)
2732 cacheItem->metaType->initializeAttachedMetaObject();
2734 QObjectPrivate::get(
this)->metaObject = cacheItem->metaType->attachedMetaObject.data();
2735 cacheItem->metaType->attachedMetaObject->addref();
2744 for (qsizetype i = 1, end = metaType->groupCount(); i <= end; ++i)
2745 m_currentIndex[i] = incubationTask->index[i];
2746 }
else if (QQmlDelegateModel *delegateModel = metaType->delegateModel()) {
2748 Compositor::iterator it = model->m_compositor.find(
2749 Compositor::Cache, model->m_cache.indexOf(m_cacheItem));
2750 for (qsizetype i = 1, end = metaType->groupCount(); i <= end; ++i)
2751 m_currentIndex[i] = it.index[i];
2757 setInGroup(QQmlListCompositor::Persisted, inPersisted);
2764 const uint groupFlag = (1 << QQmlListCompositor::Persisted);
2772 return m_cacheItem->groupIndex(QQmlListCompositor::Persisted);
2780 QQmlDelegateModel *delegateModel = m_cacheItem->metaType->delegateModel();
2785 const uint groupFlag = (1 << group);
2789 const int cacheIndex = model->m_cache.indexOf(
m_cacheItem);
2790 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2792 model->addGroups(it, 1, Compositor::Cache, groupFlag);
2794 model->removeGroups(it, 1, Compositor::Cache, groupFlag);
2800 setInGroup(QQmlListCompositor::Default, inItems);
2807 const uint groupFlag = (1 << QQmlListCompositor::Default);
2815 return m_cacheItem->groupIndex(QQmlListCompositor::Default);
2819
2820
2821
2822
2823
2824
2832
2833
2834
2835
2836
2837
2846 for (qsizetype i = 0, end = metaType->groupCount(); i < end; ++i) {
2847 if (m_cacheItem->groups & (1 << (i + 1)))
2848 groups.append(metaType->groupNames.at(i));
2858 QQmlDelegateModel *delegateModel = m_cacheItem->metaType->delegateModel();
2863 const int groupFlags = model->m_cacheMetaType->parseGroups(groups);
2864 const int cacheIndex = model->m_cache.indexOf(
m_cacheItem);
2865 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2866 model->setGroups(it, 1, Compositor::Cache, groupFlags);
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2886 return m_cacheItem->groups & Compositor::UnresolvedFlag;
2890
2891
2892
2893
2894
2895
2896
2897
2898
2901
2902
2903
2904
2905
2906
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2922
2923
2924
2925
2926
2927
2934 int indexChanges = 0;
2935 const qsizetype groupCount =
m_cacheItem->metaType->groupCount();
2936 for (qsizetype i = 1; i <= groupCount; ++i) {
2937 if (m_previousIndex[i] != m_currentIndex[i]) {
2938 m_previousIndex[i] = m_currentIndex[i];
2939 indexChanges |= (1 << i);
2947 const QMetaObject *meta = metaObject();
2948 for (qsizetype i = 1; i <= groupCount; ++i, ++notifierId) {
2949 if (groupChanges & (1 << i))
2950 QMetaObject::activate(
this, meta, notifierId,
nullptr);
2952 for (qsizetype i = 1; i <= groupCount; ++i, ++notifierId) {
2953 if (indexChanges & (1 << i))
2954 QMetaObject::activate(
this, meta, notifierId,
nullptr);
2958 emit groupsChanged();
2972 Q_Q(QQmlDelegateModelGroup);
2973 IS_SIGNAL_CONNECTED(q, QQmlDelegateModelGroup, changed, (
const QJSValue &,
const QJSValue &));
2978 Q_Q(QQmlDelegateModelGroup);
2979 if (isChangedConnected() && !changeSet.isEmpty()) {
2980 emit q->changed(QJSValuePrivate::fromReturnedValue(
2981 qdmEngineData(v4)->array(v4, changeSet.removes())),
2982 QJSValuePrivate::fromReturnedValue(
2983 qdmEngineData(v4)->array(v4, changeSet.inserts())));
2985 if (changeSet.difference() != 0)
2986 emit q->countChanged();
2991 for (QQmlDelegateModelGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
2992 it->emitModelUpdated(changeSet, reset);
3001 it->createdPackage(index, package);
3007 it->initPackage(index, package);
3013 it->destroyingPackage(package);
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
3048
3049
3050
3051
3052QQmlDelegateModelGroup::QQmlDelegateModelGroup(QObject *parent)
3053 : QObject(*
new QQmlDelegateModelGroupPrivate, parent)
3057QQmlDelegateModelGroup::QQmlDelegateModelGroup(
3058 const QString &name, QQmlDelegateModel *model,
int index, QObject *parent)
3059 : QQmlDelegateModelGroup(parent)
3061 Q_D(QQmlDelegateModelGroup);
3063 d->setModel(model, Compositor::Group(index));
3066QQmlDelegateModelGroup::~QQmlDelegateModelGroup() =
default;
3069
3070
3071
3072
3073
3074
3076QString QQmlDelegateModelGroup::name()
const
3078 Q_D(
const QQmlDelegateModelGroup);
3082void QQmlDelegateModelGroup::setName(
const QString &name)
3084 Q_D(QQmlDelegateModelGroup);
3087 if (d->name != name) {
3094
3095
3096
3097
3099int QQmlDelegateModelGroup::count()
const
3101 Q_D(
const QQmlDelegateModelGroup);
3104 return QQmlDelegateModelPrivate::get(d->model)->m_compositor.count(d->group);
3108
3109
3110
3111
3113bool QQmlDelegateModelGroup::defaultInclude()
const
3115 Q_D(
const QQmlDelegateModelGroup);
3116 return d->defaultInclude;
3119void QQmlDelegateModelGroup::setDefaultInclude(
bool include)
3121 Q_D(QQmlDelegateModelGroup);
3122 if (d->defaultInclude != include) {
3123 d->defaultInclude = include;
3127 QQmlDelegateModelPrivate::get(d->model)->m_compositor.setDefaultGroup(d->group);
3129 QQmlDelegateModelPrivate::get(d->model)->m_compositor.clearDefaultGroup(d->group);
3131 emit defaultIncludeChanged();
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3159QJSValue QQmlDelegateModelGroup::get(
int index)
3161 Q_D(QQmlDelegateModelGroup);
3165 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3166 if (!model->m_context || !model->m_context->isValid()) {
3168 }
else if (index < 0 || index >= model->m_compositor.count(d->group)) {
3169 qmlWarning(
this) << tr(
"get: index out of range");
3173 Compositor::iterator it = model->m_compositor.find(d->group, index);
3174 QQmlDelegateModelItem *cacheItem = it->inCache()
3175 ? model->m_cache.at(it.cacheIndex())
3179 cacheItem = model->m_adaptorModel.createItem(
3180 model->m_cacheMetaType, it.modelIndex());
3183 cacheItem->groups = it->flags;
3185 model->m_cache.insert(it.cacheIndex(), cacheItem);
3186 model->m_compositor.setFlags(it, 1, Compositor::CacheFlag);
3189 if (model->m_cacheMetaType->modelItemProto.isUndefined())
3190 model->m_cacheMetaType->initializePrototype();
3191 QV4::ExecutionEngine *v4 = model->m_cacheMetaType->v4Engine;
3192 QV4::Scope scope(v4);
3193 ++cacheItem->scriptRef;
3194 QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(cacheItem));
3195 QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
3196 o->setPrototypeOf(p);
3198 return QJSValuePrivate::fromReturnedValue(o->asReturnedValue());
3203 if (value.isNumber()) {
3204 *index = value.toInt32();
3208 if (!value.isObject())
3211 QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine();
3212 QV4::Scope scope(v4);
3213 QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
3217 if (QQmlDelegateModel *delegateModel = cacheItem->metaType->delegateModel()) {
3218 *index = QQmlDelegateModelPrivate::get(delegateModel)->m_cache.indexOf(cacheItem);
3219 *group = Compositor::Cache;
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3243void QQmlDelegateModelGroup::insert(QQmlV4FunctionPtr args)
3245 Q_D(QQmlDelegateModelGroup);
3246 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3248 int index = model->m_compositor.count(d->group);
3249 Compositor::Group group = d->group;
3251 if (args->length() == 0)
3255 QV4::Scope scope(args->v4engine());
3256 QV4::ScopedValue v(scope, (*args)[i]);
3257 if (d->parseIndex(v, &index, &group)) {
3258 if (index < 0 || index > model->m_compositor.count(group)) {
3259 qmlWarning(
this) << tr(
"insert: index out of range");
3262 if (++i == args->length())
3267 if (v->as<QV4::ArrayObject>())
3270 int groups = 1 << d->group;
3271 if (++i < args->length()) {
3272 QV4::ScopedValue val(scope, (*args)[i]);
3273 groups |= model->m_cacheMetaType->parseGroups(val);
3276 if (v->as<QV4::Object>()) {
3277 auto insertionResult = QQmlDelegateModelPrivate::InsertionResult::Retry;
3279 Compositor::insert_iterator before = index < model->m_compositor.count(group)
3280 ? model->m_compositor.findInsertPosition(group, index)
3281 : model->m_compositor.end();
3282 insertionResult = model->insert(before, v, groups);
3283 }
while (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Retry);
3284 if (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Success)
3285 model->emitChanges();
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3306void QQmlDelegateModelGroup::create(QQmlV4FunctionPtr args)
3308 Q_D(QQmlDelegateModelGroup);
3312 if (args->length() == 0)
3315 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3317 int index = model->m_compositor.count(d->group);
3318 Compositor::Group group = d->group;
3321 QV4::Scope scope(args->v4engine());
3322 QV4::ScopedValue v(scope, (*args)[i]);
3323 if (d->parseIndex(v, &index, &group))
3326 if (i < args->length() && index >= 0 && index <= model->m_compositor.count(group)) {
3328 if (v->as<QV4::Object>()) {
3329 int groups = 1 << d->group;
3330 if (++i < args->length()) {
3331 QV4::ScopedValue val(scope, (*args)[i]);
3332 groups |= model->m_cacheMetaType->parseGroups(val);
3335 auto insertionResult = QQmlDelegateModelPrivate::InsertionResult::Retry;
3337 Compositor::insert_iterator before = index < model->m_compositor.count(group)
3338 ? model->m_compositor.findInsertPosition(group, index)
3339 : model->m_compositor.end();
3341 index = before.index[d->group];
3344 insertionResult = model->insert(before, v, groups);
3345 }
while (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Retry);
3346 if (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Error)
3350 if (index < 0 || index >= model->m_compositor.count(group)) {
3351 qmlWarning(
this) << tr(
"create: index out of range");
3355 QObject *object = model->object(group, index, QQmlIncubator::AsynchronousIfNested);
3357 QVector<Compositor::Insert> inserts;
3358 Compositor::iterator it = model->m_compositor.find(group, index);
3359 model->m_compositor.setFlags(it, 1, d->group, Compositor::PersistedFlag, &inserts);
3360 model->itemsInserted(inserts);
3361 model->m_cache.at(it.cacheIndex())->releaseObject();
3364 args->setReturnValue(QV4::QObjectWrapper::wrap(args->v4engine(), object));
3365 model->emitChanges();
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384void QQmlDelegateModelGroup::resolve(QQmlV4FunctionPtr args)
3386 Q_D(QQmlDelegateModelGroup);
3390 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3392 if (args->length() < 2)
3397 Compositor::Group fromGroup = d->group;
3398 Compositor::Group toGroup = d->group;
3400 QV4::Scope scope(args->v4engine());
3401 QV4::ScopedValue v(scope, (*args)[0]);
3402 if (d->parseIndex(v, &from, &fromGroup)) {
3403 if (from < 0 || from >= model->m_compositor.count(fromGroup)) {
3404 qmlWarning(
this) << tr(
"resolve: from index out of range");
3408 qmlWarning(
this) << tr(
"resolve: from index invalid");
3413 if (d->parseIndex(v, &to, &toGroup)) {
3414 if (to < 0 || to >= model->m_compositor.count(toGroup)) {
3415 qmlWarning(
this) << tr(
"resolve: to index out of range");
3419 qmlWarning(
this) << tr(
"resolve: to index invalid");
3423 Compositor::iterator fromIt = model->m_compositor.find(fromGroup, from);
3424 Compositor::iterator toIt = model->m_compositor.find(toGroup, to);
3426 if (!fromIt->isUnresolved()) {
3427 qmlWarning(
this) << tr(
"resolve: from is not an unresolved item");
3431 qmlWarning(
this) << tr(
"resolve: to is not a model item");
3435 const int unresolvedFlags = fromIt->flags;
3436 const int resolvedFlags = toIt->flags;
3437 const int resolvedIndex = toIt.modelIndex();
3438 void *
const resolvedList = toIt->list;
3440 QQmlDelegateModelItem *cacheItem = model->m_cache.at(fromIt.cacheIndex());
3441 cacheItem->groups &= ~Compositor::UnresolvedFlag;
3443 if (toIt.cacheIndex() > fromIt.cacheIndex())
3444 toIt.decrementIndexes(1, unresolvedFlags);
3445 if (!toIt->inGroup(fromGroup) || toIt.index[fromGroup] > from)
3449 QVector<Compositor::Remove>(1, Compositor::Remove(fromIt, 1, unresolvedFlags, 0)),
3450 QVector<Compositor::Insert>(1, Compositor::Insert(toIt, 1, unresolvedFlags, 0)));
3451 model->itemsInserted(
3452 QVector<Compositor::Insert>(1, Compositor::Insert(toIt, 1, (resolvedFlags & ~unresolvedFlags) | Compositor::CacheFlag)));
3453 toIt.incrementIndexes(1, resolvedFlags | unresolvedFlags);
3454 model->itemsRemoved(QVector<Compositor::Remove>(1, Compositor::Remove(toIt, 1, resolvedFlags)));
3456 model->m_compositor.setFlags(toGroup, to, 1, unresolvedFlags & ~Compositor::UnresolvedFlag);
3457 model->m_compositor.clearFlags(fromGroup, from, 1, unresolvedFlags);
3459 if (resolvedFlags & Compositor::CacheFlag)
3460 model->m_compositor.insert(
3461 Compositor::Cache, toIt.cacheIndex(), resolvedList,
3462 resolvedIndex, 1, Compositor::CacheFlag);
3464 Q_ASSERT(model->m_cache.size() == model->m_compositor.count(Compositor::Cache));
3466 if (!cacheItem->isReferenced()) {
3467 Q_ASSERT(toIt.cacheIndex() == model->m_cache.indexOf(cacheItem));
3468 model->m_cache.removeAt(toIt.cacheIndex());
3469 model->m_compositor.clearFlags(
3470 Compositor::Cache, toIt.cacheIndex(), 1, Compositor::CacheFlag);
3472 Q_ASSERT(model->m_cache.size() == model->m_compositor.count(Compositor::Cache));
3474 cacheItem->resolveIndex(model->m_adaptorModel, resolvedIndex);
3475 if (QQmlDelegateModelAttached *attached = cacheItem->attached())
3476 attached->emitUnresolvedChanged();
3479 model->emitChanges();
3483
3484
3485
3486
3488void QQmlDelegateModelGroup::remove(QQmlV4FunctionPtr args)
3490 Q_D(QQmlDelegateModelGroup);
3493 Compositor::Group group = d->group;
3497 if (args->length() == 0)
3501 QV4::Scope scope(args->v4engine());
3502 QV4::ScopedValue v(scope, (*args)[0]);
3503 if (!d->parseIndex(v, &index, &group)) {
3504 qmlWarning(
this) << tr(
"remove: invalid index");
3508 if (++i < args->length()) {
3511 count = v->toInt32();
3514 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3515 if (index < 0 || index >= model->m_compositor.count(group)) {
3516 qmlWarning(
this) << tr(
"remove: index out of range");
3517 }
else if (count != 0) {
3518 Compositor::iterator it = model->m_compositor.find(group, index);
3519 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3520 qmlWarning(
this) << tr(
"remove: invalid count");
3522 model->removeGroups(it, count, d->group, 1 << d->group);
3528 QQmlV4FunctionPtr args, Compositor::Group *group,
int *index,
int *count,
int *groups)
const
3530 if (!model || !QQmlDelegateModelPrivate::get(model)->m_cacheMetaType)
3533 if (args->length() < 2)
3537 QV4::Scope scope(args->v4engine());
3538 QV4::ScopedValue v(scope, (*args)[i]);
3539 if (!parseIndex(v, index, group))
3543 if (v->isNumber()) {
3544 *count = v->toInt32();
3546 if (++i == args->length())
3551 *groups = QQmlDelegateModelPrivate::get(model)->m_cacheMetaType->parseGroups(v);
3557
3558
3559
3560
3562void QQmlDelegateModelGroup::addGroups(QQmlV4FunctionPtr args)
3564 Q_D(QQmlDelegateModelGroup);
3565 Compositor::Group group = d->group;
3570 if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
3573 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3574 if (index < 0 || index >= model->m_compositor.count(group)) {
3575 qmlWarning(
this) << tr(
"addGroups: index out of range");
3576 }
else if (count != 0) {
3577 Compositor::iterator it = model->m_compositor.find(group, index);
3578 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3579 qmlWarning(
this) << tr(
"addGroups: invalid count");
3581 model->addGroups(it, count, d->group, groups);
3587
3588
3589
3590
3592void QQmlDelegateModelGroup::removeGroups(QQmlV4FunctionPtr args)
3594 Q_D(QQmlDelegateModelGroup);
3595 Compositor::Group group = d->group;
3600 if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
3603 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3604 if (index < 0 || index >= model->m_compositor.count(group)) {
3605 qmlWarning(
this) << tr(
"removeGroups: index out of range");
3606 }
else if (count != 0) {
3607 Compositor::iterator it = model->m_compositor.find(group, index);
3608 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3609 qmlWarning(
this) << tr(
"removeGroups: invalid count");
3611 model->removeGroups(it, count, d->group, groups);
3617
3618
3619
3620
3621
3623void QQmlDelegateModelGroup::setGroups(QQmlV4FunctionPtr args)
3625 Q_D(QQmlDelegateModelGroup);
3626 Compositor::Group group = d->group;
3631 if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
3634 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3635 if (index < 0 || index >= model->m_compositor.count(group)) {
3636 qmlWarning(
this) << tr(
"setGroups: index out of range");
3637 }
else if (count != 0) {
3638 Compositor::iterator it = model->m_compositor.find(group, index);
3639 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3640 qmlWarning(
this) << tr(
"setGroups: invalid count");
3642 model->setGroups(it, count, d->group, groups);
3648
3649
3650
3651
3652
3653
3654
3655
3656
3658void QQmlDelegateModelGroup::move(QQmlV4FunctionPtr args)
3660 Q_D(QQmlDelegateModelGroup);
3662 if (args->length() < 2)
3665 Compositor::Group fromGroup = d->group;
3666 Compositor::Group toGroup = d->group;
3671 QV4::Scope scope(args->v4engine());
3672 QV4::ScopedValue v(scope, (*args)[0]);
3673 if (!d->parseIndex(v, &from, &fromGroup)) {
3674 qmlWarning(
this) << tr(
"move: invalid from index");
3679 if (!d->parseIndex(v, &to, &toGroup)) {
3680 qmlWarning(
this) << tr(
"move: invalid to index");
3684 if (args->length() > 2) {
3687 count = v->toInt32();
3690 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3693 qmlWarning(
this) << tr(
"move: invalid count");
3694 }
else if (from < 0 || from + count > model->m_compositor.count(fromGroup)) {
3695 qmlWarning(
this) << tr(
"move: from index out of range");
3696 }
else if (!model->m_compositor.verifyMoveTo(fromGroup, from, toGroup, to, count, d->group)) {
3697 qmlWarning(
this) << tr(
"move: to index out of range");
3698 }
else if (count > 0) {
3699 QVector<Compositor::Remove> removes;
3700 QVector<Compositor::Insert> inserts;
3702 model->m_compositor.move(fromGroup, from, toGroup, to, count, d->group, &removes, &inserts);
3703 model->itemsMoved(removes, inserts);
3704 model->emitChanges();
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3723QQmlPartsModel::QQmlPartsModel(QQmlDelegateModel *model,
const QString &part, QObject *parent)
3724 : QQmlInstanceModel(*
new QObjectPrivate, parent)
3727 , m_compositorGroup(Compositor::Cache)
3728 , m_inheritGroup(
true)
3731 if (d->m_cacheMetaType) {
3732 QQmlDelegateModelGroupPrivate::get(d->m_groups[1])->emitters.insert(
this);
3733 m_compositorGroup = Compositor::Default;
3746 return m_model->filterGroup();
3747 return m_filterGroup;
3752 if (QQmlDelegateModelPrivate::get(m_model)->m_transaction) {
3753 qmlWarning(
this) << tr(
"The group of a DelegateModel cannot be changed within onChanged");
3757 if (m_filterGroup != group || m_inheritGroup) {
3758 m_filterGroup = group;
3759 m_inheritGroup =
false;
3762 emit filterGroupChanged();
3768 if (!m_inheritGroup) {
3769 m_inheritGroup =
true;
3771 emit filterGroupChanged();
3778 if (!model->m_cacheMetaType)
3781 if (m_inheritGroup) {
3782 if (m_filterGroup == model->m_filterGroup)
3784 m_filterGroup = model->m_filterGroup;
3787 QQmlListCompositor::Group previousGroup = m_compositorGroup;
3788 m_compositorGroup = Compositor::Default;
3789 QQmlDelegateModelGroupPrivate::get(model->m_groups[Compositor::Default])->emitters.insert(
this);
3791 if (m_filterGroup == model->m_cacheMetaType->groupNames.at(i - 1)) {
3792 m_compositorGroup = Compositor::Group(i);
3797 QQmlDelegateModelGroupPrivate::get(model->m_groups[m_compositorGroup])->emitters.insert(
this);
3798 if (m_compositorGroup != previousGroup) {
3799 QVector<QQmlChangeSet::Change> removes;
3800 QVector<QQmlChangeSet::Change> inserts;
3801 model->m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
3803 QQmlChangeSet changeSet;
3804 changeSet.move(removes, inserts);
3805 if (!changeSet.isEmpty())
3806 emit modelUpdated(changeSet,
false);
3808 if (changeSet.difference() != 0)
3809 emit countChanged();
3814 Compositor::Group group,
const QQmlChangeSet &changeSet)
3816 if (!m_inheritGroup)
3819 m_compositorGroup = group;
3820 QQmlDelegateModelGroupPrivate::get(QQmlDelegateModelPrivate::get(m_model)->m_groups[m_compositorGroup])->emitters.insert(
this);
3822 if (!changeSet.isEmpty())
3823 emit modelUpdated(changeSet,
false);
3825 if (changeSet.difference() != 0)
3826 emit countChanged();
3828 emit filterGroupChanged();
3834 return model->m_delegate
3835 ? model->m_compositor.count(m_compositorGroup)
3841 return m_model->isValid();
3848 if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup)) {
3849 qWarning() <<
"DelegateModel::item: index out range" << index << model->m_compositor.count(m_compositorGroup);
3853 QObject *object = model->object(m_compositorGroup, index, incubationMode);
3855 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) {
3856 QObject *part = package->part(m_part);
3859 m_packaged.insert(part, package);
3863 model->release(object);
3866 qmlWarning(model->m_delegate) << tr(
"Delegate component must be Package type.");
3875 QQmlInstanceModel::ReleaseFlags flags;
3877 auto it = m_packaged.find(item);
3878 if (it != m_packaged.end()) {
3879 QQuickPackage *package = *it;
3881 flags = model->release(package);
3882 m_packaged.erase(it);
3883 if (!m_packaged.contains(item))
3884 flags &= ~Referenced;
3885 if (flags & Destroyed)
3886 QQmlDelegateModelPrivate::get(m_model)->emitDestroyingPackage(package);
3893 return QQmlDelegateModelPrivate::get(m_model)->variantValue(m_compositorGroup, index, role);
3899 model->m_adaptorModel.replaceWatchedRoles(m_watchedRoles, roles);
3900 m_watchedRoles = roles;
3906 Compositor::iterator it = model->m_compositor.find(model->m_compositorGroup, index);
3908 return QQmlIncubator::Null;
3910 if (
auto incubationTask = model->m_cache.at(it.cacheIndex())->incubationTask)
3911 return incubationTask->status();
3913 return QQmlIncubator::Ready;
3918 auto it = m_packaged.find(item);
3919 if (it != m_packaged.end()) {
3920 if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(*it))
3921 return cacheItem->groupIndex(m_compositorGroup);
3928 emit createdItem(index, package->part(m_part));
3933 if (m_modelUpdatePending)
3934 m_pendingPackageInitializations << index;
3936 emit initItem(index, package->part(m_part));
3941 QObject *item = package->part(m_part);
3942 Q_ASSERT(!m_packaged.contains(item));
3943 emit destroyingItem(item);
3948 m_modelUpdatePending =
false;
3949 emit modelUpdated(changeSet, reset);
3950 if (changeSet.difference() != 0)
3951 emit countChanged();
3954 QVector<
int> pendingPackageInitializations;
3955 qSwap(pendingPackageInitializations, m_pendingPackageInitializations);
3956 for (
int index : pendingPackageInitializations) {
3957 if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup))
3959 QObject *object = model->object(m_compositorGroup, index, QQmlIncubator::Asynchronous);
3960 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
3961 emit initItem(index, package->part(m_part));
3962 model->release(object);
3969 if (Q_UNLIKELY(m_reusableItemsPool.size() == QQmlReusableDelegateModelItemsPool::MaxSize))
3972 Q_ASSERT(m_reusableItemsPool.size() < QQmlReusableDelegateModelItemsPool::MaxSize);
4018 Q_ASSERT(modelItem->object);
4019 Q_ASSERT(modelItem->delegate);
4021 m_reusableItemsPool.push_back({modelItem, 0});
4023 qCDebug(lcItemViewDelegateRecycling)
4024 <<
"item:" << modelItem
4025 <<
"delegate:" << modelItem->delegate
4026 <<
"index:" << modelItem->modelIndex()
4027 <<
"row:" << modelItem->modelRow()
4028 <<
"column:" << modelItem->modelColumn()
4029 <<
"pool size:" << m_reusableItemsPool.size();
4038 for (
auto it = m_reusableItemsPool.cbegin(); it != m_reusableItemsPool.cend(); ++it) {
4040 if (modelItem->delegate != delegate)
4042 m_reusableItemsPool.erase(it);
4044 qCDebug(lcItemViewDelegateRecycling)
4045 <<
"item:" << modelItem
4046 <<
"delegate:" << delegate
4047 <<
"old index:" << modelItem->modelIndex()
4048 <<
"old row:" << modelItem->modelRow()
4049 <<
"old column:" << modelItem->modelColumn()
4050 <<
"new index:" << newIndexHint
4051 <<
"pool size:" << m_reusableItemsPool.size();
4056 qCDebug(lcItemViewDelegateRecycling)
4057 <<
"no available item for delegate:" << delegate
4058 <<
"new index:" << newIndexHint
4059 <<
"pool size:" << m_reusableItemsPool.size();
4072 qCDebug(lcItemViewDelegateRecycling) <<
"pool size before drain:" << m_reusableItemsPool.size();
4074 if (maxPoolTime == 0) {
4076 const std::vector<PoolItem> removed = std::exchange(m_reusableItemsPool, {});
4077 for (
const PoolItem &item : removed)
4078 releaseItem(item.item);
4079 qCDebug(lcItemViewDelegateRecycling) <<
"pool size after drain: 0";
4083 const auto begin = m_reusableItemsPool.begin();
4084 const auto oldEnd = m_reusableItemsPool.end();
4085 const auto newEnd = std::stable_partition(
4087 [maxPoolTime](
const PoolItem &item) {
return item.poolTime < maxPoolTime; });
4088 std::for_each(begin, newEnd, [](PoolItem &item) { ++item.poolTime; });
4090 QVarLengthArray<PoolItem> removed;
4091 removed.reserve(oldEnd - newEnd);
4092 std::move(newEnd, oldEnd, std::back_inserter(removed));
4093 m_reusableItemsPool.erase(newEnd, oldEnd);
4095 for (
const PoolItem &item : removed)
4096 releaseItem(item.item);
4098 qCDebug(lcItemViewDelegateRecycling) <<
"pool size after drain:" << m_reusableItemsPool.size();
4194 this->changes =
new QVector<QQmlChangeSet::Change>(changes);
4195 QV4::Scope scope(internalClass->engine);
4196 QV4::ScopedObject o(scope,
this);
4197 o->setArrayType(QV4::Heap::ArrayData::Custom);
4204 QV4::Scope scope(v4);
4206 QV4::ScopedObject proto(scope, v4->newObject());
4207 proto->defineAccessorProperty(QStringLiteral(
"index"), QQmlDelegateModelGroupChange::method_get_index,
nullptr);
4208 proto->defineAccessorProperty(QStringLiteral(
"count"), QQmlDelegateModelGroupChange::method_get_count,
nullptr);
4209 proto->defineAccessorProperty(QStringLiteral(
"moveId"), QQmlDelegateModelGroupChange::method_get_moveId,
nullptr);
4210 changeProto.set(v4, proto);
4218 const QVector<QQmlChangeSet::Change> &changes)
4220 QV4::Scope scope(v4);
4221 QV4::ScopedObject o(scope, QQmlDelegateModelGroupChangeArray::create(v4, changes));
4222 return o.asReturnedValue();
4227#include "moc_qqmldelegatemodel_p_p.cpp"
4229#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)
Combined button and popup list for selecting options.
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