feat(core): 优化下载管理器和进度窗口

- 在下载管理器中引入 CloudflareOptimizer、DownloadTaskManager 和 ExtractionHandler 模块,重构下载流程
- 优化下载进度更新频率,减少 UI 卡顿
- 改进下载和解压缩的处理逻辑,确保更流畅的用户体验
- 更新下载线程设置,支持更灵活的下载管理
This commit is contained in:
hyb-oyqq
2025-08-01 17:54:38 +08:00
parent 5c06802f65
commit 3fc74555cb
7 changed files with 696 additions and 497 deletions

View File

@@ -0,0 +1,254 @@
import os
from urllib.parse import urlparse
from PySide6 import QtWidgets
from PySide6.QtCore import Qt, QTimer
from PySide6.QtGui import QIcon, QPixmap
from utils import msgbox_frame, resource_path
from workers import IpOptimizerThread
class CloudflareOptimizer:
"""Cloudflare IP优化器负责处理IP优化和Cloudflare加速相关功能"""
def __init__(self, main_window, hosts_manager):
"""初始化Cloudflare优化器
Args:
main_window: 主窗口实例用于访问UI和状态
hosts_manager: Hosts文件管理器实例
"""
self.main_window = main_window
self.hosts_manager = hosts_manager
self.optimized_ip = None
self.optimization_done = False # 标记是否已执行过优选
self.countdown_finished = False # 标记倒计时是否结束
self.optimizing_msg_box = None
self.optimization_cancelled = False
self.ip_optimizer_thread = None
def is_optimization_done(self):
"""检查是否已完成优化
Returns:
bool: 是否已完成优化
"""
return self.optimization_done
def is_countdown_finished(self):
"""检查倒计时是否已完成
Returns:
bool: 倒计时是否已完成
"""
return self.countdown_finished
def get_optimized_ip(self):
"""获取优选的IP地址
Returns:
str: 优选的IP地址如果未优选则为None
"""
return self.optimized_ip
def start_ip_optimization(self, url):
"""开始IP优化过程
Args:
url: 用于优化的URL
"""
# 创建取消状态标记
self.optimization_cancelled = False
self.countdown_finished = False
# 使用Cloudflare图标创建消息框
self.optimizing_msg_box = msgbox_frame(
f"通知 - {self.main_window.APP_NAME}",
"\n正在优选Cloudflare IP请稍候...\n\n这可能需要5-10分钟请耐心等待喵~"
)
# 设置Cloudflare图标
cf_icon_path = resource_path("IMG/ICO/cloudflare_logo_icon.ico")
if os.path.exists(cf_icon_path):
cf_pixmap = QPixmap(cf_icon_path)
if not cf_pixmap.isNull():
self.optimizing_msg_box.setWindowIcon(QIcon(cf_pixmap))
self.optimizing_msg_box.setIconPixmap(cf_pixmap.scaled(64, 64, Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation))
# 添加取消按钮
self.optimizing_msg_box.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Cancel)
self.optimizing_msg_box.buttonClicked.connect(self._on_optimization_dialog_clicked)
self.optimizing_msg_box.setWindowModality(Qt.WindowModality.ApplicationModal)
# 创建并启动优化线程
self.ip_optimizer_thread = IpOptimizerThread(url)
self.ip_optimizer_thread.finished.connect(self.on_optimization_finished)
self.ip_optimizer_thread.start()
# 显示消息框(非模态,不阻塞)
self.optimizing_msg_box.open()
def _on_optimization_dialog_clicked(self, button):
"""处理优化对话框按钮点击
Args:
button: 被点击的按钮
"""
if button.text() == "Cancel": # 如果是取消按钮
# 标记已取消
self.optimization_cancelled = True
# 停止优化线程
if hasattr(self, 'ip_optimizer_thread') and self.ip_optimizer_thread and self.ip_optimizer_thread.isRunning():
self.ip_optimizer_thread.stop()
# 恢复主窗口状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
# 显示取消消息
QtWidgets.QMessageBox.information(
self.main_window,
f"已取消 - {self.main_window.APP_NAME}",
"\n已取消IP优选和安装过程。\n"
)
def on_optimization_finished(self, ip):
"""IP优化完成后的处理
Args:
ip: 优选的IP地址如果失败则为空字符串
"""
# 如果已经取消,则不继续处理
if hasattr(self, 'optimization_cancelled') and self.optimization_cancelled:
return
self.optimized_ip = ip
self.optimization_done = True
self.countdown_finished = False # 确保倒计时标志重置
# 关闭提示框
if hasattr(self, 'optimizing_msg_box') and self.optimizing_msg_box:
if self.optimizing_msg_box.isVisible():
self.optimizing_msg_box.accept()
self.optimizing_msg_box = None
# 显示优选结果
if not ip:
# 临时启用窗口以显示对话框
self.main_window.setEnabled(True)
msg_box = QtWidgets.QMessageBox(self.main_window)
msg_box.setWindowTitle(f"优选失败 - {self.main_window.APP_NAME}")
msg_box.setText("\n未能找到合适的Cloudflare IP将使用默认网络进行下载。\n\n10秒后自动继续...")
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Warning)
ok_button = msg_box.addButton("确定 (10)", QtWidgets.QMessageBox.ButtonRole.AcceptRole)
cancel_button = msg_box.addButton("取消安装", QtWidgets.QMessageBox.ButtonRole.RejectRole)
# 创建计时器实现倒计时
countdown = 10
timer = QTimer(self.main_window)
def update_countdown():
nonlocal countdown
countdown -= 1
ok_button.setText(f"确定 ({countdown})")
if countdown <= 0:
timer.stop()
if msg_box.isVisible():
msg_box.accept()
timer.timeout.connect(update_countdown)
timer.start(1000) # 每秒更新一次
# 显示对话框并等待用户响应
result = msg_box.exec()
# 停止计时器
timer.stop()
# 如果用户点击了取消安装
if msg_box.clickedButton() == cancel_button:
# 恢复主窗口状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
return False
# 用户点击了继续,重新禁用主窗口
self.main_window.setEnabled(False)
# 标记倒计时已完成
self.countdown_finished = True
return True
else:
# 应用优选IP到hosts文件
hostname = urlparse(self.main_window.current_url).hostname if hasattr(self.main_window, 'current_url') else None
if hostname:
# 先清理可能存在的旧记录
self.hosts_manager.clean_hostname_entries(hostname)
# 临时启用窗口以显示对话框
self.main_window.setEnabled(True)
if self.hosts_manager.apply_ip(hostname, ip):
msg_box = QtWidgets.QMessageBox(self.main_window)
msg_box.setWindowTitle(f"成功 - {self.main_window.APP_NAME}")
msg_box.setText(f"\n已将优选IP ({ip}) 应用到hosts文件。\n\n10秒后自动继续...")
msg_box.setIcon(QtWidgets.QMessageBox.Icon.Information)
ok_button = msg_box.addButton("确定 (10)", QtWidgets.QMessageBox.ButtonRole.AcceptRole)
cancel_button = msg_box.addButton("取消安装", QtWidgets.QMessageBox.ButtonRole.RejectRole)
# 创建计时器实现倒计时
countdown = 10
timer = QTimer(self.main_window)
def update_countdown():
nonlocal countdown
countdown -= 1
ok_button.setText(f"确定 ({countdown})")
if countdown <= 0:
timer.stop()
if msg_box.isVisible():
msg_box.accept()
timer.timeout.connect(update_countdown)
timer.start(1000) # 每秒更新一次
# 显示对话框并等待用户响应
result = msg_box.exec()
# 停止计时器
timer.stop()
# 如果用户点击了取消安装
if msg_box.clickedButton() == cancel_button:
# 恢复主窗口状态
self.main_window.setEnabled(True)
self.main_window.ui.start_install_text.setText("开始安装")
return False
else:
QtWidgets.QMessageBox.critical(
self.main_window,
f"错误 - {self.main_window.APP_NAME}",
"\n修改hosts文件失败请检查程序是否以管理员权限运行。\n"
)
# 恢复主窗口状态
self.main_window.ui.start_install_text.setText("开始安装")
return False
# 用户点击了继续,重新禁用主窗口
self.main_window.setEnabled(False)
# 标记倒计时已完成
self.countdown_finished = True
return True
def stop_optimization(self):
"""停止正在进行的IP优化"""
if hasattr(self, 'ip_optimizer_thread') and self.ip_optimizer_thread and self.ip_optimizer_thread.isRunning():
self.ip_optimizer_thread.stop()
self.ip_optimizer_thread.wait()
if hasattr(self, 'optimizing_msg_box') and self.optimizing_msg_box:
if self.optimizing_msg_box.isVisible():
self.optimizing_msg_box.accept()
self.optimizing_msg_box = None