mirror of
https://github.com/KenanZhu/AutoLibrary.git
synced 2026-06-18 07:23:03 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a8763add5 | |||
| c5e589f3d1 |
@@ -14,4 +14,8 @@ src/gui/AutoLibraryResources.py
|
||||
src/gui/AutoLibraryResource.py
|
||||
src/gui/Ui_ALMainWindow.py
|
||||
src/gui/Ui_ALConfigWidget.py
|
||||
src/gui/Ui_ALTimerTaskWidget.py
|
||||
src/gui/Ui_ALAddTimerTaskDialog.py
|
||||
src/gui/Ui_ALAboutDialog.py
|
||||
|
||||
Main.spec
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
# -*- 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 sys
|
||||
import platform
|
||||
|
||||
from PySide6.QtGui import (
|
||||
QIcon
|
||||
)
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QApplication
|
||||
)
|
||||
from PySide6.QtCore import (
|
||||
QTimer, Qt
|
||||
)
|
||||
|
||||
from gui.AppInfo import AL_VERSION
|
||||
from gui.Ui_ALAboutDialog import Ui_ALAboutDialog
|
||||
|
||||
from gui import AutoLibraryResource
|
||||
|
||||
|
||||
class ALAboutDialog(QDialog, Ui_ALAboutDialog):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
parent=None
|
||||
):
|
||||
super().__init__(parent)
|
||||
|
||||
self.setupUi(self)
|
||||
self.modifyUi()
|
||||
self.connectSignals()
|
||||
|
||||
|
||||
def modifyUi(
|
||||
self
|
||||
):
|
||||
|
||||
self.LogoIconLabel.setPixmap(QIcon(":/res/icon/icons/AutoLibrary.ico").pixmap(48, 48))
|
||||
info_text = self.generateAboutText()
|
||||
self.AboutInfoEdit.setHtml(info_text)
|
||||
self.AboutInfoEdit.setTextInteractionFlags(Qt.TextBrowserInteraction)
|
||||
|
||||
|
||||
def connectSignals(
|
||||
self
|
||||
):
|
||||
|
||||
self.CopyButton.clicked.connect(self.copyAboutInfo)
|
||||
|
||||
|
||||
def generateAboutText(
|
||||
self
|
||||
):
|
||||
|
||||
os_info = self.getOSInfo()
|
||||
about_text = f"""
|
||||
<h4>Version Information:</h4>
|
||||
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>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>
|
||||
"""
|
||||
return about_text
|
||||
|
||||
|
||||
def getOSInfo(
|
||||
self
|
||||
):
|
||||
|
||||
system = platform.system()
|
||||
version = platform.version()
|
||||
architecture = platform.architecture()[0]
|
||||
|
||||
if system == "Windows":
|
||||
try:
|
||||
version = platform.win32_ver()[1]
|
||||
except:
|
||||
pass
|
||||
elif system == "Darwin":
|
||||
try:
|
||||
version = platform.mac_ver()[0]
|
||||
except:
|
||||
pass
|
||||
elif system == "Linux":
|
||||
try:
|
||||
import distro # try to get Linux distro info
|
||||
version = f"{distro.name()} {distro.version()}"
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
return {
|
||||
'system': system,
|
||||
'version': version,
|
||||
'architecture': architecture
|
||||
}
|
||||
|
||||
|
||||
def getQtVersion(
|
||||
self
|
||||
):
|
||||
|
||||
try:
|
||||
from PySide6.QtCore import qVersion
|
||||
return qVersion()
|
||||
except:
|
||||
return "Unknown"
|
||||
|
||||
|
||||
def copyAboutInfo(
|
||||
self
|
||||
):
|
||||
|
||||
about_text = self.AboutInfoEdit.toPlainText()
|
||||
clipboard = QApplication.clipboard()
|
||||
clipboard.setText(about_text)
|
||||
original_text = self.CopyButton.text()
|
||||
self.CopyButton.setText("已复制")
|
||||
QTimer.singleShot(2000, lambda: self.CopyButton.setText(original_text))
|
||||
@@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ALAboutDialog</class>
|
||||
<widget class="QDialog" name="ALAboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>300</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>800</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>关于 - AutoLibrary</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="ALAboutDialogLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="LogoLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="LogoIconLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>56</width>
|
||||
<height>56</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>56</width>
|
||||
<height>56</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="LogoTextLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>24</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>AutoLibrary</string>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
<item>
|
||||
<widget class="QPushButton" name="CopyButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>复制</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,148 @@
|
||||
# -*- 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 sys
|
||||
import time
|
||||
import uuid
|
||||
import queue
|
||||
|
||||
from enum import Enum
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from PySide6.QtCore import (
|
||||
Qt, Signal, Slot, QDateTime
|
||||
)
|
||||
from PySide6.QtWidgets import (
|
||||
QLabel, QDialog, QWidget, QSpinBox, QVBoxLayout,
|
||||
QHBoxLayout, QGridLayout, QDateTimeEdit
|
||||
)
|
||||
from PySide6.QtGui import (
|
||||
QCloseEvent
|
||||
)
|
||||
|
||||
from gui.Ui_ALAddTimerTaskDialog import Ui_ALAddTimerTaskDialog
|
||||
|
||||
|
||||
class TimerTaskStatus(Enum):
|
||||
PENDING = "等待中"
|
||||
READY = "已就绪"
|
||||
RUNNING = "执行中"
|
||||
EXECUTED = "已执行"
|
||||
OUTDATED = "已过期"
|
||||
|
||||
|
||||
class ALAddTimerTaskWidget(QDialog, Ui_ALAddTimerTaskDialog):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
parent = None
|
||||
):
|
||||
|
||||
super().__init__(parent)
|
||||
|
||||
self.setupUi(self)
|
||||
self.connectSignals()
|
||||
self.modifyUi()
|
||||
|
||||
|
||||
def modifyUi(
|
||||
self
|
||||
):
|
||||
|
||||
self.TimerTypeComboBox.setCurrentIndex(0)
|
||||
self.SpecificTimerWidget = QWidget()
|
||||
self.SpecificTimerLayout = QHBoxLayout(self.SpecificTimerWidget)
|
||||
self.SpecificTimerLayout.addWidget(QLabel("定时时间:"))
|
||||
self.SpecificDateTimeEdit = QDateTimeEdit()
|
||||
self.SpecificDateTimeEdit.setCalendarPopup(True)
|
||||
self.SpecificDateTimeEdit.setDisplayFormat("yyyy-MM-dd HH:mm:ss")
|
||||
self.SpecificDateTimeEdit.setMinimumDateTime(QDateTime.currentDateTime())
|
||||
self.SpecificDateTimeEdit.setDateTime(QDateTime.currentDateTime().addSecs(60))
|
||||
self.SpecificTimerLayout.addWidget(self.SpecificDateTimeEdit)
|
||||
self.TimerConfigLayout.addWidget(self.SpecificTimerWidget)
|
||||
|
||||
self.RelativeTimerWidget = QWidget()
|
||||
self.RelativeTimerLayout = QGridLayout(self.RelativeTimerWidget)
|
||||
self.RelativeTimerLayout.addWidget(QLabel("相对时间:"), 0, 0)
|
||||
self.RelativeDaySpinBox = QSpinBox()
|
||||
self.RelativeDaySpinBox.setMinimum(0)
|
||||
self.RelativeDaySpinBox.setMaximum(365)
|
||||
self.RelativeDaySpinBox.setSuffix("天")
|
||||
self.RelativeTimerLayout.addWidget(self.RelativeDaySpinBox, 1, 0)
|
||||
self.RelativeHourSpinBox = QSpinBox()
|
||||
self.RelativeHourSpinBox.setMinimum(0)
|
||||
self.RelativeHourSpinBox.setMaximum(23)
|
||||
self.RelativeHourSpinBox.setSuffix("时")
|
||||
self.RelativeTimerLayout.addWidget(self.RelativeHourSpinBox, 1, 1)
|
||||
self.RelativeMinuteSpinBox = QSpinBox()
|
||||
self.RelativeMinuteSpinBox.setMinimum(0)
|
||||
self.RelativeMinuteSpinBox.setMaximum(59)
|
||||
self.RelativeMinuteSpinBox.setSuffix("分")
|
||||
self.RelativeTimerLayout.addWidget(self.RelativeMinuteSpinBox, 1, 2)
|
||||
self.RelativeSecondSpinBox = QSpinBox()
|
||||
self.RelativeSecondSpinBox.setMinimum(0)
|
||||
self.RelativeSecondSpinBox.setMaximum(59)
|
||||
self.RelativeSecondSpinBox.setSuffix("秒")
|
||||
self.RelativeTimerLayout.addWidget(self.RelativeSecondSpinBox, 1, 3)
|
||||
self.TimerConfigLayout.addWidget(self.RelativeTimerWidget)
|
||||
self.RelativeTimerWidget.setVisible(False)
|
||||
|
||||
|
||||
def connectSignals(
|
||||
self
|
||||
):
|
||||
|
||||
self.CancelButton.clicked.connect(self.reject)
|
||||
self.ConfirmButton.clicked.connect(self.accept)
|
||||
self.TimerTypeComboBox.currentIndexChanged.connect(self.onTimerTypeComboBoxIndexChanged)
|
||||
|
||||
|
||||
def getTimerTask(
|
||||
self
|
||||
) -> dict:
|
||||
|
||||
added_time = datetime.now()
|
||||
if not self.TaskNameLineEdit.text():
|
||||
name = f"未命名任务-{added_time.strftime("%Y%m%d%H%M%S")}"
|
||||
else:
|
||||
name = self.TaskNameLineEdit.text()
|
||||
timer_type_index = self.TimerTypeComboBox.currentIndex()
|
||||
silent = not self.ShowBeforeRunRadioButton.isChecked()
|
||||
if timer_type_index == 0:
|
||||
execute_time = self.SpecificDateTimeEdit.dateTime()
|
||||
tmp_time_str = execute_time.toString("yyyy-MM-dd HH:mm:ss")
|
||||
execute_time = datetime.strptime(tmp_time_str, "%Y-%m-%d %H:%M:%S")
|
||||
else:
|
||||
execute_time = datetime.now() + timedelta(
|
||||
days = self.RelativeDaySpinBox.value(),
|
||||
hours = self.RelativeHourSpinBox.value(),
|
||||
minutes = self.RelativeMinuteSpinBox.value(),
|
||||
seconds = self.RelativeSecondSpinBox.value()
|
||||
)
|
||||
return {
|
||||
"name": name,
|
||||
"task_uuid": uuid.uuid4().hex.upper() + f"-{added_time.strftime("%Y%m%d%H%M%S")}",
|
||||
"time_type": self.TimerTypeComboBox.currentText(),
|
||||
"execute_time": execute_time,
|
||||
"silent": silent,
|
||||
"add_time": added_time,
|
||||
"status": TimerTaskStatus.PENDING,
|
||||
"executed": False
|
||||
}
|
||||
|
||||
|
||||
@Slot(int)
|
||||
def onTimerTypeComboBoxIndexChanged(
|
||||
self,
|
||||
index: int
|
||||
):
|
||||
|
||||
self.SpecificTimerWidget.setVisible(index == 0)
|
||||
self.RelativeTimerWidget.setVisible(index == 1)
|
||||
@@ -0,0 +1,249 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ALAddTimerTaskDialog</class>
|
||||
<widget class="QDialog" name="ALAddTimerTaskDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>300</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>添加定时任务 - AutoLibrary</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="ALAddTimerTaskLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="TaskNameLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="TaskNameLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>任务名称:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="TaskNameLineEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="TimerConfigGroupBox">
|
||||
<property name="title">
|
||||
<string>定时设置</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="TimerConfigLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="TimerTypeSelectLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="TimerTypeLabel">
|
||||
<property name="text">
|
||||
<string>定时类型:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="TimerTypeComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>特定时间</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>相对时间</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="TaskConfigGroupBox">
|
||||
<property name="title">
|
||||
<string>运行设置</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="TaskConfigLayout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="SilentlyRunRadioButton">
|
||||
<property name="text">
|
||||
<string>静默运行</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="autoRepeat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="autoExclusive">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="ShowBeforeRunRadioButton">
|
||||
<property name="text">
|
||||
<string>运行前提示</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="ControLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="ControlSpaceFrame">
|
||||
<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="QPushButton" name="CancelButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>取消</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ConfirmButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>添加</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -20,8 +20,8 @@ from PySide6.QtGui import QCloseEvent
|
||||
|
||||
from gui.Ui_ALConfigWidget import Ui_ALConfigWidget
|
||||
from gui.SeatMapWidget import SeatMapWidget
|
||||
|
||||
from gui.SeatMapTable import seats_maps
|
||||
|
||||
from utils.ConfigReader import ConfigReader
|
||||
from utils.ConfigWriter import ConfigWriter
|
||||
|
||||
@@ -596,8 +596,12 @@ class ALConfigWidget(QWidget, Ui_ALConfigWidget):
|
||||
|
||||
current_item = self.UserListWidget.currentItem()
|
||||
if current_item:
|
||||
self.UserListWidget.takeItem(self.UserListWidget.row(current_item))
|
||||
self.UserListWidget.setCurrentItem(None)
|
||||
current_index = self.UserListWidget.row(current_item)
|
||||
self.UserListWidget.takeItem(current_index)
|
||||
if current_index < self.UserListWidget.count():
|
||||
self.UserListWidget.setCurrentRow(current_index)
|
||||
else:
|
||||
self.UserListWidget.setCurrentItem(None)
|
||||
|
||||
@Slot()
|
||||
def onShowPasswordCheckBoxChecked(
|
||||
|
||||
@@ -1829,6 +1829,9 @@
|
||||
<property name="text">
|
||||
<string>导出配置文件</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-save"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -1924,6 +1927,9 @@
|
||||
<property name="text">
|
||||
<string>新建配置</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-new"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -1943,6 +1949,9 @@
|
||||
<property name="text">
|
||||
<string>加载配置</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-open"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
+231
-14
@@ -13,19 +13,21 @@ import time
|
||||
import queue
|
||||
|
||||
from PySide6.QtCore import (
|
||||
Qt, Signal, Slot, QDir, QFileInfo, QTimer, QThread
|
||||
Qt, Signal, Slot, QDir, QFileInfo, QTimer, QThread, QUrl,
|
||||
)
|
||||
from PySide6.QtWidgets import (
|
||||
QMainWindow, QMenu
|
||||
QMainWindow, QMenu, QSystemTrayIcon
|
||||
)
|
||||
from PySide6.QtGui import (
|
||||
QTextCursor, QCloseEvent, QFont, QIcon
|
||||
QTextCursor, QCloseEvent, QFont, QIcon, QDesktopServices
|
||||
)
|
||||
|
||||
from .Ui_ALMainWindow import Ui_ALMainWindow
|
||||
from .ALConfigWidget import ALConfigWidget
|
||||
from gui.Ui_ALMainWindow import Ui_ALMainWindow
|
||||
from gui.ALConfigWidget import ALConfigWidget
|
||||
from gui.ALTimerTaskWidget import ALTimerTaskWidget
|
||||
from gui.ALAboutDialog import ALAboutDialog
|
||||
|
||||
from . import AutoLibraryResource
|
||||
from gui import AutoLibraryResource
|
||||
|
||||
from operators.AutoLib import AutoLib
|
||||
from utils.ConfigReader import ConfigReader
|
||||
@@ -49,7 +51,6 @@ class AutoLibWorker(QThread):
|
||||
self.__input_queue = input_queue
|
||||
self.__output_queue = output_queue
|
||||
self.__config_paths = config_paths
|
||||
self.__stopped = False
|
||||
|
||||
|
||||
def checkTimeAvailable(
|
||||
@@ -110,15 +111,46 @@ class AutoLibWorker(QThread):
|
||||
self.finishedSignal.emit()
|
||||
|
||||
|
||||
def stop(
|
||||
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.__stopped = True
|
||||
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)
|
||||
|
||||
|
||||
class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
||||
|
||||
timerTaskIsRunning = Signal(dict)
|
||||
timerTaskIsExecuted = Signal(dict)
|
||||
|
||||
def __init__(
|
||||
self
|
||||
):
|
||||
@@ -129,27 +161,100 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
||||
self.setupUi(self)
|
||||
self.__input_queue = queue.Queue()
|
||||
self.__output_queue = queue.Queue()
|
||||
self.__timer_task_queue = queue.Queue()
|
||||
script_path = sys.executable
|
||||
script_dir = QFileInfo(script_path).absoluteDir()
|
||||
self.__config_paths = {
|
||||
"system": QDir.toNativeSeparators(script_dir.absoluteFilePath("system.json")),
|
||||
"users": QDir.toNativeSeparators(script_dir.absoluteFilePath("users.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
|
||||
|
||||
self.modifyUi()
|
||||
self.setupTray()
|
||||
self.connectSignals()
|
||||
self.startMsgPolling()
|
||||
self.startTimerTaskPolling()
|
||||
|
||||
|
||||
def modifyUi(
|
||||
self
|
||||
):
|
||||
|
||||
icon = QIcon(":/res/icon/icons/AutoLibrary.ico")
|
||||
self.setWindowIcon(icon)
|
||||
self.icon = QIcon(":/res/icon/icons/AutoLibrary.ico")
|
||||
self.setWindowIcon(self.icon)
|
||||
self.MessageIOTextEdit.setFont(QFont("Courier New", 10))
|
||||
self.ManualAction.triggered.connect(self.onManualActionTriggered)
|
||||
self.AboutAction.triggered.connect(self.onAboutActionTriggered)
|
||||
|
||||
|
||||
def onAboutActionTriggered(
|
||||
self
|
||||
):
|
||||
|
||||
if self.__alAboutDialog is None:
|
||||
self.__alAboutDialog = ALAboutDialog(self)
|
||||
self.__alAboutDialog.show()
|
||||
|
||||
|
||||
def onManualActionTriggered(
|
||||
self
|
||||
):
|
||||
|
||||
url = QUrl("https://www.autolibrary.cv/docs/manual_lists.html")
|
||||
QDesktopServices.openUrl(url)
|
||||
|
||||
|
||||
def setupTray(
|
||||
self
|
||||
):
|
||||
|
||||
if not QSystemTrayIcon.isSystemTrayAvailable():
|
||||
self.showTraceSignal.emit(
|
||||
"系统不支持系统托盘功能, 无法创建系统托盘图标。"
|
||||
)
|
||||
return
|
||||
self.TrayIcon = QSystemTrayIcon(self.icon, self)
|
||||
self.TrayIcon.setToolTip("AutoLibrary")
|
||||
|
||||
self.TrayMenu = QMenu()
|
||||
self.TrayMenu.addAction("显示主窗口", self.showNormal)
|
||||
self.TrayMenu.addAction("显示定时窗口", self.onTimerTaskWidgetButtonClicked)
|
||||
self.TrayMenu.addAction("最小化到托盘", self.hideToTray)
|
||||
self.TrayMenu.addSeparator()
|
||||
self.TrayMenu.addAction("退出", self.close)
|
||||
self.TrayIcon.setContextMenu(self.TrayMenu)
|
||||
|
||||
self.TrayIcon.setContextMenu(self.TrayMenu)
|
||||
self.TrayIcon.activated.connect(self.onTrayIconActivated)
|
||||
self.TrayIcon.show()
|
||||
|
||||
|
||||
def hideToTray(
|
||||
self
|
||||
):
|
||||
|
||||
self.hide()
|
||||
self.TrayIcon.showMessage(
|
||||
"AutoLibrary",
|
||||
"\n已最小化到托盘",
|
||||
QSystemTrayIcon.MessageIcon.Information,
|
||||
2000
|
||||
)
|
||||
|
||||
|
||||
def onTrayIconActivated(
|
||||
self,
|
||||
reason: QSystemTrayIcon.ActivationReason
|
||||
):
|
||||
|
||||
if reason == QSystemTrayIcon.DoubleClick:
|
||||
self.showNormal()
|
||||
|
||||
|
||||
def connectSignals(
|
||||
@@ -157,6 +262,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
||||
):
|
||||
|
||||
self.ConfigButton.clicked.connect(self.onConfigButtonClicked)
|
||||
self.TimerTaskWidgetButton.clicked.connect(self.onTimerTaskWidgetButtonClicked)
|
||||
self.StartButton.clicked.connect(self.onStartButtonClicked)
|
||||
self.StopButton.clicked.connect(self.onStopButtonClicked)
|
||||
self.SendButton.clicked.connect(self.onSendButtonClicked)
|
||||
@@ -170,8 +276,17 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
||||
|
||||
if self.__timer and self.__timer.isActive():
|
||||
self.__timer.stop()
|
||||
if self.__timer_task_timer and self.__timer_task_timer.isActive():
|
||||
self.__timer_task_timer.stop()
|
||||
if self.__is_running_timer_task:
|
||||
self.__current_timer_task_thread.wait(2000)
|
||||
self.__current_timer_task_thread.deleteLater()
|
||||
if self.__alTimerTaskWidget:
|
||||
self.__alTimerTaskWidget.close()
|
||||
self.__alTimerTaskWidget.deleteLater()
|
||||
if self.__alConfigWidget:
|
||||
self.__alConfigWidget.close()
|
||||
self.__alConfigWidget.deleteLater()
|
||||
super().closeEvent(event)
|
||||
|
||||
|
||||
@@ -198,6 +313,51 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
||||
self.__timer.start(100)
|
||||
|
||||
|
||||
def startTimerTaskPolling(
|
||||
self
|
||||
):
|
||||
|
||||
self.__timer_task_timer = QTimer()
|
||||
self.__timer_task_timer.timeout.connect(self.pollTimerTaskQueue)
|
||||
self.__timer_task_timer.start(500)
|
||||
|
||||
|
||||
def pollTimerTaskQueue(
|
||||
self
|
||||
):
|
||||
|
||||
if self.__is_running_timer_task:
|
||||
return
|
||||
try:
|
||||
while not self.__is_running_timer_task:
|
||||
timer_task = self.__timer_task_queue.get_nowait()
|
||||
self.timerTaskIsRunning.emit(timer_task)
|
||||
self.__timer_task_timer.stop()
|
||||
self.__is_running_timer_task = True
|
||||
self.setControlButtons(False, False, True)
|
||||
if not timer_task["silent"]:
|
||||
self.TrayIcon.showMessage(
|
||||
"定时任务 - AutoLibrary",
|
||||
f"\n已开始执行定时任务: \n{timer_task['name']}",
|
||||
QSystemTrayIcon.MessageIcon.Information,
|
||||
1000
|
||||
)
|
||||
self.showNormal()
|
||||
self.__current_timer_task_thread = TimerTaskWorker(
|
||||
timer_task,
|
||||
self.__input_queue,
|
||||
self.__output_queue,
|
||||
self.__config_paths
|
||||
)
|
||||
self.__current_timer_task_thread.finishedSignal_TimerWorker.connect(self.onTimerTaskFinished)
|
||||
self.__current_timer_task_thread.showTraceSignal.connect(self.showTrace)
|
||||
self.__current_timer_task_thread.showMsgSignal.connect(self.showMsg)
|
||||
self.__current_timer_task_thread.start()
|
||||
except queue.Empty:
|
||||
self.__is_running_timer_task = False
|
||||
pass
|
||||
|
||||
|
||||
def setControlButtons(
|
||||
self,
|
||||
config_button_enabled: bool,
|
||||
@@ -238,6 +398,15 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
||||
except queue.Empty:
|
||||
pass
|
||||
|
||||
|
||||
@Slot()
|
||||
def onTimerTaskWidgetClosed(
|
||||
self
|
||||
):
|
||||
|
||||
self.TimerTaskWidgetButton.setEnabled(True)
|
||||
|
||||
|
||||
@Slot(dict)
|
||||
def onConfigWidgetClosed(
|
||||
self,
|
||||
@@ -253,6 +422,55 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
||||
self.StopButton.setEnabled(False)
|
||||
self.__config_paths = config_paths
|
||||
|
||||
@Slot(dict)
|
||||
def onTimerTaskReady(
|
||||
self,
|
||||
timer_task: dict
|
||||
):
|
||||
|
||||
self.__timer_task_queue.put(timer_task)
|
||||
|
||||
@Slot(dict)
|
||||
def onTimerTaskFinished(
|
||||
self,
|
||||
timer_task: dict
|
||||
):
|
||||
|
||||
self.__current_timer_task_thread.wait(1000)
|
||||
self.__current_timer_task_thread.finishedSignal_TimerWorker.disconnect(self.onTimerTaskFinished)
|
||||
self.__current_timer_task_thread.showTraceSignal.disconnect(self.showTrace)
|
||||
self.__current_timer_task_thread.showMsgSignal.disconnect(self.showMsg)
|
||||
self.__current_timer_task_thread.deleteLater()
|
||||
self.__current_timer_task_thread = None
|
||||
self.setControlButtons(True, True, False)
|
||||
self.__is_running_timer_task = False
|
||||
self.__timer_task_timer.start(500)
|
||||
timer_task["executed"] = True
|
||||
self.TrayIcon.showMessage(
|
||||
"定时任务 - AutoLibrary",
|
||||
f"\n定时任务 '{timer_task['name']}' 执行完成",
|
||||
QSystemTrayIcon.MessageIcon.Information,
|
||||
1000
|
||||
)
|
||||
self.showTrace(f"定时任务 {timer_task['name']} 执行完成, uuid: {timer_task['task_uuid']}")
|
||||
self.timerTaskIsExecuted.emit(timer_task)
|
||||
|
||||
@Slot()
|
||||
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()
|
||||
self.TimerTaskWidgetButton.setEnabled(False)
|
||||
|
||||
@Slot()
|
||||
def onConfigButtonClicked(
|
||||
self
|
||||
@@ -281,7 +499,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
||||
self.__auto_lib_thread = AutoLibWorker(
|
||||
self.__input_queue,
|
||||
self.__output_queue,
|
||||
self.__config_paths,
|
||||
self.__config_paths
|
||||
)
|
||||
self.__auto_lib_thread.finishedSignal.connect(self.onStopButtonClicked)
|
||||
self.__auto_lib_thread.showMsgSignal.connect(self.showMsg)
|
||||
@@ -295,8 +513,7 @@ class ALMainWindow(QMainWindow, Ui_ALMainWindow):
|
||||
|
||||
if self.__auto_lib_thread:
|
||||
self.showTrace("正在停止操作......")
|
||||
self.__auto_lib_thread.stop()
|
||||
self.__auto_lib_thread.wait()
|
||||
self.__auto_lib_thread.wait(2000)
|
||||
self.showTrace("操作已停止")
|
||||
self.__auto_lib_thread.showMsgSignal.disconnect(self.showMsg)
|
||||
self.__auto_lib_thread.showTraceSignal.disconnect(self.showTrace)
|
||||
|
||||
+38
-2
@@ -50,11 +50,33 @@
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="TimerTaskWidgetButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-open-recent"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="ControlSpaceFrame">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1280</width>
|
||||
<width>1000</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@@ -237,6 +259,9 @@ font: 700 9pt "Microsoft YaHei UI";</string>
|
||||
<property name="text">
|
||||
<string>发送</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="document-send"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -245,7 +270,7 @@ font: 700 9pt "Microsoft YaHei UI";</string>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="MenuBar">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@@ -258,6 +283,17 @@ font: 700 9pt "Microsoft YaHei UI";</string>
|
||||
<property name="nativeMenuBar">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QMenu" name="HelpMenu">
|
||||
<property name="mouseTracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>帮助</string>
|
||||
</property>
|
||||
<addaction name="ManualAction"/>
|
||||
<addaction name="AboutAction"/>
|
||||
</widget>
|
||||
<addaction name="HelpMenu"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="StatusBar">
|
||||
<property name="enabled">
|
||||
|
||||
@@ -0,0 +1,313 @@
|
||||
# -*- 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 sys
|
||||
import time
|
||||
import queue
|
||||
|
||||
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
|
||||
)
|
||||
from PySide6.QtGui import (
|
||||
QCloseEvent
|
||||
)
|
||||
|
||||
from gui.Ui_ALTimerTaskWidget import Ui_ALTimerTaskWidget
|
||||
from gui.ALAddTimerTaskDialog import ALAddTimerTaskWidget, TimerTaskStatus
|
||||
|
||||
|
||||
class TimerTaskItemWidget(QWidget):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
parent = None,
|
||||
timer_task: dict = None
|
||||
):
|
||||
|
||||
super().__init__(parent)
|
||||
|
||||
self.__timer_task = timer_task
|
||||
self.modifyUi()
|
||||
|
||||
|
||||
def modifyUi(
|
||||
self
|
||||
):
|
||||
|
||||
self.ItemWidgetLayout = QHBoxLayout(self)
|
||||
self.ItemWidgetLayout.setSpacing(10)
|
||||
self.ItemWidgetLayout.setContentsMargins(10, 5, 10, 5)
|
||||
|
||||
self.TaskInfoLayout = QVBoxLayout()
|
||||
self.TaskInfoLayout.setSpacing(5)
|
||||
TaskNameLabel = QLabel(self.__timer_task["name"])
|
||||
TaskNameLabelFont = TaskNameLabel.font()
|
||||
TaskNameLabelFont.setBold(True)
|
||||
TaskNameLabel.setFont(TaskNameLabelFont)
|
||||
TaskNameLabel.setFixedHeight(25)
|
||||
self.TaskInfoLayout.addWidget(TaskNameLabel)
|
||||
|
||||
ExecuteTimeStr = self.__timer_task["execute_time"].strftime("%Y-%m-%d %H:%M:%S")
|
||||
ExecuteTimeLabel = QLabel(f"执行时间: {ExecuteTimeStr}")
|
||||
ExecuteTimeLabel.setStyleSheet("color: gray;")
|
||||
ExecuteTimeLabel.setFixedHeight(20)
|
||||
self.TaskInfoLayout.addWidget(ExecuteTimeLabel)
|
||||
|
||||
self.ItemWidgetLayout.addLayout(self.TaskInfoLayout)
|
||||
self.ItemWidgetLayout.addStretch()
|
||||
|
||||
match self.__timer_task["status"]:
|
||||
case TimerTaskStatus.PENDING:
|
||||
TaskStatusText = "等待中"
|
||||
TaskStatusColor = "#FF9800"
|
||||
case TimerTaskStatus.READY:
|
||||
TaskStatusText = "已就绪"
|
||||
TaskStatusColor = "#316BFF"
|
||||
case TimerTaskStatus.RUNNING:
|
||||
TaskStatusText = "执行中"
|
||||
TaskStatusColor = "#2294FF"
|
||||
case TimerTaskStatus.EXECUTED:
|
||||
TaskStatusText = "已执行"
|
||||
TaskStatusColor = "#4CAF50"
|
||||
case TimerTaskStatus.OUTDATED:
|
||||
TaskStatusText = "已过期"
|
||||
TaskStatusColor = "#FF5722"
|
||||
TaskStatusLabel = QLabel(TaskStatusText)
|
||||
TaskStatusLabel.setStyleSheet(f"""
|
||||
QLabel {{
|
||||
background-color: {TaskStatusColor};
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
}}
|
||||
""")
|
||||
TaskStatusLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
TaskStatusLabel.setFixedSize(80, 25)
|
||||
self.ItemWidgetLayout.addWidget(TaskStatusLabel)
|
||||
|
||||
TaskModeText = "静默" if self.__timer_task["silent"] else "显示"
|
||||
TaskModeColor = "#6325FF" if self.__timer_task["silent"] else "#2294FF"
|
||||
TaskModeLabel = QLabel(TaskModeText)
|
||||
TaskModeLabel.setStyleSheet(f"""
|
||||
QLabel {{
|
||||
background-color: {TaskModeColor};
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
}}
|
||||
""")
|
||||
TaskModeLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
TaskModeLabel.setFixedSize(60, 25)
|
||||
self.ItemWidgetLayout.addWidget(TaskModeLabel)
|
||||
|
||||
self.DeleteButton = QPushButton("删除")
|
||||
self.DeleteButton.setFixedSize(80, 25)
|
||||
self.ItemWidgetLayout.addWidget(self.DeleteButton)
|
||||
if self.__timer_task["status"] == TimerTaskStatus.READY\
|
||||
or self.__timer_task["status"] == TimerTaskStatus.RUNNING:
|
||||
self.DeleteButton.setEnabled(False)
|
||||
self.setFixedHeight(55)
|
||||
|
||||
|
||||
class ALTimerTaskWidget(QWidget, Ui_ALTimerTaskWidget):
|
||||
|
||||
timerTasksChanged = Signal(list)
|
||||
timerTaskReady = Signal(dict)
|
||||
timerTaskWidgetClosed = Signal()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
parent = None
|
||||
):
|
||||
|
||||
super().__init__(parent)
|
||||
|
||||
self.__timer_tasks = []
|
||||
self.__check_timer = None
|
||||
self.setupUi(self)
|
||||
self.connectSignals()
|
||||
self.setupTimer()
|
||||
|
||||
|
||||
def setupTimer(
|
||||
self
|
||||
):
|
||||
|
||||
self.__check_timer = QTimer(self)
|
||||
self.__check_timer.timeout.connect(self.checkTasks)
|
||||
self.__check_timer.start(500)
|
||||
|
||||
|
||||
def connectSignals(
|
||||
self
|
||||
):
|
||||
|
||||
self.AddTimerTaskButton.clicked.connect(self.addTask)
|
||||
self.ClearAllTimerTasksButton.clicked.connect(self.clearAllTasks)
|
||||
|
||||
|
||||
def closeEvent(
|
||||
self,
|
||||
event: QCloseEvent
|
||||
):
|
||||
|
||||
self.hide()
|
||||
self.timerTaskWidgetClosed.emit()
|
||||
event.ignore()
|
||||
|
||||
|
||||
def updateStat(
|
||||
self
|
||||
):
|
||||
|
||||
pending = 0
|
||||
in_queue = 0
|
||||
executed = 0
|
||||
total = len(self.__timer_tasks)
|
||||
for timer_task in self.__timer_tasks:
|
||||
if timer_task["status"] == TimerTaskStatus.PENDING:
|
||||
pending += 1
|
||||
elif timer_task["status"] == TimerTaskStatus.READY\
|
||||
or timer_task["status"] == TimerTaskStatus.RUNNING:
|
||||
in_queue += 1
|
||||
elif timer_task["status"] == TimerTaskStatus.EXECUTED:
|
||||
executed += 1
|
||||
self.TotalTaskLabel.setText(f"总任务:{total}")
|
||||
self.PendingTaskLabel.setText(f"待执行:{pending}")
|
||||
self.InQueueTaskLabel.setText(f"队列中:{in_queue}")
|
||||
self.ExecutedTaskLabel.setText(f"已执行:{executed}")
|
||||
|
||||
|
||||
def updateTimerTaskList(
|
||||
self
|
||||
):
|
||||
|
||||
self.TimerTasksListWidget.clear()
|
||||
self.__timer_tasks.sort(
|
||||
key = lambda x: x["execute_time"]
|
||||
)
|
||||
for timer_task in self.__timer_tasks:
|
||||
item = QListWidgetItem()
|
||||
item.setData(Qt.UserRole, timer_task)
|
||||
widget = TimerTaskItemWidget(self, timer_task)
|
||||
widget.DeleteButton.clicked.connect(
|
||||
lambda _, uuid = timer_task["task_uuid"]: self.deleteTask(uuid)
|
||||
)
|
||||
item.setSizeHint(widget.size())
|
||||
self.TimerTasksListWidget.addItem(item)
|
||||
self.TimerTasksListWidget.setItemWidget(item, widget)
|
||||
|
||||
|
||||
def addTask(
|
||||
self
|
||||
):
|
||||
|
||||
dialog = ALAddTimerTaskWidget(self)
|
||||
if dialog.exec() == QDialog.DialogCode.Accepted:
|
||||
timer_task = dialog.getTimerTask()
|
||||
self.__timer_tasks.append(timer_task)
|
||||
self.updateTimerTaskList()
|
||||
self.updateStat()
|
||||
|
||||
|
||||
def deleteTask(
|
||||
self,
|
||||
task_uuid: str
|
||||
):
|
||||
|
||||
self.__timer_tasks = [
|
||||
x for x in self.__timer_tasks
|
||||
if x["task_uuid"] != task_uuid
|
||||
]
|
||||
self.updateTimerTaskList()
|
||||
self.updateStat()
|
||||
|
||||
|
||||
def clearAllTasks(
|
||||
self
|
||||
):
|
||||
|
||||
if not self.__timer_tasks:
|
||||
return
|
||||
result = QMessageBox.question(
|
||||
self,
|
||||
"确认 - AutoLibrary",
|
||||
"是否要清除所有定时任务 ?",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
||||
)
|
||||
if result is QMessageBox.StandardButton.No:
|
||||
return
|
||||
in_queue_tasks = [
|
||||
x for x in self.__timer_tasks
|
||||
if x["status"] == TimerTaskStatus.READY
|
||||
or x["status"] == TimerTaskStatus.RUNNING
|
||||
]
|
||||
in_queue_count = len(in_queue_tasks)
|
||||
if in_queue_count > 0:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"警告 - AutoLibrary",
|
||||
"存在正在执行或已就绪的队列任务,无法清除所有定时任务 !"
|
||||
)
|
||||
self.__timer_tasks = in_queue_tasks
|
||||
self.updateTimerTaskList()
|
||||
self.updateStat()
|
||||
|
||||
|
||||
def checkTasks(
|
||||
self
|
||||
):
|
||||
|
||||
now = datetime.now()
|
||||
for timer_task in self.__timer_tasks:
|
||||
if timer_task["execute_time"] > now:
|
||||
continue
|
||||
if timer_task["status"] is not TimerTaskStatus.PENDING:
|
||||
continue
|
||||
if timer_task["execute_time"] <= now + timedelta(seconds = -5):
|
||||
timer_task["status"] = TimerTaskStatus.OUTDATED
|
||||
else:
|
||||
timer_task["status"] = TimerTaskStatus.READY
|
||||
self.timerTaskReady.emit(timer_task)
|
||||
self.updateTimerTaskList()
|
||||
self.updateStat()
|
||||
|
||||
|
||||
@Slot(dict)
|
||||
def onTimerTaskIsRunning(
|
||||
self,
|
||||
timer_task: dict
|
||||
):
|
||||
|
||||
for task in self.__timer_tasks:
|
||||
if task["task_uuid"] == timer_task["task_uuid"]:
|
||||
task["status"] = TimerTaskStatus.RUNNING
|
||||
self.updateTimerTaskList()
|
||||
self.updateStat()
|
||||
|
||||
|
||||
@Slot(dict)
|
||||
def onTimerTaskIsExecuted(
|
||||
self,
|
||||
timer_task: dict
|
||||
):
|
||||
|
||||
for task in self.__timer_tasks:
|
||||
if task["task_uuid"] == timer_task["task_uuid"]:
|
||||
task["status"] = TimerTaskStatus.EXECUTED
|
||||
self.updateTimerTaskList()
|
||||
self.updateStat()
|
||||
@@ -0,0 +1,239 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ALTimerTaskWidget</class>
|
||||
<widget class="QWidget" name="ALTimerTaskWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>定时任务 - AutoLibrary</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="ALTimerTaskWidgetLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="TimerTaskStatusLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="TotalTaskLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>总任务:0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="PendingTaskLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel {
|
||||
color: #FF9800
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>待执行:0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="InQueueTaskLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel {
|
||||
color: #2294FF
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>队列中:0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="ExecutedTaskLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel {
|
||||
color: #4CAF50
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>已执行:0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="TimerTaskSpaceFrame">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="TimerTasksListWidget">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="TimerTaskEditLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ClearAllTimerTasksButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>清除全部</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="AddTimerTaskButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>添加任务</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="TimerTaskEditSpaceFrame">
|
||||
<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>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1 @@
|
||||
AL_VERSION = "1.0.0-beta"
|
||||
@@ -28,9 +28,9 @@ class SeatFrame(QFrame):
|
||||
super().__init__(parent)
|
||||
self.__seat_number = seat_number
|
||||
self.__is_selected = False
|
||||
self.setUpUi()
|
||||
self.setupUi()
|
||||
|
||||
def setUpUi(
|
||||
def setupUi(
|
||||
self
|
||||
):
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class SeatMapWidget(QWidget):
|
||||
self.__seats_data = seats_data
|
||||
self.__selected_seats = []
|
||||
self.__seat_frames = {}
|
||||
self.setUpUi()
|
||||
self.setupUi()
|
||||
self.connectSignals()
|
||||
|
||||
@staticmethod
|
||||
@@ -55,7 +55,7 @@ class SeatMapWidget(QWidget):
|
||||
return seat_number.zfill(3)
|
||||
|
||||
|
||||
def setUpUi(
|
||||
def setupUi(
|
||||
self
|
||||
):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user