feat: 添加GPU频率/功耗/风扇监控、温度告警、趋势图、右键菜单、进程列表、GPU切换
第二、三阶段功能: 数据增强(第一阶段): - GPU频率: NVIDIA nvidia-smi clocks.gr, Intel gt/gt0/rps_act_freq_mhz - 显存频率: NVIDIA nvidia-smi clocks.mem - 功耗: NVIDIA nvidia-smi power.draw, AMD hwmon power1_average - 风扇转速: NVIDIA nvidia-smi fan.speed, AMD hwmon fan1_input - 任务栏图标根据最高温度变色(≥80°C红/≥60°C橙) - readGpuStats 每次刷新前重置统计字段,避免残留旧值 交互提升(第二阶段): - 温度告警: GPU温度≥80°C时通过D-Bus发送桌面通知,30秒冷却 - 右键菜单: 使用Qt.labs.platform原生菜单+MenuHelper,支持刷新和GPU切换 - 迷你趋势图: Canvas绘制近60秒温度走势折线 - 英文翻译: 新增en.ts,23条全部翻译 高级功能(第三阶段): - NVIDIA进程列表: nvidia-smi --query-compute-apps查询,弹框中显示进程名和显存占用 - GPU切换: pkexec prime-select set <mode>,弹框按钮+右键菜单,仅PRIME模式显示 其他改进: - 自定义深色主题tooltip替代系统默认白色tooltip - 第一张卡片tooltip显示在下方避免被裁剪 - CMakeLists.txt lupdate添加C++源文件提取tr()翻译 - gpuStats格式扩展为9字段: temp|gpuUsage|memUsage|memUsed|memTotal|gpuClock|memClock|powerDraw|fanSpeed
This commit is contained in:
+4
-1
@@ -24,25 +24,28 @@ set(TRANSLATIONS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/translations)
|
||||
set(TS_FILES
|
||||
${TRANSLATIONS_DIR}/${PLUGIN_ID}_zh_CN.ts
|
||||
${TRANSLATIONS_DIR}/${PLUGIN_ID}_zh_TW.ts
|
||||
${TRANSLATIONS_DIR}/${PLUGIN_ID}_en.ts
|
||||
)
|
||||
|
||||
# 生成 .qm 编译翻译文件
|
||||
set(QM_FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_ID}_zh_CN.qm
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_ID}_zh_TW.qm
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_ID}_en.qm
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${QM_FILES}
|
||||
COMMAND /usr/lib/qt6/bin/lrelease ${TRANSLATIONS_DIR}/${PLUGIN_ID}_zh_CN.ts -qm ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_ID}_zh_CN.qm
|
||||
COMMAND /usr/lib/qt6/bin/lrelease ${TRANSLATIONS_DIR}/${PLUGIN_ID}_zh_TW.ts -qm ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_ID}_zh_TW.qm
|
||||
COMMAND /usr/lib/qt6/bin/lrelease ${TRANSLATIONS_DIR}/${PLUGIN_ID}_en.ts -qm ${CMAKE_CURRENT_BINARY_DIR}/${PLUGIN_ID}_en.qm
|
||||
DEPENDS ${TS_FILES}
|
||||
COMMENT "Compiling translations to .qm files"
|
||||
)
|
||||
|
||||
# 手动更新翻译源文件(不加入 ALL,仅在需要时手动 make update_translations)
|
||||
add_custom_target(update_translations
|
||||
COMMAND /usr/lib/qt6/bin/lupdate ${CMAKE_CURRENT_SOURCE_DIR}/package -ts ${TS_FILES}
|
||||
COMMAND /usr/lib/qt6/bin/lupdate ${CMAKE_CURRENT_SOURCE_DIR}/package ${CMAKE_CURRENT_SOURCE_DIR}/graphicsdriverapplet.cpp -ts ${TS_FILES}
|
||||
COMMENT "Updating translation source files"
|
||||
)
|
||||
|
||||
|
||||
+178
-6
@@ -12,6 +12,10 @@
|
||||
#include <QTextStream>
|
||||
#include <QRegularExpression>
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusMessage>
|
||||
#include <QVariantList>
|
||||
|
||||
DCORE_USE_NAMESPACE
|
||||
|
||||
@@ -20,6 +24,7 @@ DS_BEGIN_NAMESPACE
|
||||
GraphicsDriverApplet::GraphicsDriverApplet(QObject *parent)
|
||||
: DApplet(parent)
|
||||
, m_ready(false)
|
||||
, m_lastAlertTime(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -73,6 +78,24 @@ QStringList GraphicsDriverApplet::gpuPrimary() const
|
||||
return m_gpuPrimary;
|
||||
}
|
||||
|
||||
QVariantList GraphicsDriverApplet::tempHistory() const
|
||||
{
|
||||
QVariantList result;
|
||||
for (const QList<int> &history : m_tempHistory) {
|
||||
QVariantList gpuHistory;
|
||||
for (int temp : history) {
|
||||
gpuHistory << temp;
|
||||
}
|
||||
result << QVariant(gpuHistory);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QStringList GraphicsDriverApplet::gpuProcesses() const
|
||||
{
|
||||
return m_gpuProcesses;
|
||||
}
|
||||
|
||||
void GraphicsDriverApplet::refreshDeviceInfo()
|
||||
{
|
||||
detectGpus();
|
||||
@@ -86,6 +109,7 @@ void GraphicsDriverApplet::refreshStats()
|
||||
void GraphicsDriverApplet::detectGpus()
|
||||
{
|
||||
m_gpus.clear();
|
||||
m_tempHistory.clear();
|
||||
|
||||
// 通过 lspci 检测显卡
|
||||
QStringList lines = runCommand("lspci", {"-mm"});
|
||||
@@ -103,6 +127,10 @@ void GraphicsDriverApplet::detectGpus()
|
||||
gpu.memUsage = -1;
|
||||
gpu.memTotal = -1;
|
||||
gpu.memUsed = -1;
|
||||
gpu.gpuClock = -1;
|
||||
gpu.memClock = -1;
|
||||
gpu.powerDraw = -1;
|
||||
gpu.fanSpeed = -1;
|
||||
|
||||
// lspci -mm 格式: "Class" "Vendor" "Device" ...
|
||||
// 提取 PCI ID(行首的 01:00.0 等)
|
||||
@@ -326,10 +354,11 @@ int GraphicsDriverApplet::findDrmCard(const QString &pciId)
|
||||
void GraphicsDriverApplet::readGpuStats()
|
||||
{
|
||||
// 先处理 NVIDIA GPU(单次 nvidia-smi 调用获取所有 NVIDIA GPU 数据)
|
||||
// nvidia-smi 输出格式: pci.bus_id,temperature.gpu,utilization.gpu,utilization.memory,memory.total,memory.used
|
||||
// nvidia-smi 输出格式: pci.bus_id,temperature.gpu,utilization.gpu,utilization.memory,
|
||||
// memory.total,memory.used,clocks.gr,clocks.mem,power.draw,fan.speed
|
||||
QMap<QString, QStringList> nvidiaData; // pciId -> stats
|
||||
QStringList nvLines = runCommand("nvidia-smi", {
|
||||
"--query-gpu=pci.bus_id,temperature.gpu,utilization.gpu,utilization.memory,memory.total,memory.used",
|
||||
"--query-gpu=pci.bus_id,temperature.gpu,utilization.gpu,utilization.memory,memory.total,memory.used,clocks.gr,clocks.mem,power.draw,fan.speed",
|
||||
"--format=csv,noheader,nounits"
|
||||
});
|
||||
for (const QString &line : nvLines) {
|
||||
@@ -344,6 +373,17 @@ void GraphicsDriverApplet::readGpuStats()
|
||||
|
||||
// 逐个 GPU 读取统计
|
||||
for (GpuInfo &gpu : m_gpus) {
|
||||
// 每次刷新前重置实时统计字段,确保数据源不可用时不会残留旧值
|
||||
gpu.temperature = -1;
|
||||
gpu.gpuUsage = -1;
|
||||
gpu.memUsage = -1;
|
||||
gpu.memTotal = -1;
|
||||
gpu.memUsed = -1;
|
||||
gpu.gpuClock = -1;
|
||||
gpu.memClock = -1;
|
||||
gpu.powerDraw = -1;
|
||||
gpu.fanSpeed = -1;
|
||||
|
||||
if (gpu.driver == "nvidia" && nvidiaData.contains(gpu.pciId)) {
|
||||
// NVIDIA: 使用 nvidia-smi 数据
|
||||
QStringList &parts = nvidiaData[gpu.pciId];
|
||||
@@ -352,6 +392,19 @@ void GraphicsDriverApplet::readGpuStats()
|
||||
gpu.memUsage = parts[3].trimmed().toInt();
|
||||
gpu.memTotal = parts[4].trimmed().toInt();
|
||||
gpu.memUsed = parts[5].trimmed().toInt();
|
||||
// 频率 (parts[6]=GPU, parts[7]=显存)
|
||||
if (parts.size() > 6) gpu.gpuClock = parts[6].trimmed().toInt();
|
||||
if (parts.size() > 7) gpu.memClock = parts[7].trimmed().toInt();
|
||||
// 功耗 (parts[8]),[N/A] 时保持 -1
|
||||
if (parts.size() > 8) {
|
||||
QString pwr = parts[8].trimmed();
|
||||
if (pwr != "[N/A]" && !pwr.isEmpty()) gpu.powerDraw = pwr.toDouble();
|
||||
}
|
||||
// 风扇转速 (parts[9]),[N/A] 时保持 -1
|
||||
if (parts.size() > 9) {
|
||||
QString fan = parts[9].trimmed();
|
||||
if (fan != "[N/A]" && !fan.isEmpty()) gpu.fanSpeed = fan.toInt();
|
||||
}
|
||||
} else if (gpu.drmCard >= 0) {
|
||||
// AMD / Intel / 其他: 使用 sysfs
|
||||
QString cardPath = QString("/sys/class/drm/card%1/device").arg(gpu.drmCard);
|
||||
@@ -384,16 +437,36 @@ void GraphicsDriverApplet::readGpuStats()
|
||||
if (nameFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QString name = QTextStream(&nameFile).readAll().trimmed();
|
||||
if (name == gpu.driver || name == "amdgpu" || name == "radeon") {
|
||||
QFile tempFile(hwmonDir.absoluteFilePath(hwmon + "/temp1_input"));
|
||||
QString hwmonPath = hwmonDir.absoluteFilePath(hwmon);
|
||||
// 温度
|
||||
QFile tempFile(hwmonPath + "/temp1_input");
|
||||
if (tempFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
int tempMilli = QTextStream(&tempFile).readAll().trimmed().toInt();
|
||||
gpu.temperature = tempMilli / 1000;
|
||||
}
|
||||
// 功耗 (µW -> W)
|
||||
QFile powerFile(hwmonPath + "/power1_average");
|
||||
if (powerFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qint64 microWatts = QTextStream(&powerFile).readAll().trimmed().toLongLong();
|
||||
gpu.powerDraw = microWatts / 1000000.0;
|
||||
}
|
||||
// 风扇转速 (RPM)
|
||||
QFile fanFile(hwmonPath + "/fan1_input");
|
||||
if (fanFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
gpu.fanSpeed = QTextStream(&fanFile).readAll().trimmed().toInt();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GPU 频率: Intel i915 使用 gt/gt0/rps_act_freq_mhz,AMD 使用 hwmon freq1_input
|
||||
QString gtPath = QString("/sys/class/drm/card%1/gt/gt0/rps_act_freq_mhz").arg(gpu.drmCard);
|
||||
QFile gtFreqFile(gtPath);
|
||||
if (gtFreqFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
gpu.gpuClock = QTextStream(>FreqFile).readAll().trimmed().toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// --- 以下为 Intel 核显等无 hwmon/vram sysfs 接口时的回退逻辑 ---
|
||||
@@ -443,18 +516,117 @@ void GraphicsDriverApplet::readGpuStats()
|
||||
}
|
||||
}
|
||||
|
||||
// 生成统计数据 (格式: temp|gpuUsage|memUsage|memUsed|memTotal)
|
||||
// 生成统计数据 (格式: temp|gpuUsage|memUsage|memUsed|memTotal|gpuClock|memClock|powerDraw|fanSpeed)
|
||||
m_gpuStats.clear();
|
||||
for (const GpuInfo &gpu : m_gpus) {
|
||||
m_gpuStats << QString("%1|%2|%3|%4|%5")
|
||||
m_gpuStats << QString("%1|%2|%3|%4|%5|%6|%7|%8|%9")
|
||||
.arg(gpu.temperature)
|
||||
.arg(gpu.gpuUsage)
|
||||
.arg(gpu.memUsage)
|
||||
.arg(gpu.memUsed)
|
||||
.arg(gpu.memTotal);
|
||||
.arg(gpu.memTotal)
|
||||
.arg(gpu.gpuClock)
|
||||
.arg(gpu.memClock)
|
||||
.arg(gpu.powerDraw, 0, 'f', 1)
|
||||
.arg(gpu.fanSpeed);
|
||||
}
|
||||
|
||||
emit gpuStatsChanged();
|
||||
|
||||
// 更新温度历史(保留最近 60 个采样点)
|
||||
if (m_tempHistory.size() != m_gpus.size()) {
|
||||
m_tempHistory.resize(m_gpus.size());
|
||||
}
|
||||
for (int i = 0; i < m_gpus.size(); ++i) {
|
||||
m_tempHistory[i].append(m_gpus[i].temperature);
|
||||
if (m_tempHistory[i].size() > 60) {
|
||||
m_tempHistory[i].removeFirst();
|
||||
}
|
||||
}
|
||||
emit tempHistoryChanged();
|
||||
|
||||
// 温度告警检测
|
||||
checkTempAlert();
|
||||
|
||||
// 读取 NVIDIA 进程列表
|
||||
readGpuProcesses();
|
||||
}
|
||||
|
||||
// 温度告警:检测是否有 GPU 温度超过 80°C,30 秒内不重复告警
|
||||
void GraphicsDriverApplet::checkTempAlert()
|
||||
{
|
||||
qint64 now = QDateTime::currentSecsSinceEpoch();
|
||||
if (now - m_lastAlertTime < 30) return;
|
||||
|
||||
for (const GpuInfo &gpu : m_gpus) {
|
||||
if (gpu.temperature >= 80) {
|
||||
sendNotification(
|
||||
tr("GPU Temperature Alert"),
|
||||
tr("%1 temperature reached %2°C, please check cooling")
|
||||
.arg(gpu.name)
|
||||
.arg(gpu.temperature)
|
||||
);
|
||||
m_lastAlertTime = now;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 通过 D-Bus 发送桌面通知
|
||||
void GraphicsDriverApplet::sendNotification(const QString &summary, const QString &body)
|
||||
{
|
||||
QDBusInterface notify("org.freedesktop.Notifications",
|
||||
"/org/freedesktop/Notifications",
|
||||
"org.freedesktop.Notifications",
|
||||
QDBusConnection::sessionBus());
|
||||
if (notify.isValid()) {
|
||||
notify.call("Notify", "dde-shell-graphics-driver", 0u,
|
||||
"dialog-warning", summary, body,
|
||||
QStringList(), QVariantMap(), 5000);
|
||||
}
|
||||
}
|
||||
|
||||
// 读取 NVIDIA GPU 上运行的进程列表
|
||||
void GraphicsDriverApplet::readGpuProcesses()
|
||||
{
|
||||
m_gpuProcesses.clear();
|
||||
|
||||
// 仅当存在 NVIDIA GPU 时查询
|
||||
bool hasNvidia = false;
|
||||
for (const GpuInfo &gpu : m_gpus) {
|
||||
if (gpu.driver == "nvidia") { hasNvidia = true; break; }
|
||||
}
|
||||
if (!hasNvidia) {
|
||||
emit gpuProcessesChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
// nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv,noheader,nounits
|
||||
QStringList lines = runCommand("nvidia-smi", {
|
||||
"--query-compute-apps=pid,process_name,used_memory",
|
||||
"--format=csv,noheader,nounits"
|
||||
});
|
||||
for (const QString &line : lines) {
|
||||
QStringList parts = line.split(",");
|
||||
if (parts.size() >= 3) {
|
||||
m_gpuProcesses << QString("%1|%2|%3")
|
||||
.arg(parts[0].trimmed())
|
||||
.arg(parts[1].trimmed())
|
||||
.arg(parts[2].trimmed());
|
||||
}
|
||||
}
|
||||
|
||||
emit gpuProcessesChanged();
|
||||
}
|
||||
|
||||
// GPU 切换:调用 prime-select 切换 PRIME 模式(需要 polkit 提权)
|
||||
bool GraphicsDriverApplet::switchGpu(const QString &mode)
|
||||
{
|
||||
// mode: "nvidia" / "intel" / "on-demand"
|
||||
QProcess process;
|
||||
process.start("pkexec", {"prime-select", "set", mode});
|
||||
process.waitForFinished(30000);
|
||||
return process.exitCode() == 0;
|
||||
}
|
||||
|
||||
D_APPLET_CLASS(GraphicsDriverApplet)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QVariantList>
|
||||
|
||||
DS_BEGIN_NAMESPACE
|
||||
|
||||
@@ -26,6 +27,10 @@ struct GpuInfo {
|
||||
int memUsage; // 显存使用率 (%),-1 表示不可用
|
||||
int memTotal; // 显存总量 (MB),-1 表示不可用
|
||||
int memUsed; // 显存已用 (MB),-1 表示不可用
|
||||
int gpuClock; // GPU 频率 (MHz),-1 表示不可用
|
||||
int memClock; // 显存频率 (MHz),-1 表示不可用
|
||||
double powerDraw; // 功耗 (W),-1 表示不可用
|
||||
int fanSpeed; // 风扇转速 (%),-1 表示不可用
|
||||
};
|
||||
|
||||
class GraphicsDriverApplet : public DApplet
|
||||
@@ -39,6 +44,8 @@ class GraphicsDriverApplet : public DApplet
|
||||
Q_PROPERTY(QString gpuMode READ gpuMode NOTIFY gpuModeChanged)
|
||||
Q_PROPERTY(QStringList gpuPrimary READ gpuPrimary NOTIFY gpuPrimaryChanged)
|
||||
Q_PROPERTY(bool ready READ ready NOTIFY readyChanged)
|
||||
Q_PROPERTY(QVariantList tempHistory READ tempHistory NOTIFY tempHistoryChanged)
|
||||
Q_PROPERTY(QStringList gpuProcesses READ gpuProcesses NOTIFY gpuProcessesChanged)
|
||||
|
||||
public:
|
||||
explicit GraphicsDriverApplet(QObject *parent = nullptr);
|
||||
@@ -54,9 +61,12 @@ public:
|
||||
QString gpuMode() const;
|
||||
QStringList gpuPrimary() const;
|
||||
bool ready() const;
|
||||
QVariantList tempHistory() const;
|
||||
QStringList gpuProcesses() const;
|
||||
|
||||
Q_INVOKABLE void refreshDeviceInfo();
|
||||
Q_INVOKABLE void refreshStats();
|
||||
Q_INVOKABLE bool switchGpu(const QString &mode);
|
||||
|
||||
signals:
|
||||
void deviceInfoChanged();
|
||||
@@ -66,11 +76,16 @@ signals:
|
||||
void gpuModeChanged();
|
||||
void gpuPrimaryChanged();
|
||||
void readyChanged();
|
||||
void tempHistoryChanged();
|
||||
void gpuProcessesChanged();
|
||||
|
||||
private:
|
||||
void detectGpus();
|
||||
void readGpuStats();
|
||||
void readGpuProcesses();
|
||||
void detectGpuMode();
|
||||
void checkTempAlert();
|
||||
void sendNotification(const QString &summary, const QString &body);
|
||||
static int findDrmCard(const QString &pciId);
|
||||
static QStringList runCommand(const QString &cmd, const QStringList &args);
|
||||
static QString parseGpuName(const QString &line);
|
||||
@@ -84,6 +99,12 @@ private:
|
||||
QString m_gpuMode;
|
||||
QStringList m_gpuPrimary;
|
||||
bool m_ready;
|
||||
// 温度历史:每个 GPU 保留最近 60 个温度采样
|
||||
QVector<QList<int>> m_tempHistory;
|
||||
// NVIDIA 进程列表:每行 "pid|name|usedMemory"
|
||||
QStringList m_gpuProcesses;
|
||||
// 温度告警冷却时间戳
|
||||
qint64 m_lastAlertTime;
|
||||
};
|
||||
|
||||
DS_END_NAMESPACE
|
||||
|
||||
+337
-11
@@ -5,6 +5,7 @@
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import Qt.labs.platform 1.1 as LP
|
||||
import org.deepin.ds 1.0
|
||||
import org.deepin.ds.dock 1.0
|
||||
import org.deepin.dtk 1.0
|
||||
@@ -25,6 +26,24 @@ AppletItem {
|
||||
readonly property string currentDriver: applet ? (applet.currentDriver || qsTr("Unknown")) : qsTr("Unknown")
|
||||
readonly property string gpuMode: applet ? (applet.gpuMode || "") : ""
|
||||
|
||||
// 所有 GPU 中的最高温度,用于任务栏图标变色
|
||||
readonly property int maxTemp: {
|
||||
if (!applet || !applet.gpuStats) return -1
|
||||
var max = -1
|
||||
for (var i = 0; i < applet.gpuStats.length; i++) {
|
||||
var parts = applet.gpuStats[i].split("|")
|
||||
var temp = parseInt(parts[0])
|
||||
if (!isNaN(temp) && temp > max) max = temp
|
||||
}
|
||||
return max
|
||||
}
|
||||
// 图标颜色:温度 >=80 红色,>=60 橙色,否则正常
|
||||
readonly property color iconColor: {
|
||||
if (maxTemp >= 80) return Qt.rgba(220/255, 38/255, 38/255, 1)
|
||||
if (maxTemp >= 60) return Qt.rgba(245/255, 158/255, 11/255, 1)
|
||||
return root.primaryText
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -34,7 +53,7 @@ AppletItem {
|
||||
readonly property color accentBlue: Qt.rgba(20 / 255, 80 / 255, 160 / 255, 1)
|
||||
readonly property color accentBlueLight: Qt.rgba(20 / 255, 80 / 255, 160 / 255, 0.12)
|
||||
|
||||
// 图标区域
|
||||
// 图标区域(根据最高温度变色)
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: dockSize * 0.7
|
||||
@@ -42,14 +61,14 @@ AppletItem {
|
||||
color: "transparent"
|
||||
radius: width * 0.45
|
||||
border.width: 1
|
||||
border.color: root.secondaryText
|
||||
border.color: root.iconColor
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "GPU"
|
||||
font.pixelSize: root.dockSize * 0.22
|
||||
font.bold: true
|
||||
color: root.primaryText
|
||||
color: root.iconColor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +292,7 @@ AppletItem {
|
||||
delegate: Rectangle {
|
||||
id: gpuCard
|
||||
width: gpuColumn.width
|
||||
height: 98
|
||||
height: 120
|
||||
color: root.cardBackground
|
||||
radius: 10
|
||||
border.width: 1
|
||||
@@ -320,12 +339,65 @@ AppletItem {
|
||||
if (temp >= 60) return Qt.rgba(245/255, 158/255, 11/255, 1)
|
||||
return Qt.rgba(22/255, 163/255, 74/255, 1)
|
||||
}
|
||||
property string gpuClockStr: {
|
||||
var parts = statsLine.split("|")
|
||||
var v = parts[5]
|
||||
return v === "-1" || v === "" ? "-" : v
|
||||
}
|
||||
property string memClockStr: {
|
||||
var parts = statsLine.split("|")
|
||||
var v = parts[6]
|
||||
return v === "-1" || v === "" ? "-" : v
|
||||
}
|
||||
property string powerStr: {
|
||||
var parts = statsLine.split("|")
|
||||
var v = parts[7]
|
||||
return v === "-1.0" || v === "" ? "-" : v
|
||||
}
|
||||
property string fanStr: {
|
||||
var parts = statsLine.split("|")
|
||||
var v = parts[8]
|
||||
return v === "-1" || v === "" ? "-" : v
|
||||
}
|
||||
|
||||
ToolTip.text: qsTr("GPU: ") + parseGpuName(modelData) + "\n"
|
||||
+ qsTr("Driver: ") + parseDriverName(modelData) + "\n"
|
||||
+ qsTr("Version: ") + (parseDriverVersion(modelData) || qsTr("Unknown"))
|
||||
ToolTip.visible: cardHover.hovered
|
||||
ToolTip.delay: 300
|
||||
// 自定义深色主题悬浮提示(替代系统默认白色 tooltip)
|
||||
// 第一张卡片 tooltip 显示在下方,避免被弹框顶部裁剪
|
||||
Rectangle {
|
||||
visible: cardHover.hovered
|
||||
anchors.top: index === 0 ? parent.bottom : undefined
|
||||
anchors.topMargin: index === 0 ? 6 : 0
|
||||
anchors.bottom: index === 0 ? undefined : parent.top
|
||||
anchors.bottomMargin: index === 0 ? 0 : 6
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: tooltipContent.implicitWidth + 24
|
||||
height: tooltipContent.implicitHeight + 16
|
||||
color: Qt.rgba(0, 0, 0, 0.85)
|
||||
radius: 8
|
||||
z: 100
|
||||
|
||||
ColumnLayout {
|
||||
id: tooltipContent
|
||||
anchors.centerIn: parent
|
||||
spacing: 3
|
||||
|
||||
Text {
|
||||
text: qsTr("GPU: ") + parseGpuName(modelData)
|
||||
color: "white"
|
||||
font.pixelSize: 11
|
||||
font.bold: true
|
||||
}
|
||||
Text {
|
||||
text: qsTr("Driver: ") + parseDriverName(modelData)
|
||||
color: Qt.rgba(1, 1, 1, 0.65)
|
||||
font.pixelSize: 10
|
||||
}
|
||||
Text {
|
||||
text: qsTr("Version: ") + (parseDriverVersion(modelData) || qsTr("Unknown"))
|
||||
color: Qt.rgba(1, 1, 1, 0.65)
|
||||
font.pixelSize: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
id: cardHover
|
||||
@@ -456,10 +528,96 @@ AppletItem {
|
||||
}
|
||||
|
||||
Text {
|
||||
text: gpuUsageStr !== "—" ? gpuUsageStr + "%" : "—"
|
||||
text: gpuUsageStr !== "-" ? gpuUsageStr + "%" : "-"
|
||||
font.pixelSize: 11
|
||||
color: root.secondaryText
|
||||
font.bold: gpuUsageStr !== "—"
|
||||
font.bold: gpuUsageStr !== "-"
|
||||
}
|
||||
}
|
||||
|
||||
// 频率/功耗/风扇信息行
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 8
|
||||
|
||||
// GPU 频率
|
||||
Text {
|
||||
text: gpuClockStr !== "-" ? gpuClockStr + " MHz" : "-"
|
||||
font.pixelSize: 10
|
||||
color: root.tertiaryText
|
||||
visible: gpuClockStr !== "-"
|
||||
}
|
||||
|
||||
// 功耗
|
||||
Text {
|
||||
text: powerStr !== "-" ? powerStr + " W" : ""
|
||||
font.pixelSize: 10
|
||||
color: root.tertiaryText
|
||||
visible: powerStr !== "-"
|
||||
}
|
||||
|
||||
// 风扇转速
|
||||
Text {
|
||||
text: fanStr !== "-" ? qsTr("Fan") + " " + fanStr + "%" : ""
|
||||
font.pixelSize: 10
|
||||
color: root.tertiaryText
|
||||
visible: fanStr !== "-"
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
// 显存频率
|
||||
Text {
|
||||
text: memClockStr !== "-" ? memClockStr + " MHz" : ""
|
||||
font.pixelSize: 10
|
||||
color: root.tertiaryText
|
||||
visible: memClockStr !== "-"
|
||||
}
|
||||
}
|
||||
|
||||
// 温度趋势迷你图
|
||||
Canvas {
|
||||
id: tempCanvas
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 24
|
||||
visible: {
|
||||
if (!root.applet || !root.applet.tempHistory) return false
|
||||
var h = root.applet.tempHistory[index]
|
||||
return h && h.length > 1
|
||||
}
|
||||
|
||||
onPaint: {
|
||||
var ctx = getContext("2d")
|
||||
ctx.reset()
|
||||
var w = width
|
||||
var h = height
|
||||
if (!root.applet || !root.applet.tempHistory) return
|
||||
var history = root.applet.tempHistory[index]
|
||||
if (!history || history.length < 2) return
|
||||
|
||||
// 有效温度范围 20-100°C
|
||||
var minT = 20, maxT = 100
|
||||
var len = history.length
|
||||
ctx.strokeStyle = gpuCard.tempColor
|
||||
ctx.lineWidth = 1.5
|
||||
ctx.beginPath()
|
||||
for (var i = 0; i < len; i++) {
|
||||
var x = (i / (len - 1)) * w
|
||||
var t = history[i]
|
||||
if (t < 0) t = minT
|
||||
var y = h - ((t - minT) / (maxT - minT)) * h
|
||||
if (y < 0) y = 0
|
||||
if (y > h) y = h
|
||||
if (i === 0) ctx.moveTo(x, y)
|
||||
else ctx.lineTo(x, y)
|
||||
}
|
||||
ctx.stroke()
|
||||
}
|
||||
|
||||
// 温度历史变化时重绘
|
||||
Connections {
|
||||
target: root.applet
|
||||
function onTempHistoryChanged() { tempCanvas.requestPaint() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,6 +655,124 @@ AppletItem {
|
||||
}
|
||||
}
|
||||
|
||||
// NVIDIA 进程列表(仅有进程时显示)
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: processList.implicitHeight + 24
|
||||
color: root.cardBackground
|
||||
radius: 10
|
||||
border.width: 1
|
||||
border.color: root.cardBorder
|
||||
visible: root.applet && root.applet.gpuProcesses && root.applet.gpuProcesses.length > 0
|
||||
|
||||
ColumnLayout {
|
||||
id: processList
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
text: qsTr("GPU Processes")
|
||||
font.pixelSize: 11
|
||||
font.bold: true
|
||||
color: root.secondaryText
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: root.applet ? (root.applet.gpuProcesses || []) : []
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 8
|
||||
|
||||
Text {
|
||||
text: modelData.split("|")[1] || "?"
|
||||
font.pixelSize: 10
|
||||
color: root.primaryText
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
text: (modelData.split("|")[2] || "?") + " MB"
|
||||
font.pixelSize: 10
|
||||
color: root.tertiaryText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GPU 切换按钮(仅 PRIME 模式下显示)
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 8
|
||||
visible: root.gpuMode === "PRIME"
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 30
|
||||
font.pixelSize: 11
|
||||
text: qsTr("NVIDIA")
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? root.accentBlueLight : root.cardBackground
|
||||
radius: 6
|
||||
border.width: 1
|
||||
border.color: root.cardBorder
|
||||
}
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: root.accentBlue
|
||||
font.pixelSize: 11
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
onClicked: if (root.applet) root.applet.switchGpu("nvidia")
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 30
|
||||
font.pixelSize: 11
|
||||
text: qsTr("Intel")
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? root.accentBlueLight : root.cardBackground
|
||||
radius: 6
|
||||
border.width: 1
|
||||
border.color: root.cardBorder
|
||||
}
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: root.accentBlue
|
||||
font.pixelSize: 11
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
onClicked: if (root.applet) root.applet.switchGpu("intel")
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 30
|
||||
font.pixelSize: 11
|
||||
text: qsTr("On-Demand")
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? root.accentBlueLight : root.cardBackground
|
||||
radius: 6
|
||||
border.width: 1
|
||||
border.color: root.cardBorder
|
||||
}
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: root.accentBlue
|
||||
font.pixelSize: 11
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
onClicked: if (root.applet) root.applet.switchGpu("on-demand")
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新按钮
|
||||
Button {
|
||||
id: refreshBtn
|
||||
@@ -626,4 +902,54 @@ AppletItem {
|
||||
toolTip.close()
|
||||
}
|
||||
}
|
||||
|
||||
// 右键菜单(使用 Qt.labs.platform 原生菜单,通过 dock 的 MenuHelper 弹出)
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.RightButton
|
||||
gesturePolicy: TapHandler.ReleaseWithinBounds
|
||||
|
||||
onTapped: {
|
||||
contextMenuLoader.active = true
|
||||
if (contextMenuLoader.item) {
|
||||
MenuHelper.openMenu(contextMenuLoader.item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: contextMenuLoader
|
||||
active: false
|
||||
sourceComponent: LP.Menu {
|
||||
LP.MenuItem {
|
||||
text: qsTr("Refresh")
|
||||
onTriggered: {
|
||||
if (root.applet) root.applet.refreshDeviceInfo()
|
||||
}
|
||||
}
|
||||
|
||||
LP.MenuItem {
|
||||
text: qsTr("Switch to NVIDIA")
|
||||
visible: root.gpuMode === "PRIME"
|
||||
onTriggered: {
|
||||
if (root.applet) root.applet.switchGpu("nvidia")
|
||||
}
|
||||
}
|
||||
|
||||
LP.MenuItem {
|
||||
text: qsTr("Switch to Intel")
|
||||
visible: root.gpuMode === "PRIME"
|
||||
onTriggered: {
|
||||
if (root.applet) root.applet.switchGpu("intel")
|
||||
}
|
||||
}
|
||||
|
||||
LP.MenuItem {
|
||||
text: qsTr("Switch to On-Demand")
|
||||
visible: root.gpuMode === "PRIME"
|
||||
onTriggered: {
|
||||
if (root.applet) root.applet.switchGpu("on-demand")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="en_US">
|
||||
<context>
|
||||
<name>GraphicsDriverApplet</name>
|
||||
<message>
|
||||
<location filename="../graphicsdriverapplet.cpp" line="564"/>
|
||||
<source>GPU Temperature Alert</source>
|
||||
<translation>GPU Temperature Alert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../graphicsdriverapplet.cpp" line="565"/>
|
||||
<source>%1 temperature reached %2°C, please check cooling</source>
|
||||
<translation>%1 temperature reached %2°C, please check cooling</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>driverview</name>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="23"/>
|
||||
<location filename="../package/driverview.qml" line="77"/>
|
||||
<location filename="../package/driverview.qml" line="615"/>
|
||||
<location filename="../package/driverview.qml" line="830"/>
|
||||
<source>No GPU detected</source>
|
||||
<translation>No GPU detected</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="24"/>
|
||||
<location filename="../package/driverview.qml" line="25"/>
|
||||
<location filename="../package/driverview.qml" line="364"/>
|
||||
<location filename="../package/driverview.qml" line="802"/>
|
||||
<source>Unknown</source>
|
||||
<translation>Unknown</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="175"/>
|
||||
<source>Graphics Driver Manager</source>
|
||||
<translation>Graphics Driver Manager</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="198"/>
|
||||
<source>Current Driver:</source>
|
||||
<translation>Current Driver:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="259"/>
|
||||
<source>PRIME mode: the integrated GPU handles display, the discrete GPU renders on demand. 3D apps use PRIME Render Offload to invoke the discrete GPU.</source>
|
||||
<translation>PRIME mode: the integrated GPU handles display, the discrete GPU renders on demand. 3D apps use PRIME Render Offload to invoke the discrete GPU.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="261"/>
|
||||
<source>Bumblebee mode: a legacy dual-GPU solution, now deprecated.</source>
|
||||
<translation>Bumblebee mode: a legacy dual-GPU solution, now deprecated.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="263"/>
|
||||
<source>Solo mode: only one GPU detected.</source>
|
||||
<translation>Solo mode: only one GPU detected.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="265"/>
|
||||
<source>Hybrid mode: dual GPU detected, but no known switching solution found.</source>
|
||||
<translation>Hybrid mode: dual GPU detected, but no known switching solution found.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="362"/>
|
||||
<source>GPU: </source>
|
||||
<translation>GPU: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="363"/>
|
||||
<source>Driver: </source>
|
||||
<translation>Driver: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="364"/>
|
||||
<source>Version: </source>
|
||||
<translation>Version: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="426"/>
|
||||
<source>Primary</source>
|
||||
<translation>Primary</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="527"/>
|
||||
<source>Fan</source>
|
||||
<translation>Fan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="640"/>
|
||||
<source>GPU Processes</source>
|
||||
<translation>GPU Processes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="681"/>
|
||||
<source>NVIDIA</source>
|
||||
<translation>NVIDIA</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="702"/>
|
||||
<source>Intel</source>
|
||||
<translation>Intel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="723"/>
|
||||
<source>On-Demand</source>
|
||||
<translation>On-Demand</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="744"/>
|
||||
<location filename="../package/driverview.qml" line="885"/>
|
||||
<source>Refresh</source>
|
||||
<translation>Refresh</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="892"/>
|
||||
<source>Switch to NVIDIA</source>
|
||||
<translation>Switch to NVIDIA</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="900"/>
|
||||
<source>Switch to Intel</source>
|
||||
<translation>Switch to Intel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="908"/>
|
||||
<source>Switch to On-Demand</source>
|
||||
<translation>Switch to On-Demand</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
@@ -1,72 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="zh_CN">
|
||||
<context>
|
||||
<name>GraphicsDriverApplet</name>
|
||||
<message>
|
||||
<location filename="../graphicsdriverapplet.cpp" line="564"/>
|
||||
<source>GPU Temperature Alert</source>
|
||||
<translation>GPU 温度告警</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../graphicsdriverapplet.cpp" line="565"/>
|
||||
<source>%1 temperature reached %2°C, please check cooling</source>
|
||||
<translation>%1 温度已达 %2°C,请检查散热</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>driverview</name>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="24"/>
|
||||
<location filename="../package/driverview.qml" line="25"/>
|
||||
<location filename="../package/driverview.qml" line="364"/>
|
||||
<location filename="../package/driverview.qml" line="802"/>
|
||||
<source>Unknown</source>
|
||||
<translation>未知</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="23"/>
|
||||
<location filename="../package/driverview.qml" line="77"/>
|
||||
<location filename="../package/driverview.qml" line="615"/>
|
||||
<location filename="../package/driverview.qml" line="830"/>
|
||||
<source>No GPU detected</source>
|
||||
<translation>未检测到显卡</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="175"/>
|
||||
<source>Graphics Driver Manager</source>
|
||||
<translation>显卡驱动管理</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="198"/>
|
||||
<source>Current Driver:</source>
|
||||
<translation>当前驱动:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="640"/>
|
||||
<source>GPU Processes</source>
|
||||
<translation>GPU 进程</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="681"/>
|
||||
<source>NVIDIA</source>
|
||||
<translation>NVIDIA</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="702"/>
|
||||
<source>Intel</source>
|
||||
<translation>Intel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="723"/>
|
||||
<source>On-Demand</source>
|
||||
<translation>按需</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="744"/>
|
||||
<location filename="../package/driverview.qml" line="885"/>
|
||||
<source>Refresh</source>
|
||||
<translation>刷新</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="892"/>
|
||||
<source>Switch to NVIDIA</source>
|
||||
<translation>切换到 NVIDIA</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="900"/>
|
||||
<source>Switch to Intel</source>
|
||||
<translation>切换到 Intel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="908"/>
|
||||
<source>Switch to On-Demand</source>
|
||||
<translation>切换到按需模式</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="362"/>
|
||||
<source>GPU: </source>
|
||||
<translation>显卡名称:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="363"/>
|
||||
<source>Driver: </source>
|
||||
<translation>驱动:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="364"/>
|
||||
<source>Version: </source>
|
||||
<translation>版本号:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="426"/>
|
||||
<source>Primary</source>
|
||||
<translation>主显</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="259"/>
|
||||
<source>PRIME mode: the integrated GPU handles display, the discrete GPU renders on demand. 3D apps use PRIME Render Offload to invoke the discrete GPU.</source>
|
||||
<translation>PRIME 模式:核显负责日常显示,独显按需渲染。运行 3D 应用时通过 PRIME Render Offload 调用独显。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="261"/>
|
||||
<source>Bumblebee mode: a legacy dual-GPU solution, now deprecated.</source>
|
||||
<translation>Bumblebee 模式:旧版双 GPU 方案,已淘汰。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="263"/>
|
||||
<source>Solo mode: only one GPU detected.</source>
|
||||
<translation>Solo 模式:仅检测到一块 GPU。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="265"/>
|
||||
<source>Hybrid mode: dual GPU detected, but no known switching solution found.</source>
|
||||
<translation>Hybrid 模式:检测到双 GPU,但未发现已知切换方案。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="527"/>
|
||||
<source>Fan</source>
|
||||
<translation>风扇</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
||||
@@ -1,72 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="zh_TW">
|
||||
<context>
|
||||
<name>GraphicsDriverApplet</name>
|
||||
<message>
|
||||
<location filename="../graphicsdriverapplet.cpp" line="564"/>
|
||||
<source>GPU Temperature Alert</source>
|
||||
<translation>GPU 溫度警報</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../graphicsdriverapplet.cpp" line="565"/>
|
||||
<source>%1 temperature reached %2°C, please check cooling</source>
|
||||
<translation>%1 溫度已達 %2°C,請檢查散熱</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>driverview</name>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="24"/>
|
||||
<location filename="../package/driverview.qml" line="25"/>
|
||||
<location filename="../package/driverview.qml" line="364"/>
|
||||
<location filename="../package/driverview.qml" line="802"/>
|
||||
<source>Unknown</source>
|
||||
<translation>未知</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="23"/>
|
||||
<location filename="../package/driverview.qml" line="77"/>
|
||||
<location filename="../package/driverview.qml" line="615"/>
|
||||
<location filename="../package/driverview.qml" line="830"/>
|
||||
<source>No GPU detected</source>
|
||||
<translation>未偵測到顯示卡</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="175"/>
|
||||
<source>Graphics Driver Manager</source>
|
||||
<translation>顯示卡驅動管理</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="198"/>
|
||||
<source>Current Driver:</source>
|
||||
<translation>目前驅動:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="640"/>
|
||||
<source>GPU Processes</source>
|
||||
<translation>GPU 行程</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="681"/>
|
||||
<source>NVIDIA</source>
|
||||
<translation>NVIDIA</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="702"/>
|
||||
<source>Intel</source>
|
||||
<translation>Intel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="723"/>
|
||||
<source>On-Demand</source>
|
||||
<translation>按需</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="744"/>
|
||||
<location filename="../package/driverview.qml" line="885"/>
|
||||
<source>Refresh</source>
|
||||
<translation>重新整理</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="892"/>
|
||||
<source>Switch to NVIDIA</source>
|
||||
<translation>切換到 NVIDIA</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="900"/>
|
||||
<source>Switch to Intel</source>
|
||||
<translation>切換到 Intel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="908"/>
|
||||
<source>Switch to On-Demand</source>
|
||||
<translation>切換到按需模式</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="362"/>
|
||||
<source>GPU: </source>
|
||||
<translation>顯示卡名稱:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="363"/>
|
||||
<source>Driver: </source>
|
||||
<translation>驅動:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="364"/>
|
||||
<source>Version: </source>
|
||||
<translation>版本號:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="426"/>
|
||||
<source>Primary</source>
|
||||
<translation>主顯</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="259"/>
|
||||
<source>PRIME mode: the integrated GPU handles display, the discrete GPU renders on demand. 3D apps use PRIME Render Offload to invoke the discrete GPU.</source>
|
||||
<translation>PRIME 模式:核顯負責日常顯示,獨顯按需渲染。運行 3D 應用時通過 PRIME Render Offload 調用獨顯。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="261"/>
|
||||
<source>Bumblebee mode: a legacy dual-GPU solution, now deprecated.</source>
|
||||
<translation>Bumblebee 模式:舊版雙 GPU 方案,已淘汰。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="263"/>
|
||||
<source>Solo mode: only one GPU detected.</source>
|
||||
<translation>Solo 模式:僅偵測到一塊 GPU。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<location filename="../package/driverview.qml" line="265"/>
|
||||
<source>Hybrid mode: dual GPU detected, but no known switching solution found.</source>
|
||||
<translation>Hybrid 模式:偵測到雙 GPU,但未發現已知切換方案。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml" line="527"/>
|
||||
<source>Fan</source>
|
||||
<translation>風扇</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
||||
Reference in New Issue
Block a user