Просмотр исходного кода

feat: 优化报警显示并支持M OFF条件

main
suyu 3 недель назад
Родитель
Сommit
6345148bb7
11 измененных файлов: 194 добавлений и 54 удалений
  1. +3
    -2
      app/src/domain/alarm_model.cpp
  2. +2
    -1
      app/src/domain/alarm_model.h
  3. +8
    -0
      app/src/infrastructure/json_project_storage.cpp
  4. +9
    -3
      app/src/services/alarm_service.cpp
  5. +1
    -1
      app/src/services/alarm_service.h
  6. +8
    -1
      app/src/ui/alarm_configuration_dialog.cpp
  7. +6
    -43
      app/src/ui/hmi_editor_widget.cpp
  8. +21
    -3
      app/tests/alarm_service_tests.cpp
  9. +30
    -0
      app/tests/project_management_tests.cpp
  10. +103
    -0
      app/tests/runtime_panel_controller_tests.cpp
  11. +3
    -0
      app/tests/runtime_panel_controller_tests.pro

+ 3
- 2
app/src/domain/alarm_model.cpp Просмотреть файл

@@ -41,11 +41,12 @@ bool AlarmDefinition::validate(std::string *error) const
setError(error, "报警定义使用了无效地址"); setError(error, "报警定义使用了无效地址");
return false; return false;
} }
if (condition == AlarmCondition::MOn)
if (condition == AlarmCondition::MOn
|| condition == AlarmCondition::MOff)
{ {
if (address.area() != RegisterArea::M) if (address.area() != RegisterArea::M)
{ {
setError(error, "M ON 报警必须使用 M 地址");
setError(error, "M ON/OFF 报警必须使用 M 地址");
return false; return false;
} }
return true; return true;


+ 2
- 1
app/src/domain/alarm_model.h Просмотреть файл

@@ -5,10 +5,11 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>


// 报警触发条件:M 位为 1,或 D 字高于/低于阈值
// 报警触发条件:M 位为 1/0,或 D 字高于/低于阈值
enum class AlarmCondition enum class AlarmCondition
{ {
MOn, // M 位为 1 时触发 MOn, // M 位为 1 时触发
MOff, // M 位为 0 时触发
DHigh, // D 寄存器值高于阈值时触发 DHigh, // D 寄存器值高于阈值时触发
DLow // D 寄存器值低于阈值时触发 DLow // D 寄存器值低于阈值时触发
}; };


+ 8
- 0
app/src/infrastructure/json_project_storage.cpp Просмотреть файл

@@ -434,6 +434,10 @@ QString alarmConditionName(AlarmCondition condition)
{ {
return QStringLiteral("mOn"); return QStringLiteral("mOn");
} }
case AlarmCondition::MOff:
{
return QStringLiteral("mOff");
}
case AlarmCondition::DHigh: case AlarmCondition::DHigh:
{ {
return QStringLiteral("dHigh"); return QStringLiteral("dHigh");
@@ -456,6 +460,10 @@ bool parseAlarmCondition(
{ {
*condition = AlarmCondition::MOn; *condition = AlarmCondition::MOn;
} }
else if (value == "mOff")
{
*condition = AlarmCondition::MOff;
}
else if (value == "dHigh") else if (value == "dHigh")
{ {
*condition = AlarmCondition::DHigh; *condition = AlarmCondition::DHigh;


+ 9
- 3
app/src/services/alarm_service.cpp Просмотреть файл

@@ -78,11 +78,17 @@ const std::vector<AlarmRecord> &AlarmService::records() const
std::optional<bool> AlarmService::evaluate( std::optional<bool> AlarmService::evaluate(
const AlarmDefinition &definition) const const AlarmDefinition &definition) const
{ {
if (definition.condition == AlarmCondition::MOn)
if (definition.condition == AlarmCondition::MOn
|| definition.condition == AlarmCondition::MOff)
{ {
// MOn 报警直接读取 M 位;读取失败返回空值,交由 refresh 保留旧记录
// M ON/OFF 共用一次位读取;读取失败时保留旧记录
const BitReadResult value = repository_.readBit(definition.address); const BitReadResult value = repository_.readBit(definition.address);
return value.succeeded ? std::optional<bool>{value.value} : std::nullopt;
if (!value.succeeded)
{
return std::nullopt;
}
return definition.condition == AlarmCondition::MOn
? value.value : !value.value;
} }
// DHigh 和 DLow 报警读取 D 字,比较方向由定义中的条件决定 // DHigh 和 DLow 报警读取 D 字,比较方向由定义中的条件决定
const WordReadResult value = repository_.readWord(definition.address); const WordReadResult value = repository_.readWord(definition.address);


+ 1
- 1
app/src/services/alarm_service.h Просмотреть файл

@@ -64,7 +64,7 @@ private:
* @param definition 待评估的报警定义 * @param definition 待评估的报警定义
* @return true 表示触发,false 表示未触发;读取失败时返回空值 * @return true 表示触发,false 表示未触发;读取失败时返回空值
* *
* MOn 比较 M 位是否为 1;DHigh 使用大于等于阈值,DLow 使用小于等于阈值
* MOn/MOff 比较 M 位是否为 1/0;DHigh 使用大于等于阈值,DLow 使用小于等于阈值
*/ */
std::optional<bool> evaluate(const AlarmDefinition &definition) const; std::optional<bool> evaluate(const AlarmDefinition &definition) const;




+ 8
- 1
app/src/ui/alarm_configuration_dialog.cpp Просмотреть файл

@@ -29,6 +29,10 @@ QString conditionText(AlarmCondition condition)
{ {
return AlarmConfigurationDialog::tr("M 为 ON"); return AlarmConfigurationDialog::tr("M 为 ON");
} }
case AlarmCondition::MOff:
{
return AlarmConfigurationDialog::tr("M 为 OFF");
}
case AlarmCondition::DHigh: case AlarmCondition::DHigh:
{ {
return AlarmConfigurationDialog::tr("D 大于等于阈值"); return AlarmConfigurationDialog::tr("D 大于等于阈值");
@@ -109,7 +113,7 @@ void AlarmConfigurationDialog::reloadDefinitions(const std::string &selected_id)
row, row,
3, 3,
new QTableWidgetItem( new QTableWidgetItem(
definition.condition == AlarmCondition::MOn
definition.address.area() == RegisterArea::M
? QStringLiteral("-") ? QStringLiteral("-")
: QString::number(definition.threshold))); : QString::number(definition.threshold)));
ui_->alarmTable->setItem( ui_->alarmTable->setItem(
@@ -162,6 +166,9 @@ void AlarmConfigurationDialog::updateConditionOptions()
ui_->conditionComboBox->addItem( ui_->conditionComboBox->addItem(
conditionText(AlarmCondition::MOn), conditionText(AlarmCondition::MOn),
static_cast<int>(AlarmCondition::MOn)); static_cast<int>(AlarmCondition::MOn));
ui_->conditionComboBox->addItem(
conditionText(AlarmCondition::MOff),
static_cast<int>(AlarmCondition::MOff));
} }
else else
{ {


+ 6
- 43
app/src/ui/hmi_editor_widget.cpp Просмотреть файл

@@ -83,9 +83,9 @@ public:
{ {
if (!control_.binding.has_value()) if (!control_.binding.has_value())
{ {
return visibleControlRect();
return controlRect();
} }
return visibleControlRect().united(addressRect());
return controlRect().united(addressRect());
} }


void paint( void paint(
@@ -94,7 +94,7 @@ public:
QWidget *) override QWidget *) override
{ {
// 留出一个像素边距,避免描边被图元边界裁剪 // 留出一个像素边距,避免描边被图元边界裁剪
const QRectF rect = visibleControlRect().adjusted(1, 1, -1, -1);
const QRectF rect = controlRect().adjusted(1, 1, -1, -1);
painter->setRenderHint(QPainter::Antialiasing, true); painter->setRenderHint(QPainter::Antialiasing, true);
painter->setPen(QPen(QColor(QStringLiteral("#47545f")), 1)); painter->setPen(QPen(QColor(QStringLiteral("#47545f")), 1));


@@ -363,13 +363,9 @@ public:
void setInteractionState( void setInteractionState(
bool editable, bool runtime_active, bool runtime_write_enabled) bool editable, bool runtime_active, bool runtime_write_enabled)
{ {
if (control_.type == HmiControlType::AlarmList)
if (control_.type == HmiControlType::AlarmList && !runtime_active)
{ {
prepareGeometryChange();
if (!runtime_active)
{
alarm_page_ = 0U;
}
alarm_page_ = 0U;
} }
editing_enabled_ = editable; editing_enabled_ = editable;
runtime_active_ = runtime_active; runtime_active_ = runtime_active;
@@ -412,7 +408,6 @@ public:
page_hovered_ = false; page_hovered_ = false;
button_pressed_ = false; button_pressed_ = false;
} }
updateAlarmVisibility();
update(); update();
} }


@@ -429,15 +424,10 @@ public:


void setAlarmRecords(const std::vector<AlarmRecord> &records) void setAlarmRecords(const std::vector<AlarmRecord> &records)
{ {
if (control_.type == HmiControlType::AlarmList)
{
prepareGeometryChange();
}
alarm_records_ = records; alarm_records_ = records;
const std::size_t page_count = alarmPageCount(); const std::size_t page_count = alarmPageCount();
alarm_page_ = page_count == 0U alarm_page_ = page_count == 0U
? 0U : std::min(alarm_page_, page_count - 1U); ? 0U : std::min(alarm_page_, page_count - 1U);
updateAlarmVisibility();
update(); update();
} }


@@ -469,7 +459,7 @@ protected:
if (event->pos().y() < kAlarmHeaderHeight) if (event->pos().y() < kAlarmHeaderHeight)
{ {
const QRectF content_rect = const QRectF content_rect =
visibleControlRect().adjusted(1, 1, -1, -1);
controlRect().adjusted(1, 1, -1, -1);
const QRectF header( const QRectF header(
content_rect.left(), content_rect.left(),
content_rect.top(), content_rect.top(),
@@ -644,22 +634,6 @@ private:
alarmPageSize(), alarm_records_.size() - first_record); alarmPageSize(), alarm_records_.size() - first_record);
} }


QRectF visibleControlRect() const
{
const QRectF full_rect = controlRect();
if (control_.type != HmiControlType::AlarmList || !runtime_active_)
{
return full_rect;
}
const qreal content_height = kAlarmHeaderHeight
+ static_cast<qreal>(visibleAlarmRecordCount()) * kAlarmRowHeight
+ 2.0;
return {full_rect.left(),
full_rect.top(),
full_rect.width(),
std::min(full_rect.height(), content_height)};
}

QRectF alarmNextPageRect(const QRectF &header) const QRectF alarmNextPageRect(const QRectF &header) const
{ {
return { return {
@@ -689,17 +663,6 @@ private:
kAlarmPageButtonSize}; kAlarmPageButtonSize};
} }


void updateAlarmVisibility()
{
if (control_.type != HmiControlType::AlarmList)
{
return;
}
const bool has_active_alarm = !alarm_records_.empty();
setVisible(editing_enabled_ || !runtime_active_ || has_active_alarm);
setZValue(runtime_active_ && has_active_alarm ? 1000.0 : 0.0);
}

// 控件本体范围保持领域坐标和尺寸语义不变 // 控件本体范围保持领域坐标和尺寸语义不变
QRectF controlRect() const QRectF controlRect() const
{ {


+ 21
- 3
app/tests/alarm_service_tests.cpp Просмотреть файл

@@ -44,6 +44,13 @@ void testAlarmDefinitionsAndRuntimeLifecycle()
m_alarm.message = "Emergency stop"; m_alarm.message = "Emergency stop";
const AlarmEditorResult m_result = editor_service.addDefinition(m_alarm); const AlarmEditorResult m_result = editor_service.addDefinition(m_alarm);


AlarmDefinition m_off_alarm;
m_off_alarm.address = RegisterAddress{RegisterArea::M, 1};
m_off_alarm.condition = AlarmCondition::MOff;
m_off_alarm.message = "Safety circuit open";
const AlarmEditorResult m_off_result = editor_service.addDefinition(
m_off_alarm);

AlarmDefinition high_alarm; AlarmDefinition high_alarm;
high_alarm.address = RegisterAddress{RegisterArea::D, 0}; high_alarm.address = RegisterAddress{RegisterArea::D, 0};
high_alarm.condition = AlarmCondition::DHigh; high_alarm.condition = AlarmCondition::DHigh;
@@ -57,8 +64,9 @@ void testAlarmDefinitionsAndRuntimeLifecycle()
low_alarm.threshold = 10; low_alarm.threshold = 10;
low_alarm.message = "Pressure low"; low_alarm.message = "Pressure low";
const AlarmEditorResult low_result = editor_service.addDefinition(low_alarm); const AlarmEditorResult low_result = editor_service.addDefinition(low_alarm);
require(m_result.succeeded && high_result.succeeded && low_result.succeeded,
"M, D high and D low alarm definitions must be accepted");
require(m_result.succeeded && m_off_result.succeeded
&& high_result.succeeded && low_result.succeeded,
"M ON, M OFF, D high and D low alarms must be accepted");


AlarmDefinition invalid = high_alarm; AlarmDefinition invalid = high_alarm;
invalid.address = RegisterAddress{RegisterArea::M, 2}; invalid.address = RegisterAddress{RegisterArea::M, 2};
@@ -66,24 +74,34 @@ void testAlarmDefinitionsAndRuntimeLifecycle()
== AlarmEditorError::InvalidDefinition, == AlarmEditorError::InvalidDefinition,
"D alarm conditions must reject M addresses"); "D alarm conditions must reject M addresses");


invalid = m_off_alarm;
invalid.address = RegisterAddress{RegisterArea::D, 2};
require(editor_service.addDefinition(invalid).error
== AlarmEditorError::InvalidDefinition,
"M OFF alarm conditions must reject D addresses");

repository.writeBit(RegisterAddress{RegisterArea::M, 1}, true);
repository.writeWord(RegisterAddress{RegisterArea::D, 1}, 20); repository.writeWord(RegisterAddress{RegisterArea::D, 1}, 20);
alarm_service.refresh(); alarm_service.refresh();
require(alarm_service.records().empty(), require(alarm_service.records().empty(),
"inactive alarm conditions must not create records"); "inactive alarm conditions must not create records");


repository.writeBit(RegisterAddress{RegisterArea::M, 0}, true); repository.writeBit(RegisterAddress{RegisterArea::M, 0}, true);
repository.writeBit(RegisterAddress{RegisterArea::M, 1}, false);
repository.writeWord(RegisterAddress{RegisterArea::D, 0}, 80); repository.writeWord(RegisterAddress{RegisterArea::D, 0}, 80);
repository.writeWord(RegisterAddress{RegisterArea::D, 1}, 10); repository.writeWord(RegisterAddress{RegisterArea::D, 1}, 10);
alarm_service.refresh(); alarm_service.refresh();
require(findRecord(alarm_service, m_result.id) != nullptr require(findRecord(alarm_service, m_result.id) != nullptr
&& findRecord(alarm_service, m_off_result.id) != nullptr
&& findRecord(alarm_service, high_result.id) != nullptr && findRecord(alarm_service, high_result.id) != nullptr
&& findRecord(alarm_service, low_result.id) != nullptr, && findRecord(alarm_service, low_result.id) != nullptr,
"all three alarm conditions must create active records");
"all four alarm conditions must create active records");
require(alarm_service.acknowledge(m_result.id) require(alarm_service.acknowledge(m_result.id)
&& findRecord(alarm_service, m_result.id)->acknowledged, && findRecord(alarm_service, m_result.id)->acknowledged,
"an active alarm must be locally acknowledged"); "an active alarm must be locally acknowledged");


repository.writeBit(RegisterAddress{RegisterArea::M, 0}, false); repository.writeBit(RegisterAddress{RegisterArea::M, 0}, false);
repository.writeBit(RegisterAddress{RegisterArea::M, 1}, true);
repository.writeWord(RegisterAddress{RegisterArea::D, 0}, 79); repository.writeWord(RegisterAddress{RegisterArea::D, 0}, 79);
repository.writeWord(RegisterAddress{RegisterArea::D, 1}, 11); repository.writeWord(RegisterAddress{RegisterArea::D, 1}, 11);
alarm_service.refresh(); alarm_service.refresh();


+ 30
- 0
app/tests/project_management_tests.cpp Просмотреть файл

@@ -221,6 +221,35 @@ void testGridProjectRoundTrip()
"typed ladder instructions must survive grid round trip"); "typed ladder instructions must survive grid round trip");
} }


void testMOffAlarmRoundTrip()
{
QTemporaryDir directory;
require(directory.isValid(), "temporary directory must be valid");
JsonProjectStorage storage;
const QString path = directory.filePath("m-off-alarm.json");
Project project = makeExampleProject();
project.alarmDefinitions.push_back({
"alarm-m-off",
RegisterAddress{RegisterArea::M, 5},
AlarmCondition::MOff,
0,
"Safety circuit open"});

require(storage.save(project, path.toStdString()).succeeded,
"an M OFF alarm project must save");
require(readBytes(path).contains("\"condition\": \"mOff\""),
"M OFF alarms must serialize with the explicit mOff condition");

const ProjectLoadResult loaded = storage.load(path.toStdString());
require(loaded.succeeded
&& loaded.project.alarmDefinitions.size() == 1U
&& loaded.project.alarmDefinitions.front().condition
== AlarmCondition::MOff
&& loaded.project.alarmDefinitions.front().address
== RegisterAddress{RegisterArea::M, 5},
"the M OFF condition and address must survive JSON round trip");
}

void testStrictVersionAndRequiredFields() void testStrictVersionAndRequiredFields()
{ {
QTemporaryDir directory; QTemporaryDir directory;
@@ -390,6 +419,7 @@ int main()
{ {
testEmptyProjectRoundTrip(); testEmptyProjectRoundTrip();
testGridProjectRoundTrip(); testGridProjectRoundTrip();
testMOffAlarmRoundTrip();
testStrictVersionAndRequiredFields(); testStrictVersionAndRequiredFields();
testInvalidGridAndConnectionsAreRejected(); testInvalidGridAndConnectionsAreRejected();
testProjectServiceStateAndConfiguredLimits(); testProjectServiceStateAndConfiguredLimits();


+ 103
- 0
app/tests/runtime_panel_controller_tests.cpp Просмотреть файл

@@ -1,4 +1,5 @@
#include "domain/virtual_register_repository.h" #include "domain/virtual_register_repository.h"
#include "services/alarm_editor_service.h"
#include "services/alarm_service.h" #include "services/alarm_service.h"
#include "services/hmi_editor_service.h" #include "services/hmi_editor_service.h"
#include "services/hmi_navigation_service.h" #include "services/hmi_navigation_service.h"
@@ -9,6 +10,7 @@
#include "services/register_monitor_service.h" #include "services/register_monitor_service.h"
#include "services/runtime_mode_service.h" #include "services/runtime_mode_service.h"
#include "support/test_support.h" #include "support/test_support.h"
#include "ui/alarm_configuration_dialog.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/runtime_monitor_widget.h" #include "ui/runtime_monitor_widget.h"
@@ -18,12 +20,14 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QEventLoop> #include <QEventLoop>
#include <QGraphicsLineItem> #include <QGraphicsLineItem>
#include <QGraphicsRectItem>
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QGraphicsSimpleTextItem> #include <QGraphicsSimpleTextItem>
#include <QImage> #include <QImage>
#include <QKeyEvent> #include <QKeyEvent>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QComboBox>
#include <QMouseEvent> #include <QMouseEvent>
#include <QPainter> #include <QPainter>
#include <QWidget> #include <QWidget>
@@ -66,6 +70,103 @@ ControlLogic makeAlwaysOnLogic()
return logic; return logic;
} }


void testAlarmConfigurationOffersMOnAndMOff()
{
TestProjectStorage storage;
ProjectService project_service(storage);
AlarmEditorService alarm_editor_service(project_service);
AlarmConfigurationDialog dialog(alarm_editor_service);

QComboBox *area_combo = dialog.findChild<QComboBox *>(
QStringLiteral("areaComboBox"));
QComboBox *condition_combo = dialog.findChild<QComboBox *>(
QStringLiteral("conditionComboBox"));
require(area_combo != nullptr && condition_combo != nullptr,
"alarm configuration must expose its area and condition inputs");
require(area_combo->currentData().toInt()
== static_cast<int>(RegisterArea::M)
&& condition_combo->count() == 2
&& condition_combo->findData(
static_cast<int>(AlarmCondition::MOn)) >= 0
&& condition_combo->findData(
static_cast<int>(AlarmCondition::MOff)) >= 0
&& condition_combo->findText(QStringLiteral("M 为 ON")) >= 0
&& condition_combo->findText(QStringLiteral("M 为 OFF")) >= 0,
"M alarm configuration must offer both ON and OFF conditions");
}

void testAlarmListKeepsFixedGeometryWhileRecordsChange()
{
TestProjectStorage storage;
ProjectService project_service(storage);
VirtualRegisterRepository virtual_repository;
HmiEditorService hmi_editor_service(project_service);
HmiRuntimeService hmi_runtime_service(virtual_repository);
AlarmService alarm_service(project_service, virtual_repository);

const HmiEditorResult page = hmi_editor_service.ensureDefaultPage();
const HmiEditorResult alarm_list = hmi_editor_service.addControl(
page.id, HmiControlType::AlarmList);
require(page.succeeded && alarm_list.succeeded,
"alarm-list fixture must create a page and control");
project_service.editProject().alarmDefinitions.push_back({
"fixed-alarm",
RegisterAddress{RegisterArea::M, 0},
AlarmCondition::MOn,
0,
"Fixed alarm"});

HmiEditorWidget widget(
hmi_editor_service, hmi_runtime_service, alarm_service);
widget.setPageId(page.id);
widget.setEditingEnabled(false);
widget.setRuntimeActive(true);
widget.refreshRuntimeValues();

QGraphicsItem *alarm_item = nullptr;
for (QGraphicsItem *item : widget.scene()->items())
{
if (dynamic_cast<QGraphicsRectItem *>(item) == nullptr)
{
alarm_item = item;
break;
}
}
const HmiControl *control = hmi_editor_service.findControl(
page.id, alarm_list.id);
require(alarm_item != nullptr && control != nullptr,
"runtime HMI scene must contain the alarm-list item");
const QRectF fixed_bounds = alarm_item->boundingRect();
require(alarm_item->isVisible()
&& qFuzzyCompare(
fixed_bounds.width() + 1.0,
static_cast<qreal>(control->bounds.width) + 1.0)
&& qFuzzyCompare(
fixed_bounds.height() + 1.0,
static_cast<qreal>(control->bounds.height) + 1.0),
"an empty runtime alarm list must remain visible at its configured size");

require(virtual_repository.writeBit(
RegisterAddress{RegisterArea::M, 0}, true).succeeded,
"alarm-list fixture must activate M0");
alarm_service.refresh();
widget.refreshRuntimeValues();
require(alarm_service.records().size() == 1U
&& alarm_item->isVisible()
&& alarm_item->boundingRect() == fixed_bounds,
"adding an alarm row must not resize or hide the alarm control");

require(virtual_repository.writeBit(
RegisterAddress{RegisterArea::M, 0}, false).succeeded,
"alarm-list fixture must restore M0");
alarm_service.refresh();
widget.refreshRuntimeValues();
require(alarm_service.records().empty()
&& alarm_item->isVisible()
&& alarm_item->boundingRect() == fixed_bounds,
"removing the last alarm row must keep the fixed alarm control visible");
}

void testQueuedOfflineTraceIsIgnoredAfterReturningToEditing() void testQueuedOfflineTraceIsIgnoredAfterReturningToEditing()
{ {
TestProjectStorage storage; TestProjectStorage storage;
@@ -856,6 +957,8 @@ int main(int argc, char *argv[])
QApplication application(argc, argv); QApplication application(argc, argv);
try try
{ {
testAlarmConfigurationOffersMOnAndMOff();
testAlarmListKeepsFixedGeometryWhileRecordsChange();
testQueuedOfflineTraceIsIgnoredAfterReturningToEditing(); testQueuedOfflineTraceIsIgnoredAfterReturningToEditing();
testLogicEditorGridSelectionAndDeletion(); testLogicEditorGridSelectionAndDeletion();
testLadderLayoutAndDragDeletion(); testLadderLayoutAndDragDeletion();


+ 3
- 0
app/tests/runtime_panel_controller_tests.pro Просмотреть файл

@@ -15,6 +15,7 @@ SOURCES += \
$$SERVICE_OFFLINE_SOURCES \ $$SERVICE_OFFLINE_SOURCES \
$$SERVICE_RUNTIME_SOURCES \ $$SERVICE_RUNTIME_SOURCES \
$$SERVICE_MONITOR_SOURCES \ $$SERVICE_MONITOR_SOURCES \
../src/ui/alarm_configuration_dialog.cpp \
../src/ui/hmi_editor_widget.cpp \ ../src/ui/hmi_editor_widget.cpp \
../src/ui/logic_editor_widget.cpp \ ../src/ui/logic_editor_widget.cpp \
../src/ui/free_monitor_widget.cpp \ ../src/ui/free_monitor_widget.cpp \
@@ -33,6 +34,7 @@ HEADERS += \
$$SERVICE_RUNTIME_HEADERS \ $$SERVICE_RUNTIME_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/hmi_editor_widget.h \ ../src/ui/hmi_editor_widget.h \
../src/ui/logic_editor_widget.h \ ../src/ui/logic_editor_widget.h \
../src/ui/free_monitor_widget.h \ ../src/ui/free_monitor_widget.h \
@@ -43,6 +45,7 @@ HEADERS += \
$$TEST_SUPPORT_HEADERS $$TEST_SUPPORT_HEADERS


FORMS += \ FORMS += \
../src/ui/alarm_configuration_dialog.ui \
../src/ui/free_monitor_widget.ui \ ../src/ui/free_monitor_widget.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

Загрузка…
Отмена
Сохранить