kivy: rework send and receive screens

This commit is contained in:
ThomasV 2015-12-04 11:47:46 +01:00
parent e9ee851bb2
commit df02269bcf
4 changed files with 99 additions and 126 deletions

View File

@ -48,6 +48,7 @@ from kivy.uix.screenmanager import Screen
from kivy.uix.tabbedpanel import TabbedPanel from kivy.uix.tabbedpanel import TabbedPanel
from kivy.uix.label import Label from kivy.uix.label import Label
from kivy.uix.checkbox import CheckBox from kivy.uix.checkbox import CheckBox
from kivy.core.clipboard import Clipboard
Factory.register('TabbedCarousel', module='electrum_gui.kivy.uix.screens') Factory.register('TabbedCarousel', module='electrum_gui.kivy.uix.screens')
@ -163,7 +164,7 @@ class ElectrumWindow(App):
def __init__(self, **kwargs): def __init__(self, **kwargs):
# initialize variables # initialize variables
self._clipboard = None self._clipboard = Clipboard
self.info_bubble = None self.info_bubble = None
self.qrscanner = None self.qrscanner = None
self.nfcscanner = None self.nfcscanner = None
@ -203,18 +204,6 @@ class ElectrumWindow(App):
return return
self.send_screen.set_URI(url) self.send_screen.set_URI(url)
def send_from_clipboard(self, on_complete):
if not self._clipboard:
from kivy.core.clipboard import Clipboard
self._clipboard = Clipboard
contents = self._clipboard.get()
try:
uri = electrum.util.parse_URI(contents)
except:
self.show_info("Invalid URI", url)
return
on_complete(uri)
def scan_qr(self, on_complete): def scan_qr(self, on_complete):
from jnius import autoclass from jnius import autoclass
@ -564,14 +553,6 @@ class ElectrumWindow(App):
format(txs=tx_amount, amount=self.format_amount(v), format(txs=tx_amount, amount=self.format_amount(v),
unit=self.base_unit)) unit=self.base_unit))
def copy(self, text):
''' Copy provided text to clipboard
'''
if not self._clipboard:
from kivy.core.clipboard import Clipboard
self._clipboard = Clipboard
self._clipboard.put(text, 'text/plain')
def notify(self, message): def notify(self, message):
try: try:
global notification, os global notification, os
@ -776,7 +757,7 @@ class ElectrumWindow(App):
popup.tx_hash = tx_hash popup.tx_hash = tx_hash
popup.open() popup.open()
def amount_dialog(self, label, callback, show_max): def amount_dialog(self, screen, show_max):
popup = Builder.load_file('gui/kivy/uix/ui_screens/amount.kv') popup = Builder.load_file('gui/kivy/uix/ui_screens/amount.kv')
but_max = popup.ids.but_max but_max = popup.ids.but_max
if not show_max: if not show_max:
@ -786,15 +767,16 @@ class ElectrumWindow(App):
but_max.disabled = False but_max.disabled = False
but_max.opacity = 1 but_max.opacity = 1
if label.text != label.default_text: amount = screen.amount
a, u = label.text.split() if amount:
a, u = str(amount).split()
assert u == self.base_unit assert u == self.base_unit
popup.ids.a.amount = a popup.ids.a.amount = a
def cb(): def cb():
o = popup.ids.a.btc_text o = popup.ids.a.btc_text
label.text = o if o else label.default_text screen.amount = o
if callback:
callback()
popup.on_dismiss = cb popup.on_dismiss = cb
popup.open() popup.open()

View File

