qml: fixes and cleanup for qedaemon, qenetwork. expose many wallet properties in qewallet
This commit is contained in:
@@ -28,15 +28,6 @@ class QEWalletListModel(QAbstractListModel):
|
|||||||
def roleNames(self):
|
def roleNames(self):
|
||||||
return self._ROLE_MAP
|
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):
|
def data(self, index, role):
|
||||||
(wallet_name, wallet_path, wallet) = self.wallets[index.row()]
|
(wallet_name, wallet_path, wallet) = self.wallets[index.row()]
|
||||||
role_index = role - (Qt.UserRole + 1)
|
role_index = role - (Qt.UserRole + 1)
|
||||||
@@ -44,7 +35,7 @@ class QEWalletListModel(QAbstractListModel):
|
|||||||
if role_name == 'name':
|
if role_name == 'name':
|
||||||
return wallet_name
|
return wallet_name
|
||||||
if role_name == 'path':
|
if role_name == 'path':
|
||||||
return wallet_name
|
return wallet_path
|
||||||
if role_name == 'active':
|
if role_name == 'active':
|
||||||
return wallet != None
|
return wallet != None
|
||||||
|
|
||||||
@@ -72,8 +63,13 @@ class QEDaemon(QObject):
|
|||||||
walletLoaded = pyqtSignal()
|
walletLoaded = pyqtSignal()
|
||||||
walletRequiresPassword = pyqtSignal()
|
walletRequiresPassword = pyqtSignal()
|
||||||
|
|
||||||
|
_current_wallet = None
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
@pyqtSlot(str)
|
||||||
|
@pyqtSlot(str, str)
|
||||||
def load_wallet(self, path=None, password=None):
|
def load_wallet(self, path=None, password=None):
|
||||||
|
self._logger.debug('load wallet ' + str(path))
|
||||||
if path == None:
|
if path == None:
|
||||||
path = self.daemon.config.get('gui_last_wallet')
|
path = self.daemon.config.get('gui_last_wallet')
|
||||||
wallet = self.daemon.load_wallet(path, password)
|
wallet = self.daemon.load_wallet(path, password)
|
||||||
@@ -91,7 +87,9 @@ class QEDaemon(QObject):
|
|||||||
|
|
||||||
@pyqtProperty('QString',notify=walletLoaded)
|
@pyqtProperty('QString',notify=walletLoaded)
|
||||||
def walletName(self):
|
def walletName(self):
|
||||||
return self._current_wallet.wallet.basename()
|
if self._current_wallet != None:
|
||||||
|
return self._current_wallet.wallet.basename()
|
||||||
|
return ''
|
||||||
|
|
||||||
@pyqtProperty(QEWalletListModel)
|
@pyqtProperty(QEWalletListModel)
|
||||||
def activeWallets(self):
|
def activeWallets(self):
|
||||||
@@ -108,8 +106,5 @@ class QEDaemon(QObject):
|
|||||||
available.append(i.path)
|
available.append(i.path)
|
||||||
for path in sorted(available):
|
for path in sorted(available):
|
||||||
wallet = self.daemon.get_wallet(path)
|
wallet = self.daemon.get_wallet(path)
|
||||||
if wallet != None:
|
availableListModel.add_wallet(wallet_path = path, wallet = wallet)
|
||||||
availableListModel.add_wallet(wallet_path = wallet.storage.path, wallet = wallet)
|
|
||||||
else:
|
|
||||||
availableListModel.add_wallet(wallet_path = path)
|
|
||||||
return availableListModel
|
return availableListModel
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
|
|||||||
|
|
||||||
from electrum.util import register_callback
|
from electrum.util import register_callback
|
||||||
from electrum.logging import get_logger
|
from electrum.logging import get_logger
|
||||||
|
from electrum import constants
|
||||||
|
|
||||||
class QENetwork(QObject):
|
class QENetwork(QObject):
|
||||||
def __init__(self, network, parent=None):
|
def __init__(self, network, parent=None):
|
||||||
@@ -15,11 +16,13 @@ class QENetwork(QObject):
|
|||||||
|
|
||||||
_logger = get_logger(__name__)
|
_logger = get_logger(__name__)
|
||||||
|
|
||||||
network_updated = pyqtSignal()
|
networkUpdated = pyqtSignal()
|
||||||
blockchain_updated = pyqtSignal()
|
blockchainUpdated = pyqtSignal()
|
||||||
default_server_changed = pyqtSignal()
|
defaultServerChanged = pyqtSignal()
|
||||||
proxy_set = pyqtSignal()
|
proxySet = pyqtSignal()
|
||||||
status_updated = pyqtSignal()
|
statusUpdated = pyqtSignal()
|
||||||
|
|
||||||
|
dataChanged = pyqtSignal() # dummy to silence warnings
|
||||||
|
|
||||||
_num_updates = 0
|
_num_updates = 0
|
||||||
_server = ""
|
_server = ""
|
||||||
@@ -28,40 +31,48 @@ class QENetwork(QObject):
|
|||||||
|
|
||||||
def on_network_updated(self, event, *args):
|
def on_network_updated(self, event, *args):
|
||||||
self._num_updates = self._num_updates + 1
|
self._num_updates = self._num_updates + 1
|
||||||
self.network_updated.emit()
|
self.networkUpdated.emit()
|
||||||
|
|
||||||
def on_blockchain_updated(self, event, *args):
|
def on_blockchain_updated(self, event, *args):
|
||||||
self._logger.info('chainupdate: ' + str(event) + str(args))
|
self._logger.info('chainupdate: ' + str(event) + str(args))
|
||||||
self._height = self.network.get_local_height()
|
self._height = self.network.get_local_height()
|
||||||
self.blockchain_updated.emit()
|
self.blockchainUpdated.emit()
|
||||||
|
|
||||||
def on_default_server_changed(self, event, *args):
|
def on_default_server_changed(self, event, *args):
|
||||||
netparams = self.network.get_parameters()
|
netparams = self.network.get_parameters()
|
||||||
self._server = str(netparams.server)
|
self._server = str(netparams.server)
|
||||||
self.default_server_changed.emit()
|
self.defaultServerChanged.emit()
|
||||||
|
|
||||||
def on_proxy_set(self, event, *args):
|
def on_proxy_set(self, event, *args):
|
||||||
self._logger.info('proxy set')
|
self._logger.info('proxy set')
|
||||||
self.proxy_set.emit()
|
self.proxySet.emit()
|
||||||
|
|
||||||
def on_status(self, event, *args):
|
def on_status(self, event, *args):
|
||||||
self._logger.info('status updated')
|
self._logger.info('status updated')
|
||||||
self._status = self.network.connection_status
|
self._status = self.network.connection_status
|
||||||
self.status_updated.emit()
|
self.statusUpdated.emit()
|
||||||
|
|
||||||
@pyqtProperty(int,notify=network_updated)
|
@pyqtProperty(int,notify=networkUpdated)
|
||||||
def updates(self):
|
def updates(self):
|
||||||
return self._num_updates
|
return self._num_updates
|
||||||
|
|
||||||
@pyqtProperty(int,notify=blockchain_updated)
|
@pyqtProperty(int,notify=blockchainUpdated)
|
||||||
def height(self):
|
def height(self):
|
||||||
return self._height
|
return self._height
|
||||||
|
|
||||||
@pyqtProperty('QString',notify=default_server_changed)
|
@pyqtProperty('QString',notify=defaultServerChanged)
|
||||||
def server(self):
|
def server(self):
|
||||||
return self._server
|
return self._server
|
||||||
|
|
||||||
@pyqtProperty('QString',notify=status_updated)
|
@pyqtProperty('QString',notify=statusUpdated)
|
||||||
def status(self):
|
def status(self):
|
||||||
return self._status
|
return self._status
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=dataChanged)
|
||||||
|
def isTestNet(self):
|
||||||
|
return constants.net.TESTNET
|
||||||
|
|
||||||
|
@pyqtProperty('QString', notify=dataChanged)
|
||||||
|
def networkName(self):
|
||||||
|
return constants.net.__name__.replace('Bitcoin','')
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex, QByteArray
|
|||||||
from electrum.util import register_callback, Satoshis
|
from electrum.util import register_callback, Satoshis
|
||||||
from electrum.logging import get_logger
|
from electrum.logging import get_logger
|
||||||
from electrum.wallet import Wallet, Abstract_Wallet
|
from electrum.wallet import Wallet, Abstract_Wallet
|
||||||
|
from electrum import bitcoin
|
||||||
|
from electrum.transaction import Transaction, tx_from_any, PartialTransaction, PartialTxOutput
|
||||||
|
from electrum.invoices import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED, PR_UNCONFIRMED, PR_TYPE_ONCHAIN, PR_TYPE_LN
|
||||||
|
|
||||||
class QETransactionsListModel(QAbstractListModel):
|
class QETransactionsListModel(QAbstractListModel):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@@ -13,11 +16,10 @@ class QETransactionsListModel(QAbstractListModel):
|
|||||||
_logger = get_logger(__name__)
|
_logger = get_logger(__name__)
|
||||||
|
|
||||||
# define listmodel rolemap
|
# define listmodel rolemap
|
||||||
ROLES=('txid','fee_sat','height','confirmations','timestamp','monotonic_timestamp','incoming','bc_value',
|
_ROLE_NAMES=('txid','fee_sat','height','confirmations','timestamp','monotonic_timestamp','incoming','bc_value',
|
||||||
'bc_balance','date','label','txpos_in_block','fee','inputs','outputs')
|
'bc_balance','date','label','txpos_in_block','fee','inputs','outputs')
|
||||||
keys = range(Qt.UserRole + 1, Qt.UserRole + 1 + len(ROLES))
|
_ROLE_KEYS = range(Qt.UserRole + 1, Qt.UserRole + 1 + len(_ROLE_NAMES))
|
||||||
ROLENAMES = [bytearray(x.encode()) for x in ROLES]
|
_ROLE_MAP = dict(zip(_ROLE_KEYS, [bytearray(x.encode()) for x in _ROLE_NAMES]))
|
||||||
_ROLE_MAP = dict(zip(keys, ROLENAMES))
|
|
||||||
|
|
||||||
def rowCount(self, index):
|
def rowCount(self, index):
|
||||||
return len(self.tx_history)
|
return len(self.tx_history)
|
||||||
@@ -28,14 +30,21 @@ class QETransactionsListModel(QAbstractListModel):
|
|||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
tx = self.tx_history[index.row()]
|
tx = self.tx_history[index.row()]
|
||||||
role_index = role - (Qt.UserRole + 1)
|
role_index = role - (Qt.UserRole + 1)
|
||||||
value = tx[self.ROLES[role_index]]
|
value = tx[self._ROLE_NAMES[role_index]]
|
||||||
if isinstance(value, bool) or isinstance(value, list) or isinstance(value, int) or value is None:
|
if isinstance(value, bool) or isinstance(value, list) or isinstance(value, int) or value is None:
|
||||||
return value
|
return value
|
||||||
if isinstance(value, Satoshis):
|
if isinstance(value, Satoshis):
|
||||||
return value.value
|
return value.value
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self.beginResetModel()
|
||||||
|
self.tx_history = []
|
||||||
|
self.endResetModel()
|
||||||
|
|
||||||
|
# initial model data
|
||||||
def set_history(self, history):
|
def set_history(self, history):
|
||||||
|
self.clear()
|
||||||
self.beginInsertRows(QModelIndex(), 0, len(history) - 1)
|
self.beginInsertRows(QModelIndex(), 0, len(history) - 1)
|
||||||
self.tx_history = history
|
self.tx_history = history
|
||||||
self.tx_history.reverse()
|
self.tx_history.reverse()
|
||||||
@@ -45,23 +54,91 @@ class QEWallet(QObject):
|
|||||||
def __init__(self, wallet, parent=None):
|
def __init__(self, wallet, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.wallet = wallet
|
self.wallet = wallet
|
||||||
|
self._historyModel = QETransactionsListModel()
|
||||||
self.get_history()
|
self.get_history()
|
||||||
|
register_callback(self.on_request_status, ['request_status'])
|
||||||
|
|
||||||
_logger = get_logger(__name__)
|
_logger = get_logger(__name__)
|
||||||
|
|
||||||
_historyModel = QETransactionsListModel()
|
dataChanged = pyqtSignal() # dummy to silence warnings
|
||||||
|
|
||||||
@pyqtProperty(QETransactionsListModel)
|
requestStatus = pyqtSignal()
|
||||||
|
def on_request_status(self, event, *args):
|
||||||
|
self._logger.debug(str(event))
|
||||||
|
# (wallet, addr, status) = args
|
||||||
|
# self._historyModel.add_tx()
|
||||||
|
self.requestStatus.emit()
|
||||||
|
|
||||||
|
historyModelChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(QETransactionsListModel, notify=historyModelChanged)
|
||||||
def historyModel(self):
|
def historyModel(self):
|
||||||
return self._historyModel
|
return self._historyModel
|
||||||
|
|
||||||
|
@pyqtProperty('QString', notify=dataChanged)
|
||||||
|
def txinType(self):
|
||||||
|
return self.wallet.get_txin_type(self.wallet.dummy_address())
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=dataChanged)
|
||||||
|
def isWatchOnly(self):
|
||||||
|
return self.wallet.is_watching_only()
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=dataChanged)
|
||||||
|
def isDeterministic(self):
|
||||||
|
return self.wallet.is_deterministic()
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=dataChanged)
|
||||||
|
def isEncrypted(self):
|
||||||
|
return self.wallet.storage.is_encrypted()
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=dataChanged)
|
||||||
|
def isHardware(self):
|
||||||
|
return self.wallet.storage.is_encrypted_with_hw_device()
|
||||||
|
|
||||||
|
@pyqtProperty('QString', notify=dataChanged)
|
||||||
|
def derivationPath(self):
|
||||||
|
return self.wallet.get_address_path_str(self.wallet.dummy_address())
|
||||||
|
|
||||||
|
balanceChanged = pyqtSignal()
|
||||||
|
|
||||||
|
@pyqtProperty(int, notify=balanceChanged)
|
||||||
|
def frozenBalance(self):
|
||||||
|
return self.wallet.get_frozen_balance()
|
||||||
|
|
||||||
|
@pyqtProperty(int, notify=balanceChanged)
|
||||||
|
def unconfirmedBalance(self):
|
||||||
|
return self.wallet.get_balance()[1]
|
||||||
|
|
||||||
|
@pyqtProperty(int, notify=balanceChanged)
|
||||||
|
def confirmedBalance(self):
|
||||||
|
c, u, x = self.wallet.get_balance()
|
||||||
|
self._logger.info('balance: ' + str(c) + ' ' + str(u) + ' ' + str(x) + ' ')
|
||||||
|
|
||||||
|
return c+x
|
||||||
|
|
||||||
|
# lightning feature?
|
||||||
|
isUptodateChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(bool, notify=isUptodateChanged)
|
||||||
|
def isUptodate(self):
|
||||||
|
return self.wallet.is_up_to_date()
|
||||||
|
|
||||||
def get_history(self):
|
def get_history(self):
|
||||||
history = self.wallet.get_detailed_history(show_addresses = True)
|
history = self.wallet.get_detailed_history(show_addresses = True)
|
||||||
txs = history['transactions']
|
txs = history['transactions']
|
||||||
self._logger.info(txs)
|
|
||||||
# use primitives
|
# use primitives
|
||||||
for tx in txs:
|
for tx in txs:
|
||||||
for output in tx['outputs']:
|
for output in tx['outputs']:
|
||||||
output['value'] = output['value'].value
|
output['value'] = output['value'].value
|
||||||
self._historyModel.set_history(txs)
|
self._historyModel.set_history(txs)
|
||||||
|
self.historyModelChanged.emit()
|
||||||
|
|
||||||
|
@pyqtSlot('QString', int, int, bool)
|
||||||
|
def send_onchain(self, address, amount, fee=None, rbf=False):
|
||||||
|
self._logger.info('send_onchain: ' + address + ' ' + str(amount))
|
||||||
|
coins = self.wallet.get_spendable_coins(None)
|
||||||
|
if not bitcoin.is_address(address):
|
||||||
|
self._logger.warning('Invalid Bitcoin Address: ' + address)
|
||||||
|
return False
|
||||||
|
|
||||||
|
outputs = [PartialTxOutput.from_address_and_value(address, amount)]
|
||||||
|
tx = self.wallet.make_unsigned_transaction(coins=coins,outputs=outputs)
|
||||||
|
return True
|
||||||
|
|||||||
Reference in New Issue
Block a user