11 changed files with 208 additions and 603 deletions
@ -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() |
|
@ -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 |
|
@ -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 |
|
@ -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) |
|
Loading…
Reference in new issue