@ -10,12 +10,14 @@ from kivy.cache import Cache
from kivy.clock import Clock from kivy.clock import Clock
from kivy.compat import string_types from kivy.compat import string_types
from kivy.properties import (ObjectProperty, DictProperty, NumericProperty, from kivy.properties import (ObjectProperty, DictProperty, NumericProperty,
ListProperty) ListProperty, StringProperty)
from kivy.lang import Builder from kivy.lang import Builder
from kivy.factory import Factory from kivy.factory import Factory
from electrum.i18n import _ from electrum.i18n import _
from electrum.util import profiler from electrum.util import profiler, parse_URI
from electrum import bitcoin from electrum import bitcoin
from electrum.util import timestamp_to_datetime from electrum.util import timestamp_to_datetime
from electrum.plugins import run_hook from electrum.plugins import run_hook
@ -181,42 +183,38 @@ class SendScreen(CScreen):
kvname = 'send' kvname = 'send'
def set_URI(self, uri): def set_URI(self, uri):
print "z", uri print "set uri", uri
self.ids.payto_e.text = uri.get('address', '') self.screen.address = uri.get('address', '')
self.ids.message_e.text = uri.get('message', '') self.screen.message = uri.get('message', '')
amount = uri.get('amount') amount = uri.get('amount')
if amount: if amount:
amount_str = str( Decimal(amount) / pow(10, self.app.decimal_point())) amount_str = str( Decimal(amount) / pow(10, self.app.decimal_point()))
self.ids.amount_e.text = amount_str + ' ' + self.app.base_unit self.screen.amount = amount_str + ' ' + self.app.base_unit
def do_clear(self): def do_clear(self):
self.ids.payto_e.text = '' self.screen.amount = ''
self.ids.message_e.text = '' self.screen.message = ''
self.ids.amount_e.text = 'Amount' self.screen.address = ''
#self.set_frozen(content, False)
#self.update_status() def do_paste(self):
contents = unicode(self.app._clipboard.get())
try:
uri = parse_URI(contents)
except:
self.app.show_info("Invalid URI", contents)
return
self.set_URI(uri)
def do_send(self): def do_send(self):
scrn = self.ids address = str(self.screen.address)
label = unicode(scrn.message_e.text) amount = self.app.get_amount(self.screen.amount)
r = unicode(scrn.payto_e.text).strip() message = unicode(self.screen.message)
# label or alias, with address in brackets if not bitcoin.is_address(self.address):
m = re.match('(.*?)\s*\<([1-9A-HJ-NP-Za-km-z]{26,})\>', r) self.app.show_error(_('Invalid Bitcoin Address') + ':\n' + address)
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 return
amount = self.app.get_amount(scrn.amount_e.text)
#fee = scrn.fee_e.amt
#if not fee:
# app.show_error(_('Invalid Fee'))
# return
fee = None fee = None
message = 'sending {} {} to {}'.format(self.app.base_unit, scrn.amount_e.text, r) outputs = [('address', address, amount)]
outputs = [('address', to_address, amount)] self.app.password_dialog(self.send_tx, (outputs, fee, message))
self.app.password_dialog(self.send_tx, (outputs, fee, label))
def send_tx(self, *args): def send_tx(self, *args):
self.app.show_info("Sending...") self.app.show_info("Sending...")
@ -244,43 +242,41 @@ class SendScreen(CScreen):
class ReceiveScreen(CScreen): class ReceiveScreen(CScreen):
kvname = 'receive' kvname = 'receive'
def update(self): def update(self):
addr = self.app.wallet.get_unused_address(None) self.screen.address = self.app.wallet.get_unused_address(None)
address_label = self.screen.ids.get('address')
address_label.text = addr
self.update_qr()
def amount_callback(self, popup): def amount_callback(self, popup):
amount_label = self.screen.ids.get('amount') amount_label = self.screen.ids.get('amount')
amount_label.text = popup.ids.amount_label.text amount_label.text = popup.ids.amount_label.text
self.update_qr() self.update_qr()
@profiler def get_URI(self):
def update_qr(self):
from electrum.util import create_URI from electrum.util import create_URI
address = self.screen.ids.get('address').text amount = self.screen.amount
amount = self.screen.ids.get('amount').text if amount:
default_text = self.screen.ids.get('amount').default_text a, u = self.screen.amount.split()
if amount == default_text:
amount = None
else:
a, u = amount.split()
assert u == self.app.base_unit assert u == self.app.base_unit
amount = Decimal(a) * pow(10, self.app.decimal_point()) amount = Decimal(a) * pow(10, self.app.decimal_point())
msg = self.screen.ids.get('message').text return create_URI(self.screen.address, amount, self.screen.message)
uri = create_URI(address, amount, msg)
@profiler
def update_qr(self):
uri = self.get_URI()
qr = self.screen.ids.get('qr') qr = self.screen.ids.get('qr')
qr.set_data(uri) qr.set_data(uri)
def do_share(self): def do_copy(self):
pass uri = self.get_URI()
print "put", uri
self.app._clipboard.put(uri, 'text/plain')
print "get", self.app._clipboard.get()
def do_clear(self): def do_clear(self):
a = self.screen.ids.get('amount') self.screen.amount = ''
a.text = a.default_text self.screen.message = ''
self.screen.ids.get('message').text = ''

View File

