Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0475c7e058 | ||
|
|
b146b01a82 | ||
|
|
41232f2315 | ||
|
|
73696de876 | ||
|
|
3cbdef4f00 | ||
|
|
4b0fea887b | ||
|
|
4d77861863 | ||
|
|
2854f8751b | ||
|
|
53a09b13d7 | ||
|
|
0df709380c | ||
|
|
e49a267d4c | ||
|
|
9724b75fc2 | ||
|
|
436e250932 | ||
|
|
6160eef77b |
@@ -7,23 +7,29 @@ if [[ $(id -u) -ne 0 ]] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
##### MESSAGES FUNCTIONS #####
|
##### MESSAGES FUNCTIONS #####
|
||||||
print_error () { printf "\E[31m%s ВНИМАНИЕ: $@ %s\e[0m\n" ;}
|
if [[ -t 0 ]] ; then
|
||||||
fatal () { print_error "$@" ; exit 1 ;}
|
print_error () { printf "\E[31m%s Ошибка: $* %s\e[0m\n" ;}
|
||||||
|
else
|
||||||
|
print_error () { echo -e "Ошибка: $*" ;}
|
||||||
|
fi
|
||||||
|
|
||||||
##### UPDATE SYSTEM #####
|
fatal () {
|
||||||
apt-get update || fatal "Не удалось обновить список доступных пакетов,"
|
print_error "$@ Аварийное завершение работы WineHelper!"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
##### CHECK AREPO (x86_64-i586) #####
|
##### CHECK AREPO (x86_64-i586) #####
|
||||||
apt-repo | grep -q "x86_64-i586" || fatal "Репозиторий x86_64-i586 не подключен. \
|
apt-repo | grep -q "x86_64-i586" || fatal "Репозиторий x86_64-i586 не подключен. \
|
||||||
32-битные зависимости не будут установлены, а значит не будут работать и 32-битные \
|
32-битные зависимости не будут установлены, а значит не будут работать и 32-битные \
|
||||||
windows приложения. Подробнее по ссылке: https://www.altlinux.org/Biarch"
|
windows приложения. Подробнее по ссылке: https://www.altlinux.org/Biarch"
|
||||||
|
|
||||||
|
##### UPDATE SYSTEM #####
|
||||||
|
apt-get update || fatal "Не удалось обновить список доступных пакетов,"
|
||||||
|
|
||||||
##### INSTALL DEPENDENCIES #####
|
##### INSTALL DEPENDENCIES #####
|
||||||
# fonts-ttf-ms
|
# fonts-ttf-ms
|
||||||
|
|
||||||
apt-get install {i586-,}{glibc-core,libstdc++6,glibc-pthread,glibc-nss,\
|
apt-get install i586-{wine,glibc-core,libstdc++6,glibc-pthread,glibc-nss,\
|
||||||
libnm,libnss,libnss-mdns,libnsl1,libunwind,libunixODBC2,ocl-icd,libfreetype,\
|
libnm,libnss,libnss-mdns,libnsl1,libunwind,libunixODBC2,ocl-icd,libfreetype,\
|
||||||
libcups,libfontconfig1,libgnutls30,libGL,libEGL,libvulkan1,xorg-dri-swrast,\
|
libcups,libfontconfig1,libgnutls30,libGL,libEGL,libvulkan1,xorg-dri-swrast,\
|
||||||
xorg-dri-intel,xorg-dri-radeon} || fatal "Не удалось установить зависимости."
|
xorg-dri-intel,xorg-dri-radeon} || fatal "Не удалось установить зависимости."
|
||||||
|
|
||||||
apt-get install {i586-,}wine
|
|
||||||
|
|||||||
BIN
image/dialux.png
Normal file
BIN
image/dialux.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -2,7 +2,6 @@
|
|||||||
e9a8b79dfe12cad1304dca573d73aefe109e3d69b6fff739c8dbb8b2d3c271c6 wine-10.12.1-alt1-wow64.tar.xz
|
e9a8b79dfe12cad1304dca573d73aefe109e3d69b6fff739c8dbb8b2d3c271c6 wine-10.12.1-alt1-wow64.tar.xz
|
||||||
a862761c432f8619caf8100589678a1cbb523787259120ccd4388089d81e3b17 wine-10.18.1-tflex-alt2-wow64.tar.xz
|
a862761c432f8619caf8100589678a1cbb523787259120ccd4388089d81e3b17 wine-10.18.1-tflex-alt2-wow64.tar.xz
|
||||||
349c707148a23e667970309248bbbf97b4e2a0db59c548e73d9fe9c3f585872c wine-10.18.1-alt1-wow64.tar.xz
|
349c707148a23e667970309248bbbf97b4e2a0db59c548e73d9fe9c3f585872c wine-10.18.1-alt1-wow64.tar.xz
|
||||||
49d04a3a02e1ce66ed978d731fd0933d4fdcc1906fa1cb0de716ee20fd6cb451 wine-10.18.1-alt2-wow64.tar.xz
|
|
||||||
|
|
||||||
##### WINE AMD64 #####
|
##### WINE AMD64 #####
|
||||||
009c95bfe2df3f9264c9c5092f3e30ea7a168dd7869046058a718a70739602d4 wine_wh_tflex_10-9_amd64.tar.xz
|
009c95bfe2df3f9264c9c5092f3e30ea7a168dd7869046058a718a70739602d4 wine_wh_tflex_10-9_amd64.tar.xz
|
||||||
@@ -201,6 +200,10 @@ f18864014fdb2fead0b45b5e70e95073072b89168df8cd6debba89081ac51a2a ksamu_pfx_x64_
|
|||||||
# winetricks corefonts tahoma msxml6 msxml4 msxml3 riched30 msls31 riched20 msftedit richtx32 fontsmooth=gray
|
# winetricks corefonts tahoma msxml6 msxml4 msxml3 riched30 msls31 riched20 msftedit richtx32 fontsmooth=gray
|
||||||
# + manuall installed riched32
|
# + manuall installed riched32
|
||||||
|
|
||||||
|
06bb83c64ef5e749741fb009a12e07ad62865474c5c7db049894c7871a1471cc dialux_pfx_x86_v04.tar.xz
|
||||||
|
# create with wine_x_tkg_10-0_i586 (universal user: xuser)
|
||||||
|
# winetricks mdac27 wsh57 jet40 msxml6 mdac28 gdiplus msxml4 msxml3 vcrun2010 msls31 ie8 dotnet20sp1
|
||||||
|
|
||||||
##### ADDONS #####
|
##### ADDONS #####
|
||||||
# addons with ODBC, SSH, *.reg
|
# addons with ODBC, SSH, *.reg
|
||||||
0f4ef434df07bc338ae308af44330590eaa1d9c94b64850514e55b960642d0eb scadoffice_addons_v02.tar.xz
|
0f4ef434df07bc338ae308af44330590eaa1d9c94b64850514e55b960642d0eb scadoffice_addons_v02.tar.xz
|
||||||
|
|||||||
16
testinstall/dialux
Normal file
16
testinstall/dialux
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# info_ru: Программное обеспечение для 3D-графики, предназначенное для проектирования освещения. (Версия 4.4.0.2)
|
||||||
|
########################################################################
|
||||||
|
export WH_WINE_USE="wine_x_tkg_10-0_i586"
|
||||||
|
export WINEPREFIX="dialux"
|
||||||
|
export PROG_NAME="DIALux"
|
||||||
|
export PROG_ICON="dialux"
|
||||||
|
export BASE_PFX="dialux_pfx_x86_v04"
|
||||||
|
export WH_WINDOWS_VER="xp"
|
||||||
|
export WINEARCH="win32"
|
||||||
|
export INSTALL_DLL="mdac28 jet40 vcrun2010 gdiplus dotnet20sp1 msxml3 msxml4 msxml6 ie8"
|
||||||
|
|
||||||
|
prepair_wine
|
||||||
|
|
||||||
|
WIN_FILE_EXEC="$DRIVE_C/Program Files/DIALux/DIALux.exe"
|
||||||
|
create_desktop "$PROG_NAME" "$WIN_FILE_EXEC" "$PROG_ICON"
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# info_ru: “КСАМУ” - Комплексная система автоматизации медицинского учреждения.
|
# info_ru: “КСАМУ” - Комплексная система автоматизации медицинского учреждения.
|
||||||
########################################################################
|
########################################################################
|
||||||
export PROG_URL="https://docs.medicine-it.ru/"
|
export PROG_URL="https://docs.medicine-it.ru/"
|
||||||
export WH_WINE_USE="wine-10.18.1-alt2-wow64"
|
export WH_WINE_USE="wine-10.18.1-alt1-wow64"
|
||||||
export WINEPREFIX="ksamu"
|
export WINEPREFIX="ksamu"
|
||||||
export PROG_NAME="КСАМУ"
|
export PROG_NAME="КСАМУ"
|
||||||
export PROG_ICON="ksamu"
|
export PROG_ICON="ksamu"
|
||||||
@@ -12,11 +12,31 @@ export INSTALL_DLL="corefonts tahoma richtx32 riched20 riched30 msls31 msftedit
|
|||||||
# riched32
|
# riched32
|
||||||
export WH_WINDOWS_VER="7"
|
export WH_WINDOWS_VER="7"
|
||||||
export WH_USE_CPCSP_PROXY="1"
|
export WH_USE_CPCSP_PROXY="1"
|
||||||
export WH_USE_CPCSP_CADES="0"
|
|
||||||
export WINE_D3D_CONFIG="renderer=gdi"
|
|
||||||
export WH_MAIN_DECORATED="1"
|
export WH_MAIN_DECORATED="1"
|
||||||
export WH_VIRTUAL_DESKTOP="0"
|
export WH_VIRTUAL_DESKTOP="0"
|
||||||
export WINE_TOP_WINDOW="Открыть"
|
|
||||||
|
|
||||||
prepair_wine
|
prepair_wine
|
||||||
create_desktop "$PROG_NAME" "$DRIVE_C/KSAMU/KSAMU.exe" "$PROG_ICON"
|
create_desktop "$PROG_NAME" "$DRIVE_C/KSAMU/KSAMU.exe" "$PROG_ICON"
|
||||||
|
|
||||||
|
echo '
|
||||||
|
# хак для исправления открытия выбора файла сертификата в фоне
|
||||||
|
if ! command -v wmctrl &>/dev/null ; then
|
||||||
|
wmctrl_not_found="Для продолжения работы установите wmctrl:\n\nsu -\napt-get update\napt-get install wmctrl\nexit"
|
||||||
|
zenity --error --title="Ошибка" --text="$wmctrl_not_found" --ok-label="Выход"
|
||||||
|
fatal "$wmctrl_not_found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
background_task() {
|
||||||
|
while true; do
|
||||||
|
sleep 1
|
||||||
|
OPEN_WIN_ID=$(wmctrl -xl | grep -i "ksamu" | grep -i "открыть" | cut -d" " -f1)
|
||||||
|
if [[ -n $OPEN_WIN_ID ]] ; then
|
||||||
|
wmctrl -i -r $OPEN_WIN_ID -b add,above
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
background_task &
|
||||||
|
WH_BG_PID=$!
|
||||||
|
export WH_BG_PID
|
||||||
|
' >> "$DRIVE_C/KSAMU/KSAMU.exe.whdb"
|
||||||
|
|||||||
148
winehelper
148
winehelper
@@ -40,7 +40,6 @@ else
|
|||||||
WH_WINETRICKS="/usr/bin/winetricks"
|
WH_WINETRICKS="/usr/bin/winetricks"
|
||||||
WH_DEVEL="1"
|
WH_DEVEL="1"
|
||||||
|
|
||||||
|
|
||||||
# минимальная проверка синтаксиса скриптов
|
# минимальная проверка синтаксиса скриптов
|
||||||
for self_check_script in "$RUN_SCRIPT" \
|
for self_check_script in "$RUN_SCRIPT" \
|
||||||
"$DATA_PATH/dependencies.sh" "$DATA_PATH/autoinstall"/* \
|
"$DATA_PATH/dependencies.sh" "$DATA_PATH/autoinstall"/* \
|
||||||
@@ -101,7 +100,7 @@ if [[ "$1" == "--debug" ]] ; then
|
|||||||
export DXVK_NVAPI_LOG_LEVEL="error"
|
export DXVK_NVAPI_LOG_LEVEL="error"
|
||||||
shift
|
shift
|
||||||
else
|
else
|
||||||
check_variables WINEDEBUG "-all,err+all"
|
check_variables WINEDEBUG "-all"
|
||||||
check_variables DXVK_LOG_LEVEL "none"
|
check_variables DXVK_LOG_LEVEL "none"
|
||||||
check_variables VKD3D_SHADER_DEBUG "none"
|
check_variables VKD3D_SHADER_DEBUG "none"
|
||||||
check_variables VKD3D_DEBUG "none"
|
check_variables VKD3D_DEBUG "none"
|
||||||
@@ -150,6 +149,7 @@ check_variables WH_USE_EXTRA_FONTS "0"
|
|||||||
check_variables EXTRA_FONTS_VER "01"
|
check_variables EXTRA_FONTS_VER "01"
|
||||||
check_variables WH_FONT_MSS_REPLACE "0"
|
check_variables WH_FONT_MSS_REPLACE "0"
|
||||||
check_variables WH_FONT_SMOOTHING "0"
|
check_variables WH_FONT_SMOOTHING "0"
|
||||||
|
# check_variables FREETYPE_PROPERTIES "truetype:interpreter-version=35"
|
||||||
|
|
||||||
check_variables STAGING_SHARED_MEMORY "1"
|
check_variables STAGING_SHARED_MEMORY "1"
|
||||||
check_variables WINE_LARGE_ADDRESS_AWARE "1"
|
check_variables WINE_LARGE_ADDRESS_AWARE "1"
|
||||||
@@ -208,18 +208,29 @@ su_run () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
##### CHECK DEPENDENCIES #####
|
##### CHECK DEPENDENCIES #####
|
||||||
# fonts-ttf-ms
|
check_deps_i586 () {
|
||||||
|
if [[ $WH_USE_GUI != "1" ]] && [[ ! -t 0 ]] ; then
|
||||||
|
print_warning "Скрипт запущен из desktop файла."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if ! rpm -q {i586-,}{wine,glibc-core,libstdc++6,glibc-pthread,glibc-nss,\
|
if [[ $WH_SKIP_DEPS == "1" ]] ; then
|
||||||
|
unset WH_SKIP_DEPS
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! rpm -q i586-{wine,glibc-core,libstdc++6,glibc-pthread,glibc-nss,\
|
||||||
libnm,libnss,libnss-mdns,libnsl1,libunwind,libunixODBC2,ocl-icd,libfreetype,\
|
libnm,libnss,libnss-mdns,libnsl1,libunwind,libunixODBC2,ocl-icd,libfreetype,\
|
||||||
libcups,libfontconfig1,libgnutls30,libGL,libEGL,libvulkan1,xorg-dri-swrast,\
|
libcups,libfontconfig1,libgnutls30,libGL,libEGL,libvulkan1,xorg-dri-swrast,\
|
||||||
xorg-dri-intel,xorg-dri-radeon} 1>/dev/null
|
xorg-dri-intel,xorg-dri-radeon} 1>/dev/null
|
||||||
then
|
then
|
||||||
|
print_warning "Необходимо установить 32-битные зависимости!"
|
||||||
if su_run "$DATA_PATH/dependencies.sh"
|
if su_run "$DATA_PATH/dependencies.sh"
|
||||||
then print_info "Зависимости успешно установлены. Продолжаем работу $SCRIPT_NAME"
|
then print_info "Зависимости успешно установлены. Продолжаем работу $SCRIPT_NAME"
|
||||||
else fatal "Не удалось установить зависимости. Работа $SCRIPT_NAME прервана."
|
else fatal "Не удалось установить зависимости. Работа $SCRIPT_NAME прервана."
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
##### HELPER FUNCTIONS #####
|
##### HELPER FUNCTIONS #####
|
||||||
add_to_var () {
|
add_to_var () {
|
||||||
@@ -782,13 +793,6 @@ check_installed_programs () {
|
|||||||
[[ -n $2 ]] && fatal "Не найден файл запуска для $2"
|
[[ -n $2 ]] && fatal "Не найден файл запуска для $2"
|
||||||
}
|
}
|
||||||
|
|
||||||
run_installed_programs () {
|
|
||||||
if check_installed_programs check_only "$1" ; then
|
|
||||||
/usr/bin/env bash -c "\"$RUN_SCRIPT\" \"$EXE_PATH\"" &
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_wined3d () {
|
copy_wined3d () {
|
||||||
for wined3dfiles in $1 ; do
|
for wined3dfiles in $1 ; do
|
||||||
try_copy_wine_dll_to_pfx_64 "$wined3dfiles.dll"
|
try_copy_wine_dll_to_pfx_64 "$wined3dfiles.dll"
|
||||||
@@ -880,19 +884,26 @@ init_wine_ver () {
|
|||||||
try_download cloud "$download_url" "$wine_package" "check256sum"
|
try_download cloud "$download_url" "$wine_package" "check256sum"
|
||||||
unpack "$wine_package" "$WH_DIST_DIR/"
|
unpack "$wine_package" "$WH_DIST_DIR/"
|
||||||
try_remove_file "$wine_package"
|
try_remove_file "$wine_package"
|
||||||
|
fi
|
||||||
|
|
||||||
# Управление структурой подкаталога Proton "files", перемещая содержимое вверх
|
# Управление структурой подкаталога Proton "files", перемещая содержимое вверх
|
||||||
if [[ -d "$WINEDIR/files" ]]; then
|
if [[ ${WINEDIR,,} =~ proton ]] \
|
||||||
|
&& [[ -d "$WINEDIR/files" ]]
|
||||||
|
then
|
||||||
print_info "Обнаружена структура каталогов Proton, исправляем пути..."
|
print_info "Обнаружена структура каталогов Proton, исправляем пути..."
|
||||||
mv "$WINEDIR"/files/* "$WINEDIR/"
|
mv "$WINEDIR"/files/* "$WINEDIR/"
|
||||||
rmdir "$WINEDIR/files"
|
try_remove_dir "$WINEDIR/files"
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[[ ! -f "$WINEDIR/version" ]] && echo "$WH_WINE_USE" > "$WINEDIR/version"
|
if [[ ! -f "$WINEDIR/version" ]] ; then
|
||||||
if [[ $WH_WINE_USE =~ wow64 ]]
|
echo "$WH_WINE_USE" > "$WINEDIR/version"
|
||||||
then export WH_WINE_WOW64="1"
|
fi
|
||||||
else export WH_WINE_WOW64="0"
|
|
||||||
|
if [[ $WH_WINE_USE =~ wow64 ]] ; then
|
||||||
|
export WH_WINE_WOW64="1"
|
||||||
|
else
|
||||||
|
export WH_WINE_WOW64="0"
|
||||||
|
check_deps_i586
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export WINE="$WINEDIR/bin/wine"
|
export WINE="$WINEDIR/bin/wine"
|
||||||
@@ -1148,37 +1159,25 @@ init_wineprefix () {
|
|||||||
export DRIVE_C="$WINEPREFIX/drive_c"
|
export DRIVE_C="$WINEPREFIX/drive_c"
|
||||||
export XUSER_PATH="$DRIVE_C/users/xuser"
|
export XUSER_PATH="$DRIVE_C/users/xuser"
|
||||||
|
|
||||||
if [[ -d "$XUSER_PATH" ]] \
|
if [[ ! -d "$WINEPREFIX" ]] ; then
|
||||||
&& [[ ! -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"
|
create_new_dir "$WINEPREFIX"
|
||||||
if [[ "$CLEAR_PREFIX" == "1" ]]
|
if [[ "$CLEAR_PREFIX" == "1" ]]
|
||||||
then print_warning "Используется переменная \"CLEAR_PREFIX=1\", которая принудительно создает чистый префикс с установкой компонентов с помощью winetricks."
|
then print_warning "Используется переменная \"CLEAR_PREFIX=1\", которая принудительно создает чистый префикс с установкой компонентов с помощью winetricks."
|
||||||
elif [[ "$BASE_PFX" != "none" ]]
|
elif [[ "$BASE_PFX" != "none" ]]
|
||||||
then get_base_pfx "$BASE_PFX"
|
then get_base_pfx "$BASE_PFX"
|
||||||
fi
|
fi
|
||||||
print_info "Обновление префикса $WINEPREFIX."
|
|
||||||
if [[ -d "$WINEPREFIX/drive_c/windows" ]]
|
|
||||||
then "$WINELOADER" wineboot -u
|
|
||||||
else "$WINELOADER" wineboot -i
|
|
||||||
fi
|
|
||||||
touch "$WINEPREFIX/.firstboot"
|
|
||||||
wait_wineserver
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -f "$WINEPREFIX/system.reg" ]] \
|
if [[ ! -d "$WINEPREFIX/drive_c/windows" ]] ; then
|
||||||
&& [[ -z $(grep "Windows $WH_WINDOWS_VER" "$WINEPREFIX/system.reg") ]]
|
print_info "Создание префикса $WINEPREFIX."
|
||||||
then
|
"$WINELOADER" wineboot -i
|
||||||
if [[ $(echo "$WH_WINDOWS_VER" | sed 's/.*/\L&/') == "xp" ]] \
|
wait_wineserver
|
||||||
&& [[ "$WINEARCH" != "win32" ]]
|
elif [[ ! -f "$WINEPREFIX/.update-timestamp" ]] \
|
||||||
then export WH_WINDOWS_VER="xp64"
|
|| [[ ! -d "$WINEPREFIX/drive_c/users" ]]
|
||||||
fi
|
then
|
||||||
"$WINELOADER" winecfg -v $(echo "win${WH_WINDOWS_VER}" | sed 's/.*/\L&/')
|
print_info "Обновление префикса $WINEPREFIX."
|
||||||
|
"$WINELOADER" wineboot -u
|
||||||
wait_wineserver
|
wait_wineserver
|
||||||
print_info "Windows версия изменена на win${WH_WINDOWS_VER}"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -d "$XUSER_PATH" ]] && [[ ! -d "$DRIVE_C/users/$USER" ]]
|
if [[ -d "$XUSER_PATH" ]] && [[ ! -d "$DRIVE_C/users/$USER" ]]
|
||||||
@@ -1187,19 +1186,47 @@ init_wineprefix () {
|
|||||||
then try_force_link_dir "$DRIVE_C/users/$USER" "$XUSER_PATH"
|
then try_force_link_dir "$DRIVE_C/users/$USER" "$XUSER_PATH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -f "$WINEPREFIX/.update-timestamp" ]] ; then
|
|
||||||
print_info "Обновление префикса $WINEPREFIX."
|
|
||||||
"$WINELOADER" wineboot -u
|
|
||||||
wait_wineserver
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -L "$XUSER_PATH/Desktop" ]]
|
if [[ -L "$XUSER_PATH/Desktop" ]]
|
||||||
then rm -f "$XUSER_PATH/Desktop"
|
then rm -f "$XUSER_PATH/Desktop"
|
||||||
fi
|
fi
|
||||||
create_new_dir "$XUSER_PATH/Desktop"
|
|
||||||
|
|
||||||
if [[ ! -L "$WINEPREFIX/dosdevices/h:" ]]
|
create_new_dir "$XUSER_PATH/Desktop"
|
||||||
then try_force_link_dir "$HOME" "$WINEPREFIX/dosdevices/h:"
|
create_new_dir "$XUSER_PATH/AppData/Local/Temp"
|
||||||
|
create_new_dir "$DRIVE_C/ProgramData/Package Cache"
|
||||||
|
create_new_dir "$DRIVE_C/windows/temp"
|
||||||
|
create_new_dir "$DRIVE_C/windows/Installer"
|
||||||
|
|
||||||
|
if [[ ! -d "$WINEPREFIX/dosdevices" ]] ; then
|
||||||
|
create_new_dir "$WINEPREFIX/dosdevices"
|
||||||
|
local run_wbr="1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "${WINEPREFIX}/dosdevices/c:" ]] ; then
|
||||||
|
try_force_link_dir "${WINEPREFIX}/drive_c/" "${WINEPREFIX}/dosdevices/c:"
|
||||||
|
fi
|
||||||
|
if [[ ! -d "${WINEPREFIX}/dosdevices/z:" ]] ; then
|
||||||
|
try_force_link_dir "/" "${WINEPREFIX}/dosdevices/z:"
|
||||||
|
fi
|
||||||
|
if [[ ! -d "${WINEPREFIX}/dosdevices/h:" ]] ; then
|
||||||
|
try_force_link_dir "$HOME" "${WINEPREFIX}/dosdevices/h:"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $run_wbr == "1" ]] ; then
|
||||||
|
"$WINELOADER" wineboot -r
|
||||||
|
wait_wineserver
|
||||||
|
unset run_wbr
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$WINEPREFIX/system.reg" ]] \
|
||||||
|
&& ! grep -iq "Microsoft Windows $WH_WINDOWS_VER" "$WINEPREFIX/system.reg"
|
||||||
|
then
|
||||||
|
if [[ $(echo "$WH_WINDOWS_VER" | sed 's/.*/\L&/') == "xp" ]] \
|
||||||
|
&& [[ "$WINEARCH" != "win32" ]]
|
||||||
|
then export WH_WINDOWS_VER="xp64"
|
||||||
|
fi
|
||||||
|
"$WINELOADER" winecfg -v $(echo "win${WH_WINDOWS_VER}" | sed 's/.*/\L&/')
|
||||||
|
wait_wineserver
|
||||||
|
print_info "Windows версия изменена на win${WH_WINDOWS_VER}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $WH_USE_MESA_GL_OVERRIDE == "1" ]] \
|
if [[ $WH_USE_MESA_GL_OVERRIDE == "1" ]] \
|
||||||
@@ -2113,8 +2140,6 @@ create_base_pfx () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# удаляем всё ненужное для переноса префикса
|
# удаляем всё ненужное для переноса префикса
|
||||||
try_remove_file "$prefix_dir/.update-timestamp"
|
|
||||||
try_remove_file "$prefix_dir/.firstboot"
|
|
||||||
try_remove_file "$prefix_dir/last.conf"
|
try_remove_file "$prefix_dir/last.conf"
|
||||||
try_remove_dir "$prefix_dir/dosdevices/"
|
try_remove_dir "$prefix_dir/dosdevices/"
|
||||||
try_remove_dir "$users_dir/$USER"
|
try_remove_dir "$users_dir/$USER"
|
||||||
@@ -2131,7 +2156,7 @@ create_base_pfx () {
|
|||||||
|
|
||||||
cd "$prefix_dir"
|
cd "$prefix_dir"
|
||||||
# запускаем сжатие префикса
|
# запускаем сжатие префикса
|
||||||
if tar --no-xattrs -c -I 'xz --memlimit=8000MiB -9 -T0' -f "$archive_path" ./* ; then
|
if tar --no-xattrs -c -I 'xz --memlimit=8000MiB -9 -T0' -f "$archive_path" . ; then
|
||||||
print_ok "Архив создан по пути: $archive_path"
|
print_ok "Архив создан по пути: $archive_path"
|
||||||
xdg-open "$(dirname "$archive_path")" &
|
xdg-open "$(dirname "$archive_path")" &
|
||||||
cd -
|
cd -
|
||||||
@@ -2163,7 +2188,6 @@ backup_prefix() {
|
|||||||
print_info "Подготовка префикса к упаковке..."
|
print_info "Подготовка префикса к упаковке..."
|
||||||
if cp -a "$WINEPREFIX" "$temp_prefix_dir" ; then
|
if cp -a "$WINEPREFIX" "$temp_prefix_dir" ; then
|
||||||
try_remove_dir "$temp_prefix_dir/dosdevices"
|
try_remove_dir "$temp_prefix_dir/dosdevices"
|
||||||
try_remove_file "$temp_prefix_dir/.update-timestamp"
|
|
||||||
if [[ -d "$temp_users_dir/$USER" ]] \
|
if [[ -d "$temp_users_dir/$USER" ]] \
|
||||||
&& [[ ! -L "$temp_users_dir/$USER" ]]
|
&& [[ ! -L "$temp_users_dir/$USER" ]]
|
||||||
then
|
then
|
||||||
@@ -2612,7 +2636,6 @@ case "$arg1" in
|
|||||||
install-vkd3d) run_install_vkd3d "$@" ;;
|
install-vkd3d) run_install_vkd3d "$@" ;;
|
||||||
change-wine) run_change_wine_version "$@" ;;
|
change-wine) run_change_wine_version "$@" ;;
|
||||||
installed) check_installed_programs "$1" ;;
|
installed) check_installed_programs "$1" ;;
|
||||||
run|-r) run_installed_programs "$1" ;;
|
|
||||||
backup-prefix) backup_prefix "$@" ;;
|
backup-prefix) backup_prefix "$@" ;;
|
||||||
restore-prefix) restore_prefix "$@" ;;
|
restore-prefix) restore_prefix "$@" ;;
|
||||||
remove-all) remove_winehelper "$@" ;;
|
remove-all) remove_winehelper "$@" ;;
|
||||||
@@ -2621,6 +2644,14 @@ case "$arg1" in
|
|||||||
create-base-pfx) create_base_pfx "$@" ;;
|
create-base-pfx) create_base_pfx "$@" ;;
|
||||||
init-prefix) prepair_wine ; wait_wineserver ;;
|
init-prefix) prepair_wine ; wait_wineserver ;;
|
||||||
clear-winetricks-cache) clear_winetricks_cache "$@" ;;
|
clear-winetricks-cache) clear_winetricks_cache "$@" ;;
|
||||||
|
run|-r)
|
||||||
|
if check_installed_programs check_only "$1" ; then
|
||||||
|
WIN_FILE_EXEC="$(readlink -f "$EXE_PATH")"
|
||||||
|
shift
|
||||||
|
prepair_wine
|
||||||
|
wine_run "$WIN_FILE_EXEC" "$@"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
if [[ -f "$arg1" ]] ; then
|
if [[ -f "$arg1" ]] ; then
|
||||||
WIN_FILE_EXEC="$(readlink -f "$arg1")"
|
WIN_FILE_EXEC="$(readlink -f "$arg1")"
|
||||||
@@ -2641,3 +2672,8 @@ case "$arg1" in
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if [[ -n "$WH_BG_PID" ]] ; then
|
||||||
|
print_info "Завершение фонового процесса: $WH_BG_PID"
|
||||||
|
kill "$WH_BG_PID" 2>/dev/null
|
||||||
|
fi
|
||||||
|
|||||||
@@ -33,393 +33,6 @@ class Var:
|
|||||||
GENERAL = os.environ.get("GENERAL")
|
GENERAL = os.environ.get("GENERAL")
|
||||||
WH_WINETRICKS = os.environ.get("WH_WINETRICKS")
|
WH_WINETRICKS = os.environ.get("WH_WINETRICKS")
|
||||||
|
|
||||||
class DependencyManager:
|
|
||||||
"""Класс для управления проверкой и установкой системных зависимостей."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Инициализирует менеджер, определяя необходимые пути."""
|
|
||||||
self.dependencies_script_path = self._get_dependencies_path()
|
|
||||||
self.config_dir = os.path.join(os.path.expanduser("~"), ".config", "winehelper")
|
|
||||||
self.hash_flag_file = os.path.join(self.config_dir, "dependencies_hash.txt")
|
|
||||||
os.makedirs(self.config_dir, exist_ok=True)
|
|
||||||
self.app_icon = QIcon(Var.WH_ICON_PATH) if Var.WH_ICON_PATH and os.path.exists(Var.WH_ICON_PATH) else QIcon()
|
|
||||||
|
|
||||||
def _get_dependencies_path(self):
|
|
||||||
"""Определяет и возвращает путь к скрипту dependencies.sh."""
|
|
||||||
if not Var.DATA_PATH:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return os.path.join(Var.DATA_PATH, 'dependencies.sh')
|
|
||||||
|
|
||||||
def _calculate_file_hash(self):
|
|
||||||
"""Вычисляет хэш SHA256 файла зависимостей."""
|
|
||||||
if not self.dependencies_script_path or not os.path.exists(self.dependencies_script_path):
|
|
||||||
return None
|
|
||||||
hasher = hashlib.sha256()
|
|
||||||
try:
|
|
||||||
with open(self.dependencies_script_path, 'rb') as f:
|
|
||||||
while chunk := f.read(4096):
|
|
||||||
hasher.update(chunk)
|
|
||||||
return hasher.hexdigest()
|
|
||||||
except IOError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _parse_dependencies_from_script(self):
|
|
||||||
"""
|
|
||||||
Парсит скрипт dependencies.sh для извлечения списка базовых пакетов.
|
|
||||||
Возвращает список пакетов или None в случае ошибки.
|
|
||||||
"""
|
|
||||||
if not os.path.exists(self.dependencies_script_path):
|
|
||||||
return None
|
|
||||||
|
|
||||||
base_packages = []
|
|
||||||
try:
|
|
||||||
with open(self.dependencies_script_path, 'r', encoding='utf-8') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
content = content.replace('\\\n', '')
|
|
||||||
pattern = r'apt-get install\s+\{i586-,\}(\{.*?\}|[\w.-]+)'
|
|
||||||
matches = re.findall(pattern, content)
|
|
||||||
|
|
||||||
for match in matches:
|
|
||||||
match = match.strip()
|
|
||||||
if match.startswith('{') and match.endswith('}'):
|
|
||||||
group_content = match[1:-1]
|
|
||||||
packages = [pkg.strip() for pkg in group_content.split(',')]
|
|
||||||
base_packages.extend(packages)
|
|
||||||
else:
|
|
||||||
base_packages.append(match)
|
|
||||||
|
|
||||||
return sorted(list(set(pkg for pkg in base_packages if pkg))) or None
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _parse_repo_error_from_script(self):
|
|
||||||
"""
|
|
||||||
Парсит скрипт dependencies.sh для извлечения сообщения об ошибке репозитория.
|
|
||||||
Возвращает сообщение или None в случае ошибки.
|
|
||||||
"""
|
|
||||||
if not os.path.exists(self.dependencies_script_path):
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(self.dependencies_script_path, 'r', encoding='utf-8') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
content = content.replace('\\\n', ' ')
|
|
||||||
match = re.search(r'apt-repo.*\|\|.*fatal\s+"([^"]+)"', content)
|
|
||||||
if match:
|
|
||||||
error_message = match.group(1).strip()
|
|
||||||
return re.sub(r'\s+', ' ', error_message)
|
|
||||||
return None
|
|
||||||
except Exception:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _show_startup_messages(self):
|
|
||||||
"""
|
|
||||||
Проверяет, является ли это первым запуском или обновлением,
|
|
||||||
и показывает соответствующие сообщения.
|
|
||||||
"""
|
|
||||||
current_hash = self._calculate_file_hash()
|
|
||||||
stored_hash = None
|
|
||||||
hash_file_exists = os.path.exists(self.hash_flag_file)
|
|
||||||
|
|
||||||
if hash_file_exists:
|
|
||||||
try:
|
|
||||||
with open(self.hash_flag_file, 'r', encoding='utf-8') as f:
|
|
||||||
stored_hash = f.read().strip()
|
|
||||||
except IOError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not hash_file_exists:
|
|
||||||
msg_box = QMessageBox(QMessageBox.Information, "Первый запуск WineHelper",
|
|
||||||
"Поскольку это первый запуск, программа проверит наличие необходимых системных зависимостей.")
|
|
||||||
msg_box.setWindowIcon(self.app_icon)
|
|
||||||
msg_box.exec_()
|
|
||||||
elif current_hash != stored_hash:
|
|
||||||
msg_box = QMessageBox(QMessageBox.Information, "Обновление зависимостей",
|
|
||||||
"Обнаружены изменения в системных требованиях.\n\n"
|
|
||||||
"Программа выполнит проверку, чтобы убедиться, что все компоненты на месте.")
|
|
||||||
msg_box.setWindowIcon(self.app_icon)
|
|
||||||
msg_box.exec_()
|
|
||||||
|
|
||||||
def _save_dependency_hash(self):
|
|
||||||
"""Сохраняет хэш зависимостей в конфигурационный файл."""
|
|
||||||
current_hash = self._calculate_file_hash()
|
|
||||||
if not current_hash:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
with open(self.hash_flag_file, 'w', encoding='utf-8') as f:
|
|
||||||
f.write(current_hash)
|
|
||||||
except IOError:
|
|
||||||
print("Предупреждение: не удалось записать файл с хэшем зависимостей.")
|
|
||||||
|
|
||||||
def _perform_check_and_install(self):
|
|
||||||
"""
|
|
||||||
Выполняет основную логику проверки и установки зависимостей.
|
|
||||||
Возвращает True в случае успеха, иначе False.
|
|
||||||
"""
|
|
||||||
# Проверка наличия ключевых утилит
|
|
||||||
if not shutil.which('apt-repo') or not shutil.which('rpm'):
|
|
||||||
return True
|
|
||||||
|
|
||||||
if not self.dependencies_script_path or not os.path.exists(self.dependencies_script_path):
|
|
||||||
msg_box = QMessageBox(QMessageBox.Critical, "Критическая ошибка",
|
|
||||||
f"Файл зависимостей не найден по пути:\n'{self.dependencies_script_path}'.\n\n"
|
|
||||||
"Программа не может продолжить работу."
|
|
||||||
)
|
|
||||||
msg_box.setWindowIcon(self.app_icon)
|
|
||||||
msg_box.exec_()
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 1. Проверка наличия репозитория x86_64-i586
|
|
||||||
try:
|
|
||||||
result = subprocess.run(['apt-repo'], capture_output=True, text=True, check=False, encoding='utf-8')
|
|
||||||
if result.returncode != 0 or 'x86_64-i586' not in result.stdout:
|
|
||||||
error_message = self._parse_repo_error_from_script()
|
|
||||||
if not error_message:
|
|
||||||
msg_box = QMessageBox(QMessageBox.Critical, "Критическая ошибка",
|
|
||||||
f"Репозиторий x86_64-i586 не подключен, но не удалось извлечь текст ошибки из файла:\n'{self.dependencies_script_path}'.\n\n"
|
|
||||||
"Проверьте целостность скрипта. Работа программы будет прекращена."
|
|
||||||
)
|
|
||||||
msg_box.setWindowIcon(self.app_icon)
|
|
||||||
msg_box.exec_()
|
|
||||||
return False
|
|
||||||
|
|
||||||
msg_box = QMessageBox(QMessageBox.Critical, "Ошибка репозитория",
|
|
||||||
f"{error_message}\n\nРабота программы будет прекращена.")
|
|
||||||
msg_box.setWindowIcon(self.app_icon)
|
|
||||||
msg_box.exec_()
|
|
||||||
return False
|
|
||||||
except FileNotFoundError:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# 2. Определение списка пакетов из dependencies.sh
|
|
||||||
base_packages = self._parse_dependencies_from_script()
|
|
||||||
|
|
||||||
# Если парсинг не удался или скрипт не найден, прерываем работу.
|
|
||||||
if not base_packages:
|
|
||||||
msg_box = QMessageBox(QMessageBox.Critical, "Критическая ошибка",
|
|
||||||
f"Не удалось найти или проанализировать файл зависимостей:\n'{self.dependencies_script_path}'.\n\n"
|
|
||||||
"Программа не может продолжить работу без списка необходимых пакетов."
|
|
||||||
)
|
|
||||||
msg_box.setWindowIcon(self.app_icon)
|
|
||||||
msg_box.exec_()
|
|
||||||
return False
|
|
||||||
|
|
||||||
required_packages = [f"i586-{pkg}" for pkg in base_packages] + base_packages
|
|
||||||
|
|
||||||
# 3. Проверка, какие пакеты отсутствуют
|
|
||||||
try:
|
|
||||||
# Запрашиваем список всех установленных пакетов один раз для эффективности
|
|
||||||
result = subprocess.run(
|
|
||||||
['rpm', '-qa', '--queryformat', '%{NAME}\n'],
|
|
||||||
capture_output=True, text=True, check=True, encoding='utf-8'
|
|
||||||
)
|
|
||||||
installed_packages_set = set(result.stdout.splitlines())
|
|
||||||
required_packages_set = set(required_packages)
|
|
||||||
|
|
||||||
# Находим разницу между требуемыми и установленными пакетами
|
|
||||||
missing_packages = sorted(list(required_packages_set - installed_packages_set))
|
|
||||||
|
|
||||||
except (subprocess.CalledProcessError, FileNotFoundError) as e:
|
|
||||||
# В случае ошибки (например, rpm не найден), показываем критическое сообщение
|
|
||||||
msg_box = QMessageBox(QMessageBox.Critical, "Критическая ошибка",
|
|
||||||
f"Не удалось получить список установленных пакетов с помощью rpm.\n\nОшибка: {e}\n\n"
|
|
||||||
"Программа не может проверить зависимости и будет закрыта."
|
|
||||||
)
|
|
||||||
msg_box.setWindowIcon(self.app_icon)
|
|
||||||
msg_box.exec_()
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not missing_packages:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# 4. Запрос у пользователя на установку
|
|
||||||
msg_box = QMessageBox()
|
|
||||||
msg_box.setWindowIcon(self.app_icon)
|
|
||||||
msg_box.setIcon(QMessageBox.Warning)
|
|
||||||
msg_box.setWindowTitle("Отсутствуют зависимости")
|
|
||||||
# Устанавливаем формат текста в RichText, чтобы QMessageBox корректно обрабатывал HTML-теги.
|
|
||||||
msg_box.setTextFormat(Qt.RichText)
|
|
||||||
|
|
||||||
# Формируем весь текст как единый HTML-блок для корректного отображения.
|
|
||||||
full_html_text = (
|
|
||||||
"Для корректной работы WineHelper требуются дополнительные системные компоненты.<br><br>"
|
|
||||||
"Отсутствуют следующие пакеты:<br>"
|
|
||||||
# Ограничиваем высоту блока с пакетами и добавляем прокрутку, если список длинный.
|
|
||||||
f"""<div style="font-family: monospace; max-height: 150px; overflow-y: auto; margin-top: 5px; margin-bottom: 10px;">
|
|
||||||
{'<br>'.join(sorted(missing_packages))}
|
|
||||||
</div>"""
|
|
||||||
"Нажмите <b>'Установить'</b>, чтобы запустить установку с правами администратора. "
|
|
||||||
"Вам потребуется ввести пароль. Этот процесс может занять некоторое время."
|
|
||||||
)
|
|
||||||
msg_box.setText(full_html_text)
|
|
||||||
install_button = msg_box.addButton("Установить", QMessageBox.AcceptRole)
|
|
||||||
cancel_button = msg_box.addButton("Отмена", QMessageBox.RejectRole)
|
|
||||||
msg_box.setDefaultButton(install_button)
|
|
||||||
|
|
||||||
msg_box.exec_()
|
|
||||||
|
|
||||||
if msg_box.clickedButton() != install_button:
|
|
||||||
cancel_box = QMessageBox(QMessageBox.Warning, "Отмена",
|
|
||||||
"Установка отменена.\n\n"
|
|
||||||
"WineHelper не может продолжить работу\nбез необходимых зависимостей.")
|
|
||||||
cancel_box.setWindowIcon(self.app_icon)
|
|
||||||
cancel_box.exec_()
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 5. Запуск установки с отображением лога в диалоговом окне
|
|
||||||
if not shutil.which('pkexec'):
|
|
||||||
error_box = QMessageBox(QMessageBox.Critical, "Ошибка",
|
|
||||||
"Не найден компонент 'pkexec' для повышения прав.\n"
|
|
||||||
"Пожалуйста, установите пакет 'polkit-pkexec', "
|
|
||||||
f"а затем установите зависимости вручную:\n\n sudo apt-get install {' '.join(missing_packages)}"
|
|
||||||
)
|
|
||||||
error_box.setWindowIcon(self.app_icon)
|
|
||||||
error_box.exec_()
|
|
||||||
return False
|
|
||||||
|
|
||||||
install_cmd_str = f"apt-get update && apt-get install -y {' '.join(missing_packages)}"
|
|
||||||
|
|
||||||
# Этот флаг будет установлен в True, если установка и проверка пройдут успешно.
|
|
||||||
installation_successful = False
|
|
||||||
|
|
||||||
# Создаем диалог для вывода лога установки
|
|
||||||
dialog = QDialog()
|
|
||||||
dialog.setWindowIcon(self.app_icon)
|
|
||||||
dialog.setWindowTitle("Установка зависимостей")
|
|
||||||
dialog.setMinimumSize(680, 400)
|
|
||||||
dialog.setModal(True)
|
|
||||||
|
|
||||||
# Центрирование окна по центру экрана
|
|
||||||
screen_geometry = QApplication.primaryScreen().availableGeometry()
|
|
||||||
dialog.move(
|
|
||||||
(screen_geometry.width() - dialog.width()) // 2,
|
|
||||||
(screen_geometry.height() - dialog.height()) // 2
|
|
||||||
)
|
|
||||||
|
|
||||||
layout = QVBoxLayout(dialog)
|
|
||||||
log_output = QTextEdit()
|
|
||||||
log_output.setReadOnly(True)
|
|
||||||
log_output.setFont(QFont("DejaVu Sans Mono", 10))
|
|
||||||
layout.addWidget(log_output)
|
|
||||||
|
|
||||||
close_button = QPushButton("Закрыть")
|
|
||||||
close_button.setEnabled(False)
|
|
||||||
close_button.clicked.connect(dialog.accept)
|
|
||||||
layout.addWidget(close_button)
|
|
||||||
|
|
||||||
process = QProcess(dialog)
|
|
||||||
process.setProcessChannelMode(QProcess.MergedChannels)
|
|
||||||
|
|
||||||
def handle_output():
|
|
||||||
# Используем insertPlainText для корректного отображения потокового вывода (например, прогресс-баров)
|
|
||||||
log_output.insertPlainText(process.readAll().data().decode('utf-8', 'ignore'))
|
|
||||||
log_output.moveCursor(QTextCursor.End)
|
|
||||||
|
|
||||||
def handle_finish(exit_code, exit_status):
|
|
||||||
nonlocal installation_successful
|
|
||||||
log_output.moveCursor(QTextCursor.End)
|
|
||||||
if exit_code == 0 and exit_status == QProcess.NormalExit:
|
|
||||||
log_output.append("\n<b><font color='green'>=== Установка успешно завершена ===</font></b>")
|
|
||||||
log_output.ensureCursorVisible()
|
|
||||||
|
|
||||||
# Повторная проверка зависимостей сразу после установки
|
|
||||||
try:
|
|
||||||
result = subprocess.run(
|
|
||||||
['rpm', '-qa', '--queryformat', '%{NAME}\n'],
|
|
||||||
capture_output=True, text=True, check=True, encoding='utf-8'
|
|
||||||
)
|
|
||||||
installed_packages_set = set(result.stdout.splitlines())
|
|
||||||
missing_packages_set = set(missing_packages)
|
|
||||||
still_missing = sorted(list(missing_packages_set - installed_packages_set))
|
|
||||||
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
||||||
warn_box = QMessageBox(dialog)
|
|
||||||
warn_box.setWindowIcon(self.app_icon)
|
|
||||||
warn_box.setIcon(QMessageBox.Warning)
|
|
||||||
warn_box.setWindowTitle("Проверка не удалась")
|
|
||||||
warn_box.setText("Не удалось повторно проверить зависимости после установки.")
|
|
||||||
warn_box.exec_()
|
|
||||||
still_missing = missing_packages
|
|
||||||
|
|
||||||
if not still_missing:
|
|
||||||
installation_successful = True
|
|
||||||
close_button.setText("Запустить WineHelper")
|
|
||||||
else:
|
|
||||||
warn_box = QMessageBox(dialog)
|
|
||||||
warn_box.setWindowIcon(self.app_icon)
|
|
||||||
warn_box.setIcon(QMessageBox.Warning)
|
|
||||||
warn_box.setWindowTitle("Установка не завершена")
|
|
||||||
warn_box.setText(
|
|
||||||
"Не все зависимости были установлены. WineHelper может работать некорректно.\n\n"
|
|
||||||
f"Отсутствуют: {', '.join(sorted(still_missing))}\n\n"
|
|
||||||
"Попробуйте запустить установку снова или установите пакеты вручную."
|
|
||||||
)
|
|
||||||
warn_box.exec_()
|
|
||||||
else:
|
|
||||||
if exit_code == 127: # pkexec: пользователь отменил аутентификацию
|
|
||||||
log_output.append("\n<b><font color='orange'>=== УСТАНОВКА ОТМЕНЕНА ПОЛЬЗОВАТЕЛЕМ ===</font></b>")
|
|
||||||
log_output.append("Вы отменили ввод пароля. Установка зависимостей не была выполнена.")
|
|
||||||
elif exit_code == 126: # pkexec: у пользователя нет прав
|
|
||||||
log_output.append("\n<b><font color='red'>=== ОШИБКА: НЕДОСТАТОЧНО ПРАВ ===</font></b>")
|
|
||||||
log_output.append("У вашего пользователя нет прав для выполнения этой операции.")
|
|
||||||
else:
|
|
||||||
log_tag = "ПРЕРВАНО" if exit_status == QProcess.CrashExit else "ОШИБКА"
|
|
||||||
log_output.append(f"\n<b><font color='red'>=== {log_tag} (код: {exit_code}) ===</font></b>")
|
|
||||||
log_output.append("Произошла непредвиденная ошибка во время установки.")
|
|
||||||
log_output.ensureCursorVisible()
|
|
||||||
|
|
||||||
close_button.setEnabled(True)
|
|
||||||
|
|
||||||
def dialog_close_handler(event):
|
|
||||||
"""Обрабатывает закрытие окна во время установки зависимостей."""
|
|
||||||
if process.state() == QProcess.Running:
|
|
||||||
# QMessageBox без кнопок может некорректно обрабатывать закрытие.
|
|
||||||
# Используем простой QDialog для надежности.
|
|
||||||
info_dialog = QDialog(dialog)
|
|
||||||
info_dialog.setWindowTitle("Идет установка")
|
|
||||||
info_dialog.setModal(True)
|
|
||||||
info_dialog.setFixedSize(450, 150)
|
|
||||||
|
|
||||||
layout = QVBoxLayout(info_dialog)
|
|
||||||
label = QLabel(
|
|
||||||
"<h3>Установка зависимостей еще не завершена.</h3>"
|
|
||||||
"<p>Пожалуйста, дождитесь окончания процесса.</p>"
|
|
||||||
"<p>Закрыть основное окно можно будет после завершения установки.</p>"
|
|
||||||
)
|
|
||||||
label.setTextFormat(Qt.RichText)
|
|
||||||
label.setAlignment(Qt.AlignCenter)
|
|
||||||
layout.addWidget(label)
|
|
||||||
|
|
||||||
info_dialog.exec_()
|
|
||||||
event.ignore()
|
|
||||||
else:
|
|
||||||
event.accept()
|
|
||||||
|
|
||||||
process.readyRead.connect(handle_output)
|
|
||||||
process.finished.connect(handle_finish)
|
|
||||||
|
|
||||||
log_output.append(f"Выполнение команды:\npkexec sh -c \"{install_cmd_str}\"\n")
|
|
||||||
log_output.append("Пожалуйста, введите пароль в появившемся окне аутентификации...")
|
|
||||||
log_output.append("-" * 40 + "\n")
|
|
||||||
|
|
||||||
dialog.closeEvent = dialog_close_handler
|
|
||||||
process.start('pkexec', ['sh', '-c', install_cmd_str])
|
|
||||||
dialog.exec_()
|
|
||||||
|
|
||||||
return installation_successful
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
"""
|
|
||||||
Основной публичный метод для запуска полной проверки зависимостей.
|
|
||||||
Возвращает True, если все зависимости удовлетворены, иначе False.
|
|
||||||
"""
|
|
||||||
self._show_startup_messages()
|
|
||||||
if self._perform_check_and_install():
|
|
||||||
self._save_dependency_hash()
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
class WinetricksManagerDialog(QDialog):
|
class WinetricksManagerDialog(QDialog):
|
||||||
"""Диалог для управления компонентами Winetricks."""
|
"""Диалог для управления компонентами Winetricks."""
|
||||||
@@ -4335,6 +3948,8 @@ class WineHelperGUI(QMainWindow):
|
|||||||
QMessageBox.critical(self, "Ошибка", f"Не удалось модифицировать команду для отладки: {e}")
|
QMessageBox.critical(self, "Ошибка", f"Не удалось модифицировать команду для отладки: {e}")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
os.environ["WH_SKIP_DEPS"] = "1"
|
||||||
|
|
||||||
process = QProcess()
|
process = QProcess()
|
||||||
env = QProcessEnvironment.systemEnvironment()
|
env = QProcessEnvironment.systemEnvironment()
|
||||||
|
|
||||||
@@ -4367,6 +3982,7 @@ class WineHelperGUI(QMainWindow):
|
|||||||
self.running_apps[desktop_path] = process
|
self.running_apps[desktop_path] = process
|
||||||
self._set_run_button_state(True)
|
self._set_run_button_state(True)
|
||||||
print(f"Запущено: {program} {' '.join(arguments)}")
|
print(f"Запущено: {program} {' '.join(arguments)}")
|
||||||
|
os.environ["WH_SKIP_DEPS"] = "0"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
QMessageBox.critical(self, "Ошибка запуска",
|
QMessageBox.critical(self, "Ошибка запуска",
|
||||||
f"Не удалось запустить команду:\n{command_str}\n\nОшибка: {str(e)}")
|
f"Не удалось запустить команду:\n{command_str}\n\nОшибка: {str(e)}")
|
||||||
@@ -5201,8 +4817,6 @@ def main():
|
|||||||
# На всякий случай удаляем старый файл сокета, если он остался от сбоя.
|
# На всякий случай удаляем старый файл сокета, если он остался от сбоя.
|
||||||
QLocalServer.removeServer(socket_name)
|
QLocalServer.removeServer(socket_name)
|
||||||
|
|
||||||
dependency_manager = DependencyManager()
|
|
||||||
if dependency_manager.run():
|
|
||||||
window = WineHelperGUI()
|
window = WineHelperGUI()
|
||||||
|
|
||||||
# Создаем локальный сервер для приема "сигналов" от последующих запусков
|
# Создаем локальный сервер для приема "сигналов" от последующих запусков
|
||||||
@@ -5232,7 +4846,6 @@ def main():
|
|||||||
# window.create_tray_icon() # Временно отключено
|
# window.create_tray_icon() # Временно отключено
|
||||||
return app.exec_()
|
return app.exec_()
|
||||||
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
|||||||
Reference in New Issue
Block a user