summaryrefslogtreecommitdiff
path: root/src/profile.cpp
diff options
context:
space:
mode:
authorLostDragonist <lost.dragonist@gmail.com>2018-12-20 14:33:08 -0600
committerGitHub <noreply@github.com>2018-12-20 14:33:08 -0600
commited67ac211306bee2067178ace1a0a7fbcd0bea1b (patch)
tree8fe31503ba20a436457c8c94d61f953b4aa067b4 /src/profile.cpp
parent2232bdfc779b8575c8374a723d4d02a2b41fb352 (diff)
parent9a33dc148054443cb0efd5916ff758fca5bc09e3 (diff)
Merge pull request #586 from ModOrganizer2/Develop
Release 2.1.6
Diffstat (limited to 'src/profile.cpp')
-rw-r--r--src/profile.cpp232
1 files changed, 149 insertions, 83 deletions
diff --git a/src/profile.cpp b/src/profile.cpp
index 7f10bd02..8eb1c49a 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -73,9 +73,6 @@ Profile::Profile(const QString &name, IPluginGame const *gamePlugin, bool useDef
{
QString profilesDir = Settings::instance().getProfileDirectory();
QDir profileBase(profilesDir);
-
- m_Settings = new QSettings(profileBase.absoluteFilePath("settings.ini"));
-
QString fixedName = name;
if (!fixDirectoryName(fixedName)) {
throw MyException(tr("invalid profile name %1").arg(name));
@@ -86,6 +83,9 @@ Profile::Profile(const QString &name, IPluginGame const *gamePlugin, bool useDef
}
QString fullPath = profilesDir + "/" + fixedName;
m_Directory = QDir(fullPath);
+ m_Settings = new QSettings(m_Directory.absoluteFilePath("settings.ini"),
+ QSettings::IniFormat);
+ findProfileSettings();
try {
// create files. Needs to happen after m_Directory was set!
@@ -119,6 +119,7 @@ Profile::Profile(const QDir &directory, IPluginGame const *gamePlugin)
m_Settings = new QSettings(directory.absoluteFilePath("settings.ini"),
QSettings::IniFormat);
+ findProfileSettings();
if (!QFile::exists(m_Directory.filePath("modlist.txt"))) {
qWarning("missing modlist.txt in %s", qPrintable(directory.path()));
@@ -141,6 +142,7 @@ Profile::Profile(const Profile &reference)
{
m_Settings = new QSettings(m_Directory.absoluteFilePath("settings.ini"),
QSettings::IniFormat);
+ findProfileSettings();
refreshModStatus();
}
@@ -151,6 +153,48 @@ Profile::~Profile()
m_ModListWriter.writeImmediately(true);
}
+void Profile::findProfileSettings()
+{
+ if (setting("LocalSaves") == QVariant()) {
+ if (m_Directory.exists("saves")) {
+ storeSetting("LocalSaves", true);
+ } else {
+ if (m_Directory.exists("_saves")) {
+ m_Directory.rename("_saves", "saves");
+ }
+ storeSetting("LocalSaves", false);
+ }
+ }
+
+ if (setting("LocalSettings") == QVariant()) {
+ QString backupFile = getIniFileName() + "_";
+ if (m_Directory.exists(backupFile)) {
+ storeSetting("LocalSettings", false);
+ m_Directory.rename(backupFile, getIniFileName());
+ } else {
+ storeSetting("LocalSettings", true);
+ }
+ }
+
+ if (setting("AutomaticArchiveInvalidation") == QVariant()) {
+ BSAInvalidation *invalidation = m_GamePlugin->feature<BSAInvalidation>();
+ DataArchives *dataArchives = m_GamePlugin->feature<DataArchives>();
+ bool found = false;
+ if ((invalidation != nullptr) && (dataArchives != nullptr)) {
+ for (const QString &archive : dataArchives->archives(this)) {
+ if (invalidation->isInvalidationBSA(archive)) {
+ storeSetting("AutomaticArchiveInvalidation", true);
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ storeSetting("AutomaticArchiveInvalidation", false);
+ }
+ }
+}
+
bool Profile::exists() const
{
return m_Directory.exists();
@@ -184,9 +228,10 @@ void Profile::doWriteModlist()
return;
}
- for (int i = static_cast<int>(m_ModStatus.size()) - 1; i >= 0; --i) {
+ for (std::map<int, unsigned int>::const_reverse_iterator iter = m_ModIndexByPriority.crbegin(); iter != m_ModIndexByPriority.crend(); iter++ ) {
+ //qDebug(QString("write mod %1 to priority %2").arg(iter->first).arg(iter->second).toLocal8Bit());
// the priority order was inverted on load so it has to be inverted again
- unsigned int index = m_ModIndexByPriority[i];
+ unsigned int index = iter->second;
if (index != UINT_MAX) {
ModInfo::Ptr modInfo = ModInfo::getByIndex(index);
std::vector<ModInfo::EFlag> flags = modInfo->getFlags();
@@ -223,9 +268,9 @@ void Profile::createTweakedIniFile()
return;
}
- for (unsigned int i = 0; i < m_ModStatus.size(); ++i) {
+ for (int i = getPriorityMinimum(); i < getPriorityMinimum() + (int)numRegularMods(); ++i) {
unsigned int idx = modIndexByPriority(i);
- if ((idx != UINT_MAX) && m_ModStatus[idx].m_Enabled) {
+ if (m_ModStatus[idx].m_Enabled) {
ModInfo::Ptr modInfo = ModInfo::getByIndex(idx);
mergeTweaks(modInfo, tweakedIni);
}
@@ -454,18 +499,14 @@ void Profile::updateIndices()
{
m_NumRegularMods = 0;
m_ModIndexByPriority.clear();
- m_ModIndexByPriority.resize(m_ModStatus.size(), UINT_MAX);
for (unsigned int i = 0; i < m_ModStatus.size(); ++i) {
int priority = m_ModStatus[i].m_Priority;
- if (priority < 0) {
+ if (priority == INT_MIN) {
// don't assign this to mapping at all, it's probably the overwrite mod
continue;
- } else if (priority >= static_cast<int>(m_ModIndexByPriority.size())) {
- qCritical("invalid priority %d for mod", priority);
- continue;
} else {
++m_NumRegularMods;
- m_ModIndexByPriority.at(priority) = i;
+ m_ModIndexByPriority[priority] = i;
}
}
}
@@ -474,11 +515,10 @@ void Profile::updateIndices()
std::vector<std::tuple<QString, QString, int> > Profile::getActiveMods()
{
std::vector<std::tuple<QString, QString, int> > result;
- for (std::vector<unsigned int>::const_iterator iter = m_ModIndexByPriority.begin();
- iter != m_ModIndexByPriority.end(); ++iter) {
- if ((*iter != UINT_MAX) && m_ModStatus[*iter].m_Enabled) {
- ModInfo::Ptr modInfo = ModInfo::getByIndex(*iter);
- result.push_back(std::make_tuple(modInfo->internalName(), modInfo->absolutePath(), m_ModStatus[*iter].m_Priority));
+ for (std::map<int, unsigned int>::const_iterator iter = m_ModIndexByPriority.begin(); iter != m_ModIndexByPriority.end(); iter++ ) {
+ if ((iter->second != UINT_MAX) && m_ModStatus[iter->second].m_Enabled) {
+ ModInfo::Ptr modInfo = ModInfo::getByIndex(iter->second);
+ result.push_back(std::make_tuple(modInfo->internalName(), modInfo->absolutePath(), m_ModStatus[iter->second].m_Priority));
}
}
@@ -496,13 +536,13 @@ std::vector<std::tuple<QString, QString, int> > Profile::getActiveMods()
}
-unsigned int Profile::modIndexByPriority(unsigned int priority) const
+unsigned int Profile::modIndexByPriority(int priority) const
{
- if (priority >= m_ModStatus.size()) {
+ try {
+ return m_ModIndexByPriority.at(priority);
+ } catch (std::out_of_range) {
throw MyException(tr("invalid priority %1").arg(priority));
}
-
- return m_ModIndexByPriority[priority];
}
@@ -552,30 +592,26 @@ void Profile::setModPriority(unsigned int index, int &newPriority)
return;
}
- int newPriorityTemp =
- (std::max)(0, (std::min<int>)(static_cast<int>(m_ModStatus.size()) - 1,
- newPriority));
+ int oldPriority = m_ModStatus.at(index).m_Priority;
+ int lastPriority = INT_MIN;
- // don't try to place below overwrite
- while ((m_ModIndexByPriority.at(newPriorityTemp) >= m_ModStatus.size()) ||
- m_ModStatus.at(m_ModIndexByPriority.at(newPriorityTemp)).m_Overwrite) {
- --newPriorityTemp;
+ if (newPriority == oldPriority) {
+ // nothing to do
+ return;
}
- int oldPriority = m_ModStatus.at(index).m_Priority;
- if (newPriorityTemp > oldPriority) {
- // priority is higher than the old, so the gap we left is in lower priorities
- for (int i = oldPriority + 1; i <= newPriorityTemp; ++i) {
- --m_ModStatus.at(m_ModIndexByPriority.at(i)).m_Priority;
+ for (std::map<int, unsigned int>::iterator iter = m_ModIndexByPriority.begin(); iter != m_ModIndexByPriority.end(); iter++) {
+ if (newPriority < oldPriority && iter->first >= newPriority && iter->first < oldPriority) {
+ m_ModStatus.at(iter->second).m_Priority += 1;
}
- } else {
- for (int i = newPriorityTemp; i < oldPriority; ++i) {
- ++m_ModStatus.at(m_ModIndexByPriority.at(i)).m_Priority;
+ else if (newPriority > oldPriority && iter->first <= newPriority && iter->first > oldPriority) {
+ m_ModStatus.at(iter->second).m_Priority -= 1;
}
- ++newPriority;
+ lastPriority = std::max(lastPriority, iter->first);
}
- m_ModStatus.at(index).m_Priority = newPriorityTemp;
+ newPriority = std::min(newPriority, lastPriority);
+ m_ModStatus.at(index).m_Priority = std::min(newPriority, lastPriority);
updateIndices();
m_ModListWriter.write();
@@ -666,23 +702,11 @@ bool Profile::invalidationActive(bool *supported) const
BSAInvalidation *invalidation = m_GamePlugin->feature<BSAInvalidation>();
DataArchives *dataArchives = m_GamePlugin->feature<DataArchives>();
- if ((invalidation != nullptr) && (dataArchives != nullptr)) {
- if (supported != nullptr) {
- *supported = true;
- }
-
- for (const QString &archive : dataArchives->archives(this)) {
- if (invalidation->isInvalidationBSA(archive)) {
- return true;
- }
- }
- return false;
- } else {
- if (supported != nullptr) {
- *supported = false;
- }
+ if (supported != nullptr) {
+ *supported = ((invalidation != nullptr) && (dataArchives != nullptr));
}
- return false;
+
+ return setting("AutomaticArchiveInvalidation", false).toBool();
}
@@ -693,6 +717,8 @@ void Profile::deactivateInvalidation()
if (invalidation != nullptr) {
invalidation->deactivate(this);
}
+
+ storeSetting("AutomaticArchiveInvalidation", false);
}
@@ -703,66 +729,90 @@ void Profile::activateInvalidation()
if (invalidation != nullptr) {
invalidation->activate(this);
}
+
+ storeSetting("AutomaticArchiveInvalidation", true);
}
bool Profile::localSavesEnabled() const
{
- return m_Directory.exists("saves");
+ return setting("LocalSaves", false).toBool();
}
bool Profile::enableLocalSaves(bool enable)
{
if (enable) {
- if (m_Directory.exists("_saves")) {
- m_Directory.rename("_saves", "saves");
- } else {
+ if (!m_Directory.exists("saves")) {
m_Directory.mkdir("saves");
}
- } else {
+ } else {
QMessageBox::StandardButton res = QMessageBox::question(
- QApplication::activeModalWidget(), tr("Delete savegames?"),
- tr("Do you want to delete local savegames? (If you select \"No\", the "
- "save games will show up again if you re-enable local savegames)"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
- QMessageBox::Cancel);
+ QApplication::activeModalWidget(), tr("Delete profile-specific save games?"),
+ tr("Do you want to delete the profile-specific save games? (If you select \"No\", the "
+ "save games will show up again if you re-enable profile-specific save games)"),
+ QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
+ QMessageBox::Cancel);
if (res == QMessageBox::Yes) {
shellDelete(QStringList(m_Directory.absoluteFilePath("saves")));
} else if (res == QMessageBox::No) {
- m_Directory.rename("saves", "_saves");
+ // No action
} else {
return false;
}
}
-
- // default: assume success
+ storeSetting("LocalSaves", enable);
return true;
+
}
bool Profile::localSettingsEnabled() const
{
- return m_Directory.exists(getIniFileName());
+ bool enabled = setting("LocalSettings", false).toBool();
+ if (enabled) {
+ bool reinitConfig = false;
+ for (QString file : m_GamePlugin->iniFiles()) {
+ if (!QFile::exists(m_Directory.filePath(file))) {
+ qWarning("missing %s in %s", qPrintable(file), qPrintable(m_Directory.path()));
+ reinitConfig = true;
+ }
+ }
+ if (reinitConfig) {
+ QMessageBox::StandardButton res = QMessageBox::warning(
+ QApplication::activeModalWidget(), tr("Missing profile-specific game INI files!"),
+ tr("Some of your profile-specific game INI files were missing. They will now be copied "
+ "from the vanilla game folder. You might want double-check your settings.")
+ );
+ m_GamePlugin->initializeProfile(m_Directory, IPluginGame::CONFIGURATION);
+ }
+ }
+ return enabled;
}
bool Profile::enableLocalSettings(bool enable)
{
- // TODO: this currently assumes game settings are stored in an ini file.
- // This shall become very interesting when a game stores its settings in the
- // registry
- QString backupFile = getIniFileName() + "_";
if (enable) {
- if (m_Directory.exists(backupFile)) {
-
- shellRename(backupFile, getIniFileName());
+ m_GamePlugin->initializeProfile(m_Directory.absolutePath(), IPluginGame::CONFIGURATION);
+ } else {
+ QMessageBox::StandardButton res = QMessageBox::question(
+ QApplication::activeModalWidget(), tr("Delete profile-specific game INI files?"),
+ tr("Do you want to delete the profile-specific game INI files? (If you select \"No\", the "
+ "INI files will be used again if you re-enable profile-specific game INI files.)"),
+ QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
+ QMessageBox::Cancel);
+ if (res == QMessageBox::Yes) {
+ QStringList filesToDelete;
+ for (QString file : m_GamePlugin->iniFiles()) {
+ filesToDelete << m_Directory.absoluteFilePath(file);
+ }
+ shellDelete(filesToDelete, true);
+ } else if (res == QMessageBox::No) {
+ // No action
} else {
- IPluginGame *game = qApp->property("managed_game").value<IPluginGame *>();
- game->initializeProfile(m_Directory, IPluginGame::CONFIGURATION);
+ return false;
}
- } else {
- shellRename(getIniFileName(), backupFile);
}
-
+ storeSetting("LocalSettings", enable);
return true;
}
@@ -825,18 +875,34 @@ void Profile::rename(const QString &newName)
}
QVariant Profile::setting(const QString &section, const QString &name,
- const QVariant &fallback)
+ const QVariant &fallback) const
{
return m_Settings->value(section + "/" + name, fallback);
}
+
void Profile::storeSetting(const QString &section, const QString &name,
const QVariant &value)
{
m_Settings->setValue(section + "/" + name, value);
}
+void Profile::storeSetting(const QString &name, const QVariant &value)
+{
+ storeSetting("", name, value);
+}
+
void Profile::removeSetting(const QString &section, const QString &name)
{
m_Settings->remove(section + "/" + name);
-} \ No newline at end of file
+}
+
+void Profile::removeSetting(const QString &name)
+{
+ removeSetting("", name);
+}
+
+int Profile::getPriorityMinimum() const
+{
+ return m_ModIndexByPriority.begin()->first;
+}