Remove UPNP support & do some cleanup.
[novacoin.git] / src / qt / optionsdialog.cpp
1 #include "optionsdialog.h"
2 #include "ui_optionsdialog.h"
3
4 #include "bitcoinunits.h"
5 #include "monitoreddatamapper.h"
6 #include "netbase.h"
7 #include "optionsmodel.h"
8 #include "dialogwindowflags.h"
9
10 #include <QDir>
11 #include <QIntValidator>
12 #include <QLocale>
13 #include <QMessageBox>
14 #include <QRegExp>
15 #include <QRegExpValidator>
16 #include <QKeyEvent>
17
18 OptionsDialog::OptionsDialog(QWidget *parent) :
19     QWidget(parent, DIALOGWINDOWHINTS),
20     ui(new Ui::OptionsDialog),
21     model(0),
22     mapper(0),
23     fRestartWarningDisplayed_Proxy(false),
24     fRestartWarningDisplayed_Tor(false),
25     fRestartWarningDisplayed_Lang(false),
26     fRestartWarningDisplayed_URL(false),
27     fProxyIpValid(true),
28     fTorIpValid(true)
29 {
30     ui->setupUi(this);
31
32     /* Network elements init */
33     ui->proxyIp->setEnabled(false);
34     ui->proxyPort->setEnabled(false);
35     ui->proxyPort->setValidator(new QIntValidator(1, 65535, this));
36
37     ui->torIp->setEnabled(false);
38     ui->torPort->setEnabled(false);
39     ui->torPort->setValidator(new QIntValidator(1, 65535, this));
40     ui->TorOnly->setEnabled(false);
41     ui->torName->setEnabled(false);
42
43     ui->socksVersion->setEnabled(false);
44     ui->socksVersion->addItem("5", 5);
45     ui->socksVersion->addItem("4", 4);
46     ui->socksVersion->setCurrentIndex(0);
47
48     connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp, SLOT(setEnabled(bool)));
49     connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort, SLOT(setEnabled(bool)));
50     connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->socksVersion, SLOT(setEnabled(bool)));
51     connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Proxy()));
52
53     connect(ui->connectTor, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning_Tor()));
54     connect(ui->connectTor, SIGNAL(toggled(bool)), ui->torIp, SLOT(setEnabled(bool)));
55     connect(ui->connectTor, SIGNAL(toggled(bool)), ui->torPort, SLOT(setEnabled(bool)));
56     connect(ui->connectTor, SIGNAL(toggled(bool)), ui->TorOnly, SLOT(setEnabled(bool)));
57     connect(ui->connectTor, SIGNAL(toggled(bool)), ui->torName, SLOT(setEnabled(bool)));
58     connect(ui->TorOnly, SIGNAL(toggled(bool)), ui->connectSocks, SLOT(setDisabled(bool)));
59
60     ui->proxyIp->installEventFilter(this);
61     ui->torIp->installEventFilter(this);
62
63     /* Window elements init */
64 #ifdef Q_OS_MAC
65     ui->tabWindow->setVisible(false);
66 #endif
67
68     /* Display elements init */
69     QDir translations(":translations");
70     ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant(""));
71     foreach(const QString &langStr, translations.entryList())
72     {
73         QLocale locale(langStr);
74
75         /** check if the locale name consists of 2 parts (language_country) */
76         if(langStr.contains("_"))
77         {
78 #if QT_VERSION >= 0x040800
79             /** display language strings as "native language - native country (locale name)", e.g. "Deutsch - Deutschland (de)" */
80             ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") + locale.nativeCountryName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
81 #else
82             /** display language strings as "language - country (locale name)", e.g. "German - Germany (de)" */
83             ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" - ") + QLocale::countryToString(locale.country()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
84 #endif
85         }
86         else
87         {
88 #if QT_VERSION >= 0x040800
89             /** display language strings as "native language (locale name)", e.g. "Deutsch (de)" */
90             ui->lang->addItem(locale.nativeLanguageName() + QString(" (") + langStr + QString(")"), QVariant(langStr));
91 #else
92             /** display language strings as "language (locale name)", e.g. "German (de)" */
93             ui->lang->addItem(QLocale::languageToString(locale.language()) + QString(" (") + langStr + QString(")"), QVariant(langStr));
94 #endif
95         }
96     }
97
98 #if QT_VERSION >= 0x040700
99     ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
100 #endif
101
102
103     ui->unit->setModel(new BitcoinUnits(this));
104
105     /* Widget-to-option mapper */
106     mapper = new MonitoredDataMapper(this);
107     mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
108     mapper->setOrientation(Qt::Vertical);
109
110     /* enable apply button when data modified */
111     connect(mapper, SIGNAL(viewModified()), this, SLOT(enableApplyButton()));
112     /* disable apply button when new data loaded */
113     connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApplyButton()));
114     /* setup/change UI elements when proxy IP is invalid/valid */
115     connect(this, SIGNAL(proxyIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleProxyIpValid(QValidatedLineEdit *, bool)));
116     /* setup/change UI elements when Tor IP is invalid/valid */
117     connect(this, SIGNAL(torIpValid(QValidatedLineEdit *, bool)), this, SLOT(handleTorIpValid(QValidatedLineEdit *, bool)));
118 }
119
120 OptionsDialog::~OptionsDialog()
121 {
122     delete ui;
123 }
124
125 void OptionsDialog::setModel(OptionsModel *model)
126 {
127     this->model = model;
128
129     if(model)
130     {
131         connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
132
133         mapper->setModel(model);
134         setMapper();
135         mapper->toFirst();
136     }
137
138     /* update the display unit, to not use the default ("BTC") */
139     updateDisplayUnit();
140
141     /* warn only when language selection changes by user action (placed here so init via mapper doesn't trigger this) */
142     connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning_Lang()));
143     connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this, SLOT(showRestartWarning_URL()));
144
145     /* disable apply button after settings are loaded as there is nothing to save */
146     disableApplyButton();
147 }
148
149 void OptionsDialog::setMapper()
150 {
151     /* Main */
152     mapper->addMapping(ui->transactionFee, OptionsModel::Fee);
153     mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup);
154     mapper->addMapping(ui->detachDatabases, OptionsModel::DetachDatabases);
155
156     /* Network */
157     mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse);
158     mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP);
159     mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort);
160     mapper->addMapping(ui->socksVersion, OptionsModel::ProxySocksVersion);
161
162     mapper->addMapping(ui->connectTor, OptionsModel::TorUse);
163     mapper->addMapping(ui->torIp, OptionsModel::TorIP);
164     mapper->addMapping(ui->torPort, OptionsModel::TorPort);
165     mapper->addMapping(ui->TorOnly, OptionsModel::TorOnly);
166     mapper->addMapping(ui->torName, OptionsModel::TorName);
167
168
169     /* Window */
170 #ifndef Q_OS_MAC
171     mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
172     mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose);
173 #endif
174
175     /* Display */
176     mapper->addMapping(ui->lang, OptionsModel::Language);
177     mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
178     mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses);
179     mapper->addMapping(ui->coinControlFeatures, OptionsModel::CoinControlFeatures);
180     mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
181 }
182
183 void OptionsDialog::enableApplyButton()
184 {
185     ui->applyButton->setEnabled(true);
186 }
187
188 void OptionsDialog::disableApplyButton()
189 {
190     ui->applyButton->setEnabled(false);
191 }
192
193 void OptionsDialog::enableSaveButtons()
194 {
195     /* prevent enabling of the save buttons when data modified, if there is an invalid proxy address present */
196     if(fProxyIpValid && fTorIpValid)
197         setSaveButtonState(true);
198 }
199
200 void OptionsDialog::disableSaveButtons()
201 {
202     setSaveButtonState(false);
203 }
204
205 void OptionsDialog::setSaveButtonState(bool fState)
206 {
207     ui->applyButton->setEnabled(fState);
208     ui->okButton->setEnabled(fState);
209 }
210
211 void OptionsDialog::on_okButton_clicked()
212 {
213     mapper->submit();
214 //    accept();
215     close();
216 }
217
218 void OptionsDialog::on_cancelButton_clicked()
219 {
220 //    reject();
221     close();
222 }
223
224 void OptionsDialog::on_applyButton_clicked()
225 {
226     mapper->submit();
227     disableApplyButton();
228 }
229
230 void OptionsDialog::showRestartWarning_Proxy()
231 {
232     if(!fRestartWarningDisplayed_Proxy)
233     {
234         QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting NovaCoin."), QMessageBox::Ok);
235         fRestartWarningDisplayed_Proxy = true;
236     }
237 }
238
239 void OptionsDialog::showRestartWarning_Tor()
240 {
241     if(!fRestartWarningDisplayed_Proxy)
242     {
243         QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting NovaCoin."), QMessageBox::Ok);
244         fRestartWarningDisplayed_Tor = true;
245     }
246 }
247
248 void OptionsDialog::showRestartWarning_Lang()
249 {
250     if(!fRestartWarningDisplayed_Lang)
251     {
252         QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting NovaCoin."), QMessageBox::Ok);
253         fRestartWarningDisplayed_Lang = true;
254     }
255 }
256
257 void OptionsDialog::showRestartWarning_URL()
258 {
259     if(!fRestartWarningDisplayed_URL)
260     {
261         QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting NovaCoin."), QMessageBox::Ok);
262         fRestartWarningDisplayed_URL = true;
263     }
264 }
265
266
267 void OptionsDialog::updateDisplayUnit()
268 {
269     if(model)
270     {
271         /* Update transactionFee with the current unit */
272         ui->transactionFee->setDisplayUnit(model->getDisplayUnit());
273     }
274 }
275
276 void OptionsDialog::handleProxyIpValid(QValidatedLineEdit *object, bool fState)
277 {
278     // this is used in a check before re-enabling the save buttons
279     fProxyIpValid = fState;
280
281     if(fProxyIpValid)
282     {
283         enableSaveButtons();
284         ui->statusLabel->clear();
285     }
286     else
287     {
288         disableSaveButtons();
289         object->setValid(fProxyIpValid);
290         ui->statusLabel->setStyleSheet("QLabel { color: red; }");
291         ui->statusLabel->setText(tr("The supplied proxy address is invalid."));
292     }
293 }
294
295 void OptionsDialog::handleTorIpValid(QValidatedLineEdit *object, bool fState)
296 {
297     // this is used in a check before re-enabling the save buttons
298     fTorIpValid = fState;
299
300     if(fTorIpValid)
301     {
302         enableSaveButtons();
303         ui->statusLabel->clear();
304     }
305     else
306     {
307         disableSaveButtons();
308         object->setValid(fTorIpValid);
309         ui->statusLabel->setStyleSheet("QLabel { color: red; }");
310         ui->statusLabel->setText(tr("The supplied tor address is invalid."));
311     }
312 }
313
314 bool OptionsDialog::eventFilter(QObject *object, QEvent *event)
315 {
316     if(event->type() == QEvent::FocusOut)
317     {
318         if(object == ui->proxyIp)
319         {
320             CService addr;
321             /* Check proxyIp for a valid IPv4/IPv6 address and emit the proxyIpValid signal */
322             emit proxyIpValid(ui->proxyIp, LookupNumeric(ui->proxyIp->text().toStdString().c_str(), addr));
323         }
324
325         if(object == ui->torIp)
326         {
327             CService addr;
328             /* Check proxyIp for a valid IPv4/IPv6 address and emit the torIpValid signal */
329             emit torIpValid(ui->torIp, LookupNumeric(ui->torIp->text().toStdString().c_str(), addr));
330         }
331     }
332     return QWidget::eventFilter(object, event);
333 }
334
335 void OptionsDialog::keyPressEvent(QKeyEvent *event)
336 {
337 #ifdef ANDROID
338     if(windowType() != Qt::Widget && event->key() == Qt::Key_Back)
339     {
340         close();
341     }
342 #else
343     if(windowType() != Qt::Widget && event->key() == Qt::Key_Escape)
344     {
345         close();
346     }
347 #endif
348 }