feat: GPU切换确认弹窗、按钮选中状态、文字对比度优化
- GPU切换按钮:核显厂商自动识别(AMD/Intel),当前模式高亮选中 - 切换确认覆盖层:15秒倒计时圆环,确认/取消按钮,超时自动取消 - 文字对比度提升:primaryText 0.95, secondaryText 0.8, tertiaryText 0.65 - 图表刻度文字 0.25->0.5,网格线 0.06->0.1 - 删除卡片内频率/功耗/风扇行,驱动名版本号两端对齐 - 卡片高度78,进度条宽度180,弹窗宽度480 - 翻译更新:切换确认相关8条新增
This commit is contained in:
+249
-38
@@ -26,6 +26,55 @@ AppletItem {
|
||||
readonly property string currentDriver: applet ? (applet.currentDriver || qsTr("Unknown")) : qsTr("Unknown")
|
||||
readonly property string gpuMode: applet ? (applet.gpuMode || "") : ""
|
||||
|
||||
// 当前 PRIME 模式(nvidia/on-demand/intel)
|
||||
readonly property string currentPrimeMode: {
|
||||
if (root.gpuMode !== "PRIME" || !root.applet || !root.applet.gpuPrimary) return ""
|
||||
var lines = root.deviceInfo.split("\n").filter(function(l) { return l.trim().length > 0 })
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
if (/nvidia/i.test(lines[i]) && root.applet.gpuPrimary[i] === "true") {
|
||||
return "nvidia"
|
||||
}
|
||||
}
|
||||
return "on-demand"
|
||||
}
|
||||
|
||||
// GPU 切换确认
|
||||
property string pendingSwitchMode: ""
|
||||
property int switchCountdown: 15
|
||||
|
||||
// 切换模式描述
|
||||
function switchModeDesc(mode) {
|
||||
if (mode === "nvidia") return qsTr("Switch to NVIDIA discrete GPU for maximum performance. Higher power consumption.")
|
||||
if (mode === "intel") return qsTr("Switch to integrated GPU for power saving. NVIDIA GPU will be disabled.")
|
||||
if (mode === "on-demand") return qsTr("Hybrid mode: integrated GPU for display, NVIDIA for on-demand rendering.")
|
||||
return ""
|
||||
}
|
||||
|
||||
function switchModeLabel(mode) {
|
||||
if (mode === "nvidia") return "NVIDIA"
|
||||
if (mode === "intel") return getIgpuVendorName()
|
||||
if (mode === "on-demand") return qsTr("On-Demand")
|
||||
return mode
|
||||
}
|
||||
|
||||
function requestSwitch(mode) {
|
||||
root.pendingSwitchMode = mode
|
||||
root.switchCountdown = 15
|
||||
switchConfirmTimer.start()
|
||||
}
|
||||
|
||||
function confirmSwitch() {
|
||||
if (root.pendingSwitchMode && root.applet) {
|
||||
root.applet.switchGpu(root.pendingSwitchMode)
|
||||
}
|
||||
cancelSwitch()
|
||||
}
|
||||
|
||||
function cancelSwitch() {
|
||||
root.pendingSwitchMode = ""
|
||||
switchConfirmTimer.stop()
|
||||
}
|
||||
|
||||
// 所有 GPU 中的最高温度,用于任务栏图标变色
|
||||
readonly property int maxTemp: {
|
||||
if (!applet || !applet.gpuStats) return -1
|
||||
@@ -45,9 +94,9 @@ AppletItem {
|
||||
}
|
||||
|
||||
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 primaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.95)
|
||||
readonly property color secondaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.8)
|
||||
readonly property color tertiaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.65)
|
||||
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(20 / 255, 80 / 255, 160 / 255, 1)
|
||||
@@ -92,6 +141,19 @@ AppletItem {
|
||||
}
|
||||
}
|
||||
|
||||
// 切换确认倒计时
|
||||
Timer {
|
||||
id: switchConfirmTimer
|
||||
interval: 1000
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
root.switchCountdown--
|
||||
if (root.switchCountdown <= 0) {
|
||||
root.cancelSwitch()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: toolTipShowTimer
|
||||
interval: 50
|
||||
@@ -522,7 +584,7 @@ AppletItem {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredWidth: 140
|
||||
Layout.preferredWidth: 180
|
||||
height: 4
|
||||
color: root.cardBorder
|
||||
radius: 2
|
||||
@@ -667,12 +729,12 @@ AppletItem {
|
||||
|
||||
// 1. 绘制网格线和刻度
|
||||
ctx.font = "9px sans-serif"
|
||||
ctx.fillStyle = Qt.rgba(1, 1, 1, 0.25)
|
||||
ctx.fillStyle = Qt.rgba(1, 1, 1, 0.5)
|
||||
var temps = [40, 60, 80]
|
||||
for (var ti = 0; ti < temps.length; ti++) {
|
||||
var t = temps[ti]
|
||||
var y = h - ((t - minT) / (maxT - minT)) * (h - pad * 2) - pad
|
||||
ctx.strokeStyle = Qt.rgba(1, 1, 1, 0.06)
|
||||
ctx.strokeStyle = Qt.rgba(1, 1, 1, 0.1)
|
||||
ctx.lineWidth = 1
|
||||
ctx.setLineDash(t === 80 ? [3, 3] : [])
|
||||
ctx.beginPath()
|
||||
@@ -806,67 +868,204 @@ AppletItem {
|
||||
spacing: 8
|
||||
visible: root.gpuMode === "PRIME"
|
||||
|
||||
// 核显按钮
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 30
|
||||
Layout.preferredHeight: 32
|
||||
font.pixelSize: 11
|
||||
text: qsTr("NVIDIA")
|
||||
text: getIgpuVendorName()
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? root.accentBlueLight : root.cardBackground
|
||||
color: root.currentPrimeMode === "intel" ? root.accentBlue : (parent.hovered ? root.accentBlueLight : root.cardBackground)
|
||||
radius: 6
|
||||
border.width: 1
|
||||
border.color: root.cardBorder
|
||||
border.color: root.currentPrimeMode === "intel" ? root.accentBlue : root.cardBorder
|
||||
}
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: root.accentBlue
|
||||
color: root.currentPrimeMode === "intel" ? "white" : root.accentBlue
|
||||
font.pixelSize: 11
|
||||
font.bold: root.currentPrimeMode === "intel"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
onClicked: if (root.applet) root.applet.switchGpu("nvidia")
|
||||
onClicked: root.requestSwitch("intel")
|
||||
}
|
||||
|
||||
// 按需按钮
|
||||
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
|
||||
Layout.preferredHeight: 32
|
||||
font.pixelSize: 11
|
||||
text: qsTr("On-Demand")
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? root.accentBlueLight : root.cardBackground
|
||||
color: root.currentPrimeMode === "on-demand" ? root.accentBlue : (parent.hovered ? root.accentBlueLight : root.cardBackground)
|
||||
radius: 6
|
||||
border.width: 1
|
||||
border.color: root.cardBorder
|
||||
border.color: root.currentPrimeMode === "on-demand" ? root.accentBlue : root.cardBorder
|
||||
}
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: root.accentBlue
|
||||
color: root.currentPrimeMode === "on-demand" ? "white" : root.accentBlue
|
||||
font.pixelSize: 11
|
||||
font.bold: root.currentPrimeMode === "on-demand"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
onClicked: if (root.applet) root.applet.switchGpu("on-demand")
|
||||
onClicked: root.requestSwitch("on-demand")
|
||||
}
|
||||
|
||||
// NVIDIA 按钮
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 32
|
||||
font.pixelSize: 11
|
||||
text: qsTr("NVIDIA")
|
||||
|
||||
background: Rectangle {
|
||||
color: root.currentPrimeMode === "nvidia" ? root.accentBlue : (parent.hovered ? root.accentBlueLight : root.cardBackground)
|
||||
radius: 6
|
||||
border.width: 1
|
||||
border.color: root.currentPrimeMode === "nvidia" ? root.accentBlue : root.cardBorder
|
||||
}
|
||||
contentItem: Text {
|
||||
text: parent.text
|
||||
color: root.currentPrimeMode === "nvidia" ? "white" : root.accentBlue
|
||||
font.pixelSize: 11
|
||||
font.bold: root.currentPrimeMode === "nvidia"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
onClicked: root.requestSwitch("nvidia")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GPU 切换确认覆盖层
|
||||
Rectangle {
|
||||
id: switchOverlay
|
||||
anchors.fill: parent
|
||||
color: Qt.rgba(0, 0, 0, 0.7)
|
||||
radius: 12
|
||||
visible: root.pendingSwitchMode.length > 0
|
||||
z: 100
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - 48
|
||||
spacing: 16
|
||||
|
||||
// 模式标题
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: qsTr("Switch to") + " " + switchModeLabel(root.pendingSwitchMode)
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
color: "#e8e8e8"
|
||||
}
|
||||
|
||||
// 模式描述
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
text: switchModeDesc(root.pendingSwitchMode)
|
||||
font.pixelSize: 12
|
||||
color: "#a0a0a0"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
// 倒计时圆环
|
||||
Item {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
width: 64
|
||||
height: 64
|
||||
|
||||
// 背景圆环
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 32
|
||||
color: "transparent"
|
||||
border.width: 3
|
||||
border.color: Qt.rgba(1, 1, 1, 0.1)
|
||||
}
|
||||
|
||||
// 进度圆环
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 32
|
||||
color: "transparent"
|
||||
border.width: 3
|
||||
border.color: root.accentBlue
|
||||
// 用 ConicGradient 效果模拟进度(简化用 opacity)
|
||||
opacity: root.switchCountdown / 15
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 1000 }
|
||||
}
|
||||
}
|
||||
|
||||
// 倒计时数字
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: root.switchCountdown
|
||||
font.pixelSize: 24
|
||||
font.bold: true
|
||||
color: "#e8e8e8"
|
||||
}
|
||||
}
|
||||
|
||||
// 提示文字
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: qsTr("Auto-cancel if not confirmed")
|
||||
font.pixelSize: 10
|
||||
color: "#666666"
|
||||
}
|
||||
|
||||
// 按钮行
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: 12
|
||||
|
||||
// 取消按钮
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 34
|
||||
font.pixelSize: 12
|
||||
|
||||
background: Rectangle {
|
||||
color: parent.hovered ? Qt.rgba(1, 1, 1, 0.1) : Qt.rgba(1, 1, 1, 0.05)
|
||||
radius: 8
|
||||
border.width: 1
|
||||
border.color: Qt.rgba(1, 1, 1, 0.15)
|
||||
}
|
||||
contentItem: Text {
|
||||
text: qsTr("Cancel")
|
||||
color: "#cccccc"
|
||||
font.pixelSize: 12
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
onClicked: root.cancelSwitch()
|
||||
}
|
||||
|
||||
// 确认按钮
|
||||
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("Confirm")
|
||||
color: "white"
|
||||
font.pixelSize: 12
|
||||
font.bold: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
onClicked: root.confirmSwitch()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -928,6 +1127,18 @@ AppletItem {
|
||||
return "GPU"
|
||||
}
|
||||
|
||||
// 获取核显厂商简称
|
||||
function getIgpuVendorName() {
|
||||
if (!root.ready) return qsTr("Integrated")
|
||||
var lines = root.deviceInfo.split("\n").filter(function(l) { return l.trim().length > 0 })
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
if (!/nvidia/i.test(lines[i])) {
|
||||
return parseGpuVendorShort(lines[i])
|
||||
}
|
||||
}
|
||||
return qsTr("Integrated")
|
||||
}
|
||||
|
||||
// 构建 tooltip 文本
|
||||
function buildToolTipText() {
|
||||
if (!root.applet || !root.applet.gpuStats) {
|
||||
|
||||
@@ -153,5 +153,45 @@
|
||||
<source>Temperature Trend</source>
|
||||
<translation>温度趋势</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Switch to</source>
|
||||
<translation>切换到</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Switch to NVIDIA discrete GPU for maximum performance. Higher power consumption.</source>
|
||||
<translation>切换到 NVIDIA 独显以获得最高性能,功耗较高。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Switch to integrated GPU for power saving. NVIDIA GPU will be disabled.</source>
|
||||
<translation>切换到核显以节省功耗,NVIDIA 独显将被禁用。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Hybrid mode: integrated GPU for display, NVIDIA for on-demand rendering.</source>
|
||||
<translation>混合模式:核显负责显示,NVIDIA 按需渲染。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Auto-cancel if not confirmed</source>
|
||||
<translation>未确认将自动取消</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Cancel</source>
|
||||
<translation>取消</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Confirm</source>
|
||||
<translation>确认</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Integrated</source>
|
||||
<translation>核显</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
||||
@@ -153,5 +153,45 @@
|
||||
<source>Temperature Trend</source>
|
||||
<translation>溫度趨勢</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Switch to</source>
|
||||
<translation>切換到</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Switch to NVIDIA discrete GPU for maximum performance. Higher power consumption.</source>
|
||||
<translation>切換到 NVIDIA 獨顯以獲得最高性能,功耗較高。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Switch to integrated GPU for power saving. NVIDIA GPU will be disabled.</source>
|
||||
<translation>切換到核顯以節省功耗,NVIDIA 獨顯將被禁用。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Hybrid mode: integrated GPU for display, NVIDIA for on-demand rendering.</source>
|
||||
<translation>混合模式:核顯負責顯示,NVIDIA 按需渲染。</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Auto-cancel if not confirmed</source>
|
||||
<translation>未確認將自動取消</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Cancel</source>
|
||||
<translation>取消</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Confirm</source>
|
||||
<translation>確認</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../package/driverview.qml"/>
|
||||
<source>Integrated</source>
|
||||
<translation>核顯</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
||||
Reference in New Issue
Block a user