From a1f59c9b39b4b69491a9cabc6b0095e1df0b7f43 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Mon, 23 Oct 2023 17:06:53 +0200 Subject: [PATCH 1/2] do not use messagebox for exceptions --- src/silx/app/view/main.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/silx/app/view/main.py b/src/silx/app/view/main.py index 820bc6d930..f24ba55855 100644 --- a/src/silx/app/view/main.py +++ b/src/silx/app/view/main.py @@ -31,6 +31,7 @@ import os import signal import sys +import traceback from silx.app.utils import parseutils @@ -136,7 +137,6 @@ def sigintHandler(*args): qt.QApplication.quit() signal.signal(signal.SIGINT, sigintHandler) - sys.excepthook = qt.exceptionHandler timer = qt.QTimer() timer.start(500) @@ -155,6 +155,21 @@ def sigintHandler(*args): window = createWindow(parent=None, settings=settings) window.setAttribute(qt.Qt.WA_DeleteOnClose, True) + def exceptHook(type_, value, trace): + _logger.error("An error occured in silx view:") + _logger.error("%s %s %s", type_, value, ''.join(traceback.format_tb(trace))) + try: + label = qt.QLabel() + label.setText('⚠ Error') + label.setToolTip("An error occured:\nCheck error messages in the console") + + statusBar = window.statusBar() + statusBar.addPermanentWidget(label) + except Exception: + pass + sys.excepthook = exceptHook + + if options.use_opengl_plot: # It have to be done after the settings (after the Viewer creation) silx.config.DEFAULT_PLOT_BACKEND = "opengl" From 9516630680b1c1c6d46356e8457cbbdf11f6a45a Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Tue, 24 Oct 2023 17:52:49 +0200 Subject: [PATCH 2/2] Move error button to menu bar + store/display last error message --- src/silx/app/view/Viewer.py | 42 +++++++++++++++++++++++++++++++++++++ src/silx/app/view/main.py | 7 +------ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/silx/app/view/Viewer.py b/src/silx/app/view/Viewer.py index 327e86e76e..5f32c645fb 100644 --- a/src/silx/app/view/Viewer.py +++ b/src/silx/app/view/Viewer.py @@ -22,6 +22,8 @@ # ############################################################################*/ """Browse a data file with a GUI""" +from __future__ import annotations + __authors__ = ["V. Valls"] __license__ = "MIT" __date__ = "15/01/2019" @@ -30,6 +32,8 @@ import os import logging import functools +import traceback +from types import TracebackType from typing import Optional import silx.io.nxdata @@ -64,6 +68,8 @@ def __init__(self, parent=None, settings=None): silxIcon = icons.getQIcon("silx") self.setWindowIcon(silxIcon) + self.__error = "" + self.__context = self.createApplicationContext(settings) self.__context.restoreLibrarySettings() @@ -743,6 +749,14 @@ def createMenus(self): helpMenu.addAction(self._aboutAction) helpMenu.addAction(self._documentationAction) + self.__errorButton = qt.QToolButton(self) + self.__errorButton.setIcon( + self.style().standardIcon(qt.QStyle.SP_MessageBoxWarning)) + self.__errorButton.setToolTip("An error occured!\nClick to display last error\nor check messages in the console") + self.__errorButton.setVisible(False) + self.__errorButton.clicked.connect(self.__errorButtonClicked) + self.menuBar().setCornerWidget(self.__errorButton) + def open(self): dialog = self.createFileDialog() if self.__dialogState is None: @@ -950,3 +964,31 @@ def customContextMenu(self, event): action = qt.QAction("Synchronize %s" % obj.local_filename, event.source()) action.triggered.connect(lambda: self.__synchronizeH5pyObject(h5)) menu.addAction(action) + + def __errorButtonClicked(self): + button = qt.QMessageBox.warning( + self, + "Error", + self.getError(), + qt.QMessageBox.Reset | qt.QMessageBox.Close, + qt.QMessageBox.Close, + ) + if button == qt.QMessageBox.Reset: + self.setError("") + + def getError(self) -> str: + """Returns error information string""" + return self.__error + + def setError(self, error: str): + """Set error information string""" + if error == self.__error: + return + + self.__error = error + self.__errorButton.setVisible(error != "") + + def setErrorFromException(self, type_: type[BaseException], value: BaseException, trace: TracebackType): + """Set information about the last exception that occured""" + formattedTrace = '\n'.join(traceback.format_tb(trace)) + self.setError(f"{type_.__name__}:\n{value}\n\n{formattedTrace}") diff --git a/src/silx/app/view/main.py b/src/silx/app/view/main.py index f24ba55855..50b4399c4c 100644 --- a/src/silx/app/view/main.py +++ b/src/silx/app/view/main.py @@ -159,12 +159,7 @@ def exceptHook(type_, value, trace): _logger.error("An error occured in silx view:") _logger.error("%s %s %s", type_, value, ''.join(traceback.format_tb(trace))) try: - label = qt.QLabel() - label.setText('⚠ Error') - label.setToolTip("An error occured:\nCheck error messages in the console") - - statusBar = window.statusBar() - statusBar.addPermanentWidget(label) + window.setErrorFromException(type_, value, trace) except Exception: pass sys.excepthook = exceptHook