From 672cefd59422f97bd6257f727e1b201e2139838d Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sun, 7 Jan 2024 16:37:25 +0100 Subject: [PATCH] Track checked EsmFile pointers instead of full paths --- CHANGELOG.md | 1 + apps/launcher/datafilespage.cpp | 24 +------------ .../contentselector/model/contentmodel.cpp | 36 ++++++++----------- .../contentselector/model/contentmodel.hpp | 5 +-- 4 files changed, 20 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 580e9a2143..3f07def9ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,7 @@ Bug #7084: Resurrecting an actor doesn't take into account base record changes Bug #7088: Deleting last save game of last character doesn't clear character name/details Bug #7092: BSA archives from higher priority directories don't take priority + Bug #7103: Multiple paths pointing to the same plugin but with different cases lead to automatically removed config entries Bug #7122: Teleportation to underwater should cancel active water walking effect Bug #7131: MyGUI log spam when post processing HUD is open Bug #7134: Saves with an invalid last generated RefNum can be loaded diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index dc2c07d9bd..114221ce92 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -125,27 +125,6 @@ namespace Launcher { return Settings::navigator().mMaxNavmeshdbFileSize / (1024 * 1024); } - - std::optional findFirstPath(const QStringList& directories, const QString& fileName) - { - for (const QString& directoryPath : directories) - { - const QString filePath = QDir(directoryPath).absoluteFilePath(fileName); - if (QFile::exists(filePath)) - return filePath; - } - return std::nullopt; - } - - QStringList findAllFilePaths(const QStringList& directories, const QStringList& fileNames) - { - QStringList result; - result.reserve(fileNames.size()); - for (const QString& fileName : fileNames) - if (const auto filepath = findFirstPath(directories, fileName)) - result.append(*filepath); - return result; - } } } @@ -366,8 +345,7 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName) row++; } - mSelector->setProfileContent( - findAllFilePaths(directories, mLauncherSettings.getContentListFiles(contentModelName))); + mSelector->setProfileContent(mLauncherSettings.getContentListFiles(contentModelName)); } void Launcher::DataFilesPage::saveSettings(const QString& profile) diff --git a/components/contentselector/model/contentmodel.cpp b/components/contentselector/model/contentmodel.cpp index c3ea050064..5e6db2fd7e 100644 --- a/components/contentselector/model/contentmodel.cpp +++ b/components/contentselector/model/contentmodel.cpp @@ -128,7 +128,7 @@ Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex& index continue; noGameFiles = false; - if (isChecked(depFile->filePath())) + if (mCheckedFiles.contains(depFile)) { gamefileChecked = true; break; @@ -215,7 +215,7 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex& index, int if (file == mGameFile) return QVariant(); - return mCheckStates[file->filePath()]; + return mCheckedFiles.contains(file) ? Qt::Checked : Qt::Unchecked; } case Qt::UserRole: @@ -229,7 +229,7 @@ QVariant ContentSelectorModel::ContentModel::data(const QModelIndex& index, int } case Qt::UserRole + 1: - return isChecked(file->filePath()); + return mCheckedFiles.contains(file); } return QVariant(); } @@ -277,12 +277,12 @@ bool ContentSelectorModel::ContentModel::setData(const QModelIndex& index, const { int checkValue = value.toInt(); bool setState = false; - if ((checkValue == Qt::Checked) && !isChecked(file->filePath())) + if (checkValue == Qt::Checked && !mCheckedFiles.contains(file)) { setState = true; success = true; } - else if ((checkValue == Qt::Checked) && isChecked(file->filePath())) + else if (checkValue == Qt::Checked && mCheckedFiles.contains(file)) setState = true; else if (checkValue == Qt::Unchecked) setState = true; @@ -628,14 +628,6 @@ void ContentSelectorModel::ContentModel::sortFiles() emit layoutChanged(); } -bool ContentSelectorModel::ContentModel::isChecked(const QString& filepath) const -{ - const auto it = mCheckStates.find(filepath); - if (it == mCheckStates.end()) - return false; - return it.value() == Qt::Checked; -} - bool ContentSelectorModel::ContentModel::isEnabled(const QModelIndex& index) const { return (flags(index) & Qt::ItemIsEnabled); @@ -723,7 +715,7 @@ QList ContentSelectorModel::ContentModel:: } else { - if (!isChecked(dependentFile->filePath())) + if (!mCheckedFiles.contains(dependentFile)) { errors.append(LoadOrderError(LoadOrderError::ErrorCode_InactiveDependency, dependentfileName)); } @@ -776,9 +768,13 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString& filepath, Qt::CheckState state = Qt::Unchecked; if (checkState) + { state = Qt::Checked; + mCheckedFiles.insert(file); + } + else + mCheckedFiles.erase(file); - mCheckStates[filepath] = state; emit dataChanged(indexFromItem(item(filepath)), indexFromItem(item(filepath))); if (file->isGameFile()) @@ -794,8 +790,7 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString& filepath, if (!upstreamFile) continue; - if (!isChecked(upstreamFile->filePath())) - mCheckStates[upstreamFile->filePath()] = Qt::Checked; + mCheckedFiles.insert(upstreamFile); emit dataChanged(indexFromItem(upstreamFile), indexFromItem(upstreamFile)); } @@ -810,8 +805,7 @@ bool ContentSelectorModel::ContentModel::setCheckState(const QString& filepath, if (downstreamFile->gameFiles().contains(filename, Qt::CaseInsensitive)) { - if (mCheckStates.contains(downstreamFile->filePath())) - mCheckStates[downstreamFile->filePath()] = Qt::Unchecked; + mCheckedFiles.erase(downstreamFile); emit dataChanged(indexFromItem(downstreamFile), indexFromItem(downstreamFile)); } @@ -829,7 +823,7 @@ ContentSelectorModel::ContentFileList ContentSelectorModel::ContentModel::checke // First search for game files and next addons, // so we get more or less correct game files vs addons order. for (EsmFile* file : mFiles) - if (isChecked(file->filePath())) + if (mCheckedFiles.contains(file)) list << file; return list; @@ -838,6 +832,6 @@ ContentSelectorModel::ContentFileList ContentSelectorModel::ContentModel::checke void ContentSelectorModel::ContentModel::uncheckAll() { emit layoutAboutToBeChanged(); - mCheckStates.clear(); + mCheckedFiles.clear(); emit layoutChanged(); } diff --git a/components/contentselector/model/contentmodel.hpp b/components/contentselector/model/contentmodel.hpp index d56f8f9a3b..1ba3090a32 100644 --- a/components/contentselector/model/contentmodel.hpp +++ b/components/contentselector/model/contentmodel.hpp @@ -7,6 +7,8 @@ #include #include +#include + namespace ContentSelectorModel { class EsmFile; @@ -57,7 +59,6 @@ namespace ContentSelectorModel void setCurrentGameFile(const EsmFile* file); bool isEnabled(const QModelIndex& index) const; - bool isChecked(const QString& filepath) const; bool setCheckState(const QString& filepath, bool isChecked); bool isNew(const QString& filepath) const; void setNew(const QString& filepath, bool isChecked); @@ -85,7 +86,7 @@ namespace ContentSelectorModel const EsmFile* mGameFile; ContentFileList mFiles; QStringList mArchives; - QHash mCheckStates; + std::set mCheckedFiles; QHash mNewFiles; QSet mPluginsWithLoadOrderError; QString mEncoding;