forked from CastroFidel/winehelper
Compare commits
1 Commits
download_p
...
fixing_pan
Author | SHA1 | Date | |
---|---|---|---|
32fa7f6278 |
@ -2,7 +2,6 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import re
|
|
||||||
import shlex
|
import shlex
|
||||||
import shutil
|
import shutil
|
||||||
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QPushButton, QLabel, QTabWidget,
|
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QPushButton, QLabel, QTabWidget,
|
||||||
@ -79,10 +78,15 @@ class WineHelperGUI(QMainWindow):
|
|||||||
|
|
||||||
# Создаем табы
|
# Создаем табы
|
||||||
self.tabs = QTabWidget()
|
self.tabs = QTabWidget()
|
||||||
self.main_layout.addWidget(self.tabs, stretch=2)
|
self.main_layout.addWidget(self.tabs, stretch=1)
|
||||||
|
|
||||||
# Создаем панель информации о скрипте
|
# Создаем панель информации о скрипте
|
||||||
self.create_info_panel()
|
self.create_info_panel()
|
||||||
|
self.main_layout.addWidget(self.info_panel, stretch=1)
|
||||||
|
|
||||||
|
# Фиксируем минимальные размеры
|
||||||
|
self.tabs.setMinimumWidth(520)
|
||||||
|
self.info_panel.setMinimumWidth(415)
|
||||||
|
|
||||||
# Вкладки
|
# Вкладки
|
||||||
self.create_auto_install_tab()
|
self.create_auto_install_tab()
|
||||||
@ -90,9 +94,6 @@ class WineHelperGUI(QMainWindow):
|
|||||||
self.create_installed_tab()
|
self.create_installed_tab()
|
||||||
self.create_help_tab()
|
self.create_help_tab()
|
||||||
|
|
||||||
# Инициализируем состояние, которое будет использоваться для логов
|
|
||||||
self._reset_log_state()
|
|
||||||
|
|
||||||
# Обновляем список установленных приложений
|
# Обновляем список установленных приложений
|
||||||
self.update_installed_apps()
|
self.update_installed_apps()
|
||||||
|
|
||||||
@ -253,8 +254,6 @@ class WineHelperGUI(QMainWindow):
|
|||||||
self.installed_action_widget.setVisible(False)
|
self.installed_action_widget.setVisible(False)
|
||||||
self.installed_global_action_widget.setVisible(False)
|
self.installed_global_action_widget.setVisible(False)
|
||||||
|
|
||||||
self.main_layout.addWidget(self.info_panel, stretch=1)
|
|
||||||
|
|
||||||
def browse_install_file(self):
|
def browse_install_file(self):
|
||||||
"""Открывает диалог выбора файла для ручной установки"""
|
"""Открывает диалог выбора файла для ручной установки"""
|
||||||
file_path, _ = QFileDialog.getOpenFileName(
|
file_path, _ = QFileDialog.getOpenFileName(
|
||||||
@ -1339,16 +1338,10 @@ class WineHelperGUI(QMainWindow):
|
|||||||
|
|
||||||
self.install_dialog.show()
|
self.install_dialog.show()
|
||||||
|
|
||||||
def _reset_log_state(self):
|
|
||||||
"""Сбрасывает состояние буфера и флага прогресса для лога установки."""
|
|
||||||
self.output_buffer = ""
|
|
||||||
self.last_line_was_progress = False
|
|
||||||
|
|
||||||
def _prepare_installation(self):
|
def _prepare_installation(self):
|
||||||
"""Подготавливает и запускает процесс установки"""
|
"""Подготавливает и запускает процесс установки"""
|
||||||
self.stacked_widget.setCurrentIndex(1)
|
self.stacked_widget.setCurrentIndex(1)
|
||||||
self._reset_log_state() # Сбрасываем состояние для обработки лога
|
|
||||||
|
|
||||||
winehelper_path = self.winehelper_path
|
winehelper_path = self.winehelper_path
|
||||||
script_path = os.path.join(Var.DATA_PATH,
|
script_path = os.path.join(Var.DATA_PATH,
|
||||||
"autoinstall" if self.current_script in self.autoinstall_scripts else "manualinstall",
|
"autoinstall" if self.current_script in self.autoinstall_scripts else "manualinstall",
|
||||||
@ -1401,93 +1394,28 @@ class WineHelperGUI(QMainWindow):
|
|||||||
QMessageBox.critical(self.install_dialog, "Ошибка", f"Не удалось запустить установку:\n{str(e)}")
|
QMessageBox.critical(self.install_dialog, "Ошибка", f"Не удалось запустить установку:\n{str(e)}")
|
||||||
self.cleanup_process()
|
self.cleanup_process()
|
||||||
|
|
||||||
def append_log(self, text, is_error=False, add_newline=True):
|
def append_log(self, text, is_error=False):
|
||||||
"""Добавляет сообщение в лог"""
|
"""Добавляет сообщение в лог"""
|
||||||
if not hasattr(self, 'log_output'): return
|
if not hasattr(self, 'log_output'): return
|
||||||
cursor = self.log_output.textCursor()
|
cursor = self.log_output.textCursor()
|
||||||
cursor.movePosition(QTextCursor.End)
|
cursor.movePosition(QTextCursor.End)
|
||||||
|
|
||||||
if is_error:
|
if is_error:
|
||||||
# Для ошибок всегда добавляем перенос строки для лучшей читаемости
|
|
||||||
cursor.insertHtml(f'<font color="red">{text}</font><br>')
|
cursor.insertHtml(f'<font color="red">{text}</font><br>')
|
||||||
else:
|
else:
|
||||||
# Вставляем текст. Добавляем перенос строки, если нужно.
|
cursor.insertText(f"{text}\n")
|
||||||
formatted_text = f"{text}\n" if add_newline else text
|
|
||||||
cursor.insertText(formatted_text)
|
|
||||||
|
|
||||||
self.log_output.ensureCursorVisible()
|
self.log_output.ensureCursorVisible()
|
||||||
QApplication.processEvents()
|
QApplication.processEvents()
|
||||||
|
|
||||||
def _process_log_line(self, line_with_delimiter):
|
|
||||||
"""Обрабатывает одну строку лога, управляя заменой строк прогресса."""
|
|
||||||
is_progress_line = '\r' in line_with_delimiter
|
|
||||||
|
|
||||||
# Фильтруем "мусорные" строки прогресса (например, '-=O=-' от wget),
|
|
||||||
# обрабатывая только те, что содержат знак процента.
|
|
||||||
if is_progress_line:
|
|
||||||
if not re.search(r'\d\s*%', line_with_delimiter):
|
|
||||||
return # Игнорируем строку прогресса без процентов
|
|
||||||
|
|
||||||
clean_line = line_with_delimiter.replace('\r', '').replace('\n', '').strip()
|
|
||||||
|
|
||||||
if not clean_line:
|
|
||||||
return
|
|
||||||
|
|
||||||
cursor = self.log_output.textCursor()
|
|
||||||
|
|
||||||
# Если новая строка - это прогресс, и предыдущая тоже была прогрессом,
|
|
||||||
# то мы удаляем старую, чтобы заменить ее новой.
|
|
||||||
if is_progress_line and self.last_line_was_progress:
|
|
||||||
cursor.movePosition(QTextCursor.End)
|
|
||||||
cursor.select(QTextCursor.LineUnderCursor)
|
|
||||||
cursor.removeSelectedText()
|
|
||||||
elif not is_progress_line and self.last_line_was_progress:
|
|
||||||
# Это переход от строки прогресса к финальной строке.
|
|
||||||
# Вместо добавления переноса, мы заменяем предыдущую строку новой.
|
|
||||||
cursor.movePosition(QTextCursor.End)
|
|
||||||
cursor.select(QTextCursor.LineUnderCursor)
|
|
||||||
cursor.removeSelectedText()
|
|
||||||
|
|
||||||
# Добавляем новую очищенную строку.
|
|
||||||
# Для прогресса - без переноса строки, для обычных строк - с переносом.
|
|
||||||
self.append_log(clean_line, add_newline=not is_progress_line)
|
|
||||||
|
|
||||||
self.last_line_was_progress = is_progress_line
|
|
||||||
|
|
||||||
def handle_process_output(self):
|
def handle_process_output(self):
|
||||||
"""Обрабатывает вывод процесса, корректно отображая однострочный прогресс."""
|
"""Обрабатывает вывод процесса"""
|
||||||
new_data = self.install_process.readAllStandardOutput().data().decode('utf-8', errors='ignore')
|
output = self.install_process.readAllStandardOutput().data().decode('utf-8', errors='ignore').strip()
|
||||||
self.output_buffer += new_data
|
if output:
|
||||||
|
self.append_log(output)
|
||||||
while True:
|
|
||||||
# Ищем ближайший разделитель (\n или \r)
|
|
||||||
idx_n = self.output_buffer.find('\n')
|
|
||||||
idx_r = self.output_buffer.find('\r')
|
|
||||||
|
|
||||||
if idx_n == -1 and idx_r == -1:
|
|
||||||
break # Нет полных строк для обработки
|
|
||||||
|
|
||||||
split_idx = min(idx for idx in [idx_n, idx_r] if idx != -1)
|
|
||||||
|
|
||||||
# Получаем строку, включая разделитель
|
|
||||||
line = self.output_buffer[:split_idx + 1]
|
|
||||||
self.output_buffer = self.output_buffer[split_idx + 1:]
|
|
||||||
|
|
||||||
self._process_log_line(line)
|
|
||||||
|
|
||||||
def handle_process_finished(self, exit_code, exit_status):
|
def handle_process_finished(self, exit_code, exit_status):
|
||||||
"""Обрабатывает завершение процесса"""
|
"""Обрабатывает завершение процесса"""
|
||||||
# Обрабатываем остаток в буфере, если он есть
|
|
||||||
if self.output_buffer:
|
|
||||||
self._process_log_line(self.output_buffer)
|
|
||||||
|
|
||||||
# Если последней строкой был прогресс, "завершаем" его переносом строки.
|
|
||||||
if self.last_line_was_progress:
|
|
||||||
cursor = self.log_output.textCursor()
|
|
||||||
cursor.movePosition(QTextCursor.End)
|
|
||||||
cursor.insertText("\n")
|
|
||||||
|
|
||||||
self._reset_log_state()
|
|
||||||
if exit_code == 0 and exit_status == QProcess.NormalExit:
|
if exit_code == 0 and exit_status == QProcess.NormalExit:
|
||||||
self.append_log("\n=== Установка успешно завершена ===")
|
self.append_log("\n=== Установка успешно завершена ===")
|
||||||
# Создаем кастомный диалог, чтобы кнопка была на русском
|
# Создаем кастомный диалог, чтобы кнопка была на русском
|
||||||
|
Reference in New Issue
Block a user