| @@ -21,13 +21,11 @@ SOURCES += \ | |||||
| src/domain/register_address.cpp \ | src/domain/register_address.cpp \ | ||||
| src/domain/register_repository.cpp \ | src/domain/register_repository.cpp \ | ||||
| src/domain/active_register_repository.cpp \ | src/domain/active_register_repository.cpp \ | ||||
| src/domain/data_point_model.cpp \ | |||||
| src/domain/hmi_model.cpp \ | src/domain/hmi_model.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 \ | ||||
| src/services/project_service.cpp \ | src/services/project_service.cpp \ | ||||
| src/services/data_point_service.cpp \ | |||||
| src/services/hmi_editor_service.cpp \ | src/services/hmi_editor_service.cpp \ | ||||
| src/services/logic_editor_service.cpp \ | src/services/logic_editor_service.cpp \ | ||||
| src/services/hmi_runtime_service.cpp \ | src/services/hmi_runtime_service.cpp \ | ||||
| @@ -46,14 +44,12 @@ HEADERS += \ | |||||
| src/domain/register_address.h \ | src/domain/register_address.h \ | ||||
| src/domain/register_repository.h \ | src/domain/register_repository.h \ | ||||
| src/domain/active_register_repository.h \ | src/domain/active_register_repository.h \ | ||||
| src/domain/data_point_model.h \ | |||||
| src/domain/hmi_model.h \ | src/domain/hmi_model.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 \ | ||||
| src/domain/project_storage.h \ | src/domain/project_storage.h \ | ||||
| src/services/project_service.h \ | src/services/project_service.h \ | ||||
| src/services/data_point_service.h \ | |||||
| src/services/hmi_editor_service.h \ | src/services/hmi_editor_service.h \ | ||||
| src/services/logic_editor_service.h \ | src/services/logic_editor_service.h \ | ||||
| src/services/hmi_runtime_service.h \ | src/services/hmi_runtime_service.h \ | ||||
| @@ -1,37 +0,0 @@ | |||||
| #include "data_point_model.h" | |||||
| #include <algorithm> | |||||
| #include <cctype> | |||||
| namespace { | |||||
| bool isBlank(const std::string &value) | |||||
| { | |||||
| return value.empty() | |||||
| || std::all_of( | |||||
| value.cbegin(), value.cend(), | |||||
| [](unsigned char character) { return std::isspace(character) != 0; }); | |||||
| } | |||||
| } // namespace | |||||
| bool DataPoint::validate(std::string *error) const | |||||
| { | |||||
| if (!address.isValid()) | |||||
| { | |||||
| if (error != nullptr) | |||||
| { | |||||
| *error = "data point requires a valid M or D address"; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| if (isBlank(name)) | |||||
| { | |||||
| if (error != nullptr) | |||||
| { | |||||
| *error = "data point name must not be empty"; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| @@ -1,14 +0,0 @@ | |||||
| #pragma once | |||||
| #include "register_address.h" | |||||
| #include <string> | |||||
| struct DataPoint | |||||
| { | |||||
| RegisterAddress address; | |||||
| std::string name; | |||||
| std::string comment; | |||||
| bool validate(std::string *error = nullptr) const; | |||||
| }; | |||||
| @@ -52,29 +52,6 @@ bool Project::validate(std::string *error) const | |||||
| setError(error, "control logic ids must be unique within a project"); | setError(error, "control logic ids must be unique within a project"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| for (auto current = dataPoints.cbegin(); current != dataPoints.cend(); ++current) | |||||
| { | |||||
| if (!current->validate(error)) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| const auto duplicate = std::find_if( | |||||
| current + 1, | |||||
| dataPoints.cend(), | |||||
| [¤t](const DataPoint &candidate) | |||||
| { | |||||
| return candidate.address == current->address | |||||
| || candidate.name == current->name; | |||||
| }); | |||||
| if (duplicate != dataPoints.cend()) | |||||
| { | |||||
| if (error != nullptr) | |||||
| { | |||||
| *error = "data point addresses and names must be unique"; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| } | |||||
| for (const HmiPage &page : hmiPages) | for (const HmiPage &page : hmiPages) | ||||
| { | { | ||||
| // 工程聚合校验会向下委托页面和控件的完整规则 | // 工程聚合校验会向下委托页面和控件的完整规则 | ||||
| @@ -1,7 +1,6 @@ | |||||
| #pragma once | #pragma once | ||||
| #include "control_logic_model.h" | #include "control_logic_model.h" | ||||
| #include "data_point_model.h" | |||||
| #include "hmi_model.h" | #include "hmi_model.h" | ||||
| #include <string> | #include <string> | ||||
| @@ -27,8 +26,6 @@ struct Project | |||||
| std::vector<HmiPage> hmiPages; | std::vector<HmiPage> hmiPages; | ||||
| // 工程包含的控制逻辑集合 | // 工程包含的控制逻辑集合 | ||||
| std::vector<ControlLogic> controlLogics; | std::vector<ControlLogic> controlLogics; | ||||
| // M/D 地址的工程级名称和注释定义 | |||||
| std::vector<DataPoint> dataPoints; | |||||
| // 校验工程配置并通过 error 返回失败原因 | // 校验工程配置并通过 error 返回失败原因 | ||||
| bool validate(std::string *error = nullptr) const; | bool validate(std::string *error = nullptr) const; | ||||
| @@ -253,28 +253,6 @@ bool parseAddress( | |||||
| return true; | return true; | ||||
| } | } | ||||
| QJsonObject serializeDataPoint(const DataPoint &data_point) | |||||
| { | |||||
| QJsonObject object; | |||||
| object.insert(QStringLiteral("address"), serializeAddress(data_point.address)); | |||||
| object.insert(QStringLiteral("name"), fromUtf8(data_point.name)); | |||||
| object.insert(QStringLiteral("comment"), fromUtf8(data_point.comment)); | |||||
| return object; | |||||
| } | |||||
| bool parseDataPoint( | |||||
| const QJsonObject &object, | |||||
| const std::string &context, | |||||
| DataPoint *data_point, | |||||
| ParseState *state) | |||||
| { | |||||
| QJsonObject address; | |||||
| return readObject(object, "address", context, &address, state) | |||||
| && parseAddress(address, context + ".address", &data_point->address, state) | |||||
| && readString(object, "name", context, &data_point->name, state) | |||||
| && readString(object, "comment", context, &data_point->comment, state); | |||||
| } | |||||
| // 将 HMI 控件类型枚举转换为工程文件中的稳定字符串 | // 将 HMI 控件类型枚举转换为工程文件中的稳定字符串 | ||||
| QString hmiControlTypeName(HmiControlType type) | QString hmiControlTypeName(HmiControlType type) | ||||
| { | { | ||||
| @@ -1088,19 +1066,12 @@ QJsonObject serializeProject(const Project &project) | |||||
| logics.append(serializeControlLogic(logic)); | logics.append(serializeControlLogic(logic)); | ||||
| } | } | ||||
| QJsonArray data_points; | |||||
| for (const DataPoint &data_point : project.dataPoints) | |||||
| { | |||||
| data_points.append(serializeDataPoint(data_point)); | |||||
| } | |||||
| QJsonObject object; | QJsonObject object; | ||||
| object.insert(QStringLiteral("formatVersion"), fromUtf8(project.metadata.formatVersion)); | object.insert(QStringLiteral("formatVersion"), fromUtf8(project.metadata.formatVersion)); | ||||
| object.insert(QStringLiteral("id"), fromUtf8(project.metadata.id)); | object.insert(QStringLiteral("id"), fromUtf8(project.metadata.id)); | ||||
| object.insert(QStringLiteral("name"), fromUtf8(project.metadata.name)); | object.insert(QStringLiteral("name"), fromUtf8(project.metadata.name)); | ||||
| object.insert(QStringLiteral("hmiPages"), pages); | object.insert(QStringLiteral("hmiPages"), pages); | ||||
| object.insert(QStringLiteral("controlLogics"), logics); | object.insert(QStringLiteral("controlLogics"), logics); | ||||
| object.insert(QStringLiteral("dataPoints"), data_points); | |||||
| return object; | return object; | ||||
| } | } | ||||
| @@ -1110,7 +1081,6 @@ bool parseProject( | |||||
| { | { | ||||
| QJsonArray pages; | QJsonArray pages; | ||||
| QJsonArray logics; | QJsonArray logics; | ||||
| QJsonArray data_points; | |||||
| if (!readString( | if (!readString( | ||||
| object, | object, | ||||
| "formatVersion", | "formatVersion", | ||||
| @@ -1131,8 +1101,7 @@ bool parseProject( | |||||
| if (!readString(object, "id", "project", &project->metadata.id, state) | if (!readString(object, "id", "project", &project->metadata.id, state) | ||||
| || !readString(object, "name", "project", &project->metadata.name, state) | || !readString(object, "name", "project", &project->metadata.name, state) | ||||
| || !readArray(object, "hmiPages", "project", &pages, state) | || !readArray(object, "hmiPages", "project", &pages, state) | ||||
| || !readArray(object, "controlLogics", "project", &logics, state) | |||||
| || !readArray(object, "dataPoints", "project", &data_points, state)) | |||||
| || !readArray(object, "controlLogics", "project", &logics, state)) | |||||
| { | { | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -1179,26 +1148,6 @@ bool parseProject( | |||||
| } | } | ||||
| project->controlLogics.push_back(std::move(logic)); | project->controlLogics.push_back(std::move(logic)); | ||||
| } | } | ||||
| project->dataPoints.reserve(static_cast<std::size_t>(data_points.size())); | |||||
| for (int index = 0; index < data_points.size(); ++index) | |||||
| { | |||||
| if (!data_points.at(index).isObject()) | |||||
| { | |||||
| return state->fail( | |||||
| ProjectStorageError::InvalidField, | |||||
| "project.dataPoints items must be objects"); | |||||
| } | |||||
| DataPoint data_point{RegisterAddress{RegisterArea::M, 0}, {}, {}}; | |||||
| if (!parseDataPoint( | |||||
| data_points.at(index).toObject(), | |||||
| "project.dataPoints[" + std::to_string(index) + ']', | |||||
| &data_point, | |||||
| state)) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| project->dataPoints.push_back(std::move(data_point)); | |||||
| } | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -13,7 +13,6 @@ | |||||
| #include "infrastructure/plc_register_repository.h" | #include "infrastructure/plc_register_repository.h" | ||||
| #include "domain/active_register_repository.h" | #include "domain/active_register_repository.h" | ||||
| #include "services/hmi_editor_service.h" | #include "services/hmi_editor_service.h" | ||||
| #include "services/data_point_service.h" | |||||
| #include "services/hmi_runtime_service.h" | #include "services/hmi_runtime_service.h" | ||||
| #include "services/logic_editor_service.h" | #include "services/logic_editor_service.h" | ||||
| #include "services/offline_simulation_service.h" | #include "services/offline_simulation_service.h" | ||||
| @@ -31,7 +30,6 @@ int main(int argc, char *argv[]) | |||||
| JsonProjectStorage project_storage; | JsonProjectStorage project_storage; | ||||
| ProjectService project_service(project_storage); | ProjectService project_service(project_storage); | ||||
| HmiEditorService hmi_editor_service(project_service); | HmiEditorService hmi_editor_service(project_service); | ||||
| DataPointService data_point_service(project_service); | |||||
| LogicEditorService logic_editor_service(project_service); | LogicEditorService logic_editor_service(project_service); | ||||
| // 当前离线模式使用内存仓库,后续真机模式替换为 PLC 缓存实现 | // 当前离线模式使用内存仓库,后续真机模式替换为 PLC 缓存实现 | ||||
| VirtualRegisterRepository virtual_register_repository; | VirtualRegisterRepository virtual_register_repository; | ||||
| @@ -51,7 +49,6 @@ int main(int argc, char *argv[]) | |||||
| runtime_mode_service, | runtime_mode_service, | ||||
| project_service, | project_service, | ||||
| hmi_editor_service, | hmi_editor_service, | ||||
| data_point_service, | |||||
| logic_editor_service, | logic_editor_service, | ||||
| hmi_runtime_service); | hmi_runtime_service); | ||||
| main_window.show(); | main_window.show(); | ||||
| @@ -1,170 +0,0 @@ | |||||
| #include "data_point_service.h" | |||||
| #include "project_service.h" | |||||
| #include <algorithm> | |||||
| namespace { | |||||
| bool nodeUsesAddress(const LogicNode &node, const RegisterAddress &address) | |||||
| { | |||||
| return std::visit( | |||||
| [&address](const auto &config) { return config.address == address; }, | |||||
| node.config); | |||||
| } | |||||
| } // namespace | |||||
| DataPointService::DataPointService(ProjectService &project_service) | |||||
| : project_service_(project_service) | |||||
| { | |||||
| } | |||||
| const std::vector<DataPoint> &DataPointService::dataPoints() const | |||||
| { | |||||
| return project_service_.project().dataPoints; | |||||
| } | |||||
| const DataPoint *DataPointService::find(const RegisterAddress &address) const | |||||
| { | |||||
| const auto &points = dataPoints(); | |||||
| const auto found = std::find_if( | |||||
| points.cbegin(), points.cend(), | |||||
| [&address](const DataPoint &point) { return point.address == address; }); | |||||
| return found == points.cend() ? nullptr : &*found; | |||||
| } | |||||
| DataPointResult DataPointService::add(const DataPoint &data_point) | |||||
| { | |||||
| const DataPointResult validation = validateUnique(data_point, nullptr); | |||||
| if (!validation.succeeded) | |||||
| { | |||||
| return validation; | |||||
| } | |||||
| project_service_.editProject().dataPoints.push_back(data_point); | |||||
| return {true, DataPointError::None, {}}; | |||||
| } | |||||
| DataPointResult DataPointService::update( | |||||
| const RegisterAddress &old_address, const DataPoint &data_point) | |||||
| { | |||||
| const auto existing = std::find_if( | |||||
| dataPoints().cbegin(), dataPoints().cend(), | |||||
| [&old_address](const DataPoint &candidate) | |||||
| { | |||||
| return candidate.address == old_address; | |||||
| }); | |||||
| if (existing == dataPoints().cend()) | |||||
| { | |||||
| return {false, DataPointError::NotFound, "data point was not found"}; | |||||
| } | |||||
| const DataPointResult validation = validateUnique(data_point, &old_address); | |||||
| if (!validation.succeeded) | |||||
| { | |||||
| return validation; | |||||
| } | |||||
| if (data_point.address != old_address && !references(old_address).empty()) | |||||
| { | |||||
| return {false, DataPointError::AddressInUse, | |||||
| "referenced data point address cannot be changed"}; | |||||
| } | |||||
| Project &project = project_service_.editProject(); | |||||
| const auto point = std::find_if( | |||||
| project.dataPoints.begin(), project.dataPoints.end(), | |||||
| [&old_address](const DataPoint &candidate) | |||||
| { | |||||
| return candidate.address == old_address; | |||||
| }); | |||||
| *point = data_point; | |||||
| return {true, DataPointError::None, {}}; | |||||
| } | |||||
| DataPointResult DataPointService::remove(const RegisterAddress &address) | |||||
| { | |||||
| if (find(address) == nullptr) | |||||
| { | |||||
| return {false, DataPointError::NotFound, "data point was not found"}; | |||||
| } | |||||
| if (!references(address).empty()) | |||||
| { | |||||
| return {false, DataPointError::AddressInUse, | |||||
| "data point is still referenced by HMI or ladder logic"}; | |||||
| } | |||||
| Project &project = project_service_.editProject(); | |||||
| project.dataPoints.erase( | |||||
| std::remove_if( | |||||
| project.dataPoints.begin(), project.dataPoints.end(), | |||||
| [&address](const DataPoint &point) { return point.address == address; }), | |||||
| project.dataPoints.end()); | |||||
| return {true, DataPointError::None, {}}; | |||||
| } | |||||
| std::vector<DataPointReference> DataPointService::references( | |||||
| const RegisterAddress &address) const | |||||
| { | |||||
| std::vector<DataPointReference> result; | |||||
| const Project &project = project_service_.project(); | |||||
| for (const HmiPage &page : project.hmiPages) | |||||
| { | |||||
| for (const HmiControl &control : page.controls) | |||||
| { | |||||
| if (control.binding.has_value() && *control.binding == address) | |||||
| { | |||||
| result.push_back({"HMI/" + page.name + '/' + control.id}); | |||||
| } | |||||
| } | |||||
| } | |||||
| for (const ControlLogic &logic : project.controlLogics) | |||||
| { | |||||
| for (const LadderRung &rung : logic.rungs) | |||||
| { | |||||
| if (rung.condition.has_value()) | |||||
| { | |||||
| std::vector<const LogicNode *> nodes; | |||||
| collectConditionNodes(*rung.condition, &nodes); | |||||
| for (const LogicNode *node : nodes) | |||||
| { | |||||
| if (nodeUsesAddress(*node, address)) | |||||
| { | |||||
| result.push_back({"LAD/" + logic.name + '/' + rung.name + '/' + node->id}); | |||||
| } | |||||
| } | |||||
| } | |||||
| if (rung.output.has_value() && nodeUsesAddress(*rung.output, address)) | |||||
| { | |||||
| result.push_back({"LAD/" + logic.name + '/' + rung.name + '/' | |||||
| + rung.output->id}); | |||||
| } | |||||
| } | |||||
| } | |||||
| return result; | |||||
| } | |||||
| DataPointResult DataPointService::validateUnique( | |||||
| const DataPoint &data_point, | |||||
| const RegisterAddress *ignored_address) const | |||||
| { | |||||
| std::string error; | |||||
| if (!data_point.validate(&error)) | |||||
| { | |||||
| return {false, DataPointError::InvalidDataPoint, error}; | |||||
| } | |||||
| for (const DataPoint &existing : dataPoints()) | |||||
| { | |||||
| if (ignored_address != nullptr && existing.address == *ignored_address) | |||||
| { | |||||
| continue; | |||||
| } | |||||
| if (existing.address == data_point.address) | |||||
| { | |||||
| return {false, DataPointError::DuplicateAddress, | |||||
| "data point address already exists"}; | |||||
| } | |||||
| if (existing.name == data_point.name) | |||||
| { | |||||
| return {false, DataPointError::DuplicateName, | |||||
| "data point name already exists"}; | |||||
| } | |||||
| } | |||||
| return {true, DataPointError::None, {}}; | |||||
| } | |||||
| @@ -1,51 +0,0 @@ | |||||
| #pragma once | |||||
| #include "domain/data_point_model.h" | |||||
| #include <string> | |||||
| #include <vector> | |||||
| class ProjectService; | |||||
| enum class DataPointError | |||||
| { | |||||
| None, | |||||
| InvalidDataPoint, | |||||
| DuplicateAddress, | |||||
| DuplicateName, | |||||
| NotFound, | |||||
| AddressInUse | |||||
| }; | |||||
| struct DataPointResult | |||||
| { | |||||
| bool succeeded = false; | |||||
| DataPointError error = DataPointError::None; | |||||
| std::string message; | |||||
| }; | |||||
| struct DataPointReference | |||||
| { | |||||
| std::string location; | |||||
| }; | |||||
| class DataPointService | |||||
| { | |||||
| public: | |||||
| explicit DataPointService(ProjectService &project_service); | |||||
| const std::vector<DataPoint> &dataPoints() const; | |||||
| const DataPoint *find(const RegisterAddress &address) const; | |||||
| DataPointResult add(const DataPoint &data_point); | |||||
| DataPointResult update( | |||||
| const RegisterAddress &old_address, const DataPoint &data_point); | |||||
| DataPointResult remove(const RegisterAddress &address); | |||||
| std::vector<DataPointReference> references(const RegisterAddress &address) const; | |||||
| private: | |||||
| DataPointResult validateUnique( | |||||
| const DataPoint &data_point, | |||||
| const RegisterAddress *ignored_address) const; | |||||
| ProjectService &project_service_; | |||||
| }; | |||||
| @@ -180,10 +180,6 @@ PlcCommunicationResult RuntimeModeService::connectPlc( | |||||
| } | } | ||||
| std::vector<RegisterAddress> addresses; | std::vector<RegisterAddress> addresses; | ||||
| const Project &project = project_service_.project(); | const Project &project = project_service_.project(); | ||||
| for (const DataPoint &point : project.dataPoints) | |||||
| { | |||||
| addresses.push_back(point.address); | |||||
| } | |||||
| for (const HmiPage &page : project.hmiPages) | for (const HmiPage &page : project.hmiPages) | ||||
| { | { | ||||
| for (const HmiControl &control : page.controls) | for (const HmiControl &control : page.controls) | ||||
| @@ -4,7 +4,6 @@ | |||||
| #include "logic_editor_widget.h" | #include "logic_editor_widget.h" | ||||
| #include "plc_connection_dialog.h" | #include "plc_connection_dialog.h" | ||||
| #include "services/hmi_editor_service.h" | #include "services/hmi_editor_service.h" | ||||
| #include "services/data_point_service.h" | |||||
| #include "services/hmi_runtime_service.h" | #include "services/hmi_runtime_service.h" | ||||
| #include "services/logic_editor_service.h" | #include "services/logic_editor_service.h" | ||||
| #include "services/project_service.h" | #include "services/project_service.h" | ||||
| @@ -15,7 +14,6 @@ | |||||
| #include <QApplication> | #include <QApplication> | ||||
| #include <QComboBox> | #include <QComboBox> | ||||
| #include <QFileDialog> | #include <QFileDialog> | ||||
| #include <QHeaderView> | |||||
| #include <QInputDialog> | #include <QInputDialog> | ||||
| #include <QLabel> | #include <QLabel> | ||||
| #include <QLineEdit> | #include <QLineEdit> | ||||
| @@ -27,7 +25,6 @@ | |||||
| #include <QStyle> | #include <QStyle> | ||||
| #include <QTimer> | #include <QTimer> | ||||
| #include <QTabWidget> | #include <QTabWidget> | ||||
| #include <QTableWidget> | |||||
| #include <QToolButton> | #include <QToolButton> | ||||
| #include <QTreeWidget> | #include <QTreeWidget> | ||||
| #include <QTreeWidgetItem> | #include <QTreeWidgetItem> | ||||
| @@ -137,7 +134,6 @@ MainWindow::MainWindow( | |||||
| RuntimeModeService &runtime_mode_service, | RuntimeModeService &runtime_mode_service, | ||||
| ProjectService &project_service, | ProjectService &project_service, | ||||
| HmiEditorService &hmi_editor_service, | HmiEditorService &hmi_editor_service, | ||||
| DataPointService &data_point_service, | |||||
| LogicEditorService &logic_editor_service, | LogicEditorService &logic_editor_service, | ||||
| HmiRuntimeService &hmi_runtime_service, | HmiRuntimeService &hmi_runtime_service, | ||||
| QWidget *parent) | QWidget *parent) | ||||
| @@ -146,7 +142,6 @@ MainWindow::MainWindow( | |||||
| runtime_mode_service_(runtime_mode_service), | runtime_mode_service_(runtime_mode_service), | ||||
| project_service_(project_service), | project_service_(project_service), | ||||
| hmi_editor_service_(hmi_editor_service), | hmi_editor_service_(hmi_editor_service), | ||||
| data_point_service_(data_point_service), | |||||
| logic_editor_service_(logic_editor_service), | logic_editor_service_(logic_editor_service), | ||||
| hmi_runtime_service_(hmi_runtime_service) | hmi_runtime_service_(hmi_runtime_service) | ||||
| { | { | ||||
| @@ -154,7 +149,6 @@ MainWindow::MainWindow( | |||||
| configureAppearance(); | configureAppearance(); | ||||
| configureActions(); | configureActions(); | ||||
| configurePropertyEditor(); | configurePropertyEditor(); | ||||
| configureDataPointEditor(); | |||||
| configurePlcConnection(); | configurePlcConnection(); | ||||
| configureHmiEditor(); | configureHmiEditor(); | ||||
| configureLogicEditor(); | configureLogicEditor(); | ||||
| @@ -433,7 +427,6 @@ void MainWindow::configureHmiEditor() | |||||
| if (runtime_mode_service_.mode() != ApplicationMode::Editing) | if (runtime_mode_service_.mode() != ApplicationMode::Editing) | ||||
| { | { | ||||
| hmi_editor_widget_->refreshRuntimeValues(); | hmi_editor_widget_->refreshRuntimeValues(); | ||||
| refreshDataPointUi(); | |||||
| updateSimulationUi(false); | updateSimulationUi(false); | ||||
| } | } | ||||
| }); | }); | ||||
| @@ -492,62 +485,9 @@ void MainWindow::configurePropertyEditor() | |||||
| this, &MainWindow::applySelectedControlProperties); | this, &MainWindow::applySelectedControlProperties); | ||||
| connect(ui_->applyLogicPropertiesButton, &QPushButton::clicked, | connect(ui_->applyLogicPropertiesButton, &QPushButton::clicked, | ||||
| this, &MainWindow::applySelectedLogicNodeProperties); | this, &MainWindow::applySelectedLogicNodeProperties); | ||||
| connect(ui_->hmiDataPointComboBox, qOverload<int>(&QComboBox::currentIndexChanged), | |||||
| this, | |||||
| [this](int index) | |||||
| { | |||||
| if (index <= 0) | |||||
| { | |||||
| return; | |||||
| } | |||||
| const QString address = ui_->hmiDataPointComboBox->currentData().toString(); | |||||
| ui_->bindingAreaComboBox->setCurrentIndex(address.startsWith('M') ? 1 : 2); | |||||
| ui_->bindingIndexSpinBox->setValue(address.mid(1).toInt()); | |||||
| }); | |||||
| connect(ui_->logicDataPointComboBox, qOverload<int>(&QComboBox::currentIndexChanged), | |||||
| this, | |||||
| [this](int index) | |||||
| { | |||||
| if (index <= 0) | |||||
| { | |||||
| return; | |||||
| } | |||||
| ui_->logicAddressSpinBox->setValue( | |||||
| ui_->logicDataPointComboBox->currentData().toString().mid(1).toInt()); | |||||
| }); | |||||
| showControlProperties({}); | showControlProperties({}); | ||||
| } | } | ||||
| void MainWindow::configureDataPointEditor() | |||||
| { | |||||
| ui_->dataPointTable->horizontalHeader()->setSectionResizeMode( | |||||
| QHeaderView::ResizeToContents); | |||||
| ui_->dataPointTable->horizontalHeader()->setStretchLastSection(true); | |||||
| tabifyDockWidget(ui_->outputDock, ui_->dataPointDock); | |||||
| ui_->viewMenu->addAction(ui_->dataPointDock->toggleViewAction()); | |||||
| connect(ui_->addDataPointButton, &QPushButton::clicked, this, &MainWindow::addDataPoint); | |||||
| connect(ui_->updateDataPointButton, &QPushButton::clicked, | |||||
| this, &MainWindow::updateSelectedDataPoint); | |||||
| connect(ui_->deleteDataPointButton, &QPushButton::clicked, | |||||
| this, &MainWindow::deleteSelectedDataPoint); | |||||
| connect(ui_->dataPointTable, &QTableWidget::itemSelectionChanged, | |||||
| this, | |||||
| [this] | |||||
| { | |||||
| const int row = ui_->dataPointTable->currentRow(); | |||||
| if (row < 0) | |||||
| { | |||||
| return; | |||||
| } | |||||
| const QString address = ui_->dataPointTable->item(row, 0)->text(); | |||||
| ui_->dataPointAreaComboBox->setCurrentIndex(address.startsWith('M') ? 0 : 1); | |||||
| ui_->dataPointAddressSpinBox->setValue(address.mid(1).toInt()); | |||||
| ui_->dataPointNameEdit->setText(ui_->dataPointTable->item(row, 2)->text()); | |||||
| ui_->dataPointCommentEdit->setText(ui_->dataPointTable->item(row, 3)->text()); | |||||
| }); | |||||
| } | |||||
| void MainWindow::configurePlcConnection() | void MainWindow::configurePlcConnection() | ||||
| { | { | ||||
| connect(ui_->configurePlcAction, &QAction::triggered, this, &MainWindow::connectPlc); | connect(ui_->configurePlcAction, &QAction::triggered, this, &MainWindow::connectPlc); | ||||
| @@ -590,127 +530,6 @@ void MainWindow::refreshProjectUi() | |||||
| logic_root, {fromUtf8(logic.name) + suffix})); | logic_root, {fromUtf8(logic.name) + suffix})); | ||||
| } | } | ||||
| ui_->projectTree->expandAll(); | ui_->projectTree->expandAll(); | ||||
| refreshDataPointUi(); | |||||
| } | |||||
| void MainWindow::refreshDataPointUi() | |||||
| { | |||||
| const auto &points = data_point_service_.dataPoints(); | |||||
| ui_->dataPointTable->setRowCount(static_cast<int>(points.size())); | |||||
| ui_->hmiDataPointComboBox->blockSignals(true); | |||||
| ui_->logicDataPointComboBox->blockSignals(true); | |||||
| ui_->hmiDataPointComboBox->clear(); | |||||
| ui_->logicDataPointComboBox->clear(); | |||||
| ui_->hmiDataPointComboBox->addItem(tr("手动输入")); | |||||
| ui_->logicDataPointComboBox->addItem(tr("手动输入")); | |||||
| for (int row = 0; row < static_cast<int>(points.size()); ++row) | |||||
| { | |||||
| const DataPoint &point = points.at(static_cast<std::size_t>(row)); | |||||
| const QString address = fromUtf8(point.address.toString()); | |||||
| const QString display = tr("%1 - %2").arg(address, fromUtf8(point.name)); | |||||
| ui_->hmiDataPointComboBox->addItem(display, address); | |||||
| ui_->logicDataPointComboBox->addItem(display, address); | |||||
| QString value = QStringLiteral("-"); | |||||
| if (runtime_mode_service_.mode() != ApplicationMode::Editing) | |||||
| { | |||||
| if (point.address.area() == RegisterArea::M) | |||||
| { | |||||
| const BitReadResult read = hmi_runtime_service_.readBit(point.address); | |||||
| value = read.succeeded ? (read.value ? QStringLiteral("ON") : QStringLiteral("OFF")) | |||||
| : tr("不可用"); | |||||
| } | |||||
| else | |||||
| { | |||||
| const WordReadResult read = hmi_runtime_service_.readWord(point.address); | |||||
| value = read.succeeded ? QString::number(read.value) : tr("不可用"); | |||||
| } | |||||
| } | |||||
| QStringList references; | |||||
| for (const DataPointReference &reference : data_point_service_.references(point.address)) | |||||
| { | |||||
| references.push_back(fromUtf8(reference.location)); | |||||
| } | |||||
| const QStringList columns{ | |||||
| address, | |||||
| point.address.area() == RegisterArea::M ? tr("位") : tr("16 位字"), | |||||
| fromUtf8(point.name), | |||||
| fromUtf8(point.comment), | |||||
| value, | |||||
| references.join(QStringLiteral("; "))}; | |||||
| for (int column = 0; column < columns.size(); ++column) | |||||
| { | |||||
| ui_->dataPointTable->setItem( | |||||
| row, column, new QTableWidgetItem(columns.at(column))); | |||||
| } | |||||
| } | |||||
| ui_->hmiDataPointComboBox->blockSignals(false); | |||||
| ui_->logicDataPointComboBox->blockSignals(false); | |||||
| } | |||||
| void MainWindow::addDataPoint() | |||||
| { | |||||
| const RegisterArea area = ui_->dataPointAreaComboBox->currentIndex() == 0 | |||||
| ? RegisterArea::M : RegisterArea::D; | |||||
| const DataPointResult result = data_point_service_.add({ | |||||
| RegisterAddress{area, ui_->dataPointAddressSpinBox->value()}, | |||||
| toUtf8(ui_->dataPointNameEdit->text()), | |||||
| toUtf8(ui_->dataPointCommentEdit->text())}); | |||||
| if (!result.succeeded) | |||||
| { | |||||
| showProjectResult(tr("新增数据点"), fromUtf8(result.message), false); | |||||
| return; | |||||
| } | |||||
| refreshProjectUi(); | |||||
| statusBar()->showMessage(tr("数据点已新增"), 3000); | |||||
| } | |||||
| void MainWindow::updateSelectedDataPoint() | |||||
| { | |||||
| const int row = ui_->dataPointTable->currentRow(); | |||||
| if (row < 0) | |||||
| { | |||||
| statusBar()->showMessage(tr("请先选择要更新的数据点"), 3000); | |||||
| return; | |||||
| } | |||||
| const QString old_text = ui_->dataPointTable->item(row, 0)->text(); | |||||
| const RegisterAddress old_address{ | |||||
| old_text.startsWith('M') ? RegisterArea::M : RegisterArea::D, | |||||
| old_text.mid(1).toInt()}; | |||||
| const RegisterArea area = ui_->dataPointAreaComboBox->currentIndex() == 0 | |||||
| ? RegisterArea::M : RegisterArea::D; | |||||
| const DataPointResult result = data_point_service_.update( | |||||
| old_address, | |||||
| {RegisterAddress{area, ui_->dataPointAddressSpinBox->value()}, | |||||
| toUtf8(ui_->dataPointNameEdit->text()), | |||||
| toUtf8(ui_->dataPointCommentEdit->text())}); | |||||
| if (!result.succeeded) | |||||
| { | |||||
| showProjectResult(tr("更新数据点"), fromUtf8(result.message), false); | |||||
| return; | |||||
| } | |||||
| refreshProjectUi(); | |||||
| statusBar()->showMessage(tr("数据点已更新"), 3000); | |||||
| } | |||||
| void MainWindow::deleteSelectedDataPoint() | |||||
| { | |||||
| const int row = ui_->dataPointTable->currentRow(); | |||||
| if (row < 0) | |||||
| { | |||||
| statusBar()->showMessage(tr("请先选择要删除的数据点"), 3000); | |||||
| return; | |||||
| } | |||||
| const QString address_text = ui_->dataPointTable->item(row, 0)->text(); | |||||
| const DataPointResult result = data_point_service_.remove({ | |||||
| address_text.startsWith('M') ? RegisterArea::M : RegisterArea::D, | |||||
| address_text.mid(1).toInt()}); | |||||
| if (!result.succeeded) | |||||
| { | |||||
| showProjectResult(tr("删除数据点"), fromUtf8(result.message), false); | |||||
| return; | |||||
| } | |||||
| refreshProjectUi(); | |||||
| statusBar()->showMessage(tr("数据点已删除"), 3000); | |||||
| } | } | ||||
| void MainWindow::connectPlc() | void MainWindow::connectPlc() | ||||
| @@ -1224,7 +1043,6 @@ void MainWindow::updateModeUi(const QString &message) | |||||
| } | } | ||||
| ui_->hmiToolBar->setEnabled(policy.allowsProjectEditing); | ui_->hmiToolBar->setEnabled(policy.allowsProjectEditing); | ||||
| ui_->logicToolBar->setEnabled(policy.allowsProjectEditing); | ui_->logicToolBar->setEnabled(policy.allowsProjectEditing); | ||||
| ui_->dataPointDock->setEnabled(policy.allowsProjectEditing); | |||||
| ui_->addButtonAction->setEnabled(policy.allowsProjectEditing); | ui_->addButtonAction->setEnabled(policy.allowsProjectEditing); | ||||
| ui_->addIndicatorAction->setEnabled(policy.allowsProjectEditing); | ui_->addIndicatorAction->setEnabled(policy.allowsProjectEditing); | ||||
| ui_->addNumericDisplayAction->setEnabled(policy.allowsProjectEditing); | ui_->addNumericDisplayAction->setEnabled(policy.allowsProjectEditing); | ||||
| @@ -31,7 +31,6 @@ class RuntimeModeService; | |||||
| class ProjectService; | class ProjectService; | ||||
| class HmiEditorService; | class HmiEditorService; | ||||
| class HmiRuntimeService; | class HmiRuntimeService; | ||||
| class DataPointService; | |||||
| class HmiEditorWidget; | class HmiEditorWidget; | ||||
| class LogicEditorService; | class LogicEditorService; | ||||
| class LogicEditorWidget; | class LogicEditorWidget; | ||||
| @@ -58,7 +57,6 @@ public: | |||||
| RuntimeModeService &runtime_mode_service, | RuntimeModeService &runtime_mode_service, | ||||
| ProjectService &project_service, | ProjectService &project_service, | ||||
| HmiEditorService &hmi_editor_service, | HmiEditorService &hmi_editor_service, | ||||
| DataPointService &data_point_service, | |||||
| LogicEditorService &logic_editor_service, | LogicEditorService &logic_editor_service, | ||||
| HmiRuntimeService &hmi_runtime_service, | HmiRuntimeService &hmi_runtime_service, | ||||
| QWidget *parent = nullptr); | QWidget *parent = nullptr); | ||||
| @@ -76,7 +74,6 @@ private: | |||||
| void configureLogicEditor(); | void configureLogicEditor(); | ||||
| // 创建并连接控件属性编辑表单 | // 创建并连接控件属性编辑表单 | ||||
| void configurePropertyEditor(); | void configurePropertyEditor(); | ||||
| void configureDataPointEditor(); | |||||
| void configurePlcConnection(); | void configurePlcConnection(); | ||||
| // 刷新工程树和当前 HMI 页面信息 | // 刷新工程树和当前 HMI 页面信息 | ||||
| void refreshProjectUi(); | void refreshProjectUi(); | ||||
| @@ -102,10 +99,6 @@ private: | |||||
| void deleteSelectedLogicObject(); | void deleteSelectedLogicObject(); | ||||
| // 将逻辑属性表单内容应用到当前选中节点 | // 将逻辑属性表单内容应用到当前选中节点 | ||||
| void applySelectedLogicNodeProperties(); | void applySelectedLogicNodeProperties(); | ||||
| void refreshDataPointUi(); | |||||
| void addDataPoint(); | |||||
| void updateSelectedDataPoint(); | |||||
| void deleteSelectedDataPoint(); | |||||
| void connectPlc(); | void connectPlc(); | ||||
| void disconnectPlc(); | void disconnectPlc(); | ||||
| // 创建新的工程并刷新编辑界面 | // 创建新的工程并刷新编辑界面 | ||||
| @@ -150,7 +143,6 @@ private: | |||||
| */ | */ | ||||
| ProjectService &project_service_; | ProjectService &project_service_; | ||||
| HmiEditorService &hmi_editor_service_; | HmiEditorService &hmi_editor_service_; | ||||
| DataPointService &data_point_service_; | |||||
| LogicEditorService &logic_editor_service_; | LogicEditorService &logic_editor_service_; | ||||
| HmiRuntimeService &hmi_runtime_service_; | HmiRuntimeService &hmi_runtime_service_; | ||||
| QActionGroup *mode_action_group_ = nullptr; | QActionGroup *mode_action_group_ = nullptr; | ||||
| @@ -41,6 +41,9 @@ | |||||
| </property> | </property> | ||||
| <item> | <item> | ||||
| <widget class="QTabWidget" name="editorTabWidget"> | <widget class="QTabWidget" name="editorTabWidget"> | ||||
| <property name="currentIndex"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <property name="documentMode"> | <property name="documentMode"> | ||||
| <bool>true</bool> | <bool>true</bool> | ||||
| </property> | </property> | ||||
| @@ -214,19 +217,19 @@ | |||||
| <x>0</x> | <x>0</x> | ||||
| <y>0</y> | <y>0</y> | ||||
| <width>1280</width> | <width>1280</width> | ||||
| <height>23</height> | |||||
| <height>17</height> | |||||
| </rect> | </rect> | ||||
| </property> | </property> | ||||
| <widget class="QMenu" name="fileMenu"> | <widget class="QMenu" name="fileMenu"> | ||||
| <property name="title"> | <property name="title"> | ||||
| <string>文件(&F)</string> | <string>文件(&F)</string> | ||||
| </property> | </property> | ||||
| <addaction name="newProjectAction"/> | |||||
| <addaction name="saveProjectAction"/> | |||||
| <addaction name="saveAsProjectAction"/> | |||||
| <addaction name="loadProjectAction"/> | |||||
| <addaction name="separator"/> | |||||
| <addaction name="exitAction"/> | |||||
| <addaction name="newProjectAction"/> | |||||
| <addaction name="saveProjectAction"/> | |||||
| <addaction name="saveAsProjectAction"/> | |||||
| <addaction name="loadProjectAction"/> | |||||
| <addaction name="separator"/> | |||||
| <addaction name="exitAction"/> | |||||
| </widget> | </widget> | ||||
| <widget class="QMenu" name="runMenu"> | <widget class="QMenu" name="runMenu"> | ||||
| <property name="title"> | <property name="title"> | ||||
| @@ -234,10 +237,10 @@ | |||||
| </property> | </property> | ||||
| <addaction name="editingModeAction"/> | <addaction name="editingModeAction"/> | ||||
| <addaction name="offlineModeAction"/> | <addaction name="offlineModeAction"/> | ||||
| <addaction name="onlineModeAction"/> | |||||
| <addaction name="separator"/> | |||||
| <addaction name="configurePlcAction"/> | |||||
| <addaction name="disconnectPlcAction"/> | |||||
| <addaction name="onlineModeAction"/> | |||||
| <addaction name="separator"/> | |||||
| <addaction name="configurePlcAction"/> | |||||
| <addaction name="disconnectPlcAction"/> | |||||
| </widget> | </widget> | ||||
| <widget class="QMenu" name="viewMenu"> | <widget class="QMenu" name="viewMenu"> | ||||
| <property name="title"> | <property name="title"> | ||||
| @@ -268,36 +271,52 @@ | |||||
| <addaction name="editingModeAction"/> | <addaction name="editingModeAction"/> | ||||
| <addaction name="offlineModeAction"/> | <addaction name="offlineModeAction"/> | ||||
| <addaction name="onlineModeAction"/> | <addaction name="onlineModeAction"/> | ||||
| <addaction name="configurePlcAction"/> | |||||
| <addaction name="disconnectPlcAction"/> | |||||
| </widget> | |||||
| <widget class="QToolBar" name="hmiToolBar"> | |||||
| <property name="windowTitle"><string>HMI 控件</string></property> | |||||
| <property name="toolButtonStyle"><enum>Qt::ToolButtonTextBesideIcon</enum></property> | |||||
| <attribute name="toolBarArea"><enum>TopToolBarArea</enum></attribute> | |||||
| <attribute name="toolBarBreak"><bool>false</bool></attribute> | |||||
| <addaction name="addButtonAction"/> | |||||
| <addaction name="addIndicatorAction"/> | |||||
| <addaction name="addNumericDisplayAction"/> | |||||
| <addaction name="addNumericInputAction"/> | |||||
| <addaction name="deleteControlAction"/> | |||||
| </widget> | |||||
| <widget class="QToolBar" name="logicToolBar"> | |||||
| <property name="windowTitle"><string>控制逻辑节点</string></property> | |||||
| <property name="toolButtonStyle"><enum>Qt::ToolButtonTextBesideIcon</enum></property> | |||||
| <attribute name="toolBarArea"><enum>TopToolBarArea</enum></attribute> | |||||
| <attribute name="toolBarBreak"><bool>false</bool></attribute> | |||||
| <addaction name="addRungAction"/> | |||||
| <addaction name="parallelInsertAction"/> | |||||
| <addaction name="separator"/> | |||||
| <addaction name="addNormallyOpenAction"/> | |||||
| <addaction name="addNormallyClosedAction"/> | |||||
| <addaction name="addNormalCoilAction"/> | |||||
| <addaction name="addSetCoilAction"/> | |||||
| <addaction name="addResetCoilAction"/> | |||||
| <addaction name="addCompareAction"/> | |||||
| <addaction name="deleteLogicAction"/> | |||||
| </widget> | |||||
| <addaction name="configurePlcAction"/> | |||||
| <addaction name="disconnectPlcAction"/> | |||||
| </widget> | |||||
| <widget class="QToolBar" name="hmiToolBar"> | |||||
| <property name="windowTitle"> | |||||
| <string>HMI 控件</string> | |||||
| </property> | |||||
| <property name="toolButtonStyle"> | |||||
| <enum>Qt::ToolButtonTextBesideIcon</enum> | |||||
| </property> | |||||
| <attribute name="toolBarArea"> | |||||
| <enum>TopToolBarArea</enum> | |||||
| </attribute> | |||||
| <attribute name="toolBarBreak"> | |||||
| <bool>false</bool> | |||||
| </attribute> | |||||
| <addaction name="addButtonAction"/> | |||||
| <addaction name="addIndicatorAction"/> | |||||
| <addaction name="addNumericDisplayAction"/> | |||||
| <addaction name="addNumericInputAction"/> | |||||
| <addaction name="deleteControlAction"/> | |||||
| </widget> | |||||
| <widget class="QToolBar" name="logicToolBar"> | |||||
| <property name="windowTitle"> | |||||
| <string>控制逻辑节点</string> | |||||
| </property> | |||||
| <property name="toolButtonStyle"> | |||||
| <enum>Qt::ToolButtonTextBesideIcon</enum> | |||||
| </property> | |||||
| <attribute name="toolBarArea"> | |||||
| <enum>TopToolBarArea</enum> | |||||
| </attribute> | |||||
| <attribute name="toolBarBreak"> | |||||
| <bool>false</bool> | |||||
| </attribute> | |||||
| <addaction name="addRungAction"/> | |||||
| <addaction name="parallelInsertAction"/> | |||||
| <addaction name="separator"/> | |||||
| <addaction name="addNormallyOpenAction"/> | |||||
| <addaction name="addNormallyClosedAction"/> | |||||
| <addaction name="addNormalCoilAction"/> | |||||
| <addaction name="addSetCoilAction"/> | |||||
| <addaction name="addResetCoilAction"/> | |||||
| <addaction name="addCompareAction"/> | |||||
| <addaction name="deleteLogicAction"/> | |||||
| </widget> | |||||
| <widget class="QDockWidget" name="projectDock"> | <widget class="QDockWidget" name="projectDock"> | ||||
| <property name="minimumSize"> | <property name="minimumSize"> | ||||
| <size> | <size> | ||||
| @@ -327,10 +346,10 @@ | |||||
| </property> | </property> | ||||
| <item> | <item> | ||||
| <widget class="QTreeWidget" name="projectTree"> | <widget class="QTreeWidget" name="projectTree"> | ||||
| <property name="headerHidden"> | |||||
| <property name="rootIsDecorated"> | |||||
| <bool>true</bool> | <bool>true</bool> | ||||
| </property> | </property> | ||||
| <property name="rootIsDecorated"> | |||||
| <property name="headerHidden"> | |||||
| <bool>true</bool> | <bool>true</bool> | ||||
| </property> | </property> | ||||
| <column> | <column> | ||||
| @@ -393,86 +412,315 @@ | |||||
| <rect> | <rect> | ||||
| <x>0</x> | <x>0</x> | ||||
| <y>0</y> | <y>0</y> | ||||
| <width>232</width> | |||||
| <height>164</height> | |||||
| <width>234</width> | |||||
| <height>455</height> | |||||
| </rect> | </rect> | ||||
| </property> | </property> | ||||
| <layout class="QVBoxLayout" name="propertiesPageLayout"> | |||||
| <item> | |||||
| <layout class="QFormLayout" name="selectionForm"> | |||||
| <item row="0" column="0"><widget class="QLabel" name="selectionCaptionLabel"><property name="text"><string>当前对象</string></property></widget></item> | |||||
| <item row="0" column="1"><widget class="QLabel" name="selectionValueLabel"><property name="text"><string>未选择</string></property></widget></item> | |||||
| </layout> | |||||
| </item> | |||||
| <item> | |||||
| <widget class="QStackedWidget" name="propertyStack"> | |||||
| <widget class="QWidget" name="hmiPropertiesPage"> | |||||
| <layout class="QFormLayout" name="hmiPropertiesForm"> | |||||
| <property name="fieldGrowthPolicy"><enum>QFormLayout::AllNonFixedFieldsGrow</enum></property> | |||||
| <item row="0" column="0"><widget class="QLabel" name="controlIdLabel"><property name="text"><string>控件 ID</string></property></widget></item> | |||||
| <item row="0" column="1"><widget class="QLineEdit" name="controlIdEdit"/></item> | |||||
| <item row="1" column="0"><widget class="QLabel" name="controlTextLabel"><property name="text"><string>显示文本</string></property></widget></item> | |||||
| <item row="1" column="1"><widget class="QLineEdit" name="controlTextEdit"/></item> | |||||
| <item row="2" column="0"><widget class="QLabel" name="controlXLabel"><property name="text"><string>X</string></property></widget></item> | |||||
| <item row="2" column="1"><widget class="QSpinBox" name="controlXSpinBox"><property name="maximum"><number>4000</number></property></widget></item> | |||||
| <item row="3" column="0"><widget class="QLabel" name="controlYLabel"><property name="text"><string>Y</string></property></widget></item> | |||||
| <item row="3" column="1"><widget class="QSpinBox" name="controlYSpinBox"><property name="maximum"><number>4000</number></property></widget></item> | |||||
| <item row="4" column="0"><widget class="QLabel" name="controlWidthLabel"><property name="text"><string>宽度</string></property></widget></item> | |||||
| <item row="4" column="1"><widget class="QSpinBox" name="controlWidthSpinBox"><property name="minimum"><number>1</number></property><property name="maximum"><number>4000</number></property></widget></item> | |||||
| <item row="5" column="0"><widget class="QLabel" name="controlHeightLabel"><property name="text"><string>高度</string></property></widget></item> | |||||
| <item row="5" column="1"><widget class="QSpinBox" name="controlHeightSpinBox"><property name="minimum"><number>1</number></property><property name="maximum"><number>4000</number></property></widget></item> | |||||
| <item row="6" column="0"><widget class="QLabel" name="bindingAreaLabel"><property name="text"><string>绑定区域</string></property></widget></item> | |||||
| <item row="6" column="1"><widget class="QComboBox" name="bindingAreaComboBox"> | |||||
| <item><property name="text"><string>未绑定</string></property><property name="userData"><string notr="true">-1</string></property></item> | |||||
| <item><property name="text"><string>M</string></property><property name="userData"><string notr="true">0</string></property></item> | |||||
| <item><property name="text"><string>D</string></property><property name="userData"><string notr="true">1</string></property></item> | |||||
| </widget></item> | |||||
| <item row="7" column="0"><widget class="QLabel" name="bindingIndexLabel"><property name="text"><string>绑定地址</string></property></widget></item> | |||||
| <item row="7" column="1"><widget class="QSpinBox" name="bindingIndexSpinBox"><property name="maximum"><number>4000</number></property></widget></item> | |||||
| <item row="8" column="0"><widget class="QLabel" name="hmiDataPointLabel"><property name="text"><string>选择数据点</string></property></widget></item> | |||||
| <item row="8" column="1"><widget class="QComboBox" name="hmiDataPointComboBox"/></item> | |||||
| <item row="9" column="0" colspan="2"><widget class="QPushButton" name="applyPropertiesButton"><property name="text"><string>应用属性</string></property></widget></item> | |||||
| </layout> | |||||
| <layout class="QVBoxLayout" name="propertiesPageLayout"> | |||||
| <item> | |||||
| <layout class="QFormLayout" name="selectionForm"> | |||||
| <item row="0" column="0"> | |||||
| <widget class="QLabel" name="selectionCaptionLabel"> | |||||
| <property name="text"> | |||||
| <string>当前对象</string> | |||||
| </property> | |||||
| </widget> | </widget> | ||||
| <widget class="QWidget" name="logicPropertiesPage"> | |||||
| <layout class="QFormLayout" name="logicPropertiesForm"> | |||||
| <property name="fieldGrowthPolicy"><enum>QFormLayout::AllNonFixedFieldsGrow</enum></property> | |||||
| <item row="0" column="0"><widget class="QLabel" name="logicNodeIdLabel"><property name="text"><string>节点 ID</string></property></widget></item> | |||||
| <item row="0" column="1"><widget class="QLineEdit" name="logicNodeIdEdit"><property name="readOnly"><bool>true</bool></property></widget></item> | |||||
| <item row="1" column="0"><widget class="QLabel" name="logicNodeTypeCaption"><property name="text"><string>节点类型</string></property></widget></item> | |||||
| <item row="1" column="1"><widget class="QLabel" name="logicNodeTypeLabel"><property name="text"><string/></property></widget></item> | |||||
| <item row="2" column="0"><widget class="QLabel" name="logicAddressAreaCaption"><property name="text"><string>地址区域</string></property></widget></item> | |||||
| <item row="2" column="1"><widget class="QLabel" name="logicAddressAreaLabel"><property name="text"><string/></property></widget></item> | |||||
| <item row="3" column="0"><widget class="QLabel" name="logicAddressLabel"><property name="text"><string>地址</string></property></widget></item> | |||||
| <item row="3" column="1"><widget class="QSpinBox" name="logicAddressSpinBox"><property name="maximum"><number>4000</number></property></widget></item> | |||||
| <item row="4" column="0"><widget class="QLabel" name="logicDataPointLabel"><property name="text"><string>选择数据点</string></property></widget></item> | |||||
| <item row="4" column="1"><widget class="QComboBox" name="logicDataPointComboBox"/></item> | |||||
| <item row="5" column="0"><widget class="QLabel" name="logicModeLabel"><property name="text"><string>工作方式</string></property></widget></item> | |||||
| <item row="5" column="1"><widget class="QComboBox" name="logicModeComboBox"/></item> | |||||
| <item row="6" column="0"><widget class="QLabel" name="logicComparisonLabel"><property name="text"><string>比较运算</string></property></widget></item> | |||||
| <item row="6" column="1"><widget class="QComboBox" name="logicComparisonComboBox"> | |||||
| <item><property name="text"><string>等于</string></property><property name="userData"><string notr="true">0</string></property></item> | |||||
| <item><property name="text"><string>不等于</string></property><property name="userData"><string notr="true">1</string></property></item> | |||||
| <item><property name="text"><string>小于</string></property><property name="userData"><string notr="true">2</string></property></item> | |||||
| <item><property name="text"><string>小于等于</string></property><property name="userData"><string notr="true">3</string></property></item> | |||||
| <item><property name="text"><string>大于</string></property><property name="userData"><string notr="true">4</string></property></item> | |||||
| <item><property name="text"><string>大于等于</string></property><property name="userData"><string notr="true">5</string></property></item> | |||||
| </widget></item> | |||||
| <item row="7" column="0"><widget class="QLabel" name="logicValueLabel"><property name="text"><string>比较常量</string></property></widget></item> | |||||
| <item row="7" column="1"><widget class="QSpinBox" name="logicValueSpinBox"><property name="minimum"><number>-32768</number></property><property name="maximum"><number>32767</number></property></widget></item> | |||||
| <item row="8" column="0" colspan="2"><widget class="QPushButton" name="applyLogicPropertiesButton"><property name="text"><string>应用属性</string></property></widget></item> | |||||
| </layout> | |||||
| </item> | |||||
| <item row="0" column="1"> | |||||
| <widget class="QLabel" name="selectionValueLabel"> | |||||
| <property name="text"> | |||||
| <string>未选择</string> | |||||
| </property> | |||||
| </widget> | </widget> | ||||
| </item> | |||||
| </layout> | |||||
| </item> | |||||
| <item> | |||||
| <widget class="QStackedWidget" name="propertyStack"> | |||||
| <widget class="QWidget" name="hmiPropertiesPage"> | |||||
| <layout class="QFormLayout" name="hmiPropertiesForm"> | |||||
| <property name="fieldGrowthPolicy"> | |||||
| <enum>QFormLayout::AllNonFixedFieldsGrow</enum> | |||||
| </property> | |||||
| <item row="0" column="0"> | |||||
| <widget class="QLabel" name="controlIdLabel"> | |||||
| <property name="text"> | |||||
| <string>控件 ID</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="0" column="1"> | |||||
| <widget class="QLineEdit" name="controlIdEdit"/> | |||||
| </item> | |||||
| <item row="1" column="0"> | |||||
| <widget class="QLabel" name="controlTextLabel"> | |||||
| <property name="text"> | |||||
| <string>显示文本</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="1" column="1"> | |||||
| <widget class="QLineEdit" name="controlTextEdit"/> | |||||
| </item> | |||||
| <item row="2" column="0"> | |||||
| <widget class="QLabel" name="controlXLabel"> | |||||
| <property name="text"> | |||||
| <string>X</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="2" column="1"> | |||||
| <widget class="QSpinBox" name="controlXSpinBox"> | |||||
| <property name="maximum"> | |||||
| <number>4000</number> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="3" column="0"> | |||||
| <widget class="QLabel" name="controlYLabel"> | |||||
| <property name="text"> | |||||
| <string>Y</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="3" column="1"> | |||||
| <widget class="QSpinBox" name="controlYSpinBox"> | |||||
| <property name="maximum"> | |||||
| <number>4000</number> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="4" column="0"> | |||||
| <widget class="QLabel" name="controlWidthLabel"> | |||||
| <property name="text"> | |||||
| <string>宽度</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="4" column="1"> | |||||
| <widget class="QSpinBox" name="controlWidthSpinBox"> | |||||
| <property name="minimum"> | |||||
| <number>1</number> | |||||
| </property> | |||||
| <property name="maximum"> | |||||
| <number>4000</number> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="5" column="0"> | |||||
| <widget class="QLabel" name="controlHeightLabel"> | |||||
| <property name="text"> | |||||
| <string>高度</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="5" column="1"> | |||||
| <widget class="QSpinBox" name="controlHeightSpinBox"> | |||||
| <property name="minimum"> | |||||
| <number>1</number> | |||||
| </property> | |||||
| <property name="maximum"> | |||||
| <number>4000</number> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="6" column="0"> | |||||
| <widget class="QLabel" name="bindingAreaLabel"> | |||||
| <property name="text"> | |||||
| <string>绑定区域</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="6" column="1"> | |||||
| <widget class="QComboBox" name="bindingAreaComboBox"> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>未绑定</string> | |||||
| </property> | |||||
| </item> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>M</string> | |||||
| </property> | |||||
| </item> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>D</string> | |||||
| </property> | |||||
| </item> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="7" column="0"> | |||||
| <widget class="QLabel" name="bindingIndexLabel"> | |||||
| <property name="text"> | |||||
| <string>绑定地址</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="7" column="1"> | |||||
| <widget class="QSpinBox" name="bindingIndexSpinBox"> | |||||
| <property name="maximum"> | |||||
| <number>4000</number> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="8" column="0" colspan="2"> | |||||
| <widget class="QPushButton" name="applyPropertiesButton"> | |||||
| <property name="text"> | |||||
| <string>应用属性</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| </layout> | |||||
| </widget> | |||||
| <widget class="QWidget" name="logicPropertiesPage"> | |||||
| <layout class="QFormLayout" name="logicPropertiesForm"> | |||||
| <property name="fieldGrowthPolicy"> | |||||
| <enum>QFormLayout::AllNonFixedFieldsGrow</enum> | |||||
| </property> | |||||
| <item row="0" column="0"> | |||||
| <widget class="QLabel" name="logicNodeIdLabel"> | |||||
| <property name="text"> | |||||
| <string>节点 ID</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="0" column="1"> | |||||
| <widget class="QLineEdit" name="logicNodeIdEdit"> | |||||
| <property name="readOnly"> | |||||
| <bool>true</bool> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="1" column="0"> | |||||
| <widget class="QLabel" name="logicNodeTypeCaption"> | |||||
| <property name="text"> | |||||
| <string>节点类型</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="1" column="1"> | |||||
| <widget class="QLabel" name="logicNodeTypeLabel"> | |||||
| <property name="text"> | |||||
| <string/> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="2" column="0"> | |||||
| <widget class="QLabel" name="logicAddressAreaCaption"> | |||||
| <property name="text"> | |||||
| <string>地址区域</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="2" column="1"> | |||||
| <widget class="QLabel" name="logicAddressAreaLabel"> | |||||
| <property name="text"> | |||||
| <string/> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="3" column="0"> | |||||
| <widget class="QLabel" name="logicAddressLabel"> | |||||
| <property name="text"> | |||||
| <string>地址</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="3" column="1"> | |||||
| <widget class="QSpinBox" name="logicAddressSpinBox"> | |||||
| <property name="maximum"> | |||||
| <number>4000</number> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="4" column="0"> | |||||
| <widget class="QLabel" name="logicModeLabel"> | |||||
| <property name="text"> | |||||
| <string>工作方式</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="4" column="1"> | |||||
| <widget class="QComboBox" name="logicModeComboBox"/> | |||||
| </item> | |||||
| <item row="5" column="0"> | |||||
| <widget class="QLabel" name="logicComparisonLabel"> | |||||
| <property name="text"> | |||||
| <string>比较运算</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="5" column="1"> | |||||
| <widget class="QComboBox" name="logicComparisonComboBox"> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>等于</string> | |||||
| </property> | |||||
| </item> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>不等于</string> | |||||
| </property> | |||||
| </item> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>小于</string> | |||||
| </property> | |||||
| </item> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>小于等于</string> | |||||
| </property> | |||||
| </item> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>大于</string> | |||||
| </property> | |||||
| </item> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>大于等于</string> | |||||
| </property> | |||||
| </item> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="6" column="0"> | |||||
| <widget class="QLabel" name="logicValueLabel"> | |||||
| <property name="text"> | |||||
| <string>比较常量</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="6" column="1"> | |||||
| <widget class="QSpinBox" name="logicValueSpinBox"> | |||||
| <property name="minimum"> | |||||
| <number>-32768</number> | |||||
| </property> | |||||
| <property name="maximum"> | |||||
| <number>32767</number> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="7" column="0" colspan="2"> | |||||
| <widget class="QPushButton" name="applyLogicPropertiesButton"> | |||||
| <property name="text"> | |||||
| <string>应用属性</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| </layout> | |||||
| </widget> | </widget> | ||||
| </item> | |||||
| </layout> | |||||
| </widget> | |||||
| </item> | |||||
| </layout> | |||||
| </widget> | </widget> | ||||
| </widget> | </widget> | ||||
| </item> | </item> | ||||
| </layout> | </layout> | ||||
| </widget> | </widget> | ||||
| </widget> | </widget> | ||||
| <widget class="QDockWidget" name="outputDock"> | |||||
| <widget class="QDockWidget" name="outputDock"> | |||||
| <property name="minimumSize"> | <property name="minimumSize"> | ||||
| <size> | <size> | ||||
| <width>300</width> | <width>300</width> | ||||
| @@ -509,74 +757,161 @@ | |||||
| </widget> | </widget> | ||||
| </item> | </item> | ||||
| </layout> | </layout> | ||||
| </widget> | |||||
| </widget> | </widget> | ||||
| <widget class="QDockWidget" name="dataPointDock"> | |||||
| <property name="minimumSize"><size><width>420</width><height>170</height></size></property> | |||||
| <property name="windowTitle"><string>数据点</string></property> | |||||
| <attribute name="dockWidgetArea"><number>8</number></attribute> | |||||
| <widget class="QWidget" name="dataPointDockContents"> | |||||
| <layout class="QVBoxLayout" name="dataPointDockLayout"> | |||||
| <property name="leftMargin"><number>6</number></property> | |||||
| <property name="topMargin"><number>6</number></property> | |||||
| <property name="rightMargin"><number>6</number></property> | |||||
| <property name="bottomMargin"><number>6</number></property> | |||||
| <item> | |||||
| <widget class="QTableWidget" name="dataPointTable"> | |||||
| <property name="selectionMode"><enum>QAbstractItemView::SingleSelection</enum></property> | |||||
| <property name="selectionBehavior"><enum>QAbstractItemView::SelectRows</enum></property> | |||||
| <property name="editTriggers"><set>QAbstractItemView::NoEditTriggers</set></property> | |||||
| <column><property name="text"><string>地址</string></property></column> | |||||
| <column><property name="text"><string>类型</string></property></column> | |||||
| <column><property name="text"><string>名称</string></property></column> | |||||
| <column><property name="text"><string>注释</string></property></column> | |||||
| <column><property name="text"><string>当前值</string></property></column> | |||||
| <column><property name="text"><string>引用位置</string></property></column> | |||||
| </widget> | |||||
| </item> | |||||
| <item> | |||||
| <layout class="QHBoxLayout" name="dataPointEditorLayout"> | |||||
| <item><widget class="QLabel" name="dataPointAreaLabel"><property name="text"><string>区域</string></property></widget></item> | |||||
| <item><widget class="QComboBox" name="dataPointAreaComboBox"><item><property name="text"><string>M</string></property><property name="userData"><string notr="true">0</string></property></item><item><property name="text"><string>D</string></property><property name="userData"><string notr="true">1</string></property></item></widget></item> | |||||
| <item><widget class="QLabel" name="dataPointAddressLabel"><property name="text"><string>地址</string></property></widget></item> | |||||
| <item><widget class="QSpinBox" name="dataPointAddressSpinBox"><property name="maximum"><number>4000</number></property></widget></item> | |||||
| <item><widget class="QLabel" name="dataPointNameLabel"><property name="text"><string>名称</string></property></widget></item> | |||||
| <item><widget class="QLineEdit" name="dataPointNameEdit"/></item> | |||||
| <item><widget class="QLabel" name="dataPointCommentLabel"><property name="text"><string>注释</string></property></widget></item> | |||||
| <item><widget class="QLineEdit" name="dataPointCommentEdit"/></item> | |||||
| <item><widget class="QPushButton" name="addDataPointButton"><property name="text"><string>新增</string></property></widget></item> | |||||
| <item><widget class="QPushButton" name="updateDataPointButton"><property name="text"><string>更新</string></property></widget></item> | |||||
| <item><widget class="QPushButton" name="deleteDataPointButton"><property name="text"><string>删除</string></property></widget></item> | |||||
| </layout> | |||||
| </item> | |||||
| </layout> | |||||
| </widget> | |||||
| </widget> | |||||
| <action name="exitAction"> | |||||
| </widget> | |||||
| <action name="exitAction"> | |||||
| <property name="text"> | <property name="text"> | ||||
| <string>退出(&X)</string> | <string>退出(&X)</string> | ||||
| </property> | </property> | ||||
| </action> | |||||
| <action name="newProjectAction"><property name="text"><string>新建工程</string></property></action> | |||||
| <action name="saveProjectAction"><property name="text"><string>保存工程</string></property></action> | |||||
| <action name="saveAsProjectAction"><property name="text"><string>工程另存为</string></property></action> | |||||
| <action name="loadProjectAction"><property name="text"><string>加载工程</string></property></action> | |||||
| <action name="configurePlcAction"><property name="text"><string>PLC 配置</string></property><property name="toolTip"><string>配置参数并连接真实 PLC</string></property></action> | |||||
| <action name="disconnectPlcAction"><property name="text"><string>断开 PLC</string></property><property name="toolTip"><string>断开当前 PLC 连接</string></property></action> | |||||
| <action name="addButtonAction"><property name="text"><string>按钮</string></property><property name="toolTip"><string>添加按钮控件</string></property></action> | |||||
| <action name="addIndicatorAction"><property name="text"><string>指示灯</string></property><property name="toolTip"><string>添加指示灯控件</string></property></action> | |||||
| <action name="addNumericDisplayAction"><property name="text"><string>数值显示</string></property><property name="toolTip"><string>添加数值显示控件</string></property></action> | |||||
| <action name="addNumericInputAction"><property name="text"><string>数值输入</string></property><property name="toolTip"><string>添加数值输入控件</string></property></action> | |||||
| <action name="deleteControlAction"><property name="text"><string>删除</string></property><property name="toolTip"><string>删除当前控件</string></property></action> | |||||
| <action name="addRungAction"><property name="text"><string>新建网络</string></property><property name="toolTip"><string>在梯形图末尾新增网络</string></property></action> | |||||
| <action name="parallelInsertAction"><property name="text"><string>并联支路</string></property><property name="toolTip"><string>为画布中选中的连续节点建立并联支路</string></property></action> | |||||
| <action name="addNormallyOpenAction"><property name="text"><string>常开</string></property><property name="toolTip"><string>向当前网络添加常开触点</string></property></action> | |||||
| <action name="addNormallyClosedAction"><property name="text"><string>常闭</string></property><property name="toolTip"><string>向当前网络添加常闭触点</string></property></action> | |||||
| <action name="addNormalCoilAction"><property name="text"><string>线圈</string></property><property name="toolTip"><string>设置当前网络的普通线圈</string></property></action> | |||||
| <action name="addSetCoilAction"><property name="text"><string>置位</string></property><property name="toolTip"><string>设置当前网络的置位线圈</string></property></action> | |||||
| <action name="addResetCoilAction"><property name="text"><string>复位</string></property><property name="toolTip"><string>设置当前网络的复位线圈</string></property></action> | |||||
| <action name="addCompareAction"><property name="text"><string>D 比较</string></property><property name="toolTip"><string>向当前网络添加 D 值与常量比较</string></property></action> | |||||
| <action name="deleteLogicAction"><property name="text"><string>删除</string></property><property name="toolTip"><string>删除选中的逻辑节点或网络</string></property></action> | |||||
| </action> | |||||
| <action name="newProjectAction"> | |||||
| <property name="text"> | |||||
| <string>新建工程</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="saveProjectAction"> | |||||
| <property name="text"> | |||||
| <string>保存工程</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="saveAsProjectAction"> | |||||
| <property name="text"> | |||||
| <string>工程另存为</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="loadProjectAction"> | |||||
| <property name="text"> | |||||
| <string>加载工程</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="configurePlcAction"> | |||||
| <property name="text"> | |||||
| <string>PLC 配置</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>配置参数并连接真实 PLC</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="disconnectPlcAction"> | |||||
| <property name="text"> | |||||
| <string>断开 PLC</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>断开当前 PLC 连接</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addButtonAction"> | |||||
| <property name="text"> | |||||
| <string>按钮</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>添加按钮控件</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addIndicatorAction"> | |||||
| <property name="text"> | |||||
| <string>指示灯</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>添加指示灯控件</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addNumericDisplayAction"> | |||||
| <property name="text"> | |||||
| <string>数值显示</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>添加数值显示控件</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addNumericInputAction"> | |||||
| <property name="text"> | |||||
| <string>数值输入</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>添加数值输入控件</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="deleteControlAction"> | |||||
| <property name="text"> | |||||
| <string>删除</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>删除当前控件</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addRungAction"> | |||||
| <property name="text"> | |||||
| <string>新建网络</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>在梯形图末尾新增网络</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="parallelInsertAction"> | |||||
| <property name="text"> | |||||
| <string>并联支路</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>为画布中选中的连续节点建立并联支路</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addNormallyOpenAction"> | |||||
| <property name="text"> | |||||
| <string>常开</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>向当前网络添加常开触点</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addNormallyClosedAction"> | |||||
| <property name="text"> | |||||
| <string>常闭</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>向当前网络添加常闭触点</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addNormalCoilAction"> | |||||
| <property name="text"> | |||||
| <string>线圈</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>设置当前网络的普通线圈</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addSetCoilAction"> | |||||
| <property name="text"> | |||||
| <string>置位</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>设置当前网络的置位线圈</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addResetCoilAction"> | |||||
| <property name="text"> | |||||
| <string>复位</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>设置当前网络的复位线圈</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="addCompareAction"> | |||||
| <property name="text"> | |||||
| <string>D 比较</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>向当前网络添加 D 值与常量比较</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="deleteLogicAction"> | |||||
| <property name="text"> | |||||
| <string>删除</string> | |||||
| </property> | |||||
| <property name="toolTip"> | |||||
| <string>删除选中的逻辑节点或网络</string> | |||||
| </property> | |||||
| </action> | |||||
| <action name="editingModeAction"> | <action name="editingModeAction"> | ||||
| <property name="checkable"> | <property name="checkable"> | ||||
| <bool>true</bool> | <bool>true</bool> | ||||
| @@ -1,107 +0,0 @@ | |||||
| #include "domain/project_storage.h" | |||||
| #include "services/data_point_service.h" | |||||
| #include "services/project_service.h" | |||||
| #include <iostream> | |||||
| #include <stdexcept> | |||||
| namespace { | |||||
| class TestProjectStorage final : public ProjectStorage | |||||
| { | |||||
| public: | |||||
| ProjectSaveResult save(const Project &, const std::string &) override | |||||
| { | |||||
| return {true, ProjectStorageError::None, {}}; | |||||
| } | |||||
| ProjectLoadResult load(const std::string &) override | |||||
| { | |||||
| return {false, {}, ProjectStorageError::FileReadFailed, {}}; | |||||
| } | |||||
| }; | |||||
| void require(bool condition, const std::string &message) | |||||
| { | |||||
| if (!condition) | |||||
| { | |||||
| throw std::runtime_error(message); | |||||
| } | |||||
| } | |||||
| void testUniqueDataPointsAndReferences() | |||||
| { | |||||
| TestProjectStorage storage; | |||||
| ProjectService project_service(storage); | |||||
| DataPointService service(project_service); | |||||
| const RegisterAddress m0{RegisterArea::M, 0}; | |||||
| const RegisterAddress m1{RegisterArea::M, 1}; | |||||
| const RegisterAddress d0{RegisterArea::D, 0}; | |||||
| require(service.add({m0, "StartCommand", "启动命令"}).succeeded, | |||||
| "a valid data point must be added"); | |||||
| require(service.add({d0, "Temperature", "温度"}).succeeded, | |||||
| "M and D data points must coexist"); | |||||
| require(service.add({m0, "DuplicateAddress", {}}).error | |||||
| == DataPointError::DuplicateAddress, | |||||
| "duplicate data point addresses must be rejected"); | |||||
| require(service.add({m1, "StartCommand", {}}).error | |||||
| == DataPointError::DuplicateName, | |||||
| "duplicate data point names must be rejected"); | |||||
| HmiControl button; | |||||
| button.id = "start-button"; | |||||
| button.type = HmiControlType::Button; | |||||
| button.bounds = {0, 0, 100, 40}; | |||||
| button.text = "启动"; | |||||
| button.binding = m0; | |||||
| HmiPage page; | |||||
| page.id = "main-page"; | |||||
| page.name = "主画面"; | |||||
| page.controls.push_back(button); | |||||
| project_service.editProject().hmiPages.push_back(page); | |||||
| LogicNode contact; | |||||
| contact.id = "start-contact"; | |||||
| contact.config = ContactNodeConfig{m0, ContactMode::NormallyOpen}; | |||||
| LadderRung rung; | |||||
| rung.id = "rung-1"; | |||||
| rung.name = "网络 1"; | |||||
| rung.condition = ConditionExpression::fromNode(contact); | |||||
| ControlLogic logic; | |||||
| logic.id = "logic-1"; | |||||
| logic.name = "控制逻辑 1"; | |||||
| logic.rungs.push_back(rung); | |||||
| project_service.editProject().controlLogics.push_back(logic); | |||||
| const auto references = service.references(m0); | |||||
| require(references.size() == 2U, | |||||
| "data point references must include HMI and ladder locations"); | |||||
| require(service.remove(m0).error == DataPointError::AddressInUse, | |||||
| "referenced data points must not be deleted"); | |||||
| require(service.update(m0, {m1, "StartCommand", "启动命令"}).error | |||||
| == DataPointError::AddressInUse, | |||||
| "referenced data point addresses must not change"); | |||||
| require(service.update(m0, {m0, "Start", "启动命令"}).succeeded, | |||||
| "referenced data point names and comments may change"); | |||||
| require(service.remove(RegisterAddress{RegisterArea::D, 99}).error | |||||
| == DataPointError::NotFound, | |||||
| "removing an unknown data point must report not found"); | |||||
| } | |||||
| } // namespace | |||||
| int main() | |||||
| { | |||||
| try | |||||
| { | |||||
| testUniqueDataPointsAndReferences(); | |||||
| } | |||||
| catch (const std::exception &error) | |||||
| { | |||||
| std::cerr << "data point service tests failed: " << error.what() << '\n'; | |||||
| return 1; | |||||
| } | |||||
| std::cout << "data point service tests passed\n"; | |||||
| return 0; | |||||
| } | |||||
| @@ -1,29 +0,0 @@ | |||||
| TEMPLATE = app | |||||
| TARGET = data_point_service_tests | |||||
| CONFIG += console c++17 testcase warn_on | |||||
| CONFIG -= app_bundle qt | |||||
| INCLUDEPATH += ../src | |||||
| SOURCES += \ | |||||
| data_point_service_tests.cpp \ | |||||
| ../src/domain/register_address.cpp \ | |||||
| ../src/domain/register_repository.cpp \ | |||||
| ../src/domain/data_point_model.cpp \ | |||||
| ../src/domain/hmi_model.cpp \ | |||||
| ../src/domain/control_logic_model.cpp \ | |||||
| ../src/domain/project_model.cpp \ | |||||
| ../src/services/project_service.cpp \ | |||||
| ../src/services/data_point_service.cpp | |||||
| HEADERS += \ | |||||
| ../src/domain/register_address.h \ | |||||
| ../src/domain/register_repository.h \ | |||||
| ../src/domain/data_point_model.h \ | |||||
| ../src/domain/hmi_model.h \ | |||||
| ../src/domain/control_logic_model.h \ | |||||
| ../src/domain/project_model.h \ | |||||
| ../src/domain/project_storage.h \ | |||||
| ../src/services/project_service.h \ | |||||
| ../src/services/data_point_service.h | |||||
| @@ -10,7 +10,6 @@ SOURCES += \ | |||||
| domain_tests.cpp \ | domain_tests.cpp \ | ||||
| ../src/domain/register_address.cpp \ | ../src/domain/register_address.cpp \ | ||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/data_point_model.cpp \ | |||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| @@ -19,7 +18,6 @@ SOURCES += \ | |||||
| HEADERS += \ | HEADERS += \ | ||||
| ../src/domain/register_address.h \ | ../src/domain/register_address.h \ | ||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/data_point_model.h \ | |||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| @@ -10,7 +10,6 @@ SOURCES += \ | |||||
| hmi_editor_service_tests.cpp \ | hmi_editor_service_tests.cpp \ | ||||
| ../src/domain/register_address.cpp \ | ../src/domain/register_address.cpp \ | ||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/data_point_model.cpp \ | |||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| @@ -21,7 +20,6 @@ SOURCES += \ | |||||
| HEADERS += \ | HEADERS += \ | ||||
| ../src/domain/register_address.h \ | ../src/domain/register_address.h \ | ||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/data_point_model.h \ | |||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| @@ -9,7 +9,6 @@ INCLUDEPATH += ../src | |||||
| SOURCES += \ | SOURCES += \ | ||||
| logic_editor_service_tests.cpp \ | logic_editor_service_tests.cpp \ | ||||
| ../src/domain/register_address.cpp \ | ../src/domain/register_address.cpp \ | ||||
| ../src/domain/data_point_model.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/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| @@ -19,7 +18,6 @@ SOURCES += \ | |||||
| HEADERS += \ | HEADERS += \ | ||||
| ../src/domain/register_address.h \ | ../src/domain/register_address.h \ | ||||
| ../src/domain/data_point_model.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/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| @@ -2,7 +2,6 @@ | |||||
| #include "domain/register_repository.h" | #include "domain/register_repository.h" | ||||
| #include "services/hmi_editor_service.h" | #include "services/hmi_editor_service.h" | ||||
| #include "services/hmi_runtime_service.h" | #include "services/hmi_runtime_service.h" | ||||
| #include "services/data_point_service.h" | |||||
| #include "services/logic_editor_service.h" | #include "services/logic_editor_service.h" | ||||
| #include "services/offline_simulation_service.h" | #include "services/offline_simulation_service.h" | ||||
| #include "services/project_service.h" | #include "services/project_service.h" | ||||
| @@ -66,7 +65,6 @@ void testModeActionsControlEditingAvailability() | |||||
| TestProjectStorage storage; | TestProjectStorage storage; | ||||
| ProjectService project_service(storage); | ProjectService project_service(storage); | ||||
| HmiEditorService editor_service(project_service); | HmiEditorService editor_service(project_service); | ||||
| DataPointService data_point_service(project_service); | |||||
| LogicEditorService logic_editor_service(project_service); | LogicEditorService logic_editor_service(project_service); | ||||
| VirtualRegisterRepository repository; | VirtualRegisterRepository repository; | ||||
| HmiRuntimeService runtime_service(repository); | HmiRuntimeService runtime_service(repository); | ||||
| @@ -76,13 +74,18 @@ void testModeActionsControlEditingAvailability() | |||||
| mode_service, | mode_service, | ||||
| project_service, | project_service, | ||||
| editor_service, | editor_service, | ||||
| data_point_service, | |||||
| logic_editor_service, | logic_editor_service, | ||||
| runtime_service); | runtime_service); | ||||
| window.resize(1000, 640); | window.resize(1000, 640); | ||||
| window.show(); | window.show(); | ||||
| QApplication::processEvents(); | QApplication::processEvents(); | ||||
| require(window.findChild<QWidget *>(QStringLiteral("dataPointDock")) == nullptr, | |||||
| "the removed data point dock must not remain in the main window"); | |||||
| require(window.findChild<QWidget *>(QStringLiteral("hmiDataPointComboBox")) == nullptr | |||||
| && window.findChild<QWidget *>(QStringLiteral("logicDataPointComboBox")) == nullptr, | |||||
| "HMI and ladder properties must use direct M/D address inputs"); | |||||
| QAction *editing_action = requiredChild<QAction>(window, "editingModeAction"); | QAction *editing_action = requiredChild<QAction>(window, "editingModeAction"); | ||||
| QAction *offline_action = requiredChild<QAction>(window, "offlineModeAction"); | QAction *offline_action = requiredChild<QAction>(window, "offlineModeAction"); | ||||
| QAction *online_action = requiredChild<QAction>(window, "onlineModeAction"); | QAction *online_action = requiredChild<QAction>(window, "onlineModeAction"); | ||||
| @@ -238,7 +241,6 @@ void testPlcConfigurationUsesDialog() | |||||
| TestProjectStorage storage; | TestProjectStorage storage; | ||||
| ProjectService project_service(storage); | ProjectService project_service(storage); | ||||
| HmiEditorService editor_service(project_service); | HmiEditorService editor_service(project_service); | ||||
| DataPointService data_point_service(project_service); | |||||
| LogicEditorService logic_editor_service(project_service); | LogicEditorService logic_editor_service(project_service); | ||||
| VirtualRegisterRepository repository; | VirtualRegisterRepository repository; | ||||
| HmiRuntimeService runtime_service(repository); | HmiRuntimeService runtime_service(repository); | ||||
| @@ -248,7 +250,6 @@ void testPlcConfigurationUsesDialog() | |||||
| mode_service, | mode_service, | ||||
| project_service, | project_service, | ||||
| editor_service, | editor_service, | ||||
| data_point_service, | |||||
| logic_editor_service, | logic_editor_service, | ||||
| runtime_service); | runtime_service); | ||||
| require(window.findChild<QComboBox *>(QStringLiteral("serialPortComboBox")) == nullptr, | require(window.findChild<QComboBox *>(QStringLiteral("serialPortComboBox")) == nullptr, | ||||
| @@ -17,13 +17,11 @@ SOURCES += \ | |||||
| ../src/domain/register_address.cpp \ | ../src/domain/register_address.cpp \ | ||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/active_register_repository.cpp \ | ../src/domain/active_register_repository.cpp \ | ||||
| ../src/domain/data_point_model.cpp \ | |||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.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 \ | ||||
| ../src/services/project_service.cpp \ | ../src/services/project_service.cpp \ | ||||
| ../src/services/data_point_service.cpp \ | |||||
| ../src/services/hmi_editor_service.cpp \ | ../src/services/hmi_editor_service.cpp \ | ||||
| ../src/services/logic_editor_service.cpp \ | ../src/services/logic_editor_service.cpp \ | ||||
| ../src/services/hmi_runtime_service.cpp \ | ../src/services/hmi_runtime_service.cpp \ | ||||
| @@ -39,14 +37,12 @@ HEADERS += \ | |||||
| ../src/domain/register_address.h \ | ../src/domain/register_address.h \ | ||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/active_register_repository.h \ | ../src/domain/active_register_repository.h \ | ||||
| ../src/domain/data_point_model.h \ | |||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.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 \ | ||||
| ../src/domain/runtime_state.h \ | ../src/domain/runtime_state.h \ | ||||
| ../src/services/project_service.h \ | ../src/services/project_service.h \ | ||||
| ../src/services/data_point_service.h \ | |||||
| ../src/services/hmi_editor_service.h \ | ../src/services/hmi_editor_service.h \ | ||||
| ../src/services/logic_editor_service.h \ | ../src/services/logic_editor_service.h \ | ||||
| ../src/services/hmi_runtime_service.h \ | ../src/services/hmi_runtime_service.h \ | ||||
| @@ -154,8 +154,17 @@ void testRuntimeRepositorySwitchingAndDisconnect() | |||||
| { | { | ||||
| TestProjectStorage storage; | TestProjectStorage storage; | ||||
| ProjectService project_service(storage); | ProjectService project_service(storage); | ||||
| project_service.editProject().dataPoints.push_back( | |||||
| {{RegisterArea::M, 5}, "RunState", "运行状态"}); | |||||
| HmiPage page; | |||||
| page.id = "main-page"; | |||||
| page.name = "Main"; | |||||
| HmiControl indicator; | |||||
| indicator.id = "run-state"; | |||||
| indicator.type = HmiControlType::Indicator; | |||||
| indicator.bounds = {0, 0, 80, 40}; | |||||
| indicator.text = "Run"; | |||||
| indicator.binding = RegisterAddress{RegisterArea::M, 5}; | |||||
| page.controls.push_back(indicator); | |||||
| project_service.editProject().hmiPages.push_back(page); | |||||
| VirtualRegisterRepository virtual_repository; | VirtualRegisterRepository virtual_repository; | ||||
| PlcRegisterRepository plc_repository; | PlcRegisterRepository plc_repository; | ||||
| ActiveRegisterRepository active_repository(virtual_repository); | ActiveRegisterRepository active_repository(virtual_repository); | ||||
| @@ -13,7 +13,6 @@ SOURCES += \ | |||||
| ../src/domain/register_address.cpp \ | ../src/domain/register_address.cpp \ | ||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/active_register_repository.cpp \ | ../src/domain/active_register_repository.cpp \ | ||||
| ../src/domain/data_point_model.cpp \ | |||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| @@ -28,7 +27,6 @@ HEADERS += \ | |||||
| ../src/domain/register_address.h \ | ../src/domain/register_address.h \ | ||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/active_register_repository.h \ | ../src/domain/active_register_repository.h \ | ||||
| ../src/domain/data_point_model.h \ | |||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| @@ -115,9 +115,6 @@ Project makeExampleProject() | |||||
| project.metadata = {"example-project", "Example project", "1.0"}; | project.metadata = {"example-project", "Example project", "1.0"}; | ||||
| project.hmiPages.push_back(page); | project.hmiPages.push_back(page); | ||||
| project.controlLogics.push_back(logic); | project.controlLogics.push_back(logic); | ||||
| project.dataPoints = { | |||||
| {RegisterAddress{RegisterArea::M, 0}, "StartCommand", "启动命令"}, | |||||
| {RegisterAddress{RegisterArea::D, 2}, "Temperature", "当前温度"}}; | |||||
| return project; | return project; | ||||
| } | } | ||||
| @@ -179,9 +176,10 @@ void testExampleProjectRoundTrip() | |||||
| require(saved_json.contains("\"rungs\"") | require(saved_json.contains("\"rungs\"") | ||||
| && saved_json.contains("\"condition\"") | && saved_json.contains("\"condition\"") | ||||
| && saved_json.contains("\"children\"") | && saved_json.contains("\"children\"") | ||||
| && saved_json.contains("\"dataPoints\"") | |||||
| && saved_json.contains("\"output\""), | && saved_json.contains("\"output\""), | ||||
| "saved project must use structured ladder expressions and data points"); | |||||
| "saved project must use structured ladder expressions"); | |||||
| require(!saved_json.contains("\"dataPoints\""), | |||||
| "saved project must not contain the removed data point model"); | |||||
| require(!saved_json.contains("\"stages\"") | require(!saved_json.contains("\"stages\"") | ||||
| && !saved_json.contains("\"branches\""), | && !saved_json.contains("\"branches\""), | ||||
| "current project format must not contain the removed stage model"); | "current project format must not contain the removed stage model"); | ||||
| @@ -226,10 +224,6 @@ void testExampleProjectRoundTrip() | |||||
| rung.condition->children.at(1).node->config); | rung.condition->children.at(1).node->config); | ||||
| require(compare.address.index() == 2 && compare.value == 100, | require(compare.address.index() == 2 && compare.value == 100, | ||||
| "comparison configuration must survive round trip"); | "comparison configuration must survive round trip"); | ||||
| require(project.dataPoints.size() == 2 | |||||
| && project.dataPoints.front().name == "StartCommand", | |||||
| "data points must survive round trip"); | |||||
| require(service.saveAs(second_path.toStdString()).succeeded, | require(service.saveAs(second_path.toStdString()).succeeded, | ||||
| "save as must succeed after load"); | "save as must succeed after load"); | ||||
| require(readBytes(first_path) == readBytes(second_path), | require(readBytes(first_path) == readBytes(second_path), | ||||
| @@ -12,7 +12,6 @@ SOURCES += \ | |||||
| project_management_tests.cpp \ | project_management_tests.cpp \ | ||||
| ../src/domain/register_address.cpp \ | ../src/domain/register_address.cpp \ | ||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/data_point_model.cpp \ | |||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| @@ -23,7 +22,6 @@ SOURCES += \ | |||||
| HEADERS += \ | HEADERS += \ | ||||
| ../src/domain/register_address.h \ | ../src/domain/register_address.h \ | ||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/data_point_model.h \ | |||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||
| @@ -13,7 +13,6 @@ SOURCES += \ | |||||
| ../src/domain/register_address.cpp \ | ../src/domain/register_address.cpp \ | ||||
| ../src/domain/register_repository.cpp \ | ../src/domain/register_repository.cpp \ | ||||
| ../src/domain/active_register_repository.cpp \ | ../src/domain/active_register_repository.cpp \ | ||||
| ../src/domain/data_point_model.cpp \ | |||||
| ../src/domain/hmi_model.cpp \ | ../src/domain/hmi_model.cpp \ | ||||
| ../src/domain/control_logic_model.cpp \ | ../src/domain/control_logic_model.cpp \ | ||||
| ../src/domain/project_model.cpp \ | ../src/domain/project_model.cpp \ | ||||
| @@ -27,7 +26,6 @@ HEADERS += \ | |||||
| ../src/domain/register_address.h \ | ../src/domain/register_address.h \ | ||||
| ../src/domain/register_repository.h \ | ../src/domain/register_repository.h \ | ||||
| ../src/domain/active_register_repository.h \ | ../src/domain/active_register_repository.h \ | ||||
| ../src/domain/data_point_model.h \ | |||||
| ../src/domain/hmi_model.h \ | ../src/domain/hmi_model.h \ | ||||
| ../src/domain/control_logic_model.h \ | ../src/domain/control_logic_model.h \ | ||||
| ../src/domain/project_model.h \ | ../src/domain/project_model.h \ | ||||