Browse Source

add initial channel close dialog

patch-4
Sander van Grieken 3 years ago
parent
commit
e69fc739ca
  1. 21
      electrum/gui/qml/components/ChannelDetails.qml
  2. 130
      electrum/gui/qml/components/CloseChannelDialog.qml
  3. 49
      electrum/gui/qml/qechanneldetails.py
  4. 2
      electrum/gui/qml/qechannellistmodel.py

21
electrum/gui/qml/components/ChannelDetails.qml

@ -31,17 +31,11 @@ Pane {
icon.color: 'transparent'
action: Action {
text: qsTr('Close channel');
enabled: false
onTriggered: {}
//icon.source: '../../icons/wallet.png'
}
}
MenuItem {
icon.color: 'transparent'
action: Action {
text: qsTr('Force-close');
enabled: false
onTriggered: {}
enabled: channeldetails.canClose
onTriggered: {
var dialog = closechannel.createObject(root, { 'channelid': channelid })
dialog.open()
}
//icon.source: '../../icons/wallet.png'
}
}
@ -245,4 +239,9 @@ Pane {
id: share
GenericShareDialog {}
}
Component {
id: closechannel
CloseChannelDialog {}
}
}

130
electrum/gui/qml/components/CloseChannelDialog.qml

@ -0,0 +1,130 @@
import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.3
import QtQuick.Controls.Material 2.0
import org.electrum 1.0
import "controls"
Dialog {
id: dialog
width: parent.width
height: parent.height
property string channelid
title: qsTr('Close Channel')
standardButtons: closing ? 0 : Dialog.Cancel
modal: true
parent: Overlay.overlay
Overlay.modal: Rectangle {
color: "#aa000000"
}
property bool closing: false
closePolicy: Popup.NoAutoClose
GridLayout {
id: layout
width: parent.width
height: parent.height
columns: 2
Label {
text: qsTr('Channel name')
color: Material.accentColor
}
Label {
text: channeldetails.name
}
Label {
text: qsTr('Short channel ID')
color: Material.accentColor
}
Label {
text: channeldetails.short_cid
}
InfoTextArea {
Layout.columnSpan: 2
text: qsTr(channeldetails.message_force_close)
}
ColumnLayout {
Layout.columnSpan: 2
Layout.alignment: Qt.AlignHCenter
ButtonGroup {
id: closetypegroup
}
RadioButton {
ButtonGroup.group: closetypegroup
property string closetype: 'cooperative'
checked: true
enabled: !closing && channeldetails.canCoopClose
text: qsTr('Cooperative close')
}
RadioButton {
ButtonGroup.group: closetypegroup
property string closetype: 'force'
enabled: !closing && channeldetails.canForceClose
text: qsTr('Request Force-close')
}
}
Button {
Layout.columnSpan: 2
Layout.alignment: Qt.AlignHCenter
text: qsTr('Close')
enabled: !closing
onClicked: {
closing = true
channeldetails.close_channel(closetypegroup.checkedButton.closetype)
}
}
ColumnLayout {
Layout.columnSpan: 2
Layout.alignment: Qt.AlignHCenter
Label {
id: errorText
visible: !closing && errorText
wrapMode: Text.Wrap
Layout.preferredWidth: layout.width
}
Label {
text: qsTr('Closing...')
visible: closing
}
BusyIndicator {
visible: closing
}
}
Item { Layout.fillHeight: true; Layout.preferredWidth: 1 }
}
ChannelDetails {
id: channeldetails
wallet: Daemon.currentWallet
channelid: dialog.channelid
onChannelCloseSuccess: {
closing = false
dialog.close()
}
onChannelCloseFailed: {
closing = false
errorText.text = message
}
}
}

49
electrum/gui/qml/qechanneldetails.py

