network dialog: replace checkboxes with tri-state connect_mode ComboBox
If oneserver is enabled, display 'Fork detection disabled' in the split_label
This commit is contained in:
@@ -104,3 +104,34 @@ MSG_TERMS_OF_USE = (
|
|||||||
)
|
)
|
||||||
TERMS_OF_USE_LATEST_VERSION : int = 1 # bump this if we want users re-prompted due to changes
|
TERMS_OF_USE_LATEST_VERSION : int = 1 # bump this if we want users re-prompted due to changes
|
||||||
|
|
||||||
|
|
||||||
|
MSG_CONNECTMODE_AUTOCONNECT = _('Auto-connect')
|
||||||
|
MSG_CONNECTMODE_MANUAL = _('Manual server selection')
|
||||||
|
MSG_CONNECTMODE_ONESERVER = _('Connect only to a single server')
|
||||||
|
|
||||||
|
MSG_CONNECTMODE_SERVER_HELP = _(
|
||||||
|
"Electrum connects to a unique server in order to receive your transaction history. "
|
||||||
|
"This server will learn your wallet adddresses."
|
||||||
|
)
|
||||||
|
MSG_CONNECTMODE_NODES_HELP = _(
|
||||||
|
"In addition to your history server, Electrum will try to maintain connections with ~10 extra servers, in order to download block headers and find out the longest blockchain. "
|
||||||
|
"These servers are only used for block header notifications and fee estimates; they do not learn your wallet addresses. "
|
||||||
|
"Getting block headers from multiple sources is useful to detect lagging servers and forks. "
|
||||||
|
"Fork detection is security-critical for determining number of confirmations."
|
||||||
|
)
|
||||||
|
|
||||||
|
MSG_CONNECTMODE_AUTOCONNECT_HELP = _(
|
||||||
|
"Electrum will always use a history server that is on the longest blockchain. "
|
||||||
|
"If your current server is unresponsive or lagging, Electrum will switch to another server."
|
||||||
|
)
|
||||||
|
|
||||||
|
MSG_CONNECTMODE_MANUAL_HELP = _(
|
||||||
|
"Electrum will stay with the server you selected. It will warn you if your server is lagging."
|
||||||
|
)
|
||||||
|
|
||||||
|
MSG_CONNECTMODE_ONESERVER_HELP = _(
|
||||||
|
"Electrum will stay with the server you selected, and it will not connect to additional nodes. "
|
||||||
|
"This will disable fork detection. "
|
||||||
|
"This mode is only intended for connecting to your own fully trusted server. "
|
||||||
|
"Using this option on a public server is a security risk and is discouraged."
|
||||||
|
)
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ from electrum.interface import ServerAddr, PREFERRED_NETWORK_PROTOCOL
|
|||||||
from electrum.network import Network, ProxySettings, is_valid_host, is_valid_port
|
from electrum.network import Network, ProxySettings, is_valid_host, is_valid_port
|
||||||
from electrum.logging import get_logger
|
from electrum.logging import get_logger
|
||||||
from electrum.util import is_valid_websocket_url
|
from electrum.util import is_valid_websocket_url
|
||||||
|
from electrum.gui import messages
|
||||||
|
|
||||||
from .util import (
|
from .util import (
|
||||||
Buttons, CloseButton, HelpButton, read_QIcon, char_width_in_lineedit, PasswordLineEdit, QtEventListener,
|
Buttons, CloseButton, HelpButton, read_QIcon, char_width_in_lineedit, PasswordLineEdit, QtEventListener,
|
||||||
@@ -61,7 +62,7 @@ class NetworkDialog(QDialog, QtEventListener):
|
|||||||
self._blockchain_tab = ServerWidget(network)
|
self._blockchain_tab = ServerWidget(network)
|
||||||
self._proxy_tab = ProxyWidget(network)
|
self._proxy_tab = ProxyWidget(network)
|
||||||
self._nostr_tab = NostrWidget(network)
|
self._nostr_tab = NostrWidget(network)
|
||||||
tabs.addTab(self._blockchain_tab, _('Electrum servers'))
|
tabs.addTab(self._blockchain_tab, _('Server'))
|
||||||
tabs.addTab(self._nostr_tab, _('Nostr'))
|
tabs.addTab(self._nostr_tab, _('Nostr'))
|
||||||
tabs.addTab(self._proxy_tab, _('Proxy'))
|
tabs.addTab(self._proxy_tab, _('Proxy'))
|
||||||
vbox = QVBoxLayout(self)
|
vbox = QVBoxLayout(self)
|
||||||
@@ -362,7 +363,17 @@ class ProxyWidget(QWidget):
|
|||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
|
||||||
|
class ConnectMode(IntEnum):
|
||||||
|
AUTOCONNECT = 0
|
||||||
|
MANUAL = 1
|
||||||
|
ONESERVER = 2
|
||||||
|
|
||||||
class ServerWidget(QWidget, QtEventListener):
|
class ServerWidget(QWidget, QtEventListener):
|
||||||
|
CONNECT_MODES = {
|
||||||
|
ConnectMode.AUTOCONNECT: messages.MSG_CONNECTMODE_AUTOCONNECT,
|
||||||
|
ConnectMode.MANUAL: messages.MSG_CONNECTMODE_MANUAL,
|
||||||
|
ConnectMode.ONESERVER: messages.MSG_CONNECTMODE_ONESERVER,
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, network: Network, parent=None):
|
def __init__(self, network: Network, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@@ -373,46 +384,47 @@ class ServerWidget(QWidget, QtEventListener):
|
|||||||
|
|
||||||
grid = QGridLayout()
|
grid = QGridLayout()
|
||||||
|
|
||||||
msg = ' '.join([
|
self.connect_combo = QComboBox()
|
||||||
_("Electrum connects to several nodes in order to download block headers and find out the longest blockchain."),
|
for i, v in sorted(self.CONNECT_MODES.items()):
|
||||||
_("This blockchain is used to verify the transactions sent by your transaction server.")
|
self.connect_combo.addItem(v, i)
|
||||||
])
|
self.connect_combo.currentIndexChanged.connect(self.on_server_settings_changed)
|
||||||
|
grid.addWidget(QLabel(_('Connection mode') + ':'), 0, 0)
|
||||||
|
msg = (
|
||||||
|
f"""
|
||||||
|
{messages.MSG_CONNECTMODE_SERVER_HELP}<br/><br/>
|
||||||
|
{messages.MSG_CONNECTMODE_NODES_HELP}
|
||||||
|
<ul>
|
||||||
|
<li><b>{messages.MSG_CONNECTMODE_AUTOCONNECT}</b>: {messages.MSG_CONNECTMODE_AUTOCONNECT_HELP}</li>
|
||||||
|
<li><b>{messages.MSG_CONNECTMODE_MANUAL}</b>: {messages.MSG_CONNECTMODE_MANUAL_HELP}</li>
|
||||||
|
<li><b>{messages.MSG_CONNECTMODE_ONESERVER}</b>: {messages.MSG_CONNECTMODE_ONESERVER_HELP}</li>
|
||||||
|
</ul>
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
grid.addWidget(HelpButton(msg), 0, 4)
|
||||||
|
grid.addWidget(self.connect_combo, 0, 1, 1, 3)
|
||||||
self.status_label_header = QLabel(_('Status') + ':')
|
self.status_label_header = QLabel(_('Status') + ':')
|
||||||
self.status_label = QLabel('')
|
self.status_label = QLabel('')
|
||||||
self.status_label_helpbutton = HelpButton(msg)
|
self.status_label_helpbutton = HelpButton(messages.MSG_CONNECTMODE_NODES_HELP)
|
||||||
grid.addWidget(self.status_label_header, 0, 0)
|
grid.addWidget(self.status_label_header, 1, 0)
|
||||||
grid.addWidget(self.status_label, 0, 1, 1, 3)
|
grid.addWidget(self.status_label, 1, 1, 1, 3)
|
||||||
grid.addWidget(self.status_label_helpbutton, 0, 4)
|
grid.addWidget(self.status_label_helpbutton, 1, 4)
|
||||||
|
|
||||||
self.autoconnect_cb = QCheckBox(self.config.cv.NETWORK_AUTO_CONNECT.get_short_desc())
|
|
||||||
self.autoconnect_cb.stateChanged.connect(self.on_server_settings_changed)
|
|
||||||
|
|
||||||
grid.addWidget(self.autoconnect_cb, 1, 0, 1, 3)
|
|
||||||
grid.addWidget(HelpButton(self.config.cv.NETWORK_AUTO_CONNECT.get_long_desc()), 1, 4)
|
|
||||||
|
|
||||||
self.one_server_cb = QCheckBox(self.config.cv.NETWORK_ONESERVER.get_short_desc())
|
|
||||||
self.one_server_cb.setEnabled(self.config.cv.NETWORK_ONESERVER.is_modifiable())
|
|
||||||
self.one_server_cb.stateChanged.connect(self.on_server_settings_changed)
|
|
||||||
grid.addWidget(self.one_server_cb, 2, 0, 1, 3)
|
|
||||||
grid.addWidget(HelpButton(self.config.cv.NETWORK_ONESERVER.get_long_desc()), 2, 4)
|
|
||||||
|
|
||||||
self.server_e = QLineEdit()
|
self.server_e = QLineEdit()
|
||||||
self.server_e.editingFinished.connect(self.on_server_settings_changed)
|
self.server_e.editingFinished.connect(self.on_server_settings_changed)
|
||||||
msg = _("Electrum sends your wallet addresses to a single server, in order to receive your transaction history.")
|
grid.addWidget(QLabel(_('Server') + ':'), 4, 0)
|
||||||
grid.addWidget(QLabel(_('Server') + ':'), 3, 0)
|
grid.addWidget(self.server_e, 4, 1, 1, 3)
|
||||||
grid.addWidget(self.server_e, 3, 1, 1, 3)
|
grid.addWidget(HelpButton(messages.MSG_CONNECTMODE_SERVER_HELP), 4, 4)
|
||||||
grid.addWidget(HelpButton(msg), 3, 4)
|
|
||||||
|
|
||||||
msg = _('This is the height of your local copy of the blockchain.')
|
msg = _('This is the height of your local copy of the blockchain.')
|
||||||
self.height_label_header = QLabel(_('Blockchain') + ':')
|
self.height_label_header = QLabel(_('Blockchain') + ':')
|
||||||
self.height_label = QLabel('')
|
self.height_label = QLabel('')
|
||||||
self.height_label_helpbutton = HelpButton(msg)
|
self.height_label_helpbutton = HelpButton(msg)
|
||||||
grid.addWidget(self.height_label_header, 4, 0)
|
grid.addWidget(self.height_label_header, 2, 0)
|
||||||
grid.addWidget(self.height_label, 4, 1)
|
grid.addWidget(self.height_label, 2, 1)
|
||||||
grid.addWidget(self.height_label_helpbutton, 4, 4)
|
grid.addWidget(self.height_label_helpbutton, 2, 4)
|
||||||
|
|
||||||
self.split_label = QLabel('')
|
self.split_label = QLabel('')
|
||||||
grid.addWidget(self.split_label, 5, 0, 1, 3)
|
grid.addWidget(self.split_label, 3, 1, 1, 3)
|
||||||
|
|
||||||
self.layout().addLayout(grid)
|
self.layout().addLayout(grid)
|
||||||
|
|
||||||
@@ -439,32 +451,28 @@ class ServerWidget(QWidget, QtEventListener):
|
|||||||
self.nodes_list_widget.update() # NOTE: move event handling to widget itself?
|
self.nodes_list_widget.update() # NOTE: move event handling to widget itself?
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
def is_auto_connect(self):
|
||||||
|
return self.connect_combo.currentIndex() == ConnectMode.AUTOCONNECT
|
||||||
|
|
||||||
|
def is_one_server(self):
|
||||||
|
return self.connect_combo.currentIndex() == ConnectMode.ONESERVER
|
||||||
|
|
||||||
def on_server_settings_changed(self):
|
def on_server_settings_changed(self):
|
||||||
if not self.network._was_started:
|
if not self.network._was_started:
|
||||||
self.update()
|
self.update()
|
||||||
return
|
return
|
||||||
auto_connect = self.autoconnect_cb.isChecked()
|
|
||||||
one_server = self.one_server_cb.isChecked()
|
|
||||||
self.autoconnect_cb.setEnabled(not one_server and self.config.cv.NETWORK_AUTO_CONNECT.is_modifiable())
|
|
||||||
self.one_server_cb.setEnabled(not auto_connect and self.config.cv.NETWORK_ONESERVER.is_modifiable())
|
|
||||||
server = self.server_e.text().strip()
|
server = self.server_e.text().strip()
|
||||||
net_params = self.network.get_parameters()
|
net_params = self.network.get_parameters()
|
||||||
if server != net_params.server or auto_connect != net_params.auto_connect or one_server != net_params.oneserver:
|
if server != net_params.server or self.is_auto_connect() != net_params.auto_connect or self.is_one_server() != net_params.oneserver:
|
||||||
self.set_server()
|
self.set_server()
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
auto_connect = self.autoconnect_cb.isChecked()
|
self.server_e.setEnabled(self.config.cv.NETWORK_SERVER.is_modifiable() and not self.is_auto_connect())
|
||||||
one_server = self.one_server_cb.isChecked()
|
|
||||||
self.autoconnect_cb.setEnabled(not one_server and self.config.cv.NETWORK_AUTO_CONNECT.is_modifiable())
|
|
||||||
self.one_server_cb.setEnabled(not auto_connect and self.config.cv.NETWORK_ONESERVER.is_modifiable())
|
|
||||||
self.server_e.setEnabled(self.config.cv.NETWORK_SERVER.is_modifiable() and not auto_connect)
|
|
||||||
|
|
||||||
for item in [
|
for item in [
|
||||||
self.status_label_header, self.status_label, self.status_label_helpbutton,
|
self.status_label_header, self.status_label, self.status_label_helpbutton,
|
||||||
self.height_label_header, self.height_label, self.height_label_helpbutton]:
|
self.height_label_header, self.height_label, self.height_label_helpbutton]:
|
||||||
item.setVisible(self.network._was_started)
|
item.setVisible(self.network._was_started)
|
||||||
|
msg = _('Fork detection disabled') if self.is_one_server() else ''
|
||||||
msg = ''
|
|
||||||
if self.network._was_started:
|
if self.network._was_started:
|
||||||
# Network was started, so we don't run in initial setup wizard.
|
# Network was started, so we don't run in initial setup wizard.
|
||||||
# behavior in this case is to apply changes immediately.
|
# behavior in this case is to apply changes immediately.
|
||||||
@@ -477,8 +485,8 @@ class ServerWidget(QWidget, QtEventListener):
|
|||||||
chain = self.network.blockchain()
|
chain = self.network.blockchain()
|
||||||
forkpoint = chain.get_max_forkpoint()
|
forkpoint = chain.get_max_forkpoint()
|
||||||
name = chain.get_name()
|
name = chain.get_name()
|
||||||
msg = _('Chain split detected at block {0}').format(forkpoint) + '\n'
|
msg = _('Fork detected at block {0}').format(forkpoint) + '\n'
|
||||||
if auto_connect:
|
if self.is_auto_connect():
|
||||||
msg += _('You are following branch {}').format(name)
|
msg += _('You are following branch {}').format(name)
|
||||||
else:
|
else:
|
||||||
msg += _('Your server is on branch {0} ({1} blocks)').format(name, chain.get_branch_size())
|
msg += _('Your server is on branch {0} ({1} blocks)').format(name, chain.get_branch_size())
|
||||||
@@ -486,14 +494,13 @@ class ServerWidget(QWidget, QtEventListener):
|
|||||||
|
|
||||||
def update_from_config(self):
|
def update_from_config(self):
|
||||||
auto_connect = self.config.NETWORK_AUTO_CONNECT
|
auto_connect = self.config.NETWORK_AUTO_CONNECT
|
||||||
self.autoconnect_cb.setChecked(auto_connect)
|
|
||||||
one_server = self.config.NETWORK_ONESERVER
|
one_server = self.config.NETWORK_ONESERVER
|
||||||
self.one_server_cb.setChecked(one_server)
|
v = ConnectMode.AUTOCONNECT if auto_connect else ConnectMode.ONESERVER if one_server else ConnectMode.MANUAL
|
||||||
|
self.connect_combo.setCurrentIndex(v)
|
||||||
|
|
||||||
server = self.config.NETWORK_SERVER
|
server = self.config.NETWORK_SERVER
|
||||||
self.server_e.setText(server)
|
self.server_e.setText(server)
|
||||||
|
|
||||||
self.autoconnect_cb.setEnabled(self.config.cv.NETWORK_AUTO_CONNECT.is_modifiable() and not one_server)
|
|
||||||
self.one_server_cb.setEnabled(self.config.cv.NETWORK_ONESERVER.is_modifiable() and not auto_connect)
|
|
||||||
self.server_e.setEnabled(self.config.cv.NETWORK_SERVER.is_modifiable() and not auto_connect)
|
self.server_e.setEnabled(self.config.cv.NETWORK_SERVER.is_modifiable() and not auto_connect)
|
||||||
self.nodes_list_widget.setEnabled(self.config.cv.NETWORK_SERVER.is_modifiable())
|
self.nodes_list_widget.setEnabled(self.config.cv.NETWORK_SERVER.is_modifiable())
|
||||||
|
|
||||||
@@ -514,9 +521,11 @@ class ServerWidget(QWidget, QtEventListener):
|
|||||||
raise Exception("failed to parse server")
|
raise Exception("failed to parse server")
|
||||||
except Exception:
|
except Exception:
|
||||||
return
|
return
|
||||||
net_params = net_params._replace(server=server,
|
net_params = net_params._replace(
|
||||||
auto_connect=self.autoconnect_cb.isChecked(),
|
server=server,
|
||||||
oneserver=self.one_server_cb.isChecked())
|
auto_connect=self.is_auto_connect(),
|
||||||
|
oneserver=self.is_one_server(),
|
||||||
|
)
|
||||||
self.network.run_from_another_thread(self.network.set_parameters(net_params))
|
self.network.run_from_another_thread(self.network.set_parameters(net_params))
|
||||||
|
|
||||||
|
|
||||||
@@ -528,11 +537,16 @@ class NostrWidget(QWidget, QtEventListener):
|
|||||||
self.config = network.config
|
self.config = network.config
|
||||||
vbox = QVBoxLayout()
|
vbox = QVBoxLayout()
|
||||||
self.setLayout(vbox)
|
self.setLayout(vbox)
|
||||||
nostr_relays_label = HelpLabel.from_configvar(self.config.cv.NOSTR_RELAYS)
|
grid = QGridLayout()
|
||||||
|
nostr_relays_label = QLabel(self.config.cv.NOSTR_RELAYS.get_short_desc())
|
||||||
|
nostr_helpbutton = HelpButton(self.config.cv.NOSTR_RELAYS.get_long_desc())
|
||||||
|
grid.addWidget(nostr_relays_label, 0, 0)
|
||||||
|
grid.addWidget(nostr_helpbutton, 0, 1)
|
||||||
|
vbox.addLayout(grid)
|
||||||
|
|
||||||
self.relays_list = QListWidget()
|
self.relays_list = QListWidget()
|
||||||
self.relay_edit = QLineEdit()
|
self.relay_edit = QLineEdit()
|
||||||
self.relay_edit.textChanged.connect(self.on_relay_edited)
|
self.relay_edit.textChanged.connect(self.on_relay_edited)
|
||||||
vbox.addWidget(nostr_relays_label)
|
|
||||||
vbox.addWidget(self.relays_list)
|
vbox.addWidget(self.relays_list)
|
||||||
vbox.addStretch()
|
vbox.addStretch()
|
||||||
self.add_button = QPushButton(_('Add'))
|
self.add_button = QPushButton(_('Add'))
|
||||||
|
|||||||
Reference in New Issue
Block a user