""" ui/windows/debug_window.py DEBUG window — developer-mode only. Minimal first pass: a live console showing everything the app has printed via core.debug_log (stdout/stderr tee), so debugging doesn't require a terminal. Not wired to any other diagnostics yet — extend as needed. """ from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTextEdit, QFrame, ) from PyQt6.QtCore import Qt, pyqtSignal from PyQt6.QtGui import QFont, QCloseEvent from core.debug_log import get_broadcaster, get_history class DebugWindow(QWidget): closed = pyqtSignal() def __init__(self, parent=None): super().__init__(parent, Qt.WindowType.Window | Qt.WindowType.Tool) self.setWindowTitle("Debug") self.setMinimumSize(560, 420) self.resize(700, 500) self._build() broadcaster = get_broadcaster() if broadcaster is not None: broadcaster.line_written.connect(self._append) def _build(self): root = QVBoxLayout(self); root.setContentsMargins(0, 0, 0, 0); root.setSpacing(0) hdr = QWidget(); hdr.setObjectName("devWindowTitleBar"); hdr.setFixedHeight(44) hl = QHBoxLayout(hdr); hl.setContentsMargins(14, 0, 14, 0) title = QLabel("DEBUG"); title.setObjectName("devWindowTitle") hl.addWidget(title, 1) clear_btn = QPushButton("Clear"); clear_btn.setObjectName("configButton") clear_btn.clicked.connect(lambda: self._console.clear()) hl.addWidget(clear_btn) root.addWidget(hdr) div = QFrame(); div.setFrameShape(QFrame.Shape.HLine) div.setObjectName("devWindowDivider"); root.addWidget(div) self._console = QTextEdit(); self._console.setObjectName("codeEditor") self._console.setReadOnly(True) mono = QFont("IBM Plex Mono, Consolas, Monospace") mono.setStyleHint(QFont.StyleHint.Monospace) self._console.setFont(mono) self._console.setPlainText(get_history()) self._console.verticalScrollBar().setValue(self._console.verticalScrollBar().maximum()) root.addWidget(self._console, 1) def _append(self, text: str): self._console.insertPlainText(text) sb = self._console.verticalScrollBar() sb.setValue(sb.maximum()) def closeEvent(self, e: QCloseEvent): self.closed.emit(); e.accept()