commit e9c32bad1946d8ef07b8018f6578d7ed4782ca7a
parent 587f8aa48702496407f5044fa3a3d9f9aae36f34
Author: ThomasV <thomasv@electrum.org>
Date: Fri, 23 Aug 2019 12:15:42 +0200
kivy: remove context menus, cleanup unused files
Diffstat:
11 files changed, 208 insertions(+), 603 deletions(-)
diff --git a/electrum/gui/kivy/main.kv b/electrum/gui/kivy/main.kv
@@ -231,15 +231,14 @@
size: self.size
pos: self.pos
-<CardItem@ToggleButtonBehavior+BoxLayout>
+<CardItem@ButtonBehavior+BoxLayout>
size_hint: 1, None
height: '65dp'
group: 'requests'
padding: dp(12)
spacing: dp(5)
screen: None
- on_state:
- self.screen.show_menu(args[0]) if self.state == 'down' else self.screen.hide_menu()
+ on_release: self.screen.show_item(args[0])
canvas.before:
Color:
rgba: (0.192, .498, 0.745, 1) if self.state == 'down' else (0.15, 0.15, 0.17, 1)
diff --git a/electrum/gui/kivy/main_window.py b/electrum/gui/kivy/main_window.py
@@ -418,41 +418,6 @@ class ElectrumWindow(App):
self.request_popup.set_status(status)
self.request_popup.open()
- def show_pr_details(self, req, status, is_invoice):
- from electrum.util import format_time
- requestor = req.get('requestor')
- exp = req.get('exp')
- memo = req.get('memo')
- amount = req.get('amount')
- fund = req.get('fund')
- popup = Builder.load_file('electrum/gui/kivy/uix/ui_screens/invoice.kv')
- popup.is_invoice = is_invoice
- popup.amount = amount
- popup.requestor = requestor if is_invoice else req.get('address')
- popup.exp = format_time(exp) if exp else ''
- popup.description = memo if memo else ''
- popup.signature = req.get('signature', '')
- popup.status = status
- popup.fund = fund if fund else 0
- txid = req.get('txid')
- popup.tx_hash = txid or ''
- popup.on_open = lambda: popup.ids.output_list.update(req.get('outputs', []))
- popup.export = self.export_private_keys
- popup.open()
-
- def show_addr_details(self, req, status):
- from electrum.util import format_time
- fund = req.get('fund')
- isaddr = 'y'
- popup = Builder.load_file('electrum/gui/kivy/uix/ui_screens/invoice.kv')
- popup.isaddr = isaddr
- popup.is_invoice = False
- popup.status = status
- popup.requestor = req.get('address')
- popup.fund = fund if fund else 0
- popup.export = self.export_private_keys
- popup.open()
-
def qr_dialog(self, title, data, show_text=False, text_for_clipboard=None):
from .uix.dialogs.qr_dialog import QRDialog
def on_qr_failure():
@@ -1035,28 +1000,6 @@ class ElectrumWindow(App):
popup = AmountDialog(show_max, amount, cb)
popup.open()
- def lightning_invoices_dialog(self, cb):
- from .uix.dialogs.lightning_invoices import LightningInvoicesDialog
- report = self.wallet.lnworker._list_invoices()
- if not report['unsettled']:
- self.show_info(_('No unsettled invoices. Type in an amount to generate a new one.'))
- return
- popup = LightningInvoicesDialog(report, cb)
- popup.open()
-
- def invoices_dialog(self, screen):
- from .uix.dialogs.invoices import InvoicesDialog
- if len(self.wallet.invoices.sorted_list()) == 0:
- self.show_info(' '.join([
- _('No saved invoices.'),
- _('Signed invoices are saved automatically when you scan them.'),
- _('You may also save unsigned requests or contact addresses using the save button.')
- ]))
- return
- popup = InvoicesDialog(self, screen, None)
- popup.update()
- popup.open()
-
def addresses_dialog(self):
from .uix.dialogs.addresses import AddressesDialog
if self._addresses_dialog is None:
diff --git a/electrum/gui/kivy/uix/context_menu.py b/electrum/gui/kivy/uix/context_menu.py
@@ -1,58 +0,0 @@
-#!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
-from kivy.clock import Clock
-
-from electrum.gui.kivy.i18n import _
-
-Builder.load_string('''
-<MenuItem@Button>
- background_normal: ''
- background_color: (0.192, .498, 0.745, 1)
- height: '48dp'
- size_hint: 1, None
-
-<ContextMenu>
- size_hint: 1, None
- height: '60dp'
- pos: (0, 0)
- show_arrow: False
- arrow_pos: 'top_mid'
- padding: 0
- orientation: 'horizontal'
- background_color: (0.1, 0.1, 0.1, 1)
- background_image: ''
- BoxLayout:
- size_hint: 1, 1
- height: '54dp'
- padding: '0dp', '0dp'
- spacing: '3dp'
- 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)
- def func(f=v):
- Clock.schedule_once(lambda dt: f(obj), 0.15)
- l.on_release = func
- self.ids.buttons.add_widget(l)
-
- def hide(self):
- if self.parent:
- self.parent.hide_menu()
diff --git a/electrum/gui/kivy/uix/dialogs/addresses.py b/electrum/gui/kivy/uix/dialogs/addresses.py
@@ -3,6 +3,9 @@ from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from decimal import Decimal
+from kivy.uix.popup import Popup
+
+from electrum.gui.kivy.i18n import _
Builder.load_string('''
<AddressLabel@Label>
@@ -95,11 +98,85 @@ Builder.load_string('''
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
+
+<AddressPopup@Popup>:
+ address: ''
+ balance: ''
+ status: ''
+ pk: ''
+ BoxLayout:
+ orientation: 'vertical'
+ ScrollView:
+ GridLayout:
+ cols: 1
+ height: self.minimum_height
+ size_hint_y: None
+ padding: '10dp'
+ spacing: '10dp'
+ GridLayout:
+ cols: 1
+ size_hint_y: None
+ height: self.minimum_height
+ spacing: '10dp'
+ BoxLabel:
+ text: _('Address')
+ value: root.address
+ BoxLabel:
+ text: _('Balance')
+ value: root.balance
+ BoxLabel:
+ text: _('Status')
+ value: root.status
+ TopLabel:
+ text: _('Private Key')
+ RefLabel:
+ id: pk_label
+ touched: True if not self.touched else True
+ data: root.pk
+ Widget:
+ size_hint: 1, 0.1
+ BoxLayout:
+ size_hint: 1, None
+ height: '48dp'
+ Button:
+ size_hint: 0.5, None
+ height: '48dp'
+ text: _('Hide key') if pk_label.data else _('Show key')
+ on_release:
+ setattr(pk_label, 'data', '') if pk_label.data else root.do_export(pk_label)
+ Button:
+ size_hint: 0.5, None
+ height: '48dp'
+ text: _('Use')
+ on_release: root.do_use()
+ Button:
+ size_hint: 0.5, None
+ height: '48dp'
+ text: _('Close')
+ on_release: root.dismiss()
''')
-from electrum.gui.kivy.i18n import _
-from electrum.gui.kivy.uix.context_menu import ContextMenu
+
+class AddressPopup(Popup):
+
+ def __init__(self, parent, address, balance, status, **kwargs):
+ super(AddressPopup, self).__init__(**kwargs)
+ self.title = _('Address')
+ self.parent_dialog = parent
+ self.app = parent.app
+ self.address = address
+ self.status = status
+ self.balance = self.app.format_amount_and_units(balance)
+
+ def do_use(self):
+ self.dismiss()
+ self.parent_dialog.dismiss()
+ self.app.switch_to('receive')
+ self.app.receive_screen.set_address(self.address)
+
+ def do_export(self, pk_label):
+ self.app.export_private_keys(pk_label, self.address)
class AddressesDialog(Factory.Popup):
@@ -107,7 +184,6 @@ class AddressesDialog(Factory.Popup):
def __init__(self, app):
Factory.Popup.__init__(self)
self.app = app
- self.context_menu = None
def get_card(self, addr, balance, is_used, label):
ci = {}
@@ -119,7 +195,6 @@ class AddressesDialog(Factory.Popup):
return ci
def update(self):
- self.menu_actions = [(_('Use'), self.do_use), (_('Details'), self.do_view)]
wallet = self.app.wallet
if self.show_change == 0:
_list = wallet.get_receiving_addresses()
@@ -150,30 +225,12 @@ class AddressesDialog(Factory.Popup):
if not n:
self.app.show_error('No address matching your search')
- def do_use(self, obj):
- self.hide_menu()
- self.dismiss()
- self.app.switch_to('receive')
- self.app.receive_screen.set_address(obj.address)
-
- def do_view(self, obj):
- req = { 'address': obj.address, 'status' : obj.status }
- status = obj.status
- c, u, x = self.app.wallet.get_addr_balance(obj.address)
+ def show_item(self, obj):
+ address = obj.address
+ c, u, x = self.app.wallet.get_addr_balance(address)
balance = c + u + x
- if balance > 0:
- req['fund'] = balance
- self.app.show_addr_details(req, status)
+ d = AddressPopup(self, address, balance, obj.status)
+ d.open()
def ext_search(self, card, search):
return card['memo'].find(search) >= 0 or card['amount'].find(search) >= 0
-
- 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/dialogs/invoices.py b/electrum/gui/kivy/uix/dialogs/invoices.py
@@ -1,169 +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
-
-Builder.load_string('''
-<InvoicesLabel@Label>
- #color: .305, .309, .309, 1
- text_size: self.width, None
- halign: 'left'
- valign: 'top'
-
-<InvoiceItem@CardItem>
- requestor: ''
- 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
- InvoicesLabel:
- text: root.requestor
- shorten: True
- Widget
- InvoicesLabel:
- text: root.memo
- color: .699, .699, .699, 1
- font_size: '13sp'
- shorten: True
- Widget
- BoxLayout:
- spacing: '8dp'
- height: '32dp'
- orientation: 'vertical'
- Widget
- InvoicesLabel:
- text: root.amount
- font_size: '15sp'
- halign: 'right'
- width: '110sp'
- Widget
- InvoicesLabel:
- text: root.status
- font_size: '13sp'
- halign: 'right'
- color: .699, .699, .699, 1
- Widget
-
-
-<InvoicesDialog@Popup>
- id: popup
- title: _('Invoices')
- BoxLayout:
- id: box
- orientation: 'vertical'
- spacing: '1dp'
- ScrollView:
- GridLayout:
- cols: 1
- id: invoices_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
-
-invoice_text = {
- PR_UNPAID:_('Pending'),
- PR_UNKNOWN:_('Unknown'),
- PR_PAID:_('Paid'),
- PR_EXPIRED:_('Expired')
-}
-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'
-}
-
-
-class InvoicesDialog(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, pr):
- key = pr.get_id()
- ci = self.cards.get(key)
- if ci is None:
- ci = Factory.InvoiceItem()
- ci.key = key
- ci.screen = self
- self.cards[key] = ci
- ci.requestor = pr.get_requestor()
- ci.memo = pr.get_memo()
- amount = pr.get_amount()
- if amount:
- ci.amount = self.app.format_amount_and_units(amount)
- status = self.app.wallet.invoices.get_status(ci.key)
- ci.status = invoice_text[status]
- ci.icon = pr_icon[status]
- else:
- ci.amount = _('No Amount')
- ci.status = ''
- exp = pr.get_expiration_date()
- ci.date = format_time(exp) if exp else _('Never')
- return ci
-
- def update(self):
- self.menu_actions = [('Pay', self.do_pay), ('Details', self.do_view), ('Delete', self.do_delete)]
- invoices_list = self.ids.invoices_container
- invoices_list.clear_widgets()
- _list = self.app.wallet.invoices.sorted_list()
- for pr in _list:
- ci = self.get_card(pr)
- invoices_list.add_widget(ci)
-
- def do_pay(self, obj):
- self.hide_menu()
- self.dismiss()
- pr = self.app.wallet.invoices.get(obj.key)
- self.app.on_pr(pr)
-
- def do_view(self, obj):
- pr = self.app.wallet.invoices.get(obj.key)
- pr.verify(self.app.wallet.contacts)
- self.app.show_pr_details(pr.get_dict(), obj.status, True)
-
- def do_delete(self, obj):
- from .question import Question
- def cb(result):
- if result:
- self.app.wallet.invoices.remove(obj.key)
- self.hide_menu()
- self.update()
- d = Question(_('Delete invoice?'), 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/dialogs/lightning_channels.py b/electrum/gui/kivy/uix/dialogs/lightning_channels.py
@@ -4,10 +4,10 @@ from kivy.lang import Builder
from kivy.factory import Factory
from kivy.uix.popup import Popup
from kivy.clock import Clock
-from electrum.gui.kivy.uix.context_menu import ContextMenu
from electrum.util import bh2u
from electrum.lnutil import LOCAL, REMOTE, format_short_channel_id
from electrum.gui.kivy.i18n import _
+from .question import Question
Builder.load_string(r'''
<LightningChannelItem@CardItem>
@@ -71,38 +71,11 @@ Builder.load_string(r'''
text: _('New channel...')
on_press: popup.app.popup_dialog('lightning_open_channel_dialog')
-<ChannelDetailsItem@BoxLayout>:
- canvas.before:
- Color:
- rgba: 0.5, 0.5, 0.5, 1
- Rectangle:
- size: self.size
- pos: self.pos
- value: ''
- Label:
- text: root.value
- text_size: self.size # this makes the text not overflow, but wrap
-
-<ChannelDetailsRow@BoxLayout>:
- keyName: ''
- value: ''
- ChannelDetailsItem:
- value: root.keyName
- size_hint_x: 0.5 # this makes the column narrower
-
- # see https://blog.kivy.org/2014/07/wrapping-text-in-kivys-label/
- ScrollView:
- Label:
- text: root.value
- size_hint_y: None
- text_size: self.width, None
- height: self.texture_size[1]
-
<ChannelDetailsList@RecycleView>:
scroll_type: ['bars', 'content']
scroll_wheel_distance: dp(114)
bar_width: dp(10)
- viewclass: 'ChannelDetailsRow'
+ viewclass: 'BoxLabel'
RecycleBoxLayout:
default_size: None, dp(56)
default_size_hint: 1, None
@@ -114,64 +87,102 @@ Builder.load_string(r'''
<ChannelDetailsPopup@Popup>:
id: popuproot
data: []
- ChannelDetailsList:
- data: popuproot.data
+ BoxLayout:
+ orientation: 'vertical'
+ ScrollView:
+ ChannelDetailsList:
+ data: popuproot.data
+ Widget:
+ size_hint: 1, 0.1
+ BoxLayout:
+ size_hint: 1, None
+ height: '48dp'
+ Button:
+ size_hint: 0.5, None
+ height: '48dp'
+ text: _('Close channel')
+ on_release: root.close()
+ Button:
+ size_hint: 0.5, None
+ height: '48dp'
+ text: _('Force-close')
+ on_release: root.force_close()
+ Button:
+ size_hint: 0.5, None
+ height: '48dp'
+ text: _('Dismiss')
+ on_release: root.dismiss()
''')
+
class ChannelDetailsPopup(Popup):
- def __init__(self, data, **kwargs):
- super(ChannelDetailsPopup,self).__init__(**kwargs)
- self.data = data
-class LightningChannelsDialog(Factory.Popup):
- def __init__(self, app):
- super(LightningChannelsDialog, self).__init__()
- self.clocks = []
+ def __init__(self, chan, app, **kwargs):
+ super(ChannelDetailsPopup,self).__init__(**kwargs)
self.app = app
- self.context_menu = None
- self.app.wallet.network.register_callback(self.on_channels, ['channels'])
- self.app.wallet.network.register_callback(self.on_channel, ['channel'])
- self.update()
-
- def show_channel_details(self, obj):
- p = Factory.ChannelDetailsPopup()
- p.title = _('Details for channel ') + format_short_channel_id(obj.chan.short_channel_id)
- p.data = [{'keyName': key, 'value': str(obj.details[key])} for key in obj.details.keys()]
- p.open()
-
- def close_channel(self, obj):
+ self.chan = chan
+ self.title = _('Channel details')
+ self.data = [{'text': key, 'value': str(value)} for key, value in self.details().items()]
+
+ def details(self):
+ chan = self.chan
+ return {
+ _('Short Chan ID'): format_short_channel_id(chan.short_channel_id),
+ _('Initiator'): 'Local' if chan.constraints.is_initiator else 'Remote',
+ _('State'): chan.get_state(),
+ _('Capacity'): self.app.format_amount_and_units(chan.constraints.capacity),
+ _('Can send'): self.app.format_amount_and_units(chan.available_to_spend(LOCAL) // 1000),
+ _('Current feerate'): str(chan.get_latest_feerate(LOCAL)),
+ _('Node ID'): bh2u(chan.node_id),
+ _('Channel ID'): bh2u(chan.channel_id),
+ _('Funding TXID'): chan.funding_outpoint.txid,
+ }
+
+ def close(self):
+ Question(_('Close channel?'), self._close).open()
+
+ def _close(self, b):
+ if not b:
+ return
loop = self.app.wallet.network.asyncio_loop
- coro = asyncio.run_coroutine_threadsafe(self.app.wallet.lnworker.close_channel(obj._chan.channel_id), loop)
+ coro = asyncio.run_coroutine_threadsafe(self.app.wallet.lnworker.close_channel(self._chan.channel_id), loop)
try:
coro.result(5)
self.app.show_info(_('Channel closed'))
except Exception as e:
self.app.show_info(_('Could not close channel: ') + repr(e)) # repr because str(Exception()) == ''
- def force_close_channel(self, obj):
- if obj._chan.get_state() == 'CLOSED':
+ def force_close(self):
+ Question(_('Force-close channel?'), self._force_close).open()
+
+ def _force_close(self, b):
+ if not b:
+ return
+ if self.chan.get_state() == 'CLOSED':
self.app.show_error(_('Channel already closed'))
return
loop = self.app.wallet.network.asyncio_loop
- coro = asyncio.run_coroutine_threadsafe(self.app.wallet.lnworker.force_close_channel(obj._chan.channel_id), loop)
+ coro = asyncio.run_coroutine_threadsafe(self.app.wallet.lnworker.force_close_channel(self.chan.channel_id), loop)
try:
coro.result(1)
- self.app.show_info(_('Channel closed, you may need to wait at least {} blocks, because of CSV delays'.format(obj._chan.config[REMOTE].to_self_delay)))
+ self.app.show_info(_('Channel closed, you may need to wait at least {} blocks, because of CSV delays'.format(self.chan.config[REMOTE].to_self_delay)))
except Exception as e:
self.app.show_info(_('Could not force close channel: ') + repr(e)) # repr because str(Exception()) == ''
- def show_menu(self, obj):
- self.hide_menu()
- self.context_menu = ContextMenu(obj, [
- (_("Force close"), self.force_close_channel),
- (_("Co-op close"), self.close_channel),
- (_("Details"), self.show_channel_details)])
- 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
+class LightningChannelsDialog(Factory.Popup):
+
+ def __init__(self, app):
+ super(LightningChannelsDialog, self).__init__()
+ self.clocks = []
+ self.app = app
+ self.app.wallet.network.register_callback(self.on_channels, ['channels'])
+ self.app.wallet.network.register_callback(self.on_channel, ['channel'])
+ self.update()
+
+ def show_item(self, obj):
+ p = ChannelDetailsPopup(obj._chan, self.app)
+ p.open()
def format_fields(self, chan):
labels = {}
@@ -213,18 +224,6 @@ class LightningChannelsDialog(Factory.Popup):
item = Factory.LightningChannelItem()
item.screen = self
item.active = i.node_id in lnworker.peers
- item.details = self.channel_details(i)
item._chan = i
self.update_item(item)
channel_cards.add_widget(item)
-
- def channel_details(self, chan):
- return {_('Node ID'): bh2u(chan.node_id),
- _('Channel ID'): bh2u(chan.channel_id),
- _('Capacity'): self.app.format_amount_and_units(chan.constraints.capacity),
- _('Funding TXID'): chan.funding_outpoint.txid,
- _('Short Chan ID'): bh2u(chan.short_channel_id) if chan.short_channel_id else _('Not available'),
- _('Available to spend'): self.app.format_amount_and_units(chan.available_to_spend(LOCAL) // 1000),
- _('State'): chan.get_state(),
- _('Initiator'): 'Opened/funded by us' if chan.constraints.is_initiator else 'Opened/funded by remote party',
- _('Current feerate'): chan.get_latest_feerate(LOCAL)}
diff --git a/electrum/gui/kivy/uix/dialogs/lightning_invoices.py b/electrum/gui/kivy/uix/dialogs/lightning_invoices.py
@@ -1,65 +0,0 @@
-from kivy.factory import Factory
-from kivy.lang import Builder
-from electrum.gui.kivy.i18n import _
-from kivy.uix.recycleview import RecycleView
-from electrum.gui.kivy.uix.context_menu import ContextMenu
-
-Builder.load_string('''
-<Item@CardItem>
- addr: ''
- desc: ''
- screen: None
- BoxLayout:
- orientation: 'vertical'
- Label
- text: root.addr
- text_size: self.width, None
- shorten: True
- Label
- text: root.desc if root.desc else _('No description')
- text_size: self.width, None
- shorten: True
- font_size: '10dp'
-
-<LightningInvoicesDialog@Popup>
- id: popup
- title: _('Lightning Invoices')
- BoxLayout:
- orientation: 'vertical'
- id: box
- RecycleView:
- viewclass: 'Item'
- id: recycleview
- data: []
- RecycleBoxLayout:
- default_size: None, dp(56)
- default_size_hint: 1, None
- size_hint_y: None
- height: self.minimum_height
- orientation: 'vertical'
-''')
-
-class LightningInvoicesDialog(Factory.Popup):
-
- def __init__(self, report, callback):
- super().__init__()
- self.context_menu = None
- self.callback = callback
- self.menu_actions = [(_('Show'), self.do_show)]
- for addr, preimage, pay_req in report['unsettled']:
- self.ids.recycleview.data.append({'screen': self, 'addr': pay_req, 'desc': dict(addr.tags).get('d', '')})
-
- def do_show(self, obj):
- self.hide_menu()
- self.dismiss()
- self.callback(obj.addr)
-
- 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/dialogs/request_dialog.py b/electrum/gui/kivy/uix/dialogs/request_dialog.py
@@ -42,30 +42,33 @@ Builder.load_string('''
Button:
size_hint: 1, None
height: '48dp'
- text: _('Copy')
- on_release:
- root.copy_to_clipboard()
+ text: _('Delete')
+ on_release: root.delete_dialog()
+ IconButton:
+ icon: 'atlas://electrum/gui/kivy/theming/light/copy'
+ size_hint: 0.5, None
+ height: '48dp'
+ on_release: root.copy_to_clipboard()
IconButton:
icon: 'atlas://electrum/gui/kivy/theming/light/share'
- size_hint: 0.6, None
+ size_hint: 0.5, None
height: '48dp'
- on_release: s.parent.do_share()
+ on_release: root.do_share()
Button:
size_hint: 1, None
height: '48dp'
text: _('Close')
- on_release:
- popup.dismiss()
+ on_release: popup.dismiss()
''')
class RequestDialog(Factory.Popup):
+
def __init__(self, title, data, key):
Factory.Popup.__init__(self)
self.app = App.get_running_app()
self.title = title
self.data = data
self.key = key
- #self.text_for_clipboard = text_for_clipboard if text_for_clipboard else data
def on_open(self):
self.ids.qr.set_data(self.data)
@@ -80,3 +83,17 @@ class RequestDialog(Factory.Popup):
Clipboard.copy(self.data)
msg = _('Text copied to clipboard.')
Clock.schedule_once(lambda dt: self.app.show_info(msg))
+
+ def do_share(self):
+ self.app.do_share(self.data, _("Share Bitcoin Request"))
+ self.dismiss()
+
+ def delete_dialog(self):
+ from .question import Question
+ def cb(result):
+ if result:
+ self.app.wallet.delete_request(self.key)
+ self.dismiss()
+ self.app.receive_screen.update()
+ d = Question(_('Delete request?'), cb)
+ d.open()
diff --git a/electrum/gui/kivy/uix/dialogs/tx_dialog.py b/electrum/gui/kivy/uix/dialogs/tx_dialog.py
@@ -101,6 +101,11 @@ Builder.load_string('''
Button:
size_hint: 0.5, None
height: '48dp'
+ text: _('Label')
+ on_release: root.label_dialog()
+ Button:
+ size_hint: 0.5, None
+ height: '48dp'
text: _('Close')
on_release: root.dismiss()
''')
@@ -271,3 +276,14 @@ class TxDialog(Factory.Popup):
self.dismiss()
d = Question(question, on_prompt)
d.open()
+
+ def label_dialog(self):
+ from .label_dialog import LabelDialog
+ key = self.tx.txid()
+ text = self.app.wallet.get_label(key)
+ def callback(text):
+ self.app.wallet.set_label(key, text)
+ self.update()
+ self.app.history_screen.update()
+ d = LabelDialog(_('Enter Transaction Label'), text, callback)
+ d.open()
diff --git a/electrum/gui/kivy/uix/screens.py b/electrum/gui/kivy/uix/screens.py
@@ -33,7 +33,6 @@ from electrum import simple_config
from electrum.lnaddr import lndecode
from electrum.lnutil import RECEIVED, SENT, PaymentFailure
-from .context_menu import ContextMenu
from .dialogs.question import Question
from .dialogs.lightning_open_channel import LightningOpenChannelDialog
@@ -55,8 +54,6 @@ class CScreen(Factory.Screen):
action_view = ObjectProperty(None)
loaded = False
kvname = None
- context_menu = None
- menu_actions = []
app = App.get_running_app()
def _change_action_view(self):
@@ -94,17 +91,7 @@ class CScreen(Factory.Screen):
self.dispatch('on_deactivate')
def on_deactivate(self):
- self.hide_menu()
-
- def hide_menu(self):
- if self.context_menu is not None:
- self.remove_widget(self.context_menu)
- self.context_menu = None
-
- def show_menu(self, obj):
- self.hide_menu()
- self.context_menu = ContextMenu(obj, self.menu_actions)
- self.add_widget(self.context_menu)
+ pass
# note: this list needs to be kept in sync with another in qt
@@ -130,24 +117,15 @@ class HistoryScreen(CScreen):
def __init__(self, **kwargs):
self.ra_dialog = None
super(HistoryScreen, self).__init__(**kwargs)
- self.menu_actions = [ ('Label', self.label_dialog), ('Details', self.show_tx)]
- def show_tx(self, obj):
+ def show_item(self, obj):
+ print(obj)
key = obj.key
tx = self.app.wallet.db.get_transaction(key)
if not tx:
return
self.app.tx_dialog(tx)
- def label_dialog(self, obj):
- from .dialogs.label_dialog import LabelDialog
- key = obj.key
- text = self.app.wallet.get_label(key)
- def callback(text):
- self.app.wallet.set_label(key, text)
- self.update()
- d = LabelDialog(_('Enter Transaction Label'), text, callback)
- d.open()
def get_card(self, tx_item): #tx_hash, tx_mined_status, value, balance):
is_lightning = tx_item.get('lightning', False)
@@ -406,7 +384,6 @@ class ReceiveScreen(CScreen):
def __init__(self, **kwargs):
super(ReceiveScreen, self).__init__(**kwargs)
- self.menu_actions = [(_('Show'), self.do_show), (_('Delete'), self.delete_request_dialog)]
Clock.schedule_interval(lambda dt: self.update(), 5)
def expiry(self):
@@ -440,10 +417,6 @@ class ReceiveScreen(CScreen):
amount = Decimal(a) * pow(10, self.app.decimal_point())
return create_bip21_uri(self.screen.address, amount, self.screen.message)
- def do_share(self):
- uri = self.get_URI()
- self.app.do_share(uri, _("Share Bitcoin Request"))
-
def do_copy(self):
uri = self.get_URI()
self.app._clipboard.copy(uri)
@@ -498,8 +471,7 @@ class ReceiveScreen(CScreen):
requests_container = self.screen.ids.requests_container
requests_container.data = [self.get_card(item) for item in _list if item.get('status') != PR_PAID]
- def do_show(self, obj):
- self.hide_menu()
+ def show_item(self, obj):
self.app.show_request(obj.is_lightning, obj.key)
def expiration_dialog(self, obj):
@@ -523,24 +495,7 @@ class ReceiveScreen(CScreen):
d = Question(_('Delete expired requests?'), callback)
d.open()
- def delete_request_dialog(self, req):
- def cb(result):
- if result:
- self.app.wallet.delete_request(req.key)
- 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/invoice.kv b/electrum/gui/kivy/uix/ui_screens/invoice.kv
@@ -1,89 +0,0 @@
-#:import Decimal decimal.Decimal
-
-
-
-Popup:
- id: popup
- is_invoice: True
- amount: 0
- requestor: ''
- exp: ''
- description: ''
- status: ''
- signature: ''
- isaddr: ''
- fund: 0
- pk: ''
- title: _('Invoice') if popup.is_invoice else _('Request')
- tx_hash: ''
- BoxLayout:
- orientation: 'vertical'
- ScrollView:
- GridLayout:
- cols: 1
- height: self.minimum_height
- size_hint_y: None
- padding: '10dp'
- spacing: '10dp'
- GridLayout:
- cols: 1
- size_hint_y: None
- height: self.minimum_height
- spacing: '10dp'
- BoxLabel:
- text: (_('Status') if popup.amount or popup.is_invoice or popup.isaddr == 'y' else _('Amount received')) if root.status else ''
- value: root.status
- BoxLabel:
- text: _('Request amount') if root.amount else ''
- value: app.format_amount_and_units(root.amount) if root.amount else ''
- BoxLabel:
- text: _('Requestor') if popup.is_invoice else _('Address')
- value: root.requestor
- BoxLabel:
- text: _('Signature') if root.signature else ''
- value: root.signature
- BoxLabel:
- text: _('Expiration') if root.exp else ''
- value: root.exp
- BoxLabel:
- text: _('Description') if root.description else ''
- value: root.description
- BoxLabel:
- text: _('Balance') if popup.fund else ''
- value: app.format_amount_and_units(root.fund) if root.fund else ''
- TopLabel:
- text: _('Private Key')
- RefLabel:
- id: pk_label
- touched: True if not self.touched else True
- data: root.pk
-
- TopLabel:
- text: _('Outputs') if popup.is_invoice else ''
- OutputList:
- id: output_list
- TopLabel:
- text: _('Transaction ID') if popup.tx_hash else ''
- TxHashLabel:
- data: popup.tx_hash
- name: _('Transaction ID')
- Widget:
- size_hint: 1, 0.1
-
- BoxLayout:
- size_hint: 1, None
- height: '48dp'
- Widget:
- size_hint: 0.5, None
- height: '48dp'
- Button:
- size_hint: 2, None
- height: '48dp'
- text: _('Close')
- on_release: popup.dismiss()
- Button:
- size_hint: 2, None
- height: '48dp'
- text: _('Hide private key') if pk_label.data else _('Export private key')
- on_release:
- setattr(pk_label, 'data', '') if pk_label.data else popup.export(pk_label, popup.requestor)