URI: 
       tqrcodewidget.py - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
       tqrcodewidget.py (3689B)
       ---
            1 ''' Kivy Widget that accepts data and displays qrcode
            2 '''
            3 
            4 from threading import Thread
            5 from functools import partial
            6 
            7 import qrcode
            8 from qrcode import exceptions
            9 
           10 from kivy.uix.floatlayout import FloatLayout
           11 from kivy.graphics.texture import Texture
           12 from kivy.properties import StringProperty
           13 from kivy.properties import ObjectProperty, StringProperty, ListProperty,\
           14     BooleanProperty
           15 from kivy.lang import Builder
           16 from kivy.clock import Clock
           17 
           18 
           19 
           20 Builder.load_string('''
           21 <QRCodeWidget>
           22     canvas.before:
           23         # Draw white Rectangle
           24         Color:
           25             rgba: root.background_color
           26         Rectangle:
           27             size: self.size
           28             pos: self.pos
           29     canvas.after:
           30         Color:
           31             rgba: root.foreground_color
           32         Rectangle:
           33             size: self.size
           34             pos: self.pos
           35     Image
           36         id: qrimage
           37         pos_hint: {'center_x': .5, 'center_y': .5}
           38         allow_stretch: True
           39         size_hint: None, None
           40         size: root.width * .9, root.height * .9
           41 ''')
           42 
           43 class QRCodeWidget(FloatLayout):
           44 
           45     data = StringProperty(None, allow_none=True)
           46     background_color = ListProperty((1, 1, 1, 1))
           47     foreground_color = ListProperty((0, 0, 0, 0))
           48 
           49     def __init__(self, **kwargs):
           50         super(QRCodeWidget, self).__init__(**kwargs)
           51         self.data = None
           52         self.qr = None
           53         self._qrtexture = None
           54         self.failure_cb = None
           55 
           56     def on_data(self, instance, value):
           57         if not (self.canvas or value):
           58             return
           59         try:
           60             self.update_qr()
           61         except qrcode.exceptions.DataOverflowError:
           62             if self.failure_cb:
           63                 self.failure_cb()
           64             else:
           65                 raise
           66 
           67     def set_data(self, data, failure_cb=None):
           68         if self.data == data:
           69             return
           70         self.failure_cb = failure_cb
           71         MinSize = 210 if len(data) < 128 else 500
           72         self.setMinimumSize((MinSize, MinSize))
           73         self.data = data
           74         self.qr = None
           75 
           76     def update_qr(self):
           77         if not self.data and self.qr:
           78             return
           79         L = qrcode.constants.ERROR_CORRECT_L
           80         data = self.data
           81         self.qr = qr = qrcode.QRCode(
           82             version=None,
           83             error_correction=L,
           84             box_size=10,
           85             border=0,
           86         )
           87         qr.add_data(data)
           88         qr.make(fit=True)
           89         self.update_texture()
           90 
           91     def setMinimumSize(self, size):
           92         # currently unused, do we need this?
           93         self._texture_size = size
           94 
           95     def _create_texture(self, k):
           96         self._qrtexture = texture = Texture.create(size=(k,k), colorfmt='rgb')
           97         # don't interpolate texture
           98         texture.min_filter = 'nearest'
           99         texture.mag_filter = 'nearest'
          100 
          101     def update_texture(self):
          102         if not self.qr:
          103             return
          104         matrix = self.qr.get_matrix()
          105         k = len(matrix)
          106         # create the texture
          107         self._create_texture(k)
          108         buff = []
          109         bext = buff.extend
          110         cr, cg, cb, ca = self.background_color[:]
          111         cr, cg, cb = cr*255, cg*255, cb*255
          112         for r in range(k):
          113             for c in range(k):
          114                 bext([0, 0, 0] if matrix[k-1-r][c] else [cr, cg, cb])
          115         # then blit the buffer
          116         buff = bytes(buff)
          117         # update texture
          118         self._upd_texture(buff)
          119 
          120     def _upd_texture(self, buff):
          121         texture = self._qrtexture
          122         texture.blit_buffer(buff, colorfmt='rgb', bufferfmt='ubyte')
          123         img = self.ids.qrimage
          124         img.anim_delay = -1
          125         img.texture = texture
          126         img.canvas.ask_update()
          127 
          128 if __name__ == '__main__':
          129     from kivy.app import runTouchApp
          130     import sys
          131     data = str(sys.argv[1:])
          132     runTouchApp(QRCodeWidget(data=data))
          133 
          134