Pārlūkot izejas kodu

feat: 集成梯形图与软元件注释界面

main
suyu pirms 1 mēnesi
vecāks
revīzija
0dc0de3172
11 mainītis faili ar 794 papildinājumiem un 27 dzēšanām
  1. +5
    -0
      app/integrated_platform.pro
  2. +3
    -0
      app/src/main.cpp
  3. +158
    -6
      app/src/ui/logic_editor_widget.cpp
  4. +195
    -15
      app/src/ui/main_window.cpp
  5. +6
    -0
      app/src/ui/main_window.h
  6. +78
    -4
      app/src/ui/main_window.ui
  7. +155
    -0
      app/src/ui/register_comment_dialog.cpp
  8. +34
    -0
      app/src/ui/register_comment_dialog.h
  9. +40
    -0
      app/src/ui/register_comment_dialog.ui
  10. +113
    -0
      app/tests/main_window_tests.cpp
  11. +7
    -2
      app/tests/main_window_tests.pro

+ 5
- 0
app/integrated_platform.pro Parādīt failu

@@ -18,6 +18,7 @@ SOURCES += \
src/main.cpp \ src/main.cpp \
src/ui/main_window.cpp \ src/ui/main_window.cpp \
src/ui/alarm_configuration_dialog.cpp \ src/ui/alarm_configuration_dialog.cpp \
src/ui/register_comment_dialog.cpp \
src/ui/plc_connection_dialog.cpp \ src/ui/plc_connection_dialog.cpp \
src/ui/free_monitor_widget.cpp \ src/ui/free_monitor_widget.cpp \
src/ui/runtime_monitor_widget.cpp \ src/ui/runtime_monitor_widget.cpp \
@@ -41,6 +42,7 @@ SOURCES += \
src/services/offline_simulation_service.cpp \ src/services/offline_simulation_service.cpp \
src/services/runtime_mode_service.cpp \ src/services/runtime_mode_service.cpp \
src/services/register_monitor_service.cpp \ src/services/register_monitor_service.cpp \
src/services/register_comment_service.cpp \
src/infrastructure/plc_register_repository.cpp \ src/infrastructure/plc_register_repository.cpp \
src/infrastructure/plc_communication_error_classifier.cpp \ src/infrastructure/plc_communication_error_classifier.cpp \
src/infrastructure/plc_communication_service.cpp \ src/infrastructure/plc_communication_service.cpp \
@@ -51,6 +53,7 @@ SOURCES += \
HEADERS += \ HEADERS += \
src/ui/main_window.h \ src/ui/main_window.h \
src/ui/alarm_configuration_dialog.h \ src/ui/alarm_configuration_dialog.h \
src/ui/register_comment_dialog.h \
src/ui/plc_connection_dialog.h \ src/ui/plc_connection_dialog.h \
src/ui/free_monitor_widget.h \ src/ui/free_monitor_widget.h \
src/ui/runtime_monitor_widget.h \ src/ui/runtime_monitor_widget.h \
@@ -75,6 +78,7 @@ HEADERS += \
src/services/offline_simulation_service.h \ src/services/offline_simulation_service.h \
src/services/runtime_mode_service.h \ src/services/runtime_mode_service.h \
src/services/register_monitor_service.h \ src/services/register_monitor_service.h \
src/services/register_comment_service.h \
src/services/plc_communication_gateway.h \ src/services/plc_communication_gateway.h \
src/infrastructure/plc_register_repository.h \ src/infrastructure/plc_register_repository.h \
src/infrastructure/plc_communication_error_classifier.h \ src/infrastructure/plc_communication_error_classifier.h \
@@ -86,6 +90,7 @@ HEADERS += \
FORMS += \ FORMS += \
src/ui/main_window.ui \ src/ui/main_window.ui \
src/ui/alarm_configuration_dialog.ui \ src/ui/alarm_configuration_dialog.ui \
src/ui/register_comment_dialog.ui \
src/ui/plc_connection_dialog.ui \ src/ui/plc_connection_dialog.ui \
src/ui/free_monitor_widget.ui \ src/ui/free_monitor_widget.ui \
src/ui/runtime_monitor_widget.ui src/ui/runtime_monitor_widget.ui

+ 3
- 0
app/src/main.cpp Parādīt failu

@@ -22,6 +22,7 @@
#include "services/project_service.h" #include "services/project_service.h"
#include "services/runtime_mode_service.h" #include "services/runtime_mode_service.h"
#include "services/register_monitor_service.h" #include "services/register_monitor_service.h"
#include "services/register_comment_service.h"
#include "ui/main_window.h" #include "ui/main_window.h"


int main(int argc, char *argv[]) int main(int argc, char *argv[])
@@ -44,6 +45,7 @@ int main(int argc, char *argv[])
HmiRuntimeService hmi_runtime_service(active_register_repository); HmiRuntimeService hmi_runtime_service(active_register_repository);
AlarmEditorService alarm_editor_service(project_service); AlarmEditorService alarm_editor_service(project_service);
AlarmService alarm_service(project_service, active_register_repository); AlarmService alarm_service(project_service, active_register_repository);
RegisterCommentService register_comment_service(project_service);
RegisterMonitorService register_monitor_service(active_register_repository); RegisterMonitorService register_monitor_service(active_register_repository);
OfflineSimulationService offline_simulation_service(virtual_register_repository); OfflineSimulationService offline_simulation_service(virtual_register_repository);
RuntimeModeService runtime_mode_service( RuntimeModeService runtime_mode_service(
@@ -62,6 +64,7 @@ int main(int argc, char *argv[])
alarm_editor_service, alarm_editor_service,
alarm_service, alarm_service,
hmi_navigation_service, hmi_navigation_service,
register_comment_service,
register_monitor_service); register_monitor_service);
main_window.show(); main_window.show();




+ 158
- 6
app/src/ui/logic_editor_widget.cpp Parādīt failu

@@ -17,9 +17,9 @@ constexpr qreal kSceneMargin = 28.0;
constexpr qreal kRailInset = 40.0; constexpr qreal kRailInset = 40.0;
constexpr qreal kMinimumSceneWidth = 980.0; constexpr qreal kMinimumSceneWidth = 980.0;
constexpr qreal kCellWidth = 128.0; constexpr qreal kCellWidth = 128.0;
constexpr qreal kCellHeight = 86.0;
constexpr qreal kCellHeight = 120.0;
constexpr qreal kNodeTerminalX = 50.0; constexpr qreal kNodeTerminalX = 50.0;
constexpr qreal kRungHeaderHeight = 34.0;
constexpr qreal kRungHeaderHeight = 52.0;
constexpr qreal kRungGap = 18.0; constexpr qreal kRungGap = 18.0;
constexpr qreal kLadderLineWidth = 1.8; constexpr qreal kLadderLineWidth = 1.8;
constexpr int kMinimumLogicColumns = 7; constexpr int kMinimumLogicColumns = 7;
@@ -48,6 +48,29 @@ QString registerAddressText(const RegisterAddress &address)
return QString::fromStdString(address.toString()); return QString::fromStdString(address.toString());
} }


QString timerAddressText(const TimerAddress &address)
{
return QString::fromStdString(address.toString());
}

void drawRegisterComment(
QPainter *painter, const QString &comment, qreal top = 22.0)
{
if (comment.isEmpty())
{
return;
}
QFont font = painter->font();
font.setPointSizeF(8.0);
painter->setFont(font);
const QString visible_comment = painter->fontMetrics().elidedText(
comment, Qt::ElideRight, static_cast<int>(kCellWidth - 8.0));
painter->drawText(
QRectF(-kCellWidth / 2.0, top, kCellWidth, 18),
Qt::AlignCenter,
visible_comment);
}

QString comparisonText(ComparisonOperator comparison) QString comparisonText(ComparisonOperator comparison)
{ {
switch (comparison) switch (comparison)
@@ -76,18 +99,37 @@ QString nodeToolTip(const LogicNodeConfig &config)
: LogicEditorWidget::tr("常闭")) : LogicEditorWidget::tr("常闭"))
.arg(registerAddressText(value.address)); .arg(registerAddressText(value.address));
} }
else if constexpr (std::is_same_v<Config, EdgeContactNodeConfig>)
{
return LogicEditorWidget::tr("%1沿触点:%2")
.arg(value.mode == EdgeMode::Rising
? LogicEditorWidget::tr("上升")
: LogicEditorWidget::tr("下降"))
.arg(registerAddressText(value.address));
}
else if constexpr (std::is_same_v<Config, TimerContactNodeConfig>)
{
return LogicEditorWidget::tr("T 触点:%1")
.arg(timerAddressText(value.address));
}
else if constexpr (std::is_same_v<Config, CoilNodeConfig>) else if constexpr (std::is_same_v<Config, CoilNodeConfig>)
{ {
return LogicEditorWidget::tr("输出线圈:%1") return LogicEditorWidget::tr("输出线圈:%1")
.arg(registerAddressText(value.address)); .arg(registerAddressText(value.address));
} }
else
else if constexpr (std::is_same_v<Config, CompareNodeConfig>)
{ {
return LogicEditorWidget::tr("比较条件:%1 %2 %3") return LogicEditorWidget::tr("比较条件:%1 %2 %3")
.arg(registerAddressText(value.address)) .arg(registerAddressText(value.address))
.arg(comparisonText(value.comparison)) .arg(comparisonText(value.comparison))
.arg(value.value); .arg(value.value);
} }
else
{
return LogicEditorWidget::tr("TON:%1,预设 %2 ms")
.arg(timerAddressText(value.address))
.arg(value.presetMs);
}
}, },
config); config);
} }
@@ -187,11 +229,13 @@ public:
const LogicNode &node, const LogicNode &node,
const std::string &rung_id, const std::string &rung_id,
const QPointF &center, const QPointF &center,
const QString &register_comment,
bool active, bool active,
bool faulted) bool faulted)
: node_id_(node.id), : node_id_(node.id),
rung_id_(rung_id), rung_id_(rung_id),
config_(node.config), config_(node.config),
register_comment_(register_comment),
configured_(node.configured), configured_(node.configured),
active_(active), active_(active),
faulted_(faulted) faulted_(faulted)
@@ -199,8 +243,14 @@ public:
setPos(center); setPos(center);
setFlag(ItemIsSelectable, true); setFlag(ItemIsSelectable, true);
setZValue(3.0); setZValue(3.0);
setToolTip(configured_ ? nodeToolTip(config_)
: LogicEditorWidget::tr("待配置:请在属性区设置地址和参数"));
QString tool_tip = configured_
? nodeToolTip(config_)
: LogicEditorWidget::tr("待配置:请在属性区设置地址和参数");
if (!register_comment_.isEmpty())
{
tool_tip += LogicEditorWidget::tr("\n注释:%1").arg(register_comment_);
}
setToolTip(tool_tip);
} }


