commit 644cb871f585b433f0737dc1a9d590e90cf1db91
parent 3c1d6fab694c3c0d823b00d52163bf9877d812d7
Author: ThomasV <thomasv@electrum.org>
Date: Wed, 16 Mar 2016 20:39:59 +0100
kivy: use camera
Diffstat:
5 files changed, 70 insertions(+), 22 deletions(-)
diff --git a/gui/kivy/Readme.txt b/gui/kivy/Readme.txt
@@ -16,3 +16,6 @@ then you need to rebuild the distribution. To do so:
Note:
python-for-android must be patched with:
git pull git@github.com:denys-duchier/python-for-android.git fix-recursive-delete
+
+
+export P4A_pyjnius_DIR=local_clone
diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py
@@ -35,7 +35,7 @@ Factory.register('InstallWizard',
Factory.register('InfoBubble', module='electrum_gui.kivy.uix.dialogs')
Factory.register('OutputList', module='electrum_gui.kivy.uix.dialogs')
Factory.register('OutputItem', module='electrum_gui.kivy.uix.dialogs')
-
+Factory.register('QrScannerDialog', module='electrum_gui.kivy.uix.dialogs.qr_scanner')
#from kivy.core.window import Window
@@ -241,12 +241,15 @@ class ElectrumWindow(App):
self.show_error("invoice error:" + pr.error)
self.send_screen.do_clear()
- def on_qr(self, data):
+ def on_qr(self, d, data):
+ from electrum.bitcoin import base_decode, is_address
+ if is_address(data):
+ self.set_URI(data)
+ return
if data.startswith('bitcoin:'):
self.set_URI(data)
return
# try to decode transaction
- from electrum.bitcoin import base_decode
from electrum.transaction import Transaction
try:
text = base_decode(data, None, base=43).encode('hex')
@@ -307,6 +310,17 @@ class ElectrumWindow(App):
popup.open()
def scan_qr(self, on_complete):
+ self.scan_qr_android(on_complete)
+
+ def scan_qr_android(self, on_complete):
+ dlg = Cache.get('electrum_widgets', 'QrScannerDialog')
+ if not dlg:
+ dlg = Factory.QrScannerDialog()
+ Cache.append('electrum_widgets', 'QrScannerDialog', dlg)
+ dlg.bind(on_complete=on_complete)
+ dlg.open()
+
+ def scan_qr_zxing(self, on_complete):
if platform != 'android':
return
from jnius import autoclass
@@ -555,8 +569,8 @@ class ElectrumWindow(App):
@profiler
def update_wallet(self, *dt):
self._trigger_update_status()
- #if self.wallet.up_to_date or not self.network or not self.network.is_connected():
- self.update_tabs()
+ if self.wallet.up_to_date or not self.network or not self.network.is_connected():
+ self.update_tabs()
@profiler
def notify_transactions(self, *dt):
diff --git a/gui/kivy/qr_scanner/scanner_android.py b/gui/kivy/qr_scanner/scanner_android.py
@@ -244,6 +244,19 @@ class AndroidCamera(Widget):
self._holder.pos = pos
+from electrum.util import profiler
+
+use_camera = True
+if use_camera:
+ from kivy.uix.camera import Camera
+ from kivy.clock import Clock
+ from PIL import Image as PILImage
+ class MyCamera(Camera):
+ def start(self):
+ self.play = True
+ def stop(self):
+ self.play = False
+
class ScannerAndroid(ScannerBase):
'''Widget that use the AndroidCamera and zbar to detect qrcode.
When found, the `symbols` will be updated
@@ -251,10 +264,15 @@ class ScannerAndroid(ScannerBase):
def __init__(self, **kwargs):
super(ScannerAndroid, self).__init__(**kwargs)
- self._camera = AndroidCamera(
+ if use_camera:
+ self._camera = MyCamera(resolution=self.camera_size)
+ Clock.schedule_interval(self._detect_qrcode_frame2, 1)
+ else:
+ self._camera = AndroidCamera(
size=self.camera_size,
size_hint=(None, None))
- self._camera.bind(on_preview_frame=self._detect_qrcode_frame)
+ self._camera.bind(on_preview_frame=self._detect_qrcode_frame)
+
self.add_widget(self._camera)
# create a scanner used for detecting qrcode
@@ -264,6 +282,7 @@ class ScannerAndroid(ScannerBase):
self._scanner.setConfig(0, Config.X_DENSITY, 3)
self._scanner.setConfig(0, Config.Y_DENSITY, 3)
+
def start(self):
self._camera.start()
@@ -271,24 +290,36 @@ class ScannerAndroid(ScannerBase):
self._camera.stop()
def _detect_qrcode_frame(self, instance, camera, data):
- # the image we got by default from a camera is using the NV21 format
- # zbar only allow Y800/GREY image, so we first need to convert,
- # then start the detection on the image
if not self.get_root_window():
self.stop()
return
parameters = camera.getParameters()
size = parameters.getPreviewSize()
- barcode = Image(size.width, size.height, 'NV21')
+ self.check_image(size.width, size.height, data)
+
+ def _detect_qrcode_frame2(self, *args):
+ if not self._camera.play:
+ return
+ tex = self._camera.texture
+ if not tex:
+ return
+ im = PILImage.fromstring('RGBA', tex.size, tex.pixels)
+ im = im.convert('L')
+ self.check_image(tex.size[0], tex.size[1], im.tostring())
+
+ @profiler
+ def check_image(self, width, height, data):
+ print "zzz", width, height, len(data)
+ # the image we got by default from a camera is using the rgba format
+ # zbar only allow Y800/GREY image, so we first need to convert,
+ # then start the detection on the image
+ barcode = Image(width, height, 'NV21')
barcode.setData(data)
barcode = barcode.convert('Y800')
-
result = self._scanner.scanImage(barcode)
-
if result == 0:
self.symbols = []
return
-
# we detected qrcode! extract and dispatch them
symbols = []
it = barcode.getSymbols().iterator()
@@ -301,9 +332,9 @@ class ScannerAndroid(ScannerBase):
count=symbol.getCount(),
bounds=symbol.getBounds())
symbols.append(qrcode)
-
self.symbols = symbols
+
'''
# can't work, due to the overlay.
def on_symbols(self, instance, value):
diff --git a/gui/kivy/uix/dialogs/qr_scanner.py b/gui/kivy/uix/dialogs/qr_scanner.py
@@ -11,8 +11,8 @@ class QrScannerDialog(Factory.AnimatedPopup):
def on_symbols(self, instance, value):
instance.stop()
self.dismiss()
- uri = App.get_running_app().decode_uri(value[0].data)
- self.dispatch('on_complete', uri)
+ data = value[0].data
+ self.dispatch('on_complete', data)
def on_complete(self, x):
''' Default Handler for on_complete event.
@@ -30,10 +30,10 @@ Builder.load_string('''
size_hint: None, None
size: '340dp', '290dp'
pos_hint: {'center_y': .53}
- separator_color: .89, .89, .89, 1
- separator_height: '1.2dp'
- title_color: .437, .437, .437, 1
- background: 'atlas://gui/kivy/theming/light/dialog'
+ #separator_color: .89, .89, .89, 1
+ #separator_height: '1.2dp'
+ #title_color: .437, .437, .437, 1
+ #background: 'atlas://gui/kivy/theming/light/dialog'
on_activate:
qrscr.start()
qrscr.size = self.size
diff --git a/gui/kivy/uix/ui_screens/send.kv b/gui/kivy/uix/ui_screens/send.kv
@@ -77,7 +77,7 @@ SendScreen:
IconButton:
id: qr
size_hint: 0.6, 1
- on_release: app.scan_qr(on_complete=app.on_qr)
+ on_release: Clock.schedule_once(lambda dt: app.scan_qr(on_complete=app.on_qr))
icon: 'atlas://gui/kivy/theming/light/camera'
Button:
text: _('Paste')