Browse Source

create ChoiceWidget, refactor ChoicesLayout to ChoiceWidget

master
Sander van Grieken 2 years ago
parent
commit
d3a1cef9ba
  1. 41
      electrum/gui/qt/util.py
  2. 81
      electrum/gui/qt/wizard/wallet.py

41
electrum/gui/qt/util.py

@ -456,6 +456,47 @@ class ChoicesLayout(object):
def selected_index(self): def selected_index(self):
return self.group.checkedId() return self.group.checkedId()
class ChoiceWidget(QWidget):
itemSelected = pyqtSignal([int], arguments=['index'])
def __init__(self, *, message=None, choices=[], selected=None):
QWidget.__init__(self)
vbox = QVBoxLayout()
self.setLayout(vbox)
self.selected_index = -1
self.selected_item = None
self.choices = choices
if message and len(message) > 50:
vbox.addWidget(WWLabel(message))
message = ""
gb2 = QGroupBox(message)
vbox.addWidget(gb2)
vbox2 = QVBoxLayout()
gb2.setLayout(vbox2)
self.group = group = QButtonGroup()
assert isinstance(choices, list)
iterator = enumerate(choices)
for i, c in iterator:
button = QRadioButton(gb2)
button.setText(c[1])
vbox2.addWidget(button)
group.addButton(button)
group.setId(button, i)
if (i == 0 and selected is None) or c[0] == selected:
self.selected_index = i
self.selected_item = c
button.setChecked(True)
group.buttonClicked.connect(self.on_selected)
def on_selected(self, button):
self.selected_index = self.group.id(button)
self.selected_item = self.choices[self.selected_index]
self.itemSelected.emit(self.selected_index)
def address_field(addresses): def address_field(addresses):
hbox = QHBoxLayout() hbox = QHBoxLayout()
address_e = QLineEdit() address_e = QLineEdit()

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

