From a19bfaa489507827dea1449991f1f5398a28beb1 Mon Sep 17 00:00:00 2001 From: Mikaƫl Capelle Date: Mon, 18 Jan 2021 19:44:29 +0100 Subject: Better handling of layoutChanged in by-priority proxy to avoid resetting. --- src/modlistbypriorityproxy.cpp | 98 ++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 32 deletions(-) (limited to 'src/modlistbypriorityproxy.cpp') diff --git a/src/modlistbypriorityproxy.cpp b/src/modlistbypriorityproxy.cpp index 9b5b2f03..a0623e8c 100644 --- a/src/modlistbypriorityproxy.cpp +++ b/src/modlistbypriorityproxy.cpp @@ -25,17 +25,13 @@ void ModListByPriorityProxy::setSourceModel(QAbstractItemModel* model) QAbstractProxyModel::setSourceModel(model); if (sourceModel()) { - connect(sourceModel(), &QAbstractItemModel::layoutChanged, this, &ModListByPriorityProxy::buildTree, Qt::UniqueConnection); - connect(sourceModel(), &QAbstractItemModel::rowsRemoved, this, &ModListByPriorityProxy::buildTree, Qt::UniqueConnection); - connect(sourceModel(), &QAbstractItemModel::modelReset, this, &ModListByPriorityProxy::buildTree, Qt::UniqueConnection); - connect(sourceModel(), &QAbstractItemModel::dataChanged, this, &ModListByPriorityProxy::modelDataChanged, Qt::UniqueConnection); - refresh(); - } -} + connect(sourceModel(), &QAbstractItemModel::layoutChanged, this, &ModListByPriorityProxy::onModelLayoutChanged, Qt::UniqueConnection); + connect(sourceModel(), &QAbstractItemModel::rowsRemoved, this, &ModListByPriorityProxy::onModelRowsRemoved, Qt::UniqueConnection); + connect(sourceModel(), &QAbstractItemModel::modelReset, this, &ModListByPriorityProxy::onModelReset, Qt::UniqueConnection); + connect(sourceModel(), &QAbstractItemModel::dataChanged, this, &ModListByPriorityProxy::onModelDataChanged, Qt::UniqueConnection); -void ModListByPriorityProxy::refresh() -{ - buildTree(); + onModelReset(); + } } void ModListByPriorityProxy::setProfile(Profile* profile) @@ -48,46 +44,54 @@ void ModListByPriorityProxy::setSortOrder(Qt::SortOrder order) m_sortOrder = order; } +void ModListByPriorityProxy::buildMapping() +{ + m_IndexToItem.clear(); + for (unsigned int index = 0; index < ModInfo::getNumMods(); ++index) { + m_IndexToItem[index] = std::make_unique(ModInfo::getByIndex(index), index); + } +} + void ModListByPriorityProxy::buildTree() { if (!sourceModel()) return; - beginResetModel(); - // reset the root m_Root = { }; - m_IndexToItem.clear(); + + // clear all children + for (auto& [index, item] : m_IndexToItem) { + item->children.clear(); + } TreeItem* root = &m_Root; - std::unique_ptr overwrite; - std::vector> backups; + TreeItem* overwrite; + std::vector backups; auto fn = [&](const auto& p) { auto& [priority, index] = p; ModInfo::Ptr modInfo = ModInfo::getByIndex(index); - - TreeItem* item; + TreeItem* item = m_IndexToItem[index].get(); if (modInfo->isSeparator()) { - m_Root.children.push_back(std::make_unique(modInfo, index, &m_Root)); - item = m_Root.children.back().get(); + item->parent = &m_Root; + m_Root.children.push_back(item); root = item; } else if (modInfo->isOverwrite()) { // do not push here, because the overwrite is usually not at the right position - overwrite = std::make_unique(modInfo, index, &m_Root); - item = overwrite.get(); + item->parent = &m_Root; + overwrite = item; } else if (modInfo->isBackup()) { - backups.push_back(std::make_unique(modInfo, index, &m_Root)); - item = backups.back().get(); + // do not push here, because backups are usually not at the right position + item->parent = &m_Root; + backups.push_back(item); } else { - root->children.push_back(std::make_unique(modInfo, index, root)); - item = root->children.back().get(); + item->parent = root; + root->children.push_back(item); } - - m_IndexToItem[index] = item; }; auto& ibp = m_profile->getAllIndexesByPriority(); @@ -103,11 +107,41 @@ void ModListByPriorityProxy::buildTree() m_Root.children.insert(m_Root.children.end(), std::make_move_iterator(backups.begin()), std::make_move_iterator(backups.end())); } +} + +void ModListByPriorityProxy::onModelRowsRemoved(const QModelIndex& parent, int first, int last) +{ + onModelReset(); +} + +void ModListByPriorityProxy::onModelLayoutChanged(const QList&, LayoutChangeHint hint) +{ + MOBase::log::debug("LAYOUT"); + + emit layoutAboutToBeChanged(); + auto persistent = persistentIndexList(); + buildTree(); + + QModelIndexList toPersistent; + for (auto& idx : persistent) { + // we can still access the TreeItem* because we did not destroy them + auto* item = static_cast(idx.internalPointer()); + toPersistent.append(createIndex(item->parent->childIndex(item), idx.column(), item)); + } + changePersistentIndexList(persistent, toPersistent); + + emit layoutChanged({}, hint); +} +void ModListByPriorityProxy::onModelReset() +{ + beginResetModel(); + buildMapping(); + buildTree(); endResetModel(); } -void ModListByPriorityProxy::modelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles) +void ModListByPriorityProxy::onModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles) { QModelIndex proxyTopLeft = mapFromSource(topLeft); if (!proxyTopLeft.isValid()) { @@ -129,7 +163,7 @@ QModelIndex ModListByPriorityProxy::mapFromSource(const QModelIndex& sourceIndex return QModelIndex(); } - auto* item = m_IndexToItem.at(sourceIndex.row()); + auto* item = m_IndexToItem.at(sourceIndex.row()).get(); return createIndex(item->parent->childIndex(item), sourceIndex.column(), item); } @@ -175,7 +209,7 @@ QModelIndex ModListByPriorityProxy::parent(const QModelIndex& child) const return QModelIndex(); } - return createIndex(item->parent->parent->childIndex(item->parent), child.column(), item->parent); + return createIndex(item->parent->parent->childIndex(item->parent), 0, item->parent); } bool ModListByPriorityProxy::hasChildren(const QModelIndex& parent) const @@ -343,7 +377,7 @@ bool ModListByPriorityProxy::dropMimeData(const QMimeData* data, Qt::DropAction // in descending priority, we take the separator itself if it's empty or // its last children else { - auto* item = m_Root.children[parent.row()].get(); + auto* item = m_Root.children[parent.row()]; sourceRow = item->children.empty() ? item->index : item->children.back()->index; } } @@ -366,7 +400,7 @@ QModelIndex ModListByPriorityProxy::index(int row, int column, const QModelIndex parentItem = static_cast(parent.internalPointer()); } - return createIndex(row, column, parentItem->children[row].get()); + return createIndex(row, column, parentItem->children[row]); } void ModListByPriorityProxy::onDropEnter(const QMimeData*, bool dropExpanded, ModListView::DropPosition dropPosition) -- cgit v1.3.1