kivy: more cleanup, load qr code
This commit is contained in:
parent
28ffe32718
commit
f0b236b317
|
@ -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:
|
||||
|
|
|
@ -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):
|
||||
'''
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue