diff options
| -rw-r--r-- | src/datatab.cpp | 22 | ||||
| -rw-r--r-- | src/datatab.h | 2 | ||||
| -rw-r--r-- | src/filetree.cpp | 124 | ||||
| -rw-r--r-- | src/filetree.h | 16 | ||||
| -rw-r--r-- | src/shared/directoryentry.h | 14 |
5 files changed, 134 insertions, 44 deletions
diff --git a/src/datatab.cpp b/src/datatab.cpp index bc0ff455..b351923c 100644 --- a/src/datatab.cpp +++ b/src/datatab.cpp @@ -18,7 +18,7 @@ QString UnmanagedModName(); DataTab::DataTab( OrganizerCore& core, PluginContainer& pc, QWidget* parent, Ui::MainWindow* mwui) : - m_core(core), m_pluginContainer(pc), m_archives(false), m_parent(parent), + m_core(core), m_pluginContainer(pc), m_parent(parent), m_model(new FileTreeModel(core)), ui{ mwui->btnRefreshData, mwui->dataTree, @@ -150,7 +150,6 @@ void DataTab::onRefresh() void DataTab::refreshDataTree() { m_model->refresh(); - ui.tree->expand(m_model->index(0, 0)); } void DataTab::refreshDataTreeKeepExpandedNodes() @@ -343,12 +342,27 @@ void DataTab::onContextMenu(const QPoint &pos) void DataTab::onConflicts() { - refreshDataTreeKeepExpandedNodes(); + updateOptions(); } void DataTab::onArchives() { - m_archives = (m_core.getArchiveParsing() && ui.archives->isChecked()); + updateOptions(); +} + +void DataTab::updateOptions() +{ + FileTreeModel::Flags flags = FileTreeModel::NoFlags; + + if (ui.conflicts->isChecked()) { + flags |= FileTreeModel::Conflicts; + } + + if (ui.archives->isChecked()) { + flags |= FileTreeModel::Archives; + } + + m_model->setFlags(flags); refreshDataTree(); } diff --git a/src/datatab.h b/src/datatab.h index 8754c12d..de38cc8f 100644 --- a/src/datatab.h +++ b/src/datatab.h @@ -44,7 +44,6 @@ private: OrganizerCore& m_core; PluginContainer& m_pluginContainer; - bool m_archives; QWidget* m_parent; FileTreeModel* m_model; DataTabUi ui; @@ -56,6 +55,7 @@ private: void onContextMenu(const QPoint &pos); void onConflicts(); void onArchives(); + void updateOptions(); void updateTo( QTreeWidgetItem *subTree, const std::wstring &directorySoFar, diff --git a/src/filetree.cpp b/src/filetree.cpp index f43d07a2..cf40e01c 100644 --- a/src/filetree.cpp +++ b/src/filetree.cpp @@ -16,17 +16,16 @@ FileTreeItem::FileTreeItem() FileTreeItem::FileTreeItem( FileTreeItem* parent, int originID, - std::wstring virtualParentPath, std::wstring realPath, Flags flags, + std::wstring dataRelativeParentPath, std::wstring realPath, Flags flags, std::wstring file, std::wstring mod) : m_parent(parent), m_originID(originID), - m_virtualParentPath(QString::fromStdWString(virtualParentPath)), + m_virtualParentPath(QString::fromStdWString(dataRelativeParentPath)), m_realPath(QString::fromStdWString(realPath)), m_flags(flags), m_file(QString::fromStdWString(file)), m_mod(QString::fromStdWString(mod)), m_loaded(false) { - Q_ASSERT(!m_mod.isEmpty()); } void FileTreeItem::add(std::unique_ptr<FileTreeItem> child) @@ -56,27 +55,20 @@ const QString& FileTreeItem::virtualParentPath() const QString FileTreeItem::virtualPath() const { - if (m_virtualParentPath.isEmpty()) { - return m_file; - } else { - return m_virtualParentPath + "\\" + m_file; - } -} + QString s = "Data\\"; -QString FileTreeItem::dataRelativeParentPath() const -{ - if (m_virtualParentPath == "data") { - return ""; + if (!m_virtualParentPath.isEmpty()) { + s += m_virtualParentPath + "\\"; } - static const QString prefix = "data\\"; + s += m_file; - auto path = m_virtualParentPath; - if (path.startsWith(prefix)) { - path = path.mid(prefix.size()); - } + return s; +} - return path; +QString FileTreeItem::dataRelativeParentPath() const +{ + return m_virtualParentPath; } QString FileTreeItem::dataRelativeFilePath() const @@ -396,13 +388,13 @@ bool FileTreeModel::showConflicts() const bool FileTreeModel::showArchives() const { - return (m_flags & Archives); + return (m_flags & Archives) && m_core.getArchiveParsing(); } void FileTreeModel::refresh() { beginResetModel(); - m_root = {nullptr, 0, L"", L"", FileTreeItem::Directory, L"Data", L""}; + m_root = {nullptr, 0, L"", L"", FileTreeItem::Directory, L"Data", L"<root>"}; fill(m_root, *m_core.directoryStructure(), L""); endResetModel(); } @@ -437,27 +429,87 @@ void FileTreeModel::fill( FileTreeItem& parentItem, const MOShared::DirectoryEntry& parentEntry, const std::wstring& parentPath) { - const std::wstring path = - parentPath + - (parentPath.empty() ? L"" : L"\\") + - parentEntry.getName(); + std::wstring path = parentPath; + + if (!parentEntry.isTopLevel()) { + if (!path.empty()) { + path += L"\\"; + } + + path += parentEntry.getName(); + } + + const auto flags = FillFlag::PruneDirectories; std::vector<DirectoryEntry*>::const_iterator begin, end; parentEntry.getSubDirectories(begin, end); - fillDirectories(parentItem, path, begin, end); + fillDirectories(parentItem, path, begin, end, flags); - fillFiles(parentItem, path, parentEntry.getFiles()); + fillFiles(parentItem, path, parentEntry.getFiles(), flags); parentItem.setLoaded(true); } +bool FileTreeModel::shouldShowFile(const FileEntry& file) const +{ + if (showConflicts() && (file.getAlternatives().size() == 0)) { + return false; + } + + bool isArchive = false; + int originID = file.getOrigin(isArchive); + if (!showArchives() && isArchive) { + return false; + } + + return true; +} + +bool FileTreeModel::hasFilesAnywhere(const DirectoryEntry& dir) const +{ + bool foundFile = false; + + dir.forEachFile([&](auto&& f) { + if (shouldShowFile(f)) { + foundFile = true; + + // stop + return false; + } + + // continue + return true; + }); + + if (foundFile) { + return true; + } + + std::vector<DirectoryEntry*>::const_iterator begin, end; + dir.getSubDirectories(begin, end); + + for (auto itor=begin; itor!=end; ++itor) { + if (hasFilesAnywhere(**itor)) { + return true; + } + } + + return false; +} + void FileTreeModel::fillDirectories( FileTreeItem& parentItem, const std::wstring& path, - DirectoryIterator begin, DirectoryIterator end) + DirectoryIterator begin, DirectoryIterator end, FillFlags flags) { for (auto itor=begin; itor!=end; ++itor) { const auto& dir = **itor; + if (flags & FillFlag::PruneDirectories) { + if (!hasFilesAnywhere(dir)) { + continue; + } + } + auto child = std::make_unique<FileTreeItem>( &parentItem, 0, path, L"", FileTreeItem::Directory, dir.getName(), L""); @@ -471,18 +523,15 @@ void FileTreeModel::fillDirectories( void FileTreeModel::fillFiles( FileTreeItem& parentItem, const std::wstring& path, - const std::vector<FileEntry::Ptr>& files) + const std::vector<FileEntry::Ptr>& files, FillFlags) { for (auto&& file : files) { - if (showConflicts() && (file->getAlternatives().size() == 0)) { + if (!shouldShowFile(*file)) { continue; } bool isArchive = false; int originID = file->getOrigin(isArchive); - if (!showArchives() && isArchive) { - continue; - } FileTreeItem::Flags flags = FileTreeItem::NoFlags; @@ -549,9 +598,12 @@ QModelIndex FileTreeModel::index( ensureLoaded(parent); if (static_cast<std::size_t>(row) >= parent->children().size()) { - log::error( - "FileTreeModel::index(): row {} is out of range for {}", - row, parent->debugName()); + // don't warn if the tree hasn't been refreshed yet + if (!m_root.children().empty()) { + log::error( + "FileTreeModel::index(): row {} is out of range for {}", + row, parent->debugName()); + } return {}; } diff --git a/src/filetree.h b/src/filetree.h index 13299bb3..4fbd5a2b 100644 --- a/src/filetree.h +++ b/src/filetree.h @@ -20,7 +20,7 @@ public: FileTreeItem(); FileTreeItem( FileTreeItem* parent, int originID, - std::wstring virtualParentPath, std::wstring realPath, Flags flags, + std::wstring dataRelativeParentPath, std::wstring realPath, Flags flags, std::wstring file, std::wstring mod); FileTreeItem(const FileTreeItem&) = delete; @@ -98,6 +98,14 @@ public: Qt::ItemFlags flags(const QModelIndex& index) const override; private: + enum class FillFlag + { + None = 0x00, + PruneDirectories = 0x01 + }; + + Q_DECLARE_FLAGS(FillFlags, FillFlag); + class IconFetcher; using DirectoryIterator = std::vector<MOShared::DirectoryEntry*>::const_iterator; @@ -117,11 +125,11 @@ private: void fillDirectories( FileTreeItem& parentItem, const std::wstring& path, - DirectoryIterator begin, DirectoryIterator end); + DirectoryIterator begin, DirectoryIterator end, FillFlags flags); void fillFiles( FileTreeItem& parentItem, const std::wstring& path, - const std::vector<MOShared::FileEntry::Ptr>& files); + const std::vector<MOShared::FileEntry::Ptr>& files, FillFlags flags); std::wstring makeModName(const MOShared::FileEntry& file, int originID) const; @@ -129,6 +137,8 @@ private: void ensureLoaded(FileTreeItem* item) const; void updatePendingIcons(); + bool shouldShowFile(const MOShared::FileEntry& file) const; + bool hasFilesAnywhere(const MOShared::DirectoryEntry& dir) const; QString makeTooltip(const FileTreeItem& item) const; QVariant makeIcon(const FileTreeItem& item, const QModelIndex& index) const; }; diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index 785c3ff6..0e6b20f0 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -217,8 +217,10 @@ public: void clear();
bool isPopulated() const { return m_Populated; }
+ bool isTopLevel() const { return m_TopLevel; }
bool isEmpty() const { return m_Files.empty() && m_SubDirectories.empty(); }
+ bool hasFiles() const { return !m_Files.empty(); }
const DirectoryEntry *getParent() const { return m_Parent; }
@@ -247,6 +249,18 @@ public: begin = m_SubDirectories.begin(); end = m_SubDirectories.end();
}
+ template <class F>
+ void forEachFile(F&& f) const
+ {
+ for (auto&& p : m_Files) {
+ if (auto file=m_FileRegister->getFile(p.second)) {
+ if (!f(*file)) {
+ break;
+ }
+ }
+ }
+ }
+
DirectoryEntry *findSubDirectory(const std::wstring &name) const;
DirectoryEntry *findSubDirectoryRecursive(const std::wstring &path);
|
