URI: 
       tkivy: use camera - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 644cb871f585b433f0737dc1a9d590e90cf1db91
   DIR parent 3c1d6fab694c3c0d823b00d52163bf9877d812d7
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Wed, 16 Mar 2016 20:39:59 +0100
       
       kivy: use camera
       
       Diffstat:
         M gui/kivy/Readme.txt                 |       3 +++
         M gui/kivy/main_window.py             |      24 +++++++++++++++++++-----
         M gui/kivy/qr_scanner/scanner_androi… |      51 +++++++++++++++++++++++++------
         M gui/kivy/uix/dialogs/qr_scanner.py  |      12 ++++++------
         M gui/kivy/uix/ui_screens/send.kv     |       2 +-
       
       5 files changed, 70 insertions(+), 22 deletions(-)
       ---
   DIR diff --git a/gui/kivy/Readme.txt b/gui/kivy/Readme.txt
       t@@ -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
   DIR diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py
       t@@ -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
       t@@ -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')
       t@@ -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
       t@@ -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):
   DIR diff --git a/gui/kivy/qr_scanner/scanner_android.py b/gui/kivy/qr_scanner/scanner_android.py
       t@@ -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
       t@@ -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
       t@@ -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()
        
       t@@ -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()
       t@@ -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):
   DIR diff --git a/gui/kivy/uix/dialogs/qr_scanner.py b/gui/kivy/uix/dialogs/qr_scanner.py
       t@@ -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.
       t@@ -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
   DIR diff --git a/gui/kivy/uix/ui_screens/send.kv b/gui/kivy/uix/ui_screens/send.kv
       t@@ -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')