/*
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 .
*/
#ifndef SETTINGS_H
#define SETTINGS_H
#include "loadmechanism.h"
#include
#include
#include
#ifdef interface
#undef interface
#endif
namespace MOBase {
class IPlugin;
class IPluginGame;
}
class QSplitter;
class ServerList;
class Settings;
class ExpanderWidget;
// helper class that calls restoreGeometry() in the constructor and
// saveGeometry() in the destructor
//
class GeometrySaver
{
public:
GeometrySaver(Settings& s, QDialog* dialog);
~GeometrySaver();
private:
Settings& m_settings;
QDialog* m_dialog;
};
// setting for the currently managed game
//
class GameSettings
{
public:
GameSettings(QSettings& setting);
// game plugin
//
const MOBase::IPluginGame* plugin();
void setPlugin(const MOBase::IPluginGame* gamePlugin);
// whether files of the core game are forced-enabled so the user can't
// accidentally disable them
//
bool forceEnableCoreFiles() const;
void setForceEnableCoreFiles(bool b);
// the directory where the managed game is stored
//
std::optional directory() const;
void setDirectory(const QString& path);
// the name of the managed game
//
std::optional name() const;
void setName(const QString& name);
// the edition of the managed game
//
std::optional edition() const;
void setEdition(const QString& name);
// the current profile name
//
std::optional selectedProfileName() const;
void setSelectedProfileName(const QString& name);
// load mechanism type
//
LoadMechanism::EMechanism loadMechanismType() const;
void setLoadMechanism(LoadMechanism::EMechanism m);
// load mechanism object
//
const LoadMechanism& loadMechanism() const;
LoadMechanism& loadMechanism();
// whether the user wants unchecked plugins (esp, esm) to be hidden from
// the virtual data directory
//
bool hideUncheckedPlugins() const;
void setHideUncheckedPlugins(bool b);
private:
QSettings& m_Settings;
const MOBase::IPluginGame* m_GamePlugin;
LoadMechanism m_LoadMechanism;
};
// geometry settings for various widgets; this should contain any setting that
// can get invalid through UI changes or when users change display settings
// (resolution, monitors, etc.); see WidgetSettings for the counterpart
//
// all these settings are stored under [Geometry] and get wiped when the
// "reset geometry settings" button is clicked in the settings
//
// saveGeometry(), restoreGeometry(), saveState() and restoreState() call the
// same functions on the given widget
//
class GeometrySettings
{
public:
GeometrySettings(QSettings& s);
// asks the settings to get reset
//
// this gets called from the settings dialog and gets picked up in
// resetIfNeeded(), called from runApplication() just before exiting
//
void requestReset();
void resetIfNeeded();
void saveGeometry(const QWidget* w);
bool restoreGeometry(QWidget* w) const;
void saveState(const QMainWindow* window);
bool restoreState(QMainWindow* window) const;
void saveState(const QHeaderView* header);
bool restoreState(QHeaderView* header) const;
void saveState(const QSplitter* splitter);
bool restoreState(QSplitter* splitter) const;
void saveState(const ExpanderWidget* expander);
bool restoreState(ExpanderWidget* expander) const;
void saveVisibility(const QWidget* w);
bool restoreVisibility(QWidget* w, std::optional def={}) const;
void saveToolbars(const QMainWindow* w);
void restoreToolbars(QMainWindow* w) const;
void saveDocks(const QMainWindow* w);
void restoreDocks(QMainWindow* w) const;
// this should be a generic "tab order" setting, but it only happens for the
// mod info dialog right now
//
QStringList modInfoTabOrder() const;
void setModInfoTabOrder(const QString& names);
// assumes the given widget is a top-level
//
void centerOnMainWindowMonitor(QWidget* w);
// saves the monitor number of the given window
//
void saveMainWindowMonitor(const QMainWindow* w);
private:
QSettings& m_Settings;
bool m_Reset;
};
// widget settings that should stay valid regardless of UI changes or when users
// change display settings (resolution, monitors, etc.); see GeometrySettings
// for the counterpart
//
class WidgetSettings
{
public:
WidgetSettings(QSettings& s);
// selected index for a combobox
//
std::optional index(const QComboBox* cb) const;
void saveIndex(const QComboBox* cb);
void restoreIndex(QComboBox* cb, std::optional def={}) const;
// selected tab index for a tab widget
//
std::optional index(const QTabWidget* w) const;
void saveIndex(const QTabWidget* w);
void restoreIndex(QTabWidget* w, std::optional def={}) const;
// check state for a checkable button
//
std::optional checked(const QAbstractButton* w) const;
void saveChecked(const QAbstractButton* w);
void restoreChecked(QAbstractButton* w, std::optional def={}) const;
// returns the remembered button for a question dialog, or NoButton if the
// user hasn't saved the choice
//
MOBase::QuestionBoxMemory::Button questionButton(
const QString& windowName, const QString& filename) const;
// sets the button to be remembered for the given window
//
void setQuestionWindowButton(
const QString& windowName, MOBase::QuestionBoxMemory::Button button);
// sets the button to be remembered for the given file
//
void setQuestionFileButton(
const QString& windowName, const QString& filename,
MOBase::QuestionBoxMemory::Button choice);
// wipes all the remembered buttons
//
void resetQuestionButtons();
private:
QSettings& m_Settings;
};
// various color settings
//
class ColorSettings
{
public:
ColorSettings(QSettings& s);
QColor modlistOverwrittenLoose() const;
void setModlistOverwrittenLoose(const QColor& c);
QColor modlistOverwritingLoose() const;
void setModlistOverwritingLoose(const QColor& c);
QColor modlistOverwrittenArchive() const;
void setModlistOverwrittenArchive(const QColor& c);
QColor modlistOverwritingArchive() const;
void setModlistOverwritingArchive(const QColor& c);
QColor modlistContainsPlugin() const;
void setModlistContainsPlugin(const QColor& c);
QColor pluginListContained() const;
void setPluginListContained(const QColor& c) ;
std::optional previousSeparatorColor() const;
void setPreviousSeparatorColor(const QColor& c) const;
void removePreviousSeparatorColor();
// whether the scrollbar of the mod list should have colors for custom
// separator colors
//
bool colorSeparatorScrollbar() const;
void setColorSeparatorScrollbar(bool b);
// returns a color with a good contrast for the given background
//
static QColor idealTextColor(const QColor& rBackgroundColor);
private:
QSettings& m_Settings;
};
// settings about plugins
//
class PluginSettings
{
public:
PluginSettings(QSettings& settings);
// forgets all the plugins
//
void clearPlugins();
// adds the given plugin to the list and loads all of its settings
//
void registerPlugin(MOBase::IPlugin *plugin);
// returns all the registered plugins
//
std::vector plugins() const;
// returns the plugin setting for the given key
//
QVariant setting(const QString &pluginName, const QString &key) const;
// sets the plugin setting for the given key
//
void setSetting(const QString &pluginName, const QString &key, const QVariant &value);
// returns all settings
//
QVariantMap settings(const QString &pluginName) const;
// overwrites all settings
//
void setSettings(const QString &pluginName, const QVariantMap& map);
// returns all descriptions
//
QVariantMap descriptions(const QString &pluginName) const;
// overwrites all descriptions
//
void setDescriptions(const QString &pluginName, const QVariantMap& map);
// ?
QVariant persistent(const QString &pluginName, const QString &key, const QVariant &def) const;
void setPersistent(const QString &pluginName, const QString &key, const QVariant &value, bool sync);
// adds the given plugin to the blacklist
//
void addBlacklist(const QString &fileName);
// returns whether the given plugin is blacklisted
//
bool blacklisted(const QString &fileName) const;
// overwrites the whole blacklist
//
void setBlacklist(const QStringList& pluginNames);
// returns the blacklist
//
const QSet& blacklist() const;
// commits all the settings to the ini
//
void save();
private:
QSettings& m_Settings;
std::vector m_Plugins;
QMap m_PluginSettings;
QMap m_PluginDescriptions;
QSet m_PluginBlacklist;
// commits the blacklist to the ini
//
void writeBlacklist();
// reads the blacklist from the ini
//
QSet readBlacklist() const;
};
class PathSettings
{
public:
PathSettings(QSettings& settings);
QString base() const;
QString downloads(bool resolve = true) const;
QString mods(bool resolve = true) const;
QString cache(bool resolve = true) const;
QString profiles(bool resolve = true) const;
QString overwrite(bool resolve = true) const;
void setBase(const QString& path);
void setDownloads(const QString& path);
void setMods(const QString& path);
void setCache(const QString& path);
void setProfiles(const QString& path);
void setOverwrite(const QString& path);
std::map recent() const;
void setRecent(const std::map& map);
private:
QSettings& m_Settings;
QString getConfigurablePath(const QString &key, const QString &def, bool resolve) const;
void setConfigurablePath(const QString &key, const QString& path);
};
class NetworkSettings
{
public:
NetworkSettings(QSettings& settings);
/**
* @return true if the user disabled internet features
*/
bool offlineMode() const;
void setOfflineMode(bool b);
/**
* @return true if the user configured the use of a network proxy
*/
bool useProxy() const;
void setUseProxy(bool b);
void setDownloadSpeed(const QString &serverName, int bytesPerSecond);
ServerList servers() const;
void updateServers(ServerList servers);
void dump() const;
private:
QSettings& m_Settings;
ServerList serversFromOldMap() const;
};
enum class EndorsementState
{
Accepted = 1,
Refused,
NoDecision
};
EndorsementState endorsementStateFromString(const QString& s);
QString toString(EndorsementState s);
class NexusSettings
{
public:
NexusSettings(Settings& parent, QSettings& settings);
/**
* @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 apiKey(QString &apiKey) const;
/**
* @brief set the nexus login information
*
* @param username username
* @param password password
*/
bool setApiKey(const QString& apiKey);
/**
* @brief clears the nexus login information
*/
bool clearApiKey();
/**
* @brief returns whether an API key is currently stored
*/
bool hasApiKey() const;
/**
* @return true if endorsement integration is enabled
*/
bool endorsementIntegration() const;
void setEndorsementIntegration(bool b) const;
EndorsementState endorsementState() const;
void setEndorsementState(EndorsementState s);
/**
* @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:
Settings& m_Parent;
QSettings& m_Settings;
};
class SteamSettings
{
public:
SteamSettings(Settings& parent, QSettings& settings);
/**
* 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 appID() const;
void setAppID(const QString& id);
/**
* @brief retrieve the login information for steam
*
* @param username (out) receives the user name for nexus
* @param password (out) received the password for nexus
* @return true if a username has been specified, false otherwise
**/
bool login(QString &username, QString &password) const;
/**
* @brief set the steam login information
*
* @param username username
* @param password password
*/
void setLogin(QString username, QString password);
private:
Settings& m_Parent;
QSettings& m_Settings;
};
class InterfaceSettings
{
public:
InterfaceSettings(QSettings& settings);
/**
* @return true if the GUI should be locked when running executables
*/
bool lockGUI() const;
void setLockGUI(bool b);
std::optional styleName() const;
void setStyleName(const QString& name);
/**
* @return true if the user chose compact downloads
*/
bool compactDownloads() const;
void setCompactDownloads(bool b);
/**
* @return true if the user chose meta downloads
*/
bool metaDownloads() const;
void setMetaDownloads(bool b);
/**
* @return true if the API counter should be hidden
*/
bool hideAPICounter() const;
void setHideAPICounter(bool b);
/**
* @return true if the user wants to see non-official plugins installed outside MO in his mod list
*/
bool displayForeign() const;
void setDisplayForeign(bool b);
/**
* @return short code of the configured language (corresponding to the translation files)
*/
QString language();
void setLanguage(const QString& name);
bool isTutorialCompleted(const QString& windowName) const;
void setTutorialCompleted(const QString& windowName, bool b=true);
private:
QSettings& m_Settings;
};
class DiagnosticsSettings
{
public:
DiagnosticsSettings(QSettings& settings);
MOBase::log::Levels logLevel() const;
void setLogLevel(MOBase::log::Levels level);
CrashDumpsType crashDumpsType() const;
void setCrashDumpsType(CrashDumpsType type);
int crashDumpsMax() const;
void setCrashDumpsMax(int n);
private:
QSettings& m_Settings;
};
/**
* 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:
Settings(const QString& path);
~Settings();
static Settings &instance();
QString filename() const;
std::optional version() const;
void processUpdates(const QVersionNumber& current, const QVersionNumber& last);
bool firstStart() const;
void setFirstStart(bool b);
std::vector> executables() const;
void setExecutables(const std::vector>& v);
bool keepBackupOnInstall() const;
void setKeepBackupOnInstall(bool b);
QString executablesBlacklist() const;
void setExecutablesBlacklist(const QString& s);
/**
* @brief sets the new motd hash
**/
unsigned int motdHash() const;
void setMotdHash(unsigned int hash);
/**
* @return true if the user wants to have archives being parsed to show conflicts and contents
*/
bool archiveParsing() const;
void setArchiveParsing(bool b);
bool usePrereleases() const;
void setUsePrereleases(bool b);
GameSettings& game();
const GameSettings& game() const;
GeometrySettings& geometry();
const GeometrySettings& geometry() const;
WidgetSettings& widgets();
const WidgetSettings& widgets() const;
ColorSettings& colors();
const ColorSettings& colors() const;
PluginSettings& plugins();
const PluginSettings& plugins() const;
PathSettings& paths();
const PathSettings& paths() const;
NetworkSettings& network();
const NetworkSettings& network() const;
NexusSettings& nexus();
const NexusSettings& nexus() const;
SteamSettings& steam();
const SteamSettings& steam() const;
InterfaceSettings& interface();
const InterfaceSettings& interface() const;
DiagnosticsSettings& diagnostics();
const DiagnosticsSettings& diagnostics() const;
QSettings::Status sync() const;
void dump() const;
public slots:
void managedGameChanged(MOBase::IPluginGame const *gamePlugin);
signals:
void languageChanged(const QString &newLanguage);
void styleChanged(const QString &newStyle);
private:
static Settings *s_Instance;
mutable QSettings m_Settings;
GameSettings m_Game;
GeometrySettings m_Geometry;
WidgetSettings m_Widgets;
ColorSettings m_Colors;
PluginSettings m_Plugins;
PathSettings m_Paths;
NetworkSettings m_Network;
NexusSettings m_Nexus;
SteamSettings m_Steam;
InterfaceSettings m_Interface;
DiagnosticsSettings m_Diagnostics;
};
#endif // SETTINGS_H