Browse Source

auto-remove paid invoices from GUI

- delay 3 seconds in GUI
 - kivy remove 'delete' buttons from send/receive screens
patch-4
ThomasV 4 years ago
parent
commit
a2122a8c19
  1. 14
      electrum/gui/kivy/main_window.py
  2. 55
      electrum/gui/kivy/uix/screens.py
  3. 5
      electrum/gui/kivy/uix/ui_screens/receive.kv
  4. 4
      electrum/gui/kivy/uix/ui_screens/send.kv
  5. 2
      electrum/gui/qt/invoice_list.py
  6. 16
      electrum/gui/qt/main_window.py
  7. 17
      electrum/gui/qt/request_list.py
  8. 11
      electrum/wallet.py

14
electrum/gui/kivy/main_window.py

@ -242,9 +242,12 @@ class ElectrumWindow(App, Logger):
self._trigger_update_history()
def on_request_status(self, event, wallet, key, status):
if key not in self.wallet.receive_requests:
req = self.wallet.receive_requests.get(key)
if req is None:
return
self.update_tab('receive')
if self.receive_screen:
self.receive_screen.update_item(key, req)
Clock.schedule_once(lambda dt: self.receive_screen.update(), 3)
if self.request_popup and self.request_popup.key == key:
self.request_popup.update_status()
if status == PR_PAID:
@ -255,9 +258,10 @@ class ElectrumWindow(App, Logger):
req = self.wallet.get_invoice(key)
if req is None:
return
status = self.wallet.get_invoice_status(req)
# todo: update single item
self.update_tab('send')
if self.send_screen:
self.send_screen.update_item(key, req)
Clock.schedule_once(lambda dt: self.send_screen.update(), 3)
if self.invoice_popup and self.invoice_popup.key == key:
self.invoice_popup.update_status()

55
electrum/gui/kivy/uix/screens.py

