From 3b22ecdae4e4c72799cb666c9deb3027af7503f2 Mon Sep 17 00:00:00 2001 From: Sander van Grieken Date: Tue, 6 Apr 2021 14:13:51 +0200 Subject: [PATCH] qml: add available wallets model --- electrum/gui/qml/__init__.py | 7 +- electrum/gui/qml/components/Wallets.qml | 19 +++- electrum/gui/qml/qedaemon.py | 115 ++++++++++++++++++++++++ electrum/gui/qml/qenetwork.py | 63 +------------ 4 files changed, 135 insertions(+), 69 deletions(-) create mode 100644 electrum/gui/qml/qedaemon.py diff --git a/electrum/gui/qml/__init__.py b/electrum/gui/qml/__init__.py index 444f0a88b..5d9b2a0f6 100644 --- a/electrum/gui/qml/__init__.py +++ b/electrum/gui/qml/__init__.py @@ -15,7 +15,7 @@ try: except Exception: sys.exit("Error: Could not import PyQt5.QtQml on Linux systems, you may try 'sudo apt-get install python3-pyqt5.qtquick'") -from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QUrl, QLocale, QTimer +from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl, QLocale, QTimer from PyQt5.QtGui import QGuiApplication from PyQt5.QtQml import qmlRegisterType, QQmlComponent, QQmlApplicationEngine from PyQt5.QtQuick import QQuickView @@ -36,8 +36,9 @@ if TYPE_CHECKING: from electrum.simple_config import SimpleConfig from electrum.plugin import Plugins -from .qenetwork import QENetwork, QEDaemon, QEWalletListModel -from .qewallet import * +from .qedaemon import QEDaemon, QEWalletListModel +from .qenetwork import QENetwork +from .qewallet import QEWallet from .qeqr import QEQR class ElectrumQmlApplication(QGuiApplication): diff --git a/electrum/gui/qml/components/Wallets.qml b/electrum/gui/qml/components/Wallets.qml index 5ce2fc859..7dafba18b 100644 --- a/electrum/gui/qml/components/Wallets.qml +++ b/electrum/gui/qml/components/Wallets.qml @@ -5,13 +5,16 @@ import QtQuick.Controls 2.0 Item { property string title: 'Wallets' + anchors.fill: parent + ListView { width: parent.width - height: 200 - model: Daemon.activeWallets + height: parent.height + model: Daemon.availableWallets delegate: Item { width: ListView.view.width + height: 50 RowLayout { x: 20 @@ -22,9 +25,17 @@ Item { } Label { - font.pointSize: 13 - text: model.display + font.pointSize: model.active ? 14 : 13 + font.bold: model.active + text: model.name + Layout.fillWidth: true } + + } + + MouseArea { + anchors.fill: parent + onClicked: openMenu() } } } diff --git a/electrum/gui/qml/qedaemon.py b/electrum/gui/qml/qedaemon.py new file mode 100644 index 000000000..58f4ce928 --- /dev/null +++ b/electrum/gui/qml/qedaemon.py @@ -0,0 +1,115 @@ +import os + +from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl +from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex + +from electrum.util import register_callback, get_new_wallet_name +from electrum.logging import get_logger +from electrum.wallet import Wallet, Abstract_Wallet + +from .qewallet import QEWallet + +# wallet list model. supports both wallet basenames (wallet file basenames) +# and whole Wallet instances (loaded wallets) +class QEWalletListModel(QAbstractListModel): + _logger = get_logger(__name__) + def __init__(self, parent=None): + QAbstractListModel.__init__(self, parent) + self.wallets = [] + + # define listmodel rolemap + _ROLE_NAMES= ('name','path','active') + _ROLE_KEYS = range(Qt.UserRole + 1, Qt.UserRole + 1 + len(_ROLE_NAMES)) + _ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES])) + + def rowCount(self, index): + return len(self.wallets) + + def roleNames(self): + return self._ROLE_MAP + + def data(self, index, role): + role_index = role - (Qt.UserRole + 1) + value = tx[self._ROLE_NAMES[role_index]] + if isinstance(value, bool) or isinstance(value, list) or isinstance(value, int) or value is None: + return value + if isinstance(value, Satoshis): + return value.value + return str(value) + + def data(self, index, role): + (wallet_name, wallet_path, wallet) = self.wallets[index.row()] + role_index = role - (Qt.UserRole + 1) + role_name = self._ROLE_NAMES[role_index] + if role_name == 'name': + return wallet_name + if role_name == 'path': + return wallet_name + if role_name == 'active': + return wallet != None + + def add_wallet(self, wallet_path = None, wallet: Abstract_Wallet = None): + if wallet_path == None and wallet == None: + return + self.beginInsertRows(QModelIndex(), len(self.wallets), len(self.wallets)); + if wallet == None: + wallet_name = os.path.basename(wallet_path) + else: + wallet_name = wallet.basename() + item = (wallet_name, wallet_path, wallet) + self.wallets.append(item); + self.endInsertRows(); + + +class QEDaemon(QObject): + def __init__(self, daemon, parent=None): + super().__init__(parent) + self.daemon = daemon + + _logger = get_logger(__name__) + _loaded_wallets = QEWalletListModel() + + walletLoaded = pyqtSignal() + walletRequiresPassword = pyqtSignal() + + @pyqtSlot() + def load_wallet(self, path=None, password=None): + if path == None: + path = self.daemon.config.get('gui_last_wallet') + wallet = self.daemon.load_wallet(path, password) + if wallet != None: + self._loaded_wallets.add_wallet(wallet=wallet) + self._current_wallet = QEWallet(wallet) + self.walletLoaded.emit() + else: + self._logger.info('fail open wallet') + self.walletRequiresPassword.emit() + + @pyqtProperty(QEWallet,notify=walletLoaded) + def currentWallet(self): + return self._current_wallet + + @pyqtProperty('QString',notify=walletLoaded) + def walletName(self): + return self._current_wallet.wallet.basename() + + @pyqtProperty(QEWalletListModel) + def activeWallets(self): + return self._loaded_wallets + + @pyqtProperty(QEWalletListModel) + def availableWallets(self): + available = [] + availableListModel = QEWalletListModel(self) + wallet_folder = os.path.dirname(self.daemon.config.get_wallet_path()) + with os.scandir(wallet_folder) as it: + for i in it: + if i.is_file(): + available.append(i.path) + for path in sorted(available): + wallet = self.daemon.get_wallet(path) + if wallet != None: + availableListModel.add_wallet(wallet_path = wallet.storage.path, wallet = wallet) + else: + availableListModel.add_wallet(wallet_path = path) + return availableListModel diff --git a/electrum/gui/qml/qenetwork.py b/electrum/gui/qml/qenetwork.py index 312021d9c..38a3b6b03 100644 --- a/electrum/gui/qml/qenetwork.py +++ b/electrum/gui/qml/qenetwork.py @@ -1,11 +1,7 @@ -from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QUrl -from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex +from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject from electrum.util import register_callback from electrum.logging import get_logger -from electrum.wallet import Wallet, Abstract_Wallet - -from .qewallet import QEWallet class QENetwork(QObject): def __init__(self, network, parent=None): @@ -69,60 +65,3 @@ class QENetwork(QObject): def status(self): return self._status -class QEWalletListModel(QAbstractListModel): - def __init__(self, parent=None): - QAbstractListModel.__init__(self, parent) - self.wallets = [] - - def rowCount(self, index): - return len(self.wallets) - - def data(self, index, role): - if role == Qt.DisplayRole: - return self.wallets[index.row()].basename() - - def add_wallet(self, wallet: Abstract_Wallet = None): - if wallet == None: - return - self.beginInsertRows(QModelIndex(), len(self.wallets), len(self.wallets)); - self.wallets.append(wallet); - self.endInsertRows(); - - -class QEDaemon(QObject): - def __init__(self, daemon, parent=None): - super().__init__(parent) - self.daemon = daemon - - _logger = get_logger(__name__) - _wallet = '' - _loaded_wallets = QEWalletListModel() - - wallet_loaded = pyqtSignal() - - @pyqtSlot() - def load_wallet(self, path=None, password=None): - self._logger.info(str(self.daemon.get_wallets())) - if path == None: - path = self.daemon.config.get('recently_open')[0] - wallet = self.daemon.load_wallet(path, password) - if wallet != None: - self._loaded_wallets.add_wallet(wallet) - self._wallet = wallet.basename() - self._current_wallet = QEWallet(wallet) - self.wallet_loaded.emit() - self._logger.info(str(self.daemon.get_wallets())) - else: - self._logger.info('fail open wallet') - - @pyqtProperty('QString',notify=wallet_loaded) - def walletName(self): - return self._wallet - - @pyqtProperty(QEWalletListModel) - def activeWallets(self): - return self._loaded_wallets - - @pyqtProperty(QEWallet,notify=wallet_loaded) - def currentWallet(self): - return self._current_wallet