Merge pull request #6965 from SomberNight/202101_custom_block_explorer
qt block explorer: allow custom URL
This commit is contained in:
@@ -23,13 +23,14 @@
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import ast
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import (QComboBox, QTabWidget,
|
||||
QSpinBox, QFileDialog, QCheckBox, QLabel,
|
||||
QVBoxLayout, QGridLayout, QLineEdit,
|
||||
QPushButton, QWidget)
|
||||
QPushButton, QWidget, QHBoxLayout)
|
||||
|
||||
from electrum.i18n import _
|
||||
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))
|
||||
|
||||
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')
|
||||
block_ex_label = HelpLabel(_('Online Block Explorer') + ':', msg)
|
||||
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.setCurrentIndex(block_ex_combo.findText(util.block_explorer(self.config)))
|
||||
def on_be(x):
|
||||
be_result = block_explorers[block_ex_combo.currentIndex()]
|
||||
self.config.set_key('block_explorer', be_result, True)
|
||||
block_ex_combo.currentIndexChanged.connect(on_be)
|
||||
tx_widgets.append((block_ex_label, block_ex_combo))
|
||||
block_ex_combo.setCurrentIndex(
|
||||
block_ex_combo.findText(util.block_explorer(self.config) or BLOCK_EX_CUSTOM_ITEM))
|
||||
def showhide_block_ex_custom_e():
|
||||
block_ex_custom_e.setVisible(block_ex_combo.currentText() == BLOCK_EX_CUSTOM_ITEM)
|
||||
showhide_block_ex_custom_e()
|
||||
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
|
||||
hist_checkbox = QCheckBox()
|
||||
|
||||
@@ -796,19 +796,43 @@ testnet_block_explorers = {
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
}
|
||||
|
||||
_block_explorer_default_api_loc = {'tx': 'tx/', 'addr': 'address/'}
|
||||
|
||||
|
||||
def block_explorer_info():
|
||||
from . import constants
|
||||
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'
|
||||
be_key = config.get('block_explorer', default_)
|
||||
be = block_explorer_info().get(be_key)
|
||||
return be_key if be is not None else default_
|
||||
be_tuple = block_explorer_info().get(be_key)
|
||||
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]]:
|
||||
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]:
|
||||
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)
|
||||
if kind_str is None:
|
||||
return
|
||||
if explorer_url[-1] != "/":
|
||||
explorer_url += "/"
|
||||
url_parts = [explorer_url, kind_str, item]
|
||||
return ''.join(url_parts)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user