commit 6bd37723d3ddf89e9e34236ee07324c02ef1df14
parent 06eb3142c44cdefb5baccb72ffd20b8a0235e2aa
Author: ThomasV <thomasv@electrum.org>
Date: Sat, 12 Dec 2015 16:54:32 +0100
kivy: add context menus
Diffstat:
8 files changed, 129 insertions(+), 88 deletions(-)
diff --git a/gui/kivy/main.kv b/gui/kivy/main.kv
@@ -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:
diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py
@@ -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
diff --git a/gui/kivy/uix/context_menu.py b/gui/kivy/uix/context_menu.py
@@ -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)
diff --git a/gui/kivy/uix/dialogs/__init__.py b/gui/kivy/uix/dialogs/__init__.py
@@ -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))
diff --git a/gui/kivy/uix/screens.py b/gui/kivy/uix/screens.py
@@ -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
diff --git a/gui/kivy/uix/ui_screens/history.kv b/gui/kivy/uix/ui_screens/history.kv
@@ -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
-
diff --git a/gui/kivy/uix/ui_screens/invoices.kv b/gui/kivy/uix/ui_screens/invoices.kv
@@ -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'
diff --git a/gui/kivy/uix/ui_screens/requests.kv b/gui/kivy/uix/ui_screens/requests.kv
@@ -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'