diff options
| author | LostDragonist <lost.dragonist@gmail.com> | 2018-12-20 14:33:08 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-20 14:33:08 -0600 |
| commit | ed67ac211306bee2067178ace1a0a7fbcd0bea1b (patch) | |
| tree | 8fe31503ba20a436457c8c94d61f953b4aa067b4 /src/profile.cpp | |
| parent | 2232bdfc779b8575c8374a723d4d02a2b41fb352 (diff) | |
| parent | 9a33dc148054443cb0efd5916ff758fca5bc09e3 (diff) | |
Merge pull request #586 from ModOrganizer2/Develop
Release 2.1.6
Diffstat (limited to 'src/profile.cpp')
| -rw-r--r-- | src/profile.cpp | 232 |
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 §ion, const QString &name, - const QVariant &fallback) + const QVariant &fallback) const { return m_Settings->value(section + "/" + name, fallback); } + void Profile::storeSetting(const QString §ion, 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 §ion, 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; +} |
