| @@ -963,7 +963,7 @@ void LogicEditorWidget::reloadLogic() | |||||
| measureExpression(*rung.condition).columns); | measureExpression(*rung.condition).columns); | ||||
| } | } | ||||
| } | } | ||||
| const int grid_columns = std::max(kMinimumLogicColumns, condition_columns + 2); | |||||
| const int grid_columns = std::max(kMinimumLogicColumns, condition_columns + 1); | |||||
| const qreal left_rail_x = kSceneMargin + kRailInset; | const qreal left_rail_x = kSceneMargin + kRailInset; | ||||
| const qreal right_rail_x = left_rail_x + static_cast<qreal>(grid_columns) * kCellWidth; | const qreal right_rail_x = left_rail_x + static_cast<qreal>(grid_columns) * kCellWidth; | ||||
| const qreal scene_width = std::max(kMinimumSceneWidth, right_rail_x + kSceneMargin); | const qreal scene_width = std::max(kMinimumSceneWidth, right_rail_x + kSceneMargin); | ||||
| @@ -1016,7 +1016,7 @@ void LogicEditorWidget::reloadLogic() | |||||
| addPlaceholder( | addPlaceholder( | ||||
| *scene_, | *scene_, | ||||
| QRectF(left_rail_x, grid_top, kCellWidth, kCellHeight), | QRectF(left_rail_x, grid_top, kCellWidth, kCellHeight), | ||||
| tr("添加条件")); | |||||
| rung.output.has_value() ? tr("无条件") : tr("添加条件")); | |||||
| } | } | ||||
| const bool rung_active = runtime_trace_enabled_ && traceValue( | const bool rung_active = runtime_trace_enabled_ && traceValue( | ||||
| @@ -165,7 +165,8 @@ void LogicInstructionDialog::updateOperandRanges() | |||||
| spin->setPrefix(register_operand ? QStringLiteral("D") : QString{}); | spin->setPrefix(register_operand ? QStringLiteral("D") : QString{}); | ||||
| spin->setMinimum(register_operand | spin->setMinimum(register_operand | ||||
| ? RegisterAddress::kMinimumIndex | ? RegisterAddress::kMinimumIndex | ||||
| : std::numeric_limits<std::int16_t>::min()); | |||||
| : (combo->objectName() == QStringLiteral("counterPresetKindComboBox") | |||||
| ? 0 : std::numeric_limits<std::int16_t>::min())); | |||||
| spin->setMaximum(register_operand | spin->setMaximum(register_operand | ||||
| ? RegisterAddress::kMaximumIndex | ? RegisterAddress::kMaximumIndex | ||||
| : std::numeric_limits<std::int16_t>::max()); | : std::numeric_limits<std::int16_t>::max()); | ||||
| @@ -23,6 +23,8 @@ | |||||
| #include "services/register_comment_service.h" | #include "services/register_comment_service.h" | ||||
| #include "ui_main_window.h" | #include "ui_main_window.h" | ||||
| #include "domain/project_limits.h" | |||||
| #include <QActionGroup> | #include <QActionGroup> | ||||
| #include <QAbstractSpinBox> | #include <QAbstractSpinBox> | ||||
| #include <QApplication> | #include <QApplication> | ||||
| @@ -851,8 +853,7 @@ void MainWindow::configureRuntimeMonitor() | |||||
| }, | }, | ||||
| [this](const QString &message) | [this](const QString &message) | ||||
| { | { | ||||
| ui_->outputList->addItem(message); | |||||
| ui_->outputList->scrollToBottom(); | |||||
| appendOutputMessage(message); | |||||
| }); | }); | ||||
| runtime_panel_controller_->configure(); | runtime_panel_controller_->configure(); | ||||
| runtime_monitor_widget_ = runtime_panel_controller_->runtimeMonitorWidget(); | runtime_monitor_widget_ = runtime_panel_controller_->runtimeMonitorWidget(); | ||||
| @@ -1467,14 +1468,23 @@ void MainWindow::showProjectResult( | |||||
| { | { | ||||
| const QString output = action + QStringLiteral(": ") + message; | const QString output = action + QStringLiteral(": ") + message; | ||||
| statusBar()->showMessage(output, 5000); | statusBar()->showMessage(output, 5000); | ||||
| ui_->outputList->addItem(output); | |||||
| ui_->outputList->scrollToBottom(); | |||||
| appendOutputMessage(output); | |||||
| if (!succeeded) | if (!succeeded) | ||||
| { | { | ||||
| QMessageBox::warning(this, action, message); | QMessageBox::warning(this, action, message); | ||||
| } | } | ||||
| } | } | ||||
| void MainWindow::appendOutputMessage(const QString &message) | |||||
| { | |||||
| while (ui_->outputList->count() >= ProjectLimits::kMaximumOutputMessages) | |||||
| { | |||||
| delete ui_->outputList->takeItem(0); | |||||
| } | |||||
| ui_->outputList->addItem(message); | |||||
| ui_->outputList->scrollToBottom(); | |||||
| } | |||||
| void MainWindow::requestMode(ApplicationMode requested_mode) | void MainWindow::requestMode(ApplicationMode requested_mode) | ||||
| { | { | ||||
| // UI 仅转发模式意图,合法性由服务层和领域状态机决定 | // UI 仅转发模式意图,合法性由服务层和领域状态机决定 | ||||
| @@ -1662,8 +1672,7 @@ void MainWindow::updateModeUi(const QString &message) | |||||
| && ui_->outputList->item(ui_->outputList->count() - 1)->text() == message; | && ui_->outputList->item(ui_->outputList->count() - 1)->text() == message; | ||||
| if (!duplicate) | if (!duplicate) | ||||
| { | { | ||||
| ui_->outputList->addItem(message); | |||||
| ui_->outputList->scrollToBottom(); | |||||
| appendOutputMessage(message); | |||||
| } | } | ||||
| } | } | ||||
| @@ -162,6 +162,7 @@ private: | |||||
| void loadProject(); | void loadProject(); | ||||
| // 在状态栏和输出面板显示工程操作结果 | // 在状态栏和输出面板显示工程操作结果 | ||||
| void showProjectResult(const QString &action, const QString &message, bool succeeded); | void showProjectResult(const QString &action, const QString &message, bool succeeded); | ||||
| void appendOutputMessage(const QString &message); | |||||
| /** | /** | ||||
| * @brief 请求服务层切换模式并同步界面状态 | * @brief 请求服务层切换模式并同步界面状态 | ||||
| @@ -498,7 +498,7 @@ | |||||
| <item row="2" column="1"> | <item row="2" column="1"> | ||||
| <widget class="QSpinBox" name="controlXSpinBox"> | <widget class="QSpinBox" name="controlXSpinBox"> | ||||
| <property name="maximum"> | <property name="maximum"> | ||||
| <number>4000</number> | |||||
| <number>8192</number> | |||||
| </property> | </property> | ||||
| </widget> | </widget> | ||||
| </item> | </item> | ||||
| @@ -512,7 +512,7 @@ | |||||
| <item row="3" column="1"> | <item row="3" column="1"> | ||||
| <widget class="QSpinBox" name="controlYSpinBox"> | <widget class="QSpinBox" name="controlYSpinBox"> | ||||
| <property name="maximum"> | <property name="maximum"> | ||||
| <number>4000</number> | |||||
| <number>8192</number> | |||||
| </property> | </property> | ||||
| </widget> | </widget> | ||||
| </item> | </item> | ||||
| @@ -529,7 +529,7 @@ | |||||
| <number>1</number> | <number>1</number> | ||||
| </property> | </property> | ||||
| <property name="maximum"> | <property name="maximum"> | ||||
| <number>4000</number> | |||||
| <number>8192</number> | |||||
| </property> | </property> | ||||
| </widget> | </widget> | ||||
| </item> | </item> | ||||
| @@ -546,7 +546,7 @@ | |||||
| <number>1</number> | <number>1</number> | ||||
| </property> | </property> | ||||
| <property name="maximum"> | <property name="maximum"> | ||||
| <number>4000</number> | |||||
| <number>8192</number> | |||||
| </property> | </property> | ||||
| </widget> | </widget> | ||||
| </item> | </item> | ||||
| @@ -65,7 +65,7 @@ | |||||
| <item row="0" column="0"><widget class="QLabel" name="responseTimeoutLabel"><property name="text"><string>响应超时</string></property></widget></item> | <item row="0" column="0"><widget class="QLabel" name="responseTimeoutLabel"><property name="text"><string>响应超时</string></property></widget></item> | ||||
| <item row="0" column="1"><widget class="QSpinBox" name="responseTimeoutSpinBox"><property name="suffix"><string> ms</string></property><property name="minimum"><number>100</number></property><property name="maximum"><number>30000</number></property><property name="singleStep"><number>100</number></property><property name="value"><number>1000</number></property></widget></item> | <item row="0" column="1"><widget class="QSpinBox" name="responseTimeoutSpinBox"><property name="suffix"><string> ms</string></property><property name="minimum"><number>100</number></property><property name="maximum"><number>30000</number></property><property name="singleStep"><number>100</number></property><property name="value"><number>1000</number></property></widget></item> | ||||
| <item row="1" column="0"><widget class="QLabel" name="retriesLabel"><property name="text"><string>失败重试</string></property></widget></item> | <item row="1" column="0"><widget class="QLabel" name="retriesLabel"><property name="text"><string>失败重试</string></property></widget></item> | ||||
| <item row="1" column="1"><widget class="QSpinBox" name="retriesSpinBox"><property name="suffix"><string> 次</string></property><property name="maximum"><number>10</number></property><property name="value"><number>2</number></property></widget></item> | |||||
| <item row="1" column="1"><widget class="QSpinBox" name="retriesSpinBox"><property name="suffix"><string> 次</string></property><property name="maximum"><number>5</number></property><property name="value"><number>2</number></property></widget></item> | |||||
| <item row="2" column="0"><widget class="QLabel" name="pollIntervalLabel"><property name="text"><string>轮询周期</string></property></widget></item> | <item row="2" column="0"><widget class="QLabel" name="pollIntervalLabel"><property name="text"><string>轮询周期</string></property></widget></item> | ||||
| <item row="2" column="1"><widget class="QSpinBox" name="pollIntervalSpinBox"><property name="suffix"><string> ms</string></property><property name="minimum"><number>50</number></property><property name="maximum"><number>10000</number></property><property name="singleStep"><number>50</number></property><property name="value"><number>200</number></property></widget></item> | <item row="2" column="1"><widget class="QSpinBox" name="pollIntervalSpinBox"><property name="suffix"><string> ms</string></property><property name="minimum"><number>50</number></property><property name="maximum"><number>10000</number></property><property name="singleStep"><number>50</number></property><property name="value"><number>200</number></property></widget></item> | ||||
| </layout> | </layout> | ||||
| @@ -84,7 +84,11 @@ public: | |||||
| notifyStateChanged(); | notifyStateChanged(); | ||||
| } | } | ||||
| void setPollAddresses(const std::vector<RegisterAddress> &) override {} | |||||
| PlcCommunicationResult setPollAddresses( | |||||
| const std::vector<RegisterAddress> &) override | |||||
| { | |||||
| return {true, {}}; | |||||
| } | |||||
| PlcConnectionState state() const override { return connection_state; } | PlcConnectionState state() const override { return connection_state; } | ||||
| bool initialReadCompleted() const override { return false; } | bool initialReadCompleted() const override { return false; } | ||||
| PlcCommunicationError lastErrorType() const override | PlcCommunicationError lastErrorType() const override | ||||
| @@ -149,9 +153,11 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| void setPollAddresses(const std::vector<RegisterAddress> &addresses) override | |||||
| PlcCommunicationResult setPollAddresses( | |||||
| const std::vector<RegisterAddress> &addresses) override | |||||
| { | { | ||||
| poll_addresses = addresses; | poll_addresses = addresses; | ||||
| return {true, {}}; | |||||
| } | } | ||||
| PlcConnectionState state() const override { return connection_state; } | PlcConnectionState state() const override { return connection_state; } | ||||