2020-10-07 10:36:04 +00:00
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
// Copyright (C) 2020 KeePassXC Team <team@keepassxc.org>
|
|
|
|
// Copyright (C) 2011 Felix Geyer <debfx@fobos.de>
|
2020-12-26 19:56:06 +00:00
|
|
|
// Copyright (c) 2020-2021, The Monero Project.
|
2020-10-07 10:36:04 +00:00
|
|
|
|
|
|
|
#include "config.h"
|
2021-07-06 19:36:27 +00:00
|
|
|
#include "utils/Utils.h"
|
2021-05-25 13:06:38 +00:00
|
|
|
#include "utils/os/tails.h"
|
2020-10-07 10:36:04 +00:00
|
|
|
|
|
|
|
#define QS QStringLiteral
|
|
|
|
|
|
|
|
struct ConfigDirective
|
|
|
|
{
|
|
|
|
QString name;
|
|
|
|
QVariant defaultValue;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
|
|
|
|
// General
|
2021-05-18 15:59:18 +00:00
|
|
|
{Config::firstRun, {QS("firstRun"), true}},
|
2020-10-07 10:36:04 +00:00
|
|
|
{Config::warnOnStagenet,{QS("warnOnStagenet"), true}},
|
|
|
|
{Config::warnOnTestnet,{QS("warnOnTestnet"), true}},
|
|
|
|
{Config::warnOnAlpha,{QS("warnOnAlpha"), true}},
|
2021-05-18 15:59:18 +00:00
|
|
|
|
2020-10-07 10:36:04 +00:00
|
|
|
{Config::homeWidget,{QS("homeWidget"), "ccs"}},
|
|
|
|
{Config::donateBeg,{QS("donateBeg"), 1}},
|
2021-05-18 15:59:18 +00:00
|
|
|
{Config::showHistorySyncNotice, {QS("showHistorySyncNotice"), true}},
|
|
|
|
|
|
|
|
{Config::geometry, {QS("geometry"), {}}},
|
|
|
|
{Config::windowState, {QS("windowState"), {}}},
|
|
|
|
{Config::GUI_HistoryViewState, {QS("GUI_HistoryViewState"), {}}},
|
|
|
|
|
|
|
|
// Wallets
|
2020-10-07 10:36:04 +00:00
|
|
|
{Config::walletDirectory,{QS("walletDirectory"), ""}},
|
|
|
|
{Config::autoOpenWalletPath,{QS("autoOpenWalletPath"), ""}},
|
2021-05-18 15:59:18 +00:00
|
|
|
{Config::recentlyOpenedWallets, {QS("recentlyOpenedWallets"), {}}},
|
|
|
|
|
|
|
|
// Nodes
|
2020-10-07 10:36:04 +00:00
|
|
|
{Config::nodes,{QS("nodes"), "{}"}},
|
|
|
|
{Config::nodeSource,{QS("nodeSource"), 0}},
|
|
|
|
{Config::useOnionNodes,{QS("useOnionNodes"), false}},
|
2021-05-18 15:59:18 +00:00
|
|
|
|
|
|
|
// Tabs
|
2020-12-30 04:45:00 +00:00
|
|
|
{Config::showTabHome,{QS("showTabHome"), true}},
|
2020-10-07 10:36:04 +00:00
|
|
|
{Config::showTabCoins,{QS("showTabCoins"), false}},
|
2021-05-04 23:09:19 +00:00
|
|
|
{Config::showTabExchange, {QS("showTabExchange"), false}},
|
2020-10-14 20:12:32 +00:00
|
|
|
{Config::showTabXMRig,{QS("showTabXMRig"), false}},
|
2020-10-07 10:36:04 +00:00
|
|
|
{Config::showTabCalc,{QS("showTabCalc"), true}},
|
2021-05-23 14:58:18 +00:00
|
|
|
{Config::showSearchbar,{QS("showSearchbar"), true}},
|
2021-05-18 15:59:18 +00:00
|
|
|
|
|
|
|
// Mining
|
|
|
|
{Config::xmrigPath,{QS("xmrigPath"), ""}},
|
|
|
|
{Config::xmrigPool,{QS("xmrigPool"), "pool.xmr.pt:9000"}},
|
2021-07-07 17:11:12 +00:00
|
|
|
{Config::pools,{QS("pools"), {}}},
|
2021-05-18 15:59:18 +00:00
|
|
|
|
|
|
|
// Settings
|
|
|
|
{Config::preferredFiatCurrency,{QS("preferredFiatCurrency"), "USD"}},
|
|
|
|
{Config::skin,{QS("skin"), "light"}},
|
2021-03-24 13:21:15 +00:00
|
|
|
{Config::amountPrecision, {QS("amountPrecision"), 12}},
|
2021-03-14 21:12:02 +00:00
|
|
|
{Config::dateFormat, {QS("dateFormat"), "yyyy-MM-dd"}},
|
2021-03-16 03:17:01 +00:00
|
|
|
{Config::timeFormat, {QS("timeFormat"), "HH:mm"}},
|
2021-05-22 14:12:39 +00:00
|
|
|
{Config::balanceDisplay, {QS("balanceDisplay"), Config::BalanceDisplay::spendablePlusUnconfirmed}},
|
2021-05-18 15:59:18 +00:00
|
|
|
|
2021-05-02 18:22:38 +00:00
|
|
|
{Config::multiBroadcast, {QS("multiBroadcast"), true}},
|
2021-05-18 15:59:18 +00:00
|
|
|
{Config::warnOnExternalLink,{QS("warnOnExternalLink"), true}},
|
|
|
|
{Config::hideBalance, {QS("hideBalance"), false}},
|
|
|
|
|
|
|
|
{Config::blockExplorer,{QS("blockExplorer"), "exploremonero.com"}},
|
|
|
|
{Config::redditFrontend, {QS("redditFrontend"), "old.reddit.com"}},
|
|
|
|
{Config::localMoneroFrontend, {QS("localMoneroFrontend"), "https://localmonero.co"}},
|
|
|
|
|
2021-05-26 13:14:53 +00:00
|
|
|
{Config::fiatSymbols, {QS("fiatSymbols"), QStringList{"USD", "EUR", "GBP", "CAD", "AUD", "RUB"}}},
|
|
|
|
{Config::cryptoSymbols, {QS("cryptoSymbols"), QStringList{"BTC", "ETH", "LTC", "XMR", "ZEC"}}},
|
|
|
|
|
2021-05-18 15:59:18 +00:00
|
|
|
// Tor
|
2021-05-02 18:22:38 +00:00
|
|
|
{Config::torPrivacyLevel, {QS("torPrivacyLevel"), 1}},
|
|
|
|
{Config::socks5Host, {QS("socks5Host"), "127.0.0.1"}},
|
|
|
|
{Config::socks5Port, {QS("socks5Port"), "9050"}},
|
2021-05-18 15:59:18 +00:00
|
|
|
{Config::socks5User, {QS("socks5User"), ""}}, // Unused
|
|
|
|
{Config::socks5Pass, {QS("socks5Pass"), ""}}, // Unused
|
2021-05-24 15:20:19 +00:00
|
|
|
{Config::useLocalTor, {QS("useLocalTor"), false}},
|
|
|
|
{Config::initSyncThreshold, {QS("initSyncThreshold"), 360}}
|
2020-10-07 10:36:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
QPointer<Config> Config::m_instance(nullptr);
|
|
|
|
|
|
|
|
QVariant Config::get(ConfigKey key)
|
|
|
|
{
|
|
|
|
auto cfg = configStrings[key];
|
|
|
|
auto defaultValue = configStrings[key].defaultValue;
|
|
|
|
|
|
|
|
return m_settings->value(cfg.name, defaultValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Config::getFileName()
|
|
|
|
{
|
|
|
|
return m_settings->fileName();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Config::set(ConfigKey key, const QVariant& value)
|
|
|
|
{
|
|
|
|
if (get(key) == value) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto cfg = configStrings[key];
|
|
|
|
m_settings->setValue(cfg.name, value);
|
|
|
|
|
|
|
|
this->sync();
|
|
|
|
emit changed(key);
|
|
|
|
}
|
|
|
|
|
2021-07-08 12:03:54 +00:00
|
|
|
void Config::remove(ConfigKey key)
|
|
|
|
{
|
|
|
|
auto cfg = configStrings[key];
|
|
|
|
m_settings->remove(cfg.name);
|
|
|
|
|
|
|
|
emit changed(key);
|
|
|
|
}
|
|
|
|
|
2020-10-07 10:36:04 +00:00
|
|
|
/**
|
|
|
|
* Sync configuration with persistent storage.
|
|
|
|
*
|
|
|
|
* Usually, you don't need to call this method manually, but if you are writing
|
|
|
|
* configurations after an emitted \link QCoreApplication::aboutToQuit() signal,
|
|
|
|
* use it to guarantee your config values are persisted.
|
|
|
|
*/
|
|
|
|
void Config::sync()
|
|
|
|
{
|
|
|
|
m_settings->sync();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Config::resetToDefaults()
|
|
|
|
{
|
|
|
|
m_settings->clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Config::Config(const QString& fileName, QObject* parent)
|
|
|
|
: QObject(parent)
|
|
|
|
{
|
|
|
|
init(fileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
Config::Config(QObject* parent)
|
2021-03-12 18:26:48 +00:00
|
|
|
: QObject(parent)
|
2020-10-07 10:36:04 +00:00
|
|
|
{
|
2021-03-12 18:26:48 +00:00
|
|
|
QDir configDir = Config::defaultConfigDir();
|
2020-10-07 10:36:04 +00:00
|
|
|
|
2021-03-24 01:37:54 +00:00
|
|
|
if (!QDir().mkpath(configDir.path())) {
|
|
|
|
qWarning() << "Unable to create config path: " << configDir.path();
|
2020-10-07 10:36:04 +00:00
|
|
|
}
|
|
|
|
|
2021-03-12 18:26:48 +00:00
|
|
|
QString configPath = configDir.filePath("settings.json");
|
2020-10-07 10:36:04 +00:00
|
|
|
|
|
|
|
init(QDir::toNativeSeparators(configPath));
|
|
|
|
}
|
|
|
|
|
2021-03-12 18:26:48 +00:00
|
|
|
QDir Config::defaultConfigDir() {
|
2021-03-24 01:37:54 +00:00
|
|
|
QString portablePath = QCoreApplication::applicationDirPath().append("/%1");
|
2021-08-19 17:54:31 +00:00
|
|
|
if (QFile::exists(portablePath.arg(".portable")) || QFile::exists(portablePath.arg(".portable.txt"))) {
|
2021-03-24 01:37:54 +00:00
|
|
|
return portablePath.arg("feather_data");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TailsOS::detect()) {
|
|
|
|
QString path = []{
|
|
|
|
QString appImagePath = qgetenv("APPIMAGE");
|
|
|
|
if (appImagePath.isEmpty()) {
|
|
|
|
qDebug() << "Not an appimage, using currentPath()";
|
|
|
|
return QDir::currentPath() + "/.feather/.config/feather";
|
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo appImageDir(appImagePath);
|
|
|
|
return appImageDir.absoluteDir().path() + "/.feather/.config/feather";
|
|
|
|
}();
|
|
|
|
|
|
|
|
return QDir(path);
|
|
|
|
}
|
|
|
|
|
2021-03-12 18:26:48 +00:00
|
|
|
#if defined(Q_OS_WIN)
|
|
|
|
return QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
|
|
|
#elif defined(Q_OS_MACOS)
|
|
|
|
return QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
|
|
|
#else
|
|
|
|
return QDir(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/feather");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
QDir Config::defaultPortableConfigDir() {
|
|
|
|
return QDir(QCoreApplication::applicationDirPath() + "/feather_data");
|
|
|
|
}
|
2020-10-07 10:36:04 +00:00
|
|
|
|
|
|
|
Config::~Config()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Config::init(const QString& configFileName)
|
|
|
|
{
|
|
|
|
const QSettings::Format jsonFormat = QSettings::registerFormat("json", Utils::readJsonFile, Utils::writeJsonFile);
|
|
|
|
QSettings::setDefaultFormat(jsonFormat);
|
|
|
|
m_settings.reset(new QSettings(configFileName, jsonFormat));
|
|
|
|
|
|
|
|
connect(qApp, &QCoreApplication::aboutToQuit, this, &Config::sync);
|
|
|
|
}
|
|
|
|
|
|
|
|
Config* Config::instance()
|
|
|
|
{
|
|
|
|
if (!m_instance) {
|
|
|
|
m_instance = new Config(qApp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return m_instance;
|
|
|
|
}
|