Browse Source

qml: add expiry timers to update status string in InvoiceDialog and ReceiveDialog

master
Sander van Grieken 3 years ago
parent
commit
995754e523
  1. 11
      electrum/gui/qml/components/ReceiveDialog.qml
  2. 28
      electrum/gui/qml/qeinvoice.py
  3. 37
      electrum/gui/qml/qerequestdetails.py
  4. 20
      electrum/gui/qml/util.py

11
electrum/gui/qml/components/ReceiveDialog.qml

@ -207,10 +207,17 @@ ElDialog {
GridLayout { GridLayout {
columns: 2 columns: 2
visible: request.message || !request.amount.isEmpty // visible: request.message || !request.amount.isEmpty
Layout.maximumWidth: buttons.width Layout.maximumWidth: buttons.width
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Label {
text: qsTr('Status')
color: Material.accentColor
}
Label {
text: request.status_str
}
Label { Label {
visible: request.message visible: request.message
text: qsTr('Message') text: qsTr('Message')
@ -234,7 +241,7 @@ ElDialog {
} }
Rectangle { Rectangle {
visible: request.message || !request.amount.isEmpty // visible: request.message || !request.amount.isEmpty
height: 1 height: 1
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.preferredWidth: buttons.width Layout.preferredWidth: buttons.width

28
electrum/gui/qml/qeinvoice.py

@ -2,14 +2,14 @@ import threading
import asyncio import asyncio
from urllib.parse import urlparse from urllib.parse import urlparse
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Q_ENUMS from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Q_ENUMS, QTimer
from electrum import bitcoin from electrum import bitcoin
from electrum import lnutil from electrum import lnutil
from electrum.i18n import _ from electrum.i18n import _
from electrum.invoices import Invoice from electrum.invoices import Invoice
from electrum.invoices import (PR_UNPAID, PR_EXPIRED, PR_UNKNOWN, PR_PAID, PR_INFLIGHT, from electrum.invoices import (PR_UNPAID, PR_EXPIRED, PR_UNKNOWN, PR_PAID, PR_INFLIGHT,
PR_FAILED, PR_ROUTING, PR_UNCONFIRMED) PR_FAILED, PR_ROUTING, PR_UNCONFIRMED, LN_EXPIRY_NEVER)
from electrum.lnaddr import LnInvoiceException from electrum.lnaddr import LnInvoiceException
from electrum.logging import get_logger from electrum.logging import get_logger
from electrum.transaction import PartialTxOutput from electrum.transaction import PartialTxOutput
@ -20,6 +20,7 @@ from electrum.bitcoin import COIN
from .qetypes import QEAmount from .qetypes import QEAmount
from .qewallet import QEWallet from .qewallet import QEWallet
from .util import status_update_timer_interval
class QEInvoice(QObject): class QEInvoice(QObject):
class Type: class Type:
@ -140,6 +141,10 @@ class QEInvoiceParser(QEInvoice):
self._amount = QEAmount() self._amount = QEAmount()
self._userinfo = '' self._userinfo = ''
self._timer = QTimer(self)
self._timer.setSingleShot(True)
self._timer.timeout.connect(self.updateStatusString)
self.clear() self.clear()
@pyqtProperty(int, notify=invoiceChanged) @pyqtProperty(int, notify=invoiceChanged)
@ -190,6 +195,10 @@ class QEInvoiceParser(QEInvoice):
self.determine_can_pay() self.determine_can_pay()
self.invoiceChanged.emit() self.invoiceChanged.emit()
@pyqtProperty('quint64', notify=invoiceChanged)
def time(self):
return self._effectiveInvoice.time if self._effectiveInvoice else 0
@pyqtProperty('quint64', notify=invoiceChanged) @pyqtProperty('quint64', notify=invoiceChanged)
def expiration(self): def expiration(self):
return self._effectiveInvoice.exp if self._effectiveInvoice else 0 return self._effectiveInvoice.exp if self._effectiveInvoice else 0
@ -268,6 +277,21 @@ class QEInvoiceParser(QEInvoice):
self.invoiceChanged.emit() self.invoiceChanged.emit()
self.statusChanged.emit() self.statusChanged.emit()
self.set_status_timer()
def set_status_timer(self):
if self.status != PR_EXPIRED:
if self.expiration > 0 and self.expiration != LN_EXPIRY_NEVER:
interval = status_update_timer_interval(self.time + self.expiration)
if interval > 0:
self._timer.setInterval(interval) # msec
self._timer.start()
@pyqtSlot()
def updateStatusString(self):
self.statusChanged.emit()
self.set_status_timer()
def determine_can_pay(self): def determine_can_pay(self):
self.canPay = False self.canPay = False
self.userinfo = '' self.userinfo = ''

37
electrum/gui/qml/qerequestdetails.py

@ -1,5 +1,3 @@
from time import time
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer, Q_ENUMS from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer, Q_ENUMS
from electrum.logging import get_logger from electrum.logging import get_logger
@ -8,7 +6,7 @@ from electrum.invoices import (PR_UNPAID, PR_EXPIRED, PR_UNKNOWN, PR_PAID, PR_IN
from .qewallet import QEWallet from .qewallet import QEWallet
from .qetypes import QEAmount from .qetypes import QEAmount
from .util import QtEventListener, event_listener from .util import QtEventListener, event_listener, status_update_timer_interval
class QERequestDetails(QObject, QtEventListener): class QERequestDetails(QObject, QtEventListener):
@ -38,6 +36,10 @@ class QERequestDetails(QObject, QtEventListener):
self._timer = None self._timer = None
self._amount = None self._amount = None
self._timer = QTimer(self)
self._timer.setSingleShot(True)
self._timer.timeout.connect(self.updateStatusString)
self.register_callbacks() self.register_callbacks()
self.destroyed.connect(lambda: self.on_destroy()) self.destroyed.connect(lambda: self.on_destroy())
@ -134,31 +136,16 @@ class QERequestDetails(QObject, QtEventListener):
self._amount = QEAmount(from_invoice=self._req) self._amount = QEAmount(from_invoice=self._req)
self.detailsChanged.emit() self.detailsChanged.emit()
self.initStatusStringTimer() self.statusChanged.emit()
self.set_status_timer()
def initStatusStringTimer(self): def set_status_timer(self):
if self.status == PR_UNPAID: if self.status == PR_UNPAID:
if self.expiration > 0 and self.expiration != LN_EXPIRY_NEVER: if self.expiration > 0 and self.expiration != LN_EXPIRY_NEVER:
self._timer = QTimer(self) self._logger.debug(f'set_status_timer, expiration={self.expiration}')
self._timer.setSingleShot(True) interval = status_update_timer_interval(self.expiration)
self._timer.timeout.connect(self.updateStatusString)
# very roughly according to util.time_difference
exp_in = int(self.expiration - time())
exp_in_min = int(exp_in/60)
interval = 0
if exp_in < 0:
interval = 0
if exp_in_min < 2:
interval = 1000
elif exp_in_min < 90:
interval = 1000 * 60
elif exp_in_min < 1440:
interval = 1000 * 60 * 60
if interval > 0: if interval > 0:
self._logger.debug(f'setting status update timer to {interval}, req expires in {exp_in} seconds') self._logger.debug(f'setting status update timer to {interval}')
self._timer.setInterval(interval) # msec self._timer.setInterval(interval) # msec
self._timer.start() self._timer.start()
@ -166,5 +153,5 @@ class QERequestDetails(QObject, QtEventListener):
@pyqtSlot() @pyqtSlot()
def updateStatusString(self): def updateStatusString(self):
self.statusChanged.emit() self.statusChanged.emit()
self.initStatusStringTimer() self.set_status_timer()

20
electrum/gui/qml/util.py

@ -1,4 +1,5 @@
from functools import wraps from functools import wraps
from time import time
from PyQt5.QtCore import pyqtSignal from PyQt5.QtCore import pyqtSignal
@ -27,3 +28,22 @@ def qt_event_listener(func):
def decorator(self, *args): def decorator(self, *args):
self.qt_callback_signal.emit( (func,) + args) self.qt_callback_signal.emit( (func,) + args)
return decorator return decorator
# return delay in msec when expiry time string should be updated
# returns 0 when expired or expires > 1 day away (no updates needed)
def status_update_timer_interval(exp):
# very roughly according to util.time_difference
exp_in = int(exp - time())
exp_in_min = int(exp_in/60)
interval = 0
if exp_in < 0:
interval = 0
elif exp_in_min < 2:
interval = 1000
elif exp_in_min < 90:
interval = 1000 * 60
elif exp_in_min < 1440:
interval = 1000 * 60 * 60
return interval

Loading…
Cancel
Save