#!/usr/bin/env python3 # 使用系统默认的 python3 运行 ################################################################################################################# # 作者:gfdgd xi、为什么您不喜欢熊出没和阿布呢 # 版本:3.0.0 # 更新时间:2022年12月10日 # 感谢:感谢 wine、deepin-wine 以及星火团队,提供了 wine、deepin-wine、spark-wine-devel 给大家使用,让我能做这个程序 # 基于 Python3 的 PyQt5 构建 ################################################################################################################# ################# # 引入所需的库 ################# import os import sys import time import json import random import base64 import shutil import hashlib import platform import threading import traceback import webbrowser import subprocess import req as requests import urllib.parse as parse import PyQt5.QtGui as QtGui import PyQt5.QtCore as QtCore import PyQt5.QtWidgets as QtWidgets try: import PyQt5.QtWebEngineWidgets as QtWebEngineWidgets bad = False except: bad = True from trans import * from Model import * def PythonLower(): app = QtWidgets.QApplication(sys.argv) QtWidgets.QMessageBox.critical(None, "错误", "Python 至少需要 3.6 及以上版本,目前版本:" + platform.python_version() + "") sys.exit(1) # Python 版本检测,因为 f-string 格式化要至少 Python 3.6 及以上的版本,所以需要检测 # 判断主版本号 if sys.version_info[0] < 3: PythonLower() if sys.version_info[1] < 6: PythonLower() ################### # 程序所需事件 ################### # 打开程序官网 def OpenProgramURL(): webbrowser.open_new_tab(programUrl) # 读取文本文档 def readtxt(path): f = open(path, "r") # 设置文件对象 str = f.read() # 获取内容 f.close() # 关闭文本对象 return str # 返回结果 # 写入文本文档 def write_txt(path, things): file = open(path, 'w', encoding='UTF-8') # 设置文件对象 file.write(things) # 写入文本 file.close() # 关闭文本对象 # 获取用户桌面目录 def get_desktop_path(): 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 # 返回目录 # 获取用户主目录 def get_home(): return os.path.expanduser('~') # 第一个浏览按钮事件 def liulanbutton(): path = QtWidgets.QFileDialog.getExistingDirectory(widget, "选择 wine 容器", json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/WineBotton.json"))["path"]) if path != "" and path != "()": e1.setEditText(path) write_txt(get_home() + "/.config/deepin-wine-runner/WineBotton.json", json.dumps({"path": path})) # 写入配置文件 # 第二个浏览按钮事件 def liulanexebutton(): path = QtWidgets.QFileDialog.getOpenFileName(widget, "选择 exe 可执行文件", json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/FindExe.json"))["path"], "exe 可执行文件(*.exe);;MSI 文件(*.msi);;所有文件(*.*)") if path != "" and path != "()": e2.setEditText(path[0]) # 显示路径 write_txt(get_home() + "/.config/deepin-wine-runner/FindExe.json", json.dumps({"path": os.path.dirname(path[0])})) # 写入配置文件 run = None # 使用多线程运行可执行文件 def runexebutton(self): global run DisableButton(True) if not CheckProgramIsInstall(wine[o1.currentText()]) and not o1.currentText() in untipsWine: if QtWidgets.QMessageBox.question(widget, "提示", "检查到您未安装这个 wine,是否继续使用这个 wine 运行?") == QtWidgets.QMessageBox.No: DisableButton(False) return if e2.currentText() == "": # 判断文本框是否有内容 QtWidgets.QMessageBox.information(widget, "提示", "没有填写需要使用的 exe 应用") DisableButton(False) return returnText.setText("") run = Runexebutton_threading() run.signal.connect(QT.ShowWineReturn) run.showHistory.connect(QT.ShowHistory) run.start() class QT: message = None def ShowWineReturn(things): returnText.insertPlainText(things) def ShowHistory(temp): e1.clear() e2.clear() e2.addItems(wineBottonHistory) e2.setEditText(wineBottonHistory[-1]) e1.addItems(findExeHistory) e1.setEditText(findExeHistory[-1]) repairList = [] # Flag: 日志推断解决方案功能 class LogChecking(): def ShowWindow(): global logThread global logWindow global questionList global repairButton logWindow = QtWidgets.QWidget() logWindowLayout = QtWidgets.QGridLayout() questionList = QtWidgets.QListView() repairButton = QtWidgets.QPushButton("一键修复") repairButton.setDisabled(True) repairButton.clicked.connect(LogChecking.RepairButton) nmodel = QtGui.QStandardItemModel(window) item = QtGui.QStandardItem("正在分析中……") questionList.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers) nmodel.appendRow(item) questionList.setModel(nmodel) logWindowLayout.addWidget(questionList, 0, 0, 3, 1) logWindowLayout.addWidget(repairButton, 0, 2, 1, 1) logWindow.setWindowTitle("分析日志") logWindow.setLayout(logWindowLayout) logThread = LogThreading() logThread.done.connect(LogChecking.Show) logThread.start() logWindow.setWindowIcon(QtGui.QIcon(f"{programPath}/deepin-wine-runner.svg")) logWindow.resize(int(logWindow.frameGeometry().width() * 1.2), int(logWindow.frameGeometry().height() * 1.2)) logWindow.show() def RepairButton(): index = questionList.currentIndex().row() lists = questionMap[index] print(f"{programPath}/CheckDLL/bash/{lists[1].lower()}.sh") if lists[0] == 1 and os.path.exists(f"{programPath}/CheckDLL/bash/{lists[1].lower()}.sh"): OpenTerminal(f"'{programPath}/AutoShell/main.py' '{programPath}/CheckDLL/bash/{lists[1].lower()}.sh'") return if lists[0] == 2: QtWidgets.QMessageBox.information(logWindow, "修复方法", "切换其它 Wine") return if lists[0] == 4: QtWidgets.QMessageBox.information(logWindow, "修复方法", "如是 Deepin Wine 可以尝试切换 WineHQ,\n并且取消勾选运行器主页面菜单栏“程序”=>“设置Wine”,取消勾选“屏蔽 Wine 默认 Mono 和 Gecko 安装器”\n然后尝试在菜单栏的“Wine”=>“在指定 Wine、容器安装组件”=>“在指定 Wine、容器安装 Gecko”来安装 Gecko") return if lists[0] == 5: InstallMonoGecko("mono") return QtWidgets.QMessageBox.critical(logWindow, "错误", "无法修复该问题") def Show(lists): global questionMap nmodel = QtGui.QStandardItemModel(window) disbledButton = False print(lists) if not len(lists): nmodel.appendRow(QtGui.QStandardItem(f"√ 无法分析到错误")) disbledButton = True for i in lists: if i[0] == 0: nmodel.appendRow(QtGui.QStandardItem(f"√ 无法分析到错误")) disbledButton = True break if i[0] == 1: nmodel.appendRow(QtGui.QStandardItem(f"× 无法调用 Dll:{i[1]}")) if i[0] == 2: nmodel.appendRow(QtGui.QStandardItem(f"× 尝试用 Mono 运行非 .net 应用 {i[1]}?")) if i[0] == 3: nmodel.appendRow(QtGui.QStandardItem(f"! 无法加载 Gecko,是被禁用或未安装?")) if i[0] == 4: nmodel.appendRow(QtGui.QStandardItem(f"× 无法更新 Wine 容器版本,是否还有 Wine 程序运行?")) if i[0] == 5: nmodel.appendRow(QtGui.QStandardItem(f"× Mono 禁用/未安装")) questionMap = lists[:] repairButton.setDisabled(disbledButton) questionList.setModel(nmodel) class LogThreading(QtCore.QThread): done = QtCore.pyqtSignal(list) def __init__(self): super().__init__() def run(self): global logText repairList = [] logText = returnText.toPlainText() print(logText.splitlines()) for i in logText.splitlines(): print(i) checkingText = i.lower() if "err:module:import_dll Library".lower() in checkingText: # Lose Dll repairList.append([1, i[i.index("Library") + 8: i.index("(")].strip()]) continue if "err:module:fixup_imports_ilonly".lower() in checkingText: # Lose Dll repairList.append([1, i[i.index("_ilonly") + 8: i.index("not")].strip()]) continue if "Cannot open assembly".lower() in checkingText and ": File does not contain a valid CIL image.".lower() in checkingText: # Mono repairList.append([2, i.replace(": File does not contain a valid CIL image.", "").replace("Cannot open assembly", "").strip()[1: -1]]) if "Could not load wine-gecko. HTML rendering will be disabled.".lower() in checkingText and "Could not find Wine Gecko. HTML rendering will be disabled.".lower() in checkingText: # Disbled Gecko repairList.append([3, ""]) if "Your wineserver binary was not upgraded correctly".lower() in checkingText: repairList.append([4, ""]) if "Wine Mono is not installed".lower() in checkingText: repairList.append([5, ""]) self.done.emit(repairList) def DisableButton(things): button_r_6.setDisabled(things) button1.setDisabled(things) button2.setDisabled(things) button3.setDisabled(things) wineConfig.setDisabled(things) e1.setDisabled(things) e2.setDisabled(things) o1.setDisabled(things) miniAppStore.setDisabled(things) #winetricksOpen.configure(state=a[things]) getProgramIcon.setDisabled(things) uninstallProgram.setDisabled(things) trasButton.setDisabled(things) def CheckProgramIsInstall(program): return not bool(os.system(f"which '{program}'")) class Runexebutton_threading(QtCore.QThread): signal = QtCore.pyqtSignal(str) showHistory = QtCore.pyqtSignal(str) def __init__(self): super().__init__() def run(self): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() option = "" if setting["Architecture"] != "Auto": option += f"WINEARCH={setting['Architecture']} " if setting["MonoGeckoInstaller"]: option += f"WINEDLLOVERRIDES=\"mscoree,mshtml=\" " if not setting["Debug"]: option += "WINEDEBUG=-all " else: option += "WINEDEBUG=FIXME,ERR,WARN,TRACE,Message " wineUsingOption = "" exePath = e2.currentText() if True: fileName = [".exe"] changePath = False for i in fileName: if i in exePath: print(i) print(exePath) l = exePath.index(i) exePath = f"{exePath[:l+4]}' {exePath[l+4:]} '" print(l) print(exePath) changePath = True break #if not changePath and not os.path.exists(changePath): if not changePath and not os.path.exists(exePath): # 删除前后无用空格以防止出现问题 print(exePath) exePath = exePath.strip() l = exePath.index(" ") exePath = f"{exePath[:l]}' {exePath[l:]} '" print(l) #print(i) print(exePath) if o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable": wineUsingOption = "" if o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable": if not os.path.exists(f"{programPath}/dlls-arm"): if os.system(f"7z x -y \"{programPath}/dlls-arm.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/dlls-arm.7z") if setting["TerminalOpen"]: res = "" if e2.currentText()[-4:] == ".msi" and os.path.exists(e2.currentText()): OpenTerminal("env WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " msiexec /i '" + e2.currentText() + "' " + setting["WineOption"]) elif e2.currentText()[-4:] == ".bat" and os.path.exists(e2.currentText()): OpenTerminal("env WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " wineconsole '" + e2.currentText() + "' " + setting["WineOption"]) else: OpenTerminal("env WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " '" + exePath + "' " + setting["WineOption"]) #res = subprocess.Popen([f"'{programPath}/launch.sh' deepin-terminal -C \"WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " '" + e2.currentText() + "' " + setting["WineOption"] + "\" --keep-open" + wineUsingOption], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: if e2.currentText()[-4:] == ".msi" and os.path.exists(e2.currentText()): res = subprocess.Popen(["WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " msiexec /i '" + e2.currentText() + "' " + setting["WineOption"]], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) elif e2.currentText()[-4:] == ".bat" and os.path.exists(e2.currentText()): res = subprocess.Popen(["WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " wineconsole '" + e2.currentText() + "' " + setting["WineOption"]], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: print(["WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " '" + exePath + "' " + setting["WineOption"]]) res = subprocess.Popen(["WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " '" + exePath + "' " + setting["WineOption"]], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # 实时读取程序返回 # if not setting["TerminalOpen"]: while res.poll() is None: try: text = res.stdout.readline().decode("utf8") except: text = "" self.signal.emit(text) print(text, end="") if len(findExeHistory) == 0 or findExeHistory[-1] != wineBottonPath: findExeHistory.append(wineBottonPath) # 将记录写进数组 write_txt(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json", str(json.dumps(ListToDictionary(findExeHistory)))) # 将历史记录的数组转换为字典并写入 if len(wineBottonHistory) == 0 or wineBottonHistory[-1] != e2.currentText(): wineBottonHistory.append(e2.currentText()) # 将记录写进数组 write_txt(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json", str(json.dumps(ListToDictionary(wineBottonHistory)))) # 将历史记录的数组转换为字典并写入 self.showHistory.emit("") # 针对 QQ、TIM 安装后不会生成 lnk 的问题,由程序读取以及自动创建 # 判断是否安装了 QQ/TIM for i in iconListUnBuild: if os.path.exists(i[1].replace("wineBottonPath", wineBottonPath)): if not os.path.exists(f"{get_home()}/.local/share/applications/wine/{i[0]}-{os.path.basename(wineBottonPath)}.desktop"): print("图标不存在,创建图标") # 图标不存在 # 写入 .desktop 文件 try: os.system(f"mkdir -p '{get_home()}/.local/share/applications/wine'") name = i[0] if setting["BuildByBottleName"]: name = f"{i[0]}——{os.path.basename(wineBottonPath)}" write_txt(f"{get_home()}/.local/share/applications/wine/{i[0]}-{os.path.basename(wineBottonPath)}.desktop", f'''[Desktop Entry] Name={name} Exec=env WINEPREFIX='{wineBottonPath}' {option} {wine[o1.currentText()]} '{i[1].replace("wineBottonPath", wineBottonPath)}' {setting["WineOption"]} {wineUsingOption} Icon={programPath}/Icon/{i[0]}.svg Type=Application StartupNotify=true''') except: # 写入不进去就别写入了,当什么事情都没发生就行 traceback.print_exc() DisableButton(False) class Temp: webWindow = None def OpenUrl(url): print(url.url()) # 判断是否可以使用小窗打开 if not bad: Temp.webWindow = QtWidgets.QMainWindow() web = QtWebEngineWidgets.QWebEngineView() web.setUrl(url) Temp.webWindow.setWindowTitle("浏览页面") Temp.webWindow.setCentralWidget(web) Temp.webWindow.setWindowIcon(QtGui.QIcon(iconPath)) Temp.webWindow.show() return webbrowser.open_new_tab(url.url()) #QtCore.QUrl().url() # 显示“关于这个程序”窗口 def about_this_program()->"显示“关于这个程序”窗口": global about global title global iconPath QT.message = QtWidgets.QMainWindow() QT.message.setWindowIcon(QtGui.QIcon(iconPath)) messageWidget = QtWidgets.QWidget() QT.message.setWindowTitle(f"关于 {title}") messageLayout = QtWidgets.QGridLayout() messageLayout.addWidget(QtWidgets.QLabel(f""), 0, 0, 1, 1, QtCore.Qt.AlignTop) aboutInfo = QtWidgets.QTextBrowser(messageWidget) aboutInfo.setFocusPolicy(QtCore.Qt.NoFocus) #aboutInfo.copyAvailable.connect(lambda: print("b")) aboutInfo.anchorClicked.connect(OpenUrl) aboutInfo.setOpenLinks(False) aboutInfo.setHtml(about) aboutInfo.setOpenExternalLinks(False) messageLayout.addWidget(aboutInfo, 0, 1, 1, 1) ok = QtWidgets.QPushButton(transla.transe("U", "确定")) ok.clicked.connect(QT.message.close) messageLayout.addWidget(ok, 1, 1, 1, 1, QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight) messageWidget.setLayout(messageLayout) QT.message.setCentralWidget(messageWidget) QT.message.resize(int(messageWidget.frameGeometry().width() * 1.5), int(messageWidget.frameGeometry().height() * 1.5)) QT.message.show() # 显示“提示”窗口 def helps(): global tips QtWidgets.QMessageBox.information(widget, "提示", tips) # 显示更新内容窗口 def UpdateThings(): QtWidgets.QMessageBox.information(widget, "更新内容", updateThings) # 生成 desktop 文件在启动器 def make_desktop_on_launcher(): try: if combobox1.currentText() == "" or e2.currentText() == "": # 判断文本框是否有内容 QtWidgets.QMessageBox.information(widget, "提示", "没有填写需要使用 exe 应用或保存的文件名") return if not CheckProgramIsInstall(wine[o1.currentText()]) and not o1.currentText() in untipsWine: if QtWidgets.QMessageBox.question(widget, "提示", "检查到您未安装这个 wine,是否继续使用这个 wine 写入?") == QtWidgets.QMessageBox.No: DisableButton(False) return else: # 如果都有 if os.path.exists(get_home() + "/.local/share/applications/" + combobox1.currentText() + ".desktop"): # 判断目录是否有该文件,如果有 choose = QtWidgets.QMessageBox.question(widget, "提示", "文件已经存在,是否覆盖?") == QtWidgets.QMessageBox.Yes if choose: # 如要覆盖 os.remove(get_home() + "/.local/share/applications/" + combobox1.currentText() + ".desktop") # 删除该文件 else: # 如不覆盖 return # 结束 if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() option = "" if setting["Architecture"] != "Auto": option += f"WINEARCH={setting['Architecture']} " if not setting["Debug"]: option += "WINEDEBUG=-all " else: option += "WINEDEBUG=FIXME,ERR,WARN,TRACE,Message " wineUsingOption = "" if o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable": if not os.path.exists(f"{programPath}/dlls-arm"): if os.system(f"7z x -y \"{programPath}/dlls-arm.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/dlls-arm.7z") if o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable": wineUsingOption = "" value = "" if e2.currentText()[:2].upper() == "C:": value = f"{wineBottonPath}/drive_c/{e2.currentText()[2:]}".replace("\\", "/").replace("//", "/") print(value) iconPaths = iconPath for i in iconList: listValue = i[1].replace("wineBottonPath", wineBottonPath) if listValue == e2.currentText() or listValue == value: # 如果路径相同,即可以用程序对应的图标 iconPaths = f"{programPath}/Icon/{i[0]}.svg" # 读到了就不需要再读取了 break os.system(f"mkdir -p '{get_home()}/.local/share/applications/wine'") write_txt(get_home() + "/.local/share/applications/wine/" + combobox1.currentText() + ".desktop", f'''[Desktop Entry] Name={combobox1.currentText()} Exec=env WINEPREFIX='{wineBottonPath}' {option} {wine[o1.currentText()]} '{e2.currentText()}' {setting["WineOption"]} {wineUsingOption} Icon={iconPaths} Type=Application StartupNotify=true''') # 写入文本文档 if len(shellHistory) == 0 or shellHistory[-1] != combobox1.currentText(): shellHistory.append(combobox1.currentText()) # 将记录写进数组 write_txt(get_home() + "/.config/deepin-wine-runner/ShellHistory.json", str(json.dumps(ListToDictionary(shellHistory)))) # 将历史记录的数组转换为字典并写入 combobox1.clear() combobox1.addItems(shellHistory) QtWidgets.QMessageBox.information(widget, "提示", "生成完成!") # 显示完成对话框 except: traceback.print_exc() QtWidgets.QMessageBox.critical(widget, "错误", f"快捷方式创建失败,错误如下:\n{traceback.format_exc()}") def ConfigQemu(): lists = [] for i in qemuBottleList: lists.append(f"{i[0]}/{i[1]}") choose = QtWidgets.QInputDialog.getItem(window, "提示", "选择需要 Chroot 到里面的容器", lists, 0, False) if not choose[1]: return threading.Thread(target=OpenTerminal, args=[f"python3 '{programPath}/QemuRun.py' '{choose[0]}' '{int(setting['QemuUnMountHome'])}' "]).start() print(choose) # 生成 desktop 文件在桌面 # (第四个按钮的事件) def make_desktop_on_desktop(): try: if combobox1.currentText() == "" or e2.currentText() == "": # 判断文本框是否有内容 QtWidgets.QMessageBox.information(widget, "提示", "没有填写需要使用 exe 应用或保存的文件名") return if not CheckProgramIsInstall(wine[o1.currentText()]) and not o1.currentText() in untipsWine: if QtWidgets.QMessageBox.question(widget, "提示", "检查到您未安装这个 wine,是否继续使用这个 wine 写入?") == QtWidgets.QMessageBox.No: DisableButton(False) return else: # 如果都有 if os.path.exists(get_desktop_path() + "/" + combobox1.currentText() + ".desktop"): # 判断目录是否有该文件,如果有 choose = QtWidgets.QMessageBox.question(widget, "提示", "文件已经存在,是否覆盖?") == QtWidgets.QMessageBox.Yes if choose: # 如要覆盖 os.remove(get_desktop_path() + "/" + combobox1.currentText() + ".desktop") # 删除该文件 else: # 如不覆盖 return # 结束 if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() wineUsingOption = "" if o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable": wineUsingOption = "" if o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable": if not os.path.exists(f"{programPath}/dlls-arm"): if os.system(f"7z x -y \"{programPath}/dlls-arm.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/dlls-arm.7z") if not os.path.exists(get_desktop_path()): os.makedirs(get_home()) os.mknod(get_desktop_path() + "/" + combobox1.currentText() + ".desktop") option = "" if setting["Architecture"] != "Auto": option += f"WINEARCH={setting['Architecture']} " if not setting["Debug"]: option += "WINEDEBUG=-all " value = "" if e2.currentText()[:2].upper() == "C:": value = f"{wineBottonPath}/drive_c/{e2.currentText()[2:]}".replace("\\", "/").replace("//", "/") print(value) iconPaths = iconPath for i in iconList: listValue = i[1].replace("wineBottonPath", wineBottonPath) if listValue == e2.currentText() or listValue == value: # 如果路径相同,即可以用程序对应的图标 iconPaths = f"{programPath}/Icon/{i[0]}.svg" # 读到了就不需要再读取了 break os.system(f"mkdir -p '{get_home()}/.local/share/applications/wine'") write_txt(get_desktop_path() + "/" + combobox1.currentText() + ".desktop", f'''[Desktop Entry] Name={combobox1.currentText()} Exec=env WINEPREFIX='{wineBottonPath}' {option} {wine[o1.currentText()]} '{e2.currentText()}' {setting["WineOption"]} {wineUsingOption} Icon={iconPaths} Type=Application StartupNotify=true''') # 写入文本文档 if len(shellHistory) == 0 or shellHistory[-1] != combobox1.currentText(): shellHistory.append(combobox1.currentText()) # 将记录写进数组 write_txt(get_home() + "/.config/deepin-wine-runner/ShellHistory.json", str(json.dumps(ListToDictionary(shellHistory)))) # 将历史记录的数组转换为字典并写入 combobox1.clear() combobox1.addItems(shellHistory) QtWidgets.QMessageBox.information(widget, "提示", "生成完成!") # 显示完成对话框 except: traceback.print_exc() QtWidgets.QMessageBox.critical(widget, "错误", f"快捷方式创建失败,错误如下:\n{traceback.format_exc()}") # 数组转字典 def ListToDictionary(list): dictionary = {} for i in range(len(list)): dictionary[i] = list[i] return dictionary def CleanProgramHistory(): if QtWidgets.QMessageBox.question(widget, "警告", "删除后将无法恢复,你确定吗?\n删除后软件将会自动重启。") == QtWidgets.QMessageBox.Yes: try: shutil.rmtree(get_home() + "/.config/deepin-wine-runner") except: traceback.print_exc() QtWidgets.QMessageBox.critical(widget, "错误", traceback.format_exc()) ReStartProgram() def CleanProgramCache(): try: shutil.rmtree(get_home() + "/.cache/deepin-wine-runner") QtWidgets.QMessageBox.information(widget, "提示", "缓存清理完毕!") except: traceback.print_exc() QtWidgets.QMessageBox.critical(widget, "错误", traceback.format_exc()) # 重启本应用程序 def ReStartProgram(): python = sys.executable os.execl(python, python, * sys.argv) def KillAllProgram(): pass def KillProgram(): os.system(f"killall {wine[o1.currentText()]} -9") os.system("killall winedbg -9") exeName = os.path.basename(e2.currentText()) os.system(f"killall {exeName} -9") def InstallWine(): threading.Thread(target=OpenTerminal, args=[f"'{programPath}/AllInstall.py'"]).start() def InstallWineOnDeepin23(): threading.Thread(target=OpenTerminal, args=[f"'{programPath}/InstallWineOnDeepin23.py'"]).start() class DllWindow(): def ShowWindow(): global dllMessage global dllInfoMap global textInfo global dllName dllMessage = QtWidgets.QWidget() dllLayout = QtWidgets.QGridLayout() try: dllInfoMap["check"] except: try: with open(f"{programPath}/CheckDLL/lists.json", "r") as file: dllInfoMap = json.loads(file.read()) except: traceback.print_exc() QtWidgets.QMessageBox.critical(dllMessage, "错误", traceback.format_exc()) # UI dllName = QtWidgets.QLineEdit() dllButton = QtWidgets.QPushButton("查询") textInfo = QtWidgets.QTextBrowser() dllButton.clicked.connect(DllWindow.Find) dllLayout.addWidget(QtWidgets.QLabel("Dll 名称:"), 0, 0) dllLayout.addWidget(dllName, 0, 1) dllLayout.addWidget(dllButton, 0, 2) dllLayout.addWidget(textInfo, 1, 0, 1, 3) dllMessage.setWindowTitle(f"{title}——查询 Dll") dllMessage.setLayout(dllLayout) dllMessage.resize(int(dllMessage.frameGeometry().width() * 1.2), int(dllMessage.frameGeometry().height() * 1.1)) dllMessage.setWindowIcon(QtGui.QIcon(f"{programPath}/deepin-wine-runner.svg")) dllMessage.show() def Find(): dllNameText = dllName.text().strip().lower() if dllNameText[-4:] != ".dll": dllNameText += ".dll" try: textInfo.setText(dllInfoMap[dllNameText]) except: textInfo.setText(f"未查询到有关 Dll '{dllNameText}' 有关的内容") def InstallWineOnDeepin23Alpha(): threading.Thread(target=OpenTerminal, args=[f"'{programPath}/InstallWineOnDeepin23Alpha.py'"]).start() def InstallWineHQ(): threading.Thread(target=OpenTerminal, args=[f"{programPath}/InstallNewWineHQ.sh"]).start() def OpenWineBotton(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() os.system("xdg-open \"" + wineBottonPath.replace("\'", "\\\'") + "\"") def OpenWineFontPath(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() QtWidgets.QMessageBox.information(widget, "提示", transla.transe("U", "如果安装字体?只需要把字体文件复制到此字体目录\n按下“OK”按钮可以打开字体目录")) os.system("xdg-open \"" + wineBottonPath.replace("\'", "\\\'") + "/drive_c/windows/Fonts\"") def GetLoseDll(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() option = "" if setting["MonoGeckoInstaller"]: option += f"WINEDLLOVERRIDES=\"mscoree,mshtml=\" " if setting["Architecture"] != "Auto": option += f"WINEARCH={setting['Architecture']} " if not setting["Debug"]: option += "WINEDEBUG=-all " wineUsingOption = "" if o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable": os.system(f"'{programPath}/deepin-wine-runner-create-botton.py' '{wineBottonPath}'") if o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable": wineUsingOption = "" if o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable": if not os.path.exists(f"{programPath}/dlls-arm"): if os.system(f"7z x -y \"{programPath}/dlls-arm.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/dlls-arm.7z") threading.Thread(target=os.system, args=[f"python3 '{programPath}/CheckDLL/main.py' '{e2.currentText()}' '{wineBottonPath}' '{wine[o1.currentText()]}'" + setting["WineOption"]]).start() class RunWineProgramThread(QtCore.QThread): signal = QtCore.pyqtSignal(str) showHistory = QtCore.pyqtSignal(str) def __init__(self, wineProgram, history = False, Disbled = True): super().__init__() self.wineProgram = wineProgram self.history = history self.Disbled = Disbled def run(self): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() option = "" if setting["MonoGeckoInstaller"]: option += f"WINEDLLOVERRIDES=\"mscoree,mshtml=\" " if setting["Architecture"] != "Auto": option += f"WINEARCH={setting['Architecture']} " if not setting["Debug"]: option += "WINEDEBUG=-all " wineUsingOption = "" if o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable": os.system(f"'{programPath}/deepin-wine-runner-create-botton.py' '{wineBottonPath}'") if o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable": wineUsingOption = "" if o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable": if not os.path.exists(f"{programPath}/dlls-arm"): if os.system(f"7z x -y \"{programPath}/dlls-arm.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/dlls-arm.7z") if setting["TerminalOpen"]: res = "" OpenTerminal(f"env WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " '" + self.wineProgram + "' " + setting["WineOption"] + " " + wineUsingOption) #res = subprocess.Popen([f"'{programPath}/launch.sh' deepin-terminal -C \"WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " '" + self.wineProgram + "' " + setting["WineOption"] + " " + wineUsingOption + "\" --keep-open"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: res = subprocess.Popen(["WINEPREFIX='" + wineBottonPath + "' " + option + wine[o1.currentText()] + " '" + self.wineProgram + "' " + setting["WineOption"]], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # 实时读取程序返回 if not setting["TerminalOpen"]: while res.poll() is None: try: text = res.stdout.readline().decode("utf8") except: text = "" self.signal.emit(text) print(text, end="") if self.history: if len(findExeHistory) == 0 or findExeHistory[-1] != wineBottonPath: findExeHistory.append(wineBottonPath) # 将记录写进数组 write_txt(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json", str(json.dumps(ListToDictionary(findExeHistory)))) # 将历史记录的数组转换为字典并写入 if len(wineBottonHistory) == 0 or wineBottonHistory[-1] != e2.currentText(): wineBottonHistory.append(e2.currentText()) # 将记录写进数组 write_txt(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json", str(json.dumps(ListToDictionary(wineBottonHistory)))) # 将历史记录的数组转换为字典并写入 self.showHistory.emit("") if self.Disbled: DisableButton(False) runProgram = None def RunWineProgram(wineProgram, history = False, Disbled = True): global runProgram DisableButton(True) if not CheckProgramIsInstall(wine[o1.currentText()]) and o1.currentText() != "基于 linglong 的 deepin-wine6-stable(不推荐)" and o1.currentText() != "基于 UOS exagear 的 deepin-wine6-stable" and o1.currentText() != "基于 UOS box86 的 deepin-wine6-stable": if not CheckProgramIsInstall(wine[o1.currentText()]) and not o1.currentText() in untipsWine: DisableButton(False) return returnText.setText("") runProgram = RunWineProgramThread(wineProgram, history, Disbled) runProgram.signal.connect(QT.ShowWineReturn) runProgram.showHistory.connect(QT.ShowHistory) runProgram.start() class RunWinetricksThread(QtCore.QThread): signal = QtCore.pyqtSignal(str) def __init__(self): super().__init__() def run(self): wineBottonPath = setting["DefultBotton"] if not e1.currentText() == "": wineBottonPath = e1.currentText() option = "" if setting["Architecture"] != "Auto": option += f"WINEARCH={setting['Architecture']} " if not setting["Debug"]: option += "WINEDEBUG=-all " wineUsingOption = "" if o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable": wineUsingOption = "" if o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable": if not os.path.exists(f"{programPath}/dlls-arm"): if os.system(f"7z x -y \"{programPath}/dlls-arm.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/dlls-arm.7z") if setting["TerminalOpen"]: res = "" # 用终端开应该不用返回输出内容了 OpenTerminal(f"WINEPREFIX='{wineBottonPath}' {option} WINE=" + subprocess.getoutput(f"which {wine[o1.currentText()]}").replace(" ", "").replace("\n", "") + f" winetricks --gui {wineUsingOption}") #res = subprocess.Popen([f"'{programPath}/launch.sh' deepin-terminal -C \"WINEPREFIX='{wineBottonPath}' {option} WINE=" + subprocess.getoutput(f"which {wine[o1.currentText()]}").replace(" ", "").replace("\n", "") + f" winetricks --gui {wineUsingOption}\" --keep-open"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: res = subprocess.Popen([f"WINEPREFIX='{wineBottonPath}' {option} WINE='" + subprocess.getoutput(f"which {wine[o1.currentText()]}").replace(" ", "").replace("\n", "") + "' winetricks --gui"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # 实时读取程序返回 while res.poll() is None: try: text = res.stdout.readline().decode("utf8") except: text = "" self.signal.emit(text) print(text, end="") DisableButton(False) runWinetricks = None def RunWinetricks(): global runWinetricks DisableButton(True) if not CheckProgramIsInstall(wine[o1.currentText()]) and o1.currentText() != "基于 linglong 的 deepin-wine6-stable(不推荐)" and o1.currentText() != "基于 UOS exagear 的 deepin-wine6-stable" and o1.currentText() != "基于 UOS box86 的 deepin-wine6-stable": if not CheckProgramIsInstall(wine[o1.currentText()]) and not o1.currentText() in untipsWine: DisableButton(False) return if o1.currentText() == "基于 UOS box86 的 deepin-wine6-stable" or o1.currentText() == "基于 UOS exagear 的 deepin-wine6-stable": if not os.path.exists(f"{programPath}/dlls-arm"): if os.system(f"7z x -y \"{programPath}/dlls-arm.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/dlls-arm.7z") returnText.setText("") runWinetricks = RunWinetricksThread() runWinetricks.signal.connect(QT.ShowWineReturn) runWinetricks.start() def CleanWineBottonByUOS(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"env WINE='{wine[o1.currentText()]}' '{programPath}/cleanbottle.sh' '{wineBottonPath}'") def FontAppStore(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"env WINE='{programPath}/launch.sh' '{programPath}/InstallFont.py' '{wineBottonPath}' {int(setting['RuntimeCache'])}") def GetDllFromInternet(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"env WINE='{programPath}/launch.sh' '{programPath}/InstallDll.py' '{wineBottonPath}' '{wine[o1.currentText()]}' {int(setting['RuntimeCache'])}") def WineBottonAutoConfig(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() option = "" if setting["Architecture"] != "Auto": option += f"WINEARCH={setting['Architecture']} " if setting["MonoGeckoInstaller"]: option += f"WINEDLLOVERRIDES=\"mscoree,mshtml=\" " if not setting["Debug"]: option += "WINEDEBUG=-all " else: option += "WINEDEBUG=FIXME,ERR,WARN,TRACE,Message " os.system(f"env WINEPREFIX='{wineBottonPath}' {option} WINE='{wine[o1.currentText()]}' '{programPath}/AutoConfig.py' '{wine[o1.currentText()]}' '{wineBottonPath}'") def InstallMonoGecko(program): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"'{programPath}/InstallMono.py' '{wineBottonPath}' '{wine[o1.currentText()]}' {program} {int(setting['RuntimeCache'])}") def InstallNetFramework(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"'{programPath}/InstallNetFramework.py' '{wineBottonPath}' '{wine[o1.currentText()]}' {int(setting['RuntimeCache'])}") def InstallVB(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"'{programPath}/InstallVisualBasicRuntime.py' '{wineBottonPath}' '{wine[o1.currentText()]}' {int(setting['RuntimeCache'])}") def InstallVisualStudioCPlusPlus(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"'{programPath}/InstallVisualCPlusPlus.py' '{wineBottonPath}' '{wine[o1.currentText()]}' {int(setting['RuntimeCache'])}") def InstallMSXML(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"'{programPath}/InstallMsxml.py' '{wineBottonPath}' '{wine[o1.currentText()]}' {int(setting['RuntimeCache'])}") def InstallDXVK(): if not os.path.exists(f"{programPath}/dxvk"): if os.system(f"7z x -y \"{programPath}/dxvk.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/dxvk.7z") if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"env WINE='{wine[o1.currentText()]}' WINE64='{wine[o1.currentText()]}' WINEPREFIX='{wineBottonPath}' '{programPath}/dxvk/setup_dxvk.sh' uninstall") def InstallVkd3d(): if not os.path.exists(f"{programPath}/vkd3d-proton"): if os.system(f"7z x -y \"{programPath}/vkd3d-proton.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/vkd3d-proton.7z") if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"env WINE='{wine[o1.currentText()]}' WINE64='{wine[o1.currentText()]}' WINEPREFIX='{wineBottonPath}' '{programPath}/vkd3d-proton/setup_vkd3d_proton.sh' install") def UninstallVkd3d(): if not os.path.exists(f"{programPath}/vkd3d-proton"): if os.system(f"7z x -y \"{programPath}/vkd3d-proton.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/vkd3d-proton.7z") if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"env WINE='{wine[o1.currentText()]}' WINE64='{wine[o1.currentText()]}' WINEPREFIX='{wineBottonPath}' '{programPath}/vkd3d-proton/setup_vkd3d_proton.sh' uninstall") #process = QtCore.QProcess() #process.startDetached(f"{programPath}/launch.sh", ["deepin-terminal", "-e", #"env", f"WINE={wine[o1.currentText()]}", f"WINE64={wine[o1.currentText()]}", f"WINEPREFIX={wineBottonPath}", "bash", #f"{programPath}/dxvk/setup_dxvk.sh", "install"]) def UninstallDXVK(): if not os.path.exists(f"{programPath}/dxvk"): if os.system(f"7z x -y \"{programPath}/dxvk.7z\" -o\"{programPath}\""): QtWidgets.QMessageBox.critical(widget, "错误", "无法解压资源") return os.remove(f"{programPath}/dxvk.7z") if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"env WINE='{wine[o1.currentText()]}' WINE64='{wine[o1.currentText()]}' WINEPREFIX='{wineBottonPath}' '{programPath}/dxvk/setup_dxvk.sh' uninstall") #process = QtCore.QProcess() #process.startDetached(f"{programPath}/launch.sh", ["deepin-terminal", "-e", #"env", f"WINE={wine[o1.currentText()]}", f"WINE64={wine[o1.currentText()]}", f"WINEPREFIX={wineBottonPath}", #f"{programPath}/dxvk/setup_dxvk.sh", "uninstall"]) def MiniAppStore(): if e1.currentText()== "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"'{programPath}/AppStore.py' '{wineBottonPath}' '{wine[o1.currentText()]}'") def InstallOther(): if e1.currentText()== "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() OpenTerminal(f"'{programPath}/InstallOther.py' '{wineBottonPath}' '{wine[o1.currentText()]}' {int(setting['RuntimeCache'])}") def BuildExeDeb(): if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() threading.Thread(target=os.system, args=[f"python3 '{programPath}/deepin-wine-packager.py' '{wineBottonPath}' '{wine[o1.currentText()]}'"]).start() def SetDeepinFileDialogDeepin(): code = os.system(f"pkexec \"{programPath}/deepin-wine-venturi-setter.py\" deepin") if code != 0: if code == 1: QtWidgets.QMessageBox.critical(widget, "错误", "无法更新配置:配置不准重复配置") return QtWidgets.QMessageBox.critical(widget, "错误", "配置失败") return QtWidgets.QMessageBox.information(widget, "提示", "设置完成!") def AddReg(): path = QtWidgets.QFileDialog.getOpenFileName(window, "保存路径", get_home(), "reg文件(*.reg);;所有文件(*.*)") if path[0] == "" and not path[1]: return RunWineProgram(f"regedit' /S '{path[0]}' 'HKEY_CURRENT_USER\Software\Wine\DllOverrides") def SaveDllList(): path = QtWidgets.QFileDialog.getSaveFileName(window, "保存路径", get_home(), "reg文件(*.reg);;所有文件(*.*)") if path[0] == "" and not path[1]: return RunWineProgram(f"regedit' /E '{path[0]}' 'HKEY_CURRENT_USER\Software\Wine\DllOverrides") def SetDeepinFileDialogDefult(): code = os.system(f"pkexec \"{programPath}/deepin-wine-venturi-setter.py\" defult") if code != 0: if code == 1: QtWidgets.QMessageBox.critical(widget, "错误", "无法更新配置:配置不准重复配置") return QtWidgets.QMessageBox.critical(widget, "错误", "配置失败") return QtWidgets.QMessageBox.information(widget, "提示", "设置完成!") def SetDeepinFileDialogRecovery(): threading.Thread(target=OpenTerminal, args=[f"pkexec '{programPath}/deepin-wine-venturi-setter.py' recovery"]).start() def DeleteDesktopIcon(): if os.path.exists(f"{get_home()}/.local/share/applications/wine"): try: shutil.rmtree(f"{get_home()}/.local/share/applications/wine") except: traceback.print_exc() QtWidgets.QMessageBox.critical(widget, "错误", traceback.format_exc()) return QtWidgets.QMessageBox.information(widget, "提示", "删除完成") def DeleteWineBotton(): if QtWidgets.QMessageBox.question(widget, "提示", "你确定要删除容器吗?删除后将无法恢复!\n如果没有选择 wine 容器,将会自动删除默认的容器!") == QtWidgets.QMessageBox.No: return if e1.currentText() == "": wineBottonPath = setting["DefultBotton"] else: wineBottonPath = e1.currentText() try: shutil.rmtree(wineBottonPath) QtWidgets.QMessageBox.information(widget, "提示", "删除完毕!") except: traceback.print_exc() QtWidgets.QMessageBox.critical(widget, "错误", traceback.format_exc()) def ThankWindow(): # 直接显示关于窗口,关于窗口已经添加 about_this_program() def InstallWineFont(): # 筛选 apt if not os.system("which aptss"): threading.Thread(target=OpenTerminal, args=[f"sudo aptss install ms-core-fonts -y"]).start() elif not os.system("which ss-apt-fast"): threading.Thread(target=OpenTerminal, args=[f"sudo ss-apt-fast install ms-core-fonts -y"]).start() elif not os.system("which apt-fast"): threading.Thread(target=OpenTerminal, args=[f"sudo apt-fast install ms-core-fonts -y"]).start() else: threading.Thread(target=OpenTerminal, args=[f"sudo apt install ms-core-fonts -y"]).start() def WineRunnerBugUpload(): threading.Thread(target=os.system, args=[f"'{programPath}/deepin-wine-runner-update-bug'"]).start() def SetHttpProxy(): QtWidgets.QMessageBox.information(window, "提示", "请在下面的对话框正确输入内容以便设置代理") proxyServerAddress = QtWidgets.QInputDialog.getText(window, "提示", "请输入代理服务器地址")[0] port = QtWidgets.QInputDialog.getText(window, "提示", "请输入代理服务器端口")[0] if proxyServerAddress == "" or port == "": return RunWineProgram("reg' add 'HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings' /v ProxyEnable /t REG_DWORD /d 00000001 '/f") RunWineProgram(f"reg' add 'HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings' /v ProxyServer /d '{proxyServerAddress}:{port}' '/f") def DisbledHttpProxy(): RunWineProgram("reg' add 'HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings' /v ProxyEnable /t REG_DWORD /d 00000000 '/f") def GetScreenSize(): screenInformation = [] # 使用 xrandr 进行筛选 for i in subprocess.getoutput("xrandr").split('\n'): if not " connected " in i: # 检测连接的显示器 continue # 获取分辨率基本信息,如 # DisplayPort-0 connected 1600x900+1280+0 (normal left inverted right x axis y axis) 434mm x 236mm # 先判断是否为主屏幕 main = False if "primary" in i: main = True # 进行进一步筛选 i = i[i.index("connected"):].replace("connected", "").replace("primary", "") # 进行初步筛选,如 # 1600x900+1280+0 (normal left inverted right x axis y axis) 434mm x 236mm i = i[:i.index("(")].replace(" ", "") # 筛选为 1600x900+0+0 进行最后数值的提取 screenInformation.append([ int(i[:i.index("x")]), # 获取宽度 int(i[i.index("x") + 1 :i.index("+")]), # 获取高度 int(i[i.index("+") + 1:].split('+')[0]), # 获取显示屏 X 坐标 int(i[i.index("+") + 1:].split('+')[1]), # 获取显示屏 Y 坐标 main # 是否为主屏幕 ]) return screenInformation # 返回结果 def UOSPackageScript(): threading.Thread(target=os.system, args=[f"python3 '{programPath}/deepin-wine-packager-with-script.py'"]).start() def RunVM(): threading.Thread(target=os.system, args=[f"bash '{programPath}/RunVM.sh'"]).start() def CleanProgram(): OpenTerminal(f"{programPath}/clean-unuse-program.py") class UpdateWindow(): data = {} update = None def ShowWindow(): UpdateWindow.update = QtWidgets.QMainWindow() updateWidget = QtWidgets.QWidget() updateWidgetLayout = QtWidgets.QGridLayout() versionLabel = QtWidgets.QLabel(f"当前版本:{version}\n最新版本:未知\n更新内容:") updateText = QtWidgets.QTextBrowser() ok = QtWidgets.QPushButton(transla.transe("U", "更新(更新后需要自行手动重启程序)")) ok.clicked.connect(UpdateWindow.Update) cancel = QtWidgets.QPushButton("取消") cancel.clicked.connect(UpdateWindow.update.close) if "从源码运行的版本" == programVersionType: versionLabel = QtWidgets.QLabel(f"当前版本:{version}\n最新版本:未知(从源码运行不提供更新)\n更新内容:") updateText.setText("从源码运行不提供更新") ok.setDisabled(True) else: if 1 == 0: url = "" else: if "deepin/UOS 应用商店版本<带签名>" == programVersionType: url = "aHR0cHM6Ly9jb2RlLmdpdGxpbmsub3JnLmNuL2dmZGdkLXhpLW9yZy93aW5lLXJ1bm5lci11cGRhdGUtaW5mb3JtYXRpb24vcmF3L2JyYW5jaC9tYXN0ZXIvdXBkYXRlLXVvcy5qc29u" elif "星火应用商店版本" == programVersionType: url = "aHR0cHM6Ly9jb2RlLmdpdGxpbmsub3JnLmNuL2dmZGdkLXhpLW9yZy93aW5lLXJ1bm5lci11cGRhdGUtaW5mb3JtYXRpb24vcmF3L2JyYW5jaC9tYXN0ZXIvdXBkYXRlLXNwYXJrLmpzb24=" else: url = "aHR0cHM6Ly9jb2RlLmdpdGxpbmsub3JnLmNuL2dmZGdkLXhpLW9yZy93aW5lLXJ1bm5lci11cGRhdGUtaW5mb3JtYXRpb24vcmF3L2JyYW5jaC9tYXN0ZXIvdXBkYXRlLmpzb24=" try: UpdateWindow.data = json.loads(requests.get(base64.b64decode(url).decode("utf-8")).text) versionLabel = QtWidgets.QLabel(f"当前版本:{version}\n最新版本:{UpdateWindow.data['Version']}\n更新内容:") if UpdateWindow.data["Version"] == version: updateText.setText(transla.transe("U", "此为最新版本,无需更新")) ok.setDisabled(True) else: updateText.setText(UpdateWindow.data["New"].replace("\\n", "\n")) except: traceback.print_exc() QtWidgets.QMessageBox.critical(updateWidget, transla.transe("U", "错误"), transla.transe("U", "无法连接服务器!")) updateText.setText("无法连接服务器,无法更新") ok.setDisabled(True) updateWidgetLayout.addWidget(versionLabel, 0, 0, 1, 1) updateWidgetLayout.addWidget(updateText, 1, 0, 1, 3) updateWidgetLayout.addWidget(ok, 2, 2, 1, 1) updateWidgetLayout.addWidget(cancel, 2, 1, 1, 1) updateWidget.setLayout(updateWidgetLayout) UpdateWindow.update.setCentralWidget(updateWidget) UpdateWindow.update.setWindowTitle(transla.transe("U", "检查更新")) UpdateWindow.update.resize(updateWidget.frameGeometry().width(), int(updateWidget.frameGeometry().height() * 1.5)) UpdateWindow.update.show() def Update(): if os.path.exists("/tmp/spark-deepin-wine-runner/update"): shutil.rmtree("/tmp/spark-deepin-wine-runner/update") os.makedirs("/tmp/spark-deepin-wine-runner/update") try: print(UpdateWindow.data["Url"]) write_txt("/tmp/spark-deepin-wine-runner/update.sh", f"""#!/bin/bash echo 删除多余的安装包 rm -rfv /tmp/spark-deepin-wine-runner/update/* #echo 关闭“Wine 运行器”以及其它“Python 应用” #killall python3 echo 下载安装包 wget -P /tmp/spark-deepin-wine-runner/update {UpdateWindow.data["Url"][0]} echo 安装安装包 dpkg -i /tmp/spark-deepin-wine-runner/update/* echo 修复依赖关系 apt install -f -y notify-send -i "{iconPath}" "更新完毕!" zenity --info --text=\"更新完毕!\" --ellipsize """) except: traceback.print_exc() QtWidgets.QMessageBox.critical(None, "出现错误,无法继续更新", traceback.format_exc()) OpenTerminal("pkexec bash /tmp/spark-deepin-wine-runner/update.sh") class GetDllFromWindowsISO: wineBottonPath = get_home() + "/.wine" isoPath = None dllList = None message = None dllFound = None dllControl = None foundButton = None saveDll = None setWineBotton = None browser = None mount = False mountButton = None dllListModel = None arch = 0 def ShowWindow(): #DisableButton(True) GetDllFromWindowsISO.message = QtWidgets.QMainWindow() widget = QtWidgets.QWidget() widgetLayout = QtWidgets.QGridLayout() if not e1.currentText() == "": GetDllFromWindowsISO.wineBottonPath = e1.currentText() widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", f"""提示: 目前本提取功能暂只支持 NT 内核系统的官方安装镜像,不支持读取 ghost 等第三方封装方式的安装镜像 以及不要拷贝/替换太多的 dll,否则可能会导致 wine 容器异常,以及不要替换 Wine 的核心 dll 最后,拷贝/替换 dll 后,建议点击下面“设置 wine 容器”按钮==》函数库 进行设置 当前选择的 Wine 容器:{GetDllFromWindowsISO.wineBottonPath}""")), 0, 0, 1, 5) isoLabel = QtWidgets.QLabel(transla.transe("U", "ISO镜像:")) GetDllFromWindowsISO.isoPath = QtWidgets.QComboBox() GetDllFromWindowsISO.browser = QtWidgets.QPushButton(transla.transe("U", "浏览")) isoControl = QtWidgets.QWidget() isoControlLayout = QtWidgets.QHBoxLayout() isoControl.setLayout(isoControlLayout) dllControl = QtWidgets.QWidget() dllControlLayout = QtWidgets.QHBoxLayout() dllControl.setLayout(dllControlLayout) GetDllFromWindowsISO.mountButton = QtWidgets.QPushButton(transla.transe("U", "读取/挂载ISO镜像")) umountButton = QtWidgets.QPushButton(transla.transe("U", "关闭/卸载ISO镜像")) GetDllFromWindowsISO.dllFound = QtWidgets.QComboBox() GetDllFromWindowsISO.foundButton = QtWidgets.QPushButton(transla.transe("U", "查找")) GetDllFromWindowsISO.dllList = QtWidgets.QListView() GetDllFromWindowsISO.saveDll = QtWidgets.QPushButton(transla.transe("U", "保存到 wine 容器中")) GetDllFromWindowsISO.setWineBotton = QtWidgets.QPushButton(transla.transe("U", "设置 wine 容器")) isoLabel.setSizePolicy(size) GetDllFromWindowsISO.isoPath.setEditable(True) GetDllFromWindowsISO.isoPath.addItems(isoPath) GetDllFromWindowsISO.isoPath.setEditText("") GetDllFromWindowsISO.browser.setSizePolicy(size) GetDllFromWindowsISO.mountButton.setSizePolicy(size) isoControlLayout.addWidget(GetDllFromWindowsISO.mountButton) umountButton.setSizePolicy(size) isoControlLayout.addWidget(umountButton) GetDllFromWindowsISO.dllFound.setEditable(True) GetDllFromWindowsISO.dllFound.addItems(isoPathFound) GetDllFromWindowsISO.dllFound.setEditText("") GetDllFromWindowsISO.saveDll.setSizePolicy(size) dllControlLayout.addWidget(GetDllFromWindowsISO.saveDll) GetDllFromWindowsISO.setWineBotton.setSizePolicy(size) GetDllFromWindowsISO.DisbledDown(True) dllControlLayout.addWidget(GetDllFromWindowsISO.setWineBotton) widgetLayout.addWidget(isoLabel, 1, 0, 1, 1) widgetLayout.addWidget(GetDllFromWindowsISO.isoPath, 1, 1, 1, 1) widgetLayout.addWidget(GetDllFromWindowsISO.browser, 1, 2, 1, 1) widgetLayout.addWidget(isoControl, 2, 1, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "查找DLL\n(为空则代表不查找,\n将显示全部内容):")), 3, 0, 1, 1) widgetLayout.addWidget(GetDllFromWindowsISO.dllFound, 3, 1, 1, 1) widgetLayout.addWidget(GetDllFromWindowsISO.foundButton, 3, 2, 1, 1) widgetLayout.addWidget(GetDllFromWindowsISO.dllList, 4, 1, 1, 1) widgetLayout.addWidget(dllControl, 5, 1, 1, 1) widget.setLayout(widgetLayout) GetDllFromWindowsISO.browser.clicked.connect(GetDllFromWindowsISO.Browser) GetDllFromWindowsISO.mountButton.clicked.connect(GetDllFromWindowsISO.MountDisk) umountButton.clicked.connect(GetDllFromWindowsISO.UmountDisk) GetDllFromWindowsISO.foundButton.clicked.connect(GetDllFromWindowsISO.Found) GetDllFromWindowsISO.saveDll.clicked.connect(GetDllFromWindowsISO.CopyDll) GetDllFromWindowsISO.setWineBotton.clicked.connect(lambda: RunWineProgram("winecfg", Disbled=False)) GetDllFromWindowsISO.message.setCentralWidget(widget) GetDllFromWindowsISO.dllListModel = QtCore.QStringListModel() GetDllFromWindowsISO.dllListModel.setStringList([]) GetDllFromWindowsISO.dllList.setModel(GetDllFromWindowsISO.dllListModel) GetDllFromWindowsISO.isoPath.currentText() GetDllFromWindowsISO.message.setWindowTitle(f"Wine 运行器 {version}——从 ISO 提取 DLL") GetDllFromWindowsISO.message.setWindowIcon(QtGui.QIcon(iconPath)) GetDllFromWindowsISO.message.show() def DisbledUp(state): GetDllFromWindowsISO.isoPath.setDisabled(state) GetDllFromWindowsISO.browser.setDisabled(state) GetDllFromWindowsISO.mountButton.setDisabled(state) def DisbledDown(state): GetDllFromWindowsISO.dllList.setDisabled(state) GetDllFromWindowsISO.dllFound.setDisabled(state) GetDllFromWindowsISO.saveDll.setDisabled(state) GetDllFromWindowsISO.setWineBotton.setDisabled(state) GetDllFromWindowsISO.foundButton.setDisabled(state) def Browser(): path = QtWidgets.QFileDialog.getOpenFileName(GetDllFromWindowsISO.message, "选择 ISO 镜像文件", json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/FindISO.json"))["path"], "iso 镜像文件(*.iso);;ISO 镜像文件(*.ISO);;所有文件(*.*)")[0] if path == None or path == "": return GetDllFromWindowsISO.isoPath.setEditText(path) write_txt(get_home() + "/.config/deepin-wine-runner/FindISO.json", json.dumps({"path": os.path.dirname(path)})) # 写入配置文件 def Found(): found = GetDllFromWindowsISO.dllFound.currentText() findList = [] try: if found == "": # 显示所有内容 # 下面内容需要分类讨论 if GetDllFromWindowsISO.arch == 0: for i in os.listdir("/tmp/wine-runner-getdll/i386"): if i[-3:] == "dl_": findList.append(i[:-1] + "l") elif GetDllFromWindowsISO.arch == 32: for i in os.listdir("/tmp/wine-runner-getdll-wim/Windows/SysWOW64"): if i[-3:] == "dll": findList.append(i[:-1] + "l") elif GetDllFromWindowsISO.arch == 64: for i in os.listdir("/tmp/wine-runner-getdll-wim/Windows/System32"): if i[-3:] == "dll": findList.append(i[:-1] + "l") GetDllFromWindowsISO.dllListModel.setStringList(findList) return if GetDllFromWindowsISO.arch == 0: for i in os.listdir("/tmp/wine-runner-getdll/i386"): if found in i[:-1] + "l": findList.append(i[:-1] + "l") elif GetDllFromWindowsISO.arch == 32: for i in os.listdir("/tmp/wine-runner-getdll-wim/Windows/SysWOW64"): if found in i[:-1] + "l": findList.append(i[:-1] + "l") elif GetDllFromWindowsISO.arch == 64: for i in os.listdir("/tmp/wine-runner-getdll-wim/Windows/System32"): if found in i[:-1] + "l": findList.append(i[:-1] + "l") if len(isoPath) == 0: if isoPathFound[-1] != found: isoPathFound.append(found) # 将记录写进数组 write_txt(get_home() + "/.config/deepin-wine-runner/ISOPathFound.json", str(json.dumps(ListToDictionary(isoPathFound)))) # 将历史记录的数组转换为字典并写入 GetDllFromWindowsISO.dllFound.clear() GetDllFromWindowsISO.dllFound.addItems(isoPathFound) GetDllFromWindowsISO.dllListModel.setStringList(findList) except: traceback.print_exc() QtWidgets.QMessageBox.critical(GetDllFromWindowsISO.message, transla.trans("错误"), traceback.format_exc()) def MountDisk(): if not os.path.exists(GetDllFromWindowsISO.isoPath.currentText()): QtWidgets.QMessageBox.critical(GetDllFromWindowsISO.message, transla.trans("错误"), transla.trans("您选择的 ISO 镜像文件不存在")) return if os.path.exists("/tmp/wine-runner-getdll"): try: os.rmdir("/tmp/wine-runner-getdll") os.system("rm -rf /tmp/wine-runner-getdll-wim") except: # 如果无法删除可能是挂载了文件 os.system("wimunmount /tmp/wine-runner-getdll-wim") os.system("pkexec umount /tmp/wine-runner-getdll") try: os.rmdir("/tmp/wine-runner-getdll") os.rmdir("/tmp/wine-runner-getdll-wim") except: traceback.print_exc() QtWidgets.QMessageBox.critical(GetDllFromWindowsISO.message, "错误", traceback.format_exc()) return os.makedirs("/tmp/wine-runner-getdll") os.system(f"pkexec mount '{GetDllFromWindowsISO.isoPath.currentText()}' /tmp/wine-runner-getdll") findList = [] # 判断是新版的 Windows ISO(Windows Vista 及以上版本) if os.path.exists("/tmp/wine-runner-getdll/sources/install.wim"): # 如果没有安装 wimtools 的话 if os.system("which wimmount") != 0: QtWidgets.QMessageBox.critical(GetDllFromWindowsISO.message, "错误", f"镜像内容读取/挂载失败,因为没有安装 wimtools 以至无法读取") return # 是新版,挂载 wim # 需要让用户选择挂载内容 QtWidgets.QInputDialog.getMultiLineText(GetDllFromWindowsISO.message, "提示", "挂载文件需要用户记住并在下一个对话框输入 Index 以挂载正确的镜像,按下下方任意按钮即可继续", subprocess.getoutput("wiminfo '/tmp/wine-runner-getdll/sources/install.wim'")) choose = QtWidgets.QInputDialog.getInt(GetDllFromWindowsISO.message, "提示", "请输入 Index") if not choose[1]: return os.makedirs("/tmp/wine-runner-getdll-wim") os.system(f"wimmount /tmp/wine-runner-getdll/sources/install.wim {choose[0]} /tmp/wine-runner-getdll-wim") if os.path.exists("/tmp/wine-runner-getdll-wim/Windows/SysWOW64"): # 如果是 64 位镜像 if QtWidgets.QInputDialog.getItem(GetDllFromWindowsISO.message, "选择位数", "选择位数(如果没有选择,默认为 64 位)", ["32", "64"], 1, False) == "32": # 64 位镜像的 32 位是存在 SysWOW64 的 try: for i in os.listdir("/tmp/wine-runner-getdll-wim/Windows/SysWOW64"): if i[-3:] == "dll": findList.append(i[:-1] + "l") GetDllFromWindowsISO.dllListModel.setStringList(findList) GetDllFromWindowsISO.arch = 32 GetDllFromWindowsISO.DisbledDown(False) GetDllFromWindowsISO.DisbledUp(True) GetDllFromWindowsISO.mount = True if len(isoPath) == 0 or isoPath[-1] != GetDllFromWindowsISO.isoPath.currentText(): isoPath.append(GetDllFromWindowsISO.isoPath.currentText()) # 将记录写进数组 write_txt(get_home() + "/.config/deepin-wine-runner/ISOPath.json", str(json.dumps(ListToDictionary(isoPath)))) # 将历史记录的数组转换为字典并写入 GetDllFromWindowsISO.isoPath.clear() GetDllFromWindowsISO.isoPath.addItems(isoPath) return except: traceback.print_exc() QtWidgets.QMessageBox.critical(GetDllFromWindowsISO.message, "错误", f"镜像内容读取/挂载失败,报错如下:\n{traceback.format_exc()}") return try: for i in os.listdir("/tmp/wine-runner-getdll-wim/Windows/System32"): if i[-3:] == "dll": findList.append(i[:-1] + "l") GetDllFromWindowsISO.arch = 64 except: traceback.print_exc() QtWidgets.QMessageBox.critical(GetDllFromWindowsISO.message, "错误", f"镜像内容读取/挂载失败,报错如下:\n{traceback.format_exc()}") return GetDllFromWindowsISO.dllListModel.setStringList(findList) else: try: for i in os.listdir("/tmp/wine-runner-getdll/i386"): if i[-3:] == "dl_": findList.append(i[:-1] + "l") GetDllFromWindowsISO.arch = 0 except: traceback.print_exc() QtWidgets.QMessageBox.critical(GetDllFromWindowsISO.message, "错误", f"镜像内容读取/挂载失败,报错如下:\n{traceback.format_exc()}") return GetDllFromWindowsISO.dllListModel.setStringList(findList) GetDllFromWindowsISO.DisbledDown(False) GetDllFromWindowsISO.DisbledUp(True) GetDllFromWindowsISO.mount = True if len(isoPath) == 0 or isoPath[-1] != GetDllFromWindowsISO.isoPath.currentText(): isoPath.append(GetDllFromWindowsISO.isoPath.currentText()) # 将记录写进数组 write_txt(get_home() + "/.config/deepin-wine-runner/ISOPath.json", str(json.dumps(ListToDictionary(isoPath)))) # 将历史记录的数组转换为字典并写入 GetDllFromWindowsISO.isoPath.clear() GetDllFromWindowsISO.isoPath.addItems(isoPath) #GetDllFromWindowsISO.isoPath['value'] = isoPath def UmountDisk(): os.system("wimunmount /tmp/wine-runner-getdll-wim") os.system("pkexec umount /tmp/wine-runner-getdll") try: shutil.rmtree("/tmp/wine-runner-getdll") os.system("rm -rf /tmp/wine-runner-getdll-wim") except: traceback.print_exc() QtWidgets.QMessageBox.critical(GetDllFromWindowsISO.message, transla.transe("U", "错误"), f"关闭/卸载镜像失败,报错如下:\n{traceback.format_exc()}") return GetDllFromWindowsISO.DisbledDown(True) GetDllFromWindowsISO.DisbledUp(False) GetDllFromWindowsISO.mount = False QtWidgets.QMessageBox.information(GetDllFromWindowsISO.message, transla.transe("U", "提示"), transla.transe("U", "关闭/卸载成功!")) def CopyDll(): choose = GetDllFromWindowsISO.dllList.selectionModel().selectedIndexes()[0].data() if os.path.exists(f"{GetDllFromWindowsISO.wineBottonPath}/drive_c/windows/system32/{choose}"): if QtWidgets.QMessageBox.question(GetDllFromWindowsISO.message, "提示", f"DLL {choose} 已经存在,是否覆盖?") == QtWidgets.QMessageBox.No: return try: # 要分类讨论 if GetDllFromWindowsISO.arch == 0: shutil.copy(f"/tmp/wine-runner-getdll/i386/{choose[:-1]}_", f"{GetDllFromWindowsISO.wineBottonPath}/drive_c/windows/system32/{choose}") elif GetDllFromWindowsISO.arch == 32: shutil.copy(f"/tmp/wine-runner-getdll-wim/Windows/SysWOW64/{choose[:-1]}l", f"{GetDllFromWindowsISO.wineBottonPath}/drive_c/windows/system32/{choose}") elif GetDllFromWindowsISO.arch == 64: shutil.copy(f"/tmp/wine-runner-getdll-wim/Windows/System32/{choose[:-1]}l", f"{GetDllFromWindowsISO.wineBottonPath}/drive_c/windows/system32/{choose}") # 选择原装或优于内建 if QtWidgets.QInputDialog.getItem(GetDllFromWindowsISO.message, "选择", "选择模式", ["原装先于内建", "原装"], 0, False) == "原装先于内建": # 原装先于内建 os.system(f"WINEPREFIX='{GetDllFromWindowsISO.wineBottonPath}' '{wine[o1.currentText()]}' reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v {os.path.splitext(choose)[0]} /d native,builtin /f") else: # 原装 os.system(f"WINEPREFIX='{GetDllFromWindowsISO.wineBottonPath}' '{wine[o1.currentText()]}' reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v {os.path.splitext(choose)[0]} /d native /f") QtWidgets.QMessageBox.information(GetDllFromWindowsISO.message, "提示", "提取成功!") except: traceback.print_exc() QtWidgets.QMessageBox.critical(GetDllFromWindowsISO.message, "错误", traceback.format_exc()) choose = None class ProgramRunStatusShow(): msgWindow = None def ShowWindow(): global choose choose = None dateVersion = "" if not os.path.exists(e2.currentText()): QtWidgets.QMessageBox.information(widget, "提示", "您输入的 exe 不存在") return try: sha = ProgramRunStatusUpload.GetSHA1(e2.currentText()) lists = json.loads(requests.get(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9hcHAv").decode("utf-8") + sha + base64.b64decode("L2FsbC5qc29u").decode("utf-8")).text) r = requests.get(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9hcHAv").decode("utf-8") + sha + base64.b64decode("L3RpdGxlLnR4dA==").decode("utf-8")) r.encoding = "utf-8" title = r.text except: choosemsg = QtWidgets.QMessageBox() choosemsg.setText("""暂时还没有该软件的运行情况信息,请问需要?""") choosemsg.setWindowTitle("提示") def Choose(choices): global choose choose = choices choosemsg.addButton("取消", QtWidgets.QMessageBox.ActionRole).clicked.connect(lambda: Choose(0)) choosemsg.addButton("提交评分", QtWidgets.QMessageBox.ActionRole).clicked.connect(lambda: Choose(1)) choosemsg.addButton("预测评分(不准确)", QtWidgets.QMessageBox.ActionRole).clicked.connect(lambda: Choose(2)) choosemsg.exec_() if choose == None or choose == 0: return if choose == 1: ProgramRunStatusUpload.ShowWindow(sha) return if choose == 2: try: lists = [0, 0, 0, 0, 0, 0, 0, 0] info = json.loads(requests.get(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0OjMwMjUwL0FJP1NIQTE9").decode("utf-8") + sha).text) lists[int(info["Fen"])] = 1 dateVersion = info["Version"] title = "null" except: traceback.print_exc() QtWidgets.QMessageBox.critical(window, "错误", "无法获取预测数值") return informationList = [ "0分:无法运行并且也没有报错,自己无法解决", "1分:无法运行但有报错,自己无法解决", "2分:可以运行但是效果很差,几乎无法使用", "3分:可以运行且勉强可以使用", "4分:可以运行,体验大差不差,还是有点小问题", "5分:可以运行且完全没有bug和问题,和在 Windows 上一样", "含有不良内容,不宜安装", "含有病毒、木马等对计算机有害的软件" ] try: if title.lower() == "null": title = "未知应用" except: title = "未知应用" maxHead = lists.index(max(lists)) ProgramRunStatusShow.msgWindow = QtWidgets.QMainWindow() msgWidget = QtWidgets.QWidget() msgWidgetLayout = QtWidgets.QGridLayout() starLayout = QtWidgets.QHBoxLayout() uploadButton = QtWidgets.QPushButton(transla.transe("U", "点此上传运行情况")) uploadButton.clicked.connect(lambda: ProgramRunStatusUpload.ShowWindow(sha, title)) msgWidgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "综合评价:")), 0, 0) msgWidgetLayout.addLayout(starLayout, 0, 1) msgWidgetLayout.addWidget(QtWidgets.QLabel(informationList[maxHead]), 1, 0, 1, 2) msgWidgetLayout.addWidget(QtWidgets.QLabel("" if dateVersion == "" else f"数据版本:{dateVersion}"), 2, 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"")) else: for i in range(maxHead): starLayout.addWidget(QtWidgets.QLabel(f"")) head = maxHead for i in range(head, end): starLayout.addWidget(QtWidgets.QLabel(f"")) msgWidget.setLayout(msgWidgetLayout) ProgramRunStatusShow.msgWindow.setCentralWidget(msgWidget) ProgramRunStatusShow.msgWindow.setWindowIcon(QtGui.QIcon(iconPath)) ProgramRunStatusShow.msgWindow.setWindowTitle(f"应用“{title}”的运行情况") 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"") return for i in range(ProgramRunStatusUpload.fen.currentIndex()): ProgramRunStatusUpload.starList[i].setText(f"") head = ProgramRunStatusUpload.fen.currentIndex() end = len(ProgramRunStatusUpload.starList) for i in range(head, end): ProgramRunStatusUpload.starList[i].setText(f"") def ShowWindow(sha="", title=""): ProgramRunStatusUpload.starList = [] ProgramRunStatusUpload.sha1Value = sha ProgramRunStatusUpload.msgWindow = QtWidgets.QMainWindow() msgWidget = QtWidgets.QWidget() msgWidgetLayout = QtWidgets.QGridLayout() ProgramRunStatusUpload.programName = QtWidgets.QLineEdit() ProgramRunStatusUpload.fen = QtWidgets.QComboBox() ProgramRunStatusUpload.starLayout = QtWidgets.QHBoxLayout() upload = QtWidgets.QPushButton(transla.transe("U", "上传")) upload.clicked.connect(ProgramRunStatusUpload.Upload) if title != "": ProgramRunStatusUpload.programName.setText(title) ProgramRunStatusUpload.programName.setDisabled(True) # 生成星星列表 for i in [1, 1, 1, 1, 0]: ProgramRunStatusUpload.starList.append(QtWidgets.QLabel(f"")) ProgramRunStatusUpload.starLayout.addWidget(ProgramRunStatusUpload.starList[-1]) ProgramRunStatusUpload.starLayout.addItem(QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)) ProgramRunStatusUpload.programName.setPlaceholderText(transla.transe("U", "如果这个程序和程序名确实是合法还是检测到敏感词,改为“NULL”即可")) ProgramRunStatusUpload.fen.addItems(["0分:无法运行并且也没有报错,自己无法解决", "1分:无法运行但有报错,自己无法解决", "2分:可以运行但是效果很差,几乎无法使用", "3分:可以运行且勉强可以使用", "4分:可以运行,体验大差不差,还是有点小问题", "5分:可以运行且完全没有bug和问题,和在 Windows 上一样", "含有不良内容,不宜安装", "含有病毒、木马等对计算机有害的软件"]) ProgramRunStatusUpload.fen.setCurrentIndex(4) ProgramRunStatusUpload.fen.currentIndexChanged.connect(ProgramRunStatusUpload.ChangeStar) msgWidgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "程序名:")), 0, 0) msgWidgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "评分:")), 1, 0) msgWidgetLayout.addWidget(ProgramRunStatusUpload.programName, 0, 1) 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(transla.transe("U", "上传程序运行情况")) ProgramRunStatusUpload.msgWindow.setWindowIcon(QtGui.QIcon(iconPath)) ProgramRunStatusUpload.msgWindow.show() def Upload(): if not os.path.exists(e2.currentText()): QtWidgets.QMessageBox.critical(None, "错误", "exe 文件不存在!") return if ProgramRunStatusUpload.programName.text() == "": QtWidgets.QMessageBox.critical(None, "错误", "程序名称不能为空!") return try: if ProgramRunStatusUpload.sha1Value == "": ProgramRunStatusUpload.sha1Value = ProgramRunStatusUpload.GetSHA1(e2.currentText()) QtWidgets.QMessageBox.information(None, transla.transe("U", "提示"), json.loads(requests.post(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0OjMwMjUw").decode("utf-8"), { "SHA1": ProgramRunStatusUpload.sha1Value, "Name": ProgramRunStatusUpload.programName.text(), "Fen": ProgramRunStatusUpload.fen.currentIndex(), "Wine": o1.currentText() }).text)["Error"]) except: traceback.print_exc() QtWidgets.QMessageBox.critical(None, transla.transe("U", "错误"), transla.transe("U", "数据上传失败!")) def GetSHA1(filePath): sha1 = hashlib.sha1() file = open(filePath, "rb") while True: readByte = file.read(1024 * 1024) sha1.update(readByte) if not readByte: break file.close() return sha1.hexdigest() class ProgramSetting(): wineBottonA = None wineDebug = None defultWine = None defultBotton = None terminalOpen = None wineOption = None #wineBottonDifferent = None centerWindow = None message = None theme = None monogeckoInstaller = None autoWine = None runtimeCache = None buildByBottleName = None autoPath = None qemuUnmountHome = None def ShowWindow(): ProgramSetting.message = QtWidgets.QMainWindow() widget = QtWidgets.QWidget() widgetLayout = QtWidgets.QGridLayout() widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "选择 Wine 容器版本:")), 0, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "wine DEBUG 信息输出:")), 1, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "默认 Wine:")), 2, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "默认 Wine 容器:")), 3, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "使用终端打开:")), 4, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "自定义 wine 参数:")), 5, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "程序主题:")), 6, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "Wine 默认 Mono 和 Gecko 安装器:")), 7, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "忽略未安装的 Wine:")), 8, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "下载缓存:")), 9, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "图标生成:")), 10, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "自动根据EXE名称生成路径:")), 11, 0, 1, 1) widgetLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "Qemu + Chroot 挂载用户目录:")), 12, 0, 1, 1) ProgramSetting.wineBottonA = QtWidgets.QComboBox() ProgramSetting.wineDebug = QtWidgets.QCheckBox(transla.transe("U", "开启 DEBUG 输出")) ProgramSetting.defultWine = QtWidgets.QComboBox() ProgramSetting.defultBotton = QtWidgets.QLineEdit() ProgramSetting.theme = QtWidgets.QComboBox() ProgramSetting.theme.addItems(QtWidgets.QStyleFactory.keys()) ProgramSetting.theme.setCurrentText(setting["Theme"]) save = QtWidgets.QPushButton(transla.transe("U", "保存")) save.clicked.connect(ProgramSetting.Save) defultBottonButton = QtWidgets.QPushButton(transla.transe("U", "浏览")) defultBottonButton.clicked.connect(ProgramSetting.Browser) themeTry = QtWidgets.QPushButton(transla.transe("U", "测试(重启后变回设置的主题)")) themeTry.clicked.connect(ProgramSetting.Try) ProgramSetting.terminalOpen = QtWidgets.QCheckBox(transla.transe("U", "使用终端打开(deepin 终端)")) ProgramSetting.wineOption = QtWidgets.QLineEdit() ProgramSetting.monogeckoInstaller = QtWidgets.QCheckBox(transla.transe("U", "屏蔽 Wine 默认 Mono 和 Gecko 安装器")) ProgramSetting.autoWine = QtWidgets.QCheckBox(transla.transe("U", "不显示未检测到的 Wine")) ProgramSetting.runtimeCache = QtWidgets.QCheckBox(transla.transe("U", "开启下载缓存")) ProgramSetting.buildByBottleName = QtWidgets.QCheckBox(transla.transe("U", "本软件构建的图标后面添加容器名")) ProgramSetting.autoPath = QtWidgets.QCheckBox(transla.transe("U", "自动根据文件名生成容器路径(开启后必须通过修改默认wine容器路径才可指定其它路径,重启程序后生效)")) ProgramSetting.qemuUnmountHome = QtWidgets.QCheckBox(transla.transe("U", "使用 Qemu + Chroot 时不挂载用户目录并与系统隔离(修改后重启操作系统生效)")) ProgramSetting.wineBottonA.addItems(["Auto", "win32", "win64"]) ProgramSetting.wineBottonA.setCurrentText(setting["Architecture"]) ProgramSetting.wineDebug.setChecked(setting["Debug"]) ProgramSetting.defultWine.addItems(wine.keys()) ProgramSetting.defultWine.setCurrentText(setting["DefultWine"]) ProgramSetting.defultBotton.setText(setting["DefultBotton"]) ProgramSetting.terminalOpen.setChecked(setting["TerminalOpen"]) ProgramSetting.wineOption.setText(setting["WineOption"]) ProgramSetting.monogeckoInstaller.setChecked(setting["MonoGeckoInstaller"]) ProgramSetting.autoWine.setChecked(setting["AutoWine"]) ProgramSetting.runtimeCache.setChecked(setting["RuntimeCache"]) ProgramSetting.buildByBottleName.setChecked(setting["BuildByBottleName"]) ProgramSetting.autoPath.setChecked(setting["AutoPath"]) ProgramSetting.qemuUnmountHome.setChecked(setting["QemuUnMountHome"]) # QemuUnMountHome widgetLayout.addWidget(ProgramSetting.wineBottonA, 0, 1, 1, 1) widgetLayout.addWidget(ProgramSetting.wineDebug, 1, 1, 1, 1) widgetLayout.addWidget(ProgramSetting.defultWine, 2, 1, 1, 1) widgetLayout.addWidget(ProgramSetting.defultBotton, 3, 1, 1, 1) widgetLayout.addWidget(defultBottonButton, 3, 2, 1, 1) widgetLayout.addWidget(ProgramSetting.terminalOpen, 4, 1, 1, 1) widgetLayout.addWidget(ProgramSetting.wineOption, 5, 1, 1, 1) widgetLayout.addWidget(ProgramSetting.theme, 6, 1, 1, 1) widgetLayout.addWidget(themeTry, 6, 2, 1, 1) widgetLayout.addWidget(ProgramSetting.monogeckoInstaller, 7, 1, 1, 1) widgetLayout.addWidget(ProgramSetting.autoWine, 8, 1, 1, 1) widgetLayout.addWidget(ProgramSetting.runtimeCache, 9, 1, 1, 1) widgetLayout.addWidget(ProgramSetting.buildByBottleName, 10, 1, 1, 1) widgetLayout.addWidget(ProgramSetting.autoPath, 11, 1, 1, 2) widgetLayout.addWidget(ProgramSetting.qemuUnmountHome, 12, 1, 1, 2) widgetLayout.addWidget(save, 13, 2, 1, 1) widget.setLayout(widgetLayout) ProgramSetting.message.setCentralWidget(widget) ProgramSetting.message.setWindowIcon(QtGui.QIcon(iconPath)) ProgramSetting.message.setWindowTitle(f"设置 wine 运行器 {version}") ProgramSetting.message.show() def Browser(): path = QtWidgets.QFileDialog.getExistingDirectory(ProgramSetting.message, transla.transe("U", "选择 Wine 容器"), json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/WineBotton.json"))["path"]) if path == "" or path == None or path == "()" or path == (): return ProgramSetting.defultBotton.setText(path) def Try(): app.setStyle(QtWidgets.QStyleFactory.create(ProgramSetting.theme.currentText())) def Save(): # 写入容器位数设置 setting["Architecture"] = ProgramSetting.wineBottonA.currentText() setting["Debug"] = ProgramSetting.wineDebug.isChecked() setting["DefultWine"] = ProgramSetting.defultWine.currentText() setting["DefultBotton"] = ProgramSetting.defultBotton.text() setting["TerminalOpen"] = ProgramSetting.terminalOpen.isChecked() setting["WineOption"] = ProgramSetting.wineOption.text() setting["Theme"] = ProgramSetting.theme.currentText() setting["MonoGeckoInstaller"] = ProgramSetting.monogeckoInstaller.isChecked() setting["AutoWine"] = ProgramSetting.autoWine.isChecked() setting["RuntimeCache"] = ProgramSetting.runtimeCache.isChecked() setting["BuildByBottleName"] = ProgramSetting.buildByBottleName.isChecked() setting["AutoPath"] = ProgramSetting.autoPath.isChecked() setting["QemuUnMountHome"] = ProgramSetting.qemuUnmountHome.isChecked() try: write_txt(get_home() + "/.config/deepin-wine-runner/WineSetting.json", json.dumps(setting)) except: traceback.print_exc() QtWidgets.QMessageBox.critical(ProgramSetting.message, "错误", traceback.format_exc()) return QtWidgets.QMessageBox.information(ProgramSetting.message, "提示", "保存完毕!") class ValueCheck(): def __init__(self): pass def BASE64(self, filePath): src = "" with open(filePath, "rb") as f: base64Byte = base64.b64encode(f.read()) src += base64Byte.decode("utf-8") return src def SHA1(self, filePath): sha1 = hashlib.sha1() file = open(filePath, "rb") while True: readByte = file.read(1024 * 1024) sha1.update(readByte) if not readByte: break file.close() return sha1.hexdigest() def MD5(self, filePath): md5 = hashlib.md5() file = open(filePath, "rb") while True: readByte = file.read(1024 * 1024) md5.update(readByte) if not readByte: break file.close() return md5.hexdigest() def SHA256(self, filePath): value = hashlib.sha256() file = open(filePath, "rb") while True: readByte = file.read(1024 * 1024) value.update(readByte) if not readByte: break file.close() return value.hexdigest() def SHA384(self, filePath): value = hashlib.sha384() file = open(filePath, "rb") while True: readByte = file.read(1024 * 1024) value.update(readByte) if not readByte: break file.close() return value.hexdigest() def SHA224(self, filePath): value = hashlib.sha224() file = open(filePath, "rb") while True: readByte = file.read(1024 * 1024) value.update(readByte) if not readByte: break file.close() return value.hexdigest() def SHA512(self, filePath): value = hashlib.sha512() file = open(filePath, "rb") while True: readByte = file.read(1024 * 1024) value.update(readByte) if not readByte: break file.close() return value.hexdigest() link = { "SHA1": SHA1, "MD5": MD5, "SHA256": SHA256, "SHA512": SHA512, "SHA224": SHA224, "SHA384": SHA384, "BASE64": BASE64 } def Get(self, types): QtWidgets.QMessageBox.information(window, "提示", "在计算过程中,程序可能会出现无响应的问题,请稍后\n请在接下来的打开对话框中选择要计算的文件") file = QtWidgets.QFileDialog.getOpenFileName(window, "打开")[0] if file == "": return try: QtWidgets.QInputDialog.getMultiLineText(window, "值", "计算得到的值", self.link[types](self, file)) except: traceback.print_exc() QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc()) def ChangePath(): e1.setCurrentText(f'{setting["DefultBotton"]}/{os.path.splitext(os.path.basename(e2.currentText()))[0]}') def UploadLog(): if QtWidgets.QMessageBox.question(window, "提示", "您确定要上传吗?上传内容将不会公开,将用于加强日志分析功能") == QtWidgets.QMessageBox.Yes: text = QtWidgets.QInputDialog.getMultiLineText(window, "输入内容", "输入描述信息") try: returnList = requests.post(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0OjMwMjUwL2xvZw==").decode("utf-8"), { "Log": returnText.toPlainText(), "Wine": wine[o1.currentText()], "Tips": text }).json() if returnList["ExitCode"] == 0: QtWidgets.QMessageBox.information(window, "提示", "上传成功!") else: print(returnList) QtWidgets.QMessageBox.critical(window, "错误", "上传失败!") except: traceback.print_exc() QtWidgets.QMessageBox.critical(window, "错误", "上传失败!") def SaveLog(): path = QtWidgets.QFileDialog.getSaveFileName(window, "保存日志", get_home(), "txt文件(*.txt);;html 文件(*.html);;所有文件(*.*))") if not path[1]: return print(path) try: with open(path[0], "w") as file: if path[1] == "html 文件(*.html)": file.write(returnText.toHtml()) else: file.write(returnText.toPlainText()) except: traceback.print_exc() QtWidgets.QMessageBox.critical(window, "错误", traceback.format_exc()) def GetNewInformation(): try: text = requests.get("https://code.gitlink.org.cn/gfdgd_xi/wine-runner-list/raw/branch/master/information/index.html").text except: traceback.print_exc() text = """

