XNSim/XNMonitor/SystemStatusWidget/SystemStatusWidget.cpp

796 lines
28 KiB
C++
Raw Permalink Normal View History

2025-04-28 12:25:20 +08:00
/**
* @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("未知线程");
}