1
1
mirror of https://github.com/KenanZhu/AutoLibrary.git synced 2026-06-17 23:13:03 +08:00

refactor(style): 统一项目代码风格,整理导入顺序、间距规范与方法排列

- GUI 模块统一 QtCore → QtGui → QtWidgets 导入排列,各类独占一行按字母排序
- 统一类间两空行、类内方法间一空行、函数间一空行的间距规范
- 统一方法排列顺序:__init__ → setupUi → connectSignals → public → Slot → private
- 统一 _widgets 中 ConditionRowFrame/ActionStepFrame 方法命名(populate* / toScript / updateValueWidget)
- LibTimeSelector 迁入 operators/abs 抽象层

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 13:14:27 +08:00
parent a03ab38279
commit 5e898180c7
42 changed files with 780 additions and 1008 deletions
-15
View File
@@ -45,7 +45,6 @@ _DEFAULT_BY_TYPE: dict[str, str | int | float | bool] = {
"Boolean": False, "Boolean": False,
} }
def _getLua( def _getLua(
): ):
""" """
@@ -59,7 +58,6 @@ def _getLua(
_registerHelpers(_lua) _registerHelpers(_lua)
return _lua return _lua
def _sandbox( def _sandbox(
lua, lua,
) -> None: ) -> None:
@@ -92,7 +90,6 @@ def _sandbox(
end end
""") """)
def _registerHelpers( def _registerHelpers(
lua, lua,
) -> None: ) -> None:
@@ -154,7 +151,6 @@ def _registerHelpers(
end end
""") """)
def _navigatePath( def _navigatePath(
data: dict, data: dict,
key_path: list, key_path: list,
@@ -171,7 +167,6 @@ def _navigatePath(
return default return default
return d.get(key_path[-1], default) return d.get(key_path[-1], default)
def _assignPath( def _assignPath(
data: dict, data: dict,
key_path: list, key_path: list,
@@ -186,7 +181,6 @@ def _assignPath(
d = d.setdefault(key, {}) d = d.setdefault(key, {})
d[key_path[-1]] = value d[key_path[-1]] = value
def _pyTypeToASType( def _pyTypeToASType(
value value
) -> str: ) -> str:
@@ -204,7 +198,6 @@ def _pyTypeToASType(
return "String" return "String"
return "Unknown" return "Unknown"
def _checkDateFormat( def _checkDateFormat(
date_str: str, date_str: str,
var_name: str = "", var_name: str = "",
@@ -223,7 +216,6 @@ def _checkDateFormat(
f"应为 YYYY-MM-DD" f"应为 YYYY-MM-DD"
) )
def _checkTimeFormat( def _checkTimeFormat(
time_str: str, time_str: str,
var_name: str = "", var_name: str = "",
@@ -242,7 +234,6 @@ def _checkTimeFormat(
f"应为 HH:MM" f"应为 HH:MM"
) )
def _checkType( def _checkType(
var_name: str, var_name: str,
var_type: str, var_type: str,
@@ -306,7 +297,6 @@ def _checkType(
) )
return return
def addTargetVar( def addTargetVar(
name: str, name: str,
var_type: str, var_type: str,
@@ -328,7 +318,6 @@ def addTargetVar(
"key_path": key_path, "key_path": key_path,
} }
def resetEngine( def resetEngine(
) -> None: ) -> None:
""" """
@@ -340,7 +329,6 @@ def resetEngine(
_TARGET_VARS = {} _TARGET_VARS = {}
_lua = None _lua = None
def _push( def _push(
target_data: dict, target_data: dict,
) -> None: ) -> None:
@@ -384,7 +372,6 @@ def _push(
raw = _DEFAULT_BY_TYPE.get(vt, False) raw = _DEFAULT_BY_TYPE.get(vt, False)
g[var_name] = raw g[var_name] = raw
def _pull( def _pull(
target_data: dict, target_data: dict,
) -> None: ) -> None:
@@ -413,7 +400,6 @@ def _pull(
_checkType(var_name, vt, lua_val) _checkType(var_name, vt, lua_val)
_assignPath(target_data, info["key_path"], lua_val) _assignPath(target_data, info["key_path"], lua_val)
def _cleanLuaError( def _cleanLuaError(
raw_msg: str raw_msg: str
) -> str: ) -> str:
@@ -427,7 +413,6 @@ def _cleanLuaError(
msg = msg[:stack_idx].strip() msg = msg[:stack_idx].strip()
return msg return msg
def execute( def execute(
script_text: str, script_text: str,
target_data: dict, target_data: dict,
-2
View File
@@ -55,7 +55,6 @@ _MOCK_TYPE_VALUES = {
"Float": 0.0, "Float": 0.0,
} }
def buildMockTargetData( def buildMockTargetData(
) -> dict: ) -> dict:
""" """
@@ -70,7 +69,6 @@ def buildMockTargetData(
d[key_path[-1]] = _MOCK_TYPE_VALUES.get(var_type, "") d[key_path[-1]] = _MOCK_TYPE_VALUES.get(var_type, "")
return data return data
def registerDefaultTargetVars( def registerDefaultTargetVars(
) -> None: ) -> None:
""" """
-1
View File
@@ -29,7 +29,6 @@ class LibOperator(MsgBase):
super().__init__(input_queue, output_queue) super().__init__(input_queue, output_queue)
def _waitResponseLoad( def _waitResponseLoad(
self self
) -> bool: ) -> bool:
-4
View File
@@ -58,7 +58,6 @@ class MsgBase:
except RuntimeError: except RuntimeError:
self._logger = None self._logger = None
def _showMsg( def _showMsg(
self, self,
msg: str msg: str
@@ -66,7 +65,6 @@ class MsgBase:
self._output_queue.put(f"[{self._class_name:<15}] >>> : {msg}") self._output_queue.put(f"[{self._class_name:<15}] >>> : {msg}")
def _showTrace( def _showTrace(
self, self,
msg: str, msg: str,
@@ -79,7 +77,6 @@ class MsgBase:
if self._logger and not no_log: if self._logger and not no_log:
self._logger.log(level, msg) self._logger.log(level, msg)
def _showLog( def _showLog(
self, self,
msg: str, msg: str,
@@ -89,7 +86,6 @@ class MsgBase:
if self._logger: if self._logger:
self._logger.log(level, msg) self._logger.log(level, msg)
def _waitMsg( def _waitMsg(
self, self,
timeout: float = 1.0 timeout: float = 1.0
+1 -2
View File
@@ -1,8 +1,7 @@
""" """
Base module for the AutoLibrary project. Base module for the AutoLibrary project.
Here are the classes and modules in this package: Here are the classes and modules in this package:
- MsgBase: Base class for messages.\ - MsgBase: Base class for messages.
- LibOperator: Base class for library operators. - LibOperator: Base class for library operators.
""" """
+12 -6
View File
@@ -16,7 +16,7 @@ from managers.config.ConfigManager import instance as configInstance
from managers.driver.WebDriverManager import instance as webdriverInstance from managers.driver.WebDriverManager import instance as webdriverInstance
def initializeLogManager( def _initializeLogManager(
) -> bool: ) -> bool:
app_dir = QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppDataLocation) app_dir = QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppDataLocation)
@@ -27,7 +27,7 @@ def initializeLogManager(
logInstance(log_dir) logInstance(log_dir)
return True return True
def initializeConfigManager( def _initializeConfigManager(
) -> bool: ) -> bool:
logger = logInstance().getLogger("AppInitializer") logger = logInstance().getLogger("AppInitializer")
@@ -49,7 +49,7 @@ def initializeConfigManager(
configInstance(new_config_dir) configInstance(new_config_dir)
return True return True
def initializeWebDriverManager( def _initializeWebDriverManager(
) -> bool: ) -> bool:
logger = logInstance().getLogger("AppInitializer") logger = logInstance().getLogger("AppInitializer")
@@ -66,11 +66,17 @@ def initializeWebDriverManager(
def initializeApp( def initializeApp(
) -> bool: ) -> bool:
"""
Initialize the application components
if not initializeLogManager(): Order:
LogManager -> ConfigManager -> WebDriverManager
"""
if not _initializeLogManager():
return False return False
if not initializeConfigManager(): if not _initializeConfigManager():
return False return False
if not initializeWebDriverManager(): if not _initializeWebDriverManager():
return False return False
return True return True
+8 -11
View File
@@ -9,14 +9,17 @@ See the LICENSE file for details.
""" """
import platform import platform
from PySide6.QtCore import (
Qt,
QTimer
)
from PySide6.QtGui import ( from PySide6.QtGui import (
QIcon, QFont QFont,
QIcon
) )
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QDialog, QApplication QApplication,
) QDialog
from PySide6.QtCore import (
QTimer, Qt
) )
from gui.ALVersionInfo import ( from gui.ALVersionInfo import (
@@ -38,7 +41,6 @@ class ALAboutDialog(QDialog, Ui_ALAboutDialog):
self.modifyUi() self.modifyUi()
self.connectSignals() self.connectSignals()
def modifyUi( def modifyUi(
self self
): ):
@@ -51,14 +53,12 @@ class ALAboutDialog(QDialog, Ui_ALAboutDialog):
self.AboutInfoBrowser.setFont(browser_font) self.AboutInfoBrowser.setFont(browser_font)
self.AboutInfoBrowser.setTextInteractionFlags(Qt.TextBrowserInteraction) self.AboutInfoBrowser.setTextInteractionFlags(Qt.TextBrowserInteraction)
def connectSignals( def connectSignals(
self self
): ):
self.CopyButton.clicked.connect(self.copyAboutInfo) self.CopyButton.clicked.connect(self.copyAboutInfo)
def generateAboutText( def generateAboutText(
self self
) -> str: ) -> str:
@@ -91,7 +91,6 @@ GitHub: <a href="https://www.github.com/KenanZhu" style="text-decoration: none;"
""" """
return about_text return about_text
def getOSInfo( def getOSInfo(
self self
): ):
@@ -123,7 +122,6 @@ GitHub: <a href="https://www.github.com/KenanZhu" style="text-decoration: none;"
'architecture': architecture 'architecture': architecture
} }
def getQtVersion( def getQtVersion(
self self
): ):
@@ -134,7 +132,6 @@ GitHub: <a href="https://www.github.com/KenanZhu" style="text-decoration: none;"
except: except:
return "Unknown" return "Unknown"
def copyAboutInfo( def copyAboutInfo(
self self
): ):
+119 -133
View File
@@ -116,7 +116,6 @@ class ALScriptHighlighter(QSyntaxHighlighter):
commentFmt.setFontItalic(True) commentFmt.setFontItalic(True)
self._rules.append((r"--[^\n]*", commentFmt)) self._rules.append((r"--[^\n]*", commentFmt))
def highlightBlock( def highlightBlock(
self, self,
text text
@@ -169,7 +168,7 @@ class ALAutoScriptEditDialog(QDialog):
): ):
super().__init__(parent) super().__init__(parent)
self._fontSize = 13 self._fontSize = 21
self._mockWidgets = {} self._mockWidgets = {}
self.setupUi() self.setupUi()
@@ -181,7 +180,6 @@ class ALAutoScriptEditDialog(QDialog):
if mockData: if mockData:
self.setMockData(mockData) self.setMockData(mockData)
def setupUi( def setupUi(
self self
): ):
@@ -243,7 +241,7 @@ class ALAutoScriptEditDialog(QDialog):
"}" "}"
) )
layout.addWidget(self.textEdit) layout.addWidget(self.textEdit)
self._createButtonPanel(layout) self.createButtonPanel(layout)
self.btnBox = QDialogButtonBox( self.btnBox = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Ok |
QDialogButtonBox.StandardButton.Cancel QDialogButtonBox.StandardButton.Cancel
@@ -252,8 +250,7 @@ class ALAutoScriptEditDialog(QDialog):
self.btnBox.button(QDialogButtonBox.StandardButton.Cancel).setText("取消") self.btnBox.button(QDialogButtonBox.StandardButton.Cancel).setText("取消")
layout.addWidget(self.btnBox) layout.addWidget(self.btnBox)
def createButtonPanel(
def _createButtonPanel(
self, self,
parent_layout parent_layout
): ):
@@ -273,11 +270,11 @@ class ALAutoScriptEditDialog(QDialog):
("结束 (end)", "end"), ("结束 (end)", "end"),
("跳过 (pass)", "-- pass"), ("跳过 (pass)", "-- pass"),
] ]
self._addButtonsToGrid(basicLayout, controlButtons, 0, 0, 3) self.addButtonsToGrid(basicLayout, controlButtons, 0, 0, 3)
assignButtons = [ assignButtons = [
("赋值 (=)", " = "), ("赋值 (=)", " = "),
] ]
self._addButtonsToGrid(basicLayout, assignButtons, 1, 2, 3) self.addButtonsToGrid(basicLayout, assignButtons, 1, 2, 3)
tabWidget.addTab(basicWidget, "基本语法") tabWidget.addTab(basicWidget, "基本语法")
operatorWidget = QWidget() operatorWidget = QWidget()
operatorLayout = QGridLayout(operatorWidget) operatorLayout = QGridLayout(operatorWidget)
@@ -288,7 +285,7 @@ class ALAutoScriptEditDialog(QDialog):
("加 (+)", " + "), ("加 (+)", " + "),
("减 (-)", " - "), ("减 (-)", " - "),
] ]
self._addButtonsToGrid(operatorLayout, arithmeticButtons, 0, 0, 3) self.addButtonsToGrid(operatorLayout, arithmeticButtons, 0, 0, 3)
compareButtons = [ compareButtons = [
("等于 (==)", " == "), ("等于 (==)", " == "),
("不等于 (~=)", " ~= "), ("不等于 (~=)", " ~= "),
@@ -297,12 +294,12 @@ class ALAutoScriptEditDialog(QDialog):
("大于等于 (>=)", " >= "), ("大于等于 (>=)", " >= "),
("小于等于 (<=)", " <= "), ("小于等于 (<=)", " <= "),
] ]
self._addButtonsToGrid(operatorLayout, compareButtons, 1, 0, 3) self.addButtonsToGrid(operatorLayout, compareButtons, 1, 0, 3)
logic_buttons = [ logic_buttons = [
("且 (and)", " and "), ("且 (and)", " and "),
("或 (or)", " or "), ("或 (or)", " or "),
] ]
self._addButtonsToGrid(operatorLayout, logic_buttons, 2, 0, 3) self.addButtonsToGrid(operatorLayout, logic_buttons, 2, 0, 3)
tabWidget.addTab(operatorWidget, "运算符") tabWidget.addTab(operatorWidget, "运算符")
literalWidget = QWidget() literalWidget = QWidget()
literalLayout = QGridLayout(literalWidget) literalLayout = QGridLayout(literalWidget)
@@ -313,18 +310,18 @@ class ALAutoScriptEditDialog(QDialog):
("真 (true)", "true"), ("真 (true)", "true"),
("假 (false)", "false"), ("假 (false)", "false"),
] ]
self._addButtonsToGrid(literalLayout, bool_buttons, 0, 0, 3) self.addButtonsToGrid(literalLayout, bool_buttons, 0, 0, 3)
dateTimeButtons = [ dateTimeButtons = [
("日期", '"2099-01-01"'), ("日期", '"2099-01-01"'),
("时间", '"00:00"'), ("时间", '"00:00"'),
] ]
self._addButtonsToGrid(literalLayout, dateTimeButtons, 1, 0, 3) self.addButtonsToGrid(literalLayout, dateTimeButtons, 1, 0, 3)
hintButtons = [ hintButtons = [
("字符串", '"请输入文本"'), ("字符串", '"请输入文本"'),
("数字", "123"), ("数字", "123"),
("注释", "-- 请输入注释"), ("注释", "-- 请输入注释"),
] ]
self._addButtonsToGrid(literalLayout, hintButtons, 2, 0, 3) self.addButtonsToGrid(literalLayout, hintButtons, 2, 0, 3)
tabWidget.addTab(literalWidget, "字面量") tabWidget.addTab(literalWidget, "字面量")
varWidget = QWidget() varWidget = QWidget()
varLayout = QGridLayout(varWidget) varLayout = QGridLayout(varWidget)
@@ -334,9 +331,9 @@ class ALAutoScriptEditDialog(QDialog):
varButtons = [ varButtons = [
(display_name, name) for display_name, (name, _) in ALL_VARIABLES.items() (display_name, name) for display_name, (name, _) in ALL_VARIABLES.items()
] ]
self._addButtonsToGrid(varLayout, varButtons, 0, 0, 3) self.addButtonsToGrid(varLayout, varButtons, 0, 0, 3)
tabWidget.addTab(varWidget, "变量") tabWidget.addTab(varWidget, "变量")
mockPanel = self._createMockPanel() mockPanel = self.createMockPanel()
mockPanel.setMinimumWidth(260) mockPanel.setMinimumWidth(260)
splitter.addWidget(tabWidget) splitter.addWidget(tabWidget)
splitter.addWidget(mockPanel) splitter.addWidget(mockPanel)
@@ -345,8 +342,7 @@ class ALAutoScriptEditDialog(QDialog):
splitter.setSizes([530, 530]) splitter.setSizes([530, 530])
parent_layout.addWidget(splitter) parent_layout.addWidget(splitter)
def addButtonsToGrid(
def _addButtonsToGrid(
self, self,
grid_layout, grid_layout,
buttons, buttons,
@@ -361,7 +357,7 @@ class ALAutoScriptEditDialog(QDialog):
for btn_text, template in buttons: for btn_text, template in buttons:
btn = QPushButton(btn_text) btn = QPushButton(btn_text)
btn.setProperty("template", template) btn.setProperty("template", template)
btn.clicked.connect(self._insertTemplate) btn.clicked.connect(self.insertTemplate)
btn.setFixedWidth(100) btn.setFixedWidth(100)
btn.setFixedHeight(25) btn.setFixedHeight(25)
btn.setToolTip(f"插入: {template}") btn.setToolTip(f"插入: {template}")
@@ -371,22 +367,7 @@ class ALAutoScriptEditDialog(QDialog):
col = start_col col = start_col
row += 1 row += 1
@Slot() def createMockPanel(
def _insertTemplate(
self
):
btn = self.sender()
if not isinstance(btn, QPushButton):
return
template = btn.property("template")
if not template:
return
cursor = self.textEdit.textCursor()
cursor.insertText(template)
def _createMockPanel(
self self
) -> QGroupBox: ) -> QGroupBox:
@@ -397,14 +378,13 @@ class ALAutoScriptEditDialog(QDialog):
self._mockWidgets = {} self._mockWidgets = {}
for name, var_type, key_path, display_name in _TARGET_VAR_DEFS: for name, var_type, key_path, display_name in _TARGET_VAR_DEFS:
default = _MOCK_TYPE_VALUES.get(var_type, "") default = _MOCK_TYPE_VALUES.get(var_type, "")
widget = self._makeMockInput(var_type, default) widget = self.makeMockInput(var_type, default)
label = QLabel(f"{display_name}: {name}({var_type})") label = QLabel(f"{display_name}: {name}({var_type})")
form.addRow(label, widget) form.addRow(label, widget)
self._mockWidgets[name] = (widget, var_type, key_path) self._mockWidgets[name] = (widget, var_type, key_path)
return group return group
def makeMockInput(
def _makeMockInput(
self, self,
var_type: str, var_type: str,
default default
@@ -447,7 +427,6 @@ class ALAutoScriptEditDialog(QDialog):
w.setText(str(default)) w.setText(str(default))
return w return w
def getMockData( def getMockData(
self self
) -> dict: ) -> dict:
@@ -455,14 +434,13 @@ class ALAutoScriptEditDialog(QDialog):
data = {} data = {}
for name, var_type, key_path, display_name in _TARGET_VAR_DEFS: for name, var_type, key_path, display_name in _TARGET_VAR_DEFS:
widget, _, _ = self._mockWidgets[name] widget, _, _ = self._mockWidgets[name]
value = self._getMockValue(widget, var_type) value = self.getMockValue(widget, var_type)
d = data d = data
for key in key_path[:-1]: for key in key_path[:-1]:
d = d.setdefault(key, {}) d = d.setdefault(key, {})
d[key_path[-1]] = value d[key_path[-1]] = value
return data return data
def setMockData( def setMockData(
self, self,
data: dict data: dict
@@ -478,10 +456,9 @@ class ALAutoScriptEditDialog(QDialog):
except (KeyError, TypeError): except (KeyError, TypeError):
continue continue
widget, _, _ = self._mockWidgets[name] widget, _, _ = self._mockWidgets[name]
self._setMockValue(widget, var_type, d) self.setMockValue(widget, var_type, d)
def getMockValue(
def _getMockValue(
self, self,
widget: QWidget, widget: QWidget,
var_type: str var_type: str
@@ -499,8 +476,7 @@ class ALAutoScriptEditDialog(QDialog):
return widget.value() return widget.value()
return widget.text() return widget.text()
def setMockValue(
def _setMockValue(
self, self,
widget: QWidget, widget: QWidget,
var_type: str, var_type: str,
@@ -520,6 +496,103 @@ class ALAutoScriptEditDialog(QDialog):
else: else:
widget.setText(str(value)) widget.setText(str(value))
def connectSignals(
self
):
self.btnBox.accepted.connect(self.accept)
self.btnBox.rejected.connect(self.reject)
self.orchBtn.clicked.connect(self.onOpenOrchDialog)
self.debugBtn.clicked.connect(self.onDebugRun)
self.zoomInBtn.clicked.connect(self.onZoomIn)
self.zoomOutBtn.clicked.connect(self.onZoomOut)
self.zoomResetBtn.clicked.connect(self.onZoomReset)
self.copyBtn.clicked.connect(self.onCopy)
def getScript(
self
) -> str:
return self.textEdit.toPlainText()
def updateFontSize(
self
):
self.textEdit.setStyleSheet(
"QPlainTextEdit {"
" font-family: 'Courier New', 'Consolas', monospace;"
f" font-size: {self._fontSize}px;"
"}"
)
self.zoomLabel.setText(f"{self._fontSize}px")
@Slot()
def insertTemplate(
self
):
btn = self.sender()
if not isinstance(btn, QPushButton):
return
template = btn.property("template")
if not template:
return
cursor = self.textEdit.textCursor()
cursor.insertText(template)
@Slot()
def onZoomIn(
self
):
self._fontSize = min(self._fontSize + 2, 40)
self.updateFontSize()
@Slot()
def onZoomOut(
self
):
self._fontSize = max(self._fontSize - 2, 8)
self.updateFontSize()
@Slot()
def onZoomReset(
self
):
self._fontSize = 21
self.updateFontSize()
@Slot()
def onCopy(
self
):
clipboard = QApplication.clipboard()
clipboard.setText(self.textEdit.toPlainText())
original = self.copyBtn.text()
self.copyBtn.setText("已复制")
self.copyBtn.setEnabled(False)
QTimer.singleShot(2000, lambda: (
self.copyBtn.setText(original),
self.copyBtn.setEnabled(True)
))
@Slot()
def onOpenOrchDialog(
self
):
from gui.ALAutoScriptOrchDialog import ALAutoScriptOrchDialog
dlg = ALAutoScriptOrchDialog(self)
if dlg.exec() == QDialog.DialogCode.Accepted:
script = dlg.getScript()
if script:
cursor = self.textEdit.textCursor()
cursor.insertText(script)
dlg.deleteLater()
@Slot() @Slot()
def onDebugRun( def onDebugRun(
@@ -556,90 +629,3 @@ class ALAutoScriptEditDialog(QDialog):
dlg = _DebugResultDialog(changes, self) dlg = _DebugResultDialog(changes, self)
dlg.exec() dlg.exec()
dlg.deleteLater() dlg.deleteLater()
def connectSignals(
self
):
self.btnBox.accepted.connect(self.accept)
self.btnBox.rejected.connect(self.reject)
self.orchBtn.clicked.connect(self.onOpenOrchDialog)
self.debugBtn.clicked.connect(self.onDebugRun)
self.zoomInBtn.clicked.connect(self.onZoomIn)
self.zoomOutBtn.clicked.connect(self.onZoomOut)
self.zoomResetBtn.clicked.connect(self.onZoomReset)
self.copyBtn.clicked.connect(self.onCopy)
def getScript(
self
) -> str:
return self.textEdit.toPlainText()
def updateFontSize(
self
):
self.textEdit.setStyleSheet(
"QPlainTextEdit {"
" font-family: 'Courier New', 'Consolas', monospace;"
f" font-size: {self._fontSize}px;"
"}"
)
self.zoomLabel.setText(f"{self._fontSize}px")
@Slot()
def onZoomIn(
self
):
self._fontSize = min(self._fontSize + 2, 40)
self.updateFontSize()
@Slot()
def onZoomOut(
self
):
self._fontSize = max(self._fontSize - 2, 8)
self.updateFontSize()
@Slot()
def onZoomReset(
self
):
self._fontSize = 13
self.updateFontSize()
@Slot()
def onCopy(
self
):
clipboard = QApplication.clipboard()
clipboard.setText(self.textEdit.toPlainText())
original = self.copyBtn.text()
self.copyBtn.setText("已复制")
self.copyBtn.setEnabled(False)
QTimer.singleShot(2000, lambda: (
self.copyBtn.setText(original),
self.copyBtn.setEnabled(True)
))
@Slot()
def onOpenOrchDialog(
self
):
from gui.ALAutoScriptOrchDialog import ALAutoScriptOrchDialog
dlg = ALAutoScriptOrchDialog(self)
if dlg.exec() == QDialog.DialogCode.Accepted:
script = dlg.getScript()
if script:
cursor = self.textEdit.textCursor()
cursor.insertText(script)
dlg.deleteLater()
+15 -29
View File
@@ -47,7 +47,6 @@ class ConditionalBlock(QGroupBox):
self.connectSignals() self.connectSignals()
self.addInitialConditionRow() self.addInitialConditionRow()
def setupUi( def setupUi(
self self
): ):
@@ -103,7 +102,6 @@ class ConditionalBlock(QGroupBox):
mainLayout.addWidget(self.addActionBtn) mainLayout.addWidget(self.addActionBtn)
self.setUpdatesEnabled(True) self.setUpdatesEnabled(True)
def connectSignals( def connectSignals(
self self
): ):
@@ -112,7 +110,6 @@ class ConditionalBlock(QGroupBox):
self.addCondBtn.clicked.connect(self.addConditionRow) self.addCondBtn.clicked.connect(self.addConditionRow)
self.addActionBtn.clicked.connect(self.addActionStep) self.addActionBtn.clicked.connect(self.addActionStep)
def addInitialConditionRow( def addInitialConditionRow(
self self
): ):
@@ -124,7 +121,6 @@ class ConditionalBlock(QGroupBox):
self._conditionRows.append(row) self._conditionRows.append(row)
self.condRowsLayout.addWidget(row) self.condRowsLayout.addWidget(row)
def addConditionRow( def addConditionRow(
self self
): ):
@@ -137,7 +133,6 @@ class ConditionalBlock(QGroupBox):
self._conditionRows.append(row) self._conditionRows.append(row)
self.condRowsLayout.addWidget(row) self.condRowsLayout.addWidget(row)
def removeConditionRow( def removeConditionRow(
self, self,
row: ConditionRowFrame row: ConditionRowFrame
@@ -149,7 +144,6 @@ class ConditionalBlock(QGroupBox):
row.hide() row.hide()
row.deleteLater() row.deleteLater()
def addActionStep( def addActionStep(
self self
): ):
@@ -159,7 +153,6 @@ class ConditionalBlock(QGroupBox):
self._actionWidgets.append(step) self._actionWidgets.append(step)
self.actionsLayout.addWidget(step) self.actionsLayout.addWidget(step)
def removeActionStep( def removeActionStep(
self, self,
step: ActionStepFrame step: ActionStepFrame
@@ -171,48 +164,31 @@ class ConditionalBlock(QGroupBox):
step.hide() step.hide()
step.deleteLater() step.deleteLater()
@Slot(int)
def onTypeChanged(
self,
_idx
):
isCond = self.typeCombo.currentData() in ("IF", "ELSE IF")
self.conditionWidget.setVisible(isCond)
self.actionLabel.setText(
"执行步骤:" if isCond else "ELSE 执行步骤:"
)
def getBlockType( def getBlockType(
self self
) -> str: ) -> str:
return self.typeCombo.currentData() return self.typeCombo.currentData()
def getConditionRows( def getConditionRows(
self self
): ):
return list(self._conditionRows) return list(self._conditionRows)
def getActionSteps( def getActionSteps(
self self
): ):
return list(self._actionWidgets) return list(self._actionWidgets)
def countActionSteps( def countActionSteps(
self self
) -> int: ) -> int:
return len(self._actionWidgets) return len(self._actionWidgets)
def toScript(
def toScriptLines(
self self
) -> list: ) -> list:
""" """
@@ -223,7 +199,7 @@ class ConditionalBlock(QGroupBox):
lines = [] lines = []
if blockType in ("IF", "ELSE IF"): if blockType in ("IF", "ELSE IF"):
condTexts = [ condTexts = [
r.toConditionText() for r in self._conditionRows if r.toConditionText() r.toScript() for r in self._conditionRows if r.toScript()
] ]
if not condTexts: if not condTexts:
condTexts = ["true"] condTexts = ["true"]
@@ -245,12 +221,11 @@ class ConditionalBlock(QGroupBox):
else: else:
lines.append("else") lines.append("else")
for step in self._actionWidgets: for step in self._actionWidgets:
scriptLine = step.toScriptLine() scriptLine = step.toScript()
if scriptLine: if scriptLine:
lines.append(scriptLine) lines.append(scriptLine)
return lines return lines
def refreshVarCombos( def refreshVarCombos(
self self
): ):
@@ -260,7 +235,6 @@ class ConditionalBlock(QGroupBox):
for step in self._actionWidgets: for step in self._actionWidgets:
step.refreshVarCombos() step.refreshVarCombos()
def setPrevBlockType( def setPrevBlockType(
self, self,
prevType: str | None prevType: str | None
@@ -278,3 +252,15 @@ class ConditionalBlock(QGroupBox):
item.setEnabled(shouldEnable) item.setEnabled(shouldEnable)
if prevType == "ELSE" and self.typeCombo.currentData() in ("ELSE IF", "ELSE"): if prevType == "ELSE" and self.typeCombo.currentData() in ("ELSE IF", "ELSE"):
self.typeCombo.setCurrentIndex(0) self.typeCombo.setCurrentIndex(0)
@Slot(int)
def onTypeChanged(
self,
_idx
):
isCond = self.typeCombo.currentData() in ("IF", "ELSE IF")
self.conditionWidget.setVisible(isCond)
self.actionLabel.setText(
"执行步骤:" if isCond else "ELSE 执行步骤:"
)
+5 -11
View File
@@ -42,7 +42,6 @@ class ALAutoScriptOrchDialog(QDialog):
self.addBlock() self.addBlock()
self.scrollLayout.addStretch() self.scrollLayout.addStretch()
def setupUi( def setupUi(
self self
): ):
@@ -70,7 +69,6 @@ class ALAutoScriptOrchDialog(QDialog):
self.btnBox.button(QDialogButtonBox.StandardButton.Cancel).setText("取消") self.btnBox.button(QDialogButtonBox.StandardButton.Cancel).setText("取消")
mainLayout.addWidget(self.btnBox) mainLayout.addWidget(self.btnBox)
def connectSignals( def connectSignals(
self self
): ):
@@ -79,8 +77,7 @@ class ALAutoScriptOrchDialog(QDialog):
self.btnBox.rejected.connect(self.reject) self.btnBox.rejected.connect(self.reject)
self.addBlockBtn.clicked.connect(self.addBlock) self.addBlockBtn.clicked.connect(self.addBlock)
def updateBlockTypeRestrictions(
def _updateBlockTypeRestrictions(
self self
): ):
@@ -89,7 +86,6 @@ class ALAutoScriptOrchDialog(QDialog):
block.setPrevBlockType(prevType) block.setPrevBlockType(prevType)
prevType = block.getBlockType() prevType = block.getBlockType()
def addBlock( def addBlock(
self self
): ):
@@ -98,10 +94,10 @@ class ALAutoScriptOrchDialog(QDialog):
len(self._blocks), self._varMgr, parent=self len(self._blocks), self._varMgr, parent=self
) )
block.deleteBlockBtn.clicked.connect(lambda: self.removeBlock(block)) block.deleteBlockBtn.clicked.connect(lambda: self.removeBlock(block))
block.typeCombo.currentIndexChanged.connect(self._updateBlockTypeRestrictions) block.typeCombo.currentIndexChanged.connect(self.updateBlockTypeRestrictions)
block.addActionStep() block.addActionStep()
self._blocks.append(block) self._blocks.append(block)
self._updateBlockTypeRestrictions() self.updateBlockTypeRestrictions()
if self.scrollLayout.count() > 0: if self.scrollLayout.count() > 0:
lastItem = self.scrollLayout.itemAt( lastItem = self.scrollLayout.itemAt(
self.scrollLayout.count() - 1 self.scrollLayout.count() - 1
@@ -113,7 +109,6 @@ class ALAutoScriptOrchDialog(QDialog):
return return
self.scrollLayout.addWidget(block) self.scrollLayout.addWidget(block)
def removeBlock( def removeBlock(
self, self,
block: ConditionalBlock block: ConditionalBlock
@@ -135,8 +130,7 @@ class ALAutoScriptOrchDialog(QDialog):
else: else:
blk.typeCombo.setEnabled(True) blk.typeCombo.setEnabled(True)
blk.refreshVarCombos() blk.refreshVarCombos()
self._updateBlockTypeRestrictions() self.updateBlockTypeRestrictions()
def getScript( def getScript(
self self
@@ -151,7 +145,7 @@ class ALAutoScriptOrchDialog(QDialog):
blockType = block.getBlockType() blockType = block.getBlockType()
if blockType == "IF" and prevType is not None: if blockType == "IF" and prevType is not None:
parts.append("end") parts.append("end")
lines = block.toScriptLines() lines = block.toScript()
parts.extend(lines) parts.extend(lines)
prevType = blockType prevType = blockType
if self._blocks and self._blocks[0].getBlockType() == "IF": if self._blocks and self._blocks[0].getBlockType() == "IF":
+188 -218
View File
@@ -95,181 +95,6 @@ DATE_OFFSET_UNITS = [
] ]
class VariableManager(QObject):
def __init__(
self,
parent = None
):
super().__init__(parent)
self._vars = []
self._nameMap = {}
self._initPresetVars()
def _initPresetVars(
self
):
for p in PRESET_VARIABLES:
entry = {"name": p["name"], "type": p["type"], "display": p["display"]}
self._vars.append(entry)
self._nameMap[p["name"]] = entry
def getInfoByName(
self,
name: str
):
return self._nameMap.get(name.upper().strip())
def populateCombo(
self,
combo: QComboBox
):
currentData = combo.currentData()
combo.blockSignals(True)
combo.clear()
for entry in self._vars:
combo.addItem(
entry["display"],
(entry["name"], entry["type"])
)
if currentData:
for i in range(combo.count()):
d = combo.itemData(i)
if d and d[0] == currentData[0]:
combo.setCurrentIndex(i)
break
combo.blockSignals(False)
def findExactNameEntry(
self,
combo: QComboBox,
name: str
) -> int:
name = name.upper().strip()
for i in range(combo.count()):
d = combo.itemData(i)
if d and len(d) >= 1 and d[0].upper().strip() == name:
return i
return -1
def makeValueWidget(
var_type: str,
parent: QWidget = None
) -> QWidget:
if var_type == "Int":
w = QSpinBox(parent)
w.setRange(-999999, 999999)
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "Float":
w = QDoubleSpinBox(parent)
w.setRange(-999999.0, 999999.0)
w.setDecimals(2)
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "String":
w = QLineEdit(parent)
w.setPlaceholderText("输入值")
w.setFixedHeight(25)
w.setMinimumWidth(120)
return w
if var_type == "Boolean":
w = QComboBox(parent)
w.addItem("是 (true)", "true")
w.addItem("否 (false)", "false")
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "Date":
return _DateInputContainer(parent)
if var_type == "Time":
return _TimeInputContainer(parent)
w = QLineEdit(parent)
w.setPlaceholderText("输入值")
w.setFixedHeight(25)
w.setMinimumWidth(120)
return w
def makeOffsetWidget(
var_type: str,
parent: QWidget = None
) -> QWidget:
if var_type == "Int":
w = QSpinBox(parent)
w.setRange(-999999, 999999)
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "Float":
w = QDoubleSpinBox(parent)
w.setRange(-999999.0, 999999.0)
w.setDecimals(2)
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "Date":
return _DateOffsetContainer(parent)
if var_type == "Time":
return _TimeOffsetContainer(parent)
w = QLabel("(不支持该操作)", parent)
w.setFixedHeight(25)
return w
def makeVarRefCombo(
parent: QWidget = None
) -> QComboBox:
cb = QComboBox(parent)
cb.setFixedHeight(25)
cb.setMinimumWidth(120)
cb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
return cb
def makeComboWidget(
items,
min_width: int = 80,
parent: QWidget = None
) -> QComboBox:
cb = QComboBox(parent)
for display, data in items:
cb.addItem(display, data)
cb.setFixedHeight(25)
cb.setMinimumWidth(min_width)
return cb
def makeLabel(
text: str,
parent: QWidget = None,
width: int = None
) -> QLabel:
lbl = QLabel(text, parent)
lbl.setFixedHeight(25)
if width:
lbl.setFixedWidth(width)
return lbl
class _DateInputContainer(QWidget): class _DateInputContainer(QWidget):
def __init__( def __init__(
@@ -281,7 +106,6 @@ class _DateInputContainer(QWidget):
self._dynamicItems = {} # index -> raw expression, for one-way parsed items self._dynamicItems = {} # index -> raw expression, for one-way parsed items
self.setupUi() self.setupUi()
def setupUi( def setupUi(
self self
): ):
@@ -327,7 +151,6 @@ class _DateInputContainer(QWidget):
return self._relCombo.currentText() return self._relCombo.currentText()
return self._dateEdit.date().toString("yyyy-MM-dd") return self._dateEdit.date().toString("yyyy-MM-dd")
def setValue( def setValue(
self, self,
expr: str expr: str
@@ -392,14 +215,12 @@ class _TimeInputContainer(QWidget):
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self._timeEdit) layout.addWidget(self._timeEdit)
def getValue( def getValue(
self self
) -> str: ) -> str:
return self._timeEdit.time().toString("HH:mm") return self._timeEdit.time().toString("HH:mm")
def setValue( def setValue(
self, self,
expr: str expr: str
@@ -443,14 +264,12 @@ class _DateOffsetContainer(QWidget):
layout.addWidget(self._unitCombo) layout.addWidget(self._unitCombo)
layout.addStretch() layout.addStretch()
def getValue( def getValue(
self self
) -> str: ) -> str:
return str(self.getOffsetDays()) return str(self.getOffsetDays())
def setValue( def setValue(
self, self,
expr: str expr: str
@@ -462,7 +281,6 @@ class _DateOffsetContainer(QWidget):
except ValueError: except ValueError:
pass pass
def getOffsetDays( def getOffsetDays(
self self
) -> int: ) -> int:
@@ -477,7 +295,6 @@ class _DateOffsetContainer(QWidget):
return val * 365 return val * 365
return val return val
def getRawValue( def getRawValue(
self self
) -> str: ) -> str:
@@ -502,14 +319,12 @@ class _TimeOffsetContainer(QWidget):
layout.setContentsMargins(0, 0, 0, 0) layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self._spinBox) layout.addWidget(self._spinBox)
def getValue( def getValue(
self self
) -> str: ) -> str:
return str(self.getOffsetHours()) return str(self.getOffsetHours())
def setValue( def setValue(
self, self,
expr: str expr: str
@@ -521,14 +336,12 @@ class _TimeOffsetContainer(QWidget):
except ValueError: except ValueError:
pass pass
def getOffsetHours( def getOffsetHours(
self self
) -> int: ) -> int:
return self._spinBox.value() return self._spinBox.value()
def getRawValue( def getRawValue(
self self
) -> str: ) -> str:
@@ -536,6 +349,172 @@ class _TimeOffsetContainer(QWidget):
return str(self._spinBox.value()) return str(self._spinBox.value())
class VariableManager(QObject):
def __init__(
self,
parent = None
):
super().__init__(parent)
self._vars = []
self._nameMap = {}
self._initPresetVars()
def _initPresetVars(
self
):
for p in PRESET_VARIABLES:
entry = {"name": p["name"], "type": p["type"], "display": p["display"]}
self._vars.append(entry)
self._nameMap[p["name"]] = entry
def getInfoByName(
self,
name: str
):
return self._nameMap.get(name.upper().strip())
def populateCombo(
self,
combo: QComboBox
):
currentData = combo.currentData()
combo.blockSignals(True)
combo.clear()
for entry in self._vars:
combo.addItem(
entry["display"],
(entry["name"], entry["type"])
)
if currentData:
for i in range(combo.count()):
d = combo.itemData(i)
if d and d[0] == currentData[0]:
combo.setCurrentIndex(i)
break
combo.blockSignals(False)
def findExactNameEntry(
self,
combo: QComboBox,
name: str
) -> int:
name = name.upper().strip()
for i in range(combo.count()):
d = combo.itemData(i)
if d and len(d) >= 1 and d[0].upper().strip() == name:
return i
return -1
def makeValueWidget(
var_type: str,
parent: QWidget = None
) -> QWidget:
if var_type == "Int":
w = QSpinBox(parent)
w.setRange(-999999, 999999)
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "Float":
w = QDoubleSpinBox(parent)
w.setRange(-999999.0, 999999.0)
w.setDecimals(2)
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "String":
w = QLineEdit(parent)
w.setPlaceholderText("输入值")
w.setFixedHeight(25)
w.setMinimumWidth(120)
return w
if var_type == "Boolean":
w = QComboBox(parent)
w.addItem("是 (true)", "true")
w.addItem("否 (false)", "false")
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "Date":
return _DateInputContainer(parent)
if var_type == "Time":
return _TimeInputContainer(parent)
w = QLineEdit(parent)
w.setPlaceholderText("输入值")
w.setFixedHeight(25)
w.setMinimumWidth(120)
return w
def makeOffsetWidget(
var_type: str,
parent: QWidget = None
) -> QWidget:
if var_type == "Int":
w = QSpinBox(parent)
w.setRange(-999999, 999999)
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "Float":
w = QDoubleSpinBox(parent)
w.setRange(-999999.0, 999999.0)
w.setDecimals(2)
w.setFixedHeight(25)
w.setMinimumWidth(100)
return w
if var_type == "Date":
return _DateOffsetContainer(parent)
if var_type == "Time":
return _TimeOffsetContainer(parent)
w = QLabel("(不支持该操作)", parent)
w.setFixedHeight(25)
return w
def makeVarRefCombo(
parent: QWidget = None
) -> QComboBox:
cb = QComboBox(parent)
cb.setFixedHeight(25)
cb.setMinimumWidth(120)
cb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
return cb
def makeComboWidget(
items,
min_width: int = 80,
parent: QWidget = None
) -> QComboBox:
cb = QComboBox(parent)
for display, data in items:
cb.addItem(display, data)
cb.setFixedHeight(25)
cb.setMinimumWidth(min_width)
return cb
def makeLabel(
text: str,
parent: QWidget = None,
width: int = None
) -> QLabel:
lbl = QLabel(text, parent)
lbl.setFixedHeight(25)
if width:
lbl.setFixedWidth(width)
return lbl
def getValueFromWidget( def getValueFromWidget(
w: QWidget w: QWidget
) -> str: ) -> str:
@@ -556,8 +535,7 @@ def getValueFromWidget(
return w.text() return w.text()
return "" return ""
def setValueToWidget(
def setWidgetValue(
w: QWidget, w: QWidget,
var_type: str, var_type: str,
expr: str expr: str
@@ -619,7 +597,6 @@ def setWidgetValue(
inner = inner[1:-1].replace('\\"', '"') inner = inner[1:-1].replace('\\"', '"')
w.setText(inner) w.setText(inner)
def encodeValueStr( def encodeValueStr(
raw_value: str, raw_value: str,
var_type: str var_type: str
@@ -632,7 +609,7 @@ def encodeValueStr(
""" """
if var_type in ("Date", "Time"): if var_type in ("Date", "Time"):
return _encodeDateOrTime(str(raw_value), var_type) return encodeDateOrTime(str(raw_value), var_type)
if isinstance(raw_value, bool): if isinstance(raw_value, bool):
return "true" if raw_value else "false" return "true" if raw_value else "false"
s = str(raw_value) s = str(raw_value)
@@ -648,8 +625,7 @@ def encodeValueStr(
return f'"{escaped}"' return f'"{escaped}"'
return s return s
def encodeDateOrTime(
def _encodeDateOrTime(
raw_value: str, raw_value: str,
var_type: str var_type: str
) -> str: ) -> str:
@@ -707,7 +683,6 @@ def _encodeDateOrTime(
return s return s
return f'"{s}"' return f'"{s}"'
def stripOuterParens( def stripOuterParens(
s: str s: str
) -> str: ) -> str:
@@ -725,12 +700,10 @@ def stripOuterParens(
return s[1:-1].strip() return s[1:-1].strip()
return s return s
# Pre-compiled patterns for detecting arithmetic expressions (A + B / A - B) # Pre-compiled patterns for detecting arithmetic expressions (A + B / A - B)
_RE_ARITH_SPACED = re.compile(r'^(.+?)\s+([+-])\s+(.+)$') _RE_ARITH_SPACED = re.compile(r'^(.+?)\s+([+-])\s+(.+)$')
_RE_ARITH_NOSPACE = re.compile(r'^([A-Za-z_]\w*)([+-])(\d+|[A-Za-z_]\w*)$') _RE_ARITH_NOSPACE = re.compile(r'^([A-Za-z_]\w*)([+-])(\d+|[A-Za-z_]\w*)$')
def isArithExpr( def isArithExpr(
expr: str expr: str
) -> bool: ) -> bool:
@@ -741,7 +714,6 @@ def isArithExpr(
s = expr.strip() s = expr.strip()
return bool(_RE_ARITH_SPACED.match(s) or _RE_ARITH_NOSPACE.match(s)) return bool(_RE_ARITH_SPACED.match(s) or _RE_ARITH_NOSPACE.match(s))
def isVarReference( def isVarReference(
expr: str expr: str
) -> bool: ) -> bool:
@@ -764,27 +736,7 @@ def isVarReference(
return False return False
return bool(re.match(r"^[A-Z_][A-Z0-9_]*$", up)) return bool(re.match(r"^[A-Z_][A-Z0-9_]*$", up))
def isInsideLiteral(
def findOperatorIn(
text: str,
operators: list
) -> tuple[int, str] | None:
for op in operators:
op_upper = op.upper()
start = 0
while True:
idx = text.upper().find(op_upper, start)
if idx < 0:
break
if _isInsideLiteral(text, idx):
start = idx + 1
continue
return (idx, op)
return None
def _isInsideLiteral(
text: str, text: str,
pos: int pos: int
) -> bool: ) -> bool:
@@ -799,3 +751,21 @@ def _isInsideLiteral(
elif ch == '"' and not in_single: elif ch == '"' and not in_single:
in_double = not in_double in_double = not in_double
return in_single or in_double return in_single or in_double
def findOperatorIn(
text: str,
operators: list
) -> tuple[int, str] | None:
for op in operators:
op_upper = op.upper()
start = 0
while True:
idx = text.upper().find(op_upper, start)
if idx < 0:
break
if isInsideLiteral(text, idx):
start = idx + 1
continue
return (idx, op)
return None
+110 -120
View File
@@ -58,7 +58,6 @@ class ConditionRowFrame(QFrame):
self.setupUi() self.setupUi()
self.connectSignals() self.connectSignals()
def setupUi( def setupUi(
self self
): ):
@@ -90,15 +89,7 @@ class ConditionRowFrame(QFrame):
layout.addWidget(self._compTypeCombo) layout.addWidget(self._compTypeCombo)
self.rhsStack = QStackedWidget(self) self.rhsStack = QStackedWidget(self)
self.rhsStack.setFixedHeight(25) self.rhsStack.setFixedHeight(25)
self.literalStack = QStackedWidget(self) self.initLiteralStack()
self.literalStack.setFixedHeight(25)
self.literalWidgets = {}
for vt in VAR_TYPE_ORDER:
w = makeValueWidget(vt, self.literalStack)
self.literalWidgets[vt] = w
self.literalStack.addWidget(w)
self.literalStack.setCurrentWidget(self.literalWidgets.get("String"))
self.rhsStack.addWidget(self.literalStack)
self.rhsVarCombo = makeVarRefCombo(self) self.rhsVarCombo = makeVarRefCombo(self)
self.rhsStack.addWidget(self.rhsVarCombo) self.rhsStack.addWidget(self.rhsVarCombo)
self.rhsStack.setCurrentIndex(0) self.rhsStack.setCurrentIndex(0)
@@ -113,7 +104,6 @@ class ConditionRowFrame(QFrame):
layout.addStretch() layout.addStretch()
self.setUpdatesEnabled(True) self.setUpdatesEnabled(True)
def populateLeftVarCombo( def populateLeftVarCombo(
self self
): ):
@@ -136,13 +126,25 @@ class ConditionRowFrame(QFrame):
self.leftVarCombo.setCurrentIndex(ci) self.leftVarCombo.setCurrentIndex(ci)
break break
def populateRHSVarCombo(
def populateRhsVarCombo(
self self
): ):
self._varMgr.populateCombo(self.rhsVarCombo) self._varMgr.populateCombo(self.rhsVarCombo)
def initLiteralStack(
self
):
self.literalStack = QStackedWidget(self)
self.literalStack.setFixedHeight(25)
self._literalWidgets = {}
for vt in VAR_TYPE_ORDER:
w = makeValueWidget(vt, self.literalStack)
self._literalWidgets[vt] = w
self.literalStack.addWidget(w)
self.literalStack.setCurrentWidget(self._literalWidgets.get("String"))
self.rhsStack.addWidget(self.literalStack)
def connectSignals( def connectSignals(
self self
@@ -151,58 +153,22 @@ class ConditionRowFrame(QFrame):
self.leftVarCombo.currentIndexChanged.connect(self.onLeftVarChanged) self.leftVarCombo.currentIndexChanged.connect(self.onLeftVarChanged)
self._compTypeCombo.currentIndexChanged.connect(self.onCompTypeChanged) self._compTypeCombo.currentIndexChanged.connect(self.onCompTypeChanged)
@Slot(int)
def onLeftVarChanged(
self,
idx
):
self._rawRhsExpr = ""
if idx < 0:
return
data = self.leftVarCombo.itemData(idx)
if not data:
return
name, vartype = data
isBool = name in ("true", "false")
self._isBoolMode = isBool
self.opCombo.setVisible(not isBool)
self._compTypeCombo.setVisible(not isBool)
self.rhsStack.setVisible(not isBool)
if not isBool:
self.updateRhsLiteralWidget(vartype)
def updateRhsLiteralWidget(
self,
vartype: str
):
if vartype not in self.literalWidgets:
vartype = "String"
self.literalStack.setCurrentWidget(self.literalWidgets[vartype])
@Slot(int)
def onCompTypeChanged(
self,
idx
):
self._rawRhsExpr = ""
isVar = (self._compTypeCombo.currentData() == "variable")
self.rhsStack.setCurrentIndex(1 if isVar else 0)
if isVar:
self.populateRhsVarCombo()
def getLogic( def getLogic(
self self
) -> str: ) -> str:
return self.logicCombo.currentData() if self.logicCombo else "" return self.logicCombo.currentData() if self.logicCombo else ""
def updateRHSLiteralWidget(
self,
vartype: str
):
def toConditionText( if vartype not in self._literalWidgets:
vartype = "String"
self.literalStack.setCurrentWidget(self._literalWidgets[vartype])
def toScript(
self self
) -> str: ) -> str:
@@ -230,20 +196,53 @@ class ConditionRowFrame(QFrame):
if rhsText: if rhsText:
return f"{name} {opSym} {rhsText}" return f"{name} {opSym} {rhsText}"
return "" return ""
w = self.literalWidgets.get(vartype) w = self._literalWidgets.get(vartype)
if w: if w:
rawVal = getValueFromWidget(w) rawVal = getValueFromWidget(w)
encoded = encodeValueStr(rawVal, vartype) encoded = encodeValueStr(rawVal, vartype)
return f"{name} {opSym} {encoded}" return f"{name} {opSym} {encoded}"
return "" return ""
def refreshVarCombos( def refreshVarCombos(
self self
): ):
self.populateLeftVarCombo() self.populateLeftVarCombo()
self.populateRhsVarCombo() self.populateRHSVarCombo()
@Slot(int)
def onLeftVarChanged(
self,
idx
):
self._rawRhsExpr = ""
if idx < 0:
return
data = self.leftVarCombo.itemData(idx)
if not data:
return
name, vartype = data
isBool = name in ("true", "false")
self._isBoolMode = isBool
self.opCombo.setVisible(not isBool)
self._compTypeCombo.setVisible(not isBool)
self.rhsStack.setVisible(not isBool)
if not isBool:
self.updateRHSLiteralWidget(vartype)
@Slot(int)
def onCompTypeChanged(
self,
idx
):
self._rawRhsExpr = ""
isVar = (self._compTypeCombo.currentData() == "variable")
self.rhsStack.setCurrentIndex(1 if isVar else 0)
if isVar:
self.populateRHSVarCombo()
class ActionStepFrame(QFrame): class ActionStepFrame(QFrame):
@@ -262,7 +261,6 @@ class ActionStepFrame(QFrame):
self.setupUi() self.setupUi()
self.connectSignals() self.connectSignals()
def setupUi( def setupUi(
self self
): ):
@@ -280,7 +278,7 @@ class ActionStepFrame(QFrame):
self.targetCombo = QComboBox(self) self.targetCombo = QComboBox(self)
self.targetCombo.setFixedHeight(25) self.targetCombo.setFixedHeight(25)
self.targetCombo.setMinimumWidth(120) self.targetCombo.setMinimumWidth(120)
self.buildTargetCombo() self.populateTargetCombo()
layout.addWidget(self.targetCombo) layout.addWidget(self.targetCombo)
layout.addWidget(makeLabel("", self)) layout.addWidget(makeLabel("", self))
self.valueSrcCombo = makeComboWidget([ self.valueSrcCombo = makeComboWidget([
@@ -301,8 +299,7 @@ class ActionStepFrame(QFrame):
layout.addWidget(self.deleteBtn) layout.addWidget(self.deleteBtn)
self.setUpdatesEnabled(True) self.setUpdatesEnabled(True)
def populateTargetCombo(
def buildTargetCombo(
self self
): ):
@@ -319,7 +316,6 @@ class ActionStepFrame(QFrame):
) )
self.targetCombo.blockSignals(False) self.targetCombo.blockSignals(False)
def initValueStacks( def initValueStacks(
self self
): ):
@@ -338,7 +334,6 @@ class ActionStepFrame(QFrame):
self._offsetWidgets[vt] = lbl self._offsetWidgets[vt] = lbl
self.valueStack.addWidget(lbl) self.valueStack.addWidget(lbl)
def connectSignals( def connectSignals(
self self
): ):
@@ -347,32 +342,14 @@ class ActionStepFrame(QFrame):
self.targetCombo.currentIndexChanged.connect(self.onTargetChanged) self.targetCombo.currentIndexChanged.connect(self.onTargetChanged)
self.valueSrcCombo.currentIndexChanged.connect(self.onValueSrcChanged) self.valueSrcCombo.currentIndexChanged.connect(self.onValueSrcChanged)
@Slot(int) def getTargetName(
def onTargetChanged( self
self, ) -> str:
idx
):
if idx < 0: data = self.targetCombo.currentData()
return return data[0] if data else ""
data = self.targetCombo.itemData(idx)
if not data:
return
_, vartype = data
self._currentTargetType = vartype
self.updateRHSWidget()
self.onValueSrcChanged(self.valueSrcCombo.currentIndex())
@Slot(int) def updateValueWidget(
def onOpTypeChanged(
self,
idx
):
self.updateRHSWidget()
def updateRHSWidget(
self self
): ):
@@ -386,30 +363,7 @@ class ActionStepFrame(QFrame):
else: else:
self.valueStack.setCurrentWidget(self._literalWidgets.get("String")) self.valueStack.setCurrentWidget(self._literalWidgets.get("String"))
@Slot(int) def toScript(
def onValueSrcChanged(
self,
idx
):
isVar = (self.valueSrcCombo.currentData() == "variable")
self.valueStack.setVisible(not isVar)
self.existingVarCombo.setVisible(isVar)
if isVar:
self._varMgr.populateCombo(self.existingVarCombo)
else:
self.updateRHSWidget()
def getTargetName(
self
) -> str:
data = self.targetCombo.currentData()
return data[0] if data else ""
def toScriptLine(
self self
) -> str: ) -> str:
""" """
@@ -422,7 +376,7 @@ class ActionStepFrame(QFrame):
return " -- pass" return " -- pass"
if not target: if not target:
return "" return ""
rawVal = self._getValueRaw() rawVal = self.getValueRaw()
vartype = self._currentTargetType vartype = self._currentTargetType
if op == "set": if op == "set":
encoded = encodeValueStr(rawVal, vartype) encoded = encodeValueStr(rawVal, vartype)
@@ -445,8 +399,7 @@ class ActionStepFrame(QFrame):
return f" {target} = {target} - {rawVal}" return f" {target} = {target} - {rawVal}"
return "" return ""
def getValueRaw(
def _getValueRaw(
self self
) -> str: ) -> str:
@@ -458,13 +411,12 @@ class ActionStepFrame(QFrame):
return getValueFromWidget(w) return getValueFromWidget(w)
return "" return ""
def refreshVarCombos( def refreshVarCombos(
self self
): ):
currentData = self.targetCombo.currentData() currentData = self.targetCombo.currentData()
self.buildTargetCombo() self.populateTargetCombo()
if currentData: if currentData:
for i in range(self.targetCombo.count()): for i in range(self.targetCombo.count()):
d = self.targetCombo.itemData(i) d = self.targetCombo.itemData(i)
@@ -472,3 +424,41 @@ class ActionStepFrame(QFrame):
self.targetCombo.setCurrentIndex(i) self.targetCombo.setCurrentIndex(i)
break break
self._varMgr.populateCombo(self.existingVarCombo) self._varMgr.populateCombo(self.existingVarCombo)
@Slot(int)
def onTargetChanged(
self,
idx
):
if idx < 0:
return
data = self.targetCombo.itemData(idx)
if not data:
return
_, vartype = data
self._currentTargetType = vartype
self.updateValueWidget()
self.onValueSrcChanged(self.valueSrcCombo.currentIndex())
@Slot(int)
def onOpTypeChanged(
self,
idx
):
self.updateValueWidget()
@Slot(int)
def onValueSrcChanged(
self,
idx
):
isVar = (self.valueSrcCombo.currentData() == "variable")
self.valueStack.setVisible(not isVar)
self.existingVarCombo.setVisible(isVar)
if isVar:
self._varMgr.populateCombo(self.existingVarCombo)
else:
self.updateValueWidget()
+31 -46
View File
@@ -10,28 +10,46 @@ See the LICENSE file for details.
import os import os
from PySide6.QtCore import ( from PySide6.QtCore import (
Qt, Signal, Slot, QTime, QDate, QDir, QFileInfo QDate,
) QDir,
from PySide6.QtWidgets import ( QFileInfo,
QDialog, QWidget, QLineEdit, QMessageBox, QFileDialog, Qt,
QTreeWidgetItem, QMenu, QInputDialog QTime,
Signal,
Slot
) )
from PySide6.QtGui import ( from PySide6.QtGui import (
QCloseEvent, QAction QAction,
QCloseEvent
)
from PySide6.QtWidgets import (
QDialog,
QFileDialog,
QInputDialog,
QLineEdit,
QMenu,
QMessageBox,
QTreeWidgetItem,
QWidget
) )
import managers.config.ConfigManager as ConfigManager import managers.config.ConfigManager as ConfigManager
from utils.JSONReader import JSONReader
from utils.JSONWriter import JSONWriter
from interfaces.ConfigProvider import ConfigProvider, CfgKey
from managers.config.ConfigUtils import ConfigUtils
from gui.resources.ui.Ui_ALConfigWidget import Ui_ALConfigWidget
from gui.ALSeatMapSelectDialog import ALSeatMapSelectDialog from gui.ALSeatMapSelectDialog import ALSeatMapSelectDialog
from gui.ALSeatMapTable import ALSeatMapTable from gui.ALSeatMapTable import ALSeatMapTable
from gui.ALUserTreeWidget import ALUserTreeWidget, ALUserTreeItemType from gui.ALUserTreeWidget import (
ALUserTreeItemType,
ALUserTreeWidget
)
from gui.ALWebDriverDownloadDialog import ALWebDriverDownloadDialog from gui.ALWebDriverDownloadDialog import ALWebDriverDownloadDialog
from gui.resources.ui.Ui_ALConfigWidget import Ui_ALConfigWidget
from interfaces.ConfigProvider import (
CfgKey,
ConfigProvider
)
from managers.config.ConfigUtils import ConfigUtils
from utils.JSONReader import JSONReader
from utils.JSONWriter import JSONWriter
class ALConfigWidget(QWidget, Ui_ALConfigWidget): class ALConfigWidget(QWidget, Ui_ALConfigWidget):
@@ -54,7 +72,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
if not self.initializeConfigs(): if not self.initializeConfigs():
self.close() self.close()
def modifyUi( def modifyUi(
self self
): ):
@@ -70,7 +87,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.initializeFloorRoomMap() self.initializeFloorRoomMap()
self.initializeUserInfoWidget() self.initializeUserInfoWidget()
def connectSignals( def connectSignals(
self self
): ):
@@ -94,7 +110,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked) self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked)
self.CancelButton.clicked.connect(self.onCancelButtonClicked) self.CancelButton.clicked.connect(self.onCancelButtonClicked)
def showEvent( def showEvent(
self, self,
event event
@@ -118,7 +133,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
return result return result
def closeEvent( def closeEvent(
self, self,
event: QCloseEvent event: QCloseEvent
@@ -127,7 +141,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.configWidgetIsClosed.emit() self.configWidgetIsClosed.emit()
super().closeEvent(event) super().closeEvent(event)
def initializeFloorRoomMap( def initializeFloorRoomMap(
self self
): ):
@@ -161,7 +174,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
"五层": ["五层考研"] "五层": ["五层考研"]
} }
def initializeConfigToWidget( def initializeConfigToWidget(
self, self,
which: str, which: str,
@@ -176,7 +188,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.setUsersToTreeWidget(config_data) self.setUsersToTreeWidget(config_data)
self.CurrentUserConfigEdit.setText(self.__config_paths["user"]) self.CurrentUserConfigEdit.setText(self.__config_paths["user"])
def initializeConfig( def initializeConfig(
self, self,
which: str which: str
@@ -210,7 +221,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
is_success = False is_success = False
return is_success return is_success
def initializeConfigs( def initializeConfigs(
self self
) -> bool: ) -> bool:
@@ -223,7 +233,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.initializeConfigToWidget(which, self.__config_data[which]) self.initializeConfigToWidget(which, self.__config_data[which])
return is_success return is_success
def defaultRunConfig( def defaultRunConfig(
self self
) -> dict: ) -> dict:
@@ -247,7 +256,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
} }
} }
def defaultUserConfig( def defaultUserConfig(
self self
) -> dict: ) -> dict:
@@ -257,7 +265,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
] ]
} }
def collectRunConfigFromWidget( def collectRunConfigFromWidget(
self self
) -> dict: ) -> dict:
@@ -279,7 +286,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
run_config["mode"]["run_mode"] = run_mode run_config["mode"]["run_mode"] = run_mode
return run_config return run_config
def setRunConfigToWidget( def setRunConfigToWidget(
self, self,
run_config: dict run_config: dict
@@ -318,7 +324,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
"文件可能被意外修改或已经损坏\n" "文件可能被意外修改或已经损坏\n"
) )
def initializeUserInfoWidget( def initializeUserInfoWidget(
self self
): ):
@@ -343,7 +348,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.MaxRenewTimeDiffSpinBox.setValue(30) self.MaxRenewTimeDiffSpinBox.setValue(30)
self.PreferLateRenewTimeCheckBox.setChecked(False) self.PreferLateRenewTimeCheckBox.setChecked(False)
def collectUserFromWidget( def collectUserFromWidget(
self self
) -> dict: ) -> dict:
@@ -376,7 +380,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
user["reserve_info"]["renew_time"]["prefer_early"] = not self.PreferLateRenewTimeCheckBox.isChecked() user["reserve_info"]["renew_time"]["prefer_early"] = not self.PreferLateRenewTimeCheckBox.isChecked()
return user return user
def collectUsersFromTreeWidget( def collectUsersFromTreeWidget(
self self
) -> dict: ) -> dict:
@@ -399,7 +402,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
user_config["groups"].append(group_config) user_config["groups"].append(group_config)
return user_config return user_config
def setUserToWidget( def setUserToWidget(
self, self,
user: dict user: dict
@@ -441,7 +443,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
"文件可能被意外修改或已经损坏\n" "文件可能被意外修改或已经损坏\n"
) )
def setUsersToTreeWidget( def setUsersToTreeWidget(
self, self,
users: dict users: dict
@@ -483,7 +484,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
finally: finally:
self.UserTreeWidget.itemChanged.connect(self.onUserTreeWidgetItemChanged) self.UserTreeWidget.itemChanged.connect(self.onUserTreeWidgetItemChanged)
def loadRunConfig( def loadRunConfig(
self, self,
run_config_path: str run_config_path: str
@@ -507,7 +507,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
) )
return None return None
def saveRunConfig( def saveRunConfig(
self, self,
run_config_path: str, run_config_path: str,
@@ -529,7 +528,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
) )
return False return False
def loadUserConfig( def loadUserConfig(
self, self,
user_config_path: str user_config_path: str
@@ -563,7 +561,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
) )
return None return None
def saveUserConfig( def saveUserConfig(
self, self,
user_config_path: str, user_config_path: str,
@@ -585,7 +582,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
) )
return False return False
def saveConfigs( def saveConfigs(
self, self,
run_config_path: str, run_config_path: str,
@@ -608,7 +604,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
return False return False
return True return True
def loadConfig( def loadConfig(
self, self,
config_path: str config_path: str
@@ -637,7 +632,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
except: except:
return False return False
def addGroup( def addGroup(
self, self,
group_name: str = "" group_name: str = ""
@@ -654,7 +648,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.UserTreeWidget.itemChanged.connect(self.onUserTreeWidgetItemChanged) self.UserTreeWidget.itemChanged.connect(self.onUserTreeWidgetItemChanged)
return group_item return group_item
def delGroup( def delGroup(
self, self,
group_item: QTreeWidgetItem = None group_item: QTreeWidgetItem = None
@@ -667,7 +660,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
index = self.UserTreeWidget.indexOfTopLevelItem(group_item) index = self.UserTreeWidget.indexOfTopLevelItem(group_item)
self.UserTreeWidget.takeTopLevelItem(index) self.UserTreeWidget.takeTopLevelItem(index)
def addUser( def addUser(
self, self,
group_item: QTreeWidgetItem = None group_item: QTreeWidgetItem = None
@@ -722,7 +714,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.UserTreeWidget.itemChanged.connect(self.onUserTreeWidgetItemChanged) self.UserTreeWidget.itemChanged.connect(self.onUserTreeWidgetItemChanged)
return user_item return user_item
def delUser( def delUser(
self, self,
user_item: QTreeWidgetItem = None user_item: QTreeWidgetItem = None
@@ -738,7 +729,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
if parent_item.childCount() == 0: if parent_item.childCount() == 0:
self.UserTreeWidget.setCurrentItem(None) self.UserTreeWidget.setCurrentItem(None)
def renameItem( def renameItem(
self, self,
item: QTreeWidgetItem, item: QTreeWidgetItem,
@@ -862,7 +852,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
is_checked = item.checkState(1) == Qt.CheckState.Checked is_checked = item.checkState(1) == Qt.CheckState.Checked
item.setText(1, "" if is_checked else "跳过") item.setText(1, "" if is_checked else "跳过")
def showTreeMenu( def showTreeMenu(
self, self,
menu: QMenu menu: QMenu
@@ -872,7 +861,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
add_group_action.triggered.connect(self.addGroup) add_group_action.triggered.connect(self.addGroup)
menu.addAction(add_group_action) menu.addAction(add_group_action)
def showGroupMenu( def showGroupMenu(
self, self,
menu: QMenu, menu: QMenu,
@@ -892,7 +880,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
if group_item.checkState(1) == Qt.CheckState.Unchecked: if group_item.checkState(1) == Qt.CheckState.Unchecked:
add_user_action.setEnabled(False) add_user_action.setEnabled(False)
def showUserMenu( def showUserMenu(
self, self,
menu: QMenu, menu: QMenu,
@@ -952,7 +939,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
if browser_driver_path: if browser_driver_path:
self.BrowseBrowserDriverEdit.setText(QDir.toNativeSeparators(browser_driver_path)) self.BrowseBrowserDriverEdit.setText(QDir.toNativeSeparators(browser_driver_path))
@Slot() @Slot()
def onAutoDownloadWebDriverButtonClicked( def onAutoDownloadWebDriverButtonClicked(
self self
@@ -966,7 +952,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.BrowserTypeComboBox.setCurrentText(selected_driver_info.driver_type.value) self.BrowserTypeComboBox.setCurrentText(selected_driver_info.driver_type.value)
self.BrowseBrowserDriverEdit.setText(QDir.toNativeSeparators(str(selected_driver_info.driver_path))) self.BrowseBrowserDriverEdit.setText(QDir.toNativeSeparators(str(selected_driver_info.driver_path)))
@Slot() @Slot()
def onBrowseCurrentRunConfigButtonClicked( def onBrowseCurrentRunConfigButtonClicked(
self self
+25 -25
View File
@@ -10,24 +10,37 @@ See the LICENSE file for details.
import queue import queue
from PySide6.QtCore import ( from PySide6.QtCore import (
Qt, Signal, Slot, QTimer, QUrl, QTimer,
) QUrl,
from PySide6.QtWidgets import ( Qt,
QMainWindow, QMenu, QSystemTrayIcon, QMessageBox Signal,
Slot
) )
from PySide6.QtGui import ( from PySide6.QtGui import (
QTextCursor, QCloseEvent, QFont, QIcon, QDesktopServices QCloseEvent,
QDesktopServices,
QFont,
QIcon,
QTextCursor
)
from PySide6.QtWidgets import (
QMainWindow,
QMenu,
QMessageBox,
QSystemTrayIcon
) )
from base.MsgBase import MsgBase from base.MsgBase import MsgBase
from managers.config.ConfigUtils import ConfigUtils
from gui.resources.ui.Ui_ALMainWindow import Ui_ALMainWindow
from gui.resources import ALResource
from gui.ALConfigWidget import ALConfigWidget
from gui.ALTimerTaskManageWidget import ALTimerTaskManageWidget
from gui.ALAboutDialog import ALAboutDialog from gui.ALAboutDialog import ALAboutDialog
from gui.ALMainWorkers import TimerTaskWorker, AutoLibWorker from gui.ALConfigWidget import ALConfigWidget
from gui.ALMainWorkers import (
AutoLibWorker,
TimerTaskWorker
)
from gui.ALTimerTaskManageWidget import ALTimerTaskManageWidget
from gui.resources import ALResource
from gui.resources.ui.Ui_ALMainWindow import Ui_ALMainWindow
from managers.config.ConfigUtils import ConfigUtils
class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow): class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
@@ -59,7 +72,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.startTimerTaskPolling() self.startTimerTaskPolling()
self._showLog("主窗口初始化完成") self._showLog("主窗口初始化完成")
def modifyUi( def modifyUi(
self self
): ):
@@ -90,7 +102,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.__alTimerTaskManageWidget.timerTaskManageWidgetIsClosed.connect(self.onTimerTaskManageWidgetClosed) self.__alTimerTaskManageWidget.timerTaskManageWidgetIsClosed.connect(self.onTimerTaskManageWidgetClosed)
self.__alTimerTaskManageWidget.setWindowFlags(Qt.WindowType.Window|Qt.WindowType.WindowCloseButtonHint) self.__alTimerTaskManageWidget.setWindowFlags(Qt.WindowType.Window|Qt.WindowType.WindowCloseButtonHint)
def onAboutActionTriggered( def onAboutActionTriggered(
self self
): ):
@@ -98,7 +109,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
about_dialog = ALAboutDialog(self) about_dialog = ALAboutDialog(self)
about_dialog.exec() about_dialog.exec()
def onManualActionTriggered( def onManualActionTriggered(
self self
): ):
@@ -106,7 +116,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
url = QUrl("https://www.autolibrary.kenanzhu.com/manuals") url = QUrl("https://www.autolibrary.kenanzhu.com/manuals")
QDesktopServices.openUrl(url) QDesktopServices.openUrl(url)
def setupTray( def setupTray(
self self
): ):
@@ -128,7 +137,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.TrayIcon.activated.connect(self.onTrayIconActivated) self.TrayIcon.activated.connect(self.onTrayIconActivated)
self.TrayIcon.show() self.TrayIcon.show()
def hideToTray( def hideToTray(
self self
): ):
@@ -141,7 +149,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
2000 2000
) )
def onTrayIconActivated( def onTrayIconActivated(
self, self,
reason: QSystemTrayIcon.ActivationReason reason: QSystemTrayIcon.ActivationReason
@@ -150,7 +157,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
if reason == QSystemTrayIcon.DoubleClick: if reason == QSystemTrayIcon.DoubleClick:
self.showNormal() self.showNormal()
def connectSignals( def connectSignals(
self self
): ):
@@ -162,7 +168,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.SendButton.clicked.connect(self.onSendButtonClicked) self.SendButton.clicked.connect(self.onSendButtonClicked)
self.MessageEdit.returnPressed.connect(self.onSendButtonClicked) self.MessageEdit.returnPressed.connect(self.onSendButtonClicked)
def closeEvent( def closeEvent(
self, self,
event: QCloseEvent event: QCloseEvent
@@ -188,7 +193,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self._showLog("主窗口关闭") self._showLog("主窗口关闭")
QMainWindow.closeEvent(self, event) QMainWindow.closeEvent(self, event)
def appendToTextEdit( def appendToTextEdit(
self, self,
text: str text: str
@@ -202,7 +206,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
scrollbar = self.MessageIOTextEdit.verticalScrollBar() scrollbar = self.MessageIOTextEdit.verticalScrollBar()
scrollbar.setValue(scrollbar.maximum()) scrollbar.setValue(scrollbar.maximum())
def startMsgPolling( def startMsgPolling(
self self
): ):
@@ -211,7 +214,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.__msg_queue_timer.timeout.connect(self.pollMsgQueue) self.__msg_queue_timer.timeout.connect(self.pollMsgQueue)
self.__msg_queue_timer.start(100) self.__msg_queue_timer.start(100)
def startTimerTaskPolling( def startTimerTaskPolling(
self self
): ):
@@ -220,7 +222,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.__timer_task_timer.timeout.connect(self.pollTimerTaskQueue) self.__timer_task_timer.timeout.connect(self.pollTimerTaskQueue)
self.__timer_task_timer.start(500) self.__timer_task_timer.start(500)
def pollTimerTaskQueue( def pollTimerTaskQueue(
self self
): ):
@@ -254,7 +255,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.__is_running_timer_task = False self.__is_running_timer_task = False
pass pass
def setControlButtons( def setControlButtons(
self, self,
config_button_enabled: bool, config_button_enabled: bool,
-6
View File
@@ -37,7 +37,6 @@ class AutoLibWorker(MsgBase, QThread):
QThread.__init__(self) QThread.__init__(self)
self.__config_paths = config_paths self.__config_paths = config_paths
def checkTimeAvailable( def checkTimeAvailable(
self, self,
) -> bool: ) -> bool:
@@ -52,7 +51,6 @@ class AutoLibWorker(MsgBase, QThread):
self._showLog(f"时间检查通过, 当前时间: {current_time}", self.TraceLevel.INFO) self._showLog(f"时间检查通过, 当前时间: {current_time}", self.TraceLevel.INFO)
return True return True
def checkConfigPaths( def checkConfigPaths(
self, self,
) -> bool: ) -> bool:
@@ -68,7 +66,6 @@ class AutoLibWorker(MsgBase, QThread):
self._showLog(f"配置文件路径检查通过, 路径: {self.__config_paths}", self.TraceLevel.INFO) self._showLog(f"配置文件路径检查通过, 路径: {self.__config_paths}", self.TraceLevel.INFO)
return True return True
def loadConfigs( def loadConfigs(
self self
) -> bool: ) -> bool:
@@ -101,7 +98,6 @@ class AutoLibWorker(MsgBase, QThread):
) )
return True return True
def run( def run(
self self
): ):
@@ -161,7 +157,6 @@ class TimerTaskWorker(AutoLibWorker):
self.autoLibWorkerIsFinished.connect(self.onTimerTaskIsFinished) self.autoLibWorkerIsFinished.connect(self.onTimerTaskIsFinished)
self.autoLibWorkerFinishedWithError.connect(self.onTimerTaskFinishedWithError) self.autoLibWorkerFinishedWithError.connect(self.onTimerTaskFinishedWithError)
def run( def run(
self self
): ):
@@ -206,7 +201,6 @@ class TimerTaskWorker(AutoLibWorker):
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行结束") self._showTrace(f"定时任务 {self.__timer_task['name']} 运行结束")
self.timerTaskWorkerIsFinished.emit(False, self.__timer_task) self.timerTaskWorkerIsFinished.emit(False, self.__timer_task)
def applyRepeatAutoScript( def applyRepeatAutoScript(
self self
): ):
-4
View File
@@ -31,7 +31,6 @@ class ALSeatFrame(QFrame):
self.setupUi() self.setupUi()
def setupUi( def setupUi(
self self
): ):
@@ -55,7 +54,6 @@ class ALSeatFrame(QFrame):
self.Label.setAlignment(Qt.AlignCenter) self.Label.setAlignment(Qt.AlignCenter)
self.Label.setGeometry(0, 0, 60, 40) self.Label.setGeometry(0, 0, 60, 40)
def mousePressEvent( def mousePressEvent(
self, self,
event event
@@ -65,14 +63,12 @@ class ALSeatFrame(QFrame):
self.toggleSelection() self.toggleSelection()
self.clicked.emit(self.__seat_number) self.clicked.emit(self.__seat_number)
def isSelected( def isSelected(
self self
): ):
return self.__is_selected return self.__is_selected
def toggleSelection(self): def toggleSelection(self):
self.__is_selected = not self.__is_selected self.__is_selected = not self.__is_selected
+10 -13
View File
@@ -8,15 +8,20 @@ You may use, modify, and distribute this file under the terms of the MIT License
See the LICENSE file for details. See the LICENSE file for details.
""" """
from PySide6.QtCore import ( from PySide6.QtCore import (
Qt, Slot, Signal Qt,
) Signal,
from PySide6.QtWidgets import ( Slot
QDialog, QLabel, QHBoxLayout, QVBoxLayout,
QPushButton,
) )
from PySide6.QtGui import ( from PySide6.QtGui import (
QCloseEvent QCloseEvent
) )
from PySide6.QtWidgets import (
QDialog,
QHBoxLayout,
QLabel,
QPushButton,
QVBoxLayout
)
from gui.ALSeatMapView import ALSeatMapView from gui.ALSeatMapView import ALSeatMapView
@@ -42,7 +47,6 @@ class ALSeatMapSelectDialog(QDialog):
self.setupUi() self.setupUi()
self.connectSignals() self.connectSignals()
def setupUi( def setupUi(
self self
): ):
@@ -85,7 +89,6 @@ class ALSeatMapSelectDialog(QDialog):
self.SeatMapWidgetControlLayout.addWidget(self.ConfirmButton) self.SeatMapWidgetControlLayout.addWidget(self.ConfirmButton)
self.SeatMapWidgetMainLayout.addLayout(self.SeatMapWidgetControlLayout) self.SeatMapWidgetMainLayout.addLayout(self.SeatMapWidgetControlLayout)
def connectSignals( def connectSignals(
self self
): ):
@@ -93,7 +96,6 @@ class ALSeatMapSelectDialog(QDialog):
self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked) self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked)
self.CancelButton.clicked.connect(self.onCancelButtonClicked) self.CancelButton.clicked.connect(self.onCancelButtonClicked)
def showEvent( def showEvent(
self, self,
event event
@@ -117,7 +119,6 @@ class ALSeatMapSelectDialog(QDialog):
return result return result
def closeEvent( def closeEvent(
self, self,
event: QCloseEvent event: QCloseEvent
@@ -131,7 +132,6 @@ class ALSeatMapSelectDialog(QDialog):
self.seatMapSelectDialogIsClosed.emit(self.getSelectedSeats()) self.seatMapSelectDialogIsClosed.emit(self.getSelectedSeats())
super().closeEvent(event) super().closeEvent(event)
def selectSeat( def selectSeat(
self, self,
seat_number: str seat_number: str
@@ -139,7 +139,6 @@ class ALSeatMapSelectDialog(QDialog):
self.SeatMapGraphicsView.selectSeat(seat_number) self.SeatMapGraphicsView.selectSeat(seat_number)
def selectSeats( def selectSeats(
self, self,
seat_numbers: list[str] seat_numbers: list[str]
@@ -147,14 +146,12 @@ class ALSeatMapSelectDialog(QDialog):
return self.SeatMapGraphicsView.selectSeats(seat_numbers) return self.SeatMapGraphicsView.selectSeats(seat_numbers)
def getSelectedSeats( def getSelectedSeats(
self self
) -> list[str]: ) -> list[str]:
return self.SeatMapGraphicsView.getSelectedSeats() return self.SeatMapGraphicsView.getSelectedSeats()
def clearSelections( def clearSelections(
self self
): ):
+20 -23
View File
@@ -11,11 +11,16 @@ from PySide6.QtCore import (
Qt, Slot, QEvent Qt, Slot, QEvent
) )
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QFrame, QWidget, QFrame,
QGridLayout, QGraphicsView, QGraphicsScene, QGraphicsItem QWidget,
QGridLayout,
QGraphicsView,
QGraphicsScene,
QGraphicsItem
) )
from PySide6.QtGui import ( from PySide6.QtGui import (
QPainter, QWheelEvent QPainter,
QWheelEvent
) )
from gui.ALSeatFrame import ALSeatFrame from gui.ALSeatFrame import ALSeatFrame
@@ -35,18 +40,6 @@ class ALSeatMapView(QGraphicsView):
self.setupUi() self.setupUi()
@staticmethod
def formatSeatNumber(
seat_number: str
) -> str:
if seat_number and not seat_number[-1].isdigit():
digits = seat_number[:-1]
letter = seat_number[-1]
return digits.zfill(3) + letter
return seat_number.zfill(3)
def eventFilter( def eventFilter(
self, self,
watched, watched,
@@ -61,7 +54,6 @@ class ALSeatMapView(QGraphicsView):
return True return True
return super().eventFilter(watched, event) return super().eventFilter(watched, event)
def zoomGraphicsView( def zoomGraphicsView(
self, self,
event: QWheelEvent event: QWheelEvent
@@ -80,7 +72,6 @@ class ALSeatMapView(QGraphicsView):
self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse) self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
self.scale(zoom_factor, zoom_factor) self.scale(zoom_factor, zoom_factor)
def setupUi( def setupUi(
self self
): ):
@@ -100,7 +91,6 @@ class ALSeatMapView(QGraphicsView):
self.ContainerProxy = self.SeatMapGraphicsScene.addWidget(self.SeatsContainerWidget) self.ContainerProxy = self.SeatMapGraphicsScene.addWidget(self.SeatsContainerWidget)
self.ContainerProxy.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, False) self.ContainerProxy.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, False)
def setupSeatMap( def setupSeatMap(
self self
): ):
@@ -125,7 +115,6 @@ class ALSeatMapView(QGraphicsView):
self.SeatsContainerLayout.setContentsMargins(20, 20, 20, 20) self.SeatsContainerLayout.setContentsMargins(20, 20, 20, 20)
self.SeatsContainerWidget.adjustSize() self.SeatsContainerWidget.adjustSize()
def selectSeat( def selectSeat(
self, self,
seat_number: str seat_number: str
@@ -142,7 +131,6 @@ class ALSeatMapView(QGraphicsView):
widget.toggleSelection() widget.toggleSelection()
self.__selected_seats.append(seat_number) self.__selected_seats.append(seat_number)
def selectSeats( def selectSeats(
self, self,
selected_seats: list selected_seats: list
@@ -152,14 +140,12 @@ class ALSeatMapView(QGraphicsView):
for seat_number in selected_seats: for seat_number in selected_seats:
self.selectSeat(seat_number) self.selectSeat(seat_number)
def getSelectedSeats( def getSelectedSeats(
self self
) -> list[str]: ) -> list[str]:
return self.__selected_seats return self.__selected_seats
def clearSelections( def clearSelections(
self self
): ):
@@ -185,4 +171,15 @@ class ALSeatMapView(QGraphicsView):
if len(self.__selected_seats) < 1: if len(self.__selected_seats) < 1:
self.__selected_seats.append(seat_number) self.__selected_seats.append(seat_number)
else: else:
self.__seat_frames[seat_number].toggleSelection() self.__seat_frames[seat_number].toggleSelection()
@staticmethod
def formatSeatNumber(
seat_number: str
) -> str:
if seat_number and not seat_number[-1].isdigit():
digits = seat_number[:-1]
letter = seat_number[-1]
return digits.zfill(3) + letter
return seat_number.zfill(3)
+11 -9
View File
@@ -9,14 +9,20 @@ See the LICENSE file for details.
""" """
from enum import Enum from enum import Enum
from PySide6.QtWidgets import (
QLabel
)
from PySide6.QtCore import ( from PySide6.QtCore import (
Qt, Property, QPropertyAnimation, QEasingCurve Property,
QEasingCurve,
QPropertyAnimation,
Qt
) )
from PySide6.QtGui import ( from PySide6.QtGui import (
QPainter, QColor, QConicalGradient, QPalette QColor,
QConicalGradient,
QPainter,
QPalette
)
from PySide6.QtWidgets import (
QLabel
) )
@@ -44,7 +50,6 @@ class ALStatusLabel(QLabel):
self.setupUi() self.setupUi()
def setupUi( def setupUi(
self self
): ):
@@ -59,14 +64,12 @@ class ALStatusLabel(QLabel):
self.RunningAnimation.setLoopCount(-1) self.RunningAnimation.setLoopCount(-1)
self.RunningAnimation.setEasingCurve(QEasingCurve.Type.Linear) self.RunningAnimation.setEasingCurve(QEasingCurve.Type.Linear)
def isDarkMode( def isDarkMode(
self self
) -> bool: ) -> bool:
return self.palette().color(QPalette.ColorRole.Window).value() < 128 return self.palette().color(QPalette.ColorRole.Window).value() < 128
def getMarkColor( def getMarkColor(
self self
) -> QColor: ) -> QColor:
@@ -111,7 +114,6 @@ class ALStatusLabel(QLabel):
self.__icon_angle = value self.__icon_angle = value
self.update() self.update()
def paintEvent( def paintEvent(
self, self,
event event
+5 -9
View File
@@ -49,7 +49,6 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
if self.__edit_timer_task: if self.__edit_timer_task:
self.loadTask(self.__edit_timer_task) self.loadTask(self.__edit_timer_task)
def modifyUi( def modifyUi(
self self
): ):
@@ -101,10 +100,10 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.AutoScriptLayout.setContentsMargins(3, 3, 3, 3) self.AutoScriptLayout.setContentsMargins(3, 3, 3, 3)
self.AutoScriptLayout.setSpacing(3) self.AutoScriptLayout.setSpacing(3)
autoScriptBtnLayout = QHBoxLayout() autoScriptBtnLayout = QHBoxLayout()
self.AutoScriptPreviewButton = QPushButton("编辑") self.AutoScriptEditButton = QPushButton("编辑")
self.AutoScriptPreviewButton.setMinimumHeight(25) self.AutoScriptEditButton.setMinimumHeight(25)
self.AutoScriptPreviewButton.setFixedWidth(60) self.AutoScriptEditButton.setFixedWidth(80)
autoScriptBtnLayout.addWidget(self.AutoScriptPreviewButton) autoScriptBtnLayout.addWidget(self.AutoScriptEditButton)
autoScriptBtnLayout.addStretch() autoScriptBtnLayout.addStretch()
self.AutoScriptHelpButton = QPushButton("?") self.AutoScriptHelpButton = QPushButton("?")
self.AutoScriptHelpButton.setFixedSize(20, 20) self.AutoScriptHelpButton.setFixedSize(20, 20)
@@ -133,7 +132,6 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.__auto_script = "" self.__auto_script = ""
self.__mock_target_data = None self.__mock_target_data = None
def loadTask( def loadTask(
self, self,
task: dict task: dict
@@ -174,7 +172,6 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.__mock_target_data = mock_data self.__mock_target_data = mock_data
self.ConfirmButton.setText("保存") self.ConfirmButton.setText("保存")
def connectSignals( def connectSignals(
self self
): ):
@@ -183,10 +180,9 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.ConfirmButton.clicked.connect(self.accept) self.ConfirmButton.clicked.connect(self.accept)
self.TimerTypeComboBox.currentIndexChanged.connect(self.onTimerTypeComboBoxIndexChanged) self.TimerTypeComboBox.currentIndexChanged.connect(self.onTimerTypeComboBoxIndexChanged)
self.RepeatCheckBox.toggled.connect(self.onRepeatCheckBoxToggled) self.RepeatCheckBox.toggled.connect(self.onRepeatCheckBoxToggled)
self.AutoScriptPreviewButton.clicked.connect(self.onPreviewAutoScript) self.AutoScriptEditButton.clicked.connect(self.onPreviewAutoScript)
self.AutoScriptHelpButton.clicked.connect(self.onAutoScriptHelp) self.AutoScriptHelpButton.clicked.connect(self.onAutoScriptHelp)
def getTimerTask( def getTimerTask(
self self
) -> dict: ) -> dict:
+5 -10
View File
@@ -34,7 +34,6 @@ class ALTimerTaskHistoryDialog(QDialog):
self.setupUi() self.setupUi()
self.connectSignals() self.connectSignals()
def setupUi( def setupUi(
self self
): ):
@@ -82,7 +81,6 @@ class ALTimerTaskHistoryDialog(QDialog):
ButtonLayout.addWidget(self.CloseButton) ButtonLayout.addWidget(self.CloseButton)
MainLayout.addLayout(ButtonLayout) MainLayout.addLayout(ButtonLayout)
def connectSignals( def connectSignals(
self self
): ):
@@ -90,7 +88,6 @@ class ALTimerTaskHistoryDialog(QDialog):
self.CloseButton.clicked.connect(self.accept) self.CloseButton.clicked.connect(self.accept)
self.ClearHistoryButton.clicked.connect(self.onClearHistoryButtonClicked) self.ClearHistoryButton.clicked.connect(self.onClearHistoryButtonClicked)
def loadHistory( def loadHistory(
self self
): ):
@@ -99,6 +96,11 @@ class ALTimerTaskHistoryDialog(QDialog):
for row, record in enumerate(self.__history): for row, record in enumerate(self.__history):
self.addHistoryRow(row, record) self.addHistoryRow(row, record)
def getHistory(
self
) -> list:
return self.__history
def addHistoryRow( def addHistoryRow(
self, self,
@@ -129,13 +131,6 @@ class ALTimerTaskHistoryDialog(QDialog):
self.HistoryTableWidget.setItem(row, 2, DurationItem) self.HistoryTableWidget.setItem(row, 2, DurationItem)
self.HistoryTableWidget.setRowHeight(row, 25) self.HistoryTableWidget.setRowHeight(row, 25)
def getHistory(
self
) -> list:
return self.__history
@Slot() @Slot()
def onClearHistoryButtonClicked( def onClearHistoryButtonClicked(
self self
+27 -29
View File
@@ -15,24 +15,40 @@ from enum import Enum
from datetime import datetime, timedelta from datetime import datetime, timedelta
from PySide6.QtCore import ( from PySide6.QtCore import (
Qt, Signal, Slot, QTimer QTimer,
) Qt,
from PySide6.QtWidgets import ( Signal,
QDialog, QWidget, QListWidgetItem, QMessageBox, Slot
QHBoxLayout, QVBoxLayout, QLabel, QPushButton, QMenu
) )
from PySide6.QtGui import ( from PySide6.QtGui import (
QCloseEvent, QAction QAction,
QCloseEvent
)
from PySide6.QtWidgets import (
QDialog,
QHBoxLayout,
QLabel,
QListWidgetItem,
QMenu,
QMessageBox,
QPushButton,
QVBoxLayout,
QWidget
) )
import managers.config.ConfigManager as ConfigManager import managers.config.ConfigManager as ConfigManager
from utils.TimerUtils import TimerUtils from gui.ALTimerTaskAddDialog import (
from interfaces.ConfigProvider import ConfigProvider, CfgKey ALTimerTaskAddDialog,
ALTimerTaskStatus
from gui.resources.ui.Ui_ALTimerTaskManageWidget import Ui_ALTimerTaskManageWidget )
from gui.ALTimerTaskAddDialog import ALTimerTaskAddDialog, ALTimerTaskStatus
from gui.ALTimerTaskHistoryDialog import ALTimerTaskHistoryDialog from gui.ALTimerTaskHistoryDialog import ALTimerTaskHistoryDialog
from gui.resources.ui.Ui_ALTimerTaskManageWidget import Ui_ALTimerTaskManageWidget
from interfaces.ConfigProvider import (
CfgKey,
ConfigProvider
)
from utils.TimerUtils import TimerUtils
class ALTimerTaskItemWidget(QWidget): class ALTimerTaskItemWidget(QWidget):
@@ -53,7 +69,6 @@ class ALTimerTaskItemWidget(QWidget):
self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.customContextMenuRequested.connect(self.showContextMenu) self.customContextMenuRequested.connect(self.showContextMenu)
def modifyUi( def modifyUi(
self self
): ):
@@ -204,7 +219,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
if not self.initializeTimerTasks(): if not self.initializeTimerTasks():
raise Exception("定时任务配置文件初始化失败 !") raise Exception("定时任务配置文件初始化失败 !")
def connectSignals( def connectSignals(
self self
): ):
@@ -215,7 +229,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.TimerTaskSortOrderToggleButton.clicked.connect(self.onSortOrderToggleButtonClicked) self.TimerTaskSortOrderToggleButton.clicked.connect(self.onSortOrderToggleButtonClicked)
self.timerTasksChanged.connect(self.onTimerTasksChanged) self.timerTasksChanged.connect(self.onTimerTasksChanged)
def setupTimer( def setupTimer(
self self
): ):
@@ -224,7 +237,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.__check_timer.timeout.connect(self.checkTasks) self.__check_timer.timeout.connect(self.checkTasks)
self.__check_timer.start(500) self.__check_timer.start(500)
def initializeTimerTasks( def initializeTimerTasks(
self self
) -> bool: ) -> bool:
@@ -240,7 +252,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
return True return True
return False return False
def getTimerTasks( def getTimerTasks(
self self
) -> list: ) -> list:
@@ -265,7 +276,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
) )
return None return None
def setTimerTasks( def setTimerTasks(
self, self,
timer_tasks: list timer_tasks: list
@@ -289,7 +299,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
) )
return False return False
def showEvent( def showEvent(
self, self,
event event
@@ -313,7 +322,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
return result return result
def closeEvent( def closeEvent(
self, self,
event: QCloseEvent event: QCloseEvent
@@ -323,7 +331,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.timerTaskManageWidgetIsClosed.emit() self.timerTaskManageWidgetIsClosed.emit()
event.ignore() event.ignore()
def sortTimerTasks( def sortTimerTasks(
self, self,
policy: SortPolicy = SortPolicy.BY_EXECUTE_TIME, policy: SortPolicy = SortPolicy.BY_EXECUTE_TIME,
@@ -346,7 +353,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
reverse = order is Qt.SortOrder.DescendingOrder reverse = order is Qt.SortOrder.DescendingOrder
) )
def updateStat( def updateStat(
self self
): ):
@@ -373,7 +379,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.ExecutedTaskLabel.setText(f"已执行:{executed}") self.ExecutedTaskLabel.setText(f"已执行:{executed}")
self.InvalidTaskLabel.setText(f"无效的:{invalid}") self.InvalidTaskLabel.setText(f"无效的:{invalid}")
def updateTimerTaskList( def updateTimerTaskList(
self self
): ):
@@ -396,7 +401,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.TimerTasksListWidget.addItem(item) self.TimerTasksListWidget.addItem(item)
self.TimerTasksListWidget.setItemWidget(item, widget) self.TimerTasksListWidget.setItemWidget(item, widget)
def addTask( def addTask(
self self
): ):
@@ -407,7 +411,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.__timer_tasks.append(timer_task) self.__timer_tasks.append(timer_task)
self.timerTasksChanged.emit() self.timerTasksChanged.emit()
def editTask( def editTask(
self, self,
timer_task: dict timer_task: dict
@@ -440,7 +443,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
f"已记录次数:{history_count}" f"已记录次数:{history_count}"
) )
def deleteTask( def deleteTask(
self, self,
timer_task: dict timer_task: dict
@@ -469,7 +471,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
] ]
self.timerTasksChanged.emit() self.timerTasksChanged.emit()
def clearAllTasks( def clearAllTasks(
self self
): ):
@@ -531,7 +532,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.__timer_tasks.clear() self.__timer_tasks.clear()
self.timerTasksChanged.emit() self.timerTasksChanged.emit()
def showTaskHistory( def showTaskHistory(
self, self,
task: dict task: dict
@@ -541,7 +541,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
if dialog.exec() == QDialog.DialogCode.Accepted: if dialog.exec() == QDialog.DialogCode.Accepted:
self.timerTasksChanged.emit() self.timerTasksChanged.emit()
def checkTasks( def checkTasks(
self self
): ):
@@ -615,7 +614,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
break break
self.timerTasksChanged.emit() self.timerTasksChanged.emit()
def onRepeatTimerTaskIs( def onRepeatTimerTaskIs(
self, self,
status: ALTimerTaskStatus, status: ALTimerTaskStatus,
+12 -10
View File
@@ -10,14 +10,22 @@ See the LICENSE file for details.
from enum import Enum from enum import Enum
from PySide6.QtCore import ( from PySide6.QtCore import (
Qt, QSize, QCoreApplication, QRect, QPoint Qt,
QSize,
QCoreApplication,
QRect,
QPoint
) )
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QAbstractScrollArea, QAbstractItemView, QAbstractScrollArea,
QTreeWidget, QTreeWidgetItem QAbstractItemView,
QTreeWidget,
QTreeWidgetItem
) )
from PySide6.QtGui import ( from PySide6.QtGui import (
QDragEnterEvent, QDragMoveEvent, QDropEvent QDragEnterEvent,
QDragMoveEvent,
QDropEvent
) )
@@ -39,7 +47,6 @@ class ALUserTreeWidget(QTreeWidget):
self.setupUi() self.setupUi()
self.translateUi() self.translateUi()
def setupUi( def setupUi(
self self
): ):
@@ -70,7 +77,6 @@ class ALUserTreeWidget(QTreeWidget):
self.header().setHighlightSections(False) self.header().setHighlightSections(False)
self.header().setProperty(u"showSortIndicator", True) self.header().setProperty(u"showSortIndicator", True)
def translateUi( def translateUi(
self self
): ):
@@ -78,7 +84,6 @@ class ALUserTreeWidget(QTreeWidget):
___qtreewidgetitem = self.headerItem() ___qtreewidgetitem = self.headerItem()
___qtreewidgetitem.setText(1, QCoreApplication.translate("ALConfigWidget", u"\u72b6\u6001", None)); ___qtreewidgetitem.setText(1, QCoreApplication.translate("ALConfigWidget", u"\u72b6\u6001", None));
@staticmethod @staticmethod
def isDragPositionValid( def isDragPositionValid(
target_rect: QRect, target_rect: QRect,
@@ -90,7 +95,6 @@ class ALUserTreeWidget(QTreeWidget):
y_offset < target_rect.height()*0.8) y_offset < target_rect.height()*0.8)
return valid return valid
def dragEnterEvent( def dragEnterEvent(
self, self,
event: QDragEnterEvent event: QDragEnterEvent
@@ -98,7 +102,6 @@ class ALUserTreeWidget(QTreeWidget):
super().dragEnterEvent(event) super().dragEnterEvent(event)
def dragMoveEvent( def dragMoveEvent(
self, self,
event: QDragMoveEvent event: QDragMoveEvent
@@ -136,7 +139,6 @@ class ALUserTreeWidget(QTreeWidget):
return return
event.acceptProposedAction() event.acceptProposedAction()
def dropEvent( def dropEvent(
self, self,
event: QDropEvent event: QDropEvent
+137 -140
View File
@@ -11,20 +11,30 @@ import threading
from typing import Optional from typing import Optional
from PySide6.QtCore import ( from PySide6.QtCore import (
Qt, Slot, QThread, Signal Qt,
Slot,
QThread,
Signal
) )
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QDialog, QLabel, QComboBox, QProgressBar, QDialog,
QPushButton, QVBoxLayout, QHBoxLayout, QLabel,
QMessageBox, QFrame, QLineEdit QComboBox,
) QProgressBar,
from PySide6.QtGui import ( QPushButton,
QCloseEvent QVBoxLayout,
QHBoxLayout,
QMessageBox,
QFrame,
QLineEdit
) )
from PySide6.QtGui import QCloseEvent
from managers.driver.WebDriverManager import ( from managers.driver.WebDriverManager import (
instance as webdriver_manager_instance, instance as webdriverManagerInstance,
WebDriverManager, WebDriverInfo, WebDriverType, WebDriverManager,
WebDriverInfo,
WebDriverType,
WebDriverStatus WebDriverStatus
) )
from gui.ALStatusLabel import ALStatusLabel from gui.ALStatusLabel import ALStatusLabel
@@ -142,7 +152,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.initializeDriverManager() self.initializeDriverManager()
self.refreshDriverList() self.refreshDriverList()
def showEvent( def showEvent(
self, self,
event event
@@ -165,7 +174,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.move(target_pos) self.move(target_pos)
return result return result
def setupUi( def setupUi(
self self
): ):
@@ -237,7 +245,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.ControlLayout.addWidget(self.ConfirmButton) self.ControlLayout.addWidget(self.ConfirmButton)
self.MainLayout.addLayout(self.ControlLayout) self.MainLayout.addLayout(self.ControlLayout)
def connectSignals( def connectSignals(
self self
): ):
@@ -249,18 +256,16 @@ class ALWebDriverDownloadDialog(QDialog):
self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked) self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked)
self.DriverComboBox.currentIndexChanged.connect(self.onDriverComboBoxChanged) self.DriverComboBox.currentIndexChanged.connect(self.onDriverComboBoxChanged)
def initializeDriverManager( def initializeDriverManager(
self self
): ):
try: try:
self.__driver_manager = webdriver_manager_instance(self.__driver_dir) self.__driver_manager = webdriverManagerInstance(self.__driver_dir)
except ValueError as e: except ValueError as e:
QMessageBox.warning(self, "初始化失败", f"WebDriverManager 初始化失败:\n{str(e)}") QMessageBox.warning(self, "初始化失败", f"WebDriverManager 初始化失败:\n{str(e)}")
self.reject() self.reject()
def refreshDriverList( def refreshDriverList(
self self
): ):
@@ -270,18 +275,20 @@ class ALWebDriverDownloadDialog(QDialog):
self.__driver_manager.refresh() self.__driver_manager.refresh()
self.__driver_infos = self.__driver_manager.getDriverInfos() self.__driver_infos = self.__driver_manager.getDriverInfos()
self.DriverComboBox.clear() self.DriverComboBox.clear()
installed = 0
installed_idx = 0 installed_idx = 0
for i, driver_info in enumerate(self.__driver_infos): for i, driver_info in enumerate(self.__driver_infos):
if driver_info.driver_status == WebDriverStatus.INSTALLED:
installed_idx = i # get the installed driver index
display_text = f"{driver_info.driver_type.value} - {driver_info.browser_version}" display_text = f"{driver_info.driver_type.value} - {driver_info.browser_version}"
if driver_info.driver_status == WebDriverStatus.INSTALLED:
installed += 1
installed_idx = i # get the installed driver index
display_text += " : 已安装"
self.DriverComboBox.addItem(display_text) self.DriverComboBox.addItem(display_text)
count = len(self.__driver_infos) count = len(self.__driver_infos)
self.BrowserCountLabel.setText(f"检测到 {count} 个可用浏览器:") self.BrowserCountLabel.setText(f"检测到 {count} 个可用浏览器{installed} 个已安装驱动")
if self.__driver_infos: if self.__driver_infos:
self.DriverComboBox.setCurrentIndex(installed_idx) self.DriverComboBox.setCurrentIndex(installed_idx)
def onDriverComboBoxChanged( def onDriverComboBoxChanged(
self, self,
index: int index: int
@@ -294,6 +301,116 @@ class ALWebDriverDownloadDialog(QDialog):
self.updateProgressBarStates(driver_info) self.updateProgressBarStates(driver_info)
self.updateButtonStates(driver_info) self.updateButtonStates(driver_info)
def closeEvent(
self,
event: QCloseEvent
):
if self.__download_thread and self.__download_thread.isRunning():
reply = QMessageBox.question(
self,
"确认关闭 - AutoLibrary",
"驱动正在下载中, 确定要取消并关闭对话框吗 ?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
)
if reply == QMessageBox.StandardButton.No:
event.ignore()
return
self.__download_thread.stop()
if not self.__confirmed:
self.__selected_driver_info = None
event.accept()
super().closeEvent(event)
def onThreadFinished(
self
):
if self.__download_thread:
self.__download_thread.deleteLater()
self.__download_thread = None
def getSelectedDriverInfo(
self
) -> Optional[WebDriverInfo]:
return self.__selected_driver_info
def updateDriverInfoDisplay(
self,
driver_info: WebDriverInfo
):
if driver_info.driver_type == WebDriverType.CHROME:
driver_type = "Google Chrome"
elif driver_info.driver_type == WebDriverType.FIREFOX:
driver_type = "Mozilla Firefox"
elif driver_info.driver_type == WebDriverType.EDGE:
driver_type = "Microsoft Edge"
else:
driver_type = "未知"
self.BrowserTypeLabel.setText(f"类型:{driver_type}")
self.VersionLabel.setText(f"版本:{driver_info.driver_version}")
if driver_info.driver_path:
self.PathLabel.setText(str(driver_info.driver_path))
else:
self.PathLabel.setText("未安装")
match driver_info.driver_status:
case WebDriverStatus.NOT_INSTALLED:
self.StatusLabel.status = ALStatusLabel.Status.WAITING
case WebDriverStatus.INSTALLED:
self.StatusLabel.status = ALStatusLabel.Status.SUCCESS
case WebDriverStatus.DOWNLOADING:
self.StatusLabel.status = ALStatusLabel.Status.RUNNING
case WebDriverStatus.ERROR:
self.StatusLabel.status = ALStatusLabel.Status.FAILURE
def updateProgressBarStates(
self,
driver_info: WebDriverInfo
):
if driver_info.driver_status == WebDriverStatus.NOT_INSTALLED:
self.ProgressBar.setValue(0)
self.ProgressText.setText("未安装")
elif driver_info.driver_status == WebDriverStatus.INSTALLED:
self.ProgressBar.setValue(100)
self.ProgressText.setText("已安装")
elif driver_info.driver_status == WebDriverStatus.DOWNLOADING:
pass # update by worker thread
elif driver_info.driver_status == WebDriverStatus.ERROR:
self.ProgressBar.setValue(0)
self.ProgressText.setText("下载失败")
def updateButtonStates(
self,
driver_info: WebDriverInfo
):
if driver_info.driver_status == WebDriverStatus.NOT_INSTALLED:
self.RefreshButton.setEnabled(True)
self.DeleteButton.setEnabled(False)
self.DownloadButton.setEnabled(True)
self.CancelButton.setEnabled(True)
self.ConfirmButton.setEnabled(False)
elif driver_info.driver_status == WebDriverStatus.INSTALLED:
self.RefreshButton.setEnabled(True)
self.DownloadButton.setEnabled(False)
self.DeleteButton.setEnabled(True)
self.CancelButton.setEnabled(True)
self.ConfirmButton.setEnabled(True)
elif driver_info.driver_status == WebDriverStatus.DOWNLOADING:
self.RefreshButton.setEnabled(False)
self.DownloadButton.setEnabled(False)
self.DeleteButton.setEnabled(False)
self.CancelButton.setEnabled(True)
self.ConfirmButton.setEnabled(False)
elif driver_info.driver_status == WebDriverStatus.ERROR:
self.RefreshButton.setEnabled(True)
self.DownloadButton.setEnabled(True)
self.DeleteButton.setEnabled(False)
self.CancelButton.setEnabled(True)
self.ConfirmButton.setEnabled(False)
@Slot() @Slot()
def onRefreshButtonClicked( def onRefreshButtonClicked(
@@ -302,7 +419,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.refreshDriverList() self.refreshDriverList()
@Slot() @Slot()
def onDeleteButtonClicked( def onDeleteButtonClicked(
self self
@@ -355,7 +471,7 @@ class ALWebDriverDownloadDialog(QDialog):
self.__download_thread.downloadFinished.connect(self.onDownloadFinished) self.__download_thread.downloadFinished.connect(self.onDownloadFinished)
self.__download_thread.downloadError.connect(self.onDownloadError) self.__download_thread.downloadError.connect(self.onDownloadError)
self.__download_thread.downloadCancelled.connect(self.onDownloadCancelled) self.__download_thread.downloadCancelled.connect(self.onDownloadCancelled)
self.__download_thread.finished.connect(self.__onThreadFinished) self.__download_thread.finished.connect(self.onThreadFinished)
self.__download_thread.start() self.__download_thread.start()
@Slot() @Slot()
@@ -406,7 +522,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.updateButtonStates(driver_info) self.updateButtonStates(driver_info)
QMessageBox.critical(self, "下载失败 - AutoLibrary", error_message) QMessageBox.critical(self, "下载失败 - AutoLibrary", error_message)
@Slot() @Slot()
def onDownloadCancelled( def onDownloadCancelled(
self self
@@ -423,7 +538,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.updateButtonStates(driver_info) self.updateButtonStates(driver_info)
self.ProgressText.setText("下载已取消") self.ProgressText.setText("下载已取消")
@Slot() @Slot()
def onConfirmButtonClicked( def onConfirmButtonClicked(
self self
@@ -439,7 +553,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.__confirmed = True self.__confirmed = True
self.accept() self.accept()
@Slot() @Slot()
def onCancelButtonClicked( def onCancelButtonClicked(
self self
@@ -458,119 +571,3 @@ class ALWebDriverDownloadDialog(QDialog):
self.__confirmed = False self.__confirmed = False
self.__selected_driver_info = None self.__selected_driver_info = None
self.reject() self.reject()
def closeEvent(
self,
event: QCloseEvent
):
if self.__download_thread and self.__download_thread.isRunning():
reply = QMessageBox.question(
self,
"确认关闭 - AutoLibrary",
"驱动正在下载中, 确定要取消并关闭对话框吗 ?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
)
if reply == QMessageBox.StandardButton.No:
event.ignore()
return
self.__download_thread.stop()
if not self.__confirmed:
self.__selected_driver_info = None
event.accept()
super().closeEvent(event)
def __onThreadFinished(
self
):
if self.__download_thread:
self.__download_thread.deleteLater()
self.__download_thread = None
def getSelectedDriverInfo(
self
) -> Optional[WebDriverInfo]:
return self.__selected_driver_info
def updateDriverInfoDisplay(
self,
driver_info: WebDriverInfo
):
if driver_info.driver_type == WebDriverType.CHROME:
driver_type = "Google Chrome"
elif driver_info.driver_type == WebDriverType.FIREFOX:
driver_type = "Mozilla Firefox"
elif driver_info.driver_type == WebDriverType.EDGE:
driver_type = "Microsoft Edge"
else:
driver_type = "未知"
self.BrowserTypeLabel.setText(f"类型:{driver_type}")
self.VersionLabel.setText(f"版本:{driver_info.driver_version}")
if driver_info.driver_path:
self.PathLabel.setText(str(driver_info.driver_path))
else:
self.PathLabel.setText("未安装")
match driver_info.driver_status:
case WebDriverStatus.NOT_INSTALLED:
self.StatusLabel.status = ALStatusLabel.Status.WAITING
case WebDriverStatus.INSTALLED:
self.StatusLabel.status = ALStatusLabel.Status.SUCCESS
case WebDriverStatus.DOWNLOADING:
self.StatusLabel.status = ALStatusLabel.Status.RUNNING
case WebDriverStatus.ERROR:
self.StatusLabel.status = ALStatusLabel.Status.FAILURE
def updateProgressBarStates(
self,
driver_info: WebDriverInfo
):
if driver_info.driver_status == WebDriverStatus.NOT_INSTALLED:
self.ProgressBar.setValue(0)
self.ProgressText.setText("未安装")
elif driver_info.driver_status == WebDriverStatus.INSTALLED:
self.ProgressBar.setValue(100)
self.ProgressText.setText("已安装")
elif driver_info.driver_status == WebDriverStatus.DOWNLOADING:
pass # update by worker thread
elif driver_info.driver_status == WebDriverStatus.ERROR:
self.ProgressBar.setValue(0)
self.ProgressText.setText("下载失败")
def updateButtonStates(
self,
driver_info: WebDriverInfo
):
if driver_info.driver_status == WebDriverStatus.NOT_INSTALLED:
self.RefreshButton.setEnabled(True)
self.DeleteButton.setEnabled(False)
self.DownloadButton.setEnabled(True)
self.CancelButton.setEnabled(True)
self.ConfirmButton.setEnabled(False)
elif driver_info.driver_status == WebDriverStatus.INSTALLED:
self.RefreshButton.setEnabled(True)
self.DownloadButton.setEnabled(False)
self.DeleteButton.setEnabled(True)
self.CancelButton.setEnabled(True)
self.ConfirmButton.setEnabled(True)
elif driver_info.driver_status == WebDriverStatus.DOWNLOADING:
self.RefreshButton.setEnabled(False)
self.DownloadButton.setEnabled(False)
self.DeleteButton.setEnabled(False)
self.CancelButton.setEnabled(True)
self.ConfirmButton.setEnabled(False)
elif driver_info.driver_status == WebDriverStatus.ERROR:
self.RefreshButton.setEnabled(True)
self.DownloadButton.setEnabled(True)
self.DeleteButton.setEnabled(False)
self.CancelButton.setEnabled(True)
self.ConfirmButton.setEnabled(False)
+2
View File
@@ -16,6 +16,7 @@ class ConfigType(Enum):
""" """
Config type enum. Values represent the default filename. Config type enum. Values represent the default filename.
""" """
GLOBAL = "autolibrary.json" GLOBAL = "autolibrary.json"
BULLETIN = "bulletin.json" BULLETIN = "bulletin.json"
TIMERTASK = "timer_task.json" TIMERTASK = "timer_task.json"
@@ -30,6 +31,7 @@ class ConfigPath:
Consumers pass this directly to ConfigProvider.get/set, Consumers pass this directly to ConfigProvider.get/set,
eliminating the need to import ConfigType separately. eliminating the need to import ConfigType separately.
""" """
config_type: ConfigType config_type: ConfigType
key: str = "" key: str = ""
+1 -7
View File
@@ -33,7 +33,6 @@ class ConfigTemplate:
self.__config_type = config_type self.__config_type = config_type
def template( def template(
self self
) -> dict: ) -> dict:
@@ -83,7 +82,6 @@ class ConfigManager:
self.initialize() self.initialize()
def initialize( def initialize(
self self
): ):
@@ -91,7 +89,6 @@ class ConfigManager:
for config_type in ConfigType: for config_type in ConfigType:
self.load(config_type) self.load(config_type)
def load( def load(
self, self,
config_type: ConfigType config_type: ConfigType
@@ -108,7 +105,6 @@ class ConfigManager:
self.__config_data[config_type.value] = ConfigTemplate(config_type).template() self.__config_data[config_type.value] = ConfigTemplate(config_type).template()
JSONWriter(config_path, self.__config_data[config_type.value]) JSONWriter(config_path, self.__config_data[config_type.value])
def get( def get(
self, self,
key: ConfigPath, key: ConfigPath,
@@ -126,7 +122,6 @@ class ConfigManager:
return default return default
return config_data.get(keys[-1], default) return config_data.get(keys[-1], default)
def set( def set(
self, self,
key: ConfigPath, key: ConfigPath,
@@ -147,7 +142,6 @@ class ConfigManager:
config_data[keys[-1]] = value config_data[keys[-1]] = value
self.save(key.config_type) self.save(key.config_type)
def save( def save(
self, self,
config_type: ConfigType config_type: ConfigType
@@ -156,7 +150,6 @@ class ConfigManager:
config_path = os.path.join(self.__config_dir, config_type.value) config_path = os.path.join(self.__config_dir, config_type.value)
JSONWriter(config_path, self.__config_data[config_type.value]) JSONWriter(config_path, self.__config_data[config_type.value])
def configDir( def configDir(
self self
) -> str: ) -> str:
@@ -169,6 +162,7 @@ _config_manager_instance : ConfigManager | None = None
# Singleton instance of ConfigManager. # Singleton instance of ConfigManager.
_instance_lock = threading.Lock() _instance_lock = threading.Lock()
def instance( def instance(
config_dir: str = "" config_dir: str = ""
) -> ConfigManager: ) -> ConfigManager:
+1 -2
View File
@@ -41,6 +41,7 @@ class WebBrowserArch(Enum):
MACX86_64 = 6 MACX86_64 = 6
MACARM = 7 MACARM = 7
@dataclass @dataclass
class WebBrowserInfo: class WebBrowserInfo:
""" """
@@ -70,7 +71,6 @@ class WebBrowserArchDetector:
pass pass
def detect( def detect(
self self
) -> WebBrowserArch: ) -> WebBrowserArch:
@@ -123,7 +123,6 @@ class WebBrowserDetector:
self.browser_arch = WebBrowserArchDetector().detect() self.browser_arch = WebBrowserArchDetector().detect()
self.browser_infos : list[WebBrowserInfo] = [] self.browser_infos : list[WebBrowserInfo] = []
def detect( def detect(
self self
) -> list[WebBrowserInfo]: ) -> list[WebBrowserInfo]:
+23 -31
View File
@@ -95,7 +95,6 @@ class WebDriverName:
self.driver_type = driver_type self.driver_type = driver_type
def __str__( def __str__(
self self
) -> str: ) -> str:
@@ -125,7 +124,6 @@ class WebDriverExecName:
self.driver_type = driver_type self.driver_type = driver_type
self.arch = arch self.arch = arch
def __str__( def __str__(
self self
) -> str: ) -> str:
@@ -200,7 +198,6 @@ class WebDriverURL:
self.arch = arch self.arch = arch
self.file_name = str(WebDriverFileName(self.version, self.driver_type, self.arch)) self.file_name = str(WebDriverFileName(self.version, self.driver_type, self.arch))
def __str__( def __str__(
self self
) -> str: ) -> str:
@@ -250,31 +247,6 @@ class WebDriverDownloader:
self.download_dir.mkdir(mode=0o0755, parents=True, exist_ok=True) self.download_dir.mkdir(mode=0o0755, parents=True, exist_ok=True)
self.download_path = self.download_dir/str(WebDriverFileName(self.version, self.driver_type, self.arch)) self.download_path = self.download_dir/str(WebDriverFileName(self.version, self.driver_type, self.arch))
def download(
self,
progress_callback: Optional[Callable[[float, int, float, str], None]] = None,
cancel_event: Optional[threading.Event] = None
) -> Optional[Path]:
try:
# downlaod file : 0% - 98%
if not self._download(progress_callback, cancel_event=cancel_event):
return None
# verify file : 98% - 99%
if not self._verify(progress_callback):
progress_callback(0, 100, 0.0, "验证失败")
return None
# extract file : 99% - 100%
driver_path = self._extract(progress_callback)
if not driver_path:
progress_callback(0, 100, 0.0, "解压失败")
return None
return driver_path
except Exception as e:
raise e
def _download( def _download(
self, self,
progress_callback: Optional[Callable[[float, int, float, str], None]] = None, progress_callback: Optional[Callable[[float, int, float, str], None]] = None,
@@ -352,7 +324,6 @@ class WebDriverDownloader:
continue continue
raise e raise e
def _verify( def _verify(
self, self,
progress_callback: Optional[Callable[[float, int, float, str], None]] = None progress_callback: Optional[Callable[[float, int, float, str], None]] = None
@@ -361,7 +332,6 @@ class WebDriverDownloader:
progress_callback(98, 100, 0.0, "验证完成") progress_callback(98, 100, 0.0, "验证完成")
return True return True
def _extract( def _extract(
self, self,
progress_callback: Optional[Callable[[float, int, float, str], None]] = None progress_callback: Optional[Callable[[float, int, float, str], None]] = None
@@ -397,7 +367,6 @@ class WebDriverDownloader:
except Exception: except Exception:
return None return None
def _cleanup( def _cleanup(
self, self,
driver_file: Path driver_file: Path
@@ -410,6 +379,29 @@ class WebDriverDownloader:
else: else:
item.unlink() item.unlink()
def download(
self,
progress_callback: Optional[Callable[[float, int, float, str], None]] = None,
cancel_event: Optional[threading.Event] = None
) -> Optional[Path]:
try:
# downlaod file : 0% - 98%
if not self._download(progress_callback, cancel_event=cancel_event):
return None
# verify file : 98% - 99%
if not self._verify(progress_callback):
progress_callback(0, 100, 0.0, "验证失败")
return None
# extract file : 99% - 100%
driver_path = self._extract(progress_callback)
if not driver_path:
progress_callback(0, 100, 0.0, "解压失败")
return None
return driver_path
except Exception as e:
raise e
class ChromeDriverDownloader(WebDriverDownloader): class ChromeDriverDownloader(WebDriverDownloader):
""" """
-16
View File
@@ -81,7 +81,6 @@ class WebDriverManager:
self.initialize() self.initialize()
def initialize( def initialize(
self self
): ):
@@ -93,7 +92,6 @@ class WebDriverManager:
self._checkDriverStatus() self._checkDriverStatus()
self.__initialized = True self.__initialized = True
def _detectBrowsers( def _detectBrowsers(
self self
): ):
@@ -105,7 +103,6 @@ class WebDriverManager:
for info in browser_infos for info in browser_infos
] ]
def _checkDriverStatus( def _checkDriverStatus(
self self
): ):
@@ -117,7 +114,6 @@ class WebDriverManager:
driver_info.driver_path = driver_path driver_info.driver_path = driver_path
driver_info.driver_status = WebDriverStatus.INSTALLED driver_info.driver_status = WebDriverStatus.INSTALLED
def _mapWebBrowserTypeToDriver( def _mapWebBrowserTypeToDriver(
self, self,
browser_type: WebBrowserType browser_type: WebBrowserType
@@ -132,7 +128,6 @@ class WebDriverManager:
else: else:
raise ValueError(f"不支持的 Web 浏览器类型 : {browser_type}") raise ValueError(f"不支持的 Web 浏览器类型 : {browser_type}")
def _mapWebBrowserArchToDriver( def _mapWebBrowserArchToDriver(
self, self,
browser_type: WebBrowserType, browser_type: WebBrowserType,
@@ -199,7 +194,6 @@ class WebDriverManager:
else: else:
raise ValueError(f"不支持的 Web 浏览器类型 : {browser_type}") raise ValueError(f"不支持的 Web 浏览器类型 : {browser_type}")
def _mapFirefoxDriverVersion( def _mapFirefoxDriverVersion(
self, self,
version: str version: str
@@ -240,7 +234,6 @@ class WebDriverManager:
except Exception as e: except Exception as e:
raise ValueError(f"无效的 Firefox 版本格式 : {version}") from e raise ValueError(f"无效的 Firefox 版本格式 : {version}") from e
def _getDriverInfo( def _getDriverInfo(
self, self,
browser_info: WebBrowserInfo browser_info: WebBrowserInfo
@@ -256,7 +249,6 @@ class WebDriverManager:
driver_info.browser_version = browser_info.browser_version driver_info.browser_version = browser_info.browser_version
return driver_info return driver_info
def _getDriverPath( def _getDriverPath(
self, self,
driver_info: WebDriverInfo driver_info: WebDriverInfo
@@ -286,7 +278,6 @@ class WebDriverManager:
driver_path = driver_dir/exe_name driver_path = driver_dir/exe_name
return driver_path return driver_path
def refresh( def refresh(
self self
): ):
@@ -294,7 +285,6 @@ class WebDriverManager:
self._detectBrowsers() self._detectBrowsers()
self._checkDriverStatus() self._checkDriverStatus()
def getDriverInfos( def getDriverInfos(
self self
) -> list[WebDriverInfo]: ) -> list[WebDriverInfo]:
@@ -302,7 +292,6 @@ class WebDriverManager:
with self.__lock: with self.__lock:
return self.__driver_infos.copy() return self.__driver_infos.copy()
def getDriverInfo( def getDriverInfo(
self, self,
driver_type: WebDriverType driver_type: WebDriverType
@@ -315,7 +304,6 @@ class WebDriverManager:
if info.driver_type == driver_type if info.driver_type == driver_type
] ]
def getDriverPath( def getDriverPath(
self, self,
driver_info: WebDriverInfo driver_info: WebDriverInfo
@@ -325,7 +313,6 @@ class WebDriverManager:
return driver_info.driver_path return driver_info.driver_path
return None return None
def installDriver( def installDriver(
self, self,
driver_info: WebDriverInfo, driver_info: WebDriverInfo,
@@ -390,7 +377,6 @@ class WebDriverManager:
driver_info.driver_status = WebDriverStatus.ERROR driver_info.driver_status = WebDriverStatus.ERROR
raise e raise e
def cancelDriverDownload( def cancelDriverDownload(
self, self,
driver_info: WebDriverInfo driver_info: WebDriverInfo
@@ -411,7 +397,6 @@ class WebDriverManager:
except Exception: except Exception:
return False return False
def uninstallDriver( def uninstallDriver(
self, self,
driver_info: WebDriverInfo, driver_info: WebDriverInfo,
@@ -441,7 +426,6 @@ class WebDriverManager:
driver_info.driver_status = WebDriverStatus.ERROR driver_info.driver_status = WebDriverStatus.ERROR
raise raise
def driverDir( def driverDir(
self self
) -> str: ) -> str:
+1 -4
View File
@@ -89,7 +89,6 @@ class LogManager:
self.initialize() self.initialize()
def initialize( def initialize(
self self
): ):
@@ -139,7 +138,6 @@ class LogManager:
self.__initialized = True self.__initialized = True
def getLogger( def getLogger(
self, self,
name: Optional[str] = None name: Optional[str] = None
@@ -149,7 +147,6 @@ class LogManager:
return self.__logger.getChild(name) return self.__logger.getChild(name)
return self.__logger return self.__logger
def setLevel( def setLevel(
self, self,
level: int level: int
@@ -158,7 +155,6 @@ class LogManager:
if self.__logger: if self.__logger:
self.__logger.setLevel(level) self.__logger.setLevel(level)
def logDir( def logDir(
self self
) -> str: ) -> str:
@@ -171,6 +167,7 @@ _log_manager_instance = None
# Singleton instance lock. # Singleton instance lock.
_instance_lock = threading.Lock() _instance_lock = threading.Lock()
def instance( def instance(
log_dir: str = "" log_dir: str = ""
) -> LogManager: ) -> LogManager:
-7
View File
@@ -49,7 +49,6 @@ class AutoLib(MsgBase):
raise Exception("浏览器驱动URL初始化失败 !") raise Exception("浏览器驱动URL初始化失败 !")
self.__initLibOperators() self.__initLibOperators()
def __initBrowserDriver( def __initBrowserDriver(
self self
) -> bool: ) -> bool:
@@ -142,7 +141,6 @@ class AutoLib(MsgBase):
self._showTrace(f"浏览器驱动已初始化, 类型: {self.__driver_type}, 路径: {self.__driver_path}") self._showTrace(f"浏览器驱动已初始化, 类型: {self.__driver_type}, 路径: {self.__driver_path}")
return True return True
def __initLibOperators( def __initLibOperators(
self self
): ):
@@ -157,7 +155,6 @@ class AutoLib(MsgBase):
self.__lib_checkin = LibCheckin(self._input_queue, self._output_queue, self.__driver) self.__lib_checkin = LibCheckin(self._input_queue, self._output_queue, self.__driver)
self.__lib_renew = LibRenew(self._input_queue, self._output_queue, self.__driver) self.__lib_renew = LibRenew(self._input_queue, self._output_queue, self.__driver)
def __waitResponseLoad( def __waitResponseLoad(
self self
) -> bool: ) -> bool:
@@ -184,7 +181,6 @@ class AutoLib(MsgBase):
self._showTrace(f"登录页面加载失败 !", self.TraceLevel.ERROR) self._showTrace(f"登录页面加载失败 !", self.TraceLevel.ERROR)
return False return False
def __initDriverUrl( def __initDriverUrl(
self, self,
) -> bool: ) -> bool:
@@ -207,7 +203,6 @@ class AutoLib(MsgBase):
return False return False
return True return True
def __run( def __run(
self, self,
username: str, username: str,
@@ -292,7 +287,6 @@ class AutoLib(MsgBase):
return -1 return -1
return result return result
def run( def run(
self, self,
user_config: dict user_config: dict
@@ -339,7 +333,6 @@ class AutoLib(MsgBase):
) )
return return
def close( def close(
self self
) -> bool: ) -> bool:
-12
View File
@@ -33,7 +33,6 @@ class LibChecker(LibOperator):
self.__driver = driver self.__driver = driver
def _waitResponseLoad( def _waitResponseLoad(
self self
) -> bool: ) -> bool:
@@ -50,7 +49,6 @@ class LibChecker(LibOperator):
seconds = int(seconds%60) seconds = int(seconds%60)
return f"{hours}{minutes}{seconds}" return f"{hours}{minutes}{seconds}"
def __navigateToReserveRecordPage( def __navigateToReserveRecordPage(
self self
) -> bool: ) -> bool:
@@ -67,7 +65,6 @@ class LibChecker(LibOperator):
return False return False
return True return True
def __decodeReserveTime( def __decodeReserveTime(
self, self,
time_element time_element
@@ -105,7 +102,6 @@ class LibChecker(LibOperator):
} }
} }
def __decodeReserveInfo( def __decodeReserveInfo(
self, self,
info_elements info_elements
@@ -133,7 +129,6 @@ class LibChecker(LibOperator):
"status": status, "status": status,
} }
def __decodeReserveRecord( def __decodeReserveRecord(
self, self,
reservation reservation
@@ -160,7 +155,6 @@ class LibChecker(LibOperator):
"info": info "info": info
} }
def __loadReserveRecords( def __loadReserveRecords(
self self
) -> list: ) -> list:
@@ -177,7 +171,6 @@ class LibChecker(LibOperator):
self._showTrace("加载预约记录失败 !", self.TraceLevel.ERROR) self._showTrace("加载预约记录失败 !", self.TraceLevel.ERROR)
return None return None
def __showMoreReserveRecords( def __showMoreReserveRecords(
self self
) -> bool: ) -> bool:
@@ -203,7 +196,6 @@ class LibChecker(LibOperator):
self._showTrace("加载更多预约记录失败 !", self.TraceLevel.ERROR) self._showTrace("加载更多预约记录失败 !", self.TraceLevel.ERROR)
return False return False
def __getReserveRecord( def __getReserveRecord(
self, self,
wanted_date: str, wanted_date: str,
@@ -253,7 +245,6 @@ class LibChecker(LibOperator):
break break
return None return None
def canReserve( def canReserve(
self, self,
date: str date: str
@@ -270,7 +261,6 @@ class LibChecker(LibOperator):
self._showTrace(f"用户在 {date} 已存在有效预约, 无法预约") self._showTrace(f"用户在 {date} 已存在有效预约, 无法预约")
return False return False
def canCheckin( def canCheckin(
self self
) -> bool: ) -> bool:
@@ -307,7 +297,6 @@ class LibChecker(LibOperator):
self._showTrace(f"用户在 {date} 没有有效预约记录, 无法签到") self._showTrace(f"用户在 {date} 没有有效预约记录, 无法签到")
return False return False
def canRenew( def canRenew(
self self
) -> tuple[bool, dict]: ) -> tuple[bool, dict]:
@@ -335,7 +324,6 @@ class LibChecker(LibOperator):
self._showTrace(f"用户在 {date} 没有有效预约记录, 无法续约") self._showTrace(f"用户在 {date} 没有有效预约记录, 无法续约")
return False, None return False, None
def postRenewCheck( def postRenewCheck(
self, self,
record: dict record: dict
-3
View File
@@ -31,7 +31,6 @@ class LibCheckin(LibOperator):
self.__driver = driver self.__driver = driver
def _waitResponseLoad( def _waitResponseLoad(
self self
) -> bool: ) -> bool:
@@ -87,7 +86,6 @@ class LibCheckin(LibOperator):
ok_btn.click() ok_btn.click()
return False return False
def __enableCheckinBtn( def __enableCheckinBtn(
self self
) -> bool: ) -> bool:
@@ -112,7 +110,6 @@ class LibCheckin(LibOperator):
self._showTrace("签到按钮启用失败", self.TraceLevel.WARNING) self._showTrace("签到按钮启用失败", self.TraceLevel.WARNING)
return result return result
def checkin( def checkin(
self, self,
username: str username: str
-1
View File
@@ -33,7 +33,6 @@ class LibCheckout(LibOperator):
self.__driver = driver self.__driver = driver
def _waitResponseLoad( def _waitResponseLoad(
self self
) -> bool: ) -> bool:
-8
View File
@@ -34,7 +34,6 @@ class LibLogin(LibOperator):
self.__driver = driver self.__driver = driver
self.__ddddocr = ddddocr.DdddOcr() self.__ddddocr = ddddocr.DdddOcr()
def _waitResponseLoad( def _waitResponseLoad(
self self
) -> bool: ) -> bool:
@@ -58,7 +57,6 @@ class LibLogin(LibOperator):
) )
return False return False
def __fillLogInElements( def __fillLogInElements(
self, self,
username: str, username: str,
@@ -78,7 +76,6 @@ class LibLogin(LibOperator):
return False return False
return True return True
def __autoRecognizeCaptcha( def __autoRecognizeCaptcha(
self self
) -> str: ) -> str:
@@ -100,7 +97,6 @@ class LibLogin(LibOperator):
self._showTrace(f"验证码识别失败 ! : {e}", self.TraceLevel.ERROR) self._showTrace(f"验证码识别失败 ! : {e}", self.TraceLevel.ERROR)
return "" return ""
def __manualRecognizeCaptcha( def __manualRecognizeCaptcha(
self self
) -> str: ) -> str:
@@ -118,7 +114,6 @@ class LibLogin(LibOperator):
self._showTrace(f"输入验证码失败 ! : {e}", self.TraceLevel.ERROR) self._showTrace(f"输入验证码失败 ! : {e}", self.TraceLevel.ERROR)
return "" return ""
def __refreshCaptcha( def __refreshCaptcha(
self self
): ):
@@ -134,7 +129,6 @@ class LibLogin(LibOperator):
self._showTrace(f"刷新验证码失败 ! : {e}", self.TraceLevel.ERROR) self._showTrace(f"刷新验证码失败 ! : {e}", self.TraceLevel.ERROR)
return False return False
def __solveCaptcha( def __solveCaptcha(
self, self,
auto_captcha: bool = True auto_captcha: bool = True
@@ -158,7 +152,6 @@ class LibLogin(LibOperator):
) )
return "" return ""
def __fillCaptchaElement( def __fillCaptchaElement(
self, self,
captcha_text: str captcha_text: str
@@ -173,7 +166,6 @@ class LibLogin(LibOperator):
self._showTrace(f"验证码填写失败 ! : {e}", self.TraceLevel.ERROR) self._showTrace(f"验证码填写失败 ! : {e}", self.TraceLevel.ERROR)
return False return False
def login( def login(
self, self,
username: str, username: str,
-2
View File
@@ -28,14 +28,12 @@ class LibLogout(LibOperator):
self.__driver = driver self.__driver = driver
def _waitResponseLoad( def _waitResponseLoad(
self self
) -> bool: ) -> bool:
return True return True
def logout( def logout(
self, self,
username: str username: str
+1 -7
View File
@@ -14,7 +14,7 @@ from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from base.LibTimeSelector import LibTimeSelector from operators.abs.LibTimeSelector import LibTimeSelector
class LibRenew(LibTimeSelector): class LibRenew(LibTimeSelector):
@@ -30,7 +30,6 @@ class LibRenew(LibTimeSelector):
self.__driver = driver self.__driver = driver
def _waitResponseLoad( def _waitResponseLoad(
self self
) -> bool: ) -> bool:
@@ -38,7 +37,6 @@ class LibRenew(LibTimeSelector):
self.__driver.refresh() self.__driver.refresh()
return True return True
def __waitRenewDialog( def __waitRenewDialog(
self self
) -> bool: ) -> bool:
@@ -77,7 +75,6 @@ class LibRenew(LibTimeSelector):
return False return False
return True return True
def __selectNearestTime( def __selectNearestTime(
self, self,
record: dict, record: dict,
@@ -116,7 +113,6 @@ class LibRenew(LibTimeSelector):
self._showTrace(f"当前可供续约的时间有: {free_times}") self._showTrace(f"当前可供续约的时间有: {free_times}")
return False return False
def __validateAndAdjustRenewTime( def __validateAndAdjustRenewTime(
self, self,
end_time: str, end_time: str,
@@ -139,7 +135,6 @@ class LibRenew(LibTimeSelector):
return True return True
return True return True
def __confirmRenewal( def __confirmRenewal(
self, self,
best_opt, best_opt,
@@ -167,7 +162,6 @@ class LibRenew(LibTimeSelector):
self._showTrace("确认续约时发生错误 !", self.TraceLevel.ERROR) self._showTrace("确认续约时发生错误 !", self.TraceLevel.ERROR)
return False return False
def renew( def renew(
self, self,
username: str, username: str,
+3 -22
View File
@@ -15,7 +15,7 @@ from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support import expected_conditions as EC
from base.LibTimeSelector import LibTimeSelector from operators.abs.LibTimeSelector import LibTimeSelector
class LibReserve(LibTimeSelector): class LibReserve(LibTimeSelector):
@@ -48,7 +48,6 @@ class LibReserve(LibTimeSelector):
"8": "五层考研" "8": "五层考研"
} }
def _waitResponseLoad( def _waitResponseLoad(
self, self,
) -> bool: ) -> bool:
@@ -99,7 +98,6 @@ class LibReserve(LibTimeSelector):
self._showTrace(f"预约结果加载失败 !", self.TraceLevel.ERROR) self._showTrace(f"预约结果加载失败 !", self.TraceLevel.ERROR)
return False return False
def __containRequiredInfo( def __containRequiredInfo(
self, self,
reserve_info: dict reserve_info: dict
@@ -135,7 +133,6 @@ class LibReserve(LibTimeSelector):
) )
return False return False
def __isValidDate( def __isValidDate(
self, self,
reserve_info: dict reserve_info: dict
@@ -157,7 +154,6 @@ class LibReserve(LibTimeSelector):
reserve_info["date"] = cur_date_str reserve_info["date"] = cur_date_str
return True return True
def __isValidBeginTime( def __isValidBeginTime(
self, self,
reserve_info: dict reserve_info: dict
@@ -177,7 +173,6 @@ class LibReserve(LibTimeSelector):
self._showTrace(f"是否优先选择更早开始时间未指定, 自动设置为 True") self._showTrace(f"是否优先选择更早开始时间未指定, 自动设置为 True")
return True return True
def __isValidExpectDuration( def __isValidExpectDuration(
self, self,
reserve_info: dict reserve_info: dict
@@ -192,7 +187,6 @@ class LibReserve(LibTimeSelector):
self._showTrace("需要满足预约持续时间, 但未指定, 使用默认时长为 4 小时") self._showTrace("需要满足预约持续时间, 但未指定, 使用默认时长为 4 小时")
return True return True
def __isValidEndTime( def __isValidEndTime(
self, self,
reserve_info: dict reserve_info: dict
@@ -222,7 +216,6 @@ class LibReserve(LibTimeSelector):
self._showTrace(f"是否优先选择较晚结束时间未指定, 自动设置为 True") self._showTrace(f"是否优先选择较晚结束时间未指定, 自动设置为 True")
return True return True
def __finalCheck( def __finalCheck(
self, self,
reserve_info: dict reserve_info: dict
@@ -275,7 +268,6 @@ class LibReserve(LibTimeSelector):
reserve_info["end_time"]["time"] = self._minsToTimeStr(begin_mins + 8*60) reserve_info["end_time"]["time"] = self._minsToTimeStr(begin_mins + 8*60)
return True return True
def __checkReserveInfo( def __checkReserveInfo(
self, self,
reserve_info: dict reserve_info: dict
@@ -305,7 +297,6 @@ class LibReserve(LibTimeSelector):
) )
return True return True
def __clickElement( def __clickElement(
self, self,
trigger_locator: tuple, trigger_locator: tuple,
@@ -330,7 +321,6 @@ class LibReserve(LibTimeSelector):
self._showTrace(fail_msg) self._showTrace(fail_msg)
return False return False
def __clickElementByJS( def __clickElementByJS(
self, self,
trigger_locator_id: str, trigger_locator_id: str,
@@ -364,7 +354,6 @@ class LibReserve(LibTimeSelector):
self._showTrace(fail_msg) self._showTrace(fail_msg)
return result return result
def __selectDate( def __selectDate(
self, self,
date_str: str date_str: str
@@ -384,7 +373,6 @@ class LibReserve(LibTimeSelector):
fail_msg=f"选择日期失败 ! : {date_str} 不可用" fail_msg=f"选择日期失败 ! : {date_str} 不可用"
) )
def __selectPlace( def __selectPlace(
self, self,
place: str place: str
@@ -406,7 +394,6 @@ class LibReserve(LibTimeSelector):
fail_msg=f"选择预约场所失败 ! : {display_place} 不可用" fail_msg=f"选择预约场所失败 ! : {display_place} 不可用"
) )
def __selectFloor( def __selectFloor(
self, self,
floor: str floor: str
@@ -427,7 +414,6 @@ class LibReserve(LibTimeSelector):
fail_msg=f"选择楼层失败 ! : {display_floor} 不可用" fail_msg=f"选择楼层失败 ! : {display_floor} 不可用"
) )
def __selectRoom( def __selectRoom(
self, self,
room: str room: str
@@ -453,7 +439,6 @@ class LibReserve(LibTimeSelector):
self._showTrace(f"选择房间失败 ! : {display_room} 不可用", self.TraceLevel.ERROR) self._showTrace(f"选择房间失败 ! : {display_room} 不可用", self.TraceLevel.ERROR)
return False return False
def __selectSeat( def __selectSeat(
self, self,
seat_id: str seat_id: str
@@ -492,7 +477,6 @@ class LibReserve(LibTimeSelector):
self._showTrace(f"座位选择失败 !", self.TraceLevel.ERROR) self._showTrace(f"座位选择失败 !", self.TraceLevel.ERROR)
return False return False
def __selectNearestTime( def __selectNearestTime(
self, self,
time_id: str, time_id: str,
@@ -547,7 +531,6 @@ class LibReserve(LibTimeSelector):
self._showTrace(f"当前可供预约的 {time_type} 有: {free_times}") self._showTrace(f"当前可供预约的 {time_type} 有: {free_times}")
return -1 return -1
def __selectSeatTime( def __selectSeatTime(
self, self,
begin_time: dict, begin_time: dict,
@@ -583,7 +566,7 @@ class LibReserve(LibTimeSelector):
# If 'satisfy_duration' is True, select end time based on actual begin time # If 'satisfy_duration' is True, select end time based on actual begin time
if satisfy_duration: if satisfy_duration:
exp_end_mins = int(self.validateAndAdjustEndTime(act_beg_mins, expect_duration)) exp_end_mins = int(self.__validateAndAdjustEndTime(act_beg_mins, expect_duration))
exp_end_tm_str = self._minsToTimeStr(exp_end_mins) exp_end_tm_str = self._minsToTimeStr(exp_end_mins)
self._showTrace( self._showTrace(
f"需要满足期望预约持续时间: {expect_duration} 小时, " f"需要满足期望预约持续时间: {expect_duration} 小时, "
@@ -607,8 +590,7 @@ class LibReserve(LibTimeSelector):
) )
return True return True
def __validateAndAdjustEndTime(
def validateAndAdjustEndTime(
self, self,
begin_mins: int, begin_mins: int,
duration: int duration: int
@@ -627,7 +609,6 @@ class LibReserve(LibTimeSelector):
) )
return expect_end_mins return expect_end_mins
def reserve( def reserve(
self, self,
username: str, username: str,
@@ -16,7 +16,7 @@ from base.LibOperator import LibOperator
class LibTimeSelector(LibOperator): class LibTimeSelector(LibOperator):
""" """
Base class for time selection operations. Abstract base class for time selection operations.
This class provides common time selection logic for reservation and renewal This class provides common time selection logic for reservation and renewal
operations, including time conversion utilities and best time option finding. operations, including time conversion utilities and best time option finding.
@@ -60,7 +60,6 @@ class LibTimeSelector(LibOperator):
hour, minute = divmod(int(mins), 60) hour, minute = divmod(int(mins), 60)
return f"{hour:02d}:{minute:02d}" return f"{hour:02d}:{minute:02d}"
def _formatTimeRelation( def _formatTimeRelation(
self, self,
abs_diff: int, abs_diff: int,
@@ -78,7 +77,6 @@ class LibTimeSelector(LibOperator):
else: else:
return f"正好等于 {time_type}" return f"正好等于 {time_type}"
def _findBestTimeOption( def _findBestTimeOption(
self, self,
time_options: list, time_options: list,
+6
View File
@@ -0,0 +1,6 @@
"""
Abstract layer class of the LibOperator
Here are the classes and modules in this package:
- LibTimeSelector: Abstract base class for time selection operations.
"""
-4
View File
@@ -42,7 +42,6 @@ class JSONReader:
self.__json_data = None self.__json_data = None
self.__read() self.__read()
def __read( def __read(
self self
): ):
@@ -59,7 +58,6 @@ class JSONReader:
except Exception as e: except Exception as e:
raise Exception(f"读取文件时发生未知错误: {e}") from e raise Exception(f"读取文件时发生未知错误: {e}") from e
def read( def read(
self self
) -> bool: ) -> bool:
@@ -70,14 +68,12 @@ class JSONReader:
return False return False
return True return True
def data( def data(
self self
) -> dict: ) -> dict:
return self.__json_data.copy() return self.__json_data.copy()
def path( def path(
self self
) -> str: ) -> str:
-3
View File
@@ -46,7 +46,6 @@ class JSONWriter:
self.__json_data = json_data.copy() if json_data is not None else {} self.__json_data = json_data.copy() if json_data is not None else {}
self.__write() self.__write()
def __write( def __write(
self self
): ):
@@ -63,7 +62,6 @@ class JSONWriter:
except Exception as e: except Exception as e:
raise Exception(f"写入文件时发生未知错误: {e}") from e raise Exception(f"写入文件时发生未知错误: {e}") from e
def write( def write(
self self
) -> bool: ) -> bool:
@@ -74,7 +72,6 @@ class JSONWriter:
return False return False
return True return True
def path( def path(
self self
) -> str: ) -> str: