681 lines
24 KiB
C++
Executable File
681 lines
24 KiB
C++
Executable File
/**
|
||
* @file ModelStatusWidget.cpp
|
||
* @author jinchao
|
||
* @brief 模型状态窗口实现
|
||
* @version 1.0
|
||
* @date 2025-03-10
|
||
*
|
||
* @copyright Copyright (c) 2025 COMAC
|
||
*
|
||
*/
|
||
#include "ModelStatusWidget.h"
|
||
#include <QHBoxLayout>
|
||
#include <QScrollArea>
|
||
#include <QLabel>
|
||
#include <QGridLayout>
|
||
#include <QPushButton>
|
||
#include <QTableWidget>
|
||
#include <QHeaderView>
|
||
#include "../XNCustomPlot.h"
|
||
|
||
ModelStatusWidget::ModelStatusWidget(QWidget *parent, SystemStatusWidget *systemStatusWidget)
|
||
: QWidget(parent)
|
||
{
|
||
//初始化系统运行状态窗口指针
|
||
this->systemStatusWidget = systemStatusWidget;
|
||
//初始化模型状态标签页
|
||
setupTabModelStatus();
|
||
//初始化模型信息线程
|
||
InitialModelInfoThread();
|
||
}
|
||
|
||
ModelStatusWidget::~ModelStatusWidget()
|
||
{
|
||
//释放模型信息线程
|
||
if (modelThread != nullptr) {
|
||
modelThread->onThreadQuit();
|
||
modelThread->quit();
|
||
modelThread->wait();
|
||
delete modelThread;
|
||
modelThread = nullptr;
|
||
}
|
||
}
|
||
|
||
void ModelStatusWidget::onSetCurrentTabIndex(int index)
|
||
{
|
||
this->currentTabIndex = index;
|
||
if (currentTabIndex == 1) {
|
||
//如果当前选中的标签页为1,则显示模型状态窗口
|
||
this->show();
|
||
//控制模型信息线程
|
||
emit controlModelInfoThread(true);
|
||
} else {
|
||
//如果当前选中的标签页为0,则隐藏模型状态窗口
|
||
this->hide();
|
||
//控制模型信息线程
|
||
emit controlModelInfoThread(false);
|
||
}
|
||
}
|
||
|
||
void ModelStatusWidget::InitialModelInfoThread()
|
||
{
|
||
//初始化模型信息线程
|
||
modelThread = new ModelInfoUpdateThread(this);
|
||
//连接模型信息线程的更新模型信息信号到槽函数
|
||
connect(modelThread, &ModelInfoUpdateThread::updateModelInfo, this,
|
||
&ModelStatusWidget::updateModelData);
|
||
//连接模型信息线程的控制信号到槽函数
|
||
connect(this, &ModelStatusWidget::controlModelInfoThread, modelThread,
|
||
&ModelInfoUpdateThread::onThreadController);
|
||
//初始化模型信息线程
|
||
modelThread->Initialize();
|
||
//启动模型信息线程
|
||
modelThread->start();
|
||
}
|
||
|
||
// 设置模型状态标签页
|
||
void ModelStatusWidget::setupTabModelStatus()
|
||
{
|
||
QHBoxLayout *mainLayout = new QHBoxLayout(this); // 创建水平布局
|
||
// 使用QSplitter进行左右栏的动态分割
|
||
QSplitter *horizontalSplitter = new QSplitter(Qt::Horizontal); // 创建一个水平方向的QSplitter
|
||
|
||
// 左栏布局
|
||
setupTabModelStatusLeftPanel(horizontalSplitter);
|
||
|
||
// 右栏布局
|
||
setupTabModelStatusRightPanel(horizontalSplitter);
|
||
|
||
// 设置QSplitter的初始分割比例为1:4,即左栏占五分之一,右栏占五分之四
|
||
QList<int> sizes;
|
||
sizes << 1 << 4;
|
||
horizontalSplitter->setSizes(sizes);
|
||
|
||
// 将QSplitter添加到主布局中
|
||
mainLayout->addWidget(horizontalSplitter);
|
||
}
|
||
|
||
// 设置模型状态左栏的布局和组件
|
||
void ModelStatusWidget::setupTabModelStatusLeftPanel(QSplitter *splitter)
|
||
{
|
||
// 左栏布局
|
||
QVBoxLayout *leftMainLayout = new QVBoxLayout();
|
||
QWidget *leftMainWidget = new QWidget();
|
||
leftMainLayout->addWidget(leftMainWidget);
|
||
|
||
QVBoxLayout *leftLayout = new QVBoxLayout();
|
||
leftLayout->setObjectName("ModelStatusLeftLayout");
|
||
leftMainWidget->setLayout(leftLayout);
|
||
|
||
leftMainLayout->addStretch(); // 添加一个伸展项,使得布局可以自动调整大小
|
||
|
||
// 创建一个QWidget作为左栏的容器,并设置其布局为leftLayout
|
||
QWidget *leftPanel = new QWidget();
|
||
leftPanel->setLayout(leftMainLayout);
|
||
|
||
// 创建一个QScrollArea来包含左栏的布局
|
||
QScrollArea *leftScrollArea = new QScrollArea(this);
|
||
leftScrollArea->setWidget(leftPanel);
|
||
leftScrollArea->setWidgetResizable(true);
|
||
leftScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||
leftScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||
|
||
// 将QScrollArea添加到QSplitter中
|
||
splitter->addWidget(leftScrollArea);
|
||
}
|
||
|
||
// 创建线程信息页面
|
||
QWidget *ModelStatusWidget::createThreadInfoPage(unsigned int threadIndex)
|
||
{
|
||
QWidget *page = new QWidget();
|
||
QGridLayout *gridLayout = new QGridLayout(page);
|
||
|
||
// 定义运行信息的标签和初始值
|
||
// 定义标签列表
|
||
const QStringList labels = {"线程ID", "运行状态", "运行周期数", "实时频率", "设定频率",
|
||
"最小频率", "最大频率", "平均频率", "实时周期", "设定周期",
|
||
"最小周期", "最大周期", "平均周期"};
|
||
// 定义值列表
|
||
const QStringList values = {"0", "未运行", "0", "0Hz", "0Hz", "0Hz", "0Hz",
|
||
"0Hz", "0ms", "0ms", "0ms", "0ms", "0ms"};
|
||
|
||
// 遍历标签和值列表,为每个条目创建两个QLabel
|
||
for (int i = 0; i < labels.size(); ++i) {
|
||
QLabel *label = new QLabel(labels[i], page);
|
||
QLabel *valueLabel = new QLabel(values[i], page);
|
||
|
||
// 设置QLabel的对齐方式
|
||
// 设置标签对齐方式为左对齐
|
||
label->setAlignment(Qt::AlignLeft);
|
||
// 设置值标签对齐方式为右对齐
|
||
valueLabel->setAlignment(Qt::AlignRight);
|
||
|
||
// 设置valueLabel的objectName,以便后续可以通过findChild找到并更新它
|
||
valueLabel->setObjectName(QString("threadRunValueLabel%1_%2").arg(threadIndex).arg(i));
|
||
|
||
// 将QLabel添加到网格布局中
|
||
// 在第i行第0列放置标签
|
||
gridLayout->addWidget(label, i, 0);
|
||
// 在第i行第1列放置值
|
||
gridLayout->addWidget(valueLabel, i, 1);
|
||
}
|
||
|
||
return page;
|
||
}
|
||
|
||
// 切换线程信息页面的显示状态
|
||
void ModelStatusWidget::toggleThreadInfo()
|
||
{
|
||
QPushButton *button = qobject_cast<QPushButton *>(sender());
|
||
if (button) {
|
||
QString buttonText = button->objectName();
|
||
int threadIndex = extractTrailingNumbers(buttonText, 3); // 提取数字部分作为线程索引
|
||
if (threadIndex < 0)
|
||
return;
|
||
QWidget *coreInfoPage = findChild<QWidget *>(QString("threadInfoPage%1").arg(threadIndex));
|
||
if (!coreInfoPage)
|
||
return;
|
||
coreInfoPage->setVisible(!coreInfoPage->isVisible());
|
||
}
|
||
}
|
||
|
||
// 设置模型状态右栏的布局和组件
|
||
void ModelStatusWidget::setupTabModelStatusRightPanel(QSplitter *splitter)
|
||
{
|
||
// 右栏布局
|
||
QVBoxLayout *rightLayout = new QVBoxLayout();
|
||
|
||
// 创建一个新的QSplitter用于垂直分割右栏的上下两部分
|
||
QSplitter *verticalSplitter = new QSplitter(Qt::Vertical); // 垂直方向的QSplitter
|
||
|
||
// 表格布局
|
||
QTableWidget *modelStatusTableWidget = new QTableWidget();
|
||
setupModelStatusTableWidget(modelStatusTableWidget);
|
||
|
||
// 图表绘制区域
|
||
QWidget *modelChartWidget = new QWidget(); // 图表区域,可以使用XNCustomPlot等库进行绘制
|
||
setupModelStatusChartWidget(modelChartWidget); // 配置图表区域
|
||
|
||
// 将表格和图表添加到垂直分割器中
|
||
verticalSplitter->addWidget(modelStatusTableWidget);
|
||
verticalSplitter->addWidget(modelChartWidget);
|
||
|
||
QList<int> sizes;
|
||
sizes << 3 << 2;
|
||
verticalSplitter->setSizes(sizes);
|
||
|
||
// 将垂直分割器添加到右栏布局中
|
||
rightLayout->addWidget(verticalSplitter);
|
||
|
||
// 创建一个QWidget作为右栏的容器,并设置其布局为rightLayout
|
||
QWidget *rightPanel = new QWidget();
|
||
rightPanel->setLayout(rightLayout);
|
||
|
||
// 将右栏容器添加到QSplitter中
|
||
splitter->addWidget(rightPanel);
|
||
}
|
||
|
||
// 设置模型状态表格
|
||
void ModelStatusWidget::setupModelStatusTableWidget(QTableWidget *tableWidget)
|
||
{
|
||
tableWidget->setRowCount(10); // 设置表格的行数
|
||
tableWidget->setColumnCount(15); // 设置表格的列数
|
||
|
||
QFont headerFont("Arial", 16, QFont::Bold);
|
||
tableWidget->horizontalHeader()->setFont(headerFont);
|
||
|
||
// 设置表格的列标题
|
||
tableWidget->setHorizontalHeaderLabels(
|
||
{"模型名称", "模型ID", "运行状态", "所属线程", "运行节点", "优先级", "设定频率", "最小频率",
|
||
"最大频率", "平均频率", "周期数", "设定周期", "最小周期", "最大周期", "平均周期"});
|
||
|
||
// 设置表格列宽自适应
|
||
tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
|
||
|
||
// 设置表格的选择行为为按行选择
|
||
tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||
|
||
// 设置表格的选择模式为单选
|
||
tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
||
|
||
// 设置表格不可编辑
|
||
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||
|
||
// 设置表格的objectName,以便后续可以通过findChild找到并更新它
|
||
tableWidget->setObjectName("modelStatusTableWidget");
|
||
|
||
// 连接 threadStatusTableWidget 的 itemSelectionChanged 信号到槽函数
|
||
connect(tableWidget, &QTableWidget::itemSelectionChanged, this,
|
||
&ModelStatusWidget::onModelStatusTableSelectionChanged);
|
||
}
|
||
|
||
// 处理模型状态表格的选择变化
|
||
void ModelStatusWidget::onModelStatusTableSelectionChanged()
|
||
{
|
||
if (currentTabIndex != 1)
|
||
return;
|
||
QTableWidget *modelStatusTableWidget = findChild<QTableWidget *>("modelStatusTableWidget");
|
||
if (!modelStatusTableWidget) {
|
||
return;
|
||
}
|
||
int rowIndex = modelStatusTableWidget->currentRow();
|
||
if (rowIndex < 0 || rowIndex >= modelDataVec.size()) {
|
||
return;
|
||
}
|
||
XNCustomPlot *customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
|
||
if (!customPlot)
|
||
return; // 确保找到了XNCustomPlot对象
|
||
const XNRuntimeData &data = modelDataVec[rowIndex];
|
||
QVector<double> xData, yData;
|
||
if (freqOrPeriodIndex == 0 && data.m_CurrentPeriod.size() > 0) {
|
||
customPlot->xAxis->setRange(0, data.m_CurrentPeriod.size());
|
||
customPlot->yAxis->setRange(data.m_MinPeriod - 1, data.m_MaxPeriod + 1);
|
||
|
||
for (int i = 0; i < data.m_CurrentPeriod.size(); ++i) {
|
||
xData.push_back(i);
|
||
yData.push_back(data.m_CurrentPeriod[i]);
|
||
}
|
||
} else if (freqOrPeriodIndex == 1 && data.m_CurrentFrequency.size() > 0) {
|
||
customPlot->xAxis->setRange(0, data.m_CurrentFrequency.size());
|
||
customPlot->yAxis->setRange(data.m_MinFrequency - 1, data.m_MaxFrequency + 1);
|
||
for (int i = 0; i < data.m_CurrentFrequency.size(); ++i) {
|
||
xData.push_back(i);
|
||
yData.push_back(data.m_CurrentFrequency[i]);
|
||
}
|
||
} else {
|
||
return;
|
||
}
|
||
updatePlotData(xData, yData);
|
||
}
|
||
|
||
// 设置模型状态图表
|
||
void ModelStatusWidget::setupModelStatusChartWidget(QWidget *modelStatusChartWidget)
|
||
{
|
||
modelStatusChartWidget->setObjectName("modelStatusChartWidget");
|
||
XNCustomPlot *customPlot = new XNCustomPlot(modelStatusChartWidget);
|
||
customPlot->setObjectName("modelStatusCustomPlot");
|
||
|
||
// 设置图表布局
|
||
modelStatusChartWidget->setLayout(new QVBoxLayout());
|
||
modelStatusChartWidget->layout()->addWidget(customPlot);
|
||
|
||
// 配置图表
|
||
customPlot->setBackground(QBrush(QColor("#19232D")));
|
||
customPlot->xAxis->setLabelColor(Qt::white);
|
||
customPlot->yAxis->setLabelColor(Qt::white);
|
||
customPlot->xAxis->setLabel("时间(s)");
|
||
customPlot->yAxis->setLabel("周期(ms)");
|
||
customPlot->xAxis->setTickLabelRotation(60);
|
||
customPlot->xAxis->setTickLabelColor(Qt::white);
|
||
customPlot->yAxis->setTickLabelColor(Qt::white);
|
||
customPlot->xAxis->grid()->setVisible(true);
|
||
customPlot->yAxis->grid()->setVisible(true);
|
||
|
||
// 添加图表并设置绿色
|
||
customPlot->addGraph();
|
||
QPen greenPen(Qt::green);
|
||
greenPen.setWidth(2);
|
||
customPlot->graph(0)->setPen(greenPen);
|
||
|
||
// 为chartWidget设置上下文菜单
|
||
connect(customPlot, &XNCustomPlot::customContextMenuRequested, this,
|
||
&ModelStatusWidget::showChartContextMenu);
|
||
|
||
// 连接信号
|
||
connect(this, &ModelStatusWidget::updateModelCutomPlotData, this,
|
||
&ModelStatusWidget::onModelStatusTableSelectionChanged);
|
||
|
||
customPlot->replot();
|
||
}
|
||
|
||
// 处理图表中的右键点击事件
|
||
void ModelStatusWidget::showChartContextMenu(const QPoint &pos)
|
||
{
|
||
XNCustomPlot *customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
|
||
if (!customPlot)
|
||
return; // 确保找到了XNCustomPlot对象
|
||
QMenu contextMenu(this);
|
||
QAction *actionFrequency = contextMenu.addAction("显示频率");
|
||
QAction *actionPeriod = contextMenu.addAction("显示周期");
|
||
|
||
// 连接QAction的triggered信号到相应的槽函数
|
||
connect(actionFrequency, &QAction::triggered, this, &ModelStatusWidget::onShowFrequency);
|
||
connect(actionPeriod, &QAction::triggered, this, &ModelStatusWidget::onShowPeriod);
|
||
|
||
// 在chartWidget上显示上下文菜单
|
||
QAction *selectedAction = contextMenu.exec(customPlot->mapToGlobal(pos));
|
||
}
|
||
|
||
// 处理右键菜单中的"显示频率"选项
|
||
void ModelStatusWidget::onShowFrequency()
|
||
{
|
||
XNCustomPlot *customPlot = nullptr;
|
||
if (currentTabIndex == 1) {
|
||
customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
|
||
} else
|
||
return;
|
||
|
||
if (!customPlot)
|
||
return; // 确保找到了XNCustomPlot对象
|
||
// 实现显示频率的逻辑
|
||
customPlot->yAxis->setLabel("频率(Hz)");
|
||
freqOrPeriodIndex = 1;
|
||
customPlot->replot(); // 重新绘制图表以显示新数据
|
||
emit updateModelCutomPlotData();
|
||
}
|
||
|
||
// 处理右键菜单中的"显示周期"选项
|
||
void ModelStatusWidget::onShowPeriod()
|
||
{
|
||
XNCustomPlot *customPlot = nullptr;
|
||
if (currentTabIndex == 1) {
|
||
customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
|
||
} else
|
||
return;
|
||
|
||
if (!customPlot)
|
||
return; // 确保找到了XNCustomPlot对象
|
||
// 实现显示周期的逻辑
|
||
customPlot->yAxis->setLabel("周期(ms)");
|
||
freqOrPeriodIndex = 0;
|
||
customPlot->replot(); // 重新绘制图表以显示新数据
|
||
emit updateModelCutomPlotData();
|
||
}
|
||
|
||
// 更新线程信息页面
|
||
void ModelStatusWidget::updateThreadInfoPage(unsigned int threadIndex, const XNRuntimeData &data)
|
||
{
|
||
if (currentTabIndex != 1)
|
||
return;
|
||
QPushButton *threadInfoButton =
|
||
findChild<QPushButton *>(QString("threadInfoButton%1").arg(threadIndex));
|
||
if (NULL == threadInfoButton) {
|
||
QVBoxLayout *leftLayout = findChild<QVBoxLayout *>("ModelStatusLeftLayout");
|
||
if (NULL == leftLayout)
|
||
return;
|
||
threadInfoButton = new QPushButton(data.m_name);
|
||
threadInfoButton->setObjectName(QString("threadInfoButton%1").arg(threadIndex));
|
||
connect(threadInfoButton, &QPushButton::clicked, this,
|
||
&ModelStatusWidget::toggleThreadInfo);
|
||
leftLayout->addWidget(threadInfoButton);
|
||
QWidget *threadInfoPage = createThreadInfoPage(threadIndex);
|
||
threadInfoPage->setObjectName(QString("threadInfoPage%1").arg(threadIndex));
|
||
leftLayout->addWidget(threadInfoPage);
|
||
}
|
||
threadInfoButton->setText(data.m_name);
|
||
QWidget *threadInfoPage = findChild<QWidget *>(QString("threadInfoPage%1").arg(threadIndex));
|
||
if (threadInfoPage) {
|
||
updateThreadInfoValue(threadIndex, 0, QString::number(data.m_id));
|
||
switch (data.m_RunningState) {
|
||
case 0:
|
||
updateThreadInfoValue(threadIndex, 1, "未运行");
|
||
break;
|
||
case 1:
|
||
updateThreadInfoValue(threadIndex, 1, "运行中");
|
||
break;
|
||
case 2:
|
||
updateThreadInfoValue(threadIndex, 1, "暂停中");
|
||
break;
|
||
case 3:
|
||
updateThreadInfoValue(threadIndex, 1, "错误");
|
||
break;
|
||
default:
|
||
updateThreadInfoValue(threadIndex, 1, "未知状态");
|
||
break;
|
||
}
|
||
updateThreadInfoValue(threadIndex, 2, QString::number(data.m_CycleCount));
|
||
updateThreadInfoValue(
|
||
threadIndex, 3,
|
||
QString("%1 Hz").arg(data.m_CurrentFrequency[data.m_CurrentFrequency.size() - 1], 0,
|
||
'f', 2));
|
||
updateThreadInfoValue(threadIndex, 4, QString("%1 Hz").arg(data.m_SetFrequency, 0, 'f', 2));
|
||
updateThreadInfoValue(threadIndex, 5, QString("%1 Hz").arg(data.m_MinFrequency, 0, 'f', 2));
|
||
updateThreadInfoValue(threadIndex, 6, QString("%1 Hz").arg(data.m_MaxFrequency, 0, 'f', 2));
|
||
updateThreadInfoValue(threadIndex, 7, QString("%1 Hz").arg(data.m_AvgFrequency, 0, 'f', 2));
|
||
updateThreadInfoValue(
|
||
threadIndex, 8,
|
||
QString("%1 ms").arg(data.m_CurrentPeriod[data.m_CurrentPeriod.size() - 1], 0, 'f', 2));
|
||
updateThreadInfoValue(threadIndex, 9, QString("%1 ms").arg(data.m_SetPeriod, 0, 'f', 2));
|
||
updateThreadInfoValue(threadIndex, 10, QString("%1 ms").arg(data.m_SetPeriod, 0, 'f', 2));
|
||
updateThreadInfoValue(threadIndex, 11, QString("%1 ms").arg(data.m_MaxPeriod, 0, 'f', 2));
|
||
updateThreadInfoValue(threadIndex, 12, QString("%1 ms").arg(data.m_AvgPeriod, 0, 'f', 2));
|
||
}
|
||
}
|
||
|
||
// 更新线程信息值
|
||
void ModelStatusWidget::updateThreadInfoValue(unsigned int threadIndex, int index,
|
||
const QString &newValue)
|
||
{
|
||
if (currentTabIndex != 1)
|
||
return;
|
||
QLabel *valueLabel =
|
||
findChild<QLabel *>(QString("threadRunValueLabel%1_%2").arg(threadIndex).arg(index));
|
||
if (valueLabel) {
|
||
valueLabel->setText(newValue);
|
||
if (1 == index) {
|
||
if (newValue == "未运行") {
|
||
valueLabel->setStyleSheet("color: gray;");
|
||
} else if (newValue == "运行中") {
|
||
valueLabel->setStyleSheet("color: green;");
|
||
} else if (newValue == "暂停中") {
|
||
valueLabel->setStyleSheet("color: orange;");
|
||
} else if (newValue == "错误") {
|
||
valueLabel->setStyleSheet("color: red;");
|
||
} else {
|
||
valueLabel->setText("未知状态");
|
||
valueLabel->setStyleSheet("color: red;");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 更新图表数据
|
||
void ModelStatusWidget::updatePlotData(const QVector<double> &newXData,
|
||
const QVector<double> &newYData)
|
||
{
|
||
XNCustomPlot *customPlot = nullptr;
|
||
if (currentTabIndex == 1)
|
||
customPlot = findChild<XNCustomPlot *>("modelStatusCustomPlot");
|
||
else if (currentTabIndex == 2)
|
||
customPlot = findChild<XNCustomPlot *>("dataMonitoringCustomPlot");
|
||
else
|
||
return;
|
||
|
||
if (!customPlot)
|
||
return; // 确保找到了XNCustomPlot对象
|
||
if (customPlot->graphCount() == 1) {
|
||
// 假设我们只有一个图形
|
||
customPlot->graph(0)->setData(newXData, newYData);
|
||
customPlot->replot(); // 重新绘制图表以显示新数据
|
||
} else {
|
||
customPlot->addGraph(); // 添加一个新的图形
|
||
customPlot->graph(0)->setData(newXData, newYData);
|
||
customPlot->replot(); // 重新绘制图表以显示新数据
|
||
}
|
||
}
|
||
|
||
// 更新模型数据
|
||
void ModelStatusWidget::updateModelData(const XNRuntimeData &data)
|
||
{
|
||
// 如果当前标签页不是第二个,则直接返回
|
||
if (currentTabIndex != 1)
|
||
return;
|
||
|
||
// 遍历 modelDataVec 向量
|
||
for (size_t i = 0; i < modelDataVec.size(); i++) {
|
||
// 如果当前遍历到的元素 ID 与传入数据的 ID 相同
|
||
if (data.m_id == modelDataVec[i].m_id) {
|
||
double currectFrequency = data.m_CurrentFrequency[0]; // 当前频率
|
||
double currentPeriod = data.m_CurrentPeriod[0]; // 当前周期
|
||
// 更新模型运行状态
|
||
modelDataVec[i].m_RunningState = data.m_RunningState;
|
||
// 如果模型不是运行状态,则不更新频率和周期数据
|
||
if (data.m_RunningState != 1)
|
||
return;
|
||
// 更新当前频率
|
||
modelDataVec[i].m_CurrentFrequency.push_back(currectFrequency);
|
||
// 更新当前周期
|
||
modelDataVec[i].m_CurrentPeriod.push_back(currentPeriod);
|
||
// 更新周期计数
|
||
modelDataVec[i].m_CycleCount = data.m_CycleCount;
|
||
// 更新最小频率
|
||
modelDataVec[i].m_MinFrequency =
|
||
std::min(currectFrequency, modelDataVec[i].m_MinFrequency);
|
||
// 更新最大频率
|
||
modelDataVec[i].m_MaxFrequency =
|
||
std::max(currectFrequency, modelDataVec[i].m_MaxFrequency);
|
||
// 更新平均频率
|
||
modelDataVec[i].m_AvgFrequency =
|
||
((data.m_CycleCount - 1) * modelDataVec[i].m_AvgFrequency + currectFrequency)
|
||
/ data.m_CycleCount;
|
||
// 更新最小周期
|
||
modelDataVec[i].m_MinPeriod = std::min(currentPeriod, modelDataVec[i].m_MinPeriod);
|
||
// 更新最大周期
|
||
modelDataVec[i].m_MaxPeriod = std::max(currentPeriod, modelDataVec[i].m_MaxPeriod);
|
||
// 更新平均周期
|
||
modelDataVec[i].m_AvgPeriod =
|
||
((data.m_CycleCount - 1) * modelDataVec[i].m_AvgPeriod + currentPeriod)
|
||
/ data.m_CycleCount;
|
||
|
||
// 如果当前频率或周期向量的长度超过100,移除最前面的元素
|
||
if (modelDataVec[i].m_CurrentFrequency.size() > 100) {
|
||
modelDataVec[i].m_CurrentFrequency.pop_front();
|
||
modelDataVec[i].m_CurrentPeriod.pop_front();
|
||
}
|
||
|
||
// 检查当前选中的行是否是被更新的行
|
||
// 找到名为 "modelStatusTableWidget" 的子控件
|
||
QTableWidget *modelStatusTableWidget =
|
||
findChild<QTableWidget *>("modelStatusTableWidget");
|
||
if (modelStatusTableWidget) {
|
||
int currentRow = modelStatusTableWidget->currentRow();
|
||
if (currentRow == static_cast<int>(i)) {
|
||
emit updateModelCutomPlotData();
|
||
}
|
||
}
|
||
|
||
// 更新表格数据
|
||
updateModelTableData(modelDataVec[i], i);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 如果未找到匹配的 ID,将传入的数据添加到 modelDataVec 向量末尾
|
||
modelDataVec.push_back(data);
|
||
// 更新表格数据
|
||
updateModelTableData(data, modelDataVec.size() - 1);
|
||
}
|
||
|
||
// 更新模型表格数据
|
||
void ModelStatusWidget::updateModelTableData(const XNRuntimeData &data, int rowIndex)
|
||
{
|
||
// 如果当前标签页索引不为1,则直接返回
|
||
if (currentTabIndex != 1)
|
||
return;
|
||
|
||
// 查找名为"threadStatusTableWidget"的QTableWidget
|
||
QTableWidget *modelStatusTableWidget = findChild<QTableWidget *>("modelStatusTableWidget");
|
||
if (!modelStatusTableWidget) {
|
||
// 如果没有找到,则直接返回
|
||
return;
|
||
}
|
||
|
||
// 设置表格的行数
|
||
modelStatusTableWidget->setRowCount(std::max(rowIndex + 1, (int)modelDataVec.size()));
|
||
|
||
// 设置模型名称
|
||
modelStatusTableWidget->setItem(rowIndex, 0, new QTableWidgetItem(data.m_name));
|
||
|
||
// 设置模型ID
|
||
modelStatusTableWidget->setItem(rowIndex, 1, new QTableWidgetItem(QString::number(data.m_id)));
|
||
|
||
// 根据模型的运行状态设置不同的状态显示
|
||
switch (data.m_RunningState) {
|
||
case 0:
|
||
// 未运行状态
|
||
modelStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("未运行"));
|
||
modelStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::gray));
|
||
break;
|
||
case 1:
|
||
// 运行中状态
|
||
modelStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("运行中"));
|
||
modelStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::green));
|
||
break;
|
||
case 2:
|
||
// 暂停中状态
|
||
modelStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("暂停中"));
|
||
modelStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::yellow));
|
||
break;
|
||
default:
|
||
// 未知状态
|
||
modelStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("未知状态"));
|
||
modelStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::red));
|
||
break;
|
||
}
|
||
|
||
// 设置所属线程
|
||
if (systemStatusWidget != nullptr) {
|
||
modelStatusTableWidget->setItem(
|
||
rowIndex, 3,
|
||
new QTableWidgetItem(systemStatusWidget->getThreadName(data.m_AffinityMask)));
|
||
} else {
|
||
modelStatusTableWidget->setItem(rowIndex, 3, new QTableWidgetItem("未知线程"));
|
||
}
|
||
|
||
// 设置节点号
|
||
modelStatusTableWidget->setItem(rowIndex, 4,
|
||
new QTableWidgetItem(QString::number(data.m_NodeID)));
|
||
|
||
// 设置模型优先级
|
||
modelStatusTableWidget->setItem(rowIndex, 5,
|
||
new QTableWidgetItem(QString::number(data.m_Priority)));
|
||
|
||
// 设置模型设置频率
|
||
modelStatusTableWidget->setItem(
|
||
rowIndex, 6, new QTableWidgetItem(QString::number(data.m_SetFrequency, 'f', 2) + " Hz"));
|
||
|
||
// 设置模型最小频率
|
||
modelStatusTableWidget->setItem(
|
||
rowIndex, 7, new QTableWidgetItem(QString::number(data.m_MinFrequency, 'f', 2) + " Hz"));
|
||
|
||
// 设置模型最大频率
|
||
modelStatusTableWidget->setItem(
|
||
rowIndex, 8, new QTableWidgetItem(QString::number(data.m_MaxFrequency, 'f', 2) + " Hz"));
|
||
|
||
// 设置模型平均频率
|
||
modelStatusTableWidget->setItem(
|
||
rowIndex, 9, new QTableWidgetItem(QString::number(data.m_AvgFrequency, 'f', 2) + " Hz"));
|
||
|
||
// 设置模型周期计数
|
||
modelStatusTableWidget->setItem(rowIndex, 10,
|
||
new QTableWidgetItem(QString::number(data.m_CycleCount)));
|
||
|
||
// 设置模型设置周期
|
||
modelStatusTableWidget->setItem(
|
||
rowIndex, 11, new QTableWidgetItem(QString::number(data.m_SetPeriod, 'f', 2) + " ms"));
|
||
|
||
// 设置模型最小周期
|
||
modelStatusTableWidget->setItem(
|
||
rowIndex, 12, new QTableWidgetItem(QString::number(data.m_MinPeriod, 'f', 2) + " ms"));
|
||
|
||
// 设置模型最大周期
|
||
modelStatusTableWidget->setItem(
|
||
rowIndex, 13, new QTableWidgetItem(QString::number(data.m_MaxPeriod, 'f', 2) + " ms"));
|
||
|
||
// 设置模型平均周期
|
||
modelStatusTableWidget->setItem(
|
||
rowIndex, 14, new QTableWidgetItem(QString::number(data.m_AvgPeriod, 'f', 2) + " ms"));
|
||
}
|
||
|
||
// 提取字符串末尾的数字
|
||
int ModelStatusWidget::extractTrailingNumbers(const QString &str, int count)
|
||
{
|
||
QRegularExpression re("\\d{1," + QString::number(count) + "}$");
|
||
QRegularExpressionMatch match = re.match(str);
|
||
if (match.hasMatch()) {
|
||
return match.captured().toInt();
|
||
} else {
|
||
return -1; // 如果没有找到匹配项,则返回一个-1
|
||
}
|
||
}
|