Refactor QMainWindow to MainWindow

Signed-off-by: Loren Eteval <loren.eteval@proton.me>
This commit is contained in:
Loren Eteval
2023-08-14 19:15:54 +08:00
parent d66b4f6b32
commit bdee18f32d
9 changed files with 147 additions and 136 deletions
-2
View File
@@ -66,8 +66,6 @@ SUPPORTED_SETTINGS = (
Settings('MainWidgetWindowSize'),
# Edit Routing Widget Window Size
Settings('RoutesWidgetWindowSize'),
# Edit Routing Widget Editor Window Size
Settings('RoutesEditorWindowSize'),
# Main Widget Section Size
Settings('ServerWidgetSectionSizeTable'),
# Edit Routing Widget Section Size
+19
View File
@@ -156,6 +156,25 @@ class SupportConnectedCallback:
ob.disconnectedCallback()
class NeedSyncSettings:
Object = list()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
NeedSyncSettings.Object.append(self)
def syncSettings(self):
raise NotImplementedError
@staticmethod
def syncAll():
for ob in NeedSyncSettings.Object:
assert isinstance(ob, NeedSyncSettings)
ob.syncSettings()
class SupportThemeChangedCallback:
Object = list()
+2 -9
View File
@@ -12,7 +12,7 @@ from Furious.Utility.Constants import (
SYSTEM_LANGUAGE,
DATA_DIR,
)
from Furious.Utility.Utility import SupportThemeChangedCallback
from Furious.Utility.Utility import SupportThemeChangedCallback, NeedSyncSettings
from Furious.Utility.Proxy import Proxy
from Furious.Utility.Settings import Settings
from Furious.Utility.Translator import gettext as _
@@ -265,14 +265,7 @@ class Application(SingletonApplication):
# if self.tray is not None:
# self.tray.ConnectAction.stopCore()
if self.MainWidget is not None:
self.MainWidget.syncSettings()
if self.editRoutingWidget is not None:
self.editRoutingWidget.syncSettings()
if self.logViewerWidget is not None:
self.logViewerWidget.syncSettings()
NeedSyncSettings.syncAll()
def exit(self, exitcode=0):
if self.MainWidget is not None:
+3 -20
View File
@@ -1,5 +1,5 @@
from Furious.Gui.Action import Action, Seperator
from Furious.Widget.Widget import ListWidget, Menu, MessageBox
from Furious.Widget.Widget import ListWidget, MainWindow, Menu, MessageBox
from Furious.Utility.Constants import APPLICATION_NAME, PLATFORM, GOLDEN_RATIO, ROOT_DIR
from Furious.Utility.Utility import (
StateContext,
@@ -14,7 +14,7 @@ from Furious.Utility.Translator import Translatable, gettext as _
from PySide6 import QtCore
from PySide6.QtGui import QFont
from PySide6.QtWidgets import QFileDialog, QListWidget, QListWidgetItem, QMainWindow
from PySide6.QtWidgets import QFileDialog, QListWidget, QListWidgetItem
import os
import shutil
@@ -136,9 +136,7 @@ class ExitAction(Action):
self.parent().hide()
class AssetViewerWidget(
Translatable, SupportConnectedCallback, SupportThemeChangedCallback, QMainWindow
):
class AssetViewerWidget(SupportThemeChangedCallback, MainWindow):
AssetDir = ROOT_DIR / APPLICATION_NAME / 'Data' / 'xray'
def __init__(self, *args, **kwargs):
@@ -251,17 +249,6 @@ class AssetViewerWidget(
else:
self.flushItemByTheme(darkdetect.theme())
def closeEvent(self, event):
event.ignore()
self.hide()
def connectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
def disconnectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
def themeChangedCallback(self, theme):
if PLATFORM == 'Linux' and getUbuntuRelease() == '20.04':
# Ubuntu 20.04 system dark theme does not
@@ -269,7 +256,3 @@ class AssetViewerWidget(
pass
else:
self.flushItemByTheme(theme)
def retranslate(self):
with StateContext(self):
self.setWindowTitle(_(self.windowTitle()))
+2 -9
View File
@@ -5,6 +5,7 @@ from Furious.Core.Configuration import Configuration
from Furious.Gui.Action import Action, Seperator
from Furious.Widget.Widget import (
HeaderView,
MainWindow,
Menu,
MessageBox,
PushButton,
@@ -47,10 +48,8 @@ from PySide6.QtWidgets import (
QHBoxLayout,
QHeaderView,
QLabel,
QLineEdit,
QListWidget,
QListWidgetItem,
QMainWindow,
QPlainTextEdit,
QSplitter,
QStyledItemDelegate,
@@ -1607,7 +1606,7 @@ class NormalServerWidget(Translatable, SupportConnectedCallback, TableWidget):
)
class EditConfigurationWidget(Translatable, SupportConnectedCallback, QMainWindow):
class EditConfigurationWidget(MainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -1975,12 +1974,6 @@ class EditConfigurationWidget(Translatable, SupportConnectedCallback, QMainWindo
)
APP().EditorWidgetPointSize = str(self.plainTextEdit.font().pointSize())
def connectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
def disconnectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
def retranslate(self):
with StateContext(self):
if self.modified:
+87 -69
View File
@@ -9,6 +9,7 @@ from Furious.Gui.Action import Action, Seperator
from Furious.Widget.Widget import (
HeaderView,
Menu,
MainWindow,
MessageBox,
PushButton,
StyledItemDelegate,
@@ -39,14 +40,15 @@ from PySide6 import QtCore
from PySide6.QtGui import QFont
from PySide6.QtWidgets import (
QAbstractItemView,
QDialog,
QDialogButtonBox,
QFileDialog,
QFormLayout,
QGridLayout,
QHBoxLayout,
QHeaderView,
QInputDialog,
QLabel,
QLineEdit,
QMainWindow,
QPlainTextEdit,
QSplitter,
QStyledItemDelegate,
@@ -204,7 +206,7 @@ BUILTIN_ROUTING_TEXT = {
f'# \n'
f'# This rule is read-only.\n'
f'# \n'
f'# If no rule file or mmdb file is provided, hysteria\n'
f'# If no rule file or mmdb file is provided, {APPLICATION_NAME}\n'
f'# will fall back to proxy all traffic.\n\n'
)
+ ujson.dumps(
@@ -289,7 +291,7 @@ USER_ROUTING_TEXT = {
f'# by {APPLICATION_NAME} forever.\n'
f'# \n'
f'# Note: If any one of filepath is given but\n'
f'# does not exist, hysteria will fall back to\n'
f'# does not exist, {APPLICATION_NAME} will fall back to\n'
f'# proxy all traffic.\n\n'
)
+ ujson.dumps(
@@ -515,7 +517,7 @@ class RoutingPlainTextEdit(ZoomablePlainTextEdit):
super().wheelEvent(event)
class RoutingEditor(Translatable, SupportConnectedCallback, QMainWindow):
class RoutingEditor(MainWindow):
def __init__(self, isBuiltin, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -669,12 +671,6 @@ class RoutingEditor(Translatable, SupportConnectedCallback, QMainWindow):
self.questionSave()
def connectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
def disconnectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
def retranslate(self):
if self.isBuiltin:
# Built-in routing is translatable
@@ -852,17 +848,7 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
routingEditor = RoutingEditor(isBuiltin)
routingEditor.title = title
routingEditor.setWindowTitle(title)
try:
routingEditor.setGeometry(
100,
100,
*list(int(size) for size in APP().RoutesEditorWindowSize.split(',')),
)
except Exception:
# Any non-exit exceptions
routingEditor.setGeometry(100, 100, 728 * GOLDEN_RATIO, 728)
routingEditor.setGeometry(100, 100, 656, 856)
moveToCenter(routingEditor)
@@ -970,7 +956,52 @@ class EditRoutingTableWidget(Translatable, SupportConnectedCallback, TableWidget
item.setText(_(item.text()))
class EditRoutingWidget(Translatable, SupportConnectedCallback, QMainWindow):
class AddRoutingDialog(Translatable, SupportConnectedCallback, QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle(_('Add routing'))
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
self.remarkText = QLabel(_('Enter routing remark:'))
self.remarkEdit = QLineEdit()
self.dialogBtns = QDialogButtonBox(QtCore.Qt.Orientation.Horizontal)
self.dialogBtns.addButton(_('OK'), QDialogButtonBox.ButtonRole.AcceptRole)
self.dialogBtns.addButton(_('Cancel'), QDialogButtonBox.ButtonRole.RejectRole)
self.dialogBtns.accepted.connect(self.accept)
self.dialogBtns.rejected.connect(self.reject)
layout = QFormLayout()
layout.addRow(self.remarkText)
layout.addRow(self.remarkEdit)
layout.addRow(self.dialogBtns)
layout.setFormAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.setLayout(layout)
def routingRemark(self):
return self.remarkEdit.text()
def connectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
def disconnectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
def retranslate(self):
with StateContext(self):
self.setWindowTitle(_(self.windowTitle()))
self.remarkText.setText(_(self.remarkText.text()))
for button in self.dialogBtns.buttons():
button.setText(_(button.text()))
class EditRoutingWidget(MainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -978,6 +1009,7 @@ class EditRoutingWidget(Translatable, SupportConnectedCallback, QMainWindow):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
self.assetViewer = AssetViewerWidget()
self.addRoutingDialog = AddRoutingDialog()
try:
self.StorageObj = RoutesStorage.toObject(APP().CustomRouting)
@@ -1048,36 +1080,44 @@ class EditRoutingWidget(Translatable, SupportConnectedCallback, QMainWindow):
moveToCenter(self)
def addRoute(self):
# Get text for a new item from the user
text, ok = QInputDialog.getText(
self, _('Add routing'), _('Enter routing remark:')
)
choice = self.addRoutingDialog.exec()
if text and ok:
self.editRoutingTableWidget.appendDataByColumn(
lambda column: EditRoutingTableWidget.USER_ITEM_GET_FUNC[column](text)
)
if choice == QDialog.DialogCode.Accepted.value:
routingRemark = self.addRoutingDialog.routingRemark()
routingEditor = self.editRoutingTableWidget.appendRoutingEditor(
text, isBuiltin=False
)
for core in [XrayCore.name(), Hysteria.name()]:
routingEditor.addTabWithData(
core,
USER_ROUTING_TEXT[core],
if routingRemark:
self.editRoutingTableWidget.appendDataByColumn(
lambda column: EditRoutingTableWidget.USER_ITEM_GET_FUNC[column](
routingRemark
)
)
self.RoutesList.append({'remark': text, **DEFAULT_USER_ROUTING})
routingEditor = self.editRoutingTableWidget.appendRoutingEditor(
routingRemark, isBuiltin=False
)
# Sync it
RoutesStorage.sync()
for core in [XrayCore.name(), Hysteria.name()]:
routingEditor.addTabWithData(
core,
USER_ROUTING_TEXT[core],
)
routingAction = APP().tray.RoutingAction
# Add entry in routing menu
routingAction.addAction(
RoutingChildAction(text, checkable=True, checked=False)
)
self.RoutesList.append(
{'remark': routingRemark, **DEFAULT_USER_ROUTING}
)
# Sync it
RoutesStorage.sync()
routingAction = APP().tray.RoutingAction
# Add entry in routing menu
routingAction.addAction(
RoutingChildAction(routingRemark, checkable=True, checked=False)
)
else:
# Do nothing
pass
def deleteSelectedItem(self):
self.editRoutingTableWidget.deleteSelectedItem()
@@ -1090,12 +1130,6 @@ class EditRoutingWidget(Translatable, SupportConnectedCallback, QMainWindow):
f'{self.geometry().width()},{self.geometry().height()}'
)
if len(self.editRoutingTableWidget.routingEditorRef):
APP().RoutesEditorWindowSize = (
f'{self.editRoutingTableWidget.routingEditorRef[0].geometry().width()},'
f'{self.editRoutingTableWidget.routingEditorRef[0].geometry().height()}'
)
APP().RoutesWidgetSectionSizeTable = ujson.dumps(
self.editRoutingTableWidget.sectionSizeTable,
ensure_ascii=False,
@@ -1107,19 +1141,3 @@ class EditRoutingWidget(Translatable, SupportConnectedCallback, QMainWindow):
self.deleteSelectedItem()
else:
super().keyPressEvent(event)
def closeEvent(self, event):
event.ignore()
self.syncSettings()
self.hide()
def connectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
def disconnectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
def retranslate(self):
with StateContext(self):
self.setWindowTitle(_(self.windowTitle()))
+4 -8
View File
@@ -1,16 +1,18 @@
from Furious.Widget.Widget import MainWindow
from Furious.Utility.Constants import APPLICATION_NAME
from Furious.Utility.Utility import SupportConnectedCallback, bootstrapIcon
from Furious.Utility.Translator import gettext as _
from PySide6 import QtCore
from PySide6.QtGui import QPixmap
from PySide6.QtWidgets import QLabel, QMainWindow, QTabWidget
from PySide6.QtWidgets import QLabel, QTabWidget
import io
import pyqrcode
class ExportQRCode(SupportConnectedCallback, QMainWindow):
class ExportQRCode(MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
@@ -47,9 +49,3 @@ class ExportQRCode(SupportConnectedCallback, QMainWindow):
if self.editorTab.count() == 0:
self.hide()
def connectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
def disconnectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
+3 -19
View File
@@ -1,5 +1,5 @@
from Furious.Gui.Action import Action, Seperator
from Furious.Widget.Widget import Menu, MessageBox, ZoomableTextBrowser
from Furious.Widget.Widget import MainWindow, Menu, MessageBox, ZoomableTextBrowser
from Furious.Utility.Constants import APP
from Furious.Utility.Utility import (
StateContext,
@@ -10,7 +10,7 @@ from Furious.Utility.Translator import Translatable, gettext as _
from Furious.Utility.Theme import DraculaTheme
from PySide6 import QtCore
from PySide6.QtWidgets import QFileDialog, QMainWindow, QTextBrowser
from PySide6.QtWidgets import QFileDialog, QTextBrowser
import logging
@@ -134,7 +134,7 @@ class ZoomOutAction(Action):
self.parent().textBrowser.zoomOut()
class LogViewerWidget(Translatable, SupportConnectedCallback, QMainWindow):
class LogViewerWidget(MainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -201,19 +201,3 @@ class LogViewerWidget(Translatable, SupportConnectedCallback, QMainWindow):
def syncSettings(self):
APP().ViewerWidgetPointSize = str(self.textBrowser.font().pointSize())
def closeEvent(self, event):
event.ignore()
self.syncSettings()
self.hide()
def connectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
def disconnectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
def retranslate(self):
with StateContext(self):
self.setWindowTitle(_(self.windowTitle()))
+27
View File
@@ -3,6 +3,7 @@ from Furious.Utility.Constants import APP
from Furious.Utility.Utility import (
StateContext,
SupportConnectedCallback,
NeedSyncSettings,
bootstrapIcon,
moveToCenter,
)
@@ -15,6 +16,7 @@ from PySide6.QtWidgets import (
QInputDialog,
QLineEdit,
QListWidget,
QMainWindow,
QMenu,
QMessageBox,
QPlainTextEdit,
@@ -56,6 +58,31 @@ class ListWidget(QListWidget):
return sorted(list(set(index.row() for index in self.selectedIndexes())))
class MainWindow(Translatable, SupportConnectedCallback, NeedSyncSettings, QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def syncSettings(self):
pass
def closeEvent(self, event):
event.ignore()
# Sync partial
self.syncSettings()
self.hide()
def connectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-connected-dark.svg'))
def disconnectedCallback(self):
self.setWindowIcon(bootstrapIcon('rocket-takeoff-window.svg'))
def retranslate(self):
with StateContext(self):
self.setWindowTitle(_(self.windowTitle()))
class Menu(Translatable, QMenu):
def __init__(self, *actions, **kwargs):
super().__init__(**kwargs)