diff --git a/src/declarativeimports/core/datamodel.cpp b/src/declarativeimports/core/datamodel.cpp --- a/src/declarativeimports/core/datamodel.cpp +++ b/src/declarativeimports/core/datamodel.cpp @@ -52,13 +52,13 @@ } m_roleIds.clear(); - const QHash rNames = roleNames(); - m_roleIds.reserve(rNames.count()); - for (auto i = rNames.constBegin(); i != rNames.constEnd(); ++i) { + const QHash roles = sourceModel()->roleNames(); + m_roleIds.reserve(roles.count()); + for (auto i = roles.constBegin(); i != roles.constEnd(); ++i) { m_roleIds[QString::fromUtf8(i.value())] = i.key(); } - setRoleNames(sourceModel()->roleNames()); + setRoleNames(roles); setFilterRole(m_filterRole); setSortRole(m_sortRole); } @@ -74,17 +74,20 @@ return; } + beginResetModel(); + if (sourceModel()) { disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(syncRoleNames())); } QSortFilterProxyModel::setSourceModel(model); if (model) { connect(model, SIGNAL(modelReset()), this, SLOT(syncRoleNames())); - syncRoleNames(); } + endResetModel(); + emit sourceModelChanged(model); } @@ -362,8 +365,6 @@ void DataModel::setItems(const QString &sourceName, const QVariantList &list) { const int oldLength = m_items.value(sourceName).count(); - const int delta = list.length() - oldLength; - const bool firstRun = m_items.isEmpty(); //At what row number the first item associated to this source starts int sourceIndex = 0; @@ -374,60 +375,38 @@ } sourceIndex += i.value().count(); } - //signal as inserted the rows at the end, all the other rows will signal a dataupdated. - //better than a model reset because doesn't cause deletion and re-creation of every list item on a qml ListView, repeaters etc. - //the first run it gets reset because otherwise setRoleNames gets broken - if (firstRun) { - beginResetModel(); - } else if (delta > 0) { - beginInsertRows(QModelIndex(), sourceIndex + oldLength, sourceIndex + list.length() - 1); - } else if (delta < 0) { - beginRemoveRows(QModelIndex(), sourceIndex + list.length(), sourceIndex + oldLength - 1); + + if (oldLength > 0) { + beginRemoveRows(QModelIndex(), sourceIndex, sourceIndex + oldLength - 1); + m_items[sourceName].clear(); + endRemoveRows(); } - //convert to vector, so data() will be O(1) - m_items[sourceName] = list.toVector(); + + m_roleNames.clear(); if (!list.isEmpty()) { - if (list.first().canConvert()) { - foreach (const QVariant &item, list) { - const QVariantMap &vh = item.value(); - QMapIterator it(vh); - while (it.hasNext()) { - it.next(); - const QString &roleName = it.key(); - if (!m_roleIds.contains(roleName)) { - ++m_maxRoleId; - m_roleNames[m_maxRoleId] = roleName.toLatin1(); - m_roleIds[roleName] = m_maxRoleId; - } - } - } - } else { - foreach (const QVariant &item, list) { - const QVariantMap &vh = item.value(); - QMapIterator it(vh); - while (it.hasNext()) { - it.next(); - const QString &roleName = it.key(); - if (!m_roleIds.contains(roleName)) { - ++m_maxRoleId; - m_roleNames[m_maxRoleId] = roleName.toLatin1(); - m_roleIds[roleName] = m_maxRoleId; - } + beginInsertRows(QModelIndex(), sourceIndex, sourceIndex + list.length() - 1); + //convert to vector, so data() will be O(1) + m_items[sourceName] = list.toVector(); + endInsertRows(); + + foreach (const QVariant &item, list) { + const QVariantMap &vh = item.value(); + QMapIterator it(vh); + while (it.hasNext()) { + it.next(); + const QString &roleName = it.key(); + auto itRole = m_roleIds.find(roleName); + if (itRole == m_roleIds.end()) { + itRole = m_roleIds.insert(roleName, ++m_maxRoleId); } + m_roleNames[itRole.value()] = roleName.toLatin1(); } } } setRoleNames(m_roleNames); - if (firstRun) { - endResetModel(); - } else if (delta > 0) { - endInsertRows(); - } else if (delta < 0) { - endRemoveRows(); - } emit dataChanged(createIndex(sourceIndex, 0), createIndex(sourceIndex + qMin(list.length(), oldLength), 0)); } @@ -462,9 +441,7 @@ int count = m_items.value(sourceName).count(); if (count > 0) { beginRemoveRows(QModelIndex(), sourceIndex, sourceIndex + count - 1); - } - m_items.remove(sourceName); - if (count > 0) { + m_items.remove(sourceName); endRemoveRows(); } }