综合平台编程器项目的远程存储
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

225 строки
7.3 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_->logicNoticeLabel->setVisible(false);
  60. ui_->upperSplitter->setSizes({600, 600});
  61. ui_->verticalSplitter->setSizes({440, 260});
  62. connect(hmi_view_, &HmiEditorWidget::pageNavigationRequested,
  63. this,
  64. [this](const QString &target_page_id)
  65. {
  66. const HmiNavigationResult result =
  67. hmi_navigation_service_.navigateTo(toUtf8(target_page_id));
  68. if (!result.succeeded)
  69. {
  70. emit navigationFailed(fromUtf8(result.message));
  71. return;
  72. }
  73. showRuntimePage(result.pageId);
  74. });
  75. connect(ui_->exitRuntimeButton, &QToolButton::clicked,
  76. this, &RuntimeMonitorWidget::exitRequested);
  77. connect(ui_->runtimeLogicComboBox,
  78. QOverload<int>::of(&QComboBox::currentIndexChanged),
  79. this,
  80. [this](int index)
  81. {
  82. if (index >= 0)
  83. {
  84. selectRuntimeLogic(toUtf8(
  85. ui_->runtimeLogicComboBox->itemData(index).toString()));
  86. }
  87. });
  88. }
  89. RuntimeMonitorWidget::~RuntimeMonitorWidget() = default;
  90. void RuntimeMonitorWidget::setProjectObjects(
  91. const std::string &page_id, const std::string &logic_id)
  92. {
  93. setRuntimePage(page_id);
  94. const QSignalBlocker blocker(ui_->runtimeLogicComboBox);
  95. ui_->runtimeLogicComboBox->clear();
  96. for (const ControlLogic &logic : project_service_.project().controlLogics)
  97. {
  98. if (logic.enabled)
  99. {
  100. ui_->runtimeLogicComboBox->addItem(
  101. fromUtf8(logic.name), fromUtf8(logic.id));
  102. }
  103. }
  104. int selected_index = ui_->runtimeLogicComboBox->findData(fromUtf8(logic_id));
  105. if (selected_index < 0 && ui_->runtimeLogicComboBox->count() > 0)
  106. {
  107. selected_index = 0;
  108. }
  109. ui_->runtimeLogicComboBox->setCurrentIndex(selected_index);
  110. selectRuntimeLogic(selected_index >= 0
  111. ? toUtf8(ui_->runtimeLogicComboBox->itemData(selected_index).toString())
  112. : std::string{});
  113. }
  114. void RuntimeMonitorWidget::setRuntimePage(const std::string &page_id)
  115. {
  116. showRuntimePage(page_id);
  117. }
  118. void RuntimeMonitorWidget::setMode(
  119. ApplicationMode mode, PlcConnectionState plc_state)
  120. {
  121. const bool offline = mode == ApplicationMode::OfflineRunning;
  122. const bool online = mode == ApplicationMode::OnlineRunning;
  123. ui_->logicFrame->setVisible(offline || online);
  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 && !online)
  132. {
  133. logic_view_->clearRuntimeTrace();
  134. latest_trace_.clear();
  135. latest_fault_node_id_.clear();
  136. has_logic_trace_ = false;
  137. }
  138. ui_->logicLabel->setText(
  139. online ? tr("本地推算轨迹") : tr("梯形图运行状态"));
  140. ui_->logicNoticeLabel->setVisible(online);
  141. ui_->modeLabel->setText(
  142. offline ? tr("离线仿真 · 虚拟 M/D")
  143. : online ? tr("真机运行 · PLC 缓存 · 本地推算轨迹")
  144. : tr("当前未运行"));
  145. free_monitor_widget_->refreshValues(mode, plc_state);
  146. }
  147. void RuntimeMonitorWidget::setHmiWriteEnabled(bool enabled)
  148. {
  149. hmi_view_->setRuntimeWriteEnabled(enabled);
  150. }
  151. void RuntimeMonitorWidget::setFreeMonitorWriteEnabled(bool enabled)
  152. {
  153. free_monitor_widget_->setWriteEnabled(enabled);
  154. }
  155. void RuntimeMonitorWidget::refreshValues(
  156. ApplicationMode mode, PlcConnectionState plc_state)
  157. {
  158. // HMI、报警和自由监控共享同一个活动寄存器仓库
  159. hmi_view_->refreshRuntimeValues();
  160. free_monitor_widget_->refreshValues(mode, plc_state);
  161. }
  162. void RuntimeMonitorWidget::setLogicTrace(
  163. const LogicTraceSnapshot &trace, const std::string &fault_node_id)
  164. {
  165. latest_trace_ = trace;
  166. latest_fault_node_id_ = fault_node_id;
  167. has_logic_trace_ = true;
  168. logic_view_->setRuntimeTrace(
  169. trace.forLogic(selected_logic_id_), fault_node_id);
  170. }
  171. FreeMonitorWidget *RuntimeMonitorWidget::freeMonitorWidget() const
  172. {
  173. return free_monitor_widget_;
  174. }
  175. std::string RuntimeMonitorWidget::selectedLogicId() const
  176. {
  177. return selected_logic_id_;
  178. }
  179. void RuntimeMonitorWidget::showRuntimePage(const std::string &page_id)
  180. {
  181. hmi_view_->setPageId(page_id);
  182. hmi_view_->reloadPage();
  183. const auto page = std::find_if(
  184. project_service_.project().hmiPages.cbegin(),
  185. project_service_.project().hmiPages.cend(),
  186. [&page_id](const HmiPage &candidate) { return candidate.id == page_id; });
  187. ui_->runtimePageLabel->setText(
  188. page == project_service_.project().hmiPages.cend()
  189. ? tr("未选择页面") : fromUtf8(page->name));
  190. }
  191. void RuntimeMonitorWidget::selectRuntimeLogic(const std::string &logic_id)
  192. {
  193. selected_logic_id_ = logic_id;
  194. logic_view_->setLogicId(logic_id);
  195. logic_view_->reloadLogic();
  196. if (has_logic_trace_)
  197. {
  198. logic_view_->setRuntimeTrace(
  199. latest_trace_.forLogic(logic_id), latest_fault_node_id_);
  200. }
  201. }