summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonathan Feenstra <26406078+JonathanFeenstra@users.noreply.github.com>2025-05-23 09:23:36 +0200
committerGitHub <noreply@github.com>2025-05-23 09:23:36 +0200
commita823d2aa88bd00d10370d5516c4426e8780435f7 (patch)
treed0b78481cc4c8b3f0edcc01c9f3714070e49dfca /src
parentb531bbff39bfe6df18e324b0d0785eb1f8e0163d (diff)
Ignore conflicts between hidden files (#2148)
* Ignore conflicts between hidden files * Optimize checks for .mohidden extension
Diffstat (limited to 'src')
-rw-r--r--src/filetreemodel.cpp17
-rw-r--r--src/modinfodialogconflicts.cpp122
-rw-r--r--src/modinfodialogconflicts.h3
-rw-r--r--src/modinfowithconflictinfo.cpp53
4 files changed, 114 insertions, 81 deletions
diff --git a/src/filetreemodel.cpp b/src/filetreemodel.cpp
index 5a6f6a2c..de6194ff 100644
--- a/src/filetreemodel.cpp
+++ b/src/filetreemodel.cpp
@@ -9,6 +9,7 @@
using namespace MOBase;
using namespace MOShared;
+namespace fs = std::filesystem;
// in mainwindow.cpp
QString UnmanagedModName();
@@ -969,8 +970,11 @@ void FileTreeModel::updateFileItem(FileTreeItem& item, const MOShared::FileEntry
bool FileTreeModel::shouldShowFile(const FileEntry& file) const
{
- if (showConflictsOnly() && (file.getAlternatives().size() == 0)) {
- // only conflicts should be shown, but this file is not conflicted
+ if (showConflictsOnly() &&
+ ((file.getAlternatives().size() == 0) ||
+ QString::fromStdWString(file.getName())
+ .endsWith(ModInfo::s_HiddenExt, Qt::CaseInsensitive))) {
+ // only conflicts should be shown, but this file is hidden or not conflicted
return false;
}
@@ -979,8 +983,8 @@ bool FileTreeModel::shouldShowFile(const FileEntry& file) const
return false;
}
- if (!showHiddenFiles() &&
- file.getName().ends_with(ModInfo::s_HiddenExt.toStdWString())) {
+ if (!showHiddenFiles() && QString::fromStdWString(file.getName())
+ .endsWith(ModInfo::s_HiddenExt, Qt::CaseInsensitive)) {
// hidden files shouldn't be shown, but this file is hidden
return false;
}
@@ -991,8 +995,9 @@ bool FileTreeModel::shouldShowFile(const FileEntry& file) const
bool FileTreeModel::shouldShowFolder(const DirectoryEntry& dir,
const FileTreeItem* item) const
{
- if (!showHiddenFiles() &&
- dir.getName().ends_with(ModInfo::s_HiddenExt.toStdWString())) {
+ if ((!showHiddenFiles() || showConflictsOnly()) &&
+ QString::fromStdWString(dir.getName())
+ .endsWith(ModInfo::s_HiddenExt, Qt::CaseInsensitive)) {
return false;
}
diff --git a/src/modinfodialogconflicts.cpp b/src/modinfodialogconflicts.cpp
index 715214b3..f405f0e1 100644
--- a/src/modinfodialogconflicts.cpp
+++ b/src/modinfodialogconflicts.cpp
@@ -11,6 +11,7 @@
using namespace MOShared;
using namespace MOBase;
+namespace fs = std::filesystem;
// if there are more than 50 selected items in the conflict tree, don't bother
// checking whether menu items apply to them, just show all of them
@@ -110,7 +111,7 @@ bool ConflictsTab::canHandleUnmanaged() const
return true;
}
-void ConflictsTab::changeItemsVisibility(QTreeView* tree, bool visible)
+void ConflictsTab::hideItems(QTreeView* tree)
{
bool changed = false;
bool stop = false;
@@ -119,19 +120,16 @@ void ConflictsTab::changeItemsVisibility(QTreeView* tree, bool visible)
// logging
{
- const QString action = (visible ? "unhiding" : "hiding");
-
QString files;
if (n > max_small_selection)
files = "a lot of";
else
files = QString("%1").arg(n);
- log::debug("{} {} conflict files", action, files);
+ log::debug("hiding {} conflict files", files);
}
- QFlags<FileRenamer::RenameFlags> flags =
- (visible ? FileRenamer::UNHIDE : FileRenamer::HIDE);
+ QFlags<FileRenamer::RenameFlags> flags = FileRenamer::HIDE;
if (n > 1) {
flags |= FileRenamer::MULTIPLE;
@@ -158,25 +156,13 @@ void ConflictsTab::changeItemsVisibility(QTreeView* tree, bool visible)
return false;
}
- auto result = FileRenamer::RESULT_CANCEL;
-
- if (visible) {
- if (!item->canUnhide()) {
- log::debug("cannot unhide {}, skipping", item->relativeName());
- return true;
- }
-
- result = unhideFile(renamer, item->fileName());
-
- } else {
- if (!item->canHide()) {
- log::debug("cannot hide {}, skipping", item->relativeName());
- return true;
- }
-
- result = hideFile(renamer, item->fileName());
+ if (!item->canHide()) {
+ log::debug("cannot hide {}, skipping", item->relativeName());
+ return true;
}
+ auto result = hideFile(renamer, item->fileName());
+
switch (result) {
case FileRenamer::RESULT_OK: {
// will trigger a refresh at the end
@@ -199,7 +185,7 @@ void ConflictsTab::changeItemsVisibility(QTreeView* tree, bool visible)
return true;
});
- log::debug("{} conflict files done", (visible ? "unhiding" : "hiding"));
+ log::debug("hiding conflict files done");
if (changed) {
log::debug("triggering refresh");
@@ -351,21 +337,12 @@ void ConflictsTab::showContextMenu(const QPoint& pos, QTreeView* tree)
// hide
if (actions.hide) {
connect(actions.hide, &QAction::triggered, [&] {
- changeItemsVisibility(tree, false);
+ hideItems(tree);
});
menu.addAction(actions.hide);
}
- // unhide
- if (actions.unhide) {
- connect(actions.unhide, &QAction::triggered, [&] {
- changeItemsVisibility(tree, true);
- });
-
- menu.addAction(actions.unhide);
- }
-
if (!menu.isEmpty()) {
if (actions.open || actions.preview || actions.runHooked) {
// bold the first option
@@ -386,7 +363,6 @@ ConflictsTab::Actions ConflictsTab::createMenuActions(QTreeView* tree)
}
bool enableHide = true;
- bool enableUnhide = true;
bool enableRun = true;
bool enableOpen = true;
bool enablePreview = true;
@@ -421,7 +397,6 @@ ConflictsTab::Actions ConflictsTab::createMenuActions(QTreeView* tree)
}
enableHide = item->canHide();
- enableUnhide = item->canUnhide();
enableRun = item->canRun();
enableOpen = item->canOpen();
enablePreview = item->canPreview(plugin());
@@ -443,19 +418,14 @@ ConflictsTab::Actions ConflictsTab::createMenuActions(QTreeView* tree)
if (n <= max_small_selection) {
// if the number of selected items is low, checking them to accurately
// show the menu items is worth it
- enableHide = false;
- enableUnhide = false;
+ enableHide = false;
forEachInSelection(tree, [&](const ConflictItem* item) {
if (item->canHide()) {
enableHide = true;
}
- if (item->canUnhide()) {
- enableUnhide = true;
- }
-
- if (enableHide && enableUnhide && enableGoto) {
+ if (enableHide && enableGoto) {
// found all, no need to check more
return false;
}
@@ -487,11 +457,6 @@ ConflictsTab::Actions ConflictsTab::createMenuActions(QTreeView* tree)
actions.hide = new QAction(tr("&Hide"), parentWidget());
actions.hide->setEnabled(enableHide);
- // note that it is possible for hidden files to appear if they override other
- // hidden files from another mod
- actions.unhide = new QAction(tr("&Unhide"), parentWidget());
- actions.unhide->setEnabled(enableUnhide);
-
if (enableGoto && n == 1) {
const auto* item =
model->getItem(static_cast<std::size_t>(modelSel.indexes()[0].row()));
@@ -633,8 +598,39 @@ bool GeneralConflictsTab::update()
if (m_tab->origin() != nullptr) {
const auto rootPath = m_tab->mod().absolutePath();
+ std::set<const DirectoryEntry*> checkedDirs;
for (const auto& file : m_tab->origin()->getFiles()) {
+ if (QString::fromStdWString(file->getName())
+ .endsWith(ModInfo::s_HiddenExt, Qt::CaseInsensitive)) {
+ // skip hidden file conflicts
+ continue;
+ } else {
+ const DirectoryEntry* parent = file->getParent();
+ auto hidden = false;
+ // iterate on all parent directory entries to check for .mohiddden
+ while (parent != nullptr) {
+ auto insertResult = checkedDirs.insert(parent);
+
+ if (insertResult.second == false) {
+ // if already present break as we can assume to have checked the parents as
+ // well
+ break;
+ } else {
+ if (QString::fromStdWString(parent->getName())
+ .endsWith(ModInfo::s_HiddenExt, Qt::CaseInsensitive)) {
+ hidden = true;
+ break;
+ }
+ parent = parent->getParent();
+ }
+ }
+ if (hidden) {
+ // skip hidden file conflicts
+ continue;
+ }
+ }
+
// careful: these two strings are moved into createXItem() below
QString relativeName =
QDir::fromNativeSeparators(ToQString(file->getRelativePath()));
@@ -954,8 +950,38 @@ void AdvancedConflictsTab::update()
const auto& files = m_tab->origin()->getFiles();
m_model->reserve(files.size());
+ std::set<const DirectoryEntry*> checkedDirs;
for (const auto& file : files) {
+ if (QString::fromStdWString(file->getName())
+ .endsWith(ModInfo::s_HiddenExt, Qt::CaseInsensitive)) {
+ // skip hidden file conflicts
+ continue;
+ } else {
+ const DirectoryEntry* parent = file->getParent();
+ auto hidden = false;
+ // iterate on all parent directory entries to check for .mohiddden
+ while (parent != nullptr) {
+ auto insertResult = checkedDirs.insert(parent);
+
+ if (insertResult.second == false) {
+ // if already present break as we can assume to have checked the parents as
+ // well
+ break;
+ } else {
+ if (QString::fromStdWString(parent->getName())
+ .endsWith(ModInfo::s_HiddenExt, Qt::CaseInsensitive)) {
+ hidden = true;
+ break;
+ }
+ parent = parent->getParent();
+ }
+ }
+ if (hidden) {
+ // skip hidden file conflicts
+ continue;
+ }
+ }
// careful: these two strings are moved into createItem() below
QString relativeName =
QDir::fromNativeSeparators(ToQString(file->getRelativePath()));
diff --git a/src/modinfodialogconflicts.h b/src/modinfodialogconflicts.h
index f1edd33a..4bbd469f 100644
--- a/src/modinfodialogconflicts.h
+++ b/src/modinfodialogconflicts.h
@@ -135,7 +135,7 @@ public:
void openItem(const ConflictItem* item, bool hooked);
void previewItem(const ConflictItem* item);
- void changeItemsVisibility(QTreeView* tree, bool visible);
+ void hideItems(QTreeView* tree);
void showContextMenu(const QPoint& pos, QTreeView* tree);
@@ -143,7 +143,6 @@ private:
struct Actions
{
QAction* hide = nullptr;
- QAction* unhide = nullptr;
QAction* open = nullptr;
QAction* runHooked = nullptr;
QAction* preview = nullptr;
diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp
index df2dc7ce..af43433d 100644
--- a/src/modinfowithconflictinfo.cpp
+++ b/src/modinfowithconflictinfo.cpp
@@ -98,6 +98,7 @@ ModInfoWithConflictInfo::Conflicts ModInfoWithConflictInfo::doConflictCheck() co
bool providesAnything = false;
bool hasHiddenFiles = false;
+ bool hasVisibleFiles = false;
std::vector<int> dataIDs;
if (m_Core.directoryStructure()->originExists(L"data")) {
@@ -110,8 +111,7 @@ ModInfoWithConflictInfo::Conflicts ModInfoWithConflictInfo::doConflictCheck() co
}
}
- std::wstring name = ToWString(this->name());
- const std::wstring hideExt = ToWString(ModInfo::s_HiddenExt);
+ std::wstring name = ToWString(this->name());
if (m_Core.directoryStructure()->originExists(name)) {
FilesOrigin& origin = m_Core.directoryStructure()->getOriginByName(name);
@@ -120,36 +120,39 @@ ModInfoWithConflictInfo::Conflicts ModInfoWithConflictInfo::doConflictCheck() co
// for all files in this origin
for (FileEntryPtr file : files) {
+ if (QString::fromStdWString(file->getName())
+ .endsWith(ModInfo::s_HiddenExt, Qt::CaseInsensitive)) {
+ hasHiddenFiles = true;
+ // skip hidden file conflicts
+ continue;
+ } else {
+ const DirectoryEntry* parent = file->getParent();
+ auto hidden = false;
- // skip hiidden file check if already found one
- if (!hasHiddenFiles) {
- const fs::path nameAsPath(file->getName());
-
- if (nameAsPath.extension().wstring().compare(hideExt) == 0) {
- hasHiddenFiles = true;
- } else {
- const DirectoryEntry* parent = file->getParent();
-
- // iterate on all parent direEntries to check for .mohiddden
- while (parent != nullptr) {
- auto insertResult = checkedDirs.insert(parent);
+ // iterate on all parent directory entries to check for .mohiddden
+ while (parent != nullptr) {
+ auto insertResult = checkedDirs.insert(parent);
- if (insertResult.second == false) {
- // if already present break as we can assume to have checked the parents
- // as well
+ if (insertResult.second == false) {
+ // if already present break as we can assume to have checked the parents as
+ // well
+ break;
+ } else {
+ if (QString::fromStdWString(parent->getName())
+ .endsWith(ModInfo::s_HiddenExt, Qt::CaseInsensitive)) {
+ hasHiddenFiles = hidden = true;
break;
- } else {
- const fs::path dirPath(parent->getName());
- if (dirPath.extension().wstring().compare(hideExt) == 0) {
- hasHiddenFiles = true;
- break;
- }
- parent = parent->getParent();
}
+ parent = parent->getParent();
}
}
+ if (hidden) {
+ // skip hidden file conflicts
+ continue;
+ }
}
+ hasVisibleFiles = true;
auto alternatives = file->getAlternatives();
if ((alternatives.size() == 0) ||
std::find(dataIDs.begin(), dataIDs.end(), alternatives.back().originID()) !=
@@ -223,7 +226,7 @@ ModInfoWithConflictInfo::Conflicts ModInfoWithConflictInfo::doConflictCheck() co
}
if (files.size() != 0) {
- if (!providesAnything)
+ if (hasVisibleFiles && !providesAnything)
conflicts.m_CurrentConflictState = CONFLICT_REDUNDANT;
else if (!conflicts.m_OverwriteList.empty() &&
!conflicts.m_OverwrittenList.empty())