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])