Browse Source

qml: add serverlistmodel.py, add server list to ServerConfigDialog.qml

master
Sander van Grieken 3 years ago
parent
commit
f774174c85
  1. 1
      electrum/gui/qml/components/NetworkOverview.qml
  2. 36
      electrum/gui/qml/components/ServerConfigDialog.qml
  3. 11
      electrum/gui/qml/components/controls/PaneInsetBackground.qml
  4. 29
      electrum/gui/qml/components/controls/ServerDelegate.qml
  5. 9
      electrum/gui/qml/qenetwork.py
  6. 133
      electrum/gui/qml/qeserverlistmodel.py

1
electrum/gui/qml/components/NetworkOverview.qml

@ -154,6 +154,7 @@ Pane {
text: qsTr('disabled');
visible: !Config.useGossip
}
}
}

36
electrum/gui/qml/components/ServerConfigDialog.qml

@ -30,14 +30,44 @@ ElDialog {
height: parent.height
spacing: 0
ServerConfig {
id: serverconfig
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: constants.paddingLarge
Layout.rightMargin: constants.paddingLarge
ServerConfig {
id: serverconfig
Layout.fillWidth: true
}
Label {
text: qsTr('Servers')
font.pixelSize: constants.fontSizeLarge
color: Material.accentColor
}
Item { Layout.fillHeight: true; Layout.preferredWidth: 1 }
Rectangle {
Layout.fillWidth: true
height: 1
color: Material.accentColor
}
Frame {
background: PaneInsetBackground { baseColor: Material.dialogColor }
verticalPadding: 0
horizontalPadding: 0
Layout.fillHeight: true
Layout.fillWidth: true
ListView {
anchors.fill: parent
model: Network.serverListModel
delegate: ServerDelegate { }
}
}
}
FlatButton {
Layout.fillWidth: true

11
electrum/gui/qml/components/controls/PaneInsetBackground.qml

@ -2,25 +2,26 @@ import QtQuick 2.6
import QtQuick.Controls.Material 2.0
Rectangle {
property color baseColor: Material.background
Rectangle {
anchors { left: parent.left; top: parent.top; right: parent.right }
height: 1
color: Qt.darker(Material.background, 1.50)
color: Qt.darker(baseColor, 1.50)
}
Rectangle {
anchors { left: parent.left; top: parent.top; bottom: parent.bottom }
width: 1
color: Qt.darker(Material.background, 1.50)
color: Qt.darker(baseColor, 1.50)
}
Rectangle {
anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
height: 1
color: Qt.lighter(Material.background, 1.50)
color: Qt.lighter(baseColor, 1.50)
}
Rectangle {
anchors { right: parent.right; top: parent.top; bottom: parent.bottom }
width: 1
color: Qt.lighter(Material.background, 1.50)
color: Qt.lighter(baseColor, 1.50)
}
color: Qt.darker(Material.background, 1.15)
color: Qt.darker(baseColor, 1.15)
}

29
electrum/gui/qml/components/controls/ServerDelegate.qml

@ -0,0 +1,29 @@
import QtQuick 2.6
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import QtQuick.Controls.Material 2.0
import org.electrum 1.0
ItemDelegate {
id: root
height: itemLayout.height
width: ListView.view.width
GridLayout {
id: itemLayout
anchors {
left: parent.left
right: parent.right
leftMargin: constants.paddingSmall
rightMargin: constants.paddingSmall
}
columns: 2
Label {
text: model.address
}
Label {
text: model.chain
}
}
}

9
electrum/gui/qml/qenetwork.py

@ -5,12 +5,14 @@ from electrum import constants
from electrum.interface import ServerAddr
from .util import QtEventListener, event_listener
from .qeserverlistmodel import QEServerListModel
class QENetwork(QObject, QtEventListener):
def __init__(self, network, qeconfig, parent=None):
super().__init__(parent)
self.network = network
self._qeconfig = qeconfig
self._serverListModel = None
self._height = network.get_local_height() # init here, update event can take a while
self.register_callbacks()
@ -186,3 +188,10 @@ class QENetwork(QObject, QtEventListener):
'db_channels': self._gossipDbChannels ,
'db_policies': self._gossipDbPolicies
}
serverListModelChanged = pyqtSignal()
@pyqtProperty(QEServerListModel, notify=serverListModelChanged)
def serverListModel(self):
if self._serverListModel is None:
self._serverListModel = QEServerListModel(self.network)
return self._serverListModel

133
electrum/gui/qml/qeserverlistmodel.py

@ -0,0 +1,133 @@
from abc import abstractmethod
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex
from electrum.i18n import _
from electrum.logging import get_logger
from electrum.util import Satoshis, format_time
from electrum.interface import ServerAddr, PREFERRED_NETWORK_PROTOCOL
from electrum import blockchain
from .util import QtEventListener, qt_event_listener, event_listener
class QEServerListModel(QAbstractListModel, QtEventListener):
_logger = get_logger(__name__)
_chaintips = 0
# define listmodel rolemap
_ROLE_NAMES=('name', 'address', 'is_connected', 'is_primary', 'is_tor', 'chain', 'height')
_ROLE_KEYS = range(Qt.UserRole, Qt.UserRole + 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 __init__(self, network, parent=None):
super().__init__(parent)
self.network = network
self.init_model()
self.register_callbacks()
self.destroyed.connect(lambda: self.unregister_callbacks())
@event_listener
def on_event_network_updated(self):
self._logger.info(f'network updated')
self.init_model()
@event_listener
def on_event_blockchain_updated(self):
self._logger.info(f'blockchain updated')
self.init_model()
@event_listener
def on_event_default_server_changed(self):
self._logger.info(f'default server changed')
self.init_model()
def rowCount(self, index):
return len(self.servers)
def roleNames(self):
return self._ROLE_MAP
def data(self, index, role):
server = self.servers[index.row()]
role_index = role - Qt.UserRole
value = server[self._ROLE_NAMES[role_index]]
if isinstance(value, (bool, list, int, str)) or value is None:
return value
if isinstance(value, Satoshis):
return value.value
return str(value)
def clear(self):
self.beginResetModel()
self.servers = []
self.endResetModel()
chaintipsChanged = pyqtSignal()
@pyqtProperty(int, notify=chaintipsChanged)
def chaintips(self):
return self._chaintips
def get_chains(self):
chains = self.network.get_blockchains()
n_chains = len(chains)
if n_chains != self._chaintips:
self._chaintips = n_chains
self.chaintipsChanged.emit()
return chains
@pyqtSlot()
def init_model(self):
self.clear()
chains = self.get_chains()
for chain_id, interfaces in chains.items():
self._logger.debug(f'chain {chain_id} has {len(interfaces)} interfaces')
b = blockchain.blockchains.get(chain_id)
if b is None:
continue
name = b.get_name()
self._logger.debug(f'chain {chain_id} has name={name}, max_forkpoint=@{b.get_max_forkpoint()}, height={b.height()}')
for i in interfaces:
server = {}
server['chain'] = name
server['chain_height'] = b.height()
server['is_primary'] = i == self.network.interface
server['is_connected'] = True
server['name'] = str(i.server)
server['address'] = i.server.to_friendly_name()
server['height'] = i.tip
self._logger.debug(f'adding server: {repr(server)}')
self.servers.append(server)
# disconnected servers
all_servers = self.network.get_servers()
connected_hosts = set([iface.host for ifaces in chains.values() for iface in ifaces])
protocol = PREFERRED_NETWORK_PROTOCOL
use_tor = True
for _host, d in sorted(all_servers.items()):
if _host in connected_hosts:
continue
if _host.endswith('.onion') and not use_tor:
continue
port = d.get(protocol)
if port:
s = ServerAddr(_host, port, protocol=protocol)
server = {}
server['chain'] = ''
server['chain_height'] = 0
server['height'] = 0
server['is_primary'] = False
server['is_connected'] = False
server['name'] = s.net_addr_str()
server['address'] = server['name']
self.servers.append(server)
Loading…
Cancel
Save