Browse Source

qml: initial async wallet load

master
Sander van Grieken 3 years ago
parent
commit
a56c9687c8
  1. 39
      electrum/gui/qml/qedaemon.py
  2. 18
      electrum/gui/qml/qewallet.py

39
electrum/gui/qml/qedaemon.py

@ -1,4 +1,5 @@
import os import os
import threading
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
@ -118,12 +119,14 @@ class QEDaemon(AuthMixin, QObject):
_use_single_password = False _use_single_password = False
_password = None _password = None
_backendWalletLoaded = pyqtSignal([str], arguments=['password'])
availableWalletsChanged = pyqtSignal() availableWalletsChanged = pyqtSignal()
fxChanged = pyqtSignal() fxChanged = pyqtSignal()
newWalletWizardChanged = pyqtSignal() newWalletWizardChanged = pyqtSignal()
serverConnectWizardChanged = pyqtSignal() serverConnectWizardChanged = pyqtSignal()
walletLoaded = pyqtSignal() walletLoaded = pyqtSignal([str,str], arguments=['name','path'])
walletRequiresPassword = pyqtSignal([str,str], arguments=['name','path']) walletRequiresPassword = pyqtSignal([str,str], arguments=['name','path'])
walletOpenError = pyqtSignal([str], arguments=["error"]) walletOpenError = pyqtSignal([str], arguments=["error"])
walletDeleteError = pyqtSignal([str,str], arguments=['code', 'message']) walletDeleteError = pyqtSignal([str,str], arguments=['code', 'message'])
@ -132,6 +135,9 @@ class QEDaemon(AuthMixin, QObject):
super().__init__(parent) super().__init__(parent)
self.daemon = daemon self.daemon = daemon
self.qefx = QEFX(daemon.fx, daemon.config) self.qefx = QEFX(daemon.fx, daemon.config)
self._backendWalletLoaded.connect(self._on_backend_wallet_loaded)
self._walletdb = QEWalletDB() self._walletdb = QEWalletDB()
self._walletdb.validPasswordChanged.connect(self.passwordValidityCheck) self._walletdb.validPasswordChanged.connect(self.passwordValidityCheck)
@ -171,14 +177,14 @@ class QEDaemon(AuthMixin, QObject):
if not self._walletdb.ready: if not self._walletdb.ready:
return return
def load_wallet_task():
try: try:
wallet = self.daemon.load_wallet(self._path, password) wallet = self.daemon.load_wallet(self._path, password)
if wallet is not None:
self._current_wallet = QEWallet.getInstanceFor(wallet) if wallet is None:
if not wallet_already_open: self._logger.info('could not open wallet')
self.availableWallets.updateWallet(self._path) self.walletOpenError.emit('could not open wallet')
self._current_wallet.password = password return
self.walletLoaded.emit()
if self.daemon.config.get('single_password'): if self.daemon.config.get('single_password'):
self._use_single_password = self.daemon.update_password_for_directory(old_password=password, new_password=password) self._use_single_password = self.daemon.update_password_for_directory(old_password=password, new_password=password)
@ -189,14 +195,27 @@ class QEDaemon(AuthMixin, QObject):
self._logger.info('use single password disabled by config') self._logger.info('use single password disabled by config')
self.daemon.config.save_last_wallet(wallet) self.daemon.config.save_last_wallet(wallet)
run_hook('load_wallet', wallet) run_hook('load_wallet', wallet)
else:
self._logger.info('could not open wallet') self._backendWalletLoaded.emit(password)
self.walletOpenError.emit('could not open wallet')
except WalletFileException as e: except WalletFileException as e:
self._logger.error(str(e)) self._logger.error(str(e))
self.walletOpenError.emit(str(e)) self.walletOpenError.emit(str(e))
threading.Thread(target=load_wallet_task).start()
@pyqtSlot()
@pyqtSlot(str)
def _on_backend_wallet_loaded(self, password = None):
self._logger.debug('_on_backend_wallet_loaded')
wallet = self.daemon._wallets[self._path]
self._current_wallet = QEWallet.getInstanceFor(wallet)
self.availableWallets.updateWallet(self._path)
self._current_wallet.password = password
self.walletLoaded.emit(self._name, self._path)
@pyqtSlot(QEWallet) @pyqtSlot(QEWallet)
@pyqtSlot(QEWallet, bool) @pyqtSlot(QEWallet, bool)
@pyqtSlot(QEWallet, bool, bool) @pyqtSlot(QEWallet, bool, bool)

18
electrum/gui/qml/qewallet.py

@ -5,7 +5,7 @@ import time
from typing import TYPE_CHECKING, Optional, Tuple from typing import TYPE_CHECKING, Optional, Tuple
from functools import partial from functools import partial
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer, QMetaObject, Qt
from electrum import bitcoin from electrum import bitcoin
from electrum.i18n import _ from electrum.i18n import _
@ -113,6 +113,9 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
self.sync_progress_timer.setInterval(2000) self.sync_progress_timer.setInterval(2000)
self.sync_progress_timer.timeout.connect(self.update_sync_progress) self.sync_progress_timer.timeout.connect(self.update_sync_progress)
# post-construction init in GUI thread
# QMetaObject.invokeMethod(self, 'qt_init', Qt.QueuedConnection)
# To avoid leaking references to "self" that prevent the # To avoid leaking references to "self" that prevent the
# window from being GC-ed when closed, callbacks should be # window from being GC-ed when closed, callbacks should be
# methods of this class only, and specifically not be # methods of this class only, and specifically not be
@ -123,6 +126,19 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
self.synchronizing = True # start in sync state self.synchronizing = True # start in sync state
# @pyqtSlot()
# def qt_init(self):
# self.notification_timer = QTimer(self)
# self.notification_timer.setSingleShot(False)
# self.notification_timer.setInterval(500) # msec
# self.notification_timer.timeout.connect(self.notify_transactions)
#
# self.sync_progress_timer = QTimer(self)
# self.sync_progress_timer.setSingleShot(False)
# self.sync_progress_timer.setInterval(2000)
# self.sync_progress_timer.timeout.connect(self.update_sync_progress)
@pyqtProperty(bool, notify=isUptodateChanged) @pyqtProperty(bool, notify=isUptodateChanged)
def isUptodate(self): def isUptodate(self):
return self._isUpToDate return self._isUpToDate

Loading…
Cancel
Save