Browse Source

qt: factor out remaining ChoicesLayout uses

master
Sander van Grieken 1 year ago
parent
commit
0277950247
No known key found for this signature in database
GPG Key ID: 9BCF8209EA402EBA
  1. 10
      electrum/gui/qt/main_window.py
  2. 3
      electrum/gui/qt/receive_tab.py
  3. 18
      electrum/gui/qt/seed_dialog.py
  4. 18
      electrum/gui/qt/send_tab.py
  5. 34
      electrum/gui/qt/util.py
  6. 13
      electrum/gui/qt/wallet_info_dialog.py
  7. 8
      electrum/gui/qt/wizard/wallet.py
  8. 4
      electrum/plugins/digitalbitbox/qt.py

10
electrum/gui/qt/main_window.py

@ -82,13 +82,13 @@ from .qrtextedit import ShowQRTextEdit, ScanQRTextEdit, ScanShowQRTextEdit
from .transaction_dialog import show_transaction from .transaction_dialog import show_transaction
from .fee_slider import FeeSlider, FeeComboBox from .fee_slider import FeeSlider, FeeComboBox
from .util import (read_QIcon, ColorScheme, text_dialog, icon_path, WaitingDialog, from .util import (read_QIcon, ColorScheme, text_dialog, icon_path, WaitingDialog,
WindowModalDialog, ChoicesLayout, HelpLabel, Buttons, WindowModalDialog, HelpLabel, Buttons,
OkButton, InfoButton, WWLabel, TaskThread, CancelButton, OkButton, InfoButton, WWLabel, TaskThread, CancelButton,
CloseButton, HelpButton, MessageBoxMixin, EnterButton, CloseButton, HelpButton, MessageBoxMixin, EnterButton,
import_meta_gui, export_meta_gui, import_meta_gui, export_meta_gui,
filename_field, address_field, char_width_in_lineedit, webopen, filename_field, address_field, char_width_in_lineedit, webopen,
TRANSACTION_FILE_EXTENSION_FILTER_ANY, MONOSPACE_FONT, TRANSACTION_FILE_EXTENSION_FILTER_ANY, MONOSPACE_FONT,
getOpenFileName, getSaveFileName, BlockingWaitingDialog, font_height) getOpenFileName, getSaveFileName, BlockingWaitingDialog, font_height, ChoiceWidget)
from .util import ButtonsLineEdit, ShowQRLineEdit from .util import ButtonsLineEdit, ShowQRLineEdit
from .util import QtEventListener, qt_event_listener, event_listener from .util import QtEventListener, qt_event_listener, event_listener
from .wizard.wallet import WIF_HELP_TEXT from .wizard.wallet import WIF_HELP_TEXT
@ -1376,15 +1376,15 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener):
title = _('Question') title = _('Question')
dialog = WindowModalDialog(self.top_level_window(), title=title) dialog = WindowModalDialog(self.top_level_window(), title=title)
dialog.setMinimumWidth(400) dialog.setMinimumWidth(400)
clayout = ChoicesLayout(msg, choices, checked_index=default_choice) choice_widget = ChoiceWidget(message=msg, choices=choices, selected=default_choice)
vbox = QVBoxLayout(dialog) vbox = QVBoxLayout(dialog)
vbox.addLayout(clayout.layout()) vbox.addWidget(choice_widget)
cancel_button = CancelButton(dialog) cancel_button = CancelButton(dialog)
vbox.addLayout(Buttons(cancel_button, OkButton(dialog))) vbox.addLayout(Buttons(cancel_button, OkButton(dialog)))
cancel_button.setFocus() cancel_button.setFocus()
if not dialog.exec_(): if not dialog.exec_():
return None return None
return clayout.selected_index() return choice_widget.selected_key
def handle_payment_identifier(self, text: str): def handle_payment_identifier(self, text: str):
pi = PaymentIdentifier(self.wallet, text) pi = PaymentIdentifier(self.wallet, text)

3
electrum/gui/qt/receive_tab.py

@ -194,7 +194,8 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
_('For Lightning requests, payments will not be accepted after the expiration.'), _('For Lightning requests, payments will not be accepted after the expiration.'),
]) ])
expiry = self.config.WALLET_PAYREQ_EXPIRY_SECONDS expiry = self.config.WALLET_PAYREQ_EXPIRY_SECONDS
v = self.window.query_choice(msg, pr_expiration_values(), title=_('Expiry'), default_choice=expiry) choices = list(pr_expiration_values().items())
v = self.window.query_choice(msg, choices, title=_('Expiry'), default_choice=expiry)
if v is None: if v is None:
return return
self.config.WALLET_PAYREQ_EXPIRY_SECONDS = v self.config.WALLET_PAYREQ_EXPIRY_SECONDS = v

