Compare commits

...

31 Commits

Author SHA1 Message Date
Mikhail Tergoev
151b6d6e30 added NetTest (demo) to manualinstall 2025-09-25 01:05:34 +03:00
Mikhail Tergoev
c8049efd37 fixed create symlink from xuser to user 2025-09-23 17:31:51 +03:00
Mikhail Tergoev
8eb5a0aa86 rever wine_x_tkg_10-0_amd64 for scadoffice 2025-09-23 17:30:53 +03:00
Mikhail Tergoev
7edc205b66 updated wine and pfx for scadoffice 2025-09-23 16:40:54 +03:00
Mikhail Tergoev
b36cadd54d fixed copy user dir in create_base_pfx 2025-09-23 16:34:39 +03:00
Mikhail Tergoev
48d870979f Merge branch 'minergenon-devel' 2025-09-23 10:23:00 +03:00
Sergey Palcheh
cbe535b878 removed the jump when selecting the app button 2025-09-23 10:40:33 +06:00
Mikhail Tergoev
fd3442888d Merge branch 'minergenon-devel' 2025-09-22 22:22:22 +03:00
Sergey Palcheh
7321542477 the install app prefix button has been changed 2025-09-22 18:03:17 +06:00
Sergey Palcheh
477f44a11e the pop-up window was removed after the prefix was removed 2025-09-22 17:28:34 +06:00
Sergey Palcheh
4f9821450a removed the pop-up window after creating a shortcut 2025-09-22 17:21:11 +06:00
Sergey Palcheh
f858746064 removed the pop-up window after creating the prefix 2025-09-22 17:12:21 +06:00
Sergey Palcheh
1123c018eb removed the pop-up window after successful installation 2025-09-22 17:01:46 +06:00
Sergey Palcheh
998eff3263 changed the launch of the system wine when installing the application 2025-09-22 16:48:49 +06:00
Mikhail Tergoev
4aebb722ca changed icon for menu directory 2025-09-17 13:48:40 +03:00
Mikhail Tergoev
4672dcd4e1 disabled winebth.sys by default 2025-09-17 13:37:42 +03:00
Mikhail Tergoev
e174b034df fixed info for arm-kt-med 2025-09-17 12:38:26 +03:00
Mikhail Tergoev
3100475b1e added StartupWMClass for desktop files 2025-09-17 12:36:27 +03:00
Mikhail Tergoev
148a7dbfce force disabled winemenubuilder.exe 2025-09-17 12:28:29 +03:00
Mikhail Tergoev
5c01220382 added ARM-KT-* programs 2025-09-16 19:20:41 +03:00
Mikhail Tergoev
b74fe77bad Merge branch 'minergenon-devel' 2025-09-16 13:22:37 +03:00
Sergey Palcheh
3a442f6288 updated the creation of a list of prefixes 2025-09-12 17:49:58 +06:00
Mikhail Tergoev
20030d43e4 Merge branch 'minergenon-devel' 2025-09-12 12:54:20 +03:00
Sergey Palcheh
b44849661d added esync and fsync control buttons 2025-09-12 12:16:19 +06:00
Mikhail Tergoev
4c39ec3c8e updated doc path 2025-09-11 14:10:24 +03:00
Mikhail Tergoev
8950d8de2f Merge branch 'minergenon-devel' 2025-09-11 13:24:10 +03:00
Sergey Palcheh
85bd5fdf5d the path for reading the THIRD-PARTY file has been fixed 2025-09-11 15:20:09 +06:00
Sergey Palcheh
b98c6e5408 added auto-completion for change-wine 2025-09-11 13:28:50 +06:00
Sergey Palcheh
bab49377a3 added the wine/proton control button to the created prefix 2025-09-11 12:52:04 +06:00
Sergey Palcheh
aa591112ff simplifying the definition of the path to dependencies.sh 2025-09-11 11:12:17 +06:00
Sergey Palcheh
08090bbb6b fixed the winetricks detection path 2025-09-11 10:45:30 +06:00
18 changed files with 654 additions and 135 deletions

