Skip to content

Commit bcba04c

Browse files
committed
GUI/OptionsDialog: fix proxy field validation and checkbox handling
- Enable validation while typing for proxy fields (proxyIp, proxyPort, proxyIpTor, proxyPortTor) - Fix checkbox signal handling for Qt 6.7+ compatibility - Fix theme change color updates for QValidatedLineEdit fields - Add ProxyAddressValidator with inet_pton for proper IP validation - Ensure proxy fields are properly enabled/disabled based on checkbox state
1 parent 2954170 commit bcba04c

File tree

2 files changed

+122
-21
lines changed

2 files changed

+122
-21
lines changed

src/qt/forms/optionsdialog.ui

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@
473473
</widget>
474474
</item>
475475
<item>
476-
<widget class="QLineEdit" name="proxyPort">
476+
<widget class="QValidatedLineEdit" name="proxyPort">
477477
<property name="minimumSize">
478478
<size>
479479
<width>55</width>
@@ -660,7 +660,7 @@
660660
</widget>
661661
</item>
662662
<item>
663-
<widget class="QLineEdit" name="proxyPortTor">
663+
<widget class="QValidatedLineEdit" name="proxyPortTor">
664664
<property name="minimumSize">
665665
<size>
666666
<width>55</width>

src/qt/optionsdialog.cpp

Lines changed: 120 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,16 @@
3030
#include <util/strencodings.h>
3131
#include <chrono>
3232
#include <cmath>
33+
#include <regex>
3334
#include <utility>
3435

36+
#ifdef WIN32
37+
#include <winsock2.h>
38+
#include <ws2tcpip.h>
39+
#else
40+
#include <arpa/inet.h>
41+
#endif
42+
3543
#include <QApplication>
3644
#include <QBoxLayout>
3745
#include <QDataWidgetMapper>
@@ -278,13 +286,33 @@ OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet)
278286
ui->proxyPortTor->setEnabled(false);
279287
ui->proxyPortTor->setValidator(new QIntValidator(1, 65535, this));
280288

281-
connect(ui->connectSocks, &QPushButton::toggled, ui->proxyIp, &QWidget::setEnabled);
282-
connect(ui->connectSocks, &QPushButton::toggled, ui->proxyPort, &QWidget::setEnabled);
283-
connect(ui->connectSocks, &QPushButton::toggled, this, &OptionsDialog::updateProxyValidationState);
284-
285-
connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyIpTor, &QWidget::setEnabled);
286-
connect(ui->connectSocksTor, &QPushButton::toggled, ui->proxyPortTor, &QWidget::setEnabled);
287-
connect(ui->connectSocksTor, &QPushButton::toggled, this, &OptionsDialog::updateProxyValidationState);
289+
#if (QT_VERSION >= QT_VERSION_CHECK(6, 7, 0))
290+
connect(ui->connectSocks, &QCheckBox::checkStateChanged, [this](const Qt::CheckState state){
291+
const bool enabled = (state == Qt::Checked);
292+
ui->proxyIp->setEnabled(enabled);
293+
ui->proxyPort->setEnabled(enabled);
294+
updateProxyValidationState();
295+
});
296+
connect(ui->connectSocksTor, &QCheckBox::checkStateChanged, [this](const Qt::CheckState state){
297+
const bool enabled = (state == Qt::Checked);
298+
ui->proxyIpTor->setEnabled(enabled);
299+
ui->proxyPortTor->setEnabled(enabled);
300+
updateProxyValidationState();
301+
});
302+
#else
303+
connect(ui->connectSocks, &QCheckBox::stateChanged, [this](int state){
304+
const bool enabled = (state == Qt::Checked);
305+
ui->proxyIp->setEnabled(enabled);
306+
ui->proxyPort->setEnabled(enabled);
307+
updateProxyValidationState();
308+
});
309+
connect(ui->connectSocksTor, &QCheckBox::stateChanged, [this](int state){
310+
const bool enabled = (state == Qt::Checked);
311+
ui->proxyIpTor->setEnabled(enabled);
312+
ui->proxyPortTor->setEnabled(enabled);
313+
updateProxyValidationState();
314+
});
315+
#endif
288316

