Improve logical block spacing

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2026-09-19 13:45:52 +08:00
parent 8645b412d5
commit f06c405fb7
7 changed files with 87 additions and 0 deletions
+6
View File
@@ -960,10 +960,12 @@ class RoutingRulesDialog(AppQTransientDialog):
super().__init__(parent)
self.routing = routing
self.setWindowTitle(_('Routing Rules'))
self.setWindowModality(QtCore.Qt.WindowModality.WindowModal)
self.listView = RoutingRulesListView(self.routing, parent=self)
self.routingUnique = routingUnique
self.originalRules = copy.deepcopy(self.listView.rules())
@@ -1248,9 +1250,11 @@ class UserRoutingTableView(Mixins.QTranslatable, AppQTableView):
return
unique = self.routingUniqueByRow(row)
routing['domainStrategy'] = text
self.sourceModel.emitAllChanged()
self._routingChanged(unique)
def setEnabled(self, row: int, state: str):
@@ -1265,9 +1269,11 @@ class UserRoutingTableView(Mixins.QTranslatable, AppQTableView):
return
unique = self.routingUniqueByRow(row)
routing['enabled'] = enabled
self.sourceModel.emitAllChanged()
self._routingChanged(unique, disabled=not enabled)
def _routingChanged(self, unique, *, disabled=False):
+4
View File
@@ -441,6 +441,7 @@ class ConnectionStartOperation(QtCore.QObject):
) = self.manager._prepareTUNPolicy(configcopy, self.proxyModeOnly)
except TUNPreparationError as ex:
self.manager._lastStartError = str(ex)
self._fail(str(ex), 'native TUN preparation failed')
return
@@ -665,6 +666,7 @@ class ConnectionStartOperation(QtCore.QObject):
exitCallback=router.publish,
msgCallback=self.msgCallbackTUN_,
)
router.attach(tun, self)
self._tun = tun
@@ -1050,6 +1052,7 @@ class ConnectionStartOperation(QtCore.QObject):
return
self._terminal = True
self._cancelObservers()
concise = str(message or '')
@@ -1071,6 +1074,7 @@ class ConnectionStartOperation(QtCore.QObject):
return False
self._terminal = True
self._cancelObservers()
self.attempt.rollback('connection startup cancelled')
+3
View File
@@ -937,10 +937,12 @@ class LogManager(QtCore.QObject):
characterCount = len(entry.message)
generation = self._generationForCategoryLocked(category)
generation.append(entry, characterCount)
self._retainedEntryCount += 1
self._retainedCharacters += characterCount
self._enforceRetentionLimitsLocked()
events.append((clearedCategoryIds, entry))
@@ -1089,6 +1091,7 @@ class LogManager(QtCore.QObject):
self._retainedEntryCount -= retiredCategory.entryCount
self._retainedCharacters -= retiredCategory.characterCount
self._retireBatchLocked(retiredCategory)
if changed:
+3
View File
@@ -176,12 +176,15 @@ class _SubscriptionEditorDialog(AppQTransientDialog):
form.addWidget(self.remarkLabel, 0, 0)
form.addWidget(self.remarkEdit, 0, 1)
form.addLayout(enabledLayout, 0, 2, 1, 2)
form.addWidget(self.urlLabel, 1, 0)
form.addWidget(self.urlEdit, 1, 1, 1, 3)
form.addWidget(self.autoUpdateLabel, 2, 0)
form.addWidget(self.autoUpdateComboBox, 2, 1)
form.addWidget(self.proxyLabel, 2, 2)
form.addWidget(self.proxyComboBox, 2, 3)
form.addWidget(self.userAgentLabel, 3, 0)
form.addWidget(self.userAgentEdit, 3, 1)
form.addWidget(self.filterLabel, 3, 2)
+37
View File
@@ -712,6 +712,7 @@ class RoutingControllerTest(unittest.TestCase):
from Furious.Widget.RoutingSelector import RoutingSelector
app = application()
with isolatedSettings():
profile = ServerProfile.fromConfiguration(
ConfigXray(
@@ -723,11 +724,14 @@ class RoutingControllerTest(unittest.TestCase):
}
)
)
routings = {
'active': {'remark': 'My routing', 'enabled': True, 'rules': []}
}
registry = PluginRegistry()
registry.register(XrayPlugin())
core = FixtureCoreManager()
launchedRoutes = []
@@ -735,13 +739,16 @@ class RoutingControllerTest(unittest.TestCase):
launchedRoutes.append(
registry.normalizeRouting(configuration, kwargs['routing'])
)
return True
core.start = start
connection = ConnectionController(
coreManager=core, updatesManager=FixtureUpdatesManager()
)
logManager = LogManager()
with (
mock.patch.object(app, 'connectionController', connection),
mock.patch.object(app, 'logManager', logManager),
@@ -759,36 +766,50 @@ class RoutingControllerTest(unittest.TestCase):
):
AppSettings.set('Routing', 'Custom:active')
controller = RoutingController()
with mock.patch.object(app, 'routingController', controller):
view = UserRoutingTableView()
tray = RoutingAction(parent=view)
selector = RoutingSelector(parent=view)
try:
self.assertTrue(connection.startConnection(profile))
self.assertEqual(launchedRoutes, ['Custom:active'])
view.indexWidget(view.sourceModel.index(0, 2)).setCurrentIndex(
1
)
prompt = view.findChild(MBoxNewChangesNextTime)
self.assertIsNotNone(prompt)
prompt.button(AppQMessageBox.StandardButton.Yes).click()
processQtEvents()
fallback = AppBuiltinRouting.BypassMainlandChina.value
self.assertEqual(launchedRoutes, ['Custom:active', fallback])
tray.rebuildMenu()
self.assertEqual(controller.routing, fallback)
view.indexWidget(view.sourceModel.index(0, 2)).setCurrentIndex(
0
)
tray.rebuildMenu()
self.assertEqual(controller.routing, fallback)
self.assertEqual(AppSettings.get('Routing'), fallback)
self.assertEqual(selector.currentData(), fallback)
checked = [
action.routingValue
for action in tray._menu.actions()
if action.isChecked()
]
self.assertEqual(checked, [fallback])
self.assertEqual(len(launchedRoutes), 2)
self.assertEqual(view.findChildren(MBoxNewChangesNextTime), [])
@@ -798,22 +819,30 @@ class RoutingControllerTest(unittest.TestCase):
for action in tray._menu.actions()
if getattr(action, 'routingValue', None) == 'Custom:active'
)
customAction.trigger()
self.assertEqual(
launchedRoutes, ['Custom:active', fallback, 'Custom:active']
)
self.assertEqual(selector.currentData(), 'Custom:active')
view.indexWidget(view.sourceModel.index(0, 2)).setCurrentIndex(
1
)
prompt = view.findChild(MBoxNewChangesNextTime)
prompt.button(AppQMessageBox.StandardButton.No).click()
processQtEvents()
self.assertEqual(len(launchedRoutes), 3)
view.indexWidget(view.sourceModel.index(0, 2)).setCurrentIndex(
0
)
tray.rebuildMenu()
self.assertEqual(controller.routing, fallback)
self.assertEqual(AppSettings.get('Routing'), fallback)
self.assertEqual(len(launchedRoutes), 3)
@@ -823,6 +852,7 @@ class RoutingControllerTest(unittest.TestCase):
view.deleteLater()
controller.deleteLater()
processQtEvents()
connection.deleteLater()
logManager.deleteLater()
registry.shutdown()
@@ -831,9 +861,11 @@ class RoutingControllerTest(unittest.TestCase):
def testOnlyExplicitInvalidationPersistsFallbackWithoutReconnecting(self):
"""Capability refresh stays observational until a selected choice is revoked."""
connection = mock.Mock(activeProfile=self.connectedProfile)
registry = mock.Mock()
registry.routingOptions.return_value = (SimpleNamespace(id='fallback'),)
registry.normalizeRouting.return_value = 'fallback'
with (
isolatedSettings(),
mock.patch(
@@ -847,14 +879,19 @@ class RoutingControllerTest(unittest.TestCase):
):
AppSettings.set('Routing', 'unavailable')
controller = RoutingController()
try:
controller.refresh(force=True)
self.assertEqual(controller.routing, 'fallback')
self.assertEqual(AppSettings.get('Routing'), 'unavailable')
self.assertFalse(controller.invalidateRouting('other'))
self.assertEqual(AppSettings.get('Routing'), 'unavailable')
self.assertTrue(controller.invalidateRouting('unavailable'))
self.assertEqual(AppSettings.get('Routing'), 'fallback')
self.assertFalse(controller.invalidateRouting('fallback'))
connection.startReconnection.assert_not_called()
finally:
+1
View File
@@ -1036,6 +1036,7 @@ class ProfileTestServiceTest(unittest.TestCase):
for worker in _ControlledDownloadWorker.instances
if worker.profile.metadata.profileId == other.metadata.profileId
)
otherDownload.finish('3.00 MiB/s')
processQtEvents()
+33
View File
@@ -2479,6 +2479,7 @@ class RoutingChangeNoticeTest(unittest.TestCase):
app = application()
self.addCleanup(collectAtBoundary)
self.enterContext(isolatedSettings())
self.routings = {
unique: {
'remark': 'Same display name',
@@ -2491,9 +2492,11 @@ class RoutingChangeNoticeTest(unittest.TestCase):
}
for unique in ('active', 'other')
}
self.connection = mock.Mock()
self.connection.isConnected.return_value = True
self.routing = mock.Mock(routing='Custom:active')
self.enterContext(
mock.patch.object(app, 'connectionController', self.connection)
)
@@ -2504,6 +2507,7 @@ class RoutingChangeNoticeTest(unittest.TestCase):
self.notice = self.enterContext(
mock.patch('Furious.Backends.Xray.RoutingWindow.showMBoxNewChangesNextTime')
)
self.view = UserRoutingTableView()
self.addCleanup(self.disposeView)
@@ -2524,30 +2528,40 @@ class RoutingChangeNoticeTest(unittest.TestCase):
self.view.flushAll()
self.view.setDomainStrategy(0, 'AsIs')
self.view.setEnabled(0, 'Enabled')
self.notice.assert_not_called()
strategy = self.view.indexWidget(self.view.sourceModel.index(0, 1))
strategy.setCurrentText('IPOnDemand')
self.assertEqual(self.routings['active']['domainStrategy'], 'IPOnDemand')
self.notice.assert_called_once_with(parent=self.view)
self.notice.reset_mock()
enabled = self.view.indexWidget(self.view.sourceModel.index(0, 2))
enabled.setCurrentIndex(1)
self.assertFalse(self.routings['active']['enabled'])
self.notice.assert_called_once_with(parent=self.view)
self.notice.reset_mock()
self.view.setDomainStrategy(1, 'IPIfNonMatch')
self.view.setEnabled(1, 'Disabled')
self.connection.isConnected.return_value = False
self.view.setDomainStrategy(0, 'AsIs')
self.view.setEnabled(0, 'Enabled')
self.connection.isConnected.return_value = True
self.routing.routing = 'Global'
self.view.setDomainStrategy(0, 'IPIfNonMatch')
self.notice.assert_not_called()
processQtEvents()
exceptionHook.assert_not_called()
def testRuleChangesNotifyOnCloseWithoutRetargetingSelection(self):
@@ -2558,6 +2572,7 @@ class RoutingChangeNoticeTest(unittest.TestCase):
) as exceptionHook:
dialog = self.openRules()
view = dialog.listView
if change == 'add':
view.appendRule({'domain': ['new.test'], 'outboundTag': 'proxy'})
elif change == 'edit':
@@ -2567,12 +2582,16 @@ class RoutingChangeNoticeTest(unittest.TestCase):
else:
view.setCurrentIndex(view.rulesModel.index(0, 0))
view.moveSelectedRules('down')
self.view.selectRow(1)
self.notice.assert_not_called()
dialog.closeWindowButton.click()
processQtEvents()
self.notice.assert_called_once_with(parent=self.view)
exceptionHook.assert_not_called()
self.notice.reset_mock()
def testRuleNoticeSkipsUnchangedRevertedStaleAndInactiveEdits(self):
@@ -2587,10 +2606,12 @@ class RoutingChangeNoticeTest(unittest.TestCase):
):
with self.subTest(case=case), mock.patch('sys.excepthook') as exceptionHook:
dialog = self.openRules(1 if case == 'other' else 0)
if case != 'unchanged':
dialog.listView.appendRule(
{'domain': ['new.test'], 'outboundTag': 'proxy'}
)
if case == 'reverted':
dialog.listView.deleteRules([len(dialog.listView.rules()) - 1])
elif case == 'disconnected':
@@ -2599,10 +2620,13 @@ class RoutingChangeNoticeTest(unittest.TestCase):
self.routing.routing = 'Custom:other'
elif case == 'replaced':
self.routings['active'] = copy.deepcopy(self.routings['active'])
dialog.reject()
processQtEvents()
self.notice.assert_not_called()
exceptionHook.assert_not_called()
self.connection.isConnected.return_value = True
self.routing.routing = 'Custom:active'
@@ -2615,23 +2639,30 @@ class RoutingChangeNoticeTest(unittest.TestCase):
from shiboken6 import delete as deleteQObject, isValid
self.notice.side_effect = showMBoxNewChangesNextTime
for button in (
AppQMessageBox.StandardButton.No,
AppQMessageBox.StandardButton.Yes,
):
dialog = self.openRules()
dialog.listView.appendRule({'domain': ['new.test'], 'outboundTag': 'proxy'})
dialog.closeWindowButton.click()
processQtEvents()
prompt = self.view.findChild(MBoxNewChangesNextTime)
self.assertIsNotNone(prompt)
self.assertTrue(prompt.isVisible())
self.assertFalse(isValid(dialog))
self.assertIn(prompt, AppQDialog._openDialogs.values())
prompt.button(button).click()
processQtEvents()
self.assertFalse(isValid(prompt))
self.assertNotIn(prompt, AppQDialog._openDialogs.values())
if button == AppQMessageBox.StandardButton.No:
self.connection.startReconnection.assert_not_called()
else:
@@ -2639,8 +2670,10 @@ class RoutingChangeNoticeTest(unittest.TestCase):
self.view.setDomainStrategy(0, 'IPOnDemand')
prompt = self.view.findChild(MBoxNewChangesNextTime)
deleteQObject(self.view)
processQtEvents()
self.assertFalse(isValid(prompt))
self.assertNotIn(prompt, AppQDialog._openDialogs.values())