mirror of
https://github.com/LorenEteval/Furious.git
synced 2026-09-30 19:08:03 +03:00
Feature: Added waiting spinner support while deleting servers
Signed-off-by: LorenEteval <loren.eteval@proton.me>
This commit is contained in:
committed by
Loren Eteval
parent
7a2ccf9a17
commit
5d8e55ce81
Vendored
+19
-1
@@ -222,6 +222,7 @@ TRANSLATION = {
|
||||
"Furious.Widget.GuiCustomizeNetworkTest",
|
||||
"Furious.Widget.GuiCustomizeProxyBypass",
|
||||
"Furious.Widget.IndentSpinBox",
|
||||
"Furious.Widget.UserServersQTableView",
|
||||
"Furious.Window.TextEditorWindow",
|
||||
"Furious.Window.UserSubsWindow"
|
||||
],
|
||||
@@ -1902,10 +1903,27 @@ TRANSLATION = {
|
||||
},
|
||||
"Current": {
|
||||
"source": [
|
||||
"Furious.TrayActions.Import"
|
||||
"Furious.TrayActions.Import",
|
||||
"Furious.Widget.UserServersQTableView"
|
||||
],
|
||||
"RU": "Текущий",
|
||||
"ZH": "当前",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Canceling delete": {
|
||||
"source": [
|
||||
"Furious.Widget.UserServersQTableView"
|
||||
],
|
||||
"RU": "Отмена удаления",
|
||||
"ZH": "正在取消删除",
|
||||
"isReviewed": "True"
|
||||
},
|
||||
"Deleting": {
|
||||
"source": [
|
||||
"Furious.Widget.UserServersQTableView"
|
||||
],
|
||||
"RU": "Удаление",
|
||||
"ZH": "正在删除",
|
||||
"isReviewed": "True"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ from Furious.Widget.GuiShadowsocks import *
|
||||
from Furious.Widget.GuiTrojan import *
|
||||
from Furious.Widget.GuiVLESS import *
|
||||
from Furious.Widget.GuiVMess import *
|
||||
from Furious.Widget.WaitingSpinner import *
|
||||
from Furious.Window.QRCodeWindow import *
|
||||
from Furious.Window.TextEditorWindow import *
|
||||
|
||||
@@ -172,7 +173,9 @@ class SubscriptionManager(WebGETManager):
|
||||
break
|
||||
|
||||
parent.deleteItemByIndex(
|
||||
subsIndexes, showTrayMessage=bool(subsGroupIndex < 0)
|
||||
subsIndexes,
|
||||
showTrayMessage=bool(subsGroupIndex < 0),
|
||||
showProgress=False,
|
||||
)
|
||||
|
||||
remaining = len(Storage.UserServers())
|
||||
@@ -850,6 +853,169 @@ class DownloadSpeedTestScheduler(QtCore.QObject):
|
||||
self.scheduleDrain()
|
||||
|
||||
|
||||
class DeleteServersProgressDialog(AppQDialog):
|
||||
def __init__(self, table, indexes, showTrayMessage=True, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.table = table
|
||||
self.indexes = list(indexes)
|
||||
self.showTrayMessage = showTrayMessage
|
||||
self.total = len(self.indexes)
|
||||
self.nextIndex = 0
|
||||
self.deletedCount = 0
|
||||
self.deletedActivated = False
|
||||
self.canceled = False
|
||||
self.finishedDeletion = False
|
||||
self.currentRemark = ''
|
||||
|
||||
self.setWindowTitle(_('Delete'))
|
||||
self.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
|
||||
|
||||
self.spinner = WaitingSpinner(
|
||||
self,
|
||||
center_on_parent=False,
|
||||
lines=12,
|
||||
line_length=7,
|
||||
line_width=3,
|
||||
radius=7,
|
||||
color=QColor(96, 160, 255),
|
||||
)
|
||||
self.statusLabel = AppQLabel()
|
||||
self.detailLabel = AppQLabel()
|
||||
self.detailLabel.setWordWrap(True)
|
||||
self.cancelButton = AppQPushButton(_('Cancel'))
|
||||
self.cancelButton.clicked.connect(self.cancel)
|
||||
|
||||
statusLayout = QHBoxLayout()
|
||||
statusLayout.addWidget(self.spinner)
|
||||
statusLayout.addWidget(self.statusLabel, 1)
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addLayout(statusLayout)
|
||||
layout.addWidget(self.detailLabel)
|
||||
layout.addWidget(self.cancelButton)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
self.updateStatus()
|
||||
|
||||
def setWidthAndHeight(self):
|
||||
self.resize(420, 150)
|
||||
|
||||
def exec(self):
|
||||
self.spinner.start()
|
||||
|
||||
QtCore.QTimer.singleShot(0, self.deleteNext)
|
||||
|
||||
return super().exec()
|
||||
|
||||
def reject(self):
|
||||
self.cancel()
|
||||
|
||||
def cancel(self):
|
||||
self.canceled = True
|
||||
self.cancelButton.setEnabled(False)
|
||||
self.updateStatus()
|
||||
|
||||
def updateStatus(self):
|
||||
if self.canceled:
|
||||
self.statusLabel.setText(
|
||||
_('Canceling delete') + f'... {self.deletedCount}/{self.total}'
|
||||
)
|
||||
else:
|
||||
self.statusLabel.setText(
|
||||
_('Deleting') + f'... {self.deletedCount}/{self.total}'
|
||||
)
|
||||
|
||||
if self.currentRemark:
|
||||
self.detailLabel.setText(_('Current') + f': {self.currentRemark}')
|
||||
else:
|
||||
self.detailLabel.setText('')
|
||||
|
||||
@staticmethod
|
||||
def limitedRemark(remark: str) -> str:
|
||||
remark = str(remark).strip()
|
||||
|
||||
if len(remark) <= 120:
|
||||
return remark
|
||||
|
||||
return remark[:117] + '...'
|
||||
|
||||
def deleteNext(self):
|
||||
if self.canceled or self.nextIndex >= self.total:
|
||||
self.finishDeletion()
|
||||
|
||||
return
|
||||
|
||||
originalIndex = self.indexes[self.nextIndex]
|
||||
self.nextIndex += 1
|
||||
deleteIndex = originalIndex - self.deletedCount
|
||||
|
||||
if deleteIndex < 0 or deleteIndex >= len(Storage.UserServers()):
|
||||
self.updateStatus()
|
||||
QtCore.QTimer.singleShot(0, self.deleteNext)
|
||||
|
||||
return
|
||||
|
||||
factory = Storage.UserServers()[deleteIndex]
|
||||
|
||||
self.currentRemark = self.limitedRemark(factory.getExtras('remark'))
|
||||
|
||||
if originalIndex == Storage.UserActivatedItemIndex():
|
||||
self.deletedActivated = True
|
||||
|
||||
self.table.sourceModel.beginRemoveRows(
|
||||
QtCore.QModelIndex(),
|
||||
deleteIndex,
|
||||
deleteIndex,
|
||||
)
|
||||
|
||||
factory.deleted = True
|
||||
|
||||
Storage.UserServers().pop(deleteIndex)
|
||||
|
||||
self.table.sourceModel.endRemoveRows()
|
||||
|
||||
if not self.deletedActivated and deleteIndex < Storage.UserActivatedItemIndex():
|
||||
AppSettings.set(
|
||||
'ActivatedItemIndex', str(Storage.UserActivatedItemIndex() - 1)
|
||||
)
|
||||
|
||||
self.deletedCount += 1
|
||||
self.updateStatus()
|
||||
|
||||
QtCore.QTimer.singleShot(0, self.deleteNext)
|
||||
|
||||
def finishDeletion(self):
|
||||
if self.finishedDeletion:
|
||||
return
|
||||
|
||||
self.finishedDeletion = True
|
||||
self.spinner.stop()
|
||||
|
||||
self.table.sourceModel.refreshIndexes()
|
||||
self.table.sourceModel.emitAllChanged()
|
||||
|
||||
if self.deletedActivated:
|
||||
# Set invalid first
|
||||
AppSettings.set('ActivatedItemIndex', str(-1))
|
||||
|
||||
if APP().isSystemTrayConnected():
|
||||
if self.showTrayMessage:
|
||||
# Trigger disconnect
|
||||
APP().systemTray.ConnectAction.trigger()
|
||||
else:
|
||||
# Trigger disconnect silently
|
||||
APP().systemTray.ConnectAction.doDisconnect()
|
||||
|
||||
self.accept()
|
||||
|
||||
def retranslate(self):
|
||||
self.setWindowTitle(_(self.windowTitle()))
|
||||
self.cancelButton.setText(_(self.cancelButton.text()))
|
||||
self.updateStatus()
|
||||
|
||||
|
||||
class UserServersQTableViewHorizontalHeader(AppQHeaderView):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(QtCore.Qt.Orientation.Horizontal, *args, **kwargs)
|
||||
@@ -1933,11 +2099,26 @@ class UserServersQTableView(
|
||||
config=deepcopy,
|
||||
)
|
||||
|
||||
def deleteItemByIndex(self, indexes, showTrayMessage=True) -> int:
|
||||
def deleteItemByIndex(
|
||||
self, indexes, showTrayMessage=True, showProgress=True
|
||||
) -> int:
|
||||
indexes = sorted(set(indexes))
|
||||
|
||||
if len(indexes) == 0:
|
||||
# Nothing selected. Do nothing
|
||||
return 0
|
||||
|
||||
if showProgress and len(indexes) > 1:
|
||||
dialog = DeleteServersProgressDialog(
|
||||
self,
|
||||
indexes,
|
||||
showTrayMessage=showTrayMessage,
|
||||
parent=self.window(),
|
||||
)
|
||||
dialog.exec()
|
||||
|
||||
return dialog.deletedCount
|
||||
|
||||
if Storage.UserActivatedItemIndex() in indexes:
|
||||
deleteActivated = True
|
||||
else:
|
||||
|
||||
@@ -235,7 +235,8 @@ class AppMainWindow(AppQMainWindow):
|
||||
index
|
||||
for index, server in enumerate(Storage.UserServers())
|
||||
if server.getExtras('subsId') == unique
|
||||
)
|
||||
),
|
||||
showProgress=False,
|
||||
),
|
||||
)
|
||||
self.xrayAssetViewerWindow = XrayAssetViewerWindow(parent=self)
|
||||
|
||||
Reference in New Issue
Block a user