无法连接到服务器


你可以尝试:

1. 判断使用的是否使用吾爱版本,如果使用吾爱版本则无法连接

2. 判断是否能正常连接网络

""" global webInformation if bad: webInformation = QtWidgets.QTextBrowser() else: webInformation = QtWebEngineWidgets.QWebEngineView() webInformation.setHtml(text) webInformation.setWindowTitle("获取程序公告") webInformation.setWindowIcon(QtGui.QIcon(iconPath)) webInformation.resize(int(webInformation.frameGeometry().width() * 1.3), int(webInformation.frameGeometry().height() * 1.1)) webInformation.show() def getFileFolderSize(fileOrFolderPath): """get size for file or folder""" totalSize = 0 try: 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 except: return totalSize # 获取当前语言 def get_now_lang()->"获取当前语言": return os.getenv('LANG') # 又需要修复多线程导致的控件问题 def AddDockerMenu(): global dockers global openFileManager global openTerminal dockers = menu.addMenu("该 Docker 基础管理") openFileManager = QtWidgets.QAction("打开默认文件管理器") openTerminal = QtWidgets.QAction("打开默认终端") openFileManager.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"xdg-open '{get_home()}'"]).start()) openTerminal.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"x-terminal-emulator"]).start()) dockers.addAction(openFileManager) dockers.addAction(openTerminal) newPackage = False class GetVersionThread(QtCore.QThread): signal = QtCore.pyqtSignal(str) def __init__(self) -> None: super().__init__() def run(self): global about global window global newPackage global programVersionType # 目前分为几个版本(在 control 文件区分): # 星火版本:~spark # 商店版本:~uos # 编译版本:无版本号 # Gitee/Github……:正常版本 # Docker 版本 programVersionTypeLnk = { "spark": "星火应用商店版本", "uos": "deepin/UOS 应用商店版本<带签名>" } # 直接判断是不是 Docker 版本 if os.path.exists(f"{programPath}/docker.txt") or os.path.exists("/.dockerenv"): programVersionType = "Docker/Chroot 内置版本" window.setWindowTitle(f"{title} (Docker/Chroot 内置版本)") self.signal.emit("") else: programVersionType = "从源码运行的版本" try: if not os.path.exists("/var/lib/dpkg/status"): print("无 dpkg,结束") file = open("/var/lib/dpkg/status", "r") fileName = file.read().splitlines() package = False for i in range(0, len(fileName)): if fileName[i] == "Package: spark-deepin-wine-runner-docker": programVersionType = "Docker 内置版本" window.setWindowTitle(f"{title} (Docker 内置版本)") #AddDockerMenu() self.signal.emit("") break if fileName[i] == "Package: spark-deepin-wine-runner-52": programVersionType = "吾爱专版" window.setWindowTitle(f"{title}(吾爱专版)") newPackage = False break if fileName[i] == "Package: spark-deepin-wine-runner": package = True newPackage = True continue if fileName[i] == "Package: wine-runner-linux": package = True continue if not package: continue if fileName[i].replace(" ", "").replace("\n", "") == "": # 空行,不再考虑 break # 搜索版本号 try: if fileName[i][:fileName[i].index(":")] == "Version": version = fileName[i][fileName[i].index(":") + 1:].strip() print(f"版本号为:{version}") if not "-" in version: programVersionType = "从Gitee/Github/Gitlink等平台获取的版本" break programVersionType = version[version.index("-") + 1:] print(programVersionType) if "-" in programVersionType: # 考虑到如 2.1.0-2-spark 的情况 programVersionType = programVersionType[programVersionType.index("-") + 1:] try: programVersionType = programVersionTypeLnk[programVersionType] except: programVersionType = "从Gitee/Github/Gitlink等平台获取的版本" break except: traceback.print_exc() continue except: print("无法读取,当没有处理") print(programVersionType) about = about.replace("@VersionForType@", programVersionType) # 获取程序体积 about = about.replace("@programSize@", str(int(getFileFolderSize(programPath) / 1024 / 1024))) def GetVersion(): global runVersion runVersion = GetVersionThread() runVersion.signal.connect(AddDockerMenu) runVersion.start() def UnPackage(): QtWidgets.QMessageBox.information(window, "提示", "请在下面两个对话框中选择 deb 包所在路径和容器解压到的路径") debPath = QtWidgets.QFileDialog.getOpenFileName(window, get_home(), "deb 文件(*.deb);;所有文件(*.*)") if not debPath[1]: return path = QtWidgets.QFileDialog.getExistingDirectory(window, get_home()) print(path) if not path: return tempDebDir = f"/tmp/wine-runner-unpack-deb-{random.randint(0, 1000)}" if os.system(f"dpkg -x '{debPath[0]}' '{tempDebDir}'"): QtWidgets.QMessageBox.critical(window, "错误", "解压失败!") return zippath = FindFile(tempDebDir, "files.7z") if zippath == None: QtWidgets.QMessageBox.critical(window, "错误", "解压失败!") return print(path) # 解压文件 os.system(f"mkdir -p '{path}'") os.system(f"7z x -y '{zippath}' -o'{path}'") os.system(f"rm -rfv '{tempDebDir}'") QtWidgets.QMessageBox.information(window, "提示", "解压完成!") def FindFile(file, name): for i in os.listdir(file): path = f"{file}/{i}" if os.path.isdir(path): returnPath = FindFile(path, name) if returnPath != None: return returnPath.replace("//", "/") if os.path.isfile(path): if i == name: return path return None def TransLog(): oldText = returnText.toPlainText() lineNumber = 0 transText = "" chooseText = "" for i in oldText.splitlines(): lineNumber += 1 chooseText += f"{i}\n" if lineNumber >= 50: lineNumber = 0 try: data = { 'doctype': 'json', 'type': 'auto','i': chooseText.replace("\n\n", "\n")} jsonReturn = requests.post("http://fanyi.youdao.com/translate", data=data).json()["translateResult"] for i in jsonReturn: print(i) transText += f'{i[0]["tgt"]}\n' chooseText = "" except: transText += f"{chooseText}\n" chooseText = "" if lineNumber != 0: lineNumber = 0 try: data = { 'doctype': 'json', 'type': 'auto','i': chooseText.replace("\n\n", "\n")} jsonReturn = requests.post("http://fanyi.youdao.com/translate", data=data).json()["translateResult"] for i in jsonReturn: print(i[0]) transText += f'{i[0]["tgt"]}\n' chooseText = "" except: transText += f"{chooseText}\n" chooseText = "" #return transText returnText.setText(transText.replace("\n\n", "\n")) ########################### # 加载配置 ########################### defultProgramList = { "Architecture": "Auto", "Debug": True, "DefultWine": "deepin-wine6 stable", "DefultBotton" : get_home() + "/.wine", "TerminalOpen": False, "WineOption": "", "WineBottonDifferent": False, "CenterWindow": False, "Theme": "", "MonoGeckoInstaller": False, "AutoWine": True, "RuntimeCache": True, "MustRead": False, "BuildByBottleName": False, "AutoPath": False, "QemuUnMountHome": False } if not os.path.exists(get_home() + "/.config/"): # 如果没有配置文件夹 os.mkdir(get_home() + "/.config/") # 创建配置文件夹 if not os.path.exists(get_home() + "/.config/deepin-wine-runner"): # 如果没有配置文件夹 os.mkdir(get_home() + "/.config/deepin-wine-runner") # 创建配置文件夹 if not os.path.exists(get_home() + "/.config/deepin-wine-runner/ShellHistory.json"): # 如果没有配置文件 write_txt(get_home() + "/.config/deepin-wine-runner/ShellHistory.json", json.dumps({})) # 创建配置文件 if not os.path.exists(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json"): # 如果没有配置文件 write_txt(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json", json.dumps({})) # 创建配置文件 if not os.path.exists(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json"): # 如果没有配置文件 write_txt(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json", json.dumps({})) # 创建配置文件 if not os.path.exists(get_home() + "/.config/deepin-wine-runner/ISOPath.json"): # 如果没有配置文件 write_txt(get_home() + "/.config/deepin-wine-runner/ISOPath.json", json.dumps({})) # 写入(创建)一个配置文件 if not os.path.exists(get_home() + "/.config/deepin-wine-runner/ISOPathFound.json"): # 如果没有配置文件 write_txt(get_home() + "/.config/deepin-wine-runner/ISOPathFound.json", json.dumps({})) # 写入(创建)一个配置文件 if not os.path.exists(get_home() + "/.config/deepin-wine-runner/FindExe.json"): # 如果没有配置文件 write_txt(get_home() + "/.config/deepin-wine-runner/FindExe.json", json.dumps({"path": "~"})) # 写入(创建)一个配置文件 if not os.path.exists(get_home() + "/.config/deepin-wine-runner/FindISO.json"): # 如果没有配置文件 write_txt(get_home() + "/.config/deepin-wine-runner/FindISO.json", json.dumps({"path": "~"})) # 写入(创建)一个配置文件 if not os.path.exists(get_home() + "/.config/deepin-wine-runner/WineBotton.json"): # 如果没有配置文件 write_txt(get_home() + "/.config/deepin-wine-runner/WineBotton.json", json.dumps({"path": "~/.deepinwine"})) # 写入(创建)一个配置文件 if not os.path.exists(get_home() + "/.config/deepin-wine-runner/WineSetting.json"): # 如果没有配置文件 write_txt(get_home() + "/.config/deepin-wine-runner/WineSetting.json", json.dumps(defultProgramList)) # 写入(创建)一个配置文件 ########################### # 设置变量 ########################### programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string # 如果要添加其他 wine,请使用安装更多 Wine 功能 ############# # 检测 Wine ############# try: wine = { "基于 UOS box86 的 deepin-wine6-stable": f"WINEPREDLL='{programPath}/dlls-arm' WINEDLLPATH=/opt/deepin-wine6-stable/lib BOX86_NOSIGSEGV=1 /opt/deepin-box86/box86 /opt/deepin-wine6-stable/bin/wine ", "基于 UOS exagear 的 deepin-wine6-stable": f"WINEPREDLL='{programPath}/dlls-arm' WINEDLLPATH=/opt/deepin-wine6-stable/lib /opt/exagear/bin/ubt_x64a64_al --path-prefix {get_home()}/.deepinwine/debian-buster --utmp-paths-list {get_home()}/.deepinwine/debian-buster/.exagear/utmp-list --vpaths-list {get_home()}/.deepinwine/debian-buster/.exagear/vpaths-list --opaths-list {get_home()}/.deepinwine/debian-buster/.exagear/opaths-list --smo-mode fbase --smo-severity smart --fd-limit 8192 --foreign-ubt-binary /opt/exagear/bin/ubt_x32a64_al -- /opt/deepin-wine6-stable/bin/wine ", "deepin-wine6 stable": "deepin-wine6-stable", "deepin-wine5 stable": "deepin-wine5-stable", "spark-wine7-devel": "spark-wine7-devel", "deepin-wine": "deepin-wine", "deepin-wine5": "deepin-wine5", "wine": "wine", "wine64": "wine64", "ukylin-wine": "ukylin-wine", "mono(这不是 wine,但可以实现初步调用运行 .net 应用)": "mono", "基于 linglong 的 deepin-wine6-stable(不推荐)": f"ll-cli run '' --exec '/bin/deepin-wine6-stable'" } untipsWine = ["基于 exagear 的 deepin-wine6-stable", "基于 UOS box86 的 deepin-wine6-stable", "基于 UOS exagear 的 deepin-wine6-stable", "基于 linglong 的 deepin-wine6-stable(不推荐)"] canUseWine = [] if os.path.exists("/opt/deepin-box86/box86") and os.path.exists("/opt/deepin-wine6-stable/bin/wine"): canUseWine.append("基于 UOS box86 的 deepin-wine6-stable") if os.path.exists("/opt/exagear/bin/ubt_x64a64_al") and os.path.exists("/opt/deepin-wine6-stable/bin/wine"): canUseWine.append("基于 UOS exagear 的 deepin-wine6-stable") if not os.system("which exagear") and os.path.exists("/opt/deepin-wine6-stable/bin/wine"): canUseWine.append("基于 exagear 的 deepin-wine6-stable") for i in wine.keys(): if not os.system(f"which '{wine[i]}'"): canUseWine.append(i) if os.path.exists("/persistent/linglong/layers/"): # 判断是否使用 linglong for i in os.listdir("/persistent/linglong/layers/"): try: dire = os.listdir(f"/persistent/linglong/layers/{i}")[-1] arch = os.listdir(f"/persistent/linglong/layers/{i}/{dire}")[-1] if os.path.exists(f"/persistent/linglong/layers/{i}/{dire}/{arch}/runtime/bin/deepin-wine6-stable"): wine["基于 linglong 的 deepin-wine6-stable(不推荐)"] = f"ll-cli run {i} --exec '/bin/deepin-wine6-stable'" canUseWine.append("基于 linglong 的 deepin-wine6-stable(不推荐)") break except: pass # 读取自定义安装的 Wine(需要解包的才能使用) qemuBottleList = [] qemuPath = f"{get_home()}/.deepin-wine-runner-ubuntu-images" if not os.system("which qemu-i386-static"): if os.path.exists(qemuPath): for g in os.listdir(qemuPath): archPath = f"{qemuPath}/{g}" arch = g if os.path.isdir(archPath): for d in os.listdir(archPath): bottlePath = f"{archPath}/{d}" if os.path.isdir(bottlePath): qemuBottleList.append([ arch, d, bottlePath ]) shellHistory = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/ShellHistory.json")).values()) findExeHistory = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/FindExeHistory.json")).values()) wineBottonHistory = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/WineBottonHistory.json")).values()) isoPath = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/ISOPath.json")).values()) isoPathFound = list(json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/ISOPathFound.json")).values()) setting = json.loads(readtxt(get_home() + "/.config/deepin-wine-runner/WineSetting.json")) change = False if not os.path.exists(get_home() + "/.config/deepin-wine-runner/mono-lock"): os.mknod(f"{get_home()}/.config/deepin-wine-runner/mono-lock") setting["MonoGeckoInstaller"] = False change = True for i in defultProgramList.keys(): if not i in setting: change = True setting[i] = defultProgramList[i] if change: write_txt(get_home() + "/.config/deepin-wine-runner/WineSetting.json", json.dumps(setting)) try: # 不再从列表读取,直接读目录 for i in os.listdir(f"{programPath}/wine/"): #for i in json.loads(readtxt(f"{programPath}/wine/winelist.json")): if os.path.exists(f"{programPath}/wine/{i}") and os.path.isdir(f"{programPath}/wine/{i}"): name = "" qemuInstall = False nameValue = [["", ""]] try: if os.path.exists("/opt/deepin-box86/box86"): nameValue.append( [ "基于 UOS box86 的 ", f"WINEPREDLL='{programPath}/dlls-arm' WINEDLLPATH=/opt/deepin-wine6-stable/lib BOX86_NOSIGSEGV=1 /opt/deepin-box86/box86 " ] ) if os.system("which box86") == 0: nameValue.append( [ "基于 box86 的 ", f"box86 " ] ) if os.system("which box64") == 0: nameValue.append( [ "基于 box64 的 ", f"box64 " ] ) if os.system("which exagear") == 0: nameValue.append( [ "基于 exagear 的 ", f"exagear " ] ) if os.path.exists("/opt/exagear/bin/ubt_x64a64_al"): nameValue.append( [ "基于 UOS exagear 的 ", f"WINEPREDLL='{programPath}/dlls-arm' WINEDLLPATH=/opt/deepin-wine6-stable/lib /opt/exagear/bin/ubt_x64a64_al --path-prefix {get_home()}/.deepinwine/debian-buster --utmp-paths-list {get_home()}/.deepinwine/debian-buster/.exagear/utmp-list --vpaths-list {get_home()}/.deepinwine/debian-buster/.exagear/vpaths-list --opaths-list {get_home()}/.deepinwine/debian-buster/.exagear/opaths-list --smo-mode fbase --smo-severity smart --fd-limit 8192 --foreign-ubt-binary /opt/exagear/bin/ubt_x32a64_al -- " ] ) for g in qemuBottleList: nameValue.append([ f"使用qemu-{g[0]}-static 调用容器{g[1]}运行 ", f"python3 '{programPath}/QemuRun.py' '{g[0]}/{g[1]}' {int(setting['QemuUnMountHome'])} " ]) except: traceback.print_exc() for k in nameValue: print(k) if "qemu" in k[0]: chrootProgramPath = "/opt/apps/deepin-wine-runner" else: chrootProgramPath = programPath if os.path.exists(f"{programPath}/wine/{i}/bin/wine"): wine[f"{k[0]}{chrootProgramPath}/wine/{i}/bin/wine"] = f"{k[1]}{chrootProgramPath}/wine/{i}/bin/wine" canUseWine.append(f"{k[0]}{chrootProgramPath}/wine/{i}/bin/wine") untipsWine.append(f"{k[0]}{chrootProgramPath}/wine/{i}/bin/wine") if os.path.exists(f"{programPath}/wine/{i}/bin/wine64"): wine[f"{k[0]}{chrootProgramPath}/wine/{i}/bin/wine64"] = f"{k[1]}{chrootProgramPath}/wine/{i}/bin/wine64" canUseWine.append(f"{k[0]}{chrootProgramPath}/wine/{i}/bin/wine64") untipsWine.append(f"{k[0]}{chrootProgramPath}/wine/{i}/bin/wine64") except: pass try: for i in os.listdir(f"{get_home()}/.deepinwine/"): if os.path.exists(f"{get_home()}/.deepinwine/{i}/bin/wine"): wine[f"{get_home()}/.deepinwine/{i}/bin/wine"] = f"{get_home()}/.deepinwine/{i}/bin/wine" canUseWine.append(f"{get_home()}/.deepinwine/{i}/bin/wine") if os.path.exists(f"{get_home()}/.deepinwine/{i}/bin/wine64"): wine[f"{get_home()}/.deepinwine/{i}/bin/wine64"] = f"{get_home()}/.deepinwine/{i}/bin/wine64" canUseWine.append(f"{get_home()}/.deepinwine/{i}/bin/wine64") except: pass except: traceback.print_exc() app = QtWidgets.QApplication(sys.argv) QtWidgets.QMessageBox.critical(None, "错误", f"无法读取配置,无法继续\n{traceback.format_exc()}") sys.exit(1) # transla.transe programVersionType = "" print(wine) ########################### # 程序信息 ########################### # 语言载入 if not "zh_CN".lower() in get_now_lang().lower(): transla = Trans("en_US", f"{programPath}/trans/deepin-wine-runner.json") else: transla = Trans("zh_CN") iconPath = "{}/deepin-wine-runner.svg".format(programPath) #iconPath = "{}/Icon/Program/wine运行器.png".format(programPath) programUrl = "https://gitee.com/gfdgd-xi/deep-wine-runner\nhttps://github.com/gfdgd-xi/deep-wine-runner\nhttps://www.gitlink.org.cn/gfdgd_xi/deep-wine-runner\nhttps://gfdgd-xi.github.io" information = json.loads(readtxt(f"{programPath}/information.json")) version = information["Version"] goodRunSystem = transla.transe("U", "常见 Linux 发行版") thankText = "" tips = transla.transe("U", '''

提示:

1、使用终端运行该程序,可以看到 wine 以及程序本身的提示和报错; 2、wine 32 位和 64 位的容器互不兼容; 3、所有的 wine 和 winetricks 均需要自行安装(可以从 菜单栏=>程序 里面进行安装); 4、本程序支持带参数运行 wine 程序(之前版本也可以),只需要按以下格式即可: exe路径\' 参数 \' 即可(单引号需要输入); 5、wine 容器如果没有指定,则会默认为 ~/.wine; 6、如果可执行文件比较大的话,会出现点击“获取该程序运行情况”出现假死的情况,因为正在后台读取 SHA1,只需要等一下即可(读取速度依照您电脑处理速度、读写速度、可执行文件大小等有关); 7、对于非 X86 的用户来说,请不要使用本程序自带的 Wine 安装程序和 Windows 虚拟机安装功能(检测到为非 X86 架构会自动禁用); 8、如果非 X86 的用户的 UOS 专业版用户想要使用的话,只需要在应用商店安装一个 Wine 版本微信即可在本程序选择正确的 Wine 运行程序; 9、在使用 linglong 包的 Wine 应用时,必须安装至少一个 linglong 的使用 Wine 软件包才会出现该选项, 而程序识别到的 Wine 是按 linglong 的使用 Wine 软件包名的字母排序第一个的 Wine,且生成的容器不在用户目录下,而是在容器的用户目录下(~/.deepinwine、/tmp、桌面、下载、文档等被映射的目录除外), 同理需要运行的 EXE 也必须在被映射的目录内; 10、如果是使用 Deepin 23 的 Wine 安装脚本,请切记——安装过程会临时添加 Deepin 20 的 apt 源,不要中断安装以及 千万不要中断后不删除源的情况下 apt upgrade !!!中断后只需重新打开脚本输入 repair 或者随意安装一个 Wine(会自动执行恢复操作)即可 以及此脚本安装的 Wine 无法保证 100% 能使用,以及副作用是会提示; N: 鉴于仓库 'https://community-packages.deepin.com/beige beige InRelease' 不支持 'i386' 体系结构,跳过配置文件 'main/binary-i386/Packages' 的获取。''') updateThingsString = transla.transe("U", '''※1、不基于生态适配脚本打包器支持禁用 Mono/Gecko 打包器; ※2、自动容器配置脚本新增命令 decompressionbottle、programforum、installmsi 以及上述命令的帮助; ※3、自动容器配置脚本新增评论功能; ※4、自动容器配置脚本新增许多应用安装脚本; ※5、安装 Windows 虚拟机功能更换应答镜像图标并添加常用 Windows 组件安装功能; ※6、安装 Windows 虚拟机功能提供镜像下载的网盘链接; ※7、简易打包器支持自动添加宋体; 8、修复 installfont 命令下载的字体目录错误问题; 9、修复提交日志功能在提交成功时依旧提示提交失败问题; 10、支持强制启用所有被禁用的组件(不推荐)。 ''') for i in information["Thank"]: thankText += f"{i}\n" updateTime = "2023年01月06日" aboutProgram = transla.transe("U", """

