feat(lite): merge TUN mode with IPv6 routing
This commit is contained in:
+65
-27
@@ -931,14 +931,16 @@ class SettingsServices:
|
||||
load_icon: object
|
||||
version: str
|
||||
get_port: object
|
||||
get_builtin_pac: object
|
||||
get_system_pac: object
|
||||
get_dns: object
|
||||
get_update_via_proxy: object
|
||||
get_skip_update_check: object
|
||||
get_node_display_mode: object
|
||||
get_close_behavior: object
|
||||
parse_port: object
|
||||
set_port: object
|
||||
set_builtin_pac: object
|
||||
set_system_pac: object
|
||||
set_dns: object
|
||||
set_update_via_proxy: object
|
||||
set_skip_update_check: object
|
||||
set_node_display_mode: object
|
||||
@@ -961,7 +963,7 @@ class SettingsDialog(QDialog):
|
||||
self._services = services
|
||||
self.setWindowTitle("设置")
|
||||
self.setWindowIcon(services.load_icon())
|
||||
self.setFixedSize(300, 470)
|
||||
self.setFixedSize(620, 460)
|
||||
self.setStyleSheet(f"""
|
||||
QDialog {{ background-color: {C_BG}; }}
|
||||
QLabel {{ color: {C_TEXT}; font-family: "Microsoft YaHei", "Segoe UI", sans-serif; font-size: 12px; }}
|
||||
@@ -999,6 +1001,23 @@ class SettingsDialog(QDialog):
|
||||
layout.addWidget(self.lb_hint)
|
||||
layout.addSpacing(2)
|
||||
|
||||
columns = QHBoxLayout()
|
||||
columns.setSpacing(24)
|
||||
left_col = QVBoxLayout()
|
||||
right_col = QVBoxLayout()
|
||||
left_col.setSpacing(9)
|
||||
right_col.setSpacing(9)
|
||||
left_heading = QLabel("连接与分流")
|
||||
right_heading = QLabel("节点与维护")
|
||||
for heading in (left_heading, right_heading):
|
||||
heading.setStyleSheet(f"color: {C_TITLE}; font-size: 12px; font-weight: bold;")
|
||||
heading.setAlignment(Qt.AlignCenter)
|
||||
left_col.addWidget(left_heading)
|
||||
right_col.addWidget(right_heading)
|
||||
columns.addLayout(left_col, 1)
|
||||
columns.addLayout(right_col, 1)
|
||||
layout.addLayout(columns, 1)
|
||||
|
||||
compact_button_style = f"""
|
||||
QPushButton {{ background-color: {C_CARD}; color: {C_SUBTEXT}; border: 1px solid {C_BORDER};
|
||||
border-radius: 5px; padding: 1px 7px; min-width: 34px; min-height: 18px;
|
||||
@@ -1019,7 +1038,7 @@ class SettingsDialog(QDialog):
|
||||
self.btn_whitelist.setStyleSheet(compact_button_style)
|
||||
self.btn_whitelist.clicked.connect(self._open_whitelist)
|
||||
whitelist_row.addWidget(self.btn_whitelist)
|
||||
layout.addLayout(whitelist_row)
|
||||
left_col.addLayout(whitelist_row)
|
||||
|
||||
jump_row = QHBoxLayout()
|
||||
jump_label = QLabel("代理跳板")
|
||||
@@ -1032,7 +1051,7 @@ class SettingsDialog(QDialog):
|
||||
self.btn_jump.setStyleSheet(self.btn_whitelist.styleSheet())
|
||||
self.btn_jump.clicked.connect(self._open_jump)
|
||||
jump_row.addWidget(self.btn_jump)
|
||||
layout.addLayout(jump_row)
|
||||
left_col.addLayout(jump_row)
|
||||
|
||||
third_party_row = QHBoxLayout()
|
||||
third_party_label = QLabel("第三方订阅")
|
||||
@@ -1045,7 +1064,7 @@ class SettingsDialog(QDialog):
|
||||
self.btn_third_party.setStyleSheet(self.btn_whitelist.styleSheet())
|
||||
self.btn_third_party.clicked.connect(self._open_third_party)
|
||||
third_party_row.addWidget(self.btn_third_party)
|
||||
layout.addLayout(third_party_row)
|
||||
right_col.addLayout(third_party_row)
|
||||
|
||||
log_row = QHBoxLayout()
|
||||
log_label = QLabel("日志")
|
||||
@@ -1067,22 +1086,33 @@ class SettingsDialog(QDialog):
|
||||
self.ed_port.setFixedSize(54, 22)
|
||||
self.ed_port.setEnabled(not port_locked)
|
||||
port_row.addWidget(self.ed_port)
|
||||
layout.addLayout(port_row)
|
||||
left_col.addLayout(port_row)
|
||||
|
||||
builtin_pac_row = QHBoxLayout()
|
||||
builtin_pac_label = QLabel("使用内置 PAC")
|
||||
system_pac_row = QHBoxLayout()
|
||||
builtin_pac_label = QLabel("使用系统 PAC (系统代理)")
|
||||
builtin_pac_label.setStyleSheet(f"color: {C_SUBTEXT}; font-size: 12px;")
|
||||
builtin_pac_label.setToolTip(
|
||||
"系统使用固定的本地代理端口;转发器内部仍按 PAC 规则智能判断直连或代理"
|
||||
"仅系统代理模式使用;关闭时使用内置 PAC 智能分流"
|
||||
)
|
||||
builtin_pac_row.addWidget(builtin_pac_label)
|
||||
builtin_pac_row.addStretch()
|
||||
self.cb_builtin_pac = ToggleSwitch(checked=services.get_builtin_pac())
|
||||
self.cb_builtin_pac.setToolTip(
|
||||
"系统固定指向本地代理端口,转发器内部保留 PAC 智能分流"
|
||||
)
|
||||
builtin_pac_row.addWidget(self.cb_builtin_pac)
|
||||
layout.addLayout(builtin_pac_row)
|
||||
system_pac_row.addWidget(builtin_pac_label)
|
||||
system_pac_row.addStretch()
|
||||
self.cb_system_pac = ToggleSwitch(checked=services.get_system_pac())
|
||||
self.cb_system_pac.setToolTip("系统代理且已选 PAC 规则模式时,向 Windows 写入本地 PAC 地址;TUN 模式忽略此项")
|
||||
system_pac_row.addWidget(self.cb_system_pac)
|
||||
left_col.addLayout(system_pac_row)
|
||||
|
||||
dns_row = QHBoxLayout()
|
||||
dns_label = QLabel("自定义 DNS (虚拟网卡)")
|
||||
dns_label.setStyleSheet(f"color: {C_SUBTEXT}; font-size: 12px;")
|
||||
dns_label.setToolTip("TUN 模式使用;支持 IPv4/IPv6,请填写 1-3 个 DNS 地址")
|
||||
dns_row.addWidget(dns_label)
|
||||
dns_row.addStretch()
|
||||
self.ed_dns = QLineEdit(", ".join(services.get_dns()))
|
||||
self.ed_dns.setPlaceholderText("8.8.8.8, 1.1.1.1")
|
||||
self.ed_dns.setFixedSize(120, 22)
|
||||
self.ed_dns.setEnabled(not port_locked)
|
||||
dns_row.addWidget(self.ed_dns)
|
||||
left_col.addLayout(dns_row)
|
||||
|
||||
update_row = QHBoxLayout()
|
||||
update_label = QLabel("使用代理更新")
|
||||
@@ -1092,7 +1122,7 @@ class SettingsDialog(QDialog):
|
||||
self.cb_update_proxy = ToggleSwitch(checked=services.get_update_via_proxy())
|
||||
self.cb_update_proxy.setToolTip("开启后检查更新与下载走节点隧道(CONNECT);默认直连仓库")
|
||||
update_row.addWidget(self.cb_update_proxy)
|
||||
layout.addLayout(update_row)
|
||||
right_col.addLayout(update_row)
|
||||
|
||||
skip_row = QHBoxLayout()
|
||||
skip_label = QLabel("跳过检查更新")
|
||||
@@ -1102,7 +1132,7 @@ class SettingsDialog(QDialog):
|
||||
self.cb_skip_update = ToggleSwitch(checked=services.get_skip_update_check())
|
||||
self.cb_skip_update.setToolTip("跳过 PAC 数据与程序版本检查(节点更新与登录不受影响),被跳过的检查不输出日志")
|
||||
skip_row.addWidget(self.cb_skip_update)
|
||||
layout.addLayout(skip_row)
|
||||
right_col.addLayout(skip_row)
|
||||
|
||||
node_display_row = QHBoxLayout()
|
||||
node_display_label = QLabel("节点信息显示")
|
||||
@@ -1125,7 +1155,7 @@ class SettingsDialog(QDialog):
|
||||
self.btn_node_remark.setChecked(True)
|
||||
else:
|
||||
self.btn_node_domain.setChecked(True)
|
||||
layout.addLayout(node_display_row)
|
||||
right_col.addLayout(node_display_row)
|
||||
|
||||
close_behavior_row = QHBoxLayout()
|
||||
close_behavior_label = QLabel("默认关闭行为")
|
||||
@@ -1148,7 +1178,7 @@ class SettingsDialog(QDialog):
|
||||
self.btn_close_tray.setChecked(True)
|
||||
else:
|
||||
self.btn_close_exit.setChecked(True)
|
||||
layout.addLayout(close_behavior_row)
|
||||
right_col.addLayout(close_behavior_row)
|
||||
|
||||
reset_row = QHBoxLayout()
|
||||
reset_label = QLabel("重置用户配置")
|
||||
@@ -1162,10 +1192,11 @@ class SettingsDialog(QDialog):
|
||||
self.btn_reset.setEnabled(not port_locked)
|
||||
self.btn_reset.clicked.connect(self._reset_user_config)
|
||||
reset_row.addWidget(self.btn_reset)
|
||||
layout.addLayout(reset_row)
|
||||
right_col.addLayout(reset_row)
|
||||
|
||||
layout.addLayout(log_row)
|
||||
layout.addStretch()
|
||||
right_col.addLayout(log_row)
|
||||
left_col.addStretch()
|
||||
right_col.addStretch()
|
||||
|
||||
buttons = QHBoxLayout()
|
||||
buttons.setSpacing(10)
|
||||
@@ -1233,7 +1264,8 @@ class SettingsDialog(QDialog):
|
||||
return
|
||||
self._services.reset_user_config()
|
||||
self.ed_port.setText(str(self._services.get_port()))
|
||||
self.cb_builtin_pac.setChecked(self._services.get_builtin_pac())
|
||||
self.cb_system_pac.setChecked(self._services.get_system_pac())
|
||||
self.ed_dns.setText(", ".join(self._services.get_dns()))
|
||||
self.cb_update_proxy.setChecked(self._services.get_update_via_proxy())
|
||||
self.cb_skip_update.setChecked(self._services.get_skip_update_check())
|
||||
self.btn_node_domain.setChecked(True)
|
||||
@@ -1247,8 +1279,14 @@ class SettingsDialog(QDialog):
|
||||
self.lb_hint.setText("端口应为 1-65535 的数字")
|
||||
self.lb_hint.setStyleSheet(f"color: {C_RED}; font-size: 11px;")
|
||||
return
|
||||
try:
|
||||
self._services.set_dns(self.ed_dns.text())
|
||||
except ValueError as exc:
|
||||
self.lb_hint.setText(str(exc))
|
||||
self.lb_hint.setStyleSheet(f"color: {C_RED}; font-size: 11px;")
|
||||
return
|
||||
self._services.set_port(port)
|
||||
self._services.set_builtin_pac(bool(self.cb_builtin_pac.isChecked()))
|
||||
self._services.set_system_pac(bool(self.cb_system_pac.isChecked()))
|
||||
self._services.set_update_via_proxy(bool(self.cb_update_proxy.isChecked()))
|
||||
self._services.set_skip_update_check(bool(self.cb_skip_update.isChecked()))
|
||||
self._services.set_node_display_mode(
|
||||
|
||||
+65
-1
@@ -2,7 +2,23 @@
|
||||
|
||||
from PyQt5.QtCore import Qt, QRectF, pyqtSignal
|
||||
from PyQt5.QtGui import QColor, QPainter
|
||||
from PyQt5.QtWidgets import QCheckBox, QLabel
|
||||
from PyQt5.QtWidgets import QCheckBox, QLabel, QFrame, QHBoxLayout
|
||||
|
||||
try:
|
||||
from PyQt5.QtWidgets import QGraphicsDropShadowEffect
|
||||
except ImportError: # 轻量测试桩不提供图形效果类,真实 PyQt5 仍使用阴影。
|
||||
class QGraphicsDropShadowEffect: # type: ignore[no-redef]
|
||||
def __init__(self, *_args, **_kwargs):
|
||||
pass
|
||||
|
||||
def setBlurRadius(self, *_args):
|
||||
pass
|
||||
|
||||
def setOffset(self, *_args):
|
||||
pass
|
||||
|
||||
def setColor(self, *_args):
|
||||
pass
|
||||
|
||||
from .theme import C_BORDER, C_GREEN, C_RED, C_TITLE
|
||||
|
||||
@@ -102,3 +118,51 @@ class StatusDot(QLabel):
|
||||
border: 1px solid rgba(136, 153, 170, 50);
|
||||
}}
|
||||
""")
|
||||
|
||||
|
||||
class ProxyModeCard(QFrame):
|
||||
"""整个卡片可点击;描边表示选择,圆点表示所选模式的运行状态。"""
|
||||
|
||||
clicked = pyqtSignal()
|
||||
|
||||
def __init__(self, title: str, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setCursor(Qt.PointingHandCursor)
|
||||
self._glow = QGraphicsDropShadowEffect(self)
|
||||
self._glow.setBlurRadius(12)
|
||||
self._glow.setOffset(0, 1)
|
||||
self.setGraphicsEffect(self._glow)
|
||||
row = QHBoxLayout(self)
|
||||
row.setContentsMargins(11, 10, 11, 10)
|
||||
row.setSpacing(5)
|
||||
self.title = QLabel(title)
|
||||
self.title.setStyleSheet("font-weight: bold; background: transparent;")
|
||||
self.dot = StatusDot()
|
||||
for child in (self.title, self.dot):
|
||||
child.setAttribute(Qt.WA_TransparentForMouseEvents)
|
||||
row.addWidget(self.title)
|
||||
row.addStretch()
|
||||
row.addWidget(self.dot)
|
||||
self.set_state(False, False)
|
||||
|
||||
def set_state(self, selected: bool, running: bool) -> None:
|
||||
border = C_TITLE if selected else "#e2e8ef"
|
||||
background = "#f5f7f9" if selected else "#fafcfe"
|
||||
self.setStyleSheet(
|
||||
f"QFrame {{ background-color: {background}; border: {'2px' if selected else '1px'} "
|
||||
f"solid {border}; border-radius: 8px; }}"
|
||||
"QFrame:hover { border-color: #cbd6e2; background-color: #ffffff; }"
|
||||
"QLabel { border: none; }"
|
||||
)
|
||||
self._glow.setColor(QColor(136, 153, 170, 105 if selected else 52))
|
||||
if not selected:
|
||||
self.dot.set_disabled()
|
||||
elif running:
|
||||
self.dot.set_on()
|
||||
else:
|
||||
self.dot.set_off()
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() == Qt.LeftButton and self.rect().contains(event.pos()):
|
||||
self.clicked.emit()
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
Reference in New Issue
Block a user