refactor to new event listener framework
This commit is contained in:
@@ -5,14 +5,14 @@ from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Q_ENUMS
|
||||
from electrum.i18n import _
|
||||
from electrum.gui import messages
|
||||
from electrum.logging import get_logger
|
||||
from electrum.util import register_callback, unregister_callback
|
||||
from electrum.lnutil import LOCAL, REMOTE
|
||||
from electrum.lnchannel import ChanCloseOption
|
||||
|
||||
from .qewallet import QEWallet
|
||||
from .qetypes import QEAmount
|
||||
from .util import QtEventListener, qt_event_listener
|
||||
|
||||
class QEChannelDetails(QObject):
|
||||
class QEChannelDetails(QObject, QtEventListener):
|
||||
|
||||
_logger = get_logger(__name__)
|
||||
_wallet = None
|
||||
@@ -25,17 +25,16 @@ class QEChannelDetails(QObject):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
register_callback(self.on_network, ['channel'])
|
||||
self.register_callbacks()
|
||||
self.destroyed.connect(lambda: self.on_destroy())
|
||||
|
||||
def on_network(self, event, *args):
|
||||
if event == 'channel':
|
||||
wallet, channel = args
|
||||
if wallet == self._wallet.wallet and self._channelid == channel.channel_id.hex():
|
||||
self.channelChanged.emit()
|
||||
@qt_event_listener
|
||||
def on_event_channel(self, wallet, channel):
|
||||
if wallet == self._wallet.wallet and self._channelid == channel.channel_id.hex():
|
||||
self.channelChanged.emit()
|
||||
|
||||
def on_destroy(self):
|
||||
unregister_callback(self.on_network)
|
||||
self.unregister_callbacks()
|
||||
|
||||
walletChanged = pyqtSignal()
|
||||
@pyqtProperty(QEWallet, notify=walletChanged)
|
||||
|
||||
@@ -4,13 +4,14 @@ 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, register_callback, unregister_callback
|
||||
from electrum.util import Satoshis
|
||||
from electrum.lnutil import LOCAL, REMOTE
|
||||
from electrum.lnchannel import ChannelState
|
||||
|
||||
from .qetypes import QEAmount
|
||||
from .util import QtEventListener, qt_event_listener
|
||||
|
||||
class QEChannelListModel(QAbstractListModel):
|
||||
class QEChannelListModel(QAbstractListModel, QtEventListener):
|
||||
_logger = get_logger(__name__)
|
||||
|
||||
# define listmodel rolemap
|
||||
@@ -28,38 +29,26 @@ class QEChannelListModel(QAbstractListModel):
|
||||
self.wallet = wallet
|
||||
self.init_model()
|
||||
|
||||
self._network_signal.connect(self.on_network_qt)
|
||||
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)
|
||||
self.register_callbacks()
|
||||
self.destroyed.connect(lambda: self.on_destroy())
|
||||
|
||||
def on_network(self, event, *args):
|
||||
if event in ['channel','channels_updated']:
|
||||
# Handle in GUI thread (_network_signal -> on_network_qt)
|
||||
self._network_signal.emit(event, args)
|
||||
else:
|
||||
self.on_network_qt(event, args)
|
||||
@qt_event_listener
|
||||
def on_event_channel(self, wallet, channel):
|
||||
if wallet == self.wallet:
|
||||
self.on_channel_updated(channel)
|
||||
|
||||
def on_network_qt(self, event, args=None):
|
||||
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)))
|
||||
# elif event == 'channels_updated':
|
||||
@qt_event_listener
|
||||
def on_event_channels_updated(self, wallet):
|
||||
if wallet == self.wallet:
|
||||
self.init_model() # TODO: remove/add less crude than full re-init
|
||||
|
||||
def on_destroy(self):
|
||||
unregister_callback(self.on_network)
|
||||
self.unregister_callbacks()
|
||||
|
||||
def rowCount(self, index):
|
||||
return len(self.channels)
|
||||
|
||||
@@ -6,7 +6,7 @@ from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
|
||||
|
||||
from electrum.util import register_callback, get_new_wallet_name, WalletFileException
|
||||
from electrum.logging import get_logger
|
||||
from electrum.wallet import Wallet, Abstract_Wallet, update_password_for_directory
|
||||
from electrum.wallet import Wallet, Abstract_Wallet
|
||||
from electrum.storage import WalletStorage, StorageReadWriteError
|
||||
from electrum.wallet_db import WalletDB
|
||||
|
||||
@@ -147,7 +147,7 @@ class QEDaemon(AuthMixin, QObject):
|
||||
self.walletLoaded.emit()
|
||||
|
||||
if self.daemon.config.get('single_password'):
|
||||
self._use_single_password = update_password_for_directory(self.daemon.config, password, password)
|
||||
self._use_single_password = self.daemon.update_password_for_directory(old_password=password, new_password=password)
|
||||
self._password = password
|
||||
self._logger.info(f'use single password: {self._use_single_password}')
|
||||
|
||||
|
||||
@@ -6,28 +6,34 @@ from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||
from electrum.logging import get_logger
|
||||
from electrum.exchange_rate import FxThread
|
||||
from electrum.simple_config import SimpleConfig
|
||||
from electrum.util import register_callback
|
||||
from electrum.bitcoin import COIN
|
||||
|
||||
from .qetypes import QEAmount
|
||||
from .util import QtEventListener, qt_event_listener
|
||||
|
||||
class QEFX(QObject):
|
||||
class QEFX(QObject, QtEventListener):
|
||||
def __init__(self, fxthread: FxThread, config: SimpleConfig, parent=None):
|
||||
super().__init__(parent)
|
||||
self.fx = fxthread
|
||||
self.config = config
|
||||
register_callback(self.on_quotes, ['on_quotes'])
|
||||
register_callback(self.on_history, ['on_history'])
|
||||
self.register_callbacks()
|
||||
self.destroyed.connect(lambda: self.on_destroy())
|
||||
|
||||
_logger = get_logger(__name__)
|
||||
|
||||
quotesUpdated = pyqtSignal()
|
||||
def on_quotes(self, event, *args):
|
||||
|
||||
def on_destroy(self):
|
||||
self.unregister_callbacks()
|
||||
|
||||
@qt_event_listener
|
||||
def on_event_on_quotes(self, *args):
|
||||
self._logger.debug('new quotes')
|
||||
self.quotesUpdated.emit()
|
||||
|
||||
historyUpdated = pyqtSignal()
|
||||
def on_history(self, event, *args):
|
||||
@qt_event_listener
|
||||
def on_event_on_history(self, *args):
|
||||
self._logger.debug('new history')
|
||||
self.historyUpdated.emit()
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Q_ENUMS
|
||||
from electrum.logging import get_logger
|
||||
from electrum.i18n import _
|
||||
from electrum.util import (parse_URI, create_bip21_uri, InvalidBitcoinURI, InvoiceError,
|
||||
maybe_extract_bolt11_invoice)
|
||||
maybe_extract_lightning_payment_identifier)
|
||||
from electrum.invoices import Invoice
|
||||
from electrum.invoices import (PR_UNPAID,PR_EXPIRED,PR_UNKNOWN,PR_PAID,PR_INFLIGHT,
|
||||
PR_FAILED,PR_ROUTING,PR_UNCONFIRMED,LN_EXPIRY_NEVER)
|
||||
@@ -335,7 +335,7 @@ class QEInvoiceParser(QEInvoice):
|
||||
|
||||
lninvoice = None
|
||||
try:
|
||||
maybe_lightning_invoice = maybe_extract_bolt11_invoice(maybe_lightning_invoice)
|
||||
maybe_lightning_invoice = maybe_extract_lightning_payment_identifier(maybe_lightning_invoice)
|
||||
lninvoice = Invoice.from_bech32(maybe_lightning_invoice)
|
||||
except InvoiceError as e:
|
||||
pass
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||
|
||||
from electrum.util import register_callback
|
||||
from electrum.logging import get_logger
|
||||
from electrum import constants
|
||||
from electrum.interface import ServerAddr
|
||||
|
||||
class QENetwork(QObject):
|
||||
from .util import QtEventListener, qt_event_listener
|
||||
|
||||
class QENetwork(QObject, QtEventListener):
|
||||
def __init__(self, network, parent=None):
|
||||
super().__init__(parent)
|
||||
self.network = network
|
||||
register_callback(self.on_network_updated, ['network_updated'])
|
||||
register_callback(self.on_blockchain_updated, ['blockchain_updated'])
|
||||
register_callback(self.on_default_server_changed, ['default_server_changed'])
|
||||
register_callback(self.on_proxy_set, ['proxy_set'])
|
||||
register_callback(self.on_status, ['status'])
|
||||
register_callback(self.on_fee_histogram, ['fee_histogram'])
|
||||
self.register_callbacks()
|
||||
|
||||
_logger = get_logger(__name__)
|
||||
|
||||
@@ -33,30 +29,36 @@ class QENetwork(QObject):
|
||||
_height = 0
|
||||
_status = ""
|
||||
|
||||
def on_network_updated(self, event, *args):
|
||||
@qt_event_listener
|
||||
def on_event_network_updated(self, *args):
|
||||
self.networkUpdated.emit()
|
||||
|
||||
def on_blockchain_updated(self, event, *args):
|
||||
@qt_event_listener
|
||||
def on_event_blockchain_updated(self, *args):
|
||||
if self._height != self.network.get_local_height():
|
||||
self._height = self.network.get_local_height()
|
||||
self._logger.debug('new height: %d' % self._height)
|
||||
self.heightChanged.emit(self._height)
|
||||
self.blockchainUpdated.emit()
|
||||
|
||||
def on_default_server_changed(self, event, *args):
|
||||
@qt_event_listener
|
||||
def on_event_default_server_changed(self, *args):
|
||||
self.defaultServerChanged.emit()
|
||||
|
||||
def on_proxy_set(self, event, *args):
|
||||
@qt_event_listener
|
||||
def on_event_proxy_set(self, *args):
|
||||
self._logger.debug('proxy set')
|
||||
self.proxySet.emit()
|
||||
|
||||
def on_status(self, event, *args):
|
||||
@qt_event_listener
|
||||
def on_event_status(self, *args):
|
||||
self._logger.debug('status updated: %s' % self.network.connection_status)
|
||||
if self._status != self.network.connection_status:
|
||||
self._status = self.network.connection_status
|
||||
self.statusChanged.emit()
|
||||
|
||||
def on_fee_histogram(self, event, *args):
|
||||
@qt_event_listener
|
||||
def on_event_fee_histogram(self, *args):
|
||||
self._logger.debug('fee histogram updated')
|
||||
self.feeHistogramUpdated.emit()
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import threading
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl, QTimer
|
||||
|
||||
from electrum.i18n import _
|
||||
from electrum.util import (register_callback, unregister_callback,
|
||||
Satoshis, format_time, parse_max_spend, InvalidPassword)
|
||||
from electrum.util import (Satoshis, format_time, parse_max_spend, InvalidPassword,
|
||||
event_listener)
|
||||
from electrum.logging import get_logger
|
||||
from electrum.wallet import Wallet, Abstract_Wallet
|
||||
from electrum.storage import StorageEncryptionVersion
|
||||
@@ -24,8 +24,9 @@ from .qeaddresslistmodel import QEAddressListModel
|
||||
from .qechannellistmodel import QEChannelListModel
|
||||
from .qetypes import QEAmount
|
||||
from .auth import AuthMixin, auth_protect
|
||||
from .util import QtEventListener, qt_event_listener
|
||||
|
||||
class QEWallet(AuthMixin, QObject):
|
||||
class QEWallet(AuthMixin, QObject, QtEventListener):
|
||||
__instances = []
|
||||
|
||||
# this factory method should be used to instantiate QEWallet
|
||||
@@ -79,7 +80,7 @@ class QEWallet(AuthMixin, QObject):
|
||||
self.notification_timer.setInterval(500) # msec
|
||||
self.notification_timer.timeout.connect(self.notify_transactions)
|
||||
|
||||
self._network_signal.connect(self.on_network_qt)
|
||||
#self._network_signal.connect(self.on_network_qt)
|
||||
interests = ['wallet_updated', 'new_transaction', 'status', 'verified',
|
||||
'on_history', 'channel', 'channels_updated', 'payment_failed',
|
||||
'payment_succeeded', 'invoice_status', 'request_status']
|
||||
@@ -87,7 +88,8 @@ class QEWallet(AuthMixin, QObject):
|
||||
# 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)
|
||||
#register_callback(self.on_network, interests)
|
||||
self.register_callbacks()
|
||||
self.destroyed.connect(lambda: self.on_destroy())
|
||||
|
||||
@pyqtProperty(bool, notify=isUptodateChanged)
|
||||
@@ -108,60 +110,93 @@ class QEWallet(AuthMixin, QObject):
|
||||
wallet = args[0]
|
||||
if wallet == self.wallet:
|
||||
self._logger.debug('event %s' % event)
|
||||
if event == 'status':
|
||||
|
||||
@event_listener
|
||||
def on_event_status(self, *args, **kwargs):
|
||||
#if event == 'status':
|
||||
self.isUptodateChanged.emit()
|
||||
elif event == 'request_status':
|
||||
wallet, key, status = args
|
||||
if wallet == self.wallet:
|
||||
self._logger.debug('request status %d for key %s' % (status, key))
|
||||
self.requestStatusChanged.emit(key, status)
|
||||
elif event == 'invoice_status':
|
||||
wallet, key = args
|
||||
if wallet == self.wallet:
|
||||
self._logger.debug('invoice status update for key %s' % key)
|
||||
# FIXME event doesn't pass the new status, so we need to retrieve
|
||||
invoice = self.wallet.get_invoice(key)
|
||||
if invoice:
|
||||
status = self.wallet.get_invoice_status(invoice)
|
||||
self.invoiceStatusChanged.emit(key, status)
|
||||
else:
|
||||
self._logger.debug(f'No invoice found for key {key}')
|
||||
elif event == 'new_transaction':
|
||||
wallet, tx = args
|
||||
if wallet == self.wallet:
|
||||
self.add_tx_notification(tx)
|
||||
self.historyModel.init_model() # TODO: be less dramatic
|
||||
elif event == 'verified':
|
||||
wallet, txid, info = args
|
||||
if wallet == self.wallet:
|
||||
self.historyModel.update_tx(txid, info)
|
||||
elif event == 'wallet_updated':
|
||||
wallet, = args
|
||||
if wallet == self.wallet:
|
||||
self._logger.debug('wallet %s updated' % str(wallet))
|
||||
self.balanceChanged.emit()
|
||||
elif event == 'channel':
|
||||
wallet, channel = args
|
||||
|
||||
|
||||
# elif event == 'request_status':
|
||||
@event_listener
|
||||
def on_event_request_status(self, wallet, key, status):
|
||||
#wallet, key, status = args
|
||||
if wallet == self.wallet:
|
||||
self._logger.debug('request status %d for key %s' % (status, key))
|
||||
self.requestStatusChanged.emit(key, status)
|
||||
# elif event == 'invoice_status':
|
||||
@event_listener
|
||||
def on_event_invoice_status(self, wallet, key):
|
||||
#wallet, key = args
|
||||
if wallet == self.wallet:
|
||||
self._logger.debug('invoice status update for key %s' % key)
|
||||
# FIXME event doesn't pass the new status, so we need to retrieve
|
||||
invoice = self.wallet.get_invoice(key)
|
||||
if invoice:
|
||||
status = self.wallet.get_invoice_status(invoice)
|
||||
self.invoiceStatusChanged.emit(key, status)
|
||||
else:
|
||||
self._logger.debug(f'No invoice found for key {key}')
|
||||
|
||||
#elif event == 'new_transaction':
|
||||
@qt_event_listener
|
||||
def on_event_new_transaction(self, *args):
|
||||
wallet, tx = args
|
||||
if wallet == self.wallet:
|
||||
self.add_tx_notification(tx)
|
||||
self.historyModel.init_model() # TODO: be less dramatic
|
||||
|
||||
|
||||
# elif event == 'verified':
|
||||
@qt_event_listener
|
||||
def on_event_verified(self, wallet, txid, info):
|
||||
#wallet, txid, info = args
|
||||
if wallet == self.wallet:
|
||||
self.historyModel.update_tx(txid, info)
|
||||
|
||||
|
||||
# elif event == 'wallet_updated':
|
||||
@event_listener
|
||||
def on_event_wallet_updated(self, wallet):
|
||||
#wallet, = args
|
||||
if wallet == self.wallet:
|
||||
self._logger.debug('wallet %s updated' % str(wallet))
|
||||
self.balanceChanged.emit()
|
||||
|
||||
# elif event == 'channel':
|
||||
@event_listener
|
||||
def on_event_channel(self, wallet, channel):
|
||||
#wallet, channel = args
|
||||
if wallet == self.wallet:
|
||||
self.balanceChanged.emit()
|
||||
elif event == 'channels_updated':
|
||||
wallet, = args
|
||||
if wallet == self.wallet:
|
||||
self.balanceChanged.emit()
|
||||
elif event == 'payment_succeeded':
|
||||
wallet, key = args
|
||||
if wallet == self.wallet:
|
||||
self.paymentSucceeded.emit(key)
|
||||
self.historyModel.init_model() # TODO: be less dramatic
|
||||
elif event == 'payment_failed':
|
||||
wallet, key, reason = args
|
||||
if wallet == self.wallet:
|
||||
self.paymentFailed.emit(key, reason)
|
||||
else:
|
||||
self._logger.debug('unhandled event: %s %s' % (event, str(args)))
|
||||
|
||||
# elif event == 'channels_updated':
|
||||
@event_listener
|
||||
def on_event_channels_updated(self, wallet):
|
||||
#wallet, = args
|
||||
if wallet == self.wallet:
|
||||
self.balanceChanged.emit()
|
||||
# elif event == 'payment_succeeded':
|
||||
|
||||
@qt_event_listener
|
||||
def on_event_payment_succeeded(self, wallet, key):
|
||||
#wallet, key = args
|
||||
if wallet == self.wallet:
|
||||
self.paymentSucceeded.emit(key)
|
||||
self.historyModel.init_model() # TODO: be less dramatic
|
||||
|
||||
# elif event == 'payment_failed':
|
||||
@event_listener
|
||||
def on_event_payment_failed(self, wallet, key, reason):
|
||||
#wallet, key, reason = args
|
||||
if wallet == self.wallet:
|
||||
self.paymentFailed.emit(key, reason)
|
||||
#else:
|
||||
#self._logger.debug('unhandled event: %s %s' % (event, str(args)))
|
||||
|
||||
def on_destroy(self):
|
||||
unregister_callback(self.on_network)
|
||||
#unregister_callback(self.on_network)
|
||||
self.unregister_callbacks()
|
||||
|
||||
def add_tx_notification(self, tx):
|
||||
self._logger.debug('new transaction event')
|
||||
|
||||
31
electrum/gui/qml/util.py
Normal file
31
electrum/gui/qml/util.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from functools import wraps
|
||||
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
||||
|
||||
from electrum.logging import get_logger
|
||||
from electrum.i18n import _
|
||||
from electrum.util import EventListener, event_listener
|
||||
|
||||
class QtEventListener(EventListener):
|
||||
|
||||
qt_callback_signal = pyqtSignal(tuple)
|
||||
|
||||
def register_callbacks(self):
|
||||
self.qt_callback_signal.connect(self.on_qt_callback_signal)
|
||||
EventListener.register_callbacks(self)
|
||||
|
||||
def unregister_callbacks(self):
|
||||
#self.qt_callback_signal.disconnect()
|
||||
EventListener.unregister_callbacks(self)
|
||||
|
||||
def on_qt_callback_signal(self, args):
|
||||
func = args[0]
|
||||
return func(self, *args[1:])
|
||||
|
||||
# decorator for members of the QtEventListener class
|
||||
def qt_event_listener(func):
|
||||
func = event_listener(func)
|
||||
@wraps(func)
|
||||
def decorator(self, *args):
|
||||
self.qt_callback_signal.emit( (func,) + args)
|
||||
return decorator
|
||||
Reference in New Issue
Block a user