summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAl <26797547+Al12rs@users.noreply.github.com>2020-05-20 13:05:02 +0200
committerGitHub <noreply@github.com>2020-05-20 13:05:02 +0200
commitb7110cba2dceb172bf6a903f1c5de5ff1c460f11 (patch)
treeee3be3be522842c6ef42c14d48c822fa657333c9 /src
parentc214b67ae784537d696a53c8cae00676eefd3841 (diff)
parentc391c2b584a309f64f87dd5e00b0083279e6211c (diff)
Merge pull request #1066 from Holt59/new-filetree
Update for the new file tree implementation and minor fixes
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/archivefiletree.cpp279
-rw-r--r--src/archivefiletree.h72
-rw-r--r--src/directoryrefresher.cpp13
-rw-r--r--src/installationmanager.cpp326
-rw-r--r--src/installationmanager.h93
-rw-r--r--src/modinfo.cpp27
-rw-r--r--src/modinfo.h53
-rw-r--r--src/modinfobackup.h53
-rw-r--r--src/modinfodialognexus.cpp2
-rw-r--r--src/modinfoforeign.h110
-rw-r--r--src/modinfooverwrite.h104
-rw-r--r--src/modinforegular.cpp5
-rw-r--r--src/modinforegular.h132
-rw-r--r--src/modinfoseparator.h86
-rw-r--r--src/modinfowithconflictinfo.cpp31
-rw-r--r--src/modinfowithconflictinfo.h29
-rw-r--r--src/pluginlist.cpp17
18 files changed, 818 insertions, 615 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6e454fc1..99d31541 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -26,6 +26,7 @@ add_filter(NAME src/browser GROUPS
add_filter(NAME src/core GROUPS
categories
+ archivefiletree
installationmanager
instancemanager
loadmechanism
diff --git a/src/archivefiletree.cpp b/src/archivefiletree.cpp
new file mode 100644
index 00000000..0b715f4f
--- /dev/null
+++ b/src/archivefiletree.cpp
@@ -0,0 +1,279 @@
+/*
+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 <http://www.gnu.org/licenses/>.
+*/
+
+// For QObject::tr:
+#include <QObject>
+
+#include "archivefiletree.h"
+
+#include "log.h"
+
+using namespace MOBase;
+
+/**
+ * We use custom file entries to store the index.
+ */
+class ArchiveFileEntry : public virtual FileTreeEntry {
+public:
+
+ /**
+ * @brief Create a new entry corresponding to a file.
+ *
+ * @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<const IFileTree> 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.
+ */
+ ArchiveFileEntry(std::shared_ptr<const IFileTree> parent, QString name, int index) :
+ FileTreeEntry(parent, name), m_Index(index) {
+ }
+
+ virtual std::shared_ptr<FileTreeEntry> clone() const override {
+ return std::make_shared<ArchiveFileEntry>(nullptr, name(), m_Index);
+ }
+
+ // No private since we are in an implementation file:
+ const int m_Index;
+};
+
+
+/**
+ *
+ */
+class ArchiveFileTreeImpl: public virtual ArchiveFileTree, public virtual ArchiveFileEntry {
+public:
+
+ using File = std::tuple<QStringList, bool, int>;
+
+public: // Public for make_shared (but not accessible by other since not exposed in .h):
+
+ ArchiveFileTreeImpl(std::shared_ptr<const IFileTree> parent, QString name, int index, std::vector<File> files)
+ : FileTreeEntry(parent, name), ArchiveFileEntry(parent, name, index), IFileTree(), m_Files(std::move(files)) { }
+
+public: // Override to avoid VS warnings:
+
+ virtual std::shared_ptr<IFileTree> astree() override {
+ return IFileTree::astree();
+ }
+
+ virtual std::shared_ptr<const IFileTree> astree() const override {
+ return IFileTree::astree();
+ }
+
+protected:
+
+ virtual std::shared_ptr<FileTreeEntry> clone() const override {
+ return IFileTree::clone();
+ }
+
+public: // Overrides:
+
+ /**
+ * @override
+ */
+ std::shared_ptr<FileTreeEntry> addFile(QString path, QDateTime time = QDateTime()) override {
+ // Cannot add file to an archive.
+ throw UnsupportedOperationException(QObject::tr("Cannot create file within an archive."));
+ }
+
+ /**
+ *
+ */
+ static void mapToArchive(IFileTree const& tree, QString path, FileData* const* data)
+ {
+ if (path.length() > 0) {
+ // when using a long windows path (starting with \\?\) we apparently can have redundant
+ // . components in the path. This wasn't a problem with "regular" path names.
+ if (path == ".") {
+ path.clear();
+ }
+ else {
+ path.append("\\");
+ }
+ }
+
+ for (auto const& entry : tree) {
+ if (entry->isDir()) {
+ const ArchiveFileTreeImpl& archiveEntry = dynamic_cast<const ArchiveFileTreeImpl&>(*entry);
+ QString tmp = path + archiveEntry.name();
+ if (archiveEntry.m_Index != -1) {
+ data[archiveEntry.m_Index]->addOutputFileName(tmp);
+ }
+ mapToArchive(*archiveEntry.astree(), tmp, data);
+ }
+ else {
+ const ArchiveFileEntry& archiveFileEntry = dynamic_cast<const ArchiveFileEntry&>(*entry);
+ data[archiveFileEntry.m_Index]->addOutputFileName(path + archiveFileEntry.name());
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ void mapToArchive(Archive* archive) const override {
+ FileData* const* data;
+ size_t size;
+ archive->getFileList(data, size);
+ mapToArchive(*this, "", data);
+ }
+
+protected:
+
+ /*
+ * Overriding this to create custom FileTreeEntry with index set to -1. No need to
+ * override makeFile() since we addFile is overriden. Note that this will not be
+ * used to create existing tree since we do this manually in doPopulate.
+ *
+ * @override
+ */
+ virtual std::shared_ptr<IFileTree> makeDirectory(
+ std::shared_ptr<const IFileTree> parent, QString name) const override {
+ return std::make_shared<ArchiveFileTreeImpl>(parent, name, -1, std::vector<File>{});
+ }
+
+ virtual void doPopulate(std::shared_ptr<const IFileTree> parent, std::vector<std::shared_ptr<FileTreeEntry>>& entries) const override {
+
+ // Sort by name:
+ std::sort(std::begin(m_Files), std::end(m_Files),
+ [](const auto& a, const auto& b) {
+ return std::get<0>(a)[0].compare(std::get<0>(b)[0], Qt::CaseInsensitive) < 0; });
+
+ // We know that the files are sorted:
+ QString currentName = "";
+ int currentIndex = -1;
+ std::vector<File> currentFiles;
+ for (auto& p : m_Files) {
+
+ // At the start or if we have reset, just retrieve the current name:
+ if (currentName == "") {
+ currentName = std::get<0>(p)[0];
+ }
+
+ // If the name is different, we need to create a directory from what we have
+ // accumulated:
+ if (currentName != std::get<0>(p)[0]) {
+
+ // We may or may not have an index here, it depends on the type of archive (some archives list
+ // intermediate non-empty folders, some don't):
+ entries.push_back(std::make_shared<ArchiveFileTreeImpl>(parent, currentName, currentIndex, std::move(currentFiles)));
+
+ currentFiles.clear(); // Back to a valid state.
+
+ // Reset the index:
+ currentIndex = -1;
+ }
+
+ // We can always override the current name:
+ currentName = std::get<0>(p)[0];
+
+ // If the current path contains only one components:
+ if (std::get<0>(p).size() == 1) {
+
+ // 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<ArchiveFileEntry>(parent, currentName, std::get<2>(p), QDateTime()));
+ currentName = "";
+ }
+ else {
+ // Otherwize, it is the actual "file" corresponding to the directory we are listing, so we can retrieve
+ // the index here:
+ currentIndex = std::get<2>(p);
+ }
+ }
+ else {
+ currentFiles.push_back({
+ QStringList(std::get<0>(p).begin() + 1, std::get<0>(p).end()), std::get<1>(p), std::get<2>(p)
+ });
+ }
+ }
+
+ if (currentName != "") {
+ entries.push_back(std::make_shared<ArchiveFileTreeImpl>(parent, currentName, currentIndex, std::move(currentFiles)));
+ }
+ }
+
+ virtual std::shared_ptr<IFileTree> doClone() const override {
+ return std::make_shared<ArchiveFileTreeImpl>(nullptr, name(), m_Index, m_Files);
+ }
+
+private:
+
+ mutable std::vector<File> m_Files;
+};
+
+std::shared_ptr<ArchiveFileTree> ArchiveFileTree::makeTree(Archive* archive) {
+
+ FileData* const* data;
+ size_t size;
+ archive->getFileList(data, size);
+
+ std::vector<ArchiveFileTreeImpl::File> files;
+ files.reserve(size);
+
+ for (size_t i = 0; i < size; ++i) {
+ files.push_back(std::make_tuple(data[i]->getFileName().replace("\\", "/").split("/", Qt::SkipEmptyParts), data[i]->isDirectory(), (int) i));
+ }
+
+ auto tree = std::make_shared<ArchiveFileTreeImpl>(nullptr, "", -1, std::move(files));
+ return tree;
+}
+
+/**
+ * @brief Recursive function for the ArchiveFileTree::mapToArchive method. Need a template
+ * here because iterators from a vector of entries are not exactly the same as the iterators
+ * returned by a IFileTree.
+ *
+ */
+template <class It>
+void mapToArchive(FileData* const* data, It begin, It end) {
+ for (auto it = begin; it != end; ++it) {
+ auto entry = *it;
+ auto* aentry = dynamic_cast<const ArchiveFileEntry*>(entry.get());
+
+ if (aentry->m_Index != -1) {
+ data[aentry->m_Index]->addOutputFileName(aentry->path());
+ }
+
+ if (entry->isDir()) {
+ auto tree = entry->astree();
+ mapToArchive(data, tree->begin(), tree->end());
+ }
+ }
+}
+
+void ArchiveFileTree::mapToArchive(Archive* archive, std::vector<std::shared_ptr<const FileTreeEntry>> const& entries) {
+ FileData* const* data;
+ size_t size;
+ archive->getFileList(data, size);
+
+ ::mapToArchive(data, entries.cbegin(), entries.cend());
+}
diff --git a/src/archivefiletree.h b/src/archivefiletree.h
new file mode 100644
index 00000000..0041acd6
--- /dev/null
+++ b/src/archivefiletree.h
@@ -0,0 +1,72 @@
+/*
+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 <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef ARCHIVEFILENETRY_H
+#define ARCHIVEFILENTRY_H
+
+#include "archive.h"
+#include "ifiletree.h"
+
+
+/**
+ *
+ */
+class ArchiveFileTree: public virtual MOBase::IFileTree {
+public:
+
+ /**
+ * @brief Create a new file tree representing the given archive.
+ *
+ * @param archive Archive to represent by the file tree.
+ *
+ * @return a file tree representing the given archive.
+ */
+ static std::shared_ptr<ArchiveFileTree> makeTree(Archive* archive);
+
+ /**
+ * @brief Update the given archive to reflect change in this tree.
+ *
+ * This method disables files that have been removed from the file
+ * tree and move the ones that have been moved.
+ *
+ * @param archive The archive to update. Must be the one used to
+ * create the tree.
+ */
+ virtual void mapToArchive(Archive *archive) const = 0;
+
+ /**
+ * @brief Update the given archive to prepare for the extraction
+ * of the given entries.
+ *
+ * This method "enables" files that correspond to the given entry.
+ *
+ * @param archive The archive to update. Must be the one used to
+ * create the tree.
+ * @param entries List of entries to mark for extraction. All the entries must
+ * come from a tree created with the given archive.
+ */
+ static void mapToArchive(Archive* archive, std::vector<std::shared_ptr<const FileTreeEntry>> const& entries);
+
+protected:
+
+ using IFileTree::IFileTree;
+
+};
+
+#endif
diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp
index 0369b1b0..383e6b33 100644
--- a/src/directoryrefresher.cpp
+++ b/src/directoryrefresher.cpp
@@ -216,9 +216,12 @@ void DirectoryRefresher::addModBSAToStructure(
{
const IPluginGame *game = qApp->property("managed_game").value<IPluginGame*>();
- GamePlugins *gamePlugins = game->feature<GamePlugins>();
QStringList loadOrder = QStringList();
- gamePlugins->getLoadOrder(loadOrder);
+
+ GamePlugins* gamePlugins = game->feature<GamePlugins>();
+ if (gamePlugins) {
+ gamePlugins->getLoadOrder(loadOrder);
+ }
std::vector<std::wstring> lo;
for (auto&& s : loadOrder) {
@@ -364,9 +367,11 @@ struct ModThread
if (Settings::instance().archiveParsing()) {
const IPluginGame *game = qApp->property("managed_game").value<IPluginGame*>();
- GamePlugins *gamePlugins = game->feature<GamePlugins>();
QStringList loadOrder = QStringList();
- gamePlugins->getLoadOrder(loadOrder);
+ GamePlugins* gamePlugins = game->feature<GamePlugins>();
+ if (gamePlugins) {
+ gamePlugins->getLoadOrder(loadOrder);
+ }
std::vector<std::wstring> lo;
for (auto&& s : loadOrder) {
diff --git a/src/installationmanager.cpp b/src/installationmanager.cpp
index d62067c2..d4e6a444 100644
--- a/src/installationmanager.cpp
+++ b/src/installationmanager.cpp
@@ -17,6 +17,8 @@ You should have received a copy of the GNU General Public License
along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <tuple>
+
#include "installationmanager.h"
#include "utility.h"
@@ -56,6 +58,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include <boost/assign.hpp>
#include <boost/scoped_ptr.hpp>
+#include "archivefiletree.h"
+
using namespace MOBase;
using namespace MOShared;
@@ -121,172 +125,18 @@ void InstallationManager::queryPassword(QString *password)
tr("Password"), QLineEdit::Password);
}
-void InstallationManager::mapToArchive(const DirectoryTree::Node *node, QString path, FileData * const *data)
-{
- if (path.length() > 0) {
- // when using a long windows path (starting with \\?\) we apparently can have redundant
- // . components in the path. This wasn't a problem with "regular" path names.
- if (path == ".") {
- path.clear();
- } else {
- path.append("\\");
- }
- }
-
- for (DirectoryTree::const_leaf_iterator iter = node->leafsBegin(); iter != node->leafsEnd(); ++iter) {
- data[iter->getIndex()]->addOutputFileName(path + iter->getName().toQString());
- }
-
- for (DirectoryTree::const_node_iterator iter = node->nodesBegin(); iter != node->nodesEnd(); ++iter) {
- QString temp = path + (*iter)->getData().name.toQString();
- if ((*iter)->getData().index != -1) {
- data[(*iter)->getData().index]->addOutputFileName(temp);
- }
- mapToArchive(*iter, temp, data);
- }
-}
-
-
-void InstallationManager::mapToArchive(const DirectoryTree::Node *baseNode)
-{
- FileData* const *data;
- size_t size;
- m_ArchiveHandler->getFileList(data, size);
-
- mapToArchive(baseNode, "", data);
-}
-
-bool InstallationManager::unpackSingleFile(const QString &fileName)
+bool InstallationManager::extractFiles(QDir extractPath)
{
- FileData* const *data;
- size_t size;
- m_ArchiveHandler->getFileList(data, size);
-
- QString baseName = QFileInfo(fileName).fileName();
-
- bool available = false;
- for (size_t i = 0; i < size; ++i) {
- if (data[i]->getFileName().compare(fileName, Qt::CaseInsensitive) == 0) {
- available = true;
- data[i]->addOutputFileName(baseName);
- m_TempFilesToDelete.insert(baseName);
- }
- }
-
- if (!available) {
- return false;
- }
-
m_InstallationProgress = new QProgressDialog(m_ParentWidget);
- ON_BLOCK_EXIT([this] () {
+ ON_BLOCK_EXIT([this]() {
m_InstallationProgress->hide();
m_InstallationProgress->deleteLater();
m_InstallationProgress = nullptr;
m_Progress = 0;
- });
+ });
m_InstallationProgress->setWindowFlags(
- m_InstallationProgress->windowFlags() & ~Qt::WindowContextHelpButtonHint);
-
- m_InstallationProgress->setWindowTitle(tr("Extracting files"));
- m_InstallationProgress->setWindowModality(Qt::WindowModal);
- m_InstallationProgress->setFixedSize(600, 100);
- m_InstallationProgress->show();
-
- QFuture<bool> future = QtConcurrent::run([&]() -> bool {
- return m_ArchiveHandler->extract(
- QDir::tempPath(),
- new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
- nullptr,
- new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::report7ZipError)
- );
- });
- do {
- if (m_Progress != m_InstallationProgress->value())
- m_InstallationProgress->setValue(m_Progress);
- QCoreApplication::processEvents();
- } while (!future.isFinished() || m_InstallationProgress->isVisible());
- bool res = future.result();
-
- return res;
-}
-
-
-QString InstallationManager::extractFile(const QString &fileName)
-{
- if (unpackSingleFile(fileName)) {
- return QDir::tempPath() + "/" + QFileInfo(fileName).fileName();
- } else {
- return QString();
- }
-}
-
-
-static QString canonicalize(const QString &name)
-{
- QString result(name);
- if ((result.startsWith('/')) ||
- (result.startsWith('\\'))) {
- result.remove(0, 1);
- }
- result.replace('/', '\\');
-
- return result;
-}
-
-
-QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool flatten)
-{
- QStringList files;
-
- for (const QString &file : filesOrig) {
- files.append(canonicalize(file));
- }
-
- QStringList result;
-
- FileData* const *data;
- size_t size;
- m_ArchiveHandler->getFileList(data, size);
-
- for (size_t i = 0; i < size; ++i) {
- //FIXME Use qstring all the way through
- if (files.contains(data[i]->getFileName(), Qt::CaseInsensitive)) {
- std::wstring temp = data[i]->getFileName().toStdWString();
- wchar_t const * const origFile = temp.c_str();
- const wchar_t *targetFile = origFile;
- //Note: I don't think 'flatten' is ever set to true. so this code
- //might never be executed
- if (flatten) {
- targetFile = wcsrchr(origFile/*data[i]->getFileName()*/, '\\');
- if (targetFile == nullptr) {
- targetFile = wcsrchr(origFile/*data[i]->getFileName()*/, '/');
- }
- if (targetFile == nullptr) {
- log::error("Failed to find backslash in {}", data[i]->getFileName());
- continue;
- } else {
- // skip the slash
- ++targetFile;
- }
- }
- data[i]->addOutputFileName(ToQString(targetFile));
-
- result.append(QDir::tempPath().append("/").append(ToQString(targetFile)));
-
- m_TempFilesToDelete.insert(ToQString(targetFile));
- }
- }
-
- m_InstallationProgress = new QProgressDialog(m_ParentWidget);
- ON_BLOCK_EXIT([this] () {
- m_InstallationProgress->hide();
- m_InstallationProgress->deleteLater();
- m_InstallationProgress = nullptr;
- m_Progress = 0;
- });
- m_InstallationProgress->setWindowFlags(
- m_InstallationProgress->windowFlags() & (~Qt::WindowContextHelpButtonHint));
+ m_InstallationProgress->windowFlags() & (~Qt::WindowContextHelpButtonHint));
m_InstallationProgress->setWindowTitle(tr("Extracting files"));
m_InstallationProgress->setWindowModality(Qt::WindowModal);
m_InstallationProgress->setFixedSize(600, 100);
@@ -298,9 +148,9 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool
QDir::tempPath(),
new MethodCallback<InstallationManager, void, float>(this, &InstallationManager::updateProgress),
nullptr,
- new MethodCallback<InstallationManager, void, QString const &>(this, &InstallationManager::report7ZipError)
+ new MethodCallback<InstallationManager, void, QString const&>(this, &InstallationManager::report7ZipError)
);
- });
+ });
do {
if (m_Progress != m_InstallationProgress->value())
m_InstallationProgress->setValue(m_Progress);
@@ -310,8 +160,9 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool
if (m_ArchiveHandler->getLastError() == Archive::ERROR_EXTRACT_CANCELLED) {
if (!m_ErrorMessage.isEmpty()) {
throw MyException(tr("Extraction failed: %1").arg(m_ErrorMessage));
- } else {
- return QStringList();
+ }
+ else {
+ return false;
}
}
else {
@@ -319,122 +170,53 @@ QStringList InstallationManager::extractFiles(const QStringList &filesOrig, bool
}
}
- return result;
+ return true;
}
-IPluginInstaller::EInstallResult InstallationManager::installArchive(GuessedValue<QString> &modName, const QString &archiveName, const int &modId)
-{
- // in earlier versions the modName was copied here and the copy passed to install. I don't know why I did this and it causes
- // a problem if this is called by the bundle installer and the bundled installer adds additional names that then end up being used,
- // because the caller will then not have the right name.
- bool iniTweaks;
- return install(archiveName, modName, iniTweaks, modId);
-}
-DirectoryTree *InstallationManager::createFilesTree()
+QString InstallationManager::extractFile(std::shared_ptr<const FileTreeEntry> entry)
{
- FileData* const *data;
- size_t size;
- m_ArchiveHandler->getFileList(data, size);
+ QStringList result = this->extractFiles({ entry });
+ return result.isEmpty() ? QString() : result[0];
+}
- QScopedPointer<DirectoryTree> result(new DirectoryTree);
- for (size_t i = 0; i < size; ++i) {
- // the files are in a flat list where each file has a a full path relative to the archive root
- // to create a tree, we have to iterate over each path component of each. This could be sped up by
- // grouping the filenames first, but so far there doesn't seem to be an actual performance problem
- DirectoryTree::Node *currentNode = result.data();
+QStringList InstallationManager::extractFiles(std::vector<std::shared_ptr<const FileTreeEntry>> const& entries)
+{
+ // Remove the directory since mapToArchive would add them:
+ std::vector<std::shared_ptr<const FileTreeEntry>> files;
+ std::copy_if(entries.begin(), entries.end(), std::back_inserter(files),
+ [](auto const& entry) { return entry->isFile(); });
- QString fileName = data[i]->getFileName();
- QStringList components = fileName.split("\\");
+ // Update the archive:
+ ArchiveFileTree::mapToArchive(m_ArchiveHandler, files);
- // iterate over all path-components of this filename (including the filename itself)
- for (QStringList::iterator componentIter = components.begin(); componentIter != components.end(); ++componentIter) {
- if (componentIter->size() == 0) {
- // empty string indicates fileName is actually only a directory name and we have
- // completely processed it already.
- break;
- }
-
- bool exists = false;
- // test if this path is already in the tree
- for (DirectoryTree::node_iterator nodeIter = currentNode->nodesBegin(); nodeIter != currentNode->nodesEnd(); ++nodeIter) {
- if ((*nodeIter)->getData().name == *componentIter) {
- currentNode = *nodeIter;
- exists = true;
- break;
- }
- }
+ // Retrieve the file path:
+ QStringList result;
- if (!exists) {
- if (componentIter + 1 == components.end()) {
- // last path component. directory or file?
- if (data[i]->isDirectory()) {
- // this is a bit problematic. archives will often only list directories if they are empty,
- // otherwise the dir only appears in the path of a file. In the UI however we allow the user
- // to uncheck all files in a directory while keeping the dir checked. Those directories are
- // currently not installed.
- DirectoryTree::Node *newNode = new DirectoryTree::Node;
- newNode->setData(
- DirectoryTreeInformation(*componentIter, static_cast<int>(i)));
- currentNode->addNode(newNode, false);
- currentNode = newNode;
- } else {
- currentNode->addLeaf(FileTreeInformation(*componentIter, i));
- }
- } else {
- DirectoryTree::Node *newNode = new DirectoryTree::Node;
- newNode->setData(DirectoryTreeInformation(*componentIter, -1));
- currentNode->addNode(newNode, false);
- currentNode = newNode;
- }
- }
- }
+ for (auto &entry : files) {
+ auto path = entry->path();
+ result.append(QDir::tempPath().append("/").append(path));
+ m_TempFilesToDelete.insert(path);
}
- return result.take();
-}
-
-
-bool InstallationManager::isSimpleArchiveTopLayer(const DirectoryTree::Node *node, bool bainStyle)
-{
- // see if there is at least one directory that makes sense on the top level
- for (DirectoryTree::const_node_iterator iter = node->nodesBegin(); iter != node->nodesEnd(); ++iter) {
- if ((bainStyle && InstallationTester::isTopLevelDirectoryBain((*iter)->getData().name)) ||
- (!bainStyle && InstallationTester::isTopLevelDirectory((*iter)->getData().name))) {
- log::debug("{} on the top level", (*iter)->getData().name.toQString());
- return true;
- }
+ if (!extractFiles(QDir::tempPath())) {
+ return QStringList();
}
- // see if there is a file that makes sense on the top level
- for (DirectoryTree::const_leaf_iterator iter = node->leafsBegin(); iter != node->leafsEnd(); ++iter) {
- if (InstallationTester::isTopLevelSuffix(iter->getName())) {
- return true;
- }
- }
- return false;
+ return result;
}
-DirectoryTree::Node *InstallationManager::getSimpleArchiveBase(DirectoryTree *dataTree)
+IPluginInstaller::EInstallResult InstallationManager::installArchive(GuessedValue<QString> &modName, const QString &archiveName, int modId)
{
- DirectoryTree::Node *currentNode = dataTree;
-
- while (true) {
- if (isSimpleArchiveTopLayer(currentNode, false)) {
- return currentNode;
- } else if ((currentNode->numLeafs() == 0) &&
- (currentNode->numNodes() == 1)) {
- currentNode = *currentNode->nodesBegin();
- } else {
- log::debug("not a simple archive");
- return nullptr;
- }
- }
+ // in earlier versions the modName was copied here and the copy passed to install. I don't know why I did this and it causes
+ // a problem if this is called by the bundle installer and the bundled installer adds additional names that then end up being used,
+ // because the caller will then not have the right name.
+ bool iniTweaks;
+ return install(archiveName, modName, iniTweaks, modId);
}
-
void InstallationManager::updateProgress(float percentage)
{
if (m_InstallationProgress != nullptr) {
@@ -804,7 +586,8 @@ IPluginInstaller::EInstallResult InstallationManager::install(const QString &fil
}
ON_BLOCK_EXIT(std::bind(&InstallationManager::postInstallCleanup, this));
- QScopedPointer<DirectoryTree> filesTree(archiveOpen ? createFilesTree() : nullptr);
+ std::shared_ptr<IFileTree> filesTree =
+ archiveOpen ? ArchiveFileTree::makeTree(m_ArchiveHandler) : nullptr;
IPluginInstaller::EInstallResult installResult = IPluginInstaller::RESULT_NOTATTEMPTED;
std::sort(m_Installers.begin(), m_Installers.end(), [] (IPluginInstaller *LHS, IPluginInstaller *RHS) {
@@ -831,11 +614,20 @@ IPluginInstaller::EInstallResult InstallationManager::install(const QString &fil
IPluginInstallerSimple *installerSimple
= dynamic_cast<IPluginInstallerSimple *>(installer);
if ((installerSimple != nullptr) && (filesTree != nullptr)
- && (installer->isArchiveSupported(*filesTree))) {
+ && (installer->isArchiveSupported(filesTree))) {
installResult
- = installerSimple->install(modName, *filesTree, version, modID);
+ = installerSimple->install(modName, filesTree, version, modID);
if (installResult == IPluginInstaller::RESULT_SUCCESS) {
- mapToArchive(filesTree.data());
+
+ // Note: Have to maintain a pointer to IFileTree because install() takes a
+ // reference. This could be an issue if ever a plugin creates a new tree that
+ // is not a ArchiveFileTree.
+ ArchiveFileTree* p = dynamic_cast<ArchiveFileTree*>(filesTree.get());
+ if (p == nullptr) {
+ throw IncompatibilityException(tr("Invalid file tree returned by plugin."));
+ }
+ p->mapToArchive(m_ArchiveHandler);
+
// the simple installer only prepares the installation, the rest
// works the same for all installers
installResult = doInstall(modName, gameName, modID, version, newestVersion, categoryID, fileCategoryID, repository);
@@ -848,7 +640,7 @@ IPluginInstaller::EInstallResult InstallationManager::install(const QString &fil
= dynamic_cast<IPluginInstallerCustom *>(installer);
if ((installerCustom != nullptr)
&& (((filesTree != nullptr)
- && installer->isArchiveSupported(*filesTree))
+ && installer->isArchiveSupported(filesTree))
|| ((filesTree == nullptr)
&& installerCustom->isArchiveSupported(fileName)))) {
std::set<QString> installerExt
@@ -880,9 +672,9 @@ IPluginInstaller::EInstallResult InstallationManager::install(const QString &fil
case IPluginInstaller::RESULT_SUCCESS:
case IPluginInstaller::RESULT_SUCCESSCANCEL: {
if (filesTree != nullptr) {
- DirectoryTree::node_iterator iniTweakNode = filesTree->nodeFind(DirectoryTreeInformation("INI Tweaks"));
- hasIniTweaks = (iniTweakNode != filesTree->nodesEnd()) &&
- ((*iniTweakNode)->numLeafs() != 0);
+ auto iniTweakEntry = filesTree->find("INI Tweaks", FileTreeEntry::DIRECTORY);
+ hasIniTweaks = iniTweakEntry != nullptr
+ && !iniTweakEntry->astree()->empty();
}
return IPluginInstaller::RESULT_SUCCESS;
} break;
diff --git a/src/installationmanager.h b/src/installationmanager.h
index 199a0f82..008a0916 100644
--- a/src/installationmanager.h
+++ b/src/installationmanager.h
@@ -20,7 +20,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#ifndef INSTALLATIONMANAGER_H
#define INSTALLATIONMANAGER_H
-
+#include <ifiletree.h>
#include <iinstallationmanager.h>
#include <iplugininstaller.h>
#include <guessedvalue.h>
@@ -107,42 +107,61 @@ public:
* @brief register an installer-plugin
* @param the installer to register
*/
- void registerInstaller(MOBase::IPluginInstaller *installer);
-
+ void registerInstaller(MOBase::IPluginInstaller *installer);
+
/**
* @return list of file extensions we can install
*/
QStringList getSupportedExtensions() const;
/**
- * @brief extract the specified file from the currently open archive to a temporary location
- * @param (relative) name of the file within the archive
- * @return the absolute name of the temporary file
- * @note the call will fail with an exception if no archive is open (plugins deriving
- * from IPluginInstallerSimple can rely on that, custom installers shouldn't)
- * @note the temporary file is automatically cleaned up after the installation
- * @note This call can be very slow if the archive is large and "solid"
+ * @brief Extract the specified file from the currently opened archive to a temporary location.
+ *
+ * This method cannot be used to extract directory.
+ *
+ * @param entry Entry corresponding to the file to extract.
+ *
+ * @return the absolute path to the temporary file.
+ *
+ * @note The call will fail with an exception if no archive is open (plugins deriving
+ * from IPluginInstallerSimple can rely on that, custom installers should not).
+ * @note The temporary file is automatically cleaned up after the installation.
+ * @note This call can be very slow if the archive is large and "solid".
*/
- virtual QString extractFile(const QString &fileName);
+ virtual QString extractFile(std::shared_ptr<const MOBase::FileTreeEntry> entry) override;
/**
- * @brief extract the specified files from the currently open archive to a temporary location
- * @param (relative) names of files within the archive
- * @return the absolute names of the temporary files
- * @note the call will fail with an exception if no archive is open (plugins deriving
- * from IPluginInstallerSimple can rely on that, custom installers shouldn't)
- * @note the temporary file is automatically cleaned up after the installation
- * @note This call can be very slow if the archive is large and "solid"
+ * @brief Extract the specified files from the currently opened archive to a temporary location.
+ *
+ * This method cannot be used to extract directory.
+ *
+ * @param entres Entries corresponding to the files to extract.
+ *
+ * @return the list of absolute paths to the temporary files.
+ *
+ * @note The call will fail with an exception if no archive is open (plugins deriving
+ * from IPluginInstallerSimple can rely on that, custom installers should not).
+ * @note The temporary file is automatically cleaned up after the installation.
+ * @note This call can be very slow if the archive is large and "solid".
+ *
+ * The flatten argument is not present here while it is present in the deprecated QStringList
+ * version for multiple reasons: 1) it was never used, 2) it is kind of fishy because there
+ * is no way to know if a file is going to be overriden, 3) it is quite easy to flatten a
+ * IFileTree and thus to given a list of entries flattened (this was not possible with the
+ * QStringList version since these were based on the name of the file inside the archive).
*/
- virtual QStringList extractFiles(const QStringList &files, bool flatten);
+ virtual QStringList extractFiles(std::vector<std::shared_ptr<const MOBase::FileTreeEntry>> const& entries) override;
/**
- * @brief installs an archive
- * @param modName suggested name of the mod
- * @param archiveFile path to the archive to install
- * @return the installation result
+ * @brief Installs the given archive.
+ *
+ * @param modName Suggested name of the mod.
+ * @param archiveFile Path to the archive to install.
+ * @param modId ID of the mod, if available.
+ *
+ * @return the installation result.
*/
- virtual MOBase::IPluginInstaller::EInstallResult installArchive(MOBase::GuessedValue<QString> &modName, const QString &archiveName, const int &modId = 0);
+ virtual MOBase::IPluginInstaller::EInstallResult installArchive(MOBase::GuessedValue<QString> &modName, const QString &archiveName, int modId = 0) override;
/**
* @brief test if the specified mod name is free. If not, query the user how to proceed
@@ -161,20 +180,9 @@ private:
void updateProgressFile(const QString &fileName);
void report7ZipError(const QString &errorMessage);
- MOBase::DirectoryTree *createFilesTree();
-
- // remap all files in the archive to the directory structure represented by baseNode
- // files not present in baseNode are disabled
- void mapToArchive(const MOBase::DirectoryTree::Node *baseNode);
-
- // recursive worker function for mapToArchive
- void mapToArchive(const MOBase::DirectoryTree::Node *node, QString path, FileData * const *data);
+ // Recursive worker function for mapToArchive (takes raw reference for "speed").
bool unpackSingleFile(const QString &fileName);
-
- bool isSimpleArchiveTopLayer(const MOBase::DirectoryTree::Node *node, bool bainStyle);
- MOBase::DirectoryTree::Node *getSimpleArchiveBase(MOBase::DirectoryTree *dataTree);
-
MOBase::IPluginInstaller::EInstallResult doInstall(MOBase::GuessedValue<QString> &modName, QString gameName,
int modID, const QString &version, const QString &newestVersion, int categoryID, int fileCategoryID, const QString &repository);
@@ -205,6 +213,19 @@ private:
}
};
+ /**
+ * @brief Extract the files from the archived that are not disabled (that have
+ * output filenames associated with them) to the given path.
+ *
+ * @param extractPath Path (on the disk) were the extracted files should be put.
+ *
+ * This method is mainly a convenience method for the extractFiles() methods.
+ *
+ * @return true if the extraction was successful, false if the extraciton was
+ * cancelled. If an error occured, an exception is thrown.
+ */
+ bool extractFiles(QDir extractPath);
+
private:
bool m_IsRunning;
diff --git a/src/modinfo.cpp b/src/modinfo.cpp
index 085eaf80..7f888bdc 100644
--- a/src/modinfo.cpp
+++ b/src/modinfo.cpp
@@ -25,11 +25,9 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
#include "modinfooverwrite.h"
#include "modinfoseparator.h"
-#include "installationtester.h"
#include "categories.h"
#include "modinfodialog.h"
#include "overwriteinfodialog.h"
-#include "filenamestring.h"
#include "versioninfo.h"
#include <iplugingame.h>
@@ -475,7 +473,7 @@ bool ModInfo::removeCategory(const QString &categoryName)
return true;
}
-QStringList ModInfo::categories()
+QStringList ModInfo::categories() const
{
QStringList result;
@@ -529,28 +527,7 @@ bool ModInfo::categorySet(int categoryID) const
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();
- }
+ m_Valid = doTestValid();
}
QUrl ModInfo::parseCustomURL() const
diff --git a/src/modinfo.h b/src/modinfo.h
index 34b1ecdf..2c108378 100644
--- a/src/modinfo.h
+++ b/src/modinfo.h
@@ -319,11 +319,23 @@ public:
virtual void setNotes(const QString &notes) = 0;
/**
- * @brief set/change the source game of this mod
- *
- * @param gameName the source game shortName
- */
- virtual void setGameName(const QString &gameName) = 0;
+ * @brief set/change the source game of this mod
+ *
+ * @param gameName the source game shortName
+ */
+ virtual void setGameName(const QString& gameName) = 0;
+
+ /**
+ * @brief set the name of this mod
+ *
+ * set the name of this mod. This will also update the name of the
+ * directory that contains this mod
+ *
+ * @param name new name of the mod
+ * @return true on success, false if the new name can't be used (i.e. because the new
+ * directory name wouldn't be valid)
+ **/
+ virtual bool setName(const QString& name) = 0;
/**
* @brief set/change the nexus mod id of this mod
@@ -336,7 +348,7 @@ public:
* @brief set/change the version of this mod
* @param version new version of the mod
*/
- virtual void setVersion(const MOBase::VersionInfo &version);
+ virtual void setVersion(const MOBase::VersionInfo &version) override;
/**
* @brief Controls if mod should be highlighted based on plugin selection
@@ -382,7 +394,7 @@ public:
virtual void addCategory(const QString &categoryName) override;
virtual bool removeCategory(const QString &categoryName) override;
- virtual QStringList categories() override;
+ virtual QStringList categories() const override;
/**
* update the endorsement state for the mod. This only changes the
@@ -645,12 +657,12 @@ public:
/*
*@return the color choosen by the user for the mod/separator
*/
- virtual QColor getColor() { return QColor(); }
+ virtual QColor getColor() const { return QColor(); }
/*
*@return true if the color has been set successfully.
*/
- virtual void setColor(QColor color) { }
+ virtual void setColor(QColor) { }
/**
* @brief adds the information that a file has been installed into this mod
@@ -709,12 +721,12 @@ public:
/**
* @brief updates the mod to flag it as converted in order to ignore the alternate game warning
*/
- virtual void markConverted(bool converted) {}
+ virtual void markConverted(bool) {}
/**
* @brief updates the mod to flag it as valid in order to ignore the invalid game data flag
*/
- virtual void markValidated(bool validated) {}
+ virtual void markValidated(bool) {}
/**
* @brief reads meta information from disk
@@ -729,32 +741,32 @@ public:
/**
* @return retrieve list of mods (as mod index) that are overwritten by this one. Updates may be delayed
*/
- virtual std::set<unsigned int> getModOverwrite() { return std::set<unsigned int>(); }
+ virtual std::set<unsigned int> getModOverwrite() const { return std::set<unsigned int>(); }
/**
* @return list of mods (as mod index) that overwrite this one. Updates may be delayed
*/
- virtual std::set<unsigned int> getModOverwritten() { return std::set<unsigned int>(); }
+ virtual std::set<unsigned int> getModOverwritten() const { return std::set<unsigned int>(); }
/**
* @return retrieve list of mods (as mod index) with archives that are overwritten by this one. Updates may be delayed
*/
- virtual std::set<unsigned int> getModArchiveOverwrite() { return std::set<unsigned int>(); }
+ virtual std::set<unsigned int> getModArchiveOverwrite() const { return std::set<unsigned int>(); }
/**
* @return list of mods (as mod index) with archives that overwrite this one. Updates may be delayed
*/
- virtual std::set<unsigned int> getModArchiveOverwritten() { return std::set<unsigned int>(); }
+ virtual std::set<unsigned int> getModArchiveOverwritten() const { return std::set<unsigned int>(); }
/**
* @return retrieve list of mods (as mod index) with archives that are overwritten by thos mod's loose files. Updates may be delayed
*/
- virtual std::set<unsigned int> getModArchiveLooseOverwrite() { return std::set<unsigned int>(); }
+ virtual std::set<unsigned int> getModArchiveLooseOverwrite() const { return std::set<unsigned int>(); }
/**
* @return list of mods (as mod index) with loose files that overwrite this one's archive files. Updates may be delayed
*/
- virtual std::set<unsigned int> getModArchiveLooseOverwritten() { return std::set<unsigned int>(); }
+ virtual std::set<unsigned int> getModArchiveLooseOverwritten() const { return std::set<unsigned int>(); }
/**
* @brief update conflict information
@@ -804,6 +816,13 @@ 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,
diff --git a/src/modinfobackup.h b/src/modinfobackup.h
index 393c2e38..9eba545c 100644
--- a/src/modinfobackup.h
+++ b/src/modinfobackup.h
@@ -12,35 +12,32 @@ class ModInfoBackup : public ModInfoRegular
public:
- virtual bool updateAvailable() const { return false; }
- virtual bool updateIgnored() const { return false; }
- virtual bool downgradeAvailable() const { return false; }
- virtual bool updateNXMInfo() { return false; }
- virtual void setGameName(const QString&) {}
- virtual void setNexusID(int) {}
- virtual void endorse(bool) {}
- virtual void parseNexusInfo() {}
- virtual int getFixedPriority() const { return -1; }
- virtual void ignoreUpdate(bool) {}
- virtual bool canBeUpdated() const { return false; }
- virtual QDateTime getExpires() const { return QDateTime(); }
- virtual bool canBeEnabled() const { return false; }
- virtual std::vector<QString> getIniTweaks() const { return std::vector<QString>(); }
- virtual std::vector<EFlag> getFlags() const;
- virtual QString getDescription() const;
- virtual int getNexusFileStatus() const { return 0; }
- virtual void setNexusFileStatus(int) {}
- virtual QDateTime getLastNexusQuery() const { return QDateTime(); }
- virtual void setLastNexusQuery(QDateTime) {}
- virtual QDateTime getLastNexusUpdate() const { return QDateTime(); }
- virtual void setLastNexusUpdate(QDateTime) {}
- virtual QDateTime getNexusLastModified() const { return QDateTime(); }
- virtual void setNexusLastModified(QDateTime) {}
- virtual void getNexusFiles(QList<MOBase::ModRepositoryFileInfo*>::const_iterator&,
- QList<MOBase::ModRepositoryFileInfo*>::const_iterator&) {}
- virtual QString getNexusDescription() const { return QString(); }
+ virtual bool updateAvailable() const override { return false; }
+ virtual bool updateIgnored() const override { return false; }
+ virtual bool downgradeAvailable() const override { return false; }
+ virtual bool updateNXMInfo() override { return false; }
+ virtual void setGameName(const QString& gameName) override {}
+ virtual void setNexusID(int) override {}
+ virtual void endorse(bool) override {}
+ virtual int getFixedPriority() const override { return -1; }
+ virtual void ignoreUpdate(bool) override {}
+ virtual bool canBeUpdated() const override { return false; }
+ virtual QDateTime getExpires() const override { return QDateTime(); }
+ virtual bool canBeEnabled() const override { return false; }
+ virtual std::vector<QString> getIniTweaks() const override { return std::vector<QString>(); }
+ virtual std::vector<EFlag> getFlags() const override;
+ virtual QString getDescription() const override;
+ virtual int getNexusFileStatus() const override { return 0; }
+ virtual void setNexusFileStatus(int) override {}
+ virtual QDateTime getLastNexusQuery() const override { return QDateTime(); }
+ virtual void setLastNexusQuery(QDateTime) override {}
+ virtual QDateTime getLastNexusUpdate() const override { return QDateTime(); }
+ virtual void setLastNexusUpdate(QDateTime) override {}
+ virtual QDateTime getNexusLastModified() const override { return QDateTime(); }
+ virtual void setNexusLastModified(QDateTime) override {}
+ virtual QString getNexusDescription() const override { return QString(); }
- virtual void addInstalledFile(int, int) {}
+ virtual void addInstalledFile(int, int) override {}
private:
diff --git a/src/modinfodialognexus.cpp b/src/modinfodialognexus.cpp
index 59bfe930..8d99d230 100644
--- a/src/modinfodialognexus.cpp
+++ b/src/modinfodialognexus.cpp
@@ -324,7 +324,7 @@ void NexusTab::onSourceGameChanged()
for (auto game : plugin().plugins<MOBase::IPluginGame>()) {
if (game->gameName() == ui->sourceGame->currentText()) {
- mod().setGameName(game->gameShortName());
+ mod().setGameName(game->gameShortName());
mod().setLastNexusQuery(QDateTime::fromSecsSinceEpoch(0));
refreshData(mod().getNexusID());
return;
diff --git a/src/modinfoforeign.h b/src/modinfoforeign.h
index c5763d6b..da2c865b 100644
--- a/src/modinfoforeign.h
+++ b/src/modinfoforeign.h
@@ -1,9 +1,11 @@
#ifndef MODINFOFOREIGN_H
#define MODINFOFOREIGN_H
+#include <limits>
+
#include "modinfowithconflictinfo.h"
-class ModInfoForeign : public ModInfoWithConflictInfo
+class ModInfoForeign: public ModInfoWithConflictInfo
{
Q_OBJECT
@@ -12,65 +14,65 @@ class ModInfoForeign : public ModInfoWithConflictInfo
public:
- virtual bool updateAvailable() const { return false; }
- virtual bool updateIgnored() const { return false; }
- virtual bool downgradeAvailable() const { return false; }
- virtual bool updateNXMInfo() { return false; }
- virtual void setCategory(int, bool) {}
- virtual bool setName(const QString&) { return false; }
- virtual void setComments(const QString&) {}
- virtual void setNotes(const QString&) {}
- virtual void setGameName(const QString&) {}
- virtual void setNexusID(int) {}
- virtual void setNewestVersion(const MOBase::VersionInfo&) {}
- virtual void ignoreUpdate(bool) {}
- virtual void setNexusDescription(const QString&) {}
- virtual void setInstallationFile(const QString&) {}
- virtual void addNexusCategory(int) {}
- virtual void setIsEndorsed(bool) {}
- virtual void setNeverEndorse() {}
- virtual void setIsTracked(bool) {}
- virtual bool remove() { return false; }
- virtual void endorse(bool) {}
- virtual void track(bool) {}
- virtual void parseNexusInfo() {}
- virtual bool isEmpty() const { return false; }
- virtual QString name() const { return m_Name; }
- virtual QString internalName() const { return m_InternalName; }
- virtual QString comments() const { return ""; }
- virtual QString notes() const { return ""; }
- virtual QDateTime creationTime() const;
- virtual QString absolutePath() const;
- virtual MOBase::VersionInfo getNewestVersion() const { return QString(); }
- virtual QString getInstallationFile() const { return ""; }
- virtual QString getGameName() const { return ""; }
- virtual int getNexusID() const { return -1; }
- virtual QDateTime getExpires() const { return QDateTime(); }
- virtual std::vector<QString> getIniTweaks() const { return std::vector<QString>(); }
- virtual std::vector<ModInfo::EFlag> getFlags() const;
- virtual int getHighlight() const;
- virtual QString getDescription() const;
- virtual int getNexusFileStatus() const { return 0; }
- virtual void setNexusFileStatus(int) {}
- virtual QDateTime getLastNexusUpdate() const { return QDateTime(); }
- virtual void setLastNexusUpdate(QDateTime) {}
- virtual QDateTime getLastNexusQuery() const { return QDateTime(); }
- virtual void setLastNexusQuery(QDateTime) {}
- virtual QDateTime getNexusLastModified() const { return QDateTime(); }
- virtual void setNexusLastModified(QDateTime) {}
- virtual QString getNexusDescription() const { return QString(); }
- virtual int getFixedPriority() const { return INT_MIN; }
- virtual QStringList archives(bool checkOnDisk = false) { return m_Archives; }
- virtual QStringList stealFiles() const { return m_Archives + QStringList(m_ReferenceFile); }
- virtual bool alwaysEnabled() const { return true; }
- virtual void addInstalledFile(int, int) {}
+ virtual bool updateAvailable() const override { return false; }
+ virtual bool updateIgnored() const override { return false; }
+ virtual bool downgradeAvailable() const override { return false; }
+ virtual bool updateNXMInfo() override { return false; }
+ virtual void setCategory(int, bool) override {}
+ virtual bool setName(const QString&) override { return false; }
+ virtual void setComments(const QString&) override {}
+ virtual void setNotes(const QString&) override {}
+ virtual void setGameName(const QString& gameName) override {}
+ virtual void setNexusID(int) override {}
+ virtual void setNewestVersion(const MOBase::VersionInfo&) override {}
+ virtual void ignoreUpdate(bool) override {}
+ virtual void setNexusDescription(const QString&) override {}
+ virtual void setInstallationFile(const QString&) override {}
+ virtual void addNexusCategory(int) override {}
+ virtual void setIsEndorsed(bool) override {}
+ virtual void setNeverEndorse() override {}
+ virtual void setIsTracked(bool) override {}
+ virtual bool remove() override { return false; }
+ virtual void endorse(bool) override {}
+ virtual void track(bool) override {}
+ virtual bool isEmpty() const override { return false; }
+ virtual QString name() const override { return m_Name; }
+ virtual QString internalName() const override { return m_InternalName; }
+ virtual QString comments() const override { return ""; }
+ virtual QString notes() const override { return ""; }
+ virtual QDateTime creationTime() const override;
+ virtual QString absolutePath() const override;
+ virtual MOBase::VersionInfo getNewestVersion() const override { return QString(); }
+ virtual QString getInstallationFile() const override { return ""; }
+ virtual QString getGameName() const override { return ""; }
+ virtual int getNexusID() const override { return -1; }
+ virtual QDateTime getExpires() const override { return QDateTime(); }
+ virtual std::vector<QString> getIniTweaks() const override { return std::vector<QString>(); }
+ virtual std::vector<ModInfo::EFlag> getFlags() const override;
+ virtual int getHighlight() const override;
+ virtual QString getDescription() const override;
+ virtual int getNexusFileStatus() const override { return 0; }
+ virtual void setNexusFileStatus(int) override {}
+ virtual QDateTime getLastNexusUpdate() const override { return QDateTime(); }
+ virtual void setLastNexusUpdate(QDateTime) override {}
+ virtual QDateTime getLastNexusQuery() const override { return QDateTime(); }
+ virtual void setLastNexusQuery(QDateTime) override {}
+ virtual QDateTime getNexusLastModified() const override { return QDateTime(); }
+ virtual void setNexusLastModified(QDateTime) override {}
+ virtual QString getNexusDescription() const override { return QString(); }
+ virtual int getFixedPriority() const override { return std::numeric_limits<int>::min(); }
+ virtual QStringList archives(bool = false) override { return m_Archives; }
+ virtual QStringList stealFiles() const override { return m_Archives + QStringList(m_ReferenceFile); }
+ virtual bool alwaysEnabled() const override { return true; }
+ virtual void addInstalledFile(int, int) override {}
ModInfo::EModType modType() const { return m_ModType; }
protected:
ModInfoForeign(const QString &modName, const QString &referenceFile,
const QStringList &archives, ModInfo::EModType modType,
- MOShared::DirectoryEntry **directoryStructure, PluginContainer *pluginContainer);
+ MOShared::DirectoryEntry **directoryStructure, PluginContainer *pluginContainer);
+
private:
QString m_Name;
diff --git a/src/modinfooverwrite.h b/src/modinfooverwrite.h
index ecbdbe3d..0bcf6f27 100644
--- a/src/modinfooverwrite.h
+++ b/src/modinfooverwrite.h
@@ -1,6 +1,8 @@
#ifndef MODINFOOVERWRITE_H
#define MODINFOOVERWRITE_H
+#include <limits>
+
#include "modinfowithconflictinfo.h"
#include <QDateTime>
@@ -14,60 +16,58 @@ class ModInfoOverwrite : public ModInfoWithConflictInfo
public:
- virtual bool updateAvailable() const { return false; }
- virtual bool updateIgnored() const { return false; }
- virtual bool downgradeAvailable() const { return false; }
- virtual bool updateNXMInfo() { return false; }
- virtual void setCategory(int, bool) {}
- virtual bool setName(const QString&) { return false; }
- virtual void setComments(const QString&) {}
- virtual void setNotes(const QString&) {}
- virtual void setGameName(const QString&) {}
- virtual void setNexusID(int) {}
- virtual void setNewestVersion(const MOBase::VersionInfo&) {}
- virtual void ignoreUpdate(bool) {}
- virtual void setNexusDescription(const QString&) {}
- virtual void setInstallationFile(const QString&) {}
- virtual void addNexusCategory(int) {}
- virtual void setIsEndorsed(bool) {}
- virtual void setNeverEndorse() {}
- virtual void setIsTracked(bool) {}
- virtual bool remove() { return false; }
- virtual void endorse(bool) {}
- virtual void track(bool) {}
- virtual void parseNexusInfo() {}
- virtual bool alwaysEnabled() const { return true; }
- virtual bool isEmpty() const;
- virtual QString name() const { return "Overwrite"; }
- virtual QString comments() const { return ""; }
- virtual QString notes() const { return ""; }
- virtual QDateTime creationTime() const { return QDateTime(); }
- virtual QString absolutePath() const;
- virtual MOBase::VersionInfo getNewestVersion() const { return QString(); }
- virtual QString getInstallationFile() const { return ""; }
- virtual int getFixedPriority() const { return INT_MAX; }
- virtual QString getGameName() const { return ""; }
- virtual int getNexusID() const { return -1; }
- virtual QDateTime getExpires() const { return QDateTime(); }
- virtual std::vector<QString> getIniTweaks() const { return std::vector<QString>(); }
- virtual std::vector<ModInfo::EFlag> getFlags() const;
- virtual std::vector<ModInfo::EConflictFlag> getConflictFlags() const;
- virtual int getHighlight() const;
- virtual QString getDescription() const;
- virtual int getNexusFileStatus() const { return 0; }
- virtual void setNexusFileStatus(int) {}
- virtual QDateTime getLastNexusUpdate() const { return QDateTime(); }
- virtual void setLastNexusUpdate(QDateTime) {}
- virtual QDateTime getLastNexusQuery() const { return QDateTime(); }
- virtual void setLastNexusQuery(QDateTime) {}
- virtual QDateTime getNexusLastModified() const { return QDateTime(); }
- virtual void setNexusLastModified(QDateTime) {}
- virtual QString getNexusDescription() const { return QString(); }
- virtual QStringList archives(bool checkOnDisk = false);
- virtual void addInstalledFile(int, int) {}
+ virtual bool updateAvailable() const override { return false; }
+ virtual bool updateIgnored() const override { return false; }
+ virtual bool downgradeAvailable() const override { return false; }
+ virtual bool updateNXMInfo() override { return false; }
+ virtual void setCategory(int, bool) override {}
+ virtual bool setName(const QString&) override { return false; }
+ virtual void setComments(const QString&) override {}
+ virtual void setNotes(const QString&) override {}
+ virtual void setGameName(const QString& gameName) override {}
+ virtual void setNexusID(int) override {}
+ virtual void setNewestVersion(const MOBase::VersionInfo&) override {}
+ virtual void ignoreUpdate(bool) override {}
+ virtual void setNexusDescription(const QString&) override {}
+ virtual void setInstallationFile(const QString&) override {}
+ virtual void addNexusCategory(int) override {}
+ virtual void setIsEndorsed(bool) override {}
+ virtual void setNeverEndorse() override {}
+ virtual void setIsTracked(bool) override {}
+ virtual bool remove() override { return false; }
+ virtual void endorse(bool) override {}
+ virtual void track(bool) override {}
+ virtual bool alwaysEnabled() const override { return true; }
+ virtual bool isEmpty() const override;
+ virtual QString name() const override { return "Overwrite"; }
+ virtual QString comments() const override { return ""; }
+ virtual QString notes() const override { return ""; }
+ virtual QDateTime creationTime() const override { return QDateTime(); }
+ virtual QString absolutePath() const override;
+ virtual MOBase::VersionInfo getNewestVersion() const override { return QString(); }
+ virtual QString getInstallationFile() const override { return ""; }
+ virtual int getFixedPriority() const override { return std::numeric_limits<int>::max(); }
+ virtual QString getGameName() const override { return ""; }
+ virtual int getNexusID() const override { return -1; }
+ virtual QDateTime getExpires() const override { return QDateTime(); }
+ virtual std::vector<QString> getIniTweaks() const override { return std::vector<QString>(); }
+ virtual std::vector<ModInfo::EFlag> getFlags() const override;
+ virtual std::vector<ModInfo::EConflictFlag> getConflictFlags() const override;
+ virtual int getHighlight() const override;
+ virtual QString getDescription() const override;
+ virtual int getNexusFileStatus() const override { return 0; }
+ virtual void setNexusFileStatus(int) override {}
+ virtual QDateTime getLastNexusUpdate() const override { return QDateTime(); }
+ virtual void setLastNexusUpdate(QDateTime) override {}
+ virtual QDateTime getLastNexusQuery() const override { return QDateTime(); }
+ virtual void setLastNexusQuery(QDateTime) override {}
+ virtual QDateTime getNexusLastModified() const override { return QDateTime(); }
+ virtual void setNexusLastModified(QDateTime) override {}
+ virtual QString getNexusDescription() const override { return QString(); }
+ virtual QStringList archives(bool checkOnDisk = false) override;
+ virtual void addInstalledFile(int, int) override {}
private:
-
ModInfoOverwrite(PluginContainer *pluginContainer, MOShared::DirectoryEntry **directoryStructure );
};
diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp
index 3cff914a..a1ef5701 100644
--- a/src/modinforegular.cpp
+++ b/src/modinforegular.cpp
@@ -29,6 +29,7 @@ ModInfoRegular::ModInfoRegular(PluginContainer *pluginContainer, const IPluginGa
, m_Name(path.dirName())
, m_Path(path.absolutePath())
, m_Repository()
+ , m_GamePlugin(game)
, m_GameName(game->gameShortName())
, m_IsAlternate(false)
, m_Converted(false)
@@ -467,7 +468,7 @@ void ModInfoRegular::setNotes(const QString &notes)
m_MetaInfoChanged = true;
}
-void ModInfoRegular::setGameName(const QString &gameName)
+void ModInfoRegular::setGameName(const QString& gameName)
{
m_GameName = gameName;
m_MetaInfoChanged = true;
@@ -556,7 +557,7 @@ void ModInfoRegular::setColor(QColor color)
m_MetaInfoChanged = true;
}
-QColor ModInfoRegular::getColor()
+QColor ModInfoRegular::getColor() const
{
return m_Color;
}
diff --git a/src/modinforegular.h b/src/modinforegular.h
index 705e66a8..75b24a6b 100644
--- a/src/modinforegular.h
+++ b/src/modinforegular.h
@@ -1,6 +1,8 @@
#ifndef MODINFOREGULAR_H
#define MODINFOREGULAR_H
+#include <limits>
+
#include "modinfowithconflictinfo.h"
#include "nexusinterface.h"
@@ -22,9 +24,9 @@ public:
~ModInfoRegular();
- virtual bool isRegular() const { return true; }
+ virtual bool isRegular() const override { return true; }
- virtual bool isEmpty() const;
+ virtual bool isEmpty() const override;
bool isAlternate() { return m_IsAlternate; }
bool isConverted() { return m_Converted; }
@@ -39,12 +41,12 @@ public:
*
* @return true if there is a newer version
**/
- bool updateAvailable() const;
+ bool updateAvailable() const override;
/**
* @return true if the current update is being ignored
*/
- virtual bool updateIgnored() const { return m_IgnoredVersion.isValid() && m_IgnoredVersion == m_NewestVersion; }
+ virtual bool updateIgnored() const override { return m_IgnoredVersion.isValid() && m_IgnoredVersion == m_NewestVersion; }
/**
* @brief test if there is a newer version of the mod
@@ -55,7 +57,7 @@ public:
*
* @return true if there is a newer version
**/
- bool downgradeAvailable() const;
+ bool downgradeAvailable() const override;
/**
* @brief request an update of nexus description for this mod.
@@ -65,7 +67,7 @@ public:
*
* @return returns true if information for this mod will be updated, false if there is no nexus mod id to use
**/
- bool updateNXMInfo();
+ bool updateNXMInfo() override;
/**
* @brief assign or unassign the specified category
@@ -76,7 +78,7 @@ public:
* @param active determines wheter the category is assigned or unassigned
* @note this function does not test whether categoryID actually identifies a valid category
**/
- void setCategory(int categoryID, bool active);
+ void setCategory(int categoryID, bool active) override;
/**
* @brief set the name of this mod
@@ -88,33 +90,33 @@ public:
* @return true on success, false if the new name can't be used (i.e. because the new
* directory name wouldn't be valid)
**/
- bool setName(const QString &name);
+ bool setName(const QString &name) override;
/**
* @brief changes the comments (manually set information displayed in the mod list) for this mod
* @param comments new comments
*/
- void setComments(const QString &comments);
+ void setComments(const QString &comments) override;
/**
* @brief change the notes (manually set information) for this mod
* @param notes new notes
*/
- void setNotes(const QString &notes);
+ void setNotes(const QString &notes) override;
/**
* @brief set/change the source game of this mod
*
* @param gameName the source game shortName
*/
- void setGameName(const QString &gameName);
+ virtual void setGameName(const QString& gameName) override;
/**
* @brief set/change the nexus mod id of this mod
*
* @param modID the nexus mod id
**/
- void setNexusID(int modID);
+ void setNexusID(int modID) override;
/**
* @brief set the version of this mod
@@ -124,7 +126,7 @@ public:
*
* @param version the new version to use
**/
- void setVersion(const MOBase::VersionInfo &version);
+ void setVersion(const MOBase::VersionInfo &version) override;
/**
* @brief set the newest version of this mod on the nexus
@@ -136,73 +138,73 @@ public:
* @todo this function should be made obsolete. All queries for mod information should go through
* this class so no public function for this change is required
**/
- void setNewestVersion(const MOBase::VersionInfo &version);
+ void setNewestVersion(const MOBase::VersionInfo &version) override;
/**
* @brief changes/updates the nexus description text
* @param description the current description text
*/
- virtual void setNexusDescription(const QString &description);
+ virtual void setNexusDescription(const QString &description) override;
- virtual void setInstallationFile(const QString &fileName);
+ virtual void setInstallationFile(const QString &fileName) override;
/**
* @brief sets the category id from a nexus category id. Conversion to MO id happens internally
* @param categoryID the nexus category id
* @note if a mapping is not possible, the category is set to the default value
*/
- virtual void addNexusCategory(int categoryID);
+ virtual void addNexusCategory(int categoryID) override;
/**
* @brief sets the new primary category of the mod
* @param categoryID the category to set
*/
- virtual void setPrimaryCategory(int categoryID) { m_PrimaryCategory = categoryID; m_MetaInfoChanged = true; }
+ virtual void setPrimaryCategory(int categoryID) override { m_PrimaryCategory = categoryID; m_MetaInfoChanged = true; }
/**
* @brief sets the download repository
* @param repository
*/
- virtual void setRepository(const QString &repository) { m_Repository = repository; }
+ virtual void setRepository(const QString &repository) override { m_Repository = repository; }
/**
* update the endorsement state for the mod. This only changes the
* buffered state, it does not sync with Nexus
* @param endorsed the new endorsement state
*/
- virtual void setIsEndorsed(bool endorsed);
+ virtual void setIsEndorsed(bool endorsed) override;
/**
* set the mod to "i don't intend to endorse". The mod will not show as unendorsed but can still be endorsed
*/
- virtual void setNeverEndorse();
+ virtual void setNeverEndorse() override;
/**
* update the tracked state for the mod. This only changes the
* buffered state. It does not sync with Nexus
* @param tracked the new tracked state
*/
- virtual void setIsTracked(bool tracked);
+ virtual void setIsTracked(bool tracked) override;
/**
* @brief delete the mod from the disc. This does not update the global ModInfo structure or indices
* @return true if the mod was successfully removed
**/
- bool remove();
+ bool remove() override;
/**
* @brief endorse or un-endorse the mod
* @param doEndorse if true, the mod is endorsed, if false, it's un-endorsed.
* @note if doEndorse doesn't differ from the current value, nothing happens.
*/
- virtual void endorse(bool doEndorse);
+ virtual void endorse(bool doEndorse) override;
/**
* @brief track or untrack the mod. This will sync with nexus!
* @param doTrack if true, the mod is tracked, if false, it's untracked.
* @note if doTrack doesn't differ from the current value, nothing happens.
*/
- virtual void track(bool doTrack);
+ virtual void track(bool doTrack) override;
/**
* @brief updates the mod to flag it as converted in order to ignore the alternate game warning
@@ -219,183 +221,183 @@ public:
*
* @return the mod name
**/
- QString name() const { return m_Name; }
+ QString name() const override { return m_Name; }
/**
* @brief getter for the mod path
*
* @return the (absolute) path to the mod
**/
- QString absolutePath() const;
+ QString absolutePath() const override;
/**
* @brief getter for the newest version number of this mod
*
* @return newest version of the mod
**/
- MOBase::VersionInfo getNewestVersion() const { return m_NewestVersion; }
+ MOBase::VersionInfo getNewestVersion() const override { return m_NewestVersion; }
/**
* @brief ignore the newest version for updates
*/
- void ignoreUpdate(bool ignore);
+ void ignoreUpdate(bool ignore) override;
/**
* @brief getter for the installation file
*
* @return file used to install this mod from
*/
- virtual QString getInstallationFile() const { return m_InstallationFile; }
+ virtual QString getInstallationFile() const override { return m_InstallationFile; }
/**
* @brief getter for the source game repository
*
* @return the source game repository. should default to the active game.
**/
- QString getGameName() const { return m_GameName; }
+ QString getGameName() const override { return m_GameName; }
/**
* @brief getter for the nexus mod id
*
* @return the nexus mod id. may be 0 if the mod id isn't known or doesn't exist
**/
- int getNexusID() const { return m_NexusID; }
+ int getNexusID() const override { return m_NexusID; }
/**
* @return the fixed priority of mods of this type or INT_MIN if the priority of mods
* needs to be user-modifiable
*/
- virtual int getFixedPriority() const { return INT_MIN; }
+ virtual int getFixedPriority() const override { return std::numeric_limits<int>::min(); }
/**
* @return true if the mod can be updated
*/
- virtual bool canBeUpdated() const;
+ virtual bool canBeUpdated() const override;
/**
* @return the update expiration date based on the last updated date from Nexus
*/
- virtual QDateTime getExpires() const;
+ virtual QDateTime getExpires() const override;
/**
* @return true if the mod can be enabled/disabled
*/
- virtual bool canBeEnabled() const { return true; }
+ virtual bool canBeEnabled() const override { return true; }
/**
* @return a list of flags for this mod
*/
- virtual std::vector<EFlag> getFlags() const;
+ virtual std::vector<EFlag> getFlags() const override;
- virtual std::vector<EContent> getContents() const;
+ virtual std::vector<EContent> getContents() const override;
/**
* @return an indicator if and how this mod should be highlighted by the UI
*/
- virtual int getHighlight() const;
+ virtual int getHighlight() const override;
/**
* @return list of names of ini tweaks
**/
- std::vector<QString> getIniTweaks() const;
+ std::vector<QString> getIniTweaks() const override;
/**
* @return a description about the mod, to be displayed in the ui
*/
- virtual QString getDescription() const;
+ virtual QString getDescription() const override;
/**
* @return the nexus file status (aka category ID)
*/
- virtual int getNexusFileStatus() const;
+ virtual int getNexusFileStatus() const override;
/**
* @brief sets the file status (category ID) from Nexus
* @param status the status id of the installed file
*/
- virtual void setNexusFileStatus(int status);
+ virtual void setNexusFileStatus(int status) override;
/**
* @return comments for this mod
*/
- virtual QString comments() const;
+ virtual QString comments() const override;
/**
* @return manually set notes for this mod
*/
- virtual QString notes() const;
+ virtual QString notes() const override;
/**
* @return time this mod was created (file time of the directory)
*/
- virtual QDateTime creationTime() const;
+ virtual QDateTime creationTime() const override;
/**
* @return nexus description of the mod (html)
*/
- QString getNexusDescription() const;
+ QString getNexusDescription() const override;
/**
* @return repository from which the file was downloaded
*/
- virtual QString repository() const;
+ virtual QString repository() const override;
/**
* @return true if the file has been endorsed on nexus
*/
- virtual EEndorsedState endorsedState() const;
+ virtual EEndorsedState endorsedState() const override;
/**
* @return true if the file is being tracked on nexus
*/
- virtual ETrackedState trackedState() const;
+ virtual ETrackedState trackedState() const override;
/**
* @brief get the last time nexus was checked for file updates on this mod
*/
- virtual QDateTime getLastNexusUpdate() const;
+ virtual QDateTime getLastNexusUpdate() const override;
/**
* @brief set the last time nexus was checked for file updates on this mod
*/
- virtual void setLastNexusUpdate(QDateTime time);
+ virtual void setLastNexusUpdate(QDateTime time) override;
/**
* @return last time nexus was queried for infos on this mod
*/
- virtual QDateTime getLastNexusQuery() const;
+ virtual QDateTime getLastNexusQuery() const override;
/**
* @brief set the last time nexus was queried for info on this mod
*/
- virtual void setLastNexusQuery(QDateTime time);
+ virtual void setLastNexusQuery(QDateTime time) override;
/**
* @return last time the mod was updated on Nexus
*/
- virtual QDateTime getNexusLastModified() const;
+ virtual QDateTime getNexusLastModified() const override;
/**
* @brief set the last time the mod was updated on Nexus
*/
- virtual void setNexusLastModified(QDateTime time);
+ virtual void setNexusLastModified(QDateTime time) override;
- virtual QStringList archives(bool checkOnDisk = false);
+ virtual QStringList archives(bool checkOnDisk = false) override;
- virtual void setColor(QColor color);
+ virtual void setColor(QColor color) override;
- virtual QColor getColor();
+ virtual QColor getColor() const override;
- virtual void addInstalledFile(int modId, int fileId);
+ virtual void addInstalledFile(int modId, int fileId) override;
/**
* @brief stores meta information back to disk
*/
- virtual void saveMeta();
+ virtual void saveMeta() override;
- void readMeta();
+ void readMeta() override;
virtual void setHasCustomURL(bool b) override;
virtual bool hasCustomURL() const override;
@@ -429,6 +431,12 @@ private:
QString m_Repository;
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;
mutable QStringList m_Archives;
diff --git a/src/modinfoseparator.h b/src/modinfoseparator.h
index 4b1e5217..80734bcf 100644
--- a/src/modinfoseparator.h
+++ b/src/modinfoseparator.h
@@ -12,62 +12,44 @@ class ModInfoSeparator:
public:
- virtual bool updateAvailable() const { return false; }
- virtual bool updateIgnored() const { return false; }
- virtual bool downgradeAvailable() const { return false; }
- virtual bool updateNXMInfo() { return false; }
- virtual bool isValid() const { return true; }
+ virtual bool updateAvailable() const override { return false; }
+ virtual bool updateIgnored() const override { return false; }
+ virtual bool downgradeAvailable() const override { return false; }
+ virtual bool updateNXMInfo() override { return false; }
+ virtual bool isValid() const override { return true; }
//TODO: Fix renaming method to avoid priority reset
virtual bool setName(const QString& name);
- virtual int getNexusID() const { return -1; }
+ virtual int getNexusID() const override { return -1; }
+ virtual void setGameName(const QString& gameName) override {}
+ virtual void setNexusID(int /*modID*/) override {}
+ virtual void endorse(bool /*doEndorse*/) override {}
+ virtual void ignoreUpdate(bool /*ignore*/) override {}
+ virtual bool canBeUpdated() const override { return false; }
+ virtual QDateTime getExpires() const override { return QDateTime(); }
+ virtual bool canBeEnabled() const override { return false; }
+ virtual std::vector<QString> getIniTweaks() const override { return std::vector<QString>(); }
+ virtual std::vector<EFlag> getFlags() const override;
+ virtual int getHighlight() const override;
+ virtual QString getDescription() const override;
+ virtual QString name() const override;
+ virtual QString getGameName() const override { return ""; }
+ virtual QString getInstallationFile() const override { return ""; }
+ virtual QString repository() const override { return ""; }
+ virtual int getNexusFileStatus() const override { return 0; }
+ virtual void setNexusFileStatus(int) override {}
+ virtual QDateTime getLastNexusUpdate() const override { return QDateTime(); }
+ virtual void setLastNexusUpdate(QDateTime) override {}
+ virtual QDateTime getLastNexusQuery() const override { return QDateTime(); }
+ virtual void setLastNexusQuery(QDateTime) override {}
+ virtual QDateTime getNexusLastModified() const override { return QDateTime(); }
+ virtual void setNexusLastModified(QDateTime) override {}
+ virtual QDateTime creationTime() const override { return QDateTime(); }
+ virtual QString getNexusDescription() const override { return QString(); }
+ virtual void addInstalledFile(int /*modId*/, int /*fileId*/) override { }
- virtual void setGameName(const QString& /*gameName*/) {}
-
- virtual void setNexusID(int /*modID*/) {}
-
- virtual void endorse(bool /*doEndorse*/) {}
-
- virtual void parseNexusInfo() {}
-
- virtual void ignoreUpdate(bool /*ignore*/) {}
-
- virtual bool canBeUpdated() const { return false; }
- virtual QDateTime getExpires() const { return QDateTime(); }
- virtual bool canBeEnabled() const { return false; }
- virtual std::vector<QString> getIniTweaks() const { return std::vector<QString>(); }
-
- virtual std::vector<EFlag> getFlags() const;
- virtual int getHighlight() const;
-
- virtual QString getDescription() const;
- virtual QString name() const;
- virtual QString getGameName() const { return ""; }
- virtual QString getInstallationFile() const { return ""; }
- virtual QString getURL() const { return ""; }
- virtual QString repository() const { return ""; }
- virtual int getNexusFileStatus() const { return 0; }
- virtual void setNexusFileStatus(int) {}
- virtual QDateTime getLastNexusUpdate() const { return QDateTime(); }
- virtual void setLastNexusUpdate(QDateTime) {}
- virtual QDateTime getLastNexusQuery() const { return QDateTime(); }
- virtual void setLastNexusQuery(QDateTime) {}
- virtual QDateTime getNexusLastModified() const { return QDateTime(); }
- virtual void setNexusLastModified(QDateTime) {}
- virtual QDateTime creationTime() const { return QDateTime(); }
-
- virtual void getNexusFiles
- (
- QList<MOBase::ModRepositoryFileInfo*>::const_iterator& /*unused*/,
- QList<MOBase::ModRepositoryFileInfo*>::const_iterator& /*unused*/)
- {
- }
-
- virtual QString getNexusDescription() const { return QString(); }
-
- virtual void addInstalledFile(int /*modId*/, int /*fileId*/)
- {
- }
+protected:
+ virtual bool doTestValid() const override { return true; }
private:
diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp
index 2b4fa11c..d0516d06 100644
--- a/src/modinfowithconflictinfo.cpp
+++ b/src/modinfowithconflictinfo.cpp
@@ -1,4 +1,5 @@
#include "modinfowithconflictinfo.h"
+#include "installationtester.h"
#include "utility.h"
#include "shared/directoryentry.h"
#include "shared/filesorigin.h"
@@ -291,3 +292,33 @@ bool ModInfoWithConflictInfo::hasHiddenFiles() const
return m_HasHiddenFiles;
}
+
+
+bool ModInfoWithConflictInfo::doTestValid() const {
+
+ 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();
+ }
+
+ return valid;
+}
diff --git a/src/modinfowithconflictinfo.h b/src/modinfowithconflictinfo.h
index 460a7f49..0bb7c422 100644
--- a/src/modinfowithconflictinfo.h
+++ b/src/modinfowithconflictinfo.h
@@ -12,27 +12,36 @@ public:
ModInfoWithConflictInfo(PluginContainer *pluginContainer, MOShared::DirectoryEntry **directoryStructure);
- std::vector<ModInfo::EConflictFlag> getConflictFlags() const;
- virtual std::vector<ModInfo::EFlag> getFlags() const;
+ std::vector<ModInfo::EConflictFlag> getConflictFlags() const override;
+ virtual std::vector<ModInfo::EFlag> getFlags() const override;
/**
* @brief clear all caches held for this mod
*/
- virtual void clearCaches();
+ virtual void clearCaches() override;
- virtual std::set<unsigned int> getModOverwrite() { return m_OverwriteList; }
+ virtual std::set<unsigned int> getModOverwrite() const override { return m_OverwriteList; }
- virtual std::set<unsigned int> getModOverwritten() { return m_OverwrittenList; }
+ virtual std::set<unsigned int> getModOverwritten() const override { return m_OverwrittenList; }
- virtual std::set<unsigned int> getModArchiveOverwrite() { return m_ArchiveOverwriteList; }
+ virtual std::set<unsigned int> getModArchiveOverwrite() const override { return m_ArchiveOverwriteList; }
- virtual std::set<unsigned int> getModArchiveOverwritten() { return m_ArchiveOverwrittenList; }
+ virtual std::set<unsigned int> getModArchiveOverwritten() const override { return m_ArchiveOverwrittenList; }
- virtual std::set<unsigned int> getModArchiveLooseOverwrite() { return m_ArchiveLooseOverwriteList; }
+ virtual std::set<unsigned int> getModArchiveLooseOverwrite() const override { return m_ArchiveLooseOverwriteList; }
- virtual std::set<unsigned int> getModArchiveLooseOverwritten() { return m_ArchiveLooseOverwrittenList; }
+ virtual std::set<unsigned int> getModArchiveLooseOverwritten() const override { return m_ArchiveLooseOverwrittenList; }
- virtual void doConflictCheck() const;
+ virtual void doConflictCheck() const override;
+
+protected:
+
+ /**
+ * @brief check if the content of this mod is valid.
+ *
+ * @return true if the content is valid, false otherwize.
+ **/
+ virtual bool doTestValid() const;
private:
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index 1f320982..c2667557 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -185,7 +185,8 @@ void PluginList::refresh(const QString &profileName
ChangeBracket<PluginList> layoutChange(this);
QStringList primaryPlugins = m_GamePlugin->primaryPlugins();
- bool lightPluginsAreSupported = m_GamePlugin->feature<GamePlugins>()->lightPluginsAreSupported();
+ GamePlugins *gamePlugins = m_GamePlugin->feature<GamePlugins>();
+ const bool lightPluginsAreSupported = gamePlugins ? gamePlugins->lightPluginsAreSupported() : false;
m_CurrentProfile = profileName;
@@ -265,8 +266,9 @@ void PluginList::refresh(const QString &profileName
// indices need to work. priority will be off however
updateIndices();
- GamePlugins *gamePlugins = m_GamePlugin->feature<GamePlugins>();
- gamePlugins->readPluginLists(this);
+ if (gamePlugins) {
+ gamePlugins->readPluginLists(this);
+ }
testMasters();
@@ -521,7 +523,9 @@ void PluginList::saveTo(const QString &lockedOrderFileName
, bool hideUnchecked) const
{
GamePlugins *gamePlugins = m_GamePlugin->feature<GamePlugins>();
- gamePlugins->writePluginLists(this);
+ if (gamePlugins) {
+ gamePlugins->writePluginLists(this);
+ }
writeLockedOrder(lockedOrderFileName);
@@ -870,7 +874,10 @@ void PluginList::generatePluginIndexes()
{
int numESLs = 0;
int numSkipped = 0;
- bool lightPluginsSupported = m_GamePlugin->feature<GamePlugins>()->lightPluginsAreSupported();
+
+ GamePlugins* gamePlugins = m_GamePlugin->feature<GamePlugins>();
+ const bool lightPluginsSupported = gamePlugins ? gamePlugins->lightPluginsAreSupported() : false;
+
for (int l = 0; l < m_ESPs.size(); ++l) {
int i = m_ESPsByPriority.at(l);
if (!m_ESPs[i].enabled) {