Browse Source

keep all models and various UI items updated on new transactions

patch-4
Sander van Grieken 3 years ago
parent
commit
d88cd75460
  1. 9
      electrum/gui/qml/components/BalanceSummary.qml
  2. 6
      electrum/gui/qml/components/History.qml
  3. 7
      electrum/gui/qml/components/Receive.qml
  4. 24
      electrum/gui/qml/components/RequestDialog.qml
  5. 13
      electrum/gui/qml/qerequestlistmodel.py
  6. 30
      electrum/gui/qml/qetransactionlistmodel.py
  7. 40
      electrum/gui/qml/qewallet.py

9
electrum/gui/qml/components/BalanceSummary.qml

@ -45,6 +45,8 @@ Frame {
}
}
// instead of all these explicit connections, we should expose
// formatted balances directly as a property
Connections {
target: Config
function onBaseUnitChanged() { setBalances() }
@ -56,5 +58,12 @@ Frame {
function onWalletLoaded() { setBalances() }
}
Connections {
target: Daemon.currentWallet
function onBalanceChanged() {
setBalances()
}
}
Component.onCompleted: setBalances()
}

6
electrum/gui/qml/components/History.qml

@ -133,4 +133,10 @@ Pane {
}
Connections {
target: Network
function onHeightChanged(height) {
Daemon.currentWallet.historyModel.updateBlockchainHeight(height)
}
}
}

7
electrum/gui/qml/components/Receive.qml

@ -347,4 +347,11 @@ Pane {
}
}
Connections {
target: Daemon.currentWallet
function onRequestStatusChanged(key, status) {
Daemon.currentWallet.requestModel.updateRequest(key, status)
}
}
}

24
electrum/gui/qml/components/RequestDialog.qml

@ -13,11 +13,10 @@ Dialog {
parent: Overlay.overlay
modal: true
standardButtons: Dialog.Ok
width: parent.width - constants.paddingXLarge
height: parent.height - constants.paddingXLarge
x: (parent.width - width) / 2
y: (parent.height - height) / 2
width: parent.width
height: parent.height
Overlay.modal: Rectangle {
color: "#aa000000"
@ -42,6 +41,7 @@ Dialog {
icon.width: 32
icon.height: 32
onClicked: dialog.close()
visible: false
}
}
GridLayout {
@ -122,13 +122,19 @@ Dialog {
text: qsTr('Address')
}
Label {
Layout.columnSpan: 2
Layout.fillWidth: true
font.family: FixedFont
font.pixelSize: constants.fontSizeLarge
wrapMode: Text.WrapAnywhere
text: modelItem.address
}
ToolButton {
icon.source: '../../icons/copy.png'
icon.color: 'transparent'
onClicked: {
AppController.textToClipboard(modelItem.address)
}
}
Label {
text: qsTr('Status')
@ -162,4 +168,12 @@ Dialog {
}
}
Connections {
target: Daemon.currentWallet
function onRequestStatusChanged(key, code) {
if (key != modelItem.key)
return
modelItem = Daemon.currentWallet.get_request(key)
}
}
}

13
electrum/gui/qml/qerequestlistmodel.py

@ -17,6 +17,7 @@ class QERequestListModel(QAbstractListModel):
_ROLE_NAMES=('key','type','timestamp','message','amount','status','address')
_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]))
_ROLE_RMAP = dict(zip(_ROLE_NAMES, _ROLE_KEYS))
def rowCount(self, index):
return len(self.requests)
@ -87,3 +88,15 @@ class QERequestListModel(QAbstractListModel):
self.endRemoveRows()
break
i = i + 1
@pyqtSlot(str, int)
def updateRequest(self, key, status):
self._logger.debug('updating request for %s to %d' % (key,status))
i = 0
for item in self.requests:
if item['key'] == key:
req = self.wallet.get_request(key)
item['status'] = req.get_status_str(status)
index = self.index(i,0)
self.dataChanged.emit(index, index, [self._ROLE_RMAP['status']])
i = i + 1

30
electrum/gui/qml/qetransactionlistmodel.py

