From 0a908c49625fe0e54bc45e29fe8c4908d20b0dbe Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Thu, 19 Dec 2019 21:13:31 -0500 Subject: added a map for directories in DirectoryEntry more optimizations for filetree --- src/filetreeitem.cpp | 103 ----------------------------------- src/filetreeitem.h | 124 +++++++++++++++++++++++++++++++++++------- src/filetreemodel.cpp | 25 ++++++--- src/shared/directoryentry.cpp | 56 +++++++++++++++---- src/shared/directoryentry.h | 19 ++++++- 5 files changed, 186 insertions(+), 141 deletions(-) (limited to 'src') diff --git a/src/filetreeitem.cpp b/src/filetreeitem.cpp index c2f3a1fc..0469dfcc 100644 --- a/src/filetreeitem.cpp +++ b/src/filetreeitem.cpp @@ -27,11 +27,6 @@ FileTreeItem::FileTreeItem( { } -void FileTreeItem::add(std::unique_ptr child) -{ - m_children.push_back(std::move(child)); -} - void FileTreeItem::insert(std::unique_ptr child, std::size_t at) { if (at > m_children.size()) { @@ -55,26 +50,6 @@ void FileTreeItem::remove(std::size_t i) m_children.erase(m_children.begin() + i); } -const std::vector>& FileTreeItem::children() const -{ - return m_children; -} - -FileTreeItem* FileTreeItem::parent() -{ - return m_parent; -} - -int FileTreeItem::originID() const -{ - return m_originID; -} - -const QString& FileTreeItem::virtualParentPath() const -{ - return m_virtualParentPath; -} - QString FileTreeItem::virtualPath() const { QString s = "Data\\"; @@ -88,11 +63,6 @@ QString FileTreeItem::virtualPath() const return s; } -QString FileTreeItem::dataRelativeParentPath() const -{ - return m_virtualParentPath; -} - QString FileTreeItem::dataRelativeFilePath() const { auto path = dataRelativeParentPath(); @@ -103,31 +73,6 @@ QString FileTreeItem::dataRelativeFilePath() const return path += m_file; } -const QString& FileTreeItem::realPath() const -{ - return m_realPath; -} - -const QString& FileTreeItem::filename() const -{ - return m_file; -} - -const std::wstring& FileTreeItem::filenameWs() const -{ - return m_wsFile; -} - -const std::wstring& FileTreeItem::filenameWsLowerCase() const -{ - return m_wsLcFile; -} - -const QString& FileTreeItem::mod() const -{ - return m_mod; -} - QFont FileTreeItem::font() const { QFont f; @@ -150,49 +95,11 @@ QFileIconProvider::IconType FileTreeItem::icon() const } } -bool FileTreeItem::isDirectory() const -{ - return (m_flags & Directory); -} - -bool FileTreeItem::isFromArchive() const -{ - return (m_flags & FromArchive); -} - -bool FileTreeItem::isConflicted() const -{ - return (m_flags & Conflicted); -} - bool FileTreeItem::isHidden() const { return m_file.endsWith(ModInfo::s_HiddenExt); } -bool FileTreeItem::hasChildren() const -{ - if (!isDirectory()) { - return false; - } - - if (isLoaded() && m_children.empty()) { - return false; - } - - return true; -} - -void FileTreeItem::setLoaded(bool b) -{ - m_loaded = b; -} - -bool FileTreeItem::isLoaded() const -{ - return m_loaded; -} - void FileTreeItem::unload() { if (!m_loaded) { @@ -203,16 +110,6 @@ void FileTreeItem::unload() m_children.clear(); } -void FileTreeItem::setExpanded(bool b) -{ - m_expanded = b; -} - -bool FileTreeItem::isStrictlyExpanded() const -{ - return m_expanded; -} - bool FileTreeItem::areChildrenVisible() const { if (m_expanded) { diff --git a/src/filetreeitem.h b/src/filetreeitem.h index 423038ba..1e820f3f 100644 --- a/src/filetreeitem.h +++ b/src/filetreeitem.h @@ -27,39 +27,125 @@ public: FileTreeItem(FileTreeItem&&) = default; FileTreeItem& operator=(FileTreeItem&&) = default; - void add(std::unique_ptr child); + void add(std::unique_ptr child) + { + m_children.push_back(std::move(child)); + } + void insert(std::unique_ptr child, std::size_t at); void remove(std::size_t i); - const std::vector>& children() const; - FileTreeItem* parent(); - int originID() const; - const QString& virtualParentPath() const; + const std::vector>& children() const + { + return m_children; + } + + + FileTreeItem* parent() + { + return m_parent; + } + + int originID() const + { + return m_originID; + } + + const QString& virtualParentPath() const + { + return m_virtualParentPath; + } + QString virtualPath() const; - const QString& filename() const; - const std::wstring& filenameWs() const; - const std::wstring& filenameWsLowerCase() const; - const QString& mod() const; + const QString& filename() const + { + return m_file; + } + + const std::wstring& filenameWs() const + { + return m_wsFile; + } + + const std::wstring& filenameWsLowerCase() const + { + return m_wsLcFile; + } + + const QString& mod() const + { + return m_mod; + } + QFont font() const; - const QString& realPath() const; - QString dataRelativeParentPath() const; + const QString& realPath() const + { + return m_realPath; + } + + const QString& dataRelativeParentPath() const + { + return m_virtualParentPath; + } + QString dataRelativeFilePath() const; QFileIconProvider::IconType icon() const; - bool isDirectory() const; - bool isFromArchive() const; - bool isConflicted() const; + bool isDirectory() const + { + return (m_flags & Directory); + } + + bool isFromArchive() const + { + return (m_flags & FromArchive); + } + + bool isConflicted() const + { + return (m_flags & Conflicted); + } + bool isHidden() const; - bool hasChildren() const; - void setLoaded(bool b); - bool isLoaded() const; + bool hasChildren() const + { + if (!isDirectory()) { + return false; + } + + if (isLoaded() && m_children.empty()) { + return false; + } + + return true; + } + + + void setLoaded(bool b) + { + m_loaded = b; + } + + bool isLoaded() const + { + return m_loaded; + } + void unload(); - void setExpanded(bool b); - bool isStrictlyExpanded() const; + void setExpanded(bool b) + { + m_expanded = b; + } + + bool isStrictlyExpanded() const + { + return m_expanded; + } + bool areChildrenVisible() const; QString debugName() const; diff --git a/src/filetreemodel.cpp b/src/filetreemodel.cpp index b5ae9dc8..9332b354 100644 --- a/src/filetreemodel.cpp +++ b/src/filetreemodel.cpp @@ -255,7 +255,7 @@ void FileTreeModel::updateDirectories( break; } - if (auto d=parentEntry.findSubDirectory(item->filenameWsLowerCase())) { + if (auto d=parentEntry.findSubDirectory(item->filenameWsLowerCase(), true)) { // directory still exists seen.insert(item->filenameWs()); @@ -418,7 +418,7 @@ void FileTreeModel::updateFiles( parentItem.debugName(), (path.empty() ? L"\\" : path)); }); - std::unordered_set seen; + std::unordered_set seen; std::vector remove; for (auto&& item : parentItem.children()) { @@ -430,7 +430,7 @@ void FileTreeModel::updateFiles( if (shouldShowFile(*f)) { // file still exists trace([&]{ log::debug("{} still exists", item->debugName()); }); - seen.insert(item->filenameWs()); + seen.emplace(f->getIndex()); continue; } } @@ -483,9 +483,14 @@ void FileTreeModel::updateFiles( std::size_t insertPos = firstFile; - for (auto&& file : parentEntry.getFiles()) { - if (shouldShowFile(*file)) { - if (!seen.contains(file->getName())) { + parentEntry.forEachFileIndex([&](auto&& fileIndex) { + if (!seen.contains(fileIndex)) { + const auto& file = parentEntry.getFileByIndex(fileIndex); + if (!file) { + return true; + } + + if (shouldShowFile(*file)) { trace([&]{ log::debug( "{}: new file {}", parentItem.debugName(), QString::fromStdWString(file->getName())); @@ -532,11 +537,15 @@ void FileTreeModel::updateFiles( beginInsertRows(parentIndex, first, last); parentItem.insert(std::move(child), insertPos); endInsertRows(); + } else { + ++insertPos; } - + } else { ++insertPos; } - } + + return true; + }); } std::wstring FileTreeModel::makeModName(const FileEntry& file, int originID) const diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index c6b29fbb..97da1061 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -485,7 +485,9 @@ void DirectoryEntry::clear() for (DirectoryEntry *entry : m_SubDirectories) { delete entry; } + m_SubDirectories.clear(); + m_SubDirectoriesMap.clear(); } @@ -665,7 +667,9 @@ void DirectoryEntry::removeDirRecursive() entry->removeDirRecursive(); delete entry; } + m_SubDirectories.clear(); + m_SubDirectoriesMap.clear(); } void DirectoryEntry::removeDir(const std::wstring &path) @@ -676,6 +680,20 @@ void DirectoryEntry::removeDir(const std::wstring &path) DirectoryEntry *entry = *iter; if (CaseInsensitiveEqual(entry->getName(), path)) { entry->removeDirRecursive(); + + bool found = false; + for (auto iter2=m_SubDirectoriesMap.begin(); iter2!=m_SubDirectoriesMap.end(); ++iter2) { + if (iter2->second == entry) { + m_SubDirectoriesMap.erase(iter2); + found = true; + break; + } + } + + if (!found) { + log::error("entry {} not in sub directories map", entry->getName()); + } + m_SubDirectories.erase(iter); delete entry; break; @@ -858,14 +876,22 @@ const FileEntry::Ptr DirectoryEntry::searchFile(const std::wstring &path, const } -DirectoryEntry *DirectoryEntry::findSubDirectory(const std::wstring &name) const +DirectoryEntry *DirectoryEntry::findSubDirectory( + const std::wstring &name, bool alreadyLowerCase) const { - for (DirectoryEntry *entry : m_SubDirectories) { - if (CaseInsensitiveEqual(entry->getName(), name)) { - return entry; - } + SubDirectoriesMap::const_iterator itor; + + if (alreadyLowerCase) { + itor = m_SubDirectoriesMap.find(name); + } else { + itor = m_SubDirectoriesMap.find(ToLower(name)); + } + + if (itor == m_SubDirectoriesMap.end()) { + return nullptr; } - return nullptr; + + return itor->second; } @@ -878,7 +904,13 @@ DirectoryEntry *DirectoryEntry::findSubDirectoryRecursive(const std::wstring &pa const FileEntry::Ptr DirectoryEntry::findFile( const std::wstring &name, bool alreadyLowerCase) const { - auto iter = m_Files.find(alreadyLowerCase ? name : ToLower(name)); + std::map::const_iterator iter; + + if (alreadyLowerCase) { + iter = m_Files.find(name); + } else { + iter = m_Files.find(ToLower(name)); + } if (iter != m_Files.end()) { return m_FileRegister->getFile(iter->second); @@ -900,9 +932,13 @@ DirectoryEntry *DirectoryEntry::getSubDirectory(const std::wstring &name, bool c } } if (create) { - std::vector::iterator iter = m_SubDirectories.insert(m_SubDirectories.end(), - new DirectoryEntry(name, this, originID, m_FileRegister, m_OriginConnection)); - return *iter; + auto* entry = new DirectoryEntry( + name, this, originID, m_FileRegister, m_OriginConnection); + + m_SubDirectories.push_back(entry); + m_SubDirectoriesMap.emplace(ToLower(name), entry); + + return entry; } else { return nullptr; } diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index d33b495a..79bc5cf2 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -271,7 +271,22 @@ public: } } - DirectoryEntry *findSubDirectory(const std::wstring &name) const; + template + void forEachFileIndex(F&& f) const + { + for (auto&& p : m_Files) { + if (!f(p.second)) { + break; + } + } + } + + FileEntry::Ptr getFileByIndex(FileEntry::Index index) const + { + return m_FileRegister->getFile(index); + } + + DirectoryEntry *findSubDirectory(const std::wstring &name, bool alreadyLowerCase=false) const; DirectoryEntry *findSubDirectoryRecursive(const std::wstring &path); /** retrieve a file in this directory by name. @@ -352,6 +367,7 @@ private: void removeDirRecursive(); private: + using SubDirectoriesMap = std::unordered_map; boost::shared_ptr m_FileRegister; boost::shared_ptr m_OriginConnection; @@ -359,6 +375,7 @@ private: std::wstring m_Name; std::map m_Files; std::vector m_SubDirectories; + SubDirectoriesMap m_SubDirectoriesMap; DirectoryEntry *m_Parent; std::set m_Origins; -- cgit v1.3.1