qt: move query_choice to MessageBoxMixin, document ChoiceWidget
This commit is contained in:
@@ -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():
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user