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)