@ -1,8 +1,13 @@
import asyncio
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, Q_ENUMS
from electrum.i18n import _
from electrum.gui import messages
from electrum.logging import get_logger
from electrum.util import register_callback, unregister_callback
from electrum.lnutil import LOCAL, REMOTE
from electrum.lnchannel import ChanCloseOption
from .qewallet import QEWallet
from .qetypes import QEAmount
@ -15,6 +20,8 @@ class QEChannelDetails(QObject):
_channel = None
channelChanged = pyqtSignal()
channelCloseSuccess = pyqtSignal()
channelCloseFailed = pyqtSignal([str], arguments=['message'])
def __init__(self, parent=None):
super().__init__(parent)
@ -57,7 +64,7 @@ class QEChannelDetails(QObject):
def load(self):
lnchannels = self._wallet.wallet.lnworker.channels
for channel in lnchannels.values():
self._logger.debug('%s == %s ?' % (self._channelid, channel.channel_id))
#self._logger.debug('%s == %s ?' % (self._channelid, channel.channel_id))
if self._channelid == channel.channel_id.hex():
self._channel = channel
self.channelChanged.emit()
@ -115,22 +122,54 @@ class QEChannelDetails(QObject):
def isOpen(self):
return self._channel.is_open()
@pyqtProperty(bool, notify=channelChanged)
def canClose(self):
return self.canCoopClose or self.canForceClose
@pyqtProperty(bool, notify=channelChanged)
def canCoopClose(self):
return ChanCloseOption.COOP_CLOSE in self._channel.get_close_options()
@pyqtProperty(bool, notify=channelChanged)
def canForceClose(self):
return ChanCloseOption.LOCAL_FCLOSE in self._channel.get_close_options()
@pyqtProperty(str, notify=channelChanged)
def message_force_close(self, notify=channelChanged):
return _(messages.MSG_REQUEST_FORCE_CLOSE)
@pyqtSlot()
def freezeForSending(self):
lnworker = self._channel.lnworker
if lnworker.channel_db or lnworker.is_trampoline_peer(self._channel.node_id):
#self.is_frozen_for_sending = not self.is_frozen_for_sending
self._channel.set_frozen_for_sending(not self.frozenForSending)
self.channelChanged.emit()
else:
self._logger.debug('TODO: messages.MSG_NON_TRAMPOLINE_CHANNEL_FROZEN_WITHOUT_GOSSIP')
self._logger.debug(messages.MSG_NON_TRAMPOLINE_CHANNEL_FROZEN_WITHOUT_GOSSIP)
@pyqtSlot()
def freezeForReceiving(self):
lnworker = self._channel.lnworker
if lnworker.channel_db or lnworker.is_trampoline_peer(self._channel.node_id):
#self.is_frozen_for_sending = not self.is_frozen_for_sending
self._channel.set_frozen_for_receiving(not self.frozenForReceiving)
self.channelChanged.emit()
else:
self._logger.debug('TODO: messages.MSG_NON_TRAMPOLINE_CHANNEL_FROZEN_WITHOUT_GOSSIP')
self._logger.debug(messages.MSG_NON_TRAMPOLINE_CHANNEL_FROZEN_WITHOUT_GOSSIP)
# this method assumes the qobject is not destroyed before the close either fails or succeeds
@pyqtSlot(str)
def close_channel(self, closetype):
async def do_close(closetype, channel_id):
try:
if closetype == 'force':
await self._wallet.wallet.lnworker.request_force_close(channel_id)
else:
await self._wallet.wallet.lnworker.close_channel(channel_id)
self.channelCloseSuccess.emit()
except Exception as e:
self._logger.exception("Could not close channel: " + repr(e))
self.channelCloseFailed.emit(_('Could not close channel: ') + repr(e))
loop = self._wallet.wallet.network.asyncio_loop
coro = do_close(closetype, self._channel.channel_id)
asyncio.run_coroutine_threadsafe(coro, loop)

2
electrum/gui/qml/qechannellistmodel.py

@ -117,7 +117,7 @@ class QEChannelListModel(QAbstractListModel):
def on_channel_updated(self, channel):
i = 0
for c in self.channels:
if c['cid'] == channel.channel_id:
if c['cid'] == channel.channel_id.hex():
self.do_update(i,channel)
break
i = i + 1

Loading…
Cancel
Save