+ добавлено подсвечивание предупреждений и ошибок в таблице выбранных переменных
125 lines
4.5 KiB
Python
125 lines
4.5 KiB
Python
|
||
import sys
|
||
import re
|
||
from VariableTable import VariableTableWidget, rows
|
||
|
||
from PySide2.QtWidgets import (
|
||
QApplication, QWidget, QTableWidget, QTableWidgetItem,
|
||
QCheckBox, QComboBox, QLineEdit, QVBoxLayout, QHBoxLayout, QPushButton,
|
||
QCompleter, QAbstractItemView, QLabel, QMessageBox, QFileDialog, QTextEdit,
|
||
QDialog, QTreeWidget, QTreeWidgetItem, QSizePolicy, QHeaderView, QProgressBar
|
||
)
|
||
from PySide2.QtGui import QTextCursor, QKeyEvent
|
||
from PySide2.QtCore import Qt, QProcess, QObject, Signal, QSettings
|
||
|
||
|
||
class EmittingStream(QObject):
|
||
text_written = Signal(str)
|
||
progress_updated = Signal(str, int, int) # bar_name, current, total
|
||
|
||
def __init__(self):
|
||
super().__init__()
|
||
self._buffer = ""
|
||
self._current_bar_name = None
|
||
|
||
def write(self, text):
|
||
self._buffer += text
|
||
while '\n' in self._buffer:
|
||
line, self._buffer = self._buffer.split('\n', 1)
|
||
|
||
if line.startswith('Progress: "') and line.endswith('"'):
|
||
bar_name = self._extract_bar_name(line)
|
||
if bar_name:
|
||
self._current_bar_name = bar_name
|
||
continue # не выводим строку
|
||
elif self._is_progress_line(line):
|
||
current, total = self._extract_progress(line)
|
||
if current is not None and total is not None:
|
||
name = self._current_bar_name if self._current_bar_name else "Progress"
|
||
self.progress_updated.emit(name, current, total)
|
||
continue # не выводим строку
|
||
|
||
# если не прогресс и не имя — выводим
|
||
self.text_written.emit(line)
|
||
|
||
def _extract_bar_name(self, line):
|
||
# точно обрезаем вручную
|
||
prefix = 'Progress: "'
|
||
suffix = '"'
|
||
if line.startswith(prefix) and line.endswith(suffix):
|
||
return line[len(prefix):-1]
|
||
return None
|
||
|
||
def _is_progress_line(self, line):
|
||
return re.match(r'^Progress:\s*\d+\s*/\s*\d+$', line) is not None
|
||
|
||
def _extract_progress(self, line):
|
||
match = re.match(r'^Progress:\s*(\d+)\s*/\s*(\d+)$', line)
|
||
if match:
|
||
return int(match.group(1)), int(match.group(2))
|
||
return None, None
|
||
|
||
def flush(self):
|
||
if self._buffer:
|
||
line = self._buffer.strip()
|
||
if not self._is_progress_line(line) and not self._extract_bar_name(line):
|
||
self.text_written.emit(line)
|
||
self._buffer = ""
|
||
|
||
|
||
class ProcessOutputWindowDummy(QDialog):
|
||
def __init__(self, on_done_callback):
|
||
super().__init__()
|
||
self.setWindowTitle("Поиск переменных...")
|
||
self.resize(600, 480)
|
||
self.setModal(True)
|
||
|
||
self.layout = QVBoxLayout(self)
|
||
|
||
self.output_edit = QTextEdit()
|
||
self.output_edit.setReadOnly(True)
|
||
self.layout.addWidget(self.output_edit)
|
||
|
||
# Метка с именем прогрессбара
|
||
self.progress_label = QLabel("Progress:")
|
||
self.layout.addWidget(self.progress_label)
|
||
|
||
# Прогрессбар
|
||
self.progress_bar = QProgressBar()
|
||
self.progress_bar.setMinimum(0)
|
||
self.progress_bar.setValue(0)
|
||
self.layout.addWidget(self.progress_bar)
|
||
|
||
self.btn_close = QPushButton("Закрыть")
|
||
self.btn_close.setEnabled(False)
|
||
self.layout.addWidget(self.btn_close)
|
||
|
||
self.btn_close.clicked.connect(self.__handle_done)
|
||
self._on_done_callback = on_done_callback
|
||
|
||
self.emitting_stream = EmittingStream()
|
||
self.emitting_stream.text_written.connect(self.append_text)
|
||
self.emitting_stream.progress_updated.connect(self.update_progress)
|
||
|
||
sys.stdout = self.emitting_stream
|
||
|
||
def __handle_done(self):
|
||
sys.stdout = sys.__stdout__ # восстановить stdout
|
||
if self._on_done_callback:
|
||
self._on_done_callback()
|
||
self.accept()
|
||
|
||
def append_text(self, text):
|
||
cursor = self.output_edit.textCursor()
|
||
cursor.movePosition(QTextCursor.End)
|
||
if not text.endswith('\n'):
|
||
text += '\n'
|
||
for line in text.splitlines(True):
|
||
cursor.insertText(line)
|
||
self.output_edit.setTextCursor(cursor)
|
||
self.output_edit.ensureCursorVisible()
|
||
|
||
def update_progress(self, bar_name, current, total):
|
||
self.progress_label.setText(f"{bar_name}")
|
||
self.progress_bar.setMaximum(total)
|
||
self.progress_bar.setValue(current) |