2025-08-11 14:42:38 +08:00
|
|
|
|
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
|
|
|
|
|
|
from utils.logger import setup_logger
|
|
|
|
|
|
|
|
|
|
|
|
# 初始化logger
|
|
|
|
|
|
logger = setup_logger("cloudflare_optimizer")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.optimized_ipv6 = None
|
|
|
|
|
|
self.optimization_done = False # 标记是否已执行过优选
|
|
|
|
|
|
self.countdown_finished = False # 标记倒计时是否结束
|
|
|
|
|
|
self.optimizing_msg_box = None
|
|
|
|
|
|
self.optimization_cancelled = False
|
|
|
|
|
|
self.ip_optimizer_thread = None
|
|
|
|
|
|
self.ipv6_optimizer_thread = None
|
|
|
|
|
|
self.has_optimized_in_session = False # 本次启动是否已执行过优选
|
|
|
|
|
|
|
|
|
|
|
|
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 get_optimized_ipv6(self):
|
|
|
|
|
|
"""获取优选的IPv6地址
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
str: 优选的IPv6地址,如果未优选则为None
|
|
|
|
|
|
"""
|
|
|
|
|
|
return self.optimized_ipv6
|
|
|
|
|
|
|
|
|
|
|
|
def start_ip_optimization(self, url):
|
|
|
|
|
|
"""开始IP优化过程
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
url: 用于优化的URL
|
|
|
|
|
|
"""
|
|
|
|
|
|
# 解析域名
|
|
|
|
|
|
hostname = urlparse(url).hostname
|
|
|
|
|
|
|
|
|
|
|
|
# 判断是否继续优选的逻辑
|
|
|
|
|
|
if self.has_optimized_in_session:
|
|
|
|
|
|
# 如果本次会话中已执行过优选,则跳过优选过程
|
|
|
|
|
|
logger.info("本次会话已执行过优选,跳过优选过程")
|
|
|
|
|
|
|
|
|
|
|
|
# 设置标记为已优选完成
|
|
|
|
|
|
self.optimization_done = True
|
|
|
|
|
|
self.countdown_finished = True
|
|
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
else:
|
|
|
|
|
|
# 如果本次会话尚未优选过,则清理可能存在的旧记录
|
|
|
|
|
|
if hostname:
|
|
|
|
|
|
# 检查hosts文件中是否已有该域名的IP记录
|
|
|
|
|
|
existing_ips = self.hosts_manager.get_hostname_entries(hostname)
|
|
|
|
|
|
if existing_ips:
|
|
|
|
|
|
logger.info(f"发现hosts文件中已有域名 {hostname} 的优选IP记录,但本次会话尚未优选过")
|
|
|
|
|
|
# 清理已有的hosts记录,准备重新优选
|
|
|
|
|
|
self.hosts_manager.clean_hostname_entries(hostname)
|
|
|
|
|
|
|
|
|
|
|
|
# 创建取消状态标记
|
|
|
|
|
|
self.optimization_cancelled = False
|
|
|
|
|
|
self.countdown_finished = False
|
|
|
|
|
|
|
|
|
|
|
|
# 检查是否启用了IPv6
|
|
|
|
|
|
use_ipv6 = False
|
|
|
|
|
|
if hasattr(self.main_window, 'config'):
|
|
|
|
|
|
use_ipv6 = self.main_window.config.get("ipv6_enabled", False)
|
|
|
|
|
|
|
|
|
|
|
|
# 如果启用了IPv6,显示警告消息
|
|
|
|
|
|
if use_ipv6:
|
|
|
|
|
|
ipv6_warning = QtWidgets.QMessageBox(self.main_window)
|
|
|
|
|
|
ipv6_warning.setWindowTitle(f"IPv6优选警告 - {self.main_window.APP_NAME}")
|
|
|
|
|
|
ipv6_warning.setText("\nIPv6优选比IPv4耗时更长且感知不强(预计耗时10分钟以上),不建议使用。\n\n确定要同时执行IPv6优选吗?\n")
|
|
|
|
|
|
ipv6_warning.setIcon(QtWidgets.QMessageBox.Icon.Warning)
|
|
|
|
|
|
|
|
|
|
|
|
# 设置图标
|
2025-08-11 16:13:58 +08:00
|
|
|
|
icon_path = resource_path(os.path.join("assets", "images", "ICO", "icon.png"))
|
2025-08-11 14:42:38 +08:00
|
|
|
|
if os.path.exists(icon_path):
|
|
|
|
|
|
pixmap = QPixmap(icon_path)
|
|
|
|
|
|
if not pixmap.isNull():
|
|
|
|
|
|
ipv6_warning.setWindowIcon(QIcon(pixmap))
|
|
|
|
|
|
|
|
|
|
|
|
yes_button = ipv6_warning.addButton("是", QtWidgets.QMessageBox.ButtonRole.YesRole)
|
|
|
|
|
|
no_button = ipv6_warning.addButton("否,仅使用IPv4", QtWidgets.QMessageBox.ButtonRole.NoRole)
|
|
|
|
|
|
cancel_button = ipv6_warning.addButton("取消优选", QtWidgets.QMessageBox.ButtonRole.RejectRole)
|
|
|
|
|
|
|
|
|
|
|
|
ipv6_warning.setDefaultButton(no_button)
|
|
|
|
|
|
ipv6_warning.exec()
|
|
|
|
|
|
|
|
|
|
|
|
if ipv6_warning.clickedButton() == cancel_button:
|
|
|
|
|
|
# 用户取消了优选
|
|
|
|
|
|
self.optimization_cancelled = True
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# 根据用户选择调整IPv6设置
|
|
|
|
|
|
if ipv6_warning.clickedButton() == no_button:
|
|
|
|
|
|
use_ipv6 = False
|
|
|
|
|
|
# 临时覆盖配置(不保存到文件)
|
|
|
|
|
|
if hasattr(self.main_window, 'config'):
|
|
|
|
|
|
self.main_window.config["ipv6_enabled"] = False
|
|
|
|
|
|
|
|
|
|
|
|
# 准备提示信息
|
|
|
|
|
|
optimization_msg = "\n正在优选Cloudflare IP,请稍候...\n\n"
|
|
|
|
|
|
if use_ipv6:
|
|
|
|
|
|
optimization_msg += "已启用IPv6支持,同时进行IPv4和IPv6优选。\n这可能需要10分钟以上,请耐心等待喵~\n"
|
|
|
|
|
|
else:
|
|
|
|
|
|
optimization_msg += "这可能需要5-10分钟,请耐心等待喵~\n"
|
|
|
|
|
|
|
|
|
|
|
|
# 使用Cloudflare图标创建消息框
|
|
|
|
|
|
self.optimizing_msg_box = msgbox_frame(
|
|
|
|
|
|
f"通知 - {self.main_window.APP_NAME}",
|
|
|
|
|
|
optimization_msg
|
|
|
|
|
|
)
|
|
|
|
|
|
# 设置Cloudflare图标
|
2025-08-11 16:13:58 +08:00
|
|
|
|
cf_icon_path = resource_path("assets/images/ICO/cloudflare_logo_icon.ico")
|
2025-08-11 14:42:38 +08:00
|
|
|
|
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_ipv4_optimization_finished)
|
|
|
|
|
|
|
|
|
|
|
|
# 如果启用IPv6,同时启动IPv6优化线程
|
|
|
|
|
|
if use_ipv6:
|
|
|
|
|
|
logger.info("IPv6已启用,将同时优选IPv6地址")
|
|
|
|
|
|
self.ipv6_optimizer_thread = IpOptimizerThread(url, use_ipv6=True)
|
|
|
|
|
|
self.ipv6_optimizer_thread.finished.connect(self.on_ipv6_optimization_finished)
|
|
|
|
|
|
self.ipv6_optimizer_thread.start()
|
|
|
|
|
|
|
|
|
|
|
|
# 启动IPv4优化线程
|
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
|
|
if hasattr(self, 'ipv6_optimizer_thread') and self.ipv6_optimizer_thread and self.ipv6_optimizer_thread.isRunning():
|
|
|
|
|
|
self.ipv6_optimizer_thread.stop()
|
|
|
|
|
|
|
|
|
|
|
|
# 恢复主窗口状态
|
|
|
|
|
|
self.main_window.setEnabled(True)
|
2025-08-13 11:58:43 +08:00
|
|
|
|
if hasattr(self.main_window, 'window_manager'):
|
|
|
|
|
|
self.main_window.window_manager.change_window_state(self.main_window.window_manager.STATE_READY)
|
2025-08-11 14:42:38 +08:00
|
|
|
|
|
|
|
|
|
|
# 显示取消消息
|
|
|
|
|
|
QtWidgets.QMessageBox.information(
|
|
|
|
|
|
self.main_window,
|
|
|
|
|
|
f"已取消 - {self.main_window.APP_NAME}",
|
|
|
|
|
|
"\n已取消IP优选和安装过程。\n"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def on_ipv4_optimization_finished(self, ip):
|
|
|
|
|
|
"""IPv4优化完成后的处理
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
ip: 优选的IP地址,如果失败则为空字符串
|
|
|
|
|
|
"""
|
|
|
|
|
|
# 如果已经取消,则不继续处理
|
|
|
|
|
|
if hasattr(self, 'optimization_cancelled') and self.optimization_cancelled:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
self.optimized_ip = ip
|
|
|
|
|
|
logger.info(f"IPv4优选完成,结果: {ip if ip else '未找到合适的IP'}")
|
|
|
|
|
|
|
|
|
|
|
|
# 检查是否还有IPv6优化正在运行
|
|
|
|
|
|
if hasattr(self, 'ipv6_optimizer_thread') and self.ipv6_optimizer_thread and self.ipv6_optimizer_thread.isRunning():
|
|
|
|
|
|
logger.info("等待IPv6优选完成...")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# 所有优选都已完成,继续处理
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
# 处理优选结果
|
|
|
|
|
|
self._process_optimization_results()
|
|
|
|
|
|
|
|
|
|
|
|
def on_ipv6_optimization_finished(self, ipv6):
|
|
|
|
|
|
"""IPv6优化完成后的处理
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
ipv6: 优选的IPv6地址,如果失败则为空字符串
|
|
|
|
|
|
"""
|
|
|
|
|
|
# 如果已经取消,则不继续处理
|
|
|
|
|
|
if hasattr(self, 'optimization_cancelled') and self.optimization_cancelled:
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
self.optimized_ipv6 = ipv6
|
|
|
|
|
|
logger.info(f"IPv6优选完成,结果: {ipv6 if ipv6 else '未找到合适的IPv6'}")
|
|
|
|
|
|
|
|
|
|
|
|
# 检查IPv4优化是否已完成
|
|
|
|
|
|
if hasattr(self, 'ip_optimizer_thread') and self.ip_optimizer_thread and self.ip_optimizer_thread.isRunning():
|
|
|
|
|
|
logger.info("等待IPv4优选完成...")
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
# 所有优选都已完成,继续处理
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
# 处理优选结果
|
|
|
|
|
|
self._process_optimization_results()
|
|
|
|
|
|
|
|
|
|
|
|
def _process_optimization_results(self):
|
|
|
|
|
|
"""处理优选的IP结果,显示相应提示"""
|
|
|
|
|
|
# 无论优选结果如何,都标记本次会话已执行过优选
|
|
|
|
|
|
self.has_optimized_in_session = True
|
|
|
|
|
|
|
|
|
|
|
|
use_ipv6 = False
|
|
|
|
|
|
if hasattr(self.main_window, 'config'):
|
|
|
|
|
|
use_ipv6 = self.main_window.config.get("ipv6_enabled", False)
|
|
|
|
|
|
|
|
|
|
|
|
# 判断优选结果
|
|
|
|
|
|
ipv4_success = bool(self.optimized_ip)
|
|
|
|
|
|
ipv6_success = bool(self.optimized_ipv6) if use_ipv6 else False
|
|
|
|
|
|
|
|
|
|
|
|
# 临时启用窗口以显示对话框
|
|
|
|
|
|
self.main_window.setEnabled(True)
|
|
|
|
|
|
|
|
|
|
|
|
hostname = urlparse(self.main_window.current_url).hostname if hasattr(self.main_window, 'current_url') else None
|
|
|
|
|
|
|
|
|
|
|
|
if not ipv4_success and (not use_ipv6 or not ipv6_success):
|
|
|
|
|
|
# 两种IP都没有优选成功
|
|
|
|
|
|
msg_box = QtWidgets.QMessageBox(self.main_window)
|
|
|
|
|
|
msg_box.setWindowTitle(f"优选失败 - {self.main_window.APP_NAME}")
|
|
|
|
|
|
|
|
|
|
|
|
fail_message = "\n未能找到合适的Cloudflare "
|
|
|
|
|
|
if use_ipv6:
|
|
|
|
|
|
fail_message += "IPv4和IPv6地址"
|
|
|
|
|
|
else:
|
|
|
|
|
|
fail_message += "IP地址"
|
|
|
|
|
|
|
|
|
|
|
|
fail_message += ",将使用默认网络进行下载。\n\n10秒后自动继续..."
|
|
|
|
|
|
|
|
|
|
|
|
msg_box.setText(fail_message)
|
|
|
|
|
|
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)
|
2025-08-13 11:58:43 +08:00
|
|
|
|
if hasattr(self.main_window, 'window_manager'):
|
2025-08-13 12:48:25 +08:00
|
|
|
|
self.main_window.window_manager.change_window_state(self.main_window.window_manager.STATE_READY)
|
2025-08-11 14:42:38 +08:00
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
# 用户点击了继续,重新禁用主窗口
|
|
|
|
|
|
self.main_window.setEnabled(False)
|
|
|
|
|
|
# 标记倒计时已完成
|
|
|
|
|
|
self.countdown_finished = True
|
|
|
|
|
|
return True
|
|
|
|
|
|
else:
|
|
|
|
|
|
# 至少有一种IP优选成功
|
|
|
|
|
|
success_message = ""
|
|
|
|
|
|
if ipv4_success:
|
|
|
|
|
|
success_message += f"IPv4: {self.optimized_ip}\n"
|
|
|
|
|
|
|
|
|
|
|
|
if ipv6_success:
|
|
|
|
|
|
success_message += f"IPv6: {self.optimized_ipv6}\n"
|
|
|
|
|
|
|
|
|
|
|
|
if hostname:
|
|
|
|
|
|
# 先清理可能存在的旧记录(只清理一次)
|
|
|
|
|
|
self.hosts_manager.clean_hostname_entries(hostname)
|
|
|
|
|
|
|
|
|
|
|
|
success = False
|
|
|
|
|
|
|
|
|
|
|
|
# 应用优选IP到hosts文件
|
|
|
|
|
|
if ipv4_success:
|
|
|
|
|
|
success = self.hosts_manager.apply_ip(hostname, self.optimized_ip, clean=False) or success
|
|
|
|
|
|
|
|
|
|
|
|
# 如果启用IPv6并且找到了IPv6地址,也应用到hosts
|
|
|
|
|
|
if ipv6_success:
|
|
|
|
|
|
success = self.hosts_manager.apply_ip(hostname, self.optimized_ipv6, clean=False) or success
|
|
|
|
|
|
|
|
|
|
|
|
# 记录此次优选操作对hosts文件进行了更新
|
|
|
|
|
|
if hasattr(self.main_window, 'config'):
|
|
|
|
|
|
self.main_window.config['last_hosts_optimized_hostname'] = hostname
|
|
|
|
|
|
from utils import save_config
|
|
|
|
|
|
save_config(self.main_window.config)
|
|
|
|
|
|
|
|
|
|
|
|
if success:
|
|
|
|
|
|
msg_box = QtWidgets.QMessageBox(self.main_window)
|
|
|
|
|
|
msg_box.setWindowTitle(f"成功 - {self.main_window.APP_NAME}")
|
|
|
|
|
|
msg_box.setText(f"\n已将优选IP应用到hosts文件:\n{success_message}\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)
|
2025-08-13 11:58:43 +08:00
|
|
|
|
if hasattr(self.main_window, 'window_manager'):
|
2025-08-13 12:48:25 +08:00
|
|
|
|
self.main_window.window_manager.change_window_state(self.main_window.window_manager.STATE_READY)
|
2025-08-11 14:42:38 +08:00
|
|
|
|
return False
|
|
|
|
|
|
else:
|
|
|
|
|
|
QtWidgets.QMessageBox.critical(
|
|
|
|
|
|
self.main_window,
|
|
|
|
|
|
f"错误 - {self.main_window.APP_NAME}",
|
|
|
|
|
|
"\n修改hosts文件失败,请检查程序是否以管理员权限运行。\n"
|
|
|
|
|
|
)
|
|
|
|
|
|
# 恢复主窗口状态
|
2025-08-13 11:58:43 +08:00
|
|
|
|
if hasattr(self.main_window, 'window_manager'):
|
2025-08-13 12:48:25 +08:00
|
|
|
|
self.main_window.window_manager.change_window_state(self.main_window.window_manager.STATE_READY)
|
2025-08-11 14:42:38 +08:00
|
|
|
|
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, 'ipv6_optimizer_thread') and self.ipv6_optimizer_thread and self.ipv6_optimizer_thread.isRunning():
|
|
|
|
|
|
self.ipv6_optimizer_thread.stop()
|
|
|
|
|
|
self.ipv6_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
|