8#include <private/qqmlglobal_p.h>
9#include <private/qqmllistaccessor_p.h>
10#include <private/qqmlchangeset_p.h>
12#include <QtQml/QQmlInfo>
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
40
41
42
43
44
45
46
47
50
51
52
53
54
55
56
57
58
59
60
62QQuick3DRepeater::QQuick3DRepeater(QQuick3DNode *parent)
63 : QQuick3DNode(parent)
67 , m_delegateValidated(
false)
68 , m_explicitDelegate(
false)
69 , m_explicitDelegateModelAccess(
false)
73QQuick3DRepeater::~QQuick3DRepeater()
78 QQmlDelegateModelPointer model(m_model);
79 disconnectModel(&model);
83void QQuick3DRepeater::connectModel(QQmlDelegateModelPointer *model)
85 QQmlInstanceModel *instanceModel = model->instanceModel();
89 connect(instanceModel, &QQmlInstanceModel::modelUpdated,
90 this, &QQuick3DRepeater::modelUpdated);
91 connect(instanceModel, &QQmlInstanceModel::createdItem,
92 this, &QQuick3DRepeater::createdObject);
93 connect(instanceModel, &QQmlInstanceModel::initItem,
94 this, &QQuick3DRepeater::initObject);
95 if (QQmlDelegateModel *dataModel = model->delegateModel()) {
97 dataModel, &QQmlDelegateModel::delegateChanged,
98 this, &QQuick3DRepeater::applyDelegateChange);
101 dataModel, &QQmlDelegateModel::modelChanged,
102 this, &QQuick3DRepeater::modelChanged);
109void QQuick3DRepeater::disconnectModel(QQmlDelegateModelPointer *model)
111 QQmlInstanceModel *instanceModel = model->instanceModel();
115 disconnect(instanceModel, &QQmlInstanceModel::modelUpdated,
116 this, &QQuick3DRepeater::modelUpdated);
117 disconnect(instanceModel, &QQmlInstanceModel::createdItem,
118 this, &QQuick3DRepeater::createdObject);
119 disconnect(instanceModel, &QQmlInstanceModel::initItem,
120 this, &QQuick3DRepeater::initObject);
121 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
123 delegateModel, &QQmlDelegateModel::delegateChanged,
124 this, &QQuick3DRepeater::applyDelegateChange);
127 delegateModel, &QQmlDelegateModel::modelChanged,
128 this, &QQuick3DRepeater::modelChanged);
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
152QVariant QQuick3DRepeater::model()
const
155 return static_cast<QQmlDelegateModel *>(m_model.data())->model();
157 return QVariant::fromValue(m_model.data());
161void QQuick3DRepeater::applyDelegateChange()
163 if (m_explicitDelegate) {
164 qmlWarning(
this) <<
"Explicitly set delegate is externally overridden";
165 m_explicitDelegate =
false;
168 emit delegateChanged();
171QQmlDelegateModel *QQuick3DRepeater::createDelegateModel()
173 Q_ASSERT(m_model.isNull());
174 QQmlDelegateModel *delegateModel =
new QQmlDelegateModel(qmlContext(
this),
this);
175 m_model = delegateModel;
177 if (isComponentComplete())
178 delegateModel->componentComplete();
179 return delegateModel;
182void QQuick3DRepeater::setModel(
const QVariant &m)
185 if (model.userType() == qMetaTypeId<QJSValue>())
186 model = model.value<QJSValue>().toVariant();
188 QQmlDelegateModelPointer oldModel(m_model);
190 if (oldModel.delegateModel()->model() == model)
192 }
else if (QVariant::fromValue(m_model) == model) {
198 disconnectModel(&oldModel);
202 QObject *object = qvariant_cast<QObject *>(model);
204 QQmlDelegateModelPointer newModel(qobject_cast<QQmlInstanceModel *>(object));
206 if (m_explicitDelegate) {
207 QQmlComponent *delegate =
nullptr;
208 if (QQmlDelegateModel *old = oldModel.delegateModel())
209 delegate = old->delegate();
210 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
211 delegateModel->setDelegate(delegate);
212 }
else if (delegate) {
213 qmlWarning(
this) <<
"Cannot retain explicitly set delegate on non-DelegateModel";
214 m_explicitDelegate =
false;
218 delete oldModel.instanceModel();
221 m_model = newModel.instanceModel();
222 }
else if (m_ownModel) {
224 Q_ASSERT(oldModel.delegateModel());
226 m_model = newModel.instanceModel();
227 newModel.delegateModel()->setModel(model);
229 newModel = createDelegateModel();
230 if (m_explicitDelegate) {
231 QQmlComponent *delegate =
nullptr;
232 if (QQmlDelegateModel *old = oldModel.delegateModel())
233 delegate = old->delegate();
234 newModel.delegateModel()->setDelegate(delegate);
237 newModel.delegateModel()->setModel(model);
240 connectModel(&newModel);
247
248
249
250
251
252
253
254
255
256
257
258
259
260
262QQmlComponent *QQuick3DRepeater::delegate()
const
265 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(m_model))
266 return dataModel->delegate();
272void QQuick3DRepeater::setDelegate(QQmlComponent *delegate)
274 const auto setExplicitDelegate = [&](QQmlDelegateModel *delegateModel) {
275 if (delegateModel->delegate() == delegate) {
276 m_explicitDelegate =
true;
280 const int oldCount = delegateModel->count();
281 delegateModel->setDelegate(delegate);
283 if (oldCount != delegateModel->count())
285 m_explicitDelegate =
true;
286 m_delegateValidated =
false;
292 m_explicitDelegate =
true;
296 setExplicitDelegate(createDelegateModel());
300 emit delegateChanged();
304 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(m_model)) {
306 m_explicitDelegate =
false;
307 setExplicitDelegate(delegateModel);
312 qmlWarning(
this) <<
"Cannot set a delegate on an explicitly provided non-DelegateModel";
314 m_explicitDelegate =
true;
318
319
320
321
322
323
324
325
326
328int QQuick3DRepeater::count()
const
331 return m_model->count();
336
337
338
339
340
342QQuick3DObject *QQuick3DRepeater::objectAt(
int index)
const
344 if (index >= 0 && index < m_deletables.size())
345 return m_deletables[index];
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371QQmlDelegateModel::DelegateModelAccess QQuick3DRepeater::delegateModelAccess()
const
373 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(m_model))
374 return dataModel->delegateModelAccess();
375 return QQmlDelegateModel::Qt5ReadWrite;
378void QQuick3DRepeater::setDelegateModelAccess(QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
380 const auto setExplicitDelegateModelAccess = [&](QQmlDelegateModel *delegateModel) {
381 delegateModel->setDelegateModelAccess(delegateModelAccess);
382 m_explicitDelegateModelAccess =
true;
386 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
388 m_explicitDelegateModelAccess =
true;
392 QQmlDelegateModel *delegateModel =
new QQmlDelegateModel(qmlContext(
this),
this);
393 m_model = delegateModel;
395 if (isComponentComplete())
396 delegateModel->componentComplete();
398 setExplicitDelegateModelAccess(delegateModel);
403 emit delegateModelAccessChanged();
407 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(m_model)) {
410 m_explicitDelegateModelAccess =
false;
411 setExplicitDelegateModelAccess(delegateModel);
415 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
416 m_explicitDelegateModelAccess =
true;
418 qmlWarning(
this) <<
"Cannot set a delegateModelAccess on an explicitly provided "
423void QQuick3DRepeater::clear()
425 bool complete = isComponentComplete();
430 for (
int i = m_deletables.size() - 1; i >= 0; --i) {
431 if (QQuick3DObject *item = m_deletables.at(i)) {
433 emit objectRemoved(i, item);
434 m_model->release(item);
437 for (QQuick3DObject *item : std::as_const(m_deletables)) {
439 item->setParentItem(
nullptr);
442 m_deletables.clear();
446void QQuick3DRepeater::regenerate()
448 if (!isComponentComplete())
453 if (!m_model || !m_model->count() || !m_model->isValid() || !parentItem() || !isComponentComplete())
456 m_itemCount = count();
457 m_deletables.resize(m_itemCount);
461void QQuick3DRepeater::componentComplete()
463 if (m_model && m_ownModel)
464 static_cast<QQmlDelegateModel *>(m_model.data())->componentComplete();
465 QQuick3DNode::componentComplete();
467 if (m_model && m_model->count())
471void QQuick3DRepeater::itemChange(QQuick3DObject::ItemChange change,
const QQuick3DObject::ItemChangeData &value)
473 QQuick3DObject::itemChange(change, value);
474 if (change == ItemParentHasChanged) {
479void QQuick3DRepeater::createdObject(
int index, QObject *)
481 QObject *object = m_model->object(index, QQmlIncubator::AsynchronousIfNested);
482 QQuick3DObject *item = qmlobject_cast<QQuick3DObject*>(object);
483 emit objectAdded(index, item);
486void QQuick3DRepeater::initObject(
int index, QObject *object)
488 QQuick3DNode *item = qmlobject_cast<QQuick3DNode*>(object);
490 if (!m_deletables.at(index)) {
493 m_model->release(object);
494 if (!m_delegateValidated) {
495 m_delegateValidated =
true;
496 QObject* delegate =
this->delegate();
497 qmlWarning(delegate ? delegate :
this) << QQuick3DRepeater::tr(
"Delegate must be of Node type");
502 m_deletables[index] = item;
503 item->setParent(
this);
504 item->setParentItem(
static_cast<QQuick3DNode*>(
this));
505 initDelegate(index, item);
509void QQuick3DRepeater::modelUpdated(
const QQmlChangeSet &changeSet,
bool reset)
511 if (!isComponentComplete())
516 if (changeSet.difference() != 0)
522 QHash<
int, QVector<QPointer<QQuick3DNode> > > moved;
523 for (
const QQmlChangeSet::Change &remove : changeSet.removes()) {
524 int index = qMin(remove.index, m_deletables.size());
525 int count = qMin(remove.index + remove.count, m_deletables.size()) - index;
526 if (remove.isMove()) {
527 moved.insert(remove.moveId, m_deletables.mid(index, count));
529 m_deletables.begin() + index,
530 m_deletables.begin() + index + count);
531 }
else while (count--) {
532 QQuick3DNode *item = m_deletables.at(index);
533 m_deletables.remove(index);
534 emit objectRemoved(index, item);
536 m_model->release(item);
537 item->setParentItem(
nullptr);
542 difference -= remove.count;
545 for (
const QQmlChangeSet::Change &insert : changeSet.inserts()) {
546 int index = qMin(insert.index, m_deletables.size());
547 if (insert.isMove()) {
548 QVector<QPointer<QQuick3DNode> > items = moved.value(insert.moveId);
549 m_deletables = m_deletables.mid(0, index) + items + m_deletables.mid(index);
550 }
else for (
int i = 0; i < insert.count; ++i) {
551 int modelIndex = index + i;
553 m_deletables.insert(modelIndex,
nullptr);
554 QObject *object = m_model->object(modelIndex, QQmlIncubator::AsynchronousIfNested);
556 m_model->release(object);
558 difference += insert.count;
565void QQuick3DRepeater::requestItems()
567 for (
int i = 0; i < m_itemCount; i++) {
568 QObject *object = m_model->object(i, QQmlIncubator::AsynchronousIfNested);
570 m_model->release(object);
576#include "moc_qquick3drepeater_p.cpp"