You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
10 KiB
281 lines
10 KiB
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QListWidget, QPushButton, QHBoxLayout, QLineEdit,
|
|
QMessageBox, QMenu, QAction, QTableWidget, QAbstractItemView)
|
|
from utils.globals import get_serial_manager
|
|
from utils.logger import logger
|
|
from utils.config_manager import ConfigManager
|
|
from PyQt5.QtCore import Qt
|
|
|
|
class PresetPanel(QWidget):
|
|
def __init__(self, preset_manager, screen_manager, parent=None):
|
|
super().__init__(parent)
|
|
self.preset_manager = preset_manager
|
|
self.screen_manager = screen_manager # 用来获取当前选中或发送指令
|
|
self.init_ui()
|
|
|
|
# --- 新增:实例化配置管理器 ---
|
|
self.config_manager = ConfigManager()
|
|
|
|
# --- 新增:初始化时尝试加载配置 ---
|
|
self.load_presets_from_disk()
|
|
|
|
def init_ui(self):
|
|
layout = QVBoxLayout()
|
|
|
|
# 名称输入和保存按钮
|
|
top_layout = QHBoxLayout()
|
|
self.name_input = QLineEdit()
|
|
self.name_input.setPlaceholderText("输入预案名称")
|
|
save_btn = QPushButton("保存当前布局")
|
|
save_btn.clicked.connect(self.on_save)
|
|
|
|
top_layout.addWidget(self.name_input)
|
|
top_layout.addWidget(save_btn)
|
|
|
|
# 预案列表
|
|
self.list_widget = QListWidget()
|
|
self.list_widget.addItems(self.preset_manager.presets.keys())
|
|
self.list_widget.itemDoubleClicked.connect(self.on_call) # 双击调用
|
|
|
|
# 操作按钮
|
|
btn_layout = QHBoxLayout()
|
|
call_btn = QPushButton("调用")
|
|
del_btn = QPushButton("删除")
|
|
call_btn.clicked.connect(self.on_call)
|
|
del_btn.clicked.connect(self.on_delete)
|
|
|
|
btn_layout.addWidget(call_btn)
|
|
btn_layout.addWidget(del_btn)
|
|
|
|
layout.addLayout(top_layout)
|
|
layout.addWidget(self.list_widget)
|
|
layout.addLayout(btn_layout)
|
|
|
|
self.setLayout(layout)
|
|
|
|
# 1. 先创建表格对象
|
|
self.table_widget = QTableWidget(4, 4) # 请替换为你实际的行列数
|
|
self.table_widget.setWindowTitle("分屏布局")
|
|
|
|
# 2. 设置表格属性(现在的 self.table_widget 已经存在了)
|
|
self.table_widget.setContextMenuPolicy(Qt.CustomContextMenu)
|
|
self.table_widget.customContextMenuRequested.connect(self.open_context_menu)
|
|
|
|
# 3. 设置选择模式 (之前提到的多选功能)
|
|
self.table_widget.setSelectionMode(QAbstractItemView.ExtendedSelection)
|
|
|
|
# 4. 将表格加入布局
|
|
main_layout = QVBoxLayout()
|
|
main_layout.addWidget(self.table_widget)
|
|
self.setLayout(main_layout)
|
|
|
|
# 1. 设置表格的右键菜单策略
|
|
self.table_widget.setContextMenuPolicy(Qt.CustomContextMenu)
|
|
|
|
# 2. 连接信号
|
|
self.table_widget.customContextMenuRequested.connect(self.open_context_menu)
|
|
|
|
def on_save(self):
|
|
name = self.name_input.text()
|
|
if not name:
|
|
return
|
|
|
|
# 获取当前的布局参数 (这里需要你从 screen_manager 或当前选中状态获取)
|
|
# 假设 get_current_layout_params() 是你封装好的方法
|
|
current_layouts = self.screen_manager.get_current_layout_params()
|
|
|
|
self.preset_manager.save_preset(name, current_layouts)
|
|
self.list_widget.addItem(name) # 刷新界面
|
|
print(f"预案 {name} 保存成功")
|
|
|
|
def on_call(self):
|
|
try:
|
|
serial_manager = get_serial_manager()
|
|
|
|
if serial_manager.is_connected:
|
|
# 发送指令...
|
|
current_item = self.list_widget.currentItem()
|
|
if current_item:
|
|
preset_name = current_item.text()
|
|
preset_data = self.preset_manager.get_preset(preset_name)
|
|
|
|
if preset_data and 'layouts' in preset_data:
|
|
for layout in preset_data['layouts']:
|
|
# 确保参数完整
|
|
self.screen_manager.send_mosaic_command(
|
|
start=layout.get('start', 0),
|
|
hcount=layout.get('hcount', 1),
|
|
vcount=layout.get('vcount', 1)
|
|
)
|
|
else:
|
|
logger.warning("没连上,别发")
|
|
except Exception as e:
|
|
print(f"调用预案时出错: {e}")
|
|
|
|
def on_delete(self):
|
|
"""
|
|
处理删除预案的逻辑
|
|
"""
|
|
# 1. 获取当前选中的列表项
|
|
current_item = self.list_widget.currentItem()
|
|
|
|
if current_item:
|
|
# 2. 获取预案名称
|
|
preset_name = current_item.text()
|
|
|
|
# 3. 从列表控件中移除
|
|
self.list_widget.takeItem(self.list_widget.row(current_item))
|
|
|
|
# 4. 从数据管理器中删除
|
|
if preset_name in self.preset_manager.presets:
|
|
del self.preset_manager.presets[preset_name]
|
|
self.preset_manager.save_to_file() # 立即保存到文件
|
|
|
|
print(f"预案 {preset_name} 已删除")
|
|
|
|
def save_presets_to_disk(self):
|
|
"""
|
|
将当前界面的预案保存到磁盘
|
|
"""
|
|
name = self.name_input.text()
|
|
if not name:
|
|
return
|
|
# 1. 准备数据:遍历所有按钮,把它们的参数抓出来
|
|
preset_list = []
|
|
|
|
current_layouts = self.screen_manager.get_current_layout_params()
|
|
|
|
self.preset_manager.save_preset(name, current_layouts)
|
|
self.list_widget.addItem(name) # 刷新界面
|
|
|
|
current_item = self.list_widget.currentItem()
|
|
|
|
print(current_item)
|
|
if current_item:
|
|
preset_name = current_item.text()
|
|
preset_data = self.preset_manager.get_preset(preset_name)
|
|
|
|
print(preset_data)
|
|
|
|
if preset_data and 'layouts' in preset_data:
|
|
for layout in preset_data['layouts']:
|
|
preset_data = {
|
|
"name": preset_name,
|
|
"start": layout.start_idx, # 假设你存了
|
|
"hcount": layout.h_count,
|
|
"vcount": layout.v_count
|
|
}
|
|
# 这里需要根据你实际存储参数的方式修改
|
|
# 比如:我之前把参数存到了按钮的属性里
|
|
preset_list.append(preset_data)
|
|
|
|
# 2. 交给管家保存
|
|
if self.config_manager.save_presets(preset_list):
|
|
logger.info("💾 预案保存成功")
|
|
else:
|
|
logger.error("💾 预案保存失败")
|
|
|
|
def load_presets_from_disk(self):
|
|
"""
|
|
从磁盘加载预案,并重建按钮
|
|
"""
|
|
# 1. 从硬盘读数据
|
|
preset_data_list = self.config_manager.load_presets()
|
|
|
|
if not preset_data_list:
|
|
logger.info("📭 没有找到历史预案,开始新工作")
|
|
return
|
|
|
|
# 2. 遍历数据,重建按钮
|
|
logger.info(f"📂 正在加载 {len(preset_data_list)} 个预案...")
|
|
|
|
for data in preset_data_list:
|
|
# 调用你创建按钮的函数
|
|
# 假设你有一个 create_button(name, start, h, v) 函数
|
|
self.create_button(
|
|
name=data["name"],
|
|
start=data["start"],
|
|
hcount=data["hcount"],
|
|
vcount=data["vcount"]
|
|
)
|
|
|
|
# 假设你在 init_ui 里有一个保存按钮 self.btnSave
|
|
def on_save_clicked(self):
|
|
"""
|
|
当用户点击保存按钮时
|
|
"""
|
|
self.save_presets_to_disk()
|
|
QMessageBox.information(self, "成功", "当前的预案布局已保存!")
|
|
|
|
# -------------------------------
|
|
# 右键菜单核心逻辑
|
|
# -------------------------------
|
|
def open_context_menu(self, pos):
|
|
"""
|
|
打开右键菜单
|
|
:param pos: 鼠标位置 (QPoint)
|
|
"""
|
|
# 获取选中的单元格
|
|
selected_items = self.table_widget.selectedItems()
|
|
if not selected_items:
|
|
return
|
|
|
|
# 创建菜单
|
|
menu = QMenu(self)
|
|
|
|
# --- 获取实际的信号列表 ---
|
|
# 这里去问 manager 要数据
|
|
sources = self.preset_manager.get_source_list()
|
|
|
|
if not sources:
|
|
# 防止列表为空时难看
|
|
no_action = QAction("暂无信号源", self)
|
|
no_action.setEnabled(False)
|
|
menu.addAction(no_action)
|
|
else:
|
|
# 遍历实际的信号列表,创建菜单项
|
|
for source in sources:
|
|
action = QAction(source, self)
|
|
# 绑定点击事件,传入参数 source
|
|
action.triggered.connect(lambda checked, s=source: self.handle_source_selected(s, selected_items))
|
|
menu.addAction(action)
|
|
|
|
# 在鼠标位置显示菜单
|
|
# 注意:pos 是相对于表格的坐标,需要转成全局坐标
|
|
menu.exec_(self.table_widget.mapToGlobal(pos))
|
|
|
|
# -------------------------------
|
|
# 菜单点击处理逻辑
|
|
# -------------------------------
|
|
def handle_source_selected(self, source_name, target_items):
|
|
"""
|
|
处理用户点击了某个信号源
|
|
"""
|
|
# 这里可以弹个确认框,或者直接执行
|
|
reply = QMessageBox.question(
|
|
self,
|
|
"确认",
|
|
f"确定将 {len(target_items)} 个分屏切换到 [{source_name}] 吗?",
|
|
QMessageBox.Yes | QMessageBox.No
|
|
)
|
|
|
|
if reply == QMessageBox.Yes:
|
|
# 执行批量切换逻辑
|
|
self.batch_update_layout(source_name, target_items)
|
|
|
|
def batch_update_layout(self, source_name, target_items):
|
|
"""
|
|
批量更新界面和数据
|
|
"""
|
|
for item in target_items:
|
|
row = item.row()
|
|
col = item.column()
|
|
|
|
# 1. 更新表格显示
|
|
item.setText(f"{source_name}\n({row},{col})")
|
|
item.setBackground(Qt.cyan) # 高亮显示
|
|
|
|
# 2. 这里可以更新你的内部数据结构
|
|
# 例如:self.current_layout.set_input(row, col, source_name)
|
|
|
|
# 3. 提示成功
|
|
self.statusBar().showMessage(f"已批量设置为 {source_name}", 2000)
|