QRectF boundingRect() const override QRectF boundingRect() const override
@@ -241,6 +291,41 @@ public:
QRectF(-kCellWidth / 2.0, -40, kCellWidth, 18), QRectF(-kCellWidth / 2.0, -40, kCellWidth, 18),
Qt::AlignCenter, Qt::AlignCenter,
configured_ ? registerAddressText(contact->address) : tr("< M 地址 >")); configured_ ? registerAddressText(contact->address) : tr("< M 地址 >"));
drawRegisterComment(painter, register_comment_);
}
else if (const auto *edge = std::get_if<EdgeContactNodeConfig>(&config_))
{
painter->fillRect(QRectF(-25, -22, 50, 44), Qt::white);
painter->drawLine(QPointF(-kNodeTerminalX, 0), QPointF(-18, 0));
painter->drawLine(QPointF(18, 0), QPointF(kNodeTerminalX, 0));
painter->drawLine(QPointF(-18, -15), QPointF(-18, 15));
painter->drawLine(QPointF(18, -15), QPointF(18, 15));
painter->drawText(
QRectF(-14, -12, 28, 24),
Qt::AlignCenter,
edge->mode == EdgeMode::Rising ? QStringLiteral("P") : QStringLiteral("N"));
painter->drawText(
QRectF(-kCellWidth / 2.0, -40, kCellWidth, 18),
Qt::AlignCenter,
configured_ ? registerAddressText(edge->address) : tr("< M 地址 >"));
drawRegisterComment(painter, register_comment_);
}
else if (const auto *timer_contact =
std::get_if<TimerContactNodeConfig>(&config_))
{
painter->fillRect(QRectF(-25, -22, 50, 44), Qt::white);
painter->drawLine(QPointF(-kNodeTerminalX, 0), QPointF(-18, 0));
painter->drawLine(QPointF(18, 0), QPointF(kNodeTerminalX, 0));
painter->drawLine(QPointF(-18, -15), QPointF(-18, 15));
painter->drawLine(QPointF(18, -15), QPointF(18, 15));
if (timer_contact->mode == ContactMode::NormallyClosed)
{
painter->drawLine(QPointF(-23, 18), QPointF(23, -18));
}
painter->drawText(
QRectF(-kCellWidth / 2.0, -40, kCellWidth, 18),
Qt::AlignCenter,
configured_ ? timerAddressText(timer_contact->address) : tr("< T 地址 >"));
} }
else if (const auto *coil = std::get_if<CoilNodeConfig>(&config_)) else if (const auto *coil = std::get_if<CoilNodeConfig>(&config_))
{ {
@@ -266,6 +351,7 @@ public:
QRectF(-kCellWidth / 2.0, -40, kCellWidth, 18), QRectF(-kCellWidth / 2.0, -40, kCellWidth, 18),
Qt::AlignCenter, Qt::AlignCenter,
configured_ ? registerAddressText(coil->address) : tr("< M 地址 >")); configured_ ? registerAddressText(coil->address) : tr("< M 地址 >"));
drawRegisterComment(painter, register_comment_);
} }
else if (const auto *comparison = std::get_if<CompareNodeConfig>(&config_)) else if (const auto *comparison = std::get_if<CompareNodeConfig>(&config_))
{ {
@@ -285,6 +371,25 @@ public:
QRectF(-kCellWidth / 2.0, 22, kCellWidth, 18), QRectF(-kCellWidth / 2.0, 22, kCellWidth, 18),
Qt::AlignCenter, Qt::AlignCenter,
configured_ ? QString::number(comparison->value) : tr("< 常量 >")); configured_ ? QString::number(comparison->value) : tr("< 常量 >"));
drawRegisterComment(painter, register_comment_, 40.0);
}
else if (const auto *ton = std::get_if<TonNodeConfig>(&config_))
{
const QRectF box(-47, -18, 94, 36);
painter->fillRect(box.adjusted(-1, -1, 1, 1), Qt::white);
painter->drawLine(QPointF(-kNodeTerminalX, 0), QPointF(-47, 0));
painter->drawLine(QPointF(47, 0), QPointF(kNodeTerminalX, 0));
painter->drawRect(box);
painter->drawText(box, Qt::AlignCenter, QStringLiteral("TON"));
painter->drawText(
QRectF(-kCellWidth / 2.0, -40, kCellWidth, 18),
Qt::AlignCenter,
configured_ ? timerAddressText(ton->address) : tr("< T 地址 >"));
painter->drawText(
QRectF(-kCellWidth / 2.0, 22, kCellWidth, 18),
Qt::AlignCenter,
configured_ ? QStringLiteral("PT %1 ms").arg(ton->presetMs)
: tr("< 预设时间 >"));
} }
} }


@@ -295,6 +400,7 @@ private:
std::string node_id_; std::string node_id_;
std::string rung_id_; std::string rung_id_;
LogicNodeConfig config_; LogicNodeConfig config_;
QString register_comment_;
bool configured_ = true; bool configured_ = true;
bool active_ = false; bool active_ = false;
bool faulted_ = false; bool faulted_ = false;
@@ -312,6 +418,7 @@ public:
qreal cursor_left) qreal cursor_left)
: rung_id_(rung.id), : rung_id_(rung.id),
name_(QString::fromStdString(rung.name)), name_(QString::fromStdString(rung.name)),
comment_(QString::fromStdString(rung.comment)),
number_(number), number_(number),
height_(height), height_(height),
width_(width), width_(width),
@@ -321,6 +428,10 @@ public:
setPos(0, top); setPos(0, top);
setFlag(ItemIsSelectable, true); setFlag(ItemIsSelectable, true);
setZValue(-2.0); setZValue(-2.0);
if (!comment_.isEmpty())
{
setToolTip(comment_);
}
} }


