kivy: more cleanup, load qr code

This commit is contained in:
ThomasV 2015-10-06 14:30:44 +02:00
parent 28ffe32718
commit f0b236b317
6 changed files with 108 additions and 239 deletions

View File

@ -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:

View File

@ -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):
'''

View File

@ -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()

View File

@ -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
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)
@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:
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'

View File

@ -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'

View File

@ -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