summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/instancemanager.cpp3
-rw-r--r--src/mainwindow.cpp17
-rw-r--r--src/mainwindow.h1
-rw-r--r--src/modinfo.h2
-rw-r--r--src/modinfoforeign.h2
-rw-r--r--src/modinfooverwrite.cpp2
-rw-r--r--src/modinfooverwrite.h2
-rw-r--r--src/modinforegular.cpp20
-rw-r--r--src/modinforegular.h4
-rw-r--r--src/modlist.cpp40
-rw-r--r--src/modlist.h13
-rw-r--r--src/modlistsortproxy.cpp8
-rw-r--r--src/organizercore.cpp188
-rw-r--r--src/organizercore.h3
-rw-r--r--src/pluginlist.cpp24
-rw-r--r--src/profile.cpp31
-rw-r--r--src/profile.h17
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 &current, 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