From ea6292168a6acd4c263913f0ccd7dd64daf4f5cf Mon Sep 17 00:00:00 2001 From: Sandro Jäckel Date: Fri, 23 Feb 2018 01:45:58 +0100 Subject: Revert "Applied clang-format on source" This reverts commit 5e5c9c07291f6b09623d31c92b1fb61c4ede576e. --- src/settings.cpp | 1491 +++++++++++++++++++++++++++++------------------------- 1 file changed, 809 insertions(+), 682 deletions(-) (limited to 'src/settings.cpp') diff --git a/src/settings.cpp b/src/settings.cpp index 2694c59a..d1130e05 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -19,38 +19,39 @@ along with Mod Organizer. If not, see . #include "settings.h" -#include "appconfig.h" -#include "organizercore.h" #include "pluginsetting.h" #include "serverinfo.h" #include "settingsdialog.h" #include "versioninfo.h" +#include "appconfig.h" +#include "organizercore.h" +#include #include #include #include #include -#include -#include #include -#include #include +#include #include #include #include #include #include -#include #include +#include #include #include #include +#include #include -#include +#include #include #include +#include -#include // for Qt::UserRole, etc +#include // for Qt::UserRole, etc #include // for qDebug, qWarning #include // For ShellExecuteW, HINSTANCE, etc @@ -66,808 +67,934 @@ using namespace MOBase; template class QListWidgetItemEx : public QListWidgetItem { public: - QListWidgetItemEx(const QString& text, int sortRole = Qt::DisplayRole, QListWidget* parent = 0, int type = Type) - : QListWidgetItem(text, parent, type), m_SortRole(sortRole) {} - - virtual bool operator<(const QListWidgetItem& other) const { - return this->data(m_SortRole).value() < other.data(m_SortRole).value(); - } + QListWidgetItemEx(const QString &text, int sortRole = Qt::DisplayRole, QListWidget *parent = 0, int type = Type) + : QListWidgetItem(text, parent, type), m_SortRole(sortRole) {} + virtual bool operator< ( const QListWidgetItem & other ) const { + return this->data(m_SortRole).value() < other.data(m_SortRole).value(); + } private: - int m_SortRole; + int m_SortRole; }; -static const unsigned char Key2[20] = {0x99, 0xb8, 0x76, 0x42, 0x3e, 0xc1, 0x60, 0xa4, 0x5b, 0x01, - 0xdb, 0xf8, 0x43, 0x3a, 0xb7, 0xb6, 0x98, 0xd4, 0x7d, 0xa2}; -Settings* Settings::s_Instance = nullptr; +static const unsigned char Key2[20] = { 0x99, 0xb8, 0x76, 0x42, 0x3e, 0xc1, 0x60, 0xa4, 0x5b, 0x01, + 0xdb, 0xf8, 0x43, 0x3a, 0xb7, 0xb6, 0x98, 0xd4, 0x7d, 0xa2 }; -Settings::Settings(const QSettings& settingsSource) : m_Settings(settingsSource.fileName(), settingsSource.format()) { - if (s_Instance != nullptr) { - throw std::runtime_error("second instance of \"Settings\" created"); - } else { - s_Instance = this; - } -} +Settings *Settings::s_Instance = nullptr; -Settings::~Settings() { s_Instance = nullptr; } -Settings& Settings::instance() { - if (s_Instance == nullptr) { - throw std::runtime_error("no instance of \"Settings\""); - } - return *s_Instance; +Settings::Settings(const QSettings &settingsSource) + : m_Settings(settingsSource.fileName(), settingsSource.format()) +{ + if (s_Instance != nullptr) { + throw std::runtime_error("second instance of \"Settings\" created"); + } else { + s_Instance = this; + } } -void Settings::clearPlugins() { - m_Plugins.clear(); - m_PluginSettings.clear(); - m_PluginBlacklist.clear(); - int count = m_Settings.beginReadArray("pluginBlacklist"); - for (int i = 0; i < count; ++i) { - m_Settings.setArrayIndex(i); - m_PluginBlacklist.insert(m_Settings.value("name").toString()); - } - m_Settings.endArray(); +Settings::~Settings() +{ + s_Instance = nullptr; } -bool Settings::pluginBlacklisted(const QString& fileName) const { return m_PluginBlacklist.contains(fileName); } -void Settings::registerAsNXMHandler(bool force) { - std::wstring nxmPath = ToWString(QCoreApplication::applicationDirPath() + "/nxmhandler.exe"); - std::wstring executable = ToWString(QCoreApplication::applicationFilePath()); - std::wstring mode = force ? L"forcereg" : L"reg"; - std::wstring parameters = mode + L" " + m_GamePlugin->gameShortName().toStdWString() + L" \"" + executable + L"\""; - HINSTANCE res = ::ShellExecuteW(nullptr, L"open", nxmPath.c_str(), parameters.c_str(), nullptr, SW_SHOWNORMAL); - if ((int)res <= 32) { - QMessageBox::critical(nullptr, tr("Failed"), tr("Sorry, failed to start the helper application")); - } +Settings &Settings::instance() +{ + if (s_Instance == nullptr) { + throw std::runtime_error("no instance of \"Settings\""); + } + return *s_Instance; } -void Settings::managedGameChanged(IPluginGame const* gamePlugin) { m_GamePlugin = gamePlugin; } +void Settings::clearPlugins() +{ + m_Plugins.clear(); + m_PluginSettings.clear(); -void Settings::registerPlugin(IPlugin* plugin) { - m_Plugins.push_back(plugin); - m_PluginSettings.insert(plugin->name(), QMap()); - m_PluginDescriptions.insert(plugin->name(), QMap()); - for (const PluginSetting& setting : plugin->settings()) { - QVariant temp = m_Settings.value("Plugins/" + plugin->name() + "/" + setting.key, setting.defaultValue); - if (!temp.convert(setting.defaultValue.type())) { - qWarning("failed to interpret \"%s\" as correct type for \"%s\" in plugin \"%s\", using default", - qPrintable(temp.toString()), qPrintable(setting.key), qPrintable(plugin->name())); - temp = setting.defaultValue; - } - m_PluginSettings[plugin->name()][setting.key] = temp; - m_PluginDescriptions[plugin->name()][setting.key] = - QString("%1 (default: %2)").arg(setting.description).arg(setting.defaultValue.toString()); - } + m_PluginBlacklist.clear(); + int count = m_Settings.beginReadArray("pluginBlacklist"); + for (int i = 0; i < count; ++i) { + m_Settings.setArrayIndex(i); + m_PluginBlacklist.insert(m_Settings.value("name").toString()); + } + m_Settings.endArray(); } -QString Settings::obfuscate(const QString& password) { - QByteArray temp = password.toUtf8(); +bool Settings::pluginBlacklisted(const QString &fileName) const +{ + return m_PluginBlacklist.contains(fileName); +} - QByteArray buffer; - for (int i = 0; i < temp.length(); ++i) { - buffer.append(temp.at(i) ^ Key2[i % 20]); - } - return buffer.toBase64(); +void Settings::registerAsNXMHandler(bool force) +{ + std::wstring nxmPath = ToWString(QCoreApplication::applicationDirPath() + "/nxmhandler.exe"); + std::wstring executable = ToWString(QCoreApplication::applicationFilePath()); + std::wstring mode = force ? L"forcereg" : L"reg"; + std::wstring parameters = mode + L" " + m_GamePlugin->gameShortName().toStdWString() + L" \"" + executable + L"\""; + HINSTANCE res = ::ShellExecuteW(nullptr, L"open", nxmPath.c_str(), parameters.c_str(), nullptr, SW_SHOWNORMAL); + if ((int)res <= 32) { + QMessageBox::critical(nullptr, tr("Failed"), + tr("Sorry, failed to start the helper application")); + } } -QString Settings::deObfuscate(const QString& password) { - QByteArray temp(QByteArray::fromBase64(password.toUtf8())); +void Settings::managedGameChanged(IPluginGame const *gamePlugin) +{ + m_GamePlugin = gamePlugin; +} - QByteArray buffer; - for (int i = 0; i < temp.length(); ++i) { - buffer.append(temp.at(i) ^ Key2[i % 20]); +void Settings::registerPlugin(IPlugin *plugin) +{ + m_Plugins.push_back(plugin); + m_PluginSettings.insert(plugin->name(), QMap()); + m_PluginDescriptions.insert(plugin->name(), QMap()); + for (const PluginSetting &setting : plugin->settings()) { + QVariant temp = m_Settings.value("Plugins/" + plugin->name() + "/" + setting.key, setting.defaultValue); + if (!temp.convert(setting.defaultValue.type())) { + qWarning("failed to interpret \"%s\" as correct type for \"%s\" in plugin \"%s\", using default", + qPrintable(temp.toString()), qPrintable(setting.key), qPrintable(plugin->name())); + temp = setting.defaultValue; } - return QString::fromUtf8(buffer.constData()); + m_PluginSettings[plugin->name()][setting.key] = temp; + m_PluginDescriptions[plugin->name()][setting.key] = QString("%1 (default: %2)").arg(setting.description).arg(setting.defaultValue.toString()); + } } -bool Settings::hideUncheckedPlugins() const { - return m_Settings.value("Settings/hide_unchecked_plugins", false).toBool(); -} +QString Settings::obfuscate(const QString &password) +{ + QByteArray temp = password.toUtf8(); -bool Settings::forceEnableCoreFiles() const { - return m_Settings.value("Settings/force_enable_core_files", true).toBool(); + QByteArray buffer; + for (int i = 0; i < temp.length(); ++i) { + buffer.append(temp.at(i) ^ Key2[i % 20]); + } + return buffer.toBase64(); } -bool Settings::automaticLoginEnabled() const { return m_Settings.value("Settings/nexus_login", false).toBool(); } +QString Settings::deObfuscate(const QString &password) +{ + QByteArray temp(QByteArray::fromBase64(password.toUtf8())); + + QByteArray buffer; + for (int i = 0; i < temp.length(); ++i) { + buffer.append(temp.at(i) ^ Key2[i % 20]); + } + return QString::fromUtf8(buffer.constData()); +} -QString Settings::getSteamAppID() const { - return m_Settings.value("Settings/app_id", m_GamePlugin->steamAPPId()).toString(); +bool Settings::hideUncheckedPlugins() const +{ + return m_Settings.value("Settings/hide_unchecked_plugins", false).toBool(); } -bool Settings::usePrereleases() const { return m_Settings.value("Settings/use_prereleases", false).toBool(); } +bool Settings::forceEnableCoreFiles() const +{ + return m_Settings.value("Settings/force_enable_core_files", true).toBool(); +} -void Settings::setDownloadSpeed(const QString& serverName, int bytesPerSecond) { - m_Settings.beginGroup("Servers"); +bool Settings::automaticLoginEnabled() const +{ + return m_Settings.value("Settings/nexus_login", false).toBool(); +} - for (const QString& serverKey : m_Settings.childKeys()) { - QVariantMap data = m_Settings.value(serverKey).toMap(); - if (serverKey == serverName) { - data["downloadCount"] = data["downloadCount"].toInt() + 1; - data["downloadSpeed"] = data["downloadSpeed"].toDouble() + static_cast(bytesPerSecond); - m_Settings.setValue(serverKey, data); - } - } +QString Settings::getSteamAppID() const +{ + return m_Settings.value("Settings/app_id", m_GamePlugin->steamAPPId()).toString(); +} - m_Settings.endGroup(); - m_Settings.sync(); +bool Settings::usePrereleases() const +{ + return m_Settings.value("Settings/use_prereleases", false).toBool(); } -std::map Settings::getPreferredServers() { - std::map result; - m_Settings.beginGroup("Servers"); +void Settings::setDownloadSpeed(const QString &serverName, int bytesPerSecond) +{ + m_Settings.beginGroup("Servers"); - for (const QString& serverKey : m_Settings.childKeys()) { - QVariantMap data = m_Settings.value(serverKey).toMap(); - int preference = data["preferred"].toInt(); - if (preference > 0) { - result[serverKey] = preference; - } + for (const QString &serverKey : m_Settings.childKeys()) { + QVariantMap data = m_Settings.value(serverKey).toMap(); + if (serverKey == serverName) { + data["downloadCount"] = data["downloadCount"].toInt() + 1; + data["downloadSpeed"] = data["downloadSpeed"].toDouble() + static_cast(bytesPerSecond); + m_Settings.setValue(serverKey, data); } - m_Settings.endGroup(); + } - return result; + m_Settings.endGroup(); + m_Settings.sync(); } -QString Settings::getConfigurablePath(const QString& key, const QString& def, bool resolve) const { - QString result = QDir::fromNativeSeparators( - m_Settings.value(QString("settings/") + key, QString("%BASE_DIR%/") + def).toString()); - if (resolve) { - result.replace("%BASE_DIR%", getBaseDirectory()); +std::map Settings::getPreferredServers() +{ + std::map result; + m_Settings.beginGroup("Servers"); + + for (const QString &serverKey : m_Settings.childKeys()) { + QVariantMap data = m_Settings.value(serverKey).toMap(); + int preference = data["preferred"].toInt(); + if (preference > 0) { + result[serverKey] = preference; } - return result; -} + } + m_Settings.endGroup(); -QString Settings::getBaseDirectory() const { - return QDir::fromNativeSeparators( - m_Settings.value("settings/base_directory", qApp->property("dataPath").toString()).toString()); + return result; } -QString Settings::getDownloadDirectory(bool resolve) const { - return getConfigurablePath("download_directory", ToQString(AppConfig::downloadPath()), resolve); +QString Settings::getConfigurablePath(const QString &key, + const QString &def, + bool resolve) const +{ + QString result = QDir::fromNativeSeparators( + m_Settings.value(QString("settings/") + key, QString("%BASE_DIR%/") + def) + .toString()); + if (resolve) { + result.replace("%BASE_DIR%", getBaseDirectory()); + } + return result; } -QString Settings::getCacheDirectory(bool resolve) const { - return getConfigurablePath("cache_directory", ToQString(AppConfig::cachePath()), resolve); +QString Settings::getBaseDirectory() const +{ + return QDir::fromNativeSeparators(m_Settings.value( + "settings/base_directory", qApp->property("dataPath").toString()).toString()); } -QString Settings::getModDirectory(bool resolve) const { - return getConfigurablePath("mod_directory", ToQString(AppConfig::modsPath()), resolve); +QString Settings::getDownloadDirectory(bool resolve) const +{ + return getConfigurablePath("download_directory", ToQString(AppConfig::downloadPath()), resolve); } -QString Settings::getProfileDirectory(bool resolve) const { - return getConfigurablePath("profiles_directory", ToQString(AppConfig::profilesPath()), resolve); +QString Settings::getCacheDirectory(bool resolve) const +{ + return getConfigurablePath("cache_directory", ToQString(AppConfig::cachePath()), resolve); } -QString Settings::getOverwriteDirectory(bool resolve) const { - return getConfigurablePath("overwrite_directory", ToQString(AppConfig::overwritePath()), resolve); +QString Settings::getModDirectory(bool resolve) const +{ + return getConfigurablePath("mod_directory", ToQString(AppConfig::modsPath()), resolve); } -QString Settings::getNMMVersion() const { - static const QString MIN_NMM_VERSION = "0.61.13"; - QString result = m_Settings.value("Settings/nmm_version", MIN_NMM_VERSION).toString(); - if (VersionInfo(result) < VersionInfo(MIN_NMM_VERSION)) { - result = MIN_NMM_VERSION; - } - return result; +QString Settings::getProfileDirectory(bool resolve) const +{ + return getConfigurablePath("profiles_directory", ToQString(AppConfig::profilesPath()), resolve); } -bool Settings::getNexusLogin(QString& username, QString& password) const { - if (m_Settings.value("Settings/nexus_login", false).toBool()) { - username = m_Settings.value("Settings/nexus_username", "").toString(); - password = deObfuscate(m_Settings.value("Settings/nexus_password", "").toString()); - return true; - } else { - return false; - } +QString Settings::getOverwriteDirectory(bool resolve) const +{ + return getConfigurablePath("overwrite_directory", + ToQString(AppConfig::overwritePath()), resolve); } -bool Settings::getSteamLogin(QString& username, QString& password) const { - if (m_Settings.contains("Settings/steam_username") && m_Settings.contains("Settings/steam_password")) { - username = m_Settings.value("Settings/steam_username").toString(); - password = deObfuscate(m_Settings.value("Settings/steam_password").toString()); - return true; - } else { - return false; - } +QString Settings::getNMMVersion() const +{ + static const QString MIN_NMM_VERSION = "0.61.13"; + QString result = m_Settings.value("Settings/nmm_version", MIN_NMM_VERSION).toString(); + if (VersionInfo(result) < VersionInfo(MIN_NMM_VERSION)) { + result = MIN_NMM_VERSION; + } + return result; } -bool Settings::compactDownloads() const { return m_Settings.value("Settings/compact_downloads", false).toBool(); } - -bool Settings::metaDownloads() const { return m_Settings.value("Settings/meta_downloads", false).toBool(); } -bool Settings::offlineMode() const { return m_Settings.value("Settings/offline_mode", false).toBool(); } - -int Settings::logLevel() const { - return m_Settings.value("Settings/log_level", static_cast(LogLevel::Info)).toInt(); +bool Settings::getNexusLogin(QString &username, QString &password) const +{ + if (m_Settings.value("Settings/nexus_login", false).toBool()) { + username = m_Settings.value("Settings/nexus_username", "").toString(); + password = deObfuscate(m_Settings.value("Settings/nexus_password", "").toString()); + return true; + } else { + return false; + } } -int Settings::crashDumpsType() const { - return m_Settings.value("Settings/crash_dumps_type", static_cast(CrashDumpsType::Mini)).toInt(); +bool Settings::getSteamLogin(QString &username, QString &password) const +{ + if (m_Settings.contains("Settings/steam_username") + && m_Settings.contains("Settings/steam_password")) { + username = m_Settings.value("Settings/steam_username").toString(); + password = deObfuscate(m_Settings.value("Settings/steam_password").toString()); + return true; + } else { + return false; + } } - -int Settings::crashDumpsMax() const { return m_Settings.value("Settings/crash_dumps_max", 5).toInt(); } - -void Settings::setNexusLogin(QString username, QString password) { - m_Settings.setValue("Settings/nexus_login", true); - m_Settings.setValue("Settings/nexus_username", username); - m_Settings.setValue("Settings/nexus_password", obfuscate(password)); +bool Settings::compactDownloads() const +{ + return m_Settings.value("Settings/compact_downloads", false).toBool(); } -void Settings::setSteamLogin(QString username, QString password) { - if (username == "") { - m_Settings.remove("Settings/steam_username"); - password = ""; - } else { - m_Settings.setValue("Settings/steam_username", username); - } - if (password == "") { - m_Settings.remove("Settings/steam_password"); - } else { - m_Settings.setValue("Settings/steam_password", obfuscate(password)); - } +bool Settings::metaDownloads() const +{ + return m_Settings.value("Settings/meta_downloads", false).toBool(); } -LoadMechanism::EMechanism Settings::getLoadMechanism() const { - switch (m_Settings.value("Settings/load_mechanism").toInt()) { - case LoadMechanism::LOAD_MODORGANIZER: - return LoadMechanism::LOAD_MODORGANIZER; - case LoadMechanism::LOAD_SCRIPTEXTENDER: - return LoadMechanism::LOAD_SCRIPTEXTENDER; - case LoadMechanism::LOAD_PROXYDLL: - return LoadMechanism::LOAD_PROXYDLL; - } - throw std::runtime_error("invalid load mechanism"); +bool Settings::offlineMode() const +{ + return m_Settings.value("Settings/offline_mode", false).toBool(); } -void Settings::setupLoadMechanism() { m_LoadMechanism.activate(getLoadMechanism()); } - -bool Settings::useProxy() const { return m_Settings.value("Settings/use_proxy", false).toBool(); } - -bool Settings::displayForeign() const { return m_Settings.value("Settings/display_foreign", true).toBool(); } - -void Settings::setMotDHash(uint hash) { m_Settings.setValue("motd_hash", hash); } - -uint Settings::getMotDHash() const { return m_Settings.value("motd_hash", 0).toUInt(); } - -QVariant Settings::pluginSetting(const QString& pluginName, const QString& key) const { - auto iterPlugin = m_PluginSettings.find(pluginName); - if (iterPlugin == m_PluginSettings.end()) { - return QVariant(); - } - auto iterSetting = iterPlugin->find(key); - if (iterSetting == iterPlugin->end()) { - return QVariant(); - } - - return *iterSetting; +int Settings::logLevel() const +{ + return m_Settings.value("Settings/log_level", static_cast(LogLevel::Info)).toInt(); } -void Settings::setPluginSetting(const QString& pluginName, const QString& key, const QVariant& value) { - auto iterPlugin = m_PluginSettings.find(pluginName); - if (iterPlugin == m_PluginSettings.end()) { - throw MyException(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; - m_Settings.setValue("Plugins/" + pluginName + "/" + key, value); +int Settings::crashDumpsType() const +{ + return m_Settings.value("Settings/crash_dumps_type", static_cast(CrashDumpsType::Mini)).toInt(); } -QVariant Settings::pluginPersistent(const QString& pluginName, const QString& key, const QVariant& def) const { - if (!m_PluginSettings.contains(pluginName)) { - return def; - } - return m_Settings.value("PluginPersistance/" + pluginName + "/" + key, def); +int Settings::crashDumpsMax() const +{ + return m_Settings.value("Settings/crash_dumps_max", 5).toInt(); } -void Settings::setPluginPersistent(const QString& pluginName, const QString& key, const QVariant& value, bool sync) { - if (!m_PluginSettings.contains(pluginName)) { - throw MyException(tr("attempt to store setting for unknown plugin \"%1\"").arg(pluginName)); - } - m_Settings.setValue("PluginPersistance/" + pluginName + "/" + key, value); - if (sync) { - m_Settings.sync(); - } +void Settings::setNexusLogin(QString username, QString password) +{ + m_Settings.setValue("Settings/nexus_login", true); + m_Settings.setValue("Settings/nexus_username", username); + m_Settings.setValue("Settings/nexus_password", obfuscate(password)); } -QString Settings::language() { - QString result = m_Settings.value("Settings/language", "").toString(); - if (result.isEmpty()) { - QStringList languagePreferences = QLocale::system().uiLanguages(); - if (languagePreferences.length() > 0) { - // the users most favoritest language - result = languagePreferences.at(0); - } else { - // fallback system locale - result = QLocale::system().name(); - } - } - return result; +void Settings::setSteamLogin(QString username, QString password) +{ + if (username == "") { + m_Settings.remove("Settings/steam_username"); + password = ""; + } else { + m_Settings.setValue("Settings/steam_username", username); + } + if (password == "") { + m_Settings.remove("Settings/steam_password"); + } else { + m_Settings.setValue("Settings/steam_password", obfuscate(password)); + } } -void Settings::updateServers(const QList& servers) { - m_Settings.beginGroup("Servers"); - QStringList oldServerKeys = m_Settings.childKeys(); - - for (const ServerInfo& server : servers) { - if (!oldServerKeys.contains(server.name)) { - // not yet known server - QVariantMap newVal; - newVal["premium"] = server.premium; - newVal["preferred"] = server.preferred ? 1 : 0; - newVal["lastSeen"] = server.lastSeen; - newVal["downloadCount"] = 0; - newVal["downloadSpeed"] = 0.0; - - m_Settings.setValue(server.name, newVal); - } else { - QVariantMap data = m_Settings.value(server.name).toMap(); - data["lastSeen"] = server.lastSeen; - data["premium"] = server.premium; +LoadMechanism::EMechanism Settings::getLoadMechanism() const +{ + switch (m_Settings.value("Settings/load_mechanism").toInt()) { + case LoadMechanism::LOAD_MODORGANIZER: return LoadMechanism::LOAD_MODORGANIZER; + case LoadMechanism::LOAD_SCRIPTEXTENDER: return LoadMechanism::LOAD_SCRIPTEXTENDER; + case LoadMechanism::LOAD_PROXYDLL: return LoadMechanism::LOAD_PROXYDLL; + } + throw std::runtime_error("invalid load mechanism"); +} - m_Settings.setValue(server.name, data); - } - } - // clean up unavailable servers - QDate now = QDate::currentDate(); - for (const QString& key : m_Settings.childKeys()) { - QVariantMap val = m_Settings.value(key).toMap(); - QDate lastSeen = val["lastSeen"].toDate(); - if (lastSeen.daysTo(now) > 30) { - qDebug("removing server %s since it hasn't been available for downloads in over a month", qPrintable(key)); - m_Settings.remove(key); - } - } +void Settings::setupLoadMechanism() +{ + m_LoadMechanism.activate(getLoadMechanism()); +} - m_Settings.endGroup(); - m_Settings.sync(); +bool Settings::useProxy() const +{ + return m_Settings.value("Settings/use_proxy", false).toBool(); } -void Settings::addBlacklistPlugin(const QString& fileName) { - m_PluginBlacklist.insert(fileName); - writePluginBlacklist(); +bool Settings::displayForeign() const +{ + return m_Settings.value("Settings/display_foreign", true).toBool(); } -void Settings::writePluginBlacklist() { - m_Settings.beginWriteArray("pluginBlacklist"); - int idx = 0; - for (const QString& plugin : m_PluginBlacklist) { - m_Settings.setArrayIndex(idx++); - m_Settings.setValue("name", plugin); - } - - m_Settings.endArray(); -} - -void Settings::addLanguages(QComboBox* languageBox) { - std::vector> languages; - - QDirIterator langIter(QCoreApplication::applicationDirPath() + "/translations", QDir::Files); - QString pattern = ToQString(AppConfig::translationPrefix()) + "_([a-z]{2,3}(_[A-Z]{2,2})?).qm"; - QRegExp exp(pattern); - while (langIter.hasNext()) { - langIter.next(); - QString file = langIter.fileName(); - if (exp.exactMatch(file)) { - QString languageCode = exp.cap(1); - QLocale locale(languageCode); - QString languageString = - QString("%1 (%2)") - .arg(locale.nativeLanguageName()) - .arg(locale.nativeCountryName()); // QLocale::languageToString(locale.language()); - if (locale.language() == QLocale::Chinese) { - if (languageCode == "zh_TW") { - languageString = "Chinese (traditional)"; - } else { - languageString = "Chinese (simplified)"; - } - } - languages.push_back(std::make_pair(QString("%1").arg(languageString), exp.cap(1))); - // languageBox->addItem(QString("%1").arg(languageString), exp.cap(1)); - } - } - if (!languageBox->findText("English")) { - languages.push_back(std::make_pair(QString("English"), QString("en_US"))); - // languageBox->addItem("English", "en_US"); - } - std::sort(languages.begin(), languages.end()); - for (const auto& lang : languages) { - languageBox->addItem(lang.first, lang.second); - } +void Settings::setMotDHash(uint hash) +{ + m_Settings.setValue("motd_hash", hash); } -void Settings::addStyles(QComboBox* styleBox) { - styleBox->addItem("None", ""); - styleBox->addItem("Fusion", "Fusion"); - - QDirIterator langIter(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::stylesheetsPath()), - QStringList("*.qss"), QDir::Files); - while (langIter.hasNext()) { - langIter.next(); - QString style = langIter.fileName(); - styleBox->addItem(style, style); - } +uint Settings::getMotDHash() const +{ + return m_Settings.value("motd_hash", 0).toUInt(); } -void Settings::resetDialogs() { QuestionBoxMemory::resetDialogs(); } - -void Settings::query(QWidget* parent) { - SettingsDialog dialog(parent); - - connect(&dialog, SIGNAL(resetDialogs()), this, SLOT(resetDialogs())); - - std::vector> tabs; +QVariant Settings::pluginSetting(const QString &pluginName, const QString &key) const +{ + auto iterPlugin = m_PluginSettings.find(pluginName); + if (iterPlugin == m_PluginSettings.end()) { + return QVariant(); + } + auto iterSetting = iterPlugin->find(key); + if (iterSetting == iterPlugin->end()) { + return QVariant(); + } - tabs.push_back(std::unique_ptr(new GeneralTab(this, dialog))); - tabs.push_back(std::unique_ptr(new PathsTab(this, dialog))); - tabs.push_back(std::unique_ptr(new DiagnosticsTab(this, dialog))); - tabs.push_back(std::unique_ptr(new NexusTab(this, dialog))); - tabs.push_back(std::unique_ptr(new SteamTab(this, dialog))); - tabs.push_back(std::unique_ptr(new PluginsTab(this, dialog))); - tabs.push_back(std::unique_ptr(new WorkaroundsTab(this, dialog))); - - if (dialog.exec() == QDialog::Accepted) { - // remember settings before change - QMap before; - m_Settings.beginGroup("Settings"); - for (auto k : m_Settings.allKeys()) - before[k] = m_Settings.value(k).toString(); - m_Settings.endGroup(); - - // transfer modified settings to configuration file - for (std::unique_ptr const& tab : tabs) { - tab->update(); - } - - // print "changed" settings - m_Settings.beginGroup("Settings"); - bool first_update = true; - for (auto k : m_Settings.allKeys()) - if (m_Settings.value(k).toString() != before[k] && !k.contains("username") && !k.contains("password")) { - if (first_update) { - qDebug("Changed settings:"); - first_update = false; - } - qDebug(" %s=%s", k.toUtf8().data(), m_Settings.value(k).toString().toUtf8().data()); - } - m_Settings.endGroup(); - } + return *iterSetting; } -Settings::SettingsTab::SettingsTab(Settings* m_parent, SettingsDialog& m_dialog) - : m_parent(m_parent), m_Settings(m_parent->m_Settings), m_dialog(m_dialog) {} - -Settings::SettingsTab::~SettingsTab() {} - -Settings::GeneralTab::GeneralTab(Settings* m_parent, SettingsDialog& m_dialog) - : Settings::SettingsTab(m_parent, m_dialog), m_languageBox(m_dialog.findChild("languageBox")), - m_styleBox(m_dialog.findChild("styleBox")), - m_compactBox(m_dialog.findChild("compactBox")), - m_showMetaBox(m_dialog.findChild("showMetaBox")), - m_usePrereleaseBox(m_dialog.findChild("usePrereleaseBox")) { - // FIXME I think 'addLanguages' lives in here not in parent - m_parent->addLanguages(m_languageBox); - { - QString languageCode = m_parent->language(); - int currentID = m_languageBox->findData(languageCode); - // I made a mess. :( Most languages are stored with only the iso country - // code (2 characters like "de") but chinese - // with the exact language variant (zh_TW) so I have to search for both - // variants - if (currentID == -1) { - currentID = m_languageBox->findData(languageCode.mid(0, 2)); - } - if (currentID != -1) { - m_languageBox->setCurrentIndex(currentID); - } - } - - // FIXME I think addStyles lives in here not in parent - m_parent->addStyles(m_styleBox); - { - int currentID = m_styleBox->findData(m_Settings.value("Settings/style", "").toString()); - if (currentID != -1) { - m_styleBox->setCurrentIndex(currentID); - } - } +void Settings::setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value) +{ + auto iterPlugin = m_PluginSettings.find(pluginName); + if (iterPlugin == m_PluginSettings.end()) { + throw MyException(tr("attempt to store setting for unknown plugin \"%1\"").arg(pluginName)); + } - m_compactBox->setChecked(m_parent->compactDownloads()); - m_showMetaBox->setChecked(m_parent->metaDownloads()); - m_usePrereleaseBox->setChecked(m_parent->usePrereleases()); + // store the new setting both in memory and in the ini + m_PluginSettings[pluginName][key] = value; + m_Settings.setValue("Plugins/" + pluginName + "/" + key, value); } -void Settings::GeneralTab::update() { - QString oldLanguage = m_parent->language(); - QString newLanguage = m_languageBox->itemData(m_languageBox->currentIndex()).toString(); - if (newLanguage != oldLanguage) { - m_Settings.setValue("Settings/language", newLanguage); - emit m_parent->languageChanged(newLanguage); - } - - QString oldStyle = m_Settings.value("Settings/style", "").toString(); - QString newStyle = m_styleBox->itemData(m_styleBox->currentIndex()).toString(); - if (oldStyle != newStyle) { - m_Settings.setValue("Settings/style", newStyle); - emit m_parent->styleChanged(newStyle); - } - - m_Settings.setValue("Settings/compact_downloads", m_compactBox->isChecked()); - m_Settings.setValue("Settings/meta_downloads", m_showMetaBox->isChecked()); - m_Settings.setValue("Settings/use_prereleases", m_usePrereleaseBox->isChecked()); -} - -Settings::PathsTab::PathsTab(Settings* parent, SettingsDialog& dialog) - : SettingsTab(parent, dialog), m_baseDirEdit(m_dialog.findChild("baseDirEdit")), - m_downloadDirEdit(m_dialog.findChild("downloadDirEdit")), - m_modDirEdit(m_dialog.findChild("modDirEdit")), - m_cacheDirEdit(m_dialog.findChild("cacheDirEdit")), - m_profilesDirEdit(m_dialog.findChild("profilesDirEdit")), - m_overwriteDirEdit(m_dialog.findChild("overwriteDirEdit")) { - m_baseDirEdit->setText(m_parent->getBaseDirectory()); - - QString basePath = parent->getBaseDirectory(); - QDir baseDir(basePath); - for (const auto& dir : {std::make_pair(m_downloadDirEdit, m_parent->getDownloadDirectory(false)), - std::make_pair(m_modDirEdit, m_parent->getModDirectory(false)), - std::make_pair(m_cacheDirEdit, m_parent->getCacheDirectory(false)), - std::make_pair(m_profilesDirEdit, m_parent->getProfileDirectory(false)), - std::make_pair(m_overwriteDirEdit, m_parent->getOverwriteDirectory(false))}) { - QString storePath = baseDir.relativeFilePath(dir.second); - storePath = dir.second; - dir.first->setText(storePath); - } +QVariant Settings::pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const +{ + if (!m_PluginSettings.contains(pluginName)) { + return def; + } + return m_Settings.value("PluginPersistance/" + pluginName + "/" + key, def); } -void Settings::PathsTab::update() { - typedef std::tuple Directory; - - QString basePath = m_parent->getBaseDirectory(); - - for (const Directory& dir : - {Directory{m_downloadDirEdit->text(), "download_directory", AppConfig::downloadPath()}, - Directory{m_cacheDirEdit->text(), "cache_directory", AppConfig::cachePath()}, - Directory{m_modDirEdit->text(), "mod_directory", AppConfig::modsPath()}, - Directory{m_overwriteDirEdit->text(), "overwrite_directory", AppConfig::overwritePath()}, - Directory{m_profilesDirEdit->text(), "profiles_directory", AppConfig::profilesPath()}}) { - QString path, settingsKey; - std::wstring defaultName; - std::tie(path, settingsKey, defaultName) = dir; - - settingsKey = QString("Settings/%1").arg(settingsKey); - - QString realPath = path; - realPath.replace("%BASE_DIR%", m_baseDirEdit->text()); - - if (!QDir(realPath).exists()) { - if (!QDir().mkpath(realPath)) { - QMessageBox::warning(qApp->activeWindow(), tr("Error"), - tr("Failed to create \"%1\", you may not have the " - "necessary permission. path remains unchanged.") - .arg(realPath)); - } - } - - if (QFileInfo(realPath) != QFileInfo(basePath + "/" + QString::fromStdWString(defaultName))) { - m_Settings.setValue(settingsKey, path); - } else { - m_Settings.remove(settingsKey); - } - } +void Settings::setPluginPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync) +{ + if (!m_PluginSettings.contains(pluginName)) { + throw MyException(tr("attempt to store setting for unknown plugin \"%1\"").arg(pluginName)); + } + m_Settings.setValue("PluginPersistance/" + pluginName + "/" + key, value); + if (sync) { + m_Settings.sync(); + } +} - if (QFileInfo(m_baseDirEdit->text()) != QFileInfo(qApp->property("dataPath").toString())) { - m_Settings.setValue("Settings/base_directory", m_baseDirEdit->text()); +QString Settings::language() +{ + QString result = m_Settings.value("Settings/language", "").toString(); + if (result.isEmpty()) { + QStringList languagePreferences = QLocale::system().uiLanguages(); + if (languagePreferences.length() > 0) { + // the users most favoritest language + result = languagePreferences.at(0); } else { - m_Settings.remove("Settings/base_directory"); + // fallback system locale + result = QLocale::system().name(); } + } + return result; } -Settings::DiagnosticsTab::DiagnosticsTab(Settings* m_parent, SettingsDialog& m_dialog) - : Settings::SettingsTab(m_parent, m_dialog), m_logLevelBox(m_dialog.findChild("logLevelBox")), - m_dumpsTypeBox(m_dialog.findChild("dumpsTypeBox")), - m_dumpsMaxEdit(m_dialog.findChild("dumpsMaxEdit")), - m_diagnosticsExplainedLabel(m_dialog.findChild("diagnosticsExplainedLabel")) { - m_logLevelBox->setCurrentIndex(m_parent->logLevel()); - m_dumpsTypeBox->setCurrentIndex(m_parent->crashDumpsType()); - m_dumpsMaxEdit->setValue(m_parent->crashDumpsMax()); - QString logsPath = qApp->property("dataPath").toString() + "/" + QString::fromStdWString(AppConfig::logPath()); - m_diagnosticsExplainedLabel->setText( - m_diagnosticsExplainedLabel->text() - .replace("LOGS_FULL_PATH", logsPath) - .replace("LOGS_DIR", QString::fromStdWString(AppConfig::logPath())) - .replace("DUMPS_FULL_PATH", QString::fromStdWString(OrganizerCore::crashDumpsPath())) - .replace("DUMPS_DIR", QString::fromStdWString(AppConfig::dumpsDir()))); -} - -void Settings::DiagnosticsTab::update() { - m_Settings.setValue("Settings/log_level", m_logLevelBox->currentIndex()); - m_Settings.setValue("Settings/crash_dumps_type", m_dumpsTypeBox->currentIndex()); - m_Settings.setValue("Settings/crash_dumps_max", m_dumpsMaxEdit->value()); -} - -Settings::NexusTab::NexusTab(Settings* parent, SettingsDialog& dialog) - : Settings::SettingsTab(parent, dialog), m_loginCheckBox(dialog.findChild("loginCheckBox")), - m_usernameEdit(dialog.findChild("usernameEdit")), - m_passwordEdit(dialog.findChild("passwordEdit")), - m_offlineBox(dialog.findChild("offlineBox")), m_proxyBox(dialog.findChild("proxyBox")), - m_knownServersList(dialog.findChild("knownServersList")), - m_preferredServersList(dialog.findChild("preferredServersList")) { - if (parent->automaticLoginEnabled()) { - m_loginCheckBox->setChecked(true); - m_usernameEdit->setText(m_Settings.value("Settings/nexus_username", "").toString()); - m_passwordEdit->setText(deObfuscate(m_Settings.value("Settings/nexus_password", "").toString())); - } - - m_offlineBox->setChecked(parent->offlineMode()); - m_proxyBox->setChecked(parent->useProxy()); +void Settings::updateServers(const QList &servers) +{ + m_Settings.beginGroup("Servers"); + QStringList oldServerKeys = m_Settings.childKeys(); - // display server preferences - m_Settings.beginGroup("Servers"); - for (const QString& key : m_Settings.childKeys()) { - QVariantMap val = m_Settings.value(key).toMap(); - QString type = val["premium"].toBool() ? "(premium)" : "(free)"; + for (const ServerInfo &server : servers) { + if (!oldServerKeys.contains(server.name)) { + // not yet known server + QVariantMap newVal; + newVal["premium"] = server.premium; + newVal["preferred"] = server.preferred ? 1 : 0; + newVal["lastSeen"] = server.lastSeen; + newVal["downloadCount"] = 0; + newVal["downloadSpeed"] = 0.0; - QString descriptor = key + " " + type; - if (val.contains("downloadSpeed") && val.contains("downloadCount") && (val["downloadCount"].toInt() > 0)) { - int bps = static_cast(val["downloadSpeed"].toDouble() / val["downloadCount"].toInt()); - descriptor += QString(" (%1 kbps)").arg(bps / 1024); - } - - QListWidgetItem* newItem = new QListWidgetItemEx(descriptor, Qt::UserRole + 1); + m_Settings.setValue(server.name, newVal); + } else { + QVariantMap data = m_Settings.value(server.name).toMap(); + data["lastSeen"] = server.lastSeen; + data["premium"] = server.premium; - newItem->setData(Qt::UserRole, key); - newItem->setData(Qt::UserRole + 1, val["preferred"].toInt()); - if (val["preferred"].toInt() > 0) { - m_preferredServersList->addItem(newItem); - } else { - m_knownServersList->addItem(newItem); - } - m_preferredServersList->sortItems(Qt::DescendingOrder); + m_Settings.setValue(server.name, data); } - m_Settings.endGroup(); -} + } -void Settings::NexusTab::update() { - if (m_loginCheckBox->isChecked()) { - m_Settings.setValue("Settings/nexus_login", true); - m_Settings.setValue("Settings/nexus_username", m_usernameEdit->text()); - m_Settings.setValue("Settings/nexus_password", obfuscate(m_passwordEdit->text())); - } else { - m_Settings.setValue("Settings/nexus_login", false); - m_Settings.remove("Settings/nexus_username"); - m_Settings.remove("Settings/nexus_password"); - } - m_Settings.setValue("Settings/offline_mode", m_offlineBox->isChecked()); - m_Settings.setValue("Settings/use_proxy", m_proxyBox->isChecked()); - - // store server preference - m_Settings.beginGroup("Servers"); - for (int i = 0; i < m_knownServersList->count(); ++i) { - QString key = m_knownServersList->item(i)->data(Qt::UserRole).toString(); - QVariantMap val = m_Settings.value(key).toMap(); - val["preferred"] = 0; - m_Settings.setValue(key, val); - } - int count = m_preferredServersList->count(); - for (int i = 0; i < count; ++i) { - QString key = m_preferredServersList->item(i)->data(Qt::UserRole).toString(); - QVariantMap val = m_Settings.value(key).toMap(); - val["preferred"] = count - i; - m_Settings.setValue(key, val); + // clean up unavailable servers + QDate now = QDate::currentDate(); + for (const QString &key : m_Settings.childKeys()) { + QVariantMap val = m_Settings.value(key).toMap(); + QDate lastSeen = val["lastSeen"].toDate(); + if (lastSeen.daysTo(now) > 30) { + qDebug("removing server %s since it hasn't been available for downloads in over a month", qPrintable(key)); + m_Settings.remove(key); } - m_Settings.endGroup(); -} + } -Settings::SteamTab::SteamTab(Settings* m_parent, SettingsDialog& m_dialog) - : Settings::SettingsTab(m_parent, m_dialog), m_steamUserEdit(m_dialog.findChild("steamUserEdit")), - m_steamPassEdit(m_dialog.findChild("steamPassEdit")) { - if (m_Settings.contains("Settings/steam_username")) { - m_steamUserEdit->setText(m_Settings.value("Settings/steam_username", "").toString()); - if (m_Settings.contains("Settings/steam_password")) { - m_steamPassEdit->setText(deObfuscate(m_Settings.value("Settings/steam_password", "").toString())); - } - } -} + m_Settings.endGroup(); -void Settings::SteamTab::update() { - // FIXME this should be inlined here? - m_parent->setSteamLogin(m_steamUserEdit->text(), m_steamPassEdit->text()); + m_Settings.sync(); } -Settings::PluginsTab::PluginsTab(Settings* m_parent, SettingsDialog& m_dialog) - : Settings::SettingsTab(m_parent, m_dialog), m_pluginsList(m_dialog.findChild("pluginsList")), - m_pluginBlacklistList(m_dialog.findChild("pluginBlacklist")) { - // display plugin settings - for (IPlugin* plugin : m_parent->m_Plugins) { - QListWidgetItem* listItem = new QListWidgetItem(plugin->name(), m_pluginsList); - listItem->setData(Qt::UserRole, QVariant::fromValue((void*)plugin)); - listItem->setData(Qt::UserRole + 1, m_parent->m_PluginSettings[plugin->name()]); - listItem->setData(Qt::UserRole + 2, m_parent->m_PluginDescriptions[plugin->name()]); - m_pluginsList->addItem(listItem); - } - - // display plugin blacklist - for (const QString& pluginName : m_parent->m_PluginBlacklist) { - m_pluginBlacklistList->addItem(pluginName); - } +void Settings::addBlacklistPlugin(const QString &fileName) +{ + m_PluginBlacklist.insert(fileName); + writePluginBlacklist(); } -void Settings::PluginsTab::update() { - // transfer plugin settings to in-memory structure - for (int i = 0; i < m_pluginsList->count(); ++i) { - QListWidgetItem* item = m_pluginsList->item(i); - m_parent->m_PluginSettings[item->text()] = item->data(Qt::UserRole + 1).toMap(); - } - // store plugin settings on disc - for (auto iterPlugins = m_parent->m_PluginSettings.begin(); iterPlugins != m_parent->m_PluginSettings.end(); - ++iterPlugins) { - for (auto iterSettings = iterPlugins->begin(); iterSettings != iterPlugins->end(); ++iterSettings) { - m_Settings.setValue("Plugins/" + iterPlugins.key() + "/" + iterSettings.key(), iterSettings.value()); - } - } +void Settings::writePluginBlacklist() +{ + m_Settings.beginWriteArray("pluginBlacklist"); + int idx = 0; + for (const QString &plugin : m_PluginBlacklist) { + m_Settings.setArrayIndex(idx++); + m_Settings.setValue("name", plugin); + } - // store plugin blacklist - m_parent->m_PluginBlacklist.clear(); - for (QListWidgetItem* item : m_pluginBlacklistList->findItems("*", Qt::MatchWildcard)) { - m_parent->m_PluginBlacklist.insert(item->text()); - } - m_parent->writePluginBlacklist(); + m_Settings.endArray(); } -Settings::WorkaroundsTab::WorkaroundsTab(Settings* m_parent, SettingsDialog& m_dialog) - : Settings::SettingsTab(m_parent, m_dialog), m_appIDEdit(m_dialog.findChild("appIDEdit")), - m_mechanismBox(m_dialog.findChild("mechanismBox")), - m_nmmVersionEdit(m_dialog.findChild("nmmVersionEdit")), - m_hideUncheckedBox(m_dialog.findChild("hideUncheckedBox")), - m_forceEnableBox(m_dialog.findChild("forceEnableBox")), - m_displayForeignBox(m_dialog.findChild("displayForeignBox")) { - m_appIDEdit->setText(m_parent->getSteamAppID()); - - LoadMechanism::EMechanism mechanismID = m_parent->getLoadMechanism(); - int index = 0; +void Settings::addLanguages(QComboBox *languageBox) +{ + std::vector> languages; - if (m_parent->m_LoadMechanism.isDirectLoadingSupported()) { - m_mechanismBox->addItem(QObject::tr("Mod Organizer"), LoadMechanism::LOAD_MODORGANIZER); - if (mechanismID == LoadMechanism::LOAD_MODORGANIZER) { - index = m_mechanismBox->count() - 1; + QDirIterator langIter(QCoreApplication::applicationDirPath() + "/translations", QDir::Files); + QString pattern = ToQString(AppConfig::translationPrefix()) + "_([a-z]{2,3}(_[A-Z]{2,2})?).qm"; + QRegExp exp(pattern); + while (langIter.hasNext()) { + langIter.next(); + QString file = langIter.fileName(); + if (exp.exactMatch(file)) { + QString languageCode = exp.cap(1); + QLocale locale(languageCode); + QString languageString = QString("%1 (%2)").arg(locale.nativeLanguageName()).arg(locale.nativeCountryName()); //QLocale::languageToString(locale.language()); + if (locale.language() == QLocale::Chinese) { + if (languageCode == "zh_TW") { + languageString = "Chinese (traditional)"; + } else { + languageString = "Chinese (simplified)"; } - } + } + languages.push_back(std::make_pair(QString("%1").arg(languageString), exp.cap(1))); + //languageBox->addItem(QString("%1").arg(languageString), exp.cap(1)); + } + } + if (!languageBox->findText("English")) { + languages.push_back(std::make_pair(QString("English"), QString("en_US"))); + //languageBox->addItem("English", "en_US"); + } + std::sort(languages.begin(), languages.end()); + for (const auto &lang : languages) { + languageBox->addItem(lang.first, lang.second); + } +} + +void Settings::addStyles(QComboBox *styleBox) +{ + styleBox->addItem("None", ""); + styleBox->addItem("Fusion", "Fusion"); + + QDirIterator langIter(QCoreApplication::applicationDirPath() + "/" + ToQString(AppConfig::stylesheetsPath()), QStringList("*.qss"), QDir::Files); + while (langIter.hasNext()) { + langIter.next(); + QString style = langIter.fileName(); + styleBox->addItem(style, style); + } +} + +void Settings::resetDialogs() +{ + QuestionBoxMemory::resetDialogs(); +} + + +void Settings::query(QWidget *parent) +{ + SettingsDialog dialog(parent); + + connect(&dialog, SIGNAL(resetDialogs()), this, SLOT(resetDialogs())); + + std::vector> tabs; + + tabs.push_back(std::unique_ptr(new GeneralTab(this, dialog))); + tabs.push_back(std::unique_ptr(new PathsTab(this, dialog))); + tabs.push_back(std::unique_ptr(new DiagnosticsTab(this, dialog))); + tabs.push_back(std::unique_ptr(new NexusTab(this, dialog))); + tabs.push_back(std::unique_ptr(new SteamTab(this, dialog))); + tabs.push_back(std::unique_ptr(new PluginsTab(this, dialog))); + tabs.push_back(std::unique_ptr(new WorkaroundsTab(this, dialog))); + + if (dialog.exec() == QDialog::Accepted) { + // remember settings before change + QMap before; + m_Settings.beginGroup("Settings"); + for (auto k : m_Settings.allKeys()) + before[k] = m_Settings.value(k).toString(); + m_Settings.endGroup(); - if (m_parent->m_LoadMechanism.isScriptExtenderSupported()) { - m_mechanismBox->addItem(QObject::tr("Script Extender"), LoadMechanism::LOAD_SCRIPTEXTENDER); - if (mechanismID == LoadMechanism::LOAD_SCRIPTEXTENDER) { - index = m_mechanismBox->count() - 1; - } + // transfer modified settings to configuration file + for (std::unique_ptr const &tab: tabs) { + tab->update(); } - if (m_parent->m_LoadMechanism.isProxyDLLSupported()) { - m_mechanismBox->addItem(QObject::tr("Proxy DLL"), LoadMechanism::LOAD_PROXYDLL); - if (mechanismID == LoadMechanism::LOAD_PROXYDLL) { - index = m_mechanismBox->count() - 1; + // print "changed" settings + m_Settings.beginGroup("Settings"); + bool first_update = true; + for (auto k : m_Settings.allKeys()) + if (m_Settings.value(k).toString() != before[k] && !k.contains("username") && !k.contains("password")) + { + if (first_update) { + qDebug("Changed settings:"); + first_update = false; } + qDebug(" %s=%s", k.toUtf8().data(), m_Settings.value(k).toString().toUtf8().data()); + } + m_Settings.endGroup(); + } +} + +Settings::SettingsTab::SettingsTab(Settings *m_parent, SettingsDialog &m_dialog) + : m_parent(m_parent) + , m_Settings(m_parent->m_Settings) + , m_dialog(m_dialog) +{ +} + +Settings::SettingsTab::~SettingsTab() +{} + +Settings::GeneralTab::GeneralTab(Settings *m_parent, SettingsDialog &m_dialog) + : Settings::SettingsTab(m_parent, m_dialog) + , m_languageBox(m_dialog.findChild("languageBox")) + , m_styleBox(m_dialog.findChild("styleBox")) + , m_compactBox(m_dialog.findChild("compactBox")) + , m_showMetaBox(m_dialog.findChild("showMetaBox")) + , m_usePrereleaseBox(m_dialog.findChild("usePrereleaseBox")) +{ + // FIXME I think 'addLanguages' lives in here not in parent + m_parent->addLanguages(m_languageBox); + { + QString languageCode = m_parent->language(); + int currentID = m_languageBox->findData(languageCode); + // I made a mess. :( Most languages are stored with only the iso country + // code (2 characters like "de") but chinese + // with the exact language variant (zh_TW) so I have to search for both + // variants + if (currentID == -1) { + currentID = m_languageBox->findData(languageCode.mid(0, 2)); + } + if (currentID != -1) { + m_languageBox->setCurrentIndex(currentID); + } + } + + // FIXME I think addStyles lives in here not in parent + m_parent->addStyles(m_styleBox); + { + int currentID = m_styleBox->findData( + m_Settings.value("Settings/style", "").toString()); + if (currentID != -1) { + m_styleBox->setCurrentIndex(currentID); + } + } + + m_compactBox->setChecked(m_parent->compactDownloads()); + m_showMetaBox->setChecked(m_parent->metaDownloads()); + m_usePrereleaseBox->setChecked(m_parent->usePrereleases()); +} + +void Settings::GeneralTab::update() +{ + QString oldLanguage = m_parent->language(); + QString newLanguage = m_languageBox->itemData(m_languageBox->currentIndex()).toString(); + if (newLanguage != oldLanguage) { + m_Settings.setValue("Settings/language", newLanguage); + emit m_parent->languageChanged(newLanguage); + } + + QString oldStyle = m_Settings.value("Settings/style", "").toString(); + QString newStyle = m_styleBox->itemData(m_styleBox->currentIndex()).toString(); + if (oldStyle != newStyle) { + m_Settings.setValue("Settings/style", newStyle); + emit m_parent->styleChanged(newStyle); + } + + m_Settings.setValue("Settings/compact_downloads", m_compactBox->isChecked()); + m_Settings.setValue("Settings/meta_downloads", m_showMetaBox->isChecked()); + m_Settings.setValue("Settings/use_prereleases", m_usePrereleaseBox->isChecked()); +} + +Settings::PathsTab::PathsTab(Settings *parent, SettingsDialog &dialog) + : SettingsTab(parent, dialog) + , m_baseDirEdit(m_dialog.findChild("baseDirEdit")) + , m_downloadDirEdit(m_dialog.findChild("downloadDirEdit")) + , m_modDirEdit(m_dialog.findChild("modDirEdit")) + , m_cacheDirEdit(m_dialog.findChild("cacheDirEdit")) + , m_profilesDirEdit(m_dialog.findChild("profilesDirEdit")) + , m_overwriteDirEdit(m_dialog.findChild("overwriteDirEdit")) +{ + m_baseDirEdit->setText(m_parent->getBaseDirectory()); + + QString basePath = parent->getBaseDirectory(); + QDir baseDir(basePath); + for (const auto &dir : { + std::make_pair(m_downloadDirEdit, m_parent->getDownloadDirectory(false)), + std::make_pair(m_modDirEdit, m_parent->getModDirectory(false)), + std::make_pair(m_cacheDirEdit, m_parent->getCacheDirectory(false)), + std::make_pair(m_profilesDirEdit, m_parent->getProfileDirectory(false)), + std::make_pair(m_overwriteDirEdit, m_parent->getOverwriteDirectory(false)) + }) { + QString storePath = baseDir.relativeFilePath(dir.second); + storePath = dir.second; + dir.first->setText(storePath); + } +} + +void Settings::PathsTab::update() +{ + typedef std::tuple Directory; + + QString basePath = m_parent->getBaseDirectory(); + + for (const Directory &dir :{ + Directory{m_downloadDirEdit->text(), "download_directory", AppConfig::downloadPath()}, + Directory{m_cacheDirEdit->text(), "cache_directory", AppConfig::cachePath()}, + Directory{m_modDirEdit->text(), "mod_directory", AppConfig::modsPath()}, + Directory{m_overwriteDirEdit->text(), "overwrite_directory", AppConfig::overwritePath()}, + Directory{m_profilesDirEdit->text(), "profiles_directory", AppConfig::profilesPath()} + }) { + QString path, settingsKey; + std::wstring defaultName; + std::tie(path, settingsKey, defaultName) = dir; + + settingsKey = QString("Settings/%1").arg(settingsKey); + + QString realPath = path; + realPath.replace("%BASE_DIR%", m_baseDirEdit->text()); + + if (!QDir(realPath).exists()) { + if (!QDir().mkpath(realPath)) { + QMessageBox::warning(qApp->activeWindow(), tr("Error"), + tr("Failed to create \"%1\", you may not have the " + "necessary permission. path remains unchanged.") + .arg(realPath)); + } + } + + if (QFileInfo(realPath) + != QFileInfo(basePath + "/" + QString::fromStdWString(defaultName))) { + m_Settings.setValue(settingsKey, path); + } else { + m_Settings.remove(settingsKey); + } + } + + if (QFileInfo(m_baseDirEdit->text()) != + QFileInfo(qApp->property("dataPath").toString())) { + m_Settings.setValue("Settings/base_directory", m_baseDirEdit->text()); + } else { + m_Settings.remove("Settings/base_directory"); + } +} + +Settings::DiagnosticsTab::DiagnosticsTab(Settings *m_parent, SettingsDialog &m_dialog) + : Settings::SettingsTab(m_parent, m_dialog) + , m_logLevelBox(m_dialog.findChild("logLevelBox")) + , m_dumpsTypeBox(m_dialog.findChild("dumpsTypeBox")) + , m_dumpsMaxEdit(m_dialog.findChild("dumpsMaxEdit")) + , m_diagnosticsExplainedLabel(m_dialog.findChild("diagnosticsExplainedLabel")) +{ + m_logLevelBox->setCurrentIndex(m_parent->logLevel()); + m_dumpsTypeBox->setCurrentIndex(m_parent->crashDumpsType()); + m_dumpsMaxEdit->setValue(m_parent->crashDumpsMax()); + QString logsPath = qApp->property("dataPath").toString() + + "/" + QString::fromStdWString(AppConfig::logPath()); + m_diagnosticsExplainedLabel->setText( + m_diagnosticsExplainedLabel->text() + .replace("LOGS_FULL_PATH", logsPath) + .replace("LOGS_DIR", QString::fromStdWString(AppConfig::logPath())) + .replace("DUMPS_FULL_PATH", QString::fromStdWString(OrganizerCore::crashDumpsPath())) + .replace("DUMPS_DIR", QString::fromStdWString(AppConfig::dumpsDir())) + ); +} + +void Settings::DiagnosticsTab::update() +{ + m_Settings.setValue("Settings/log_level", m_logLevelBox->currentIndex()); + m_Settings.setValue("Settings/crash_dumps_type", m_dumpsTypeBox->currentIndex()); + m_Settings.setValue("Settings/crash_dumps_max", m_dumpsMaxEdit->value()); +} + +Settings::NexusTab::NexusTab(Settings *parent, SettingsDialog &dialog) + : Settings::SettingsTab(parent, dialog) + , m_loginCheckBox(dialog.findChild("loginCheckBox")) + , m_usernameEdit(dialog.findChild("usernameEdit")) + , m_passwordEdit(dialog.findChild("passwordEdit")) + , m_offlineBox(dialog.findChild("offlineBox")) + , m_proxyBox(dialog.findChild("proxyBox")) + , m_knownServersList(dialog.findChild("knownServersList")) + , m_preferredServersList( + dialog.findChild("preferredServersList")) +{ + if (parent->automaticLoginEnabled()) { + m_loginCheckBox->setChecked(true); + m_usernameEdit->setText(m_Settings.value("Settings/nexus_username", "").toString()); + m_passwordEdit->setText(deObfuscate(m_Settings.value("Settings/nexus_password", "").toString())); + } + + m_offlineBox->setChecked(parent->offlineMode()); + m_proxyBox->setChecked(parent->useProxy()); + + // display server preferences + m_Settings.beginGroup("Servers"); + for (const QString &key : m_Settings.childKeys()) { + QVariantMap val = m_Settings.value(key).toMap(); + QString type = val["premium"].toBool() ? "(premium)" : "(free)"; + + QString descriptor = key + " " + type; + if (val.contains("downloadSpeed") && val.contains("downloadCount") && (val["downloadCount"].toInt() > 0)) { + int bps = static_cast(val["downloadSpeed"].toDouble() / val["downloadCount"].toInt()); + descriptor += QString(" (%1 kbps)").arg(bps / 1024); + } + + QListWidgetItem *newItem = new QListWidgetItemEx(descriptor, Qt::UserRole + 1); + + newItem->setData(Qt::UserRole, key); + newItem->setData(Qt::UserRole + 1, val["preferred"].toInt()); + if (val["preferred"].toInt() > 0) { + m_preferredServersList->addItem(newItem); + } else { + m_knownServersList->addItem(newItem); } - - m_mechanismBox->setCurrentIndex(index); - - m_nmmVersionEdit->setText(m_parent->getNMMVersion()); - m_hideUncheckedBox->setChecked(m_parent->hideUncheckedPlugins()); - m_forceEnableBox->setChecked(m_parent->forceEnableCoreFiles()); - m_displayForeignBox->setChecked(m_parent->displayForeign()); + m_preferredServersList->sortItems(Qt::DescendingOrder); + } + m_Settings.endGroup(); } -void Settings::WorkaroundsTab::update() { - if (m_appIDEdit->text() != m_parent->m_GamePlugin->steamAPPId()) { - m_Settings.setValue("Settings/app_id", m_appIDEdit->text()); - } else { - m_Settings.remove("Settings/app_id"); - } - m_Settings.setValue("Settings/load_mechanism", m_mechanismBox->itemData(m_mechanismBox->currentIndex()).toInt()); - m_Settings.setValue("Settings/nmm_version", m_nmmVersionEdit->text()); - m_Settings.setValue("Settings/hide_unchecked_plugins", m_hideUncheckedBox->isChecked()); - m_Settings.setValue("Settings/force_enable_core_files", m_forceEnableBox->isChecked()); - m_Settings.setValue("Settings/display_foreign", m_displayForeignBox->isChecked()); +void Settings::NexusTab::update() +{ + if (m_loginCheckBox->isChecked()) { + m_Settings.setValue("Settings/nexus_login", true); + m_Settings.setValue("Settings/nexus_username", m_usernameEdit->text()); + m_Settings.setValue("Settings/nexus_password", obfuscate(m_passwordEdit->text())); + } else { + m_Settings.setValue("Settings/nexus_login", false); + m_Settings.remove("Settings/nexus_username"); + m_Settings.remove("Settings/nexus_password"); + } + m_Settings.setValue("Settings/offline_mode", m_offlineBox->isChecked()); + m_Settings.setValue("Settings/use_proxy", m_proxyBox->isChecked()); + + // store server preference + m_Settings.beginGroup("Servers"); + for (int i = 0; i < m_knownServersList->count(); ++i) { + QString key = m_knownServersList->item(i)->data(Qt::UserRole).toString(); + QVariantMap val = m_Settings.value(key).toMap(); + val["preferred"] = 0; + m_Settings.setValue(key, val); + } + int count = m_preferredServersList->count(); + for (int i = 0; i < count; ++i) { + QString key = m_preferredServersList->item(i)->data(Qt::UserRole).toString(); + QVariantMap val = m_Settings.value(key).toMap(); + val["preferred"] = count - i; + m_Settings.setValue(key, val); + } + m_Settings.endGroup(); +} + +Settings::SteamTab::SteamTab(Settings *m_parent, SettingsDialog &m_dialog) + : Settings::SettingsTab(m_parent, m_dialog) + , m_steamUserEdit(m_dialog.findChild("steamUserEdit")) + , m_steamPassEdit(m_dialog.findChild("steamPassEdit")) +{ + if (m_Settings.contains("Settings/steam_username")) { + m_steamUserEdit->setText(m_Settings.value("Settings/steam_username", "").toString()); + if (m_Settings.contains("Settings/steam_password")) { + m_steamPassEdit->setText(deObfuscate(m_Settings.value("Settings/steam_password", "").toString())); + } + } +} + +void Settings::SteamTab::update() +{ + //FIXME this should be inlined here? + m_parent->setSteamLogin(m_steamUserEdit->text(), m_steamPassEdit->text()); +} + +Settings::PluginsTab::PluginsTab(Settings *m_parent, SettingsDialog &m_dialog) + : Settings::SettingsTab(m_parent, m_dialog) + , m_pluginsList(m_dialog.findChild("pluginsList")) + , m_pluginBlacklistList(m_dialog.findChild("pluginBlacklist")) +{ + // display plugin settings + for (IPlugin *plugin : m_parent->m_Plugins) { + QListWidgetItem *listItem = new QListWidgetItem(plugin->name(), m_pluginsList); + listItem->setData(Qt::UserRole, QVariant::fromValue((void*)plugin)); + listItem->setData(Qt::UserRole + 1, m_parent->m_PluginSettings[plugin->name()]); + listItem->setData(Qt::UserRole + 2, m_parent->m_PluginDescriptions[plugin->name()]); + m_pluginsList->addItem(listItem); + } + + // display plugin blacklist + for (const QString &pluginName : m_parent->m_PluginBlacklist) { + m_pluginBlacklistList->addItem(pluginName); + } +} + +void Settings::PluginsTab::update() +{ + // transfer plugin settings to in-memory structure + for (int i = 0; i < m_pluginsList->count(); ++i) { + QListWidgetItem *item = m_pluginsList->item(i); + m_parent->m_PluginSettings[item->text()] = item->data(Qt::UserRole + 1).toMap(); + } + // store plugin settings on disc + for (auto iterPlugins = m_parent->m_PluginSettings.begin(); iterPlugins != m_parent->m_PluginSettings.end(); ++iterPlugins) { + for (auto iterSettings = iterPlugins->begin(); iterSettings != iterPlugins->end(); ++iterSettings) { + m_Settings.setValue("Plugins/" + iterPlugins.key() + "/" + iterSettings.key(), iterSettings.value()); + } + } + + // store plugin blacklist + m_parent->m_PluginBlacklist.clear(); + for (QListWidgetItem *item : m_pluginBlacklistList->findItems("*", Qt::MatchWildcard)) { + m_parent->m_PluginBlacklist.insert(item->text()); + } + m_parent->writePluginBlacklist(); +} + +Settings::WorkaroundsTab::WorkaroundsTab(Settings *m_parent, + SettingsDialog &m_dialog) + : Settings::SettingsTab(m_parent, m_dialog) + , m_appIDEdit(m_dialog.findChild("appIDEdit")) + , m_mechanismBox(m_dialog.findChild("mechanismBox")) + , m_nmmVersionEdit(m_dialog.findChild("nmmVersionEdit")) + , m_hideUncheckedBox(m_dialog.findChild("hideUncheckedBox")) + , m_forceEnableBox(m_dialog.findChild("forceEnableBox")) + , m_displayForeignBox(m_dialog.findChild("displayForeignBox")) +{ + m_appIDEdit->setText(m_parent->getSteamAppID()); + + LoadMechanism::EMechanism mechanismID = m_parent->getLoadMechanism(); + int index = 0; + + if (m_parent->m_LoadMechanism.isDirectLoadingSupported()) { + m_mechanismBox->addItem(QObject::tr("Mod Organizer"), LoadMechanism::LOAD_MODORGANIZER); + if (mechanismID == LoadMechanism::LOAD_MODORGANIZER) { + index = m_mechanismBox->count() - 1; + } + } + + if (m_parent->m_LoadMechanism.isScriptExtenderSupported()) { + m_mechanismBox->addItem(QObject::tr("Script Extender"), LoadMechanism::LOAD_SCRIPTEXTENDER); + if (mechanismID == LoadMechanism::LOAD_SCRIPTEXTENDER) { + index = m_mechanismBox->count() - 1; + } + } + + if (m_parent->m_LoadMechanism.isProxyDLLSupported()) { + m_mechanismBox->addItem(QObject::tr("Proxy DLL"), LoadMechanism::LOAD_PROXYDLL); + if (mechanismID == LoadMechanism::LOAD_PROXYDLL) { + index = m_mechanismBox->count() - 1; + } + } + + m_mechanismBox->setCurrentIndex(index); + + m_nmmVersionEdit->setText(m_parent->getNMMVersion()); + m_hideUncheckedBox->setChecked(m_parent->hideUncheckedPlugins()); + m_forceEnableBox->setChecked(m_parent->forceEnableCoreFiles()); + m_displayForeignBox->setChecked(m_parent->displayForeign()); + +} + +void Settings::WorkaroundsTab::update() +{ + if (m_appIDEdit->text() != m_parent->m_GamePlugin->steamAPPId()) { + m_Settings.setValue("Settings/app_id", m_appIDEdit->text()); + } else { + m_Settings.remove("Settings/app_id"); + } + m_Settings.setValue("Settings/load_mechanism", m_mechanismBox->itemData(m_mechanismBox->currentIndex()).toInt()); + m_Settings.setValue("Settings/nmm_version", m_nmmVersionEdit->text()); + m_Settings.setValue("Settings/hide_unchecked_plugins", m_hideUncheckedBox->isChecked()); + m_Settings.setValue("Settings/force_enable_core_files", m_forceEnableBox->isChecked()); + m_Settings.setValue("Settings/display_foreign", m_displayForeignBox->isChecked()); } -- cgit v1.3.1