From 8d6c715672023577dca5a6528ff49081dede1052 Mon Sep 17 00:00:00 2001 From: Silarn Date: Wed, 11 Apr 2018 17:46:59 -0500 Subject: Initial archive conflict parsing Squashed commit: Basic archive conflict parsing - pass 1 Merge fixes for archive parsing Basic archive conflict parsing - pass 1 Merge fixes for archive parsing Should fix conflict detection for archive files --- src/shared/directoryentry.cpp | 114 +++++++++++++++++++++++++++++------------- src/shared/directoryentry.h | 26 ++++++---- 2 files changed, 93 insertions(+), 47 deletions(-) (limited to 'src/shared') diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index cebf270e..477f4dad 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -220,12 +220,19 @@ std::vector FilesOrigin::getFiles() const return result; } +bool FilesOrigin::containsArchive(std::wstring archiveName) +{ + for (FileEntry::Index fileIdx : m_Files) + if (FileEntry::Ptr p = m_FileRegister.lock()->getFile(fileIdx)) + if (p->isFromArchive(archiveName)) return true; + return false; +} // // FileEntry // -void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &archive) +void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &archive, int order) { m_LastAccessed = time(nullptr); if (m_Parent != nullptr) { @@ -234,36 +241,36 @@ void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &arc if (m_Origin == -1) { m_Origin = origin; m_FileTime = fileTime; - m_Archive = archive; + m_Archive = std::pair(archive, order); } else if ((m_Parent != nullptr) && (m_Parent->getOriginByID(origin).getPriority() > m_Parent->getOriginByID(m_Origin).getPriority()) - && (archive.size() == 0 || m_Archive.size() > 0 )) { - if (std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair &i) -> bool { return i.first == m_Origin; }) == m_Alternatives.end()) { - m_Alternatives.push_back(std::pair(m_Origin, m_Archive)); + && (archive.size() == 0 || m_Archive.first.size() > 0 )) { + if (std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair> &i) -> bool { return i.first == m_Origin; }) == m_Alternatives.end()) { + m_Alternatives.push_back(std::pair>(m_Origin, m_Archive)); } m_Origin = origin; m_FileTime = fileTime; - m_Archive = archive; + m_Archive = std::pair(archive, order); } else { bool found = false; if (m_Origin == origin) { // already an origin return; } - for (std::vector>::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) { + for (std::vector>>::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) { if (iter->first == origin) { // already an origin return; } if ((m_Parent != nullptr) && (m_Parent->getOriginByID(iter->first).getPriority() < m_Parent->getOriginByID(origin).getPriority())) { - m_Alternatives.insert(iter, std::pair(origin, archive)); + m_Alternatives.insert(iter, std::pair>(origin, std::pair(archive, order))); found = true; break; } } if (!found) { - m_Alternatives.push_back(std::pair(origin, archive)); + m_Alternatives.push_back(std::pair>(origin, std::pair(archive, order))); } } } @@ -273,8 +280,8 @@ bool FileEntry::removeOrigin(int origin) if (m_Origin == origin) { if (!m_Alternatives.empty()) { // find alternative with the highest priority - std::vector>::iterator currentIter = m_Alternatives.begin(); - for (std::vector>::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) { + std::vector>>::iterator currentIter = m_Alternatives.begin(); + for (std::vector>>::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) { if ((m_Parent->getOriginByID(iter->first).getPriority() > m_Parent->getOriginByID(currentIter->first).getPriority()) && (iter->first != origin)) { currentIter = iter; @@ -292,9 +299,9 @@ bool FileEntry::removeOrigin(int origin) if (!::GetFileTime(file, nullptr, nullptr, &m_FileTime)) { // maybe this file is in a bsa, but there is no easy way to find out which. User should refresh // the view to find out - m_Archive = L"bsa?"; + m_Archive = std::pair(L"bsa?", -1); } else { - m_Archive = L""; + m_Archive = std::pair(L"", -1); } ::CloseHandle(file); @@ -304,7 +311,7 @@ bool FileEntry::removeOrigin(int origin) return true; } } else { - std::vector>::iterator newEnd = std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair &i) -> bool { return i.first == origin; }); + std::vector>>::iterator newEnd = std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair> &i) -> bool { return i.first == origin; }); if (newEnd != m_Alternatives.end()) m_Alternatives.erase(newEnd, m_Alternatives.end()); } @@ -318,7 +325,7 @@ FileEntry::FileEntry() } FileEntry::FileEntry(Index index, const std::wstring &name, DirectoryEntry *parent) - : m_Index(index), m_Name(name), m_Origin(-1), m_Archive(L""), m_Parent(parent), m_LastAccessed(time(nullptr)) + : m_Index(index), m_Name(name), m_Origin(-1), m_Archive(L"", -1), m_Parent(parent), m_LastAccessed(time(nullptr)) { LEAK_TRACE; } @@ -330,16 +337,23 @@ FileEntry::~FileEntry() void FileEntry::sortOrigins() { - m_Alternatives.push_back(std::pair(m_Origin, m_Archive)); - std::sort(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair &LHS, const std::pair &RHS) -> bool { - if ((!LHS.second.size() && !RHS.second.size()) || (LHS.second.size() && RHS.second.size())) { + m_Alternatives.push_back(std::pair>(m_Origin, m_Archive)); + std::sort(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair> &LHS, const std::pair> &RHS) -> bool { + if (!LHS.second.first.size() && !RHS.second.first.size()) { int l = m_Parent->getOriginByID(LHS.first).getPriority(); if (l < 0) l = INT_MAX; int r = m_Parent->getOriginByID(RHS.first).getPriority(); if (r < 0) r = INT_MAX; return l < r; } - if (RHS.second.size()) return false; + if (LHS.second.first.size() && RHS.second.first.size()) { + int l = LHS.second.second; if (l < 0) l = INT_MAX; + int r = RHS.second.second; if (r < 0) r = INT_MAX; + + return l < r; + } + + if (RHS.second.first.size()) return false; return true; }); if (!m_Alternatives.empty()) { @@ -379,6 +393,16 @@ std::wstring FileEntry::getRelativePath() const return result + L"\\" + m_Name; } +bool FileEntry::isFromArchive(std::wstring archiveName) +{ + if (archiveName.length() == 0) return m_Archive.first.length() != 0; + if (m_Archive.first.compare(archiveName) == 0) return true; + for (auto alternative : m_Alternatives) { + if (alternative.second.first.compare(archiveName) == 0) return true; + } + return false; +} + // // DirectoryEntry @@ -451,7 +475,7 @@ void DirectoryEntry::addFromOrigin(const std::wstring &originName, const std::ws } -void DirectoryEntry::addFromBSA(const std::wstring &originName, std::wstring &directory, const std::wstring &fileName, int priority) +void DirectoryEntry::addFromBSA(const std::wstring &originName, std::wstring &directory, const std::wstring &fileName, int priority, int order) { FilesOrigin &origin = createOrigin(originName, directory, priority); @@ -459,23 +483,33 @@ void DirectoryEntry::addFromBSA(const std::wstring &originName, std::wstring &di if (::GetFileAttributesExW(fileName.c_str(), GetFileExInfoStandard, &fileData) == 0) { throw windows_error("failed to determine file time"); } + FILETIME now; + ::GetSystemTimeAsFileTime(&now); + + const double clfSecondsPer100ns = 100. * 1.E-9; + + ((ULARGE_INTEGER *)&now)->QuadPart -= ((double)5) / clfSecondsPer100ns; - BSA::Archive archive; - BSA::EErrorCode res = archive.read(ToString(fileName, false).c_str(), false); - if ((res != BSA::ERROR_NONE) && (res != BSA::ERROR_INVALIDHASHES)) { - std::ostringstream stream; - stream << "invalid bsa file: " << ToString(fileName, false) << " errorcode " << res << " - " << ::GetLastError(); - throw std::runtime_error(stream.str()); - } size_t namePos = fileName.find_last_of(L"\\/"); if (namePos == std::wstring::npos) { namePos = 0; - } else { + } + else { ++namePos; } - addFiles(origin, archive.getRoot(), fileData.ftLastWriteTime, fileName.substr(namePos)); - m_Populated = true; + if (!containsArchive(fileName.substr(namePos)) || ::CompareFileTime(&fileData.ftLastWriteTime, &now) > 0) { + BSA::Archive archive; + BSA::EErrorCode res = archive.read(ToString(fileName, false).c_str(), false); + if ((res != BSA::ERROR_NONE) && (res != BSA::ERROR_INVALIDHASHES)) { + std::ostringstream stream; + stream << "invalid bsa file: " << ToString(fileName, false) << " errorcode " << res << " - " << ::GetLastError(); + throw std::runtime_error(stream.str()); + } + + addFiles(origin, archive.getRoot(), fileData.ftLastWriteTime, fileName.substr(namePos), order); + m_Populated = true; + } } void DirectoryEntry::propagateOrigin(int origin) @@ -536,7 +570,7 @@ void DirectoryEntry::addFiles(FilesOrigin &origin, wchar_t *buffer, int bufferOf getSubDirectory(findData.cFileName, true, origin.getID())->addFiles(origin, buffer, bufferOffset + offset); } } else { - insert(findData.cFileName, origin, findData.ftLastWriteTime, L""); + insert(findData.cFileName, origin, findData.ftLastWriteTime, L"", -1); } result = ::FindNextFileW(searchHandle, &findData); } @@ -546,12 +580,12 @@ void DirectoryEntry::addFiles(FilesOrigin &origin, wchar_t *buffer, int bufferOf } -void DirectoryEntry::addFiles(FilesOrigin &origin, BSA::Folder::Ptr archiveFolder, FILETIME &fileTime, const std::wstring &archiveName) +void DirectoryEntry::addFiles(FilesOrigin &origin, BSA::Folder::Ptr archiveFolder, FILETIME &fileTime, const std::wstring &archiveName, int order) { // add files for (unsigned int fileIdx = 0; fileIdx < archiveFolder->getNumFiles(); ++fileIdx) { BSA::File::Ptr file = archiveFolder->getFile(fileIdx); - insert(ToWString(file->getName(), true), origin, fileTime, archiveName); + insert(ToWString(file->getName(), true), origin, fileTime, archiveName, order); } // recurse into subdirectories @@ -559,7 +593,7 @@ void DirectoryEntry::addFiles(FilesOrigin &origin, BSA::Folder::Ptr archiveFolde BSA::Folder::Ptr folder = archiveFolder->getSubFolder(folderIdx); DirectoryEntry *folderEntry = getSubDirectoryRecursive(ToWString(folder->getName(), true), true, origin.getID()); - folderEntry->addFiles(origin, folder, fileTime, archiveName); + folderEntry->addFiles(origin, folder, fileTime, archiveName, order); } } @@ -626,7 +660,7 @@ void DirectoryEntry::insertFile(const std::wstring &filePath, FilesOrigin &origi { size_t pos = filePath.find_first_of(L"\\/"); if (pos == std::string::npos) { - this->insert(filePath, origin, fileTime, std::wstring()); + this->insert(filePath, origin, fileTime, std::wstring(), -1); } else { std::wstring dirName = filePath.substr(0, pos); std::wstring rest = filePath.substr(pos + 1); @@ -667,6 +701,14 @@ void DirectoryEntry::removeFiles(const std::set &indices) } } +bool DirectoryEntry::containsArchive(std::wstring archiveName) +{ + for (auto iter = m_Files.begin(); iter != m_Files.end(); ++iter) { + FileEntry::Ptr entry = m_FileRegister->getFile(iter->second); + if (entry->isFromArchive(archiveName)) return true; + } + return false; +} int DirectoryEntry::anyOrigin() const { @@ -890,7 +932,7 @@ void FileRegister::unregisterFile(FileEntry::Ptr file) // unregister from origin int originID = file->getOrigin(ignore); m_OriginConnection->getByID(originID).removeFile(file->getIndex()); - const std::vector> &alternatives = file->getAlternatives(); + const std::vector>> &alternatives = file->getAlternatives(); for (auto iter = alternatives.begin(); iter != alternatives.end(); ++iter) { m_OriginConnection->getByID(iter->first).removeFile(file->getIndex()); } diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index 8dbedaf4..12cef11d 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -64,7 +64,7 @@ public: time_t lastAccessed() const { return m_LastAccessed; } - void addOrigin(int origin, FILETIME fileTime, const std::wstring &archive); + void addOrigin(int origin, FILETIME fileTime, const std::wstring &archive, int order); // remove the specified origin from the list of origins that contain this file. if no origin is left, // the file is effectively deleted and true is returned. otherwise, false is returned bool removeOrigin(int origin); @@ -72,13 +72,13 @@ public: // gets the list of alternative origins (origins with lower priority than the primary one). // if sortOrigins has been called, it is sorted by priority (ascending) - const std::vector> &getAlternatives() const { return m_Alternatives; } + const std::vector>> &getAlternatives() const { return m_Alternatives; } const std::wstring &getName() const { return m_Name; } int getOrigin() const { return m_Origin; } - int getOrigin(bool &archive) const { archive = (m_Archive.length() != 0); return m_Origin; } - const std::wstring &getArchive() const { return m_Archive; } - bool isFromArchive() const { return m_Archive.length() != 0; } + int getOrigin(bool &archive) const { archive = (m_Archive.first.length() != 0); return m_Origin; } + const std::pair &getArchive() const { return m_Archive; } + bool isFromArchive(std::wstring archiveName = L""); std::wstring getFullPath() const; std::wstring getRelativePath() const; DirectoryEntry *getParent() { return m_Parent; } @@ -97,8 +97,8 @@ private: Index m_Index; std::wstring m_Name; int m_Origin = -1; - std::wstring m_Archive; - std::vector> m_Alternatives; + std::pair m_Archive; + std::vector>> m_Alternatives; DirectoryEntry *m_Parent; mutable FILETIME m_FileTime; @@ -142,6 +142,8 @@ public: void addFile(FileEntry::Index index) { m_Files.insert(index); } void removeFile(FileEntry::Index index); + bool containsArchive(std::wstring archiveName); + private: FilesOrigin(int ID, const std::wstring &name, const std::wstring &path, int priority, @@ -221,7 +223,7 @@ public: // add files to this directory (and subdirectories) from the specified origin. That origin may exist or not void addFromOrigin(const std::wstring &originName, const std::wstring &directory, int priority); - void addFromBSA(const std::wstring &originName, std::wstring &directory, const std::wstring &fileName, int priority); + void addFromBSA(const std::wstring &originName, std::wstring &directory, const std::wstring &fileName, int priority, int order); void propagateOrigin(int origin); @@ -253,6 +255,8 @@ public: */ const FileEntry::Ptr findFile(const std::wstring &name) const; + bool containsArchive(std::wstring archiveName); + /** search through this directory and all subdirectories for a file by the specified name (relative path). if directory is not nullptr, the referenced variable will be set to the path containing the file */ const FileEntry::Ptr searchFile(const std::wstring &path, const DirectoryEntry **directory) const; @@ -297,7 +301,7 @@ private: DirectoryEntry(const DirectoryEntry &reference); DirectoryEntry &operator=(const DirectoryEntry &reference); - void insert(const std::wstring &fileName, FilesOrigin &origin, FILETIME fileTime, const std::wstring &archive) { + void insert(const std::wstring &fileName, FilesOrigin &origin, FILETIME fileTime, const std::wstring &archive, int order) { std::wstring fileNameLower = ToLower(fileName); auto iter = m_Files.find(fileNameLower); FileEntry::Ptr file; @@ -308,12 +312,12 @@ private: // TODO this has been observed to cause a crash, no clue why m_Files[fileNameLower] = file->getIndex(); } - file->addOrigin(origin.getID(), fileTime, archive); + file->addOrigin(origin.getID(), fileTime, archive, order); origin.addFile(file->getIndex()); } void addFiles(FilesOrigin &origin, wchar_t *buffer, int bufferOffset); - void addFiles(FilesOrigin &origin, BSA::Folder::Ptr archiveFolder, FILETIME &fileTime, const std::wstring &archiveName); + void addFiles(FilesOrigin &origin, BSA::Folder::Ptr archiveFolder, FILETIME &fileTime, const std::wstring &archiveName, int order); DirectoryEntry *getSubDirectory(const std::wstring &name, bool create, int originID = -1); -- cgit v1.3.1 From 49159de5d7084bf1ac159e3e37e2b406cdd87dbf Mon Sep 17 00:00:00 2001 From: Al12rs Date: Tue, 14 Aug 2018 11:35:20 -0500 Subject: Improved refresh performance by replacing std::transform() with CharLowerBuffer(). Fixed padding to four spaces and removed references to FLAG_ARCHIVE_LOOSE_CONFLICTS_MIXED that isn't used. --- src/modflagicondelegate.cpp | 32 +++++++++++++++++++------------- src/modflagicondelegate.h | 2 +- src/modinfo.h | 1 - src/modlist.cpp | 1 - src/modlistsortproxy.cpp | 1 - src/shared/util.cpp | 12 ++++++++---- 6 files changed, 28 insertions(+), 21 deletions(-) (limited to 'src/shared') diff --git a/src/modflagicondelegate.cpp b/src/modflagicondelegate.cpp index a0a0a86d..48d71313 100644 --- a/src/modflagicondelegate.cpp +++ b/src/modflagicondelegate.cpp @@ -7,8 +7,7 @@ ModInfo::EFlag ModFlagIconDelegate::m_ConflictFlags[4] = { ModInfo::FLAG_CONFLIC , ModInfo::FLAG_CONFLICT_OVERWRITTEN , ModInfo::FLAG_CONFLICT_REDUNDANT }; -ModInfo::EFlag ModFlagIconDelegate::m_ArchiveLooseConflictFlags[3] = { ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_MIXED - , ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITE +ModInfo::EFlag ModFlagIconDelegate::m_ArchiveLooseConflictFlags[2] = { ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITE , ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITTEN }; ModInfo::EFlag ModFlagIconDelegate::m_ArchiveConflictFlags[3] = { ModInfo::FLAG_ARCHIVE_CONFLICT_MIXED @@ -39,26 +38,33 @@ QList ModFlagIconDelegate::getIcons(const QModelIndex &index) const { } } - { // insert archive vs loose conflicts second - int pad = 2; + { // insert loose vs archive overwrite second + auto iter = std::find(flags.begin(), flags.end(), + ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITE); + if (iter != flags.end()) { + result.append(getFlagIcon(*iter)); + flags.erase(iter); + } + else { + result.append(QString()); + } + } + + { // insert loose vs archive overwritten third auto iter = std::find_first_of(flags.begin(), flags.end(), - m_ArchiveLooseConflictFlags, m_ArchiveLooseConflictFlags + 4); - while (iter != flags.end()) { + m_ArchiveLooseConflictFlags + 1, m_ArchiveLooseConflictFlags + 2); + if (iter != flags.end()) { result.append(getFlagIcon(*iter)); flags.erase(iter); - pad--; - iter = std::find_first_of(flags.begin(), flags.end(), - m_ArchiveLooseConflictFlags, m_ArchiveLooseConflictFlags + 4); } - while (pad > 0) { + else { result.append(QString()); - pad--; } } { // insert archive conflicts last auto iter = std::find_first_of(flags.begin(), flags.end(), - m_ArchiveConflictFlags, m_ArchiveConflictFlags + 4); + m_ArchiveConflictFlags, m_ArchiveConflictFlags + 3); if (iter != flags.end()) { result.append(getFlagIcon(*iter)); flags.erase(iter); @@ -87,7 +93,7 @@ QString ModFlagIconDelegate::getFlagIcon(ModInfo::EFlag flag) const case ModInfo::FLAG_CONFLICT_OVERWRITTEN: return ":/MO/gui/emblem_conflict_overwritten"; case ModInfo::FLAG_CONFLICT_MIXED: return ":/MO/gui/emblem_conflict_mixed"; case ModInfo::FLAG_CONFLICT_REDUNDANT: return ":MO/gui/emblem_conflict_redundant"; - case ModInfo::FLAG_ALTERNATE_GAME: return ":MO/gui/alternate_game"; + case ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_MIXED: return ":/MO/gui/archive_loose_conflict_mixed"; case ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITE: return ":/MO/gui/archive_loose_conflict_overwrite"; case ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITTEN: return ":/MO/gui/archive_loose_conflict_overwritten"; case ModInfo::FLAG_ARCHIVE_CONFLICT_MIXED: return ":/MO/gui/archive_conflict_mixed"; diff --git a/src/modflagicondelegate.h b/src/modflagicondelegate.h index 7324d516..0f257c7d 100644 --- a/src/modflagicondelegate.h +++ b/src/modflagicondelegate.h @@ -15,7 +15,7 @@ private: QString getFlagIcon(ModInfo::EFlag flag) const; private: static ModInfo::EFlag m_ConflictFlags[4]; - static ModInfo::EFlag m_ArchiveLooseConflictFlags[3]; + static ModInfo::EFlag m_ArchiveLooseConflictFlags[2]; static ModInfo::EFlag m_ArchiveConflictFlags[3]; }; diff --git a/src/modinfo.h b/src/modinfo.h index 99ce35b5..00859209 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -74,7 +74,6 @@ public: FLAG_CONFLICT_REDUNDANT, FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITE, FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITTEN, - FLAG_ARCHIVE_LOOSE_CONFLICT_MIXED, FLAG_ARCHIVE_CONFLICT_OVERWRITE, FLAG_ARCHIVE_CONFLICT_OVERWRITTEN, FLAG_ARCHIVE_CONFLICT_MIXED, diff --git a/src/modlist.cpp b/src/modlist.cpp index fd6da43b..8c070667 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -163,7 +163,6 @@ QString ModList::getFlagText(ModInfo::EFlag flag, ModInfo::Ptr modInfo) const case ModInfo::FLAG_CONFLICT_OVERWRITTEN: return tr("Overwritten loose files"); case ModInfo::FLAG_CONFLICT_MIXED: return tr("Loose files Overwrites & Overwritten"); case ModInfo::FLAG_CONFLICT_REDUNDANT: return tr("Redundant"); - case ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_MIXED: return tr("Contains archive files overwritten by loose files and loose files overwriting an archive"); case ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITE: return tr("Overwrites an archive with loose files"); case ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITTEN: return tr("Archive is overwritten by loose files"); case ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITE: return tr("Overwrites another archive file"); diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 88a073e0..8cf4bb9c 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -244,7 +244,6 @@ bool ModListSortProxy::hasConflictFlag(const std::vector &flags) (flag == ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITE) || (flag == ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITTEN) || (flag == ModInfo::FLAG_ARCHIVE_CONFLICT_MIXED) || - (flag == ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_MIXED) || (flag == ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITE) || (flag == ModInfo::FLAG_ARCHIVE_LOOSE_CONFLICT_OVERWRITTEN)) { return true; diff --git a/src/shared/util.cpp b/src/shared/util.cpp index 102565f5..b65ed071 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -108,27 +108,31 @@ static auto locToLower = [] (char in) -> char { std::string &ToLower(std::string &text) { - std::transform(text.begin(), text.end(), text.begin(), locToLower); + //std::transform(text.begin(), text.end(), text.begin(), locToLower); + CharLowerBuffA(const_cast(text.c_str()), static_cast(text.size())); return text; } std::string ToLower(const std::string &text) { std::string result(text); - std::transform(result.begin(), result.end(), result.begin(), locToLower); + //std::transform(result.begin(), result.end(), result.begin(), locToLower); + CharLowerBuffA(const_cast(result.c_str()), static_cast(result.size())); return result; } std::wstring &ToLower(std::wstring &text) { - std::transform(text.begin(), text.end(), text.begin(), locToLowerW); + //std::transform(text.begin(), text.end(), text.begin(), locToLowerW); + CharLowerBuffW(const_cast(text.c_str()), static_cast(text.size())); return text; } std::wstring ToLower(const std::wstring &text) { std::wstring result(text); - std::transform(result.begin(), result.end(), result.begin(), locToLowerW); + //std::transform(result.begin(), result.end(), result.begin(), locToLowerW); + CharLowerBuffW(const_cast(result.c_str()), static_cast(result.size())); return result; } -- cgit v1.3.1 From 40c82fc1908a8ca53abeeabdc618e81e941c987c Mon Sep 17 00:00:00 2001 From: Al12rs Date: Mon, 10 Sep 2018 05:58:24 -0500 Subject: Fixed mainwindow.cpp so that Qt Creator does not break it anymore. We should be able to normally use Creator now without having to worry about breaking the build. Partial fix for conflict information getting messd up after opening infodialog or disabling a mod. Icons still get messed up but conflict tab remains consistent at first inspection. Reverted main tab to plugins Changed version of Archive conflicts branch to 2.2.0 pre-alpha. --- src/directoryrefresher.cpp | 12 ++++---- src/mainwindow.cpp | 1 + src/mainwindow.ui | 66 +++++++++++++++++++++---------------------- src/shared/directoryentry.cpp | 31 ++++++++++++++++---- src/version.rc | 4 +-- 5 files changed, 68 insertions(+), 46 deletions(-) (limited to 'src/shared') diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp index 5c789049..82eb093b 100644 --- a/src/directoryrefresher.cpp +++ b/src/directoryrefresher.cpp @@ -85,17 +85,17 @@ void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure int priority, const QString &directory, const QStringList &archives) { std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory)); + //QStringList loadOrder = QStringList(); + IPluginGame *game = qApp->property("managed_game").value(); + + GamePlugins *gamePlugins = game->feature(); QStringList loadOrder = QStringList(); + gamePlugins->getLoadOrder(loadOrder); for (const QString &archive : archives) { QFileInfo fileInfo(archive); if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) { - IPluginGame *game = qApp->property("managed_game").value(); - - GamePlugins *gamePlugins = game->feature(); - QStringList loadOrder = QStringList(); - gamePlugins->getLoadOrder(loadOrder); - + int order = -1; for (auto plugin : loadOrder) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 0d3abce5..cdd53dc9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -313,6 +313,7 @@ MainWindow::MainWindow(QSettings &initSettings ui->espList->setItemDelegateForColumn(PluginList::COL_FLAGS, new GenericIconDelegate(ui->espList)); ui->espList->installEventFilter(m_OrganizerCore.pluginList()); + //bsaList converted to normal QTreeWidget since we can't sort BSAs anymore. //ui->bsaList->setLocalMoveOnly(true); bool pluginListAdjusted = registerWidgetState(ui->espList->objectName(), ui->espList->header(), "plugin_list_state"); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index fba246f5..eb88a855 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1152,39 +1152,39 @@ p, li { white-space: pre-wrap; } - - - - - - Filters the above list so that only conflicts are displayed. - - - Filters the above list so that only conflicts are displayed. - - - Show only conflicts - - - - - - - Filters the above list so that files from archives are not shown - - - - - - Filters the above list so that files from archives are not shown - - - Show files from Archives - - - - - + + + + + + Filters the above list so that only conflicts are displayed. + + + Filters the above list so that only conflicts are displayed. + + + Show only conflicts + + + + + + + Filters the above list so that files from archives are not shown + + + + + + Filters the above list so that files from archives are not shown + + + Show files from Archives + + + + + diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 477f4dad..602d58c7 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -282,12 +282,32 @@ bool FileEntry::removeOrigin(int origin) // find alternative with the highest priority std::vector>>::iterator currentIter = m_Alternatives.begin(); for (std::vector>>::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) { - if ((m_Parent->getOriginByID(iter->first).getPriority() > m_Parent->getOriginByID(currentIter->first).getPriority()) && - (iter->first != origin)) { - currentIter = iter; + if (iter->first != origin) { + + //Both files are not from archives. + if (!iter->second.first.size() && !currentIter->second.first.size()) { + if ((m_Parent->getOriginByID(iter->first).getPriority() > m_Parent->getOriginByID(currentIter->first).getPriority())) { + currentIter = iter; + } + } + else { + //Both files are from archives + if (iter->second.first.size() && currentIter->second.first.size()) { + if (iter->second.second > currentIter->second.second) { + currentIter = iter; + } + } + else { + //Only one of the two is an archive, so we change currentIter only if he is the archive one. + if (currentIter->second.first.size()) { + currentIter = iter; + } + } + } } } int currentID = currentIter->first; + m_Archive = currentIter->second; m_Alternatives.erase(currentIter); m_Origin = currentID; @@ -299,15 +319,16 @@ bool FileEntry::removeOrigin(int origin) if (!::GetFileTime(file, nullptr, nullptr, &m_FileTime)) { // maybe this file is in a bsa, but there is no easy way to find out which. User should refresh // the view to find out - m_Archive = std::pair(L"bsa?", -1); + //m_Archive = std::pair(L"bsa?", -1); } else { - m_Archive = std::pair(L"", -1); + //m_Archive = std::pair(L"", -1); } ::CloseHandle(file); } else { m_Origin = -1; + m_Archive = std::pair(L"", -1); return true; } } else { diff --git a/src/version.rc b/src/version.rc index 3f2deab0..e1f80785 100644 --- a/src/version.rc +++ b/src/version.rc @@ -3,8 +3,8 @@ // If VS_FF_PRERELEASE is not set, MO labels the build as a release and uses VER_FILEVERSION to determine version number. // Otherwise, if letters are used in VER_FILEVERSION_STR, uses the full MOBase::VersionInfo parser // Otherwise, uses the numbers from VER_FILEVERSION and sets the release type as pre-alpha -#define VER_FILEVERSION 2,1,6 -#define VER_FILEVERSION_STR "2.1.6\0" +#define VER_FILEVERSION 2,2,0 +#define VER_FILEVERSION_STR "2.2.0\0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION -- cgit v1.3.1 From 858930cb461988adec846bdf96fad6f600b81cd6 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Tue, 1 Jan 2019 00:57:12 -0600 Subject: Change find_if to remove_if --- src/shared/directoryentry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shared') diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 602d58c7..9f54e526 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -332,7 +332,7 @@ bool FileEntry::removeOrigin(int origin) return true; } } else { - std::vector>>::iterator newEnd = std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair> &i) -> bool { return i.first == origin; }); + auto newEnd = std::remove_if(m_Alternatives.begin(), m_Alternatives.end(), [&](auto &i) -> bool { return i.first == origin; }); if (newEnd != m_Alternatives.end()) m_Alternatives.erase(newEnd, m_Alternatives.end()); } -- cgit v1.3.1 From e97f0735704155e90e32c6cbec236adf35c8c344 Mon Sep 17 00:00:00 2001 From: Al Date: Sat, 5 Jan 2019 20:59:00 +0100 Subject: Improve ToLower() performance significally. --- src/shared/util.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/shared') diff --git a/src/shared/util.cpp b/src/shared/util.cpp index bad0d64d..ed7c434e 100644 --- a/src/shared/util.cpp +++ b/src/shared/util.cpp @@ -108,27 +108,31 @@ static auto locToLower = [] (char in) -> char { std::string &ToLower(std::string &text) { - std::transform(text.begin(), text.end(), text.begin(), locToLower); + //std::transform(text.begin(), text.end(), text.begin(), locToLower); + CharLowerBuffA(const_cast(text.c_str()), static_cast(text.size())); return text; } std::string ToLower(const std::string &text) { std::string result(text); - std::transform(result.begin(), result.end(), result.begin(), locToLower); + //std::transform(result.begin(), result.end(), result.begin(), locToLower); + CharLowerBuffA(const_cast(result.c_str()), static_cast(result.size())); return result; } std::wstring &ToLower(std::wstring &text) { - std::transform(text.begin(), text.end(), text.begin(), locToLowerW); + //std::transform(text.begin(), text.end(), text.begin(), locToLowerW); + CharLowerBuffW(const_cast(text.c_str()), static_cast(text.size())); return text; } std::wstring ToLower(const std::wstring &text) { std::wstring result(text); - std::transform(result.begin(), result.end(), result.begin(), locToLowerW); + //std::transform(result.begin(), result.end(), result.begin(), locToLowerW); + CharLowerBuffW(const_cast(result.c_str()), static_cast(result.size())); return result; } -- cgit v1.3.1 From cc7c3adcad973949ac976c3dc71bb8cf2677056c Mon Sep 17 00:00:00 2001 From: Al Date: Fri, 11 Jan 2019 13:50:51 +0100 Subject: Fix or ignore a number of compiler warnings. --- src/aboutdialog.ui | 10 +++++----- src/overwriteinfodialog.cpp | 2 +- src/pluginlist.cpp | 2 +- src/selfupdater.cpp | 3 +-- src/settings.cpp | 2 +- src/shared/leaktrace.cpp | 13 ++++++++++++- src/spawn.cpp | 2 +- 7 files changed, 22 insertions(+), 12 deletions(-) (limited to 'src/shared') diff --git a/src/aboutdialog.ui b/src/aboutdialog.ui index ac7db1fc..86b95c83 100644 --- a/src/aboutdialog.ui +++ b/src/aboutdialog.ui @@ -161,7 +161,7 @@ - + QAbstractItemView::NoSelection @@ -202,7 +202,7 @@ - + QAbstractItemView::NoSelection @@ -231,9 +231,9 @@ Translators - + - + QAbstractItemView::NoSelection @@ -363,7 +363,7 @@ Other Supporters && Contributors - + diff --git a/src/overwriteinfodialog.cpp b/src/overwriteinfodialog.cpp index 1fe3f645..4d35a2c3 100644 --- a/src/overwriteinfodialog.cpp +++ b/src/overwriteinfodialog.cpp @@ -220,7 +220,7 @@ void OverwriteInfoDialog::openFile(const QModelIndex &index) QString fileName = m_FileSystemModel->filePath(index); HINSTANCE res = ::ShellExecuteW(nullptr, L"open", ToWString(fileName).c_str(), nullptr, nullptr, SW_SHOW); - if ((int)res <= 32) { + if ((INT_PTR)res <= 32) { qCritical("failed to invoke %s: %d", fileName.toUtf8().constData(), res); } } diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 6f417331..25f9c545 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -153,7 +153,7 @@ void PluginList::highlightPlugins(const QItemSelectionModel *selection, const MO } } } - emit dataChanged(this->index(0, 0), this->index(m_ESPs.size() - 1, this->columnCount() - 1)); + emit dataChanged(this->index(0, 0), this->index(static_cast(m_ESPs.size()) - 1, this->columnCount() - 1)); } void PluginList::refresh(const QString &profileName diff --git a/src/selfupdater.cpp b/src/selfupdater.cpp index c913af6a..b5e7684c 100644 --- a/src/selfupdater.cpp +++ b/src/selfupdater.cpp @@ -338,9 +338,8 @@ void SelfUpdater::installUpdate() } else { reportError(tr("Failed to start %1: %2") .arg(m_UpdateFile.fileName()) - .arg((int)res)); + .arg((INT_PTR)res)); } - m_UpdateFile.remove(); } diff --git a/src/settings.cpp b/src/settings.cpp index f981f811..9267cccf 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -142,7 +142,7 @@ void Settings::registerAsNXMHandler(bool force) } parameters += L" \"" + executable + L"\""; HINSTANCE res = ::ShellExecuteW(nullptr, L"open", nxmPath.c_str(), parameters.c_str(), nullptr, SW_SHOWNORMAL); - if ((int)res <= 32) { + if ((INT_PTR)res <= 32) { QMessageBox::critical(nullptr, tr("Failed"), tr("Sorry, failed to start the helper application")); } diff --git a/src/shared/leaktrace.cpp b/src/shared/leaktrace.cpp index 1ff1fa9d..466162a4 100644 --- a/src/shared/leaktrace.cpp +++ b/src/shared/leaktrace.cpp @@ -1,3 +1,8 @@ +//disable warning messages 4302 , 4311 and 4312 +#pragma warning( disable : 4302 ) +#pragma warning( disable : 4311 ) +#pragma warning( disable : 4312 ) + #include "leaktrace.h" #include "stackdata.h" #include @@ -31,7 +36,7 @@ static struct __TraceData { for (auto iter = result.begin(); iter != result.end(); ++iter) { printf("-----------------------------------\n" "%d objects not freed, allocated at:\n%s", - iter->second.size(), iter->first.toString().c_str()); + static_cast(iter->second.size()), iter->first.toString().c_str()); printf("Addresses: "); for (int i = 0; i < (std::min)(5, static_cast(iter->second.size())); ++i) { @@ -55,3 +60,9 @@ void LeakTrace::TraceDealloc(void *ptr) { __trace.deregTrace(ptr); } + +//re-enable warning messages 4302 , 4311 and 4312 +#pragma warning( default : 4302 ) +#pragma warning( default : 4311 ) +#pragma warning( default : 4312 ) + diff --git a/src/spawn.cpp b/src/spawn.cpp index f8a7bb5f..e1de5c0f 100644 --- a/src/spawn.cpp +++ b/src/spawn.cpp @@ -94,7 +94,7 @@ static bool spawn(LPCWSTR binary, LPCWSTR arguments, LPCWSTR currentDirectory, PROCESS_INFORMATION pi; BOOL success = FALSE; if (hooked) { - qDebug() << "Creating process hooked: <" << QString::fromWCharArray(commandLine, length) <<">"; + qDebug() << "Creating process hooked: <" << QString::fromWCharArray(commandLine, static_cast(length)) <<">"; success = ::CreateProcessHooked(nullptr, commandLine, nullptr, nullptr, // no special process or thread attributes -- cgit v1.3.1 From b38a26c2bc731ad123365e7f164d1a9ed0c89b6a Mon Sep 17 00:00:00 2001 From: Al Date: Tue, 12 Feb 2019 23:56:09 +0100 Subject: Performance improvements: * Avoid accessing disk for finding archives if archive parsing is disabled. * Avoid very expensive createFile() call in removeOrigin(), after disabling a mod or closing modinfodialog. --- src/modinforegular.cpp | 4 +++- src/shared/directoryentry.cpp | 14 +++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/shared') diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp index 15ce56ba..529f20cb 100644 --- a/src/modinforegular.cpp +++ b/src/modinforegular.cpp @@ -47,7 +47,9 @@ ModInfoRegular::ModInfoRegular(PluginContainer *pluginContainer, const IPluginGa //populate m_Archives m_Archives = QStringList(); - archives(true); + if (Settings::instance().archiveParsing()) { + archives(true); + } connect(&m_NexusBridge, SIGNAL(descriptionAvailable(QString,int,QVariant,QVariant)) , this, SLOT(nxmDescriptionAvailable(QString,int,QVariant,QVariant))); diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 9f54e526..8fc63188 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -313,18 +313,18 @@ bool FileEntry::removeOrigin(int origin) m_Origin = currentID; // now we need to update the file time... - std::wstring filePath = getFullPath(); - HANDLE file = ::CreateFile(filePath.c_str(), GENERIC_READ | GENERIC_WRITE, - 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (!::GetFileTime(file, nullptr, nullptr, &m_FileTime)) { + //std::wstring filePath = getFullPath(); + //HANDLE file = ::CreateFile(filePath.c_str(), GENERIC_READ | GENERIC_WRITE, + // 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + //if (!::GetFileTime(file, nullptr, nullptr, &m_FileTime)) { // maybe this file is in a bsa, but there is no easy way to find out which. User should refresh // the view to find out //m_Archive = std::pair(L"bsa?", -1); - } else { + //} else { //m_Archive = std::pair(L"", -1); - } + //} - ::CloseHandle(file); + //::CloseHandle(file); } else { m_Origin = -1; -- cgit v1.3.1 From 6dd246363e538d7730ff0eec3c23338553ca1392 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Fri, 22 Mar 2019 21:26:50 -0500 Subject: Fix origin determination for the case of a lower priority, loose files mod being added after a higher priority, archived files mod. --- src/shared/directoryentry.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'src/shared') diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 8fc63188..1179110a 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -238,20 +238,30 @@ void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &arc if (m_Parent != nullptr) { m_Parent->propagateOrigin(origin); } + + // If this file has no previous origin, this mod is now the origin with no alternatives if (m_Origin == -1) { m_Origin = origin; m_FileTime = fileTime; m_Archive = std::pair(archive, order); - } else if ((m_Parent != nullptr) - && (m_Parent->getOriginByID(origin).getPriority() > m_Parent->getOriginByID(m_Origin).getPriority()) - && (archive.size() == 0 || m_Archive.first.size() > 0 )) { + } + + // If this mod has a higher priority than the origin mod OR + // this mod has a loose file and the origin mod has an archived file, + // this mod is now the origin and the previous origin is the first alternative + else if ((m_Parent != nullptr) + && ((m_Parent->getOriginByID(origin).getPriority() > m_Parent->getOriginByID(m_Origin).getPriority()) + || (archive.size() == 0 && m_Archive.first.size() > 0 ))) { if (std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair> &i) -> bool { return i.first == m_Origin; }) == m_Alternatives.end()) { m_Alternatives.push_back(std::pair>(m_Origin, m_Archive)); } m_Origin = origin; m_FileTime = fileTime; m_Archive = std::pair(archive, order); - } else { + } + + // This mod is just an alternative + else { bool found = false; if (m_Origin == origin) { // already an origin -- cgit v1.3.1