289317
ui->maxuploadtarget->setMinimum(144 /* MiB/day */);
290318
ui->maxuploadtarget->setMaximum(std::numeric_limits<int>::max());
@@ -720,10 +748,23 @@ OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet)
720748
/* setup/change UI elements when proxy IPs are invalid/valid */
721749
ui->proxyIp->setCheckValidator(new ProxyAddressValidator(parent));
722750
ui->proxyIpTor->setCheckValidator(new ProxyAddressValidator(parent));
751+
752+
// do not allow empty input for validation for all proxy fields
753+
ui->proxyIp->setAllowEmptyInput(false);
754+
ui->proxyIpTor->setAllowEmptyInput(false);
755+
ui->proxyPort->setAllowEmptyInput(false);
756+
ui->proxyPortTor->setAllowEmptyInput(false);
757+
758+
// Enable validation while typing for all proxy fields
759+
ui->proxyIp->setAllowValidationWhileEditing(true);
760+
ui->proxyPort->setAllowValidationWhileEditing(true);
761+
ui->proxyIpTor->setAllowValidationWhileEditing(true);
762+
ui->proxyPortTor->setAllowValidationWhileEditing(true);
763+
723764
connect(ui->proxyIp, &QValidatedLineEdit::validationDidChange, this, &OptionsDialog::updateProxyValidationState);
724765
connect(ui->proxyIpTor, &QValidatedLineEdit::validationDidChange, this, &OptionsDialog::updateProxyValidationState);
725-
connect(ui->proxyPort, &QLineEdit::textChanged, this, &OptionsDialog::updateProxyValidationState);
726-
connect(ui->proxyPortTor, &QLineEdit::textChanged, this, &OptionsDialog::updateProxyValidationState);
766+
connect(ui->proxyPort, &QValidatedLineEdit::validationDidChange, this, &OptionsDialog::updateProxyValidationState);
767+
connect(ui->proxyPortTor, &QValidatedLineEdit::validationDidChange, this, &OptionsDialog::updateProxyValidationState);
727768

728769
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
729770
ui->showTrayIcon->setChecked(false);
@@ -1152,6 +1193,16 @@ void OptionsDialog::on_okButton_clicked()
11521193
model->setData(model->index(OptionsModel::dustdynamic, 0), "off");
11531194
}
11541195

1196+
// Before mapper->submit()
1197+
if (!ui->connectSocks->isChecked()) {
1198+
ui->proxyIp->clear();
1199+
ui->proxyPort->clear();
1200+
}
1201+
if (!ui->connectSocksTor->isChecked()) {
1202+
ui->proxyIpTor->clear();
1203+
ui->proxyPortTor->clear();
1204+
}
1205+
11551206
mapper->submit();
11561207
accept();
11571208
updateDefaultProxyNets();
@@ -1174,11 +1225,13 @@ void OptionsDialog::on_showTrayIcon_stateChanged(int state)
11741225

11751226
void OptionsDialog::changeEvent(QEvent* e)
11761227
{
1228+
// First let the base class update all child widget palettes
1229+
// required for qvalidatedlineedit invalid colors to update properly
1230+
QWidget::changeEvent(e);
11771231
if (e->type() == QEvent::PaletteChange) {
1232+
// Then update theme colors with the new palette
11781233
updateThemeColors();
11791234
}
1180-
1181-
QWidget::changeEvent(e);
11821235
}
11831236

11841237
void OptionsDialog::togglePruneWarning(bool enabled)
@@ -1211,17 +1264,51 @@ void OptionsDialog::clearStatusLabel()
12111264

