diff --git a/src/gui_qt/_py/basewindow.py b/src/gui_qt/_py/basewindow.py
index a5e7ab9..f680529 100644
--- a/src/gui_qt/_py/basewindow.py
+++ b/src/gui_qt/_py/basewindow.py
@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'src/resources/_ui/basewindow.ui'
#
-# Created by: PyQt5 UI code generator 5.15.2
+# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
@@ -75,7 +75,7 @@ class Ui_BaseWindow(object):
self.horizontalLayout.addWidget(self.splitter)
BaseWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(BaseWindow)
- self.menubar.setGeometry(QtCore.QRect(0, 0, 1386, 24))
+ self.menubar.setGeometry(QtCore.QRect(0, 0, 1386, 20))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
@@ -356,6 +356,8 @@ class Ui_BaseWindow(object):
self.action_draw_object.setObjectName("action_draw_object")
self.actionBugs = QtWidgets.QAction(BaseWindow)
self.actionBugs.setObjectName("actionBugs")
+ self.actionShow_error_log = QtWidgets.QAction(BaseWindow)
+ self.actionShow_error_log.setObjectName("actionShow_error_log")
self.menuSave.addAction(self.actionSave)
self.menuSave.addAction(self.actionExportGraphic)
self.menuSave.addAction(self.action_save_fit_parameter)
@@ -380,6 +382,7 @@ class Ui_BaseWindow(object):
self.menuData.addAction(self.action_cut)
self.menuData.addSeparator()
self.menuData.addAction(self.actionChange_datatypes)
+ self.menuHelp.addAction(self.actionShow_error_log)
self.menuHelp.addAction(self.actionDocumentation)
self.menuHelp.addAction(self.actionUpdate)
self.menuHelp.addAction(self.actionBugs)
@@ -479,7 +482,7 @@ class Ui_BaseWindow(object):
self.retranslateUi(BaseWindow)
self.tabWidget.setCurrentIndex(0)
- self.action_close.triggered.connect(BaseWindow.close)
+ self.action_close.triggered.connect(BaseWindow.close) # type: ignore
QtCore.QMetaObject.connectSlotsByName(BaseWindow)
def retranslateUi(self, BaseWindow):
@@ -608,6 +611,7 @@ class Ui_BaseWindow(object):
self.actionMine.setText(_translate("BaseWindow", "Mine"))
self.action_draw_object.setText(_translate("BaseWindow", "Draw objects..."))
self.actionBugs.setText(_translate("BaseWindow", "Bugs! Problems! Wishes!"))
+ self.actionShow_error_log.setText(_translate("BaseWindow", "Show error log"))
from ..data.datawidget.datawidget import DataWidget
from ..data.integral_widget import IntegralWidget
from ..data.point_select import PointSelectWidget
diff --git a/src/gui_qt/lib/logger.py b/src/gui_qt/lib/logger.py
new file mode 100644
index 0000000..43b6bb1
--- /dev/null
+++ b/src/gui_qt/lib/logger.py
@@ -0,0 +1,114 @@
+import sys
+from pathlib import Path
+
+from .codeeditor import _make_textformats
+from ..Qt import QtWidgets, QtCore, QtGui
+from nmreval.configs import config_paths
+
+
+STYLES = {'INFO': _make_textformats('black'),
+ 'WARNING': _make_textformats('blue'),
+ 'ERROR': _make_textformats('red', 'bold'),
+ 'DEBUG': _make_textformats('black', 'italic'),
+ 'file': _make_textformats('red', 'italic'),
+ 'PyError': _make_textformats('red', 'bold-italic')}
+
+
+class LogHighlighter(QtGui.QSyntaxHighlighter):
+ msg = ['INFO', 'DEBUG', 'ERROR', 'WARNING']
+
+ def __init__(self, parent):
+ super(LogHighlighter, self).__init__(parent)
+
+ rules = list()
+ rules += [(r'\b\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2} - %s - .*' % m, 0, STYLES[m]) for m in LogHighlighter.msg]
+ rules += [(r'\b[A-Z]\w*Error: .*\b', 0, STYLES['PyError'])]
+ rules += [(r'\bFile .*', 0, STYLES['file'])]
+
+ self.rules = [(QtCore.QRegExp(pat), index, fmt) for (pat, index, fmt) in rules]
+
+ def highlightBlock(self, text):
+ """Apply syntax highlighting to the given block of text.
+ """
+ # Do other syntax formatting
+ for expression, nth, format in self.rules:
+ index = expression.indexIn(text, 0)
+
+ while index >= 0:
+ # We actually want the index of the nth match
+ index = expression.pos(nth)
+ try:
+ length = expression.cap(nth).length()
+ except AttributeError:
+ length = len(expression.cap(nth))
+ self.setFormat(index, length, format)
+ index = expression.indexIn(text, index + length)
+
+ self.setCurrentBlockState(0)
+
+ def match_multiline(self, text, delimiter, in_state, style):
+ if self.previousBlockState() == in_state:
+ start = 0
+ add = 0
+ else:
+ start = delimiter.indexIn(text)
+ add = delimiter.matchedLength()
+
+ while start >= 0:
+ end = delimiter.indexIn(text, start + add)
+ if end >= add:
+ length = end - start + add + delimiter.matchedLength()
+ self.setCurrentBlockState(0)
+ else:
+ self.setCurrentBlockState(in_state)
+ try:
+ length = text.length() - start + add
+ except AttributeError:
+ length = len(text) - start + add
+ # Apply formatting
+ self.setFormat(start, length, style)
+ # Look for the next match
+ start = delimiter.indexIn(text, start + length)
+
+ # Return True if still inside a multi-line string, False otherwise
+ if self.currentBlockState() == in_state:
+ return True
+ else:
+ return False
+
+
+class QLog(QtWidgets.QDialog):
+ def __init__(self, parent=None):
+ super(QLog, self).__init__(parent=parent)
+
+ self._initUi()
+
+ self.logfile = config_paths() / 'errors.log'
+
+ self.read_log()
+
+ def _initUi(self):
+
+ self.resize(960, 640)
+ layout = QtWidgets.QVBoxLayout()
+ self.plainTextEdit = QtWidgets.QPlainTextEdit()
+ self.plainTextEdit.highlight = LogHighlighter(self.plainTextEdit.document())
+ self.plainTextEdit.setReadOnly(True)
+ self.plainTextEdit.setMaximumBlockCount(50)
+ layout.addWidget(self.plainTextEdit)
+
+ self.buttonBox = QtWidgets.QDialogButtonBox()
+ self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close)
+ self.buttonBox.accepted.connect(self.accept)
+ self.buttonBox.rejected.connect(self.reject)
+
+ layout.addWidget(self.buttonBox)
+
+ self.setLayout(layout)
+
+ def read_log(self):
+ with Path(self.logfile).open('r') as f:
+ text = f.readlines()
+
+ for lines in text[-100:]:
+ self.plainTextEdit.appendPlainText(lines[:-1])
diff --git a/src/gui_qt/main/mainwindow.py b/src/gui_qt/main/mainwindow.py
index c9fc62b..19877d5 100644
--- a/src/gui_qt/main/mainwindow.py
+++ b/src/gui_qt/main/mainwindow.py
@@ -1019,3 +1019,10 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
def look_for_update(self):
w = UpdateDialog(parent=self)
w.show()
+
+ @QtCore.pyqtSlot(name='on_actionShow_error_log_triggered')
+ def open_log(self):
+ from ..lib.logger import QLog
+
+ QLog(parent=self).show()
+
diff --git a/src/resources/_ui/basewindow.ui b/src/resources/_ui/basewindow.ui
index 0cb9372..5edcf51 100644
--- a/src/resources/_ui/basewindow.ui
+++ b/src/resources/_ui/basewindow.ui
@@ -136,7 +136,7 @@
0
0
1386
- 24
+ 20