forked from CastroFidel/winehelper
added the ability to install the application in the created prefix
This commit is contained in:
@@ -1220,7 +1220,7 @@ class WineHelperGUI(QMainWindow):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.setWindowTitle("WineHelper")
|
self.setWindowTitle("WineHelper")
|
||||||
self.setMinimumSize(950, 500)
|
self.setMinimumSize(950, 550)
|
||||||
|
|
||||||
if Var.WH_ICON_PATH and os.path.exists(Var.WH_ICON_PATH):
|
if Var.WH_ICON_PATH and os.path.exists(Var.WH_ICON_PATH):
|
||||||
self.setWindowIcon(QIcon(Var.WH_ICON_PATH))
|
self.setWindowIcon(QIcon(Var.WH_ICON_PATH))
|
||||||
@@ -1900,6 +1900,7 @@ class WineHelperGUI(QMainWindow):
|
|||||||
|
|
||||||
# --- Левая сторона: Кнопки ---
|
# --- Левая сторона: Кнопки ---
|
||||||
self.prefix_winetricks_button = QPushButton("Менеджер компонентов")
|
self.prefix_winetricks_button = QPushButton("Менеджер компонентов")
|
||||||
|
self.prefix_winetricks_button.setMinimumHeight(32)
|
||||||
self.prefix_winetricks_button.clicked.connect(
|
self.prefix_winetricks_button.clicked.connect(
|
||||||
lambda: self.open_winetricks_manager(prefix_name=self.current_managed_prefix_name))
|
lambda: self.open_winetricks_manager(prefix_name=self.current_managed_prefix_name))
|
||||||
self.prefix_winetricks_button.setToolTip(
|
self.prefix_winetricks_button.setToolTip(
|
||||||
@@ -1907,6 +1908,7 @@ class WineHelperGUI(QMainWindow):
|
|||||||
management_layout.addWidget(self.prefix_winetricks_button, 0, 0)
|
management_layout.addWidget(self.prefix_winetricks_button, 0, 0)
|
||||||
|
|
||||||
self.prefix_winecfg_button = QPushButton("Редактор настроек")
|
self.prefix_winecfg_button = QPushButton("Редактор настроек")
|
||||||
|
self.prefix_winecfg_button.setMinimumHeight(32)
|
||||||
self.prefix_winecfg_button.clicked.connect(
|
self.prefix_winecfg_button.clicked.connect(
|
||||||
lambda: self._run_wine_util('winecfg', prefix_name=self.current_managed_prefix_name))
|
lambda: self._run_wine_util('winecfg', prefix_name=self.current_managed_prefix_name))
|
||||||
self.prefix_winecfg_button.setToolTip(
|
self.prefix_winecfg_button.setToolTip(
|
||||||
@@ -1914,6 +1916,7 @@ class WineHelperGUI(QMainWindow):
|
|||||||
management_layout.addWidget(self.prefix_winecfg_button, 0, 1)
|
management_layout.addWidget(self.prefix_winecfg_button, 0, 1)
|
||||||
|
|
||||||
self.prefix_regedit_button = QPushButton("Редактор реестра")
|
self.prefix_regedit_button = QPushButton("Редактор реестра")
|
||||||
|
self.prefix_regedit_button.setMinimumHeight(32)
|
||||||
self.prefix_regedit_button.clicked.connect(
|
self.prefix_regedit_button.clicked.connect(
|
||||||
lambda: self._run_wine_util('regedit', prefix_name=self.current_managed_prefix_name))
|
lambda: self._run_wine_util('regedit', prefix_name=self.current_managed_prefix_name))
|
||||||
self.prefix_regedit_button.setToolTip(
|
self.prefix_regedit_button.setToolTip(
|
||||||
@@ -1921,6 +1924,7 @@ class WineHelperGUI(QMainWindow):
|
|||||||
management_layout.addWidget(self.prefix_regedit_button, 1, 0)
|
management_layout.addWidget(self.prefix_regedit_button, 1, 0)
|
||||||
|
|
||||||
self.prefix_uninstaller_button = QPushButton("Удаление программ")
|
self.prefix_uninstaller_button = QPushButton("Удаление программ")
|
||||||
|
self.prefix_uninstaller_button.setMinimumHeight(32)
|
||||||
self.prefix_uninstaller_button.clicked.connect(
|
self.prefix_uninstaller_button.clicked.connect(
|
||||||
lambda: self._run_wine_util('uninstaller', prefix_name=self.current_managed_prefix_name))
|
lambda: self._run_wine_util('uninstaller', prefix_name=self.current_managed_prefix_name))
|
||||||
self.prefix_uninstaller_button.setToolTip(
|
self.prefix_uninstaller_button.setToolTip(
|
||||||
@@ -1928,11 +1932,13 @@ class WineHelperGUI(QMainWindow):
|
|||||||
management_layout.addWidget(self.prefix_uninstaller_button, 1, 1)
|
management_layout.addWidget(self.prefix_uninstaller_button, 1, 1)
|
||||||
|
|
||||||
self.prefix_cmd_button = QPushButton("Командная строка")
|
self.prefix_cmd_button = QPushButton("Командная строка")
|
||||||
|
self.prefix_cmd_button.setMinimumHeight(32)
|
||||||
self.prefix_cmd_button.clicked.connect(lambda: self._run_wine_util('cmd', prefix_name=self.current_managed_prefix_name))
|
self.prefix_cmd_button.clicked.connect(lambda: self._run_wine_util('cmd', prefix_name=self.current_managed_prefix_name))
|
||||||
self.prefix_cmd_button.setToolTip("Запуск командной строки (cmd) в окружении выбранного префикса.")
|
self.prefix_cmd_button.setToolTip("Запуск командной строки (cmd) в окружении выбранного префикса.")
|
||||||
management_layout.addWidget(self.prefix_cmd_button, 2, 0)
|
management_layout.addWidget(self.prefix_cmd_button, 2, 0)
|
||||||
|
|
||||||
self.prefix_winefile_button = QPushButton("Файловый менеджер")
|
self.prefix_winefile_button = QPushButton("Файловый менеджер")
|
||||||
|
self.prefix_winefile_button.setMinimumHeight(32)
|
||||||
self.prefix_winefile_button.clicked.connect(
|
self.prefix_winefile_button.clicked.connect(
|
||||||
lambda: self._run_wine_util('winefile', prefix_name=self.current_managed_prefix_name))
|
lambda: self._run_wine_util('winefile', prefix_name=self.current_managed_prefix_name))
|
||||||
self.prefix_winefile_button.setToolTip("Запуск файлового менеджера Wine (winefile) для просмотра файлов внутри префикса.")
|
self.prefix_winefile_button.setToolTip("Запуск файлового менеджера Wine (winefile) для просмотра файлов внутри префикса.")
|
||||||
@@ -1948,6 +1954,34 @@ class WineHelperGUI(QMainWindow):
|
|||||||
management_layout.setColumnStretch(1, 1)
|
management_layout.setColumnStretch(1, 1)
|
||||||
management_layout.setColumnStretch(2, 2)
|
management_layout.setColumnStretch(2, 2)
|
||||||
|
|
||||||
|
# --- Separator and Installer ---
|
||||||
|
separator = QFrame()
|
||||||
|
separator.setFrameShape(QFrame.HLine)
|
||||||
|
separator.setFrameShadow(QFrame.Sunken)
|
||||||
|
management_layout.addWidget(separator, 3, 0, 1, 3)
|
||||||
|
|
||||||
|
install_group = QWidget()
|
||||||
|
install_layout = QVBoxLayout(install_group)
|
||||||
|
install_layout.setContentsMargins(0, 5, 0, 0)
|
||||||
|
install_layout.setSpacing(5)
|
||||||
|
|
||||||
|
install_path_layout = QHBoxLayout()
|
||||||
|
self.prefix_install_path_edit = QLineEdit()
|
||||||
|
self.prefix_install_path_edit.setPlaceholderText("Путь к .exe или .msi файлу...")
|
||||||
|
install_path_layout.addWidget(self.prefix_install_path_edit)
|
||||||
|
|
||||||
|
self.prefix_browse_button = QPushButton("Обзор...")
|
||||||
|
self.prefix_browse_button.clicked.connect(self.browse_for_prefix_installer)
|
||||||
|
install_path_layout.addWidget(self.prefix_browse_button)
|
||||||
|
install_layout.addLayout(install_path_layout)
|
||||||
|
|
||||||
|
self.prefix_install_button = QPushButton("Установить приложение в префикс")
|
||||||
|
self.prefix_install_button.setEnabled(False)
|
||||||
|
self.prefix_install_button.clicked.connect(self.run_prefix_installer)
|
||||||
|
install_layout.addWidget(self.prefix_install_button)
|
||||||
|
|
||||||
|
management_layout.addWidget(install_group, 4, 0, 1, 3)
|
||||||
|
|
||||||
container_layout.addWidget(self.prefix_management_groupbox)
|
container_layout.addWidget(self.prefix_management_groupbox)
|
||||||
layout.addWidget(self.management_container_groupbox)
|
layout.addWidget(self.management_container_groupbox)
|
||||||
layout.addStretch()
|
layout.addStretch()
|
||||||
@@ -1957,6 +1991,7 @@ class WineHelperGUI(QMainWindow):
|
|||||||
self.prefix_name_edit.textChanged.connect(self.update_create_prefix_button_state)
|
self.prefix_name_edit.textChanged.connect(self.update_create_prefix_button_state)
|
||||||
self.prefix_name_edit.textChanged.connect(self.on_prefix_name_edited)
|
self.prefix_name_edit.textChanged.connect(self.on_prefix_name_edited)
|
||||||
self.wine_version_edit.textChanged.connect(self.update_create_prefix_button_state)
|
self.wine_version_edit.textChanged.connect(self.update_create_prefix_button_state)
|
||||||
|
self.prefix_install_path_edit.textChanged.connect(self.update_prefix_install_button_state)
|
||||||
|
|
||||||
def _load_state(self):
|
def _load_state(self):
|
||||||
"""Загружает последнее состояние GUI из файла."""
|
"""Загружает последнее состояние GUI из файла."""
|
||||||
@@ -2072,6 +2107,8 @@ class WineHelperGUI(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
self.prefix_management_groupbox.setEnabled(False)
|
self.prefix_management_groupbox.setEnabled(False)
|
||||||
self.prefix_info_display.clear()
|
self.prefix_info_display.clear()
|
||||||
|
self.prefix_install_path_edit.clear()
|
||||||
|
self.update_prefix_install_button_state()
|
||||||
|
|
||||||
def update_prefix_info_display(self, prefix_name):
|
def update_prefix_info_display(self, prefix_name):
|
||||||
"""Обновляет информационный блок для созданного префикса."""
|
"""Обновляет информационный блок для созданного префикса."""
|
||||||
@@ -2088,6 +2125,70 @@ class WineHelperGUI(QMainWindow):
|
|||||||
<b>Путь:</b> {html.escape(info['path'])}</p>"""
|
<b>Путь:</b> {html.escape(info['path'])}</p>"""
|
||||||
self.prefix_info_display.setHtml(html_content)
|
self.prefix_info_display.setHtml(html_content)
|
||||||
|
|
||||||
|
def browse_for_prefix_installer(self):
|
||||||
|
"""Открывает диалог выбора файла для установки в созданный префикс."""
|
||||||
|
file_path, _ = QFileDialog.getOpenFileName(
|
||||||
|
self,
|
||||||
|
"Выберите установочный файл",
|
||||||
|
os.path.expanduser("~"),
|
||||||
|
"Исполняемые файлы (*.exe *.msi);;Все файлы (*)"
|
||||||
|
)
|
||||||
|
if file_path:
|
||||||
|
self.prefix_install_path_edit.setText(file_path)
|
||||||
|
|
||||||
|
def update_prefix_install_button_state(self):
|
||||||
|
"""Обновляет состояние кнопки установки в префикс."""
|
||||||
|
path_ok = bool(self.prefix_install_path_edit.text().strip())
|
||||||
|
prefix_selected = self.current_managed_prefix_name is not None
|
||||||
|
self.prefix_install_button.setEnabled(path_ok and prefix_selected)
|
||||||
|
|
||||||
|
def run_prefix_installer(self):
|
||||||
|
"""Запускает установку файла в выбранный префикс."""
|
||||||
|
prefix_name = self.current_managed_prefix_name
|
||||||
|
installer_path = self.prefix_install_path_edit.text().strip()
|
||||||
|
|
||||||
|
if not prefix_name:
|
||||||
|
QMessageBox.warning(self, "Ошибка", "Не выбран префикс для установки.")
|
||||||
|
return
|
||||||
|
if not installer_path or not os.path.isfile(installer_path):
|
||||||
|
QMessageBox.warning(self, "Ошибка", "Указан неверный путь к установочному файлу.")
|
||||||
|
return
|
||||||
|
|
||||||
|
prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name)
|
||||||
|
wine_executable = self._get_wine_executable_for_prefix(prefix_name)
|
||||||
|
|
||||||
|
self.command_dialog = QDialog(self)
|
||||||
|
self.command_dialog.setWindowTitle(f"Установка в префикс: {prefix_name}")
|
||||||
|
self.command_dialog.setMinimumSize(750, 400)
|
||||||
|
self.command_dialog.setModal(True)
|
||||||
|
self.command_dialog.setWindowFlags(self.command_dialog.windowFlags() & ~Qt.WindowCloseButtonHint)
|
||||||
|
|
||||||
|
layout = QVBoxLayout()
|
||||||
|
self.command_log_output = QTextEdit()
|
||||||
|
self.command_log_output.setReadOnly(True)
|
||||||
|
self.command_log_output.setFont(QFont('DejaVu Sans Mono', 10))
|
||||||
|
layout.addWidget(self.command_log_output)
|
||||||
|
|
||||||
|
self.command_close_button = QPushButton("Закрыть")
|
||||||
|
self.command_close_button.setEnabled(False)
|
||||||
|
self.command_close_button.clicked.connect(self.command_dialog.close)
|
||||||
|
layout.addWidget(self.command_close_button)
|
||||||
|
self.command_dialog.setLayout(layout)
|
||||||
|
|
||||||
|
self.command_process = QProcess(self.command_dialog)
|
||||||
|
self.command_process.setProcessChannelMode(QProcess.MergedChannels)
|
||||||
|
self.command_process.readyReadStandardOutput.connect(self._handle_command_output)
|
||||||
|
self.command_process.finished.connect(self._handle_prefix_install_finished)
|
||||||
|
|
||||||
|
env = QProcessEnvironment.systemEnvironment()
|
||||||
|
env.insert("WINEPREFIX", prefix_path)
|
||||||
|
self.command_process.setProcessEnvironment(env)
|
||||||
|
|
||||||
|
args = [installer_path]
|
||||||
|
self.command_log_output.append(f"Запуск установки: {shlex.quote(wine_executable)} {shlex.quote(installer_path)}")
|
||||||
|
self.command_process.start(wine_executable, args)
|
||||||
|
self.command_dialog.exec_()
|
||||||
|
|
||||||
def create_help_tab(self):
|
def create_help_tab(self):
|
||||||
"""Создает вкладку 'Справка' с подвкладками"""
|
"""Создает вкладку 'Справка' с подвкладками"""
|
||||||
help_tab = QWidget()
|
help_tab = QWidget()
|
||||||
@@ -2390,6 +2491,20 @@ class WineHelperGUI(QMainWindow):
|
|||||||
self.installed_scroll_layout.addWidget(frame, row, column)
|
self.installed_scroll_layout.addWidget(frame, row, column)
|
||||||
self.installed_buttons.append(btn)
|
self.installed_buttons.append(btn)
|
||||||
|
|
||||||
|
def _handle_prefix_install_finished(self, exit_code, exit_status):
|
||||||
|
"""Обрабатывает завершение установки в префикс."""
|
||||||
|
if exit_code == 0:
|
||||||
|
self.command_log_output.append("\n=== Установка успешно завершена ===")
|
||||||
|
else:
|
||||||
|
self.command_log_output.append(f"\n=== Ошибка выполнения (код: {exit_code}) ===")
|
||||||
|
|
||||||
|
if self.command_process:
|
||||||
|
self.command_process.deleteLater()
|
||||||
|
self.command_process = None
|
||||||
|
self.command_close_button.setEnabled(True)
|
||||||
|
self.prefix_install_path_edit.clear()
|
||||||
|
self.update_installed_apps()
|
||||||
|
|
||||||
def _set_active_button(self, button_widget):
|
def _set_active_button(self, button_widget):
|
||||||
"""Устанавливает активную кнопку и обновляет стили ее обертки (QFrame)."""
|
"""Устанавливает активную кнопку и обновляет стили ее обертки (QFrame)."""
|
||||||
# Сброс стиля предыдущей активной кнопки
|
# Сброс стиля предыдущей активной кнопки
|
||||||
@@ -2626,6 +2741,33 @@ class WineHelperGUI(QMainWindow):
|
|||||||
"Не удалось определить префикс. Выберите установленное приложение или создайте новый префикс.")
|
"Не удалось определить префикс. Выберите установленное приложение или создайте новый префикс.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _get_wine_executable_for_prefix(self, prefix_name):
|
||||||
|
"""Определяет и возвращает путь к исполняемому файлу wine для указанного префикса."""
|
||||||
|
prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name)
|
||||||
|
last_conf_path = os.path.join(prefix_path, "last.conf")
|
||||||
|
wh_wine_use = None
|
||||||
|
|
||||||
|
if os.path.exists(last_conf_path):
|
||||||
|
try:
|
||||||
|
with open(last_conf_path, 'r', encoding='utf-8') as f:
|
||||||
|
for line in f:
|
||||||
|
if 'WH_WINE_USE=' in line:
|
||||||
|
value = line.split('=', 1)[1].strip().strip('"\'')
|
||||||
|
if value:
|
||||||
|
wh_wine_use = value
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Предупреждение: не удалось прочитать или обработать {last_conf_path}: {e}")
|
||||||
|
|
||||||
|
if wh_wine_use and not wh_wine_use.startswith('system'):
|
||||||
|
local_wine_path = os.path.join(Var.USER_WORK_PATH, "dist", wh_wine_use, "bin", "wine")
|
||||||
|
if os.path.exists(local_wine_path):
|
||||||
|
return local_wine_path
|
||||||
|
QMessageBox.warning(self, "Предупреждение",
|
||||||
|
f"Локальная версия Wine '{wh_wine_use}' не найдена по пути:\n{local_wine_path}\n\n"
|
||||||
|
"Будет использована системная версия Wine.")
|
||||||
|
return 'wine' # По умолчанию системный wine
|
||||||
|
|
||||||
prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name)
|
prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name)
|
||||||
if not os.path.isdir(prefix_path):
|
if not os.path.isdir(prefix_path):
|
||||||
QMessageBox.critical(self, "Ошибка", f"Каталог префикса не найден:\n{prefix_path}")
|
QMessageBox.critical(self, "Ошибка", f"Каталог префикса не найден:\n{prefix_path}")
|
||||||
@@ -2665,33 +2807,7 @@ class WineHelperGUI(QMainWindow):
|
|||||||
QMessageBox.critical(self, "Ошибка", f"Каталог префикса не найден:\n{prefix_path}")
|
QMessageBox.critical(self, "Ошибка", f"Каталог префикса не найден:\n{prefix_path}")
|
||||||
return
|
return
|
||||||
|
|
||||||
# --- Определение используемой версии Wine ---
|
wine_executable = self._get_wine_executable_for_prefix(prefix_name)
|
||||||
wine_executable = 'wine' # По умолчанию системный wine
|
|
||||||
last_conf_path = os.path.join(prefix_path, "last.conf")
|
|
||||||
wh_wine_use = None
|
|
||||||
|
|
||||||
if os.path.exists(last_conf_path):
|
|
||||||
try:
|
|
||||||
with open(last_conf_path, 'r', encoding='utf-8') as f:
|
|
||||||
for line in f:
|
|
||||||
if 'WH_WINE_USE=' in line:
|
|
||||||
# Извлекаем значение из строки вида: export WH_WINE_USE="wine_ver"
|
|
||||||
value = line.split('=', 1)[1].strip().strip('"\'')
|
|
||||||
if value:
|
|
||||||
wh_wine_use = value
|
|
||||||
break
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Предупреждение: не удалось прочитать или обработать {last_conf_path}: {e}")
|
|
||||||
|
|
||||||
if wh_wine_use and not wh_wine_use.startswith('system'):
|
|
||||||
local_wine_path = os.path.join(Var.USER_WORK_PATH, "dist", wh_wine_use, "bin", "wine")
|
|
||||||
if os.path.exists(local_wine_path):
|
|
||||||
wine_executable = local_wine_path
|
|
||||||
else:
|
|
||||||
QMessageBox.warning(self, "Предупреждение",
|
|
||||||
f"Локальная версия Wine '{wh_wine_use}' не найдена по пути:\n{local_wine_path}\n\n"
|
|
||||||
"Будет использована системная версия Wine.")
|
|
||||||
# --- Конец определения версии Wine ---
|
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env["WINEPREFIX"] = prefix_path
|
env["WINEPREFIX"] = prefix_path
|
||||||
|
Reference in New Issue
Block a user