QRectF boundingRect() const override { return {kSceneMargin, 0, width_, height_}; } QRectF boundingRect() const override { return {kSceneMargin, 0, width_, height_}; }
@@ -351,6 +462,16 @@ public:
QRectF(kSceneMargin + 8, 5, 320, 22), QRectF(kSceneMargin + 8, 5, 320, 22),
Qt::AlignLeft | Qt::AlignVCenter, Qt::AlignLeft | Qt::AlignVCenter,
title); title);
if (!comment_.isEmpty())
{
painter->setPen(QColor(QStringLiteral("#7b8790")));
const QString visible_comment = painter->fontMetrics().elidedText(
comment_, Qt::ElideRight, static_cast<int>(width_ - 16.0));
painter->drawText(
QRectF(kSceneMargin + 8, 24, width_ - 16, 22),
Qt::AlignLeft | Qt::AlignVCenter,
visible_comment);
}
painter->setPen(QPen(QColor(QStringLiteral("#d4dce1")), 1)); painter->setPen(QPen(QColor(QStringLiteral("#d4dce1")), 1));
painter->drawLine( painter->drawLine(
QPointF(kSceneMargin + 8, height_ - 1), QPointF(kSceneMargin + 8, height_ - 1),
@@ -362,6 +483,7 @@ public:
private: private:
std::string rung_id_; std::string rung_id_;
QString name_; QString name_;
QString comment_;
int number_ = 0; int number_ = 0;
qreal height_ = 0.0; qreal height_ = 0.0;
qreal width_ = 0.0; qreal width_ = 0.0;
@@ -373,6 +495,7 @@ namespace {


RenderResult renderExpression( RenderResult renderExpression(
QGraphicsScene &scene, QGraphicsScene &scene,
const LogicEditorService &editor_service,
const ConditionExpression &expression, const ConditionExpression &expression,
const std::string &rung_id, const std::string &rung_id,
const QPointF &top_left, const QPointF &top_left,
@@ -399,6 +522,15 @@ RenderResult renderExpression(
*expression.node, *expression.node,
rung_id, rung_id,
center, center,
[&editor_service, &expression]
{
const std::optional<RegisterAddress> address =
registerAddressForLogicNode(expression.node->config);
return address.has_value()
? QString::fromStdString(
editor_service.registerCommentFor(*address))
: QString{};
}(),
node_active, node_active,
expression.node->id == fault_node_id)); expression.node->id == fault_node_id));
return { return {
@@ -416,6 +548,7 @@ RenderResult renderExpression(
const ExpressionMetrics child_metrics = measureExpression(expression.children[index]); const ExpressionMetrics child_metrics = measureExpression(expression.children[index]);
const RenderResult current = renderExpression( const RenderResult current = renderExpression(
scene, scene,
editor_service,
expression.children[index], expression.children[index],
rung_id, rung_id,
QPointF(x, top_left.y()), QPointF(x, top_left.y()),
@@ -445,6 +578,7 @@ RenderResult renderExpression(
const ExpressionMetrics child_metrics = measureExpression(child); const ExpressionMetrics child_metrics = measureExpression(child);
branches.push_back(renderExpression( branches.push_back(renderExpression(
scene, scene,
editor_service,
child, child,
rung_id, rung_id,
QPointF(top_left.x(), y), QPointF(top_left.x(), y),
@@ -588,6 +722,7 @@ void LogicEditorWidget::reloadLogic()
{ {
const RenderResult rendered = renderExpression( const RenderResult rendered = renderExpression(
*scene_, *scene_,
editor_service_,
*rung.condition, *rung.condition,
rung.id, rung.id,
QPointF(left_rail_x, grid_top), QPointF(left_rail_x, grid_top),
@@ -620,7 +755,24 @@ void LogicEditorWidget::reloadLogic()
*rung.output, *rung.output,
rung.id, rung.id,
QPointF(output_left + kCellWidth / 2.0, main_y), QPointF(output_left + kCellWidth / 2.0, main_y),
rung_active,
[&rung, this]
{
const std::optional<RegisterAddress> address =
registerAddressForLogicNode(rung.output->config);
return address.has_value()
? QString::fromStdString(
editor_service_.registerCommentFor(*address))
: QString{};
}(),
[&rung, this, rung_active]
{
return std::holds_alternative<TonNodeConfig>(rung.output->config)
? traceValue(
trace_,
&LogicTraceSnapshot::nodeValues,
rung.output->id)
: rung_active;
}(),
rung.output->id == fault_node_id_)); rung.output->id == fault_node_id_));
} }
else else


+ 195
- 15
app/src/ui/main_window.cpp Parādīt failu

@@ -2,6 +2,7 @@


#include "hmi_editor_widget.h" #include "hmi_editor_widget.h"
#include "alarm_configuration_dialog.h" #include "alarm_configuration_dialog.h"
#include "register_comment_dialog.h"
#include "logic_editor_widget.h" #include "logic_editor_widget.h"
#include "plc_connection_dialog.h" #include "plc_connection_dialog.h"
#include "runtime_monitor_widget.h" #include "runtime_monitor_widget.h"
@@ -15,6 +16,7 @@
#include "services/project_service.h" #include "services/project_service.h"
#include "services/runtime_mode_service.h" #include "services/runtime_mode_service.h"
#include "services/register_monitor_service.h" #include "services/register_monitor_service.h"
#include "services/register_comment_service.h"
#include "ui_main_window.h" #include "ui_main_window.h"


#include <QActionGroup> #include <QActionGroup>
@@ -200,6 +202,7 @@ MainWindow::MainWindow(
HmiRuntimeService &hmi_runtime_service, HmiRuntimeService &hmi_runtime_service,
AlarmEditorService &alarm_editor_service, AlarmEditorService &alarm_editor_service,
AlarmService &alarm_service, AlarmService &alarm_service,
RegisterCommentService &register_comment_service,
RegisterMonitorService &register_monitor_service, RegisterMonitorService &register_monitor_service,
QWidget *parent) QWidget *parent)
: QMainWindow(parent), : QMainWindow(parent),
@@ -211,6 +214,7 @@ MainWindow::MainWindow(
hmi_runtime_service_(hmi_runtime_service), hmi_runtime_service_(hmi_runtime_service),
alarm_editor_service_(alarm_editor_service), alarm_editor_service_(alarm_editor_service),
alarm_service_(alarm_service), alarm_service_(alarm_service),
register_comment_service_(register_comment_service),
register_monitor_service_(register_monitor_service), register_monitor_service_(register_monitor_service),
owned_hmi_navigation_service_( owned_hmi_navigation_service_(
std::make_unique<HmiNavigationService>(project_service)), std::make_unique<HmiNavigationService>(project_service)),
@@ -228,6 +232,7 @@ MainWindow::MainWindow(
AlarmEditorService &alarm_editor_service, AlarmEditorService &alarm_editor_service,
AlarmService &alarm_service, AlarmService &alarm_service,
HmiNavigationService &hmi_navigation_service, HmiNavigationService &hmi_navigation_service,
RegisterCommentService &register_comment_service,
RegisterMonitorService &register_monitor_service, RegisterMonitorService &register_monitor_service,
QWidget *parent) QWidget *parent)
: QMainWindow(parent), : QMainWindow(parent),
@@ -239,6 +244,7 @@ MainWindow::MainWindow(
hmi_runtime_service_(hmi_runtime_service), hmi_runtime_service_(hmi_runtime_service),
alarm_editor_service_(alarm_editor_service), alarm_editor_service_(alarm_editor_service),
alarm_service_(alarm_service), alarm_service_(alarm_service),
register_comment_service_(register_comment_service),
register_monitor_service_(register_monitor_service), register_monitor_service_(register_monitor_service),
hmi_navigation_service_(&hmi_navigation_service) hmi_navigation_service_(&hmi_navigation_service)
{ {
@@ -253,6 +259,7 @@ void MainWindow::initializeUi()
configurePropertyEditor(); configurePropertyEditor();
configurePlcConnection(); configurePlcConnection();
configureAlarms(); configureAlarms();
configureRegisterComments();
configureHmiEditor(); configureHmiEditor();
configureLogicEditor(); configureLogicEditor();
configureRuntimeMonitor(); configureRuntimeMonitor();
@@ -332,6 +339,9 @@ void MainWindow::configureActions()
QMenu *parallel_menu = new QMenu(this); QMenu *parallel_menu = new QMenu(this);
QAction *parallel_open = parallel_menu->addAction(tr("并联常开触点")); QAction *parallel_open = parallel_menu->addAction(tr("并联常开触点"));
QAction *parallel_closed = parallel_menu->addAction(tr("并联常闭触点")); QAction *parallel_closed = parallel_menu->addAction(tr("并联常闭触点"));
QAction *parallel_rising = parallel_menu->addAction(tr("并联上升沿触点"));
QAction *parallel_falling = parallel_menu->addAction(tr("并联下降沿触点"));
QAction *parallel_timer = parallel_menu->addAction(tr("并联 T 触点"));
QAction *parallel_compare = parallel_menu->addAction(tr("并联比较条件")); QAction *parallel_compare = parallel_menu->addAction(tr("并联比较条件"));
connect(parallel_open, &QAction::triggered, connect(parallel_open, &QAction::triggered,
this, this,
@@ -349,6 +359,27 @@ void MainWindow::configureActions()
RegisterAddress{RegisterArea::M, 0}, RegisterAddress{RegisterArea::M, 0},
ContactMode::NormallyClosed}); ContactMode::NormallyClosed});
}); });
connect(parallel_rising, &QAction::triggered,
this,
[this]
{
addLogicParallelBranch(EdgeContactNodeConfig{
RegisterAddress{RegisterArea::M, 0}, EdgeMode::Rising});
});
connect(parallel_falling, &QAction::triggered,
this,
[this]
{
addLogicParallelBranch(EdgeContactNodeConfig{
RegisterAddress{RegisterArea::M, 0}, EdgeMode::Falling});
});
connect(parallel_timer, &QAction::triggered,
this,
[this]
{
addLogicParallelBranch(TimerContactNodeConfig{
TimerAddress{0}, ContactMode::NormallyOpen});
});
connect(parallel_compare, &QAction::triggered, connect(parallel_compare, &QAction::triggered,
this, this,
[this] [this]
@@ -380,6 +411,27 @@ void MainWindow::configureActions()
RegisterAddress{RegisterArea::M, 0}, RegisterAddress{RegisterArea::M, 0},
ContactMode::NormallyClosed}); ContactMode::NormallyClosed});
}); });
connect(ui_->addRisingEdgeAction, &QAction::triggered,
this,
[this]
{
addLogicCondition(EdgeContactNodeConfig{
RegisterAddress{RegisterArea::M, 0}, EdgeMode::Rising});
});
connect(ui_->addFallingEdgeAction, &QAction::triggered,
this,
[this]
{
addLogicCondition(EdgeContactNodeConfig{
RegisterAddress{RegisterArea::M, 0}, EdgeMode::Falling});
});
connect(ui_->addTimerContactAction, &QAction::triggered,
this,
[this]
{
addLogicCondition(TimerContactNodeConfig{
TimerAddress{0}, ContactMode::NormallyOpen});
});
connect(ui_->addNormalCoilAction, &QAction::triggered, connect(ui_->addNormalCoilAction, &QAction::triggered,
this, this,
[this] [this]
@@ -404,6 +456,12 @@ void MainWindow::configureActions()
RegisterAddress{RegisterArea::M, 0}, RegisterAddress{RegisterArea::M, 0},
CoilMode::Reset}); CoilMode::Reset});
}); });
connect(ui_->addTonAction, &QAction::triggered,
this,
[this]
{
setLogicOutput(TonNodeConfig{TimerAddress{0}, 1000});
});
connect(ui_->addCompareAction, &QAction::triggered, connect(ui_->addCompareAction, &QAction::triggered,
this, this,
[this] [this]
@@ -415,6 +473,8 @@ void MainWindow::configureActions()
}); });
connect(ui_->deleteLogicAction, &QAction::triggered, connect(ui_->deleteLogicAction, &QAction::triggered,
this, &MainWindow::deleteSelectedLogicObject); this, &MainWindow::deleteSelectedLogicObject);
connect(ui_->editRungCommentAction, &QAction::triggered,
this, &MainWindow::editSelectedRungComment);


