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()