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

Compare commits

...

4 Commits

11 changed files with 454 additions and 187 deletions
+10 -10
View File
@@ -30,7 +30,7 @@ class ALAboutDialog(QDialog, Ui_ALAboutDialog):
def __init__(
self,
parent=None
parent = None
):
super().__init__(parent)
@@ -67,21 +67,21 @@ Version: {AL_VERSION}<br>
Python version: {platform.python_version()}<br>
Qt version: {self.getQtVersion()}<br>
<h4>Author Information:</h4>
Developer: KenanZhu<br>
Contact: nanoki_zh@163.com<br>
GitHub: <a href="https://www.github.com/KenanZhu" style="text-decoration: none;">https://www.github.com/KenanZhu</a><br>
<h4>System Information:</h4>
Processor: {platform.processor()}<br>
Operating system: {os_info['system']}<br>
System version: {os_info['version']}<br>
System architecture: {os_info['architecture']}<br>
<h4>Project Information:</h4>
License: MIT License<br>
Project repository: <a href="https://www.github.com/KenanZhu/AutoLibrary" style="text-decoration: none;">https://www.github.com/KenanZhu/AutoLibrary</a><br>
Project website: <a href="https://www.autolibrary.cv/" style="text-decoration: none;">https://www.autolibrary.cv/</a><br>
<h4>System Information:</h4>
Processor: {platform.processor()}<br>
Operating system: {os_info['system']}<br>
System version: {os_info['version']}<br>
System architecture: {os_info['architecture']}<br>
<h4>Author Information:</h4>
Developer: KenanZhu<br>
Contact: nanoki_zh@163.com<br>
GitHub: <a href="https://www.github.com/KenanZhu" style="text-decoration: none;">https://www.github.com/KenanZhu</a><br>
"""
return about_text
+56 -21
View File
@@ -6,25 +6,28 @@
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>300</height>
<width>400</width>
<height>400</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>300</height>
<width>400</width>
<height>400</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>800</width>
<height>300</height>
<height>400</height>
</size>
</property>
<property name="windowTitle">
<string>关于 - AutoLibrary</string>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="ALAboutDialogLayout">
<property name="spacing">
<number>5</number>
@@ -96,23 +99,55 @@
</layout>
</item>
<item>
<widget class="QTextEdit" name="AboutInfoEdit">
<property name="font">
<font>
<family>Courier New</family>
<bold>false</bold>
</font>
<layout class="QHBoxLayout" name="AboutInfoLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::LineWrapMode::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
</property>
</widget>
<item>
<widget class="QFrame" name="frame">
<property name="minimumSize">
<size>
<width>56</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>56</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="QTextEdit" name="AboutInfoEdit">
<property name="font">
<font>
<family>Courier New</family>
<bold>false</bold>
</font>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::LineWrapMode::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="CopyButton">
+1
View File
@@ -31,6 +31,7 @@ from gui.Ui_ALAddTimerTaskDialog import Ui_ALAddTimerTaskDialog
class TimerTaskStatus(Enum):
PENDING = "等待中"
READY = "已就绪"
RUNNING = "执行中"
+3 -3
View File
@@ -19,8 +19,8 @@ from PySide6.QtWidgets import (
from PySide6.QtGui import QCloseEvent
from gui.Ui_ALConfigWidget import Ui_ALConfigWidget
from gui.SeatMapWidget import SeatMapWidget
from gui.SeatMapTable import seats_maps
from gui.ALSeatMapWidget import ALSeatMapWidget
from gui.ALSeatMapTable import seats_maps
from utils.ConfigReader import ConfigReader
from utils.ConfigWriter import ConfigWriter
@@ -647,7 +647,7 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
floor_idx = self.__floor_rmap[floor]
room_idx = self.__room_rmap[room]
if self.__seat_map_widget is None:
self.__seat_map_widget = SeatMapWidget(
self.__seat_map_widget = ALSeatMapWidget(
self,
floor,
room,
+16 -127
View File
@@ -13,7 +13,7 @@ import time
import queue
from PySide6.QtCore import (
Qt, Signal, Slot, QDir, QFileInfo, QTimer, QThread, QUrl,
Qt, Signal, Slot, QDir, QFileInfo, QTimer, QUrl,
)
from PySide6.QtWidgets import (
QMainWindow, QMenu, QSystemTrayIcon
@@ -26,124 +26,12 @@ from gui.Ui_ALMainWindow import Ui_ALMainWindow
from gui.ALConfigWidget import ALConfigWidget
from gui.ALTimerTaskWidget import ALTimerTaskWidget
from gui.ALAboutDialog import ALAboutDialog
from gui.ALMainWorkers import TimerTaskWorker, AutoLibWorker
from gui import AutoLibraryResource
from operators.AutoLib import AutoLib
from utils.ConfigReader import ConfigReader
class AutoLibWorker(QThread):
finishedSignal = Signal()
showTraceSignal = Signal(str)
showMsgSignal = Signal(str)
def __init__(
self,
input_queue: queue.Queue,
output_queue: queue.Queue,
config_paths: dict
):
super().__init__()
self.__input_queue = input_queue
self.__output_queue = output_queue
self.__config_paths = config_paths
def checkTimeAvailable(
self,
) -> bool:
current_time = time.strftime("%H:%M", time.localtime())
if current_time >= "23:30" or current_time <= "07:30":
return False
return True
def checkConfigPaths(
self,
) -> bool:
if not all(
os.path.exists(path) for path in self.__config_paths.values()
):
self.showTraceSignal.emit(
"配置文件路径不存在, 请检查配置文件路径是否正确。"
)
return False
return True
def run(
self
):
auto_lib = None
try:
if not self.checkTimeAvailable():
self.showTraceSignal.emit(
"当前时间不在图书馆开放时间内。\n"\
" 请在 07:30 - 23:30 之间尝试"
)
return
if not self.checkConfigPaths():
return
self.showTraceSignal.emit("AutoLibrary 开始运行")
auto_lib = AutoLib(
self.__input_queue,
self.__output_queue,
)
auto_lib.run(
ConfigReader(self.__config_paths["system"]),
ConfigReader(self.__config_paths["users"]),
)
except Exception as e:
self.showTraceSignal.emit(
f"AutoLibrary 运行时发生异常 : {e}"
)
finally:
if auto_lib:
auto_lib.close()
self.showTraceSignal.emit("AutoLibrary 运行结束")
self.finishedSignal.emit()
class TimerTaskWorker(AutoLibWorker):
finishedSignal_TimerWorker = Signal(dict)
def __init__(
self,
timer_task: dict,
input_queue: queue.Queue,
output_queue: queue.Queue,
config_paths: dict
):
super().__init__(
input_queue,
output_queue,
config_paths,
)
self.__timer_task = timer_task
self.__stopped = False
def run(
self
):
self.showTraceSignal.emit(
f"定时任务 {self.__timer_task['name']} 开始运行"
)
super().run()
self.showTraceSignal.emit(
f"定时任务 {self.__timer_task['name']} 运行结束"
)
self.finishedSignal_TimerWorker.emit(self.__timer_task)
from utils.ConfigWriter import ConfigWriter
class ALMainWindow(QMainWindow, Ui_ALMainWindow):
@@ -167,10 +55,10 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
self.__config_paths = {
"system": QDir.toNativeSeparators(script_dir.absoluteFilePath("system.json")),
"users": QDir.toNativeSeparators(script_dir.absoluteFilePath("users.json")),
"timer_tasks": QDir.toNativeSeparators(script_dir.absoluteFilePath("timer_tasks.json")),
}
self.__alTimerTaskWidget = None
self.__alConfigWidget = None
self.__alAboutDialog = None
self.__auto_lib_thread = None
self.__current_timer_task_thread = None
self.__is_running_timer_task = False
@@ -192,14 +80,21 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
self.ManualAction.triggered.connect(self.onManualActionTriggered)
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(
self
):
if self.__alAboutDialog is None:
self.__alAboutDialog = ALAboutDialog(self)
self.__alAboutDialog.show()
about_dialog = ALAboutDialog(self)
about_dialog.exec()
def onManualActionTriggered(
@@ -423,7 +318,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
self.__config_paths = config_paths
@Slot(dict)
def onTimerTaskReady(
def onTimerTaskIsReady(
self,
timer_task: dict
):
@@ -459,13 +354,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
def onTimerTaskWidgetButtonClicked(
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.raise_()
self.__alTimerTaskWidget.activateWindow()
+132
View File
@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
"""
Copyright (c) 2025 KenanZhu.
All rights reserved.
This software is provided "as is", without any warranty of any kind.
You may use, modify, and distribute this file under the terms of the MIT License.
See the LICENSE file for details.
"""
import os
import time
import queue
from PySide6.QtCore import (
Signal, QThread
)
from operators.AutoLib import AutoLib
from utils.ConfigReader import ConfigReader
class AutoLibWorker(QThread):
finishedSignal = Signal()
showTraceSignal = Signal(str)
showMsgSignal = Signal(str)
def __init__(
self,
input_queue: queue.Queue,
output_queue: queue.Queue,
config_paths: dict
):
super().__init__()
self.__input_queue = input_queue
self.__output_queue = output_queue
self.__config_paths = config_paths
def checkTimeAvailable(
self,
) -> bool:
current_time = time.strftime("%H:%M", time.localtime())
if current_time >= "23:30" or current_time <= "07:30":
return False
return True
def checkConfigPaths(
self,
) -> bool:
if not all(
os.path.exists(path) for path in self.__config_paths.values()
):
self.showTraceSignal.emit(
"配置文件路径不存在, 请检查配置文件路径是否正确。"
)
return False
return True
def run(
self
):
auto_lib = None
try:
if not self.checkTimeAvailable():
self.showTraceSignal.emit(
"当前时间不在图书馆开放时间内。\n"\
" 请在 07:30 - 23:30 之间尝试"
)
return
if not self.checkConfigPaths():
return
self.showTraceSignal.emit("AutoLibrary 开始运行")
auto_lib = AutoLib(
self.__input_queue,
self.__output_queue,
)
auto_lib.run(
ConfigReader(self.__config_paths["system"]),
ConfigReader(self.__config_paths["users"]),
)
except Exception as e:
self.showTraceSignal.emit(
f"AutoLibrary 运行时发生异常 : {e}"
)
finally:
if auto_lib:
auto_lib.close()
self.showTraceSignal.emit("AutoLibrary 运行结束")
self.finishedSignal.emit()
class TimerTaskWorker(AutoLibWorker):
finishedSignal_TimerWorker = Signal(dict)
def __init__(
self,
timer_task: dict,
input_queue: queue.Queue,
output_queue: queue.Queue,
config_paths: dict
):
super().__init__(
input_queue,
output_queue,
config_paths,
)
self.__timer_task = timer_task
self.__stopped = False
def run(
self
):
self.showTraceSignal.emit(
f"定时任务 {self.__timer_task['name']} 开始运行"
)
super().run()
self.showTraceSignal.emit(
f"定时任务 {self.__timer_task['name']} 运行结束"
)
self.finishedSignal_TimerWorker.emit(self.__timer_task)
@@ -15,7 +15,7 @@ from PySide6.QtWidgets import (
)
class SeatFrame(QFrame):
class ALSeatFrame(QFrame):
clicked = Signal(str)
@@ -18,10 +18,10 @@ from PySide6.QtWidgets import (
from PySide6.QtGui import (
QPainter, QWheelEvent, QCloseEvent
)
from gui.SeatFrame import SeatFrame
from gui.ALSeatFrame import ALSeatFrame
class SeatMapWidget(QWidget):
class ALSeatMapWidget(QWidget):
seatMapWidgetClosed = Signal(list)
@@ -160,7 +160,7 @@ class SeatMapWidget(QWidget):
seats_number = [seat.strip() for seat in row.split(",")]
for seat_number in seats_number:
if seat_number:
seat_widget = SeatFrame(seat_number)
seat_widget = ALSeatFrame(seat_number)
seat_widget.clicked.connect(self.onSeatClicked)
self.SeatsContainerLayout.addWidget(seat_widget, row_idx, col_idx)
self.__seat_frames[seat_number] = seat_widget
+156 -22
View File
@@ -10,6 +10,7 @@ See the LICENSE file for details.
import os
import sys
import time
import copy
import queue
from enum import Enum
@@ -23,12 +24,22 @@ from PySide6.QtWidgets import (
QHBoxLayout, QVBoxLayout, QLabel, QPushButton
)
from PySide6.QtGui import (
QCloseEvent
QCloseEvent, QScreen
)
from gui.Ui_ALTimerTaskWidget import Ui_ALTimerTaskWidget
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):
@@ -125,22 +136,38 @@ class TimerTaskItemWidget(QWidget):
class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
timerTasksChanged = Signal(list)
timerTaskReady = Signal(dict)
timerTasksChanged = Signal()
timerTaskIsReady = Signal(dict)
timerTaskWidgetClosed = Signal()
def __init__(
self,
parent = None
parent = None,
timer_tasks_config_path: str = ""
):
super().__init__(parent)
self.__timer_tasks = []
self.__check_timer = None
self.__sort_policy = SortPolicy.BY_EXECUTE_TIME
self.__timer_tasks_config_path = timer_tasks_config_path
self.setupUi(self)
self.connectSignals()
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(
@@ -152,12 +179,79 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
self.__check_timer.start(500)
def connectSignals(
def initializeTimerTasks(
self
):
) -> bool:
self.AddTimerTaskButton.clicked.connect(self.addTask)
self.ClearAllTimerTasksButton.clicked.connect(self.clearAllTasks)
timer_tasks = self.loadTimerTasks(self.__timer_tasks_config_path)
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(
@@ -170,6 +264,25 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
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(
self
):
@@ -197,9 +310,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
):
self.TimerTasksListWidget.clear()
self.__timer_tasks.sort(
key = lambda x: x["execute_time"]
)
self.sortTimerTasks(self.__sort_policy)
for timer_task in self.__timer_tasks:
item = QListWidgetItem()
item.setData(Qt.UserRole, timer_task)
@@ -220,8 +331,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
if dialog.exec() == QDialog.DialogCode.Accepted:
timer_task = dialog.getTimerTask()
self.__timer_tasks.append(timer_task)
self.updateTimerTaskList()
self.updateStat()
self.timerTasksChanged.emit()
def deleteTask(
@@ -233,8 +343,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
x for x in self.__timer_tasks
if x["task_uuid"] != task_uuid
]
self.updateTimerTaskList()
self.updateStat()
self.timerTasksChanged.emit()
def clearAllTasks(
@@ -264,14 +373,15 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
"存在正在执行或已就绪的队列任务,无法清除所有定时任务 !"
)
self.__timer_tasks = in_queue_tasks
self.updateTimerTaskList()
self.updateStat()
self.timerTasksChanged.emit()
def checkTasks(
self
):
need_update = False
now = datetime.now()
for timer_task in self.__timer_tasks:
if timer_task["execute_time"] > now:
@@ -280,9 +390,35 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
continue
if timer_task["execute_time"] <= now + timedelta(seconds = -5):
timer_task["status"] = TimerTaskStatus.OUTDATED
need_update = True
else:
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.updateStat()
@@ -296,8 +432,7 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
for task in self.__timer_tasks:
if task["task_uuid"] == timer_task["task_uuid"]:
task["status"] = TimerTaskStatus.RUNNING
self.updateTimerTaskList()
self.updateStat()
self.timerTasksChanged.emit()
@Slot(dict)
@@ -309,5 +444,4 @@ class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
for task in self.__timer_tasks:
if task["task_uuid"] == timer_task["task_uuid"]:
task["status"] = TimerTaskStatus.EXECUTED
self.updateTimerTaskList()
self.updateStat()
self.timerTasksChanged.emit()
+76
View File
@@ -161,6 +161,82 @@
</item>
</layout>
</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>
<widget class="QListWidget" name="TimerTasksListWidget">
<property name="enabled">