Wine运行器是一个能让Linux用户更加方便地运行Windows应用的程序,内置了对Wine图形化的支持、各种Wine工具、自制的Wine程序打包器和运行库安装工具等。

它同时还内置了基于VirtualBox制作的、专供小白使用的Windows虚拟机安装工具,可以做到只需下载系统镜像并点击安装即可,无需考虑虚拟机的安装、创建、分区等操作。


一个图形化了如下命令的程序(最简单格式)
env WINEPREFIX=容器路径 wine(wine的路径) 可执行文件路径
让你可以简易方便的使用 wine""")
about = f'''

关于

{aboutProgram} 版本:{version} 适用平台:{goodRunSystem}(@VersionForType@) Qt 版本:{QtCore.qVersion()} 程序官网:{programUrl} 当前程序占用体积:@programSize@MB

本程序依照 GPLV3 协议开源


鸣谢名单

{thankText}

更新内容

{updateThingsString}
更新时间:{updateTime}

提示

{tips}

关于 RacoonGX 项目组

是由 @gfdgd xi 带头的团队,gfdgd xi开发了UEngine运行器等好用的开源软件。


友谊链接

星火应用商店:https://spark-app.store/
Deepin 官网:https://www.deepin.org
Deepin 论坛:https://bbs.deepin.org
论坛:https://gfdgdxi.flarum.cloud/

©2020~{time.strftime("%Y")} By gfdgd xi、为什么您不喜欢熊出没和阿布呢,RacoonGX 团队作品

''' title = "Wine 运行器 {}".format(version) #

©2020~{time.strftime("%Y")} RacoonGX 团队,By gfdgd xi、为什么您不喜欢熊出没和阿布呢

''' updateThings = "{} 更新内容:\n{}\n更新时间:{}".format(version, updateThingsString, updateTime, time.strftime("%Y")) try: threading.Thread(target=requests.get, args=[parse.unquote(base64.b64decode("aHR0cDovLzEyMC4yNS4xNTMuMTQ0L3NwYXJrLWRlZXBpbi13aW5lLXJ1bm5lci9vcGVuL0luc3RhbGwucGhw").decode("utf-8")) + "?Version=" + version]).start() except: pass 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) print(iconList) # Qemu Lock try: if os.path.exists("/tmp/deepin-wine-runner-lock.txt"): print("lock") with open(f"/tmp/deepin-wine-runner-lock.txt", "r") as file: setting["QemuUnMountHome"] = bool(int(file.read())) else: print("unlock") with open(f"/tmp/deepin-wine-runner-lock.txt", "w") as file: # = bool(int(file.read())) file.write(str(int(setting["QemuUnMountHome"]))) except: traceback.print_exc() ########################### # 窗口创建 ########################### # 读取主题 # Qt 窗口 app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QMainWindow() window.setWindowTitle(title) widget = QtWidgets.QWidget() window.setCentralWidget(widget) mainLayout = QtWidgets.QGridLayout() # 权重 size = QtWidgets.QSizePolicy() size.setHorizontalPolicy(0) widgetSize = QtWidgets.QSizePolicy() #size.setHorizontalPolicy(0) widgetSize.setVerticalPolicy(0) # leftUp = QtWidgets.QWidget() mainLayout.addWidget(leftUp, 0, 0, 1, 1) leftUpLayout = QtWidgets.QGridLayout() leftUp.setLayout(leftUpLayout) fastLabel = QtWidgets.QLabel(transla.transe("U", "快速启动")) fastLabel.setStyleSheet("font: 30px;") leftUpLayout.addWidget(fastLabel, 0, 0, 1, 2) leftUpLayout.addWidget(QtWidgets.QLabel("
"), 1, 0, 1, 2) leftUpLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "请选择容器路径:")), 2, 0, 1, 1) e1 = QtWidgets.QComboBox() e1.setEditable(True) leftUpLayout.addWidget(e1, 3, 0, 1, 1) button1 = QtWidgets.QPushButton("浏览") button1.clicked.connect(liulanbutton) leftUpLayout.addWidget(button1, 3, 1, 1, 1) leftUpLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "请选择要执行的程序(EXE、MSI或者命令):")), 4, 0, 1, 1) e2 = QtWidgets.QComboBox() if setting["AutoPath"]: e2.editTextChanged.connect(ChangePath) e2.setEditable(True) leftUpLayout.addWidget(e2, 5, 0, 1, 1) button2 = QtWidgets.QPushButton(transla.transe("U", "浏览")) button2.clicked.connect(liulanexebutton) leftUpLayout.addWidget(button2, 5, 1, 1, 1) leftUpLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "请选择WINE版本:")), 6, 0, 1, 1) o1 = QtWidgets.QComboBox() leftUpLayout.addWidget(o1, 7, 0, 1, 1) # 设置空间权重 button1.setSizePolicy(size) button2.setSizePolicy(size) leftDown = QtWidgets.QWidget() mainLayout.addWidget(leftDown, 1, 0, 1, 1) leftDownLayout = QtWidgets.QVBoxLayout() leftDown.setLayout(leftDownLayout) highLabel = QtWidgets.QLabel(transla.transe("U", "高级功能")) highLabel.setStyleSheet("font: 30px;") leftDownLayout.addWidget(highLabel) leftDownLayout.addWidget(QtWidgets.QLabel("
")) leftDownLayout.addWidget(QtWidgets.QLabel(transla.transe("U", "创建快捷方式(Desktop文件):"))) createDesktopLink = QtWidgets.QHBoxLayout() label_r_2 = QtWidgets.QLabel(transla.transe("U", "名称:")) createDesktopLink.addWidget(label_r_2) combobox1 = QtWidgets.QComboBox() combobox1.setEditable(True) createDesktopLink.addWidget(combobox1) button5 = QtWidgets.QPushButton(transla.transe("U", "创建到桌面")) button5.clicked.connect(make_desktop_on_desktop) createDesktopLink.addWidget(button5) saveDesktopFileOnLauncher = QtWidgets.QPushButton(transla.transe("U", "创建到开始菜单")) saveDesktopFileOnLauncher.clicked.connect(make_desktop_on_launcher) createDesktopLink.addWidget(saveDesktopFileOnLauncher) leftDownLayout.addLayout(createDesktopLink) programManager = QtWidgets.QGridLayout() leftDownLayout.addLayout(programManager) programManager.addWidget(QtWidgets.QLabel(transla.transe("U", "程序管理:")), 0, 0, 1, 1) getProgramIcon = QtWidgets.QPushButton(transla.transe("U", "提取图标")) getProgramIcon.clicked.connect(lambda: RunWineProgram(f"{programPath}/BeCyIconGrabber.exe' '{e2.currentText()}" if e2.currentText()[:2].upper() == "C:" else f"{programPath}/BeCyIconGrabber.exe' 'z:/{e2.currentText()}")) programManager.addWidget(getProgramIcon, 1, 0, 1, 1) programManager.addWidget(QtWidgets.QLabel(" "*5), 1, 1, 1, 1) trasButton = QtWidgets.QPushButton(transla.transe("U", "窗口透明工具")) trasButton.clicked.connect(lambda: RunWineProgram(f"{programPath}/窗体透明度设置工具.exe")) programManager.addWidget(trasButton, 1, 2, 1, 1) uninstallProgram = QtWidgets.QPushButton(transla.transe("U", "卸载程序")) uninstallProgram.clicked.connect(lambda: RunWineProgram(f"{programPath}/geek.exe")) programManager.addWidget(QtWidgets.QLabel(" "*5), 1, 3, 1, 1) programManager.addWidget(uninstallProgram, 1, 4, 1, 1) miniAppStore = QtWidgets.QPushButton(transla.transe("U", "微型应用商店")) miniAppStore.clicked.connect(lambda: threading.Thread(target=MiniAppStore).start()) programManager.addWidget(QtWidgets.QLabel(" "*5), 1, 5, 1, 1) programManager.addWidget(miniAppStore, 1, 6, 1, 1) programManager.addWidget(QtWidgets.QLabel(" "*5), 1, 7, 1, 1) getProgramStatus = QtWidgets.QPushButton(transla.transe("U", "获取该程序运行情况")) getProgramStatus.clicked.connect(ProgramRunStatusShow.ShowWindow) programManager.addWidget(getProgramStatus, 1, 8, 1, 1) getLoseDll = QtWidgets.QPushButton(transla.transe("U", "检测静态下程序缺少DLL")) getLoseDll.clicked.connect(GetLoseDll) programManager.addWidget(QtWidgets.QLabel(" "*5), 1, 9, 1, 1) programManager.addWidget(getLoseDll, 1, 10, 1, 1) programManager.addItem(QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum), 1, 11, 1, 1) programManager.addWidget(QtWidgets.QLabel(transla.transe("U", "WINE配置:")), 2, 0, 1, 1) wineConfig = QtWidgets.QPushButton(transla.transe("U", "配置容器")) wineConfig.clicked.connect(lambda: RunWineProgram("winecfg")) programManager.addWidget(wineConfig, 3, 0, 1, 1) fontAppStore = QtWidgets.QPushButton(transla.transe("U", "字体商店")) fontAppStore.clicked.connect(FontAppStore) programManager.addWidget(fontAppStore, 3, 2, 1, 1) button_r_6 = QtWidgets.QPushButton(transla.transe("U", "RegShot")) button_r_6.clicked.connect(lambda: RunWineProgram(f"{programPath}/RegShot/regshot.exe")) programManager.addWidget(button_r_6, 3, 4, 1, 1) sparkWineSetting = QtWidgets.QPushButton(transla.transe("U", "星火wine配置")) sparkWineSetting.clicked.connect(lambda: threading.Thread(target=os.system, args=["/opt/durapps/spark-dwine-helper/spark-dwine-helper-settings/settings.sh"]).start()) programManager.addWidget(sparkWineSetting, 3, 6, 1, 1) wineAutoConfig = QtWidgets.QPushButton(transla.transe("U", "自动/手动配置 Wine 容器")) wineAutoConfig.clicked.connect(WineBottonAutoConfig) programManager.addWidget(wineAutoConfig, 3, 8, 1, 1) # 权重 button5.setSizePolicy(size) saveDesktopFileOnLauncher.setSizePolicy(size) label_r_2.setSizePolicy(size) getProgramIcon.setSizePolicy(size) #trasButton.setSizePolicy(size) button_r_6.setSizePolicy(size) wineConfig.setSizePolicy(size) returnText = QtWidgets.QTextBrowser() returnText.setStyleSheet(""" background-color: black; color: white; """) returnText.setText(transla.transe("U", "在此可以看到wine安装应用时的终端输出内容")) mainLayout.setRowStretch(0, 2) mainLayout.setRowStretch(1, 1) mainLayout.setColumnStretch(0, 2) mainLayout.setColumnStretch(1, 1) mainLayout.addWidget(returnText, 0, 1, 2, 1) # 版权 copy = QtWidgets.QLabel(f"""\n程序版本:{version},提示:Wine 无法运行保证可以运行所有的 Windows 程序,如果想要运行更多可执行程序,可以考虑虚拟机和双系统
©2020~{time.strftime("%Y")} gfdgd xi、为什么您不喜欢熊出没和阿布呢,RacoonGX 团队作品""") mainLayout.addWidget(copy, 2, 0, 1, 1) # 程序运行 programRun = QtWidgets.QWidget() programRunLayout = QtWidgets.QHBoxLayout() programRun.setLayout(programRunLayout) programRunLayout.addItem(QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)) button3 = QtWidgets.QPushButton(transla.transe("U", "运行程序")) button3.clicked.connect(runexebutton) programRunLayout.addWidget(button3) killProgram = QtWidgets.QPushButton(transla.transe("U", "终止程序")) killProgram.clicked.connect(KillProgram) programRunLayout.addWidget(killProgram) killBottonProgram = QtWidgets.QPushButton(transla.transe("U", "终止指定容器的程序")) killBottonProgram.clicked.connect(lambda: threading.Thread(target=os.system, args=[f"'{programPath}/kill.sh' '{os.path.basename(e1.currentText())}'"]).start()) programRunLayout.addWidget(killBottonProgram) mainLayout.addWidget(programRun, 2, 1, 1, 1) # 菜单栏 menu = window.menuBar() programmenu = menu.addMenu(transla.transe("U", "程序(&P)")) p1 = QtWidgets.QAction(QtGui.QIcon(f"{programPath}/Icon/Function/wine.png"), transla.transe("U", "安装 wine(&I)")) installWineOnDeepin23 = QtWidgets.QAction(QtGui.QIcon(f"{programPath}/Icon/Function/wine23P.png"), transla.transe("U", "安装 wine(只限Deepin23 Preview)")) installWineOnDeepin23Alpha = QtWidgets.QAction(QtGui.QIcon(f"{programPath}/Icon/Function/wine23A.png"), transla.transe("U", "安装 wine(只限Deepin23 Alpha)")) installWineHQ = QtWidgets.QAction(QtGui.QIcon(f"{programPath}/Icon/Function/wine.png"), transla.transe("U", "安装 WineHQ")) installMoreWine = QtWidgets.QAction(QtGui.QIcon(f"{programPath}/Icon/Function/more-wine.png"), transla.transe("U", "安装更多 Wine")) downloadChrootBottle = QtWidgets.QAction(QtGui.QIcon(f"{programPath}/Icon/Function/CHROOT.png"), transla.transe("U", "下载 Chroot 容器")) p2 = QtWidgets.QAction(transla.transe("U", "设置程序(&S)")) enabledAll = QtWidgets.QAction(transla.transe("U", "强制启用所有被禁用的组件(不推荐)")) p3 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(47), transla.transe("U", "清空软件历史记录(&C)")) cleanCache = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(47), transla.transe("U", "清空软件缓存")) cleanProgramUnuse = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(47), transla.transe("U", "删除程序组件")) p4 = QtWidgets.QAction(transla.transe("U", "退出程序(&E)")) programmenu.addAction(p1) programmenu.addAction(installWineOnDeepin23) programmenu.addAction(installWineOnDeepin23Alpha) programmenu.addAction(installWineHQ) programmenu.addAction(installMoreWine) programmenu.addAction(downloadChrootBottle) programmenu.addSeparator() programmenu.addAction(p2) programmenu.addAction(enabledAll) programmenu.addSeparator() programmenu.addAction(p3) programmenu.addAction(cleanCache) programmenu.addAction(cleanProgramUnuse) programmenu.addSeparator() programmenu.addAction(p4) p1.triggered.connect(InstallWine) installWineOnDeepin23.triggered.connect(InstallWineOnDeepin23) installWineOnDeepin23Alpha.triggered.connect(InstallWineOnDeepin23Alpha) installWineHQ.triggered.connect(InstallWineHQ) installMoreWine.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"'{programPath}/wine/installwine'"]).start()) downloadChrootBottle.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"'{programPath}/QemuDownload.py'"]).start()) p2.triggered.connect(ProgramSetting.ShowWindow) enabledAll.triggered.connect(lambda: DisableButton(False)) p3.triggered.connect(CleanProgramHistory) cleanCache.triggered.connect(CleanProgramCache) cleanProgramUnuse.triggered.connect(CleanProgram) p4.triggered.connect(window.close) wineOption = menu.addMenu(transla.transe("U", "Wine(&W)")) w1 = QtWidgets.QAction(transla.transe("U", "打开 Wine 容器目录")) w2 = QtWidgets.QAction(QtGui.QIcon.fromTheme("font"), transla.transe("U", "安装常见字体")) w3 = QtWidgets.QAction(QtGui.QIcon.fromTheme("font"), transla.transe("U", "安装自定义字体")) w4 = QtWidgets.QAction(transla.transe("U", "删除选择的 Wine 容器")) cleanBottonUOS = QtWidgets.QAction(transla.transe("U", "清理 Wine 容器(基于 Wine 适配活动脚本)")) wineKeyboardLnk = QtWidgets.QAction(transla.transe("U", "Wine 快捷键映射")) w5 = QtWidgets.QAction(QtGui.QIcon.fromTheme("deb"), transla.transe("U", "打包 wine 应用")) w6 = QtWidgets.QAction(QtGui.QIcon.fromTheme("deb"), transla.transe("U", "使用官方 Wine 适配活动的脚本进行打包")) easyPackager = QtWidgets.QAction(QtGui.QIcon.fromTheme("deb"), transla.transe("U", "使用简易打包器进行打包(小白且无特殊需求建议使用这个)")) getDllOnInternet = QtWidgets.QAction(QtGui.QIcon.fromTheme("1CD8_rundll32.0"), transla.transe("U", "从互联网获取DLL")) w7 = QtWidgets.QAction(transla.transe("U", "从镜像获取DLL(只支持官方安装镜像,DOS内核如 Windows 95 暂不支持)")) updateGeek = QtWidgets.QAction(transla.transe("U", "从 Geek Uninstaller 官网升级程序")) deletePartIcon = QtWidgets.QAction(transla.transe("U", "快捷方式管理工具")) deleteDesktopIcon = QtWidgets.QAction(transla.transe("U", "删除所有 Wine 程序在启动器的快捷方式")) wineOption.addAction(w1) wineOption.addAction(w2) wineOption.addAction(w3) wineOption.addAction(w4) wineOption.addAction(cleanBottonUOS) wineOption.addSeparator() wineOption.addAction(w5) wineOption.addAction(w6) wineOption.addAction(easyPackager) wineOption.addAction(deletePartIcon) wineOption.addSeparator() wineOption.addAction(wineKeyboardLnk) wineOption.addSeparator() wineOption.addAction(getDllOnInternet) wineOption.addAction(w7) wineOption.addSeparator() wineOption.addAction(updateGeek) wineOption.addSeparator() wm1 = wineOption.addMenu(transla.transe("U", "在指定 Wine、容器安装组件")) wm1_1 = QtWidgets.QAction(transla.transe("U", "在指定wine、指定容器安装 .net framework")) wm1_2 = QtWidgets.QAction(transla.transe("U", "在指定wine、指定容器安装 Visual Studio C++")) wm1_3 = QtWidgets.QAction(transla.transe("U", "在指定wine、指定容器安装 MSXML")) wm1_4 = QtWidgets.QAction(transla.transe("U", "在指定wine、指定容器安装 gecko")) wm1_5 = QtWidgets.QAction(QtGui.QIcon.fromTheme("mono"), transla.transe("U", "在指定wine、指定容器安装 mono")) wm1_7 = QtWidgets.QAction(transla.transe("U", "在指定wine、指定容器安装 Visual Basic Runtime")) wm1_6 = QtWidgets.QAction(transla.transe("U", "在指定wine、指定容器安装其它运行库")) wm1.addAction(wm1_1) wm1.addAction(wm1_2) wm1.addAction(wm1_3) wm1.addAction(wm1_4) wm1.addAction(wm1_5) wm1.addAction(wm1_7) wm1.addAction(wm1_6) wm2 = wineOption.addMenu(transla.transe("U", "在指定 Wine、容器运行基础应用")) wm2_1 = QtWidgets.QAction(QtGui.QIcon.fromTheme("control-center2"), transla.transe("U", "打开指定wine、指定容器的控制面板")) wm2_2 = QtWidgets.QAction(QtGui.QIcon.fromTheme("web-browser"), transla.transe("U", "打开指定wine、指定容器的浏览器")) wm2_3 = QtWidgets.QAction(QtGui.QIcon.fromTheme("regedit"), transla.transe("U", "打开指定wine、指定容器的注册表")) wm2_4 = QtWidgets.QAction(transla.transe("U", "打开指定wine、指定容器的任务管理器")) wm2_5 = QtWidgets.QAction(transla.transe("U", "打开指定wine、指定容器的资源管理器")) wm2_6 = QtWidgets.QAction(transla.transe("U", "打开指定wine、指定容器的关于 wine")) wm2.addAction(wm2_1) wm2.addAction(wm2_2) wm2.addAction(wm2_3) wm2.addAction(wm2_4) wm2.addAction(wm2_5) wm2.addAction(wm2_6) wineOption.addSeparator() settingRunV3Sh = wineOption.addMenu(transla.transe("U", "run_v3.sh 管理")) w8 = QtWidgets.QAction(transla.transe("U", "设置 run_v3.sh 的文管为 Deepin 默认文管")) w9 = QtWidgets.QAction(transla.transe("U", "设置 run_v3.sh 的文管为 Wine 默认文管")) w10 = QtWidgets.QAction(transla.transe("U", "重新安装 deepin-wine-helper")) w11 = QtWidgets.QAction(QtGui.QIcon.fromTheme("winetricks"), transla.transe("U", "使用winetricks打开指定容器")) settingRunV3Sh.addAction(w8) settingRunV3Sh.addAction(w9) settingRunV3Sh.addAction(w10) wineOption.addSeparator() wineOption.addAction(w11) wineOption.addSeparator() optionCheckDemo = wineOption.addMenu(transla.transe("U", "组件功能测试")) vbDemo = QtWidgets.QAction(transla.transe("U", "测试 Visual Basic 6 程序")) netDemo = QtWidgets.QAction(transla.transe("U", "测试 .net framework 程序")) netIEDemo = QtWidgets.QAction(transla.transe("U", "测试 .net framework + Internet Explorer 程序")) optionCheckDemo.addAction(vbDemo) optionCheckDemo.addAction(netDemo) optionCheckDemo.addAction(netIEDemo) wineOption.addSeparator() wm3 = wineOption.addMenu(transla.transe("U", "启用/禁用功能")) ed1 = wm3.addMenu(transla.transe("U", "启用/禁用 opengl")) wm3_1 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(45), transla.transe("U", "开启 opengl")) wm3_2 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(40), transla.transe("U", "禁用 opengl")) ed1.addAction(wm3_1) ed1.addAction(wm3_2) ed2 = wm3.addMenu(transla.transe("U", "安装/卸载 winbind")) wm4_1 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(45), transla.transe("U", "安装 winbind")) wm4_2 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(40), transla.transe("U", "卸载 winbind")) ed2.addAction(wm4_1) ed2.addAction(wm4_2) dxvkMenu = wm3.addMenu(transla.transe("U", "安装/卸载 DXVK")) installDxvk = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(45), transla.transe("U", "安装 DXVK")) uninstallDxvk = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(40), transla.transe("U", "卸载 DXVK")) dxvkMenu.addAction(installDxvk) dxvkMenu.addAction(uninstallDxvk) vkd3dMenu = wm3.addMenu(transla.transe("U", "安装/卸载 Vkd3d")) installvkd3d = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(45), transla.transe("U", "安装 Vkd3d")) uninstallvkd3d = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(40), transla.transe("U", "卸载 Vkd3d")) vkd3dMenu.addAction(installvkd3d) vkd3dMenu.addAction(uninstallvkd3d) wineOption.addSeparator() wineOption.addAction(deleteDesktopIcon) wineOption.addSeparator() settingWineBottleCreateLink = wm3.addMenu(transla.transe("U", "启用/禁止指定 wine 容器生成快捷方式")) enabledWineBottleCreateLink = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(45), transla.transe("U", "允许指定 wine 容器生成快捷方式")) disbledWineBottleCreateLink = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(40), transla.transe("U", "禁止指定 wine 容器生成快捷方式")) settingWineBottleCreateLink.addAction(enabledWineBottleCreateLink) settingWineBottleCreateLink.addAction(disbledWineBottleCreateLink) settingWineCrashDialog = wm3.addMenu(transla.transe("U", "启用/禁用指定 wine 容器崩溃提示窗口")) disbledWineCrashDialog = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(40), transla.transe("U", "禁用指定 wine 容器崩溃提示窗口")) enabledWineCrashDialog = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(45), transla.transe("U", "启用指定 wine 容器崩溃提示窗口")) settingWineCrashDialog.addAction(enabledWineCrashDialog) settingWineCrashDialog.addAction(disbledWineCrashDialog) settingOpenProgram = wm3.addMenu(transla.transe("U", "启用/禁止指定 wine 容器创建文件关联")) enabledOpenProgram = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(45), transla.transe("U", "允许指定 wine 容器创建文件关联")) disbledOpenProgram = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(40), transla.transe("U", "禁止指定 wine 容器创建文件关联")) settingOpenProgram.addAction(enabledOpenProgram) settingOpenProgram.addAction(disbledOpenProgram) settingHttpProxy = wineOption.addMenu(transla.transe("U", "设置指定 Wine 容器代理")) enabledHttpProxy = QtWidgets.QAction(transla.transe("U", "设置指定 wine 容器的代理")) disbledHttpProxy = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(40), transla.transe("U", "禁用指定 wine 容器的代理")) settingHttpProxy.addAction(enabledHttpProxy) settingHttpProxy.addAction(disbledHttpProxy) dllOver = wineOption.addMenu(transla.transe("U", "函数顶替库列表")) saveDllOver = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(43), transla.transe("U", "导出函数顶替列表")) addDllOver = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(32), transla.transe("U", "导入函数顶替列表")) editDllOver = QtWidgets.QAction(transla.transe("U", "编辑函数顶替库列表")) dllOver.addAction(saveDllOver) dllOver.addAction(addDllOver) dllOver.addAction(editDllOver) w1.triggered.connect(OpenWineBotton) w2.triggered.connect(InstallWineFont) w3.triggered.connect(OpenWineFontPath) w4.triggered.connect(DeleteWineBotton) cleanBottonUOS.triggered.connect(CleanWineBottonByUOS) w5.triggered.connect(BuildExeDeb) w6.triggered.connect(UOSPackageScript) easyPackager.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"'{programPath}/deepin-wine-easy-packager.py' '{e2.currentText()}'"]).start()) wineKeyboardLnk.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"'{programPath}/key/key-add-gui.py'"]).start()) getDllOnInternet.triggered.connect(GetDllFromInternet) w7.triggered.connect(GetDllFromWindowsISO.ShowWindow) updateGeek.triggered.connect(lambda: os.system(f"'{programPath}/launch.sh' deepin-terminal -C '\"{programPath}/UpdateGeek.sh\"' --keep-open")) w8.triggered.connect(SetDeepinFileDialogDeepin) w9.triggered.connect(SetDeepinFileDialogDefult) w10.triggered.connect(SetDeepinFileDialogRecovery) w11.triggered.connect(lambda: RunWinetricks()) wm1_1.triggered.connect(lambda: threading.Thread(target=InstallNetFramework).start()) wm1_2.triggered.connect(lambda: threading.Thread(target=InstallVisualStudioCPlusPlus).start()) wm1_3.triggered.connect(lambda: threading.Thread(target=InstallMSXML).start()) wm1_4.triggered.connect(lambda: threading.Thread(target=InstallMonoGecko, args=["gecko"]).start()) wm1_5.triggered.connect(lambda: threading.Thread(target=InstallMonoGecko, args=["mono"]).start()) wm1_7.triggered.connect(lambda: threading.Thread(target=InstallVB).start()) wm1_6.triggered.connect(lambda: threading.Thread(target=InstallOther).start()) wm2_1.triggered.connect(lambda: RunWineProgram("control")) wm2_2.triggered.connect(lambda: RunWineProgram("iexplore' 'https://gfdgd-xi.github.io")) wm2_3.triggered.connect(lambda: RunWineProgram("regedit")) wm2_4.triggered.connect(lambda: RunWineProgram("taskmgr")) wm2_5.triggered.connect(lambda: RunWineProgram("explorer")) wm2_6.triggered.connect(lambda: RunWineProgram("winver")) wm3_1.triggered.connect(lambda: RunWineProgram(f"regedit.exe' /s '{programPath}/EnabledOpengl.reg")) wm3_2.triggered.connect(lambda: RunWineProgram(f"regedit.exe' /s '{programPath}/DisabledOpengl.reg")) wm4_1.triggered.connect(lambda: os.system(f"'{programPath}/launch.sh' deepin-terminal -C 'pkexec apt install winbind -y' --keep-open")) wm4_2.triggered.connect(lambda: os.system(f"'{programPath}/launch.sh' deepin-terminal -C 'pkexec apt purge winbind -y' --keep-open")) installDxvk.triggered.connect(InstallDXVK) uninstallDxvk.triggered.connect(UninstallDXVK) installvkd3d.triggered.connect(InstallVkd3d) uninstallvkd3d.triggered.connect(UninstallVkd3d) deletePartIcon.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"python3 '{programPath}/BuildDesktop.py'"]).start()) deleteDesktopIcon.triggered.connect(DeleteDesktopIcon) enabledWineBottleCreateLink.triggered.connect(lambda: RunWineProgram("reg' delete 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v winemenubuilder.exe '/f")) disbledWineBottleCreateLink.triggered.connect(lambda: RunWineProgram("reg' add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v winemenubuilder.exe '/f")) disbledWineCrashDialog.triggered.connect(lambda: RunWineProgram("reg' add 'HKEY_CURRENT_USER\Software\Wine\WineDbg' /v ShowCrashDialog /t REG_DWORD /d 00000000 '/f")) enabledWineCrashDialog.triggered.connect(lambda: RunWineProgram("reg' add 'HKEY_CURRENT_USER\Software\Wine\WineDbg' /v ShowCrashDialog /t REG_DWORD /d 00000001 '/f")) disbledOpenProgram.triggered.connect(lambda: RunWineProgram("reg' add 'HKEY_CURRENT_USER\Software\Wine\FileOpenAssociations' /v Enable /d N '/f")) enabledOpenProgram.triggered.connect(lambda: RunWineProgram("reg' add 'HKEY_CURRENT_USER\Software\Wine\FileOpenAssociations' /v Enable /d Y '/f")) enabledHttpProxy.triggered.connect(SetHttpProxy) disbledHttpProxy.triggered.connect(DisbledHttpProxy) saveDllOver.triggered.connect(SaveDllList) addDllOver.triggered.connect(AddReg) editDllOver.triggered.connect(lambda: RunWineProgram("winecfg")) vbDemo.triggered.connect(lambda: RunWineProgram(f"{programPath}/Test/vb.exe")) netDemo.triggered.connect(lambda: RunWineProgram(f"{programPath}/Test/net.exe")) netIEDemo.triggered.connect(lambda: RunWineProgram(f"{programPath}/Test/netandie.exe")) virtualMachine = menu.addMenu(transla.transe("U", "虚拟机(&V)")) v1 = QtWidgets.QAction(QtGui.QIcon.fromTheme("virtualbox"), transla.transe("U", "使用 Virtualbox 虚拟机运行 Windows 应用")) virtualMachine.addAction(v1) v1.triggered.connect(RunVM) checkValue = menu.addMenu(transla.transe("U", "校验值计算(&S)")) md5Value = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(32), transla.transe("U", "MD5(&M)")) sha1Value = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(32), transla.transe("U", "SHA1(&M)")) base64Value = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(32), transla.transe("U", "Base64(建议小文件)(&B)")) sha256Value = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(32), transla.transe("U", "SHA256(&S)")) sha512Value = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(32), transla.transe("U", "SHA512(&S)")) md5Value.triggered.connect(lambda: ValueCheck().Get("MD5")) sha1Value.triggered.connect(lambda: ValueCheck().Get("SHA1")) base64Value.triggered.connect(lambda: ValueCheck().Get("BASE64")) sha256Value.triggered.connect(lambda: ValueCheck().Get("SHA256")) sha512Value.triggered.connect(lambda: ValueCheck().Get("SHA512")) checkValue.addAction(md5Value) checkValue.addAction(sha1Value) checkValue.addAction(base64Value) checkValue.addAction(sha256Value) checkValue.addAction(sha512Value) safeWebsize = menu.addMenu(transla.transe("U", "云沙箱(&C)")) s1 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(9), transla.transe("U", "360 沙箱云")) s2 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(9), transla.transe("U", "微步云沙箱")) s3 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(9), transla.transe("U", "VIRUSTOTAL")) safeWebsize.addAction(s1) safeWebsize.addAction(s2) safeWebsize.addAction(s3) s1.triggered.connect(lambda: webbrowser.open_new_tab("https://ata.360.net/")) s2.triggered.connect(lambda: webbrowser.open_new_tab("https://s.threatbook.cn/")) s3.triggered.connect(lambda: webbrowser.open_new_tab("https://www.virustotal.com/")) log = menu.addMenu(transla.transe("U", "日志(&L)")) getDllInfo = QtWidgets.QAction(transla.transe("U", "查询 Dll")) checkLogText = QtWidgets.QAction(transla.transe("U", "日志分析")) saveLogText = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(16), transla.transe("U", "另存为日志")) transLogText = QtWidgets.QAction(transla.transe("U", "翻译日志(翻译后日志分析功能会故障)")) uploadLogText = QtWidgets.QAction(transla.transe("U", "上传日志")) getDllInfo.triggered.connect(DllWindow.ShowWindow) checkLogText.triggered.connect(LogChecking.ShowWindow) saveLogText.triggered.connect(SaveLog) transLogText.triggered.connect(TransLog) uploadLogText.triggered.connect(UploadLog) log.addAction(getDllInfo) log.addAction(checkLogText) log.addAction(saveLogText) log.addAction(transLogText) log.addAction(uploadLogText) qemuMenu = menu.addMenu(transla.transe("U", "容器(&C)")) unpackDeb = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(32), transla.transe("U", "解包 deb 提取容器")) qemuMenu.addAction(unpackDeb) unpackDeb.triggered.connect(UnPackage) if len(qemuBottleList) >= 1: configMenu = QtWidgets.QAction(QtGui.QIcon(f"{programPath}/Icon/Function/CHROOT.png"), transla.transe("U", "配置指定 Chroot 容器")) qemuMenu.addAction(configMenu) configMenu.triggered.connect(ConfigQemu) print(qemuBottleList) help = menu.addMenu(transla.transe("U", "帮助(&H)")) runStatusWebSize = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "查询程序在 Wine 的运行情况")) h1 = help.addMenu(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "程序官网")) h2 = QtWidgets.QAction(transla.transe("U", "小提示")) wineRunnerHelp = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "Wine运行器和Wine打包器傻瓜式使用教程(小白专用) By 鹤舞白沙")) h3 = QtWidgets.QAction(transla.transe("U", "更新内容")) h4 = QtWidgets.QAction(transla.transe("U", "鸣谢名单")) h5 = QtWidgets.QAction(transla.transe("U", "更新这个程序")) programInformation = QtWidgets.QAction(transla.transe("U", "获取程序公告")) h6 = QtWidgets.QAction(transla.transe("U", "反馈这个程序的建议和问题")) fenUpload = QtWidgets.QAction(transla.transe("U", "程序评分")) h7 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(9), transla.transe("U", "关于这个程序")) h8 = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(9), transla.transe("U", "关于 Qt")) gfdgdxiio = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "作者个人站")) forumWebsize = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "程序论坛")) gitee = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "Gitee")) github = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "Github")) gitlink = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "Gitlink")) gitlab = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "Gitlab")) jihu = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "极狐")) h1.addAction(gfdgdxiio) h1.addAction(gitee) h1.addAction(github) h1.addAction(gitlink) h1.addAction(gitlab) h1.addAction(jihu) help.addSeparator() help.addAction(forumWebsize) help.addAction(wineRunnerHelp) help.addAction(runStatusWebSize) help.addSeparator() help.addAction(h2) help.addAction(h3) help.addAction(h4) help.addSeparator() wikiHelp = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "程序 Wiki")) help.addAction(wikiHelp) videoHelp = help.addMenu(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "视频教程")) easyHelp = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "简易使用教程")) buildHelp = QtWidgets.QAction(QtWidgets.QApplication.style().standardIcon(20), transla.transe("U", "打包教程")) videoHelp.addAction(easyHelp) videoHelp.addAction(buildHelp) help.addSeparator() help.addAction(h5) help.addAction(h6) help.addAction(fenUpload) help.addAction(programInformation) help.addAction(h7) help.addAction(h8) help.addSeparator() hm1 = help.addMenu(transla.transe("U", "更多生态适配应用")) hm1_1 = QtWidgets.QAction(transla.transe("U", "运行 Android 应用:UEngine 运行器")) hm1.addAction(hm1_1) gfdgdxiio.triggered.connect(lambda: webbrowser.open_new_tab("https://gfdgd-xi.github.io")) gitee.triggered.connect(lambda: webbrowser.open_new_tab("https://gitee.com/gfdgd-xi/deep-wine-runner")) github.triggered.connect(lambda: webbrowser.open_new_tab("https://github.com/gfdgd-xi/deep-wine-runner")) gitlink.triggered.connect(lambda: webbrowser.open_new_tab("https://gitlink.org.cn/gfdgd_xi/deep-wine-runner")) gitlab.triggered.connect(lambda: webbrowser.open_new_tab("https://gitlab.com/gfdgd-xi/deep-wine-runner")) jihu.triggered.connect(lambda: webbrowser.open_new_tab("https://jihulab.com//gfdgd-xi/deep-wine-runner")) runStatusWebSize.triggered.connect(lambda: webbrowser.open_new_tab("https://gfdgd-xi.github.io/wine-runner-info")) forumWebsize.triggered.connect(lambda: webbrowser.open_new_tab("https://gfdgdxi.flarum.cloud/")) h2.triggered.connect(helps) h3.triggered.connect(UpdateThings) wineRunnerHelp.triggered.connect(lambda: webbrowser.open_new_tab("https://bbs.deepin.org/post/246837")) h4.triggered.connect(ThankWindow) wikiHelp.triggered.connect(lambda: webbrowser.open_new_tab("https://gfdgd-xi.github.io/wine-runner-wiki")) easyHelp.triggered.connect(lambda: webbrowser.open_new_tab("https://www.bilibili.com/video/BV1ma411972Y")) buildHelp.triggered.connect(lambda: webbrowser.open_new_tab("https://www.bilibili.com/video/BV1EU4y1k7zr")) h5.triggered.connect(UpdateWindow.ShowWindow) h6.triggered.connect(WineRunnerBugUpload) fenUpload.triggered.connect(lambda: threading.Thread(target=os.system, args=[f"python3 '{programPath}/ProgramFen.py'"]).start()) h7.triggered.connect(about_this_program) h8.triggered.connect(lambda: QtWidgets.QMessageBox.aboutQt(widget)) hm1_1.triggered.connect(lambda: webbrowser.open_new_tab("https://gitee.com/gfdgd-xi/uengine-runner")) programInformation.triggered.connect(GetNewInformation) # 异同步获取信息 #threading.Thread(target=GetVersion).start() GetVersion() # 窗口设置 window.resize(widget.frameGeometry().width() * 2, widget.frameGeometry().height()) widget.setLayout(mainLayout) window.setWindowIcon(QtGui.QIcon(f"{programPath}/deepin-wine-runner.svg")) widget.show() window.show() # 控件设置 app.setStyle(QtWidgets.QStyleFactory.create(setting["Theme"])) e1.addItems(findExeHistory) e2.addItems(wineBottonHistory) combobox1.addItems(shellHistory) if setting["AutoWine"]: o1.addItems(canUseWine) else: o1.addItems(wine.keys()) # 禁用被精简掉的控件 for i in [ [[p1, installWineOnDeepin23, installWineHQ, installMoreWine], f"{programPath}/InstallWineOnDeepin23.py"], [[w5], f"{programPath}/deepin-wine-packager.py"], [[w6], f"{programPath}/deepin-wine-packager-with-script.py"], [[p1, v1], f"{programPath}/RunVM.sh"], [[getProgramIcon, uninstallProgram, updateGeek, trasButton, miniAppStore, fontAppStore, wm1_1, wm1_2, wm1_3, wm1_6, w7, w2], f"{programPath}/geek.exe"], ]: if not os.path.exists(i[1]): for x in i[0]: x.setDisabled(True) # 有些功能是非 X86 不适用的,需要屏蔽 if subprocess.getoutput("arch").lower() != "x86_64": p1.setDisabled(True) installWineOnDeepin23.setDisabled(True) installMoreWine.setEnabled(True) virtualMachine.setDisabled(True) v1.setDisabled(True) installWineHQ.setDisabled(True) pass o1.setCurrentText(setting["DefultWine"]) e1.setEditText(setting["DefultBotton"]) e2.setEditText("") combobox1.setEditText("") if len(sys.argv) > 1 and sys.argv[1]: e2.setEditText(sys.argv[1]) if not os.path.exists("/opt/durapps/spark-dwine-helper/spark-dwine-helper-settings/settings.sh"): sparkWineSetting.setEnabled(False) if o1.currentText() == "": # 一个 Wine 都没有却用 Wine 的功能 # 还是要处理的,至少不会闪退 wine["没有识别到任何Wine,请在菜单栏“程序”安装Wine或安装任意Wine应用"] = "没有识别到任何Wine,请在菜单栏“程序”安装Wine或安装任意Wine应用" canUseWine.append("没有识别到任何Wine,请在菜单栏“程序”安装Wine或安装任意Wine应用") o1.addItem("没有识别到任何Wine,请在菜单栏“程序”安装Wine或安装任意Wine应用") sys.exit(app.exec_())