Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f10e5aace | |||
| 683a1a876e | |||
| 9fb280271b | |||
| 12d8fb69e8 | |||
| 1cbb6d59be | |||
| 2170aa7959 | |||
| a7cf18bd28 | |||
| 38544a72f0 | |||
| efa2c65886 | |||
| 1e1f451d6c | |||
| ddbf0089b4 | |||
| 368bea581e | |||
|
|
cf60f70ba5 | ||
|
|
a1fe72e4b9 | ||
|
|
da347935b7 | ||
| 163923de8d | |||
| e90708e03d | |||
| ca939881e3 | |||
| fc8989db9f | |||
| b60f2cd0eb | |||
| 27eb980190 | |||
| 8a7010529d | |||
| 640c9f77a0 | |||
| ed39b338c9 | |||
| 51635cf2c0 | |||
| b2e15d12ac | |||
| dc998a4fa0 | |||
| 66963e6f26 | |||
| c8ccc1dff5 | |||
| 08dbe1cb80 | |||
| 01a3307626 | |||
| f6698e2f39 | |||
| 9c0e2d11b3 | |||
| bcebe543cc | |||
| 9fdc3a998c | |||
| fb0ff07ad6 | |||
| a5352c6942 | |||
| e724d19663 | |||
| e78fb2b4a4 | |||
| d330c83691 | |||
| de0a9b13f1 | |||
| 9cc549527d | |||
| 43e473ad39 | |||
| d78916f4b0 | |||
| bf370e9a91 | |||
| 84f71c2043 | |||
| e5231d7846 | |||
| b653bcbb80 | |||
| ad9deaed81 | |||
| 1b9e106d2a | |||
| c51cf18f4c | |||
| 4217f58c2c |
3
ChangePassword.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
echo -e "123456\n123456\n\n\n\n\n\n\n\n\n" | adduser "$1"
|
||||
echo -e "123456\n123456\n" | passwd root
|
||||
5
Download.py
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import base64
|
||||
import requests
|
||||
print(requests.get(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9JbnN0YWxsLnBocD9WZXJzaW9uPQ==").decode("utf-8") + sys.argv[1]).text)
|
||||
BIN
GetEXEVersion.exe
Executable file
BIN
Icon/Function/CHROOT.png
Executable file
|
After Width: | Height: | Size: 22 KiB |
BIN
Icon/Function/more-wine.png
Executable file
|
After Width: | Height: | Size: 62 KiB |
BIN
Icon/Function/wine.png
Executable file
|
After Width: | Height: | Size: 67 KiB |
BIN
Icon/Function/wine23A.png
Executable file
|
After Width: | Height: | Size: 75 KiB |
BIN
Icon/Function/wine23P.png
Executable file
|
After Width: | Height: | Size: 75 KiB |
BIN
Icon/Program/Windows虚拟机.png
Executable file
|
After Width: | Height: | Size: 63 KiB |
BIN
Icon/Program/webp2.png
Executable file
|
After Width: | Height: | Size: 84 KiB |
BIN
Icon/Program/webp3.png
Executable file
|
After Width: | Height: | Size: 85 KiB |
BIN
Icon/Program/wine打包器.png
Executable file
|
After Width: | Height: | Size: 67 KiB |
BIN
Icon/Program/wine运行器.png
Executable file
|
After Width: | Height: | Size: 68 KiB |
BIN
Icon/Screen/202211121646232464_image.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
29
IconList.json
Executable file
@@ -0,0 +1,29 @@
|
||||
[
|
||||
[
|
||||
["QQ", "wineBottonPath/drive_c/Program Files/Tencent/QQ/Bin/QQ.exe"],
|
||||
["QQ", "wineBottonPath/drive_c/Program Files (x86)/Tencent/QQ/Bin/QQ.exe"],
|
||||
["TIM", "wineBottonPath/drive_c/Program Files/Tencent/TIM/Bin/TIM.exe"],
|
||||
["TIM", "wineBottonPath/drive_c/Program Files (x86)/Tencent/TIM/Bin/TIM.exe"]
|
||||
],
|
||||
[
|
||||
["cmd", "cmd"],
|
||||
["cmd", "cmd.exe"],
|
||||
["cmd", "wineBottonPath/drive_c/windows/system32/cmd.exe"],
|
||||
["Internet Explorer", "iexplore"],
|
||||
["Internet Explorer", "iexplore.exe"],
|
||||
["Internet Explorer", "wineBottonPath/drive_c/Program Files/Internet Explorer/iexplore.exe"],
|
||||
["Internet Explorer", "wineBottonPath/drive_c/Program Files (x86)/Internet Explorer/iexplore.exe"],
|
||||
["微信", "wineBottonPath/drive_c/Program Files/Tencent/WeChat/WeChat.exe"],
|
||||
["微信", "wineBottonPath/drive_c/Program Files (x86)/Tencent/WeChat/WeChat.exe"],
|
||||
["UltraISO", "wineBottonPath/drive_c/Program Files/UltraISO/UltraISO.exe"],
|
||||
["UltraISO", "wineBottonPath/drive_c/Program Files (x86)/UltraISO/UltraISO.exe"],
|
||||
["迅雷", "wineBottonPath/drive_c/Program Files/Thunder Network/MiniThunder/Bin/ThunderMini.exe"],
|
||||
["迅雷", "wineBottonPath/drive_c/Program Files (x86)/Thunder Network/MiniThunder/Bin/ThunderMini.exe"],
|
||||
["Microsoft Office Word", "wineBottonPath/drive_c/Program Files/Microsoft Office/Office12/WINWORD.EXE"],
|
||||
["Microsoft Office Word", "wineBottonPath/drive_c/Program Files (x86)/Microsoft Office/Office12/WINWORD.EXE"],
|
||||
["腾讯会议", "wineBottonPath/drive_c/Program Files/Tencent/WeMeet/wemeetapp.exe"],
|
||||
["腾讯会议", "wineBottonPath/drive_c/Program Files (x86)/Tencent/WeMeet/wemeetapp.exe"],
|
||||
["腾讯课堂", "wineBottonPath/drive_c/Program Files/Tencent/EDU/bin/TXEDU.exe"],
|
||||
["腾讯课堂", "wineBottonPath/drive_c/Program Files (x86)/Tencent/EDU/bin/TXEDU.exe"]
|
||||
]
|
||||
]
|
||||
159
Makefile
@@ -3,78 +3,93 @@ build:
|
||||
#cd VM-source && make
|
||||
#cd wine && make
|
||||
cp -rv helperset deb/opt/apps/deepin-wine-runner/
|
||||
cp -rv VM-source/VirtualMachine VM
|
||||
cp -rv VM-source/deepin-wine-runner.svg VM
|
||||
cp -rv VM-source/api VM
|
||||
cp -rv VM-source/Windows7X64Auto.iso VM
|
||||
cp -rv VM-source/Windows7X86Auto.iso VM
|
||||
cp -rv VM-source/run.py VM
|
||||
cp -rv wine/ deb/opt/apps/deepin-wine-runner/
|
||||
cp -rv Test/ deb/opt/apps/deepin-wine-runner/
|
||||
cp -rv VM-source/VirtualMachine VM
|
||||
cp -rv VM-source/deepin-wine-runner.svg VM
|
||||
cp -rv VM-source/api VM
|
||||
cp -rv VM-source/Windows7X64Auto.iso VM
|
||||
cp -rv VM-source/Windows7X86Auto.iso VM
|
||||
cp -rv VM-source/run.py VM
|
||||
cp -rv wine/ deb/opt/apps/deepin-wine-runner/
|
||||
cp -rv Test/ deb/opt/apps/deepin-wine-runner/
|
||||
zip -v -q -r package-script.zip package-script
|
||||
cp -rv VM deb/opt/apps/deepin-wine-runner
|
||||
cp -rv AllInstall.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv kill.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallWineOnDeepin23Alpha.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv VM deb/opt/apps/deepin-wine-runner
|
||||
cp -rv Download.py deb/opt/apps/deepin-wine-runner/
|
||||
cp -rv AllInstall.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv ShellList deb/opt/apps/deepin-wine-runner
|
||||
cp -rv QemuDownload.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv QemuRun.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv kill.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallWineOnDeepin23Alpha.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv wrestool deb/opt/apps/deepin-wine-runner
|
||||
cp -rv Mount.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv UnMount.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv vkd3d-proton.7z deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-easy-packager.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv IconList.json deb/opt/apps/deepin-wine-runner
|
||||
cp -rv GetEXEVersion.exe deb/opt/apps/deepin-wine-runner
|
||||
cp -rv MountWithoutHome.sh deb/opt/apps/deepin-wine-runner
|
||||
echo "[]" > deb/opt/apps/deepin-wine-runner/wine/winelist.json
|
||||
rm -rfv deb/opt/apps/deepin-wine-runner/wine/winelist.json
|
||||
cp -rv req deb/opt/apps/deepin-wine-runner
|
||||
cp -rv BuildDesktop.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv RegShot deb/opt/apps/deepin-wine-runner
|
||||
cp -rv BeCyIconGrabber.exe deb/opt/apps/deepin-wine-runner
|
||||
cp -rv AutoShell deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-packager-with-script.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-packager.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-runner-update-bug deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-runner.svg deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-venturi-setter.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallVisualBasicRuntime.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv DisabledOpengl.reg deb/opt/apps/deepin-wine-runner
|
||||
cp -rv EnabledOpengl.reg deb/opt/apps/deepin-wine-runner
|
||||
cp -rv geek.exe deb/opt/apps/deepin-wine-runner
|
||||
cp -rv information.json deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallMono.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallMsxml.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallNetFramework.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallOther.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallVisualCPlusPlus.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv launch.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv LICENSE deb/opt/apps/deepin-wine-runner
|
||||
cp -rv mainwindow.py deb/opt/apps/deepin-wine-runner/deepin-wine-runner
|
||||
cp -rv package-script.zip deb/opt/apps/deepin-wine-runner
|
||||
cp -rv Run.bat deb/opt/apps/deepin-wine-runner
|
||||
cp -rv RunVM.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv "wine install" deb/opt/apps/deepin-wine-runner
|
||||
cp -rv 窗体透明度设置工具.exe deb/opt/apps/deepin-wine-runner
|
||||
cp -rv UpdateGeek.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv AppStore.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallWineOnDeepin23.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv dxvk.7z deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallFont.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv CheckDLL deb/opt/apps/deepin-wine-runner
|
||||
#cp -rv exagear.7z deb/opt/apps/deepin-wine-runner
|
||||
cp -rv dlls-arm.7z deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin.list deb/opt/apps/deepin-wine-runner
|
||||
cp -rv sparkstore.list deb/opt/apps/deepin-wine-runner
|
||||
cp -rv arm-package.7z deb/opt/apps/deepin-wine-runner
|
||||
#cp -rv exa.7z deb/opt/apps/deepin-wine-runner
|
||||
cp -rv clean-unuse-program.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallNewWineHQ.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv cleanbottle.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv StartVM.sh deb/opt/apps/deepin-wine-runner
|
||||
#cp -rv deepin-wine-runner-create-botton.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv Icon deb/opt/apps/deepin-wine-runner
|
||||
cp -rv ConfigLanguareRunner-help.json deb/opt/apps/deepin-wine-runner
|
||||
cp -rv gtkGetFileNameDlg deb/opt/apps/deepin-wine-runner
|
||||
cp -rv LANG/*.qm deb/opt/apps/deepin-wine-runner/LANG
|
||||
cp -rv InstallDll.py deb/opt/apps/deepin-wine-runner/LANG
|
||||
cp -rv ConfigLanguareRunner.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv AutoConfig.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv UI deb/opt/apps/deepin-wine-runner/
|
||||
cp -rv InstallDll.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv Model deb/opt/apps/deepin-wine-runner
|
||||
cp -rv API deb/opt/apps/deepin-wine-runner
|
||||
cp -rv key deb/opt/apps/deepin-wine-runner
|
||||
cp -rv req deb/opt/apps/deepin-wine-runner
|
||||
cp -rv BuildDesktop.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv ChangePassword.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv trans deb/opt/apps/deepin-wine-runner
|
||||
cp -rv RegShot deb/opt/apps/deepin-wine-runner
|
||||
cp -rv BeCyIconGrabber.exe deb/opt/apps/deepin-wine-runner
|
||||
cp -rv AutoShell deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-packager-with-script.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-packager.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-runner-update-bug deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-runner.svg deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin-wine-venturi-setter.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallVisualBasicRuntime.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv DisabledOpengl.reg deb/opt/apps/deepin-wine-runner
|
||||
cp -rv EnabledOpengl.reg deb/opt/apps/deepin-wine-runner
|
||||
cp -rv geek.exe deb/opt/apps/deepin-wine-runner
|
||||
cp -rv ProgramFen.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv information.json deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallMono.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallMsxml.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallNetFramework.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallOther.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallVisualCPlusPlus.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv launch.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv LICENSE deb/opt/apps/deepin-wine-runner
|
||||
cp -rv mainwindow.py deb/opt/apps/deepin-wine-runner/deepin-wine-runner
|
||||
cp -rv package-script.zip deb/opt/apps/deepin-wine-runner
|
||||
cp -rv Run.bat deb/opt/apps/deepin-wine-runner
|
||||
cp -rv RunVM.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv "wine install" deb/opt/apps/deepin-wine-runner
|
||||
cp -rv 窗体透明度设置工具.exe deb/opt/apps/deepin-wine-runner
|
||||
cp -rv UpdateGeek.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv AppStore.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallWineOnDeepin23.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv dxvk.7z deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallFont.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv CheckDLL deb/opt/apps/deepin-wine-runner
|
||||
#cp -rv exagear.7z deb/opt/apps/deepin-wine-runner
|
||||
cp -rv dlls-arm.7z deb/opt/apps/deepin-wine-runner
|
||||
cp -rv deepin.list deb/opt/apps/deepin-wine-runner
|
||||
cp -rv sparkstore.list deb/opt/apps/deepin-wine-runner
|
||||
cp -rv arm-package.7z deb/opt/apps/deepin-wine-runner
|
||||
#cp -rv exa.7z deb/opt/apps/deepin-wine-runner
|
||||
cp -rv clean-unuse-program.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv InstallNewWineHQ.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv cleanbottle.sh deb/opt/apps/deepin-wine-runner
|
||||
cp -rv StartVM.sh deb/opt/apps/deepin-wine-runner
|
||||
#cp -rv deepin-wine-runner-create-botton.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv Icon deb/opt/apps/deepin-wine-runner
|
||||
cp -rv ConfigLanguareRunner-help.json deb/opt/apps/deepin-wine-runner
|
||||
cp -rv gtkGetFileNameDlg deb/opt/apps/deepin-wine-runner
|
||||
cp -rv LANG/*.qm deb/opt/apps/deepin-wine-runner/LANG
|
||||
cp -rv InstallDll.py deb/opt/apps/deepin-wine-runner/LANG
|
||||
cp -rv ConfigLanguareRunner.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv AutoConfig.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv UI deb/opt/apps/deepin-wine-runner/
|
||||
cp -rv InstallDll.py deb/opt/apps/deepin-wine-runner
|
||||
cp -rv Model deb/opt/apps/deepin-wine-runner
|
||||
cp -rv API deb/opt/apps/deepin-wine-runner
|
||||
cp -rv key deb/opt/apps/deepin-wine-runner
|
||||
dpkg -b deb spark-deepin-wine-runner.deb
|
||||
|
||||
|
||||
@@ -87,11 +102,5 @@ install:
|
||||
remove:
|
||||
sudo apt purge spark-deepin-wine-runner
|
||||
|
||||
depend:
|
||||
sudo apt update
|
||||
sudo apt install python3 python3-pil python3-pil.imagetk\
|
||||
python3-pyquery deepin-terminal aria2 curl unrar unzip\
|
||||
python3-requests fakeroot bash python3-pyqt5
|
||||
|
||||
run:
|
||||
python3 mainwindow.py
|
||||
|
||||
BIN
Model/__pycache__/__init__.cpython-310.pyc
Executable file → Normal file
BIN
Model/__pycache__/__init__.cpython-36.pyc
Normal file
44
Mount.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
if [ ` whoami ` != "root" ]; then
|
||||
echo "Only root can run me"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$1" ]; then
|
||||
echo "路径不存在!"
|
||||
exit 1
|
||||
fi
|
||||
echo $0
|
||||
echo $1
|
||||
echo $2
|
||||
echo $3
|
||||
# 挂载必备目录
|
||||
cd "$1"
|
||||
# 拷贝 Qemu Static
|
||||
cp -r /usr/bin/qemu-*-static ./usr/bin
|
||||
# 挂载目录
|
||||
mount --bind /dev ./dev
|
||||
#mount --bind /dev/pts ./dev/pts
|
||||
mount -t proc /proc ./proc
|
||||
mount --bind /etc/resolv.conf ./etc/resolv.conf
|
||||
mount -t sysfs /sys ./sys
|
||||
#mount --bind /dev/shm ./dev/shm
|
||||
chmod 777 -R root
|
||||
xhost +
|
||||
# 挂载 Wine 运行器目录
|
||||
mount -o bind `dirname $0` ./opt/apps/deepin-wine-runner/
|
||||
# 挂载字体
|
||||
mount -o bind /usr/share/fonts ./usr/share/fonts
|
||||
# 配置用户
|
||||
if [ ! -d "home/$2" ]; then
|
||||
# 新建用户,且密码为 123456,以便读写
|
||||
chroot . bash /opt/apps/deepin-wine-runner/ChangePassword.sh "$2"
|
||||
fi
|
||||
# 挂载用户目录到 /root(默认 $HOME 路径)
|
||||
if [[ $2 == "root" ]]; then
|
||||
mount --bind root "$1/root/"
|
||||
else
|
||||
mount --bind "/home/$2" "$1/home/$2"
|
||||
fi
|
||||
|
||||
# 如果参数 3 存在
|
||||
chroot "--userspec=$2:$2" . env "HOME=/home/$2" ${@:3}
|
||||
29
MountWithoutHome.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
if [ ` whoami ` != "root" ]; then
|
||||
echo "Only root can run me"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$1" ]; then
|
||||
echo "路径不存在!"
|
||||
exit 1
|
||||
fi
|
||||
echo $0
|
||||
echo $1
|
||||
echo $2
|
||||
echo $3
|
||||
# 挂载必备目录
|
||||
cd "$1"
|
||||
# 拷贝 Qemu Static
|
||||
cp -r /usr/bin/qemu-*-static ./usr/bin
|
||||
# 挂载目录
|
||||
mount --bind /dev ./dev
|
||||
#mount --bind /dev/pts ./dev/pts
|
||||
mount -t proc /proc ./proc
|
||||
mount --bind /etc/resolv.conf ./etc/resolv.conf
|
||||
mount -t sysfs /sys ./sys
|
||||
#mount --bind /dev/shm ./dev/shm
|
||||
chmod 777 -R root
|
||||
xhost +
|
||||
|
||||
# 如果参数 3 存在
|
||||
chroot . ${@:3}
|
||||
122
ProgramFen.py
Executable file
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import base64
|
||||
import traceback
|
||||
import req as requests
|
||||
import PyQt5.QtGui as QtGui
|
||||
import PyQt5.QtCore as QtCore
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
|
||||
class ProgramRunStatusShow():
|
||||
msgWindow = None
|
||||
def ShowWindow():
|
||||
try:
|
||||
#fenlists = requests.get(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9iYXNoYXBwLw==").decode("utf-8") + fileName + base64.b64decode("L2FsbC5qc29u").decode("utf-8")).json()
|
||||
fenlists = []
|
||||
for i in range(6):
|
||||
fenlists.append(int(requests.get(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9GZW4=").decode("utf-8") + f"{i}/data.txt").text))
|
||||
tipsInfo = ""
|
||||
except:
|
||||
traceback.print_exc()
|
||||
fenlists = [0, 0, 0, 0, 0]
|
||||
tipsInfo = "暂时无人提交此脚本运行情况,是否立即提交?"
|
||||
|
||||
maxHead = fenlists.index(max(fenlists))
|
||||
allNumber = 0
|
||||
for i in fenlists:
|
||||
allNumber += i
|
||||
try:
|
||||
tipsInfo = ""
|
||||
for i in range(len(fenlists)):
|
||||
tipsInfo += f"有 {fenlists[i] / allNumber * 100}% 的用户选择了 {i} 分({fenlists[i]}/{allNumber})\n"
|
||||
maxNumber = max(fenlists) / allNumber * 100
|
||||
#if tipsInfo == "":
|
||||
# tipsInfo = f"有{maxNumber}%的用户选择了这个评分"
|
||||
except:
|
||||
pass
|
||||
ProgramRunStatusShow.msgWindow = QtWidgets.QMainWindow()
|
||||
msgWidget = QtWidgets.QWidget()
|
||||
msgWidgetLayout = QtWidgets.QGridLayout()
|
||||
starLayout = QtWidgets.QHBoxLayout()
|
||||
uploadButton = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "点此上传运行情况"))
|
||||
uploadButton.clicked.connect(ProgramRunStatusUpload.ShowWindow)
|
||||
msgWidgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "综合评价:")), 0, 0)
|
||||
msgWidgetLayout.addLayout(starLayout, 0, 1)
|
||||
msgWidgetLayout.addWidget(QtWidgets.QLabel(tipsInfo), 1, 0, 1, 2)
|
||||
msgWidgetLayout.addWidget(uploadButton, 3, 0, 1, 2)
|
||||
end = 5
|
||||
if maxHead > 5:
|
||||
for i in range(end):
|
||||
starLayout.addWidget(QtWidgets.QLabel(f"<img src='{programPath}/Icon/BadStar.svg' width=50>"))
|
||||
else:
|
||||
for i in range(maxHead):
|
||||
starLayout.addWidget(QtWidgets.QLabel(f"<img src='{programPath}/Icon/Star.svg' width=50>"))
|
||||
head = maxHead
|
||||
for i in range(head, end):
|
||||
starLayout.addWidget(QtWidgets.QLabel(f"<img src='{programPath}/Icon/UnStar.svg' width=50>"))
|
||||
msgWidget.setLayout(msgWidgetLayout)
|
||||
ProgramRunStatusShow.msgWindow.setCentralWidget(msgWidget)
|
||||
ProgramRunStatusShow.msgWindow.setWindowIcon(QtGui.QIcon(iconPath))
|
||||
ProgramRunStatusShow.msgWindow.setWindowTitle(f"程序运行情况")
|
||||
ProgramRunStatusShow.msgWindow.show()
|
||||
|
||||
class ProgramRunStatusUpload():
|
||||
msgWindow = None
|
||||
starLayout = None
|
||||
fen = None
|
||||
starList = []
|
||||
sha1Value = ""
|
||||
programName = None
|
||||
def ChangeStar():
|
||||
if ProgramRunStatusUpload.fen.currentIndex() > 5:
|
||||
for i in ProgramRunStatusUpload.starList:
|
||||
i.setText(f"<img src='{programPath}/Icon/BadStar.svg' width=25>")
|
||||
return
|
||||
for i in range(ProgramRunStatusUpload.fen.currentIndex()):
|
||||
ProgramRunStatusUpload.starList[i].setText(f"<img src='{programPath}/Icon/Star.svg' width=25>")
|
||||
head = ProgramRunStatusUpload.fen.currentIndex()
|
||||
end = len(ProgramRunStatusUpload.starList)
|
||||
for i in range(head, end):
|
||||
ProgramRunStatusUpload.starList[i].setText(f"<img src='{programPath}/Icon/UnStar.svg' width=25>")
|
||||
|
||||
def ShowWindow():
|
||||
ProgramRunStatusUpload.starList = []
|
||||
ProgramRunStatusUpload.msgWindow = QtWidgets.QMainWindow(ProgramRunStatusShow.msgWindow)
|
||||
msgWidget = QtWidgets.QWidget()
|
||||
msgWidgetLayout = QtWidgets.QGridLayout()
|
||||
ProgramRunStatusUpload.fen = QtWidgets.QComboBox()
|
||||
ProgramRunStatusUpload.starLayout = QtWidgets.QHBoxLayout()
|
||||
upload = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "上传"))
|
||||
upload.clicked.connect(ProgramRunStatusUpload.Upload)
|
||||
# 生成星星列表
|
||||
for i in [1, 1, 1, 1, 1]:
|
||||
ProgramRunStatusUpload.starList.append(QtWidgets.QLabel(f"<img src='{programPath}/Icon/{['Un', ''][i]}Star.svg' width=25>"))
|
||||
ProgramRunStatusUpload.starLayout.addWidget(ProgramRunStatusUpload.starList[-1])
|
||||
ProgramRunStatusUpload.starLayout.addItem(QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum))
|
||||
ProgramRunStatusUpload.fen.addItems(["0分", "1分", "2分", "3分", "4分", "5分"])
|
||||
ProgramRunStatusUpload.fen.setCurrentIndex(5)
|
||||
ProgramRunStatusUpload.fen.currentIndexChanged.connect(ProgramRunStatusUpload.ChangeStar)
|
||||
msgWidgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "评分:")), 1, 0)
|
||||
msgWidgetLayout.addWidget(ProgramRunStatusUpload.fen, 1, 1)
|
||||
msgWidgetLayout.addLayout(ProgramRunStatusUpload.starLayout, 2, 1)
|
||||
msgWidgetLayout.addWidget(upload, 3, 1)
|
||||
msgWidget.setLayout(msgWidgetLayout)
|
||||
ProgramRunStatusUpload.msgWindow.setCentralWidget(msgWidget)
|
||||
ProgramRunStatusUpload.msgWindow.setWindowTitle(QtCore.QCoreApplication.translate("U", "上传程序运行情况"))
|
||||
ProgramRunStatusUpload.msgWindow.setWindowIcon(QtGui.QIcon(iconPath))
|
||||
ProgramRunStatusUpload.msgWindow.show()
|
||||
|
||||
def Upload():
|
||||
try:
|
||||
QtWidgets.QMessageBox.information(ProgramRunStatusUpload.msgWindow, QtCore.QCoreApplication.translate("U", "提示"), requests.get(f"http://120.25.153.144/spark-deepin-wine-runner/Install.php?Version=Fen{ProgramRunStatusUpload.fen.currentIndex()}").json()["Error"])
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(ProgramRunStatusUpload.msgWindow, QtCore.QCoreApplication.translate("U", "错误"), QtCore.QCoreApplication.translate("U", "数据上传失败!"))
|
||||
|
||||
if __name__ == "__main__":
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
iconPath = "{}/deepin-wine-runner.svg".format(programPath)
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
ProgramRunStatusShow.ShowWindow()
|
||||
app.exec_()
|
||||
438
QemuDownload.py
Executable file
@@ -0,0 +1,438 @@
|
||||
#!/usr/bin/env python3
|
||||
# 本来是用C++写的,但在非deepin/UOS编译/运行就是下载不了https文件,只能用python重写
|
||||
#########################################################################
|
||||
# 作者:gfdgd xi、为什么您不喜欢熊出没和阿布
|
||||
# 版本:2.4.0
|
||||
# 感谢:感谢 deepin-wine 团队,提供了 deepin-wine 给大家使用,让我能做这个程序
|
||||
# 基于 Python3 的 PyQt5 构建
|
||||
#########################################################################
|
||||
#################
|
||||
# 引入所需的库
|
||||
#################
|
||||
import os
|
||||
import shutil
|
||||
import random
|
||||
import sys
|
||||
import json
|
||||
import traceback
|
||||
import requests
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
sys.path.append(f"{programPath}/../")
|
||||
from Model import *
|
||||
from trans import *
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
# UI 布局(自动生成)
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(693, 404)
|
||||
if not get_now_lang() == "zh_CN.UTF-8":
|
||||
transla = Trans("en_US", f"{programPath}/trans/deepin-wine-runner-qemu-download.json")
|
||||
else:
|
||||
transla = Trans("zh_CN")
|
||||
_translate = transla.transe
|
||||
self.centralWidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralWidget.setObjectName("centralWidget")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralWidget)
|
||||
self.verticalLayout_2.setContentsMargins(11, 11, 11, 11)
|
||||
self.verticalLayout_2.setSpacing(6)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setSpacing(6)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.localWineList = QtWidgets.QListView(self.centralWidget)
|
||||
self.localWineList.setObjectName("localWineList")
|
||||
self.horizontalLayout_2.addWidget(self.localWineList)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout.setSpacing(6)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.verticalLayout_2.addWidget(QtWidgets.QLabel(_translate("U", """使用前须知:
|
||||
1、Qemu 跨架构效率较低,如果有条件建议优先使用 box86、exagear 等效率较高的转换层;
|
||||
2、使用此方案需要使用到 Root 权限(需开启管理员模式)并安装 qemu-user-static;
|
||||
3、chroot 时候可能会出现问题导致程序闪退或异常,出现该问题重启电脑即可;
|
||||
4、在此环境使用 Wine 时,只能读取到您用户目录或本程序文件夹下的文件,其它路径无法读取;
|
||||
5、移除容器时请保证在这次打开电脑时没有调用过需要删除容器,如果有调用过建议重启电脑后再移除;
|
||||
6、暂时属于测试功能;""")))
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem)
|
||||
self.addButton = QtWidgets.QPushButton(self.centralWidget)
|
||||
self.addButton.setObjectName("addButton")
|
||||
self.verticalLayout.addWidget(self.addButton)
|
||||
self.delButton = QtWidgets.QPushButton(self.centralWidget)
|
||||
self.delButton.setObjectName("delButton")
|
||||
self.verticalLayout.addWidget(self.delButton)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem1)
|
||||
self.horizontalLayout_2.addLayout(self.verticalLayout)
|
||||
self.internetWineList = QtWidgets.QListView(self.centralWidget)
|
||||
self.internetWineList.setObjectName("internetWineList")
|
||||
self.horizontalLayout_2.addWidget(self.internetWineList)
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout_2)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setSpacing(6)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
#self.unzip = QtWidgets.QCheckBox(self.centralWidget)
|
||||
#self.unzip.setObjectName("unzip")
|
||||
#self.horizontalLayout.addWidget(self.unzip)
|
||||
#self.deleteZip = QtWidgets.QCheckBox(self.centralWidget)
|
||||
#self.deleteZip.setChecked(True)
|
||||
#self.deleteZip.setTristate(False)
|
||||
#self.deleteZip.setObjectName("deleteZip")
|
||||
#self.horizontalLayout.addWidget(self.deleteZip)
|
||||
#self.addOtherWine = QtWidgets.QPushButton(self.centralWidget)
|
||||
#self.horizontalLayout.addWidget(self.addOtherWine)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem2)
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
||||
MainWindow.setCentralWidget(self.centralWidget)
|
||||
# 菜单栏
|
||||
#_translate = QtCore.QCoreApplication.translate
|
||||
|
||||
self.menu = MainWindow.menuBar()
|
||||
self.changeSources = self.menu.addMenu(_translate("MainWindow", "更换源"))
|
||||
self.gitlinkAction = QtWidgets.QAction(_translate("MainWindow", "Gitlink 源(推荐)"))
|
||||
self.ipv6Action = QtWidgets.QAction(_translate("MainWindow", "备用源(只支持 IPv6 用户)"))
|
||||
self.localAction = QtWidgets.QAction(_translate("MainWindow", "本地测试源(127.0.0.1)"))
|
||||
self.changeSources.addAction(self.gitlinkAction)
|
||||
self.changeSources.addAction(self.ipv6Action)
|
||||
self.changeSources.addAction(self.localAction)
|
||||
for i in [self.gitlinkAction, self.ipv6Action, self.localAction]:
|
||||
i.setCheckable(True)
|
||||
self.gitlinkAction.setChecked(True)
|
||||
self.changeSourcesGroup = QtWidgets.QActionGroup(MainWindow)
|
||||
self.changeSourcesGroup.addAction(self.gitlinkAction)
|
||||
self.changeSourcesGroup.addAction(self.ipv6Action)
|
||||
self.changeSourcesGroup.addAction(self.localAction)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "下载 Qemu 镜像"))
|
||||
self.addButton.setText(_translate("MainWindow", "<<"))
|
||||
self.delButton.setText(_translate("MainWindow", ">>"))
|
||||
#self.unzip.setText(_translate("MainWindow", "不解压Wine资源文件"))
|
||||
#self.deleteZip.setText(_translate("MainWindow", "删除下载的资源包,只解压保留(两个选项都选相互抵消)"))
|
||||
#self.addOtherWine.setText(_translate("MainWindow", "导入自己的Wine"))
|
||||
|
||||
def ReadLocalInformation():
|
||||
try:
|
||||
global localJsonList
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "r")
|
||||
localJsonList = json.loads(file.read())
|
||||
nmodel = QtGui.QStandardItemModel(window)
|
||||
for i in localJsonList:
|
||||
item = QtGui.QStandardItem(i)
|
||||
nmodel.appendRow(item)
|
||||
ui.localWineList.setModel(nmodel)
|
||||
file.close()
|
||||
except:
|
||||
print("新建空列表")
|
||||
try:
|
||||
with open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "w") as file:
|
||||
file.write("[]")
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc())
|
||||
|
||||
def InstallOtherWine():
|
||||
path = QtWidgets.QFileDialog.getOpenFileName(window, "选择 Wine", os.getenv("~"), "wine(wine);;wine64(wine64);;全部文件(*.*)")
|
||||
if path[0] == "" or not path[1]:
|
||||
return
|
||||
try:
|
||||
# 写入配置文件
|
||||
rfile = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/winelist.json", "r")
|
||||
list = json.loads(rfile.read())
|
||||
rfile.close()
|
||||
# 创建映射
|
||||
name = os.path.basename(os.path.dirname(os.path.dirname(path[0])))
|
||||
if name == "" or name == None:
|
||||
name = f"useradd-wine-{random.randint(0, 99999)}"
|
||||
#binPath = os.path.dirname(os.path.dirname(path[0]))
|
||||
os.makedirs(f"{programPath}/{name}/bin")
|
||||
if os.system(f"ln -s '{path[0]}' '{programPath}/{name}/bin/wine'") != 0:
|
||||
QtWidgets.QMessageBox.critical(window, "新建wine映射失败")
|
||||
# C++ 版注释:不直接用 readwrite 是因为不能覆盖写入
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "w")
|
||||
list.append(name)
|
||||
file.write(json.dumps(list))
|
||||
file.close()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc())
|
||||
ReadLocalInformation()
|
||||
|
||||
def ChangeSources():
|
||||
global urlSources
|
||||
global internetWineSource
|
||||
sources = [ui.gitlinkAction, ui.ipv6Action, ui.localAction]
|
||||
for i in range(0, len(sources)):
|
||||
if sources[i].isChecked():
|
||||
urlSources = internetWineSourceList[i]
|
||||
internetWineSource = internetWineSourceList[i]
|
||||
# 读取信息
|
||||
ReadLocalInformation()
|
||||
ReadInternetInformation()
|
||||
break
|
||||
print(urlSources)
|
||||
|
||||
# 下面内容均翻译自 C++ 版本
|
||||
def ReadInternetInformation():
|
||||
global internetJsonList
|
||||
# C++ 版本是用 curl 的,考虑到 Python 用 requests 反而方便,于是不用 curl
|
||||
try:
|
||||
internetJsonList = json.loads(requests.get(f"{internetWineSource}/lists.json").text)
|
||||
internetJsonListNew = []
|
||||
for k in internetJsonList:
|
||||
archList = json.loads(requests.get(f"{internetWineSource}/{k}/lists.json").text)
|
||||
for e in archList:
|
||||
internetJsonListNew.append([e[0], e[1], k])
|
||||
internetJsonList = internetJsonListNew
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", "无法连接服务器!")
|
||||
return
|
||||
print(internetJsonList)
|
||||
nmodel = QtGui.QStandardItemModel(window)
|
||||
for i in internetJsonList:
|
||||
item = QtGui.QStandardItem(i[0])
|
||||
nmodel.appendRow(item)
|
||||
ui.internetWineList.setModel(nmodel)
|
||||
|
||||
class DownloadThread(QtCore.QThread):
|
||||
MessageBoxInfo = QtCore.pyqtSignal(str)
|
||||
MessageBoxError = QtCore.pyqtSignal(str)
|
||||
ChangeDialog = QtCore.pyqtSignal(QtWidgets.QProgressDialog, int, int, int)
|
||||
Finish = QtCore.pyqtSignal()
|
||||
def __init__(self, progressDialog: QtWidgets.QProgressDialog,
|
||||
url: str, savePath: str, fileName: str, view: QtWidgets.QListView, deleteZip: bool,
|
||||
unzip: bool, localList) -> None:
|
||||
self.dialog = progressDialog
|
||||
self.fileUrl = url
|
||||
self.fileSavePath = savePath
|
||||
self.fileSaveName = fileName
|
||||
self.localView = view
|
||||
self.downloadDeleteZip = deleteZip
|
||||
self.downloadUnzip = unzip
|
||||
self.localJsonList = localList
|
||||
super().__init__()
|
||||
|
||||
def ReadLocalInformation(self):
|
||||
global localJsonList
|
||||
try:
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "r")
|
||||
nmodel = QtGui.QStandardItemModel()
|
||||
localJsonList = json.loads(file.read())
|
||||
for i in localJsonList:
|
||||
nmodel.appendRow(QtGui.QStandardItem(i))
|
||||
self.localView.setModel(nmodel)
|
||||
file.close()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc())
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
# 创建文件夹
|
||||
dir = QtCore.QDir()
|
||||
#savePath = f"{programPath}/{self.fileSaveName}"
|
||||
choose = ui.internetWineList.currentIndex().row()
|
||||
arch = internetJsonList[choose][2]
|
||||
savePath = f"{homePath}/.deepin-wine-runner-ubuntu-images/{arch}/{self.fileSaveName}"
|
||||
if not os.path.exists(os.path.dirname(savePath)):
|
||||
os.makedirs(os.path.dirname(savePath))
|
||||
# 文件下载
|
||||
timeout = 0
|
||||
f = requests.get(self.fileUrl, stream=True)
|
||||
allSize = int(f.headers["content-length"]) # 文件总大小
|
||||
bytesRead = 0
|
||||
with open(savePath, "wb") as filePart:
|
||||
for chunk in f.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
#progressbar.update(int(part / show))
|
||||
filePart.write(chunk)
|
||||
bytesRead += 1024
|
||||
self.ChangeDialog.emit(self.dialog, bytesRead / allSize * 100, bytesRead / 1024 / 1024, allSize / 1024 / 1024)
|
||||
self.ChangeDialog.emit(self.dialog, 100, 100, 100)
|
||||
# 写入配置文件
|
||||
rfile = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "r")
|
||||
list = json.loads(rfile.read())
|
||||
rfile.close()
|
||||
# C++ 版注释:不直接用 readwrite 是因为不能覆盖写入
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "w")
|
||||
list.append(self.fileSaveName.replace(".tar.gz", ""))
|
||||
file.write(json.dumps(list))
|
||||
file.close()
|
||||
# 读取配置文件
|
||||
self.ReadLocalInformation()
|
||||
self.localJsonList = list
|
||||
# 解压文件
|
||||
shellCommand = ""
|
||||
path = f"{homePath}/.deepin-wine-runner-ubuntu-images/{arch}/{self.fileSaveName.replace('.tar.gz', '')}/"
|
||||
#path = f"{programPath}/{self.fileSaveName.replace('.7z', '')}"
|
||||
shellCommand += f"""#!/bin/bash
|
||||
mkdir -p \"{path}\"
|
||||
tar -xvf \"{savePath}\" -C \"{path}\"
|
||||
rm \"{savePath}\"
|
||||
"""
|
||||
#if self.downloadDeleteZip:
|
||||
# shellCommand += f"rm -rf \"{savePath}\"\n"
|
||||
shellFile = open("/tmp/depein-wine-runner-wine-install.sh", "w")
|
||||
shellFile.write(shellCommand)
|
||||
shellFile.close()
|
||||
process = QtCore.QProcess()
|
||||
command = ["deepin-terminal", "-e", "bash", "/tmp/depein-wine-runner-wine-install.sh"]
|
||||
process.start(f"{programPath}/../launch.sh", command)
|
||||
process.waitForFinished()
|
||||
OpenTerminal("bash /tmp/depein-wine-runner-wine-install.sh")
|
||||
self.Finish.emit()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.MessageBoxError.emit(traceback.format_exc())
|
||||
|
||||
def MessageBoxInfo(info):
|
||||
QtWidgets.QMessageBox.information(window, "提示", info)
|
||||
|
||||
def MessageBoxError(info):
|
||||
QtWidgets.QMessageBox.critical(window, "错误", info)
|
||||
|
||||
def ChangeDialog(dialog: QtWidgets.QProgressDialog, value, downloadBytes, totalBytes):
|
||||
dialog.setValue(value)
|
||||
dialog.setLabelText(f"{downloadBytes}MB/{totalBytes}MB")
|
||||
|
||||
def DownloadFinish():
|
||||
ui.centralWidget.setEnabled(True)
|
||||
|
||||
class QT:
|
||||
thread = None
|
||||
|
||||
def on_addButton_clicked():
|
||||
choose = ui.internetWineList.currentIndex().row()
|
||||
if choose < 0:
|
||||
QtWidgets.QMessageBox.information(window, "提示", "您未选中任何项,无法继续")
|
||||
return
|
||||
downloadName = internetJsonList[choose][1]
|
||||
ReadLocalInformation()
|
||||
for i in localJsonList:
|
||||
if i.replace(".tar.gz", "") == internetJsonList[choose][0]:
|
||||
QtWidgets.QMessageBox.information(window, "提示", "您已经安装了这个镜像了!无需重复安装!")
|
||||
return
|
||||
#if(ui.deleteZip.isChecked() + ui.unzip.isChecked() == 2):
|
||||
# ui.deleteZip.setChecked(False)
|
||||
# ui.unzip.setChecked(False)
|
||||
arch = internetJsonList[choose][2]
|
||||
downloadUrl = f"{internetWineSource}/{arch}/{downloadName}"
|
||||
dialog = QtWidgets.QProgressDialog()
|
||||
cancel = QtWidgets.QPushButton("取消")
|
||||
cancel.setDisabled(True)
|
||||
dialog.setWindowIcon(QtGui.QIcon(f"{programPath}/deepin-wine-runner.svg"))
|
||||
dialog.setCancelButton(cancel)
|
||||
dialog.setWindowTitle(f"正在下载“{internetJsonList[choose][0]}”")
|
||||
QT.thread = DownloadThread(
|
||||
dialog,
|
||||
downloadUrl,
|
||||
"",
|
||||
internetJsonList[choose][1],
|
||||
ui.localWineList,
|
||||
False,
|
||||
not True,
|
||||
localJsonList
|
||||
)
|
||||
QT.thread.MessageBoxInfo.connect(MessageBoxInfo)
|
||||
QT.thread.MessageBoxError.connect(MessageBoxError)
|
||||
QT.thread.ChangeDialog.connect(ChangeDialog)
|
||||
QT.thread.Finish.connect(DownloadFinish)
|
||||
ui.centralWidget.setDisabled(True)
|
||||
QT.thread.start()
|
||||
|
||||
def on_delButton_clicked():
|
||||
if os.path.exists("/tmp/deepin-wine-runner-qemu-lock"):
|
||||
if QtWidgets.QMessageBox.question(window, "提示", "检测到您的电脑已经运行了 Qemu/Chroot 容器,建议您重启电脑后再删除该容器,否则容易造成数据损失!\n是否取消操作?") == QtWidgets.QMessageBox.Yes:
|
||||
return
|
||||
if QtWidgets.QMessageBox.question(window, "提示", "你确定要删除吗?") == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
if ui.localWineList.currentIndex().row() < 0:
|
||||
QtWidgets.QMessageBox.information(window, "提示", "您未选择任何项")
|
||||
return
|
||||
try:
|
||||
# {localJsonList[ui.localWineList.currentIndex().row()]}
|
||||
path = f"{homePath}/.deepin-wine-runner-ubuntu-images/"
|
||||
changed = False
|
||||
for i in os.listdir(path):
|
||||
if os.path.exists(f"{path}/{i}/{localJsonList[ui.localWineList.currentIndex().row()]}"):
|
||||
changed = True
|
||||
name = f"{path}/{i}/{localJsonList[ui.localWineList.currentIndex().row()]}".replace(".tar.gz", "")
|
||||
if not changed:
|
||||
name = f"{path}/i386/{localJsonList[ui.localWineList.currentIndex().row()]}".replace(".tar.gz", "")
|
||||
print(name)
|
||||
# 必须取消挂载目录才行
|
||||
os.system(f"bash '{programPath}/UnMount.sh' '{name}'")
|
||||
#name = f"{homePath}/.deepin-wine-runner-ubuntu-images/{localJsonList[ui.localWineList.currentIndex().row()]}"
|
||||
dir = QtCore.QDir(name)
|
||||
dir.removeRecursively()
|
||||
QtCore.QFile.remove(name + ".tar.gz")
|
||||
del localJsonList[ui.localWineList.currentIndex().row()]
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "w")
|
||||
file.write(json.dumps(localJsonList))
|
||||
file.close()
|
||||
ReadLocalInformation()
|
||||
QtWidgets.QMessageBox.information(window, "提示", "删除成功!")
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc())
|
||||
|
||||
# 获取当前语言
|
||||
def get_now_lang()->"获取当前语言":
|
||||
return os.getenv('LANG')
|
||||
|
||||
if __name__ == "__main__":
|
||||
homePath = os.getenv("HOME")
|
||||
localJsonList = []
|
||||
internetJsonList = []
|
||||
internetWineSourceList = [
|
||||
"https://code.gitlink.org.cn/gfdgd_xi/deepin-wine-runner-ubuntu-image/raw/branch/master/Sandbox",
|
||||
"http://gfdgdxi.msns.cn/deepin-wine-runner-ubuntu-image/Sandbox", # 备用源,纯 IPv6 源
|
||||
"http://127.0.0.1/deepin-wine-runner-ubuntu-image/Sandbox/" # 本地测试源
|
||||
]
|
||||
internetWineSource = internetWineSourceList[0]
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
if os.system("which qemu-i386-static"):
|
||||
if QtWidgets.QMessageBox.question(None, "提示", "检测到您未安装 qemu-user-static,是否安装?") == QtWidgets.QMessageBox.Yes:
|
||||
OpenTerminal(f"pkexec bash '{programPath}/ShellList/InstallQemuUserStatic.sh'")
|
||||
exit()
|
||||
try:
|
||||
if not os.path.exists(f"{homePath}/.deepin-wine-runner-ubuntu-images/"):
|
||||
os.makedirs(f"{homePath}/.deepin-wine-runner-ubuntu-images/")
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(None, "错误", traceback.format_exc())
|
||||
exit()
|
||||
# 读取翻译
|
||||
if not get_now_lang() == "zh_CN.UTF-8":
|
||||
trans = QtCore.QTranslator()
|
||||
trans.load(f"{programPath}/../LANG/installwine-en_US.qm")
|
||||
app.installTranslator(trans)
|
||||
# 窗口构建
|
||||
window = QtWidgets.QMainWindow()
|
||||
ui = Ui_MainWindow()
|
||||
window.setWindowIcon(QtGui.QIcon(f"{programPath}/deepin-wine-runner.svg"))
|
||||
ui.setupUi(window)
|
||||
window.show()
|
||||
# 连接信号
|
||||
ui.addButton.clicked.connect(on_addButton_clicked)
|
||||
ui.delButton.clicked.connect(on_delButton_clicked)
|
||||
#ui.addOtherWine.clicked.connect(InstallOtherWine)
|
||||
ui.changeSourcesGroup.triggered.connect(ChangeSources)
|
||||
## 加载内容
|
||||
# 设置列表双击不会编辑
|
||||
ui.localWineList.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
ui.internetWineList.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
# 读取信息
|
||||
ReadLocalInformation()
|
||||
ReadInternetInformation()
|
||||
# 图标
|
||||
ui.centralWidget.setWindowIcon(QtGui.QIcon(f"{programPath}/../deepin-wine-runner.svg"))
|
||||
|
||||
app.exec_()
|
||||
44
QemuRun.py
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import getpass
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
|
||||
if __name__ == "__main__":
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
homePath = os.getenv("HOME")
|
||||
if len(sys.argv) <= 1:
|
||||
print("参数不足")
|
||||
sys.exit(1)
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
# 判断是否已下载镜像
|
||||
if not os.path.exists(f"{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}"):
|
||||
QtWidgets.QMessageBox.information(None, "提示", "此镜像未下载解压,无法继续")
|
||||
exit()
|
||||
commandList = ""
|
||||
userName = getpass.getuser()
|
||||
for i in sys.argv[3:]:
|
||||
commandList += f"'{i}' "
|
||||
if commandList.replace(" ", "") == "":
|
||||
commandList = "bash"
|
||||
# 需要先取消挂载其它目录以防止冲突
|
||||
path = f"{homePath}/.deepin-wine-runner-ubuntu-images"
|
||||
for i in os.listdir(path):
|
||||
archPath = f"{path}/{i}"
|
||||
if os.path.isdir(archPath):
|
||||
for k in os.listdir(archPath):
|
||||
bottlePath = f"{archPath}/{k}"
|
||||
if os.path.isdir(bottlePath):
|
||||
if f"{i}/{k}" == sys.argv[1]:
|
||||
continue
|
||||
if os.path.ismount(f"{bottlePath}/dev"):
|
||||
os.system(f"pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY bash '{programPath}/UnMount.sh' '{bottlePath}' ")
|
||||
os.system("touch /tmp/deepin-wine-runner-qemu-lock")
|
||||
# 判断是否挂载
|
||||
if not os.path.ismount(f"{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}/dev"):
|
||||
print("文件暂未挂载,开始挂载")
|
||||
if int(sys.argv[2]):
|
||||
sys.exit(os.system(f"pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY bash '{programPath}/MountWithoutHome.sh' '{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}' '{userName}' {commandList}"))
|
||||
else:
|
||||
sys.exit(os.system(f"pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY bash '{programPath}/Mount.sh' '{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}' '{userName}' {commandList}"))
|
||||
sys.exit(os.system(f"pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY chroot '--userspec={userName}:{userName}' '{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}/' env 'HOME=/home/{userName}' {commandList}"))
|
||||
38
README.md
@@ -1,5 +1,5 @@
|
||||
<p width=100px align="center"><img src="https://storage.deepin.org/thread/202208031419283599_deepin-wine-runner.png"></p>
|
||||
<h1 align="center">Wine 运行器 2.5.0</h1>
|
||||
<h1 align="center">Wine 运行器 3.0.0</h1>
|
||||
<hr>
|
||||
|
||||
## 介绍
|
||||
@@ -11,8 +11,7 @@ env WINEPREFIX=容器路径 wine(wine的路径) 可执行文件路径
|
||||
```
|
||||
让你可以简易方便的使用 wine
|
||||
是使用 Python3 的 PyQt5 构建的
|
||||
(自己美术功底太差,图标只能在网络上找了)
|
||||
(测试平台:deepin 20.7.1;UOS 家庭版 21.3.1;Ubuntu 22.04;Ubuntu 20.04;UOS 专业版 1050;openkylin)
|
||||
(测试平台:deepin 20.8;UOS 家庭版 21.3.1;Ubuntu 22.04;Ubuntu 20.04;UOS 专业版 1050;openkylin)
|
||||

|
||||
而打包器可以方便的把您的 wine 容器打包成 deb 包供他人使用,程序创建的 deb 构建临时文件夹目录树如下:
|
||||
```bash
|
||||
@@ -38,17 +37,16 @@ env WINEPREFIX=容器路径 wine(wine的路径) 可执行文件路径
|
||||
|
||||
11 directories, 6 files
|
||||
```
|
||||
](https://gitee.com/gfdgd-xi/deep-wine-runner/stargazers)
|
||||
最后感谢 [@鹤舞白沙](https://bbs.deepin.org/user/227203) 编写的《Wine运行器和Wine打包器傻瓜式使用教程(小白专用)》,链接:https://bbs.deepin.org/post/246837
|
||||
|
||||
## 软件架构
|
||||
i386、amd64 和 arm64,deepin-wine、deepin-wine5、wine、wine64、deepin-wine5-stable、deepin-wine6-stable、spark-wine7-devel、ukylin-wine 运行在哪就运行在哪
|
||||
理论上支持全架构,如果 Python 能运行的话
|
||||
非 X86 架构会利用到 `box86`、`exagear`等技术
|
||||
非 X86 架构会利用到 `box86`、`exagear`、`qemu` 等技术
|
||||
|
||||
## 分支介绍
|
||||
### main 分支
|
||||
主分支,稳定分支
|
||||
### Alpha 分支
|
||||
开发版分支,一般不稳定,有许多 bug
|
||||
|
||||
## 版本区分
|
||||
### 无特殊标识
|
||||
@@ -104,6 +102,32 @@ desktop文件中StartupWMClass字段。用于让桌面组件将窗口类名与de
|
||||

|
||||
|
||||
## 更新日志
|
||||
### 3.0.0(2022年12月10日)
|
||||
**※1、支持使用 Qemu + Chroot 跨运行 Wine 以及指定程序的功能;**
|
||||
**※2、提供了简易打包器以用于打包简易 deb;**
|
||||
**※3、支持下载配置过的 Qemu + Chroot 容器;**
|
||||
**※4、支持在隔离的 Chroot 容器内运行 Wine;**
|
||||
**※5、支持解压指定 deb 的内打包好的容器;**
|
||||
**※6、优化 Wine 列表显示;**
|
||||
**※7、新增程序论坛和教程入口;**
|
||||
**※8、程序公告功能;**
|
||||
**※9、新增程序评分功能;**
|
||||
**※10、新增解包 deb 内 Wine 容器功能;**
|
||||
**※11、新增 Vkd3d Proton 安装功能,更新 dxvk 版本至 2.0.0;**
|
||||
**※12、新增程序菜单栏部分栏目图标;**
|
||||
**※13、打包器支持按下 Shift + F1 查看指定选项提示;**
|
||||
14、优化非基于生态适配脚本的打包器内容自动填充功能;
|
||||
15、优化程序文案;
|
||||
16、新增日志翻译功能;
|
||||
17、程序进一步完善英语翻译(机翻);
|
||||
18、优化程序更新策略;
|
||||
19、优化日志分析功能;
|
||||
20、优化程序 UI。
|
||||

|
||||
|
||||
### 2.5.0.1(2022年11月25日)
|
||||
**※1、修复已知问题**
|
||||
|
||||
### 2.5.0(2022年11月25日)
|
||||
**※1、容器自动配置脚本 GUI 查看介绍使用 QWebEngineWidget,支持图片(非强制依赖,只做推荐);**
|
||||
**※2、不基于生态适配活动脚本打包器跟进 arm 架构 2022年11月11日的 Wine 微信打包方式;**
|
||||
|
||||
4
RunVM.sh
@@ -8,10 +8,10 @@
|
||||
# 基于 Python3 的 tkinter 构建
|
||||
###########################################################################################
|
||||
cd `dirname $0`
|
||||
which VBoxManage1
|
||||
which VBoxManage
|
||||
if test $? == 0 ; then
|
||||
VM/VirtualMachine
|
||||
exit
|
||||
fi
|
||||
zenity --info --no-wrap --text="未安装 VirtualBox,请自行安装 VirtualBox 并重新运行"
|
||||
#./launch.sh deepin-terminal -C "pkexec apt install virtualbox-6.1 -y && zenity --info --text=\"安装完毕,关闭此对话框和安装终端重新运行程序即可\" --no-wrap" --keep-open
|
||||
#./launch.sh deepin-terminal -C "pkexec apt install virtualbox-6.1 -y && zenity --info --text=\"安装完毕,关闭此对话框和安装终端重新运行程序即可\" --no-wrap" --keep-open
|
||||
|
||||
3
ShellList/InstallQemuUserStatic.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
echo 开始安装 qemu-user-static
|
||||
pkexec apt update
|
||||
pkexec apt install qemu-user-static -y
|
||||
BIN
UI/__pycache__/KeyAddGui.cpython-37.pyc
Executable file → Normal file
37
UnMount.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
if [ ` whoami ` != "root" ]; then
|
||||
echo "Only root can run me"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$1" ]; then
|
||||
echo "路径不存在!"
|
||||
exit 1
|
||||
fi
|
||||
echo $0
|
||||
echo $1
|
||||
echo $2
|
||||
#echo $3
|
||||
# 挂载必备目录
|
||||
cd "$1"
|
||||
umount ./dev
|
||||
umount ./dev/pts
|
||||
umount ./proc
|
||||
umount ./etc/resolv.conf
|
||||
umount ./sys
|
||||
umount ./dev/shm
|
||||
# 挂载 Wine 运行器目录
|
||||
umount ./opt
|
||||
umount ./opt/apps/deepin-wine-runner
|
||||
# 挂载字体
|
||||
umount ./usr/share/fonts
|
||||
# 挂载用户目录到 /root(默认 $HOME 路径)
|
||||
umount ./root
|
||||
for username in $(ls ./home)
|
||||
do
|
||||
echo ./home/$username
|
||||
umount ./home/$username
|
||||
# if [ -d ./home/$username/.deepinwine/$CONTAINER_NAME ]
|
||||
# then
|
||||
# rm -rf ./home/$username/.deepinwine/$CONTAINER_NAME
|
||||
# fi
|
||||
done
|
||||
BIN
Wine运行器和Wine打包器傻瓜式使用教程(小白专用)20221126-V2.pdf
Executable file
0
arm-package.7z
Normal file → Executable file
@@ -1,29 +1,36 @@
|
||||
Package: spark-deepin-wine-runner
|
||||
Version: 2.5.0
|
||||
Version: 3.0.0
|
||||
Maintainer: gfdgd xi <3025613752@qq.com>, 为什么您不喜欢熊出没和阿布呢
|
||||
Homepage: https://gitee.com/gfdgd-xi/deep-wine-runner, https://github.com/gfdgd-xi/deep-wine-runner, https://gitlink.org.cn/gfdgd_xi/deep-wine-runner
|
||||
Architecture: all
|
||||
Priority: optional
|
||||
Depends: python3, python3-pil, python3-pil.imagetk, python3-pyquery, aria2, curl, unrar, unzip, python3-requests, fakeroot, bash, python3-pyqt5, python3-psutil, deepin-terminal | mate-terminal | gnome-terminal | xfce4-terminal, python3-dbus, python3-pip
|
||||
Recommends: winbind, wimtools
|
||||
Depends: python3, python3-pil, python3-pil.imagetk, python3-pyquery, aria2, curl, unrar, unzip, python3-requests, fakeroot, bash, python3-pyqt5, python3-psutil, deepin-terminal | mate-terminal | gnome-terminal | xfce4-terminal, python3-dbus, python3-pip, p7zip-full, sudo
|
||||
Recommends: winbind, wimtools, python3-pyqt5.qtwebengine
|
||||
Section: utils
|
||||
Conflicts: spark.deepin-venturi-setter, spark-deepin-wine5-application-packer
|
||||
Replaces: spark.deepin-venturi-setter, spark-deepin-wine5-application-packer
|
||||
Installed-Size: 21844
|
||||
Conflicts: spark.deepin-venturi-setter, spark-deepin-wine5-application-packer, spark-deepin-wine-runner-52
|
||||
Replaces: spark.deepin-venturi-setter, spark-deepin-wine5-application-packer, spark-deepin-wine-runner-52
|
||||
Installed-Size: 25856
|
||||
Description: gfdgd xi、为什么您不喜欢熊出没和阿布呢 制作的 wine 运行器
|
||||
2.5.0 更新内容:
|
||||
※1、容器自动配置脚本 GUI 查看介绍使用 QWebEngineWidget,支持图片(非强制依赖,只做推荐);
|
||||
※2、不基于生态适配活动脚本打包器跟进 arm 架构 2022年11月11日的 Wine 微信打包方式;
|
||||
※3、支持多图标的程序打包;
|
||||
※4、修复了安装更多 Wine 换源换了个寂寞的问题;
|
||||
※5、修复安装更多 Wine 重新安装后列表丢失的问题;
|
||||
※6、新增了对 Deepin 23 Alpha 优化的 Wine 安装器;
|
||||
※7、新增 Dll 名称查询功能,可以查询对应 Dll 的作用;
|
||||
※8、支持静态获取可执行文件可以调用的 Dll 并提供解决方案;
|
||||
※9、支持移除指定的 .desktop 快捷方式;
|
||||
※10、新增日志分析功能以及导出、上传日志功能;
|
||||
11、修复了不基于生态适配活动脚本打包器在选择 arm 打包架构下容器自动删除脚本取消勾选无用的问题;
|
||||
12、优化文案、新增友链;
|
||||
13、提供了部分组件的测试功能。
|
||||
更新时间:2022年11月25日
|
||||
3.0.0 更新内容:
|
||||
※1、支持使用 Qemu + Chroot 跨运行 Wine 以及指定程序的功能;
|
||||
※2、提供了简易打包器以用于打包简易 deb;
|
||||
※3、支持下载配置过的 Qemu + Chroot 容器;
|
||||
※4、支持在隔离的 Chroot 容器内运行 Wine;
|
||||
※5、支持解压指定 deb 的内打包好的容器;
|
||||
※6、优化 Wine 列表显示;
|
||||
※7、新增程序论坛和教程入口;
|
||||
※8、程序公告功能;
|
||||
※9、新增程序评分功能;
|
||||
※10、新增解包 deb 内 Wine 容器功能;
|
||||
※11、新增 Vkd3d Proton 安装功能,更新 dxvk 版本至 2.0.0;
|
||||
※12、新增程序菜单栏部分栏目图标;
|
||||
※13、打包器支持按下 Shift + F1 查看指定选项提示;
|
||||
14、优化非基于生态适配脚本的打包器内容自动填充功能;
|
||||
15、优化程序文案;
|
||||
16、新增日志翻译功能;
|
||||
17、程序进一步完善英语翻译(机翻);
|
||||
18、优化程序更新策略;
|
||||
19、优化日志分析功能;
|
||||
20、优化程序 UI。
|
||||
更新时间:2022年12月09日
|
||||
作者:gfdgd xi、为什么您不喜欢熊出没和阿布呢
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# 使用系统默认的 sh 运行
|
||||
#################################################################################################################
|
||||
# 作者:gfdgd xi、为什么您不喜欢熊出没和阿布呢
|
||||
# 版本:2.3.0
|
||||
# 版本:2.6.0
|
||||
# 更新时间:2022年10月02日
|
||||
# 感谢:感谢 wine、deepin-wine 以及星火团队,提供了 wine、deepin-wine、spark-wine-devel 给大家使用,让我能做这个程序
|
||||
# 基于 sh
|
||||
@@ -10,6 +10,7 @@
|
||||
# 非强制性的必应组件,所以成功不成功都行
|
||||
echo 安装组件
|
||||
python3 -m pip install --upgrade pynput --trusted-host https://repo.huaweicloud.com -i https://repo.huaweicloud.com/repository/pypi/simple > /dev/null 2>&1 | true
|
||||
python3 -m pip install --upgrade xpinyin --trusted-host https://repo.huaweicloud.com -i https://repo.huaweicloud.com/repository/pypi/simple > /dev/null 2>&1 | true
|
||||
echo 执行完成
|
||||
echo 移除旧组件
|
||||
if [ -d /opt/apps/deepin-wine-runner/arm-package ]; then
|
||||
@@ -48,9 +49,13 @@ if [ `arch` != "x86_64" ]; then
|
||||
rm -rf /opt/apps/deepin-wine-runner/InstallNewWineHQ.sh
|
||||
fi
|
||||
# 到时候切换 gpg 源会方便很多
|
||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys FD6EEA1F20CD4B27 > /dev/null 2>&1 | true
|
||||
if [ -d /usr/share/deepin-installer ]; then
|
||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys FD6EEA1F20CD4B27 > /dev/null 2>&1 | true
|
||||
# 用于修复 2022.11.25 Better DDE 导致的 Deepin Community Live CD Install 版问题
|
||||
sh -c 'echo "deb [trusted=yes] https://proposed-packages.deepin.com/dde-apricot unstable main contrib non-free" > /etc/apt/sources.list.d/deepin-unstable.list'
|
||||
fi
|
||||
apt update > /dev/null 2>&1 | true
|
||||
# 设置目录权限,让用户可读可写,方便后续删除组件
|
||||
chmod 777 -R /opt/apps/deepin-wine-runner
|
||||
# 向服务器返回安装数加1(不显示内容且忽略错误)
|
||||
curl https://304626p927.goho.co/spark-deepin-wine-runner/Install.php?Version=2.5.0 -s > /dev/null 2>&1 | true
|
||||
python3 /opt/apps/deepin-wine-runner/Download.py 3.0.0 > /dev/null 2>&1 | true
|
||||
|
||||
3
deb/opt/apps/deepin-wine-runner/ChangePassword.sh
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
echo -e "123456\n123456\n\n\n\n\n\n\n\n\n" | adduser "$1"
|
||||
echo -e "123456\n123456\n" | passwd root
|
||||
5
deb/opt/apps/deepin-wine-runner/Download.py
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import base64
|
||||
import requests
|
||||
print(requests.get(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9JbnN0YWxsLnBocD9WZXJzaW9uPQ==").decode("utf-8") + sys.argv[1]).text)
|
||||
BIN
deb/opt/apps/deepin-wine-runner/GetEXEVersion.exe
Executable file
BIN
deb/opt/apps/deepin-wine-runner/Icon/Function/CHROOT.png
Executable file
|
After Width: | Height: | Size: 22 KiB |
BIN
deb/opt/apps/deepin-wine-runner/Icon/Function/more-wine.png
Executable file
|
After Width: | Height: | Size: 62 KiB |
BIN
deb/opt/apps/deepin-wine-runner/Icon/Function/wine.png
Executable file
|
After Width: | Height: | Size: 67 KiB |
BIN
deb/opt/apps/deepin-wine-runner/Icon/Function/wine23A.png
Executable file
|
After Width: | Height: | Size: 75 KiB |
BIN
deb/opt/apps/deepin-wine-runner/Icon/Function/wine23P.png
Executable file
|
After Width: | Height: | Size: 75 KiB |
BIN
deb/opt/apps/deepin-wine-runner/Icon/Program/Windows虚拟机.png
Executable file
|
After Width: | Height: | Size: 63 KiB |
BIN
deb/opt/apps/deepin-wine-runner/Icon/Program/webp2.png
Executable file
|
After Width: | Height: | Size: 84 KiB |
BIN
deb/opt/apps/deepin-wine-runner/Icon/Program/webp3.png
Executable file
|
After Width: | Height: | Size: 85 KiB |
BIN
deb/opt/apps/deepin-wine-runner/Icon/Program/wine打包器.png
Executable file
|
After Width: | Height: | Size: 67 KiB |
BIN
deb/opt/apps/deepin-wine-runner/Icon/Program/wine运行器.png
Executable file
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
29
deb/opt/apps/deepin-wine-runner/IconList.json
Executable file
@@ -0,0 +1,29 @@
|
||||
[
|
||||
[
|
||||
["QQ", "wineBottonPath/drive_c/Program Files/Tencent/QQ/Bin/QQ.exe"],
|
||||
["QQ", "wineBottonPath/drive_c/Program Files (x86)/Tencent/QQ/Bin/QQ.exe"],
|
||||
["TIM", "wineBottonPath/drive_c/Program Files/Tencent/TIM/Bin/TIM.exe"],
|
||||
["TIM", "wineBottonPath/drive_c/Program Files (x86)/Tencent/TIM/Bin/TIM.exe"]
|
||||
],
|
||||
[
|
||||
["cmd", "cmd"],
|
||||
["cmd", "cmd.exe"],
|
||||
["cmd", "wineBottonPath/drive_c/windows/system32/cmd.exe"],
|
||||
["Internet Explorer", "iexplore"],
|
||||
["Internet Explorer", "iexplore.exe"],
|
||||
["Internet Explorer", "wineBottonPath/drive_c/Program Files/Internet Explorer/iexplore.exe"],
|
||||
["Internet Explorer", "wineBottonPath/drive_c/Program Files (x86)/Internet Explorer/iexplore.exe"],
|
||||
["微信", "wineBottonPath/drive_c/Program Files/Tencent/WeChat/WeChat.exe"],
|
||||
["微信", "wineBottonPath/drive_c/Program Files (x86)/Tencent/WeChat/WeChat.exe"],
|
||||
["UltraISO", "wineBottonPath/drive_c/Program Files/UltraISO/UltraISO.exe"],
|
||||
["UltraISO", "wineBottonPath/drive_c/Program Files (x86)/UltraISO/UltraISO.exe"],
|
||||
["迅雷", "wineBottonPath/drive_c/Program Files/Thunder Network/MiniThunder/Bin/ThunderMini.exe"],
|
||||
["迅雷", "wineBottonPath/drive_c/Program Files (x86)/Thunder Network/MiniThunder/Bin/ThunderMini.exe"],
|
||||
["Microsoft Office Word", "wineBottonPath/drive_c/Program Files/Microsoft Office/Office12/WINWORD.EXE"],
|
||||
["Microsoft Office Word", "wineBottonPath/drive_c/Program Files (x86)/Microsoft Office/Office12/WINWORD.EXE"],
|
||||
["腾讯会议", "wineBottonPath/drive_c/Program Files/Tencent/WeMeet/wemeetapp.exe"],
|
||||
["腾讯会议", "wineBottonPath/drive_c/Program Files (x86)/Tencent/WeMeet/wemeetapp.exe"],
|
||||
["腾讯课堂", "wineBottonPath/drive_c/Program Files/Tencent/EDU/bin/TXEDU.exe"],
|
||||
["腾讯课堂", "wineBottonPath/drive_c/Program Files (x86)/Tencent/EDU/bin/TXEDU.exe"]
|
||||
]
|
||||
]
|
||||
44
deb/opt/apps/deepin-wine-runner/Mount.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
if [ ` whoami ` != "root" ]; then
|
||||
echo "Only root can run me"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$1" ]; then
|
||||
echo "路径不存在!"
|
||||
exit 1
|
||||
fi
|
||||
echo $0
|
||||
echo $1
|
||||
echo $2
|
||||
echo $3
|
||||
# 挂载必备目录
|
||||
cd "$1"
|
||||
# 拷贝 Qemu Static
|
||||
cp -r /usr/bin/qemu-*-static ./usr/bin
|
||||
# 挂载目录
|
||||
mount --bind /dev ./dev
|
||||
#mount --bind /dev/pts ./dev/pts
|
||||
mount -t proc /proc ./proc
|
||||
mount --bind /etc/resolv.conf ./etc/resolv.conf
|
||||
mount -t sysfs /sys ./sys
|
||||
#mount --bind /dev/shm ./dev/shm
|
||||
chmod 777 -R root
|
||||
xhost +
|
||||
# 挂载 Wine 运行器目录
|
||||
mount -o bind `dirname $0` ./opt/apps/deepin-wine-runner/
|
||||
# 挂载字体
|
||||
mount -o bind /usr/share/fonts ./usr/share/fonts
|
||||
# 配置用户
|
||||
if [ ! -d "home/$2" ]; then
|
||||
# 新建用户,且密码为 123456,以便读写
|
||||
chroot . bash /opt/apps/deepin-wine-runner/ChangePassword.sh "$2"
|
||||
fi
|
||||
# 挂载用户目录到 /root(默认 $HOME 路径)
|
||||
if [[ $2 == "root" ]]; then
|
||||
mount --bind root "$1/root/"
|
||||
else
|
||||
mount --bind "/home/$2" "$1/home/$2"
|
||||
fi
|
||||
|
||||
# 如果参数 3 存在
|
||||
chroot "--userspec=$2:$2" . env "HOME=/home/$2" ${@:3}
|
||||
29
deb/opt/apps/deepin-wine-runner/MountWithoutHome.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
if [ ` whoami ` != "root" ]; then
|
||||
echo "Only root can run me"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$1" ]; then
|
||||
echo "路径不存在!"
|
||||
exit 1
|
||||
fi
|
||||
echo $0
|
||||
echo $1
|
||||
echo $2
|
||||
echo $3
|
||||
# 挂载必备目录
|
||||
cd "$1"
|
||||
# 拷贝 Qemu Static
|
||||
cp -r /usr/bin/qemu-*-static ./usr/bin
|
||||
# 挂载目录
|
||||
mount --bind /dev ./dev
|
||||
#mount --bind /dev/pts ./dev/pts
|
||||
mount -t proc /proc ./proc
|
||||
mount --bind /etc/resolv.conf ./etc/resolv.conf
|
||||
mount -t sysfs /sys ./sys
|
||||
#mount --bind /dev/shm ./dev/shm
|
||||
chmod 777 -R root
|
||||
xhost +
|
||||
|
||||
# 如果参数 3 存在
|
||||
chroot . ${@:3}
|
||||
122
deb/opt/apps/deepin-wine-runner/ProgramFen.py
Normal file
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import base64
|
||||
import traceback
|
||||
import req as requests
|
||||
import PyQt5.QtGui as QtGui
|
||||
import PyQt5.QtCore as QtCore
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
|
||||
class ProgramRunStatusShow():
|
||||
msgWindow = None
|
||||
def ShowWindow():
|
||||
try:
|
||||
#fenlists = requests.get(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9iYXNoYXBwLw==").decode("utf-8") + fileName + base64.b64decode("L2FsbC5qc29u").decode("utf-8")).json()
|
||||
fenlists = []
|
||||
for i in range(6):
|
||||
fenlists.append(int(requests.get(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9GZW4=").decode("utf-8") + f"{i}/data.txt").text))
|
||||
tipsInfo = ""
|
||||
except:
|
||||
traceback.print_exc()
|
||||
fenlists = [0, 0, 0, 0, 0]
|
||||
tipsInfo = "暂时无人提交此脚本运行情况,是否立即提交?"
|
||||
|
||||
maxHead = fenlists.index(max(fenlists))
|
||||
allNumber = 0
|
||||
for i in fenlists:
|
||||
allNumber += i
|
||||
try:
|
||||
tipsInfo = ""
|
||||
for i in range(len(fenlists)):
|
||||
tipsInfo += f"有 {fenlists[i] / allNumber * 100}% 的用户选择了 {i} 分({fenlists[i]}/{allNumber})\n"
|
||||
maxNumber = max(fenlists) / allNumber * 100
|
||||
#if tipsInfo == "":
|
||||
# tipsInfo = f"有{maxNumber}%的用户选择了这个评分"
|
||||
except:
|
||||
pass
|
||||
ProgramRunStatusShow.msgWindow = QtWidgets.QMainWindow()
|
||||
msgWidget = QtWidgets.QWidget()
|
||||
msgWidgetLayout = QtWidgets.QGridLayout()
|
||||
starLayout = QtWidgets.QHBoxLayout()
|
||||
uploadButton = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "点此上传运行情况"))
|
||||
uploadButton.clicked.connect(ProgramRunStatusUpload.ShowWindow)
|
||||
msgWidgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "综合评价:")), 0, 0)
|
||||
msgWidgetLayout.addLayout(starLayout, 0, 1)
|
||||
msgWidgetLayout.addWidget(QtWidgets.QLabel(tipsInfo), 1, 0, 1, 2)
|
||||
msgWidgetLayout.addWidget(uploadButton, 3, 0, 1, 2)
|
||||
end = 5
|
||||
if maxHead > 5:
|
||||
for i in range(end):
|
||||
starLayout.addWidget(QtWidgets.QLabel(f"<img src='{programPath}/Icon/BadStar.svg' width=50>"))
|
||||
else:
|
||||
for i in range(maxHead):
|
||||
starLayout.addWidget(QtWidgets.QLabel(f"<img src='{programPath}/Icon/Star.svg' width=50>"))
|
||||
head = maxHead
|
||||
for i in range(head, end):
|
||||
starLayout.addWidget(QtWidgets.QLabel(f"<img src='{programPath}/Icon/UnStar.svg' width=50>"))
|
||||
msgWidget.setLayout(msgWidgetLayout)
|
||||
ProgramRunStatusShow.msgWindow.setCentralWidget(msgWidget)
|
||||
ProgramRunStatusShow.msgWindow.setWindowIcon(QtGui.QIcon(iconPath))
|
||||
ProgramRunStatusShow.msgWindow.setWindowTitle(f"程序运行情况")
|
||||
ProgramRunStatusShow.msgWindow.show()
|
||||
|
||||
class ProgramRunStatusUpload():
|
||||
msgWindow = None
|
||||
starLayout = None
|
||||
fen = None
|
||||
starList = []
|
||||
sha1Value = ""
|
||||
programName = None
|
||||
def ChangeStar():
|
||||
if ProgramRunStatusUpload.fen.currentIndex() > 5:
|
||||
for i in ProgramRunStatusUpload.starList:
|
||||
i.setText(f"<img src='{programPath}/Icon/BadStar.svg' width=25>")
|
||||
return
|
||||
for i in range(ProgramRunStatusUpload.fen.currentIndex()):
|
||||
ProgramRunStatusUpload.starList[i].setText(f"<img src='{programPath}/Icon/Star.svg' width=25>")
|
||||
head = ProgramRunStatusUpload.fen.currentIndex()
|
||||
end = len(ProgramRunStatusUpload.starList)
|
||||
for i in range(head, end):
|
||||
ProgramRunStatusUpload.starList[i].setText(f"<img src='{programPath}/Icon/UnStar.svg' width=25>")
|
||||
|
||||
def ShowWindow():
|
||||
ProgramRunStatusUpload.starList = []
|
||||
ProgramRunStatusUpload.msgWindow = QtWidgets.QMainWindow(ProgramRunStatusShow.msgWindow)
|
||||
msgWidget = QtWidgets.QWidget()
|
||||
msgWidgetLayout = QtWidgets.QGridLayout()
|
||||
ProgramRunStatusUpload.fen = QtWidgets.QComboBox()
|
||||
ProgramRunStatusUpload.starLayout = QtWidgets.QHBoxLayout()
|
||||
upload = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "上传"))
|
||||
upload.clicked.connect(ProgramRunStatusUpload.Upload)
|
||||
# 生成星星列表
|
||||
for i in [1, 1, 1, 1, 1]:
|
||||
ProgramRunStatusUpload.starList.append(QtWidgets.QLabel(f"<img src='{programPath}/Icon/{['Un', ''][i]}Star.svg' width=25>"))
|
||||
ProgramRunStatusUpload.starLayout.addWidget(ProgramRunStatusUpload.starList[-1])
|
||||
ProgramRunStatusUpload.starLayout.addItem(QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum))
|
||||
ProgramRunStatusUpload.fen.addItems(["0分", "1分", "2分", "3分", "4分", "5分"])
|
||||
ProgramRunStatusUpload.fen.setCurrentIndex(5)
|
||||
ProgramRunStatusUpload.fen.currentIndexChanged.connect(ProgramRunStatusUpload.ChangeStar)
|
||||
msgWidgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "评分:")), 1, 0)
|
||||
msgWidgetLayout.addWidget(ProgramRunStatusUpload.fen, 1, 1)
|
||||
msgWidgetLayout.addLayout(ProgramRunStatusUpload.starLayout, 2, 1)
|
||||
msgWidgetLayout.addWidget(upload, 3, 1)
|
||||
msgWidget.setLayout(msgWidgetLayout)
|
||||
ProgramRunStatusUpload.msgWindow.setCentralWidget(msgWidget)
|
||||
ProgramRunStatusUpload.msgWindow.setWindowTitle(QtCore.QCoreApplication.translate("U", "上传程序运行情况"))
|
||||
ProgramRunStatusUpload.msgWindow.setWindowIcon(QtGui.QIcon(iconPath))
|
||||
ProgramRunStatusUpload.msgWindow.show()
|
||||
|
||||
def Upload():
|
||||
try:
|
||||
QtWidgets.QMessageBox.information(ProgramRunStatusUpload.msgWindow, QtCore.QCoreApplication.translate("U", "提示"), requests.get(f"http://120.25.153.144/spark-deepin-wine-runner/Install.php?Version=Fen{ProgramRunStatusUpload.fen.currentIndex()}").json()["Error"])
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(ProgramRunStatusUpload.msgWindow, QtCore.QCoreApplication.translate("U", "错误"), QtCore.QCoreApplication.translate("U", "数据上传失败!"))
|
||||
|
||||
if __name__ == "__main__":
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
iconPath = "{}/deepin-wine-runner.svg".format(programPath)
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
ProgramRunStatusShow.ShowWindow()
|
||||
app.exec_()
|
||||
438
deb/opt/apps/deepin-wine-runner/QemuDownload.py
Executable file
@@ -0,0 +1,438 @@
|
||||
#!/usr/bin/env python3
|
||||
# 本来是用C++写的,但在非deepin/UOS编译/运行就是下载不了https文件,只能用python重写
|
||||
#########################################################################
|
||||
# 作者:gfdgd xi、为什么您不喜欢熊出没和阿布
|
||||
# 版本:2.4.0
|
||||
# 感谢:感谢 deepin-wine 团队,提供了 deepin-wine 给大家使用,让我能做这个程序
|
||||
# 基于 Python3 的 PyQt5 构建
|
||||
#########################################################################
|
||||
#################
|
||||
# 引入所需的库
|
||||
#################
|
||||
import os
|
||||
import shutil
|
||||
import random
|
||||
import sys
|
||||
import json
|
||||
import traceback
|
||||
import requests
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
sys.path.append(f"{programPath}/../")
|
||||
from Model import *
|
||||
from trans import *
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
# UI 布局(自动生成)
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(693, 404)
|
||||
if not get_now_lang() == "zh_CN.UTF-8":
|
||||
transla = Trans("en_US", f"{programPath}/trans/deepin-wine-runner-qemu-download.json")
|
||||
else:
|
||||
transla = Trans("zh_CN")
|
||||
_translate = transla.transe
|
||||
self.centralWidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralWidget.setObjectName("centralWidget")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralWidget)
|
||||
self.verticalLayout_2.setContentsMargins(11, 11, 11, 11)
|
||||
self.verticalLayout_2.setSpacing(6)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setSpacing(6)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.localWineList = QtWidgets.QListView(self.centralWidget)
|
||||
self.localWineList.setObjectName("localWineList")
|
||||
self.horizontalLayout_2.addWidget(self.localWineList)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout.setSpacing(6)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.verticalLayout_2.addWidget(QtWidgets.QLabel(_translate("U", """使用前须知:
|
||||
1、Qemu 跨架构效率较低,如果有条件建议优先使用 box86、exagear 等效率较高的转换层;
|
||||
2、使用此方案需要使用到 Root 权限(需开启管理员模式)并安装 qemu-user-static;
|
||||
3、chroot 时候可能会出现问题导致程序闪退或异常,出现该问题重启电脑即可;
|
||||
4、在此环境使用 Wine 时,只能读取到您用户目录或本程序文件夹下的文件,其它路径无法读取;
|
||||
5、移除容器时请保证在这次打开电脑时没有调用过需要删除容器,如果有调用过建议重启电脑后再移除;
|
||||
6、暂时属于测试功能;""")))
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem)
|
||||
self.addButton = QtWidgets.QPushButton(self.centralWidget)
|
||||
self.addButton.setObjectName("addButton")
|
||||
self.verticalLayout.addWidget(self.addButton)
|
||||
self.delButton = QtWidgets.QPushButton(self.centralWidget)
|
||||
self.delButton.setObjectName("delButton")
|
||||
self.verticalLayout.addWidget(self.delButton)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem1)
|
||||
self.horizontalLayout_2.addLayout(self.verticalLayout)
|
||||
self.internetWineList = QtWidgets.QListView(self.centralWidget)
|
||||
self.internetWineList.setObjectName("internetWineList")
|
||||
self.horizontalLayout_2.addWidget(self.internetWineList)
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout_2)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setSpacing(6)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
#self.unzip = QtWidgets.QCheckBox(self.centralWidget)
|
||||
#self.unzip.setObjectName("unzip")
|
||||
#self.horizontalLayout.addWidget(self.unzip)
|
||||
#self.deleteZip = QtWidgets.QCheckBox(self.centralWidget)
|
||||
#self.deleteZip.setChecked(True)
|
||||
#self.deleteZip.setTristate(False)
|
||||
#self.deleteZip.setObjectName("deleteZip")
|
||||
#self.horizontalLayout.addWidget(self.deleteZip)
|
||||
#self.addOtherWine = QtWidgets.QPushButton(self.centralWidget)
|
||||
#self.horizontalLayout.addWidget(self.addOtherWine)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem2)
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
||||
MainWindow.setCentralWidget(self.centralWidget)
|
||||
# 菜单栏
|
||||
#_translate = QtCore.QCoreApplication.translate
|
||||
|
||||
self.menu = MainWindow.menuBar()
|
||||
self.changeSources = self.menu.addMenu(_translate("MainWindow", "更换源"))
|
||||
self.gitlinkAction = QtWidgets.QAction(_translate("MainWindow", "Gitlink 源(推荐)"))
|
||||
self.ipv6Action = QtWidgets.QAction(_translate("MainWindow", "备用源(只支持 IPv6 用户)"))
|
||||
self.localAction = QtWidgets.QAction(_translate("MainWindow", "本地测试源(127.0.0.1)"))
|
||||
self.changeSources.addAction(self.gitlinkAction)
|
||||
self.changeSources.addAction(self.ipv6Action)
|
||||
self.changeSources.addAction(self.localAction)
|
||||
for i in [self.gitlinkAction, self.ipv6Action, self.localAction]:
|
||||
i.setCheckable(True)
|
||||
self.gitlinkAction.setChecked(True)
|
||||
self.changeSourcesGroup = QtWidgets.QActionGroup(MainWindow)
|
||||
self.changeSourcesGroup.addAction(self.gitlinkAction)
|
||||
self.changeSourcesGroup.addAction(self.ipv6Action)
|
||||
self.changeSourcesGroup.addAction(self.localAction)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "下载 Qemu 镜像"))
|
||||
self.addButton.setText(_translate("MainWindow", "<<"))
|
||||
self.delButton.setText(_translate("MainWindow", ">>"))
|
||||
#self.unzip.setText(_translate("MainWindow", "不解压Wine资源文件"))
|
||||
#self.deleteZip.setText(_translate("MainWindow", "删除下载的资源包,只解压保留(两个选项都选相互抵消)"))
|
||||
#self.addOtherWine.setText(_translate("MainWindow", "导入自己的Wine"))
|
||||
|
||||
def ReadLocalInformation():
|
||||
try:
|
||||
global localJsonList
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "r")
|
||||
localJsonList = json.loads(file.read())
|
||||
nmodel = QtGui.QStandardItemModel(window)
|
||||
for i in localJsonList:
|
||||
item = QtGui.QStandardItem(i)
|
||||
nmodel.appendRow(item)
|
||||
ui.localWineList.setModel(nmodel)
|
||||
file.close()
|
||||
except:
|
||||
print("新建空列表")
|
||||
try:
|
||||
with open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "w") as file:
|
||||
file.write("[]")
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc())
|
||||
|
||||
def InstallOtherWine():
|
||||
path = QtWidgets.QFileDialog.getOpenFileName(window, "选择 Wine", os.getenv("~"), "wine(wine);;wine64(wine64);;全部文件(*.*)")
|
||||
if path[0] == "" or not path[1]:
|
||||
return
|
||||
try:
|
||||
# 写入配置文件
|
||||
rfile = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/winelist.json", "r")
|
||||
list = json.loads(rfile.read())
|
||||
rfile.close()
|
||||
# 创建映射
|
||||
name = os.path.basename(os.path.dirname(os.path.dirname(path[0])))
|
||||
if name == "" or name == None:
|
||||
name = f"useradd-wine-{random.randint(0, 99999)}"
|
||||
#binPath = os.path.dirname(os.path.dirname(path[0]))
|
||||
os.makedirs(f"{programPath}/{name}/bin")
|
||||
if os.system(f"ln -s '{path[0]}' '{programPath}/{name}/bin/wine'") != 0:
|
||||
QtWidgets.QMessageBox.critical(window, "新建wine映射失败")
|
||||
# C++ 版注释:不直接用 readwrite 是因为不能覆盖写入
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "w")
|
||||
list.append(name)
|
||||
file.write(json.dumps(list))
|
||||
file.close()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc())
|
||||
ReadLocalInformation()
|
||||
|
||||
def ChangeSources():
|
||||
global urlSources
|
||||
global internetWineSource
|
||||
sources = [ui.gitlinkAction, ui.ipv6Action, ui.localAction]
|
||||
for i in range(0, len(sources)):
|
||||
if sources[i].isChecked():
|
||||
urlSources = internetWineSourceList[i]
|
||||
internetWineSource = internetWineSourceList[i]
|
||||
# 读取信息
|
||||
ReadLocalInformation()
|
||||
ReadInternetInformation()
|
||||
break
|
||||
print(urlSources)
|
||||
|
||||
# 下面内容均翻译自 C++ 版本
|
||||
def ReadInternetInformation():
|
||||
global internetJsonList
|
||||
# C++ 版本是用 curl 的,考虑到 Python 用 requests 反而方便,于是不用 curl
|
||||
try:
|
||||
internetJsonList = json.loads(requests.get(f"{internetWineSource}/lists.json").text)
|
||||
internetJsonListNew = []
|
||||
for k in internetJsonList:
|
||||
archList = json.loads(requests.get(f"{internetWineSource}/{k}/lists.json").text)
|
||||
for e in archList:
|
||||
internetJsonListNew.append([e[0], e[1], k])
|
||||
internetJsonList = internetJsonListNew
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", "无法连接服务器!")
|
||||
return
|
||||
print(internetJsonList)
|
||||
nmodel = QtGui.QStandardItemModel(window)
|
||||
for i in internetJsonList:
|
||||
item = QtGui.QStandardItem(i[0])
|
||||
nmodel.appendRow(item)
|
||||
ui.internetWineList.setModel(nmodel)
|
||||
|
||||
class DownloadThread(QtCore.QThread):
|
||||
MessageBoxInfo = QtCore.pyqtSignal(str)
|
||||
MessageBoxError = QtCore.pyqtSignal(str)
|
||||
ChangeDialog = QtCore.pyqtSignal(QtWidgets.QProgressDialog, int, int, int)
|
||||
Finish = QtCore.pyqtSignal()
|
||||
def __init__(self, progressDialog: QtWidgets.QProgressDialog,
|
||||
url: str, savePath: str, fileName: str, view: QtWidgets.QListView, deleteZip: bool,
|
||||
unzip: bool, localList) -> None:
|
||||
self.dialog = progressDialog
|
||||
self.fileUrl = url
|
||||
self.fileSavePath = savePath
|
||||
self.fileSaveName = fileName
|
||||
self.localView = view
|
||||
self.downloadDeleteZip = deleteZip
|
||||
self.downloadUnzip = unzip
|
||||
self.localJsonList = localList
|
||||
super().__init__()
|
||||
|
||||
def ReadLocalInformation(self):
|
||||
global localJsonList
|
||||
try:
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "r")
|
||||
nmodel = QtGui.QStandardItemModel()
|
||||
localJsonList = json.loads(file.read())
|
||||
for i in localJsonList:
|
||||
nmodel.appendRow(QtGui.QStandardItem(i))
|
||||
self.localView.setModel(nmodel)
|
||||
file.close()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc())
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
# 创建文件夹
|
||||
dir = QtCore.QDir()
|
||||
#savePath = f"{programPath}/{self.fileSaveName}"
|
||||
choose = ui.internetWineList.currentIndex().row()
|
||||
arch = internetJsonList[choose][2]
|
||||
savePath = f"{homePath}/.deepin-wine-runner-ubuntu-images/{arch}/{self.fileSaveName}"
|
||||
if not os.path.exists(os.path.dirname(savePath)):
|
||||
os.makedirs(os.path.dirname(savePath))
|
||||
# 文件下载
|
||||
timeout = 0
|
||||
f = requests.get(self.fileUrl, stream=True)
|
||||
allSize = int(f.headers["content-length"]) # 文件总大小
|
||||
bytesRead = 0
|
||||
with open(savePath, "wb") as filePart:
|
||||
for chunk in f.iter_content(chunk_size=1024):
|
||||
if chunk:
|
||||
#progressbar.update(int(part / show))
|
||||
filePart.write(chunk)
|
||||
bytesRead += 1024
|
||||
self.ChangeDialog.emit(self.dialog, bytesRead / allSize * 100, bytesRead / 1024 / 1024, allSize / 1024 / 1024)
|
||||
self.ChangeDialog.emit(self.dialog, 100, 100, 100)
|
||||
# 写入配置文件
|
||||
rfile = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "r")
|
||||
list = json.loads(rfile.read())
|
||||
rfile.close()
|
||||
# C++ 版注释:不直接用 readwrite 是因为不能覆盖写入
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "w")
|
||||
list.append(self.fileSaveName.replace(".tar.gz", ""))
|
||||
file.write(json.dumps(list))
|
||||
file.close()
|
||||
# 读取配置文件
|
||||
self.ReadLocalInformation()
|
||||
self.localJsonList = list
|
||||
# 解压文件
|
||||
shellCommand = ""
|
||||
path = f"{homePath}/.deepin-wine-runner-ubuntu-images/{arch}/{self.fileSaveName.replace('.tar.gz', '')}/"
|
||||
#path = f"{programPath}/{self.fileSaveName.replace('.7z', '')}"
|
||||
shellCommand += f"""#!/bin/bash
|
||||
mkdir -p \"{path}\"
|
||||
tar -xvf \"{savePath}\" -C \"{path}\"
|
||||
rm \"{savePath}\"
|
||||
"""
|
||||
#if self.downloadDeleteZip:
|
||||
# shellCommand += f"rm -rf \"{savePath}\"\n"
|
||||
shellFile = open("/tmp/depein-wine-runner-wine-install.sh", "w")
|
||||
shellFile.write(shellCommand)
|
||||
shellFile.close()
|
||||
process = QtCore.QProcess()
|
||||
command = ["deepin-terminal", "-e", "bash", "/tmp/depein-wine-runner-wine-install.sh"]
|
||||
process.start(f"{programPath}/../launch.sh", command)
|
||||
process.waitForFinished()
|
||||
OpenTerminal("bash /tmp/depein-wine-runner-wine-install.sh")
|
||||
self.Finish.emit()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.MessageBoxError.emit(traceback.format_exc())
|
||||
|
||||
def MessageBoxInfo(info):
|
||||
QtWidgets.QMessageBox.information(window, "提示", info)
|
||||
|
||||
def MessageBoxError(info):
|
||||
QtWidgets.QMessageBox.critical(window, "错误", info)
|
||||
|
||||
def ChangeDialog(dialog: QtWidgets.QProgressDialog, value, downloadBytes, totalBytes):
|
||||
dialog.setValue(value)
|
||||
dialog.setLabelText(f"{downloadBytes}MB/{totalBytes}MB")
|
||||
|
||||
def DownloadFinish():
|
||||
ui.centralWidget.setEnabled(True)
|
||||
|
||||
class QT:
|
||||
thread = None
|
||||
|
||||
def on_addButton_clicked():
|
||||
choose = ui.internetWineList.currentIndex().row()
|
||||
if choose < 0:
|
||||
QtWidgets.QMessageBox.information(window, "提示", "您未选中任何项,无法继续")
|
||||
return
|
||||
downloadName = internetJsonList[choose][1]
|
||||
ReadLocalInformation()
|
||||
for i in localJsonList:
|
||||
if i.replace(".tar.gz", "") == internetJsonList[choose][0]:
|
||||
QtWidgets.QMessageBox.information(window, "提示", "您已经安装了这个镜像了!无需重复安装!")
|
||||
return
|
||||
#if(ui.deleteZip.isChecked() + ui.unzip.isChecked() == 2):
|
||||
# ui.deleteZip.setChecked(False)
|
||||
# ui.unzip.setChecked(False)
|
||||
arch = internetJsonList[choose][2]
|
||||
downloadUrl = f"{internetWineSource}/{arch}/{downloadName}"
|
||||
dialog = QtWidgets.QProgressDialog()
|
||||
cancel = QtWidgets.QPushButton("取消")
|
||||
cancel.setDisabled(True)
|
||||
dialog.setWindowIcon(QtGui.QIcon(f"{programPath}/deepin-wine-runner.svg"))
|
||||
dialog.setCancelButton(cancel)
|
||||
dialog.setWindowTitle(f"正在下载“{internetJsonList[choose][0]}”")
|
||||
QT.thread = DownloadThread(
|
||||
dialog,
|
||||
downloadUrl,
|
||||
"",
|
||||
internetJsonList[choose][1],
|
||||
ui.localWineList,
|
||||
False,
|
||||
not True,
|
||||
localJsonList
|
||||
)
|
||||
QT.thread.MessageBoxInfo.connect(MessageBoxInfo)
|
||||
QT.thread.MessageBoxError.connect(MessageBoxError)
|
||||
QT.thread.ChangeDialog.connect(ChangeDialog)
|
||||
QT.thread.Finish.connect(DownloadFinish)
|
||||
ui.centralWidget.setDisabled(True)
|
||||
QT.thread.start()
|
||||
|
||||
def on_delButton_clicked():
|
||||
if os.path.exists("/tmp/deepin-wine-runner-qemu-lock"):
|
||||
if QtWidgets.QMessageBox.question(window, "提示", "检测到您的电脑已经运行了 Qemu/Chroot 容器,建议您重启电脑后再删除该容器,否则容易造成数据损失!\n是否取消操作?") == QtWidgets.QMessageBox.Yes:
|
||||
return
|
||||
if QtWidgets.QMessageBox.question(window, "提示", "你确定要删除吗?") == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
if ui.localWineList.currentIndex().row() < 0:
|
||||
QtWidgets.QMessageBox.information(window, "提示", "您未选择任何项")
|
||||
return
|
||||
try:
|
||||
# {localJsonList[ui.localWineList.currentIndex().row()]}
|
||||
path = f"{homePath}/.deepin-wine-runner-ubuntu-images/"
|
||||
changed = False
|
||||
for i in os.listdir(path):
|
||||
if os.path.exists(f"{path}/{i}/{localJsonList[ui.localWineList.currentIndex().row()]}"):
|
||||
changed = True
|
||||
name = f"{path}/{i}/{localJsonList[ui.localWineList.currentIndex().row()]}".replace(".tar.gz", "")
|
||||
if not changed:
|
||||
name = f"{path}/i386/{localJsonList[ui.localWineList.currentIndex().row()]}".replace(".tar.gz", "")
|
||||
print(name)
|
||||
# 必须取消挂载目录才行
|
||||
os.system(f"bash '{programPath}/UnMount.sh' '{name}'")
|
||||
#name = f"{homePath}/.deepin-wine-runner-ubuntu-images/{localJsonList[ui.localWineList.currentIndex().row()]}"
|
||||
dir = QtCore.QDir(name)
|
||||
dir.removeRecursively()
|
||||
QtCore.QFile.remove(name + ".tar.gz")
|
||||
del localJsonList[ui.localWineList.currentIndex().row()]
|
||||
file = open(f"{homePath}/.deepin-wine-runner-ubuntu-images/lists.json", "w")
|
||||
file.write(json.dumps(localJsonList))
|
||||
file.close()
|
||||
ReadLocalInformation()
|
||||
QtWidgets.QMessageBox.information(window, "提示", "删除成功!")
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc())
|
||||
|
||||
# 获取当前语言
|
||||
def get_now_lang()->"获取当前语言":
|
||||
return os.getenv('LANG')
|
||||
|
||||
if __name__ == "__main__":
|
||||
homePath = os.getenv("HOME")
|
||||
localJsonList = []
|
||||
internetJsonList = []
|
||||
internetWineSourceList = [
|
||||
"https://code.gitlink.org.cn/gfdgd_xi/deepin-wine-runner-ubuntu-image/raw/branch/master/Sandbox",
|
||||
"http://gfdgdxi.msns.cn/deepin-wine-runner-ubuntu-image/Sandbox", # 备用源,纯 IPv6 源
|
||||
"http://127.0.0.1/deepin-wine-runner-ubuntu-image/Sandbox/" # 本地测试源
|
||||
]
|
||||
internetWineSource = internetWineSourceList[0]
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
if os.system("which qemu-i386-static"):
|
||||
if QtWidgets.QMessageBox.question(None, "提示", "检测到您未安装 qemu-user-static,是否安装?") == QtWidgets.QMessageBox.Yes:
|
||||
OpenTerminal(f"pkexec bash '{programPath}/ShellList/InstallQemuUserStatic.sh'")
|
||||
exit()
|
||||
try:
|
||||
if not os.path.exists(f"{homePath}/.deepin-wine-runner-ubuntu-images/"):
|
||||
os.makedirs(f"{homePath}/.deepin-wine-runner-ubuntu-images/")
|
||||
except:
|
||||
traceback.print_exc()
|
||||
QtWidgets.QMessageBox.critical(None, "错误", traceback.format_exc())
|
||||
exit()
|
||||
# 读取翻译
|
||||
if not get_now_lang() == "zh_CN.UTF-8":
|
||||
trans = QtCore.QTranslator()
|
||||
trans.load(f"{programPath}/../LANG/installwine-en_US.qm")
|
||||
app.installTranslator(trans)
|
||||
# 窗口构建
|
||||
window = QtWidgets.QMainWindow()
|
||||
ui = Ui_MainWindow()
|
||||
window.setWindowIcon(QtGui.QIcon(f"{programPath}/deepin-wine-runner.svg"))
|
||||
ui.setupUi(window)
|
||||
window.show()
|
||||
# 连接信号
|
||||
ui.addButton.clicked.connect(on_addButton_clicked)
|
||||
ui.delButton.clicked.connect(on_delButton_clicked)
|
||||
#ui.addOtherWine.clicked.connect(InstallOtherWine)
|
||||
ui.changeSourcesGroup.triggered.connect(ChangeSources)
|
||||
## 加载内容
|
||||
# 设置列表双击不会编辑
|
||||
ui.localWineList.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
ui.internetWineList.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
# 读取信息
|
||||
ReadLocalInformation()
|
||||
ReadInternetInformation()
|
||||
# 图标
|
||||
ui.centralWidget.setWindowIcon(QtGui.QIcon(f"{programPath}/../deepin-wine-runner.svg"))
|
||||
|
||||
app.exec_()
|
||||
44
deb/opt/apps/deepin-wine-runner/QemuRun.py
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import getpass
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
|
||||
if __name__ == "__main__":
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
homePath = os.getenv("HOME")
|
||||
if len(sys.argv) <= 1:
|
||||
print("参数不足")
|
||||
sys.exit(1)
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
# 判断是否已下载镜像
|
||||
if not os.path.exists(f"{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}"):
|
||||
QtWidgets.QMessageBox.information(None, "提示", "此镜像未下载解压,无法继续")
|
||||
exit()
|
||||
commandList = ""
|
||||
userName = getpass.getuser()
|
||||
for i in sys.argv[3:]:
|
||||
commandList += f"'{i}' "
|
||||
if commandList.replace(" ", "") == "":
|
||||
commandList = "bash"
|
||||
# 需要先取消挂载其它目录以防止冲突
|
||||
path = f"{homePath}/.deepin-wine-runner-ubuntu-images"
|
||||
for i in os.listdir(path):
|
||||
archPath = f"{path}/{i}"
|
||||
if os.path.isdir(archPath):
|
||||
for k in os.listdir(archPath):
|
||||
bottlePath = f"{archPath}/{k}"
|
||||
if os.path.isdir(bottlePath):
|
||||
if f"{i}/{k}" == sys.argv[1]:
|
||||
continue
|
||||
if os.path.ismount(f"{bottlePath}/dev"):
|
||||
os.system(f"pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY bash '{programPath}/UnMount.sh' '{bottlePath}' ")
|
||||
os.system("touch /tmp/deepin-wine-runner-qemu-lock")
|
||||
# 判断是否挂载
|
||||
if not os.path.ismount(f"{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}/dev"):
|
||||
print("文件暂未挂载,开始挂载")
|
||||
if int(sys.argv[2]):
|
||||
sys.exit(os.system(f"pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY bash '{programPath}/MountWithoutHome.sh' '{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}' '{userName}' {commandList}"))
|
||||
else:
|
||||
sys.exit(os.system(f"pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY bash '{programPath}/Mount.sh' '{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}' '{userName}' {commandList}"))
|
||||
sys.exit(os.system(f"pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY chroot '--userspec={userName}:{userName}' '{homePath}/.deepin-wine-runner-ubuntu-images/{sys.argv[1]}/' env 'HOME=/home/{userName}' {commandList}"))
|
||||
@@ -8,10 +8,10 @@
|
||||
# 基于 Python3 的 tkinter 构建
|
||||
###########################################################################################
|
||||
cd `dirname $0`
|
||||
which VBoxManage1
|
||||
which VBoxManage
|
||||
if test $? == 0 ; then
|
||||
VM/VirtualMachine
|
||||
exit
|
||||
fi
|
||||
zenity --info --no-wrap --text="未安装 VirtualBox,请自行安装 VirtualBox 并重新运行"
|
||||
#./launch.sh deepin-terminal -C "pkexec apt install virtualbox-6.1 -y && zenity --info --text=\"安装完毕,关闭此对话框和安装终端重新运行程序即可\" --no-wrap" --keep-open
|
||||
#./launch.sh deepin-terminal -C "pkexec apt install virtualbox-6.1 -y && zenity --info --text=\"安装完毕,关闭此对话框和安装终端重新运行程序即可\" --no-wrap" --keep-open
|
||||
|
||||
3
deb/opt/apps/deepin-wine-runner/ShellList/InstallQemuUserStatic.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
echo 开始安装 qemu-user-static
|
||||
pkexec apt update
|
||||
pkexec apt install qemu-user-static -y
|
||||
37
deb/opt/apps/deepin-wine-runner/UnMount.sh
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
if [ ` whoami ` != "root" ]; then
|
||||
echo "Only root can run me"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$1" ]; then
|
||||
echo "路径不存在!"
|
||||
exit 1
|
||||
fi
|
||||
echo $0
|
||||
echo $1
|
||||
echo $2
|
||||
#echo $3
|
||||
# 挂载必备目录
|
||||
cd "$1"
|
||||
umount ./dev
|
||||
umount ./dev/pts
|
||||
umount ./proc
|
||||
umount ./etc/resolv.conf
|
||||
umount ./sys
|
||||
umount ./dev/shm
|
||||
# 挂载 Wine 运行器目录
|
||||
umount ./opt
|
||||
umount ./opt/apps/deepin-wine-runner
|
||||
# 挂载字体
|
||||
umount ./usr/share/fonts
|
||||
# 挂载用户目录到 /root(默认 $HOME 路径)
|
||||
umount ./root
|
||||
for username in $(ls ./home)
|
||||
do
|
||||
echo ./home/$username
|
||||
umount ./home/$username
|
||||
# if [ -d ./home/$username/.deepinwine/$CONTAINER_NAME ]
|
||||
# then
|
||||
# rm -rf ./home/$username/.deepinwine/$CONTAINER_NAME
|
||||
# fi
|
||||
done
|
||||
648
deb/opt/apps/deepin-wine-runner/deepin-wine-easy-packager.py
Executable file
@@ -0,0 +1,648 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import random
|
||||
import xpinyin
|
||||
import traceback
|
||||
import subprocess
|
||||
import PyQt5.QtGui as QtGui
|
||||
import PyQt5.QtCore as QtCore
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
|
||||
def ShowText(text: str):
|
||||
if text.replace(" ", "").replace("\n", "") == "":
|
||||
return
|
||||
logText.append(text.replace("\n", ""))
|
||||
|
||||
def ErrorMessage(text: str):
|
||||
QtWidgets.QMessageBox.critical(window, "错误", text)
|
||||
|
||||
def InformationMessage(text: str):
|
||||
QtWidgets.QMessageBox.information(window, "提示", text)
|
||||
|
||||
questionChoose = False
|
||||
questionStatus = False
|
||||
def QuestionMessage(text: str):
|
||||
global questionChoose
|
||||
global questionStatus
|
||||
# 清零
|
||||
questionChoose = False
|
||||
questionStatus = False
|
||||
if QtWidgets.QMessageBox.question(window, "提示", text) == QtWidgets.QMessageBox.Yes:
|
||||
questionChoose = True
|
||||
print(questionChoose)
|
||||
questionStatus = True
|
||||
return
|
||||
questionChoose = False
|
||||
questionStatus = True
|
||||
|
||||
|
||||
def DisbledAndEnabledAll(choose: bool):
|
||||
exePath.setDisabled(choose)
|
||||
browserExeButton.setDisabled(choose)
|
||||
buildButton.setDisabled(choose)
|
||||
|
||||
# 获取用户主目录
|
||||
def get_home():
|
||||
return os.path.expanduser('~')
|
||||
|
||||
def get_desktop_path():
|
||||
try:
|
||||
for line in open(get_home() + "/.config/user-dirs.dirs"): # 以行来读取配置文件
|
||||
desktop_index = line.find("XDG_DESKTOP_DIR=\"") # 寻找是否有对应项,有返回 0,没有返回 -1
|
||||
if desktop_index != -1: # 如果有对应项
|
||||
break # 结束循环
|
||||
if desktop_index == -1: # 如果是提前结束,值一定≠-1,如果是没有提前结束,值一定=-1
|
||||
return -1
|
||||
else:
|
||||
get = line[17:-2] # 截取桌面目录路径
|
||||
get_index = get.find("$HOME") # 寻找是否有对应的项,需要替换内容
|
||||
if get != -1: # 如果有
|
||||
get = get.replace("$HOME", get_home()) # 则把其替换为用户目录(~)
|
||||
return get # 返回目录
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return get_home()
|
||||
|
||||
def CleanPressCompleteDownloadState(option):
|
||||
global pressCompleteDownload
|
||||
pressCompleteDownload = False
|
||||
installCmpleteButton.setEnabled(True)
|
||||
|
||||
# 读取 lnk 文件
|
||||
def GetLnkDesktop(path):
|
||||
lnkList = []
|
||||
for i in os.listdir(path):
|
||||
filePath = f"{path}/{i}"
|
||||
if os.path.islink(filePath):
|
||||
# 忽略 link 链接
|
||||
continue
|
||||
if os.path.isdir(filePath):
|
||||
lists = GetLnkDesktop(filePath)
|
||||
for k in lists:
|
||||
lnkList.append(k)
|
||||
continue
|
||||
if os.path.isfile(filePath) and os.path.splitext(filePath)[1] == ".lnk":
|
||||
with open(filePath, "rb") as file:
|
||||
while True:
|
||||
things = file.readline().lower()
|
||||
if things == b"":
|
||||
break
|
||||
print(things[1: -2].split("\x00".encode("gbk")))
|
||||
for k in things[1: -2].split("\x00".encode("gbk")):
|
||||
if "c:".encode("gbk") in k:
|
||||
print(k.decode("gbk"))
|
||||
lnkList.append([filePath, k.decode("gbk")])
|
||||
return lnkList
|
||||
|
||||
def ReplaceText(string: str, lists: list):
|
||||
for i in lists:
|
||||
string = string.replace(i[0], i[1])
|
||||
return string
|
||||
|
||||
control = '''Package: @@@Package@@@
|
||||
Version: @@@Version@@@
|
||||
Architecture: i386
|
||||
Maintainer: @@@Maintainer@@@
|
||||
Depends: @@@Depends@@@
|
||||
Section: non-free/otherosfs
|
||||
Priority: optional
|
||||
Multi-Arch: foreign
|
||||
Installed-Size: @@@Installed-Size@@@
|
||||
Description: @@@Description@@@
|
||||
'''
|
||||
|
||||
info = f'''{{
|
||||
"appid": "@@@Package@@@",
|
||||
"name": "@@@Name@@@",
|
||||
"version": "@@@Version@@@",
|
||||
"arch": ["i386"],
|
||||
"permissions": {{
|
||||
"autostart": false,
|
||||
"notification": false,
|
||||
"trayicon": true,
|
||||
"clipboard": true,
|
||||
"account": false,
|
||||
"bluetooth": false,
|
||||
"camera": true,
|
||||
"audio_record": true,
|
||||
"installed_apps": false
|
||||
}}
|
||||
}}'''
|
||||
|
||||
postrm = f"""#!/bin/bash
|
||||
if [ "$1" = "remove" ] || [ "$1" = "purge" ];then
|
||||
|
||||
echo "清理卸载残留"
|
||||
CONTAINER_NAME="@@@Package@@@"
|
||||
|
||||
if [ -z $CONTAINER_NAME ];then
|
||||
echo "W: 没有指定容器,跳过清理容器。请手动前往 ~/.deepinwine/ 下删除"
|
||||
exit
|
||||
fi
|
||||
|
||||
/opt/deepinwine/tools/kill.sh $CONTAINER_NAME
|
||||
###这里注意,如果没写CONTAINER_NAME,会把QQ杀了
|
||||
|
||||
for username in $(ls /home)
|
||||
do
|
||||
echo /home/$username
|
||||
if [ -d /home/$username/.deepinwine/$CONTAINER_NAME ]
|
||||
then
|
||||
rm -rf /home/$username/.deepinwine/$CONTAINER_NAME
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "非卸载,跳过清理"
|
||||
fi"""
|
||||
|
||||
runsh = f'''#!/bin/sh
|
||||
|
||||
# Copyright (C) 2016 Deepin, Inc.
|
||||
#
|
||||
# Author: Li LongYu <lilongyu@linuxdeepin.com>
|
||||
# Peng Hao <penghao@linuxdeepin.com>
|
||||
#
|
||||
#
|
||||
# Copyright (C) 2022 The Spark Project
|
||||
#
|
||||
#
|
||||
# Modifier shenmo <shenmo@spark-app.store>
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
#######################函数段。下文调用的额外功能会在此处声明
|
||||
|
||||
Get_Dist_Name()
|
||||
{{
|
||||
if grep -Eqii "Deepin" /etc/issue || grep -Eq "Deepin" /etc/*-release; then
|
||||
DISTRO='Deepin'
|
||||
elif grep -Eqi "UnionTech" /etc/issue || grep -Eq "UnionTech" /etc/*-release; then
|
||||
DISTRO='UniontechOS'
|
||||
else
|
||||
DISTRO='OtherOS'
|
||||
fi
|
||||
}}
|
||||
|
||||
|
||||
####获得发行版名称
|
||||
|
||||
#########################预设值段
|
||||
|
||||
version_gt() {{ test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }}
|
||||
####用于比较版本?未实装
|
||||
BOTTLENAME="@@@Package@@@"
|
||||
APPVER="@@@Version@@@"
|
||||
EXEC_PATH="@@@EXEC_PATH@@@"
|
||||
##### 软件在wine中的启动路径
|
||||
START_SHELL_PATH="/opt/deepinwine/tools/spark_run_v4.sh"
|
||||
export MIME_TYPE=""
|
||||
#####没什么用
|
||||
export DEB_PACKAGE_NAME="@@@Package@@@"
|
||||
####这里写包名才能在启动的时候正确找到files.7z,似乎也和杀残留进程有关
|
||||
export APPRUN_CMD="deepin-wine6-stable"
|
||||
#####wine启动指令,建议
|
||||
EXPORT_ENVS=""
|
||||
|
||||
export SPECIFY_SHELL_DIR=`dirname $START_SHELL_PATH`
|
||||
|
||||
ARCHIVE_FILE_DIR="/opt/apps/$DEB_PACKAGE_NAME/files"
|
||||
|
||||
export WINEDLLPATH=/opt/$APPRUN_CMD/lib:/opt/$APPRUN_CMD/lib64
|
||||
|
||||
export WINEPREDLL="$ARCHIVE_FILE_DIR/dlls"
|
||||
|
||||
DISABLE_ATTACH_FILE_DIALOG=""
|
||||
##默认为空。若为1,则不使用系统自带的文件选择,而是使用wine的
|
||||
##对于deepin/UOS,大部分的应用都不需要使用wine的,如果有需求(比如wine应用选择的限定种类文件系统的文管不支持)
|
||||
##请填1。
|
||||
##注意:因为非DDE的环境不确定,所以默认会在非Deepin/UOS发行版上禁用这个功能。如果你确认在适配的发行版上可以正常启动,请注释或者删除下面这段
|
||||
|
||||
##############<<<<<<<<<禁用文件选择工具开始
|
||||
Get_Dist_Name
|
||||
#此功能实现参见结尾函数段
|
||||
if [ "$DISTRO" != "Deepin" ] && [ "$DISTRO" != "UniontechOS" ];then
|
||||
DISABLE_ATTACH_FILE_DIALOG="1"
|
||||
echo "非deepin/UOS,默认关闭系统自带的文件选择工具,使用Wine的"
|
||||
echo "如果你想改变这个行为,请到/opt/apps/$DEB_PACKAGE_NAME/files/$0处修改"
|
||||
echo "To打包者:如果你要打开自带请注意在适配的发行版上进行测试"
|
||||
echo "To用户:打包者没有打开这个功能,这证明启用这个功能可能造成运行问题。如果你要修改这个行为,请确保你有一定的动手能力"
|
||||
fi
|
||||
##############>>>>>>>>>禁用文件选择工具结束
|
||||
|
||||
##############<<<<<<<<<屏蔽mono和gecko安装器开始
|
||||
##默认屏蔽mono和gecko安装器
|
||||
#if [ "$APPRUN_CMD" = "spark-wine7-devel" ];then
|
||||
|
||||
#export WINEDLLOVERRIDES="mscoree,mshtml="
|
||||
#echo "为了降低打包体积,默认关闭gecko和momo,如有需要,注释此行(仅对spark-wine7-devel有效)"
|
||||
|
||||
#fi
|
||||
##############>>>>>>>>>屏蔽mono和gecko安装器结束
|
||||
|
||||
#########################执行段
|
||||
|
||||
|
||||
|
||||
|
||||
if [ -z "$DISABLE_ATTACH_FILE_DIALOG" ];then
|
||||
export ATTACH_FILE_DIALOG=1
|
||||
fi
|
||||
|
||||
if [ -n "$EXPORT_ENVS" ];then
|
||||
export $EXPORT_ENVS
|
||||
fi
|
||||
|
||||
if [ -n "$EXEC_PATH" ];then
|
||||
if [ -z "${{EXEC_PATH##*.lnk*}}" ];then
|
||||
$START_SHELL_PATH $BOTTLENAME $APPVER "C:/windows/command/start.exe" "/Unix" "$EXEC_PATH" "$@"
|
||||
else
|
||||
$START_SHELL_PATH $BOTTLENAME $APPVER "$EXEC_PATH" "$@"
|
||||
fi
|
||||
else
|
||||
$START_SHELL_PATH $BOTTLENAME $APPVER "uninstaller.exe" "$@"
|
||||
fi'''
|
||||
|
||||
desktopFile = f'''#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Type=Application
|
||||
X-Created-By=@@@Maintainer@@@
|
||||
Icon=@@@Icon@@@
|
||||
Exec="/opt/apps/@@@Package@@@/files/run.sh"
|
||||
Name=@@@Name@@@
|
||||
Comment=@@@Description@@@
|
||||
MimeType=
|
||||
GenericName=@@@Package@@@
|
||||
Terminal=false
|
||||
StartupNotify=false'''
|
||||
|
||||
def getFileFolderSize(fileOrFolderPath):
|
||||
"""get size for file or folder"""
|
||||
totalSize = 0
|
||||
if not os.path.exists(fileOrFolderPath):
|
||||
return totalSize
|
||||
if os.path.isfile(fileOrFolderPath):
|
||||
totalSize = os.path.getsize(fileOrFolderPath) # 5041481
|
||||
return totalSize
|
||||
if os.path.isdir(fileOrFolderPath):
|
||||
with os.scandir(fileOrFolderPath) as dirEntryList:
|
||||
for curSubEntry in dirEntryList:
|
||||
curSubEntryFullPath = os.path.join(fileOrFolderPath, curSubEntry.name)
|
||||
if curSubEntry.is_dir():
|
||||
curSubFolderSize = getFileFolderSize(curSubEntryFullPath) # 5800007
|
||||
totalSize += curSubFolderSize
|
||||
elif curSubEntry.is_file():
|
||||
curSubFileSize = os.path.getsize(curSubEntryFullPath) # 1891
|
||||
totalSize += curSubFileSize
|
||||
return totalSize
|
||||
|
||||
|
||||
def WriteTxt(path, things):
|
||||
with open(path, "w") as file:
|
||||
file.write(things)
|
||||
|
||||
def ReadTxt(path):
|
||||
things = ""
|
||||
with open(path, "r") as file:
|
||||
things = file.read()
|
||||
return things
|
||||
|
||||
def GetEXEVersion(exePath):
|
||||
versionPath = f"/tmp/wine-runner-exe-version-{random.randint(0, 1000)}.txt"
|
||||
if os.system(f"deepin-wine6-stable '{programPath}/GetEXEVersion.exe' '{exePath}' '{versionPath}'"):
|
||||
return "1.0.0"
|
||||
try:
|
||||
exeVersion = ReadTxt(versionPath).replace("\n", "")
|
||||
if exeVersion.replace(" ", "") == "":
|
||||
return "1.0.0"
|
||||
return exeVersion
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return "1.0.0"
|
||||
|
||||
def StrToByteToStr(text: str):
|
||||
lists = text.split("\\x")
|
||||
for i in range(len(lists)):
|
||||
lists[i]
|
||||
return text
|
||||
|
||||
def UnUseUpperCharPath(path: str):
|
||||
pathList = []
|
||||
lowerList = path.split("/")[1:]
|
||||
for i in lowerList:
|
||||
path = "/" + "/".join(pathList)
|
||||
before = len(pathList)
|
||||
for k in os.listdir(path):
|
||||
if k.lower() == i.lower():
|
||||
pathList.append(k)
|
||||
break
|
||||
end = len(pathList)
|
||||
if before == end:
|
||||
raise OSError("文件路径不存在")
|
||||
return "/" + "/".join(pathList)
|
||||
|
||||
def ReadMe():
|
||||
QtWidgets.QMessageBox.information(window, "提示", """1、目前只支持打包 X86 架构的 deb 包,暂未支持 arm;
|
||||
2、需要区分要打包的程序是绿色软件还是单文件安装包,两个对应的打包方式不相同;
|
||||
3、打包绿色软件时为尽可能减小程序体积,请将绿化后的程序(或程序文件夹)单独拷贝到干净的目录后再浏览选择主程序打包;
|
||||
4、打包详情:
|
||||
①调用 Wine:Deepin Wine6 Stable
|
||||
②调用 Helper:Spark Wine Helper
|
||||
③有卸载自动移除容器脚本""")
|
||||
|
||||
|
||||
class RunThread(QtCore.QThread):
|
||||
showLogText = QtCore.pyqtSignal(str)
|
||||
error = QtCore.pyqtSignal(str)
|
||||
info = QtCore.pyqtSignal(str)
|
||||
question = QtCore.pyqtSignal(str)
|
||||
disbledAll = QtCore.pyqtSignal(bool)
|
||||
cleanPressState = QtCore.pyqtSignal(bool)
|
||||
def RunCommand(self, command):
|
||||
res = subprocess.Popen([command], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
while res.poll() is None:
|
||||
try:
|
||||
text = res.stdout.readline().decode("utf8")
|
||||
except:
|
||||
text = ""
|
||||
self.showLogText.emit(text)
|
||||
print(text, end="")
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def GetEXEVersion(self, exePath):
|
||||
versionPath = f"/tmp/wine-runner-exe-version-{random.randint(0, 1000)}.txt"
|
||||
self.RunCommand(f"deepin-wine6-stable '{programPath}/GetEXEVersion.exe' '{exePath}' '{versionPath}'")
|
||||
try:
|
||||
exeVersion = ReadTxt(versionPath).replace("\n", "")
|
||||
if exeVersion.replace(" ", "") == "":
|
||||
return "1.0.0"
|
||||
return exeVersion
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return "1.0.0"
|
||||
|
||||
def QuestionMsg(self, text):
|
||||
global questionStatus
|
||||
questionStatus = False
|
||||
self.question.emit(text)
|
||||
while not questionStatus:
|
||||
time.sleep(0.1)
|
||||
print(questionChoose)
|
||||
return questionChoose
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.disbledAll.emit(True)
|
||||
if not self.QuestionMsg("在此过程中,需要回答一系列的问题以进行打包,点击确定继续"):
|
||||
self.disbledAll.emit(False)
|
||||
return
|
||||
bottlePath = f"/tmp/deepin-wine-runner-bottle-{random.randint(0, 10000)}"
|
||||
# 清空容器以保证能正常使用
|
||||
if os.path.exists(bottlePath):
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}'")
|
||||
############# 后面将全部调用 deepin wine6 stable 进行操作
|
||||
exeName = os.path.basename(exePath.text())
|
||||
# 暂定
|
||||
packageName = xpinyin.Pinyin().get_pinyin(os.path.splitext(exeName)[0].replace(" ", ""), "").lower().replace(" ", "").replace("_", ".").replace("-", ".").replace("..", ".")
|
||||
|
||||
if " " in packageName:
|
||||
packageName = ""
|
||||
for i in os.path.splitext(exeName)[0].split(" "):
|
||||
packageName += xpinyin.Pinyin().get_pinyin(i).lower().replace(" ", "").replace("_", ".").replace("-", ".").replace("..", ".") + "."
|
||||
print(packageName)
|
||||
packageName = packageName[:-1]
|
||||
debPackageName = "com." + packageName + ".spark"
|
||||
debPackageVersion = "1.0.0"
|
||||
programIconPath = f"/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/{debPackageName}.png"
|
||||
debMaintainer = os.getlogin()
|
||||
debBuildPath = f"/tmp/deepin-wine-packager-builder-{debPackageName}-{random.randint(0, 1000)}"
|
||||
bottlePackagePath = f"{debBuildPath}/opt/apps/{debPackageName}/files/files.7z"
|
||||
desktopPath = get_desktop_path()
|
||||
############## 运行 EXE
|
||||
if self.QuestionMsg("请问此可执行文件是安装包还是绿色软件?是安装包请按 Yes,绿色软件按 No"):
|
||||
# 清空无益处的 lnk 文件
|
||||
lnkPath = f"{bottlePath}/drive_c/ProgramData/Microsoft/Windows/Start Menu/Programs"
|
||||
self.RunCommand(f"rm -rfv '{lnkPath}'")
|
||||
self.RunCommand(f"mkdir -pv '{bottlePath}'")
|
||||
self.RunCommand(f"chmod 777 -Rv '{bottlePath}'")
|
||||
# 禁止生成 .desktop 文件
|
||||
self.RunCommand(f"WINEPREFIX='{bottlePath}' deepin-wine6-stable 'reg' 'add' 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v winemenubuilder.exe '/f'")
|
||||
# 安装包
|
||||
self.info.emit("请在运行完安装程序后按下打包器主界面的“安装程序执行完成按钮”以进行下一步操作")
|
||||
global pressCompleteDownload
|
||||
pressCompleteDownload = False
|
||||
installCmpleteButton.setEnabled(True)
|
||||
self.RunCommand(f"WINEPREFIX='{bottlePath}' deepin-wine6-stable '{exePath.text()}' &") # 非堵塞线程
|
||||
|
||||
# 安装锁,锁解除后才可继续
|
||||
while not pressCompleteDownload:
|
||||
time.sleep(0.1)
|
||||
# 杀死容器内应用
|
||||
self.RunCommand(f"'{programPath}/kill.sh' '{os.path.basename(bottlePath)}'")
|
||||
# 识别 lnk
|
||||
lnkList = GetLnkDesktop(lnkPath)
|
||||
if len(lnkList) <= 0:
|
||||
self.error.emit("无法识别到任何 lnk 快捷方式")
|
||||
self.RunCommand(f"rm -rfv '{debBuildPath}' > /dev/null")
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}' > /dev/null")
|
||||
self.disbledAll.emit(False)
|
||||
return
|
||||
# 选择最优 lnk
|
||||
secondChooseList = []
|
||||
for k in lnkList:
|
||||
lnkPath = k[0].lower()
|
||||
lnkExePath = k[1].lower()
|
||||
if "卸载" in lnkPath or "uninstall" in lnkPath or "update" in lnkPath or "网页" in lnkPath or "websize" in lnkPath or not ".exe" in lnkExePath:
|
||||
continue
|
||||
secondChooseList.append(k)
|
||||
if len(secondChooseList) <= 0:
|
||||
secondChooseList = lnkList
|
||||
rightLnk = secondChooseList[0]
|
||||
miniLenge = len(rightLnk[1])
|
||||
for k in secondChooseList:
|
||||
# 择优选择路径最短一项
|
||||
if len(k[1]) < miniLenge:
|
||||
rightLnk = k
|
||||
miniLenge = len(rightLnk[1])
|
||||
debPackageName = "com." + xpinyin.Pinyin().get_pinyin(os.path.splitext(os.path.basename(rightLnk[0]))[0].replace(" ", "")).lower().replace("--", "-").replace(" ", "").replace("_", "-").replace("-", ".") + ".spark"
|
||||
programIconPath = f"/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/{debPackageName}.png"
|
||||
bottlePackagePath = f"{debBuildPath}/opt/apps/{debPackageName}/files/files.7z"
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/'")
|
||||
folderExePath = os.path.dirname(rightLnk[1].replace("\\", "/").replace("c:/", bottlePath))
|
||||
exePathInBottle = rightLnk[1]
|
||||
exeName = os.path.splitext(os.path.basename(folderExePath))[0]
|
||||
exePathInSystem = rightLnk[1].replace("\\", "/").replace("c:", f"{bottlePath}/drive_c")
|
||||
debPackageVersion = self.GetEXEVersion(exePathInSystem)
|
||||
cpNow = False
|
||||
for i in iconList:
|
||||
path = i[1].replace("wineBottonPath", bottlePath).lower()
|
||||
if path == exePathInSystem.lower():
|
||||
self.RunCommand(f"cp -rv '{programPath}/Icon/{i[0]}.svg' '{debBuildPath}/{programIconPath}'")
|
||||
exeName = i[0]
|
||||
cpNow = True
|
||||
break
|
||||
if not cpNow:
|
||||
self.RunCommand(f"'{programPath}/wrestool' '{UnUseUpperCharPath(exePathInSystem)}' -x -t 14 > '{debBuildPath}/{programIconPath}'")
|
||||
else:
|
||||
#/home/gfdgd_xi/Desktop/新建文件夹1/BeCyIconGrabber.exe
|
||||
# 绿色软件
|
||||
self.RunCommand(f"mkdir -pv '{bottlePath}'")
|
||||
self.RunCommand(f"chmod 777 -Rv '{bottlePath}'")
|
||||
self.RunCommand(f"WINEPREFIX='{bottlePath}' deepin-wine6-stable exit")
|
||||
folderExePath = os.path.dirname(exePath.text())
|
||||
exePathInBottle = f"c:/Program Files/{os.path.basename(folderExePath)}/{exeName}"
|
||||
exeName = os.path.splitext(os.path.basename(os.path.basename(exePath.text())))[0]
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/'")
|
||||
self.RunCommand(f"'{programPath}/wrestool' '{exePath.text()}' -x -t 14 > '{debBuildPath}/{programIconPath}'")
|
||||
# 拷贝文件到容器
|
||||
self.RunCommand(f"cp -rv '{folderExePath}' '{bottlePath}/drive_c/Program Files'")
|
||||
debPackageVersion = self.GetEXEVersion(exePath.text())
|
||||
debDescription = f"{exeName} By Deepin Wine 6 Stable And Build By Wine Runner Easy Packager"
|
||||
debDepends = "deepin-wine6-stable, spark-dwine-helper | store.spark-app.spark-dwine-helper, fonts-wqy-microhei, fonts-wqy-zenhei"
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/DEBIAN'")
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/files'")
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/applications'")
|
||||
#self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/'")
|
||||
############ 处理容器
|
||||
# 对用户目录进行处理
|
||||
os.chdir(bottlePath)
|
||||
self.RunCommand("sed -i \"s#$USER#@current_user@#\" ./*.reg")
|
||||
os.chdir(f"{bottlePath}/drive_c/users")
|
||||
# 如果缩放文件 scale.txt 存在,需要移除以便用户自行调节缩放设置
|
||||
if os.path.exists(f"{bottlePath}/scale.txt"):
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}/scale.txt'")
|
||||
# 删除因为脚本失误导致用户目录嵌套(如果存在)
|
||||
if os.path.exists(f"{bottlePath}/drive_c/users/@current_user@/@current_user@"):
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}/drive_c/users/@current_user@/@current_user@'")
|
||||
self.RunCommand(f"mv -fv '{os.getlogin()}' @current_user@")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/我的'*")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/My '*")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/Desktop'")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/Downloads'")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/Templates'")
|
||||
########### 打包容器
|
||||
self.RunCommand(f"7z a '{bottlePackagePath}' '{bottlePath}/'*")
|
||||
########### 生成文件内容
|
||||
buildProgramSize = getFileFolderSize(debBuildPath) / 1000
|
||||
replaceMap = [
|
||||
["@@@Package@@@", debPackageName],
|
||||
["@@@Version@@@", debPackageVersion],
|
||||
["@@@Maintainer@@@", debMaintainer],
|
||||
["@@@Depends@@@", debDepends],
|
||||
["@@@Description@@@", debDescription],
|
||||
["@@@Installed-Size@@@", str(buildProgramSize)],
|
||||
["@@@Name@@@", exeName],
|
||||
["@@@EXEC_PATH@@@", exePathInBottle],
|
||||
["@@@Icon@@@", programIconPath]
|
||||
]
|
||||
debControl = ReplaceText(control, replaceMap)
|
||||
debPostrm = ReplaceText(postrm, replaceMap)
|
||||
debInfo = ReplaceText(info, replaceMap)
|
||||
debRunSh = ReplaceText(runsh, replaceMap)
|
||||
debDesktop = ReplaceText(desktopFile, replaceMap)
|
||||
########### 写入文件
|
||||
WriteTxt(f"{debBuildPath}/opt/apps/{debPackageName}/entries/applications/{debPackageName}.desktop", debDesktop)
|
||||
WriteTxt(f"{debBuildPath}/opt/apps/{debPackageName}/files/run.sh", debRunSh)
|
||||
WriteTxt(f"{debBuildPath}/opt/apps/{debPackageName}/info", debInfo)
|
||||
WriteTxt(f"{debBuildPath}/DEBIAN/control", debControl)
|
||||
WriteTxt(f"{debBuildPath}/DEBIAN/postrm", debPostrm)
|
||||
########### 赋值权限
|
||||
self.RunCommand(f"chmod -Rv 644 '{debBuildPath}/opt/apps/{debPackageName}/info'")
|
||||
self.RunCommand(f"chmod -Rv 0755 '{debBuildPath}/DEBIAN'")
|
||||
self.RunCommand(f"chmod -Rv 755 '{debBuildPath}/opt/apps/{debPackageName}/files/'*.sh")
|
||||
self.RunCommand(f"chmod -Rv 755 '{debBuildPath}/opt/apps/{debPackageName}/entries/applications/'*.desktop")
|
||||
########### 打包 deb
|
||||
print(debPackageVersion)
|
||||
self.RunCommand(f"dpkg -b '{debBuildPath}' '{desktopPath}/{debPackageName}_{debPackageVersion}_i386.deb'")
|
||||
self.info.emit("打包完成!")
|
||||
self.disbledAll.emit(False)
|
||||
########### 移除临时文件
|
||||
self.RunCommand(f"rm -rfv '{debBuildPath}' > /dev/null")
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}' > /dev/null")
|
||||
except:
|
||||
self.RunCommand(f"rm -rfv '{debBuildPath}' > /dev/null")
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}' > /dev/null")
|
||||
# 若打包出现任何错误
|
||||
traceback.print_exc()
|
||||
self.error.emit(f"打包错误,详细详细如下:{traceback.format_exc()}")
|
||||
self.showLogText.emit(traceback.format_exc())
|
||||
self.disbledAll.emit(False)
|
||||
|
||||
#/home/gfdgd_xi/Downloads/XPcalc.exe
|
||||
def RunBuildThread():
|
||||
global buildThread
|
||||
buildThread = RunThread()
|
||||
buildThread.showLogText.connect(ShowText)
|
||||
buildThread.error.connect(ErrorMessage)
|
||||
buildThread.info.connect(InformationMessage)
|
||||
buildThread.question.connect(QuestionMessage)
|
||||
buildThread.disbledAll.connect(DisbledAndEnabledAll)
|
||||
buildThread.cleanPressState.connect(CleanPressCompleteDownloadState)
|
||||
logText.clear()
|
||||
buildThread.start()
|
||||
|
||||
pressCompleteDownload = False
|
||||
|
||||
def PressCompleteDownload():
|
||||
global pressCompleteDownload
|
||||
pressCompleteDownload = True
|
||||
installCmpleteButton.setDisabled(True)
|
||||
|
||||
def BrowserExe():
|
||||
filePath = QtWidgets.QFileDialog.getOpenFileName(window, "选择 exe", get_home(), "可执行文件(*.exe);;所有文件(*.*)")
|
||||
if filePath[0] != "" or filePath[0] != None:
|
||||
exePath.setText(filePath[0])
|
||||
|
||||
if __name__ == "__main__":
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
iconPath = "{}/deepin-wine-runner.svg".format(programPath)
|
||||
information = json.loads(ReadTxt(f"{programPath}/information.json"))
|
||||
iconListUnBuild = json.loads(ReadTxt(f"{programPath}/IconList.json"))[0]
|
||||
iconList = json.loads(ReadTxt(f"{programPath}/IconList.json"))[1]
|
||||
for i in iconListUnBuild:
|
||||
iconList.append(i)
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
version = information["Version"]
|
||||
window = QtWidgets.QMainWindow()
|
||||
widget = QtWidgets.QWidget()
|
||||
layout = QtWidgets.QGridLayout()
|
||||
exePath = QtWidgets.QLineEdit()
|
||||
browserExeButton = QtWidgets.QPushButton("浏览……")
|
||||
logText = QtWidgets.QTextBrowser()
|
||||
logText.setStyleSheet("""
|
||||
background-color: black;
|
||||
color: white;
|
||||
""")
|
||||
controlLayout = QtWidgets.QHBoxLayout()
|
||||
buildButton = QtWidgets.QPushButton("现在打包……")
|
||||
installCmpleteButton = QtWidgets.QPushButton("安装程序执行完成")
|
||||
helpButton = QtWidgets.QPushButton("帮助")
|
||||
browserExeButton.clicked.connect(BrowserExe)
|
||||
buildButton.clicked.connect(RunBuildThread)
|
||||
installCmpleteButton.clicked.connect(PressCompleteDownload)
|
||||
helpButton.clicked.connect(ReadMe)
|
||||
installCmpleteButton.setDisabled(True)
|
||||
controlLayout.addWidget(buildButton)
|
||||
controlLayout.addWidget(installCmpleteButton)
|
||||
controlLayout.addWidget(helpButton)
|
||||
layout.addWidget(QtWidgets.QLabel("选择 EXE:"), 0, 0)
|
||||
layout.addWidget(exePath, 0, 1)
|
||||
layout.addWidget(browserExeButton, 0, 2)
|
||||
layout.addLayout(controlLayout, 1, 1)
|
||||
layout.addWidget(logText, 2, 0, 1, 3)
|
||||
widget.setLayout(layout)
|
||||
window.setCentralWidget(widget)
|
||||
window.setWindowTitle(f"Wine 运行器 {version}——简易打包器")
|
||||
try:
|
||||
exePath.setText(sys.argv[1])
|
||||
except:
|
||||
pass
|
||||
window.resize(int(window.frameGeometry().width() * 1.2), int(window.frameGeometry().height() * 1.1))
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
||||
@@ -23,23 +23,24 @@ from PIL import Image
|
||||
import PyQt5.QtGui as QtGui
|
||||
import PyQt5.QtCore as QtCore
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
from trans import *
|
||||
|
||||
#################
|
||||
# 程序所需事件
|
||||
#################
|
||||
|
||||
def button1_cl():
|
||||
path = QtWidgets.QFileDialog.getExistingDirectory(widget, QtCore.QCoreApplication.translate("U", "选择 wine 容器"), f"{get_home()}/.deepinwine")
|
||||
path = QtWidgets.QFileDialog.getExistingDirectory(widget, transla.transe("U", "选择 wine 容器"), f"{get_home()}/.deepinwine")
|
||||
if path != "":
|
||||
e6_text.setText(path)
|
||||
|
||||
def button2_cl(number):
|
||||
path = QtWidgets.QFileDialog.getOpenFileName(widget, QtCore.QCoreApplication.translate("U", "选择图标文件"), get_home(), "PNG图标(*.png);;SVG图标(*.svg);;全部文件(*.*)")[0]
|
||||
path = QtWidgets.QFileDialog.getOpenFileName(widget, transla.transe("U", "选择图标文件"), get_home(), "PNG图标(*.png);;SVG图标(*.svg);;全部文件(*.*)")[0]
|
||||
if path != "":
|
||||
mapLink[number].setText(path)
|
||||
|
||||
def button4_cl():
|
||||
path = QtWidgets.QFileDialog.getSaveFileName(widget, QtCore.QCoreApplication.translate("U", "保存 deb 包"), get_home(), "deb 文件(*.deb);;所有文件(*.*)", "{}_{}_i386.deb".format(e1_text.text(), e2_text.text()))[0]
|
||||
path = QtWidgets.QFileDialog.getSaveFileName(widget, transla.transe("U", "保存 deb 包"), get_home(), "deb 文件(*.deb);;所有文件(*.*)", "{}_{}_i386.deb".format(e1_text.text(), e2_text.text()))[0]
|
||||
if path != "":
|
||||
e12_text.setText(path)
|
||||
|
||||
@@ -203,14 +204,41 @@ def Build7zButton_Clicked():
|
||||
QT.thread.start()
|
||||
|
||||
def make_deb(build=False):
|
||||
global bottleNameLock
|
||||
clean_textbox1_things()
|
||||
disabled_or_NORMAL_all(False)
|
||||
if e1_text.text() == "" or e2_text.text() == "" or e3_text.text() == "" or e4_text.text() == "" or e5_text.text() == "" or e6_text.text() == "" or e7_text.text() == "" or e8_text.text() == "" or e12_text.text() == "":
|
||||
badComplete = False
|
||||
# 规范检测
|
||||
if e1_text.text().lower() != e1_text.text():
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"包名 {e1_text.text()} 似乎不符合规范,可能会导致打包后的包无法投稿到应用商店,是否继续?\n可参考 deb 安装包打包标准", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
for i in range(len(iconUiList)):
|
||||
if os.path.splitext(iconUiList[i][4].text())[1] == ".ico":
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"图标 {iconUiList[i][4].text()} 似乎为 ico 格式,可能会导致打包后的程序在启动器的图标无法正常显示,是否继续?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
if os.path.exists(iconUiList[i][0].text()) and not "c:" in iconUiList[i][0].text().lower():
|
||||
if not e6_text.text() in iconUiList[i][0].text():
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"路径 {iconUiList[i][0].text()} 似乎不符合规范且不位于容器内,可能会导致打包后的程序无法运行,是否继续?\n可参考 Windows 下的文件路径", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"路径 {iconUiList[i][0].text()} 似乎不符合规范,可能会导致打包后的程序无法运行,是否继续?\n可参考 Windows 下的文件路径", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
for k in [0, 3]:
|
||||
if iconUiList[i][k].text().replace(" ", "") == "":
|
||||
badComplete = True
|
||||
if badComplete or e1_text.text() == "" or e2_text.text() == "" or e3_text.text() == "" or e4_text.text() == "" or e5_text.text() == "" or e6_text.text() == "" or e7_text.text() == "" or e8_text.text() == "" or e12_text.text() == "":
|
||||
QtWidgets.QMessageBox.critical(widget, "错误", "必填信息没有填写完整,无法继续构建 deb 包")
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("必填信息没有填写完整,无法继续构建 deb 包")
|
||||
return
|
||||
if QtWidgets.QMessageBox.question(widget, QtCore.QCoreApplication.translate("U", "提示"), QtCore.QCoreApplication.translate("U", "打包将会改动现在选择的容器,是否继续?")) == QtWidgets.QMessageBox.No:
|
||||
if QtWidgets.QMessageBox.question(widget, transla.transe("U", "提示"), transla.transe("U", "打包将会改动现在选择的容器,是否继续?")) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
return
|
||||
# 警告信息
|
||||
@@ -232,6 +260,7 @@ def make_deb(build=False):
|
||||
QT.thread.errorMsg.connect(ErrorMsg)
|
||||
QT.thread.infoMsg.connect(InfoMsg)
|
||||
QT.thread.disabled_or_NORMAL_all.connect(disabled_or_NORMAL_all)
|
||||
bottleNameLock = False
|
||||
QT.thread.start()
|
||||
#thread.start()
|
||||
|
||||
@@ -245,7 +274,6 @@ def ReplaceText(string: str, lists: list):
|
||||
return string
|
||||
|
||||
class make_deb_threading(QtCore.QThread):
|
||||
|
||||
signal = QtCore.pyqtSignal(str)
|
||||
label = QtCore.pyqtSignal(str)
|
||||
getSavePath = QtCore.pyqtSignal(str)
|
||||
@@ -1204,7 +1232,7 @@ fi
|
||||
# 获取文件大小
|
||||
################
|
||||
self.label.emit("正在计算文件大小……")
|
||||
size = int(getFileFolderSize(debPackagePath) / 1024)
|
||||
size = int(getFileFolderSize(debPackagePath) / 1000)
|
||||
################
|
||||
# 写入文本文档
|
||||
################
|
||||
@@ -1324,6 +1352,12 @@ StartupNotify=false
|
||||
self.label.emit("正在构建 deb 包……")
|
||||
self.run_command("bash -c 'dpkg -b \"{}\" \"{}\"'".format(debPackagePath, e12_text.text()))
|
||||
################
|
||||
# 删除临时文件
|
||||
################
|
||||
if not self.build:
|
||||
self.label.emit("正在删除临时文件……")
|
||||
self.run_command(f"rm -rfv '{debPackagePath}'")
|
||||
################
|
||||
# 完成构建
|
||||
################
|
||||
self.label.emit("完成构建!")
|
||||
@@ -1689,7 +1723,7 @@ mapLink = []
|
||||
|
||||
def AddTab():
|
||||
global mapLink
|
||||
button2 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "浏览……"))
|
||||
button2 = QtWidgets.QPushButton(transla.transe("U", "浏览……"))
|
||||
e7_text = QtWidgets.QLineEdit()
|
||||
e8_text = QtWidgets.QLineEdit()
|
||||
e9_text = QtWidgets.QLineEdit()
|
||||
@@ -1703,11 +1737,11 @@ def AddTab():
|
||||
mapLink.append(e9_text)
|
||||
#desktopIconTabLayout = QtWidgets.QGridLayout()
|
||||
desktopIconTabLayout = QtWidgets.QGridLayout()
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件的参数(选填):")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的图标(选填):")), 10, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "wine 容器里需要运行的可执行文件的参数:")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的图标:")), 10, 0, 1, 1)
|
||||
iconTab1.setLayout(desktopIconTabLayout)
|
||||
desktopIconTab.addTab(iconTab1, f"图标{desktopIconTab.count() + 1}")
|
||||
desktopIconTabLayout.addWidget(e7_text, 6, 1, 1, 1)
|
||||
@@ -1716,7 +1750,24 @@ def AddTab():
|
||||
desktopIconTabLayout.addWidget(e8_text, 9, 1, 1, 1)
|
||||
desktopIconTabLayout.addWidget(e9_text, 10, 1, 1, 1)
|
||||
desktopIconTabLayout.addWidget(button2, 10, 2, 1, 1)
|
||||
e8_text.setWhatsThis(transla.transe("U", """填写该软件的中文或英文名称。"""))
|
||||
e9_text.setWhatsThis(transla.transe("U", """图标只支持PNG格式和SVG格式,其他格式无法显示。"""))
|
||||
e15_text.setWhatsThis(transla.transe("U", "程序参数,如%u,一般不需要"))
|
||||
e7_text.setWhatsThis(transla.transe("U", """可执行文件的运行路径格式是“C:/XXX/XXX.exe”(不包含引号)"""))
|
||||
option1_text.setWhatsThis(transla.transe("U", """点击右侧的下拉箭头,选择该软件所属的软件分类即可,常见软件分类名称释义:
|
||||
Network=网络应用;
|
||||
Chat=即时通讯或社交沟通;
|
||||
Video=视频播放;
|
||||
Graphics=图形图像;
|
||||
Office=办公学习;
|
||||
Translation=阅读翻译;
|
||||
Development=软件开发;
|
||||
Utility=工具软件或其他应用。
|
||||
不明白英文的可以百度查询一下软件分类名称的意思。
|
||||
注意:此时选择的软件分类名称决定了该软件打包后再安装时会安装在启动器中的哪个软件分类目录中。"""))
|
||||
e7_text.textChanged.connect(ChangeTapTitle)
|
||||
e7_text.setPlaceholderText("例如 c:/Program Files/Tencent/QQ/Bin/QQ.exe")
|
||||
e9_text.setPlaceholderText(transla.transe("U", "支持 png 和 svg 格式,不支持 ico 格式"))
|
||||
iconUiList.append([e7_text, option1_text, e15_text, e8_text, e9_text])
|
||||
print(iconUiList)
|
||||
|
||||
@@ -1727,6 +1778,30 @@ def DelTab():
|
||||
del iconUiList[desktopIconTab.currentIndex()]
|
||||
desktopIconTab.removeTab(desktopIconTab.currentIndex())
|
||||
|
||||
def ChangeBottleName():
|
||||
global bottleNameLock
|
||||
global bottleNameChangeLock
|
||||
e1_text.setText(e1_text.text().replace(" ", ""))
|
||||
if bottleNameLock:
|
||||
return
|
||||
if os.path.basename(e6_text.text()) == ".wine" or e6_text.text() == "":
|
||||
bottleNameChangeLock = True
|
||||
e5_text.setText(e1_text.text())
|
||||
return
|
||||
bottleNameChangeLock = True
|
||||
e5_text.setText(os.path.basename(e6_text.text().replace(" ", "")))
|
||||
|
||||
def LockBottleName():
|
||||
global bottleNameLock
|
||||
if bottleNameChangeLock:
|
||||
return
|
||||
bottleNameLock = True
|
||||
|
||||
# 获取当前语言
|
||||
def get_now_lang()->"获取当前语言":
|
||||
return os.getenv('LANG')
|
||||
|
||||
bottleNameLock = False
|
||||
###############
|
||||
# 程序信息
|
||||
###############
|
||||
@@ -1758,18 +1833,27 @@ iconUiList = []
|
||||
iconPath = "{}/deepin-wine-runner.svg".format(programPath)
|
||||
information = json.loads(readtxt(f"{programPath}/information.json"))
|
||||
version = information["Version"]
|
||||
tips = """提示:
|
||||
# 语言载入
|
||||
if not get_now_lang() == "zh_CN.UTF-8":
|
||||
#trans = QtCore.QTranslator()
|
||||
#trans.load(f"{programPath}/LANG/deepin-wine-runner-en_US.qm")
|
||||
#app.installTranslator(trans)
|
||||
transla = Trans("en_US", f"{programPath}/trans/deepin-wine-packager.json")
|
||||
else:
|
||||
transla = Trans("zh_CN")
|
||||
tips = transla.transe("U", """提示:
|
||||
1、deb 打包软件包名要求:
|
||||
软件包名只能含有小写字母(a-z)、数字(0-9)、加号(+)和减号(-)、以及点号(.),软件包名最短长度两个字符;它必须以字母开头
|
||||
2、如果要填写路径,有“浏览……”按钮的是要填本计算机对应文件的路径,否则就是填写安装到其他计算机使用的路径
|
||||
3、输入 wine 的容器路径时最后面请不要输入“/”
|
||||
4、输入可执行文件的运行路径时是以“C:/XXX/XXX.exe”的格式进行输入,默认是以 C: 为开头,不用“\”做命令的分隔,而是用“/”
|
||||
5、.desktop 的图标只支持 PNG 格式和 SVG 格式,其他格式无法显示图标
|
||||
6、路径建议不要带空格,容易出问题"""
|
||||
6、路径建议不要带空格,容易出问题""")
|
||||
|
||||
###############
|
||||
# 窗口创建
|
||||
###############
|
||||
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
window = QtWidgets.QMainWindow()
|
||||
widget = QtWidgets.QWidget()
|
||||
@@ -1792,25 +1876,25 @@ e12_text = QtWidgets.QLineEdit()
|
||||
e15_text = QtWidgets.QLineEdit()
|
||||
label13_text = QtWidgets.QLabel("<p align='center'>当前 deb 打包情况:暂未打包</p>")
|
||||
option1_text = QtWidgets.QComboBox()
|
||||
button1 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "浏览……"))
|
||||
button2 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "浏览……"))
|
||||
button4 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "浏览……"))
|
||||
button1 = QtWidgets.QPushButton(transla.transe("U", "浏览……"))
|
||||
button2 = QtWidgets.QPushButton(transla.transe("U", "浏览……"))
|
||||
button4 = QtWidgets.QPushButton(transla.transe("U", "浏览……"))
|
||||
debControlFrame = QtWidgets.QHBoxLayout()
|
||||
button5 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "打包……"))
|
||||
installDeb = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "安装打包完成的 deb……"))
|
||||
buildDebDir = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "根据填写内容打包模板"))
|
||||
build7z = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "打包容器 7z 包"))
|
||||
button5 = QtWidgets.QPushButton(transla.transe("U", "打包……"))
|
||||
installDeb = QtWidgets.QPushButton(transla.transe("U", "安装打包完成的 deb……"))
|
||||
buildDebDir = QtWidgets.QPushButton(transla.transe("U", "根据填写内容打包模板"))
|
||||
build7z = QtWidgets.QPushButton(transla.transe("U", "打包容器 7z 包"))
|
||||
debControlFrame.addWidget(button5)
|
||||
debControlFrame.addWidget(installDeb)
|
||||
rmBash = QtWidgets.QCheckBox(QtCore.QCoreApplication.translate("U", "设置卸载该 deb 后自动删除该容器"))
|
||||
cleanBottonByUOS = QtWidgets.QCheckBox(QtCore.QCoreApplication.translate("U", "使用统信 Wine 生态适配活动容器清理脚本"))
|
||||
rmBash = QtWidgets.QCheckBox(transla.transe("U", "设置卸载该 deb 后自动删除该容器"))
|
||||
cleanBottonByUOS = QtWidgets.QCheckBox(transla.transe("U", "使用统信 Wine 生态适配活动容器清理脚本"))
|
||||
debArch = QtWidgets.QComboBox()
|
||||
debArch.addItems(["i386", "arm64(box86+exagear)"])
|
||||
textbox1 = QtWidgets.QTextBrowser()
|
||||
option1_text.addItems(["Network", "Chat", "Audio", "Video", "Graphics", "Office", "Translation", "Development", "Utility"])
|
||||
option1_text.setCurrentText("Network")
|
||||
wineFrame = QtWidgets.QHBoxLayout()
|
||||
chooseWineHelperValue = QtWidgets.QCheckBox(QtCore.QCoreApplication.translate("U", "使用星火wine helper\n(如不勾选默认为deepin-wine-helper)"))
|
||||
chooseWineHelperValue = QtWidgets.QCheckBox(transla.transe("U", "使用星火wine helper\n(如不勾选默认为deepin-wine-helper)"))
|
||||
button1.clicked.connect(button1_cl)
|
||||
button2.clicked.connect(lambda: button2_cl(0))
|
||||
mapLink.append(e9_text)
|
||||
@@ -1820,19 +1904,23 @@ buildDebDir.clicked.connect(lambda: make_deb(True))
|
||||
build7z.clicked.connect(Build7zButton_Clicked)
|
||||
installDeb.clicked.connect(InstallDeb)
|
||||
wineFrame.addWidget(wineVersion)
|
||||
e1_text.textChanged.connect(ChangeBottleName)
|
||||
e5_text.textChanged.connect(LockBottleName)
|
||||
e6_text.textChanged.connect(ChangeBottleName)
|
||||
e7_text.textChanged.connect(ChangeTapTitle)
|
||||
# 创建控件
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的包名(※必填):")), 0, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的版本号(※必填):")), 1, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的说明(※必填):")), 2, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的维护者(※必填):")), 3, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要解压的 wine 容器的容器名(※必填):")), 4, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要解压的 wine 容器(※必填):")), 5, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要打包的 deb 包的包名(※必填):")), 0, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 包的版本号(※必填):")), 1, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 包的说明(※必填):")), 2, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 包的维护者(※必填):")), 3, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要解压的 wine 容器的名称(※必填):")), 4, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要打包的 wine 容器路径(※必填):")), 5, 0, 1, 1)
|
||||
desktopIconTab = QtWidgets.QTabWidget()
|
||||
controlWidget = QtWidgets.QWidget()
|
||||
controlWidgetLayout = QtWidgets.QHBoxLayout()
|
||||
desktopIconTabAdd = QtWidgets.QPushButton("+")
|
||||
desktopIconTabDel = QtWidgets.QPushButton("-")
|
||||
desktopIconTabAdd.setWhatsThis("添加新图标")
|
||||
desktopIconTabDel.setWhatsThis("移除选中图标")
|
||||
controlWidgetLayout.addWidget(desktopIconTabAdd)
|
||||
controlWidgetLayout.addWidget(desktopIconTabDel)
|
||||
controlWidget.setLayout(controlWidgetLayout)
|
||||
@@ -1840,18 +1928,18 @@ desktopIconTabAdd.clicked.connect(AddTab)
|
||||
desktopIconTabDel.clicked.connect(DelTab)
|
||||
iconTab1 = QtWidgets.QWidget()
|
||||
desktopIconTabLayout = QtWidgets.QGridLayout()
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件的参数(选填):")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的图标(选填):")), 10, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "wine 容器里需要运行的可执行文件的参数:")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的图标:")), 10, 0, 1, 1)
|
||||
iconTab1.setLayout(desktopIconTabLayout)
|
||||
#desktopIconTab.setTabPosition(QtWidgets.QTabWidget.East)
|
||||
desktopIconTab.addTab(iconTab1, "Defult")
|
||||
desktopIconTab.setCornerWidget(controlWidget)
|
||||
widgetLayout.addWidget(desktopIconTab, 8, 0, 6, 3)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "选择打包的 wine 版本(※必选):")), 6, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "打包 deb 的保存路径(※必填):")), 7, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "选择打包的 wine 版本(※必选):")), 6, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "打包 deb 的保存路径(※必填):")), 7, 0, 1, 1)
|
||||
widgetLayout.addWidget(e1_text, 0, 1, 1, 1)
|
||||
widgetLayout.addWidget(e2_text, 1, 1, 1, 1)
|
||||
widgetLayout.addWidget(e3_text, 2, 1, 1, 1)
|
||||
@@ -1874,30 +1962,30 @@ widgetLayout.addLayout(debControlFrame, 16, 1, 1, 1)
|
||||
widgetLayout.addWidget(label13_text, 17, 0, 1, 3)
|
||||
widgetLayout.addWidget(textbox1, 18, 0, 1, 3)
|
||||
# 高级功能
|
||||
moreSetting = QtWidgets.QGroupBox(QtCore.QCoreApplication.translate("U", "高级设置"))
|
||||
moreSetting = QtWidgets.QGroupBox(transla.transe("U", "高级设置"))
|
||||
debDepends = QtWidgets.QLineEdit()
|
||||
debRecommend = QtWidgets.QLineEdit()
|
||||
debDepends.setPlaceholderText(QtCore.QCoreApplication.translate("U", "deb 包的依赖(如无特殊需求默认即可)"))
|
||||
debDepends.setPlaceholderText(transla.transe("U", "deb 包的依赖(如无特殊需求默认即可)"))
|
||||
debDepends.setText("deepin-wine6-stable, deepin-wine-helper (>= 5.1.30-1), fonts-wqy-microhei, fonts-wqy-zenhei")
|
||||
debRecommend.setPlaceholderText(QtCore.QCoreApplication.translate("U", "deb 包的推荐依赖(非强制,一般默认即可)"))
|
||||
debRecommend.setPlaceholderText(transla.transe("U", "deb 包的推荐依赖(非强制,一般默认即可)"))
|
||||
moreSettingLayout = QtWidgets.QVBoxLayout()
|
||||
localWineVersion = QtWidgets.QComboBox()
|
||||
useInstallWineArch = QtWidgets.QComboBox()
|
||||
useInstallWineArch.addItems(["wine", "wine64"])
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "Wine 位数(只限本地需要打包集成的Wine):\n提示:32位的Wine不能使用64位容器")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "Wine 位数(只限本地需要打包集成的Wine):\n提示:32位的Wine不能使用64位容器")))
|
||||
#moreSettingLayout.addWidget(localWineVersion)
|
||||
moreSettingLayout.addWidget(useInstallWineArch)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "deb 包选项:")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 包选项:")))
|
||||
moreSettingLayout.addWidget(rmBash)
|
||||
moreSettingLayout.addWidget(cleanBottonByUOS)
|
||||
moreSettingLayout.addWidget(chooseWineHelperValue)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "deb 的依赖(强制,如无特殊需求默认即可):")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 的依赖(强制,如无特殊需求默认即可):")))
|
||||
moreSettingLayout.addWidget(debDepends)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "deb 的推荐依赖(非强制,一般默认即可):")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 的推荐依赖(非强制,一般默认即可):")))
|
||||
moreSettingLayout.addWidget(debRecommend)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的 MimeType:")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的 MimeType:")))
|
||||
moreSettingLayout.addWidget(e10_text)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "打包 deb 架构:")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "打包 deb 架构:")))
|
||||
moreSettingLayout.addWidget(debArch)
|
||||
moreSetting.setLayout(moreSettingLayout)
|
||||
widgetLayout.addWidget(moreSetting, 0, 3, 16, 2)
|
||||
@@ -1911,22 +1999,27 @@ e2_text.textChanged.connect(AutoPathSet)
|
||||
debArch.currentIndexChanged.connect(AutoPathSet)
|
||||
debArch.currentIndexChanged.connect(ChangeArchCombobox)
|
||||
e12_text.textChanged.connect(UserPathSet)
|
||||
e1_text.setPlaceholderText("例如 spark-deepin-wine-runner,不建议有大写字符")
|
||||
e2_text.setPlaceholderText(f"例如 {version}")
|
||||
e7_text.setPlaceholderText("例如 c:/Program Files/Tencent/QQ/Bin/QQ.exe")
|
||||
e9_text.setPlaceholderText(transla.transe("U", "支持 png 和 svg 格式,不支持 ico 格式"))
|
||||
# 菜单栏
|
||||
menu = window.menuBar()
|
||||
programmenu = menu.addMenu(QtCore.QCoreApplication.translate("U", "程序"))
|
||||
debMenu = menu.addMenu(QtCore.QCoreApplication.translate("U", "deb 包"))
|
||||
uploadSparkStore = menu.addMenu(QtCore.QCoreApplication.translate("U", "投稿到星火应用商店"))
|
||||
help = menu.addMenu(QtCore.QCoreApplication.translate("U", "帮助"))
|
||||
exit = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "退出程序"))
|
||||
debE = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "只读取 Control 信息"))
|
||||
debX = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "读取所有(需解包,时间较久)"))
|
||||
uploadSparkStoreWebsize = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "从网页端投稿"))
|
||||
programmenu = menu.addMenu(transla.transe("U", "程序"))
|
||||
debMenu = menu.addMenu(transla.transe("U", "deb 包"))
|
||||
uploadSparkStore = menu.addMenu(transla.transe("U", "投稿到星火应用商店"))
|
||||
help = menu.addMenu(transla.transe("U", "帮助"))
|
||||
exit = QtWidgets.QAction(transla.transe("U", "退出程序"))
|
||||
debE = QtWidgets.QAction(transla.transe("U", "只读取 Control 信息"))
|
||||
debX = QtWidgets.QAction(transla.transe("U", "读取所有(需解包,时间较久)"))
|
||||
uploadSparkStoreWebsize = QtWidgets.QAction(transla.transe("U", "从网页端投稿"))
|
||||
if os.path.exists("/opt/spark-store-submitter/bin/spark-store-submitter"):
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "使用投稿器投稿(推荐)"))
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(transla.transe("U", "使用投稿器投稿(推荐)"))
|
||||
else:
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "使用投稿器投稿(推荐,请先安装投稿器)"))
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(transla.transe("U", "使用投稿器投稿(推荐,请先安装投稿器)"))
|
||||
uploadSparkStoreProgram.setDisabled(True)
|
||||
tip = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "小提示"))
|
||||
tip = QtWidgets.QAction(transla.transe("U", "小提示"))
|
||||
getPdfHelp = QtWidgets.QAction(transla.transe("U", "Wine运行器和Wine打包器傻瓜式使用教程(小白专用)\nBy @雁舞白沙"))
|
||||
exit.triggered.connect(window.close)
|
||||
tip.triggered.connect(helps)
|
||||
programmenu.addAction(exit)
|
||||
@@ -1938,7 +2031,9 @@ debE.triggered.connect(lambda: ReadDeb(False))
|
||||
debX.triggered.connect(lambda: ReadDeb(True))
|
||||
uploadSparkStoreWebsize.triggered.connect(lambda: webbrowser.open_new_tab("https://upload.deepinos.org"))
|
||||
uploadSparkStoreProgram.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"/opt/spark-store-submitter/bin/spark-store-submitter '{e12_text.text()}'"]).start())
|
||||
getPdfHelp.triggered.connect(lambda: webbrowser.open_new_tab("https://bbs.deepin.org/post/246837"))
|
||||
help.addAction(tip)
|
||||
help.addAction(getPdfHelp)
|
||||
# 控件配置
|
||||
try:
|
||||
e6_text.setText(sys.argv[1].replace("~", get_home()))
|
||||
@@ -1955,6 +2050,44 @@ window.setCentralWidget(widget)
|
||||
window.setWindowTitle(f"wine 应用打包器 {version}")
|
||||
window.setWindowIcon(QtGui.QIcon(iconPath))
|
||||
window.resize(int(window.frameSize().width() * 2.1), int(window.frameSize().height()))
|
||||
e1_text.setWhatsThis("""com.XXX.deepin
|
||||
XXX指windows软件的英文名称,可以自定义名称,但最好是用软件解压安装后自动生成的英文名称,如:dingtalk。包名只能含有小写字母(a-z)、数字(0-9)、加号(+)和减号(-)、以及点号(.),软件包名最短长度为两个字符,且包名必须以字母开头。""")
|
||||
# 创建控件
|
||||
e2_text.setWhatsThis(transla.transe("U", """6.5.50(随便填写或填写该软件的windows版本的版本号,6.5.50只是示例)。"""))
|
||||
e3_text.setWhatsThis(transla.transe("U", """随便填写或使用该软件的windows版本的软件简介。"""))
|
||||
e4_text.setWhatsThis(transla.transe("U", """填写自己的网名,若是自用软件,不上架至应用商店,不进行后续维护,可随便填写。"""))
|
||||
e5_text.setWhatsThis(f"<p>解压容器到其它机器的容器名称,一般自动带出</p><p><img src='{programPath}/Icon/Screen/202211121646232464_image.png'></p>")
|
||||
e6_text.setWhatsThis(transla.transe("U", f"要打包的容器所在路径,也可以选择已经好打包的 7z 文件,一般自动带出"))
|
||||
e7_text.setWhatsThis("""可执行文件的运行路径格式是“C:/XXX/XXX.exe”(不包含引号)""")
|
||||
debArch.setWhatsThis(transla.transe("U", "选择生成 deb 包所对应的架构"))
|
||||
rmBash.setWhatsThis(transla.transe("U", "清理容器无用内容,一般建议勾选,最新版本默认勾选,如果有特殊需求(如容器内有 mono、gecko 等)建议取消勾选"))
|
||||
debDepends.setWhatsThis(transla.transe("U", "生成 deb 包所需的依赖,一般情况下默认即可"))
|
||||
debRecommend.setWhatsThis(transla.transe("U", "生成 deb 包的推荐依赖,一般情况下为空即可"))
|
||||
cleanBottonByUOS.setWhatsThis(transla.transe("U", "清理容器无用内容,一般建议勾选,最新版本默认勾选,如果有特殊需求(如容器内有 mono、gecko 等)建议取消勾选"))
|
||||
chooseWineHelperValue.setWhatsThis(transla.transe("U", "使用星火 dwine helper 替换 Deepin Wine Helper,投稿星火应用商店的话建议勾选,最新版本默认勾选(如果打包 arm 包将不会提供选择)"))
|
||||
option1_text.setWhatsThis("""点击右侧的下拉箭头,选择该软件所属的软件分类即可,常见软件分类名称释义:
|
||||
Network=网络应用;
|
||||
Chat=即时通讯或社交沟通;
|
||||
Video=视频播放;
|
||||
Graphics=图形图像;
|
||||
Office=办公学习;
|
||||
Translation=阅读翻译;
|
||||
Development=软件开发;
|
||||
Utility=工具软件或其他应用。
|
||||
不明白英文的可以百度查询一下软件分类名称的意思。
|
||||
注意:此时选择的软件分类名称决定了该软件打包后再安装时会安装在启动器中的哪个软件分类目录中。""")
|
||||
e8_text.setWhatsThis(transla.transe("U", """填写该软件的中文或英文名称。"""))
|
||||
e9_text.setWhatsThis(transla.transe("U", """图标只支持PNG格式和SVG格式,其他格式无法显示。"""))
|
||||
e10_text.setWhatsThis(transla.transe("U", "快捷方式的 MimeType 项,一般为空即可"))
|
||||
option1_text.setWhatsThis(transla.transe("U", "打包的 Wine 版本,根据实际情况选择(如果打包 arm 包将不会提供选择)"))
|
||||
e12_text.setWhatsThis(transla.transe("U", "打包出的 deb 生成的位置,一般自动生成"))
|
||||
e15_text.setWhatsThis(transla.transe("U", "程序参数,如%u,一般不需要"))
|
||||
build7z.setWhatsThis(transla.transe("U", "只打包容器生成 7z 包,不做其它操作"))
|
||||
buildDebDir.setWhatsThis(transla.transe("U", "构建 deb 包目录,但不打包成 deb"))
|
||||
textbox1.setWhatsThis(transla.transe("U", "查看打包过程中命令返回内容"))
|
||||
button5.setWhatsThis(transla.transe("U", "点击该按钮打包生成 deb"))
|
||||
installDeb.setWhatsThis(transla.transe("U", "调用默认的 deb 安装工具安装生成的 deb"))
|
||||
#window.setWindowFlag(QtGui.Qt)
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
||||
# Flag:解包只读control和解包全部读取
|
||||
@@ -1,9 +1,16 @@
|
||||
{
|
||||
"Version": "2.5.0",
|
||||
"Version": "3.0.0",
|
||||
"Thank": [
|
||||
"感谢 @豪 提供程序图标",
|
||||
"感谢 @鹤舞白沙 对程序文案进行优化以及编写《Wine运行器和Wine打包器傻瓜式使用教程(小白专用) 》",
|
||||
"感谢 @璀璨星空 提供的彩蛋图标",
|
||||
"感谢 @Bail 反馈的更新策略问题",
|
||||
"感谢 @白水 反馈的安装 exagear 后无法识别和调用 box86 的问题",
|
||||
"感谢 @汐光. 提供的翻译接口",
|
||||
"感谢 @鹤舞白沙 专门为小白用户编写的使用 Wine 运行器非基于生态适配脚本的程序打包教程",
|
||||
"感谢 @牦牛儿苗 进行了龙芯 3a5000 平台的测试与移植",
|
||||
"感谢 @雁舞白沙 优化了程序文案",
|
||||
"感谢 @豪 的程序测试和制作的非官方论坛 https://gfdgdxi.flarum.cloud/",
|
||||
"感谢 @豪 的程序测试和制作的论坛 https://gfdgdxi.flarum.cloud/",
|
||||
"感谢 @185******67 反馈的 2.4.0 无法打开 Visual Basic 组件安装工具的问题",
|
||||
"感谢 @shenmo 提供的 在打包器的 postrm 脚本添加 kill.sh、追加参数改为 --uri xxxxxxx、独立生成容器 7z 文件的功能",
|
||||
"感谢 @a2035274 @虚幻的早晨 https://bbs.deepin.org/post/238301",
|
||||
|
||||
@@ -7,32 +7,21 @@ with open("/var/lib/dpkg/status", "r") as i:
|
||||
if unConnect:
|
||||
print("52专版,将会无法连接服务器")
|
||||
|
||||
badUrl = [
|
||||
"http://120.25.153.144",
|
||||
"https://304626p927.goho.co",
|
||||
"https://30x46269h2.goho.co",
|
||||
"http://gfdgdxi.msns.cn"
|
||||
]
|
||||
|
||||
class Respon:
|
||||
text = ""
|
||||
|
||||
def get(url, timeout=None): # -> requests.Response:
|
||||
if unConnect:
|
||||
# 筛选 Url,只有特定的 url 才会被拦截
|
||||
for i in badUrl:
|
||||
if i in url:
|
||||
raise Exception("52专版不支持连接作者服务器")
|
||||
# 全部 Url 都拦截
|
||||
raise Exception("52专版不支持连接服务器")
|
||||
if timeout == None:
|
||||
return requests.get(url)
|
||||
return requests.get(url, timeout=timeout)
|
||||
|
||||
def post(url, data, timeout=None):
|
||||
if unConnect:
|
||||
# 筛选 Url,只有特定的 url 才会被拦截
|
||||
for i in badUrl:
|
||||
if i in url:
|
||||
raise Exception("52专版不支持连接作者服务器")
|
||||
# 全部 Url 都拦截
|
||||
raise Exception("52专版不支持连接服务器")
|
||||
if timeout == None:
|
||||
return requests.post(url, data)
|
||||
return requests.post(url, data, timeout=timeout)
|
||||
53
deb/opt/apps/deepin-wine-runner/trans/__init__.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
import traceback
|
||||
|
||||
class Trans():
|
||||
isTrans = False
|
||||
unCloudTrans = True
|
||||
word = {}
|
||||
fileName = ""
|
||||
|
||||
def __init__(self, lang="zh_CN", fileName=f"trans.json") -> None:
|
||||
self.fileName = fileName
|
||||
self.isTrans = (lang != "zh_CN")
|
||||
if self.isTrans:
|
||||
try:
|
||||
if not os.path.exists(fileName):
|
||||
with open(fileName, "w") as file:
|
||||
file.write("{}")
|
||||
with open(fileName, "r") as file:
|
||||
self.word = json.loads(file.read())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.isTrans = False
|
||||
|
||||
def transe(self, temp, text) -> str:
|
||||
if not self.isTrans:
|
||||
return text
|
||||
try:
|
||||
return self.word[text].replace("(", "(").replace(")", ")")
|
||||
except:
|
||||
if self.unCloudTrans:
|
||||
return text
|
||||
# 机翻
|
||||
data = { 'doctype': 'json', 'type': 'auto','i': text}
|
||||
jsonReturn = requests.post("http://fanyi.youdao.com/translate", data=data).json()["translateResult"]
|
||||
transText = ""
|
||||
for i in jsonReturn:
|
||||
print(i[0])
|
||||
transText += f'{i[0]["tgt"]}\n'
|
||||
if "\n" in text:
|
||||
transText = transText.replace("\n\n", "\n")[:-1]
|
||||
else:
|
||||
transText = transText[:-1]
|
||||
self.word[text] = transText.replace("(", "(").replace(")", ")")
|
||||
try:
|
||||
with open(self.fileName, "w") as file:
|
||||
file.write(json.dumps(self.word, ensure_ascii=False))
|
||||
except:
|
||||
traceback.print_exc()
|
||||
print(f"{text}=>{transText}")
|
||||
return transText
|
||||
@@ -0,0 +1 @@
|
||||
{"更换源": "Change the source", "Gitlink 源(推荐)": "Gitlink source (recommended)", "备用源(只支持 IPv6 用户)": "The alternate source (only support IPv6 users)", "本地测试源(127.0.0.1)": "Local test source (127.0.0.1)", "使用前须知:\n1、Qemu 跨架构效率较低,如果有条件建议优先使用 box86、exagear 等效率较高的转换层;\n2、使用此方案需要使用到 Root 权限(需开启管理员模式)并安装 qemu-user-static;\n3、chroot 时候可能会出现问题导致程序闪退或异常,出现该问题重启电脑即可;\n4、在此环境使用 Wine 时,只能读取到您用户目录或本程序文件夹下的文件,其它路径无法读取;\n5、移除容器时请保证在这次打开电脑时没有调用过需要删除容器,如果有调用过建议重启电脑后再移除;\n6、暂时属于测试功能;": "Instructions before use:\n1, Qemu across architecture efficiency is low, if there is condition is preferred to use box86, exagear high efficiency transformation layer;\n2, use this program to need to use the Root administrator mode (open) and install qemu - user - static;\n3, when chroot flash back problems may cause the program or abnormal, the problems to restart the computer;\n4, in this environment using Wine, can only read your user directory or folder of the program files, other path cannot read;\n5, remove the container please make sure that no calls while in the open a computer need to delete the container, if there is a call after advice to restart the computer to remove;\n6, a temporary belong to test functionality;"}
|
||||
BIN
deb/opt/apps/deepin-wine-runner/vkd3d-proton.7z
Normal file
BIN
deb/opt/apps/deepin-wine-runner/wrestool
Executable file
1
deb/usr/bin/deepin-wine-packager-easy-builder
Symbolic link
@@ -0,0 +1 @@
|
||||
/opt/apps/deepin-wine-runner/deepin-wine-easy-packager.py
|
||||
12
deb/usr/share/applications/spark-deepin-wine-packager-easy-builder.desktop
Executable file
@@ -0,0 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
X-Categories=System;Wine;
|
||||
Exec=/usr/bin/deepin-wine-packager-easy-builder %F
|
||||
Icon=/opt/apps/deepin-wine-runner/deepin-wine-runner.svg
|
||||
Name=Wine Package Builder
|
||||
Name[zh]=Wine 简易打包器
|
||||
Terminal=false
|
||||
StartupNotify=true
|
||||
NoDisplay=true
|
||||
Keywords=exe;scr;
|
||||
MimeType=application/x-ms-dos-executable;application/x-msi;application/x-ms-shortcut;
|
||||
648
deepin-wine-easy-packager.py
Executable file
@@ -0,0 +1,648 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import random
|
||||
import xpinyin
|
||||
import traceback
|
||||
import subprocess
|
||||
import PyQt5.QtGui as QtGui
|
||||
import PyQt5.QtCore as QtCore
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
|
||||
def ShowText(text: str):
|
||||
if text.replace(" ", "").replace("\n", "") == "":
|
||||
return
|
||||
logText.append(text.replace("\n", ""))
|
||||
|
||||
def ErrorMessage(text: str):
|
||||
QtWidgets.QMessageBox.critical(window, "错误", text)
|
||||
|
||||
def InformationMessage(text: str):
|
||||
QtWidgets.QMessageBox.information(window, "提示", text)
|
||||
|
||||
questionChoose = False
|
||||
questionStatus = False
|
||||
def QuestionMessage(text: str):
|
||||
global questionChoose
|
||||
global questionStatus
|
||||
# 清零
|
||||
questionChoose = False
|
||||
questionStatus = False
|
||||
if QtWidgets.QMessageBox.question(window, "提示", text) == QtWidgets.QMessageBox.Yes:
|
||||
questionChoose = True
|
||||
print(questionChoose)
|
||||
questionStatus = True
|
||||
return
|
||||
questionChoose = False
|
||||
questionStatus = True
|
||||
|
||||
|
||||
def DisbledAndEnabledAll(choose: bool):
|
||||
exePath.setDisabled(choose)
|
||||
browserExeButton.setDisabled(choose)
|
||||
buildButton.setDisabled(choose)
|
||||
|
||||
# 获取用户主目录
|
||||
def get_home():
|
||||
return os.path.expanduser('~')
|
||||
|
||||
def get_desktop_path():
|
||||
try:
|
||||
for line in open(get_home() + "/.config/user-dirs.dirs"): # 以行来读取配置文件
|
||||
desktop_index = line.find("XDG_DESKTOP_DIR=\"") # 寻找是否有对应项,有返回 0,没有返回 -1
|
||||
if desktop_index != -1: # 如果有对应项
|
||||
break # 结束循环
|
||||
if desktop_index == -1: # 如果是提前结束,值一定≠-1,如果是没有提前结束,值一定=-1
|
||||
return -1
|
||||
else:
|
||||
get = line[17:-2] # 截取桌面目录路径
|
||||
get_index = get.find("$HOME") # 寻找是否有对应的项,需要替换内容
|
||||
if get != -1: # 如果有
|
||||
get = get.replace("$HOME", get_home()) # 则把其替换为用户目录(~)
|
||||
return get # 返回目录
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return get_home()
|
||||
|
||||
def CleanPressCompleteDownloadState(option):
|
||||
global pressCompleteDownload
|
||||
pressCompleteDownload = False
|
||||
installCmpleteButton.setEnabled(True)
|
||||
|
||||
# 读取 lnk 文件
|
||||
def GetLnkDesktop(path):
|
||||
lnkList = []
|
||||
for i in os.listdir(path):
|
||||
filePath = f"{path}/{i}"
|
||||
if os.path.islink(filePath):
|
||||
# 忽略 link 链接
|
||||
continue
|
||||
if os.path.isdir(filePath):
|
||||
lists = GetLnkDesktop(filePath)
|
||||
for k in lists:
|
||||
lnkList.append(k)
|
||||
continue
|
||||
if os.path.isfile(filePath) and os.path.splitext(filePath)[1] == ".lnk":
|
||||
with open(filePath, "rb") as file:
|
||||
while True:
|
||||
things = file.readline().lower()
|
||||
if things == b"":
|
||||
break
|
||||
print(things[1: -2].split("\x00".encode("gbk")))
|
||||
for k in things[1: -2].split("\x00".encode("gbk")):
|
||||
if "c:".encode("gbk") in k:
|
||||
print(k.decode("gbk"))
|
||||
lnkList.append([filePath, k.decode("gbk")])
|
||||
return lnkList
|
||||
|
||||
def ReplaceText(string: str, lists: list):
|
||||
for i in lists:
|
||||
string = string.replace(i[0], i[1])
|
||||
return string
|
||||
|
||||
control = '''Package: @@@Package@@@
|
||||
Version: @@@Version@@@
|
||||
Architecture: i386
|
||||
Maintainer: @@@Maintainer@@@
|
||||
Depends: @@@Depends@@@
|
||||
Section: non-free/otherosfs
|
||||
Priority: optional
|
||||
Multi-Arch: foreign
|
||||
Installed-Size: @@@Installed-Size@@@
|
||||
Description: @@@Description@@@
|
||||
'''
|
||||
|
||||
info = f'''{{
|
||||
"appid": "@@@Package@@@",
|
||||
"name": "@@@Name@@@",
|
||||
"version": "@@@Version@@@",
|
||||
"arch": ["i386"],
|
||||
"permissions": {{
|
||||
"autostart": false,
|
||||
"notification": false,
|
||||
"trayicon": true,
|
||||
"clipboard": true,
|
||||
"account": false,
|
||||
"bluetooth": false,
|
||||
"camera": true,
|
||||
"audio_record": true,
|
||||
"installed_apps": false
|
||||
}}
|
||||
}}'''
|
||||
|
||||
postrm = f"""#!/bin/bash
|
||||
if [ "$1" = "remove" ] || [ "$1" = "purge" ];then
|
||||
|
||||
echo "清理卸载残留"
|
||||
CONTAINER_NAME="@@@Package@@@"
|
||||
|
||||
if [ -z $CONTAINER_NAME ];then
|
||||
echo "W: 没有指定容器,跳过清理容器。请手动前往 ~/.deepinwine/ 下删除"
|
||||
exit
|
||||
fi
|
||||
|
||||
/opt/deepinwine/tools/kill.sh $CONTAINER_NAME
|
||||
###这里注意,如果没写CONTAINER_NAME,会把QQ杀了
|
||||
|
||||
for username in $(ls /home)
|
||||
do
|
||||
echo /home/$username
|
||||
if [ -d /home/$username/.deepinwine/$CONTAINER_NAME ]
|
||||
then
|
||||
rm -rf /home/$username/.deepinwine/$CONTAINER_NAME
|
||||
fi
|
||||
done
|
||||
else
|
||||
echo "非卸载,跳过清理"
|
||||
fi"""
|
||||
|
||||
runsh = f'''#!/bin/sh
|
||||
|
||||
# Copyright (C) 2016 Deepin, Inc.
|
||||
#
|
||||
# Author: Li LongYu <lilongyu@linuxdeepin.com>
|
||||
# Peng Hao <penghao@linuxdeepin.com>
|
||||
#
|
||||
#
|
||||
# Copyright (C) 2022 The Spark Project
|
||||
#
|
||||
#
|
||||
# Modifier shenmo <shenmo@spark-app.store>
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
#######################函数段。下文调用的额外功能会在此处声明
|
||||
|
||||
Get_Dist_Name()
|
||||
{{
|
||||
if grep -Eqii "Deepin" /etc/issue || grep -Eq "Deepin" /etc/*-release; then
|
||||
DISTRO='Deepin'
|
||||
elif grep -Eqi "UnionTech" /etc/issue || grep -Eq "UnionTech" /etc/*-release; then
|
||||
DISTRO='UniontechOS'
|
||||
else
|
||||
DISTRO='OtherOS'
|
||||
fi
|
||||
}}
|
||||
|
||||
|
||||
####获得发行版名称
|
||||
|
||||
#########################预设值段
|
||||
|
||||
version_gt() {{ test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"; }}
|
||||
####用于比较版本?未实装
|
||||
BOTTLENAME="@@@Package@@@"
|
||||
APPVER="@@@Version@@@"
|
||||
EXEC_PATH="@@@EXEC_PATH@@@"
|
||||
##### 软件在wine中的启动路径
|
||||
START_SHELL_PATH="/opt/deepinwine/tools/spark_run_v4.sh"
|
||||
export MIME_TYPE=""
|
||||
#####没什么用
|
||||
export DEB_PACKAGE_NAME="@@@Package@@@"
|
||||
####这里写包名才能在启动的时候正确找到files.7z,似乎也和杀残留进程有关
|
||||
export APPRUN_CMD="deepin-wine6-stable"
|
||||
#####wine启动指令,建议
|
||||
EXPORT_ENVS=""
|
||||
|
||||
export SPECIFY_SHELL_DIR=`dirname $START_SHELL_PATH`
|
||||
|
||||
ARCHIVE_FILE_DIR="/opt/apps/$DEB_PACKAGE_NAME/files"
|
||||
|
||||
export WINEDLLPATH=/opt/$APPRUN_CMD/lib:/opt/$APPRUN_CMD/lib64
|
||||
|
||||
export WINEPREDLL="$ARCHIVE_FILE_DIR/dlls"
|
||||
|
||||
DISABLE_ATTACH_FILE_DIALOG=""
|
||||
##默认为空。若为1,则不使用系统自带的文件选择,而是使用wine的
|
||||
##对于deepin/UOS,大部分的应用都不需要使用wine的,如果有需求(比如wine应用选择的限定种类文件系统的文管不支持)
|
||||
##请填1。
|
||||
##注意:因为非DDE的环境不确定,所以默认会在非Deepin/UOS发行版上禁用这个功能。如果你确认在适配的发行版上可以正常启动,请注释或者删除下面这段
|
||||
|
||||
##############<<<<<<<<<禁用文件选择工具开始
|
||||
Get_Dist_Name
|
||||
#此功能实现参见结尾函数段
|
||||
if [ "$DISTRO" != "Deepin" ] && [ "$DISTRO" != "UniontechOS" ];then
|
||||
DISABLE_ATTACH_FILE_DIALOG="1"
|
||||
echo "非deepin/UOS,默认关闭系统自带的文件选择工具,使用Wine的"
|
||||
echo "如果你想改变这个行为,请到/opt/apps/$DEB_PACKAGE_NAME/files/$0处修改"
|
||||
echo "To打包者:如果你要打开自带请注意在适配的发行版上进行测试"
|
||||
echo "To用户:打包者没有打开这个功能,这证明启用这个功能可能造成运行问题。如果你要修改这个行为,请确保你有一定的动手能力"
|
||||
fi
|
||||
##############>>>>>>>>>禁用文件选择工具结束
|
||||
|
||||
##############<<<<<<<<<屏蔽mono和gecko安装器开始
|
||||
##默认屏蔽mono和gecko安装器
|
||||
#if [ "$APPRUN_CMD" = "spark-wine7-devel" ];then
|
||||
|
||||
#export WINEDLLOVERRIDES="mscoree,mshtml="
|
||||
#echo "为了降低打包体积,默认关闭gecko和momo,如有需要,注释此行(仅对spark-wine7-devel有效)"
|
||||
|
||||
#fi
|
||||
##############>>>>>>>>>屏蔽mono和gecko安装器结束
|
||||
|
||||
#########################执行段
|
||||
|
||||
|
||||
|
||||
|
||||
if [ -z "$DISABLE_ATTACH_FILE_DIALOG" ];then
|
||||
export ATTACH_FILE_DIALOG=1
|
||||
fi
|
||||
|
||||
if [ -n "$EXPORT_ENVS" ];then
|
||||
export $EXPORT_ENVS
|
||||
fi
|
||||
|
||||
if [ -n "$EXEC_PATH" ];then
|
||||
if [ -z "${{EXEC_PATH##*.lnk*}}" ];then
|
||||
$START_SHELL_PATH $BOTTLENAME $APPVER "C:/windows/command/start.exe" "/Unix" "$EXEC_PATH" "$@"
|
||||
else
|
||||
$START_SHELL_PATH $BOTTLENAME $APPVER "$EXEC_PATH" "$@"
|
||||
fi
|
||||
else
|
||||
$START_SHELL_PATH $BOTTLENAME $APPVER "uninstaller.exe" "$@"
|
||||
fi'''
|
||||
|
||||
desktopFile = f'''#!/usr/bin/env xdg-open
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Type=Application
|
||||
X-Created-By=@@@Maintainer@@@
|
||||
Icon=@@@Icon@@@
|
||||
Exec="/opt/apps/@@@Package@@@/files/run.sh"
|
||||
Name=@@@Name@@@
|
||||
Comment=@@@Description@@@
|
||||
MimeType=
|
||||
GenericName=@@@Package@@@
|
||||
Terminal=false
|
||||
StartupNotify=false'''
|
||||
|
||||
def getFileFolderSize(fileOrFolderPath):
|
||||
"""get size for file or folder"""
|
||||
totalSize = 0
|
||||
if not os.path.exists(fileOrFolderPath):
|
||||
return totalSize
|
||||
if os.path.isfile(fileOrFolderPath):
|
||||
totalSize = os.path.getsize(fileOrFolderPath) # 5041481
|
||||
return totalSize
|
||||
if os.path.isdir(fileOrFolderPath):
|
||||
with os.scandir(fileOrFolderPath) as dirEntryList:
|
||||
for curSubEntry in dirEntryList:
|
||||
curSubEntryFullPath = os.path.join(fileOrFolderPath, curSubEntry.name)
|
||||
if curSubEntry.is_dir():
|
||||
curSubFolderSize = getFileFolderSize(curSubEntryFullPath) # 5800007
|
||||
totalSize += curSubFolderSize
|
||||
elif curSubEntry.is_file():
|
||||
curSubFileSize = os.path.getsize(curSubEntryFullPath) # 1891
|
||||
totalSize += curSubFileSize
|
||||
return totalSize
|
||||
|
||||
|
||||
def WriteTxt(path, things):
|
||||
with open(path, "w") as file:
|
||||
file.write(things)
|
||||
|
||||
def ReadTxt(path):
|
||||
things = ""
|
||||
with open(path, "r") as file:
|
||||
things = file.read()
|
||||
return things
|
||||
|
||||
def GetEXEVersion(exePath):
|
||||
versionPath = f"/tmp/wine-runner-exe-version-{random.randint(0, 1000)}.txt"
|
||||
if os.system(f"deepin-wine6-stable '{programPath}/GetEXEVersion.exe' '{exePath}' '{versionPath}'"):
|
||||
return "1.0.0"
|
||||
try:
|
||||
exeVersion = ReadTxt(versionPath).replace("\n", "")
|
||||
if exeVersion.replace(" ", "") == "":
|
||||
return "1.0.0"
|
||||
return exeVersion
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return "1.0.0"
|
||||
|
||||
def StrToByteToStr(text: str):
|
||||
lists = text.split("\\x")
|
||||
for i in range(len(lists)):
|
||||
lists[i]
|
||||
return text
|
||||
|
||||
def UnUseUpperCharPath(path: str):
|
||||
pathList = []
|
||||
lowerList = path.split("/")[1:]
|
||||
for i in lowerList:
|
||||
path = "/" + "/".join(pathList)
|
||||
before = len(pathList)
|
||||
for k in os.listdir(path):
|
||||
if k.lower() == i.lower():
|
||||
pathList.append(k)
|
||||
break
|
||||
end = len(pathList)
|
||||
if before == end:
|
||||
raise OSError("文件路径不存在")
|
||||
return "/" + "/".join(pathList)
|
||||
|
||||
def ReadMe():
|
||||
QtWidgets.QMessageBox.information(window, "提示", """1、目前只支持打包 X86 架构的 deb 包,暂未支持 arm;
|
||||
2、需要区分要打包的程序是绿色软件还是单文件安装包,两个对应的打包方式不相同;
|
||||
3、打包绿色软件时为尽可能减小程序体积,请将绿化后的程序(或程序文件夹)单独拷贝到干净的目录后再浏览选择主程序打包;
|
||||
4、打包详情:
|
||||
①调用 Wine:Deepin Wine6 Stable
|
||||
②调用 Helper:Spark Wine Helper
|
||||
③有卸载自动移除容器脚本""")
|
||||
|
||||
|
||||
class RunThread(QtCore.QThread):
|
||||
showLogText = QtCore.pyqtSignal(str)
|
||||
error = QtCore.pyqtSignal(str)
|
||||
info = QtCore.pyqtSignal(str)
|
||||
question = QtCore.pyqtSignal(str)
|
||||
disbledAll = QtCore.pyqtSignal(bool)
|
||||
cleanPressState = QtCore.pyqtSignal(bool)
|
||||
def RunCommand(self, command):
|
||||
res = subprocess.Popen([command], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
while res.poll() is None:
|
||||
try:
|
||||
text = res.stdout.readline().decode("utf8")
|
||||
except:
|
||||
text = ""
|
||||
self.showLogText.emit(text)
|
||||
print(text, end="")
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
def GetEXEVersion(self, exePath):
|
||||
versionPath = f"/tmp/wine-runner-exe-version-{random.randint(0, 1000)}.txt"
|
||||
self.RunCommand(f"deepin-wine6-stable '{programPath}/GetEXEVersion.exe' '{exePath}' '{versionPath}'")
|
||||
try:
|
||||
exeVersion = ReadTxt(versionPath).replace("\n", "")
|
||||
if exeVersion.replace(" ", "") == "":
|
||||
return "1.0.0"
|
||||
return exeVersion
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return "1.0.0"
|
||||
|
||||
def QuestionMsg(self, text):
|
||||
global questionStatus
|
||||
questionStatus = False
|
||||
self.question.emit(text)
|
||||
while not questionStatus:
|
||||
time.sleep(0.1)
|
||||
print(questionChoose)
|
||||
return questionChoose
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
self.disbledAll.emit(True)
|
||||
if not self.QuestionMsg("在此过程中,需要回答一系列的问题以进行打包,点击确定继续"):
|
||||
self.disbledAll.emit(False)
|
||||
return
|
||||
bottlePath = f"/tmp/deepin-wine-runner-bottle-{random.randint(0, 10000)}"
|
||||
# 清空容器以保证能正常使用
|
||||
if os.path.exists(bottlePath):
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}'")
|
||||
############# 后面将全部调用 deepin wine6 stable 进行操作
|
||||
exeName = os.path.basename(exePath.text())
|
||||
# 暂定
|
||||
packageName = xpinyin.Pinyin().get_pinyin(os.path.splitext(exeName)[0].replace(" ", ""), "").lower().replace(" ", "").replace("_", ".").replace("-", ".").replace("..", ".")
|
||||
|
||||
if " " in packageName:
|
||||
packageName = ""
|
||||
for i in os.path.splitext(exeName)[0].split(" "):
|
||||
packageName += xpinyin.Pinyin().get_pinyin(i).lower().replace(" ", "").replace("_", ".").replace("-", ".").replace("..", ".") + "."
|
||||
print(packageName)
|
||||
packageName = packageName[:-1]
|
||||
debPackageName = "com." + packageName + ".spark"
|
||||
debPackageVersion = "1.0.0"
|
||||
programIconPath = f"/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/{debPackageName}.png"
|
||||
debMaintainer = os.getlogin()
|
||||
debBuildPath = f"/tmp/deepin-wine-packager-builder-{debPackageName}-{random.randint(0, 1000)}"
|
||||
bottlePackagePath = f"{debBuildPath}/opt/apps/{debPackageName}/files/files.7z"
|
||||
desktopPath = get_desktop_path()
|
||||
############## 运行 EXE
|
||||
if self.QuestionMsg("请问此可执行文件是安装包还是绿色软件?是安装包请按 Yes,绿色软件按 No"):
|
||||
# 清空无益处的 lnk 文件
|
||||
lnkPath = f"{bottlePath}/drive_c/ProgramData/Microsoft/Windows/Start Menu/Programs"
|
||||
self.RunCommand(f"rm -rfv '{lnkPath}'")
|
||||
self.RunCommand(f"mkdir -pv '{bottlePath}'")
|
||||
self.RunCommand(f"chmod 777 -Rv '{bottlePath}'")
|
||||
# 禁止生成 .desktop 文件
|
||||
self.RunCommand(f"WINEPREFIX='{bottlePath}' deepin-wine6-stable 'reg' 'add' 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v winemenubuilder.exe '/f'")
|
||||
# 安装包
|
||||
self.info.emit("请在运行完安装程序后按下打包器主界面的“安装程序执行完成按钮”以进行下一步操作")
|
||||
global pressCompleteDownload
|
||||
pressCompleteDownload = False
|
||||
installCmpleteButton.setEnabled(True)
|
||||
self.RunCommand(f"WINEPREFIX='{bottlePath}' deepin-wine6-stable '{exePath.text()}' &") # 非堵塞线程
|
||||
|
||||
# 安装锁,锁解除后才可继续
|
||||
while not pressCompleteDownload:
|
||||
time.sleep(0.1)
|
||||
# 杀死容器内应用
|
||||
self.RunCommand(f"'{programPath}/kill.sh' '{os.path.basename(bottlePath)}'")
|
||||
# 识别 lnk
|
||||
lnkList = GetLnkDesktop(lnkPath)
|
||||
if len(lnkList) <= 0:
|
||||
self.error.emit("无法识别到任何 lnk 快捷方式")
|
||||
self.RunCommand(f"rm -rfv '{debBuildPath}' > /dev/null")
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}' > /dev/null")
|
||||
self.disbledAll.emit(False)
|
||||
return
|
||||
# 选择最优 lnk
|
||||
secondChooseList = []
|
||||
for k in lnkList:
|
||||
lnkPath = k[0].lower()
|
||||
lnkExePath = k[1].lower()
|
||||
if "卸载" in lnkPath or "uninstall" in lnkPath or "update" in lnkPath or "网页" in lnkPath or "websize" in lnkPath or not ".exe" in lnkExePath:
|
||||
continue
|
||||
secondChooseList.append(k)
|
||||
if len(secondChooseList) <= 0:
|
||||
secondChooseList = lnkList
|
||||
rightLnk = secondChooseList[0]
|
||||
miniLenge = len(rightLnk[1])
|
||||
for k in secondChooseList:
|
||||
# 择优选择路径最短一项
|
||||
if len(k[1]) < miniLenge:
|
||||
rightLnk = k
|
||||
miniLenge = len(rightLnk[1])
|
||||
debPackageName = "com." + xpinyin.Pinyin().get_pinyin(os.path.splitext(os.path.basename(rightLnk[0]))[0].replace(" ", "")).lower().replace("--", "-").replace(" ", "").replace("_", "-").replace("-", ".") + ".spark"
|
||||
programIconPath = f"/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/{debPackageName}.png"
|
||||
bottlePackagePath = f"{debBuildPath}/opt/apps/{debPackageName}/files/files.7z"
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/'")
|
||||
folderExePath = os.path.dirname(rightLnk[1].replace("\\", "/").replace("c:/", bottlePath))
|
||||
exePathInBottle = rightLnk[1]
|
||||
exeName = os.path.splitext(os.path.basename(folderExePath))[0]
|
||||
exePathInSystem = rightLnk[1].replace("\\", "/").replace("c:", f"{bottlePath}/drive_c")
|
||||
debPackageVersion = self.GetEXEVersion(exePathInSystem)
|
||||
cpNow = False
|
||||
for i in iconList:
|
||||
path = i[1].replace("wineBottonPath", bottlePath).lower()
|
||||
if path == exePathInSystem.lower():
|
||||
self.RunCommand(f"cp -rv '{programPath}/Icon/{i[0]}.svg' '{debBuildPath}/{programIconPath}'")
|
||||
exeName = i[0]
|
||||
cpNow = True
|
||||
break
|
||||
if not cpNow:
|
||||
self.RunCommand(f"'{programPath}/wrestool' '{UnUseUpperCharPath(exePathInSystem)}' -x -t 14 > '{debBuildPath}/{programIconPath}'")
|
||||
else:
|
||||
#/home/gfdgd_xi/Desktop/新建文件夹1/BeCyIconGrabber.exe
|
||||
# 绿色软件
|
||||
self.RunCommand(f"mkdir -pv '{bottlePath}'")
|
||||
self.RunCommand(f"chmod 777 -Rv '{bottlePath}'")
|
||||
self.RunCommand(f"WINEPREFIX='{bottlePath}' deepin-wine6-stable exit")
|
||||
folderExePath = os.path.dirname(exePath.text())
|
||||
exePathInBottle = f"c:/Program Files/{os.path.basename(folderExePath)}/{exeName}"
|
||||
exeName = os.path.splitext(os.path.basename(os.path.basename(exePath.text())))[0]
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/'")
|
||||
self.RunCommand(f"'{programPath}/wrestool' '{exePath.text()}' -x -t 14 > '{debBuildPath}/{programIconPath}'")
|
||||
# 拷贝文件到容器
|
||||
self.RunCommand(f"cp -rv '{folderExePath}' '{bottlePath}/drive_c/Program Files'")
|
||||
debPackageVersion = self.GetEXEVersion(exePath.text())
|
||||
debDescription = f"{exeName} By Deepin Wine 6 Stable And Build By Wine Runner Easy Packager"
|
||||
debDepends = "deepin-wine6-stable, spark-dwine-helper | store.spark-app.spark-dwine-helper, fonts-wqy-microhei, fonts-wqy-zenhei"
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/DEBIAN'")
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/files'")
|
||||
self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/applications'")
|
||||
#self.RunCommand(f"mkdir -pv '{debBuildPath}/opt/apps/{debPackageName}/entries/icons/hicolor/scalable/apps/'")
|
||||
############ 处理容器
|
||||
# 对用户目录进行处理
|
||||
os.chdir(bottlePath)
|
||||
self.RunCommand("sed -i \"s#$USER#@current_user@#\" ./*.reg")
|
||||
os.chdir(f"{bottlePath}/drive_c/users")
|
||||
# 如果缩放文件 scale.txt 存在,需要移除以便用户自行调节缩放设置
|
||||
if os.path.exists(f"{bottlePath}/scale.txt"):
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}/scale.txt'")
|
||||
# 删除因为脚本失误导致用户目录嵌套(如果存在)
|
||||
if os.path.exists(f"{bottlePath}/drive_c/users/@current_user@/@current_user@"):
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}/drive_c/users/@current_user@/@current_user@'")
|
||||
self.RunCommand(f"mv -fv '{os.getlogin()}' @current_user@")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/我的'*")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/My '*")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/Desktop'")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/Downloads'")
|
||||
self.RunCommand(f"rm -fv '{bottlePath}/drive_c/users/@current_user@/Templates'")
|
||||
########### 打包容器
|
||||
self.RunCommand(f"7z a '{bottlePackagePath}' '{bottlePath}/'*")
|
||||
########### 生成文件内容
|
||||
buildProgramSize = getFileFolderSize(debBuildPath) / 1000
|
||||
replaceMap = [
|
||||
["@@@Package@@@", debPackageName],
|
||||
["@@@Version@@@", debPackageVersion],
|
||||
["@@@Maintainer@@@", debMaintainer],
|
||||
["@@@Depends@@@", debDepends],
|
||||
["@@@Description@@@", debDescription],
|
||||
["@@@Installed-Size@@@", str(buildProgramSize)],
|
||||
["@@@Name@@@", exeName],
|
||||
["@@@EXEC_PATH@@@", exePathInBottle],
|
||||
["@@@Icon@@@", programIconPath]
|
||||
]
|
||||
debControl = ReplaceText(control, replaceMap)
|
||||
debPostrm = ReplaceText(postrm, replaceMap)
|
||||
debInfo = ReplaceText(info, replaceMap)
|
||||
debRunSh = ReplaceText(runsh, replaceMap)
|
||||
debDesktop = ReplaceText(desktopFile, replaceMap)
|
||||
########### 写入文件
|
||||
WriteTxt(f"{debBuildPath}/opt/apps/{debPackageName}/entries/applications/{debPackageName}.desktop", debDesktop)
|
||||
WriteTxt(f"{debBuildPath}/opt/apps/{debPackageName}/files/run.sh", debRunSh)
|
||||
WriteTxt(f"{debBuildPath}/opt/apps/{debPackageName}/info", debInfo)
|
||||
WriteTxt(f"{debBuildPath}/DEBIAN/control", debControl)
|
||||
WriteTxt(f"{debBuildPath}/DEBIAN/postrm", debPostrm)
|
||||
########### 赋值权限
|
||||
self.RunCommand(f"chmod -Rv 644 '{debBuildPath}/opt/apps/{debPackageName}/info'")
|
||||
self.RunCommand(f"chmod -Rv 0755 '{debBuildPath}/DEBIAN'")
|
||||
self.RunCommand(f"chmod -Rv 755 '{debBuildPath}/opt/apps/{debPackageName}/files/'*.sh")
|
||||
self.RunCommand(f"chmod -Rv 755 '{debBuildPath}/opt/apps/{debPackageName}/entries/applications/'*.desktop")
|
||||
########### 打包 deb
|
||||
print(debPackageVersion)
|
||||
self.RunCommand(f"dpkg -b '{debBuildPath}' '{desktopPath}/{debPackageName}_{debPackageVersion}_i386.deb'")
|
||||
self.info.emit("打包完成!")
|
||||
self.disbledAll.emit(False)
|
||||
########### 移除临时文件
|
||||
self.RunCommand(f"rm -rfv '{debBuildPath}' > /dev/null")
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}' > /dev/null")
|
||||
except:
|
||||
self.RunCommand(f"rm -rfv '{debBuildPath}' > /dev/null")
|
||||
self.RunCommand(f"rm -rfv '{bottlePath}' > /dev/null")
|
||||
# 若打包出现任何错误
|
||||
traceback.print_exc()
|
||||
self.error.emit(f"打包错误,详细详细如下:{traceback.format_exc()}")
|
||||
self.showLogText.emit(traceback.format_exc())
|
||||
self.disbledAll.emit(False)
|
||||
|
||||
#/home/gfdgd_xi/Downloads/XPcalc.exe
|
||||
def RunBuildThread():
|
||||
global buildThread
|
||||
buildThread = RunThread()
|
||||
buildThread.showLogText.connect(ShowText)
|
||||
buildThread.error.connect(ErrorMessage)
|
||||
buildThread.info.connect(InformationMessage)
|
||||
buildThread.question.connect(QuestionMessage)
|
||||
buildThread.disbledAll.connect(DisbledAndEnabledAll)
|
||||
buildThread.cleanPressState.connect(CleanPressCompleteDownloadState)
|
||||
logText.clear()
|
||||
buildThread.start()
|
||||
|
||||
pressCompleteDownload = False
|
||||
|
||||
def PressCompleteDownload():
|
||||
global pressCompleteDownload
|
||||
pressCompleteDownload = True
|
||||
installCmpleteButton.setDisabled(True)
|
||||
|
||||
def BrowserExe():
|
||||
filePath = QtWidgets.QFileDialog.getOpenFileName(window, "选择 exe", get_home(), "可执行文件(*.exe);;所有文件(*.*)")
|
||||
if filePath[0] != "" or filePath[0] != None:
|
||||
exePath.setText(filePath[0])
|
||||
|
||||
if __name__ == "__main__":
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
iconPath = "{}/deepin-wine-runner.svg".format(programPath)
|
||||
information = json.loads(ReadTxt(f"{programPath}/information.json"))
|
||||
iconListUnBuild = json.loads(ReadTxt(f"{programPath}/IconList.json"))[0]
|
||||
iconList = json.loads(ReadTxt(f"{programPath}/IconList.json"))[1]
|
||||
for i in iconListUnBuild:
|
||||
iconList.append(i)
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
version = information["Version"]
|
||||
window = QtWidgets.QMainWindow()
|
||||
widget = QtWidgets.QWidget()
|
||||
layout = QtWidgets.QGridLayout()
|
||||
exePath = QtWidgets.QLineEdit()
|
||||
browserExeButton = QtWidgets.QPushButton("浏览……")
|
||||
logText = QtWidgets.QTextBrowser()
|
||||
logText.setStyleSheet("""
|
||||
background-color: black;
|
||||
color: white;
|
||||
""")
|
||||
controlLayout = QtWidgets.QHBoxLayout()
|
||||
buildButton = QtWidgets.QPushButton("现在打包……")
|
||||
installCmpleteButton = QtWidgets.QPushButton("安装程序执行完成")
|
||||
helpButton = QtWidgets.QPushButton("帮助")
|
||||
browserExeButton.clicked.connect(BrowserExe)
|
||||
buildButton.clicked.connect(RunBuildThread)
|
||||
installCmpleteButton.clicked.connect(PressCompleteDownload)
|
||||
helpButton.clicked.connect(ReadMe)
|
||||
installCmpleteButton.setDisabled(True)
|
||||
controlLayout.addWidget(buildButton)
|
||||
controlLayout.addWidget(installCmpleteButton)
|
||||
controlLayout.addWidget(helpButton)
|
||||
layout.addWidget(QtWidgets.QLabel("选择 EXE:"), 0, 0)
|
||||
layout.addWidget(exePath, 0, 1)
|
||||
layout.addWidget(browserExeButton, 0, 2)
|
||||
layout.addLayout(controlLayout, 1, 1)
|
||||
layout.addWidget(logText, 2, 0, 1, 3)
|
||||
widget.setLayout(layout)
|
||||
window.setCentralWidget(widget)
|
||||
window.setWindowTitle(f"Wine 运行器 {version}——简易打包器")
|
||||
try:
|
||||
exePath.setText(sys.argv[1])
|
||||
except:
|
||||
pass
|
||||
window.resize(int(window.frameGeometry().width() * 1.2), int(window.frameGeometry().height() * 1.1))
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
||||
@@ -23,23 +23,24 @@ from PIL import Image
|
||||
import PyQt5.QtGui as QtGui
|
||||
import PyQt5.QtCore as QtCore
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
from trans import *
|
||||
|
||||
#################
|
||||
# 程序所需事件
|
||||
#################
|
||||
|
||||
def button1_cl():
|
||||
path = QtWidgets.QFileDialog.getExistingDirectory(widget, QtCore.QCoreApplication.translate("U", "选择 wine 容器"), f"{get_home()}/.deepinwine")
|
||||
path = QtWidgets.QFileDialog.getExistingDirectory(widget, transla.transe("U", "选择 wine 容器"), f"{get_home()}/.deepinwine")
|
||||
if path != "":
|
||||
e6_text.setText(path)
|
||||
|
||||
def button2_cl(number):
|
||||
path = QtWidgets.QFileDialog.getOpenFileName(widget, QtCore.QCoreApplication.translate("U", "选择图标文件"), get_home(), "PNG图标(*.png);;SVG图标(*.svg);;全部文件(*.*)")[0]
|
||||
path = QtWidgets.QFileDialog.getOpenFileName(widget, transla.transe("U", "选择图标文件"), get_home(), "PNG图标(*.png);;SVG图标(*.svg);;全部文件(*.*)")[0]
|
||||
if path != "":
|
||||
mapLink[number].setText(path)
|
||||
|
||||
def button4_cl():
|
||||
path = QtWidgets.QFileDialog.getSaveFileName(widget, QtCore.QCoreApplication.translate("U", "保存 deb 包"), get_home(), "deb 文件(*.deb);;所有文件(*.*)", "{}_{}_i386.deb".format(e1_text.text(), e2_text.text()))[0]
|
||||
path = QtWidgets.QFileDialog.getSaveFileName(widget, transla.transe("U", "保存 deb 包"), get_home(), "deb 文件(*.deb);;所有文件(*.*)", "{}_{}_i386.deb".format(e1_text.text(), e2_text.text()))[0]
|
||||
if path != "":
|
||||
e12_text.setText(path)
|
||||
|
||||
@@ -203,14 +204,41 @@ def Build7zButton_Clicked():
|
||||
QT.thread.start()
|
||||
|
||||
def make_deb(build=False):
|
||||
global bottleNameLock
|
||||
clean_textbox1_things()
|
||||
disabled_or_NORMAL_all(False)
|
||||
if e1_text.text() == "" or e2_text.text() == "" or e3_text.text() == "" or e4_text.text() == "" or e5_text.text() == "" or e6_text.text() == "" or e7_text.text() == "" or e8_text.text() == "" or e12_text.text() == "":
|
||||
badComplete = False
|
||||
# 规范检测
|
||||
if e1_text.text().lower() != e1_text.text():
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"包名 {e1_text.text()} 似乎不符合规范,可能会导致打包后的包无法投稿到应用商店,是否继续?\n可参考 deb 安装包打包标准", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
for i in range(len(iconUiList)):
|
||||
if os.path.splitext(iconUiList[i][4].text())[1] == ".ico":
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"图标 {iconUiList[i][4].text()} 似乎为 ico 格式,可能会导致打包后的程序在启动器的图标无法正常显示,是否继续?", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
if os.path.exists(iconUiList[i][0].text()) and not "c:" in iconUiList[i][0].text().lower():
|
||||
if not e6_text.text() in iconUiList[i][0].text():
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"路径 {iconUiList[i][0].text()} 似乎不符合规范且不位于容器内,可能会导致打包后的程序无法运行,是否继续?\n可参考 Windows 下的文件路径", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
if QtWidgets.QMessageBox.warning(window, "提示", f"路径 {iconUiList[i][0].text()} 似乎不符合规范,可能会导致打包后的程序无法运行,是否继续?\n可参考 Windows 下的文件路径", QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("用户已取消")
|
||||
return
|
||||
for k in [0, 3]:
|
||||
if iconUiList[i][k].text().replace(" ", "") == "":
|
||||
badComplete = True
|
||||
if badComplete or e1_text.text() == "" or e2_text.text() == "" or e3_text.text() == "" or e4_text.text() == "" or e5_text.text() == "" or e6_text.text() == "" or e7_text.text() == "" or e8_text.text() == "" or e12_text.text() == "":
|
||||
QtWidgets.QMessageBox.critical(widget, "错误", "必填信息没有填写完整,无法继续构建 deb 包")
|
||||
disabled_or_NORMAL_all(True)
|
||||
label13_text_change("必填信息没有填写完整,无法继续构建 deb 包")
|
||||
return
|
||||
if QtWidgets.QMessageBox.question(widget, QtCore.QCoreApplication.translate("U", "提示"), QtCore.QCoreApplication.translate("U", "打包将会改动现在选择的容器,是否继续?")) == QtWidgets.QMessageBox.No:
|
||||
if QtWidgets.QMessageBox.question(widget, transla.transe("U", "提示"), transla.transe("U", "打包将会改动现在选择的容器,是否继续?")) == QtWidgets.QMessageBox.No:
|
||||
disabled_or_NORMAL_all(True)
|
||||
return
|
||||
# 警告信息
|
||||
@@ -232,6 +260,7 @@ def make_deb(build=False):
|
||||
QT.thread.errorMsg.connect(ErrorMsg)
|
||||
QT.thread.infoMsg.connect(InfoMsg)
|
||||
QT.thread.disabled_or_NORMAL_all.connect(disabled_or_NORMAL_all)
|
||||
bottleNameLock = False
|
||||
QT.thread.start()
|
||||
#thread.start()
|
||||
|
||||
@@ -245,7 +274,6 @@ def ReplaceText(string: str, lists: list):
|
||||
return string
|
||||
|
||||
class make_deb_threading(QtCore.QThread):
|
||||
|
||||
signal = QtCore.pyqtSignal(str)
|
||||
label = QtCore.pyqtSignal(str)
|
||||
getSavePath = QtCore.pyqtSignal(str)
|
||||
@@ -1204,7 +1232,7 @@ fi
|
||||
# 获取文件大小
|
||||
################
|
||||
self.label.emit("正在计算文件大小……")
|
||||
size = int(getFileFolderSize(debPackagePath) / 1024)
|
||||
size = int(getFileFolderSize(debPackagePath) / 1000)
|
||||
################
|
||||
# 写入文本文档
|
||||
################
|
||||
@@ -1324,6 +1352,12 @@ StartupNotify=false
|
||||
self.label.emit("正在构建 deb 包……")
|
||||
self.run_command("bash -c 'dpkg -b \"{}\" \"{}\"'".format(debPackagePath, e12_text.text()))
|
||||
################
|
||||
# 删除临时文件
|
||||
################
|
||||
if not self.build:
|
||||
self.label.emit("正在删除临时文件……")
|
||||
self.run_command(f"rm -rfv '{debPackagePath}'")
|
||||
################
|
||||
# 完成构建
|
||||
################
|
||||
self.label.emit("完成构建!")
|
||||
@@ -1689,7 +1723,7 @@ mapLink = []
|
||||
|
||||
def AddTab():
|
||||
global mapLink
|
||||
button2 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "浏览……"))
|
||||
button2 = QtWidgets.QPushButton(transla.transe("U", "浏览……"))
|
||||
e7_text = QtWidgets.QLineEdit()
|
||||
e8_text = QtWidgets.QLineEdit()
|
||||
e9_text = QtWidgets.QLineEdit()
|
||||
@@ -1703,11 +1737,11 @@ def AddTab():
|
||||
mapLink.append(e9_text)
|
||||
#desktopIconTabLayout = QtWidgets.QGridLayout()
|
||||
desktopIconTabLayout = QtWidgets.QGridLayout()
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件的参数(选填):")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的图标(选填):")), 10, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "wine 容器里需要运行的可执行文件的参数:")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的图标:")), 10, 0, 1, 1)
|
||||
iconTab1.setLayout(desktopIconTabLayout)
|
||||
desktopIconTab.addTab(iconTab1, f"图标{desktopIconTab.count() + 1}")
|
||||
desktopIconTabLayout.addWidget(e7_text, 6, 1, 1, 1)
|
||||
@@ -1716,7 +1750,24 @@ def AddTab():
|
||||
desktopIconTabLayout.addWidget(e8_text, 9, 1, 1, 1)
|
||||
desktopIconTabLayout.addWidget(e9_text, 10, 1, 1, 1)
|
||||
desktopIconTabLayout.addWidget(button2, 10, 2, 1, 1)
|
||||
e8_text.setWhatsThis(transla.transe("U", """填写该软件的中文或英文名称。"""))
|
||||
e9_text.setWhatsThis(transla.transe("U", """图标只支持PNG格式和SVG格式,其他格式无法显示。"""))
|
||||
e15_text.setWhatsThis(transla.transe("U", "程序参数,如%u,一般不需要"))
|
||||
e7_text.setWhatsThis(transla.transe("U", """可执行文件的运行路径格式是“C:/XXX/XXX.exe”(不包含引号)"""))
|
||||
option1_text.setWhatsThis(transla.transe("U", """点击右侧的下拉箭头,选择该软件所属的软件分类即可,常见软件分类名称释义:
|
||||
Network=网络应用;
|
||||
Chat=即时通讯或社交沟通;
|
||||
Video=视频播放;
|
||||
Graphics=图形图像;
|
||||
Office=办公学习;
|
||||
Translation=阅读翻译;
|
||||
Development=软件开发;
|
||||
Utility=工具软件或其他应用。
|
||||
不明白英文的可以百度查询一下软件分类名称的意思。
|
||||
注意:此时选择的软件分类名称决定了该软件打包后再安装时会安装在启动器中的哪个软件分类目录中。"""))
|
||||
e7_text.textChanged.connect(ChangeTapTitle)
|
||||
e7_text.setPlaceholderText("例如 c:/Program Files/Tencent/QQ/Bin/QQ.exe")
|
||||
e9_text.setPlaceholderText(transla.transe("U", "支持 png 和 svg 格式,不支持 ico 格式"))
|
||||
iconUiList.append([e7_text, option1_text, e15_text, e8_text, e9_text])
|
||||
print(iconUiList)
|
||||
|
||||
@@ -1727,6 +1778,30 @@ def DelTab():
|
||||
del iconUiList[desktopIconTab.currentIndex()]
|
||||
desktopIconTab.removeTab(desktopIconTab.currentIndex())
|
||||
|
||||
def ChangeBottleName():
|
||||
global bottleNameLock
|
||||
global bottleNameChangeLock
|
||||
e1_text.setText(e1_text.text().replace(" ", ""))
|
||||
if bottleNameLock:
|
||||
return
|
||||
if os.path.basename(e6_text.text()) == ".wine" or e6_text.text() == "":
|
||||
bottleNameChangeLock = True
|
||||
e5_text.setText(e1_text.text())
|
||||
return
|
||||
bottleNameChangeLock = True
|
||||
e5_text.setText(os.path.basename(e6_text.text().replace(" ", "")))
|
||||
|
||||
def LockBottleName():
|
||||
global bottleNameLock
|
||||
if bottleNameChangeLock:
|
||||
return
|
||||
bottleNameLock = True
|
||||
|
||||
# 获取当前语言
|
||||
def get_now_lang()->"获取当前语言":
|
||||
return os.getenv('LANG')
|
||||
|
||||
bottleNameLock = False
|
||||
###############
|
||||
# 程序信息
|
||||
###############
|
||||
@@ -1758,18 +1833,27 @@ iconUiList = []
|
||||
iconPath = "{}/deepin-wine-runner.svg".format(programPath)
|
||||
information = json.loads(readtxt(f"{programPath}/information.json"))
|
||||
version = information["Version"]
|
||||
tips = """提示:
|
||||
# 语言载入
|
||||
if not get_now_lang() == "zh_CN.UTF-8":
|
||||
#trans = QtCore.QTranslator()
|
||||
#trans.load(f"{programPath}/LANG/deepin-wine-runner-en_US.qm")
|
||||
#app.installTranslator(trans)
|
||||
transla = Trans("en_US", f"{programPath}/trans/deepin-wine-packager.json")
|
||||
else:
|
||||
transla = Trans("zh_CN")
|
||||
tips = transla.transe("U", """提示:
|
||||
1、deb 打包软件包名要求:
|
||||
软件包名只能含有小写字母(a-z)、数字(0-9)、加号(+)和减号(-)、以及点号(.),软件包名最短长度两个字符;它必须以字母开头
|
||||
2、如果要填写路径,有“浏览……”按钮的是要填本计算机对应文件的路径,否则就是填写安装到其他计算机使用的路径
|
||||
3、输入 wine 的容器路径时最后面请不要输入“/”
|
||||
4、输入可执行文件的运行路径时是以“C:/XXX/XXX.exe”的格式进行输入,默认是以 C: 为开头,不用“\”做命令的分隔,而是用“/”
|
||||
5、.desktop 的图标只支持 PNG 格式和 SVG 格式,其他格式无法显示图标
|
||||
6、路径建议不要带空格,容易出问题"""
|
||||
6、路径建议不要带空格,容易出问题""")
|
||||
|
||||
###############
|
||||
# 窗口创建
|
||||
###############
|
||||
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
window = QtWidgets.QMainWindow()
|
||||
widget = QtWidgets.QWidget()
|
||||
@@ -1792,25 +1876,25 @@ e12_text = QtWidgets.QLineEdit()
|
||||
e15_text = QtWidgets.QLineEdit()
|
||||
label13_text = QtWidgets.QLabel("<p align='center'>当前 deb 打包情况:暂未打包</p>")
|
||||
option1_text = QtWidgets.QComboBox()
|
||||
button1 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "浏览……"))
|
||||
button2 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "浏览……"))
|
||||
button4 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "浏览……"))
|
||||
button1 = QtWidgets.QPushButton(transla.transe("U", "浏览……"))
|
||||
button2 = QtWidgets.QPushButton(transla.transe("U", "浏览……"))
|
||||
button4 = QtWidgets.QPushButton(transla.transe("U", "浏览……"))
|
||||
debControlFrame = QtWidgets.QHBoxLayout()
|
||||
button5 = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "打包……"))
|
||||
installDeb = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "安装打包完成的 deb……"))
|
||||
buildDebDir = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "根据填写内容打包模板"))
|
||||
build7z = QtWidgets.QPushButton(QtCore.QCoreApplication.translate("U", "打包容器 7z 包"))
|
||||
button5 = QtWidgets.QPushButton(transla.transe("U", "打包……"))
|
||||
installDeb = QtWidgets.QPushButton(transla.transe("U", "安装打包完成的 deb……"))
|
||||
buildDebDir = QtWidgets.QPushButton(transla.transe("U", "根据填写内容打包模板"))
|
||||
build7z = QtWidgets.QPushButton(transla.transe("U", "打包容器 7z 包"))
|
||||
debControlFrame.addWidget(button5)
|
||||
debControlFrame.addWidget(installDeb)
|
||||
rmBash = QtWidgets.QCheckBox(QtCore.QCoreApplication.translate("U", "设置卸载该 deb 后自动删除该容器"))
|
||||
cleanBottonByUOS = QtWidgets.QCheckBox(QtCore.QCoreApplication.translate("U", "使用统信 Wine 生态适配活动容器清理脚本"))
|
||||
rmBash = QtWidgets.QCheckBox(transla.transe("U", "设置卸载该 deb 后自动删除该容器"))
|
||||
cleanBottonByUOS = QtWidgets.QCheckBox(transla.transe("U", "使用统信 Wine 生态适配活动容器清理脚本"))
|
||||
debArch = QtWidgets.QComboBox()
|
||||
debArch.addItems(["i386", "arm64(box86+exagear)"])
|
||||
textbox1 = QtWidgets.QTextBrowser()
|
||||
option1_text.addItems(["Network", "Chat", "Audio", "Video", "Graphics", "Office", "Translation", "Development", "Utility"])
|
||||
option1_text.setCurrentText("Network")
|
||||
wineFrame = QtWidgets.QHBoxLayout()
|
||||
chooseWineHelperValue = QtWidgets.QCheckBox(QtCore.QCoreApplication.translate("U", "使用星火wine helper\n(如不勾选默认为deepin-wine-helper)"))
|
||||
chooseWineHelperValue = QtWidgets.QCheckBox(transla.transe("U", "使用星火wine helper\n(如不勾选默认为deepin-wine-helper)"))
|
||||
button1.clicked.connect(button1_cl)
|
||||
button2.clicked.connect(lambda: button2_cl(0))
|
||||
mapLink.append(e9_text)
|
||||
@@ -1820,19 +1904,23 @@ buildDebDir.clicked.connect(lambda: make_deb(True))
|
||||
build7z.clicked.connect(Build7zButton_Clicked)
|
||||
installDeb.clicked.connect(InstallDeb)
|
||||
wineFrame.addWidget(wineVersion)
|
||||
e1_text.textChanged.connect(ChangeBottleName)
|
||||
e5_text.textChanged.connect(LockBottleName)
|
||||
e6_text.textChanged.connect(ChangeBottleName)
|
||||
e7_text.textChanged.connect(ChangeTapTitle)
|
||||
# 创建控件
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的包名(※必填):")), 0, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的版本号(※必填):")), 1, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的说明(※必填):")), 2, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要打包的 deb 包的维护者(※必填):")), 3, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要解压的 wine 容器的容器名(※必填):")), 4, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要解压的 wine 容器(※必填):")), 5, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要打包的 deb 包的包名(※必填):")), 0, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 包的版本号(※必填):")), 1, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 包的说明(※必填):")), 2, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 包的维护者(※必填):")), 3, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要解压的 wine 容器的名称(※必填):")), 4, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要打包的 wine 容器路径(※必填):")), 5, 0, 1, 1)
|
||||
desktopIconTab = QtWidgets.QTabWidget()
|
||||
controlWidget = QtWidgets.QWidget()
|
||||
controlWidgetLayout = QtWidgets.QHBoxLayout()
|
||||
desktopIconTabAdd = QtWidgets.QPushButton("+")
|
||||
desktopIconTabDel = QtWidgets.QPushButton("-")
|
||||
desktopIconTabAdd.setWhatsThis("添加新图标")
|
||||
desktopIconTabDel.setWhatsThis("移除选中图标")
|
||||
controlWidgetLayout.addWidget(desktopIconTabAdd)
|
||||
controlWidgetLayout.addWidget(desktopIconTabDel)
|
||||
controlWidget.setLayout(controlWidgetLayout)
|
||||
@@ -1840,18 +1928,18 @@ desktopIconTabAdd.clicked.connect(AddTab)
|
||||
desktopIconTabDel.clicked.connect(DelTab)
|
||||
iconTab1 = QtWidgets.QWidget()
|
||||
desktopIconTabLayout = QtWidgets.QGridLayout()
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "wine 容器里需要运行的可执行文件的参数(选填):")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的图标(选填):")), 10, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "wine 容器里需要运行的可执行文件路径(※必填):")), 6, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的分类(※必填):")), 7, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "wine 容器里需要运行的可执行文件的参数:")), 8, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的名称(※必填):")), 9, 0, 1, 1)
|
||||
desktopIconTabLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的图标:")), 10, 0, 1, 1)
|
||||
iconTab1.setLayout(desktopIconTabLayout)
|
||||
#desktopIconTab.setTabPosition(QtWidgets.QTabWidget.East)
|
||||
desktopIconTab.addTab(iconTab1, "Defult")
|
||||
desktopIconTab.setCornerWidget(controlWidget)
|
||||
widgetLayout.addWidget(desktopIconTab, 8, 0, 6, 3)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "选择打包的 wine 版本(※必选):")), 6, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "打包 deb 的保存路径(※必填):")), 7, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "选择打包的 wine 版本(※必选):")), 6, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "打包 deb 的保存路径(※必填):")), 7, 0, 1, 1)
|
||||
widgetLayout.addWidget(e1_text, 0, 1, 1, 1)
|
||||
widgetLayout.addWidget(e2_text, 1, 1, 1, 1)
|
||||
widgetLayout.addWidget(e3_text, 2, 1, 1, 1)
|
||||
@@ -1874,30 +1962,30 @@ widgetLayout.addLayout(debControlFrame, 16, 1, 1, 1)
|
||||
widgetLayout.addWidget(label13_text, 17, 0, 1, 3)
|
||||
widgetLayout.addWidget(textbox1, 18, 0, 1, 3)
|
||||
# 高级功能
|
||||
moreSetting = QtWidgets.QGroupBox(QtCore.QCoreApplication.translate("U", "高级设置"))
|
||||
moreSetting = QtWidgets.QGroupBox(transla.transe("U", "高级设置"))
|
||||
debDepends = QtWidgets.QLineEdit()
|
||||
debRecommend = QtWidgets.QLineEdit()
|
||||
debDepends.setPlaceholderText(QtCore.QCoreApplication.translate("U", "deb 包的依赖(如无特殊需求默认即可)"))
|
||||
debDepends.setPlaceholderText(transla.transe("U", "deb 包的依赖(如无特殊需求默认即可)"))
|
||||
debDepends.setText("deepin-wine6-stable, deepin-wine-helper (>= 5.1.30-1), fonts-wqy-microhei, fonts-wqy-zenhei")
|
||||
debRecommend.setPlaceholderText(QtCore.QCoreApplication.translate("U", "deb 包的推荐依赖(非强制,一般默认即可)"))
|
||||
debRecommend.setPlaceholderText(transla.transe("U", "deb 包的推荐依赖(非强制,一般默认即可)"))
|
||||
moreSettingLayout = QtWidgets.QVBoxLayout()
|
||||
localWineVersion = QtWidgets.QComboBox()
|
||||
useInstallWineArch = QtWidgets.QComboBox()
|
||||
useInstallWineArch.addItems(["wine", "wine64"])
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "Wine 位数(只限本地需要打包集成的Wine):\n提示:32位的Wine不能使用64位容器")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "Wine 位数(只限本地需要打包集成的Wine):\n提示:32位的Wine不能使用64位容器")))
|
||||
#moreSettingLayout.addWidget(localWineVersion)
|
||||
moreSettingLayout.addWidget(useInstallWineArch)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "deb 包选项:")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 包选项:")))
|
||||
moreSettingLayout.addWidget(rmBash)
|
||||
moreSettingLayout.addWidget(cleanBottonByUOS)
|
||||
moreSettingLayout.addWidget(chooseWineHelperValue)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "deb 的依赖(强制,如无特殊需求默认即可):")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 的依赖(强制,如无特殊需求默认即可):")))
|
||||
moreSettingLayout.addWidget(debDepends)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "deb 的推荐依赖(非强制,一般默认即可):")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "deb 的推荐依赖(非强制,一般默认即可):")))
|
||||
moreSettingLayout.addWidget(debRecommend)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "要显示的 .desktop 文件的 MimeType:")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "要显示的 .desktop 文件的 MimeType:")))
|
||||
moreSettingLayout.addWidget(e10_text)
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(QtCore.QCoreApplication.translate("U", "打包 deb 架构:")))
|
||||
moreSettingLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "打包 deb 架构:")))
|
||||
moreSettingLayout.addWidget(debArch)
|
||||
moreSetting.setLayout(moreSettingLayout)
|
||||
widgetLayout.addWidget(moreSetting, 0, 3, 16, 2)
|
||||
@@ -1911,22 +1999,27 @@ e2_text.textChanged.connect(AutoPathSet)
|
||||
debArch.currentIndexChanged.connect(AutoPathSet)
|
||||
debArch.currentIndexChanged.connect(ChangeArchCombobox)
|
||||
e12_text.textChanged.connect(UserPathSet)
|
||||
e1_text.setPlaceholderText("例如 spark-deepin-wine-runner,不建议有大写字符")
|
||||
e2_text.setPlaceholderText(f"例如 {version}")
|
||||
e7_text.setPlaceholderText("例如 c:/Program Files/Tencent/QQ/Bin/QQ.exe")
|
||||
e9_text.setPlaceholderText(transla.transe("U", "支持 png 和 svg 格式,不支持 ico 格式"))
|
||||
# 菜单栏
|
||||
menu = window.menuBar()
|
||||
programmenu = menu.addMenu(QtCore.QCoreApplication.translate("U", "程序"))
|
||||
debMenu = menu.addMenu(QtCore.QCoreApplication.translate("U", "deb 包"))
|
||||
uploadSparkStore = menu.addMenu(QtCore.QCoreApplication.translate("U", "投稿到星火应用商店"))
|
||||
help = menu.addMenu(QtCore.QCoreApplication.translate("U", "帮助"))
|
||||
exit = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "退出程序"))
|
||||
debE = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "只读取 Control 信息"))
|
||||
debX = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "读取所有(需解包,时间较久)"))
|
||||
uploadSparkStoreWebsize = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "从网页端投稿"))
|
||||
programmenu = menu.addMenu(transla.transe("U", "程序"))
|
||||
debMenu = menu.addMenu(transla.transe("U", "deb 包"))
|
||||
uploadSparkStore = menu.addMenu(transla.transe("U", "投稿到星火应用商店"))
|
||||
help = menu.addMenu(transla.transe("U", "帮助"))
|
||||
exit = QtWidgets.QAction(transla.transe("U", "退出程序"))
|
||||
debE = QtWidgets.QAction(transla.transe("U", "只读取 Control 信息"))
|
||||
debX = QtWidgets.QAction(transla.transe("U", "读取所有(需解包,时间较久)"))
|
||||
uploadSparkStoreWebsize = QtWidgets.QAction(transla.transe("U", "从网页端投稿"))
|
||||
if os.path.exists("/opt/spark-store-submitter/bin/spark-store-submitter"):
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "使用投稿器投稿(推荐)"))
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(transla.transe("U", "使用投稿器投稿(推荐)"))
|
||||
else:
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "使用投稿器投稿(推荐,请先安装投稿器)"))
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(transla.transe("U", "使用投稿器投稿(推荐,请先安装投稿器)"))
|
||||
uploadSparkStoreProgram.setDisabled(True)
|
||||
tip = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "小提示"))
|
||||
tip = QtWidgets.QAction(transla.transe("U", "小提示"))
|
||||
getPdfHelp = QtWidgets.QAction(transla.transe("U", "Wine运行器和Wine打包器傻瓜式使用教程(小白专用)\nBy @雁舞白沙"))
|
||||
exit.triggered.connect(window.close)
|
||||
tip.triggered.connect(helps)
|
||||
programmenu.addAction(exit)
|
||||
@@ -1938,7 +2031,9 @@ debE.triggered.connect(lambda: ReadDeb(False))
|
||||
debX.triggered.connect(lambda: ReadDeb(True))
|
||||
uploadSparkStoreWebsize.triggered.connect(lambda: webbrowser.open_new_tab("https://upload.deepinos.org"))
|
||||
uploadSparkStoreProgram.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"/opt/spark-store-submitter/bin/spark-store-submitter '{e12_text.text()}'"]).start())
|
||||
getPdfHelp.triggered.connect(lambda: webbrowser.open_new_tab("https://bbs.deepin.org/post/246837"))
|
||||
help.addAction(tip)
|
||||
help.addAction(getPdfHelp)
|
||||
# 控件配置
|
||||
try:
|
||||
e6_text.setText(sys.argv[1].replace("~", get_home()))
|
||||
@@ -1955,6 +2050,44 @@ window.setCentralWidget(widget)
|
||||
window.setWindowTitle(f"wine 应用打包器 {version}")
|
||||
window.setWindowIcon(QtGui.QIcon(iconPath))
|
||||
window.resize(int(window.frameSize().width() * 2.1), int(window.frameSize().height()))
|
||||
e1_text.setWhatsThis("""com.XXX.deepin
|
||||
XXX指windows软件的英文名称,可以自定义名称,但最好是用软件解压安装后自动生成的英文名称,如:dingtalk。包名只能含有小写字母(a-z)、数字(0-9)、加号(+)和减号(-)、以及点号(.),软件包名最短长度为两个字符,且包名必须以字母开头。""")
|
||||
# 创建控件
|
||||
e2_text.setWhatsThis(transla.transe("U", """6.5.50(随便填写或填写该软件的windows版本的版本号,6.5.50只是示例)。"""))
|
||||
e3_text.setWhatsThis(transla.transe("U", """随便填写或使用该软件的windows版本的软件简介。"""))
|
||||
e4_text.setWhatsThis(transla.transe("U", """填写自己的网名,若是自用软件,不上架至应用商店,不进行后续维护,可随便填写。"""))
|
||||
e5_text.setWhatsThis(f"<p>解压容器到其它机器的容器名称,一般自动带出</p><p><img src='{programPath}/Icon/Screen/202211121646232464_image.png'></p>")
|
||||
e6_text.setWhatsThis(transla.transe("U", f"要打包的容器所在路径,也可以选择已经好打包的 7z 文件,一般自动带出"))
|
||||
e7_text.setWhatsThis("""可执行文件的运行路径格式是“C:/XXX/XXX.exe”(不包含引号)""")
|
||||
debArch.setWhatsThis(transla.transe("U", "选择生成 deb 包所对应的架构"))
|
||||
rmBash.setWhatsThis(transla.transe("U", "清理容器无用内容,一般建议勾选,最新版本默认勾选,如果有特殊需求(如容器内有 mono、gecko 等)建议取消勾选"))
|
||||
debDepends.setWhatsThis(transla.transe("U", "生成 deb 包所需的依赖,一般情况下默认即可"))
|
||||
debRecommend.setWhatsThis(transla.transe("U", "生成 deb 包的推荐依赖,一般情况下为空即可"))
|
||||
cleanBottonByUOS.setWhatsThis(transla.transe("U", "清理容器无用内容,一般建议勾选,最新版本默认勾选,如果有特殊需求(如容器内有 mono、gecko 等)建议取消勾选"))
|
||||
chooseWineHelperValue.setWhatsThis(transla.transe("U", "使用星火 dwine helper 替换 Deepin Wine Helper,投稿星火应用商店的话建议勾选,最新版本默认勾选(如果打包 arm 包将不会提供选择)"))
|
||||
option1_text.setWhatsThis("""点击右侧的下拉箭头,选择该软件所属的软件分类即可,常见软件分类名称释义:
|
||||
Network=网络应用;
|
||||
Chat=即时通讯或社交沟通;
|
||||
Video=视频播放;
|
||||
Graphics=图形图像;
|
||||
Office=办公学习;
|
||||
Translation=阅读翻译;
|
||||
Development=软件开发;
|
||||
Utility=工具软件或其他应用。
|
||||
不明白英文的可以百度查询一下软件分类名称的意思。
|
||||
注意:此时选择的软件分类名称决定了该软件打包后再安装时会安装在启动器中的哪个软件分类目录中。""")
|
||||
e8_text.setWhatsThis(transla.transe("U", """填写该软件的中文或英文名称。"""))
|
||||
e9_text.setWhatsThis(transla.transe("U", """图标只支持PNG格式和SVG格式,其他格式无法显示。"""))
|
||||
e10_text.setWhatsThis(transla.transe("U", "快捷方式的 MimeType 项,一般为空即可"))
|
||||
option1_text.setWhatsThis(transla.transe("U", "打包的 Wine 版本,根据实际情况选择(如果打包 arm 包将不会提供选择)"))
|
||||
e12_text.setWhatsThis(transla.transe("U", "打包出的 deb 生成的位置,一般自动生成"))
|
||||
e15_text.setWhatsThis(transla.transe("U", "程序参数,如%u,一般不需要"))
|
||||
build7z.setWhatsThis(transla.transe("U", "只打包容器生成 7z 包,不做其它操作"))
|
||||
buildDebDir.setWhatsThis(transla.transe("U", "构建 deb 包目录,但不打包成 deb"))
|
||||
textbox1.setWhatsThis(transla.transe("U", "查看打包过程中命令返回内容"))
|
||||
button5.setWhatsThis(transla.transe("U", "点击该按钮打包生成 deb"))
|
||||
installDeb.setWhatsThis(transla.transe("U", "调用默认的 deb 安装工具安装生成的 deb"))
|
||||
#window.setWindowFlag(QtGui.Qt)
|
||||
window.show()
|
||||
sys.exit(app.exec_())
|
||||
# Flag:解包只读control和解包全部读取
|
||||
7
demo/APICheck/main.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <iostream>
|
||||
#include <Windows.h>
|
||||
using namespace std;
|
||||
int main(){
|
||||
MessageBox(NULL, TEXT("a"), TEXT("A"), 32);
|
||||
return 0;
|
||||
}
|
||||
BIN
demo/APICheck/main.exe
Executable file
69
demo/GetExeVersion/main.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/**********************************
|
||||
* <20><><EFBFBD>ߣ<EFBFBD>gfdgd xi<78><69>Ϊʲô<CAB2><C3B4><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD>ܳ<EFBFBD>û<EFBFBD>Ͱ<EFBFBD><CDB0><EFBFBD><EFBFBD><EFBFBD>
|
||||
* <20>汾<EFBFBD><E6B1BE>2.5.0
|
||||
* <20><><EFBFBD><EFBFBD>ʱ<EFBFBD>䣺2022<32><32>11<31><31>27<32><37>
|
||||
* ֻ<><D6BB><EFBFBD><EFBFBD> Wine/Windows <20><><EFBFBD><EFBFBD>
|
||||
**********************************/
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <Windows.h>
|
||||
#pragma comment(lib, "version.lib");
|
||||
using namespace std;
|
||||
|
||||
// <20>ȿӡ<C8BF><D3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA> Dev CPP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD> -lversion
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC>汾<EFBFBD><E6B1BE>
|
||||
//@params:filename:<3A>ļ<EFBFBD><C4BC><EFBFBD>
|
||||
string GetFileVersion(LPCWSTR filename)
|
||||
{
|
||||
string asVer = "";
|
||||
VS_FIXEDFILEINFO *pVsInfo;
|
||||
unsigned int iFileInfoSize = sizeof(VS_FIXEDFILEINFO);
|
||||
int iVerInfoSize = GetFileVersionInfoSizeW(filename, NULL);
|
||||
if(iVerInfoSize != 0)
|
||||
{
|
||||
char *pBuf = NULL;
|
||||
|
||||
while(!pBuf)
|
||||
{
|
||||
pBuf = new char[iVerInfoSize];
|
||||
}
|
||||
if(GetFileVersionInfoW(filename, 0, iVerInfoSize, pBuf))
|
||||
{
|
||||
if(VerQueryValueA(pBuf, "\\", (void **)&pVsInfo, &iFileInfoSize))
|
||||
{
|
||||
sprintf(pBuf, "%d.%d.%d.%d", HIWORD(pVsInfo->dwFileVersionMS), LOWORD(pVsInfo->dwFileVersionMS), HIWORD(pVsInfo->dwFileVersionLS), LOWORD(pVsInfo->dwFileVersionLS));
|
||||
asVer = pBuf;
|
||||
}
|
||||
}
|
||||
delete pBuf;
|
||||
}
|
||||
return asVer;
|
||||
}
|
||||
|
||||
// <20><>ʽת<CABD><D7AA>
|
||||
LPWSTR ConvertCharToLPWSTR(const char* szString)
|
||||
{
|
||||
int dwLen = strlen(szString) + 1;
|
||||
int nwLen = MultiByteToWideChar(CP_ACP, 0, szString, dwLen, NULL, 0);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵij<CAB5><C4B3><EFBFBD>
|
||||
LPWSTR lpszPath = new WCHAR[dwLen];
|
||||
MultiByteToWideChar(CP_ACP, 0, szString, dwLen, lpszPath, nwLen);
|
||||
return lpszPath;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]){
|
||||
if (argc < 2){
|
||||
cout << "Unfull Option" << endl;
|
||||
return 1;
|
||||
}
|
||||
string version = GetFileVersion(ConvertCharToLPWSTR(argv[1]));
|
||||
cout << "Version: " << version << endl;
|
||||
if (argc == 3){
|
||||
cout << "Write To " << argv[2] << endl;
|
||||
// Ϊ<>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>д<EFBFBD><D0B4><EFBFBD>ı<EFBFBD><C4B1>ĵ<EFBFBD>
|
||||
ofstream write(argv[2], ios::trunc);
|
||||
write << version;
|
||||
write.close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
BIN
demo/GetExeVersion/main.exe
Executable file
0
dlls-arm.7z
Normal file → Executable file
@@ -1,9 +1,16 @@
|
||||
{
|
||||
"Version": "2.5.0",
|
||||
"Version": "3.0.0",
|
||||
"Thank": [
|
||||
"感谢 @豪 提供程序图标",
|
||||
"感谢 @鹤舞白沙 对程序文案进行优化以及编写《Wine运行器和Wine打包器傻瓜式使用教程(小白专用) 》",
|
||||
"感谢 @璀璨星空 提供的彩蛋图标",
|
||||
"感谢 @Bail 反馈的更新策略问题",
|
||||
"感谢 @白水 反馈的安装 exagear 后无法识别和调用 box86 的问题",
|
||||
"感谢 @汐光. 提供的翻译接口",
|
||||
"感谢 @鹤舞白沙 专门为小白用户编写的使用 Wine 运行器非基于生态适配脚本的程序打包教程",
|
||||
"感谢 @牦牛儿苗 进行了龙芯 3a5000 平台的测试与移植",
|
||||
"感谢 @雁舞白沙 优化了程序文案",
|
||||
"感谢 @豪 的程序测试和制作的非官方论坛 https://gfdgdxi.flarum.cloud/",
|
||||
"感谢 @豪 的程序测试和制作的论坛 https://gfdgdxi.flarum.cloud/",
|
||||
"感谢 @185******67 反馈的 2.4.0 无法打开 Visual Basic 组件安装工具的问题",
|
||||
"感谢 @shenmo 提供的 在打包器的 postrm 脚本添加 kill.sh、追加参数改为 --uri xxxxxxx、独立生成容器 7z 文件的功能",
|
||||
"感谢 @a2035274 @虚幻的早晨 https://bbs.deepin.org/post/238301",
|
||||
|
||||
1098
mainwindow.py
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"Version": "2.5.0"
|
||||
"Version": "3.0.0"
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import subprocess
|
||||
import PyQt5.QtGui as QtGui
|
||||
import PyQt5.QtCore as QtCore
|
||||
import PyQt5.QtWidgets as QtWidgets
|
||||
from trans import *
|
||||
|
||||
###################
|
||||
# 程序所需事件
|
||||
@@ -147,6 +148,10 @@ def NameChange(packageOrBotton: int):
|
||||
elif packageOrBotton == 1 and bottonName.text() != packageName.text():
|
||||
lockB = True
|
||||
|
||||
# 获取当前语言
|
||||
def get_now_lang()->"获取当前语言":
|
||||
return os.getenv('LANG')
|
||||
|
||||
###########################
|
||||
# 程序信息
|
||||
###########################
|
||||
@@ -154,7 +159,12 @@ programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
information = json.loads(readtxt(f"{programPath}/information.json"))
|
||||
version = information["Version"]
|
||||
iconPath = "{}/deepin-wine-runner.svg".format(programPath)
|
||||
tips = """第一个文本框是应用程序中文名
|
||||
# 语言载入
|
||||
if not get_now_lang() == "zh_CN.UTF-8":
|
||||
transla = Trans("en_US", f"{programPath}/trans/packager.json")
|
||||
else:
|
||||
transla = Trans("zh_CN")
|
||||
tips = transla.transe("U", """第一个文本框是应用程序中文名
|
||||
第二个文本框是应用程序英文名
|
||||
第三个文本框是最终生成的包的描述
|
||||
第四个选择框是desktop文件中的分类
|
||||
@@ -164,7 +174,7 @@ desktop文件中StartupWMClass字段。用于让桌面组件将窗口类名与de
|
||||
第六个输入框是最终生成的包的包名,包名的命名规则以deepin开头,加官网域名(需要前后对调位置),如还不能区分再加上应用名
|
||||
最后一个是最终生成的包的版本号,版本号命名规则:应用版本号+deepin+数字
|
||||
提示:包名和容器名相同,无法设置为不相同,如果需要设置为不相同,需要用另一个非基于生态适配脚本的打包器
|
||||
"""
|
||||
""")
|
||||
|
||||
###########################
|
||||
# 窗口创建
|
||||
@@ -186,22 +196,22 @@ packageName = QtWidgets.QLineEdit()
|
||||
bottonName = QtWidgets.QLineEdit()
|
||||
versionName = QtWidgets.QLineEdit()
|
||||
controlFrame = QtWidgets.QHBoxLayout()
|
||||
buildDeb = QtWidgets.QPushButton("打包")
|
||||
debPath = QtWidgets.QPushButton("deb 包生成目录")
|
||||
buildDeb = QtWidgets.QPushButton(transla.transe("U", "打包"))
|
||||
debPath = QtWidgets.QPushButton(transla.transe("U", "deb 包生成目录"))
|
||||
buildDeb.setSizePolicy(size)
|
||||
debPath.setSizePolicy(size)
|
||||
commandReturn = QtWidgets.QTextBrowser()
|
||||
typeName.addItems(["Network", "Chat", "Audio", "Video", "Graphics", "Office", "Translation", "Development", "Utility", "System"])
|
||||
controlFrame.addWidget(buildDeb)
|
||||
controlFrame.addWidget(debPath)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel("程序中文名:"), 0, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel("程序英文名:"), 1, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel("包描述:"), 2, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel("程序分类:"), 3, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel("程序在 Wine 容器的位置:"), 4, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel("包名:"), 5, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel("容器名:"), 6, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel("版本号:"), 7, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "程序中文名:")), 0, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "程序英文名:")), 1, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "包描述:")), 2, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "程序分类:")), 3, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "程序在 Wine 容器的位置:")), 4, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "包名:")), 5, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "容器名:")), 6, 0, 1, 1)
|
||||
widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "版本号:")), 7, 0, 1, 1)
|
||||
widgetLayout.addWidget(chineseName, 0, 1, 1, 1)
|
||||
widgetLayout.addWidget(englishName, 1, 1, 1, 1)
|
||||
widgetLayout.addWidget(debDescription, 2, 1, 1, 1)
|
||||
@@ -221,27 +231,47 @@ window.setCentralWidget(widget)
|
||||
window.resize(int(window.frameGeometry().width() * 1.5), int(window.frameGeometry().height()))
|
||||
window.setWindowIcon(QtGui.QIcon(iconPath))
|
||||
menu = window.menuBar()
|
||||
programMenu = menu.addMenu("程序")
|
||||
exit = QtWidgets.QAction("退出")
|
||||
programMenu = menu.addMenu(transla.transe("U", "程序"))
|
||||
exit = QtWidgets.QAction(transla.transe("U", "退出"))
|
||||
exit.triggered.connect(window.close)
|
||||
uploadSparkStore = menu.addMenu(QtCore.QCoreApplication.translate("U", "投稿到星火应用商店"))
|
||||
uploadSparkStoreWebsize = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "从网页端投稿"))
|
||||
uploadSparkStore = menu.addMenu(transla.transe("U", "投稿到星火应用商店"))
|
||||
uploadSparkStoreWebsize = QtWidgets.QAction(transla.transe("U", "从网页端投稿"))
|
||||
if os.path.exists("/opt/spark-store-submitter/bin/spark-store-submitter"):
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "使用投稿器投稿(推荐)"))
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(transla.transe("U", "使用投稿器投稿(推荐)"))
|
||||
else:
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(QtCore.QCoreApplication.translate("U", "使用投稿器投稿(推荐,请先安装投稿器)"))
|
||||
uploadSparkStoreProgram = QtWidgets.QAction(transla.transe("U", "使用投稿器投稿(推荐,请先安装投稿器)"))
|
||||
uploadSparkStoreProgram.setDisabled(True)
|
||||
uploadSparkStore.addAction(uploadSparkStoreProgram)
|
||||
uploadSparkStore.addAction(uploadSparkStoreWebsize)
|
||||
uploadSparkStoreWebsize.triggered.connect(lambda: webbrowser.open_new_tab("https://upload.deepinos.org"))
|
||||
uploadSparkStoreProgram.triggered.connect(lambda: threading.Thread(target=os.system, args=["/opt/spark-store-submitter/bin/spark-store-submitter"]).start())
|
||||
helpMenu = menu.addMenu("帮助")
|
||||
help = QtWidgets.QAction("帮助")
|
||||
helpMenu = menu.addMenu(transla.transe("U", "帮助"))
|
||||
help = QtWidgets.QAction(transla.transe("U", "帮助"))
|
||||
help.triggered.connect(ShowHelp)
|
||||
helpMenu.addAction(help)
|
||||
programMenu.addAction(exit)
|
||||
print(iconPath)
|
||||
window.show()
|
||||
chineseName.setWhatsThis(transla.transe("U", "应用程序中文名"))
|
||||
englishName.setWhatsThis(transla.transe("U", "应用程序英文名"))
|
||||
debDescription.setWhatsThis(transla.transe("U", "最终生成的包的描述"))
|
||||
typeName.setWhatsThis(transla.transe("U", """点击右侧的下拉箭头,选择该软件所属的软件分类即可,常见软件分类名称释义:
|
||||
Network=网络应用;
|
||||
Chat=即时通讯或社交沟通;
|
||||
Video=视频播放;
|
||||
Graphics=图形图像;
|
||||
Office=办公学习;
|
||||
Translation=阅读翻译;
|
||||
Development=软件开发;
|
||||
Utility=工具软件或其他应用。
|
||||
不明白英文的可以百度查询一下软件分类名称的意思。
|
||||
注意:此时选择的软件分类名称决定了该软件打包后再安装时会安装在启动器中的哪个软件分类目录中。"""))
|
||||
exePath.setWhatsThis("""程序在 Wine 容器的位置,以 c:\\XXX 的形式,盘符必须小写,用反斜杠,如果路径带用户名的话会自动替换为$USER
|
||||
而 StartupWMClass 字段将会由程序自动生成,作用如下:
|
||||
desktop文件中StartupWMClass字段。用于让桌面组件将窗口类名与desktop文件相对应。这个值为实际运行的主程序EXE的文件名,wine/crossover在程序运行后会将文件名设置为窗口类名""")
|
||||
packageName.setWhatsThis(transla.transe("U", "最终生成的包的包名,包名的命名规则以deepin开头,加官网域名(需要前后对调位置),如还不能区分再加上应用名"))
|
||||
bottonName.setWhatsThis(transla.transe("U", "容器名"))
|
||||
versionName.setWhatsThis(transla.transe("U", "最终生成的包的版本号,版本号命名规则:应用版本号+deepin+数字"))
|
||||
window.setWindowTitle(f"Wine 打包器 {version}——基于统信 Wine 生态活动打包脚本制作")
|
||||
windowFrameInputValueList = [
|
||||
chineseName,
|
||||
|
||||
53
package-script/trans/__init__.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
import traceback
|
||||
|
||||
class Trans():
|
||||
isTrans = False
|
||||
unCloudTrans = True
|
||||
word = {}
|
||||
fileName = ""
|
||||
|
||||
def __init__(self, lang="zh_CN", fileName=f"trans.json") -> None:
|
||||
self.fileName = fileName
|
||||
self.isTrans = (lang != "zh_CN")
|
||||
if self.isTrans:
|
||||
try:
|
||||
if not os.path.exists(fileName):
|
||||
with open(fileName, "w") as file:
|
||||
file.write("{}")
|
||||
with open(fileName, "r") as file:
|
||||
self.word = json.loads(file.read())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.isTrans = False
|
||||
|
||||
def transe(self, temp, text) -> str:
|
||||
if not self.isTrans:
|
||||
return text
|
||||
try:
|
||||
return self.word[text]
|
||||
except:
|
||||
if self.unCloudTrans:
|
||||
return text
|
||||
# 机翻
|
||||
data = { 'doctype': 'json', 'type': 'auto','i': text}
|
||||
jsonReturn = requests.post("http://fanyi.youdao.com/translate", data=data).json()["translateResult"]
|
||||
transText = ""
|
||||
for i in jsonReturn:
|
||||
print(i[0])
|
||||
transText += f'{i[0]["tgt"]}\n'
|
||||
if "\n" in text:
|
||||
transText = transText.replace("\n\n", "\n")[:-1]
|
||||
else:
|
||||
transText = transText[:-1]
|
||||
self.word[text] = transText
|
||||
try:
|
||||
with open(self.fileName, "w") as file:
|
||||
file.write(json.dumps(self.word, ensure_ascii=False))
|
||||
except:
|
||||
traceback.print_exc()
|
||||
print(f"{text}=>{transText}")
|
||||
return transText
|
||||
BIN
package-script/trans/__pycache__/__init__.cpython-37.pyc
Normal file
1
package-script/trans/packager.json
Normal file
@@ -0,0 +1 @@
|
||||
{"第一个文本框是应用程序中文名\n第二个文本框是应用程序英文名\n第三个文本框是最终生成的包的描述\n第四个选择框是desktop文件中的分类\n第五个输入框是程序在 Wine 容器的位置,以 c:\\XXX 的形式,盘符必须小写,用反斜杠,如果路径带用户名的话会自动替换为$USER\n而 StartupWMClass 字段将会由程序自动生成,作用如下:\ndesktop文件中StartupWMClass字段。用于让桌面组件将窗口类名与desktop文件相对应。这个值为实际运行的主程序EXE的文件名,wine/crossover在程序运行后会将文件名设置为窗口类名\n第六个输入框是最终生成的包的包名,包名的命名规则以deepin开头,加官网域名(需要前后对调位置),如还不能区分再加上应用名\n最后一个是最终生成的包的版本号,版本号命名规则:应用版本号+deepin+数字\n提示:包名和容器名相同,无法设置为不相同,如果需要设置为不相同,需要用另一个非基于生态适配脚本的打包器\n": "The first is the application Chinese name text box\nThe second text box is application English name\nThe third one is a text box that ultimately make the description of the package\nA fourth option box is a classification in the desktop file\nThe fifth input box is program in Wine vessel position, to the c: \\ XXX's form, the drive must be lowercase, with a backslash, if the path with the USER name will be automatically replaced with $USER\nWhile StartupWMClass fields will be automatically generated by the program, function is as follows:\nThe desktop file StartupWMClass fields.\nThe sixth input box is the package name of the resulting package, the package name begin with deepin naming rules, plus the website domain name (need change over) before and after, if can't distinguish between plus application name\nThe last one is the resulting package version number, version number naming rules: application version number + deepin + number\nTip: package name is the same as the container name, cannot be set to different, if you need to set up for different, need to use another based on the ecological adaptation of the script package", "投稿到星火应用商店": "Contribute to spark the app store", "从网页端投稿": "From the web", "使用投稿器投稿(推荐)": "Use contribute contributes (recommended)", "打包": "packaging", "deb 包生成目录": "Deb package generated directory", "程序中文名:": "Program name:", "程序英文名:": "English name:", "包描述:": "Package description:", "程序分类:": "Program classification:", "程序在 Wine 容器的位置:": "The location of the program in Wine container:", "包名:": "Package name:", "容器名:": "Vessel name:", "版本号:": "The version number:", "程序": "The program", "退出": "exit", "帮助": "help", "应用程序中文名": "The application name", "应用程序英文名": "The application name in English", "最终生成的包的描述": "The resulting package description", "点击右侧的下拉箭头,选择该软件所属的软件分类即可,常见软件分类名称释义:\nNetwork=网络应用;\nChat=即时通讯或社交沟通;\nVideo=视频播放;\nGraphics=图形图像;\nOffice=办公学习;\nTranslation=阅读翻译;\nDevelopment=软件开发;\nUtility=工具软件或其他应用。\n不明白英文的可以百度查询一下软件分类名称的意思。\n注意:此时选择的软件分类名称决定了该软件打包后再安装时会安装在启动器中的哪个软件分类目录中。": "Click on the right side of the drop-down menu, select the software's classification, the classification of common software name definition:\nThe Network = web applications;\nChat = instant messaging or social communication;\nVideo = Video playback;\nGraphics = Graphics;\nOffice = Office learning;\nTranslation = read Translation;\nDevelopment = software Development;\nThe Utility = tool software or other applications.\nDon't understand English can baidu query the meaning of classification of software name.\nNote: the choice of software classification name determines the software package installs again after installation in the starter which classification of software directory.", "最终生成的包的包名,包名的命名规则以deepin开头,加官网域名(需要前后对调位置),如还不能区分再加上应用名": "The package name of the resulting package, the package name begin with deepin naming rules, plus (need change over) before and after the website domain name, such as can not distinguish between plus application name", "容器名": "Container name", "最终生成的包的版本号,版本号命名规则:应用版本号+deepin+数字": "The resulting package version number, version number naming rules: application version number + deepin + number"}
|
||||
@@ -7,32 +7,21 @@ with open("/var/lib/dpkg/status", "r") as i:
|
||||
if unConnect:
|
||||
print("52专版,将会无法连接服务器")
|
||||
|
||||
badUrl = [
|
||||
"http://120.25.153.144",
|
||||
"https://304626p927.goho.co",
|
||||
"https://30x46269h2.goho.co",
|
||||
"http://gfdgdxi.msns.cn"
|
||||
]
|
||||
|
||||
class Respon:
|
||||
text = ""
|
||||
|
||||
def get(url, timeout=None): # -> requests.Response:
|
||||
if unConnect:
|
||||
# 筛选 Url,只有特定的 url 才会被拦截
|
||||
for i in badUrl:
|
||||
if i in url:
|
||||
raise Exception("52专版不支持连接作者服务器")
|
||||
# 全部 Url 都拦截
|
||||
raise Exception("52专版不支持连接服务器")
|
||||
if timeout == None:
|
||||
return requests.get(url)
|
||||
return requests.get(url, timeout=timeout)
|
||||
|
||||
def post(url, data, timeout=None):
|
||||
if unConnect:
|
||||
# 筛选 Url,只有特定的 url 才会被拦截
|
||||
for i in badUrl:
|
||||
if i in url:
|
||||
raise Exception("52专版不支持连接作者服务器")
|
||||
# 全部 Url 都拦截
|
||||
raise Exception("52专版不支持连接服务器")
|
||||
if timeout == None:
|
||||
return requests.post(url, data)
|
||||
return requests.post(url, data, timeout=timeout)
|
||||
BIN
req/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
req/__pycache__/__init__.cpython-36.pyc
Normal file
53
trans/__init__.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
import traceback
|
||||
|
||||
class Trans():
|
||||
isTrans = False
|
||||
unCloudTrans = True
|
||||
word = {}
|
||||
fileName = ""
|
||||
|
||||
def __init__(self, lang="zh_CN", fileName=f"trans.json") -> None:
|
||||
self.fileName = fileName
|
||||
self.isTrans = (lang != "zh_CN")
|
||||
if self.isTrans:
|
||||
try:
|
||||
if not os.path.exists(fileName):
|
||||
with open(fileName, "w") as file:
|
||||
file.write("{}")
|
||||
with open(fileName, "r") as file:
|
||||
self.word = json.loads(file.read())
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.isTrans = False
|
||||
|
||||
def transe(self, temp, text) -> str:
|
||||
if not self.isTrans:
|
||||
return text
|
||||
try:
|
||||
return self.word[text].replace("(", "(").replace(")", ")")
|
||||
except:
|
||||
if self.unCloudTrans:
|
||||
return text
|
||||
# 机翻
|
||||
data = { 'doctype': 'json', 'type': 'auto','i': text}
|
||||
jsonReturn = requests.post("http://fanyi.youdao.com/translate", data=data).json()["translateResult"]
|
||||
transText = ""
|
||||
for i in jsonReturn:
|
||||
print(i[0])
|
||||
transText += f'{i[0]["tgt"]}\n'
|
||||
if "\n" in text:
|
||||
transText = transText.replace("\n\n", "\n")[:-1]
|
||||
else:
|
||||
transText = transText[:-1]
|
||||
self.word[text] = transText.replace("(", "(").replace(")", ")")
|
||||
try:
|
||||
with open(self.fileName, "w") as file:
|
||||
file.write(json.dumps(self.word, ensure_ascii=False))
|
||||
except:
|
||||
traceback.print_exc()
|
||||
print(f"{text}=>{transText}")
|
||||
return transText
|
||||