Furious-GUI 0.2.1__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Action/Routing.py +4 -4
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/Constants.py +5 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/Translator.py +27 -0
- Furious-GUI-0.2.2/Furious/Version.py +1 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/ConnectingProgressBar.py +4 -4
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/EditConfiguration.py +4 -3
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/EditRouting.py +264 -114
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/Widget.py +16 -16
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious_GUI.egg-info/PKG-INFO +17 -1
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/PKG-INFO +17 -1
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/README.md +16 -0
- Furious-GUI-0.2.1/Furious/Version.py +0 -1
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Action/Connect.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Action/EditConfiguration.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Action/Exit.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Action/Export.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Action/Import.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Action/Language.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Action/Settings.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Action/__init__.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Core/Configuration.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Core/Core.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Core/Intellisense.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Core/__init__.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Data/font/CascadiaMono +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Data/font/LICENSE +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Data/hysteria/bypass-Iran.acl +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Data/hysteria/bypass-mainland-China.acl +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Data/hysteria/country.mmdb +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Data/xray/geoip.dat +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Data/xray/geosite.dat +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Data/xray/iran.dat +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Gui/Action.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Gui/Icon.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Gui/__init__.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/Process.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/Proxy.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/Resources.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/Settings.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/StartupOnBoot.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/Theme.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/Utility.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Utility/__init__.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/Application.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/AssetViewer.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/ExportQRCode.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/IndentSpinBox.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/LogViewer.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/SystemTrayIcon.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/Widget/__init__.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/__init__.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious/__main__.py +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious_GUI.egg-info/SOURCES.txt +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious_GUI.egg-info/dependency_links.txt +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious_GUI.egg-info/entry_points.txt +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious_GUI.egg-info/requires.txt +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/Furious_GUI.egg-info/top_level.txt +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/LICENSE +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/setup.cfg +0 -0
- {Furious-GUI-0.2.1 → Furious-GUI-0.2.2}/setup.py +0 -0
|
@@ -46,8 +46,8 @@ BUILTIN_ROUTING_TABLE = {
|
|
|
46
46
|
],
|
|
47
47
|
},
|
|
48
48
|
Hysteria.name(): {
|
|
49
|
-
'acl':
|
|
50
|
-
'mmdb':
|
|
49
|
+
'acl': (DATA_DIR / 'hysteria' / 'bypass-mainland-China.acl').as_posix(),
|
|
50
|
+
'mmdb': (DATA_DIR / 'hysteria' / 'country.mmdb').as_posix(),
|
|
51
51
|
},
|
|
52
52
|
},
|
|
53
53
|
'Bypass Iran': {
|
|
@@ -91,8 +91,8 @@ BUILTIN_ROUTING_TABLE = {
|
|
|
91
91
|
],
|
|
92
92
|
},
|
|
93
93
|
Hysteria.name(): {
|
|
94
|
-
'acl':
|
|
95
|
-
'mmdb':
|
|
94
|
+
'acl': (DATA_DIR / 'hysteria' / 'bypass-Iran.acl').as_posix(),
|
|
95
|
+
'mmdb': (DATA_DIR / 'hysteria' / 'country.mmdb').as_posix(),
|
|
96
96
|
},
|
|
97
97
|
},
|
|
98
98
|
'Global': {
|
|
@@ -702,6 +702,33 @@ TRANSLATION = {
|
|
|
702
702
|
'ZH': '保存路由配置时出错',
|
|
703
703
|
'TW': '保存路由配置時出錯',
|
|
704
704
|
},
|
|
705
|
+
f'Edit {XrayCore.name()} Routing Rules': {
|
|
706
|
+
'ES': f'Editar Reglas de Enrutamiento de {XrayCore.name()}',
|
|
707
|
+
'ZH': f'编辑{XrayCore.name()}路由规则',
|
|
708
|
+
'TW': f'編輯{XrayCore.name()}路由規則',
|
|
709
|
+
},
|
|
710
|
+
f'Edit {Hysteria.name()} Routing Rules': {
|
|
711
|
+
'ES': f'Editar Reglas de Enrutamiento de {Hysteria.name()}',
|
|
712
|
+
'ZH': f'编辑{Hysteria.name()}路由规则',
|
|
713
|
+
'TW': f'編輯{Hysteria.name()}路由規則',
|
|
714
|
+
},
|
|
715
|
+
f'{XrayCore.name()} Routing Rules': {
|
|
716
|
+
'ES': f'Reglas de Enrutamiento de {XrayCore.name()}',
|
|
717
|
+
'ZH': f'{XrayCore.name()}路由规则',
|
|
718
|
+
'TW': f'{XrayCore.name()}路由規則',
|
|
719
|
+
},
|
|
720
|
+
f'Note: If acl is empty or does not exist, {APPLICATION_NAME} '
|
|
721
|
+
f'will fall back to proxy all traffic.': {
|
|
722
|
+
'ES': f'NOTA: Si la ACL está vacía o no existe, '
|
|
723
|
+
f'{APPLICATION_NAME} volverá a utilizar proxy para todo el tráfico.',
|
|
724
|
+
'ZH': f'注意:如果acl为空或不存在,{APPLICATION_NAME}将回落到代理所有流量。',
|
|
725
|
+
'TW': f'注意:如果acl為空或不存在,{APPLICATION_NAME}將回落到代理所有流量。',
|
|
726
|
+
},
|
|
727
|
+
f'Note: "Custom" will use acl and mmdb defined in current user configuration.': {
|
|
728
|
+
'ES': f'NOTA: "Personalizado" utilizará la acl y mmdb definidas en la configuración de usuario actual',
|
|
729
|
+
'ZH': f'注意:"自定义"将使用当前用户配置中定义的acl和mmdb。',
|
|
730
|
+
'TW': f'注意:"自定義"將使用當前用戶配置中定義的acl和mmdb。',
|
|
731
|
+
},
|
|
705
732
|
# Asset Viewer
|
|
706
733
|
'Asset File': {
|
|
707
734
|
'ES': 'Activos',
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.2.2'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from Furious.Utility.Constants import APPLICATION_NAME, GOLDEN_RATIO
|
|
1
|
+
from Furious.Utility.Constants import APPLICATION_NAME, GOLDEN_RATIO, Color
|
|
2
2
|
from Furious.Utility.Utility import (
|
|
3
3
|
bootstrapIcon,
|
|
4
4
|
StateContext,
|
|
@@ -31,7 +31,7 @@ class ConnectingProgressBar(Translatable, SupportConnectedCallback, QWidget):
|
|
|
31
31
|
# Create a progress bar widget
|
|
32
32
|
self.progressBar = QProgressBar(self)
|
|
33
33
|
self.progressBar.setRange(0, 100)
|
|
34
|
-
self.progressBar.setStyleSheet(self.getStyleSheet(
|
|
34
|
+
self.progressBar.setStyleSheet(self.getStyleSheet(Color.LIGHT_BLUE))
|
|
35
35
|
|
|
36
36
|
# create a timer to update the progress bar
|
|
37
37
|
self.timer = QtCore.QTimer(self)
|
|
@@ -64,11 +64,11 @@ class ConnectingProgressBar(Translatable, SupportConnectedCallback, QWidget):
|
|
|
64
64
|
|
|
65
65
|
def connectedCallback(self):
|
|
66
66
|
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
|
|
67
|
-
self.progressBar.setStyleSheet(self.getStyleSheet(
|
|
67
|
+
self.progressBar.setStyleSheet(self.getStyleSheet(Color.LIGHT_RED_))
|
|
68
68
|
|
|
69
69
|
def disconnectedCallback(self):
|
|
70
70
|
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
|
|
71
|
-
self.progressBar.setStyleSheet(self.getStyleSheet(
|
|
71
|
+
self.progressBar.setStyleSheet(self.getStyleSheet(Color.LIGHT_BLUE))
|
|
72
72
|
|
|
73
73
|
def retranslate(self):
|
|
74
74
|
with StateContext(self):
|
|
@@ -24,6 +24,7 @@ from Furious.Utility.Constants import (
|
|
|
24
24
|
APPLICATION_REPO_NAME,
|
|
25
25
|
PLATFORM,
|
|
26
26
|
GOLDEN_RATIO,
|
|
27
|
+
Color,
|
|
27
28
|
)
|
|
28
29
|
from Furious.Utility.Utility import (
|
|
29
30
|
Base64Encoder,
|
|
@@ -1088,7 +1089,7 @@ class NormalServerWidget(Translatable, SupportConnectedCallback, TableWidget):
|
|
|
1088
1089
|
self.setVerticalHeader(NormalServerVerticalHeader(self))
|
|
1089
1090
|
|
|
1090
1091
|
# Selection
|
|
1091
|
-
self.setSelectionColor(
|
|
1092
|
+
self.setSelectionColor(Color.LIGHT_BLUE)
|
|
1092
1093
|
self.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
|
|
1093
1094
|
self.setSelectionMode(QTableWidget.SelectionMode.ExtendedSelection)
|
|
1094
1095
|
|
|
@@ -1591,12 +1592,12 @@ class NormalServerWidget(Translatable, SupportConnectedCallback, TableWidget):
|
|
|
1591
1592
|
super().keyPressEvent(event)
|
|
1592
1593
|
|
|
1593
1594
|
def connectedCallback(self):
|
|
1594
|
-
self.setSelectionColor(
|
|
1595
|
+
self.setSelectionColor(Color.LIGHT_RED_)
|
|
1595
1596
|
# Reactivate with possible color
|
|
1596
1597
|
self.activateItemByIndex(self.activatedItemIndex)
|
|
1597
1598
|
|
|
1598
1599
|
def disconnectedCallback(self):
|
|
1599
|
-
self.setSelectionColor(
|
|
1600
|
+
self.setSelectionColor(Color.LIGHT_BLUE)
|
|
1600
1601
|
# Reactivate with possible color
|
|
1601
1602
|
self.activateItemByIndex(self.activatedItemIndex)
|
|
1602
1603
|
|
|
@@ -25,7 +25,13 @@ from Furious.Widget.EditConfiguration import (
|
|
|
25
25
|
QuestionDeleteBox,
|
|
26
26
|
)
|
|
27
27
|
from Furious.Widget.AssetViewer import AssetViewerWidget
|
|
28
|
-
from Furious.Utility.Constants import
|
|
28
|
+
from Furious.Utility.Constants import (
|
|
29
|
+
APP,
|
|
30
|
+
APPLICATION_NAME,
|
|
31
|
+
GOLDEN_RATIO,
|
|
32
|
+
DATA_DIR,
|
|
33
|
+
Color,
|
|
34
|
+
)
|
|
29
35
|
from Furious.Utility.Utility import (
|
|
30
36
|
RoutesStorage,
|
|
31
37
|
StateContext,
|
|
@@ -50,6 +56,7 @@ from PySide6.QtWidgets import (
|
|
|
50
56
|
QLabel,
|
|
51
57
|
QLineEdit,
|
|
52
58
|
QPlainTextEdit,
|
|
59
|
+
QPushButton,
|
|
53
60
|
QSplitter,
|
|
54
61
|
QStyledItemDelegate,
|
|
55
62
|
QTableWidget,
|
|
@@ -99,28 +106,6 @@ BUILTIN_ROUTING_TEXT = {
|
|
|
99
106
|
ensure_ascii=False,
|
|
100
107
|
escape_forward_slashes=False,
|
|
101
108
|
),
|
|
102
|
-
Hysteria.name(): (
|
|
103
|
-
f'# Hysteria Routing rules\n'
|
|
104
|
-
f'# \n'
|
|
105
|
-
f'# This rule is read-only.\n'
|
|
106
|
-
f'# \n'
|
|
107
|
-
f'# Hysteria will use rule file defined in "acl"\n'
|
|
108
|
-
f'# key and database file defined in "mmdb" key.\n'
|
|
109
|
-
f'# \n'
|
|
110
|
-
f'# "bypass-mainland-China.acl" and "country.mmdb"\n'
|
|
111
|
-
f'# are shipped with {APPLICATION_NAME} by default.\n'
|
|
112
|
-
f'# Their locations are listed below.\n'
|
|
113
|
-
f'# \n'
|
|
114
|
-
f'# See more information:\n'
|
|
115
|
-
f'# \n'
|
|
116
|
-
f'# https://hysteria.network/docs/acl/\n\n'
|
|
117
|
-
)
|
|
118
|
-
+ ujson.dumps(
|
|
119
|
-
BUILTIN_ROUTING_TABLE['Bypass Mainland China'][Hysteria.name()],
|
|
120
|
-
indent=2,
|
|
121
|
-
ensure_ascii=False,
|
|
122
|
-
escape_forward_slashes=False,
|
|
123
|
-
),
|
|
124
109
|
},
|
|
125
110
|
'Bypass Iran': {
|
|
126
111
|
XrayCore.name(): (
|
|
@@ -154,28 +139,6 @@ BUILTIN_ROUTING_TEXT = {
|
|
|
154
139
|
ensure_ascii=False,
|
|
155
140
|
escape_forward_slashes=False,
|
|
156
141
|
),
|
|
157
|
-
Hysteria.name(): (
|
|
158
|
-
f'# Hysteria Routing rules\n'
|
|
159
|
-
f'# \n'
|
|
160
|
-
f'# This rule is read-only.\n'
|
|
161
|
-
f'# \n'
|
|
162
|
-
f'# Hysteria will use rule file defined in "acl"\n'
|
|
163
|
-
f'# key and database file defined in "mmdb" key.\n'
|
|
164
|
-
f'# \n'
|
|
165
|
-
f'# "bypass-Iran.acl" and "country.mmdb" are\n'
|
|
166
|
-
f'# shipped with {APPLICATION_NAME} by default.\n'
|
|
167
|
-
f'# Their locations are listed below.\n'
|
|
168
|
-
f'# \n'
|
|
169
|
-
f'# See more information:\n'
|
|
170
|
-
f'# \n'
|
|
171
|
-
f'# https://hysteria.network/docs/acl/\n\n'
|
|
172
|
-
)
|
|
173
|
-
+ ujson.dumps(
|
|
174
|
-
BUILTIN_ROUTING_TABLE['Bypass Iran'][Hysteria.name()],
|
|
175
|
-
indent=2,
|
|
176
|
-
ensure_ascii=False,
|
|
177
|
-
escape_forward_slashes=False,
|
|
178
|
-
),
|
|
179
142
|
},
|
|
180
143
|
'Global': {
|
|
181
144
|
XrayCore.name(): (
|
|
@@ -201,20 +164,6 @@ BUILTIN_ROUTING_TEXT = {
|
|
|
201
164
|
ensure_ascii=False,
|
|
202
165
|
escape_forward_slashes=False,
|
|
203
166
|
),
|
|
204
|
-
Hysteria.name(): (
|
|
205
|
-
f'# Hysteria Routing rules\n'
|
|
206
|
-
f'# \n'
|
|
207
|
-
f'# This rule is read-only.\n'
|
|
208
|
-
f'# \n'
|
|
209
|
-
f'# If no rule file or mmdb file is provided, {APPLICATION_NAME}\n'
|
|
210
|
-
f'# will fall back to proxy all traffic.\n\n'
|
|
211
|
-
)
|
|
212
|
-
+ ujson.dumps(
|
|
213
|
-
BUILTIN_ROUTING_TABLE['Global'][Hysteria.name()],
|
|
214
|
-
indent=2,
|
|
215
|
-
ensure_ascii=False,
|
|
216
|
-
escape_forward_slashes=False,
|
|
217
|
-
),
|
|
218
167
|
},
|
|
219
168
|
'Custom': {
|
|
220
169
|
XrayCore.name(): (
|
|
@@ -225,13 +174,26 @@ BUILTIN_ROUTING_TEXT = {
|
|
|
225
174
|
f'# "Custom" will use RoutingObject defined\n'
|
|
226
175
|
f'# in current user configuration.\n\n'
|
|
227
176
|
),
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
ROUTING_HINT = {
|
|
182
|
+
'Bypass Mainland China': {
|
|
183
|
+
XrayCore.name(): '',
|
|
184
|
+
},
|
|
185
|
+
'Bypass Iran': {
|
|
186
|
+
XrayCore.name(): '',
|
|
187
|
+
},
|
|
188
|
+
'Global': {
|
|
189
|
+
XrayCore.name(): (
|
|
190
|
+
f'Note: If acl is empty or does not exist, {APPLICATION_NAME} '
|
|
191
|
+
f'will fall back to proxy all traffic.'
|
|
192
|
+
),
|
|
193
|
+
},
|
|
194
|
+
'Custom': {
|
|
195
|
+
XrayCore.name(): (
|
|
196
|
+
f'Note: "Custom" will use acl and mmdb defined in current user configuration.'
|
|
235
197
|
),
|
|
236
198
|
},
|
|
237
199
|
}
|
|
@@ -252,7 +214,7 @@ DEFAULT_USER_ROUTING = {
|
|
|
252
214
|
},
|
|
253
215
|
Hysteria.name(): {
|
|
254
216
|
'acl': '',
|
|
255
|
-
'mmdb':
|
|
217
|
+
'mmdb': (DATA_DIR / 'hysteria' / 'country.mmdb').as_posix(),
|
|
256
218
|
},
|
|
257
219
|
}
|
|
258
220
|
|
|
@@ -276,30 +238,6 @@ USER_ROUTING_TEXT = {
|
|
|
276
238
|
ensure_ascii=False,
|
|
277
239
|
escape_forward_slashes=False,
|
|
278
240
|
),
|
|
279
|
-
Hysteria.name(): (
|
|
280
|
-
f'# Hysteria Routing rules\n'
|
|
281
|
-
f'# \n'
|
|
282
|
-
f'# Define your own routing rules here.\n'
|
|
283
|
-
f'# A built-in mmdb filepath is defined\n'
|
|
284
|
-
f'# for convenience.\n'
|
|
285
|
-
f'# \n'
|
|
286
|
-
f'# Need any help? You can check those built-in\n'
|
|
287
|
-
f'# routing rules shipped with {APPLICATION_NAME} first.\n'
|
|
288
|
-
f'# \n'
|
|
289
|
-
f'# Note: JSON does not support comments. Any\n'
|
|
290
|
-
f'# lines starting with "#" will be discarded\n'
|
|
291
|
-
f'# by {APPLICATION_NAME} forever.\n'
|
|
292
|
-
f'# \n'
|
|
293
|
-
f'# Note: If any one of filepath is given but\n'
|
|
294
|
-
f'# does not exist, {APPLICATION_NAME} will fall back to\n'
|
|
295
|
-
f'# proxy all traffic.\n\n'
|
|
296
|
-
)
|
|
297
|
-
+ ujson.dumps(
|
|
298
|
-
DEFAULT_USER_ROUTING[Hysteria.name()],
|
|
299
|
-
indent=2,
|
|
300
|
-
ensure_ascii=False,
|
|
301
|
-
escape_forward_slashes=False,
|
|
302
|
-
),
|
|
303
241
|
}
|
|
304
242
|
|
|
305
243
|
|
|
@@ -477,6 +415,65 @@ class ZoomOutAction(Action):
|
|
|
477
415
|
editor.zoomOut()
|
|
478
416
|
|
|
479
417
|
|
|
418
|
+
class EditRoutingAction(Action):
|
|
419
|
+
def __init__(self, *args, **kwargs):
|
|
420
|
+
super().__init__(*args, **kwargs)
|
|
421
|
+
|
|
422
|
+
self.saveConfInfo = SaveConfInfo(icon=MessageBox.Icon.Information)
|
|
423
|
+
|
|
424
|
+
self.RoutesList = self.parent().RoutesList
|
|
425
|
+
|
|
426
|
+
self.routingEditorRef = self.parent().routingEditorRef
|
|
427
|
+
self.routingDialogRef = self.parent().routingDialogRef
|
|
428
|
+
|
|
429
|
+
def triggeredCallback(self, checked):
|
|
430
|
+
if self.textCompare(f'Edit {XrayCore.name()} Routing Rules'):
|
|
431
|
+
for index in self.parent().selectedIndex:
|
|
432
|
+
self.routingEditorRef[index].show()
|
|
433
|
+
|
|
434
|
+
if self.textCompare(f'Edit {Hysteria.name()} Routing Rules'):
|
|
435
|
+
for index in self.parent().selectedIndex:
|
|
436
|
+
dialog = self.routingDialogRef[index]
|
|
437
|
+
choice = dialog.exec()
|
|
438
|
+
|
|
439
|
+
if dialog.isBuiltin:
|
|
440
|
+
# Built-in. Nothing to do
|
|
441
|
+
logger.info(
|
|
442
|
+
f'built-in routing dialog {BUILTIN_ROUTING[index]} called exec. Nothing to do'
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
continue
|
|
446
|
+
|
|
447
|
+
assert index >= len(BUILTIN_ROUTING)
|
|
448
|
+
|
|
449
|
+
parentIndex = index - len(BUILTIN_ROUTING)
|
|
450
|
+
|
|
451
|
+
if choice == QDialog.DialogCode.Accepted.value:
|
|
452
|
+
ruleValue = dialog.ruleValue()
|
|
453
|
+
mmdbValue = dialog.mmdbValue()
|
|
454
|
+
|
|
455
|
+
self.RoutesList[parentIndex][Hysteria.name()] = {
|
|
456
|
+
'acl': ruleValue,
|
|
457
|
+
'mmdb': mmdbValue,
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
# Sync it
|
|
461
|
+
RoutesStorage.sync()
|
|
462
|
+
|
|
463
|
+
if parentIndex == routingToIndex() - len(BUILTIN_ROUTING):
|
|
464
|
+
# Activated routing modified
|
|
465
|
+
|
|
466
|
+
if APP().tray.ConnectAction.isConnected():
|
|
467
|
+
questionFastReconnect(self.saveConfInfo)
|
|
468
|
+
else:
|
|
469
|
+
# Restore
|
|
470
|
+
|
|
471
|
+
routingObject = self.RoutesList[parentIndex][Hysteria.name()]
|
|
472
|
+
|
|
473
|
+
dialog.setRuleValue(routingObject.get('acl', ''))
|
|
474
|
+
dialog.setMmdbValue(routingObject.get('mmdb', ''))
|
|
475
|
+
|
|
476
|
+
|
|
480
477
|
class RoutingTextBrowser(ZoomableTextBrowser):
|
|
481
478
|
def __init__(self, *args, **kwargs):
|
|
482
479
|
super().__init__(*args, **kwargs)
|
|
@@ -522,8 +519,7 @@ class RoutingEditor(MainWindow):
|
|
|
522
519
|
super().__init__(*args, **kwargs)
|
|
523
520
|
|
|
524
521
|
self.isBuiltin = isBuiltin
|
|
525
|
-
|
|
526
|
-
self.setWindowTitle(_('Edit Routing'))
|
|
522
|
+
self.title = ''
|
|
527
523
|
|
|
528
524
|
if APP().tray is not None and APP().tray.ConnectAction.isConnected():
|
|
529
525
|
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
|
|
@@ -535,8 +531,6 @@ class RoutingEditor(MainWindow):
|
|
|
535
531
|
icon=MessageBox.Icon.Question, parent=self
|
|
536
532
|
)
|
|
537
533
|
|
|
538
|
-
self.title = ''
|
|
539
|
-
|
|
540
534
|
# Modified flag
|
|
541
535
|
self.modified = False
|
|
542
536
|
self.modifiedMark = ' *'
|
|
@@ -619,7 +613,7 @@ class RoutingEditor(MainWindow):
|
|
|
619
613
|
|
|
620
614
|
self.editorRef.append(editor)
|
|
621
615
|
self.editorLastSavedText.append(text)
|
|
622
|
-
self.editorTab.addTab(editor, core)
|
|
616
|
+
self.editorTab.addTab(editor, _(f'{core} Routing Rules'))
|
|
623
617
|
|
|
624
618
|
def markAsModified(self):
|
|
625
619
|
# Built-in is read-only. Should not be modified
|
|
@@ -678,6 +672,116 @@ class RoutingEditor(MainWindow):
|
|
|
678
672
|
self.setWindowTitle(_(self.windowTitle()))
|
|
679
673
|
|
|
680
674
|
|
|
675
|
+
class RoutingDialog(Translatable, SupportConnectedCallback, QDialog):
|
|
676
|
+
def __init__(self, isBuiltin, hint='', *args, **kwargs):
|
|
677
|
+
super().__init__(*args, **kwargs)
|
|
678
|
+
|
|
679
|
+
self.isBuiltin = isBuiltin
|
|
680
|
+
|
|
681
|
+
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
|
|
682
|
+
|
|
683
|
+
self.ruleText = QLabel(f'{Hysteria.name()} acl:')
|
|
684
|
+
|
|
685
|
+
self.ruleEdit = QLineEdit()
|
|
686
|
+
self.ruleEdit.setFixedWidth(500)
|
|
687
|
+
|
|
688
|
+
self.ruleFile = QPushButton('...')
|
|
689
|
+
self.ruleFile.setFixedWidth(30)
|
|
690
|
+
|
|
691
|
+
self.ruleHBox = QHBoxLayout()
|
|
692
|
+
self.ruleHBox.addWidget(self.ruleEdit)
|
|
693
|
+
self.ruleHBox.addWidget(self.ruleFile)
|
|
694
|
+
|
|
695
|
+
self.mmdbText = QLabel(f'{Hysteria.name()} mmdb:')
|
|
696
|
+
|
|
697
|
+
self.mmdbEdit = QLineEdit()
|
|
698
|
+
self.mmdbEdit.setFixedWidth(500)
|
|
699
|
+
|
|
700
|
+
self.mmdbFile = QPushButton('...')
|
|
701
|
+
self.mmdbFile.setFixedWidth(30)
|
|
702
|
+
|
|
703
|
+
self.mmdbHBox = QHBoxLayout()
|
|
704
|
+
self.mmdbHBox.addWidget(self.mmdbEdit)
|
|
705
|
+
self.mmdbHBox.addWidget(self.mmdbFile)
|
|
706
|
+
|
|
707
|
+
self.ruleFile.clicked.connect(self.handleRuleFileClicked)
|
|
708
|
+
self.mmdbFile.clicked.connect(self.handleMmdbFileClicked)
|
|
709
|
+
|
|
710
|
+
if self.isBuiltin:
|
|
711
|
+
self.ruleEdit.setReadOnly(True)
|
|
712
|
+
self.mmdbEdit.setReadOnly(True)
|
|
713
|
+
|
|
714
|
+
self.dialogBtns = QDialogButtonBox(QtCore.Qt.Orientation.Horizontal)
|
|
715
|
+
|
|
716
|
+
self.dialogBtns.addButton(_('OK'), QDialogButtonBox.ButtonRole.AcceptRole)
|
|
717
|
+
self.dialogBtns.addButton(_('Cancel'), QDialogButtonBox.ButtonRole.RejectRole)
|
|
718
|
+
self.dialogBtns.accepted.connect(self.accept)
|
|
719
|
+
self.dialogBtns.rejected.connect(self.reject)
|
|
720
|
+
|
|
721
|
+
layout = QFormLayout()
|
|
722
|
+
|
|
723
|
+
if hint:
|
|
724
|
+
self.hint = QLabel(hint)
|
|
725
|
+
|
|
726
|
+
layout.addRow(self.hint)
|
|
727
|
+
else:
|
|
728
|
+
self.hint = None
|
|
729
|
+
|
|
730
|
+
layout.addRow(self.ruleText, self.ruleHBox)
|
|
731
|
+
layout.addRow(self.mmdbText, self.mmdbHBox)
|
|
732
|
+
layout.addRow(self.dialogBtns)
|
|
733
|
+
layout.setFormAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
|
734
|
+
|
|
735
|
+
self.setLayout(layout)
|
|
736
|
+
|
|
737
|
+
@QtCore.Slot()
|
|
738
|
+
def handleRuleFileClicked(self):
|
|
739
|
+
filename, selectedFilter = QFileDialog.getOpenFileName(
|
|
740
|
+
self.parent(), _('Import File'), filter=_('All files (*)')
|
|
741
|
+
)
|
|
742
|
+
|
|
743
|
+
if not self.isBuiltin and filename:
|
|
744
|
+
self.ruleEdit.setText(filename)
|
|
745
|
+
|
|
746
|
+
@QtCore.Slot()
|
|
747
|
+
def handleMmdbFileClicked(self):
|
|
748
|
+
filename, selectedFilter = QFileDialog.getOpenFileName(
|
|
749
|
+
self.parent(), _('Import File'), filter=_('All files (*)')
|
|
750
|
+
)
|
|
751
|
+
|
|
752
|
+
if not self.isBuiltin and filename:
|
|
753
|
+
self.mmdbEdit.setText(filename)
|
|
754
|
+
|
|
755
|
+
def setRuleValue(self, text):
|
|
756
|
+
self.ruleEdit.setText(text)
|
|
757
|
+
|
|
758
|
+
def setMmdbValue(self, text):
|
|
759
|
+
self.mmdbEdit.setText(text)
|
|
760
|
+
|
|
761
|
+
def ruleValue(self):
|
|
762
|
+
return self.ruleEdit.text()
|
|
763
|
+
|
|
764
|
+
def mmdbValue(self):
|
|
765
|
+
return self.mmdbEdit.text()
|
|
766
|
+
|
|
767
|
+
def connectedCallback(self):
|
|
768
|
+
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
|
|
769
|
+
|
|
770
|
+
def disconnectedCallback(self):
|
|
771
|
+
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
|
|
772
|
+
|
|
773
|
+
def retranslate(self):
|
|
774
|
+
with StateContext(self):
|
|
775
|
+
if self.isBuiltin:
|
|
776
|
+
self.setWindowTitle(_(self.windowTitle()))
|
|
777
|
+
|
|
778
|
+
if self.hint is not None:
|
|
779
|
+
self.hint.setText(_(self.hint.text()))
|
|
780
|
+
|
|
781
|
+
for button in self.dialogBtns.buttons():
|
|
782
|
+
button.setText(_(button.text()))
|
|
783
|
+
|
|
784
|
+
|
|
681
785
|
class EditRoutingTableHorizontalHeader(HeaderView):
|
|
682
786
|
def __init__(self, *args, **kwargs):
|
|
683
787
|
super().__init__(QtCore.Qt.Orientation.Horizontal, *args, **kwargs)
|
|
@@ -725,7 +829,10 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
|
|
|
725
829
|
# Handy reference
|
|
726
830
|
self.RoutesList = self.editRoutingWidget.RoutesList
|
|
727
831
|
|
|
832
|
+
# Currently only has Xray-Core
|
|
728
833
|
self.routingEditorRef = []
|
|
834
|
+
# Currently only has Hysteria
|
|
835
|
+
self.routingDialogRef = []
|
|
729
836
|
|
|
730
837
|
# Column count
|
|
731
838
|
self.setColumnCount(len(EditRoutingTableWidget.HEADER_LABEL))
|
|
@@ -784,7 +891,7 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
|
|
|
784
891
|
self.setVerticalHeader(EditRoutingTableVerticalHeader(self))
|
|
785
892
|
|
|
786
893
|
# Selection
|
|
787
|
-
self.setSelectionColor(
|
|
894
|
+
self.setSelectionColor(Color.LIGHT_BLUE)
|
|
788
895
|
self.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
|
|
789
896
|
self.setSelectionMode(QTableWidget.SelectionMode.ExtendedSelection)
|
|
790
897
|
|
|
@@ -794,25 +901,44 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
|
|
|
794
901
|
self.setDropIndicatorShown(False)
|
|
795
902
|
self.setDefaultDropAction(QtCore.Qt.DropAction.IgnoreAction)
|
|
796
903
|
|
|
904
|
+
contextMenuActions = [
|
|
905
|
+
EditRoutingAction(_(f'Edit {XrayCore.name()} Routing Rules'), parent=self),
|
|
906
|
+
EditRoutingAction(_(f'Edit {Hysteria.name()} Routing Rules'), parent=self),
|
|
907
|
+
]
|
|
908
|
+
|
|
909
|
+
self.contextMenu = Menu(*contextMenuActions)
|
|
910
|
+
self.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
|
|
911
|
+
|
|
797
912
|
# Signals
|
|
798
|
-
self.
|
|
913
|
+
self.customContextMenuRequested.connect(self.handleCustomContextMenuRequested)
|
|
799
914
|
|
|
800
915
|
def initTableFromData(self):
|
|
801
|
-
for row in
|
|
916
|
+
for row, routing in enumerate(BUILTIN_ROUTING):
|
|
802
917
|
self.appendDataByColumn(
|
|
803
918
|
lambda column: EditRoutingTableWidget.BUILTIN_ITEM_GET_FUNC[column](row)
|
|
804
919
|
)
|
|
805
920
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
)
|
|
921
|
+
text = self.item(row, 0).text()
|
|
922
|
+
|
|
923
|
+
routingEditor = self.appendRoutingEditor(text, isBuiltin=True)
|
|
809
924
|
|
|
810
|
-
for core in [XrayCore.name()
|
|
925
|
+
for core in [XrayCore.name()]:
|
|
811
926
|
routingEditor.addTabWithData(
|
|
812
927
|
core,
|
|
813
928
|
BUILTIN_ROUTING_TEXT[BUILTIN_ROUTING[row]][core],
|
|
814
929
|
)
|
|
815
930
|
|
|
931
|
+
routingDialog = self.appendRoutingDialog(
|
|
932
|
+
text, hint=_(ROUTING_HINT[routing][XrayCore.name()]), isBuiltin=True
|
|
933
|
+
)
|
|
934
|
+
|
|
935
|
+
routingDialog.ruleEdit.setText(
|
|
936
|
+
BUILTIN_ROUTING_TABLE[routing][Hysteria.name()].get('acl', '')
|
|
937
|
+
)
|
|
938
|
+
routingDialog.mmdbEdit.setText(
|
|
939
|
+
BUILTIN_ROUTING_TABLE[routing][Hysteria.name()].get('mmdb', '')
|
|
940
|
+
)
|
|
941
|
+
|
|
816
942
|
for row in range(
|
|
817
943
|
len(BUILTIN_ROUTING),
|
|
818
944
|
len(BUILTIN_ROUTING) + len(self.RoutesList),
|
|
@@ -825,11 +951,11 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
|
|
|
825
951
|
lambda column: EditRoutingTableWidget.USER_ITEM_GET_FUNC[column](remark)
|
|
826
952
|
)
|
|
827
953
|
|
|
828
|
-
|
|
829
|
-
self.item(row, 0).text(), isBuiltin=False
|
|
830
|
-
)
|
|
954
|
+
text = self.item(row, 0).text()
|
|
831
955
|
|
|
832
|
-
|
|
956
|
+
routingEditor = self.appendRoutingEditor(text, isBuiltin=False)
|
|
957
|
+
|
|
958
|
+
for core in [XrayCore.name()]:
|
|
833
959
|
routingEditor.addTabWithData(
|
|
834
960
|
core,
|
|
835
961
|
ujson.dumps(
|
|
@@ -840,9 +966,18 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
|
|
|
840
966
|
),
|
|
841
967
|
)
|
|
842
968
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
969
|
+
routingDialog = self.appendRoutingDialog(text, isBuiltin=False)
|
|
970
|
+
|
|
971
|
+
routingDialog.ruleEdit.setText(
|
|
972
|
+
self.RoutesList[routesIndex][Hysteria.name()].get('acl', '')
|
|
973
|
+
)
|
|
974
|
+
routingDialog.mmdbEdit.setText(
|
|
975
|
+
self.RoutesList[routesIndex][Hysteria.name()].get('mmdb', '')
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
@QtCore.Slot(QtCore.QPoint)
|
|
979
|
+
def handleCustomContextMenuRequested(self, point):
|
|
980
|
+
self.contextMenu.exec(self.mapToGlobal(point))
|
|
846
981
|
|
|
847
982
|
def appendRoutingEditor(self, title, isBuiltin=False):
|
|
848
983
|
routingEditor = RoutingEditor(isBuiltin)
|
|
@@ -856,6 +991,14 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
|
|
|
856
991
|
|
|
857
992
|
return routingEditor
|
|
858
993
|
|
|
994
|
+
def appendRoutingDialog(self, title, hint='', isBuiltin=False):
|
|
995
|
+
routingDialog = RoutingDialog(isBuiltin, hint)
|
|
996
|
+
routingDialog.setWindowTitle(title)
|
|
997
|
+
|
|
998
|
+
self.routingDialogRef.append(routingDialog)
|
|
999
|
+
|
|
1000
|
+
return routingDialog
|
|
1001
|
+
|
|
859
1002
|
def deleteSelectedItem(self):
|
|
860
1003
|
# Builtin routing cannot be deleted
|
|
861
1004
|
indexes = list(filter(lambda x: x >= len(BUILTIN_ROUTING), self.selectedIndex))
|
|
@@ -890,6 +1033,7 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
|
|
|
890
1033
|
|
|
891
1034
|
self.removeRow(takedRow)
|
|
892
1035
|
self.routingEditorRef.pop(takedRow)
|
|
1036
|
+
self.routingDialogRef.pop(takedRow)
|
|
893
1037
|
self.RoutesList.pop(takedRow - len(BUILTIN_ROUTING))
|
|
894
1038
|
|
|
895
1039
|
# Remove entry from routing menu
|
|
@@ -927,12 +1071,12 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
|
|
|
927
1071
|
self.setItem(row, column, item)
|
|
928
1072
|
|
|
929
1073
|
def connectedCallback(self):
|
|
930
|
-
self.setSelectionColor(
|
|
1074
|
+
self.setSelectionColor(Color.LIGHT_RED_)
|
|
931
1075
|
# Reactivate with possible color
|
|
932
1076
|
self.activateItemByIndex(routingToIndex(), activate=True)
|
|
933
1077
|
|
|
934
1078
|
def disconnectedCallback(self):
|
|
935
|
-
self.setSelectionColor(
|
|
1079
|
+
self.setSelectionColor(Color.LIGHT_BLUE)
|
|
936
1080
|
# Reactivate with possible color
|
|
937
1081
|
self.activateItemByIndex(routingToIndex(), activate=True)
|
|
938
1082
|
|
|
@@ -1096,12 +1240,19 @@ class EditRoutingWidget(MainWindow):
|
|
|
1096
1240
|
routingRemark, isBuiltin=False
|
|
1097
1241
|
)
|
|
1098
1242
|
|
|
1099
|
-
for core in [XrayCore.name()
|
|
1243
|
+
for core in [XrayCore.name()]:
|
|
1100
1244
|
routingEditor.addTabWithData(
|
|
1101
1245
|
core,
|
|
1102
1246
|
USER_ROUTING_TEXT[core],
|
|
1103
1247
|
)
|
|
1104
1248
|
|
|
1249
|
+
routingDialog = self.editRoutingTableWidget.appendRoutingDialog(
|
|
1250
|
+
routingRemark, isBuiltin=False
|
|
1251
|
+
)
|
|
1252
|
+
routingDialog.mmdbEdit.setText(
|
|
1253
|
+
(DATA_DIR / 'hysteria' / 'country.mmdb').as_posix()
|
|
1254
|
+
)
|
|
1255
|
+
|
|
1105
1256
|
self.RoutesList.append(
|
|
1106
1257
|
{'remark': routingRemark, **DEFAULT_USER_ROUTING}
|
|
1107
1258
|
)
|
|
@@ -1114,7 +1265,6 @@ class EditRoutingWidget(MainWindow):
|
|
|
1114
1265
|
routingAction.addAction(
|
|
1115
1266
|
RoutingChildAction(routingRemark, checkable=True, checked=False)
|
|
1116
1267
|
)
|
|
1117
|
-
|
|
1118
1268
|
else:
|
|
1119
1269
|
# Do nothing
|
|
1120
1270
|
pass
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from Furious.Gui.Action import Action, Seperator
|
|
2
|
-
from Furious.Utility.Constants import APP
|
|
2
|
+
from Furious.Utility.Constants import APP, Color
|
|
3
3
|
from Furious.Utility.Utility import (
|
|
4
4
|
StateContext,
|
|
5
5
|
SupportConnectedCallback,
|
|
@@ -36,17 +36,17 @@ class HeaderView(SupportConnectedCallback, QHeaderView):
|
|
|
36
36
|
self.setSectionsClickable(True)
|
|
37
37
|
|
|
38
38
|
self.setStyleSheet(
|
|
39
|
-
f'QHeaderView::section:hover {{ background-color:
|
|
39
|
+
f'QHeaderView::section:hover {{ background-color: {Color.LIGHT_BLUE}; }}'
|
|
40
40
|
)
|
|
41
41
|
|
|
42
42
|
def connectedCallback(self):
|
|
43
43
|
self.setStyleSheet(
|
|
44
|
-
f'QHeaderView::section:hover {{ background-color:
|
|
44
|
+
f'QHeaderView::section:hover {{ background-color: {Color.LIGHT_RED_}; }}'
|
|
45
45
|
)
|
|
46
46
|
|
|
47
47
|
def disconnectedCallback(self):
|
|
48
48
|
self.setStyleSheet(
|
|
49
|
-
f'QHeaderView::section:hover {{ background-color:
|
|
49
|
+
f'QHeaderView::section:hover {{ background-color: {Color.LIGHT_BLUE}; }}'
|
|
50
50
|
)
|
|
51
51
|
|
|
52
52
|
|
|
@@ -54,7 +54,7 @@ class ListWidget(SupportConnectedCallback, QListWidget):
|
|
|
54
54
|
def __init__(self, *args, **kwargs):
|
|
55
55
|
super().__init__(*args, **kwargs)
|
|
56
56
|
|
|
57
|
-
self.setSelectionColor(
|
|
57
|
+
self.setSelectionColor(Color.LIGHT_BLUE)
|
|
58
58
|
|
|
59
59
|
def setSelectionColor(self, color):
|
|
60
60
|
self.setStyleSheet(
|
|
@@ -72,10 +72,10 @@ class ListWidget(SupportConnectedCallback, QListWidget):
|
|
|
72
72
|
return sorted(list(set(index.row() for index in self.selectedIndexes())))
|
|
73
73
|
|
|
74
74
|
def connectedCallback(self):
|
|
75
|
-
self.setSelectionColor(
|
|
75
|
+
self.setSelectionColor(Color.LIGHT_RED_)
|
|
76
76
|
|
|
77
77
|
def disconnectedCallback(self):
|
|
78
|
-
self.setSelectionColor(
|
|
78
|
+
self.setSelectionColor(Color.LIGHT_BLUE)
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
class MainWindow(Translatable, SupportConnectedCallback, NeedSyncSettings, QMainWindow):
|
|
@@ -118,7 +118,7 @@ class Menu(Translatable, SupportConnectedCallback, QMenu):
|
|
|
118
118
|
|
|
119
119
|
self.addAction(action)
|
|
120
120
|
|
|
121
|
-
self.setStyleSheet(self.getStyleSheet(
|
|
121
|
+
self.setStyleSheet(self.getStyleSheet(Color.LIGHT_BLUE))
|
|
122
122
|
|
|
123
123
|
@staticmethod
|
|
124
124
|
def getStyleSheet(color):
|
|
@@ -133,10 +133,10 @@ class Menu(Translatable, SupportConnectedCallback, QMenu):
|
|
|
133
133
|
)
|
|
134
134
|
|
|
135
135
|
def connectedCallback(self):
|
|
136
|
-
self.setStyleSheet(self.getStyleSheet(
|
|
136
|
+
self.setStyleSheet(self.getStyleSheet(Color.LIGHT_RED_))
|
|
137
137
|
|
|
138
138
|
def disconnectedCallback(self):
|
|
139
|
-
self.setStyleSheet(self.getStyleSheet(
|
|
139
|
+
self.setStyleSheet(self.getStyleSheet(Color.LIGHT_BLUE))
|
|
140
140
|
|
|
141
141
|
def retranslate(self):
|
|
142
142
|
with StateContext(self):
|
|
@@ -147,7 +147,7 @@ class MenuBar(SupportConnectedCallback, QMenuBar):
|
|
|
147
147
|
def __init__(self, *args, **kwargs):
|
|
148
148
|
super().__init__(*args, **kwargs)
|
|
149
149
|
|
|
150
|
-
self.setSelectionColor(
|
|
150
|
+
self.setSelectionColor(Color.LIGHT_BLUE)
|
|
151
151
|
|
|
152
152
|
def setSelectionColor(self, color):
|
|
153
153
|
self.setStyleSheet(
|
|
@@ -161,10 +161,10 @@ class MenuBar(SupportConnectedCallback, QMenuBar):
|
|
|
161
161
|
)
|
|
162
162
|
|
|
163
163
|
def connectedCallback(self):
|
|
164
|
-
self.setSelectionColor(
|
|
164
|
+
self.setSelectionColor(Color.LIGHT_RED_)
|
|
165
165
|
|
|
166
166
|
def disconnectedCallback(self):
|
|
167
|
-
self.setSelectionColor(
|
|
167
|
+
self.setSelectionColor(Color.LIGHT_BLUE)
|
|
168
168
|
|
|
169
169
|
|
|
170
170
|
class MessageBox(Translatable, SupportConnectedCallback, QMessageBox):
|
|
@@ -263,12 +263,12 @@ class TableWidget(QTableWidget):
|
|
|
263
263
|
|
|
264
264
|
if APP().tray is None:
|
|
265
265
|
# Initializing
|
|
266
|
-
item.setForeground(QColor(
|
|
266
|
+
item.setForeground(QColor(Color.LIGHT_BLUE))
|
|
267
267
|
else:
|
|
268
268
|
if APP().tray.ConnectAction.isConnected():
|
|
269
|
-
item.setForeground(QColor(
|
|
269
|
+
item.setForeground(QColor(Color.LIGHT_RED_))
|
|
270
270
|
else:
|
|
271
|
-
item.setForeground(QColor(
|
|
271
|
+
item.setForeground(QColor(Color.LIGHT_BLUE))
|
|
272
272
|
else:
|
|
273
273
|
for column in range(self.columnCount()):
|
|
274
274
|
item = self.item(int(index), column)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: Furious-GUI
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A PySide6-based cross platform GUI client that launches your beloved GFW to outer space.
|
|
5
5
|
Home-page: https://github.com/LorenEteval/Furious
|
|
6
6
|
Author: Loren Eteval
|
|
@@ -23,6 +23,8 @@ License-File: LICENSE
|
|
|
23
23
|
|
|
24
24
|
# Furious
|
|
25
25
|
|
|
26
|
+
[](https://github.com/LorenEteval/Furious/actions/workflows/wheels.yml)
|
|
27
|
+
|
|
26
28
|
A PySide6-based cross platform GUI client that launches your beloved GFW to outer space.
|
|
27
29
|
Support [Xray-core](https://github.com/XTLS/Xray-core)
|
|
28
30
|
and [hysteria](https://github.com/apernet/hysteria).
|
|
@@ -137,6 +139,20 @@ python -m Furious
|
|
|
137
139
|
|
|
138
140
|
> Note: Furious will ignore current startup on boot request if it's lauched from source.
|
|
139
141
|
|
|
142
|
+
## Build Status
|
|
143
|
+
|
|
144
|
+
See the build result in [github actions](https://github.com/LorenEteval/Furious/actions).
|
|
145
|
+
|
|
146
|
+
| Platform | Python 3.8-Python 3.11 |
|
|
147
|
+
|--------------|:----------------------:|
|
|
148
|
+
| ubuntu 20.04 | :heavy_check_mark: |
|
|
149
|
+
| ubuntu 22.04 | :heavy_check_mark: |
|
|
150
|
+
| windows-2019 | :heavy_check_mark: |
|
|
151
|
+
| windows-2022 | :heavy_check_mark: |
|
|
152
|
+
| macos-11 | :heavy_check_mark: |
|
|
153
|
+
| macos-12 | :heavy_check_mark: |
|
|
154
|
+
| macos-13 | :heavy_check_mark: |
|
|
155
|
+
|
|
140
156
|
## Core Installation Script
|
|
141
157
|
|
|
142
158
|
Below are some one-click/automatic installation script that's been tested to work in Furious.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: Furious-GUI
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A PySide6-based cross platform GUI client that launches your beloved GFW to outer space.
|
|
5
5
|
Home-page: https://github.com/LorenEteval/Furious
|
|
6
6
|
Author: Loren Eteval
|
|
@@ -23,6 +23,8 @@ License-File: LICENSE
|
|
|
23
23
|
|
|
24
24
|
# Furious
|
|
25
25
|
|
|
26
|
+
[](https://github.com/LorenEteval/Furious/actions/workflows/wheels.yml)
|
|
27
|
+
|
|
26
28
|
A PySide6-based cross platform GUI client that launches your beloved GFW to outer space.
|
|
27
29
|
Support [Xray-core](https://github.com/XTLS/Xray-core)
|
|
28
30
|
and [hysteria](https://github.com/apernet/hysteria).
|
|
@@ -137,6 +139,20 @@ python -m Furious
|
|
|
137
139
|
|
|
138
140
|
> Note: Furious will ignore current startup on boot request if it's lauched from source.
|
|
139
141
|
|
|
142
|
+
## Build Status
|
|
143
|
+
|
|
144
|
+
See the build result in [github actions](https://github.com/LorenEteval/Furious/actions).
|
|
145
|
+
|
|
146
|
+
| Platform | Python 3.8-Python 3.11 |
|
|
147
|
+
|--------------|:----------------------:|
|
|
148
|
+
| ubuntu 20.04 | :heavy_check_mark: |
|
|
149
|
+
| ubuntu 22.04 | :heavy_check_mark: |
|
|
150
|
+
| windows-2019 | :heavy_check_mark: |
|
|
151
|
+
| windows-2022 | :heavy_check_mark: |
|
|
152
|
+
| macos-11 | :heavy_check_mark: |
|
|
153
|
+
| macos-12 | :heavy_check_mark: |
|
|
154
|
+
| macos-13 | :heavy_check_mark: |
|
|
155
|
+
|
|
140
156
|
## Core Installation Script
|
|
141
157
|
|
|
142
158
|
Below are some one-click/automatic installation script that's been tested to work in Furious.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Furious
|
|
2
2
|
|
|
3
|
+
[](https://github.com/LorenEteval/Furious/actions/workflows/wheels.yml)
|
|
4
|
+
|
|
3
5
|
A PySide6-based cross platform GUI client that launches your beloved GFW to outer space.
|
|
4
6
|
Support [Xray-core](https://github.com/XTLS/Xray-core)
|
|
5
7
|
and [hysteria](https://github.com/apernet/hysteria).
|
|
@@ -114,6 +116,20 @@ python -m Furious
|
|
|
114
116
|
|
|
115
117
|
> Note: Furious will ignore current startup on boot request if it's lauched from source.
|
|
116
118
|
|
|
119
|
+
## Build Status
|
|
120
|
+
|
|
121
|
+
See the build result in [github actions](https://github.com/LorenEteval/Furious/actions).
|
|
122
|
+
|
|
123
|
+
| Platform | Python 3.8-Python 3.11 |
|
|
124
|
+
|--------------|:----------------------:|
|
|
125
|
+
| ubuntu 20.04 | :heavy_check_mark: |
|
|
126
|
+
| ubuntu 22.04 | :heavy_check_mark: |
|
|
127
|
+
| windows-2019 | :heavy_check_mark: |
|
|
128
|
+
| windows-2022 | :heavy_check_mark: |
|
|
129
|
+
| macos-11 | :heavy_check_mark: |
|
|
130
|
+
| macos-12 | :heavy_check_mark: |
|
|
131
|
+
| macos-13 | :heavy_check_mark: |
|
|
132
|
+
|
|
117
133
|
## Core Installation Script
|
|
118
134
|
|
|
119
135
|
Below are some one-click/automatic installation script that's been tested to work in Furious.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '0.2.1'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|