XNSim/XNMonitor/SystemStatusWidget/SystemStatusWidget.cpp
2025-04-28 12:25:20 +08:00

796 lines
28 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file SystemStatusWidget.cpp
* @author jinchao
* @brief 系统运行状态窗口类实现
* @version 1.0
* @date 2025-03-10
*
* @copyright Copyright (c) 2025 COMAC
*
*/
#include "SystemStatusWidget.h"
#include <QHBoxLayout>
#include <QSplitter>
#include <QList>
#include <QPushButton>
#include <QScrollArea>
#include <QGridLayout>
#include <QLabel>
#include <QVBoxLayout>
#include <QHeaderView>
#include <QTableWidget>
#include <QAbstractItemView>
#include <QFont>
#include <QMutexLocker>
SystemStatusWidget::SystemStatusWidget(QWidget *parent)
: QWidget(parent), engineInfoPage(nullptr), coreInfoPage(nullptr),
threadStatusTableWidget(nullptr), systemStatusChartWidget(nullptr), customPlot(nullptr),
currentTabIndex(0), freqOrPeriodIndex(0), labelXNEngine(nullptr),
labelProcessIDValue(nullptr), labelStatusValue(nullptr), labelAffinityValue(nullptr),
labelThreadCountValue(nullptr), threadInfoThread(nullptr)
{
// 初始化系统状态窗口
setupTabSystemStatus();
// 初始化线程信息更新线程
InitializeThreadInfoThread();
}
SystemStatusWidget::~SystemStatusWidget()
{
if (threadInfoThread != nullptr) {
// 断开所有信号槽连接
disconnect(threadInfoThread, nullptr, this, nullptr);
disconnect(this, nullptr, threadInfoThread, nullptr);
// 发送退出信号并等待线程结束
threadInfoThread->onThreadQuit();
threadInfoThread->quit();
threadInfoThread->wait();
}
}
void SystemStatusWidget::onSetCurrentTabIndex(int index)
{
// 设置当前选中的标签页索引
this->currentTabIndex = index;
if (currentTabIndex == 0) {
// 如果当前选中的标签页索引为0则显示系统运行状态窗口并控制线程信息更新线程
this->show();
emit controlThreadInfoThread(true);
} else if (currentTabIndex == 1) {
// 如果当前选中的标签页索引为1则隐藏系统运行状态窗口并控制线程信息更新线程
this->hide();
emit controlThreadInfoThread(true);
} else {
// 如果当前选中的标签页索引为其他,则隐藏系统运行状态窗口,并控制线程信息更新线程
this->hide();
emit controlThreadInfoThread(false);
}
}
void SystemStatusWidget::InitializeThreadInfoThread()
{
// 初始化线程信息更新线程
threadInfoThread = new SystemInfoUpdateThread(this);
// 连接线程信息更新线程的信号和槽函数
connect(threadInfoThread, &SystemInfoUpdateThread::updateThreadInfo, this,
&SystemStatusWidget::updateThreadData);
connect(threadInfoThread, &SystemInfoUpdateThread::updateEngineName, this,
&SystemStatusWidget::updateProcessName);
connect(threadInfoThread, &SystemInfoUpdateThread::updateEngineID, this,
&SystemStatusWidget::updateProcessID);
connect(threadInfoThread, &SystemInfoUpdateThread::updateEngineStatus, this,
&SystemStatusWidget::updateEngineStatus);
connect(threadInfoThread, &SystemInfoUpdateThread::updateCoreStatus, this,
&SystemStatusWidget::updateCoreStatus);
connect(threadInfoThread, &SystemInfoUpdateThread::updateThreadCount, this,
&SystemStatusWidget::updateThreadCount);
connect(threadInfoThread, &SystemInfoUpdateThread::updateAffinity, this,
&SystemStatusWidget::updateAffinity);
connect(this, &SystemStatusWidget::controlThreadInfoThread, threadInfoThread,
&SystemInfoUpdateThread::onThreadController);
// 初始化线程信息更新线程
threadInfoThread->Initialize();
// 启动线程信息更新线程
threadInfoThread->start();
}
// 设置 tabSystemStatus 的布局和组件
void SystemStatusWidget::setupTabSystemStatus()
{
QHBoxLayout *mainLayout = new QHBoxLayout(this); // 创建水平布局
// 使用QSplitter进行左右栏的动态分割
QSplitter *horizontalSplitter =
new QSplitter(Qt::Horizontal, this); // 创建一个水平方向的QSplitter
// 左栏布局
setupTabSystemStatusLeftPanel(horizontalSplitter);
// 右栏布局
setupTabSystemStatusRightPanel(horizontalSplitter);
// 设置QSplitter的初始分割比例为1:4即左栏占五分之一右栏占五分之四
QList<int> sizes;
sizes << 1 << 4;
horizontalSplitter->setSizes(sizes);
// 将QSplitter添加到主布局中
mainLayout->addWidget(horizontalSplitter);
}
//设置 tabSystemStatus 左栏的布局和组件
void SystemStatusWidget::setupTabSystemStatusLeftPanel(QSplitter *splitter)
{
// 左栏布局
QVBoxLayout *leftLayout = new QVBoxLayout();
// 创建引擎信息的 QStackedWidget 和按钮
// 创建引擎信息的按钮
QPushButton *engineInfoButton = new QPushButton("引擎信息", this);
leftLayout->addWidget(engineInfoButton);
// 创建或获取 "引擎信息" 页面的 widget
engineInfoPage = createEngineInfoPage();
leftLayout->addWidget(engineInfoPage);
// 创建内核信息的 QStackedWidget 和按钮
// 创建内核信息的按钮
QPushButton *coreInfoButton = new QPushButton("内核信息", this);
leftLayout->addWidget(coreInfoButton);
// 创建或获取 "内核信息" 页面的 widget
coreInfoPage = createCoreInfoPage();
leftLayout->addWidget(coreInfoPage);
// 连接按钮的 clicked 信号到槽函数
connect(engineInfoButton, &QPushButton::clicked, this, &SystemStatusWidget::toggleEngineInfo);
connect(coreInfoButton, &QPushButton::clicked, this, &SystemStatusWidget::toggleCoreInfo);
leftLayout->addStretch(); // 添加一个伸展项,使得布局可以自动调整大小
// 创建一个QWidget作为左栏的容器并设置其布局为leftLayout
QWidget *leftPanel = new QWidget(this);
leftPanel->setLayout(leftLayout);
// 创建一个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);
}
// 创建包含 QLabel 的引擎信息页面
QWidget *SystemStatusWidget::createEngineInfoPage()
{
QWidget *page = new QWidget(this);
QGridLayout *gridLayout = new QGridLayout(page);
// 创建 QLabel 并设置文本和对齐方式
QLabel *labelProcessName = new QLabel("进程名称", page); // 进程名称标签
labelXNEngine = new QLabel("XNEngine", page); // XNEngine标签
QLabel *labelProcessID = new QLabel("进程ID", page); // 进程ID标签
labelProcessIDValue = new QLabel("0000", page); // 进程ID值标签
QLabel *labelStatus = new QLabel("运行状态", page); // 运行状态标签
labelStatusValue = new QLabel("未运行", page); // 运行状态值标签
QLabel *labelAffinity = new QLabel("CPU亲和性", page); // CPU亲和性标签
labelAffinityValue = new QLabel("0", page); // CPU亲和性值标签
QLabel *labelThreadCount = new QLabel("线程数", page); // 线程数标签
labelThreadCountValue = new QLabel("0", page); // 线程数值标签
// 设置第一列 QLabel 左对齐
labelProcessName->setAlignment(Qt::AlignLeft); // 进程名称标签左对齐
labelProcessID->setAlignment(Qt::AlignLeft); // 进程ID标签左对齐
labelStatus->setAlignment(Qt::AlignLeft); // 运行状态标签左对齐
labelAffinity->setAlignment(Qt::AlignLeft); // CPU亲和性标签左对齐
labelThreadCount->setAlignment(Qt::AlignLeft); // 线程数标签左对齐
// 设置第二列 QLabel 右对齐
labelXNEngine->setAlignment(Qt::AlignRight); // XNEngine标签右对齐
labelProcessIDValue->setAlignment(Qt::AlignRight); // 进程ID值标签右对齐
labelStatusValue->setAlignment(Qt::AlignRight); // 运行状态值标签右对齐
labelAffinityValue->setAlignment(Qt::AlignRight); // CPU亲和性值标签右对齐
labelThreadCountValue->setAlignment(Qt::AlignRight); // 线程数值标签右对齐
// 如果状态为 "未运行",则设置灰色文本
if (labelStatusValue->text() == "未运行") {
labelStatusValue->setStyleSheet("color: gray;"); // 设置灰色文本
}
// 将 QLabel 添加到网格布局中
gridLayout->addWidget(labelProcessName, 0, 0); // 将进程名称标签添加到网格布局中位于第0行第0列
gridLayout->addWidget(labelXNEngine, 0, 1); // 将XNEngine标签添加到网格布局中位于第0行第1列
gridLayout->addWidget(labelProcessID, 1, 0); // 将进程ID标签添加到网格布局中位于第1行第0列
gridLayout->addWidget(labelProcessIDValue, 1,
1); // 将进程ID值标签添加到网格布局中位于第1行第1列
gridLayout->addWidget(labelStatus, 2, 0); // 将运行状态标签添加到网格布局中位于第2行第0列
gridLayout->addWidget(labelStatusValue, 2,
1); // 将运行状态值标签添加到网格布局中位于第2行第1列
gridLayout->addWidget(labelAffinity, 3, 0); // 将CPU亲和性标签添加到网格布局中位于第3行第0列
gridLayout->addWidget(labelAffinityValue, 3,
1); // 将CPU亲和性值标签添加到网格布局中位于第3行第1列
gridLayout->addWidget(labelThreadCount, 4, 0); // 将线程数标签添加到网格布局中位于第4行第0列
gridLayout->addWidget(labelThreadCountValue, 4,
1); // 将线程数值标签添加到网格布局中位于第4行第1列
return page;
}
// 创建包含 QLabel 的内核信息页面
QWidget *SystemStatusWidget::createCoreInfoPage()
{
QWidget *page = new QWidget(this);
QGridLayout *gridLayout = new QGridLayout(page);
// 定义管理器名称和状态
// 定义管理器名称列表
const QStringList managerNames = {"主框架", "时间管理器", "事件管理器", "场景描述管理器",
"线程管理器", "模型管理器", "服务管理器", "DDS管理器"};
const QString initialStatus = "未加载";
// 遍历管理器名称列表为每个管理器创建两个QLabel
for (int i = 0; i < managerNames.size(); ++i) {
QLabel *managerLabel = new QLabel(managerNames[i], page);
QLabel *statusLabel = new QLabel(initialStatus, page);
// 设置QLabel的对齐方式
// 设置管理器名称标签左对齐
managerLabel->setAlignment(Qt::AlignLeft);
// 设置状态标签右对齐
statusLabel->setAlignment(Qt::AlignRight);
// 设置状态标签的初始文本颜色为灰色
statusLabel->setStyleSheet("color: gray;");
// 设置状态标签的objectName以便后续可以通过findChild找到它们
statusLabel->setObjectName(QString("coreStatusLabel%1").arg(i));
// 将QLabel添加到网格布局中
// 第一列放置管理器名称
gridLayout->addWidget(managerLabel, i, 0);
// 第二列放置状态
gridLayout->addWidget(statusLabel, i, 1);
}
return page;
}
// 切换引擎信息的显示状态
void SystemStatusWidget::toggleEngineInfo()
{
if (engineInfoPage == nullptr)
return;
engineInfoPage->setVisible(!engineInfoPage->isVisible());
}
// 切换内核信息的显示状态
void SystemStatusWidget::toggleCoreInfo()
{
if (coreInfoPage == nullptr)
return;
coreInfoPage->setVisible(!coreInfoPage->isVisible());
}
//设置 tabSystemStatus 右栏的布局和组件
void SystemStatusWidget::setupTabSystemStatusRightPanel(QSplitter *splitter)
{
// 右栏布局
QVBoxLayout *rightLayout = new QVBoxLayout();
// 创建一个新的QSplitter用于垂直分割右栏的上下两部分
QSplitter *verticalSplitter = new QSplitter(Qt::Vertical, this); // 垂直方向的QSplitter
// 表格布局
setupSystemStatusTableWidget();
// 图表绘制区域
setupSystemStatusChartWidget();
// 将表格和图表添加到垂直分割器中
if (threadStatusTableWidget != nullptr) {
verticalSplitter->addWidget(threadStatusTableWidget);
}
if (systemStatusChartWidget != nullptr) {
verticalSplitter->addWidget(systemStatusChartWidget);
}
QList<int> sizes;
sizes << 3 << 2;
verticalSplitter->setSizes(sizes);
// 将垂直分割器添加到右栏布局中
rightLayout->addWidget(verticalSplitter);
// 创建一个QWidget作为右栏的容器并设置其布局为rightLayout
QWidget *rightPanel = new QWidget(this);
rightPanel->setLayout(rightLayout);
// 将右栏容器添加到QSplitter中
splitter->addWidget(rightPanel);
}
// 设置线程运行状态表格
void SystemStatusWidget::setupSystemStatusTableWidget()
{
threadStatusTableWidget = new QTableWidget(this);
threadStatusTableWidget->setRowCount(10); // 设置表格的行数
threadStatusTableWidget->setColumnCount(14); // 设置表格的列数
QFont headerFont("Arial", 16, QFont::Bold);
threadStatusTableWidget->horizontalHeader()->setFont(headerFont);
// 设置表格的列标题
threadStatusTableWidget->setHorizontalHeaderLabels(
{"线程名称", "线程ID", "运行状态", "CPU亲和性", "优先级", "设定频率", "最小频率",
"最大频率", "平均频率", "周期数", "设定周期", "最小周期", "最大周期", "平均周期"});
// 设置表格列宽自适应
threadStatusTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
// 设置表格的选择行为为按行选择
threadStatusTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
// 设置表格的选择模式为单选
threadStatusTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
// 设置表格不可编辑
threadStatusTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
// 连接 threadStatusTableWidget 的 itemSelectionChanged 信号到槽函数
connect(threadStatusTableWidget, &QTableWidget::itemSelectionChanged, this,
&SystemStatusWidget::onThreadStatusTableSelectionChanged);
}
// 处理线程状态表格的选择变化
void SystemStatusWidget::onThreadStatusTableSelectionChanged()
{
if (currentTabIndex != 0)
return;
if (threadStatusTableWidget == nullptr) {
return;
}
QVector<double> xData, yData;
{
// 加锁,保护线程数据,用花括号包裹限制锁的作用域
QMutexLocker locker(&mutex);
// 获取当前选中的行索引
int rowIndex = threadStatusTableWidget->currentRow();
// 如果行索引小于0或大于线程数据向量的大小则返回
if (rowIndex < 0 || rowIndex >= threadDataVec.size()) {
return;
}
// 如果图表绘图对象为空,则返回
if (customPlot == nullptr)
return; // 确保找到了XNCustomPlot对象
// 获取当前选中的行索引对应的线程数据
const XNRuntimeData &data = threadDataVec[rowIndex];
if (freqOrPeriodIndex == 0 && data.m_CurrentPeriod.size() > 0) {
// 如果显示周期则设置图表的x轴和y轴范围
customPlot->xAxis->setRange(0, data.m_CurrentPeriod.size());
customPlot->yAxis->setRange(data.m_MinPeriod - 1, data.m_MaxPeriod + 1);
// 遍历当前周期的数据并将其添加到x轴和y轴的数据向量中
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) {
// 如果显示频率则设置图表的x轴和y轴范围
customPlot->xAxis->setRange(0, data.m_CurrentFrequency.size());
customPlot->yAxis->setRange(data.m_MinFrequency - 1, data.m_MaxFrequency + 1);
// 遍历当前频率的数据并将其添加到x轴和y轴的数据向量中
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 SystemStatusWidget::setupSystemStatusChartWidget()
{
// 创建一个QWidget作为图表的容器
systemStatusChartWidget = new QWidget(this);
// 创建一个XNCustomPlot对象并将其添加到图表容器中
customPlot = new XNCustomPlot(systemStatusChartWidget);
// 设置图表布局
systemStatusChartWidget->setLayout(new QVBoxLayout());
// 将XNCustomPlot对象添加到图表容器中
systemStatusChartWidget->layout()->addWidget(customPlot);
// 配置图表
customPlot->setBackground(QBrush(QColor("#19232D"))); // 设置图表的背景颜色
customPlot->xAxis->setLabelColor(Qt::white); // 设置x轴标签的颜色
customPlot->yAxis->setLabelColor(Qt::white); // 设置y轴标签的颜色
customPlot->xAxis->setLabel("时间(s)"); // 设置x轴标签
customPlot->yAxis->setLabel("周期(ms)"); // 设置y轴标签
customPlot->xAxis->setTickLabelRotation(60); // 设置x轴标签的旋转角度
customPlot->xAxis->setTickLabelColor(Qt::white); // 设置x轴标签的颜色
customPlot->yAxis->setTickLabelColor(Qt::white); // 设置y轴标签的颜色
customPlot->xAxis->grid()->setVisible(true); // 设置x轴网格线
customPlot->yAxis->grid()->setVisible(true); // 设置y轴网格线
// 添加图表并设置绿色
customPlot->addGraph();
QPen greenPen(Qt::green); // 设置绿色笔
greenPen.setWidth(2); // 设置笔宽
customPlot->graph(0)->setPen(greenPen); // 设置图表的笔
// 为chartWidget设置上下文菜单
connect(customPlot, &XNCustomPlot::customContextMenuRequested, this,
&SystemStatusWidget::showChartContextMenu);
// 连接信号
connect(this, &SystemStatusWidget::updateThreadCutomPlotData, this,
&SystemStatusWidget::onThreadStatusTableSelectionChanged, Qt::QueuedConnection);
customPlot->replot();
}
// 处理图表中的右键点击事件
void SystemStatusWidget::showChartContextMenu(const QPoint &pos)
{
if (customPlot == nullptr)
return; // 确保找到了XNCustomPlot对象
QMenu contextMenu(this);
QAction *actionFrequency = contextMenu.addAction("显示频率");
QAction *actionPeriod = contextMenu.addAction("显示周期");
// 连接QAction的triggered信号到相应的槽函数
connect(actionFrequency, &QAction::triggered, this, &SystemStatusWidget::onShowFrequency);
connect(actionPeriod, &QAction::triggered, this, &SystemStatusWidget::onShowPeriod);
// 在chartWidget上显示上下文菜单
QAction *selectedAction = contextMenu.exec(customPlot->mapToGlobal(pos));
}
// 处理右键菜单中的"显示频率"选项
void SystemStatusWidget::onShowFrequency()
{
if (currentTabIndex != 0)
return;
if (customPlot == nullptr)
return; // 确保找到了XNCustomPlot对象
// 实现显示频率的逻辑
customPlot->yAxis->setLabel("频率(Hz)");
freqOrPeriodIndex = 1;
customPlot->replot(); // 重新绘制图表以显示新数据
emit updateThreadCutomPlotData();
}
// 处理右键菜单中的"显示周期"选项
void SystemStatusWidget::onShowPeriod()
{
if (currentTabIndex != 0)
return;
if (customPlot == nullptr)
return; // 确保找到了XNCustomPlot对象
// 实现显示周期的逻辑
customPlot->yAxis->setLabel("周期(ms)");
freqOrPeriodIndex = 0;
customPlot->replot(); // 重新绘制图表以显示新数据
emit updateThreadCutomPlotData();
}
// 更新进程名称
void SystemStatusWidget::updateProcessName(const QString &name)
{
if (currentTabIndex != 0)
return;
if (labelXNEngine != nullptr) {
labelXNEngine->setText(name);
}
}
// 更新进程ID
void SystemStatusWidget::updateProcessID(const unsigned int &id)
{
if (currentTabIndex != 0)
return;
if (labelProcessIDValue != nullptr) {
labelProcessIDValue->setText(QString::number(id));
}
}
// 更新引擎状态
void SystemStatusWidget::updateEngineStatus(const unsigned int &status)
{
if (currentTabIndex != 0)
return;
if (labelStatusValue != nullptr) {
switch (status) {
case 0:
labelStatusValue->setText("未运行");
labelStatusValue->setStyleSheet("color: gray;");
break;
case 1:
labelStatusValue->setText("运行中");
labelStatusValue->setStyleSheet("color: green;");
break;
case 2:
labelStatusValue->setText("暂停中");
labelStatusValue->setStyleSheet("color: orange;");
break;
case 3:
labelStatusValue->setText("错误");
labelStatusValue->setStyleSheet("color: red;");
break;
default:
labelStatusValue->setText("未知状态");
labelStatusValue->setStyleSheet("color: red;");
break;
}
}
}
// 更新内核状态
void SystemStatusWidget::updateCoreStatus(int index, const unsigned int &status)
{
if (currentTabIndex != 0)
return;
QLabel *statusLabel = findChild<QLabel *>(QString("coreStatusLabel%1").arg(index));
if (statusLabel) {
switch (status) {
case 0:
statusLabel->setText("未加载");
statusLabel->setStyleSheet("color: gray;");
break;
case 1:
statusLabel->setText("初始化完成");
statusLabel->setStyleSheet("color: orange;");
break;
case 2:
statusLabel->setText("正常");
statusLabel->setStyleSheet("color: green;");
break;
case 3:
statusLabel->setText("异常");
statusLabel->setStyleSheet("color: red;");
break;
default:
statusLabel->setText("未知状态");
statusLabel->setStyleSheet("color: yellow;"); // 默认颜色或其他状态的颜色设置
}
}
}
// 更新线程数据
void SystemStatusWidget::updateThreadData(const XNRuntimeData &data)
{
// 如果当前标签页不是第一个或第二个,则直接返回
if (currentTabIndex != 0 && currentTabIndex != 1)
return;
QMutexLocker locker(&mutex);
// 遍历 threadDataVec 向量
for (size_t i = 0; i < threadDataVec.size(); i++) {
// 如果当前遍历到的元素 ID 与传入数据的 ID 相同
if (data.m_id == threadDataVec[i].m_id) {
double currectFrequency = data.m_CurrentFrequency[0]; // 当前频率
double currentPeriod = data.m_CurrentPeriod[0]; // 当前周期
// 更新线程运行状态
threadDataVec[i].m_RunningState = data.m_RunningState;
// 如果线程不是运行状态,则不更新频率和周期数据
if (data.m_RunningState == 1) {
// 更新当前频率
threadDataVec[i].m_CurrentFrequency.push_back(currectFrequency);
// 更新当前周期
threadDataVec[i].m_CurrentPeriod.push_back(currentPeriod);
// 更新周期计数
threadDataVec[i].m_CycleCount = data.m_CycleCount;
// 更新最小频率
threadDataVec[i].m_MinFrequency =
std::min(currectFrequency, threadDataVec[i].m_MinFrequency);
// 更新最大频率
threadDataVec[i].m_MaxFrequency =
std::max(currectFrequency, threadDataVec[i].m_MaxFrequency);
// 更新平均频率
threadDataVec[i].m_AvgFrequency =
((data.m_CycleCount - 1) * threadDataVec[i].m_AvgFrequency + currectFrequency)
/ data.m_CycleCount;
// 更新最小周期
threadDataVec[i].m_MinPeriod =
std::min(currentPeriod, threadDataVec[i].m_MinPeriod);
// 更新最大周期
threadDataVec[i].m_MaxPeriod =
std::max(currentPeriod, threadDataVec[i].m_MaxPeriod);
// 更新平均周期
threadDataVec[i].m_AvgPeriod =
((data.m_CycleCount - 1) * threadDataVec[i].m_AvgPeriod + currentPeriod)
/ data.m_CycleCount;
// 如果当前频率或周期向量的长度超过100移除最前面的元素
if (threadDataVec[i].m_CurrentFrequency.size() > 100) {
threadDataVec[i].m_CurrentFrequency.pop_front();
threadDataVec[i].m_CurrentPeriod.pop_front();
}
}
// 检查当前选中的行是否是被更新的行
if (currentTabIndex == 0) {
if (threadStatusTableWidget != nullptr) {
int currentRow = threadStatusTableWidget->currentRow();
if (currentRow == static_cast<int>(i)) {
emit updateThreadCutomPlotData();
}
}
// 更新表格数据
updateThreadTableData(threadDataVec[i], i);
} else if (currentTabIndex == 1) {
emit updateThreadInfo(i, threadDataVec[i]);
}
return;
}
}
// 如果未找到匹配的 ID将传入的数据添加到 threadDataVec 向量末尾
threadDataVec.push_back(data);
// 更新表格数据
if (currentTabIndex == 0) {
updateThreadTableData(data, threadDataVec.size() - 1);
} else if (currentTabIndex == 1) {
emit updateThreadInfo(threadDataVec.size() - 1, data);
}
}
// 更新线程数
void SystemStatusWidget::updateThreadCount(const unsigned int &count)
{
// 如果当前标签页索引不为0则直接返回
if (currentTabIndex != 0)
return;
if (labelThreadCountValue != nullptr) {
labelThreadCountValue->setText(QString::number(count));
}
}
// 更新CPU亲和性
void SystemStatusWidget::updateAffinity(const QString &affinity)
{
// 如果当前标签页索引不为0则直接返回
if (currentTabIndex != 0)
return;
if (labelAffinityValue != nullptr) {
labelAffinityValue->setText(affinity);
}
}
// 更新线程表格数据
void SystemStatusWidget::updateThreadTableData(const XNRuntimeData &data, int rowIndex)
{
// 如果当前标签页索引不为0则直接返回
if (currentTabIndex != 0)
return;
// 查找threadStatusTableWidget
if (threadStatusTableWidget == nullptr) {
// 如果没有找到,则直接返回
return;
}
// 设置表格的行数
threadStatusTableWidget->setRowCount(std::max(rowIndex + 1, (int)threadDataVec.size()));
// 设置线程名称
threadStatusTableWidget->setItem(rowIndex, 0, new QTableWidgetItem(data.m_name));
// 设置线程ID
threadStatusTableWidget->setItem(rowIndex, 1, new QTableWidgetItem(QString::number(data.m_id)));
// 根据线程的运行状态设置不同的状态显示
switch (data.m_RunningState) {
case 0:
// 未运行状态
threadStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("未运行"));
threadStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::gray));
break;
case 1:
// 运行中状态
threadStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("运行中"));
threadStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::green));
break;
case 2:
// 暂停中状态
threadStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("暂停中"));
threadStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::yellow));
break;
default:
// 未知状态
threadStatusTableWidget->setItem(rowIndex, 2, new QTableWidgetItem("未知状态"));
threadStatusTableWidget->item(rowIndex, 2)->setForeground(QBrush(Qt::red));
break;
}
// 初始化affinity字符串
QString affinity = "";
for (int i = 0; i < 32; i++) {
// 如果线程亲和性掩码对应位为1则添加该位的索引到affinity字符串中
if (data.m_AffinityMask & (1 << i)) {
affinity += QString::number(i) + " ";
}
}
// 设置affinity
threadStatusTableWidget->setItem(rowIndex, 3, new QTableWidgetItem(affinity));
// 设置线程优先级
threadStatusTableWidget->setItem(rowIndex, 4,
new QTableWidgetItem(QString::number(data.m_Priority)));
// 设置线程设置频率
threadStatusTableWidget->setItem(
rowIndex, 5, new QTableWidgetItem(QString::number(data.m_SetFrequency, 'f', 2) + " Hz"));
// 设置线程最小频率
threadStatusTableWidget->setItem(
rowIndex, 6, new QTableWidgetItem(QString::number(data.m_MinFrequency, 'f', 2) + " Hz"));
// 设置线程最大频率
threadStatusTableWidget->setItem(
rowIndex, 7, new QTableWidgetItem(QString::number(data.m_MaxFrequency, 'f', 2) + " Hz"));
// 设置线程平均频率
threadStatusTableWidget->setItem(
rowIndex, 8, new QTableWidgetItem(QString::number(data.m_AvgFrequency, 'f', 2) + " Hz"));
// 设置线程周期计数
threadStatusTableWidget->setItem(rowIndex, 9,
new QTableWidgetItem(QString::number(data.m_CycleCount)));
// 设置线程设置周期
threadStatusTableWidget->setItem(
rowIndex, 10, new QTableWidgetItem(QString::number(data.m_SetPeriod, 'f', 2) + " ms"));
// 设置线程最小周期
threadStatusTableWidget->setItem(
rowIndex, 11, new QTableWidgetItem(QString::number(data.m_MinPeriod, 'f', 2) + " ms"));
// 设置线程最大周期
threadStatusTableWidget->setItem(
rowIndex, 12, new QTableWidgetItem(QString::number(data.m_MaxPeriod, 'f', 2) + " ms"));
// 设置线程平均周期
threadStatusTableWidget->setItem(
rowIndex, 13, new QTableWidgetItem(QString::number(data.m_AvgPeriod, 'f', 2) + " ms"));
}
// 更新图表数据
void SystemStatusWidget::updatePlotData(const QVector<double> &newXData,
const QVector<double> &newYData)
{
if (currentTabIndex != 0)
return;
if (customPlot == nullptr)
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(); // 重新绘制图表以显示新数据
}
}
QString SystemStatusWidget::getThreadName(const quint32 threadID)
{
QMutexLocker locker(&mutex);
// 遍历threadDataVec向量
for (int i = 0; i < threadDataVec.size(); i++) {
// 如果当前遍历到的元素的ID与传入的ID相同
if (threadID == threadDataVec[i].m_id) {
// 返回当前遍历到的元素的名称
return threadDataVec[i].m_name;
}
}
// 如果未找到匹配的ID则返回未知线程
return QString("未知线程");
}