View File

@@ -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

View File

@@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View File

@@ -6,10 +6,10 @@ export WH_WINE_USE="wine_x_tkg_10-0_amd64"
export WINEPREFIX="scadoffice"
export PROG_NAME="SCAD Office"
export PROG_ICON="scadoffice"
export BASE_PFX="scadaoffice_pfx_x64_v03"
export BASE_PFX="scadaoffice_pfx_x64_v04"
export WH_WINDOWS_VER="10"
export WINEARCH="win64"
export INSTALL_DLL="dotnet20 dotnet472 dotnet48 gdiplus vcrun6sp6 vcrun2005 vcrun2019 d3dx11_42 d3dx11_43 d3dx9 d3dcompiler_42 d3dcompiler_43 d3dcompiler_46 d3dcompiler_47 richtx32 riched30 riched20 msxml6"
export INSTALL_DLL="dotnet20 dotnet48 gdiplus vcrun6sp6 vcrun2005 vcrun2019 d3dx11_42 d3dx11_43 d3dx9 d3dcompiler_42 d3dcompiler_43 d3dcompiler_46 d3dcompiler_47 richtx32 riched30 riched20 msxml6"
export WH_XDG_OPEN="rtf"
AUTOINSTALL_EXE="${WH_TMP_DIR}/SCADOffice_installer.exe"
SCADOFFICE_ADDONS_URL="https://cloud.linux-gaming.ru/portproton/scadoffice_addons_v02.tar.xz"

BIN
image/armkt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
image/nettest_client.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
image/nettest_server.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

34
manualinstall/nettest Normal file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# info_ru: Установщик программного комплекса NetTest (демо-версия)
########################################################################
export PROG_URL="https://www.kpolyakov.spb.ru/prog/nettest/nettget.htm"
export WH_WINE_USE="wine_x_tkg_10-0_amd64"
export WINEPREFIX="nettest"
export PROG_NAME="NetTest"
export PROG_ICON="nettest"
export BASE_PFX="none"
export WINEARCH="win64"
export INSTALL_DLL=""
export WH_WINDOWS_VER="10"
ZIP_FILE="$2"
if [[ -f "$ZIP_FILE" ]] \
&& [[ $ZIP_FILE =~ ".zip" ]]
then
prepair_wine
PROG_PATH="$DRIVE_C/nettest"
unpack "$2" "$PROG_PATH"
cp -fr "$PROG_PATH/fonts/"* "$DRIVE_C/windows/Fonts/"
create_desktop "$PROG_NAME (Сервер)" "$PROG_PATH/testser.exe" "nettest_server"
create_desktop "$PROG_NAME (Клиент)" "$PROG_PATH/testcli.exe" "nettest_client"
else
fatal "Не найден файл архива для $PROG_NAME. Перезапустите по примеру:
winehelper install $1 \"/путь/до/архива\""
fi

View File

