|
- /**
- * @file logic_editor_widget.h
- * @brief 定义结构化梯形图编辑和运行轨迹画布
- * @version 1.0.0
- * @author suyu
- * @date 2026-08-22
- */
-
- #pragma once
-
- #include "domain/control_logic_model.h"
- #include "services/logic_command_service.h"
- #include "services/logic_editor_service.h"
- #include "services/software_logic_executor.h"
-
- #include <QGraphicsView>
-
- #include <string>
- #include <utility>
- #include <vector>
-
- class QGraphicsScene;
- class QCompleter;
- class QEvent;
- class QLineEdit;
- class QMouseEvent;
- class QRubberBand;
- class QResizeEvent;
-
- /** 将结构化梯形图表达式投影成网格图元;不保存自由线段,编辑通过服务提交 */
- class LogicEditorWidget final : public QGraphicsView
- {
- Q_OBJECT
-
- public:
- /** 梯形图中的条件、输出、横线和辅助选择图元类型 */
- class NodeItem;
- class WireItem;
- class WireCellItem;
- class GapCellItem;
- class VerticalConnectorItem;
- class RungItem;
- class EmptySlotItem;
- class OutputSlotItem;
-
- /** 创建梯形图画布并绑定编辑服务 */
- explicit LogicEditorWidget(
- LogicEditorService &editor_service,
- QWidget *parent = nullptr);
-
- /** 切换当前显示的控制逻辑;不存在时显示空场景 */
- void setLogicId(const std::string &logic_id);
- /** 设置是否允许编辑梯形图 */
- void setEditingEnabled(bool enabled);
- /** 设置离线运行轨迹;真机模式应传入空轨迹,避免显示本地伪轨迹 */
- void setRuntimeTrace(
- const LogicTraceSnapshot &trace,
- const std::string &fault_node_id = {});
- /** 清除当前运行轨迹和故障节点标记 */
- void clearRuntimeTrace();
- /** 返回当前是否正在显示运行轨迹 */
- bool runtimeTraceEnabled() const;
- /** 根据当前逻辑模型重建梯形图场景 */
- void reloadLogic();
- /** 选中指定节点并滚动到可见区域 */
- void selectNode(const std::string &node_id);
- /** 返回当前选中的单个节点标识 */
- std::string selectedNodeId() const;
- /** 返回当前选中的多个节点标识 */
- std::vector<std::string> selectedNodeIds() const;
- /** 返回当前选中的网络标识 */
- std::string selectedRungId() const;
-
- /** 新增一个空的梯形图网络 */
- LogicEditorResult addRung();
- /** 将当前选择转换为服务调用并新增串联条件 */
- LogicEditorResult addCondition(const LogicNodeConfig &config);
- /** 将当前选择转换为服务调用并新增并联支路 */
- LogicEditorResult addParallelBranch(const LogicNodeConfig &config);
- /** 在当前选择位置新增横线 */
- LogicEditorResult addHorizontalWire();
- /** 在当前选择位置新增竖线 */
- LogicEditorResult addVerticalWire();
- /** 删除当前选择位置的横线 */
- LogicEditorResult deleteHorizontalWire();
- /** 删除当前选择位置的竖线 */
- LogicEditorResult deleteVerticalWire();
- /** 设置当前网络的输出线圈 */
- LogicEditorResult setOutput(
- const LogicNodeConfig &config, bool configured = false);
- /** 按当前画布选择位置粘贴一组连续条件 */
- LogicEditorResult pasteConditionNodes(const std::vector<LogicNode> &nodes);
- /** 删除当前选中的节点、线段或网络 */
- LogicEditorResult deleteSelected();
-
- signals:
- /** 当前选中的节点发生变化时发出 */
- void nodeSelected(const QString &node_id);
- /** 梯形图模型成功发生变化时发出 */
- void graphChanged();
- /** 编辑服务操作失败时发出可显示的错误信息 */
- void editorError(const QString &message);
-
- protected:
- /** 在任意网络区域开始鼠标框选 */
- void mousePressEvent(QMouseEvent *event) override;
- /** 更新鼠标框选区域 */
- void mouseMoveEvent(QMouseEvent *event) override;
- /** 完成鼠标框选并提交场景选择 */
- void mouseReleaseEvent(QMouseEvent *event) override;
- /** 在条件网格或输出槽双击时打开命令输入框 */
- void mouseDoubleClickEvent(QMouseEvent *event) override;
- /** 在窗口大小变化后重新布局梯形图场景 */
- void resizeEvent(QResizeEvent *event) override;
- /** 滚动画布时同步命令输入框位置 */
- void scrollContentsBy(int dx, int dy) override;
- /** 处理命令输入框的回车、取消和按键事件 */
- bool eventFilter(QObject *watched, QEvent *event) override;
-
- private:
- /** 处理图形场景选择变化 */
- void handleSelectionChanged();
- /** 把编辑服务结果转换为错误信号 */
- void reportFailure(const LogicEditorResult &result);
- /** 返回当前选中的网络标识 */
- std::string currentRungId() const;
- /** 选中指定表达式图元 */
- void selectExpression(const std::string &expression_id);
- /** 选中指定横线图元 */
- void selectWire(const std::string &wire_id);
- /** 收集当前选中的表达式标识 */
- std::vector<std::string> selectedExpressionIds() const;
- /** 收集当前选中的横线标识 */
- std::vector<std::string> selectedWireIds() const;
- /** 收集当前选中的并联支路标识 */
- std::vector<std::string> selectedBranchIds() const;
- /** 收集当前选中的空网格位置 */
- std::vector<std::pair<std::string, int>> selectedEmptySlots() const;
- /** 收集当前选中的横线网格位置 */
- std::vector<std::pair<std::string, int>> selectedWireCells() const;
- /** 收集当前选中的显式断路网格位置 */
- std::vector<std::pair<std::string, int>> selectedGapCells() const;
- /** 判断当前是否选中了网络内的图元 */
- bool hasSelectedRungItem() const;
- /** 收集当前明确选中的网络图元 */
- std::vector<std::string> selectedRungItemIds() const;
- /** 打开指定目标位置的命令输入框 */
- void beginCommandInput(
- const LogicCommandTarget &target,
- const QPointF &scene_center);
- /** 提交当前命令输入;失败时保留输入框并标红 */
- void commitCommandInput();
- /** 关闭命令输入框并清理临时状态 */
- void cancelCommandInput();
- /** 根据网络、列和支路标识查找下一输入位置 */
- bool beginNextCommandInput();
- /** 按目标定位输入框的屏幕矩形 */
- void positionCommandInput(const QPointF &scene_center);
- /** 返回当前场景目标的中心位置 */
- bool findCommandTargetCenter(
- const LogicCommandTarget &target,
- QPointF *scene_center) const;
- /** 将成功命令选中并刷新属性面板 */
- void selectCommandResult(const LogicCommandResult &result);
-
- /** 梯形图编辑服务,不由控件拥有 */
- LogicEditorService &editor_service_;
- /** 命令语解析和结构化编辑适配服务 */
- LogicCommandService command_service_;
- /** 承载梯形图图元的场景 */
- QGraphicsScene *scene_ = nullptr;
- /** 当前显示的控制逻辑标识 */
- std::string logic_id_;
- /** 当前选中的网络标识 */
- std::string current_rung_id_;
- /** 最近一次收到的运行轨迹 */
- LogicTraceSnapshot trace_;
- /** 最近一次运行故障节点标识 */
- std::string fault_node_id_;
- /** 是否显示运行轨迹 */
- bool runtime_trace_enabled_ = false;
- /** 是否允许编辑梯形图 */
- bool editing_enabled_ = true;
- /** 鼠标框选覆盖层 */
- QRubberBand *selection_band_ = nullptr;
- /** 框选起点(视口坐标) */
- QPoint selection_origin_;
- /** 框选时是否已超过拖拽阈值 */
- bool selection_dragging_ = false;
- /** 框选起始时的键盘修饰键 */
- Qt::KeyboardModifiers selection_modifiers_ = Qt::NoModifier;
- /** 命令输入框,仅在编辑态临时创建 */
- QLineEdit *command_editor_ = nullptr;
- /** 命令输入补全器 */
- QCompleter *command_completer_ = nullptr;
- /** 当前命令输入目标 */
- LogicCommandTarget command_target_;
- /** 是否沿当前命令序列继续输入 */
- bool command_continuing_ = false;
- /** OR/ORI 只增加支路,不推进主表达式列 */
- bool command_keep_column_ = false;
- /** 连续输入对应的当前网络 */
- std::string command_current_rung_id_;
- /** 编辑已有网络 OR 时保留的选择范围 */
- std::vector<std::string> command_parallel_node_ids_;
- };
|