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 QList<QQmlChangeSet::Change> &changes);
87 QV4::ExecutionEngine *engine, uint flag,
90 QV4::Heap::FunctionObject::init(engine, QStringLiteral(
"DelegateModelGroupFunction"));
108 const QList<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 cacheItem->destroyObject();
238 cacheItem->removeGroups(Compositor::UnresolvedFlag);
239 cacheItem->clearObjectWeakReferences();
241 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask()) {
242 d->releaseIncubator(incubationTask);
243 incubationTask->vdm =
nullptr;
244 cacheItem->clearIncubationTask();
247 if (!cacheItem->isScriptReferenced())
253void QQmlDelegateModel::classBegin()
255 Q_D(QQmlDelegateModel);
257 d->m_context = qmlContext(
this);
260void QQmlDelegateModel::componentComplete()
262 Q_D(QQmlDelegateModel);
263 d->m_complete =
true;
265 int defaultGroups = 0;
266 QStringList groupNames;
267 groupNames.append(QStringLiteral(
"items"));
268 groupNames.append(QStringLiteral(
"persistedItems"));
269 if (QQmlDelegateModelGroupPrivate::get(d->m_items)->defaultInclude)
270 defaultGroups |= Compositor::DefaultFlag;
271 if (QQmlDelegateModelGroupPrivate::get(d->m_persistedItems)->defaultInclude)
272 defaultGroups |= Compositor::PersistedFlag;
273 for (
int i = Compositor::MinimumGroupCount; i < d->m_groupCount; ++i) {
274 QString name = d->m_groups[i]->name();
275 if (name.isEmpty()) {
276 d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
279 }
else if (name.at(0).isUpper()) {
280 qmlWarning(d->m_groups[i]) << QQmlDelegateModelGroup::tr(
"Group names must start with a lower case letter");
281 d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
285 groupNames.append(name);
287 QQmlDelegateModelGroupPrivate *group = QQmlDelegateModelGroupPrivate::get(d->m_groups[i]);
288 group->setModel(
this, Compositor::Group(i));
289 if (group->defaultInclude)
290 defaultGroups |= (1 << i);
294 d->m_cacheMetaType = QQml::makeRefPointer<QQmlDelegateModelItemMetaType>(
295 d->m_context->engine()->handle(),
this, groupNames);
297 d->m_compositor.setGroupCount(d->m_groupCount);
298 d->m_compositor.setDefaultGroups(defaultGroups);
299 d->updateFilterGroup();
301 while (!d->m_pendingParts.isEmpty())
302 static_cast<QQmlPartsModel *>(d->m_pendingParts.first())->updateFilterGroup();
304 QList<Compositor::Insert> inserts;
305 d->m_count = d->adaptorModelCount();
306 d->m_compositor.append(
310 defaultGroups | Compositor::AppendFlag | Compositor::PrependFlag,
312 d->itemsInserted(inserts);
314 d->requestMoreIfNecessary();
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332QVariant QQmlDelegateModel::model()
const
334 Q_D(
const QQmlDelegateModel);
335 return d->m_adaptorModel.model();
340 Q_Q(QQmlDelegateModel);
341 if (!m_adaptorModel.adaptsAim())
344 auto aim = m_adaptorModel.aim();
346 QObject::connect(aim, &QAbstractItemModel::rowsInserted, q, &QQmlDelegateModel::_q_rowsInserted);
347 QObject::connect(aim, &QAbstractItemModel::rowsRemoved, q, &QQmlDelegateModel::_q_rowsRemoved);
348 QObject::connect(aim, &QAbstractItemModel::rowsAboutToBeRemoved, q, &QQmlDelegateModel::_q_rowsAboutToBeRemoved);
349 QObject::connect(aim, &QAbstractItemModel::columnsInserted, q, &QQmlDelegateModel::_q_columnsInserted);
350 QObject::connect(aim, &QAbstractItemModel::columnsRemoved, q, &QQmlDelegateModel::_q_columnsRemoved);
351 QObject::connect(aim, &QAbstractItemModel::columnsMoved, q, &QQmlDelegateModel::_q_columnsMoved);
352 QObject::connect(aim, &QAbstractItemModel::dataChanged, q, &QQmlDelegateModel::_q_dataChanged);
353 QObject::connect(aim, &QAbstractItemModel::rowsMoved, q, &QQmlDelegateModel::_q_rowsMoved);
354 QObject::connect(aim, &QAbstractItemModel::modelAboutToBeReset, q, &QQmlDelegateModel::_q_modelAboutToBeReset);
355 QObject::connect(aim, &QAbstractItemModel::layoutChanged, q, &QQmlDelegateModel::_q_layoutChanged);
360 Q_Q(QQmlDelegateModel);
361 if (!m_adaptorModel.adaptsAim())
364 auto aim = m_adaptorModel.aim();
366 QObject::disconnect(aim, &QAbstractItemModel::rowsInserted, q, &QQmlDelegateModel::_q_rowsInserted);
367 QObject::disconnect(aim, &QAbstractItemModel::rowsAboutToBeRemoved, q, &QQmlDelegateModel::_q_rowsAboutToBeRemoved);
368 QObject::disconnect(aim, &QAbstractItemModel::rowsRemoved, q, &QQmlDelegateModel::_q_rowsRemoved);
369 QObject::disconnect(aim, &QAbstractItemModel::columnsInserted, q, &QQmlDelegateModel::_q_columnsInserted);
370 QObject::disconnect(aim, &QAbstractItemModel::columnsRemoved, q, &QQmlDelegateModel::_q_columnsRemoved);
371 QObject::disconnect(aim, &QAbstractItemModel::columnsMoved, q, &QQmlDelegateModel::_q_columnsMoved);
372 QObject::disconnect(aim, &QAbstractItemModel::dataChanged, q, &QQmlDelegateModel::_q_dataChanged);
373 QObject::disconnect(aim, &QAbstractItemModel::rowsMoved, q, &QQmlDelegateModel::_q_rowsMoved);
374 QObject::disconnect(aim, &QAbstractItemModel::modelAboutToBeReset, q, &QQmlDelegateModel::_q_modelAboutToBeReset);
375 QObject::disconnect(aim, &QAbstractItemModel::layoutChanged, q, &QQmlDelegateModel::_q_layoutChanged);
378void QQmlDelegateModel::setModel(
const QVariant &model)
380 Q_D(QQmlDelegateModel);
382 if (d->m_adaptorModel.model() == model)
386 _q_itemsRemoved(0, d->m_count);
388 d->disconnectFromAbstractItemModel();
389 d->m_adaptorModel.setModel(model);
390 d->connectToAbstractItemModel();
392 d->m_adaptorModel.replaceWatchedRoles(QList<QByteArray>(), d->m_watchedRoles);
393 for (
int i = 0; d->m_parts && i < d->m_parts->models.size(); ++i) {
394 d->m_adaptorModel.replaceWatchedRoles(
395 QList<QByteArray>(), d->m_parts->models.at(i)->watchedRoles());
399 _q_itemsInserted(0, d->adaptorModelCount());
400 d->requestMoreIfNecessary();
411 if (d->m_adaptorModel.adaptsAim()) {
412 auto *aim = d->m_adaptorModel.aim();
413 auto *aimPrivate = QAbstractItemModelPrivate::get(aim);
414 if (aimPrivate->resetting)
415 QObject::connect(aim, &QAbstractItemModel::modelReset,
this, &QQmlDelegateModel::handleModelReset, Qt::SingleShotConnection);
422
423
424
425
426
427
428QQmlComponent *QQmlDelegateModel::delegate()
const
430 Q_D(
const QQmlDelegateModel);
431 return d->m_delegate;
434void QQmlDelegateModel::setDelegate(QQmlComponent *delegate)
436 Q_D(QQmlDelegateModel);
437 if (d->m_transaction) {
438 qmlWarning(
this) << tr(
"The delegate of a DelegateModel cannot be changed within onUpdated.");
441 if (d->m_delegate == delegate)
444 _q_itemsRemoved(0, d->m_count);
445 d->m_delegate.setObject(delegate,
this);
446 d->m_delegateValidated =
false;
447 if (d->m_delegateChooser)
448 QObject::disconnect(d->m_delegateChooserChanged);
450 d->m_delegateChooser =
nullptr;
452 QQmlAbstractDelegateComponent *adc =
453 qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
455 d->m_delegateChooser = adc;
456 d->m_delegateChooserChanged = connect(adc, &QQmlAbstractDelegateComponent::delegateChanged,
this,
457 [d](){ d->delegateChanged(); });
461 _q_itemsInserted(0, d->adaptorModelCount());
462 d->requestMoreIfNecessary();
464 emit delegateChanged();
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495QVariant QQmlDelegateModel::rootIndex()
const
497 Q_D(
const QQmlDelegateModel);
498 return QVariant::fromValue(QModelIndex(d->m_adaptorModel.rootIndex));
501void QQmlDelegateModel::setRootIndex(
const QVariant &root)
503 Q_D(QQmlDelegateModel);
505 QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
506 const bool changed = d->m_adaptorModel.rootIndex != modelIndex;
507 if (changed || !d->m_adaptorModel.isValid()) {
508 const int oldCount = d->m_count;
509 d->m_adaptorModel.rootIndex = modelIndex;
510 if (!d->m_adaptorModel.isValid() && d->m_adaptorModel.aim()) {
512 d->disconnectFromAbstractItemModel();
513 d->m_adaptorModel.setModel(d->m_adaptorModel.list.list());
514 d->connectToAbstractItemModel();
516 if (d->m_adaptorModel.canFetchMore())
517 d->m_adaptorModel.fetchMore();
519 const int newCount = d->adaptorModelCount();
521 _q_itemsRemoved(0, oldCount);
523 _q_itemsInserted(0, newCount);
526 emit rootIndexChanged();
531
532
533
534
535
536QQmlDelegateModel::DelegateModelAccess QQmlDelegateModel::delegateModelAccess()
const
538 Q_D(
const QQmlDelegateModel);
539 return d->m_adaptorModel.delegateModelAccess;
542void QQmlDelegateModel::setDelegateModelAccess(
543 QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
545 Q_D(QQmlDelegateModel);
546 if (d->m_adaptorModel.delegateModelAccess == delegateModelAccess)
549 if (d->m_transaction) {
550 qmlWarning(
this) << tr(
"The delegateModelAccess of a DelegateModel "
551 "cannot be changed within onUpdated.");
556 _q_itemsRemoved(0, d->m_count);
557 d->m_adaptorModel.delegateModelAccess = delegateModelAccess;
558 _q_itemsInserted(0, d->adaptorModelCount());
559 d->requestMoreIfNecessary();
561 d->m_adaptorModel.delegateModelAccess = delegateModelAccess;
564 emit delegateModelAccessChanged();
568
569
570
571
572
573
574
575
576
577
578
579QVariant QQmlDelegateModel::modelIndex(
int idx)
const
581 Q_D(
const QQmlDelegateModel);
582 return d->m_adaptorModel.modelIndex(idx);
586
587
588
589
590
591
592
593
594
595
596
597QVariant QQmlDelegateModel::parentModelIndex()
const
599 Q_D(
const QQmlDelegateModel);
600 return d->m_adaptorModel.parentModelIndex();
604
605
607int QQmlDelegateModel::count()
const
609 Q_D(
const QQmlDelegateModel);
612 return d->m_compositor.count(d->m_compositorGroup);
618 return QQmlDelegateModel::ReleaseFlags{};
622 return QQmlDelegateModel::ReleaseFlags{};
624 if (!cacheItem->releaseObjectWeak())
625 return QQmlDelegateModel::Referenced;
627 if (reusableFlag == QQmlInstanceModel::Reusable && m_reusableItemsPool.insertItem(cacheItem)) {
629 emit q_func()->itemPooled(cacheItem->modelIndex(), cacheItem->object());
630 return QQmlInstanceModel::Pooled;
634 return QQmlInstanceModel::Destroyed;
639 if (QObject *object = cacheItem->object()) {
640 emitDestroyingItem(object);
652
653
654QQmlDelegateModel::ReleaseFlags QQmlDelegateModel::release(QObject *item, QQmlInstanceModel::ReusableFlag reusableFlag)
656 Q_D(QQmlDelegateModel);
657 QQmlInstanceModel::ReleaseFlags stat = d->release(item, reusableFlag);
662void QQmlDelegateModel::cancel(
int index)
664 Q_D(QQmlDelegateModel);
665 if (index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
666 qWarning() <<
"DelegateModel::cancel: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
670 Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
671 QQmlDelegateModelItem *cacheItem = it->inCache() ? d->m_cache.at(it.cacheIndex()) : 0;
673 if (cacheItem->incubationTask() && !cacheItem->isObjectReferenced()) {
674 d->releaseIncubator(cacheItem->incubationTask());
675 cacheItem->clearIncubationTask();
677 if (QObject *object = cacheItem->object()) {
678 cacheItem->destroyObjectLater();
679 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
680 d->emitDestroyingPackage(package);
682 d->emitDestroyingItem(object);
685 if (!cacheItem->isScriptReferenced() && !cacheItem->object()) {
686 d->m_compositor.clearFlags(
687 Compositor::Cache, it.cacheIndex(), 1, Compositor::CacheFlag);
688 d->m_cache.removeAt(it.cacheIndex());
690 Q_ASSERT(d->m_cache.size() == d->m_compositor.count(Compositor::Cache));
696 QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group)
701 if (d->m_groupCount == Compositor::MaximumGroupCount) {
702 qmlWarning(d->q_func()) << QQmlDelegateModel::tr(
"The maximum number of supported DelegateModelGroups is 8");
710 QQmlListProperty<QQmlDelegateModelGroup> *property)
717 QQmlListProperty<QQmlDelegateModelGroup> *property, qsizetype index)
721 ? d->m_groups[index + 1]
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
753QQmlListProperty<QQmlDelegateModelGroup> QQmlDelegateModel::groups()
755 Q_D(QQmlDelegateModel);
756 return QQmlListProperty<QQmlDelegateModelGroup>(
759 QQmlDelegateModelPrivate::group_append,
760 QQmlDelegateModelPrivate::group_count,
761 QQmlDelegateModelPrivate::group_at,
762 nullptr,
nullptr,
nullptr);
766
767
768
769
771QQmlDelegateModelGroup *QQmlDelegateModel::items()
773 Q_D(QQmlDelegateModel);
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
794QQmlDelegateModelGroup *QQmlDelegateModel::persistedItems()
796 Q_D(QQmlDelegateModel);
797 return d->m_persistedItems;
801
802
803
804
805
806
807
808
810QString QQmlDelegateModel::filterGroup()
const
812 Q_D(
const QQmlDelegateModel);
813 return d->m_filterGroup;
816void QQmlDelegateModel::setFilterGroup(
const QString &group)
818 Q_D(QQmlDelegateModel);
820 if (d->m_transaction) {
821 qmlWarning(
this) << tr(
"The group of a DelegateModel cannot be changed within onChanged");
825 if (d->m_filterGroup != group) {
826 d->m_filterGroup = group;
827 d->updateFilterGroup();
828 emit filterGroupChanged();
832void QQmlDelegateModel::resetFilterGroup()
834 setFilterGroup(QStringLiteral(
"items"));
839 Q_Q(QQmlDelegateModel);
840 if (!m_cacheMetaType)
843 QQmlListCompositor::Group previousGroup = m_compositorGroup;
844 m_compositorGroup = Compositor::Default;
846 if (m_filterGroup == m_cacheMetaType->groupNames.at(i - 1)) {
847 m_compositorGroup = Compositor::Group(i);
852 QQmlDelegateModelGroupPrivate::get(m_groups[m_compositorGroup])->emitters.insert(
this);
853 if (m_compositorGroup != previousGroup) {
854 QList<QQmlChangeSet::Change> removes;
855 QList<QQmlChangeSet::Change> inserts;
856 m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
858 QQmlChangeSet changeSet;
859 changeSet.move(removes, inserts);
860 emit q->modelUpdated(changeSet,
false);
862 if (changeSet.difference() != 0)
863 emit q->countChanged();
866 auto partsCopy =
m_parts->models;
867 for (QQmlPartsModel *model : std::as_const(partsCopy))
868 model->updateFilterGroup(m_compositorGroup, changeSet);
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
901QObject *QQmlDelegateModel::parts()
903 Q_D(QQmlDelegateModel);
905 d->m_parts =
new QQmlDelegateModelParts(
this);
909const QAbstractItemModel *QQmlDelegateModel::abstractItemModel()
const
911 Q_D(
const QQmlDelegateModel);
912 return d->m_adaptorModel.adaptsAim() ? d->m_adaptorModel.aim() :
nullptr;
917 for (
int i = 1; i < m_groupCount; ++i)
918 QQmlDelegateModelGroupPrivate::get(m_groups[i])->createdPackage(incubationTask->index[i], package);
923 for (
int i = 1; i < m_groupCount; ++i)
924 QQmlDelegateModelGroupPrivate::get(m_groups[i])->initPackage(incubationTask->index[i], package);
929 for (
int i = 1; i < m_groupCount; ++i)
930 QQmlDelegateModelGroupPrivate::get(m_groups[i])->destroyingPackage(package);
935 return status == QQmlIncubator::Ready || status == QQmlIncubator::Error;
998 QObject *targetObject =
nullptr;
999 RequiredProperties *requiredProperties =
nullptr;
1006 QQmlDelegateModel::DelegateModelAccess access)
1010 QQmlData *d = QQmlData::get(object);
1011 if (
auto contextData = d ? d->context :
nullptr)
1012 contextData->setExtraObject(modelItemToIncubate);
1014 Q_ASSERT(modelItemToIncubate->delegate());
1015 const bool isBound = QQmlComponentPrivate::get(modelItemToIncubate->delegate())->isBound();
1017 auto incubatorPriv = QQmlIncubatorPrivate::get(
this);
1018 if (incubatorPriv->hadTopLevelRequiredProperties()) {
1024 incubating->contextData()->setContextObject(
nullptr);
1027 proxyContext->setContextObject(
nullptr);
1033 const QMetaObject *qmlMetaObject = modelItemToIncubate->metaObject();
1035 RequiredProperties *requiredProperties = incubatorPriv->requiredProperties();
1036 if (requiredProperties->empty())
1040 QQmlEnginePrivate::get(incubatorPriv->enginePriv),
1041 object, requiredProperties, access);
1051 initializer(qmlMetaObject, modelItemToIncubate);
1053 auto delegateModelItemSubclassMO = qmlMetaObject->superClass();
1054 initializer(delegateModelItemSubclassMO, modelItemToIncubate);
1056 while (strcmp(delegateModelItemSubclassMO->className(),
1057 modelItemToIncubate->staticMetaObject.className())) {
1058 delegateModelItemSubclassMO = delegateModelItemSubclassMO->superClass();
1059 initializer(delegateModelItemSubclassMO, modelItemToIncubate);
1063 initializer(proxiedObject->metaObject(), proxiedObject.data());
1071 modelItemToIncubate->contextData()->setContextObject(modelItemToIncubate);
1073 proxyContext->setContextObject(proxiedObject);
1080 modelItemToIncubate->metaObject();
1087 vdm->incubatorStatusChanged(
this, status);
1088 }
else if (isDoneIncubating(status)) {
1098 Q_Q(QQmlDelegateModel);
1099 if (!incubationTask->isError())
1100 incubationTask->clear();
1101 m_finishedIncubating.append(incubationTask);
1104 QCoreApplication::postEvent(q,
new QEvent(QEvent::User));
1110 Q_ASSERT(item->object());
1119 const bool alwaysEmit =
true;
1125 auto const updateAllRoles = QList<
int>();
1126 m_adaptorModel.notify(itemAsList, newModelIndex, 1, updateAllRoles);
1129 qmlAttachedPropertiesObject<QQmlDelegateModel>(item->object(),
false))) {
1139 emit q_func()->itemReused(newModelIndex, item->object());
1144 m_reusableItemsPool.drain(maxPoolTime, [
this](QQmlDelegateModelItem *cacheItem){ destroyCacheItem(cacheItem); });
1147void QQmlDelegateModel::drainReusableItemsPool(
int maxPoolTime)
1149 d_func()->drainReusableItemsPool(maxPoolTime);
1152int QQmlDelegateModel::poolSize()
1154 return d_func()->m_reusableItemsPool.size();
1159 if (!m_delegateChooser)
1162 QQmlComponent *delegate =
nullptr;
1166 delegate = chooser->delegate(&m_adaptorModel, index);
1167 chooser = qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
1175 m_cache.insert(it.cacheIndex(), item);
1176 m_compositor.setFlags(it, 1, Compositor::CacheFlag);
1177 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1182 int cidx = m_cache.lastIndexOf(cacheItem);
1184 m_compositor.clearFlags(Compositor::Cache, cidx, 1, Compositor::CacheFlag);
1185 m_cache.removeAt(cidx);
1187 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1192 if (!isDoneIncubating(status))
1195 const QList<QQmlError> incubationTaskErrors = incubationTask->errors();
1202 QObject *object = cacheItem->object();
1203 if (status == QQmlIncubator::Ready) {
1204 QQmlDelegateModelItem::ObjectReference guard(cacheItem);
1205 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
1208 emitCreatedItem(incubationTask, object);
1209 }
else if (status == QQmlIncubator::Error) {
1210 qmlInfo(m_delegate, incubationTaskErrors + m_delegate->errors()) <<
"Cannot create delegate";
1214 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
1217 emitDestroyingItem(object);
1229 vdm->setInitialState(
this, o);
1240 incubationTask->initializeRequiredProperties(
1241 incubationTask
->incubating, o, m_adaptorModel.delegateModelAccess);
1242 cacheItem->setObject(o);
1244 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(o))
1247 emitInitItem(incubationTask, o);
1252 if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
1253 qWarning() <<
"DelegateModel::item: index out range" << index << m_compositor.count(group);
1255 }
else if (!m_context || !m_context->isValid()) {
1259 Compositor::iterator it = m_compositor.find(group, index);
1260 const auto flags = it->flags;
1261 const auto modelIndex = it.modelIndex();
1265 if (!cacheItem || !cacheItem->delegate()) {
1266 QQmlComponent *delegate = resolveDelegate(modelIndex);
1271 cacheItem = m_reusableItemsPool.takeItem(delegate, index);
1276 addCacheItem(cacheItem, it);
1279 if (index == m_compositor.count(group) - 1)
1281 return cacheItem->referenceObjectWeak();
1285 cacheItem = m_adaptorModel.createItem(m_cacheMetaType, modelIndex);
1290 addCacheItem(cacheItem, it);
1293 cacheItem->setDelegate(delegate);
1300 QQmlDelegateModelItem::ObjectReference objectRef(cacheItem);
1303 bool sync = (incubationMode == QQmlIncubator::Synchronous
1304 || incubationMode == QQmlIncubator::AsynchronousIfNested);
1305 if (sync && incubationTask->incubationMode() == QQmlIncubator::Asynchronous) {
1307 incubationTask->forceCompletion();
1309 }
else if (!cacheItem->object()) {
1310 QQmlContext *creationContext = cacheItem->delegate()->creationContext();
1315 incubationTask->clear();
1318 incubationTask->index[i] = it.index[i];
1320 const QQmlRefPointer<QQmlContextData> componentContext
1321 = QQmlContextData::get(creationContext ? creationContext : m_context.data());
1322 QQmlComponentPrivate *cp = QQmlComponentPrivate::get(cacheItem->delegate());
1324 if (cp->isBound()) {
1325 cacheItem->setContextData(componentContext);
1329 if (m_adaptorModel.hasProxyObject())
1330 cacheItem->initProxy();
1333 incubationTask, cacheItem->delegate(), m_context->engine(),
1334 componentContext, QQmlContextData::get(m_context));
1336 QQmlRefPointer<QQmlContextData> ctxt
1337 = QQmlContextData::createRefCounted(componentContext);
1338 ctxt->setContextObject(cacheItem);
1339 cacheItem->setContextData(ctxt);
1343 if (m_adaptorModel.hasProxyObject()) {
1344 if (m_adaptorModel.delegateModelAccess == QQmlDelegateModel::ReadOnly)
1345 cacheItem->initProxy();
1347 ctxt = cacheItem->initProxy();
1352 ctxt, QQmlContextData::get(m_context));
1356 if (index == m_compositor.count(group) - 1)
1360 if (cacheItem->object()) {
1362 if (!incubationTask || isDoneIncubating(incubationTask->status()))
1363 return cacheItem->referenceObjectWeak();
1371 Q_ASSERT(!cacheItem->object());
1381
1382
1383
1384
1385
1386
1387
1388QObject *QQmlDelegateModel::object(
int index, QQmlIncubator::IncubationMode incubationMode)
1390 Q_D(QQmlDelegateModel);
1391 if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
1392 qWarning() <<
"DelegateModel::item: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
1396 return d->object(d->m_compositorGroup, index, incubationMode);
1399QQmlIncubator::Status QQmlDelegateModel::incubationStatus(
int index)
1401 Q_D(QQmlDelegateModel);
1402 if (d->m_compositor.count(d->m_compositorGroup) <= index)
1403 return QQmlIncubator::Null;
1404 Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
1406 return QQmlIncubator::Null;
1408 if (
auto incubationTask = d->m_cache.at(it.cacheIndex())->incubationTask())
1409 return incubationTask->status();
1411 return QQmlIncubator::Ready;
1416 Compositor::iterator it = m_compositor.find(group, index);
1417 if (QQmlAdaptorModel *model = it.list<QQmlAdaptorModel>()) {
1418 QString role = name;
1419 int dot = name.indexOf(QLatin1Char(
'.'));
1421 role = name.left(dot);
1422 QVariant value = model->value(it.modelIndex(), role);
1424 const int from = dot + 1;
1425 dot = name.indexOf(QLatin1Char(
'.'), from);
1426 QStringView propertyName = QStringView{name}.mid(from, dot - from);
1427 if (QObject *obj = qvariant_cast<QObject*>(value)) {
1428 value = obj->property(propertyName.toUtf8());
1429 }
else if (
const QMetaObject *metaObject = QQmlMetaType::metaObjectForValueType(value.metaType())) {
1431 const int propertyIndex = metaObject->indexOfProperty(propertyName.toUtf8());
1432 if (propertyIndex >= 0)
1433 value = metaObject->property(propertyIndex).readOnGadget(value.constData());
1443QVariant QQmlDelegateModel::variantValue(
int index,
const QString &role)
1445 Q_D(QQmlDelegateModel);
1446 return d->variantValue(d->m_compositorGroup, index, role);
1449int QQmlDelegateModel::indexOf(QObject *item, QObject *)
const
1451 Q_D(
const QQmlDelegateModel);
1452 if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(item))
1453 return cacheItem->groupIndex(d->m_compositorGroup);
1457void QQmlDelegateModel::setWatchedRoles(
const QList<QByteArray> &roles)
1459 Q_D(QQmlDelegateModel);
1460 d->m_adaptorModel.replaceWatchedRoles(d->m_watchedRoles, roles);
1461 d->m_watchedRoles = roles;
1465 Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags)
1467 QList<Compositor::Insert> inserts;
1468 m_compositor.setFlags(from, count, group, groupFlags, &inserts);
1469 itemsInserted(inserts);
1474 Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags)
1476 QList<Compositor::Remove> removes;
1477 m_compositor.clearFlags(from, count, group, groupFlags, &removes);
1478 itemsRemoved(removes);
1483 Compositor::iterator from,
int count, Compositor::Group group,
int groupFlags)
1485 QList<Compositor::Remove> removes;
1486 QList<Compositor::Insert> inserts;
1488 m_compositor.setFlags(from, count, group, groupFlags, &inserts);
1489 itemsInserted(inserts);
1490 const int removeFlags = ~groupFlags & Compositor::GroupMask;
1492 from = m_compositor.find(from.group, from.index[from.group]);
1493 m_compositor.clearFlags(from, count, group, removeFlags, &removes);
1494 itemsRemoved(removes);
1498bool QQmlDelegateModel::event(QEvent *e)
1500 Q_D(QQmlDelegateModel);
1501 if (e->type() == QEvent::UpdateRequest) {
1502 d->m_waitingToFetchMore =
false;
1503 d->m_adaptorModel.fetchMore();
1504 }
else if (e->type() == QEvent::User) {
1505 d->m_incubatorCleanupScheduled =
false;
1506 qDeleteAll(d->m_finishedIncubating);
1507 d->m_finishedIncubating.clear();
1509 return QQmlInstanceModel::event(e);
1517 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedChanges(m_groupCount);
1519 for (
const Compositor::Change &change : changes) {
1520 for (
int i = 1; i < m_groupCount; ++i) {
1521 if (change.inGroup(i)) {
1522 translatedChanges[i].append(QQmlChangeSet::Change(change.index[i], change.count));
1527 for (
int i = 1; i < m_groupCount; ++i)
1528 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.change(translatedChanges.at(i));
1531void QQmlDelegateModel::_q_itemsChanged(
int index,
int count,
const QList<
int> &roles)
1533 Q_D(QQmlDelegateModel);
1534 if (count <= 0 || !d->m_complete)
1537 if (d->m_adaptorModel.notify(d->m_cache, index, count, roles)) {
1538 QList<Compositor::Change> changes;
1539 d->m_compositor.listItemsChanged(&d->m_adaptorModel, index, count, &changes);
1540 d->itemsChanged(changes);
1543 const bool needToCheckDelegateChoiceInvalidation = d->m_delegateChooser && !roles.isEmpty();
1544 if (!needToCheckDelegateChoiceInvalidation)
1549 if (!d->m_adaptorModel.adaptsAim())
1552 const auto aim = d->m_adaptorModel.aim();
1553 const auto choiceRole = d->m_delegateChooser->role().toUtf8();
1554 const auto &roleNames = aim->roleNames();
1555 auto it = std::find_if(roles.begin(), roles.end(), [&](
int role) {
1556 return roleNames[role] == choiceRole;
1558 if (it == roles.end())
1564
1565
1566
1567 QList<Compositor::Remove> removes;
1568 QList<Compositor::Insert> inserts;
1569 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, index, count, &removes);
1571 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1572 QQmlDelegateModelItem::ObjectSpanReference guard(cache);
1573 for (
const auto &removed: std::as_const(removes)) {
1574 if (!d->m_cache.isSharedWith(cache))
1576 QQmlDelegateModelItem *item = cache.value(removed.cacheIndex(),
nullptr);
1577 if (!d->m_cache.contains(item))
1579 if (item->modelIndex() != -1)
1580 item->setModelIndex(-1, -1, -1);
1583 d->m_compositor.listItemsInserted(&d->m_adaptorModel, index, count, &inserts);
1584 d->itemsMoved(removes, inserts);
1591 for (
int i = 1; i < count; ++i)
1592 incubationTask->index[i] += deltas[i];
1595 for (
int i = 1; i < qMin<
int>(count, Compositor::MaximumGroupCount); ++i)
1596 attached->m_currentIndex[i] += deltas[i];
1601 const QList<Compositor::Insert> &inserts,
1602 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
1603 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems)
1607 int inserted[Compositor::MaximumGroupCount];
1611 for (
const Compositor::Insert &insert : inserts) {
1612 for (; cacheIndex < insert.cacheIndex(); ++cacheIndex)
1613 incrementIndexes(m_cache.at(cacheIndex), m_groupCount, inserted);
1615 for (
int i = 1; i < m_groupCount; ++i) {
1616 if (insert.inGroup(i)) {
1617 (*translatedInserts)[i].append(
1618 QQmlChangeSet::Change(insert.index[i], insert.count, insert.moveId));
1619 inserted[i] += insert.count;
1623 if (!insert.inCache())
1626 if (movedItems && insert.isMove()) {
1627 QList<QQmlDelegateModelItem *> items = movedItems->take(insert.moveId);
1628 Q_ASSERT(items.size() == insert.count);
1629 m_cache = m_cache.mid(0, insert.cacheIndex())
1630 + items + m_cache.mid(insert.cacheIndex());
1632 if (insert.inGroup()) {
1633 for (
int offset = 0; cacheIndex < insert.cacheIndex() + insert.count;
1634 ++cacheIndex, ++offset) {
1635 QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
1636 cacheItem->addGroups(insert.flags & Compositor::GroupMask);
1638 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask()) {
1639 for (
int i = 1; i < m_groupCount; ++i)
1640 incubationTask->index[i] = cacheItem->groups() & (1 << i)
1641 ? insert.index[i] + offset
1644 if (QQmlDelegateModelAttached *attached = cacheItem->attached()) {
1645 for (
int i = 1; i < m_groupCount; ++i)
1646 attached->m_currentIndex[i] = cacheItem->groups() & (1 << i)
1647 ? insert.index[i] + offset
1652 cacheIndex = insert.cacheIndex() + insert.count;
1655 for (
const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.size(); ++cacheIndex)
1656 incrementIndexes(cache.at(cacheIndex),
m_groupCount, inserted);
1661 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
1662 itemsInserted(inserts, &translatedInserts);
1663 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1667 for (
int i = 1; i < m_groupCount; ++i)
1668 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(translatedInserts.at(i));
1671void QQmlDelegateModel::_q_itemsInserted(
int index,
int count)
1674 Q_D(QQmlDelegateModel);
1675 if (count <= 0 || !d->m_complete)
1678 d->m_count += count;
1680 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1681 for (
int i = 0, c = cache.size(); i < c; ++i) {
1682 QQmlDelegateModelItem *item = cache.at(i);
1685 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
1688 if (item->modelIndex() >= index) {
1689 const int newIndex = item->modelIndex() + count;
1690 const int row = newIndex;
1691 const int column = 0;
1692 item->setModelIndex(newIndex, row, column);
1696 QList<Compositor::Insert> inserts;
1697 d->m_compositor.listItemsInserted(&d->m_adaptorModel, index, count, &inserts);
1698 d->itemsInserted(inserts);
1710 const QList<Compositor::Remove> &removes,
1711 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
1712 QHash<
int, QList<QQmlDelegateModelItem *> > *movedItems)
1715 int removedCache = 0;
1717 int removed[Compositor::MaximumGroupCount];
1721 for (
const Compositor::Remove &remove : removes) {
1722 for (; cacheIndex < remove.cacheIndex() && cacheIndex < m_cache.size(); ++cacheIndex)
1723 incrementIndexes(m_cache.at(cacheIndex), m_groupCount, removed);
1725 for (
int i = 1; i < m_groupCount; ++i) {
1726 if (remove.inGroup(i)) {
1727 (*translatedRemoves)[i].append(
1728 QQmlChangeSet::Change(remove.index[i], remove.count, remove.moveId));
1729 removed[i] -= remove.count;
1733 if (!remove.inCache())
1736 if (movedItems && remove.isMove()) {
1737 movedItems->insert(remove.moveId, m_cache.mid(remove.cacheIndex(), remove.count));
1738 QList<QQmlDelegateModelItem *>::const_iterator begin = m_cache.constBegin() + remove.cacheIndex();
1739 QList<QQmlDelegateModelItem *>::const_iterator end = begin + remove.count;
1740 m_cache.erase(begin, end);
1742 for (; cacheIndex < remove.cacheIndex() + remove.count - removedCache; ++cacheIndex) {
1743 QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
1744 if (remove.inGroup(Compositor::Persisted)
1745 && cacheItem->objectStrongRef() == 0
1746 && cacheItem->objectWeakRef() == 0
1747 && cacheItem->object()) {
1748 QObject *object = cacheItem->object();
1749 cacheItem->destroyObjectLater();
1750 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
1751 emitDestroyingPackage(package);
1753 emitDestroyingItem(object);
1755 if (!cacheItem->isScriptReferenced()
1756 && !cacheItem->object()
1757 && !remove.inGroup(Compositor::Persisted)) {
1758 m_compositor.clearFlags(Compositor::Cache, cacheIndex, 1, Compositor::CacheFlag);
1759 m_cache.removeAt(cacheIndex);
1763 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1764 }
else if (remove.groups() == cacheItem->groups()) {
1765 cacheItem->setGroups(0);
1766 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask()) {
1767 for (
int i = 1; i < m_groupCount; ++i)
1768 incubationTask->index[i] = -1;
1770 if (QQmlDelegateModelAttached *attached = cacheItem->attached()) {
1771 for (
int i = 1; i < m_groupCount; ++i)
1772 attached->m_currentIndex[i] = -1;
1775 if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask()) {
1776 if (!cacheItem->isObjectReferenced()) {
1777 releaseIncubator(incubationTask);
1778 cacheItem->clearIncubationTask();
1779 if (QObject *object = cacheItem->object()) {
1780 cacheItem->destroyObjectLater();
1781 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
1782 emitDestroyingPackage(package);
1784 emitDestroyingItem(object);
1787 for (
int i = 1; i < m_groupCount; ++i) {
1788 if (remove.inGroup(i))
1789 incubationTask->index[i] = remove.index[i];
1793 if (QQmlDelegateModelAttached *attached = cacheItem->attached()) {
1794 for (
int i = 1; i < m_groupCount; ++i) {
1795 if (remove.inGroup(i))
1796 attached->m_currentIndex[i] = remove.index[i];
1799 cacheItem->removeGroups(remove.flags);
1805 for (
const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.size(); ++cacheIndex)
1806 incrementIndexes(cache.at(cacheIndex),
m_groupCount, removed);
1811 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
1812 itemsRemoved(removes, &translatedRemoves);
1813 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1817 for (
int i = 1; i < m_groupCount; ++i)
1818 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(translatedRemoves.at(i));
1821void QQmlDelegateModel::_q_itemsRemoved(
int index,
int count)
1823 Q_D(QQmlDelegateModel);
1824 if (count <= 0|| !d->m_complete)
1827 d->m_count -= count;
1828 Q_ASSERT(d->m_count >= 0);
1831 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1834 QQmlDelegateModelItem::ObjectSpanReference guard(cache);
1836 for (
int i = 0, c = cache.size(); i < c; ++i) {
1837 QQmlDelegateModelItem *item = cache.at(i);
1840 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
1843 if (item->modelIndex() >= index + count) {
1844 const int newIndex = item->modelIndex() - count;
1845 const int row = newIndex;
1846 const int column = 0;
1847 item->setModelIndex(newIndex, row, column);
1848 }
else if (item->modelIndex() >= index) {
1849 item->setModelIndex(-1, -1, -1);
1854 QList<Compositor::Remove> removes;
1855 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, index, count, &removes);
1856 d->itemsRemoved(removes);
1862 const QList<Compositor::Remove> &removes,
const QList<Compositor::Insert> &inserts)
1864 QHash<
int, QList<QQmlDelegateModelItem *> > movedItems;
1866 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
1867 itemsRemoved(removes, &translatedRemoves, &movedItems);
1869 QVarLengthArray<QList<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
1870 itemsInserted(inserts, &translatedInserts, &movedItems);
1871 Q_ASSERT(m_cache.size() == m_compositor.count(Compositor::Cache));
1872 Q_ASSERT(movedItems.isEmpty());
1877 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.move(
1878 translatedRemoves.at(i),
1879 translatedInserts.at(i));
1883void QQmlDelegateModel::_q_itemsMoved(
int from,
int to,
int count)
1885 Q_D(QQmlDelegateModel);
1886 if (count <= 0 || !d->m_complete)
1889 const int minimum = qMin(from, to);
1890 const int maximum = qMax(from, to) + count;
1891 const int difference = from > to ? count : -count;
1893 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
1894 for (
int i = 0, c = cache.size(); i < c; ++i) {
1895 QQmlDelegateModelItem *item = cache.at(i);
1898 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
1901 if (item->modelIndex() >= from && item->modelIndex() < from + count) {
1902 const int newIndex = item->modelIndex() - from + to;
1903 const int row = newIndex;
1904 const int column = 0;
1905 item->setModelIndex(newIndex, row, column);
1906 }
else if (item->modelIndex() >= minimum && item->modelIndex() < maximum) {
1907 const int newIndex = item->modelIndex() + difference;
1908 const int row = newIndex;
1909 const int column = 0;
1910 item->setModelIndex(newIndex, row, column);
1914 QList<Compositor::Remove> removes;
1915 QList<Compositor::Insert> inserts;
1916 d->m_compositor.listItemsMoved(&d->m_adaptorModel, from, to, count, &removes, &inserts);
1917 d->itemsMoved(removes, inserts);
1923 Q_Q(QQmlDelegateModel);
1924 emit q->modelUpdated(changeSet, reset);
1925 if (changeSet.difference() != 0)
1926 emit q->countChanged();
1931 Q_Q(QQmlDelegateModel);
1936 qmlWarning(q) << QQmlDelegateModel::tr(
"The delegates of a DelegateModel cannot be changed within onUpdated.");
1942 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(
1943 0, m_compositor.count(Compositor::Group(i)));
1948 QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(
1949 0, m_compositor.count(Compositor::Group(i)));
1957 if (m_transaction || !m_complete || !m_context || !m_context->isValid())
1961 QV4::ExecutionEngine *engine = m_context->engine()->handle();
1962 for (
int i = 1; i < m_groupCount; ++i)
1963 QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitChanges(engine);
1968 for (
int i = 1; i < m_groupCount; ++i)
1969 QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset);
1972 QVarLengthArray<QPointer<QQmlDelegateModelAttached>> attachedObjects;
1973 attachedObjects.reserve(m_cache.length());
1974 for (
const QQmlDelegateModelItem *cacheItem : std::as_const(m_cache))
1975 attachedObjects.append(cacheItem->attached());
1977 for (
const QPointer<QQmlDelegateModelAttached> &attached : std::as_const(attachedObjects)) {
1978 if (attached && attached->m_cacheItem)
1979 attached->emitChanges();
1983void QQmlDelegateModel::_q_modelAboutToBeReset()
1985 Q_D(QQmlDelegateModel);
1986 if (!d->m_adaptorModel.adaptsAim())
1988 auto aim = d->m_adaptorModel.aim();
1989 auto oldRoleNames = aim->roleNames();
1992 QObject::connect(aim, &QAbstractItemModel::modelReset,
this, [
this, d, oldRoleNames, aim](){
1993 if (!d->m_adaptorModel.adaptsAim() || d->m_adaptorModel.aim() != aim)
1995 if (oldRoleNames == aim->roleNames()) {
2001 QVariant m = model();
2002 setModel(QVariant());
2008 }, Qt::SingleShotConnection);
2011void QQmlDelegateModel::handleModelReset()
2013 Q_D(QQmlDelegateModel);
2017 int oldCount = d->m_count;
2018 d->m_adaptorModel.rootIndex = QModelIndex();
2020 if (d->m_complete) {
2021 d->m_count = d->adaptorModelCount();
2024 const QList<QQmlDelegateModelItem *> cache = d->m_cache;
2025 QQmlDelegateModelItem::ObjectSpanReference guard(cache);
2027 for (
int i = 0, c = cache.size(); i < c; ++i) {
2028 QQmlDelegateModelItem *item = cache.at(i);
2031 if (!d->m_cache.isSharedWith(cache) && !d->m_cache.contains(item))
2034 if (item->modelIndex() != -1)
2035 item->setModelIndex(-1, -1, -1);
2039 QList<Compositor::Remove> removes;
2040 QList<Compositor::Insert> inserts;
2042 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
2044 d->m_compositor.listItemsInserted(&d->m_adaptorModel, 0, d->m_count, &inserts);
2045 d->itemsMoved(removes, inserts);
2048 if (d->m_adaptorModel.canFetchMore())
2049 d->m_adaptorModel.fetchMore();
2053 emit rootIndexChanged();
2056void QQmlDelegateModel::_q_rowsInserted(
const QModelIndex &parent,
int begin,
int end)
2058 Q_D(QQmlDelegateModel);
2059 if (parent == d->m_adaptorModel.rootIndex)
2060 _q_itemsInserted(begin, end - begin + 1);
2063void QQmlDelegateModel::_q_rowsAboutToBeRemoved(
const QModelIndex &parent,
int begin,
int end)
2065 Q_D(QQmlDelegateModel);
2066 if (!d->m_adaptorModel.rootIndex.isValid())
2068 const QModelIndex index = d->m_adaptorModel.rootIndex;
2069 if (index.parent() == parent && index.row() >= begin && index.row() <= end) {
2070 const int oldCount = d->m_count;
2072 d->disconnectFromAbstractItemModel();
2073 d->m_adaptorModel.invalidateModel();
2075 if (d->m_complete && oldCount > 0) {
2076 QList<Compositor::Remove> removes;
2077 d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
2078 d->itemsRemoved(removes);
2084void QQmlDelegateModel::_q_rowsRemoved(
const QModelIndex &parent,
int begin,
int end)
2086 Q_D(QQmlDelegateModel);
2087 if (parent == d->m_adaptorModel.rootIndex)
2088 _q_itemsRemoved(begin, end - begin + 1);
2091void QQmlDelegateModel::_q_rowsMoved(
2092 const QModelIndex &sourceParent,
int sourceStart,
int sourceEnd,
2093 const QModelIndex &destinationParent,
int destinationRow)
2095 Q_D(QQmlDelegateModel);
2096 const int count = sourceEnd - sourceStart + 1;
2097 if (destinationParent == d->m_adaptorModel.rootIndex && sourceParent == d->m_adaptorModel.rootIndex) {
2098 _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow - count, count);
2099 }
else if (sourceParent == d->m_adaptorModel.rootIndex) {
2100 _q_itemsRemoved(sourceStart, count);
2101 }
else if (destinationParent == d->m_adaptorModel.rootIndex) {
2102 _q_itemsInserted(destinationRow, count);
2106void QQmlDelegateModel::_q_columnsInserted(
const QModelIndex &parent,
int begin,
int end)
2108 Q_D(QQmlDelegateModel);
2110 if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
2112 _q_itemsChanged(0, d->m_count, QList<
int>());
2116void QQmlDelegateModel::_q_columnsRemoved(
const QModelIndex &parent,
int begin,
int end)
2118 Q_D(QQmlDelegateModel);
2120 if (parent == d->m_adaptorModel.rootIndex && begin == 0) {
2122 _q_itemsChanged(0, d->m_count, QList<
int>());
2126void QQmlDelegateModel::_q_columnsMoved(
const QModelIndex &parent,
int start,
int end,
2127 const QModelIndex &destination,
int column)
2129 Q_D(QQmlDelegateModel);
2131 if ((parent == d->m_adaptorModel.rootIndex && start == 0)
2132 || (destination == d->m_adaptorModel.rootIndex && column == 0)) {
2134 _q_itemsChanged(0, d->m_count, QList<
int>());
2138void QQmlDelegateModel::_q_dataChanged(
const QModelIndex &begin,
const QModelIndex &end,
const QList<
int> &roles)
2140 Q_D(QQmlDelegateModel);
2141 if (begin.parent() == d->m_adaptorModel.rootIndex)
2142 _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, roles);
2145bool QQmlDelegateModel::isDescendantOf(
const QPersistentModelIndex& desc,
const QList< QPersistentModelIndex >& parents)
const
2147 for (
int i = 0, c = parents.size(); i < c; ++i) {
2148 for (QPersistentModelIndex parent = desc; parent.isValid(); parent = parent.parent()) {
2149 if (parent == parents[i])
2157void QQmlDelegateModel::_q_layoutChanged(
const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
2159 Q_D(QQmlDelegateModel);
2163 if (hint == QAbstractItemModel::VerticalSortHint) {
2164 if (!parents.isEmpty() && d->m_adaptorModel.rootIndex.isValid() && !isDescendantOf(d->m_adaptorModel.rootIndex, parents)) {
2169 _q_itemsChanged(0, d->m_count, QList<
int>());
2171 }
else if (hint == QAbstractItemModel::HorizontalSortHint) {
2179QQmlDelegateModelAttached *QQmlDelegateModel::qmlAttachedProperties(QObject *obj)
2181 if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(obj))
2182 return new QQmlDelegateModelAttached(cacheItem, obj);
2183 return new QQmlDelegateModelAttached(obj);
2189 if (!m_context || !m_context->isValid())
2195 if (!object.isObject())
2198 QV4::ExecutionEngine *v4 = object.as<QV4::Object>()->engine();
2199 QV4::Scope scope(v4);
2200 QV4::ScopedObject o(scope, object);
2204 QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
2205 QV4::ScopedValue propertyName(scope);
2206 QV4::ScopedValue v(scope);
2207 const auto oldCache = m_cache;
2209 propertyName = it.nextPropertyNameAsString(v);
2210 if (propertyName->isNull())
2212 cacheItem->setValue(
2213 propertyName->toQStringNoThrow(),
2214 QV4::ExecutionEngine::toVariant(v, QMetaType {}));
2216 const bool cacheModified = !m_cache.isSharedWith(oldCache);
2220 cacheItem
->setGroups(groups | Compositor::UnresolvedFlag | Compositor::CacheFlag);
2223 itemsInserted(QList<Compositor::Insert>(
2224 1, Compositor::Insert(before, 1, cacheItem->groups() & ~Compositor::CacheFlag)));
2226 m_cache.insert(before.cacheIndex(), cacheItem);
2227 m_compositor.insert(before,
nullptr, 0, 1, cacheItem->groups());
2234QQmlDelegateModelItemMetaType::QQmlDelegateModelItemMetaType(
2235 QV4::ExecutionEngine *engine, QQmlDelegateModel *model,
const QStringList &groupNames)
2238 , groupNames(groupNames)
2239 , modelKind(ModelKind::DelegateModel)
2243QQmlDelegateModelItemMetaType::QQmlDelegateModelItemMetaType(
2244 QV4::ExecutionEngine *engine, QQmlTableInstanceModel *model)
2247 , modelKind(ModelKind::TableInstanceModel)
2251QQmlDelegateModelItemMetaType::~QQmlDelegateModelItemMetaType() =
default;
2253void QQmlDelegateModelItemMetaType::emitModelChanged()
const
2255 switch (modelKind) {
2256 case ModelKind::InstanceModel:
2258 case ModelKind::DelegateModel:
2259 emit
static_cast<QQmlDelegateModel *>(model.data())->modelChanged();
2261 case ModelKind::TableInstanceModel:
2262 emit
static_cast<QQmlTableInstanceModel *>(model.data())->modelChanged();
2267void QQmlDelegateModelItemMetaType::initializeAttachedMetaObject()
2269 QMetaObjectBuilder builder;
2270 builder.setFlags(DynamicMetaObject);
2271 builder.setClassName(QQmlDelegateModelAttached::staticMetaObject.className());
2272 builder.setSuperClass(&QQmlDelegateModelAttached::staticMetaObject);
2275 for (qsizetype i = 0, end = groupCount(); i < end; ++i, ++notifierId) {
2276 QString propertyName = QLatin1String(
"in") + groupNames.at(i);
2277 propertyName.replace(2, 1, propertyName.at(2).toUpper());
2278 builder.addSignal(
"__" + propertyName.toUtf8() +
"Changed()");
2279 QMetaPropertyBuilder propertyBuilder = builder.addProperty(
2280 propertyName.toUtf8(),
"bool", notifierId);
2281 propertyBuilder.setWritable(
true);
2282 propertyBuilder.setFinal(
true);
2284 for (qsizetype i = 0, end = groupCount(); i < end; ++i, ++notifierId) {
2285 const QString propertyName = groupNames.at(i) + QLatin1String(
"Index");
2286 builder.addSignal(
"__" + propertyName.toUtf8() +
"Changed()");
2287 QMetaPropertyBuilder propertyBuilder = builder.addProperty(
2288 propertyName.toUtf8(),
"int", notifierId);
2289 propertyBuilder.setWritable(
true);
2290 propertyBuilder.setFinal(
true);
2293 attachedMetaObject = QQml::makeRefPointer<QQmlDelegateModelAttachedMetaObject>(
2294 this, builder.toMetaObject());
2297void QQmlDelegateModelItemMetaType::initializePrototype()
2299 QV4::Scope scope(v4Engine);
2301 QV4::ScopedObject proto(scope, v4Engine->newObject());
2302 proto->defineAccessorProperty(QStringLiteral(
"model"), QQmlDelegateModelItem::get_model,
nullptr);
2303 proto->defineAccessorProperty(QStringLiteral(
"groups"), QQmlDelegateModelItem::get_groups, QQmlDelegateModelItem::set_groups);
2304 QV4::ScopedString s(scope);
2305 QV4::ScopedProperty p(scope);
2307 s = v4Engine->newString(QStringLiteral(
"isUnresolved"));
2308 QV4::ScopedFunctionObject f(scope);
2309 QV4::ExecutionEngine *engine = scope.engine;
2310 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, 30, QQmlDelegateModelItem::get_member)));
2311 p->setSetter(
nullptr);
2312 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2314 s = v4Engine->newString(QStringLiteral(
"inItems"));
2315 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)));
2316 p->setSetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)));
2317 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2319 s = v4Engine->newString(QStringLiteral(
"inPersistedItems"));
2320 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)));
2321 p->setSetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)));
2322 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2324 s = v4Engine->newString(QStringLiteral(
"itemsIndex"));
2325 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)));
2326 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2328 s = v4Engine->newString(QStringLiteral(
"persistedItemsIndex"));
2329 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)));
2330 p->setSetter(
nullptr);
2331 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2333 for (qsizetype i = 2, end = groupCount(); i < end; ++i) {
2334 QString propertyName = QLatin1String(
"in") + groupNames.at(i);
2335 propertyName.replace(2, 1, propertyName.at(2).toUpper());
2336 s = v4Engine->newString(propertyName);
2337 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, i + 1, QQmlDelegateModelItem::get_member)));
2338 p->setSetter((f = QV4::DelegateModelGroupFunction::create(engine, i + 1, QQmlDelegateModelItem::set_member)));
2339 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2341 for (qsizetype i = 2, end = groupCount(); i < end; ++i) {
2342 const QString propertyName = groupNames.at(i) + QLatin1String(
"Index");
2343 s = v4Engine->newString(propertyName);
2344 p->setGetter((f = QV4::DelegateModelGroupFunction::create(engine, i + 1, QQmlDelegateModelItem::get_index)));
2345 p->setSetter(
nullptr);
2346 proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
2348 modelItemProto.set(v4Engine, proto);
2351int QQmlDelegateModelItemMetaType::parseGroups(
const QStringList &groups)
const
2354 for (
const QString &groupName : groups) {
2355 int index = groupNames.indexOf(groupName);
2357 groupFlags |= 2 << index;
2362int QQmlDelegateModelItemMetaType::parseGroups(
const QV4::Value &groups)
const
2365 QV4::Scope scope(v4Engine);
2367 QV4::ScopedString s(scope, groups);
2369 const QString groupName = s->toQString();
2370 int index = groupNames.indexOf(groupName);
2372 groupFlags |= 2 << index;
2376 QV4::ScopedArrayObject array(scope, groups);
2378 QV4::ScopedValue v(scope);
2379 uint arrayLength = array->getLength();
2380 for (uint i = 0; i < arrayLength; ++i) {
2382 const QString groupName = v->toQString();
2383 int index = groupNames.indexOf(groupName);
2385 groupFlags |= 2 << index;
2391QV4::ReturnedValue
QQmlDelegateModelItem::get_model(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *,
int)
2393 QV4::Scope scope(b);
2394 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
2396 return b->engine()->throwTypeError(QStringLiteral(
"Not a valid DelegateModel object"));
2399 if (!item->m_metaType->model)
2405QV4::ReturnedValue
QQmlDelegateModelItem::get_groups(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *,
int)
2407 QV4::Scope scope(b);
2408 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
2410 return scope.engine->throwTypeError(QStringLiteral(
"Not a valid DelegateModel object"));
2414 const auto &metaType = item->m_metaType;
2415 for (qsizetype i = 0, end = metaType->groupCount(); i < end; ++i) {
2416 if (item->m_groups & (1 << (i + 1)))
2417 groups.append(metaType->groupNames.at(i));
2420 return scope.engine->fromVariant(groups);
2423QV4::ReturnedValue
QQmlDelegateModelItem::set_groups(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
2425 QV4::Scope scope(b);
2426 QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
2428 return scope.engine->throwTypeError(QStringLiteral(
"Not a valid DelegateModel object"));
2434 QQmlDelegateModel *delegateModel = item->m_metaType->delegateModel();
2439 const int groupFlags = model->m_cacheMetaType->parseGroups(argv[0]);
2440 const int cacheIndex = model->m_cache.indexOf(item);
2441 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2442 model->setGroups(it, 1, Compositor::Cache, groupFlags);
2443 return QV4::Encode::undefined();
2448 return QV4::Encode(
bool(thisItem->m_groups & (1 << flag)));
2453 bool member = arg.toBoolean();
2454 uint groupFlag = (1 << flag);
2455 if (member == ((cacheItem->m_groups & groupFlag) != 0))
2456 return QV4::Encode::undefined();
2458 QQmlDelegateModel *delegateModel = cacheItem->m_metaType->delegateModel();
2460 return QV4::Encode::undefined();
2463 const int cacheIndex = model->m_cache.indexOf(cacheItem);
2464 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2466 model->addGroups(it, 1, Compositor::Cache, groupFlag);
2468 model->removeGroups(it, 1, Compositor::Cache, groupFlag);
2469 return QV4::Encode::undefined();
2474 return QV4::Encode((
int)thisItem->groupIndex(Compositor::Group(flag)));
2482 for (QQmlRefPointer<QQmlContextData> ctxt = m_contextData->childContexts(); ctxt;
2483 ctxt = ctxt->nextChild()) {
2484 ctxt->deepClearContextObject(childContextObject);
2498 reinterpret_cast<QQmlDelegateModelItem::ScriptReference *>(&ref)->~ScriptReference();
2505 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
2506 QQmlAdaptorModel::Accessors *accessor,
2507 int modelIndex,
int row,
int column)
2509 , m_index(modelIndex)
2513 if (accessor->propertyCache) {
2521 QQmlData::get(
this,
true)->propertyCache = accessor->propertyCache;
2527 Q_ASSERT(m_scriptRef == 0);
2528 Q_ASSERT(m_objectStrongRef == 0);
2529 Q_ASSERT(!m_object);
2531 if (m_incubationTask) {
2532 if (QQmlDelegateModel *delegateModel = m_metaType->delegateModel())
2533 QQmlDelegateModelPrivate::get(delegateModel)->releaseIncubator(m_incubationTask);
2535 delete m_incubationTask;
2541 if (isScriptReferenced() || m_object)
2544 if (QQmlDelegateModel *delegateModel = m_metaType->delegateModel())
2545 QQmlDelegateModelPrivate::get(delegateModel)->removeCacheItem(
this);
2552 const int prevIndex = m_index;
2553 const int prevRow = m_row;
2554 const int prevColumn = m_column;
2558 m_column = newColumn;
2560 if (idx != prevIndex || alwaysEmit)
2561 emit modelIndexChanged();
2562 if (m_row != prevRow || alwaysEmit)
2564 if (m_column != prevColumn || alwaysEmit)
2565 emit columnChanged();
2570 delete std::exchange(m_object,
nullptr);
2571 m_contextData.reset();
2577 Q_ASSERT(m_contextData);
2579 QQmlData *data = QQmlData::get(m_object);
2581 if (data->ownContext) {
2582 data->ownContext->emitDestruction();
2583 data->ownContext->clearExpressions();
2584 data->ownContext->deepClearContextObject(m_object);
2585 data->ownContext.reset();
2586 data->context =
nullptr;
2589
2590
2591
2592
2593
2594
2595 if (Q_UNLIKELY(
static_cast<QCoreApplicationPrivate *>(QCoreApplicationPrivate::get(QCoreApplication::instance()))->aboutToQuitEmitted)) {
2596 if (m_object->parent() ==
nullptr)
2597 m_object->setParent(QCoreApplication::instance());
2599 m_object->deleteLater();
2604 m_contextData.reset();
2610 QQmlData *d = QQmlData::get(object);
2614 QQmlRefPointer<QQmlContextData> context = d->context;
2615 if (!context || !context->isValid())
2618 if (QObject *extraObject = context->extraObject())
2621 for (context = context->parent(); context; context = context->parent()) {
2622 if (QObject *extraObject = context->extraObject())
2625 context->contextObject())) {
2634 if (QQmlDelegateModel *delegateModel = m_metaType->delegateModel()) {
2636 return model->m_compositor.find(Compositor::Cache, model->m_cache.indexOf(
this)).index[group];
2644 QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject)
2654 *
static_cast<QMetaObject *>(
this) = *metaObject;
2667int QQmlDelegateModelAttachedMetaObject::
metaCall(QObject *object, QMetaObject::Call call,
int _id,
void **arguments)
2670 if (call == QMetaObject::ReadProperty) {
2671 if (_id >= indexPropertyOffset) {
2672 Compositor::Group group = Compositor::Group(_id - indexPropertyOffset + 1);
2673 *
static_cast<
int *>(arguments[0]) = attached->m_currentIndex[group];
2675 }
else if (_id >= memberPropertyOffset) {
2676 Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
2680 }
else if (call == QMetaObject::WriteProperty) {
2681 if (_id >= memberPropertyOffset) {
2682 QQmlDelegateModel *delegateModel = metaType->delegateModel();
2686 Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
2687 const int groupFlag = 1 << group;
2689 if (member && !*
static_cast<
bool *>(arguments[0])) {
2690 Compositor::iterator it = model->m_compositor.find(
2691 group, attached->m_currentIndex[group]);
2692 model->removeGroups(it, 1, group, groupFlag);
2693 }
else if (!member && *
static_cast<
bool *>(arguments[0])) {
2694 for (qsizetype i = 1, end = metaType->groupCount(); i <= end; ++i) {
2695 if (attached->m_cacheItem->groups() & (1 << i)) {
2696 Compositor::iterator it = model->m_compositor.find(
2697 Compositor::Group(i), attached->m_currentIndex[i]);
2698 model->addGroups(it, 1, Compositor::Group(i), groupFlag);
2706 return attached->qt_metacall(call, _id, arguments);
2713 QQml_setParent_noEvent(
this, parent);
2721 QQml_setParent_noEvent(
this, parent);
2724 std::copy(std::begin(m_currentIndex), std::end(m_currentIndex), std::begin(m_previousIndex));
2726 const auto &metaType = cacheItem->metaType();
2727 if (!metaType->attachedMetaObject)
2728 metaType->initializeAttachedMetaObject();
2730 QObjectPrivate::get(
this)->metaObject = metaType->attachedMetaObject.data();
2731 metaType->attachedMetaObject->addref();
2740 for (qsizetype i = 1, end = metaType->groupCount(); i <= end; ++i)
2741 m_currentIndex[i] = incubationTask->index[i];
2742 }
else if (QQmlDelegateModel *delegateModel = metaType->delegateModel()) {
2744 Compositor::iterator it = model->m_compositor.find(
2745 Compositor::Cache, model->m_cache.indexOf(
m_cacheItem));
2746 for (qsizetype i = 1, end = metaType->groupCount(); i <= end; ++i)
2747 m_currentIndex[i] = it.index[i];
2753 setInGroup(QQmlListCompositor::Persisted, inPersisted);
2760 const uint groupFlag = (1 << QQmlListCompositor::Persisted);
2768 return m_cacheItem->groupIndex(QQmlListCompositor::Persisted);
2776 QQmlDelegateModel *delegateModel = m_cacheItem->metaType()->delegateModel();
2781 const uint groupFlag = (1 << group);
2785 const int cacheIndex = model->m_cache.indexOf(
m_cacheItem);
2786 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2788 model->addGroups(it, 1, Compositor::Cache, groupFlag);
2790 model->removeGroups(it, 1, Compositor::Cache, groupFlag);
2796 setInGroup(QQmlListCompositor::Default, inItems);
2803 const uint groupFlag = (1 << QQmlListCompositor::Default);
2811 return m_cacheItem->groupIndex(QQmlListCompositor::Default);
2815
2816
2817
2818
2819
2820
2828
2829
2830
2831
2832
2833
2842 for (qsizetype i = 0, end = metaType->groupCount(); i < end; ++i) {
2843 if (m_cacheItem->groups() & (1 << (i + 1)))
2844 groups.append(metaType->groupNames.at(i));
2854 QQmlDelegateModel *delegateModel = m_cacheItem->metaType()->delegateModel();
2859 const int groupFlags = model->m_cacheMetaType->parseGroups(groups);
2860 const int cacheIndex = model->m_cache.indexOf(
m_cacheItem);
2861 Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
2862 model->setGroups(it, 1, Compositor::Cache, groupFlags);
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2882 return m_cacheItem->groups() & Compositor::UnresolvedFlag;
2886
2887
2888
2889
2890
2891
2892
2893
2894
2897
2898
2899
2900
2901
2902
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2918
2919
2920
2921
2922
2923
2930 int indexChanges = 0;
2931 const qsizetype groupCount =
m_cacheItem->metaType()->groupCount();
2932 for (qsizetype i = 1; i <= groupCount; ++i) {
2933 if (m_previousIndex[i] != m_currentIndex[i]) {
2934 m_previousIndex[i] = m_currentIndex[i];
2935 indexChanges |= (1 << i);
2943 const QMetaObject *meta = metaObject();
2944 for (qsizetype i = 1; i <= groupCount; ++i, ++notifierId) {
2945 if (groupChanges & (1 << i))
2946 QMetaObject::activate(
this, meta, notifierId,
nullptr);
2948 for (qsizetype i = 1; i <= groupCount; ++i, ++notifierId) {
2949 if (indexChanges & (1 << i))
2950 QMetaObject::activate(
this, meta, notifierId,
nullptr);
2954 emit groupsChanged();
2968 Q_Q(QQmlDelegateModelGroup);
2969 IS_SIGNAL_CONNECTED(q, QQmlDelegateModelGroup, changed, (
const QJSValue &,
const QJSValue &));
2974 Q_Q(QQmlDelegateModelGroup);
2975 if (isChangedConnected() && !changeSet.isEmpty()) {
2976 emit q->changed(QJSValuePrivate::fromReturnedValue(
2977 qdmEngineData(v4)->array(v4, changeSet.removes())),
2978 QJSValuePrivate::fromReturnedValue(
2979 qdmEngineData(v4)->array(v4, changeSet.inserts())));
2981 if (changeSet.difference() != 0)
2982 emit q->countChanged();
2987 for (QQmlDelegateModelGroupEmitterList::iterator it =
emitters.begin(); it !=
emitters.end(); ++it)
2988 it->emitModelUpdated(changeSet, reset);
2997 it->createdPackage(index, package);
3003 it->initPackage(index, package);
3009 it->destroyingPackage(package);
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048QQmlDelegateModelGroup::QQmlDelegateModelGroup(QObject *parent)
3049 : QObject(*
new QQmlDelegateModelGroupPrivate, parent)
3053QQmlDelegateModelGroup::QQmlDelegateModelGroup(
3054 const QString &name, QQmlDelegateModel *model,
int index, QObject *parent)
3055 : QQmlDelegateModelGroup(parent)
3057 Q_D(QQmlDelegateModelGroup);
3059 d->setModel(model, Compositor::Group(index));
3062QQmlDelegateModelGroup::~QQmlDelegateModelGroup() =
default;
3065
3066
3067
3068
3069
3070
3072QString QQmlDelegateModelGroup::name()
const
3074 Q_D(
const QQmlDelegateModelGroup);
3078void QQmlDelegateModelGroup::setName(
const QString &name)
3080 Q_D(QQmlDelegateModelGroup);
3083 if (d->name != name) {
3090
3091
3092
3093
3095int QQmlDelegateModelGroup::count()
const
3097 Q_D(
const QQmlDelegateModelGroup);
3100 return QQmlDelegateModelPrivate::get(d->model)->m_compositor.count(d->group);
3104
3105
3106
3107
3109bool QQmlDelegateModelGroup::defaultInclude()
const
3111 Q_D(
const QQmlDelegateModelGroup);
3112 return d->defaultInclude;
3115void QQmlDelegateModelGroup::setDefaultInclude(
bool include)
3117 Q_D(QQmlDelegateModelGroup);
3118 if (d->defaultInclude != include) {
3119 d->defaultInclude = include;
3123 QQmlDelegateModelPrivate::get(d->model)->m_compositor.setDefaultGroup(d->group);
3125 QQmlDelegateModelPrivate::get(d->model)->m_compositor.clearDefaultGroup(d->group);
3127 emit defaultIncludeChanged();
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3155QJSValue QQmlDelegateModelGroup::get(
int index)
3157 Q_D(QQmlDelegateModelGroup);
3161 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3162 if (!model->m_context || !model->m_context->isValid()) {
3164 }
else if (index < 0 || index >= model->m_compositor.count(d->group)) {
3165 qmlWarning(
this) << tr(
"get: index out of range");
3169 Compositor::iterator it = model->m_compositor.find(d->group, index);
3170 QQmlDelegateModelItem *cacheItem = it->inCache()
3171 ? model->m_cache.at(it.cacheIndex())
3175 cacheItem = model->m_adaptorModel.createItem(
3176 model->m_cacheMetaType, it.modelIndex());
3179 cacheItem->setGroups(it->flags);
3181 model->m_cache.insert(it.cacheIndex(), cacheItem);
3182 model->m_compositor.setFlags(it, 1, Compositor::CacheFlag);
3185 if (model->m_cacheMetaType->modelItemProto.isUndefined())
3186 model->m_cacheMetaType->initializePrototype();
3187 QV4::ExecutionEngine *v4 = model->m_cacheMetaType->v4Engine;
3188 QV4::Scope scope(v4);
3189 QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(cacheItem));
3190 QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
3191 o->setPrototypeOf(p);
3193 return QJSValuePrivate::fromReturnedValue(o->asReturnedValue());
3198 if (value.isNumber()) {
3199 *index = value.toInt32();
3203 if (!value.isObject())
3206 QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine();
3207 QV4::Scope scope(v4);
3208 QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
3212 if (QQmlDelegateModel *delegateModel = cacheItem->metaType()->delegateModel()) {
3213 *index = QQmlDelegateModelPrivate::get(delegateModel)->m_cache.indexOf(cacheItem);
3214 *group = Compositor::Cache;
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3238void QQmlDelegateModelGroup::insert(QQmlV4FunctionPtr args)
3240 Q_D(QQmlDelegateModelGroup);
3241 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3243 int index = model->m_compositor.count(d->group);
3244 Compositor::Group group = d->group;
3246 if (args->length() == 0)
3250 QV4::Scope scope(args->v4engine());
3251 QV4::ScopedValue v(scope, (*args)[i]);
3252 if (d->parseIndex(v, &index, &group)) {
3253 if (index < 0 || index > model->m_compositor.count(group)) {
3254 qmlWarning(
this) << tr(
"insert: index out of range");
3257 if (++i == args->length())
3262 if (v->as<QV4::ArrayObject>())
3265 int groups = 1 << d->group;
3266 if (++i < args->length()) {
3267 QV4::ScopedValue val(scope, (*args)[i]);
3268 groups |= model->m_cacheMetaType->parseGroups(val);
3271 if (v->as<QV4::Object>()) {
3272 auto insertionResult = QQmlDelegateModelPrivate::InsertionResult::Retry;
3274 Compositor::insert_iterator before = index < model->m_compositor.count(group)
3275 ? model->m_compositor.findInsertPosition(group, index)
3276 : model->m_compositor.end();
3277 insertionResult = model->insert(before, v, groups);
3278 }
while (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Retry);
3279 if (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Success)
3280 model->emitChanges();
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3301void QQmlDelegateModelGroup::create(QQmlV4FunctionPtr args)
3303 Q_D(QQmlDelegateModelGroup);
3307 if (args->length() == 0)
3310 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3312 int index = model->m_compositor.count(d->group);
3313 Compositor::Group group = d->group;
3316 QV4::Scope scope(args->v4engine());
3317 QV4::ScopedValue v(scope, (*args)[i]);
3318 if (d->parseIndex(v, &index, &group))
3321 if (i < args->length() && index >= 0 && index <= model->m_compositor.count(group)) {
3323 if (v->as<QV4::Object>()) {
3324 int groups = 1 << d->group;
3325 if (++i < args->length()) {
3326 QV4::ScopedValue val(scope, (*args)[i]);
3327 groups |= model->m_cacheMetaType->parseGroups(val);
3330 auto insertionResult = QQmlDelegateModelPrivate::InsertionResult::Retry;
3332 Compositor::insert_iterator before = index < model->m_compositor.count(group)
3333 ? model->m_compositor.findInsertPosition(group, index)
3334 : model->m_compositor.end();
3336 index = before.index[d->group];
3339 insertionResult = model->insert(before, v, groups);
3340 }
while (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Retry);
3341 if (insertionResult == QQmlDelegateModelPrivate::InsertionResult::Error)
3345 if (index < 0 || index >= model->m_compositor.count(group)) {
3346 qmlWarning(
this) << tr(
"create: index out of range");
3350 QObject *object = model->object(group, index, QQmlIncubator::AsynchronousIfNested);
3352 QList<Compositor::Insert> inserts;
3353 Compositor::iterator it = model->m_compositor.find(group, index);
3354 model->m_compositor.setFlags(it, 1, d->group, Compositor::PersistedFlag, &inserts);
3355 model->itemsInserted(inserts);
3356 model->m_cache.at(it.cacheIndex())->releaseObjectWeak();
3359 args->setReturnValue(QV4::QObjectWrapper::wrap(args->v4engine(), object));
3360 model->emitChanges();
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379void QQmlDelegateModelGroup::resolve(QQmlV4FunctionPtr args)
3381 Q_D(QQmlDelegateModelGroup);
3385 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3387 if (args->length() < 2)
3392 Compositor::Group fromGroup = d->group;
3393 Compositor::Group toGroup = d->group;
3395 QV4::Scope scope(args->v4engine());
3396 QV4::ScopedValue v(scope, (*args)[0]);
3397 if (d->parseIndex(v, &from, &fromGroup)) {
3398 if (from < 0 || from >= model->m_compositor.count(fromGroup)) {
3399 qmlWarning(
this) << tr(
"resolve: from index out of range");
3403 qmlWarning(
this) << tr(
"resolve: from index invalid");
3408 if (d->parseIndex(v, &to, &toGroup)) {
3409 if (to < 0 || to >= model->m_compositor.count(toGroup)) {
3410 qmlWarning(
this) << tr(
"resolve: to index out of range");
3414 qmlWarning(
this) << tr(
"resolve: to index invalid");
3418 Compositor::iterator fromIt = model->m_compositor.find(fromGroup, from);
3419 Compositor::iterator toIt = model->m_compositor.find(toGroup, to);
3421 if (!fromIt->isUnresolved()) {
3422 qmlWarning(
this) << tr(
"resolve: from is not an unresolved item");
3426 qmlWarning(
this) << tr(
"resolve: to is not a model item");
3430 const int unresolvedFlags = fromIt->flags;
3431 const int resolvedFlags = toIt->flags;
3432 const int resolvedIndex = toIt.modelIndex();
3433 void *
const resolvedList = toIt->list;
3435 QQmlDelegateModelItem *cacheItem = model->m_cache.at(fromIt.cacheIndex());
3436 cacheItem->removeGroups(Compositor::UnresolvedFlag);
3438 if (toIt.cacheIndex() > fromIt.cacheIndex())
3439 toIt.decrementIndexes(1, unresolvedFlags);
3440 if (!toIt->inGroup(fromGroup) || toIt.index[fromGroup] > from)
3444 QList<Compositor::Remove>(1, Compositor::Remove(fromIt, 1, unresolvedFlags, 0)),
3445 QList<Compositor::Insert>(1, Compositor::Insert(toIt, 1, unresolvedFlags, 0)));
3446 model->itemsInserted(
3447 QList<Compositor::Insert>(1, Compositor::Insert(toIt, 1, (resolvedFlags & ~unresolvedFlags) | Compositor::CacheFlag)));
3448 toIt.incrementIndexes(1, resolvedFlags | unresolvedFlags);
3449 model->itemsRemoved(QList<Compositor::Remove>(1, Compositor::Remove(toIt, 1, resolvedFlags)));
3451 model->m_compositor.setFlags(toGroup, to, 1, unresolvedFlags & ~Compositor::UnresolvedFlag);
3452 model->m_compositor.clearFlags(fromGroup, from, 1, unresolvedFlags);
3454 if (resolvedFlags & Compositor::CacheFlag)
3455 model->m_compositor.insert(
3456 Compositor::Cache, toIt.cacheIndex(), resolvedList,
3457 resolvedIndex, 1, Compositor::CacheFlag);
3459 Q_ASSERT(model->m_cache.size() == model->m_compositor.count(Compositor::Cache));
3461 if (!cacheItem->isScriptReferenced() && !cacheItem->object()) {
3462 Q_ASSERT(toIt.cacheIndex() == model->m_cache.indexOf(cacheItem));
3463 model->m_cache.removeAt(toIt.cacheIndex());
3464 model->m_compositor.clearFlags(
3465 Compositor::Cache, toIt.cacheIndex(), 1, Compositor::CacheFlag);
3467 Q_ASSERT(model->m_cache.size() == model->m_compositor.count(Compositor::Cache));
3469 cacheItem->resolveIndex(model->m_adaptorModel, resolvedIndex);
3470 if (QQmlDelegateModelAttached *attached = cacheItem->attached())
3471 attached->emitUnresolvedChanged();
3474 model->emitChanges();
3478
3479
3480
3481
3483void QQmlDelegateModelGroup::remove(QQmlV4FunctionPtr args)
3485 Q_D(QQmlDelegateModelGroup);
3488 Compositor::Group group = d->group;
3492 if (args->length() == 0)
3496 QV4::Scope scope(args->v4engine());
3497 QV4::ScopedValue v(scope, (*args)[0]);
3498 if (!d->parseIndex(v, &index, &group)) {
3499 qmlWarning(
this) << tr(
"remove: invalid index");
3503 if (++i < args->length()) {
3506 count = v->toInt32();
3509 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3510 if (index < 0 || index >= model->m_compositor.count(group)) {
3511 qmlWarning(
this) << tr(
"remove: index out of range");
3512 }
else if (count != 0) {
3513 Compositor::iterator it = model->m_compositor.find(group, index);
3514 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3515 qmlWarning(
this) << tr(
"remove: invalid count");
3517 model->removeGroups(it, count, d->group, 1 << d->group);
3523 QQmlV4FunctionPtr args, Compositor::Group *group,
int *index,
int *count,
int *groups)
const
3525 if (!model || !QQmlDelegateModelPrivate::get(model)->m_cacheMetaType)
3528 if (args->length() < 2)
3532 QV4::Scope scope(args->v4engine());
3533 QV4::ScopedValue v(scope, (*args)[i]);
3534 if (!parseIndex(v, index, group))
3538 if (v->isNumber()) {
3539 *count = v->toInt32();
3541 if (++i == args->length())
3546 *groups = QQmlDelegateModelPrivate::get(model)->m_cacheMetaType->parseGroups(v);
3552
3553
3554
3555
3557void QQmlDelegateModelGroup::addGroups(QQmlV4FunctionPtr args)
3559 Q_D(QQmlDelegateModelGroup);
3560 Compositor::Group group = d->group;
3565 if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
3568 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3569 if (index < 0 || index >= model->m_compositor.count(group)) {
3570 qmlWarning(
this) << tr(
"addGroups: index out of range");
3571 }
else if (count != 0) {
3572 Compositor::iterator it = model->m_compositor.find(group, index);
3573 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3574 qmlWarning(
this) << tr(
"addGroups: invalid count");
3576 model->addGroups(it, count, d->group, groups);
3582
3583
3584
3585
3587void QQmlDelegateModelGroup::removeGroups(QQmlV4FunctionPtr args)
3589 Q_D(QQmlDelegateModelGroup);
3590 Compositor::Group group = d->group;
3595 if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
3598 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3599 if (index < 0 || index >= model->m_compositor.count(group)) {
3600 qmlWarning(
this) << tr(
"removeGroups: index out of range");
3601 }
else if (count != 0) {
3602 Compositor::iterator it = model->m_compositor.find(group, index);
3603 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3604 qmlWarning(
this) << tr(
"removeGroups: invalid count");
3606 model->removeGroups(it, count, d->group, groups);
3612
3613
3614
3615
3616
3618void QQmlDelegateModelGroup::setGroups(QQmlV4FunctionPtr args)
3620 Q_D(QQmlDelegateModelGroup);
3621 Compositor::Group group = d->group;
3626 if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
3629 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3630 if (index < 0 || index >= model->m_compositor.count(group)) {
3631 qmlWarning(
this) << tr(
"setGroups: index out of range");
3632 }
else if (count != 0) {
3633 Compositor::iterator it = model->m_compositor.find(group, index);
3634 if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
3635 qmlWarning(
this) << tr(
"setGroups: invalid count");
3637 model->setGroups(it, count, d->group, groups);
3643
3644
3645
3646
3647
3648
3649
3650
3651
3653void QQmlDelegateModelGroup::move(QQmlV4FunctionPtr args)
3655 Q_D(QQmlDelegateModelGroup);
3657 if (args->length() < 2)
3660 Compositor::Group fromGroup = d->group;
3661 Compositor::Group toGroup = d->group;
3666 QV4::Scope scope(args->v4engine());
3667 QV4::ScopedValue v(scope, (*args)[0]);
3668 if (!d->parseIndex(v, &from, &fromGroup)) {
3669 qmlWarning(
this) << tr(
"move: invalid from index");
3674 if (!d->parseIndex(v, &to, &toGroup)) {
3675 qmlWarning(
this) << tr(
"move: invalid to index");
3679 if (args->length() > 2) {
3682 count = v->toInt32();
3685 QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
3688 qmlWarning(
this) << tr(
"move: invalid count");
3689 }
else if (from < 0 || from + count > model->m_compositor.count(fromGroup)) {
3690 qmlWarning(
this) << tr(
"move: from index out of range");
3691 }
else if (!model->m_compositor.verifyMoveTo(fromGroup, from, toGroup, to, count, d->group)) {
3692 qmlWarning(
this) << tr(
"move: to index out of range");
3693 }
else if (count > 0) {
3694 QList<Compositor::Remove> removes;
3695 QList<Compositor::Insert> inserts;
3697 model->m_compositor.move(fromGroup, from, toGroup, to, count, d->group, &removes, &inserts);
3698 model->itemsMoved(removes, inserts);
3699 model->emitChanges();
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3718QQmlPartsModel::QQmlPartsModel(QQmlDelegateModel *model,
const QString &part, QObject *parent)
3719 : QQmlInstanceModel(*
new QObjectPrivate, parent)
3722 , m_compositorGroup(Compositor::Cache)
3723 , m_inheritGroup(
true)
3726 if (d->m_cacheMetaType) {
3727 QQmlDelegateModelGroupPrivate::get(d->m_groups[1])->emitters.insert(
this);
3728 m_compositorGroup = Compositor::Default;
3741 return m_model->filterGroup();
3742 return m_filterGroup;
3747 if (QQmlDelegateModelPrivate::get(m_model)->m_transaction) {
3748 qmlWarning(
this) << tr(
"The group of a DelegateModel cannot be changed within onChanged");
3752 if (m_filterGroup != group || m_inheritGroup) {
3753 m_filterGroup = group;
3754 m_inheritGroup =
false;
3757 emit filterGroupChanged();
3763 if (!m_inheritGroup) {
3764 m_inheritGroup =
true;
3766 emit filterGroupChanged();
3773 if (!model->m_cacheMetaType)
3776 if (m_inheritGroup) {
3777 if (m_filterGroup == model->m_filterGroup)
3779 m_filterGroup = model->m_filterGroup;
3782 QQmlListCompositor::Group previousGroup = m_compositorGroup;
3783 m_compositorGroup = Compositor::Default;
3784 QQmlDelegateModelGroupPrivate::get(model->m_groups[Compositor::Default])->emitters.insert(
this);
3786 if (m_filterGroup == model->m_cacheMetaType->groupNames.at(i - 1)) {
3787 m_compositorGroup = Compositor::Group(i);
3792 QQmlDelegateModelGroupPrivate::get(model->m_groups[m_compositorGroup])->emitters.insert(
this);
3793 if (m_compositorGroup != previousGroup) {
3794 QList<QQmlChangeSet::Change> removes;
3795 QList<QQmlChangeSet::Change> inserts;
3796 model->m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
3798 QQmlChangeSet changeSet;
3799 changeSet.move(removes, inserts);
3800 if (!changeSet.isEmpty())
3801 emit modelUpdated(changeSet,
false);
3803 if (changeSet.difference() != 0)
3804 emit countChanged();
3809 Compositor::Group group,
const QQmlChangeSet &changeSet)
3811 if (!m_inheritGroup)
3814 m_compositorGroup = group;
3815 QQmlDelegateModelGroupPrivate::get(QQmlDelegateModelPrivate::get(m_model)->m_groups[m_compositorGroup])->emitters.insert(
this);
3817 if (!changeSet.isEmpty())
3818 emit modelUpdated(changeSet,
false);
3820 if (changeSet.difference() != 0)
3821 emit countChanged();
3823 emit filterGroupChanged();
3829 return model->m_delegate
3830 ? model->m_compositor.count(m_compositorGroup)
3836 return m_model->isValid();
3843 if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup)) {
3844 qWarning() <<
"DelegateModel::item: index out range" << index << model->m_compositor.count(m_compositorGroup);
3848 QObject *object = model->object(m_compositorGroup, index, incubationMode);
3850 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) {
3851 QObject *part = package->part(m_part);
3854 m_packaged.insert(part, package);
3858 model->release(object);
3861 qmlWarning(model->m_delegate) << tr(
"Delegate component must be Package type.");
3870 QQmlInstanceModel::ReleaseFlags flags;
3872 auto it = m_packaged.find(item);
3873 if (it != m_packaged.end()) {
3874 QQuickPackage *package = *it;
3876 flags = model->release(package);
3877 m_packaged.erase(it);
3878 if (!m_packaged.contains(item))
3879 flags &= ~Referenced;
3880 if (flags & Destroyed)
3881 QQmlDelegateModelPrivate::get(m_model)->emitDestroyingPackage(package);
3888 return QQmlDelegateModelPrivate::get(m_model)->variantValue(m_compositorGroup, index, role);
3894 model->m_adaptorModel.replaceWatchedRoles(m_watchedRoles, roles);
3895 m_watchedRoles = roles;
3901 Compositor::iterator it = model->m_compositor.find(model->m_compositorGroup, index);
3903 return QQmlIncubator::Null;
3905 if (
auto incubationTask = model->m_cache.at(it.cacheIndex())->incubationTask())
3906 return incubationTask->status();
3908 return QQmlIncubator::Ready;
3913 auto it = m_packaged.find(item);
3914 if (it != m_packaged.end()) {
3916 return cacheItem->groupIndex(m_compositorGroup);
3923 emit createdItem(index, package->part(m_part));
3928 if (m_modelUpdatePending)
3929 m_pendingPackageInitializations << index;
3931 emit initItem(index, package->part(m_part));
3936 QObject *item = package->part(m_part);
3937 Q_ASSERT(!m_packaged.contains(item));
3938 emit destroyingItem(item);
3943 m_modelUpdatePending =
false;
3944 emit modelUpdated(changeSet, reset);
3945 if (changeSet.difference() != 0)
3946 emit countChanged();
3949 QList<
int> pendingPackageInitializations;
3950 qSwap(pendingPackageInitializations, m_pendingPackageInitializations);
3951 for (
int index : pendingPackageInitializations) {
3952 if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup))
3954 QObject *object = model->object(m_compositorGroup, index, QQmlIncubator::Asynchronous);
3955 if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
3956 emit initItem(index, package->part(m_part));
3957 model->release(object);
3964 if (Q_UNLIKELY(m_reusableItemsPool.size() == QQmlReusableDelegateModelItemsPool::MaxSize))
3967 Q_ASSERT(m_reusableItemsPool.size() < QQmlReusableDelegateModelItemsPool::MaxSize);
4013 Q_ASSERT(modelItem->object());
4014 Q_ASSERT(modelItem->delegate());
4016 m_reusableItemsPool.push_back({modelItem, 0});
4018 qCDebug(lcItemViewDelegateRecycling)
4019 <<
"item:" << modelItem
4020 <<
"delegate:" << modelItem->delegate()
4021 <<
"index:" << modelItem->modelIndex()
4022 <<
"row:" << modelItem->modelRow()
4023 <<
"column:" << modelItem->modelColumn()
4024 <<
"pool size:" << m_reusableItemsPool.size();
4033 for (
auto it = m_reusableItemsPool.cbegin(); it != m_reusableItemsPool.cend(); ++it) {
4035 if (modelItem->delegate() != delegate)
4037 m_reusableItemsPool.erase(it);
4039 qCDebug(lcItemViewDelegateRecycling)
4040 <<
"item:" << modelItem
4041 <<
"delegate:" << delegate
4042 <<
"old index:" << modelItem->modelIndex()
4043 <<
"old row:" << modelItem->modelRow()
4044 <<
"old column:" << modelItem->modelColumn()
4045 <<
"new index:" << newIndexHint
4046 <<
"pool size:" << m_reusableItemsPool.size();
4051 qCDebug(lcItemViewDelegateRecycling)
4052 <<
"no available item for delegate:" << delegate
4053 <<
"new index:" << newIndexHint
4054 <<
"pool size:" << m_reusableItemsPool.size();
4067 qCDebug(lcItemViewDelegateRecycling) <<
"pool size before drain:" << m_reusableItemsPool.size();
4069 if (maxPoolTime == 0) {
4071 const std::vector<PoolItem> removed = std::exchange(m_reusableItemsPool, {});
4072 for (
const PoolItem &item : removed)
4073 releaseItem(item.item);
4074 qCDebug(lcItemViewDelegateRecycling) <<
"pool size after drain: 0";
4078 const auto begin = m_reusableItemsPool.begin();
4079 const auto oldEnd = m_reusableItemsPool.end();
4080 const auto newEnd = std::stable_partition(
4082 [maxPoolTime](
const PoolItem &item) {
return item.poolTime < maxPoolTime; });
4083 std::for_each(begin, newEnd, [](PoolItem &item) { ++item.poolTime; });
4085 QVarLengthArray<PoolItem> removed;
4086 removed.reserve(oldEnd - newEnd);
4087 std::move(newEnd, oldEnd, std::back_inserter(removed));
4088 m_reusableItemsPool.erase(newEnd, oldEnd);
4090 for (
const PoolItem &item : removed)
4091 releaseItem(item.item);
4093 qCDebug(lcItemViewDelegateRecycling) <<
"pool size after drain:" << m_reusableItemsPool.size();
4189 this->changes =
new QList<QQmlChangeSet::Change>(changes);
4190 QV4::Scope scope(internalClass->engine);
4191 QV4::ScopedObject o(scope,
this);
4192 o->setArrayType(QV4::Heap::ArrayData::Custom);
4199 QV4::Scope scope(v4);
4201 QV4::ScopedObject proto(scope, v4->newObject());
4202 proto->defineAccessorProperty(QStringLiteral(
"index"), QQmlDelegateModelGroupChange::method_get_index,
nullptr);
4203 proto->defineAccessorProperty(QStringLiteral(
"count"), QQmlDelegateModelGroupChange::method_get_count,
nullptr);
4204 proto->defineAccessorProperty(QStringLiteral(
"moveId"), QQmlDelegateModelGroupChange::method_get_moveId,
nullptr);
4205 changeProto.set(v4, proto);
4213 const QList<QQmlChangeSet::Change> &changes)
4215 QV4::Scope scope(v4);
4216 QV4::ScopedObject o(scope, QQmlDelegateModelGroupChangeArray::create(v4, changes));
4217 return o.asReturnedValue();
4222#include "moc_qqmldelegatemodel_p_p.cpp"
4224#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 QList< 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 destroyObjectLater()
void disableStructuredModelData()
void childContextObjectDestroyed(QObject *childContextObject)
bool isScriptReferenced() const
int groupIndex(Compositor::Group group)
void setGroups(int groups)
void setIncubationTask(QQDMIncubationTask *incubationTask)
virtual void setModelIndex(int idx, int newRow, int newColumn, bool alwaysEmit=false)
bool isObjectReferenced() const
QQmlDelegateModelItem(const QQmlRefPointer< QQmlDelegateModelItemMetaType > &metaType, QQmlAdaptorModel::Accessors *accessor, int modelIndex, int row, int column)
void clearIncubationTask()
QQmlDelegateModelAttached * attached() const
QQDMIncubationTask * incubationTask() 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)
void itemsMoved(const QList< Compositor::Remove > &removes, const QList< Compositor::Insert > &inserts)
QQmlDelegateModelParts * m_parts
QQmlAbstractDelegateComponent * m_delegateChooser
void itemsInserted(const QList< Compositor::Insert > &inserts)
void addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it)
void reuseItem(QQmlDelegateModelItem *item, int newModelIndex, int newGroups)
void drainReusableItemsPool(int maxPoolTime)
void itemsRemoved(const QList< Compositor::Remove > &removes, QVarLengthArray< QList< QQmlChangeSet::Change >, Compositor::MaximumGroupCount > *translatedRemoves, QHash< int, QList< QQmlDelegateModelItem * > > *movedItems=nullptr)
QQmlDelegateModelGroupEmitterList m_pendingParts
void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override
QObject * object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode)
void destroyCacheItem(QQmlDelegateModelItem *cacheItem)
void itemsRemoved(const QList< Compositor::Remove > &removes)
void connectToAbstractItemModel()
int adaptorModelCount() const
InsertionResult insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups)
void setGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
void delegateChanged(bool add=true, bool remove=true)
void releaseIncubator(QQDMIncubationTask *incubationTask)
bool m_waitingToFetchMore
void itemsInserted(const QList< Compositor::Insert > &inserts, QVarLengthArray< QList< QQmlChangeSet::Change >, Compositor::MaximumGroupCount > *translatedInserts, QHash< int, QList< QQmlDelegateModelItem * > > *movedItems=nullptr)
void incubatorStatusChanged(QQDMIncubationTask *incubationTask, QQmlIncubator::Status status)
void emitInitPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package)
void addGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
void emitDestroyingPackage(QQuickPackage *package)
void requestMoreIfNecessary()
QQmlComponent * resolveDelegate(int index)
void removeGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
void itemsChanged(const QList< Compositor::Change > &changes)
void disconnectFromAbstractItemModel()
~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 QList< QQmlChangeSet::Change > &changes)
QList< QQmlChangeSet::Change > * changes
QQmlChangeSet::ChangeData change
QQmlDelegateModelItem * item() const