diff --git a/electrum/gui/qml/__init__.py b/electrum/gui/qml/__init__.py index 15c389a5c..1957e2aa2 100644 --- a/electrum/gui/qml/__init__.py +++ b/electrum/gui/qml/__init__.py @@ -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) diff --git a/electrum/gui/qml/qeapp.py b/electrum/gui/qml/qeapp.py index 927870f1c..bb8587824 100644 --- a/electrum/gui/qml/qeapp.py +++ b/electrum/gui/qml/qeapp.py @@ -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) diff --git a/electrum/gui/qml/qedaemon.py b/electrum/gui/qml/qedaemon.py index 7f7c57b9d..d1e236ad4 100644 --- a/electrum/gui/qml/qedaemon.py +++ b/electrum/gui/qml/qedaemon.py @@ -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) diff --git a/electrum/gui/qml/qenetwork.py b/electrum/gui/qml/qenetwork.py index 204966d89..25dc1c24f 100644 --- a/electrum/gui/qml/qenetwork.py +++ b/electrum/gui/qml/qenetwork.py @@ -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) diff --git a/electrum/plugins/trustedcoin/qml.py b/electrum/plugins/trustedcoin/qml.py index 1d970ccb3..aa93a1d91 100644 --- a/electrum/plugins/trustedcoin/qml.py +++ b/electrum/plugins/trustedcoin/qml.py @@ -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,