Files
JSwitchDisplayApplet/graphicsdriverapplet.cpp
T
Jokul b440fdf40a feat: 移除D-Bus依赖,改用 lspci 直接检测显卡,重构弹窗UI
- C++ 后端:移除 D-Bus 通信,改用 lspci -mm + /sys/bus/pci 直接检测显卡和驱动
- 新增 gpuSummary、ready 属性,通过 /sys/module 和 /proc/driver 读取驱动版本
- QML:使用 DTK 配色,卡片式布局展示 GPU 列表,每张显卡独立卡片
- 移除安装/测试/取消按钮,聚焦显卡信息展示
- 翻译精简为 5 条,同步 zh_CN / zh_TW
2026-07-13 21:14:12 +08:00

208 lines
5.5 KiB
C++

// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "graphicsdriverapplet.h"
#include <pluginfactory.h>
#include <QProcess>
#include <QDir>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QRegularExpression>
DCORE_USE_NAMESPACE
DS_BEGIN_NAMESPACE
GraphicsDriverApplet::GraphicsDriverApplet(QObject *parent)
: DApplet(parent)
, m_ready(false)
{
}
GraphicsDriverApplet::~GraphicsDriverApplet()
{
}
bool GraphicsDriverApplet::load()
{
return DApplet::load();
}
bool GraphicsDriverApplet::init()
{
detectGpus();
return DApplet::init();
}
QString GraphicsDriverApplet::deviceInfo() const
{
return m_deviceInfo;
}
QString GraphicsDriverApplet::currentDriver() const
{
return m_currentDriver;
}
QString GraphicsDriverApplet::gpuSummary() const
{
return m_gpuSummary;
}
bool GraphicsDriverApplet::ready() const
{
return m_ready;
}
void GraphicsDriverApplet::refreshDeviceInfo()
{
detectGpus();
}
void GraphicsDriverApplet::detectGpus()
{
m_gpus.clear();
// 通过 lspci 检测显卡
QStringList lines = runCommand("lspci", {"-mm"});
for (const QString &line : lines) {
if (line.contains("VGA compatible controller", Qt::CaseInsensitive) ||
line.contains("3D controller", Qt::CaseInsensitive) ||
line.contains("Display controller", Qt::CaseInsensitive)) {
GpuInfo gpu;
// lspci -mm 格式: "Class" "Vendor" "Device" ...
// 提取 PCI ID(行首的 01:00.0 等)
int spaceIdx = line.indexOf(' ');
if (spaceIdx > 0) {
gpu.pciId = line.left(spaceIdx);
}
gpu.name = parseGpuName(line);
// 检测驱动
QString sysPath = "/sys/bus/pci/devices/0000:" + gpu.pciId + "/driver";
QDir driverDir(sysPath);
if (driverDir.exists()) {
gpu.driver = driverDir.dirName();
// 读取驱动版本
gpu.driverVersion = readDriverVersion(gpu.driver);
} else {
gpu.driver = "unknown";
}
m_gpus.append(gpu);
}
}
// 生成摘要信息
QStringList parts;
QStringList driverParts;
for (const GpuInfo &gpu : m_gpus) {
QString info = gpu.name;
if (!gpu.driver.isEmpty() && gpu.driver != "unknown") {
info += " (" + gpu.driver;
if (!gpu.driverVersion.isEmpty()) {
info += " " + gpu.driverVersion;
}
info += ")";
}
parts << info;
if (!gpu.driver.isEmpty() && !driverParts.contains(gpu.driver)) {
driverParts << gpu.driver;
}
}
m_deviceInfo = parts.join("\n");
m_currentDriver = driverParts.join(", ");
m_gpuSummary = parts.join(" | ");
m_ready = !m_gpus.isEmpty();
qDebug() << "Detected GPUs:" << m_deviceInfo;
qDebug() << "Current drivers:" << m_currentDriver;
emit deviceInfoChanged();
emit currentDriverChanged();
emit gpuSummaryChanged();
emit readyChanged();
}
QStringList GraphicsDriverApplet::runCommand(const QString &cmd, const QStringList &args)
{
QProcess process;
process.start(cmd, args);
process.waitForFinished(5000);
QString output = QString::fromUtf8(process.readAllStandardOutput());
return output.split('\n', Qt::SkipEmptyParts);
}
QString GraphicsDriverApplet::parseGpuName(const QString &line)
{
// lspci -mm 格式示例:
// 01:00.0 "VGA compatible controller" "NVIDIA Corporation" "GA106M [GeForce RTX 3060 Mobile / Max-Q]" "ASUSTeK Computer Inc." "Device 10a2"
// 提取引号中的内容
QStringList parts;
int pos = 0;
while (pos < line.length()) {
int start = line.indexOf('"', pos);
if (start < 0) break;
int end = line.indexOf('"', start + 1);
if (end < 0) break;
parts << line.mid(start + 1, end - start - 1);
pos = end + 1;
}
if (parts.size() >= 3) {
// parts[0] = class, parts[1] = vendor, parts[2] = device
QString vendor = parts[1];
QString device = parts[2];
// 去掉方括号内的别名,保留主要名称
int bracket = device.indexOf('[');
if (bracket > 0) {
// 保留完整名称,方括号内是子系统信息
}
return vendor + " " + device;
}
return line;
}
QString GraphicsDriverApplet::readDriverVersion(const QString &driverName)
{
// 尝试从 /sys/module/<driver>/version 读取版本
QString path = "/sys/module/" + driverName + "/version";
QFile file(path);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QString version = QTextStream(&file).readAll().trimmed();
if (!version.isEmpty()) {
return version;
}
}
// nvidia 特殊处理:从 /proc/driver/nvidia/version 读取
if (driverName == "nvidia") {
QFile nvFile("/proc/driver/nvidia/version");
if (nvFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
QString content = QTextStream(&nvFile).readAll();
// 格式: NVRM version: NVIDIA UNIX x86_64 Kernel Module 535.183.01 ...
QRegularExpression re("Kernel Module\\s+(\\d+\\.\\d+\\.\\d+)");
auto match = re.match(content);
if (match.hasMatch()) {
return match.captured(1);
}
}
}
return QString();
}
D_APPLET_CLASS(GraphicsDriverApplet)
DS_END_NAMESPACE
#include "graphicsdriverapplet.moc"