qml: network status improvements
create NetworkStatusIndicator component add forks/chaintips and lagging property to qenetwork add synchronizing and synchronizing progress properties to qewallet Note: new wallet synchronizing is not picked up in UI yet, missing an is_up_to_date event at the start still..
This commit is contained in:
@@ -3,6 +3,8 @@ import QtQuick.Layouts 1.0
|
|||||||
import QtQuick.Controls 2.0
|
import QtQuick.Controls 2.0
|
||||||
import QtQuick.Controls.Material 2.0
|
import QtQuick.Controls.Material 2.0
|
||||||
|
|
||||||
|
import "controls"
|
||||||
|
|
||||||
Pane {
|
Pane {
|
||||||
property string title: qsTr('Network')
|
property string title: qsTr('Network')
|
||||||
|
|
||||||
@@ -45,17 +47,9 @@ Pane {
|
|||||||
color: Material.primaryHighlightedTextColor;
|
color: Material.primaryHighlightedTextColor;
|
||||||
font.bold: true
|
font.bold: true
|
||||||
}
|
}
|
||||||
Image {
|
|
||||||
Layout.preferredWidth: constants.iconSizeSmall
|
NetworkStatusIndicator {}
|
||||||
Layout.preferredHeight: constants.iconSizeSmall
|
|
||||||
source: Network.status == 'connecting' || Network.status == 'disconnected'
|
|
||||||
? '../../icons/status_disconnected.png'
|
|
||||||
: Network.status == 'connected'
|
|
||||||
? Daemon.currentWallet && !Daemon.currentWallet.isUptodate
|
|
||||||
? '../../icons/status_lagging.png'
|
|
||||||
: '../../icons/status_connected.png'
|
|
||||||
: '../../icons/status_connected.png'
|
|
||||||
}
|
|
||||||
Label {
|
Label {
|
||||||
text: Network.status
|
text: Network.status
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import QtQuick 2.6
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
sourceSize.width: constants.iconSizeMedium
|
||||||
|
sourceSize.height: constants.iconSizeMedium
|
||||||
|
|
||||||
|
property bool connected: Network.status == 'connected'
|
||||||
|
property bool lagging: connected && Network.isLagging
|
||||||
|
property bool fork: connected && Network.chaintips > 1
|
||||||
|
property bool syncing: connected && Daemon.currentWallet && Daemon.currentWallet.synchronizing
|
||||||
|
|
||||||
|
// ?: in order to keep this a binding..
|
||||||
|
source: !connected
|
||||||
|
? '../../../icons/status_disconnected.png'
|
||||||
|
: syncing
|
||||||
|
? '../../../icons/status_waiting.png'
|
||||||
|
: lagging
|
||||||
|
? fork
|
||||||
|
? '../../../icons/status_lagging_fork.png'
|
||||||
|
: '../../../icons/status_lagging.png'
|
||||||
|
: fork
|
||||||
|
? '../../../icons/status_connected_fork.png'
|
||||||
|
: '../../../icons/status_connected.png'
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: 'disconnected'
|
||||||
|
when: !connected
|
||||||
|
PropertyChanges { target: root; rotation: 0 }
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: 'normal'
|
||||||
|
when: !(syncing || fork)
|
||||||
|
PropertyChanges { target: root; rotation: 0 }
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: 'syncing'
|
||||||
|
when: syncing
|
||||||
|
PropertyChanges { target: spin; running: true }
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: 'forked'
|
||||||
|
when: fork
|
||||||
|
PropertyChanges { target: root; rotation: 0 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
RotationAnimation {
|
||||||
|
id: spin
|
||||||
|
target: root
|
||||||
|
from: 0
|
||||||
|
to: 360
|
||||||
|
duration: 1000
|
||||||
|
loops: Animation.Infinite
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -88,17 +88,7 @@ ApplicationWindow
|
|||||||
scale: 1.5
|
scale: 1.5
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
NetworkStatusIndicator { }
|
||||||
Layout.preferredWidth: constants.iconSizeSmall
|
|
||||||
Layout.preferredHeight: constants.iconSizeSmall
|
|
||||||
source: Network.status == 'connecting' || Network.status == 'disconnected'
|
|
||||||
? '../../icons/status_disconnected.png'
|
|
||||||
: Network.status == 'connected'
|
|
||||||
? Daemon.currentWallet && !Daemon.currentWallet.isUptodate
|
|
||||||
? '../../icons/status_lagging.png'
|
|
||||||
: '../../icons/status_connected.png'
|
|
||||||
: '../../icons/status_connected.png'
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: 'transparent'
|
color: 'transparent'
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class QENetwork(QObject, QtEventListener):
|
|||||||
def __init__(self, network, parent=None):
|
def __init__(self, network, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.network = network
|
self.network = network
|
||||||
|
self._height = network.get_local_height() # init here, update event can take a while
|
||||||
self.register_callbacks()
|
self.register_callbacks()
|
||||||
|
|
||||||
_logger = get_logger(__name__)
|
_logger = get_logger(__name__)
|
||||||
@@ -22,12 +23,16 @@ class QENetwork(QObject, QtEventListener):
|
|||||||
proxyChanged = pyqtSignal()
|
proxyChanged = pyqtSignal()
|
||||||
statusChanged = pyqtSignal()
|
statusChanged = pyqtSignal()
|
||||||
feeHistogramUpdated = pyqtSignal()
|
feeHistogramUpdated = pyqtSignal()
|
||||||
|
chaintipsChanged = pyqtSignal()
|
||||||
|
isLaggingChanged = pyqtSignal()
|
||||||
|
|
||||||
# shared signal for static properties
|
# shared signal for static properties
|
||||||
dataChanged = pyqtSignal()
|
dataChanged = pyqtSignal()
|
||||||
|
|
||||||
_height = 0
|
_height = 0
|
||||||
_status = ""
|
_status = ""
|
||||||
|
_chaintips = 1
|
||||||
|
_islagging = False
|
||||||
_fee_histogram = []
|
_fee_histogram = []
|
||||||
|
|
||||||
@event_listener
|
@event_listener
|
||||||
@@ -35,7 +40,7 @@ class QENetwork(QObject, QtEventListener):
|
|||||||
self.networkUpdated.emit()
|
self.networkUpdated.emit()
|
||||||
|
|
||||||
@event_listener
|
@event_listener
|
||||||
def on_event_blockchain_updated(self, *args):
|
def on_event_blockchain_updated(self):
|
||||||
if self._height != self.network.get_local_height():
|
if self._height != self.network.get_local_height():
|
||||||
self._height = self.network.get_local_height()
|
self._height = self.network.get_local_height()
|
||||||
self._logger.debug('new height: %d' % self._height)
|
self._logger.debug('new height: %d' % self._height)
|
||||||
@@ -57,6 +62,16 @@ class QENetwork(QObject, QtEventListener):
|
|||||||
if self._status != self.network.connection_status:
|
if self._status != self.network.connection_status:
|
||||||
self._status = self.network.connection_status
|
self._status = self.network.connection_status
|
||||||
self.statusChanged.emit()
|
self.statusChanged.emit()
|
||||||
|
chains = len(self.network.get_blockchains())
|
||||||
|
if chains != self._chaintips:
|
||||||
|
self._logger.debug('chain tips # changed: ' + chains)
|
||||||
|
self._chaintips = chains
|
||||||
|
self.chaintipsChanged.emit()
|
||||||
|
server_lag = self.network.get_local_height() - self.network.get_server_height()
|
||||||
|
if self._islagging ^ (server_lag > 1):
|
||||||
|
self._logger.debug('lagging changed: ' + (server_lag > 1))
|
||||||
|
self._islagging = server_lag > 1
|
||||||
|
self.isLaggingChanged.emit()
|
||||||
|
|
||||||
@event_listener
|
@event_listener
|
||||||
def on_event_fee_histogram(self, histogram):
|
def on_event_fee_histogram(self, histogram):
|
||||||
@@ -68,7 +83,7 @@ class QENetwork(QObject, QtEventListener):
|
|||||||
def height(self):
|
def height(self):
|
||||||
return self._height
|
return self._height
|
||||||
|
|
||||||
@pyqtProperty('QString', notify=defaultServerChanged)
|
@pyqtProperty(str, notify=defaultServerChanged)
|
||||||
def server(self):
|
def server(self):
|
||||||
return str(self.network.get_parameters().server)
|
return str(self.network.get_parameters().server)
|
||||||
|
|
||||||
@@ -83,15 +98,23 @@ class QENetwork(QObject, QtEventListener):
|
|||||||
net_params = net_params._replace(server=server)
|
net_params = net_params._replace(server=server)
|
||||||
self.network.run_from_another_thread(self.network.set_parameters(net_params))
|
self.network.run_from_another_thread(self.network.set_parameters(net_params))
|
||||||
|
|
||||||
@pyqtProperty('QString', notify=statusChanged)
|
@pyqtProperty(str, notify=statusChanged)
|
||||||
def status(self):
|
def status(self):
|
||||||
return self._status
|
return self._status
|
||||||
|
|
||||||
|
@pyqtProperty(int, notify=chaintipsChanged)
|
||||||
|
def chaintips(self):
|
||||||
|
return self._chaintips
|
||||||
|
|
||||||
|
@pyqtProperty(bool, notify=isLaggingChanged)
|
||||||
|
def isLagging(self):
|
||||||
|
return self._islagging
|
||||||
|
|
||||||
@pyqtProperty(bool, notify=dataChanged)
|
@pyqtProperty(bool, notify=dataChanged)
|
||||||
def isTestNet(self):
|
def isTestNet(self):
|
||||||
return constants.net.TESTNET
|
return constants.net.TESTNET
|
||||||
|
|
||||||
@pyqtProperty('QString', notify=dataChanged)
|
@pyqtProperty(str, notify=dataChanged)
|
||||||
def networkName(self):
|
def networkName(self):
|
||||||
return constants.net.__name__.replace('Bitcoin','')
|
return constants.net.__name__.replace('Bitcoin','')
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,10 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
|
|||||||
|
|
||||||
_network_signal = pyqtSignal(str, object)
|
_network_signal = pyqtSignal(str, object)
|
||||||
|
|
||||||
|
_isUpToDate = False
|
||||||
|
_synchronizing = False
|
||||||
|
_synchronizing_progress = ''
|
||||||
|
|
||||||
def __init__(self, wallet, parent=None):
|
def __init__(self, wallet, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.wallet = wallet
|
self.wallet = wallet
|
||||||
@@ -91,11 +95,52 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
|
|||||||
|
|
||||||
@pyqtProperty(bool, notify=isUptodateChanged)
|
@pyqtProperty(bool, notify=isUptodateChanged)
|
||||||
def isUptodate(self):
|
def isUptodate(self):
|
||||||
return self.wallet.is_up_to_date()
|
return self._isUpToDate
|
||||||
|
|
||||||
|
synchronizingChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(bool, notify=synchronizingChanged)
|
||||||
|
def synchronizing(self):
|
||||||
|
return self._synchronizing
|
||||||
|
|
||||||
|
@synchronizing.setter
|
||||||
|
def synchronizing(self, synchronizing):
|
||||||
|
if self._synchronizing != synchronizing:
|
||||||
|
self._synchronizing = synchronizing
|
||||||
|
self.synchronizingChanged.emit()
|
||||||
|
|
||||||
|
synchronizingProgressChanged = pyqtSignal()
|
||||||
|
@pyqtProperty(str, notify=synchronizingProgressChanged)
|
||||||
|
def synchronizing_progress(self):
|
||||||
|
return self._synchronizing_progress
|
||||||
|
|
||||||
|
@synchronizing_progress.setter
|
||||||
|
def synchronizing_progress(self, progress):
|
||||||
|
if self._synchronizing_progress != progress:
|
||||||
|
self._synchronizing_progress = progress
|
||||||
|
self.synchronizingProgressChanged.emit()
|
||||||
|
|
||||||
@event_listener
|
@event_listener
|
||||||
def on_event_status(self, *args, **kwargs):
|
def on_event_status(self):
|
||||||
self.isUptodateChanged.emit()
|
self._logger.debug('status')
|
||||||
|
uptodate = self.wallet.is_up_to_date()
|
||||||
|
if self._isUpToDate != uptodate:
|
||||||
|
self._isUpToDate = uptodate
|
||||||
|
self.isUptodateChanged.emit()
|
||||||
|
|
||||||
|
if self.wallet.network.is_connected():
|
||||||
|
server_height = self.wallet.network.get_server_height()
|
||||||
|
server_lag = self.wallet.network.get_local_height() - server_height
|
||||||
|
# Server height can be 0 after switching to a new server
|
||||||
|
# until we get a headers subscription request response.
|
||||||
|
# Display the synchronizing message in that case.
|
||||||
|
if not self._isUpToDate or server_height == 0:
|
||||||
|
num_sent, num_answered = self.wallet.adb.get_history_sync_state_details()
|
||||||
|
self.synchronizing_progress = ("{} ({}/{})"
|
||||||
|
.format(_("Synchronizing..."), num_answered, num_sent))
|
||||||
|
self.synchronizing = True
|
||||||
|
else:
|
||||||
|
self.synchronizing_progress = ''
|
||||||
|
self.synchronizing = False
|
||||||
|
|
||||||
@event_listener
|
@event_listener
|
||||||
def on_event_request_status(self, wallet, key, status):
|
def on_event_request_status(self, wallet, key, status):
|
||||||
@@ -116,8 +161,7 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
|
|||||||
self._logger.debug(f'No invoice found for key {key}')
|
self._logger.debug(f'No invoice found for key {key}')
|
||||||
|
|
||||||
@qt_event_listener
|
@qt_event_listener
|
||||||
def on_event_new_transaction(self, *args):
|
def on_event_new_transaction(self, wallet, tx):
|
||||||
wallet, tx = args
|
|
||||||
if wallet == self.wallet:
|
if wallet == self.wallet:
|
||||||
self.add_tx_notification(tx)
|
self.add_tx_notification(tx)
|
||||||
self.historyModel.init_model() # TODO: be less dramatic
|
self.historyModel.init_model() # TODO: be less dramatic
|
||||||
|
|||||||
Reference in New Issue
Block a user