tnetwork/gui: unify host/port input fields to single server str - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 9e57ae630ba96e6d2c40288d2633aeca8d20764d DIR parent b2cfaddff25b93189e8fb26f04fe9667958fe2d6 HTML Author: SomberNight <somber.night@protonmail.com> Date: Thu, 16 Apr 2020 21:12:23 +0200 network/gui: unify host/port input fields to single server str This allows optionally specifying the protocol for the main server. fixes #6095 fixes #5278 Diffstat: M electrum/gui/kivy/main_window.py | 6 ++---- M electrum/gui/kivy/uix/ui_screens/s… | 23 ++++------------------- M electrum/gui/qt/network_dialog.py | 51 ++++++++----------------------- M electrum/interface.py | 24 +++++++++++++++++++++++- M electrum/network.py | 6 +----- 5 files changed, 42 insertions(+), 68 deletions(-) --- DIR diff --git a/electrum/gui/kivy/main_window.py b/electrum/gui/kivy/main_window.py t@@ -145,13 +145,11 @@ class ElectrumWindow(App): servers = self.network.get_servers() ChoiceDialog(_('Choose a server'), sorted(servers), popup.ids.host.text, cb2).open() - def maybe_switch_to_server(self, *, host: str, port: str): + def maybe_switch_to_server(self, server_str: str): from electrum.interface import ServerAddr net_params = self.network.get_parameters() try: - server = ServerAddr(host=host, - port=port, - protocol=net_params.server.protocol) + server = ServerAddr.from_str_with_inference(server_str) except Exception as e: self.show_error(_("Invalid server details: {}").format(repr(e))) return DIR diff --git a/electrum/gui/kivy/uix/ui_screens/server.kv b/electrum/gui/kivy/uix/ui_screens/server.kv t@@ -1,5 +1,3 @@ -#:import ServerAddr electrum.interface.ServerAddr - Popup: id: nd title: _('Server') t@@ -18,27 +16,14 @@ Popup: height: '36dp' size_hint_x: 1 size_hint_y: None - text: _('Host') + ':' + text: _('Server') + ':' TextInput: - id: host + id: server_str multiline: False height: '36dp' size_hint_x: 3 size_hint_y: None - text: app.network.get_parameters().server.host - Label: - height: '36dp' - size_hint_x: 1 - size_hint_y: None - text: _('Port') + ':' - TextInput: - id: port - multiline: False - input_type: 'number' - height: '36dp' - size_hint_x: 3 - size_hint_y: None - text: str(app.network.get_parameters().server.port) + text: app.network.get_parameters().server.net_addr_str() Widget Button: id: chooser t@@ -58,5 +43,5 @@ Popup: height: '48dp' text: _('OK') on_release: - app.maybe_switch_to_server(host=str(root.ids.host.text), port=str(root.ids.port.text)) + app.maybe_switch_to_server(str(root.ids.server_str.text)) nd.dismiss() DIR diff --git a/electrum/gui/qt/network_dialog.py b/electrum/gui/qt/network_dialog.py t@@ -36,8 +36,8 @@ from PyQt5.QtGui import QFontMetrics from electrum.i18n import _ from electrum import constants, blockchain, util -from electrum.interface import ServerAddr -from electrum.network import Network, PREFERRED_NETWORK_PROTOCOL +from electrum.interface import ServerAddr, PREFERRED_NETWORK_PROTOCOL +from electrum.network import Network from electrum.logging import get_logger from .util import (Buttons, CloseButton, HelpButton, read_QIcon, char_width_in_lineedit, t@@ -171,8 +171,7 @@ class ServerListWidget(QTreeWidget): menu.exec_(self.viewport().mapToGlobal(position)) def set_server(self, server: ServerAddr): - self.parent.server_host.setText(server.host) - self.parent.server_port.setText(str(server.port)) + self.parent.server_e.setText(server.net_addr_str()) self.parent.set_server() def keyPressEvent(self, event): t@@ -230,15 +229,12 @@ class NetworkChoiceLayout(object): grid = QGridLayout(server_tab) grid.setSpacing(8) - self.server_host = QLineEdit() - self.server_host.setFixedWidth(fixed_width_hostname) - self.server_port = QLineEdit() - self.server_port.setFixedWidth(fixed_width_port) + self.server_e = QLineEdit() + self.server_e.setFixedWidth(fixed_width_hostname + fixed_width_port) self.autoconnect_cb = QCheckBox(_('Select server automatically')) self.autoconnect_cb.setEnabled(self.config.is_modifiable('auto_connect')) - self.server_host.editingFinished.connect(self.set_server) - self.server_port.editingFinished.connect(self.set_server) + self.server_e.editingFinished.connect(self.set_server) self.autoconnect_cb.clicked.connect(self.set_server) self.autoconnect_cb.clicked.connect(self.update) t@@ -250,8 +246,7 @@ class NetworkChoiceLayout(object): grid.addWidget(HelpButton(msg), 0, 4) grid.addWidget(QLabel(_('Server') + ':'), 1, 0) - grid.addWidget(self.server_host, 1, 1, 1, 2) - grid.addWidget(self.server_port, 1, 3) + grid.addWidget(self.server_e, 1, 1, 1, 3) label = _('Server peers') if network.is_connected() else _('Default Servers') grid.addWidget(QLabel(label), 2, 0, 1, 5) t@@ -355,20 +350,18 @@ class NetworkChoiceLayout(object): def enable_set_server(self): if self.config.is_modifiable('server'): enabled = not self.autoconnect_cb.isChecked() - self.server_host.setEnabled(enabled) - self.server_port.setEnabled(enabled) + self.server_e.setEnabled(enabled) self.servers_list.setEnabled(enabled) else: - for w in [self.autoconnect_cb, self.server_host, self.server_port, self.servers_list]: + for w in [self.autoconnect_cb, self.server_e, self.servers_list]: w.setEnabled(False) def update(self): net_params = self.network.get_parameters() server = net_params.server proxy_config, auto_connect = net_params.proxy, net_params.auto_connect - if not self.server_host.hasFocus() and not self.server_port.hasFocus(): - self.server_host.setText(server.host) - self.server_port.setText(str(server.port)) + if not self.server_e.hasFocus(): + self.server_e.setText(server.net_addr_str()) self.autoconnect_cb.setChecked(auto_connect) interface = self.network.interface t@@ -425,33 +418,13 @@ class NetworkChoiceLayout(object): self.network.run_from_another_thread(self.network.follow_chain_given_server(server)) self.update() - def change_server(self, host, protocol): - pp = self.servers.get(host, constants.net.DEFAULT_PORTS) - if protocol and protocol not in protocol_letters: - protocol = None - if protocol: - port = pp.get(protocol) - if port is None: - protocol = None - if not protocol: - if 's' in pp.keys(): - protocol = 's' - port = pp.get(protocol) - else: - protocol = list(pp.keys())[0] - port = pp.get(protocol) - self.server_host.setText(host) - self.server_port.setText(port) - def accept(self): pass def set_server(self): net_params = self.network.get_parameters() try: - server = ServerAddr(host=str(self.server_host.text()), - port=str(self.server_port.text()), - protocol=net_params.server.protocol) + server = ServerAddr.from_str_with_inference(str(self.server_e.text())) except Exception: return net_params = net_params._replace(server=server, DIR diff --git a/electrum/interface.py b/electrum/interface.py t@@ -65,6 +65,10 @@ BUCKET_NAME_OF_ONION_SERVERS = 'onion' MAX_INCOMING_MSG_SIZE = 1_000_000 # in bytes +_KNOWN_NETWORK_PROTOCOLS = {'t', 's'} +PREFERRED_NETWORK_PROTOCOL = 's' +assert PREFERRED_NETWORK_PROTOCOL in _KNOWN_NETWORK_PROTOCOLS + class NetworkTimeout: # seconds t@@ -212,7 +216,7 @@ class ServerAddr: net_addr = NetAddress(host, port) # this validates host and port except Exception as e: raise ValueError(f"cannot construct ServerAddr: invalid host or port (host={host}, port={port})") from e - if protocol not in ('s', 't'): + if protocol not in _KNOWN_NETWORK_PROTOCOLS: raise ValueError(f"invalid network protocol: {protocol}") self.host = str(net_addr.host) # canonical form (if e.g. IPv6 address) self.port = int(net_addr.port) t@@ -225,6 +229,24 @@ class ServerAddr: host, port, protocol = str(s).rsplit(':', 2) return ServerAddr(host=host, port=port, protocol=protocol) + @classmethod + def from_str_with_inference(cls, s: str) -> Optional['ServerAddr']: + """Construct ServerAddr from str, guessing missing details. + Ongoing compatibility not guaranteed. + """ + if not s: + return None + items = str(s).rsplit(':', 2) + if len(items) < 2: + return None # although maybe we could guess the port too? + host = items[0] + port = items[1] + if len(items) >= 3: + protocol = items[2] + else: + protocol = PREFERRED_NETWORK_PROTOCOL + return ServerAddr(host=host, port=port, protocol=protocol) + def __str__(self): return '{}:{}'.format(self.net_addr_str(), self.protocol) DIR diff --git a/electrum/network.py b/electrum/network.py t@@ -53,7 +53,7 @@ from . import bitcoin from . import dns_hacks from .transaction import Transaction from .blockchain import Blockchain, HEADER_SIZE -from .interface import (Interface, +from .interface import (Interface, PREFERRED_NETWORK_PROTOCOL, RequestTimedOut, NetworkTimeout, BUCKET_NAME_OF_ONION_SERVERS, NetworkException, RequestCorrupted, ServerAddr) from .version import PROTOCOL_VERSION t@@ -75,10 +75,6 @@ NUM_TARGET_CONNECTED_SERVERS = 10 NUM_STICKY_SERVERS = 4 NUM_RECENT_SERVERS = 20 -_KNOWN_NETWORK_PROTOCOLS = {'t', 's'} -PREFERRED_NETWORK_PROTOCOL = 's' -assert PREFERRED_NETWORK_PROTOCOL in _KNOWN_NETWORK_PROTOCOLS - def parse_servers(result: Sequence[Tuple[str, str, List[str]]]) -> Dict[str, dict]: """ parse servers list into dict format"""