From 7b45d807d6c2c8b5663ec53183e81e16a5baf739 Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Fri, 15 Dec 2017 15:01:39 -0600 Subject: Restore archive tab and partial functionality --- src/modinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/modinfo.cpp') diff --git a/src/modinfo.cpp b/src/modinfo.cpp index 4f74086f..d3687d31 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -94,7 +94,7 @@ QString ModInfo::getContentTypeName(int contentType) case CONTENT_PLUGIN: return tr("Plugins"); case CONTENT_TEXTURE: return tr("Textures"); case CONTENT_MESH: return tr("Meshes"); - case CONTENT_BSA: return tr("BSA"); + case CONTENT_BSA: return tr("Bethesda Archive"); case CONTENT_INTERFACE: return tr("UI Changes"); case CONTENT_SOUND: return tr("Sound Effects"); case CONTENT_SCRIPT: return tr("Scripts"); -- cgit v1.3.1 From 385a888c0bc8e5b4d4a6791e46eed3b5963c403a Mon Sep 17 00:00:00 2001 From: Jeremy Rimpo Date: Sun, 17 Dec 2017 21:33:04 -0600 Subject: Implement file priority for loose files > archives --- src/mainwindow.cpp | 24 +++++++-------- src/mainwindow.ui | 30 +++++++++--------- src/modinfo.cpp | 3 +- src/modinfodialog.cpp | 10 +++--- src/modinfowithconflictinfo.cpp | 10 +++--- src/modlist.cpp | 11 +++---- src/organizercore.cpp | 8 ++--- src/pluginlist.cpp | 26 ++++++++-------- src/shared/directoryentry.cpp | 68 ++++++++++++++++++++++------------------- src/shared/directoryentry.h | 6 ++-- src/syncoverwritedialog.cpp | 6 ++-- 11 files changed, 103 insertions(+), 99 deletions(-) (limited to 'src/modinfo.cpp') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 141bcf2a..22e99e37 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1148,17 +1148,17 @@ void MainWindow::updateTo(QTreeWidgetItem *subTree, const std::wstring &director fileChild->setData(1, Qt::UserRole, source); fileChild->setData(1, Qt::UserRole + 1, originID); - std::vector alternatives = current->getAlternatives(); + std::vector> alternatives = current->getAlternatives(); if (!alternatives.empty()) { std::wostringstream altString; altString << ToWString(tr("Also in:
")); - for (std::vector::iterator altIter = alternatives.begin(); + for (std::vector>::iterator altIter = alternatives.begin(); altIter != alternatives.end(); ++altIter) { if (altIter != alternatives.begin()) { altString << " , "; } - altString << "" << m_OrganizerCore.directoryStructure()->getOriginByID(*altIter).getName() << ""; + altString << "" << m_OrganizerCore.directoryStructure()->getOriginByID(altIter->first).getName() << ""; } fileChild->setToolTip(1, QString("%1").arg(ToQString(altString.str()))); fileChild->setForeground(1, QBrush(Qt::red)); @@ -1396,7 +1396,8 @@ void MainWindow::updateBSAList(const QStringList &defaultArchives, const QString QStringList plugins = m_OrganizerCore.findFiles("", [](const QString &fileName) -> bool { return fileName.endsWith(".esp", Qt::CaseInsensitive) - || fileName.endsWith(".esm", Qt::CaseInsensitive); + || fileName.endsWith(".esm", Qt::CaseInsensitive) + || fileName.endsWith(".esl", Qt::CaseInsensitive); }); auto hasAssociatedPlugin = [&](const QString &bsaName) -> bool { @@ -1434,7 +1435,7 @@ void MainWindow::updateBSAList(const QStringList &defaultArchives, const QString << ToQString(origin.getName())); newItem->setData(0, Qt::UserRole, index); newItem->setData(1, Qt::UserRole, originId); - newItem->setFlags(newItem->flags() & ~Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable); + newItem->setFlags(newItem->flags() & ~(Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable)); newItem->setCheckState(0, (index != -1) ? Qt::Checked : Qt::Unchecked); newItem->setData(0, Qt::UserRole, false); if (m_OrganizerCore.settings().forceEnableCoreFiles() @@ -1448,6 +1449,9 @@ void MainWindow::updateBSAList(const QStringList &defaultArchives, const QString } else if (hasAssociatedPlugin(fileInfo.fileName())) { newItem->setCheckState(0, Qt::Checked); newItem->setDisabled(true); + } else { + newItem->setCheckState(0, Qt::Unchecked); + newItem->setDisabled(true); } if (index < 0) index = 0; @@ -2900,11 +2904,7 @@ void MainWindow::saveArchiveList() for (int j = 0; j < tlItem->childCount(); ++j) { QTreeWidgetItem * item = tlItem->child(j); if (item->checkState(0) == Qt::Checked) { - // in managed mode, "register" all enabled archives, otherwise register only the files registered in the ini - if (ui->manageArchivesBox->isChecked() || - item->data(0, Qt::UserRole).toBool()) { - archiveFile->write(item->text(0).toUtf8().append("\r\n")); - } + archiveFile->write(item->text(0).toUtf8().append("\r\n")); } } } @@ -3763,8 +3763,8 @@ void MainWindow::previewDataFile() }; addFunc(file->getOrigin()); - for (int i : file->getAlternatives()) { - addFunc(i); + for (auto alt : file->getAlternatives()) { + addFunc(alt.first); } if (preview.numVariants() > 0) { preview.exec(); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 1e7339b8..d8fa1432 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -922,23 +922,23 @@ p, li { white-space: pre-wrap; } - - - - - - - true - - - + + + + + + + + + + - <html><head/><body><p>BSAs are bundles of game assets (textures, scripts, ...). By default, the engine loads these bundles in a separate step from loose files. MO can manage those archives to align their load order with that of loose files:</p><p>If archives are <span style=" font-weight:600;">managed</span>, their load order is specified by the priority of the corresponding mod (left pane), the same as the loose files. You can manually enable any BSA that has no corresponding plugin active.<br/></p><p>If archives are <span style=" font-weight:600;">not managed</span> their load order is specified by the priority of the corresponding plugin (right pane, plugins tab). You can then not manually enable BSAs where the plugin isn't active.</p><p>In either case you can not disable archives if there is a matching plugin, the game will load them no matter what.</p></body></html> + <html><head/><body><p>BSAs / BA2s are bundles of game assets (textures, scripts, etc.). By default, the engine loads these bundles in a separate step from loose files. <p>Their load order is specified by the priority of the corresponding plugin (right pane, plugins tab).</p><p>If there is a matching plugin, the game will load them no matter what.</p></body></html> - <html><head/><body><p>Have MO manage archives (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">read more</span></a>)</p></body></html> + <html><head/><body><p>Currently detected archives. (<a href="#"><span style=" text-decoration: underline; color:#0000ff;">What is an archive?</span></a>)</p></body></html> true @@ -965,7 +965,7 @@ p, li { white-space: pre-wrap; } QAbstractItemView::NoEditTriggers - true + false false @@ -974,10 +974,10 @@ p, li { white-space: pre-wrap; } false - QAbstractItemView::DragDrop + QAbstractItemView::NoDragDrop - Qt::MoveAction + Qt::IgnoreAction QAbstractItemView::SingleSelection diff --git a/src/modinfo.cpp b/src/modinfo.cpp index d3687d31..c14eedb7 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -123,9 +123,10 @@ ModInfo::Ptr ModInfo::getByIndex(unsigned int index) { QMutexLocker locker(&s_Mutex); - if (index >= s_Collection.size()) { + if (index >= s_Collection.size() && index != ULONG_MAX) { throw MyException(tr("invalid mod index %1").arg(index)); } + if (index == ULONG_MAX) return s_Collection[ModInfo::getIndex("Overwrite")]; return s_Collection[index]; } diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp index d43808b6..ccd2a122 100644 --- a/src/modinfodialog.cpp +++ b/src/modinfodialog.cpp @@ -266,22 +266,22 @@ void ModInfoDialog::refreshLists() QString fileName = relativeName.mid(0).prepend(m_RootPath); bool archive; if ((*iter)->getOrigin(archive) == m_Origin->getID()) { - std::vector alternatives = (*iter)->getAlternatives(); + std::vector> alternatives = (*iter)->getAlternatives(); if (!alternatives.empty()) { std::wostringstream altString; - for (std::vector::iterator altIter = alternatives.begin(); + for (std::vector>::iterator altIter = alternatives.begin(); altIter != alternatives.end(); ++altIter) { if (altIter != alternatives.begin()) { altString << ", "; } - altString << m_Directory->getOriginByID(*altIter).getName(); + altString << m_Directory->getOriginByID(altIter->first).getName(); } QStringList fields(relativeName.prepend("...")); 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[0]).getName())); - item->setData(1, Qt::UserRole + 1, alternatives[0]); + 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 + 2, archive); ui->overwriteTree->addTopLevelItem(item); ++numOverwrite; diff --git a/src/modinfowithconflictinfo.cpp b/src/modinfowithconflictinfo.cpp index fbf2345f..b8ece783 100644 --- a/src/modinfowithconflictinfo.cpp +++ b/src/modinfowithconflictinfo.cpp @@ -57,8 +57,8 @@ void ModInfoWithConflictInfo::doConflictCheck() const std::vector files = origin.getFiles(); // for all files in this origin for (FileEntry::Ptr file : files) { - const std::vector &alternatives = file->getAlternatives(); - if ((alternatives.size() == 0) || (alternatives[0] == dataID)) { + const std::vector> &alternatives = file->getAlternatives(); + if ((alternatives.size() == 0) || (alternatives.begin()->first == dataID)) { // no alternatives -> no conflict providesAnything = true; } else { @@ -71,9 +71,9 @@ void ModInfoWithConflictInfo::doConflictCheck() const } // for all non-providing alternative origins - for (int altId : alternatives) { - if ((altId != dataID) && (altId != origin.getID())) { - FilesOrigin &altOrigin = (*m_DirectoryStructure)->getOriginByID(altId); + 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); diff --git a/src/modlist.cpp b/src/modlist.cpp index d7b5f471..3afa94b5 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -701,14 +701,13 @@ void ModList::highlightMods(const QItemSelection &selected, const MOShared::Dire if (fileEntry.get() != nullptr) { QString fileName; bool archive = false; - std::vector origins; + std::vector> origins; { - std::vector alternatives = fileEntry->getAlternatives(); - origins.push_back(fileEntry->getOrigin(archive)); - origins.insert(origins.end(), alternatives.begin(), alternatives.end()); + std::vector> alternatives = fileEntry->getAlternatives(); + origins.insert(origins.end(), std::pair(fileEntry->getOrigin(archive), fileEntry->getArchive())); } - for (int originId : origins) { - MOShared::FilesOrigin &origin = directoryEntry.getOriginByID(originId); + for (auto originInfo : origins) { + MOShared::FilesOrigin &origin = directoryEntry.getOriginByID(originInfo.first); for (unsigned int i = 0; i < ModInfo::getNumMods(); ++i) { if (ModInfo::getByIndex(i)->internalName() == QString::fromStdWString(origin.getName())) { ModInfo::getByIndex(i)->setPluginSelected(true); diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 1a336d91..98920479 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1002,9 +1002,9 @@ QStringList OrganizerCore::getFileOrigins(const QString &fileName) const if (file.get() != nullptr) { result.append(ToQString( m_DirectoryStructure->getOriginByID(file->getOrigin()).getName())); - foreach (int i, file->getAlternatives()) { + foreach (auto i, file->getAlternatives()) { result.append( - ToQString(m_DirectoryStructure->getOriginByID(i).getName())); + ToQString(m_DirectoryStructure->getOriginByID(i.first).getName())); } } else { qDebug("%s not found", qPrintable(fileName)); @@ -1030,9 +1030,9 @@ QList OrganizerCore::findFileInfos( m_DirectoryStructure->getOriginByID(file->getOrigin(fromArchive)) .getName())); info.archive = fromArchive ? ToQString(file->getArchive()) : ""; - foreach (int idx, file->getAlternatives()) { + foreach (auto idx, file->getAlternatives()) { info.origins.append( - ToQString(m_DirectoryStructure->getOriginByID(idx).getName())); + ToQString(m_DirectoryStructure->getOriginByID(idx.first).getName())); } if (filter(info)) { diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 6392d44b..775086fd 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -115,23 +115,23 @@ void PluginList::highlightPlugins(const QItemSelection &selected, const MOShared } for (QModelIndex idx : selected.indexes()) { ModInfo::Ptr selectedMod = ModInfo::getByIndex(idx.data(Qt::UserRole + 1).toInt()); - if (!selectedMod.isNull() && profile.modEnabled(idx.data(Qt::UserRole + 1).toInt())) { - QDir dir(selectedMod->absolutePath()); - QStringList plugins = dir.entryList(QStringList() << "*.esp" << "*.esm" << "*.esl"); - MOShared::FilesOrigin origin = directoryEntry.getOriginByName(selectedMod->internalName().toStdWString()); - if (plugins.size() > 0) { - for (auto plugin : plugins) { + if (!selectedMod.isNull() && profile.modEnabled(idx.data(Qt::UserRole + 1).toInt())) { + QDir dir(selectedMod->absolutePath()); + QStringList plugins = dir.entryList(QStringList() << "*.esp" << "*.esm" << "*.esl"); + MOShared::FilesOrigin origin = directoryEntry.getOriginByName(selectedMod->internalName().toStdWString()); + if (plugins.size() > 0) { + for (auto plugin : plugins) { MOShared::FileEntry::Ptr file = directoryEntry.findFile(plugin.toStdWString()); if (file->getOrigin() != origin.getID()) { - const std::vector alternatives = file->getAlternatives(); - if (std::find(alternatives.begin(), alternatives.end(), origin.getID()) == alternatives.end()) + const std::vector> alternatives = file->getAlternatives(); + if (std::find_if(alternatives.begin(), alternatives.end(), [&](const std::pair& element) { return element.first == origin.getID(); }) == alternatives.end()) continue; } - std::map::iterator iter = m_ESPsByName.find(plugin.toLower()); - if (iter != m_ESPsByName.end()) { - m_ESPs[iter->second].m_ModSelected = true; - } - } + std::map::iterator iter = m_ESPsByName.find(plugin.toLower()); + if (iter != m_ESPsByName.end()) { + m_ESPs[iter->second].m_ModSelected = true; + } + } } } } diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index df6a7b5a..e1cba08c 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -236,9 +236,10 @@ void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &arc m_FileTime = fileTime; m_Archive = archive; } else if ((m_Parent != nullptr) - && (m_Parent->getOriginByID(origin).getPriority() > m_Parent->getOriginByID(m_Origin).getPriority())) { - if (std::find(m_Alternatives.begin(), m_Alternatives.end(), m_Origin) == m_Alternatives.end()) { - m_Alternatives.push_back(m_Origin); + && (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)); } m_Origin = origin; m_FileTime = fileTime; @@ -249,20 +250,20 @@ void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &arc // already an origin return; } - for (std::vector::iterator iter = m_Alternatives.begin(); iter != m_Alternatives.end(); ++iter) { - if (*iter == origin) { + 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).getPriority() < m_Parent->getOriginByID(origin).getPriority())) { - m_Alternatives.insert(iter, origin); + && (m_Parent->getOriginByID(iter->first).getPriority() < m_Parent->getOriginByID(origin).getPriority())) { + m_Alternatives.insert(iter, std::pair(origin, archive)); found = true; break; } } if (!found) { - m_Alternatives.push_back(origin); + m_Alternatives.push_back(std::pair(origin, archive)); } } } @@ -272,14 +273,14 @@ 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) { - if ((m_Parent->getOriginByID(*iter).getPriority() > m_Parent->getOriginByID(*currentIter).getPriority()) && - (*iter != origin)) { + 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; } } - int currentID = *currentIter; + int currentID = currentIter->first; m_Alternatives.erase(currentIter); m_Origin = currentID; @@ -303,23 +304,13 @@ bool FileEntry::removeOrigin(int origin) return true; } } else { - std::vector::iterator newEnd = std::remove(m_Alternatives.begin(), m_Alternatives.end(), origin); - m_Alternatives.erase(newEnd, m_Alternatives.end()); + 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()); } return false; } - -// sorted by priority descending -static bool ByOriginPriority(DirectoryEntry *entry, int LHS, int RHS) -{ - int l = entry->getOriginByID(LHS).getPriority(); if (l < 0) l = INT_MAX; - int r = entry->getOriginByID(RHS).getPriority(); if (r < 0) r = INT_MAX; - - return l < r; -} - - FileEntry::FileEntry() : m_Index(UINT_MAX), m_Name(), m_Origin(-1), m_Parent(nullptr), m_LastAccessed(time(nullptr)) { @@ -339,10 +330,23 @@ FileEntry::~FileEntry() void FileEntry::sortOrigins() { - m_Alternatives.push_back(m_Origin); - std::sort(m_Alternatives.begin(), m_Alternatives.end(), boost::bind(ByOriginPriority, m_Parent, _1, _2)); - m_Origin = m_Alternatives[m_Alternatives.size() - 1]; - m_Alternatives.pop_back(); + 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())) { + 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; + return true; + }); + if (!m_Alternatives.empty()) { + m_Origin = m_Alternatives.back().first; + m_Archive = m_Alternatives.back().second; + m_Alternatives.pop_back(); + } } @@ -886,9 +890,9 @@ 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).removeFile(file->getIndex()); + m_OriginConnection->getByID(iter->first).removeFile(file->getIndex()); } // unregister from directory diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index 04b8782b..8dbedaf4 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -72,7 +72,7 @@ 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; } @@ -96,9 +96,9 @@ private: Index m_Index; std::wstring m_Name; - int m_Origin; + int m_Origin = -1; std::wstring m_Archive; - std::vector m_Alternatives; + std::vector> m_Alternatives; DirectoryEntry *m_Parent; mutable FILETIME m_FileTime; diff --git a/src/syncoverwritedialog.cpp b/src/syncoverwritedialog.cpp index aeed0a55..f03e29c5 100644 --- a/src/syncoverwritedialog.cpp +++ b/src/syncoverwritedialog.cpp @@ -98,9 +98,9 @@ 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 &alternatives = entry->getAlternatives(); - for (std::vector::const_iterator iter = alternatives.begin(); iter != alternatives.end(); ++iter) { - addToComboBox(combo, ToQString(m_DirectoryStructure->getOriginByID(*iter).getName()), *iter); + const std::vector> &alternatives = entry->getAlternatives(); + for (std::vector>::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); } else { -- cgit v1.3.1