From e3cafee4f5f614673a416d5bf81f6412a07ce9dd Mon Sep 17 00:00:00 2001 From: Sergey Palcheh Date: Tue, 7 Oct 2025 13:35:29 +0600 Subject: [PATCH 1/4] added a filter for unnecessary components --- winehelper_gui.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/winehelper_gui.py b/winehelper_gui.py index d5e1c92..1780341 100644 --- a/winehelper_gui.py +++ b/winehelper_gui.py @@ -617,12 +617,33 @@ class WinetricksManagerDialog(QDialog): self._log(f"--- Предупреждение: не удалось прочитать {log_path}: {e} ---") return installed_verbs - def _parse_winetricks_list_output(self, output, installed_verbs, list_widget): + def _parse_winetricks_list_output(self, output, installed_verbs, list_widget, category): """Парсит вывод 'winetricks list' и заполняет QListWidget.""" # Regex, который обрабатывает строки как с префиксом статуса '[ ]', так и без него. # 1. `(?:\[(.)]\s+)?` - опциональная группа для статуса (напр. '[x]'). # 2. `([^\s]+)` - имя компонента (без пробелов). # 3. `(.*)` - оставшаяся часть строки (описание). + + # Определяем шаблоны для фильтрации на основе категории + dlls_blacklist_pattern = None + fonts_blacklist_pattern = None + settings_blacklist_pattern = None + + if category == 'dlls': + # Исключаем d3d*, directx9, dont_use, dxvk*, vkd3d*, galliumnine, faudio*, Foundation + dlls_blacklist_pattern = re.compile( + r'^(d3d|directx9|dont_use|dxvk|vkd3d|galliumnine|faudio|foundation)', re.IGNORECASE + ) + elif category == 'fonts': + fonts_blacklist_pattern = re.compile( + r'^(dont_use)', re.IGNORECASE + ) + elif category == 'settings': + # Исключаем vista*, alldlls, autostart_*, bad*, good*, win*, videomemory*, vd=*, isolate_home + settings_blacklist_pattern = re.compile( + r'^(vista|alldlls|autostart_|bad|good|win|videomemory|vd=|isolate_home)', re.IGNORECASE + ) + line_re = re.compile(r"^\s*(?:\[(.)]\s+)?([^\s]+)\s*(.*)") found_items = False @@ -643,6 +664,14 @@ class WinetricksManagerDialog(QDialog): if '/' in name or '\\' in name or name.lower() in ('executing', 'using', 'warning:') or name.endswith(':'): continue + # Применяем фильтры для черных списков + if dlls_blacklist_pattern and dlls_blacklist_pattern.search(name): + continue + if fonts_blacklist_pattern and fonts_blacklist_pattern.search(name): + continue + if settings_blacklist_pattern and settings_blacklist_pattern.search(name): + continue + is_checked = name in installed_verbs item_text = f"{name.ljust(27)}{description.strip()}" item = QListWidgetItem(item_text) @@ -681,7 +710,7 @@ class WinetricksManagerDialog(QDialog): self._log("--------------------------------------------------", "red") else: installed_verbs = self._parse_winetricks_log() - found_items = self._parse_winetricks_list_output(output, installed_verbs, list_widget) + found_items = self._parse_winetricks_list_output(output, installed_verbs, list_widget, category) if from_cache is None: # Только если мы не читали из кэша # Сохраняем успешный результат в кэш From 9d16883e6efbe58fe746eeb82bc4bb9bde7aa192 Mon Sep 17 00:00:00 2001 From: Sergey Palcheh Date: Tue, 7 Oct 2025 14:28:18 +0600 Subject: [PATCH 2/4] added display of installed Winetricks components --- winehelper_gui.py | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/winehelper_gui.py b/winehelper_gui.py index 1780341..4dae2ea 100644 --- a/winehelper_gui.py +++ b/winehelper_gui.py @@ -13,7 +13,7 @@ from functools import partial from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QTabWidget, QTabBar, QTextEdit, QFileDialog, QMessageBox, QLineEdit, QCheckBox, QStackedWidget, QScrollArea, QFormLayout, QGroupBox, QRadioButton, QComboBox, QListWidget, QListWidgetItem, QGridLayout, QFrame, QDialog, QTextBrowser, QInputDialog, QDialogButtonBox, QSystemTrayIcon, QMenu) -from PyQt5.QtCore import Qt, QProcess, QSize, QTimer, QProcessEnvironment, QPropertyAnimation, QEasingCurve +from PyQt5.QtCore import Qt, QProcess, QSize, QTimer, QProcessEnvironment, QPropertyAnimation, QEasingCurve, pyqtSignal from PyQt5.QtGui import QIcon, QFont, QTextCursor, QPixmap, QPainter, QCursor from PyQt5.QtNetwork import QLocalServer, QLocalSocket @@ -428,6 +428,8 @@ class WinetricksManagerDialog(QDialog): "Для переустановки компонента: Выделите его в списке и нажмите кнопку «Переустановить»." ) + installation_complete = pyqtSignal() + def __init__(self, prefix_path, winetricks_path, parent=None, wine_executable=None): super().__init__(parent) self.prefix_path = prefix_path @@ -885,6 +887,7 @@ class WinetricksManagerDialog(QDialog): # Перезагружаем данные, чтобы обновить состояние self.initial_states.clear() self.load_all_categories() + self.installation_complete.emit() self.installation_finished = True def closeEvent(self, event): @@ -2630,19 +2633,39 @@ class WineHelperGUI(QMainWindow): self.esync_button.blockSignals(False) self.fsync_button.blockSignals(False) + # --- Чтение и отображение установленных компонентов Winetricks --- + winetricks_log_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name, "winetricks.log") + installed_verbs = [] + if os.path.exists(winetricks_log_path): + try: + with open(winetricks_log_path, 'r', encoding='utf-8') as f: + for line in f: + verb = line.split('#', 1)[0].strip() + if verb: + installed_verbs.append(verb) + except IOError as e: + print(f"Ошибка чтения winetricks.log: {e}") + + # Фильтруем служебные компоненты, чтобы не засорять вывод + verbs_to_ignore = { + 'isolate_home', 'winxp', 'win7', 'win10', 'win11', + 'vista', 'win2k', 'win2k3', 'win2k8', 'win8', 'win81', + 'workaround', 'internal' + } + display_verbs = sorted([v for v in installed_verbs if v not in verbs_to_ignore]) + # Карта для красивого отображения известных переменных display_map = { "WINEPREFIX": ("Путь", lambda v: v), "WINEARCH": ("Архитектура", lambda v: "64-bit" if v == "win64" else "32-bit"), "WH_WINE_USE": ("Версия Wine", lambda v: "Системная" if v == "system" else v), - "BASE_PFX": ("Тип", lambda v: 'Чистый' if v == "none" else 'С рекомендуемыми библиотеками'), "DXVK_VER": ("Версия DXVK", lambda v: v if v else "Не установлено"), "VKD3D_VER": ("Версия VKD3D", lambda v: v if v else "Не установлено"), "WINEESYNC": ("ESync", lambda v: "Включен" if v == "1" else "Выключен"), "WINEFSYNC": ("FSync", lambda v: "Включен" if v == "1" else "Выключен"), "WH_XDG_OPEN": ("Ассоциации файлов", lambda v: v if v and v != "0" else "Не заданы"), } - display_order = ["WINEPREFIX", "WINEARCH", "WH_WINE_USE", "BASE_PFX", "DXVK_VER", "VKD3D_VER", "WINEESYNC", "WINEFSYNC", "WH_XDG_OPEN"] + display_order = ["WINEPREFIX", "WINEARCH", "WH_WINE_USE", "DXVK_VER", "VKD3D_VER", "WINEESYNC", "WINEFSYNC", "WH_XDG_OPEN"] html_content = f'

