feat(core): 优化主窗口和UI管理功能

- 移除不再使用的UI组件,简化主窗口代码结构。
- 更新按钮状态管理,统一通过UIManager控制安装按钮状态,提升代码可读性。
- 优化解压和下载管理逻辑,确保在操作过程中提供清晰的用户反馈。
- 增强日志记录,确保在关键操作中提供详细的调试信息,便于后续排查和用户反馈。
This commit is contained in:
hyb-oyqq
2025-08-12 17:11:09 +08:00
parent 2c91319d5f
commit 4f2217ca95
10 changed files with 159 additions and 128 deletions

View File

@@ -5,6 +5,7 @@ from PySide6.QtWidgets import QMessageBox
from PySide6.QtCore import QTimer, QCoreApplication
from utils.logger import setup_logger
from workers.extraction_thread import ExtractionThread
# 初始化logger
logger = setup_logger("extraction_handler")
@@ -45,8 +46,8 @@ class ExtractionHandler:
QCoreApplication.processEvents()
# 创建并启动解压线程
self.main_window.extraction_thread = self.main_window.create_extraction_thread(
_7z_path, game_folder, plugin_path, game_version, extracted_path
self.main_window.extraction_thread = ExtractionThread(
_7z_path, game_folder, plugin_path, game_version, self.main_window, extracted_path
)
# 连接进度信号
@@ -109,7 +110,7 @@ class ExtractionHandler:
self.main_window.download_manager.on_extraction_finished(True)
else:
# 用户选择停止,保持窗口启用状态
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
# 通知DownloadManager停止下载队列
self.main_window.download_manager.on_extraction_finished(False)
return

View File

@@ -94,7 +94,7 @@ class PatchToggleHandler(QObject):
selected_game_dirs = {game: games_with_patch[game]["dir"] for game in selected_games if game in games_with_patch}
self._execute_batch_toggle(selected_game_dirs, operation, self.debug_manager.debug_mode)
self._execute_batch_toggle(selected_game_dirs, operation, self.debug_manager._is_debug_mode)
def _handle_multiple_games(self, game_dirs, debug_mode):
"""

View File

@@ -188,7 +188,7 @@ class MultiStageAnimations(QObject):
widget.show()
# 禁用所有按钮,直到动画完成
self.ui.start_install_btn.setEnabled(False)
self.ui.start_install_btn.setEnabled(False) # 动画期间禁用
self.ui.uninstall_btn.setEnabled(False)
self.ui.exit_btn.setEnabled(False)
@@ -358,7 +358,7 @@ class MultiStageAnimations(QObject):
self.clear_animations()
# 确保按钮在动画开始时被禁用
self.ui.start_install_btn.setEnabled(False)
self.ui.start_install_btn.setEnabled(False) # 动画期间禁用
self.ui.uninstall_btn.setEnabled(False)
self.ui.exit_btn.setEnabled(False)

View File

@@ -199,7 +199,7 @@ class CloudflareOptimizer:
# 恢复主窗口状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
# 显示取消消息
QtWidgets.QMessageBox.information(
@@ -332,7 +332,7 @@ class CloudflareOptimizer:
if msg_box.clickedButton() == cancel_button:
# 恢复主窗口状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return False
# 用户点击了继续,重新禁用主窗口
@@ -403,7 +403,7 @@ class CloudflareOptimizer:
if msg_box.clickedButton() == cancel_button:
# 恢复主窗口状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return False
else:
QtWidgets.QMessageBox.critical(
@@ -412,7 +412,7 @@ class CloudflareOptimizer:
"\n修改hosts文件失败请检查程序是否以管理员权限运行。\n"
)
# 恢复主窗口状态
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return False
# 用户点击了继续,重新禁用主窗口

View File

@@ -63,7 +63,7 @@ class DownloadManager:
)
return
self.main_window.ui.start_install_text.setText("正在安装")
self.main_window.ui_manager.set_install_button_state("installing")
self.main_window.setEnabled(False)
@@ -264,7 +264,7 @@ class DownloadManager:
self.main_window, f"通知 - {APP_NAME}", "\n未在选择的目录中找到支持的游戏\n"
)
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return
# 关闭可能存在的哈希校验窗口
@@ -281,7 +281,7 @@ class DownloadManager:
install_paths = self.get_install_paths()
# 创建并启动哈希线程进行预检查
self.main_window.hash_thread = self.main_window.create_hash_thread("pre", install_paths)
self.main_window.hash_thread = self.main_window.patch_detector.create_hash_thread("pre", install_paths)
self.main_window.hash_thread.pre_finished.connect(
lambda updated_status: self.on_pre_hash_finished_with_dirs(updated_status, game_dirs)
)
@@ -384,7 +384,16 @@ class DownloadManager:
layout.addWidget(list_widget)
# 添加按钮
# 添加全选/取消全选按钮
select_all_layout = QtWidgets.QHBoxLayout()
select_all_button = QtWidgets.QPushButton("全选")
deselect_all_button = QtWidgets.QPushButton("取消全选")
select_all_layout.addWidget(select_all_button)
select_all_layout.addWidget(deselect_all_button)
select_all_layout.addStretch() # 添加弹性空间,将按钮左对齐
layout.addLayout(select_all_layout)
# 添加主要操作按钮
button_layout = QtWidgets.QHBoxLayout()
ok_button = QtWidgets.QPushButton("确定")
cancel_button = QtWidgets.QPushButton("取消")
@@ -394,7 +403,22 @@ class DownloadManager:
dialog.setLayout(layout)
# 全选功能的实现
def select_all_items():
"""选择所有游戏项目"""
for i in range(list_widget.count()):
item = list_widget.item(i)
item.setSelected(True)
def deselect_all_items():
"""取消选择所有游戏项目"""
for i in range(list_widget.count()):
item = list_widget.item(i)
item.setSelected(False)
# 连接按钮信号
select_all_button.clicked.connect(select_all_items)
deselect_all_button.clicked.connect(deselect_all_items)
ok_button.clicked.connect(dialog.accept)
cancel_button.clicked.connect(dialog.reject)
@@ -435,7 +459,7 @@ class DownloadManager:
else:
if debug_mode:
logger.debug("DEBUG: 用户取消了游戏选择")
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
else:
# 如果没有可安装的游戏,显示提示
if already_installed_games:
@@ -448,7 +472,7 @@ class DownloadManager:
f"通知 - {APP_NAME}",
msg
)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
def _continue_download_after_config_fetch(self, data, error, selected_game_dirs):
"""云端配置获取完成后继续下载流程
@@ -486,7 +510,7 @@ class DownloadManager:
self.main_window, f"错误 - {APP_NAME}", "\n网络状态异常或服务器故障,请重试\n"
)
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return
self._fill_download_queue(config, selected_game_dirs)
@@ -659,7 +683,7 @@ class DownloadManager:
clicked_button = msg_box.clickedButton()
if clicked_button == cancel_button:
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
self.download_queue.clear()
return
@@ -916,7 +940,7 @@ class DownloadManager:
logger.info("下载已全部停止。")
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
QtWidgets.QMessageBox.information(
self.main_window,
@@ -960,7 +984,7 @@ class DownloadManager:
self.main_window, f"通知 - {APP_NAME}", "\n未在选择的目录中找到支持的游戏\n"
)
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return
# 过滤出存在的游戏目录
@@ -971,7 +995,7 @@ class DownloadManager:
self.main_window, f"通知 - {APP_NAME}", "\n未找到指定游戏的安装目录\n"
)
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return
self.main_window.setEnabled(False)
@@ -983,7 +1007,7 @@ class DownloadManager:
self.main_window, f"错误 - {APP_NAME}", "\n网络状态异常或服务器故障,请重试\n"
)
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return
# 填充下载队列
@@ -1104,6 +1128,32 @@ class DownloadManager:
Args:
game_dirs: 识别到的游戏目录
"""
self.main_window.hide_loading_dialog()
self.main_window.setEnabled(True)
self.main_window.patch_detector.on_offline_pre_hash_finished(updated_status, game_dirs)
self.main_window.ui_manager.hide_loading_dialog()
if not game_dirs:
self.main_window.setEnabled(True)
self.main_window.ui_manager.set_install_button_state("ready")
from PySide6.QtWidgets import QMessageBox
from config.config import APP_NAME
QMessageBox.warning(
self.main_window,
f"目录错误 - {APP_NAME}",
"\n未能识别到任何游戏目录。\n\n请确认您选择的是游戏的上级目录并且该目录中包含NEKOPARA系列游戏文件夹。\n"
)
return
self.main_window.ui_manager.show_loading_dialog("正在检查补丁状态...")
install_paths = self.get_install_paths()
# 使用异步方式进行哈希预检查
self.main_window.pre_hash_thread = self.main_window.patch_detector.create_hash_thread("pre", install_paths)
self.main_window.pre_hash_thread.pre_finished.connect(
lambda updated_status: self.on_pre_hash_finished_with_dirs(updated_status, game_dirs)
)
# 在线程自然结束时清理引用
try:
self.main_window.pre_hash_thread.finished.connect(lambda: setattr(self.main_window, 'pre_hash_thread', None))
except Exception:
pass
self.main_window.pre_hash_thread.start()

View File

@@ -4,6 +4,7 @@ from PySide6.QtWidgets import QDialog, QVBoxLayout, QRadioButton, QPushButton, Q
from PySide6.QtGui import QFont
from config.config import DOWNLOAD_THREADS
from workers.download import DownloadThread
class DownloadTaskManager:
@@ -34,7 +35,7 @@ class DownloadTaskManager:
# 按钮在file_dialog中已设置为禁用状态
# 创建并连接下载线程
self.current_download_thread = self.main_window.create_download_thread(url, _7z_path, game_version)
self.current_download_thread = DownloadThread(url, _7z_path, game_version, self.main_window)
self.current_download_thread.progress.connect(self.main_window.progress_window.update_progress)
self.current_download_thread.finished.connect(
lambda success, error: self.main_window.download_manager.on_download_finished(

View File

@@ -111,41 +111,25 @@ class OfflineModeManager:
# 要查找的补丁文件名
patch_files = ["vol.1.7z", "vol.2.7z", "vol.3.7z", "vol.4.7z", "after.7z"]
# 尝试多个可能的目录位置,从指定目录开始,然后是其父目录
# 只在指定目录中查找,不查找父目录和其他目录
search_dirs = [directory]
# 添加可能的父目录
current = directory
for i in range(3): # 最多向上查找3层目录
parent = os.path.dirname(current)
if parent and parent != current: # 确保不是根目录
search_dirs.append(parent)
current = parent
else:
break
# 添加工作目录(如果与指定目录不同)
work_dir = os.getcwd()
if work_dir not in search_dirs:
search_dirs.append(work_dir)
if debug_mode:
logger.debug(f"DEBUG: 将在以下目录中查找补丁文件: {search_dirs}")
found_patches = {}
# 扫描所有可能的目录查找补丁文件
# 扫描目录查找补丁文件
try:
# 首先尝试在指定目录查找
for search_dir in search_dirs:
# 搜索指定目录
search_dir = directory
if debug_mode:
logger.debug(f"DEBUG: 正在搜索目录: {search_dir}")
if not os.path.exists(search_dir):
if debug_mode:
logger.debug(f"DEBUG: 正在搜索目录: {search_dir}")
if not os.path.exists(search_dir):
if debug_mode:
logger.debug(f"DEBUG: 目录不存在,跳过: {search_dir}")
continue
logger.debug(f"DEBUG: 目录不存在,跳过: {search_dir}")
else:
for file in os.listdir(search_dir):
if file.lower() in patch_files:
file_path = os.path.join(search_dir, file)
@@ -156,13 +140,6 @@ class OfflineModeManager:
logger.info(f"找到离线补丁文件: {patch_name} 路径: {file_path}")
if debug_mode:
logger.debug(f"DEBUG: 找到离线补丁文件: {patch_name} 路径: {file_path}")
# 如果在当前目录找到了补丁文件,停止继续查找
if found_patches:
if debug_mode:
logger.debug(f"DEBUG: 在目录 {search_dir} 找到补丁文件,停止继续搜索")
break
except Exception as e:
logger.error(f"扫描目录时出错: {str(e)}")
@@ -870,7 +847,7 @@ class OfflineModeManager:
QMessageBox.StandardButton.Ok
).exec()
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return True
@@ -930,7 +907,7 @@ class OfflineModeManager:
else:
# 恢复UI状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return
@@ -956,8 +933,9 @@ class OfflineModeManager:
pass
# 启动解压线程
self.extraction_thread = self.main_window.create_extraction_thread(
patch_file, game_folder, plugin_path, game_version
from workers.extraction_thread import ExtractionThread
self.extraction_thread = ExtractionThread(
patch_file, game_folder, plugin_path, game_version, self.main_window
)
# 连接进度更新到窗口控件
@@ -1062,4 +1040,4 @@ class OfflineModeManager:
# 恢复UI状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")

View File

@@ -268,7 +268,7 @@ class PatchDetector:
QMessageBox.critical(self.main_window, f"文件校验失败 - {APP_NAME}", message)
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
QTimer.singleShot(100, self.main_window.show_result)
def on_offline_pre_hash_finished(self, updated_status, game_dirs):
@@ -333,7 +333,7 @@ class PatchDetector:
"\n未检测到任何需要安装补丁的游戏。\n\n请确保游戏文件夹位于选择的目录中。\n",
)
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return
from PySide6 import QtWidgets
@@ -367,7 +367,7 @@ class PatchDetector:
result = dialog.exec()
if result != QtWidgets.QDialog.DialogCode.Accepted or not list_widget.selectedItems():
self.main_window.ui.start_install_text.setText("开始安装")
self.main_window.ui_manager.set_install_button_state("ready")
return
selected_games = [item.text() for item in list_widget.selectedItems()]

View File

@@ -977,9 +977,8 @@ class UIManager:
self.main_window.config["offline_mode"] = True
self.main_window.save_config(self.main_window.config)
# 在离线模式下始终启用开始安装按钮
if hasattr(self.main_window, 'set_start_button_enabled'):
self.main_window.set_start_button_enabled(True)
# 在离线模式下启用开始安装按钮
self.set_install_button_state("ready")
# 清除版本警告标志
if hasattr(self.main_window, 'version_warning'):
@@ -1073,4 +1072,34 @@ class UIManager:
"""隐藏并销毁加载对话框."""
if self.loading_dialog:
self.loading_dialog.hide()
self.loading_dialog = None
self.loading_dialog = None
def set_install_button_state(self, state):
"""统一的安装按钮状态管理方法
Args:
state (str): 按钮状态 - "ready", "installing", "disabled", "completed"
"""
if hasattr(self.main_window, 'window_manager'):
if state == "ready":
self.main_window.window_manager.change_window_state(self.main_window.window_manager.STATE_READY)
elif state == "installing":
self.main_window.window_manager.change_window_state(self.main_window.window_manager.STATE_INSTALLING)
elif state == "disabled":
self.main_window.window_manager.change_window_state(self.main_window.window_manager.STATE_ERROR)
elif state == "completed":
self.main_window.window_manager.change_window_state(self.main_window.window_manager.STATE_COMPLETED)
else:
# 降级处理,直接设置按钮状态
if state == "ready":
self.main_window.ui.start_install_btn.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
elif state == "installing":
self.main_window.ui.start_install_btn.setEnabled(False)
self.main_window.ui.start_install_text.setText("正在安装")
elif state == "disabled":
self.main_window.ui.start_install_btn.setEnabled(False)
self.main_window.ui.start_install_text.setText("!无法安装!")
elif state == "completed":
self.main_window.ui.start_install_btn.setEnabled(True)
self.main_window.ui.start_install_text.setText("安装完成")