8#include <private/qqmlglobal_p.h>
9#include <private/qqmlchangeset_p.h>
10#include <private/qqmldelegatemodel_p.h>
12#include <QtQml/QQmlInfo>
13#include <QtQml/qqmlcomponent.h>
17QQuickRepeaterPrivate::QQuickRepeaterPrivate()
20 , delegateValidated(
false)
21 , explicitDelegate(
false)
22 , explicitDelegateModelAccess(
false)
25 setTransparentForPositioner(
true);
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
104
105
106
107
108
109
112
113
114
115
116
117
118
119
120
121QQuickRepeater::QQuickRepeater(QQuickItem *parent)
122 : QQuickItem(*(
new QQuickRepeaterPrivate), parent)
126QQuickRepeater::~QQuickRepeater()
129 QQmlDelegateModelPointer model(d->model);
130 d->disconnectModel(
this, &model);
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151QVariant QQuickRepeater::model()
const
153 Q_D(
const QQuickRepeater);
156 return static_cast<QQmlDelegateModel *>(d->model.data())->model();
158 return QVariant::fromValue(d->model.data());
162void QQuickRepeater::setModel(
const QVariant &m)
166 if (model.userType() == qMetaTypeId<QJSValue>())
167 model = model.value<QJSValue>().toVariant();
169 QQmlDelegateModelPointer oldModel(d->model);
171 if (oldModel.delegateModel()->model() == model)
173 }
else if (QVariant::fromValue(d->model) == model) {
179 d->disconnectModel(
this, &oldModel);
182 QObject *object = qvariant_cast<QObject *>(model);
184 QQmlDelegateModelPointer newModel(qobject_cast<QQmlInstanceModel *>(object));
186 if (d->explicitDelegate) {
187 QQmlComponent *delegate =
nullptr;
188 if (QQmlDelegateModel *old = oldModel.delegateModel())
189 delegate = old->delegate();
191 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
192 delegateModel->setDelegate(delegate);
193 }
else if (delegate) {
194 qmlWarning(
this) <<
"Cannot retain explicitly set delegate on non-DelegateModel";
195 d->explicitDelegate =
false;
199 if (d->explicitDelegateModelAccess) {
200 QQmlDelegateModel::DelegateModelAccess access = QQmlDelegateModel::Qt5ReadWrite;
201 if (QQmlDelegateModel *old = oldModel.delegateModel())
202 access = old->delegateModelAccess();
204 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
205 delegateModel->setDelegateModelAccess(access);
206 }
else if (access != QQmlDelegateModel::Qt5ReadWrite) {
207 qmlWarning(
this) <<
"Cannot retain explicitly set delegate model access "
208 "on non-DelegateModel";
209 d->explicitDelegateModelAccess =
false;
214 delete oldModel.instanceModel();
217 d->model = newModel.instanceModel();
218 }
else if (d->ownModel) {
220 Q_ASSERT(oldModel.delegateModel());
222 d->model = newModel.instanceModel();
223 newModel.delegateModel()->setModel(model);
225 newModel = QQmlDelegateModel::createForView(
this, d);
226 if (d->explicitDelegate) {
227 QQmlComponent *delegate =
nullptr;
228 if (QQmlDelegateModel *old = oldModel.delegateModel())
229 delegate = old->delegate();
230 newModel.delegateModel()->setDelegate(delegate);
233 if (d->explicitDelegateModelAccess) {
234 QQmlDelegateModel::DelegateModelAccess access = QQmlDelegateModel::Qt5ReadWrite;
235 if (QQmlDelegateModel *old = oldModel.delegateModel())
236 access = old->delegateModelAccess();
237 newModel.delegateModel()->setDelegateModelAccess(access);
240 newModel.delegateModel()->setModel(model);
243 d->connectModel(
this, &newModel);
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281QQmlComponent *QQuickRepeater::delegate()
const
283 Q_D(
const QQuickRepeater);
285 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
286 return dataModel->delegate();
292void QQuickRepeater::setDelegate(QQmlComponent *delegate)
295 const auto setExplicitDelegate = [&](QQmlDelegateModel *delegateModel) {
296 if (delegateModel->delegate() == delegate) {
297 d->explicitDelegate =
true;
301 const int oldCount = delegateModel->count();
302 delegateModel->setDelegate(delegate);
304 if (oldCount != delegateModel->count())
306 d->explicitDelegate =
true;
307 d->delegateValidated =
false;
313 d->explicitDelegate =
true;
317 setExplicitDelegate(QQmlDelegateModel::createForView(
this, d));
321 emit delegateChanged();
325 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
327 d->explicitDelegate =
false;
328 setExplicitDelegate(delegateModel);
333 qmlWarning(
this) <<
"Cannot set a delegate on an explicitly provided non-DelegateModel";
335 d->explicitDelegate =
true;
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365int QQuickRepeater::count()
const
367 Q_D(
const QQuickRepeater);
369 return d->model->count();
374
375
376
377
378
379QQuickItem *QQuickRepeater::itemAt(
int index)
const
381 Q_D(
const QQuickRepeater);
382 if (index >= 0 && index < d->deletables.size())
383 return d->deletables[index];
387void QQuickRepeater::componentComplete()
390 if (d->model && d->ownModel)
391 static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
392 QQuickItem::componentComplete();
394 if (d->model && d->model->count())
398void QQuickRepeater::itemChange(ItemChange change,
const ItemChangeData &value)
400 QQuickItem::itemChange(change, value);
401 if (change == ItemParentHasChanged) {
406void QQuickRepeater::clear()
409 bool complete = isComponentComplete();
414 for (
int i = d->deletables.size() - 1; i >= 0; --i) {
415 if (QQuickItem *item = d->deletables.at(i)) {
417 emit itemRemoved(i, item);
418 d->model->release(item);
421 for (QQuickItem *item : std::as_const(d->deletables)) {
423 item->setParentItem(
nullptr);
426 d->deletables.clear();
430void QQuickRepeater::regenerate()
433 if (!isComponentComplete())
438 if (!d->model || !d->model->count() || !d->model->isValid() || !parentItem() || !isComponentComplete())
441 d->itemCount = count();
442 d->deletables.resize(d->itemCount);
448 for (
int i = 0; i < itemCount; i++) {
449 QObject *object = model->object(i, QQmlIncubator::AsynchronousIfNested);
451 model->release(object);
457 QQmlInstanceModel *instanceModel = model->instanceModel();
461 QObject::connect(instanceModel, &QQmlInstanceModel::modelUpdated,
462 q, &QQuickRepeater::modelUpdated);
463 QObject::connect(instanceModel, &QQmlInstanceModel::createdItem,
464 q, &QQuickRepeater::createdItem);
465 QObject::connect(instanceModel, &QQmlInstanceModel::initItem,
466 q, &QQuickRepeater::initItem);
467 if (QQmlDelegateModel *dataModel = model->delegateModel()) {
468 QObjectPrivate::connect(
469 dataModel, &QQmlDelegateModel::delegateChanged,
470 this, &QQuickRepeaterPrivate::applyDelegateChange);
471 QObjectPrivate::connect(
472 dataModel, &QQmlDelegateModel::delegateModelAccessChanged,
473 this, &QQuickRepeaterPrivate::applyDelegateModelAccessChange);
475 QObject::connect(dataModel, &QQmlDelegateModel::modelChanged,
476 q, &QQuickRepeater::modelChanged);
484 QQmlInstanceModel *instanceModel = model->instanceModel();
488 QObject::disconnect(instanceModel, &QQmlInstanceModel::modelUpdated,
489 q, &QQuickRepeater::modelUpdated);
490 QObject::disconnect(instanceModel, &QQmlInstanceModel::createdItem,
491 q, &QQuickRepeater::createdItem);
492 QObject::disconnect(instanceModel, &QQmlInstanceModel::initItem,
493 q, &QQuickRepeater::initItem);
494 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
495 QObjectPrivate::disconnect(
496 delegateModel, &QQmlDelegateModel::delegateChanged,
497 this, &QQuickRepeaterPrivate::applyDelegateChange);
498 QObjectPrivate::disconnect(
499 delegateModel, &QQmlDelegateModel::delegateModelAccessChanged,
500 this, &QQuickRepeaterPrivate::applyDelegateModelAccessChange);
502 QObject::disconnect(delegateModel, &QQmlDelegateModel::modelChanged,
503 q, &QQuickRepeater::modelChanged);
508void QQuickRepeater::createdItem(
int index, QObject *)
511 QObject *object = d->model->object(index, QQmlIncubator::AsynchronousIfNested);
512 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
513 emit itemAdded(index, item);
516void QQuickRepeater::initItem(
int index, QObject *object)
519 if (index >= d->deletables.size()) {
523 d->deletables.resize(d->model->count() + 1);
525 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
527 if (!d->deletables.at(index)) {
530 d->model->release(object);
531 if (!d->delegateValidated) {
532 d->delegateValidated =
true;
533 QObject* delegate =
this->delegate();
534 qmlWarning(delegate ? delegate :
this) << QQuickRepeater::tr(
"Delegate must be of Item type");
539 d->deletables[index] = item;
540 item->setParentItem(parentItem());
545 if (d->model && !d->ownModel)
546 QQuickItemPrivate::get(item)->setCulled(
false);
547 if (index > 0 && d->deletables.at(index-1)) {
548 item->stackAfter(d->deletables.at(index-1));
550 QQuickItem *after =
this;
551 for (
int si = index+1; si < d->itemCount; ++si) {
552 if (d->deletables.at(si)) {
553 after = d->deletables.at(si);
557 item->stackBefore(after);
562void QQuickRepeater::modelUpdated(
const QQmlChangeSet &changeSet,
bool reset)
566 if (!isComponentComplete())
571 if (changeSet.difference() != 0)
577 QHash<
int, QVector<QPointer<QQuickItem> > > moved;
578 for (
const QQmlChangeSet::Change &remove : changeSet.removes()) {
579 int index = qMin(remove.index, d->deletables.size());
580 int count = qMin(remove.index + remove.count, d->deletables.size()) - index;
581 if (remove.isMove()) {
582 moved.insert(remove.moveId, d->deletables.mid(index, count));
584 d->deletables.begin() + index,
585 d->deletables.begin() + index + count);
586 }
else while (count--) {
587 QQuickItem *item = d->deletables.at(index);
588 d->deletables.remove(index);
589 emit itemRemoved(index, item);
591 d->model->release(item);
592 item->setParentItem(
nullptr);
597 difference -= remove.count;
600 for (
const QQmlChangeSet::Change &insert : changeSet.inserts()) {
601 int index = qMin(insert.index, d->deletables.size());
602 if (insert.isMove()) {
603 QVector<QPointer<QQuickItem> > items = moved.value(insert.moveId);
604 d->deletables = d->deletables.mid(0, index) + items + d->deletables.mid(index);
605 QQuickItem *stackBefore = index + items.size() < d->deletables.size()
606 ? d->deletables.at(index + items.size())
609 for (
int i = index; i < index + items.size(); ++i) {
610 if (i < d->deletables.size()) {
611 QPointer<QQuickItem> item = d->deletables.at(i);
613 item->stackBefore(stackBefore);
617 }
else for (
int i = 0; i < insert.count; ++i) {
618 int modelIndex = index + i;
620 d->deletables.insert(modelIndex,
nullptr);
621 QObject *object = d->model->object(modelIndex, QQmlIncubator::AsynchronousIfNested);
623 d->model->release(object);
625 difference += insert.count;
633
634
635
636
637QQmlDelegateModel::DelegateModelAccess QQuickRepeater::delegateModelAccess()
const
639 Q_D(
const QQuickRepeater);
640 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->model))
641 return dataModel->delegateModelAccess();
642 return QQmlDelegateModel::Qt5ReadWrite;
645void QQuickRepeater::setDelegateModelAccess(
646 QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
649 const auto setExplicitDelegateModelAccess = [&](QQmlDelegateModel *delegateModel) {
650 delegateModel->setDelegateModelAccess(delegateModelAccess);
651 d->explicitDelegateModelAccess =
true;
655 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
657 d->explicitDelegateModelAccess =
true;
661 setExplicitDelegateModelAccess(QQmlDelegateModel::createForView(
this, d));
666 emit delegateModelAccessChanged();
670 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
673 d->explicitDelegateModelAccess =
false;
674 setExplicitDelegateModelAccess(delegateModel);
678 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
679 d->explicitDelegateModelAccess =
true;
681 qmlWarning(
this) <<
"Cannot set a delegateModelAccess on an explicitly provided "
688#include "moc_qquickrepeater_p.cpp"