]>
Commit | Line | Data |
---|---|---|
e592d43f WL |
1 | // Copyright (c) 2011-2013 The Bitcoin developers |
2 | // Distributed under the MIT/X11 software license, see the accompanying | |
3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | |
4 | ||
35b8af92 CF |
5 | #if defined(HAVE_CONFIG_H) |
6 | #include "bitcoin-config.h" | |
7 | #endif | |
8 | ||
0fd01780 | 9 | #include "optionsdialog.h" |
c4443c2b PK |
10 | #include "ui_optionsdialog.h" |
11 | ||
ee014e5b | 12 | #include "bitcoinunits.h" |
7e195e84 | 13 | #include "guiutil.h" |
c4443c2b | 14 | #include "monitoreddatamapper.h" |
c4443c2b | 15 | #include "optionsmodel.h" |
df577886 | 16 | |
c6cb21d1 | 17 | #include "main.h" // for CTransaction::minTxFee and MAX_SCRIPTCHECK_THREADS |
51ed9ec9 | 18 | #include "netbase.h" |
82e96006 | 19 | #include "txdb.h" // for -dbcache defaults |
51ed9ec9 | 20 | |
c4443c2b PK |
21 | #include <QDir> |
22 | #include <QIntValidator> | |
2943f608 | 23 | #include <QLocale> |
5ac114c7 | 24 | #include <QMessageBox> |
7e195e84 | 25 | #include <QTimer> |
c3e0734d | 26 | |
c4443c2b PK |
27 | OptionsDialog::OptionsDialog(QWidget *parent) : |
28 | QDialog(parent), | |
29 | ui(new Ui::OptionsDialog), | |
30 | model(0), | |
31 | mapper(0), | |
c4443c2b | 32 | fProxyIpValid(true) |
6ddf8610 | 33 | { |
c4443c2b | 34 | ui->setupUi(this); |
7e195e84 PK |
35 | GUIUtil::restoreWindowGeometry("nOptionsDialogWindow", this->size(), this); |
36 | ||
37 | /* Main elements init */ | |
82e96006 PK |
38 | ui->databaseCache->setMinimum(nMinDbCache); |
39 | ui->databaseCache->setMaximum(nMaxDbCache); | |
5409404d PK |
40 | ui->threadsScriptVerif->setMinimum(-(int)boost::thread::hardware_concurrency()); |
41 | ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS); | |
6ddf8610 | 42 | |
c4443c2b PK |
43 | /* Network elements init */ |
44 | #ifndef USE_UPNP | |
45 | ui->mapPortUpnp->setEnabled(false); | |
527137e3 | 46 | #endif |
e285ffcd | 47 | |
1376a542 PK |
48 | ui->proxyIp->setEnabled(false); |
49 | ui->proxyPort->setEnabled(false); | |
50 | ui->proxyPort->setValidator(new QIntValidator(1, 65535, this)); | |
51 | ||
7e195e84 | 52 | /** SOCKS version is only selectable for default proxy and is always 5 for IPv6 and Tor */ |
c4443c2b PK |
53 | ui->socksVersion->setEnabled(false); |
54 | ui->socksVersion->addItem("5", 5); | |
55 | ui->socksVersion->addItem("4", 4); | |
56 | ui->socksVersion->setCurrentIndex(0); | |
6ddf8610 | 57 | |
c4443c2b PK |
58 | connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool))); |
59 | connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool))); | |
1376a542 | 60 | connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool))); |
df577886 | 61 | |
c4443c2b | 62 | ui->proxyIp->installEventFilter(this); |
df577886 | 63 | |
c4443c2b | 64 | /* Window elements init */ |
81605d90 | 65 | #ifdef Q_OS_MAC |
f679b290 JS |
66 | /* remove Window tab on Mac */ |
67 | ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWindow)); | |
81c45c0a | 68 | #endif |
e285ffcd | 69 | |
c4443c2b PK |
70 | /* Display elements init */ |
71 | QDir translations(":translations"); | |
72 | ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant("")); | |
73 | foreach(const QString &langStr, translations.entryList()) | |
6ddf8610 | 74 | { |
2943f608 PK |
75 | QLocale locale(langStr); |
76 | ||
77 | /** check if the locale name consists of 2 parts (language_country) */ | |
78 | if(langStr.contains("_")) | |
79 | { | |
81ccec40 PK |
80 | #if QT_VERSION >= 0x040800 |
81 | /** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */ | |
82 | ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr)); | |
83 | #else | |
2943f608 PK |
84 | /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */ |
85 | ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr)); | |
81ccec40 | 86 | #endif |
2943f608 PK |
87 | } |
88 | else | |
89 | { | |
81ccec40 PK |
90 | #if QT_VERSION >= 0x040800 |
91 | /** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */ | |
92 | ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr)); | |
93 | #else | |
2943f608 PK |
94 | /** display language strings as "language (locale name)", e.g. "German (de)" */ |
95 | ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr)); | |
81ccec40 | 96 | #endif |
2943f608 | 97 | } |
6ddf8610 | 98 | } |
40c5b939 CL |
99 | #if QT_VERSION >= 0x040700 |
100 | ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s"); | |
101 | #endif | |
df577886 | 102 | |
c4443c2b | 103 | ui->unit->setModel(new BitcoinUnits(this)); |
c6cb21d1 | 104 | ui->transactionFee->setSingleStep(CTransaction::minTxFee.GetFeePerK()); |
df577886 | 105 | |
c6dd35f0 | 106 | /* Widget-to-option mapper */ |
c3e0734d | 107 | mapper = new MonitoredDataMapper(this); |
92f20d53 WL |
108 | mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit); |
109 | mapper->setOrientation(Qt::Vertical); | |
c4443c2b | 110 | |
1376a542 | 111 | /* setup/change UI elements when proxy IP is invalid/valid */ |
7e195e84 | 112 | connect(this, SIGNAL(proxyIpChecks(QValidatedLineEdit *, int)), this, SLOT(doProxyIpChecks(QValidatedLineEdit *, int))); |
c4443c2b PK |
113 | } |
114 | ||
115 | OptionsDialog::~OptionsDialog() | |
116 | { | |
7e195e84 | 117 | GUIUtil::saveWindowGeometry("nOptionsDialogWindow", this); |
c4443c2b | 118 | delete ui; |
92f20d53 WL |
119 | } |
120 | ||
121 | void OptionsDialog::setModel(OptionsModel *model) | |
122 | { | |
123 | this->model = model; | |
124 | ||
c4443c2b | 125 | if(model) |
6ddf8610 | 126 | { |
7e195e84 PK |
127 | /* check if client restart is needed and show persistent message */ |
128 | if (model->isRestartRequired()) | |
129 | showRestartWarning(true); | |
130 | ||
131 | QString strLabel = model->getOverriddenByCommandLine(); | |
132 | if (strLabel.isEmpty()) | |
133 | strLabel = tr("none"); | |
134 | ui->overriddenByCommandLineLabel->setText(strLabel); | |
135 | ||
c4443c2b PK |
136 | connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); |
137 | ||
138 | mapper->setModel(model); | |
139 | setMapper(); | |
140 | mapper->toFirst(); | |
6ddf8610 | 141 | } |
df577886 | 142 | |
1376a542 | 143 | /* update the display unit, to not use the default ("BTC") */ |
c4443c2b | 144 | updateDisplayUnit(); |
1376a542 | 145 | |
7e195e84 | 146 | /* warn when one of the following settings changes by user action (placed here so init via mapper doesn't trigger them) */ |
4aaa4313 | 147 | |
7e195e84 PK |
148 | /* Main */ |
149 | connect(ui->databaseCache, SIGNAL(valueChanged(int)), this, SLOT(showRestartWarning())); | |
150 | connect(ui->threadsScriptVerif, SIGNAL(valueChanged(int)), this, SLOT(showRestartWarning())); | |
71f82bf2 | 151 | /* Wallet */ |
152 | connect(ui->spendZeroConfChange, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning())); | |
7e195e84 PK |
153 | /* Network */ |
154 | connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning())); | |
155 | /* Display */ | |
156 | connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning())); | |
40c5b939 | 157 | connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this, SLOT(showRestartWarning())); |
df577886 WL |
158 | } |
159 | ||
c4443c2b | 160 | void OptionsDialog::setMapper() |
df577886 | 161 | { |
c4443c2b | 162 | /* Main */ |
c4443c2b | 163 | mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup); |
7e195e84 PK |
164 | mapper->addMapping(ui->threadsScriptVerif, OptionsModel::ThreadsScriptVerif); |
165 | mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache); | |
c6dd35f0 | 166 | |
29d45073 WL |
167 | /* Wallet */ |
168 | mapper->addMapping(ui->transactionFee, OptionsModel::Fee); | |
169 | mapper->addMapping(ui->spendZeroConfChange, OptionsModel::SpendZeroConfChange); | |
16d281ba | 170 | mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures); |
29d45073 | 171 | |
c4443c2b PK |
172 | /* Network */ |
173 | mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP); | |
1376a542 | 174 | |
c4443c2b | 175 | mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse); |
c4443c2b PK |
176 | mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP); |
177 | mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort); | |
1376a542 | 178 | mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion); |
c6dd35f0 | 179 | |
c4443c2b | 180 | /* Window */ |
ada2a396 | 181 | #ifndef Q_OS_MAC |
c4443c2b PK |
182 | mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray); |
183 | mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose); | |
184 | #endif | |
c6dd35f0 | 185 | |
c4443c2b PK |
186 | /* Display */ |
187 | mapper->addMapping(ui->lang, OptionsModel::Language); | |
188 | mapper->addMapping(ui->unit, OptionsModel::DisplayUnit); | |
189 | mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses); | |
40c5b939 | 190 | mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls); |
c6dd35f0 WL |
191 | } |
192 | ||
7e195e84 | 193 | void OptionsDialog::enableOkButton() |
c6dd35f0 | 194 | { |
7e195e84 | 195 | /* prevent enabling of the OK button when data modified, if there is an invalid proxy address present */ |
c4443c2b | 196 | if(fProxyIpValid) |
7e195e84 | 197 | setOkButtonState(true); |
c6dd35f0 | 198 | } |
c3e0734d | 199 | |
7e195e84 | 200 | void OptionsDialog::disableOkButton() |
c3e0734d | 201 | { |
7e195e84 | 202 | setOkButtonState(false); |
c3e0734d WL |
203 | } |
204 | ||
7e195e84 | 205 | void OptionsDialog::setOkButtonState(bool fState) |
6ddf8610 | 206 | { |
c4443c2b | 207 | ui->okButton->setEnabled(fState); |
6ddf8610 WL |
208 | } |
209 | ||
5fb445b4 PK |
210 | void OptionsDialog::on_resetButton_clicked() |
211 | { | |
212 | if(model) | |
213 | { | |
214 | // confirmation dialog | |
215 | QMessageBox::StandardButton btnRetVal = QMessageBox::question(this, tr("Confirm options reset"), | |
7e195e84 | 216 | tr("Client restart required to activate changes.") + "<br><br>" + tr("Client will be shutdown, do you want to proceed?"), |
5fb445b4 PK |
217 | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); |
218 | ||
219 | if(btnRetVal == QMessageBox::Cancel) | |
220 | return; | |
221 | ||
1ba3560f | 222 | /* reset all options and close GUI */ |
5fb445b4 | 223 | model->Reset(); |
7e195e84 | 224 | QApplication::quit(); |
5fb445b4 PK |
225 | } |
226 | } | |
227 | ||
c4443c2b | 228 | void OptionsDialog::on_okButton_clicked() |
6ddf8610 | 229 | { |
c4443c2b PK |
230 | mapper->submit(); |
231 | accept(); | |
6ddf8610 WL |
232 | } |
233 | ||
c4443c2b | 234 | void OptionsDialog::on_cancelButton_clicked() |
c3e0734d | 235 | { |
c4443c2b | 236 | reject(); |
6ddf8610 WL |
237 | } |
238 | ||
7e195e84 | 239 | void OptionsDialog::showRestartWarning(bool fPersistent) |
6ddf8610 | 240 | { |
7e195e84 | 241 | ui->statusLabel->setStyleSheet("QLabel { color: red; }"); |
6ddf8610 | 242 | |
7e195e84 PK |
243 | if(fPersistent) |
244 | { | |
245 | ui->statusLabel->setText(tr("Client restart required to activate changes.")); | |
246 | } | |
247 | else | |
5ac114c7 | 248 | { |
7e195e84 PK |
249 | ui->statusLabel->setText(tr("This change would require a client restart.")); |
250 | // clear non-persistent status label after 10 seconds | |
251 | // Todo: should perhaps be a class attribute, if we extend the use of statusLabel | |
252 | QTimer::singleShot(10000, this, SLOT(clearStatusLabel())); | |
5ac114c7 WL |
253 | } |
254 | } | |
255 | ||
7e195e84 | 256 | void OptionsDialog::clearStatusLabel() |
6ddf8610 | 257 | { |
7e195e84 | 258 | ui->statusLabel->clear(); |
6ddf8610 WL |
259 | } |
260 | ||
c4443c2b | 261 | void OptionsDialog::updateDisplayUnit() |
6ddf8610 | 262 | { |
c4443c2b PK |
263 | if(model) |
264 | { | |
1376a542 | 265 | /* Update transactionFee with the current unit */ |
c4443c2b PK |
266 | ui->transactionFee->setDisplayUnit(model->getDisplayUnit()); |
267 | } | |
c3e0734d WL |
268 | } |
269 | ||
7e195e84 | 270 | void OptionsDialog::doProxyIpChecks(QValidatedLineEdit *pUiProxyIp, int nProxyPort) |
1376a542 | 271 | { |
7e195e84 | 272 | Q_UNUSED(nProxyPort); |
1376a542 | 273 | |
7e195e84 PK |
274 | const std::string strAddrProxy = pUiProxyIp->text().toStdString(); |
275 | CService addrProxy; | |
276 | ||
277 | /* Check for a valid IPv4 / IPv6 address */ | |
278 | if (!(fProxyIpValid = LookupNumeric(strAddrProxy.c_str(), addrProxy))) | |
1376a542 | 279 | { |
7e195e84 PK |
280 | disableOkButton(); |
281 | pUiProxyIp->setValid(false); | |
282 | ui->statusLabel->setStyleSheet("QLabel { color: red; }"); | |
283 | ui->statusLabel->setText(tr("The supplied proxy address is invalid.")); | |
1376a542 PK |
284 | } |
285 | else | |
286 | { | |
7e195e84 PK |
287 | enableOkButton(); |
288 | ui->statusLabel->clear(); | |
1376a542 PK |
289 | } |
290 | } | |
291 | ||
c4443c2b | 292 | bool OptionsDialog::eventFilter(QObject *object, QEvent *event) |
c3e0734d | 293 | { |
1376a542 | 294 | if(event->type() == QEvent::FocusOut) |
c4443c2b | 295 | { |
1376a542 | 296 | if(object == ui->proxyIp) |
c4443c2b | 297 | { |
7e195e84 | 298 | emit proxyIpChecks(ui->proxyIp, ui->proxyPort->text().toInt()); |
c4443c2b PK |
299 | } |
300 | } | |
301 | return QDialog::eventFilter(object, event); | |
e285ffcd | 302 | } |