From c0035ada020fe90085c698c0829f771c8d542031 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 16 May 2020 21:54:01 +0200 Subject: Add QDirFileTree implementation. --- src/CMakeLists.txt | 1 + src/qdirfiletree.cpp | 46 ++++++++++++++++++++++++++++++++++++++ src/qdirfiletree.h | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 src/qdirfiletree.cpp create mode 100644 src/qdirfiletree.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 99d31541..6625e4b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,6 +36,7 @@ add_filter(NAME src/core GROUPS organizerproxy apiuseraccount processrunner + qdirfiletree uilocker ) diff --git a/src/qdirfiletree.cpp b/src/qdirfiletree.cpp new file mode 100644 index 00000000..5570060a --- /dev/null +++ b/src/qdirfiletree.cpp @@ -0,0 +1,46 @@ +#include "qdirfiletree.h" + +#include + +using namespace MOBase; + +/** + * + */ +std::shared_ptr QDirFileTree::makeTree(QDir directory) { + return std::shared_ptr(new QDirFileTree(nullptr, directory)); +} + +/** + * + */ +QDirFileTree::QDirFileTree(std::shared_ptr parent, QDir directory) : FileTreeEntry(parent, directory.dirName()), IFileTree(), qDir(directory) { + qDir.setFilter(qDir.filter() | QDir::NoDotAndDotDot); +} + +/** + * No mutable operations allowed. + */ +bool QDirFileTree::beforeReplace(IFileTree const* dstTree, FileTreeEntry const* destination, FileTreeEntry const* source) { return false; } +bool QDirFileTree::beforeInsert(IFileTree const* entry, FileTreeEntry const* name) { return false; } +bool QDirFileTree::beforeRemove(IFileTree const* entry, FileTreeEntry const* name) { return false; } +std::shared_ptr QDirFileTree::makeFile(std::shared_ptr parent, QString name, QDateTime time) const { return nullptr; } +std::shared_ptr QDirFileTree::makeDirectory(std::shared_ptr parent, QString name) const { return nullptr; } + +void QDirFileTree::doPopulate(std::shared_ptr parent, std::vector>& entries) const { + QDirIterator iter(qDir); + while (iter.hasNext()) { + QString name = iter.next(); + QFileInfo info = iter.fileInfo(); + if (info.isDir()) { + entries.push_back(std::shared_ptr(new QDirFileTree(parent, QDir(info.absoluteFilePath())))); + } + else { + entries.push_back(createFileEntry(parent, info.fileName(), info.fileTime(QFileDevice::FileModificationTime))); + } + } +} + +std::shared_ptr QDirFileTree::doClone() const { + return std::shared_ptr(new QDirFileTree(nullptr, qDir)); +} diff --git a/src/qdirfiletree.h b/src/qdirfiletree.h new file mode 100644 index 00000000..000ef69a --- /dev/null +++ b/src/qdirfiletree.h @@ -0,0 +1,63 @@ +/* +Copyright (C) MO2 Team. All rights reserved. + +This file is part of Mod Organizer. + +Mod Organizer is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Mod Organizer is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Mod Organizer. If not, see . +*/ + +#ifndef ARCHIVEFILENETRY_H +#define ARCHIVEFILENTRY_H + +#include + +#include "ifiletree.h" + + +/** + * Class that expose a directory on the drive, using QDir, as a `MOBase::IFileTree`. + * + * This class does not expose mutable operations, so any mutable operations will + * fail. + */ +class QDirFileTree : public MOBase::IFileTree { +public: + + /** + * @brief Create a new file tree representing the given directory. + * + * @param directory Directory to represent. + * + * @return a file tree representing the given directory. + */ + static std::shared_ptr makeTree(QDir directory); + +protected: + + QDirFileTree(std::shared_ptr parent, QDir directory); + + virtual bool beforeReplace(IFileTree const* dstTree, FileTreeEntry const* destination, FileTreeEntry const* source) override; + virtual bool beforeInsert(IFileTree const* entry, FileTreeEntry const* name) override; + virtual bool beforeRemove(IFileTree const* entry, FileTreeEntry const* name) override; + + virtual std::shared_ptr makeFile(std::shared_ptr parent, QString name, QDateTime time) const override; + virtual std::shared_ptr makeDirectory(std::shared_ptr parent, QString name) const override; + virtual void doPopulate(std::shared_ptr parent, std::vector>& entries) const override; + virtual std::shared_ptr doClone() const override; + + QDir qDir; + +}; + +#endif -- cgit v1.3.1 From 5fc66d879391135878e06ee25a32526b9d5c59d9 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Fri, 22 May 2020 15:27:19 +0200 Subject: Move m_GamePlugin up into ModInfoWithConflictInfo. --- src/modinfo.cpp | 9 ++++++--- src/modinfo.h | 4 +++- src/modinfoforeign.cpp | 3 ++- src/modinfoforeign.h | 1 + src/modinfooverwrite.cpp | 4 ++-- src/modinfooverwrite.h | 2 +- src/modinforegular.cpp | 3 +-- src/modinforegular.h | 3 --- src/modinfoseparator.h | 8 ++++---- src/modinfowithconflictinfo.cpp | 7 +++++-- src/modinfowithconflictinfo.h | 10 ++++++++-- 11 files changed, 33 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 7f888bdc..379fa071 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -97,11 +97,12 @@ ModInfo::Ptr ModInfo::createFromPlugin(const QString &modName, const QString &espName, const QStringList &bsaNames, ModInfo::EModType modType, + const MOBase::IPluginGame* game, DirectoryEntry **directoryStructure, PluginContainer *pluginContainer) { QMutexLocker locker(&s_Mutex); ModInfo::Ptr result = ModInfo::Ptr( - new ModInfoForeign(modName, espName, bsaNames, modType, directoryStructure, pluginContainer)); + new ModInfoForeign(modName, espName, bsaNames, modType, game, directoryStructure, pluginContainer)); s_Collection.push_back(result); return result; } @@ -128,11 +129,12 @@ QString ModInfo::getContentTypeName(int contentType) } void ModInfo::createFromOverwrite(PluginContainer *pluginContainer, + const MOBase::IPluginGame* game, MOShared::DirectoryEntry **directoryStructure) { QMutexLocker locker(&s_Mutex); - s_Collection.push_back(ModInfo::Ptr(new ModInfoOverwrite(pluginContainer, directoryStructure))); + s_Collection.push_back(ModInfo::Ptr(new ModInfoOverwrite(pluginContainer, game, directoryStructure))); } unsigned int ModInfo::getNumMods() @@ -274,12 +276,13 @@ void ModInfo::updateFromDisc(const QString &modDirectory, unmanaged->referenceFile(modName).absoluteFilePath(), unmanaged->secondaryFiles(modName), modType, + game, directoryStructure, pluginContainer); } } - createFromOverwrite(pluginContainer, directoryStructure); + createFromOverwrite(pluginContainer, game, directoryStructure); std::sort(s_Collection.begin(), s_Collection.end(), ModInfo::ByName); diff --git a/src/modinfo.h b/src/modinfo.h index 2c108378..f582cc32 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -232,7 +232,8 @@ public: * @param bsaNames names of archives * @return a new mod */ - static ModInfo::Ptr createFromPlugin(const QString &modName, const QString &espName, const QStringList &bsaNames, ModInfo::EModType modType, MOShared::DirectoryEntry **directoryStructure, PluginContainer *pluginContainer); + static ModInfo::Ptr createFromPlugin(const QString &modName, const QString &espName, const QStringList &bsaNames, ModInfo::EModType modType, + const MOBase::IPluginGame* game, MOShared::DirectoryEntry **directoryStructure, PluginContainer *pluginContainer); // whether the given name is used for separators // @@ -826,6 +827,7 @@ protected: private: static void createFromOverwrite(PluginContainer *pluginContainer, + const MOBase::IPluginGame* game, MOShared::DirectoryEntry **directoryStructure); protected: diff --git a/src/modinfoforeign.cpp b/src/modinfoforeign.cpp index e8f9548a..19413891 100644 --- a/src/modinfoforeign.cpp +++ b/src/modinfoforeign.cpp @@ -46,9 +46,10 @@ ModInfoForeign::ModInfoForeign(const QString &modName, const QString &referenceFile, const QStringList &archives, ModInfo::EModType modType, + const MOBase::IPluginGame* gamePlugin, DirectoryEntry **directoryStructure, PluginContainer *pluginContainer) - : ModInfoWithConflictInfo(pluginContainer, directoryStructure), + : ModInfoWithConflictInfo(pluginContainer, gamePlugin, directoryStructure), m_ReferenceFile(referenceFile), m_Archives(archives), m_ModType(modType) { m_CreationTime = QFileInfo(referenceFile).birthTime(); diff --git a/src/modinfoforeign.h b/src/modinfoforeign.h index da2c865b..ae4241ee 100644 --- a/src/modinfoforeign.h +++ b/src/modinfoforeign.h @@ -71,6 +71,7 @@ public: protected: ModInfoForeign(const QString &modName, const QString &referenceFile, const QStringList &archives, ModInfo::EModType modType, + const MOBase::IPluginGame *gamePlugin, MOShared::DirectoryEntry **directoryStructure, PluginContainer *pluginContainer); private: diff --git a/src/modinfooverwrite.cpp b/src/modinfooverwrite.cpp index 1f7f9318..3b914134 100644 --- a/src/modinfooverwrite.cpp +++ b/src/modinfooverwrite.cpp @@ -6,8 +6,8 @@ #include #include -ModInfoOverwrite::ModInfoOverwrite(PluginContainer *pluginContainer, MOShared::DirectoryEntry **directoryStructure) - : ModInfoWithConflictInfo(pluginContainer, directoryStructure) +ModInfoOverwrite::ModInfoOverwrite(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, MOShared::DirectoryEntry **directoryStructure) + : ModInfoWithConflictInfo(pluginContainer, game, directoryStructure) { testValid(); } diff --git a/src/modinfooverwrite.h b/src/modinfooverwrite.h index 0bcf6f27..9770ecbb 100644 --- a/src/modinfooverwrite.h +++ b/src/modinfooverwrite.h @@ -68,7 +68,7 @@ public: virtual void addInstalledFile(int, int) override {} private: - ModInfoOverwrite(PluginContainer *pluginContainer, MOShared::DirectoryEntry **directoryStructure ); + ModInfoOverwrite(PluginContainer *pluginContainer, const MOBase::IPluginGame* game, MOShared::DirectoryEntry **directoryStructure); }; diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp index a1ef5701..d89716da 100644 --- a/src/modinforegular.cpp +++ b/src/modinforegular.cpp @@ -25,11 +25,10 @@ namespace { } ModInfoRegular::ModInfoRegular(PluginContainer *pluginContainer, const IPluginGame *game, const QDir &path, DirectoryEntry **directoryStructure) - : ModInfoWithConflictInfo(pluginContainer, directoryStructure) + : ModInfoWithConflictInfo(pluginContainer, game, directoryStructure) , m_Name(path.dirName()) , m_Path(path.absolutePath()) , m_Repository() - , m_GamePlugin(game) , m_GameName(game->gameShortName()) , m_IsAlternate(false) , m_Converted(false) diff --git a/src/modinforegular.h b/src/modinforegular.h index 75b24a6b..0f22b6cb 100644 --- a/src/modinforegular.h +++ b/src/modinforegular.h @@ -432,9 +432,6 @@ private: QString m_CustomURL; bool m_HasCustomURL; - // Current game plugin running in MO2: - MOBase::IPluginGame const* m_GamePlugin; - // Game name for the mod, can be different from the actual game running in MO2 // e.g., for Skyrim / Skyrim SE. QString m_GameName; diff --git a/src/modinfoseparator.h b/src/modinfoseparator.h index 80734bcf..4cfb9ea0 100644 --- a/src/modinfoseparator.h +++ b/src/modinfoseparator.h @@ -53,10 +53,10 @@ protected: private: - ModInfoSeparator - ( - PluginContainer* pluginContainer, const MOBase::IPluginGame* game, const QDir& path, - MOShared::DirectoryEntry** directoryStructure); + ModInfoSeparator( + PluginContainer* pluginContainer, + const MOBase::IPluginGame* game, const QDir& path, + MOShared::DirectoryEntry** directoryStructure); }; #endif diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp index d0516d06..00f4275c 100644 --- a/src/modinfowithconflictinfo.cpp +++ b/src/modinfowithconflictinfo.cpp @@ -6,12 +6,15 @@ #include "shared/fileentry.h" #include +#include "qdirfiletree.h" + using namespace MOBase; using namespace MOShared; namespace fs = std::filesystem; -ModInfoWithConflictInfo::ModInfoWithConflictInfo(PluginContainer *pluginContainer, DirectoryEntry **directoryStructure) - : ModInfo(pluginContainer), m_DirectoryStructure(directoryStructure), m_HasLooseOverwrite(false), m_HasHiddenFiles(false) {} +ModInfoWithConflictInfo::ModInfoWithConflictInfo( + PluginContainer *pluginContainer, const MOBase::IPluginGame* gamePlugin, DirectoryEntry **directoryStructure) + : ModInfo(pluginContainer), m_GamePlugin(gamePlugin), m_DirectoryStructure(directoryStructure), m_HasLooseOverwrite(false), m_HasHiddenFiles(false) {} void ModInfoWithConflictInfo::clearCaches() { diff --git a/src/modinfowithconflictinfo.h b/src/modinfowithconflictinfo.h index 0bb7c422..94a61c62 100644 --- a/src/modinfowithconflictinfo.h +++ b/src/modinfowithconflictinfo.h @@ -10,8 +10,6 @@ class ModInfoWithConflictInfo : public ModInfo public: - ModInfoWithConflictInfo(PluginContainer *pluginContainer, MOShared::DirectoryEntry **directoryStructure); - std::vector getConflictFlags() const override; virtual std::vector getFlags() const override; @@ -43,6 +41,11 @@ protected: **/ virtual bool doTestValid() const; + ModInfoWithConflictInfo( + PluginContainer* pluginContainer, + const MOBase::IPluginGame* gamePlugin, + MOShared::DirectoryEntry** directoryStructure); + private: enum EConflictType { @@ -80,6 +83,9 @@ private: private: + // Current game plugin running in MO2: + MOBase::IPluginGame const* m_GamePlugin; + MOShared::DirectoryEntry **m_DirectoryStructure; mutable EConflictType m_CurrentConflictState; -- cgit v1.3.1 From ee7438827e6fde8862b880e054a1506a06313de5 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Fri, 22 May 2020 15:50:50 +0200 Subject: Switch to ModDataChecker for testing mod validity. --- src/modinfowithconflictinfo.cpp | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp index 00f4275c..0c67b4f7 100644 --- a/src/modinfowithconflictinfo.cpp +++ b/src/modinfowithconflictinfo.cpp @@ -1,11 +1,11 @@ #include "modinfowithconflictinfo.h" -#include "installationtester.h" #include "utility.h" #include "shared/directoryentry.h" #include "shared/filesorigin.h" #include "shared/fileentry.h" #include +#include "moddatachecker.h" #include "qdirfiletree.h" using namespace MOBase; @@ -298,30 +298,12 @@ bool ModInfoWithConflictInfo::hasHiddenFiles() const bool ModInfoWithConflictInfo::doTestValid() const { + auto mdc = m_GamePlugin->feature(); - bool valid = false; - QDirIterator dirIter(absolutePath()); - while (dirIter.hasNext()) { - dirIter.next(); - if (dirIter.fileInfo().isDir()) { - if (InstallationTester::isTopLevelDirectory(dirIter.fileName())) { - valid = true; - break; - } - } - else { - if (InstallationTester::isTopLevelSuffix(dirIter.fileName())) { - valid = true; - break; - } - } - } - - // NOTE: in Qt 4.7 it seems that QDirIterator leaves a file handle open if it is not iterated to the - // end - while (dirIter.hasNext()) { - dirIter.next(); + if (mdc) { + auto qdirfiletree = QDirFileTree::makeTree(absolutePath()); + return mdc->dataLooksValid(qdirfiletree); } - return valid; + return true; } -- cgit v1.3.1 From ee995b8df5a1b9c708a069e62f0e786ff359e76b Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 23 May 2020 17:09:20 +0200 Subject: Remove include that has been removed from uibase. --- src/modlist.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/modlist.cpp b/src/modlist.cpp index 9fbd3de4..ea4aa2e3 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -20,7 +20,6 @@ along with Mod Organizer. If not, see . #include "modlist.h" #include "messagedialog.h" -#include "installationtester.h" #include "qtgroupingproxy.h" #include "viewmarkingscrollbar.h" #include "modlistsortproxy.h" -- cgit v1.3.1 From 064ef4cfeb7307cae1cfbc640ca3c47e8032f365 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 23 May 2020 17:33:01 +0200 Subject: Update IFileTree implementations following uibase changes. --- src/archivefiletree.cpp | 29 ++++++++++------------------- src/qdirfiletree.cpp | 19 +++++++++---------- src/qdirfiletree.h | 7 ++++--- 3 files changed, 23 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/archivefiletree.cpp b/src/archivefiletree.cpp index 0b715f4f..6ba06924 100644 --- a/src/archivefiletree.cpp +++ b/src/archivefiletree.cpp @@ -33,23 +33,11 @@ class ArchiveFileEntry : public virtual FileTreeEntry { public: /** - * @brief Create a new entry corresponding to a file. + * @brief Create a new entry. * - * @param parent The tree containing this file. - * @param name The name of this file. - * @param index The index of the file in the archive. - * @param time The modification time of this file. - */ - ArchiveFileEntry(std::shared_ptr parent, QString name, int index, QDateTime time) : - FileTreeEntry(parent, name, time), m_Index(index) { - } - - /** - * @brief Create a new entry corresponding to a directory. - * - * @param parent The tree containing this directory. - * @param name The name of this directory. - * @param index The index of the directory in the archive, or -1. + * @param parent The tree containing this entry. + * @param name The name of this entry. + * @param index The index of the entry in the archive. */ ArchiveFileEntry(std::shared_ptr parent, QString name, int index) : FileTreeEntry(parent, name), m_Index(index) { @@ -98,7 +86,7 @@ public: // Overrides: /** * @override */ - std::shared_ptr addFile(QString path, QDateTime time = QDateTime()) override { + std::shared_ptr addFile(QString path) override { // Cannot add file to an archive. throw UnsupportedOperationException(QObject::tr("Cannot create file within an archive.")); } @@ -159,7 +147,7 @@ protected: return std::make_shared(parent, name, -1, std::vector{}); } - virtual void doPopulate(std::shared_ptr parent, std::vector>& entries) const override { + virtual bool doPopulate(std::shared_ptr parent, std::vector>& entries) const override { // Sort by name: std::sort(std::begin(m_Files), std::end(m_Files), @@ -200,7 +188,7 @@ protected: // If it is not a directory, then it is a file in directly under this tree: if (!std::get<1>(p)) { entries.push_back( - std::make_shared(parent, currentName, std::get<2>(p), QDateTime())); + std::make_shared(parent, currentName, std::get<2>(p))); currentName = ""; } else { @@ -219,6 +207,9 @@ protected: if (currentName != "") { entries.push_back(std::make_shared(parent, currentName, currentIndex, std::move(currentFiles))); } + + // Let the parent class sort the entries: + return false; } virtual std::shared_ptr doClone() const override { diff --git a/src/qdirfiletree.cpp b/src/qdirfiletree.cpp index 5570060a..e80c7127 100644 --- a/src/qdirfiletree.cpp +++ b/src/qdirfiletree.cpp @@ -14,9 +14,7 @@ std::shared_ptr QDirFileTree::makeTree(QDir directory) { /** * */ -QDirFileTree::QDirFileTree(std::shared_ptr parent, QDir directory) : FileTreeEntry(parent, directory.dirName()), IFileTree(), qDir(directory) { - qDir.setFilter(qDir.filter() | QDir::NoDotAndDotDot); -} +QDirFileTree::QDirFileTree(std::shared_ptr parent, QDir directory) : FileTreeEntry(parent, directory.dirName()), IFileTree(), qDir(directory) { } /** * No mutable operations allowed. @@ -24,21 +22,22 @@ QDirFileTree::QDirFileTree(std::shared_ptr parent, QDir directo bool QDirFileTree::beforeReplace(IFileTree const* dstTree, FileTreeEntry const* destination, FileTreeEntry const* source) { return false; } bool QDirFileTree::beforeInsert(IFileTree const* entry, FileTreeEntry const* name) { return false; } bool QDirFileTree::beforeRemove(IFileTree const* entry, FileTreeEntry const* name) { return false; } -std::shared_ptr QDirFileTree::makeFile(std::shared_ptr parent, QString name, QDateTime time) const { return nullptr; } +std::shared_ptr QDirFileTree::makeFile(std::shared_ptr parent, QString name) const { return nullptr; } std::shared_ptr QDirFileTree::makeDirectory(std::shared_ptr parent, QString name) const { return nullptr; } -void QDirFileTree::doPopulate(std::shared_ptr parent, std::vector>& entries) const { - QDirIterator iter(qDir); - while (iter.hasNext()) { - QString name = iter.next(); - QFileInfo info = iter.fileInfo(); +bool QDirFileTree::doPopulate(std::shared_ptr parent, std::vector>& entries) const { + auto infoList = qDir.entryInfoList(qDir.filter() | QDir::NoDotAndDotDot, QDir::Name | QDir::DirsFirst | QDir::IgnoreCase); + for (auto& info : infoList) { if (info.isDir()) { entries.push_back(std::shared_ptr(new QDirFileTree(parent, QDir(info.absoluteFilePath())))); } else { - entries.push_back(createFileEntry(parent, info.fileName(), info.fileTime(QFileDevice::FileModificationTime))); + entries.push_back(createFileEntry(parent, info.fileName())); } } + + // Vector is already sorted: + return true; } std::shared_ptr QDirFileTree::doClone() const { diff --git a/src/qdirfiletree.h b/src/qdirfiletree.h index 000ef69a..e6b8706e 100644 --- a/src/qdirfiletree.h +++ b/src/qdirfiletree.h @@ -43,17 +43,18 @@ public: */ static std::shared_ptr makeTree(QDir directory); + QDirFileTree(std::shared_ptr parent, QDir directory); + protected: - QDirFileTree(std::shared_ptr parent, QDir directory); virtual bool beforeReplace(IFileTree const* dstTree, FileTreeEntry const* destination, FileTreeEntry const* source) override; virtual bool beforeInsert(IFileTree const* entry, FileTreeEntry const* name) override; virtual bool beforeRemove(IFileTree const* entry, FileTreeEntry const* name) override; - virtual std::shared_ptr makeFile(std::shared_ptr parent, QString name, QDateTime time) const override; + virtual std::shared_ptr makeFile(std::shared_ptr parent, QString name) const override; virtual std::shared_ptr makeDirectory(std::shared_ptr parent, QString name) const override; - virtual void doPopulate(std::shared_ptr parent, std::vector>& entries) const override; + virtual bool doPopulate(std::shared_ptr parent, std::vector>& entries) const override; virtual std::shared_ptr doClone() const override; QDir qDir; -- cgit v1.3.1 From 7b973d5f10299c116c3c707ba28c7d6922be0a9a Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 23 May 2020 17:33:16 +0200 Subject: Remove header that has been removed from uibase. --- src/installationmanager.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp index d4e6a444..62a97591 100644 --- a/src/installationmanager.cpp +++ b/src/installationmanager.cpp @@ -34,7 +34,6 @@ along with Mod Organizer. If not, see . #include "selectiondialog.h" #include "modinfo.h" #include -#include #include #include -- cgit v1.3.1 From 2652ed120964e568527fd7e1858a3dd91611fca4 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 23 May 2020 18:40:21 +0200 Subject: Update QDirFileTree to hide implementation and allow querying time through QFileInfo. --- src/qdirfiletree.cpp | 91 ++++++++++++++++++++++++++++++++++------------------ src/qdirfiletree.h | 15 ++------- 2 files changed, 61 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/qdirfiletree.cpp b/src/qdirfiletree.cpp index e80c7127..691bac87 100644 --- a/src/qdirfiletree.cpp +++ b/src/qdirfiletree.cpp @@ -4,42 +4,69 @@ using namespace MOBase; -/** - * - */ -std::shared_ptr QDirFileTree::makeTree(QDir directory) { - return std::shared_ptr(new QDirFileTree(nullptr, directory)); -} +class QFileTreeEntry : public virtual FileTreeEntry { +public: + using FileTreeEntry::FileTreeEntry; -/** - * - */ -QDirFileTree::QDirFileTree(std::shared_ptr parent, QDir directory) : FileTreeEntry(parent, directory.dirName()), IFileTree(), qDir(directory) { } + QFileTreeEntry(std::shared_ptr parent, QFileInfo fileInfo) : + FileTreeEntry(parent, fileInfo.fileName()), m_FileInfo(fileInfo) { } -/** - * No mutable operations allowed. - */ -bool QDirFileTree::beforeReplace(IFileTree const* dstTree, FileTreeEntry const* destination, FileTreeEntry const* source) { return false; } -bool QDirFileTree::beforeInsert(IFileTree const* entry, FileTreeEntry const* name) { return false; } -bool QDirFileTree::beforeRemove(IFileTree const* entry, FileTreeEntry const* name) { return false; } -std::shared_ptr QDirFileTree::makeFile(std::shared_ptr parent, QString name) const { return nullptr; } -std::shared_ptr QDirFileTree::makeDirectory(std::shared_ptr parent, QString name) const { return nullptr; } - -bool QDirFileTree::doPopulate(std::shared_ptr parent, std::vector>& entries) const { - auto infoList = qDir.entryInfoList(qDir.filter() | QDir::NoDotAndDotDot, QDir::Name | QDir::DirsFirst | QDir::IgnoreCase); - for (auto& info : infoList) { - if (info.isDir()) { - entries.push_back(std::shared_ptr(new QDirFileTree(parent, QDir(info.absoluteFilePath())))); - } - else { - entries.push_back(createFileEntry(parent, info.fileName())); + QDateTime time() const override { + return m_FileInfo.lastModified(); + } + +protected: + QFileInfo m_FileInfo; +}; + +class QDirFileTreeImpl : public QDirFileTree { +public: + + + /** + * + */ + QDirFileTreeImpl(std::shared_ptr parent, QDir dir) : + FileTreeEntry(parent, dir.dirName()), QDirFileTree(), qDir(dir) { } + +protected: + + /** + * No mutable operations allowed. + */ + bool beforeReplace(IFileTree const* dstTree, FileTreeEntry const* destination, FileTreeEntry const* source) override { return false; } + bool beforeInsert(IFileTree const* entry, FileTreeEntry const* name) override { return false; } + bool beforeRemove(IFileTree const* entry, FileTreeEntry const* name) override { return false; } + std::shared_ptr makeFile(std::shared_ptr parent, QString name) const override { return nullptr; } + std::shared_ptr makeDirectory(std::shared_ptr parent, QString name) const override { return nullptr; } + + bool doPopulate(std::shared_ptr parent, std::vector>& entries) const override { + auto infoList = qDir.entryInfoList(qDir.filter() | QDir::NoDotAndDotDot, QDir::Name | QDir::DirsFirst | QDir::IgnoreCase); + for (auto& info : infoList) { + if (info.isDir()) { + entries.push_back(std::make_shared(parent, QDir(info.absoluteFilePath()))); + } + else { + entries.push_back(std::make_shared(parent, info)); + } } + + // Vector is already sorted: + return true; } - // Vector is already sorted: - return true; -} + std::shared_ptr QDirFileTree::doClone() const { + return std::make_shared(nullptr, qDir); + } + +private: + QDir qDir; -std::shared_ptr QDirFileTree::doClone() const { - return std::shared_ptr(new QDirFileTree(nullptr, qDir)); +}; + +/** + * + */ +std::shared_ptr QDirFileTree::makeTree(QDir directory) { + return std::make_shared(nullptr, directory); } diff --git a/src/qdirfiletree.h b/src/qdirfiletree.h index e6b8706e..1f85b04f 100644 --- a/src/qdirfiletree.h +++ b/src/qdirfiletree.h @@ -43,22 +43,11 @@ public: */ static std::shared_ptr makeTree(QDir directory); - QDirFileTree(std::shared_ptr parent, QDir directory); - protected: + using IFileTree::IFileTree; - virtual bool beforeReplace(IFileTree const* dstTree, FileTreeEntry const* destination, FileTreeEntry const* source) override; - virtual bool beforeInsert(IFileTree const* entry, FileTreeEntry const* name) override; - virtual bool beforeRemove(IFileTree const* entry, FileTreeEntry const* name) override; - - virtual std::shared_ptr makeFile(std::shared_ptr parent, QString name) const override; - virtual std::shared_ptr makeDirectory(std::shared_ptr parent, QString name) const override; - virtual bool doPopulate(std::shared_ptr parent, std::vector>& entries) const override; - virtual std::shared_ptr doClone() const override; - - QDir qDir; - + virtual bool doPopulate(std::shared_ptr parent, std::vector>& entries) const = 0; }; #endif -- cgit v1.3.1 From 5f794fec2ce2c297a6641a2db1e1152370adf636 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 23 May 2020 21:45:57 +0200 Subject: Remove time() method from FileTreeEntry. --- src/qdirfiletree.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'src') diff --git a/src/qdirfiletree.cpp b/src/qdirfiletree.cpp index 691bac87..770a9df8 100644 --- a/src/qdirfiletree.cpp +++ b/src/qdirfiletree.cpp @@ -4,21 +4,6 @@ using namespace MOBase; -class QFileTreeEntry : public virtual FileTreeEntry { -public: - using FileTreeEntry::FileTreeEntry; - - QFileTreeEntry(std::shared_ptr parent, QFileInfo fileInfo) : - FileTreeEntry(parent, fileInfo.fileName()), m_FileInfo(fileInfo) { } - - QDateTime time() const override { - return m_FileInfo.lastModified(); - } - -protected: - QFileInfo m_FileInfo; -}; - class QDirFileTreeImpl : public QDirFileTree { public: @@ -47,7 +32,7 @@ protected: entries.push_back(std::make_shared(parent, QDir(info.absoluteFilePath()))); } else { - entries.push_back(std::make_shared(parent, info)); + entries.push_back(createFileEntry(parent, info.fileName())); } } -- cgit v1.3.1 From fceca422db04ae9d8cd9ca5e2e21a06697293937 Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 23 May 2020 22:21:38 +0200 Subject: Add comment about lazy-populating the QDirFileTree. --- src/qdirfiletree.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/qdirfiletree.h b/src/qdirfiletree.h index 1f85b04f..219a3a6f 100644 --- a/src/qdirfiletree.h +++ b/src/qdirfiletree.h @@ -26,7 +26,10 @@ along with Mod Organizer. If not, see . /** - * Class that expose a directory on the drive, using QDir, as a `MOBase::IFileTree`. + * @brief Class that expose a directory on the drive, using QDir, as a `MOBase::IFileTree`. + * + * The tree is lazily populated: each subtree is only populated (from the disk) when needed, + * as specified by IFileTree. * * This class does not expose mutable operations, so any mutable operations will * fail. -- cgit v1.3.1 From 20649ec027a6da0994819c0ce18c4862f8ff66f9 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Sat, 23 May 2020 23:08:05 +0200 Subject: Fix issues with very slow refresh time for large root data directories. --- src/organizercore.cpp | 16 ++++++---------- src/shared/directoryentry.cpp | 32 +++----------------------------- src/shared/directoryentry.h | 21 ++++++++++----------- 3 files changed, 19 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/organizercore.cpp b/src/organizercore.cpp index a6d6e34f..feab76a7 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -834,10 +834,8 @@ QStringList OrganizerCore::listDirectories(const QString &directoryName) const if (!directoryName.isEmpty()) dir = dir->findSubDirectoryRecursive(ToWString(directoryName)); if (dir != nullptr) { - std::vector::iterator current, end; - dir->getSubDirectories(current, end); - for (; current != end; ++current) { - result.append(ToQString((*current)->getName())); + for (const auto& d : dir->getSubDirectories()) { + result.append(ToQString(d->getName())); } } return result; @@ -1926,14 +1924,12 @@ std::vector OrganizerCore::fileMapping( } // recurse into subdirectories - std::vector::const_iterator current, end; - directoryEntry->getSubDirectories(current, end); - for (; current != end; ++current) { - int origin = (*current)->anyOrigin(); + for (const auto& d : directoryEntry->getSubDirectories()) { + int origin = d->anyOrigin(); QString originPath = QString::fromStdWString(base->getOriginByID(origin).getPath()); - QString dirName = QString::fromStdWString((*current)->getName()); + QString dirName = QString::fromStdWString(d->getName()); QString source = originPath + relPath + dirName; QString target = dataPath + relPath + dirName; @@ -1942,7 +1938,7 @@ std::vector OrganizerCore::fileMapping( result.push_back({source, target, true, writeDestination}); std::vector subRes = fileMapping( - dataPath, relPath + dirName + "\\", base, *current, createDestination); + dataPath, relPath + dirName + "\\", base, d, createDestination); result.insert(result.end(), subRes.begin(), subRes.end()); } return result; diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 43408dcf..c4b467d6 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -67,7 +67,8 @@ static bool SupportOptimizedFind() return (::VerifyVersionInfo(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, mask) == TRUE); } -static bool DirCompareByName(const DirectoryEntry* lhs, const DirectoryEntry* rhs) +bool DirCompareByName::operator()( + const DirectoryEntry* lhs, const DirectoryEntry* rhs) const { return _wcsicmp(lhs->getName().c_str(), rhs->getName().c_str()) < 0; } @@ -156,13 +157,6 @@ void DirectoryEntry::addDir( } }); - elapsed(stats.sortTimes, [&]{ - std::sort( - m_SubDirectories.begin(), - m_SubDirectories.end(), - &DirCompareByName); - }); - m_Populated = true; } @@ -647,15 +641,6 @@ void DirectoryEntry::addFiles( onFile((Context*)pcx, path, ft); } ); - - { - std::scoped_lock lock(m_SubDirMutex); - - std::sort( - m_SubDirectories.begin(), - m_SubDirectories.end(), - &DirCompareByName); - } } void DirectoryEntry::onDirectoryStart(Context* cx, std::wstring_view path) @@ -671,17 +656,6 @@ void DirectoryEntry::onDirectoryStart(Context* cx, std::wstring_view path) void DirectoryEntry::onDirectoryEnd(Context* cx, std::wstring_view path) { elapsed(cx->stats.dirTimes, [&] { - auto* current = cx->current.top(); - - { - std::scoped_lock lock(current->m_SubDirMutex); - - std::sort( - current->m_SubDirectories.begin(), - current->m_SubDirectories.end(), - &DirCompareByName); - } - cx->current.pop(); }); } @@ -842,7 +816,7 @@ void DirectoryEntry::removeDirRecursive() void DirectoryEntry::addDirectoryToList(DirectoryEntry* e, std::wstring nameLc) { - m_SubDirectories.push_back(e); + m_SubDirectories.insert(e); m_SubDirectoriesLookup.emplace(std::move(nameLc), e); } diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index a28ceeae..0ee3c919 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -46,10 +46,18 @@ namespace std namespace MOShared { +struct DirCompareByName +{ + bool operator()(const DirectoryEntry* a, const DirectoryEntry* b) const; +}; + + class DirectoryEntry { public: - DirectoryEntry( + using SubDirectories = std::set; + + DirectoryEntry( std::wstring name, DirectoryEntry* parent, OriginID originID); DirectoryEntry( @@ -137,15 +145,7 @@ public: std::vector getFiles() const; - void getSubDirectories( - std::vector::const_iterator& begin, - std::vector::const_iterator& end) const - { - begin = m_SubDirectories.begin(); - end = m_SubDirectories.end(); - } - - const std::vector& getSubDirectories() const + const SubDirectories& getSubDirectories() const { return m_SubDirectories; } @@ -238,7 +238,6 @@ public: private: using FilesMap = std::map; using FilesLookup = std::unordered_map; - using SubDirectories = std::vector; using SubDirectoriesLookup = std::unordered_map; boost::shared_ptr m_FileRegister; -- cgit v1.3.1 From 6374845a28c8f1f65a05fb954b4df1ebd541344b Mon Sep 17 00:00:00 2001 From: Mikaël Capelle Date: Sat, 23 May 2020 23:09:20 +0200 Subject: Bump to 2.3.0a9 and update copyright to 2020. --- src/version.rc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/version.rc b/src/version.rc index b845233d..b0969b89 100644 --- a/src/version.rc +++ b/src/version.rc @@ -4,7 +4,7 @@ // Otherwise, if letters are used in VER_FILEVERSION_STR, uses the full MOBase::VersionInfo parser // Otherwise, uses the numbers from VER_FILEVERSION and sets the release type as pre-alpha #define VER_FILEVERSION 2,3,0 -#define VER_FILEVERSION_STR "2.3.0alpha8\0" +#define VER_FILEVERSION_STR "2.3.0alpha9\0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION @@ -24,7 +24,7 @@ BEGIN VALUE "FileDescription", "Mod Organizer 2 GUI\0" VALUE "OriginalFilename", "ModOrganizer.exe\0" VALUE "InternalName", "ModOrganizer2\0" - VALUE "LegalCopyright", "Copyright 2011-2016 Sebastian Herbord\r\nCopyright 2016-2019 Mod Organizer 2 contributors\0" + VALUE "LegalCopyright", "Copyright 2011-2016 Sebastian Herbord\r\nCopyright 2016-2020 Mod Organizer 2 contributors\0" VALUE "ProductName", "Mod Organizer 2\0" VALUE "ProductVersion", VER_FILEVERSION_STR END -- cgit v1.3.1