connect(ui_->editorTabWidget, &QTabWidget::currentChanged, connect(ui_->editorTabWidget, &QTabWidget::currentChanged,
this, this,
@@ -481,10 +541,15 @@ void MainWindow::configureAppearance()
ui_->parallelInsertAction->setIcon(style()->standardIcon(QStyle::SP_ArrowDown)); ui_->parallelInsertAction->setIcon(style()->standardIcon(QStyle::SP_ArrowDown));
ui_->addNormallyOpenAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight)); ui_->addNormallyOpenAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight));
ui_->addNormallyClosedAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight)); ui_->addNormallyClosedAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight));
ui_->addRisingEdgeAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight));
ui_->addFallingEdgeAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight));
ui_->addTimerContactAction->setIcon(style()->standardIcon(QStyle::SP_ArrowRight));
ui_->addNormalCoilAction->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton)); ui_->addNormalCoilAction->setIcon(style()->standardIcon(QStyle::SP_DialogApplyButton));
ui_->addSetCoilAction->setIcon(style()->standardIcon(QStyle::SP_DialogYesButton)); ui_->addSetCoilAction->setIcon(style()->standardIcon(QStyle::SP_DialogYesButton));
ui_->addResetCoilAction->setIcon(style()->standardIcon(QStyle::SP_DialogNoButton)); ui_->addResetCoilAction->setIcon(style()->standardIcon(QStyle::SP_DialogNoButton));
ui_->addTonAction->setIcon(style()->standardIcon(QStyle::SP_BrowserReload));
ui_->addCompareAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogInfoView)); ui_->addCompareAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogInfoView));
ui_->editRungCommentAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogDetailedView));
ui_->deleteLogicAction->setIcon(style()->standardIcon(QStyle::SP_TrashIcon)); ui_->deleteLogicAction->setIcon(style()->standardIcon(QStyle::SP_TrashIcon));
ui_->editorTabWidget->setTabIcon(0, style()->standardIcon(QStyle::SP_DesktopIcon)); ui_->editorTabWidget->setTabIcon(0, style()->standardIcon(QStyle::SP_DesktopIcon));
ui_->editorTabWidget->setTabIcon(1, style()->standardIcon(QStyle::SP_FileDialogListView)); ui_->editorTabWidget->setTabIcon(1, style()->standardIcon(QStyle::SP_FileDialogListView));
@@ -755,7 +820,22 @@ void MainWindow::configureAlarms()
AlarmConfigurationDialog dialog(alarm_editor_service_, this); AlarmConfigurationDialog dialog(alarm_editor_service_, this);
dialog.exec(); dialog.exec();
refreshProjectUi(); refreshProjectUi();
});
});
}

void MainWindow::configureRegisterComments()
{
connect(
ui_->configureRegisterCommentsAction,
&QAction::triggered,
this,
[this]
{
RegisterCommentDialog dialog(register_comment_service_, this);
dialog.exec();
logic_editor_widget_->reloadLogic();
refreshProjectUi();
});
} }


void MainWindow::refreshProjectUi() void MainWindow::refreshProjectUi()
@@ -1300,6 +1380,7 @@ void MainWindow::showLogicNodeProperties(const std::string &node_id)
static_cast<QWidget *>(ui_->logicModeComboBox), static_cast<QWidget *>(ui_->logicModeComboBox),
static_cast<QWidget *>(ui_->logicComparisonComboBox), static_cast<QWidget *>(ui_->logicComparisonComboBox),
static_cast<QWidget *>(ui_->logicValueSpinBox), static_cast<QWidget *>(ui_->logicValueSpinBox),
static_cast<QWidget *>(ui_->logicPresetSpinBox),
static_cast<QWidget *>(ui_->applyLogicPropertiesButton)}) static_cast<QWidget *>(ui_->applyLogicPropertiesButton)})
{ {
widget->setEnabled(has_node); widget->setEnabled(has_node);
@@ -1312,11 +1393,15 @@ void MainWindow::showLogicNodeProperties(const std::string &node_id)
ui_->logicNodeTypeLabel->clear(); ui_->logicNodeTypeLabel->clear();
ui_->logicAddressAreaLabel->clear(); ui_->logicAddressAreaLabel->clear();
ui_->logicModeComboBox->clear(); ui_->logicModeComboBox->clear();
ui_->logicPresetSpinBox->setValue(TonNodeConfig::kMinimumPresetMs);
return; return;
} }


ui_->logicNodeIdEdit->setText(fromUtf8(node->id)); ui_->logicNodeIdEdit->setText(fromUtf8(node->id));
ui_->logicModeComboBox->clear(); ui_->logicModeComboBox->clear();
ui_->logicComparisonComboBox->setEnabled(false);
ui_->logicValueSpinBox->setEnabled(false);
ui_->logicPresetSpinBox->setEnabled(false);
if (const auto *contact = std::get_if<ContactNodeConfig>(&node->config)) if (const auto *contact = std::get_if<ContactNodeConfig>(&node->config))
{ {
ui_->logicNodeTypeLabel->setText(tr("触点")); ui_->logicNodeTypeLabel->setText(tr("触点"));
@@ -1327,10 +1412,36 @@ void MainWindow::showLogicNodeProperties(const std::string &node_id)
ui_->logicModeComboBox->addItem( ui_->logicModeComboBox->addItem(
tr("常闭"), static_cast<int>(ContactMode::NormallyClosed)); tr("常闭"), static_cast<int>(ContactMode::NormallyClosed));
ui_->logicModeComboBox->setCurrentIndex( ui_->logicModeComboBox->setCurrentIndex(
ui_->logicModeComboBox->findData(static_cast<int>(contact->mode)));
ui_->logicModeComboBox->findData(static_cast<int>(contact->mode)));
ui_->logicModeComboBox->setEnabled(true);
}
else if (const auto *edge = std::get_if<EdgeContactNodeConfig>(&node->config))
{
ui_->logicNodeTypeLabel->setText(tr("边沿触点"));
ui_->logicAddressAreaLabel->setText(QStringLiteral("M"));
ui_->logicAddressSpinBox->setValue(edge->address.index());
ui_->logicModeComboBox->addItem(
tr("上升沿"), static_cast<int>(EdgeMode::Rising));
ui_->logicModeComboBox->addItem(
tr("下降沿"), static_cast<int>(EdgeMode::Falling));
ui_->logicModeComboBox->setCurrentIndex(
ui_->logicModeComboBox->findData(static_cast<int>(edge->mode)));
ui_->logicModeComboBox->setEnabled(true);
}
else if (const auto *timer_contact =
std::get_if<TimerContactNodeConfig>(&node->config))
{
ui_->logicNodeTypeLabel->setText(tr("T 触点"));
ui_->logicAddressAreaLabel->setText(QStringLiteral("T"));
ui_->logicAddressSpinBox->setValue(timer_contact->address.index());
ui_->logicModeComboBox->addItem(
tr("常开"), static_cast<int>(ContactMode::NormallyOpen));
ui_->logicModeComboBox->addItem(
tr("常闭"), static_cast<int>(ContactMode::NormallyClosed));
ui_->logicModeComboBox->setCurrentIndex(
ui_->logicModeComboBox->findData(
static_cast<int>(timer_contact->mode)));
ui_->logicModeComboBox->setEnabled(true); ui_->logicModeComboBox->setEnabled(true);
ui_->logicComparisonComboBox->setEnabled(false);
ui_->logicValueSpinBox->setEnabled(false);
} }
else if (const auto *coil = std::get_if<CoilNodeConfig>(&node->config)) else if (const auto *coil = std::get_if<CoilNodeConfig>(&node->config))
{ {
@@ -1344,25 +1455,33 @@ void MainWindow::showLogicNodeProperties(const std::string &node_id)
ui_->logicModeComboBox->addItem( ui_->logicModeComboBox->addItem(
tr("复位"), static_cast<int>(CoilMode::Reset)); tr("复位"), static_cast<int>(CoilMode::Reset));
ui_->logicModeComboBox->setCurrentIndex( ui_->logicModeComboBox->setCurrentIndex(
ui_->logicModeComboBox->findData(static_cast<int>(coil->mode)));
ui_->logicModeComboBox->findData(static_cast<int>(coil->mode)));
ui_->logicModeComboBox->setEnabled(true); ui_->logicModeComboBox->setEnabled(true);
ui_->logicComparisonComboBox->setEnabled(false);
ui_->logicValueSpinBox->setEnabled(false);
} }
else
else if (const auto *compare = std::get_if<CompareNodeConfig>(&node->config))
{ {
const auto &compare = std::get<CompareNodeConfig>(node->config);
ui_->logicNodeTypeLabel->setText(tr("D 值比较")); ui_->logicNodeTypeLabel->setText(tr("D 值比较"));
ui_->logicAddressAreaLabel->setText(QStringLiteral("D")); ui_->logicAddressAreaLabel->setText(QStringLiteral("D"));
ui_->logicAddressSpinBox->setValue(compare.address.index());
ui_->logicAddressSpinBox->setValue(compare->address.index());
ui_->logicModeComboBox->addItem(tr("不适用")); ui_->logicModeComboBox->addItem(tr("不适用"));
ui_->logicModeComboBox->setEnabled(false); ui_->logicModeComboBox->setEnabled(false);
ui_->logicComparisonComboBox->setEnabled(true); ui_->logicComparisonComboBox->setEnabled(true);
ui_->logicComparisonComboBox->setCurrentIndex( ui_->logicComparisonComboBox->setCurrentIndex(
ui_->logicComparisonComboBox->findData( ui_->logicComparisonComboBox->findData(
static_cast<int>(compare.comparison)));
static_cast<int>(compare->comparison)));
ui_->logicValueSpinBox->setEnabled(true); ui_->logicValueSpinBox->setEnabled(true);
ui_->logicValueSpinBox->setValue(compare.value);
ui_->logicValueSpinBox->setValue(compare->value);
}
else
{
const auto &ton = std::get<TonNodeConfig>(node->config);
ui_->logicNodeTypeLabel->setText(tr("TON"));
ui_->logicAddressAreaLabel->setText(QStringLiteral("T"));
ui_->logicAddressSpinBox->setValue(ton.address.index());
ui_->logicModeComboBox->addItem(tr("非保持接通延时"));
ui_->logicModeComboBox->setEnabled(false);
ui_->logicPresetSpinBox->setEnabled(true);
ui_->logicPresetSpinBox->setValue(ton.presetMs);
} }
if (!node->configured) if (!node->configured)
{ {
@@ -1500,13 +1619,13 @@ void MainWindow::setLogicOutput(const LogicNodeConfig &config)
const LogicEditorResult result = logic_editor_widget_->setOutput(config); const LogicEditorResult result = logic_editor_widget_->setOutput(config);
if (!result.succeeded) if (!result.succeeded)
{ {
showProjectResult(tr("设置输出线圈"), fromUtf8(result.message), false);
showProjectResult(tr("设置逻辑输出"), fromUtf8(result.message), false);
return; return;
} }
selected_logic_node_id_ = result.id; selected_logic_node_id_ = result.id;
showLogicNodeProperties(result.id); showLogicNodeProperties(result.id);
refreshProjectUi(); refreshProjectUi();
statusBar()->showMessage(tr("输出线圈已设置"), 3000);
statusBar()->showMessage(tr("逻辑输出已设置"), 3000);
} }


