diff options
Diffstat (limited to 'src/modinfo.cpp')
| -rw-r--r-- | src/modinfo.cpp | 498 |
1 files changed, 267 insertions, 231 deletions
diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 0b9d65f8..c14eedb7 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -20,22 +20,22 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include "modinfo.h" #include "modinfobackup.h" +#include "modinforegular.h" #include "modinfoforeign.h" #include "modinfooverwrite.h" -#include "modinforegular.h" -#include "categories.h" -#include "filenamestring.h" #include "installationtester.h" +#include "categories.h" #include "modinfodialog.h" #include "overwriteinfodialog.h" +#include "filenamestring.h" #include "versioninfo.h" -#include <appconfig.h> #include <iplugingame.h> +#include <versioninfo.h> +#include <appconfig.h> #include <scriptextender.h> #include <unmanagedmods.h> -#include <versioninfo.h> #include <QApplication> #include <QDirIterator> @@ -45,317 +45,353 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. using namespace MOBase; using namespace MOShared; + std::vector<ModInfo::Ptr> ModInfo::s_Collection; std::map<QString, unsigned int> ModInfo::s_ModsByName; -std::map<int, std::vector<unsigned int>> ModInfo::s_ModsByModID; +std::map<int, std::vector<unsigned int> > ModInfo::s_ModsByModID; int ModInfo::s_NextID; QMutex ModInfo::s_Mutex(QMutex::Recursive); QString ModInfo::s_HiddenExt(".mohidden"); -static bool ByName(const ModInfo::Ptr& LHS, const ModInfo::Ptr& RHS) { - return QString::compare(LHS->name(), RHS->name(), Qt::CaseInsensitive) < 0; + +static bool ByName(const ModInfo::Ptr &LHS, const ModInfo::Ptr &RHS) +{ + return QString::compare(LHS->name(), RHS->name(), Qt::CaseInsensitive) < 0; } -ModInfo::Ptr ModInfo::createFrom(const QDir& dir, DirectoryEntry** directoryStructure) { - QMutexLocker locker(&s_Mutex); - // int id = s_NextID++; - static QRegExp backupExp(".*backup[0-9]*"); - ModInfo::Ptr result; - if (backupExp.exactMatch(dir.dirName())) { - result = ModInfo::Ptr(new ModInfoBackup(dir, directoryStructure)); - } else { - result = ModInfo::Ptr(new ModInfoRegular(dir, directoryStructure)); - } - s_Collection.push_back(result); - return result; + +ModInfo::Ptr ModInfo::createFrom(const QDir &dir, DirectoryEntry **directoryStructure) +{ + QMutexLocker locker(&s_Mutex); +// int id = s_NextID++; + static QRegExp backupExp(".*backup[0-9]*"); + ModInfo::Ptr result; + if (backupExp.exactMatch(dir.dirName())) { + result = ModInfo::Ptr(new ModInfoBackup(dir, directoryStructure)); + } else { + result = ModInfo::Ptr(new ModInfoRegular(dir, directoryStructure)); + } + s_Collection.push_back(result); + return result; } -ModInfo::Ptr ModInfo::createFromPlugin(const QString& modName, const QString& espName, const QStringList& bsaNames, - ModInfo::EModType modType, DirectoryEntry** directoryStructure) { - QMutexLocker locker(&s_Mutex); - ModInfo::Ptr result = ModInfo::Ptr(new ModInfoForeign(modName, espName, bsaNames, modType, directoryStructure)); - s_Collection.push_back(result); - return result; +ModInfo::Ptr ModInfo::createFromPlugin(const QString &modName, + const QString &espName, + const QStringList &bsaNames, + ModInfo::EModType modType, + DirectoryEntry **directoryStructure) { + QMutexLocker locker(&s_Mutex); + ModInfo::Ptr result = ModInfo::Ptr( + new ModInfoForeign(modName, espName, bsaNames, modType, directoryStructure)); + s_Collection.push_back(result); + return result; } -QString ModInfo::getContentTypeName(int contentType) { - switch (contentType) { - case CONTENT_PLUGIN: - return tr("Plugins"); - case CONTENT_TEXTURE: - return tr("Textures"); - case CONTENT_MESH: - return tr("Meshes"); - case CONTENT_BSA: - return tr("Bethesda Archive"); - case CONTENT_INTERFACE: - return tr("UI Changes"); - case CONTENT_SOUND: - return tr("Sound Effects"); - case CONTENT_SCRIPT: - return tr("Scripts"); - case CONTENT_SKSE: - return tr("SKSE Plugins"); - case CONTENT_SKYPROC: - return tr("SkyProc Tools"); - case CONTENT_MCM: - return tr("MCM Data"); - default: - throw MyException(tr("invalid content type %1").arg(contentType)); - } +QString ModInfo::getContentTypeName(int contentType) +{ + switch (contentType) { + case CONTENT_PLUGIN: return tr("Plugins"); + case CONTENT_TEXTURE: return tr("Textures"); + case CONTENT_MESH: return tr("Meshes"); + case CONTENT_BSA: return tr("Bethesda Archive"); + case CONTENT_INTERFACE: return tr("UI Changes"); + case CONTENT_SOUND: return tr("Sound Effects"); + case CONTENT_SCRIPT: return tr("Scripts"); + case CONTENT_SKSE: return tr("SKSE Plugins"); + case CONTENT_SKYPROC: return tr("SkyProc Tools"); + case CONTENT_MCM: return tr("MCM Data"); + default: throw MyException(tr("invalid content type %1").arg(contentType)); + } } -void ModInfo::createFromOverwrite() { - QMutexLocker locker(&s_Mutex); +void ModInfo::createFromOverwrite() +{ + QMutexLocker locker(&s_Mutex); - s_Collection.push_back(ModInfo::Ptr(new ModInfoOverwrite)); + s_Collection.push_back(ModInfo::Ptr(new ModInfoOverwrite)); } -unsigned int ModInfo::getNumMods() { - QMutexLocker locker(&s_Mutex); - return static_cast<unsigned int>(s_Collection.size()); +unsigned int ModInfo::getNumMods() +{ + QMutexLocker locker(&s_Mutex); + return static_cast<unsigned int>(s_Collection.size()); } -ModInfo::Ptr ModInfo::getByIndex(unsigned int index) { - QMutexLocker locker(&s_Mutex); - if (index >= s_Collection.size() && index != ULONG_MAX) { - throw MyException(tr("invalid mod index %1").arg(index)); - } - if (index == ULONG_MAX) - return s_Collection[ModInfo::getIndex("Overwrite")]; - return s_Collection[index]; +ModInfo::Ptr ModInfo::getByIndex(unsigned int index) +{ + QMutexLocker locker(&s_Mutex); + + if (index >= s_Collection.size() && index != ULONG_MAX) { + throw MyException(tr("invalid mod index %1").arg(index)); + } + if (index == ULONG_MAX) return s_Collection[ModInfo::getIndex("Overwrite")]; + return s_Collection[index]; } -std::vector<ModInfo::Ptr> ModInfo::getByModID(int modID) { - QMutexLocker locker(&s_Mutex); - auto iter = s_ModsByModID.find(modID); - if (iter == s_ModsByModID.end()) { - return std::vector<ModInfo::Ptr>(); - } +std::vector<ModInfo::Ptr> ModInfo::getByModID(int modID) +{ + QMutexLocker locker(&s_Mutex); - std::vector<ModInfo::Ptr> result; - for (auto idxIter = iter->second.begin(); idxIter != iter->second.end(); ++idxIter) { - result.push_back(getByIndex(*idxIter)); - } + auto iter = s_ModsByModID.find(modID); + if (iter == s_ModsByModID.end()) { + return std::vector<ModInfo::Ptr>(); + } + + std::vector<ModInfo::Ptr> result; + for (auto idxIter = iter->second.begin(); idxIter != iter->second.end(); ++idxIter) { + result.push_back(getByIndex(*idxIter)); + } - return result; + return result; } -bool ModInfo::removeMod(unsigned int index) { - QMutexLocker locker(&s_Mutex); - if (index >= s_Collection.size()) { - throw MyException(tr("remove: invalid mod index %1").arg(index)); - } - // update the indices first - ModInfo::Ptr modInfo = s_Collection[index]; - s_ModsByName.erase(s_ModsByName.find(modInfo->name())); +bool ModInfo::removeMod(unsigned int index) +{ + QMutexLocker locker(&s_Mutex); - auto iter = s_ModsByModID.find(modInfo->getNexusID()); - if (iter != s_ModsByModID.end()) { - std::vector<unsigned int> indices = iter->second; - indices.erase(std::remove(indices.begin(), indices.end(), index), indices.end()); - s_ModsByModID[modInfo->getNexusID()] = indices; - } + if (index >= s_Collection.size()) { + throw MyException(tr("remove: invalid mod index %1").arg(index)); + } + // update the indices first + ModInfo::Ptr modInfo = s_Collection[index]; + s_ModsByName.erase(s_ModsByName.find(modInfo->name())); + + auto iter = s_ModsByModID.find(modInfo->getNexusID()); + if (iter != s_ModsByModID.end()) { + std::vector<unsigned int> indices = iter->second; + indices.erase(std::remove(indices.begin(), indices.end(), index), indices.end()); + s_ModsByModID[modInfo->getNexusID()] = indices; + } - // physically remove the mod directory - // TODO the return value is ignored because the indices were already removed here, so stopping - // would cause data inconsistencies. Instead we go through with the removal but the mod will show up - // again if the user refreshes - modInfo->remove(); + // physically remove the mod directory + //TODO the return value is ignored because the indices were already removed here, so stopping + // would cause data inconsistencies. Instead we go through with the removal but the mod will show up + // again if the user refreshes + modInfo->remove(); - // finally, remove the mod from the collection - s_Collection.erase(s_Collection.begin() + index); + // finally, remove the mod from the collection + s_Collection.erase(s_Collection.begin() + index); - // and update the indices - updateIndices(); - return true; + // and update the indices + updateIndices(); + return true; } -unsigned int ModInfo::getIndex(const QString& name) { - QMutexLocker locker(&s_Mutex); - std::map<QString, unsigned int>::iterator iter = s_ModsByName.find(name); - if (iter == s_ModsByName.end()) { - return UINT_MAX; - } +unsigned int ModInfo::getIndex(const QString &name) +{ + QMutexLocker locker(&s_Mutex); + + std::map<QString, unsigned int>::iterator iter = s_ModsByName.find(name); + if (iter == s_ModsByName.end()) { + return UINT_MAX; + } - return iter->second; + return iter->second; } -unsigned int ModInfo::findMod(const boost::function<bool(ModInfo::Ptr)>& filter) { - for (unsigned int i = 0U; i < s_Collection.size(); ++i) { - if (filter(s_Collection[i])) { - return i; - } +unsigned int ModInfo::findMod(const boost::function<bool (ModInfo::Ptr)> &filter) +{ + for (unsigned int i = 0U; i < s_Collection.size(); ++i) { + if (filter(s_Collection[i])) { + return i; } - return UINT_MAX; + } + return UINT_MAX; } -void ModInfo::updateFromDisc(const QString& modDirectory, DirectoryEntry** directoryStructure, bool displayForeign, - MOBase::IPluginGame const* game) { - QMutexLocker lock(&s_Mutex); - s_Collection.clear(); - s_NextID = 0; - { // list all directories in the mod directory and make a mod out of each - QDir mods(QDir::fromNativeSeparators(modDirectory)); - mods.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); - QDirIterator modIter(mods); - while (modIter.hasNext()) { - createFrom(QDir(modIter.next()), directoryStructure); - } +void ModInfo::updateFromDisc(const QString &modDirectory, + DirectoryEntry **directoryStructure, + bool displayForeign, + MOBase::IPluginGame const *game) +{ + QMutexLocker lock(&s_Mutex); + s_Collection.clear(); + s_NextID = 0; + + { // list all directories in the mod directory and make a mod out of each + QDir mods(QDir::fromNativeSeparators(modDirectory)); + mods.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); + QDirIterator modIter(mods); + while (modIter.hasNext()) { + createFrom(QDir(modIter.next()), directoryStructure); } + } - UnmanagedMods* unmanaged = game->feature<UnmanagedMods>(); - if (unmanaged != nullptr) { - for (const QString& modName : unmanaged->mods(!displayForeign)) { - ModInfo::EModType modType = - game->DLCPlugins().contains(unmanaged->referenceFile(modName).fileName(), Qt::CaseInsensitive) - ? ModInfo::EModType::MOD_DLC - : (game->CCPlugins().contains(unmanaged->referenceFile(modName).fileName(), Qt::CaseInsensitive) - ? ModInfo::EModType::MOD_CC - : ModInfo::EModType::MOD_DEFAULT); + UnmanagedMods *unmanaged = game->feature<UnmanagedMods>(); + if (unmanaged != nullptr) { + for (const QString &modName : unmanaged->mods(!displayForeign)) { + ModInfo::EModType modType = game->DLCPlugins().contains(unmanaged->referenceFile(modName).fileName(), Qt::CaseInsensitive) ? ModInfo::EModType::MOD_DLC : + (game->CCPlugins().contains(unmanaged->referenceFile(modName).fileName(), Qt::CaseInsensitive) ? ModInfo::EModType::MOD_CC : ModInfo::EModType::MOD_DEFAULT); - createFromPlugin(unmanaged->displayName(modName), unmanaged->referenceFile(modName).absoluteFilePath(), - unmanaged->secondaryFiles(modName), modType, directoryStructure); - } + createFromPlugin(unmanaged->displayName(modName), + unmanaged->referenceFile(modName).absoluteFilePath(), + unmanaged->secondaryFiles(modName), + modType, + directoryStructure); } + } - createFromOverwrite(); + createFromOverwrite(); - std::sort(s_Collection.begin(), s_Collection.end(), ByName); + std::sort(s_Collection.begin(), s_Collection.end(), ByName); - updateIndices(); + updateIndices(); } -void ModInfo::updateIndices() { - s_ModsByName.clear(); - s_ModsByModID.clear(); - for (unsigned int i = 0; i < s_Collection.size(); ++i) { - QString modName = s_Collection[i]->internalName(); - int modID = s_Collection[i]->getNexusID(); - s_ModsByName[modName] = i; - s_ModsByModID[modID].push_back(i); - } +void ModInfo::updateIndices() +{ + s_ModsByName.clear(); + s_ModsByModID.clear(); + + for (unsigned int i = 0; i < s_Collection.size(); ++i) { + QString modName = s_Collection[i]->internalName(); + int modID = s_Collection[i]->getNexusID(); + s_ModsByName[modName] = i; + s_ModsByModID[modID].push_back(i); + } } -ModInfo::ModInfo() : m_Valid(false), m_PrimaryCategory(-1) {} -void ModInfo::checkChunkForUpdate(const std::vector<int>& modIDs, QObject* receiver) { - if (modIDs.size() != 0) { - NexusInterface::instance()->requestUpdates(modIDs, receiver, QVariant(), QString()); - } +ModInfo::ModInfo() + : m_Valid(false), m_PrimaryCategory(-1) +{ +} + + +void ModInfo::checkChunkForUpdate(const std::vector<int> &modIDs, QObject *receiver) +{ + if (modIDs.size() != 0) { + NexusInterface::instance()->requestUpdates(modIDs, receiver, QVariant(), QString()); + } } -int ModInfo::checkAllForUpdate(QObject* receiver) { - // technically this should be 255 but those requests can take nexus fairly long, produce - // large output and may have been the cause of issue #1166 - static const int chunkSize = 64; - int result = 0; - std::vector<int> modIDs; +int ModInfo::checkAllForUpdate(QObject *receiver) +{ + // technically this should be 255 but those requests can take nexus fairly long, produce + // large output and may have been the cause of issue #1166 + static const int chunkSize = 64; + + int result = 0; + std::vector<int> modIDs; - // I ought to store this, it's used elsewhere - IPluginGame const* game = qApp->property("managed_game").value<IPluginGame*>(); + //I ought to store this, it's used elsewhere + IPluginGame const *game = qApp->property("managed_game").value<IPluginGame *>(); - modIDs.push_back(game->nexusModOrganizerID()); + modIDs.push_back(game->nexusModOrganizerID()); - for (const ModInfo::Ptr& mod : s_Collection) { - if (mod->canBeUpdated()) { - modIDs.push_back(mod->getNexusID()); - if (modIDs.size() >= chunkSize) { - checkChunkForUpdate(modIDs, receiver); - modIDs.clear(); - } - } + for (const ModInfo::Ptr &mod : s_Collection) { + if (mod->canBeUpdated()) { + modIDs.push_back(mod->getNexusID()); + if (modIDs.size() >= chunkSize) { + checkChunkForUpdate(modIDs, receiver); + modIDs.clear(); + } } + } - checkChunkForUpdate(modIDs, receiver); + checkChunkForUpdate(modIDs, receiver); - return result; + return result; } -void ModInfo::setVersion(const VersionInfo& version) { m_Version = version; } +void ModInfo::setVersion(const VersionInfo &version) +{ + m_Version = version; +} -void ModInfo::setPluginSelected(const bool& isSelected) { m_PluginSelected = isSelected; } +void ModInfo::setPluginSelected(const bool &isSelected) +{ + m_PluginSelected = isSelected; +} -void ModInfo::addCategory(const QString& categoryName) { - int id = CategoryFactory::instance().getCategoryID(categoryName); - if (id == -1) { - id = CategoryFactory::instance().addCategory(categoryName, std::vector<int>(), 0); - } - setCategory(id, true); +void ModInfo::addCategory(const QString &categoryName) +{ + int id = CategoryFactory::instance().getCategoryID(categoryName); + if (id == -1) { + id = CategoryFactory::instance().addCategory(categoryName, std::vector<int>(), 0); + } + setCategory(id, true); } -bool ModInfo::removeCategory(const QString& categoryName) { - int id = CategoryFactory::instance().getCategoryID(categoryName); - if (id == -1) { - return false; - } - if (!categorySet(id)) { - return false; - } - setCategory(id, false); - return true; +bool ModInfo::removeCategory(const QString &categoryName) +{ + int id = CategoryFactory::instance().getCategoryID(categoryName); + if (id == -1) { + return false; + } + if (!categorySet(id)) { + return false; + } + setCategory(id, false); + return true; } -QStringList ModInfo::categories() { - QStringList result; +QStringList ModInfo::categories() +{ + QStringList result; - CategoryFactory& catFac = CategoryFactory::instance(); - for (int id : m_Categories) { - result.append(catFac.getCategoryName(catFac.getCategoryIndex(id))); - } + CategoryFactory &catFac = CategoryFactory::instance(); + for (int id : m_Categories) { + result.append(catFac.getCategoryName(catFac.getCategoryIndex(id))); + } - return result; + return result; } -bool ModInfo::hasFlag(ModInfo::EFlag flag) const { - std::vector<EFlag> flags = getFlags(); - return std::find(flags.begin(), flags.end(), flag) != flags.end(); +bool ModInfo::hasFlag(ModInfo::EFlag flag) const +{ + std::vector<EFlag> flags = getFlags(); + return std::find(flags.begin(), flags.end(), flag) != flags.end(); } -bool ModInfo::hasContent(ModInfo::EContent content) const { - std::vector<EContent> contents = getContents(); - return std::find(contents.begin(), contents.end(), content) != contents.end(); +bool ModInfo::hasContent(ModInfo::EContent content) const +{ + std::vector<EContent> contents = getContents(); + return std::find(contents.begin(), contents.end(), content) != contents.end(); } -bool ModInfo::categorySet(int categoryID) const { - for (std::set<int>::const_iterator iter = m_Categories.begin(); iter != m_Categories.end(); ++iter) { - if ((*iter == categoryID) || (CategoryFactory::instance().isDecendantOf(*iter, categoryID))) { - return true; - } +bool ModInfo::categorySet(int categoryID) const +{ + for (std::set<int>::const_iterator iter = m_Categories.begin(); iter != m_Categories.end(); ++iter) { + if ((*iter == categoryID) || + (CategoryFactory::instance().isDecendantOf(*iter, categoryID))) { + return true; } + } - return false; + return false; } -void ModInfo::testValid() { - m_Valid = false; - QDirIterator dirIter(absolutePath()); - while (dirIter.hasNext()) { - dirIter.next(); - if (dirIter.fileInfo().isDir()) { - if (InstallationTester::isTopLevelDirectory(dirIter.fileName())) { - m_Valid = true; - break; - } - } else { - if (InstallationTester::isTopLevelSuffix(dirIter.fileName())) { - m_Valid = true; - break; - } - } +void ModInfo::testValid() +{ + m_Valid = false; + QDirIterator dirIter(absolutePath()); + while (dirIter.hasNext()) { + dirIter.next(); + if (dirIter.fileInfo().isDir()) { + if (InstallationTester::isTopLevelDirectory(dirIter.fileName())) { + m_Valid = true; + break; + } + } else { + if (InstallationTester::isTopLevelSuffix(dirIter.fileName())) { + m_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(); - } + // 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(); + } } |