12121265
void OptionsDialog::updateProxyValidationState()
12131266
{
1214-
QValidatedLineEdit *pUiProxyIp = ui->proxyIp;
1215-
QValidatedLineEdit *otherProxyWidget = (pUiProxyIp == ui->proxyIpTor) ? ui->proxyIp : ui->proxyIpTor;
1216-
if (pUiProxyIp->isValid() && (!ui->proxyPort->isEnabled() || ui->proxyPort->text().toInt() > 0) && (!ui->proxyPortTor->isEnabled() || ui->proxyPortTor->text().toInt() > 0))
1267+
bool socksProxyEnabled = ui->connectSocks->isChecked();
1268+
bool torProxyEnabled = ui->connectSocksTor->isChecked();
1269+
1270+
bool proxyIpValid = ui->proxyIp->isValid();
1271+
bool proxyPortValid = ui->proxyPort->isValid();
1272+
bool proxyIpTorValid = ui->proxyIpTor->isValid();
1273+
bool proxyPortTorValid = ui->proxyPortTor->isValid();
1274+
1275+
// proxy is OK if: disabled OR (enabled AND valid ip and valid port)
1276+
bool socksProxyOk = !socksProxyEnabled || (proxyIpValid && proxyPortValid);
1277+
bool torProxyOk = !torProxyEnabled || (proxyIpTorValid && proxyPortTorValid);
1278+
1279+
// Both must be OK for the form to be valid
1280+
if (socksProxyOk && torProxyOk)
12171281
{
1218-
setOkButtonState(otherProxyWidget->isValid()); //only enable ok button if both proxies are valid
1282+
setOkButtonState(true);
12191283
clearStatusLabel();
12201284
}
12211285
else
12221286
{
12231287
setOkButtonState(false);
1224-
ui->statusLabel->setText(tr("The supplied proxy address is invalid."));
1288+
QStringList socksErrors;
1289+
1290+
if (socksProxyEnabled) {
1291+
if (!proxyIpValid && !proxyPortValid) {
1292+
socksErrors.append(tr("The supplied proxy address and port are invalid."));
1293+
} else if (!proxyIpValid) {
1294+
socksErrors.append(tr("The supplied proxy address is invalid."));
1295+
} else if (!proxyPortValid) {
1296+
socksErrors.append(tr("The supplied proxy port is invalid."));
1297+
}
1298+
}
1299+
if (torProxyEnabled) {
1300+
if (!proxyIpTorValid && !proxyPortTorValid) {
1301+
socksErrors.append(tr("The supplied Tor proxy address and port are invalid."));
1302+
} else if (!proxyIpTorValid) {
1303+
socksErrors.append(tr("The supplied Tor proxy address is invalid."));
1304+
} else if (!proxyPortTorValid) {
1305+
socksErrors.append(tr("The supplied Tor proxy port is invalid."));
1306+
}
1307+
}
1308+
1309+
if (socksErrors.size() > 0) {
1310+
ui->statusLabel->setText(socksErrors.join(" "));
1311+
}
12251312
}
12261313
}
12271314

@@ -1264,6 +1351,13 @@ void OptionsDialog::updateThemeColors()
12641351
const QColor networkport_warning = networkport_dark ? QColor("#FF8080") : QColor("#FF0000");
12651352
ui->networkPort->setStyleSheet(QStringLiteral("color: %1;").arg(networkport_warning.name()));
12661353
}
1354+
// Re-trigger validation on all qvalidatedlineedit input fields to update their styling
1355+
// including background and text color
1356+
// Use setText to trigger validation
1357+
if (!ui->proxyIp->isValid()) ui->proxyIp->setText(ui->proxyIp->text());
1358+
if (!ui->proxyPort->isValid()) ui->proxyPort->setText(ui->proxyPort->text());
1359+
if (!ui->proxyIpTor->isValid()) ui->proxyIpTor->setText(ui->proxyIpTor->text());
1360+
if (!ui->proxyPortTor->isValid()) ui->proxyPortTor->setText(ui->proxyPortTor->text());
12671361
}
12681362

12691363
ProxyAddressValidator::ProxyAddressValidator(QObject *parent) :
@@ -1278,10 +1372,17 @@ QValidator::State ProxyAddressValidator::validate(QString &input, int &pos) cons
12781372
std::string hostname;
12791373
if (!SplitHostPort(input.toStdString(), port, hostname) || port != 0) return QValidator::Invalid;
12801374

1281-
CService serv(LookupNumeric(input.toStdString(), DEFAULT_GUI_PROXY_PORT));
1282-
Proxy addrProxy = Proxy(serv, true);
1283-
if (addrProxy.IsValid())
1375+
// Check if it's a valid IPv4 address
1376+
struct sockaddr_in sa4;
1377+
if (inet_pton(AF_INET, hostname.c_str(), &sa4.sin_addr) == 1) {
12841378
return QValidator::Acceptable;
1379+
}
1380+
1381+
// Check if it's a valid IPv6 address
1382+
struct sockaddr_in6 sa6;
1383+
if (inet_pton(AF_INET6, hostname.c_str(), &sa6.sin6_addr) == 1) {
1384+
return QValidator::Acceptable;
1385+
}
12851386

12861387
return QValidator::Invalid;
12871388
}

0 commit comments

Comments
 (0)