Compare commits
	
		
			28 Commits
		
	
	
		
			0.5.4.1
			...
			463306d0cf
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 463306d0cf | ||
|  | 940cface08 | ||
|  | 48d870979f | ||
|  | cbe535b878 | ||
|  | fd3442888d | ||
|  | 7321542477 | ||
|  | 477f44a11e | ||
|  | 4f9821450a | ||
|  | f858746064 | ||
|  | 1123c018eb | ||
|  | 998eff3263 | ||
|  | 4aebb722ca | ||
|  | 4672dcd4e1 | ||
|  | e174b034df | ||
|  | 3100475b1e | ||
|  | 148a7dbfce | ||
|  | 5c01220382 | ||
|  | b74fe77bad | ||
|  | 3a442f6288 | ||
|  | 20030d43e4 | ||
|  | b44849661d | ||
|  | 4c39ec3c8e | ||
|  | 8950d8de2f | ||
|  | 85bd5fdf5d | ||
|  | b98c6e5408 | ||
|  | bab49377a3 | ||
|  | aa591112ff | ||
|  | 08090bbb6b | 
| @@ -4,7 +4,7 @@ _winehelper_completions() { | ||||
|     COMPREPLY=() | ||||
|     cur="${COMP_WORDS[COMP_CWORD]}" | ||||
|     prev="${COMP_WORDS[COMP_CWORD-1]}" | ||||
|     opts="--help --version --debug install installed install-dxvk install-vkd3d -r -i remove-all --clear-pfx killall remove-prefix backup-prefix restore-prefix create-prefix --changelog changelog" | ||||
|     opts="--help --version --debug install installed install-dxvk install-vkd3d -r -i remove-all --clear-pfx killall remove-prefix backup-prefix restore-prefix create-prefix --changelog changelog change-wine" | ||||
|     wine_cmd="winecfg winereg winefile wineconsole winetricks desktop regedit explorer cmd run" | ||||
|  | ||||
|     case "${prev}" in | ||||
| @@ -34,6 +34,20 @@ _winehelper_completions() { | ||||
|         restore-prefix) | ||||
|             return 0 | ||||
|             ;; | ||||
|         install-dxvk|install-vkd3d) | ||||
|             local versions=$(winehelper "${prev}" list 2>/dev/null | grep ' - ' | sed 's/ - //') | ||||
|             COMPREPLY=( $(compgen -W "${versions} none list" -- "${cur}") ) | ||||
|             return 0 | ||||
|             ;; | ||||
|         change-wine) | ||||
|             local wine_versions=$(awk ' | ||||
|                 /^#+\s*(WINE|WINE_LG|PROTON_LG|PROTON_STEAM)\s*#*$/ { in_group=1 } | ||||
|                 /^#+/ { if (! ($0 ~ /^#+\s*(WINE|WINE_LG|PROTON_LG|PROTON_STEAM)\s*#*$/)) in_group=0 } | ||||
|                 /^[a-f0-9]{64}/ && in_group { sub(/\.tar\.xz$/, "", $2); print $2 } | ||||
|             ' /usr/share/winehelper/sha256sum.list 2>/dev/null) | ||||
|             COMPREPLY=( $(compgen -W "system ${wine_versions}" -- "${cur}") ) | ||||
|             return 0 | ||||
|             ;; | ||||
|         *) | ||||
|             ;; | ||||
|     esac | ||||
|   | ||||
| @@ -20,6 +20,7 @@ _winehelper() { | ||||
|     'remove-prefix[Удалить префикс и все связанные данные]' | ||||
|     'backup-prefix[Создать резерную копию префикса]' | ||||
|     'restore-prefix[восстановить префикс из резервной копии "путь/до/whpack"]' | ||||
|     'change-wine[Изменить версию Wine/Proton для префикса]' | ||||
|   ) | ||||
|  | ||||
|   wine_cmd=( | ||||
| @@ -69,6 +70,9 @@ _winehelper() { | ||||
|         install-vkd3d) | ||||
|           _get_component_versions 'install-vkd3d' | ||||
|           ;; | ||||
|         change-wine) | ||||
|           _get_wine_versions | ||||
|           ;; | ||||
|         *) | ||||
|           _values 'winehelper options' "${opts[@]}" "${wine_cmd[@]}" | ||||
|           ;; | ||||
| @@ -87,6 +91,22 @@ _get_component_versions () { | ||||
|   _values 'versions' "${versions[@]}" | ||||
| } | ||||
|  | ||||
| _get_wine_versions () { | ||||
|   local -a versions | ||||
|   local sha256_file="/usr/share/winehelper/sha256sum.list" | ||||
|  | ||||
|   if [[ -f "$sha256_file" ]]; then | ||||
|     versions=( ${(f)"$(awk ' | ||||
|         /^#+\s*(WINE|WINE_LG|PROTON_LG|PROTON_STEAM)\s*#*$/ { in_group=1 } | ||||
|         /^#+/ { if (! ($0 ~ /^#+\s*(WINE|WINE_LG|PROTON_LG|PROTON_STEAM)\s*#*$/)) in_group=0 } | ||||
|         /^[a-f0-9]{64}/ && in_group { sub(/\.tar\.xz$/, "", $2); print $2 } | ||||
|     ' "$sha256_file" 2>/dev/null)"} ) | ||||
|   fi | ||||
|  | ||||
|   versions+=(system) | ||||
|   _values 'wine/proton versions' "${versions[@]}" | ||||
| } | ||||
|  | ||||
| _get_prefixes () { | ||||
|   prefixes=( ${(f)"$(ls -1 ~/.local/share/winehelper/prefixes 2>/dev/null)"} ) | ||||
|  | ||||
|   | ||||
							
								
								
									
										39
									
								
								autoinstall/arm-kt-att
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								autoinstall/arm-kt-att
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru: Программа “АРМ КТ ПРОФ АТТЕСТАТ” для документов об основном общем, среднем общем образовании. | ||||
| ######################################################################## | ||||
| export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-4" | ||||
| export WH_WINE_USE="wine_x_tkg_10-0_amd64" | ||||
| export WINEPREFIX="arm-kt" | ||||
| export PROG_NAME="АРМ КТ ПРОФ АТТЕСТАТ" | ||||
| export PROG_ICON="armkt" | ||||
| export BASE_PFX="none" | ||||
| export WINEARCH="win64" | ||||
| export INSTALL_DLL="" | ||||
| export WH_WINDOWS_VER="7" | ||||
|  | ||||
| AUTOINSTALL_URL=$(curl -s "$PROG_URL" | grep "setup.zip" | awk -F'"' '{print $2}') | ||||
| SHORT_NAME=$(echo $AUTOINSTALL_URL | awk -F'/' '{print $5}') | ||||
| VER_EXE=$(echo $AUTOINSTALL_URL | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') | ||||
| AUTOINSTALL_ZIP="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.zip" | ||||
| AUTOINSTALL_EXE="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.exe" | ||||
|  | ||||
| if [[ -z $VER_EXE ]] | ||||
| then fatal "Не удалось получить версию ПО со страницы на сайте!" | ||||
| else print_info "Устанавливаем $PROG_NAME версии $VER_EXE" | ||||
| fi | ||||
|  | ||||
| prepair_wine | ||||
|  | ||||
| if try_download "$AUTOINSTALL_URL" "$AUTOINSTALL_ZIP" ; then | ||||
|     unpack "$AUTOINSTALL_ZIP" "${WH_TMP_DIR}" | ||||
|     try_remove_file "$AUTOINSTALL_ZIP" | ||||
|  | ||||
|     wine_run_install "${AUTOINSTALL_EXE}" /VERYSILENT | ||||
|     try_remove_file "${AUTOINSTALL_EXE}" | ||||
|  | ||||
|     create_desktop "$PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/$SHORT_NAME.exe" "$PROG_ICON" | ||||
|  | ||||
|     create_desktop "Регистрация $PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/${SHORT_NAME}Reg.exe" "$PROG_ICON" | ||||
| fi | ||||
							
								
								
									
										39
									
								
								autoinstall/arm-kt-dpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								autoinstall/arm-kt-dpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru: Программа “АРМ КТ ПРОФ ДПП” для заполнения бланков документов о повышении квалификации и профессиональной переподготовке. | ||||
| ######################################################################## | ||||
| export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank" | ||||
| export WH_WINE_USE="wine_x_tkg_10-0_amd64" | ||||
| export WINEPREFIX="arm-kt" | ||||
| export PROG_NAME="АРМ КТ ПРОФ ДПП" | ||||
| export PROG_ICON="armkt" | ||||
| export BASE_PFX="none" | ||||
| export WINEARCH="win64" | ||||
| export INSTALL_DLL="" | ||||
| export WH_WINDOWS_VER="7" | ||||
|  | ||||
| AUTOINSTALL_URL=$(curl -s "$PROG_URL" | grep "setup.zip" | awk -F'"' '{print $2}') | ||||
| SHORT_NAME=$(echo $AUTOINSTALL_URL | awk -F'/' '{print $5}') | ||||
| VER_EXE=$(echo $AUTOINSTALL_URL | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') | ||||
| AUTOINSTALL_ZIP="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.zip" | ||||
| AUTOINSTALL_EXE="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.exe" | ||||
|  | ||||
| if [[ -z $VER_EXE ]] | ||||
| then fatal "Не удалось получить версию ПО со страницы на сайте!" | ||||
| else print_info "Устанавливаем $PROG_NAME версии $VER_EXE" | ||||
| fi | ||||
|  | ||||
| prepair_wine | ||||
|  | ||||
| if try_download "$AUTOINSTALL_URL" "$AUTOINSTALL_ZIP" ; then | ||||
|     unpack "$AUTOINSTALL_ZIP" "${WH_TMP_DIR}" | ||||
|     try_remove_file "$AUTOINSTALL_ZIP" | ||||
|  | ||||
|     wine_run_install "${AUTOINSTALL_EXE}" /VERYSILENT | ||||
|     try_remove_file "${AUTOINSTALL_EXE}" | ||||
|  | ||||
|     create_desktop "$PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/$SHORT_NAME.exe" "$PROG_ICON" | ||||
|  | ||||
|     create_desktop "Регистрация $PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/${SHORT_NAME}Reg.exe" "$PROG_ICON" | ||||
| fi | ||||
							
								
								
									
										35
									
								
								autoinstall/arm-kt-es
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								autoinstall/arm-kt-es
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru: Программа “АРМ КТ ПРОФ НШ” для заполнения бланков документов об окончании начальной школы. | ||||
| ######################################################################## | ||||
| export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-1" | ||||
| export WH_WINE_USE="wine_x_tkg_10-0_amd64" | ||||
| export WINEPREFIX="arm-kt" | ||||
| export PROG_NAME="АРМ КТ ПРОФ НШ" | ||||
| export PROG_ICON="armkt" | ||||
| export BASE_PFX="none" | ||||
| export WINEARCH="win64" | ||||
| export INSTALL_DLL="" | ||||
| export WH_WINDOWS_VER="7" | ||||
|  | ||||
| AUTOINSTALL_URL=$(curl -s "$PROG_URL" | grep "setup.exe" | awk -F'"' '{print $2}') | ||||
| SHORT_NAME=$(echo $AUTOINSTALL_URL | awk -F'/' '{print $5}') | ||||
| VER_EXE=$(echo $AUTOINSTALL_URL | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') | ||||
| AUTOINSTALL_EXE="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.exe" | ||||
|  | ||||
| if [[ -z $VER_EXE ]] | ||||
| then fatal "Не удалось получить версию ПО со страницы на сайте!" | ||||
| else print_info "Устанавливаем $PROG_NAME версии $VER_EXE" | ||||
| fi | ||||
|  | ||||
| prepair_wine | ||||
|  | ||||
| if try_download "$AUTOINSTALL_URL" "$AUTOINSTALL_EXE" ; then | ||||
|     wine_run_install "${AUTOINSTALL_EXE}" /VERYSILENT | ||||
|     try_remove_file "${AUTOINSTALL_EXE}" | ||||
|  | ||||
|     create_desktop "$PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/$SHORT_NAME.exe" "$PROG_ICON" | ||||
|  | ||||
|     create_desktop "Регистрация $PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/${SHORT_NAME}Reg.exe" "$PROG_ICON" | ||||
| fi | ||||
							
								
								
									
										39
									
								
								autoinstall/arm-kt-med
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								autoinstall/arm-kt-med
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru: Программа “АРМ КТ ПРОФ МЕД” для заполнения бланков документов о послевузовском профессиональном образовании и сертификатов специалиста. | ||||
| ###################################################### | ||||
| export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-3" | ||||
| export WH_WINE_USE="wine_x_tkg_10-0_amd64" | ||||
| export WINEPREFIX="arm-kt" | ||||
| export PROG_NAME="АРМ КТ ПРОФ МЕД" | ||||
| export PROG_ICON="armkt" | ||||
| export BASE_PFX="none" | ||||
| export WINEARCH="win64" | ||||
| export INSTALL_DLL="" | ||||
| export WH_WINDOWS_VER="7" | ||||
|  | ||||
| AUTOINSTALL_URL=$(curl -s "$PROG_URL" | grep "setup.zip" | awk -F'"' '{print $2}') | ||||
| SHORT_NAME=$(echo $AUTOINSTALL_URL | awk -F'/' '{print $5}') | ||||
| VER_EXE=$(echo $AUTOINSTALL_URL | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') | ||||
| AUTOINSTALL_ZIP="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.zip" | ||||
| AUTOINSTALL_EXE="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.exe" | ||||
|  | ||||
| if [[ -z $VER_EXE ]] | ||||
| then fatal "Не удалось получить версию ПО со страницы на сайте!" | ||||
| else print_info "Устанавливаем $PROG_NAME версии $VER_EXE" | ||||
| fi | ||||
|  | ||||
| prepair_wine | ||||
|  | ||||
| if try_download "$AUTOINSTALL_URL" "$AUTOINSTALL_ZIP" ; then | ||||
|     unpack "$AUTOINSTALL_ZIP" "${WH_TMP_DIR}" | ||||
|     try_remove_file "$AUTOINSTALL_ZIP" | ||||
|  | ||||
|     wine_run_install "${AUTOINSTALL_EXE}" /VERYSILENT | ||||
|     try_remove_file "${AUTOINSTALL_EXE}" | ||||
|  | ||||
|     create_desktop "$PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/$SHORT_NAME.exe" "$PROG_ICON" | ||||
|  | ||||
|     create_desktop "Регистрация $PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/${SHORT_NAME}Reg.exe" "$PROG_ICON" | ||||
| fi | ||||
							
								
								
									
										39
									
								
								autoinstall/arm-kt-prof
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								autoinstall/arm-kt-prof
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru: Программа “АРМ КТ ПРОФ ПРОФЕССИЯ” для заполнения бланков документов профессионального обучения. | ||||
| ######################################################################## | ||||
| export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-5" | ||||
| export WH_WINE_USE="wine_x_tkg_10-0_amd64" | ||||
| export WINEPREFIX="arm-kt" | ||||
| export PROG_NAME="АРМ КТ ПРОФ ПРОФЕССИЯ" | ||||
| export PROG_ICON="armkt" | ||||
| export BASE_PFX="none" | ||||
| export WINEARCH="win64" | ||||
| export INSTALL_DLL="" | ||||
| export WH_WINDOWS_VER="7" | ||||
|  | ||||
| AUTOINSTALL_URL=$(curl -s "$PROG_URL" | grep "setup.zip" | awk -F'"' '{print $2}') | ||||
| SHORT_NAME=$(echo $AUTOINSTALL_URL | awk -F'/' '{print $5}') | ||||
| VER_EXE=$(echo $AUTOINSTALL_URL | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') | ||||
| AUTOINSTALL_ZIP="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.zip" | ||||
| AUTOINSTALL_EXE="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.exe" | ||||
|  | ||||
| if [[ -z $VER_EXE ]] | ||||
| then fatal "Не удалось получить версию ПО со страницы на сайте!" | ||||
| else print_info "Устанавливаем $PROG_NAME версии $VER_EXE" | ||||
| fi | ||||
|  | ||||
| prepair_wine | ||||
|  | ||||
| if try_download "$AUTOINSTALL_URL" "$AUTOINSTALL_ZIP" ; then | ||||
|     unpack "$AUTOINSTALL_ZIP" "${WH_TMP_DIR}" | ||||
|     try_remove_file "$AUTOINSTALL_ZIP" | ||||
|  | ||||
|     wine_run_install "${AUTOINSTALL_EXE}" /VERYSILENT | ||||
|     try_remove_file "${AUTOINSTALL_EXE}" | ||||
|  | ||||
|     create_desktop "$PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/$SHORT_NAME.exe" "$PROG_ICON" | ||||
|  | ||||
|     create_desktop "Регистрация $PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/${SHORT_NAME}Reg.exe" "$PROG_ICON" | ||||
| fi | ||||
							
								
								
									
										39
									
								
								autoinstall/arm-kt-spo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								autoinstall/arm-kt-spo
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru: Программа “АРМ КТ ПРОФ СПО” для заполнения бланков документов о среднем профессиональном образовании. | ||||
| ######################################################################## | ||||
| export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-2" | ||||
| export WH_WINE_USE="wine_x_tkg_10-0_amd64" | ||||
| export WINEPREFIX="arm-kt" | ||||
| export PROG_NAME="АРМ КТ ПРОФ СПО" | ||||
| export PROG_ICON="armkt" | ||||
| export BASE_PFX="none" | ||||
| export WINEARCH="win64" | ||||
| export INSTALL_DLL="" | ||||
| export WH_WINDOWS_VER="7" | ||||
|  | ||||
| AUTOINSTALL_URL=$(curl -s "$PROG_URL" | grep "setup.zip" | awk -F'"' '{print $2}') | ||||
| SHORT_NAME=$(echo $AUTOINSTALL_URL | awk -F'/' '{print $5}') | ||||
| VER_EXE=$(echo $AUTOINSTALL_URL | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') | ||||
| AUTOINSTALL_ZIP="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.zip" | ||||
| AUTOINSTALL_EXE="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.exe" | ||||
|  | ||||
| if [[ -z $VER_EXE ]] | ||||
| then fatal "Не удалось получить версию ПО со страницы на сайте!" | ||||
| else print_info "Устанавливаем $PROG_NAME версии $VER_EXE" | ||||
| fi | ||||
|  | ||||
| prepair_wine | ||||
|  | ||||
| if try_download "$AUTOINSTALL_URL" "$AUTOINSTALL_ZIP" ; then | ||||
|     unpack "$AUTOINSTALL_ZIP" "${WH_TMP_DIR}" | ||||
|     try_remove_file "$AUTOINSTALL_ZIP" | ||||
|  | ||||
|     wine_run_install "${AUTOINSTALL_EXE}" /VERYSILENT | ||||
|     try_remove_file "${AUTOINSTALL_EXE}" | ||||
|  | ||||
|     create_desktop "$PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/$SHORT_NAME.exe" "$PROG_ICON" | ||||
|  | ||||
|     create_desktop "Регистрация $PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/${SHORT_NAME}Reg.exe" "$PROG_ICON" | ||||
| fi | ||||
							
								
								
									
										39
									
								
								autoinstall/arm-kt-vuz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								autoinstall/arm-kt-vuz
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru: Программа “АРМ КТ ПРОФ ВУЗ” для заполнения бланков документов о высшем образовании. | ||||
| ######################################################################## | ||||
| export PROG_URL="https://armregistr.ru/programmnoe-obespechenie/licenziya-na-programmnoe-obespechenie-dlya-zapolneniya-blank-6" | ||||
| export WH_WINE_USE="wine_x_tkg_10-0_amd64" | ||||
| export WINEPREFIX="arm-kt" | ||||
| export PROG_NAME="АРМ КТ ПРОФ ВУЗ" | ||||
| export PROG_ICON="armkt" | ||||
| export BASE_PFX="none" | ||||
| export WINEARCH="win64" | ||||
| export INSTALL_DLL="" | ||||
| export WH_WINDOWS_VER="7" | ||||
|  | ||||
| AUTOINSTALL_URL=$(curl -s "$PROG_URL" | grep "setup.zip" | awk -F'"' '{print $2}') | ||||
| SHORT_NAME=$(echo $AUTOINSTALL_URL | awk -F'/' '{print $5}') | ||||
| VER_EXE=$(echo $AUTOINSTALL_URL | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+') | ||||
| AUTOINSTALL_ZIP="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.zip" | ||||
| AUTOINSTALL_EXE="${WH_TMP_DIR}/$SHORT_NAME-$VER_EXE-setup.exe" | ||||
|  | ||||
| if [[ -z $VER_EXE ]] | ||||
| then fatal "Не удалось получить версию ПО со страницы на сайте!" | ||||
| else print_info "Устанавливаем $PROG_NAME версии $VER_EXE" | ||||
| fi | ||||
|  | ||||
| prepair_wine | ||||
|  | ||||
| if try_download "$AUTOINSTALL_URL" "$AUTOINSTALL_ZIP" ; then | ||||
|     unpack "$AUTOINSTALL_ZIP" "${WH_TMP_DIR}" | ||||
|     try_remove_file "$AUTOINSTALL_ZIP" | ||||
|  | ||||
|     wine_run_install "${AUTOINSTALL_EXE}" /VERYSILENT | ||||
|     try_remove_file "${AUTOINSTALL_EXE}" | ||||
|  | ||||
|     create_desktop "$PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/$SHORT_NAME.exe" "$PROG_ICON" | ||||
|  | ||||
|     create_desktop "Регистрация $PROG_NAME" \ | ||||
|     "$DRIVE_C/Program Files/KtSoftware/$SHORT_NAME/${SHORT_NAME}Reg.exe" "$PROG_ICON" | ||||
| fi | ||||
							
								
								
									
										
											BIN
										
									
								
								image/armkt.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								image/armkt.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 23 KiB | 
							
								
								
									
										64
									
								
								winehelper
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								winehelper
									
									
									
									
									
								
							| @@ -7,18 +7,20 @@ if [[ $(id -u) -eq 0 ]] ; then | ||||
| fi | ||||
|  | ||||
| ##### DEFAULT PATH ##### | ||||
| export SCRIPT_NAME USER_WORK_PATH RUN_SCRIPT DATA_PATH CHANGELOG_FILE WH_ICON_PATH LICENSE_FILE AGREEMENT | ||||
| export SCRIPT_NAME USER_WORK_PATH RUN_SCRIPT DATA_PATH CHANGELOG_FILE WH_ICON_PATH LICENSE_FILE AGREEMENT THIRD_PARTY_FILE | ||||
|  | ||||
| SCRIPT_NAME="$(basename "$0")" | ||||
| if [[ "$(realpath "$0")" == "/usr/bin/$SCRIPT_NAME" ]] ; then | ||||
|     # переменные для установленного WineHelper в систему | ||||
|     WH_VERSION="$(rpm -q winehelper | awk -F'-' '{print $2}')" | ||||
|     USER_WORK_PATH="$HOME/.local/share/$SCRIPT_NAME" | ||||
|     RUN_SCRIPT="/usr/bin/$SCRIPT_NAME" | ||||
|     DATA_PATH="/usr/share/$SCRIPT_NAME" | ||||
|     CHANGELOG_FILE="$(realpath "/usr/share/doc/winehelper"-*/CHANGELOG)" | ||||
|     WH_ICON_PATH="$DATA_PATH/image/gui/winehelper.svg" | ||||
|     LICENSE_FILE="$(realpath "/usr/share/doc/winehelper"-*/LICENSE)" | ||||
|     AGREEMENT="$(realpath "/usr/share/doc/winehelper"-*/LICENSE_AGREEMENT)" | ||||
|     CHANGELOG_FILE="/usr/share/doc/winehelper-$WH_VERSION/CHANGELOG" | ||||
|     LICENSE_FILE="/usr/share/doc/winehelper-$WH_VERSION/LICENSE" | ||||
|     AGREEMENT="/usr/share/doc/winehelper-$WH_VERSION/LICENSE_AGREEMENT" | ||||
|     THIRD_PARTY_FILE="/usr/share/doc/winehelper-$WH_VERSION/THIRD-PARTY" | ||||
| else | ||||
|     # переменные для тестового запуска WineHelper из репозитория | ||||
|     USER_WORK_PATH="$HOME/test-$SCRIPT_NAME" | ||||
| @@ -28,6 +30,7 @@ else | ||||
|     WH_ICON_PATH="$DATA_PATH/image/gui/winehelper-devel.svg" | ||||
|     LICENSE_FILE="$DATA_PATH/LICENSE" | ||||
|     AGREEMENT="$DATA_PATH/LICENSE_AGREEMENT" | ||||
|     THIRD_PARTY_FILE="$DATA_PATH/THIRD-PARTY" | ||||
|  | ||||
|     # минимальная проверка синтаксиса скриптов | ||||
|     for self_check_script in "$RUN_SCRIPT" \ | ||||
| @@ -614,6 +617,7 @@ create_desktop () { | ||||
|         echo "StartupNotify=true" | ||||
|         echo "Path=$DATA_PATH" | ||||
|         echo "Icon=$icon_file" | ||||
|         echo "StartupWMClass=$(basename "$exe_file")" | ||||
|     } > "$USER_WORK_PATH/$desktop_filename.desktop" | ||||
|     chmod +x "$USER_WORK_PATH/$desktop_filename.desktop" | ||||
|  | ||||
| @@ -649,7 +653,7 @@ create_desktop () { | ||||
| [Desktop Entry] | ||||
| Type=Directory | ||||
| Name=WineHelper | ||||
| Icon=wine | ||||
| Icon=winehelper | ||||
| EOF | ||||
|     fi | ||||
|  | ||||
| @@ -1352,8 +1356,6 @@ init_database () { | ||||
| } | ||||
|  | ||||
| prepair_wine () { | ||||
|     var_winedlloverride_update "winemenubuilder.exe=d" | ||||
|  | ||||
|     if [[ -n "$INSTALL_SCRIPT_NAME" ]] | ||||
|     then print_info "Используются настройки из скрипта установки: $INSTALL_SCRIPT_NAME" | ||||
|     else init_database | ||||
| @@ -1652,8 +1654,8 @@ select_wine_version() { | ||||
|         read -p "Введите номер для выбора wine/proton (0-$max_choice): " user_choice | ||||
|         if [[ "$user_choice" =~ ^[0-9]+$ ]] && (( user_choice >= 0 && user_choice <= max_choice )); then | ||||
|             if [[ "$user_choice" == "0" ]]; then | ||||
|                 print_info "Создание префикса отменено." | ||||
|                 exit 0 | ||||
|                 print_info "Операция отменена." | ||||
|                 return 1 | ||||
|             fi | ||||
|             local selected_opt | ||||
|             selected_opt="${selectable_options[$user_choice]}" | ||||
| @@ -1667,6 +1669,7 @@ select_wine_version() { | ||||
|             print_error "Неверный выбор. Введите число от 0 до $max_choice." | ||||
|         fi | ||||
|     done | ||||
|     return 0 | ||||
| } | ||||
|  | ||||
| create_prefix() { | ||||
| @@ -1716,7 +1719,7 @@ create_prefix() { | ||||
|         *) fatal "Неверный выбор. Операция отменена." ;; | ||||
|     esac | ||||
|  | ||||
|     select_wine_version | ||||
|     select_wine_version || exit 0 | ||||
|  | ||||
|     print_info "Выберите тип создаваемого префикса:" | ||||
|     echo " 0) Отмена создания префикса" | ||||
| @@ -2123,6 +2126,19 @@ select_component_version() { | ||||
|     done | ||||
| } | ||||
|  | ||||
| run_install_to_prefix() { | ||||
|     export WINEPREFIX="$1" | ||||
|     local WIN_FILE_EXEC="$2" | ||||
|  | ||||
|     if [[ -z "$WINEPREFIX" ]] || [[ -z "$WIN_FILE_EXEC" ]]; then | ||||
|         fatal "Использование: $SCRIPT_NAME install-to-prefix <имя_префикса> <путь_к_установщику>" | ||||
|     fi | ||||
|  | ||||
|     check_prefix_var | ||||
|     prepair_wine | ||||
|     wine_run_install "$WIN_FILE_EXEC" | ||||
| } | ||||
|  | ||||
| run_install_dxvk() { | ||||
|     local version="$1" | ||||
|     if [[ -z "$version" ]] ; then | ||||
| @@ -2171,6 +2187,27 @@ run_install_vkd3d() { | ||||
|     wait_wineserver | ||||
| } | ||||
|  | ||||
| run_change_wine_version() { | ||||
|     local new_version="$1" | ||||
|  | ||||
|     check_prefix_var | ||||
|     init_database | ||||
|  | ||||
|     if [[ -z "$new_version" ]]; then | ||||
|         select_wine_version || exit 0 | ||||
|         new_version="$WH_WINE_USE" | ||||
|     else | ||||
|         export WH_WINE_USE="$new_version" | ||||
|     fi | ||||
|  | ||||
|     init_wine_ver | ||||
|  | ||||
|     init_wineprefix | ||||
|  | ||||
|     wait_wineserver | ||||
|     print_ok "Версия Wine для префикса $PREFIX_NAME успешно изменена на $WH_WINE_USE." | ||||
| } | ||||
|  | ||||
| wh_info () { | ||||
|     echo "Использование: $SCRIPT_NAME [команда] | ||||
|  | ||||
| @@ -2181,6 +2218,7 @@ wh_info () { | ||||
|  | ||||
|     install-dxvk [версия|none|list] установить, удалить или показать версии DXVK | ||||
|     install-vkd3d [версия|none|list] установить, удалить или показать версии VKD3D | ||||
|     change-wine [версия]            изменить версию Wine/Proton для текущего префикса | ||||
|  | ||||
|     installed                       список установленных программ | ||||
|     run [программа]                 запуск программы (отладка) | ||||
| @@ -2217,6 +2255,10 @@ else | ||||
|     arg1="--help" | ||||
| fi | ||||
|  | ||||
| # отключаем создание .desktop файлов средствами wine | ||||
| # и отключаем winebth, так как может сломать winedevice.exe | ||||
| var_winedlloverride_update "winemenubuilder.exe,winebth.sys=d" | ||||
|  | ||||
| case "$arg1" in | ||||
|     --version|version) rpm -qi "$SCRIPT_NAME" ; exit 0 ;; | ||||
|     --help|help) wh_info ; exit 0 ;; | ||||
| @@ -2229,8 +2271,10 @@ case "$arg1" in | ||||
|     winetricks) prepair_wine ; "$WH_WINETRICKS" -q "$@" ;; | ||||
|     desktop) create_desktop "$@" ; exit 0 ;; | ||||
|     install|-i) run_autoinstall "$@" ;; | ||||
|     install-to-prefix) run_install_to_prefix "$@" ;; | ||||
|     install-dxvk) run_install_dxvk "$@" ;; | ||||
|     install-vkd3d) run_install_vkd3d "$@" ;; | ||||
|     change-wine) run_change_wine_version "$@" ;; | ||||
|     installed) check_installed_programs "$1" ;; | ||||
|     run|-r) run_installed_programs "$1" ;; | ||||
|     backup-prefix) backup_prefix "$@" ;; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| #!/usr/bin/env xdg-open | ||||
| [Desktop Entry] | ||||
| Name=WineHelper | ||||
| Exec=winehelper gui %F | ||||
| @@ -7,3 +8,4 @@ Type=Application | ||||
| Categories=WineHelper;Utility;Emulator; | ||||
| StartupNotify=true | ||||
| Icon=winehelper | ||||
| StartupWMClass=winehelper | ||||
|   | ||||
| @@ -28,6 +28,7 @@ class Var: | ||||
|     WH_ICON_PATH = os.environ.get("WH_ICON_PATH") | ||||
|     LICENSE_FILE = os.environ.get("LICENSE_FILE") | ||||
|     LICENSE_AGREEMENT_FILE = os.environ.get("AGREEMENT") | ||||
|     THIRD_PARTY_FILE = os.environ.get("THIRD_PARTY_FILE") | ||||
|  | ||||
| class DependencyManager: | ||||
|     """Класс для управления проверкой и установкой системных зависимостей.""" | ||||
| @@ -42,14 +43,10 @@ class DependencyManager: | ||||
|  | ||||
|     def _get_dependencies_path(self): | ||||
|         """Определяет и возвращает путь к скрипту dependencies.sh.""" | ||||
|         if Var.DATA_PATH: | ||||
|             base_path = Var.DATA_PATH | ||||
|         elif Var.RUN_SCRIPT and os.path.exists(Var.RUN_SCRIPT): | ||||
|             base_path = os.path.dirname(Var.RUN_SCRIPT) | ||||
|         else: | ||||
|         if not Var.DATA_PATH: | ||||
|             return None | ||||
|  | ||||
|         return os.path.join(base_path, 'dependencies.sh') | ||||
|         return os.path.join(Var.DATA_PATH, 'dependencies.sh') | ||||
|  | ||||
|     def _calculate_file_hash(self): | ||||
|         """Вычисляет хэш SHA256 файла зависимостей.""" | ||||
| @@ -477,10 +474,9 @@ class WinetricksManagerDialog(QDialog): | ||||
|         self.log_output.setText(self.INFO_TEXT) | ||||
|         main_layout.addWidget(self.log_output) | ||||
|  | ||||
|         # Кнопки управления | ||||
|         # Кнопки управления, выровненные по правому краю | ||||
|         button_layout = QHBoxLayout() | ||||
|         self.status_label = QLabel("Загрузка компонентов...") | ||||
|         button_layout.addWidget(self.status_label, 1) | ||||
|         button_layout.addStretch(1) | ||||
|  | ||||
|         self.apply_button = QPushButton("Применить") | ||||
|         self.apply_button.setEnabled(False) | ||||
| @@ -551,7 +547,6 @@ class WinetricksManagerDialog(QDialog): | ||||
|     def load_all_categories(self): | ||||
|         """Запускает загрузку всех категорий.""" | ||||
|         self.loading_count = len(self.categories) | ||||
|         self.category_statuses = {name: "загрузка..." for name in self.categories.keys()} | ||||
|         for internal_name in self.categories.values(): | ||||
|             self._start_load_process(internal_name) | ||||
|  | ||||
| @@ -605,13 +600,6 @@ class WinetricksManagerDialog(QDialog): | ||||
|         process.finished.connect(partial(self._on_load_finished, category)) | ||||
|         process.start(self.winetricks_path, [category, "list"]) | ||||
|  | ||||
|     def _update_status_label(self): | ||||
|         """Обновляет текстовую метку состояния загрузки.""" | ||||
|         status_parts = [] | ||||
|         for name, status in self.category_statuses.items(): | ||||
|             status_parts.append(f"{name}: {status}") | ||||
|         self.status_label.setText(" | ".join(status_parts)) | ||||
|  | ||||
|     def _parse_winetricks_log(self): | ||||
|         """Читает winetricks.log и возвращает множество установленных компонентов.""" | ||||
|         installed_verbs = set() | ||||
| @@ -684,22 +672,15 @@ class WinetricksManagerDialog(QDialog): | ||||
|  | ||||
|         if exit_code != 0 or exit_status != QProcess.NormalExit: | ||||
|             error_string = process.errorString() if process else "N/A" | ||||
|             self._log(f"--- Ошибка загрузки категории '{category}' (код: {exit_code}) ---", "red") | ||||
|             self.category_statuses[category_display_name] = "ошибка" | ||||
|             self._update_status_label() # Показываем ошибку в статусе | ||||
|             self._log(f"--- Ошибка загрузки категории '{category_display_name}' (код: {exit_code}) ---", "red") | ||||
|             if exit_status == QProcess.CrashExit: | ||||
|                 self._log("--- Процесс winetricks завершился аварийно. ---", "red") | ||||
|             # По умолчанию используется "Неизвестная ошибка", которая не очень полезна. | ||||
|             if error_string != "Неизвестная ошибка": | ||||
|                 self._log(f"--- Системная ошибка: {error_string} ---", "red") | ||||
|             self._log(output if output.strip() else "Winetricks не вернул вывод. Проверьте, что он работает корректно.") | ||||
|             self._log("--------------------------------------------------", "red") | ||||
|         else: | ||||
|             self.category_statuses[category_display_name] = "готово" | ||||
|             installed_verbs = self._parse_winetricks_log() | ||||
|             # Обновляем статус только если это была сетевая загрузка | ||||
|             if from_cache is None: | ||||
|                 self._update_status_label() | ||||
|             found_items = self._parse_winetricks_list_output(output, installed_verbs, list_widget) | ||||
|  | ||||
|             if from_cache is None:  # Только если мы не читали из кэша | ||||
| @@ -724,7 +705,6 @@ class WinetricksManagerDialog(QDialog): | ||||
|  | ||||
|         self.loading_count -= 1 | ||||
|         if self.loading_count == 0: | ||||
|             self.status_label.setText("Готово.") | ||||
|             self._update_ui_state() | ||||
|  | ||||
|     def _on_item_changed(self, item): | ||||
| @@ -865,11 +845,6 @@ class WinetricksManagerDialog(QDialog): | ||||
|  | ||||
|         # 3. Обрабатываем успех | ||||
|         self._log("\n=== Все операции успешно завершены ===") | ||||
|         self._show_message_box("Успех", | ||||
|                                "Операции с компонентами были успешно выполнены.", | ||||
|                                QMessageBox.Information, | ||||
|                                {"buttons": {"Да": QMessageBox.AcceptRole}}) | ||||
|  | ||||
|         self.apply_button.setEnabled(True) | ||||
|         self.reinstall_button.setEnabled(False) # Сбрасываем в неактивное состояние | ||||
|         self.close_button.setEnabled(True) | ||||
| @@ -879,7 +854,6 @@ class WinetricksManagerDialog(QDialog): | ||||
|             search_edit.clear() | ||||
|  | ||||
|         # Перезагружаем данные, чтобы обновить состояние | ||||
|         self.status_label.setText("Обновление данных...") | ||||
|         self.initial_states.clear() | ||||
|         self.load_all_categories() | ||||
|         self.installation_finished = True | ||||
| @@ -1574,6 +1548,12 @@ class WineHelperGUI(QMainWindow): | ||||
|  | ||||
|         # Загружаем состояние после создания всех виджетов | ||||
|         self._load_created_prefixes() | ||||
|         # После загрузки выбираем первый элемент, если он доступен | ||||
|         if self.created_prefix_selector.count() > 0: | ||||
|             self.created_prefix_selector.setCurrentIndex(0) | ||||
|         else: | ||||
|             # Если список пуст, сбрасываем панель управления | ||||
|             self.on_created_prefix_selected(-1) | ||||
|  | ||||
|         # Инициализируем состояние, которое будет использоваться для логов | ||||
|         self._reset_log_state() | ||||
| @@ -2109,80 +2089,79 @@ class WineHelperGUI(QMainWindow): | ||||
|         self.prefix_winefile_button.setToolTip("Запуск файлового менеджера Wine (winefile) для просмотра файлов внутри префикса.") | ||||
|         management_layout.addWidget(self.prefix_winefile_button, 2, 1) | ||||
|  | ||||
|         # Добавляем небольшой отступ | ||||
|         spacer_widget = QWidget() | ||||
|         spacer_widget.setFixedHeight(5) | ||||
|         management_layout.addWidget(spacer_widget, 3, 0, 1, 2) | ||||
|         self.change_wine_version_button = QPushButton("Управление Wine/Proton") | ||||
|         self.change_wine_version_button.setMinimumHeight(32) | ||||
|         self.change_wine_version_button.clicked.connect(self.open_wine_version_manager) | ||||
|         self.change_wine_version_button.setToolTip("Изменение версии Wine или Proton для выбранного префикса.") | ||||
|         management_layout.addWidget(self.change_wine_version_button, 3, 0, 1, 2) | ||||
|  | ||||
|         self.esync_button = QPushButton("ESync") | ||||
|         self.esync_button.setCheckable(True) | ||||
|         self.esync_button.setToolTip("Включить/выключить Eventfd-based synchronization.") | ||||
|         self.esync_button.clicked.connect(lambda: self.update_sync_option("WINEESYNC", self.esync_button.isChecked())) | ||||
|         management_layout.addWidget(self.esync_button, 4, 0) | ||||
|  | ||||
|         self.fsync_button = QPushButton("FSync") | ||||
|         self.fsync_button.setCheckable(True) | ||||
|         self.fsync_button.setToolTip("Включить/выключить Futex-based synchronization.") | ||||
|         self.fsync_button.clicked.connect(lambda: self.update_sync_option("WINEFSYNC", self.fsync_button.isChecked())) | ||||
|         management_layout.addWidget(self.fsync_button, 4, 1) | ||||
|  | ||||
|         self.dxvk_manage_button = QPushButton("Управление DXVK") | ||||
|         self.dxvk_manage_button.setMinimumHeight(32) | ||||
|         self.dxvk_manage_button.clicked.connect(lambda: self.open_component_version_manager('dxvk')) | ||||
|         self.dxvk_manage_button.setToolTip("Установка или удаление определенной версии DXVK в префиксе.") | ||||
|         management_layout.addWidget(self.dxvk_manage_button, 4, 0) | ||||
|         management_layout.addWidget(self.dxvk_manage_button, 5, 0) | ||||
|  | ||||
|         self.vkd3d_manage_button = QPushButton("Управление VKD3D") | ||||
|         self.vkd3d_manage_button.setMinimumHeight(32) | ||||
|         self.vkd3d_manage_button.clicked.connect(lambda: self.open_component_version_manager('vkd3d-proton')) | ||||
|         self.vkd3d_manage_button.setToolTip("Установка или удаление определенной версии vkd3d-proton в префиксе.") | ||||
|         management_layout.addWidget(self.vkd3d_manage_button, 4, 1) | ||||
|         management_layout.addWidget(self.vkd3d_manage_button, 5, 1) | ||||
|  | ||||
|         # --- Правая сторона: Информационный блок и кнопки установки --- | ||||
|         right_column_widget = QWidget() | ||||
|         right_column_layout = QVBoxLayout(right_column_widget) | ||||
|         right_column_layout.setContentsMargins(0, 0, 0, 0) | ||||
|         right_column_layout.setSpacing(10) | ||||
|  | ||||
|         # --- Правая сторона: Информационный блок --- | ||||
|         self.prefix_info_display = QTextBrowser() | ||||
|         self.prefix_info_display.setReadOnly(True) | ||||
|         self.prefix_info_display.setFrameStyle(QFrame.StyledPanel) | ||||
|         # Увеличиваем rowspan, чтобы учесть добавленный отступ | ||||
|         management_layout.addWidget(self.prefix_info_display, 0, 2, 5, 1) | ||||
|  | ||||
|         management_layout.setColumnStretch(0, 1) | ||||
|         management_layout.setColumnStretch(1, 1) | ||||
|         management_layout.setColumnStretch(2, 2) | ||||
|  | ||||
|         # --- Separator and Installer --- | ||||
|         separator = QFrame() | ||||
|         separator.setFrameShape(QFrame.HLine) | ||||
|         separator.setFrameShadow(QFrame.Sunken) | ||||
|         management_layout.addWidget(separator, 5, 0, 1, 3) | ||||
|         right_column_layout.addWidget(self.prefix_info_display) | ||||
|  | ||||
|         install_group = QWidget() | ||||
|         install_layout = QVBoxLayout(install_group) | ||||
|         install_layout.setContentsMargins(0, 5, 0, 0) | ||||
|         install_layout.setContentsMargins(0, 0, 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) | ||||
|  | ||||
|         # Layout для кнопок установки и создания ярлыка | ||||
|         action_buttons_layout = QHBoxLayout() | ||||
|  | ||||
|         self.prefix_install_button = QPushButton("Установить приложение в префикс") | ||||
|         self.prefix_install_button.setEnabled(False) | ||||
|         self.prefix_install_button.clicked.connect(self.run_prefix_installer) | ||||
|         action_buttons_layout.addWidget(self.prefix_install_button) | ||||
|         self.prefix_install_button.clicked.connect(self.browse_and_run_prefix_installer) | ||||
|         install_layout.addWidget(self.prefix_install_button) | ||||
|  | ||||
|         self.create_launcher_button = QPushButton("Создать ярлык для приложения в префиксе") | ||||
|         self.create_launcher_button.setToolTip( | ||||
|             "Создает ярлык в меню и на вкладке 'Установленные' для .exe файла внутри префикса.") | ||||
|         self.create_launcher_button.clicked.connect(self.create_launcher_for_prefix) | ||||
|         self.create_launcher_button.setEnabled(False)  # Изначально неактивна | ||||
|         action_buttons_layout.addWidget(self.create_launcher_button) | ||||
|         install_layout.addLayout(action_buttons_layout) | ||||
|         install_layout.addWidget(self.create_launcher_button) | ||||
|         right_column_layout.addWidget(install_group) | ||||
|  | ||||
|         management_layout.addWidget(install_group, 6, 0, 1, 3) | ||||
|         right_column_layout.setStretch(0, 1)  # Информационное окно растягивается | ||||
|         right_column_layout.setStretch(1, 0)  # Группа кнопок не растягивается | ||||
|  | ||||
|         management_layout.addWidget(right_column_widget, 0, 2, 6, 1) | ||||
|  | ||||
|         management_layout.setColumnStretch(0, 1) | ||||
|         management_layout.setColumnStretch(1, 1) | ||||
|         management_layout.setColumnStretch(2, 2) | ||||
|  | ||||
|         container_layout.addWidget(self.prefix_management_groupbox) | ||||
|         layout.addWidget(self.management_container_groupbox) | ||||
|         layout.addStretch() | ||||
|         self.add_tab(self.prefix_tab, "Менеджер префиксов") | ||||
|  | ||||
|         self.prefix_install_path_edit.textChanged.connect(self.update_prefix_install_button_state) | ||||
|  | ||||
|     def _get_current_prefixes(self): | ||||
|         """Возвращает множество имен существующих префиксов.""" | ||||
|         prefixes_root_path = os.path.join(Var.USER_WORK_PATH, "prefixes") | ||||
| @@ -2204,7 +2183,7 @@ class WineHelperGUI(QMainWindow): | ||||
|             self.created_prefix_selector.removeItem(index_to_remove) | ||||
|  | ||||
|     def _load_created_prefixes(self): | ||||
|         """Загружает список созданных префиксов, сканируя файловую систему, и восстанавливает последнее выбранное состояние.""" | ||||
|         """Загружает и обновляет список созданных префиксов в выпадающем списке.""" | ||||
|         prefixes_root_path = os.path.join(Var.USER_WORK_PATH, "prefixes") | ||||
|         if not os.path.isdir(prefixes_root_path): | ||||
|             self.management_container_groupbox.setVisible(False) | ||||
| @@ -2232,13 +2211,6 @@ class WineHelperGUI(QMainWindow): | ||||
|  | ||||
|         self.management_container_groupbox.setVisible(True) | ||||
|  | ||||
|         # По умолчанию выбираем первый элемент в списке, если он есть. | ||||
|         if self.created_prefix_selector.count() > 0: | ||||
|             self.created_prefix_selector.setCurrentIndex(0) | ||||
|         else: | ||||
|             # Если список пуст, убедимся, что панель управления сброшена. | ||||
|             self.on_created_prefix_selected(-1) | ||||
|  | ||||
|     def on_created_prefix_selected(self, index): | ||||
|         """Обрабатывает выбор префикса из выпадающего списка.""" | ||||
|         if index == -1: | ||||
| @@ -2315,7 +2287,6 @@ class WineHelperGUI(QMainWindow): | ||||
|             # Успешное удаление, обновляем GUI | ||||
|             self._remove_prefix_from_gui_state(prefix_name) | ||||
|             self.update_installed_apps() | ||||
|             QMessageBox.information(self, "Успех", f"Префикс '{prefix_name}' и все связанные с ним данные были успешно удалены.") | ||||
|         else: | ||||
|             QMessageBox.critical(self, "Ошибка удаления", f"Не удалось удалить префикс '{prefix_name}'.\nПодробности смотрите в логе.") | ||||
|  | ||||
| @@ -2324,25 +2295,30 @@ class WineHelperGUI(QMainWindow): | ||||
|         is_prefix_selected = bool(prefix_name) | ||||
|         self.prefix_management_groupbox.setEnabled(is_prefix_selected) | ||||
|         self.create_launcher_button.setEnabled(is_prefix_selected) | ||||
|         self.prefix_install_button.setEnabled(is_prefix_selected) | ||||
|  | ||||
|         if is_prefix_selected: | ||||
|             self.update_prefix_info_display(prefix_name) | ||||
|         else: | ||||
|             self.prefix_info_display.clear() | ||||
|             self.prefix_install_path_edit.clear() | ||||
|  | ||||
|         self.update_prefix_install_button_state() | ||||
|             # Сбрасываем состояние кнопок, когда префикс не выбран | ||||
|             self.esync_button.setChecked(False) | ||||
|             self.fsync_button.setChecked(False) | ||||
|  | ||||
|     def update_prefix_info_display(self, prefix_name): | ||||
|         """Обновляет информационный блок для созданного префикса, читая данные из last.conf.""" | ||||
|         if not prefix_name: | ||||
|             self.prefix_info_display.clear() | ||||
|             self.esync_button.setChecked(False) | ||||
|             self.fsync_button.setChecked(False) | ||||
|             return | ||||
|  | ||||
|         last_conf_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name, "last.conf") | ||||
|  | ||||
|         if not os.path.exists(last_conf_path): | ||||
|             self.prefix_info_display.setHtml(f"<p>Файл конфигурации last.conf не найден для префикса '{prefix_name}'.</p>") | ||||
|             self.esync_button.setChecked(False) | ||||
|             self.fsync_button.setChecked(False) | ||||
|             return | ||||
|  | ||||
|         # Словарь для хранения всех переменных из файла | ||||
| @@ -2361,6 +2337,17 @@ class WineHelperGUI(QMainWindow): | ||||
|             self.prefix_info_display.setHtml(f"<p>Ошибка чтения last.conf: {e}</p>") | ||||
|             return | ||||
|  | ||||
|         # --- Обновить кнопки ESync/FSync --- | ||||
|         # Блокировать сигналы, чтобы предотвратить запуск метода обновления, когда мы устанавливаем состояние | ||||
|         self.esync_button.blockSignals(True) | ||||
|         self.fsync_button.blockSignals(True) | ||||
|  | ||||
|         self.esync_button.setChecked(all_vars.get("WINEESYNC") == "1") | ||||
|         self.fsync_button.setChecked(all_vars.get("WINEFSYNC") == "1") | ||||
|  | ||||
|         self.esync_button.blockSignals(False) | ||||
|         self.fsync_button.blockSignals(False) | ||||
|  | ||||
|         # Карта для красивого отображения известных переменных | ||||
|         display_map = { | ||||
|             "WINEPREFIX": ("Путь", lambda v: v), | ||||
| @@ -2369,8 +2356,10 @@ class WineHelperGUI(QMainWindow): | ||||
|             "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 "Выключен"), | ||||
|         } | ||||
|         display_order = ["WINEPREFIX", "WINEARCH", "WH_WINE_USE", "BASE_PFX", "DXVK_VER", "VKD3D_VER"] | ||||
|         display_order = ["WINEPREFIX", "WINEARCH", "WH_WINE_USE", "BASE_PFX", "DXVK_VER", "VKD3D_VER", "WINEESYNC", "WINEFSYNC"] | ||||
|  | ||||
|         html_content = f'<p style="line-height: 1.3; font-size: 9pt;">' | ||||
|         html_content += f"<b>Имя:</b> {html.escape(prefix_name)}<br>" | ||||
| @@ -2395,8 +2384,13 @@ class WineHelperGUI(QMainWindow): | ||||
|         html_content += "</p>" | ||||
|         self.prefix_info_display.setHtml(html_content) | ||||
|  | ||||
|     def browse_for_prefix_installer(self): | ||||
|         """Открывает диалог выбора файла для установки в созданный префикс.""" | ||||
|     def browse_and_run_prefix_installer(self): | ||||
|         """Открывает диалог выбора файла и запускает установку в созданный префикс.""" | ||||
|         prefix_name = self.current_managed_prefix_name | ||||
|         if not prefix_name: | ||||
|             QMessageBox.warning(self, "Ошибка", "Сначала выберите префикс для установки.") | ||||
|             return | ||||
|  | ||||
|         file_path, _ = QFileDialog.getOpenFileName( | ||||
|             self, | ||||
|             "Выберите установочный файл", | ||||
| @@ -2404,18 +2398,11 @@ class WineHelperGUI(QMainWindow): | ||||
|             "Исполняемые файлы (*.exe *.msi);;Все файлы (*)" | ||||
|         ) | ||||
|         if file_path: | ||||
|             self.prefix_install_path_edit.setText(file_path) | ||||
|             self.run_prefix_installer(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): | ||||
|         """Запускает установку файла в выбранный префикс.""" | ||||
|     def run_prefix_installer(self, installer_path): | ||||
|         """Запускает установку файла в выбранный префикс через скрипт winehelper.""" | ||||
|         prefix_name = self.current_managed_prefix_name | ||||
|         installer_path = self.prefix_install_path_edit.text().strip() | ||||
|  | ||||
|         if not prefix_name: | ||||
|             QMessageBox.warning(self, "Ошибка", "Не выбран префикс для установки.") | ||||
| @@ -2424,9 +2411,6 @@ class WineHelperGUI(QMainWindow): | ||||
|             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) | ||||
| @@ -2450,13 +2434,12 @@ class WineHelperGUI(QMainWindow): | ||||
|         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) | ||||
|         # Окружение полностью настраивается скриптом winehelper | ||||
|         self.command_process.setProcessEnvironment(QProcessEnvironment.systemEnvironment()) | ||||
|  | ||||
|         args = [installer_path] | ||||
|         self.command_log_output.append(f"Запуск установки: {shlex.quote(wine_executable)} {shlex.quote(installer_path)}") | ||||
|         self.command_process.start(wine_executable, args) | ||||
|         args = ["install-to-prefix", prefix_name, installer_path] | ||||
|         self.command_log_output.append(f"Выполнение: {shlex.quote(self.winehelper_path)} {' '.join(shlex.quote(a) for a in args)}") | ||||
|         self.command_process.start(self.winehelper_path, args) | ||||
|         self.command_dialog.exec_() | ||||
|  | ||||
|     def _get_prefix_component_version(self, prefix_name, component_key): | ||||
| @@ -2532,6 +2515,81 @@ class WineHelperGUI(QMainWindow): | ||||
|                 # Если лицензия принята, запускаем установку. | ||||
|                 self.run_component_install_command(prefix_name, command, version) | ||||
|  | ||||
|     def open_wine_version_manager(self): | ||||
|         """Открывает диалог для смены версии Wine/Proton для префикса.""" | ||||
|         prefix_name = self.current_managed_prefix_name | ||||
|         if not prefix_name: | ||||
|             QMessageBox.warning(self, "Ошибка", "Сначала выберите префикс.") | ||||
|             return | ||||
|  | ||||
|         # Определяем архитектуру префикса | ||||
|         prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name) | ||||
|         last_conf_path = os.path.join(prefix_path, "last.conf") | ||||
|         architecture = "win64"  # По умолчанию | ||||
|         if os.path.exists(last_conf_path): | ||||
|             try: | ||||
|                 with open(last_conf_path, 'r', encoding='utf-8') as f: | ||||
|                     for line in f: | ||||
|                         if 'WINEARCH=' in line: | ||||
|                             arch_val = line.split('=', 1)[1].strip().strip('"\'') | ||||
|                             if arch_val: | ||||
|                                 architecture = arch_val | ||||
|                                 break | ||||
|             except Exception as e: | ||||
|                 print(f"Предупреждение: не удалось прочитать архитектуру из {last_conf_path}: {e}") | ||||
|  | ||||
|         dialog = WineVersionSelectionDialog(architecture, self) | ||||
|         if dialog.exec_() == QDialog.Accepted and dialog.selected_version: | ||||
|             new_version = dialog.selected_version | ||||
|             new_version_display = dialog.selected_display_text | ||||
|  | ||||
|             if not self._show_license_agreement_dialog(): | ||||
|                 return  # Пользователь отклонил лицензию | ||||
|  | ||||
|             self.run_change_wine_version_command(prefix_name, new_version, new_version_display) | ||||
|  | ||||
|     def run_change_wine_version_command(self, prefix_name, new_version, new_version_display): | ||||
|         """Выполняет команду смены версии Wine/Proton через winehelper.""" | ||||
|         self.command_dialog = QDialog(self) | ||||
|         self.command_dialog.setWindowTitle(f"Смена версии Wine на: {new_version_display}") | ||||
|         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_output_buffer = "" | ||||
|         self.command_last_line_was_progress = False | ||||
|  | ||||
|         self.command_process = QProcess(self.command_dialog) | ||||
|         self.command_process.setProcessChannelMode(QProcess.MergedChannels) | ||||
|         self.command_process.readyReadStandardOutput.connect(self._handle_prefix_creation_output) | ||||
|         self.command_process.finished.connect( | ||||
|             lambda exit_code, exit_status: self._handle_change_wine_version_finished( | ||||
|                 prefix_name, exit_code, exit_status | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|         env = QProcessEnvironment.systemEnvironment() | ||||
|         env.insert("WINEPREFIX", os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name)) | ||||
|         self.command_process.setProcessEnvironment(env) | ||||
|  | ||||
|         args = ["change-wine", new_version] | ||||
|         self.command_log_output.append(f"Выполнение: {shlex.quote(self.winehelper_path)} {' '.join(shlex.quote(a) for a in args)}") | ||||
|         self.command_process.start(self.winehelper_path, args) | ||||
|         self.command_dialog.exec_() | ||||
|  | ||||
|     def run_component_install_command(self, prefix_name, command, version): | ||||
|         """Выполняет команду установки компонента (DXVK/VKD3D) через winehelper.""" | ||||
|         prefix_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name) | ||||
| @@ -2572,11 +2630,31 @@ class WineHelperGUI(QMainWindow): | ||||
|         self.command_process.start(self.winehelper_path, args) | ||||
|         self.command_dialog.exec_() | ||||
|  | ||||
|     def _handle_change_wine_version_finished(self, prefix_name, exit_code, exit_status): | ||||
|         """Обрабатывает завершение смены версии Wine и обновляет информацию о префиксе.""" | ||||
|         # Обрабатываем остаток в буфере, если он есть | ||||
|         if self.command_output_buffer: | ||||
|             self._process_command_log_line(self.command_output_buffer) | ||||
|             self.command_output_buffer = "" | ||||
|  | ||||
|         # Если последней строкой был прогресс, "завершаем" его переносом строки. | ||||
|         if self.command_last_line_was_progress: | ||||
|             cursor = self.command_log_output.textCursor() | ||||
|             cursor.movePosition(QTextCursor.End) | ||||
|             cursor.insertText("\n") | ||||
|             self.command_last_line_was_progress = False | ||||
|  | ||||
|         # Вызываем общий обработчик для обновления лога и кнопки закрытия | ||||
|         self._handle_command_finished(exit_code, exit_status) | ||||
|  | ||||
|         # В случае успеха обновляем панель информации о префиксе | ||||
|         if exit_code == 0: | ||||
|             self.update_prefix_info_display(prefix_name) | ||||
|  | ||||
|     def _handle_component_install_finished(self, prefix_name, exit_code, exit_status): | ||||
|         """Обрабатывает завершение установки компонента и обновляет информацию о префиксе.""" | ||||
|         # Вызываем общий обработчик для обновления лога и кнопки закрытия | ||||
|         self._handle_command_finished(exit_code, exit_status) | ||||
|  | ||||
|         # В случае успеха обновляем панель информации о префиксе | ||||
|         if exit_code == 0: | ||||
|             self.update_prefix_info_display(prefix_name) | ||||
| @@ -2723,8 +2801,8 @@ class WineHelperGUI(QMainWindow): | ||||
|  | ||||
|             # Читаем и парсим файл THIRD-PARTY | ||||
|             third_party_html = "" | ||||
|             third_party_file_path = os.path.join(Var.DATA_PATH, "THIRD-PARTY") | ||||
|             if os.path.exists(third_party_file_path): | ||||
|             third_party_file_path = Var.THIRD_PARTY_FILE | ||||
|             if third_party_file_path and os.path.exists(third_party_file_path): | ||||
|                 with open(third_party_file_path, 'r', encoding='utf-8') as f_tp: | ||||
|                     third_party_content = f_tp.read() | ||||
|  | ||||
| @@ -2869,10 +2947,6 @@ class WineHelperGUI(QMainWindow): | ||||
|             if not self.management_container_groupbox.isVisible(): | ||||
|                 self.management_container_groupbox.setVisible(True) | ||||
|  | ||||
|             QMessageBox.information(self, "Успех", | ||||
|                                     f"Префикс '{prefix_name}' успешно создан.\n" | ||||
|                                     "Теперь вы можете управлять им, выбрав его из выпадающего списка.") | ||||
|  | ||||
|     def update_installed_apps(self): | ||||
|         """Обновляет список установленных приложений в виде кнопок""" | ||||
|         # Если активная кнопка находится в списке удаляемых, сбрасываем ее | ||||
| @@ -2941,7 +3015,6 @@ class WineHelperGUI(QMainWindow): | ||||
|             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): | ||||
| @@ -2962,11 +3035,13 @@ class WineHelperGUI(QMainWindow): | ||||
|     def show_installed_app_info(self, desktop_path, button_widget): | ||||
|         """Показывает информацию об установленном приложении в правой панели.""" | ||||
|         self._set_active_button(button_widget) | ||||
|         # Очищаем поле поиска и принудительно обновляем список, чтобы показать все приложения | ||||
|         self.installed_search_edit.blockSignals(True) | ||||
|         self.installed_search_edit.clear() | ||||
|         self.installed_search_edit.blockSignals(False) | ||||
|         self.filter_installed_buttons() | ||||
|         # Если в поиске был текст, очищаем его и перерисовываем список. | ||||
|         # Это предотвращает "прыжок", если список не был отфильтрован. | ||||
|         if self.installed_search_edit.text(): | ||||
|             self.installed_search_edit.blockSignals(True) | ||||
|             self.installed_search_edit.clear() | ||||
|             self.installed_search_edit.blockSignals(False) | ||||
|             self.filter_installed_buttons() | ||||
|  | ||||
|         # Прокручиваем к выбранному элементу | ||||
|         frame = button_widget.parent() | ||||
| @@ -3196,20 +3271,20 @@ class WineHelperGUI(QMainWindow): | ||||
|             QMessageBox.critical(self, "Ошибка", f"Каталог префикса не найден:\n{prefix_path}") | ||||
|             return | ||||
|  | ||||
|         winehelper_dir = os.path.dirname(self.winehelper_path) | ||||
|         winetricks_search_dir = Var.DATA_PATH | ||||
|         winetricks_path = None | ||||
|         try: | ||||
|             # Ищем файл, который начинается с 'winetricks_' | ||||
|             for filename in os.listdir(winehelper_dir): | ||||
|             for filename in os.listdir(winetricks_search_dir): | ||||
|                 if filename.startswith("winetricks_"): | ||||
|                     winetricks_path = os.path.join(winehelper_dir, filename) | ||||
|                     winetricks_path = os.path.join(winetricks_search_dir, filename) | ||||
|                     break  # Нашли, выходим из цикла | ||||
|         except OSError as e: | ||||
|             QMessageBox.critical(self, "Ошибка", f"Не удалось прочитать директорию {winehelper_dir}: {e}") | ||||
|             QMessageBox.critical(self, "Ошибка", f"Не удалось прочитать директорию {winetricks_search_dir}: {e}") | ||||
|             return | ||||
|  | ||||
|         if not winetricks_path: | ||||
|             QMessageBox.critical(self, "Ошибка", f"Скрипт winetricks не найден в директории:\n{winehelper_dir}") | ||||
|             QMessageBox.critical(self, "Ошибка", f"Скрипт winetricks не найден в директории:\n{winetricks_search_dir}") | ||||
|             return | ||||
|  | ||||
|         wine_executable = self._get_wine_executable_for_prefix(prefix_name) | ||||
| @@ -3243,6 +3318,43 @@ class WineHelperGUI(QMainWindow): | ||||
|                                 "Будет использована системная версия Wine.") | ||||
|         return 'wine'  # По умолчанию системный wine | ||||
|  | ||||
|     def update_sync_option(self, var_name, is_enabled): | ||||
|         """Обновляет значение WINEESYNC или WINEFSYNC в last.conf.""" | ||||
|         prefix_name = self.current_managed_prefix_name | ||||
|         if not prefix_name: | ||||
|             return | ||||
|  | ||||
|         last_conf_path = os.path.join(Var.USER_WORK_PATH, "prefixes", prefix_name, "last.conf") | ||||
|         if not os.path.exists(last_conf_path): | ||||
|             QMessageBox.warning(self, "Ошибка", f"Файл last.conf не найден для префикса '{prefix_name}'.") | ||||
|             return | ||||
|  | ||||
|         new_value = "1" if is_enabled else "0" | ||||
|         updated = False | ||||
|         lines = [] | ||||
|  | ||||
|         try: | ||||
|             with open(last_conf_path, 'r', encoding='utf-8') as f: | ||||
|                 lines = f.readlines() | ||||
|  | ||||
|             for i, line in enumerate(lines): | ||||
|                 if line.strip().startswith(f"export {var_name}="): | ||||
|                     lines[i] = f'export {var_name}="{new_value}"\n' | ||||
|                     updated = True | ||||
|                     break | ||||
|  | ||||
|             if not updated: | ||||
|                 lines.append(f'export {var_name}="{new_value}"\n') | ||||
|  | ||||
|             with open(last_conf_path, 'w', encoding='utf-8') as f: | ||||
|                 f.writelines(lines) | ||||
|  | ||||
|             # Обновляем информационную панель, чтобы отразить изменения | ||||
|             self.update_prefix_info_display(prefix_name) | ||||
|  | ||||
|         except IOError as e: | ||||
|             QMessageBox.critical(self, "Ошибка записи", f"Не удалось обновить файл last.conf:\n{e}") | ||||
|  | ||||
|     def _run_wine_util(self, util_name, prefix_name=None): | ||||
|         """Запускает стандартную утилиту Wine для выбранного префикса.""" | ||||
|         if not prefix_name: | ||||
| @@ -3599,11 +3711,14 @@ class WineHelperGUI(QMainWindow): | ||||
|         search_edit = tab_data['search_edit'] | ||||
|         scroll_area = tab_data['scroll_area'] | ||||
|  | ||||
|         # Общая логика: очищаем поиск, обновляем список и прокручиваем к элементу | ||||
|         search_edit.blockSignals(True) | ||||
|         search_edit.clear() | ||||
|         search_edit.blockSignals(False) | ||||
|         self.filter_buttons(tab_type) | ||||
|         # Если в поиске был текст, очищаем его и перерисовываем список. | ||||
|         # Это предотвращает "прыжок", если список не был отфильтрован. | ||||
|         if search_edit.text(): | ||||
|             search_edit.blockSignals(True) | ||||
|             search_edit.clear() | ||||
|             search_edit.blockSignals(False) | ||||
|             self.filter_buttons(tab_type) | ||||
|  | ||||
|         frame = button_widget.parent() | ||||
|         if isinstance(frame, QFrame): | ||||
|             QTimer.singleShot(0, lambda: scroll_area.ensureWidgetVisible(frame)) | ||||
| @@ -3951,26 +4066,19 @@ class WineHelperGUI(QMainWindow): | ||||
|             self._load_created_prefixes() | ||||
|  | ||||
|             new_prefix_name = None | ||||
|             selected_new = False | ||||
|             if new_prefixes: | ||||
|                 # Обычно создается один префикс, берем первый из найденных | ||||
|                 # Обычно создается один префикс, берем первый из найденных. | ||||
|                 new_prefix_name = new_prefixes.pop() | ||||
|                 # Находим и выбираем его в выпадающем списке | ||||
|                 # Находим и выбираем его в выпадающем списке. | ||||
|                 index = self.created_prefix_selector.findText(new_prefix_name) | ||||
|                 if index != -1: | ||||
|                     self.created_prefix_selector.setCurrentIndex(index) | ||||
|             # --- Конец обновления списка префиксов --- | ||||
|                     selected_new = True | ||||
|  | ||||
|             # Создаем кастомный диалог, чтобы кнопка была на русском | ||||
|             success_box = QMessageBox(self.install_dialog) | ||||
|             success_box.setWindowTitle("Успех") | ||||
|             title_name = self._get_current_app_title() | ||||
|             success_text = f"Программа «{title_name}» установлена успешно!" | ||||
|             if new_prefix_name: | ||||
|                 success_text += f"\n\nНовый префикс '{new_prefix_name}' был автоматически выбран в списке управления на вкладке 'Менеджер префиксов'." | ||||
|             success_box.setText(success_text) | ||||
|             success_box.setIcon(QMessageBox.Information) | ||||
|             success_box.addButton("Готово", QMessageBox.AcceptRole) | ||||
|             success_box.exec_() | ||||
|             if not selected_new and self.created_prefix_selector.count() > 0: | ||||
|                 self.created_prefix_selector.setCurrentIndex(0) | ||||
|             # --- Конец обновления списка префиксов --- | ||||
|  | ||||
|             self.update_installed_apps() | ||||
|  | ||||
| @@ -4071,7 +4179,6 @@ class WineHelperGUI(QMainWindow): | ||||
|         """Обрабатывает завершение создания ярлыка.""" | ||||
|         self._handle_command_finished(exit_code, exit_status) | ||||
|         if exit_code == 0: | ||||
|             QMessageBox.information(self, "Успех", "Ярлык успешно создан.") | ||||
|             self.update_installed_apps() | ||||
|             # Переключаемся на вкладку "Установленные" | ||||
|             for i in range(self.tab_bar.count()): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user