Skip to content

Commit

Permalink
Ignore conflicts between hidden files
Browse files Browse the repository at this point in the history
  • Loading branch information
JonathanFeenstra committed Oct 16, 2024
1 parent 61ef16d commit 8e4e03f
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 78 deletions.
19 changes: 14 additions & 5 deletions src/filetreemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

using namespace MOBase;
using namespace MOShared;
namespace fs = std::filesystem;

// in mainwindow.cpp
QString UnmanagedModName();
Expand Down Expand Up @@ -969,8 +970,12 @@ 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) ||
fs::path(file.getName())
.extension()
.compare(ModInfo::s_HiddenExt.toStdWString()) == 0)) {
// only conflicts should be shown, but this file is hidden or not conflicted
return false;
}

Expand All @@ -980,7 +985,9 @@ bool FileTreeModel::shouldShowFile(const FileEntry& file) const
}

if (!showHiddenFiles() &&
file.getName().ends_with(ModInfo::s_HiddenExt.toStdWString())) {
fs::path(file.getName())
.extension()
.compare(ModInfo::s_HiddenExt.toStdWString()) == 0) {
// hidden files shouldn't be shown, but this file is hidden
return false;
}
Expand All @@ -991,8 +998,10 @@ 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()) &&
fs::path(dir.getName())
.extension()
.compare(ModInfo::s_HiddenExt.toStdWString()) == 0) {
return false;
}

Expand Down
124 changes: 76 additions & 48 deletions src/modinfodialogconflicts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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");
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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());
Expand All @@ -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;
}
Expand Down Expand Up @@ -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()));
Expand Down Expand Up @@ -633,8 +598,40 @@ bool GeneralConflictsTab::update()

if (m_tab->origin() != nullptr) {
const auto rootPath = m_tab->mod().absolutePath();
const auto hideExt = ModInfo::s_HiddenExt.toStdWString();
std::set<const DirectoryEntry*> checkedDirs;

for (const auto& file : m_tab->origin()->getFiles()) {
const fs::path nameAsPath(file->getName());
if (nameAsPath.extension().wstring().compare(hideExt) == 0) {
// skip hidden file conflicts
continue;
} else {
const DirectoryEntry* parent = file->getParent();
auto hidden = false;
// iterate on all parent direEntries 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 {
const fs::path dirPath(parent->getName());
if (dirPath.extension().wstring().compare(hideExt) == 0) {
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()));
Expand Down Expand Up @@ -951,11 +948,42 @@ void AdvancedConflictsTab::update()

if (m_tab->origin() != nullptr) {
const auto rootPath = m_tab->mod().absolutePath();
const auto hideExt = ModInfo::s_HiddenExt.toStdWString();

const auto& files = m_tab->origin()->getFiles();
m_model->reserve(files.size());
std::set<const DirectoryEntry*> checkedDirs;

for (const auto& file : files) {
const fs::path nameAsPath(file->getName());
if (nameAsPath.extension().wstring().compare(hideExt) == 0) {
// skip hidden file conflicts
continue;
} else {
const DirectoryEntry* parent = file->getParent();
auto hidden = false;
// iterate on all parent direEntries 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 {
const fs::path dirPath(parent->getName());
if (dirPath.extension().wstring().compare(hideExt) == 0) {
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()));
Expand Down
3 changes: 1 addition & 2 deletions src/modinfodialogconflicts.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,14 @@ class ConflictsTab : public ModInfoDialogTab

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);

private:
struct Actions
{
QAction* hide = nullptr;
QAction* unhide = nullptr;
QAction* open = nullptr;
QAction* runHooked = nullptr;
QAction* preview = nullptr;
Expand Down
50 changes: 27 additions & 23 deletions src/modinfowithconflictinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")) {
Expand All @@ -120,36 +121,39 @@ ModInfoWithConflictInfo::Conflicts ModInfoWithConflictInfo::doConflictCheck() co

// for all files in this origin
for (FileEntryPtr file : files) {
const fs::path nameAsPath(file->getName());
if (nameAsPath.extension().wstring().compare(hideExt) == 0) {
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 direEntries 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 {
const fs::path dirPath(parent->getName());
if (dirPath.extension().wstring().compare(hideExt) == 0) {
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()) !=
Expand Down Expand Up @@ -223,7 +227,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())
Expand Down

0 comments on commit 8e4e03f

Please sign in to comment.