diff options
| author | Mikaël Capelle <capelle.mikael@gmail.com> | 2020-05-24 13:27:40 +0200 |
|---|---|---|
| committer | Mikaël Capelle <capelle.mikael@gmail.com> | 2020-05-24 13:27:40 +0200 |
| commit | 9fb639a00e1a809a9ea9b5e68777ec46f534761c (patch) | |
| tree | 9f72cebe6ba9825a0330fefe60a0b55de2392a2e /src | |
| parent | 08ae9db2fd2a07acb2433275fc84c2ca47267a92 (diff) | |
Update ModInfo to use a single file tree for all content-related operations.
Diffstat (limited to 'src')
| -rw-r--r-- | src/mainwindow.cpp | 4 | ||||
| -rw-r--r-- | src/modinfo.cpp | 7 | ||||
| -rw-r--r-- | src/modinfo.h | 23 | ||||
| -rw-r--r-- | src/modinfooverwrite.cpp | 1 | ||||
| -rw-r--r-- | src/modinforegular.cpp | 90 | ||||
| -rw-r--r-- | src/modinforegular.h | 3 | ||||
| -rw-r--r-- | src/modinfowithconflictinfo.cpp | 18 | ||||
| -rw-r--r-- | src/modinfowithconflictinfo.h | 38 | ||||
| -rw-r--r-- | src/modlist.cpp | 4 | ||||
| -rw-r--r-- | src/modlist.h | 2 | ||||
| -rw-r--r-- | src/organizercore.cpp | 2 |
11 files changed, 112 insertions, 80 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b5beb229..cc681dba 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3062,7 +3062,7 @@ void MainWindow::ignoreMissingData_clicked() int row_idx = idx.data(Qt::UserRole + 1).toInt(); ModInfo::Ptr info = ModInfo::getByIndex(row_idx); //QDir(info->absolutePath()).mkdir("textures"); - info->testValid(); + info->diskContentModified(); info->markValidated(true); connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex))); @@ -3071,7 +3071,7 @@ void MainWindow::ignoreMissingData_clicked() } else { ModInfo::Ptr info = ModInfo::getByIndex(m_ContextRow); //QDir(info->absolutePath()).mkdir("textures"); - info->testValid(); + info->diskContentModified(); info->markValidated(true); connect(this, SIGNAL(modListDataChanged(QModelIndex, QModelIndex)), m_OrganizerCore.modList(), SIGNAL(dataChanged(QModelIndex, QModelIndex))); diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 379fa071..0dd113c5 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -306,7 +306,7 @@ void ModInfo::updateIndices() ModInfo::ModInfo(PluginContainer *pluginContainer) - : m_Valid(false), m_PrimaryCategory(-1) + : m_PrimaryCategory(-1) { } @@ -528,11 +528,6 @@ bool ModInfo::categorySet(int categoryID) const return false; } -void ModInfo::testValid() -{ - m_Valid = doTestValid(); -} - QUrl ModInfo::parseCustomURL() const { if (!hasCustomURL() || getCustomURL().isEmpty()) { diff --git a/src/modinfo.h b/src/modinfo.h index f582cc32..b3e75bc4 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -702,7 +702,7 @@ public: /** * @return true if this mod is considered "valid", that is: it contains data used by the game **/ - virtual bool isValid() const { return m_Valid; } + virtual bool isValid() const = 0; /** * @return true if the file has been endorsed on nexus @@ -715,11 +715,6 @@ public: virtual ETrackedState trackedState() const { return TRACKED_FALSE; } /** - * @brief updates the valid-flag for this mod - */ - void testValid(); - - /** * @brief updates the mod to flag it as converted in order to ignore the alternate game warning */ virtual void markConverted(bool) {} @@ -801,6 +796,13 @@ public: **/ QUrl parseCustomURL() const; +public slots: + + /** + * @brief Notify this mod that the content of the disk may have changed. + */ + virtual void diskContentModified() = 0; + signals: /** @@ -817,13 +819,6 @@ protected: static void updateIndices(); static bool ByName(const ModInfo::Ptr &LHS, const ModInfo::Ptr &RHS); - /** - * @brief check if the content of this mod is valid. - * - * @return true if the content is valid, false otherwize. - **/ - virtual bool doTestValid() const = 0; - private: static void createFromOverwrite(PluginContainer *pluginContainer, @@ -848,8 +843,6 @@ private: static std::map<std::pair<QString, int>, std::vector<unsigned int> > s_ModsByModID; static int s_NextID; - bool m_Valid; - }; diff --git a/src/modinfooverwrite.cpp b/src/modinfooverwrite.cpp index 3b914134..8aad6209 100644 --- a/src/modinfooverwrite.cpp +++ b/src/modinfooverwrite.cpp @@ -9,7 +9,6 @@ ModInfoOverwrite::ModInfoOverwrite(PluginContainer *pluginContainer, const MOBase::IPluginGame *game, MOShared::DirectoryEntry **directoryStructure) : ModInfoWithConflictInfo(pluginContainer, game, directoryStructure) { - testValid(); } bool ModInfoOverwrite::isEmpty() const diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp index d89716da..3c1d49ea 100644 --- a/src/modinforegular.cpp +++ b/src/modinforegular.cpp @@ -38,7 +38,6 @@ ModInfoRegular::ModInfoRegular(PluginContainer *pluginContainer, const IPluginGa , m_TrackedState(TRACKED_UNKNOWN) , m_NexusBridge(pluginContainer) { - testValid(); m_CreationTime = QFileInfo(path.absolutePath()).birthTime(); // read out the meta-file for information readMeta(); @@ -656,58 +655,59 @@ std::vector<ModInfo::EFlag> ModInfoRegular::getFlags() const std::vector<ModInfo::EContent> ModInfoRegular::getContents() const { - QTime now = QTime::currentTime(); - if (m_LastContentCheck.isNull() || (m_LastContentCheck.secsTo(now) > 60)) { - m_CachedContent.clear(); - QDir dir(absolutePath()); - if (dir.entryList(QStringList() << "*.esp" << "*.esm" << "*.esl").size() > 0) { - m_CachedContent.push_back(CONTENT_PLUGIN); - } - if (dir.entryList(QStringList() << "*.bsa" << "*.ba2").size() > 0) { - m_CachedContent.push_back(CONTENT_BSA); - } - //use >1 for ini files since there is meta.ini in all mods already. - if (dir.entryList(QStringList() << "*.ini").size() > 1) { - m_CachedContent.push_back(CONTENT_INI); - } + auto tree = contentFileTree(); + std::vector<ModInfo::EContent> contents; - if (dir.entryList(QStringList() << "*.modgroups").size() > 0) { - m_CachedContent.push_back(CONTENT_MODGROUP); + for (auto e : *tree) { + if (e->isFile()) { + auto suffix = e->suffix(); + if (suffix == "esp" || suffix == "esm" || suffix == "esl") { + contents.push_back(CONTENT_PLUGIN); + } + else if (suffix == "bsa" || suffix == "ba2") { + contents.push_back(CONTENT_BSA); + } + //use >1 for ini files since there is meta.ini in all mods already. + else if (suffix == "ini" && e->compare("meta.ini") != 0) { + contents.push_back(CONTENT_INI); + } + else if (suffix == "modgroups") { + contents.push_back(CONTENT_MODGROUP); + } } + else { + if (e->compare("textures") == 0 || e->compare("icons") == 0 || e->compare("bookart") == 0) + contents.push_back(CONTENT_TEXTURE); + if (e->compare("meshes") == 0) + contents.push_back(CONTENT_MESH); + if (e->compare("interface") == 0 || e->compare("menus") == 0) + contents.push_back(CONTENT_INTERFACE); + if (e->compare("music") == 0 || e->compare("sound") == 0) + contents.push_back(CONTENT_SOUND); + if (e->compare("scripts") == 0) + contents.push_back(CONTENT_SCRIPT); + if (e->compare("SkyProc Patchers") == 0) + contents.push_back(CONTENT_SKYPROC); + if (e->compare("MCM") == 0) + contents.push_back(CONTENT_MCM); + } + } - ScriptExtender *extender = qApp->property("managed_game") - .value<IPluginGame *>() - ->feature<ScriptExtender>(); - - if (extender != nullptr) { - QString sePluginPath = extender->PluginPath(); - if (dir.exists(sePluginPath)) { - m_CachedContent.push_back(CONTENT_SKSEFILES); - QDir sePluginDir(absolutePath() + "/" + sePluginPath); - if (sePluginDir.entryList(QStringList() << "*.dll").size() > 0) { - m_CachedContent.push_back(CONTENT_SKSE); + ScriptExtender* extender = m_GamePlugin->feature<ScriptExtender>(); + if (extender != nullptr) { + auto e = tree->findDirectory(extender->PluginPath()); + if (e) { + contents.push_back(CONTENT_SKSEFILES); + for (auto f : *e) { + if (e->suffix().compare("dll") == 0) { + contents.push_back(CONTENT_SKSE); + break; } } } - if (dir.exists("textures") || dir.exists("icons") || dir.exists("bookart")) - m_CachedContent.push_back(CONTENT_TEXTURE); - if (dir.exists("meshes")) - m_CachedContent.push_back(CONTENT_MESH); - if (dir.exists("interface") || dir.exists("menus")) - m_CachedContent.push_back(CONTENT_INTERFACE); - if (dir.exists("music") || dir.exists("sound")) - m_CachedContent.push_back(CONTENT_SOUND); - if (dir.exists("scripts")) - m_CachedContent.push_back(CONTENT_SCRIPT); - if (dir.exists("SkyProc Patchers")) - m_CachedContent.push_back(CONTENT_SKYPROC); - if (dir.exists("MCM")) - m_CachedContent.push_back(CONTENT_MCM); - - m_LastContentCheck = QTime::currentTime(); } - return m_CachedContent; + return contents; } diff --git a/src/modinforegular.h b/src/modinforegular.h index 0f22b6cb..08546c69 100644 --- a/src/modinforegular.h +++ b/src/modinforegular.h @@ -462,9 +462,6 @@ private: NexusBridge m_NexusBridge; - mutable std::vector<ModInfo::EContent> m_CachedContent; - mutable QTime m_LastContentCheck; - bool needsDescriptionUpdate() const; }; diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp index 0c67b4f7..45ecffb7 100644 --- a/src/modinfowithconflictinfo.cpp +++ b/src/modinfowithconflictinfo.cpp @@ -296,14 +296,30 @@ bool ModInfoWithConflictInfo::hasHiddenFiles() const return m_HasHiddenFiles; } +void ModInfoWithConflictInfo::diskContentModified() { + std::unique_lock lock(m_Mutex); + m_FileTree = nullptr; +} + +std::shared_ptr<const IFileTree> ModInfoWithConflictInfo::contentFileTree() const { + std::unique_lock lock(m_Mutex); + if (!m_FileTree) { + m_FileTree = QDirFileTree::makeTree(absolutePath()); + } + return m_FileTree; +} bool ModInfoWithConflictInfo::doTestValid() const { auto mdc = m_GamePlugin->feature<ModDataChecker>(); if (mdc) { - auto qdirfiletree = QDirFileTree::makeTree(absolutePath()); + auto qdirfiletree = contentFileTree(); return mdc->dataLooksValid(qdirfiletree); } return true; } + +bool ModInfoWithConflictInfo::isValid() const { + return doTestValid(); +} diff --git a/src/modinfowithconflictinfo.h b/src/modinfowithconflictinfo.h index 94a61c62..5bc1d585 100644 --- a/src/modinfowithconflictinfo.h +++ b/src/modinfowithconflictinfo.h @@ -1,6 +1,8 @@ #ifndef MODINFOWITHCONFLICTINFO_H #define MODINFOWITHCONFLICTINFO_H +#include <ifiletree.h> + #include "modinfo.h" #include <QTime> @@ -14,6 +16,11 @@ public: virtual std::vector<ModInfo::EFlag> getFlags() const override; /** + * @return true if this mod is considered "valid", that is: it contains data used by the game + **/ + virtual bool isValid() const override; + + /** * @brief clear all caches held for this mod */ virtual void clearCaches() override; @@ -32,6 +39,13 @@ public: virtual void doConflictCheck() const override; +public slots: + + /** + * @brief Notify this mod that the content of the disk may have changed. + */ + virtual void diskContentModified(); + protected: /** @@ -41,6 +55,17 @@ protected: **/ virtual bool doTestValid() const; + /** + * @brief Retrieve a file tree corresponding to the underlying disk content + * of this mod. + * + * The file tree should not be cached since it is already cached and updated when + * required. + * + * @return a file tree representing the content of this mod. + */ + std::shared_ptr<const MOBase::IFileTree> contentFileTree() const; + ModInfoWithConflictInfo( PluginContainer* pluginContainer, const MOBase::IPluginGame* gamePlugin, @@ -81,10 +106,19 @@ private: bool hasHiddenFiles() const; -private: +protected: // Current game plugin running in MO2: - MOBase::IPluginGame const* m_GamePlugin; + MOBase::IPluginGame const * const m_GamePlugin; + +private: + + // Mutex: + mutable std::mutex m_Mutex; + + // File tree representing the content of the disk. A null pointer indicates + // that the content needs to be loaded from the disk: + mutable std::shared_ptr<const MOBase::IFileTree> m_FileTree = nullptr; MOShared::DirectoryEntry **m_DirectoryStructure; diff --git a/src/modlist.cpp b/src/modlist.cpp index ea4aa2e3..e8c14434 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -849,7 +849,7 @@ void ModList::modInfoChanged(ModInfo::Ptr info) } int row = ModInfo::getIndex(info->name()); - info->testValid(); + info->diskContentModified(); emit aboutToChangeData(); emit dataChanged(index(row, 0), index(row, columnCount())); emit postDataChanged(); @@ -1076,7 +1076,7 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa } if (!modInfo->isValid()) { - modInfo->testValid(); + modInfo->diskContentModified(); } return true; diff --git a/src/modlist.h b/src/modlist.h index d8980dec..4d456a9a 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -276,8 +276,6 @@ protected: private:
- bool testValid(const QString &modDir);
-
QVariant getOverwriteData(int column, int role) const;
QString getFlagText(ModInfo::EFlag flag, ModInfo::Ptr modInfo) const;
diff --git a/src/organizercore.cpp b/src/organizercore.cpp index feab76a7..74163d8d 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1629,7 +1629,7 @@ void OrganizerCore::syncOverwrite() qApp->activeWindow()); if (syncDialog.exec() == QDialog::Accepted) { syncDialog.apply(QDir::fromNativeSeparators(m_Settings.paths().mods())); - modInfo->testValid(); + modInfo->diskContentModified(); refreshDirectoryStructure(); } } |