@ -6,7 +6,7 @@ from typing import TYPE_CHECKING
from PyQt5.QtCore import Qt, QTimer, QRect, pyqtSignal from PyQt5.QtCore import Qt, QTimer, QRect, pyqtSignal
from PyQt5.QtGui import QPen, QPainter, QPalette from PyQt5.QtGui import QPen, QPainter, QPalette
from PyQt5.QtWidgets import (QApplication, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QWidget, from PyQt5.QtWidgets import (QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QWidget,
QFileDialog, QSlider, QGridLayout) QFileDialog, QSlider, QGridLayout)
from electrum.bip32 import is_bip32_derivation, BIP32Node, normalize_bip32_derivation, xpub_type from electrum.bip32 import is_bip32_derivation, BIP32Node, normalize_bip32_derivation, xpub_type
@ -21,10 +21,12 @@ from .wizard import QEAbstractWizard, WizardComponent
from electrum.logging import get_logger, Logger from electrum.logging import get_logger, Logger
from electrum import WalletStorage, mnemonic, keystore from electrum import WalletStorage, mnemonic, keystore
from electrum.wizard import NewWalletWizard from electrum.wizard import NewWalletWizard
from ..bip39_recovery_dialog import Bip39RecoveryDialog
from ..password_dialog import PasswordLayout, PW_NEW, MSG_ENTER_PASSWORD, PasswordLayoutForHW from electrum.gui.qt.bip39_recovery_dialog import Bip39RecoveryDialog
from ..seed_dialog import SeedLayout, MSG_PASSPHRASE_WARN_ISSUE4566, KeysLayout from electrum.gui.qt.password_dialog import PasswordLayout, PW_NEW, MSG_ENTER_PASSWORD, PasswordLayoutForHW
from ..util import ChoicesLayout, PasswordLineEdit, char_width_in_lineedit, WWLabel, InfoButton, font_height 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,
ChoiceWidget)
if TYPE_CHECKING: if TYPE_CHECKING:
from electrum.simple_config import SimpleConfig from electrum.simple_config import SimpleConfig
@ -276,15 +278,13 @@ class WCWalletType(WizardComponent):
] ]
choices = [pair for pair in wallet_kinds if pair[0] in wallet_types] choices = [pair for pair in wallet_kinds if pair[0] in wallet_types]
self.c_values = [x[0] for x in choices] self.choice_w = ChoiceWidget(message=message, choices=choices, selected='standard')
c_titles = [x[1] for x in choices] self.layout().addWidget(self.choice_w)
self.clayout = ChoicesLayout(message, c_titles)
self.layout().addLayout(self.clayout.layout())
self.layout().addStretch(1) self.layout().addStretch(1)
self._valid = True self._valid = True
def apply(self): def apply(self):
self.wizard_data['wallet_type'] = self.c_values[self.clayout.selected_index()] self.wizard_data['wallet_type'] = self.choice_w.selected_item[0]
class WCKeystoreType(WizardComponent): class WCKeystoreType(WizardComponent):
@ -298,15 +298,13 @@ class WCKeystoreType(WizardComponent):
('hardware', _('Use a hardware device')) ('hardware', _('Use a hardware device'))
] ]
self.c_values = [x[0] for x in choices] self.choice_w = ChoiceWidget(message=message, choices=choices)
c_titles = [x[1] for x in choices] self.layout().addWidget(self.choice_w)
self.clayout = ChoicesLayout(message, c_titles)
self.layout().addLayout(self.clayout.layout())
self.layout().addStretch(1) self.layout().addStretch(1)
self._valid = True self._valid = True
def apply(self): def apply(self):
self.wizard_data['keystore_type'] = self.c_values[self.clayout.selected_index()] self.wizard_data['keystore_type'] = self.choice_w.selected_item[0]
class WCCreateSeed(WizardComponent): class WCCreateSeed(WizardComponent):
@ -542,7 +540,6 @@ class WCScriptAndDerivation(WizardComponent):
WizardComponent.__init__(self, parent, wizard, title=_('Script type and Derivation path')) WizardComponent.__init__(self, parent, wizard, title=_('Script type and Derivation path'))
def on_ready(self): def on_ready(self):
message1 = _('Choose the type of addresses in your wallet.') message1 = _('Choose the type of addresses in your wallet.')
message2 = ' '.join([ message2 = ' '.join([
_('You can override the suggested derivation path.'), _('You can override the suggested derivation path.'),
@ -560,15 +557,12 @@ class WCScriptAndDerivation(WizardComponent):
if 'multisig_current_cosigner' in self.wizard_data: if 'multisig_current_cosigner' in self.wizard_data:
# get script type of first cosigner # get script type of first cosigner
ks = self.wizard.keystore_from_data(self.wizard_data['wallet_type'], self.wizard_data) ks = self.wizard.keystore_from_data(self.wizard_data['wallet_type'], self.wizard_data)
script_type = xpub_type(ks.get_master_public_key()) default_choice = xpub_type(ks.get_master_public_key())
script_types = [*zip(*choices)][0]
chosen_idx = script_types.index(script_type)
default_choice_idx = chosen_idx
hide_choices = True hide_choices = True
else: else:
default_choice_idx = 2 default_choice = 'p2wsh'
else: else:
default_choice_idx = 2 default_choice = 'p2wpkh'
choices = [ choices = [
# TODO: nicer to refactor 'standard' to 'p2pkh', but backend wallet still uses 'standard' # TODO: nicer to refactor 'standard' to 'p2pkh', but backend wallet still uses 'standard'
('standard', 'legacy (p2pkh)', bip44_derivation(0, bip43_purpose=44)), ('standard', 'legacy (p2pkh)', bip44_derivation(0, bip43_purpose=44)),
@ -604,24 +598,22 @@ class WCScriptAndDerivation(WizardComponent):
self.layout().addWidget(button, alignment=Qt.AlignLeft) self.layout().addWidget(button, alignment=Qt.AlignLeft)
self.layout().addWidget(QLabel(_("Or"))) self.layout().addWidget(QLabel(_("Or")))
self.c_values = [x[0] for x in choices] def on_choice_click(index):
c_titles = [x[1] for x in choices] self.derivation_path_edit.setText(self.choice_w.selected_item[2])
c_default_text = [x[2] for x in choices] self.choice_w = ChoiceWidget(message=message1, choices=choices, selected=default_choice)
self.choice_w.itemSelected.connect(on_choice_click)
def on_choice_click(clayout):
idx = clayout.selected_index()
self.derivation_path_edit.setText(c_default_text[idx])
self.clayout = ChoicesLayout(message1, c_titles, on_choice_click,
checked_index=default_choice_idx)
if not hide_choices: if not hide_choices:
self.layout().addLayout(self.clayout.layout()) self.layout().addWidget(self.choice_w)
self.layout().addWidget(WWLabel(message2)) self.layout().addWidget(WWLabel(message2))
self.derivation_path_edit = QLineEdit() self.derivation_path_edit = QLineEdit()
self.derivation_path_edit.textChanged.connect(self.validate) self.derivation_path_edit.textChanged.connect(self.validate)
on_choice_click(self.clayout) # set default value for derivation path
self.layout().addWidget(self.derivation_path_edit) self.layout().addWidget(self.derivation_path_edit)
on_choice_click(self.choice_w.selected_index) # set default value for derivation path
self.layout().addStretch(1) self.layout().addStretch(1)
def validate(self): def validate(self):
@ -649,7 +641,7 @@ class WCScriptAndDerivation(WizardComponent):
def apply(self): def apply(self):
cosigner_data = self._current_cosigner(self.wizard_data) cosigner_data = self._current_cosigner(self.wizard_data)
cosigner_data['script_type'] = self.c_values[self.clayout.selected_index()] cosigner_data['script_type'] = self.choice_w.selected_item[0]
cosigner_data['derivation_path'] = str(self.derivation_path_edit.text()) cosigner_data['derivation_path'] = str(self.derivation_path_edit.text())
@ -664,10 +656,8 @@ class WCCosignerKeystore(WizardComponent):
('hardware', _('Cosign with hardware device')) ('hardware', _('Cosign with hardware device'))
] ]
self.c_values = [x[0] for x in choices] self.choice_w = ChoiceWidget(message=message, choices=choices)
c_titles = [x[1] for x in choices] self.layout().addWidget(self.choice_w)
self.clayout = ChoicesLayout(message, c_titles)
self.layout().addLayout(self.clayout.layout())
self.cosigner = 0 self.cosigner = 0
self.participants = 0 self.participants = 0
@ -696,7 +686,7 @@ class WCCosignerKeystore(WizardComponent):
self.layout().addStretch(1) self.layout().addStretch(1)
def apply(self): def apply(self):
self.wizard_data['cosigner_keystore_type'] = self.c_values[self.clayout.selected_index()] self.wizard_data['cosigner_keystore_type'] = self.choice_w.selected_item[0]
self.wizard_data['multisig_current_cosigner'] = self.cosigner self.wizard_data['multisig_current_cosigner'] = self.cosigner
self.wizard_data['multisig_cosigner_data'][str(self.cosigner)] = {} self.wizard_data['multisig_cosigner_data'][str(self.cosigner)] = {}
@ -964,7 +954,7 @@ class WCChooseHWDevice(WizardComponent, Logger):
self.device_list = QWidget() self.device_list = QWidget()
self.device_list_layout = QVBoxLayout() self.device_list_layout = QVBoxLayout()
self.device_list.setLayout(self.device_list_layout) self.device_list.setLayout(self.device_list_layout)
self.clayout = None self.choice_w = None
self.rescan_button = QPushButton(_('Rescan devices')) self.rescan_button = QPushButton(_('Rescan devices'))
self.rescan_button.clicked.connect(self.on_rescan) self.rescan_button.clicked.connect(self.on_rescan)
@ -1004,15 +994,13 @@ class WCChooseHWDevice(WizardComponent, Logger):
descr = f"{label} [{info.model_name or name}, {state}, {transport_str}]" descr = f"{label} [{info.model_name or name}, {state}, {transport_str}]"
choices.append(((name, info), descr)) choices.append(((name, info), descr))
msg = _('Select a device') + ':' msg = _('Select a device') + ':'
self.c_values = [x[0] for x in choices]
c_titles = [x[1] for x in choices]
# remove old component before adding anew # remove old component before adding anew
a = self.device_list.layout().itemAt(0) a = self.device_list.layout().itemAt(0)
self.device_list.layout().removeItem(a) self.device_list.layout().removeItem(a)
self.clayout = ChoicesLayout(msg, c_titles) self.choice_w = ChoiceWidget(message=msg, choices=choices)
self.device_list_layout = self.clayout.layout() self.device_list.layout().addWidget(self.choice_w)
self.device_list.layout().addLayout(self.device_list_layout)
self.valid = True self.valid = True
@ -1098,10 +1086,9 @@ class WCChooseHWDevice(WizardComponent, Logger):
t.start() t.start()
def apply(self): def apply(self):
if self.clayout: if self.choice_w:
# TODO: data is not (de)serializable yet, wizard_data cannot be persisted # TODO: data is not (de)serializable yet, wizard_data cannot be persisted
self.wizard_data['hardware_device'] = self.c_values[self.clayout.selected_index()] self.wizard_data['hardware_device'] = self.choice_w.selected_item[0]
self.logger.debug(repr(self.wizard_data['hardware_device']))
class WCWalletPasswordHardware(WizardComponent): class WCWalletPasswordHardware(WizardComponent):

Loading…
Cancel
Save