Browse Source

qt block explorer: allow custom URL

The QTextEdit expects values such as (one per line):
```
https://blockstream.info/testnet/
https://192.168.0.38:3021/
("https://blockstream.info/testnet/", {'tx': 'tx/', 'addr': 'address/'})
```

closes #4831
patch-4
SomberNight 4 years ago
parent
commit
1abecf25c9
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 44
      electrum/gui/qt/settings_dialog.py
  2. 36
      electrum/util.py

44
electrum/gui/qt/settings_dialog.py

@ -23,13 +23,14 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE. # SOFTWARE.
import ast
from typing import Optional, TYPE_CHECKING from typing import Optional, TYPE_CHECKING
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QComboBox, QTabWidget, from PyQt5.QtWidgets import (QComboBox, QTabWidget,
QSpinBox, QFileDialog, QCheckBox, QLabel, QSpinBox, QFileDialog, QCheckBox, QLabel,
QVBoxLayout, QGridLayout, QLineEdit, QVBoxLayout, QGridLayout, QLineEdit,
QPushButton, QWidget) QPushButton, QWidget, QHBoxLayout)
from electrum.i18n import _ from electrum.i18n import _
from electrum import util, coinchooser, paymentrequest from electrum import util, coinchooser, paymentrequest
@ -328,16 +329,45 @@ Use this if you want your local watchtower to keep running after you close your
tx_widgets.append((outrounding_cb, None)) tx_widgets.append((outrounding_cb, None))
block_explorers = sorted(util.block_explorer_info().keys()) block_explorers = sorted(util.block_explorer_info().keys())
BLOCK_EX_CUSTOM_ITEM = _("Custom URL")
if BLOCK_EX_CUSTOM_ITEM in block_explorers: # malicious translation?
block_explorers.remove(BLOCK_EX_CUSTOM_ITEM)
block_explorers.append(BLOCK_EX_CUSTOM_ITEM)
msg = _('Choose which online block explorer to use for functions that open a web browser') msg = _('Choose which online block explorer to use for functions that open a web browser')
block_ex_label = HelpLabel(_('Online Block Explorer') + ':', msg) block_ex_label = HelpLabel(_('Online Block Explorer') + ':', msg)
block_ex_combo = QComboBox() block_ex_combo = QComboBox()
block_ex_custom_e = QLineEdit(self.config.get('block_explorer_custom') or '')
block_ex_combo.addItems(block_explorers) block_ex_combo.addItems(block_explorers)
block_ex_combo.setCurrentIndex(block_ex_combo.findText(util.block_explorer(self.config))) block_ex_combo.setCurrentIndex(
def on_be(x): block_ex_combo.findText(util.block_explorer(self.config) or BLOCK_EX_CUSTOM_ITEM))
be_result = block_explorers[block_ex_combo.currentIndex()] def showhide_block_ex_custom_e():
self.config.set_key('block_explorer', be_result, True) block_ex_custom_e.setVisible(block_ex_combo.currentText() == BLOCK_EX_CUSTOM_ITEM)
block_ex_combo.currentIndexChanged.connect(on_be) showhide_block_ex_custom_e()
tx_widgets.append((block_ex_label, block_ex_combo)) def on_be_combo(x):
if block_ex_combo.currentText() == BLOCK_EX_CUSTOM_ITEM:
on_be_edit()
else:
be_result = block_explorers[block_ex_combo.currentIndex()]
self.config.set_key('block_explorer_custom', None, False)
self.config.set_key('block_explorer', be_result, True)
showhide_block_ex_custom_e()
block_ex_combo.currentIndexChanged.connect(on_be_combo)
def on_be_edit():
val = block_ex_custom_e.text()
try:
val = ast.literal_eval(val) # to also accept tuples
except:
pass
self.config.set_key('block_explorer_custom', val)
block_ex_custom_e.editingFinished.connect(on_be_edit)
block_ex_hbox = QHBoxLayout()
block_ex_hbox.setContentsMargins(0, 0, 0, 0)
block_ex_hbox.setSpacing(0)
block_ex_hbox.addWidget(block_ex_combo)
block_ex_hbox.addWidget(block_ex_custom_e)
block_ex_hbox_w = QWidget()
block_ex_hbox_w.setLayout(block_ex_hbox)
tx_widgets.append((block_ex_label, block_ex_hbox_w))
# Fiat Currency # Fiat Currency
hist_checkbox = QCheckBox() hist_checkbox = QCheckBox()

36
electrum/util.py

@ -796,19 +796,43 @@ testnet_block_explorers = {
{'tx': 'tx/', 'addr': 'address/'}), {'tx': 'tx/', 'addr': 'address/'}),
} }
_block_explorer_default_api_loc = {'tx': 'tx/', 'addr': 'address/'}
def block_explorer_info(): def block_explorer_info():
from . import constants from . import constants
return mainnet_block_explorers if not constants.net.TESTNET else testnet_block_explorers return mainnet_block_explorers if not constants.net.TESTNET else testnet_block_explorers
def block_explorer(config: 'SimpleConfig') -> str:
from . import constants def block_explorer(config: 'SimpleConfig') -> Optional[str]:
"""Returns name of selected block explorer,
or None if a custom one (not among hardcoded ones) is configured.
"""
if config.get('block_explorer_custom') is not None:
return None
default_ = 'Blockstream.info' default_ = 'Blockstream.info'
be_key = config.get('block_explorer', default_) be_key = config.get('block_explorer', default_)
be = block_explorer_info().get(be_key) be_tuple = block_explorer_info().get(be_key)
return be_key if be is not None else default_ if be_tuple is None:
be_key = default_
assert isinstance(be_key, str), f"{be_key!r} should be str"
return be_key
def block_explorer_tuple(config: 'SimpleConfig') -> Optional[Tuple[str, dict]]: def block_explorer_tuple(config: 'SimpleConfig') -> Optional[Tuple[str, dict]]:
return block_explorer_info().get(block_explorer(config)) custom_be = config.get('block_explorer_custom')
if custom_be:
if isinstance(custom_be, str):
return custom_be, _block_explorer_default_api_loc
if isinstance(custom_be, (tuple, list)) and len(custom_be) == 2:
return tuple(custom_be)
_logger.warning(f"not using 'block_explorer_custom' from config. "
f"expected a str or a pair but got {custom_be!r}")
return None
else:
# using one of the hardcoded block explorers
return block_explorer_info().get(block_explorer(config))
def block_explorer_URL(config: 'SimpleConfig', kind: str, item: str) -> Optional[str]: def block_explorer_URL(config: 'SimpleConfig', kind: str, item: str) -> Optional[str]:
be_tuple = block_explorer_tuple(config) be_tuple = block_explorer_tuple(config)
@ -818,6 +842,8 @@ def block_explorer_URL(config: 'SimpleConfig', kind: str, item: str) -> Optional
kind_str = explorer_dict.get(kind) kind_str = explorer_dict.get(kind)
if kind_str is None: if kind_str is None:
return return
if explorer_url[-1] != "/":
explorer_url += "/"
url_parts = [explorer_url, kind_str, item] url_parts = [explorer_url, kind_str, item]
return ''.join(url_parts) return ''.join(url_parts)

Loading…
Cancel
Save