From 07f1ac7a96dcf4c91a24bb1d30af92851ecda78f Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Sat, 3 Aug 2019 01:55:21 -0400
Subject: split into GeometrySettings removed most of storeSettings() from
OrganizerCore: QSettings handles saving by itself, no need for that removed
topLevelSplitter from ui, unused since the log widget is in a dock removed
QSettings from MainWindow::readSettings() replaced return values for some of
the new getters in Settings to std::optional
---
src/executableslist.cpp | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
(limited to 'src/executableslist.cpp')
diff --git a/src/executableslist.cpp b/src/executableslist.cpp
index 3f76bb6f..2b3219df 100644
--- a/src/executableslist.cpp
+++ b/src/executableslist.cpp
@@ -21,6 +21,7 @@ along with Mod Organizer. If not, see .
#include "iplugingame.h"
#include "utility.h"
+#include "settings.h"
#include
#include
@@ -64,7 +65,7 @@ bool ExecutablesList::empty() const
return m_Executables.empty();
}
-void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings)
+void ExecutablesList::load(const MOBase::IPluginGame* game, const Settings& s)
{
log::debug("loading executables");
@@ -74,6 +75,8 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings)
// executables from 2.2.0, see upgradeFromCustom()
bool needsUpgrade = false;
+ auto& settings = const_cast(s.directInterface());
+
int numCustomExecutables = settings.beginReadArray("customExecutables");
for (int i = 0; i < numCustomExecutables; ++i) {
settings.setArrayIndex(i);
@@ -108,8 +111,10 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, QSettings& settings)
dump();
}
-void ExecutablesList::store(QSettings& settings)
+void ExecutablesList::store(Settings& s)
{
+ auto& settings = s.directInterface();
+
settings.remove("customExecutables");
settings.beginWriteArray("customExecutables");
--
cgit v1.3.1
From 4d4f25d1774659e0dfae8e60e13c494cab0f0a44 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Mon, 5 Aug 2019 13:10:21 -0400
Subject: moved getting and setting executables to Settings
---
src/executableslist.cpp | 54 +++++++++++++++++++++----------------------------
src/settings.cpp | 44 ++++++++++++++++++++++++++++++++++++++++
src/settings.h | 3 +++
3 files changed, 70 insertions(+), 31 deletions(-)
(limited to 'src/executableslist.cpp')
diff --git a/src/executableslist.cpp b/src/executableslist.cpp
index 2b3219df..f2df2d6d 100644
--- a/src/executableslist.cpp
+++ b/src/executableslist.cpp
@@ -75,34 +75,29 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, const Settings& s)
// executables from 2.2.0, see upgradeFromCustom()
bool needsUpgrade = false;
- auto& settings = const_cast(s.directInterface());
-
- int numCustomExecutables = settings.beginReadArray("customExecutables");
- for (int i = 0; i < numCustomExecutables; ++i) {
- settings.setArrayIndex(i);
-
+ for (auto& map : s.getExecutables()) {
Executable::Flags flags;
- if (settings.value("toolbar", false).toBool())
+
+ if (map["toolbar"].toBool())
flags |= Executable::ShowInToolbar;
- if (settings.value("ownicon", false).toBool())
+
+ if (map["ownicon"].toBool())
flags |= Executable::UseApplicationIcon;
- if (settings.contains("custom")) {
+ if (map.contains("custom")) {
// the "custom" setting only exists in older versions
needsUpgrade = true;
}
setExecutable(Executable()
- .title(settings.value("title").toString())
- .binaryInfo(settings.value("binary").toString())
- .arguments(settings.value("arguments").toString())
- .steamAppID(settings.value("steamAppID", "").toString())
- .workingDirectory(settings.value("workingDirectory", "").toString())
+ .title(map["title"].toString())
+ .binaryInfo(map["binary"].toString())
+ .arguments(map["arguments"].toString())
+ .steamAppID(map["steamAppID"].toString())
+ .workingDirectory(map["workingDirectory"].toString())
.flags(flags));
}
- settings.endArray();
-
addFromPlugin(game, IgnoreExisting);
if (needsUpgrade)
@@ -113,26 +108,23 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, const Settings& s)
void ExecutablesList::store(Settings& s)
{
- auto& settings = s.directInterface();
+ std::vector> v;
- settings.remove("customExecutables");
- settings.beginWriteArray("customExecutables");
+ for (const auto& item : *this) {
+ std::map map;
- int count = 0;
+ map["title"] = item.title();
+ map["toolbar"] = item.isShownOnToolbar();
+ map["ownicon"] = item.usesOwnIcon();
+ map["binary"] = item.binaryInfo().absoluteFilePath();
+ map["arguments"] = item.arguments();
+ map["workingDirectory"] = item.workingDirectory();
+ map["steamAppID"] = item.steamAppID();
- for (const auto& item : *this) {
- settings.setArrayIndex(count++);
-
- settings.setValue("title", item.title());
- settings.setValue("toolbar", item.isShownOnToolbar());
- settings.setValue("ownicon", item.usesOwnIcon());
- settings.setValue("binary", item.binaryInfo().absoluteFilePath());
- settings.setValue("arguments", item.arguments());
- settings.setValue("workingDirectory", item.workingDirectory());
- settings.setValue("steamAppID", item.steamAppID());
+ v.push_back(std::move(map));
}
- settings.endArray();
+ s.setExecutables(v);
}
std::vector ExecutablesList::getPluginExecutables(
diff --git a/src/settings.cpp b/src/settings.cpp
index cfc5c1d7..a8dcfa39 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -19,6 +19,7 @@ along with Mod Organizer. If not, see .
#include "settings.h"
#include "serverinfo.h"
+#include "executableslist.h"
#include "appconfig.h"
#include
#include
@@ -803,6 +804,49 @@ void Settings::setRecentDirectories(const std::map& map)
m_Settings.endArray();
}
+std::vector> Settings::getExecutables() const
+{
+ const int count = m_Settings.beginReadArray("customExecutables");
+ std::vector> v;
+
+ for (int i=0; i map;
+
+ const auto keys = m_Settings.childKeys();
+ for (auto&& key : keys) {
+ map[key] = m_Settings.value(key);
+ }
+
+ v.push_back(map);
+ }
+
+ m_Settings.endArray();
+
+ return v;
+}
+
+void Settings::setExecutables(const std::vector>& v)
+{
+ m_Settings.remove("customExecutables");
+ m_Settings.beginWriteArray("customExecutables");
+
+ int i = 0;
+
+ for (const auto& map : v) {
+ m_Settings.setArrayIndex(i);
+
+ for (auto&& p : map) {
+ m_Settings.setValue(p.first, p.second);
+ }
+
+ ++i;
+ }
+
+ m_Settings.endArray();
+}
+
GeometrySettings& Settings::geometry()
{
return m_Geometry;
diff --git a/src/settings.h b/src/settings.h
index 5b02ca67..2c4c7ca6 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -221,6 +221,9 @@ public:
std::map getRecentDirectories() const;
void setRecentDirectories(const std::map& map);
+ std::vector> getExecutables() const;
+ void setExecutables(const std::vector>& v);
+
GeometrySettings& geometry();
const GeometrySettings& geometry() const;
--
cgit v1.3.1
From e9dba260cb9548dd5863ac66da18c295f6499b92 Mon Sep 17 00:00:00 2001
From: isanae <14251494+isanae@users.noreply.github.com>
Date: Mon, 2 Sep 2019 14:52:02 -0400
Subject: split settings into a bunch of classes removed "get" from the getters
that had it
---
src/browserdialog.cpp | 2 +-
src/downloadlistsortproxy.cpp | 2 +-
src/downloadmanager.cpp | 2 +-
src/executableslist.cpp | 2 +-
src/filedialogmemory.cpp | 4 +-
src/main.cpp | 26 +-
src/mainwindow.cpp | 121 +--
src/modinfodialog.cpp | 2 +-
src/modinfodialogconflicts.cpp | 16 +-
src/modinfodialogimages.cpp | 4 +-
src/modinfodialognexus.cpp | 2 +-
src/modinfooverwrite.cpp | 2 +-
src/modinforegular.cpp | 2 +-
src/modlist.cpp | 8 +-
src/nxmaccessmanager.cpp | 2 +-
src/organizercore.cpp | 112 +-
src/pluginlist.cpp | 2 +-
src/profile.cpp | 8 +-
src/profilesdialog.cpp | 4 +-
src/settings.cpp | 2075 ++++++++++++++++++++-----------------
src/settings.h | 569 ++++++----
src/settingsdialog.cpp | 6 +-
src/settingsdialogdiagnostics.cpp | 13 +-
src/settingsdialoggeneral.cpp | 28 +-
src/settingsdialognexus.cpp | 32 +-
src/settingsdialogpaths.cpp | 52 +-
src/settingsdialogsteam.cpp | 4 +-
src/settingsdialogworkarounds.cpp | 30 +-
src/statusbar.cpp | 2 +-
src/usvfsconnector.cpp | 4 +-
30 files changed, 1712 insertions(+), 1426 deletions(-)
(limited to 'src/executableslist.cpp')
diff --git a/src/browserdialog.cpp b/src/browserdialog.cpp
index 70da0b9c..72cb8862 100644
--- a/src/browserdialog.cpp
+++ b/src/browserdialog.cpp
@@ -49,7 +49,7 @@ BrowserDialog::BrowserDialog(QWidget *parent)
ui->setupUi(this);
m_AccessManager->setCookieJar(new PersistentCookieJar(
- QDir::fromNativeSeparators(Settings::instance().getCacheDirectory() + "/cookies.dat")));
+ QDir::fromNativeSeparators(Settings::instance().paths().cache() + "/cookies.dat")));
Qt::WindowFlags flags = windowFlags() | Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint;
Qt::WindowFlags helpFlag = Qt::WindowContextHelpButtonHint;
diff --git a/src/downloadlistsortproxy.cpp b/src/downloadlistsortproxy.cpp
index 7bda139b..a69993c0 100644
--- a/src/downloadlistsortproxy.cpp
+++ b/src/downloadlistsortproxy.cpp
@@ -110,7 +110,7 @@ bool DownloadListSortProxy::filterAcceptsRow(int sourceRow, const QModelIndex&)
if (m_CurrentFilter.length() == 0) {
return true;
} else if (sourceRow < m_Manager->numTotalDownloads()) {
- QString displayedName = Settings::instance().metaDownloads()
+ QString displayedName = Settings::instance().interface().metaDownloads()
? m_Manager->getDisplayName(sourceRow)
: m_Manager->getFileName(sourceRow);
return displayedName.contains(m_CurrentFilter, Qt::CaseInsensitive);
diff --git a/src/downloadmanager.cpp b/src/downloadmanager.cpp
index a5dc164c..56238ef3 100644
--- a/src/downloadmanager.cpp
+++ b/src/downloadmanager.cpp
@@ -1731,7 +1731,7 @@ void DownloadManager::nxmDownloadURLsAvailable(QString gameName, int modID, int
return;
}
- const auto servers = m_OrganizerCore->settings().getServers();
+ const auto servers = m_OrganizerCore->settings().network().servers();
std::sort(
resultList.begin(),
diff --git a/src/executableslist.cpp b/src/executableslist.cpp
index f2df2d6d..dce9181b 100644
--- a/src/executableslist.cpp
+++ b/src/executableslist.cpp
@@ -75,7 +75,7 @@ void ExecutablesList::load(const MOBase::IPluginGame* game, const Settings& s)
// executables from 2.2.0, see upgradeFromCustom()
bool needsUpgrade = false;
- for (auto& map : s.getExecutables()) {
+ for (auto& map : s.executables()) {
Executable::Flags flags;
if (map["toolbar"].toBool())
diff --git a/src/filedialogmemory.cpp b/src/filedialogmemory.cpp
index 96587ac7..8cfeb6b5 100644
--- a/src/filedialogmemory.cpp
+++ b/src/filedialogmemory.cpp
@@ -25,12 +25,12 @@ static std::map g_Cache;
void FileDialogMemory::save(Settings& s)
{
- s.setRecentDirectories(g_Cache);
+ s.paths().setRecent(g_Cache);
}
void FileDialogMemory::restore(const Settings& s)
{
- g_Cache = s.getRecentDirectories();
+ g_Cache = s.paths().recent();
}
QString FileDialogMemory::getOpenFileName(
diff --git a/src/main.cpp b/src/main.cpp
index aa781c19..b5568fec 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -246,7 +246,7 @@ static bool HaveWriteAccess(const std::wstring &path)
QString determineProfile(QStringList &arguments, const Settings &settings)
{
- auto selectedProfileName = settings.getSelectedProfileName();
+ auto selectedProfileName = settings.game().selectedProfileName();
{ // see if there is a profile on the command line
int profileIndex = arguments.indexOf("-p", 1);
@@ -271,12 +271,12 @@ QString determineProfile(QStringList &arguments, const Settings &settings)
MOBase::IPluginGame *selectGame(
Settings &settings, QDir const &gamePath, MOBase::IPluginGame *game)
{
- settings.setManagedGameName(game->gameName());
+ settings.game().setName(game->gameName());
QString gameDir = gamePath.absolutePath();
game->setGamePath(gameDir);
- settings.setManagedGameDirectory(gameDir);
+ settings.game().setDirectory(gameDir);
return game;
}
@@ -289,7 +289,7 @@ MOBase::IPluginGame *determineCurrentGame(
//user has done something odd.
//If the game name has been set up, try to use that.
- const auto gameName = settings.getManagedGameName();
+ const auto gameName = settings.game().name();
const bool gameConfigured = (gameName.has_value() && *gameName != "");
if (gameConfigured) {
@@ -299,7 +299,7 @@ MOBase::IPluginGame *determineCurrentGame(
return nullptr;
}
- auto gamePath = settings.getManagedGameDirectory();
+ auto gamePath = settings.game().directory();
if (!gamePath || *gamePath == "") {
gamePath = game->gameDirectory().absolutePath();
}
@@ -320,7 +320,7 @@ MOBase::IPluginGame *determineCurrentGame(
//If we've made it this far and the instance is already configured for a game, something has gone wrong.
//Tell the user about it.
if (gameConfigured) {
- const auto gamePath = settings.getManagedGameDirectory();
+ const auto gamePath = settings.game().directory();
reportError(
QObject::tr("Could not use configuration settings for game \"%1\", path \"%2\".")
@@ -570,11 +570,11 @@ int runApplication(MOApplication &application, SingleInstance &instance,
log::info("working directory: {}", QDir::currentPath());
Settings settings(dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()));
- log::getDefault().setLevel(settings.logLevel());
+ log::getDefault().setLevel(settings.diagnostics().logLevel());
// global crashDumpType sits in OrganizerCore to make a bit less ugly to
// update it when the settings are changed during runtime
- OrganizerCore::setGlobalCrashDumpsType(settings.crashDumpsType());
+ OrganizerCore::setGlobalCrashDumpsType(settings.diagnostics().crashDumpsType());
env::Environment env;
@@ -621,7 +621,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
QString edition;
- if (auto v=settings.getManagedGameEdition()) {
+ if (auto v=settings.game().edition()) {
edition = *v;
} else {
QStringList editions = game->gameVariants();
@@ -640,7 +640,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
return 1;
} else {
edition = selection.getChoiceString();
- settings.setManagedGameEdition(edition);
+ settings.game().setEdition(edition);
}
}
}
@@ -702,7 +702,7 @@ int runApplication(MOApplication &application, SingleInstance &instance,
splash.activateWindow();
QString apiKey;
- if (settings.getNexusApiKey(apiKey)) {
+ if (settings.nexus().apiKey(apiKey)) {
NexusInterface::instance(&pluginContainer)->getAccessManager()->apiCheck(apiKey);
}
@@ -712,9 +712,9 @@ int runApplication(MOApplication &application, SingleInstance &instance,
+ QString::fromStdWString(AppConfig::tutorialsPath()) + "/",
&organizer);
- if (!application.setStyleFile(settings.getStyleName().value_or(""))) {
+ if (!application.setStyleFile(settings.interface().styleName().value_or(""))) {
// disable invalid stylesheet
- settings.setStyleName("");
+ settings.interface().setStyleName("");
}
int res = 1;
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 42b19cb7..657c1a27 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -222,8 +222,8 @@ MainWindow::MainWindow(Settings &settings
{
QWebEngineProfile::defaultProfile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);
QWebEngineProfile::defaultProfile()->setHttpCacheMaximumSize(52428800);
- QWebEngineProfile::defaultProfile()->setCachePath(settings.getCacheDirectory());
- QWebEngineProfile::defaultProfile()->setPersistentStoragePath(settings.getCacheDirectory());
+ QWebEngineProfile::defaultProfile()->setCachePath(settings.paths().cache());
+ QWebEngineProfile::defaultProfile()->setPersistentStoragePath(settings.paths().cache());
ui->setupUi(this);
ui->statusBar->setup(ui);
@@ -253,7 +253,7 @@ MainWindow::MainWindow(Settings &settings
ui->statusBar->setAPI(ni->getAPIStats(), ni->getAPIUserAccount());
}
- languageChange(settings.language());
+ languageChange(settings.interface().language());
m_CategoryFactory.loadCategories();
@@ -1194,7 +1194,7 @@ void MainWindow::hookUpWindowTutorials()
QString firstLine = QString::fromUtf8(file.readLine());
if (firstLine.startsWith("//WIN")) {
QString windowName = firstLine.mid(6).trimmed();
- if (!m_OrganizerCore.settings().isTutorialCompleted(windowName)) {
+ if (!m_OrganizerCore.settings().interface().isTutorialCompleted(windowName)) {
TutorialManager::instance().activateTutorial(windowName, fileName);
}
}
@@ -1225,7 +1225,7 @@ void MainWindow::showEvent(QShowEvent *event)
hookUpWindowTutorials();
- if (m_OrganizerCore.settings().getFirstStart()) {
+ if (m_OrganizerCore.settings().firstStart()) {
QString firstStepsTutorial = ToQString(AppConfig::firstStepsTutorial());
if (TutorialManager::instance().hasTutorial(firstStepsTutorial)) {
if (QMessageBox::question(this, tr("Show tutorial?"),
@@ -1247,11 +1247,11 @@ void MainWindow::showEvent(QShowEvent *event)
m_OrganizerCore.settings().setFirstStart(false);
}
- m_OrganizerCore.settings().restoreIndex(ui->groupCombo);
+ m_OrganizerCore.settings().widgets().restoreIndex(ui->groupCombo);
allowListResize();
- m_OrganizerCore.settings().registerAsNXMHandler(false);
+ m_OrganizerCore.settings().nexus().registerAsNXMHandler(false);
m_WasVisible = true;
updateProblemsButton();
}
@@ -1751,7 +1751,7 @@ bool MainWindow::refreshProfiles(bool selectProfile)
profileBox->clear();
profileBox->addItem(QObject::tr(""));
- QDir profilesDir(Settings::instance().getProfileDirectory());
+ QDir profilesDir(Settings::instance().paths().profiles());
profilesDir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
QDirIterator profileIter(profilesDir);
@@ -1990,7 +1990,7 @@ void MainWindow::updateBSAList(const QStringList &defaultArchives, const QString
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()
+ if (m_OrganizerCore.settings().game().forceEnableCoreFiles()
&& defaultArchives.contains(fileInfo.fileName())) {
newItem->setCheckState(0, Qt::Checked);
newItem->setDisabled(true);
@@ -2140,7 +2140,7 @@ void MainWindow::readSettings(const Settings& settings)
{
// special case in case someone puts 0 in the INI
- auto v = settings.getIndex(ui->executablesListBox);
+ auto v = settings.widgets().index(ui->executablesListBox);
if (!v || v == 0) {
v = 1;
}
@@ -2148,7 +2148,7 @@ void MainWindow::readSettings(const Settings& settings)
ui->executablesListBox->setCurrentIndex(*v);
}
- settings.restoreIndex(ui->groupCombo);
+ settings.widgets().restoreIndex(ui->groupCombo);
{
settings.geometry().restoreVisibility(ui->categoriesGroup, false);
@@ -2157,7 +2157,7 @@ void MainWindow::readSettings(const Settings& settings)
ui->displayCategoriesBtn->setChecked(v);
}
- if (settings.getUseProxy()) {
+ if (settings.network().useProxy()) {
activateProxy(true);
}
}
@@ -2165,12 +2165,12 @@ void MainWindow::readSettings(const Settings& settings)
void MainWindow::processUpdates(Settings& settings) {
const auto earliest = QVersionNumber::fromString("2.1.2").normalized();
- const auto lastVersion = settings.getVersion().value_or(earliest);
+ const auto lastVersion = settings.version().value_or(earliest);
const auto currentVersion = m_OrganizerCore.getVersion().asQVersionNumber();
settings.processUpdates(currentVersion, lastVersion);
- if (!settings.getFirstStart()) {
+ if (!settings.firstStart()) {
if (lastVersion < QVersionNumber(2, 1, 3)) {
bool lastHidden = true;
for (int i = ModList::COL_GAME; i < ui->modList->model()->columnCount(); ++i) {
@@ -2222,8 +2222,8 @@ void MainWindow::storeSettings(Settings& s)
s.geometry().saveState(ui->downloadView->header());
s.geometry().saveState(ui->modList->header());
- s.saveIndex(ui->groupCombo);
- s.saveIndex(ui->executablesListBox);
+ s.widgets().saveIndex(ui->groupCombo);
+ s.widgets().saveIndex(ui->executablesListBox);
}
ILockedWaitingForProcess* MainWindow::lock()
@@ -2751,7 +2751,7 @@ void MainWindow::restoreBackup_clicked()
ModInfo::Ptr modInfo = ModInfo::getByIndex(m_ContextRow);
if (backupRegEx.indexIn(modInfo->name()) != -1) {
QString regName = backupRegEx.cap(1);
- QDir modDir(QDir::fromNativeSeparators(m_OrganizerCore.settings().getModDirectory()));
+ QDir modDir(QDir::fromNativeSeparators(m_OrganizerCore.settings().paths().mods()));
if (!modDir.exists(regName) ||
(QMessageBox::question(this, tr("Overwrite?"),
tr("This will replace the existing mod \"%1\". Continue?").arg(regName),
@@ -2759,7 +2759,7 @@ void MainWindow::restoreBackup_clicked()
if (modDir.exists(regName) && !shellDelete(QStringList(modDir.absoluteFilePath(regName)))) {
reportError(tr("failed to remove mod \"%1\"").arg(regName));
} else {
- QString destinationPath = QDir::fromNativeSeparators(m_OrganizerCore.settings().getModDirectory()) + "/" + regName;
+ QString destinationPath = QDir::fromNativeSeparators(m_OrganizerCore.settings().paths().mods()) + "/" + regName;
if (!modDir.rename(modInfo->absolutePath(), destinationPath)) {
reportError(tr("failed to rename \"%1\" to \"%2\"").arg(modInfo->absolutePath()).arg(destinationPath));
}
@@ -3015,7 +3015,7 @@ void MainWindow::untrack_clicked()
void MainWindow::windowTutorialFinished(const QString &windowName)
{
- m_OrganizerCore.settings().setTutorialCompleted(windowName);
+ m_OrganizerCore.settings().interface().setTutorialCompleted(windowName);
}
void MainWindow::overwriteClosed(int)
@@ -3645,7 +3645,7 @@ void MainWindow::createSeparator_clicked()
m_OrganizerCore.modList()->changeModPriority(ModInfo::getIndex(name), newPriority);
}
- if (auto c=m_OrganizerCore.settings().getPreviousSeparatorColor()) {
+ if (auto c=m_OrganizerCore.settings().colors().previousSeparatorColor()) {
ModInfo::getByIndex(ModInfo::getIndex(name))->setColor(*c);
}
}
@@ -3662,7 +3662,7 @@ void MainWindow::setColor_clicked()
if (currentColor.isValid()) {
dialog.setCurrentColor(currentColor);
}
- else if (auto c=settings.getPreviousSeparatorColor()) {
+ else if (auto c=settings.colors().previousSeparatorColor()) {
dialog.setCurrentColor(*c);
}
@@ -3673,7 +3673,7 @@ void MainWindow::setColor_clicked()
if (!currentColor.isValid())
return;
- settings.setPreviousSeparatorColor(currentColor);
+ settings.colors().setPreviousSeparatorColor(currentColor);
QItemSelectionModel *selection = ui->modList->selectionModel();
if (selection->hasSelection() && selection->selectedRows().count() > 1) {
@@ -3710,7 +3710,7 @@ void MainWindow::resetColor_clicked()
modInfo->setColor(color);
}
- m_OrganizerCore.settings().removePreviousSeparatorColor();
+ m_OrganizerCore.settings().colors().removePreviousSeparatorColor();
}
void MainWindow::createModFromOverwrite()
@@ -4184,7 +4184,7 @@ void MainWindow::checkModsForUpdates()
NexusInterface::instance(&m_PluginContainer)->requestTrackingInfo(this, QVariant(), QString());
} else {
QString apiKey;
- if (m_OrganizerCore.settings().getNexusApiKey(apiKey)) {
+ if (m_OrganizerCore.settings().nexus().apiKey(apiKey)) {
m_OrganizerCore.doAfterLogin([this] () { this->checkModsForUpdates(); });
NexusInterface::instance(&m_PluginContainer)->getAccessManager()->apiCheck(apiKey);
} else {
@@ -4387,12 +4387,12 @@ void MainWindow::openIniFolder()
void MainWindow::openDownloadsFolder()
{
- shell::ExploreFile(m_OrganizerCore.settings().getDownloadDirectory());
+ shell::ExploreFile(m_OrganizerCore.settings().paths().downloads());
}
void MainWindow::openModsFolder()
{
- shell::ExploreFile(m_OrganizerCore.settings().getModDirectory());
+ shell::ExploreFile(m_OrganizerCore.settings().paths().mods());
}
void MainWindow::openGameFolder()
@@ -4758,7 +4758,7 @@ void MainWindow::on_modList_customContextMenuRequested(const QPoint &pos)
menu.addSeparator();
- if (info->getNexusID() > 0 && Settings::instance().endorsementIntegration()) {
+ if (info->getNexusID() > 0 && Settings::instance().nexus().endorsementIntegration()) {
switch (info->endorsedState()) {
case ModInfo::ENDORSED_TRUE: {
menu.addAction(tr("Un-Endorse"), this, SLOT(unendorse_clicked()));
@@ -5007,19 +5007,19 @@ void MainWindow::on_actionSettings_triggered()
{
Settings &settings = m_OrganizerCore.settings();
- QString oldModDirectory(settings.getModDirectory());
- QString oldCacheDirectory(settings.getCacheDirectory());
- QString oldProfilesDirectory(settings.getProfileDirectory());
- QString oldManagedGameDirectory(settings.getManagedGameDirectory().value_or(""));
- bool oldDisplayForeign(settings.displayForeign());
- bool proxy = settings.getUseProxy();
+ QString oldModDirectory(settings.paths().mods());
+ QString oldCacheDirectory(settings.paths().cache());
+ QString oldProfilesDirectory(settings.paths().profiles());
+ QString oldManagedGameDirectory(settings.game().directory().value_or(""));
+ bool oldDisplayForeign(settings.interface().displayForeign());
+ bool proxy = settings.network().useProxy();
DownloadManager *dlManager = m_OrganizerCore.downloadManager();
SettingsDialog dialog(&m_PluginContainer, settings, this);
dialog.exec();
- if (oldManagedGameDirectory != settings.getManagedGameDirectory()) {
+ if (oldManagedGameDirectory != settings.game().directory()) {
QMessageBox::about(this, tr("Restarting MO"),
tr("Changing the managed game directory requires restarting MO.\n"
"Any pending downloads will be paused.\n\n"
@@ -5029,28 +5029,28 @@ void MainWindow::on_actionSettings_triggered()
}
InstallationManager *instManager = m_OrganizerCore.installationManager();
- instManager->setModsDirectory(settings.getModDirectory());
- instManager->setDownloadDirectory(settings.getDownloadDirectory());
+ instManager->setModsDirectory(settings.paths().mods());
+ instManager->setDownloadDirectory(settings.paths().downloads());
fixCategories();
refreshFilters();
- if (settings.getProfileDirectory() != oldProfilesDirectory) {
+ if (settings.paths().profiles() != oldProfilesDirectory) {
refreshProfiles();
}
- if (dlManager->getOutputDirectory() != settings.getDownloadDirectory()) {
+ if (dlManager->getOutputDirectory() != settings.paths().downloads()) {
if (dlManager->downloadsInProgress()) {
MessageDialog::showMessage(tr("Can't change download directory while "
"downloads are in progress!"),
this);
} else {
- dlManager->setOutputDirectory(settings.getDownloadDirectory());
+ dlManager->setOutputDirectory(settings.paths().downloads());
}
}
- if ((settings.getModDirectory() != oldModDirectory)
- || (settings.displayForeign() != oldDisplayForeign)) {
+ if ((settings.paths().mods() != oldModDirectory)
+ || (settings.interface().displayForeign() != oldDisplayForeign)) {
m_OrganizerCore.profileRefresh();
}
@@ -5075,18 +5075,19 @@ void MainWindow::on_actionSettings_triggered()
m_OrganizerCore.refreshLists();
}
- if (settings.getCacheDirectory() != oldCacheDirectory) {
- NexusInterface::instance(&m_PluginContainer)->setCacheDirectory(settings.getCacheDirectory());
+ if (settings.paths().cache() != oldCacheDirectory) {
+ NexusInterface::instance(&m_PluginContainer)->setCacheDirectory(
+ settings.paths().cache());
}
- if (proxy != settings.getUseProxy()) {
- activateProxy(settings.getUseProxy());
+ if (proxy != settings.network().useProxy()) {
+ activateProxy(settings.network().useProxy());
}
ui->statusBar->checkSettings(m_OrganizerCore.settings());
updateDownloadView();
- m_OrganizerCore.setLogLevel(settings.logLevel());
+ m_OrganizerCore.setLogLevel(settings.diagnostics().logLevel());
m_OrganizerCore.cycleDiagnostics();
toggleMO2EndorseState();
@@ -5402,10 +5403,10 @@ void MainWindow::motdReceived(const QString &motd)
// internet connection is faster next time
if (m_StartTime.secsTo(QTime::currentTime()) < 5) {
uint hash = qHash(motd);
- if (hash != m_OrganizerCore.settings().getMotDHash()) {
+ if (hash != m_OrganizerCore.settings().motdHash()) {
MotDDialog dialog(motd);
dialog.exec();
- m_OrganizerCore.settings().setMotDHash(hash);
+ m_OrganizerCore.settings().setMotdHash(hash);
}
}
}
@@ -5528,7 +5529,7 @@ void MainWindow::initDownloadView()
void MainWindow::updateDownloadView()
{
// set the view attribute and default row sizes
- if (m_OrganizerCore.settings().compactDownloads()) {
+ if (m_OrganizerCore.settings().interface().compactDownloads()) {
ui->downloadView->setProperty("downloadView", "compact");
setStyleSheet("DownloadListWidget::item { padding: 4px 2px; }");
} else {
@@ -5541,7 +5542,7 @@ void MainWindow::updateDownloadView()
// reapply global stylesheet on the widget level (!) to override the defaults
//ui->downloadView->setStyleSheet(styleSheet());
- ui->downloadView->setMetaDisplay(m_OrganizerCore.settings().metaDownloads());
+ ui->downloadView->setMetaDisplay(m_OrganizerCore.settings().interface().metaDownloads());
ui->downloadView->style()->unpolish(ui->downloadView);
ui->downloadView->style()->polish(ui->downloadView);
qobject_cast(ui->downloadView->header())->customResizeSections();
@@ -5554,7 +5555,7 @@ void MainWindow::modUpdateCheck(std::multimap IDs)
ModInfo::manualUpdateCheck(&m_PluginContainer, this, IDs);
} else {
QString apiKey;
- if (m_OrganizerCore.settings().getNexusApiKey(apiKey)) {
+ if (m_OrganizerCore.settings().nexus().apiKey(apiKey)) {
m_OrganizerCore.doAfterLogin([=]() { this->modUpdateCheck(IDs); });
NexusInterface::instance(&m_PluginContainer)->getAccessManager()->apiCheck(apiKey);
} else
@@ -5566,7 +5567,7 @@ void MainWindow::toggleMO2EndorseState()
{
const auto& s = m_OrganizerCore.settings();
- if (!s.endorsementIntegration()) {
+ if (!s.nexus().endorsementIntegration()) {
ui->actionEndorseMO->setVisible(false);
return;
}
@@ -5576,7 +5577,7 @@ void MainWindow::toggleMO2EndorseState()
bool enabled = false;
QString text;
- switch (s.endorsementState())
+ switch (s.nexus().endorsementState())
{
case EndorsementState::Accepted:
{
@@ -5631,9 +5632,9 @@ void MainWindow::nxmEndorsementsAvailable(QVariant userData, QVariant resultData
mod->setIsEndorsed(false);
}
- if (Settings::instance().endorsementIntegration()) {
+ if (Settings::instance().nexus().endorsementIntegration()) {
if (result->first == "skyrimspecialedition" && result->second.first == gamePlugin->nexusModOrganizerID()) {
- m_OrganizerCore.settings().setEndorsementState(
+ m_OrganizerCore.settings().nexus().setEndorsementState(
endorsementStateFromString(result->second.second));
toggleMO2EndorseState();
@@ -5642,13 +5643,13 @@ void MainWindow::nxmEndorsementsAvailable(QVariant userData, QVariant resultData
}
}
- if (!searchedMO2NexusGame && Settings::instance().endorsementIntegration()) {
+ if (!searchedMO2NexusGame && Settings::instance().nexus().endorsementIntegration()) {
auto gamePlugin = m_OrganizerCore.getGame("SkyrimSE");
if (gamePlugin) {
auto iter = sorted.equal_range(gamePlugin->gameNexusName());
for (auto result = iter.first; result != iter.second; ++result) {
if (result->second.first == gamePlugin->nexusModOrganizerID()) {
- m_OrganizerCore.settings().setEndorsementState(
+ m_OrganizerCore.settings().nexus().setEndorsementState(
endorsementStateFromString(result->second.second));
toggleMO2EndorseState();
@@ -5862,7 +5863,7 @@ void MainWindow::nxmEndorsementToggled(QString, int, QVariant, QVariant resultDa
}
}
- m_OrganizerCore.settings().setEndorsementState(s);
+ m_OrganizerCore.settings().nexus().setEndorsementState(s);
toggleMO2EndorseState();
if (!disconnect(sender(), SIGNAL(nxmEndorsementToggled(QString, int, QVariant, QVariant, int)),
@@ -5901,7 +5902,7 @@ void MainWindow::nxmTrackedModsAvailable(QVariant userData, QVariant resultData,
void MainWindow::nxmDownloadURLs(QString, int, int, QVariant, QVariant resultData, int)
{
- auto servers = m_OrganizerCore.settings().getServers();
+ auto servers = m_OrganizerCore.settings().network().servers();
for (const QVariant &var : resultData.toList()) {
const QVariantMap map = var.toMap();
@@ -5929,7 +5930,7 @@ void MainWindow::nxmDownloadURLs(QString, int, int, QVariant, QVariant resultDat
}
}
- m_OrganizerCore.settings().updateServers(servers);
+ m_OrganizerCore.settings().network().updateServers(servers);
}
diff --git a/src/modinfodialog.cpp b/src/modinfodialog.cpp
index f3840230..2178ef34 100644
--- a/src/modinfodialog.cpp
+++ b/src/modinfodialog.cpp
@@ -381,7 +381,7 @@ void ModInfoDialog::reAddTabs(
Q_ASSERT(visibility.size() == m_tabs.size());
// ordered tab names from settings
- const auto orderedNames = m_core->settings().geometry().getModInfoTabOrder();
+ const auto orderedNames = m_core->settings().geometry().modInfoTabOrder();
// whether the tabs can be sorted; if the object name of a tab widget is not
// found in orderedNames, the list cannot be sorted safely
diff --git a/src/modinfodialogconflicts.cpp b/src/modinfodialogconflicts.cpp
index 7840269d..3a71b405 100644
--- a/src/modinfodialogconflicts.cpp
+++ b/src/modinfodialogconflicts.cpp
@@ -409,7 +409,7 @@ void ConflictsTab::clear()
void ConflictsTab::saveState(Settings& s)
{
- s.saveIndex(ui->tabConflictsTabs);
+ s.widgets().saveIndex(ui->tabConflictsTabs);
m_general.saveState(s);
m_advanced.saveState(s);
@@ -417,7 +417,7 @@ void ConflictsTab::saveState(Settings& s)
void ConflictsTab::restoreState(const Settings& s)
{
- s.restoreIndex(ui->tabConflictsTabs, 0);
+ s.widgets().restoreIndex(ui->tabConflictsTabs, 0);
m_general.restoreState(s);
m_advanced.restoreState(s);
@@ -1014,17 +1014,17 @@ void AdvancedConflictsTab::clear()
void AdvancedConflictsTab::saveState(Settings& s)
{
s.geometry().saveState(ui->conflictsAdvancedList->header());
- s.saveChecked(ui->conflictsAdvancedShowNoConflict);
- s.saveChecked(ui->conflictsAdvancedShowAll);
- s.saveChecked(ui->conflictsAdvancedShowNearest);
+ s.widgets().saveChecked(ui->conflictsAdvancedShowNoConflict);
+ s.widgets().saveChecked(ui->conflictsAdvancedShowAll);
+ s.widgets().saveChecked(ui->conflictsAdvancedShowNearest);
}
void AdvancedConflictsTab::restoreState(const Settings& s)
{
s.geometry().restoreState(ui->conflictsAdvancedList->header());
- s.restoreChecked(ui->conflictsAdvancedShowNoConflict);
- s.restoreChecked(ui->conflictsAdvancedShowAll);
- s.restoreChecked(ui->conflictsAdvancedShowNearest);
+ s.widgets().restoreChecked(ui->conflictsAdvancedShowNoConflict);
+ s.widgets().restoreChecked(ui->conflictsAdvancedShowAll);
+ s.widgets().restoreChecked(ui->conflictsAdvancedShowNearest);
}
void AdvancedConflictsTab::update()
diff --git a/src/modinfodialogimages.cpp b/src/modinfodialogimages.cpp
index 38c12d8a..9d347f57 100644
--- a/src/modinfodialogimages.cpp
+++ b/src/modinfodialogimages.cpp
@@ -130,13 +130,13 @@ void ImagesTab::update()
void ImagesTab::saveState(Settings& s)
{
- s.saveChecked(ui->imagesShowDDS);
+ s.widgets().saveChecked(ui->imagesShowDDS);
s.geometry().saveState(ui->tabImagesSplitter);
}
void ImagesTab::restoreState(const Settings& s)
{
- s.restoreChecked(ui->imagesShowDDS);
+ s.widgets().restoreChecked(ui->imagesShowDDS);
s.geometry().restoreState(ui->tabImagesSplitter);
}
diff --git a/src/modinfodialognexus.cpp b/src/modinfodialognexus.cpp
index 6d28cbe3..95e62328 100644
--- a/src/modinfodialognexus.cpp
+++ b/src/modinfodialognexus.cpp
@@ -19,7 +19,7 @@ NexusTab::NexusTab(ModInfoDialogTabContext cx) :
ModInfoDialogTab(std::move(cx)), m_requestStarted(false), m_loading(false)
{
ui->modID->setValidator(new QIntValidator(ui->modID));
- ui->endorse->setVisible(core().settings().endorsementIntegration());
+ ui->endorse->setVisible(core().settings().nexus().endorsementIntegration());
connect(ui->modID, &QLineEdit::editingFinished, [&]{ onModIDChanged(); });
connect(
diff --git a/src/modinfooverwrite.cpp b/src/modinfooverwrite.cpp
index 37c8c650..fb110abb 100644
--- a/src/modinfooverwrite.cpp
+++ b/src/modinfooverwrite.cpp
@@ -23,7 +23,7 @@ bool ModInfoOverwrite::isEmpty() const
QString ModInfoOverwrite::absolutePath() const
{
- return Settings::instance().getOverwriteDirectory();
+ return Settings::instance().paths().overwrite();
}
std::vector ModInfoOverwrite::getFlags() const
diff --git a/src/modinforegular.cpp b/src/modinforegular.cpp
index ce29e11e..3cff914a 100644
--- a/src/modinforegular.cpp
+++ b/src/modinforegular.cpp
@@ -631,7 +631,7 @@ std::vector ModInfoRegular::getFlags() const
std::vector result = ModInfoWithConflictInfo::getFlags();
if ((m_NexusID > 0) &&
(endorsedState() == ENDORSED_FALSE) &&
- Settings::instance().endorsementIntegration()) {
+ Settings::instance().nexus().endorsementIntegration()) {
result.push_back(ModInfo::FLAG_NOTENDORSED);
}
if ((m_NexusID > 0) &&
diff --git a/src/modlist.cpp b/src/modlist.cpp
index 94b4a387..6018d3d4 100644
--- a/src/modlist.cpp
+++ b/src/modlist.cpp
@@ -390,7 +390,7 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
return QVariant();
} else if (role == Qt::ForegroundRole) {
if (modInfo->hasFlag(ModInfo::FLAG_SEPARATOR) && modInfo->getColor().isValid()) {
- return Settings::getIdealTextColor(modInfo->getColor());
+ return ColorSettings::idealTextColor(modInfo->getColor());
} else if (column == COL_NAME) {
int highlight = modInfo->getHighlight();
if (highlight & ModInfo::HIGHLIGHT_IMPORTANT)
@@ -428,7 +428,7 @@ QVariant ModList::data(const QModelIndex &modelIndex, int role) const
} else if (modInfo->hasFlag(ModInfo::FLAG_SEPARATOR)
&& modInfo->getColor().isValid()
&& ((role != ViewMarkingScrollBar::DEFAULT_ROLE)
- || Settings::instance().colorSeparatorScrollbar())) {
+ || Settings::instance().colors().colorSeparatorScrollbar())) {
return modInfo->getColor();
} else {
return QVariant();
@@ -999,8 +999,8 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa
ModInfo::Ptr modInfo = ModInfo::getByIndex(row);
QDir modDir = QDir(modInfo->absolutePath());
- QDir allModsDir(Settings::instance().getModDirectory());
- QDir overwriteDir(Settings::instance().getOverwriteDirectory());
+ QDir allModsDir(Settings::instance().paths().mods());
+ QDir overwriteDir(Settings::instance().paths().overwrite());
QStringList sourceList;
QStringList targetList;
diff --git a/src/nxmaccessmanager.cpp b/src/nxmaccessmanager.cpp
index 16190ca4..c6ef7bc7 100644
--- a/src/nxmaccessmanager.cpp
+++ b/src/nxmaccessmanager.cpp
@@ -572,7 +572,7 @@ NXMAccessManager::NXMAccessManager(QObject *parent, const QString &moVersion)
m_validator.finished = [&](auto&& user){ onValidatorFinished(user); };
setCookieJar(new PersistentCookieJar(QDir::fromNativeSeparators(
- Settings::instance().getCacheDirectory() + "/nexus_cookies.dat")));
+ Settings::instance().paths().cache() + "/nexus_cookies.dat")));
if (networkAccessible() == QNetworkAccessManager::UnknownAccessibility) {
// why is this necessary all of a sudden?
diff --git a/src/organizercore.cpp b/src/organizercore.cpp
index af0cf969..1a89641d 100644
--- a/src/organizercore.cpp
+++ b/src/organizercore.cpp
@@ -146,7 +146,7 @@ static void startSteam(QWidget *widget)
QStringList args;
QString username;
QString password;
- if (Settings::instance().getSteamLogin(username, password)) {
+ if (Settings::instance().steam().login(username, password)) {
args << "-login";
args << username;
if (password != "") {
@@ -275,12 +275,13 @@ OrganizerCore::OrganizerCore(Settings &settings)
, m_ArchivesInit(false)
, m_PluginListsWriter(std::bind(&OrganizerCore::savePluginList, this))
{
- m_DownloadManager.setOutputDirectory(m_Settings.getDownloadDirectory());
+ m_DownloadManager.setOutputDirectory(m_Settings.paths().downloads());
- NexusInterface::instance(m_PluginContainer)->setCacheDirectory(m_Settings.getCacheDirectory());
+ NexusInterface::instance(m_PluginContainer)->setCacheDirectory(
+ m_Settings.paths().cache());
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
- m_InstallationManager.setDownloadDirectory(m_Settings.getDownloadDirectory());
+ m_InstallationManager.setModsDirectory(m_Settings.paths().mods());
+ m_InstallationManager.setDownloadDirectory(m_Settings.paths().downloads());
connect(&m_DownloadManager, SIGNAL(downloadSpeed(QString, int)), this,
SLOT(downloadSpeed(QString, int)));
@@ -333,7 +334,7 @@ OrganizerCore::~OrganizerCore()
void OrganizerCore::storeSettings()
{
if (m_CurrentProfile != nullptr) {
- m_Settings.setSelectedProfileName(m_CurrentProfile->name());
+ m_Settings.game().setSelectedProfileName(m_CurrentProfile->name());
}
m_ExecutablesList.store(m_Settings);
@@ -356,7 +357,7 @@ void OrganizerCore::storeSettings()
QMessageBox::critical(
qApp->activeWindow(), tr("Failed to write settings"),
tr("An error occurred trying to write back MO settings to %1: %2")
- .arg(m_Settings.getFilename(), reason));
+ .arg(m_Settings.filename(), reason));
}
}
@@ -432,8 +433,9 @@ void OrganizerCore::updateExecutablesList()
// TODO this has nothing to do with executables list move to an appropriate
// function!
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure,
- m_PluginContainer, m_Settings.displayForeign(), managedGame());
+ ModInfo::updateFromDisc(
+ m_Settings.paths().mods(), &m_DirectoryStructure,
+ m_PluginContainer, m_Settings.interface().displayForeign(), managedGame());
}
void OrganizerCore::setUserInterface(IUserInterface *userInterface,
@@ -478,7 +480,7 @@ void OrganizerCore::setUserInterface(IUserInterface *userInterface,
if (userInterface != nullptr) {
// this currently wouldn't work reliably if the ui isn't initialized yet to
// display the result
- if (isOnline() && !m_Settings.offlineMode()) {
+ if (isOnline() && !m_Settings.network().offlineMode()) {
m_Updater.testForUpdate();
} else {
log::debug("user doesn't seem to be connected to the internet");
@@ -541,7 +543,7 @@ bool OrganizerCore::nexusApi(bool retry)
return false;
} else {
QString apiKey;
- if (m_Settings.getNexusApiKey(apiKey)) {
+ if (m_Settings.nexus().apiKey(apiKey)) {
// credentials stored or user entered them manually
log::debug("attempt to verify nexus api key");
accessManager->apiCheck(apiKey);
@@ -608,7 +610,7 @@ void OrganizerCore::removeOrigin(const QString &name)
void OrganizerCore::downloadSpeed(const QString &serverName, int bytesPerSecond)
{
- m_Settings.setDownloadSpeed(serverName, bytesPerSecond);
+ m_Settings.network().setDownloadSpeed(serverName, bytesPerSecond);
}
InstallationManager *OrganizerCore::installationManager()
@@ -629,9 +631,9 @@ bool OrganizerCore::createDirectory(const QString &path) {
}
bool OrganizerCore::checkPathSymlinks() {
- bool hasSymlink = (QFileInfo(m_Settings.getProfileDirectory()).isSymLink() ||
- QFileInfo(m_Settings.getModDirectory()).isSymLink() ||
- QFileInfo(m_Settings.getOverwriteDirectory()).isSymLink());
+ bool hasSymlink = (QFileInfo(m_Settings.paths().profiles()).isSymLink() ||
+ QFileInfo(m_Settings.paths().mods()).isSymLink() ||
+ QFileInfo(m_Settings.paths().overwrite()).isSymLink());
if (hasSymlink) {
QMessageBox::critical(nullptr, QObject::tr("Error"),
QObject::tr("One of the configured MO2 directories (profiles, mods, or overwrite) "
@@ -643,17 +645,17 @@ bool OrganizerCore::checkPathSymlinks() {
}
bool OrganizerCore::bootstrap() {
- return createDirectory(m_Settings.getProfileDirectory()) &&
- createDirectory(m_Settings.getModDirectory()) &&
- createDirectory(m_Settings.getDownloadDirectory()) &&
- createDirectory(m_Settings.getOverwriteDirectory()) &&
+ return createDirectory(m_Settings.paths().profiles()) &&
+ createDirectory(m_Settings.paths().mods()) &&
+ createDirectory(m_Settings.paths().downloads()) &&
+ createDirectory(m_Settings.paths().overwrite()) &&
createDirectory(QString::fromStdWString(crashDumpsPath())) &&
checkPathSymlinks() && cycleDiagnostics();
}
void OrganizerCore::createDefaultProfile()
{
- QString profilesPath = settings().getProfileDirectory();
+ QString profilesPath = settings().paths().profiles();
if (QDir(profilesPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot).size()
== 0) {
Profile newProf("Default", managedGame(), false);
@@ -674,18 +676,18 @@ void OrganizerCore::updateVFSParams(
void OrganizerCore::setLogLevel(log::Levels level)
{
- m_Settings.setLogLevel(level);
+ m_Settings.diagnostics().setLogLevel(level);
updateVFSParams(
- m_Settings.logLevel(),
- m_Settings.crashDumpsType(),
+ m_Settings.diagnostics().logLevel(),
+ m_Settings.diagnostics().crashDumpsType(),
m_Settings.executablesBlacklist());
- log::getDefault().setLevel(m_Settings.logLevel());
+ log::getDefault().setLevel(m_Settings.diagnostics().logLevel());
}
bool OrganizerCore::cycleDiagnostics() {
- if (int maxDumps = settings().crashDumpsMax())
+ if (int maxDumps = settings().diagnostics().crashDumpsMax())
removeOldFiles(QString::fromStdWString(crashDumpsPath()), "*.dmp", maxDumps, QDir::Time|QDir::Reversed);
return true;
}
@@ -720,7 +722,7 @@ void OrganizerCore::setCurrentProfile(const QString &profileName)
return;
}
- QDir profileBaseDir(settings().getProfileDirectory());
+ QDir profileBaseDir(settings().paths().profiles());
QString profileDir = profileBaseDir.absoluteFilePath(profileName);
if (!QDir(profileDir).exists()) {
@@ -744,7 +746,7 @@ void OrganizerCore::setCurrentProfile(const QString &profileName)
m_CurrentProfile->deactivateInvalidation();
}
- m_Settings.setSelectedProfileName(m_CurrentProfile->name());
+ m_Settings.game().setSelectedProfileName(m_CurrentProfile->name());
connect(m_CurrentProfile, SIGNAL(modStatusChanged(uint)), this, SLOT(modStatusChanged(uint)));
connect(m_CurrentProfile, SIGNAL(modStatusChanged(QList)), this, SLOT(modStatusChanged(QList)));
@@ -776,22 +778,22 @@ QString OrganizerCore::profilePath() const
QString OrganizerCore::downloadsPath() const
{
- return QDir::fromNativeSeparators(m_Settings.getDownloadDirectory());
+ return QDir::fromNativeSeparators(m_Settings.paths().downloads());
}
QString OrganizerCore::overwritePath() const
{
- return QDir::fromNativeSeparators(m_Settings.getOverwriteDirectory());
+ return QDir::fromNativeSeparators(m_Settings.paths().overwrite());
}
QString OrganizerCore::basePath() const
{
- return QDir::fromNativeSeparators(m_Settings.getBaseDirectory());
+ return QDir::fromNativeSeparators(m_Settings.paths().base());
}
QString OrganizerCore::modsPath() const
{
- return QDir::fromNativeSeparators(m_Settings.getModDirectory());
+ return QDir::fromNativeSeparators(m_Settings.paths().mods());
}
MOBase::VersionInfo OrganizerCore::appVersion() const
@@ -821,10 +823,10 @@ MOBase::IModInterface *OrganizerCore::createMod(GuessedValue &name)
return nullptr;
}
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
+ m_InstallationManager.setModsDirectory(m_Settings.paths().mods());
QString targetDirectory
- = QDir::fromNativeSeparators(m_Settings.getModDirectory())
+ = QDir::fromNativeSeparators(m_Settings.paths().mods())
.append("/")
.append(name);
@@ -912,7 +914,7 @@ MOBase::IModInterface *OrganizerCore::installMod(const QString &fileName,
modName.update(initModName, GUESS_USER);
}
m_CurrentProfile->writeModlistNow();
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
+ m_InstallationManager.setModsDirectory(m_Settings.paths().mods());
if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) {
MessageDialog::showMessage(tr("Installation successful"),
qApp->activeWindow());
@@ -977,7 +979,7 @@ void OrganizerCore::installDownload(int index)
m_CurrentProfile->writeModlistNow();
bool hasIniTweaks = false;
- m_InstallationManager.setModsDirectory(m_Settings.getModDirectory());
+ m_InstallationManager.setModsDirectory(m_Settings.paths().mods());
if (m_InstallationManager.install(fileName, modName, hasIniTweaks)) {
MessageDialog::showMessage(tr("Installation successful"),
qApp->activeWindow());
@@ -1270,7 +1272,7 @@ bool OrganizerCore::previewFileWithAlternatives(
else {
// crude: we search for the next slash after the base mod directory to skip
// everything up to the data-relative directory
- int offset = settings().getModDirectory().size() + 1;
+ int offset = settings().paths().mods().size() + 1;
offset = fileName.indexOf("/", offset);
fileName = fileName.mid(offset + 1);
}
@@ -1412,7 +1414,7 @@ HANDLE OrganizerCore::spawnBinaryDirect(const QFileInfo &binary,
LPDWORD exitCode)
{
HANDLE processHandle = spawnBinaryProcess(binary, arguments, profileName, currentDirectory, steamAppID, customOverwrite, forcedLibraries);
- if (Settings::instance().lockGUI() && processHandle != INVALID_HANDLE_VALUE) {
+ if (Settings::instance().interface().lockGUI() && processHandle != INVALID_HANDLE_VALUE) {
std::unique_ptr dlg;
ILockedWaitingForProcess* uilock = nullptr;
@@ -1461,7 +1463,7 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary,
::SetEnvironmentVariableW(L"SteamAPPId", ToWString(steamAppID).c_str());
} else {
::SetEnvironmentVariableW(L"SteamAPPId",
- ToWString(m_Settings.getSteamAppID()).c_str());
+ ToWString(m_Settings.steam().appID()).c_str());
}
QWidget *window = qApp->activeWindow();
@@ -1477,7 +1479,7 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary,
|| QFileInfo(managedGame()->gameDirectory().absoluteFilePath(
"steam_api64.dll"))
.exists())
- && (m_Settings.getLoadMechanism() == LoadMechanism::LOAD_MODORGANIZER)) {
+ && (m_Settings.game().loadMechanismType() == LoadMechanism::LOAD_MODORGANIZER)) {
bool steamFound = true;
bool steamAccess = true;
@@ -1592,7 +1594,7 @@ HANDLE OrganizerCore::spawnBinaryProcess(const QFileInfo &binary,
}
}
- QString modsPath = settings().getModDirectory();
+ QString modsPath = settings().paths().mods();
// Check if this a request with either an executable or a working directory under our mods folder
// then will start the process in a virtualized "environment" with the appropriate paths fixed:
@@ -1749,7 +1751,7 @@ HANDLE OrganizerCore::startApplication(const QString &executable,
bool OrganizerCore::waitForApplication(HANDLE handle, LPDWORD exitCode)
{
- if (!Settings::instance().lockGUI())
+ if (!Settings::instance().interface().lockGUI())
return true;
ILockedWaitingForProcess* uilock = nullptr;
@@ -1960,8 +1962,10 @@ void OrganizerCore::refreshModList(bool saveChanges)
if (saveChanges) {
m_CurrentProfile->writeModlistNow(true);
}
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure,
- m_PluginContainer, m_Settings.displayForeign(), managedGame());
+
+ ModInfo::updateFromDisc(
+ m_Settings.paths().mods(), &m_DirectoryStructure,
+ m_PluginContainer, m_Settings.interface().displayForeign(), managedGame());
m_CurrentProfile->refreshModStatus();
@@ -2130,7 +2134,7 @@ void OrganizerCore::updateModsInDirectoryStructure(QMaparchivesWriter().writeImmediately(false);
@@ -2156,7 +2160,7 @@ void OrganizerCore::loggedInAction(QWidget* parent, std::function f)
f();
} else {
QString apiKey;
- if (settings().getNexusApiKey(apiKey)) {
+ if (settings().nexus().apiKey(apiKey)) {
doAfterLogin([f]{ f(); });
NexusInterface::instance(m_PluginContainer)->getAccessManager()->apiCheck(apiKey);
} else {
@@ -2295,8 +2299,10 @@ void OrganizerCore::profileRefresh()
{
// have to refresh mods twice (again in refreshModList), otherwise the refresh
// isn't complete. Not sure why
- ModInfo::updateFromDisc(m_Settings.getModDirectory(), &m_DirectoryStructure,
- m_PluginContainer, m_Settings.displayForeign(), managedGame());
+ ModInfo::updateFromDisc(
+ m_Settings.paths().mods(), &m_DirectoryStructure,
+ m_PluginContainer, m_Settings.interface().displayForeign(), managedGame());
+
m_CurrentProfile->refreshModStatus();
refreshModList();
@@ -2463,7 +2469,7 @@ void OrganizerCore::syncOverwrite()
SyncOverwriteDialog syncDialog(modInfo->absolutePath(), m_DirectoryStructure,
qApp->activeWindow());
if (syncDialog.exec() == QDialog::Accepted) {
- syncDialog.apply(QDir::fromNativeSeparators(m_Settings.getModDirectory()));
+ syncDialog.apply(QDir::fromNativeSeparators(m_Settings.paths().mods()));
modInfo->testValid();
refreshDirectoryStructure();
}
@@ -2486,7 +2492,7 @@ std::vector OrganizerCore::activeProblems() const
const auto& hookdll = oldMO1HookDll();
if (!hookdll.isEmpty()) {
// This warning will now be shown every time the problems are checked, which is a bit
- // of a "log spam". But since this is a sevre error which will most likely make the
+ // of a "log spam". But since this is a sever error which will most likely make the
// game crash/freeze/etc. and is very hard to diagnose, this "log spam" will make it
// easier for the user to notice the warning.
log::warn("hook.dll found in game folder: {}", hookdll);
@@ -2562,7 +2568,7 @@ void OrganizerCore::savePluginList()
}
m_PluginList.saveTo(m_CurrentProfile->getLockedOrderFileName(),
m_CurrentProfile->getDeleterFileName(),
- m_Settings.hideUncheckedPlugins());
+ m_Settings.game().hideUncheckedPlugins());
m_PluginList.saveLoadOrder(*m_DirectoryStructure);
}
@@ -2574,7 +2580,7 @@ void OrganizerCore::prepareStart()
m_CurrentProfile->writeModlist();
m_CurrentProfile->createTweakedIniFile();
saveCurrentLists();
- m_Settings.setupLoadMechanism();
+ m_Settings.game().setupLoadMechanism();
storeSettings();
}
@@ -2588,7 +2594,7 @@ std::vector OrganizerCore::fileMapping(const QString &profileName,
}
IPluginGame *game = qApp->property("managed_game").value();
- Profile profile(QDir(m_Settings.getProfileDirectory() + "/" + profileName),
+ Profile profile(QDir(m_Settings.paths().profiles() + "/" + profileName),
game);
MappingType result;
@@ -2634,7 +2640,7 @@ std::vector OrganizerCore::fileMapping(const QString &profileName,
}
result.insert(result.end(), {
- QDir::toNativeSeparators(m_Settings.getOverwriteDirectory()),
+ QDir::toNativeSeparators(m_Settings.paths().overwrite()),
dataPath,
true,
customOverwrite.isEmpty()
diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp
index ddfe492e..33423225 100644
--- a/src/pluginlist.cpp
+++ b/src/pluginlist.cpp
@@ -191,7 +191,7 @@ void PluginList::refresh(const QString &profileName
continue;
}
- bool forceEnabled = Settings::instance().forceEnableCoreFiles() &&
+ bool forceEnabled = Settings::instance().game().forceEnableCoreFiles() &&
primaryPlugins.contains(filename, Qt::CaseInsensitive);
//(std::find(primaryPlugins.begin(), primaryPlugins.end(), filename.toLower()) != primaryPlugins.end());
diff --git a/src/profile.cpp b/src/profile.cpp
index 7f4ebcaa..e76060b9 100644
--- a/src/profile.cpp
+++ b/src/profile.cpp
@@ -73,7 +73,7 @@ Profile::Profile(const QString &name, IPluginGame const *gamePlugin, bool useDef
: m_ModListWriter(std::bind(&Profile::doWriteModlist, this))
, m_GamePlugin(gamePlugin)
{
- QString profilesDir = Settings::instance().getProfileDirectory();
+ QString profilesDir = Settings::instance().paths().profiles();
QDir profileBase(profilesDir);
QString fixedName = name;
if (!fixDirectoryName(fixedName)) {
@@ -299,7 +299,7 @@ void Profile::createTweakedIniFile()
// static
void Profile::renameModInAllProfiles(const QString& oldName, const QString& newName)
{
- QDir profilesDir(Settings::instance().getProfileDirectory());
+ QDir profilesDir(Settings::instance().paths().profiles());
profilesDir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
QDirIterator profileIter(profilesDir);
while (profileIter.hasNext()) {
@@ -655,7 +655,7 @@ void Profile::setModPriority(unsigned int index, int &newPriority)
Profile *Profile::createPtrFrom(const QString &name, const Profile &reference, MOBase::IPluginGame const *gamePlugin)
{
- QString profileDirectory = Settings::instance().getProfileDirectory() + "/" + name;
+ QString profileDirectory = Settings::instance().paths().profiles() + "/" + name;
reference.copyFilesTo(profileDirectory);
return new Profile(QDir(profileDirectory), gamePlugin);
}
@@ -906,7 +906,7 @@ QString Profile::savePath() const
void Profile::rename(const QString &newName)
{
- QDir profileDir(Settings::instance().getProfileDirectory());
+ QDir profileDir(Settings::instance().paths().profiles());
profileDir.rename(name(), newName);
m_Directory.setPath(profileDir.absoluteFilePath(newName));
}
diff --git a/src/profilesdialog.cpp b/src/profilesdialog.cpp
index 2f1bd059..c91f48f4 100644
--- a/src/profilesdialog.cpp
+++ b/src/profilesdialog.cpp
@@ -57,7 +57,7 @@ ProfilesDialog::ProfilesDialog(const QString &profileName, MOBase::IPluginGame c
{
ui->setupUi(this);
- QDir profilesDir(Settings::instance().getProfileDirectory());
+ QDir profilesDir(Settings::instance().paths().profiles());
profilesDir.setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
QDirIterator profileIter(profilesDir);
@@ -203,7 +203,7 @@ void ProfilesDialog::on_removeProfileButton_clicked()
if (confirmBox.exec() == QMessageBox::Yes) {
QString profilePath;
if (profileToDelete.get() == nullptr) {
- profilePath = Settings::instance().getProfileDirectory()
+ profilePath = Settings::instance().paths().profiles()
+ "/" + ui->profilesList->currentItem()->text();
if (QMessageBox::question(this, tr("Profile broken"),
tr("This profile you're about to delete seems to be broken or the path is invalid. "
diff --git a/src/settings.cpp b/src/settings.cpp
index 71288950..8b063efb 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -150,7 +150,7 @@ std::optional getOptional(
template
T get(
const QSettings& settings,
- const QString& section, const QString& key, T def={})
+ const QString& section, const QString& key, T def)
{
if (auto v=getOptional(settings, section, key)) {
return *v;
@@ -453,22 +453,74 @@ void warnIfNotCheckable(const QAbstractButton* b)
}
+bool setWindowsCredential(const QString key, const QString data)
+{
+ QString finalKey("ModOrganizer2_" + key);
+ wchar_t* keyData = new wchar_t[finalKey.size()+1];
+ finalKey.toWCharArray(keyData);
+ keyData[finalKey.size()] = L'\0';
+ bool result = false;
+ if (data.isEmpty()) {
+ result = CredDeleteW(keyData, CRED_TYPE_GENERIC, 0);
+ if (!result)
+ if (GetLastError() == ERROR_NOT_FOUND)
+ result = true;
+ } else {
+ wchar_t* charData = new wchar_t[data.size()];
+ data.toWCharArray(charData);
+
+ CREDENTIALW cred = {};
+ cred.Flags = 0;
+ cred.Type = CRED_TYPE_GENERIC;
+ cred.TargetName = keyData;
+ cred.CredentialBlob = (LPBYTE)charData;
+ cred.CredentialBlobSize = sizeof(wchar_t) * data.size();
+ cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
+
+ result = CredWriteW(&cred, 0);
+ delete[] charData;
+ }
+ delete[] keyData;
+ return result;
+}
+
+QString getWindowsCredential(const QString key)
+{
+ QString result;
+ QString finalKey("ModOrganizer2_" + key);
+ wchar_t* keyData = new wchar_t[finalKey.size()+1];
+ finalKey.toWCharArray(keyData);
+ keyData[finalKey.size()] = L'\0';
+ PCREDENTIALW creds;
+ if (CredReadW(keyData, 1, 0, &creds)) {
+ wchar_t *charData = (wchar_t *)creds->CredentialBlob;
+ result = QString::fromWCharArray(charData, creds->CredentialBlobSize / sizeof(wchar_t));
+ CredFree(creds);
+ } else {
+ const auto e = GetLastError();
+ if (e != ERROR_NOT_FOUND) {
+ log::error("Retrieving encrypted data failed: {}", formatSystemMessage(e));
+ }
+ }
+ delete[] keyData;
+ return result;
+}
+
+
Settings *Settings::s_Instance = nullptr;
Settings::Settings(const QString& path) :
m_Settings(path, QSettings::IniFormat),
- m_Geometry(m_Settings), m_Colors(m_Settings), m_Plugins(m_Settings)
+ m_Game(m_Settings), m_Geometry(m_Settings), m_Widgets(m_Settings),
+ m_Colors(m_Settings), m_Plugins(m_Settings), m_Paths(m_Settings),
+ m_Network(m_Settings), m_Nexus(*this, m_Settings), m_Steam(*this, m_Settings),
+ m_Interface(m_Settings), m_Diagnostics(m_Settings)
{
if (s_Instance != nullptr) {
throw std::runtime_error("second instance of \"Settings\" created");
} else {
s_Instance = this;
}
-
- MOBase::QuestionBoxMemory::setCallbacks(
- [this](auto&& w, auto&& f){ return getQuestionButton(w, f); },
- [this](auto&& w, auto&& b){ setQuestionWindowButton(w, b); },
- [this](auto&& w, auto&& f, auto&& b){ setQuestionFileButton(w, f, b); });
}
Settings::~Settings()
@@ -488,7 +540,7 @@ Settings &Settings::instance()
void Settings::processUpdates(
const QVersionNumber& currentVersion, const QVersionNumber& lastVersion)
{
- if (getFirstStart()) {
+ if (firstStart()) {
return;
}
@@ -523,1569 +575,1670 @@ void Settings::processUpdates(
set(m_Settings, "General", "version", currentVersion.toString());
}
-QString Settings::getFilename() const
+QString Settings::filename() const
{
return m_Settings.fileName();
}
-void Settings::registerAsNXMHandler(bool force)
+bool Settings::usePrereleases() const
{
- const auto nxmPath = QCoreApplication::applicationDirPath() + "/nxmhandler.exe";
- const auto executable = QCoreApplication::applicationFilePath();
-
- QString mode = force ? "forcereg" : "reg";
- QString parameters = mode + " " + m_GamePlugin->gameShortName();
- for (const QString& altGame : m_GamePlugin->validShortNames()) {
- parameters += "," + altGame;
- }
- parameters += " \"" + executable + "\"";
-
- if (!shell::Execute(nxmPath, parameters)) {
- QMessageBox::critical(
- nullptr, tr("Failed"), tr("Failed to start the helper application"));
- }
+ return get(m_Settings, "Settings", "use_prereleases", false);
}
-bool Settings::colorSeparatorScrollbar() const
+void Settings::setUsePrereleases(bool b)
{
- return get(m_Settings, "Settings", "colorSeparatorScrollbars", true);
+ set(m_Settings, "Settings", "use_prereleases", b);
}
-void Settings::setColorSeparatorScrollbar(bool b)
+std::optional Settings::version() const
{
- set(m_Settings, "Settings", "colorSeparatorScrollbars", b);
+ if (auto v=getOptional(m_Settings, "General", "version")) {
+ return QVersionNumber::fromString(*v).normalized();
+ }
+
+ return {};
}
-void Settings::managedGameChanged(IPluginGame const *gamePlugin)
+bool Settings::firstStart() const
{
- m_GamePlugin = gamePlugin;
+ return get(m_Settings, "General", "first_start", true);
}
-bool Settings::obfuscate(const QString key, const QString data)
+void Settings::setFirstStart(bool b)
{
- QString finalKey("ModOrganizer2_" + key);
- wchar_t* keyData = new wchar_t[finalKey.size()+1];
- finalKey.toWCharArray(keyData);
- keyData[finalKey.size()] = L'\0';
- bool result = false;
- if (data.isEmpty()) {
- result = CredDeleteW(keyData, CRED_TYPE_GENERIC, 0);
- if (!result)
- if (GetLastError() == ERROR_NOT_FOUND)
- result = true;
- } else {
- wchar_t* charData = new wchar_t[data.size()];
- data.toWCharArray(charData);
+ set(m_Settings, "General", "first_start", b);
+}
- CREDENTIALW cred = {};
- cred.Flags = 0;
- cred.Type = CRED_TYPE_GENERIC;
- cred.TargetName = keyData;
- cred.CredentialBlob = (LPBYTE)charData;
- cred.CredentialBlobSize = sizeof(wchar_t) * data.size();
- cred.Persist = CRED_PERSIST_LOCAL_MACHINE;
+QString Settings::executablesBlacklist() const
+{
+ static const QString def = (QStringList()
+ << "Chrome.exe"
+ << "Firefox.exe"
+ << "TSVNCache.exe"
+ << "TGitCache.exe"
+ << "Steam.exe"
+ << "GameOverlayUI.exe"
+ << "Discord.exe"
+ << "GalaxyClient.exe"
+ << "Spotify.exe"
+ ).join(";");
- result = CredWriteW(&cred, 0);
- delete[] charData;
- }
- delete[] keyData;
- return result;
+ return get(m_Settings, "Settings", "executable_blacklist", def);
}
-QString Settings::deObfuscate(const QString key)
+void Settings::setExecutablesBlacklist(const QString& s)
{
- QString result;
- QString finalKey("ModOrganizer2_" + key);
- wchar_t* keyData = new wchar_t[finalKey.size()+1];
- finalKey.toWCharArray(keyData);
- keyData[finalKey.size()] = L'\0';
- PCREDENTIALW creds;
- if (CredReadW(keyData, 1, 0, &creds)) {
- wchar_t *charData = (wchar_t *)creds->CredentialBlob;
- result = QString::fromWCharArray(charData, creds->CredentialBlobSize / sizeof(wchar_t));
- CredFree(creds);
- } else {
- const auto e = GetLastError();
- if (e != ERROR_NOT_FOUND) {
- log::error("Retrieving encrypted data failed: {}", formatSystemMessage(e));
- }
- }
- delete[] keyData;
- return result;
+ set(m_Settings, "Settings", "executable_blacklist", s);
}
-QColor Settings::getIdealTextColor(const QColor& rBackgroundColor)
+void Settings::setMotdHash(uint hash)
{
- if (rBackgroundColor.alpha() == 0)
- return QColor(Qt::black);
-
- const int THRESHOLD = 106 * 255.0f / rBackgroundColor.alpha();
- int BackgroundDelta = (rBackgroundColor.red() * 0.299) + (rBackgroundColor.green() * 0.587) + (rBackgroundColor.blue() * 0.114);
- return QColor((255 - BackgroundDelta <= THRESHOLD) ? Qt::black : Qt::white);
+ set(m_Settings, "General", "motd_hash", hash);
}
-
-bool Settings::hideUncheckedPlugins() const
+unsigned int Settings::motdHash() const
{
- return get(m_Settings, "Settings", "hide_unchecked_plugins", false);
+ return get(m_Settings, "General", "motd_hash", 0);
}
-void Settings::setHideUncheckedPlugins(bool b)
+bool Settings::archiveParsing() const
{
- set(m_Settings, "Settings", "hide_unchecked_plugins", b);
+ return get(m_Settings, "Settings", "archive_parsing_experimental", false);
}
-bool Settings::forceEnableCoreFiles() const
+void Settings::setArchiveParsing(bool b)
{
- return get(m_Settings, "Settings", "force_enable_core_files", true);
+ set(m_Settings, "Settings", "archive_parsing_experimental", b);
}
-void Settings::setForceEnableCoreFiles(bool b)
+std::vector> Settings::executables() const
{
- set(m_Settings, "Settings", "force_enable_core_files", b);
+ ScopedReadArray sra(m_Settings, "customExecutables");
+ std::vector> v;
+
+ sra.for_each([&]{
+ std::map map;
+
+ for (auto&& key : sra.keys()) {
+ map[key] = m_Settings.value(key);
+ }
+
+ v.push_back(map);
+ });
+
+ return v;
}
-bool Settings::lockGUI() const
+void Settings::setExecutables(const std::vector>& v)
{
- return get(m_Settings, "Settings", "lock_gui", true);
+ removeSection(m_Settings, "customExecutables");
+
+ ScopedWriteArray swa(m_Settings, "customExecutables");
+
+ for (const auto& map : v) {
+ swa.next();
+
+ for (auto&& p : map) {
+ swa.set(p.first, p.second);
+ }
+ }
}
-void Settings::setLockGUI(bool b)
+bool Settings::keepBackupOnInstall() const
{
- set(m_Settings, "Settings", "lock_gui", b);
+ return get(m_Settings, "General", "backup_install", false);
}
-bool Settings::automaticLoginEnabled() const
+void Settings::setKeepBackupOnInstall(bool b)
{
- return get(m_Settings, "Settings", "nexus_login", false);
+ set(m_Settings, "General", "backup_install", b);
}
-QString Settings::getSteamAppID() const
+GameSettings& Settings::game()
{
- return get(m_Settings, "Settings", "app_id", m_GamePlugin->steamAPPId());
+ return m_Game;
}
-void Settings::setSteamAppID(const QString& id)
+const GameSettings& Settings::game() const
{
- if (id.isEmpty()) {
- remove(m_Settings, "Settings", "app_id");
- } else {
- set(m_Settings, "Settings", "app_id", id);
- }
+ return m_Game;
}
-bool Settings::usePrereleases() const
+GeometrySettings& Settings::geometry()
{
- return get(m_Settings, "Settings", "use_prereleases", false);
+ return m_Geometry;
}
-void Settings::setUsePrereleases(bool b)
+const GeometrySettings& Settings::geometry() const
{
- set(m_Settings, "Settings", "use_prereleases", b);
+ return m_Geometry;
}
-QString Settings::getConfigurablePath(const QString &key,
- const QString &def,
- bool resolve) const
+WidgetSettings& Settings::widgets()
{
- QString result = QDir::fromNativeSeparators(
- get(m_Settings, "Settings", key, QString("%BASE_DIR%/") + def));
-
- if (resolve) {
- result.replace("%BASE_DIR%", getBaseDirectory());
- }
-
- return result;
+ return m_Widgets;
}
-void Settings::setConfigurablePath(const QString &key, const QString& path)
+const WidgetSettings& Settings::widgets() const
{
- if (path.isEmpty()) {
- remove(m_Settings, "Settings", key);
- } else {
- set(m_Settings, "Settings", key, path);
- }
+ return m_Widgets;
}
-QString Settings::getBaseDirectory() const
+ColorSettings& Settings::colors()
{
- return QDir::fromNativeSeparators(get(m_Settings,
- "Settings", "base_directory", qApp->property("dataPath").toString()));
+ return m_Colors;
}
-QString Settings::getDownloadDirectory(bool resolve) const
+const ColorSettings& Settings::colors() const
{
- return getConfigurablePath(
- "download_directory",
- ToQString(AppConfig::downloadPath()),
- resolve);
+ return m_Colors;
}
-QString Settings::getCacheDirectory(bool resolve) const
+PluginSettings& Settings::plugins()
{
- return getConfigurablePath(
- "cache_directory",
- ToQString(AppConfig::cachePath()),
- resolve);
+ return m_Plugins;
}
-QString Settings::getModDirectory(bool resolve) const
+const PluginSettings& Settings::plugins() const
{
- return getConfigurablePath(
- "mod_directory",
- ToQString(AppConfig::modsPath()),
- resolve);
+ return m_Plugins;
}
-QString Settings::getProfileDirectory(bool resolve) const
+PathSettings& Settings::paths()
{
- return getConfigurablePath(
- "profiles_directory",
- ToQString(AppConfig::profilesPath()),
- resolve);
+ return m_Paths;
}
-QString Settings::getOverwriteDirectory(bool resolve) const
+const PathSettings& Settings::paths() const
{
- return getConfigurablePath(
- "overwrite_directory",
- ToQString(AppConfig::overwritePath()),
- resolve);
+ return m_Paths;
}
-void Settings::setBaseDirectory(const QString& path)
+NetworkSettings& Settings::network()
{
- if (path.isEmpty()) {
- remove(m_Settings, "Settings", "base_directory");
- } else {
- set(m_Settings, "Settings", "base_directory", path);
- }
+ return m_Network;
}
-void Settings::setDownloadDirectory(const QString& path)
+const NetworkSettings& Settings::network() const
{
- setConfigurablePath("download_directory", path);
+ return m_Network;
}
-void Settings::setModDirectory(const QString& path)
+NexusSettings& Settings::nexus()
{
- setConfigurablePath("mod_directory", path);
+ return m_Nexus;
}
-void Settings::setCacheDirectory(const QString& path)
+const NexusSettings& Settings::nexus() const
{
- setConfigurablePath("cache_directory", path);
+ return m_Nexus;
}
-void Settings::setProfileDirectory(const QString& path)
+SteamSettings& Settings::steam()
{
- setConfigurablePath("profiles_directory", path);
+ return m_Steam;
}
-void Settings::setOverwriteDirectory(const QString& path)
+const SteamSettings& Settings::steam() const
{
- setConfigurablePath("overwrite_directory", path);
+ return m_Steam;
}
-std::optional Settings::getManagedGameDirectory() const
+InterfaceSettings& Settings::interface()
{
- if (auto v=getOptional(m_Settings, "General", "gamePath")) {
- return QString::fromUtf8(*v);
- }
-
- return {};
+ return m_Interface;
}
-void Settings::setManagedGameDirectory(const QString& path)
+const InterfaceSettings& Settings::interface() const
{
- set(m_Settings, "General", "gamePath", QDir::toNativeSeparators(path).toUtf8());
+ return m_Interface;
}
-std::optional Settings::getManagedGameName() const
+DiagnosticsSettings& Settings::diagnostics()
{
- return getOptional(m_Settings, "General", "gameName");
+ return m_Diagnostics;
}
-void Settings::setManagedGameName(const QString& name)
+const DiagnosticsSettings& Settings::diagnostics() const
{
- set(m_Settings, "General", "gameName", name);
+ return m_Diagnostics;
}
-std::optional Settings::getManagedGameEdition() const
+QSettings::Status Settings::sync() const
{
- return getOptional(m_Settings, "General", "game_edition");
+ m_Settings.sync();
+ return m_Settings.status();
}
-void Settings::setManagedGameEdition(const QString& name)
+void Settings::dump() const
{
- set(m_Settings, "General", "game_edition", name);
-}
+ static const QStringList ignore({
+ "username", "password", "nexus_api_key"
+ });
-std::optional Settings::getSelectedProfileName() const
-{
- if (auto v=getOptional(m_Settings, "General", "selected_profile")) {
- return QString::fromUtf8(*v);
+ log::debug("settings:");
+
+ {
+ ScopedGroup sg(m_Settings, "Settings");
+
+ for (auto k : m_Settings.allKeys()) {
+ if (ignore.contains(k, Qt::CaseInsensitive)) {
+ continue;
+ }
+
+ log::debug(" . {}={}", k, m_Settings.value(k).toString());
+ }
}
- return {};
+ m_Network.dump();
}
-void Settings::setSelectedProfileName(const QString& name)
+void Settings::managedGameChanged(IPluginGame const *gamePlugin)
{
- set(m_Settings, "General", "selected_profile", name.toUtf8());
+ m_Game.setPlugin(gamePlugin);
}
-std::optional Settings::getStyleName() const
+
+GameSettings::GameSettings(QSettings& settings)
+ : m_Settings(settings), m_GamePlugin(nullptr)
{
- return getOptional(m_Settings, "Settings", "style");
}
-void Settings::setStyleName(const QString& name)
+const MOBase::IPluginGame* GameSettings::plugin()
{
- set(m_Settings, "Settings", "style", name);
+ return m_GamePlugin;
}
-bool Settings::getUseProxy() const
+void GameSettings::setPlugin(const MOBase::IPluginGame* gamePlugin)
{
- return get(m_Settings, "Settings", "use_proxy", false);
+ m_GamePlugin = gamePlugin;
}
-void Settings::setUseProxy(bool b)
+bool GameSettings::forceEnableCoreFiles() const
{
- set(m_Settings, "Settings", "use_proxy", b);
+ return get(m_Settings, "Settings", "force_enable_core_files", true);
}
-std::optional Settings::getVersion() const
+void GameSettings::setForceEnableCoreFiles(bool b)
{
- if (auto v=getOptional(m_Settings, "General", "version")) {
- return QVersionNumber::fromString(*v).normalized();
- }
-
- return {};
+ set(m_Settings, "Settings", "force_enable_core_files", b);
}
-bool Settings::getFirstStart() const
+std::optional GameSettings::directory() const
{
- return get(m_Settings, "General", "first_start", true);
+ if (auto v=getOptional(m_Settings, "General", "gamePath")) {
+ return QString::fromUtf8(*v);
+ }
+
+ return {};
}
-void Settings::setFirstStart(bool b)
+void GameSettings::setDirectory(const QString& path)
{
- set(m_Settings, "General", "first_start", b);
+ set(m_Settings, "General", "gamePath", QDir::toNativeSeparators(path).toUtf8());
}
-std::optional Settings::getPreviousSeparatorColor() const
+std::optional GameSettings::name() const
{
- const auto c = getOptional(m_Settings, "General", "previousSeparatorColor");
- if (c && c->isValid()) {
- return c;
- }
-
- return {};
+ return getOptional(m_Settings, "General", "gameName");
}
-void Settings::setPreviousSeparatorColor(const QColor& c) const
+void GameSettings::setName(const QString& name)
{
- set(m_Settings, "General", "previousSeparatorColor", c);
+ set(m_Settings, "General", "gameName", name);
}
-void Settings::removePreviousSeparatorColor()
+std::optional GameSettings::edition() const
{
- remove(m_Settings, "General", "previousSeparatorColor");
+ return getOptional(m_Settings, "General", "game_edition");
}
-bool Settings::getNexusApiKey(QString &apiKey) const
+void GameSettings::setEdition(const QString& name)
{
- QString tempKey = deObfuscate("APIKEY");
- if (tempKey.isEmpty())
- return false;
-
- apiKey = tempKey;
- return true;
+ set(m_Settings, "General", "game_edition", name);
}
-bool Settings::setNexusApiKey(const QString& apiKey)
+std::optional GameSettings::selectedProfileName() const
{
- if (!obfuscate("APIKEY", apiKey)) {
- const auto e = GetLastError();
- log::error("Storing API key failed: {}", formatSystemMessage(e));
- return false;
+ if (auto v=getOptional(m_Settings, "General", "selected_profile")) {
+ return QString::fromUtf8(*v);
}
- return true;
+ return {};
}
-bool Settings::clearNexusApiKey()
+void GameSettings::setSelectedProfileName(const QString& name)
{
- return setNexusApiKey("");
+ set(m_Settings, "General", "selected_profile", name.toUtf8());
}
-bool Settings::hasNexusApiKey() const
+LoadMechanism::EMechanism GameSettings::loadMechanismType() const
{
- return !deObfuscate("APIKEY").isEmpty();
-}
+ const auto def = LoadMechanism::LOAD_MODORGANIZER;
-bool Settings::getSteamLogin(QString &username, QString &password) const
-{
- username = get(m_Settings, "Settings", "steam_username", "");
- password = deObfuscate("steam_password");
+ const auto i = get(m_Settings,
+ "Settings", "load_mechanism", def);
- return !username.isEmpty() && !password.isEmpty();
-}
+ switch (i)
+ {
+ // ok
+ case LoadMechanism::LOAD_MODORGANIZER: // fall-through
+ {
+ break;
+ }
-bool Settings::compactDownloads() const
-{
- return get(m_Settings, "Settings", "compact_downloads", false);
-}
+ default:
+ {
+ log::error(
+ "invalid load mechanism {}, reverting to {}",
+ static_cast(i), toString(def));
-void Settings::setCompactDownloads(bool b)
-{
- set(m_Settings, "Settings", "compact_downloads", b);
-}
+ set(m_Settings, "Settings", "load_mechanism", def);
-bool Settings::metaDownloads() const
-{
- return get(m_Settings, "Settings", "meta_downloads", false);
-}
+ return def;
+ }
+ }
-void Settings::setMetaDownloads(bool b)
-{
- set(m_Settings, "Settings", "meta_downloads", b);
+ return i;
}
-bool Settings::offlineMode() const
+void GameSettings::setLoadMechanism(LoadMechanism::EMechanism m)
{
- return get(m_Settings, "Settings/offline_mode", false);
+ set(m_Settings, "Settings", "load_mechanism", m);
}
-void Settings::setOfflineMode(bool b)
+const LoadMechanism& GameSettings::loadMechanism() const
{
- set(m_Settings, "Settings", "offline_mode", b);
+ return m_LoadMechanism;
}
-log::Levels Settings::logLevel() const
+void GameSettings::setupLoadMechanism()
{
- return get(m_Settings, "Settings", "log_level", log::Levels::Info);
+ m_LoadMechanism.activate(loadMechanismType());
}
-void Settings::setLogLevel(log::Levels level)
+bool GameSettings::hideUncheckedPlugins() const
{
- set(m_Settings, "Settings", "log_level", level);
+ return get(m_Settings, "Settings", "hide_unchecked_plugins", false);
}
-CrashDumpsType Settings::crashDumpsType() const
+void GameSettings::setHideUncheckedPlugins(bool b)
{
- return get(m_Settings,
- "Settings", "crash_dumps_type", CrashDumpsType::Mini);
+ set(m_Settings, "Settings", "hide_unchecked_plugins", b);
}
-void Settings::setCrashDumpsType(CrashDumpsType type)
-{
- set(m_Settings, "Settings", "crash_dumps_type", type);
-}
-int Settings::crashDumpsMax() const
+GeometrySettings::GeometrySettings(QSettings& s)
+ : m_Settings(s), m_Reset(false)
{
- return get(m_Settings, "Settings", "crash_dumps_max", 5);
}
-void Settings::setCrashDumpsMax(int n)
+void GeometrySettings::requestReset()
{
- set(m_Settings, "Settings", "crash_dumps_max", n);
+ m_Reset = true;
}
-QString Settings::executablesBlacklist() const
+void GeometrySettings::resetIfNeeded()
{
- static const QString def = (QStringList()
- << "Chrome.exe"
- << "Firefox.exe"
- << "TSVNCache.exe"
- << "TGitCache.exe"
- << "Steam.exe"
- << "GameOverlayUI.exe"
- << "Discord.exe"
- << "GalaxyClient.exe"
- << "Spotify.exe"
- ).join(";");
+ if (!m_Reset) {
+ return;
+ }
- return get(m_Settings, "Settings", "executable_blacklist", def);
+ removeSection(m_Settings, "Geometry");
}
-void Settings::setExecutablesBlacklist(const QString& s)
+void GeometrySettings::saveGeometry(const QWidget* w)
{
- set(m_Settings, "Settings", "executable_blacklist", s);
+ set(m_Settings, "Geometry", geoSettingName(w), w->saveGeometry());
}
-void Settings::setSteamLogin(QString username, QString password)
+bool GeometrySettings::restoreGeometry(QWidget* w) const
{
- if (username == "") {
- remove(m_Settings, "Settings", "steam_username");
- password = "";
- } else {
- set(m_Settings, "Settings", "steam_username", username);
+ if (auto v=getOptional(m_Settings, "Geometry", geoSettingName(w))) {
+ w->restoreGeometry(*v);
+ return true;
}
- if (!obfuscate("steam_password", password)) {
- const auto e = GetLastError();
- log::error("Storing or deleting password failed: {}", formatSystemMessage(e));
- }
+ return false;
}
-LoadMechanism::EMechanism Settings::getLoadMechanism() const
+void GeometrySettings::saveState(const QMainWindow* w)
{
- const auto def = LoadMechanism::LOAD_MODORGANIZER;
-
- const auto i = get(m_Settings,
- "Settings", "load_mechanism", def);
-
- switch (i)
- {
- // ok
- case LoadMechanism::LOAD_MODORGANIZER: // fall-through
- {
- break;
- }
-
- default:
- {
- log::error(
- "invalid load mechanism {}, reverting to {}",
- static_cast(i), toString(def));
-
- set(m_Settings, "Settings", "load_mechanism", def);
-
- return def;
- }
- }
-
- return i;
+ set(m_Settings, "Geometry", stateSettingName(w), w->saveState());
}
-void Settings::setLoadMechanism(LoadMechanism::EMechanism m)
+bool GeometrySettings::restoreState(QMainWindow* w) const
{
- set(m_Settings, "Settings", "load_mechanism", m);
-}
+ if (auto v=getOptional(m_Settings, "Geometry", stateSettingName(w))) {
+ w->restoreState(*v);
+ return true;
+ }
-void Settings::setupLoadMechanism()
-{
- m_LoadMechanism.activate(getLoadMechanism());
+ return false;
}
-bool Settings::endorsementIntegration() const
+void GeometrySettings::saveState(const QHeaderView* w)
{
- return get(m_Settings, "Settings", "endorsement_integration", true);
+ set(m_Settings, "Geometry", stateSettingName(w), w->saveState());
}
-void Settings::setEndorsementIntegration(bool b) const
+bool GeometrySettings::restoreState(QHeaderView* w) const
{
- set(m_Settings, "Settings", "endorsement_integration", b);
+ if (auto v=getOptional(m_Settings, "Geometry", stateSettingName(w))) {
+ w->restoreState(*v);
+ return true;
+ }
+
+ return false;
}
-EndorsementState Settings::endorsementState() const
+void GeometrySettings::saveState(const QSplitter* w)
{
- return endorsementStateFromString(
- get(m_Settings, "General", "endorse_state", ""));
+ set(m_Settings, "Geometry", stateSettingName(w), w->saveState());
}
-void Settings::setEndorsementState(EndorsementState s)
+bool GeometrySettings::restoreState(QSplitter* w) const
{
- const auto v = toString(s);
-
- if (v.isEmpty()) {
- remove(m_Settings, "General", "endorse_state");
- } else {
- set(m_Settings, "General", "endorse_state", v);
+ if (auto v=getOptional(m_Settings, "Geometry", stateSettingName(w))) {
+ w->restoreState(*v);
+ return true;
}
-}
-bool Settings::hideAPICounter() const
-{
- return get(m_Settings, "Settings", "hide_api_counter", false);
+ return false;
}
-void Settings::setHideAPICounter(bool b)
+void GeometrySettings::saveState(const ExpanderWidget* expander)
{
- set(m_Settings, "Settings", "hide_api_counter", b);
+ set(m_Settings, "Geometry", stateSettingName(expander), expander->saveState());
}
-bool Settings::displayForeign() const
+bool GeometrySettings::restoreState(ExpanderWidget* expander) const
{
- return get(m_Settings, "Settings", "display_foreign", true);
-}
+ if (auto v=getOptional(m_Settings, "Geometry", stateSettingName(expander))) {
+ expander->restoreState(*v);
+ return true;
+ }
-void Settings::setDisplayForeign(bool b)
-{
- set(m_Settings, "Settings", "display_foreign", b);
+ return false;
}
-void Settings::setMotDHash(uint hash)
+void GeometrySettings::saveVisibility(const QWidget* w)
{
- set(m_Settings, "General", "motd_hash", hash);
+ set(m_Settings, "Geometry", visibilitySettingName(w), w->isVisible());
}
-unsigned int Settings::getMotDHash() const
+bool GeometrySettings::restoreVisibility(QWidget* w, std::optional def) const
{
- return get(m_Settings, "motd_hash", 0);
-}
+ if (auto v=getOptional(m_Settings, "Geometry", visibilitySettingName(w), def)) {
+ w->setVisible(*v);
+ return true;
+ }
-bool Settings::archiveParsing() const
-{
- return get(m_Settings, "Settings", "archive_parsing_experimental", false);
+ return false;
}
-void Settings::setArchiveParsing(bool b)
+void GeometrySettings::restoreToolbars(QMainWindow* w) const
{
- set(m_Settings, "Settings", "archive_parsing_experimental", b);
-}
+ // all toolbars have the same size and button style settings
+ const auto size = getOptional(m_Settings, "Geometry", "toolbar_size");
+ const auto style = getOptional(m_Settings, "Geometry", "toolbar_button_style");
-QString Settings::language()
+ for (auto* tb : w->findChildren()) {
+ if (size) {
+ tb->setIconSize(*size);
+ }
+
+ if (style) {
+ tb->setToolButtonStyle(static_cast(*style));
+ }
+
+ restoreVisibility(tb);
+ }
+}
+
+void GeometrySettings::saveToolbars(const QMainWindow* w)
{
- QString result = get(m_Settings, "Settings", "language", "");
+ const auto tbs = w->findChildren();
- if (result.isEmpty()) {
- QStringList languagePreferences = QLocale::system().uiLanguages();
+ // save visibility for all
+ for (auto* tb : tbs) {
+ saveVisibility(tb);
+ }
- if (languagePreferences.length() > 0) {
- // the users most favoritest language
- result = languagePreferences.at(0);
- } else {
- // fallback system locale
- result = QLocale::system().name();
+ // all toolbars have the same size and button style settings, just save the
+ // first one
+ if (!tbs.isEmpty()) {
+ const auto* tb = tbs[0];
+
+ set(m_Settings, "Geometry", "toolbar_size", tb->iconSize());
+ set(m_Settings, "Geometry", "toolbar_button_style", static_cast(tb->toolButtonStyle()));
+ }
+}
+
+QStringList GeometrySettings::modInfoTabOrder() const
+{
+ QStringList v;
+
+ if (m_Settings.contains("mod_info_tabs")) {
+ // old byte array from 2.2.0
+ QDataStream stream(m_Settings.value("mod_info_tabs").toByteArray());
+
+ int count = 0;
+ stream >> count;
+
+ for (int i=0; i> s;
+ v.push_back(s);
+ }
+ } else {
+ // string list since 2.2.1
+ QString string = m_Settings.value("mod_info_tab_order").toString();
+ QTextStream stream(&string);
+
+ while (!stream.atEnd()) {
+ QString s;
+ stream >> s;
+ v.push_back(s);
}
}
- return result;
+ return v;
}
-void Settings::setLanguage(const QString& name)
+void GeometrySettings::setModInfoTabOrder(const QString& names)
{
- set(m_Settings, "Settings", "language", name);
+ set(m_Settings, "Geometry", "mod_info_tab_order", names);
}
-void Settings::setDownloadSpeed(const QString& name, int bytesPerSecond)
+void GeometrySettings::centerOnMainWindowMonitor(QWidget* w)
{
- auto servers = getServers();
+ const auto monitor = getOptional(
+ m_Settings, "Geometry", "MainWindow_monitor");
- for (auto& server : servers) {
- if (server.name() == name) {
- server.addDownload(bytesPerSecond);
- updateServers(servers);
- return;
+ QPoint center;
+
+ if (monitor && QGuiApplication::screens().size() > *monitor) {
+ center = QGuiApplication::screens().at(*monitor)->geometry().center();
+ } else {
+ center = QGuiApplication::primaryScreen()->geometry().center();
+ }
+
+ w->move(center - w->rect().center());
+}
+
+void GeometrySettings::saveMainWindowMonitor(const QMainWindow* w)
+{
+ if (auto* handle=w->windowHandle()) {
+ if (auto* screen = handle->screen()) {
+ const int screenId = QGuiApplication::screens().indexOf(screen);
+ set(m_Settings, "Geometry", "MainWindow_monitor", screenId);
}
}
+}
- log::error(
- "server '{}' not found while trying to add a download with bps {}",
- name, bytesPerSecond);
+Qt::Orientation dockOrientation(const QMainWindow* mw, const QDockWidget* d)
+{
+ // docks in these areas are horizontal
+ const auto horizontalAreas =
+ Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea;
+
+ if (mw->dockWidgetArea(const_cast(d)) & horizontalAreas) {
+ return Qt::Horizontal;
+ } else {
+ return Qt::Vertical;
+ }
}
-ServerList Settings::getServers() const
+void GeometrySettings::saveDocks(const QMainWindow* mw)
{
- // servers used to be a map of byte arrays until 2.2.1, it's now an array of
- // individual values instead
+ // this attempts to fix https://bugreports.qt.io/browse/QTBUG-46620 where dock
+ // sizes are not restored when the main window is maximized; it is used in
+ // MainWindow::readSettings() and MainWindow::storeSettings()
+ //
+ // there's also https://stackoverflow.com/questions/44005852, which has what
+ // seems to be a popular fix, but it breaks the restored size of the window
+ // by setting it to the desktop's resolution, so that doesn't work
+ //
+ // the only fix I could find is to remember the sizes of the docks and manually
+ // setting them back; saving is straightforward, but restoring is messy
+ //
+ // this also depends on the window being visible before the timer in restore()
+ // is fired and the timer must be processed by application.exec(); therefore,
+ // the splash screen _must_ be closed before readSettings() is called, because
+ // it has its own event loop, which seems to interfere with this
+ //
+ // all of this should become unnecessary when QTBUG-46620 is fixed
//
- // so post 2.2.1, only one key is returned: "size", the size of the arrays;
- // in 2.2.1, one key per server is returned
- {
- const QStringList keys = ScopedGroup(m_Settings, "Servers").keys();
- if (!keys.empty() && keys[0] != "size") {
- // old format
- return getServersFromOldMap();
+ // saves the size of each dock
+ for (const auto* dock : mw->findChildren()) {
+ int size = 0;
+
+ // save the width for horizontal docks, or the height for vertical
+ if (dockOrientation(mw, dock) == Qt::Horizontal) {
+ size = dock->size().width();
+ } else {
+ size = dock->size().height();
}
+
+ set(m_Settings, "Geometry", dockSettingName(dock), size);
}
+}
+void GeometrySettings::restoreDocks(QMainWindow* mw) const
+{
+ struct DockInfo
+ {
+ QDockWidget* d;
+ int size = 0;
+ Qt::Orientation ori;
+ };
- // post 2.2.1 format, array of values
+ std::vector dockInfos;
- ServerList list;
+ // for each dock
+ for (auto* dock : mw->findChildren()) {
+ if (auto size=getOptional(m_Settings, "Geometry", dockSettingName(dock))) {
+ // remember this dock, its size and orientation
+ dockInfos.push_back({dock, *size, dockOrientation(mw, dock)});
+ }
+ }
- {
- ScopedReadArray sra(m_Settings, "Servers");
+ // the main window must have had time to process the settings from
+ // readSettings() or it seems to override whatever is set here
+ //
+ // some people said a single processEvents() call is enough, but it doesn't
+ // look like it
+ QTimer::singleShot(5, [=] {
+ for (const auto& info : dockInfos) {
+ mw->resizeDocks({info.d}, {info.size}, info.ori);
+ }
+ });
+}
- sra.for_each([&] {
- ServerInfo::SpeedList lastDownloads;
- const auto lastDownloadsString = sra.get("lastDownloads", "");
+WidgetSettings::WidgetSettings(QSettings& s)
+ : m_Settings(s)
+{
+ MOBase::QuestionBoxMemory::setCallbacks(
+ [this](auto&& w, auto&& f){ return questionButton(w, f); },
+ [this](auto&& w, auto&& b){ setQuestionWindowButton(w, b); },
+ [this](auto&& w, auto&& f, auto&& b){ setQuestionFileButton(w, f, b); });
+}
- for (const auto& s : lastDownloadsString.split(" ")) {
- const auto bytesPerSecond = s.toInt();
- if (bytesPerSecond > 0) {
- lastDownloads.push_back(bytesPerSecond);
- }
- }
+std::optional WidgetSettings::index(const QComboBox* cb) const
+{
+ return getOptional(m_Settings, "Widgets", indexSettingName(cb));
+}
- ServerInfo server(
- sra.get("name", ""),
- sra.get("premium", false),
- QDate::fromString(sra.get("lastSeen", ""), Qt::ISODate),
- sra.get("preferred", 0),
- lastDownloads);
+void WidgetSettings::saveIndex(const QComboBox* cb)
+{
+ set(m_Settings, "Widgets", indexSettingName(cb), cb->currentIndex());
+}
- list.add(std::move(server));
- });
+void WidgetSettings::restoreIndex(QComboBox* cb, std::optional def) const
+{
+ if (auto v=getOptional(m_Settings, "Widgets", indexSettingName(cb), def)) {
+ cb->setCurrentIndex(*v);
}
-
- return list;
}
-ServerList Settings::getServersFromOldMap() const
+std::optional WidgetSettings::index(const QTabWidget* w) const
{
- // for 2.2.1 and before
+ return getOptional(m_Settings, "Widgets", indexSettingName(w));
+}
- ServerList list;
- const ScopedGroup sg(m_Settings, "Servers");
+void WidgetSettings::saveIndex(const QTabWidget* w)
+{
+ set(m_Settings, "Widgets", indexSettingName(w), w->currentIndex());
+}
- sg.for_each([&](auto&& serverKey) {
- QVariantMap data = sg.get(serverKey);
+void WidgetSettings::restoreIndex(QTabWidget* w, std::optional def) const
+{
+ if (auto v=getOptional(m_Settings, "Widgets", indexSettingName(w), def)) {
+ w->setCurrentIndex(*v);
+ }
+}
- ServerInfo server(
- serverKey,
- data["premium"].toBool(),
- data["lastSeen"].toDate(),
- data["preferred"].toInt(),
- {});
+std::optional WidgetSettings::checked(const QAbstractButton* w) const
+{
+ warnIfNotCheckable(w);
+ return getOptional(m_Settings, "Widgets", checkedSettingName(w));
+}
- // ignoring download count and speed, it's now a list of values instead of
- // a total
+void WidgetSettings::saveChecked(const QAbstractButton* w)
+{
+ warnIfNotCheckable(w);
+ set(m_Settings, "Widgets", checkedSettingName(w), w->isChecked());
+}
- list.add(std::move(server));
- });
+void WidgetSettings::restoreChecked(QAbstractButton* w, std::optional def) const
+{
+ warnIfNotCheckable(w);
- return list;
+ if (auto v=getOptional(m_Settings, "Widgets", checkedSettingName(w), def)) {
+ w->setChecked(*v);
+ }
}
-void Settings::updateServers(ServerList servers)
+QuestionBoxMemory::Button WidgetSettings::questionButton(
+ const QString& windowName, const QString& filename) const
{
- // clean up unavailable servers
- servers.cleanup();
-
- removeSection(m_Settings, "Servers");
+ const QString sectionName("DialogChoices");
- {
- ScopedWriteArray swa(m_Settings, "Servers");
+ if (!filename.isEmpty()) {
+ const auto fileSetting = windowName + "/" + filename;
+ if (auto v=getOptional(m_Settings, sectionName, filename)) {
+ return static_cast(*v);
+ }
+ }
- for (const auto& server : servers) {
- swa.next();
+ if (auto v=getOptional(m_Settings, sectionName, windowName)) {
+ return static_cast(*v);
+ }
- swa.set("name", server.name());
- swa.set("premium", server.isPremium());
- swa.set("lastSeen", server.lastSeen().toString(Qt::ISODate));
- swa.set("preferred", server.preferred());
+ return QuestionBoxMemory::NoButton;
+}
- QString lastDownloads;
- for (const auto& speed : server.lastDownloads()) {
- if (speed > 0) {
- lastDownloads += QString("%1 ").arg(speed);
- }
- }
+void WidgetSettings::setQuestionWindowButton(
+ const QString& windowName, QuestionBoxMemory::Button button)
+{
+ const QString sectionName("DialogChoices");
- swa.set("lastDownloads", lastDownloads.trimmed());
- }
+ if (button == QuestionBoxMemory::NoButton) {
+ remove(m_Settings, sectionName, windowName);
+ } else {
+ set(m_Settings, sectionName, windowName, button);
}
}
-std::map Settings::getRecentDirectories() const
+void WidgetSettings::setQuestionFileButton(
+ const QString& windowName, const QString& filename,
+ QuestionBoxMemory::Button button)
{
- std::map map;
+ const QString sectionName("DialogChoices");
+ const QString settingName(windowName + "/" + filename);
- ScopedReadArray sra(m_Settings, "RecentDirectories");
+ if (button == QuestionBoxMemory::NoButton) {
+ remove(m_Settings, sectionName, settingName);
+ } else {
+ set(m_Settings, sectionName, settingName, button);
+ }
+}
- sra.for_each([&] {
- const QVariant name = sra.get("name");
- const QVariant dir = sra.get("directory");
+void WidgetSettings::resetQuestionButtons()
+{
+ removeSection(m_Settings, "DialogChoices");
+}
- if (name.isValid() && dir.isValid()) {
- map.emplace(name.toString(), dir.toString());
- }
- });
- return map;
+ColorSettings::ColorSettings(QSettings& s)
+ : m_Settings(s)
+{
}
-void Settings::setRecentDirectories(const std::map& map)
+QColor ColorSettings::modlistOverwrittenLoose() const
{
- removeSection(m_Settings, "RecentDirectories");
+ return get(
+ m_Settings, "Settings", "overwrittenLooseFilesColor",
+ QColor(0, 255, 0, 64));
+}
- ScopedWriteArray swa(m_Settings, "recentDirectories");
+void ColorSettings::setModlistOverwrittenLoose(const QColor& c)
+{
+ set(m_Settings, "Settings", "overwrittenLooseFilesColor", c);
+}
- for (auto&& p : map) {
- swa.next();
+QColor ColorSettings::modlistOverwritingLoose() const
+{
+ return get(
+ m_Settings, "Settings", "overwritingLooseFilesColor",
+ QColor(255, 0, 0, 64));
+}
- swa.set("name", p.first);
- swa.set("directory", p.second);
- }
+void ColorSettings::setModlistOverwritingLoose(const QColor& c)
+{
+ set(m_Settings, "Settings", "overwritingLooseFilesColor", c);
}
-std::vector> Settings::getExecutables() const
+QColor ColorSettings::modlistOverwrittenArchive() const
{
- ScopedReadArray sra(m_Settings, "customExecutables");
- std::vector> v;
+ return get(
+ m_Settings, "Settings", "overwrittenArchiveFilesColor",
+ QColor(0, 255, 255, 64));
+}
- sra.for_each([&]{
- std::map map;
+void ColorSettings::setModlistOverwrittenArchive(const QColor& c)
+{
+ set(m_Settings, "Settings", "overwrittenArchiveFilesColor", c);
+}
- for (auto&& key : sra.keys()) {
- map[key] = m_Settings.value(key);
- }
+QColor ColorSettings::modlistOverwritingArchive() const
+{
+ return get(
+ m_Settings, "Settings", "overwritingArchiveFilesColor",
+ QColor(255, 0, 255, 64));
+}
- v.push_back(map);
- });
+void ColorSettings::setModlistOverwritingArchive(const QColor& c)
+{
+ set(m_Settings, "Settings", "overwritingArchiveFilesColor", c);
+}
- return v;
+QColor ColorSettings::modlistContainsPlugin() const
+{
+ return get(
+ m_Settings, "Settings", "containsPluginColor",
+ QColor(0, 0, 255, 64));
}
-void Settings::setExecutables(const std::vector>& v)
+void ColorSettings::setModlistContainsPlugin(const QColor& c)
{
- removeSection(m_Settings, "customExecutables");
+ set(m_Settings, "Settings", "containsPluginColor", c);
+}
- ScopedWriteArray swa(m_Settings, "customExecutables");
+QColor ColorSettings::pluginListContained() const
+{
+ return get(
+ m_Settings, "Settings", "containedColor",
+ QColor(0, 0, 255, 64));
+}
- for (const auto& map : v) {
- swa.next();
+void ColorSettings::setPluginListContained(const QColor& c)
+{
+ set(m_Settings, "Settings", "containedColor", c);
+}
- for (auto&& p : map) {
- swa.set(p.first, p.second);
- }
+std::optional ColorSettings::previousSeparatorColor() const
+{
+ const auto c = getOptional(m_Settings, "General", "previousSeparatorColor");
+ if (c && c->isValid()) {
+ return c;
}
+
+ return {};
}
-bool Settings::isTutorialCompleted(const QString& windowName) const
+void ColorSettings::setPreviousSeparatorColor(const QColor& c) const
{
- return get(m_Settings, "CompletedWindowTutorials", windowName, false);
+ set(m_Settings, "General", "previousSeparatorColor", c);
}
-void Settings::setTutorialCompleted(const QString& windowName, bool b)
+void ColorSettings::removePreviousSeparatorColor()
{
- set(m_Settings, "CompletedWindowTutorials", windowName, b);
+ remove(m_Settings, "General", "previousSeparatorColor");
}
-bool Settings::keepBackupOnInstall() const
+bool ColorSettings::colorSeparatorScrollbar() const
{
- return get(m_Settings, "backup_install", false);
+ return get(m_Settings, "Settings", "colorSeparatorScrollbars", true);
}
-void Settings::setKeepBackupOnInstall(bool b)
+void ColorSettings::setColorSeparatorScrollbar(bool b)
{
- set(m_Settings, "General", "backup_install", b);
+ set(m_Settings, "Settings", "colorSeparatorScrollbars", b);
}
-QuestionBoxMemory::Button Settings::getQuestionButton(
- const QString& windowName, const QString& filename) const
+QColor ColorSettings::idealTextColor(const QColor& rBackgroundColor)
{
- const QString sectionName("DialogChoices");
+ if (rBackgroundColor.alpha() == 0)
+ return QColor(Qt::black);
- if (!filename.isEmpty()) {
- const auto fileSetting = windowName + "/" + filename;
- if (auto v=getOptional(m_Settings, sectionName, filename)) {
- return static_cast(*v);
+ const int THRESHOLD = 106 * 255.0f / rBackgroundColor.alpha();
+ int BackgroundDelta = (rBackgroundColor.red() * 0.299) + (rBackgroundColor.green() * 0.587) + (rBackgroundColor.blue() * 0.114);
+ return QColor((255 - BackgroundDelta <= THRESHOLD) ? Qt::black : Qt::white);
+}
+
+
+
+PluginSettings::PluginSettings(QSettings& settings)
+ : m_Settings(settings)
+{
+}
+
+void PluginSettings::clearPlugins()
+{
+ m_Plugins.clear();
+ m_PluginSettings.clear();
+
+ m_PluginBlacklist.clear();
+
+ ScopedReadArray sra(m_Settings, "pluginBlacklist");
+ sra.for_each([&]{
+ m_PluginBlacklist.insert(sra.get("name"));
+ });
+}
+
+void PluginSettings::registerPlugin(IPlugin *plugin)
+{
+ m_Plugins.push_back(plugin);
+ m_PluginSettings.insert(plugin->name(), QVariantMap());
+ m_PluginDescriptions.insert(plugin->name(), QVariantMap());
+
+ for (const PluginSetting &setting : plugin->settings()) {
+ const QString settingName = plugin->name() + "/" + setting.key;
+
+ QVariant temp = get(
+ m_Settings, "Plugins", settingName, setting.defaultValue);
+
+ if (!temp.convert(setting.defaultValue.type())) {
+ log::warn(
+ "failed to interpret \"{}\" as correct type for \"{}\" in plugin \"{}\", using default",
+ temp.toString(), setting.key, plugin->name());
+
+ temp = setting.defaultValue;
}
- }
- if (auto v=getOptional(m_Settings, sectionName, windowName)) {
- return static_cast(*v);
+ m_PluginSettings[plugin->name()][setting.key] = temp;
+
+ m_PluginDescriptions[plugin->name()][setting.key] = QString("%1 (default: %2)")
+ .arg(setting.description)
+ .arg(setting.defaultValue.toString());
}
+}
- return QuestionBoxMemory::NoButton;
+bool PluginSettings::pluginBlacklisted(const QString &fileName) const
+{
+ return m_PluginBlacklist.contains(fileName);
}
-void Settings::setQuestionWindowButton(
- const QString& windowName, QuestionBoxMemory::Button button)
+QVariant PluginSettings::pluginSetting(const QString &pluginName, const QString &key) const
{
- const QString sectionName("DialogChoices/");
+ auto iterPlugin = m_PluginSettings.find(pluginName);
+ if (iterPlugin == m_PluginSettings.end()) {
+ return QVariant();
+ }
- if (button == QuestionBoxMemory::NoButton) {
- remove(m_Settings, sectionName, windowName);
- } else {
- set(m_Settings, sectionName, windowName, button);
+ auto iterSetting = iterPlugin->find(key);
+ if (iterSetting == iterPlugin->end()) {
+ return QVariant();
}
+
+ return *iterSetting;
}
-void Settings::setQuestionFileButton(
- const QString& windowName, const QString& filename,
- QuestionBoxMemory::Button button)
+void PluginSettings::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value)
{
- const QString sectionName("DialogChoices");
- const QString settingName(windowName + "/" + filename);
+ auto iterPlugin = m_PluginSettings.find(pluginName);
- if (button == QuestionBoxMemory::NoButton) {
- remove(m_Settings, sectionName, settingName);
- } else {
- set(m_Settings, sectionName, settingName, button);
+ if (iterPlugin == m_PluginSettings.end()) {
+ throw MyException(
+ QObject::tr("attempt to store setting for unknown plugin \"%1\"")
+ .arg(pluginName));
}
+
+ // store the new setting both in memory and in the ini
+ m_PluginSettings[pluginName][key] = value;
+ set(m_Settings, "Plugins", pluginName + "/" + key, value);
}
-void Settings::resetQuestionButtons()
+QVariant PluginSettings::pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const
{
- removeSection(m_Settings, "DialogChoices");
+ if (!m_PluginSettings.contains(pluginName)) {
+ return def;
+ }
+
+ return get(m_Settings, "PluginPersistance", pluginName + "/" + key, def);
}
-std::optional Settings::getIndex(const QComboBox* cb) const
+void PluginSettings::setPluginPersistent(
+ const QString &pluginName, const QString &key, const QVariant &value, bool sync)
{
- return getOptional(m_Settings, "Widgets", indexSettingName(cb));
+ if (!m_PluginSettings.contains(pluginName)) {
+ throw MyException(
+ QObject::tr("attempt to store setting for unknown plugin \"%1\"")
+ .arg(pluginName));
+ }
+
+ set(m_Settings, "PluginPersistance", pluginName + "/" + key, value);
+
+ if (sync) {
+ m_Settings.sync();
+ }
}
-void Settings::saveIndex(const QComboBox* cb)
+void PluginSettings::addBlacklistPlugin(const QString &fileName)
{
- set(m_Settings, "Widgets", indexSettingName(cb), cb->currentIndex());
+ m_PluginBlacklist.insert(fileName);
+ writePluginBlacklist();
}
-void Settings::restoreIndex(QComboBox* cb, std::optional def) const
+void PluginSettings::writePluginBlacklist()
{
- if (auto v=getOptional(m_Settings, "Widgets", indexSettingName(cb), def)) {
- cb->setCurrentIndex(*v);
+ removeSection(m_Settings, "PluginBlacklist");
+
+ ScopedWriteArray swa(m_Settings, "PluginBlacklist");
+
+ for (const QString &plugin : m_PluginBlacklist) {
+ swa.next();
+ swa.set("name", plugin);
}
}
-std::optional Settings::getIndex(const QTabWidget* w) const
+QVariantMap PluginSettings::pluginSettings(const QString &pluginName) const
{
- return getOptional(m_Settings, "Widgets", indexSettingName(w));
+ return m_PluginSettings[pluginName];
}
-void Settings::saveIndex(const QTabWidget* w)
+void PluginSettings::setPluginSettings(const QString &pluginName, const QVariantMap& map)
{
- set(m_Settings, "Widgets", indexSettingName(w), w->currentIndex());
+ m_PluginSettings[pluginName] = map;
}
-void Settings::restoreIndex(QTabWidget* w, std::optional def) const
+QVariantMap PluginSettings::pluginDescriptions(const QString &pluginName) const
{
- if (auto v=getOptional(m_Settings, "Widgets", indexSettingName(w), def)) {
- w->setCurrentIndex(*v);
- }
+ return m_PluginDescriptions[pluginName];
}
-std::optional Settings::getChecked(const QAbstractButton* w) const
+void PluginSettings::pluginDescriptions(const QString &pluginName, const QVariantMap& map)
{
- warnIfNotCheckable(w);
- return getOptional(m_Settings, "Widgets", checkedSettingName(w));
+ m_PluginDescriptions[pluginName] = map;
}
-void Settings::saveChecked(const QAbstractButton* w)
+const QSet& PluginSettings::pluginBlacklist() const
{
- warnIfNotCheckable(w);
- set(m_Settings, "Widgets", checkedSettingName(w), w->isChecked());
+ return m_PluginBlacklist;
}
-void Settings::restoreChecked(QAbstractButton* w, std::optional def) const
+void PluginSettings::setPluginBlacklist(const QStringList& pluginNames)
{
- warnIfNotCheckable(w);
+ m_PluginBlacklist.clear();
- if (auto v=getOptional(m_Settings, "Widgets", checkedSettingName(w), def)) {
- w->setChecked(*v);
+ for (const auto& name : pluginNames) {
+ m_PluginBlacklist.insert(name);
}
}
-GeometrySettings& Settings::geometry()
+void PluginSettings::save()
{
- return m_Geometry;
-}
+ for (auto iterPlugins=m_PluginSettings.begin(); iterPlugins!=m_PluginSettings.end(); ++iterPlugins) {
+ for (auto iterSettings=iterPlugins->begin(); iterSettings!=iterPlugins->end(); ++iterSettings) {
+ const auto key = iterPlugins.key() + "/" + iterSettings.key();
+ set(m_Settings, "Plugins", key, iterSettings.value());
+ }
+ }
-const GeometrySettings& Settings::geometry() const
-{
- return m_Geometry;
+ writePluginBlacklist();
}
-ColorSettings& Settings::colors()
-{
- return m_Colors;
-}
-const ColorSettings& Settings::colors() const
+PathSettings::PathSettings(QSettings& settings)
+ : m_Settings(settings)
{
- return m_Colors;
}
-PluginSettings& Settings::plugins()
+std::map PathSettings::recent() const
{
- return m_Plugins;
-}
+ std::map map;
-const PluginSettings& Settings::plugins() const
-{
- return m_Plugins;
-}
+ ScopedReadArray sra(m_Settings, "RecentDirectories");
-QSettings::Status Settings::sync() const
-{
- m_Settings.sync();
- return m_Settings.status();
-}
+ sra.for_each([&] {
+ const QVariant name = sra.get("name");
+ const QVariant dir = sra.get("directory");
-void Settings::dump() const
-{
- static const QStringList ignore({
- "username", "password", "nexus_api_key"
+ if (name.isValid() && dir.isValid()) {
+ map.emplace(name.toString(), dir.toString());
+ }
});
- log::debug("settings:");
+ return map;
+}
- {
- ScopedGroup sg(m_Settings, "Settings");
+void PathSettings::setRecent(const std::map& map)
+{
+ removeSection(m_Settings, "RecentDirectories");
- for (auto k : m_Settings.allKeys()) {
- if (ignore.contains(k, Qt::CaseInsensitive)) {
- continue;
- }
+ ScopedWriteArray swa(m_Settings, "recentDirectories");
- log::debug(" . {}={}", k, m_Settings.value(k).toString());
- }
- }
+ for (auto&& p : map) {
+ swa.next();
- log::debug("servers:");
+ swa.set("name", p.first);
+ swa.set("directory", p.second);
+ }
+}
- for (const auto& server : getServers()) {
- QString lastDownloads;
- for (auto speed : server.lastDownloads()) {
- lastDownloads += QString("%1 ").arg(speed);
- }
+QString PathSettings::getConfigurablePath(const QString &key,
+ const QString &def,
+ bool resolve) const
+{
+ QString result = QDir::fromNativeSeparators(
+ get(m_Settings, "Settings", key, QString("%BASE_DIR%/") + def));
- log::debug(
- " . {} premium={} lastSeen={} preferred={} lastDownloads={}",
- server.name(),
- server.isPremium() ? "yes" : "no",
- server.lastSeen().toString(Qt::ISODate),
- server.preferred(),
- lastDownloads.trimmed());
+ if (resolve) {
+ result.replace("%BASE_DIR%", base());
}
-}
+ return result;
+}
-GeometrySettings::GeometrySettings(QSettings& s)
- : m_Settings(s), m_Reset(false)
+void PathSettings::setConfigurablePath(const QString &key, const QString& path)
{
+ if (path.isEmpty()) {
+ remove(m_Settings, "Settings", key);
+ } else {
+ set(m_Settings, "Settings", key, path);
+ }
}
-void GeometrySettings::requestReset()
+QString PathSettings::base() const
{
- m_Reset = true;
+ return QDir::fromNativeSeparators(get(m_Settings,
+ "Settings", "base_directory", qApp->property("dataPath").toString()));
}
-void GeometrySettings::resetIfNeeded()
+QString PathSettings::downloads(bool resolve) const
{
- if (!m_Reset) {
- return;
- }
-
- removeSection(m_Settings, "Geometry");
+ return getConfigurablePath(
+ "download_directory",
+ ToQString(AppConfig::downloadPath()),
+ resolve);
}
-void GeometrySettings::saveGeometry(const QWidget* w)
+QString PathSettings::cache(bool resolve) const
{
- set(m_Settings, "Geometry", geoSettingName(w), w->saveGeometry());
+ return getConfigurablePath(
+ "cache_directory",
+ ToQString(AppConfig::cachePath()),
+ resolve);
}
-bool GeometrySettings::restoreGeometry(QWidget* w) const
+QString PathSettings::mods(bool resolve) const
{
- if (auto v=getOptional(m_Settings, "Geometry", geoSettingName(w))) {
- w->restoreGeometry(*v);
- return true;
- }
+ return getConfigurablePath(
+ "mod_directory",
+ ToQString(AppConfig::modsPath()),
+ resolve);
+}
- return false;
+QString PathSettings::profiles(bool resolve) const
+{
+ return getConfigurablePath(
+ "profiles_directory",
+ ToQString(AppConfig::profilesPath()),
+ resolve);
}
-void GeometrySettings::saveState(const QMainWindow* w)
+QString PathSettings::overwrite(bool resolve) const
{
- set(m_Settings, "Geometry", stateSettingName(w), w->saveState());
+ return getConfigurablePath(
+ "overwrite_directory",
+ ToQString(AppConfig::overwritePath()),
+ resolve);
}
-bool GeometrySettings::restoreState(QMainWindow* w) const
+void PathSettings::setBase(const QString& path)
{
- if (auto v=getOptional(m_Settings, "Geometry", stateSettingName(w))) {
- w->restoreState(*v);
- return true;
+ if (path.isEmpty()) {
+ remove(m_Settings, "Settings", "base_directory");
+ } else {
+ set(m_Settings, "Settings", "base_directory", path);
}
-
- return false;
}
-void GeometrySettings::saveState(const QHeaderView* w)
+void PathSettings::setDownloads(const QString& path)
{
- set(m_Settings, "Geometry", stateSettingName(w), w->saveState());
+ setConfigurablePath("download_directory", path);
}
-bool GeometrySettings::restoreState(QHeaderView* w) const
+void PathSettings::setMods(const QString& path)
{
- if (auto v=getOptional(m_Settings, "Geometry", stateSettingName(w))) {
- w->restoreState(*v);
- return true;
- }
-
- return false;
+ setConfigurablePath("mod_directory", path);
}
-void GeometrySettings::saveState(const QSplitter* w)
+void PathSettings::setCache(const QString& path)
{
- set(m_Settings, "Geometry", stateSettingName(w), w->saveState());
+ setConfigurablePath("cache_directory", path);
}
-bool GeometrySettings::restoreState(QSplitter* w) const
+void PathSettings::setProfiles(const QString& path)
{
- if (auto v=getOptional(m_Settings, "Geometry", stateSettingName(w))) {
- w->restoreState(*v);
- return true;
- }
-
- return false;
+ setConfigurablePath("profiles_directory", path);
}
-void GeometrySettings::saveState(const ExpanderWidget* expander)
+void PathSettings::setOverwrite(const QString& path)
{
- set(m_Settings, "Geometry", stateSettingName(expander), expander->saveState());
+ setConfigurablePath("overwrite_directory", path);
}
-bool GeometrySettings::restoreState(ExpanderWidget* expander) const
-{
- if (auto v=getOptional(m_Settings, "Geometry", stateSettingName(expander))) {
- expander->restoreState(*v);
- return true;
- }
- return false;
+NetworkSettings::NetworkSettings(QSettings& settings)
+ : m_Settings(settings)
+{
}
-void GeometrySettings::saveVisibility(const QWidget* w)
+bool NetworkSettings::offlineMode() const
{
- set(m_Settings, "Geometry", visibilitySettingName(w), w->isVisible());
+ return get(m_Settings, "Settings", "offline_mode", false);
}
-bool GeometrySettings::restoreVisibility(QWidget* w, std::optional def) const
+void NetworkSettings::setOfflineMode(bool b)
{
- if (auto v=getOptional(m_Settings, "Geometry", visibilitySettingName(w), def)) {
- w->setVisible(*v);
- return true;
- }
+ set(m_Settings, "Settings", "offline_mode", b);
+}
- return false;
+bool NetworkSettings::useProxy() const
+{
+ return get(m_Settings, "Settings", "use_proxy", false);
}
-void GeometrySettings::restoreToolbars(QMainWindow* w) const
+void NetworkSettings::setUseProxy(bool b)
{
- // all toolbars have the same size and button style settings
- const auto size = getOptional(m_Settings, "Geometry", "toolbar_size");
- const auto style = getOptional(m_Settings, "Geometry", "toolbar_button_style");
+ set(m_Settings, "Settings", "use_proxy", b);
+}
- for (auto* tb : w->findChildren()) {
- if (size) {
- tb->setIconSize(*size);
- }
+void NetworkSettings::setDownloadSpeed(const QString& name, int bytesPerSecond)
+{
+ auto current = servers();
- if (style) {
- tb->setToolButtonStyle(static_cast(*style));
+ for (auto& server : current) {
+ if (server.name() == name) {
+ server.addDownload(bytesPerSecond);
+ updateServers(current);
+ return;
}
-
- restoreVisibility(tb);
}
+
+ log::error(
+ "server '{}' not found while trying to add a download with bps {}",
+ name, bytesPerSecond);
}
-void GeometrySettings::saveToolbars(const QMainWindow* w)
+ServerList NetworkSettings::servers() const
{
- const auto tbs = w->findChildren();
+ // servers used to be a map of byte arrays until 2.2.1, it's now an array of
+ // individual values instead
+ //
+ // so post 2.2.1, only one key is returned: "size", the size of the arrays;
+ // in 2.2.1, one key per server is returned
+ {
+ const QStringList keys = ScopedGroup(m_Settings, "Servers").keys();
- // save visibility for all
- for (auto* tb : tbs) {
- saveVisibility(tb);
+ if (!keys.empty() && keys[0] != "size") {
+ // old format
+ return serversFromOldMap();
+ }
}
- // all toolbars have the same size and button style settings, just save the
- // first one
- if (!tbs.isEmpty()) {
- const auto* tb = tbs[0];
- set(m_Settings, "Geometry", "toolbar_size", tb->iconSize());
- set(m_Settings, "Geometry", "toolbar_button_style", static_cast(tb->toolButtonStyle()));
- }
-}
+ // post 2.2.1 format, array of values
-QStringList GeometrySettings::getModInfoTabOrder() const
-{
- QStringList v;
+ ServerList list;
- if (m_Settings.contains("mod_info_tabs")) {
- // old byte array from 2.2.0
- QDataStream stream(m_Settings.value("mod_info_tabs").toByteArray());
+ {
+ ScopedReadArray sra(m_Settings, "Servers");
- int count = 0;
- stream >> count;
+ sra.for_each([&] {
+ ServerInfo::SpeedList lastDownloads;
- for (int i=0; i> s;
- v.push_back(s);
- }
- } else {
- // string list since 2.2.1
- QString string = m_Settings.value("mod_info_tab_order").toString();
- QTextStream stream(&string);
+ const auto lastDownloadsString = sra.get("lastDownloads", "");
- while (!stream.atEnd()) {
- QString s;
- stream >> s;
- v.push_back(s);
- }
+ for (const auto& s : lastDownloadsString.split(" ")) {
+ const auto bytesPerSecond = s.toInt();
+ if (bytesPerSecond > 0) {
+ lastDownloads.push_back(bytesPerSecond);
+ }
+ }
+
+ ServerInfo server(
+ sra.get("name", ""),
+ sra.get("premium", false),
+ QDate::fromString(sra.get("lastSeen", ""), Qt::ISODate),
+ sra.get("preferred", 0),
+ lastDownloads);
+
+ list.add(std::move(server));
+ });
}
- return v;
+ return list;
}
-void GeometrySettings::setModInfoTabOrder(const QString& names)
+ServerList NetworkSettings::serversFromOldMap() const
{
- set(m_Settings, "Geometry", "mod_info_tab_order", names);
-}
+ // for 2.2.1 and before
-void GeometrySettings::centerOnMainWindowMonitor(QWidget* w)
-{
- const auto monitor = getOptional(
- m_Settings, "Geometry", "MainWindow_monitor");
+ ServerList list;
+ const ScopedGroup sg(m_Settings, "Servers");
- QPoint center;
+ sg.for_each([&](auto&& serverKey) {
+ QVariantMap data = sg.get(serverKey);
- if (monitor && QGuiApplication::screens().size() > *monitor) {
- center = QGuiApplication::screens().at(*monitor)->geometry().center();
- } else {
- center = QGuiApplication::primaryScreen()->geometry().center();
- }
+ ServerInfo server(
+ serverKey,
+ data["premium"].toBool(),
+ data["lastSeen"].toDate(),
+ data["preferred"].toInt(),
+ {});
- w->move(center - w->rect().center());
-}
+ // ignoring download count and speed, it's now a list of values instead of
+ // a total
-void GeometrySettings::saveMainWindowMonitor(const QMainWindow* w)
-{
- if (auto* handle=w->windowHandle()) {
- if (auto* screen = handle->screen()) {
- const int screenId = QGuiApplication::screens().indexOf(screen);
- set(m_Settings, "Geometry", "MainWindow_monitor", screenId);
- }
- }
+ list.add(std::move(server));
+ });
+
+ return list;
}
-Qt::Orientation dockOrientation(const QMainWindow* mw, const QDockWidget* d)
+void NetworkSettings::updateServers(ServerList servers)
{
- // docks in these areas are horizontal
- const auto horizontalAreas =
- Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea;
+ // clean up unavailable servers
+ servers.cleanup();
- if (mw->dockWidgetArea(const_cast(d)) & horizontalAreas) {
- return Qt::Horizontal;
- } else {
- return Qt::Vertical;
- }
-}
+ removeSection(m_Settings, "Servers");
-void GeometrySettings::saveDocks(const QMainWindow* mw)
-{
- // this attempts to fix https://bugreports.qt.io/browse/QTBUG-46620 where dock
- // sizes are not restored when the main window is maximized; it is used in
- // MainWindow::readSettings() and MainWindow::storeSettings()
- //
- // there's also https://stackoverflow.com/questions/44005852, which has what
- // seems to be a popular fix, but it breaks the restored size of the window
- // by setting it to the desktop's resolution, so that doesn't work
- //
- // the only fix I could find is to remember the sizes of the docks and manually
- // setting them back; saving is straightforward, but restoring is messy
- //
- // this also depends on the window being visible before the timer in restore()
- // is fired and the timer must be processed by application.exec(); therefore,
- // the splash screen _must_ be closed before readSettings() is called, because
- // it has its own event loop, which seems to interfere with this
- //
- // all of this should become unnecessary when QTBUG-46620 is fixed
- //
+ {
+ ScopedWriteArray swa(m_Settings, "Servers");
- // saves the size of each dock
- for (const auto* dock : mw->findChildren()) {
- int size = 0;
+ for (const auto& server : servers) {
+ swa.next();
- // save the width for horizontal docks, or the height for vertical
- if (dockOrientation(mw, dock) == Qt::Horizontal) {
- size = dock->size().width();
- } else {
- size = dock->size().height();
- }
+ swa.set("name", server.name());
+ swa.set("premium", server.isPremium());
+ swa.set("lastSeen", server.lastSeen().toString(Qt::ISODate));
+ swa.set("preferred", server.preferred());
- set(m_Settings, "Geometry", dockSettingName(dock), size);
+ QString lastDownloads;
+ for (const auto& speed : server.lastDownloads()) {
+ if (speed > 0) {
+ lastDownloads += QString("%1 ").arg(speed);
+ }
+ }
+
+ swa.set("lastDownloads", lastDownloads.trimmed());
+ }
}
}
-void GeometrySettings::restoreDocks(QMainWindow* mw) const
+void NetworkSettings::dump() const
{
- struct DockInfo
- {
- QDockWidget* d;
- int size = 0;
- Qt::Orientation ori;
- };
-
- std::vector dockInfos;
+ log::debug("servers:");
- // for each dock
- for (auto* dock : mw->findChildren()) {
- if (auto size=getOptional(m_Settings, "Geometry", dockSettingName(dock))) {
- // remember this dock, its size and orientation
- dockInfos.push_back({dock, *size, dockOrientation(mw, dock)});
+ for (const auto& server : servers()) {
+ QString lastDownloads;
+ for (auto speed : server.lastDownloads()) {
+ lastDownloads += QString("%1 ").arg(speed);
}
- }
- // the main window must have had time to process the settings from
- // readSettings() or it seems to override whatever is set here
- //
- // some people said a single processEvents() call is enough, but it doesn't
- // look like it
- QTimer::singleShot(5, [=] {
- for (const auto& info : dockInfos) {
- mw->resizeDocks({info.d}, {info.size}, info.ori);
- }
- });
+ log::debug(
+ " . {} premium={} lastSeen={} preferred={} lastDownloads={}",
+ server.name(),
+ server.isPremium() ? "yes" : "no",
+ server.lastSeen().toString(Qt::ISODate),
+ server.preferred(),
+ lastDownloads.trimmed());
+ }
}
-ColorSettings::ColorSettings(QSettings& s)
- : m_Settings(s)
+NexusSettings::NexusSettings(Settings& parent, QSettings& settings)
+ : m_Parent(parent), m_Settings(settings)
{
}
-QColor ColorSettings::modlistOverwrittenLoose() const
+bool NexusSettings::automaticLoginEnabled() const
{
- return get(
- m_Settings, "Settings", "overwrittenLooseFilesColor",
- QColor(0, 255, 0, 64));
+ return get(m_Settings, "Settings", "nexus_login", false);
}
-void ColorSettings::setModlistOverwrittenLoose(const QColor& c)
+bool NexusSettings::apiKey(QString &apiKey) const
{
- set(m_Settings, "Settings", "overwrittenLooseFilesColor", c);
+ QString tempKey = getWindowsCredential("APIKEY");
+ if (tempKey.isEmpty())
+ return false;
+
+ apiKey = tempKey;
+ return true;
}
-QColor ColorSettings::modlistOverwritingLoose() const
+bool NexusSettings::setApiKey(const QString& apiKey)
{
- return get(
- m_Settings, "Settings", "overwritingLooseFilesColor",
- QColor(255, 0, 0, 64));
+ if (!setWindowsCredential("APIKEY", apiKey)) {
+ const auto e = GetLastError();
+ log::error("Storing API key failed: {}", formatSystemMessage(e));
+ return false;
+ }
+
+ return true;
}
-void ColorSettings::setModlistOverwritingLoose(const QColor& c)
+bool NexusSettings::clearApiKey()
{
- set(m_Settings, "Settings", "overwritingLooseFilesColor", c);
+ return setApiKey("");
}
-QColor ColorSettings::modlistOverwrittenArchive() const
+bool NexusSettings::hasApiKey() const
{
- return get(
- m_Settings, "Settings", "overwrittenArchiveFilesColor",
- QColor(0, 255, 255, 64));
+ return !getWindowsCredential("APIKEY").isEmpty();
}
-void ColorSettings::setModlistOverwrittenArchive(const QColor& c)
+bool NexusSettings::endorsementIntegration() const
{
- set(m_Settings, "Settings", "overwrittenArchiveFilesColor", c);
+ return get(m_Settings, "Settings", "endorsement_integration", true);
}
-QColor ColorSettings::modlistOverwritingArchive() const
+void NexusSettings::setEndorsementIntegration(bool b) const
{
- return get(
- m_Settings, "Settings", "overwritingArchiveFilesColor",
- QColor(255, 0, 255, 64));
+ set(m_Settings, "Settings", "endorsement_integration", b);
}
-void ColorSettings::setModlistOverwritingArchive(const QColor& c)
+EndorsementState NexusSettings::endorsementState() const
{
- set(m_Settings, "Settings", "overwritingArchiveFilesColor", c);
+ return endorsementStateFromString(
+ get(m_Settings, "General", "endorse_state", ""));
}
-QColor ColorSettings::modlistContainsPlugin() const
+void NexusSettings::setEndorsementState(EndorsementState s)
{
- return get(
- m_Settings, "Settings", "containsPluginColor",
- QColor(0, 0, 255, 64));
+ const auto v = toString(s);
+
+ if (v.isEmpty()) {
+ remove(m_Settings, "General", "endorse_state");
+ } else {
+ set(m_Settings, "General", "endorse_state", v);
+ }
}
-void ColorSettings::setModlistContainsPlugin(const QColor& c)
+void NexusSettings::registerAsNXMHandler(bool force)
{
- set(m_Settings, "Settings", "containsPluginColor", c);
+ const auto nxmPath = QCoreApplication::applicationDirPath() + "/nxmhandler.exe";
+ const auto executable = QCoreApplication::applicationFilePath();
+
+ QString mode = force ? "forcereg" : "reg";
+ QString parameters = mode + " " + m_Parent.game().plugin()->gameShortName();
+ for (const QString& altGame : m_Parent.game().plugin()->validShortNames()) {
+ parameters += "," + altGame;
+ }
+ parameters += " \"" + executable + "\"";
+
+ if (!shell::Execute(nxmPath, parameters)) {
+ QMessageBox::critical(
+ nullptr, QObject::tr("Failed"),
+ QObject::tr("Failed to start the helper application"));
+ }
}
-QColor ColorSettings::pluginListContained() const
+
+SteamSettings::SteamSettings(Settings& parent, QSettings& settings)
+ : m_Parent(parent), m_Settings(settings)
{
- return get(
- m_Settings, "Settings", "containedColor",
- QColor(0, 0, 255, 64));
}
-void ColorSettings::setPluginListContained(const QColor& c)
+QString SteamSettings::appID() const
{
- set(m_Settings, "Settings", "containedColor", c);
+ return get(
+ m_Settings, "Settings", "app_id", m_Parent.game().plugin()->steamAPPId());
}
-
-PluginSettings::PluginSettings(QSettings& settings)
- : m_Settings(settings)
+void SteamSettings::setAppID(const QString& id)
{
+ if (id.isEmpty()) {
+ remove(m_Settings, "Settings", "app_id");
+ } else {
+ set(m_Settings, "Settings", "app_id", id);
+ }
}
-void PluginSettings::clearPlugins()
+bool SteamSettings::login(QString &username, QString &password) const
{
- m_Plugins.clear();
- m_PluginSettings.clear();
-
- m_PluginBlacklist.clear();
+ username = get(m_Settings, "Settings", "steam_username", "");
+ password = getWindowsCredential("steam_password");
- ScopedReadArray sra(m_Settings, "pluginBlacklist");
- sra.for_each([&]{
- m_PluginBlacklist.insert(sra.get("name"));
- });
+ return !username.isEmpty() && !password.isEmpty();
}
-void PluginSettings::registerPlugin(IPlugin *plugin)
+void SteamSettings::setLogin(QString username, QString password)
{
- m_Plugins.push_back(plugin);
- m_PluginSettings.insert(plugin->name(), QVariantMap());
- m_PluginDescriptions.insert(plugin->name(), QVariantMap());
+ if (username == "") {
+ remove(m_Settings, "Settings", "steam_username");
+ password = "";
+ } else {
+ set(m_Settings, "Settings", "steam_username", username);
+ }
- for (const PluginSetting &setting : plugin->settings()) {
- const QString settingName = plugin->name() + "/" + setting.key;
+ if (!setWindowsCredential("steam_password", password)) {
+ const auto e = GetLastError();
+ log::error("Storing or deleting password failed: {}", formatSystemMessage(e));
+ }
+}
- QVariant temp = get(
- m_Settings, "Plugins", settingName, setting.defaultValue);
- if (!temp.convert(setting.defaultValue.type())) {
- log::warn(
- "failed to interpret \"{}\" as correct type for \"{}\" in plugin \"{}\", using default",
- temp.toString(), setting.key, plugin->name());
+InterfaceSettings::InterfaceSettings(QSettings& settings)
+ : m_Settings(settings)
+{
+}
- temp = setting.defaultValue;
- }
+bool InterfaceSettings::lockGUI() const
+{
+ return get(m_Settings, "Settings", "lock_gui", true);
+}
- m_PluginSettings[plugin->name()][setting.key] = temp;
+void InterfaceSettings::setLockGUI(bool b)
+{
+ set(m_Settings, "Settings", "lock_gui", b);
+}
- m_PluginDescriptions[plugin->name()][setting.key] = QString("%1 (default: %2)")
- .arg(setting.description)
- .arg(setting.defaultValue.toString());
- }
+std::optional InterfaceSettings::styleName() const
+{
+ return getOptional(m_Settings, "Settings", "style");
}
-bool PluginSettings::pluginBlacklisted(const QString &fileName) const
+void InterfaceSettings::setStyleName(const QString& name)
{
- return m_PluginBlacklist.contains(fileName);
+ set(m_Settings, "Settings", "style", name);
}
-QVariant PluginSettings::pluginSetting(const QString &pluginName, const QString &key) const
+bool InterfaceSettings::compactDownloads() const
{
- auto iterPlugin = m_PluginSettings.find(pluginName);
- if (iterPlugin == m_PluginSettings.end()) {
- return QVariant();
- }
+ return get(m_Settings, "Settings", "compact_downloads", false);
+}
- auto iterSetting = iterPlugin->find(key);
- if (iterSetting == iterPlugin->end()) {
- return QVariant();
- }
+void InterfaceSettings::setCompactDownloads(bool b)
+{
+ set(m_Settings, "Settings", "compact_downloads", b);
+}
- return *iterSetting;
+bool InterfaceSettings::metaDownloads() const
+{
+ return get(m_Settings, "Settings", "meta_downloads", false);
}
-void PluginSettings::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value)
+void InterfaceSettings::setMetaDownloads(bool b)
{
- auto iterPlugin = m_PluginSettings.find(pluginName);
+ set(m_Settings, "Settings", "meta_downloads", b);
+}
- if (iterPlugin == m_PluginSettings.end()) {
- throw MyException(
- QObject::tr("attempt to store setting for unknown plugin \"%1\"")
- .arg(pluginName));
- }
+bool InterfaceSettings::hideAPICounter() const
+{
+ return get(m_Settings, "Settings", "hide_api_counter", false);
+}
- // store the new setting both in memory and in the ini
- m_PluginSettings[pluginName][key] = value;
- set(m_Settings, "Plugins", pluginName + "/" + key, value);
+void InterfaceSettings::setHideAPICounter(bool b)
+{
+ set(m_Settings, "Settings", "hide_api_counter", b);
}
-QVariant PluginSettings::pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const
+bool InterfaceSettings::displayForeign() const
{
- if (!m_PluginSettings.contains(pluginName)) {
- return def;
- }
+ return get(m_Settings, "Settings", "display_foreign", true);
+}
- return get(m_Settings, "PluginPersistance", pluginName + "/" + key, def);
+void InterfaceSettings::setDisplayForeign(bool b)
+{
+ set(m_Settings, "Settings", "display_foreign", b);
}
-void PluginSettings::setPluginPersistent(
- const QString &pluginName, const QString &key, const QVariant &value, bool sync)
+QString InterfaceSettings::language()
{
- if (!m_PluginSettings.contains(pluginName)) {
- throw MyException(
- QObject::tr("attempt to store setting for unknown plugin \"%1\"")
- .arg(pluginName));
- }
+ QString result = get(m_Settings, "Settings", "language", "");
- set(m_Settings, "PluginPersistance", pluginName + "/" + key, value);
+ if (result.isEmpty()) {
+ QStringList languagePreferences = QLocale::system().uiLanguages();
- if (sync) {
- m_Settings.sync();
+ if (languagePreferences.length() > 0) {
+ // the users most favoritest language
+ result = languagePreferences.at(0);
+ } else {
+ // fallback system locale
+ result = QLocale::system().name();
+ }
}
+
+ return result;
}
-void PluginSettings::addBlacklistPlugin(const QString &fileName)
+void InterfaceSettings::setLanguage(const QString& name)
{
- m_PluginBlacklist.insert(fileName);
- writePluginBlacklist();
+ set(m_Settings, "Settings", "language", name);
}
-void PluginSettings::writePluginBlacklist()
+bool InterfaceSettings::isTutorialCompleted(const QString& windowName) const
{
- removeSection(m_Settings, "PluginBlacklist");
-
- ScopedWriteArray swa(m_Settings, "PluginBlacklist");
-
- for (const QString &plugin : m_PluginBlacklist) {
- swa.next();
- swa.set("name", plugin);
- }
+ return get(m_Settings, "CompletedWindowTutorials", windowName, false);
}
-QVariantMap PluginSettings::pluginSettings(const QString &pluginName) const
+void InterfaceSettings::setTutorialCompleted(const QString& windowName, bool b)
{
- return m_PluginSettings[pluginName];
+ set(m_Settings, "CompletedWindowTutorials", windowName, b);
}
-void PluginSettings::setPluginSettings(const QString &pluginName, const QVariantMap& map)
+
+DiagnosticsSettings::DiagnosticsSettings(QSettings& settings)
+ : m_Settings(settings)
{
- m_PluginSettings[pluginName] = map;
}
-QVariantMap PluginSettings::pluginDescriptions(const QString &pluginName) const
+log::Levels DiagnosticsSettings::logLevel() const
{
- return m_PluginDescriptions[pluginName];
+ return get(m_Settings, "Settings", "log_level", log::Levels::Info);
}
-void PluginSettings::pluginDescriptions(const QString &pluginName, const QVariantMap& map)
+void DiagnosticsSettings::setLogLevel(log::Levels level)
{
- m_PluginDescriptions[pluginName] = map;
+ set(m_Settings, "Settings", "log_level", level);
}
-const QSet& PluginSettings::pluginBlacklist() const
+CrashDumpsType DiagnosticsSettings::crashDumpsType() const
{
- return m_PluginBlacklist;
+ return get(m_Settings,
+ "Settings", "crash_dumps_type", CrashDumpsType::Mini);
}
-void PluginSettings::setPluginBlacklist(const QStringList& pluginNames)
+void DiagnosticsSettings::setCrashDumpsType(CrashDumpsType type)
{
- m_PluginBlacklist.clear();
-
- for (const auto& name : pluginNames) {
- m_PluginBlacklist.insert(name);
- }
+ set(m_Settings, "Settings", "crash_dumps_type", type);
}
-void PluginSettings::save()
+int DiagnosticsSettings::crashDumpsMax() const
{
- for (auto iterPlugins=m_PluginSettings.begin(); iterPlugins!=m_PluginSettings.end(); ++iterPlugins) {
- for (auto iterSettings=iterPlugins->begin(); iterSettings!=iterPlugins->end(); ++iterSettings) {
- const auto key = iterPlugins.key() + "/" + iterSettings.key();
- set(m_Settings, "Plugins", key, iterSettings.value());
- }
- }
+ return get(m_Settings, "Settings", "crash_dumps_max", 5);
+}
- writePluginBlacklist();
+void DiagnosticsSettings::setCrashDumpsMax(int n)
+{
+ set(m_Settings, "Settings", "crash_dumps_max", n);
}
diff --git a/src/settings.h b/src/settings.h
index 403c2d71..5c0a2542 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -25,6 +25,10 @@ along with Mod Organizer. If not, see .
#include
#include
+#ifdef interface
+ #undef interface
+#endif
+
namespace MOBase {
class IPlugin;
class IPluginGame;
@@ -50,6 +54,58 @@ private:
};
+class GameSettings
+{
+public:
+ GameSettings(QSettings& setting);
+
+ const MOBase::IPluginGame* plugin();
+ void setPlugin(const MOBase::IPluginGame* gamePlugin);
+
+ /**
+ * whether files of the core game are forced-enabled so the user can't
+ * accidentally disable them
+ */
+ bool forceEnableCoreFiles() const;
+ void setForceEnableCoreFiles(bool b);
+
+ /**
+ * the directory where the managed game is stored (with native separators)
+ **/
+ std::optional directory() const;
+ void setDirectory(const QString& path);
+
+ std::optional name() const;
+ void setName(const QString& name);
+
+ std::optional edition() const;
+ void setEdition(const QString& name);
+
+ std::optional selectedProfileName() const;
+ void setSelectedProfileName(const QString& name);
+
+ /**
+ * @return the load mechanism to be used
+ **/
+ LoadMechanism::EMechanism loadMechanismType() const;
+ void setLoadMechanism(LoadMechanism::EMechanism m);
+ const LoadMechanism& loadMechanism() const;
+ void setupLoadMechanism();
+
+ /**
+ * @return true if the user wants unchecked plugins (esp, esm) should be hidden from
+ * the virtual data directory
+ **/
+ bool hideUncheckedPlugins() const;
+ void setHideUncheckedPlugins(bool b);
+
+private:
+ QSettings& m_Settings;
+ const MOBase::IPluginGame* m_GamePlugin;
+ LoadMechanism m_LoadMechanism;
+};
+
+
class GeometrySettings
{
public:
@@ -83,7 +139,7 @@ public:
void saveDocks(const QMainWindow* w);
void restoreDocks(QMainWindow* w) const;
- QStringList getModInfoTabOrder() const;
+ QStringList modInfoTabOrder() const;
void setModInfoTabOrder(const QString& names);
void centerOnMainWindowMonitor(QWidget* w);
@@ -95,6 +151,40 @@ private:
};
+class WidgetSettings
+{
+public:
+ WidgetSettings(QSettings& s);
+
+ std::optional