Browse Source

qt: move query_choice to MessageBoxMixin, document ChoiceWidget

master
Sander van Grieken 1 year ago
parent
commit
0b09592ef1
No known key found for this signature in database
GPG Key ID: 9BCF8209EA402EBA
  1. 22
      electrum/gui/qt/main_window.py
  2. 37
      electrum/gui/qt/util.py
  3. 16
      electrum/gui/qt/wizard/wallet.py
  4. 6
      electrum/plugins/hw_wallet/qt.py

22
electrum/gui/qt/main_window.py

@ -34,7 +34,7 @@ import base64
from functools import partial from functools import partial
import queue import queue
import asyncio import asyncio
from typing import Optional, TYPE_CHECKING, Sequence, List, Union, Dict, Set, Mapping from typing import Optional, TYPE_CHECKING, Sequence, Union, Dict, Mapping
import concurrent.futures import concurrent.futures
from PyQt5.QtGui import QPixmap, QKeySequence, QIcon, QCursor, QFont, QFontMetrics from PyQt5.QtGui import QPixmap, QKeySequence, QIcon, QCursor, QFont, QFontMetrics
@ -45,7 +45,7 @@ from PyQt5.QtWidgets import (QMessageBox, QSystemTrayIcon, QTabWidget,
QHBoxLayout, QPushButton, QScrollArea, QTextEdit, QHBoxLayout, QPushButton, QScrollArea, QTextEdit,
QShortcut, QMainWindow, QInputDialog, QShortcut, QMainWindow, QInputDialog,
QWidget, QSizePolicy, QStatusBar, QToolTip, QWidget, QSizePolicy, QStatusBar, QToolTip,
QMenu, QAction, QStackedWidget, QToolButton) QMenu, QAction, QToolButton)
import electrum import electrum
from electrum.gui import messages from electrum.gui import messages
@ -88,7 +88,7 @@ from .util import (read_QIcon, ColorScheme, text_dialog, icon_path, WaitingDialo
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, ChoiceWidget) getOpenFileName, getSaveFileName, BlockingWaitingDialog, font_height)
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
@ -1370,22 +1370,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener):
else: else:
self.show_message(message) self.show_message(message)
def query_choice(self, msg, choices, title=None, default_choice=None):
# Needed by QtHandler for hardware wallets
if title is None:
title = _('Question')
dialog = WindowModalDialog(self.top_level_window(), title=title)
dialog.setMinimumWidth(400)
choice_widget = ChoiceWidget(message=msg, choices=choices, selected=default_choice)
vbox = QVBoxLayout(dialog)
vbox.addWidget(choice_widget)
cancel_button = CancelButton(dialog)
vbox.addLayout(Buttons(cancel_button, OkButton(dialog)))
cancel_button.setFocus()
if not dialog.exec_():
return None
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)
if pi.is_valid(): if pi.is_valid():

37
electrum/gui/qt/util.py

