|
|
|
@@ -6,6 +6,7 @@ |
|
|
|
#include "runtime_monitor_widget.h" |
|
|
|
#include "free_monitor_widget.h" |
|
|
|
#include "services/hmi_editor_service.h" |
|
|
|
#include "services/hmi_navigation_service.h" |
|
|
|
#include "services/hmi_runtime_service.h" |
|
|
|
#include "services/logic_editor_service.h" |
|
|
|
#include "services/project_service.h" |
|
|
|
@@ -23,6 +24,7 @@ |
|
|
|
#include <QMessageBox> |
|
|
|
#include <QMenu> |
|
|
|
#include <QPushButton> |
|
|
|
#include <QSignalBlocker> |
|
|
|
#include <QSpinBox> |
|
|
|
#include <QStatusBar> |
|
|
|
#include <QStyle> |
|
|
|
@@ -37,6 +39,16 @@ |
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
enum class ProjectTreeItemKind |
|
|
|
{ |
|
|
|
Root = 0, |
|
|
|
HmiPage = 1, |
|
|
|
ControlLogic = 2 |
|
|
|
}; |
|
|
|
|
|
|
|
constexpr int kProjectTreeKindRole = Qt::UserRole; |
|
|
|
constexpr int kProjectTreeIdRole = Qt::UserRole + 1; |
|
|
|
|
|
|
|
QString modeText(ApplicationMode mode) |
|
|
|
{ |
|
|
|
switch (mode) |
|
|
|
@@ -157,10 +169,17 @@ QString controlTypeText(HmiControlType type) |
|
|
|
return MainWindow::tr("数值输入"); |
|
|
|
} |
|
|
|
case HmiControlType::Label: |
|
|
|
default: |
|
|
|
{ |
|
|
|
return MainWindow::tr("文本"); |
|
|
|
} |
|
|
|
case HmiControlType::PageJump: |
|
|
|
{ |
|
|
|
return MainWindow::tr("页面跳转"); |
|
|
|
} |
|
|
|
default: |
|
|
|
{ |
|
|
|
return MainWindow::tr("未知控件"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -181,7 +200,37 @@ MainWindow::MainWindow( |
|
|
|
hmi_editor_service_(hmi_editor_service), |
|
|
|
logic_editor_service_(logic_editor_service), |
|
|
|
hmi_runtime_service_(hmi_runtime_service), |
|
|
|
register_monitor_service_(register_monitor_service) |
|
|
|
register_monitor_service_(register_monitor_service), |
|
|
|
owned_hmi_navigation_service_( |
|
|
|
std::make_unique<HmiNavigationService>(project_service)), |
|
|
|
hmi_navigation_service_(owned_hmi_navigation_service_.get()) |
|
|
|
{ |
|
|
|
initializeUi(); |
|
|
|
} |
|
|
|
|
|
|
|
MainWindow::MainWindow( |
|
|
|
RuntimeModeService &runtime_mode_service, |
|
|
|
ProjectService &project_service, |
|
|
|
HmiEditorService &hmi_editor_service, |
|
|
|
LogicEditorService &logic_editor_service, |
|
|
|
HmiRuntimeService &hmi_runtime_service, |
|
|
|
HmiNavigationService &hmi_navigation_service, |
|
|
|
RegisterMonitorService ®ister_monitor_service, |
|
|
|
QWidget *parent) |
|
|
|
: QMainWindow(parent), |
|
|
|
ui_(std::make_unique<Ui::MainWindow>()), |
|
|
|
runtime_mode_service_(runtime_mode_service), |
|
|
|
project_service_(project_service), |
|
|
|
hmi_editor_service_(hmi_editor_service), |
|
|
|
logic_editor_service_(logic_editor_service), |
|
|
|
hmi_runtime_service_(hmi_runtime_service), |
|
|
|
register_monitor_service_(register_monitor_service), |
|
|
|
hmi_navigation_service_(&hmi_navigation_service) |
|
|
|
{ |
|
|
|
initializeUi(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::initializeUi() |
|
|
|
{ |
|
|
|
ui_->setupUi(this); |
|
|
|
configureAppearance(); |
|
|
|
@@ -191,10 +240,13 @@ MainWindow::MainWindow( |
|
|
|
configureHmiEditor(); |
|
|
|
configureLogicEditor(); |
|
|
|
configureRuntimeMonitor(); |
|
|
|
configureProjectTree(); |
|
|
|
runtime_mode_service_.setPlcStatusChangedCallback( |
|
|
|
[this] { schedulePlcStatusUpdate(); }); |
|
|
|
hmi_editor_service_.ensureDefaultPage(); |
|
|
|
logic_editor_service_.ensureDefaultLogic(); |
|
|
|
current_hmi_page_id_ = hmi_editor_service_.firstPageId(); |
|
|
|
current_logic_id_ = logic_editor_service_.firstLogicId(); |
|
|
|
refreshProjectUi(); |
|
|
|
updateModeUi(tr("系统已进入编辑态")); |
|
|
|
} |
|
|
|
@@ -204,6 +256,16 @@ MainWindow::~MainWindow() |
|
|
|
runtime_mode_service_.setPlcStatusChangedCallback({}); |
|
|
|
} |
|
|
|
|
|
|
|
const std::string &MainWindow::currentHmiPageId() const |
|
|
|
{ |
|
|
|
return current_hmi_page_id_; |
|
|
|
} |
|
|
|
|
|
|
|
const std::string &MainWindow::currentLogicId() const |
|
|
|
{ |
|
|
|
return current_logic_id_; |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::configureActions() |
|
|
|
{ |
|
|
|
mode_action_group_ = new QActionGroup(this); |
|
|
|
@@ -232,6 +294,10 @@ void MainWindow::configureActions() |
|
|
|
[this] { addHmiControl(HmiControlType::NumericDisplay); }); |
|
|
|
connect(ui_->addNumericInputAction, &QAction::triggered, this, |
|
|
|
[this] { addHmiControl(HmiControlType::NumericInput); }); |
|
|
|
connect(ui_->addLabelAction, &QAction::triggered, this, |
|
|
|
[this] { addHmiControl(HmiControlType::Label); }); |
|
|
|
connect(ui_->addPageJumpAction, &QAction::triggered, this, |
|
|
|
[this] { addHmiControl(HmiControlType::PageJump); }); |
|
|
|
connect(ui_->deleteControlAction, &QAction::triggered, |
|
|
|
this, &MainWindow::deleteSelectedControl); |
|
|
|
|
|
|
|
@@ -349,6 +415,7 @@ void MainWindow::configureActions() |
|
|
|
if (index == 0 || index == 1) |
|
|
|
{ |
|
|
|
last_editing_tab_index_ = index; |
|
|
|
refreshProjectUi(); |
|
|
|
} |
|
|
|
}); |
|
|
|
ui_->hmiToolBar->setVisible(ui_->editorTabWidget->currentIndex() == 0); |
|
|
|
@@ -383,6 +450,10 @@ void MainWindow::configureAppearance() |
|
|
|
style()->standardIcon(QStyle::SP_FileDialogInfoView)); |
|
|
|
ui_->addNumericInputAction->setIcon( |
|
|
|
style()->standardIcon(QStyle::SP_FileDialogContentsView)); |
|
|
|
ui_->addLabelAction->setIcon( |
|
|
|
style()->standardIcon(QStyle::SP_FileDialogInfoView)); |
|
|
|
ui_->addPageJumpAction->setIcon( |
|
|
|
style()->standardIcon(QStyle::SP_ArrowForward)); |
|
|
|
ui_->deleteControlAction->setIcon(style()->standardIcon(QStyle::SP_TrashIcon)); |
|
|
|
ui_->addRungAction->setIcon(style()->standardIcon(QStyle::SP_FileIcon)); |
|
|
|
ui_->parallelInsertAction->setIcon(style()->standardIcon(QStyle::SP_ArrowDown)); |
|
|
|
@@ -483,7 +554,8 @@ void MainWindow::configureHmiEditor() |
|
|
|
[this] |
|
|
|
{ |
|
|
|
logic_editor_widget_->setRuntimeTrace( |
|
|
|
runtime_mode_service_.offlineSimulationService().traceSnapshot()); |
|
|
|
runtime_mode_service_.offlineSimulationService() |
|
|
|
.traceSnapshot().forLogic(current_logic_id_)); |
|
|
|
runtime_monitor_widget_->setLogicTrace( |
|
|
|
runtime_mode_service_.offlineSimulationService().traceSnapshot()); |
|
|
|
}, |
|
|
|
@@ -521,6 +593,8 @@ void MainWindow::configureRuntimeMonitor() |
|
|
|
hmi_editor_service_, |
|
|
|
hmi_runtime_service_, |
|
|
|
logic_editor_service_, |
|
|
|
project_service_, |
|
|
|
*hmi_navigation_service_, |
|
|
|
register_monitor_service_, |
|
|
|
ui_->runtimeMonitorTab); |
|
|
|
runtime_monitor_widget_->setObjectName(QStringLiteral("runtimeMonitorWidget")); |
|
|
|
@@ -543,9 +617,76 @@ void MainWindow::configureRuntimeMonitor() |
|
|
|
{ |
|
|
|
statusBar()->showMessage(message, 4000); |
|
|
|
}); |
|
|
|
connect(runtime_monitor_widget_, &RuntimeMonitorWidget::navigationFailed, |
|
|
|
this, |
|
|
|
[this](const QString &message) |
|
|
|
{ |
|
|
|
statusBar()->showMessage(message, 5000); |
|
|
|
ui_->outputList->addItem(tr("页面导航失败:%1").arg(message)); |
|
|
|
}); |
|
|
|
ui_->editorTabWidget->setTabVisible(2, false); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::configureProjectTree() |
|
|
|
{ |
|
|
|
ui_->projectTree->setContextMenuPolicy(Qt::ActionsContextMenu); |
|
|
|
|
|
|
|
add_page_action_ = new QAction(tr("新建页面"), this); |
|
|
|
add_page_action_->setObjectName(QStringLiteral("addPageAction")); |
|
|
|
add_logic_action_ = new QAction(tr("新建控制逻辑"), this); |
|
|
|
add_logic_action_->setObjectName(QStringLiteral("addLogicAction")); |
|
|
|
rename_project_item_action_ = new QAction(tr("重命名"), this); |
|
|
|
rename_project_item_action_->setObjectName( |
|
|
|
QStringLiteral("renameProjectItemAction")); |
|
|
|
delete_project_item_action_ = new QAction(tr("删除"), this); |
|
|
|
delete_project_item_action_->setObjectName( |
|
|
|
QStringLiteral("deleteProjectItemAction")); |
|
|
|
move_project_item_up_action_ = new QAction(tr("上移"), this); |
|
|
|
move_project_item_up_action_->setObjectName( |
|
|
|
QStringLiteral("moveProjectItemUpAction")); |
|
|
|
move_project_item_down_action_ = new QAction(tr("下移"), this); |
|
|
|
move_project_item_down_action_->setObjectName( |
|
|
|
QStringLiteral("moveProjectItemDownAction")); |
|
|
|
set_initial_page_action_ = new QAction(tr("设为初始页面"), this); |
|
|
|
set_initial_page_action_->setObjectName( |
|
|
|
QStringLiteral("setInitialPageAction")); |
|
|
|
toggle_logic_enabled_action_ = new QAction(tr("禁用控制逻辑"), this); |
|
|
|
toggle_logic_enabled_action_->setObjectName( |
|
|
|
QStringLiteral("toggleLogicEnabledAction")); |
|
|
|
|
|
|
|
ui_->projectTree->addActions({ |
|
|
|
add_page_action_, |
|
|
|
add_logic_action_, |
|
|
|
rename_project_item_action_, |
|
|
|
delete_project_item_action_, |
|
|
|
move_project_item_up_action_, |
|
|
|
move_project_item_down_action_, |
|
|
|
set_initial_page_action_, |
|
|
|
toggle_logic_enabled_action_}); |
|
|
|
|
|
|
|
connect(add_page_action_, &QAction::triggered, this, &MainWindow::addPage); |
|
|
|
connect(add_logic_action_, &QAction::triggered, this, &MainWindow::addLogic); |
|
|
|
connect(rename_project_item_action_, &QAction::triggered, |
|
|
|
this, &MainWindow::renameProjectItem); |
|
|
|
connect(delete_project_item_action_, &QAction::triggered, |
|
|
|
this, &MainWindow::deleteProjectItem); |
|
|
|
connect(move_project_item_up_action_, &QAction::triggered, |
|
|
|
this, [this] { moveProjectItem(-1); }); |
|
|
|
connect(move_project_item_down_action_, &QAction::triggered, |
|
|
|
this, [this] { moveProjectItem(1); }); |
|
|
|
connect(set_initial_page_action_, &QAction::triggered, |
|
|
|
this, &MainWindow::setSelectedPageAsInitial); |
|
|
|
connect(toggle_logic_enabled_action_, &QAction::triggered, |
|
|
|
this, &MainWindow::toggleSelectedLogicEnabled); |
|
|
|
connect(ui_->projectTree, &QTreeWidget::currentItemChanged, |
|
|
|
this, |
|
|
|
[this](QTreeWidgetItem *, QTreeWidgetItem *) |
|
|
|
{ |
|
|
|
handleProjectTreeSelection(); |
|
|
|
}); |
|
|
|
updateProjectTreeActions(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::configurePropertyEditor() |
|
|
|
{ |
|
|
|
ui_->bindingAreaComboBox->setItemData(0, -1); |
|
|
|
@@ -567,6 +708,8 @@ void MainWindow::configurePropertyEditor() |
|
|
|
this, &MainWindow::applySelectedControlProperties); |
|
|
|
connect(ui_->applyLogicPropertiesButton, &QPushButton::clicked, |
|
|
|
this, &MainWindow::applySelectedLogicNodeProperties); |
|
|
|
ui_->targetPageLabel->setVisible(false); |
|
|
|
ui_->targetPageComboBox->setVisible(false); |
|
|
|
showControlProperties({}); |
|
|
|
} |
|
|
|
|
|
|
|
@@ -578,28 +721,61 @@ void MainWindow::configurePlcConnection() |
|
|
|
|
|
|
|
void MainWindow::refreshProjectUi() |
|
|
|
{ |
|
|
|
// 工程树只展示模型摘要,画布内容由 HmiEditorWidget 单独投影 |
|
|
|
const std::string current_page_id = hmi_editor_service_.firstPageId(); |
|
|
|
// 仅在当前对象消失时回退,普通刷新必须保留用户的会话选择 |
|
|
|
if (hmi_editor_service_.findPage(current_hmi_page_id_) == nullptr) |
|
|
|
{ |
|
|
|
const std::string &initial_id = project_service_.project().initialHmiPageId; |
|
|
|
current_hmi_page_id_ = hmi_editor_service_.findPage(initial_id) != nullptr |
|
|
|
? initial_id : hmi_editor_service_.firstPageId(); |
|
|
|
selected_control_id_.clear(); |
|
|
|
} |
|
|
|
if (logic_editor_service_.findLogic(current_logic_id_) == nullptr) |
|
|
|
{ |
|
|
|
current_logic_id_ = logic_editor_service_.firstLogicId(); |
|
|
|
selected_logic_node_id_.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
if (hmi_editor_widget_ != nullptr) |
|
|
|
{ |
|
|
|
hmi_editor_widget_->setPageId(current_page_id); |
|
|
|
hmi_editor_widget_->setPageId(current_hmi_page_id_); |
|
|
|
} |
|
|
|
const HmiPage *page = hmi_editor_service_.findPage(current_page_id); |
|
|
|
const std::string current_logic_id = logic_editor_service_.firstLogicId(); |
|
|
|
const HmiPage *page = hmi_editor_service_.findPage(current_hmi_page_id_); |
|
|
|
if (logic_editor_widget_ != nullptr) |
|
|
|
{ |
|
|
|
logic_editor_widget_->setLogicId(current_logic_id); |
|
|
|
logic_editor_widget_->setLogicId(current_logic_id_); |
|
|
|
} |
|
|
|
if (runtime_monitor_widget_ != nullptr) |
|
|
|
if (runtime_monitor_widget_ != nullptr |
|
|
|
&& runtime_mode_service_.mode() != ApplicationMode::Editing) |
|
|
|
{ |
|
|
|
runtime_monitor_widget_->setProjectObjects(current_page_id, current_logic_id); |
|
|
|
runtime_monitor_widget_->setProjectObjects( |
|
|
|
hmi_navigation_service_->currentPageId(), current_logic_id_); |
|
|
|
} |
|
|
|
runtime_mode_service_.refreshPlcPollAddresses(); |
|
|
|
|
|
|
|
const QSignalBlocker blocker(ui_->projectTree); |
|
|
|
ui_->projectTree->clear(); |
|
|
|
auto *hmi_root = new QTreeWidgetItem(ui_->projectTree, {tr("HMI 页面")}); |
|
|
|
hmi_root->setData(0, kProjectTreeKindRole, |
|
|
|
static_cast<int>(ProjectTreeItemKind::Root)); |
|
|
|
QTreeWidgetItem *selected_tree_item = nullptr; |
|
|
|
for (const HmiPage &candidate : project_service_.project().hmiPages) |
|
|
|
{ |
|
|
|
const QString initial_suffix = candidate.id |
|
|
|
== project_service_.project().initialHmiPageId |
|
|
|
? tr("(初始)") : QString{}; |
|
|
|
auto *item = new QTreeWidgetItem( |
|
|
|
hmi_root, {fromUtf8(candidate.name) + initial_suffix}); |
|
|
|
item->setData(0, kProjectTreeKindRole, |
|
|
|
static_cast<int>(ProjectTreeItemKind::HmiPage)); |
|
|
|
item->setData(0, kProjectTreeIdRole, fromUtf8(candidate.id)); |
|
|
|
if (candidate.id == current_hmi_page_id_ |
|
|
|
&& ui_->editorTabWidget->currentIndex() == 0) |
|
|
|
{ |
|
|
|
selected_tree_item = item; |
|
|
|
} |
|
|
|
} |
|
|
|
if (page != nullptr) |
|
|
|
{ |
|
|
|
hmi_root->addChild(new QTreeWidgetItem(hmi_root, {fromUtf8(page->name)})); |
|
|
|
ui_->hmiPageTitleLabel->setText(fromUtf8(page->name)); |
|
|
|
ui_->hmiPageSizeLabel->setText( |
|
|
|
tr("%1 x %2").arg(page->width).arg(page->height)); |
|
|
|
@@ -610,13 +786,311 @@ void MainWindow::refreshProjectUi() |
|
|
|
ui_->hmiPageSizeLabel->clear(); |
|
|
|
} |
|
|
|
auto *logic_root = new QTreeWidgetItem(ui_->projectTree, {tr("控制逻辑")}); |
|
|
|
logic_root->setData(0, kProjectTreeKindRole, |
|
|
|
static_cast<int>(ProjectTreeItemKind::Root)); |
|
|
|
for (const ControlLogic &logic : project_service_.project().controlLogics) |
|
|
|
{ |
|
|
|
const QString suffix = logic.enabled ? QString{} : tr("(已禁用)"); |
|
|
|
logic_root->addChild(new QTreeWidgetItem( |
|
|
|
logic_root, {fromUtf8(logic.name) + suffix})); |
|
|
|
auto *item = new QTreeWidgetItem( |
|
|
|
logic_root, {fromUtf8(logic.name) + suffix}); |
|
|
|
item->setData(0, kProjectTreeKindRole, |
|
|
|
static_cast<int>(ProjectTreeItemKind::ControlLogic)); |
|
|
|
item->setData(0, kProjectTreeIdRole, fromUtf8(logic.id)); |
|
|
|
if (logic.id == current_logic_id_ |
|
|
|
&& ui_->editorTabWidget->currentIndex() == 1) |
|
|
|
{ |
|
|
|
selected_tree_item = item; |
|
|
|
} |
|
|
|
} |
|
|
|
ui_->projectTree->expandAll(); |
|
|
|
if (selected_tree_item != nullptr) |
|
|
|
{ |
|
|
|
ui_->projectTree->setCurrentItem(selected_tree_item); |
|
|
|
} |
|
|
|
updateProjectTreeActions(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::handleProjectTreeSelection() |
|
|
|
{ |
|
|
|
QTreeWidgetItem *item = ui_->projectTree->currentItem(); |
|
|
|
if (item == nullptr) |
|
|
|
{ |
|
|
|
updateProjectTreeActions(); |
|
|
|
return; |
|
|
|
} |
|
|
|
const auto kind = static_cast<ProjectTreeItemKind>( |
|
|
|
item->data(0, kProjectTreeKindRole).toInt()); |
|
|
|
const std::string id = toUtf8(item->data(0, kProjectTreeIdRole).toString()); |
|
|
|
if (kind == ProjectTreeItemKind::HmiPage |
|
|
|
&& hmi_editor_service_.findPage(id) != nullptr) |
|
|
|
{ |
|
|
|
current_hmi_page_id_ = id; |
|
|
|
selected_control_id_.clear(); |
|
|
|
hmi_editor_widget_->setPageId(id); |
|
|
|
hmi_editor_widget_->reloadPage(); |
|
|
|
ui_->editorTabWidget->setCurrentWidget(ui_->hmiEditorTab); |
|
|
|
showControlProperties({}); |
|
|
|
const HmiPage *page = hmi_editor_service_.findPage(id); |
|
|
|
ui_->hmiPageTitleLabel->setText(fromUtf8(page->name)); |
|
|
|
ui_->hmiPageSizeLabel->setText( |
|
|
|
tr("%1 x %2").arg(page->width).arg(page->height)); |
|
|
|
} |
|
|
|
else if (kind == ProjectTreeItemKind::ControlLogic |
|
|
|
&& logic_editor_service_.findLogic(id) != nullptr) |
|
|
|
{ |
|
|
|
current_logic_id_ = id; |
|
|
|
selected_logic_node_id_.clear(); |
|
|
|
logic_editor_widget_->setLogicId(id); |
|
|
|
logic_editor_widget_->reloadLogic(); |
|
|
|
ui_->editorTabWidget->setCurrentWidget(ui_->logicEditorTab); |
|
|
|
showLogicNodeProperties({}); |
|
|
|
} |
|
|
|
updateProjectTreeActions(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::updateProjectTreeActions() |
|
|
|
{ |
|
|
|
if (add_page_action_ == nullptr) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
QTreeWidgetItem *item = ui_->projectTree->currentItem(); |
|
|
|
const auto kind = item == nullptr ? ProjectTreeItemKind::Root |
|
|
|
: static_cast<ProjectTreeItemKind>( |
|
|
|
item->data(0, kProjectTreeKindRole).toInt()); |
|
|
|
const bool page_selected = kind == ProjectTreeItemKind::HmiPage; |
|
|
|
const bool logic_selected = kind == ProjectTreeItemKind::ControlLogic; |
|
|
|
const bool editable = runtime_mode_service_.policy().allowsProjectEditing; |
|
|
|
add_page_action_->setEnabled(editable); |
|
|
|
add_logic_action_->setEnabled(editable); |
|
|
|
rename_project_item_action_->setEnabled( |
|
|
|
editable && (page_selected || logic_selected)); |
|
|
|
delete_project_item_action_->setEnabled( |
|
|
|
editable && (page_selected || logic_selected)); |
|
|
|
move_project_item_up_action_->setEnabled( |
|
|
|
editable && (page_selected || logic_selected)); |
|
|
|
move_project_item_down_action_->setEnabled( |
|
|
|
editable && (page_selected || logic_selected)); |
|
|
|
set_initial_page_action_->setEnabled(editable && page_selected); |
|
|
|
toggle_logic_enabled_action_->setEnabled(editable && logic_selected); |
|
|
|
if (logic_selected) |
|
|
|
{ |
|
|
|
const std::string id = toUtf8(item->data(0, kProjectTreeIdRole).toString()); |
|
|
|
const ControlLogic *logic = logic_editor_service_.findLogic(id); |
|
|
|
toggle_logic_enabled_action_->setText( |
|
|
|
logic != nullptr && logic->enabled |
|
|
|
? tr("禁用控制逻辑") : tr("启用控制逻辑")); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::addPage() |
|
|
|
{ |
|
|
|
const QString name = QInputDialog::getText( |
|
|
|
this, tr("新建页面"), tr("页面名称")); |
|
|
|
if (name.isEmpty()) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
const HmiEditorResult result = hmi_editor_service_.addPage(toUtf8(name)); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("新建页面"), fromUtf8(result.message), false); |
|
|
|
return; |
|
|
|
} |
|
|
|
current_hmi_page_id_ = result.id; |
|
|
|
selected_control_id_.clear(); |
|
|
|
ui_->editorTabWidget->setCurrentWidget(ui_->hmiEditorTab); |
|
|
|
refreshProjectUi(); |
|
|
|
hmi_editor_widget_->reloadPage(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::addLogic() |
|
|
|
{ |
|
|
|
const QString name = QInputDialog::getText( |
|
|
|
this, tr("新建控制逻辑"), tr("逻辑名称")); |
|
|
|
if (name.isEmpty()) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
const LogicEditorResult result = logic_editor_service_.addLogic(toUtf8(name)); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("新建控制逻辑"), fromUtf8(result.message), false); |
|
|
|
return; |
|
|
|
} |
|
|
|
current_logic_id_ = result.id; |
|
|
|
selected_logic_node_id_.clear(); |
|
|
|
ui_->editorTabWidget->setCurrentWidget(ui_->logicEditorTab); |
|
|
|
refreshProjectUi(); |
|
|
|
logic_editor_widget_->reloadLogic(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::renameProjectItem() |
|
|
|
{ |
|
|
|
QTreeWidgetItem *item = ui_->projectTree->currentItem(); |
|
|
|
if (item == nullptr) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
const auto kind = static_cast<ProjectTreeItemKind>( |
|
|
|
item->data(0, kProjectTreeKindRole).toInt()); |
|
|
|
const std::string id = toUtf8(item->data(0, kProjectTreeIdRole).toString()); |
|
|
|
QString current_name; |
|
|
|
if (kind == ProjectTreeItemKind::HmiPage) |
|
|
|
{ |
|
|
|
const HmiPage *page = hmi_editor_service_.findPage(id); |
|
|
|
current_name = page == nullptr ? QString{} : fromUtf8(page->name); |
|
|
|
} |
|
|
|
else if (kind == ProjectTreeItemKind::ControlLogic) |
|
|
|
{ |
|
|
|
const ControlLogic *logic = logic_editor_service_.findLogic(id); |
|
|
|
current_name = logic == nullptr ? QString{} : fromUtf8(logic->name); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
bool accepted = false; |
|
|
|
const QString name = QInputDialog::getText( |
|
|
|
this, tr("重命名"), tr("新名称"), QLineEdit::Normal, |
|
|
|
current_name, &accepted); |
|
|
|
if (!accepted) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
if (kind == ProjectTreeItemKind::HmiPage) |
|
|
|
{ |
|
|
|
const HmiEditorResult result = hmi_editor_service_.renamePage(id, toUtf8(name)); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("重命名页面"), fromUtf8(result.message), false); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
const LogicEditorResult result = logic_editor_service_.renameLogic(id, toUtf8(name)); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("重命名控制逻辑"), fromUtf8(result.message), false); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
refreshProjectUi(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::deleteProjectItem() |
|
|
|
{ |
|
|
|
QTreeWidgetItem *item = ui_->projectTree->currentItem(); |
|
|
|
if (item == nullptr) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
const auto kind = static_cast<ProjectTreeItemKind>( |
|
|
|
item->data(0, kProjectTreeKindRole).toInt()); |
|
|
|
const std::string id = toUtf8(item->data(0, kProjectTreeIdRole).toString()); |
|
|
|
if (kind == ProjectTreeItemKind::HmiPage) |
|
|
|
{ |
|
|
|
const HmiEditorResult result = hmi_editor_service_.removePage(id); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("删除页面"), fromUtf8(result.message), false); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (kind == ProjectTreeItemKind::ControlLogic) |
|
|
|
{ |
|
|
|
const LogicEditorResult result = logic_editor_service_.removeLogic(id); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("删除控制逻辑"), fromUtf8(result.message), false); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
refreshProjectUi(); |
|
|
|
showControlProperties({}); |
|
|
|
showLogicNodeProperties({}); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::moveProjectItem(int offset) |
|
|
|
{ |
|
|
|
QTreeWidgetItem *item = ui_->projectTree->currentItem(); |
|
|
|
if (item == nullptr) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
const auto kind = static_cast<ProjectTreeItemKind>( |
|
|
|
item->data(0, kProjectTreeKindRole).toInt()); |
|
|
|
const std::string id = toUtf8(item->data(0, kProjectTreeIdRole).toString()); |
|
|
|
if (kind == ProjectTreeItemKind::HmiPage) |
|
|
|
{ |
|
|
|
const HmiEditorResult result = hmi_editor_service_.movePage(id, offset); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
statusBar()->showMessage(fromUtf8(result.message), 4000); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (kind == ProjectTreeItemKind::ControlLogic) |
|
|
|
{ |
|
|
|
const LogicEditorResult result = logic_editor_service_.moveLogic(id, offset); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
statusBar()->showMessage(fromUtf8(result.message), 4000); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
refreshProjectUi(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::setSelectedPageAsInitial() |
|
|
|
{ |
|
|
|
QTreeWidgetItem *item = ui_->projectTree->currentItem(); |
|
|
|
if (item == nullptr |
|
|
|
|| static_cast<ProjectTreeItemKind>( |
|
|
|
item->data(0, kProjectTreeKindRole).toInt()) |
|
|
|
!= ProjectTreeItemKind::HmiPage) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
const HmiEditorResult result = hmi_editor_service_.setInitialPage( |
|
|
|
toUtf8(item->data(0, kProjectTreeIdRole).toString())); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("设置初始页面"), fromUtf8(result.message), false); |
|
|
|
return; |
|
|
|
} |
|
|
|
refreshProjectUi(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::toggleSelectedLogicEnabled() |
|
|
|
{ |
|
|
|
QTreeWidgetItem *item = ui_->projectTree->currentItem(); |
|
|
|
if (item == nullptr |
|
|
|
|| static_cast<ProjectTreeItemKind>( |
|
|
|
item->data(0, kProjectTreeKindRole).toInt()) |
|
|
|
!= ProjectTreeItemKind::ControlLogic) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
const std::string id = toUtf8(item->data(0, kProjectTreeIdRole).toString()); |
|
|
|
const ControlLogic *logic = logic_editor_service_.findLogic(id); |
|
|
|
if (logic == nullptr) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
const LogicEditorResult result = logic_editor_service_.setLogicEnabled( |
|
|
|
id, !logic->enabled); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("启停控制逻辑"), fromUtf8(result.message), false); |
|
|
|
return; |
|
|
|
} |
|
|
|
refreshProjectUi(); |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::connectPlc() |
|
|
|
@@ -682,14 +1156,16 @@ void MainWindow::showControlProperties(const std::string &control_id) |
|
|
|
|
|
|
|
// 在第一页画面中,根据ID查找目标控件,获取只读模型指针 |
|
|
|
const HmiControl *control = hmi_editor_service_.findControl( |
|
|
|
hmi_editor_service_.firstPageId(), control_id); |
|
|
|
current_hmi_page_id_, control_id); |
|
|
|
// 判断是否查询到有效控件 |
|
|
|
const bool has_control = control != nullptr; |
|
|
|
|
|
|
|
// 更新属性面板顶部状态标签,显示选中控件ID或提示未选择 |
|
|
|
ui_->selectionValueLabel->setText( |
|
|
|
has_control ? fromUtf8(control->id) |
|
|
|
+ (control->isConfigured() ? QString{} : tr("(未绑定)")) |
|
|
|
+ (control->isConfigured() ? QString{} |
|
|
|
: control->type == HmiControlType::PageJump |
|
|
|
? tr("(未配置)") : tr("(未绑定)")) |
|
|
|
: tr("未选择")); |
|
|
|
|
|
|
|
// 批量控制所有属性编辑组件可用性:无选中控件时整体置灰,禁止编辑 |
|
|
|
@@ -701,6 +1177,7 @@ void MainWindow::showControlProperties(const std::string &control_id) |
|
|
|
static_cast<QWidget *>(ui_->controlHeightSpinBox), |
|
|
|
static_cast<QWidget *>(ui_->bindingAreaComboBox), |
|
|
|
static_cast<QWidget *>(ui_->bindingIndexSpinBox), |
|
|
|
static_cast<QWidget *>(ui_->targetPageComboBox), |
|
|
|
static_cast<QWidget *>(ui_->buttonOperationComboBox), |
|
|
|
static_cast<QWidget *>(ui_->applyPropertiesButton)}) |
|
|
|
{ |
|
|
|
@@ -710,6 +1187,12 @@ void MainWindow::showControlProperties(const std::string &control_id) |
|
|
|
// 未选中有效控件,无需填充属性,直接退出 |
|
|
|
if (!has_control) |
|
|
|
{ |
|
|
|
ui_->bindingAreaLabel->setVisible(false); |
|
|
|
ui_->bindingAreaComboBox->setVisible(false); |
|
|
|
ui_->bindingIndexLabel->setVisible(false); |
|
|
|
ui_->bindingIndexSpinBox->setVisible(false); |
|
|
|
ui_->targetPageLabel->setVisible(false); |
|
|
|
ui_->targetPageComboBox->setVisible(false); |
|
|
|
ui_->buttonOperationLabel->setVisible(false); |
|
|
|
ui_->buttonOperationComboBox->setVisible(false); |
|
|
|
return; |
|
|
|
@@ -731,6 +1214,12 @@ void MainWindow::showControlProperties(const std::string &control_id) |
|
|
|
: control->binding->area() == RegisterArea::M ? 1 : 2); |
|
|
|
ui_->bindingIndexSpinBox->setValue( |
|
|
|
control->binding.has_value() ? control->binding->index() : 0); |
|
|
|
const bool has_binding = control->type != HmiControlType::Label |
|
|
|
&& control->type != HmiControlType::PageJump; |
|
|
|
ui_->bindingAreaLabel->setVisible(has_binding); |
|
|
|
ui_->bindingAreaComboBox->setVisible(has_binding); |
|
|
|
ui_->bindingIndexLabel->setVisible(has_binding); |
|
|
|
ui_->bindingIndexSpinBox->setVisible(has_binding); |
|
|
|
const bool is_button = control->type == HmiControlType::Button; |
|
|
|
ui_->buttonOperationLabel->setVisible(is_button); |
|
|
|
ui_->buttonOperationComboBox->setVisible(is_button); |
|
|
|
@@ -738,6 +1227,23 @@ void MainWindow::showControlProperties(const std::string &control_id) |
|
|
|
ui_->buttonOperationComboBox->setCurrentIndex( |
|
|
|
ui_->buttonOperationComboBox->findData( |
|
|
|
static_cast<int>(control->buttonOperation))); |
|
|
|
const bool is_page_jump = control->type == HmiControlType::PageJump; |
|
|
|
ui_->targetPageLabel->setVisible(is_page_jump); |
|
|
|
ui_->targetPageComboBox->setVisible(is_page_jump); |
|
|
|
ui_->targetPageComboBox->setEnabled(is_page_jump); |
|
|
|
ui_->targetPageComboBox->clear(); |
|
|
|
if (is_page_jump) |
|
|
|
{ |
|
|
|
for (const HmiPage &page : project_service_.project().hmiPages) |
|
|
|
{ |
|
|
|
ui_->targetPageComboBox->addItem( |
|
|
|
fromUtf8(page.name), fromUtf8(page.id)); |
|
|
|
} |
|
|
|
const std::string target_id = control->pageJump.has_value() |
|
|
|
? control->pageJump->targetPageId : std::string{}; |
|
|
|
ui_->targetPageComboBox->setCurrentIndex( |
|
|
|
ui_->targetPageComboBox->findData(fromUtf8(target_id))); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void MainWindow::showLogicNodeProperties(const std::string &node_id) |
|
|
|
@@ -745,7 +1251,7 @@ void MainWindow::showLogicNodeProperties(const std::string &node_id) |
|
|
|
ui_->propertyStack->setCurrentWidget(ui_->logicPropertiesPage); |
|
|
|
selected_logic_node_id_ = node_id; |
|
|
|
const LogicNode *node = logic_editor_service_.findNode( |
|
|
|
logic_editor_service_.firstLogicId(), node_id); |
|
|
|
current_logic_id_, node_id); |
|
|
|
const bool has_node = node != nullptr; |
|
|
|
ui_->selectionValueLabel->setText( |
|
|
|
has_node ? fromUtf8(node->id) : tr("未选择")); |
|
|
|
@@ -827,8 +1333,8 @@ void MainWindow::showLogicNodeProperties(const std::string &node_id) |
|
|
|
|
|
|
|
void MainWindow::addHmiControl(HmiControlType type) |
|
|
|
{ |
|
|
|
const std::string page_id = hmi_editor_service_.firstPageId(); |
|
|
|
const HmiEditorResult result = hmi_editor_service_.addControl(page_id, type); |
|
|
|
const HmiEditorResult result = hmi_editor_service_.addControl( |
|
|
|
current_hmi_page_id_, type); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("添加控件"), fromUtf8(result.message), false); |
|
|
|
@@ -848,7 +1354,7 @@ void MainWindow::deleteSelectedControl() |
|
|
|
return; |
|
|
|
} |
|
|
|
const HmiEditorResult result = hmi_editor_service_.removeControl( |
|
|
|
hmi_editor_service_.firstPageId(), selected_control_id_); |
|
|
|
current_hmi_page_id_, selected_control_id_); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("删除控件"), fromUtf8(result.message), false); |
|
|
|
@@ -863,7 +1369,7 @@ void MainWindow::deleteSelectedControl() |
|
|
|
void MainWindow::applySelectedControlProperties() |
|
|
|
{ |
|
|
|
const HmiControl *old_control = hmi_editor_service_.findControl( |
|
|
|
hmi_editor_service_.firstPageId(), selected_control_id_); |
|
|
|
current_hmi_page_id_, selected_control_id_); |
|
|
|
if (old_control == nullptr) |
|
|
|
{ |
|
|
|
return; |
|
|
|
@@ -876,23 +1382,38 @@ void MainWindow::applySelectedControlProperties() |
|
|
|
control.bounds.y = ui_->controlYSpinBox->value(); |
|
|
|
control.bounds.width = ui_->controlWidthSpinBox->value(); |
|
|
|
control.bounds.height = ui_->controlHeightSpinBox->value(); |
|
|
|
const int binding_area = ui_->bindingAreaComboBox->currentData().toInt(); |
|
|
|
if (binding_area < 0) |
|
|
|
if (control.type == HmiControlType::Label |
|
|
|
|| control.type == HmiControlType::PageJump) |
|
|
|
{ |
|
|
|
control.binding.reset(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
const RegisterArea area = binding_area == 0 ? RegisterArea::M : RegisterArea::D; |
|
|
|
control.binding = RegisterAddress{area, ui_->bindingIndexSpinBox->value()}; |
|
|
|
const int binding_area = ui_->bindingAreaComboBox->currentData().toInt(); |
|
|
|
if (binding_area < 0) |
|
|
|
{ |
|
|
|
control.binding.reset(); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
const RegisterArea area = binding_area == 0 |
|
|
|
? RegisterArea::M : RegisterArea::D; |
|
|
|
control.binding = RegisterAddress{ |
|
|
|
area, ui_->bindingIndexSpinBox->value()}; |
|
|
|
} |
|
|
|
} |
|
|
|
if (control.type == HmiControlType::Button) |
|
|
|
{ |
|
|
|
control.buttonOperation = static_cast<HmiButtonOperation>( |
|
|
|
ui_->buttonOperationComboBox->currentData().toInt()); |
|
|
|
} |
|
|
|
if (control.type == HmiControlType::PageJump) |
|
|
|
{ |
|
|
|
control.pageJump = HmiPageJumpConfig{ |
|
|
|
toUtf8(ui_->targetPageComboBox->currentData().toString())}; |
|
|
|
} |
|
|
|
const HmiEditorResult result = hmi_editor_service_.updateControl( |
|
|
|
hmi_editor_service_.firstPageId(), selected_control_id_, control); |
|
|
|
current_hmi_page_id_, selected_control_id_, control); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("应用属性"), fromUtf8(result.message), false); |
|
|
|
@@ -975,9 +1496,8 @@ void MainWindow::deleteSelectedLogicObject() |
|
|
|
|
|
|
|
void MainWindow::applySelectedLogicNodeProperties() |
|
|
|
{ |
|
|
|
const std::string logic_id = logic_editor_service_.firstLogicId(); |
|
|
|
const LogicNode *node = logic_editor_service_.findNode( |
|
|
|
logic_id, selected_logic_node_id_); |
|
|
|
current_logic_id_, selected_logic_node_id_); |
|
|
|
if (node == nullptr) |
|
|
|
{ |
|
|
|
return; |
|
|
|
@@ -1006,7 +1526,7 @@ void MainWindow::applySelectedLogicNodeProperties() |
|
|
|
} |
|
|
|
|
|
|
|
const LogicEditorResult result = logic_editor_service_.updateNodeConfig( |
|
|
|
logic_id, selected_logic_node_id_, config); |
|
|
|
current_logic_id_, selected_logic_node_id_, config); |
|
|
|
if (!result.succeeded) |
|
|
|
{ |
|
|
|
showProjectResult(tr("应用逻辑属性"), fromUtf8(result.message), false); |
|
|
|
@@ -1037,6 +1557,8 @@ void MainWindow::createNewProject() |
|
|
|
logic_editor_service_.ensureDefaultLogic(); |
|
|
|
selected_control_id_.clear(); |
|
|
|
selected_logic_node_id_.clear(); |
|
|
|
current_hmi_page_id_ = project_service_.project().initialHmiPageId; |
|
|
|
current_logic_id_ = logic_editor_service_.firstLogicId(); |
|
|
|
refreshProjectUi(); |
|
|
|
hmi_editor_widget_->reloadPage(); |
|
|
|
logic_editor_widget_->reloadLogic(); |
|
|
|
@@ -1086,6 +1608,8 @@ void MainWindow::loadProject() |
|
|
|
} |
|
|
|
selected_control_id_.clear(); |
|
|
|
selected_logic_node_id_.clear(); |
|
|
|
current_hmi_page_id_ = project_service_.project().initialHmiPageId; |
|
|
|
current_logic_id_ = logic_editor_service_.firstLogicId(); |
|
|
|
refreshProjectUi(); |
|
|
|
hmi_editor_widget_->reloadPage(); |
|
|
|
logic_editor_widget_->reloadLogic(); |
|
|
|
@@ -1165,14 +1689,28 @@ void MainWindow::updateModeUi(const QString &message) |
|
|
|
ui_->editorTabWidget->setTabVisible(2, running); |
|
|
|
if (running) |
|
|
|
{ |
|
|
|
if (hmi_navigation_service_->currentPageId().empty()) |
|
|
|
{ |
|
|
|
const HmiNavigationResult navigation = hmi_navigation_service_->start(); |
|
|
|
if (!navigation.succeeded) |
|
|
|
{ |
|
|
|
statusBar()->showMessage(fromUtf8(navigation.message), 5000); |
|
|
|
} |
|
|
|
} |
|
|
|
runtime_monitor_widget_->setProjectObjects( |
|
|
|
hmi_editor_service_.firstPageId(), logic_editor_service_.firstLogicId()); |
|
|
|
hmi_navigation_service_->currentPageId(), current_logic_id_); |
|
|
|
runtime_monitor_widget_->setMode(mode, runtime_mode_service_.plcConnectionState()); |
|
|
|
ui_->editorTabWidget->setCurrentWidget(ui_->runtimeMonitorTab); |
|
|
|
} |
|
|
|
else if (ui_->editorTabWidget->currentWidget() == ui_->runtimeMonitorTab) |
|
|
|
else |
|
|
|
{ |
|
|
|
ui_->editorTabWidget->setCurrentIndex(last_editing_tab_index_); |
|
|
|
hmi_navigation_service_->stop(); |
|
|
|
runtime_monitor_widget_->setMode( |
|
|
|
mode, runtime_mode_service_.plcConnectionState()); |
|
|
|
if (ui_->editorTabWidget->currentWidget() == ui_->runtimeMonitorTab) |
|
|
|
{ |
|
|
|
ui_->editorTabWidget->setCurrentIndex(last_editing_tab_index_); |
|
|
|
} |
|
|
|
} |
|
|
|
// 将同一份模式策略同步到所有可编辑入口,避免只禁用部分操作 |
|
|
|
ui_->projectDock->setEnabled(policy.allowsProjectEditing); |
|
|
|
@@ -1191,6 +1729,8 @@ void MainWindow::updateModeUi(const QString &message) |
|
|
|
ui_->addIndicatorAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
ui_->addNumericDisplayAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
ui_->addNumericInputAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
ui_->addLabelAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
ui_->addPageJumpAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
ui_->deleteControlAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
ui_->addNormallyOpenAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
ui_->addNormallyClosedAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
@@ -1203,6 +1743,7 @@ void MainWindow::updateModeUi(const QString &message) |
|
|
|
ui_->saveProjectAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
ui_->saveAsProjectAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
ui_->loadProjectAction->setEnabled(policy.allowsProjectEditing); |
|
|
|
updateProjectTreeActions(); |
|
|
|
|
|
|
|
mode_status_label_->setText(modeText(mode)); |
|
|
|
if (mode == ApplicationMode::Editing) |
|
|
|
@@ -1300,8 +1841,17 @@ void MainWindow::updateSimulationUi(bool report_fault) |
|
|
|
if (report_fault) |
|
|
|
{ |
|
|
|
const LogicScanResult &error = runtime_mode_service_.simulationError(); |
|
|
|
if (!error.logicId.empty() |
|
|
|
&& logic_editor_service_.findLogic(error.logicId) != nullptr) |
|
|
|
{ |
|
|
|
current_logic_id_ = error.logicId; |
|
|
|
logic_editor_widget_->setLogicId(current_logic_id_); |
|
|
|
runtime_monitor_widget_->setProjectObjects( |
|
|
|
hmi_navigation_service_->currentPageId(), current_logic_id_); |
|
|
|
} |
|
|
|
logic_editor_widget_->setRuntimeTrace( |
|
|
|
runtime_mode_service_.offlineSimulationService().traceSnapshot(), |
|
|
|
runtime_mode_service_.offlineSimulationService() |
|
|
|
.traceSnapshot().forLogic(current_logic_id_), |
|
|
|
error.nodeId); |
|
|
|
runtime_monitor_widget_->setLogicTrace( |
|
|
|
runtime_mode_service_.offlineSimulationService().traceSnapshot(), |
|
|
|
|