Files
EZProxy/child/ui/main_window.py
2025-11-10 17:29:11 +08:00

185 lines
6.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from PyQt5.QtWidgets import (
QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QTextEdit, QLabel, QSplitter,
QMessageBox, QSystemTrayIcon, QMenu
)
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QIcon, QTextCursor
from .traffic_widget import TrafficWidget
from core.v2ray_manager import V2RayManager
from core.proxy_manager import ProxyManager
class MainWindow(QMainWindow):
def __init__(self, app_context):
super().__init__()
self.app_context = app_context
self.v2ray = V2RayManager(
app_context.config['v2ray_config_path'],
app_context.config['v2ray_log_path']
)
self.proxy = ProxyManager()
self.tray_icon = None
self.init_ui()
self.init_tray()
self.init_timers()
def init_ui(self):
# 主窗口设置
self.setWindowTitle("EZProxy")
self.setWindowIcon(QIcon(str(self.app_context.resources / "icon.icns")))
self.setMinimumSize(800, 600)
# 创建中央部件
central_widget = QWidget()
main_layout = QVBoxLayout(central_widget)
# 顶部控制栏
control_layout = QHBoxLayout()
self.toggle_btn = QPushButton("启用代理")
self.toggle_btn.clicked.connect(self.toggle_proxy)
self.update_btn = QPushButton("检查更新")
self.update_btn.clicked.connect(self.check_updates)
control_layout.addWidget(self.toggle_btn)
control_layout.addWidget(self.update_btn)
control_layout.addStretch()
# 日志显示区域
self.log_view = QTextEdit()
self.log_view.setReadOnly(True)
self.log_view.setFontFamily("Menlo")
# 流量监控组件
self.traffic_widget = TrafficWidget()
# 创建分割器
splitter = QSplitter(Qt.Vertical)
splitter.addWidget(self.log_view)
splitter.addWidget(self.traffic_widget)
splitter.setSizes([400, 200])
# 添加到主布局
main_layout.addLayout(control_layout)
main_layout.addWidget(splitter)
self.setCentralWidget(central_widget)
def init_tray(self):
"""初始化系统托盘"""
self.tray_icon = QSystemTrayIcon(self)
self.tray_icon.setIcon(QIcon(str(self.app_context.resources / "icon.icns")))
tray_menu = QMenu()
toggle_action = tray_menu.addAction("启用代理")
toggle_action.triggered.connect(self.toggle_proxy)
update_action = tray_menu.addAction("检查更新")
update_action.triggered.connect(self.check_updates)
quit_action = tray_menu.addAction("退出")
quit_action.triggered.connect(self.confirm_exit)
self.tray_icon.setContextMenu(tray_menu)
self.tray_icon.activated.connect(self.tray_activated)
self.tray_icon.show()
# 默认隐藏到托盘
self.hide()
def init_timers(self):
"""初始化定时器"""
# 日志更新定时器
self.log_timer = QTimer()
self.log_timer.timeout.connect(self.update_logs)
self.log_timer.start(500)
# 流量更新定时器
self.traffic_timer = QTimer()
self.traffic_timer.timeout.connect(self.update_traffic)
self.traffic_timer.start(1000)
# 更新检查定时器 (1小时)
self.update_timer = QTimer()
self.update_timer.timeout.connect(self.auto_check_updates)
self.update_timer.start(3600000) # 1小时
def toggle_proxy(self):
"""切换代理状态"""
if self.v2ray.running:
self.stop_proxy()
else:
self.start_proxy()
def start_proxy(self):
"""启动代理服务"""
# 验证配置
if not self.app_context.validate_config():
QMessageBox.warning(self, "配置错误", "请先设置有效的代理地址")
return
# 启动v2ray
if not self.v2ray.start():
QMessageBox.critical(self, "启动失败", "无法启动v2ray核心")
return
# 配置系统代理
if not self.proxy.enable():
QMessageBox.warning(self, "代理警告", "系统代理配置失败但v2ray仍在运行")
self.toggle_btn.setText("停止代理")
self.tray_icon.setToolTip("EZProxy - 已启用")
def stop_proxy(self):
"""停止代理服务"""
self.proxy.disable()
self.v2ray.stop()
self.toggle_btn.setText("启用代理")
self.tray_icon.setToolTip("EZProxy - 已停止")
def update_logs(self):
"""更新日志显示"""
while not self.v2ray.log_queue.empty():
log_line = self.v2ray.log_queue.get()
self.log_view.append(log_line)
# 保持滚动到底部
scrollbar = self.log_view.verticalScrollBar()
scrollbar.setValue(scrollbar.maximum())
def update_traffic(self):
"""更新流量统计"""
if self.v2ray.running:
stats = self.v2ray.get_traffic_stats()
self.traffic_widget.update_stats(stats)
def closeEvent(self, event):
"""关闭事件处理"""
event.ignore()
self.hide()
self.tray_icon.showMessage(
"EZProxy",
"应用已最小化到系统托盘",
QSystemTrayIcon.Information,
2000
)
def confirm_exit(self):
"""确认退出"""
if self.v2ray.running:
reply = QMessageBox.question(
self, "确认退出",
"代理服务正在运行,确定要退出吗?",
QMessageBox.Yes | QMessageBox.No,
QMessageBox.No
)
if reply == QMessageBox.No:
return
self.stop_proxy()
QApplication.quit()
def tray_activated(self, reason):
"""托盘图标激活"""
if reason == QSystemTrayIcon.DoubleClick:
self.show()