void MainWindow::addLogicRung() void MainWindow::addLogicRung()
@@ -1523,6 +1642,43 @@ void MainWindow::addLogicRung()
statusBar()->showMessage(tr("已新建网络"), 3000); statusBar()->showMessage(tr("已新建网络"), 3000);
} }


void MainWindow::editSelectedRungComment()
{
const std::string rung_id = logic_editor_widget_->selectedRungId();
if (rung_id.empty())
{
showProjectResult(tr("网络注释"), tr("请先选择一个梯形图网络"), false);
return;
}
const LadderRung *rung = logic_editor_service_.findRung(
current_logic_id_, rung_id);
if (rung == nullptr)
{
return;
}
bool accepted = false;
const QString comment = QInputDialog::getMultiLineText(
this,
tr("网络注释"),
tr("说明"),
fromUtf8(rung->comment),
&accepted);
if (!accepted)
{
return;
}
const LogicEditorResult result = logic_editor_service_.updateRungComment(
current_logic_id_, rung_id, toUtf8(comment));
if (!result.succeeded)
{
showProjectResult(tr("网络注释"), fromUtf8(result.message), false);
return;
}
logic_editor_widget_->reloadLogic();
refreshProjectUi();
statusBar()->showMessage(tr("网络注释已更新"), 3000);
}

void MainWindow::deleteSelectedLogicObject() void MainWindow::deleteSelectedLogicObject()
{ {
const LogicEditorResult result = logic_editor_widget_->deleteSelected(); const LogicEditorResult result = logic_editor_widget_->deleteSelected();
@@ -1551,13 +1707,25 @@ void MainWindow::applySelectedLogicNodeProperties()
RegisterAddress{RegisterArea::M, ui_->logicAddressSpinBox->value()}, RegisterAddress{RegisterArea::M, ui_->logicAddressSpinBox->value()},
static_cast<ContactMode>(ui_->logicModeComboBox->currentData().toInt())}; static_cast<ContactMode>(ui_->logicModeComboBox->currentData().toInt())};
} }
else if (std::holds_alternative<EdgeContactNodeConfig>(config))
{
config = EdgeContactNodeConfig{
RegisterAddress{RegisterArea::M, ui_->logicAddressSpinBox->value()},
static_cast<EdgeMode>(ui_->logicModeComboBox->currentData().toInt())};
}
else if (std::holds_alternative<TimerContactNodeConfig>(config))
{
config = TimerContactNodeConfig{
TimerAddress{ui_->logicAddressSpinBox->value()},
static_cast<ContactMode>(ui_->logicModeComboBox->currentData().toInt())};
}
else if (std::holds_alternative<CoilNodeConfig>(config)) else if (std::holds_alternative<CoilNodeConfig>(config))
{ {
config = CoilNodeConfig{ config = CoilNodeConfig{
RegisterAddress{RegisterArea::M, ui_->logicAddressSpinBox->value()}, RegisterAddress{RegisterArea::M, ui_->logicAddressSpinBox->value()},
static_cast<CoilMode>(ui_->logicModeComboBox->currentData().toInt())}; static_cast<CoilMode>(ui_->logicModeComboBox->currentData().toInt())};
} }
else
else if (std::holds_alternative<CompareNodeConfig>(config))
{ {
config = CompareNodeConfig{ config = CompareNodeConfig{
RegisterAddress{RegisterArea::D, ui_->logicAddressSpinBox->value()}, RegisterAddress{RegisterArea::D, ui_->logicAddressSpinBox->value()},
@@ -1565,6 +1733,12 @@ void MainWindow::applySelectedLogicNodeProperties()
ui_->logicComparisonComboBox->currentData().toInt()), ui_->logicComparisonComboBox->currentData().toInt()),
static_cast<std::int16_t>(ui_->logicValueSpinBox->value())}; static_cast<std::int16_t>(ui_->logicValueSpinBox->value())};
} }
else
{
config = TonNodeConfig{
TimerAddress{ui_->logicAddressSpinBox->value()},
ui_->logicPresetSpinBox->value()};
}


const LogicEditorResult result = logic_editor_service_.updateNodeConfig( const LogicEditorResult result = logic_editor_service_.updateNodeConfig(
current_logic_id_, selected_logic_node_id_, config); current_logic_id_, selected_logic_node_id_, config);
@@ -1775,13 +1949,19 @@ void MainWindow::updateModeUi(const QString &message)
ui_->addPageJumpAction->setEnabled(policy.allowsProjectEditing); ui_->addPageJumpAction->setEnabled(policy.allowsProjectEditing);
ui_->addAlarmListAction->setEnabled(policy.allowsProjectEditing); ui_->addAlarmListAction->setEnabled(policy.allowsProjectEditing);
ui_->configureAlarmsAction->setEnabled(policy.allowsProjectEditing); ui_->configureAlarmsAction->setEnabled(policy.allowsProjectEditing);
ui_->configureRegisterCommentsAction->setEnabled(policy.allowsProjectEditing);
ui_->deleteControlAction->setEnabled(policy.allowsProjectEditing); ui_->deleteControlAction->setEnabled(policy.allowsProjectEditing);
ui_->addNormallyOpenAction->setEnabled(policy.allowsProjectEditing); ui_->addNormallyOpenAction->setEnabled(policy.allowsProjectEditing);
ui_->addNormallyClosedAction->setEnabled(policy.allowsProjectEditing); ui_->addNormallyClosedAction->setEnabled(policy.allowsProjectEditing);
ui_->addRisingEdgeAction->setEnabled(policy.allowsProjectEditing);
ui_->addFallingEdgeAction->setEnabled(policy.allowsProjectEditing);
ui_->addTimerContactAction->setEnabled(policy.allowsProjectEditing);
ui_->addNormalCoilAction->setEnabled(policy.allowsProjectEditing); ui_->addNormalCoilAction->setEnabled(policy.allowsProjectEditing);
ui_->addSetCoilAction->setEnabled(policy.allowsProjectEditing); ui_->addSetCoilAction->setEnabled(policy.allowsProjectEditing);
ui_->addResetCoilAction->setEnabled(policy.allowsProjectEditing); ui_->addResetCoilAction->setEnabled(policy.allowsProjectEditing);
ui_->addTonAction->setEnabled(policy.allowsProjectEditing);
ui_->addCompareAction->setEnabled(policy.allowsProjectEditing); ui_->addCompareAction->setEnabled(policy.allowsProjectEditing);
ui_->editRungCommentAction->setEnabled(policy.allowsProjectEditing);
ui_->deleteLogicAction->setEnabled(policy.allowsProjectEditing); ui_->deleteLogicAction->setEnabled(policy.allowsProjectEditing);
ui_->newProjectAction->setEnabled(policy.allowsProjectEditing); ui_->newProjectAction->setEnabled(policy.allowsProjectEditing);
ui_->saveProjectAction->setEnabled(policy.allowsProjectEditing); ui_->saveProjectAction->setEnabled(policy.allowsProjectEditing);


+ 6
- 0
app/src/ui/main_window.h Parādīt failu

@@ -35,6 +35,7 @@ class HmiRuntimeService;
class AlarmEditorService; class AlarmEditorService;
class AlarmService; class AlarmService;
class HmiNavigationService; class HmiNavigationService;
class RegisterCommentService;
class HmiEditorWidget; class HmiEditorWidget;
class LogicEditorService; class LogicEditorService;
class LogicEditorWidget; class LogicEditorWidget;
@@ -67,6 +68,7 @@ public:
HmiRuntimeService &hmi_runtime_service, HmiRuntimeService &hmi_runtime_service,
AlarmEditorService &alarm_editor_service, AlarmEditorService &alarm_editor_service,
AlarmService &alarm_service, AlarmService &alarm_service,
RegisterCommentService &register_comment_service,
RegisterMonitorService &register_monitor_service, RegisterMonitorService &register_monitor_service,
QWidget *parent = nullptr); QWidget *parent = nullptr);
MainWindow( MainWindow(
@@ -78,6 +80,7 @@ public:
AlarmEditorService &alarm_editor_service, AlarmEditorService &alarm_editor_service,
AlarmService &alarm_service, AlarmService &alarm_service,
HmiNavigationService &hmi_navigation_service, HmiNavigationService &hmi_navigation_service,
RegisterCommentService &register_comment_service,
RegisterMonitorService &register_monitor_service, RegisterMonitorService &register_monitor_service,
QWidget *parent = nullptr); QWidget *parent = nullptr);


