6#include <private/qqmlglobal_p.h>
7#include <private/qqmllistaccessor_p.h>
8#include <private/qqmlchangeset_p.h>
10#include <QtQml/QQmlInfo>
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
38
39
40
41
42
43
44
45
48
49
50
51
52
53
54
55
56
57
58
60QQuick3DRepeater::QQuick3DRepeater(QQuick3DNode *parent)
61 : QQuick3DNode(parent)
65 , m_delegateValidated(
false)
66 , m_explicitDelegate(
false)
67 , m_explicitDelegateModelAccess(
false)
71QQuick3DRepeater::~QQuick3DRepeater()
76 QQmlDelegateModelPointer model(m_model);
77 disconnectModel(&model);
81void QQuick3DRepeater::connectModel(QQmlDelegateModelPointer *model)
83 QQmlInstanceModel *instanceModel = model->instanceModel();
87 connect(instanceModel, &QQmlInstanceModel::modelUpdated,
88 this, &QQuick3DRepeater::modelUpdated);
89 connect(instanceModel, &QQmlInstanceModel::createdItem,
90 this, &QQuick3DRepeater::createdObject);
91 connect(instanceModel, &QQmlInstanceModel::initItem,
92 this, &QQuick3DRepeater::initObject);
93 if (QQmlDelegateModel *dataModel = model->delegateModel()) {
95 dataModel, &QQmlDelegateModel::delegateChanged,
96 this, &QQuick3DRepeater::applyDelegateChange);
99 dataModel, &QQmlDelegateModel::modelChanged,
100 this, &QQuick3DRepeater::modelChanged);
107void QQuick3DRepeater::disconnectModel(QQmlDelegateModelPointer *model)
109 QQmlInstanceModel *instanceModel = model->instanceModel();
113 disconnect(instanceModel, &QQmlInstanceModel::modelUpdated,
114 this, &QQuick3DRepeater::modelUpdated);
115 disconnect(instanceModel, &QQmlInstanceModel::createdItem,
116 this, &QQuick3DRepeater::createdObject);
117 disconnect(instanceModel, &QQmlInstanceModel::initItem,
118 this, &QQuick3DRepeater::initObject);
119 if (QQmlDelegateModel *delegateModel = model->delegateModel()) {
121 delegateModel, &QQmlDelegateModel::delegateChanged,
122 this, &QQuick3DRepeater::applyDelegateChange);
125 delegateModel, &QQmlDelegateModel::modelChanged,
126 this, &QQuick3DRepeater::modelChanged);
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
150QVariant QQuick3DRepeater::model()
const
153 return static_cast<QQmlDelegateModel *>(m_model.data())->model();
155 return QVariant::fromValue(m_model.data());
159void QQuick3DRepeater::applyDelegateChange()
161 if (m_explicitDelegate) {
162 qmlWarning(
this) <<
"Explicitly set delegate is externally overridden";
163 m_explicitDelegate =
false;
166 emit delegateChanged();
169QQmlDelegateModel *QQuick3DRepeater::createDelegateModel()
171 Q_ASSERT(m_model.isNull());
172 QQmlDelegateModel *delegateModel =
new QQmlDelegateModel(qmlContext(
this),
this);
173 m_model = delegateModel;
175 if (isComponentComplete())
176 delegateModel->componentComplete();
177 return delegateModel;
180void QQuick3DRepeater::setModel(
const QVariant &m)
183 if (model.userType() == qMetaTypeId<QJSValue>())
184 model = model.value<QJSValue>().toVariant();
186 QQmlDelegateModelPointer oldModel(m_model);
188 if (oldModel.delegateModel()->model() == model)
190 }
else if (QVariant::fromValue(m_model) == model) {
196 disconnectModel(&oldModel);
200 QObject *object = qvariant_cast<QObject *>(model);
202 QQmlDelegateModelPointer newModel(qobject_cast<QQmlInstanceModel *>(object));
204 if (m_explicitDelegate) {
205 QQmlComponent *delegate =
nullptr;
206 if (QQmlDelegateModel *old = oldModel.delegateModel())
207 delegate = old->delegate();
208 if (QQmlDelegateModel *delegateModel = newModel.delegateModel()) {
209 delegateModel->setDelegate(delegate);
210 }
else if (delegate) {
211 qmlWarning(
this) <<
"Cannot retain explicitly set delegate on non-DelegateModel";
212 m_explicitDelegate =
false;
216 delete oldModel.instanceModel();
219 m_model = newModel.instanceModel();
220 }
else if (m_ownModel) {
222 Q_ASSERT(oldModel.delegateModel());
224 m_model = newModel.instanceModel();
225 newModel.delegateModel()->setModel(model);
227 newModel = createDelegateModel();
228 if (m_explicitDelegate) {
229 QQmlComponent *delegate =
nullptr;
230 if (QQmlDelegateModel *old = oldModel.delegateModel())
231 delegate = old->delegate();
232 newModel.delegateModel()->setDelegate(delegate);
235 newModel.delegateModel()->setModel(model);
238 connectModel(&newModel);
245
246
247
248
249
250
251
252
253
254
255
256
257
258
260QQmlComponent *QQuick3DRepeater::delegate()
const
263 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(m_model))
264 return dataModel->delegate();
270void QQuick3DRepeater::setDelegate(QQmlComponent *delegate)
272 const auto setExplicitDelegate = [&](QQmlDelegateModel *delegateModel) {
273 if (delegateModel->delegate() == delegate) {
274 m_explicitDelegate =
true;
278 const int oldCount = delegateModel->count();
279 delegateModel->setDelegate(delegate);
281 if (oldCount != delegateModel->count())
283 m_explicitDelegate =
true;
284 m_delegateValidated =
false;
290 m_explicitDelegate =
true;
294 setExplicitDelegate(createDelegateModel());
298 emit delegateChanged();
302 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(m_model)) {
304 m_explicitDelegate =
false;
305 setExplicitDelegate(delegateModel);
310 qmlWarning(
this) <<
"Cannot set a delegate on an explicitly provided non-DelegateModel";
312 m_explicitDelegate =
true;
316
317
318
319
320
321
322
323
324
326int QQuick3DRepeater::count()
const
329 return m_model->count();
334
335
336
337
338
340QQuick3DObject *QQuick3DRepeater::objectAt(
int index)
const
342 if (index >= 0 && index < m_deletables.size())
343 return m_deletables[index];
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369QQmlDelegateModel::DelegateModelAccess QQuick3DRepeater::delegateModelAccess()
const
371 if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(m_model))
372 return dataModel->delegateModelAccess();
373 return QQmlDelegateModel::Qt5ReadWrite;
376void QQuick3DRepeater::setDelegateModelAccess(QQmlDelegateModel::DelegateModelAccess delegateModelAccess)
378 const auto setExplicitDelegateModelAccess = [&](QQmlDelegateModel *delegateModel) {
379 delegateModel->setDelegateModelAccess(delegateModelAccess);
380 m_explicitDelegateModelAccess =
true;
384 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
386 m_explicitDelegateModelAccess =
true;
390 QQmlDelegateModel *delegateModel =
new QQmlDelegateModel(qmlContext(
this),
this);
391 m_model = delegateModel;
393 if (isComponentComplete())
394 delegateModel->componentComplete();
396 setExplicitDelegateModelAccess(delegateModel);
401 emit delegateModelAccessChanged();
405 if (QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(m_model)) {
408 m_explicitDelegateModelAccess =
false;
409 setExplicitDelegateModelAccess(delegateModel);
413 if (delegateModelAccess == QQmlDelegateModel::Qt5ReadWrite) {
414 m_explicitDelegateModelAccess =
true;
416 qmlWarning(
this) <<
"Cannot set a delegateModelAccess on an explicitly provided "
421void QQuick3DRepeater::clear()
423 bool complete = isComponentComplete();
428 for (
int i = m_deletables.size() - 1; i >= 0; --i) {
429 if (QQuick3DObject *item = m_deletables.at(i)) {
431 emit objectRemoved(i, item);
432 m_model->release(item);
435 for (QQuick3DObject *item : std::as_const(m_deletables)) {
437 item->setParentItem(
nullptr);
440 m_deletables.clear();
444void QQuick3DRepeater::regenerate()
446 if (!isComponentComplete())
451 if (!m_model || !m_model->count() || !m_model->isValid() || !parentItem() || !isComponentComplete())
454 m_itemCount = count();
455 m_deletables.resize(m_itemCount);
459void QQuick3DRepeater::componentComplete()
461 if (m_model && m_ownModel)
462 static_cast<QQmlDelegateModel *>(m_model.data())->componentComplete();
463 QQuick3DNode::componentComplete();
465 if (m_model && m_model->count())
469void QQuick3DRepeater::itemChange(QQuick3DObject::ItemChange change,
const QQuick3DObject::ItemChangeData &value)
471 QQuick3DObject::itemChange(change, value);
472 if (change == ItemParentHasChanged) {
477void QQuick3DRepeater::createdObject(
int index, QObject *)
479 QObject *object = m_model->object(index, QQmlIncubator::AsynchronousIfNested);
480 QQuick3DObject *item = qmlobject_cast<QQuick3DObject*>(object);
481 emit objectAdded(index, item);
484void QQuick3DRepeater::initObject(
int index, QObject *object)
486 QQuick3DNode *item = qmlobject_cast<QQuick3DNode*>(object);
488 if (!m_deletables.at(index)) {
491 m_model->release(object);
492 if (!m_delegateValidated) {
493 m_delegateValidated =
true;
494 QObject* delegate =
this->delegate();
495 qmlWarning(delegate ? delegate :
this) << QQuick3DRepeater::tr(
"Delegate must be of Node type");
500 m_deletables[index] = item;
501 item->setParent(
this);
502 item->setParentItem(
static_cast<QQuick3DNode*>(
this));
503 initDelegate(index, item);
507void QQuick3DRepeater::modelUpdated(
const QQmlChangeSet &changeSet,
bool reset)
509 if (!isComponentComplete())
514 if (changeSet.difference() != 0)
520 QHash<
int, QVector<QPointer<QQuick3DNode> > > moved;
521 for (
const QQmlChangeSet::Change &remove : changeSet.removes()) {
522 int index = qMin(remove.index, m_deletables.size());
523 int count = qMin(remove.index + remove.count, m_deletables.size()) - index;
524 if (remove.isMove()) {
525 moved.insert(remove.moveId, m_deletables.mid(index, count));
527 m_deletables.begin() + index,
528 m_deletables.begin() + index + count);
529 }
else while (count--) {
530 QQuick3DNode *item = m_deletables.at(index);
531 m_deletables.remove(index);
532 emit objectRemoved(index, item);
534 m_model->release(item);
535 item->setParentItem(
nullptr);
540 difference -= remove.count;
543 for (
const QQmlChangeSet::Change &insert : changeSet.inserts()) {
544 int index = qMin(insert.index, m_deletables.size());
545 if (insert.isMove()) {
546 QVector<QPointer<QQuick3DNode> > items = moved.value(insert.moveId);
547 m_deletables = m_deletables.mid(0, index) + items + m_deletables.mid(index);
548 }
else for (
int i = 0; i < insert.count; ++i) {
549 int modelIndex = index + i;
551 m_deletables.insert(modelIndex,
nullptr);
552 QObject *object = m_model->object(modelIndex, QQmlIncubator::AsynchronousIfNested);
554 m_model->release(object);
556 difference += insert.count;
563void QQuick3DRepeater::requestItems()
565 for (
int i = 0; i < m_itemCount; i++) {
566 QObject *object = m_model->object(i, QQmlIncubator::AsynchronousIfNested);
568 m_model->release(object);
574#include "moc_qquick3drepeater_p.cpp"