@@ -5,6 +5,7 @@
fb7fdfde96de10a1b3b051bdf2727b6a7c1768b878483726454dd6726e9e0193 wine-9.0.14-alt1-i586-spravkibk.tar.xz
e0a84bb4908c3927954d7eef6b8ac7212e442b8c107d000c6890fec340f96183 wine-9.0.14-alt1-amd64.tar.xz
6f86d2220b65b709bf88c6f829a4998de3b929cc2091cd1333a51c32e1491b79 wine-9.0.9-alt1-i586.tar.xz
f1bf1261550ca2928cefacdb724926d3d6d103433d0ff6882ee9783a50d8f4e4 wine-8.8-staging-amd64.tar.xz
61bec1230b37b8fcc69fd45f848b44fd88cc41fcdd5dc3080336d7da63660f40 wine-7.16.1-alt1-amd64.tar.xz
6fea17fd131f57c2ebf7ca4c60d3c5a9e819afe16e5d0b77ecb750da99ae0e38 wine-7.16.1-alt1-i586.tar.xz
@@ -211,8 +212,8 @@ dfb44ce5e5af7dba1686932c63d6b05e5dd6919a21c78130a7d1d0271b93958e audiorecstatio
# create with wine_x_tkg_10-0_i586 (universal user: xuser)
# winetricks arial dotnet7 dotnetdesktop7 renderer=gdi
25e277c7afa4a9afc5f013cb05f872c12a7f381c4f0503a423dcacccca9a14c6 scadaoffice_pfx_x64_v03.tar.xz
# create with wine_x_tkg_10-0_i586 (universal user: xuser)
4fa93434c5c15440014357323257ddcee7d28b94ad6a56bd6f5a08b33ae4c3cb scadaoffice_pfx_x64_v04.tar.xz
# create with wine-8.8-staging-amd64
# winetricks dotnet48 gdiplus vcrun6sp6 vcrun2005 vcrun2019 d3dx11_42 d3dx11_43 d3dx9 d3dcompiler_42 d3dcompiler_43 d3dcompiler_46 d3dcompiler_47 richtx32 riched30 riched20 msxml6 dotnet20
# + addons with ODBC, SSH, *.reg
0f4ef434df07bc338ae308af44330590eaa1d9c94b64850514e55b960642d0eb scadoffice_addons_v02.tar.xz

View File

@@ -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
@@ -1107,6 +1111,11 @@ init_wineprefix () {
export DRIVE_C="$WINEPREFIX/drive_c"
export XUSER_PATH="$DRIVE_C/users/xuser"
if [[ -d "$XUSER_PATH" ]] \
&& [[ ! -d "$DRIVE_C/users/$USER" ]]
then try_force_link_dir "$XUSER_PATH" "$DRIVE_C/users/$USER"
fi
if [[ ! -f "$WINEPREFIX/.firstboot" ]] ; then
create_new_dir "$WINEPREFIX"
if [[ "$CLEAR_PREFIX" == "1" ]]
@@ -1352,8 +1361,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 +1659,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 +1674,7 @@ select_wine_version() {
print_error "Неверный выбор. Введите число от 0 до $max_choice."
fi
done
return 0
}
create_prefix() {
@@ -1716,7 +1724,7 @@ create_prefix() {
*) fatal "Неверный выбор. Операция отменена." ;;
esac
select_wine_version
select_wine_version || exit 0
print_info "Выберите тип создаваемого префикса:"
echo " 0) Отмена создания префикса"
@@ -1810,9 +1818,9 @@ create_base_pfx () {
&& [[ ! -L "$users_dir/$USER" ]]
then
if [[ -L "$users_dir/xuser" ]]
then try_remove_dir "$users_dir/xuser/"
then try_remove_dir "$users_dir/xuser"
fi
create_new_dir "$users_dir/xuser/"
create_new_dir "$users_dir/xuser"
cp -fr "$users_dir/$USER"/* "$users_dir/xuser/"
fi
@@ -2123,6 +2131,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 +2192,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 +2223,7 @@ wh_info () {
install-dxvk [версия|none|list] установить, удалить или показать версии DXVK
install-vkd3d [версия|none|list] установить, удалить или показать версии VKD3D
change-wine [версия] изменить версию Wine/Proton для текущего префикса
installed список установленных программ
run [программа] запуск программы (отладка)
@@ -2217,6 +2260,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 +2276,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 "$@" ;;

View File

@@ -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

View File

@@ -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 файла зависимостей."""
@@ -1574,6 +1571,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 +2112,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 +2206,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 +2234,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 +2310,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 +2318,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 +2360,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 +2379,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 +2407,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 +2421,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 +2434,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 +2457,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 +2538,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 +2653,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 +2824,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 +2970,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 +3038,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 +3058,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 +3294,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 +3341,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 +3734,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 +4089,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 +4202,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()):