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

feat(ALTimerTask*): 实现定时任务编辑功能,统一代码规范并重命名重复任务历史字段

This commit is contained in:
2026-05-09 10:07:25 +08:00
parent 46b3447d1e
commit 27250dba2f
6 changed files with 344 additions and 223 deletions
+111 -91
View File
@@ -8,7 +8,7 @@ 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 QTime, QDate
from PySide6.QtCore import QTime, QDate, Slot
from PySide6.QtWidgets import (
QDialog, QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QComboBox, QPushButton, QScrollArea, QTimeEdit,
@@ -21,18 +21,15 @@ from utils.AutoScriptEngine import AutoScriptEngine
VARIABLE_META = AutoScriptEngine.VARIABLE_META
_VAR_COMBO_ITEMS = [
(display, varname, vartype)
for display, (varname, vartype) in VARIABLE_META.items()
]
_VAR_COMBO_ITEMS_SET = [
(display, varname, vartype)
for display, (varname, vartype) in VARIABLE_META.items()
if not varname.startswith("CURRENT_")
]
OP_ITEMS = [
("等于", ".EQ."),
("不等于", ".NEQ."),
@@ -298,7 +295,7 @@ class ActionStepFrame(QFrame):
self.setupUi()
self.connectSignals()
self._onTargetChanged(0)
self.onTargetChanged(0)
def setupUi(
@@ -316,7 +313,7 @@ class ActionStepFrame(QFrame):
self.targetCombo = _makeSetVarCombo()
self.valueWidgetStack = QStackedWidget()
self.valueWidgetStack.setFixedHeight(25)
self._initValueStack()
self.initValueStack()
setLabel = QLabel("设置")
setLabel.setFixedHeight(25)
@@ -337,9 +334,10 @@ class ActionStepFrame(QFrame):
self
):
self.targetCombo.currentIndexChanged.connect(self._onTargetChanged)
self.targetCombo.currentIndexChanged.connect(self.onTargetChanged)
def _initValueStack(
def initValueStack(
self
):
@@ -353,18 +351,6 @@ class ActionStepFrame(QFrame):
self._valueWidgets.get("String", self.valueWidgetStack.widget(0))
)
def _onTargetChanged(
self,
idx
):
if idx < 0:
return
data = self.targetCombo.itemData(idx)
if data:
_, vartype = data
w = self._valueWidgets.get(vartype)
if w:
self.valueWidgetStack.setCurrentWidget(w)
def getTarget(
self
@@ -373,6 +359,7 @@ class ActionStepFrame(QFrame):
data = self.targetCombo.currentData()
return data[0] if data else ""
def getTargetType(
self
) -> str:
@@ -380,6 +367,7 @@ class ActionStepFrame(QFrame):
data = self.targetCombo.currentData()
return data[1] if data else "String"
def getValueRaw(
self
) -> str:
@@ -390,6 +378,7 @@ class ActionStepFrame(QFrame):
return _getValueFromWidget(w)
return ""
def toScriptLine(
self
) -> str:
@@ -405,6 +394,7 @@ class ActionStepFrame(QFrame):
return f" {target} .ADD. {hours}"
return f" SET {target} = {encoded}"
def loadFromScript(
self,
targetVar: str,
@@ -416,9 +406,10 @@ class ActionStepFrame(QFrame):
if data and data[0] == targetVar:
self.targetCombo.setCurrentIndex(idx)
break
self._setValueFromExpr(valueExpr)
self.setValueFromExpr(valueExpr)
def _setValueFromExpr(
def setValueFromExpr(
self,
expr: str
):
@@ -429,6 +420,20 @@ class ActionStepFrame(QFrame):
return
_setWidgetValue(w, targetType, expr)
@Slot(int)
def onTargetChanged(
self,
idx
):
if idx < 0:
return
data = self.targetCombo.itemData(idx)
if data:
_, vartype = data
w = self._valueWidgets.get(vartype)
if w:
self.valueWidgetStack.setCurrentWidget(w)
class ConditionalBlock(QGroupBox):
@@ -444,7 +449,7 @@ class ConditionalBlock(QGroupBox):
self.setupUi()
self.connectSignals()
self._onOperandChanged(0)
self.onOperandChanged(0)
def setupUi(
@@ -453,7 +458,7 @@ class ConditionalBlock(QGroupBox):
self.setStyleSheet(
"QGroupBox { font-weight: bold; border: 1px solid #ccc; "
"margin-top: 8px; padding-top: 8px; }"
"margin-top: 5px; padding-top: 5px; }"
)
self.setSizePolicy(
QSizePolicy.Policy.Preferred,
@@ -522,41 +527,12 @@ class ConditionalBlock(QGroupBox):
self
):
self.operandCombo.currentIndexChanged.connect(self._onOperandChanged)
self.typeCombo.currentIndexChanged.connect(self._onTypeChanged)
self.addActionBtn.clicked.connect(self._addActionStep)
self.operandCombo.currentIndexChanged.connect(self.onOperandChanged)
self.typeCombo.currentIndexChanged.connect(self.onTypeChanged)
self.addActionBtn.clicked.connect(self.addActionStep)
def _onOperandChanged(
self,
idx
):
if idx < 0:
return
data = self.operandCombo.itemData(idx)
if data:
_, vartype = data
w = self._condValueWidgets.get(vartype)
if w:
self.condValueStack.setCurrentWidget(w)
def _onTypeChanged(
self,
idx
):
isCond = self.typeCombo.currentData() in ("IF", "ELSE IF")
self.conditionWidget.setVisible(isCond)
self.actionLabel.setText("执行步骤:" if isCond else "ELSE 执行步骤:")
def _addActionStep(
self
):
step = ActionStepFrame(self)
step.deleteBtn.clicked.connect(lambda: self._removeActionStep(step))
self._actionWidgets.append(step)
self.actionsLayout.addWidget(step)
def _removeActionStep(
def removeActionStep(
self,
step: ActionStepFrame
):
@@ -567,12 +543,14 @@ class ConditionalBlock(QGroupBox):
step.hide()
step.deleteLater()
def getBlockType(
self
) -> str:
return self.typeCombo.currentData()
def toScriptLines(
self
) -> list:
@@ -602,6 +580,7 @@ class ConditionalBlock(QGroupBox):
return lines
def getConditionSummary(
self
) -> str:
@@ -617,6 +596,7 @@ class ConditionalBlock(QGroupBox):
rawVal = self.getConditionRawValuePreview()
return f"{bt} ({operandDisplay} {opDisplay} {rawVal})"
def getConditionRawValuePreview(
self
) -> str:
@@ -630,12 +610,46 @@ class ConditionalBlock(QGroupBox):
return _getValueFromWidget(w)
return ""
def countActionSteps(
self
) -> int:
return len(self._actionWidgets)
@Slot(int)
def onOperandChanged(
self,
idx
):
if idx < 0:
return
data = self.operandCombo.itemData(idx)
if data:
_, vartype = data
w = self._condValueWidgets.get(vartype)
if w:
self.condValueStack.setCurrentWidget(w)
@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 执行步骤:")
@Slot()
def addActionStep(
self
):
step = ActionStepFrame(self)
step.deleteBtn.clicked.connect(lambda: self.removeActionStep(step))
self._actionWidgets.append(step)
self.actionsLayout.addWidget(step)
class ALAutoScriptOrchDialog(QDialog):
@@ -651,9 +665,9 @@ class ALAutoScriptOrchDialog(QDialog):
self.connectSignals()
if existingScript and existingScript.strip():
self._loadFromScript(existingScript)
self.loadFromScript(existingScript)
else:
self._addBlock()
self.addBlock()
self._scrollLayout.addStretch()
@@ -695,28 +709,10 @@ class ALAutoScriptOrchDialog(QDialog):
self.btnBox.accepted.connect(self.accept)
self.btnBox.rejected.connect(self.reject)
self.addBlockBtn.clicked.connect(self._addBlock)
self.addBlockBtn.clicked.connect(self.addBlock)
def _addBlock(
self
):
block = ConditionalBlock(len(self._blocks), self)
block.deleteBlockBtn.clicked.connect(lambda: self._removeBlock(block))
self._blocks.append(block)
block._addActionStep()
if self._scrollLayout.count() > 0:
lastItem = self._scrollLayout.itemAt(
self._scrollLayout.count() - 1
)
if lastItem and lastItem.spacerItem():
self._scrollLayout.insertWidget(
self._scrollLayout.count() - 1, block
)
return
self._scrollLayout.addWidget(block)
def _removeBlock(
def removeBlock(
self,
block: ConditionalBlock
):
@@ -727,6 +723,7 @@ class ALAutoScriptOrchDialog(QDialog):
block.hide()
block.deleteLater()
def getScript(
self
) -> str:
@@ -742,6 +739,7 @@ class ALAutoScriptOrchDialog(QDialog):
parts.append("ENDIF")
return "\n".join(parts)
def getScriptPreview(
self
) -> str:
@@ -751,7 +749,8 @@ class ALAutoScriptOrchDialog(QDialog):
return s[:7] + "..."
return s
def _loadFromScript(
def loadFromScript(
self,
script: str
):
@@ -759,7 +758,7 @@ class ALAutoScriptOrchDialog(QDialog):
import re
lines = [l.strip() for l in script.split("\n") if l.strip()]
if not lines:
self._addBlock()
self.addBlock()
return
currentBlock = None
@@ -773,11 +772,11 @@ class ALAutoScriptOrchDialog(QDialog):
typeIdxMap = {"IF": 0, "ELSE IF": 1, "ELSE": 2}
idx = typeIdxMap.get(currentBlockType, 0)
currentBlock.typeCombo.setCurrentIndex(idx)
currentBlock._onTypeChanged(idx)
currentBlock.onTypeChanged(idx)
for oldStep in list(currentBlock._actionWidgets):
currentBlock._removeActionStep(oldStep)
currentBlock.removeActionStep(oldStep)
for target, valueExpr in actionsBuffer:
currentBlock._addActionStep()
currentBlock.addActionStep()
step = currentBlock._actionWidgets[-1]
step.loadFromScript(target, valueExpr)
self._blocks.clear()
@@ -792,24 +791,24 @@ class ALAutoScriptOrchDialog(QDialog):
flushBlock()
currentBlockType = "IF"
actionsBuffer = []
self._addBlock()
self.addBlock()
currentBlock = self._blocks[-1]
self._parseConditionToBlock(currentBlock, ifMatch.group(1))
self.parseConditionToBlock(currentBlock, ifMatch.group(1))
continue
elifIfMatch = re.match(r"^ELSE\s+IF\((.+)\)\s*THEN\s*$", upper)
if elifIfMatch:
flushBlock()
currentBlockType = "ELSE IF"
actionsBuffer = []
self._addBlock()
self.addBlock()
currentBlock = self._blocks[-1]
self._parseConditionToBlock(currentBlock, elifIfMatch.group(1))
self.parseConditionToBlock(currentBlock, elifIfMatch.group(1))
continue
if upper == "ELSE":
flushBlock()
currentBlockType = "ELSE"
actionsBuffer = []
self._addBlock()
self.addBlock()
currentBlock = self._blocks[-1]
currentBlock.conditionWidget.setVisible(False)
continue
@@ -833,9 +832,10 @@ class ALAutoScriptOrchDialog(QDialog):
continue
flushBlock()
if not self._blocks:
self._addBlock()
self.addBlock()
def _parseConditionToBlock(
def parseConditionToBlock(
self,
block: ConditionalBlock,
condStr: str
@@ -862,3 +862,23 @@ class ALAutoScriptOrchDialog(QDialog):
if w:
_setWidgetValue(w, vartype, rightPart)
return
@Slot()
def addBlock(
self
):
block = ConditionalBlock(len(self._blocks), self)
block.deleteBlockBtn.clicked.connect(lambda: self.removeBlock(block))
self._blocks.append(block)
block.addActionStep()
if self._scrollLayout.count() > 0:
lastItem = self._scrollLayout.itemAt(
self._scrollLayout.count() - 1
)
if lastItem and lastItem.spacerItem():
self._scrollLayout.insertWidget(
self._scrollLayout.count() - 1, block
)
return
self._scrollLayout.addWidget(block)
+47 -45
View File
@@ -8,6 +8,8 @@ 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 Slot
from PySide6.QtGui import (
QSyntaxHighlighter, QTextCharFormat, QColor, QFont, QIcon
)
@@ -162,53 +164,13 @@ class ALAutoScriptPreviewDialog(QDialog):
):
self._btnBox.rejected.connect(self.reject)
self._zoomInBtn.clicked.connect(self._onZoomIn)
self._zoomOutBtn.clicked.connect(self._onZoomOut)
self._zoomResetBtn.clicked.connect(self._onZoomReset)
self._copyBtn.clicked.connect(self._onCopy)
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 _onZoomIn(
self
):
self.__fontSize = min(self.__fontSize + 2, 40)
self._updateFontSize()
def _onZoomOut(
self
):
self.__fontSize = max(self.__fontSize - 2, 8)
self._updateFontSize()
def _onZoomReset(
self
):
self.__fontSize = 13
self._updateFontSize()
def _onCopy(
self
):
clipboard = QApplication.clipboard()
clipboard.setText(self._textEdit.toPlainText())
original = self._copyBtn.text()
self._copyBtn.setText("已复制")
self._copyBtn.setEnabled(False)
from PySide6.QtCore import QTimer
QTimer.singleShot(2000, lambda: (
self._copyBtn.setText(original),
self._copyBtn.setEnabled(True)
))
def _updateFontSize(
def updateFontSize(
self
):
@@ -222,3 +184,43 @@ class ALAutoScriptPreviewDialog(QDialog):
"}"
)
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)
from PySide6.QtCore import QTimer
QTimer.singleShot(2000, lambda: (
self._copyBtn.setText(original),
self._copyBtn.setEnabled(True)
))
+10 -10
View File
@@ -174,7 +174,7 @@ class TimerTaskWorker(AutoLibWorker):
try:
if not self.loadConfigs():
raise Exception("配置文件加载失败")
self._applyRepeatAutoScript()
self.applyRepeatAutoScript()
auto_lib = AutoLib(
self._input_queue,
self._output_queue,
@@ -207,7 +207,7 @@ class TimerTaskWorker(AutoLibWorker):
self.timerTaskWorkerIsFinished.emit(False, self.__timer_task)
def _applyRepeatAutoScript(
def applyRepeatAutoScript(
self
):
@@ -238,6 +238,14 @@ class TimerTaskWorker(AutoLibWorker):
self.TraceLevel.INFO
)
@Slot()
def onTimerTaskIsFinished(
self
):
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行结束")
self.timerTaskWorkerIsFinished.emit(False, self.__timer_task)
@Slot()
def onTimerTaskFinishedWithError(
self
@@ -248,11 +256,3 @@ class TimerTaskWorker(AutoLibWorker):
self.TraceLevel.ERROR
)
self.timerTaskWorkerIsFinished.emit(True, self.__timer_task)
@Slot()
def onTimerTaskIsFinished(
self
):
self._showTrace(f"定时任务 {self.__timer_task['name']} 运行结束")
self.timerTaskWorkerIsFinished.emit(False, self.__timer_task)
+100 -41
View File
@@ -36,15 +36,20 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
def __init__(
self,
parent = None
parent = None,
timer_task: dict = None
):
super().__init__(parent)
self.__edit_timer_task = timer_task
self.setupUi(self)
self.modifyUi()
self.connectSignals()
if self.__edit_timer_task:
self.loadTask(self.__edit_timer_task)
def modifyUi(
self
@@ -130,6 +135,45 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.__auto_script = ""
def loadTask(
self,
task: dict
):
self.TaskNameLineEdit.setText(task.get("name", ""))
time_type = task.get("time_type", "特定时间")
self.TimerTypeComboBox.setCurrentText(time_type)
self.SpecificDateTimeEdit.setDateTime(
QDateTime(task["execute_time"])
)
self.RelativeDaySpinBox.setValue(0)
self.RelativeHourSpinBox.setValue(0)
self.RelativeMinuteSpinBox.setValue(0)
self.RelativeSecondSpinBox.setValue(0)
if task.get("silent", False):
self.SilentlyRunRadioButton.setChecked(True)
else:
self.ShowBeforeRunRadioButton.setChecked(True)
repeat = task.get("repeat", False)
self.RepeatCheckBox.setChecked(repeat)
if repeat:
repeat_days = task.get("repeat_days", [])
self.MonCheckBox.setChecked(0 in repeat_days)
self.TueCheckBox.setChecked(1 in repeat_days)
self.WedCheckBox.setChecked(2 in repeat_days)
self.ThuCheckBox.setChecked(3 in repeat_days)
self.FriCheckBox.setChecked(4 in repeat_days)
self.SatCheckBox.setChecked(5 in repeat_days)
self.SunCheckBox.setChecked(6 in repeat_days)
auto_script = task.get("repeat_auto_script", "")
if auto_script:
self.__auto_script = auto_script
self.AutoScriptStatusLabel.setText("已设置")
self.AutoScriptStatusLabel.setStyleSheet("color: #4CAF50;")
self.AutoScriptPreviewButton.setEnabled(True)
self.ConfirmButton.setText("保存")
def connectSignals(
self
):
@@ -138,44 +182,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.AutoScriptSetButton.clicked.connect(self._onSetAutoScript)
self.AutoScriptPreviewButton.clicked.connect(self._onPreviewAutoScript)
self.AutoScriptHelpButton.clicked.connect(self._onAutoScriptHelp)
@Slot()
def _onSetAutoScript(self):
dlg = ALAutoScriptOrchDialog(self, existingScript=self.__auto_script)
if dlg.exec() == QDialog.DialogCode.Accepted:
script = dlg.getScript()
self.__auto_script = script
if script:
self.AutoScriptStatusLabel.setText("已设置")
self.AutoScriptStatusLabel.setStyleSheet("color: #4CAF50;")
self.AutoScriptPreviewButton.setEnabled(True)
else:
self.AutoScriptStatusLabel.setText("未设置")
self.AutoScriptStatusLabel.setStyleSheet("color: #969696;")
self.AutoScriptPreviewButton.setEnabled(False)
dlg.deleteLater()
@Slot()
def _onPreviewAutoScript(self):
if not self.__auto_script:
return
from gui.ALAutoScriptPrevDialog import ALAutoScriptPreviewDialog
dlg = ALAutoScriptPreviewDialog(self, self.__auto_script)
dlg.exec()
dlg.deleteLater()
@Slot()
def _onAutoScriptHelp(
self
):
QDesktopServices.openUrl(
QUrl("https://www.autolibrary.kenanzhu.com/manuals/autoscript")
)
self.AutoScriptSetButton.clicked.connect(self.onSetAutoScript)
self.AutoScriptPreviewButton.clicked.connect(self.onPreviewAutoScript)
self.AutoScriptHelpButton.clicked.connect(self.onAutoScriptHelp)
def getTimerTask(
@@ -200,6 +209,16 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
minutes = self.RelativeMinuteSpinBox.value(),
seconds = self.RelativeSecondSpinBox.value()
)
if self.__edit_timer_task:
task_data = dict(self.__edit_timer_task)
task_data["name"] = name
task_data["execute_time"] = execute_time
task_data["silent"] = silent
task_data["status"] = ALTimerTaskStatus.PENDING
task_data["executed"] = False
task_data["repeat_auto_script"] = self.__auto_script
else:
task_data = {
"name": name,
"uuid": uuid.uuid4().hex.upper() + f"-{added_time.strftime("%Y%m%d%H%M%S")}",
@@ -212,8 +231,12 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
"repeat": self.RepeatCheckBox.isChecked(),
"repeat_auto_script": self.__auto_script,
}
if task_data["repeat"]:
task_data["history"] = [] # repeat history
repeat = self.RepeatCheckBox.isChecked()
task_data["repeat"] = repeat
if repeat:
if "repeat_history" not in task_data:
task_data["repeat_history"] = []
repeat_days = []
if self.MonCheckBox.isChecked():
repeat_days.append(0)
@@ -266,3 +289,39 @@ class ALTimerTaskAddDialog(QDialog, Ui_ALTimerTaskAddDialog):
self.SatCheckBox.setEnabled(checked)
self.SunCheckBox.setEnabled(checked)
self.AutoScriptGroupBox.setVisible(checked)
@Slot()
def onSetAutoScript(self):
dlg = ALAutoScriptOrchDialog(self, existingScript=self.__auto_script)
if dlg.exec() == QDialog.DialogCode.Accepted:
script = dlg.getScript()
self.__auto_script = script
if script:
self.AutoScriptStatusLabel.setText("已设置")
self.AutoScriptStatusLabel.setStyleSheet("color: #4CAF50;")
self.AutoScriptPreviewButton.setEnabled(True)
else:
self.AutoScriptStatusLabel.setText("未设置")
self.AutoScriptStatusLabel.setStyleSheet("color: #969696;")
self.AutoScriptPreviewButton.setEnabled(False)
dlg.deleteLater()
@Slot()
def onPreviewAutoScript(self):
if not self.__auto_script:
return
from gui.ALAutoScriptPrevDialog import ALAutoScriptPreviewDialog
dlg = ALAutoScriptPreviewDialog(self, self.__auto_script)
dlg.exec()
dlg.deleteLater()
@Slot()
def onAutoScriptHelp(
self
):
QDesktopServices.openUrl(
QUrl("https://www.autolibrary.kenanzhu.com/manuals/autoscript")
)
+9 -9
View File
@@ -30,7 +30,7 @@ class ALTimerTaskHistoryDialog(QDialog):
super().__init__(parent)
self.__task_data = task_data
self.__history = task_data.get("history", [])
self.__history = task_data.get("repeat_history", [])
self.modifyUi()
self.connectSignals()
@@ -130,6 +130,13 @@ 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
@@ -137,11 +144,4 @@ class ALTimerTaskHistoryDialog(QDialog):
self.__history.clear()
self.HistoryTableWidget.setRowCount(0)
self.__task_data["history"] = self.__history
def getHistory(
self
) -> list:
return self.__history
self.__task_data["repeat_history"] = self.__history
+53 -13
View File
@@ -19,10 +19,10 @@ from PySide6.QtCore import (
)
from PySide6.QtWidgets import (
QDialog, QWidget, QListWidgetItem, QMessageBox,
QHBoxLayout, QVBoxLayout, QLabel, QPushButton
QHBoxLayout, QVBoxLayout, QLabel, QPushButton, QMenu
)
from PySide6.QtGui import (
QCloseEvent
QCloseEvent, QAction
)
import managers.config.ConfigManager as ConfigManager
@@ -35,6 +35,8 @@ from gui.ALTimerTaskHistoryDialog import ALTimerTaskHistoryDialog
class ALTimerTaskItemWidget(QWidget):
editRequested = Signal(dict)
def __init__(
self,
parent = None,
@@ -45,6 +47,8 @@ class ALTimerTaskItemWidget(QWidget):
self.__timer_task = timer_task
self.modifyUi()
self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.customContextMenuRequested.connect(self.showContextMenu)
def modifyUi(
@@ -145,6 +149,27 @@ class ALTimerTaskItemWidget(QWidget):
self.DeleteButton.setEnabled(False)
self.setFixedHeight(55)
@Slot(object)
def showContextMenu(
self,
pos
):
menu = QMenu(self)
edit_action = QAction("编辑", self)
edit_action.triggered.connect(
lambda: self.editRequested.emit(self.__timer_task)
)
menu.addAction(edit_action)
if self.__timer_task["status"] != ALTimerTaskStatus.RUNNING\
and self.__timer_task["status"] != ALTimerTaskStatus.READY:
delete_action = QAction("删除", self)
delete_action.triggered.connect(
lambda: self.parent().deleteTask(self.__timer_task)
)
menu.addAction(delete_action)
menu.exec(self.mapToGlobal(pos))
class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
@@ -224,8 +249,8 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
task["added_time"] = datetime.strptime(task["added_time"], "%Y-%m-%d %H:%M:%S")
task["execute_time"] = datetime.strptime(task["execute_time"], "%Y-%m-%d %H:%M:%S")
task["status"] = ALTimerTaskStatus(task["status"])
if "history" in task:
for item in task["history"]:
if "repeat_history" in task:
for item in task["repeat_history"]:
item["result"] = ALTimerTaskStatus(item["result"])
return timer_tasks["timer_tasks"]
raise Exception("定时任务配置文件格式错误")
@@ -248,8 +273,8 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
task["added_time"] = task["added_time"].strftime("%Y-%m-%d %H:%M:%S")
task["execute_time"] = task["execute_time"].strftime("%Y-%m-%d %H:%M:%S")
task["status"] = task["status"].value
if "history" in task:
for item in task["history"]:
if "repeat_history" in task:
for item in task["repeat_history"]:
item["result"] = item["result"].value
self.__cfg_mgr.set(ConfigManager.ConfigType.TIMERTASK, "", { "timer_tasks": timer_tasks })
return True
@@ -363,6 +388,7 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
widget.HistoryButton.clicked.connect(
lambda _, task = timer_task: self.showTaskHistory(task)
)
widget.editRequested.connect(self.editTask)
item.setSizeHint(widget.size())
self.TimerTasksListWidget.addItem(item)
self.TimerTasksListWidget.setItemWidget(item, widget)
@@ -378,15 +404,30 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.__timer_tasks.append(timer_task)
self.timerTasksChanged.emit()
def editTask(
self,
timer_task: dict
):
dialog = ALTimerTaskAddDialog(self, timer_task)
if dialog.exec() == QDialog.DialogCode.Accepted:
updated = dialog.getTimerTask()
for i, task in enumerate(self.__timer_tasks):
if task["uuid"] == updated["uuid"]:
self.__timer_tasks[i] = updated
break
self.timerTasksChanged.emit()
@staticmethod
def getTimerTaskDetailMessage(
timer_task: dict
):
if "history" not in timer_task:
if "repeat_history" not in timer_task:
history = []
else:
history = timer_task["history"]
history = timer_task["repeat_history"]
history_count = len(history)
return (
f"任务名称:{timer_task["name"]}\n"
@@ -559,7 +600,6 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
self.updateTimerTaskList()
self.updateStat()
@Slot(dict)
def onTimerTaskIsRunning(
self,
@@ -584,12 +624,12 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
ALTimerTaskStatus.OUTDATED}
if status not in valid_statuses:
return timer_task
if "history" not in timer_task:
timer_task["history"] = []
if "repeat_history" not in timer_task:
timer_task["repeat_history"] = []
if status != ALTimerTaskStatus.OUTDATED:
executed_time = datetime.now()
duration = (executed_time - timer_task["execute_time"]).total_seconds()
timer_task["history"].append({
timer_task["repeat_history"].append({
"execute_time": timer_task["execute_time"].strftime("%Y-%m-%d %H:%M:%S"),
"executed_time": executed_time.strftime("%Y-%m-%d %H:%M:%S"),
"result": status,
@@ -603,7 +643,7 @@ class ALTimerTaskManageWidget(QWidget, Ui_ALTimerTaskManageWidget):
delta_days = (current_time - execute_time).days
for i in range(delta_days + 1):
if (execute_weekday + i)%7 in timer_task["repeat_days"]:
timer_task["history"].append({
timer_task["repeat_history"].append({
"execute_time": (execute_time + timedelta(days=i)).strftime("%Y-%m-%d %H:%M:%S"),
"executed_time": (execute_time + timedelta(days=i)).strftime("%Y-%m-%d %H:%M:%S"),
"result": status,