' html_content += f"Имя: {html.escape(prefix_name)}
" @@ -2664,6 +2687,15 @@ class WineHelperGUI(QMainWindow): html_content += "
Дополнительные параметры:
" html_content += other_vars_html + html_content += "
Компоненты (Winetricks): " + if display_verbs: + # Используем span вместо div, чтобы избежать лишних отступов + html_content += '' + html_content += ", ".join(html.escape(v) for v in display_verbs) + html_content += '' + else: + html_content += "Не установлены" + html_content += "

" self.prefix_info_display.setHtml(html_content) @@ -3673,6 +3705,7 @@ class WineHelperGUI(QMainWindow): wine_executable = self._get_wine_executable_for_prefix(prefix_name) dialog = WinetricksManagerDialog(prefix_path, winetricks_path, self, wine_executable=wine_executable) + dialog.installation_complete.connect(lambda: self.update_prefix_info_display(prefix_name)) dialog.exec_() def _get_wine_executable_for_prefix(self, prefix_name): From 5f4d3a54b137d6f149710408bd185e9eb6531a0f Mon Sep 17 00:00:00 2001 From: Sergey Palcheh Date: Tue, 7 Oct 2025 14:55:37 +0600 Subject: [PATCH 3/4] fixed auto-scrolling of the log to the final message when creating a prefix --- winehelper_gui.py | 1 + 1 file changed, 1 insertion(+) diff --git a/winehelper_gui.py b/winehelper_gui.py index 4dae2ea..9320004 100644 --- a/winehelper_gui.py +++ b/winehelper_gui.py @@ -4698,6 +4698,7 @@ class WineHelperGUI(QMainWindow): self.command_process.deleteLater() self.command_process = None self.command_close_button.setEnabled(True) + self.command_log_output.ensureCursorVisible() def _handle_launcher_creation_finished(self, exit_code, exit_status): """Обрабатывает завершение создания ярлыка.""" From 9e8e41e8124b0be2c6f5c66d02389b1f11f05bd7 Mon Sep 17 00:00:00 2001 From: Sergey Palcheh Date: Tue, 7 Oct 2025 15:03:08 +0600 Subject: [PATCH 4/4] the license agreement window has been removed when creating a prefix --- winehelper_gui.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/winehelper_gui.py b/winehelper_gui.py index 9320004..c85f5ae 100644 --- a/winehelper_gui.py +++ b/winehelper_gui.py @@ -3252,9 +3252,6 @@ class WineHelperGUI(QMainWindow): """Открывает диалог создания нового префикса.""" dialog = CreatePrefixDialog(self) if dialog.exec_() == QDialog.Accepted: - if not self._show_license_agreement_dialog(): - return - self.start_prefix_creation( prefix_name=dialog.prefix_name, wine_arch=dialog.wine_arch,