gui: logwindow improvements

* make state consistent with menu action
* colorize
* add time to log message

Change-Id: I0c0800ddb1843b826a6adacf4e4b18d52598acf2
Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/30759
Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
Reviewed-by: Alexander Zaft <a.zaft@fz-juelich.de>
This commit is contained in:
Alexander Zaft 2023-03-23 15:03:00 +01:00 committed by Markus Zolliker
parent 2f730ab444
commit 155efb06bf
4 changed files with 85 additions and 27 deletions

View File

@ -1,45 +1,72 @@
from logging import DEBUG, NOTSET, Handler from logging import NOTSET, Handler
from frappy.gui.qt import QMainWindow, QObject, pyqtSignal from frappy.gui.qt import QMainWindow, QObject, pyqtSignal
from frappy.gui.util import loadUi from frappy.gui.util import Colors, loadUi
class LogWindowHandler(Handler, QObject): class LogWindowHandler(Handler, QObject):
logmessage = pyqtSignal(str, int) logmessage = pyqtSignal(object)
def __init__(self, level=NOTSET): def __init__(self, level=NOTSET):
QObject.__init__(self) QObject.__init__(self)
Handler.__init__(self, level) Handler.__init__(self, level)
self.log = []
def emit(self, record): def emit(self, record):
self.logmessage.emit(record.getMessage(), record.levelno) self.log.append(record)
self.logmessage.emit(record)
def getEntries(self, level):
return [rec for rec in self.log if rec.levelno >= level]
class LogWindow(QMainWindow): class LogWindow(QMainWindow):
closed = pyqtSignal()
levels = {'Debug':10, 'Info':20, 'Warning':30, 'Error':40} levels = {'Debug':10, 'Info':20, 'Warning':30, 'Error':40}
def __init__(self, logger, parent=None):
def __init__(self, handler, parent=None):
super().__init__(parent) super().__init__(parent)
loadUi(self, 'logwindow.ui') loadUi(self, 'logwindow.ui')
self.log = [] self.timecolor = Colors.colors['gray']
self.level = self.levels['Info'] self.level = self.levels['Info']
handler = LogWindowHandler(DEBUG) self.messagecolors = {
handler.logmessage.connect(self.newEntry) 10 : Colors.colors['gray'],
logger.addHandler(handler) 20 : Colors.palette.windowText().color(),
30 : Colors.colors['orange'],
40 : Colors.colors['red'],
}
self.handler = handler
self.handler.logmessage.connect(self.newEntry)
self.setMessages(self.handler.getEntries(self.level))
def newEntry(self, msg, lvl): def setMessages(self, msgs):
self.log.append((lvl, msg)) for msg in msgs:
if lvl >= self.level: self.appendMessage(msg)
self.logBrowser.append(msg)
def newEntry(self, record):
if record.levelno >= self.level:
self.appendMessage(record)
def appendMessage(self, record):
s = record.getMessage()
time = record.created
if record.levelno == self.levels['Error']:
s = '<b>%s</b>' %s
s='<span style="color:%s">[%s] </span><span style="color:%s">%s: %s</span>' \
% (self.timecolor.name(), time, \
self.messagecolors[record.levelno].name(), \
record.name, s)
self.logBrowser.append(s)
def on_logLevel_currentTextChanged(self, level): def on_logLevel_currentTextChanged(self, level):
self.level = self.levels[level] self.level = self.levels[level]
self.logBrowser.clear() self.logBrowser.clear()
self.logBrowser.setPlainText('\n'.join(msg for (lvl, msg) in self.log if lvl >= self.level)) self.setMessages(self.handler.getEntries(self.level))
def on_clear_pressed(self): def on_clear_pressed(self):
self.logBrowser.clear() self.logBrowser.clear()
self.log.clear()
def onClose(self): def closeEvent(self, event):
pass self.closed.emit()
self.deleteLater()

View File

