Browse Source

qml: fixes for CloseChannelDialog;

- split RequestForceClose and LocalForceClose options, as request force close is only available if connected.
- disable no close policy on dialog, as it locks the user in the dialog if no succesful close is initiated.
  what this intended to do is keep the backing object QEChannelDetails alive until a result is obtained, to avoid
  exceptions when emitting the result signal. this is now handled more robustly, the user can leave the dialog
  without triggering exceptions later.
master
Sander van Grieken 2 years ago
parent
commit
0fb47c87d2
  1. 10
      electrum/gui/qml/components/CloseChannelDialog.qml
  2. 29
      electrum/gui/qml/qechanneldetails.py

10
electrum/gui/qml/components/CloseChannelDialog.qml

@ -20,8 +20,6 @@ ElDialog {
property string _closing_method property string _closing_method
closePolicy: Popup.NoAutoClose
padding: 0 padding: 0
ColumnLayout { ColumnLayout {
@ -120,14 +118,14 @@ ElDialog {
id: closetypeRemoteForce id: closetypeRemoteForce
ButtonGroup.group: closetypegroup ButtonGroup.group: closetypegroup
property string closetype: 'remote_force' property string closetype: 'remote_force'
enabled: !channeldetails.isClosing && channeldetails.canForceClose enabled: !channeldetails.isClosing && channeldetails.canRequestForceClose
text: qsTr('Request Force-close') text: qsTr('Request Force-close')
} }
ElRadioButton { ElRadioButton {
id: closetypeLocalForce id: closetypeLocalForce
ButtonGroup.group: closetypegroup ButtonGroup.group: closetypegroup
property string closetype: 'local_force' property string closetype: 'local_force'
enabled: !channeldetails.isClosing && channeldetails.canForceClose && !channeldetails.isBackup enabled: !channeldetails.isClosing && channeldetails.canLocalForceClose && !channeldetails.isBackup
text: qsTr('Local Force-close') text: qsTr('Local Force-close')
} }
} }
@ -213,8 +211,10 @@ ElDialog {
// init default choice // init default choice
if (channeldetails.canCoopClose) if (channeldetails.canCoopClose)
closetypeCoop.checked = true closetypeCoop.checked = true
else else if (channeldetails.canRequestForceClose)
closetypeRemoteForce.checked = true closetypeRemoteForce.checked = true
else
closetypeLocalForce.checked = true
} }
onChannelCloseSuccess: { onChannelCloseSuccess: {

29
electrum/gui/qml/qechanneldetails.py

@ -160,15 +160,19 @@ class QEChannelDetails(AuthMixin, QObject, QtEventListener):
@pyqtProperty(bool, notify=channelChanged) @pyqtProperty(bool, notify=channelChanged)
def canClose(self): def canClose(self):
return self.canCoopClose or self.canForceClose return self.canCoopClose or self.canLocalForceClose or self.canRequestForceClose
@pyqtProperty(bool, notify=channelChanged) @pyqtProperty(bool, notify=channelChanged)
def canCoopClose(self): def canCoopClose(self):
return ChanCloseOption.COOP_CLOSE in self._channel.get_close_options() return ChanCloseOption.COOP_CLOSE in self._channel.get_close_options()
@pyqtProperty(bool, notify=channelChanged) @pyqtProperty(bool, notify=channelChanged)
def canForceClose(self): def canLocalForceClose(self):
return any([o in [ChanCloseOption.LOCAL_FCLOSE, ChanCloseOption.REQUEST_REMOTE_FCLOSE] for o in self._channel.get_close_options()]) return ChanCloseOption.LOCAL_FCLOSE in self._channel.get_close_options()
@pyqtProperty(bool, notify=channelChanged)
def canRequestForceClose(self):
return ChanCloseOption.REQUEST_REMOTE_FCLOSE in self._channel.get_close_options()
@pyqtProperty(bool, notify=channelChanged) @pyqtProperty(bool, notify=channelChanged)
def canDelete(self): def canDelete(self):
@ -234,6 +238,18 @@ class QEChannelDetails(AuthMixin, QObject, QtEventListener):
def do_close_channel(self, closetype): def do_close_channel(self, closetype):
channel_id = self._channel.channel_id channel_id = self._channel.channel_id
def handle_result(success: bool, msg: str = ''):
try:
if success:
self.channelCloseSuccess.emit()
else:
self.channelCloseFailed.emit(msg)
self._is_closing = False
self.isClosingChanged.emit()
except RuntimeError: # QEChannelDetails might be deleted at this point if the user closed the dialog.
pass
def do_close(): def do_close():
try: try:
self._is_closing = True self._is_closing = True
@ -245,13 +261,10 @@ class QEChannelDetails(AuthMixin, QObject, QtEventListener):
else: else:
self._wallet.wallet.network.run_from_another_thread(self._wallet.wallet.lnworker.close_channel(channel_id)) self._wallet.wallet.network.run_from_another_thread(self._wallet.wallet.lnworker.close_channel(channel_id))
self._logger.debug('Channel close successful') self._logger.debug('Channel close successful')
self.channelCloseSuccess.emit() handle_result(True)
except Exception as e: except Exception as e:
self._logger.exception("Could not close channel: " + repr(e)) self._logger.exception("Could not close channel: " + repr(e))
self.channelCloseFailed.emit(_('Could not close channel: ') + repr(e)) handle_result(False, _('Could not close channel: ') + repr(e))
finally:
self._is_closing = False
self.isClosingChanged.emit()
threading.Thread(target=do_close, daemon=True).start() threading.Thread(target=do_close, daemon=True).start()

Loading…
Cancel
Save