18
electrum/gui/qt/seed_dialog.py

@ -37,8 +37,7 @@ from electrum import old_mnemonic
from electrum import slip39 from electrum import slip39
from .util import (Buttons, OkButton, WWLabel, ButtonsTextEdit, icon_path, from .util import (Buttons, OkButton, WWLabel, ButtonsTextEdit, icon_path,
EnterButton, CloseButton, WindowModalDialog, ColorScheme, EnterButton, CloseButton, WindowModalDialog, ColorScheme, font_height, ChoiceWidget)
ChoicesLayout, font_height)
from .qrtextedit import ShowQRTextEdit, ScanQRTextEdit from .qrtextedit import ShowQRTextEdit, ScanQRTextEdit
from .completion_text_edit import CompletionTextEdit from .completion_text_edit import CompletionTextEdit
@ -87,15 +86,15 @@ class SeedLayout(QVBoxLayout):
) )
if value in self.options or value == 'electrum' if value in self.options or value == 'electrum'
] ]
seed_type_values = [t[0] for t in seed_types]
if 'ext' in self.options: if 'ext' in self.options:
cb_ext = QCheckBox(_('Extend this seed with custom words')) cb_ext = QCheckBox(_('Extend this seed with custom words'))
cb_ext.setChecked(self.is_ext) cb_ext.setChecked(self.is_ext)
vbox.addWidget(cb_ext) vbox.addWidget(cb_ext)
if len(seed_types) >= 2: if len(seed_types) >= 2:
def f(choices_layout): def on_selected(idx):
self.seed_type = seed_type_values[choices_layout.selected_index()] self.seed_type = seed_type_choice.selected_key
self.is_seed = (lambda x: bool(x)) if self.seed_type != 'electrum' else self.saved_is_seed self.is_seed = (lambda x: bool(x)) if self.seed_type != 'electrum' else self.saved_is_seed
self.slip39_current_mnemonic_invalid = None self.slip39_current_mnemonic_invalid = None
self.seed_status.setText('') self.seed_status.setText('')
@ -120,16 +119,15 @@ class SeedLayout(QVBoxLayout):
self.initialize_completer() self.initialize_completer()
self.seed_warning.setText(msg) self.seed_warning.setText(msg)
checked_index = seed_type_values.index(self.seed_type) seed_type_choice = ChoiceWidget(message=_('Seed type'), choices=seed_types, selected=self.seed_type)
titles = [t[1] for t in seed_types] seed_type_choice.itemSelected.connect(on_selected)
clayout = ChoicesLayout(_('Seed type'), titles, on_clicked=f, checked_index=checked_index) vbox.addWidget(seed_type_choice)
vbox.addLayout(clayout.layout())
vbox.addLayout(Buttons(OkButton(dialog))) vbox.addLayout(Buttons(OkButton(dialog)))
if not dialog.exec_(): if not dialog.exec_():
return None return None
self.is_ext = cb_ext.isChecked() if 'ext' in self.options else False self.is_ext = cb_ext.isChecked() if 'ext' in self.options else False
self.seed_type = seed_type_values[clayout.selected_index()] if len(seed_types) >= 2 else 'electrum' self.seed_type = seed_type_choice.selected_key if len(seed_types) >= 2 else 'electrum'
self.updated.emit() self.updated.emit()
def __init__( def __init__(

18
electrum/gui/qt/send_tab.py

@ -672,31 +672,31 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
can_pay_with_swap = lnworker.suggest_swap_to_send(amount_sat, coins=coins) can_pay_with_swap = lnworker.suggest_swap_to_send(amount_sat, coins=coins)
rebalance_suggestion = lnworker.suggest_rebalance_to_send(amount_sat) rebalance_suggestion = lnworker.suggest_rebalance_to_send(amount_sat)
can_rebalance = bool(rebalance_suggestion) and self.window.num_tasks() == 0 can_rebalance = bool(rebalance_suggestion) and self.window.num_tasks() == 0
choices = {} choices = []
if can_rebalance: if can_rebalance:
msg = ''.join([ msg = ''.join([
_('Rebalance existing channels'), '\n', _('Rebalance existing channels'), '\n',
_('Move funds between your channels in order to increase your sending capacity.') _('Move funds between your channels in order to increase your sending capacity.')
]) ])
choices[0] = msg choices.append(('rebalance', msg))
if can_pay_with_new_channel: if can_pay_with_new_channel:
msg = ''.join([ msg = ''.join([
_('Open a new channel'), '\n', _('Open a new channel'), '\n',
_('You will be able to pay once the channel is open.') _('You will be able to pay once the channel is open.')
]) ])
choices[1] = msg choices.append(('new_channel', msg))
if can_pay_with_swap: if can_pay_with_swap:
msg = ''.join([ msg = ''.join([
_('Swap onchain funds for lightning funds'), '\n', _('Swap onchain funds for lightning funds'), '\n',
_('You will be able to pay once the swap is confirmed.') _('You will be able to pay once the swap is confirmed.')
]) ])
choices[2] = msg choices.append(('swap', msg))
if can_pay_onchain: if can_pay_onchain:
msg = ''.join([ msg = ''.join([
_('Pay onchain'), '\n', _('Pay onchain'), '\n',
_('Funds will be sent to the invoice fallback address.') _('Funds will be sent to the invoice fallback address.')
]) ])
choices[3] = msg choices.append(('onchain', msg))
msg = _('You cannot pay that invoice using Lightning.') msg = _('You cannot pay that invoice using Lightning.')
if lnworker and lnworker.channels: if lnworker and lnworker.channels:
num_sats_can_send = int(lnworker.num_sats_can_send()) num_sats_can_send = int(lnworker.num_sats_can_send())
@ -709,16 +709,16 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
r = self.window.query_choice(msg, choices) r = self.window.query_choice(msg, choices)
if r is not None: if r is not None:
self.save_pending_invoice() self.save_pending_invoice()
if r == 0: if r == 'rebalance':
chan1, chan2, delta = rebalance_suggestion chan1, chan2, delta = rebalance_suggestion
self.window.rebalance_dialog(chan1, chan2, amount_sat=delta) self.window.rebalance_dialog(chan1, chan2, amount_sat=delta)
elif r == 1: elif r == 'new_channel':
amount_sat, min_amount_sat = can_pay_with_new_channel amount_sat, min_amount_sat = can_pay_with_new_channel
self.window.new_channel_dialog(amount_sat=amount_sat, min_amount_sat=min_amount_sat) self.window.new_channel_dialog(amount_sat=amount_sat, min_amount_sat=min_amount_sat)
elif r == 2: elif r == 'swap':
chan, swap_recv_amount_sat = can_pay_with_swap chan, swap_recv_amount_sat = can_pay_with_swap
self.window.run_swap_dialog(is_reverse=False, recv_amount_sat=swap_recv_amount_sat, channels=[chan]) self.window.run_swap_dialog(is_reverse=False, recv_amount_sat=swap_recv_amount_sat, channels=[chan])
elif r == 3: elif r == 'onchain':
self.pay_onchain_dialog(invoice.get_outputs(), nonlocal_only=True) self.pay_onchain_dialog(invoice.get_outputs(), nonlocal_only=True)
return return

34
electrum/gui/qt/util.py

@ -422,40 +422,6 @@ def text_dialog(
return txt.toPlainText() return txt.toPlainText()
class ChoicesLayout(object):
def __init__(self, msg, choices, on_clicked=None, checked_index=0):
vbox = QVBoxLayout()
if len(msg) > 50:
vbox.addWidget(WWLabel(msg))
msg = ""
gb2 = QGroupBox(msg)
vbox.addWidget(gb2)
vbox2 = QVBoxLayout()
gb2.setLayout(vbox2)
self.group = group = QButtonGroup(gb2)
if isinstance(choices, list):
iterator = enumerate(choices)
else:
iterator = choices.items()
for i, c in iterator:
button = QRadioButton(gb2)
button.setText(c)
vbox2.addWidget(button)
group.addButton(button)
group.setId(button, i)
if i == checked_index:
button.setChecked(True)
if on_clicked:
group.buttonClicked.connect(partial(on_clicked, self))
self.vbox = vbox
def layout(self):
return self.vbox
def selected_index(self):
return self.group.checkedId()
class ChoiceWidget(QWidget): class ChoiceWidget(QWidget):
itemSelected = pyqtSignal([int], arguments=['index']) itemSelected = pyqtSignal([int], arguments=['index'])

13
electrum/gui/qt/wallet_info_dialog.py

@ -9,14 +9,13 @@ from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QLabel, QVBoxLayout, QGridLayout, from PyQt5.QtWidgets import (QLabel, QVBoxLayout, QGridLayout,
QHBoxLayout, QPushButton, QWidget, QStackedWidget) QHBoxLayout, QPushButton, QWidget, QStackedWidget)
from electrum import keystore
from electrum.plugin import run_hook from electrum.plugin import run_hook
from electrum.i18n import _ from electrum.i18n import _
from electrum.wallet import Multisig_Wallet from electrum.wallet import Multisig_Wallet
from .qrtextedit import ShowQRTextEdit from .qrtextedit import ShowQRTextEdit
from .util import (read_QIcon, WindowModalDialog, ChoicesLayout, Buttons, from .util import (read_QIcon, WindowModalDialog, Buttons,
WWLabel, CloseButton, HelpButton, font_height, ShowQRLineEdit) WWLabel, CloseButton, HelpButton, font_height, ShowQRLineEdit, ChoiceWidget)
if TYPE_CHECKING: if TYPE_CHECKING:
from .main_window import ElectrumWindow from .main_window import ElectrumWindow
@ -118,11 +117,11 @@ class WalletInfoDialog(WindowModalDialog):
else: else:
return _("keystore") + f' {idx+1}' return _("keystore") + f' {idx+1}'
labels = [label(idx, ks) for idx, ks in enumerate(wallet.get_keystores())] labels = [(idx, label(idx, ks)) for idx, ks in enumerate(wallet.get_keystores())]
on_click = lambda clayout: select_ks(clayout.selected_index()) keystore_choice = ChoiceWidget(message=_("Select keystore"), choices=labels)
labels_clayout = ChoicesLayout(_("Select keystore"), labels, on_click) keystore_choice.itemSelected.connect(lambda x: select_ks(x))
vbox.addLayout(labels_clayout.layout()) vbox.addWidget(keystore_choice)
for ks in keystores: for ks in keystores:
ks_w = QWidget() ks_w = QWidget()

8
electrum/gui/qt/wizard/wallet.py

@ -29,7 +29,7 @@ from electrum.gui.qt.bip39_recovery_dialog import Bip39RecoveryDialog
from electrum.gui.qt.password_dialog import PasswordLayout, PW_NEW, MSG_ENTER_PASSWORD, PasswordLayoutForHW from electrum.gui.qt.password_dialog import PasswordLayout, PW_NEW, MSG_ENTER_PASSWORD, PasswordLayoutForHW
from electrum.gui.qt.seed_dialog import SeedLayout, MSG_PASSPHRASE_WARN_ISSUE4566, KeysLayout from electrum.gui.qt.seed_dialog import SeedLayout, MSG_PASSPHRASE_WARN_ISSUE4566, KeysLayout
from electrum.gui.qt.util import (PasswordLineEdit, char_width_in_lineedit, WWLabel, InfoButton, font_height, from electrum.gui.qt.util import (PasswordLineEdit, char_width_in_lineedit, WWLabel, InfoButton, font_height,
ChoiceWidget, MessageBoxMixin, WindowModalDialog, ChoicesLayout, CancelButton, ChoiceWidget, MessageBoxMixin, WindowModalDialog, CancelButton,
Buttons, OkButton, icon_path) Buttons, OkButton, icon_path)
if TYPE_CHECKING: if TYPE_CHECKING:
@ -243,15 +243,15 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard, MessageBoxMixin):
title = _('Question') title = _('Question')
dialog = WindowModalDialog(self.top_level_window(), title=title) dialog = WindowModalDialog(self.top_level_window(), title=title)
dialog.setMinimumWidth(400) dialog.setMinimumWidth(400)
clayout = ChoicesLayout(msg, choices, checked_index=default_choice) choice_widget = ChoiceWidget(message=msg, choices=choices, selected=default_choice)
vbox = QVBoxLayout(dialog) vbox = QVBoxLayout(dialog)
vbox.addLayout(clayout.layout()) vbox.addWidget(choice_widget)
cancel_button = CancelButton(dialog) cancel_button = CancelButton(dialog)
vbox.addLayout(Buttons(cancel_button, OkButton(dialog))) vbox.addLayout(Buttons(cancel_button, OkButton(dialog)))
cancel_button.setFocus() cancel_button.setFocus()
if not dialog.exec_(): if not dialog.exec_():
return None return None
return clayout.selected_index() return choice_widget.selected_key
class WalletWizardComponent(WizardComponent, ABC): class WalletWizardComponent(WizardComponent, ABC):

4
electrum/plugins/digitalbitbox/qt.py

@ -69,6 +69,10 @@ class DigitalBitbox_Handler(QtHandlerBase):
def __init__(self, win): def __init__(self, win):
super(DigitalBitbox_Handler, self).__init__(win, 'Digital Bitbox') super(DigitalBitbox_Handler, self).__init__(win, 'Digital Bitbox')
def query_choice(self, msg, labels):
choices = [(i, v) for i, v in enumerate(labels)]
return QtHandlerBase.query_choice(self, msg, choices)
class WCDigitalBitboxScriptAndDerivation(WCScriptAndDerivation): class WCDigitalBitboxScriptAndDerivation(WCScriptAndDerivation):
requestRecheck = pyqtSignal() requestRecheck = pyqtSignal()

Loading…
Cancel
Save