diff --git a/pyproject.toml b/pyproject.toml index 3d4ce05..4fcb423 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ jmdaemon = [ jmfrost = [ ] jmqtui = [ - "PySide6==6.9.0", # https://bugreports.qt.io/browse/QTBUG-88688 + "PySide6==6.9.3", # https://bugreports.qt.io/browse/QTBUG-88688 "qrcode[pil]==7.3.1", 'pywin32; platform_system == "Windows"', "qt5reactor@git+https://github.com/zebra-lucky/qt5reactor@update_versioneer#egg=qt5reactor", diff --git a/scripts/joinmarket-qt.py b/scripts/joinmarket-qt.py index fc3a0c4..681b5d3 100755 --- a/scripts/joinmarket-qt.py +++ b/scripts/joinmarket-qt.py @@ -1683,24 +1683,38 @@ class JMMainWindow(QMainWindow): # a flag to indicate that shutdown should not # depend on user input self.unconditional_shutdown = False + self.close_event_confirmed = False def closeEvent(self, event): - if self.unconditional_shutdown: - JMQtMessageBox(self, - "RPC connection is lost; shutting down.", - mbtype='crit', - title="Error") - reply = QMessageBox.Yes - else: - quit_msg = "Are you sure you want to quit?" - reply = JMQtMessageBox(self, quit_msg, mbtype='question') - if reply == QMessageBox.Yes: + + if self.close_event_confirmed: event.accept() if self.reactor.threadpool is not None: self.reactor.threadpool.stop() stop_reactor() + return + + def finished_cb(result): + if result == QMessageBox.Yes: + self.close_event_confirmed = True + self.close() + elif result == QMessageBox.Ok and self.unconditional_shutdown: + self.close_event_confirmed = True + self.close() + + if self.unconditional_shutdown: + quit_msg = "RPC connection is lost; shutting down." + asyncio.ensure_future( + JMQtMessageBox( + self, quit_msg, mbtype='crit', title="Error", + finished_cb=finished_cb)) else: - event.ignore() + quit_msg = "Are you sure you want to quit?" + asyncio.ensure_future( + JMQtMessageBox( + self, quit_msg, mbtype='question', + finished_cb=finished_cb)) + event.ignore() def initUI(self): self.statusBar().showMessage("Ready") diff --git a/scripts/qtsupport.py b/scripts/qtsupport.py index d1f6658..83ce4fd 100644 --- a/scripts/qtsupport.py +++ b/scripts/qtsupport.py @@ -148,54 +148,70 @@ donation_more_message = '\n'.join( 'is no change output that can be linked with your inputs later.']) """ -def JMQtMessageBox(obj, msg, mbtype='info', title='', detailed_text= None): - mbtypes = {'info': QMessageBox.information, - 'crit': QMessageBox.critical, - 'warn': QMessageBox.warning, - 'question': QMessageBox.question} + +async def JMQtMessageBox(parent, msg, mbtype='info', title='', + detailed_text=None, finished_cb=None): title = "JoinmarketQt - " + title + result_fut = asyncio.get_event_loop().create_future() + + class JMQtDMessageBox(QMessageBox, QtCore.QObject): + + def __init__(self, parent): + QMessageBox.__init__(self, parent=parent) + self.setSizeGripEnabled(True) + self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.layout().setSizeConstraint(QLayout.SetMaximumSize) + + def resizeEvent(self, event): + self.setMinimumHeight(0) + self.setMaximumHeight(16777215) + self.setMinimumWidth(0) + self.setMaximumWidth(16777215) + result = super().resizeEvent(event) + + if detailed_text: + assert mbtype == 'info' + details_box = self.findChild(QTextEdit) + if details_box is not None: + details_box.setMinimumHeight(0) + details_box.setMaximumHeight(16777215) + details_box.setMinimumWidth(0) + details_box.setMaximumWidth(16777215) + details_box.setSizePolicy(QSizePolicy.Expanding, + QSizePolicy.Expanding) + return result + + @QtCore.Slot(QMessageBox.StandardButton) + def on_finished(self, button): + result_fut.set_result(button) + + mb = JMQtDMessageBox(parent) if mbtype == 'question': - return QMessageBox.question(obj, title, msg, QMessageBox.Yes, - QMessageBox.No) + icon = QMessageBox.Question + elif mbtype == 'warn': + icon = QMessageBox.Warning + elif mbtype == 'crit': + icon = QMessageBox.Critical else: - if detailed_text: - assert mbtype == 'info' - - class JMQtDMessageBox(QMessageBox): - def __init__(self): - QMessageBox.__init__(self) - self.setSizeGripEnabled(True) - self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) - self.layout().setSizeConstraint(QLayout.SetMaximumSize) - def resizeEvent(self, event): - self.setMinimumHeight(0) - self.setMaximumHeight(16777215) - self.setMinimumWidth(0) - self.setMaximumWidth(16777215) - result = super().resizeEvent(event) - details_box = self.findChild(QTextEdit) - if details_box is not None: - details_box.setMinimumHeight(0) - details_box.setMaximumHeight(16777215) - details_box.setMinimumWidth(0) - details_box.setMaximumWidth(16777215) - details_box.setSizePolicy(QSizePolicy.Expanding, - QSizePolicy.Expanding) - return result - - b = JMQtDMessageBox() - b.setIcon(QMessageBox.Information) - b.setWindowTitle(title) - b.setText(msg) - b.setDetailedText(detailed_text) - b.setStandardButtons(QMessageBox.Ok) - b.open(self.message_box_clicked) - else: - mbtypes[mbtype](obj, title, msg) + icon = QMessageBox.Information + mb.setIcon(icon) + mb.setWindowTitle(title) + mb.setText(msg) + if detailed_text: + mb.setDetailedText(detailed_text) + if mbtype == 'question': + mb.setStandardButtons(QMessageBox.Yes | QMessageBox.No) + mb.setDefaultButton(QMessageBox.No) + else: + mb.setStandardButtons(QMessageBox.Ok) + mb.setDefaultButton(QMessageBox.NoButton) + mb.finished.connect(mb.on_finished) + mb.open() + result = await result_fut + if finished_cb is not None: + finished_cb(result) + return result - @QtCore.Slot(QMessageBox.StandardButton) - def message_box_clicked(self, button_id): - print('QMessageBox.StandardButton', button_id) class QtHandler(logging.Handler):