From 7ef52c66258aa5d0c055d0c75f4c3f0a76dc4b32 Mon Sep 17 00:00:00 2001 From: Sander van Grieken Date: Thu, 2 Jun 2022 12:00:06 +0200 Subject: [PATCH] listmodels self-initialize, lazy-load listmodels in QEWallet, process channel updates in qechannellistmodel --- electrum/gui/qml/components/Addresses.qml | 1 - electrum/gui/qml/components/Channels.qml | 1 - electrum/gui/qml/qeaddresslistmodel.py | 4 +- electrum/gui/qml/qechannellistmodel.py | 43 +++++++++++++++++++++- electrum/gui/qml/qeinvoicelistmodel.py | 2 +- electrum/gui/qml/qetransactionlistmodel.py | 2 +- electrum/gui/qml/qewallet.py | 23 ++++++++---- 7 files changed, 59 insertions(+), 17 deletions(-) diff --git a/electrum/gui/qml/components/Addresses.qml b/electrum/gui/qml/components/Addresses.qml index c4d249da4..daef18775 100644 --- a/electrum/gui/qml/components/Addresses.qml +++ b/electrum/gui/qml/components/Addresses.qml @@ -169,5 +169,4 @@ Pane { } } - Component.onCompleted: Daemon.currentWallet.addressModel.init_model() } diff --git a/electrum/gui/qml/components/Channels.qml b/electrum/gui/qml/components/Channels.qml index f4a88547f..ada4c4693 100644 --- a/electrum/gui/qml/components/Channels.qml +++ b/electrum/gui/qml/components/Channels.qml @@ -102,5 +102,4 @@ Pane { } - Component.onCompleted: Daemon.currentWallet.channelModel.init_model() } diff --git a/electrum/gui/qml/qeaddresslistmodel.py b/electrum/gui/qml/qeaddresslistmodel.py index eb042b8f2..e0d9dceab 100644 --- a/electrum/gui/qml/qeaddresslistmodel.py +++ b/electrum/gui/qml/qeaddresslistmodel.py @@ -10,9 +10,7 @@ class QEAddressListModel(QAbstractListModel): def __init__(self, wallet, parent=None): super().__init__(parent) self.wallet = wallet - self.receive_addresses = [] - self.change_addresses = [] - + self.init_model() _logger = get_logger(__name__) diff --git a/electrum/gui/qml/qechannellistmodel.py b/electrum/gui/qml/qechannellistmodel.py index 27910378c..8d6e266b2 100644 --- a/electrum/gui/qml/qechannellistmodel.py +++ b/electrum/gui/qml/qechannellistmodel.py @@ -4,7 +4,7 @@ from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex from electrum.logging import get_logger -from electrum.util import Satoshis, TxMinedInfo +from electrum.util import Satoshis, register_callback from .qetypes import QEAmount @@ -12,7 +12,16 @@ class QEChannelListModel(QAbstractListModel): def __init__(self, wallet, parent=None): super().__init__(parent) self.wallet = wallet - self.channels = [] + self.init_model() + + interests = ['channel', 'channels_updated', 'gossip_peers', + 'ln_gossip_sync_progress', 'unknown_channels', + 'channel_db', 'gossip_db_loaded'] + # To avoid leaking references to "self" that prevent the + # window from being GC-ed when closed, callbacks should be + # methods of this class only, and specifically not be + # partials, lambdas or methods of subobjects. Hence... + register_callback(self.on_network, interests) _logger = get_logger(__name__) @@ -48,6 +57,7 @@ class QEChannelListModel(QAbstractListModel): def channel_to_model(self, lnc): lnworker = self.wallet.lnworker item = {} + item['channel_id'] = lnc.channel_id item['node_alias'] = lnworker.get_node_alias(lnc.node_id) or lnc.node_id.hex() item['short_cid'] = lnc.short_id_for_GUI() item['state'] = lnc.get_state_for_GUI() @@ -57,6 +67,7 @@ class QEChannelListModel(QAbstractListModel): @pyqtSlot() def init_model(self): + self._logger.debug('init_model') if not self.wallet.lnworker: self._logger.warning('lnworker should be defined') return @@ -73,3 +84,31 @@ class QEChannelListModel(QAbstractListModel): self.beginInsertRows(QModelIndex(), 0, len(channels) - 1) self.channels = channels self.endInsertRows() + + def on_network(self, event, *args): + if event == 'channel': + wallet, channel = args + if wallet == self.wallet: + self.on_channel_updated(channel) + elif event == 'channels_updated': + wallet, = args + if wallet == self.wallet: + self.init_model() # TODO: remove/add less crude than full re-init + else: + self._logger.debug('unhandled event %s: %s' % (event, repr(args))) + + def on_channel_updated(self, channel): + i = 0 + for c in self.channels: + if c['channel_id'] == channel.channel_id: + self.do_update(i,channel) + break + i = i + 1 + + def do_update(self, modelindex, channel): + modelitem = self.channels[modelindex] + self._logger.debug(repr(modelitem)) + modelitem.update(self.channel_to_model(channel)) + + mi = self.createIndex(modelindex, 0) + self.dataChanged.emit(mi, mi, self._ROLE_KEYS) diff --git a/electrum/gui/qml/qeinvoicelistmodel.py b/electrum/gui/qml/qeinvoicelistmodel.py index 91eec07ad..ef041c96b 100644 --- a/electrum/gui/qml/qeinvoicelistmodel.py +++ b/electrum/gui/qml/qeinvoicelistmodel.py @@ -15,7 +15,7 @@ class QEAbstractInvoiceListModel(QAbstractListModel): def __init__(self, wallet, parent=None): super().__init__(parent) self.wallet = wallet - self.invoices = [] + self.init_model() # define listmodel rolemap _ROLE_NAMES=('key','is_lightning','timestamp','date','message','amount','status','status_str','address','expiration','type') diff --git a/electrum/gui/qml/qetransactionlistmodel.py b/electrum/gui/qml/qetransactionlistmodel.py index 85574fce2..8d8fb0e92 100644 --- a/electrum/gui/qml/qetransactionlistmodel.py +++ b/electrum/gui/qml/qetransactionlistmodel.py @@ -12,7 +12,7 @@ class QETransactionListModel(QAbstractListModel): def __init__(self, wallet, parent=None): super().__init__(parent) self.wallet = wallet - self.tx_history = [] + self.init_model() _logger = get_logger(__name__) diff --git a/electrum/gui/qml/qewallet.py b/electrum/gui/qml/qewallet.py index 08c9bc8b7..3e08b7a25 100644 --- a/electrum/gui/qml/qewallet.py +++ b/electrum/gui/qml/qewallet.py @@ -57,16 +57,12 @@ class QEWallet(QObject): super().__init__(parent) self.wallet = wallet - self._historyModel = QETransactionListModel(wallet) - self._addressModel = QEAddressListModel(wallet) - self._requestModel = QERequestListModel(wallet) - self._invoiceModel = QEInvoiceListModel(wallet) + self._historyModel = None + self._addressModel = None + self._requestModel = None + self._invoiceModel = None self._channelModel = None - self._historyModel.init_model() - self._requestModel.init_model() - self._invoiceModel.init_model() - self.tx_notification_queue = queue.Queue() self.tx_notification_last_time = 0 @@ -125,6 +121,9 @@ class QEWallet(QObject): if wallet == self.wallet: self._logger.debug('wallet %s updated' % str(wallet)) self.balanceChanged.emit() + elif event in ['channel','channels_updated']: + # TODO update balance/can-spend etc + pass else: self._logger.debug('unhandled event: %s %s' % (event, str(args))) @@ -177,21 +176,29 @@ class QEWallet(QObject): historyModelChanged = pyqtSignal() @pyqtProperty(QETransactionListModel, notify=historyModelChanged) def historyModel(self): + if self._historyModel is None: + self._historyModel = QETransactionListModel(self.wallet) return self._historyModel addressModelChanged = pyqtSignal() @pyqtProperty(QEAddressListModel, notify=addressModelChanged) def addressModel(self): + if self._addressModel is None: + self._addressModel = QEAddressListModel(self.wallet) return self._addressModel requestModelChanged = pyqtSignal() @pyqtProperty(QERequestListModel, notify=requestModelChanged) def requestModel(self): + if self._requestModel is None: + self._requestModel = QERequestListModel(self.wallet) return self._requestModel invoiceModelChanged = pyqtSignal() @pyqtProperty(QEInvoiceListModel, notify=invoiceModelChanged) def invoiceModel(self): + if self._invoiceModel is None: + self._invoiceModel = QEInvoiceListModel(self.wallet) return self._invoiceModel channelModelChanged = pyqtSignal()