综合平台编程器项目的远程存储
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.
 
 
 
 

221 lines
7.1 KiB

  1. #include "runtime_monitor_widget.h"
  2. #include "free_monitor_widget.h"
  3. #include "hmi_editor_widget.h"
  4. #include "logic_editor_widget.h"
  5. #include "services/hmi_navigation_service.h"
  6. #include "services/alarm_service.h"
  7. #include "services/project_service.h"
  8. #include "toolbar_icon_factory.h"
  9. #include "ui_runtime_monitor_widget.h"
  10. #include <QSplitter>
  11. #include <QComboBox>
  12. #include <QSignalBlocker>
  13. #include <QToolButton>
  14. #include <algorithm>
  15. namespace {
  16. QString fromUtf8(const std::string &value)
  17. {
  18. return QString::fromUtf8(value.data(), static_cast<int>(value.size()));
  19. }
  20. std::string toUtf8(const QString &value)
  21. {
  22. const QByteArray bytes = value.toUtf8();
  23. return std::string(bytes.constData(), static_cast<std::size_t>(bytes.size()));
  24. }
  25. } // namespace
  26. RuntimeMonitorWidget::RuntimeMonitorWidget(
  27. HmiEditorService &hmi_editor_service,
  28. HmiRuntimeService &hmi_runtime_service,
  29. LogicEditorService &logic_editor_service,
  30. ProjectService &project_service,
  31. HmiNavigationService &hmi_navigation_service,
  32. AlarmService &alarm_service,
  33. RegisterMonitorService &register_monitor_service,
  34. QWidget *parent)
  35. : QWidget(parent),
  36. ui_(std::make_unique<Ui::RuntimeMonitorWidget>()),
  37. project_service_(project_service),
  38. hmi_navigation_service_(hmi_navigation_service)
  39. {
  40. ui_->setupUi(this);
  41. ui_->exitRuntimeButton->setIcon(makeUiIcon(UiIcon::Exit));
  42. hmi_view_ = new HmiEditorWidget(
  43. hmi_editor_service,
  44. hmi_runtime_service,
  45. alarm_service,
  46. ui_->hmiViewContainer);
  47. hmi_view_->setObjectName(QStringLiteral("runtimeHmiView"));
  48. hmi_view_->setEditingEnabled(false);
  49. hmi_view_->setRuntimeActive(true);
  50. ui_->hmiViewLayout->addWidget(hmi_view_);
  51. logic_view_ = new LogicEditorWidget(logic_editor_service, ui_->logicViewContainer);
  52. logic_view_->setObjectName(QStringLiteral("runtimeLogicView"));
  53. logic_view_->setEditingEnabled(false);
  54. ui_->logicViewLayout->addWidget(logic_view_);
  55. free_monitor_widget_ = new FreeMonitorWidget(
  56. register_monitor_service, ui_->monitorContainer);
  57. free_monitor_widget_->setObjectName(QStringLiteral("freeMonitorWidget"));
  58. ui_->monitorContainerLayout->addWidget(free_monitor_widget_);
  59. ui_->upperSplitter->setSizes({600, 600});
  60. ui_->verticalSplitter->setSizes({440, 260});
  61. connect(hmi_view_, &HmiEditorWidget::pageNavigationRequested,
  62. this,
  63. [this](const QString &target_page_id)
  64. {
  65. const HmiNavigationResult result =
  66. hmi_navigation_service_.navigateTo(toUtf8(target_page_id));
  67. if (!result.succeeded)
  68. {
  69. emit navigationFailed(fromUtf8(result.message));
  70. return;
  71. }
  72. showRuntimePage(result.pageId);
  73. });
  74. connect(ui_->exitRuntimeButton, &QToolButton::clicked,
  75. this, &RuntimeMonitorWidget::exitRequested);
  76. connect(ui_->runtimeLogicComboBox,
  77. QOverload<int>::of(&QComboBox::currentIndexChanged),
  78. this,
  79. [this](int index)
  80. {
  81. if (index >= 0)
  82. {
  83. selectRuntimeLogic(toUtf8(
  84. ui_->runtimeLogicComboBox->itemData(index).toString()));
  85. }
  86. });
  87. }
  88. RuntimeMonitorWidget::~RuntimeMonitorWidget() = default;
  89. void RuntimeMonitorWidget::setProjectObjects(
  90. const std::string &page_id, const std::string &logic_id)
  91. {
  92. setRuntimePage(page_id);
  93. const QSignalBlocker blocker(ui_->runtimeLogicComboBox);
  94. ui_->runtimeLogicComboBox->clear();
  95. for (const ControlLogic &logic : project_service_.project().controlLogics)
  96. {
  97. if (logic.enabled)
  98. {
  99. ui_->runtimeLogicComboBox->addItem(
  100. fromUtf8(logic.name), fromUtf8(logic.id));
  101. }
  102. }
  103. int selected_index = ui_->runtimeLogicComboBox->findData(fromUtf8(logic_id));
  104. if (selected_index < 0 && ui_->runtimeLogicComboBox->count() > 0)
  105. {
  106. selected_index = 0;
  107. }
  108. ui_->runtimeLogicComboBox->setCurrentIndex(selected_index);
  109. selectRuntimeLogic(selected_index >= 0
  110. ? toUtf8(ui_->runtimeLogicComboBox->itemData(selected_index).toString())
  111. : std::string{});
  112. }
  113. void RuntimeMonitorWidget::setRuntimePage(const std::string &page_id)
  114. {
  115. showRuntimePage(page_id);
  116. }
  117. void RuntimeMonitorWidget::setMode(
  118. ApplicationMode mode, PlcConnectionState plc_state)
  119. {
  120. // 真机时清空本地轨迹,防止把 PC 离线执行结果误认为 PLC 内部程序轨迹
  121. const bool offline = mode == ApplicationMode::OfflineRunning;
  122. const bool online = mode == ApplicationMode::OnlineRunning;
  123. ui_->logicFrame->setVisible(offline);
  124. hmi_view_->setRuntimeActive(offline || online);
  125. if (!offline && !online)
  126. {
  127. setHmiWriteEnabled(false);
  128. }
  129. setFreeMonitorWriteEnabled(offline
  130. || (online && plc_state == PlcConnectionState::Connected));
  131. if (!offline)
  132. {
  133. logic_view_->clearRuntimeTrace();
  134. latest_trace_.clear();
  135. latest_fault_node_id_.clear();
  136. has_logic_trace_ = false;
  137. }
  138. ui_->modeLabel->setText(
  139. offline ? tr("离线仿真 · 虚拟 M/D")
  140. : online ? tr("真机运行 · PLC 缓存") : tr("当前未运行"));
  141. free_monitor_widget_->refreshValues(mode, plc_state);
  142. }
  143. void RuntimeMonitorWidget::setHmiWriteEnabled(bool enabled)
  144. {
  145. hmi_view_->setRuntimeWriteEnabled(enabled);
  146. }
  147. void RuntimeMonitorWidget::setFreeMonitorWriteEnabled(bool enabled)
  148. {
  149. free_monitor_widget_->setWriteEnabled(enabled);
  150. }
  151. void RuntimeMonitorWidget::refreshValues(
  152. ApplicationMode mode, PlcConnectionState plc_state)
  153. {
  154. // HMI、报警和自由监控共享同一个活动寄存器仓库
  155. hmi_view_->refreshRuntimeValues();
  156. free_monitor_widget_->refreshValues(mode, plc_state);
  157. }
  158. void RuntimeMonitorWidget::setLogicTrace(
  159. const LogicTraceSnapshot &trace, const std::string &fault_node_id)
  160. {
  161. latest_trace_ = trace;
  162. latest_fault_node_id_ = fault_node_id;
  163. has_logic_trace_ = true;
  164. logic_view_->setRuntimeTrace(
  165. trace.forLogic(selected_logic_id_), fault_node_id);
  166. }
  167. FreeMonitorWidget *RuntimeMonitorWidget::freeMonitorWidget() const
  168. {
  169. return free_monitor_widget_;
  170. }
  171. std::string RuntimeMonitorWidget::selectedLogicId() const
  172. {
  173. return selected_logic_id_;
  174. }
  175. void RuntimeMonitorWidget::showRuntimePage(const std::string &page_id)
  176. {
  177. hmi_view_->setPageId(page_id);
  178. hmi_view_->reloadPage();
  179. const auto page = std::find_if(
  180. project_service_.project().hmiPages.cbegin(),
  181. project_service_.project().hmiPages.cend(),
  182. [&page_id](const HmiPage &candidate) { return candidate.id == page_id; });
  183. ui_->runtimePageLabel->setText(
  184. page == project_service_.project().hmiPages.cend()
  185. ? tr("未选择页面") : fromUtf8(page->name));
  186. }
  187. void RuntimeMonitorWidget::selectRuntimeLogic(const std::string &logic_id)
  188. {
  189. selected_logic_id_ = logic_id;
  190. logic_view_->setLogicId(logic_id);
  191. logic_view_->reloadLogic();
  192. if (has_logic_trace_)
  193. {
  194. logic_view_->setRuntimeTrace(
  195. latest_trace_.forLogic(logic_id), latest_fault_node_id_);
  196. }
  197. }