diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp index 9afbfca89..09defe90c 100644 --- a/src/directoryrefresher.cpp +++ b/src/directoryrefresher.cpp @@ -179,10 +179,13 @@ void DirectoryRefresher::setMods( m_Mods.clear(); for (auto mod = mods.begin(); mod != mods.end(); ++mod) { - QString name = std::get<0>(*mod); - ModInfo::Ptr info = ModInfo::getByIndex(ModInfo::getIndex(name)); - m_Mods.push_back(EntryInfo(name, std::get<1>(*mod), info->stealFiles(), - info->archives(), std::get<2>(*mod))); + QString name = std::get<0>(*mod); + ModInfo::Ptr info = ModInfo::getByIndex(ModInfo::getIndex(name)); + QString path = std::get<1>(*mod); + QString modDataDir = m_Core.managedGame()->modDataDirectory(); + path = modDataDir.isEmpty() ? path : path + "/" + modDataDir; + m_Mods.push_back( + EntryInfo(name, path, info->stealFiles(), info->archives(), std::get<2>(*mod))); } m_EnabledArchives = managedArchives; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index aa2c76418..4137c4563 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2916,8 +2916,11 @@ void MainWindow::originModified(int originID) origin.enable(false); DirectoryStats dummy; + QString path = QString::fromStdWString(origin.getPath()); + QString modDataDir = m_OrganizerCore.managedGame()->modDataDirectory(); + path = modDataDir.isEmpty() ? path : path + "/" + modDataDir; m_OrganizerCore.directoryStructure()->addFromOrigin( - origin.getName(), origin.getPath(), origin.getPriority(), dummy); + origin.getName(), path.toStdWString(), origin.getPriority(), dummy); DirectoryRefresher::cleanStructure(m_OrganizerCore.directoryStructure()); } diff --git a/src/moapplication.cpp b/src/moapplication.cpp index cac60f480..4640540f8 100644 --- a/src/moapplication.cpp +++ b/src/moapplication.cpp @@ -287,6 +287,7 @@ int MOApplication::setup(MOMultiProcess& multiProcess, bool forceSelect) // setting up organizer core m_core->setManagedGame(m_instance->gamePlugin()); m_core->createDefaultProfile(); + m_core->createOverwriteDirectories(); log::info("using game plugin '{}' ('{}', variant {}, steam id '{}') at {}", m_instance->gamePlugin()->gameName(), diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index 1798e9870..04ef003a8 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -571,25 +571,30 @@ void ModInfoDialog::updateTabs(bool becauseOriginChanged) void ModInfoDialog::feedFiles(std::vector& interestedTabs) { - const auto rootPath = m_mod->absolutePath(); + const auto rootPath = + m_mod->absolutePath() + (m_core.managedGame()->modDataDirectory().isEmpty() + ? "" + : "/" + m_core.managedGame()->modDataDirectory()); if (rootPath.isEmpty()) { return; } - const fs::path fsPath(rootPath.toStdWString()); + if (fs::exists(rootPath.toStdWString())) { + const fs::path fsPath(rootPath.toStdWString()); - for (const auto& entry : fs::recursive_directory_iterator(fsPath)) { - if (!entry.is_regular_file()) { - // skip directories - continue; - } + for (const auto& entry : fs::recursive_directory_iterator(fsPath)) { + if (!entry.is_regular_file()) { + // skip directories + continue; + } - const auto filePath = QString::fromStdWString(entry.path().native()); + const auto filePath = QString::fromStdWString(entry.path().native()); - // for each tab - for (auto* tabInfo : interestedTabs) { - if (tabInfo->tab->feedFile(rootPath, filePath)) { - break; + // for each tab + for (auto* tabInfo : interestedTabs) { + if (tabInfo->tab->feedFile(rootPath, filePath)) { + break; + } } } } diff --git a/src/modinfooverwrite.cpp b/src/modinfooverwrite.cpp index 9d0ed5f9d..c65cbace4 100644 --- a/src/modinfooverwrite.cpp +++ b/src/modinfooverwrite.cpp @@ -3,6 +3,7 @@ #include "settings.h" #include "shared/appconfig.h" +#include "organizercore.h" #include #include @@ -14,10 +15,24 @@ bool ModInfoOverwrite::isEmpty() const QDirIterator iter(absolutePath(), QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); if (!iter.hasNext()) return true; - iter.next(); - if ((iter.fileName() == "meta.ini") && !iter.hasNext()) - return true; - return false; + while (iter.hasNext()) { + iter.next(); + if (iter.fileInfo().isDir() && + !m_Core.managedGame()->getModMappings().keys().contains(iter.fileName(), + Qt::CaseInsensitive)) + return false; + if (iter.fileInfo().isDir() && + m_Core.managedGame()->getModMappings().keys().contains(iter.fileName(), + Qt::CaseInsensitive)) { + if (QDir(iter.filePath()).count() > 2) { + return false; + } + } + if (iter.fileInfo().isFile() && iter.fileName() != "meta.ini") + return false; + } + + return true; } QString ModInfoOverwrite::absolutePath() const diff --git a/src/modlist.cpp b/src/modlist.cpp index 8945dea11..4ef3afbc9 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -1028,15 +1028,50 @@ bool ModList::dropLocalFiles(const ModListDropInfo& dropInfo, int row, QList> relativePathList; for (auto localUrl : dropInfo.localUrls()) { - QFileInfo sourceInfo(localUrl.url.toLocalFile()); - QString sourceFile = sourceInfo.canonicalFilePath(); + if (localUrl.originName.compare("overwrite", Qt::CaseInsensitive) == 0) { + bool needsMove = true; + if (sourceInfo.isDir()) { + for (auto dir : m_Organizer->managedGame()->getModMappings().keys()) { + QDir overDir(m_Organizer->overwritePath()); + if (sourceInfo.canonicalFilePath().compare(overDir.absoluteFilePath(dir), + Qt::CaseInsensitive) == 0) { + needsMove = false; + + QDirIterator dirIter(overDir.absoluteFilePath(dir), + QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); + while (dirIter.hasNext()) { + auto entry = dirIter.nextFileInfo(); + QString sourceFile = entry.canonicalFilePath(); + + QFileInfo targetInfo(modDir.absoluteFilePath( + overDir.relativeFilePath(entry.absoluteFilePath()))); + sourceList << sourceFile; + targetList << targetInfo.absoluteFilePath(); + relativePathList << QPair(localUrl.relativePath, + localUrl.originName); + } + } + } + } + if (needsMove) { + QString sourceFile = sourceInfo.canonicalFilePath(); + + QFileInfo targetInfo(modDir.absoluteFilePath(localUrl.relativePath)); + sourceList << sourceFile; + targetList << targetInfo.absoluteFilePath(); + relativePathList << QPair(localUrl.relativePath, + localUrl.originName); + } + } else { + QString sourceFile = sourceInfo.canonicalFilePath(); - QFileInfo targetInfo(modDir.absoluteFilePath(localUrl.relativePath)); - sourceList << sourceFile; - targetList << targetInfo.absoluteFilePath(); - relativePathList << QPair(localUrl.relativePath, - localUrl.originName); + QFileInfo targetInfo(modDir.absoluteFilePath(localUrl.relativePath)); + sourceList << sourceFile; + targetList << targetInfo.absoluteFilePath(); + relativePathList << QPair(localUrl.relativePath, + localUrl.originName); + } } if (sourceList.count()) { diff --git a/src/modlistviewactions.cpp b/src/modlistviewactions.cpp index a38e876b1..efe48c313 100644 --- a/src/modlistviewactions.cpp +++ b/src/modlistviewactions.cpp @@ -548,7 +548,7 @@ void ModListViewActions::displayModInformation(ModInfo::Ptr modInfo, QDialog* dialog = m_parent->findChild("__overwriteDialog"); try { if (dialog == nullptr) { - dialog = new OverwriteInfoDialog(modInfo, m_parent); + dialog = new OverwriteInfoDialog(modInfo, m_core, m_parent); dialog->setObjectName("__overwriteDialog"); } else { qobject_cast(dialog)->setModInfo(modInfo); @@ -599,10 +599,12 @@ void ModListViewActions::displayModInformation(ModInfo::Ptr modInfo, FilesOrigin& origin = m_core.directoryStructure()->getOriginByName(ToWString(modInfo->name())); origin.enable(false); - + QString path = modInfo->absolutePath(); + QString modDataDir = m_core.managedGame()->modDataDirectory(); + path = modDataDir.isEmpty() ? path : path + "/" + modDataDir; m_core.directoryRefresher()->addModToStructure( m_core.directoryStructure(), modInfo->name(), - m_core.currentProfile()->getModPriority(modIndex), modInfo->absolutePath(), + m_core.currentProfile()->getModPriority(modIndex), path, modInfo->stealFiles(), modInfo->archives()); DirectoryRefresher::cleanStructure(m_core.directoryStructure()); m_core.directoryStructure()->getFileRegister()->sortOrigins(); @@ -1299,9 +1301,42 @@ void ModListViewActions::restoreBackup(const QModelIndex& index) const void ModListViewActions::moveOverwriteContentsTo(const QString& absolutePath) const { ModInfo::Ptr overwriteInfo = ModInfo::getOverwrite(); - bool successful = - shellMove((QDir::toNativeSeparators(overwriteInfo->absolutePath()) + "\\*"), - (QDir::toNativeSeparators(absolutePath)), false, m_parent); + bool successful = false; + if (m_core.managedGame()->getModMappings().count() > 1 || + m_core.managedGame()->getModMappings().keys().first() != "") { + QDirIterator iter(overwriteInfo->absolutePath(), + QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); + while (iter.hasNext()) { + auto entry = iter.nextFileInfo(); + if (entry.isDir() && m_core.managedGame()->getModMappings().keys().contains( + entry.fileName(), Qt::CaseInsensitive)) { + successful = + shellCopy((QDir::toNativeSeparators(entry.absolutePath())), + (QDir::toNativeSeparators(absolutePath)), false, m_parent); + QDirIterator subDirIter(entry.absoluteFilePath(), + QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); + while (subDirIter.hasNext()) { + auto subDirEntry = subDirIter.nextFileInfo(); + if (subDirEntry.isDir()) { + QDir(subDirEntry.absoluteFilePath()).removeRecursively(); + } else { + QFile(subDirEntry.absoluteFilePath()).remove(); + } + } + } else { + successful = + shellMove((QDir::toNativeSeparators(iter.filePath())), + (QDir::toNativeSeparators(absolutePath)), false, m_parent); + } + if (!successful) + break; + } + + } else { + successful = + shellMove((QDir::toNativeSeparators(overwriteInfo->absolutePath()) + "\\*"), + (QDir::toNativeSeparators(absolutePath)), false, m_parent); + } if (successful) { MessageDialog::showMessage(tr("Move successful."), m_parent); @@ -1396,9 +1431,19 @@ void ModListViewActions::clearOverwrite() const tr("About to recursively delete:\n") + overwriteDir.absolutePath(), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { QStringList delList; - for (auto f : - overwriteDir.entryList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot)) - delList.push_back(overwriteDir.absoluteFilePath(f)); + for (auto f : overwriteDir.entryInfoList(QDir::AllDirs | QDir::Files | + QDir::NoDotAndDotDot)) { + if (f.isDir() && m_core.managedGame()->getModMappings().keys().contains( + f.fileName(), Qt::CaseInsensitive)) { + for (auto sf : + QDir(f.absoluteFilePath()) + .entryInfoList(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot)) { + delList.push_back(sf.absoluteFilePath()); + } + } else { + delList.push_back(f.absoluteFilePath()); + } + } if (shellDelete(delList, true)) { emit overwriteCleared(); m_core.refresh(); diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 19439d76a..4eac3d66d 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -462,6 +462,16 @@ void OrganizerCore::createDefaultProfile() } } +void OrganizerCore::createOverwriteDirectories() +{ + QString overwritePath = settings().paths().overwrite(); + for (auto modDirectory : managedGame()->getModMappings().keys()) { + if (!modDirectory.isEmpty()) { + QDir(overwritePath).mkdir(modDirectory); + } + } +} + void OrganizerCore::prepareVFS() { m_USVFS.updateMapping(fileMapping(m_CurrentProfile->name(), QString())); @@ -1396,8 +1406,11 @@ void OrganizerCore::updateModsInDirectoryStructure( std::vector entries; for (auto idx : modInfo.keys()) { + QString path = modInfo[idx]->absolutePath(); + QString modDataDir = managedGame()->modDataDirectory(); + path = modDataDir.isEmpty() ? path : path + "/" + modDataDir; entries.push_back({modInfo[idx]->name(), - modInfo[idx]->absolutePath(), + path, modInfo[idx]->stealFiles(), {}, m_CurrentProfile->getModPriority(idx)}); @@ -1426,10 +1439,12 @@ void OrganizerCore::updateModsInDirectoryStructure( // finally also add files from bsas to the directory structure for (auto idx : modInfo.keys()) { + QString path = modInfo[idx]->absolutePath(); + QString modDataDir = managedGame()->modDataDirectory(); + path = modDataDir.isEmpty() ? path : path + "/" + modDataDir; m_DirectoryRefresher->addModBSAToStructure( m_DirectoryStructure, modInfo[idx]->name(), - m_CurrentProfile->getModPriority(idx), modInfo[idx]->absolutePath(), - modInfo[idx]->archives()); + m_CurrentProfile->getModPriority(idx), path, modInfo[idx]->archives()); } } @@ -2034,12 +2049,7 @@ std::vector OrganizerCore::fileMapping(const QString& profileName, MappingType result; - QStringList dataPaths; - dataPaths.append(QDir::toNativeSeparators(game->dataDirectory().absolutePath())); - - for (auto directory : game->secondaryDataDirectories()) { - dataPaths.append(directory.absolutePath()); - } + auto dataMaps = game->getModMappings(); bool overwriteActive = false; @@ -2052,13 +2062,19 @@ std::vector OrganizerCore::fileMapping(const QString& profileName, ModInfo::Ptr modPtr = ModInfo::getByIndex(modIndex); bool createTarget = customOverwrite == std::get<0>(mod); + QDir modDir = QDir(std::get<1>(mod)); overwriteActive |= createTarget; if (modPtr->isRegular()) { - for (auto dataPath : dataPaths) { - result.insert(result.end(), {QDir::toNativeSeparators(std::get<1>(mod)), - dataPath, true, createTarget}); + for (auto dataMap : dataMaps.asKeyValueRange()) { + auto mapDir = QDir(modDir.absoluteFilePath(dataMap.first)); + if (mapDir.exists()) { + for (auto dir : dataMap.second) { + result.insert(result.end(), + {mapDir.absolutePath(), dir, true, createTarget}); + } + } } } } @@ -2080,10 +2096,15 @@ std::vector OrganizerCore::fileMapping(const QString& profileName, } } - for (auto dataPath : dataPaths) { - result.insert(result.end(), - {QDir::toNativeSeparators(m_Settings.paths().overwrite()), dataPath, - true, customOverwrite.isEmpty()}); + QDir overwriteDir(m_Settings.paths().overwrite()); + for (auto dataMap : dataMaps.asKeyValueRange()) { + auto overwriteSubpath = overwriteDir.absoluteFilePath(dataMap.first); + if (QDir(overwriteSubpath).exists()) { + for (auto dir : dataMap.second) { + result.insert(result.end(), + {overwriteSubpath, dir, true, customOverwrite.isEmpty()}); + } + } } for (MOBase::IPluginFileMapper* mapper : diff --git a/src/organizercore.h b/src/organizercore.h index 923adc12d..3e0cdbba5 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -332,6 +332,7 @@ class OrganizerCore : public QObject, public MOBase::IPluginDiagnose bool checkPathSymlinks(); bool bootstrap(); void createDefaultProfile(); + void createOverwriteDirectories(); MOBase::DelayedFileWriter& pluginsWriter() { return m_PluginListsWriter; } diff --git a/src/overwriteinfodialog.cpp b/src/overwriteinfodialog.cpp index 366671e7c..11e6fc324 100644 --- a/src/overwriteinfodialog.cpp +++ b/src/overwriteinfodialog.cpp @@ -18,7 +18,6 @@ along with Mod Organizer. If not, see . */ #include "overwriteinfodialog.h" -#include "organizercore.h" #include "report.h" #include "ui_overwriteinfodialog.h" #include "utility.h" @@ -29,15 +28,17 @@ along with Mod Organizer. If not, see . using namespace MOBase; -OverwriteInfoDialog::OverwriteInfoDialog(ModInfo::Ptr modInfo, QWidget* parent) - : QDialog(parent), ui(new Ui::OverwriteInfoDialog), m_FileSystemModel(nullptr), - m_DeleteAction(nullptr), m_RenameAction(nullptr), m_OpenAction(nullptr) +OverwriteInfoDialog::OverwriteInfoDialog(ModInfo::Ptr modInfo, OrganizerCore& organizer, + QWidget* parent) + : QDialog(parent), m_Organizer(organizer), ui(new Ui::OverwriteInfoDialog), + m_FileSystemModel(nullptr), m_DeleteAction(nullptr), m_RenameAction(nullptr), + m_OpenAction(nullptr) { ui->setupUi(this); this->setWindowModality(Qt::NonModal); - m_FileSystemModel = new OverwriteFileSystemModel(this); + m_FileSystemModel = new OverwriteFileSystemModel(this, organizer); m_FileSystemModel->setReadOnly(false); setModInfo(modInfo); ui->filesView->setModel(m_FileSystemModel); @@ -137,10 +138,19 @@ void OverwriteInfoDialog::delete_activated() QItemSelectionModel* selection = ui->filesView->selectionModel(); if (selection->hasSelection() && selection->selectedRows().count() >= 1) { + auto root = m_FileSystemModel->rootDirectory(); if (selection->selectedRows().count() == 0) { return; } else if (selection->selectedRows().count() == 1) { + for (auto modDir : m_Organizer.managedGame()->getModMappings().keys()) { + if (root.absoluteFilePath(modDir).compare( + m_FileSystemModel->filePath(selection->selectedRows().at(0)), + Qt::CaseInsensitive) == 0) { + return; + } + } + QString fileName = m_FileSystemModel->fileName(selection->selectedRows().at(0)); if (QMessageBox::question( this, tr("Confirm"), @@ -158,6 +168,12 @@ void OverwriteInfoDialog::delete_activated() } foreach (QModelIndex index, selection->selectedRows()) { + for (auto modDir : m_Organizer.managedGame()->getModMappings().keys()) { + if (root.absoluteFilePath(modDir).compare(m_FileSystemModel->filePath(index), + Qt::CaseInsensitive) == 0) { + return; + } + } deleteFile(index); } } @@ -166,9 +182,17 @@ void OverwriteInfoDialog::delete_activated() void OverwriteInfoDialog::deleteTriggered() { + auto root = m_FileSystemModel->rootDirectory(); if (m_FileSelection.count() == 0) { return; } else if (m_FileSelection.count() == 1) { + for (auto modDir : m_Organizer.managedGame()->getModMappings().keys()) { + if (root.absoluteFilePath(modDir).compare( + m_FileSystemModel->filePath(m_FileSelection.at(0)), + Qt::CaseInsensitive) == 0) { + return; + } + } QString fileName = m_FileSystemModel->fileName(m_FileSelection.at(0)); if (QMessageBox::question( this, tr("Confirm"), @@ -185,18 +209,30 @@ void OverwriteInfoDialog::deleteTriggered() } foreach (QModelIndex index, m_FileSelection) { + for (auto modDir : m_Organizer.managedGame()->getModMappings().keys()) { + if (root.absoluteFilePath(modDir).compare(m_FileSystemModel->filePath(index), + Qt::CaseInsensitive) == 0) { + return; + } + } deleteFile(index); } } void OverwriteInfoDialog::renameTriggered() { + auto root = m_FileSystemModel->rootDirectory(); QModelIndex selection = m_FileSelection.at(0); QModelIndex index = selection.sibling(selection.row(), 0); if (!index.isValid() || m_FileSystemModel->isReadOnly()) { return; } - + for (auto modDir : m_Organizer.managedGame()->getModMappings().keys()) { + if (root.absoluteFilePath(modDir).compare(m_FileSystemModel->filePath(selection), + Qt::CaseInsensitive) == 0) { + return; + } + } ui->filesView->edit(index); } diff --git a/src/overwriteinfodialog.h b/src/overwriteinfodialog.h index e9fa34397..59f6f7522 100644 --- a/src/overwriteinfodialog.h +++ b/src/overwriteinfodialog.h @@ -21,6 +21,8 @@ along with Mod Organizer. If not, see . #define OVERWRITEINFODIALOG_H #include "modinfo.h" +#include "modlistdropinfo.h" +#include "organizercore.h" #include #include @@ -34,8 +36,8 @@ class OverwriteFileSystemModel : public QFileSystemModel Q_OBJECT; public: - OverwriteFileSystemModel(QObject* parent) - : QFileSystemModel(parent), m_RegularColumnCount(0) + OverwriteFileSystemModel(QObject* parent, OrganizerCore& organizer) + : QFileSystemModel(parent), m_Organizer(organizer), m_RegularColumnCount(0) {} virtual int columnCount(const QModelIndex& parent) const @@ -70,8 +72,27 @@ class OverwriteFileSystemModel : public QFileSystemModel } } + virtual bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, + int column, const QModelIndex& parent) + { + ModListDropInfo dropInfo(data, m_Organizer); + if (dropInfo.isLocalFileDrop()) { + for (auto entry : dropInfo.localUrls()) { + QFileInfo sourceInfo(entry.url.toLocalFile()); + if (sourceInfo.isDir() && + m_Organizer.managedGame()->getModMappings().keys().contains( + entry.relativePath, Qt::CaseInsensitive)) { + return false; + } + } + } + return QFileSystemModel::dropMimeData(data, action, row, column, parent); + } + private: mutable int m_RegularColumnCount; + + OrganizerCore& m_Organizer; }; class OverwriteInfoDialog : public QDialog @@ -79,7 +100,8 @@ class OverwriteInfoDialog : public QDialog Q_OBJECT public: - explicit OverwriteInfoDialog(ModInfo::Ptr modInfo, QWidget* parent = 0); + explicit OverwriteInfoDialog(ModInfo::Ptr modInfo, OrganizerCore& organizer, + QWidget* parent = 0); ~OverwriteInfoDialog(); ModInfo::Ptr modInfo() const { return m_ModInfo; } @@ -122,6 +144,7 @@ private slots: QAction* m_NewFolderAction; ModInfo::Ptr m_ModInfo; + OrganizerCore& m_Organizer; }; #endif // OVERWRITEINFODIALOG_H diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index fc468cef5..622845439 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -147,10 +147,18 @@ void PluginList::highlightPlugins(const std::vector& modIndices, for (auto& modIndex : modIndices) { ModInfo::Ptr selectedMod = ModInfo::getByIndex(modIndex); if (!selectedMod.isNull() && profile->modEnabled(modIndex)) { - QDir dir(selectedMod->absolutePath()); - QStringList plugins = dir.entryList(QStringList() << "*.esp" - << "*.esm" - << "*.esl"); + QString modDataPath = selectedMod->absolutePath(); + modDataPath = + m_Organizer.managedGame()->modDataDirectory().isEmpty() + ? modDataPath + : modDataPath + "/" + m_Organizer.managedGame()->modDataDirectory(); + QDir dir(modDataPath); + QStringList plugins; + if (dir.exists()) { + plugins = dir.entryList(QStringList() << "*.esp" + << "*.esm" + << "*.esl"); + } const MOShared::FilesOrigin& origin = directoryEntry.getOriginByName(selectedMod->internalName().toStdWString()); if (plugins.size() > 0) { diff --git a/src/savestab.cpp b/src/savestab.cpp index 2cbd17de9..f59245cb0 100644 --- a/src/savestab.cpp +++ b/src/savestab.cpp @@ -4,6 +4,7 @@ #include "ui_mainwindow.h" #include #include +#include using namespace MOBase; @@ -128,13 +129,15 @@ void SavesTab::refreshSavesIfOpen() QDir SavesTab::currentSavesDir() const { + // TODO: This code should probably be handled by the game plugins QDir savesDir; if (m_core.currentProfile()->localSavesEnabled()) { savesDir.setPath(m_core.currentProfile()->savePath()); } else { auto iniFiles = m_core.managedGame()->iniFiles(); - if (iniFiles.isEmpty()) { + if (iniFiles.isEmpty() || + m_core.gameFeatures().gameFeature() == nullptr) { return m_core.managedGame()->savesDirectory(); } diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 01c325ef1..6351083bc 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -24,6 +24,7 @@ along with Mod Organizer. If not, see . #include "originconnection.h" #include "util.h" #include "windows_error.h" +#include #include #include @@ -630,19 +631,21 @@ void DirectoryEntry::addFiles(env::DirectoryWalker& walker, FilesOrigin& origin, Context cx = {origin, stats}; cx.current.push(this); - walker.forEachEntry( - path, &cx, - [](void* pcx, std::wstring_view path) { - onDirectoryStart((Context*)pcx, path); - }, + if (std::filesystem::exists(path)) { + walker.forEachEntry( + path, &cx, + [](void* pcx, std::wstring_view path) { + onDirectoryStart((Context*)pcx, path); + }, - [](void* pcx, std::wstring_view path) { - onDirectoryEnd((Context*)pcx, path); - }, + [](void* pcx, std::wstring_view path) { + onDirectoryEnd((Context*)pcx, path); + }, - [](void* pcx, std::wstring_view path, FILETIME ft, uint64_t) { - onFile((Context*)pcx, path, ft); - }); + [](void* pcx, std::wstring_view path, FILETIME ft, uint64_t) { + onFile((Context*)pcx, path, ft); + }); + } } void DirectoryEntry::onDirectoryStart(Context* cx, std::wstring_view path)