1
0

Merge pull request #9720 from accumulator/qml_singletons

qml: simplify QEConfig and QEDaemon use.
This commit is contained in:
accumulator
2025-04-10 10:23:29 +02:00
committed by GitHub
5 changed files with 36 additions and 34 deletions

View File

@@ -82,7 +82,7 @@ class ElectrumGui(BaseElectrumGui, Logger):
self.timer.timeout.connect(lambda: None) # periodically enter python scope
# hook for crash reporter
Exception_Hook.maybe_setup(config=config, slot=self.app.appController.crash)
Exception_Hook.maybe_setup(slot=self.app.appController.crash)
# Initialize any QML plugins
run_hook('init_qml', self.app)

View File

@@ -75,14 +75,13 @@ class QEAppController(BaseCrashReporter, QObject):
secureWindowChanged = pyqtSignal()
wantCloseChanged = pyqtSignal()
def __init__(self, qeapp: 'ElectrumQmlApplication', qedaemon: 'QEDaemon', plugins: 'Plugins'):
def __init__(self, qeapp: 'ElectrumQmlApplication', plugins: 'Plugins'):
BaseCrashReporter.__init__(self, None, None, None)
QObject.__init__(self)
self._app = qeapp
self._qedaemon = qedaemon
self._plugins = plugins
self.config = qedaemon.daemon.config
self.config = QEConfig.instance.config
self._crash_user_text = ''
self._app_started = False
@@ -101,7 +100,7 @@ class QEAppController(BaseCrashReporter, QObject):
self.notification_timer.setInterval(500) # msec
self.notification_timer.timeout.connect(self.on_notification_timer)
self._qedaemon.walletLoaded.connect(self.on_wallet_loaded)
QEDaemon.instance.walletLoaded.connect(self.on_wallet_loaded)
self.userNotify.connect(self.doNotify)
@@ -111,12 +110,12 @@ class QEAppController(BaseCrashReporter, QObject):
self._want_close = False
def on_wallet_loaded(self):
qewallet = self._qedaemon.currentWallet
qewallet = QEDaemon.instance.currentWallet
if not qewallet:
return
# register wallet in Exception_Hook
Exception_Hook.maybe_setup(config=qewallet.wallet.config, wallet=qewallet.wallet)
Exception_Hook.maybe_setup(wallet=qewallet.wallet)
# attach to the wallet user notification events
# connect only once
@@ -344,8 +343,8 @@ class QEAppController(BaseCrashReporter, QObject):
'reportstring': self.get_report_string()
}
@pyqtSlot(object, object, object, object)
def crash(self, config, e, text, tb):
@pyqtSlot(object, object, object)
def crash(self, e, text, tb):
self.exc_args = (e, text, tb) # for BaseCrashReporter
self.showException.emit(self.crashData())
@@ -423,8 +422,6 @@ class ElectrumQmlApplication(QGuiApplication):
self.logger = get_logger(__name__)
ElectrumQmlApplication._daemon = daemon
# TODO QT6 order of declaration is important now?
qmlRegisterType(QEAmount, 'org.electrum', 1, 0, 'Amount')
qmlRegisterType(QENewWalletWizard, 'org.electrum', 1, 0, 'QNewWalletWizard')
@@ -479,17 +476,17 @@ class ElectrumQmlApplication(QGuiApplication):
self.context = self.engine.rootContext()
self.plugins = plugins
self._qeconfig = QEConfig(config)
self._qenetwork = QENetwork(daemon.network, self._qeconfig)
self.config = QEConfig(config)
self.network = QENetwork(daemon.network)
self.daemon = QEDaemon(daemon, self.plugins)
self.appController = QEAppController(self, self.daemon, self.plugins)
self._maxAmount = QEAmount(is_max=True)
self.appController = QEAppController(self, self.plugins)
self.maxAmount = QEAmount(is_max=True)
self.context.setContextProperty('AppController', self.appController)
self.context.setContextProperty('Config', self._qeconfig)
self.context.setContextProperty('Network', self._qenetwork)
self.context.setContextProperty('Config', self.config)
self.context.setContextProperty('Network', self.network)
self.context.setContextProperty('Daemon', self.daemon)
self.context.setContextProperty('FixedFont', self.fixedFont)
self.context.setContextProperty('MAX', self._maxAmount)
self.context.setContextProperty('MAX', self.maxAmount)
self.context.setContextProperty('QRIP', self.qr_ip_h)
self.context.setContextProperty('BUILD', {
'electrum_version': version.ELECTRUM_VERSION,
@@ -527,33 +524,33 @@ class ElectrumQmlApplication(QGuiApplication):
class Exception_Hook(QObject, Logger):
_report_exception = pyqtSignal(object, object, object, object)
_report_exception = pyqtSignal(object, object, object)
_INSTANCE = None # type: Optional[Exception_Hook] # singleton
def __init__(self, *, config: 'SimpleConfig', slot):
def __init__(self, *, slot):
QObject.__init__(self)
Logger.__init__(self)
assert self._INSTANCE is None, "Exception_Hook is supposed to be a singleton"
self.config = config
self.wallet_types_seen = set() # type: Set[str]
sys.excepthook = self.handler
threading.excepthook = self.handler
self._report_exception.connect(slot)
if slot:
self._report_exception.connect(slot)
EarlyExceptionsQueue.set_hook_as_ready()
@classmethod
def maybe_setup(cls, *, config: 'SimpleConfig', wallet: 'Abstract_Wallet' = None, slot = None) -> None:
if not config.SHOW_CRASH_REPORTER:
def maybe_setup(cls, *, wallet: 'Abstract_Wallet' = None, slot=None) -> None:
if not QEConfig.instance.config.SHOW_CRASH_REPORTER:
EarlyExceptionsQueue.set_hook_as_ready() # flush already queued exceptions
return
if not cls._INSTANCE:
cls._INSTANCE = Exception_Hook(config=config, slot=slot)
cls._INSTANCE = Exception_Hook(slot=slot)
if wallet:
cls._INSTANCE.wallet_types_seen.add(wallet.wallet_type)
def handler(self, *exc_info):
self.logger.error('exception caught by crash reporter', exc_info=exc_info)
self._report_exception.emit(self.config, *exc_info)
self._report_exception.emit(*exc_info)

View File

@@ -121,6 +121,8 @@ class QEWalletListModel(QAbstractListModel):
class QEDaemon(AuthMixin, QObject):
instance = None # type: Optional[QEDaemon]
_logger = get_logger(__name__)
_available_wallets = None
@@ -149,6 +151,9 @@ class QEDaemon(AuthMixin, QObject):
def __init__(self, daemon: 'Daemon', plugins: 'Plugins', parent=None):
super().__init__(parent)
if QEDaemon.instance:
raise RuntimeError('There should only be one QEDaemon instance')
QEDaemon.instance = self
self.daemon = daemon
self.plugins = plugins
self.qefx = QEFX(daemon.fx, daemon.config)

View File

@@ -9,10 +9,10 @@ from electrum.interface import ServerAddr
from electrum.fee_policy import FEERATE_DEFAULT_RELAY
from .util import QtEventListener, event_listener
from .qeconfig import QEConfig
from .qeserverlistmodel import QEServerListModel
if TYPE_CHECKING:
from .qeconfig import QEConfig
from electrum.network import Network
@@ -49,18 +49,17 @@ class QENetwork(QObject, QtEventListener):
_gossipDbChannels = 0
_gossipDbPolicies = 0
def __init__(self, network: 'Network', qeconfig: 'QEConfig', parent=None):
def __init__(self, network: 'Network', parent=None):
super().__init__(parent)
assert network, "--offline is not yet implemented for this GUI" # TODO
self.network = network
self._qeconfig = qeconfig
self._serverListModel = None
self._height = network.get_local_height() # init here, update event can take a while
self._server_height = network.get_server_height() # init here, update event can take a while
self.register_callbacks()
self.destroyed.connect(lambda: self.on_destroy())
self._qeconfig.useGossipChanged.connect(self.on_gossip_setting_changed)
QEConfig.instance.useGossipChanged.connect(self.on_gossip_setting_changed)
def on_destroy(self):
self.unregister_callbacks()
@@ -172,7 +171,7 @@ class QENetwork(QObject, QtEventListener):
def on_gossip_setting_changed(self):
if not self.network:
return
if self._qeconfig.useGossip:
if QEConfig.instance.useGossip:
self.network.start_gossip()
else:
self.network.run_from_another_thread(self.network.stop_gossip())
@@ -198,7 +197,7 @@ class QENetwork(QObject, QtEventListener):
raise Exception('failed to parse')
except Exception:
return
net_params = net_params._replace(server=server, auto_connect=self._qeconfig.autoConnect)
net_params = net_params._replace(server=server, auto_connect=QEConfig.instance.autoConnect)
self.network.run_from_another_thread(self.network.set_parameters(net_params))
@pyqtProperty(str, notify=statusChanged)

View File

@@ -5,8 +5,9 @@ from electrum.plugin import hook
from electrum.util import UserFacingException
from electrum.gui.qml.qewallet import QEWallet
from .common_qt import TrustedcoinPluginQObject
from electrum.gui.qml.qedaemon import QEDaemon
from .common_qt import TrustedcoinPluginQObject
from .trustedcoin import TrustedCoinPlugin, TrustedCoinException
if TYPE_CHECKING:
@@ -44,7 +45,7 @@ class Plugin(TrustedCoinPlugin):
def init_qml(self, app: 'ElectrumQmlApplication'):
self.logger.debug(f'init_qml hook called, gui={str(type(app))}')
self._app = app
wizard = self._app.daemon.newWalletWizard
wizard = QEDaemon.instance.newWalletWizard
# important: TrustedcoinPluginQObject needs to be parented, as keeping a ref
# in the plugin is not enough to avoid gc
# Note: storing the trustedcoin qt helper in the plugin is different from the desktop client,