Separate protocol action and editor titles

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2026-08-20 21:49:52 +08:00
parent 3340e8bbb3
commit c78ebcf172
9 changed files with 159 additions and 64 deletions
+13 -9
View File
@@ -38,24 +38,28 @@ def _placeholder(value):
_ = _placeholder
_TRANSLATABLE = (_('Add External Core...'),)
_TRANSLATABLE = (
_('Add External Core...'),
_('Add External Core'),
)
class ExternalCoreProtocolHandler(ProtocolHandler):
"""Own local External Core mappings while declining URI import/export."""
descriptor = ProtocolDescriptor(
EXTERNAL_CORE_TYPE,
'External Core',
'Add External Core...',
100,
True,
{
id=EXTERNAL_CORE_TYPE,
displayName='External Core',
addActionText='Add External Core...',
editorWindowTitle='Add External Core',
menuOrder=100,
separatorBefore=True,
configurationSchema={
'type': 'object',
'required': ('type', 'executable', 'arguments', 'environment'),
},
True,
False,
translatable=True,
subscriptionImportable=False,
)
schemes = tuple()
+12 -8
View File
@@ -42,20 +42,24 @@ def _placeholder(x):
_ = _placeholder
_TRANSLATABLE = (_('Add Hysteria1 Server...'),)
_TRANSLATABLE = (
_('Add Hysteria1 Server...'),
_('Add Hysteria1 Server'),
)
class Hysteria1ProtocolHandler(ProtocolHandler):
"""Own Hysteria 1 URI, mapping, validation, and export behavior."""
descriptor = ProtocolDescriptor(
'hysteria1',
'Hysteria1',
'Add Hysteria1 Server...',
50,
True,
{'type': 'object', 'required': ('server',)},
True,
id='hysteria1',
displayName='Hysteria1',
addActionText='Add Hysteria1 Server...',
editorWindowTitle='Add Hysteria1 Server',
menuOrder=50,
separatorBefore=True,
configurationSchema={'type': 'object', 'required': ('server',)},
translatable=True,
)
schemes = ('hysteria',)
+9 -5
View File
@@ -42,17 +42,21 @@ def _placeholder(x):
_ = _placeholder
_TRANSLATABLE = (_('Add Hysteria2 Server...'),)
_TRANSLATABLE = (
_('Add Hysteria2 Server...'),
_('Add Hysteria2 Server'),
)
class Hysteria2ProtocolHandler(ProtocolHandler):
"""Own Hysteria 2 URI, mapping, validation, and export behavior."""
descriptor = ProtocolDescriptor(
'hysteria2',
'Hysteria2',
'Add Hysteria2 Server...',
60,
id='hysteria2',
displayName='Hysteria2',
addActionText='Add Hysteria2 Server...',
editorWindowTitle='Add Hysteria2 Server',
menuOrder=60,
configurationSchema={'type': 'object', 'required': ('server', 'auth')},
translatable=True,
)
+33 -23
View File
@@ -172,19 +172,25 @@ _ = _placeholder
_TRANSLATABLE = (
_('Add VMess Server...'),
_('Add VMess Server'),
_('Add VLESS Server...'),
_('Add VLESS Server'),
_('Add Shadowsocks Server...'),
_('Add Shadowsocks Server'),
_('Add Trojan Server...'),
_('Add Trojan Server'),
_('Add SOCKS Server...'),
_('Add SOCKS Server'),
)
XRAY_PROTOCOL_HANDLERS = (
XrayProtocolHandler(
ProtocolDescriptor(
'VMess',
'VMess',
'Add VMess Server...',
10,
id='VMess',
displayName='VMess',
addActionText='Add VMess Server...',
editorWindowTitle='Add VMess Server',
menuOrder=10,
configurationSchema={
'type': 'object',
'required': ('outbounds',),
@@ -197,10 +203,11 @@ XRAY_PROTOCOL_HANDLERS = (
),
XrayProtocolHandler(
ProtocolDescriptor(
'VLESS',
'VLESS',
'Add VLESS Server...',
20,
id='VLESS',
displayName='VLESS',
addActionText='Add VLESS Server...',
editorWindowTitle='Add VLESS Server',
menuOrder=20,
configurationSchema={
'type': 'object',
'required': ('outbounds',),
@@ -213,10 +220,11 @@ XRAY_PROTOCOL_HANDLERS = (
),
XrayProtocolHandler(
ProtocolDescriptor(
'Shadowsocks',
'Shadowsocks',
'Add Shadowsocks Server...',
30,
id='Shadowsocks',
displayName='Shadowsocks',
addActionText='Add Shadowsocks Server...',
editorWindowTitle='Add Shadowsocks Server',
menuOrder=30,
configurationSchema={
'type': 'object',
'required': ('outbounds',),
@@ -229,10 +237,11 @@ XRAY_PROTOCOL_HANDLERS = (
),
XrayProtocolHandler(
ProtocolDescriptor(
'Trojan',
'Trojan',
'Add Trojan Server...',
40,
id='Trojan',
displayName='Trojan',
addActionText='Add Trojan Server...',
editorWindowTitle='Add Trojan Server',
menuOrder=40,
configurationSchema={
'type': 'object',
'required': ('outbounds',),
@@ -245,17 +254,18 @@ XRAY_PROTOCOL_HANDLERS = (
),
SocksProtocolHandler(
ProtocolDescriptor(
'SOCKS',
'SOCKS',
'Add SOCKS Server...',
70,
True,
{
id='SOCKS',
displayName='SOCKS',
addActionText='Add SOCKS Server...',
editorWindowTitle='Add SOCKS Server',
menuOrder=70,
separatorBefore=True,
configurationSchema={
'type': 'object',
'required': ('outbounds',),
'proxyProtocol': 'socks',
},
True,
translatable=True,
),
SOCKS_URI_SCHEMES,
'URI2ProxyOutboundObjectSocks',
+67 -3
View File
@@ -1,7 +1,7 @@
TRANSLATION = {
"Delete": {
"source": [
"Furious.Backends.Xray.AssetListWidget",
"Furious.Backends.Xray.AssetWindow",
"Furious.Backends.Xray.RoutingWindow",
"Furious.Qt.QtWidgets",
"Furious.Widget.ServerTableView",
@@ -285,6 +285,7 @@ TRANSLATION = {
},
"Close Window": {
"source": [
"Furious.Backends.Xray.AssetWindow",
"Furious.Backends.Xray.RoutingWindow",
"Furious.Window.TextEditorWindow"
],
@@ -692,8 +693,7 @@ TRANSLATION = {
},
"Exit": {
"source": [
"Furious.Actions.Exit",
"Furious.Backends.Xray.AssetWindow"
"Furious.Actions.Exit"
],
"RU": "Выход",
"ZH": "退出",
@@ -3207,5 +3207,69 @@ TRANSLATION = {
"RU": "Статистика трафика",
"ZH": "流量统计",
"isReviewed": "True"
},
"Add External Core": {
"source": [
"Furious.Backends.ExternalCore.Protocols"
],
"RU": "Добавить внешнее ядро",
"ZH": "添加外部Core",
"isReviewed": "True"
},
"Add Hysteria1 Server": {
"source": [
"Furious.Backends.Hysteria1.Protocols"
],
"RU": "Добавить сервер Hysteria 1",
"ZH": "添加Hysteria1服务器",
"isReviewed": "True"
},
"Add Hysteria2 Server": {
"source": [
"Furious.Backends.Hysteria2.Protocols"
],
"RU": "Добавить сервер Hysteria 2",
"ZH": "添加Hysteria2服务器",
"isReviewed": "True"
},
"Add VMess Server": {
"source": [
"Furious.Backends.Xray.Protocols"
],
"RU": "Добавить сервер VMess",
"ZH": "添加VMess服务器",
"isReviewed": "True"
},
"Add VLESS Server": {
"source": [
"Furious.Backends.Xray.Protocols"
],
"RU": "Добавить сервер VLESS",
"ZH": "添加VLESS服务器",
"isReviewed": "True"
},
"Add Shadowsocks Server": {
"source": [
"Furious.Backends.Xray.Protocols"
],
"RU": "Добавить сервер Shadowsocks",
"ZH": "添加Shadowsocks服务器",
"isReviewed": "True"
},
"Add Trojan Server": {
"source": [
"Furious.Backends.Xray.Protocols"
],
"RU": "Добавить сервер Trojan",
"ZH": "添加Trojan服务器",
"isReviewed": "True"
},
"Add SOCKS Server": {
"source": [
"Furious.Backends.Xray.Protocols"
],
"RU": "Добавить сервер SOCKS",
"ZH": "添加SOCKS服务器",
"isReviewed": "True"
}
}
+2 -1
View File
@@ -201,6 +201,7 @@ class ProtocolDescriptor:
id: str
displayName: str
addActionText: str
editorWindowTitle: str
menuOrder: int = 0
separatorBefore: bool = False
configurationSchema: Mapping[str, Any] = field(default_factory=dict)
@@ -273,7 +274,7 @@ class ProtocolHandler(PluginCapability):
"""Own one protocol's validation and serialization behavior."""
capabilityKind = CapabilityKind.Protocol
descriptor = ProtocolDescriptor('', '', '')
descriptor = ProtocolDescriptor('', '', '', '')
schemes = tuple()
@property
+3
View File
@@ -205,6 +205,9 @@ class PluginRegistry:
if not isinstance(descriptor.addActionText, str):
raise TypeError('protocol add-action text must be a string')
if not isinstance(descriptor.editorWindowTitle, str):
raise TypeError('protocol editor-window title must be a string')
if not isinstance(descriptor.configurationSchema, Mapping):
raise TypeError('protocol configuration schema must be a mapping')
+12 -9
View File
@@ -1789,23 +1789,26 @@ class ServerTableView(
"""Show all, manual, or one subscription group's profiles."""
self.proxyModel.setSubscriptionFilter(unique)
def addServerViaGui(
self,
protocol,
windowTitle: str = APPLICATION_NAME,
**kwargs,
):
def addServerViaGui(self, protocol, **kwargs):
"""Add server via GUI."""
factory = blankProfile(protocol)
guiEditor = self.getGuiEditorByFactory(factory, **kwargs)
windowTitle, translatable = (
kwargs.pop('windowTitle', APPLICATION_NAME),
kwargs.pop('translatable', True),
)
if translatable is True:
windowTitle = _(windowTitle)
guiEditor = self.getGuiEditorByFactory(
factory, windowTitle=windowTitle, translatable=translatable, **kwargs
)
if guiEditor is None:
# Unrecognized. Do nothing
return
guiEditor.setWindowTitle(windowTitle)
try:
guiEditor.factoryToInput(factory)
except Exception as ex:
+8 -6
View File
@@ -670,19 +670,21 @@ class HomePage(Mixins.QTranslatable, QMainWindow):
if descriptor.separatorBefore and serverActions:
serverActions.append(AppQSeparator())
actionText = (
_(descriptor.addActionText)
if descriptor.translatable
else descriptor.addActionText
)
if descriptor.translatable:
actionText = _(descriptor.addActionText)
else:
actionText = descriptor.addActionText
serverActions.append(
AppQAction(
actionText,
callback=functools.partial(
self.userServersQTableWidget.addServerViaGui,
descriptor.id,
actionText,
# By default, editor window title is translatable
windowTitle=_(descriptor.editorWindowTitle),
),
translatable=descriptor.translatable,
)
)