@@ -101,6 +104,7 @@ private:
void configurePropertyEditor(); void configurePropertyEditor();
void configurePlcConnection(); void configurePlcConnection();
void configureAlarms(); void configureAlarms();
void configureRegisterComments();
// 刷新工程树和当前 HMI 页面信息 // 刷新工程树和当前 HMI 页面信息
void refreshProjectUi(); void refreshProjectUi();
void handleProjectTreeSelection(); void handleProjectTreeSelection();
@@ -130,6 +134,7 @@ private:
void setLogicOutput(const LogicNodeConfig &config); void setLogicOutput(const LogicNodeConfig &config);
// 新增一个梯形图网络 // 新增一个梯形图网络
void addLogicRung(); void addLogicRung();
void editSelectedRungComment();
// 删除当前选中的逻辑节点或网络 // 删除当前选中的逻辑节点或网络
void deleteSelectedLogicObject(); void deleteSelectedLogicObject();
// 将逻辑属性表单内容应用到当前选中节点 // 将逻辑属性表单内容应用到当前选中节点
@@ -185,6 +190,7 @@ private:
HmiRuntimeService &hmi_runtime_service_; HmiRuntimeService &hmi_runtime_service_;
AlarmEditorService &alarm_editor_service_; AlarmEditorService &alarm_editor_service_;
AlarmService &alarm_service_; AlarmService &alarm_service_;
RegisterCommentService &register_comment_service_;
RegisterMonitorService &register_monitor_service_; RegisterMonitorService &register_monitor_service_;
std::unique_ptr<HmiNavigationService> owned_hmi_navigation_service_; std::unique_ptr<HmiNavigationService> owned_hmi_navigation_service_;
HmiNavigationService *hmi_navigation_service_ = nullptr; HmiNavigationService *hmi_navigation_service_ = nullptr;


+ 78
- 4
app/src/ui/main_window.ui Parādīt failu

@@ -254,9 +254,10 @@
<addaction name="disconnectPlcAction"/> <addaction name="disconnectPlcAction"/>
</widget> </widget>
<widget class="QMenu" name="viewMenu"> <widget class="QMenu" name="viewMenu">
<property name="title">
<string>视图(&amp;V)</string>
</property>
<property name="title">
<string>视图(&amp;V)</string>
</property>
<addaction name="configureRegisterCommentsAction"/>
</widget> </widget>
<addaction name="fileMenu"/> <addaction name="fileMenu"/>
<addaction name="runMenu"/> <addaction name="runMenu"/>
@@ -326,10 +327,15 @@
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="addNormallyOpenAction"/> <addaction name="addNormallyOpenAction"/>
<addaction name="addNormallyClosedAction"/> <addaction name="addNormallyClosedAction"/>
<addaction name="addRisingEdgeAction"/>
<addaction name="addFallingEdgeAction"/>
<addaction name="addTimerContactAction"/>
<addaction name="addNormalCoilAction"/> <addaction name="addNormalCoilAction"/>
<addaction name="addSetCoilAction"/> <addaction name="addSetCoilAction"/>
<addaction name="addResetCoilAction"/> <addaction name="addResetCoilAction"/>
<addaction name="addTonAction"/>
<addaction name="addCompareAction"/> <addaction name="addCompareAction"/>
<addaction name="editRungCommentAction"/>
<addaction name="deleteLogicAction"/> <addaction name="deleteLogicAction"/>
</widget> </widget>
<widget class="QDockWidget" name="projectDock"> <widget class="QDockWidget" name="projectDock">
@@ -758,7 +764,27 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0" colspan="2">
<item row="7" column="0">
<widget class="QLabel" name="logicPresetLabel">
<property name="text">
<string>预设时间(ms)</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSpinBox" name="logicPresetSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>86400000</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item row="8" column="0" colspan="2">
<widget class="QPushButton" name="applyLogicPropertiesButton"> <widget class="QPushButton" name="applyLogicPropertiesButton">
<property name="text"> <property name="text">
<string>应用属性</string> <string>应用属性</string>
@@ -848,6 +874,14 @@
<string>配置参数并连接真实 PLC</string> <string>配置参数并连接真实 PLC</string>
</property> </property>
</action> </action>
<action name="configureRegisterCommentsAction">
<property name="text">
<string>软元件注释</string>
</property>
<property name="toolTip">
<string>维护工程级 M/D 地址注释</string>
</property>
</action>
<action name="disconnectPlcAction"> <action name="disconnectPlcAction">
<property name="text"> <property name="text">
<string>断开 PLC</string> <string>断开 PLC</string>
@@ -960,6 +994,30 @@
<string>向当前网络添加常闭触点</string> <string>向当前网络添加常闭触点</string>
</property> </property>
</action> </action>
<action name="addRisingEdgeAction">
<property name="text">
<string>上升沿</string>
</property>
<property name="toolTip">
<string>添加一个扫描周期的上升沿触点</string>
</property>
</action>
<action name="addFallingEdgeAction">
<property name="text">
<string>下降沿</string>
</property>
<property name="toolTip">
<string>添加一个扫描周期的下降沿触点</string>
</property>
</action>
<action name="addTimerContactAction">
<property name="text">
<string>T 触点</string>
</property>
<property name="toolTip">
<string>添加离线仿真定时器触点</string>
</property>
</action>
<action name="addNormalCoilAction"> <action name="addNormalCoilAction">
<property name="text"> <property name="text">
<string>线圈</string> <string>线圈</string>
@@ -984,6 +1042,14 @@
<string>设置当前网络的复位线圈</string> <string>设置当前网络的复位线圈</string>
</property> </property>
</action> </action>
<action name="addTonAction">
<property name="text">
<string>TON</string>
</property>
<property name="toolTip">
<string>设置非保持接通延时定时器输出</string>
</property>
</action>
<action name="addCompareAction"> <action name="addCompareAction">
<property name="text"> <property name="text">
<string>D 比较</string> <string>D 比较</string>
@@ -992,6 +1058,14 @@
<string>向当前网络添加 D 值与常量比较</string> <string>向当前网络添加 D 值与常量比较</string>
</property> </property>
</action> </action>
<action name="editRungCommentAction">
<property name="text">
<string>网络注释</string>
</property>
<property name="toolTip">
<string>编辑当前梯形图网络说明</string>
</property>
</action>
<action name="deleteLogicAction"> <action name="deleteLogicAction">
<property name="text"> <property name="text">
<string>删除</string> <string>删除</string>


+ 155
- 0
app/src/ui/register_comment_dialog.cpp Parādīt failu

@@ -0,0 +1,155 @@
#include "register_comment_dialog.h"

#include "services/register_comment_service.h"
#include "ui_register_comment_dialog.h"

#include <QHeaderView>
#include <QMessageBox>
#include <QTableWidgetItem>

#include <optional>

namespace {

QString fromUtf8(const std::string &value)
{
return QString::fromUtf8(value.data(), static_cast<int>(value.size()));
}

std::string toUtf8(const QString &value)
{
const QByteArray bytes = value.toUtf8();
return std::string(bytes.constData(), static_cast<std::size_t>(bytes.size()));
}

} // namespace

RegisterCommentDialog::RegisterCommentDialog(
RegisterCommentService &service,
QWidget *parent)
: QDialog(parent),
ui_(std::make_unique<Ui::RegisterCommentDialog>()),
service_(service)
{
ui_->setupUi(this);
ui_->commentTable->horizontalHeader()->setSectionResizeMode(
0, QHeaderView::ResizeToContents);
ui_->commentTable->horizontalHeader()->setSectionResizeMode(
1, QHeaderView::Stretch);
ui_->areaComboBox->setItemData(0, static_cast<int>(RegisterArea::M));
ui_->areaComboBox->setItemData(1, static_cast<int>(RegisterArea::D));
connect(ui_->commentTable, &QTableWidget::itemSelectionChanged,
this, [this] { loadSelectedComment(); });
connect(ui_->saveButton, &QPushButton::clicked,
this, [this] { saveComment(); });
connect(ui_->removeButton, &QPushButton::clicked,
this, [this] { removeComment(); });
connect(ui_->buttonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject);
reloadComments();
}

RegisterCommentDialog::~RegisterCommentDialog() = default;

void RegisterCommentDialog::reloadComments(
const RegisterAddress *selected_address)
{
const auto &comments = service_.comments();
ui_->commentTable->setRowCount(static_cast<int>(comments.size()));
int selected_row = -1;
for (std::size_t index = 0; index < comments.size(); ++index)
{
const RegisterComment &comment = comments[index];
const int row = static_cast<int>(index);
auto *address_item = new QTableWidgetItem(
QString::fromStdString(comment.address.toString()));
address_item->setData(Qt::UserRole, static_cast<int>(comment.address.area()));
address_item->setData(Qt::UserRole + 1, comment.address.index());
ui_->commentTable->setItem(row, 0, address_item);
ui_->commentTable->setItem(row, 1, new QTableWidgetItem(fromUtf8(comment.text)));
if (selected_address != nullptr && comment.address == *selected_address)
{
selected_row = row;
}
}
if (selected_row >= 0)
{
ui_->commentTable->selectRow(selected_row);
}
else
{
ui_->commentTable->clearSelection();
ui_->removeButton->setEnabled(false);
}
}

void RegisterCommentDialog::loadSelectedComment()
{
const std::optional<RegisterAddress> address = selectedAddress();
const RegisterComment *comment = address.has_value()
? service_.findComment(*address) : nullptr;
ui_->removeButton->setEnabled(comment != nullptr);
if (comment == nullptr)
{
return;
}
ui_->areaComboBox->setCurrentIndex(
comment->address.area() == RegisterArea::M ? 0 : 1);
ui_->indexSpinBox->setValue(comment->address.index());
ui_->commentEdit->setText(fromUtf8(comment->text));
}

void RegisterCommentDialog::saveComment()
{
const RegisterAddress address = addressFromInputs();
const RegisterCommentResult result = service_.setComment(
address, toUtf8(ui_->commentEdit->text()));
if (!result.succeeded)
{
QMessageBox::warning(this, tr("保存注释"), fromUtf8(result.message));
return;
}
reloadComments(&address);
}

