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

feat(ALTimerTaskWidget): timer tasks' data persistence and perpetuation

This commit is contained in:
2025-12-09 08:49:44 +08:00
parent b129f47b48
commit 6472d3938e
4 changed files with 244 additions and 30 deletions
+1
View File
@@ -31,6 +31,7 @@ from gui.Ui_ALAddTimerTaskDialog import Ui_ALAddTimerTaskDialog
class TimerTaskStatus(Enum): class TimerTaskStatus(Enum):
PENDING = "等待中" PENDING = "等待中"
READY = "已就绪" READY = "已就绪"
RUNNING = "执行中" RUNNING = "执行中"
+11 -8
View File
@@ -55,6 +55,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
self.__config_paths = { self.__config_paths = {
"system": QDir.toNativeSeparators(script_dir.absoluteFilePath("system.json")), "system": QDir.toNativeSeparators(script_dir.absoluteFilePath("system.json")),
"users": QDir.toNativeSeparators(script_dir.absoluteFilePath("users.json")), "users": QDir.toNativeSeparators(script_dir.absoluteFilePath("users.json")),
"timer_tasks": QDir.toNativeSeparators(script_dir.absoluteFilePath("timer_tasks.json")),
} }
self.__alTimerTaskWidget = None self.__alTimerTaskWidget = None
self.__alConfigWidget = None self.__alConfigWidget = None
@@ -79,6 +80,14 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
self.ManualAction.triggered.connect(self.onManualActionTriggered) self.ManualAction.triggered.connect(self.onManualActionTriggered)
self.AboutAction.triggered.connect(self.onAboutActionTriggered) self.AboutAction.triggered.connect(self.onAboutActionTriggered)
# initialize timer task widget, but not show it
self.__alTimerTaskWidget = ALTimerTaskWidget(self, self.__config_paths["timer_tasks"])
self.timerTaskIsRunning.connect(self.__alTimerTaskWidget.onTimerTaskIsRunning)
self.timerTaskIsExecuted.connect(self.__alTimerTaskWidget.onTimerTaskIsExecuted)
self.__alTimerTaskWidget.timerTaskIsReady.connect(self.onTimerTaskIsReady)
self.__alTimerTaskWidget.timerTaskWidgetClosed.connect(self.onTimerTaskWidgetClosed)
self.__alTimerTaskWidget.setWindowFlags(Qt.WindowType.Window|Qt.WindowType.WindowCloseButtonHint)
def onAboutActionTriggered( def onAboutActionTriggered(
self self
@@ -309,7 +318,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
self.__config_paths = config_paths self.__config_paths = config_paths
@Slot(dict) @Slot(dict)
def onTimerTaskReady( def onTimerTaskIsReady(
self, self,
timer_task: dict timer_task: dict
): ):
@@ -345,13 +354,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
def onTimerTaskWidgetButtonClicked( def onTimerTaskWidgetButtonClicked(
self self
): ):
if self.__alTimerTaskWidget is None:
self.__alTimerTaskWidget = ALTimerTaskWidget(self)
self.timerTaskIsRunning.connect(self.__alTimerTaskWidget.onTimerTaskIsRunning)
self.timerTaskIsExecuted.connect(self.__alTimerTaskWidget.onTimerTaskIsExecuted)
self.__alTimerTaskWidget.timerTaskReady.connect(self.onTimerTaskReady)
self.__alTimerTaskWidget.timerTaskWidgetClosed.connect(self.onTimerTaskWidgetClosed)
self.__alTimerTaskWidget.setWindowFlags(Qt.Window)
self.__alTimerTaskWidget.show() self.__alTimerTaskWidget.show()
self.__alTimerTaskWidget.raise_() self.__alTimerTaskWidget.raise_()
self.__alTimerTaskWidget.activateWindow() self.__alTimerTaskWidget.activateWindow()
+156 -22
View File
@@ -10,6 +10,7 @@ See the LICENSE file for details.
import os import os
import sys import sys
import time import time
import copy
import queue import queue
from enum import Enum from enum import Enum
@@ -23,12 +24,22 @@ from PySide6.QtWidgets import (
QHBoxLayout, QVBoxLayout, QLabel, QPushButton QHBoxLayout, QVBoxLayout, QLabel, QPushButton
) )
from PySide6.QtGui import ( from PySide6.QtGui import (
QCloseEvent QCloseEvent, QScreen
) )
from gui.Ui_ALTimerTaskWidget import Ui_ALTimerTaskWidget from gui.Ui_ALTimerTaskWidget import Ui_ALTimerTaskWidget
from gui.ALAddTimerTaskDialog import ALAddTimerTaskWidget, TimerTaskStatus from gui.ALAddTimerTaskDialog import ALAddTimerTaskWidget, TimerTaskStatus
from utils.ConfigReader import ConfigReader
from utils.ConfigWriter import ConfigWriter
class SortPolicy(Enum):
BY_NAME = "按名称"
BY_ADD_TIME = "按添加时间"
BY_EXECUTE_TIME = "按执行时间"
class TimerTaskItemWidget(QWidget): class TimerTaskItemWidget(QWidget):
@@ -125,22 +136,38 @@ class TimerTaskItemWidget(QWidget):
class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget): class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
timerTasksChanged = Signal(list) timerTasksChanged = Signal()
timerTaskReady = Signal(dict) timerTaskIsReady = Signal(dict)
timerTaskWidgetClosed = Signal() timerTaskWidgetClosed = Signal()
def __init__( def __init__(
self, self,
parent = None parent = None,
timer_tasks_config_path: str = ""
): ):
super().__init__(parent) super().__init__(parent)
self.__timer_tasks = [] self.__timer_tasks = []
self.__check_timer = None self.__check_timer = None
self.__sort_policy = SortPolicy.BY_EXECUTE_TIME
self.__timer_tasks_config_path = timer_tasks_config_path
self.setupUi(self) self.setupUi(self)
self.connectSignals() self.connectSignals()
self.setupTimer() self.setupTimer()
if not self.initializeTimerTasks():
return
def connectSignals(
self
):
self.AddTimerTaskButton.clicked.connect(self.addTask)
self.ClearAllTimerTasksButton.clicked.connect(self.clearAllTasks)
self.TimerTaskSortTypeComboBox.currentIndexChanged.connect(self.onSortPolicyComboBoxChanged)
self.timerTasksChanged.connect(self.onTimerTasksChanged)
def setupTimer( def setupTimer(
@@ -152,12 +179,79 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
self.__check_timer.start(500) self.__check_timer.start(500)
def connectSignals( def initializeTimerTasks(
self self
): ) -> bool:
self.AddTimerTaskButton.clicked.connect(self.addTask) timer_tasks = self.loadTimerTasks(self.__timer_tasks_config_path)
self.ClearAllTimerTasksButton.clicked.connect(self.clearAllTasks) if timer_tasks is not None:
self.__timer_tasks = timer_tasks
self.timerTasksChanged.emit()
return True
if self.saveTimerTasks(self.__timer_tasks_config_path, copy.deepcopy(timer_tasks)):
QMessageBox.information(
self,
"信息 - AutoLibrary",
f"定时任务配置文件初始化完成: \n{self.__timer_tasks_config_path}"
)
self.__timer_tasks = timer_tasks
self.updateTimerTaskList()
return True
return False
def loadTimerTasks(
self,
timer_tasks_config_path: str
) -> list:
try:
if not timer_tasks_config_path or not os.path.exists(timer_tasks_config_path):
raise Exception("定时任务配置文件不存在")
timer_tasks = ConfigReader(timer_tasks_config_path).getConfigs()
if timer_tasks and "timer_tasks" in timer_tasks:
for task in timer_tasks["timer_tasks"]:
task["add_time"] = datetime.strptime(task["add_time"], "%Y-%m-%d %H:%M:%S")
task["execute_time"] = datetime.strptime(task["execute_time"], "%Y-%m-%d %H:%M:%S")
task["status"] = TimerTaskStatus(task["status"])
return timer_tasks["timer_tasks"]
raise Exception("定时任务配置文件格式错误")
except Exception as e:
QMessageBox.warning(
self,
"警告 - AutoLibrary",
f"加载定时任务配置发生错误 ! : {e}\n"\
f"文件路径: {timer_tasks_config_path}"
)
return None
def saveTimerTasks(
self,
timer_tasks_config_path: str,
timer_tasks: list
) -> bool:
try:
if not timer_tasks_config_path:
raise Exception("配置文件路径为空")
for task in timer_tasks:
task["add_time"] = task["add_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
ConfigWriter(
timer_tasks_config_path,
{ "timer_tasks": timer_tasks }
)
return True
except Exception as e:
QMessageBox.warning(
self,
"警告 - AutoLibrary",
f"保存定时任务配置发生错误 ! : {e}\n"\
f"文件路径: {timer_tasks_config_path}"
)
return False
def closeEvent( def closeEvent(
@@ -170,6 +264,25 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
event.ignore() event.ignore()
def sortTimerTasks(
self,
policy: SortPolicy = SortPolicy.BY_EXECUTE_TIME
):
if policy == SortPolicy.BY_NAME:
self.__timer_tasks.sort(
key = lambda x: x["name"]
)
elif policy == SortPolicy.BY_ADD_TIME:
self.__timer_tasks.sort(
key = lambda x: x["add_time"]
)
elif policy == SortPolicy.BY_EXECUTE_TIME:
self.__timer_tasks.sort(
key = lambda x: x["execute_time"]
)
def updateStat( def updateStat(
self self
): ):
@@ -197,9 +310,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
): ):
self.TimerTasksListWidget.clear() self.TimerTasksListWidget.clear()
self.__timer_tasks.sort( self.sortTimerTasks(self.__sort_policy)
key = lambda x: x["execute_time"]
)
for timer_task in self.__timer_tasks: for timer_task in self.__timer_tasks:
item = QListWidgetItem() item = QListWidgetItem()
item.setData(Qt.UserRole, timer_task) item.setData(Qt.UserRole, timer_task)
@@ -220,8 +331,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
if dialog.exec() == QDialog.DialogCode.Accepted: if dialog.exec() == QDialog.DialogCode.Accepted:
timer_task = dialog.getTimerTask() timer_task = dialog.getTimerTask()
self.__timer_tasks.append(timer_task) self.__timer_tasks.append(timer_task)
self.updateTimerTaskList() self.timerTasksChanged.emit()
self.updateStat()
def deleteTask( def deleteTask(
@@ -233,8 +343,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
x for x in self.__timer_tasks x for x in self.__timer_tasks
if x["task_uuid"] != task_uuid if x["task_uuid"] != task_uuid
] ]
self.updateTimerTaskList() self.timerTasksChanged.emit()
self.updateStat()
def clearAllTasks( def clearAllTasks(
@@ -264,14 +373,15 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
"存在正在执行或已就绪的队列任务,无法清除所有定时任务 !" "存在正在执行或已就绪的队列任务,无法清除所有定时任务 !"
) )
self.__timer_tasks = in_queue_tasks self.__timer_tasks = in_queue_tasks
self.updateTimerTaskList() self.timerTasksChanged.emit()
self.updateStat()
def checkTasks( def checkTasks(
self self
): ):
need_update = False
now = datetime.now() now = datetime.now()
for timer_task in self.__timer_tasks: for timer_task in self.__timer_tasks:
if timer_task["execute_time"] > now: if timer_task["execute_time"] > now:
@@ -280,9 +390,35 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
continue continue
if timer_task["execute_time"] <= now + timedelta(seconds = -5): if timer_task["execute_time"] <= now + timedelta(seconds = -5):
timer_task["status"] = TimerTaskStatus.OUTDATED timer_task["status"] = TimerTaskStatus.OUTDATED
need_update = True
else: else:
timer_task["status"] = TimerTaskStatus.READY timer_task["status"] = TimerTaskStatus.READY
self.timerTaskReady.emit(timer_task) self.timerTaskIsReady.emit(timer_task)
need_update = True
if need_update:
self.timerTasksChanged.emit()
@Slot(int)
def onSortPolicyComboBoxChanged(
self,
policy: int
):
mapping = {
0: SortPolicy.BY_NAME,
1: SortPolicy.BY_ADD_TIME,
2: SortPolicy.BY_EXECUTE_TIME
}
self.__sort_policy = mapping[policy]
self.updateTimerTaskList()
@Slot()
def onTimerTasksChanged(
self
):
self.saveTimerTasks(self.__timer_tasks_config_path, copy.deepcopy(self.__timer_tasks))
self.updateTimerTaskList() self.updateTimerTaskList()
self.updateStat() self.updateStat()
@@ -296,8 +432,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
for task in self.__timer_tasks: for task in self.__timer_tasks:
if task["task_uuid"] == timer_task["task_uuid"]: if task["task_uuid"] == timer_task["task_uuid"]:
task["status"] = TimerTaskStatus.RUNNING task["status"] = TimerTaskStatus.RUNNING
self.updateTimerTaskList() self.timerTasksChanged.emit()
self.updateStat()
@Slot(dict) @Slot(dict)
@@ -309,5 +444,4 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
for task in self.__timer_tasks: for task in self.__timer_tasks:
if task["task_uuid"] == timer_task["task_uuid"]: if task["task_uuid"] == timer_task["task_uuid"]:
task["status"] = TimerTaskStatus.EXECUTED task["status"] = TimerTaskStatus.EXECUTED
self.updateTimerTaskList() self.timerTasksChanged.emit()
self.updateStat()
+76
View File
@@ -161,6 +161,82 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="TimerTaskSortLayout">
<property name="spacing">
<number>5</number>
</property>
<item>
<widget class="QFrame" name="TimerTaskSortSpaceFrame">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="TimerTaskSortLabel">
<property name="minimumSize">
<size>
<width>40</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>40</width>
<height>25</height>
</size>
</property>
<property name="text">
<string>排序:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="TimerTaskSortTypeComboBox">
<property name="minimumSize">
<size>
<width>90</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>90</width>
<height>25</height>
</size>
</property>
<item>
<property name="text">
<string>按名称</string>
</property>
</item>
<item>
<property name="text">
<string>按添加时间</string>
</property>
</item>
<item>
<property name="text">
<string>按执行时间</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QListWidget" name="TimerTasksListWidget"> <widget class="QListWidget" name="TimerTasksListWidget">
<property name="enabled"> <property name="enabled">