mirror of
https://github.com/goldenfishs/MRobot.git
synced 2025-08-01 21:29:01 +08:00
修改了
This commit is contained in:
parent
08193b8093
commit
88ec1517fb
@ -1,11 +1,12 @@
|
|||||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QStackedLayout, QFileDialog, QHeaderView
|
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QStackedLayout, QFileDialog, QHeaderView
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtWidgets import QTreeWidgetItem as TreeItem
|
from PyQt5.QtWidgets import QTreeWidgetItem as TreeItem
|
||||||
from qfluentwidgets import TitleLabel, BodyLabel, SubtitleLabel, StrongBodyLabel, HorizontalSeparator, PushButton, TreeWidget, InfoBar,FluentIcon, Dialog
|
from qfluentwidgets import TitleLabel, BodyLabel, SubtitleLabel, StrongBodyLabel, HorizontalSeparator, PushButton, TreeWidget, InfoBar,FluentIcon, Dialog,SubtitleLabel,BodyLabel
|
||||||
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QSpinBox, QPushButton, QTableWidget, QTableWidgetItem, QHeaderView, QCheckBox
|
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QSpinBox, QPushButton, QTableWidget, QTableWidgetItem, QHeaderView, QCheckBox
|
||||||
from qfluentwidgets import CardWidget, LineEdit, SpinBox, CheckBox, TextEdit, PrimaryPushButton, PushButton, InfoBar
|
from qfluentwidgets import CardWidget, LineEdit, SpinBox, CheckBox, TextEdit, PrimaryPushButton, PushButton, InfoBar
|
||||||
from qfluentwidgets import HeaderCardWidget
|
from qfluentwidgets import HeaderCardWidget
|
||||||
from PyQt5.QtWidgets import QScrollArea, QWidget
|
from PyQt5.QtWidgets import QScrollArea, QWidget
|
||||||
|
from qfluentwidgets import theme, Theme
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
@ -686,30 +687,39 @@ class DataInterface(QWidget):
|
|||||||
yaml.safe_dump(task_list, f, allow_unicode=True)
|
yaml.safe_dump(task_list, f, allow_unicode=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TaskConfigDialog(QDialog):
|
class TaskConfigDialog(QDialog):
|
||||||
def __init__(self, parent=None, config_path=None):
|
def __init__(self, parent=None, config_path=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setWindowTitle("任务配置")
|
self.setWindowTitle("任务配置")
|
||||||
self.resize(900, 520)
|
self.resize(900, 520)
|
||||||
|
|
||||||
|
# 设置背景色跟随主题
|
||||||
|
if theme() == Theme.DARK:
|
||||||
|
self.setStyleSheet("background-color: #232323;")
|
||||||
|
else:
|
||||||
|
self.setStyleSheet("background-color: #faf9f8;")
|
||||||
|
|
||||||
|
|
||||||
# 主布局
|
# 主布局
|
||||||
main_layout = QVBoxLayout(self)
|
main_layout = QVBoxLayout(self)
|
||||||
main_layout.setContentsMargins(16, 16, 16, 16)
|
main_layout.setContentsMargins(16, 16, 16, 16)
|
||||||
main_layout.setSpacing(12)
|
main_layout.setSpacing(12)
|
||||||
|
|
||||||
# 顶部横向分栏
|
# 顶部横向分栏
|
||||||
self.top_layout = QHBoxLayout() # 注意:改为 self.top_layout
|
self.top_layout = QHBoxLayout()
|
||||||
self.top_layout.setSpacing(16)
|
self.top_layout.setSpacing(16)
|
||||||
|
|
||||||
# 左侧:任务列表(按钮)
|
# ----------- 左侧任务按钮区 -----------
|
||||||
left_widget = QWidget()
|
self.left_widget = QWidget()
|
||||||
left_vbox = QVBoxLayout(left_widget)
|
self.left_layout = QVBoxLayout(self.left_widget)
|
||||||
left_vbox.setContentsMargins(0, 0, 0, 0)
|
self.left_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
left_vbox.setSpacing(8)
|
self.left_layout.setSpacing(8)
|
||||||
|
|
||||||
self.add_btn = PrimaryPushButton("添加任务")
|
self.add_btn = PrimaryPushButton("添加任务")
|
||||||
self.add_btn.clicked.connect(self.add_task)
|
self.add_btn.clicked.connect(self.add_task)
|
||||||
left_vbox.addWidget(self.add_btn)
|
self.left_layout.addWidget(self.add_btn)
|
||||||
|
|
||||||
self.task_btn_area = QScrollArea()
|
self.task_btn_area = QScrollArea()
|
||||||
self.task_btn_area.setWidgetResizable(True)
|
self.task_btn_area.setWidgetResizable(True)
|
||||||
@ -720,10 +730,11 @@ class TaskConfigDialog(QDialog):
|
|||||||
self.task_btn_layout.setSpacing(4)
|
self.task_btn_layout.setSpacing(4)
|
||||||
self.task_btn_layout.addStretch()
|
self.task_btn_layout.addStretch()
|
||||||
self.task_btn_area.setWidget(self.task_btn_container)
|
self.task_btn_area.setWidget(self.task_btn_container)
|
||||||
left_vbox.addWidget(self.task_btn_area, stretch=1)
|
self.left_layout.addWidget(self.task_btn_area, stretch=1)
|
||||||
|
|
||||||
left_widget.setFixedWidth(220)
|
self.left_widget.setFixedWidth(180)
|
||||||
self.top_layout.addWidget(left_widget, stretch=0)
|
self.top_layout.addWidget(self.left_widget, stretch=0)
|
||||||
|
# ----------- 左侧任务按钮区 END -----------
|
||||||
|
|
||||||
main_layout.addLayout(self.top_layout, stretch=1)
|
main_layout.addLayout(self.top_layout, stretch=1)
|
||||||
|
|
||||||
@ -753,8 +764,66 @@ class TaskConfigDialog(QDialog):
|
|||||||
pass
|
pass
|
||||||
if not self.tasks:
|
if not self.tasks:
|
||||||
self.tasks.append(self._make_task_obj())
|
self.tasks.append(self._make_task_obj())
|
||||||
|
self.current_index = 0
|
||||||
self.refresh_task_btns()
|
self.refresh_task_btns()
|
||||||
self.select_task(0)
|
self.show_task_form(self.tasks[0])
|
||||||
|
|
||||||
|
def refresh_task_btns(self):
|
||||||
|
# 清空旧按钮
|
||||||
|
while self.task_btn_layout.count():
|
||||||
|
item = self.task_btn_layout.takeAt(0)
|
||||||
|
w = item.widget()
|
||||||
|
if w:
|
||||||
|
w.deleteLater()
|
||||||
|
# 重新添加按钮
|
||||||
|
for idx, t in enumerate(self.tasks):
|
||||||
|
btn = PushButton(t["name"])
|
||||||
|
btn.setCheckable(True)
|
||||||
|
btn.setChecked(idx == self.current_index)
|
||||||
|
btn.clicked.connect(lambda checked, i=idx: self.select_task(i))
|
||||||
|
self.task_btn_layout.addWidget(btn)
|
||||||
|
# 删除按钮
|
||||||
|
del_btn = PushButton("删除")
|
||||||
|
del_btn.setFixedWidth(48)
|
||||||
|
del_btn.clicked.connect(lambda _, i=idx: self.delete_task(i))
|
||||||
|
hbox = QHBoxLayout()
|
||||||
|
hbox.addWidget(btn)
|
||||||
|
hbox.addWidget(del_btn)
|
||||||
|
hbox.setContentsMargins(0, 0, 0, 0)
|
||||||
|
hbox.setSpacing(4)
|
||||||
|
container = QWidget()
|
||||||
|
container.setLayout(hbox)
|
||||||
|
self.task_btn_layout.addWidget(container)
|
||||||
|
self.task_btn_layout.addStretch()
|
||||||
|
|
||||||
|
def add_task(self):
|
||||||
|
self.save_form()
|
||||||
|
new_idx = len(self.tasks)
|
||||||
|
self.tasks.append(self._make_task_obj({"name": f"Task{new_idx+1}"}))
|
||||||
|
self.current_index = new_idx
|
||||||
|
self.refresh_task_btns()
|
||||||
|
self.show_task_form(self.tasks[self.current_index])
|
||||||
|
|
||||||
|
def delete_task(self, idx):
|
||||||
|
if len(self.tasks) <= 1:
|
||||||
|
InfoBar.warning(
|
||||||
|
title="至少保留一个任务",
|
||||||
|
content="至少需要保留一个任务!",
|
||||||
|
parent=self,
|
||||||
|
duration=2000
|
||||||
|
)
|
||||||
|
return
|
||||||
|
del self.tasks[idx]
|
||||||
|
if self.current_index >= len(self.tasks):
|
||||||
|
self.current_index = len(self.tasks) - 1
|
||||||
|
self.refresh_task_btns()
|
||||||
|
self.show_task_form(self.tasks[self.current_index])
|
||||||
|
|
||||||
|
def select_task(self, idx):
|
||||||
|
self.save_form()
|
||||||
|
self.current_index = idx
|
||||||
|
self.refresh_task_btns()
|
||||||
|
self.show_task_form(self.tasks[idx])
|
||||||
|
|
||||||
def show_task_form(self, task):
|
def show_task_form(self, task):
|
||||||
# 先移除旧的 form_widget
|
# 先移除旧的 form_widget
|
||||||
@ -773,7 +842,7 @@ class TaskConfigDialog(QDialog):
|
|||||||
self.top_layout.addWidget(self.form_widget, stretch=1)
|
self.top_layout.addWidget(self.form_widget, stretch=1)
|
||||||
|
|
||||||
if not task:
|
if not task:
|
||||||
label = QLabel("选择左侧任务。")
|
label = BodyLabel("未找到任务。")
|
||||||
label.setAlignment(Qt.AlignCenter)
|
label.setAlignment(Qt.AlignCenter)
|
||||||
self.form_layout.addWidget(label)
|
self.form_layout.addWidget(label)
|
||||||
self.form_layout.addStretch()
|
self.form_layout.addStretch()
|
||||||
@ -781,7 +850,7 @@ class TaskConfigDialog(QDialog):
|
|||||||
|
|
||||||
# 任务名称
|
# 任务名称
|
||||||
row1 = QHBoxLayout()
|
row1 = QHBoxLayout()
|
||||||
label_name = QLabel("任务名称")
|
label_name = BodyLabel("任务名称")
|
||||||
self.name_edit = LineEdit()
|
self.name_edit = LineEdit()
|
||||||
self.name_edit.setText(task["name"])
|
self.name_edit.setText(task["name"])
|
||||||
self.name_edit.setPlaceholderText("任务名称")
|
self.name_edit.setPlaceholderText("任务名称")
|
||||||
@ -791,7 +860,7 @@ class TaskConfigDialog(QDialog):
|
|||||||
|
|
||||||
# 频率
|
# 频率
|
||||||
row2 = QHBoxLayout()
|
row2 = QHBoxLayout()
|
||||||
label_freq = QLabel("频率")
|
label_freq = BodyLabel("频率")
|
||||||
self.freq_spin = SpinBox()
|
self.freq_spin = SpinBox()
|
||||||
self.freq_spin.setRange(1, 10000)
|
self.freq_spin.setRange(1, 10000)
|
||||||
self.freq_spin.setSuffix(" Hz")
|
self.freq_spin.setSuffix(" Hz")
|
||||||
@ -802,7 +871,7 @@ class TaskConfigDialog(QDialog):
|
|||||||
|
|
||||||
# 延迟
|
# 延迟
|
||||||
row3 = QHBoxLayout()
|
row3 = QHBoxLayout()
|
||||||
label_delay = QLabel("延迟")
|
label_delay = BodyLabel("延迟")
|
||||||
self.delay_spin = SpinBox()
|
self.delay_spin = SpinBox()
|
||||||
self.delay_spin.setRange(0, 10000)
|
self.delay_spin.setRange(0, 10000)
|
||||||
self.delay_spin.setSuffix(" ms")
|
self.delay_spin.setSuffix(" ms")
|
||||||
@ -813,7 +882,7 @@ class TaskConfigDialog(QDialog):
|
|||||||
|
|
||||||
# 堆栈
|
# 堆栈
|
||||||
row4 = QHBoxLayout()
|
row4 = QHBoxLayout()
|
||||||
label_stack = QLabel("堆栈")
|
label_stack = BodyLabel("堆栈")
|
||||||
self.stack_spin = SpinBox()
|
self.stack_spin = SpinBox()
|
||||||
self.stack_spin.setRange(128, 8192)
|
self.stack_spin.setRange(128, 8192)
|
||||||
self.stack_spin.setSingleStep(128)
|
self.stack_spin.setSingleStep(128)
|
||||||
@ -830,7 +899,7 @@ class TaskConfigDialog(QDialog):
|
|||||||
self.form_layout.addLayout(row5)
|
self.form_layout.addLayout(row5)
|
||||||
|
|
||||||
# 描述
|
# 描述
|
||||||
label_desc = QLabel("任务描述")
|
label_desc = BodyLabel("任务描述")
|
||||||
self.desc_edit = TextEdit()
|
self.desc_edit = TextEdit()
|
||||||
self.desc_edit.setText(task.get("description", ""))
|
self.desc_edit.setText(task.get("description", ""))
|
||||||
self.desc_edit.setPlaceholderText("任务描述")
|
self.desc_edit.setPlaceholderText("任务描述")
|
||||||
@ -839,11 +908,9 @@ class TaskConfigDialog(QDialog):
|
|||||||
|
|
||||||
self.form_layout.addStretch()
|
self.form_layout.addStretch()
|
||||||
|
|
||||||
|
|
||||||
def _make_task_obj(self, task=None):
|
def _make_task_obj(self, task=None):
|
||||||
# 生成一个任务数据结构
|
|
||||||
return {
|
return {
|
||||||
"name": task["name"] if task else f"Task{len(self.tasks)+1}",
|
"name": task["name"] if task else f"Task1",
|
||||||
"frequency": task.get("frequency", 500) if task else 500,
|
"frequency": task.get("frequency", 500) if task else 500,
|
||||||
"delay": task.get("delay", 0) if task else 0,
|
"delay": task.get("delay", 0) if task else 0,
|
||||||
"stack": task.get("stack", 256) if task else 256,
|
"stack": task.get("stack", 256) if task else 256,
|
||||||
@ -851,66 +918,7 @@ class TaskConfigDialog(QDialog):
|
|||||||
"freq_control": task.get("freq_control", True) if task else True,
|
"freq_control": task.get("freq_control", True) if task else True,
|
||||||
}
|
}
|
||||||
|
|
||||||
def refresh_task_btns(self):
|
|
||||||
# 清空所有控件和stretch
|
|
||||||
while self.task_btn_layout.count():
|
|
||||||
item = self.task_btn_layout.takeAt(0)
|
|
||||||
widget = item.widget()
|
|
||||||
if widget is not None:
|
|
||||||
widget.deleteLater()
|
|
||||||
else:
|
|
||||||
# 是 QSpacerItem 也要删除
|
|
||||||
del item
|
|
||||||
|
|
||||||
# 重新添加任务按钮
|
|
||||||
for idx, t in enumerate(self.tasks):
|
|
||||||
row = QWidget()
|
|
||||||
hbox = QHBoxLayout(row)
|
|
||||||
hbox.setContentsMargins(0, 0, 0, 0)
|
|
||||||
hbox.setSpacing(4)
|
|
||||||
btn = PushButton(t["name"])
|
|
||||||
btn.setCheckable(True)
|
|
||||||
btn.setChecked(idx == self.current_index)
|
|
||||||
btn.clicked.connect(lambda _, i=idx: self.select_task(i))
|
|
||||||
hbox.addWidget(btn, stretch=1)
|
|
||||||
row.setLayout(hbox)
|
|
||||||
self.task_btn_layout.addWidget(row)
|
|
||||||
self.task_btn_layout.addStretch()
|
|
||||||
|
|
||||||
def select_task(self, idx):
|
|
||||||
if idx < 0 or idx >= len(self.tasks):
|
|
||||||
# 没有可选任务时,右侧显示提示
|
|
||||||
self.show_task_form(None)
|
|
||||||
return
|
|
||||||
# 保存当前表单内容
|
|
||||||
self.save_form()
|
|
||||||
self.current_index = idx
|
|
||||||
self.refresh_task_btns()
|
|
||||||
self.show_task_form(self.tasks[idx])
|
|
||||||
|
|
||||||
def add_task(self):
|
|
||||||
self.save_form()
|
|
||||||
self.tasks.append(self._make_task_obj())
|
|
||||||
self.refresh_task_btns()
|
|
||||||
self.select_task(len(self.tasks) - 1)
|
|
||||||
|
|
||||||
def delete_task(self, idx):
|
|
||||||
if len(self.tasks) <= 1:
|
|
||||||
return # 至少保留一个
|
|
||||||
if idx == self.current_index:
|
|
||||||
# 删除当前,切换到前一个
|
|
||||||
self.tasks.pop(idx)
|
|
||||||
self.current_index = max(0, idx - 1)
|
|
||||||
else:
|
|
||||||
self.tasks.pop(idx)
|
|
||||||
if self.current_index > idx:
|
|
||||||
self.current_index -= 1
|
|
||||||
self.refresh_task_btns()
|
|
||||||
self.select_task(self.current_index)
|
|
||||||
|
|
||||||
|
|
||||||
def save_form(self):
|
def save_form(self):
|
||||||
# 保存当前表单内容到 self.tasks[self.current_index]
|
|
||||||
if self.current_index < 0 or self.current_index >= len(self.tasks):
|
if self.current_index < 0 or self.current_index >= len(self.tasks):
|
||||||
return
|
return
|
||||||
t = self.tasks[self.current_index]
|
t = self.tasks[self.current_index]
|
||||||
@ -931,7 +939,6 @@ class TaskConfigDialog(QDialog):
|
|||||||
stack = t["stack"]
|
stack = t["stack"]
|
||||||
desc = t["description"].strip()
|
desc = t["description"].strip()
|
||||||
freq_ctrl = t["freq_control"]
|
freq_ctrl = t["freq_control"]
|
||||||
# 校验 stack 必须为 128*2^n
|
|
||||||
if stack < 128 or (stack & (stack - 1)) != 0 or stack % 128 != 0:
|
if stack < 128 or (stack & (stack - 1)) != 0 or stack % 128 != 0:
|
||||||
raise ValueError(f"第{idx+1}个任务“{name}”的堆栈大小必须为128、256、512、1024等(128*2^n)")
|
raise ValueError(f"第{idx+1}个任务“{name}”的堆栈大小必须为128、256、512、1024等(128*2^n)")
|
||||||
task = {
|
task = {
|
||||||
|
Loading…
Reference in New Issue
Block a user