diff options
| author | Silarn <jrim@rimpo.org> | 2018-04-11 17:46:59 -0500 |
|---|---|---|
| committer | LostDragonist <lost.dragonist@gmail.com> | 2018-12-12 20:15:55 -0600 |
| commit | 8d6c715672023577dca5a6528ff49081dede1052 (patch) | |
| tree | 19640a69058b966e70ff2173def1a3e238aa9793 | |
| parent | 20008e17b71f3b23f94893554b3623b2d4f732d6 (diff) | |
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
| -rw-r--r-- | src/directoryrefresher.cpp | 27 | ||||
| -rw-r--r-- | src/directoryrefresher.h | 1 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 25 | ||||
| -rw-r--r-- | src/modflagicondelegate.cpp | 3 | ||||
| -rw-r--r-- | src/modinfo.h | 24 | ||||
| -rw-r--r-- | src/modinfodialog.cpp | 8 | ||||
| -rw-r--r-- | src/modinfodialog.h | 2 | ||||
| -rw-r--r-- | src/modinfowithconflictinfo.cpp | 75 | ||||
| -rw-r--r-- | src/modinfowithconflictinfo.h | 12 | ||||
| -rw-r--r-- | src/modlist.cpp | 40 | ||||
| -rw-r--r-- | src/modlist.h | 6 | ||||
| -rw-r--r-- | src/modlistsortproxy.cpp | 5 | ||||
| -rw-r--r-- | src/organizercore.cpp | 2 | ||||
| -rw-r--r-- | src/pluginlist.cpp | 4 | ||||
| -rw-r--r-- | src/shared/directoryentry.cpp | 114 | ||||
| -rw-r--r-- | src/shared/directoryentry.h | 26 | ||||
| -rw-r--r-- | src/syncoverwritedialog.cpp | 4 |
17 files changed, 295 insertions, 83 deletions
diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp index 272b0596..5c789049 100644 --- a/src/directoryrefresher.cpp +++ b/src/directoryrefresher.cpp @@ -27,6 +27,8 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <QApplication>
#include <QDir>
#include <QString>
+#include <QTextCodec>
+#include <gameplugins.h>
using namespace MOBase;
@@ -83,13 +85,30 @@ void DirectoryRefresher::addModBSAToStructure(DirectoryEntry *directoryStructure int priority, const QString &directory, const QStringList &archives)
{
std::wstring directoryW = ToWString(QDir::toNativeSeparators(directory));
+ QStringList loadOrder = QStringList();
for (const QString &archive : archives) {
QFileInfo fileInfo(archive);
if (m_EnabledArchives.find(fileInfo.fileName()) != m_EnabledArchives.end()) {
+ IPluginGame *game = qApp->property("managed_game").value<IPluginGame*>();
+
+ GamePlugins *gamePlugins = game->feature<GamePlugins>();
+ QStringList loadOrder = QStringList();
+ gamePlugins->getLoadOrder(loadOrder);
+
+ int order = -1;
+
+ for (auto plugin : loadOrder)
+ {
+ QString name = plugin.left(plugin.size() - 4);
+ if (fileInfo.fileName().startsWith(name + " - ", Qt::CaseInsensitive) || fileInfo.fileName().startsWith(name + ".", Qt::CaseInsensitive)) {
+ order = loadOrder.indexOf(plugin);
+ }
+ }
+
try {
- //directoryStructure->addFromBSA(ToWString(modName), directoryW,
- // ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority);
+ IPluginGame *game = qApp->property("managed_game").value<IPluginGame*>();
+ directoryStructure->addFromBSA(ToWString(modName), directoryW, ToWString(QDir::toNativeSeparators(fileInfo.absoluteFilePath())), priority, order);
} catch (const std::exception &e) {
throw MyException(tr("failed to parse bsa %1: %2").arg(archive, e.what()));
}
@@ -115,7 +134,7 @@ void DirectoryRefresher::addModFilesToStructure(DirectoryEntry *directoryStructu file->removeOrigin(0);
}
origin.addFile(file->getIndex());
- file->addOrigin(origin.getID(), file->getFileTime(), L"");
+ file->addOrigin(origin.getID(), file->getFileTime(), L"", -1);
} else {
qWarning("%s not found", qPrintable(fileInfo.fileName()));
}
@@ -162,6 +181,8 @@ void DirectoryRefresher::refresh() emit progress((i * 100) / static_cast<int>(m_Mods.size()) + 1);
}
+ m_DirectoryStructure->getFileRegister()->sortOrigins();
+
emit progress(100);
cleanStructure(m_DirectoryStructure);
diff --git a/src/directoryrefresher.h b/src/directoryrefresher.h index 53709e1e..a4fc5dbc 100644 --- a/src/directoryrefresher.h +++ b/src/directoryrefresher.h @@ -27,6 +27,7 @@ along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>. #include <vector>
#include <set>
#include <tuple>
+#include "profile.h"
/**
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 931fa2af..832f42d0 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1263,9 +1263,9 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director source = modInfo->name();
}
- std::wstring archive = current->getArchive();
- if (archive.length() != 0) {
- source.append(" (").append(ToQString(archive)).append(")");
+ std::pair<std::wstring, int> archive = current->getArchive();
+ if (archive.first.length() != 0) {
+ source.append(" (").append(ToQString(archive.first)).append(")");
}
columns.append(source);
QTreeWidgetItem *fileChild = new QTreeWidgetItem(columns);
@@ -1287,12 +1287,12 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director fileChild->setData(1, Qt::UserRole, source);
fileChild->setData(1, Qt::UserRole + 1, originID);
- std::vector<std::pair<int, std::wstring>> alternatives = current->getAlternatives();
+ std::vector<std::pair<int, std::pair<std::wstring, int>>> alternatives = current->getAlternatives();
if (!alternatives.empty()) {
std::wostringstream altString;
altString << ToWString(tr("Also in: <br>"));
- for (std::vector<std::pair<int, std::wstring>>::iterator altIter = alternatives.begin();
+ for (std::vector<std::pair<int, std::pair<std::wstring, int>>>::iterator altIter = alternatives.begin();
altIter != alternatives.end(); ++altIter) {
if (altIter != alternatives.begin()) {
altString << " , ";
@@ -2196,9 +2196,16 @@ void MainWindow::modorder_changed() for (int i : modInfo->getModOverwritten()) {
ModInfo::getByIndex(i)->clearCaches();
}
+ for (int i : modInfo->getModArchiveOverwrite()) {
+ ModInfo::getByIndex(i)->clearCaches();
+ }
+ for (int i : modInfo->getModArchiveOverwritten()) {
+ ModInfo::getByIndex(i)->clearCaches();
+ }
// update conflict check on the moved mod
modInfo->doConflictCheck();
m_OrganizerCore.modList()->setOverwriteMarkers(modInfo->getModOverwrite(), modInfo->getModOverwritten());
+ m_OrganizerCore.modList()->setArchiveOverwriteMarkers(modInfo->getModArchiveOverwrite(), modInfo->getModArchiveOverwritten());
if (m_ModListSortProxy != nullptr) {
m_ModListSortProxy->invalidate();
}
@@ -2274,7 +2281,7 @@ void MainWindow::fileMoved(const QString &filePath, const QString &oldOriginName WIN32_FIND_DATAW findData;
HANDLE hFind;
hFind = ::FindFirstFileW(ToWString(fullNewPath).c_str(), &findData);
- filePtr->addOrigin(newOrigin.getID(), findData.ftCreationTime, L"");
+ filePtr->addOrigin(newOrigin.getID(), findData.ftCreationTime, L"", -1);
FindClose(hFind);
}
if (m_OrganizerCore.directoryStructure()->originExists(ToWString(oldOriginName))) {
@@ -2434,8 +2441,10 @@ void MainWindow::modlistSelectionChanged(const QModelIndex ¤t, const QMode if (current.isValid()) {
ModInfo::Ptr selectedMod = ModInfo::getByIndex(current.data(Qt::UserRole + 1).toInt());
m_OrganizerCore.modList()->setOverwriteMarkers(selectedMod->getModOverwrite(), selectedMod->getModOverwritten());
+ m_OrganizerCore.modList()->setArchiveOverwriteMarkers(selectedMod->getModArchiveOverwrite(), selectedMod->getModArchiveOverwritten());
} else {
m_OrganizerCore.modList()->setOverwriteMarkers(std::set<unsigned int>(), std::set<unsigned int>());
+ m_OrganizerCore.modList()->setArchiveOverwriteMarkers(std::set<unsigned int>(), std::set<unsigned int>());
}
/* if ((m_ModListSortProxy != nullptr)
&& !m_ModListSortProxy->beingInvalidated()) {
@@ -2656,7 +2665,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, }
} else {
modInfo->saveMeta();
- ModInfoDialog dialog(modInfo, m_OrganizerCore.directoryStructure(), modInfo->hasFlag(ModInfo::FLAG_FOREIGN), &m_OrganizerCore, &m_PluginContainer,this);
+ ModInfoDialog dialog(modInfo, m_OrganizerCore.directoryStructure(), modInfo->hasFlag(ModInfo::FLAG_FOREIGN), &m_OrganizerCore, &m_PluginContainer, this);
connect(&dialog, SIGNAL(linkActivated(QString)), this, SLOT(linkClicked(QString)));
connect(&dialog, SIGNAL(downloadRequest(QString)), &m_OrganizerCore, SLOT(downloadRequestedNXM(QString)));
connect(&dialog, SIGNAL(modOpen(QString, int)), this, SLOT(displayModInformation(QString, int)), Qt::QueuedConnection);
@@ -2691,7 +2700,6 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, m_OrganizerCore.settings().directInterface().setValue("mod_info_tabs", dialog.saveTabState());
settings.setValue(key, dialog.saveGeometry());
-
modInfo->saveMeta();
emit modInfoDisplayed();
m_OrganizerCore.modList()->modInfoChanged(modInfo);
@@ -2713,6 +2721,7 @@ void MainWindow::displayModInformation(ModInfo::Ptr modInfo, unsigned int index, , modInfo->stealFiles()
, modInfo->archives());
DirectoryRefresher::cleanStructure(m_OrganizerCore.directoryStructure());
+ m_OrganizerCore.directoryStructure()->getFileRegister()->sortOrigins();
m_OrganizerCore.refreshLists();
}
}
diff --git a/src/modflagicondelegate.cpp b/src/modflagicondelegate.cpp index 1995964b..4404ce60 100644 --- a/src/modflagicondelegate.cpp +++ b/src/modflagicondelegate.cpp @@ -49,6 +49,9 @@ QString ModFlagIconDelegate::getFlagIcon(ModInfo::EFlag flag) const 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_CONFLICT_MIXED: return ":/MO/gui/archive_conflict_mixed";
+ case ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITE: return ":/MO/gui/archive_conflict_winner";
+ case ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITTEN: return ":/MO/gui/archive_conflict_loser";
default: return QString();
}
}
diff --git a/src/modinfo.h b/src/modinfo.h index 5a69185d..15876a23 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -72,6 +72,9 @@ public: FLAG_CONFLICT_OVERWRITTEN,
FLAG_CONFLICT_MIXED,
FLAG_CONFLICT_REDUNDANT,
+ FLAG_ARCHIVE_CONFLICT_OVERWRITE,
+ FLAG_ARCHIVE_CONFLICT_OVERWRITTEN,
+ FLAG_ARCHIVE_CONFLICT_MIXED,
FLAG_PLUGIN_SELECTED,
FLAG_ALTERNATE_GAME
};
@@ -90,7 +93,6 @@ public: CONTENT_MCM,
CONTENT_INI,
CONTENT_MODGROUP
-
};
static const int NUM_CONTENT_TYPES = CONTENT_MODGROUP + 1;
@@ -626,6 +628,26 @@ public: virtual std::set<unsigned int> getModOverwritten() { return std::set<unsigned int>(); }
/**
+ * @return retrieve list of mods (as mod index) with archives that are overwritten by this one. Updates may be delayed
+ */
+ virtual std::set<unsigned int> getModArchiveOverwrite() { return std::set<unsigned int>(); }
+
+ /**
+ * @return list of mods (as mod index) with archives that overwrite this one. Updates may be delayed
+ */
+ virtual std::set<unsigned int> getModArchiveOverwritten() { return std::set<unsigned int>(); }
+
+ /**
+ * @return retrieve list of mods (as mod index) with archives that are overwritten by this one. Updates may be delayed
+ */
+ virtual std::set<unsigned int> getModArchiveOverwrite() { return std::set<unsigned int>(); }
+
+ /**
+ * @return list of mods (as mod index) with archives that overwrite this one. Updates may be delayed
+ */
+ virtual std::set<unsigned int> getModArchiveOverwritten() { return std::set<unsigned int>(); }
+
+ /**
* @brief update conflict information
*/
virtual void doConflictCheck() const {}
diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index 416eca58..204b539b 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -312,10 +312,10 @@ void ModInfoDialog::refreshLists() QString fileName = relativeName.mid(0).prepend(m_RootPath);
bool archive;
if ((*iter)->getOrigin(archive) == m_Origin->getID()) {
- std::vector<std::pair<int, std::wstring>> alternatives = (*iter)->getAlternatives();
+ std::vector<std::pair<int, std::pair<std::wstring, int>>> alternatives = (*iter)->getAlternatives();
if (!alternatives.empty()) {
std::wostringstream altString;
- for (std::vector<std::pair<int, std::wstring>>::iterator altIter = alternatives.begin();
+ for (std::vector<std::pair<int, std::pair<std::wstring, int>>>::iterator altIter = alternatives.begin();
altIter != alternatives.end(); ++altIter) {
if (altIter != alternatives.begin()) {
altString << ", ";
@@ -326,8 +326,8 @@ void ModInfoDialog::refreshLists() fields.append(ToQString(altString.str()));
QTreeWidgetItem *item = new QTreeWidgetItem(fields);
item->setData(0, Qt::UserRole, fileName);
- item->setData(1, Qt::UserRole, ToQString(m_Directory->getOriginByID(alternatives.begin()->first).getName()));
- item->setData(1, Qt::UserRole + 1, alternatives.begin()->first);
+ item->setData(1, Qt::UserRole, ToQString(m_Directory->getOriginByID(alternatives.back().first).getName()));
+ item->setData(1, Qt::UserRole + 1, alternatives.back().first);
item->setData(1, Qt::UserRole + 2, archive);
ui->overwriteTree->addTopLevelItem(item);
++numOverwrite;
diff --git a/src/modinfodialog.h b/src/modinfodialog.h index f3bc48b4..6a315a93 100644 --- a/src/modinfodialog.h +++ b/src/modinfodialog.h @@ -78,7 +78,7 @@ public: * @param modInfo info structure about the mod to display
* @param parent parend widget
**/
- explicit ModInfoDialog(ModInfo::Ptr modInfo, const MOShared::DirectoryEntry *directory, bool unmanaged, OrganizerCore *organizerCore, PluginContainer *pluginContainer,QWidget *parent = 0);
+ explicit ModInfoDialog(ModInfo::Ptr modInfo, const MOShared::DirectoryEntry *directory, bool unmanaged, OrganizerCore *organizerCore, PluginContainer *pluginContainer, QWidget *parent = 0);
~ModInfoDialog();
/**
diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp index e88ba29d..67006261 100644 --- a/src/modinfowithconflictinfo.cpp +++ b/src/modinfowithconflictinfo.cpp @@ -32,6 +32,18 @@ std::vector<ModInfo::EFlag> ModInfoWithConflictInfo::getFlags() const } break; default: { /* NOP */ } } + switch (isArchiveConflicted()) { + case CONFLICT_MIXED: { + result.push_back(ModInfo::FLAG_ARCHIVE_CONFLICT_MIXED); + } break; + case CONFLICT_OVERWRITE: { + result.push_back(ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITE); + } break; + case CONFLICT_OVERWRITTEN: { + result.push_back(ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITTEN); + } break; + default: { /* NOP */ } + } return result; } @@ -40,6 +52,8 @@ void ModInfoWithConflictInfo::doConflictCheck() const { m_OverwriteList.clear(); m_OverwrittenList.clear(); + m_ArchiveOverwriteList.clear(); + m_ArchiveOverwrittenList.clear(); bool providesAnything = false; @@ -51,34 +65,66 @@ void ModInfoWithConflictInfo::doConflictCheck() const std::wstring name = ToWString(this->name()); m_CurrentConflictState = CONFLICT_NONE; + m_ArchiveConflictState = CONFLICT_NONE; if ((*m_DirectoryStructure)->originExists(name)) { FilesOrigin &origin = (*m_DirectoryStructure)->getOriginByName(name); std::vector<FileEntry::Ptr> files = origin.getFiles(); // for all files in this origin for (FileEntry::Ptr file : files) { - const std::vector<std::pair<int, std::wstring>> &alternatives = file->getAlternatives(); - if ((alternatives.size() == 0) || (alternatives.begin()->first == dataID)) { + auto alternatives = file->getAlternatives(); + if ((alternatives.size() == 0) || (alternatives.back().first == dataID)) { // no alternatives -> no conflict providesAnything = true; } else { if (file->getOrigin() != origin.getID()) { FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID(file->getOrigin()); unsigned int altIndex = ModInfo::getIndex(ToQString(altOrigin.getName())); - m_OverwrittenList.insert(altIndex); + if (file->getArchive().first.size() == 0) + m_OverwrittenList.insert(altIndex); + else + m_ArchiveOverwrittenList.insert(altIndex); } else { providesAnything = true; } // for all non-providing alternative origins + bool found = file->getOrigin() == origin.getID(); + std::pair<std::wstring, int> archiveData; + if (found) + archiveData = file->getArchive(); + else { + for (auto alts : alternatives) { + if (alts.first == origin.getID()) { + archiveData = alts.second; + break; + } + } + } for (auto altInfo : alternatives) { if ((altInfo.first != dataID) && (altInfo.first != origin.getID())) { FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID(altInfo.first); unsigned int altIndex = ModInfo::getIndex(ToQString(altOrigin.getName())); - if (origin.getPriority() > altOrigin.getPriority()) { - m_OverwriteList.insert(altIndex); + if (altInfo.second.first.size() == 0) { + if (archiveData.first.size() == 0) { + if (origin.getPriority() > altOrigin.getPriority()) { + m_OverwriteList.insert(altIndex); + } else { + m_OverwrittenList.insert(altIndex); + } + } else { + m_ArchiveOverwrittenList.insert(altIndex); + } } else { - m_OverwrittenList.insert(altIndex); + if (archiveData.first.size() == 0) { + m_ArchiveOverwrittenList.insert(altIndex); + } else { + if (archiveData.second > altInfo.second.second) { + m_ArchiveOverwriteList.insert(altIndex); + } else if (archiveData.second < altInfo.second.second) { + m_ArchiveOverwrittenList.insert(altIndex); + } + } } } } @@ -96,6 +142,13 @@ void ModInfoWithConflictInfo::doConflictCheck() const else if (!m_OverwrittenList.empty()) m_CurrentConflictState = CONFLICT_OVERWRITTEN; } + + if (!m_ArchiveOverwriteList.empty() && !m_ArchiveOverwrittenList.empty()) + m_ArchiveConflictState = CONFLICT_MIXED; + else if (!m_ArchiveOverwriteList.empty()) + m_ArchiveConflictState = CONFLICT_OVERWRITE; + else if (!m_ArchiveOverwrittenList.empty()) + m_ArchiveConflictState = CONFLICT_OVERWRITTEN; } } @@ -110,6 +163,16 @@ ModInfoWithConflictInfo::EConflictType ModInfoWithConflictInfo::isConflicted() c return m_CurrentConflictState; } +ModInfoWithConflictInfo::EConflictType ModInfoWithConflictInfo::isArchiveConflicted() const +{ + QTime now = QTime::currentTime(); + if (m_LastConflictCheck.isNull() || (m_LastConflictCheck.secsTo(now) > 10)) { + doConflictCheck(); + } + + return m_ArchiveConflictState; +} + bool ModInfoWithConflictInfo::isRedundant() const { diff --git a/src/modinfowithconflictinfo.h b/src/modinfowithconflictinfo.h index 6c1591c5..5cf2d24e 100644 --- a/src/modinfowithconflictinfo.h +++ b/src/modinfowithconflictinfo.h @@ -23,6 +23,10 @@ public: virtual std::set<unsigned int> getModOverwritten() { return m_OverwrittenList; } + virtual std::set<unsigned int> getModArchiveOverwrite() { return m_ArchiveOverwriteList; } + + virtual std::set<unsigned int> getModArchiveOverwritten() { return m_ArchiveOverwrittenList; } + virtual void doConflictCheck() const; private: @@ -43,6 +47,11 @@ private: EConflictType isConflicted() const; /** + * @return true if there are archive conflicts for files in this mod + */ + EConflictType isArchiveConflicted() const; + + /** * @return true if this mod is completely replaced by others */ bool isRedundant() const; @@ -52,10 +61,13 @@ private: MOShared::DirectoryEntry **m_DirectoryStructure; mutable EConflictType m_CurrentConflictState; + mutable EConflictType m_ArchiveConflictState; mutable QTime m_LastConflictCheck; mutable std::set<unsigned int> m_OverwriteList; // indices of mods overritten by this mod mutable std::set<unsigned int> m_OverwrittenList; // indices of mods overwriting this mod + mutable std::set<unsigned int> m_ArchiveOverwriteList; // indices of mods with archive files overritten by this mod + mutable std::set<unsigned int> m_ArchiveOverwrittenList; // indices of mods with archive files overwriting this mod }; diff --git a/src/modlist.cpp b/src/modlist.cpp index 16d2cd07..e9a12862 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -163,6 +163,9 @@ QString ModList::getFlagText(ModInfo::EFlag flag, ModInfo::Ptr modInfo) const case ModInfo::FLAG_CONFLICT_MIXED: return tr("Overwrites & Overwritten");
case ModInfo::FLAG_CONFLICT_REDUNDANT: return tr("Redundant");
case ModInfo::FLAG_ALTERNATE_GAME: return tr("Alternate game source");
+ case ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITE: return tr("Overwrites another archive file");
+ case ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITTEN: return tr("Overwritten by another archive file");
+ case ModInfo::FLAG_ARCHIVE_CONFLICT_MIXED: return tr("Archive files overwrites & overwritten");
default: return "";
}
}
@@ -401,10 +404,18 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const || (role == ViewMarkingScrollBar::DEFAULT_ROLE)) {
if (modInfo->getHighlight() & ModInfo::HIGHLIGHT_PLUGIN) {
return Settings::instance().modlistContainsPluginColor();
- } else if (m_Overwrite.find(modIndex) != m_Overwrite.end()) {
+ } else if (m_Overwrite.find(modIndex) != m_Overwrite.end() && m_ArchiveOverwritten.find(modIndex) != m_ArchiveOverwritten.end()) {
+ return QColor(255, 0, 255, 32); //TODO: Make configurable
+ } else if (m_Overwrite.find(modIndex) != m_Overwrite.end() && m_ArchiveOverwritten.find(modIndex) != m_ArchiveOverwritten.end()) {
+ return QColor(255, 0, 255, 32); //TODO: Make configurable
+ } else if (m_Overwritten.find(modIndex) != m_Overwritten.end() && m_ArchiveOverwrite.find(modIndex) != m_ArchiveOverwrite.end()) {
+ return QColor(255, 0, 255, 32); //TODO: Make configurable
+ } else if (m_Overwritten.find(modIndex) != m_Overwritten.end() && m_ArchiveOverwrite.find(modIndex) != m_ArchiveOverwrite.end()) {
+ return QColor(255, 0, 255, 32); //TODO: Make configurable
+ } else if (m_Overwrite.find(modIndex) != m_Overwrite.end() || m_ArchiveOverwrite.find(modIndex) != m_ArchiveOverwrite.end()) {
return Settings::instance().modlistOverwrittenLooseColor();
}
- else if (m_Overwritten.find(modIndex) != m_Overwritten.end()) {
+ } else if (m_Overwritten.find(modIndex) != m_Overwritten.end() || m_ArchiveOverwritten.find(modIndex) != m_ArchiveOverwritten.end()) {
return Settings::instance().modlistOverwritingLooseColor();
} else if (modInfo->hasFlag(ModInfo::FLAG_SEPARATOR)
&& modInfo->getColor().isValid()
@@ -516,7 +527,6 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) ModInfo::Ptr info = ModInfo::getByIndex(modID);
IModList::ModStates oldState = state(modID);
-
bool result = false;
emit aboutToChangeData();
@@ -754,9 +764,23 @@ void ModList::setOverwriteMarkers(const std::set<unsigned int> &overwrite, const notifyChange(0, rowCount() - 1);
}
+void ModList::setArchiveOverwriteMarkers(const std::set<unsigned int> &overwrite, const std::set<unsigned int> &overwritten)
+{
+ m_ArchiveOverwrite = overwrite;
+ m_ArchiveOverwritten = overwritten;
+ notifyChange(0, rowCount() - 1);
+}
+
void ModList::setPluginContainer(PluginContainer *pluginContianer)
{
- m_PluginContainer = pluginContianer;
+ m_PluginContainer = pluginContianer;
+}
+
+void ModList::setArchiveOverwriteMarkers(const std::set<unsigned int> &overwrite, const std::set<unsigned int> &overwritten)
+{
+ m_ArchiveOverwrite = overwrite;
+ m_ArchiveOverwritten = overwritten;
+ notifyChange(0, rowCount() - 1);
}
bool ModList::modInfoAboutToChange(ModInfo::Ptr info)
@@ -810,10 +834,10 @@ void ModList::highlightMods(const QItemSelectionModel *selection, const MOShared const MOShared::FileEntry::Ptr fileEntry = directoryEntry.findFile(modName.toStdWString());
if (fileEntry.get() != nullptr) {
bool archive = false;
- std::vector<std::pair<int, std::wstring>> origins;
+ std::vector<std::pair<int, std::pair<std::wstring, int>>> origins;
{
- std::vector<std::pair<int, std::wstring>> alternatives = fileEntry->getAlternatives();
- origins.insert(origins.end(), std::pair<int, std::wstring>(fileEntry->getOrigin(archive), fileEntry->getArchive()));
+ std::vector<std::pair<int, std::pair<std::wstring, int>>> alternatives = fileEntry->getAlternatives();
+ origins.insert(origins.end(), std::pair<int, std::pair<std::wstring, int>>(fileEntry->getOrigin(archive), fileEntry->getArchive()));
}
for (auto originInfo : origins) {
MOShared::FilesOrigin &origin = directoryEntry.getOriginByID(originInfo.first);
@@ -1117,6 +1141,8 @@ void ModList::notifyChange(int rowStart, int rowEnd) if (rowStart < 0) {
m_Overwrite.clear();
m_Overwritten.clear();
+ m_ArchiveOverwrite.clear();
+ m_ArchiveOverwritten.clear();
beginResetModel();
endResetModel();
} else {
diff --git a/src/modlist.h b/src/modlist.h index 42269386..5841b9f2 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -112,6 +112,10 @@ public: void setOverwriteMarkers(const std::set<unsigned int> &overwrite, const std::set<unsigned int> &overwritten);
void setPluginContainer(PluginContainer *pluginContainer);
+ void setArchiveOverwriteMarkers(const std::set<unsigned int> &overwrite, const std::set<unsigned int> &overwritten);
+
+ void setArchiveOverwriteMarkers(const std::set<unsigned int> &overwrite, const std::set<unsigned int> &overwritten);
+
bool modInfoAboutToChange(ModInfo::Ptr info);
void modInfoChanged(ModInfo::Ptr info);
@@ -331,6 +335,8 @@ private: std::set<unsigned int> m_Overwrite;
std::set<unsigned int> m_Overwritten;
+ std::set<unsigned int> m_ArchiveOverwrite;
+ std::set<unsigned int> m_ArchiveOverwritten;
TModInfoChange m_ChangeInfo;
diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index 9adaa511..6f6983ba 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -240,7 +240,10 @@ bool ModListSortProxy::hasConflictFlag(const std::vector<ModInfo::EFlag> &flags) if ((flag == ModInfo::FLAG_CONFLICT_MIXED) ||
(flag == ModInfo::FLAG_CONFLICT_OVERWRITE) ||
(flag == ModInfo::FLAG_CONFLICT_OVERWRITTEN) ||
- (flag == ModInfo::FLAG_CONFLICT_REDUNDANT)) {
+ (flag == ModInfo::FLAG_CONFLICT_REDUNDANT) ||
+ (flag == ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITE) ||
+ (flag == ModInfo::FLAG_ARCHIVE_CONFLICT_OVERWRITTEN) ||
+ (flag == ModInfo::FLAG_ARCHIVE_CONFLICT_MIXED)) {
return true;
}
}
diff --git a/src/organizercore.cpp b/src/organizercore.cpp index d52ef40b..f19f56c3 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1151,7 +1151,7 @@ QList<MOBase::IOrganizer::FileInfo> OrganizerCore::findFileInfos( info.origins.append(ToQString(
m_DirectoryStructure->getOriginByID(file->getOrigin(fromArchive))
.getName()));
- info.archive = fromArchive ? ToQString(file->getArchive()) : "";
+ info.archive = fromArchive ? ToQString(file->getArchive().first) : "";
foreach (auto idx, file->getAlternatives()) {
info.origins.append(
ToQString(m_DirectoryStructure->getOriginByID(idx.first).getName()));
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index b0f59e1e..04e39abf 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -140,8 +140,8 @@ void PluginList::highlightPlugins(const QItemSelectionModel *selection, const MO for (auto plugin : plugins) {
MOShared::FileEntry::Ptr file = directoryEntry.findFile(plugin.toStdWString());
if (file->getOrigin() != origin.getID()) {
- const std::vector<std::pair<int, std::wstring>> alternatives = file->getAlternatives();
- if (std::find_if(alternatives.begin(), alternatives.end(), [&](const std::pair<int, std::wstring>& element) { return element.first == origin.getID(); }) == alternatives.end())
+ const std::vector<std::pair<int, std::pair<std::wstring, int>>> alternatives = file->getAlternatives();
+ if (std::find_if(alternatives.begin(), alternatives.end(), [&](const std::pair<int, std::pair<std::wstring, int>>& element) { return element.first == origin.getID(); }) == alternatives.end())
continue;
}
std::map<QString, int>::iterator iter = m_ESPsByName.find(plugin.toLower());
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<FileEntry::Ptr> 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<std::wstring, int>(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<int, std::wstring> &i) -> bool { return i.first == m_Origin; }) == m_Alternatives.end()) {
- m_Alternatives.push_back(std::pair<int, std::wstring>(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<int, std::pair<std::wstring, int>> &i) -> bool { return i.first == m_Origin; }) == m_Alternatives.end()) {
+ m_Alternatives.push_back(std::pair<int, std::pair<std::wstring, int>>(m_Origin, m_Archive));
}
m_Origin = origin;
m_FileTime = fileTime;
- m_Archive = archive;
+ m_Archive = std::pair<std::wstring, int>(archive, order);
} else {
bool found = false;
if (m_Origin == origin) {
// already an origin
return;
}
- for (std::vector<std::pair<int, std::wstring>>::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) {
+ for (std::vector<std::pair<int, std::pair<std::wstring, int>>>::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<int, std::wstring>(origin, archive));
+ m_Alternatives.insert(iter, std::pair<int, std::pair<std::wstring, int>>(origin, std::pair<std::wstring, int>(archive, order)));
found = true;
break;
}
}
if (!found) {
- m_Alternatives.push_back(std::pair<int, std::wstring>(origin, archive));
+ m_Alternatives.push_back(std::pair<int, std::pair<std::wstring, int>>(origin, std::pair<std::wstring, int>(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<std::pair<int, std::wstring>>::iterator currentIter = m_Alternatives.begin();
- for (std::vector<std::pair<int, std::wstring>>::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) {
+ std::vector<std::pair<int, std::pair<std::wstring, int>>>::iterator currentIter = m_Alternatives.begin();
+ for (std::vector<std::pair<int, std::pair<std::wstring, int>>>::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<std::wstring, int>(L"bsa?", -1);
} else {
- m_Archive = L"";
+ m_Archive = std::pair<std::wstring, int>(L"", -1);
}
::CloseHandle(file);
@@ -304,7 +311,7 @@ bool FileEntry::removeOrigin(int origin) return true;
}
} else {
- std::vector<std::pair<int, std::wstring>>::iterator newEnd = std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair<int, std::wstring> &i) -> bool { return i.first == origin; });
+ std::vector<std::pair<int, std::pair<std::wstring, int>>>::iterator newEnd = std::find_if(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair<int, std::pair<std::wstring, int>> &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<int, std::wstring>(m_Origin, m_Archive));
- std::sort(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair<int, std::wstring> &LHS, const std::pair<int, std::wstring> &RHS) -> bool {
- if ((!LHS.second.size() && !RHS.second.size()) || (LHS.second.size() && RHS.second.size())) {
+ m_Alternatives.push_back(std::pair<int, std::pair<std::wstring, int>>(m_Origin, m_Archive));
+ std::sort(m_Alternatives.begin(), m_Alternatives.end(), [&](const std::pair<int, std::pair<std::wstring, int>> &LHS, const std::pair<int, std::pair<std::wstring, int>> &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<FileEntry::Index> &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<std::pair<int, std::wstring>> &alternatives = file->getAlternatives();
+ const std::vector<std::pair<int, std::pair<std::wstring, int>>> &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<std::pair<int, std::wstring>> &getAlternatives() const { return m_Alternatives; }
+ const std::vector<std::pair<int, std::pair<std::wstring, int>>> &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<std::wstring, int> &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<std::pair<int, std::wstring>> m_Alternatives;
+ std::pair<std::wstring, int> m_Archive;
+ std::vector<std::pair<int, std::pair<std::wstring, int>>> 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);
diff --git a/src/syncoverwritedialog.cpp b/src/syncoverwritedialog.cpp index f03e29c5..7c341567 100644 --- a/src/syncoverwritedialog.cpp +++ b/src/syncoverwritedialog.cpp @@ -98,8 +98,8 @@ void SyncOverwriteDialog::readTree(const QString &path, DirectoryEntry *director bool ignore;
int origin = entry->getOrigin(ignore);
addToComboBox(combo, ToQString(m_DirectoryStructure->getOriginByID(origin).getName()), origin);
- const std::vector<std::pair<int, std::wstring>> &alternatives = entry->getAlternatives();
- for (std::vector<std::pair<int, std::wstring>>::const_iterator iter = alternatives.begin(); iter != alternatives.end(); ++iter) {
+ const std::vector<std::pair<int, std::pair<std::wstring, int>>> &alternatives = entry->getAlternatives();
+ for (std::vector<std::pair<int, std::pair<std::wstring, int>>>::const_iterator iter = alternatives.begin(); iter != alternatives.end(); ++iter) {
addToComboBox(combo, ToQString(m_DirectoryStructure->getOriginByID(iter->first).getName()), iter->first);
}
combo->setCurrentIndex(combo->count() - 1);
|
