forked from CastroFidel/winehelper
		
	Compare commits
	
		
			32 Commits
		
	
	
		
			tflex18
			...
			dfc6c1c836
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | dfc6c1c836 | ||
|  | 04187e9463 | ||
|  | 5f915ab58d | ||
|  | 0e8ee7788a | ||
|  | 49c1ac6846 | ||
|  | 971bcd0f5a | ||
|  | 5b21015aee | ||
|  | 7dee08bcfb | ||
|  | 633deaf1c1 | ||
|  | 4df9508547 | ||
|  | 989f04cdd8 | ||
|  | 95b189f5a2 | ||
|  | 371553277a | ||
|  | dabf50103d | ||
|  | 590b37f1a3 | ||
|  | 1f9b4a9146 | ||
|  | 39f21373f1 | ||
|  | e984ffdb8c | ||
|  | 48834dc078 | ||
|  | b62d06ed71 | ||
|  | 9a1b78276e | ||
|  | f788307f05 | ||
|  | 14273f723b | ||
|  | a8e0fdce0a | ||
|  | da3d5cd7af | ||
|  | 3ee499c758 | ||
|  | 6286cccbab | ||
|  | e8d462b665 | ||
|  | a817d1a6f5 | ||
|  | e1fc25bb72 | ||
|  | 7c90da2088 | ||
|  | 108316148a | 
							
								
								
									
										11
									
								
								CHANGELOG
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								CHANGELOG
									
									
									
									
									
								
							| @@ -1,5 +1,16 @@ | ||||
| История изменений: | ||||
|  | ||||
| 0.7.0 | ||||
| * обновлен графический режим Qt5 | ||||
|     - добавлена кнопка открытия каталога с резервными копиями и логами | ||||
|     - добавлена кнопка открытия каталога с префиксом | ||||
|     - добавлена блокировка кнопок для установленного приложения, если оно уже запущено | ||||
|     - добавлено отображения процесса установки сторонних компонентов с помощью winetricks | ||||
|     - добавлена возможность отображения и установки тестовых скриптов (выключено по умолчанию) | ||||
| * добавлены скрипты установки для t-flex версии 18 | ||||
| * добавлен список тестовых скриптов установки ПО | ||||
| * добавлена возможность ассоциации файлов для передачи в приложения запускаемых в WineHelper | ||||
|  | ||||
| 0.6.0 | ||||
| * обновлен графический режим Qt5 | ||||
| * добавлен иконка в трее для графического режима Qt5 | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru:  Сервис обновления ПО | ||||
| # info_ru:  Сервис обновления ПО: "R-Атлас", "R-Инфо" и "R-Тариф". | ||||
| ######################################################################## | ||||
| export PROG_URL="https://daobit.ru" | ||||
| export WH_WINE_USE="wine_x_tkg_10-0_i586" # wine-9.0.9-alt1-i586" | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru: «Справки БК» — специальное программное обеспечение, предназначенное для заполнения справок о доходах, расходах, об имуществе и обязательствах имущественного характера. | ||||
| # info_ru: «Справки БК» (Windows версия 2.5.5) от 31.01.2024 — специальное программное обеспечение, предназначенное для заполнения справок о доходах, расходах, об имуществе и обязательствах имущественного характера. | ||||
| ######################################################################## | ||||
| export PROG_URL="https://spravki-bk.ru" | ||||
| export WH_WINE_USE="wine-9.0.14-alt1-i586-spravkibk" | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| #!/usr/bin/env bash | ||||
| # info_ru: Обучающие материалы, примеры, бесплатные библиотеки для T-FLEX CAD 18 (Учебное пособие 18, Стандартные элементы 18, Примеры 17) | ||||
| # info_ru: Обучающие материалы, примеры, бесплатные библиотеки для T-FLEX CAD 18 (Учебное пособие 18, Стандартные элементы 18, Примеры 18) | ||||
| ######################################################################## | ||||
| export PROG_URL="https://www.tflexcad.ru" | ||||
| export PROG_NAME="Ресурсы для T-FLEX CAD 18" | ||||
|   | ||||
| @@ -62,8 +62,8 @@ fi | ||||
| if try_download "https://scadhelp.ru/files/10/download" "${AUTOINSTALL_EXE}" ; then | ||||
|     create_new_dir "$DRIVE_C/SDATA" | ||||
|     create_new_dir "$DRIVE_C/SWORK" | ||||
|     export WINE_WIN_START="" | ||||
|     var_winedlloverride_update "hasplms.exe,hasplmv.exe=d" | ||||
|     # временно запрещаем запуск hasplms.exe, hasplmv.exe для успешного завершения установки | ||||
|     tmp_winedlloverride_update "hasplms.exe,hasplmv.exe=d" | ||||
|     wine_run_install "$AUTOINSTALL_EXE" | ||||
|     try_remove_file "$AUTOINSTALL_EXE" | ||||
| 
 | ||||
							
								
								
									
										201
									
								
								winehelper
									
									
									
									
									
								
							
							
						
						
									
										201
									
								
								winehelper
									
									
									
									
									
								
							| @@ -17,6 +17,7 @@ if [[ "$(realpath "$0")" == "/usr/bin/$SCRIPT_NAME" ]] ; then | ||||
