| @@ -32,6 +32,7 @@ SOURCES += \ | |||||
| src/domain/register_monitor_model.cpp \ | src/domain/register_monitor_model.cpp \ | ||||
| src/domain/alarm_model.cpp \ | src/domain/alarm_model.cpp \ | ||||
| src/domain/hmi_model.cpp \ | src/domain/hmi_model.cpp \ | ||||
| src/domain/hmi_control_registry.cpp \ | |||||
| src/domain/control_logic_model.cpp \ | src/domain/control_logic_model.cpp \ | ||||
| src/domain/project_model.cpp \ | src/domain/project_model.cpp \ | ||||
| src/domain/runtime_state.cpp \ | src/domain/runtime_state.cpp \ | ||||
| @@ -71,6 +72,7 @@ HEADERS += \ | |||||
| src/domain/register_monitor_model.h \ | src/domain/register_monitor_model.h \ | ||||
| src/domain/alarm_model.h \ | src/domain/alarm_model.h \ | ||||
| src/domain/hmi_model.h \ | src/domain/hmi_model.h \ | ||||
| src/domain/hmi_control_registry.h \ | |||||
| src/domain/control_logic_model.h \ | src/domain/control_logic_model.h \ | ||||
| src/domain/project_model.h \ | src/domain/project_model.h \ | ||||
| src/domain/runtime_state.h \ | src/domain/runtime_state.h \ | ||||
| @@ -0,0 +1,125 @@ | |||||
| #include "hmi_control_registry.h" | |||||
| #include <algorithm> | |||||
| #include <array> | |||||
| #include <cstddef> | |||||
| namespace { | |||||
| constexpr std::array kControlDescriptors = { | |||||
| HmiControlDescriptor{HmiControlType::Button, | |||||
| "button", | |||||
| "按钮", | |||||
| "button", | |||||
| "按钮", | |||||
| {0, 0, 120, 40}, | |||||
| HmiBindingKind::Bit, | |||||
| HmiRuntimeValueKind::Bit, | |||||
| true}, | |||||
| HmiControlDescriptor{HmiControlType::Indicator, | |||||
| "indicator", | |||||
| "指示灯", | |||||
| "indicator", | |||||
| "指示灯", | |||||
| {0, 0, 64, 64}, | |||||
| HmiBindingKind::Bit, | |||||
| HmiRuntimeValueKind::Bit, | |||||
| true}, | |||||
| HmiControlDescriptor{HmiControlType::NumericDisplay, | |||||
| "numericDisplay", | |||||
| "数值显示", | |||||
| "numeric-display", | |||||
| "数值显示", | |||||
| {0, 0, 120, 40}, | |||||
| HmiBindingKind::Word, | |||||
| HmiRuntimeValueKind::Word, | |||||
| true}, | |||||
| HmiControlDescriptor{HmiControlType::NumericInput, | |||||
| "numericInput", | |||||
| "数值输入", | |||||
| "numeric-input", | |||||
| "数值输入", | |||||
| {0, 0, 120, 40}, | |||||
| HmiBindingKind::Word, | |||||
| HmiRuntimeValueKind::Word, | |||||
| true}, | |||||
| HmiControlDescriptor{HmiControlType::Label, | |||||
| "label", | |||||
| "文本", | |||||
| "label", | |||||
| "文本", | |||||
| {0, 0, 120, 40}, | |||||
| HmiBindingKind::None, | |||||
| HmiRuntimeValueKind::None, | |||||
| false}, | |||||
| HmiControlDescriptor{HmiControlType::PageJump, | |||||
| "pageJump", | |||||
| "页面跳转", | |||||
| "page-jump", | |||||
| "页面跳转", | |||||
| {0, 0, 120, 40}, | |||||
| HmiBindingKind::None, | |||||
| HmiRuntimeValueKind::None, | |||||
| false}, | |||||
| HmiControlDescriptor{HmiControlType::AlarmList, | |||||
| "alarmList", | |||||
| "报警列表", | |||||
| "alarm-list", | |||||
| "报警信息", | |||||
| {0, 0, 360, 180}, | |||||
| HmiBindingKind::None, | |||||
| HmiRuntimeValueKind::None, | |||||
| false} | |||||
| }; | |||||
| static_assert( | |||||
| kControlDescriptors.size() | |||||
| == static_cast<std::size_t>(HmiControlType::Count), | |||||
| "每个 HMI 控件类型都必须注册描述"); | |||||
| } // namespace | |||||
| const HmiControlDescriptor *findHmiControlDescriptor(HmiControlType type) | |||||
| { | |||||
| const auto descriptor = std::find_if( | |||||
| kControlDescriptors.cbegin(), | |||||
| kControlDescriptors.cend(), | |||||
| [type](const HmiControlDescriptor &candidate) | |||||
| { | |||||
| return candidate.type == type; | |||||
| }); | |||||
| return descriptor == kControlDescriptors.cend() ? nullptr : &*descriptor; | |||||
| } | |||||
| const HmiControlDescriptor *findHmiControlDescriptor( | |||||
| std::string_view storage_name) | |||||
| { | |||||
| const auto descriptor = std::find_if( | |||||
| kControlDescriptors.cbegin(), | |||||
| kControlDescriptors.cend(), | |||||
| [storage_name](const HmiControlDescriptor &candidate) | |||||
| { | |||||
| return storage_name == candidate.storageName; | |||||
| }); | |||||
| return descriptor == kControlDescriptors.cend() ? nullptr : &*descriptor; | |||||
| } | |||||
| std::optional<RegisterArea> hmiBindingArea(HmiBindingKind binding_kind) | |||||
| { | |||||
| switch (binding_kind) | |||||
| { | |||||
| case HmiBindingKind::Bit: | |||||
| { | |||||
| return RegisterArea::M; | |||||
| } | |||||
| case HmiBindingKind::Word: | |||||
| { | |||||
| return RegisterArea::D; | |||||
| } | |||||
| case HmiBindingKind::None: | |||||
| default: | |||||
| { | |||||
| return std::nullopt; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,68 @@ | |||||
| /** | |||||
| * @file hmi_control_registry.h | |||||
| * @brief 定义 HMI 控件公共描述及查询接口 | |||||
| * @author suyu | |||||
| * @date 2026-08-17 | |||||
| */ | |||||
| #pragma once | |||||
| #include "hmi_model.h" | |||||
| #include <optional> | |||||
| #include <string_view> | |||||
| /** | |||||
| * @brief 控件允许绑定的寄存器数据类型 | |||||
| */ | |||||
| enum class HmiBindingKind | |||||
| { | |||||
| None, | |||||
| Bit, | |||||
| Word | |||||
| }; | |||||
| /** | |||||
| * @brief 控件运行态读取的值类型 | |||||
| */ | |||||
| enum class HmiRuntimeValueKind | |||||
| { | |||||
| None, | |||||
| Bit, | |||||
| Word | |||||
| }; | |||||
| /** | |||||
| * @brief 保存一种 HMI 控件的稳定名称、默认值和寄存器能力 | |||||
| */ | |||||
| struct HmiControlDescriptor | |||||
| { | |||||
| HmiControlType type; | |||||
| const char *storageName; | |||||
| const char *displayName; | |||||
| const char *idPrefix; | |||||
| const char *defaultText; | |||||
| HmiRect defaultBounds; | |||||
| HmiBindingKind bindingKind; | |||||
| HmiRuntimeValueKind runtimeValueKind; | |||||
| bool requiresBindingForRunning; | |||||
| }; | |||||
| /** | |||||
| * @brief 按领域类型查找控件描述 | |||||
| * @return 找到时返回描述指针,不支持的类型返回 nullptr | |||||
| */ | |||||
| const HmiControlDescriptor *findHmiControlDescriptor(HmiControlType type); | |||||
| /** | |||||
| * @brief 按工程文件中的稳定类型名查找控件描述 | |||||
| * @return 找到时返回描述指针,未知名称返回 nullptr | |||||
| */ | |||||
| const HmiControlDescriptor *findHmiControlDescriptor( | |||||
| std::string_view storage_name); | |||||
| /** | |||||
| * @brief 返回绑定类型要求的寄存器区域 | |||||
| * @return 不支持寄存器绑定时返回空值 | |||||
| */ | |||||
| std::optional<RegisterArea> hmiBindingArea(HmiBindingKind binding_kind); | |||||
| @@ -1,5 +1,7 @@ | |||||
| #include "hmi_model.h" | #include "hmi_model.h" | ||||
| #include "hmi_control_registry.h" | |||||
| #include <algorithm> | #include <algorithm> | ||||
| namespace { | namespace { | ||||
| @@ -13,44 +15,12 @@ void setError(std::string *error, const std::string &message) | |||||
| } | } | ||||
| } | } | ||||
| // 判断控件是否必须绑定 M 区位地址 | |||||
| bool requiresBitBinding(HmiControlType type) | |||||
| { | |||||
| return type == HmiControlType::Button || type == HmiControlType::Indicator; | |||||
| } | |||||
| // 判断控件是否必须绑定 D 区字地址 | |||||
| bool requiresWordBinding(HmiControlType type) | |||||
| { | |||||
| return type == HmiControlType::NumericDisplay || type == HmiControlType::NumericInput; | |||||
| } | |||||
| bool supportsRegisterBinding(HmiControlType type) | |||||
| { | |||||
| return requiresBitBinding(type) || requiresWordBinding(type); | |||||
| } | |||||
| bool isSupportedControlType(HmiControlType type) | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case HmiControlType::Button: | |||||
| case HmiControlType::Indicator: | |||||
| case HmiControlType::NumericDisplay: | |||||
| case HmiControlType::NumericInput: | |||||
| case HmiControlType::Label: | |||||
| case HmiControlType::PageJump: | |||||
| case HmiControlType::AlarmList: | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| } // namespace | } // namespace | ||||
| bool HmiControl::validate(std::string *error) const | bool HmiControl::validate(std::string *error) const | ||||
| { | { | ||||
| if (!isSupportedControlType(type)) | |||||
| const HmiControlDescriptor *descriptor = findHmiControlDescriptor(type); | |||||
| if (descriptor == nullptr) | |||||
| { | { | ||||
| setError(error, "不支持的 HMI 控件类型"); | setError(error, "不支持的 HMI 控件类型"); | ||||
| return false; | return false; | ||||
| @@ -73,32 +43,31 @@ bool HmiControl::validate(std::string *error) const | |||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| if (requiresBitBinding(type)) | |||||
| const std::optional<RegisterArea> binding_area = | |||||
| hmiBindingArea(descriptor->bindingKind); | |||||
| if (binding.has_value() && !binding_area.has_value()) | |||||
| { | { | ||||
| if (binding.has_value() && binding->area() != RegisterArea::M) | |||||
| setError(error, "文本、页面跳转和报警列表控件不能绑定寄存器"); | |||||
| return false; | |||||
| } | |||||
| if (binding.has_value() && binding_area.has_value() | |||||
| && binding->area() != *binding_area) | |||||
| { | |||||
| if (descriptor->bindingKind == HmiBindingKind::Bit) | |||||
| { | { | ||||
| setError(error, "按钮和指示灯必须绑定 M 区地址"); | setError(error, "按钮和指示灯必须绑定 M 区地址"); | ||||
| return false; | |||||
| } | } | ||||
| } | |||||
| if (requiresWordBinding(type)) | |||||
| { | |||||
| if (binding.has_value() && binding->area() != RegisterArea::D) | |||||
| else | |||||
| { | { | ||||
| setError(error, "数值控件必须绑定 D 区地址"); | setError(error, "数值控件必须绑定 D 区地址"); | ||||
| return false; | |||||
| } | } | ||||
| return false; | |||||
| } | } | ||||
| if (binding.has_value() && !binding->isValid()) | if (binding.has_value() && !binding->isValid()) | ||||
| { | { | ||||
| setError(error, "HMI 控件绑定了无效地址"); | setError(error, "HMI 控件绑定了无效地址"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (!supportsRegisterBinding(type) && binding.has_value()) | |||||
| { | |||||
| setError(error, "文本、页面跳转和报警列表控件不能绑定寄存器"); | |||||
| return false; | |||||
| } | |||||
| if (type == HmiControlType::PageJump) | if (type == HmiControlType::PageJump) | ||||
| { | { | ||||
| if (!pageJump.has_value()) | if (!pageJump.has_value()) | ||||
| @@ -117,7 +86,13 @@ bool HmiControl::validate(std::string *error) const | |||||
| bool HmiControl::isConfigured() const | bool HmiControl::isConfigured() const | ||||
| { | { | ||||
| if (type == HmiControlType::Label || type == HmiControlType::AlarmList) | |||||
| const HmiControlDescriptor *descriptor = findHmiControlDescriptor(type); | |||||
| if (descriptor == nullptr) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| if (!descriptor->requiresBindingForRunning | |||||
| && type != HmiControlType::PageJump) | |||||
| { | { | ||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -125,15 +100,15 @@ bool HmiControl::isConfigured() const | |||||
| { | { | ||||
| return pageJump.has_value() && !pageJump->targetPageId.empty(); | return pageJump.has_value() && !pageJump->targetPageId.empty(); | ||||
| } | } | ||||
| if (!binding.has_value() || !binding->isValid()) | |||||
| if (!descriptor->requiresBindingForRunning | |||||
| || !binding.has_value() | |||||
| || !binding->isValid()) | |||||
| { | { | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (requiresBitBinding(type)) | |||||
| { | |||||
| return binding->area() == RegisterArea::M; | |||||
| } | |||||
| return !requiresWordBinding(type) || binding->area() == RegisterArea::D; | |||||
| const std::optional<RegisterArea> binding_area = | |||||
| hmiBindingArea(descriptor->bindingKind); | |||||
| return binding_area.has_value() && binding->area() == *binding_area; | |||||
| } | } | ||||
| bool HmiPage::validate(std::string *error) const | bool HmiPage::validate(std::string *error) const | ||||
| @@ -43,7 +43,8 @@ enum class HmiControlType | |||||
| NumericInput, // 数值输入 | NumericInput, // 数值输入 | ||||
| Label, // 标签 | Label, // 标签 | ||||
| PageJump, // 页面跳转 | PageJump, // 页面跳转 | ||||
| AlarmList // 报警列表 | |||||
| AlarmList, // 报警列表 | |||||
| Count // 已注册控件类型数量,不作为实际控件使用 | |||||
| }; | }; | ||||
| /** | /** | ||||
| @@ -1,5 +1,7 @@ | |||||
| #include "json_project_storage.h" | #include "json_project_storage.h" | ||||
| #include "domain/hmi_control_registry.h" | |||||
| #include <QFile> | #include <QFile> | ||||
| #include <QJsonArray> | #include <QJsonArray> | ||||
| #include <QJsonDocument> | #include <QJsonDocument> | ||||
| @@ -392,81 +394,24 @@ bool parseWordOperand( | |||||
| // 将 HMI 控件类型枚举转换为工程文件中的稳定字符串 | // 将 HMI 控件类型枚举转换为工程文件中的稳定字符串 | ||||
| QString hmiControlTypeName(HmiControlType type) | QString hmiControlTypeName(HmiControlType type) | ||||
| { | { | ||||
| switch (type) | |||||
| { | |||||
| case HmiControlType::Button: | |||||
| { | |||||
| return QStringLiteral("button"); | |||||
| } | |||||
| case HmiControlType::Indicator: | |||||
| { | |||||
| return QStringLiteral("indicator"); | |||||
| } | |||||
| case HmiControlType::NumericDisplay: | |||||
| { | |||||
| return QStringLiteral("numericDisplay"); | |||||
| } | |||||
| case HmiControlType::NumericInput: | |||||
| { | |||||
| return QStringLiteral("numericInput"); | |||||
| } | |||||
| case HmiControlType::Label: | |||||
| { | |||||
| return QStringLiteral("label"); | |||||
| } | |||||
| case HmiControlType::PageJump: | |||||
| { | |||||
| return QStringLiteral("pageJump"); | |||||
| } | |||||
| case HmiControlType::AlarmList: | |||||
| { | |||||
| return QStringLiteral("alarmList"); | |||||
| } | |||||
| default: | |||||
| { | |||||
| return {}; | |||||
| } | |||||
| } | |||||
| const HmiControlDescriptor *descriptor = findHmiControlDescriptor(type); | |||||
| return descriptor == nullptr | |||||
| ? QString{} | |||||
| : QString::fromLatin1(descriptor->storageName); | |||||
| } | } | ||||
| // 将工程文件中的控件类型字符串转换为 HMI 控件类型枚举 | // 将工程文件中的控件类型字符串转换为 HMI 控件类型枚举 | ||||
| bool parseHmiControlType( | bool parseHmiControlType( | ||||
| const std::string &value, HmiControlType *type, ParseState *state) | const std::string &value, HmiControlType *type, ParseState *state) | ||||
| { | { | ||||
| if (value == "button") | |||||
| { | |||||
| *type = HmiControlType::Button; | |||||
| } | |||||
| else if (value == "indicator") | |||||
| { | |||||
| *type = HmiControlType::Indicator; | |||||
| } | |||||
| else if (value == "numericDisplay") | |||||
| { | |||||
| *type = HmiControlType::NumericDisplay; | |||||
| } | |||||
| else if (value == "numericInput") | |||||
| { | |||||
| *type = HmiControlType::NumericInput; | |||||
| } | |||||
| else if (value == "label") | |||||
| { | |||||
| *type = HmiControlType::Label; | |||||
| } | |||||
| else if (value == "pageJump") | |||||
| { | |||||
| *type = HmiControlType::PageJump; | |||||
| } | |||||
| else if (value == "alarmList") | |||||
| { | |||||
| *type = HmiControlType::AlarmList; | |||||
| } | |||||
| else | |||||
| const HmiControlDescriptor *descriptor = findHmiControlDescriptor(value); | |||||
| if (descriptor == nullptr) | |||||
| { | { | ||||
| return state->fail( | return state->fail( | ||||
| ProjectStorageError::InvalidField, | ProjectStorageError::InvalidField, | ||||
| "不支持的 HMI 控件类型:" + value); | "不支持的 HMI 控件类型:" + value); | ||||
| } | } | ||||
| *type = descriptor->type; | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -1,5 +1,6 @@ | |||||
| #include "hmi_editor_service.h" | #include "hmi_editor_service.h" | ||||
| #include "domain/hmi_control_registry.h" | |||||
| #include "project_service.h" | #include "project_service.h" | ||||
| #include <algorithm> | #include <algorithm> | ||||
| @@ -17,84 +18,6 @@ void setError(std::string *error, const std::string &message) | |||||
| } | } | ||||
| } | } | ||||
| std::string controlPrefix(HmiControlType type) | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case HmiControlType::Button: | |||||
| { | |||||
| return "button"; | |||||
| } | |||||
| case HmiControlType::Indicator: | |||||
| { | |||||
| return "indicator"; | |||||
| } | |||||
| case HmiControlType::NumericDisplay: | |||||
| { | |||||
| return "numeric-display"; | |||||
| } | |||||
| case HmiControlType::NumericInput: | |||||
| { | |||||
| return "numeric-input"; | |||||
| } | |||||
| case HmiControlType::Label: | |||||
| { | |||||
| return "label"; | |||||
| } | |||||
| case HmiControlType::PageJump: | |||||
| { | |||||
| return "page-jump"; | |||||
| } | |||||
| case HmiControlType::AlarmList: | |||||
| { | |||||
| return "alarm-list"; | |||||
| } | |||||
| default: | |||||
| { | |||||
| return "control"; | |||||
| } | |||||
| } | |||||
| } | |||||
| std::string defaultText(HmiControlType type) | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case HmiControlType::Button: | |||||
| { | |||||
| return "按钮"; | |||||
| } | |||||
| case HmiControlType::Indicator: | |||||
| { | |||||
| return "指示灯"; | |||||
| } | |||||
| case HmiControlType::NumericDisplay: | |||||
| { | |||||
| return "数值显示"; | |||||
| } | |||||
| case HmiControlType::NumericInput: | |||||
| { | |||||
| return "数值输入"; | |||||
| } | |||||
| case HmiControlType::Label: | |||||
| { | |||||
| return "文本"; | |||||
| } | |||||
| case HmiControlType::PageJump: | |||||
| { | |||||
| return "页面跳转"; | |||||
| } | |||||
| case HmiControlType::AlarmList: | |||||
| { | |||||
| return "报警信息"; | |||||
| } | |||||
| default: | |||||
| { | |||||
| return "控件"; | |||||
| } | |||||
| } | |||||
| } | |||||
| HmiEditorResult failure(HmiEditorError error, const std::string &message) | HmiEditorResult failure(HmiEditorError error, const std::string &message) | ||||
| { | { | ||||
| return {false, error, message, {}}; | return {false, error, message, {}}; | ||||
| @@ -351,9 +274,14 @@ HmiEditorResult HmiEditorService::addControl( | |||||
| { | { | ||||
| return failure(HmiEditorError::PageNotFound, "未找到 HMI 页面"); | return failure(HmiEditorError::PageNotFound, "未找到 HMI 页面"); | ||||
| } | } | ||||
| const HmiControlDescriptor *descriptor = findHmiControlDescriptor(type); | |||||
| if (descriptor == nullptr) | |||||
| { | |||||
| return failure(HmiEditorError::InvalidControl, "不支持的 HMI 控件类型"); | |||||
| } | |||||
| // 新控件初始不绑定寄存器,避免自动分配地址造成误写风险 | // 新控件初始不绑定寄存器,避免自动分配地址造成误写风险 | ||||
| HmiControl control = makeControl(*page, type); | |||||
| HmiControl control = makeControl(*page, *descriptor); | |||||
| Project &project = project_service_.editProject(); | Project &project = project_service_.editProject(); | ||||
| auto target_page = std::find_if( | auto target_page = std::find_if( | ||||
| project.hmiPages.begin(), | project.hmiPages.begin(), | ||||
| @@ -484,27 +412,11 @@ HmiEditorResult HmiEditorService::updateControl( | |||||
| bool HmiEditorService::validateEditableControl( | bool HmiEditorService::validateEditableControl( | ||||
| const HmiPage &page, const HmiControl &control, std::string *error) const | const HmiPage &page, const HmiControl &control, std::string *error) const | ||||
| { | { | ||||
| switch (control.type) | |||||
| { | |||||
| case HmiControlType::Button: | |||||
| case HmiControlType::Indicator: | |||||
| case HmiControlType::NumericDisplay: | |||||
| case HmiControlType::NumericInput: | |||||
| case HmiControlType::Label: | |||||
| case HmiControlType::PageJump: | |||||
| case HmiControlType::AlarmList: | |||||
| break; | |||||
| default: | |||||
| setError(error, "不支持的 HMI 控件类型"); | |||||
| return false; | |||||
| } | |||||
| if (control.id.empty()) | |||||
| if (!control.validate(error)) | |||||
| { | { | ||||
| setError(error, "HMI 控件 ID 不能为空"); | |||||
| return false; | return false; | ||||
| } | } | ||||
| if (control.bounds.width <= 0 || control.bounds.height <= 0 | |||||
| || control.bounds.x < 0 || control.bounds.y < 0 | |||||
| if (control.bounds.x < 0 || control.bounds.y < 0 | |||||
| || control.bounds.width > page.width || control.bounds.height > page.height | || control.bounds.width > page.width || control.bounds.height > page.height | ||||
| || control.bounds.x > page.width - control.bounds.width | || control.bounds.x > page.width - control.bounds.width | ||||
| || control.bounds.y > page.height - control.bounds.height) | || control.bounds.y > page.height - control.bounds.height) | ||||
| @@ -512,60 +424,11 @@ bool HmiEditorService::validateEditableControl( | |||||
| setError(error, "HMI 控件不能超出页面范围"); | setError(error, "HMI 控件不能超出页面范围"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| for (const auto &property : control.properties) | |||||
| { | |||||
| if (property.first.empty()) | |||||
| { | |||||
| setError(error, "HMI 控件属性名称不能为空"); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| if (control.binding.has_value() && !control.binding->isValid()) | |||||
| { | |||||
| setError(error, "HMI 控件绑定了无效地址"); | |||||
| return false; | |||||
| } | |||||
| if (control.binding.has_value() | |||||
| && (control.type == HmiControlType::Button | |||||
| || control.type == HmiControlType::Indicator) | |||||
| && control.binding->area() != RegisterArea::M) | |||||
| { | |||||
| setError(error, "按钮和指示灯必须绑定 M 区地址"); | |||||
| return false; | |||||
| } | |||||
| if (control.binding.has_value() | |||||
| && (control.type == HmiControlType::NumericDisplay | |||||
| || control.type == HmiControlType::NumericInput) | |||||
| && control.binding->area() != RegisterArea::D) | |||||
| { | |||||
| setError(error, "数值控件必须绑定 D 区地址"); | |||||
| return false; | |||||
| } | |||||
| if ((control.type == HmiControlType::Label | |||||
| || control.type == HmiControlType::PageJump | |||||
| || control.type == HmiControlType::AlarmList) | |||||
| && control.binding.has_value()) | |||||
| { | |||||
| setError(error, "文本、页面跳转和报警列表控件不能绑定寄存器"); | |||||
| return false; | |||||
| } | |||||
| if (control.type == HmiControlType::PageJump) | |||||
| { | |||||
| if (!control.pageJump.has_value()) | |||||
| { | |||||
| setError(error, "页面跳转控件缺少跳转配置"); | |||||
| return false; | |||||
| } | |||||
| if (!control.pageJump->targetPageId.empty() | |||||
| && findPage(control.pageJump->targetPageId) == nullptr) | |||||
| { | |||||
| setError(error, "页面跳转控件的目标页面不存在"); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| else if (control.pageJump.has_value()) | |||||
| if (control.type == HmiControlType::PageJump | |||||
| && !control.pageJump->targetPageId.empty() | |||||
| && findPage(control.pageJump->targetPageId) == nullptr) | |||||
| { | { | ||||
| setError(error, "非页面跳转控件不能包含跳转配置"); | |||||
| setError(error, "页面跳转控件的目标页面不存在"); | |||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| @@ -586,23 +449,15 @@ bool HmiEditorService::hasDuplicateControlId( | |||||
| // 根据控件类型生成默认样式、文字、大小、初始坐标 | // 根据控件类型生成默认样式、文字、大小、初始坐标 | ||||
| HmiControl HmiEditorService::makeControl( | HmiControl HmiEditorService::makeControl( | ||||
| const HmiPage &page, HmiControlType type) | |||||
| const HmiPage &page, const HmiControlDescriptor &descriptor) | |||||
| { | { | ||||
| HmiControl control; | HmiControl control; | ||||
| control.id = makeUniqueId(page, controlPrefix(type)); | |||||
| control.type = type; | |||||
| control.text = defaultText(type); | |||||
| if (type == HmiControlType::AlarmList) | |||||
| { | |||||
| control.bounds.width = std::min(360, page.width); | |||||
| control.bounds.height = std::min(180, page.height); | |||||
| } | |||||
| else | |||||
| { | |||||
| control.bounds.width = type == HmiControlType::Indicator ? 64 : 120; | |||||
| control.bounds.height = type == HmiControlType::Indicator ? 64 : 40; | |||||
| } | |||||
| if (type == HmiControlType::PageJump) | |||||
| control.id = makeUniqueId(page, descriptor.idPrefix); | |||||
| control.type = descriptor.type; | |||||
| control.text = descriptor.defaultText; | |||||
| control.bounds.width = std::min(descriptor.defaultBounds.width, page.width); | |||||
| control.bounds.height = std::min(descriptor.defaultBounds.height, page.height); | |||||
| if (descriptor.type == HmiControlType::PageJump) | |||||
| { | { | ||||
| control.pageJump = HmiPageJumpConfig{}; | control.pageJump = HmiPageJumpConfig{}; | ||||
| } | } | ||||
| @@ -12,6 +12,7 @@ | |||||
| #include <string> | #include <string> | ||||
| class ProjectService; | class ProjectService; | ||||
| struct HmiControlDescriptor; | |||||
| /** | /** | ||||
| * @brief HMI 编辑操作的失败分类 | * @brief HMI 编辑操作的失败分类 | ||||
| @@ -158,7 +159,7 @@ private: | |||||
| * @return 未绑定寄存器的默认控件配置 | * @return 未绑定寄存器的默认控件配置 | ||||
| */ | */ | ||||
| static HmiControl makeControl( | static HmiControl makeControl( | ||||
| const HmiPage &page, HmiControlType type); | |||||
| const HmiPage &page, const HmiControlDescriptor &descriptor); | |||||
| /** | /** | ||||
| * @brief 在页面内生成带指定前缀的唯一控件标识 | * @brief 在页面内生成带指定前缀的唯一控件标识 | ||||
| * @param page 待检查页面 | * @param page 待检查页面 | ||||
| @@ -1,5 +1,7 @@ | |||||
| #include "hmi_runtime_service.h" | #include "hmi_runtime_service.h" | ||||
| #include "domain/hmi_control_registry.h" | |||||
| namespace { | namespace { | ||||
| HmiRuntimeReadResult readFailure(HmiRuntimeError error) | HmiRuntimeReadResult readFailure(HmiRuntimeError error) | ||||
| @@ -12,17 +14,6 @@ HmiRuntimeWriteResult writeFailure(HmiRuntimeError error) | |||||
| return {false, error}; | return {false, error}; | ||||
| } | } | ||||
| bool isBitControl(HmiControlType type) | |||||
| { | |||||
| return type == HmiControlType::Button || type == HmiControlType::Indicator; | |||||
| } | |||||
| bool isWordControl(HmiControlType type) | |||||
| { | |||||
| return type == HmiControlType::NumericDisplay | |||||
| || type == HmiControlType::NumericInput; | |||||
| } | |||||
| } // namespace | } // namespace | ||||
| HmiRuntimeService::HmiRuntimeService(RegisterRepository &repository) | HmiRuntimeService::HmiRuntimeService(RegisterRepository &repository) | ||||
| @@ -32,8 +23,10 @@ HmiRuntimeService::HmiRuntimeService(RegisterRepository &repository) | |||||
| HmiRuntimeReadResult HmiRuntimeService::readControl(const HmiControl &control) const | HmiRuntimeReadResult HmiRuntimeService::readControl(const HmiControl &control) const | ||||
| { | { | ||||
| // 标签等静态控件不参与寄存器读写 | |||||
| if (!isBitControl(control.type) && !isWordControl(control.type)) | |||||
| const HmiControlDescriptor *descriptor = | |||||
| findHmiControlDescriptor(control.type); | |||||
| if (descriptor == nullptr | |||||
| || descriptor->runtimeValueKind == HmiRuntimeValueKind::None) | |||||
| { | { | ||||
| return readFailure(HmiRuntimeError::UnsupportedControl); | return readFailure(HmiRuntimeError::UnsupportedControl); | ||||
| } | } | ||||
| @@ -45,7 +38,16 @@ HmiRuntimeReadResult HmiRuntimeService::readControl(const HmiControl &control) c | |||||
| { | { | ||||
| return readFailure(HmiRuntimeError::InvalidBinding); | return readFailure(HmiRuntimeError::InvalidBinding); | ||||
| } | } | ||||
| if (isBitControl(control.type)) | |||||
| const std::optional<RegisterArea> binding_area = | |||||
| hmiBindingArea(descriptor->bindingKind); | |||||
| if (!binding_area.has_value() || control.binding->area() != *binding_area) | |||||
| { | |||||
| return readFailure(HmiRuntimeError::InvalidBinding); | |||||
| } | |||||
| switch (descriptor->runtimeValueKind) | |||||
| { | |||||
| case HmiRuntimeValueKind::Bit: | |||||
| { | { | ||||
| // 按控件类型选择仓库的 M 位读取契约 | // 按控件类型选择仓库的 M 位读取契约 | ||||
| const BitReadResult result = repository_.readBit(*control.binding); | const BitReadResult result = repository_.readBit(*control.binding); | ||||
| @@ -55,7 +57,7 @@ HmiRuntimeReadResult HmiRuntimeService::readControl(const HmiControl &control) c | |||||
| } | } | ||||
| return {true, HmiRuntimeError::None, result.value, 0}; | return {true, HmiRuntimeError::None, result.value, 0}; | ||||
| } | } | ||||
| if (isWordControl(control.type)) | |||||
| case HmiRuntimeValueKind::Word: | |||||
| { | { | ||||
| const WordReadResult result = repository_.readWord(*control.binding); | const WordReadResult result = repository_.readWord(*control.binding); | ||||
| if (!result.succeeded) | if (!result.succeeded) | ||||
| @@ -64,7 +66,12 @@ HmiRuntimeReadResult HmiRuntimeService::readControl(const HmiControl &control) c | |||||
| } | } | ||||
| return {true, HmiRuntimeError::None, false, result.value}; | return {true, HmiRuntimeError::None, false, result.value}; | ||||
| } | } | ||||
| return readFailure(HmiRuntimeError::UnsupportedControl); | |||||
| case HmiRuntimeValueKind::None: | |||||
| default: | |||||
| { | |||||
| return readFailure(HmiRuntimeError::UnsupportedControl); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| HmiRuntimeWriteResult HmiRuntimeService::operateButton( | HmiRuntimeWriteResult HmiRuntimeService::operateButton( | ||||
| @@ -1,5 +1,6 @@ | |||||
| #include "property_panel_controller.h" | #include "property_panel_controller.h" | ||||
| #include "domain/hmi_control_registry.h" | |||||
| #include "hmi_editor_widget.h" | #include "hmi_editor_widget.h" | ||||
| #include "logic_editor_widget.h" | #include "logic_editor_widget.h" | ||||
| #include "logic_instruction_dialog.h" | #include "logic_instruction_dialog.h" | ||||
| @@ -33,45 +34,6 @@ std::string toUtf8(const QString &value) | |||||
| return std::string(bytes.constData(), static_cast<std::size_t>(bytes.size())); | return std::string(bytes.constData(), static_cast<std::size_t>(bytes.size())); | ||||
| } | } | ||||
| QString controlTypeText(HmiControlType type) | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case HmiControlType::Button: | |||||
| { | |||||
| return QObject::tr("按钮"); | |||||
| } | |||||
| case HmiControlType::Indicator: | |||||
| { | |||||
| return QObject::tr("指示灯"); | |||||
| } | |||||
| case HmiControlType::NumericDisplay: | |||||
| { | |||||
| return QObject::tr("数值显示"); | |||||
| } | |||||
| case HmiControlType::NumericInput: | |||||
| { | |||||
| return QObject::tr("数值输入"); | |||||
| } | |||||
| case HmiControlType::Label: | |||||
| { | |||||
| return QObject::tr("文本"); | |||||
| } | |||||
| case HmiControlType::PageJump: | |||||
| { | |||||
| return QObject::tr("页面跳转"); | |||||
| } | |||||
| case HmiControlType::AlarmList: | |||||
| { | |||||
| return QObject::tr("报警列表"); | |||||
| } | |||||
| default: | |||||
| { | |||||
| return QObject::tr("未知控件"); | |||||
| } | |||||
| } | |||||
| } | |||||
| } // namespace | } // namespace | ||||
| PropertyPanelController::PropertyPanelController( | PropertyPanelController::PropertyPanelController( | ||||
| @@ -174,6 +136,8 @@ void PropertyPanelController::showControlProperties(const std::string &control_i | |||||
| const HmiControl *control = hmi_editor_service_.findControl( | const HmiControl *control = hmi_editor_service_.findControl( | ||||
| current_page_id_(), control_id); | current_page_id_(), control_id); | ||||
| const bool has_control = control != nullptr; | const bool has_control = control != nullptr; | ||||
| const HmiControlDescriptor *descriptor = has_control | |||||
| ? findHmiControlDescriptor(control->type) : nullptr; | |||||
| ui_.selectionValueLabel->setText( | ui_.selectionValueLabel->setText( | ||||
| has_control ? fromUtf8(control->id) | has_control ? fromUtf8(control->id) | ||||
| + (control->isConfigured() ? QString{} | + (control->isConfigured() ? QString{} | ||||
| @@ -219,9 +183,8 @@ void PropertyPanelController::showControlProperties(const std::string &control_i | |||||
| : control->binding->area() == RegisterArea::M ? 1 : 2); | : control->binding->area() == RegisterArea::M ? 1 : 2); | ||||
| ui_.bindingIndexSpinBox->setValue( | ui_.bindingIndexSpinBox->setValue( | ||||
| control->binding.has_value() ? control->binding->index() : 0); | control->binding.has_value() ? control->binding->index() : 0); | ||||
| const bool has_binding = control->type != HmiControlType::Label | |||||
| && control->type != HmiControlType::PageJump | |||||
| && control->type != HmiControlType::AlarmList; | |||||
| const bool has_binding = descriptor != nullptr | |||||
| && descriptor->bindingKind != HmiBindingKind::None; | |||||
| ui_.bindingAreaLabel->setVisible(has_binding); | ui_.bindingAreaLabel->setVisible(has_binding); | ||||
| ui_.bindingAreaComboBox->setVisible(has_binding); | ui_.bindingAreaComboBox->setVisible(has_binding); | ||||
| ui_.bindingIndexLabel->setVisible(has_binding); | ui_.bindingIndexLabel->setVisible(has_binding); | ||||
| @@ -434,7 +397,11 @@ void PropertyPanelController::addHmiControl(HmiControlType type) | |||||
| hmi_editor_widget_->selectControl(result.id); | hmi_editor_widget_->selectControl(result.id); | ||||
| showControlProperties(result.id); | showControlProperties(result.id); | ||||
| refresh_project_ui_(); | refresh_project_ui_(); | ||||
| status_reporter_(QObject::tr("已添加%1").arg(controlTypeText(type)), 3000); | |||||
| const HmiControlDescriptor *descriptor = findHmiControlDescriptor(type); | |||||
| const QString display_name = descriptor == nullptr | |||||
| ? QObject::tr("未知控件") | |||||
| : QString::fromUtf8(descriptor->displayName); | |||||
| status_reporter_(QObject::tr("已添加%1").arg(display_name), 3000); | |||||
| } | } | ||||
| void PropertyPanelController::deleteSelectedControl() | void PropertyPanelController::deleteSelectedControl() | ||||
| @@ -471,9 +438,10 @@ void PropertyPanelController::applySelectedControlProperties() | |||||
| control.bounds.y = ui_.controlYSpinBox->value(); | control.bounds.y = ui_.controlYSpinBox->value(); | ||||
| control.bounds.width = ui_.controlWidthSpinBox->value(); | control.bounds.width = ui_.controlWidthSpinBox->value(); | ||||
| control.bounds.height = ui_.controlHeightSpinBox->value(); | control.bounds.height = ui_.controlHeightSpinBox->value(); | ||||
| if (control.type == HmiControlType::Label | |||||
| || control.type == HmiControlType::PageJump | |||||
| || control.type == HmiControlType::AlarmList) | |||||
| const HmiControlDescriptor *descriptor = | |||||
| findHmiControlDescriptor(control.type); | |||||
| if (descriptor == nullptr | |||||
| || descriptor->bindingKind == HmiBindingKind::None) | |||||
| { | { | ||||
| control.binding.reset(); | control.binding.reset(); | ||||
| } | } | ||||
| @@ -12,6 +12,7 @@ SOURCES += \ | |||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/alarm_model.cpp \ | ../src/domain/alarm_model.cpp \ | ||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/hmi_control_registry.cpp \ | |||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| ../src/services/project_service.cpp \ | ../src/services/project_service.cpp \ | ||||
| @@ -23,6 +24,7 @@ HEADERS += \ | |||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/alarm_model.h \ | ../src/domain/alarm_model.h \ | ||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/hmi_control_registry.h \ | |||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| ../src/domain/project_storage.h \ | ../src/domain/project_storage.h \ | ||||
| @@ -1,4 +1,5 @@ | |||||
| #include "domain/control_logic_model.h" | #include "domain/control_logic_model.h" | ||||
| #include "domain/hmi_control_registry.h" | |||||
| #include "domain/hmi_model.h" | #include "domain/hmi_model.h" | ||||
| #include "domain/project_model.h" | #include "domain/project_model.h" | ||||
| #include "domain/register_address.h" | #include "domain/register_address.h" | ||||
| @@ -8,6 +9,7 @@ | |||||
| #include <cstdint> | #include <cstdint> | ||||
| #include <exception> | #include <exception> | ||||
| #include <iostream> | #include <iostream> | ||||
| #include <set> | |||||
| #include <stdexcept> | #include <stdexcept> | ||||
| #include <string> | #include <string> | ||||
| @@ -76,6 +78,92 @@ void testRegisterRepositorySeparatesAreas() | |||||
| "M address must not be read as a word"); | "M address must not be read as a word"); | ||||
| } | } | ||||
| void testHmiControlRegistryCompleteness() | |||||
| { | |||||
| std::set<const HmiControlDescriptor *> descriptors; | |||||
| std::set<std::string> storage_names; | |||||
| std::set<std::string> id_prefixes; | |||||
| const std::size_t control_type_count = | |||||
| static_cast<std::size_t>(HmiControlType::Count); | |||||
| for (std::size_t index = 0; index < control_type_count; ++index) | |||||
| { | |||||
| const HmiControlType type = static_cast<HmiControlType>(index); | |||||
| const HmiControlDescriptor *descriptor = | |||||
| findHmiControlDescriptor(type); | |||||
| require(descriptor != nullptr, | |||||
| "every HMI control type must have one descriptor"); | |||||
| require(descriptor->type == type, | |||||
| "HMI type lookup must return the requested descriptor"); | |||||
| require(descriptors.emplace(descriptor).second, | |||||
| "each HMI control type must resolve to a different descriptor"); | |||||
| require(descriptor->storageName != nullptr | |||||
| && descriptor->storageName[0] != '\0', | |||||
| "HMI storage names must not be empty"); | |||||
| require(descriptor->displayName != nullptr | |||||
| && descriptor->displayName[0] != '\0', | |||||
| "HMI display names must not be empty"); | |||||
| require(descriptor->idPrefix != nullptr | |||||
| && descriptor->idPrefix[0] != '\0', | |||||
| "HMI id prefixes must not be empty"); | |||||
| require(descriptor->defaultText != nullptr, | |||||
| "HMI default text must not be null"); | |||||
| require(descriptor->defaultBounds.width > 0 | |||||
| && descriptor->defaultBounds.height > 0, | |||||
| "HMI default bounds must have a positive size"); | |||||
| require(findHmiControlDescriptor(descriptor->storageName) == descriptor, | |||||
| "HMI storage name lookup must return its registered descriptor"); | |||||
| require(storage_names.emplace(descriptor->storageName).second, | |||||
| "HMI storage names must be unique"); | |||||
| require(id_prefixes.emplace(descriptor->idPrefix).second, | |||||
| "HMI id prefixes must be unique"); | |||||
| const std::optional<RegisterArea> binding_area = | |||||
| hmiBindingArea(descriptor->bindingKind); | |||||
| switch (descriptor->runtimeValueKind) | |||||
| { | |||||
| case HmiRuntimeValueKind::Bit: | |||||
| { | |||||
| require(descriptor->bindingKind == HmiBindingKind::Bit | |||||
| && binding_area == RegisterArea::M, | |||||
| "bit runtime controls must bind to the M area"); | |||||
| break; | |||||
| } | |||||
| case HmiRuntimeValueKind::Word: | |||||
| { | |||||
| require(descriptor->bindingKind == HmiBindingKind::Word | |||||
| && binding_area == RegisterArea::D, | |||||
| "word runtime controls must bind to the D area"); | |||||
| break; | |||||
| } | |||||
| case HmiRuntimeValueKind::None: | |||||
| { | |||||
| require(descriptor->bindingKind == HmiBindingKind::None | |||||
| && !binding_area.has_value(), | |||||
| "static controls must not declare a register binding"); | |||||
| break; | |||||
| } | |||||
| } | |||||
| require(descriptor->requiresBindingForRunning | |||||
| == (descriptor->runtimeValueKind | |||||
| != HmiRuntimeValueKind::None), | |||||
| "runtime value controls must require a configured binding"); | |||||
| } | |||||
| require(findHmiControlDescriptor(HmiControlType::Count) == nullptr, | |||||
| "the HMI control count marker must not be registered"); | |||||
| require(findHmiControlDescriptor(static_cast<HmiControlType>(99)) == nullptr, | |||||
| "unknown HMI control types must not resolve"); | |||||
| require(findHmiControlDescriptor("unknown") == nullptr, | |||||
| "unknown HMI storage names must not resolve"); | |||||
| require(hmiBindingArea(HmiBindingKind::Bit) == RegisterArea::M, | |||||
| "bit bindings must use the M area"); | |||||
| require(hmiBindingArea(HmiBindingKind::Word) == RegisterArea::D, | |||||
| "word bindings must use the D area"); | |||||
| require(!hmiBindingArea(HmiBindingKind::None).has_value(), | |||||
| "controls without bindings must not resolve a register area"); | |||||
| } | |||||
| Project makeValidProject() | Project makeValidProject() | ||||
| { | { | ||||
| // 构造包含 HMI 绑定和完整梯形图网络的最小合法工程作为测试基线 | // 构造包含 HMI 绑定和完整梯形图网络的最小合法工程作为测试基线 | ||||
| @@ -584,6 +672,7 @@ int main() | |||||
| testRegisterAddressBoundaries(); | testRegisterAddressBoundaries(); | ||||
| testRegisterAddressParsing(); | testRegisterAddressParsing(); | ||||
| testRegisterRepositorySeparatesAreas(); | testRegisterRepositorySeparatesAreas(); | ||||
| testHmiControlRegistryCompleteness(); | |||||
| testLogicNodeConfigurationBoundaries(); | testLogicNodeConfigurationBoundaries(); | ||||
| testTimerAndCommentBoundaries(); | testTimerAndCommentBoundaries(); | ||||
| testTimerReferencesForRunning(); | testTimerReferencesForRunning(); | ||||
| @@ -12,6 +12,7 @@ SOURCES += \ | |||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/alarm_model.cpp \ | ../src/domain/alarm_model.cpp \ | ||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/hmi_control_registry.cpp \ | |||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| ../src/domain/runtime_state.cpp | ../src/domain/runtime_state.cpp | ||||
| @@ -21,6 +22,7 @@ HEADERS += \ | |||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/alarm_model.h \ | ../src/domain/alarm_model.h \ | ||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/hmi_control_registry.h \ | |||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| ../src/domain/runtime_state.h | ../src/domain/runtime_state.h | ||||
| @@ -12,6 +12,7 @@ SOURCES += \ | |||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/alarm_model.cpp \ | ../src/domain/alarm_model.cpp \ | ||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/hmi_control_registry.cpp \ | |||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| ../src/services/project_service.cpp \ | ../src/services/project_service.cpp \ | ||||
| @@ -24,6 +25,7 @@ HEADERS += \ | |||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/alarm_model.h \ | ../src/domain/alarm_model.h \ | ||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/hmi_control_registry.h \ | |||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| ../src/domain/project_storage.h \ | ../src/domain/project_storage.h \ | ||||
| @@ -12,6 +12,7 @@ SOURCES += \ | |||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/hmi_control_registry.cpp \ | |||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/alarm_model.cpp \ | ../src/domain/alarm_model.cpp \ | ||||
| ../src/services/project_service.cpp \ | ../src/services/project_service.cpp \ | ||||
| @@ -22,6 +23,7 @@ HEADERS += \ | |||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/hmi_control_registry.h \ | |||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/alarm_model.h \ | ../src/domain/alarm_model.h \ | ||||
| ../src/domain/project_storage.h \ | ../src/domain/project_storage.h \ | ||||
| @@ -28,6 +28,7 @@ SOURCES += \ | |||||
| ../src/domain/register_monitor_model.cpp \ | ../src/domain/register_monitor_model.cpp \ | ||||
| ../src/domain/alarm_model.cpp \ | ../src/domain/alarm_model.cpp \ | ||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/hmi_control_registry.cpp \ | |||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| ../src/domain/runtime_state.cpp \ | ../src/domain/runtime_state.cpp \ | ||||
| @@ -63,6 +64,7 @@ HEADERS += \ | |||||
| ../src/domain/register_monitor_model.h \ | ../src/domain/register_monitor_model.h \ | ||||
| ../src/domain/alarm_model.h \ | ../src/domain/alarm_model.h \ | ||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/hmi_control_registry.h \ | |||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| ../src/domain/project_storage.h \ | ../src/domain/project_storage.h \ | ||||
| @@ -14,6 +14,7 @@ SOURCES += \ | |||||
| ../src/domain/register_address.cpp \ | ../src/domain/register_address.cpp \ | ||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/hmi_control_registry.cpp \ | |||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/services/hmi_runtime_service.cpp \ | ../src/services/hmi_runtime_service.cpp \ | ||||
| ../src/services/software_logic_executor.cpp \ | ../src/services/software_logic_executor.cpp \ | ||||
| @@ -23,6 +24,7 @@ HEADERS += \ | |||||
| ../src/domain/register_address.h \ | ../src/domain/register_address.h \ | ||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/hmi_control_registry.h \ | |||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/services/hmi_runtime_service.h \ | ../src/services/hmi_runtime_service.h \ | ||||
| ../src/services/software_logic_executor.h \ | ../src/services/software_logic_executor.h \ | ||||
| @@ -16,6 +16,7 @@ SOURCES += \ | |||||
| ../src/domain/register_monitor_model.cpp \ | ../src/domain/register_monitor_model.cpp \ | ||||
| ../src/domain/alarm_model.cpp \ | ../src/domain/alarm_model.cpp \ | ||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/hmi_control_registry.cpp \ | |||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| ../src/domain/runtime_state.cpp \ | ../src/domain/runtime_state.cpp \ | ||||
| @@ -33,6 +34,7 @@ HEADERS += \ | |||||
| ../src/domain/register_monitor_model.h \ | ../src/domain/register_monitor_model.h \ | ||||
| ../src/domain/alarm_model.h \ | ../src/domain/alarm_model.h \ | ||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/hmi_control_registry.h \ | |||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| ../src/domain/project_storage.h \ | ../src/domain/project_storage.h \ | ||||
| @@ -14,6 +14,7 @@ SOURCES += \ | |||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/alarm_model.cpp \ | ../src/domain/alarm_model.cpp \ | ||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/hmi_control_registry.cpp \ | |||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| ../src/domain/runtime_state.cpp \ | ../src/domain/runtime_state.cpp \ | ||||
| @@ -26,6 +27,7 @@ HEADERS += \ | |||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/alarm_model.h \ | ../src/domain/alarm_model.h \ | ||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/hmi_control_registry.h \ | |||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| ../src/domain/runtime_state.h \ | ../src/domain/runtime_state.h \ | ||||
| @@ -16,6 +16,7 @@ SOURCES += \ | |||||
| ../src/domain/register_monitor_model.cpp \ | ../src/domain/register_monitor_model.cpp \ | ||||
| ../src/domain/alarm_model.cpp \ | ../src/domain/alarm_model.cpp \ | ||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/hmi_control_registry.cpp \ | |||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| ../src/domain/runtime_state.cpp \ | ../src/domain/runtime_state.cpp \ | ||||
| @@ -31,6 +32,7 @@ HEADERS += \ | |||||
| ../src/domain/register_monitor_model.h \ | ../src/domain/register_monitor_model.h \ | ||||
| ../src/domain/alarm_model.h \ | ../src/domain/alarm_model.h \ | ||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/hmi_control_registry.h \ | |||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| ../src/domain/project_storage.h \ | ../src/domain/project_storage.h \ | ||||