62 lines
2.0 KiB
Python
62 lines
2.0 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
from PySide6.QtGui import QTextCursor
|
|
from PySide6.QtWidgets import QMessageBox, QPlainTextEdit
|
|
|
|
from main_window.constants import _NEXT_CHECK_RE
|
|
|
|
|
|
class UIHelpersMixin:
|
|
def _safe(self, fn, *, title: str = "Error"):
|
|
try:
|
|
return fn()
|
|
except Exception as e: # pragma: no cover - GUI
|
|
try:
|
|
self.ctrl.log_gui(f"[ui-error] {title}: {e}")
|
|
except Exception:
|
|
pass
|
|
QMessageBox.critical(self, title, str(e))
|
|
return None
|
|
|
|
def _set_text(self, widget: QPlainTextEdit, text: str, *, preserve_scroll: bool = False) -> None:
|
|
"""Set text, optionally сохраняя положение скролла (для trace)."""
|
|
if not preserve_scroll:
|
|
widget.setPlainText(text)
|
|
return
|
|
|
|
sb = widget.verticalScrollBar()
|
|
old_max = sb.maximum()
|
|
old_val = sb.value()
|
|
at_end = old_val >= old_max - 2
|
|
|
|
widget.setPlainText(text)
|
|
|
|
new_max = sb.maximum()
|
|
if at_end:
|
|
sb.setValue(new_max)
|
|
else:
|
|
# подвинем на ту же относительную позицию, учитывая прирост размера
|
|
sb.setValue(max(0, min(new_max, old_val+(new_max-old_max))))
|
|
|
|
def _append_text(self, widget: QPlainTextEdit, text: str) -> None:
|
|
cursor = widget.textCursor()
|
|
cursor.movePosition(QTextCursor.End)
|
|
cursor.insertText(text)
|
|
widget.setTextCursor(cursor)
|
|
widget.ensureCursorVisible()
|
|
|
|
def _clean_ui_lines(self, lines) -> str:
|
|
buf = "\n".join([str(x) for x in (lines or [])]).replace("\r", "\n")
|
|
out_lines = []
|
|
for ln in buf.splitlines():
|
|
t = ln.strip()
|
|
if not t:
|
|
continue
|
|
t2 = _NEXT_CHECK_RE.sub("", t).strip()
|
|
if not t2:
|
|
continue
|
|
out_lines.append(t2)
|
|
return "\n".join(out_lines).rstrip()
|