Files
Feeding_control_system/controller/bottom_control_controller.py

324 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.monitor_thread import MonitorThread
"""
控制主界面底部的所有按钮, 包括系统诊断、系统中心等的行为。
以及 版本信息相关弹窗, 如: 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.diagnostics_device_row = 0 # 系统诊断弹窗的设备检测行号从0开始
self.diagnostics_device_col = 0 # 系统诊断弹窗的设备检测列号从0开始
self.diagnostics_service_row = 0 # 系统诊断弹窗的服务检测行号从0开始
self.diagnostics_service_col = 2 # 系统诊断弹窗的服务检测行号从2开始
# 系统中心弹窗
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 = MonitorThread()
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_device) # 重置系统诊断弹窗中的设备检测
self.device_monitor.connect_success.connect(self._handle_diagnostics_device_connect_success) # 设备正常
self.device_monitor.connect_failed.connect(self._handle_diagnostics_device_connect_failed) # 设备异常
self.device_monitor.check_finished.connect(self._reset_diagnostics_service) # 重置系统诊断弹窗中的服务检测
self.device_monitor.service_normal.connect(self._handle_diagnostics_service_normal) # 服务正常
self.device_monitor.service_error.connect(self._handle_diagnostics_service_error) # 服务异常
# ------------------- 系统中心弹窗逻辑-------------------
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_device_row_col(self):
"""获取系统诊断弹窗中 设备检测的 行号 和 列号, 都从0开始"""
device_row = self.diagnostics_device_row
device_col = self.diagnostics_device_col
self.diagnostics_device_col += 1
if self.diagnostics_device_col == self.system_diagnostics_dialog.max_col // 2: # 左边两列是 设备检测
self.diagnostics_device_row += 1
self.diagnostics_device_col = 0
if self.diagnostics_device_row == self.system_diagnostics_dialog.max_row:
self.diagnostics_device_row = 0
return device_row, device_col
def _reset_diagnostics_device(self):
"""重置系统诊断弹窗中 设备检测"""
# 0、隐藏多余的设备检测框
# 1、设备检测的行号 和 列号(diagnostics_device_row、 self.diagnostics_device_col) 重置为0
while True:
if self.diagnostics_device_row == 0 and self.diagnostics_device_col == 0:
break
row, col = self._get_diagnostics_device_row_col()
self.system_diagnostics_dialog.set_selected_hide(row, col)
def _handle_diagnostics_device_connect_success(self, device_name:str, delay:int):
"""处理系统诊断弹窗: 设备连接成功 (设备检测正常)"""
row, col = self._get_diagnostics_device_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")
# 显示检测组件
self.system_diagnostics_dialog.set_selected_show(row, col)
def _handle_diagnostics_device_connect_failed(self, device_name:str):
"""处理系统诊断弹窗: 设备检测异常"""
row, col = self._get_diagnostics_device_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")
# 显示检测组件
self.system_diagnostics_dialog.set_selected_show(row, col)
def _get_diagnostics_service_row_col(self):
"""获取系统诊断弹窗中 服务检测的 行号 和 列号"""
service_row = self.diagnostics_service_row
service_col = self.diagnostics_service_col
self.diagnostics_service_col += 1
if self.diagnostics_service_col == self.system_diagnostics_dialog.max_col: # 右边两列是 服务检测
self.diagnostics_service_row += 1
self.diagnostics_service_col = 2
if self.diagnostics_service_row == self.system_diagnostics_dialog.max_row:
self.diagnostics_service_row = 0
return service_row, service_col
def _handle_diagnostics_service_normal(self, service_name:str, delay:int):
"""处理系统诊断弹窗: 服务检测正常"""
row, col = self._get_diagnostics_service_row_col()
self.system_diagnostics_dialog.set_selected_service(row, col, service_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")
# 显示检测组件
self.system_diagnostics_dialog.set_selected_show(row, col)
def _handle_diagnostics_service_error(self, service_name:str):
"""处理系统诊断弹窗: 服务检测异常"""
row, col = self._get_diagnostics_service_row_col()
self.system_diagnostics_dialog.set_selected_service(row, col, service_name)
self.system_diagnostics_dialog.set_ms_value(row, col, -1)
self.system_diagnostics_dialog.set_circle_status(row, col, "error")
# 显示检测组件
self.system_diagnostics_dialog.set_selected_show(row, col)
def _reset_diagnostics_service(self):
"""重置系统诊断弹窗中 服务检测"""
# 0、隐藏多余的服务检测框
# 1、设备检测的行号 self.diagnostics_service_row 重置为0 self.diagnostics_service_col 重置为2
while True:
if self.diagnostics_service_row == 0 and self.diagnostics_service_col == 2:
break
row, col = self._get_diagnostics_service_row_col()
self.system_diagnostics_dialog.set_selected_hide(row, col)
# ================== 系统状态消息列表: 显示系统消息 ===================
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)