Browse Source

Qt PayToEdit: add option to scan QR code from screen(shot)

this ports the following commits:
448376e441
6053f6f696
patch-4
Jonas Lundqvist 3 years ago
committed by SomberNight
parent
commit
b7b53e56bc
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 19
      electrum/gui/qt/qrreader/__init__.py
  2. 8
      electrum/gui/qt/qrtextedit.py
  3. 40
      electrum/gui/qt/util.py

19
electrum/gui/qt/qrreader/__init__.py

@ -22,14 +22,15 @@
# Note: this module is safe to import on all platforms.
import sys
from typing import Callable, Optional, TYPE_CHECKING, Mapping
from typing import Callable, Optional, TYPE_CHECKING, Mapping, Sequence
from PyQt5.QtWidgets import QMessageBox, QWidget
from PyQt5.QtGui import QImage
from electrum.i18n import _
from electrum.util import UserFacingException
from electrum.logging import get_logger
from electrum.qrreader import MissingQrDetectionLib
from electrum.qrreader import get_qr_reader, QrCodeResult, MissingQrDetectionLib
from electrum.gui.qt.util import MessageBoxMixin, custom_message_box
@ -47,12 +48,26 @@ def scan_qrcode(
config: 'SimpleConfig',
callback: Callable[[bool, str, Optional[str]], None],
) -> None:
"""Scans QR code using camera."""
if sys.platform == 'darwin' or sys.platform in ('windows', 'win32'):
_scan_qrcode_using_qtmultimedia(parent=parent, config=config, callback=callback)
else: # desktop Linux and similar
_scan_qrcode_using_zbar(parent=parent, config=config, callback=callback)
def scan_qr_from_image(image: QImage) -> Sequence[QrCodeResult]:
"""Might raise exception: MissingQrDetectionLib."""
qr_reader = get_qr_reader()
image_y800 = image.convertToFormat(QImage.Format_Grayscale8)
res = qr_reader.read_qr_code(
image_y800.constBits().__int__(), image_y800.byteCount(),
image_y800.bytesPerLine(),
image_y800.width(),
image_y800.height()
)
return res
def find_system_cameras() -> Mapping[str, str]:
"""Returns a camera_description -> camera_path map."""
if sys.platform == 'darwin' or sys.platform in ('windows', 'win32'):

8
electrum/gui/qt/qrtextedit.py

@ -30,7 +30,9 @@ class ScanQRTextEdit(ButtonsTextEdit, MessageBoxMixin):
def contextMenuEvent(self, e):
m = self.createStandardContextMenu()
m.addAction(_("Read QR code"), self.on_qr_input_btn)
m.addSeparator()
m.addAction(_("Read QR code from camera"), self.on_qr_from_camera_input_btn)
m.addAction(_("Read QR code from screen"), self.on_qr_from_screenshot_input_btn)
m.exec_(e.globalPos())
@ -46,6 +48,8 @@ class ScanShowQRTextEdit(ButtonsTextEdit, MessageBoxMixin):
def contextMenuEvent(self, e):
m = self.createStandardContextMenu()
m.addAction(_("Read QR code"), self.on_qr_input_btn)
m.addSeparator()
m.addAction(_("Read QR code from camera"), self.on_qr_from_camera_input_btn)
m.addAction(_("Read QR code from screen"), self.on_qr_from_screenshot_input_btn)
m.addAction(_("Show as QR code"), self.on_qr_show_btn)
m.exec_(e.globalPos())

40
electrum/gui/qt/util.py

@ -30,6 +30,7 @@ from electrum.i18n import _, languages
from electrum.util import FileImportFailed, FileExportFailed, make_aiohttp_session, resource_path
from electrum.invoices import PR_UNPAID, PR_PAID, PR_EXPIRED, PR_INFLIGHT, PR_UNKNOWN, PR_FAILED, PR_ROUTING, PR_UNCONFIRMED
from electrum.logging import Logger
from electrum.qrreader import MissingQrDetectionLib
if TYPE_CHECKING:
from .main_window import ElectrumWindow
@ -879,7 +880,7 @@ class OverlayControlMixin:
# The old code positioned the items the other way around, so we just insert at position 0 instead
self.overlay_layout.insertWidget(0, widget)
def addButton(self, icon_name: str, on_click, tooltip: str) -> QAbstractButton:
def addButton(self, icon_name: str, on_click, tooltip: str) -> QPushButton:
button = QPushButton(self.overlay_widget)
button.setToolTip(tooltip)
button.setIcon(read_QIcon(icon_name))
@ -943,7 +944,7 @@ class OverlayControlMixin:
):
if setText is None:
setText = self.setText
def qr_input():
def qr_from_camera_input() -> None:
def cb(success: bool, error: str, data):
if not success:
if error:
@ -960,10 +961,39 @@ class OverlayControlMixin:
from .qrreader import scan_qrcode
scan_qrcode(parent=self, config=config, callback=cb)
def qr_from_screenshot_input() -> None:
from .qrreader import scan_qr_from_image
scanned_qr = None
for screen in QApplication.instance().screens():
try:
scan_result = scan_qr_from_image(screen.grabWindow(0).toImage())
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
if allow_multi:
new_text = self.text() + data + '\n'
else:
new_text = data
setText(new_text)
icon = "camera_white.png" if ColorScheme.dark_scheme else "camera_dark.png"
self.addButton(icon, qr_input, _("Read QR code"))
# side-effect: we export this method:
self.on_qr_input_btn = qr_input
btn = self.addButton(icon, lambda: None, _("Read QR code"))
menu = QMenu()
menu.addAction(_("Read QR code from camera"), qr_from_camera_input)
menu.addAction(_("Read QR code from screen"), qr_from_screenshot_input)
btn.setMenu(menu)
# side-effect: we export these methods:
self.on_qr_from_camera_input_btn = qr_from_camera_input
self.on_qr_from_screenshot_input_btn = qr_from_screenshot_input
def add_file_input_button(
self,

Loading…
Cancel
Save