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
This commit is contained in:
2026-07-13 21:14:12 +08:00
parent 2e10de4bcc
commit b440fdf40a
5 changed files with 376 additions and 418 deletions
+141 -207
View File
@@ -5,29 +5,20 @@
#include "graphicsdriverapplet.h" #include "graphicsdriverapplet.h"
#include <pluginfactory.h> #include <pluginfactory.h>
#include <QDBusConnection> #include <QProcess>
#include <QDBusConnectionInterface> #include <QDir>
#include <QDBusPendingReply>
#include <QDebug> #include <QDebug>
#include <QJsonDocument> #include <QFile>
#include <QJsonObject> #include <QTextStream>
#include <QJsonArray> #include <QRegularExpression>
DCORE_USE_NAMESPACE DCORE_USE_NAMESPACE
DS_BEGIN_NAMESPACE DS_BEGIN_NAMESPACE
static const QString DBUS_SERVICE = "com.deepin.daemon.GraphicsDriver";
static const QString DBUS_PATH = "/com/deepin/daemon/GraphicsDriver";
static const QString DBUS_INTERFACE = "com.deepin.daemon.GraphicsDriver";
GraphicsDriverApplet::GraphicsDriverApplet(QObject *parent) GraphicsDriverApplet::GraphicsDriverApplet(QObject *parent)
: DApplet(parent) : DApplet(parent)
, m_dbusInterface(nullptr) , m_ready(false)
, m_progressTimer(new QTimer(this))
, m_installProgress(0)
, m_isInstalling(false)
, m_dbusAvailable(false)
{ {
} }
@@ -37,233 +28,176 @@ GraphicsDriverApplet::~GraphicsDriverApplet()
bool GraphicsDriverApplet::load() bool GraphicsDriverApplet::load()
{ {
initDBusConnection();
return DApplet::load(); return DApplet::load();
} }
bool GraphicsDriverApplet::init() bool GraphicsDriverApplet::init()
{ {
if (m_dbusAvailable) { detectGpus();
refreshDeviceInfo();
}
return DApplet::init(); return DApplet::init();
} }
QString GraphicsDriverApplet::currentDriver() const
{
return m_currentDriver;
}
QString GraphicsDriverApplet::deviceInfo() const QString GraphicsDriverApplet::deviceInfo() const
{ {
return m_deviceInfo; return m_deviceInfo;
} }
int GraphicsDriverApplet::installProgress() const QString GraphicsDriverApplet::currentDriver() const
{ {
return m_installProgress; return m_currentDriver;
} }
bool GraphicsDriverApplet::isInstalling() const QString GraphicsDriverApplet::gpuSummary() const
{ {
return m_isInstalling; return m_gpuSummary;
} }
bool GraphicsDriverApplet::dbusAvailable() const bool GraphicsDriverApplet::ready() const
{ {
return m_dbusAvailable; return m_ready;
} }
void GraphicsDriverApplet::refreshDeviceInfo() void GraphicsDriverApplet::refreshDeviceInfo()
{ {
if (!m_dbusInterface || !m_dbusInterface->isValid()) { detectGpus();
qWarning() << "DBus interface is not valid";
return;
}
// Get device info
QDBusPendingCall deviceCall = m_dbusInterface->asyncCall("GetDevice");
QDBusPendingCallWatcher *deviceWatcher = new QDBusPendingCallWatcher(deviceCall, this);
connect(deviceWatcher, &QDBusPendingCallWatcher::finished, this, &GraphicsDriverApplet::onGetDeviceReply);
// Get current driver
QDBusPendingCall currCall = m_dbusInterface->asyncCall("GetCurrDriverName");
QDBusPendingCallWatcher *currWatcher = new QDBusPendingCallWatcher(currCall, this);
connect(currWatcher, &QDBusPendingCallWatcher::finished, this, &GraphicsDriverApplet::onGetCurrDriverReply);
} }
void GraphicsDriverApplet::prepareInstall(const QString &driverName) void GraphicsDriverApplet::detectGpus()
{ {
if (!m_dbusInterface || !m_dbusInterface->isValid()) { m_gpus.clear();
emit installFailed("DBus interface is not valid");
return;
}
QLocale locale; // 通过 lspci 检测显卡
QString language = locale.name(); 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)) {
QDBusPendingCall call = m_dbusInterface->asyncCall("PrepareInstall", driverName, language); GpuInfo gpu;
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); // lspci -mm 格式: "Class" "Vendor" "Device" ...
connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *call) { // 提取 PCI ID(行首的 01:00.0 等)
QDBusPendingReply<> reply = *call; int spaceIdx = line.indexOf(' ');
if (reply.isError()) { if (spaceIdx > 0) {
qWarning() << "Failed to prepare install:" << reply.error().message(); gpu.pciId = line.left(spaceIdx);
emit installFailed(reply.error().message()); }
} else {
qDebug() << "Prepare install succeeded";
}
call->deleteLater();
});
}
void GraphicsDriverApplet::testInstall() gpu.name = parseGpuName(line);
{
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
emit installFailed("DBus interface is not valid");
return;
}
setInstalling(true); // 检测驱动
QString sysPath = "/sys/bus/pci/devices/0000:" + gpu.pciId + "/driver";
QDir driverDir(sysPath);
if (driverDir.exists()) {
gpu.driver = driverDir.dirName();
QDBusPendingCall call = m_dbusInterface->asyncCall("TestInstall"); // 读取驱动版本
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); gpu.driverVersion = readDriverVersion(gpu.driver);
connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *call) { } else {
QDBusPendingReply<> reply = *call; gpu.driver = "unknown";
if (reply.isError()) { }
qWarning() << "Failed to test install:" << reply.error().message();
emit installFailed(reply.error().message());
setInstalling(false);
} else {
qDebug() << "Test install succeeded";
realInstall();
}
call->deleteLater();
});
}
void GraphicsDriverApplet::realInstall() m_gpus.append(gpu);
{
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
emit installFailed("DBus interface is not valid");
return;
}
QDBusPendingCall call = m_dbusInterface->asyncCall("RealInstall");
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
connect(watcher, &QDBusPendingCallWatcher::finished, [this](QDBusPendingCallWatcher *call) {
QDBusPendingReply<> reply = *call;
if (reply.isError()) {
qWarning() << "Failed to real install:" << reply.error().message();
emit installFailed(reply.error().message());
setInstalling(false);
} else {
qDebug() << "Real install succeeded";
setInstalling(false);
emit installSuccess();
emit requestReboot();
}
call->deleteLater();
});
}
void GraphicsDriverApplet::cancelInstall()
{
if (!m_dbusInterface || !m_dbusInterface->isValid()) {
return;
}
m_dbusInterface->asyncCall("CancelInstall");
setInstalling(false);
}
void GraphicsDriverApplet::onGetDeviceReply(QDBusPendingCallWatcher *call)
{
QDBusPendingReply<QString> reply = *call;
if (reply.isError()) {
qWarning() << "Failed to get device:" << reply.error().message();
} else {
m_deviceInfo = reply.value();
qDebug() << "Device info:" << m_deviceInfo;
emit deviceInfoChanged();
}
call->deleteLater();
}
void GraphicsDriverApplet::onGetCurrDriverReply(QDBusPendingCallWatcher *call)
{
QDBusPendingReply<QString> reply = *call;
if (reply.isError()) {
qWarning() << "Failed to get current driver:" << reply.error().message();
} else {
m_currentDriver = reply.value();
qDebug() << "Current driver:" << m_currentDriver;
emit currentDriverChanged();
}
call->deleteLater();
}
void GraphicsDriverApplet::onReportProgress(const QString &ratio)
{
bool ok;
int progress = ratio.toInt(&ok);
if (ok) {
m_installProgress = progress;
emit installProgressChanged();
}
}
void GraphicsDriverApplet::initDBusConnection()
{
QDBusConnection bus = QDBusConnection::sessionBus();
if (!bus.isConnected()) {
qWarning() << "Cannot connect to D-Bus session bus";
return;
}
// 检查服务是否已注册
bool registered = bus.interface()->isServiceRegistered(DBUS_SERVICE);
if (!registered) {
qWarning() << "GraphicsDriver D-Bus service is not registered";
return;
}
m_dbusInterface = new QDBusInterface(
DBUS_SERVICE,
DBUS_PATH,
DBUS_INTERFACE,
bus,
this
);
if (!m_dbusInterface->isValid()) {
qWarning() << "DBus interface is not valid:" << m_dbusInterface->lastError().message();
return;
}
m_dbusAvailable = true;
emit dbusAvailableChanged();
connect(m_dbusInterface, SIGNAL(ReportProgress(QString)),
this, SLOT(onReportProgress(QString)));
qDebug() << "GraphicsDriver D-Bus connected successfully";
}
void GraphicsDriverApplet::setInstalling(bool installing)
{
if (m_isInstalling != installing) {
m_isInstalling = installing;
emit isInstallingChanged();
if (installing) {
m_progressTimer->start(1000);
} else {
m_progressTimer->stop();
m_installProgress = 0;
emit installProgressChanged();
} }
} }
// 生成摘要信息
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) D_APPLET_CLASS(GraphicsDriverApplet)
+26 -37
View File
@@ -6,23 +6,27 @@
#include <applet.h> #include <applet.h>
#include <QDBusInterface> #include <QString>
#include <QDBusPendingCallWatcher> #include <QStringList>
#include <QTimer> #include <QTimer>
#include <QJsonObject>
#include <QJsonArray>
DS_BEGIN_NAMESPACE DS_BEGIN_NAMESPACE
struct GpuInfo {
QString name; // 显卡名称,如 "NVIDIA GeForce RTX 3060"
QString driver; // 驱动模块名,如 "nvidia"
QString driverVersion; // 驱动版本
QString pciId; // PCI ID,如 "01:00.0"
};
class GraphicsDriverApplet : public DApplet class GraphicsDriverApplet : public DApplet
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString currentDriver READ currentDriver NOTIFY currentDriverChanged)
Q_PROPERTY(QString deviceInfo READ deviceInfo NOTIFY deviceInfoChanged) Q_PROPERTY(QString deviceInfo READ deviceInfo NOTIFY deviceInfoChanged)
Q_PROPERTY(int installProgress READ installProgress NOTIFY installProgressChanged) Q_PROPERTY(QString currentDriver READ currentDriver NOTIFY currentDriverChanged)
Q_PROPERTY(bool isInstalling READ isInstalling NOTIFY isInstallingChanged) Q_PROPERTY(QString gpuSummary READ gpuSummary NOTIFY gpuSummaryChanged)
Q_PROPERTY(bool dbusAvailable READ dbusAvailable NOTIFY dbusAvailableChanged) Q_PROPERTY(bool ready READ ready NOTIFY readyChanged)
public: public:
explicit GraphicsDriverApplet(QObject *parent = nullptr); explicit GraphicsDriverApplet(QObject *parent = nullptr);
@@ -31,45 +35,30 @@ public:
virtual bool load() override; virtual bool load() override;
virtual bool init() override; virtual bool init() override;
QString currentDriver() const;
QString deviceInfo() const; QString deviceInfo() const;
int installProgress() const; QString currentDriver() const;
bool isInstalling() const; QString gpuSummary() const;
bool dbusAvailable() const; bool ready() const;
Q_INVOKABLE void refreshDeviceInfo(); Q_INVOKABLE void refreshDeviceInfo();
Q_INVOKABLE void prepareInstall(const QString &driverName);
Q_INVOKABLE void testInstall();
Q_INVOKABLE void realInstall();
Q_INVOKABLE void cancelInstall();
signals: signals:
void currentDriverChanged();
void deviceInfoChanged(); void deviceInfoChanged();
void installProgressChanged(); void currentDriverChanged();
void isInstallingChanged(); void gpuSummaryChanged();
void installSuccess(); void readyChanged();
void installFailed(const QString &error);
void requestReboot();
void dbusAvailableChanged();
private slots:
void onGetDeviceReply(QDBusPendingCallWatcher *call);
void onGetCurrDriverReply(QDBusPendingCallWatcher *call);
void onReportProgress(const QString &ratio);
private: private:
void initDBusConnection(); void detectGpus();
void setInstalling(bool installing); static QStringList runCommand(const QString &cmd, const QStringList &args);
static QString parseGpuName(const QString &line);
static QString readDriverVersion(const QString &driverName);
QDBusInterface *m_dbusInterface; QList<GpuInfo> m_gpus;
QTimer *m_progressTimer;
bool m_dbusAvailable;
QString m_currentDriver;
QString m_deviceInfo; QString m_deviceInfo;
int m_installProgress; QString m_currentDriver;
bool m_isInstalling; QString m_gpuSummary;
bool m_ready;
}; };
DS_END_NAMESPACE DS_END_NAMESPACE
+203 -108
View File
@@ -7,6 +7,7 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import org.deepin.ds 1.0 import org.deepin.ds 1.0
import org.deepin.ds.dock 1.0 import org.deepin.ds.dock 1.0
import org.deepin.dtk 1.0
AppletItem { AppletItem {
id: root id: root
@@ -17,24 +18,32 @@ AppletItem {
implicitWidth: dockSize implicitWidth: dockSize
implicitHeight: dockSize implicitHeight: dockSize
// 访问 C++ 后端
readonly property var applet: Applet readonly property var applet: Applet
readonly property bool dbusAvailable: applet && applet.dbusAvailable readonly property bool ready: applet ? applet.ready : false
readonly property string currentDriver: applet ? (applet.currentDriver || qsTr("Unknown")) : qsTr("Unknown") readonly property string gpuSummary: applet ? (applet.gpuSummary || qsTr("No GPU detected")) : qsTr("No GPU detected")
readonly property string deviceInfo: applet ? (applet.deviceInfo || qsTr("Unknown")) : qsTr("Unknown") readonly property string deviceInfo: applet ? (applet.deviceInfo || qsTr("Unknown")) : qsTr("Unknown")
readonly property bool isInstalling: applet ? applet.isInstalling : false readonly property string currentDriver: applet ? (applet.currentDriver || qsTr("Unknown")) : qsTr("Unknown")
readonly property int installProgress: applet ? applet.installProgress : 0
property Palette basePalette: DockPalette.iconTextPalette
readonly property color primaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.9)
readonly property color secondaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.65)
readonly property color tertiaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.5)
readonly property color cardBackground: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.06)
readonly property color cardBorder: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.1)
readonly property color accentBlue: Qt.rgba(36 / 255, 118 / 255, 220 / 255, 1)
readonly property color accentBlueLight: Qt.rgba(36 / 255, 118 / 255, 220 / 255, 0.15)
// 图标区域 // 图标区域
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: "#3498db" color: accentBlue
radius: 8 radius: 8
Text { Text {
anchors.centerIn: parent anchors.centerIn: parent
text: "GPU" text: "GPU"
font.pixelSize: root.dockSize * 0.3 font.pixelSize: root.dockSize * 0.3
font.bold: true
color: "white" color: "white"
} }
} }
@@ -42,7 +51,7 @@ AppletItem {
// 悬停提示 // 悬停提示
PanelToolTip { PanelToolTip {
id: toolTip id: toolTip
text: qsTr("Graphics Driver: ") + root.currentDriver text: root.ready ? root.gpuSummary : qsTr("No GPU detected")
toolTipX: DockPanelPositioner.x toolTipX: DockPanelPositioner.x
toolTipY: DockPanelPositioner.y toolTipY: DockPanelPositioner.y
} }
@@ -73,8 +82,8 @@ AppletItem {
// 弹出窗口 // 弹出窗口
PanelPopup { PanelPopup {
id: driverPopup id: driverPopup
width: 320 width: 360
height: 400 height: 320
popupX: DockPanelPositioner.x popupX: DockPanelPositioner.x
popupY: DockPanelPositioner.y popupY: DockPanelPositioner.y
@@ -90,114 +99,196 @@ AppletItem {
padding: 16 padding: 16
contentItem: ColumnLayout { contentItem: ColumnLayout {
spacing: 12 spacing: 14
Text { // 标题区域
text: qsTr("Graphics Driver Manager") RowLayout {
font.pixelSize: 16
font.bold: true
Layout.fillWidth: true Layout.fillWidth: true
spacing: 10
Rectangle {
width: 28
height: 28
color: accentBlueLight
radius: 8
Text {
anchors.centerIn: parent
text: "GPU"
font.pixelSize: 12
font.bold: true
color: accentBlue
}
}
Text {
text: qsTr("Graphics Driver Manager")
font.pixelSize: 16
font.bold: true
color: root.primaryText
Layout.fillWidth: true
}
} }
// 分隔线
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 1 Layout.preferredHeight: 1
color: "#cccccc" color: root.cardBorder
} }
// D-Bus 不可用提示 // 当前驱动信息
Rectangle { RowLayout {
Layout.fillWidth: true
height: 40
visible: !root.dbusAvailable
color: "#fff3cd"
radius: 6
Text {
anchors.centerIn: parent
text: qsTr("Driver service is not available")
color: "#856404"
font.pixelSize: 12
}
}
// 设备信息
GroupBox {
Layout.fillWidth: true
title: qsTr("Device Information")
visible: root.dbusAvailable
ColumnLayout {
anchors.fill: parent
spacing: 8
Text {
text: qsTr("Current Driver: ") + root.currentDriver
font.pixelSize: 12
Layout.fillWidth: true
}
Text {
text: qsTr("Device: ") + root.deviceInfo
font.pixelSize: 12
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
}
}
// 操作按钮
Button {
text: qsTr("Refresh")
Layout.fillWidth: true
enabled: root.dbusAvailable && !root.isInstalling
onClicked: {
if (root.applet) {
root.applet.refreshDeviceInfo()
}
}
}
Button {
text: qsTr("Test Install")
Layout.fillWidth: true
enabled: root.dbusAvailable && !root.isInstalling
onClicked: {
if (root.applet) {
root.applet.testInstall()
}
}
}
// 安装进度
ColumnLayout {
visible: root.isInstalling
Layout.fillWidth: true Layout.fillWidth: true
spacing: 8 spacing: 8
visible: root.ready
Text { Text {
text: qsTr("Installing... ") + root.installProgress + "%" text: qsTr("Current Driver:")
font.pixelSize: 12 font.pixelSize: 12
color: root.secondaryText
} }
ProgressBar { Text {
text: root.currentDriver
font.pixelSize: 12
font.bold: true
color: root.primaryText
Layout.fillWidth: true Layout.fillWidth: true
value: root.installProgress / 100 elide: Text.ElideRight
}
}
// GPU 列表区域
Flickable {
id: gpuListFlick
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
contentWidth: width
contentHeight: gpuColumn.height
boundsBehavior: Flickable.StopAtBounds
Column {
id: gpuColumn
width: gpuListFlick.width
spacing: 10
visible: root.ready
Repeater {
model: root.ready ? root.deviceInfo.split("\n").filter(function(line) { return line.trim().length > 0 }) : []
delegate: Rectangle {
width: gpuColumn.width
height: 72
color: root.cardBackground
radius: 10
border.width: 1
border.color: root.cardBorder
RowLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 12
// GPU 图标
Rectangle {
width: 44
height: 44
color: root.accentBlueLight
radius: 8
Text {
anchors.centerIn: parent
text: "GPU"
font.pixelSize: 14
font.bold: true
color: root.accentBlue
}
}
// GPU 信息
ColumnLayout {
spacing: 4
Layout.fillWidth: true
Text {
text: parseGpuName(modelData)
font.pixelSize: 13
font.bold: true
color: root.primaryText
Layout.fillWidth: true
elide: Text.ElideRight
}
Text {
text: parseDriverInfo(modelData)
font.pixelSize: 11
color: root.secondaryText
Layout.fillWidth: true
elide: Text.ElideRight
}
}
}
}
}
} }
Button { // 未检测到 GPU 提示
text: qsTr("Cancel") Rectangle {
Layout.fillWidth: true anchors.centerIn: parent
onClicked: { width: gpuListFlick.width - 32
if (root.applet) { height: 80
root.applet.cancelInstall() color: root.cardBackground
radius: 10
border.width: 1
border.color: root.cardBorder
visible: !root.ready
ColumnLayout {
anchors.centerIn: parent
spacing: 6
Text {
text: "⚠"
font.pixelSize: 24
}
Text {
text: qsTr("No GPU detected")
font.pixelSize: 13
color: root.secondaryText
} }
} }
} }
} }
Item { // 刷新按钮
Layout.fillHeight: true Button {
id: refreshBtn
text: qsTr("Refresh")
Layout.fillWidth: true
Layout.preferredHeight: 36
font.pixelSize: 13
background: Rectangle {
color: refreshBtn.hovered ? root.accentBlue : root.accentBlueLight
radius: 8
}
contentItem: Text {
text: refreshBtn.text
color: refreshBtn.hovered ? "white" : root.accentBlue
font.pixelSize: refreshBtn.font.pixelSize
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: {
if (root.applet) {
root.applet.refreshDeviceInfo()
}
}
} }
} }
} }
@@ -210,6 +301,25 @@ AppletItem {
} }
} }
// 解析 GPU 名称的辅助函数
function parseGpuName(info) {
var parts = info.split("(")
if (parts.length > 0) {
return parts[0].trim()
}
return info
}
// 解析驱动信息的辅助函数
function parseDriverInfo(info) {
var startIndex = info.indexOf("(")
var endIndex = info.lastIndexOf(")")
if (startIndex !== -1 && endIndex !== -1) {
return info.substring(startIndex + 1, endIndex)
}
return info
}
// 点击处理 // 点击处理
TapHandler { TapHandler {
acceptedButtons: Qt.LeftButton acceptedButtons: Qt.LeftButton
@@ -220,7 +330,6 @@ AppletItem {
driverPopup.close() driverPopup.close()
} else { } else {
Panel.requestClosePopup() Panel.requestClosePopup()
// 在打开前设置定位,确保弹窗出现在插件附近
const point = root.mapToItem(null, root.width / 2, root.height / 2) const point = root.mapToItem(null, root.width / 2, root.height / 2)
driverPopup.DockPanelPositioner.bounding = Qt.rect(point.x, point.y, driverPopup.width, driverPopup.height) driverPopup.DockPanelPositioner.bounding = Qt.rect(point.x, point.y, driverPopup.width, driverPopup.height)
driverPopup.open() driverPopup.open()
@@ -228,18 +337,4 @@ AppletItem {
toolTip.close() toolTip.close()
} }
} }
// 后端信号处理
Connections {
target: root.applet
function onInstallSuccess() {
console.log("Install succeeded")
}
function onInstallFailed(error) {
console.log("Install failed:", error)
}
function onRequestReboot() {
console.log("Reboot requested")
}
}
} }
@@ -10,8 +10,8 @@
</message> </message>
<message> <message>
<location filename="../package/driverview.qml"/> <location filename="../package/driverview.qml"/>
<source>Graphics Driver: </source> <source>No GPU detected</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../package/driverview.qml"/> <location filename="../package/driverview.qml"/>
@@ -20,43 +20,13 @@
</message> </message>
<message> <message>
<location filename="../package/driverview.qml"/> <location filename="../package/driverview.qml"/>
<source>Driver service is not available</source> <source>Current Driver:</source>
<translation></translation>
</message>
<message>
<location filename="../package/driverview.qml"/>
<source>Device Information</source>
<translation></translation>
</message>
<message>
<location filename="../package/driverview.qml"/>
<source>Current Driver: </source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../package/driverview.qml"/>
<source>Device: </source>
<translation></translation>
</message>
<message> <message>
<location filename="../package/driverview.qml"/> <location filename="../package/driverview.qml"/>
<source>Refresh</source> <source>Refresh</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../package/driverview.qml"/>
<source>Test Install</source>
<translation></translation>
</message>
<message>
<location filename="../package/driverview.qml"/>
<source>Installing... </source>
<translation>...</translation>
</message>
<message>
<location filename="../package/driverview.qml"/>
<source>Cancel</source>
<translation></translation>
</message>
</context> </context>
</TS> </TS>
@@ -10,8 +10,8 @@
</message> </message>
<message> <message>
<location filename="../package/driverview.qml"/> <location filename="../package/driverview.qml"/>
<source>Graphics Driver: </source> <source>No GPU detected</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../package/driverview.qml"/> <location filename="../package/driverview.qml"/>
@@ -20,43 +20,13 @@
</message> </message>
<message> <message>
<location filename="../package/driverview.qml"/> <location filename="../package/driverview.qml"/>
<source>Driver service is not available</source> <source>Current Driver:</source>
<translation></translation>
</message>
<message>
<location filename="../package/driverview.qml"/>
<source>Device Information</source>
<translation></translation>
</message>
<message>
<location filename="../package/driverview.qml"/>
<source>Current Driver: </source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../package/driverview.qml"/>
<source>Device: </source>
<translation></translation>
</message>
<message> <message>
<location filename="../package/driverview.qml"/> <location filename="../package/driverview.qml"/>
<source>Refresh</source> <source>Refresh</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../package/driverview.qml"/>
<source>Test Install</source>
<translation></translation>
</message>
<message>
<location filename="../package/driverview.qml"/>
<source>Installing... </source>
<translation>...</translation>
</message>
<message>
<location filename="../package/driverview.qml"/>
<source>Cancel</source>
<translation></translation>
</message>
</context> </context>
</TS> </TS>