diff options
| author | Mikaël Capelle <capelle.mikael@gmail.com> | 2020-12-26 20:48:38 +0100 |
|---|---|---|
| committer | Mikaël Capelle <capelle.mikael@gmail.com> | 2021-01-02 15:38:14 +0100 |
| commit | be0d6aef00891286f33242073627611413ad79c4 (patch) | |
| tree | 037f2c69d8d11adba6be428704bb4612fd7f79fc /src | |
| parent | 71055e373de639d9654361084f39d81211d08819 (diff) | |
Start working on collapsible separators.
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 8 | ||||
| -rw-r--r-- | src/modlist.h | 2 | ||||
| -rw-r--r-- | src/modlistbypriorityproxy.cpp | 214 | ||||
| -rw-r--r-- | src/modlistbypriorityproxy.h | 56 | ||||
| -rw-r--r-- | src/modlistsortproxy.cpp | 4 | ||||
| -rw-r--r-- | src/profile.h | 2 |
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. |
