Browse Source

qml: add QR code imageprovider using qrcode/PIL

adds buildozer 'pillow' recipe to requirements

add initial PoC on qml receive tab
patch-4
Sander van Grieken 3 years ago
parent
commit
492f246b9a
  1. 3
      contrib/android/buildozer_qml.spec
  2. 32
      electrum/gui/qml/components/Receive.qml
  3. 8
      electrum/gui/qml/components/WalletMainView.qml
  4. 7
      electrum/gui/qml/qeapp.py
  5. 51
      electrum/gui/qml/qeqr.py

3
contrib/android/buildozer_qml.spec

@ -51,7 +51,8 @@ requirements =
libsecp256k1,
cryptography,
pyqt5sip,
pyqt5
pyqt5,
pillow
# (str) Presplash of the application
#presplash.filename = %(source.dir)s/gui/kivy/theming/splash.png

32
electrum/gui/qml/components/Receive.qml

@ -0,0 +1,32 @@
import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import org.electrum 1.0
Pane {
id: rootItem
visible: Daemon.currentWallet !== undefined
ColumnLayout {
width: parent.width
spacing: 20
Image {
id: img
}
TextField {
id: text
}
Button {
text: 'generate'
onClicked: {
img.source = 'image://qrgen/' + text.text
}
}
}
}

8
electrum/gui/qml/components/WalletMainView.qml

@ -63,11 +63,9 @@ Item {
currentIndex: tabbar.currentIndex
Item {
ColumnLayout {
width: parent.width
y: 20
spacing: 20
Receive {
id: receive
anchors.fill: parent
}
}

7
electrum/gui/qml/qeapp.py

@ -10,7 +10,7 @@ from .qeconfig import QEConfig
from .qedaemon import QEDaemon, QEWalletListModel
from .qenetwork import QENetwork
from .qewallet import QEWallet
from .qeqr import QEQR
from .qeqr import QEQR, QEQRImageProvider
from .qewalletdb import QEWalletDB
from .qebitcoin import QEBitcoin
@ -36,6 +36,9 @@ class ElectrumQmlApplication(QGuiApplication):
self.engine = QQmlApplicationEngine(parent=self)
self.engine.addImportPath('./qml')
self.qr_ip = QEQRImageProvider()
self.engine.addImageProvider('qrgen', self.qr_ip)
self.context = self.engine.rootContext()
self._singletons['config'] = QEConfig(config)
self._singletons['network'] = QENetwork(daemon.network)
@ -63,7 +66,7 @@ class ElectrumQmlApplication(QGuiApplication):
def message_handler(self, line, funct, file):
# filter out common harmless messages
if re.search('file:///.*TypeError:\ Cannot\ read\ property.*null$', file):
if re.search('file:///.*TypeError: Cannot read property.*null$', file):
return
self.logger.warning(file)

51
electrum/gui/qml/qeqr.py

@ -1,8 +1,15 @@
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl
from PyQt5.QtGui import QImage
from PyQt5.QtQuick import QQuickImageProvider
from electrum.logging import get_logger
#from PIL import Image
import qrcode
#from qrcode.image.styledpil import StyledPilImage
#from qrcode.image.styles.moduledrawers import *
from PIL import Image, ImageQt
from ctypes import *
class QEQR(QObject):
@ -11,22 +18,25 @@ class QEQR(QObject):
self._text = text
_logger = get_logger(__name__)
scan_ready_changed = pyqtSignal()
_ready = True
scanReadyChanged = pyqtSignal()
imageChanged = pyqtSignal()
_scanReady = True
_image = None
@pyqtSlot('QImage')
def scanImage(self, image=None):
if not self._ready:
if not self._scanReady:
self._logger.warning("Already processing an image. Check 'ready' property before calling scanImage")
return
self._ready = False
self.scan_ready_changed.emit()
self._scanReady = False
self.scanReadyChanged.emit()
pilimage = self.convertToPILImage(image)
self.parseQR(pilimage)
self._ready = True
self._scanReady = True
def logImageStats(self, image):
self._logger.info('width: ' + str(image.width()))
@ -47,13 +57,32 @@ class QEQR(QObject):
memmove(c_buf, c_void_p(rawimage.__int__()), numbytes)
buf2 = bytes(buf)
return None #Image.frombytes('RGBA', (image.width(), image.height()), buf2, 'raw')
return Image.frombytes('RGBA', (image.width(), image.height()), buf2, 'raw')
def parseQR(self, image):
# TODO
pass
@pyqtProperty(bool, notify=scan_ready_changed)
def ready(self):
return self._ready
@pyqtProperty(bool, notify=scanReadyChanged)
def scanReady(self):
return self._scanReady
@pyqtProperty('QImage', notify=imageChanged)
def image(self):
return self._image
class QEQRImageProvider(QQuickImageProvider):
def __init__(self, parent=None):
super().__init__(QQuickImageProvider.Image)
_logger = get_logger(__name__)
def requestImage(self, qstr, size):
self._logger.debug('QR requested for %s' % qstr)
qr = qrcode.QRCode(version=1, box_size=8, border=2)
qr.add_data(qstr)
qr.make(fit=True)
pimg = qr.make_image(fill_color='black', back_color='white') #image_factory=StyledPilImage, module_drawer=CircleModuleDrawer())
qimg = ImageQt.ImageQt(pimg)
return qimg, qimg.size()

Loading…
Cancel
Save