185 lines
6.1 KiB
Python
185 lines
6.1 KiB
Python
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() |