URI: 
       tkivy: show pending requests in receive tab instead of dialog - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 46c2d7821fb3a8e60b5a41cd46ecdc12cd1dc154
   DIR parent f8038d024b899d624326de71abbc60688e1339c8
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Fri,  9 Aug 2019 15:51:45 +0200
       
       kivy: show pending requests in receive tab instead of dialog
       
       Diffstat:
         D electrum/gui/kivy/uix/dialogs/requ… |     175 -------------------------------
         M electrum/gui/kivy/uix/screens.py    |      67 ++++++++++++++++++++++++++++++-
         M electrum/gui/kivy/uix/ui_screens/r… |      94 +++++++++++++++++++++++++------
       
       3 files changed, 141 insertions(+), 195 deletions(-)
       ---
   DIR diff --git a/electrum/gui/kivy/uix/dialogs/requests.py b/electrum/gui/kivy/uix/dialogs/requests.py
       t@@ -1,175 +0,0 @@
       -from kivy.app import App
       -from kivy.factory import Factory
       -from kivy.properties import ObjectProperty
       -from kivy.lang import Builder
       -from decimal import Decimal
       -
       -from electrum.util import age, PR_UNPAID
       -from electrum.lnutil import SENT, RECEIVED
       -from electrum.lnaddr import lndecode
       -import electrum.constants as constants
       -from electrum.bitcoin import COIN
       -
       -Builder.load_string('''
       -<RequestLabel@Label>
       -    #color: .305, .309, .309, 1
       -    text_size: self.width, None
       -    halign: 'left'
       -    valign: 'top'
       -
       -<RequestItem@CardItem>
       -    address: ''
       -    memo: ''
       -    amount: ''
       -    status: ''
       -    date: ''
       -    icon: 'atlas://electrum/gui/kivy/theming/light/important'
       -    Image:
       -        id: icon
       -        source: root.icon
       -        size_hint: None, 1
       -        width: self.height *.54
       -        mipmap: True
       -    BoxLayout:
       -        spacing: '8dp'
       -        height: '32dp'
       -        orientation: 'vertical'
       -        Widget
       -        RequestLabel:
       -            text: root.address
       -            shorten: True
       -        Widget
       -        RequestLabel:
       -            text: root.memo
       -            color: .699, .699, .699, 1
       -            font_size: '13sp'
       -            shorten: True
       -        Widget
       -    BoxLayout:
       -        spacing: '8dp'
       -        height: '32dp'
       -        orientation: 'vertical'
       -        Widget
       -        RequestLabel:
       -            text: root.amount
       -            halign: 'right'
       -            font_size: '15sp'
       -        Widget
       -        RequestLabel:
       -            text: root.status
       -            halign: 'right'
       -            font_size: '13sp'
       -            color: .699, .699, .699, 1
       -        Widget
       -
       -<RequestsDialog@Popup>
       -    id: popup
       -    title: _('Pending requests')
       -    BoxLayout:
       -        id:box
       -        orientation: 'vertical'
       -        spacing: '1dp'
       -        ScrollView:
       -            GridLayout:
       -                cols: 1
       -                id: requests_container
       -                size_hint: 1, None
       -                height: self.minimum_height
       -                spacing: '2dp'
       -                padding: '12dp'
       -''')
       -
       -from kivy.properties import BooleanProperty
       -from electrum.gui.kivy.i18n import _
       -from electrum.util import format_time
       -from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED
       -from electrum.gui.kivy.uix.context_menu import ContextMenu
       -
       -pr_icon = {
       -    PR_UNPAID: 'atlas://electrum/gui/kivy/theming/light/important',
       -    PR_UNKNOWN: 'atlas://electrum/gui/kivy/theming/light/important',
       -    PR_PAID: 'atlas://electrum/gui/kivy/theming/light/confirmed',
       -    PR_EXPIRED: 'atlas://electrum/gui/kivy/theming/light/close'
       -}
       -request_text = {
       -    PR_UNPAID: _('Pending'),
       -    PR_UNKNOWN: _('Unknown'),
       -    PR_PAID: _('Received'),
       -    PR_EXPIRED: _('Expired')
       -}
       -
       -
       -class RequestsDialog(Factory.Popup):
       -
       -    def __init__(self, app, screen, callback):
       -        Factory.Popup.__init__(self)
       -        self.app = app
       -        self.screen = screen
       -        self.callback = callback
       -        self.cards = {}
       -        self.context_menu = None
       -
       -    def get_card(self, is_lightning, key, address, amount, memo, timestamp):
       -        ci = self.cards.get(key)
       -        if ci is None:
       -            ci = Factory.RequestItem()
       -            ci.address = address
       -            ci.screen = self
       -            ci.is_lightning = is_lightning
       -            ci.key = key
       -            self.cards[key] = ci
       -
       -        ci.amount = self.app.format_amount_and_units(amount) if amount else ''
       -        ci.memo = memo
       -        ci.status = age(timestamp)
       -        #ci.icon = pr_icon[status]
       -        #exp = pr.get_expiration_date()
       -        #ci.date = format_time(exp) if exp else _('Never')
       -        return ci
       -
       -    def update(self):
       -        self.menu_actions = [(_('Show'), self.do_show), (_('Delete'), self.do_delete)]
       -        requests_list = self.ids.requests_container
       -        requests_list.clear_widgets()
       -        _list = self.app.wallet.get_sorted_requests(self.app.electrum_config)
       -        for req in _list[::-1]:
       -            is_lightning = req.get('lightning', False)
       -            status = req['status']
       -            if status != PR_UNPAID:
       -                continue
       -            if not is_lightning:
       -                address = req['address']
       -                key = address
       -            else:
       -                key = req['rhash']
       -                address = req['invoice']
       -            timestamp = req.get('time', 0)
       -            amount = req.get('amount')
       -            description = req.get('memo', '')
       -            ci = self.get_card(is_lightning, key, address, amount, description, timestamp)
       -            requests_list.add_widget(ci)
       -
       -    def do_show(self, obj):
       -        self.hide_menu()
       -        self.dismiss()
       -        self.app.show_request(obj.is_lightning, obj.key)
       -
       -    def do_delete(self, req):
       -        from .question import Question
       -        def cb(result):
       -            if result:
       -                self.app.wallet.remove_payment_request(req.address, self.app.electrum_config)
       -                self.hide_menu()
       -                self.update()
       -        d = Question(_('Delete request'), cb)
       -        d.open()
       -
       -    def show_menu(self, obj):
       -        self.hide_menu()
       -        self.context_menu = ContextMenu(obj, self.menu_actions)
       -        self.ids.box.add_widget(self.context_menu)
       -
       -    def hide_menu(self):
       -        if self.context_menu is not None:
       -            self.ids.box.remove_widget(self.context_menu)
       -            self.context_menu = None
   DIR diff --git a/electrum/gui/kivy/uix/screens.py b/electrum/gui/kivy/uix/screens.py
       t@@ -27,7 +27,7 @@ from electrum.util import profiler, parse_URI, format_time, InvalidPassword, Not
        from electrum import bitcoin, constants
        from electrum.transaction import TxOutput, Transaction, tx_from_str
        from electrum.util import send_exception_to_crash_reporter, parse_URI, InvalidBitcoinURI
       -from electrum.util import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED, TxMinedInfo
       +from electrum.util import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED, TxMinedInfo, age
        from electrum.plugin import run_hook
        from electrum.wallet import InternalAddressCorruption
        from electrum import simple_config
       t@@ -47,6 +47,9 @@ class Destination(Enum):
        class HistoryRecycleView(RecycleView):
            pass
        
       +class RequestRecycleView(RecycleView):
       +    pass
       +
        class CScreen(Factory.Screen):
            __events__ = ('on_activate', 'on_deactivate', 'on_enter', 'on_leave')
            action_view = ObjectProperty(None)
       t@@ -396,9 +399,15 @@ class SendScreen(CScreen):
                    self.app.tx_dialog(tx)
        
        
       +
        class ReceiveScreen(CScreen):
        
            kvname = 'receive'
       +    cards = {}
       +
       +    def __init__(self, **kwargs):
       +        super(ReceiveScreen, self).__init__(**kwargs)
       +        self.menu_actions = [(_('Show'), self.do_show), (_('Delete'), self.do_delete)]
        
            def clear(self):
                self.screen.address = ''
       t@@ -454,11 +463,65 @@ class ReceiveScreen(CScreen):
                    self.screen.address = addr
                    req = self.app.wallet.make_payment_request(addr, amount, message, expiration)
                    self.app.wallet.add_payment_request(req, self.app.electrum_config)
       -            #request = self.get_URI()
                    key = addr
                self.app.show_request(lightning, key)
        
       +    def get_card(self, req):
       +        is_lightning = req.get('lightning', False)
       +        status = req['status']
       +        #if status != PR_UNPAID:
       +        #    continue
       +        if not is_lightning:
       +            address = req['address']
       +            key = address
       +        else:
       +            key = req['rhash']
       +            address = req['invoice']
       +        timestamp = req.get('time', 0)
       +        amount = req.get('amount')
       +        description = req.get('memo', '')
       +        ci = self.cards.get(key)
       +        if ci is None:
       +            ci = {}
       +            ci['address'] = address
       +            ci['is_lightning'] = is_lightning
       +            ci['key'] = key
       +            ci['screen'] = self
       +            self.cards[key] = ci
       +        ci['amount'] = self.app.format_amount_and_units(amount) if amount else ''
       +        ci['memo'] = description
       +        ci['status'] = age(timestamp)
       +        return ci
       +
       +    def update(self):
       +        self.menu_actions = [(_('Show'), self.do_show), (_('Delete'), self.do_delete)]
       +        _list = self.app.wallet.get_sorted_requests(self.app.electrum_config)
       +        requests_container = self.screen.ids.requests_container
       +        requests_container.data = [self.get_card(item) for item in _list]
        
       +    def do_show(self, obj):
       +        self.hide_menu()
       +        self.app.show_request(obj.is_lightning, obj.key)
       +
       +    def do_delete(self, req):
       +        from .dialogs.question import Question
       +        def cb(result):
       +            if result:
       +                self.app.wallet.remove_payment_request(req.address, self.app.electrum_config)
       +                self.hide_menu()
       +                self.update()
       +        d = Question(_('Delete request'), cb)
       +        d.open()
       +
       +    def show_menu(self, obj):
       +        self.hide_menu()
       +        self.context_menu = ContextMenu(obj, self.menu_actions)
       +        self.add_widget(self.context_menu)
       +
       +    def hide_menu(self):
       +        if self.context_menu is not None:
       +            self.remove_widget(self.context_menu)
       +            self.context_menu = None
        
        class TabbedCarousel(Factory.TabbedPanel):
            '''Custom TabbedPanel using a carousel used in the Main Screen
   DIR diff --git a/electrum/gui/kivy/uix/ui_screens/receive.kv b/electrum/gui/kivy/uix/ui_screens/receive.kv
       t@@ -1,10 +1,71 @@
        #:import _ electrum.gui.kivy.i18n._
       +#:import Factory kivy.factory.Factory
        #:import Decimal decimal.Decimal
        #:set btc_symbol chr(171)
        #:set mbtc_symbol chr(187)
        #:set font_light 'electrum/gui/kivy/data/fonts/Roboto-Condensed.ttf'
        
        
       +<RequestLabel@Label>
       +    #color: .305, .309, .309, 1
       +    text_size: self.width, None
       +    halign: 'left'
       +    valign: 'top'
       +
       +<RequestItem@CardItem>
       +    address: ''
       +    memo: ''
       +    amount: ''
       +    status: ''
       +    date: ''
       +    icon: 'atlas://electrum/gui/kivy/theming/light/important'
       +    Image:
       +        id: icon
       +        source: root.icon
       +        size_hint: None, 1
       +        width: self.height *.54
       +        mipmap: True
       +    BoxLayout:
       +        spacing: '8dp'
       +        height: '32dp'
       +        orientation: 'vertical'
       +        Widget
       +        RequestLabel:
       +            text: root.address
       +            shorten: True
       +        Widget
       +        RequestLabel:
       +            text: root.memo
       +            color: .699, .699, .699, 1
       +            font_size: '13sp'
       +            shorten: True
       +        Widget
       +    BoxLayout:
       +        spacing: '8dp'
       +        height: '32dp'
       +        orientation: 'vertical'
       +        Widget
       +        RequestLabel:
       +            text: root.amount
       +            halign: 'right'
       +            font_size: '15sp'
       +        Widget
       +        RequestLabel:
       +            text: root.status
       +            halign: 'right'
       +            font_size: '13sp'
       +            color: .699, .699, .699, 1
       +        Widget
       +
       +<RequestRecycleView>:
       +    viewclass: 'RequestItem'
       +    RecycleBoxLayout:
       +        default_size: None, dp(56)
       +        default_size_hint: 1, None
       +        size_hint: 1, None
       +        height: self.minimum_height
       +        orientation: 'vertical'
       +
        
        ReceiveScreen:
            id: s
       t@@ -14,6 +75,7 @@ ReceiveScreen:
            message: ''
            status: ''
            is_lightning: False
       +    show_list: True
        
            BoxLayout
                padding: '12dp', '12dp', '12dp', '12dp'
       t@@ -29,7 +91,7 @@ ReceiveScreen:
                        height: blue_bottom.item_height
                        spacing: '5dp'
                        Image:
       -                    source: 'atlas://electrum/gui/kivy/theming/light/globe'
       +                    source: 'atlas://electrum/gui/kivy/theming/light/lightning' if root.is_lightning else 'atlas://electrum/gui/kivy/theming/light/globe'
                            size_hint: None, None
                            size: '22dp', '22dp'
                            pos_hint: {'center_y': .5}
       t@@ -37,9 +99,8 @@ ReceiveScreen:
                            id: address_label
                            text: _('Lightning') if root.is_lightning else (s.address if s.address else _('Bitcoin Address'))
                            shorten: True
       +                    on_release: root.is_lightning = not root.is_lightning
                            #on_release: Clock.schedule_once(lambda dt: app.addresses_dialog(s))
       -                    on_release:
       -                        root.is_lightning = not root.is_lightning
                    CardSeparator:
                        opacity: message_selection.opacity
                        color: blue_bottom.foreground_color
       t@@ -81,11 +142,12 @@ ReceiveScreen:
                    height: '48dp'
                    IconButton:
                        icon: 'atlas://electrum/gui/kivy/theming/light/list'
       -                size_hint: 1, None
       +                size_hint: 0.5, None
                        height: '48dp'
       -                on_release: Clock.schedule_once(lambda dt: app.requests_dialog(s))
       -            #Widget:
       -            #    size_hint: 0.5, 1
       +                on_release: root.show_list = not root.show_list
       +                #Clock.schedule_once(lambda dt: app.requests_dialog(s))
       +            Widget:
       +                size_hint: 0.5, None
                    Button:
                        text: _('Clear')
                        size_hint: 1, None
       t@@ -97,14 +159,10 @@ ReceiveScreen:
                        height: '48dp'
                        on_release: Clock.schedule_once(lambda dt: s.parent.new_request(root.is_lightning))
                Widget:
       -            size_hint: 1, 1
       -        #BoxLayout:
       -        #    size_hint: 1, None
       -        #    height: '48dp'
       -        #    IconButton:
       -        #        icon: 'atlas://electrum/gui/kivy/theming/light/list'
       -        #        size_hint: 0.5, None
       -        #        height: '48dp'
       -        #        on_release: Clock.schedule_once(lambda dt: app.requests_dialog(s))
       -        #    Widget:
       -        #        size_hint: 2.5, 1
       +            size_hint: 1, 0.1
       +        RequestRecycleView:
       +            id: requests_container
       +            scroll_type: ['bars', 'content']
       +            bar_width: '25dp'
       +            opacity: 1 if root.show_list else 0
       +            disabled: not root.show_list