diff options
Diffstat (limited to 'src/qml/types/qqmldelegatemodel.cpp')
-rw-r--r-- | src/qml/types/qqmldelegatemodel.cpp | 192 |
1 files changed, 145 insertions, 47 deletions
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 7a12813f0c..62ccf0d66c 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -93,7 +93,7 @@ struct DelegateModelGroupFunction : QV4::FunctionObject static Heap::DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg)) { - return scope->engine()->memoryManager->allocObject<DelegateModelGroupFunction>(scope, flag, code); + return scope->engine()->memoryManager->allocate<DelegateModelGroupFunction>(scope, flag, code); } static ReturnedValue call(const QV4::FunctionObject *that, const Value *thisObject, const Value *argv, int argc) @@ -200,8 +200,7 @@ QQmlDelegateModelParts::QQmlDelegateModelParts(QQmlDelegateModel *parent) */ QQmlDelegateModelPrivate::QQmlDelegateModelPrivate(QQmlContext *ctxt) - : m_delegate(nullptr) - , m_cacheMetaType(nullptr) + : m_cacheMetaType(nullptr) , m_context(ctxt) , m_parts(nullptr) , m_filterGroup(QStringLiteral("items")) @@ -214,6 +213,7 @@ QQmlDelegateModelPrivate::QQmlDelegateModelPrivate(QQmlContext *ctxt) , m_transaction(false) , m_incubatorCleanupScheduled(false) , m_waitingToFetchMore(false) + , m_useFirstColumnOnly(true) , m_cacheItems(nullptr) , m_items(nullptr) , m_persistedItems(nullptr) @@ -228,6 +228,11 @@ QQmlDelegateModelPrivate::~QQmlDelegateModelPrivate() m_cacheMetaType->release(); } +int QQmlDelegateModelPrivate::adaptorModelCount() const +{ + return m_useFirstColumnOnly ? m_adaptorModel.rowCount() : m_adaptorModel.count(); +} + void QQmlDelegateModelPrivate::requestMoreIfNecessary() { Q_Q(QQmlDelegateModel); @@ -263,6 +268,7 @@ QQmlDelegateModel::QQmlDelegateModel(QQmlContext *ctxt, QObject *parent) QQmlDelegateModel::~QQmlDelegateModel() { Q_D(QQmlDelegateModel); + d->m_adaptorModel.setObject(nullptr, this); for (QQmlDelegateModelItem *cacheItem : qAsConst(d->m_cache)) { if (cacheItem->object) { @@ -336,7 +342,7 @@ void QQmlDelegateModel::componentComplete() static_cast<QQmlPartsModel *>(d->m_pendingParts.first())->updateFilterGroup(); QVector<Compositor::Insert> inserts; - d->m_count = d->m_adaptorModel.count(); + d->m_count = d->adaptorModelCount(); d->m_compositor.append( &d->m_adaptorModel, 0, @@ -383,7 +389,7 @@ void QQmlDelegateModel::setModel(const QVariant &model) } if (d->m_complete) { - _q_itemsInserted(0, d->m_adaptorModel.count()); + _q_itemsInserted(0, d->adaptorModelCount()); d->requestMoreIfNecessary(); } } @@ -409,7 +415,7 @@ void QQmlDelegateModel::setDelegate(QQmlComponent *delegate) return; } bool wasValid = d->m_delegate != nullptr; - d->m_delegate = delegate; + d->m_delegate.setObject(delegate, this); d->m_delegateValidated = false; if (wasValid && d->m_complete) { for (int i = 1; i < d->m_groupCount; ++i) { @@ -475,7 +481,7 @@ void QQmlDelegateModel::setRootIndex(const QVariant &root) if (d->m_adaptorModel.canFetchMore()) d->m_adaptorModel.fetchMore(); if (d->m_complete) { - const int newCount = d->m_adaptorModel.count(); + const int newCount = d->adaptorModelCount(); if (oldCount) _q_itemsRemoved(0, oldCount); if (newCount) @@ -487,6 +493,35 @@ void QQmlDelegateModel::setRootIndex(const QVariant &root) } /*! + \qmlproperty int QtQml.Models::DelegateModel::rows + + Contains the number of rows in the model. If the model + is a list of items, it will be equal to the number of items + in the list. + + \since QtQml.Models 2.12 +*/ +int QQmlDelegateModel::rows() const +{ + Q_D(const QQmlDelegateModel); + return d->m_adaptorModel.rowCount(); +} + +/*! + \qmlproperty int QtQml.Models::DelegateModel::columns + + Contains the number of columns in the model. If the model + is a list of items, it will be equal to \c 1. + + \since QtQml.Models 2.12 +*/ +int QQmlDelegateModel::columns() const +{ + Q_D(const QQmlDelegateModel); + return d->m_adaptorModel.columnCount(); +} + +/*! \qmlmethod QModelIndex QtQml.Models::DelegateModel::modelIndex(int index) QAbstractItemModel provides a hierarchical tree of data, whereas @@ -536,25 +571,24 @@ int QQmlDelegateModel::count() const QQmlDelegateModel::ReleaseFlags QQmlDelegateModelPrivate::release(QObject *object) { - QQmlDelegateModel::ReleaseFlags stat = nullptr; if (!object) - return stat; - - if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(object)) { - if (cacheItem->releaseObject()) { - cacheItem->destroyObject(); - emitDestroyingItem(object); - if (cacheItem->incubationTask) { - releaseIncubator(cacheItem->incubationTask); - cacheItem->incubationTask = nullptr; - } - cacheItem->Dispose(); - stat |= QQmlInstanceModel::Destroyed; - } else { - stat |= QQmlDelegateModel::Referenced; - } + return QQmlDelegateModel::ReleaseFlags(0); + + QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(object); + if (!cacheItem) + return QQmlDelegateModel::ReleaseFlags(0); + + if (!cacheItem->releaseObject()) + return QQmlDelegateModel::Referenced; + + cacheItem->destroyObject(); + emitDestroyingItem(object); + if (cacheItem->incubationTask) { + releaseIncubator(cacheItem->incubationTask); + cacheItem->incubationTask = nullptr; } - return stat; + cacheItem->Dispose(); + return QQmlInstanceModel::Destroyed; } /* @@ -862,6 +896,13 @@ void QQmlDelegateModelPrivate::releaseIncubator(QQDMIncubationTask *incubationTa } } +void QQmlDelegateModelPrivate::addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it) +{ + m_cache.insert(it.cacheIndex, item); + m_compositor.setFlags(it, 1, Compositor::CacheFlag); + Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache)); +} + void QQmlDelegateModelPrivate::removeCacheItem(QQmlDelegateModelItem *cacheItem) { int cidx = m_cache.lastIndexOf(cacheItem); @@ -951,10 +992,7 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ return nullptr; cacheItem->groups = it->flags; - - m_cache.insert(it.cacheIndex, cacheItem); - m_compositor.setFlags(it, 1, Compositor::CacheFlag); - Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache)); + addCacheItem(cacheItem, it); } // Bump the reference counts temporarily so neither the content data or the delegate object @@ -1046,7 +1084,10 @@ QQmlIncubator::Status QQmlDelegateModel::incubationStatus(int index) if (!it->inCache()) return QQmlIncubator::Null; - return d->m_cache.at(it.cacheIndex)->incubationTask->status(); + if (auto incubationTask = d->m_cache.at(it.cacheIndex)->incubationTask) + return incubationTask->status(); + + return QQmlIncubator::Ready; } QString QQmlDelegateModelPrivate::stringValue(Compositor::Group group, int index, const QString &name) @@ -1510,7 +1551,7 @@ void QQmlDelegateModel::_q_modelReset() d->m_adaptorModel.rootIndex = QModelIndex(); if (d->m_complete) { - d->m_count = d->m_adaptorModel.count(); + d->m_count = d->adaptorModelCount(); const QList<QQmlDelegateModelItem *> cache = d->m_cache; for (int i = 0, c = cache.count(); i < c; ++i) { @@ -1588,8 +1629,15 @@ void QQmlDelegateModel::_q_rowsMoved( void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles) { Q_D(QQmlDelegateModel); - if (begin.parent() == d->m_adaptorModel.rootIndex) - _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, roles); + if (begin.parent() != d->m_adaptorModel.rootIndex) + return; + + int rowCount = end.row() - begin.row() + 1; + + for (int col = begin.column(); col <= end.column(); ++col) { + int startIndex = d->m_adaptorModel.indexAt(begin.row(), col); + _q_itemsChanged(startIndex, rowCount, roles); + } } bool QQmlDelegateModel::isDescendantOf(const QPersistentModelIndex& desc, const QList< QPersistentModelIndex >& parents) const @@ -1918,6 +1966,8 @@ QQmlDelegateModelItem::QQmlDelegateModelItem( , scriptRef(0) , groups(0) , index(modelIndex) + , row(QQmlDelegateModelPrivate::get(metaType->model)->m_adaptorModel.rowAt(modelIndex)) + , column(QQmlDelegateModelPrivate::get(metaType->model)->m_adaptorModel.columnAt(modelIndex)) { metaType->addref(); } @@ -1952,6 +2002,27 @@ void QQmlDelegateModelItem::Dispose() delete this; } +void QQmlDelegateModelItem::setModelIndex(int idx) +{ + if (idx == index) + return; + + const int prevRow = row; + const int prevColumn = column; + const QQmlAdaptorModel &adaptorModel = QQmlDelegateModelPrivate::get(metaType->model)->m_adaptorModel; + + index = idx; + row = adaptorModel.rowAt(idx); + column = adaptorModel.columnAt(idx); + + Q_EMIT modelIndexChanged(); + + if (row != prevRow) + emit rowChanged(); + if (column != prevColumn) + emit columnChanged(); +} + void QQmlDelegateModelItem::destroyObject() { Q_ASSERT(object); @@ -2080,22 +2151,29 @@ QQmlDelegateModelAttached::QQmlDelegateModelAttached( , m_previousGroups(cacheItem->groups) { QQml_setParent_noEvent(this, parent); + resetCurrentIndex(); + // Let m_previousIndex be equal to m_currentIndex + std::copy(std::begin(m_currentIndex), std::end(m_currentIndex), std::begin(m_previousIndex)); + + if (!cacheItem->metaType->metaObject) + cacheItem->metaType->initializeMetaObject(); + + QObjectPrivate::get(this)->metaObject = cacheItem->metaType->metaObject; + cacheItem->metaType->metaObject->addref(); +} + +void QQmlDelegateModelAttached::resetCurrentIndex() +{ if (QQDMIncubationTask *incubationTask = m_cacheItem->incubationTask) { for (int i = 1; i < qMin<int>(m_cacheItem->metaType->groupCount, Compositor::MaximumGroupCount); ++i) - m_currentIndex[i] = m_previousIndex[i] = incubationTask->index[i]; + m_currentIndex[i] = incubationTask->index[i]; } else { QQmlDelegateModelPrivate * const model = QQmlDelegateModelPrivate::get(m_cacheItem->metaType->model); Compositor::iterator it = model->m_compositor.find( Compositor::Cache, model->m_cache.indexOf(m_cacheItem)); for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) - m_currentIndex[i] = m_previousIndex[i] = it.index[i]; + m_currentIndex[i] = it.index[i]; } - - if (!cacheItem->metaType->metaObject) - cacheItem->metaType->initializeMetaObject(); - - QObjectPrivate::get(this)->metaObject = cacheItem->metaType->metaObject; - cacheItem->metaType->metaObject->addref(); } /*! @@ -2483,7 +2561,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index) model->m_cacheMetaType->initializePrototype(); QV4::ExecutionEngine *v4 = model->m_cacheMetaType->v4Engine; QV4::Scope scope(v4); - QV4::ScopedObject o(scope, v4->memoryManager->allocObject<QQmlDelegateModelItemObject>(cacheItem)); + QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(cacheItem)); QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value()); o->setPrototype(p); ++cacheItem->scriptRef; @@ -3194,7 +3272,10 @@ QQmlIncubator::Status QQmlPartsModel::incubationStatus(int index) if (!it->inCache()) return QQmlIncubator::Null; - return model->m_cache.at(it.cacheIndex)->incubationTask->status(); + if (auto incubationTask = model->m_cache.at(it.cacheIndex)->incubationTask) + return incubationTask->status(); + + return QQmlIncubator::Ready; } int QQmlPartsModel::indexOf(QObject *item, QObject *) const @@ -3214,7 +3295,10 @@ void QQmlPartsModel::createdPackage(int index, QQuickPackage *package) void QQmlPartsModel::initPackage(int index, QQuickPackage *package) { - emit initItem(index, package->part(m_part)); + if (m_modelUpdatePending) + m_pendingPackageInitializations << index; + else + emit initItem(index, package->part(m_part)); } void QQmlPartsModel::destroyingPackage(QQuickPackage *package) @@ -3226,9 +3310,22 @@ void QQmlPartsModel::destroyingPackage(QQuickPackage *package) void QQmlPartsModel::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) { + m_modelUpdatePending = false; emit modelUpdated(changeSet, reset); if (changeSet.difference() != 0) emit countChanged(); + + QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model); + QVector<int> pendingPackageInitializations; + qSwap(pendingPackageInitializations, m_pendingPackageInitializations); + for (int index : pendingPackageInitializations) { + if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup)) + continue; + QObject *object = model->object(m_compositorGroup, index, QQmlIncubator::Asynchronous); + if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) + emit initItem(index, package->part(m_part)); + model->release(object); + } } //============================================================================ @@ -3238,7 +3335,7 @@ struct QQmlDelegateModelGroupChange : QV4::Object V4_OBJECT2(QQmlDelegateModelGroupChange, QV4::Object) static QV4::Heap::QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) { - return e->memoryManager->allocObject<QQmlDelegateModelGroupChange>(); + return e->memoryManager->allocate<QQmlDelegateModelGroupChange>(); } static QV4::ReturnedValue method_get_index(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) { @@ -3275,7 +3372,7 @@ struct QQmlDelegateModelGroupChangeArray : public QV4::Object public: static QV4::Heap::QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes) { - return engine->memoryManager->allocObject<QQmlDelegateModelGroupChangeArray>(changes); + return engine->memoryManager->allocate<QQmlDelegateModelGroupChangeArray>(changes); } quint32 count() const { return d()->changes->count(); } @@ -3306,12 +3403,13 @@ public: return object.asReturnedValue(); } - static QV4::ReturnedValue get(const QV4::Managed *m, QV4::String *name, bool *hasProperty) + static QV4::ReturnedValue get(const QV4::Managed *m, QV4::StringOrSymbol *name, bool *hasProperty) { Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>()); const QQmlDelegateModelGroupChangeArray *array = static_cast<const QQmlDelegateModelGroupChangeArray *>(m); - if (name->equals(array->engine()->id_length())) { + name->makeIdentifier(); + if (name->identifier() == array->engine()->id_length()->identifier()) { if (hasProperty) *hasProperty = true; return QV4::Encode(array->count()); |