URI: 
       tkivy: add context menus - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 6bd37723d3ddf89e9e34236ee07324c02ef1df14
   DIR parent 06eb3142c44cdefb5baccb72ffd20b8a0235e2aa
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Sat, 12 Dec 2015 16:54:32 +0100
       
       kivy: add context menus
       
       Diffstat:
         M gui/kivy/main.kv                    |      36 ++++++++++++++++++++++++-------
         M gui/kivy/main_window.py             |      17 ++---------------
         A gui/kivy/uix/context_menu.py        |      43 ++++++++++++++++++++++++++++++
         M gui/kivy/uix/dialogs/__init__.py    |       1 +
         M gui/kivy/uix/screens.py             |      49 ++++++++++++++++++++++++++-----
         M gui/kivy/uix/ui_screens/history.kv  |      34 +++----------------------------
         M gui/kivy/uix/ui_screens/invoices.kv |      15 +++------------
         M gui/kivy/uix/ui_screens/requests.kv |      22 +++++++---------------
       
       8 files changed, 129 insertions(+), 88 deletions(-)
       ---
   DIR diff --git a/gui/kivy/main.kv b/gui/kivy/main.kv
       t@@ -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 []
       t@@ -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:
   DIR diff --git a/gui/kivy/main_window.py b/gui/kivy/main_window.py
       t@@ -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('')
        
       t@@ -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
   DIR diff --git a/gui/kivy/uix/context_menu.py b/gui/kivy/uix/context_menu.py
       t@@ -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)
   DIR diff --git a/gui/kivy/uix/dialogs/__init__.py b/gui/kivy/uix/dialogs/__init__.py
       t@@ -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))
        
   DIR diff --git a/gui/kivy/uix/screens.py b/gui/kivy/uix/screens.py
       t@@ -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):
       t@@ -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):
       t@@ -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)
       t@@ -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:
       t@@ -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
       t@@ -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():
       t@@ -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):
       t@@ -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
   DIR diff --git a/gui/kivy/uix/ui_screens/history.kv b/gui/kivy/uix/ui_screens/history.kv
       t@@ -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'
       t@@ -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'
       t@@ -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:
       t@@ -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
       -
   DIR diff --git a/gui/kivy/uix/ui_screens/invoices.kv b/gui/kivy/uix/ui_screens/invoices.kv
       t@@ -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:
       t@@ -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'
   DIR diff --git a/gui/kivy/uix/ui_screens/requests.kv b/gui/kivy/uix/ui_screens/requests.kv
       t@@ -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:
       t@@ -51,3 +42,4 @@ RequestsScreen:
                        size_hint_y: None
                        height: self.minimum_height
                        spacing: '1dp'
       +                padding: '12dp'