diff --git a/winehelper_gui.py b/winehelper_gui.py index 8dd0324..8766a95 100644 --- a/winehelper_gui.py +++ b/winehelper_gui.py @@ -1227,6 +1227,133 @@ class WineVersionSelectionDialog(QDialog): self.selected_display_text = version_name self.accept() +class CreatePrefixDialog(QDialog): + """Диалог для создания нового префикса.""" + + def __init__(self, parent=None): + super().__init__(parent) + self.parent_gui = parent # Store reference to main window + self.setWindowTitle("Создание нового префикса") + self.setMinimumSize(500, 250) + self.setModal(True) + + # Attributes to store results + self.prefix_name = None + self.wine_arch = None + self.base_pfx = None + self.selected_wine_version_value = None + self.selected_wine_version_display = None + + layout = QVBoxLayout(self) + form_layout = QFormLayout() + form_layout.setSpacing(10) + + self.prefix_name_edit = QLineEdit() + self.prefix_name_edit.setPlaceholderText("Например: my_prefix") + form_layout.addRow("Имя нового префикса:", self.prefix_name_edit) + + arch_widget = QWidget() + arch_layout = QHBoxLayout(arch_widget) + arch_layout.setContentsMargins(0, 0, 0, 0) + self.arch_win32_radio = QRadioButton("32-bit") + self.arch_win64_radio = QRadioButton("64-bit") + self.arch_win64_radio.setChecked(True) + arch_layout.addWidget(self.arch_win32_radio) + arch_layout.addWidget(self.arch_win64_radio) + form_layout.addRow("Разрядность:", arch_widget) + + type_widget = QWidget() + type_layout = QHBoxLayout(type_widget) + type_layout.setContentsMargins(0, 0, 0, 0) + self.type_clean_radio = QRadioButton("Чистый") + self.type_clean_radio.setToolTip("Создает пустой префикс Wine без каких-либо дополнительных компонентов.") + self.type_recommended_radio = QRadioButton("С рекомендуемыми библиотеками") + tooltip_text = "Устанавливает базовый набор компонентов, необходимый для большинства приложений" + self.type_recommended_radio.setToolTip(tooltip_text) + self.type_clean_radio.setChecked(True) + type_layout.addWidget(self.type_clean_radio) + type_layout.addWidget(self.type_recommended_radio) + form_layout.addRow("Наполнение:", type_widget) + + self.wine_version_edit = QLineEdit() + self.wine_version_edit.setReadOnly(True) + self.wine_version_edit.setPlaceholderText("Версия не выбрана") + + select_version_button = QPushButton("Выбрать версию...") + select_version_button.clicked.connect(self.open_wine_version_dialog) + + version_layout = QHBoxLayout() + version_layout.addWidget(self.wine_version_edit) + version_layout.addWidget(select_version_button) + form_layout.addRow("Версия Wine/Proton:", version_layout) + + layout.addLayout(form_layout) + + # Buttons + button_layout = QHBoxLayout() + self.create_button = QPushButton("Создать") + self.create_button.setFont(QFont('Arial', 11, QFont.Bold)) + self.create_button.setStyleSheet("background-color: #0078d7; color: white;") + self.create_button.setEnabled(False) + self.create_button.clicked.connect(self.accept_creation) + + cancel_button = QPushButton("Отмена") + cancel_button.clicked.connect(self.reject) + + button_layout.addStretch() + button_layout.addWidget(self.create_button) + button_layout.addWidget(cancel_button) + layout.addLayout(button_layout) + + # Connect signals + self.arch_win32_radio.toggled.connect(self.clear_wine_version_selection) + self.prefix_name_edit.textChanged.connect(self.update_create_button_state) + self.wine_version_edit.textChanged.connect(self.update_create_button_state) + + def open_wine_version_dialog(self): + """Открывает диалог выбора версии Wine.""" + architecture = "win32" if self.arch_win32_radio.isChecked() else "win64" + dialog = WineVersionSelectionDialog(architecture, self) + if dialog.exec_() == QDialog.Accepted and dialog.selected_version: + self.wine_version_edit.setText(dialog.selected_display_text) + self.selected_wine_version_value = dialog.selected_version + + def clear_wine_version_selection(self): + """Сбрасывает выбор версии Wine.""" + self.wine_version_edit.clear() + self.selected_wine_version_value = None + + def update_create_button_state(self): + """Включает или выключает кнопку 'Создать'.""" + name_ok = bool(self.prefix_name_edit.text().strip()) + version_ok = bool(self.wine_version_edit.text().strip()) + self.create_button.setEnabled(name_ok and version_ok) + + def accept_creation(self): + """Валидирует данные, сохраняет их и закрывает диалог с успехом.""" + prefix_name = self.prefix_name_edit.text().strip() + + if not prefix_name: + QMessageBox.warning(self, "Ошибка", "Имя префикса не может быть пустым.") + return + + if not re.match(r'^[a-zA-Z0-9_.-]+$', prefix_name): + QMessageBox.warning(self, "Ошибка", "Имя префикса может содержать только латинские буквы, цифры, точки, дефисы и подчеркивания.") + return + + prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name) + if os.path.exists(prefix_path): + QMessageBox.warning(self, "Ошибка", f"Префикс с именем '{prefix_name}' уже существует.") + return + + # Save data + self.prefix_name = prefix_name + self.wine_arch = "win32" if self.arch_win32_radio.isChecked() else "win64" + self.base_pfx = "none" if self.type_clean_radio.isChecked() else "" + self.selected_wine_version_display = self.wine_version_edit.text() + + self.accept() + class WineHelperGUI(QMainWindow): def __init__(self): super().__init__() @@ -1279,7 +1406,6 @@ class WineHelperGUI(QMainWindow): self.current_selected_app = None self.icon_animators = {} self.previous_tab_index = 0 - self.selected_wine_version_value = None self.current_managed_prefix_name = None # Имя префикса, выбранного в выпадающем списке self.prefixes_before_install = set() @@ -1804,81 +1930,25 @@ class WineHelperGUI(QMainWindow): ) self.add_tab(installed_tab, "Установленные") - def open_wine_version_dialog(self): - """Открывает диалог выбора версии Wine.""" - architecture = "win32" if self.arch_win32_radio.isChecked() else "win64" - dialog = WineVersionSelectionDialog(architecture, self) - if dialog.exec_() == QDialog.Accepted and dialog.selected_version: - self.wine_version_edit.setText(dialog.selected_display_text) - self.selected_wine_version_value = dialog.selected_version - - def clear_wine_version_selection(self): - """ - Сбрасывает выбор версии Wine при смене архитектуры, - чтобы заставить пользователя выбрать заново. - """ - self.wine_version_edit.clear() - self.selected_wine_version_value = None - def create_prefix_tab(self): """Создает вкладку 'Менеджер префиксов'""" self.prefix_tab = QWidget() layout = QVBoxLayout(self.prefix_tab) layout.setContentsMargins(10, 10, 10, 10) + layout.setSpacing(10) - form_layout = QFormLayout() - form_layout.setSpacing(10) - - self.prefix_name_edit = QLineEdit() - self.prefix_name_edit.setPlaceholderText("Например: my_prefix") - form_layout.addRow("Имя нового префикса:", self.prefix_name_edit) - - arch_widget = QWidget() - arch_layout = QHBoxLayout(arch_widget) - arch_layout.setContentsMargins(0, 0, 0, 0) - self.arch_win32_radio = QRadioButton("32-bit") - self.arch_win64_radio = QRadioButton("64-bit") - self.arch_win64_radio.setChecked(True) - arch_layout.addWidget(self.arch_win32_radio) - arch_layout.addWidget(self.arch_win64_radio) - form_layout.addRow("Разрядность:", arch_widget) - - type_widget = QWidget() - type_layout = QHBoxLayout(type_widget) - type_layout.setContentsMargins(0, 0, 0, 0) - self.type_clean_radio = QRadioButton("Чистый") - self.type_clean_radio.setToolTip("Создает пустой префикс Wine без каких-либо дополнительных компонентов.") - self.type_recommended_radio = QRadioButton("С рекомендуемыми библиотеками") - tooltip_text = "Устанавливает базовый набор компонентов, необходимый для большинства приложений" - self.type_recommended_radio.setToolTip(tooltip_text) - self.type_clean_radio.setChecked(True) - type_layout.addWidget(self.type_clean_radio) - type_layout.addWidget(self.type_recommended_radio) - form_layout.addRow("Наполнение:", type_widget) - - self.wine_version_edit = QLineEdit() - self.wine_version_edit.setReadOnly(True) - self.wine_version_edit.setPlaceholderText("Версия не выбрана") - - select_version_button = QPushButton("Выбрать версию...") - select_version_button.clicked.connect(self.open_wine_version_dialog) - - version_layout = QHBoxLayout() - version_layout.addWidget(self.wine_version_edit) - version_layout.addWidget(select_version_button) - form_layout.addRow("Версия Wine/Proton:", version_layout) - - self.create_prefix_button = QPushButton("Создать префикс") - self.create_prefix_button.setFont(QFont('Arial', 12, QFont.Bold)) - self.create_prefix_button.setStyleSheet("background-color: #0078d7; color: white;") - self.create_prefix_button.setEnabled(False) - self.create_prefix_button.clicked.connect(self.start_prefix_creation) - - layout.addLayout(form_layout) - layout.addWidget(self.create_prefix_button) + # --- Контейнер для создания нового префикса --- + creation_groupbox = QGroupBox() + creation_layout = QVBoxLayout(creation_groupbox) + create_prefix_button = QPushButton("Создать новый префикс") + create_prefix_button.setFont(QFont('Arial', 12, QFont.Bold)) + create_prefix_button.setStyleSheet("background-color: #0078d7; color: white; padding: 5px;") + create_prefix_button.clicked.connect(self.open_create_prefix_dialog) + creation_layout.addWidget(create_prefix_button) + layout.addWidget(creation_groupbox) # --- Контейнер для выбора и управления созданными префиксами --- - self.management_container_groupbox = QGroupBox("Управление созданными префиксами") + self.management_container_groupbox = QGroupBox() self.management_container_groupbox.setVisible(False) # Скрыт, пока нет префиксов container_layout = QVBoxLayout(self.management_container_groupbox) @@ -2003,10 +2073,6 @@ class WineHelperGUI(QMainWindow): layout.addStretch() self.add_tab(self.prefix_tab, "Менеджер префиксов") - self.arch_win32_radio.toggled.connect(self.clear_wine_version_selection) - self.prefix_name_edit.textChanged.connect(self.update_create_prefix_button_state) - self.prefix_name_edit.textChanged.connect(self.on_prefix_name_edited) - 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 _get_current_prefixes(self): @@ -2072,6 +2138,10 @@ class WineHelperGUI(QMainWindow): self._setup_prefix_management_panel(None) self.delete_prefix_button.setEnabled(False) else: + # Прокручиваем к выбранному элементу, чтобы он был виден в списке + self.created_prefix_selector.view().scrollTo( + self.created_prefix_selector.model().index(index, 0) + ) prefix_name = self.created_prefix_selector.itemText(index) self.current_managed_prefix_name = prefix_name self._setup_prefix_management_panel(prefix_name) @@ -2141,12 +2211,6 @@ class WineHelperGUI(QMainWindow): else: QMessageBox.critical(self, "Ошибка удаления", f"Не удалось удалить префикс '{prefix_name}'.\nПодробности смотрите в логе.") - def on_prefix_name_edited(self, text): - """Сбрасывает состояние управления префиксом, когда пользователь вводит новое имя.""" - if text: - if self.created_prefix_selector.currentIndex() != -1: - self.created_prefix_selector.setCurrentIndex(-1) - def _setup_prefix_management_panel(self, prefix_name): """Настраивает панель управления префиксом на основе текущего состояния.""" is_prefix_selected = bool(prefix_name) @@ -2478,40 +2542,29 @@ class WineHelperGUI(QMainWindow): self.add_tab(help_tab, "Справка") - def update_create_prefix_button_state(self): - """Включает или выключает кнопку 'Создать префикс' в зависимости от заполнения полей.""" - name_ok = bool(self.prefix_name_edit.text().strip()) - version_ok = bool(self.wine_version_edit.text().strip()) - self.create_prefix_button.setEnabled(name_ok and version_ok) + def open_create_prefix_dialog(self): + """Открывает диалог создания нового префикса.""" + dialog = CreatePrefixDialog(self) + if dialog.exec_() == QDialog.Accepted: + if not self._show_license_agreement_dialog(): + return - def start_prefix_creation(self): - """Запускает создание префикса после валидации.""" - if not self._show_license_agreement_dialog(): - return + self.start_prefix_creation( + prefix_name=dialog.prefix_name, + wine_arch=dialog.wine_arch, + base_pfx=dialog.base_pfx, + wine_use=dialog.selected_wine_version_value, + wine_use_display=dialog.selected_wine_version_display + ) + + def start_prefix_creation(self, prefix_name, wine_arch, base_pfx, wine_use, wine_use_display): + """Запускает создание префикса с заданными параметрами.""" # Сбрасываем выбор в выпадающем списке, чтобы панель управления скрылась на время создания if self.created_prefix_selector.count() > 0: self.created_prefix_selector.setCurrentIndex(-1) - prefix_name = self.prefix_name_edit.text().strip() - - if not prefix_name: - QMessageBox.warning(self, "Ошибка", "Имя префикса не может быть пустым.") - return - - if not re.match(r'^[a-zA-Z0-9_.-]+$', prefix_name): - QMessageBox.warning(self, "Ошибка", "Имя префикса может содержать только латинские буквы, цифры, точки, дефисы и подчеркивания.") - return - prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name) - if os.path.exists(prefix_path): - QMessageBox.warning(self, "Ошибка", f"Префикс с именем '{prefix_name}' уже существует.") - return - - wine_arch = "win32" if self.arch_win32_radio.isChecked() else "win64" - base_pfx = "none" if self.type_clean_radio.isChecked() else "" - wine_use = self.selected_wine_version_value - wine_use_display = self.wine_version_edit.text() self.command_dialog = QDialog(self) self.command_dialog.setWindowTitle(f"Создание префикса: {prefix_name}") @@ -2584,8 +2637,6 @@ class WineHelperGUI(QMainWindow): if not self.management_container_groupbox.isVisible(): self.management_container_groupbox.setVisible(True) - self.prefix_name_edit.clear() - self.wine_version_edit.clear() QMessageBox.information(self, "Успех", f"Префикс '{prefix_name}' успешно создан.\n" "Теперь вы можете управлять им, выбрав его из выпадающего списка.")