From 264a5fe421317a0a39a356301c7d692b30165ffe Mon Sep 17 00:00:00 2001 From: SomberNight Date: Thu, 9 Jan 2025 12:15:01 +0000 Subject: [PATCH] qt gui: add command for console use: "scan_qr()" try ``` >>> scan_qr().data ``` to read a qr code from the screen --- electrum/gui/qt/main_window.py | 4 ++- electrum/gui/qt/util.py | 52 +++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py index c93889ccf..aea6eaaa9 100644 --- a/electrum/gui/qt/main_window.py +++ b/electrum/gui/qt/main_window.py @@ -93,6 +93,7 @@ from .util import (read_QIcon, ColorScheme, text_dialog, icon_path, WaitingDialo getOpenFileName, getSaveFileName, font_height) from .util import ButtonsLineEdit, ShowQRLineEdit from .util import QtEventListener, qt_event_listener, event_listener +from .util import scan_qr_from_screenshot from .wizard.wallet import WIF_HELP_TEXT from .history_list import HistoryList, HistoryModel from .update_checker import UpdateCheck, UpdateCheckThread @@ -1689,7 +1690,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener): 'util': util, 'bitcoin': bitcoin, 'lnutil': lnutil, - 'channels': list(self.wallet.lnworker.channels.values()) if self.wallet.lnworker else [] + 'channels': list(self.wallet.lnworker.channels.values()) if self.wallet.lnworker else [], + 'scan_qr': scan_qr_from_screenshot, }) c = commands.Commands( diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py index 52da25554..560263b39 100644 --- a/electrum/gui/qt/util.py +++ b/electrum/gui/qt/util.py @@ -21,10 +21,10 @@ from PyQt6.QtWidgets import (QPushButton, QLabel, QMessageBox, QHBoxLayout, QVBo from electrum.i18n import _ from electrum.util import FileImportFailed, FileExportFailed, resource_path -from electrum.util import EventListener, event_listener, get_logger, UserCancelled +from electrum.util import EventListener, event_listener, get_logger, UserCancelled, UserFacingException from electrum.invoices import PR_UNPAID, PR_PAID, PR_EXPIRED, PR_INFLIGHT, PR_UNKNOWN, PR_FAILED, PR_ROUTING, PR_UNCONFIRMED, PR_BROADCASTING, PR_BROADCAST from electrum.logging import Logger -from electrum.qrreader import MissingQrDetectionLib +from electrum.qrreader import MissingQrDetectionLib, QrCodeResult if TYPE_CHECKING: from .main_window import ElectrumWindow @@ -662,6 +662,28 @@ def editor_contextMenuEvent(self, p: 'PayToEdit', e: 'QContextMenuEvent') -> Non m.exec(e.globalPos()) +def scan_qr_from_screenshot() -> QrCodeResult: + from .qrreader import scan_qr_from_image + screenshots = [screen.grabWindow(0).toImage() + for screen in QApplication.instance().screens()] + if all(screen.allGray() for screen in screenshots): + raise UserFacingException(_("Failed to take screenshot.")) + scanned_qr = None + for screenshot in screenshots: + try: + scan_result = scan_qr_from_image(screenshot) + except MissingQrDetectionLib as e: + raise UserFacingException(_("Unable to scan image.") + "\n" + repr(e)) + if len(scan_result) > 0: + if (scanned_qr is not None) or len(scan_result) > 1: + raise UserFacingException(_("More than one QR code was found on the screen.")) + scanned_qr = scan_result + if scanned_qr is None: + raise UserFacingException(_("No QR code was found on the screen.")) + assert len(scanned_qr) == 1, f"{len(scanned_qr)=}, expected 1" + return scanned_qr[0] + + class GenericInputHandler: def input_qr_from_camera( self, @@ -711,28 +733,12 @@ class GenericInputHandler: ) -> None: if setText is None: setText = self.setText - from .qrreader import scan_qr_from_image - screenshots = [screen.grabWindow(0).toImage() - for screen in QApplication.instance().screens()] - if all(screen.allGray() for screen in screenshots): - show_error(_("Failed to take screenshot.")) + try: + scanned_qr = scan_qr_from_screenshot() + except UserFacingException as e: + show_error(str(e)) return - scanned_qr = None - for screenshot in screenshots: - try: - scan_result = scan_qr_from_image(screenshot) - except MissingQrDetectionLib as e: - show_error(_("Unable to scan image.") + "\n" + repr(e)) - return - if len(scan_result) > 0: - if (scanned_qr is not None) or len(scan_result) > 1: - show_error(_("More than one QR code was found on the screen.")) - return - scanned_qr = scan_result - if scanned_qr is None: - show_error(_("No QR code was found on the screen.")) - return - data = scanned_qr[0].data + data = scanned_qr.data try: if allow_multi: text = self.text()