summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMikaël Capelle <capelle.mikael@gmail.com>2020-12-26 20:48:38 +0100
committerMikaël Capelle <capelle.mikael@gmail.com>2021-01-02 15:38:14 +0100
commitbe0d6aef00891286f33242073627611413ad79c4 (patch)
tree037f2c69d8d11adba6be428704bb4612fd7f79fc /src
parent71055e373de639d9654361084f39d81211d08819 (diff)
Start working on collapsible separators.
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/mainwindow.cpp8
-rw-r--r--src/modlist.h2
-rw-r--r--src/modlistbypriorityproxy.cpp214
-rw-r--r--src/modlistbypriorityproxy.h56
-rw-r--r--src/modlistsortproxy.cpp4
-rw-r--r--src/profile.h2
7 files changed, 282 insertions, 5 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 98bbe05f..0a913649 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -135,6 +135,7 @@ add_filter(NAME src/modinfo/dialog GROUPS
add_filter(NAME src/modlist GROUPS
modlist
modlistsortproxy
+ modlistbypriorityproxy
modlistview
)
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index cfce9bef..ddde1d9b 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -87,6 +87,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "listdialog.h"
#include "envshortcut.h"
#include "browserdialog.h"
+#include "modlistbypriorityproxy.h"
#include "directoryrefresher.h"
#include "shared/directoryentry.h"
@@ -543,6 +544,8 @@ MainWindow::MainWindow(Settings &settings
processUpdates();
ui->statusBar->updateNormalMessage(m_OrganizerCore);
+
+ on_groupCombo_currentIndexChanged(0);
}
void MainWindow::setupModList()
@@ -5935,7 +5938,7 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index)
Qt::UserRole + 2);
} break;
default: {
- newModel = nullptr;
+ newModel = nullptr;
} break;
}
@@ -5948,7 +5951,8 @@ void MainWindow::on_groupCombo_currentIndexChanged(int index)
connect(ui->modList, SIGNAL(collapsed(QModelIndex)), newModel, SLOT(collapsed(QModelIndex)));
connect(newModel, SIGNAL(expandItem(QModelIndex)), this, SLOT(expandModList(QModelIndex)));
} else {
- m_ModListSortProxy->setSourceModel(m_OrganizerCore.modList());
+ m_ModListSortProxy->setSourceModel(new ModListByPriorityProxy(m_OrganizerCore.modList(), this));
+ // m_ModListSortProxy->setSourceModel(m_OrganizerCore.modList());
}
modFilterActive(m_ModListSortProxy->isFilterActive());
}
diff --git a/src/modlist.h b/src/modlist.h
index 21a19fab..fad53755 100644
--- a/src/modlist.h
+++ b/src/modlist.h
@@ -369,6 +369,8 @@ private:
private:
+ friend class ModListByPriorityProxy;
+
OrganizerCore *m_Organizer;
Profile *m_Profile;
diff --git a/src/modlistbypriorityproxy.cpp b/src/modlistbypriorityproxy.cpp
new file mode 100644
index 00000000..69c6ff88
--- /dev/null
+++ b/src/modlistbypriorityproxy.cpp
@@ -0,0 +1,214 @@
+#include "modlistbypriorityproxy.h"
+
+#include "modinfo.h"
+#include "modlist.h"
+
+ModListByPriorityProxy::ModListByPriorityProxy(ModList* modList, QObject* parent) :
+ QAbstractProxyModel(parent), m_ModList(modList)
+{
+ setSourceModel(modList);
+}
+
+ModListByPriorityProxy::~ModListByPriorityProxy()
+{
+}
+
+void ModListByPriorityProxy::setSourceModel(QAbstractItemModel* model)
+{
+ QAbstractProxyModel::setSourceModel(model);
+ // connect(sourceModel(), &QAbstractItemModel::layoutChanged, this, &ModListByPriorityProxy::buildTree);
+}
+
+void ModListByPriorityProxy::buildTree()
+{
+ if (!sourceModel()) return;
+
+ beginResetModel();
+
+ endResetModel();
+
+}
+
+std::vector<ModListByPriorityProxy::ModInfoWithPriority> ModListByPriorityProxy::topLevelItems() const
+{
+ std::vector<ModListByPriorityProxy::ModInfoWithPriority> items;
+ bool separator = false;
+ for (auto& [priority, index] : m_ModList->m_Profile->getAllIndexesByPriority()) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
+ if (modInfo->isSeparator()) {
+ items.emplace_back(modInfo, priority);
+ separator = true;
+ }
+ else if (modInfo->isOverwrite() || !separator) {
+ items.emplace_back(modInfo, priority);
+ }
+ }
+
+ return items;
+}
+
+std::vector<ModListByPriorityProxy::ModInfoWithPriority> ModListByPriorityProxy::childItems(int priority) const
+{
+ std::vector<ModListByPriorityProxy::ModInfoWithPriority> children;
+ for (auto& [p, index] : m_ModList->m_Profile->getAllIndexesByPriority()) {
+ if (p > priority) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
+ if (modInfo->isSeparator()) {
+ break;
+ }
+ children.emplace_back(modInfo, p);
+ }
+ }
+ return children;
+}
+
+std::optional<ModListByPriorityProxy::ModInfoWithPriority> ModListByPriorityProxy::separator(int priority) const
+{
+ // overwrites
+ if (priority == ULONG_MAX) {
+ return {};
+ }
+
+ auto& indexByPriority = m_ModList->m_Profile->getAllIndexesByPriority();
+
+ auto it = indexByPriority.find(priority);
+ if (it == std::end(indexByPriority)) {
+ return {};
+ }
+
+ {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(it->second);
+ if (modInfo->isSeparator() || modInfo->isOverwrite()) {
+ return {};
+ }
+ }
+
+ auto rit = std::reverse_iterator{ it };
+ for (; rit != std::rend(indexByPriority); ++rit) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(rit->second);
+ if (modInfo->isSeparator()) {
+ return ModInfoWithPriority{ modInfo, rit->first };
+ }
+ }
+
+ return {};
+}
+
+QModelIndex ModListByPriorityProxy::mapFromSource(const QModelIndex& sourceIndex) const
+{
+ if (!sourceIndex.isValid()) {
+ return QModelIndex();
+ }
+
+ auto topItems = topLevelItems();
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(sourceIndex.row());
+
+ for (std::size_t i = 0; i < topItems.size(); ++i) {
+ if (topItems[i].mod == modInfo) {
+ return createIndex(i, sourceIndex.column(), modInfo.get());
+ }
+ }
+
+ auto sep = separator(m_ModList->priority(modInfo->name()));
+ auto children = childItems(sep->priority);
+ for (std::size_t i = 0; i < children.size(); ++i) {
+ if (children[i].mod == modInfo) {
+ return createIndex(i, sourceIndex.column(), modInfo.get());
+ }
+ }
+
+ return QModelIndex();
+}
+
+QModelIndex ModListByPriorityProxy::mapToSource(const QModelIndex& proxyIndex) const
+{
+ if (!proxyIndex.isValid()) {
+ return QModelIndex();
+ }
+ auto topItems = topLevelItems();
+ ModInfo::Ptr modInfo;
+ if (proxyIndex.parent().isValid()) {
+ ModInfo::Ptr parentInfo = topItems[proxyIndex.parent().row()].mod;
+ modInfo = childItems(m_ModList->priority(parentInfo->name()))[proxyIndex.row()].mod;
+ }
+ else {
+ modInfo = topItems[proxyIndex.row()].mod;
+ }
+ return sourceModel()->index(ModInfo::getIndex(modInfo->name()), proxyIndex.column(), mapToSource(proxyIndex.parent()));
+}
+
+int ModListByPriorityProxy::rowCount(const QModelIndex& parent) const
+{
+ auto topItems = topLevelItems();
+ if (!parent.isValid()) {
+ return topItems.size();
+ }
+
+ ModInfo::Ptr modInfo = topItems[parent.row()].mod;
+ if (!modInfo->isSeparator()) {
+ return 0;
+ }
+
+ auto priority = m_ModList->priority(modInfo->name());
+ return childItems(priority).size();
+}
+
+int ModListByPriorityProxy::columnCount(const QModelIndex& index) const
+{
+ return sourceModel()->columnCount(mapToSource(index));
+}
+
+
+QModelIndex ModListByPriorityProxy::parent(const QModelIndex& child) const
+{
+
+ auto topItems = topLevelItems();
+ ModInfo::Ptr modInfo;
+ if (child.parent().isValid()) {
+ ModInfo::Ptr parentInfo = topItems[child.parent().row()].mod;
+ modInfo = childItems(m_ModList->priority(parentInfo->name()))[child.row()].mod;
+ }
+ else {
+ modInfo = topItems[child.row()].mod;
+ }
+
+ auto sep = separator(m_ModList->priority(modInfo->name()));
+
+ if (!sep) {
+ return QModelIndex();
+ }
+
+ for (std::size_t i = 0; i < topItems.size(); ++i) {
+ if (topItems[i].mod == sep->mod) {
+ return createIndex(i, child.column(), sep->mod.get());
+ }
+ }
+
+ return QModelIndex();
+}
+
+bool ModListByPriorityProxy::hasChildren(const QModelIndex& parent) const
+{
+ if (!parent.isValid()) {
+ return false;
+ }
+ ModInfo* modInfo = static_cast<ModInfo*>(parent.internalPointer());
+ for (auto& item : topLevelItems()) {
+ if (modInfo == item.mod) {
+ return modInfo->isSeparator() && !childItems(item.priority).empty();
+ }
+ }
+ return false;
+}
+
+QModelIndex ModListByPriorityProxy::index(int row, int column, const QModelIndex& parent) const
+{
+ auto topItems = topLevelItems();
+ if (!parent.isValid()) {
+ return createIndex(row, column, topItems[row].mod.get());
+ }
+ else {
+ auto children = childItems(topItems[parent.row()].priority);
+ return createIndex(row, column, children[row].mod.get());
+ }
+}
diff --git a/src/modlistbypriorityproxy.h b/src/modlistbypriorityproxy.h
new file mode 100644
index 00000000..6ec04b9b
--- /dev/null
+++ b/src/modlistbypriorityproxy.h
@@ -0,0 +1,56 @@
+#ifndef MODLISBYPRIORITYPROXY_H
+#define MODLISBYPRIORITYPROXY_H
+
+#include <optional>
+#include <vector>
+
+#include <QAbstractProxyModel>
+#include <QModelIndex>
+#include <QMultiHash>
+#include <QStringList>
+#include <QIcon>
+#include <QSet>
+
+#include "modinfo.h"
+
+class ModList;
+
+class ModListByPriorityProxy : public QAbstractProxyModel
+{
+ Q_OBJECT
+
+public:
+ explicit ModListByPriorityProxy(ModList* modList, QObject* parent = nullptr);
+ ~ModListByPriorityProxy();
+
+ void setSourceModel(QAbstractItemModel* sourceModel) override;
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+ QModelIndex parent(const QModelIndex& child) const override;
+ QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex& index) const override;
+ bool hasChildren(const QModelIndex& parent) const override;
+
+ QModelIndex mapFromSource(const QModelIndex& sourceIndex) const override;
+ QModelIndex mapToSource(const QModelIndex& proxyIndex) const override;
+
+private:
+
+ void buildTree();
+
+ struct ModInfoWithPriority {
+ const ModInfo::Ptr mod;
+ const int priority;
+ };
+
+ std::vector<ModInfoWithPriority> topLevelItems() const;
+ std::vector<ModInfoWithPriority> childItems(int priority) const;
+ std::optional<ModInfoWithPriority> separator(int priority) const;
+
+private:
+
+ ModList* m_ModList;
+
+};
+
+#endif //GROUPINGPROXY_H
diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp
index ca0f3bb1..f54f3b7a 100644
--- a/src/modlistsortproxy.cpp
+++ b/src/modlistsortproxy.cpp
@@ -383,7 +383,7 @@ bool ModListSortProxy::categoryMatchesMod(
b = (hasConflictFlag(info->getConflictFlags()));
break;
}
-
+
case CategoryFactory::HasHiddenFiles:
{
b = (info->hasFlag(ModInfo::FLAG_HIDDEN_FILES));
@@ -645,7 +645,7 @@ bool ModListSortProxy::dropMimeData(const QMimeData *data, Qt::DropAction action
void ModListSortProxy::setSourceModel(QAbstractItemModel *sourceModel)
{
QSortFilterProxyModel::setSourceModel(sourceModel);
- QtGroupingProxy *proxy = qobject_cast<QtGroupingProxy*>(sourceModel);
+ QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel*>(sourceModel);
if (proxy != nullptr) {
sourceModel = proxy->sourceModel();
}
diff --git a/src/profile.h b/src/profile.h
index b8628276..04452ff6 100644
--- a/src/profile.h
+++ b/src/profile.h
@@ -250,7 +250,7 @@ public:
*
* @return map of indexes by priority
**/
- std::map<int, unsigned int> getAllIndexesByPriority() { return m_ModIndexByPriority; }
+ const std::map<int, unsigned int>& getAllIndexesByPriority() { return m_ModIndexByPriority; }
/**
* retrieve the number of mods for which this object has status information.