forked from IPKM/nmreval
		
	run scripts Co-authored-by: Dominik Demuth <dominik.demuth@physik.tu-darmstadt.de> Reviewed-on: IPKM/nmreval#291
		
			
				
	
	
		
			144 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import logging
 | |
| from pathlib import Path
 | |
| 
 | |
| from PyQt5 import QtWidgets
 | |
| 
 | |
| from ..editors.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])
 | |
| 
 | |
| 
 | |
| class ConsoleDock(QtWidgets.QDockWidget):
 | |
|     def __init__(self, parent=None):
 | |
|         super().__init__(parent=parent)
 | |
| 
 | |
|         self.code = QtWidgets.QPlainTextEdit(parent)
 | |
|         self.code.highlight = LogHighlighter(self.code.document())
 | |
|         self.code.setReadOnly(True)
 | |
|         self.code.setMaximumBlockCount(50)
 | |
|         self.setWidget(self.code)
 | |
| 
 | |
| 
 | |
| class QTextHandler(logging.Handler):
 | |
|     def __init__(self, parent):
 | |
|         super().__init__()
 | |
| 
 | |
|         self.console = ConsoleDock(parent)
 | |
|         self.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
 | |
|         self.setLevel(logging.WARNING)
 | |
| 
 | |
|     def emit(self, record):
 | |
|         msg = self.format(record)
 | |
|         self.console.code.appendPlainText(msg)
 | |
|         self.console.show()
 |