@ -7,9 +7,20 @@
ReceiveScreen: ReceiveScreen:
id: receive_screen id: s
name: 'receive' name: 'receive'
address: ''
amount: ''
message: ''
on_address:
self.parent.update_qr()
on_amount:
self.parent.update_qr()
on_message:
self.parent.update_qr()
BoxLayout BoxLayout
padding: '12dp', '12dp', '12dp', '12dp' padding: '12dp', '12dp', '12dp', '12dp'
spacing: '12dp' spacing: '12dp'
@ -27,10 +38,11 @@ ReceiveScreen:
self.shaded = not self.shaded self.shaded = not self.shaded
self.foreground_color = (0, 0, 0, 0.5) if self.shaded else (0, 0, 0, 0) self.foreground_color = (0, 0, 0, 0.5) if self.shaded else (0, 0, 0, 0)
Label: Label:
id: address id: address_label
size_hint: 1, None size_hint: 1, None
height: '48dp' height: '48dp'
opacity: 0.5 if qr.shaded else 1 opacity: 0.5 if qr.shaded else 1
text: s.address
SendReceiveBlueBottom: SendReceiveBlueBottom:
id: blue_bottom id: blue_bottom
@ -45,8 +57,9 @@ ReceiveScreen:
size: '22dp', '22dp' size: '22dp', '22dp'
pos_hint: {'center_y': .5} pos_hint: {'center_y': .5}
AmountButton: AmountButton:
id: amount id: amount_label
on_release: app.amount_dialog(amount, receive_screen.parent.update_qr, False) text: s.amount if s.amount else 'Amount'
on_release: app.amount_dialog(s, False)
CardSeparator: CardSeparator:
opacity: message_selection.opacity opacity: message_selection.opacity
color: blue_bottom.foreground_color color: blue_bottom.foreground_color
@ -62,23 +75,23 @@ ReceiveScreen:
size: '22dp', '22dp' size: '22dp', '22dp'
pos_hint: {'center_y': .5} pos_hint: {'center_y': .5}
TextInputBlue: TextInputBlue:
id: message id: message_input
hint_text: 'Description' hint_text: 'Description'
on_text_validate: receive_screen.parent.update_qr() text: s.message
on_text_validate: s.message = self.text
BoxLayout: BoxLayout:
size_hint: 1, None size_hint: 1, None
height: '48dp' height: '48dp'
Button:
text: _('Copy')
size_hint: 1, None
height: '48dp'
on_release: s.parent.do_copy()
Button: Button:
text: _('Clear') text: _('Clear')
size_hint: 1, None size_hint: 1, None
height: '48dp' height: '48dp'
on_release: receive_screen.parent.do_clear() on_release: s.parent.do_clear()
Button:
text: _('Share')
size_hint: 1, None
height: '48dp'
on_release: receive_screen.parent.do_share()
Widget: Widget:
size_hint: 1, 0.3 size_hint: 1, 0.3

View File

@ -7,36 +7,14 @@
#:set font_light 'data/fonts/Roboto-Condensed.ttf' #:set font_light 'data/fonts/Roboto-Condensed.ttf'
<SendToggle@ToggleButton>
source: ''
markup: False
bold: True
border: 4, 4, 4, 4
group: 'transfer_type'
background_normal: self.background_down
color:
(.140, .140, .140, 1) if self.state == 'down' else (.796, .796, .796, 1)
canvas.after:
Color:
rgba: 1, 1, 1, 1
Image:
source: root.source
color: root.color
size: '30dp', '30dp'
center_x: root.center_x - ((root.texture_size[0]/2)+(self.width/1.5))
center_y: root.center_y
SendScreen: SendScreen:
id: send_screen id: s
name: 'send' name: 'send'
#action_view: Factory.SendActionView() address: ''
#on_deactivate: amount: ''
# self.ids.amount_e.focus = False message: ''
# self.ids.payto_e.focus = False
# self.ids.message_e.focus = False
BoxLayout BoxLayout
padding: '12dp', '12dp', '12dp', '12dp' padding: '12dp', '12dp', '12dp', '12dp'
spacing: '12dp' spacing: '12dp'
@ -56,6 +34,7 @@ SendScreen:
pos_hint: {'center_y': .5} pos_hint: {'center_y': .5}
TextInputBlue: TextInputBlue:
id: payto_e id: payto_e
text: s.address
hint_text: "Recipient" hint_text: "Recipient"
CardSeparator: CardSeparator:
opacity: message_selection.opacity opacity: message_selection.opacity
@ -70,8 +49,8 @@ SendScreen:
pos_hint: {'center_y': .5} pos_hint: {'center_y': .5}
AmountButton: AmountButton:
id: amount_e id: amount_e
on_release: app.amount_dialog(self, None, True) text: s.amount if s.amount else 'Amount'
on_release: app.amount_dialog(s, True)
CardSeparator: CardSeparator:
opacity: message_selection.opacity opacity: message_selection.opacity
@ -89,6 +68,7 @@ SendScreen:
pos_hint: {'center_y': .5} pos_hint: {'center_y': .5}
TextInputBlue: TextInputBlue:
id: message_e id: message_e
text: s.message
hint_text: 'Description' hint_text: 'Description'
BoxLayout: BoxLayout:
size_hint: 1, None size_hint: 1, None
@ -97,26 +77,28 @@ SendScreen:
id: qr id: qr
text: _('QR Code') text: _('QR Code')
on_release: on_release:
app.scan_qr(on_complete=root.set_URI) app.scan_qr(on_complete=s.parent.set_URI)
Button: Button:
id: paste_button id: paste_button
text: _('Clipboard') text: _('Paste')
on_release: on_release:
app.send_from_clipboard(on_complete=root.set_URI) s.parent.do_paste()
Button: Button:
text: _('Clear') text: _('Clear')
size_hint: 1, None size_hint: 1, None
height: '48dp' height: '48dp'
on_release: send_screen.do_clear() on_release: s.parent.do_clear()
Widget:
size_hint: 1, 1
BoxLayout: BoxLayout:
size_hint: 1, None size_hint: 1, None
height: '48dp' height: '48dp'
Widget:
size_hint: 1, 1
Button: Button:
text: _('Send') text: _('Send')
size_hint: 1, None size_hint: 1, None
height: '48dp' height: '48dp'
on_release: send_screen.do_send() on_release: s.parent.do_send()
Widget:
size_hint: 1, 1