Source code for betty.gui.logging
"""
Provide logging for the Graphical User Interface.
"""
import logging
from PyQt6.QtCore import QObject, pyqtSignal, Qt
from PyQt6.QtWidgets import QWidget, QVBoxLayout
from betty.gui.text import Text
[docs]
class LogRecord(Text):
_LEVELS = [
logging.CRITICAL,
logging.ERROR,
logging.WARNING,
logging.INFO,
logging.DEBUG,
logging.NOTSET,
]
_formatter = logging.Formatter()
def __init__(self, record: logging.LogRecord):
super().__init__(self._formatter.format(record))
self.setProperty("level", self._normalize_level(record.levelno))
def _normalize_level(self, record_level: int) -> int:
for level in self._LEVELS:
if record_level >= level:
return level
return logging.NOTSET
[docs]
class LogRecordViewer(QWidget):
def __init__(self):
super().__init__()
self._log_record_layout = QVBoxLayout()
self.setLayout(self._log_record_layout)
[docs]
def log(self, record: logging.LogRecord) -> None:
self._log_record_layout.addWidget(LogRecord(record))
class _LogRecordViewerHandlerObject(QObject):
"""
Provide a signal for logging handlers to log records to a LogRecordViewer in the main (GUI) thread.
"""
log = pyqtSignal(logging.LogRecord)
def __init__(self, viewer: LogRecordViewer):
super().__init__()
self.log.connect( # type: ignore[call-arg]
viewer.log,
Qt.ConnectionType.QueuedConnection,
)
[docs]
class LogRecordViewerHandler(logging.Handler):
log = pyqtSignal(logging.LogRecord)
def __init__(self, viewer: LogRecordViewer):
super().__init__()
self._object = _LogRecordViewerHandlerObject(viewer)
[docs]
def emit(self, record: logging.LogRecord) -> None:
self._object.log.emit(record)