从零到一:用Qt打造企业级《系统监控工具》[附完整源码]
欢迎来到【Qt开发宝典】微信公众号【知识宝库】!
本期《Qt C++工程师》动手实践系列,第051期。本期我们聚焦一个兼具实用性与学习深度的主题——《从零到一:用Qt打造企业级《系统监控工具》[附完整源码]》。本系列文章旨在为关注Qt跨平台开发、Linux C++后端及系统底层架构的开发者,提供一个系统的学习参考。内容将通过原理讲解与实战结合的方式,解析相关核心知识与设计思路,以期对您的技术探索与实践有所裨益。
【技术交流说明】
欢迎关注【Qt开发宝典】微信公众号,定期分享更多Linux C++/Qt等技术干货!
技术交流QQ群:895876809(纯技术讨论群)。入群即构成您对本协议及群规的最终确认。
你是否曾经想过,那些专业的系统监控工具是如何实现的?为什么它们能够实时捕捉系统的每一个细节,并以优雅的方式呈现给用户?
今天,我将带你走进一个真实的项目——内存性能安全卫士(Memory Monitor),一个功能完整、高性能的系统资源监控工具。通过这个项目,你将学到:
-
🎯如何用Qt构建跨平台应用:一套代码Windows、Linux、macOS三平台无缝运行
-
📊实时数据可视化的秘诀:波浪动画、图表展示、性能趋势分析
-
🚨智能告警机制的设计:多级别告警、防频繁触发、系统通知集成
-
💾数据持久化的最佳实践:SQLite数据库、历史数据查询、CSV导出
-
🔧系统编程的核心技能:Windows API、Linux /proc、macOS libproc
-
⚡性能优化的实战经验:帧率控制、内存管理、线程优化
-
🏆企业级功能的实现:性能基准测试、系统优化建议、健康度评分
一、【工程项目运行】
一、【工程项目运行】