@ -27,7 +27,7 @@ from frappy.gui.qt import QAction, QInputDialog, QKeySequence, QMainWindow, \
import frappy.version import frappy.version
from frappy.gui.connection import QSECNode from frappy.gui.connection import QSECNode
from frappy.gui.logwindow import LogWindow from frappy.gui.logwindow import LogWindow, LogWindowHandler
from frappy.gui.nodewidget import NodeWidget from frappy.gui.nodewidget import NodeWidget
from frappy.gui.tabwidget import TearOffTabWidget from frappy.gui.tabwidget import TearOffTabWidget
from frappy.gui.util import Colors, is_light_theme, loadUi from frappy.gui.util import Colors, is_light_theme, loadUi
@ -94,9 +94,11 @@ class MainWindow(QMainWindow):
def __init__(self, hosts, logger, parent=None): def __init__(self, hosts, logger, parent=None):
super().__init__(parent) super().__init__(parent)
# centralized handling for logging and cmd-history
self.loghandler = LogWindowHandler()
self.log = logger self.log = logger
self.logwin = LogWindow(logger, self) self.log.addHandler(self.loghandler)
self.logwin.hide() self.logwin = None
self.historySerializer = HistorySerializer() self.historySerializer = HistorySerializer()
loadUi(self, 'mainwin.ui') loadUi(self, 'mainwin.ui')
@ -173,7 +175,18 @@ class MainWindow(QMainWindow):
self._rebuildAdvanced(toggled) self._rebuildAdvanced(toggled)
def on_actionShow_Logs_toggled(self, active): def on_actionShow_Logs_toggled(self, active):
self.logwin.setHidden(not active) if not active and self.logwin:
self.logwin.close()
self.logwin = None
return
self.logwin = LogWindow(self.loghandler, self)
self.logwin.closed.connect(self.onLogWindowClose)
self.logwin.show()
def onLogWindowClose(self):
if self.actionShow_Logs.isChecked():
self.actionShow_Logs.toggle()
self.logwin = None
def on_actionHighlightAnimation_toggled(self, toggled): def on_actionHighlightAnimation_toggled(self, toggled):
settings = QSettings() settings = QSettings()
@ -274,4 +287,3 @@ class MainWindow(QMainWindow):
# this is only qt signals deconnecting! # this is only qt signals deconnecting!
widget.getSecNode().terminate_connection() widget.getSecNode().terminate_connection()
self.historySerializer.saveHistory() self.historySerializer.saveHistory()
self.logwin.onClose()

View File

@ -6,23 +6,35 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>350</width> <width>659</width>
<height>271</height> <height>306</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Log</string> <string>Log</string>
</property> </property>
<widget class="QWidget" name=""> <widget class="QWidget" name="layoutWidget">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
<y>10</y> <y>10</y>
<width>351</width> <width>651</width>
<height>261</height> <height>291</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
@ -30,6 +42,9 @@
<property name="currentText"> <property name="currentText">
<string>Info</string> <string>Info</string>
</property> </property>
<property name="currentIndex">
<number>2</number>
</property>
<item> <item>
<property name="text"> <property name="text">
<string>Error</string> <string>Error</string>

View File

@ -47,6 +47,8 @@ class Colors:
cls.palette = palette cls.palette = palette
if is_light_theme(palette): # light if is_light_theme(palette): # light
cls.colors = { cls.colors = {
'gray' : QColor('#696969'),
'red' : QColor('#FF0000'),
'orange': QColor('#FA6800'), 'orange': QColor('#FA6800'),
'yellow': QColor('#FCFFa4'), 'yellow': QColor('#FCFFa4'),
'plot-fg': QColor('black'), 'plot-fg': QColor('black'),
@ -60,6 +62,8 @@ class Colors:
} }
else: # dark else: # dark
cls.colors = { cls.colors = {
'gray' : QColor('#AAAAAA'),
'red' : QColor('#FF0000'),
'orange': QColor('#FA6800'), 'orange': QColor('#FA6800'),
'yellow': QColor('#FEFE22'), 'yellow': QColor('#FEFE22'),
'plot-fg': QColor('white'), 'plot-fg': QColor('white'),