From f1f262e4ee4791b9d08a7b822fda323ae3f38473 Mon Sep 17 00:00:00 2001 From: Loren Eteval Date: Sun, 9 Aug 2026 09:51:56 +0800 Subject: [PATCH] Refactor package architecture Signed-off-by: Loren Eteval --- .../Configuration.py} | 0 .../Connect.py => Actions/Connection.py} | 21 +- Furious/{TrayActions => Actions}/Exit.py | 0 Furious/{TrayActions => Actions}/Import.py | 5 +- Furious/{TrayActions => Actions}/Language.py | 0 Furious/{TrayActions => Actions}/Routing.py | 2 +- Furious/{TrayActions => Actions}/Settings.py | 0 .../{TrayActions => Actions}/SystemProxy.py | 0 Furious/{TrayActions => Actions}/__init__.py | 8 +- .../{Application.py => DesktopApplication.py} | 45 +- .../{SystemTrayIcon.py => TrayIcon.py} | 10 +- Furious/Application/__init__.py | 6 +- .../Official => Backends}/Configuration.py | 4 +- .../Hysteria1/Editor.py} | 10 +- .../Official => Backends}/Hysteria1/Plugin.py | 8 +- .../Core.py => Backends/Hysteria1/Process.py} | 0 .../Hysteria1/__init__.py | 0 .../Hysteria2/Editor.py} | 12 +- .../Official => Backends}/Hysteria2/Plugin.py | 16 +- .../Core.py => Backends/Hysteria2/Process.py} | 0 .../Official => Backends}/Hysteria2/TUN.py | 0 .../Hysteria2/TunSettingsDialog.py} | 4 +- .../Hysteria2/__init__.py | 0 .../Xray/AssetDownloadManager.py} | 0 .../Xray/AssetListWidget.py} | 6 +- .../Xray/AssetWindow.py} | 10 +- .../Official => Backends}/Xray/Plugin.py | 40 +- .../Xray/Core.py => Backends/Xray/Process.py} | 2 +- .../Official => Backends}/Xray/Routing.py | 2 +- .../Xray/RoutingWindow.py} | 15 +- .../Xray/ShadowsocksEditor.py} | 14 +- .../Xray/SocksEditor.py} | 14 +- .../Official => Backends}/Xray/TUN.py | 0 .../GuiVTLS.py => Backends/Xray/TlsEditor.py} | 6 +- .../Xray/TransportEditor.py} | 6 +- .../Xray/TrojanEditor.py} | 14 +- .../Xray/TunSettingsDialog.py} | 4 +- .../Xray/VlessEditor.py} | 14 +- .../Xray/VmessEditor.py} | 14 +- .../Official => Backends}/Xray/__init__.py | 0 .../Official => Backends}/__init__.py | 2 +- Furious/Core/CoreProcessWorker.py | 2 +- Furious/{Library => Domain}/Configuration.py | 4 +- .../Encoder.py => Domain/Encoding.py} | 8 +- Furious/{Library => Domain}/__init__.py | 6 +- Furious/Externals/GenTranslation.py | 712 +++++++++--------- .../{ApplicationFactory.py => Application.py} | 6 +- .../Interface/{EncoderFactory.py => Codec.py} | 4 +- .../{GuiEditorItemFactory.py => Editor.py} | 10 +- .../{CoreProcessFactory.py => Process.py} | 8 +- .../{UserServersTableItem.py => Server.py} | 6 +- .../{StorageFactory.py => Storage.py} | 4 +- Furious/Interface/__init__.py | 26 +- Furious/Plugins/Registry.py | 35 +- Furious/Plugins/__init__.py | 2 + .../Qt/{GuiEditorXXX.py => EditorWidgets.py} | 16 +- Furious/Qt/QtGui.py | 2 +- Furious/Qt/QtWidgets.py | 2 +- Furious/Qt/__init__.py | 10 +- .../Routings.py} | 4 +- .../UserServers.py => Repository/Servers.py} | 6 +- Furious/{Library => Repository}/Storage.py | 8 +- .../Subscriptions.py} | 4 +- .../TunSettings.py} | 4 +- Furious/Repository/__init__.py | 24 + .../{CoreManager.py => ConnectionManager.py} | 16 +- .../ConnectivityManager.py} | 18 +- .../DNSResolver.py => Service/DnsResolver.py} | 10 +- .../UpdateManager.py} | 8 +- Furious/Service/__init__.py | 12 +- Furious/Utility/AppMainProcess.py | 6 +- .../ConnectionProgressWidget.py} | 12 +- ...erversQTableView.py => ServerTableView.py} | 101 ++- ...QTableView.py => SubscriptionTableView.py} | 36 +- Furious/{Qt => Widget}/WaitingSpinner.py | 0 Furious/Widget/__init__.py | 26 +- .../IndentDialog.py} | 6 +- .../{LogViewerWindow.py => LogWindow.py} | 6 +- .../{AppMainWindow.py => MainWindow.py} | 92 ++- .../NetworkTestDialog.py} | 6 +- .../ProxyBypassDialog.py} | 6 +- Furious/{Widget => Window}/QRCodeWindow.py | 2 +- ...serSubsWindow.py => SubscriptionWindow.py} | 18 +- .../{Widget => Window}/TextEditorWindow.py | 7 +- .../TunSettingsDialog.py} | 10 +- Furious/Window/__init__.py | 26 +- Furious/__main__.py | 10 +- Translation.py | 2 +- 88 files changed, 869 insertions(+), 794 deletions(-) rename Furious/{TrayActions/EditConfiguration.py => Actions/Configuration.py} (100%) rename Furious/{TrayActions/Connect.py => Actions/Connection.py} (95%) rename Furious/{TrayActions => Actions}/Exit.py (100%) rename Furious/{TrayActions => Actions}/Import.py (99%) rename Furious/{TrayActions => Actions}/Language.py (100%) rename Furious/{TrayActions => Actions}/Routing.py (99%) rename Furious/{TrayActions => Actions}/Settings.py (100%) rename Furious/{TrayActions => Actions}/SystemProxy.py (100%) rename Furious/{TrayActions => Actions}/__init__.py (86%) rename Furious/Application/{Application.py => DesktopApplication.py} (94%) rename Furious/Application/{SystemTrayIcon.py => TrayIcon.py} (97%) rename Furious/{Plugins/Official => Backends}/Configuration.py (99%) rename Furious/{Plugins/Official/Hysteria1/GuiHysteria1.py => Backends/Hysteria1/Editor.py} (98%) rename Furious/{Plugins/Official => Backends}/Hysteria1/Plugin.py (96%) rename Furious/{Plugins/Official/Hysteria1/Core.py => Backends/Hysteria1/Process.py} (100%) rename Furious/{Plugins/Official => Backends}/Hysteria1/__init__.py (100%) rename Furious/{Plugins/Official/Hysteria2/GuiHysteria2.py => Backends/Hysteria2/Editor.py} (98%) rename Furious/{Plugins/Official => Backends}/Hysteria2/Plugin.py (93%) rename Furious/{Plugins/Official/Hysteria2/Core.py => Backends/Hysteria2/Process.py} (100%) rename Furious/{Plugins/Official => Backends}/Hysteria2/TUN.py (100%) rename Furious/{Plugins/Official/Hysteria2/GuiTUNSettings.py => Backends/Hysteria2/TunSettingsDialog.py} (98%) rename Furious/{Plugins/Official => Backends}/Hysteria2/__init__.py (100%) rename Furious/{Plugins/Official/Xray/XrayAssetDownloadManager.py => Backends/Xray/AssetDownloadManager.py} (100%) rename Furious/{Plugins/Official/Xray/XrayAssetViewerQListWidget.py => Backends/Xray/AssetListWidget.py} (98%) rename Furious/{Plugins/Official/Xray/XrayAssetViewerWindow.py => Backends/Xray/AssetWindow.py} (93%) rename Furious/{Plugins/Official => Backends}/Xray/Plugin.py (93%) rename Furious/{Plugins/Official/Xray/Core.py => Backends/Xray/Process.py} (99%) rename Furious/{Plugins/Official => Backends}/Xray/Routing.py (98%) rename Furious/{Plugins/Official/Xray/UserRoutingWindow.py => Backends/Xray/RoutingWindow.py} (99%) rename Furious/{Plugins/Official/Xray/GuiShadowsocks.py => Backends/Xray/ShadowsocksEditor.py} (95%) rename Furious/{Plugins/Official/Xray/GuiSocks.py => Backends/Xray/SocksEditor.py} (94%) rename Furious/{Plugins/Official => Backends}/Xray/TUN.py (100%) rename Furious/{Plugins/Official/Xray/GuiVTLS.py => Backends/Xray/TlsEditor.py} (99%) rename Furious/{Plugins/Official/Xray/GuiVTransport.py => Backends/Xray/TransportEditor.py} (99%) rename Furious/{Plugins/Official/Xray/GuiTrojan.py => Backends/Xray/TrojanEditor.py} (94%) rename Furious/{Plugins/Official/Xray/GuiTUNSettings.py => Backends/Xray/TunSettingsDialog.py} (98%) rename Furious/{Plugins/Official/Xray/GuiVLESS.py => Backends/Xray/VlessEditor.py} (97%) rename Furious/{Plugins/Official/Xray/GuiVMess.py => Backends/Xray/VmessEditor.py} (97%) rename Furious/{Plugins/Official => Backends}/Xray/__init__.py (100%) rename Furious/{Plugins/Official => Backends}/__init__.py (92%) rename Furious/{Library => Domain}/Configuration.py (98%) rename Furious/{Library/Encoder.py => Domain/Encoding.py} (95%) rename Furious/{Library => Domain}/__init__.py (86%) rename Furious/Interface/{ApplicationFactory.py => Application.py} (92%) rename Furious/Interface/{EncoderFactory.py => Codec.py} (95%) rename Furious/Interface/{GuiEditorItemFactory.py => Editor.py} (86%) rename Furious/Interface/{CoreProcessFactory.py => Process.py} (94%) rename Furious/Interface/{UserServersTableItem.py => Server.py} (94%) rename Furious/Interface/{StorageFactory.py => Storage.py} (95%) rename Furious/Qt/{GuiEditorXXX.py => EditorWidgets.py} (96%) rename Furious/{Library/UserRoutings.py => Repository/Routings.py} (95%) rename Furious/{Library/UserServers.py => Repository/Servers.py} (93%) rename Furious/{Library => Repository}/Storage.py (95%) rename Furious/{Library/UserSubs.py => Repository/Subscriptions.py} (96%) rename Furious/{Library/UserTUNSettings.py => Repository/TunSettings.py} (95%) create mode 100644 Furious/Repository/__init__.py rename Furious/Service/{CoreManager.py => ConnectionManager.py} (97%) rename Furious/{Qt/NetworkConnectivityManager.py => Service/ConnectivityManager.py} (85%) rename Furious/{Qt/DNSResolver.py => Service/DnsResolver.py} (96%) rename Furious/{Qt/UpdatesManager.py => Service/UpdateManager.py} (97%) rename Furious/{TrayActions/ConnectProgressBar.py => Widget/ConnectionProgressWidget.py} (92%) rename Furious/Widget/{UserServersQTableView.py => ServerTableView.py} (96%) rename Furious/Widget/{UserSubsQTableView.py => SubscriptionTableView.py} (95%) rename Furious/{Qt => Widget}/WaitingSpinner.py (100%) rename Furious/{Widget/IndentSpinBox.py => Window/IndentDialog.py} (94%) rename Furious/Window/{LogViewerWindow.py => LogWindow.py} (97%) rename Furious/Window/{AppMainWindow.py => MainWindow.py} (90%) rename Furious/{Widget/GuiCustomizeNetworkTest.py => Window/NetworkTestDialog.py} (97%) rename Furious/{Widget/GuiCustomizeProxyBypass.py => Window/ProxyBypassDialog.py} (96%) rename Furious/{Widget => Window}/QRCodeWindow.py (99%) rename Furious/Window/{UserSubsWindow.py => SubscriptionWindow.py} (92%) rename Furious/{Widget => Window}/TextEditorWindow.py (98%) rename Furious/{Widget/GuiTUNSettings.py => Window/TunSettingsDialog.py} (98%) diff --git a/Furious/TrayActions/EditConfiguration.py b/Furious/Actions/Configuration.py similarity index 100% rename from Furious/TrayActions/EditConfiguration.py rename to Furious/Actions/Configuration.py diff --git a/Furious/TrayActions/Connect.py b/Furious/Actions/Connection.py similarity index 95% rename from Furious/TrayActions/Connect.py rename to Furious/Actions/Connection.py index ba1f28f..373147f 100644 --- a/Furious/TrayActions/Connect.py +++ b/Furious/Actions/Connection.py @@ -21,12 +21,13 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * +from Furious.Repository import * from Furious.Plugins import getPluginRegistry from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Service import CoreManager -from Furious.TrayActions.ConnectProgressBar import ConnectProgressBar +from Furious.Service import ConnectionManager, UpdateManager +from Furious.Widget.ConnectionProgressWidget import ConnectionProgressWidget from PySide6 import QtCore @@ -69,13 +70,13 @@ class ConnectAction(AppQAction): ) self.actionQueue = queue.Queue() - self.coreManager = CoreManager() - self.progressBar = ConnectProgressBar() + self.coreManager = ConnectionManager() + self.progressBar = ConnectionProgressWidget() self.actionTimer = QtCore.QTimer() self.actionTimer.timeout.connect(lambda: self.callActionFromQueue()) - self.updatesManager = UpdatesManager() + self.updatesManager = UpdateManager() def reset(self): """Restore the connect action to its initial state.""" @@ -358,7 +359,7 @@ class ConnectAction(AppQAction): if callable(action): action() - def coreExitCallback(self, core: CoreProcessFactory, exitcode: int): + def coreExitCallback(self, core: CoreProcess, exitcode: int): """Handle the core exit callback.""" def putItem(item): @@ -370,11 +371,11 @@ class ConnectAction(AppQAction): pass - if exitcode == CoreProcessFactory.ExitCode.SystemShuttingDown.value: + if exitcode == CoreProcess.ExitCode.SystemShuttingDown.value: # System shutting down. Do nothing return None - if exitcode == CoreProcessFactory.ExitCode.ConfigurationError.value: + if exitcode == CoreProcess.ExitCode.ConfigurationError.value: putItem( functools.partial( self.doDisconnectWithTrayMessage, @@ -384,7 +385,7 @@ class ConnectAction(AppQAction): return None - if exitcode == CoreProcessFactory.ExitCode.ServerStartFailure.value: + if exitcode == CoreProcess.ExitCode.ServerStartFailure.value: putItem( functools.partial( self.doDisconnectWithTrayMessage, diff --git a/Furious/TrayActions/Exit.py b/Furious/Actions/Exit.py similarity index 100% rename from Furious/TrayActions/Exit.py rename to Furious/Actions/Exit.py diff --git a/Furious/TrayActions/Import.py b/Furious/Actions/Import.py similarity index 99% rename from Furious/TrayActions/Import.py rename to Furious/Actions/Import.py index 956da6c..bbb4405 100644 --- a/Furious/TrayActions/Import.py +++ b/Furious/Actions/Import.py @@ -20,10 +20,11 @@ from __future__ import annotations from Furious.Frozenlib import * -from Furious.Library import * +from Furious.Domain import * +from Furious.Repository import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Qt.WaitingSpinner import * +from Furious.Widget.WaitingSpinner import * from PySide6 import QtCore from PySide6.QtGui import QColor diff --git a/Furious/TrayActions/Language.py b/Furious/Actions/Language.py similarity index 100% rename from Furious/TrayActions/Language.py rename to Furious/Actions/Language.py diff --git a/Furious/TrayActions/Routing.py b/Furious/Actions/Routing.py similarity index 99% rename from Furious/TrayActions/Routing.py rename to Furious/Actions/Routing.py index 9fb7897..94a8851 100644 --- a/Furious/TrayActions/Routing.py +++ b/Furious/Actions/Routing.py @@ -20,7 +20,7 @@ from __future__ import annotations from Furious.Frozenlib import * -from Furious.Library import * +from Furious.Repository import * from Furious.Plugins import getPluginRegistry from Furious.Qt import * from Furious.Qt import gettext as _ diff --git a/Furious/TrayActions/Settings.py b/Furious/Actions/Settings.py similarity index 100% rename from Furious/TrayActions/Settings.py rename to Furious/Actions/Settings.py diff --git a/Furious/TrayActions/SystemProxy.py b/Furious/Actions/SystemProxy.py similarity index 100% rename from Furious/TrayActions/SystemProxy.py rename to Furious/Actions/SystemProxy.py diff --git a/Furious/TrayActions/__init__.py b/Furious/Actions/__init__.py similarity index 86% rename from Furious/TrayActions/__init__.py rename to Furious/Actions/__init__.py index 6c029e9..245cf8d 100644 --- a/Furious/TrayActions/__init__.py +++ b/Furious/Actions/__init__.py @@ -15,13 +15,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""Expose system-tray actions used by the application.""" +"""Expose reusable application actions and action menus.""" from __future__ import annotations -from .Connect import ConnectAction -from .ConnectProgressBar import ConnectProgressBar -from .EditConfiguration import EditConfigurationAction +from .Configuration import EditConfigurationAction +from .Connection import ConnectAction from .Exit import ExitAction from .Import import ( ImportAction, @@ -37,7 +36,6 @@ from .SystemProxy import SystemProxyAction __all__ = [ 'ConnectAction', - 'ConnectProgressBar', 'EditConfigurationAction', 'ExitAction', 'ImportAction', diff --git a/Furious/Application/Application.py b/Furious/Application/DesktopApplication.py similarity index 94% rename from Furious/Application/Application.py rename to Furious/Application/DesktopApplication.py index 4af593f..6c3bad0 100644 --- a/Furious/Application/Application.py +++ b/Furious/Application/DesktopApplication.py @@ -22,14 +22,15 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * from Furious.Core import Tun2socks -from Furious.Plugins import getPluginRegistry +from Furious.Backends import OFFICIAL_PLUGIN_TYPES +from Furious.Plugins import initializePluginRegistry from Furious.Qt import AppStyleSheet from Furious.Qt.TextEditorTheme import configureEditorLogMetadata from Furious.Qt import gettext as _ -from Furious.Library import * -from Furious.Application.SystemTrayIcon import * -from Furious.Window.AppMainWindow import * -from Furious.Window.LogViewerWindow import * +from Furious.Repository import * +from Furious.Application.TrayIcon import * +from Furious.Window.LogWindow import * +from Furious.Window.MainWindow import * from PySide6 import QtCore from PySide6.QtGui import * @@ -168,11 +169,11 @@ class ApplicationThemeDetector(QtCore.QObject): super().__init__(*args, **kwargs) -class Application(ApplicationFactory, SingletonApplication): +class DesktopApplication(ApplicationRunner, SingletonApplication): """Represent application.""" def __init__(self, argv): - """Initialize the Application.""" + """Initialize the desktop application.""" super().__init__(argv) self.setApplicationName(APPLICATION_NAME) @@ -229,7 +230,7 @@ class Application(ApplicationFactory, SingletonApplication): datastr = str(data) if datastr == AppBuiltinCommand.Empty.value: - if isinstance(self.systemTray, SystemTrayIcon): + if isinstance(self.systemTray, TrayIcon): logger.info('attempting to start multiple instance. Show tray message') self.systemTray.showMessage(_('Already started')) @@ -246,17 +247,17 @@ class Application(ApplicationFactory, SingletonApplication): def configureLogging(self): """Configure logging.""" - self.logViewerWindowSelf = LogViewerWindow( + self.logViewerWindowSelf = LogWindow( tabTitle=_('Furious Log'), fontFamily=self.customFontName, pointSizeSettingsName='LogViewerWidgetPointSizeSelf', ) - self.logViewerWindowCore = LogViewerWindow( + self.logViewerWindowCore = LogWindow( tabTitle=_('Core Log'), fontFamily=self.customFontName, pointSizeSettingsName='LogViewerWidgetPointSizeCore', ) - self.logViewerWindowTun_ = LogViewerWindow( + self.logViewerWindowTun_ = LogWindow( tabTitle=_('Tun2socks Log'), fontFamily=self.customFontName, pointSizeSettingsName='LogViewerWidgetPointSizeTun_', @@ -298,7 +299,7 @@ class Application(ApplicationFactory, SingletonApplication): @staticmethod def addEnviron(): """Add environ.""" - pluginRegistry = getPluginRegistry() + pluginRegistry = initializePluginRegistry(OFFICIAL_PLUGIN_TYPES) configureEditorLogMetadata( lambda: (*pluginRegistry.coreVersions(), Tun2socks.version()), pluginRegistry.logTimestampPatterns, @@ -321,7 +322,7 @@ class Application(ApplicationFactory, SingletonApplication): def isSystemTrayConnected(self): """Return whether system tray connected.""" - if isinstance(self.systemTray, SystemTrayIcon): + if isinstance(self.systemTray, TrayIcon): return self.systemTray.ConnectAction.isConnected() else: return False @@ -467,11 +468,11 @@ class Application(ApplicationFactory, SingletonApplication): # sys.exit(None) in multiprocessing will produce # exitcode 1 in some Python version, which is # not what we want. - return ApplicationFactory.ExitCode.ExitSuccess.value + return ApplicationRunner.ExitCode.ExitSuccess.value - if not SystemTrayIcon.isSystemTrayAvailable(): + if not TrayIcon.isSystemTrayAvailable(): raise SystemTrayUnavailable( - 'SystemTrayIcon is not available on this platform' + 'TrayIcon is not available on this platform' ) self.addEnviron() @@ -560,9 +561,9 @@ class Application(ApplicationFactory, SingletonApplication): # Mandatory self.setQuitOnLastWindowClosed(False) - self.aboutToQuit.connect(Application.cleanup) + self.aboutToQuit.connect(DesktopApplication.cleanup) - Win32Session.set(Application.cleanup) + Win32Session.set(DesktopApplication.cleanup) Win32Session.run() if AppSettings.get('SystemProxyMode') == AppBuiltinProxyMode.Auto.value: @@ -570,8 +571,8 @@ class Application(ApplicationFactory, SingletonApplication): SystemProxy.off() SystemProxy.daemonOn_() - self.mainWindow = AppMainWindow() - self.systemTray = SystemTrayIcon() + self.mainWindow = MainWindow() + self.systemTray = TrayIcon() if PLATFORM == 'Darwin': if AppSettings.isStateON_('HideDockIcon'): @@ -601,10 +602,10 @@ class Application(ApplicationFactory, SingletonApplication): return self.exec() except SystemTrayUnavailable: - return ApplicationFactory.ExitCode.PlatformNotSupported.value + return ApplicationRunner.ExitCode.PlatformNotSupported.value except Exception: # Any non-exit exceptions traceback.print_exc() - return ApplicationFactory.ExitCode.UnknownException.value + return ApplicationRunner.ExitCode.UnknownException.value diff --git a/Furious/Application/SystemTrayIcon.py b/Furious/Application/TrayIcon.py similarity index 97% rename from Furious/Application/SystemTrayIcon.py rename to Furious/Application/TrayIcon.py index 9ec16ea..ae9c767 100644 --- a/Furious/Application/SystemTrayIcon.py +++ b/Furious/Application/TrayIcon.py @@ -22,7 +22,7 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.TrayActions import * +from Furious.Actions import * from PySide6 import QtCore from PySide6.QtWidgets import QSystemTrayIcon @@ -32,7 +32,7 @@ import platform logger = logging.getLogger(__name__) -__all__ = ['SystemTrayIcon'] +__all__ = ['TrayIcon'] _MACOS_DISCONNECTED_MONOCHROME_OPACITY = 0.55 @@ -41,7 +41,7 @@ _TRANSLATABLE_ADMIN = [ ] -class SystemTrayIcon( +class TrayIcon( Mixins.QTranslatable, Mixins.ConnectionAware, Mixins.ThemeAware, @@ -50,7 +50,7 @@ class SystemTrayIcon( """Represent system tray icon.""" def __init__(self, *args, **kwargs): - """Initialize the SystemTrayIcon.""" + """Initialize the tray icon.""" super().__init__(*args, **kwargs) actions = [ @@ -71,7 +71,7 @@ class SystemTrayIcon( self._dynamicMenuRefs = [] # Some old version PySide6 does not have setMenu method - # for QAction. Protect it. Currently only used in SystemTrayIcon + # for QAction. Protect it. Currently only used in TrayIcon if hasattr(AppQAction, 'setMenu'): logger.info('contextMenu uses setMenu implementation') diff --git a/Furious/Application/__init__.py b/Furious/Application/__init__.py index c221a7f..a686ec7 100644 --- a/Furious/Application/__init__.py +++ b/Furious/Application/__init__.py @@ -19,7 +19,7 @@ from __future__ import annotations -from .Application import Application -from .SystemTrayIcon import SystemTrayIcon +from .DesktopApplication import DesktopApplication +from .TrayIcon import TrayIcon -__all__ = ['Application', 'SystemTrayIcon'] +__all__ = ['DesktopApplication', 'TrayIcon'] diff --git a/Furious/Plugins/Official/Configuration.py b/Furious/Backends/Configuration.py similarity index 99% rename from Furious/Plugins/Official/Configuration.py rename to Furious/Backends/Configuration.py index 838aab7..d86e2ce 100644 --- a/Furious/Plugins/Official/Configuration.py +++ b/Furious/Backends/Configuration.py @@ -21,8 +21,8 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library.Configuration import ConfigFactory -from Furious.Library.Encoder import * +from Furious.Domain.Configuration import ConfigFactory +from Furious.Domain.Encoding import * from typing import Union, Tuple diff --git a/Furious/Plugins/Official/Hysteria1/GuiHysteria1.py b/Furious/Backends/Hysteria1/Editor.py similarity index 98% rename from Furious/Plugins/Official/Hysteria1/GuiHysteria1.py rename to Furious/Backends/Hysteria1/Editor.py index 8de557f..cc8fb0b 100644 --- a/Furious/Plugins/Official/Hysteria1/GuiHysteria1.py +++ b/Furious/Backends/Hysteria1/Editor.py @@ -21,7 +21,7 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import ConfigFactory +from Furious.Domain import ConfigFactory from Furious.Qt import * from Furious.Qt import gettext as _ @@ -32,7 +32,7 @@ from PySide6.QtWidgets import * import logging import functools -__all__ = ['GuiHysteria1'] +__all__ = ['Hysteria1Editor'] logger = logging.getLogger(__name__) @@ -343,7 +343,7 @@ class GuiHy1GroupBoxTLS(GuiEditorWidgetQGroupBox): ] -class GuiHy1GroupBoxOther(GuiEditorItemFactory, AppQGroupBox): +class GuiHy1GroupBoxOther(EditorBinding, AppQGroupBox): """Represent GUI hy1 group box other.""" def __init__(self, **kwargs): @@ -366,11 +366,11 @@ class GuiHy1GroupBoxOther(GuiEditorItemFactory, AppQGroupBox): pass -class GuiHysteria1(GuiEditorWidgetQDialog): +class Hysteria1Editor(GuiEditorWidgetQDialog): """Represent GUI hysteria1.""" def __init__(self, *args, **kwargs): - """Initialize the GuiHysteria1.""" + """Initialize the Hysteria 1 configuration editor.""" super().__init__(*args, **kwargs) self.setTabText(Protocol.Hysteria1.value) diff --git a/Furious/Plugins/Official/Hysteria1/Plugin.py b/Furious/Backends/Hysteria1/Plugin.py similarity index 96% rename from Furious/Plugins/Official/Hysteria1/Plugin.py rename to Furious/Backends/Hysteria1/Plugin.py index 3595c95..b9903b4 100644 --- a/Furious/Plugins/Official/Hysteria1/Plugin.py +++ b/Furious/Backends/Hysteria1/Plugin.py @@ -22,9 +22,9 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Qt.DynamicTranslate import gettext as _ from Furious.Plugins.API import * -from Furious.Plugins.Official.Configuration import * +from Furious.Backends.Configuration import * -from .Core import * +from .Process import * import copy import logging @@ -94,9 +94,9 @@ class Hysteria1Plugin(FuriousPlugin): def createEditorForProtocol(self, protocol, parent=None, **kwargs): """Create the Hysteria 1 editor.""" # Plugin discovery can occur while the Furious.Qt package is initializing. - from .GuiHysteria1 import GuiHysteria1 + from .Editor import Hysteria1Editor - return GuiHysteria1(parent=parent, **kwargs) + return Hysteria1Editor(parent=parent, **kwargs) def routingOptions(self, config=None): """Return the routing modes supported by Hysteria 1.""" diff --git a/Furious/Plugins/Official/Hysteria1/Core.py b/Furious/Backends/Hysteria1/Process.py similarity index 100% rename from Furious/Plugins/Official/Hysteria1/Core.py rename to Furious/Backends/Hysteria1/Process.py diff --git a/Furious/Plugins/Official/Hysteria1/__init__.py b/Furious/Backends/Hysteria1/__init__.py similarity index 100% rename from Furious/Plugins/Official/Hysteria1/__init__.py rename to Furious/Backends/Hysteria1/__init__.py diff --git a/Furious/Plugins/Official/Hysteria2/GuiHysteria2.py b/Furious/Backends/Hysteria2/Editor.py similarity index 98% rename from Furious/Plugins/Official/Hysteria2/GuiHysteria2.py rename to Furious/Backends/Hysteria2/Editor.py index 01d80f0..2e654e0 100644 --- a/Furious/Plugins/Official/Hysteria2/GuiHysteria2.py +++ b/Furious/Backends/Hysteria2/Editor.py @@ -21,7 +21,7 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import ConfigFactory +from Furious.Domain import ConfigFactory from Furious.Qt import * from Furious.Qt import gettext as _ @@ -32,7 +32,7 @@ from PySide6.QtWidgets import * import logging import functools -__all__ = ['GuiHysteria2'] +__all__ = ['Hysteria2Editor'] logger = logging.getLogger(__name__) @@ -699,7 +699,7 @@ class GuiHy2GroupBoxProxy(GuiEditorWidgetQGroupBox): ] -class GuiHy2GroupBoxObfs(GuiEditorItemFactory, AppQGroupBox): +class GuiHy2GroupBoxObfs(EditorBinding, AppQGroupBox): """Represent GUI hy2 group box obfs.""" def __init__(self, **kwargs): @@ -848,7 +848,7 @@ class GuiHy2ProjectWebsiteURL(AppQLabel): self.setWebsiteURL() -class GuiHy2GroupBoxOther(GuiEditorItemFactory, AppQGroupBox): +class GuiHy2GroupBoxOther(EditorBinding, AppQGroupBox): """Represent GUI hy2 group box other.""" def __init__(self, **kwargs): @@ -871,11 +871,11 @@ class GuiHy2GroupBoxOther(GuiEditorItemFactory, AppQGroupBox): pass -class GuiHysteria2(GuiEditorWidgetQDialog): +class Hysteria2Editor(GuiEditorWidgetQDialog): """Represent GUI hysteria2.""" def __init__(self, *args, **kwargs): - """Initialize the GuiHysteria2.""" + """Initialize the Hysteria 2 configuration editor.""" super().__init__(*args, **kwargs) self.setTabText(Protocol.Hysteria2.value) diff --git a/Furious/Plugins/Official/Hysteria2/Plugin.py b/Furious/Backends/Hysteria2/Plugin.py similarity index 93% rename from Furious/Plugins/Official/Hysteria2/Plugin.py rename to Furious/Backends/Hysteria2/Plugin.py index 3e67067..4282bfb 100644 --- a/Furious/Plugins/Official/Hysteria2/Plugin.py +++ b/Furious/Backends/Hysteria2/Plugin.py @@ -22,9 +22,9 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Qt.DynamicTranslate import gettext as _ from Furious.Plugins.API import * -from Furious.Plugins.Official.Configuration import * +from Furious.Backends.Configuration import * -from .Core import Hysteria2 +from .Process import Hysteria2 from .TUN import * import copy @@ -103,9 +103,9 @@ class Hysteria2Plugin(FuriousPlugin): def createEditorForProtocol(self, protocol, parent=None, **kwargs): """Create the Hysteria 2 editor.""" # Plugin discovery can occur while the Furious.Qt package is initializing. - from .GuiHysteria2 import GuiHysteria2 + from .Editor import Hysteria2Editor - return GuiHysteria2(parent=parent, **kwargs) + return Hysteria2Editor(parent=parent, **kwargs) def createManagementActions(self, parent=None, **kwargs): """Create Hysteria 2 native TUN management actions.""" @@ -115,7 +115,7 @@ class Hysteria2Plugin(FuriousPlugin): from Furious.Qt import AppQAction, showMBoxNewChangesNextTime from Furious.Qt import gettext as _ - from .GuiTUNSettings import GuiHysteria2TUNSettings + from .TunSettingsDialog import Hysteria2TunSettingsDialog useHysteria2TUNAction = AppQAction( _('Use Hysteria2 TUN'), @@ -136,7 +136,7 @@ class Hysteria2Plugin(FuriousPlugin): useHysteria2TUNAction, AppQAction( _('Customize Hysteria2 TUN Settings...'), - callback=lambda: GuiHysteria2TUNSettings( + callback=lambda: Hysteria2TunSettingsDialog( parent=parent, isConnectionActive=lambda: isCoreActive(Hysteria2), ).open(), @@ -146,7 +146,7 @@ class Hysteria2Plugin(FuriousPlugin): def prepareTUN(self, config) -> bool: """Add Hysteria 2 native TUN mode when enabled and safe to route.""" if not isHysteria2TUNEnabled(): - # Work on CoreManager's connection copy so a stored native TUN block + # Work on ConnectionManager's copy so a stored native TUN block # cannot run alongside the external tun2socks implementation. config.pop('tun', None) @@ -154,7 +154,7 @@ class Hysteria2Plugin(FuriousPlugin): if PLATFORM == 'Linux' and not SystemRuntime.isAdmin(): # Native Hysteria 2 creates the interface and routing table in its - # own process, so it cannot use CoreManager's privileged helper. + # own process, so it cannot use ConnectionManager's privileged helper. # Keep the existing external tun2socks path available instead. config.pop('tun', None) diff --git a/Furious/Plugins/Official/Hysteria2/Core.py b/Furious/Backends/Hysteria2/Process.py similarity index 100% rename from Furious/Plugins/Official/Hysteria2/Core.py rename to Furious/Backends/Hysteria2/Process.py diff --git a/Furious/Plugins/Official/Hysteria2/TUN.py b/Furious/Backends/Hysteria2/TUN.py similarity index 100% rename from Furious/Plugins/Official/Hysteria2/TUN.py rename to Furious/Backends/Hysteria2/TUN.py diff --git a/Furious/Plugins/Official/Hysteria2/GuiTUNSettings.py b/Furious/Backends/Hysteria2/TunSettingsDialog.py similarity index 98% rename from Furious/Plugins/Official/Hysteria2/GuiTUNSettings.py rename to Furious/Backends/Hysteria2/TunSettingsDialog.py index 2f1089d..b25c5e0 100644 --- a/Furious/Plugins/Official/Hysteria2/GuiTUNSettings.py +++ b/Furious/Backends/Hysteria2/TunSettingsDialog.py @@ -34,7 +34,7 @@ import copy import logging import functools -__all__ = ['GuiHysteria2TUNSettings'] +__all__ = ['Hysteria2TunSettingsDialog'] logger = logging.getLogger(__name__) @@ -262,7 +262,7 @@ class Hysteria2TUNDocumentationURL(AppQLabel): self.setWebsiteURL() -class GuiHysteria2TUNSettings(GuiEditorWidgetQDialog): +class Hysteria2TunSettingsDialog(GuiEditorWidgetQDialog): """Edit and persist Hysteria 2 native TUN settings.""" def __init__(self, *args, **kwargs): diff --git a/Furious/Plugins/Official/Hysteria2/__init__.py b/Furious/Backends/Hysteria2/__init__.py similarity index 100% rename from Furious/Plugins/Official/Hysteria2/__init__.py rename to Furious/Backends/Hysteria2/__init__.py diff --git a/Furious/Plugins/Official/Xray/XrayAssetDownloadManager.py b/Furious/Backends/Xray/AssetDownloadManager.py similarity index 100% rename from Furious/Plugins/Official/Xray/XrayAssetDownloadManager.py rename to Furious/Backends/Xray/AssetDownloadManager.py diff --git a/Furious/Plugins/Official/Xray/XrayAssetViewerQListWidget.py b/Furious/Backends/Xray/AssetListWidget.py similarity index 98% rename from Furious/Plugins/Official/Xray/XrayAssetViewerQListWidget.py rename to Furious/Backends/Xray/AssetListWidget.py index aeee701..eb9fb6a 100644 --- a/Furious/Plugins/Official/Xray/XrayAssetViewerQListWidget.py +++ b/Furious/Backends/Xray/AssetListWidget.py @@ -33,7 +33,7 @@ import logging import datetime import functools -__all__ = ['XrayAssetViewerQListWidget'] +__all__ = ['XrayAssetListWidget'] logger = logging.getLogger(__name__) @@ -59,11 +59,11 @@ class MBoxAssetExists(AppQMessageBox): self.moveToCenter() -class XrayAssetViewerQListWidget(Mixins.ThemeAware, AppQListWidget): +class XrayAssetListWidget(Mixins.ThemeAware, AppQListWidget): """Provide the Xray asset viewer Qt list widget.""" def __init__(self, *args, **kwargs): - """Initialize the XrayAssetViewerQListWidget.""" + """Initialize the Xray asset list widget.""" super().__init__(*args, **kwargs) self.setAlternatingRowColors(True) diff --git a/Furious/Plugins/Official/Xray/XrayAssetViewerWindow.py b/Furious/Backends/Xray/AssetWindow.py similarity index 93% rename from Furious/Plugins/Official/Xray/XrayAssetViewerWindow.py rename to Furious/Backends/Xray/AssetWindow.py index 32eb5f9..3d4ea86 100644 --- a/Furious/Plugins/Official/Xray/XrayAssetViewerWindow.py +++ b/Furious/Backends/Xray/AssetWindow.py @@ -23,7 +23,7 @@ from Furious.Frozenlib import * from Furious.Qt import * from Furious.Qt import gettext as _ -from .XrayAssetViewerQListWidget import * +from .AssetListWidget import * from PySide6 import QtCore from PySide6.QtGui import * @@ -31,21 +31,21 @@ from PySide6.QtWidgets import * import logging -__all__ = ['XrayAssetViewerWindow'] +__all__ = ['XrayAssetWindow'] logger = logging.getLogger(__name__) -class XrayAssetViewerWindow(AppQMainWindow): +class XrayAssetWindow(AppQMainWindow): """Present the Xray asset viewer window.""" def __init__(self, *args, **kwargs): - """Initialize the XrayAssetViewerWindow.""" + """Initialize the Xray asset window.""" super().__init__(*args, **kwargs) self.setWindowTitle(_('Xray-core Asset File')) - self.xrayAssetViewerWidget = XrayAssetViewerQListWidget(parent=self) + self.xrayAssetViewerWidget = XrayAssetListWidget(parent=self) self.setCentralWidget(self.xrayAssetViewerWidget) if versionToValue(PYSIDE6_VERSION) <= versionToValue('6.1.3'): diff --git a/Furious/Plugins/Official/Xray/Plugin.py b/Furious/Backends/Xray/Plugin.py similarity index 93% rename from Furious/Plugins/Official/Xray/Plugin.py rename to Furious/Backends/Xray/Plugin.py index 73485c9..ebe99fb 100644 --- a/Furious/Plugins/Official/Xray/Plugin.py +++ b/Furious/Backends/Xray/Plugin.py @@ -22,11 +22,11 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Qt.DynamicTranslate import gettext as _ from Furious.Core import * -from Furious.Library import * +from Furious.Repository import * from Furious.Plugins.API import * -from Furious.Plugins.Official.Configuration import * +from Furious.Backends.Configuration import * -from .Core import * +from .Process import * from .Routing import * from .TUN import * @@ -161,18 +161,18 @@ class XrayPlugin(FuriousPlugin): def createEditorForProtocol(self, protocol, parent=None, **kwargs): """Create the Xray editor matching a protocol identifier.""" # Plugin discovery can occur while the Furious.Qt package is initializing. - from .GuiShadowsocks import GuiShadowsocks - from .GuiSocks import GuiSocks - from .GuiTrojan import GuiTrojan - from .GuiVLESS import GuiVLESS - from .GuiVMess import GuiVMess + from .ShadowsocksEditor import ShadowsocksEditor + from .SocksEditor import SocksEditor + from .TrojanEditor import TrojanEditor + from .VlessEditor import VlessEditor + from .VmessEditor import VmessEditor editors = { - 'vmess': GuiVMess, - 'vless': GuiVLESS, - 'shadowsocks': GuiShadowsocks, - 'socks': GuiSocks, - 'trojan': GuiTrojan, + 'vmess': VmessEditor, + 'vless': VlessEditor, + 'shadowsocks': ShadowsocksEditor, + 'socks': SocksEditor, + 'trojan': TrojanEditor, } editorType = editors.get(_protocolId(protocol)) @@ -195,12 +195,12 @@ class XrayPlugin(FuriousPlugin): ) from Furious.Qt import gettext as _ - from .GuiTUNSettings import GuiXrayTUNSettings - from .UserRoutingWindow import UserRoutingWindow - from .XrayAssetViewerWindow import XrayAssetViewerWindow + from .AssetWindow import XrayAssetWindow + from .RoutingWindow import XrayRoutingWindow + from .TunSettingsDialog import XrayTunSettingsDialog - routingEditor = UserRoutingWindow(parent=parent, **kwargs) - assetViewer = XrayAssetViewerWindow(parent=parent) + routingEditor = XrayRoutingWindow(parent=parent, **kwargs) + assetViewer = XrayAssetWindow(parent=parent) def showRoutingDialog(): """Restore and foreground the persistent routing editor window.""" @@ -237,7 +237,7 @@ class XrayPlugin(FuriousPlugin): useXrayTUNAction, AppQAction( _('Customize Xray-core TUN Settings...'), - callback=lambda: GuiXrayTUNSettings( + callback=lambda: XrayTunSettingsDialog( parent=parent, isConnectionActive=lambda: isCoreActive(XrayCore), ).open(), @@ -443,7 +443,7 @@ class XrayPlugin(FuriousPlugin): return # The download manager is Qt-based and is not needed until this hook runs. - from .XrayAssetDownloadManager import XrayAssetDownloadManager + from .AssetDownloadManager import XrayAssetDownloadManager try: assetDownloadManager = self._assetDownloadManager diff --git a/Furious/Plugins/Official/Xray/Core.py b/Furious/Backends/Xray/Process.py similarity index 99% rename from Furious/Plugins/Official/Xray/Core.py rename to Furious/Backends/Xray/Process.py index 19d8aae..4c34f0b 100644 --- a/Furious/Plugins/Official/Xray/Core.py +++ b/Furious/Backends/Xray/Process.py @@ -21,7 +21,7 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * from Furious.Core import * from enum import Enum diff --git a/Furious/Plugins/Official/Xray/Routing.py b/Furious/Backends/Xray/Routing.py similarity index 98% rename from Furious/Plugins/Official/Xray/Routing.py rename to Furious/Backends/Xray/Routing.py index 49d34fd..ac517c0 100644 --- a/Furious/Plugins/Official/Xray/Routing.py +++ b/Furious/Backends/Xray/Routing.py @@ -19,7 +19,7 @@ from __future__ import annotations -from Furious.Library import * +from Furious.Repository import * __all__ = ['cleanRoutingRule', 'customRoutingObjectFromSettings'] diff --git a/Furious/Plugins/Official/Xray/UserRoutingWindow.py b/Furious/Backends/Xray/RoutingWindow.py similarity index 99% rename from Furious/Plugins/Official/Xray/UserRoutingWindow.py rename to Furious/Backends/Xray/RoutingWindow.py index ef0883a..f57ad97 100644 --- a/Furious/Plugins/Official/Xray/UserRoutingWindow.py +++ b/Furious/Backends/Xray/RoutingWindow.py @@ -20,7 +20,8 @@ from __future__ import annotations from Furious.Frozenlib import * -from Furious.Library import * +from Furious.Domain import * +from Furious.Repository import * from Furious.Qt import * from Furious.Qt import gettext as _ @@ -35,7 +36,7 @@ import functools from .Routing import cleanRoutingRule -__all__ = ['UserRoutingWindow'] +__all__ = ['XrayRoutingWindow'] logger = logging.getLogger(__name__) @@ -1187,13 +1188,13 @@ class UserRoutingTableView(Mixins.QTranslatable, AppQTableView): dialog.open() -class UserRoutingWindow(AppQMainWindow): +class XrayRoutingWindow(AppQMainWindow): """Present the user routing window.""" DEFAULT_WINDOW_SIZE = QtCore.QSize(980, 560) def __init__(self, *args, **kwargs): - """Initialize the UserRoutingWindow.""" + """Initialize the Xray routing editor window.""" super().__init__(*args, **kwargs) self.setWindowTitle(_('Edit Routing')) @@ -1225,17 +1226,17 @@ class UserRoutingWindow(AppQMainWindow): def setWidthAndHeight(self): """Apply the default size for the user routing window.""" if AppSettings.get('UserRoutingWindowGeometry') is None: - self.resize(UserRoutingWindow.DEFAULT_WINDOW_SIZE) + self.resize(XrayRoutingWindow.DEFAULT_WINDOW_SIZE) else: if PLATFORM == 'Darwin': - self.resize(UserRoutingWindow.DEFAULT_WINDOW_SIZE) + self.resize(XrayRoutingWindow.DEFAULT_WINDOW_SIZE) else: try: self.restoreGeometry(AppSettings.get('UserRoutingWindowGeometry')) except Exception: # Any non-exit exceptions - self.resize(UserRoutingWindow.DEFAULT_WINDOW_SIZE) + self.resize(XrayRoutingWindow.DEFAULT_WINDOW_SIZE) try: self.restoreState(AppSettings.get('UserRoutingWindowState')) diff --git a/Furious/Plugins/Official/Xray/GuiShadowsocks.py b/Furious/Backends/Xray/ShadowsocksEditor.py similarity index 95% rename from Furious/Plugins/Official/Xray/GuiShadowsocks.py rename to Furious/Backends/Xray/ShadowsocksEditor.py index da98956..64b21b1 100644 --- a/Furious/Plugins/Official/Xray/GuiShadowsocks.py +++ b/Furious/Backends/Xray/ShadowsocksEditor.py @@ -21,16 +21,16 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Plugins.Official.Configuration import * -from Furious.Plugins.Official.Xray.GuiVTransport import * -from Furious.Plugins.Official.Xray.GuiVTLS import * +from Furious.Backends.Configuration import * +from Furious.Backends.Xray.TlsEditor import * +from Furious.Backends.Xray.TransportEditor import * import functools -__all__ = ['GuiShadowsocks'] +__all__ = ['ShadowsocksEditor'] getProxyOutboundServer = functools.partial( ConfigXray.getProxyOutboundServer, @@ -214,11 +214,11 @@ class GuiSSGroupBoxProxy(GuiEditorWidgetQGroupBox): ] -class GuiShadowsocks(GuiEditorWidgetQDialog): +class ShadowsocksEditor(GuiEditorWidgetQDialog): """Represent GUI shadowsocks.""" def __init__(self, *args, **kwargs): - """Initialize the GuiShadowsocks.""" + """Initialize the Shadowsocks configuration editor.""" super().__init__(*args, **kwargs) self.setTabText(Protocol.Shadowsocks.value) diff --git a/Furious/Plugins/Official/Xray/GuiSocks.py b/Furious/Backends/Xray/SocksEditor.py similarity index 94% rename from Furious/Plugins/Official/Xray/GuiSocks.py rename to Furious/Backends/Xray/SocksEditor.py index 47fbebb..80fec2c 100644 --- a/Furious/Plugins/Official/Xray/GuiSocks.py +++ b/Furious/Backends/Xray/SocksEditor.py @@ -21,16 +21,16 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Plugins.Official.Configuration import * -from Furious.Plugins.Official.Xray.GuiVTransport import * -from Furious.Plugins.Official.Xray.GuiVTLS import * +from Furious.Backends.Configuration import * +from Furious.Backends.Xray.TlsEditor import * +from Furious.Backends.Xray.TransportEditor import * import functools -__all__ = ['GuiSocks'] +__all__ = ['SocksEditor'] getProxyOutboundServer = functools.partial( ConfigXray.getProxyOutboundServer, @@ -157,11 +157,11 @@ class GuiSocksGroupBoxProxy(GuiEditorWidgetQGroupBox): ] -class GuiSocks(GuiEditorWidgetQDialog): +class SocksEditor(GuiEditorWidgetQDialog): """Represent GUI SOCKS.""" def __init__(self, *args, **kwargs): - """Initialize the GuiSocks.""" + """Initialize the SOCKS configuration editor.""" super().__init__(*args, **kwargs) self.setTabText(Protocol.Socks.value) diff --git a/Furious/Plugins/Official/Xray/TUN.py b/Furious/Backends/Xray/TUN.py similarity index 100% rename from Furious/Plugins/Official/Xray/TUN.py rename to Furious/Backends/Xray/TUN.py diff --git a/Furious/Plugins/Official/Xray/GuiVTLS.py b/Furious/Backends/Xray/TlsEditor.py similarity index 99% rename from Furious/Plugins/Official/Xray/GuiVTLS.py rename to Furious/Backends/Xray/TlsEditor.py index 09dddc1..0759a95 100644 --- a/Furious/Plugins/Official/Xray/GuiVTLS.py +++ b/Furious/Backends/Xray/TlsEditor.py @@ -20,9 +20,9 @@ from __future__ import annotations from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt import * -from Furious.Plugins.Official.Configuration import * +from Furious.Backends.Configuration import * from PySide6 import QtCore from PySide6.QtWidgets import * @@ -738,7 +738,7 @@ class GuiVTLSPageStackedWidget(QStackedWidget): page.connectActivated(func) -class GuiVTLSQGroupBox(GuiEditorItemFactory, AppQGroupBox): +class GuiVTLSQGroupBox(EditorBinding, AppQGroupBox): """Group the GUI vtlsq editor controls.""" def __init__(self, **kwargs): diff --git a/Furious/Plugins/Official/Xray/GuiVTransport.py b/Furious/Backends/Xray/TransportEditor.py similarity index 99% rename from Furious/Plugins/Official/Xray/GuiVTransport.py rename to Furious/Backends/Xray/TransportEditor.py index b6dd961..2e4a6fb 100644 --- a/Furious/Plugins/Official/Xray/GuiVTransport.py +++ b/Furious/Backends/Xray/TransportEditor.py @@ -20,10 +20,10 @@ from __future__ import annotations from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Plugins.Official.Configuration import * +from Furious.Backends.Configuration import * from PySide6.QtWidgets import * @@ -1923,7 +1923,7 @@ class GuiVTransportPageStackedWidget(QStackedWidget): page.connectActivated(func) -class GuiVTransportQGroupBox(GuiEditorItemFactory, AppQGroupBox): +class GuiVTransportQGroupBox(EditorBinding, AppQGroupBox): """Group the GUI v transport q editor controls.""" def __init__(self, **kwargs): diff --git a/Furious/Plugins/Official/Xray/GuiTrojan.py b/Furious/Backends/Xray/TrojanEditor.py similarity index 94% rename from Furious/Plugins/Official/Xray/GuiTrojan.py rename to Furious/Backends/Xray/TrojanEditor.py index b11f650..4ad1236 100644 --- a/Furious/Plugins/Official/Xray/GuiTrojan.py +++ b/Furious/Backends/Xray/TrojanEditor.py @@ -21,16 +21,16 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Plugins.Official.Configuration import * -from Furious.Plugins.Official.Xray.GuiVTransport import * -from Furious.Plugins.Official.Xray.GuiVTLS import * +from Furious.Backends.Configuration import * +from Furious.Backends.Xray.TlsEditor import * +from Furious.Backends.Xray.TransportEditor import * import functools -__all__ = ['GuiTrojan'] +__all__ = ['TrojanEditor'] getProxyOutboundServer = functools.partial( ConfigXray.getProxyOutboundServer, @@ -158,11 +158,11 @@ class GuiTrojanGroupBoxProxy(GuiEditorWidgetQGroupBox): ] -class GuiTrojan(GuiEditorWidgetQDialog): +class TrojanEditor(GuiEditorWidgetQDialog): """Represent GUI trojan.""" def __init__(self, *args, **kwargs): - """Initialize the GuiTrojan.""" + """Initialize the Trojan configuration editor.""" super().__init__(*args, **kwargs) self.setTabText(Protocol.Trojan.value) diff --git a/Furious/Plugins/Official/Xray/GuiTUNSettings.py b/Furious/Backends/Xray/TunSettingsDialog.py similarity index 98% rename from Furious/Plugins/Official/Xray/GuiTUNSettings.py rename to Furious/Backends/Xray/TunSettingsDialog.py index 36c50f2..4388034 100644 --- a/Furious/Plugins/Official/Xray/GuiTUNSettings.py +++ b/Furious/Backends/Xray/TunSettingsDialog.py @@ -34,7 +34,7 @@ import copy import logging import functools -__all__ = ['GuiXrayTUNSettings'] +__all__ = ['XrayTunSettingsDialog'] logger = logging.getLogger(__name__) @@ -227,7 +227,7 @@ class GuiXrayTUNSettingsGroupBoxNetwork(GuiEditorWidgetQGroupBox): ] -class GuiXrayTUNSettings(GuiEditorWidgetQDialog): +class XrayTunSettingsDialog(GuiEditorWidgetQDialog): """Edit and persist Xray-core native TUN settings.""" def __init__(self, *args, **kwargs): diff --git a/Furious/Plugins/Official/Xray/GuiVLESS.py b/Furious/Backends/Xray/VlessEditor.py similarity index 97% rename from Furious/Plugins/Official/Xray/GuiVLESS.py rename to Furious/Backends/Xray/VlessEditor.py index 1b4ce2b..ef56295 100644 --- a/Furious/Plugins/Official/Xray/GuiVLESS.py +++ b/Furious/Backends/Xray/VlessEditor.py @@ -21,19 +21,19 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Plugins.Official.Configuration import * -from Furious.Plugins.Official.Xray.GuiVTransport import * -from Furious.Plugins.Official.Xray.GuiVTLS import * +from Furious.Backends.Configuration import * +from Furious.Backends.Xray.TlsEditor import * +from Furious.Backends.Xray.TransportEditor import * from PySide6.QtWidgets import * import uuid import functools -__all__ = ['GuiVLESS'] +__all__ = ['VlessEditor'] getProxyOutboundServer = functools.partial( ConfigXray.getProxyOutboundServer, @@ -357,11 +357,11 @@ class GuiVLESSGroupBoxProxy(GuiEditorWidgetQGroupBox): ] -class GuiVLESS(GuiEditorWidgetQDialog): +class VlessEditor(GuiEditorWidgetQDialog): """Represent GUI VLESS.""" def __init__(self, *args, **kwargs): - """Initialize the GuiVLESS.""" + """Initialize the VLESS configuration editor.""" super().__init__(*args, **kwargs) self.setTabText(Protocol.VLESS.value) diff --git a/Furious/Plugins/Official/Xray/GuiVMess.py b/Furious/Backends/Xray/VmessEditor.py similarity index 97% rename from Furious/Plugins/Official/Xray/GuiVMess.py rename to Furious/Backends/Xray/VmessEditor.py index 9741be7..b5e5073 100644 --- a/Furious/Plugins/Official/Xray/GuiVMess.py +++ b/Furious/Backends/Xray/VmessEditor.py @@ -21,19 +21,19 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Plugins.Official.Configuration import * -from Furious.Plugins.Official.Xray.GuiVTransport import * -from Furious.Plugins.Official.Xray.GuiVTLS import * +from Furious.Backends.Configuration import * +from Furious.Backends.Xray.TlsEditor import * +from Furious.Backends.Xray.TransportEditor import * from PySide6.QtWidgets import * import uuid import functools -__all__ = ['GuiVMess'] +__all__ = ['VmessEditor'] getProxyOutboundServer = functools.partial( ConfigXray.getProxyOutboundServer, @@ -366,11 +366,11 @@ class GuiVMessGroupBoxProxy(GuiEditorWidgetQGroupBox): ] -class GuiVMess(GuiEditorWidgetQDialog): +class VmessEditor(GuiEditorWidgetQDialog): """Represent GUI v mess.""" def __init__(self, *args, **kwargs): - """Initialize the GuiVMess.""" + """Initialize the VMess configuration editor.""" super().__init__(*args, **kwargs) self.setTabText(Protocol.VMess.value) diff --git a/Furious/Plugins/Official/Xray/__init__.py b/Furious/Backends/Xray/__init__.py similarity index 100% rename from Furious/Plugins/Official/Xray/__init__.py rename to Furious/Backends/Xray/__init__.py diff --git a/Furious/Plugins/Official/__init__.py b/Furious/Backends/__init__.py similarity index 92% rename from Furious/Plugins/Official/__init__.py rename to Furious/Backends/__init__.py index 6747dfd..7bc3fd3 100644 --- a/Furious/Plugins/Official/__init__.py +++ b/Furious/Backends/__init__.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""Register the core plugins maintained with Furious itself.""" +"""Expose the official proxy backend implementations bundled with Furious.""" from __future__ import annotations diff --git a/Furious/Core/CoreProcessWorker.py b/Furious/Core/CoreProcessWorker.py index 43dcd7e..20c1e0e 100644 --- a/Furious/Core/CoreProcessWorker.py +++ b/Furious/Core/CoreProcessWorker.py @@ -208,7 +208,7 @@ class MsgQueue(multiprocessing.queues.Queue): self.startTimer() -class CoreProcessMonitor(CoreProcessFactory, ABC): +class CoreProcessMonitor(CoreProcess, ABC): """Track the state and lifetime of a proxy-core child process.""" StopJoinTimeout = 3 diff --git a/Furious/Library/Configuration.py b/Furious/Domain/Configuration.py similarity index 98% rename from Furious/Library/Configuration.py rename to Furious/Domain/Configuration.py index a5941ab..08c1313 100644 --- a/Furious/Library/Configuration.py +++ b/Furious/Domain/Configuration.py @@ -19,7 +19,7 @@ from __future__ import annotations -from Furious.Interface.UserServersTableItem import UserServersTableItem +from Furious.Interface.Server import ServerTableItem from typing import Union @@ -39,7 +39,7 @@ __all__ = [ ] -class ConfigFactory(UserServersTableItem, dict): +class ConfigFactory(ServerTableItem, dict): """ ConfigurationFactory is how Furious sees the core config. diff --git a/Furious/Library/Encoder.py b/Furious/Domain/Encoding.py similarity index 95% rename from Furious/Library/Encoder.py rename to Furious/Domain/Encoding.py index 91b9de6..971e5c3 100644 --- a/Furious/Library/Encoder.py +++ b/Furious/Domain/Encoding.py @@ -36,7 +36,7 @@ __all__ = [ ] -class JSONEncoder(EncoderFactory): +class JSONEncoder(Codec): """Encode and decode data using JSON.""" @staticmethod @@ -52,7 +52,7 @@ class JSONEncoder(EncoderFactory): return json.loads(data, **kwargs) -class UJSONEncoder(EncoderFactory): +class UJSONEncoder(Codec): """Encode and decode data using ujson.""" @staticmethod @@ -74,7 +74,7 @@ class UJSONEncoder(EncoderFactory): return ujson.loads(data, **kwargs) -class Base64Encoder(EncoderFactory): +class Base64Encoder(Codec): """Encode and decode data using base64.""" @staticmethod @@ -90,7 +90,7 @@ class Base64Encoder(EncoderFactory): return base64.b64decode(data, validate=validate, **kwargs) -class PyBase64Encoder(EncoderFactory): +class PyBase64Encoder(Codec): """Encode and decode data using py base64.""" @staticmethod diff --git a/Furious/Library/__init__.py b/Furious/Domain/__init__.py similarity index 86% rename from Furious/Library/__init__.py rename to Furious/Domain/__init__.py index 679113b..b5f66d3 100644 --- a/Furious/Library/__init__.py +++ b/Furious/Domain/__init__.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""Expose domain configuration, encoding, and persistent storage services.""" +"""Expose configuration models, provider registration, and data encoding.""" from __future__ import annotations @@ -28,8 +28,7 @@ from .Configuration import ( configurationRegistry, registerConfigurationProvider, ) -from .Encoder import Base64Encoder, JSONEncoder, PyBase64Encoder, UJSONEncoder -from .Storage import Storage +from .Encoding import Base64Encoder, JSONEncoder, PyBase64Encoder, UJSONEncoder __all__ = [ 'Base64Encoder', @@ -37,7 +36,6 @@ __all__ = [ 'ConfigurationRegistry', 'JSONEncoder', 'PyBase64Encoder', - 'Storage', 'UJSONEncoder', 'configFactoryBlank', 'configFactoryFromAny', diff --git a/Furious/Externals/GenTranslation.py b/Furious/Externals/GenTranslation.py index 16feee0..816d8ae 100644 --- a/Furious/Externals/GenTranslation.py +++ b/Furious/Externals/GenTranslation.py @@ -1,12 +1,12 @@ TRANSLATION = { "Delete": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow", - "Furious.Plugins.Official.Xray.XrayAssetViewerQListWidget", + "Furious.Backends.Xray.RoutingWindow", + "Furious.Backends.Xray.AssetListWidget", "Furious.Qt.QtWidgets", - "Furious.Widget.UserServersQTableView", - "Furious.Widget.UserSubsQTableView", - "Furious.Window.UserSubsWindow" + "Furious.Widget.ServerTableView", + "Furious.Widget.SubscriptionTableView", + "Furious.Window.SubscriptionWindow" ], "RU": "Удалить", "ZH": "删除", @@ -54,7 +54,7 @@ TRANSLATION = { }, "New version available": { "source": [ - "Furious.Qt.UpdatesManager" + "Furious.Service.UpdateManager" ], "RU": "Доступна новая версия", "ZH": "新版本可用", @@ -62,7 +62,7 @@ TRANSLATION = { }, "Check for updates failed": { "source": [ - "Furious.Qt.UpdatesManager" + "Furious.Service.UpdateManager" ], "RU": "Не удалось проверить наличие обновлений", "ZH": "检查更新失败", @@ -70,7 +70,7 @@ TRANSLATION = { }, "Go to download page?": { "source": [ - "Furious.Qt.UpdatesManager" + "Furious.Service.UpdateManager" ], "RU": "Перейти на страницу загрузки?", "ZH": "前往下载页面?", @@ -78,7 +78,7 @@ TRANSLATION = { }, "Furious is already the latest version": { "source": [ - "Furious.Qt.UpdatesManager" + "Furious.Service.UpdateManager" ], "RU": "Используется последняя версия Furious", "ZH": "Furious已是最新版本", @@ -86,7 +86,7 @@ TRANSLATION = { }, "Invalid data": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Неверные данные", "ZH": "无效的数据", @@ -94,7 +94,7 @@ TRANSLATION = { }, "Invalid data. The content of the clipboard is:": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Неверные данные. Содержимое буфера обмена:", "ZH": "无效的数据。剪贴板内容为", @@ -102,8 +102,8 @@ TRANSLATION = { }, "Import": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerQListWidget", - "Furious.TrayActions.Import" + "Furious.Backends.Xray.AssetListWidget", + "Furious.Actions.Import" ], "RU": "Импорт", "ZH": "导入", @@ -111,7 +111,7 @@ TRANSLATION = { }, "Import share link success": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Успешный импорт общей ссылки", "ZH": "导入分享链接成功", @@ -119,7 +119,7 @@ TRANSLATION = { }, "Imported to row": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Импорт в строку", "ZH": "导入至行", @@ -127,7 +127,7 @@ TRANSLATION = { }, "Import success": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Успешный импорт", "ZH": "导入成功", @@ -135,8 +135,8 @@ TRANSLATION = { }, "Import From File...": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerWindow", - "Furious.TrayActions.Import" + "Furious.Backends.Xray.AssetWindow", + "Furious.Actions.Import" ], "RU": "Импорт из файла...", "ZH": "从文件导入...", @@ -144,8 +144,8 @@ TRANSLATION = { }, "Import File": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerWindow", - "Furious.TrayActions.Import" + "Furious.Backends.Xray.AssetWindow", + "Furious.Actions.Import" ], "RU": "Импорт файла", "ZH": "导入文件", @@ -153,8 +153,8 @@ TRANSLATION = { }, "Text files (*.json);;All files (*)": { "source": [ - "Furious.TrayActions.Import", - "Furious.Widget.TextEditorWindow" + "Furious.Actions.Import", + "Furious.Window.TextEditorWindow" ], "RU": "Текст файлов (*.json);;Остальные файлы (*)", "ZH": "文本文件 (*.json);;所有文件 (*)", @@ -162,7 +162,7 @@ TRANSLATION = { }, "Error opening file": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Ошибка открытия файла", "ZH": "打开文件出错", @@ -170,7 +170,7 @@ TRANSLATION = { }, "Invalid configuration file": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Недопустимый конфигурационный файл", "ZH": "无效的配置文件", @@ -178,7 +178,7 @@ TRANSLATION = { }, "Import Share Link From Clipboard": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Импортировать ссылку из буфера обмена", "ZH": "从剪贴板导入分享链接", @@ -186,7 +186,7 @@ TRANSLATION = { }, "Import JSON Configuration From Clipboard": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Импортировать JSON конфигурацию из буфера обмена", "ZH": "从剪贴板导入JSON配置", @@ -194,7 +194,7 @@ TRANSLATION = { }, "Scan QR Code On The Screen": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Отсканируйте QR-код на экране", "ZH": "扫描屏幕上的二维码", @@ -202,7 +202,7 @@ TRANSLATION = { }, "Set Indent": { "source": [ - "Furious.Widget.IndentSpinBox" + "Furious.Window.IndentDialog" ], "RU": "Установить отступ", "ZH": "设置缩进", @@ -210,7 +210,7 @@ TRANSLATION = { }, "Indent:": { "source": [ - "Furious.Widget.IndentSpinBox" + "Furious.Window.IndentDialog" ], "RU": "Отступ", "ZH": "缩进:", @@ -218,15 +218,15 @@ TRANSLATION = { }, "Cancel": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow", - "Furious.Qt.GuiEditorXXX", - "Furious.TrayActions.Import", - "Furious.Widget.GuiCustomizeNetworkTest", - "Furious.Widget.GuiCustomizeProxyBypass", - "Furious.Widget.IndentSpinBox", - "Furious.Widget.UserServersQTableView", - "Furious.Widget.TextEditorWindow", - "Furious.Window.UserSubsWindow" + "Furious.Backends.Xray.RoutingWindow", + "Furious.Qt.EditorWidgets", + "Furious.Actions.Import", + "Furious.Window.NetworkTestDialog", + "Furious.Window.ProxyBypassDialog", + "Furious.Window.IndentDialog", + "Furious.Widget.ServerTableView", + "Furious.Window.TextEditorWindow", + "Furious.Window.SubscriptionWindow" ], "RU": "Отмена", "ZH": "取消", @@ -234,7 +234,7 @@ TRANSLATION = { }, "Save Changes": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Сохранить изменения", "ZH": "保存更改", @@ -242,7 +242,7 @@ TRANSLATION = { }, "The content has been modified. Save changes?": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Содержимое было изменено. Сохранить изменения?", "ZH": "内容已修改。保存更改?", @@ -250,7 +250,7 @@ TRANSLATION = { }, "Save": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Сохранить", "ZH": "保存", @@ -258,7 +258,7 @@ TRANSLATION = { }, "Discard": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Отказаться", "ZH": "丢弃", @@ -266,7 +266,7 @@ TRANSLATION = { }, "Please check if the configuration is in valid JSON format": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Проверьте, имеет ли конфигурация допустимый формат JSON", "ZH": "请检查配置是否为有效的JSON格式", @@ -274,8 +274,8 @@ TRANSLATION = { }, "Save As...": { "source": [ - "Furious.Window.LogViewerWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Window.LogWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Сохранить как...", "ZH": "另存为...", @@ -283,7 +283,7 @@ TRANSLATION = { }, "Close Window": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Закрыть окно", "ZH": "关闭窗口", @@ -291,9 +291,9 @@ TRANSLATION = { }, "File": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerWindow", - "Furious.Window.LogViewerWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Backends.Xray.AssetWindow", + "Furious.Window.LogWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Файл", "ZH": "文件", @@ -301,7 +301,7 @@ TRANSLATION = { }, "Undo": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Отменить", "ZH": "撤销", @@ -309,7 +309,7 @@ TRANSLATION = { }, "Redo": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Повторить", "ZH": "重做", @@ -317,7 +317,7 @@ TRANSLATION = { }, "Cut": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Вырезать", "ZH": "剪切", @@ -325,8 +325,8 @@ TRANSLATION = { }, "Copy": { "source": [ - "Furious.Window.LogViewerWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Window.LogWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Копировать", "ZH": "复制", @@ -334,7 +334,7 @@ TRANSLATION = { }, "Paste": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Вставить", "ZH": "粘贴", @@ -342,9 +342,9 @@ TRANSLATION = { }, "Select All": { "source": [ - "Furious.Widget.UserServersQTableView", - "Furious.Window.LogViewerWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Widget.ServerTableView", + "Furious.Window.LogWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Выбрать все", "ZH": "全选", @@ -352,7 +352,7 @@ TRANSLATION = { }, "Indent...": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Настройка отступа...", "ZH": "缩进...", @@ -360,8 +360,8 @@ TRANSLATION = { }, "Edit": { "source": [ - "Furious.Window.LogViewerWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Window.LogWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Редактировать", "ZH": "编辑", @@ -369,8 +369,8 @@ TRANSLATION = { }, "Zoom In": { "source": [ - "Furious.Window.LogViewerWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Window.LogWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Увеличить маcштаб", "ZH": "变大", @@ -378,8 +378,8 @@ TRANSLATION = { }, "Zoom Out": { "source": [ - "Furious.Window.LogViewerWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Window.LogWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Уменьшить маcштаб", "ZH": "变小", @@ -387,8 +387,8 @@ TRANSLATION = { }, "View": { "source": [ - "Furious.Window.LogViewerWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Window.LogWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Вид", "ZH": "显示", @@ -396,7 +396,7 @@ TRANSLATION = { }, "Error saving configuration": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Ошибка сохранения конфигурации", "ZH": "保存配置出错", @@ -404,8 +404,8 @@ TRANSLATION = { }, "Save File": { "source": [ - "Furious.Window.LogViewerWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Window.LogWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Сохранить файл", "ZH": "保存文件", @@ -413,7 +413,7 @@ TRANSLATION = { }, "Error Saving File": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Ошибка сохранения файла", "ZH": "保存文件出错", @@ -421,8 +421,8 @@ TRANSLATION = { }, "Invalid server configuration": { "source": [ - "Furious.TrayActions.Connect", - "Furious.Widget.TextEditorWindow" + "Furious.Actions.Connection", + "Furious.Window.TextEditorWindow" ], "RU": "Неверная конфигурация сервера", "ZH": "无效的服务器配置", @@ -430,7 +430,7 @@ TRANSLATION = { }, "Error setting indent": { "source": [ - "Furious.Widget.TextEditorWindow" + "Furious.Window.TextEditorWindow" ], "RU": "Ошибка при установке отступов", "ZH": "设置缩进出错", @@ -438,16 +438,16 @@ TRANSLATION = { }, "Remark": { "source": [ - "Furious.Plugins.Official.Hysteria1.GuiHysteria1", - "Furious.Plugins.Official.Hysteria2.GuiHysteria2", - "Furious.Plugins.Official.Xray.GuiShadowsocks", - "Furious.Plugins.Official.Xray.GuiSocks", - "Furious.Plugins.Official.Xray.GuiTrojan", - "Furious.Plugins.Official.Xray.GuiVLESS", - "Furious.Plugins.Official.Xray.GuiVMess", - "Furious.Plugins.Official.Xray.UserRoutingWindow", - "Furious.Widget.UserServersQTableView", - "Furious.Widget.UserSubsQTableView" + "Furious.Backends.Hysteria1.Editor", + "Furious.Backends.Hysteria2.Editor", + "Furious.Backends.Xray.ShadowsocksEditor", + "Furious.Backends.Xray.SocksEditor", + "Furious.Backends.Xray.TrojanEditor", + "Furious.Backends.Xray.VlessEditor", + "Furious.Backends.Xray.VmessEditor", + "Furious.Backends.Xray.RoutingWindow", + "Furious.Widget.ServerTableView", + "Furious.Widget.SubscriptionTableView" ], "RU": "Примечание", "ZH": "别名", @@ -455,8 +455,8 @@ TRANSLATION = { }, "Protocol": { "source": [ - "Furious.Plugins.Official.Hysteria1.GuiHysteria1", - "Furious.Widget.UserServersQTableView" + "Furious.Backends.Hysteria1.Editor", + "Furious.Widget.ServerTableView" ], "RU": "Протокол", "ZH": "协议", @@ -464,12 +464,12 @@ TRANSLATION = { }, "Address": { "source": [ - "Furious.Plugins.Official.Xray.GuiShadowsocks", - "Furious.Plugins.Official.Xray.GuiSocks", - "Furious.Plugins.Official.Xray.GuiTrojan", - "Furious.Plugins.Official.Xray.GuiVLESS", - "Furious.Plugins.Official.Xray.GuiVMess", - "Furious.Widget.UserServersQTableView" + "Furious.Backends.Xray.ShadowsocksEditor", + "Furious.Backends.Xray.SocksEditor", + "Furious.Backends.Xray.TrojanEditor", + "Furious.Backends.Xray.VlessEditor", + "Furious.Backends.Xray.VmessEditor", + "Furious.Widget.ServerTableView" ], "RU": "Адрес", "ZH": "地址", @@ -477,12 +477,12 @@ TRANSLATION = { }, "Port": { "source": [ - "Furious.Plugins.Official.Xray.GuiShadowsocks", - "Furious.Plugins.Official.Xray.GuiSocks", - "Furious.Plugins.Official.Xray.GuiTrojan", - "Furious.Plugins.Official.Xray.GuiVLESS", - "Furious.Plugins.Official.Xray.GuiVMess", - "Furious.Widget.UserServersQTableView" + "Furious.Backends.Xray.ShadowsocksEditor", + "Furious.Backends.Xray.SocksEditor", + "Furious.Backends.Xray.TrojanEditor", + "Furious.Backends.Xray.VlessEditor", + "Furious.Backends.Xray.VmessEditor", + "Furious.Widget.ServerTableView" ], "RU": "Порт", "ZH": "端口", @@ -490,8 +490,8 @@ TRANSLATION = { }, "Transport": { "source": [ - "Furious.Plugins.Official.Xray.GuiVTransport", - "Furious.Widget.UserServersQTableView" + "Furious.Backends.Xray.TransportEditor", + "Furious.Widget.ServerTableView" ], "RU": "Способ передачи", "ZH": "传输方式", @@ -499,7 +499,7 @@ TRANSLATION = { }, "TLS": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "TLS", "ZH": "TLS", @@ -507,8 +507,8 @@ TRANSLATION = { }, "Subscription": { "source": [ - "Furious.Widget.UserServersQTableView", - "Furious.Window.AppMainWindow" + "Furious.Widget.ServerTableView", + "Furious.Window.MainWindow" ], "RU": "Подписка", "ZH": "订阅", @@ -516,7 +516,7 @@ TRANSLATION = { }, "Latency": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Задержка", "ZH": "延迟", @@ -524,8 +524,8 @@ TRANSLATION = { }, "Speed": { "source": [ - "Furious.Plugins.Official.Hysteria1.GuiHysteria1", - "Furious.Widget.UserServersQTableView" + "Furious.Backends.Hysteria1.Editor", + "Furious.Widget.ServerTableView" ], "RU": "Скорость", "ZH": "速度", @@ -533,7 +533,7 @@ TRANSLATION = { }, "Edit Configuration...": { "source": [ - "Furious.TrayActions.EditConfiguration" + "Furious.Actions.Configuration" ], "RU": "Изменить конфигурацию...", "ZH": "编辑配置...", @@ -541,7 +541,7 @@ TRANSLATION = { }, "Move Up": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Переместить вверх", "ZH": "上移", @@ -549,7 +549,7 @@ TRANSLATION = { }, "Move Down": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Переместить вниз", "ZH": "下移", @@ -557,7 +557,7 @@ TRANSLATION = { }, "Duplicate": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Дубликат", "ZH": "克隆", @@ -565,7 +565,7 @@ TRANSLATION = { }, "Scroll To Activated Server": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Перейдите к активированному серверу", "ZH": "滚动到激活的服务器", @@ -573,7 +573,7 @@ TRANSLATION = { }, "Test Ping Latency": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Измерить задержку (ping)", "ZH": "测试Ping延迟", @@ -581,7 +581,7 @@ TRANSLATION = { }, "Test Download Speed": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Измерить скорость загрузки", "ZH": "测试下行速度", @@ -589,7 +589,7 @@ TRANSLATION = { }, "Test Download Speed (Multithreaded)": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Измерить скорость загрузки (многопоточная)", "ZH": "测试下行速度(多线程)", @@ -597,7 +597,7 @@ TRANSLATION = { }, "Clear Test Results": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Очистить результаты тестирования", "ZH": "清除测试结果", @@ -605,8 +605,8 @@ TRANSLATION = { }, "New Empty Configuration": { "source": [ - "Furious.Widget.UserServersQTableView", - "Furious.Window.AppMainWindow" + "Furious.Widget.ServerTableView", + "Furious.Window.MainWindow" ], "RU": "Создать новую пустую конфигурацию", "ZH": "新建空白配置", @@ -614,7 +614,7 @@ TRANSLATION = { }, "Export Share Link To Clipboard": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Копировать ссылку в буфер обмена", "ZH": "导出分享链接至剪贴板", @@ -622,7 +622,7 @@ TRANSLATION = { }, "Export As QR Code": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Экспорт в виде QR-кода", "ZH": "导出为二维码", @@ -630,7 +630,7 @@ TRANSLATION = { }, "Export JSON Configuration To Clipboard": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Копировать JSON конфигурацию в буфер обмена", "ZH": "导出JSON配置至剪贴板", @@ -638,8 +638,8 @@ TRANSLATION = { }, "Connecting": { "source": [ - "Furious.TrayActions.Connect", - "Furious.Widget.UserServersQTableView" + "Furious.Actions.Connection", + "Furious.Widget.ServerTableView" ], "RU": "Подключение", "ZH": "正在连接", @@ -647,7 +647,7 @@ TRANSLATION = { }, "Connecting. Please wait...": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Подключение. Пожалуйста, подождите...", "ZH": "正在连接。请稍候", @@ -655,7 +655,7 @@ TRANSLATION = { }, "Untitled": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Без названия", "ZH": "未命名", @@ -663,7 +663,7 @@ TRANSLATION = { }, "Add Subscription": { "source": [ - "Furious.Window.UserSubsWindow" + "Furious.Window.SubscriptionWindow" ], "RU": "Добавить подписку", "ZH": "添加订阅", @@ -671,7 +671,7 @@ TRANSLATION = { }, "Enter subscription remark:": { "source": [ - "Furious.Window.UserSubsWindow" + "Furious.Window.SubscriptionWindow" ], "RU": "Введите примечание о подписке:", "ZH": "输入订阅名称:", @@ -679,7 +679,7 @@ TRANSLATION = { }, "Enter subscription URL:": { "source": [ - "Furious.Window.UserSubsWindow" + "Furious.Window.SubscriptionWindow" ], "RU": "Введите URL-адрес подписки:", "ZH": "输入订阅URL:", @@ -687,7 +687,7 @@ TRANSLATION = { }, "Edit Subscription": { "source": [ - "Furious.Window.UserSubsWindow" + "Furious.Window.SubscriptionWindow" ], "RU": "Редактировать подписку", "ZH": "编辑订阅", @@ -695,7 +695,7 @@ TRANSLATION = { }, "Subscription List": { "source": [ - "Furious.Window.UserSubsWindow" + "Furious.Window.SubscriptionWindow" ], "RU": "Список подписок", "ZH": "订阅列表", @@ -703,8 +703,8 @@ TRANSLATION = { }, "Add": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow", - "Furious.Window.UserSubsWindow" + "Furious.Backends.Xray.RoutingWindow", + "Furious.Window.SubscriptionWindow" ], "RU": "Добавить", "ZH": "添加", @@ -712,9 +712,9 @@ TRANSLATION = { }, "Exit": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerWindow", - "Furious.TrayActions.Exit", - "Furious.Window.LogViewerWindow" + "Furious.Backends.Xray.AssetWindow", + "Furious.Actions.Exit", + "Furious.Window.LogWindow" ], "RU": "Выход", "ZH": "退出", @@ -722,7 +722,7 @@ TRANSLATION = { }, "Unable to save log": { "source": [ - "Furious.Window.LogViewerWindow" + "Furious.Window.LogWindow" ], "RU": "Не удалось сохранить журнал", "ZH": "无法保存日志", @@ -730,7 +730,7 @@ TRANSLATION = { }, "Text files (*.txt);;All files (*)": { "source": [ - "Furious.Window.LogViewerWindow" + "Furious.Window.LogWindow" ], "RU": "Текстовые файлы (*.txt);;Все файлы (*)", "ZH": "文本文件 (*.txt);;所有文件 (*)", @@ -738,7 +738,7 @@ TRANSLATION = { }, "Error saving log": { "source": [ - "Furious.Window.LogViewerWindow" + "Furious.Window.LogWindow" ], "RU": "Ошибка сохранения журнала", "ZH": "保存日志出错", @@ -746,7 +746,7 @@ TRANSLATION = { }, "Log Viewer": { "source": [ - "Furious.Window.LogViewerWindow" + "Furious.Window.LogWindow" ], "RU": "Средство просмотра журнала", "ZH": "日志查看器", @@ -754,7 +754,7 @@ TRANSLATION = { }, "Asset file already exists. Overwrite?": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerQListWidget" + "Furious.Backends.Xray.AssetListWidget" ], "RU": "Файл ресурсов уже существует. Перезаписать?", "ZH": "资源文件已存在。是否覆盖?", @@ -762,7 +762,7 @@ TRANSLATION = { }, "Error import asset file": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerQListWidget" + "Furious.Backends.Xray.AssetListWidget" ], "RU": "Ошибка при импорте файла ресурсов", "ZH": "导入资源文件出错", @@ -770,7 +770,7 @@ TRANSLATION = { }, "Import asset file success": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerQListWidget" + "Furious.Backends.Xray.AssetListWidget" ], "RU": "Успешно импортирован файл ресурсов", "ZH": "导入资源文件成功", @@ -778,7 +778,7 @@ TRANSLATION = { }, "Xray-core Asset File": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerWindow" + "Furious.Backends.Xray.AssetWindow" ], "RU": "Xray-core Asset File", "ZH": "Xray-core资源文件", @@ -786,7 +786,7 @@ TRANSLATION = { }, "Refresh": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerWindow" + "Furious.Backends.Xray.AssetWindow" ], "RU": "Обновить", "ZH": "刷新", @@ -794,7 +794,7 @@ TRANSLATION = { }, "Open Asset Directory": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerWindow" + "Furious.Backends.Xray.AssetWindow" ], "RU": "Открыть каталог ресурсов", "ZH": "打开资源目录", @@ -802,7 +802,7 @@ TRANSLATION = { }, "All files (*)": { "source": [ - "Furious.Plugins.Official.Xray.XrayAssetViewerWindow" + "Furious.Backends.Xray.AssetWindow" ], "RU": "Все файлы (*)", "ZH": "所有文件 (*)", @@ -810,9 +810,9 @@ TRANSLATION = { }, "Server": { "source": [ - "Furious.Plugins.Official.Hysteria1.GuiHysteria1", - "Furious.Plugins.Official.Hysteria2.GuiHysteria2", - "Furious.Window.AppMainWindow" + "Furious.Backends.Hysteria1.Editor", + "Furious.Backends.Hysteria2.Editor", + "Furious.Window.MainWindow" ], "RU": "Сервер", "ZH": "服务器", @@ -820,7 +820,7 @@ TRANSLATION = { }, "Log": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Журнал событий", "ZH": "日志", @@ -828,8 +828,8 @@ TRANSLATION = { }, "Show Furious Log...": { "source": [ - "Furious.Widget.UserServersQTableView", - "Furious.Window.AppMainWindow" + "Furious.Widget.ServerTableView", + "Furious.Window.MainWindow" ], "RU": "Показать журнал Furious...", "ZH": "显示Furious日志...", @@ -837,8 +837,8 @@ TRANSLATION = { }, "Show Core Log...": { "source": [ - "Furious.Widget.UserServersQTableView", - "Furious.Window.AppMainWindow" + "Furious.Widget.ServerTableView", + "Furious.Window.MainWindow" ], "RU": "Показать журнал ядра...", "ZH": "显示内核日志...", @@ -846,8 +846,8 @@ TRANSLATION = { }, "Show Tun2socks Log...": { "source": [ - "Furious.Widget.UserServersQTableView", - "Furious.Window.AppMainWindow" + "Furious.Widget.ServerTableView", + "Furious.Window.MainWindow" ], "RU": "Показать журнал Tun2socks...", "ZH": "显示Tun2socks日志...", @@ -855,7 +855,7 @@ TRANSLATION = { }, "Update Subscription (Use Current Proxy)": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Обновить подписки (использовать текущий прокси-сервер)", "ZH": "更新订阅(使用当前代理)", @@ -863,7 +863,7 @@ TRANSLATION = { }, "Update Subscription (Force Proxy)": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Обновить подписки (обязательно через прокси-сервер)", "ZH": "更新订阅(强制代理)", @@ -871,7 +871,7 @@ TRANSLATION = { }, "Update Subscription (No Proxy)": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Обновить подписки (не использовать прокси)", "ZH": "更新订阅(无代理)", @@ -879,7 +879,7 @@ TRANSLATION = { }, "Edit Subscription...": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Редактировать подписки...", "ZH": "编辑订阅...", @@ -887,7 +887,7 @@ TRANSLATION = { }, "Tools": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Инструменты", "ZH": "工具", @@ -895,7 +895,7 @@ TRANSLATION = { }, "Plugins": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Плагины", "ZH": "插件", @@ -903,7 +903,7 @@ TRANSLATION = { }, "Core": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Core", "ZH": "Core", @@ -911,7 +911,7 @@ TRANSLATION = { }, "Open Application Folder": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Открыть папку приложения", "ZH": "打开应用程序文件夹", @@ -919,7 +919,7 @@ TRANSLATION = { }, "Check For Updates": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Проверка обновлений", "ZH": "检查更新", @@ -927,7 +927,7 @@ TRANSLATION = { }, "About": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "О нас", "ZH": "关于", @@ -935,7 +935,7 @@ TRANSLATION = { }, "Already started": { "source": [ - "Furious.Application.Application" + "Furious.Application.DesktopApplication" ], "RU": "Активированный", "ZH": "已启动", @@ -943,7 +943,7 @@ TRANSLATION = { }, "Furious Log": { "source": [ - "Furious.Application.Application" + "Furious.Application.DesktopApplication" ], "RU": "Лог Furious", "ZH": "Furious日志", @@ -951,7 +951,7 @@ TRANSLATION = { }, "Core Log": { "source": [ - "Furious.Application.Application" + "Furious.Application.DesktopApplication" ], "RU": "Лог ядра", "ZH": "内核日志", @@ -959,7 +959,7 @@ TRANSLATION = { }, "Tun2socks Log": { "source": [ - "Furious.Application.Application" + "Furious.Application.DesktopApplication" ], "RU": "Лог Tun2socks", "ZH": "Tun2socks日志", @@ -967,7 +967,7 @@ TRANSLATION = { }, "Connect": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Подключиться", "ZH": "连接", @@ -975,7 +975,7 @@ TRANSLATION = { }, "Disconnect": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Отключиться", "ZH": "断开连接", @@ -984,7 +984,7 @@ TRANSLATION = { "Unable to connect": { "source": [ "Furious.Qt.QtWidgets", - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Не удается подключиться", "ZH": "无法连接", @@ -992,7 +992,7 @@ TRANSLATION = { }, "Server configuration empty. Please configure your server first": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Конфигурация сервера пуста. Пожалуйста, сначала настройте свой сервер", "ZH": "服务器配置为空。请先配置服务器", @@ -1000,7 +1000,7 @@ TRANSLATION = { }, "Connected": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Подключен", "ZH": "已连接", @@ -1008,7 +1008,7 @@ TRANSLATION = { }, "Unknown error": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Неизвестная ошибка", "ZH": "未知错误", @@ -1016,7 +1016,7 @@ TRANSLATION = { }, "Failed to start core": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Сбой при запуске ядра", "ZH": "内核启动失败", @@ -1024,7 +1024,7 @@ TRANSLATION = { }, "Core terminated unexpectedly": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Неожиданное завершение работы ядра", "ZH": "内核意外终止", @@ -1032,7 +1032,7 @@ TRANSLATION = { }, "Disconnected": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Отключен", "ZH": "已断开", @@ -1040,7 +1040,7 @@ TRANSLATION = { }, "Language": { "source": [ - "Furious.TrayActions.Language" + "Furious.Actions.Language" ], "RU": "Язык", "ZH": "语言", @@ -1048,7 +1048,7 @@ TRANSLATION = { }, "Routing": { "source": [ - "Furious.TrayActions.Routing" + "Furious.Actions.Routing" ], "RU": "Маршрутизация", "ZH": "路由", @@ -1056,7 +1056,7 @@ TRANSLATION = { }, "TUN Mode": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "TUN режим", "ZH": "TUN模式", @@ -1064,7 +1064,7 @@ TRANSLATION = { }, "TUN Mode Disabled (Administrator)": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "TUN режим отключен (Administrator)", "ZH": "TUN模式已禁用(管理员)", @@ -1072,7 +1072,7 @@ TRANSLATION = { }, "TUN Mode Disabled (Superuser)": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "TUN режим отключен (Superuser)", "ZH": "TUN模式已禁用(Superuser)", @@ -1080,7 +1080,7 @@ TRANSLATION = { }, "Settings": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Настройки", "ZH": "设置", @@ -1088,7 +1088,7 @@ TRANSLATION = { }, "Dark Mode": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Темный режим", "ZH": "深色模式", @@ -1096,7 +1096,7 @@ TRANSLATION = { }, "Startup On Boot": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Автозапуск при загрузке системы", "ZH": "开机启动", @@ -1104,7 +1104,7 @@ TRANSLATION = { }, "Force To 127.0.0.1 When Setting Local Proxy": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Принудительно 127.0.0.1 для локального прокси", "ZH": "设置本地代理时强制使用127.0.0.1", @@ -1112,7 +1112,7 @@ TRANSLATION = { }, "Automatically Update Asset Files": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Автоматически обновлять файлы активов", "ZH": "自动更新资源文件", @@ -1120,7 +1120,7 @@ TRANSLATION = { }, "Show Progress Bar When Connecting": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Отображение индикатора выполнения при подключении", "ZH": "连接时显示进度条", @@ -1128,7 +1128,7 @@ TRANSLATION = { }, "Show Tab And Spaces In Editor": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Показывать табуляцию и пробелы в редакторе", "ZH": "在编辑器中显示制表符和空格", @@ -1136,7 +1136,7 @@ TRANSLATION = { }, "System Proxy": { "source": [ - "Furious.TrayActions.SystemProxy" + "Furious.Actions.SystemProxy" ], "RU": "Системный прокси", "ZH": "系统代理", @@ -1144,7 +1144,7 @@ TRANSLATION = { }, "Automatically Configure System Proxy": { "source": [ - "Furious.TrayActions.SystemProxy" + "Furious.Actions.SystemProxy" ], "RU": "Автоматическая настройка системного прокси-сервера", "ZH": "自动配置系统代理", @@ -1152,7 +1152,7 @@ TRANSLATION = { }, "Do Not Change System Proxy": { "source": [ - "Furious.TrayActions.SystemProxy" + "Furious.Actions.SystemProxy" ], "RU": "Не изменять системный прокси-сервер", "ZH": "不修改系统代理", @@ -1208,7 +1208,7 @@ TRANSLATION = { }, "Bypass Mainland China": { "source": [ - "Furious.TrayActions.Routing" + "Furious.Actions.Routing" ], "RU": "В обход Китая", "ZH": "绕过中国大陆", @@ -1216,7 +1216,7 @@ TRANSLATION = { }, "Global": { "source": [ - "Furious.TrayActions.Routing" + "Furious.Actions.Routing" ], "RU": "глобальный режим", "ZH": "全球", @@ -1224,7 +1224,7 @@ TRANSLATION = { }, "Custom": { "source": [ - "Furious.TrayActions.Routing" + "Furious.Actions.Routing" ], "RU": "Свои настройки", "ZH": "自定义", @@ -1232,7 +1232,7 @@ TRANSLATION = { }, "Furious cannot find any valid http proxy endpoint in the configuration": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Я не могу найти ни одной допустимой конечной точки http-прокси в конфигурации", "ZH": "Furious在配置中无法找到任何有效的http代理端点", @@ -1240,7 +1240,7 @@ TRANSLATION = { }, "Please complete your server configuration": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Пожалуйста, завершите настройку вашего сервера", "ZH": "请完善服务器配置", @@ -1248,7 +1248,7 @@ TRANSLATION = { }, "Help": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Помощь", "ZH": "帮助", @@ -1256,7 +1256,7 @@ TRANSLATION = { }, "Test Tcping Latency": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Измерить задержку (Tсping)", "ZH": "测试Tcping延迟", @@ -1264,14 +1264,14 @@ TRANSLATION = { }, "Basic Configuration": { "source": [ - "Furious.Plugins.Official.Hysteria1.GuiHysteria1", - "Furious.Plugins.Official.Hysteria2.GuiHysteria2", - "Furious.Plugins.Official.Xray.GuiShadowsocks", - "Furious.Plugins.Official.Xray.GuiSocks", - "Furious.Plugins.Official.Xray.GuiTrojan", - "Furious.Plugins.Official.Xray.GuiVLESS", - "Furious.Plugins.Official.Xray.GuiVMess", - "Furious.Widget.GuiTUNSettings" + "Furious.Backends.Hysteria1.Editor", + "Furious.Backends.Hysteria2.Editor", + "Furious.Backends.Xray.ShadowsocksEditor", + "Furious.Backends.Xray.SocksEditor", + "Furious.Backends.Xray.TrojanEditor", + "Furious.Backends.Xray.VlessEditor", + "Furious.Backends.Xray.VmessEditor", + "Furious.Window.TunSettingsDialog" ], "RU": "Базовая конфигурация", "ZH": "基本配置", @@ -1279,13 +1279,13 @@ TRANSLATION = { }, "Proxy": { "source": [ - "Furious.Plugins.Official.Hysteria1.GuiHysteria1", - "Furious.Plugins.Official.Hysteria2.GuiHysteria2", - "Furious.Plugins.Official.Xray.GuiShadowsocks", - "Furious.Plugins.Official.Xray.GuiSocks", - "Furious.Plugins.Official.Xray.GuiTrojan", - "Furious.Plugins.Official.Xray.GuiVLESS", - "Furious.Plugins.Official.Xray.GuiVMess" + "Furious.Backends.Hysteria1.Editor", + "Furious.Backends.Hysteria2.Editor", + "Furious.Backends.Xray.ShadowsocksEditor", + "Furious.Backends.Xray.SocksEditor", + "Furious.Backends.Xray.TrojanEditor", + "Furious.Backends.Xray.VlessEditor", + "Furious.Backends.Xray.VmessEditor" ], "RU": "Прокси", "ZH": "代理", @@ -1293,8 +1293,8 @@ TRANSLATION = { }, "Project Website": { "source": [ - "Furious.Plugins.Official.Hysteria1.GuiHysteria1", - "Furious.Plugins.Official.Hysteria2.GuiHysteria2" + "Furious.Backends.Hysteria1.Editor", + "Furious.Backends.Hysteria2.Editor" ], "RU": "Веб-сайт проекта", "ZH": "项目网站", @@ -1302,8 +1302,8 @@ TRANSLATION = { }, "Other": { "source": [ - "Furious.Plugins.Official.Hysteria1.GuiHysteria1", - "Furious.Plugins.Official.Hysteria2.GuiHysteria2" + "Furious.Backends.Hysteria1.Editor", + "Furious.Backends.Hysteria2.Editor" ], "RU": "Прочее", "ZH": "其它", @@ -1311,8 +1311,8 @@ TRANSLATION = { }, "Encryption": { "source": [ - "Furious.Plugins.Official.Xray.GuiShadowsocks", - "Furious.Plugins.Official.Xray.GuiVLESS" + "Furious.Backends.Xray.ShadowsocksEditor", + "Furious.Backends.Xray.VlessEditor" ], "RU": "Шифрование", "ZH": "加密", @@ -1320,9 +1320,9 @@ TRANSLATION = { }, "Password": { "source": [ - "Furious.Plugins.Official.Xray.GuiShadowsocks", - "Furious.Plugins.Official.Xray.GuiSocks", - "Furious.Plugins.Official.Xray.GuiTrojan" + "Furious.Backends.Xray.ShadowsocksEditor", + "Furious.Backends.Xray.SocksEditor", + "Furious.Backends.Xray.TrojanEditor" ], "RU": "Пароль", "ZH": "密码", @@ -1330,7 +1330,7 @@ TRANSLATION = { }, "Flow": { "source": [ - "Furious.Plugins.Official.Xray.GuiVLESS" + "Furious.Backends.Xray.VlessEditor" ], "RU": "Поток", "ZH": "流控", @@ -1338,7 +1338,7 @@ TRANSLATION = { }, "Use Monochrome Tray Icon": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Использовать монохромный значок в трее", "ZH": "使用单色托盘图标", @@ -1346,7 +1346,7 @@ TRANSLATION = { }, "Hide Dock Icon": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Скрыть значок Dock", "ZH": "隐藏程序坞图标", @@ -1354,7 +1354,7 @@ TRANSLATION = { }, "Customize JSON Configuration...": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Редактировать JSON конфигурацию...", "ZH": "自定义JSON配置...", @@ -1378,7 +1378,7 @@ TRANSLATION = { }, "Select and press Enter to activate configuration and connect": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "Выберите конфигурацию и нажмите Enter, чтобы активировать ее и подключиться", "ZH": "选择并按下Enter键以激活配置并连接", @@ -1386,7 +1386,7 @@ TRANSLATION = { }, "Power Save Mode": { "source": [ - "Furious.TrayActions.Settings" + "Furious.Actions.Settings" ], "RU": "Режим энергосбережения", "ZH": "省电模式", @@ -1395,12 +1395,12 @@ TRANSLATION = { "OK": { "source": [ "Furious.__main__", - "Furious.Plugins.Official.Xray.UserRoutingWindow", - "Furious.Qt.GuiEditorXXX", - "Furious.Widget.GuiCustomizeNetworkTest", - "Furious.Widget.GuiCustomizeProxyBypass", - "Furious.Widget.IndentSpinBox", - "Furious.Window.UserSubsWindow" + "Furious.Backends.Xray.RoutingWindow", + "Furious.Qt.EditorWidgets", + "Furious.Window.NetworkTestDialog", + "Furious.Window.ProxyBypassDialog", + "Furious.Window.IndentDialog", + "Furious.Window.SubscriptionWindow" ], "RU": "OK", "ZH": "OK", @@ -1408,7 +1408,7 @@ TRANSLATION = { }, "Advanced...": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Расширенные...", "ZH": "高级...", @@ -1416,7 +1416,7 @@ TRANSLATION = { }, "is available to download": { "source": [ - "Furious.TrayActions.Connect" + "Furious.Actions.Connection" ], "RU": "доступен для скачивания", "ZH": "可供下载", @@ -1424,7 +1424,7 @@ TRANSLATION = { }, "Update subscription completed": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Подписка на обновление завершена", "ZH": "更新订阅完成", @@ -1432,7 +1432,7 @@ TRANSLATION = { }, "Update subscription failed": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Обновить подписку не удалось", "ZH": "更新订阅失败", @@ -1440,7 +1440,7 @@ TRANSLATION = { }, "Configuration has been updated": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Конфигурация обновлена", "ZH": "配置已更新", @@ -1448,7 +1448,7 @@ TRANSLATION = { }, "Configuration update failed": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Обновление конфигурации не удалось", "ZH": "配置更新失败", @@ -1456,7 +1456,7 @@ TRANSLATION = { }, "Auto Update": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Автообновление", "ZH": "自动更新", @@ -1464,7 +1464,7 @@ TRANSLATION = { }, "Auto Update Use Proxy": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Автообновление (используя прокси)", "ZH": "自动更新使用代理", @@ -1472,7 +1472,7 @@ TRANSLATION = { }, "Never": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Никогда", "ZH": "从不", @@ -1480,7 +1480,7 @@ TRANSLATION = { }, "Every 5 mins": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 5 минут", "ZH": "每5分钟", @@ -1488,7 +1488,7 @@ TRANSLATION = { }, "Every 10 mins": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 10 минут", "ZH": "每10分钟", @@ -1496,7 +1496,7 @@ TRANSLATION = { }, "Every 15 mins": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 15 минут", "ZH": "每15分钟", @@ -1504,7 +1504,7 @@ TRANSLATION = { }, "Every 30 mins": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 30 минут", "ZH": "每30分钟", @@ -1512,7 +1512,7 @@ TRANSLATION = { }, "Every 45 mins": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 45 минут", "ZH": "每45分钟", @@ -1520,7 +1520,7 @@ TRANSLATION = { }, "Every 1 hour": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждый 1 час", "ZH": "每1小时", @@ -1528,7 +1528,7 @@ TRANSLATION = { }, "Every 2 hours": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 2 часа", "ZH": "每2小时", @@ -1536,7 +1536,7 @@ TRANSLATION = { }, "Every 3 hours": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 3 часа", "ZH": "每3小时", @@ -1544,7 +1544,7 @@ TRANSLATION = { }, "Every 6 hours": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 6 часов", "ZH": "每6小时", @@ -1552,7 +1552,7 @@ TRANSLATION = { }, "Every 8 hours": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 8 часов", "ZH": "每8小时", @@ -1560,7 +1560,7 @@ TRANSLATION = { }, "Every 10 hours": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 10 часов", "ZH": "每10小时", @@ -1568,7 +1568,7 @@ TRANSLATION = { }, "Every 12 hours": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 12 часов", "ZH": "每12小时", @@ -1576,7 +1576,7 @@ TRANSLATION = { }, "Every 24 hours": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Каждые 24 часа", "ZH": "每24小时", @@ -1584,7 +1584,7 @@ TRANSLATION = { }, "Use current proxy": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Использовать текущий прокси-сервер", "ZH": "使用当前代理", @@ -1592,7 +1592,7 @@ TRANSLATION = { }, "Force proxy": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Обязательно через прокси-сервер", "ZH": "强制代理", @@ -1600,7 +1600,7 @@ TRANSLATION = { }, "No proxy": { "source": [ - "Furious.Widget.UserSubsQTableView" + "Furious.Widget.SubscriptionTableView" ], "RU": "Не использовать прокси", "ZH": "无代理", @@ -1608,7 +1608,7 @@ TRANSLATION = { }, "Customize Tun2socks Settings": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "Настроить параметры Tun2socks", "ZH": "自定义Tun2socks设置", @@ -1616,8 +1616,8 @@ TRANSLATION = { }, "Customize Tun2socks Settings...": { "source": [ - "Furious.TrayActions.Settings", - "Furious.Window.AppMainWindow" + "Furious.Actions.Settings", + "Furious.Window.MainWindow" ], "RU": "Настроить параметры Tun2socks...", "ZH": "自定义Tun2socks设置...", @@ -1625,7 +1625,7 @@ TRANSLATION = { }, "Go to help page": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "Перейти на страницу помощи", "ZH": "转到帮助页面", @@ -1633,7 +1633,7 @@ TRANSLATION = { }, "Primary Adapter Interface Name": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "Имя основного сетевого адаптера", "ZH": "主适配器接口名称", @@ -1641,7 +1641,7 @@ TRANSLATION = { }, "Primary Adapter Interface IP": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "IP-адрес основного сетевого адаптера", "ZH": "主适配器接口IP", @@ -1649,7 +1649,7 @@ TRANSLATION = { }, "Default Primary Gateway IP": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "IP-адрес основного шлюза по умолчанию", "ZH": "默认主网关IP", @@ -1657,7 +1657,7 @@ TRANSLATION = { }, "Tun2socks Adapter Interface DNS": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "DNS-адрес интерфейса адаптера Tun2socks", "ZH": "Tun2socks适配器接口DNS", @@ -1665,7 +1665,7 @@ TRANSLATION = { }, "Bypass Tun2socks Adapter Interface IP (separated by commas)": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "Обход IP-адреса интерфейса адаптера Tun2socks (через запятую)", "ZH": "绕过Tun2socks适配器接口IP(以逗号分隔)", @@ -1673,7 +1673,7 @@ TRANSLATION = { }, "Disable Primary Adapter Interface DNS (Mitigating DNS leaks on Windows)": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "Отключить DNS основного сетевого адаптера (для предотвращения утечек DNS в Windows)", "ZH": "禁用主适配器接口DNS(在Windows上缓解DNS泄露)", @@ -1681,7 +1681,7 @@ TRANSLATION = { }, "Memory Optimization": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "Оптимизация памяти", "ZH": "内存优化", @@ -1689,7 +1689,7 @@ TRANSLATION = { }, "TCP Send Buffer Size (MiB)": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "Размер буфера отправки TCP (MiB)", "ZH": "TCP发送缓冲区大小(MiB)", @@ -1697,7 +1697,7 @@ TRANSLATION = { }, "TCP Receive Buffer Size (MiB)": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "Размер буфера приема TCP (MiB)", "ZH": "TCP接收缓冲区大小(MiB)", @@ -1705,7 +1705,7 @@ TRANSLATION = { }, "TCP Receive Buffer Auto-tuning": { "source": [ - "Furious.Widget.GuiTUNSettings" + "Furious.Window.TunSettingsDialog" ], "RU": "Автоматическая настройка буфера приема TCP", "ZH": "TCP接收缓冲区自动调优", @@ -1713,7 +1713,7 @@ TRANSLATION = { }, "Restart The Application As Administrator": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Перезапустите приложение от имени администратора", "ZH": "以管理员身份重新启动应用程序", @@ -1721,7 +1721,7 @@ TRANSLATION = { }, "Restart The Application As Superuser": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Перезапустите приложение от имени суперпользователя", "ZH": "以Superuser身份重新启动应用程序", @@ -1729,7 +1729,7 @@ TRANSLATION = { }, "Administrator": { "source": [ - "Furious.Application.SystemTrayIcon" + "Furious.Application.TrayIcon" ], "RU": "Administrator", "ZH": "管理员", @@ -1737,7 +1737,7 @@ TRANSLATION = { }, "I am the supreme authority 👑": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Я — единственная высшая инстанция 👑", "ZH": "我就是至高无上的存在 👑", @@ -1745,7 +1745,7 @@ TRANSLATION = { }, "Customize System Proxy Bypass Address": { "source": [ - "Furious.Widget.GuiCustomizeProxyBypass" + "Furious.Window.ProxyBypassDialog" ], "RU": "Настроить адреса исключений системного прокси", "ZH": "自定义系统代理绕过地址", @@ -1753,7 +1753,7 @@ TRANSLATION = { }, "Customize System Proxy Bypass Address...": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Настроить адреса исключений системного прокси...", "ZH": "自定义系统代理绕过地址...", @@ -1761,8 +1761,8 @@ TRANSLATION = { }, "Reset": { "source": [ - "Furious.Widget.GuiCustomizeNetworkTest", - "Furious.Widget.GuiCustomizeProxyBypass" + "Furious.Window.NetworkTestDialog", + "Furious.Window.ProxyBypassDialog" ], "RU": "Сбросить", "ZH": "重置", @@ -1770,7 +1770,7 @@ TRANSLATION = { }, "Enter system proxy bypass address (separated by semicolons):": { "source": [ - "Furious.Widget.GuiCustomizeProxyBypass" + "Furious.Window.ProxyBypassDialog" ], "RU": "Введите адреса исключений системного прокси (через точку с запятой):", "ZH": "输入系统代理绕过地址(以分号分隔):", @@ -1778,7 +1778,7 @@ TRANSLATION = { }, "Customize Network Test URL": { "source": [ - "Furious.Widget.GuiCustomizeNetworkTest" + "Furious.Window.NetworkTestDialog" ], "RU": "Настроить URL теста сети", "ZH": "自定义网络测试URL", @@ -1786,7 +1786,7 @@ TRANSLATION = { }, "Customize Network Test URL...": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Настроить URL теста сети...", "ZH": "自定义网络测试URL...", @@ -1794,7 +1794,7 @@ TRANSLATION = { }, "Enter network speed test URL:": { "source": [ - "Furious.Widget.GuiCustomizeNetworkTest" + "Furious.Window.NetworkTestDialog" ], "RU": "Введите URL теста скорости сети:", "ZH": "输入网络速度测试URL:", @@ -1802,7 +1802,7 @@ TRANSLATION = { }, "Enter network connectivity test URL:": { "source": [ - "Furious.Widget.GuiCustomizeNetworkTest" + "Furious.Window.NetworkTestDialog" ], "RU": "Введите URL теста подключения к сети:", "ZH": "输入网络连通性测试URL:", @@ -1810,7 +1810,7 @@ TRANSLATION = { }, "Activate Selected Server": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Активировать выбранный сервер", "ZH": "激活选定的服务器", @@ -1818,7 +1818,7 @@ TRANSLATION = { }, "Search servers with text or regex, e.g. trojan, hk|jp, ^vmess, (us|sg).*tls": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Поиск серверов по тексту или регулярному выражению, например: trojan, hk|jp, ^vmess, (us|sg).*tls", "ZH": "使用文本或正则表达式搜索服务器,例如:trojan、hk|jp、^vmess、(us|sg).*tls", @@ -1826,7 +1826,7 @@ TRANSLATION = { }, "Search": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Поиск", "ZH": "查找", @@ -1834,7 +1834,7 @@ TRANSLATION = { }, "Network OK": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Сеть работает", "ZH": "网络正常", @@ -1842,7 +1842,7 @@ TRANSLATION = { }, "Network error": { "source": [ - "Furious.Window.AppMainWindow" + "Furious.Window.MainWindow" ], "RU": "Ошибка сети", "ZH": "网络异常", @@ -1850,7 +1850,7 @@ TRANSLATION = { }, "Canceling import": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Отмена импорта", "ZH": "正在取消导入", @@ -1858,7 +1858,7 @@ TRANSLATION = { }, "Importing": { "source": [ - "Furious.TrayActions.Import" + "Furious.Actions.Import" ], "RU": "Импортирование", "ZH": "正在导入", @@ -1866,8 +1866,8 @@ TRANSLATION = { }, "Current": { "source": [ - "Furious.TrayActions.Import", - "Furious.Widget.UserServersQTableView" + "Furious.Actions.Import", + "Furious.Widget.ServerTableView" ], "RU": "Текущий", "ZH": "当前", @@ -1875,7 +1875,7 @@ TRANSLATION = { }, "Canceling delete": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Отмена удаления", "ZH": "正在取消删除", @@ -1883,7 +1883,7 @@ TRANSLATION = { }, "Deleting": { "source": [ - "Furious.Widget.UserServersQTableView" + "Furious.Widget.ServerTableView" ], "RU": "Удаление", "ZH": "正在删除", @@ -1891,7 +1891,7 @@ TRANSLATION = { }, "Edit Routing Rule": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Редактировать правило маршрутизации", "ZH": "编辑路由规则", @@ -1899,7 +1899,7 @@ TRANSLATION = { }, "Domain (one per line or comma-separated)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Domain (по одному в строке или через запятую)", "ZH": "Domain(每行一个或以逗号分隔)", @@ -1907,7 +1907,7 @@ TRANSLATION = { }, "IP (one per line or comma-separated)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "IP (по одному в строке или через запятую)", "ZH": "IP(每行一个或以逗号分隔)", @@ -1915,7 +1915,7 @@ TRANSLATION = { }, "Port (comma/range, e.g. 53,443,1000-2000)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Port (через запятую/диапазон, например: 53,443,1000-2000)", "ZH": "Port(逗号/范围,例如:53,443,1000-2000)", @@ -1923,7 +1923,7 @@ TRANSLATION = { }, "VLESS Route (comma/range, e.g. 53,443,1000-2000)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "VLESS Route (через запятую/диапазон, например: 53,443,1000-2000)", "ZH": "VLESS Route(逗号/范围,例如:53,443,1000-2000)", @@ -1931,7 +1931,7 @@ TRANSLATION = { }, "Source IP (one per line or comma-separated)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Source IP (по одному в строке или через запятую)", "ZH": "Source IP(每行一个或以逗号分隔)", @@ -1939,7 +1939,7 @@ TRANSLATION = { }, "Source Port (comma/range, e.g. 53,443,1000-2000)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Source Port (через запятую/диапазон, например: 53,443,1000-2000)", "ZH": "Source Port(逗号/范围,例如:53,443,1000-2000)", @@ -1947,7 +1947,7 @@ TRANSLATION = { }, "Local IP (one per line or comma-separated)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Local IP (по одному в строке или через запятую)", "ZH": "Local IP(每行一个或以逗号分隔)", @@ -1955,7 +1955,7 @@ TRANSLATION = { }, "Local Port (comma/range, e.g. 53,443,1000-2000)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Local Port (через запятую/диапазон, например: 53,443,1000-2000)", "ZH": "Local Port(逗号/范围,例如:53,443,1000-2000)", @@ -1963,7 +1963,7 @@ TRANSLATION = { }, "User (one per line or comma-separated)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "User (по одному в строке или через запятую)", "ZH": "User(每行一个或以逗号分隔)", @@ -1971,7 +1971,7 @@ TRANSLATION = { }, "Inbound Tag (one per line or comma-separated)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Inbound Tag (по одному в строке или через запятую)", "ZH": "Inbound Tag(每行一个或以逗号分隔)", @@ -1979,7 +1979,7 @@ TRANSLATION = { }, "Process (one per line or comma-separated)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Process (по одному в строке или через запятую)", "ZH": "Process(每行一个或以逗号分隔)", @@ -1987,7 +1987,7 @@ TRANSLATION = { }, "Protocol (one per line or comma-separated)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Protocol (по одному в строке или через запятую)", "ZH": "Protocol(每行一个或以逗号分隔)", @@ -1995,7 +1995,7 @@ TRANSLATION = { }, "Edit Routing Remark": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Редактировать примечание к маршруту", "ZH": "编辑路由备注", @@ -2003,7 +2003,7 @@ TRANSLATION = { }, "Add Routing": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Добавить маршрут", "ZH": "添加路由", @@ -2011,7 +2011,7 @@ TRANSLATION = { }, "Routing Rules": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Правила маршрутизации", "ZH": "路由规则", @@ -2019,7 +2019,7 @@ TRANSLATION = { }, "Edit Routing": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Редактировать маршрут", "ZH": "编辑路由", @@ -2027,7 +2027,7 @@ TRANSLATION = { }, "Edit Text": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Редактировать текст", "ZH": "编辑文本", @@ -2035,7 +2035,7 @@ TRANSLATION = { }, "Rename": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Переименовать", "ZH": "重命名", @@ -2043,7 +2043,7 @@ TRANSLATION = { }, "Double-click to enlarge": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Дважды щёлкните, чтобы увеличить", "ZH": "双击放大", @@ -2051,7 +2051,7 @@ TRANSLATION = { }, "State": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Состояние", "ZH": "状态", @@ -2059,7 +2059,7 @@ TRANSLATION = { }, "Enabled": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Включено", "ZH": "已启用", @@ -2067,7 +2067,7 @@ TRANSLATION = { }, "Disabled": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Отключено", "ZH": "已禁用", @@ -2075,7 +2075,7 @@ TRANSLATION = { }, "New Routing": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Новый маршрут", "ZH": "新路由", @@ -2083,7 +2083,7 @@ TRANSLATION = { }, "Routing Documentation": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Документация по маршрутизации", "ZH": "路由文档", @@ -2091,7 +2091,7 @@ TRANSLATION = { }, "Preview Routing": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Предпросмотр маршрутизации", "ZH": "预览路由", @@ -2099,7 +2099,7 @@ TRANSLATION = { }, "OutBound (e.g. proxy/direct/block)": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "OutBound (например: proxy/direct/block)", "ZH": "OutBound(例如:proxy/direct/block)", @@ -2107,7 +2107,7 @@ TRANSLATION = { }, "Preview": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow" + "Furious.Backends.Xray.RoutingWindow" ], "RU": "Предпросмотр", "ZH": "预览", @@ -2115,8 +2115,8 @@ TRANSLATION = { }, "Close": { "source": [ - "Furious.Plugins.Official.Xray.UserRoutingWindow", - "Furious.Widget.TextEditorWindow" + "Furious.Backends.Xray.RoutingWindow", + "Furious.Window.TextEditorWindow" ], "RU": "Закрыть", "ZH": "关闭", @@ -2124,8 +2124,8 @@ TRANSLATION = { }, "Generate": { "source": [ - "Furious.Plugins.Official.Xray.GuiVLESS", - "Furious.Plugins.Official.Xray.GuiVMess" + "Furious.Backends.Xray.VlessEditor", + "Furious.Backends.Xray.VmessEditor" ], "RU": "Сгенерировать", "ZH": "生成", @@ -2133,7 +2133,7 @@ TRANSLATION = { }, "Username": { "source": [ - "Furious.Plugins.Official.Xray.GuiSocks" + "Furious.Backends.Xray.SocksEditor" ], "RU": "Имя пользователя", "ZH": "用户名", @@ -2141,7 +2141,7 @@ TRANSLATION = { }, "Manage Xray-core Asset File...": { "source": [ - "Furious.Plugins.Official.Xray.Plugin" + "Furious.Backends.Xray.Plugin" ], "RU": "Управление файлами ресурсов Xray-core...", "ZH": "管理Xray-core资源文件...", @@ -2149,7 +2149,7 @@ TRANSLATION = { }, "Edit Routing...": { "source": [ - "Furious.Plugins.Official.Xray.Plugin" + "Furious.Backends.Xray.Plugin" ], "RU": "Редактировать маршрут...", "ZH": "编辑路由...", @@ -2157,7 +2157,7 @@ TRANSLATION = { }, "Add VMess Server...": { "source": [ - "Furious.Plugins.Official.Xray.Plugin" + "Furious.Backends.Xray.Plugin" ], "RU": "Добавить сервер VMess...", "ZH": "添加VMess服务器...", @@ -2165,7 +2165,7 @@ TRANSLATION = { }, "Add VLESS Server...": { "source": [ - "Furious.Plugins.Official.Xray.Plugin" + "Furious.Backends.Xray.Plugin" ], "RU": "Добавить сервер VLESS...", "ZH": "添加VLESS服务器...", @@ -2173,7 +2173,7 @@ TRANSLATION = { }, "Add Shadowsocks Server...": { "source": [ - "Furious.Plugins.Official.Xray.Plugin" + "Furious.Backends.Xray.Plugin" ], "RU": "Добавить сервер Shadowsocks...", "ZH": "添加Shadowsocks服务器...", @@ -2181,7 +2181,7 @@ TRANSLATION = { }, "Add Trojan Server...": { "source": [ - "Furious.Plugins.Official.Xray.Plugin" + "Furious.Backends.Xray.Plugin" ], "RU": "Добавить сервер Trojan...", "ZH": "添加Trojan服务器...", @@ -2189,7 +2189,7 @@ TRANSLATION = { }, "Add Hysteria1 Server...": { "source": [ - "Furious.Plugins.Official.Hysteria1.Plugin" + "Furious.Backends.Hysteria1.Plugin" ], "RU": "Добавить сервер Hysteria 1...", "ZH": "添加Hysteria1服务器...", @@ -2197,7 +2197,7 @@ TRANSLATION = { }, "Add Hysteria2 Server...": { "source": [ - "Furious.Plugins.Official.Hysteria2.Plugin" + "Furious.Backends.Hysteria2.Plugin" ], "RU": "Добавить сервер Hysteria 2...", "ZH": "添加Hysteria2服务器...", @@ -2205,7 +2205,7 @@ TRANSLATION = { }, "Add SOCKS Server...": { "source": [ - "Furious.Plugins.Official.Xray.Plugin" + "Furious.Backends.Xray.Plugin" ], "RU": "Добавить сервер SOCKS...", "ZH": "添加SOCKS服务器...", @@ -2213,8 +2213,8 @@ TRANSLATION = { }, "Interface": { "source": [ - "Furious.Plugins.Official.Hysteria2.GuiTUNSettings", - "Furious.Plugins.Official.Xray.GuiTUNSettings" + "Furious.Backends.Hysteria2.TunSettingsDialog", + "Furious.Backends.Xray.TunSettingsDialog" ], "RU": "Интерфейс", "ZH": "接口", @@ -2222,8 +2222,8 @@ TRANSLATION = { }, "Network": { "source": [ - "Furious.Plugins.Official.Hysteria2.GuiTUNSettings", - "Furious.Plugins.Official.Xray.GuiTUNSettings" + "Furious.Backends.Hysteria2.TunSettingsDialog", + "Furious.Backends.Xray.TunSettingsDialog" ], "RU": "Сеть", "ZH": "网络", @@ -2231,7 +2231,7 @@ TRANSLATION = { }, "Use Xray-core TUN": { "source": [ - "Furious.Plugins.Official.Xray.Plugin" + "Furious.Backends.Xray.Plugin" ], "RU": "Использовать TUN Xray-core", "ZH": "使用Xray-core TUN", @@ -2239,7 +2239,7 @@ TRANSLATION = { }, "Customize Xray-core TUN Settings": { "source": [ - "Furious.Plugins.Official.Xray.GuiTUNSettings" + "Furious.Backends.Xray.TunSettingsDialog" ], "RU": "Настроить параметры TUN Xray-core", "ZH": "自定义Xray-core TUN设置", @@ -2247,7 +2247,7 @@ TRANSLATION = { }, "Customize Xray-core TUN Settings...": { "source": [ - "Furious.Plugins.Official.Xray.Plugin" + "Furious.Backends.Xray.Plugin" ], "RU": "Настроить параметры TUN Xray-core...", "ZH": "自定义Xray-core TUN设置...", @@ -2255,7 +2255,7 @@ TRANSLATION = { }, "Gateway (separated by commas)": { "source": [ - "Furious.Plugins.Official.Xray.GuiTUNSettings" + "Furious.Backends.Xray.TunSettingsDialog" ], "RU": "Gateway (через запятую)", "ZH": "Gateway(以逗号分隔)", @@ -2263,7 +2263,7 @@ TRANSLATION = { }, "DNS (separated by commas)": { "source": [ - "Furious.Plugins.Official.Xray.GuiTUNSettings" + "Furious.Backends.Xray.TunSettingsDialog" ], "RU": "DNS (через запятую)", "ZH": "DNS(以逗号分隔)", @@ -2271,7 +2271,7 @@ TRANSLATION = { }, "AutoSystemRoutingTable (separated by commas)": { "source": [ - "Furious.Plugins.Official.Xray.GuiTUNSettings" + "Furious.Backends.Xray.TunSettingsDialog" ], "RU": "AutoSystemRoutingTable (через запятую)", "ZH": "AutoSystemRoutingTable(以逗号分隔)", @@ -2279,8 +2279,8 @@ TRANSLATION = { }, "TUN Documentation": { "source": [ - "Furious.Plugins.Official.Hysteria2.GuiTUNSettings", - "Furious.Plugins.Official.Xray.GuiTUNSettings" + "Furious.Backends.Hysteria2.TunSettingsDialog", + "Furious.Backends.Xray.TunSettingsDialog" ], "RU": "Документация TUN", "ZH": "TUN文档", @@ -2288,7 +2288,7 @@ TRANSLATION = { }, "Use Hysteria2 TUN": { "source": [ - "Furious.Plugins.Official.Hysteria2.Plugin" + "Furious.Backends.Hysteria2.Plugin" ], "RU": "Использовать TUN Hysteria2", "ZH": "使用Hysteria2 TUN", @@ -2296,7 +2296,7 @@ TRANSLATION = { }, "Customize Hysteria2 TUN Settings": { "source": [ - "Furious.Plugins.Official.Hysteria2.GuiTUNSettings" + "Furious.Backends.Hysteria2.TunSettingsDialog" ], "RU": "Настроить параметры TUN Hysteria2", "ZH": "自定义Hysteria2 TUN设置", @@ -2304,7 +2304,7 @@ TRANSLATION = { }, "Customize Hysteria2 TUN Settings...": { "source": [ - "Furious.Plugins.Official.Hysteria2.Plugin" + "Furious.Backends.Hysteria2.Plugin" ], "RU": "Настроить параметры TUN Hysteria2...", "ZH": "自定义Hysteria2 TUN设置...", diff --git a/Furious/Interface/ApplicationFactory.py b/Furious/Interface/Application.py similarity index 92% rename from Furious/Interface/ApplicationFactory.py rename to Furious/Interface/Application.py index 274c371..4eb3594 100644 --- a/Furious/Interface/ApplicationFactory.py +++ b/Furious/Interface/Application.py @@ -21,10 +21,10 @@ from __future__ import annotations from enum import Enum -__all__ = ['ApplicationFactory'] +__all__ = ['ApplicationRunner'] -class ApplicationFactory: +class ApplicationRunner: """Define the lifecycle contract for the top-level application runner.""" class ExitCode(Enum): @@ -36,7 +36,7 @@ class ApplicationFactory: AssertionError = 63 def __init__(self, *args, **kwargs): - """Initialize the ApplicationFactory.""" + """Initialize the application runner.""" super().__init__(*args, **kwargs) def run(self): diff --git a/Furious/Interface/EncoderFactory.py b/Furious/Interface/Codec.py similarity index 95% rename from Furious/Interface/EncoderFactory.py rename to Furious/Interface/Codec.py index b5ed212..488d42f 100644 --- a/Furious/Interface/EncoderFactory.py +++ b/Furious/Interface/Codec.py @@ -22,10 +22,10 @@ from __future__ import annotations from abc import ABC, abstractmethod from typing import Any -__all__ = ['EncoderFactory'] +__all__ = ['Codec'] -class EncoderFactory(ABC): +class Codec(ABC): """Define the interface and shared behavior for encoder objects.""" @abstractmethod diff --git a/Furious/Interface/GuiEditorItemFactory.py b/Furious/Interface/Editor.py similarity index 86% rename from Furious/Interface/GuiEditorItemFactory.py rename to Furious/Interface/Editor.py index 1c5acbb..0cbb7f8 100644 --- a/Furious/Interface/GuiEditorItemFactory.py +++ b/Furious/Interface/Editor.py @@ -21,14 +21,14 @@ from __future__ import annotations from typing import Any -__all__ = ['GuiEditorItemFactory', 'GuiEditorItemWidgetContainer'] +__all__ = ['EditorBinding', 'EditorWidgetBinding'] -class GuiEditorItemFactory: +class EditorBinding: """Define the interface and shared behavior for GUI editor item objects.""" def __init__(self, *args, **kwargs): - """Initialize the GuiEditorItemFactory.""" + """Initialize the editor binding.""" super().__init__(*args, **kwargs) def inputToFactory(self, *args, **kwargs) -> Any: @@ -40,11 +40,11 @@ class GuiEditorItemFactory: raise NotImplementedError -class GuiEditorItemWidgetContainer(GuiEditorItemFactory): +class EditorWidgetBinding(EditorBinding): """Bind one or more editor widgets to configuration data.""" def __init__(self, *args, **kwargs): - """Initialize the GuiEditorItemWidgetContainer.""" + """Initialize the editor widget binding.""" super().__init__(*args, **kwargs) def widgets(self) -> Any: diff --git a/Furious/Interface/CoreProcessFactory.py b/Furious/Interface/Process.py similarity index 94% rename from Furious/Interface/CoreProcessFactory.py rename to Furious/Interface/Process.py index 0a4ea6a..6afe7d2 100644 --- a/Furious/Interface/CoreProcessFactory.py +++ b/Furious/Interface/Process.py @@ -28,10 +28,10 @@ from typing import Callable, Union import ujson import functools -__all__ = ['CoreProcessFactory'] +__all__ = ['CoreProcess'] -class CoreProcessFactory(ABC): +class CoreProcess(ABC): """Define the interface and shared behavior for core process objects.""" class ExitCode(Enum): @@ -45,9 +45,9 @@ class CoreProcessFactory(ABC): def __init__( self, - exitCallback: Union[Callable[[CoreProcessFactory, int], None], None] = None, + exitCallback: Union[Callable[[CoreProcess, int], None], None] = None, ): - """Initialize the CoreProcessFactory.""" + """Initialize the core process.""" super().__init__() self._exitCallback = exitCallback diff --git a/Furious/Interface/UserServersTableItem.py b/Furious/Interface/Server.py similarity index 94% rename from Furious/Interface/UserServersTableItem.py rename to Furious/Interface/Server.py index 7d42f47..3d93c75 100644 --- a/Furious/Interface/UserServersTableItem.py +++ b/Furious/Interface/Server.py @@ -19,14 +19,14 @@ from __future__ import annotations -__all__ = ['UserServersTableItem'] +__all__ = ['ServerTableItem'] -class UserServersTableItem: +class ServerTableItem: """Define the display fields required by a server-table row.""" def __init__(self, *args, **kwargs): - """Initialize the UserServersTableItem.""" + """Initialize the server table item.""" super().__init__(*args, **kwargs) @property diff --git a/Furious/Interface/StorageFactory.py b/Furious/Interface/Storage.py similarity index 95% rename from Furious/Interface/StorageFactory.py rename to Furious/Interface/Storage.py index a8f0e85..bfa22b3 100644 --- a/Furious/Interface/StorageFactory.py +++ b/Furious/Interface/Storage.py @@ -22,10 +22,10 @@ from __future__ import annotations from abc import ABC, abstractmethod from typing import Any -__all__ = ['StorageFactory'] +__all__ = ['StorageBackend'] -class StorageFactory(ABC): +class StorageBackend(ABC): """Define the interface and shared behavior for storage objects.""" @abstractmethod diff --git a/Furious/Interface/__init__.py b/Furious/Interface/__init__.py index d4c2cba..c79525e 100644 --- a/Furious/Interface/__init__.py +++ b/Furious/Interface/__init__.py @@ -19,19 +19,19 @@ from __future__ import annotations -from .ApplicationFactory import ApplicationFactory -from .CoreProcessFactory import CoreProcessFactory -from .EncoderFactory import EncoderFactory -from .GuiEditorItemFactory import GuiEditorItemFactory, GuiEditorItemWidgetContainer -from .StorageFactory import StorageFactory -from .UserServersTableItem import UserServersTableItem +from .Application import ApplicationRunner +from .Codec import Codec +from .Editor import EditorBinding, EditorWidgetBinding +from .Process import CoreProcess +from .Server import ServerTableItem +from .Storage import StorageBackend __all__ = [ - 'ApplicationFactory', - 'CoreProcessFactory', - 'EncoderFactory', - 'GuiEditorItemFactory', - 'GuiEditorItemWidgetContainer', - 'StorageFactory', - 'UserServersTableItem', + 'ApplicationRunner', + 'Codec', + 'CoreProcess', + 'EditorBinding', + 'EditorWidgetBinding', + 'ServerTableItem', + 'StorageBackend', ] diff --git a/Furious/Plugins/Registry.py b/Furious/Plugins/Registry.py index aceac1e..01e6623 100644 --- a/Furious/Plugins/Registry.py +++ b/Furious/Plugins/Registry.py @@ -19,7 +19,7 @@ from __future__ import annotations -from Furious.Library.Configuration import configurationRegistry +from Furious.Domain.Configuration import configurationRegistry from importlib import metadata @@ -32,6 +32,7 @@ __all__ = [ 'PLUGIN_ENTRY_POINT_GROUP', 'PluginRegistry', 'getPluginRegistry', + 'initializePluginRegistry', 'registerPlugin', ] @@ -160,6 +161,10 @@ class PluginRegistry: """Return registered plugins in registration order.""" return tuple(self._plugins.values()) + def plugin(self, pluginId: str): + """Return the plugin registered with ``pluginId``, if any.""" + return self._plugins.get(pluginId) + def protocolDescriptors(self): """Return contributed protocols in their requested menu order.""" descriptors = list( @@ -443,29 +448,41 @@ _registryLock = threading.RLock() _registryInitialized = False -def getPluginRegistry() -> PluginRegistry: - """Return the process-wide registry after lazy official/external discovery.""" +def initializePluginRegistry(pluginTypes=()) -> PluginRegistry: + """Initialize discovery and register host-provided plugin implementations.""" global _registry, _registryInitialized with _registryLock: if not _registryInitialized: - # Importing official plugins is an intentional extension-loading - # boundary. Keeping it here prevents package initialization from - # eagerly importing GUI and core implementations. - from .Official import OFFICIAL_PLUGIN_TYPES - registry = PluginRegistry(configurationRegistry) - for pluginType in OFFICIAL_PLUGIN_TYPES: + for pluginType in pluginTypes: registry.register(pluginType()) registry.discover() _registry = registry _registryInitialized = True + else: + for pluginType in pluginTypes: + plugin = pluginType() + registered = _registry.plugin(plugin.pluginId) + + if registered is None: + _registry.register(plugin) + elif not isinstance(registered, pluginType): + raise ValueError( + f'plugin {plugin.pluginId!r} is already registered by ' + f'{type(registered).__name__}' + ) return _registry +def getPluginRegistry() -> PluginRegistry: + """Return the process-wide registry, discovering external plugins lazily.""" + return initializePluginRegistry() + + def registerPlugin(plugin: FuriousPlugin): """Register a plugin programmatically and return it.""" return getPluginRegistry().register(plugin) diff --git a/Furious/Plugins/__init__.py b/Furious/Plugins/__init__.py index 18a1545..9a6591b 100644 --- a/Furious/Plugins/__init__.py +++ b/Furious/Plugins/__init__.py @@ -24,6 +24,7 @@ from .Registry import ( PLUGIN_ENTRY_POINT_GROUP, PluginRegistry, getPluginRegistry, + initializePluginRegistry, registerPlugin, ) @@ -35,5 +36,6 @@ __all__ = [ 'PluginRegistry', 'PluginRouting', 'getPluginRegistry', + 'initializePluginRegistry', 'registerPlugin', ] diff --git a/Furious/Qt/GuiEditorXXX.py b/Furious/Qt/EditorWidgets.py similarity index 96% rename from Furious/Qt/GuiEditorXXX.py rename to Furious/Qt/EditorWidgets.py index b6dad18..c475011 100644 --- a/Furious/Qt/GuiEditorXXX.py +++ b/Furious/Qt/EditorWidgets.py @@ -21,7 +21,7 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import ConfigFactory +from Furious.Domain import ConfigFactory from Furious.Qt.DynamicTranslate import gettext as _ from Furious.Qt.QtWidgets import * @@ -46,7 +46,7 @@ __all__ = [ ] -class GuiEditorItemTextInput(GuiEditorItemWidgetContainer): +class GuiEditorItemTextInput(EditorWidgetBinding): """Represent GUI editor item text input.""" def __init__(self, *args, **kwargs): @@ -76,7 +76,7 @@ class GuiEditorItemTextInput(GuiEditorItemWidgetContainer): return self._title, self._input -class GuiEditorItemTextSpinBox(GuiEditorItemWidgetContainer): +class GuiEditorItemTextSpinBox(EditorWidgetBinding): """Represent GUI editor item text spin box.""" def __init__(self, *args, **kwargs): @@ -110,7 +110,7 @@ class GuiEditorItemTextSpinBox(GuiEditorItemWidgetContainer): return self._title, self._input -class GuiEditorItemTextComboBox(GuiEditorItemWidgetContainer): +class GuiEditorItemTextComboBox(EditorWidgetBinding): """Represent GUI editor item text combo box.""" def __init__(self, *args, **kwargs): @@ -148,7 +148,7 @@ class GuiEditorItemTextComboBox(GuiEditorItemWidgetContainer): return self._title, self._input -class GuiEditorItemTextCheckBox(GuiEditorItemWidgetContainer): +class GuiEditorItemTextCheckBox(EditorWidgetBinding): """Represent GUI editor item text check box.""" def __init__(self, *args, **kwargs): @@ -284,7 +284,7 @@ class GuiEditorItemProxySocks(GuiEditorItemTextInput): self.setText('') -class GuiEditorWidget(GuiEditorItemFactory): +class GuiEditorWidget(EditorBinding): """Provide the GUI editor widget.""" def __init__(self, *args, **kwargs): @@ -293,7 +293,7 @@ class GuiEditorWidget(GuiEditorItemFactory): self._containers = self.containerSequence() - def containerSequence(self) -> Sequence[GuiEditorItemWidgetContainer]: + def containerSequence(self) -> Sequence[EditorWidgetBinding]: """Return the editor item containers in display order.""" raise NotImplementedError @@ -374,7 +374,7 @@ class GuiEditorWidgetQGroupBox(GuiEditorWidget, AppQGroupBox): return layout -class GuiEditorWidgetQDialog(GuiEditorItemFactory, AppQDialog): +class GuiEditorWidgetQDialog(EditorBinding, AppQDialog): """Present the GUI editor widget Qt dialog.""" def __init__(self, *args, **kwargs): diff --git a/Furious/Qt/QtGui.py b/Furious/Qt/QtGui.py index c2e078b..d534445 100644 --- a/Furious/Qt/QtGui.py +++ b/Furious/Qt/QtGui.py @@ -147,7 +147,7 @@ class AppQAction(Mixins.QTranslatable, Mixins.ThemeAware, QAction): self._menu = menu # Some old version PySide6 does not have setMenu method - # for QAction. Protect it. Currently only used in SystemTrayIcon + # for QAction. Protect it. Currently only used in TrayIcon if hasattr(self, 'setMenu') and useSetMenu: self.setMenu(menu) diff --git a/Furious/Qt/QtWidgets.py b/Furious/Qt/QtWidgets.py index 2a2ac34..84284b2 100644 --- a/Furious/Qt/QtWidgets.py +++ b/Furious/Qt/QtWidgets.py @@ -20,7 +20,7 @@ from __future__ import annotations from Furious.Frozenlib import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt.AppStyleSheet import * from Furious.Qt.DynamicTheme import * from Furious.Qt.DynamicTranslate import gettext as _ diff --git a/Furious/Qt/__init__.py b/Furious/Qt/__init__.py index 0308645..a0ab24f 100644 --- a/Furious/Qt/__init__.py +++ b/Furious/Qt/__init__.py @@ -20,7 +20,6 @@ from __future__ import annotations from .AppStyleSheet import AppStyleSheet -from .DNSResolver import DNSResolver from .DynamicTheme import AppHue from .DynamicTranslate import ( ABBR_TO_LANGUAGE, @@ -28,7 +27,7 @@ from .DynamicTranslate import ( SUPPORTED_LANGUAGE, gettext, ) -from .GuiEditorXXX import ( +from .EditorWidgets import ( GuiEditorItemBasicRemark, GuiEditorItemProxyHttp, GuiEditorItemProxySocks, @@ -40,7 +39,6 @@ from .GuiEditorXXX import ( GuiEditorWidgetQGroupBox, GuiEditorWidgetQWidget, ) -from .NetworkConnectivityManager import NetworkConnectivityManager from .QtGui import ( AppQAction, AppQActionGroup, @@ -94,8 +92,6 @@ from .TextEditorTheme import ( DraculaLoggerSyntaxHighlighter, configureEditorLogMetadata, ) -from .UpdatesManager import UpdatesManager -from .WaitingSpinner import WaitingSpinner from .WebGETManager import WebGETManager __all__ = [ @@ -128,7 +124,6 @@ __all__ = [ 'AppQTextBrowser', 'AppQToolBar', 'AppStyleSheet', - 'DNSResolver', 'DraculaEditorTheme', 'DraculaJSONSyntaxHighlighter', 'DraculaJSONTextEditor', @@ -150,10 +145,7 @@ __all__ = [ 'MBoxNewChangesNextTime', 'MBoxQuestionDelete', 'MBoxUnrecognizedConfig', - 'NetworkConnectivityManager', 'SUPPORTED_LANGUAGE', - 'UpdatesManager', - 'WaitingSpinner', 'WebGETManager', 'bootstrapIcon', 'bootstrapIconMask', diff --git a/Furious/Library/UserRoutings.py b/Furious/Repository/Routings.py similarity index 95% rename from Furious/Library/UserRoutings.py rename to Furious/Repository/Routings.py index f88792d..a9cbb2c 100644 --- a/Furious/Library/UserRoutings.py +++ b/Furious/Repository/Routings.py @@ -21,14 +21,14 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library.Encoder import * +from Furious.Domain.Encoding import * __all__ = ['UserRoutings'] registerAppSettings('CustomRouting') -class UserRoutings(Mixins.CleanupOnExit, StorageFactory): +class UserRoutings(Mixins.CleanupOnExit, StorageBackend): """Manage the persisted custom-routing collection.""" def __init__(self, *args, **kwargs): diff --git a/Furious/Library/UserServers.py b/Furious/Repository/Servers.py similarity index 93% rename from Furious/Library/UserServers.py rename to Furious/Repository/Servers.py index 76de033..aa4fdfc 100644 --- a/Furious/Library/UserServers.py +++ b/Furious/Repository/Servers.py @@ -21,8 +21,8 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library.Configuration import ConfigFactory, configFactoryFromAny -from Furious.Library.Encoder import * +from Furious.Domain.Configuration import ConfigFactory, configFactoryFromAny +from Furious.Domain.Encoding import * __all__ = ['UserServers'] @@ -37,7 +37,7 @@ class UserServer: subsId: str -class UserServers(Mixins.CleanupOnExit, StorageFactory): +class UserServers(Mixins.CleanupOnExit, StorageBackend): # remark, config, subsId. (subsId corresponds to unique in user subscription) """Manage the persisted list of server configurations.""" diff --git a/Furious/Library/Storage.py b/Furious/Repository/Storage.py similarity index 95% rename from Furious/Library/Storage.py rename to Furious/Repository/Storage.py index ad5e4c0..7c95f99 100644 --- a/Furious/Library/Storage.py +++ b/Furious/Repository/Storage.py @@ -21,10 +21,10 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library.UserServers import UserServers -from Furious.Library.UserSubs import UserSubs -from Furious.Library.UserRoutings import UserRoutings -from Furious.Library.UserTUNSettings import UserTUNSettings +from Furious.Repository.Routings import UserRoutings +from Furious.Repository.Servers import UserServers +from Furious.Repository.Subscriptions import UserSubs +from Furious.Repository.TunSettings import UserTUNSettings from typing import Union diff --git a/Furious/Library/UserSubs.py b/Furious/Repository/Subscriptions.py similarity index 96% rename from Furious/Library/UserSubs.py rename to Furious/Repository/Subscriptions.py index cbbb80f..40ed779 100644 --- a/Furious/Library/UserSubs.py +++ b/Furious/Repository/Subscriptions.py @@ -21,7 +21,7 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library.Encoder import * +from Furious.Domain.Encoding import * __all__ = ['UserSubs'] @@ -43,7 +43,7 @@ class UserSub: unique: dict[str, dict] -class UserSubs(Mixins.CleanupOnExit, StorageFactory): +class UserSubs(Mixins.CleanupOnExit, StorageBackend): # unique: { remark, webURL } """Manage the persisted subscription collection.""" diff --git a/Furious/Library/UserTUNSettings.py b/Furious/Repository/TunSettings.py similarity index 95% rename from Furious/Library/UserTUNSettings.py rename to Furious/Repository/TunSettings.py index fc59155..b6fff4f 100644 --- a/Furious/Library/UserTUNSettings.py +++ b/Furious/Repository/TunSettings.py @@ -21,14 +21,14 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library.Encoder import * +from Furious.Domain.Encoding import * __all__ = ['UserTUNSettings'] registerAppSettings('CustomTUNSettings') -class UserTUNSettings(Mixins.CleanupOnExit, StorageFactory): +class UserTUNSettings(Mixins.CleanupOnExit, StorageBackend): """Manage persisted TUN customization values.""" def __init__(self, *args, **kwargs): diff --git a/Furious/Repository/__init__.py b/Furious/Repository/__init__.py new file mode 100644 index 0000000..4f51c4d --- /dev/null +++ b/Furious/Repository/__init__.py @@ -0,0 +1,24 @@ +# Copyright (C) 2024–present Loren Eteval & contributors +# +# This file is part of Furious. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""Expose persisted user-state repositories through the storage facade.""" + +from __future__ import annotations + +from .Storage import Storage + +__all__ = ['Storage'] diff --git a/Furious/Service/CoreManager.py b/Furious/Service/ConnectionManager.py similarity index 97% rename from Furious/Service/CoreManager.py rename to Furious/Service/ConnectionManager.py index df8c545..b34912d 100644 --- a/Furious/Service/CoreManager.py +++ b/Furious/Service/ConnectionManager.py @@ -21,9 +21,11 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * +from Furious.Repository import * from Furious.Plugins import * from Furious.Qt import * +from Furious.Service.DnsResolver import DnsResolver from Furious.Core.CoreProcessWorker import * from Furious.Core.Tun2socks import * @@ -34,7 +36,7 @@ import logging import tempfile import functools -__all__ = ['CoreManager'] +__all__ = ['ConnectionManager'] logger = logging.getLogger(__name__) @@ -67,11 +69,11 @@ def getUserTUNSettings(*args, **kwargs): ) -class CoreManager(Mixins.CleanupOnExit): +class ConnectionManager(Mixins.CleanupOnExit): """Coordinate proxy cores, TUN setup, DNS changes, and routing cleanup.""" def __init__(self, *args, **kwargs): - """Initialize the CoreManager.""" + """Initialize the connection manager.""" super().__init__(*args, **kwargs) self.uniqueCleanup = False @@ -317,9 +319,9 @@ class CoreManager(Mixins.CleanupOnExit): address = configcopy.itemAddress if not isValidIPAddress(address): - DNSResolver.configureHttpProxy(configcopy.httpProxy()) + DnsResolver.configureHttpProxy(configcopy.httpProxy()) - error, resolved = DNSResolver.resolve(address) + error, resolved = DnsResolver.resolve(address) if error: SystemRoutingTable.Relations.clear() @@ -543,7 +545,7 @@ class CoreManager(Mixins.CleanupOnExit): """Stop every managed proxy and TUN process.""" try: for process in list(self.processesPool): - if not isinstance(process, CoreProcessFactory): + if not isinstance(process, CoreProcess): continue try: diff --git a/Furious/Qt/NetworkConnectivityManager.py b/Furious/Service/ConnectivityManager.py similarity index 85% rename from Furious/Qt/NetworkConnectivityManager.py rename to Furious/Service/ConnectivityManager.py index 042c3db..9372700 100644 --- a/Furious/Qt/NetworkConnectivityManager.py +++ b/Furious/Service/ConnectivityManager.py @@ -28,25 +28,25 @@ from PySide6.QtNetwork import * import logging import functools -__all__ = ['NetworkConnectivityManager'] +__all__ = ['ConnectivityManager'] logger = logging.getLogger(__name__) -class NetworkConnectivityManager(Mixins.ConnectionAware, WebGETManager): +class ConnectivityManager(Mixins.ConnectionAware, WebGETManager): """Coordinate network connectivity operations.""" MIN_JOB_INTERVAL = 2500 MAX_JOB_INTERVAL = 2000000000 def __init__(self, parent=None, **kwargs): - """Initialize the NetworkConnectivityManager.""" + """Initialize the connectivity manager.""" actionMessage = kwargs.pop('actionMessage', 'test network connectivity') super().__init__(parent, actionMessage=actionMessage) self.jobStatus = False - self.jobInterval = NetworkConnectivityManager.MIN_JOB_INTERVAL + self.jobInterval = ConnectivityManager.MIN_JOB_INTERVAL self.jobTimeoutTimer = QtCore.QTimer() self.jobArrangeTimer = QtCore.QTimer() @@ -60,13 +60,13 @@ class NetworkConnectivityManager(Mixins.ConnectionAware, WebGETManager): if self.jobStatus is jobStatus: self.jobInterval *= 2 else: - self.jobInterval = NetworkConnectivityManager.MIN_JOB_INTERVAL + self.jobInterval = ConnectivityManager.MIN_JOB_INTERVAL self.jobStatus = jobStatus - if self.jobInterval >= NetworkConnectivityManager.MAX_JOB_INTERVAL: + if self.jobInterval >= ConnectivityManager.MAX_JOB_INTERVAL: # Limited - self.jobInterval = NetworkConnectivityManager.MAX_JOB_INTERVAL + self.jobInterval = ConnectivityManager.MAX_JOB_INTERVAL return self.jobInterval @@ -98,7 +98,7 @@ class NetworkConnectivityManager(Mixins.ConnectionAware, WebGETManager): _networkReply.abort() self.jobTimeoutTimer.timeout.connect(functools.partial(abort, networkReply)) - self.jobTimeoutTimer.start(NetworkConnectivityManager.MIN_JOB_INTERVAL - 500) + self.jobTimeoutTimer.start(ConnectivityManager.MIN_JOB_INTERVAL - 500) def stopTest(self): """Stop test.""" @@ -113,7 +113,7 @@ class NetworkConnectivityManager(Mixins.ConnectionAware, WebGETManager): self.stopTest() else: - self.jobInterval = NetworkConnectivityManager.MIN_JOB_INTERVAL + self.jobInterval = ConnectivityManager.MIN_JOB_INTERVAL self.jobArrangeTimer.start(self.jobInterval) diff --git a/Furious/Qt/DNSResolver.py b/Furious/Service/DnsResolver.py similarity index 96% rename from Furious/Qt/DNSResolver.py rename to Furious/Service/DnsResolver.py index 5a58fa0..4a8a8e7 100644 --- a/Furious/Qt/DNSResolver.py +++ b/Furious/Service/DnsResolver.py @@ -20,7 +20,7 @@ from __future__ import annotations from Furious.Frozenlib import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt.WebGETManager import * from PySide6 import QtCore @@ -30,16 +30,16 @@ from typing import Tuple import logging -__all__ = ['DNSResolver'] +__all__ = ['DnsResolver'] logger = logging.getLogger(__name__) -class _DNSResolver(WebGETManager): +class _DnsResolver(WebGETManager): """Represent DNS resolver.""" def __init__(self, parent=None, **kwargs): - """Initialize the _DNSResolver.""" + """Initialize the DNS resolver.""" actionMessage = kwargs.pop('actionMessage', 'DNS resolution') super().__init__(parent, actionMessage=actionMessage) @@ -161,4 +161,4 @@ class _DNSResolver(WebGETManager): networkReply.abort() -DNSResolver = _DNSResolver() +DnsResolver = _DnsResolver() diff --git a/Furious/Qt/UpdatesManager.py b/Furious/Service/UpdateManager.py similarity index 97% rename from Furious/Qt/UpdatesManager.py rename to Furious/Service/UpdateManager.py index 9e1c60d..ba3f428 100644 --- a/Furious/Qt/UpdatesManager.py +++ b/Furious/Service/UpdateManager.py @@ -20,7 +20,7 @@ from __future__ import annotations from Furious.Frozenlib import * -from Furious.Library import * +from Furious.Domain import * from Furious.Qt.QtWidgets import * from Furious.Qt.DynamicTranslate import gettext as _ from Furious.Qt.WebGETManager import * @@ -33,7 +33,7 @@ from typing import Callable import logging import functools -__all__ = ['UpdatesManager'] +__all__ = ['UpdateManager'] logger = logging.getLogger(__name__) @@ -66,7 +66,7 @@ class MBoxQuestionUpdate(AppQMessageBox): self.moveToCenter() -class UpdatesManager(WebGETManager): +class UpdateManager(WebGETManager): """Coordinate updates operations.""" API_URL = ( @@ -75,7 +75,7 @@ class UpdatesManager(WebGETManager): ) def __init__(self, parent=None, **kwargs): - """Initialize the UpdatesManager.""" + """Initialize the update manager.""" actionMessage = kwargs.pop('actionMessage', 'check for updates') super().__init__(parent, actionMessage=actionMessage) diff --git a/Furious/Service/__init__.py b/Furious/Service/__init__.py index e8f4104..5cdd549 100644 --- a/Furious/Service/__init__.py +++ b/Furious/Service/__init__.py @@ -19,6 +19,14 @@ from __future__ import annotations -from .CoreManager import CoreManager +from .ConnectionManager import ConnectionManager +from .ConnectivityManager import ConnectivityManager +from .DnsResolver import DnsResolver +from .UpdateManager import UpdateManager -__all__ = ['CoreManager'] +__all__ = [ + 'ConnectionManager', + 'ConnectivityManager', + 'DnsResolver', + 'UpdateManager', +] diff --git a/Furious/Utility/AppMainProcess.py b/Furious/Utility/AppMainProcess.py index 2dab7ae..5632717 100644 --- a/Furious/Utility/AppMainProcess.py +++ b/Furious/Utility/AppMainProcess.py @@ -47,7 +47,7 @@ else: class AppMainProcess(ProcessContext.Process): """Represent app main process.""" - def __init__(self, func: Callable[[], ApplicationFactory], **kwargs): + def __init__(self, func: Callable[[], ApplicationRunner], **kwargs): """Initialize the AppMainProcess.""" super().__init__(**kwargs) @@ -64,9 +64,9 @@ class AppMainProcess(ProcessContext.Process): traceback.print_exception(exceptionType, exceptionValue, tb) if isinstance(exceptionValue, AssertionError): - exitcode = ApplicationFactory.ExitCode.AssertionError.value + exitcode = ApplicationRunner.ExitCode.AssertionError.value else: - exitcode = ApplicationFactory.ExitCode.UnknownException.value + exitcode = ApplicationRunner.ExitCode.UnknownException.value logger.error(f'stopped with exitcode {exitcode}') diff --git a/Furious/TrayActions/ConnectProgressBar.py b/Furious/Widget/ConnectionProgressWidget.py similarity index 92% rename from Furious/TrayActions/ConnectProgressBar.py rename to Furious/Widget/ConnectionProgressWidget.py index d1149da..00bec46 100644 --- a/Furious/TrayActions/ConnectProgressBar.py +++ b/Furious/Widget/ConnectionProgressWidget.py @@ -26,14 +26,14 @@ from Furious.Qt import gettext as _ from PySide6 import QtCore from PySide6.QtWidgets import * -__all__ = ['ConnectProgressBar'] +__all__ = ['ConnectionProgressWidget'] -class AutoUpdateProgressBar(Mixins.ConnectionAware, QProgressBar): +class ConnectionProgressBar(Mixins.ConnectionAware, QProgressBar): """Represent auto update progress bar.""" def __init__(self, **kwargs): - """Initialize the AutoUpdateProgressBar.""" + """Initialize the connection progress bar.""" super().__init__(**kwargs) self.setRange(0, 100) @@ -97,11 +97,11 @@ class AutoUpdateProgressBar(Mixins.ConnectionAware, QProgressBar): self._setConnectionState('connected') -class ConnectProgressBar(Mixins.QTranslatable, Mixins.ConnectionAware, QWidget): +class ConnectionProgressWidget(Mixins.QTranslatable, Mixins.ConnectionAware, QWidget): """Provide the connect progress bar widget.""" def __init__(self, parent=None): - """Initialize the ConnectProgressBar.""" + """Initialize the connection progress widget.""" super().__init__(parent) self.setWindowTitle(_(APPLICATION_NAME)) @@ -109,7 +109,7 @@ class ConnectProgressBar(Mixins.QTranslatable, Mixins.ConnectionAware, QWidget): self.setFixedSize(280, 61) # Create a progress bar widget - self._widget = AutoUpdateProgressBar(parent=self) + self._widget = ConnectionProgressBar(parent=self) self._widget.setRange(0, 100) self._layout = QVBoxLayout() diff --git a/Furious/Widget/UserServersQTableView.py b/Furious/Widget/ServerTableView.py similarity index 96% rename from Furious/Widget/UserServersQTableView.py rename to Furious/Widget/ServerTableView.py index fae7008..fcf0efe 100644 --- a/Furious/Widget/UserServersQTableView.py +++ b/Furious/Widget/ServerTableView.py @@ -21,15 +21,13 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * +from Furious.Repository import * from Furious.Plugins import getPluginRegistry from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Service import CoreManager -from Furious.TrayActions.Import import * -from Furious.Qt.WaitingSpinner import * -from Furious.Widget.QRCodeWindow import * -from Furious.Widget.TextEditorWindow import * +from Furious.Service import ConnectionManager +from Furious.Widget.WaitingSpinner import * from PySide6 import QtCore from PySide6.QtGui import * @@ -44,7 +42,7 @@ import icmplib import functools import collections -__all__ = ['UserServersQTableView'] +__all__ = ['ServerTableView'] logger = logging.getLogger(__name__) @@ -160,7 +158,7 @@ class SubscriptionManager(WebGETManager): parent = self.parent() - if isinstance(parent, UserServersQTableView): + if isinstance(parent, ServerTableView): isConnected = APP().isSystemTrayConnected() subsIndexes = list( @@ -471,7 +469,7 @@ class TestDownloadSpeedWorker(WebGETManager): self.hasDataCounter = 0 - self.coreManager = CoreManager() + self.coreManager = ConnectionManager() self.networkReply = None self.elapsedTimer = QtCore.QElapsedTimer() @@ -514,13 +512,13 @@ class TestDownloadSpeedWorker(WebGETManager): def coreExitCallback(self, config: ConfigFactory, exitcode: int): """Handle the core exit callback.""" try: - if exitcode == CoreProcessFactory.ExitCode.ConfigurationError.value: + if exitcode == CoreProcess.ExitCode.ConfigurationError.value: self.factory.setExtras('speedResult', f'Invalid') self.sync() - elif exitcode == CoreProcessFactory.ExitCode.ServerStartFailure.value: + elif exitcode == CoreProcess.ExitCode.ServerStartFailure.value: self.factory.setExtras('speedResult', f'Core start failed') self.sync() - elif exitcode == CoreProcessFactory.ExitCode.SystemShuttingDown.value: + elif exitcode == CoreProcess.ExitCode.SystemShuttingDown.value: pass else: self.factory.setExtras('speedResult', f'Core exited {exitcode}') @@ -1026,27 +1024,27 @@ class DeleteServersProgressDialog(AppQDialog): self.updateStatus() -class UserServersQTableViewHorizontalHeader(AppQHeaderView): +class ServerTableHorizontalHeader(AppQHeaderView): """Provide the user servers Qt table view horizontal table header.""" def __init__(self, *args, **kwargs): - """Initialize the UserServersQTableViewHorizontalHeader.""" + """Initialize the ServerTableHorizontalHeader.""" super().__init__(QtCore.Qt.Orientation.Horizontal, *args, **kwargs) -class UserServersQTableViewVerticalHeader(AppQHeaderView): +class ServerTableVerticalHeader(AppQHeaderView): """Provide the user servers Qt table view vertical table header.""" def __init__(self, *args, **kwargs): - """Initialize the UserServersQTableViewVerticalHeader.""" + """Initialize the ServerTableVerticalHeader.""" super().__init__(QtCore.Qt.Orientation.Vertical, *args, **kwargs) -class UserServersQTableViewHeaders: +class ServerTableColumn: """Describe and render user servers Qt table view table columns.""" def __init__(self, name: str, func: Callable[[ConfigFactory], str] = None): - """Initialize the UserServersQTableViewHeaders.""" + """Initialize the ServerTableColumn.""" self.name = name self.func = func @@ -1078,7 +1076,7 @@ class UserServersTableModel(QtCore.QAbstractTableModel): SortRole = QtCore.Qt.ItemDataRole.UserRole + 1 - def __init__(self, headers: list[UserServersQTableViewHeaders], parent=None): + def __init__(self, headers: list[ServerTableColumn], parent=None): """Initialize the UserServersTableModel.""" super().__init__(parent) @@ -1395,7 +1393,7 @@ _TRANSLATABLE_HEADERS = [ ] -class UserServersQTableView( +class ServerTableView( Mixins.QTranslatable, Mixins.CleanupOnExit, AppQTableView, @@ -1405,19 +1403,23 @@ class UserServersQTableView( RowHeight = 42 Headers = [ - UserServersQTableViewHeaders('Remark'), - UserServersQTableViewHeaders('Protocol'), - UserServersQTableViewHeaders('Address'), - UserServersQTableViewHeaders('Port'), - UserServersQTableViewHeaders('Transport'), - UserServersQTableViewHeaders('TLS'), - UserServersQTableViewHeaders('Subscription', _subscriptionRemark), - UserServersQTableViewHeaders('Latency'), - UserServersQTableViewHeaders('Speed'), + ServerTableColumn('Remark'), + ServerTableColumn('Protocol'), + ServerTableColumn('Address'), + ServerTableColumn('Port'), + ServerTableColumn('Transport'), + ServerTableColumn('TLS'), + ServerTableColumn('Subscription', _subscriptionRemark), + ServerTableColumn('Latency'), + ServerTableColumn('Speed'), ] def __init__(self, *args, **kwargs): - """Initialize the UserServersQTableView.""" + """Initialize the server table view.""" + configurationEditorFactory = kwargs.pop('configurationEditorFactory') + self.qrCodeWindowFactory = kwargs.pop('qrCodeWindowFactory') + importActionsFactory = kwargs.pop('importActionsFactory') + super().__init__(*args, **kwargs) self.sourceModel = UserServersTableModel(self.Headers, parent=self) @@ -1438,18 +1440,17 @@ class UserServersQTableView( parent=self, ) - # Text Editor Window - self.textEditorWindow = TextEditorWindow(parent=self.parent()) + self.configurationEditor = configurationEditorFactory() # Install custom header self.setHorizontalHeader( - UserServersQTableViewHorizontalHeader( + ServerTableHorizontalHeader( parent=self, legacySectionSizeSettingsName='ServerWidgetSectionSizeTable', sectionSizeSettingsName='UserServersHeaderViewState', ) ) - self.setVerticalHeader(UserServersQTableViewVerticalHeader(self)) + self.setVerticalHeader(ServerTableVerticalHeader(self)) self.setDefaultRowHeight(self.RowHeight) self.horizontalHeader().setCustomSectionResizeMode() @@ -1625,21 +1626,7 @@ class UserServersQTableView( QtCore.Qt.Key.Key_N, ), ), - ImportFromFileAction(), - ImportURIFromClipboardAction( - shortcut=QtCore.QKeyCombination( - QtCore.Qt.KeyboardModifier.ControlModifier, - QtCore.Qt.Key.Key_V, - ), - ), - ImportJSONFromClipboardAction( - shortcut=QtCore.QKeyCombination( - QtCore.Qt.KeyboardModifier.ControlModifier - | QtCore.Qt.KeyboardModifier.ShiftModifier, - QtCore.Qt.Key.Key_J, - ), - ), - ImportQRCodeOnTheScreenAction(), + *importActionsFactory(), AppQSeperator(), AppQAction( _('Export Share Link To Clipboard'), @@ -2287,13 +2274,13 @@ class UserServersQTableView( index = indexes[0] title = f'{index + 1} - ' + Storage.UserServers()[index].getExtras('remark') - self.textEditorWindow.currentIndex = index - self.textEditorWindow.customWindowTitle = title - self.textEditorWindow.setWindowTitle(title) - self.textEditorWindow.setPlainText( + self.configurationEditor.currentIndex = index + self.configurationEditor.customWindowTitle = title + self.configurationEditor.setWindowTitle(title) + self.configurationEditor.setPlainText( Storage.UserServers()[index].toJSONString(), True ) - self.textEditorWindow.show() + self.configurationEditor.show() def activateSelectedServer(self): """Activate selected server.""" @@ -2586,7 +2573,7 @@ class UserServersQTableView( # Nothing selected. Do nothing return - window = QRCodeWindow() + window = self.qrCodeWindowFactory() window.initTabByIndex(indexes) if window.tabCount() > 0: @@ -2609,11 +2596,11 @@ class UserServersQTableView( def showTabAndSpaces(self): """Show tab and spaces.""" - self.textEditorWindow.showTabAndSpaces() + self.configurationEditor.showTabAndSpaces() def hideTabAndSpaces(self): """Hide tab and spaces.""" - self.textEditorWindow.hideTabAndSpaces() + self.configurationEditor.hideTabAndSpaces() def keyPressEvent(self, event): """Handle a key press for the user servers Qt table view.""" diff --git a/Furious/Widget/UserSubsQTableView.py b/Furious/Widget/SubscriptionTableView.py similarity index 95% rename from Furious/Widget/UserSubsQTableView.py rename to Furious/Widget/SubscriptionTableView.py index c1063b9..642eea7 100644 --- a/Furious/Widget/UserSubsQTableView.py +++ b/Furious/Widget/SubscriptionTableView.py @@ -20,7 +20,7 @@ from __future__ import annotations from Furious.Frozenlib import * -from Furious.Library import * +from Furious.Repository import * from Furious.Qt import * from Furious.Qt import gettext as _ @@ -35,34 +35,34 @@ import functools logger = logging.getLogger(__name__) -__all__ = ['UserSubsQTableView'] +__all__ = ['SubscriptionTableView'] # Migrate legacy settings registerAppSettings('SubscriptionWidgetSectionSizeTable') registerAppSettings('UserSubsHeaderViewState') -class UserSubsQTableViewHorizontalHeader(AppQHeaderView): +class SubscriptionTableHorizontalHeader(AppQHeaderView): """Provide the user subs Qt table view horizontal table header.""" def __init__(self, *args, **kwargs): - """Initialize the UserSubsQTableViewHorizontalHeader.""" + """Initialize the SubscriptionTableHorizontalHeader.""" super().__init__(QtCore.Qt.Orientation.Horizontal, *args, **kwargs) -class UserSubsQTableViewVerticalHeader(AppQHeaderView): +class SubscriptionTableVerticalHeader(AppQHeaderView): """Provide the user subs Qt table view vertical table header.""" def __init__(self, *args, **kwargs): - """Initialize the UserSubsQTableViewVerticalHeader.""" + """Initialize the SubscriptionTableVerticalHeader.""" super().__init__(QtCore.Qt.Orientation.Vertical, *args, **kwargs) -class UserSubsQTableViewHeaders: +class SubscriptionTableColumn: """Describe and render user subs Qt table view table columns.""" def __init__(self, name: str, func: Callable[[dict], str] = None): - """Initialize the UserSubsQTableViewHeaders.""" + """Initialize the SubscriptionTableColumn.""" self.name = name self.func = func @@ -101,7 +101,7 @@ class UserSubsTableModel(QtCore.QAbstractTableModel): def __init__( self, - headers: list[UserSubsQTableViewHeaders], + headers: list[SubscriptionTableColumn], itemKey: list[str], parent=None, ): @@ -271,7 +271,7 @@ _TRANSLATABLE_HEADERS = [ ] -class UserSubsQTableView(Mixins.QTranslatable, AppQTableView): +class SubscriptionTableView(Mixins.QTranslatable, AppQTableView): """Represent user subs Qt table view.""" RowHeight = 42 @@ -302,12 +302,10 @@ class UserSubsQTableView(Mixins.QTranslatable, AppQTableView): } Headers = [ - UserSubsQTableViewHeaders('Remark', lambda item: item.get('remark', '')), - UserSubsQTableViewHeaders('URL', lambda item: item.get('webURL', '')), - UserSubsQTableViewHeaders( - 'Auto Update', lambda item: item.get('autoupdate', '') - ), - UserSubsQTableViewHeaders( + SubscriptionTableColumn('Remark', lambda item: item.get('remark', '')), + SubscriptionTableColumn('URL', lambda item: item.get('webURL', '')), + SubscriptionTableColumn('Auto Update', lambda item: item.get('autoupdate', '')), + SubscriptionTableColumn( 'Auto Update Use Proxy', lambda item: item.get('proxy', '') ), ] @@ -316,7 +314,7 @@ class UserSubsQTableView(Mixins.QTranslatable, AppQTableView): ItemKey = ['remark', 'webURL', 'autoupdate', 'proxy'] def __init__(self, *args, **kwargs): - """Initialize the UserSubsQTableView.""" + """Initialize the subscription table view.""" self.deleteUniqueCallback = kwargs.pop('deleteUniqueCallback', None) super().__init__(*args, **kwargs) @@ -328,13 +326,13 @@ class UserSubsQTableView(Mixins.QTranslatable, AppQTableView): # Install custom header self.setHorizontalHeader( - UserSubsQTableViewHorizontalHeader( + SubscriptionTableHorizontalHeader( parent=self, legacySectionSizeSettingsName='SubscriptionWidgetSectionSizeTable', sectionSizeSettingsName='UserSubsHeaderViewState', ) ) - self.setVerticalHeader(UserSubsQTableViewVerticalHeader(self)) + self.setVerticalHeader(SubscriptionTableVerticalHeader(self)) self.setDefaultRowHeight(self.RowHeight) self.horizontalHeader().setCustomSectionResizeMode() diff --git a/Furious/Qt/WaitingSpinner.py b/Furious/Widget/WaitingSpinner.py similarity index 100% rename from Furious/Qt/WaitingSpinner.py rename to Furious/Widget/WaitingSpinner.py diff --git a/Furious/Widget/__init__.py b/Furious/Widget/__init__.py index 99220a8..b03e2c9 100644 --- a/Furious/Widget/__init__.py +++ b/Furious/Widget/__init__.py @@ -15,26 +15,18 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""Expose reusable application widgets and configuration editors.""" +"""Expose reusable visual components that do not own application windows.""" from __future__ import annotations -from .GuiCustomizeNetworkTest import GuiCustomizeNetworkTestDialog -from .GuiCustomizeProxyBypass import GuiCustomizeProxyBypassDialog -from .GuiTUNSettings import GuiTUNSettings -from .IndentSpinBox import IndentSpinBox -from .QRCodeWindow import QRCodeWindow -from .TextEditorWindow import TextEditorWindow -from .UserServersQTableView import UserServersQTableView -from .UserSubsQTableView import UserSubsQTableView +from .ConnectionProgressWidget import ConnectionProgressWidget +from .ServerTableView import ServerTableView +from .SubscriptionTableView import SubscriptionTableView +from .WaitingSpinner import WaitingSpinner __all__ = [ - 'GuiCustomizeNetworkTestDialog', - 'GuiCustomizeProxyBypassDialog', - 'GuiTUNSettings', - 'IndentSpinBox', - 'QRCodeWindow', - 'TextEditorWindow', - 'UserServersQTableView', - 'UserSubsQTableView', + 'ConnectionProgressWidget', + 'ServerTableView', + 'SubscriptionTableView', + 'WaitingSpinner', ] diff --git a/Furious/Widget/IndentSpinBox.py b/Furious/Window/IndentDialog.py similarity index 94% rename from Furious/Widget/IndentSpinBox.py rename to Furious/Window/IndentDialog.py index 1291c4a..719082d 100644 --- a/Furious/Widget/IndentSpinBox.py +++ b/Furious/Window/IndentDialog.py @@ -25,14 +25,14 @@ from Furious.Qt import gettext as _ from PySide6 import QtCore from PySide6.QtWidgets import * -__all__ = ['IndentSpinBox'] +__all__ = ['IndentDialog'] -class IndentSpinBox(AppQDialog): +class IndentDialog(AppQDialog): """Represent indent spin box.""" def __init__(self, parent=None): - """Initialize the IndentSpinBox.""" + """Initialize the indentation dialog.""" super().__init__(parent) self.setWindowTitle(_('Set Indent')) diff --git a/Furious/Window/LogViewerWindow.py b/Furious/Window/LogWindow.py similarity index 97% rename from Furious/Window/LogViewerWindow.py rename to Furious/Window/LogWindow.py index 937648e..4c608d4 100644 --- a/Furious/Window/LogViewerWindow.py +++ b/Furious/Window/LogWindow.py @@ -25,7 +25,7 @@ from Furious.Qt import gettext as _ from PySide6 import QtCore from PySide6.QtWidgets import * -__all__ = ['LogViewerWindow'] +__all__ = ['LogWindow'] class MBoxSaveError(AppQMessageBox): @@ -76,11 +76,11 @@ def saveAsFile(content: str): mbox.open() -class LogViewerWindow(AppQMainWindow): +class LogWindow(AppQMainWindow): """Present the log viewer window.""" def __init__(self, *args, **kwargs): - """Initialize the LogViewerWindow.""" + """Initialize the log window.""" tabTitle = kwargs.pop('tabTitle', '') fontFamily = kwargs.pop('fontFamily', '') pointSizeSettingsName = kwargs.pop('pointSizeSettingsName', '') diff --git a/Furious/Window/AppMainWindow.py b/Furious/Window/MainWindow.py similarity index 90% rename from Furious/Window/AppMainWindow.py rename to Furious/Window/MainWindow.py index e9fb522..0177c7e 100644 --- a/Furious/Window/AppMainWindow.py +++ b/Furious/Window/MainWindow.py @@ -21,15 +21,25 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Domain import * +from Furious.Repository import * from Furious.Plugins import getPluginRegistry from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Widget.UserServersQTableView import * -from Furious.Widget.GuiCustomizeNetworkTest import * -from Furious.Widget.GuiCustomizeProxyBypass import * -from Furious.Widget.GuiTUNSettings import * -from Furious.Window.UserSubsWindow import * +from Furious.Service import ConnectivityManager, UpdateManager +from Furious.Actions.Import import ( + ImportFromFileAction, + ImportJSONFromClipboardAction, + ImportQRCodeOnTheScreenAction, + ImportURIFromClipboardAction, +) +from Furious.Widget.ServerTableView import * +from Furious.Window.NetworkTestDialog import * +from Furious.Window.ProxyBypassDialog import * +from Furious.Window.QRCodeWindow import QRCodeWindow +from Furious.Window.SubscriptionWindow import * +from Furious.Window.TextEditorWindow import TextEditorWindow +from Furious.Window.TunSettingsDialog import * from PySide6 import QtCore from PySide6.QtGui import * @@ -41,7 +51,7 @@ import os import logging import functools -__all__ = ['AppMainWindow'] +__all__ = ['MainWindow'] logger = logging.getLogger(__name__) @@ -66,18 +76,18 @@ registerAppSettings('AppMainWindowGeometry') registerAppSettings('AppMainWindowState') -class AppNetworkConnectivityManager(NetworkConnectivityManager): +class AppConnectivityManager(ConnectivityManager): """Coordinate app network connectivity operations.""" def __init__(self, parent=None): - """Initialize the AppNetworkConnectivityManager.""" + """Initialize the application connectivity manager.""" super().__init__(parent) def successCallback(self, networkReply, **kwargs): """Handle a successful network operation.""" parent = self.parent() - if isinstance(parent, AppMainWindow): + if isinstance(parent, MainWindow): parent.setNetworkState(True) super().successCallback(networkReply, **kwargs) @@ -86,7 +96,7 @@ class AppNetworkConnectivityManager(NetworkConnectivityManager): """Handle a failed network operation.""" parent = self.parent() - if isinstance(parent, AppMainWindow): + if isinstance(parent, MainWindow): parent.setNetworkState(False, errorString=networkReply.errorString()) super().failureCallback(networkReply, **kwargs) @@ -96,7 +106,7 @@ class AppNetworkConnectivityManager(NetworkConnectivityManager): if not APP().isSystemTrayConnected(): parent = self.parent() - if isinstance(parent, AppMainWindow): + if isinstance(parent, MainWindow): parent.resetNetworkState() self.stopTest() @@ -106,7 +116,7 @@ class AppNetworkConnectivityManager(NetworkConnectivityManager): if connectedHttpProxy is None: parent = self.parent() - if isinstance(parent, AppMainWindow): + if isinstance(parent, MainWindow): parent.resetNetworkState() else: self.configureHttpProxy(connectedHttpProxy) @@ -117,7 +127,7 @@ class AppNetworkConnectivityManager(NetworkConnectivityManager): """Update the app network connectivity manager for a disconnected state.""" parent = self.parent() - if isinstance(parent, AppMainWindow): + if isinstance(parent, MainWindow): parent.resetNetworkState() super().disconnectedCallback() @@ -263,7 +273,7 @@ class SearchButton(AppQPushButton): self.setText(self.customText()) -class AppMainWindow(AppQMainWindow): +class MainWindow(AppQMainWindow): """Present the app main window.""" DEFAULT_WINDOW_SIZE_DARWIN = QtCore.QSize(1500, 780) @@ -271,8 +281,29 @@ class AppMainWindow(AppQMainWindow): QtCore.QSize(1800, 960) if PLATFORM != 'Darwin' else DEFAULT_WINDOW_SIZE_DARWIN ) + @staticmethod + def serverImportActions(): + """Build import actions contributed to the server table context menu.""" + return ( + ImportFromFileAction(), + ImportURIFromClipboardAction( + shortcut=QtCore.QKeyCombination( + QtCore.Qt.KeyboardModifier.ControlModifier, + QtCore.Qt.Key.Key_V, + ), + ), + ImportJSONFromClipboardAction( + shortcut=QtCore.QKeyCombination( + QtCore.Qt.KeyboardModifier.ControlModifier + | QtCore.Qt.KeyboardModifier.ShiftModifier, + QtCore.Qt.Key.Key_J, + ), + ), + ImportQRCodeOnTheScreenAction(), + ) + def __init__(self, *args, **kwargs): - """Initialize the AppMainWindow.""" + """Initialize the main window.""" super().__init__(*args, **kwargs) if SystemRuntime.isAdmin(): @@ -283,11 +314,16 @@ class AppMainWindow(AppQMainWindow): # TODO: Need this? # self.setAttribute(QtCore.Qt.WidgetAttribute.WA_ShowWithoutActivating) - self.updatesManager = UpdatesManager(parent=self) - self.networkConnectivityManager = AppNetworkConnectivityManager(parent=self) + self.updatesManager = UpdateManager(parent=self) + self.networkConnectivityManager = AppConnectivityManager(parent=self) - self.userServersQTableWidget = UserServersQTableView(parent=self) - self.userSubsWindow = UserSubsWindow( + self.userServersQTableWidget = ServerTableView( + parent=self, + configurationEditorFactory=lambda: TextEditorWindow(parent=self), + qrCodeWindowFactory=QRCodeWindow, + importActionsFactory=self.serverImportActions, + ) + self.userSubsWindow = SubscriptionWindow( parent=self, deleteUniqueCallback=lambda unique: self.userServersQTableWidget.deleteItemByIndex( list( @@ -299,8 +335,8 @@ class AppMainWindow(AppQMainWindow): ), ) pluginRegistry = getPluginRegistry() - self.customizeProxyBypassDialog = GuiCustomizeProxyBypassDialog(parent=self) - self.customizeNetworkTestDialog = GuiCustomizeNetworkTestDialog(parent=self) + self.customizeProxyBypassDialog = ProxyBypassDialog(parent=self) + self.customizeNetworkTestDialog = NetworkTestDialog(parent=self) self.mainTab = AppQTabWidget() self.mainTab.addTab(self.userServersQTableWidget, _('Server')) @@ -702,7 +738,7 @@ class AppMainWindow(AppQMainWindow): """Return the cached GUI TUN settings value used by the app main window.""" parent = kwargs.pop('parent', self) - return GuiTUNSettings(parent=parent, **kwargs) + return TunSettingsDialog(parent=parent, **kwargs) guiTUNSettings = cachedGuiTUNSettings() guiTUNSettings.factoryToInput(Storage.UserTUNSettings()) @@ -808,20 +844,20 @@ class AppMainWindow(AppQMainWindow): width, height = tuple(int(size) for size in windowSize) if (width, height) == (640, 480): - self.resize(AppMainWindow.DEFAULT_WINDOW_SIZE) + self.resize(MainWindow.DEFAULT_WINDOW_SIZE) else: self.resize(width, height) except Exception: # Any non-exit exceptions - self.resize(AppMainWindow.DEFAULT_WINDOW_SIZE) + self.resize(MainWindow.DEFAULT_WINDOW_SIZE) else: try: self.restoreGeometry(AppSettings.get('AppMainWindowGeometry')) except Exception: # Any non-exit exceptions - self.resize(AppMainWindow.DEFAULT_WINDOW_SIZE) + self.resize(MainWindow.DEFAULT_WINDOW_SIZE) try: self.restoreState(AppSettings.get('AppMainWindowState')) @@ -839,9 +875,9 @@ class AppMainWindow(AppQMainWindow): logger.error( f'detected unresolve Qt bug on macOS. ' f'Resizing main window to default ' - f'{AppMainWindow.DEFAULT_WINDOW_SIZE.toTuple()}' + f'{MainWindow.DEFAULT_WINDOW_SIZE.toTuple()}' ) - self.resize(AppMainWindow.DEFAULT_WINDOW_SIZE) + self.resize(MainWindow.DEFAULT_WINDOW_SIZE) else: logger.info( f'restore main window size on macOS success: ' diff --git a/Furious/Widget/GuiCustomizeNetworkTest.py b/Furious/Window/NetworkTestDialog.py similarity index 97% rename from Furious/Widget/GuiCustomizeNetworkTest.py rename to Furious/Window/NetworkTestDialog.py index f288a93..871fcc5 100644 --- a/Furious/Widget/GuiCustomizeNetworkTest.py +++ b/Furious/Window/NetworkTestDialog.py @@ -29,7 +29,7 @@ from PySide6.QtWidgets import * import logging import functools -__all__ = ['GuiCustomizeNetworkTestDialog'] +__all__ = ['NetworkTestDialog'] logger = logging.getLogger(__name__) @@ -37,11 +37,11 @@ registerAppSettings('CustomNetworkSpeedTestURL') registerAppSettings('CustomNetworkConnectivityTestURL') -class GuiCustomizeNetworkTestDialog(AppQDialog): +class NetworkTestDialog(AppQDialog): """Present the GUI customize network test dialog.""" def __init__(self, *args, **kwargs): - """Initialize the GuiCustomizeNetworkTestDialog.""" + """Initialize the network test settings dialog.""" super().__init__(*args, **kwargs) self.setWindowTitle(_('Customize Network Test URL')) diff --git a/Furious/Widget/GuiCustomizeProxyBypass.py b/Furious/Window/ProxyBypassDialog.py similarity index 96% rename from Furious/Widget/GuiCustomizeProxyBypass.py rename to Furious/Window/ProxyBypassDialog.py index 7d23307..e9db69f 100644 --- a/Furious/Widget/GuiCustomizeProxyBypass.py +++ b/Furious/Window/ProxyBypassDialog.py @@ -29,18 +29,18 @@ from PySide6.QtWidgets import * import logging import functools -__all__ = ['GuiCustomizeProxyBypassDialog'] +__all__ = ['ProxyBypassDialog'] logger = logging.getLogger(__name__) registerAppSettings('CustomProxyBypass') -class GuiCustomizeProxyBypassDialog(AppQDialog): +class ProxyBypassDialog(AppQDialog): """Present the GUI customize proxy bypass dialog.""" def __init__(self, *args, **kwargs): - """Initialize the GuiCustomizeProxyBypassDialog.""" + """Initialize the proxy bypass settings dialog.""" super().__init__(*args, **kwargs) self.setWindowTitle(_('Customize System Proxy Bypass Address')) diff --git a/Furious/Widget/QRCodeWindow.py b/Furious/Window/QRCodeWindow.py similarity index 99% rename from Furious/Widget/QRCodeWindow.py rename to Furious/Window/QRCodeWindow.py index 0c49199..63d150c 100644 --- a/Furious/Widget/QRCodeWindow.py +++ b/Furious/Window/QRCodeWindow.py @@ -20,7 +20,7 @@ from __future__ import annotations from Furious.Frozenlib import * -from Furious.Library import * +from Furious.Repository import * from Furious.Qt import * from Furious.Qt import gettext as _ diff --git a/Furious/Window/UserSubsWindow.py b/Furious/Window/SubscriptionWindow.py similarity index 92% rename from Furious/Window/UserSubsWindow.py rename to Furious/Window/SubscriptionWindow.py index 97ee9fd..4e66e6b 100644 --- a/Furious/Window/UserSubsWindow.py +++ b/Furious/Window/SubscriptionWindow.py @@ -22,7 +22,7 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Widget.UserSubsQTableView import * +from Furious.Widget.SubscriptionTableView import * from PySide6 import QtCore from PySide6.QtWidgets import * @@ -30,7 +30,7 @@ from PySide6.QtWidgets import * import uuid import functools -__all__ = ['UserSubsWindow'] +__all__ = ['SubscriptionWindow'] # Migrate legacy settings registerAppSettings('SubscriptionWidgetWindowSize') @@ -84,20 +84,20 @@ class AddSubsDialog(AppQDialog): return self.webURLEdit.text() -class UserSubsWindow(AppQMainWindow): +class SubscriptionWindow(AppQMainWindow): """Present the user subs window.""" DEFAULT_WINDOW_SIZE = QtCore.QSize(1120, 600) def __init__(self, *args, **kwargs): - """Initialize the UserSubsWindow.""" + """Initialize the subscription window.""" callback = kwargs.pop('deleteUniqueCallback', None) super().__init__(*args, **kwargs) self.setWindowTitle(_('Edit Subscription')) - self.userSubsQTableWidget = UserSubsQTableView( + self.userSubsQTableWidget = SubscriptionTableView( deleteUniqueCallback=callback, parent=self ) @@ -176,23 +176,23 @@ class UserSubsWindow(AppQMainWindow): width, height = tuple(int(size) for size in windowSize) if (width, height) == (640, 480): - self.resize(UserSubsWindow.DEFAULT_WINDOW_SIZE) + self.resize(SubscriptionWindow.DEFAULT_WINDOW_SIZE) else: self.resize(width, height) except Exception: # Any non-exit exceptions - self.resize(UserSubsWindow.DEFAULT_WINDOW_SIZE) + self.resize(SubscriptionWindow.DEFAULT_WINDOW_SIZE) else: if PLATFORM == 'Darwin': - self.resize(UserSubsWindow.DEFAULT_WINDOW_SIZE) + self.resize(SubscriptionWindow.DEFAULT_WINDOW_SIZE) else: try: self.restoreGeometry(AppSettings.get('UserSubsWindowGeometry')) except Exception: # Any non-exit exceptions - self.resize(UserSubsWindow.DEFAULT_WINDOW_SIZE) + self.resize(SubscriptionWindow.DEFAULT_WINDOW_SIZE) try: self.restoreState(AppSettings.get('UserSubsWindowState')) diff --git a/Furious/Widget/TextEditorWindow.py b/Furious/Window/TextEditorWindow.py similarity index 98% rename from Furious/Widget/TextEditorWindow.py rename to Furious/Window/TextEditorWindow.py index 19e7dcc..0a8b4ec 100644 --- a/Furious/Widget/TextEditorWindow.py +++ b/Furious/Window/TextEditorWindow.py @@ -20,10 +20,11 @@ from __future__ import annotations from Furious.Frozenlib import * -from Furious.Library import * +from Furious.Domain import * +from Furious.Repository import * from Furious.Qt import * from Furious.Qt import gettext as _ -from Furious.Widget.IndentSpinBox import * +from Furious.Window.IndentDialog import * from PySide6 import QtCore from PySide6.QtGui import * @@ -367,7 +368,7 @@ class TextEditorWindow(AppQMainWindow): # Do nothing pass - indentSpinBox = IndentSpinBox(parent=self) + indentSpinBox = IndentDialog(parent=self) indentSpinBox.finished.connect( functools.partial(handleResultCode, indentSpinBox) ) diff --git a/Furious/Widget/GuiTUNSettings.py b/Furious/Window/TunSettingsDialog.py similarity index 98% rename from Furious/Widget/GuiTUNSettings.py rename to Furious/Window/TunSettingsDialog.py index 5a805d8..ea7ef04 100644 --- a/Furious/Widget/GuiTUNSettings.py +++ b/Furious/Window/TunSettingsDialog.py @@ -21,7 +21,7 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Interface import * -from Furious.Library import * +from Furious.Repository import * from Furious.Qt import * from Furious.Qt import gettext as _ @@ -32,7 +32,7 @@ from PySide6.QtWidgets import * import logging import functools -__all__ = ['GuiTUNSettings'] +__all__ = ['TunSettingsDialog'] logger = logging.getLogger(__name__) @@ -173,7 +173,7 @@ class AppQLabelHelpPage(AppQLabel): self.setWebsiteURL() -class GuiTUNSettingsItemHelpPage(GuiEditorItemWidgetContainer): +class GuiTUNSettingsItemHelpPage(EditorWidgetBinding): """Provide the TUN settings item help configuration editor page.""" def __init__(self, *args, **kwargs): @@ -289,11 +289,11 @@ class GuiTUNSettingsGroupBoxMemory(GuiEditorWidgetQGroupBox): ] -class GuiTUNSettings(GuiEditorWidgetQDialog): +class TunSettingsDialog(GuiEditorWidgetQDialog): """Store and validate GUI TUN settings.""" def __init__(self, *args, **kwargs): - """Initialize the GuiTUNSettings.""" + """Initialize the tun2socks settings dialog.""" tabTranslatable = kwargs.pop('tabTranslatable', True) style = kwargs.pop('style', 'portrait') diff --git a/Furious/Window/__init__.py b/Furious/Window/__init__.py index 75bb168..29c98d4 100644 --- a/Furious/Window/__init__.py +++ b/Furious/Window/__init__.py @@ -15,12 +15,28 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""Expose the application window classes.""" +"""Expose application windows and complete dialog compositions.""" from __future__ import annotations -from .AppMainWindow import AppMainWindow -from .LogViewerWindow import LogViewerWindow -from .UserSubsWindow import UserSubsWindow +from .IndentDialog import IndentDialog +from .LogWindow import LogWindow +from .MainWindow import MainWindow +from .NetworkTestDialog import NetworkTestDialog +from .ProxyBypassDialog import ProxyBypassDialog +from .QRCodeWindow import QRCodeWindow +from .SubscriptionWindow import SubscriptionWindow +from .TextEditorWindow import TextEditorWindow +from .TunSettingsDialog import TunSettingsDialog -__all__ = ['AppMainWindow', 'LogViewerWindow', 'UserSubsWindow'] +__all__ = [ + 'IndentDialog', + 'LogWindow', + 'MainWindow', + 'NetworkTestDialog', + 'ProxyBypassDialog', + 'QRCodeWindow', + 'SubscriptionWindow', + 'TextEditorWindow', + 'TunSettingsDialog', +] diff --git a/Furious/__main__.py b/Furious/__main__.py index 905357b..ccd7a06 100644 --- a/Furious/__main__.py +++ b/Furious/__main__.py @@ -24,7 +24,7 @@ from Furious.Interface import * from Furious.Qt import * from Furious.Qt import gettext as _ from Furious.Utility import * -from Furious.Application import Application +from Furious.Application import DesktopApplication from PySide6 import QtCore from PySide6.QtGui import QDesktopServices @@ -59,7 +59,7 @@ def runClearSettings(): def runAppMain(): """Run app main.""" - process = AppMainProcess(functools.partial(Application, sys.argv)) + process = AppMainProcess(functools.partial(DesktopApplication, sys.argv)) process.start() process.join() @@ -70,9 +70,9 @@ def runAppMain(): sys.exit(exitcode) # For Qt runtime. Not used - _app = Application(sys.argv) + _app = DesktopApplication(sys.argv) - if exitcode == ApplicationFactory.ExitCode.PlatformNotSupported.value: + if exitcode == ApplicationRunner.ExitCode.PlatformNotSupported.value: mbox = AppQMessageBox(icon=AppQMessageBox.Icon.Critical) mbox.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg')) @@ -102,7 +102,7 @@ def runAppMain(): # Show the MessageBox and wait for the user to close it mbox.exec() else: - if exitcode == ApplicationFactory.ExitCode.AssertionError.value: + if exitcode == ApplicationRunner.ExitCode.AssertionError.value: # Assertion error text = _( f'{APPLICATION_NAME} encountered an internal error and needs to be stopped' diff --git a/Translation.py b/Translation.py index e9051f5..8daf838 100644 --- a/Translation.py +++ b/Translation.py @@ -19,7 +19,7 @@ from __future__ import annotations from Furious.Frozenlib import * from Furious.Externals import * -from Furious.Library import * +from Furious.Domain import * import os import re