From e53905329a7a204ad0ad41600a9fb3040b942991 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Mon, 11 Jan 2021 18:55:15 +0100 Subject: Allow collapsible separator in descending priority. --- src/modlistsortproxy.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/modlistsortproxy.cpp') diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 9ae37a43..0682b9c3 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -617,6 +617,13 @@ bool ModListSortProxy::canDropMimeData(const QMimeData* data, Qt::DropAction act } } + // in the regular model, when dropping between rows, the row-value passed to + // the sourceModel is inconsistent between ascending and descending ordering. + // This should fix that + if (sortOrder() == Qt::DescendingOrder) { + --row; + } + return QSortFilterProxyModel::canDropMimeData(data, action, row, column, parent); } -- cgit v1.3.1 From 08520822eb91c065a0893da0e2e9d11574450208 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Mon, 11 Jan 2021 19:15:39 +0100 Subject: Fix drop in separator and create mod in separator in descending priority. --- src/modlistbypriorityproxy.cpp | 3 --- src/modlistsortproxy.cpp | 4 ++-- src/modlistview.cpp | 5 +++++ src/modlistview.h | 3 ++- src/modlistviewactions.cpp | 31 +++++++++++++++++++++---------- 5 files changed, 30 insertions(+), 16 deletions(-) (limited to 'src/modlistsortproxy.cpp') diff --git a/src/modlistbypriorityproxy.cpp b/src/modlistbypriorityproxy.cpp index e6728942..eca7108c 100644 --- a/src/modlistbypriorityproxy.cpp +++ b/src/modlistbypriorityproxy.cpp @@ -104,9 +104,6 @@ void ModListByPriorityProxy::buildTree() std::make_move_iterator(backups.begin()), std::make_move_iterator(backups.end())); } - // we do not really care about their position in the root - // as long as those are not in a separator - endResetModel(); } diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 0682b9c3..bc28490f 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -620,7 +620,7 @@ bool ModListSortProxy::canDropMimeData(const QMimeData* data, Qt::DropAction act // in the regular model, when dropping between rows, the row-value passed to // the sourceModel is inconsistent between ascending and descending ordering. // This should fix that - if (sortOrder() == Qt::DescendingOrder) { + if (sortOrder() == Qt::DescendingOrder && row != -1) { --row; } @@ -645,7 +645,7 @@ bool ModListSortProxy::dropMimeData(const QMimeData *data, Qt::DropAction action // in the regular model, when dropping between rows, the row-value passed to // the sourceModel is inconsistent between ascending and descending ordering. // This should fix that - if (sortOrder() == Qt::DescendingOrder) { + if (sortOrder() == Qt::DescendingOrder && row != -1) { --row; } diff --git a/src/modlistview.cpp b/src/modlistview.cpp index 1926a3f4..88c588f6 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -209,6 +209,11 @@ int ModListView::sortColumn() const return m_sortProxy ? m_sortProxy->sortColumn() : -1; } +Qt::SortOrder ModListView::sortOrder() const +{ + return m_sortProxy ? m_sortProxy->sortOrder() : Qt::AscendingOrder; +} + ModListView::GroupByMode ModListView::groupByMode() const { if (m_sortProxy == nullptr) { diff --git a/src/modlistview.h b/src/modlistview.h index 53c71458..13f868c6 100644 --- a/src/modlistview.h +++ b/src/modlistview.h @@ -61,9 +61,10 @@ public: // bool hasCollapsibleSeparators() const; - // the column by which the mod list is currently sorted + // the column/order by which the mod list is currently sorted // int sortColumn() const; + Qt::SortOrder sortOrder() const; // the current group mode // diff --git a/src/modlistviewactions.cpp b/src/modlistviewactions.cpp index cc50f009..09142026 100644 --- a/src/modlistviewactions.cpp +++ b/src/modlistviewactions.cpp @@ -103,22 +103,33 @@ void ModListViewActions::createEmptyMod(const QModelIndex& index) const auto info = ModInfo::getByIndex(mIndex); newPriority = m_core.currentProfile()->getModPriority(mIndex); if (info->isSeparator()) { + + auto isSeparator = [](const auto& p) { + return ModInfo::getByIndex(p.second)->isSeparator(); + }; + auto& ibp = m_core.currentProfile()->getAllIndexesByPriority(); - // start right after the current priority and look for the next + // start right after/before the current priority and look for the next // separator - auto it = ibp.find(newPriority + 1); - for (; it != ibp.end(); ++it) { - auto info = ModInfo::getByIndex(it->second); - if (info->isSeparator()) { + if (m_view->sortOrder() == Qt::AscendingOrder) { + auto it = std::find_if(ibp.find(newPriority + 1), ibp.end(), isSeparator); + if (it != ibp.end()) { newPriority = it->first; - break; + } + else { + newPriority = -1; } } - - // no separator found, create at the end - if (it == ibp.end()) { - newPriority = -1; + else { + auto it = std::find_if(std::reverse_iterator{ ibp.find(newPriority - 1) }, ibp.rend(), isSeparator); + if (it != ibp.rend()) { + newPriority = it->first + 1; + } + else { + // create "before" priority 0, i.e. at the end in descending priority. + newPriority = 0; + } } } } -- cgit v1.3.1 From 16b825bc5d9a03a3d0ef6453e07cf298e23965a2 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Mon, 11 Jan 2021 20:57:32 +0100 Subject: Fix drop in first item of separators. --- src/modlistbypriorityproxy.cpp | 55 +++++++++++++++++++++++++++--------------- src/modlistsortproxy.cpp | 11 ++++++--- src/modlistsortproxy.h | 4 +++ 3 files changed, 48 insertions(+), 22 deletions(-) (limited to 'src/modlistsortproxy.cpp') diff --git a/src/modlistbypriorityproxy.cpp b/src/modlistbypriorityproxy.cpp index eca7108c..4fd589a4 100644 --- a/src/modlistbypriorityproxy.cpp +++ b/src/modlistbypriorityproxy.cpp @@ -257,25 +257,29 @@ bool ModListByPriorityProxy::dropMimeData(const QMimeData* data, Qt::DropAction else { if (row >= 0) { - MOBase::log::debug("row={}, name={}, expand={}, drop={}", row, m_Root.children[row]->mod->name(), m_dropExpanded, m_dropPosition); if (!parent.isValid()) { if (row < m_Root.children.size()) { - sourceRow = m_Root.children[row]->index; - if (row > 0 - && m_sortOrder == Qt::AscendingOrder - && m_Root.children[row - 1]->mod->isSeparator() - && !m_Root.children[row - 1]->children.empty() - && m_dropExpanded - && m_dropPosition == ModListView::DropPosition::BelowItem) { + if (m_sortOrder == Qt::AscendingOrder) { + sourceRow = m_Root.children[row]->index; + if (row > 0 + && m_sortOrder == Qt::AscendingOrder + && m_Root.children[row - 1]->mod->isSeparator() + && !m_Root.children[row - 1]->children.empty() + && m_dropExpanded + && m_dropPosition == ModListView::DropPosition::BelowItem) { sourceRow = m_Root.children[row - 1]->children[0]->index; + } } - else if (row > 0 - && m_sortOrder == Qt::DescendingOrder - && m_Root.children[row]->mod->isSeparator() - && !m_Root.children[row]->children.empty() - && (!m_dropExpanded - || m_dropPosition == ModListView::DropPosition::AboveItem)) { - sourceRow = m_Root.children[row]->children.back()->index; + else { + sourceRow = m_Root.children[row - 1]->index; + if (row > 0 + && m_sortOrder == Qt::DescendingOrder + && m_Root.children[row - 1]->mod->isSeparator() + && !m_Root.children[row - 1]->children.empty() + && (!m_dropExpanded + || m_dropPosition == ModListView::DropPosition::AboveItem)) { + sourceRow = m_Root.children[row - 1]->children.back()->index; + } } } else { @@ -285,12 +289,25 @@ bool ModListByPriorityProxy::dropMimeData(const QMimeData* data, Qt::DropAction else { auto* item = static_cast(parent.internalPointer()); - if (row < item->children.size()) { - sourceRow = item->children[row]->index; + if (m_sortOrder == Qt::DescendingOrder + && row == 0 && m_dropPosition == ModListView::DropPosition::AboveItem) { + sourceRow = item->index; } - else if (parent.row() + 1 < m_Root.children.size()) { - sourceRow = m_Root.children[parent.row() + 1]->index; + else { + + if (m_sortOrder == Qt::DescendingOrder) { + row--; + } + + if (row < item->children.size()) { + sourceRow = item->children[row]->index; + } + else if (parent.row() + 1 < m_Root.children.size()) { + sourceRow = m_Root.children[parent.row() + 1]->index; + } } + + } } else if (parent.isValid()) { diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index bc28490f..1077a833 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -18,6 +18,7 @@ along with Mod Organizer. If not, see . */ #include "modlistsortproxy.h" +#include "modlistbypriorityproxy.h" #include "modlistdropinfo.h" #include "modinfo.h" #include "profile.h" @@ -279,7 +280,6 @@ bool ModListSortProxy::filterMatchesModOr(ModInfo::Ptr info, bool enabled) const bool ModListSortProxy::optionsMatchMod(ModInfo::Ptr info, bool) const { - return true; } @@ -598,6 +598,11 @@ bool ModListSortProxy::filterAcceptsRow(int source_row, const QModelIndex &paren } } +bool ModListSortProxy::sourceIsByPriorityProxy() const +{ + return dynamic_cast(sourceModel()) != nullptr; +} + bool ModListSortProxy::canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const { ModListDropInfo dropInfo(data, *m_Organizer); @@ -620,7 +625,7 @@ bool ModListSortProxy::canDropMimeData(const QMimeData* data, Qt::DropAction act // in the regular model, when dropping between rows, the row-value passed to // the sourceModel is inconsistent between ascending and descending ordering. // This should fix that - if (sortOrder() == Qt::DescendingOrder && row != -1) { + if (sortOrder() == Qt::DescendingOrder && row != -1 && !sourceIsByPriorityProxy()) { --row; } @@ -645,7 +650,7 @@ bool ModListSortProxy::dropMimeData(const QMimeData *data, Qt::DropAction action // in the regular model, when dropping between rows, the row-value passed to // the sourceModel is inconsistent between ascending and descending ordering. // This should fix that - if (sortOrder() == Qt::DescendingOrder && row != -1) { + if (sortOrder() == Qt::DescendingOrder && row != -1 && !sourceIsByPriorityProxy()) { --row; } diff --git a/src/modlistsortproxy.h b/src/modlistsortproxy.h index 421c82cc..23be77ed 100644 --- a/src/modlistsortproxy.h +++ b/src/modlistsortproxy.h @@ -140,6 +140,10 @@ private: bool filterMatchesModAnd(ModInfo::Ptr info, bool enabled) const; bool filterMatchesModOr(ModInfo::Ptr info, bool enabled) const; + // check if the source model is the by-priority proxy + // + bool sourceIsByPriorityProxy() const; + private slots: void aboutToChangeData(); -- cgit v1.3.1 From 18f70a2dff138f273a9b6babaec226775a03649f Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Mon, 11 Jan 2021 21:07:25 +0100 Subject: Add documentation for row computation. --- src/modlistbypriorityproxy.cpp | 35 ++++++++++++++++++++++++++++++++--- src/modlistsortproxy.cpp | 11 ++++++----- 2 files changed, 38 insertions(+), 8 deletions(-) (limited to 'src/modlistsortproxy.cpp') diff --git a/src/modlistbypriorityproxy.cpp b/src/modlistbypriorityproxy.cpp index b5d17c46..9b5b2f03 100644 --- a/src/modlistbypriorityproxy.cpp +++ b/src/modlistbypriorityproxy.cpp @@ -243,8 +243,9 @@ bool ModListByPriorityProxy::canDropMimeData(const QMimeData* data, Qt::DropActi bool ModListByPriorityProxy::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) { - // we need to fix the source model row - ModListDropInfo dropInfo(data, m_core); + // we need to fix the source model row if we are dropping at a + // given priority (not a local file) + const ModListDropInfo dropInfo(data, m_core); int sourceRow = -1; if (dropInfo.isLocalFileDrop()) { @@ -257,8 +258,14 @@ bool ModListByPriorityProxy::dropMimeData(const QMimeData* data, Qt::DropAction if (row >= 0) { if (!parent.isValid()) { if (row < m_Root.children.size()) { + if (m_sortOrder == Qt::AscendingOrder) { sourceRow = m_Root.children[row]->index; + + // fix bug when dropping a mod just below an expanded separator + // + // by default, Qt consider it's a drop at the end of that separator + // but we want to make it a drop at the beginning if (row > 0 && m_sortOrder == Qt::AscendingOrder && m_Root.children[row - 1]->mod->isSeparator() @@ -270,6 +277,9 @@ bool ModListByPriorityProxy::dropMimeData(const QMimeData* data, Qt::DropAction } else { sourceRow = m_Root.children[row - 1]->index; + + // fix drop below a collapsed separator or at the end of an expanded + // separator, above the next item if (row > 0 && m_sortOrder == Qt::DescendingOrder && m_Root.children[row - 1]->mod->isSeparator() @@ -284,15 +294,21 @@ bool ModListByPriorityProxy::dropMimeData(const QMimeData* data, Qt::DropAction sourceRow = ModInfo::getNumMods(); } } + + // the parent is valid, we are dropping in a separator else { auto* item = static_cast(parent.internalPointer()); + // we usually need to decrement the row in descending priority, but if + // it's the first row, we need to go back to the separator itself if (m_sortOrder == Qt::DescendingOrder && row == 0 && m_dropPosition == ModListView::DropPosition::AboveItem) { sourceRow = item->index; } else { + // in descending priority, we decrement the row to fix the drop position + // because this is not done by the sort proxy for us if (m_sortOrder == Qt::DescendingOrder) { row--; } @@ -308,11 +324,24 @@ bool ModListByPriorityProxy::dropMimeData(const QMimeData* data, Qt::DropAction } } + + // row < 0 and valid parent means we are dropping into an item, + // which can only be a separator since dropping into non-separators + // is disabled + // + // we want to drop at the end of the separator, so we need to find + // the right priority else if (parent.isValid()) { - // this is a drop in a separator + + // in ascending priority, we take the priority of the next top-level + // item, which can be a separator or the overwrite mod, but is guaranteed + // to exist if (m_sortOrder == Qt::AscendingOrder) { sourceRow = m_Root.children[parent.row() + 1]->index; } + + // 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(); sourceRow = item->children.empty() ? item->index : item->children.back()->index; diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 1077a833..18e91e6e 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -622,9 +622,7 @@ bool ModListSortProxy::canDropMimeData(const QMimeData* data, Qt::DropAction act } } - // in the regular model, when dropping between rows, the row-value passed to - // the sourceModel is inconsistent between ascending and descending ordering. - // This should fix that + // see dropMimeData for details if (sortOrder() == Qt::DescendingOrder && row != -1 && !sourceIsByPriorityProxy()) { --row; } @@ -648,8 +646,11 @@ bool ModListSortProxy::dropMimeData(const QMimeData *data, Qt::DropAction action } // in the regular model, when dropping between rows, the row-value passed to - // the sourceModel is inconsistent between ascending and descending ordering. - // This should fix that + // the sourceModel is inconsistent between ascending and descending ordering + // + // we want to fix that, but we cannot do it for the by-priority proxy because + // it messes up with non top-level items, so we simply forward the row and the + // by-priority proxy will fix the row for us if (sortOrder() == Qt::DescendingOrder && row != -1 && !sourceIsByPriorityProxy()) { --row; } -- cgit v1.3.1