@ -218,11 +218,23 @@ class SendScreen(CScreen, Logger):
def update(self):
if self.app.wallet is None:
return
_list = self.app.wallet.get_invoices()
_list = self.app.wallet.get_unpaid_invoices()
_list.reverse()
payments_container = self.ids.payments_container
payments_container.data = [self.get_card(item) for item in _list]
def update_item(self, key, invoice):
payments_container = self.ids.payments_container
data = payments_container.data
for item in data:
if item['key'] == key:
status = self.app.wallet.get_invoice_status(invoice)
status_str = invoice.get_status_str(status)
item['status'] = status
item['status_str'] = status_str
payments_container.data = data
payments_container.refresh_from_data()
def show_item(self, obj):
self.app.show_invoice(obj.is_lightning, obj.key)
@ -421,20 +433,6 @@ class SendScreen(CScreen, Logger):
else:
self.app.tx_dialog(tx)
def clear_invoices_dialog(self):
invoices = self.app.wallet.get_invoices()
if not invoices:
return
def callback(c):
if c:
for req in invoices:
key = req.rhash if req.is_lightning() else req.get_address()
self.app.wallet.delete_invoice(key)
self.update()
n = len(invoices)
d = Question(_('Delete {} invoices?').format(n), callback)
d.open()
class ReceiveScreen(CScreen):
@ -531,11 +529,23 @@ class ReceiveScreen(CScreen):
def update(self):
if self.app.wallet is None:
return
_list = self.app.wallet.get_sorted_requests()
_list = self.app.wallet.get_unpaid_requests()
_list.reverse()
requests_container = self.ids.requests_container
requests_container.data = [self.get_card(item) for item in _list]
def update_item(self, key, request):
payments_container = self.ids.requests_container
data = payments_container.data
for item in data:
if item['key'] == key:
status = self.app.wallet.get_request_status(key)
status_str = request.get_status_str(status)
item['status'] = status
item['status_str'] = status_str
payments_container.data = data # needed?
payments_container.refresh_from_data()
def show_item(self, obj):
self.app.show_request(obj.is_lightning, obj.key)
@ -546,19 +556,6 @@ class ReceiveScreen(CScreen):
d = ChoiceDialog(_('Expiration date'), pr_expiration_values, self.expiry(), callback)
d.open()
def clear_requests_dialog(self):
requests = self.app.wallet.get_sorted_requests()
if not requests:
return
def callback(c):
if c:
self.app.wallet.clear_requests()
self.update()
n = len(requests)
d = Question(_('Delete {} requests?').format(n), callback)
d.open()
class TabbedCarousel(Factory.TabbedPanel):
'''Custom TabbedPanel using a carousel used in the Main Screen

5
electrum/gui/kivy/uix/ui_screens/receive.kv

@ -134,11 +134,6 @@
BoxLayout:
size_hint: 1, None
height: '48dp'
IconButton:
icon: f'atlas://{KIVY_GUI_PATH}/theming/light/delete'
size_hint: 0.5, None
height: '48dp'
on_release: Clock.schedule_once(lambda dt: s.clear_requests_dialog())
IconButton:
icon: f'atlas://{KIVY_GUI_PATH}/theming/light/clock1'
size_hint: 0.5, None

4
electrum/gui/kivy/uix/ui_screens/send.kv

@ -150,10 +150,6 @@
BoxLayout:
size_hint: 1, None
height: '48dp'
IconButton:
icon: f'atlas://{KIVY_GUI_PATH}/theming/light/delete'
size_hint: 0.5, 1
on_release: Clock.schedule_once(lambda dt: s.clear_invoices_dialog())
IconButton:
size_hint: 0.5, 1
on_release: s.do_save()

2
electrum/gui/qt/invoice_list.py

@ -98,7 +98,7 @@ class InvoiceList(MyTreeView):
self.proxy.setDynamicSortFilter(False) # temp. disable re-sorting after every change
self.std_model.clear()
self.update_headers(self.__class__.headers)
for idx, item in enumerate(self.parent.wallet.get_invoices()):
for idx, item in enumerate(self.parent.wallet.get_unpaid_invoices()):
if item.is_lightning():
key = item.rhash
icon_name = 'lightning.png'

16
electrum/gui/qt/main_window.py

@ -40,6 +40,7 @@ from typing import Optional, TYPE_CHECKING, Sequence, List, Union
from PyQt5.QtGui import QPixmap, QKeySequence, QIcon, QCursor, QFont
from PyQt5.QtCore import Qt, QRect, QStringListModel, QSize, pyqtSignal
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import (QMessageBox, QComboBox, QSystemTrayIcon, QTabWidget,
QMenuBar, QFileDialog, QCheckBox, QLabel,
QVBoxLayout, QGridLayout, QLineEdit,
@ -1516,8 +1517,16 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
def on_request_status(self, wallet, key, status):
if wallet != self.wallet:
return
if key not in self.wallet.receive_requests:
req = self.wallet.receive_requests.get(key)
if req is None:
return
# update item
self.request_list.update_item(key, req)
# update list later
self.timer = QTimer()
self.timer.timeout.connect(self.request_list.update)
self.timer.start(3000)
if status == PR_PAID:
self.notify(_('Payment received') + '\n' + key)
self.need_update.set()
@ -1528,7 +1537,12 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
req = self.wallet.get_invoice(key)
if req is None:
return
# update item
self.invoice_list.update_item(key, req)
# update list later.
self.timer = QTimer()
self.timer.timeout.connect(self.invoice_list.update)
self.timer.start(3000)
def on_payment_succeeded(self, wallet, key):
description = self.wallet.get_label(key)

17
electrum/gui/qt/request_list.py

@ -34,6 +34,7 @@ from electrum.i18n import _
from electrum.util import format_time
from electrum.invoices import PR_TYPE_ONCHAIN, PR_TYPE_LN, LNInvoice, OnchainInvoice
from electrum.plugin import run_hook
from electrum.invoices import Invoice
from .util import MyTreeView, pr_icons, read_QIcon, webopen, MySortModel
@ -126,13 +127,27 @@ class RequestList(MyTreeView):
status_item.setText(status_str)
status_item.setIcon(read_QIcon(pr_icons.get(status)))
def update_item(self, key, invoice: Invoice):
model = self.std_model
for row in range(0, model.rowCount()):
item = model.item(row, 0)
if item.data(ROLE_KEY) == key:
break
else:
return
status_item = model.item(row, self.Columns.STATUS)
status = self.parent.wallet.get_request_status(key)
status_str = invoice.get_status_str(status)
status_item.setText(status_str)
status_item.setIcon(read_QIcon(pr_icons.get(status)))
def update(self):
# not calling maybe_defer_update() as it interferes with conditional-visibility
self.parent.update_receive_address_styling()
self.proxy.setDynamicSortFilter(False) # temp. disable re-sorting after every change
self.std_model.clear()
self.update_headers(self.__class__.headers)
for req in self.wallet.get_sorted_requests():
for req in self.wallet.get_unpaid_requests():
if req.is_lightning():
assert isinstance(req, LNInvoice)
key = req.rhash

11
electrum/wallet.py

@ -761,10 +761,13 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
def get_invoices(self):
out = list(self.invoices.values())
#out = list(filter(None, out)) filter out ln
out.sort(key=lambda x:x.time)
return out
def get_unpaid_invoices(self):
invoices = self.get_invoices()
return [x for x in invoices if self.get_invoice_status(x) != PR_PAID]
def get_invoice(self, key):
return self.invoices.get(key)
@ -2035,6 +2038,12 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
out.sort(key=lambda x: x.time)
return out
def get_unpaid_requests(self):
out = [self.get_request(x) for x in self.receive_requests.keys() if self.get_request_status(x) != PR_PAID]
out = [x for x in out if x is not None]
out.sort(key=lambda x: x.time)
return out
@abstractmethod
def get_fingerprint(self) -> str:
"""Returns a string that can be used to identify this wallet.

Loading…
Cancel
Save