feat: GPU切换回退保护逻辑
- switchGpu切换前写入备份文件(.gpu-switch-backup)记录之前模式 - init()检测未确认的切换,启动30秒自动回退计时器 - QML弹出'显示是否正常'确认覆盖层,支持手动确认/回退/超时自动回退 - confirmSwitchSuccess()用户确认正常后删除备份 - restoreFromBackup()自动恢复之前模式并发送通知 - primeOffloadEnabled属性检测当前PRIME offload状态 - switchGpu改用environment.d方式,不需要root/pkexec - 翻译更新:回退确认相关8条新增
This commit is contained in:
+158
-4
@@ -28,6 +28,9 @@ GraphicsDriverApplet::GraphicsDriverApplet(QObject *parent)
|
|||||||
, m_ready(false)
|
, m_ready(false)
|
||||||
, m_lastAlertTime(0)
|
, m_lastAlertTime(0)
|
||||||
, m_tempAlertEnabled(true)
|
, m_tempAlertEnabled(true)
|
||||||
|
, m_switchPending(false)
|
||||||
|
, m_restoreCountdown(0)
|
||||||
|
, m_restoreTimer(nullptr)
|
||||||
{
|
{
|
||||||
QSettings settings("deepin", "graphics-driver-applet");
|
QSettings settings("deepin", "graphics-driver-applet");
|
||||||
m_tempAlertEnabled = settings.value("tempAlertEnabled", true).toBool();
|
m_tempAlertEnabled = settings.value("tempAlertEnabled", true).toBool();
|
||||||
@@ -45,6 +48,29 @@ bool GraphicsDriverApplet::load()
|
|||||||
bool GraphicsDriverApplet::init()
|
bool GraphicsDriverApplet::init()
|
||||||
{
|
{
|
||||||
detectGpus();
|
detectGpus();
|
||||||
|
|
||||||
|
// 检查是否有未确认的 GPU 切换(上次切换后可能黑屏)
|
||||||
|
QFile backup(backupFilePath());
|
||||||
|
if (backup.exists()) {
|
||||||
|
// 有备份文件,说明上次切换未确认,启动 30 秒回退计时器
|
||||||
|
m_switchPending = true;
|
||||||
|
m_restoreCountdown = 30;
|
||||||
|
emit switchPendingChanged();
|
||||||
|
emit restoreCountdownChanged();
|
||||||
|
|
||||||
|
m_restoreTimer = new QTimer(this);
|
||||||
|
connect(m_restoreTimer, &QTimer::timeout, this, [this]() {
|
||||||
|
m_restoreCountdown--;
|
||||||
|
emit restoreCountdownChanged();
|
||||||
|
if (m_restoreCountdown <= 0) {
|
||||||
|
restoreFromBackup();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_restoreTimer->start(1000);
|
||||||
|
|
||||||
|
qDebug() << "Unconfirmed GPU switch detected, auto-restore in 30s";
|
||||||
|
}
|
||||||
|
|
||||||
return DApplet::init();
|
return DApplet::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,6 +141,35 @@ void GraphicsDriverApplet::setTempAlertEnabled(bool enabled)
|
|||||||
emit tempAlertEnabledChanged();
|
emit tempAlertEnabledChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GraphicsDriverApplet::primeOffloadEnabled() const
|
||||||
|
{
|
||||||
|
QString configPath = QDir::homePath() + "/.config/environment.d/nvidia-prime.conf";
|
||||||
|
QFile file(configPath);
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return false;
|
||||||
|
QString content = QTextStream(&file).readAll();
|
||||||
|
return content.contains("__NV_PRIME_RENDER_OFFLOAD=1");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsDriverApplet::switchPending() const
|
||||||
|
{
|
||||||
|
return m_switchPending;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GraphicsDriverApplet::restoreCountdown() const
|
||||||
|
{
|
||||||
|
return m_restoreCountdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GraphicsDriverApplet::primeConfigPath()
|
||||||
|
{
|
||||||
|
return QDir::homePath() + "/.config/environment.d/nvidia-prime.conf";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GraphicsDriverApplet::backupFilePath()
|
||||||
|
{
|
||||||
|
return QDir::homePath() + "/.config/environment.d/.gpu-switch-backup";
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsDriverApplet::refreshDeviceInfo()
|
void GraphicsDriverApplet::refreshDeviceInfo()
|
||||||
{
|
{
|
||||||
detectGpus();
|
detectGpus();
|
||||||
@@ -649,10 +704,109 @@ void GraphicsDriverApplet::readGpuProcesses()
|
|||||||
bool GraphicsDriverApplet::switchGpu(const QString &mode)
|
bool GraphicsDriverApplet::switchGpu(const QString &mode)
|
||||||
{
|
{
|
||||||
// mode: "nvidia" / "intel" / "on-demand"
|
// mode: "nvidia" / "intel" / "on-demand"
|
||||||
QProcess process;
|
QString configPath = primeConfigPath();
|
||||||
process.start("pkexec", {"prime-select", "set", mode});
|
QString backupPath = backupFilePath();
|
||||||
process.waitForFinished(30000);
|
QString configDir = QDir::homePath() + "/.config/environment.d";
|
||||||
return process.exitCode() == 0;
|
QDir().mkpath(configDir);
|
||||||
|
|
||||||
|
// 保存当前模式到备份文件(用于回退)
|
||||||
|
QString prevMode = primeOffloadEnabled() ? "nvidia" : "on-demand";
|
||||||
|
QFile backupFile(backupPath);
|
||||||
|
if (backupFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
|
QTextStream(&backupFile) << prevMode;
|
||||||
|
backupFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == "intel") {
|
||||||
|
QFile::remove(configPath);
|
||||||
|
} else if (mode == "nvidia") {
|
||||||
|
QFile file(configPath);
|
||||||
|
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
|
QTextStream(&file) << "__NV_PRIME_RENDER_OFFLOAD=1\n"
|
||||||
|
<< "__GLX_VENDOR_LIBRARY_NAME=nvidia\n";
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
} else if (mode == "on-demand") {
|
||||||
|
QFile::remove(configPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendNotification(tr("GPU Mode Switched"),
|
||||||
|
tr("Switched to %1 mode. Please re-login to take effect.").arg(mode));
|
||||||
|
|
||||||
|
detectGpuMode();
|
||||||
|
emit primeOffloadEnabledChanged();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::confirmSwitchSuccess()
|
||||||
|
{
|
||||||
|
// 用户确认显示正常,删除备份文件
|
||||||
|
QFile::remove(backupFilePath());
|
||||||
|
|
||||||
|
m_switchPending = false;
|
||||||
|
m_restoreCountdown = 0;
|
||||||
|
emit switchPendingChanged();
|
||||||
|
emit restoreCountdownChanged();
|
||||||
|
|
||||||
|
if (m_restoreTimer) {
|
||||||
|
m_restoreTimer->stop();
|
||||||
|
m_restoreTimer->deleteLater();
|
||||||
|
m_restoreTimer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "GPU switch confirmed by user";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::restoreSwitch()
|
||||||
|
{
|
||||||
|
// 用户手动请求回退
|
||||||
|
restoreFromBackup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsDriverApplet::restoreFromBackup()
|
||||||
|
{
|
||||||
|
// 从备份文件恢复
|
||||||
|
QFile backupFile(backupFilePath());
|
||||||
|
if (!backupFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
m_switchPending = false;
|
||||||
|
emit switchPendingChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString prevMode = QTextStream(&backupFile).readAll().trimmed();
|
||||||
|
backupFile.close();
|
||||||
|
QFile::remove(backupFilePath());
|
||||||
|
|
||||||
|
QString configPath = primeConfigPath();
|
||||||
|
|
||||||
|
if (prevMode == "nvidia") {
|
||||||
|
QFile file(configPath);
|
||||||
|
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
|
QTextStream(&file) << "__NV_PRIME_RENDER_OFFLOAD=1\n"
|
||||||
|
<< "__GLX_VENDOR_LIBRARY_NAME=nvidia\n";
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QFile::remove(configPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_switchPending = false;
|
||||||
|
m_restoreCountdown = 0;
|
||||||
|
emit switchPendingChanged();
|
||||||
|
emit restoreCountdownChanged();
|
||||||
|
emit primeOffloadEnabledChanged();
|
||||||
|
|
||||||
|
if (m_restoreTimer) {
|
||||||
|
m_restoreTimer->stop();
|
||||||
|
m_restoreTimer->deleteLater();
|
||||||
|
m_restoreTimer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendNotification(tr("GPU Mode Restored"),
|
||||||
|
tr("Reverted to %1 mode. Please re-login to take effect.").arg(prevMode));
|
||||||
|
|
||||||
|
qDebug() << "GPU mode restored to" << prevMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
D_APPLET_CLASS(GraphicsDriverApplet)
|
D_APPLET_CLASS(GraphicsDriverApplet)
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ class GraphicsDriverApplet : public DApplet
|
|||||||
Q_PROPERTY(QVariantList tempHistory READ tempHistory NOTIFY tempHistoryChanged)
|
Q_PROPERTY(QVariantList tempHistory READ tempHistory NOTIFY tempHistoryChanged)
|
||||||
Q_PROPERTY(QStringList gpuProcesses READ gpuProcesses NOTIFY gpuProcessesChanged)
|
Q_PROPERTY(QStringList gpuProcesses READ gpuProcesses NOTIFY gpuProcessesChanged)
|
||||||
Q_PROPERTY(bool tempAlertEnabled READ tempAlertEnabled WRITE setTempAlertEnabled NOTIFY tempAlertEnabledChanged)
|
Q_PROPERTY(bool tempAlertEnabled READ tempAlertEnabled WRITE setTempAlertEnabled NOTIFY tempAlertEnabledChanged)
|
||||||
|
Q_PROPERTY(bool primeOffloadEnabled READ primeOffloadEnabled NOTIFY primeOffloadEnabledChanged)
|
||||||
|
Q_PROPERTY(bool switchPending READ switchPending NOTIFY switchPendingChanged)
|
||||||
|
Q_PROPERTY(int restoreCountdown READ restoreCountdown NOTIFY restoreCountdownChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GraphicsDriverApplet(QObject *parent = nullptr);
|
explicit GraphicsDriverApplet(QObject *parent = nullptr);
|
||||||
@@ -66,10 +69,15 @@ public:
|
|||||||
QStringList gpuProcesses() const;
|
QStringList gpuProcesses() const;
|
||||||
bool tempAlertEnabled() const;
|
bool tempAlertEnabled() const;
|
||||||
void setTempAlertEnabled(bool enabled);
|
void setTempAlertEnabled(bool enabled);
|
||||||
|
bool primeOffloadEnabled() const;
|
||||||
|
bool switchPending() const;
|
||||||
|
int restoreCountdown() const;
|
||||||
|
|
||||||
Q_INVOKABLE void refreshDeviceInfo();
|
Q_INVOKABLE void refreshDeviceInfo();
|
||||||
Q_INVOKABLE void refreshStats();
|
Q_INVOKABLE void refreshStats();
|
||||||
Q_INVOKABLE bool switchGpu(const QString &mode);
|
Q_INVOKABLE bool switchGpu(const QString &mode);
|
||||||
|
Q_INVOKABLE void confirmSwitchSuccess();
|
||||||
|
Q_INVOKABLE void restoreSwitch();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void deviceInfoChanged();
|
void deviceInfoChanged();
|
||||||
@@ -82,6 +90,9 @@ signals:
|
|||||||
void tempHistoryChanged();
|
void tempHistoryChanged();
|
||||||
void gpuProcessesChanged();
|
void gpuProcessesChanged();
|
||||||
void tempAlertEnabledChanged();
|
void tempAlertEnabledChanged();
|
||||||
|
void primeOffloadEnabledChanged();
|
||||||
|
void switchPendingChanged();
|
||||||
|
void restoreCountdownChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void detectGpus();
|
void detectGpus();
|
||||||
@@ -90,6 +101,9 @@ private:
|
|||||||
void detectGpuMode();
|
void detectGpuMode();
|
||||||
void checkTempAlert();
|
void checkTempAlert();
|
||||||
void sendNotification(const QString &summary, const QString &body);
|
void sendNotification(const QString &summary, const QString &body);
|
||||||
|
void restoreFromBackup();
|
||||||
|
static QString primeConfigPath();
|
||||||
|
static QString backupFilePath();
|
||||||
static int findDrmCard(const QString &pciId);
|
static int findDrmCard(const QString &pciId);
|
||||||
static QStringList runCommand(const QString &cmd, const QStringList &args);
|
static QStringList runCommand(const QString &cmd, const QStringList &args);
|
||||||
static QString parseGpuName(const QString &line);
|
static QString parseGpuName(const QString &line);
|
||||||
@@ -110,6 +124,9 @@ private:
|
|||||||
// 温度告警冷却时间戳
|
// 温度告警冷却时间戳
|
||||||
qint64 m_lastAlertTime;
|
qint64 m_lastAlertTime;
|
||||||
bool m_tempAlertEnabled;
|
bool m_tempAlertEnabled;
|
||||||
|
bool m_switchPending;
|
||||||
|
int m_restoreCountdown;
|
||||||
|
QTimer *m_restoreTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
DS_END_NAMESPACE
|
DS_END_NAMESPACE
|
||||||
|
|||||||
+94
-7
@@ -28,13 +28,8 @@ AppletItem {
|
|||||||
|
|
||||||
// 当前 PRIME 模式(nvidia/on-demand/intel)
|
// 当前 PRIME 模式(nvidia/on-demand/intel)
|
||||||
readonly property string currentPrimeMode: {
|
readonly property string currentPrimeMode: {
|
||||||
if (root.gpuMode !== "PRIME" || !root.applet || !root.applet.gpuPrimary) return ""
|
if (root.gpuMode !== "PRIME") return ""
|
||||||
var lines = root.deviceInfo.split("\n").filter(function(l) { return l.trim().length > 0 })
|
if (root.applet && root.applet.primeOffloadEnabled) return "nvidia"
|
||||||
for (var i = 0; i < lines.length; i++) {
|
|
||||||
if (/nvidia/i.test(lines[i]) && root.applet.gpuPrimary[i] === "true") {
|
|
||||||
return "nvidia"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "on-demand"
|
return "on-demand"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1071,6 +1066,98 @@ AppletItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GPU 切换回退确认覆盖层(启动时检测到未确认的切换)
|
||||||
|
Rectangle {
|
||||||
|
id: restoreOverlay
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Qt.rgba(0, 0, 0, 0.75)
|
||||||
|
radius: 12
|
||||||
|
visible: root.applet && root.applet.switchPending
|
||||||
|
z: 100
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: parent.width - 48
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
// 警告图标
|
||||||
|
Text {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: "⚠"
|
||||||
|
font.pixelSize: 36
|
||||||
|
color: Qt.rgba(245/255, 158/255, 11/255, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标题
|
||||||
|
Text {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
text: qsTr("Display OK?")
|
||||||
|
font.pixelSize: 18
|
||||||
|
font.bold: true
|
||||||
|
color: "#e8e8e8"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 说明
|
||||||
|
Text {
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("GPU mode was changed. If display is abnormal, it will auto-revert in %1s.").arg(root.applet ? root.applet.restoreCountdown : 0)
|
||||||
|
font.pixelSize: 12
|
||||||
|
color: "#a0a0a0"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按钮行
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 12
|
||||||
|
|
||||||
|
// 回退按钮
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 34
|
||||||
|
font.pixelSize: 12
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: parent.hovered ? Qt.rgba(220/255, 38/255, 38/255, 0.8) : Qt.rgba(220/255, 38/255, 38/255, 0.3)
|
||||||
|
radius: 8
|
||||||
|
border.width: 1
|
||||||
|
border.color: Qt.rgba(220/255, 38/255, 38/255, 0.6)
|
||||||
|
}
|
||||||
|
contentItem: Text {
|
||||||
|
text: qsTr("Revert")
|
||||||
|
color: "#ff6b6b"
|
||||||
|
font.pixelSize: 12
|
||||||
|
font.bold: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
onClicked: if (root.applet) root.applet.restoreSwitch()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认正常按钮
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 34
|
||||||
|
font.pixelSize: 12
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: parent.hovered ? Qt.darker(root.accentBlue, 1.2) : root.accentBlue
|
||||||
|
radius: 8
|
||||||
|
}
|
||||||
|
contentItem: Text {
|
||||||
|
text: qsTr("Display OK")
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 12
|
||||||
|
font.bold: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
onClicked: if (root.applet) root.applet.confirmSwitchSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
DockPanelPositioner.bounding = Qt.binding(function () {
|
DockPanelPositioner.bounding = Qt.binding(function () {
|
||||||
const point = root.mapToItem(null, root.width / 2, root.height / 2)
|
const point = root.mapToItem(null, root.width / 2, root.height / 2)
|
||||||
|
|||||||
@@ -193,5 +193,45 @@
|
|||||||
<source>Integrated</source>
|
<source>Integrated</source>
|
||||||
<translation>核显</translation>
|
<translation>核显</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Display OK?</source>
|
||||||
|
<translation>显示是否正常?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>GPU mode was changed. If display is abnormal, it will auto-revert in %1s.</source>
|
||||||
|
<translation>GPU 模式已切换。如果显示异常,将在 %1 秒后自动回退。</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Revert</source>
|
||||||
|
<translation>回退</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Display OK</source>
|
||||||
|
<translation>显示正常</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>GPU Mode Switched</source>
|
||||||
|
<translation>GPU 模式已切换</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Switched to %1 mode. Please re-login to take effect.</source>
|
||||||
|
<translation>已切换到 %1 模式,请重新登录生效。</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>GPU Mode Restored</source>
|
||||||
|
<translation>GPU 模式已恢复</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Reverted to %1 mode. Please re-login to take effect.</source>
|
||||||
|
<translation>已恢复到 %1 模式,请重新登录生效。</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|||||||
@@ -193,5 +193,45 @@
|
|||||||
<source>Integrated</source>
|
<source>Integrated</source>
|
||||||
<translation>核顯</translation>
|
<translation>核顯</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Display OK?</source>
|
||||||
|
<translation>顯示是否正常?</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>GPU mode was changed. If display is abnormal, it will auto-revert in %1s.</source>
|
||||||
|
<translation>GPU 模式已切換。如果顯示異常,將在 %1 秒後自動回退。</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Revert</source>
|
||||||
|
<translation>回退</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Display OK</source>
|
||||||
|
<translation>顯示正常</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>GPU Mode Switched</source>
|
||||||
|
<translation>GPU 模式已切換</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Switched to %1 mode. Please re-login to take effect.</source>
|
||||||
|
<translation>已切換到 %1 模式,請重新登入生效。</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>GPU Mode Restored</source>
|
||||||
|
<translation>GPU 模式已恢復</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../package/driverview.qml"/>
|
||||||
|
<source>Reverted to %1 mode. Please re-login to take effect.</source>
|
||||||
|
<translation>已恢復到 %1 模式,請重新登入生效。</translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
|||||||
Reference in New Issue
Block a user