@ -283,6 +283,26 @@ class MessageBoxMixin(object):
rich_text=rich_text, rich_text=rich_text,
checkbox=checkbox) checkbox=checkbox)
def query_choice(self,
msg: Optional[str],
choices: Sequence[Tuple],
title: Optional[str] = None,
default_choice: Optional[Any] = None) -> Optional[Any]:
# Needed by QtHandler for hardware wallets
if title is None:
title = _('Question')
dialog = WindowModalDialog(self.top_level_window(), title=title)
dialog.setMinimumWidth(400)
choice_widget = ChoiceWidget(message=msg, choices=choices, selected=default_choice)
vbox = QVBoxLayout(dialog)
vbox.addWidget(choice_widget)
cancel_button = CancelButton(dialog)
vbox.addLayout(Buttons(cancel_button, OkButton(dialog)))
cancel_button.setFocus()
if not dialog.exec_():
return None
return choice_widget.selected_key
def custom_message_box(*, icon, parent, title, text, buttons=QMessageBox.Ok, def custom_message_box(*, icon, parent, title, text, buttons=QMessageBox.Ok,
defaultButton=QMessageBox.NoButton, rich_text=False, defaultButton=QMessageBox.NoButton, rich_text=False,
@ -423,9 +443,18 @@ def text_dialog(
class ChoiceWidget(QWidget): class ChoiceWidget(QWidget):
"""Renders a list of tuples as a radiobuttons group.
The first element of each tuple is used as a key.
The second element of each tuple is used as user facing string.
The remainder of the tuple can be any additional data.
Callers can pre-select an item by key, through the 'selected' parameter.
The selected item is made available by index (selected_index),
by key (selected_key) and by whole tuple (selected_item).
"""
itemSelected = pyqtSignal([int], arguments=['index']) itemSelected = pyqtSignal([int], arguments=['index'])
def __init__(self, *, message=None, choices=None, selected=None): def __init__(self, *, message: Optional[str] = None, choices: Sequence[Tuple] = None, selected: Optional[Any] = None):
QWidget.__init__(self) QWidget.__init__(self)
vbox = QVBoxLayout() vbox = QVBoxLayout()
self.setLayout(vbox) self.setLayout(vbox)
@ -433,9 +462,9 @@ class ChoiceWidget(QWidget):
if choices is None: if choices is None:
choices = [] choices = []
self.selected_index = -1 self.selected_index = -1 # int
self.selected_item = None self.selected_item = None # Optional[Tuple]
self.selected_key = None self.selected_key = None # Optional[Any]
self.choices = choices self.choices = choices

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

@ -237,22 +237,6 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard, MessageBoxMixin):
if on_finished: if on_finished:
on_finished() on_finished()
def query_choice(self, msg, choices, title=None, default_choice=None):
# Needed by QtHandler for hardware wallets
if title is None:
title = _('Question')
dialog = WindowModalDialog(self.top_level_window(), title=title)
dialog.setMinimumWidth(400)
choice_widget = ChoiceWidget(message=msg, choices=choices, selected=default_choice)
vbox = QVBoxLayout(dialog)
vbox.addWidget(choice_widget)
cancel_button = CancelButton(dialog)
vbox.addLayout(Buttons(cancel_button, OkButton(dialog)))
cancel_button.setFocus()
if not dialog.exec_():
return None
return choice_widget.selected_key
class WalletWizardComponent(WizardComponent, ABC): class WalletWizardComponent(WizardComponent, ABC):
# ^ this class only exists to help with typing # ^ this class only exists to help with typing

6
electrum/plugins/hw_wallet/qt.py

@ -26,7 +26,7 @@
import threading import threading
from functools import partial from functools import partial
from typing import TYPE_CHECKING, Union, Optional from typing import TYPE_CHECKING, Union, Optional, Sequence, Tuple
from PyQt5.QtCore import QObject, pyqtSignal, Qt from PyQt5.QtCore import QObject, pyqtSignal, Qt
from PyQt5.QtWidgets import QVBoxLayout, QLineEdit, QHBoxLayout, QLabel from PyQt5.QtWidgets import QVBoxLayout, QLineEdit, QHBoxLayout, QLabel
@ -95,7 +95,7 @@ class QtHandlerBase(HardwareHandlerBase, QObject, Logger):
icon_name = button.icon_paired if paired else button.icon_unpaired icon_name = button.icon_paired if paired else button.icon_unpaired
button.setIcon(read_QIcon(icon_name)) button.setIcon(read_QIcon(icon_name))
def query_choice(self, msg, labels): def query_choice(self, msg: str, labels: Sequence[Tuple]):
self.done.clear() self.done.clear()
self.query_signal.emit(msg, labels) self.query_signal.emit(msg, labels)
self.done.wait() self.done.wait()
@ -194,7 +194,7 @@ class QtHandlerBase(HardwareHandlerBase, QObject, Logger):
self.dialog.accept() self.dialog.accept()
self.dialog = None self.dialog = None
def win_query_choice(self, msg, labels): def win_query_choice(self, msg: str, labels: Sequence[Tuple]):
try: try:
self.choice = self.win.query_choice(msg, labels) self.choice = self.win.query_choice(msg, labels)
except UserCancelled: except UserCancelled:

Loading…
Cancel
Save