diff --git a/src/sas/qtgui/MainWindow/GuiManager.py b/src/sas/qtgui/MainWindow/GuiManager.py
index e3d787116e..f94d7b6cb5 100644
--- a/src/sas/qtgui/MainWindow/GuiManager.py
+++ b/src/sas/qtgui/MainWindow/GuiManager.py
@@ -6,7 +6,7 @@
from packaging.version import Version
from PySide6.QtCore import QLocale, Qt
-from PySide6.QtGui import QStandardItem
+from PySide6.QtGui import QStandardItem, QTextCursor
from PySide6.QtWidgets import QDockWidget, QLabel, QMessageBox, QProgressBar, QTextBrowser
from twisted.internet import reactor
@@ -80,9 +80,6 @@ def __init__(self, parent=None):
# Decide on a locale
QLocale.setDefault(QLocale('en_US'))
- # Redefine exception hook to not explicitly crash the app.
- sys.excepthook = self.info
-
# Ensure the user directory has all required layout and files
create_user_files_if_needed()
@@ -124,9 +121,6 @@ def __init__(self, parent=None):
if self.WhatsNew.has_new_messages(): # Not a static method
self.WhatsNew.show()
- def info(self, type, value, tb):
- logger.error("".join(traceback.format_exception(type, value, tb)))
-
def addWidgets(self):
"""
Populate the main window with widgets
@@ -139,6 +133,8 @@ def addWidgets(self):
self.logDockWidget.setVisible(False)
self.listWidget = QTextBrowser()
+ # We could put error log styling here:
+ # self.listWidget.setStyleSheet("QTextBrowser { line-height: 1.0; }")
self.logDockWidget.setWidget(self.listWidget)
self._workspace.addDockWidget(Qt.BottomDockWidgetArea, self.logDockWidget)
@@ -244,7 +240,6 @@ def addCategories():
model_list = ModelManager().cat_model_list()
CategoryInstaller.check_install(model_list=model_list)
except Exception:
- import traceback
logger.error("Category manager: could not load SasView models")
logger.error(traceback.format_exc())
@@ -500,7 +495,18 @@ def appendLog(self, signal):
"""Appends a message to the list widget in the Log Explorer. Use this
instead of listWidget.insertPlainText() to facilitate auto-scrolling"""
(message, record) = signal
- self.listWidget.append(message.strip())
+
+ # Move cursor to the end of text and append the next log message;
+ # Don't use append() to add the block since it messes up the formatting
+ # we do is SasviewLogger. Instead put a
between every entry.
+ # Scroll the text so that it is visible.
+ cursor = self.listWidget.textCursor()
+ cursor.movePosition(QTextCursor.End)
+ cursor.insertHtml(f"\n
\n{message.strip()}")
+ self.listWidget.ensureCursorVisible()
+
+ # Show the mess inside the log widget. Qt is doing too much!
+ # print("\n\n===log contains: ", self.listWidget.toHtml())
# Display log if message is warning (30) or higher
# 10: Debug
@@ -623,9 +629,6 @@ def actionWhatsNew(self):
def showWelcomeMessage(self):
""" Show the Welcome panel, when required """
- # Assure the welcome screen is requested
- show_welcome_widget = True
-
if config.SHOW_WELCOME_PANEL:
self.actionWelcome()
diff --git a/src/sas/qtgui/MainWindow/MainWindow.py b/src/sas/qtgui/MainWindow/MainWindow.py
index 7a49aa5ff8..48cda366c3 100644
--- a/src/sas/qtgui/MainWindow/MainWindow.py
+++ b/src/sas/qtgui/MainWindow/MainWindow.py
@@ -1,5 +1,6 @@
import logging
import sys
+import traceback
from importlib import resources
from PySide6.QtCore import Qt, QTimer
@@ -16,6 +17,9 @@
from .UI.MainWindowUI import Ui_SasView
logger = logging.getLogger(__name__)
+def log_uncaught_exception(type, value, tb):
+ formatted_tb = "".join(traceback.format_exception(type, value, tb))
+ logger.error(f"--- Uncaught exception ---\n{formatted_tb.strip()}")
class MainSasViewWindow(QMainWindow, Ui_SasView):
# Main window of the application
@@ -113,6 +117,9 @@ def run_sasview(file_list: list[str] | None = None):
# Show the main SV window
mainwindow = MainSasViewWindow()
+ # Redirect uncaught exceptions to logger
+ sys.excepthook = log_uncaught_exception
+
# no more splash screen
splash.finish(mainwindow)
diff --git a/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py b/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
index a09f7c0a96..d91c215b67 100644
--- a/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
+++ b/src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
@@ -102,9 +102,6 @@ def __init__(self, parent: QtWidgets.QWidget | None = None, data: Any | None = N
# Which tab is this widget displayed in?
self.tab_id = tab_id
- import sys
- sys.excepthook = self.info
-
# Globals
self.initializeGlobals()
@@ -189,9 +186,6 @@ def __init__(self, parent: QtWidgets.QWidget | None = None, data: Any | None = N
self.label_17.setStyleSheet(new_font)
self.label_19.setStyleSheet(new_font)
- def info(self, type: Any, value: Any, tb: Any) -> None:
- logger.error("".join(traceback.format_exception(type, value, tb)))
-
@property
def logic(self) -> FittingLogic:
# make sure the logic contains at least one element
diff --git a/src/sas/qtgui/Utilities/ModelEditors/TabbedEditor/TabbedModelEditor.py b/src/sas/qtgui/Utilities/ModelEditors/TabbedEditor/TabbedModelEditor.py
index 615c2d3bc2..498ce0cb8f 100644
--- a/src/sas/qtgui/Utilities/ModelEditors/TabbedEditor/TabbedModelEditor.py
+++ b/src/sas/qtgui/Utilities/ModelEditors/TabbedEditor/TabbedModelEditor.py
@@ -466,10 +466,8 @@ def findFirstError(self, full_path: str | Path) -> int:
logger.error(msg)
# print four last lines of the stack trace
# this will point out the exact line failing
- all_lines = traceback.format_exc().split("\n")
+ all_lines = traceback.format_exc().strip().split("\n")
last_lines = all_lines[-4:]
- traceback_to_show = "\n".join(last_lines)
- logger.error(traceback_to_show)
# Set the status bar message
# GuiUtils.communicator.statusBarUpdateSignal.emit("Model check failed")
diff --git a/src/sas/qtgui/Utilities/SasviewLogger.py b/src/sas/qtgui/Utilities/SasviewLogger.py
index 1a9a36a355..a899b561d4 100644
--- a/src/sas/qtgui/Utilities/SasviewLogger.py
+++ b/src/sas/qtgui/Utilities/SasviewLogger.py
@@ -16,7 +16,14 @@ def format(self, record):
if record.levelname in self.LOG_COLORS:
level_style = f' style="color: {self.LOG_COLORS[record.levelname]}"'
- return logging.Formatter(fmt=self.LOG_FORMAT.format(level_style), datefmt=self.DATE_FORMAT).format(record)
+ # Format the timestamp, etc.
+ msg = logging.Formatter(fmt=self.LOG_FORMAT.format(level_style), datefmt=self.DATE_FORMAT).format(record)
+
+ # If it is a multiline error message then put the additional lines in a
block
+ if "\n" in msg:
+ lead, tail = msg.split("\n", 1)
+ msg = f"{lead}\n{tail}"
+ return msg
class QtPostman(QObject):
messageWritten = Signal(object)