void RegisterCommentDialog::removeComment()
{
const std::optional<RegisterAddress> address = selectedAddress();
if (!address.has_value())
{
return;
}
if (QMessageBox::question(
this, tr("删除注释"), tr("确定删除当前软元件注释吗?"))
!= QMessageBox::Yes)
{
return;
}
const RegisterCommentResult result = service_.removeComment(*address);
if (!result.succeeded)
{
QMessageBox::warning(this, tr("删除注释"), fromUtf8(result.message));
return;
}
reloadComments();
}

RegisterAddress RegisterCommentDialog::addressFromInputs() const
{
const RegisterArea area = static_cast<RegisterArea>(
ui_->areaComboBox->currentData().toInt());
return RegisterAddress{area, ui_->indexSpinBox->value()};
}

std::optional<RegisterAddress> RegisterCommentDialog::selectedAddress() const
{
const int row = ui_->commentTable->currentRow();
const QTableWidgetItem *item = row >= 0 ? ui_->commentTable->item(row, 0) : nullptr;
if (item == nullptr)
{
return std::nullopt;
}
return RegisterAddress{
static_cast<RegisterArea>(item->data(Qt::UserRole).toInt()),
item->data(Qt::UserRole + 1).toInt()};
}

+ 34
- 0
app/src/ui/register_comment_dialog.h Parādīt failu

@@ -0,0 +1,34 @@
#pragma once

#include "domain/register_address.h"

#include <QDialog>

#include <memory>
#include <optional>

namespace Ui {
class RegisterCommentDialog;
}

class RegisterCommentService;

class RegisterCommentDialog final : public QDialog
{
public:
explicit RegisterCommentDialog(
RegisterCommentService &service,
QWidget *parent = nullptr);
~RegisterCommentDialog() override;

private:
void reloadComments(const RegisterAddress *selected_address = nullptr);
void loadSelectedComment();
void saveComment();
void removeComment();
RegisterAddress addressFromInputs() const;
std::optional<RegisterAddress> selectedAddress() const;

std::unique_ptr<Ui::RegisterCommentDialog> ui_;
RegisterCommentService &service_;
};

+ 40
- 0
app/src/ui/register_comment_dialog.ui Parādīt failu

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RegisterCommentDialog</class>
<widget class="QDialog" name="RegisterCommentDialog">
<property name="windowTitle"><string>软元件注释</string></property>
<property name="minimumSize"><size><width>620</width><height>400</height></size></property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="commentTable">
<property name="selectionBehavior"><enum>QAbstractItemView::SelectRows</enum></property>
<property name="selectionMode"><enum>QAbstractItemView::SingleSelection</enum></property>
<property name="editTriggers"><set>QAbstractItemView::NoEditTriggers</set></property>
<property name="columnCount"><number>2</number></property>
<column><property name="text"><string>地址</string></property></column>
<column><property name="text"><string>注释</string></property></column>
</widget>
</item>
<item>
<layout class="QFormLayout" name="commentForm">
<item row="0" column="0"><widget class="QLabel" name="areaLabel"><property name="text"><string>地址区域</string></property></widget></item>
<item row="0" column="1"><widget class="QComboBox" name="areaComboBox"><item><property name="text"><string>M</string></property></item><item><property name="text"><string>D</string></property></item></widget></item>
<item row="1" column="0"><widget class="QLabel" name="indexLabel"><property name="text"><string>地址</string></property></widget></item>
<item row="1" column="1"><widget class="QSpinBox" name="indexSpinBox"><property name="maximum"><number>4000</number></property></widget></item>
<item row="2" column="0"><widget class="QLabel" name="commentLabel"><property name="text"><string>注释</string></property></widget></item>
<item row="2" column="1"><widget class="QLineEdit" name="commentEdit"><property name="placeholderText"><string>例如:启动按钮</string></property></widget></item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="operationLayout">
<item><widget class="QPushButton" name="saveButton"><property name="text"><string>保存</string></property></widget></item>
<item><widget class="QPushButton" name="removeButton"><property name="text"><string>删除</string></property></widget></item>
<item><spacer name="operationSpacer"><property name="orientation"><enum>Qt::Horizontal</enum></property><property name="sizeHint" stdset="0"><size><width>40</width><height>20</height></size></property></spacer></item>
<item><widget class="QDialogButtonBox" name="buttonBox"><property name="standardButtons"><set>QDialogButtonBox::Close</set></property></widget></item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

+ 113
- 0
app/tests/main_window_tests.cpp Parādīt failu

@@ -11,6 +11,7 @@
#include "services/project_service.h" #include "services/project_service.h"
#include "services/runtime_mode_service.h" #include "services/runtime_mode_service.h"
#include "services/register_monitor_service.h" #include "services/register_monitor_service.h"
#include "services/register_comment_service.h"
#include "ui/hmi_editor_widget.h" #include "ui/hmi_editor_widget.h"
#include "ui/free_monitor_widget.h" #include "ui/free_monitor_widget.h"
#include "ui/logic_editor_widget.h" #include "ui/logic_editor_widget.h"
@@ -29,9 +30,11 @@
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QListWidget> #include <QListWidget>
#include <QMenu>
#include <QPainter> #include <QPainter>
#include <QSpinBox> #include <QSpinBox>
#include <QPushButton> #include <QPushButton>
#include <QStringList>
#include <QTableWidget> #include <QTableWidget>
#include <QTimer> #include <QTimer>
#include <QTest> #include <QTest>
@@ -501,6 +504,7 @@ void testModeActionsControlEditingAvailability()
HmiRuntimeService runtime_service(repository); HmiRuntimeService runtime_service(repository);
AlarmEditorService alarm_editor_service(project_service); AlarmEditorService alarm_editor_service(project_service);
AlarmService alarm_service(project_service, repository); AlarmService alarm_service(project_service, repository);
RegisterCommentService register_comment_service(project_service);
OfflineSimulationService simulation_service(repository); OfflineSimulationService simulation_service(repository);
RuntimeModeService mode_service(project_service, simulation_service); RuntimeModeService mode_service(project_service, simulation_service);
RegisterMonitorService monitor_service(repository); RegisterMonitorService monitor_service(repository);
@@ -512,6 +516,7 @@ void testModeActionsControlEditingAvailability()
runtime_service, runtime_service,
alarm_editor_service, alarm_editor_service,
alarm_service, alarm_service,
register_comment_service,
monitor_service); monitor_service);
window.resize(1000, 640); window.resize(1000, 640);
window.show(); window.show();
@@ -711,6 +716,105 @@ void testModeActionsControlEditingAvailability()
"rejected online running must restore the editing action"); "rejected online running must restore the editing action");
} }


void testEdgeTimerPropertyEditingAndParallelMenu()
{
TestProjectStorage storage;
ProjectService project_service(storage);
HmiEditorService editor_service(project_service);
LogicEditorService logic_editor_service(project_service);
VirtualRegisterRepository repository;
HmiRuntimeService runtime_service(repository);
AlarmEditorService alarm_editor_service(project_service);
AlarmService alarm_service(project_service, repository);
RegisterCommentService register_comment_service(project_service);
OfflineSimulationService simulation_service(repository);
RuntimeModeService mode_service(project_service, simulation_service);
RegisterMonitorService monitor_service(repository);
MainWindow window(
mode_service,
project_service,
editor_service,
logic_editor_service,
runtime_service,
alarm_editor_service,
alarm_service,
register_comment_service,
monitor_service);
window.show();
QApplication::processEvents();

QAction *parallel_action = requiredChild<QAction>(window, "parallelInsertAction");
require(parallel_action->menu() != nullptr,
"parallel insertion must expose its node type menu");
QStringList parallel_labels;
for (QAction *action : parallel_action->menu()->actions())
{
parallel_labels.push_back(action->text());
}
require(parallel_labels.contains(QStringLiteral("并联上升沿触点"))
&& parallel_labels.contains(QStringLiteral("并联下降沿触点"))
&& parallel_labels.contains(QStringLiteral("并联 T 触点")),
"parallel insertion must include edge and T contact choices");

QAction *rising_action = requiredChild<QAction>(window, "addRisingEdgeAction");
QAction *falling_action = requiredChild<QAction>(window, "addFallingEdgeAction");
QAction *timer_contact_action = requiredChild<QAction>(
window, "addTimerContactAction");
QAction *ton_action = requiredChild<QAction>(window, "addTonAction");
requiredChild<QAction>(window, "editRungCommentAction");
requiredChild<QAction>(window, "configureRegisterCommentsAction");
QSpinBox *address = requiredChild<QSpinBox>(window, "logicAddressSpinBox");
QSpinBox *preset = requiredChild<QSpinBox>(window, "logicPresetSpinBox");
QComboBox *mode = requiredChild<QComboBox>(window, "logicModeComboBox");
QPushButton *apply = requiredChild<QPushButton>(
window, "applyLogicPropertiesButton");
const std::string logic_id = logic_editor_service.firstLogicId();

rising_action->trigger();
address->setValue(8);
mode->setCurrentIndex(mode->findData(static_cast<int>(EdgeMode::Falling)));
apply->click();
const LogicNode *edge = logic_editor_service.findNode(logic_id, "edge-1");
require(edge != nullptr && edge->configured
&& std::get<EdgeContactNodeConfig>(edge->config).address.index() == 8
&& std::get<EdgeContactNodeConfig>(edge->config).mode
== EdgeMode::Falling,
"edge properties must update M address and edge mode");

timer_contact_action->trigger();
address->setValue(9);
mode->setCurrentIndex(mode->findData(
static_cast<int>(ContactMode::NormallyClosed)));
apply->click();
const LogicNode *timer_contact = logic_editor_service.findNode(
logic_id, "timer-contact-1");
require(timer_contact != nullptr && timer_contact->configured
&& std::get<TimerContactNodeConfig>(timer_contact->config).address
== TimerAddress{9}
&& std::get<TimerContactNodeConfig>(timer_contact->config).mode
== ContactMode::NormallyClosed,
"T contact properties must update T address and contact mode");

ton_action->trigger();
require(preset->isEnabled() && !mode->isEnabled(),
"TON properties must enable PT and disable irrelevant mode editing");
address->setValue(9);
preset->setValue(1234);
apply->click();
const LogicNode *ton = logic_editor_service.findNode(logic_id, "ton-1");
require(ton != nullptr && ton->configured
&& std::get<TonNodeConfig>(ton->config).address == TimerAddress{9}
&& std::get<TonNodeConfig>(ton->config).presetMs == 1234,
"TON properties must update T address and preset milliseconds");

falling_action->trigger();
const LogicNode *falling = logic_editor_service.findNode(logic_id, "edge-2");
require(falling != nullptr
&& std::get<EdgeContactNodeConfig>(falling->config).mode
== EdgeMode::Falling,
"falling edge action must create a falling-edge condition");
}

