# controller/bottom_control_controller.py from PySide6.QtCore import Qt, QPropertyAnimation, QRect, QParallelAnimationGroup, QEasingCurve, QPoint, Slot from view.widgets.system_center_dialog import SystemCenterDialog from view.widgets.bottom_control_widget import BottomControlWidget from view.widgets.system_diagnostics_dialog import SystemDiagnosticsDialog from view.widgets.message_popup_widget import MessagePopupWidget from service.msg_recorder import MessageRecorder from service.msg_query_thread import MsgQueryThread from service.device_monitor_thread import DeviceMonitorThread """ 控制主界面底部的所有按钮, 包括系统诊断、系统中心等的行为。 以及 版本信息相关弹窗, 如: v1.0 """ class BottomControlController: def __init__(self, bottom_control_widget:BottomControlWidget, main_window): self.bottom_control_widget = bottom_control_widget self.main_window = main_window # 系统诊断弹窗 self.system_diagnostics_dialog = SystemDiagnosticsDialog(self.main_window) self.current_diagnostics_row = 0 # 系统诊断弹窗的行号,从0开始 self.current_diagnostics_col = 0 # 系统诊断弹窗的列号,从0开始 # 系统中心弹窗 self.system_center_dialog = SystemCenterDialog(self.main_window) # ===================== 消息列表相关 ==================================== # 系统状态消息列表控件 self.status_msg_widget = MessagePopupWidget("系统状态消息", self.main_window) # 预警消息列表控件 self.warning_msg_widget = MessagePopupWidget("预警消息", self.main_window) # 消息数据库查询线程 self.msg_query_thread = MsgQueryThread() # 默认1秒查询一次,每次16条消息 # 连接线程信号到UI更新函数 self.msg_query_thread.new_messages.connect(self.update_message_ui, Qt.QueuedConnection) self.msg_query_thread.start() # 启动线程 # ======================================================================= # ===================== 设备检测(系统诊断相关) ==================================== self.device_monitor = DeviceMonitorThread() self.device_monitor.start() # ======================================================================= # 绑定主界面底部按钮的信号(如:系统诊断按钮等,点击触发弹窗) self._bind_buttons() # 绑定弹窗中按钮的信号 self._bind_dialog_signals() @Slot(int, list) def update_message_ui(self, message_type, messages): """根据消息类型更新对应UI, message_type为1表示系统状态消息, 为2表示预警消息""" # 清空当前消息列表(避免重复) target_widget = self.status_msg_widget if message_type == 1 else self.warning_msg_widget target_widget.list_widget.clear() # 添加新消息 (第三个为 create_time, 第四个为 last_modified) for content, is_processed, create_time, _ in messages: target_widget.add_message(content, is_processed = bool(is_processed), msg_time = create_time) def stop_threads(self): """停止当前控制器中的所有线程""" if hasattr(self, 'msg_query_thread') and self.msg_query_thread.isRunning(): self.msg_query_thread.stop() if hasattr(self, 'device_monitor') and self.device_monitor.isRunning(): self.device_monitor.stop_thread() def _bind_buttons(self): # 底部系统中心按钮 → 触发弹窗显示/隐藏 self.bottom_control_widget.center_btn.clicked.connect(self.toggle_system_center_dialog) # 底部系统诊断按钮 → 触发弹窗显示/隐藏 self.bottom_control_widget.diagnosis_btn.clicked.connect(self.toggle_system_diagnostics_dialog) # 底部系统状态消息按钮 → 触发系统状态消息列表显示/隐藏 self.bottom_control_widget.status_msg_btn.clicked.connect(self.toggle_system_status_msg_list) # 底部预警消息列表按钮 → 触发预警消息列表显示/隐藏 self.bottom_control_widget.warning_list_btn.clicked.connect(self.toggle_system_warning_msg_list) # 设备检测结果显示(底部的系统诊断按钮处显示) self.device_monitor.state_result.connect( self.bottom_control_widget.set_system_status, Qt.QueuedConnection) def _bind_dialog_signals(self): """绑定弹窗按钮的信号""" # 系统中心弹窗的按钮信号 self.system_center_dialog.sys_setting_clicked.connect(self.handle_sys_setting) self.system_center_dialog.data_center_clicked.connect(self.handle_data_center) self.system_center_dialog.user_center_clicked.connect(self.handle_user_center) # 系统诊断弹窗的信号 self.device_monitor.check_finished.connect(self.reset_diagnostics_row_col) # 重置系统诊断的行号和列号 self.device_monitor.connect_success.connect(self._handle_diagnostics_connect_success) # 设备正常 self.device_monitor.connect_failed.connect(self._handle_diagnostics_connect_failed) # 设备异常 # ------------------- 系统中心弹窗逻辑------------------- def toggle_system_center_dialog(self): """切换系统中心弹窗的显示/隐藏状态""" if self.system_center_dialog.isVisible(): # 已显示 → 隐藏 self.system_center_dialog.hide() else: # 未显示 → 计算位置并显示 self._calc_system_center_dialog_position() # 每次显示都计算位置 self.system_center_dialog.show() def _calc_system_center_dialog_position(self): """计算系统中心弹窗位置, 并move移动""" btn = self.bottom_control_widget.center_btn bottom_widget = self.bottom_control_widget # 计算按钮相对于主窗口的位置 bottom_pos_rel_main = bottom_widget.pos() btn_pos_rel_bottom = btn.pos() btn_pos_rel_main = bottom_pos_rel_main + btn_pos_rel_bottom # 计算弹窗坐标 btn_width = btn.width() dialog_size = self.system_center_dialog.size() dialog_x = btn_pos_rel_main.x() + (btn_width - dialog_size.width()) // 2 dialog_y = btn_pos_rel_main.y() - dialog_size.height() # 设置弹窗位置 self.system_center_dialog.move(dialog_x, dialog_y) # ------------------- 系统中心弹窗业务逻辑------------------- def handle_sys_setting(self): """系统设置按钮的业务逻辑""" # print("执行系统设置逻辑:如打开系统配置窗口、修改参数等") # 示例:打开系统配置弹窗(后续可新建 SystemSettingDialog) # setting_dialog = SystemSettingDialog(self.main_window) # setting_dialog.exec() def handle_data_center(self): """数据中心按钮的业务逻辑""" # print("执行数据中心逻辑:如查看生产数据、导出报表等") def handle_user_center(self): """用户中心按钮的业务逻辑""" # print("执行用户中心逻辑:如切换用户、修改密码等") # ------------------- 系统诊断弹窗逻辑------------------- def toggle_system_diagnostics_dialog(self): """切换系统诊断弹窗的显示/隐藏状态""" if self.system_diagnostics_dialog.isVisible(): # 已显示 → 执行隐藏 self.system_diagnostics_dialog.hide() else: # 立即执行设备检测 self.device_monitor.force_immediate_check() # 未显示 → 计算位置并显示 self._calc_system_diagnostics_dialog_position() self.system_diagnostics_dialog.show() def _calc_system_diagnostics_dialog_position(self): """计算系统诊断弹窗位置(显示在系统诊断按钮上方)""" btn = self.bottom_control_widget.diagnosis_btn # 诊断按钮 bottom_widget = self.bottom_control_widget # 计算按钮相对于主窗口的位置 bottom_pos_rel_main = bottom_widget.pos() btn_pos_rel_bottom = btn.pos() btn_pos_rel_main = bottom_pos_rel_main + btn_pos_rel_bottom # 计算弹窗坐标 dialog_size = self.system_diagnostics_dialog.size() dialog_x = btn_pos_rel_main.x() dialog_y = btn_pos_rel_main.y() - dialog_size.height() # 设置弹窗位置 self.system_diagnostics_dialog.move(dialog_x, dialog_y) def get_diagnostics_row_col(self): """获取系统诊断弹窗的 行号 和 列号, 都从0开始""" diagnostics_row = self.current_diagnostics_row diagnostics_col = self.current_diagnostics_col self.current_diagnostics_col += 1 if self.current_diagnostics_col == self.system_diagnostics_dialog.max_col: self.current_diagnostics_row += 1 self.current_diagnostics_col = 0 if self.current_diagnostics_row == self.system_diagnostics_dialog.max_row: self.current_diagnostics_row = 0 return diagnostics_row, diagnostics_col def reset_diagnostics_row_col(self): """重置系统诊断弹窗的 行号 和 列号 为0""" self.current_diagnostics_row = 0 self.current_diagnostics_col = 0 def _handle_diagnostics_connect_success(self, device_name:str, delay:int): """处理系统诊断弹窗: 设备连接成功 (设备检测正常)""" row, col = self.get_diagnostics_row_col() self.system_diagnostics_dialog.set_selected_device(row, col, device_name) self.system_diagnostics_dialog.set_ms_value(row, col, delay) if delay <= self.device_monitor.warning_delay: self.system_diagnostics_dialog.set_circle_status(row, col, "normal") else: self.system_diagnostics_dialog.set_circle_status(row, col, "warning") def _handle_diagnostics_connect_failed(self, device_name:str): """处理系统诊断弹窗: 设备检测异常""" row, col = self.get_diagnostics_row_col() self.system_diagnostics_dialog.set_selected_device(row, col, device_name) self.system_diagnostics_dialog.set_ms_value(row, col, -1) self.system_diagnostics_dialog.set_circle_status(row, col, "error") # ================== 系统状态消息列表: 显示系统消息 =================== def toggle_system_status_msg_list(self): """切换系统状态消息弹窗的显示/隐藏状态""" if not self.status_msg_widget.isVisible(): self._calc_system_status_msg_position() self.status_msg_widget.show() else: self.status_msg_widget.hide() def _calc_system_status_msg_position(self): """计算系统状态消息弹窗位置, 并move移动""" btn = self.bottom_control_widget.status_msg_btn bottom_widget = self.bottom_control_widget # 计算按钮相对于主窗口的位置 bottom_pos_rel_main = bottom_widget.pos() btn_pos_rel_bottom = btn.pos() btn_pos_rel_main = bottom_pos_rel_main + btn_pos_rel_bottom # 计算弹窗坐标 dialog_size = self.status_msg_widget.size() dialog_x = btn_pos_rel_main.x() dialog_y = btn_pos_rel_main.y() - dialog_size.height() # 设置弹窗位置 self.status_msg_widget.move(dialog_x, dialog_y) # ================== 预警消息列表: 显示预警消息 =================== def toggle_system_warning_msg_list(self): """切换预警消息列表弹窗的显示/隐藏状态""" if not self.warning_msg_widget.isVisible(): self._calc_system_warning_msg_position() self.warning_msg_widget.show() else: self.warning_msg_widget.hide() def _calc_system_warning_msg_position(self): """计算预警消息列表弹窗位置, 并move移动""" btn = self.bottom_control_widget.warning_list_btn bottom_widget = self.bottom_control_widget # 计算按钮相对于主窗口的位置 bottom_pos_rel_main = bottom_widget.pos() btn_pos_rel_bottom = btn.pos() btn_pos_rel_main = bottom_pos_rel_main + btn_pos_rel_bottom # 计算弹窗坐标 dialog_size = self.warning_msg_widget.size() dialog_x = btn_pos_rel_main.x() dialog_y = btn_pos_rel_main.y() - dialog_size.height() # 设置弹窗位置 self.warning_msg_widget.move(dialog_x, dialog_y)