commit 167088e22a422366297d26eb764795eb37e0c0f7
parent 1f1dbaf523ee02eb3960f5ba2182a4bb8b9390ff
Author: ThomasV <thomasv@electrum.org>
Date: Thu, 17 Mar 2016 09:55:42 +0100
kivy: remove qr_scanner
Diffstat:
4 files changed, 0 insertions(+), 552 deletions(-)
diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py
@@ -35,7 +35,6 @@ 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
@@ -191,7 +190,6 @@ class ElectrumWindow(App):
# initialize variables
self._clipboard = Clipboard
self.info_bubble = None
- self.qrscanner = None
self.nfcscanner = None
self.tabs = None
self.is_exit = False
@@ -610,15 +608,11 @@ class ElectrumWindow(App):
def on_pause(self):
# pause nfc
- if self.qrscanner:
- self.qrscanner.stop()
if self.nfcscanner:
self.nfcscanner.nfc_disable()
return True
def on_resume(self):
- if self.qrscanner and qrscanner.get_parent_window():
- self.qrscanner.start()
if self.nfcscanner:
self.nfcscanner.nfc_enable()
diff --git a/gui/kivy/qr_scanner/__init__.py b/gui/kivy/qr_scanner/__init__.py
@@ -1,60 +0,0 @@
-'''QrScanner Base Abstract implementation
-'''
-
-__all__ = ('ScannerBase', 'QRScanner')
-
-from collections import namedtuple
-
-from kivy.uix.anchorlayout import AnchorLayout
-from kivy.core import core_select_lib
-from kivy.metrics import dp
-from kivy.properties import ListProperty, BooleanProperty
-from kivy.factory import Factory
-
-
-class ScannerBase(AnchorLayout):
- ''' Base implementation for camera based scanner
- '''
- camera_size = ListProperty([320, 240] if dp(1) < 2 else [640, 480])
-
- symbols = ListProperty([])
-
- # XXX can't work now, due to overlay.
- show_bounds = BooleanProperty(False)
-
- running = BooleanProperty(False)
-
- Qrcode = namedtuple('Qrcode',
- ['type', 'data', 'bounds', 'quality', 'count'])
-
- def start(self):
- pass
-
- def stop(self):
- pass
-
- def on_symbols(self, instance, value):
- #if self.show_bounds:
- # self.update_bounds()
- pass
-
- def update_bounds(self):
- self.canvas.after.remove_group('bounds')
- if not self.symbols:
- return
- with self.canvas.after:
- Color(1, 0, 0, group='bounds')
- for symbol in self.symbols:
- x, y, w, h = symbol.bounds
- x = self._camera.right - x - w
- y = self._camera.top - y - h
- Line(rectangle=[x, y, w, h], group='bounds')
-
-
-# load QRCodeDetector implementation
-
-QRScanner = core_select_lib('qr_scanner', (
- ('android', 'scanner_android', 'ScannerAndroid'),
- ('camera', 'scanner_camera', 'ScannerCamera')), False, 'electrum_gui.kivy')
-
-Factory.register('QRScanner', cls=QRScanner)
diff --git a/gui/kivy/qr_scanner/scanner_android.py b/gui/kivy/qr_scanner/scanner_android.py
@@ -1,390 +0,0 @@
-'''
-Qrcode example application
-==========================
-
-Author: Mathieu Virbel <mat@meltingrocks.com>
-
-License:
-Copyright (c) 2013 Mathieu Virbel <mat@meltingrocks.com>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-Featuring:
-
-- Android camera initialization
-- Show the android camera into a Android surface that act as an overlay
-- New AndroidWidgetHolder that control any android view as an overlay
-- New ZbarQrcodeDetector that use AndroidCamera / PreviewFrame + zbar to
- detect Qrcode.
-
-'''
-
-__all__ = ('ScannerAndroid', )
-
-from kivy.utils import platform
-if platform != 'android':
- raise ImportError
-
-from electrum_gui.kivy.qr_scanner import ScannerBase
-from kivy.properties import ObjectProperty, NumericProperty
-from kivy.uix.widget import Widget
-from kivy.uix.anchorlayout import AnchorLayout
-from kivy.graphics import Color, Line
-from jnius import autoclass, PythonJavaClass, java_method, cast
-from android.runnable import run_on_ui_thread
-
-# preload java classes
-System = autoclass('java.lang.System')
-System.loadLibrary('iconv')
-PythonActivity = autoclass('org.renpy.android.PythonActivity')
-Camera = autoclass('android.hardware.Camera')
-ImageScanner = autoclass('net.sourceforge.zbar.ImageScanner')
-Image = autoclass('net.sourceforge.zbar.Image')
-Symbol = autoclass('net.sourceforge.zbar.Symbol')
-Config = autoclass('net.sourceforge.zbar.Config')
-SurfaceView = autoclass('android.view.SurfaceView')
-LayoutParams = autoclass('android.view.ViewGroup$LayoutParams')
-ImageFormat = autoclass('android.graphics.ImageFormat')
-LinearLayout = autoclass('android.widget.LinearLayout')
-
-
-class PreviewCallback(PythonJavaClass):
- '''Interface used to get back the preview frame of the Android Camera
- '''
- __javainterfaces__ = ('android.hardware.Camera$PreviewCallback', )
-
- def __init__(self, callback):
- super(PreviewCallback, self).__init__()
- self.callback = callback
-
- @java_method('([BLandroid/hardware/Camera;)V')
- def onPreviewFrame(self, data, camera):
- self.callback(camera, data)
-
-
-class SurfaceHolderCallback(PythonJavaClass):
- '''Interface used to know exactly when the Surface used for the Android
- Camera will be created and changed.
- '''
-
- __javainterfaces__ = ('android.view.SurfaceHolder$Callback', )
-
- def __init__(self, callback):
- super(SurfaceHolderCallback, self).__init__()
- self.callback = callback
-
- @java_method('(Landroid/view/SurfaceHolder;III)V')
- def surfaceChanged(self, surface, fmt, width, height):
- self.callback(fmt, width, height)
-
- @java_method('(Landroid/view/SurfaceHolder;)V')
- def surfaceCreated(self, surface):
- pass
-
- @java_method('(Landroid/view/SurfaceHolder;)V')
- def surfaceDestroyed(self, surface):
- pass
-
-
-class AndroidWidgetHolder(Widget):
- '''Act as a placeholder for an Android widget.
- It will automatically add / remove the android view depending if the widget
- view is set or not. The android view will act as an overlay, so any graphics
- instruction in this area will be covered by the overlay.
- '''
-
- view = ObjectProperty(allownone=True)
- '''Must be an Android View
- '''
-
- def __init__(self, **kwargs):
- self._old_view = None
- from kivy.core.window import Window
- self._window = Window
- kwargs['size_hint'] = (None, None)
- super(AndroidWidgetHolder, self).__init__(**kwargs)
-
- def on_view(self, instance, view):
- if self._old_view is not None:
- layout = cast(LinearLayout, self._old_view.getParent())
- layout.removeView(self._old_view)
- self._old_view = None
-
- if view is None:
- return
-
- activity = PythonActivity.mActivity
- activity.addContentView(view, LayoutParams(*self.size))
- view.setZOrderOnTop(True)
- view.setX(self.x)
- view.setY(self._window.height - self.y - self.height)
- self._old_view = view
-
- def on_size(self, instance, size):
- if self.view:
- params = self.view.getLayoutParams()
- params.width = self.width
- params.height = self.height
- self.view.setLayoutParams(params)
- self.view.setY(self._window.height - self.y - self.height)
-
- def on_x(self, instance, x):
- if self.view:
- self.view.setX(x)
-
- def on_y(self, instance, y):
- if self.view:
- self.view.setY(self._window.height - self.y - self.height)
-
-
-class AndroidCamera(Widget):
- '''Widget for controling an Android Camera.
- '''
-
- index = NumericProperty(0)
-
- __events__ = ('on_preview_frame', )
-
- def __init__(self, **kwargs):
- self._holder = None
- self._android_camera = None
- super(AndroidCamera, self).__init__(**kwargs)
- self._holder = AndroidWidgetHolder(size=self.size, pos=self.pos)
- self.add_widget(self._holder)
-
- @run_on_ui_thread
- def stop(self):
- self.running = False
- if self._android_camera is None:
- return
- self._android_camera.setPreviewCallback(None)
- self._android_camera.release()
- self._android_camera = None
- self._holder.view = None
-
- @run_on_ui_thread
- def start(self):
- self.running = True
- if self._android_camera is not None:
- return
-
- self._android_camera = Camera.open(self.index)
-
- # create a fake surfaceview to get the previewCallback working.
- self._android_surface = SurfaceView(PythonActivity.mActivity)
- surface_holder = self._android_surface.getHolder()
-
- # create our own surface holder to correctly call the next method when
- # the surface is ready
- self._android_surface_cb = SurfaceHolderCallback(self._on_surface_changed)
- surface_holder.addCallback(self._android_surface_cb)
-
- # attach the android surfaceview to our android widget holder
- self._holder.view = self._android_surface
-
- # set orientation
- self._android_camera.setDisplayOrientation(90)
-
- def _on_surface_changed(self, fmt, width, height):
- # internal, called when the android SurfaceView is ready
- # FIXME if the size is not handled by the camera, it will failed.
- params = self._android_camera.getParameters()
- params.setPreviewSize(width, height)
- self._android_camera.setParameters(params)
-
- # now that we know the camera size, we'll create 2 buffers for faster
- # result (using Callback buffer approach, as described in Camera android
- # documentation)
- # it also reduce the GC collection
- bpp = ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8.
- buf = '\x00' * int(width * height * bpp)
- self._android_camera.addCallbackBuffer(buf)
- self._android_camera.addCallbackBuffer(buf)
-
- # create a PreviewCallback to get back the onPreviewFrame into python
- self._previewCallback = PreviewCallback(self._on_preview_frame)
-
- # connect everything and start the preview
- self._android_camera.setPreviewCallbackWithBuffer(self._previewCallback);
- self._android_camera.setPreviewDisplay(self._android_surface.getHolder())
- self._android_camera.startPreview();
-
- def _on_preview_frame(self, camera, data):
- # internal, called by the PreviewCallback when onPreviewFrame is
- # received
- self.dispatch('on_preview_frame', camera, data)
- # reintroduce the data buffer into the queue
- self._android_camera.addCallbackBuffer(data)
-
- def on_preview_frame(self, camera, data):
- pass
-
- def on_size(self, instance, size):
- if self._holder:
- self._holder.size = size
-
- def on_pos(self, instance, pos):
- if self._holder:
- 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
- '''
-
- def __init__(self, **kwargs):
- super(ScannerAndroid, self).__init__(**kwargs)
- 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.add_widget(self._camera)
-
- # create a scanner used for detecting qrcode
- self._scanner = ImageScanner()
- self._scanner.setConfig(0, Config.ENABLE, 0)
- self._scanner.setConfig(Symbol.QRCODE, Config.ENABLE, 1)
- self._scanner.setConfig(0, Config.X_DENSITY, 3)
- self._scanner.setConfig(0, Config.Y_DENSITY, 3)
-
-
- def start(self):
- self._camera.start()
-
- def stop(self):
- self._camera.stop()
-
- def _detect_qrcode_frame(self, instance, camera, data):
- if not self.get_root_window():
- self.stop()
- return
- parameters = camera.getParameters()
- size = parameters.getPreviewSize()
- 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()
- while it.hasNext():
- symbol = it.next()
- qrcode = ScannerAndroid.Qrcode(
- type=symbol.getType(),
- data=symbol.getData(),
- quality=symbol.getQuality(),
- 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):
- if self.show_bounds:
- self.update_bounds()
-
- def update_bounds(self):
- self.canvas.after.remove_group('bounds')
- if not self.symbols:
- return
- with self.canvas.after:
- Color(1, 0, 0, group='bounds')
- for symbol in self.symbols:
- x, y, w, h = symbol.bounds
- x = self._camera.right - x - w
- y = self._camera.top - y - h
- Line(rectangle=[x, y, w, h], group='bounds')
- '''
-
-
-if __name__ == '__main__':
- from kivy.lang import Builder
- from kivy.app import App
-
- qrcode_kv = '''
-BoxLayout:
- orientation: 'vertical'
-
- ZbarQrcodeDetector:
- id: detector
-
- Label:
- text: '\\n'.join(map(repr, detector.symbols))
- size_hint_y: None
- height: '100dp'
-
- BoxLayout:
- size_hint_y: None
- height: '48dp'
-
- Button:
- text: 'Scan a qrcode'
- on_release: detector.start()
- Button:
- text: 'Stop detection'
- on_release: detector.stop()
-'''
-
- class QrcodeExample(App):
- def build(self):
- return Builder.load_string(qrcode_kv)
-
- QrcodeExample().run()
diff --git a/gui/kivy/qr_scanner/scanner_camera.py b/gui/kivy/qr_scanner/scanner_camera.py
@@ -1,96 +0,0 @@
-from kivy.uix.camera import Camera
-from kivy.clock import Clock
-from kivy.utils import platform
-
-from electrum_gui.kivy.qr_scanner import ScannerBase
-
-import iconv
-
-try:
- from zbar import ImageScanner, Config, Image, Symbol
-except ImportError:
- raise SystemError('unable to import zbar please make sure you have'
- ' it installed.\nFor mac osx: `brew install zbar then\n`'
- '`pip install https://github.com/npinchot/zbar/archive/d3c1611ad2411fbdc3e79eb96ca704a63d30ae69.zip`')
-try:
- from PIL import Image as PILImage
-except ImportError:
- raise SystemError('unable to import Pil/pillow'
- ' please install one of the two.')
-
-__all__ = ('ScannerCamera', )
-
-class ScannerCamera(ScannerBase):
- '''Widget that use the kivy.uix.camera.Camera and zbar to detect
- qrcode. When found, the `symbols` will be updated
- '''
-
- def __init__(self, **kwargs):
- super(ScannerCamera, self).__init__(**kwargs)
- self._camera = None
- # create a scanner used for detecting qrcode
- self._scanner = ImageScanner()
- self._scanner.parse_config('enable')
- #self._scanner.setConfig(Symbol.QRCODE, Config.ENABLE, 1)
- #self._scanner.setConfig(0, Config.X_DENSITY, 3)
- #self._scanner.setConfig(0, Config.Y_DENSITY, 3)
-
- def start(self):
- if not self._camera:
- self._camera = Camera(
- resolution=self.camera_size,
- size_hint=(None, None))
- self.add_widget(self._camera)
- self.bind(size=self._camera.setter('size'))
- self.bind(pos=self._camera.setter('pos'))
- else:
- self._camera._camera.init_camera()
- self._camera.play = True
- Clock.schedule_interval(self._detect_qrcode_frame, 1/15)
-
- def stop(self):
- if not self._camera:
- return
- self._camera.play = False
- Clock.unschedule(self._detect_qrcode_frame)
- # TODO: testing for various platforms(windows, mac)
- if platform == 'linux':
- self._camera._camera._pipeline.set_state(1)
- #self._camera = None
-
- def _detect_qrcode_frame(self, *args):
- # 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
- if not self.get_root_window():
- self.stop()
- return
- cam = self._camera
- tex = cam.texture
- if not tex:
- return
- im = PILImage.fromstring('RGBA', tex.size, tex.pixels)
- im = im.convert('L')
- barcode = Image(tex.size[0],
- tex.size[1], 'Y800', im.tostring())
-
- result = self._scanner.scan(barcode)
-
- if result == 0:
- self.symbols = []
- del(barcode)
- return
-
- # we detected qrcode! extract and dispatch them
- symbols = []
- for symbol in barcode.symbols:
- qrcode = ScannerCamera.Qrcode(
- type=symbol.type,
- data=symbol.data,
- quality=symbol.quality,
- count=symbol.count,
- bounds=symbol.location)
- symbols.append(qrcode)
-
- self.symbols = symbols
- del(barcode)