1
1
mirror of https://github.com/KenanZhu/AutoLibrary.git synced 2026-06-19 16:03:02 +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
+8 -11
View File
@@ -9,14 +9,17 @@ See the LICENSE file for details.
"""
import platform
from PySide6.QtCore import (
Qt,
QTimer
)
from PySide6.QtGui import (
QIcon, QFont
QFont,
QIcon
)
from PySide6.QtWidgets import (
QDialog, QApplication
)
from PySide6.QtCore import (
QTimer, Qt
QApplication,
QDialog
)
from gui.ALVersionInfo import (
@@ -38,7 +41,6 @@ class ALAboutDialog(QDialog, Ui_ALAboutDialog):
self.modifyUi()
self.connectSignals()
def modifyUi(
self
):
@@ -51,14 +53,12 @@ class ALAboutDialog(QDialog, Ui_ALAboutDialog):
self.AboutInfoBrowser.setFont(browser_font)
self.AboutInfoBrowser.setTextInteractionFlags(Qt.TextBrowserInteraction)
def connectSignals(
self
):
self.CopyButton.clicked.connect(self.copyAboutInfo)
def generateAboutText(
self
) -> str:
@@ -91,7 +91,6 @@ GitHub: <a href="https://www.github.com/KenanZhu" style="text-decoration: none;"
"""
return about_text
def getOSInfo(
self
):
@@ -123,7 +122,6 @@ GitHub: <a href="https://www.github.com/KenanZhu" style="text-decoration: none;"
'architecture': architecture
}
def getQtVersion(
self
):
@@ -134,7 +132,6 @@ GitHub: <a href="https://www.github.com/KenanZhu" style="text-decoration: none;"
except:
return "Unknown"
def copyAboutInfo(
self
):
+119 -133
View File
@@ -116,7 +116,6 @@ class ALScriptHighlighter(QSyntaxHighlighter):
commentFmt.setFontItalic(True)
self._rules.append((r"--[^\n]*", commentFmt))
def highlightBlock(
self,
text
@@ -169,7 +168,7 @@ class ALAutoScriptEditDialog(QDialog):
):
super().__init__(parent)
self._fontSize = 13
self._fontSize = 21
self._mockWidgets = {}
self.setupUi()
@@ -181,7 +180,6 @@ class ALAutoScriptEditDialog(QDialog):
if mockData:
self.setMockData(mockData)
def setupUi(
self
):
@@ -243,7 +241,7 @@ class ALAutoScriptEditDialog(QDialog):
"}"
)
layout.addWidget(self.textEdit)
self._createButtonPanel(layout)
self.createButtonPanel(layout)
self.btnBox = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok |
QDialogButtonBox.StandardButton.Cancel
@@ -252,8 +250,7 @@ class ALAutoScriptEditDialog(QDialog):
self.btnBox.button(QDialogButtonBox.StandardButton.Cancel).setText("取消")
layout.addWidget(self.btnBox)
def _createButtonPanel(
def createButtonPanel(
self,
parent_layout
):
@@ -273,11 +270,11 @@ class ALAutoScriptEditDialog(QDialog):
("结束 (end)", "end"),
("跳过 (pass)", "-- pass"),
]
self._addButtonsToGrid(basicLayout, controlButtons, 0, 0, 3)
self.addButtonsToGrid(basicLayout, controlButtons, 0, 0, 3)
assignButtons = [
("赋值 (=)", " = "),
]
self._addButtonsToGrid(basicLayout, assignButtons, 1, 2, 3)
self.addButtonsToGrid(basicLayout, assignButtons, 1, 2, 3)
tabWidget.addTab(basicWidget, "基本语法")
operatorWidget = QWidget()
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 = [
("等于 (==)", " == "),
("不等于 (~=)", " ~= "),
@@ -297,12 +294,12 @@ class ALAutoScriptEditDialog(QDialog):
("大于等于 (>=)", " >= "),
("小于等于 (<=)", " <= "),
]
self._addButtonsToGrid(operatorLayout, compareButtons, 1, 0, 3)
self.addButtonsToGrid(operatorLayout, compareButtons, 1, 0, 3)
logic_buttons = [
("且 (and)", " and "),
("或 (or)", " or "),
]
self._addButtonsToGrid(operatorLayout, logic_buttons, 2, 0, 3)
self.addButtonsToGrid(operatorLayout, logic_buttons, 2, 0, 3)
tabWidget.addTab(operatorWidget, "运算符")
literalWidget = QWidget()
literalLayout = QGridLayout(literalWidget)
@@ -313,18 +310,18 @@ class ALAutoScriptEditDialog(QDialog):
("真 (true)", "true"),
("假 (false)", "false"),
]
self._addButtonsToGrid(literalLayout, bool_buttons, 0, 0, 3)
self.addButtonsToGrid(literalLayout, bool_buttons, 0, 0, 3)
dateTimeButtons = [
("日期", '"2099-01-01"'),
("时间", '"00:00"'),
]
self._addButtonsToGrid(literalLayout, dateTimeButtons, 1, 0, 3)
self.addButtonsToGrid(literalLayout, dateTimeButtons, 1, 0, 3)
hintButtons = [
("字符串", '"请输入文本"'),
("数字", "123"),
("注释", "-- 请输入注释"),
]
self._addButtonsToGrid(literalLayout, hintButtons, 2, 0, 3)
self.addButtonsToGrid(literalLayout, hintButtons, 2, 0, 3)
tabWidget.addTab(literalWidget, "字面量")
varWidget = QWidget()
varLayout = QGridLayout(varWidget)
@@ -334,9 +331,9 @@ class ALAutoScriptEditDialog(QDialog):
varButtons = [
(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, "变量")
mockPanel = self._createMockPanel()
mockPanel = self.createMockPanel()
mockPanel.setMinimumWidth(260)
splitter.addWidget(tabWidget)
splitter.addWidget(mockPanel)
@@ -345,8 +342,7 @@ class ALAutoScriptEditDialog(QDialog):
splitter.setSizes([530, 530])
parent_layout.addWidget(splitter)
def _addButtonsToGrid(
def addButtonsToGrid(
self,
grid_layout,
buttons,
@@ -361,7 +357,7 @@ class ALAutoScriptEditDialog(QDialog):
for btn_text, template in buttons:
btn = QPushButton(btn_text)
btn.setProperty("template", template)
btn.clicked.connect(self._insertTemplate)
btn.clicked.connect(self.insertTemplate)
btn.setFixedWidth(100)
btn.setFixedHeight(25)
btn.setToolTip(f"插入: {template}")
@@ -371,22 +367,7 @@ class ALAutoScriptEditDialog(QDialog):
col = start_col
row += 1
@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)
def _createMockPanel(
def createMockPanel(
self
) -> QGroupBox:
@@ -397,14 +378,13 @@ class ALAutoScriptEditDialog(QDialog):
self._mockWidgets = {}
for name, var_type, key_path, display_name in _TARGET_VAR_DEFS:
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})")
form.addRow(label, widget)
self._mockWidgets[name] = (widget, var_type, key_path)
return group
def _makeMockInput(
def makeMockInput(
self,
var_type: str,
default
@@ -447,7 +427,6 @@ class ALAutoScriptEditDialog(QDialog):
w.setText(str(default))
return w
def getMockData(
self
) -> dict:
@@ -455,14 +434,13 @@ class ALAutoScriptEditDialog(QDialog):
data = {}
for name, var_type, key_path, display_name in _TARGET_VAR_DEFS:
widget, _, _ = self._mockWidgets[name]
value = self._getMockValue(widget, var_type)
value = self.getMockValue(widget, var_type)
d = data
for key in key_path[:-1]:
d = d.setdefault(key, {})
d[key_path[-1]] = value
return data
def setMockData(
self,
data: dict
@@ -478,10 +456,9 @@ class ALAutoScriptEditDialog(QDialog):
except (KeyError, TypeError):
continue
widget, _, _ = self._mockWidgets[name]
self._setMockValue(widget, var_type, d)
self.setMockValue(widget, var_type, d)
def _getMockValue(
def getMockValue(
self,
widget: QWidget,
var_type: str
@@ -499,8 +476,7 @@ class ALAutoScriptEditDialog(QDialog):
return widget.value()
return widget.text()
def _setMockValue(
def setMockValue(
self,
widget: QWidget,
var_type: str,
@@ -520,6 +496,103 @@ class ALAutoScriptEditDialog(QDialog):
else:
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()
def onDebugRun(
@@ -556,90 +629,3 @@ class ALAutoScriptEditDialog(QDialog):
dlg = _DebugResultDialog(changes, self)
dlg.exec()
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.addInitialConditionRow()
def setupUi(
self
):
@@ -103,7 +102,6 @@ class ConditionalBlock(QGroupBox):
mainLayout.addWidget(self.addActionBtn)
self.setUpdatesEnabled(True)
def connectSignals(
self
):
@@ -112,7 +110,6 @@ class ConditionalBlock(QGroupBox):
self.addCondBtn.clicked.connect(self.addConditionRow)
self.addActionBtn.clicked.connect(self.addActionStep)
def addInitialConditionRow(
self
):
@@ -124,7 +121,6 @@ class ConditionalBlock(QGroupBox):
self._conditionRows.append(row)
self.condRowsLayout.addWidget(row)
def addConditionRow(
self
):
@@ -137,7 +133,6 @@ class ConditionalBlock(QGroupBox):
self._conditionRows.append(row)
self.condRowsLayout.addWidget(row)
def removeConditionRow(
self,
row: ConditionRowFrame
@@ -149,7 +144,6 @@ class ConditionalBlock(QGroupBox):
row.hide()
row.deleteLater()
def addActionStep(
self
):
@@ -159,7 +153,6 @@ class ConditionalBlock(QGroupBox):
self._actionWidgets.append(step)
self.actionsLayout.addWidget(step)
def removeActionStep(
self,
step: ActionStepFrame
@@ -171,48 +164,31 @@ class ConditionalBlock(QGroupBox):
step.hide()
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(
self
) -> str:
return self.typeCombo.currentData()
def getConditionRows(
self
):
return list(self._conditionRows)
def getActionSteps(
self
):
return list(self._actionWidgets)
def countActionSteps(
self
) -> int:
return len(self._actionWidgets)
def toScriptLines(
def toScript(
self
) -> list:
"""
@@ -223,7 +199,7 @@ class ConditionalBlock(QGroupBox):
lines = []
if blockType in ("IF", "ELSE IF"):
condTexts = [
r.toConditionText() for r in self._conditionRows if r.toConditionText()
r.toScript() for r in self._conditionRows if r.toScript()
]
if not condTexts:
condTexts = ["true"]
@@ -245,12 +221,11 @@ class ConditionalBlock(QGroupBox):
else:
lines.append("else")
for step in self._actionWidgets:
scriptLine = step.toScriptLine()
scriptLine = step.toScript()
if scriptLine:
lines.append(scriptLine)
return lines
def refreshVarCombos(
self
):
@@ -260,7 +235,6 @@ class ConditionalBlock(QGroupBox):
for step in self._actionWidgets:
step.refreshVarCombos()
def setPrevBlockType(
self,
prevType: str | None
@@ -278,3 +252,15 @@ class ConditionalBlock(QGroupBox):
item.setEnabled(shouldEnable)
if prevType == "ELSE" and self.typeCombo.currentData() in ("ELSE IF", "ELSE"):
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.scrollLayout.addStretch()
def setupUi(
self
):
@@ -70,7 +69,6 @@ class ALAutoScriptOrchDialog(QDialog):
self.btnBox.button(QDialogButtonBox.StandardButton.Cancel).setText("取消")
mainLayout.addWidget(self.btnBox)
def connectSignals(
self
):
@@ -79,8 +77,7 @@ class ALAutoScriptOrchDialog(QDialog):
self.btnBox.rejected.connect(self.reject)
self.addBlockBtn.clicked.connect(self.addBlock)
def _updateBlockTypeRestrictions(
def updateBlockTypeRestrictions(
self
):
@@ -89,7 +86,6 @@ class ALAutoScriptOrchDialog(QDialog):
block.setPrevBlockType(prevType)
prevType = block.getBlockType()
def addBlock(
self
):
@@ -98,10 +94,10 @@ class ALAutoScriptOrchDialog(QDialog):
len(self._blocks), self._varMgr, parent=self
)
block.deleteBlockBtn.clicked.connect(lambda: self.removeBlock(block))
block.typeCombo.currentIndexChanged.connect(self._updateBlockTypeRestrictions)
block.typeCombo.currentIndexChanged.connect(self.updateBlockTypeRestrictions)
block.addActionStep()
self._blocks.append(block)
self._updateBlockTypeRestrictions()
self.updateBlockTypeRestrictions()
if self.scrollLayout.count() > 0:
lastItem = self.scrollLayout.itemAt(
self.scrollLayout.count() - 1
@@ -113,7 +109,6 @@ class ALAutoScriptOrchDialog(QDialog):
return
self.scrollLayout.addWidget(block)
def removeBlock(
self,
block: ConditionalBlock
@@ -135,8 +130,7 @@ class ALAutoScriptOrchDialog(QDialog):
else:
blk.typeCombo.setEnabled(True)
blk.refreshVarCombos()
self._updateBlockTypeRestrictions()
self.updateBlockTypeRestrictions()
def getScript(
self
@@ -151,7 +145,7 @@ class ALAutoScriptOrchDialog(QDialog):
blockType = block.getBlockType()
if blockType == "IF" and prevType is not None:
parts.append("end")
lines = block.toScriptLines()
lines = block.toScript()
parts.extend(lines)
prevType = blockType
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):
def __init__(
@@ -281,7 +106,6 @@ class _DateInputContainer(QWidget):
self._dynamicItems = {} # index -> raw expression, for one-way parsed items
self.setupUi()
def setupUi(
self
):
@@ -327,7 +151,6 @@ class _DateInputContainer(QWidget):
return self._relCombo.currentText()
return self._dateEdit.date().toString("yyyy-MM-dd")
def setValue(
self,
expr: str
@@ -392,14 +215,12 @@ class _TimeInputContainer(QWidget):
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self._timeEdit)
def getValue(
self
) -> str:
return self._timeEdit.time().toString("HH:mm")
def setValue(
self,
expr: str
@@ -443,14 +264,12 @@ class _DateOffsetContainer(QWidget):
layout.addWidget(self._unitCombo)
layout.addStretch()
def getValue(
self
) -> str:
return str(self.getOffsetDays())
def setValue(
self,
expr: str
@@ -462,7 +281,6 @@ class _DateOffsetContainer(QWidget):
except ValueError:
pass
def getOffsetDays(
self
) -> int:
@@ -477,7 +295,6 @@ class _DateOffsetContainer(QWidget):
return val * 365
return val
def getRawValue(
self
) -> str:
@@ -502,14 +319,12 @@ class _TimeOffsetContainer(QWidget):
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self._spinBox)
def getValue(
self
) -> str:
return str(self.getOffsetHours())
def setValue(
self,
expr: str
@@ -521,14 +336,12 @@ class _TimeOffsetContainer(QWidget):
except ValueError:
pass
def getOffsetHours(
self
) -> int:
return self._spinBox.value()
def getRawValue(
self
) -> str:
@@ -536,6 +349,172 @@ class _TimeOffsetContainer(QWidget):
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(
w: QWidget
) -> str:
@@ -556,8 +535,7 @@ def getValueFromWidget(
return w.text()
return ""
def setWidgetValue(
def setValueToWidget(
w: QWidget,
var_type: str,
expr: str
@@ -619,7 +597,6 @@ def setWidgetValue(
inner = inner[1:-1].replace('\\"', '"')
w.setText(inner)
def encodeValueStr(
raw_value: str,
var_type: str
@@ -632,7 +609,7 @@ def encodeValueStr(
"""
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):
return "true" if raw_value else "false"
s = str(raw_value)
@@ -648,8 +625,7 @@ def encodeValueStr(
return f'"{escaped}"'
return s
def _encodeDateOrTime(
def encodeDateOrTime(
raw_value: str,
var_type: str
) -> str:
@@ -707,7 +683,6 @@ def _encodeDateOrTime(
return s
return f'"{s}"'
def stripOuterParens(
s: str
) -> str:
@@ -725,12 +700,10 @@ def stripOuterParens(
return s[1:-1].strip()
return s
# Pre-compiled patterns for detecting arithmetic expressions (A + B / A - B)
_RE_ARITH_SPACED = re.compile(r'^(.+?)\s+([+-])\s+(.+)$')
_RE_ARITH_NOSPACE = re.compile(r'^([A-Za-z_]\w*)([+-])(\d+|[A-Za-z_]\w*)$')
def isArithExpr(
expr: str
) -> bool:
@@ -741,7 +714,6 @@ def isArithExpr(
s = expr.strip()
return bool(_RE_ARITH_SPACED.match(s) or _RE_ARITH_NOSPACE.match(s))
def isVarReference(
expr: str
) -> bool:
@@ -764,27 +736,7 @@ def isVarReference(
return False
return bool(re.match(r"^[A-Z_][A-Z0-9_]*$", up))
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(
def isInsideLiteral(
text: str,
pos: int
) -> bool:
@@ -799,3 +751,21 @@ def _isInsideLiteral(
elif ch == '"' and not in_single:
in_double = not 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.connectSignals()
def setupUi(
self
):
@@ -90,15 +89,7 @@ class ConditionRowFrame(QFrame):
layout.addWidget(self._compTypeCombo)
self.rhsStack = QStackedWidget(self)
self.rhsStack.setFixedHeight(25)
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)
self.initLiteralStack()
self.rhsVarCombo = makeVarRefCombo(self)
self.rhsStack.addWidget(self.rhsVarCombo)
self.rhsStack.setCurrentIndex(0)
@@ -113,7 +104,6 @@ class ConditionRowFrame(QFrame):
layout.addStretch()
self.setUpdatesEnabled(True)
def populateLeftVarCombo(
self
):
@@ -136,13 +126,25 @@ class ConditionRowFrame(QFrame):
self.leftVarCombo.setCurrentIndex(ci)
break
def populateRhsVarCombo(
def populateRHSVarCombo(
self
):
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(
self
@@ -151,58 +153,22 @@ class ConditionRowFrame(QFrame):
self.leftVarCombo.currentIndexChanged.connect(self.onLeftVarChanged)
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(
self
) -> str:
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
) -> str:
@@ -230,20 +196,53 @@ class ConditionRowFrame(QFrame):
if rhsText:
return f"{name} {opSym} {rhsText}"
return ""
w = self.literalWidgets.get(vartype)
w = self._literalWidgets.get(vartype)
if w:
rawVal = getValueFromWidget(w)
encoded = encodeValueStr(rawVal, vartype)
return f"{name} {opSym} {encoded}"
return ""
def refreshVarCombos(
self
):
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):
@@ -262,7 +261,6 @@ class ActionStepFrame(QFrame):
self.setupUi()
self.connectSignals()
def setupUi(
self
):
@@ -280,7 +278,7 @@ class ActionStepFrame(QFrame):
self.targetCombo = QComboBox(self)
self.targetCombo.setFixedHeight(25)
self.targetCombo.setMinimumWidth(120)
self.buildTargetCombo()
self.populateTargetCombo()
layout.addWidget(self.targetCombo)
layout.addWidget(makeLabel("", self))
self.valueSrcCombo = makeComboWidget([
@@ -301,8 +299,7 @@ class ActionStepFrame(QFrame):
layout.addWidget(self.deleteBtn)
self.setUpdatesEnabled(True)
def buildTargetCombo(
def populateTargetCombo(
self
):
@@ -319,7 +316,6 @@ class ActionStepFrame(QFrame):
)
self.targetCombo.blockSignals(False)
def initValueStacks(
self
):
@@ -338,7 +334,6 @@ class ActionStepFrame(QFrame):
self._offsetWidgets[vt] = lbl
self.valueStack.addWidget(lbl)
def connectSignals(
self
):
@@ -347,32 +342,14 @@ class ActionStepFrame(QFrame):
self.targetCombo.currentIndexChanged.connect(self.onTargetChanged)
self.valueSrcCombo.currentIndexChanged.connect(self.onValueSrcChanged)
@Slot(int)
def onTargetChanged(
self,
idx
):
def getTargetName(
self
) -> str:
if idx < 0:
return
data = self.targetCombo.itemData(idx)
if not data:
return
_, vartype = data
self._currentTargetType = vartype
self.updateRHSWidget()
self.onValueSrcChanged(self.valueSrcCombo.currentIndex())
data = self.targetCombo.currentData()
return data[0] if data else ""
@Slot(int)
def onOpTypeChanged(
self,
idx
):
self.updateRHSWidget()
def updateRHSWidget(
def updateValueWidget(
self
):
@@ -386,30 +363,7 @@ class ActionStepFrame(QFrame):
else:
self.valueStack.setCurrentWidget(self._literalWidgets.get("String"))
@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.updateRHSWidget()
def getTargetName(
self
) -> str:
data = self.targetCombo.currentData()
return data[0] if data else ""
def toScriptLine(
def toScript(
self
) -> str:
"""
@@ -422,7 +376,7 @@ class ActionStepFrame(QFrame):
return " -- pass"
if not target:
return ""
rawVal = self._getValueRaw()
rawVal = self.getValueRaw()
vartype = self._currentTargetType
if op == "set":
encoded = encodeValueStr(rawVal, vartype)
@@ -445,8 +399,7 @@ class ActionStepFrame(QFrame):
return f" {target} = {target} - {rawVal}"
return ""
def _getValueRaw(
def getValueRaw(
self
) -> str:
@@ -458,13 +411,12 @@ class ActionStepFrame(QFrame):
return getValueFromWidget(w)
return ""
def refreshVarCombos(
self
):
currentData = self.targetCombo.currentData()
self.buildTargetCombo()
self.populateTargetCombo()
if currentData:
for i in range(self.targetCombo.count()):
d = self.targetCombo.itemData(i)
@@ -472,3 +424,41 @@ class ActionStepFrame(QFrame):
self.targetCombo.setCurrentIndex(i)
break
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
from PySide6.QtCore import (
Qt, Signal, Slot, QTime, QDate, QDir, QFileInfo
)
from PySide6.QtWidgets import (
QDialog, QWidget, QLineEdit, QMessageBox, QFileDialog,
QTreeWidgetItem, QMenu, QInputDialog
QDate,
QDir,
QFileInfo,
Qt,
QTime,
Signal,
Slot
)
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
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.ALSeatMapTable import ALSeatMapTable
from gui.ALUserTreeWidget import ALUserTreeWidget, ALUserTreeItemType
from gui.ALUserTreeWidget import (
ALUserTreeItemType,
ALUserTreeWidget
)
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):
@@ -54,7 +72,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
if not self.initializeConfigs():
self.close()
def modifyUi(
self
):
@@ -70,7 +87,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.initializeFloorRoomMap()
self.initializeUserInfoWidget()
def connectSignals(
self
):
@@ -94,7 +110,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked)
self.CancelButton.clicked.connect(self.onCancelButtonClicked)
def showEvent(
self,
event
@@ -118,7 +133,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
return result
def closeEvent(
self,
event: QCloseEvent
@@ -127,7 +141,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.configWidgetIsClosed.emit()
super().closeEvent(event)
def initializeFloorRoomMap(
self
):
@@ -161,7 +174,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
"五层": ["五层考研"]
}
def initializeConfigToWidget(
self,
which: str,
@@ -176,7 +188,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.setUsersToTreeWidget(config_data)
self.CurrentUserConfigEdit.setText(self.__config_paths["user"])
def initializeConfig(
self,
which: str
@@ -210,7 +221,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
is_success = False
return is_success
def initializeConfigs(
self
) -> bool:
@@ -223,7 +233,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.initializeConfigToWidget(which, self.__config_data[which])
return is_success
def defaultRunConfig(
self
) -> dict:
@@ -247,7 +256,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
}
}
def defaultUserConfig(
self
) -> dict:
@@ -257,7 +265,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
]
}
def collectRunConfigFromWidget(
self
) -> dict:
@@ -279,7 +286,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
run_config["mode"]["run_mode"] = run_mode
return run_config
def setRunConfigToWidget(
self,
run_config: dict
@@ -318,7 +324,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
"文件可能被意外修改或已经损坏\n"
)
def initializeUserInfoWidget(
self
):
@@ -343,7 +348,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.MaxRenewTimeDiffSpinBox.setValue(30)
self.PreferLateRenewTimeCheckBox.setChecked(False)
def collectUserFromWidget(
self
) -> dict:
@@ -376,7 +380,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
user["reserve_info"]["renew_time"]["prefer_early"] = not self.PreferLateRenewTimeCheckBox.isChecked()
return user
def collectUsersFromTreeWidget(
self
) -> dict:
@@ -399,7 +402,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
user_config["groups"].append(group_config)
return user_config
def setUserToWidget(
self,
user: dict
@@ -441,7 +443,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
"文件可能被意外修改或已经损坏\n"
)
def setUsersToTreeWidget(
self,
users: dict
@@ -483,7 +484,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
finally:
self.UserTreeWidget.itemChanged.connect(self.onUserTreeWidgetItemChanged)
def loadRunConfig(
self,
run_config_path: str
@@ -507,7 +507,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
)
return None
def saveRunConfig(
self,
run_config_path: str,
@@ -529,7 +528,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
)
return False
def loadUserConfig(
self,
user_config_path: str
@@ -563,7 +561,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
)
return None
def saveUserConfig(
self,
user_config_path: str,
@@ -585,7 +582,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
)
return False
def saveConfigs(
self,
run_config_path: str,
@@ -608,7 +604,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
return False
return True
def loadConfig(
self,
config_path: str
@@ -637,7 +632,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
except:
return False
def addGroup(
self,
group_name: str = ""
@@ -654,7 +648,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.UserTreeWidget.itemChanged.connect(self.onUserTreeWidgetItemChanged)
return group_item
def delGroup(
self,
group_item: QTreeWidgetItem = None
@@ -667,7 +660,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
index = self.UserTreeWidget.indexOfTopLevelItem(group_item)
self.UserTreeWidget.takeTopLevelItem(index)
def addUser(
self,
group_item: QTreeWidgetItem = None
@@ -722,7 +714,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.UserTreeWidget.itemChanged.connect(self.onUserTreeWidgetItemChanged)
return user_item
def delUser(
self,
user_item: QTreeWidgetItem = None
@@ -738,7 +729,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
if parent_item.childCount() == 0:
self.UserTreeWidget.setCurrentItem(None)
def renameItem(
self,
item: QTreeWidgetItem,
@@ -862,7 +852,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
is_checked = item.checkState(1) == Qt.CheckState.Checked
item.setText(1, "" if is_checked else "跳过")
def showTreeMenu(
self,
menu: QMenu
@@ -872,7 +861,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
add_group_action.triggered.connect(self.addGroup)
menu.addAction(add_group_action)
def showGroupMenu(
self,
menu: QMenu,
@@ -892,7 +880,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
if group_item.checkState(1) == Qt.CheckState.Unchecked:
add_user_action.setEnabled(False)
def showUserMenu(
self,
menu: QMenu,
@@ -952,7 +939,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
if browser_driver_path:
self.BrowseBrowserDriverEdit.setText(QDir.toNativeSeparators(browser_driver_path))
@Slot()
def onAutoDownloadWebDriverButtonClicked(
self
@@ -966,7 +952,6 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
self.BrowserTypeComboBox.setCurrentText(selected_driver_info.driver_type.value)
self.BrowseBrowserDriverEdit.setText(QDir.toNativeSeparators(str(selected_driver_info.driver_path)))
@Slot()
def onBrowseCurrentRunConfigButtonClicked(
self
+25 -25
View File
@@ -10,24 +10,37 @@ See the LICENSE file for details.
import queue
from PySide6.QtCore import (
Qt, Signal, Slot, QTimer, QUrl,
)
from PySide6.QtWidgets import (
QMainWindow, QMenu, QSystemTrayIcon, QMessageBox
QTimer,
QUrl,
Qt,
Signal,
Slot
)
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 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.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):
@@ -59,7 +72,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.startTimerTaskPolling()
self._showLog("主窗口初始化完成")
def modifyUi(
self
):
@@ -90,7 +102,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.__alTimerTaskManageWidget.timerTaskManageWidgetIsClosed.connect(self.onTimerTaskManageWidgetClosed)
self.__alTimerTaskManageWidget.setWindowFlags(Qt.WindowType.Window|Qt.WindowType.WindowCloseButtonHint)
def onAboutActionTriggered(
self
):
@@ -98,7 +109,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
about_dialog = ALAboutDialog(self)
about_dialog.exec()
def onManualActionTriggered(
self
):
@@ -106,7 +116,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
url = QUrl("https://www.autolibrary.kenanzhu.com/manuals")
QDesktopServices.openUrl(url)
def setupTray(
self
):
@@ -128,7 +137,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.TrayIcon.activated.connect(self.onTrayIconActivated)
self.TrayIcon.show()
def hideToTray(
self
):
@@ -141,7 +149,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
2000
)
def onTrayIconActivated(
self,
reason: QSystemTrayIcon.ActivationReason
@@ -150,7 +157,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
if reason == QSystemTrayIcon.DoubleClick:
self.showNormal()
def connectSignals(
self
):
@@ -162,7 +168,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.SendButton.clicked.connect(self.onSendButtonClicked)
self.MessageEdit.returnPressed.connect(self.onSendButtonClicked)
def closeEvent(
self,
event: QCloseEvent
@@ -188,7 +193,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self._showLog("主窗口关闭")
QMainWindow.closeEvent(self, event)
def appendToTextEdit(
self,
text: str
@@ -202,7 +206,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
scrollbar = self.MessageIOTextEdit.verticalScrollBar()
scrollbar.setValue(scrollbar.maximum())
def startMsgPolling(
self
):
@@ -211,7 +214,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.__msg_queue_timer.timeout.connect(self.pollMsgQueue)
self.__msg_queue_timer.start(100)
def startTimerTaskPolling(
self
):
@@ -220,7 +222,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.__timer_task_timer.timeout.connect(self.pollTimerTaskQueue)
self.__timer_task_timer.start(500)
def pollTimerTaskQueue(
self
):
@@ -254,7 +255,6 @@ class ALMainWindow(MsgBase, QMainWindow, Ui_ALMainWindow):
self.__is_running_timer_task = False
pass
def setControlButtons(
self,
config_button_enabled: bool,
-6
View File
@@ -37,7 +37,6 @@ class AutoLibWorker(MsgBase, QThread):
QThread.__init__(self)
self.__config_paths = config_paths
def checkTimeAvailable(
self,
) -> bool:
@@ -52,7 +51,6 @@ class AutoLibWorker(MsgBase, QThread):
self._showLog(f"时间检查通过, 当前时间: {current_time}", self.TraceLevel.INFO)
return True
def checkConfigPaths(
self,
) -> bool:
@@ -68,7 +66,6 @@ class AutoLibWorker(MsgBase, QThread):
self._showLog(f"配置文件路径检查通过, 路径: {self.__config_paths}", self.TraceLevel.INFO)
return True
def loadConfigs(
self
) -> bool:
@@ -101,7 +98,6 @@ class AutoLibWorker(MsgBase, QThread):
)
return True
def run(
self
):
@@ -161,7 +157,6 @@ class TimerTaskWorker(AutoLibWorker):
self.autoLibWorkerIsFinished.connect(self.onTimerTaskIsFinished)
self.autoLibWorkerFinishedWithError.connect(self.onTimerTaskFinishedWithError)
def run(
self
):
@@ -206,7 +201,6 @@ class TimerTaskWorker(AutoLibWorker):
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行结束")
self.timerTaskWorkerIsFinished.emit(False, self.__timer_task)
def applyRepeatAutoScript(
self
):
-4
View File
@@ -31,7 +31,6 @@ class ALSeatFrame(QFrame):
self.setupUi()
def setupUi(
self
):
@@ -55,7 +54,6 @@ class ALSeatFrame(QFrame):
self.Label.setAlignment(Qt.AlignCenter)
self.Label.setGeometry(0, 0, 60, 40)
def mousePressEvent(
self,
event
@@ -65,14 +63,12 @@ class ALSeatFrame(QFrame):
self.toggleSelection()
self.clicked.emit(self.__seat_number)
def isSelected(
self
):
return self.__is_selected
def toggleSelection(self):
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.
"""
from PySide6.QtCore import (
Qt, Slot, Signal
)
from PySide6.QtWidgets import (
QDialog, QLabel, QHBoxLayout, QVBoxLayout,
QPushButton,
Qt,
Signal,
Slot
)
from PySide6.QtGui import (
QCloseEvent
)
from PySide6.QtWidgets import (
QDialog,
QHBoxLayout,
QLabel,
QPushButton,
QVBoxLayout
)
from gui.ALSeatMapView import ALSeatMapView
@@ -42,7 +47,6 @@ class ALSeatMapSelectDialog(QDialog):
self.setupUi()
self.connectSignals()
def setupUi(
self
):
@@ -85,7 +89,6 @@ class ALSeatMapSelectDialog(QDialog):
self.SeatMapWidgetControlLayout.addWidget(self.ConfirmButton)
self.SeatMapWidgetMainLayout.addLayout(self.SeatMapWidgetControlLayout)
def connectSignals(
self
):
@@ -93,7 +96,6 @@ class ALSeatMapSelectDialog(QDialog):
self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked)
self.CancelButton.clicked.connect(self.onCancelButtonClicked)
def showEvent(
self,
event
@@ -117,7 +119,6 @@ class ALSeatMapSelectDialog(QDialog):
return result
def closeEvent(
self,
event: QCloseEvent
@@ -131,7 +132,6 @@ class ALSeatMapSelectDialog(QDialog):
self.seatMapSelectDialogIsClosed.emit(self.getSelectedSeats())
super().closeEvent(event)
def selectSeat(
self,
seat_number: str
@@ -139,7 +139,6 @@ class ALSeatMapSelectDialog(QDialog):
self.SeatMapGraphicsView.selectSeat(seat_number)
def selectSeats(
self,
seat_numbers: list[str]
@@ -147,14 +146,12 @@ class ALSeatMapSelectDialog(QDialog):
return self.SeatMapGraphicsView.selectSeats(seat_numbers)
def getSelectedSeats(
self
) -> list[str]:
return self.SeatMapGraphicsView.getSelectedSeats()
def clearSelections(
self
):
+20 -23
View File
@@ -11,11 +11,16 @@ from PySide6.QtCore import (
Qt, Slot, QEvent
)
from PySide6.QtWidgets import (
QFrame, QWidget,
QGridLayout, QGraphicsView, QGraphicsScene, QGraphicsItem
QFrame,
QWidget,
QGridLayout,
QGraphicsView,
QGraphicsScene,
QGraphicsItem
)
from PySide6.QtGui import (
QPainter, QWheelEvent
QPainter,
QWheelEvent
)
from gui.ALSeatFrame import ALSeatFrame
@@ -35,18 +40,6 @@ class ALSeatMapView(QGraphicsView):
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(
self,
watched,
@@ -61,7 +54,6 @@ class ALSeatMapView(QGraphicsView):
return True
return super().eventFilter(watched, event)
def zoomGraphicsView(
self,
event: QWheelEvent
@@ -80,7 +72,6 @@ class ALSeatMapView(QGraphicsView):
self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
self.scale(zoom_factor, zoom_factor)
def setupUi(
self
):
@@ -100,7 +91,6 @@ class ALSeatMapView(QGraphicsView):
self.ContainerProxy = self.SeatMapGraphicsScene.addWidget(self.SeatsContainerWidget)
self.ContainerProxy.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, False)
def setupSeatMap(
self
):
@@ -125,7 +115,6 @@ class ALSeatMapView(QGraphicsView):
self.SeatsContainerLayout.setContentsMargins(20, 20, 20, 20)
self.SeatsContainerWidget.adjustSize()
def selectSeat(
self,
seat_number: str
@@ -142,7 +131,6 @@ class ALSeatMapView(QGraphicsView):
widget.toggleSelection()
self.__selected_seats.append(seat_number)
def selectSeats(
self,
selected_seats: list
@@ -152,14 +140,12 @@ class ALSeatMapView(QGraphicsView):
for seat_number in selected_seats:
self.selectSeat(seat_number)
def getSelectedSeats(
self
) -> list[str]:
return self.__selected_seats
def clearSelections(
self
):
@@ -185,4 +171,15 @@ class ALSeatMapView(QGraphicsView):
if len(self.__selected_seats) < 1:
self.__selected_seats.append(seat_number)
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 PySide6.QtWidgets import (
QLabel
)
from PySide6.QtCore import (
Qt, Property, QPropertyAnimation, QEasingCurve
Property,
QEasingCurve,
QPropertyAnimation,
Qt
)
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()
def setupUi(
self
):
@@ -59,14 +64,12 @@ class ALStatusLabel(QLabel):
self.RunningAnimation.setLoopCount(-1)
self.RunningAnimation.setEasingCurve(QEasingCurve.Type.Linear)
def isDarkMode(
self
) -> bool:
return self.palette().color(QPalette.ColorRole.Window).value() < 128
def getMarkColor(
self
) -> QColor:
@@ -111,7 +114,6 @@ class ALStatusLabel(QLabel):
self.__icon_angle = value
self.update()
def paintEvent(
self,
event
+5 -9
View File
@@ -49,7 +49,6 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
if self.__edit_timer_task:
self.loadTask(self.__edit_timer_task)
def modifyUi(
self
):
@@ -101,10 +100,10 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.AutoScriptLayout.setContentsMargins(3, 3, 3, 3)
self.AutoScriptLayout.setSpacing(3)
autoScriptBtnLayout = QHBoxLayout()
self.AutoScriptPreviewButton = QPushButton("编辑")
self.AutoScriptPreviewButton.setMinimumHeight(25)
self.AutoScriptPreviewButton.setFixedWidth(60)
autoScriptBtnLayout.addWidget(self.AutoScriptPreviewButton)
self.AutoScriptEditButton = QPushButton("编辑")
self.AutoScriptEditButton.setMinimumHeight(25)
self.AutoScriptEditButton.setFixedWidth(80)
autoScriptBtnLayout.addWidget(self.AutoScriptEditButton)
autoScriptBtnLayout.addStretch()
self.AutoScriptHelpButton = QPushButton("?")
self.AutoScriptHelpButton.setFixedSize(20, 20)
@@ -133,7 +132,6 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.__auto_script = ""
self.__mock_target_data = None
def loadTask(
self,
task: dict
@@ -174,7 +172,6 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.__mock_target_data = mock_data
self.ConfirmButton.setText("保存")
def connectSignals(
self
):
@@ -183,10 +180,9 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.ConfirmButton.clicked.connect(self.accept)
self.TimerTypeComboBox.currentIndexChanged.connect(self.onTimerTypeComboBoxIndexChanged)
self.RepeatCheckBox.toggled.connect(self.onRepeatCheckBoxToggled)
self.AutoScriptPreviewButton.clicked.connect(self.onPreviewAutoScript)
self.AutoScriptEditButton.clicked.connect(self.onPreviewAutoScript)
self.AutoScriptHelpButton.clicked.connect(self.onAutoScriptHelp)
def getTimerTask(
self
) -> dict:
+5 -10
View File
@@ -34,7 +34,6 @@ class ALTimerTaskHistoryDialog(QDialog):
self.setupUi()
self.connectSignals()
def setupUi(
self
):
@@ -82,7 +81,6 @@ class ALTimerTaskHistoryDialog(QDialog):
ButtonLayout.addWidget(self.CloseButton)
MainLayout.addLayout(ButtonLayout)
def connectSignals(
self
):
@@ -90,7 +88,6 @@ class ALTimerTaskHistoryDialog(QDialog):
self.CloseButton.clicked.connect(self.accept)
self.ClearHistoryButton.clicked.connect(self.onClearHistoryButtonClicked)
def loadHistory(
self
):
@@ -99,6 +96,11 @@ class ALTimerTaskHistoryDialog(QDialog):
for row, record in enumerate(self.__history):
self.addHistoryRow(row, record)
def getHistory(
self
) -> list:
return self.__history
def addHistoryRow(
self,
@@ -129,13 +131,6 @@ class ALTimerTaskHistoryDialog(QDialog):
self.HistoryTableWidget.setItem(row, 2, DurationItem)
self.HistoryTableWidget.setRowHeight(row, 25)
def getHistory(
self
) -> list:
return self.__history
@Slot()
def onClearHistoryButtonClicked(
self
+27 -29
View File
@@ -15,24 +15,40 @@ from enum import Enum
from datetime import datetime, timedelta
from PySide6.QtCore import (
Qt, Signal, Slot, QTimer
)
from PySide6.QtWidgets import (
QDialog, QWidget, QListWidgetItem, QMessageBox,
QHBoxLayout, QVBoxLayout, QLabel, QPushButton, QMenu
QTimer,
Qt,
Signal,
Slot
)
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
from utils.TimerUtils import TimerUtils
from interfaces.ConfigProvider import ConfigProvider, CfgKey
from gui.resources.ui.Ui_ALTimerTaskManageWidget import Ui_ALTimerTaskManageWidget
from gui.ALTimerTaskAddDialog import ALTimerTaskAddDialog, ALTimerTaskStatus
from gui.ALTimerTaskAddDialog import (
ALTimerTaskAddDialog,
ALTimerTaskStatus
)
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):
@@ -53,7 +69,6 @@ class ALTimerTaskItemWidget(QWidget):
self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.customContextMenuRequested.connect(self.showContextMenu)
def modifyUi(
self
):
@@ -204,7 +219,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
if not self.initializeTimerTasks():
raise Exception("定时任务配置文件初始化失败 !")
def connectSignals(
self
):
@@ -215,7 +229,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.TimerTaskSortOrderToggleButton.clicked.connect(self.onSortOrderToggleButtonClicked)
self.timerTasksChanged.connect(self.onTimerTasksChanged)
def setupTimer(
self
):
@@ -224,7 +237,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.__check_timer.timeout.connect(self.checkTasks)
self.__check_timer.start(500)
def initializeTimerTasks(
self
) -> bool:
@@ -240,7 +252,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
return True
return False
def getTimerTasks(
self
) -> list:
@@ -265,7 +276,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
)
return None
def setTimerTasks(
self,
timer_tasks: list
@@ -289,7 +299,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
)
return False
def showEvent(
self,
event
@@ -313,7 +322,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
return result
def closeEvent(
self,
event: QCloseEvent
@@ -323,7 +331,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.timerTaskManageWidgetIsClosed.emit()
event.ignore()
def sortTimerTasks(
self,
policy: SortPolicy = SortPolicy.BY_EXECUTE_TIME,
@@ -346,7 +353,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
reverse = order is Qt.SortOrder.DescendingOrder
)
def updateStat(
self
):
@@ -373,7 +379,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.ExecutedTaskLabel.setText(f"已执行:{executed}")
self.InvalidTaskLabel.setText(f"无效的:{invalid}")
def updateTimerTaskList(
self
):
@@ -396,7 +401,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.TimerTasksListWidget.addItem(item)
self.TimerTasksListWidget.setItemWidget(item, widget)
def addTask(
self
):
@@ -407,7 +411,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.__timer_tasks.append(timer_task)
self.timerTasksChanged.emit()
def editTask(
self,
timer_task: dict
@@ -440,7 +443,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
f"已记录次数:{history_count}"
)
def deleteTask(
self,
timer_task: dict
@@ -469,7 +471,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
]
self.timerTasksChanged.emit()
def clearAllTasks(
self
):
@@ -531,7 +532,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.__timer_tasks.clear()
self.timerTasksChanged.emit()
def showTaskHistory(
self,
task: dict
@@ -541,7 +541,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
if dialog.exec() == QDialog.DialogCode.Accepted:
self.timerTasksChanged.emit()
def checkTasks(
self
):
@@ -615,7 +614,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
break
self.timerTasksChanged.emit()
def onRepeatTimerTaskIs(
self,
status: ALTimerTaskStatus,
+12 -10
View File
@@ -10,14 +10,22 @@ See the LICENSE file for details.
from enum import Enum
from PySide6.QtCore import (
Qt, QSize, QCoreApplication, QRect, QPoint
Qt,
QSize,
QCoreApplication,
QRect,
QPoint
)
from PySide6.QtWidgets import (
QAbstractScrollArea, QAbstractItemView,
QTreeWidget, QTreeWidgetItem
QAbstractScrollArea,
QAbstractItemView,
QTreeWidget,
QTreeWidgetItem
)
from PySide6.QtGui import (
QDragEnterEvent, QDragMoveEvent, QDropEvent
QDragEnterEvent,
QDragMoveEvent,
QDropEvent
)
@@ -39,7 +47,6 @@ class ALUserTreeWidget(QTreeWidget):
self.setupUi()
self.translateUi()
def setupUi(
self
):
@@ -70,7 +77,6 @@ class ALUserTreeWidget(QTreeWidget):
self.header().setHighlightSections(False)
self.header().setProperty(u"showSortIndicator", True)
def translateUi(
self
):
@@ -78,7 +84,6 @@ class ALUserTreeWidget(QTreeWidget):
___qtreewidgetitem = self.headerItem()
___qtreewidgetitem.setText(1, QCoreApplication.translate("ALConfigWidget", u"\u72b6\u6001", None));
@staticmethod
def isDragPositionValid(
target_rect: QRect,
@@ -90,7 +95,6 @@ class ALUserTreeWidget(QTreeWidget):
y_offset < target_rect.height()*0.8)
return valid
def dragEnterEvent(
self,
event: QDragEnterEvent
@@ -98,7 +102,6 @@ class ALUserTreeWidget(QTreeWidget):
super().dragEnterEvent(event)
def dragMoveEvent(
self,
event: QDragMoveEvent
@@ -136,7 +139,6 @@ class ALUserTreeWidget(QTreeWidget):
return
event.acceptProposedAction()
def dropEvent(
self,
event: QDropEvent
+137 -140
View File
@@ -11,20 +11,30 @@ import threading
from typing import Optional
from PySide6.QtCore import (
Qt, Slot, QThread, Signal
Qt,
Slot,
QThread,
Signal
)
from PySide6.QtWidgets import (
QDialog, QLabel, QComboBox, QProgressBar,
QPushButton, QVBoxLayout, QHBoxLayout,
QMessageBox, QFrame, QLineEdit
)
from PySide6.QtGui import (
QCloseEvent
QDialog,
QLabel,
QComboBox,
QProgressBar,
QPushButton,
QVBoxLayout,
QHBoxLayout,
QMessageBox,
QFrame,
QLineEdit
)
from PySide6.QtGui import QCloseEvent
from managers.driver.WebDriverManager import (
instance as webdriver_manager_instance,
WebDriverManager, WebDriverInfo, WebDriverType,
instance as webdriverManagerInstance,
WebDriverManager,
WebDriverInfo,
WebDriverType,
WebDriverStatus
)
from gui.ALStatusLabel import ALStatusLabel
@@ -142,7 +152,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.initializeDriverManager()
self.refreshDriverList()
def showEvent(
self,
event
@@ -165,7 +174,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.move(target_pos)
return result
def setupUi(
self
):
@@ -237,7 +245,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.ControlLayout.addWidget(self.ConfirmButton)
self.MainLayout.addLayout(self.ControlLayout)
def connectSignals(
self
):
@@ -249,18 +256,16 @@ class ALWebDriverDownloadDialog(QDialog):
self.ConfirmButton.clicked.connect(self.onConfirmButtonClicked)
self.DriverComboBox.currentIndexChanged.connect(self.onDriverComboBoxChanged)
def initializeDriverManager(
self
):
try:
self.__driver_manager = webdriver_manager_instance(self.__driver_dir)
self.__driver_manager = webdriverManagerInstance(self.__driver_dir)
except ValueError as e:
QMessageBox.warning(self, "初始化失败", f"WebDriverManager 初始化失败:\n{str(e)}")
self.reject()
def refreshDriverList(
self
):
@@ -270,18 +275,20 @@ class ALWebDriverDownloadDialog(QDialog):
self.__driver_manager.refresh()
self.__driver_infos = self.__driver_manager.getDriverInfos()
self.DriverComboBox.clear()
installed = 0
installed_idx = 0
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}"
if driver_info.driver_status == WebDriverStatus.INSTALLED:
installed += 1
installed_idx = i # get the installed driver index
display_text += " : 已安装"
self.DriverComboBox.addItem(display_text)
count = len(self.__driver_infos)
self.BrowserCountLabel.setText(f"检测到 {count} 个可用浏览器:")
self.BrowserCountLabel.setText(f"检测到 {count} 个可用浏览器{installed} 个已安装驱动")
if self.__driver_infos:
self.DriverComboBox.setCurrentIndex(installed_idx)
def onDriverComboBoxChanged(
self,
index: int
@@ -294,6 +301,116 @@ class ALWebDriverDownloadDialog(QDialog):
self.updateProgressBarStates(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()
def onRefreshButtonClicked(
@@ -302,7 +419,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.refreshDriverList()
@Slot()
def onDeleteButtonClicked(
self
@@ -355,7 +471,7 @@ class ALWebDriverDownloadDialog(QDialog):
self.__download_thread.downloadFinished.connect(self.onDownloadFinished)
self.__download_thread.downloadError.connect(self.onDownloadError)
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()
@Slot()
@@ -406,7 +522,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.updateButtonStates(driver_info)
QMessageBox.critical(self, "下载失败 - AutoLibrary", error_message)
@Slot()
def onDownloadCancelled(
self
@@ -423,7 +538,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.updateButtonStates(driver_info)
self.ProgressText.setText("下载已取消")
@Slot()
def onConfirmButtonClicked(
self
@@ -439,7 +553,6 @@ class ALWebDriverDownloadDialog(QDialog):
self.__confirmed = True
self.accept()
@Slot()
def onCancelButtonClicked(
self
@@ -458,119 +571,3 @@ class ALWebDriverDownloadDialog(QDialog):
self.__confirmed = False
self.__selected_driver_info = None
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)