Files
elmprodvpn/selective-vpn-gui/main_window/ui_helpers_mixin.py

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()