kivy: add context menus
This commit is contained in:
parent
06eb3142c4
commit
6bd37723d3
|
@ -187,6 +187,34 @@
|
|||
size: self.size
|
||||
pos: self.pos
|
||||
|
||||
<xxCardItem@ToggleButtonBehavior+GridLayout>
|
||||
canvas.before:
|
||||
Color:
|
||||
rgba: 0.192, .498, 0.745, 1 if self.state == 'down' else 0
|
||||
Rectangle
|
||||
size: self.size
|
||||
pos: self.x, self.y + dp(5)
|
||||
padding: '2dp', '2dp'
|
||||
spacing: '2dp'
|
||||
height: self.minimum_height
|
||||
|
||||
|
||||
<CardItem@ToggleButtonBehavior+BoxLayout>
|
||||
size_hint: 1, None
|
||||
height: '65dp'
|
||||
group: 'requests'
|
||||
padding: dp(12)
|
||||
spacing: dp(5)
|
||||
screen: None
|
||||
on_release:
|
||||
self.screen.show_menu(args[0]) if self.state == 'down' else self.screen.hide_menu()
|
||||
canvas.before:
|
||||
Color:
|
||||
rgba: (0.192, .498, 0.745, 1) if self.state == 'down' else (0.3, 0.3, 0.3, 1)
|
||||
Rectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
|
||||
<AddressSelector@BlueSpinner>
|
||||
icon: 'atlas://gui/kivy/theming/light/globe'
|
||||
values: [] #app.wallet.addresses() if app.wallet else []
|
||||
|
@ -388,14 +416,6 @@ BoxLayout:
|
|||
font_size: '22dp'
|
||||
minimum_width: '1dp'
|
||||
|
||||
ActionButton:
|
||||
id: context_button
|
||||
text: app.context
|
||||
width: 0
|
||||
on_text:
|
||||
self.width = 20 if self.text else 0
|
||||
on_release: app.context_action()
|
||||
|
||||
ActionOverflow:
|
||||
id: ao
|
||||
ActionOvrButton:
|
||||
|
|
|
@ -78,8 +78,6 @@ class ElectrumWindow(App):
|
|||
keys = sorted(base_units.keys())
|
||||
self.base_unit = keys[ (keys.index(self.base_unit) + 1) % len(keys)]
|
||||
|
||||
context = StringProperty('')
|
||||
context_action = lambda x: None
|
||||
status = StringProperty('')
|
||||
fiat_unit = StringProperty('')
|
||||
|
||||
|
@ -749,22 +747,11 @@ class ElectrumWindow(App):
|
|||
pos = (win.center[0], win.center[1] - (info_bubble.height/2))
|
||||
info_bubble.show(pos, duration, width, modal=modal, exit=exit)
|
||||
|
||||
def tx_dialog(self, tx_hash):
|
||||
def tx_dialog(self, obj):
|
||||
popup = Builder.load_file('gui/kivy/uix/ui_screens/transaction.kv')
|
||||
popup.tx_hash = tx_hash
|
||||
popup.tx_hash = obj.tx_hash
|
||||
popup.open()
|
||||
|
||||
def tx_selected(self, txid, state):
|
||||
if state == 'down':
|
||||
self.context = 'tx'
|
||||
self.context_action = lambda: self.tx_dialog(txid)
|
||||
else:
|
||||
self.reset_context()
|
||||
|
||||
def reset_context(self):
|
||||
self.context = ''
|
||||
self.context_action = lambda: None
|
||||
|
||||
def amount_dialog(self, screen, show_max):
|
||||
popup = Builder.load_file('gui/kivy/uix/ui_screens/amount.kv')
|
||||
but_max = popup.ids.but_max
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#!python
|
||||
#!/usr/bin/env python
|
||||
from kivy.app import App
|
||||
from kivy.uix.bubble import Bubble
|
||||
from kivy.animation import Animation
|
||||
from kivy.uix.floatlayout import FloatLayout
|
||||
from kivy.lang import Builder
|
||||
from kivy.factory import Factory
|
||||
|
||||
Builder.load_string('''
|
||||
<MenuItem@Button>
|
||||
background_color: .2, .9, 1, 1
|
||||
height: '40dp'
|
||||
size_hint: 1, None
|
||||
|
||||
<ContextMenu>
|
||||
size_hint: 1, None
|
||||
height: '32dp'
|
||||
#size: 120, 250
|
||||
pos: (0, 0)
|
||||
show_arrow: False
|
||||
padding: 0
|
||||
orientation: 'horizontal'
|
||||
BoxLayout:
|
||||
size_hint: 1, 1
|
||||
height: '40dp'
|
||||
orientation: 'horizontal'
|
||||
id: buttons
|
||||
''')
|
||||
|
||||
|
||||
class MenuItem(Factory.Button):
|
||||
pass
|
||||
|
||||
class ContextMenu(Bubble):
|
||||
def __init__(self, obj, action_list):
|
||||
Bubble.__init__(self)
|
||||
self.obj = obj
|
||||
for k, v in action_list:
|
||||
l = MenuItem()
|
||||
l.text = k
|
||||
l.on_release = lambda: v(obj)
|
||||
self.ids.buttons.add_widget(l)
|
|
@ -144,6 +144,7 @@ class InfoBubble(Factory.Bubble):
|
|||
m.add_widget(self)
|
||||
else:
|
||||
Window.add_widget(self)
|
||||
|
||||
# wait for the bubble to adjust it's size according to text then animate
|
||||
Clock.schedule_once(lambda dt: self._show(pos, duration))
|
||||
|
||||
|
|
|
@ -22,12 +22,17 @@ from electrum import bitcoin
|
|||
from electrum.util import timestamp_to_datetime
|
||||
from electrum.plugins import run_hook
|
||||
|
||||
from context_menu import ContextMenu
|
||||
|
||||
|
||||
class CScreen(Factory.Screen):
|
||||
|
||||
__events__ = ('on_activate', 'on_deactivate', 'on_enter', 'on_leave')
|
||||
action_view = ObjectProperty(None)
|
||||
loaded = False
|
||||
kvname = None
|
||||
context_menu = None
|
||||
menu_actions = []
|
||||
app = App.get_running_app()
|
||||
|
||||
def _change_action_view(self):
|
||||
|
@ -65,8 +70,19 @@ class CScreen(Factory.Screen):
|
|||
self.dispatch('on_deactivate')
|
||||
|
||||
def on_deactivate(self):
|
||||
pass
|
||||
#Clock.schedule_once(lambda dt: self._change_action_view())
|
||||
self.hide_menu()
|
||||
|
||||
def hide_menu(self):
|
||||
if self.context_menu:
|
||||
self.screen.remove_widget(self.context_menu)
|
||||
self.context_menu = None
|
||||
|
||||
def show_menu(self, obj):
|
||||
if self.context_menu is None:
|
||||
self.context_menu = ContextMenu(obj, self.menu_actions)
|
||||
self.screen.remove_widget(self.context_menu)
|
||||
self.screen.add_widget(self.context_menu)
|
||||
|
||||
|
||||
|
||||
class HistoryScreen(CScreen):
|
||||
|
@ -77,6 +93,7 @@ class HistoryScreen(CScreen):
|
|||
def __init__(self, **kwargs):
|
||||
self.ra_dialog = None
|
||||
super(HistoryScreen, self).__init__(**kwargs)
|
||||
self.menu_actions = [(_('Details'), self.app.tx_dialog)]
|
||||
|
||||
def get_history_rate(self, btc_balance, timestamp):
|
||||
date = timestamp_to_datetime(timestamp)
|
||||
|
@ -120,14 +137,12 @@ class HistoryScreen(CScreen):
|
|||
if self.app.wallet is None:
|
||||
return
|
||||
|
||||
history_card = self.screen.ids.recent_activity_card
|
||||
history_card = self.screen.ids.history_container
|
||||
history = self.parse_history(reversed(
|
||||
self.app.wallet.get_history(self.app.current_account)))
|
||||
# repopulate History Card
|
||||
last_widget = history_card.ids.content.children[-1]
|
||||
history_card.ids.content.clear_widgets()
|
||||
history_add = history_card.ids.content.add_widget
|
||||
history_add(last_widget)
|
||||
history_card.clear_widgets()
|
||||
history_add = history_card.add_widget
|
||||
RecentActivityItem = Factory.RecentActivityItem
|
||||
count = 0
|
||||
for item in history:
|
||||
|
@ -141,6 +156,7 @@ class HistoryScreen(CScreen):
|
|||
ri.quote_text = quote_text
|
||||
ri.confirmations = conf
|
||||
ri.tx_hash = tx
|
||||
ri.screen = self
|
||||
history_add(ri)
|
||||
if count == 8 and not see_all:
|
||||
break
|
||||
|
@ -345,6 +361,7 @@ class InvoicesScreen(CScreen):
|
|||
kvname = 'invoices'
|
||||
|
||||
def update(self):
|
||||
self.menu_actions = [(_('Pay'), self.do_pay), (_('Delete'), self.do_delete)]
|
||||
invoices_list = self.screen.ids.invoices_container
|
||||
invoices_list.clear_widgets()
|
||||
for pr in self.app.invoices.sorted_list():
|
||||
|
@ -356,12 +373,22 @@ class InvoicesScreen(CScreen):
|
|||
#ci.status = self.invoices.get_status(key)
|
||||
exp = pr.get_expiration_date()
|
||||
ci.date = format_time(exp) if exp else _('Never')
|
||||
ci.screen = self
|
||||
invoices_list.add_widget(ci)
|
||||
|
||||
def do_pay(self, x):
|
||||
pass
|
||||
|
||||
def do_delete(self, x):
|
||||
pass
|
||||
|
||||
class RequestsScreen(CScreen):
|
||||
kvname = 'requests'
|
||||
|
||||
def update(self):
|
||||
|
||||
self.menu_actions = [(_('View'), self.do_view), (_('Delete'), self.do_delete)]
|
||||
|
||||
requests_list = self.screen.ids.requests_container
|
||||
requests_list.clear_widgets()
|
||||
for req in self.app.wallet.get_sorted_requests(self.app.electrum_config):
|
||||
|
@ -378,9 +405,17 @@ class RequestsScreen(CScreen):
|
|||
#ci.status = req.get('status')
|
||||
ci.amount = self.app.format_amount(amount) if amount else ''
|
||||
ci.date = format_time(timestamp)
|
||||
ci.screen = self
|
||||
requests_list.add_widget(ci)
|
||||
|
||||
|
||||
def do_view(self, o):
|
||||
print o
|
||||
|
||||
def do_delete(self, o):
|
||||
print o
|
||||
|
||||
|
||||
|
||||
class CSpinner(Factory.Spinner):
|
||||
'''CustomDropDown that allows fading out the dropdown
|
||||
|
|
|
@ -38,20 +38,6 @@
|
|||
size: self.texture_size[0] + dp(32), self.texture_size[1] + dp(7)
|
||||
|
||||
|
||||
<CardItem@ToggleButtonBehavior+GridLayout>
|
||||
canvas.before:
|
||||
Color:
|
||||
rgba: 0.192, .498, 0.745, 1 if self.state == 'down' else 0
|
||||
Rectangle
|
||||
size: self.size
|
||||
pos: self.x, self.y + dp(5)
|
||||
cols: 1
|
||||
padding: '2dp', '2dp'
|
||||
spacing: '2dp'
|
||||
size_hint: 1, None
|
||||
height: self.minimum_height
|
||||
group: 'history'
|
||||
|
||||
<RecentActivityItem@CardItem>
|
||||
icon: 'atlas://gui/kivy/theming/light/important'
|
||||
address: 'no address set'
|
||||
|
@ -62,8 +48,7 @@
|
|||
date: '0/0/0'
|
||||
quote_text: '.'
|
||||
spacing: '9dp'
|
||||
on_release:
|
||||
app.tx_selected(root.tx_hash, self.state)
|
||||
cols: 1
|
||||
BoxLayout:
|
||||
size_hint: 1, None
|
||||
spacing: '8dp'
|
||||
|
@ -100,16 +85,6 @@
|
|||
u'[/color]'.format(amount_color=root.amount_color,\
|
||||
amount=root.amount[1:], qt=root.quote_text, sign=root.amount[0],\
|
||||
unit=app.base_unit)
|
||||
CardSeparator
|
||||
|
||||
<CardRecentActivity@Card>
|
||||
GridLayout:
|
||||
id: content
|
||||
spacing: '7dp'
|
||||
cols: 1
|
||||
size_hint: 1, None
|
||||
height: self.minimum_height
|
||||
CardSeparator
|
||||
|
||||
|
||||
HistoryScreen:
|
||||
|
@ -119,12 +94,9 @@ HistoryScreen:
|
|||
id: content
|
||||
do_scroll_x: False
|
||||
GridLayout
|
||||
id: grid
|
||||
cols: 1 #if root.width < root.height else 2
|
||||
id: history_container
|
||||
cols: 1
|
||||
size_hint: 1, None
|
||||
height: self.minimum_height
|
||||
padding: '12dp'
|
||||
spacing: '12dp'
|
||||
CardRecentActivity:
|
||||
id: recent_activity_card
|
||||
|
||||
|
|
|
@ -4,22 +4,12 @@
|
|||
halign: 'left'
|
||||
valign: 'middle'
|
||||
|
||||
<InvoiceItem@BoxLayout>
|
||||
<InvoiceItem@CardItem>
|
||||
requestor: ''
|
||||
memo: ''
|
||||
amount: ''
|
||||
status: ''
|
||||
date: ''
|
||||
size_hint_y: None
|
||||
height: '65dp'
|
||||
padding: dp(12)
|
||||
spacing: dp(5)
|
||||
canvas.before:
|
||||
Color:
|
||||
rgba: 0.3, 0.3, 0.3, 1
|
||||
Rectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
InvoicesLabel:
|
||||
text: root.requestor
|
||||
InvoicesLabel:
|
||||
|
@ -45,6 +35,7 @@ InvoicesScreen:
|
|||
GridLayout:
|
||||
cols: 1
|
||||
id: invoices_container
|
||||
size_hint_y: None
|
||||
size_hint: 1, None
|
||||
height: self.minimum_height
|
||||
spacing: '1dp'
|
||||
padding: '12dp'
|
||||
|
|
|
@ -1,35 +1,26 @@
|
|||
<InvoicesLabel@Label>
|
||||
<RequestLabel@Label>
|
||||
#color: .305, .309, .309, 1
|
||||
text_size: self.size
|
||||
halign: 'left'
|
||||
valign: 'middle'
|
||||
|
||||
<RequestItem@BoxLayout>
|
||||
<RequestItem@CardItem>
|
||||
address: ''
|
||||
memo: ''
|
||||
amount: ''
|
||||
status: ''
|
||||
date: ''
|
||||
size_hint_y: None
|
||||
height: '65dp'
|
||||
padding: dp(12)
|
||||
spacing: dp(5)
|
||||
canvas.before:
|
||||
Color:
|
||||
rgba: 0.3, 0.3, 0.3, 1
|
||||
Rectangle:
|
||||
size: self.size
|
||||
pos: self.pos
|
||||
InvoicesLabel:
|
||||
RequestLabel:
|
||||
text: root.address
|
||||
font_size: '13dp'
|
||||
InvoicesLabel:
|
||||
RequestLabel:
|
||||
text: root.memo
|
||||
InvoicesLabel:
|
||||
RequestLabel:
|
||||
text: root.amount
|
||||
#InvoicesLabel:
|
||||
# text: root.status
|
||||
|
||||
|
||||
RequestsScreen:
|
||||
name: 'requests'
|
||||
on_activate:
|
||||
|
@ -51,3 +42,4 @@ RequestsScreen:
|
|||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
spacing: '1dp'
|
||||
padding: '12dp'
|
||||
|
|
Loading…
Reference in New Issue