|
4 | 4 | from aao.utils.logger import add_qt_sink |
5 | 5 | handler = QtLogHandler() |
6 | 6 | add_qt_sink(handler.emit) # loguru sink → handler.emit → Signal → UI |
7 | | - handler.log.connect(text_edit.appendPlainText) |
| 7 | + handler.log_html.connect(text_edit.appendHtml) |
8 | 8 |
|
9 | 9 | loguru sink 在产生日志的线程触发;经 Signal(默认 QueuedConnection)跨线程 |
10 | | -投递到 UI 线程槽。显示格式由 logger 配置(仅 {message},去来源)。 |
| 10 | +投递到 UI 线程槽。显示格式由 logger 配置(仅 {message},去来源),此处按 level |
| 11 | +追加 HTML 颜色。 |
11 | 12 | """ |
12 | 13 |
|
13 | 14 | from __future__ import annotations |
14 | 15 |
|
| 16 | +import html |
| 17 | +from typing import Any |
| 18 | + |
15 | 19 | from PySide6.QtCore import QObject, Signal, SignalInstance |
16 | 20 |
|
| 21 | +_LEVEL_COLORS = { |
| 22 | + "TRACE": "#6b7280", |
| 23 | + "DEBUG": "#6b7280", |
| 24 | + "INFO": "#d1d5db", |
| 25 | + "SUCCESS": "#4caf50", |
| 26 | + "WARNING": "#ff9800", |
| 27 | + "ERROR": "#f44336", |
| 28 | + "CRITICAL": "#ffffff;background-color:#b91c1c", |
| 29 | +} |
| 30 | + |
17 | 31 |
|
18 | 32 | class _Emitter(QObject): |
19 | 33 | """承载 Signal(loguru sink 是普通 callable,需 QObject 转 Signal 跨线程)。""" |
20 | 34 |
|
21 | | - log = Signal(str) |
| 35 | + log_html = Signal(str) |
22 | 36 |
|
23 | 37 |
|
24 | 38 | class QtLogHandler: |
25 | | - """loguru sink → Signal(str)。 |
| 39 | + """loguru sink → Signal(str HTML)。 |
26 | 40 |
|
27 | | - emit 作为 loguru sink 的 callback,接收格式化后的消息字符串,转 Signal。 |
| 41 | + emit 作为 loguru sink 的 callback,接收 loguru Message,按 level 着色后转 Signal。 |
28 | 42 | """ |
29 | 43 |
|
30 | 44 | def __init__(self) -> None: |
31 | 45 | self.emitter = _Emitter() |
32 | 46 |
|
33 | 47 | @property |
34 | | - def log(self) -> SignalInstance: |
35 | | - return self.emitter.log |
36 | | - |
37 | | - def emit(self, message: str) -> None: # noqa: A003 |
38 | | - """loguru sink callback:message 是已格式化的日志文本。""" |
39 | | - self.emitter.log.emit(message) |
| 48 | + def log_html(self) -> SignalInstance: |
| 49 | + return self.emitter.log_html |
| 50 | + |
| 51 | + def emit(self, message: Any) -> None: # noqa: A003 |
| 52 | + """loguru sink callback:message 是 loguru Message(含 record)。""" |
| 53 | + text = str(message).rstrip("\n") |
| 54 | + level = "INFO" |
| 55 | + record = getattr(message, "record", None) |
| 56 | + if record: |
| 57 | + level = record["level"].name |
| 58 | + color = _LEVEL_COLORS.get(level, "#d1d5db") |
| 59 | + safe = html.escape(text) |
| 60 | + self.emitter.log_html.emit(f'<span style="color:{color};">{safe}</span>') |
0 commit comments