commit a2122a8c19579a2dc3d91f0d41633c9d4d129988
parent 90abfda12bf78ce13332ab0474dcade418a211b1
Author: ThomasV <thomasv@electrum.org>
Date: Sun, 6 Dec 2020 10:58:04 +0100
auto-remove paid invoices from GUI
- delay 3 seconds in GUI
- kivy remove 'delete' buttons from send/receive screens
Diffstat:
8 files changed, 77 insertions(+), 47 deletions(-)
diff --git a/electrum/gui/kivy/main_window.py b/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()
diff --git a/electrum/gui/kivy/uix/screens.py b/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
diff --git a/electrum/gui/kivy/uix/ui_screens/receive.kv b/electrum/gui/kivy/uix/ui_screens/receive.kv
@@ -135,11 +135,6 @@
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
height: '48dp'
diff --git a/electrum/gui/kivy/uix/ui_screens/send.kv b/electrum/gui/kivy/uix/ui_screens/send.kv
@@ -151,10 +151,6 @@
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()
icon: f'atlas://{KIVY_GUI_PATH}/theming/light/save'
diff --git a/electrum/gui/qt/invoice_list.py b/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'
diff --git a/electrum/gui/qt/main_window.py b/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)
diff --git a/electrum/gui/qt/request_list.py b/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
diff --git a/electrum/wallet.py b/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.