diff --git a/sha256sum.list b/sha256sum.list index 38d14ca..6280738 100644 --- a/sha256sum.list +++ b/sha256sum.list @@ -180,9 +180,6 @@ dfb44ce5e5af7dba1686932c63d6b05e5dd6919a21c78130a7d1d0271b93958e audiorecstatio # create with wine_x_tkg_10-0_amd64 (universal user: xuser) # winetricks dotnet48 gdiplus vcrun6sp6 vcrun2005 vcrun2019 d3dx11_42 d3dx11_43 d3dx9 d3dcompiler_42 d3dcompiler_43 d3dcompiler_46 d3dcompiler_47 richtx32 riched30 riched20 msxml6 dotnet20 -# addons with ODBC, SSH, *.reg -0f4ef434df07bc338ae308af44330590eaa1d9c94b64850514e55b960642d0eb scadoffice_addons_v02.tar.xz - ef7e8f1ba785d48e4ea287feed5b79bd630d423e59efadb43da9653adefef218 ais-lpu-client_pfx_x86_v01.tar.xz # create with wine_x_tkg_10-0_i586 (universal user: xuser) # winetricks vcrun2005 vcrun2008 dotnet20sp2 dotnet40 mfc42 7zip @@ -191,3 +188,7 @@ f18864014fdb2fead0b45b5e70e95073072b89168df8cd6debba89081ac51a2a ksamu_pfx_x64_ # create with wine_x_tkg_10-0_i586 (universal user: xuser) # winetricks msxml6 msxml4 msxml3 riched30 msls31 riched20 msftedit richtx32 fontsmooth=gray # + manuall installed riched32 + +##### ADDONS ##### +# addons with ODBC, SSH, *.reg +0f4ef434df07bc338ae308af44330590eaa1d9c94b64850514e55b960642d0eb scadoffice_addons_v02.tar.xz diff --git a/winehelper b/winehelper index 9edbebe..00dc272 100755 --- a/winehelper +++ b/winehelper @@ -1694,14 +1694,16 @@ select_wine_version() { local total_versions_found=0 # --- System --- - local system_wine_display_name="system" - if command -v wine &>/dev/null; then - local system_wine_version - system_wine_version=$(wine --version 2>/dev/null) - [[ -n "$system_wine_version" ]] && system_wine_display_name="$system_wine_version" + # Добавляем системную версию только для 64-битного префикса + if [[ "$WINEARCH" == "win64" ]]; then + local system_wine_display_name="system" + if command -v wine &>/dev/null; then + local system_wine_version + system_wine_version=$(wine --version 2>/dev/null) + [[ -n "$system_wine_version" ]] && system_wine_display_name="$system_wine_version" + fi + options+=("--- SYSTEM ---" "$system_wine_display_name") fi - options+=("--- SYSTEM ---") - options+=("$system_wine_display_name") # --- Other versions from sha256sum.list --- local current_group="" @@ -1724,8 +1726,22 @@ select_wine_version() { # Отображаем только группы, которые являются сборками WINE или PROTON case "$current_group" in "WINE WOW64"|"WINE AMD64"|"WINE I586") - local pretty_key="$current_group" - options+=("--- $pretty_key ---") + # Фильтрация групп в зависимости от архитектуры префикса + if [[ "$WINEARCH" == "win64" ]]; then + # Для 64-битного префикса скрываем группу I586 + if [[ "$current_group" != "WINE I586" ]]; then + local pretty_key="$current_group" + options+=("--- $pretty_key ---") + else + current_group="" # Игнорируем группу I586 + fi + elif [[ "$WINEARCH" == "win32" ]]; then + # Для 32-битного префикса скрываем только группу WOW64 + if [[ "$current_group" != "WINE WOW64" ]]; then + local pretty_key="$current_group" + options+=("--- $pretty_key ---") + fi + fi ;; *) current_group="" @@ -1736,11 +1752,14 @@ select_wine_version() { local version_name=${filename%.tar.xz} if [[ "$WINEARCH" == "win64" ]]; then - if [[ "$version_name" =~ (amd64|x86_64|wow64) ]] || ! [[ "$version_name" =~ i[3-6]86 ]]; then + # Для 64-битного префикса показываем только 64-битные версии + if ! [[ "$version_name" =~ i[3-6]86 ]]; then group_versions+=("$version_name") fi - else # win32 - group_versions+=("$version_name") + else # Для 32-битного префикса показываем и i586, и amd64 + if [[ "$version_name" =~ (i[3-6]86|amd64) ]]; then + group_versions+=("$version_name") + fi fi fi done < "$sha256_file" @@ -1824,13 +1843,7 @@ select_wine_version() { print_info "Операция отменена." return 1 fi - local selected_opt - selected_opt="${selectable_options[$user_choice]}" - if [[ "$selected_opt" == "$system_wine_display_name" ]]; then - export WH_WINE_USE="system" - else - export WH_WINE_USE="$selected_opt" - fi + export WH_WINE_USE="${selectable_options[$user_choice]}" break else print_error "Неверный выбор. Введите число от 0 до $max_choice." @@ -1839,6 +1852,64 @@ select_wine_version() { return 0 } +select_prepared_prefix() { + local arch="$1" + local sha256_file="$DATA_PATH/sha256sum.list" + [[ ! -f "$sha256_file" ]] && fatal "Файл с описаниями префиксов не найден: $sha256_file" + + options=() + descriptions=() + + options+=("none") + descriptions+=("Создать чистый префикс без дополнительных библиотек") + + local in_prefix_section=false + local current_description="" + while IFS= read -r line; do + if [[ "$line" =~ ^#####[[:space:]]PREFIX[[:space:]]#####$ ]]; then + in_prefix_section=true + continue + elif [[ "$line" =~ ^#####.* ]]; then + if [[ "$in_prefix_section" == true ]] && [[ -n "$current_description" ]]; then + descriptions+=("$(echo -e "$current_description" | sed 's/\\n$//')") + current_description="" + fi + in_prefix_section=false + fi + + if [[ "$in_prefix_section" == true ]]; then + if [[ "$line" =~ ^[a-f0-9]{64} ]]; then + [[ -n "$current_description" ]] && descriptions+=("$(echo -e "$current_description" | sed 's/\\n$//')") + current_description="" + + local filename + filename=$(echo "$line" | awk '{print $2}') + local prefix_name=${filename%.tar.xz} + + if [[ "$arch" == "win32" ]]; then + if [[ "$prefix_name" == *"_x86_"* ]] || [[ "$prefix_name" == *"_i586_"* ]]; then + options+=("$prefix_name") + fi + elif [[ "$arch" == "win64" ]]; then + if [[ "$prefix_name" == *"_x64_"* ]] || [[ "$prefix_name" == *"_amd64_"* ]]; then + options+=("$prefix_name") + fi + fi + elif [[ "$line" =~ ^#[[:space:]] ]]; then + local comment_line=${line:2} # Удаляем '# ' + current_description+="$comment_line\n" + fi + fi + done < "$sha256_file" + + echo + print_info "Выберите тип создаваемого префикса:" + for i in "${!options[@]}"; do + printf "\n\E[36m %s) %s \e[0m\n" "$((i+1))" "${options[$i]}" + [[ -n "${descriptions[$i]}" ]] && printf " \E[33m%s\e[0m\n" "$(echo -e "${descriptions[$i]}" | sed 's/^/ /g')" + done +} + create_prefix() { print_info "Существующие префиксы:" local prefixes=() @@ -1888,19 +1959,22 @@ create_prefix() { select_wine_version || exit 0 - print_info "Выберите тип создаваемого префикса:" - echo " 0) Отмена создания префикса" - echo " 1) Чистый префикс (без библиотек)" - echo " 2) С рекомендуемыми библиотеками" - echo - local pfx_type_choice - read -p "Ваш выбор [0-2] (по умолчанию 1): " pfx_type_choice - case "${pfx_type_choice:-1}" in - 0) print_info "Создание префикса отменено." ; exit 0 ;; - 1) export BASE_PFX="none" ;; - 2) ;; # Оставляем BASE_PFX пустым, чтобы init_wineprefix использовал значение по умолчанию - *) fatal "Неверный выбор. Операция отменена." ;; - esac + select_prepared_prefix "$WINEARCH" + local max_choice=${#options[@]} + local user_choice + while true; do + read -p "Ваш выбор [1-$max_choice] (0 для отмены): " user_choice + if [[ "$user_choice" == "0" ]]; then + print_info "Создание префикса отменено." ; exit 0 + elif [[ "$user_choice" -ge 1 && "$user_choice" -le "$max_choice" ]]; then + export BASE_PFX="${options[$((user_choice-1))]}" + break + else + print_error "Неверный выбор. Введите число от 1 до $max_choice." + fi + done + + print_license_agreement || exit 0 export WINEPREFIX="$WH_PREFIXES_DIR/$prefix_name" diff --git a/winehelper_gui.py b/winehelper_gui.py index 93362c3..6d6213f 100644 --- a/winehelper_gui.py +++ b/winehelper_gui.py @@ -1224,6 +1224,7 @@ class WineVersionSelectionDialog(QDialog): self.installed_grid_layout.setAlignment(Qt.AlignTop) installed_versions_for_grid = [] + # Системная версия if shutil.which('wine'): try: @@ -1231,7 +1232,6 @@ class WineVersionSelectionDialog(QDialog): self.system_wine_display_name = result.stdout.strip() except (FileNotFoundError, subprocess.CalledProcessError) as e: print(f"Не удалось получить версию системного wine: {e}") - self.system_wine_display_name = "Системная версия" installed_versions_for_grid.append((self.system_wine_display_name, "system")) # Локально установленные версии @@ -1265,8 +1265,8 @@ class WineVersionSelectionDialog(QDialog): allowed_groups_for_arch = {"WINE AMD64", "WINE WOW64"} tab_order = ["WINE AMD64", "WINE WOW64"] else: # win32 - allowed_groups_for_arch = {"WINE I586","WINE AMD64", "WINE WOW64"} - tab_order = ["WINE I586","WINE AMD64", "WINE WOW64"] + allowed_groups_for_arch = {"WINE I586","WINE AMD64"} + tab_order = ["WINE I586","WINE AMD64"] # Получаем только те ключи, которые есть в данных и разрешены для данной архитектуры available_keys = [key for key in self.wine_versions_data.keys() if key in allowed_groups_for_arch] @@ -1302,6 +1302,7 @@ class WineVersionSelectionDialog(QDialog): def _create_grid_buttons(self, grid_layout, versions_list, is_download_tab=False): is_win64_prefix = self.architecture == "win64" + is_win32_prefix = self.architecture == "win32" re_32bit_version = re.compile(r'i[3-6]86|i586') num_columns = 3 @@ -1326,6 +1327,12 @@ class WineVersionSelectionDialog(QDialog): btn.setEnabled(False) btn.setToolTip("Эта 32-битная версия Wine несовместима с 64-битным префиксом.") + # Отключение 64-битных версий Wine (системной и wow64) при выборе 32-битного префикса + if not is_download_tab and is_win32_prefix: + if value_name == "system" or 'wow64' in value_name: + btn.setEnabled(False) + btn.setToolTip("Эта 64-битная версия Wine несовместима с 32-битным префиксом.") + grid_layout.addWidget(btn, row, col) col += 1 if col >= num_columns: @@ -1390,6 +1397,7 @@ class CreatePrefixDialog(QDialog): self.prefix_name = None self.wine_arch = None self.base_pfx = None + self.prepared_prefixes = {} self.selected_wine_version_value = None self.selected_wine_version_display = None @@ -1424,18 +1432,10 @@ class CreatePrefixDialog(QDialog): 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.prefix_template_selector = QComboBox() + self.prefix_template_selector.setToolTip("Выберите шаблон для создания префикса.") + form_layout.addRow("Шаблон префикса:", self.prefix_template_selector) self.wine_version_edit = QLineEdit() self.wine_version_edit.setReadOnly(True) @@ -1468,10 +1468,66 @@ class CreatePrefixDialog(QDialog): layout.addLayout(button_layout) # Connect signals - self.arch_win32_radio.toggled.connect(self.clear_wine_version_selection) + self.arch_win32_radio.toggled.connect(self.on_architecture_changed) self.prefix_name_edit.textChanged.connect(self.validate_prefix_name) self.wine_version_edit.textChanged.connect(self.update_create_button_state) + # Загружаем и настраиваем шаблоны префиксов + self._load_prepared_prefixes() + self.on_architecture_changed() + + def _load_prepared_prefixes(self): + """Загружает и парсит шаблоны префиксов из sha256sum.list.""" + self.prepared_prefixes = {'win32': [], 'win64': []} + sha256_file = os.path.join(Var.DATA_PATH, "sha256sum.list") + if not os.path.exists(sha256_file): + QMessageBox.warning(self, "Ошибка", f"Файл с описаниями префиксов не найден: {sha256_file}") + return + + in_prefix_section = False + current_description = "" + current_prefix_name = None + + try: + with open(sha256_file, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if "##### PREFIX #####" in line: + in_prefix_section = True + continue + elif line.startswith("#####"): + in_prefix_section = False + continue + + if not in_prefix_section: + continue + + if re.match(r'^[a-f0-9]{64}', line): + current_prefix_name = line.split(maxsplit=1)[1].replace('.tar.xz', '') + + arch = None + if "_x86_" in current_prefix_name or "_i586_" in current_prefix_name: + arch = 'win32' + elif "_x64_" in current_prefix_name or "_amd64_" in current_prefix_name: + arch = 'win64' + + if arch: + description = current_description.strip().replace('\\n', '\n') if current_description else "Рекомендуемый набор библиотек" + self.prepared_prefixes[arch].append((current_prefix_name, description)) + + current_description = "" + current_prefix_name = None + + elif line.startswith('# '): + current_description += line[2:] + "\\n" + + except IOError as e: + QMessageBox.warning(self, "Ошибка", f"Не удалось прочитать файл с описаниями префиксов: {e}") + + # Добавляем опцию "Чистый префикс" для обеих архитектур + self.prepared_prefixes['win32'].insert(0, ('none', 'Создать чистый префикс без дополнительных библиотек')) + self.prepared_prefixes['win64'].insert(0, ('none', 'Создать чистый префикс без дополнительных библиотек')) + def open_wine_version_dialog(self): """Открывает диалог выбора версии Wine.""" architecture = "win32" if self.arch_win32_radio.isChecked() else "win64" @@ -1480,11 +1536,29 @@ class CreatePrefixDialog(QDialog): self.wine_version_edit.setText(dialog.selected_display_text) self.selected_wine_version_value = dialog.selected_version - def clear_wine_version_selection(self): - """Сбрасывает выбор версии Wine.""" + def on_architecture_changed(self): + """Обновляет список шаблонов и сбрасывает выбор версии Wine при смене архитектуры.""" + # Сбрасываем выбор версии self.wine_version_edit.clear() self.selected_wine_version_value = None + # Обновляем список шаблонов + self.prefix_template_selector.blockSignals(True) + self.prefix_template_selector.clear() + + architecture = "win32" if self.arch_win32_radio.isChecked() else "win64" + templates = self.prepared_prefixes.get(architecture, []) + + for value, description in templates: + # Для 'none' используем более понятное имя + display_name = "Чистый префикс" if value == "none" else value + self.prefix_template_selector.addItem(display_name, userData={'value': value, 'tooltip': description}) + + self.prefix_template_selector.blockSignals(False) + # Обновляем тултип при смене элемента + self.prefix_template_selector.currentIndexChanged.connect(lambda i: self.prefix_template_selector.setToolTip(self.prefix_template_selector.itemData(i)['tooltip'])) + self.prefix_template_selector.setToolTip(self.prefix_template_selector.itemData(0)['tooltip']) + def validate_prefix_name(self, text): """Проверяет имя префикса в реальном времени и показывает/скрывает предупреждение.""" valid_pattern = r'^[a-zA-Z0-9_-]*$' @@ -1528,7 +1602,10 @@ class CreatePrefixDialog(QDialog): # 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 "" + + # Получаем значение `BASE_PFX` из выбранного шаблона + current_index = self.prefix_template_selector.currentIndex() + self.base_pfx = self.prefix_template_selector.itemData(current_index)['value'] self.selected_wine_version_display = self.wine_version_edit.text() self.accept()