|     RUN_SCRIPT="/usr/bin/$SCRIPT_NAME" | ||||
|     DATA_PATH="/usr/share/$SCRIPT_NAME" | ||||
|     WH_ICON_PATH="/usr/share/icons/hicolor/scalable/apps/winehelper.svg" | ||||
|     WH_ICON_TRAY=" /usr/share/icons/hicolor/symbolic/apps/winehelper-symbolic.svg" | ||||
|     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" | ||||
| @@ -28,9 +29,11 @@ else | ||||
|     DATA_PATH="$(dirname "$RUN_SCRIPT")" | ||||
|     CHANGELOG_FILE="$DATA_PATH/CHANGELOG" | ||||
|     WH_ICON_PATH="$DATA_PATH/image/gui/winehelper-devel.svg" | ||||
|     WH_ICON_TRAY="$DATA_PATH/image/gui/winehelper-symbolic.svg" | ||||
|     LICENSE_FILE="$DATA_PATH/LICENSE" | ||||
|     AGREEMENT="$DATA_PATH/LICENSE_AGREEMENT" | ||||
|     THIRD_PARTY_FILE="$DATA_PATH/THIRD-PARTY" | ||||
|     WH_DEVEL="1" | ||||
|  | ||||
|     # минимальная проверка синтаксиса скриптов | ||||
|     for self_check_script in "$RUN_SCRIPT" \ | ||||
| @@ -101,16 +104,6 @@ else | ||||
|     check_variables DXVK_NVAPI_LOG_LEVEL "none" | ||||
| fi | ||||
|  | ||||
| if [[ $WINEDEBUG != "-all" ]] ; then | ||||
|     log_dir="$HOME/winehelper_backup_log" | ||||
|     mkdir -p "$log_dir" | ||||
|     export LOG_FILE="$log_dir/winehelper.log" | ||||
|     date > "$LOG_FILE" | ||||
|     print_warning "Включен режим логирования работы WINE." | ||||
|     print_warning "Лог будет сохранен по пути: $LOG_FILE" | ||||
|     sleep 3 | ||||
| fi | ||||
|  | ||||
| ##### WINETRICKS VERSION ##### | ||||
| WINETRICKS_VERSION="20250102" | ||||
|  | ||||
| @@ -485,6 +478,10 @@ var_winedlloverride_update () { | ||||
|     fi | ||||
| } | ||||
|  | ||||
| tmp_winedlloverride_update () { | ||||
|     var_winedlloverride_update "$1" | ||||
| } | ||||
|  | ||||
| var_dxvk_config_update () { | ||||
|     if [[ -n "${DXVK_CONFIG}" ]] | ||||
|     then export DXVK_CONFIG="${1};${DXVK_CONFIG}" | ||||
| @@ -1287,7 +1284,8 @@ init_wineprefix () { | ||||
|     echo "# переменные последнего использования префикса:" > "$WINEPREFIX/last.conf" | ||||
|     for var in WH_WINE_USE BASE_PFX WINEARCH WH_WINDOWS_VER WINEESYNC WINEFSYNC \ | ||||
|     STAGING_SHARED_MEMORY WINE_LARGE_ADDRESS_AWARE WH_USE_SHADER_CACHE WH_USE_WINE_DXGI \ | ||||
|     WINE_CPU_TOPOLOGY DXVK_VER VKD3D_VER WH_XDG_OPEN WH_USE_MESA_GL_OVERRIDE | ||||
|     WINE_CPU_TOPOLOGY DXVK_VER VKD3D_VER WH_XDG_OPEN WH_USE_MESA_GL_OVERRIDE \ | ||||
|     WH_USE_CPCSP_PROXY | ||||
|     do | ||||
|         echo "export $var=\"${!var}\"" >> "$WINEPREFIX/last.conf" | ||||
|     done | ||||
| @@ -1348,23 +1346,25 @@ kill_wine () { | ||||
| } | ||||
|  | ||||
| init_database () { | ||||
|     WHDB_FILE="0" | ||||
|     if [[ -f "$WIN_FILE_EXEC" ]] ; then | ||||
|     local whdb_file="0" | ||||
|     if [[ -n "$WIN_FILE_EXEC" ]] \ | ||||
|     && [[ -f "$WIN_FILE_EXEC" ]] | ||||
|     then | ||||
|         WHDB="$(basename "$WIN_FILE_EXEC" .exe)" | ||||
|         if [[ -f "$WIN_FILE_EXEC".whdb ]] ; then | ||||
|             WHDB_FILE="$WIN_FILE_EXEC".whdb | ||||
|             whdb_file="$WIN_FILE_EXEC".whdb | ||||
|         else | ||||
|             orig_IFS="$IFS" && IFS=$'\n' | ||||
|             if WH_FIND_DB_FILE="$(grep -ilw "#$WHDB.exe" "$WH_DB_DIR"/* )" ; then | ||||
|                 WHDB_FILE="$WH_FIND_DB_FILE" | ||||
|                 whdb_file="$WH_FIND_DB_FILE" | ||||
|             fi | ||||
|             IFS="$orig_IFS" | ||||
|         fi | ||||
|     fi | ||||
|  | ||||
|     if [[ "$WHDB_FILE" != "0" ]] ; then | ||||
|         print_info "Используется файл настроек: $WHDB_FILE" | ||||
|         . "$WHDB_FILE" | ||||
|     if [[ "$whdb_file" != "0" ]] ; then | ||||
|         print_info "Используется файл настроек: $whdb_file" | ||||
|         . "$whdb_file" | ||||
|     fi | ||||
|  | ||||
|     if check_prefix_var && [[ -f "$WINEPREFIX/last.conf" ]] ; then | ||||
| @@ -1389,40 +1389,89 @@ prepair_wine () { | ||||
|     [[ "$MANGOHUD" == 1 ]] && MANGOHUD_RUN="mangohud" | ||||
| } | ||||
|  | ||||
| wine_regfile () { | ||||
|     print_info "Запускаем команду: $WINELOADER $@" | ||||
|     "$WINELOADER" "$@" && print_ok "Выполнено." || fatal "Не выполнено: $WINELOADER $@" | ||||
|     wait_wineserver | ||||
|  | ||||
|     if [[ "$WINEARCH" == "win64" ]] \ | ||||
|     && [[ -f "${WINELOADER}64" ]] | ||||
|     then | ||||
|         print_info "Запускаем команду: ${WINELOADER}64 $@" | ||||
|         "${WINELOADER}64" "$@" && print_ok "Выполнено." || fatal "Не выполнено: ${WINELOADER}64 $@" | ||||
|         wait_wineserver | ||||
|     fi | ||||
| } | ||||
|  | ||||
| wine_run () { | ||||
|     local wh_add_args win_file_exec win_file_path win_file_name | ||||
|  | ||||
|     if [[ $1 =~ (winecfg|regedit|winefile|wineconsole) ]] ; then | ||||
|         win_file_exec="$1" | ||||
|         win_file_name="$win_file_exec" | ||||
|         win_file_path="$DRIVE_C" | ||||
|         wh_add_args="" | ||||
|     elif [[ $1 =~ \.dll$ ]] ; then | ||||
|         wine_regfile regsvr32 /s "$@" | ||||
|         return 0 | ||||
|     elif [[ -f "$1" ]] ; then | ||||
|         win_file_exec="$(readlink -f "$1")" | ||||
|         win_file_path="$(dirname "$win_file_exec")" | ||||
|         win_file_name="$(basename "$win_file_exec")" | ||||
|  | ||||
|         case "${win_file_name,,}" in | ||||
|             *.exe) wh_add_args="$WINE_WIN_START" ;; | ||||
|             *.msi) wh_add_args="msiexec /i" ;; | ||||
|             *.bat|*.cmd) wh_add_args="" ;; | ||||
|             *.reg) wine_regfile regedit "$@" ; return 0 ;; | ||||
|             *) fatal "Не удалось запустить файл $1. Проверьте расширение файла." ;; | ||||
|         esac | ||||
|  | ||||
|         if [[ $WINEARCH == "win32" ]] \ | ||||
|     && file "$WIN_FILE_EXEC" | grep -q "x86-64" | ||||
|         && file "$win_file_exec" | grep -q "x86-64" | ||||
|         then fatal "Нельзя запустить 64-битное приложение в 32-битном префиксе!" | ||||
|         fi | ||||
|  | ||||
|     WIN_FILE_PATH="$(dirname "$WIN_FILE_EXEC")" | ||||
|     [[ -d "$WIN_FILE_PATH" ]] && cd "$WIN_FILE_PATH" | ||||
|  | ||||
|     if [[ -n $LOG_FILE ]] && [[ -f "$LOG_FILE" ]] ; then | ||||
|         echo "##### Основные переменные #####" | tee -a "$LOG_FILE" | ||||
|         env | grep -e "WH_" -e "WINE" -e "DXVK" -e "VKD3D" | tee -a "$LOG_FILE" | ||||
|  | ||||
|         echo "##### Лог WINE #####" | tee -a "$LOG_FILE" | ||||
|         $MANGOHUD_RUN "$WINELOADER" "$@" $LAUNCH_PARAMETERS 2>&1 | tee -a "$LOG_FILE" | ||||
|     else | ||||
|         $MANGOHUD_RUN "$WINELOADER" "$@" $LAUNCH_PARAMETERS | ||||
|         fatal "Команда введена не правильно или не найден исполняемый файл $1" | ||||
|     fi | ||||
|  | ||||
|     shift | ||||
|     cd "$win_file_path" | ||||
|  | ||||
|     if [[ $WINEDEBUG != "-all" ]] ; then | ||||
|         local log_dir log_file | ||||
|         log_dir="$HOME/winehelper_backup_log" | ||||
|         log_file="$log_dir/${PREFIX_NAME}_${win_file_name%.*}.log" | ||||
|         create_new_dir "$log_dir" | ||||
|         date > "$log_file" | ||||
|  | ||||
|         print_warning "Включен режим логирования работы WINE." | ||||
|         print_warning "Лог будет сохранен по пути: $log_file" | ||||
|  | ||||
|         echo "##### Основные переменные #####" | tee -a "$log_file" | ||||
|         env | grep -e "WH_" -e "WINE" -e "DXVK" -e "VKD3D" | tee -a "$log_file" | ||||
|         echo "##### Лог WINE #####" | tee -a "$log_file" | ||||
|  | ||||
|         $MANGOHUD_RUN "$WINELOADER" $wh_add_args "$win_file_exec" "$@" $LAUNCH_PARAMETERS 2>&1 | tee -a "$log_file" | ||||
|     else | ||||
|         $MANGOHUD_RUN "$WINELOADER" $wh_add_args "$win_file_exec" "$@" $LAUNCH_PARAMETERS | ||||
|     fi | ||||
|  | ||||
|     wait_wineserver | ||||
|     cd "$DRIVE_C" | ||||
| } | ||||
|  | ||||
| wine_run_install () { | ||||
|     print_info "Запускаем установку: $1." | ||||
|     if [[ "$INSTALL_MODE" == "manual" ]] | ||||
|     then print_warning "Рекомендуется не менять пути для установки приложения!" | ||||
|     fi | ||||
|     [[ ! -f "$1" ]] && fatal "Нет файла для установки: $1" | ||||
|     case "${1,,}" in | ||||
|         *.exe) wine_run $WINE_WIN_START "$@" ;; | ||||
|         *.msi) wine_run msiexec /i "$@" ;; | ||||
|         *.bat|*.cmd) wine_run "$@" ;; | ||||
|         *) fatal "Не удалось запустить файл $1. Проверьте расширение файла." ;; | ||||
|     case "$WH_INSTALL_MODE" in | ||||
|         "manual") print_warning "Рекомендуется не менять пути для установки приложения!" ;; | ||||
|           "test") print_warning "Установка приложения из списка экспериментальных скриптов." ;; | ||||
|     esac | ||||
|     wait_wineserver | ||||
|  | ||||
|     if [[ ! -f "$1" ]] | ||||
|     then fatal "Нет файла для установки: $1" | ||||
|     else wine_run "$@" | ||||
|     fi | ||||
| } | ||||
|  | ||||
| run_autoinstall () { | ||||
| @@ -1440,24 +1489,20 @@ run_autoinstall () { | ||||
|     elif [[ -f "$WH_MANUALINSTALL_DIR/$INSTALL_SCRIPT_NAME" ]] ; then | ||||
|         INSTALL_SCRIPT="$WH_MANUALINSTALL_DIR/$INSTALL_SCRIPT_NAME" | ||||
|         WH_INSTALL_MODE="manual" | ||||
|     elif [[ -d "$WH_TESTINSTALL_DIR" ]] \ | ||||
|     && [[ -f "$WH_TESTINSTALL_DIR/$INSTALL_SCRIPT_NAME" ]] | ||||
|     then | ||||
|     elif [[ -f "$WH_TESTINSTALL_DIR/$INSTALL_SCRIPT_NAME" ]] ; then | ||||
|         INSTALL_SCRIPT="$WH_TESTINSTALL_DIR/$INSTALL_SCRIPT_NAME" | ||||
|         WH_INSTALL_MODE="test" | ||||
|     else | ||||
|         INSTALL_SCRIPT="0" | ||||
|     fi | ||||
|     export INSTALL_SCRIPT INSTALL_MODE | ||||
|     export INSTALL_SCRIPT WH_INSTALL_MODE | ||||
|  | ||||
|     if [[ $INSTALL_SCRIPT_NAME == "list" ]] || [[ -z "$INSTALL_SCRIPT_NAME" ]] ; then | ||||
|  | ||||
|         list_install_scripts() { | ||||
|             local dir="$1" | ||||
|             local title="$2" | ||||
|             [[ ! -d "$dir" ]] || [[ -z "$(ls -A "$dir" 2>/dev/null)" ]] && return | ||||
|  | ||||
|             print_info "$title" | ||||
|         print_install_list () { | ||||
|             parse_install_scripts() { | ||||
|                 local parse_dir="$1" | ||||
|                 [[ ! -d "$parse_dir" ]] || [[ -z "$(ls -A "$parse_dir" 2>/dev/null)" ]] && return | ||||
|  | ||||
|                 awk ' | ||||
|                     FNR==1 { | ||||
| @@ -1474,12 +1519,19 @@ run_autoinstall () { | ||||
|                             printf "\n%s - %s\n%s\n", filename, progname, info | ||||
|                         } | ||||
|                     } | ||||
|             ' "$dir"/* | ||||
|                 ' "$parse_dir"/* | ||||
|                 echo | ||||
|             } | ||||
|             print_info "Список программ с возможностью автоматической установки:" | ||||
|             parse_install_scripts "$WH_AUTOINSTALL_DIR" | ||||
|             print_info "Список программ с возможностью установки из существующего дистрибутива:" | ||||
|             parse_install_scripts "$WH_MANUALINSTALL_DIR" | ||||
|             print_warning "Программы из списка экспериментальных скриптов:" | ||||
|             parse_install_scripts "$WH_TESTINSTALL_DIR" | ||||
|         } | ||||
|  | ||||
|         list_install_scripts "$WH_AUTOINSTALL_DIR" "Список программ с возможностью автоматической установки:" | ||||
|         echo | ||||
|         list_install_scripts "$WH_MANUALINSTALL_DIR" "Список программ с возможностью установки из существующего дистрибутива:" | ||||
|         print_install_list | less -R --use-color | ||||
|  | ||||
|     elif [[ "$INSTALL_SCRIPT" != "0" ]] ; then | ||||
|         if [[ $WH_USE_GUI == "1" ]] \ | ||||
|         && [[ $(ps -o command= -p "$PPID" | awk '{print $2}') =~ "$DATA_PATH/winehelper_gui.py" ]] | ||||
| @@ -2151,20 +2203,21 @@ select_component_version() { | ||||
| } | ||||
|  | ||||
| run_install_to_prefix() { | ||||
|     export WINEPREFIX="$1" | ||||
|     local WIN_FILE_EXEC="$2" | ||||
|  | ||||
|     if [[ -z "$WINEPREFIX" ]] || [[ -z "$WIN_FILE_EXEC" ]]; then | ||||
|     if [[ -z "$1" ]] || [[ -z "$2" ]] || [[ ! -f "$2" ]] ; then | ||||
|         fatal "Использование: $SCRIPT_NAME install-to-prefix <имя_префикса> <путь_к_установщику>" | ||||
|     fi | ||||
|  | ||||
|     export WINEPREFIX="$1" | ||||
|     shift | ||||
|  | ||||
|     check_prefix_var | ||||
|     prepair_wine | ||||
|     wine_run_install "$WIN_FILE_EXEC" | ||||
|     wine_run "$@" | ||||
| } | ||||
|  | ||||
| run_install_dxvk() { | ||||
|     local version="$1" | ||||
|  | ||||
|     if [[ -z "$version" ]] ; then | ||||
|         version=$(select_component_version "DXVK") | ||||
|         [[ $? -ne 0 ]] && print_info "Установка DXVK отменена." && return | ||||
| @@ -2172,21 +2225,27 @@ run_install_dxvk() { | ||||
|         list_component_versions "DXVK" | ||||
|         return | ||||
|     fi | ||||
|  | ||||
|     check_prefix_var | ||||
|     init_database | ||||
|  | ||||
|     export DXVK_VER="$version" | ||||
|  | ||||
|     init_wine_ver | ||||
|     init_wineprefix | ||||
|  | ||||
|     if [[ "$DXVK_VER" == "none" ]] | ||||
|     then print_info "Удаление DXVK..." | ||||
|     else print_info "Установка DXVK: $DXVK_VER" | ||||
|     fi | ||||
|  | ||||
|     init_dxvk "$DXVK_VER" | ||||
|     wait_wineserver | ||||
| } | ||||
|  | ||||
| run_install_vkd3d() { | ||||
|     local version="$1" | ||||
|  | ||||
|     if [[ -z "$version" ]] ; then | ||||
|         version=$(select_component_version "VKD3D") | ||||
|         [[ $? -ne 0 ]] && print_info "Установка VKD3D отменена." && return | ||||
| @@ -2194,15 +2253,20 @@ run_install_vkd3d() { | ||||
|         list_component_versions "VKD3D" | ||||
|         return | ||||
|     fi | ||||
|  | ||||
|     check_prefix_var | ||||
|     init_database | ||||
|  | ||||
|     export VKD3D_VER="$version" | ||||
|  | ||||
|     init_wine_ver | ||||
|     init_wineprefix | ||||
|  | ||||
|     if [[ "$VKD3D_VER" == "none" ]] | ||||
|     then print_info "Удаление VKD3D..." | ||||
|     else print_info "Установка VKD3D: $VKD3D_VER" | ||||
|     fi | ||||
|  | ||||
|     init_vkd3d "$VKD3D_VER" | ||||
|     wait_wineserver | ||||
| } | ||||
| @@ -2221,9 +2285,7 @@ run_change_wine_version() { | ||||
|     fi | ||||
|  | ||||
|     init_wine_ver | ||||
|  | ||||
|     init_wineprefix | ||||
|  | ||||
|     wait_wineserver | ||||
|     print_ok "Версия Wine для префикса $PREFIX_NAME успешно изменена на $WH_WINE_USE." | ||||
| } | ||||
| @@ -2263,7 +2325,8 @@ create_new_dir "$WH_DIST_DIR" | ||||
| create_new_dir "$WH_PREFIXES_DIR" | ||||
| create_new_dir "$WH_VULKAN_LIBDIR" | ||||
|  | ||||
| if [[ -d "$HOME/.local/share/$SCRIPT_NAME" ]] \ | ||||
| if [[ $WH_DEVEL != "1" ]] \ | ||||
| && [[ -d "$HOME/.local/share/$SCRIPT_NAME" ]] \ | ||||
| && [[ ! -L "$HOME/.winehelper" ]] | ||||
| then try_force_link_dir "$HOME/.local/share/$SCRIPT_NAME" "$HOME/.winehelper" | ||||
| fi | ||||
| @@ -2309,12 +2372,14 @@ case "$arg1" in | ||||
|             WIN_FILE_EXEC="$(readlink -f "$arg1")" | ||||
|             WIN_FILE_NAME="$(basename "$WIN_FILE_EXEC")" | ||||
|             find_prefix "$WIN_FILE_EXEC" | ||||
|             case "${WIN_FILE_NAME,,}" in | ||||
|                 *.exe) prepair_wine ; wine_run $WINE_WIN_START "$WIN_FILE_EXEC" "$@" ;; | ||||
|                 *.msi) prepair_wine ; wine_run msiexec /i "$WIN_FILE_EXEC" "$@" ;; | ||||
|                 *.bat|*.cmd) prepair_wine ; wine_run start "$WIN_FILE_EXEC" "$@" ;; | ||||
|                 *) fatal "Тип файла не поддерживается." ;; | ||||
|             esac | ||||
|             prepair_wine | ||||
|  | ||||
|             if [[ -n "$1" ]] && [[ -f "$1" ]] ; then | ||||
|                 WIN_OPEN_FILE="$("$WINELOADER" winepath -w "$1")" | ||||
|                 shift | ||||
|             fi | ||||
|  | ||||
|             wine_run "$WIN_FILE_EXEC" "$@" "$WIN_OPEN_FILE" | ||||
|         else | ||||
|             print_error "Команды $arg1 не существует." | ||||
|             wh_info | ||||
|   | ||||
| @@ -14,7 +14,7 @@ from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QH | ||||
|                              QTextEdit, QFileDialog, QMessageBox, QLineEdit, QCheckBox, QStackedWidget, QScrollArea, QFormLayout, QGroupBox, QRadioButton, QComboBox, | ||||
|                              QListWidget, QListWidgetItem, QGridLayout, QFrame, QDialog, QTextBrowser, QInputDialog, QDialogButtonBox, QSystemTrayIcon, QMenu) | ||||
| from PyQt5.QtCore import Qt, QProcess, QSize, QTimer, QProcessEnvironment, QPropertyAnimation, QEasingCurve, pyqtSignal | ||||
| from PyQt5.QtGui import QIcon, QFont, QTextCursor, QPixmap, QPainter, QCursor | ||||
| from PyQt5.QtGui import QIcon, QFont, QTextCursor, QPixmap, QPainter, QCursor, QTextCharFormat | ||||
| from PyQt5.QtNetwork import QLocalServer, QLocalSocket | ||||
|  | ||||
|  | ||||
| @@ -870,6 +870,9 @@ class WinetricksManagerDialog(QDialog): | ||||
|                                    "Подробности смотрите в логе.", | ||||
|                                    QMessageBox.Warning, | ||||
|                                    {"buttons": {"OK": QMessageBox.AcceptRole}}) | ||||
|             # Сбрасываем формат символов к значению по умолчанию. | ||||
|             # Это гарантирует, что следующий вызов append() не унаследует красный цвет. | ||||
|             self.log_output.setCurrentCharFormat(QTextCharFormat()) | ||||
|             self.apply_button.setEnabled(True) | ||||
|             self.close_button.setEnabled(True) | ||||
|             return | ||||
| @@ -1622,10 +1625,34 @@ class WineHelperGUI(QMainWindow): | ||||
|             "padding-left: 10px;", "padding-left: 15px;" | ||||
|         ) | ||||
|  | ||||
|         # Стиль для кнопок тестовых программ | ||||
|         self.TEST_BUTTON_LIST_STYLE = """ | ||||
|             QPushButton { | ||||
|                 background-color: #ffdc64; /* Более темный желтый фон */ | ||||
|                 color: black; /* Черный цвет текста для контраста */ | ||||
|                 text-align: left; | ||||
|                 padding-left: 10px; | ||||
|                 padding-right: 10px; | ||||
|                 height: 42px; min-height: 42px; max-height: 42px; | ||||
|             } | ||||
|             QPushButton::icon { padding-left: 10px; } | ||||
|         """ | ||||
|  | ||||
|         # Стили для оберток кнопок (для рамки выделения) | ||||
|         self.FRAME_STYLE_DEFAULT = "QFrame { border: 2px solid transparent; border-radius: 8px; padding: 0px; }" | ||||
|         self.FRAME_STYLE_SELECTED = "QFrame { border: 2px solid #0078d7; border-radius: 8px; padding: 0px; }" | ||||
|  | ||||
|         # Стили для кнопок Запустить/Остановить | ||||
|         self.RUN_BUTTON_STYLE = """ | ||||
|             QPushButton { | ||||
|                 background-color: #4CAF50; color: white; | ||||
|                 font-weight: bold; | ||||
|             } | ||||
|         """ | ||||
|         self.STOP_BUTTON_STYLE = """ | ||||
|             QPushButton { background-color: #d32f2f; color: white; font-weight: bold; } | ||||
|         """ | ||||
|  | ||||
|         # Основные переменные | ||||
|         self.winehelper_path = Var.RUN_SCRIPT | ||||
|         self.process = None | ||||
| @@ -1764,8 +1791,11 @@ class WineHelperGUI(QMainWindow): | ||||
|         if tab_name == "Автоматическая установка": | ||||
|             title = "Автоматическая установка" | ||||
|             html_content = ("<h3>Автоматическая установка</h3>" | ||||
|                             "<p>Скрипты из этого списка скачают, установят и настроят приложение за вас.</p>" | ||||
|                             "<p>Просто выберите программу и нажмите «Установить».</p>") | ||||
|                             "<p>Скрипты из этого списка скачают, установят и настроят приложение за вас. Просто выберите программу и нажмите «Установить».</p>" | ||||
|                             "<p>Для доступа к экспериментальным скриптам установки отметьте опцию <b>«Показать тестовые версии»</b> внизу списка.</p>" | ||||
|                             "<br><h3>Совместимость с дистрибутивами Альт</h3>" | ||||
|                             "<p>С полным списком совместимого ПО и сертификатами (не только для WineHelper) можно ознакомиться по следующим ссылкам:<br>" | ||||
|                             "<a href='https://www.basealt.ru/fileadmin/user_upload/compatibility/P10-view2.html'>Для 10 платформы</a> | <a href='https://www.basealt.ru/fileadmin/user_upload/compatibility/P11-view2.html'>Для 11 платформы</a></p>") | ||||
|             show_global = False | ||||
|         elif tab_name == "Ручная установка": | ||||
|             title = "Ручная установка" | ||||
| @@ -1889,6 +1919,7 @@ class WineHelperGUI(QMainWindow): | ||||
|         # --- Верхний ряд кнопок --- | ||||
|         top_buttons_layout = QHBoxLayout() | ||||
|         self.run_button = QPushButton("Запустить") | ||||
|         self.run_button.setStyleSheet(self.RUN_BUTTON_STYLE) | ||||
|         self.run_button.clicked.connect(self.toggle_run_stop_app) | ||||
|         top_buttons_layout.addWidget(self.run_button) | ||||
|         installed_action_layout.addLayout(top_buttons_layout) | ||||
| @@ -2052,14 +2083,14 @@ class WineHelperGUI(QMainWindow): | ||||
|  | ||||
|         return btn | ||||
|  | ||||
|     def _populate_install_grid(self, grid_layout, scripts_list, script_folder, button_list): | ||||
|     def _populate_install_grid(self, grid_layout, scripts_list, script_folder, button_list, start_index=None): | ||||
|         """ | ||||
|         Заполняет QGridLayout кнопками установщиков. | ||||
|         Кнопки создаются только для скриптов, в которых найдена переменная PROG_NAME. | ||||
|  | ||||
|         :param grid_layout: QGridLayout для заполнения. | ||||
|         :param scripts_list: Список имен скриптов. | ||||
|         :param script_folder: Имя папки со скриптами ('autoinstall' или 'manualinstall'). | ||||
|         :param script_folder: Имя папки со скриптами ('autoinstall', 'manualinstall' или 'testinstall'). | ||||
|         :param button_list: Список для хранения созданных кнопок. | ||||
|         """ | ||||
|         button_index = 0 | ||||
| @@ -2073,7 +2104,13 @@ class WineHelperGUI(QMainWindow): | ||||
|  | ||||
|             icon_names = ScriptParser.extract_icons_from_script(script_path) | ||||
|             icon_paths = [os.path.join(Var.DATA_PATH, "image", f"{name}.png") for name in icon_names] | ||||
|             btn = self._create_app_button(prog_name, icon_paths, self.BUTTON_LIST_STYLE) | ||||
|  | ||||
|             # Выбираем стиль в зависимости от папки | ||||
|             if script_folder == 'testinstall': | ||||
|                 style_sheet = self.TEST_BUTTON_LIST_STYLE | ||||
|             else: | ||||
|                 style_sheet = self.BUTTON_LIST_STYLE | ||||
|             btn = self._create_app_button(prog_name, icon_paths, style_sheet) | ||||
|  | ||||
|             # Обертка для рамки выделения | ||||
|             frame = QFrame() | ||||
| @@ -2083,12 +2120,12 @@ class WineHelperGUI(QMainWindow): | ||||
|             layout.addWidget(btn) | ||||
|  | ||||
|             btn.clicked.connect(lambda _, s=script, b=btn: self.show_script_info(s, b)) | ||||
|             row, column = divmod(button_index, 2) | ||||
|             row, column = divmod(len(button_list), 2) | ||||
|             grid_layout.addWidget(frame, row, column) | ||||
|             button_list.append(btn) | ||||
|             button_index += 1 | ||||
|  | ||||
|     def _create_searchable_grid_tab(self, placeholder_text, filter_slot): | ||||
|     def _create_searchable_grid_tab(self, placeholder_text, filter_slot, add_stretch=True): | ||||
|         """ | ||||
|         Создает стандартную вкладку с полем поиска и сеточным макетом с прокруткой. | ||||
|         Возвращает кортеж (главный виджет вкладки, сеточный макет, поле поиска, область прокрутки). | ||||
| @@ -2122,11 +2159,12 @@ class WineHelperGUI(QMainWindow): | ||||
|         grid_layout.setColumnStretch(1, 1) | ||||
|  | ||||
|         v_scroll_layout.addLayout(grid_layout) | ||||
|         if add_stretch: | ||||
|             v_scroll_layout.addStretch(1) | ||||
|  | ||||
|         return tab_widget, grid_layout, search_edit, scroll_area | ||||
|  | ||||
|     def _create_and_populate_install_tab(self, tab_title, script_folder, search_placeholder, filter_slot): | ||||
|     def _create_and_populate_install_tab(self, tab_title, script_folders, search_placeholder, filter_slot): | ||||
|         """ | ||||
|         Создает и заполняет вкладку для установки (автоматической или ручной). | ||||
|         Возвращает кортеж со скриптами, кнопками и виджетами. | ||||
| @@ -2136,16 +2174,17 @@ class WineHelperGUI(QMainWindow): | ||||
|         ) | ||||
|  | ||||
|         scripts = [] | ||||
|         script_path = os.path.join(Var.DATA_PATH, script_folder) | ||||
|         buttons_list = [] | ||||
|         for folder in script_folders: | ||||
|             script_path = os.path.join(Var.DATA_PATH, folder) | ||||
|             if os.path.isdir(script_path): | ||||
|                 try: | ||||
|                 scripts = sorted(os.listdir(script_path)) | ||||
|                     folder_scripts = sorted(os.listdir(script_path)) | ||||
|                     scripts.extend(folder_scripts) | ||||
|                     self._populate_install_grid(grid_layout, folder_scripts, folder, buttons_list) | ||||
|                 except OSError as e: | ||||
|                     print(f"Не удалось прочитать директорию {script_path}: {e}") | ||||
|  | ||||
|         buttons_list = [] | ||||
|         self._populate_install_grid(grid_layout, scripts, script_folder, buttons_list) | ||||
|  | ||||
|         self.add_tab(tab_widget, tab_title) | ||||
|  | ||||
|         return scripts, buttons_list, grid_layout, search_edit, scroll_area | ||||
| @@ -2156,30 +2195,89 @@ class WineHelperGUI(QMainWindow): | ||||
|             scripts, buttons, layout, | ||||
|             search_edit, scroll_area | ||||
|         ) = self._create_and_populate_install_tab( | ||||
|             "Автоматическая установка", "autoinstall", "Поиск скрипта автоматической установки...", partial(self.filter_buttons, 'auto') | ||||
|             "Автоматическая установка", ["autoinstall"], "Поиск скрипта автоматической установки...", partial(self.filter_buttons, 'auto') | ||||
|         ) | ||||
|         self.autoinstall_scripts = scripts | ||||
|         self.install_tabs_data['auto'] = { | ||||
|             'buttons': buttons, 'layout': layout, 'search_edit': search_edit, 'scroll_area': scroll_area | ||||
|         } | ||||
|  | ||||
|         # Добавляем чекбокс для тестовых версий | ||||
|         test_checkbox = QCheckBox("Показать тестовые версии") | ||||
|         test_checkbox.setToolTip("Показать/скрыть экспериментальные скрипты установки") | ||||
|  | ||||
|         # Находим layout вкладки, чтобы добавить чекбокс | ||||
|         tab_widget = self.stacked_widget.widget(self.stacked_widget.count() - 1) | ||||
|         if tab_widget and tab_widget.layout(): | ||||
|             tab_widget.layout().addWidget(test_checkbox) | ||||
|  | ||||
|         # Подключаем сигнал к слоту обновления | ||||
|         test_checkbox.stateChanged.connect(self.update_auto_install_list) | ||||
|  | ||||
|         # Сохраняем чекбокс для доступа в будущем | ||||
|         self.install_tabs_data['auto']['test_checkbox'] = test_checkbox | ||||
|  | ||||
|     def create_manual_install_tab(self): | ||||
|         """Создает вкладку для ручной установки программ""" | ||||
|         ( | ||||
|             scripts, buttons, layout, | ||||
|             search_edit, scroll_area | ||||
|         ) = self._create_and_populate_install_tab( | ||||
|             "Ручная установка", "manualinstall", "Поиск скрипта ручной установки...", partial(self.filter_buttons, 'manual') | ||||
|             "Ручная установка", ["manualinstall"], "Поиск скрипта ручной установки...", partial(self.filter_buttons, 'manual') | ||||
|         ) | ||||
|         self.manualinstall_scripts = scripts | ||||
|         self.install_tabs_data['manual'] = { | ||||
|             'buttons': buttons, 'layout': layout, 'search_edit': search_edit, 'scroll_area': scroll_area | ||||
|         } | ||||
|  | ||||
|     def update_auto_install_list(self): | ||||
|         """Обновляет список на вкладке 'Автоматическая установка' при изменении чекбокса.""" | ||||
|         data = self.install_tabs_data.get('auto') | ||||
|         if not data: | ||||
|             return | ||||
|  | ||||
|         script_folders = ["autoinstall"] | ||||
|         if data['test_checkbox'].isChecked(): | ||||
|             script_folders.append("testinstall") | ||||
|  | ||||
|         # Перед удалением кнопок останавливаем все связанные с ними таймеры анимации | ||||
|         for btn in data['buttons']: | ||||
|             if btn in self.icon_animators: | ||||
|                 anim_data = self.icon_animators.pop(btn) | ||||
|                 if 'main_timer' in anim_data: | ||||
|                     anim_data['main_timer'].stop() | ||||
|                 if 'animation' in anim_data and anim_data['animation']: | ||||
|                     anim_data['animation'].stop() | ||||
|  | ||||
|         # Сбрасываем ссылку на активную кнопку, если она была удалена | ||||
|         if self.current_active_button in data['buttons']: | ||||
|             self.current_active_button = None | ||||
|  | ||||
|         # Очищаем старые кнопки и layout | ||||
|         for btn in data['buttons']: | ||||
|             btn.parent().deleteLater() | ||||
|         data['buttons'].clear() | ||||
|  | ||||
|         # Заполняем layout новыми кнопками | ||||
|         scripts = [] | ||||
|         for folder in script_folders: | ||||
|             script_path = os.path.join(Var.DATA_PATH, folder) | ||||
|             if os.path.isdir(script_path): | ||||
|                 try: | ||||
|                     folder_scripts = sorted(os.listdir(script_path)) | ||||
|                     self._populate_install_grid(data['layout'], folder_scripts, folder, data['buttons']) | ||||
|                     scripts.extend(folder_scripts) | ||||
|                 except OSError as e: | ||||
|                     print(f"Не удалось прочитать директорию {script_path}: {e}") | ||||
|  | ||||
|         self.autoinstall_scripts = scripts | ||||
|         # Применяем текущий фильтр поиска к обновленному списку | ||||
|         self.filter_buttons('auto') | ||||
|  | ||||
|     def create_installed_tab(self): | ||||
|         """Создает вкладку для отображения установленных программ в виде кнопок""" | ||||
|         installed_tab, self.installed_scroll_layout, self.installed_search_edit, self.installed_scroll_area = self._create_searchable_grid_tab( | ||||
|             "Поиск установленной программы...", self.filter_installed_buttons | ||||
|             "Поиск установленной программы...", self.filter_installed_buttons, add_stretch=True | ||||
|         ) | ||||
|         self.add_tab(installed_tab, "Установленные") | ||||
|  | ||||
| @@ -2421,7 +2519,7 @@ class WineHelperGUI(QMainWindow): | ||||
|             prefix_names = [] | ||||
|  | ||||
|         self.created_prefix_selector.blockSignals(True) | ||||
|         self.remove_all_button.setEnabled(bool(prefix_names)) | ||||
|         self.remove_all_button.setEnabled(True) | ||||
|         self.created_prefix_selector.clear() | ||||
|         if prefix_names: | ||||
|             self.created_prefix_selector.addItems(prefix_names) | ||||
| @@ -2437,7 +2535,7 @@ class WineHelperGUI(QMainWindow): | ||||
|             self.current_managed_prefix_name = None | ||||
|             self._setup_prefix_management_panel(None) | ||||
|             self.delete_prefix_button.setEnabled(False) | ||||
|             self.remove_all_button.setEnabled(False) | ||||
|             self.remove_all_button.setEnabled(True) | ||||
|             self.create_base_pfx_button.setEnabled(False) | ||||
|             self.open_prefix_folder_button.setEnabled(False) | ||||
|         else: | ||||
| @@ -3468,11 +3566,7 @@ class WineHelperGUI(QMainWindow): | ||||
|                 self.current_selected_app['name'] = name | ||||
|                 self.current_selected_app['exec'] = exec_cmd | ||||
|  | ||||
|                 # Состояния кнопки | ||||
|                 if desktop_path in self.running_apps: | ||||
|                     self.run_button.setText("Остановить") | ||||
|                 else: | ||||
|                     self.run_button.setText("Запустить") | ||||
|                 self._set_run_button_state(desktop_path in self.running_apps) | ||||
|  | ||||
|                 # Показываем панель информации | ||||
|                 self.info_panel.setVisible(True) | ||||
| @@ -3660,7 +3754,8 @@ class WineHelperGUI(QMainWindow): | ||||
|         msg_box.setText( | ||||
|             "Приложение будет запущено в режиме отладки.\n\n" | ||||
|             "После закрытия приложения лог будет сохранен в папке 'winehelper_backup_log' " | ||||
|             "в вашем домашнем каталоге под именем 'winehelper.log'." | ||||
|             "в вашем домашнем каталоге под именем (пример: prefix_program.log).\n\n" | ||||
|             "Продолжить?" | ||||
|         ) | ||||
|         msg_box.addButton(yes_button, QMessageBox.YesRole) | ||||
|         msg_box.addButton(no_button, QMessageBox.NoRole) | ||||
| @@ -3865,10 +3960,27 @@ class WineHelperGUI(QMainWindow): | ||||
|  | ||||
|             # Если текущее выбранное приложение - то, что только что завершилось, обновляем кнопку | ||||
|             if self.current_selected_app and self.current_selected_app.get('desktop_path') == desktop_path: | ||||
|                 self.run_button.setText("Запустить") | ||||
|                 self._set_run_button_state(False) | ||||
|         else: | ||||
|             print(f"Предупреждение: получен сигнал finished для неизвестного процесса {desktop_path}") | ||||
|  | ||||
|     def _set_run_button_state(self, is_running): | ||||
|         """Устанавливает текст и стиль для кнопки Запустить/Остановить.""" | ||||
|         if is_running: | ||||
|             self.run_button.setText("Остановить") | ||||
|             self.run_button.setStyleSheet(self.STOP_BUTTON_STYLE) | ||||
|             self.create_log_button.setEnabled(False) | ||||
|             self.backup_button.setEnabled(False) | ||||
|             self.uninstall_button.setEnabled(False) | ||||
|             self.restore_prefix_button_panel.setEnabled(False) | ||||
|         else: | ||||
|             self.run_button.setText("Запустить") | ||||
|             self.run_button.setStyleSheet(self.RUN_BUTTON_STYLE) | ||||
|             self.create_log_button.setEnabled(True) | ||||
|             self.backup_button.setEnabled(True) | ||||
|             self.uninstall_button.setEnabled(True) | ||||
|             self.restore_prefix_button_panel.setEnabled(True) | ||||
|  | ||||
|     def _run_app_launcher(self, debug=False): | ||||
|         """Внутренний метод для запуска приложения (с отладкой или без) с использованием QProcess.""" | ||||
|         if not self.current_selected_app or 'exec' not in self.current_selected_app: | ||||
| @@ -3935,7 +4047,7 @@ class WineHelperGUI(QMainWindow): | ||||
|                     raise RuntimeError(f"Не удалось запустить процесс: {process.errorString()}") | ||||
|  | ||||
|                 self.running_apps[desktop_path] = process | ||||
|                 self.run_button.setText("Остановить") | ||||
|                 self._set_run_button_state(True) | ||||
|                 print(f"Запущено: {program} {' '.join(arguments)}") | ||||
|             except Exception as e: | ||||
|                 QMessageBox.critical(self, "Ошибка запуска", | ||||
| @@ -4213,6 +4325,8 @@ class WineHelperGUI(QMainWindow): | ||||
|         if script_name in self.autoinstall_scripts: | ||||
|             script_path = os.path.join(Var.DATA_PATH, "autoinstall", script_name) | ||||
|             tab_type = 'auto' | ||||
|             if not os.path.exists(script_path): # Проверяем в testinstall, если не нашли в autoinstall | ||||
|                 script_path = os.path.join(Var.DATA_PATH, "testinstall", script_name) | ||||
|             self.manual_install_path_widget.setVisible(False) | ||||
|         else: | ||||
|             script_path = os.path.join(Var.DATA_PATH, "manualinstall", script_name) | ||||
| @@ -4378,7 +4492,9 @@ class WineHelperGUI(QMainWindow): | ||||
|  | ||||
|         winehelper_path = self.winehelper_path | ||||
|         script_path = os.path.join(Var.DATA_PATH, | ||||
|                                    "autoinstall" if self.current_script in self.autoinstall_scripts else "manualinstall", | ||||
|                                    "autoinstall" if os.path.exists(os.path.join(Var.DATA_PATH, "autoinstall", self.current_script)) | ||||
|                                    else "testinstall" if os.path.exists(os.path.join(Var.DATA_PATH, "testinstall", self.current_script)) | ||||
|                                    else "manualinstall", | ||||
|                                    self.current_script) | ||||
|  | ||||
|         if not os.path.exists(winehelper_path): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user