mirror of
https://github.com/hyb-oyqq/FRAISEMOE-Addons-Installer-NEXT.git
synced 2025-12-19 21:38:35 +00:00
refactor(source): 重构 Main.py 文件结构
- 删除了大量未使用的导入语句 - 移除了冗长的配置信息和全局变量定义 - 精简了主窗口类 MainWindow 的代码 - 提取了部分代码到新的文件 main_window.py 中
This commit is contained in:
197
source/utils.py
Normal file
197
source/utils.py
Normal file
@@ -0,0 +1,197 @@
|
||||
import os
|
||||
import sys
|
||||
import base64
|
||||
import hashlib
|
||||
import concurrent.futures
|
||||
import ctypes
|
||||
import psutil
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
from PySide6.QtGui import QIcon, QPixmap
|
||||
from pic_data import img_data
|
||||
from config import APP_NAME
|
||||
|
||||
def resource_path(relative_path):
|
||||
if getattr(sys, 'frozen', False):
|
||||
if hasattr(sys, '_MEIPASS'):
|
||||
base_path = sys._MEIPASS # type: ignore
|
||||
else:
|
||||
base_path = os.path.dirname(sys.executable)
|
||||
else:
|
||||
base_path = os.path.dirname(os.path.abspath(__file__))
|
||||
return os.path.join(base_path, relative_path)
|
||||
|
||||
def load_base64_image(base64_str):
|
||||
pixmap = QPixmap()
|
||||
pixmap.loadFromData(base64.b64decode(base64_str))
|
||||
return pixmap
|
||||
|
||||
def msgbox_frame(title, text, buttons=QtWidgets.QMessageBox.StandardButton.NoButton):
|
||||
msg_box = QtWidgets.QMessageBox()
|
||||
msg_box.setWindowTitle(title)
|
||||
msg_box.setWindowModality(QtCore.Qt.WindowModality.WindowModal)
|
||||
|
||||
icon_data = img_data.get("icon")
|
||||
if icon_data:
|
||||
pixmap = load_base64_image(icon_data)
|
||||
if not pixmap.isNull():
|
||||
msg_box.setWindowIcon(QIcon(pixmap))
|
||||
msg_box.setIconPixmap(pixmap.scaled(64, 64, QtCore.Qt.AspectRatioMode.KeepAspectRatio))
|
||||
else:
|
||||
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Information)
|
||||
|
||||
msg_box.setText(text)
|
||||
msg_box.setStandardButtons(buttons)
|
||||
return msg_box
|
||||
|
||||
class HashManager:
|
||||
def __init__(self, HASH_SIZE):
|
||||
self.HASH_SIZE = HASH_SIZE
|
||||
|
||||
def hash_calculate(self, file_path):
|
||||
sha256_hash = hashlib.sha256()
|
||||
with open(file_path, "rb") as f:
|
||||
for byte_block in iter(lambda: f.read(self.HASH_SIZE), b""):
|
||||
sha256_hash.update(byte_block)
|
||||
return sha256_hash.hexdigest()
|
||||
|
||||
def calculate_hashes_in_parallel(self, file_paths):
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
future_to_file = {
|
||||
executor.submit(self.hash_calculate, path): path for path in file_paths
|
||||
}
|
||||
results = {}
|
||||
for future in concurrent.futures.as_completed(future_to_file):
|
||||
file_path = future_to_file[future]
|
||||
try:
|
||||
results[file_path] = future.result()
|
||||
except Exception as e:
|
||||
results[file_path] = None
|
||||
msg_box = msgbox_frame(
|
||||
f"错误 - {APP_NAME}",
|
||||
f"\n文件哈希值计算失败\n\n【错误信息】:{e}\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
return results
|
||||
|
||||
def hash_pop_window(self):
|
||||
msg_box = msgbox_frame(f"通知 - {APP_NAME}", "\n正在检验文件状态...\n")
|
||||
msg_box.open()
|
||||
QtWidgets.QApplication.processEvents()
|
||||
return msg_box
|
||||
|
||||
def cfg_pre_hash_compare(self, install_path, game_version, plugin_hash, installed_status):
|
||||
if not os.path.exists(install_path):
|
||||
installed_status[game_version] = False
|
||||
return
|
||||
file_hash = self.hash_calculate(install_path)
|
||||
if file_hash == plugin_hash[game_version]:
|
||||
installed_status[game_version] = True
|
||||
else:
|
||||
reply = msgbox_frame(
|
||||
f"文件校验 - {APP_NAME}",
|
||||
f"\n检测到 {game_version} 的文件哈希值不匹配,是否重新安装?\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
).exec()
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
installed_status[game_version] = False
|
||||
else:
|
||||
installed_status[game_version] = True
|
||||
|
||||
def cfg_after_hash_compare(self, install_paths, plugin_hash, installed_status):
|
||||
passed = True
|
||||
file_paths = [
|
||||
install_paths[game] for game in plugin_hash if installed_status.get(game)
|
||||
]
|
||||
hash_results = self.calculate_hashes_in_parallel(file_paths)
|
||||
|
||||
for game, hash_value in plugin_hash.items():
|
||||
if installed_status.get(game):
|
||||
file_hash = hash_results.get(install_paths[game])
|
||||
if file_hash != hash_value:
|
||||
msg_box = msgbox_frame(
|
||||
f"文件校验 - {APP_NAME}",
|
||||
f"\n检测到 {game} 的文件哈希值不匹配\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
installed_status[game] = False
|
||||
passed = False
|
||||
break
|
||||
return passed
|
||||
|
||||
class AdminPrivileges:
|
||||
def __init__(self):
|
||||
self.required_exes = [
|
||||
"nekopara_vol1.exe",
|
||||
"nekopara_vol2.exe",
|
||||
"NEKOPARAvol3.exe",
|
||||
"nekopara_vol4.exe",
|
||||
"nekopara_after.exe",
|
||||
]
|
||||
|
||||
def is_admin(self):
|
||||
try:
|
||||
return ctypes.windll.shell32.IsUserAnAdmin()
|
||||
except:
|
||||
return False
|
||||
|
||||
def request_admin_privileges(self):
|
||||
if not self.is_admin():
|
||||
msg_box = msgbox_frame(
|
||||
f"权限检测 - {APP_NAME}",
|
||||
"\n需要管理员权限运行此程序\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
)
|
||||
reply = msg_box.exec()
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
try:
|
||||
ctypes.windll.shell32.ShellExecuteW(
|
||||
None, "runas", sys.executable, " ".join(sys.argv), None, 1
|
||||
)
|
||||
except Exception as e:
|
||||
msg_box = msgbox_frame(
|
||||
f"错误 - {APP_NAME}",
|
||||
f"\n请求管理员权限失败\n\n【错误信息】:{e}\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
else:
|
||||
msg_box = msgbox_frame(
|
||||
f"权限检测 - {APP_NAME}",
|
||||
"\n无法获取管理员权限,程序将退出\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
|
||||
def check_and_terminate_processes(self):
|
||||
for proc in psutil.process_iter(["pid", "name"]):
|
||||
if proc.info["name"] in self.required_exes:
|
||||
msg_box = msgbox_frame(
|
||||
f"进程检测 - {APP_NAME}",
|
||||
f"\n检测到游戏正在运行: {proc.info['name']} \n\n是否终止?\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No,
|
||||
)
|
||||
reply = msg_box.exec()
|
||||
if reply == QtWidgets.QMessageBox.StandardButton.Yes:
|
||||
try:
|
||||
proc.terminate()
|
||||
proc.wait(timeout=3)
|
||||
except psutil.AccessDenied:
|
||||
msg_box = msgbox_frame(
|
||||
f"错误 - {APP_NAME}",
|
||||
f"\n无法关闭游戏: {proc.info['name']} \n\n请手动关闭后重启应用\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
else:
|
||||
msg_box = msgbox_frame(
|
||||
f"进程检测 - {APP_NAME}",
|
||||
f"\n未关闭的游戏: {proc.info['name']} \n\n请手动关闭后重启应用\n",
|
||||
QtWidgets.QMessageBox.StandardButton.Ok,
|
||||
)
|
||||
msg_box.exec()
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user