2023-02-11 17:11:21 +00:00
// SPDX-License-Identifier: BSD-3-Clause
// SPDX-FileCopyrightText: 2020-2023 The Monero Project
2023-02-11 17:24:18 +00:00
# include "SettingsDialog.h"
# include "ui_SettingsDialog.h"
2023-02-11 17:11:21 +00:00
# include <QCloseEvent>
# include <QDesktopServices>
# include <QFileDialog>
# include <QMessageBox>
2023-03-01 02:05:56 +00:00
# include "libwalletqt/WalletManager.h"
# include "utils/AppData.h"
2023-02-11 17:11:21 +00:00
# include "utils/Icons.h"
# include "utils/WebsocketNotifier.h"
# include "widgets/NetworkProxyWidget.h"
2023-03-01 02:05:56 +00:00
Settings : : Settings ( Nodes * nodes , QWidget * parent )
2023-02-11 17:11:21 +00:00
: QDialog ( parent )
2023-02-11 17:24:18 +00:00
, ui ( new Ui : : Settings )
2023-03-01 02:05:56 +00:00
, m_nodes ( nodes )
2023-02-11 17:11:21 +00:00
{
ui - > setupUi ( this ) ;
this - > setupAppearanceTab ( ) ;
this - > setupNetworkTab ( ) ;
this - > setupStorageTab ( ) ;
this - > setupDisplayTab ( ) ;
this - > setupMemoryTab ( ) ;
this - > setupTransactionsTab ( ) ;
this - > setupMiscTab ( ) ;
connect ( ui - > selector , & QListWidget : : currentItemChanged , [ this ] ( QListWidgetItem * current , QListWidgetItem * previous ) {
ui - > stackedWidget - > setCurrentIndex ( current - > type ( ) ) ;
} ) ;
ui - > selector - > setSelectionMode ( QAbstractItemView : : SingleSelection ) ;
ui - > selector - > setSelectionBehavior ( QAbstractItemView : : SelectRows ) ;
// ui->selector->setCurrentRow(config()->get(Config::lastSettingsPage).toInt());
new QListWidgetItem ( icons ( ) - > icon ( " interface_32px.png " ) , " Appearance " , ui - > selector , Pages : : APPEARANCE ) ;
new QListWidgetItem ( icons ( ) - > icon ( " nw_32px.png " ) , " Network " , ui - > selector , Pages : : NETWORK ) ;
new QListWidgetItem ( icons ( ) - > icon ( " hd_32px.png " ) , " Storage " , ui - > selector , Pages : : STORAGE ) ;
new QListWidgetItem ( icons ( ) - > icon ( " vrdp_32px.png " ) , " Display " , ui - > selector , Pages : : DISPLAY ) ;
// new QListWidgetItem(icons()->icon("chipset_32px.png"), "Memory", ui->selector, Pages::MEMORY);
new QListWidgetItem ( icons ( ) - > icon ( " file_manager_32px.png " ) , " Transactions " , ui - > selector , Pages : : TRANSACTIONS ) ;
new QListWidgetItem ( icons ( ) - > icon ( " settings_disabled_32px.png " ) , " Misc " , ui - > selector , Pages : : MISC ) ;
ui - > selector - > setFixedWidth ( ui - > selector - > sizeHintForColumn ( 0 ) + ui - > selector - > frameWidth ( ) + 5 ) ;
// for (int i = 0; i < ui->selector->count(); ++i) {
// QListWidgetItem *item = ui->selector->item(i);
// item->setSizeHint(QSize(item->sizeHint().width(), ui->selector->iconSize().height() + 8));
// }
connect ( ui - > closeButton , & QDialogButtonBox : : accepted , [ this ] {
// Save Proxy settings
bool isProxySettingChanged = ui - > proxyWidget - > isProxySettingsChanged ( ) ;
ui - > proxyWidget - > setProxySettings ( ) ;
if ( isProxySettingChanged ) {
emit proxySettingsChanged ( ) ;
}
config ( ) - > set ( Config : : lastSettingsPage , ui - > selector - > currentRow ( ) ) ;
this - > close ( ) ;
} ) ;
this - > setSelection ( config ( ) - > get ( Config : : lastSettingsPage ) . toInt ( ) ) ;
this - > adjustSize ( ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : setupAppearanceTab ( ) {
2023-02-11 17:11:21 +00:00
// [Theme]
this - > setupThemeComboBox ( ) ;
auto settingsTheme = config ( ) - > get ( Config : : skin ) . toString ( ) ;
if ( m_themes . contains ( settingsTheme ) ) {
ui - > comboBox_theme - > setCurrentIndex ( m_themes . indexOf ( settingsTheme ) ) ;
}
connect ( ui - > comboBox_theme , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ this ] ( int pos ) {
emit skinChanged ( m_themes . at ( pos ) ) ;
} ) ;
// [Amount precision]
for ( int i = 0 ; i < = 12 ; i + + ) {
ui - > comboBox_amountPrecision - > addItem ( QString : : number ( i ) ) ;
}
ui - > comboBox_amountPrecision - > setCurrentIndex ( config ( ) - > get ( Config : : amountPrecision ) . toInt ( ) ) ;
connect ( ui - > comboBox_amountPrecision , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ this ] ( int pos ) {
config ( ) - > set ( Config : : amountPrecision , pos ) ;
emit updateBalance ( ) ;
} ) ;
// [Date format]
QDateTime now = QDateTime : : currentDateTime ( ) ;
for ( const auto & format : m_dateFormats ) {
ui - > comboBox_dateFormat - > addItem ( now . toString ( format ) ) ;
}
QString dateFormatSetting = config ( ) - > get ( Config : : dateFormat ) . toString ( ) ;
if ( m_dateFormats . contains ( dateFormatSetting ) ) {
ui - > comboBox_dateFormat - > setCurrentIndex ( m_dateFormats . indexOf ( dateFormatSetting ) ) ;
}
connect ( ui - > comboBox_dateFormat , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ this ] ( int pos ) {
config ( ) - > set ( Config : : dateFormat , m_dateFormats . at ( pos ) ) ;
} ) ;
// [Time format]
for ( const auto & format : m_timeFormats ) {
ui - > comboBox_timeFormat - > addItem ( now . toString ( format ) ) ;
}
QString timeFormatSetting = config ( ) - > get ( Config : : timeFormat ) . toString ( ) ;
if ( m_timeFormats . contains ( timeFormatSetting ) ) {
ui - > comboBox_timeFormat - > setCurrentIndex ( m_timeFormats . indexOf ( timeFormatSetting ) ) ;
}
connect ( ui - > comboBox_timeFormat , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ this ] ( int pos ) {
config ( ) - > set ( Config : : timeFormat , m_timeFormats . at ( pos ) ) ;
} ) ;
// [Balance display]
ui - > comboBox_balanceDisplay - > setCurrentIndex ( config ( ) - > get ( Config : : balanceDisplay ) . toInt ( ) ) ;
connect ( ui - > comboBox_balanceDisplay , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ this ] ( int pos ) {
config ( ) - > set ( Config : : balanceDisplay , pos ) ;
emit updateBalance ( ) ;
} ) ;
// [Preferred fiat currency]
QStringList availableFiatCurrencies = appData ( ) - > prices . rates . keys ( ) ;
for ( const auto & currency : availableFiatCurrencies ) {
ui - > comboBox_fiatCurrency - > addItem ( currency ) ;
}
QStringList fiatCurrencies ;
for ( int index = 0 ; index < ui - > comboBox_fiatCurrency - > count ( ) ; index + + ) {
fiatCurrencies < < ui - > comboBox_fiatCurrency - > itemText ( index ) ;
}
auto preferredFiatCurrency = config ( ) - > get ( Config : : preferredFiatCurrency ) . toString ( ) ;
if ( ! preferredFiatCurrency . isEmpty ( ) & & fiatCurrencies . contains ( preferredFiatCurrency ) ) {
ui - > comboBox_fiatCurrency - > setCurrentText ( preferredFiatCurrency ) ;
}
connect ( ui - > comboBox_fiatCurrency , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ this ] ( int index ) {
QString selection = ui - > comboBox_fiatCurrency - > itemText ( index ) ;
config ( ) - > set ( Config : : preferredFiatCurrency , selection ) ;
emit preferredFiatCurrencyChanged ( selection ) ;
} ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : setupNetworkTab ( ) {
2023-02-11 17:11:21 +00:00
// Node
2023-03-01 02:05:56 +00:00
if ( m_nodes ) {
ui - > nodeWidget - > setupUI ( m_nodes ) ;
connect ( ui - > nodeWidget , & NodeWidget : : nodeSourceChanged , m_nodes , & Nodes : : onNodeSourceChanged ) ;
connect ( ui - > nodeWidget , & NodeWidget : : connectToNode , m_nodes , QOverload < const FeatherNode & > : : of ( & Nodes : : connectToNode ) ) ;
2023-02-11 17:11:21 +00:00
} else {
2023-03-01 02:05:56 +00:00
m_nodes = new Nodes ( this , nullptr ) ;
2023-02-11 17:11:21 +00:00
ui - > nodeWidget - > setupUI ( m_nodes ) ;
ui - > nodeWidget - > setCanConnect ( false ) ;
}
// Proxy
2023-02-11 17:24:18 +00:00
connect ( ui - > proxyWidget , & NetworkProxyWidget : : proxySettingsChanged , this , & Settings : : onProxySettingsChanged ) ;
2023-02-11 17:11:21 +00:00
// Websocket
// [Obtain third-party data]
ui - > checkBox_enableWebsocket - > setChecked ( ! config ( ) - > get ( Config : : disableWebsocket ) . toBool ( ) ) ;
connect ( ui - > checkBox_enableWebsocket , & QCheckBox : : toggled , [ this ] ( bool checked ) {
config ( ) - > set ( Config : : disableWebsocket , ! checked ) ;
this - > enableWebsocket ( checked ) ;
} ) ;
// Overview
ui - > checkBox_offlineMode - > setChecked ( config ( ) - > get ( Config : : offlineMode ) . toBool ( ) ) ;
connect ( ui - > checkBox_offlineMode , & QCheckBox : : toggled , [ this ] ( bool checked ) {
config ( ) - > set ( Config : : offlineMode , checked ) ;
emit offlineMode ( checked ) ;
this - > enableWebsocket ( ! checked ) ;
} ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : setupStorageTab ( ) {
2023-02-11 17:11:21 +00:00
// Paths
ui - > lineEdit_defaultWalletDir - > setText ( config ( ) - > get ( Config : : walletDirectory ) . toString ( ) ) ;
ui - > lineEdit_configDir - > setText ( Config : : defaultConfigDir ( ) . path ( ) ) ;
ui - > lineEdit_applicationDir - > setText ( Utils : : applicationPath ( ) ) ;
bool portableMode = Utils : : isPortableMode ( ) ;
if ( portableMode ) {
ui - > btn_browseDefaultWalletDir - > setDisabled ( true ) ;
ui - > btn_browseDefaultWalletDir - > setToolTip ( " Portable Mode enabled " ) ;
}
connect ( ui - > btn_browseDefaultWalletDir , & QPushButton : : clicked , [ this ] {
QString walletDirOld = config ( ) - > get ( Config : : walletDirectory ) . toString ( ) ;
QString walletDir = QFileDialog : : getExistingDirectory ( this , " Select wallet directory " , walletDirOld , QFileDialog : : ShowDirsOnly ) ;
if ( walletDir . isEmpty ( ) )
return ;
config ( ) - > set ( Config : : walletDirectory , walletDir ) ;
ui - > lineEdit_defaultWalletDir - > setText ( walletDir ) ;
} ) ;
connect ( ui - > btn_openWalletDir , & QPushButton : : clicked , [ ] {
QDesktopServices : : openUrl ( QUrl : : fromLocalFile ( config ( ) - > get ( Config : : walletDirectory ) . toString ( ) ) ) ;
} ) ;
connect ( ui - > btn_openConfigDir , & QPushButton : : clicked , [ ] {
QDesktopServices : : openUrl ( QUrl : : fromLocalFile ( Config : : defaultConfigDir ( ) . path ( ) ) ) ;
} ) ;
ui - > frame_portableMode - > setVisible ( portableMode ) ;
// Logging
// [Write log files to disk]
ui - > checkBox_enableLogging - > setChecked ( ! config ( ) - > get ( Config : : disableLogging ) . toBool ( ) ) ;
connect ( ui - > checkBox_enableLogging , & QCheckBox : : toggled , [ ] ( bool toggled ) {
config ( ) - > set ( Config : : disableLogging , ! toggled ) ;
WalletManager : : instance ( ) - > setLogLevel ( toggled ? config ( ) - > get ( Config : : logLevel ) . toInt ( ) : - 1 ) ;
} ) ;
// [Log level]
ui - > comboBox_logLevel - > setCurrentIndex ( config ( ) - > get ( Config : : logLevel ) . toInt ( ) ) ;
2023-02-27 12:28:04 +00:00
connect ( ui - > comboBox_logLevel , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ ] ( int index ) {
2023-02-11 17:11:21 +00:00
config ( ) - > set ( Config : : logLevel , index ) ;
if ( ! config ( ) - > get ( Config : : disableLogging ) . toBool ( ) ) {
WalletManager : : instance ( ) - > setLogLevel ( index ) ;
}
} ) ;
// [Write stack trace to disk on crash]
ui - > checkBox_writeStackTraceToDisk - > setChecked ( config ( ) - > get ( Config : : writeStackTraceToDisk ) . toBool ( ) ) ;
connect ( ui - > checkBox_writeStackTraceToDisk , & QCheckBox : : toggled , [ ] ( bool toggled ) {
config ( ) - > set ( Config : : writeStackTraceToDisk , toggled ) ;
} ) ;
// [Open log file]
connect ( ui - > btn_openLogFile , & QPushButton : : clicked , [ ] {
QDesktopServices : : openUrl ( QUrl : : fromLocalFile ( Config : : defaultConfigDir ( ) . path ( ) + " /libwallet.log " ) ) ;
} ) ;
// Misc
// [Save recently opened wallet to config file]
ui - > checkBox_writeRecentlyOpened - > setChecked ( config ( ) - > get ( Config : : writeRecentlyOpenedWallets ) . toBool ( ) ) ;
connect ( ui - > checkBox_writeRecentlyOpened , & QCheckBox : : toggled , [ ] ( bool toggled ) {
config ( ) - > set ( Config : : writeRecentlyOpenedWallets , toggled ) ;
if ( ! toggled ) {
config ( ) - > set ( Config : : recentlyOpenedWallets , { } ) ;
}
} ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : setupDisplayTab ( ) {
2023-02-11 17:11:21 +00:00
// [Hide balance]
ui - > checkBox_hideBalance - > setChecked ( config ( ) - > get ( Config : : hideBalance ) . toBool ( ) ) ;
connect ( ui - > checkBox_hideBalance , & QCheckBox : : toggled , [ this ] ( bool toggled ) {
config ( ) - > set ( Config : : hideBalance , toggled ) ;
emit updateBalance ( ) ;
} ) ;
// [Hide update notifications]
ui - > checkBox_hideUpdateNotifications - > setChecked ( config ( ) - > get ( Config : : hideUpdateNotifications ) . toBool ( ) ) ;
connect ( ui - > checkBox_hideUpdateNotifications , & QCheckBox : : toggled , [ this ] ( bool toggled ) {
config ( ) - > set ( Config : : hideUpdateNotifications , toggled ) ;
emit hideUpdateNotifications ( toggled ) ;
} ) ;
// [Hide transaction notifications]
ui - > checkBox_hideTransactionNotifications - > setChecked ( config ( ) - > get ( Config : : hideNotifications ) . toBool ( ) ) ;
connect ( ui - > checkBox_hideTransactionNotifications , & QCheckBox : : toggled , [ ] ( bool toggled ) {
config ( ) - > set ( Config : : hideNotifications , toggled ) ;
} ) ;
// [Warn before opening external link]
ui - > checkBox_warnOnExternalLink - > setChecked ( config ( ) - > get ( Config : : warnOnExternalLink ) . toBool ( ) ) ;
connect ( ui - > checkBox_warnOnExternalLink , & QCheckBox : : clicked , this , [ this ] {
bool state = ui - > checkBox_warnOnExternalLink - > isChecked ( ) ;
config ( ) - > set ( Config : : warnOnExternalLink , state ) ;
} ) ;
// [Lock wallet on inactivity]
ui - > checkBox_lockOnInactivity - > setChecked ( config ( ) - > get ( Config : : inactivityLockEnabled ) . toBool ( ) ) ;
ui - > spinBox_lockOnInactivity - > setValue ( config ( ) - > get ( Config : : inactivityLockTimeout ) . toInt ( ) ) ;
connect ( ui - > checkBox_lockOnInactivity , & QCheckBox : : toggled , [ ] ( bool toggled ) {
config ( ) - > set ( Config : : inactivityLockEnabled , toggled ) ;
} ) ;
connect ( ui - > spinBox_lockOnInactivity , QOverload < int > : : of ( & QSpinBox : : valueChanged ) , [ ] ( int value ) {
config ( ) - > set ( Config : : inactivityLockTimeout , value ) ;
} ) ;
// [Lock wallet on minimize]
ui - > checkBox_lockOnMinimize - > setChecked ( config ( ) - > get ( Config : : lockOnMinimize ) . toBool ( ) ) ;
connect ( ui - > checkBox_lockOnMinimize , & QCheckBox : : toggled , [ ] ( bool toggled ) {
config ( ) - > set ( Config : : lockOnMinimize , toggled ) ;
} ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : setupMemoryTab ( ) {
2023-02-11 17:11:21 +00:00
// Nothing here, yet
}
2023-02-11 17:24:18 +00:00
void Settings : : setupTransactionsTab ( ) {
2023-02-11 17:11:21 +00:00
// [Multibroadcast outgoing transactions]
ui - > checkBox_multibroadcast - > setChecked ( config ( ) - > get ( Config : : multiBroadcast ) . toBool ( ) ) ;
connect ( ui - > checkBox_multibroadcast , & QCheckBox : : toggled , [ ] ( bool toggled ) {
config ( ) - > set ( Config : : multiBroadcast , toggled ) ;
} ) ;
connect ( ui - > btn_multibroadcast , & QPushButton : : clicked , [ this ] {
QMessageBox : : information ( this , " Multibroadcasting " , " Multibroadcasting relays outgoing transactions to all nodes in your selected node list. This may improve transaction relay speed and reduces the chance of your transaction failing. " ) ;
} ) ;
// Hide unimplemented settings
ui - > checkBox_alwaysOpenAdvancedTxDialog - > hide ( ) ;
ui - > checkBox_requirePasswordToSpend - > hide ( ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : setupMiscTab ( ) {
2023-02-11 17:11:21 +00:00
// [Block explorer]
ui - > comboBox_blockExplorer - > setCurrentIndex ( ui - > comboBox_blockExplorer - > findText ( config ( ) - > get ( Config : : blockExplorer ) . toString ( ) ) ) ;
connect ( ui - > comboBox_blockExplorer , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ this ] {
QString blockExplorer = ui - > comboBox_blockExplorer - > currentText ( ) ;
config ( ) - > set ( Config : : blockExplorer , blockExplorer ) ;
emit blockExplorerChanged ( blockExplorer ) ;
} ) ;
// [Reddit frontend]
ui - > comboBox_redditFrontend - > setCurrentIndex ( ui - > comboBox_redditFrontend - > findText ( config ( ) - > get ( Config : : redditFrontend ) . toString ( ) ) ) ;
connect ( ui - > comboBox_redditFrontend , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ this ] {
QString redditFrontend = ui - > comboBox_redditFrontend - > currentText ( ) ;
config ( ) - > set ( Config : : redditFrontend , redditFrontend ) ;
} ) ;
// [LocalMonero frontend]
ui - > comboBox_localMoneroFrontend - > addItem ( " localmonero.co " , " https://localmonero.co " ) ;
ui - > comboBox_localMoneroFrontend - > addItem ( " localmonero.co/nojs " , " https://localmonero.co/nojs " ) ;
ui - > comboBox_localMoneroFrontend - > addItem ( " nehdddktmhvqklsnkjqcbpmb63htee2iznpcbs5tgzctipxykpj6yrid.onion " ,
" http://nehdddktmhvqklsnkjqcbpmb63htee2iznpcbs5tgzctipxykpj6yrid.onion " ) ;
ui - > comboBox_localMoneroFrontend - > addItem ( " yeyar743vuwmm6fpgf3x6bzmj7fxb5uxhuoxx4ea76wqssdi4f3q.b32.i2p " ,
" http://yeyar743vuwmm6fpgf3x6bzmj7fxb5uxhuoxx4ea76wqssdi4f3q.b32.i2p " ) ;
ui - > comboBox_localMoneroFrontend - > setCurrentIndex ( ui - > comboBox_localMoneroFrontend - > findData ( config ( ) - > get ( Config : : localMoneroFrontend ) . toString ( ) ) ) ;
connect ( ui - > comboBox_localMoneroFrontend , QOverload < int > : : of ( & QComboBox : : currentIndexChanged ) , [ this ] {
QString localMoneroFrontend = ui - > comboBox_localMoneroFrontend - > currentData ( ) . toString ( ) ;
config ( ) - > set ( Config : : localMoneroFrontend , localMoneroFrontend ) ;
} ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : onProxySettingsChanged ( ) {
2023-02-11 17:11:21 +00:00
ui - > closeButton - > addButton ( QDialogButtonBox : : Apply ) ;
connect ( ui - > closeButton - > button ( QDialogButtonBox : : Apply ) , & QAbstractButton : : clicked , [ this ] ( ) {
ui - > proxyWidget - > setProxySettings ( ) ;
emit proxySettingsChanged ( ) ;
ui - > closeButton - > removeButton ( ui - > closeButton - > button ( QDialogButtonBox : : Apply ) ) ;
} ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : showNetworkProxyTab ( ) {
this - > setSelection ( Settings : : Pages : : NETWORK ) ;
2023-02-11 17:11:21 +00:00
ui - > tabWidget_network - > setCurrentIndex ( 1 ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : setupThemeComboBox ( ) {
2023-02-11 17:11:21 +00:00
# if defined(Q_OS_WIN)
m_themes . removeOne ( " Breeze/Dark " ) ;
m_themes . removeOne ( " Breeze/Light " ) ;
# elif defined(Q_OS_MAC)
m_themes . removeOne ( " QDarkStyle " ) ;
# endif
ui - > comboBox_theme - > insertItems ( 0 , m_themes ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : setSelection ( int index ) {
2023-02-11 17:11:21 +00:00
// You'd really think there is a better way
QListWidgetItem * item = ui - > selector - > item ( index ) ;
QModelIndex idx = ui - > selector - > indexFromItem ( item ) ;
ui - > selector - > setCurrentRow ( index ) ;
ui - > selector - > selectionModel ( ) - > select ( idx , QItemSelectionModel : : ClearAndSelect | QItemSelectionModel : : Rows ) ;
}
2023-02-11 17:24:18 +00:00
void Settings : : enableWebsocket ( bool enabled ) {
2023-02-11 17:11:21 +00:00
if ( enabled & & ! config ( ) - > get ( Config : : offlineMode ) . toBool ( ) & & ! config ( ) - > get ( Config : : disableWebsocket ) . toBool ( ) ) {
websocketNotifier ( ) - > websocketClient . restart ( ) ;
} else {
websocketNotifier ( ) - > websocketClient . stop ( ) ;
}
ui - > nodeWidget - > onWebsocketStatusChanged ( ) ;
emit websocketStatusChanged ( enabled ) ;
}
2023-02-11 17:24:18 +00:00
Settings : : ~ Settings ( ) = default ;