diff options
| author | LostDragonist <lost.dragonist@gmail.com> | 2019-01-22 17:57:46 -0600 |
|---|---|---|
| committer | LostDragonist <lost.dragonist@gmail.com> | 2019-01-22 17:57:46 -0600 |
| commit | 0ab87850c4cb405b93c592e455a9d052ec84f66f (patch) | |
| tree | 5fe08b611e70a3f0bff446dd3632de3acb1f33fb | |
| parent | 952a9c2dedf63e4b9b182b7dce379c4fe7898355 (diff) | |
| parent | 5800f2b7b32b564352b029b2f9a5fe27d05ee14c (diff) | |
Merge remote-tracking branch 'remotes/origin/Develop' into archive_conflicts_2
| -rw-r--r-- | src/instancemanager.cpp | 3 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 17 | ||||
| -rw-r--r-- | src/mainwindow.h | 1 | ||||
| -rw-r--r-- | src/modinfo.h | 2 | ||||
| -rw-r--r-- | src/modinfoforeign.h | 2 | ||||
| -rw-r--r-- | src/modinfooverwrite.cpp | 2 | ||||
| -rw-r--r-- | src/modinfooverwrite.h | 2 | ||||
| -rw-r--r-- | src/modinforegular.cpp | 20 | ||||
| -rw-r--r-- | src/modinforegular.h | 4 | ||||
| -rw-r--r-- | src/modlist.cpp | 40 | ||||
| -rw-r--r-- | src/modlist.h | 13 | ||||
| -rw-r--r-- | src/modlistsortproxy.cpp | 8 | ||||
| -rw-r--r-- | src/organizercore.cpp | 188 | ||||
| -rw-r--r-- | src/organizercore.h | 3 | ||||
| -rw-r--r-- | src/pluginlist.cpp | 24 | ||||
| -rw-r--r-- | src/profile.cpp | 31 | ||||
| -rw-r--r-- | src/profile.h | 17 |
17 files changed, 264 insertions, 113 deletions
diff --git a/src/instancemanager.cpp b/src/instancemanager.cpp index a5a52d63..b0a59363 100644 --- a/src/instancemanager.cpp +++ b/src/instancemanager.cpp @@ -138,7 +138,8 @@ QString InstanceManager::queryInstanceName(const QStringList &instanceList) cons dialog.setWindowTitle(QObject::tr("Enter a Name for the new Instance")); dialog.setLabelText(QObject::tr("Enter a new name or select one from the suggested list: \n" - "(This is just the name of the Instance, not the game selection)")); + "(This is just a name for the Instance and can be whatever you wish,\n" + " the actual game selection will happen on the next screen regardless of chosen name)")); // would be neat if we could take the names from the game plugins but // the required initialization order requires the ini file to be // available *before* we load plugins diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6cae2d63..44e63997 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2540,6 +2540,12 @@ void MainWindow::modlistChanged(const QModelIndex&, int) updateModCount();
}
+void MainWindow::modlistChanged(const QModelIndexList&, int)
+{
+ m_OrganizerCore.currentProfile()->writeModlist();
+ updateModCount();
+}
+
void MainWindow::modlistSelectionChanged(const QModelIndex ¤t, const QModelIndex&)
{
if (current.isValid()) {
@@ -3607,6 +3613,7 @@ void MainWindow::on_modList_doubleClicked(const QModelIndex &index) case ModList::COL_MODID: tab = ModInfoDialog::TAB_NEXUS; break;
case ModList::COL_GAME: tab = ModInfoDialog::TAB_NEXUS; break;
case ModList::COL_CATEGORY: tab = ModInfoDialog::TAB_CATEGORIES; break;
+ case ModList::COL_FLAGS: tab = ModInfoDialog::TAB_CONFLICTS; break;
default: tab = -1;
}
displayModInformation(sourceIdx.row(), tab);
@@ -5075,12 +5082,18 @@ void MainWindow::sendSelectedPluginsToPriority_clicked() void MainWindow::enableSelectedMods_clicked()
{
m_OrganizerCore.modList()->enableSelected(ui->modList->selectionModel());
+ if (m_ModListSortProxy != nullptr) {
+ m_ModListSortProxy->invalidate();
+ }
}
void MainWindow::disableSelectedMods_clicked()
{
m_OrganizerCore.modList()->disableSelected(ui->modList->selectionModel());
+ if (m_ModListSortProxy != nullptr) {
+ m_ModListSortProxy->invalidate();
+ }
}
@@ -5311,10 +5324,10 @@ void MainWindow::updateDownloadView() // set the view attribute and default row sizes
if (m_OrganizerCore.settings().compactDownloads()) {
ui->downloadView->setProperty("downloadView", "compact");
- setStyleSheet("DownloadListWidget::item { padding: 4px 0; }");
+ setStyleSheet("DownloadListWidget::item { padding: 4px 2px; }");
} else {
ui->downloadView->setProperty("downloadView", "standard");
- setStyleSheet("DownloadListWidget::item { padding: 16px 0; }");
+ setStyleSheet("DownloadListWidget::item { padding: 16px 4px; }");
}
//setStyleSheet("DownloadListWidget::item:hover { padding: 0px; }");
//setStyleSheet("DownloadListWidget::item:selected { padding: 0px; }");
diff --git a/src/mainwindow.h b/src/mainwindow.h index cd22dbfa..24d726ca 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -551,6 +551,7 @@ private slots: void updateStyle(const QString &style);
void modlistChanged(const QModelIndex &index, int role);
+ void modlistChanged(const QModelIndexList &indicies, int role);
void fileMoved(const QString &filePath, const QString &oldOriginName, const QString &newOriginName);
diff --git a/src/modinfo.h b/src/modinfo.h index 350b3a0d..6b7c714e 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -538,7 +538,7 @@ public: /**
* @return a list of archives belonging to this mod (as absolute file paths)
*/
- virtual QStringList archives() const = 0;
+ virtual QStringList archives(bool checkOnDisk = false) = 0;
/*
*@return the color choosen by the user for the mod/separator
diff --git a/src/modinfoforeign.h b/src/modinfoforeign.h index 93061294..45fe7689 100644 --- a/src/modinfoforeign.h +++ b/src/modinfoforeign.h @@ -49,7 +49,7 @@ public: virtual QDateTime getLastNexusQuery() const { return QDateTime(); } virtual QString getNexusDescription() const { return QString(); } virtual int getFixedPriority() const { return INT_MIN; } - virtual QStringList archives() const { return m_Archives; } + virtual QStringList archives(bool checkOnDisk = false) { return m_Archives; } virtual QStringList stealFiles() const { return m_Archives + QStringList(m_ReferenceFile); } virtual bool alwaysEnabled() const { return true; } virtual void addInstalledFile(int, int) {} diff --git a/src/modinfooverwrite.cpp b/src/modinfooverwrite.cpp index 742ae384..0e428483 100644 --- a/src/modinfooverwrite.cpp +++ b/src/modinfooverwrite.cpp @@ -49,7 +49,7 @@ QString ModInfoOverwrite::getDescription() const "modified (i.e. by the construction kit)"); } -QStringList ModInfoOverwrite::archives() const +QStringList ModInfoOverwrite::archives(bool checkOnDisk) { QStringList result; QDir dir(this->absolutePath()); diff --git a/src/modinfooverwrite.h b/src/modinfooverwrite.h index 4b98d715..cfd662af 100644 --- a/src/modinfooverwrite.h +++ b/src/modinfooverwrite.h @@ -51,7 +51,7 @@ public: virtual QString getDescription() const; virtual QDateTime getLastNexusQuery() const { return QDateTime(); } virtual QString getNexusDescription() const { return QString(); } - virtual QStringList archives() const; + virtual QStringList archives(bool checkOnDisk = false); virtual void addInstalledFile(int, int) {} private: diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp index 185f0495..f29d3725 100644 --- a/src/modinforegular.cpp +++ b/src/modinforegular.cpp @@ -45,6 +45,10 @@ ModInfoRegular::ModInfoRegular(PluginContainer *pluginContainer, const IPluginGa if (!game->primarySources().contains(m_GameName, Qt::CaseInsensitive)) m_IsAlternate = true; + //populate m_Archives + m_Archives = QStringList(); + archives(true); + connect(&m_NexusBridge, SIGNAL(descriptionAvailable(QString,int,QVariant,QVariant)) , this, SLOT(nxmDescriptionAvailable(QString,int,QVariant,QVariant))); connect(&m_NexusBridge, SIGNAL(endorsementToggled(QString,int,QVariant,QVariant)) @@ -627,14 +631,18 @@ QString ModInfoRegular::getURL() const -QStringList ModInfoRegular::archives() const +QStringList ModInfoRegular::archives(bool checkOnDisk) { - QStringList result; - QDir dir(this->absolutePath()); - for (const QString &archive : dir.entryList(QStringList({ "*.bsa", "*.ba2" }))) { - result.append(this->absolutePath() + "/" + archive); + if (checkOnDisk) { + QStringList result; + QDir dir(this->absolutePath()); + QStringList bsaList = dir.entryList(QStringList({ "*.bsa", "*.ba2" })); + for (const QString &archive : bsaList) { + result.append(this->absolutePath() + "/" + archive); + } + m_Archives = result; } - return result; + return m_Archives; } void ModInfoRegular::addInstalledFile(int modId, int fileId) diff --git a/src/modinforegular.h b/src/modinforegular.h index 33b26998..093b4e5b 100644 --- a/src/modinforegular.h +++ b/src/modinforegular.h @@ -320,7 +320,7 @@ public: */ virtual QDateTime getLastNexusQuery() const; - virtual QStringList archives() const; + virtual QStringList archives(bool checkOnDisk = false); virtual void setColor(QColor color); @@ -371,6 +371,8 @@ private: QString m_URL; QString m_GameName; + mutable QStringList m_Archives; + QDateTime m_CreationTime; QDateTime m_LastNexusQuery; diff --git a/src/modlist.cpp b/src/modlist.cpp index 178b4b16..2e6959d5 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -540,7 +540,7 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) m_Profile->setModEnabled(modID, enabled);
m_Modified = true;
m_LastCheck.restart();
- emit modlist_changed(index, role);
+ emit modlistChanged(index, role);
}
result = true;
emit dataChanged(index, index);
@@ -575,7 +575,7 @@ bool ModList::setData(const QModelIndex &index, const QVariant &value, int role) int newID = value.toInt(&ok);
if (ok) {
info->setNexusID(newID);
- emit modlist_changed(index, role);
+ emit modlistChanged(index, role);
result = true;
} else {
result = false;
@@ -1314,12 +1314,24 @@ bool ModList::toggleSelection(QAbstractItemView *itemView) QItemSelectionModel *selectionModel = itemView->selectionModel();
+ QList<unsigned int> modsToEnable;
+ QList<unsigned int> modsToDisable;
+ QModelIndexList dirtyMods;
for (QModelIndex idx : selectionModel->selectedRows()) {
int modId = idx.data(Qt::UserRole + 1).toInt();
- m_Profile->setModEnabled(modId, !m_Profile->modEnabled(modId));
- emit modlist_changed(idx, 0);
+ if (m_Profile->modEnabled(modId)) {
+ modsToDisable.append(modId);
+ dirtyMods.append(idx);
+ } else {
+ modsToEnable.append(modId);
+ dirtyMods.append(idx);
+ }
}
+ m_Profile->setModsEnabled(modsToEnable, modsToDisable);
+
+ emit modlistChanged(dirtyMods, 0);
+
m_Modified = true;
m_LastCheck.restart();
@@ -1358,32 +1370,28 @@ bool ModList::eventFilter(QObject *obj, QEvent *event) return QAbstractItemModel::eventFilter(obj, event);
}
-
+//note: caller needs to make sure sort proxy is updated
void ModList::enableSelected(const QItemSelectionModel *selectionModel)
{
if (selectionModel->hasSelection()) {
- bool dirty = false;
+ QList<unsigned int> modsToEnable;
for (auto row : selectionModel->selectedRows(COL_PRIORITY)) {
int modID = m_Profile->modIndexByPriority(row.data().toInt());
- if (!m_Profile->modEnabled(modID)) {
- m_Profile->setModEnabled(modID, true);
- emit modlist_changed(row, 0);
- }
+ modsToEnable.append(modID);
}
+ m_Profile->setModsEnabled(modsToEnable, QList<unsigned int>());
}
}
-
+//note: caller needs to make sure sort proxy is updated
void ModList::disableSelected(const QItemSelectionModel *selectionModel)
{
if (selectionModel->hasSelection()) {
- bool dirty = false;
+ QList<unsigned int> modsToDisable;
for (auto row : selectionModel->selectedRows(COL_PRIORITY)) {
int modID = m_Profile->modIndexByPriority(row.data().toInt());
- if (m_Profile->modEnabled(modID)) {
- m_Profile->setModEnabled(modID, false);
- emit modlist_changed(row, 0);
- }
+ modsToDisable.append(modID);
}
+ m_Profile->setModsEnabled(QList<unsigned int>(), modsToDisable);
}
}
diff --git a/src/modlist.h b/src/modlist.h index 49627d68..402d662f 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -236,9 +236,18 @@ signals: * @param role role of the field that changed
* @note this signal must only be emitted if the row really did change.
* Slots handling this signal therefore do not have to verify that a change has happened
- * @note this signal is currently only used in tutorials
**/
- void modlist_changed(const QModelIndex &index, int role);
+ void modlistChanged(const QModelIndex &index, int role);
+
+ /**
+ * @brief emitted whenever multiple row sin the list has changed
+ *
+ * @param indicies the list of indicies of the changed field
+ * @param role role of the field that changed
+ * @note this signal must only be emitted if the row really did change.
+ * Slots handling this signal therefore do not have to verify that a change has happened
+ **/
+ void modlistChanged(const QModelIndexList &indicies, int role);
/**
* @brief emitted to have all selected mods deleted
diff --git a/src/modlistsortproxy.cpp b/src/modlistsortproxy.cpp index b1bb9013..99f0efef 100644 --- a/src/modlistsortproxy.cpp +++ b/src/modlistsortproxy.cpp @@ -86,10 +86,12 @@ void ModListSortProxy::enableAllVisible() {
if (m_Profile == nullptr) return;
+ QList<unsigned int> modsToEnable;
for (int i = 0; i < this->rowCount(); ++i) {
int modID = mapToSource(index(i, 0)).data(Qt::UserRole + 1).toInt();
- m_Profile->setModEnabled(modID, true);
+ modsToEnable.append(modID);
}
+ m_Profile->setModsEnabled(modsToEnable, QList<unsigned int>());
invalidate();
}
@@ -97,10 +99,12 @@ void ModListSortProxy::disableAllVisible() {
if (m_Profile == nullptr) return;
+ QList<unsigned int> modsToDisable;
for (int i = 0; i < this->rowCount(); ++i) {
int modID = mapToSource(index(i, 0)).data(Qt::UserRole + 1).toInt();
- m_Profile->setModEnabled(modID, false);
+ modsToDisable.append(modID);
}
+ m_Profile->setModsEnabled(QList<unsigned int>(), modsToDisable);
invalidate();
}
diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 6710f89a..b5a1cb8a 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -542,8 +542,10 @@ void OrganizerCore::setUserInterface(IUserInterface *userInterface, m_UserInterface = userInterface;
if (widget != nullptr) {
- connect(&m_ModList, SIGNAL(modlist_changed(QModelIndex, int)), widget,
+ connect(&m_ModList, SIGNAL(modlistChanged(QModelIndex, int)), widget,
SLOT(modlistChanged(QModelIndex, int)));
+ connect(&m_ModList, SIGNAL(modlistChanged(QModelIndexList, int)), widget,
+ SLOT(modlistChanged(QModelIndexList, int)));
connect(&m_ModList, SIGNAL(showMessage(QString)), widget,
SLOT(showMessage(QString)));
connect(&m_ModList, SIGNAL(modRenamed(QString, QString)), widget,
@@ -831,8 +833,8 @@ void OrganizerCore::setCurrentProfile(const QString &profileName) m_CurrentProfile->deactivateInvalidation();
}
- connect(m_CurrentProfile, SIGNAL(modStatusChanged(uint)), this,
- SLOT(modStatusChanged(uint)));
+ connect(m_CurrentProfile, SIGNAL(modStatusChanged(uint)), this, SLOT(modStatusChanged(uint)));
+ connect(m_CurrentProfile, SIGNAL(modStatusChanged(QList<uint>)), this, SLOT(modStatusChanged(QList<uint>)));
refreshDirectoryStructure();
}
@@ -1808,60 +1810,70 @@ void OrganizerCore::refreshLists() void OrganizerCore::updateModActiveState(int index, bool active)
{
- ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
- QDir dir(modInfo->absolutePath());
- for (const QString &esm :
- dir.entryList(QStringList() << "*.esm", QDir::Files)) {
- const FileEntry::Ptr file = m_DirectoryStructure->findFile(ToWString(esm));
- if (file.get() == nullptr) {
- qWarning("failed to activate %s", qUtf8Printable(esm));
- continue;
- }
+ QList<unsigned int> modsToUpdate;
+ modsToUpdate.append(index);
+ updateModsActiveState(modsToUpdate, active);
+}
- if (active != m_PluginList.isEnabled(esm)
- && file->getAlternatives().empty()) {
- m_PluginList.blockSignals(true);
- m_PluginList.enableESP(esm, active);
- m_PluginList.blockSignals(false);
- }
- }
- int enabled = 0;
- for (const QString &esl :
- dir.entryList(QStringList() << "*.esl", QDir::Files)) {
- const FileEntry::Ptr file = m_DirectoryStructure->findFile(ToWString(esl));
- if (file.get() == nullptr) {
- qWarning("failed to activate %s", qUtf8Printable(esl));
- continue;
- }
+void OrganizerCore::updateModsActiveState(const QList<unsigned int> &modIndices, bool active)
+{
+ int enabled = 0;
+ for (auto index : modIndices) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
+ QDir dir(modInfo->absolutePath());
+ for (const QString &esm :
+ dir.entryList(QStringList() << "*.esm", QDir::Files)) {
+ const FileEntry::Ptr file = m_DirectoryStructure->findFile(ToWString(esm));
+ if (file.get() == nullptr) {
+ qWarning("failed to activate %s", qUtf8Printable(esm));
+ continue;
+ }
- if (active != m_PluginList.isEnabled(esl)
+ if (active != m_PluginList.isEnabled(esm)
&& file->getAlternatives().empty()) {
- m_PluginList.blockSignals(true);
- m_PluginList.enableESP(esl, active);
- m_PluginList.blockSignals(false);
- ++enabled;
+ m_PluginList.blockSignals(true);
+ m_PluginList.enableESP(esm, active);
+ m_PluginList.blockSignals(false);
+ }
}
- }
- QStringList esps = dir.entryList(QStringList() << "*.esp", QDir::Files);
- for (const QString &esp : esps) {
- const FileEntry::Ptr file = m_DirectoryStructure->findFile(ToWString(esp));
- if (file.get() == nullptr) {
- qWarning("failed to activate %s", qUtf8Printable(esp));
- continue;
+
+ for (const QString &esl :
+ dir.entryList(QStringList() << "*.esl", QDir::Files)) {
+ const FileEntry::Ptr file = m_DirectoryStructure->findFile(ToWString(esl));
+ if (file.get() == nullptr) {
+ qWarning("failed to activate %s", qUtf8Printable(esl));
+ continue;
+ }
+
+ if (active != m_PluginList.isEnabled(esl)
+ && file->getAlternatives().empty()) {
+ m_PluginList.blockSignals(true);
+ m_PluginList.enableESP(esl, active);
+ m_PluginList.blockSignals(false);
+ ++enabled;
+ }
}
+ QStringList esps = dir.entryList(QStringList() << "*.esp", QDir::Files);
+ for (const QString &esp : esps) {
+ const FileEntry::Ptr file = m_DirectoryStructure->findFile(ToWString(esp));
+ if (file.get() == nullptr) {
+ qWarning("failed to activate %s", qUtf8Printable(esp));
+ continue;
+ }
- if (active != m_PluginList.isEnabled(esp)
+ if (active != m_PluginList.isEnabled(esp)
&& file->getAlternatives().empty()) {
- m_PluginList.blockSignals(true);
- m_PluginList.enableESP(esp, active);
- m_PluginList.blockSignals(false);
- ++enabled;
+ m_PluginList.blockSignals(true);
+ m_PluginList.enableESP(esp, active);
+ m_PluginList.blockSignals(false);
+ ++enabled;
+ }
}
}
if (active && (enabled > 1)) {
MessageDialog::showMessage(
- tr("Multiple esps/esls activated, please check that they don't conflict."),
- qApp->activeWindow());
+ tr("Multiple esps/esls activated, please check that they don't conflict."),
+ qApp->activeWindow());
}
m_PluginList.refreshLoadOrder();
// immediately save affected lists
@@ -1871,18 +1883,27 @@ void OrganizerCore::updateModActiveState(int index, bool active) void OrganizerCore::updateModInDirectoryStructure(unsigned int index,
ModInfo::Ptr modInfo)
{
- // add files of the bsa to the directory structure
- m_DirectoryRefresher.addModFilesToStructure(
- m_DirectoryStructure, modInfo->name(),
- m_CurrentProfile->getModPriority(index), modInfo->absolutePath(),
- modInfo->stealFiles());
+ QMap<unsigned int, ModInfo::Ptr> allModInfo;
+ allModInfo[index] = modInfo;
+ updateModsInDirectoryStructure(allModInfo);
+}
+
+void OrganizerCore::updateModsInDirectoryStructure(QMap<unsigned int, ModInfo::Ptr> modInfo)
+{
+ for (auto idx : modInfo.keys()) {
+ // add files of the bsa to the directory structure
+ m_DirectoryRefresher.addModFilesToStructure(
+ m_DirectoryStructure, modInfo[idx]->name(),
+ m_CurrentProfile->getModPriority(idx), modInfo[idx]->absolutePath(),
+ modInfo[idx]->stealFiles());
+ }
DirectoryRefresher::cleanStructure(m_DirectoryStructure);
// need to refresh plugin list now so we can activate esps
refreshESPList(true);
// activate all esps of the specified mod so the bsas get activated along with
// it
m_PluginList.blockSignals(true);
- updateModActiveState(index, true);
+ updateModsActiveState(modInfo.keys(), true);
m_PluginList.blockSignals(false);
// now we need to refresh the bsa list and save it so there is no confusion
// about what archives are avaiable and active
@@ -1893,14 +1914,16 @@ void OrganizerCore::updateModInDirectoryStructure(unsigned int index, std::vector<QString> archives = enabledArchives();
m_DirectoryRefresher.setMods(
- m_CurrentProfile->getActiveMods(),
- std::set<QString>(archives.begin(), archives.end()));
+ m_CurrentProfile->getActiveMods(),
+ std::set<QString>(archives.begin(), archives.end()));
// finally also add files from bsas to the directory structure
- m_DirectoryRefresher.addModBSAToStructure(
- m_DirectoryStructure, modInfo->name(),
- m_CurrentProfile->getModPriority(index), modInfo->absolutePath(),
- modInfo->archives());
+ for (auto idx : modInfo.keys()) {
+ m_DirectoryRefresher.addModBSAToStructure(
+ m_DirectoryStructure, modInfo[idx]->name(),
+ m_CurrentProfile->getModPriority(idx), modInfo[idx]->absolutePath(),
+ modInfo[idx]->archives());
+ }
}
void OrganizerCore::requestDownload(const QUrl &url, QNetworkReply *reply)
@@ -2077,6 +2100,55 @@ void OrganizerCore::modStatusChanged(unsigned int index) }
}
+void OrganizerCore::modStatusChanged(QList<unsigned int> index) {
+ try {
+ QMap<unsigned int, ModInfo::Ptr> modsToEnable;
+ QMap<unsigned int, ModInfo::Ptr> modsToDisable;
+ for (auto idx : index) {
+ if (m_CurrentProfile->modEnabled(idx)) {
+ modsToEnable[idx] = ModInfo::getByIndex(idx);
+ } else {
+ modsToDisable[idx] = ModInfo::getByIndex(idx);
+ }
+ }
+ if (!modsToEnable.isEmpty()) {
+ updateModsInDirectoryStructure(modsToEnable);
+ for (auto modInfo : modsToEnable.values()) {
+ modInfo->clearCaches();
+ }
+ }
+ if (!modsToDisable.isEmpty()) {
+ updateModsActiveState(modsToDisable.keys(), false);
+ for (auto idx : modsToDisable.keys()) {
+ if (m_DirectoryStructure->originExists(ToWString(modsToDisable[idx]->name()))) {
+ FilesOrigin &origin
+ = m_DirectoryStructure->getOriginByName(ToWString(modsToDisable[idx]->name()));
+ origin.enable(false);
+ }
+ }
+ if (m_UserInterface != nullptr) {
+ m_UserInterface->archivesWriter().write();
+ }
+ }
+
+ for (unsigned int i = 0; i < m_CurrentProfile->numMods(); ++i) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(i);
+ int priority = m_CurrentProfile->getModPriority(i);
+ if (m_DirectoryStructure->originExists(ToWString(modInfo->name()))) {
+ // priorities in the directory structure are one higher because data is
+ // 0
+ m_DirectoryStructure->getOriginByName(ToWString(modInfo->name()))
+ .setPriority(priority + 1);
+ }
+ }
+ m_DirectoryStructure->getFileRegister()->sortOrigins();
+
+ refreshLists();
+ } catch (const std::exception &e) {
+ reportError(tr("failed to update mod list: %1").arg(e.what()));
+ }
+}
+
void OrganizerCore::loginSuccessful(bool necessary)
{
if (necessary) {
diff --git a/src/organizercore.h b/src/organizercore.h index cde77f92..68d4e7e4 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -136,6 +136,7 @@ public: void refreshDirectoryStructure();
void updateModInDirectoryStructure(unsigned int index, ModInfo::Ptr modInfo);
+ void updateModsInDirectoryStructure(QMap<unsigned int, ModInfo::Ptr> modInfos);
void doAfterLogin(const std::function<void()> &function) { m_PostLoginTasks.append(function); }
@@ -240,6 +241,7 @@ public slots: void installDownload(int downloadIndex);
void modStatusChanged(unsigned int index);
+ void modStatusChanged(QList<unsigned int> index);
void requestDownload(const QUrl &url, QNetworkReply *reply);
void downloadRequestedNXM(const QString &url);
@@ -268,6 +270,7 @@ private: bool queryLogin(QString &username, QString &password);
void updateModActiveState(int index, bool active);
+ void updateModsActiveState(const QList<unsigned int> &modIndices, bool active);
bool testForSteam();
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 614a2a9e..b2fabbe0 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -175,19 +175,6 @@ void PluginList::refresh(const QString &profileName QStringList availablePlugins;
- QRegExp bsaReg = QRegExp();
- QRegExp ba2Reg = QRegExp();
- bsaReg.setPatternSyntax(QRegExp::Wildcard);
- bsaReg.setCaseSensitivity(Qt::CaseInsensitive);
- ba2Reg.setPatternSyntax(QRegExp::Wildcard);
- ba2Reg.setCaseSensitivity(Qt::CaseInsensitive);
-
- //TODO: try QRegularExpression when we move to Qt5.12
- /*QRegularExpression bsaReg = QRegularExpression();
- QRegularExpression ba2Reg = QRegularExpression();
- bsaReg.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
- ba2Reg.setPatternOptions(QRegularExpression::CaseInsensitiveOption);*/
-
std::vector<FileEntry::Ptr> files = baseDirectory.getFiles();
for (FileEntry::Ptr current : files) {
if (current.get() == nullptr) {
@@ -217,18 +204,13 @@ void PluginList::refresh(const QString &profileName QString iniPath = baseName + ".ini";
bool hasIni = baseDirectory.findFile(ToWString(iniPath)).get() != nullptr;
-
- bsaReg.setPattern(baseName + "*.bsa");
- ba2Reg.setPattern(baseName + "*.ba2");
-
-
- //bsaReg.setPattern(QRegularExpression::wildcardToRegularExpression(baseName + "*.bsa"));
- //ba2Reg.setPattern(QRegularExpression::wildcardToRegularExpression(baseName + "*.ba2"));
std::set<QString> loadedArchives;
QString candidateName;
for (FileEntry::Ptr archiveCandidate : files) {
candidateName = ToQString(archiveCandidate->getName());
- if (candidateName.contains(bsaReg) || candidateName.contains(ba2Reg)) {
+ if (candidateName.startsWith(baseName, Qt::CaseInsensitive) &&
+ (candidateName.endsWith(".bsa", Qt::CaseInsensitive) ||
+ candidateName.endsWith(".ba2", Qt::CaseInsensitive))) {
loadedArchives.insert(candidateName);
}
}
diff --git a/src/profile.cpp b/src/profile.cpp index afe6fdc7..629e043f 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -568,6 +568,37 @@ void Profile::setModEnabled(unsigned int index, bool enabled) } } +void Profile::setModsEnabled(const QList<unsigned int> &modsToEnable, const QList<unsigned int> &modsToDisable) +{ + QList<unsigned int> dirtyMods; + for (auto idx : modsToEnable) { + if (idx >= m_ModStatus.size()) { + qCritical() << tr("invalid index %1").arg(idx); + continue; + } + if (!m_ModStatus[idx].m_Enabled) { + m_ModStatus[idx].m_Enabled = true; + dirtyMods.append(idx); + } + } + for (auto idx : modsToDisable) { + if (idx >= m_ModStatus.size()) { + qCritical() << tr("invalid index %1").arg(idx); + continue; + } + if (ModInfo::getByIndex(idx)->alwaysEnabled()) { + continue; + } + if (m_ModStatus[idx].m_Enabled) { + m_ModStatus[idx].m_Enabled = false; + dirtyMods.append(idx); + } + } + if (!dirtyMods.isEmpty()) { + emit modStatusChanged(dirtyMods); + } +} + bool Profile::modEnabled(unsigned int index) const { if (index >= m_ModStatus.size()) { diff --git a/src/profile.h b/src/profile.h index dea933ad..a7ba7e91 100644 --- a/src/profile.h +++ b/src/profile.h @@ -274,6 +274,16 @@ public: void setModEnabled(unsigned int index, bool enabled); /** + * @brief enable or disable multiple mods at once + * This is an abbreviated process and should be immediately followed by a full refresh + * to maintain data consistency. + * + * @param modsToEnable list of mod indicies to enable + * @param modsToDisable list of mod indicies to disable + **/ + void setModsEnabled(const QList<unsigned int> &modsToEnable, const QList<unsigned int> &modsToDisable); + + /** * change the priority of a mod. Of course this also changes the priority of other mods. * The priority of the mods in the range ]old, new priority] are shifted so that no gaps * are possible. @@ -335,6 +345,13 @@ signals: **/ void modStatusChanged(unsigned int index); + /** + * @brief emitted whenever the status (enabled/disabled) of multiple mods change + * + * @param index list of indices of the mods that changed + **/ + void modStatusChanged(QList<unsigned int> index); + public slots: // should only be called by DelayedFileWriter, use writeModlist() and writeModlistNow() instead |
