diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py index 8cc3cec43..32b6eb710 100644 --- a/electrum/gui/qt/main_window.py +++ b/electrum/gui/qt/main_window.py @@ -85,7 +85,7 @@ from electrum.lnaddr import lndecode, LnInvoiceException from .exception_window import Exception_Hook from .amountedit import AmountEdit, BTCAmountEdit, FreezableLineEdit, FeerateEdit, SizedFreezableLineEdit from .qrcodewidget import QRCodeWidget, QRDialog -from .qrtextedit import ShowQRTextEdit, ScanQRTextEdit +from .qrtextedit import ShowQRTextEdit, ScanQRTextEdit, ScanShowQRTextEdit from .transaction_dialog import show_transaction from .fee_slider import FeeSlider, FeeComboBox from .util import (read_QIcon, ColorScheme, text_dialog, icon_path, WaitingDialog, @@ -2898,9 +2898,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): layout.addWidget(QLabel(_('Address')), 2, 0) layout.addWidget(address_e, 2, 1) - signature_e = ButtonsTextEdit() - qr_icon = "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png" - signature_e.addButton(qr_icon, lambda: self.show_qrcode(signature_e.text()), _("Show QR Code")) + signature_e = ScanShowQRTextEdit(config=self.config) layout.addWidget(QLabel(_('Signature')), 3, 0) layout.addWidget(signature_e, 3, 1) layout.setRowStretch(3,1) diff --git a/electrum/gui/qt/qrtextedit.py b/electrum/gui/qt/qrtextedit.py index 3542090ac..a7cb553bc 100644 --- a/electrum/gui/qt/qrtextedit.py +++ b/electrum/gui/qt/qrtextedit.py @@ -1,97 +1,140 @@ -from PyQt5.QtWidgets import QFileDialog +from functools import partial +from typing import Callable from electrum.i18n import _ from electrum.plugin import run_hook from electrum.simple_config import SimpleConfig -from electrum.util import UserFacingException -from electrum.logging import Logger from .util import ButtonsTextEdit, MessageBoxMixin, ColorScheme, getOpenFileName from .qrreader import scan_qrcode +def qr_show(text_edit, *, config: SimpleConfig) -> None: + from .qrcodewidget import QRDialog + try: + s = str(text_edit.text()) + except: + s = text_edit.text() + if not s: + return + QRDialog( + data=s, + parent=text_edit, + config=config, + ).exec_() + + +def qr_input( + text_edit, + *, + config: SimpleConfig, + allow_multi: bool = False, + show_error: Callable[[str], None], +) -> None: + def cb(success: bool, error: str, data): + if not success: + if error: + show_error(error) + return + if not data: + data = '' + if allow_multi: + new_text = text_edit.text() + data + '\n' + else: + new_text = data + text_edit.setText(new_text) + + scan_qrcode(parent=text_edit, config=config, callback=cb) + + +def file_input( + text_edit, + *, + config: SimpleConfig, + show_error: Callable[[str], None], +) -> None: + fileName = getOpenFileName( + parent=text_edit, + title='select file', + config=config, + ) + if not fileName: + return + try: + try: + with open(fileName, "r") as f: + data = f.read() + except UnicodeError as e: + with open(fileName, "rb") as f: + data = f.read() + data = data.hex() + except BaseException as e: + show_error(_('Error opening file') + ':\n' + repr(e)) + else: + text_edit.setText(data) + + class ShowQRTextEdit(ButtonsTextEdit): def __init__(self, text=None, *, config: SimpleConfig): ButtonsTextEdit.__init__(self, text) self.config = config self.setReadOnly(True) + # qr_show + self.qr_show = partial(qr_show, self, config=config) icon = "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png" self.addButton(icon, self.qr_show, _("Show as QR code")) run_hook('show_text_edit', self) - def qr_show(self): - from .qrcodewidget import QRDialog - try: - s = str(self.toPlainText()) - except: - s = self.toPlainText() - QRDialog( - data=s, - parent=self, - config=self.config, - ).exec_() - def contextMenuEvent(self, e): m = self.createStandardContextMenu() m.addAction(_("Show as QR code"), self.qr_show) m.exec_(e.globalPos()) -class ScanQRTextEdit(ButtonsTextEdit, MessageBoxMixin, Logger): +class ScanQRTextEdit(ButtonsTextEdit, MessageBoxMixin): - def __init__(self, text="", allow_multi=False, *, config: SimpleConfig): + def __init__(self, text="", allow_multi: bool = False, *, config: SimpleConfig): ButtonsTextEdit.__init__(self, text) - Logger.__init__(self) - self.allow_multi = allow_multi self.config = config self.setReadOnly(False) + # file_input + self.file_input = partial(file_input, self, config=config, show_error=self.show_error) self.addButton("file.png", self.file_input, _("Read file")) + # qr_input + self.qr_input = partial(qr_input, self, config=config, show_error=self.show_error, allow_multi=allow_multi) icon = "camera_white.png" if ColorScheme.dark_scheme else "camera_dark.png" self.addButton(icon, self.qr_input, _("Read QR code")) + run_hook('scan_text_edit', self) - def file_input(self): - fileName = getOpenFileName( - parent=self, - title='select file', - config=self.config, - ) - if not fileName: - return - try: - try: - with open(fileName, "r") as f: - data = f.read() - except UnicodeError as e: - with open(fileName, "rb") as f: - data = f.read() - data = data.hex() - except BaseException as e: - self.show_error(_('Error opening file') + ':\n' + repr(e)) - else: - self.setText(data) - - def qr_input(self, *, callback=None) -> None: - def cb(success: bool, error: str, data): - if not success: - if error: - self.show_error(error) - return - if not data: - data = '' - if self.allow_multi: - new_text = self.text() + data + '\n' - else: - new_text = data - self.setText(new_text) - if callback and success: - callback(data) - - scan_qrcode(parent=self.top_level_window(), config=self.config, callback=cb) + def contextMenuEvent(self, e): + m = self.createStandardContextMenu() + m.addAction(_("Read QR code"), self.qr_input) + m.exec_(e.globalPos()) + + +class ScanShowQRTextEdit(ButtonsTextEdit, MessageBoxMixin): + + def __init__(self, text="", allow_multi: bool = False, *, config: SimpleConfig): + ButtonsTextEdit.__init__(self, text) + self.config = config + self.setReadOnly(False) + # qr_input + self.qr_input = partial(qr_input, self, config=config, show_error=self.show_error, allow_multi=allow_multi) + icon = "camera_white.png" if ColorScheme.dark_scheme else "camera_dark.png" + self.addButton(icon, self.qr_input, _("Read QR code")) + # qr_show + self.qr_show = partial(qr_show, self, config=config) + icon = "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png" + self.addButton(icon, self.qr_show, _("Show as QR code")) + + run_hook('scan_text_edit', self) + run_hook('show_text_edit', self) def contextMenuEvent(self, e): m = self.createStandardContextMenu() m.addAction(_("Read QR code"), self.qr_input) + m.addAction(_("Show as QR code"), self.qr_show) m.exec_(e.globalPos())