void testPlcConfigurationUsesDialog() void testPlcConfigurationUsesDialog()
{ {
PlcSerialConfiguration initial; PlcSerialConfiguration initial;
@@ -746,6 +850,7 @@ void testPlcConfigurationUsesDialog()
HmiRuntimeService runtime_service(repository); HmiRuntimeService runtime_service(repository);
AlarmEditorService alarm_editor_service(project_service); AlarmEditorService alarm_editor_service(project_service);
AlarmService alarm_service(project_service, repository); AlarmService alarm_service(project_service, repository);
RegisterCommentService register_comment_service(project_service);
OfflineSimulationService simulation_service(repository); OfflineSimulationService simulation_service(repository);
RuntimeModeService mode_service(project_service, simulation_service); RuntimeModeService mode_service(project_service, simulation_service);
RegisterMonitorService monitor_service(repository); RegisterMonitorService monitor_service(repository);
@@ -757,6 +862,7 @@ void testPlcConfigurationUsesDialog()
runtime_service, runtime_service,
alarm_editor_service, alarm_editor_service,
alarm_service, alarm_service,
register_comment_service,
monitor_service); monitor_service);
require(window.findChild<QComboBox *>(QStringLiteral("serialPortComboBox")) == nullptr, require(window.findChild<QComboBox *>(QStringLiteral("serialPortComboBox")) == nullptr,
"serial configuration controls must not be embedded in the main window"); "serial configuration controls must not be embedded in the main window");
@@ -791,6 +897,7 @@ void testRepeatedPlcStatusNotificationsAreCoalesced()
HmiRuntimeService runtime_service(active_repository); HmiRuntimeService runtime_service(active_repository);
AlarmEditorService alarm_editor_service(project_service); AlarmEditorService alarm_editor_service(project_service);
AlarmService alarm_service(project_service, active_repository); AlarmService alarm_service(project_service, active_repository);
RegisterCommentService register_comment_service(project_service);
OfflineSimulationService simulation_service(virtual_repository); OfflineSimulationService simulation_service(virtual_repository);
RepeatedStatusGateway gateway; RepeatedStatusGateway gateway;
RuntimeModeService mode_service(project_service, simulation_service); RuntimeModeService mode_service(project_service, simulation_service);
@@ -805,6 +912,7 @@ void testRepeatedPlcStatusNotificationsAreCoalesced()
runtime_service, runtime_service,
alarm_editor_service, alarm_editor_service,
alarm_service, alarm_service,
register_comment_service,
monitor_service); monitor_service);
QListWidget *output = requiredChild<QListWidget>(window, "outputList"); QListWidget *output = requiredChild<QListWidget>(window, "outputList");
const int initial_count = output->count(); const int initial_count = output->count();
@@ -839,6 +947,7 @@ void testOnlineWorkspaceShowsHmiAndFreeMonitorOnly()
HmiRuntimeService runtime_service(active_repository); HmiRuntimeService runtime_service(active_repository);
AlarmEditorService alarm_editor_service(project_service); AlarmEditorService alarm_editor_service(project_service);
AlarmService alarm_service(project_service, active_repository); AlarmService alarm_service(project_service, active_repository);
RegisterCommentService register_comment_service(project_service);
OfflineSimulationService simulation_service(virtual_repository); OfflineSimulationService simulation_service(virtual_repository);
OnlineReadyGateway gateway; OnlineReadyGateway gateway;
RuntimeModeService mode_service(project_service, simulation_service); RuntimeModeService mode_service(project_service, simulation_service);
@@ -853,6 +962,7 @@ void testOnlineWorkspaceShowsHmiAndFreeMonitorOnly()
runtime_service, runtime_service,
alarm_editor_service, alarm_editor_service,
alarm_service, alarm_service,
register_comment_service,
monitor_service); monitor_service);
window.resize(1200, 760); window.resize(1200, 760);
window.show(); window.show();
@@ -965,6 +1075,7 @@ void testMultiPageAndLogicMainWindowIntegration()
HmiRuntimeService runtime_service(repository); HmiRuntimeService runtime_service(repository);
AlarmEditorService alarm_editor_service(project_service); AlarmEditorService alarm_editor_service(project_service);
AlarmService alarm_service(project_service, repository); AlarmService alarm_service(project_service, repository);
RegisterCommentService register_comment_service(project_service);
OfflineSimulationService simulation_service(repository); OfflineSimulationService simulation_service(repository);
RuntimeModeService mode_service(project_service, simulation_service); RuntimeModeService mode_service(project_service, simulation_service);
RegisterMonitorService monitor_service(repository); RegisterMonitorService monitor_service(repository);
@@ -978,6 +1089,7 @@ void testMultiPageAndLogicMainWindowIntegration()
alarm_editor_service, alarm_editor_service,
alarm_service, alarm_service,
navigation_service, navigation_service,
register_comment_service,
monitor_service); monitor_service);
window.resize(1400, 820); window.resize(1400, 820);
window.show(); window.show();
@@ -1078,6 +1190,7 @@ int main(int argc, char *argv[])
testRuntimePageJumpDoesNotRequireRegisterWritePermission(); testRuntimePageJumpDoesNotRequireRegisterWritePermission();
testRuntimeAlarmListInteraction(); testRuntimeAlarmListInteraction();
testModeActionsControlEditingAvailability(); testModeActionsControlEditingAvailability();
testEdgeTimerPropertyEditingAndParallelMenu();
testPlcConfigurationUsesDialog(); testPlcConfigurationUsesDialog();
testRepeatedPlcStatusNotificationsAreCoalesced(); testRepeatedPlcStatusNotificationsAreCoalesced();
testOnlineWorkspaceShowsHmiAndFreeMonitorOnly(); testOnlineWorkspaceShowsHmiAndFreeMonitorOnly();


+ 7
- 2
app/tests/main_window_tests.pro Parādīt failu

@@ -12,6 +12,7 @@ SOURCES += \
main_window_tests.cpp \ main_window_tests.cpp \
../src/ui/main_window.cpp \ ../src/ui/main_window.cpp \
../src/ui/alarm_configuration_dialog.cpp \ ../src/ui/alarm_configuration_dialog.cpp \
../src/ui/register_comment_dialog.cpp \
../src/ui/plc_connection_dialog.cpp \ ../src/ui/plc_connection_dialog.cpp \
../src/ui/free_monitor_widget.cpp \ ../src/ui/free_monitor_widget.cpp \
../src/ui/runtime_monitor_widget.cpp \ ../src/ui/runtime_monitor_widget.cpp \
@@ -36,11 +37,13 @@ SOURCES += \
../src/services/software_logic_executor.cpp \ ../src/services/software_logic_executor.cpp \
../src/services/offline_simulation_service.cpp \ ../src/services/offline_simulation_service.cpp \
../src/services/runtime_mode_service.cpp \ ../src/services/runtime_mode_service.cpp \
../src/services/register_monitor_service.cpp
../src/services/register_monitor_service.cpp \
../src/services/register_comment_service.cpp


HEADERS += \ HEADERS += \
../src/ui/main_window.h \ ../src/ui/main_window.h \
../src/ui/alarm_configuration_dialog.h \ ../src/ui/alarm_configuration_dialog.h \
../src/ui/register_comment_dialog.h \
../src/ui/plc_connection_dialog.h \ ../src/ui/plc_connection_dialog.h \
../src/ui/free_monitor_widget.h \ ../src/ui/free_monitor_widget.h \
../src/ui/runtime_monitor_widget.h \ ../src/ui/runtime_monitor_widget.h \
@@ -66,7 +69,8 @@ HEADERS += \
../src/services/software_logic_executor.h \ ../src/services/software_logic_executor.h \
../src/services/offline_simulation_service.h \ ../src/services/offline_simulation_service.h \
../src/services/runtime_mode_service.h \ ../src/services/runtime_mode_service.h \
../src/services/register_monitor_service.h
../src/services/register_monitor_service.h \
../src/services/register_comment_service.h


HEADERS += \ HEADERS += \
../src/services/plc_communication_gateway.h ../src/services/plc_communication_gateway.h
@@ -74,6 +78,7 @@ HEADERS += \
FORMS += \ FORMS += \
../src/ui/main_window.ui \ ../src/ui/main_window.ui \
../src/ui/alarm_configuration_dialog.ui \ ../src/ui/alarm_configuration_dialog.ui \
../src/ui/register_comment_dialog.ui \
../src/ui/plc_connection_dialog.ui \ ../src/ui/plc_connection_dialog.ui \
../src/ui/free_monitor_widget.ui \ ../src/ui/free_monitor_widget.ui \
../src/ui/runtime_monitor_widget.ui ../src/ui/runtime_monitor_widget.ui

Notiek ielāde…
Atcelt
Saglabāt