electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit f0b236b317407b5397d170189c0f35ead5607d72
parent 28ffe32718bc836c001639f4cff9ad31990290f7
Author: ThomasV <thomasv@electrum.org>
Date:   Tue,  6 Oct 2015 14:30:44 +0200

kivy: more cleanup, load qr code

Diffstat:
Mgui/kivy/main.kv | 2+-
Mgui/kivy/main_window.py | 58+++-------------------------------------------------------
Mgui/kivy/uix/qrcodewidget.py | 44+++++++++++++++-----------------------------
Mgui/kivy/uix/screens.py | 75++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mgui/kivy/uix/ui_screens/receive.kv | 163+++++++++++--------------------------------------------------------------------
Mgui/kivy/uix/ui_screens/send.kv | 3++-
6 files changed, 107 insertions(+), 238 deletions(-)

diff --git a/gui/kivy/main.kv b/gui/kivy/main.kv @@ -370,7 +370,7 @@ TabbedCarousel: id: panel tab_height: '48dp' - default_tab: send_tab + #default_tab: send_tab strip_border: 0, 0, 0, 0 HistoryScreen: diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py @@ -6,8 +6,7 @@ import traceback from electrum import WalletStorage, Wallet from electrum.i18n import _, set_language from electrum.contacts import Contacts -from electrum import bitcoin -from electrum.util import profiler, print_error +from electrum.util import profiler from kivy.app import App from kivy.core.window import Window @@ -100,7 +99,7 @@ class ElectrumWindow(App): ''' status = StringProperty(_('Not Connected')) - balance = StringProperty('') + def _get_num_zeros(self): @@ -498,14 +497,12 @@ class ElectrumWindow(App): else: c, u, x = self.wallet.get_account_balance(self.current_account) text = self.format_amount(c) - self.balance = text if u: unconfirmed = " [%s unconfirmed]" %( self.format_amount(u, True).strip()) if x: unmatured = " [%s unmatured]"%(self.format_amount(x, True).strip()) - self.balance = text.strip() quote_text = self.create_quote_text(Decimal(c+u+x)/100000000, mode='symbol') or '' - self.status = self.balance + self.status = text.strip() + ' ' + self.base_unit else: self.status = _("Not connected") @@ -552,55 +549,6 @@ class ElectrumWindow(App): self.contacts_screen.update() - def do_send(self): - app = App.get_running_app() - screen_send = app.root.main_screen.ids.tabs.ids.screen_send - scrn = screen_send.ids - label = unicode(scrn.message_e.text) - r = unicode(scrn.payto_e.text).strip() - # label or alias, with address in brackets - m = re.match('(.*?)\s*\<([1-9A-HJ-NP-Za-km-z]{26,})\>', r) - to_address = m.group(2) if m else r - - if not bitcoin.is_address(to_address): - app.show_error(_('Invalid Bitcoin Address') + ':\n' + to_address) - return - - amount = self.get_amount(scrn.amount_e.text) - - fee = scrn.fee_e.amt - if not fee: - app.show_error(_('Invalid Fee')) - return - - #from pudb import set_trace; set_trace() - message = 'sending {} {} to {}'.format(app.base_unit, scrn.amount_e.text, r) - - # assume no password and fee is None - password = None - fee = None - self.send_tx([('address', to_address, amount)], fee, label, password) - - def send_tx(self, outputs, fee, label, password): - app = App.get_running_app() - # make unsigned transaction - coins = self.wallet.get_spendable_coins() - try: - tx = self.wallet.make_unsigned_transaction(coins, outputs, self.electrum_config, fee) - except Exception as e: - traceback.print_exc(file=sys.stdout) - app.show_error(str(e)) - return - # sign transaction - try: - self.wallet.sign_transaction(tx, password) - except Exception as e: - traceback.print_exc(file=sys.stdout) - app.show_error(str(e)) - return - # broadcast - self.wallet.sendtx(tx) - @profiler def notify_transactions(self, *dt): ''' diff --git a/gui/kivy/uix/qrcodewidget.py b/gui/kivy/uix/qrcodewidget.py @@ -1,4 +1,4 @@ -''' Kivy Widget that accepts data and displas qrcode +''' Kivy Widget that accepts data and displays qrcode ''' from threading import Thread @@ -28,7 +28,7 @@ Builder.load_string(''' pos: self.pos canvas.after: Color: - rgba: .5, .5, .5, 1 if root.show_border else 0 + rgba: .5, .5, .5, 0 Line: width: dp(1.333) points: @@ -47,13 +47,6 @@ Builder.load_string(''' class QRCodeWidget(FloatLayout): - show_border = BooleanProperty(True) - '''Whether to show border around the widget. - - :data:`show_border` is a :class:`~kivy.properties.BooleanProperty`, - defaulting to `True`. - ''' - data = StringProperty(None, allow_none=True) ''' Data using which the qrcode is generated. @@ -77,7 +70,7 @@ class QRCodeWidget(FloatLayout): self._qrtexture = None def on_data(self, instance, value): - print "on data" + print "on data", value if not (self.canvas or value): return img = self.ids.get('qrimage', None) @@ -86,18 +79,15 @@ class QRCodeWidget(FloatLayout): # if texture hasn't yet been created delay the texture updation Clock.schedule_once(lambda dt: self.on_data(instance, value)) return - img.anim_delay = .05 - img.source = self.loading_image - Thread(target=partial(self.generate_qr, value)).start() - def generate_qr(self, value): - self.set_data(value) + #Thread(target=partial(self.update_qr, )).start() self.update_qr() def set_data(self, data): + print "set data", data if self.data == data: return - MinSize = 210 if len(addr) < 128 else 500 + MinSize = 210 if len(data) < 128 else 500 self.setMinimumSize((MinSize, MinSize)) self.data = data self.qr = None @@ -107,18 +97,14 @@ class QRCodeWidget(FloatLayout): return L = qrcode.constants.ERROR_CORRECT_L data = self.data - try: - self.qr = qr = qrcode.QRCode( - version=None, - error_correction=L, - box_size=10, - border=0, - ) - qr.add_data(data) - qr.make(fit=True) - except Exception as e: - print e - self.qr=None + self.qr = qr = qrcode.QRCode( + version=None, + error_correction=L, + box_size=10, + border=0, + ) + qr.add_data(data) + qr.make(fit=True) self.update_texture() def setMinimumSize(self, size): @@ -132,7 +118,7 @@ class QRCodeWidget(FloatLayout): texture.mag_filter = 'nearest' def update_texture(self): - if not self.addr: + if not self.qr: return matrix = self.qr.get_matrix() diff --git a/gui/kivy/uix/screens.py b/gui/kivy/uix/screens.py @@ -8,9 +8,7 @@ from kivy.lang import Builder from kivy.factory import Factory from electrum.i18n import _ - -# Delayed imports -app = None +from electrum.util import profiler class CScreen(Factory.Screen): @@ -40,16 +38,17 @@ class CScreen(Factory.Screen): def update(self): pass + @profiler + def load_screen(self): + self.screen = Builder.load_file('gui/kivy/uix/ui_screens/' + self.kvname + '.kv') + self.add_widget(self.screen) + self.loaded = True + self.update() + setattr(self.app, self.kvname + '_screen', self) + def on_activate(self): - if self.kvname and not self.loaded: - print "loading:" + self.kvname - self.screen = Builder.load_file('gui/kivy/uix/ui_screens/' + self.kvname + '.kv') - self.add_widget(self.screen) - self.loaded = True - self.update() - setattr(self.app, self.kvname + '_screen', self) - + self.load_screen() #Clock.schedule_once(lambda dt: self._change_action_view()) def on_leave(self): @@ -197,8 +196,62 @@ class SendScreen(CScreen): self.ids.message_e.text = uri.get('message', '') self.ids.amount_e.text = uri.get('amount', '') + def do_send(self): + import re + from electrum import bitcoin + scrn = self.ids + label = unicode(scrn.message_e.text) + r = unicode(scrn.payto_e.text).strip() + # label or alias, with address in brackets + m = re.match('(.*?)\s*\<([1-9A-HJ-NP-Za-km-z]{26,})\>', r) + to_address = m.group(2) if m else r + + if not bitcoin.is_address(to_address): + self.app.show_error(_('Invalid Bitcoin Address') + ':\n' + to_address) + return + + amount = self.app.get_amount(scrn.amount_e.text) + fee = scrn.fee_e.amt + if not fee: + app.show_error(_('Invalid Fee')) + return + + message = 'sending {} {} to {}'.format(app.base_unit, scrn.amount_e.text, r) + + # assume no password and fee is None + password = None + fee = None + #self.send_tx([('address', to_address, amount)], fee, label, password) + + def send_tx(self, outputs, fee, label, password): + app = App.get_running_app() + # make unsigned transaction + coins = self.wallet.get_spendable_coins() + try: + tx = self.wallet.make_unsigned_transaction(coins, outputs, self.electrum_config, fee) + except Exception as e: + traceback.print_exc(file=sys.stdout) + app.show_error(str(e)) + return + # sign transaction + try: + self.wallet.sign_transaction(tx, password) + except Exception as e: + traceback.print_exc(file=sys.stdout) + app.show_error(str(e)) + return + # broadcast + self.wallet.sendtx(tx) + + + class ReceiveScreen(CScreen): kvname = 'receive' + def update(self): + addr = self.app.wallet.get_unused_address(None) + qr = self.screen.ids.get('qr') + qr.set_data(addr) + class ContactsScreen(CScreen): kvname = 'contacts' diff --git a/gui/kivy/uix/ui_screens/receive.kv b/gui/kivy/uix/ui_screens/receive.kv @@ -7,157 +7,38 @@ ReceiveScreen: + id: receive_screen name: 'receive' mode: 'qr' on_mode: if args[1] == 'nfc': from electrum_gui.kivy.nfc_scanner import NFCScanner - action_view: Factory.ReceiveActionView() - - #on_activate: - # self.ids.toggle_qr.state = 'down' - # first_address = app.wallet.addresses()[0] - # qr.data = app.encode_uri(first_address, - # amount=amount_e.text, - # label=app.wallet.labels.get(first_address, first_address), - # message='') if app.wallet and app.wallet.addresses() else '' - #on_deactivate: - # self.ids.amount_e.focus = False BoxLayout padding: '12dp', '12dp', '12dp', '12dp' spacing: '12dp' mode: 'qr' orientation: 'vertical' - SendReceiveToggle - SendToggle: - id: toggle_qr - text: 'QR' - state: 'down' if root.mode == 'qr' else 'normal' - source: 'atlas://gui/kivy/theming/light/qrcode' - background_down: 'atlas://gui/kivy/theming/light/btn_send_address' - on_release: - if root.mode == 'qr': root.mode = 'nr' - root.mode = 'qr' - SendToggle: - id: toggle_nfc - text: 'NFC' - state: 'down' if root.mode == 'nfc' else 'normal' - source: 'atlas://gui/kivy/theming/light/nfc' - background_down: 'atlas://gui/kivy/theming/light/btn_send_nfc' - on_release: - if root.mode == 'nfc': root.mode = 'nr' - root.mode = 'nfc' + + FloatLayout: + id: bl + QRCodeWidget: + id: qr + size_hint: None, 1 + width: min(self.height, bl.width) + pos_hint: {'center': (.5, .5)} + on_touch_down: + if self.collide_point(*args[1].pos):\ + app.show_info_bubble(icon=self.ids.qrimage.texture, text='texture') + GridLayout: id: grid cols: 1 - #size_hint: 1, None - #height: self.minimum_height - SendReceiveCardTop - height: '110dp' - BoxLayout: - size_hint: 1, None - height: '42dp' - rows: 1 - Label: - color: amount_e.foreground_color - bold: True - text_size: self.size - valign: 'bottom' - font_size: '22sp' - text: - u'[font={fnt}]{smbl}[/font]'.\ - format(smbl=btc_symbol if app.base_unit == 'BTC' else mbtc_symbol, fnt=font_light) - size_hint_x: .25 - ELTextInput: - id: amount_e - input_type: 'number' - multiline: False - bold: True - font_size: '50sp' - foreground_color: .308, .308, .308, 1 - background_normal: 'atlas://gui/kivy/theming/light/tab_btn' - pos_hint: {'top': 1.5} - size_hint: .7, None - height: '67dp' - hint_text: 'Amount' - text: '0.0' - CardSeparator - BoxLayout: - size_hint: 1, None - height: '32dp' - spacing: '5dp' - Label: - color: lbl_quote.color - font_size: '12dp' - text: 'Ask to scan the QR below' - text_size: self.size - halign: 'left' - valign: 'middle' - Label: - id: lbl_quote - font_size: '12dp' - size_hint: .5, 1 - color: .761, .761, .761, 1 - text: u'= {}'.format(app.create_quote_text(Decimal(float(amount_e.text)), mode='symbol')) if amount_e.text else u'0' - text_size: self.size - halign: 'right' - valign: 'middle' - SendReceiveBlueBottom - id: blue_bottom - padding: '12dp', 0, '12dp', '12dp' - AddressSelector: - id: address_selection - foreground_color: blue_bottom.foreground_color - opacity: 1 - size_hint: 1, None - height: blue_bottom.item_height - on_text: - if not args[1].startswith('Select'):\ - qr.data = app.encode_uri(args[1],\ - amount=amount_e.text,\ - label=app.wallet.labels.get(args[1], args[1]),\ - message='') - CardSeparator - opacity: address_selection.opacity - color: blue_bottom.foreground_color - Widget: - size_hint_y: None - height: dp(10) - FloatLayout - id: bl - QRCodeWidget: - id: qr - size_hint: None, 1 - width: min(self.height, bl.width) - pos_hint: {'center': (.5, .5)} - on_touch_down: - if self.collide_point(*args[1].pos):\ - app.show_info_bubble(icon=self.ids.qrimage.texture, text='texture') - Button: - background_color: (1, 1, 1, 1) if self.disabled else ((.258, .80, .388, 1) if self.state == 'normal' else (.203, .490, .741, 1)) - text: _('Goto next step') if app.wallet and app.wallet.seed else _('Create unsigned transaction') - size_hint_y: None - height: '38dp' - #disabled: True if wallet_selection.opacity == 0 else False - on_release: - message = 'sending {} {} to {}'.format(\ - app.base_unit, amount_e.text, payto_e.text) - app.gui.main_gui.do_send(self, message=message) + Button: + text: 'Amount: None' + size_hint_y: None + height: '48dp' + on_release: receive_screen.set_amount_dialog() + Button: + text: 'Message: None' + size_hint_y: None + height: '48dp' -<ReceiveActionView@ActionView> - WalletActionPrevious: - id: action_previous - width: '32dp' - ActionButton: - id: action_logo - important: True - size_hint: 1, 1 - markup: True - mipmap: True - bold: True - markup: True - color: 1, 1, 1, 1 - text: - "[color=#777777][sub] [sup][size=9dp]{}[/size][/sup][/sub]{}[/color]"\ - .format(app.base_unit, app.status) - font_size: '22dp' - minimum_width: '1dp' diff --git a/gui/kivy/uix/ui_screens/send.kv b/gui/kivy/uix/ui_screens/send.kv @@ -23,6 +23,7 @@ SendScreen: + id: send_screen mode: 'address' name: 'send' #action_view: Factory.SendActionView() @@ -207,7 +208,7 @@ SendScreen: size_hint_y: None height: '38dp' disabled: False - on_release: app.do_send() + on_release: send_screen.do_send() Widget