Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore conflicts between hidden files #2148

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 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,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;
}

Expand All @@ -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;
}
Expand All @@ -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;
}

Expand Down
122 changes: 74 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,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()));
Expand Down Expand Up @@ -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()));
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
53 changes: 28 additions & 25 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 @@ -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);
Expand All @@ -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()) !=
Expand Down Expand Up @@ -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())
Expand Down
Loading