commit 46c2d7821fb3a8e60b5a41cd46ecdc12cd1dc154
parent f8038d024b899d624326de71abbc60688e1339c8
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:
3 files changed, 141 insertions(+), 195 deletions(-)
diff --git a/electrum/gui/kivy/uix/dialogs/requests.py b/electrum/gui/kivy/uix/dialogs/requests.py
@@ -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
diff --git a/electrum/gui/kivy/uix/screens.py b/electrum/gui/kivy/uix/screens.py
@@ -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
@@ -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)
@@ -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 = ''
@@ -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
diff --git a/electrum/gui/kivy/uix/ui_screens/receive.kv b/electrum/gui/kivy/uix/ui_screens/receive.kv
@@ -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
@@ -14,6 +75,7 @@ ReceiveScreen:
message: ''
status: ''
is_lightning: False
+ show_list: True
BoxLayout
padding: '12dp', '12dp', '12dp', '12dp'
@@ -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}
@@ -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
@@ -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
@@ -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