summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTannin <devnull@localhost>2014-09-10 20:34:31 +0200
committerTannin <devnull@localhost>2014-09-10 20:34:31 +0200
commitb0a4748da5ffbb5010656d57bbb16912c616ef71 (patch)
tree632078b12eda1503c23855963546f55adda2631b
parent9daeb9479bd2675d0feef1e1f7bffb3f73361e30 (diff)
- descriptions for plugin settings are now displayed
-rw-r--r--src/settings.cpp1464
-rw-r--r--src/settings.h621
-rw-r--r--src/settingsdialog.cpp355
3 files changed, 1227 insertions, 1213 deletions
diff --git a/src/settings.cpp b/src/settings.cpp
index 293a06ab..146896db 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -1,730 +1,734 @@
-/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "settings.h"
-
-#include "settingsdialog.h"
-#include "utility.h"
-#include "helper.h"
-#include <gameinfo.h>
-#include <appconfig.h>
-#include <utility.h>
-#include <json.h>
-
-#include <QCheckBox>
-#include <QLineEdit>
-#include <QDirIterator>
-#include <QRegExp>
-#include <QCoreApplication>
-#include <QMessageBox>
-#include <QDesktopServices>
-
-
-using namespace MOBase;
-using namespace MOShared;
-
-
-template <typename T>
-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<T>() < other.data(m_SortRole).value<T>();
- }
-private:
- 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 = NULL;
-
-
-Settings::Settings()
- : m_Settings(ToQString(GameInfo::instance().getIniFilename()), QSettings::IniFormat)
-{
- if (s_Instance != NULL) {
- throw std::runtime_error("second instance of \"Settings\" created");
- } else {
- s_Instance = this;
- }
-}
-
-
-Settings::~Settings()
-{
- s_Instance = NULL;
-}
-
-
-Settings &Settings::instance()
-{
- if (s_Instance == NULL) {
- throw std::runtime_error("no instance of \"Settings\"");
- }
- return *s_Instance;
-}
-
-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();
-}
-
-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" " + GameInfo::instance().getGameShortName() + L" \"" + executable + L"\"";
- HINSTANCE res = ::ShellExecuteW(NULL, L"open", nxmPath.c_str(), parameters.c_str(), NULL, SW_SHOWNORMAL);
- if ((int)res <= 32) {
- QMessageBox::critical(NULL, tr("Failed"),
- tr("Sorry, failed to start the helper application"));
- }
-}
-
-void Settings::registerPlugin(IPlugin *plugin)
-{
- m_Plugins.push_back(plugin);
- m_PluginSettings.insert(plugin->name(), QMap<QString, QVariant>());
- foreach (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;
- }
-}
-
-QString Settings::obfuscate(const QString &password) const
-{
- QByteArray temp = password.toUtf8();
-
- QByteArray buffer;
- for (int i = 0; i < temp.length(); ++i) {
- buffer.append(temp.at(i) ^ Key2[i % 20]);
- }
- return buffer.toBase64();
-}
-
-
-QString Settings::deObfuscate(const QString &password) const
-{
- 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());
-}
-
-
-bool Settings::hideUncheckedPlugins() const
-{
- return m_Settings.value("Settings/hide_unchecked_plugins", false).toBool();
-}
-
-bool Settings::forceEnableCoreFiles() const
-{
- return m_Settings.value("Settings/force_enable_core_files", true).toBool();
-}
-
-bool Settings::automaticLoginEnabled() const
-{
- return m_Settings.value("Settings/nexus_login", false).toBool();
-}
-
-QString Settings::getSteamAppID() const
-{
- return m_Settings.value("Settings/app_id", ToQString(GameInfo::instance().getSteamAPPId(m_Settings.value("game_edition", 0).toInt()))).toString();
-}
-
-QString Settings::getDownloadDirectory() const
-{
- return QDir::toNativeSeparators(m_Settings.value("Settings/download_directory", ToQString(GameInfo::instance().getDownloadDir())).toString());
-}
-
-
-void Settings::setDownloadSpeed(const QString &serverName, int bytesPerSecond)
-{
- m_Settings.beginGroup("Servers");
-
- foreach (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<double>(bytesPerSecond);
- m_Settings.setValue(serverKey, data);
- }
- }
-
- m_Settings.endGroup();
- m_Settings.sync();
-}
-
-std::map<QString, int> Settings::getPreferredServers()
-{
- std::map<QString, int> result;
- m_Settings.beginGroup("Servers");
-
- foreach (const QString &serverKey, m_Settings.childKeys()) {
- QVariantMap data = m_Settings.value(serverKey).toMap();
- int preference = data["preferred"].toInt();
- if (preference > 0) {
- result[serverKey] = preference;
- }
- }
- m_Settings.endGroup();
-
- return result;
-}
-
-QString Settings::getCacheDirectory() const
-{
- return QDir::toNativeSeparators(m_Settings.value("Settings/cache_directory", ToQString(GameInfo::instance().getCacheDir())).toString());
-}
-
-QString Settings::getModDirectory() const
-{
- return QDir::toNativeSeparators(m_Settings.value("Settings/mod_directory", ToQString(GameInfo::instance().getModsDir())).toString());
-}
-
-QString Settings::getNMMVersion() const
-{
- static const QString MIN_NMM_VERSION = "0.47.0";
- 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::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;
- }
-}
-
-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", 0).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));
-}
-
-
-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");
-}
-
-
-void Settings::setupLoadMechanism()
-{
- m_LoadMechanism.activate(getLoadMechanism());
-}
-
-
-bool Settings::useProxy()
-{
- return m_Settings.value("Settings/use_proxy", false).toBool();
-}
-
-bool Settings::displayForeign()
-{
- 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;
-}
-
-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);
-}
-
-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::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();
- }
-}
-
-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::updateServers(const QList<ServerInfo> &servers)
-{
- m_Settings.beginGroup("Servers");
- QStringList oldServerKeys = m_Settings.childKeys();
-
- foreach (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;
-
- m_Settings.setValue(server.name, data);
- }
- }
-
- m_Settings.endGroup();
- m_Settings.sync();
-}
-
-void Settings::addBlacklistPlugin(const QString &fileName)
-{
- m_PluginBlacklist.insert(fileName);
- writePluginBlacklist();
-}
-
-void Settings::writePluginBlacklist()
-{
- m_Settings.beginWriteArray("pluginBlacklist");
- int idx = 0;
- foreach (const QString &plugin, m_PluginBlacklist) {
- m_Settings.setArrayIndex(idx++);
- m_Settings.setValue("name", plugin);
- }
-
- m_Settings.endArray();
-}
-
-void Settings::addLanguages(QComboBox *languageBox)
-{
- languageBox->addItem("English", "en_US");
-
- 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 = QLocale::languageToString(locale.language());
- if (locale.language() == QLocale::Chinese) {
- if (languageCode == "zh_TW") {
- languageString = "Chinese (traditional)";
- } else {
- languageString = "Chinese (simplified)";
- }
- }
- languageBox->addItem(QString("%1").arg(languageString), exp.cap(1));
- }
- }
-}
-
-void Settings::addStyles(QComboBox *styleBox)
-{
- styleBox->addItem("None", "");
-#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
- styleBox->addItem("Fusion", "Fusion");
-#else
- styleBox->addItem("Plastique", "Plastique");
- styleBox->addItem("Cleanlooks", "Cleanlooks");
-#endif
-
- 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()
-{
- m_Settings.beginGroup("DialogChoices");
- QStringList keys = m_Settings.childKeys();
- foreach (QString key, keys) {
- m_Settings.remove(key);
- }
-
- m_Settings.endGroup();
-}
-
-
-void Settings::query(QWidget *parent)
-{
- SettingsDialog dialog(parent);
-
- connect(&dialog, SIGNAL(resetDialogs()), this, SLOT(resetDialogs()));
-
- // General Page
- QComboBox *languageBox = dialog.findChild<QComboBox*>("languageBox");
- QComboBox *styleBox = dialog.findChild<QComboBox*>("styleBox");
- QComboBox *logLevelBox = dialog.findChild<QComboBox*>("logLevelBox");
- QCheckBox *compactBox = dialog.findChild<QCheckBox*>("compactBox");
- QCheckBox *showMetaBox = dialog.findChild<QCheckBox*>("showMetaBox");
-
- QLineEdit *downloadDirEdit = dialog.findChild<QLineEdit*>("downloadDirEdit");
- QLineEdit *modDirEdit = dialog.findChild<QLineEdit*>("modDirEdit");
- QLineEdit *cacheDirEdit = dialog.findChild<QLineEdit*>("cacheDirEdit");
-
- // nexus page
- QCheckBox *loginCheckBox = dialog.findChild<QCheckBox*>("loginCheckBox");
- QLineEdit *usernameEdit = dialog.findChild<QLineEdit*>("usernameEdit");
- QLineEdit *passwordEdit = dialog.findChild<QLineEdit*>("passwordEdit");
- QCheckBox *offlineBox = dialog.findChild<QCheckBox*>("offlineBox");
- QCheckBox *proxyBox = dialog.findChild<QCheckBox*>("proxyBox");
-
- QListWidget *knownServersList = dialog.findChild<QListWidget*>("knownServersList");
- QListWidget *preferredServersList = dialog.findChild<QListWidget*>("preferredServersList");
-
- // plugis page
- QListWidget *pluginsList = dialog.findChild<QListWidget*>("pluginsList");
- QListWidget *pluginBlacklistList = dialog.findChild<QListWidget*>("pluginBlacklist");
-
- // workarounds page
- QCheckBox *forceEnableBox = dialog.findChild<QCheckBox*>("forceEnableBox");
- QComboBox *mechanismBox = dialog.findChild<QComboBox*>("mechanismBox");
- QLineEdit *appIDEdit = dialog.findChild<QLineEdit*>("appIDEdit");
- QLineEdit *nmmVersionEdit = dialog.findChild<QLineEdit*>("nmmVersionEdit");
- QCheckBox *hideUncheckedBox = dialog.findChild<QCheckBox*>("hideUncheckedBox");
- QCheckBox *displayForeignBox = dialog.findChild<QCheckBox*>("displayForeignBox");
-
-
- //
- // set up current settings
- //
- LoadMechanism::EMechanism mechanismID = getLoadMechanism();
- int index = 0;
-
- if (m_LoadMechanism.isDirectLoadingSupported()) {
- mechanismBox->addItem(QObject::tr("Mod Organizer"), LoadMechanism::LOAD_MODORGANIZER);
- if (mechanismID == LoadMechanism::LOAD_MODORGANIZER) {
- index = mechanismBox->count() - 1;
- }
- }
-
- if (m_LoadMechanism.isScriptExtenderSupported()) {
- mechanismBox->addItem(QObject::tr("Script Extender"), LoadMechanism::LOAD_SCRIPTEXTENDER);
- if (mechanismID == LoadMechanism::LOAD_SCRIPTEXTENDER) {
- index = mechanismBox->count() - 1;
- }
- }
-
- if (m_LoadMechanism.isProxyDLLSupported()) {
- mechanismBox->addItem(QObject::tr("Proxy DLL"), LoadMechanism::LOAD_PROXYDLL);
- if (mechanismID == LoadMechanism::LOAD_PROXYDLL) {
- index = mechanismBox->count() - 1;
- }
- }
-
- mechanismBox->setCurrentIndex(index);
-
- {
- addLanguages(languageBox);
- QString languageCode = language();
- int currentID = 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 = languageBox->findData(languageCode.mid(0, 2));
- }
- if (currentID != -1) {
- languageBox->setCurrentIndex(currentID);
- }
- }
-
- {
- addStyles(styleBox);
- int currentID = styleBox->findData(m_Settings.value("Settings/style", "").toString());
- if (currentID != -1) {
- styleBox->setCurrentIndex(currentID);
- }
- }
-
- compactBox->setChecked(compactDownloads());
- showMetaBox->setChecked(metaDownloads());
-
- hideUncheckedBox->setChecked(hideUncheckedPlugins());
- displayForeignBox->setChecked(displayForeign());
- forceEnableBox->setChecked(forceEnableCoreFiles());
-
- appIDEdit->setText(getSteamAppID());
-
- if (automaticLoginEnabled()) {
- loginCheckBox->setChecked(true);
- usernameEdit->setText(m_Settings.value("Settings/nexus_username", "").toString());
- passwordEdit->setText(deObfuscate(m_Settings.value("Settings/nexus_password", "").toString()));
- }
-
- downloadDirEdit->setText(getDownloadDirectory());
- modDirEdit->setText(getModDirectory());
- cacheDirEdit->setText(getCacheDirectory());
- offlineBox->setChecked(offlineMode());
- proxyBox->setChecked(useProxy());
- nmmVersionEdit->setText(getNMMVersion());
- logLevelBox->setCurrentIndex(logLevel());
-
- // display plugin settings
- foreach (IPlugin *plugin, m_Plugins) {
- QListWidgetItem *listItem = new QListWidgetItem(plugin->name(), pluginsList);
- listItem->setData(Qt::UserRole, QVariant::fromValue((void*)plugin));
- listItem->setData(Qt::UserRole + 1, m_PluginSettings[plugin->name()]);
- pluginsList->addItem(listItem);
- }
-
- // display plugin blacklist
- foreach (const QString &pluginName, m_PluginBlacklist) {
- pluginBlacklistList->addItem(pluginName);
- }
-
- // display server preferences
- m_Settings.beginGroup("Servers");
- foreach (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<int>(val["downloadSpeed"].toDouble() / val["downloadCount"].toInt());
- descriptor += QString(" (%1 kbps)").arg(bps / 1024);
- }
-
- QListWidgetItem *newItem = new QListWidgetItemEx<int>(descriptor, Qt::UserRole + 1);
-
- newItem->setData(Qt::UserRole, key);
- newItem->setData(Qt::UserRole + 1, val["preferred"].toInt());
- if (val["preferred"].toInt() > 0) {
- preferredServersList->addItem(newItem);
- } else {
- knownServersList->addItem(newItem);
- }
- preferredServersList->sortItems(Qt::DescendingOrder);
- }
- m_Settings.endGroup();
-
- if (dialog.exec() == QDialog::Accepted) {
- //
- // transfer modified settings to configuration file
- //
-
- m_Settings.setValue("Settings/hide_unchecked_plugins", hideUncheckedBox->checkState() ? true : false);
- m_Settings.setValue("Settings/force_enable_core_files", forceEnableBox->checkState() ? true : false);
- m_Settings.setValue("Settings/compact_downloads", compactBox->isChecked());
- m_Settings.setValue("Settings/meta_downloads", showMetaBox->isChecked());
- m_Settings.setValue("Settings/load_mechanism", mechanismBox->itemData(mechanismBox->currentIndex()).toInt());
- if (QDir(downloadDirEdit->text()).exists()) {
- m_Settings.setValue("Settings/download_directory", QDir::toNativeSeparators(downloadDirEdit->text()));
- }
- if (!QDir(cacheDirEdit->text()).exists()) {
- QDir().mkpath(cacheDirEdit->text());
- }
- m_Settings.setValue("Settings/cache_directory", QDir::toNativeSeparators(cacheDirEdit->text()));
- if (QDir(modDirEdit->text()).exists()) {
- if ((QDir::fromNativeSeparators(modDirEdit->text()) != QDir::fromNativeSeparators(getModDirectory())) &&
- (QMessageBox::question(NULL, tr("Confirm"), tr("Changing the mod directory affects all your profiles! "
- "Mods not present (or named differently) in the new location will be disabled in all profiles. "
- "There is no way to undo this unless you backed up your profiles manually. Proceed?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)) {
- m_Settings.setValue("Settings/mod_directory", QDir::toNativeSeparators(modDirEdit->text()));
- }
- }
- QString oldLanguage = m_Settings.value("Settings/language", "en_US").toString();
- QString newLanguage = languageBox->itemData(languageBox->currentIndex()).toString();
- if (newLanguage != oldLanguage) {
- m_Settings.setValue("Settings/language", newLanguage);
- emit languageChanged(newLanguage);
- }
-
- QString oldStyle = m_Settings.value("Settings/style", "").toString();
- QString newStyle = styleBox->itemData(styleBox->currentIndex()).toString();
- if (oldStyle != newStyle) {
- m_Settings.setValue("Settings/style", newStyle);
- emit styleChanged(newStyle);
- }
-
- m_Settings.setValue("Settings/log_level", logLevelBox->currentIndex());
-
- if (appIDEdit->text() != ToQString(GameInfo::instance().getSteamAPPId())) {
- m_Settings.setValue("Settings/app_id", appIDEdit->text());
- } else {
- m_Settings.remove("Settings/app_id");
- }
- if (loginCheckBox->isChecked()) {
- m_Settings.setValue("Settings/nexus_login", true);
- m_Settings.setValue("Settings/nexus_username", usernameEdit->text());
- m_Settings.setValue("Settings/nexus_password", obfuscate(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", offlineBox->isChecked());
- m_Settings.setValue("Settings/use_proxy", proxyBox->isChecked());
- m_Settings.setValue("Settings/display_foreign", displayForeignBox->isChecked());
-
- m_Settings.setValue("Settings/nmm_version", nmmVersionEdit->text());
-
- // transfer plugin settings to in-memory structure
- for (int i = 0; i < pluginsList->count(); ++i) {
- QListWidgetItem *item = pluginsList->item(i);
- m_PluginSettings[item->text()] = item->data(Qt::UserRole + 1).toMap();
- }
- // store plugin settings on disc
- for (auto iterPlugins = m_PluginSettings.begin(); iterPlugins != 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_PluginBlacklist.clear();
- foreach (QListWidgetItem *item, pluginBlacklistList->findItems("*", Qt::MatchWildcard)) {
- m_PluginBlacklist.insert(item->text());
- }
- writePluginBlacklist();
-
- // store server preference
- m_Settings.beginGroup("Servers");
- for (int i = 0; i < knownServersList->count(); ++i) {
- QString key = knownServersList->item(i)->data(Qt::UserRole).toString();
- QVariantMap val = m_Settings.value(key).toMap();
- val["preferred"] = 0;
- m_Settings.setValue(key, val);
- }
- int count = preferredServersList->count();
- for (int i = 0; i < count; ++i) {
- QString key = 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();
- }
-}
+/*
+Copyright (C) 2012 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "settings.h"
+
+#include "settingsdialog.h"
+#include "utility.h"
+#include "helper.h"
+#include <gameinfo.h>
+#include <appconfig.h>
+#include <utility.h>
+#include <json.h>
+
+#include <QCheckBox>
+#include <QLineEdit>
+#include <QDirIterator>
+#include <QRegExp>
+#include <QCoreApplication>
+#include <QMessageBox>
+#include <QDesktopServices>
+
+
+using namespace MOBase;
+using namespace MOShared;
+
+
+template <typename T>
+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<T>() < other.data(m_SortRole).value<T>();
+ }
+private:
+ 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 = NULL;
+
+
+Settings::Settings()
+ : m_Settings(ToQString(GameInfo::instance().getIniFilename()), QSettings::IniFormat)
+{
+ if (s_Instance != NULL) {
+ throw std::runtime_error("second instance of \"Settings\" created");
+ } else {
+ s_Instance = this;
+ }
+}
+
+
+Settings::~Settings()
+{
+ s_Instance = NULL;
+}
+
+
+Settings &Settings::instance()
+{
+ if (s_Instance == NULL) {
+ throw std::runtime_error("no instance of \"Settings\"");
+ }
+ return *s_Instance;
+}
+
+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();
+}
+
+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" " + GameInfo::instance().getGameShortName() + L" \"" + executable + L"\"";
+ HINSTANCE res = ::ShellExecuteW(NULL, L"open", nxmPath.c_str(), parameters.c_str(), NULL, SW_SHOWNORMAL);
+ if ((int)res <= 32) {
+ QMessageBox::critical(NULL, tr("Failed"),
+ tr("Sorry, failed to start the helper application"));
+ }
+}
+
+void Settings::registerPlugin(IPlugin *plugin)
+{
+ m_Plugins.push_back(plugin);
+ m_PluginSettings.insert(plugin->name(), QMap<QString, QVariant>());
+ m_PluginDescriptions.insert(plugin->name(), QMap<QString, QVariant>());
+ foreach (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());
+ }
+}
+
+
+QString Settings::obfuscate(const QString &password) const
+{
+ QByteArray temp = password.toUtf8();
+
+ QByteArray buffer;
+ for (int i = 0; i < temp.length(); ++i) {
+ buffer.append(temp.at(i) ^ Key2[i % 20]);
+ }
+ return buffer.toBase64();
+}
+
+
+QString Settings::deObfuscate(const QString &password) const
+{
+ 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());
+}
+
+
+bool Settings::hideUncheckedPlugins() const
+{
+ return m_Settings.value("Settings/hide_unchecked_plugins", false).toBool();
+}
+
+bool Settings::forceEnableCoreFiles() const
+{
+ return m_Settings.value("Settings/force_enable_core_files", true).toBool();
+}
+
+bool Settings::automaticLoginEnabled() const
+{
+ return m_Settings.value("Settings/nexus_login", false).toBool();
+}
+
+QString Settings::getSteamAppID() const
+{
+ return m_Settings.value("Settings/app_id", ToQString(GameInfo::instance().getSteamAPPId(m_Settings.value("game_edition", 0).toInt()))).toString();
+}
+
+QString Settings::getDownloadDirectory() const
+{
+ return QDir::toNativeSeparators(m_Settings.value("Settings/download_directory", ToQString(GameInfo::instance().getDownloadDir())).toString());
+}
+
+
+void Settings::setDownloadSpeed(const QString &serverName, int bytesPerSecond)
+{
+ m_Settings.beginGroup("Servers");
+
+ foreach (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<double>(bytesPerSecond);
+ m_Settings.setValue(serverKey, data);
+ }
+ }
+
+ m_Settings.endGroup();
+ m_Settings.sync();
+}
+
+std::map<QString, int> Settings::getPreferredServers()
+{
+ std::map<QString, int> result;
+ m_Settings.beginGroup("Servers");
+
+ foreach (const QString &serverKey, m_Settings.childKeys()) {
+ QVariantMap data = m_Settings.value(serverKey).toMap();
+ int preference = data["preferred"].toInt();
+ if (preference > 0) {
+ result[serverKey] = preference;
+ }
+ }
+ m_Settings.endGroup();
+
+ return result;
+}
+
+QString Settings::getCacheDirectory() const
+{
+ return QDir::toNativeSeparators(m_Settings.value("Settings/cache_directory", ToQString(GameInfo::instance().getCacheDir())).toString());
+}
+
+QString Settings::getModDirectory() const
+{
+ return QDir::toNativeSeparators(m_Settings.value("Settings/mod_directory", ToQString(GameInfo::instance().getModsDir())).toString());
+}
+
+QString Settings::getNMMVersion() const
+{
+ static const QString MIN_NMM_VERSION = "0.47.0";
+ 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::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;
+ }
+}
+
+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", 0).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));
+}
+
+
+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");
+}
+
+
+void Settings::setupLoadMechanism()
+{
+ m_LoadMechanism.activate(getLoadMechanism());
+}
+
+
+bool Settings::useProxy()
+{
+ return m_Settings.value("Settings/use_proxy", false).toBool();
+}
+
+bool Settings::displayForeign()
+{
+ 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;
+}
+
+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);
+}
+
+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::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();
+ }
+}
+
+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::updateServers(const QList<ServerInfo> &servers)
+{
+ m_Settings.beginGroup("Servers");
+ QStringList oldServerKeys = m_Settings.childKeys();
+
+ foreach (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;
+
+ m_Settings.setValue(server.name, data);
+ }
+ }
+
+ m_Settings.endGroup();
+ m_Settings.sync();
+}
+
+void Settings::addBlacklistPlugin(const QString &fileName)
+{
+ m_PluginBlacklist.insert(fileName);
+ writePluginBlacklist();
+}
+
+void Settings::writePluginBlacklist()
+{
+ m_Settings.beginWriteArray("pluginBlacklist");
+ int idx = 0;
+ foreach (const QString &plugin, m_PluginBlacklist) {
+ m_Settings.setArrayIndex(idx++);
+ m_Settings.setValue("name", plugin);
+ }
+
+ m_Settings.endArray();
+}
+
+void Settings::addLanguages(QComboBox *languageBox)
+{
+ languageBox->addItem("English", "en_US");
+
+ 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 = QLocale::languageToString(locale.language());
+ if (locale.language() == QLocale::Chinese) {
+ if (languageCode == "zh_TW") {
+ languageString = "Chinese (traditional)";
+ } else {
+ languageString = "Chinese (simplified)";
+ }
+ }
+ languageBox->addItem(QString("%1").arg(languageString), exp.cap(1));
+ }
+ }
+}
+
+void Settings::addStyles(QComboBox *styleBox)
+{
+ styleBox->addItem("None", "");
+#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
+ styleBox->addItem("Fusion", "Fusion");
+#else
+ styleBox->addItem("Plastique", "Plastique");
+ styleBox->addItem("Cleanlooks", "Cleanlooks");
+#endif
+
+ 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()
+{
+ m_Settings.beginGroup("DialogChoices");
+ QStringList keys = m_Settings.childKeys();
+ foreach (QString key, keys) {
+ m_Settings.remove(key);
+ }
+
+ m_Settings.endGroup();
+}
+
+
+void Settings::query(QWidget *parent)
+{
+ SettingsDialog dialog(parent);
+
+ connect(&dialog, SIGNAL(resetDialogs()), this, SLOT(resetDialogs()));
+
+ // General Page
+ QComboBox *languageBox = dialog.findChild<QComboBox*>("languageBox");
+ QComboBox *styleBox = dialog.findChild<QComboBox*>("styleBox");
+ QComboBox *logLevelBox = dialog.findChild<QComboBox*>("logLevelBox");
+ QCheckBox *compactBox = dialog.findChild<QCheckBox*>("compactBox");
+ QCheckBox *showMetaBox = dialog.findChild<QCheckBox*>("showMetaBox");
+
+ QLineEdit *downloadDirEdit = dialog.findChild<QLineEdit*>("downloadDirEdit");
+ QLineEdit *modDirEdit = dialog.findChild<QLineEdit*>("modDirEdit");
+ QLineEdit *cacheDirEdit = dialog.findChild<QLineEdit*>("cacheDirEdit");
+
+ // nexus page
+ QCheckBox *loginCheckBox = dialog.findChild<QCheckBox*>("loginCheckBox");
+ QLineEdit *usernameEdit = dialog.findChild<QLineEdit*>("usernameEdit");
+ QLineEdit *passwordEdit = dialog.findChild<QLineEdit*>("passwordEdit");
+ QCheckBox *offlineBox = dialog.findChild<QCheckBox*>("offlineBox");
+ QCheckBox *proxyBox = dialog.findChild<QCheckBox*>("proxyBox");
+
+ QListWidget *knownServersList = dialog.findChild<QListWidget*>("knownServersList");
+ QListWidget *preferredServersList = dialog.findChild<QListWidget*>("preferredServersList");
+
+ // plugis page
+ QListWidget *pluginsList = dialog.findChild<QListWidget*>("pluginsList");
+ QListWidget *pluginBlacklistList = dialog.findChild<QListWidget*>("pluginBlacklist");
+
+ // workarounds page
+ QCheckBox *forceEnableBox = dialog.findChild<QCheckBox*>("forceEnableBox");
+ QComboBox *mechanismBox = dialog.findChild<QComboBox*>("mechanismBox");
+ QLineEdit *appIDEdit = dialog.findChild<QLineEdit*>("appIDEdit");
+ QLineEdit *nmmVersionEdit = dialog.findChild<QLineEdit*>("nmmVersionEdit");
+ QCheckBox *hideUncheckedBox = dialog.findChild<QCheckBox*>("hideUncheckedBox");
+ QCheckBox *displayForeignBox = dialog.findChild<QCheckBox*>("displayForeignBox");
+
+
+ //
+ // set up current settings
+ //
+ LoadMechanism::EMechanism mechanismID = getLoadMechanism();
+ int index = 0;
+
+ if (m_LoadMechanism.isDirectLoadingSupported()) {
+ mechanismBox->addItem(QObject::tr("Mod Organizer"), LoadMechanism::LOAD_MODORGANIZER);
+ if (mechanismID == LoadMechanism::LOAD_MODORGANIZER) {
+ index = mechanismBox->count() - 1;
+ }
+ }
+
+ if (m_LoadMechanism.isScriptExtenderSupported()) {
+ mechanismBox->addItem(QObject::tr("Script Extender"), LoadMechanism::LOAD_SCRIPTEXTENDER);
+ if (mechanismID == LoadMechanism::LOAD_SCRIPTEXTENDER) {
+ index = mechanismBox->count() - 1;
+ }
+ }
+
+ if (m_LoadMechanism.isProxyDLLSupported()) {
+ mechanismBox->addItem(QObject::tr("Proxy DLL"), LoadMechanism::LOAD_PROXYDLL);
+ if (mechanismID == LoadMechanism::LOAD_PROXYDLL) {
+ index = mechanismBox->count() - 1;
+ }
+ }
+
+ mechanismBox->setCurrentIndex(index);
+
+ {
+ addLanguages(languageBox);
+ QString languageCode = language();
+ int currentID = 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 = languageBox->findData(languageCode.mid(0, 2));
+ }
+ if (currentID != -1) {
+ languageBox->setCurrentIndex(currentID);
+ }
+ }
+
+ {
+ addStyles(styleBox);
+ int currentID = styleBox->findData(m_Settings.value("Settings/style", "").toString());
+ if (currentID != -1) {
+ styleBox->setCurrentIndex(currentID);
+ }
+ }
+
+ compactBox->setChecked(compactDownloads());
+ showMetaBox->setChecked(metaDownloads());
+
+ hideUncheckedBox->setChecked(hideUncheckedPlugins());
+ displayForeignBox->setChecked(displayForeign());
+ forceEnableBox->setChecked(forceEnableCoreFiles());
+
+ appIDEdit->setText(getSteamAppID());
+
+ if (automaticLoginEnabled()) {
+ loginCheckBox->setChecked(true);
+ usernameEdit->setText(m_Settings.value("Settings/nexus_username", "").toString());
+ passwordEdit->setText(deObfuscate(m_Settings.value("Settings/nexus_password", "").toString()));
+ }
+
+ downloadDirEdit->setText(getDownloadDirectory());
+ modDirEdit->setText(getModDirectory());
+ cacheDirEdit->setText(getCacheDirectory());
+ offlineBox->setChecked(offlineMode());
+ proxyBox->setChecked(useProxy());
+ nmmVersionEdit->setText(getNMMVersion());
+ logLevelBox->setCurrentIndex(logLevel());
+
+ // display plugin settings
+ foreach (IPlugin *plugin, m_Plugins) {
+ QListWidgetItem *listItem = new QListWidgetItem(plugin->name(), pluginsList);
+ listItem->setData(Qt::UserRole, QVariant::fromValue((void*)plugin));
+ listItem->setData(Qt::UserRole + 1, m_PluginSettings[plugin->name()]);
+ listItem->setData(Qt::UserRole + 2, m_PluginDescriptions[plugin->name()]);
+ pluginsList->addItem(listItem);
+ }
+
+ // display plugin blacklist
+ foreach (const QString &pluginName, m_PluginBlacklist) {
+ pluginBlacklistList->addItem(pluginName);
+ }
+
+ // display server preferences
+ m_Settings.beginGroup("Servers");
+ foreach (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<int>(val["downloadSpeed"].toDouble() / val["downloadCount"].toInt());
+ descriptor += QString(" (%1 kbps)").arg(bps / 1024);
+ }
+
+ QListWidgetItem *newItem = new QListWidgetItemEx<int>(descriptor, Qt::UserRole + 1);
+
+ newItem->setData(Qt::UserRole, key);
+ newItem->setData(Qt::UserRole + 1, val["preferred"].toInt());
+ if (val["preferred"].toInt() > 0) {
+ preferredServersList->addItem(newItem);
+ } else {
+ knownServersList->addItem(newItem);
+ }
+ preferredServersList->sortItems(Qt::DescendingOrder);
+ }
+ m_Settings.endGroup();
+
+ if (dialog.exec() == QDialog::Accepted) {
+ //
+ // transfer modified settings to configuration file
+ //
+
+ m_Settings.setValue("Settings/hide_unchecked_plugins", hideUncheckedBox->checkState() ? true : false);
+ m_Settings.setValue("Settings/force_enable_core_files", forceEnableBox->checkState() ? true : false);
+ m_Settings.setValue("Settings/compact_downloads", compactBox->isChecked());
+ m_Settings.setValue("Settings/meta_downloads", showMetaBox->isChecked());
+ m_Settings.setValue("Settings/load_mechanism", mechanismBox->itemData(mechanismBox->currentIndex()).toInt());
+ if (QDir(downloadDirEdit->text()).exists()) {
+ m_Settings.setValue("Settings/download_directory", QDir::toNativeSeparators(downloadDirEdit->text()));
+ }
+ if (!QDir(cacheDirEdit->text()).exists()) {
+ QDir().mkpath(cacheDirEdit->text());
+ }
+ m_Settings.setValue("Settings/cache_directory", QDir::toNativeSeparators(cacheDirEdit->text()));
+ if (QDir(modDirEdit->text()).exists()) {
+ if ((QDir::fromNativeSeparators(modDirEdit->text()) != QDir::fromNativeSeparators(getModDirectory())) &&
+ (QMessageBox::question(NULL, tr("Confirm"), tr("Changing the mod directory affects all your profiles! "
+ "Mods not present (or named differently) in the new location will be disabled in all profiles. "
+ "There is no way to undo this unless you backed up your profiles manually. Proceed?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)) {
+ m_Settings.setValue("Settings/mod_directory", QDir::toNativeSeparators(modDirEdit->text()));
+ }
+ }
+ QString oldLanguage = m_Settings.value("Settings/language", "en_US").toString();
+ QString newLanguage = languageBox->itemData(languageBox->currentIndex()).toString();
+ if (newLanguage != oldLanguage) {
+ m_Settings.setValue("Settings/language", newLanguage);
+ emit languageChanged(newLanguage);
+ }
+
+ QString oldStyle = m_Settings.value("Settings/style", "").toString();
+ QString newStyle = styleBox->itemData(styleBox->currentIndex()).toString();
+ if (oldStyle != newStyle) {
+ m_Settings.setValue("Settings/style", newStyle);
+ emit styleChanged(newStyle);
+ }
+
+ m_Settings.setValue("Settings/log_level", logLevelBox->currentIndex());
+
+ if (appIDEdit->text() != ToQString(GameInfo::instance().getSteamAPPId())) {
+ m_Settings.setValue("Settings/app_id", appIDEdit->text());
+ } else {
+ m_Settings.remove("Settings/app_id");
+ }
+ if (loginCheckBox->isChecked()) {
+ m_Settings.setValue("Settings/nexus_login", true);
+ m_Settings.setValue("Settings/nexus_username", usernameEdit->text());
+ m_Settings.setValue("Settings/nexus_password", obfuscate(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", offlineBox->isChecked());
+ m_Settings.setValue("Settings/use_proxy", proxyBox->isChecked());
+ m_Settings.setValue("Settings/display_foreign", displayForeignBox->isChecked());
+
+ m_Settings.setValue("Settings/nmm_version", nmmVersionEdit->text());
+
+ // transfer plugin settings to in-memory structure
+ for (int i = 0; i < pluginsList->count(); ++i) {
+ QListWidgetItem *item = pluginsList->item(i);
+ m_PluginSettings[item->text()] = item->data(Qt::UserRole + 1).toMap();
+ }
+ // store plugin settings on disc
+ for (auto iterPlugins = m_PluginSettings.begin(); iterPlugins != 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_PluginBlacklist.clear();
+ foreach (QListWidgetItem *item, pluginBlacklistList->findItems("*", Qt::MatchWildcard)) {
+ m_PluginBlacklist.insert(item->text());
+ }
+ writePluginBlacklist();
+
+ // store server preference
+ m_Settings.beginGroup("Servers");
+ for (int i = 0; i < knownServersList->count(); ++i) {
+ QString key = knownServersList->item(i)->data(Qt::UserRole).toString();
+ QVariantMap val = m_Settings.value(key).toMap();
+ val["preferred"] = 0;
+ m_Settings.setValue(key, val);
+ }
+ int count = preferredServersList->count();
+ for (int i = 0; i < count; ++i) {
+ QString key = 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();
+ }
+}
diff --git a/src/settings.h b/src/settings.h
index 40fd2c5a..5d398f49 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -1,310 +1,311 @@
-/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef WORKAROUNDS_H
-#define WORKAROUNDS_H
-
-#include "loadmechanism.h"
-#include "serverinfo.h"
-#include <iplugin.h>
-
-#include <QSettings>
-#include <QListWidget>
-#include <QComboBox>
-
-
-/**
- * manages the settings for Mod Organizer. The settings are not cached
- * inside the class but read/written directly from/to disc
- **/
-class Settings : public QObject
-{
-
- Q_OBJECT
-
-public:
-
- /**
- * @brief constructor
- **/
- Settings();
-
- virtual ~Settings();
-
- static Settings &instance();
-
- /**
- * unregister all plugins from settings
- */
- void clearPlugins();
-
- /**
- * @brief register plugin to be configurable
- * @param plugin the plugin to register
- * @return true if the plugin may be registered, false if it is blacklisted
- */
- void registerPlugin(MOBase::IPlugin *plugin);
-
- /**
- * displays a SettingsDialog that allows the user to change settings. If the
- * user accepts the changes, the settings are immediately written
- **/
- void query(QWidget *parent);
-
- /**
- * set up the settings for the specified plugins
- **/
- void addPluginSettings(const std::vector<MOBase::IPlugin*> &plugins);
-
- /**
- * @return true if the user wants unchecked plugins (esp, esm) should be hidden from
- * the virtual dat adirectory
- **/
- bool hideUncheckedPlugins() const;
-
- /**
- * @return true if files of the core game are forced-enabled so the user can't accidentally disable them
- */
- bool forceEnableCoreFiles() const;
-
- /**
- * @brief register download speed
- * @param url complete download url
- * @param bytesPerSecond download size in bytes per second
- */
- void setDownloadSpeed(const QString &serverName, int bytesPerSecond);
-
- /**
- * the steam appid is assigned by the steam platform to each product sold there.
- * The appid may differ between different versions of a game so it may be impossible
- * for Mod Organizer to automatically recognize it, though usually it does
- * @return the steam appid for the game
- **/
- QString getSteamAppID() const;
-
- /**
- * retrieve the directory where downloads are stored (with native separators)
- **/
- QString getDownloadDirectory() const;
-
- /**
- * retrieve a sorted list of preferred servers
- */
- std::map<QString, int> getPreferredServers();
-
- /**
- * retrieve the directory where mods are stored (with native separators)
- **/
- QString getModDirectory() const;
-
- /**
- * returns the version of nmm to impersonate when connecting to nexus
- **/
- QString getNMMVersion() const;
-
- /**
- * retrieve the directory where the web cache is stored (with native separators)
- **/
- QString getCacheDirectory() const;
-
- /**
- * @return true if the user has set up automatic login to nexus
- **/
- bool automaticLoginEnabled() const;
-
- /**
- * @brief retrieve the login information for nexus
- *
- * @param username (out) receives the user name for nexus
- * @param password (out) received the password for nexus
- * @return true if automatic login is active, false otherwise
- **/
- bool getNexusLogin(QString &username, QString &password) const;
-
- /**
- * @return true if the user disabled internet features
- */
- bool offlineMode() const;
-
- /**
- * @return true if the user chose compact downloads
- */
- bool compactDownloads() const;
-
- /**
- * @return true if the user chose meta downloads
- */
- bool metaDownloads() const;
-
- /**
- * @return the configured log level
- */
- int logLevel() const;
-
- /**
- * @brief set the nexus login information
- *
- * @param username username
- * @param password password
- */
- void setNexusLogin(QString username, QString password);
-
- /**
- * @return the load mechanism to be used
- **/
- LoadMechanism::EMechanism getLoadMechanism() const;
-
- /**
- * @brief activate the load mechanism selected by the user
- **/
- void setupLoadMechanism();
-
- /**
- * @return true if the user configured the use of a network proxy
- */
- bool useProxy();
-
- /**
- * @return true if the user wants to see non-official plugins installed outside MO in his mod list
- */
- bool displayForeign();
-
- /**
- * @brief sets the new motd hash
- **/
- void setMotDHash(uint hash);
-
- /**
- * @return hash of the last displayed message of the day
- **/
- uint getMotDHash() const;
-
- /**
- * @brief allows direct access to the wrapped QSettings object
- * @return the wrapped QSettings object
- */
- QSettings &directInterface() { return m_Settings; }
-
- /**
- * @brief retrieve a setting for one of the installed plugins
- * @param pluginName name of the plugin
- * @param key name of the setting to retrieve
- * @return the requested value as a QVariant
- * @note an invalid QVariant is returned if the the plugin/setting is not declared
- */
- QVariant pluginSetting(const QString &pluginName, const QString &key) const;
-
- /**
- * @brief set a setting for one of the installed mods
- * @param pluginName name of the plugin
- * @param key name of the setting to change
- * @param value the new value to set
- * @throw an exception is thrown if pluginName is invalid
- */
- void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value);
-
- /**
- * @brief retrieve a persistent value for a plugin
- * @param pluginName name of the plugin to store data for
- * @param key id of the value to retrieve
- * @param def default value to return if the value is not set
- * @return the requested value
- */
- QVariant pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const;
-
- /**
- * @brief set a persistent value for a plugin
- * @param pluginName name of the plugin to store data for
- * @param key id of the value to retrieve
- * @param value value to set
- * @throw an exception is thrown if pluginName is invalid
- */
- void setPluginPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync);
-
- /**
- * @return short code of the configured language (corresponding to the translation files)
- */
- QString language();
-
- /**
- * @brief updates the list of known servers
- * @param list of servers from a recent query
- */
- void updateServers(const QList<ServerInfo> &servers);
-
- /**
- * @brief add a plugin that is to be blacklisted
- * @param fileName name of the plugin to blacklist
- */
- void addBlacklistPlugin(const QString &fileName);
-
- /**
- * @brief test if a plugin is blacklisted and shouldn't be loaded
- * @param fileName name of the plugin
- * @return true if the file is blacklisted
- */
- bool pluginBlacklisted(const QString &fileName) const;
-
- /**
- * @return all loaded MO plugins
- */
- std::vector<MOBase::IPlugin*> plugins() const { return m_Plugins; }
-
- /**
- * @brief register MO as the handler for nxm links
- * @param force set to true to enforce the registration dialog to show up,
- * even if the user said earlier not to
- */
- void registerAsNXMHandler(bool force);
-private:
-
- QString obfuscate(const QString &password) const;
- QString deObfuscate(const QString &password) const;
-
- void addLanguages(QComboBox *languageBox);
- void addStyles(QComboBox *styleBox);
- void readPluginBlacklist();
- void writePluginBlacklist();
-
-private slots:
-
- void resetDialogs();
-
-signals:
-
- void languageChanged(const QString &newLanguage);
- void styleChanged(const QString &newStyle);
-
-private:
-
- static Settings *s_Instance;
-
- QSettings m_Settings;
-
- LoadMechanism m_LoadMechanism;
-
- std::vector<MOBase::IPlugin*> m_Plugins;
-
- QMap<QString, QMap<QString, QVariant> > m_PluginSettings;
-
- QSet<QString> m_PluginBlacklist;
-
-};
-
-#endif // WORKAROUNDS_H
+/*
+Copyright (C) 2012 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef WORKAROUNDS_H
+#define WORKAROUNDS_H
+
+#include "loadmechanism.h"
+#include "serverinfo.h"
+#include <iplugin.h>
+
+#include <QSettings>
+#include <QListWidget>
+#include <QComboBox>
+
+
+/**
+ * manages the settings for Mod Organizer. The settings are not cached
+ * inside the class but read/written directly from/to disc
+ **/
+class Settings : public QObject
+{
+
+ Q_OBJECT
+
+public:
+
+ /**
+ * @brief constructor
+ **/
+ Settings();
+
+ virtual ~Settings();
+
+ static Settings &instance();
+
+ /**
+ * unregister all plugins from settings
+ */
+ void clearPlugins();
+
+ /**
+ * @brief register plugin to be configurable
+ * @param plugin the plugin to register
+ * @return true if the plugin may be registered, false if it is blacklisted
+ */
+ void registerPlugin(MOBase::IPlugin *plugin);
+
+ /**
+ * displays a SettingsDialog that allows the user to change settings. If the
+ * user accepts the changes, the settings are immediately written
+ **/
+ void query(QWidget *parent);
+
+ /**
+ * set up the settings for the specified plugins
+ **/
+ void addPluginSettings(const std::vector<MOBase::IPlugin*> &plugins);
+
+ /**
+ * @return true if the user wants unchecked plugins (esp, esm) should be hidden from
+ * the virtual dat adirectory
+ **/
+ bool hideUncheckedPlugins() const;
+
+ /**
+ * @return true if files of the core game are forced-enabled so the user can't accidentally disable them
+ */
+ bool forceEnableCoreFiles() const;
+
+ /**
+ * @brief register download speed
+ * @param url complete download url
+ * @param bytesPerSecond download size in bytes per second
+ */
+ void setDownloadSpeed(const QString &serverName, int bytesPerSecond);
+
+ /**
+ * the steam appid is assigned by the steam platform to each product sold there.
+ * The appid may differ between different versions of a game so it may be impossible
+ * for Mod Organizer to automatically recognize it, though usually it does
+ * @return the steam appid for the game
+ **/
+ QString getSteamAppID() const;
+
+ /**
+ * retrieve the directory where downloads are stored (with native separators)
+ **/
+ QString getDownloadDirectory() const;
+
+ /**
+ * retrieve a sorted list of preferred servers
+ */
+ std::map<QString, int> getPreferredServers();
+
+ /**
+ * retrieve the directory where mods are stored (with native separators)
+ **/
+ QString getModDirectory() const;
+
+ /**
+ * returns the version of nmm to impersonate when connecting to nexus
+ **/
+ QString getNMMVersion() const;
+
+ /**
+ * retrieve the directory where the web cache is stored (with native separators)
+ **/
+ QString getCacheDirectory() const;
+
+ /**
+ * @return true if the user has set up automatic login to nexus
+ **/
+ bool automaticLoginEnabled() const;
+
+ /**
+ * @brief retrieve the login information for nexus
+ *
+ * @param username (out) receives the user name for nexus
+ * @param password (out) received the password for nexus
+ * @return true if automatic login is active, false otherwise
+ **/
+ bool getNexusLogin(QString &username, QString &password) const;
+
+ /**
+ * @return true if the user disabled internet features
+ */
+ bool offlineMode() const;
+
+ /**
+ * @return true if the user chose compact downloads
+ */
+ bool compactDownloads() const;
+
+ /**
+ * @return true if the user chose meta downloads
+ */
+ bool metaDownloads() const;
+
+ /**
+ * @return the configured log level
+ */
+ int logLevel() const;
+
+ /**
+ * @brief set the nexus login information
+ *
+ * @param username username
+ * @param password password
+ */
+ void setNexusLogin(QString username, QString password);
+
+ /**
+ * @return the load mechanism to be used
+ **/
+ LoadMechanism::EMechanism getLoadMechanism() const;
+
+ /**
+ * @brief activate the load mechanism selected by the user
+ **/
+ void setupLoadMechanism();
+
+ /**
+ * @return true if the user configured the use of a network proxy
+ */
+ bool useProxy();
+
+ /**
+ * @return true if the user wants to see non-official plugins installed outside MO in his mod list
+ */
+ bool displayForeign();
+
+ /**
+ * @brief sets the new motd hash
+ **/
+ void setMotDHash(uint hash);
+
+ /**
+ * @return hash of the last displayed message of the day
+ **/
+ uint getMotDHash() const;
+
+ /**
+ * @brief allows direct access to the wrapped QSettings object
+ * @return the wrapped QSettings object
+ */
+ QSettings &directInterface() { return m_Settings; }
+
+ /**
+ * @brief retrieve a setting for one of the installed plugins
+ * @param pluginName name of the plugin
+ * @param key name of the setting to retrieve
+ * @return the requested value as a QVariant
+ * @note an invalid QVariant is returned if the the plugin/setting is not declared
+ */
+ QVariant pluginSetting(const QString &pluginName, const QString &key) const;
+
+ /**
+ * @brief set a setting for one of the installed mods
+ * @param pluginName name of the plugin
+ * @param key name of the setting to change
+ * @param value the new value to set
+ * @throw an exception is thrown if pluginName is invalid
+ */
+ void setPluginSetting(const QString &pluginName, const QString &key, const QVariant &value);
+
+ /**
+ * @brief retrieve a persistent value for a plugin
+ * @param pluginName name of the plugin to store data for
+ * @param key id of the value to retrieve
+ * @param def default value to return if the value is not set
+ * @return the requested value
+ */
+ QVariant pluginPersistent(const QString &pluginName, const QString &key, const QVariant &def) const;
+
+ /**
+ * @brief set a persistent value for a plugin
+ * @param pluginName name of the plugin to store data for
+ * @param key id of the value to retrieve
+ * @param value value to set
+ * @throw an exception is thrown if pluginName is invalid
+ */
+ void setPluginPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync);
+
+ /**
+ * @return short code of the configured language (corresponding to the translation files)
+ */
+ QString language();
+
+ /**
+ * @brief updates the list of known servers
+ * @param list of servers from a recent query
+ */
+ void updateServers(const QList<ServerInfo> &servers);
+
+ /**
+ * @brief add a plugin that is to be blacklisted
+ * @param fileName name of the plugin to blacklist
+ */
+ void addBlacklistPlugin(const QString &fileName);
+
+ /**
+ * @brief test if a plugin is blacklisted and shouldn't be loaded
+ * @param fileName name of the plugin
+ * @return true if the file is blacklisted
+ */
+ bool pluginBlacklisted(const QString &fileName) const;
+
+ /**
+ * @return all loaded MO plugins
+ */
+ std::vector<MOBase::IPlugin*> plugins() const { return m_Plugins; }
+
+ /**
+ * @brief register MO as the handler for nxm links
+ * @param force set to true to enforce the registration dialog to show up,
+ * even if the user said earlier not to
+ */
+ void registerAsNXMHandler(bool force);
+private:
+
+ QString obfuscate(const QString &password) const;
+ QString deObfuscate(const QString &password) const;
+
+ void addLanguages(QComboBox *languageBox);
+ void addStyles(QComboBox *styleBox);
+ void readPluginBlacklist();
+ void writePluginBlacklist();
+
+private slots:
+
+ void resetDialogs();
+
+signals:
+
+ void languageChanged(const QString &newLanguage);
+ void styleChanged(const QString &newStyle);
+
+private:
+
+ static Settings *s_Instance;
+
+ QSettings m_Settings;
+
+ LoadMechanism m_LoadMechanism;
+
+ std::vector<MOBase::IPlugin*> m_Plugins;
+
+ QMap<QString, QMap<QString, QVariant> > m_PluginSettings;
+ QMap<QString, QMap<QString, QVariant> > m_PluginDescriptions;
+
+ QSet<QString> m_PluginBlacklist;
+
+};
+
+#endif // WORKAROUNDS_H
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index a7d44d72..d1947b5a 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -1,173 +1,182 @@
-/*
-Copyright (C) 2012 Sebastian Herbord. All rights reserved.
-
-This file is part of Mod Organizer.
-
-Mod Organizer is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Mod Organizer is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "settingsdialog.h"
-#include "ui_settingsdialog.h"
-#include "categoriesdialog.h"
-#include "helper.h"
-#include "noeditdelegate.h"
-#include <gameinfo.h>
-#include <QDirIterator>
-#include <QFileDialog>
-#include <QMessageBox>
-#include <QShortcut>
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#include "settings.h"
-
-
-using namespace MOBase;
-using namespace MOShared;
-
-
-SettingsDialog::SettingsDialog(QWidget *parent)
- : TutorableDialog("SettingsDialog", parent), ui(new Ui::SettingsDialog)
-{
- ui->setupUi(this);
-
- QShortcut *delShortcut = new QShortcut(QKeySequence(Qt::Key_Delete), ui->pluginBlacklist);
- connect(delShortcut, SIGNAL(activated()), this, SLOT(deleteBlacklistItem()));
-}
-
-SettingsDialog::~SettingsDialog()
-{
- delete ui;
-}
-
-void SettingsDialog::addPlugins(const std::vector<IPlugin*> &plugins)
-{
- foreach (IPlugin *plugin, plugins) {
- ui->pluginsList->addItem(plugin->name());
- }
-}
-
-void SettingsDialog::accept()
-{
- storeSettings(ui->pluginsList->currentItem());
- TutorableDialog::accept();
-}
-
-
-void SettingsDialog::on_loginCheckBox_toggled(bool checked)
-{
- QLineEdit *usernameEdit = findChild<QLineEdit*>("usernameEdit");
- QLineEdit *passwordEdit = findChild<QLineEdit*>("passwordEdit");
- if (checked) {
- passwordEdit->setEnabled(true);
- usernameEdit->setEnabled(true);
- } else {
- passwordEdit->setEnabled(false);
- usernameEdit->setEnabled(false);
- }
-}
-
-void SettingsDialog::on_categoriesBtn_clicked()
-{
- CategoriesDialog dialog(this);
- if (dialog.exec() == QDialog::Accepted) {
- dialog.commitChanges();
- }
-}
-
-void SettingsDialog::on_bsaDateBtn_clicked()
-{
- Helper::backdateBSAs(GameInfo::instance().getOrganizerDirectory(), GameInfo::instance().getGameDirectory().append(L"\\data"));
-}
-
-void SettingsDialog::on_browseDownloadDirBtn_clicked()
-{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select download directory"), ui->downloadDirEdit->text());
- if (!temp.isEmpty()) {
- ui->downloadDirEdit->setText(temp);
- }
-}
-
-void SettingsDialog::on_browseModDirBtn_clicked()
-{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select mod directory"), ui->downloadDirEdit->text());
- if (!temp.isEmpty()) {
- ui->modDirEdit->setText(temp);
- }
-}
-
-void SettingsDialog::on_browseCacheDirBtn_clicked()
-{
- QString temp = QFileDialog::getExistingDirectory(this, tr("Select cache directory"), ui->cacheDirEdit->text());
- if (!temp.isEmpty()) {
- ui->cacheDirEdit->setText(temp);
- }
-}
-
-void SettingsDialog::on_resetDialogsButton_clicked()
-{
- if (QMessageBox::question(this, tr("Confirm?"),
- tr("This will make all dialogs show up again where you checked the \"Remember selection\"-box. Continue?"),
- QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
- emit resetDialogs();
- }
-}
-
-void SettingsDialog::storeSettings(QListWidgetItem *pluginItem)
-{
- if (pluginItem != NULL) {
- QMap<QString, QVariant> settings = pluginItem->data(Qt::UserRole + 1).toMap();
-
- for (int i = 0; i < ui->pluginSettingsList->topLevelItemCount(); ++i) {
- const QTreeWidgetItem *item = ui->pluginSettingsList->topLevelItem(i);
- settings[item->text(0)] = item->data(1, Qt::DisplayRole);
- }
-
- pluginItem->setData(Qt::UserRole + 1, settings);
- }
-}
-
-void SettingsDialog::on_pluginsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
-{
- storeSettings(previous);
-
- ui->pluginSettingsList->clear();
- IPlugin *plugin = static_cast<IPlugin*>(current->data(Qt::UserRole).value<void*>());
- ui->authorLabel->setText(plugin->author());
- ui->versionLabel->setText(plugin->version().canonicalString());
- ui->descriptionLabel->setText(plugin->description());
-
- QMap<QString, QVariant> settings = current->data(Qt::UserRole + 1).toMap();
- ui->pluginSettingsList->setEnabled(settings.count() != 0);
- for (auto iter = settings.begin(); iter != settings.end(); ++iter) {
- QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList(iter.key()));
- QVariant value = *iter;
-
- ui->pluginSettingsList->setItemDelegateForColumn(0, new NoEditDelegate());
- newItem->setData(1, Qt::DisplayRole, value);
- newItem->setData(1, Qt::EditRole, value);
-
- newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
- ui->pluginSettingsList->addTopLevelItem(newItem);
- }
-}
-
-void SettingsDialog::deleteBlacklistItem()
-{
- ui->pluginBlacklist->takeItem(ui->pluginBlacklist->currentIndex().row());
-}
-
-void SettingsDialog::on_associateButton_clicked()
-{
- Settings::instance().registerAsNXMHandler(true);
-}
+/*
+Copyright (C) 2012 Sebastian Herbord. All rights reserved.
+
+This file is part of Mod Organizer.
+
+Mod Organizer is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Mod Organizer is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "settingsdialog.h"
+#include "ui_settingsdialog.h"
+#include "categoriesdialog.h"
+#include "helper.h"
+#include "noeditdelegate.h"
+#include <gameinfo.h>
+#include <QDirIterator>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QShortcut>
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include "settings.h"
+
+
+using namespace MOBase;
+using namespace MOShared;
+
+
+SettingsDialog::SettingsDialog(QWidget *parent)
+ : TutorableDialog("SettingsDialog", parent), ui(new Ui::SettingsDialog)
+{
+ ui->setupUi(this);
+
+ QShortcut *delShortcut = new QShortcut(QKeySequence(Qt::Key_Delete), ui->pluginBlacklist);
+ connect(delShortcut, SIGNAL(activated()), this, SLOT(deleteBlacklistItem()));
+}
+
+SettingsDialog::~SettingsDialog()
+{
+ delete ui;
+}
+
+void SettingsDialog::addPlugins(const std::vector<IPlugin*> &plugins)
+{
+ foreach (IPlugin *plugin, plugins) {
+ ui->pluginsList->addItem(plugin->name());
+ }
+}
+
+void SettingsDialog::accept()
+{
+ storeSettings(ui->pluginsList->currentItem());
+ TutorableDialog::accept();
+}
+
+
+void SettingsDialog::on_loginCheckBox_toggled(bool checked)
+{
+ QLineEdit *usernameEdit = findChild<QLineEdit*>("usernameEdit");
+ QLineEdit *passwordEdit = findChild<QLineEdit*>("passwordEdit");
+ if (checked) {
+ passwordEdit->setEnabled(true);
+ usernameEdit->setEnabled(true);
+ } else {
+ passwordEdit->setEnabled(false);
+ usernameEdit->setEnabled(false);
+ }
+}
+
+void SettingsDialog::on_categoriesBtn_clicked()
+{
+ CategoriesDialog dialog(this);
+ if (dialog.exec() == QDialog::Accepted) {
+ dialog.commitChanges();
+ }
+}
+
+void SettingsDialog::on_bsaDateBtn_clicked()
+{
+ Helper::backdateBSAs(GameInfo::instance().getOrganizerDirectory(), GameInfo::instance().getGameDirectory().append(L"\\data"));
+}
+
+void SettingsDialog::on_browseDownloadDirBtn_clicked()
+{
+ QString temp = QFileDialog::getExistingDirectory(this, tr("Select download directory"), ui->downloadDirEdit->text());
+ if (!temp.isEmpty()) {
+ ui->downloadDirEdit->setText(temp);
+ }
+}
+
+void SettingsDialog::on_browseModDirBtn_clicked()
+{
+ QString temp = QFileDialog::getExistingDirectory(this, tr("Select mod directory"), ui->downloadDirEdit->text());
+ if (!temp.isEmpty()) {
+ ui->modDirEdit->setText(temp);
+ }
+}
+
+void SettingsDialog::on_browseCacheDirBtn_clicked()
+{
+ QString temp = QFileDialog::getExistingDirectory(this, tr("Select cache directory"), ui->cacheDirEdit->text());
+ if (!temp.isEmpty()) {
+ ui->cacheDirEdit->setText(temp);
+ }
+}
+
+void SettingsDialog::on_resetDialogsButton_clicked()
+{
+ if (QMessageBox::question(this, tr("Confirm?"),
+ tr("This will make all dialogs show up again where you checked the \"Remember selection\"-box. Continue?"),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
+ emit resetDialogs();
+ }
+}
+
+void SettingsDialog::storeSettings(QListWidgetItem *pluginItem)
+{
+ if (pluginItem != NULL) {
+ QMap<QString, QVariant> settings = pluginItem->data(Qt::UserRole + 1).toMap();
+
+ for (int i = 0; i < ui->pluginSettingsList->topLevelItemCount(); ++i) {
+ const QTreeWidgetItem *item = ui->pluginSettingsList->topLevelItem(i);
+ settings[item->text(0)] = item->data(1, Qt::DisplayRole);
+ }
+
+ pluginItem->setData(Qt::UserRole + 1, settings);
+ }
+}
+
+void SettingsDialog::on_pluginsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
+{
+ storeSettings(previous);
+
+ ui->pluginSettingsList->clear();
+ IPlugin *plugin = static_cast<IPlugin*>(current->data(Qt::UserRole).value<void*>());
+ ui->authorLabel->setText(plugin->author());
+ ui->versionLabel->setText(plugin->version().canonicalString());
+ ui->descriptionLabel->setText(plugin->description());
+
+ QMap<QString, QVariant> settings = current->data(Qt::UserRole + 1).toMap();
+ QMap<QString, QVariant> descriptions = current->data(Qt::UserRole + 2).toMap();
+ ui->pluginSettingsList->setEnabled(settings.count() != 0);
+ for (auto iter = settings.begin(); iter != settings.end(); ++iter) {
+ QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList(iter.key()));
+ QVariant value = *iter;
+ QString description;
+ {
+ auto descriptionIter = descriptions.find(iter.key());
+ if (descriptionIter != descriptions.end()) {
+ description = descriptionIter->toString();
+ }
+ }
+
+ ui->pluginSettingsList->setItemDelegateForColumn(0, new NoEditDelegate());
+ newItem->setData(1, Qt::DisplayRole, value);
+ newItem->setData(1, Qt::EditRole, value);
+ newItem->setToolTip(1, description);
+
+ newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);
+ ui->pluginSettingsList->addTopLevelItem(newItem);
+ }
+}
+
+void SettingsDialog::deleteBlacklistItem()
+{
+ ui->pluginBlacklist->takeItem(ui->pluginBlacklist->currentIndex().row());
+}
+
+void SettingsDialog::on_associateButton_clicked()
+{
+ Settings::instance().registerAsNXMHandler(true);
+}