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
102
103
106
107
108
109
110
111
114
115
116
117
118
119
120
121
122
123QQuickRepeater::QQuickRepeater(QQuickItem *parent)
124 : QQuickItem(*(
new QQuickRepeaterPrivate), parent)
128QQuickRepeater::~QQuickRepeater()
131 QQmlDelegateModelPointer model(d->model);
132 d->disconnectModel(
this, &model);
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153QVariant QQuickRepeater::model()
const
155 Q_D(
const QQuickRepeater);
158 return static_cast<QQmlDelegateModel *>(d->model.data())->model();
160 return QVariant::fromValue(d->model.data());
164void QQuickRepeater::setModel(
const QVariant &m)
168 if (model.userType() == qMetaTypeId<QJSValue>())
169 model = model.value<QJSValue>().toVariant();
171 QQmlDelegateModelPointer oldModel(d->model);
173 if (oldModel.delegateModel()->model() == model)
175 }
else if (QVariant::fromValue(d->model) == model) {
181 d->disconnectModel(
this, &oldModel);
184 QObject *object = qvariant_cast<QObject *>(model);
186 QQmlDelegateModelPointer newModel(qobject_cast<QQmlInstanceModel *>(object));
188 if (d->explicitDelegate) {
189 QQmlComponent *delegate =
nullptr;
190 if (QQmlDelegateModel *old = oldModel.delegateModel())
191 delegate = old->delegate();
193 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
194 delegateModel->setDelegate(delegate);
195 }
else if (delegate) {
196 qmlWarning(
this) <<
"Cannot retain explicitly set delegate on non-DelegateModel";
197 d->explicitDelegate =
false;
201 if (d->explicitDelegateModelAccess) {
202 QQmlDelegateModel::DelegateModelAccess access = QQmlDelegateModel::Qt5ReadWrite;
203 if (QQmlDelegateModel *old = oldModel.delegateModel())
204 access = old->delegateModelAccess();
206 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
207 delegateModel->setDelegateModelAccess(access);
208 }
else if (access != QQmlDelegateModel::Qt5ReadWrite) {
209 qmlWarning(
this) <<
"Cannot retain explicitly set delegate model access "
210 "on non-DelegateModel";
211 d->explicitDelegateModelAccess =
false;
216 delete oldModel.instanceModel();
219 d->model = newModel.instanceModel();
220 }
else if (d->ownModel) {
222 Q_ASSERT(oldModel.delegateModel());
224 d->model = newModel.instanceModel();
225 newModel.delegateModel()->setModel(model);
227 newModel = QQmlDelegateModel::createForView(
this, d);
228 if (d->explicitDelegate) {
229 QQmlComponent *delegate =
nullptr;
230 if (QQmlDelegateModel *old = oldModel.delegateModel())
231 delegate = old->delegate();
232 newModel.delegateModel()->setDelegate(delegate);
235 if (d->explicitDelegateModelAccess) {
236 QQmlDelegateModel::DelegateModelAccess access = QQmlDelegateModel::Qt5ReadWrite;
237 if (QQmlDelegateModel *old = oldModel.delegateModel())
238 access = old->delegateModelAccess();
239 newModel.delegateModel()->setDelegateModelAccess(access);
242 newModel.delegateModel()->setModel(model);
245 d->connectModel(
this, &newModel);
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
281
282
283
284
285QQmlComponent *QQuickRepeater::delegate()
const
287 Q_D(
const QQuickRepeater);
289 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
290 return dataModel->delegate();
296void QQuickRepeater::setDelegate(QQmlComponent *delegate)
299 const auto setExplicitDelegate = [&](QQmlDelegateModel *delegateModel) {
300 if (delegateModel->delegate() == delegate) {
301 d->explicitDelegate =
true;
305 const int oldCount = delegateModel->count();
306 delegateModel->setDelegate(delegate);
308 if (oldCount != delegateModel->count())
310 d->explicitDelegate =
true;
311 d->delegateValidated =
false;
317 d->explicitDelegate =
true;
321 setExplicitDelegate(QQmlDelegateModel::createForView(
this, d));
325 emit delegateChanged();
329 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
331 d->explicitDelegate =
false;
332 setExplicitDelegate(delegateModel);
337 qmlWarning(
this) <<
"Cannot set a delegate on an explicitly provided non-DelegateModel";
339 d->explicitDelegate =
true;
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369int QQuickRepeater::count()
const
371 Q_D(
const QQuickRepeater);
373 return d->model->count();
378
379
380
381
382
383QQuickItem *QQuickRepeater::itemAt(
int index)
const
385 Q_D(
const QQuickRepeater);
386 if (index >= 0 && index < d->deletables.size())
387 return d->deletables[index];
391void QQuickRepeater::componentComplete()
394 if (d->model && d->ownModel)
395 static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
396 QQuickItem::componentComplete();
398 if (d->model && d->model->count())
402void QQuickRepeater::itemChange(ItemChange change,
const ItemChangeData &value)
404 QQuickItem::itemChange(change, value);
405 if (change == ItemParentHasChanged) {
410void QQuickRepeater::clear()
413 bool complete = isComponentComplete();
418 for (
int i = d->deletables.size() - 1; i >= 0; --i) {
419 if (QQuickItem *item = d->deletables.at(i)) {
421 emit itemRemoved(i, item);
422 d->model->release(item);
425 for (QQuickItem *item : std::as_const(d->deletables)) {
427 item->setParentItem(
nullptr);
430 d->deletables.clear();
434void QQuickRepeater::regenerate()
437 if (!isComponentComplete())
442 if (!d->model || !d->model->count() || !d->model->isValid() || !parentItem() || !isComponentComplete())
445 d->itemCount = count();
446 d->deletables.resize(d->itemCount);
452 for (
int i = 0; i < itemCount; i++) {
453 QObject *object = model->object(i, QQmlIncubator::AsynchronousIfNested);
455 model->release(object);
461 QQmlInstanceModel *instanceModel = model->instanceModel();
465 QObject::connect(instanceModel, &QQmlInstanceModel::modelUpdated,
466 q, &QQuickRepeater::modelUpdated);
467 QObject::connect(instanceModel, &QQmlInstanceModel::createdItem,
468 q, &QQuickRepeater::createdItem);
469 QObject::connect(instanceModel, &QQmlInstanceModel::initItem,
470 q, &QQuickRepeater::initItem);
471 if (QQmlDelegateModel *dataModel = model->delegateModel()) {
472 QObjectPrivate::connect(
473 dataModel, &QQmlDelegateModel::delegateChanged,
474 this, &QQuickRepeaterPrivate::applyDelegateChange);
475 QObjectPrivate::connect(
476 dataModel, &QQmlDelegateModel::delegateModelAccessChanged,
477 this, &QQuickRepeaterPrivate::applyDelegateModelAccessChange);
479 QObject::connect(dataModel, &QQmlDelegateModel::modelChanged,
480 q, &QQuickRepeater::modelChanged);
488 QQmlInstanceModel *instanceModel = model->instanceModel();
492 QObject::disconnect(instanceModel, &QQmlInstanceModel::modelUpdated,
493 q, &QQuickRepeater::modelUpdated);
494 QObject::disconnect(instanceModel, &QQmlInstanceModel::createdItem,
495 q, &QQuickRepeater::createdItem);
496 QObject::disconnect(instanceModel, &QQmlInstanceModel::initItem,
497 q, &QQuickRepeater::initItem);
498 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
499 QObjectPrivate::disconnect(
500 delegateModel, &QQmlDelegateModel::delegateChanged,
501 this, &QQuickRepeaterPrivate::applyDelegateChange);
502 QObjectPrivate::disconnect(
503 delegateModel, &QQmlDelegateModel::delegateModelAccessChanged,
504 this, &QQuickRepeaterPrivate::applyDelegateModelAccessChange);
506 QObject::disconnect(delegateModel, &QQmlDelegateModel::modelChanged,
507 q, &QQuickRepeater::modelChanged);
512void QQuickRepeater::createdItem(
int index, QObject *)
515 QObject *object = d->model->object(index, QQmlIncubator::AsynchronousIfNested);
516 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
517 emit itemAdded(index, item);
520void QQuickRepeater::initItem(
int index, QObject *object)
523 if (index >= d->deletables.size()) {
527 d->deletables.resize(d->model->count() + 1);
529 QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
531 if (!d->deletables.at(index)) {
534 d->model->release(object);
535 if (!d->delegateValidated) {
536 d->delegateValidated =
true;
537 QObject* delegate =
this->delegate();
538 qmlWarning(delegate ? delegate :
this) << QQuickRepeater::tr(
"Delegate must be of Item type");
543 d->deletables[index] = item;
544 item->setParentItem(parentItem());
549 if (d->model && !d->ownModel)
550 QQuickItemPrivate::get(item)->setCulled(
false);
551 if (index > 0 && d->deletables.at(index-1)) {
552 item->stackAfter(d->deletables.at(index-1));
554 QQuickItem *after =
this;
555 for (
int si = index+1; si < d->itemCount; ++si) {
556 if (d->deletables.at(si)) {
557 after = d->deletables.at(si);
561 item->stackBefore(after);
566void QQuickRepeater::modelUpdated(
const QQmlChangeSet &changeSet,
bool reset)
570 if (!isComponentComplete())
575 if (changeSet.difference() != 0)
581 QHash<
int, QList<QPointer<QQuickItem> > > moved;
582 for (
const QQmlChangeSet::Change &remove : changeSet.removes()) {
583 int index = qMin(remove.index, d->deletables.size());
584 int count = qMin(remove.index + remove.count, d->deletables.size()) - index;
585 if (remove.isMove()) {
586 moved.insert(remove.moveId, d->deletables.mid(index, count));
588 d->deletables.begin() + index,
589 d->deletables.begin() + index + count);
590 }
else while (count--) {
591 QQuickItem *item = d->deletables.at(index);
592 d->deletables.remove(index);
593 emit itemRemoved(index, item);
595 d->model->release(item);
596 item->setParentItem(
nullptr);
601 difference -= remove.count;
604 for (
const QQmlChangeSet::Change &insert : changeSet.inserts()) {
605 int index = qMin(insert.index, d->deletables.size());
606 if (insert.isMove()) {
607 QList<QPointer<QQuickItem> > items = moved.value(insert.moveId);
608 d->deletables = d->deletables.mid(0, index) + items + d->deletables.mid(index);
609 QQuickItem *stackBefore = index + items.size() < d->deletables.size()
610 ? d->deletables.at(index + items.size())
613 for (
int i = index; i < index + items.size(); ++i) {
614 if (i < d->deletables.size()) {
615 QPointer<QQuickItem> item = d->deletables.at(i);
617 item->stackBefore(stackBefore);
621 }
else for (
int i = 0; i < insert.count; ++i) {
622 int modelIndex = index + i;
624 d->deletables.insert(modelIndex,
nullptr);
625 QObject *object = d->model->object(modelIndex, QQmlIncubator::AsynchronousIfNested);
627 d->model->release(object);
629 difference += insert.count;
637
638
639
640
641
642QQmlDelegateModel::DelegateModelAccess QQuickRepeater::delegateModelAccess()
const
644 Q_D(
const QQuickRepeater);
645 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->model))
646 return dataModel->delegateModelAccess();
647 return QQmlDelegateModel::Qt5ReadWrite;
650void QQuickRepeater::setDelegateModelAccess(
651 QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
654 const auto setExplicitDelegateModelAccess = [&](QQmlDelegateModel *delegateModel) {
655 delegateModel->setDelegateModelAccess(delegateModelAccess);
656 d->explicitDelegateModelAccess =
true;
660 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
662 d->explicitDelegateModelAccess =
true;
666 setExplicitDelegateModelAccess(QQmlDelegateModel::createForView(
this, d));
671 emit delegateModelAccessChanged();
675 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(d->model)) {
678 d->explicitDelegateModelAccess =
false;
679 setExplicitDelegateModelAccess(delegateModel);
683 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
684 d->explicitDelegateModelAccess =
true;
686 qmlWarning(
this) <<
"Cannot set a delegateModelAccess on an explicitly provided "
693#include "moc_qquickrepeater_p.cpp"
Combined button and popup list for selecting options.