二、【工程项目简介】
– ✅ 实时内存监控(物理内存 + 交换空间)
– ✅ CPU使用率监控(多核支持)
– ✅ 磁盘使用率监控(多分区支持)
– ✅ 网络速率监控(上行/下行)
– ✅ 进程监控(TOP 10内存/CPU进程)
【数据管理】
– ✅ SQLite数据库集成
– ✅ 历史数据保存(可配置保留天数)
– ✅ 数据查询和统计
– ✅ CSV格式导出
– ✅ 自动数据清理
【告警机制】
– ✅ 5种告警类型(内存、CPU、磁盘、交换空间、网络)
– ✅ 两级告警(警告/严重)
– ✅ 系统通知集成
– ✅ 告警历史记录
– ✅ 防止频繁告警
– ✅ 波浪动画帧率优化(自适应帧率控制)
– ✅ 内存泄漏检查和修复
– ✅ 数据更新优化(只在变化时更新UI)
– ✅ 线程优化(避免UI阻塞)
– ✅ 窗口几何信息保存
– ✅ 主题设置(深浅主题)
– ✅ 更新频率配置
– ✅ 告警阈值配置
– ✅ 数据保留天数设置
– ✅ 语言设置
【历史数据图表】
– ✅ 时间序列图表显示
– ✅ 多指标支持(内存、CPU、磁盘)
– ✅ 时间范围选择
– ✅ 图表导出功能
– ✅ 自动缩放和平移
三、【工程项目】部分源码
#ifndef ALERTMANAGER_H#define ALERTMANAGER_H#include<QString>#include<QObject>#include<QMap>#include<QVector>#include<QDateTime>#include<QMutex>#include"systeminfo.h"class AlertManager : public QObject {Q_OBJECTpublic:enum AlertLevel {INFO,WARNING,CRITICAL};enum AlertType {MEMORY_HIGH,CPU_HIGH,DISK_FULL,SWAP_HIGH,NETWORK_ANOMALY};struct AlertRecord {QDateTime timestamp;AlertType type;AlertLevel level;QString message;double value;};static AlertManager& instance();// 设置告警阈值voidsetThreshold(AlertType type, double warningValue, double criticalValue);// 检查并触发告警voidcheckMetrics(const SystemMetrics &metrics);// 启用/禁用告警voidsetAlertEnabled(AlertType type, bool enabled);// 获取告警历史QVector<AlertRecord> getAlertHistory(int count = 100);// 清空告警历史voidclearAlertHistory();// 获取当前告警状态QMap<AlertType, bool> getCurrentAlertStates()const;// 获取告警阈值QPair<double, double> getThreshold(AlertType type)const;signals:voidalertTriggered(AlertLevel level, const QString &message);voidalertResolved(AlertType type);private:AlertManager();~AlertManager();// 禁止拷贝AlertManager(const AlertManager&) = delete;AlertManager& operator=(const AlertManager&) = delete;// 触发告警voidtriggerAlert(AlertType type, AlertLevel level, const QString &message, double value);// 解除告警voidresolveAlert(AlertType type);// 发送系统通知voidsendSystemNotification(AlertLevel level, const QString &message);// 数据成员QMap<AlertType, QPair<double, double>> m_thresholds; // warning, criticalQMap<AlertType, bool> m_alertStates; // 当前告警状态QMap<AlertType, bool> m_alertEnabled; // 告警是否启用QVector<AlertRecord> m_alertHistory;QMutex m_mutex;// 防止频繁告警的时间戳QMap<AlertType, QDateTime> m_lastAlertTime;static const int ALERT_COOLDOWN_SECONDS = 60; // 60秒内不重复告警};#endif// ALERTMANAGER_H
#include"alertmanager.h"#include<QMutexLocker>#include<QDebug>#include<QDateTime>#ifdef Q_OS_WIN#include<windows.h>#elif defined(Q_OS_LINUX)#include<QProcess>#elif defined(Q_OS_MAC)#include<QProcess>#endifAlertManager& AlertManager::instance(){static AlertManager s_instance;return s_instance;}AlertManager::AlertManager() : QObject(nullptr) {// 初始化默认阈值setThreshold(MEMORY_HIGH, 70.0, 85.0);setThreshold(CPU_HIGH, 70.0, 85.0);setThreshold(DISK_FULL, 80.0, 90.0);setThreshold(SWAP_HIGH, 50.0, 75.0);setThreshold(NETWORK_ANOMALY, 100.0, 200.0); // MB/s// 初始化告警状态m_alertStates[MEMORY_HIGH] = false;m_alertStates[CPU_HIGH] = false;m_alertStates[DISK_FULL] = false;m_alertStates[SWAP_HIGH] = false;m_alertStates[NETWORK_ANOMALY] = false;// 初始化告警启用状态m_alertEnabled[MEMORY_HIGH] = true;m_alertEnabled[CPU_HIGH] = true;m_alertEnabled[DISK_FULL] = true;m_alertEnabled[SWAP_HIGH] = true;m_alertEnabled[NETWORK_ANOMALY] = false; // 默认禁用网络告警}AlertManager::~AlertManager() {}voidAlertManager::setThreshold(AlertType type, double warningValue, double criticalValue){QMutexLocker locker(&m_mutex);m_thresholds[type] = qMakePair(warningValue, criticalValue);}voidAlertManager::checkMetrics(const SystemMetrics &metrics){QMutexLocker locker(&m_mutex);// 检查内存使用率if (m_alertEnabled[MEMORY_HIGH]) {auto threshold = m_thresholds[MEMORY_HIGH];if (metrics.memoryUsagePercent >= threshold.second) {triggerAlert(MEMORY_HIGH, CRITICAL,QString("内存使用率过高: %1%").arg(metrics.memoryUsagePercent, 0, 'f', 1),metrics.memoryUsagePercent);} else if (metrics.memoryUsagePercent >= threshold.first) {triggerAlert(MEMORY_HIGH, WARNING,QString("内存使用率较高: %1%").arg(metrics.memoryUsagePercent, 0, 'f', 1),metrics.memoryUsagePercent);} else if (m_alertStates[MEMORY_HIGH]) {resolveAlert(MEMORY_HIGH);}}// 检查CPU使用率if (m_alertEnabled[CPU_HIGH]) {auto threshold = m_thresholds[CPU_HIGH];if (metrics.cpuUsagePercent >= threshold.second) {triggerAlert(CPU_HIGH, CRITICAL,QString("CPU使用率过高: %1%").arg(metrics.cpuUsagePercent, 0, 'f', 1),metrics.cpuUsagePercent);} else if (metrics.cpuUsagePercent >= threshold.first) {triggerAlert(CPU_HIGH, WARNING,QString("CPU使用率较高: %1%").arg(metrics.cpuUsagePercent, 0, 'f', 1),metrics.cpuUsagePercent);} else if (m_alertStates[CPU_HIGH]) {resolveAlert(CPU_HIGH);}}// 检查磁盘使用率if (m_alertEnabled[DISK_FULL]) {auto threshold = m_thresholds[DISK_FULL];if (metrics.diskUsagePercent >= threshold.second) {triggerAlert(DISK_FULL, CRITICAL,QString("磁盘空间即将满: %1%").arg(metrics.diskUsagePercent, 0, 'f', 1),metrics.diskUsagePercent);} else if (metrics.diskUsagePercent >= threshold.first) {triggerAlert(DISK_FULL, WARNING,QString("磁盘使用率较高: %1%").arg(metrics.diskUsagePercent, 0, 'f', 1),metrics.diskUsagePercent);} else if (m_alertStates[DISK_FULL]) {resolveAlert(DISK_FULL);}}// 检查交换空间使用率if (m_alertEnabled[SWAP_HIGH]) {auto threshold = m_thresholds[SWAP_HIGH];if (metrics.swapUsagePercent >= threshold.second) {triggerAlert(SWAP_HIGH, CRITICAL,QString("交换空间使用率过高: %1%").arg(metrics.swapUsagePercent, 0, 'f', 1),metrics.swapUsagePercent);} else if (metrics.swapUsagePercent >= threshold.first) {triggerAlert(SWAP_HIGH, WARNING,QString("交换空间使用率较高: %1%").arg(metrics.swapUsagePercent, 0, 'f', 1),metrics.swapUsagePercent);} else if (m_alertStates[SWAP_HIGH]) {resolveAlert(SWAP_HIGH);}}// 检查网络异常if (m_alertEnabled[NETWORK_ANOMALY]) {auto threshold = m_thresholds[NETWORK_ANOMALY];double maxNetworkSpeed = qMax(metrics.networkSpeedIn, metrics.networkSpeedOut);if (maxNetworkSpeed >= threshold.second) {triggerAlert(NETWORK_ANOMALY, CRITICAL,QString("网络速率异常: In=%1 KB/s, Out=%2 KB/s").arg(metrics.networkSpeedIn, 0, 'f', 1).arg(metrics.networkSpeedOut, 0, 'f', 1),maxNetworkSpeed);} else if (maxNetworkSpeed >= threshold.first) {triggerAlert(NETWORK_ANOMALY, WARNING,QString("网络速率较高: In=%1 KB/s, Out=%2 KB/s").arg(metrics.networkSpeedIn, 0, 'f', 1).arg(metrics.networkSpeedOut, 0, 'f', 1),maxNetworkSpeed);} else if (m_alertStates[NETWORK_ANOMALY]) {resolveAlert(NETWORK_ANOMALY);}}}voidAlertManager::setAlertEnabled(AlertType type, bool enabled){QMutexLocker locker(&m_mutex);m_alertEnabled[type] = enabled;}QVector<AlertManager::AlertRecord> AlertManager::getAlertHistory(int count){QMutexLocker locker(&m_mutex);QVector<AlertRecord> result;int start = qMax(0, m_alertHistory.size() - count);for (int i = start; i < m_alertHistory.size(); ++i) {result.append(m_alertHistory[i]);}return result;}voidAlertManager::clearAlertHistory(){QMutexLocker locker(&m_mutex);m_alertHistory.clear();}QMap<AlertManager::AlertType, bool> AlertManager::getCurrentAlertStates()const{return m_alertStates;}QPair<double, double> AlertManager::getThreshold(AlertType type)const{if (m_thresholds.contains(type)) {return m_thresholds[type];}return qMakePair(0.0, 0.0);}voidAlertManager::triggerAlert(AlertType type, AlertLevel level, const QString &message, double value){// 检查冷却时间,防止频繁告警if (m_lastAlertTime.contains(type)) {QDateTime lastTime = m_lastAlertTime[type];if (lastTime.secsTo(QDateTime::currentDateTime()) < ALERT_COOLDOWN_SECONDS) {return; // 在冷却期内,不触发告警}}// 如果已经处于告警状态,则不重复触发if (m_alertStates[type]) {return;}m_alertStates[type] = true;m_lastAlertTime[type] = QDateTime::currentDateTime();// 记录告警历史AlertRecord record;record.timestamp = QDateTime::currentDateTime();record.type = type;record.level = level;record.message = message;record.value = value;m_alertHistory.append(record);// 限制历史记录数量if (m_alertHistory.size() > 1000) {m_alertHistory.removeFirst();}qDebug() << "[ALERT]" << message;// 发送系统通知sendSystemNotification(level, message);// 发送信号emit alertTriggered(level, message);}voidAlertManager::resolveAlert(AlertType type){if (!m_alertStates[type]) {return;}m_alertStates[type] = false;QString typeStr;switch (type) {case MEMORY_HIGH: typeStr = "内存告警"; break;case CPU_HIGH: typeStr = "CPU告警"; break;case DISK_FULL: typeStr = "磁盘告警"; break;case SWAP_HIGH: typeStr = "交换空间告警"; break;case NETWORK_ANOMALY: typeStr = "网络告警"; break;}qDebug() << "[ALERT RESOLVED]" << typeStr;emit alertResolved(type);}voidAlertManager::sendSystemNotification(AlertLevel level, const QString &message){Q_UNUSED(level);Q_UNUSED(message);#ifdef Q_OS_WIN// Windows 系统通知(使用 Windows Toast Notification)// 简化实现:使用消息框// 实际应用中可使用 Windows Runtime API#elif defined(Q_OS_LINUX)// Linux 系统通知(使用 DBus)QString urgency;switch (level) {case INFO: urgency = "low"; break;case WARNING: urgency = "normal"; break;case CRITICAL: urgency = "critical"; break;}QProcess::startDetached("notify-send", QStringList()<< "-u" << urgency<< "内存监控系统"<< message);#elif defined(Q_OS_MAC)// macOS 系统通知QString script = QString("display notification \"%1\" with title \"内存监控系统\"").arg(message);QProcess::startDetached("osascript", QStringList() << "-e" << script);#endif}
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include<QMainWindow>#include<QTimer>#include<QLabel>#include<QGridLayout>#include<QProgressBar>#include<QGroupBox>#include<QPushButton>#include<QStyle>#include<QTableWidget>#include"wavewidget.h"#include"systeminfo.h"#include"datamanager.h"#include"alertmanager.h"#include"processmonitor.h"class MainWindow : public QMainWindow{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:voidupdateMemoryUsage();voidtoggleTheme();voidshowMemoryInfo();voidshowSystemInfo();voidshowSettings();voidshowProcessList();voidshowAlertHistory();voidexportData();voidonAlertTriggered(AlertManager::AlertLevel level, const QString &message);voidonAlertResolved(AlertManager::AlertType type);private:voidsetupUI();voidsetupConnections();voidgetMemoryInfo();voidupdateInfoLabels();voidupdateProgressBars();voidupdateSystemMetrics();voidapplyDarkTheme();voidapplyLightTheme();QString formatMemory(qint64 bytes)const;QString formatSpeed(double kbps)const;// 内存数据结构struct MemoryInfo {qint64 totalPhysical = 0;qint64 freePhysical = 0;qint64 usedPhysical = 0;qint64 totalSwap = 0;qint64 freeSwap = 0;qint64 usedSwap = 0;};MemoryInfo currentMemory;SystemMetrics currentMetrics;QTimer *updateTimer;// UI 组件WaveWidget *waveWidget;QLabel *physicalLabel;QLabel *swapLabel;QLabel *totalPhysicalLabel;QLabel *usedPhysicalLabel;QLabel *freePhysicalLabel;QLabel *totalSwapLabel;QLabel *usedSwapLabel;QLabel *freeSwapLabel;QLabel *cpuLabel;QLabel *diskLabel;QLabel *networkLabel;QProgressBar *physicalBar;QProgressBar *swapBar;QProgressBar *cpuBar;QProgressBar *diskBar;QPushButton *themeButton;QPushButton *infoButton;QPushButton *systemButton;QPushButton *settingsButton;QPushButton *processButton;QPushButton *alertButton;QPushButton *exportButton;bool darkTheme = true;};#endif// MAINWINDOW_H
#include "mainwindow.h"#include <QApplication>#include <QGridLayout>#include <QGroupBox>#include <QStyleFactory>#include <QStatusBar>#include <QDateTime>#include <QMessageBox>#include <QSysInfo>#include <QVBoxLayout>#include <QHBoxLayout>#include <QFileDialog>#ifdef Q_OS_WIN#include <windows.h>#elif defined(Q_OS_LINUX)#include <sys/sysinfo.h>#endifMainWindow::MainWindow(QWidget *p) : QMainWindow(p), currentMetrics() {setWindowTitle("Monitor");resize(1200, 800);QApplication::setStyle(QStyleFactory::create("Fusion"));DataManager::instance().initDatabase();QWidget *cw = new QWidget(this);setCentralWidget(cw);QGridLayout *ml = new QGridLayout(cw);ml->setSpacing(20);ml->setContentsMargins(20, 20, 20, 20);waveWidget = new WaveWidget(this);waveWidget->setMinimumHeight(350);ml->addWidget(waveWidget, 0, 0, 1, 2);QGroupBox *pg = new QGroupBox("Resources", this);QVBoxLayout *pl = new QVBoxLayout(pg);physicalBar = new QProgressBar(this);physicalBar->setRange(0, 100);physicalBar->setFormat("Mem: %p%");physicalBar->setTextVisible(true);swapBar = new QProgressBar(this);swapBar->setRange(0, 100);swapBar->setFormat("Swap: %p%");swapBar->setTextVisible(true);cpuBar = new QProgressBar(this);cpuBar->setRange(0, 100);cpuBar->setFormat("CPU: %p%");cpuBar->setTextVisible(true);diskBar = new QProgressBar(this);diskBar->setRange(0, 100);diskBar->setFormat("Disk: %p%");diskBar->setTextVisible(true);pl->addWidget(physicalBar);pl->addWidget(swapBar);pl->addWidget(cpuBar);pl->addWidget(diskBar);ml->addWidget(pg, 1, 0);QGroupBox *ig = new QGroupBox("Info", this);QGridLayout *il = new QGridLayout(ig);totalPhysicalLabel = new QLabel(this);usedPhysicalLabel = new QLabel(this);freePhysicalLabel = new QLabel(this);totalSwapLabel = new QLabel(this);usedSwapLabel = new QLabel(this);freeSwapLabel = new QLabel(this);cpuLabel = new QLabel(this);diskLabel = new QLabel(this);networkLabel = new QLabel(this);il->addWidget(new QLabel("Total:", this), 0, 0);il->addWidget(totalPhysicalLabel, 0, 1);il->addWidget(new QLabel("Used:", this), 1, 0);il->addWidget(usedPhysicalLabel, 1, 1);il->addWidget(new QLabel("Free:", this), 2, 0);il->addWidget(freePhysicalLabel, 2, 1);il->addWidget(new QLabel("Swap:", this), 4, 0);il->addWidget(totalSwapLabel, 4, 1);il->addWidget(new QLabel("CPU:", this), 8, 0);il->addWidget(cpuLabel, 8, 1);il->addWidget(new QLabel("Disk:", this), 9, 0);il->addWidget(diskLabel, 9, 1);il->addWidget(new QLabel("Net:", this), 10, 0);il->addWidget(networkLabel, 10, 1);ml->addWidget(ig, 1, 1);QHBoxLayout *bl = new QHBoxLayout();themeButton = new QPushButton("Theme", this);infoButton = new QPushButton("Mem", this);systemButton = new QPushButton("Sys", this);processButton = new QPushButton("Proc", this);alertButton = new QPushButton("Alert", this);exportButton = new QPushButton("Export", this);settingsButton = new QPushButton("Set", this);for(auto btn : {themeButton, infoButton, systemButton, processButton, alertButton, exportButton, settingsButton}) {btn->setMinimumHeight(35);bl->addWidget(btn);}ml->addLayout(bl, 2, 0, 1, 2);applyDarkTheme();updateTimer = new QTimer(this);connect(updateTimer, &QTimer::timeout, this, &MainWindow::updateMemoryUsage);updateTimer->start(1000);setupConnections();updateMemoryUsage();statusBar()->showMessage("OK");}MainWindow::~MainWindow() {if(updateTimer) {updateTimer->stop();delete updateTimer;}DataManager::instance().closeDatabase();}void MainWindow::setupConnections() {connect(themeButton, &QPushButton::clicked, this, &MainWindow::toggleTheme);connect(infoButton, &QPushButton::clicked, this, &MainWindow::showMemoryInfo);connect(systemButton, &QPushButton::clicked, this, &MainWindow::showSystemInfo);connect(processButton, &QPushButton::clicked, this, &MainWindow::showProcessList);connect(alertButton, &QPushButton::clicked, this, &MainWindow::showAlertHistory);connect(exportButton, &QPushButton::clicked, this, &MainWindow::exportData);connect(settingsButton, &QPushButton::clicked, this, &MainWindow::showSettings);connect(&AlertManager::instance(), QOverload<AlertManager::AlertLevel, const QString&>::of(&AlertManager::alertTriggered),this, &MainWindow::onAlertTriggered);connect(&AlertManager::instance(), QOverload<AlertManager::AlertType>::of(&AlertManager::alertResolved),this, &MainWindow::onAlertResolved);}QString MainWindow::formatMemory(qint64 b) const {if(b >= 1024*1024*1024) return QString("%1G").arg(b / (1024.0*1024*1024), 0, 'f', 1);if(b >= 1024*1024) return QString("%1M").arg(b / (1024.0*1024), 0, 'f', 1);if(b >= 1024) return QString("%1K").arg(b / 1024.0, 0, 'f', 1);return QString("%1B").arg(b);}QString MainWindow::formatSpeed(double k) const {if(k >= 1024) return QString("%1M/s").arg(k / 1024.0, 0, 'f', 1);return QString("%1K/s").arg(k, 0, 'f', 1);}void MainWindow::getMemoryInfo() {#ifdef Q_OS_WINMEMORYSTATUSEX ms;ms.dwLength = sizeof(ms);if(GlobalMemoryStatusEx(&ms)) {currentMemory.totalPhysical = ms.ullTotalPhys;currentMemory.freePhysical = ms.ullAvailPhys;currentMemory.usedPhysical = currentMemory.totalPhysical - currentMemory.freePhysical;currentMemory.totalSwap = ms.ullTotalPageFile;currentMemory.freeSwap = ms.ullAvailPageFile;currentMemory.usedSwap = currentMemory.totalSwap - currentMemory.freeSwap;}#elif defined(Q_OS_LINUX)struct sysinfo info;if(sysinfo(&info) == 0) {currentMemory.totalPhysical = info.totalram * info.mem_unit;currentMemory.freePhysical = info.freeram * info.mem_unit;currentMemory.usedPhysical = currentMemory.totalPhysical - currentMemory.freePhysical;currentMemory.totalSwap = info.totalswap * info.mem_unit;currentMemory.freeSwap = info.freeswap * info.mem_unit;currentMemory.usedSwap = currentMemory.totalSwap - currentMemory.freeSwap;}#endif}void MainWindow::updateSystemMetrics() {currentMetrics = SystemMonitor::instance().getCurrentMetrics();}void MainWindow::updateMemoryUsage() {getMemoryInfo();updateSystemMetrics();updateInfoLabels();updateProgressBars();DataManager::instance().saveMetrics(currentMetrics);AlertManager::instance().checkMetrics(currentMetrics);double pu = currentMemory.totalPhysical > 0 ? (currentMemory.usedPhysical * 100.0 / currentMemory.totalPhysical) : 0;waveWidget->setMemoryUsage(pu);statusBar()->showMessage(QDateTime::currentDateTime().toString("hh:mm:ss") + " | Mem:" + QString::number(pu, 'f', 1) + "% CPU:" + QString::number(currentMetrics.cpuUsagePercent, 'f', 1) + "%");}void MainWindow::updateInfoLabels() {totalPhysicalLabel->setText(formatMemory(currentMemory.totalPhysical));usedPhysicalLabel->setText(formatMemory(currentMemory.usedPhysical));freePhysicalLabel->setText(formatMemory(currentMemory.freePhysical));totalSwapLabel->setText(formatMemory(currentMemory.totalSwap));usedSwapLabel->setText(formatMemory(currentMemory.usedSwap));freeSwapLabel->setText(formatMemory(currentMemory.freeSwap));cpuLabel->setText(QString::number(currentMetrics.cpuCoreCount));diskLabel->setText(QString::number(currentMetrics.diskUsagePercent, 'f', 1) + "%");networkLabel->setText(formatSpeed(currentMetrics.networkSpeedIn));}void MainWindow::updateProgressBars() {int pp = currentMemory.totalPhysical > 0 ? (int)(currentMemory.usedPhysical * 100 / currentMemory.totalPhysical) : 0;physicalBar->setValue(pp);int sp = currentMemory.totalSwap > 0 ? (int)(currentMemory.usedSwap * 100 / currentMemory.totalSwap) : 0;swapBar->setValue(sp);cpuBar->setValue((int)currentMetrics.cpuUsagePercent);diskBar->setValue((int)currentMetrics.diskUsagePercent);}void MainWindow::toggleTheme() {darkTheme ? applyLightTheme() : applyDarkTheme();darkTheme = !darkTheme;}void MainWindow::showMemoryInfo() {QMessageBox::information(this, "Mem", "Total: " + formatMemory(currentMemory.totalPhysical) + "\nUsed: " + formatMemory(currentMemory.usedPhysical));}void MainWindow::showSystemInfo() {QMessageBox::information(this, "Sys", "OS: " + QSysInfo::prettyProductName() + "\nCores: " + QString::number(currentMetrics.cpuCoreCount));}void MainWindow::showProcessList() {QVector<ProcessInfo> tp = ProcessMonitor::instance().getTopMemoryProcesses(10);QString t = "Top 10\n";for(const auto& p : tp) t += p.name + " " + formatMemory(p.memoryBytes) + "\n";QMessageBox::information(this, "Proc", t);}void MainWindow::showAlertHistory() {QVector<AlertManager::AlertRecord> h = AlertManager::instance().getAlertHistory(50);QString t = "Alerts\n";for(const auto& r : h) t += r.timestamp.toString("hh:mm:ss") + " " + r.message + "\n";QMessageBox::information(this, "Alert", t);}void MainWindow::exportData() {QString fn = QFileDialog::getSaveFileName(this, "Export", "", "CSV (*.csv)");if(!fn.isEmpty()) {QDateTime et = QDateTime::currentDateTime();DataManager::instance().exportToCSV(fn, et.addDays(-1), et);}}void MainWindow::showSettings() {QMessageBox::information(this, "Set", "Coming");}void MainWindow::onAlertTriggered(AlertManager::AlertLevel l, const QString &m) {statusBar()->showMessage((l == AlertManager::CRITICAL ? "CRIT: ": "WARN: ") + m);}void MainWindow::onAlertResolved(AlertManager::AlertType t) {Q_UNUSED(t);statusBar()->showMessage("OK");}void MainWindow::applyDarkTheme() {QPalette dp;dp.setColor(QPalette::Window, QColor(53, 53, 53));dp.setColor(QPalette::WindowText, Qt::white);dp.setColor(QPalette::Base, QColor(25, 25, 25));dp.setColor(QPalette::Button, QColor(53, 53, 53));dp.setColor(QPalette::ButtonText, Qt::white);dp.setColor(QPalette::Highlight, QColor(42, 130, 218));qApp->setPalette(dp);QString bs = "QPushButton { background-color: #3A3A3A; color: white; border: 1px solid #555; border-radius: 5px; padding: 8px; }";for(auto btn : {themeButton, infoButton, systemButton, processButton, alertButton, exportButton, settingsButton}) btn->setStyleSheet(bs);for(QGroupBox *box : findChildren<QGroupBox*>()) box->setStyleSheet("QGroupBox { color: #AAA; border: 2px solid #555; }");for(QLabel *label : findChildren<QLabel*>()) label->setStyleSheet("QLabel { color: #DDD; }");}void MainWindow::applyLightTheme() {qApp->setPalette(QApplication::style()->standardPalette());QString bs = "QPushButton { background-color: #F0F0F0; color: #333; border: 1px solid #AAA; border-radius: 5px; padding: 8px; }";for(auto btn : {themeButton, infoButton, systemButton, processButton, alertButton, exportButton, settingsButton}) btn->setStyleSheet(bs);for(QGroupBox *box : findChildren<QGroupBox*>()) box->setStyleSheet("QGroupBox { color: #0066CC; border: 2px solid #AAA; }");for(QLabel *label : findChildren<QLabel*>()) label->setStyleSheet("QLabel { color: #333; }");}
夜雨聆风