Compare commits

..

3 Commits

3 changed files with 85 additions and 8 deletions

View File

@ -1,5 +1,8 @@
История изменений:
0.5.2:
* исправлен запуск winehelper.desktop для winehelper-qt
0.5.1:
* добавлена функция извлечения иконки из .exe файлов
* добавлен вывод истории изменений командой: winehelper --changelog

View File

@ -6,5 +6,4 @@ Comment[ru]=Запуск графического интерфейса WineHelpe
Type=Application
Categories=WineHelper;Utility;Emulator;
StartupNotify=true
Path=/usr/bin/winehelper
Icon=winehelper

View File

@ -2,6 +2,7 @@
import os
import subprocess
import sys
import re
import shlex
import shutil
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QPushButton, QLabel, QTabWidget,
@ -89,6 +90,9 @@ class WineHelperGUI(QMainWindow):
self.create_installed_tab()
self.create_help_tab()
# Инициализируем состояние, которое будет использоваться для логов
self._reset_log_state()
# Обновляем список установленных приложений
self.update_installed_apps()
@ -1335,10 +1339,16 @@ class WineHelperGUI(QMainWindow):
self.install_dialog.show()
def _reset_log_state(self):
"""Сбрасывает состояние буфера и флага прогресса для лога установки."""
self.output_buffer = ""
self.last_line_was_progress = False
def _prepare_installation(self):
"""Подготавливает и запускает процесс установки"""
self.stacked_widget.setCurrentIndex(1)
self._reset_log_state() # Сбрасываем состояние для обработки лога
winehelper_path = self.winehelper_path
script_path = os.path.join(Var.DATA_PATH,
"autoinstall" if self.current_script in self.autoinstall_scripts else "manualinstall",
@ -1391,28 +1401,93 @@ class WineHelperGUI(QMainWindow):
QMessageBox.critical(self.install_dialog, "Ошибка", f"Не удалось запустить установку:\n{str(e)}")
self.cleanup_process()
def append_log(self, text, is_error=False):
def append_log(self, text, is_error=False, add_newline=True):
"""Добавляет сообщение в лог"""
if not hasattr(self, 'log_output'): return
cursor = self.log_output.textCursor()
cursor.movePosition(QTextCursor.End)
if is_error:
# Для ошибок всегда добавляем перенос строки для лучшей читаемости
cursor.insertHtml(f'<font color="red">{text}</font><br>')
else:
cursor.insertText(f"{text}\n")
# Вставляем текст. Добавляем перенос строки, если нужно.
formatted_text = f"{text}\n" if add_newline else text
cursor.insertText(formatted_text)
self.log_output.ensureCursorVisible()
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):
"""Обрабатывает вывод процесса"""
output = self.install_process.readAllStandardOutput().data().decode('utf-8', errors='ignore').strip()
if output:
self.append_log(output)
"""Обрабатывает вывод процесса, корректно отображая однострочный прогресс."""
new_data = self.install_process.readAllStandardOutput().data().decode('utf-8', errors='ignore')
self.output_buffer += new_data
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):
"""Обрабатывает завершение процесса"""
# Обрабатываем остаток в буфере, если он есть
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:
self.append_log("\n=== Установка успешно завершена ===")
# Создаем кастомный диалог, чтобы кнопка была на русском