| @@ -8,6 +8,7 @@ | |||||
| #include <cctype> | #include <cctype> | ||||
| #include <cstddef> | #include <cstddef> | ||||
| #include <map> | #include <map> | ||||
| #include <optional> | |||||
| #include <set> | #include <set> | ||||
| #include <utility> | #include <utility> | ||||
| @@ -26,6 +27,68 @@ HmiEditorResult failure(HmiEditorError error, const std::string &message) | |||||
| return {false, error, message, {}}; | return {false, error, message, {}}; | ||||
| } | } | ||||
| int hmiBindingWordCount(const HmiControl &control) | |||||
| { | |||||
| if (control.binding.has_value() && control.binding->area() == RegisterArea::M) | |||||
| { | |||||
| return 1; | |||||
| } | |||||
| if (control.type == HmiControlType::NumericDisplay | |||||
| || control.type == HmiControlType::NumericInput | |||||
| || (control.type == HmiControlType::StatusText | |||||
| && control.binding.has_value() | |||||
| && control.binding->area() == RegisterArea::D)) | |||||
| { | |||||
| return registerDataTypeWordCount(control.dataType); | |||||
| } | |||||
| return 1; | |||||
| } | |||||
| std::optional<RegisterAddress> nextHmiBindingAddress( | |||||
| const Project &project, | |||||
| const HmiControlDescriptor &descriptor, | |||||
| RegisterDataType data_type) | |||||
| { | |||||
| std::optional<RegisterArea> area = hmiBindingArea(descriptor.bindingKind); | |||||
| if (descriptor.bindingKind == HmiBindingKind::BitOrWord) | |||||
| { | |||||
| area = RegisterArea::M; | |||||
| } | |||||
| if (!area.has_value()) | |||||
| { | |||||
| return std::nullopt; | |||||
| } | |||||
| int next_index = RegisterAddress::kMinimumIndex; | |||||
| for (const HmiPage &page : project.hmiPages) | |||||
| { | |||||
| for (const HmiControl &control : page.controls) | |||||
| { | |||||
| if (!control.binding.has_value() | |||||
| || control.binding->area() != *area) | |||||
| { | |||||
| continue; | |||||
| } | |||||
| next_index = std::max( | |||||
| next_index, | |||||
| control.binding->index() + hmiBindingWordCount(control)); | |||||
| } | |||||
| } | |||||
| for (int index = next_index; | |||||
| index <= RegisterAddress::kMaximumIndex; | |||||
| ++index) | |||||
| { | |||||
| const RegisterAddress candidate{*area, index}; | |||||
| if (*area == RegisterArea::D | |||||
| && !registerDataTypeAddressIsValid(data_type, candidate)) | |||||
| { | |||||
| continue; | |||||
| } | |||||
| return candidate; | |||||
| } | |||||
| return std::nullopt; | |||||
| } | |||||
| bool isBlank(const std::string &value) | bool isBlank(const std::string &value) | ||||
| { | { | ||||
| return value.empty() | return value.empty() | ||||
| @@ -459,8 +522,16 @@ HmiEditorResult HmiEditorService::addControl( | |||||
| return failure(HmiEditorError::InvalidControl, "不支持的 HMI 控件类型"); | return failure(HmiEditorError::InvalidControl, "不支持的 HMI 控件类型"); | ||||
| } | } | ||||
| // 新控件初始不绑定寄存器,避免自动分配地址造成误写风险 | |||||
| HmiControl control = makeControl(*page, *descriptor); | HmiControl control = makeControl(*page, *descriptor); | ||||
| const std::optional<RegisterAddress> binding = nextHmiBindingAddress( | |||||
| project_service_.project(), *descriptor, control.dataType); | |||||
| if (descriptor->bindingKind != HmiBindingKind::None && !binding.has_value()) | |||||
| { | |||||
| return failure( | |||||
| HmiEditorError::InvalidControl, | |||||
| "没有可用的 HMI 默认寄存器地址"); | |||||
| } | |||||
| control.binding = binding; | |||||
| HistoryState before = captureState(); | HistoryState before = captureState(); | ||||
| Project &project = project_service_.editProject(); | Project &project = project_service_.editProject(); | ||||
| auto target_page = std::find_if( | auto target_page = std::find_if( | ||||
| @@ -301,7 +301,7 @@ private: | |||||
| * @brief 按控件类型创建带默认属性的新控件 | * @brief 按控件类型创建带默认属性的新控件 | ||||
| * @param page 新控件所属页面,用于确定初始位置和唯一标识 | * @param page 新控件所属页面,用于确定初始位置和唯一标识 | ||||
| * @param descriptor 新控件类型对应的注册描述 | * @param descriptor 新控件类型对应的注册描述 | ||||
| * @return 未绑定寄存器的默认控件配置 | |||||
| * @return 带默认外观和未分配地址的控件配置 | |||||
| */ | */ | ||||
| static HmiControl makeControl( | static HmiControl makeControl( | ||||
| const HmiPage &page, const HmiControlDescriptor &descriptor); | const HmiPage &page, const HmiControlDescriptor &descriptor); | ||||
| @@ -626,38 +626,12 @@ | |||||
| </item> | </item> | ||||
| <item row="6" column="0"> | <item row="6" column="0"> | ||||
| <widget class="QLabel" name="bindingAreaLabel"> | <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"> | <property name="text"> | ||||
| <string>M</string> | |||||
| <string>绑定地址</string> | |||||
| </property> | </property> | ||||
| </item> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>D</string> | |||||
| </property> | |||||
| </item> | |||||
| </widget> | </widget> | ||||
| </item> | </item> | ||||
| <item row="7" column="0"> | |||||
| <widget class="QLabel" name="bindingIndexLabel"> | |||||
| <property name="text"> | |||||
| <string>绑定地址</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item row="7" column="1"> | |||||
| <item row="6" column="1"> | |||||
| <widget class="QSpinBox" name="bindingIndexSpinBox"> | <widget class="QSpinBox" name="bindingIndexSpinBox"> | ||||
| <property name="maximum"> | <property name="maximum"> | ||||
| <number>4000</number> | <number>4000</number> | ||||
| @@ -13,7 +13,6 @@ | |||||
| #include "ui_main_window.h" | #include "ui_main_window.h" | ||||
| #include <QApplication> | #include <QApplication> | ||||
| #include <QCheckBox> | |||||
| #include <QColorDialog> | #include <QColorDialog> | ||||
| #include <QComboBox> | #include <QComboBox> | ||||
| #include <QLabel> | #include <QLabel> | ||||
| @@ -99,9 +98,6 @@ void PropertyPanelController::configure() | |||||
| ui_.fontSizeSpinBox->setRange( | ui_.fontSizeSpinBox->setRange( | ||||
| ProjectLimits::kMinimumHmiFontPointSize, | ProjectLimits::kMinimumHmiFontPointSize, | ||||
| ProjectLimits::kMaximumHmiFontPointSize); | ProjectLimits::kMaximumHmiFontPointSize); | ||||
| ui_.bindingAreaComboBox->setItemData(0, -1); | |||||
| ui_.bindingAreaComboBox->setItemData(1, 0); | |||||
| ui_.bindingAreaComboBox->setItemData(2, 1); | |||||
| ui_.buttonOperationComboBox->setItemData( | ui_.buttonOperationComboBox->setItemData( | ||||
| 0, static_cast<int>(HmiButtonOperation::SetOn)); | 0, static_cast<int>(HmiButtonOperation::SetOn)); | ||||
| ui_.buttonOperationComboBox->setItemData( | ui_.buttonOperationComboBox->setItemData( | ||||
| @@ -205,7 +201,6 @@ void PropertyPanelController::showControlProperties(const std::string &control_i | |||||
| static_cast<QWidget *>(ui_.controlYSpinBox), | static_cast<QWidget *>(ui_.controlYSpinBox), | ||||
| static_cast<QWidget *>(ui_.controlWidthSpinBox), | static_cast<QWidget *>(ui_.controlWidthSpinBox), | ||||
| static_cast<QWidget *>(ui_.controlHeightSpinBox), | static_cast<QWidget *>(ui_.controlHeightSpinBox), | ||||
| static_cast<QWidget *>(ui_.bindingAreaComboBox), | |||||
| static_cast<QWidget *>(ui_.bindingIndexSpinBox), | static_cast<QWidget *>(ui_.bindingIndexSpinBox), | ||||
| static_cast<QWidget *>(ui_.targetPageComboBox), | static_cast<QWidget *>(ui_.targetPageComboBox), | ||||
| static_cast<QWidget *>(ui_.buttonOperationComboBox), | static_cast<QWidget *>(ui_.buttonOperationComboBox), | ||||
| @@ -227,8 +222,6 @@ void PropertyPanelController::showControlProperties(const std::string &control_i | |||||
| ui_.controlTextEdit->setMaxLength( | ui_.controlTextEdit->setMaxLength( | ||||
| static_cast<int>(ProjectLimits::kMaximumHmiControlTextCharacters)); | static_cast<int>(ProjectLimits::kMaximumHmiControlTextCharacters)); | ||||
| ui_.bindingAreaLabel->setVisible(false); | ui_.bindingAreaLabel->setVisible(false); | ||||
| ui_.bindingAreaComboBox->setVisible(false); | |||||
| ui_.bindingIndexLabel->setVisible(false); | |||||
| ui_.bindingIndexSpinBox->setVisible(false); | ui_.bindingIndexSpinBox->setVisible(false); | ||||
| ui_.targetPageLabel->setVisible(false); | ui_.targetPageLabel->setVisible(false); | ||||
| ui_.targetPageComboBox->setVisible(false); | ui_.targetPageComboBox->setVisible(false); | ||||
| @@ -263,17 +256,22 @@ void PropertyPanelController::showControlProperties(const std::string &control_i | |||||
| ui_.controlYSpinBox->setValue(control->bounds.y); | ui_.controlYSpinBox->setValue(control->bounds.y); | ||||
| ui_.controlWidthSpinBox->setValue(control->bounds.width); | ui_.controlWidthSpinBox->setValue(control->bounds.width); | ||||
| ui_.controlHeightSpinBox->setValue(control->bounds.height); | ui_.controlHeightSpinBox->setValue(control->bounds.height); | ||||
| ui_.bindingAreaComboBox->setCurrentIndex(!control->binding.has_value() ? 0 | |||||
| : control->binding->area() == RegisterArea::M ? 1 : 2); | |||||
| const std::optional<RegisterArea> fixed_binding_area = descriptor == nullptr | |||||
| ? std::nullopt : hmiBindingArea(descriptor->bindingKind); | |||||
| ui_.bindingAreaLabel->setText( | |||||
| fixed_binding_area.has_value() | |||||
| ? QObject::tr("绑定地址(%1)") | |||||
| .arg(*fixed_binding_area == RegisterArea::M ? QStringLiteral("M") | |||||
| : QStringLiteral("D")) | |||||
| : QObject::tr("绑定地址")); | |||||
| ui_.bindingIndexSpinBox->setValue( | ui_.bindingIndexSpinBox->setValue( | ||||
| control->binding.has_value() ? control->binding->index() : 0); | control->binding.has_value() ? control->binding->index() : 0); | ||||
| const bool has_binding = descriptor != nullptr | const bool has_binding = descriptor != nullptr | ||||
| && descriptor->bindingKind != HmiBindingKind::None | && descriptor->bindingKind != HmiBindingKind::None | ||||
| && !is_status_text; | && !is_status_text; | ||||
| ui_.bindingAreaLabel->setVisible(has_binding); | ui_.bindingAreaLabel->setVisible(has_binding); | ||||
| ui_.bindingAreaComboBox->setVisible(has_binding); | |||||
| ui_.bindingIndexLabel->setVisible(has_binding); | |||||
| ui_.bindingIndexSpinBox->setVisible(has_binding); | ui_.bindingIndexSpinBox->setVisible(has_binding); | ||||
| ui_.bindingIndexSpinBox->setEnabled(has_binding); | |||||
| const bool is_button = control->type == HmiControlType::Button; | const bool is_button = control->type == HmiControlType::Button; | ||||
| ui_.buttonOperationLabel->setVisible(is_button); | ui_.buttonOperationLabel->setVisible(is_button); | ||||
| @@ -625,17 +623,16 @@ void PropertyPanelController::applySelectedControlProperties() | |||||
| } | } | ||||
| else if (control.type != HmiControlType::StatusText) | else if (control.type != HmiControlType::StatusText) | ||||
| { | { | ||||
| const int binding_area = ui_.bindingAreaComboBox->currentData().toInt(); | |||||
| if (binding_area < 0) | |||||
| const std::optional<RegisterArea> fixed_binding_area = descriptor == nullptr | |||||
| ? std::nullopt : hmiBindingArea(descriptor->bindingKind); | |||||
| if (fixed_binding_area.has_value()) | |||||
| { | { | ||||
| control.binding.reset(); | |||||
| control.binding = RegisterAddress{ | |||||
| *fixed_binding_area, ui_.bindingIndexSpinBox->value()}; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| const RegisterArea area = binding_area == 0 | |||||
| ? RegisterArea::M : RegisterArea::D; | |||||
| control.binding = RegisterAddress{ | |||||
| area, ui_.bindingIndexSpinBox->value()}; | |||||
| control.binding.reset(); | |||||
| } | } | ||||
| } | } | ||||
| if (control.type == HmiControlType::Button) | if (control.type == HmiControlType::Button) | ||||
| @@ -42,6 +42,15 @@ void testControlEditing() | |||||
| const HmiPage *page = service.findPage(page_id); | const HmiPage *page = service.findPage(page_id); | ||||
| require(page != nullptr && page->controls.size() == 4, | require(page != nullptr && page->controls.size() == 4, | ||||
| "all added controls must be kept in the page model"); | "all added controls must be kept in the page model"); | ||||
| require(service.findControl(page_id, button.id)->binding | |||||
| == RegisterAddress{RegisterArea::M, 0} | |||||
| && service.findControl(page_id, indicator.id)->binding | |||||
| == RegisterAddress{RegisterArea::M, 1} | |||||
| && service.findControl(page_id, display.id)->binding | |||||
| == RegisterAddress{RegisterArea::D, 0} | |||||
| && service.findControl(page_id, input.id)->binding | |||||
| == RegisterAddress{RegisterArea::D, 1}, | |||||
| "new basic HMI controls must receive sequential M/D addresses"); | |||||
| require(service.moveControl(page_id, button.id, {120, 80, 120, 40}).succeeded, | require(service.moveControl(page_id, button.id, {120, 80, 120, 40}).succeeded, | ||||
| "a valid control move must succeed"); | "a valid control move must succeed"); | ||||
| require(!service.moveControl(page_id, button.id, {790, 460, 120, 40}).succeeded, | require(!service.moveControl(page_id, button.id, {790, 460, 120, 40}).succeeded, | ||||
| @@ -14,8 +14,10 @@ | |||||
| #include "ui/free_monitor_widget.h" | #include "ui/free_monitor_widget.h" | ||||
| #include "ui/hmi_editor_widget.h" | #include "ui/hmi_editor_widget.h" | ||||
| #include "ui/logic_editor_widget.h" | #include "ui/logic_editor_widget.h" | ||||
| #include "ui/property_panel_controller.h" | |||||
| #include "ui/runtime_monitor_widget.h" | #include "ui/runtime_monitor_widget.h" | ||||
| #include "ui/runtime_panel_controller.h" | #include "ui/runtime_panel_controller.h" | ||||
| #include "ui_main_window.h" | |||||
| #include <QApplication> | #include <QApplication> | ||||
| #include <QCoreApplication> | #include <QCoreApplication> | ||||
| @@ -28,10 +30,12 @@ | |||||
| #include <QKeyEvent> | #include <QKeyEvent> | ||||
| #include <QLabel> | #include <QLabel> | ||||
| #include <QLineEdit> | #include <QLineEdit> | ||||
| #include <QMainWindow> | |||||
| #include <QComboBox> | #include <QComboBox> | ||||
| #include <QMouseEvent> | #include <QMouseEvent> | ||||
| #include <QPainter> | #include <QPainter> | ||||
| #include <QScrollBar> | #include <QScrollBar> | ||||
| #include <QSpinBox> | |||||
| #include <QWidget> | #include <QWidget> | ||||
| #include <algorithm> | #include <algorithm> | ||||
| @@ -204,6 +208,111 @@ void testAlarmListKeepsFixedGeometryWhileRecordsChange() | |||||
| "removing the last alarm row must keep the fixed alarm control visible"); | "removing the last alarm row must keep the fixed alarm control visible"); | ||||
| } | } | ||||
| void testHmiPropertyPanelInfersFixedBindingAreas() | |||||
| { | |||||
| TestProjectStorage storage; | |||||
| ProjectService project_service(storage, defaultProjectLimitSettings()); | |||||
| VirtualRegisterRepository repository; | |||||
| HmiDefaultSettings hmi_defaults; | |||||
| HmiEditorService hmi_editor_service(project_service, hmi_defaults); | |||||
| HmiRuntimeService hmi_runtime_service(repository); | |||||
| AlarmService alarm_service(project_service, repository); | |||||
| LogicEditorService logic_editor_service(project_service); | |||||
| const HmiEditorResult page = hmi_editor_service.ensureDefaultPage(); | |||||
| const HmiEditorResult button = hmi_editor_service.addControl( | |||||
| page.id, HmiControlType::Button); | |||||
| const HmiEditorResult second_button = hmi_editor_service.addControl( | |||||
| page.id, HmiControlType::Button); | |||||
| const HmiEditorResult display = hmi_editor_service.addControl( | |||||
| page.id, HmiControlType::NumericDisplay); | |||||
| const HmiEditorResult second_display = hmi_editor_service.addControl( | |||||
| page.id, HmiControlType::NumericDisplay); | |||||
| require(page.succeeded && button.succeeded && second_button.succeeded | |||||
| && display.succeeded && second_display.succeeded, | |||||
| "property-panel fixture must create its page and controls"); | |||||
| const HmiControl *default_button = hmi_editor_service.findControl( | |||||
| page.id, button.id); | |||||
| const HmiControl *default_second_button = hmi_editor_service.findControl( | |||||
| page.id, second_button.id); | |||||
| const HmiControl *default_display = hmi_editor_service.findControl( | |||||
| page.id, display.id); | |||||
| const HmiControl *default_second_display = hmi_editor_service.findControl( | |||||
| page.id, second_display.id); | |||||
| require(default_button != nullptr && default_second_button != nullptr | |||||
| && default_display != nullptr && default_second_display != nullptr | |||||
| && default_button->binding | |||||
| == RegisterAddress{RegisterArea::M, 0} | |||||
| && default_second_button->binding | |||||
| == RegisterAddress{RegisterArea::M, 1} | |||||
| && default_display->binding | |||||
| == RegisterAddress{RegisterArea::D, 0} | |||||
| && default_second_display->binding | |||||
| == RegisterAddress{RegisterArea::D, 1}, | |||||
| "new HMI controls must receive sequential default M/D addresses"); | |||||
| QMainWindow parent; | |||||
| Ui::MainWindow ui; | |||||
| ui.setupUi(&parent); | |||||
| HmiEditorWidget hmi_editor_widget( | |||||
| hmi_editor_service, hmi_runtime_service, alarm_service, &parent); | |||||
| LogicEditorWidget logic_editor_widget(logic_editor_service, &parent); | |||||
| hmi_editor_widget.setPageId(page.id); | |||||
| std::string selected_control_id; | |||||
| std::string selected_logic_node_id; | |||||
| PropertyPanelController controller( | |||||
| parent, | |||||
| ui, | |||||
| project_service, | |||||
| hmi_editor_service, | |||||
| logic_editor_service, | |||||
| hmi_defaults, | |||||
| [&page] { return page.id; }, | |||||
| [] { return std::string{}; }, | |||||
| selected_control_id, | |||||
| selected_logic_node_id, | |||||
| [] {}, | |||||
| [](const QString &, const QString &message, bool succeeded) | |||||
| { | |||||
| require(succeeded, message.toStdString()); | |||||
| }, | |||||
| [](const QString &, int) {}); | |||||
| controller.configure(); | |||||
| controller.bindEditorWidgets(hmi_editor_widget, logic_editor_widget); | |||||
| controller.showControlProperties(button.id); | |||||
| require(ui.bindingAreaLabel->text() | |||||
| == QStringLiteral("绑定地址(M)") | |||||
| && ui.bindingIndexSpinBox->isEnabled() | |||||
| && ui.bindingIndexSpinBox->value() == 0, | |||||
| "button properties must show the fixed M address"); | |||||
| ui.bindingIndexSpinBox->setValue(17); | |||||
| controller.applySelectedControlProperties(); | |||||
| const HmiControl *updated_button = hmi_editor_service.findControl( | |||||
| page.id, button.id); | |||||
| require(updated_button != nullptr | |||||
| && updated_button->binding | |||||
| == RegisterAddress{RegisterArea::M, 17}, | |||||
| "button property submission must infer the M area"); | |||||
| controller.showControlProperties(display.id); | |||||
| require(ui.bindingAreaLabel->text() | |||||
| == QStringLiteral("绑定地址(D)") | |||||
| && ui.bindingIndexSpinBox->isEnabled() | |||||
| && ui.bindingIndexSpinBox->value() == 0, | |||||
| "numeric properties must show the fixed D address"); | |||||
| ui.bindingIndexSpinBox->setValue(23); | |||||
| controller.applySelectedControlProperties(); | |||||
| const HmiControl *updated_display = hmi_editor_service.findControl( | |||||
| page.id, display.id); | |||||
| require(updated_display != nullptr | |||||
| && updated_display->binding | |||||
| == RegisterAddress{RegisterArea::D, 23}, | |||||
| "numeric property submission must infer the D area"); | |||||
| } | |||||
| void testQueuedOfflineTraceIsIgnoredAfterReturningToEditing() | void testQueuedOfflineTraceIsIgnoredAfterReturningToEditing() | ||||
| { | { | ||||
| TestProjectStorage storage; | TestProjectStorage storage; | ||||
| @@ -1283,6 +1392,7 @@ int main(int argc, char *argv[]) | |||||
| testAlarmConfigurationOffersMOnAndMOff(); | testAlarmConfigurationOffersMOnAndMOff(); | ||||
| testMonitorOffersAllNumericTypes(); | testMonitorOffersAllNumericTypes(); | ||||
| testAlarmListKeepsFixedGeometryWhileRecordsChange(); | testAlarmListKeepsFixedGeometryWhileRecordsChange(); | ||||
| testHmiPropertyPanelInfersFixedBindingAreas(); | |||||
| testQueuedOfflineTraceIsIgnoredAfterReturningToEditing(); | testQueuedOfflineTraceIsIgnoredAfterReturningToEditing(); | ||||
| testLogicEditorGridSelectionAndDeletion(); | testLogicEditorGridSelectionAndDeletion(); | ||||
| testLadderLayoutAndDragDeletion(); | testLadderLayoutAndDragDeletion(); | ||||
| @@ -16,11 +16,15 @@ SOURCES += \ | |||||
| $$SERVICE_RUNTIME_SOURCES \ | $$SERVICE_RUNTIME_SOURCES \ | ||||
| $$SERVICE_MONITOR_SOURCES \ | $$SERVICE_MONITOR_SOURCES \ | ||||
| ../src/ui/alarm_configuration_dialog.cpp \ | ../src/ui/alarm_configuration_dialog.cpp \ | ||||
| ../src/ui/button_extension_dialog.cpp \ | |||||
| ../src/ui/hmi_editor_widget.cpp \ | ../src/ui/hmi_editor_widget.cpp \ | ||||
| ../src/ui/logic_instruction_dialog.cpp \ | |||||
| ../src/ui/logic_editor_widget.cpp \ | ../src/ui/logic_editor_widget.cpp \ | ||||
| ../src/ui/property_panel_controller.cpp \ | |||||
| ../src/ui/free_monitor_widget.cpp \ | ../src/ui/free_monitor_widget.cpp \ | ||||
| ../src/ui/runtime_monitor_window.cpp \ | ../src/ui/runtime_monitor_window.cpp \ | ||||
| ../src/ui/runtime_monitor_widget.cpp \ | ../src/ui/runtime_monitor_widget.cpp \ | ||||
| ../src/ui/status_text_dialog.cpp \ | |||||
| ../src/ui/toolbar_icon_factory.cpp \ | ../src/ui/toolbar_icon_factory.cpp \ | ||||
| ../src/ui/runtime_panel_controller.cpp | ../src/ui/runtime_panel_controller.cpp | ||||
| @@ -35,17 +39,25 @@ HEADERS += \ | |||||
| $$SERVICE_MONITOR_HEADERS \ | $$SERVICE_MONITOR_HEADERS \ | ||||
| ../src/services/plc_communication_gateway.h \ | ../src/services/plc_communication_gateway.h \ | ||||
| ../src/ui/alarm_configuration_dialog.h \ | ../src/ui/alarm_configuration_dialog.h \ | ||||
| ../src/ui/button_extension_dialog.h \ | |||||
| ../src/ui/hmi_editor_widget.h \ | ../src/ui/hmi_editor_widget.h \ | ||||
| ../src/ui/logic_instruction_dialog.h \ | |||||
| ../src/ui/logic_editor_widget.h \ | ../src/ui/logic_editor_widget.h \ | ||||
| ../src/ui/property_panel_controller.h \ | |||||
| ../src/ui/free_monitor_widget.h \ | ../src/ui/free_monitor_widget.h \ | ||||
| ../src/ui/runtime_monitor_window.h \ | ../src/ui/runtime_monitor_window.h \ | ||||
| ../src/ui/runtime_monitor_widget.h \ | ../src/ui/runtime_monitor_widget.h \ | ||||
| ../src/ui/status_text_dialog.h \ | |||||
| ../src/ui/toolbar_icon_factory.h \ | ../src/ui/toolbar_icon_factory.h \ | ||||
| ../src/ui/runtime_panel_controller.h \ | ../src/ui/runtime_panel_controller.h \ | ||||
| $$TEST_SUPPORT_HEADERS | $$TEST_SUPPORT_HEADERS | ||||
| FORMS += \ | FORMS += \ | ||||
| ../src/ui/alarm_configuration_dialog.ui \ | ../src/ui/alarm_configuration_dialog.ui \ | ||||
| ../src/ui/button_extension_dialog.ui \ | |||||
| ../src/ui/free_monitor_widget.ui \ | ../src/ui/free_monitor_widget.ui \ | ||||
| ../src/ui/logic_instruction_dialog.ui \ | |||||
| ../src/ui/main_window.ui \ | |||||
| ../src/ui/runtime_monitor_window.ui \ | ../src/ui/runtime_monitor_window.ui \ | ||||
| ../src/ui/runtime_monitor_widget.ui | |||||
| ../src/ui/runtime_monitor_widget.ui \ | |||||
| ../src/ui/status_text_dialog.ui | |||||