@ -1,8 +1,10 @@
from datetime import datetime
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from electrum.logging import get_logger
from electrum.util import Satoshis
from electrum.util import Satoshis, TxMinedInfo
class QETransactionListModel(QAbstractListModel):
def __init__(self, wallet, parent=None):
@ -18,6 +20,7 @@ class QETransactionListModel(QAbstractListModel):
'inputs','outputs')
_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]))
_ROLE_RMAP = dict(zip(_ROLE_NAMES, _ROLE_KEYS))
def rowCount(self, index):
return len(self.tx_history)
@ -55,3 +58,28 @@ class QETransactionListModel(QAbstractListModel):
self.tx_history.reverse()
self.endInsertRows()
def update_tx(self, txid, info):
i = 0
for tx in self.tx_history:
if tx['txid'] == txid:
tx['height'] = info.height
tx['confirmations'] = info.conf
tx['timestamp'] = info.timestamp
tx['date'] = datetime.fromtimestamp(info.timestamp)
index = self.index(i,0)
roles = [self._ROLE_RMAP[x] for x in ['height','confirmations','timestamp','date']]
self.dataChanged.emit(index, index, roles)
return
i = i + 1
@pyqtSlot(int)
def updateBlockchainHeight(self, height):
self._logger.debug('updating height to %d' % height)
i = 0
for tx in self.tx_history:
if tx['height'] > 0:
tx['confirmations'] = height - tx['height'] + 1
index = self.index(i,0)
roles = [self._ROLE_RMAP['confirmations']]
self.dataChanged.emit(index, index, roles)
i = i + 1

40
electrum/gui/qml/qewallet.py

@ -28,7 +28,7 @@ class QEWallet(QObject):
dataChanged = pyqtSignal()
isUptodateChanged = pyqtSignal()
requestStatus = pyqtSignal()
requestStatusChanged = pyqtSignal([str,int], arguments=['key','status'])
requestCreateSuccess = pyqtSignal()
requestCreateError = pyqtSignal([str,str], arguments=['code','error'])
@ -37,6 +37,7 @@ class QEWallet(QObject):
def __init__(self, wallet, parent=None):
super().__init__(parent)
self.wallet = wallet
self._historyModel = QETransactionListModel(wallet)
self._addressModel = QEAddressListModel(wallet)
self._requestModel = QERequestListModel(wallet)
@ -53,9 +54,8 @@ class QEWallet(QObject):
self.notification_timer.timeout.connect(self.notify_transactions)
self._network_signal.connect(self.on_network_qt)
interests = ['wallet_updated', 'network_updated', 'blockchain_updated',
'new_transaction', 'status', 'verified', 'on_history',
'channel', 'channels_updated', 'payment_failed',
interests = ['wallet_updated', 'new_transaction', 'status', 'verified',
'on_history', 'channel', 'channels_updated', 'payment_failed',
'payment_succeeded', 'invoice_status', 'request_status']
# To avoid leaking references to "self" that prevent the
# window from being GC-ed when closed, callbacks should be
@ -77,13 +77,24 @@ class QEWallet(QObject):
if event == 'status':
self.isUptodateChanged.emit()
elif event == 'request_status':
self._logger.info(str(args))
self.requestStatus.emit()
wallet, addr, c = args
if wallet == self.wallet:
self._logger.debug('request status %d for address %s' % (c, addr))
self.requestStatusChanged.emit(addr, c)
elif event == 'new_transaction':
wallet, tx = args
if wallet == self.wallet:
self.add_tx_notification(tx)
self._historyModel.init_model()
self._historyModel.init_model() # TODO: be less dramatic
elif event == 'verified':
wallet, txid, info = args
if wallet == self.wallet:
self._historyModel.update_tx(txid, info)
elif event == 'wallet_updated':
wallet, = args
if wallet == self.wallet:
self._logger.debug('wallet %s updated' % str(wallet))
self.balanceChanged.emit()
else:
self._logger.debug('unhandled event: %s %s' % (event, str(args)))
@ -115,8 +126,7 @@ class QEWallet(QObject):
except queue.Empty:
break
from .qeapp import ElectrumQmlApplication
config = ElectrumQmlApplication._config
config = self.wallet.config
# Combine the transactions if there are at least three
if len(txns) >= 3:
total_amount = 0
@ -222,10 +232,7 @@ class QEWallet(QObject):
self._logger.info('no change output??? : %s' % str(tx.to_json()['outputs']))
return
from .qeapp import ElectrumQmlApplication
self.config = ElectrumQmlApplication._config
use_rbf = bool(self.config.get('use_rbf', True))
use_rbf = bool(self.wallet.config.get('use_rbf', True))
tx.set_rbf(use_rbf)
def cb(result):
@ -235,7 +242,7 @@ class QEWallet(QObject):
self._logger.info('tx not complete')
return
self.network = ElectrumQmlApplication._daemon.network
self.network = self.wallet.network # TODO not always defined?
try:
self._logger.info('running broadcast in thread')
@ -318,3 +325,8 @@ class QEWallet(QObject):
def delete_request(self, key: str):
self.wallet.delete_request(key)
self._requestModel.delete_request(key)
@pyqtSlot('QString', result='QVariant')
def get_request(self, key: str):
req = self.wallet.get_request(key)
return self._requestModel.request_to_model(req)

Loading…
Cancel
Save