fix: 独立窗口及任务栏图标适配深色模式

4 个独立窗口(AboutWindow/SettingsWindow/TextColorPicker/TrafficChartWindow)
新增 isDarkMode 属性,由 networkview.qml 检测后注入,各窗口定义深/浅双色方案。

深色模式检测从 DockPalette.iconTextPalette 改为 DTK.palette.window.hslLightness,
因 DockPalette 不随系统深色主题变化。

同时将 networkview.qml 任务栏图标和 NetworkPopup 弹窗的颜色基从
DockPalette.iconTextPalette 改为 DTK.palette.windowText,修复深色模式
下黑底黑字、浅色模式下白底白字的问题。
This commit is contained in:
2026-07-24 09:30:18 +08:00
parent 42028d93bd
commit c614df5fbe
7 changed files with 219 additions and 116 deletions
+3 -2
View File
@@ -21,8 +21,9 @@
~~`m_totalDownload = currentRxBytes` 只存储活动接口的当前计数器值,并非真正的累计流量。~~ ~~`m_totalDownload = currentRxBytes` 只存储活动接口的当前计数器值,并非真正的累计流量。~~
已改为累加会话增量 `m_totalDownload += rxDeltaClamped`"总计"语义从"活动接口计数器值"变为"本次会话累计流量":从 0 开始增长,切换网卡不再跳变,网卡重启不归零。跨重启持久化属于 #18 的范畴。 已改为累加会话增量 `m_totalDownload += rxDeltaClamped`"总计"语义从"活动接口计数器值"变为"本次会话累计流量":从 0 开始增长,切换网卡不再跳变,网卡重启不归零。跨重启持久化属于 #18 的范畴。
**4. 独立窗口不支持深色模式** **4. ~~独立窗口不支持深色模式~~ ✅ 已修复**
`AboutWindow.qml``SettingsWindow.qml``TextColorPicker.qml``TrafficChartWindow.qml` 全部硬编码浅色`#FFFFFF``#333333``#f5f5f5` 等),不随系统主题适配。而 `networkview.qml``NetworkPopup.qml` 正确地从 `DockPalette` 派生颜色。deepin 深色模式下这些窗口视觉割裂严重。 ~~`AboutWindow.qml``SettingsWindow.qml``TextColorPicker.qml``TrafficChartWindow.qml` 全部硬编码浅色,不随系统主题适配。~~
已为 4 个独立窗口新增 `isDarkMode` 属性(由 networkview.qml 检测后注入),各窗口定义深/浅双色方案切换。深色模式检测改用 `DTK.palette.window.hslLightness < 0.5`(原 `DockPalette.iconTextPalette` 不随系统主题变化)。同时修复 networkview.qml 任务栏图标和 NetworkPopup 弹窗的颜色基:从 `DockPalette.iconTextPalette` 改为 `DTK.palette.windowText`,解决深色模式黑底黑字问题。
**5. `detectInterfaces()` 过滤规则与 `readNetworkStats()` 不一致** **5. `detectInterfaces()` 过滤规则与 `readNetworkStats()` 不一致**
`init()` 先调 `detectInterfaces()`(读 `/sys/class/net`,仅过滤 `lo`),再调 `readNetworkStats()`(读 `/proc/net/dev`,过滤 `lo`/`veth`/`docker`/`br-`)。首次刷新前,docker/veth 接口会短暂出现在列表中,造成 UI 闪烁。且 `detectInterfaces()` 的结果会被 `readNetworkStats()` 完全覆盖,属于冗余调用。 `init()` 先调 `detectInterfaces()`(读 `/sys/class/net`,仅过滤 `lo`),再调 `readNetworkStats()`(读 `/proc/net/dev`,过滤 `lo`/`veth`/`docker`/`br-`)。首次刷新前,docker/veth 接口会短暂出现在列表中,造成 UI 闪烁。且 `detectInterfaces()` 的结果会被 `readNetworkStats()` 完全覆盖,属于冗余调用。
+36 -22
View File
@@ -3,9 +3,11 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// 关于窗口:DTK 原生风格的独立顶层窗口,桌面居中弹出,展示插件信息 // 关于窗口:DTK 原生风格的独立顶层窗口,桌面居中弹出,展示插件信息
// 设计要点:白色圆角卡片 + 键值对信息布局,信息标签使用 deepin 蓝(#0081FF), // 设计要点:圆角卡片 + 键值对信息布局,信息标签使用 deepin 蓝(#0081FF),
// 关闭按钮 hover 高亮色由父组件通过 accentColor 传入(红色) // 关闭按钮 hover 高亮色由父组件通过 accentColor 传入(红色)
// 对外依赖:accentColor,由 networkview.qml 实例化时传入,触发方式为 show()/raise()/requestActivate() // 深/浅主题由 isDarkMode 切换(networkview.qml 依据 DockPalette 检测任务栏深浅后传入),
// 默认浅色,保证组件独立预览时与原版视觉一致
// 对外依赖:accentColor、isDarkMode,由 networkview.qml 实例化时传入,触发方式为 show()/raise()/requestActivate()
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
import QtQuick.Window 2.15 import QtQuick.Window 2.15
@@ -21,6 +23,18 @@ Window {
// 默认值保证组件独立可用(如 qmlscene 预览时未传入) // 默认值保证组件独立可用(如 qmlscene 预览时未传入)
property string version: "1.0" property string version: "1.0"
// 深色模式标记:由 networkview.qml 根据 DockPalette 检测后传入;
// 默认 false(浅色)保证组件独立预览时与原版视觉一致
property bool isDarkMode: false
// ---- 主题感知颜色:isDarkMode 为 false 时取值与原浅色硬编码完全一致 ----
readonly property color winBg: isDarkMode ? "#202020" : "#FFFFFF"
readonly property color cardBg: isDarkMode ? "#2A2A2A" : "#FFFFFF"
readonly property color lineColor: isDarkMode ? "#383838" : "#E8E8E8"
readonly property color textPrimary: isDarkMode ? "#E0E0E0" : "#333333"
readonly property color textSecondary: isDarkMode ? "#AAAAAA" : "#666666"
readonly property color textTertiary: isDarkMode ? "#888888" : "#999999"
// 复制成功状态标记:true 时复制图标变绿并显示"已复制"提示, // 复制成功状态标记:true 时复制图标变绿并显示"已复制"提示,
// 2 秒后由 copyResetTimer 复位 // 2 秒后由 copyResetTimer 复位
property bool copied: false property bool copied: false
@@ -39,13 +53,13 @@ Window {
} }
} }
// 窗口主体:白色圆角卡片,1px 浅灰边框模拟 DTK 窗口描边 // 窗口主体:圆角卡片(背景与边框随 isDarkMode 切换深浅)1px 边框模拟 DTK 窗口描边
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: "#FFFFFF" color: root.winBg
radius: 12 radius: 12
border.width: 1 border.width: 1
border.color: "#E8E8E8" border.color: root.lineColor
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
@@ -70,7 +84,7 @@ Window {
text: qsTr("关于") text: qsTr("关于")
font.pixelSize: 15 font.pixelSize: 15
font.weight: Font.Bold font.weight: Font.Bold
color: "#333333" color: root.textPrimary
} }
// 关闭按钮:28x28 圆形,hover 时淡红底 + 红色 ×(颜色由 accentColor 决定) // 关闭按钮:28x28 圆形,hover 时淡红底 + 红色 ×(颜色由 accentColor 决定)
@@ -88,7 +102,7 @@ Window {
text: "×" text: "×"
font.pixelSize: 20 font.pixelSize: 20
font.weight: Font.Bold font.weight: Font.Bold
color: aboutCloseMouse.containsMouse ? accentColor : "#666666" color: aboutCloseMouse.containsMouse ? accentColor : root.textSecondary
} }
MouseArea { MouseArea {
@@ -117,7 +131,7 @@ Window {
text: qsTr("网络速度监控") text: qsTr("网络速度监控")
font.pixelSize: 18 font.pixelSize: 18
font.weight: Font.Bold font.weight: Font.Bold
color: "#333333" color: root.textPrimary
Layout.fillWidth: true Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
} }
@@ -125,7 +139,7 @@ Window {
Text { Text {
text: "JNetApplet" text: "JNetApplet"
font.pixelSize: 12 font.pixelSize: 12
color: "#999999" color: root.textTertiary
Layout.fillWidth: true Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
} }
@@ -142,7 +156,7 @@ Window {
Layout.leftMargin: 24 Layout.leftMargin: 24
Layout.rightMargin: 24 Layout.rightMargin: 24
Layout.preferredHeight: 1 Layout.preferredHeight: 1
color: "#E8E8E8" color: root.lineColor
} }
// 信息区上方间距 // 信息区上方间距
@@ -173,7 +187,7 @@ Window {
Text { Text {
text: version text: version
font.pixelSize: 12 font.pixelSize: 12
color: "#333333" color: root.textPrimary
Layout.fillWidth: true Layout.fillWidth: true
} }
} }
@@ -194,7 +208,7 @@ Window {
Text { Text {
text: "Jokul" text: "Jokul"
font.pixelSize: 12 font.pixelSize: 12
color: "#333333" color: root.textPrimary
Layout.fillWidth: true Layout.fillWidth: true
} }
} }
@@ -215,7 +229,7 @@ Window {
Text { Text {
text: qsTr("监控网络速度和流量") text: qsTr("监控网络速度和流量")
font.pixelSize: 12 font.pixelSize: 12
color: "#333333" color: root.textPrimary
Layout.fillWidth: true Layout.fillWidth: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
} }
@@ -237,7 +251,7 @@ Window {
Text { Text {
text: "git.jokul.space/Jokul/JNetApplet" text: "git.jokul.space/Jokul/JNetApplet"
font.pixelSize: 11 font.pixelSize: 11
color: "#999999" color: root.textTertiary
Layout.fillWidth: true Layout.fillWidth: true
wrapMode: Text.WrapAnywhere wrapMode: Text.WrapAnywhere
} }
@@ -248,7 +262,7 @@ Window {
Layout.preferredHeight: 24 Layout.preferredHeight: 24
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
// "已复制"提示:白底绿字小标签,显示在按钮左侧, // "已复制"提示:卡片底色绿字小标签,显示在按钮左侧,
// 覆盖于 URL 文字上方,避免与值文本混排 // 覆盖于 URL 文字上方,避免与值文本混排
Rectangle { Rectangle {
anchors.right: parent.left anchors.right: parent.left
@@ -258,7 +272,7 @@ Window {
width: copiedHintText.implicitWidth + 10 width: copiedHintText.implicitWidth + 10
height: 18 height: 18
radius: 4 radius: 4
color: "#FFFFFF" color: root.cardBg
border.width: 1 border.width: 1
border.color: "#22A34A" border.color: "#22A34A"
@@ -286,7 +300,7 @@ Window {
} }
// 复制图标:两个重叠的小圆角矩形 // 复制图标:两个重叠的小圆角矩形
// 前层矩形白底压住后层边框重叠区,形成"堆叠纸张"的视觉效果 // 前层矩形以卡片底色压住后层边框重叠区,形成"堆叠纸张"的视觉效果
// 后层矩形(向右下偏移 2px // 后层矩形(向右下偏移 2px
Rectangle { Rectangle {
x: 8 x: 8
@@ -294,9 +308,9 @@ Window {
width: 10 width: 10
height: 10 height: 10
radius: 2 radius: 2
color: "#FFFFFF" color: root.cardBg
border.width: 1 border.width: 1
border.color: copyRepoMouse.containsMouse ? "#333333" : "#999999" border.color: copyRepoMouse.containsMouse ? root.textPrimary : root.textTertiary
} }
// 前层矩形(左上),复制成功时边框短暂变绿 // 前层矩形(左上),复制成功时边框短暂变绿
@@ -306,9 +320,9 @@ Window {
width: 10 width: 10
height: 10 height: 10
radius: 2 radius: 2
color: "#FFFFFF" color: root.cardBg
border.width: 1 border.width: 1
border.color: copied ? "#22A34A" : (copyRepoMouse.containsMouse ? "#333333" : "#999999") border.color: copied ? "#22A34A" : (copyRepoMouse.containsMouse ? root.textPrimary : root.textTertiary)
} }
} }
} }
+11 -8
View File
@@ -32,14 +32,17 @@ Control {
readonly property string ipv6Address: applet ? (applet.ipv6Address || "") : "" readonly property string ipv6Address: applet ? (applet.ipv6Address || "") : ""
readonly property var networkInterfaces: applet ? (applet.networkInterfaces || []) : [] readonly property var networkInterfaces: applet ? (applet.networkInterfaces || []) : []
// 弹窗颜色全部派生自 DockPalette.iconTextPalette,与任务栏颜色独立 // 弹窗颜色派生自 DTK 系统调色板(windowText),而非 DockPalette.iconTextPalette
// 设计原因:PanelPopup 不继承 AppletItem 的颜色属性,需要自行派生 // 设计原因:PanelPopup 背景跟随系统主题(深色模式下变黑),但 DockPalette.iconTextPalette
property Palette basePalette: DockPalette.iconTextPalette // 反映的是任务栏图标文字色,不随系统深色主题变化,导致深色模式下弹窗黑底黑字。
readonly property color primaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.95) // DTK.palette.windowText 在深色模式下为浅色文字、浅色模式下为深色文字,与弹窗背景同步。
readonly property color secondaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.80) // 主题切换时 DTK.paletteChanged 信号自动触发属性绑定重新求值。
readonly property color tertiaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.65) readonly property color baseTextColor: DTK.palette.windowText
readonly property color cardBackground: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.06) readonly property color primaryText: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.95)
readonly property color cardBorder: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.10) readonly property color secondaryText: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.80)
readonly property color tertiaryText: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.65)
readonly property color cardBackground: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.06)
readonly property color cardBorder: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.10)
// 强调色:下载蓝、上传绿,是面板的主视觉区分 // 强调色:下载蓝、上传绿,是面板的主视觉区分
readonly property color accentBlue: Qt.rgba(20 / 255, 80 / 255, 160 / 255, 1) readonly property color accentBlue: Qt.rgba(20 / 255, 80 / 255, 160 / 255, 1)
+62 -37
View File
@@ -3,9 +3,12 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// 设置窗口:独立顶层窗口,桌面居中弹出,提供网络接口选择、字体颜色选择、插件卸载功能 // 设置窗口:独立顶层窗口,桌面居中弹出,提供网络接口选择、字体颜色选择、插件卸载功能
// 设计要点:白色圆角卡片 + 自定义标题栏可拖动,接口单选切换,卸载按钮带复制命令功能 // 设计要点:圆角卡片 + 自定义标题栏可拖动,接口单选切换,卸载按钮带复制命令功能
// 深/浅主题由 isDarkMode 切换(networkview.qml 依据 DockPalette 检测任务栏深浅后传入),
// 默认浅色,保证组件独立预览时与原版视觉一致
// 对外依赖:appletC++ 后端对象)、networkInterfaces(接口列表)、activeInterface(当前接口)、 // 对外依赖:appletC++ 后端对象)、networkInterfaces(接口列表)、activeInterface(当前接口)、
// accentColor(强调色),由 networkview.qml 实例化时传入,触发方式为 show()/raise()/requestActivate() // accentColor(强调色)、isDarkMode(深色模式标记),由 networkview.qml 实例化时传入,
// 触发方式为 show()/raise()/requestActivate()
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15 import QtQuick.Layouts 1.15
@@ -27,6 +30,26 @@ Window {
// 默认值与 networkview.qml 中 root.accentRed 一致,确保独立可用 // 默认值与 networkview.qml 中 root.accentRed 一致,确保独立可用
property color accentColor: Qt.rgba(220 / 255, 38 / 255, 38 / 255, 1) property color accentColor: Qt.rgba(220 / 255, 38 / 255, 38 / 255, 1)
// 深色模式标记:由 networkview.qml 根据 DockPalette 检测后传入;
// 默认 false(浅色)保证组件独立预览时与原版视觉一致
property bool isDarkMode: false
// ---- 主题感知颜色:isDarkMode 为 false 时取值与原浅色硬编码完全一致 ----
readonly property color winBg: isDarkMode ? "#202020" : "#F5F5F5"
readonly property color cardBg: isDarkMode ? "#2A2A2A" : "#FFFFFF"
readonly property color lineColor: isDarkMode ? "#383838" : "#E0E0E0"
readonly property color textPrimary: isDarkMode ? "#E0E0E0" : "#333333"
readonly property color textSecondary: isDarkMode ? "#AAAAAA" : "#666666"
readonly property color textTertiary: isDarkMode ? "#888888" : "#999999"
readonly property color iconGray: isDarkMode ? "#AAAAAA" : "#777777"
readonly property color hoverBg: isDarkMode ? "#353535" : "#F0F0F0"
readonly property color codeBg: isDarkMode ? "#2A2A2A" : "#E8E8E8"
// 选中态蓝色系:深色模式下背景压暗、文字改浅蓝,保证深色卡片上的对比度
readonly property color selBg: isDarkMode ? "#1A3A5C" : "#E3F2FD"
readonly property color selBgHover: isDarkMode ? "#1E4A6E" : "#D8ECFD"
readonly property color selBorder: isDarkMode ? "#2C5A8A" : "#90CAF9"
readonly property color selText: isDarkMode ? "#64B5F6" : "#1565C0"
// 卸载按钮文字:复制命令后临时显示提示,定时器到期后还原 // 卸载按钮文字:复制命令后临时显示提示,定时器到期后还原
property string uninstallButtonText: qsTr("卸载插件") property string uninstallButtonText: qsTr("卸载插件")
@@ -82,13 +105,13 @@ Window {
} }
} }
// 主容器:提供不透明背景 + 圆角 + 边框 // 主容器:提供不透明背景(随 isDarkMode 切换深浅)+ 圆角 + 边框
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: "#f5f5f5" color: root.winBg
radius: 12 radius: 12
border.width: 1 border.width: 1
border.color: "#e0e0e0" border.color: root.lineColor
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
@@ -118,7 +141,7 @@ Window {
text: qsTr("设置") text: qsTr("设置")
font.pixelSize: 15 font.pixelSize: 15
font.weight: Font.Bold font.weight: Font.Bold
color: "#333333" color: root.textPrimary
} }
// 关闭按钮 // 关闭按钮
@@ -137,7 +160,7 @@ Window {
text: "×" text: "×"
font.pixelSize: 20 font.pixelSize: 20
font.weight: Font.Bold font.weight: Font.Bold
color: closeMouse.containsMouse ? accentColor : "#666666" color: closeMouse.containsMouse ? accentColor : root.textSecondary
} }
MouseArea { MouseArea {
@@ -154,7 +177,7 @@ Window {
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 1 Layout.preferredHeight: 1
color: "#e0e0e0" color: root.lineColor
} }
// 内容区域 // 内容区域
@@ -172,7 +195,7 @@ Window {
text: qsTr("网络接口") text: qsTr("网络接口")
font.pixelSize: 13 font.pixelSize: 13
font.weight: Font.Bold font.weight: Font.Bold
color: "#666666" color: root.textSecondary
} }
// 接口列表容器:最多显示约 5 行(160px),超出部分垂直滚动 // 接口列表容器:最多显示约 5 行(160px),超出部分垂直滚动
@@ -183,10 +206,10 @@ Window {
Layout.preferredHeight: networkInterfaces.length > 0 Layout.preferredHeight: networkInterfaces.length > 0
? Math.min(ifaceColumn.implicitHeight, 160) + 20 ? Math.min(ifaceColumn.implicitHeight, 160) + 20
: 80 : 80
color: "#ffffff" color: root.cardBg
radius: 10 radius: 10
border.width: 1 border.width: 1
border.color: "#e0e0e0" border.color: root.lineColor
// 用 ScrollView 而非裸 Flickable:自带滚轮滚动支持, // 用 ScrollView 而非裸 Flickable:自带滚轮滚动支持,
// 且滚动条显示时自动让出内容宽度,不会遮挡行内文字 // 且滚动条显示时自动让出内容宽度,不会遮挡行内文字
@@ -200,7 +223,7 @@ Window {
contentWidth: availableWidth contentWidth: availableWidth
// 自定义滚动条样式:与 networkview.qml chip 滚动条一致(4px 圆角矩形), // 自定义滚动条样式:与 networkview.qml chip 滚动条一致(4px 圆角矩形),
// 颜色改用硬编码灰色系适配本窗口浅色主题 // 颜色使用主题感知灰色系(随 isDarkMode 切换深浅)
// AsNeeded 策略保证接口少时不显示滚动条 // AsNeeded 策略保证接口少时不显示滚动条
ScrollBar.vertical: ScrollBar { ScrollBar.vertical: ScrollBar {
id: ifaceScrollBar id: ifaceScrollBar
@@ -210,9 +233,9 @@ Window {
contentItem: Rectangle { contentItem: Rectangle {
implicitWidth: 4 implicitWidth: 4
radius: 2 radius: 2
// 按压/悬停加深、默认稍淡,保证滚动条在白色卡片上可见 // 按压/悬停加深、默认稍淡,保证滚动条在卡片背景上可见
color: ifaceScrollBar.pressed ? "#666666" color: ifaceScrollBar.pressed ? root.textSecondary
: (ifaceScrollBar.hovered ? "#666666" : "#999999") : (ifaceScrollBar.hovered ? root.textSecondary : root.textTertiary)
} }
} }
@@ -224,7 +247,7 @@ Window {
// 接口列表:整行点击切换活动接口 // 接口列表:整行点击切换活动接口
// 行样式:类型图标 + 单选圆点 + 名称 + 右侧类型描述; // 行样式:类型图标 + 单选圆点 + 名称 + 右侧类型描述;
// hover 显示浅灰底,选中行浅蓝底 + 蓝色细边框 // hover 底、选中底与边框颜色均随 isDarkMode 切换深浅
Repeater { Repeater {
model: networkInterfaces model: networkInterfaces
delegate: Rectangle { delegate: Rectangle {
@@ -235,16 +258,16 @@ Window {
// 当前行是否为活动接口(选中态) // 当前行是否为活动接口(选中态)
readonly property bool isActive: modelData === activeInterface readonly property bool isActive: modelData === activeInterface
readonly property bool hovered: rowMouse.containsMouse readonly property bool hovered: rowMouse.containsMouse
// 选中态强调色用 #1565c0(较 #1976d2 更深): // 选中态强调色由 root.selText 提供(浅色 #1565c0 / 深色 #64b5f6):
// 保证 ▢ 等空心图标在浅蓝选中背景上仍有足够对比度 // 保证 ▢ 等空心图标在选中背景上仍有足够对比度
readonly property color activeColor: "#1565c0" readonly property color activeColor: root.selText
// 背景优先级:选中 > hover;选中行 hover 时稍加深以保留交互反馈 // 背景优先级:选中 > hover;选中行 hover 时稍加深以保留交互反馈
color: isActive color: isActive
? (hovered ? "#d8ecfd" : "#e3f2fd") ? (hovered ? root.selBgHover : root.selBg)
: (hovered ? "#f0f0f0" : "transparent") : (hovered ? root.hoverBg : "transparent")
// 选中行加蓝色细边框增强视觉;未选中保持透明边框占位,避免切换时出现 1px 抖动 // 选中行加细边框增强视觉;未选中保持透明边框占位,避免切换时出现 1px 抖动
border.width: 1 border.width: 1
border.color: isActive ? "#90caf9" : "transparent" border.color: isActive ? root.selBorder : "transparent"
// 整行 hover + 点击:行内元素均不处理鼠标事件, // 整行 hover + 点击:行内元素均不处理鼠标事件,
// 点击行任意位置即选中该接口 // 点击行任意位置即选中该接口
@@ -269,7 +292,7 @@ Window {
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
text: interfaceIcon(modelData) text: interfaceIcon(modelData)
font.pixelSize: 14 font.pixelSize: 14
color: ifaceRow.isActive ? ifaceRow.activeColor : "#777777" color: ifaceRow.isActive ? ifaceRow.activeColor : root.iconGray
} }
// 自绘单选圆点:替代 RadioButton 作纯视觉指示器, // 自绘单选圆点:替代 RadioButton 作纯视觉指示器,
@@ -283,7 +306,7 @@ Window {
color: "transparent" color: "transparent"
border.width: 2 border.width: 2
border.color: ifaceRow.isActive ? ifaceRow.activeColor border.color: ifaceRow.isActive ? ifaceRow.activeColor
: (ifaceRow.hovered ? "#666666" : "#999999") : (ifaceRow.hovered ? root.textSecondary : root.textTertiary)
Rectangle { Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
@@ -302,7 +325,7 @@ Window {
text: modelData text: modelData
font.pixelSize: 13 font.pixelSize: 13
font.weight: ifaceRow.isActive ? Font.Medium : Font.Normal font.weight: ifaceRow.isActive ? Font.Medium : Font.Normal
color: ifaceRow.isActive ? ifaceRow.activeColor : "#333333" color: ifaceRow.isActive ? ifaceRow.activeColor : root.textPrimary
elide: Text.ElideRight elide: Text.ElideRight
} }
@@ -311,7 +334,7 @@ Window {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
text: interfaceDescription(modelData) text: interfaceDescription(modelData)
font.pixelSize: 12 font.pixelSize: 12
color: "#999999" color: root.textTertiary
} }
} }
} }
@@ -324,7 +347,7 @@ Window {
anchors.centerIn: parent anchors.centerIn: parent
text: qsTr("未检测到网络接口") text: qsTr("未检测到网络接口")
font.pixelSize: 12 font.pixelSize: 12
color: "#999999" color: root.textTertiary
visible: networkInterfaces.length === 0 visible: networkInterfaces.length === 0
} }
} }
@@ -336,12 +359,14 @@ Window {
text: qsTr("字体颜色") text: qsTr("字体颜色")
font.pixelSize: 13 font.pixelSize: 13
font.weight: Font.Bold font.weight: Font.Bold
color: "#666666" color: root.textSecondary
} }
TextColorPicker { TextColorPicker {
Layout.fillWidth: true Layout.fillWidth: true
currentColor: applet ? applet.textColor : "" currentColor: applet ? applet.textColor : ""
// 深色模式标记向下传递:TextColorPicker 内部色板卡片同样主题感知
isDarkMode: root.isDarkMode
onColorSelected: if (applet) applet.textColor = color onColorSelected: if (applet) applet.textColor = color
} }
@@ -405,10 +430,10 @@ Window {
y: (root.height - height) / 2 y: (root.height - height) / 2
background: Rectangle { background: Rectangle {
color: "#f5f5f5" color: root.winBg
radius: 12 radius: 12
border.width: 1 border.width: 1
border.color: "#e0e0e0" border.color: root.lineColor
} }
contentItem: ColumnLayout { contentItem: ColumnLayout {
@@ -427,7 +452,7 @@ Window {
Text { Text {
text: qsTr("以下命令用于卸载插件并重启 dde-shell,请复制到终端中执行:") text: qsTr("以下命令用于卸载插件并重启 dde-shell,请复制到终端中执行:")
font.pixelSize: 12 font.pixelSize: 12
color: "#333333" color: root.textPrimary
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
@@ -438,7 +463,7 @@ Window {
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 60 Layout.preferredHeight: 60
color: "#e8e8e8" color: root.codeBg
radius: 8 radius: 8
Text { Text {
@@ -447,7 +472,7 @@ Window {
text: "sudo rm -rf /usr/share/dde-shell/space.jokul.JNetApplet/ && systemctl --user restart dde-shell@DDE" text: "sudo rm -rf /usr/share/dde-shell/space.jokul.JNetApplet/ && systemctl --user restart dde-shell@DDE"
font.pixelSize: 10 font.pixelSize: 10
font.family: "monospace" font.family: "monospace"
color: "#666666" color: root.textSecondary
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
} }
} }
@@ -463,16 +488,16 @@ Window {
Rectangle { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 36 Layout.preferredHeight: 36
color: cancelUninstallMouse.containsMouse ? "#f0f0f0" : "#ffffff" color: cancelUninstallMouse.containsMouse ? root.hoverBg : root.cardBg
radius: 8 radius: 8
border.width: 1 border.width: 1
border.color: "#e0e0e0" border.color: root.lineColor
Text { Text {
anchors.centerIn: parent anchors.centerIn: parent
text: qsTr("取消") text: qsTr("取消")
font.pixelSize: 13 font.pixelSize: 13
color: "#333333" color: root.textPrimary
} }
MouseArea { MouseArea {
+30 -14
View File
@@ -3,9 +3,10 @@
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// 字体颜色选择器:用于设置窗口,提供预设色板与"跟随系统"选项 // 字体颜色选择器:用于设置窗口,提供预设色板与"跟随系统"选项
// 设计要点:白色圆角卡片与设置窗口其他分区视觉一致;圆形色块 22x22, // 设计要点:圆角卡片与设置窗口其他分区视觉一致;圆形色块 22x22,
// 当前选中色加 2px 深色边框高亮;点击只发射 colorSelected 信号, // 当前选中色加 2px 边框高亮(颜色随主题切换);点击只发射 colorSelected 信号,
// 由父层(networkview.qml)回写 currentColor 并同步到 C++ 后端持久化 // 由父层(SettingsWindow)回写 currentColor 并同步到 C++ 后端持久化
// 深/浅主题由 isDarkMode 切换(SettingsWindow 传入),默认浅色保证独立预览可用
// 属性语义: // 属性语义:
// currentColor - 当前选中颜色字符串,空串表示"跟随系统"(默认) // currentColor - 当前选中颜色字符串,空串表示"跟随系统"(默认)
// colorSelected(string) - 用户点击色块时发射,参数为空串或 #RRGGBB // colorSelected(string) - 用户点击色块时发射,参数为空串或 #RRGGBB
@@ -27,12 +28,25 @@ Rectangle {
"#16A34A", "#1450A0", "#7C3AED", "#0891B2" "#16A34A", "#1450A0", "#7C3AED", "#0891B2"
] ]
// 深色模式标记:由 SettingsWindow 传入;默认 false(浅色)保证独立预览可用
property bool isDarkMode: false
// ---- 主题感知颜色:isDarkMode 为 false 时取值与原浅色硬编码完全一致 ----
readonly property color cardBg: isDarkMode ? "#2A2A2A" : "#FFFFFF"
readonly property color lineColor: isDarkMode ? "#383838" : "#E0E0E0"
readonly property color ringColor: isDarkMode ? "#E0E0E0" : "#333333"
// "跟随系统"色块底色:深色模式下用比卡片更深的灰保持可辨识
readonly property color systemSwatchBg: isDarkMode ? "#202020" : "#F5F5F5"
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 52 Layout.preferredHeight: 52
color: "#ffffff" color: root.cardBg
radius: 10 radius: 10
border.width: 1 border.width: 1
border.color: "#e0e0e0" border.color: root.lineColor
// Canvas 不随属性绑定自动重绘,主题切换时主动触发"跟随系统"斜线重绘
onIsDarkModeChanged: slashCanvas.requestPaint()
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent
@@ -47,19 +61,20 @@ Rectangle {
height: 26 height: 26
radius: 13 radius: 13
color: "transparent" color: "transparent"
// 当前选中态:2px 深色边框 // 当前选中态:2px 边框高亮(颜色随主题切换)
border.width: root.currentColor === modelData ? 2 : 0 border.width: root.currentColor === modelData ? 2 : 0
border.color: "#333333" border.color: root.ringColor
Rectangle { Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
width: 22 width: 22
height: 22 height: 22
radius: 11 radius: 11
// 白色色块在白卡上需细边框可见 // 白色色块在白卡上需细边框可见;深色模式下深色卡片上的黑色色块同理
color: modelData color: modelData
border.width: modelData === "#FFFFFF" ? 1 : 0 border.width: (modelData === "#FFFFFF"
border.color: "#e0e0e0" || (root.isDarkMode && modelData === "#000000")) ? 1 : 0
border.color: root.lineColor
} }
MouseArea { MouseArea {
@@ -78,24 +93,25 @@ Rectangle {
color: "transparent" color: "transparent"
// currentColor 为空串时高亮(跟随系统选中态) // currentColor 为空串时高亮(跟随系统选中态)
border.width: root.currentColor === "" ? 2 : 0 border.width: root.currentColor === "" ? 2 : 0
border.color: "#333333" border.color: root.ringColor
Rectangle { Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
width: 22 width: 22
height: 22 height: 22
radius: 11 radius: 11
color: "#f5f5f5" color: root.systemSwatchBg
border.width: 1 border.width: 1
border.color: "#e0e0e0" border.color: root.lineColor
// 斜线:表示"无自定义色/跟随系统" // 斜线:表示"无自定义色/跟随系统"
Canvas { Canvas {
id: slashCanvas
anchors.fill: parent anchors.fill: parent
onPaint: { onPaint: {
var ctx = getContext("2d") var ctx = getContext("2d")
ctx.reset() ctx.reset()
ctx.strokeStyle = "#999999" ctx.strokeStyle = root.isDarkMode ? "#888888" : "#999999"
ctx.lineWidth = 2 ctx.lineWidth = 2
ctx.beginPath() ctx.beginPath()
ctx.moveTo(2, height - 2) ctx.moveTo(2, height - 2)
+51 -22
View File
@@ -5,9 +5,11 @@
// 流量波动图窗口:屏幕居中的独立顶层窗口,展示当前活动接口最近 5 分钟的 // 流量波动图窗口:屏幕居中的独立顶层窗口,展示当前活动接口最近 5 分钟的
// 网速趋势(下载/上传双折线图),随 C++ 后端 speedHistoryChanged 信号每秒动态刷新 // 网速趋势(下载/上传双折线图),随 C++ 后端 speedHistoryChanged 信号每秒动态刷新
// 设计要点: // 设计要点:
// - 视觉风格复用 AboutWindow.qml白色圆角卡片 12px、1px #E8E8E8 边框、 // - 视觉风格复用 AboutWindow.qml(圆角卡片 12px、1px 边框、44px 标题栏
// 44px 标题栏、28x28 圆形关闭按钮 hover 淡红底) // 28x28 圆形关闭按钮 hover 淡红底);深/浅主题由 isDarkMode 切换
// - 图表使用纯 QML Canvas 绘制,无 QtCharts 等外部依赖(与项目零依赖风格一致) // networkview.qml 依据 DockPalette 检测任务栏深浅后传入),默认浅色保证独立预览可用
// - 图表使用纯 QML Canvas 绘制,无 QtCharts 等外部依赖(与项目零依赖风格一致);
// Canvas 不随属性绑定自动重绘,isDarkMode 变化时主动 requestPaint()
// - 数据通过属性注入:applet 即 networkview.qml 的 root.appletC++ 后端对象), // - 数据通过属性注入:applet 即 networkview.qml 的 root.appletC++ 后端对象),
// 为 null 时组件可独立预览(Canvas 显示"暂无历史数据"空状态) // 为 null 时组件可独立预览(Canvas 显示"暂无历史数据"空状态)
// 触发方式:右键菜单"流量波动图" -> show()/raise()/requestActivate() // 触发方式:右键菜单"流量波动图" -> show()/raise()/requestActivate()
@@ -28,6 +30,27 @@ Window {
// 为 null 时组件可独立预览(显示空状态),所有数据访问处均需做空值兜底 // 为 null 时组件可独立预览(显示空状态),所有数据访问处均需做空值兜底
property var applet: null property var applet: null
// 深色模式标记:由 networkview.qml 根据 DockPalette 检测后传入;
// 默认 false(浅色)保证组件独立预览时与原版视觉一致
property bool isDarkMode: false
// ---- 主题感知颜色:isDarkMode 为 false 时取值与原浅色硬编码完全一致 ----
readonly property color winBg: isDarkMode ? "#202020" : "#FFFFFF"
readonly property color lineColor: isDarkMode ? "#383838" : "#E8E8E8"
readonly property color textPrimary: isDarkMode ? "#E0E0E0" : "#333333"
readonly property color textSecondary: isDarkMode ? "#AAAAAA" : "#666666"
readonly property color textTertiary: isDarkMode ? "#888888" : "#999999"
// 置顶按钮 hover 底色:浅色用淡黑、深色用淡白,保证两种卡片背景上均可见
readonly property color pinHoverBg: isDarkMode ? Qt.rgba(1, 1, 1, 0.10) : Qt.rgba(0, 0, 0, 0.06)
// 图表绘制色:声明为 string 供 Canvas 2D 上下文直接使用
//QML color 类型含 alpha 时序列化为 #AARRGGBBCanvas 无法正确解析,故不用 color 类型)
readonly property string gridBaselineColor: isDarkMode ? "#383838" : "#DDDDDD"
readonly property string gridLineColor: isDarkMode ? "#2A2A2A" : "#E5E5E5"
readonly property string axisTextColor: isDarkMode ? "#888888" : "#999999"
readonly property string hoverLineColor: isDarkMode ? "#555555" : "#BBBBBB"
readonly property string dotCoreColor: isDarkMode ? "#202020" : "#FFFFFF"
// Hover 状态:当前悬停采样点在历史缓冲中的索引,-1 表示无悬停 // Hover 状态:当前悬停采样点在历史缓冲中的索引,-1 表示无悬停
// 由图表区 MouseArea 根据 mouseX 反查最近采样点更新;Canvas 据此绘制 // 由图表区 MouseArea 根据 mouseX 反查最近采样点更新;Canvas 据此绘制
// 竖直辅助线与圆点标记,底部提示条据此显示该时刻数值 // 竖直辅助线与圆点标记,底部提示条据此显示该时刻数值
@@ -44,6 +67,12 @@ Window {
// 置顶状态变化时重绘图钉图标(未置顶=灰色轮廓,置顶=蓝色填充) // 置顶状态变化时重绘图钉图标(未置顶=灰色轮廓,置顶=蓝色填充)
onPinnedChanged: pinIcon.requestPaint() onPinnedChanged: pinIcon.requestPaint()
// 主题切换时重绘图表与图钉图标:Canvas 不随属性绑定自动重绘,需主动触发
onIsDarkModeChanged: {
pinIcon.requestPaint()
canvas.requestPaint()
}
// 下载折线颜色(绿)与上传折线颜色(橙),与规范 §4.4 一致 // 下载折线颜色(绿)与上传折线颜色(橙),与规范 §4.4 一致
readonly property color downloadLineColor: "#34C759" readonly property color downloadLineColor: "#34C759"
readonly property color uploadLineColor: "#FF9500" readonly property color uploadLineColor: "#FF9500"
@@ -118,13 +147,13 @@ Window {
return s + " " + unit.suffix return s + " " + unit.suffix
} }
// 窗口主体:白色圆角卡片,1px 浅灰边框模拟 DTK 窗口描边(与 AboutWindow 一致) // 窗口主体:圆角卡片(背景与边框随 isDarkMode 切换深浅),1px 边框模拟 DTK 窗口描边(与 AboutWindow 一致)
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
color: "#FFFFFF" color: root.winBg
radius: 12 radius: 12
border.width: 1 border.width: 1
border.color: "#E8E8E8" border.color: root.lineColor
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
@@ -153,7 +182,7 @@ Window {
text: qsTr("流量波动图") text: qsTr("流量波动图")
font.pixelSize: 15 font.pixelSize: 15
font.weight: Font.Bold font.weight: Font.Bold
color: "#333333" color: root.textPrimary
} }
// 置顶按钮:28x28 圆形(与关闭按钮一致),位于关闭按钮左侧 // 置顶按钮:28x28 圆形(与关闭按钮一致),位于关闭按钮左侧
@@ -167,7 +196,7 @@ Window {
height: 28 height: 28
radius: 14 radius: 14
color: root.pinned ? Qt.rgba(0, 129 / 255, 1, 0.12) color: root.pinned ? Qt.rgba(0, 129 / 255, 1, 0.12)
: (pinMouse.containsMouse ? Qt.rgba(0, 0, 0, 0.06) : "transparent") : (pinMouse.containsMouse ? root.pinHoverBg : "transparent")
// 置顶图标:Canvas 绘制"上箭头触顶"(⤒ 风格)——向上箭头指向顶部横杠, // 置顶图标:Canvas 绘制"上箭头触顶"(⤒ 风格)——向上箭头指向顶部横杠,
// 是"置顶/移到顶部"最通用的视觉语言,与关闭按钮"×"形态区分明显 // 是"置顶/移到顶部"最通用的视觉语言,与关闭按钮"×"形态区分明显
@@ -181,7 +210,7 @@ Window {
onPaint: { onPaint: {
var ctx = getContext("2d") var ctx = getContext("2d")
ctx.clearRect(0, 0, width, height) ctx.clearRect(0, 0, width, height)
var c = root.pinned ? "#0081FF" : "#999999" var c = root.pinned ? "#0081FF" : root.axisTextColor
ctx.strokeStyle = c ctx.strokeStyle = c
ctx.fillStyle = c ctx.fillStyle = c
ctx.lineCap = "round" ctx.lineCap = "round"
@@ -246,7 +275,7 @@ Window {
text: "×" text: "×"
font.pixelSize: 20 font.pixelSize: 20
font.weight: Font.Bold font.weight: Font.Bold
color: chartCloseMouse.containsMouse ? root.accentColor : "#666666" color: chartCloseMouse.containsMouse ? root.accentColor : root.textSecondary
} }
MouseArea { MouseArea {
@@ -279,7 +308,7 @@ Window {
// applet 为空时兜底为 0,保证独立预览不报错 // applet 为空时兜底为 0,保证独立预览不报错
text: root.formatSpeed(root.applet ? root.applet.downloadSpeed : 0) text: root.formatSpeed(root.applet ? root.applet.downloadSpeed : 0)
font.pixelSize: 12 font.pixelSize: 12
color: "#333333" color: root.textPrimary
} }
Item { Layout.preferredWidth: 10 } Item { Layout.preferredWidth: 10 }
@@ -294,7 +323,7 @@ Window {
Text { Text {
text: root.formatSpeed(root.applet ? root.applet.uploadSpeed : 0) text: root.formatSpeed(root.applet ? root.applet.uploadSpeed : 0)
font.pixelSize: 12 font.pixelSize: 12
color: "#333333" color: root.textPrimary
} }
Item { Layout.fillWidth: true } Item { Layout.fillWidth: true }
@@ -303,7 +332,7 @@ Window {
text: (root.applet && root.applet.activeInterface text: (root.applet && root.applet.activeInterface
? root.applet.activeInterface : "—") + " · 5min" ? root.applet.activeInterface : "—") + " · 5min"
font.pixelSize: 12 font.pixelSize: 12
color: "#999999" color: root.textTertiary
} }
} }
@@ -362,15 +391,15 @@ Window {
for (g = 0; g <= 4; g++) { for (g = 0; g <= 4; g++) {
gy = pt + ph - (ph * g / 4) gy = pt + ph - (ph * g / 4)
// +0.5 让 1px 线条落在像素边界上,避免抗锯齿发虚 // +0.5 让 1px 线条落在像素边界上,避免抗锯齿发虚
// 基线(g=0)略深一档,其余 4 条网格线用规范色 #E5E5E5 // 基线(g=0)略深一档;网格与刻度颜色均随 isDarkMode 切换深浅
ctx.strokeStyle = g === 0 ? "#DDDDDD" : "#E5E5E5" ctx.strokeStyle = g === 0 ? root.gridBaselineColor : root.gridLineColor
ctx.lineWidth = 1 ctx.lineWidth = 1
ctx.beginPath() ctx.beginPath()
ctx.moveTo(pl, gy + 0.5) ctx.moveTo(pl, gy + 0.5)
ctx.lineTo(pl + pw, gy + 0.5) ctx.lineTo(pl + pw, gy + 0.5)
ctx.stroke() ctx.stroke()
// 刻度标签右对齐于绘图区左侧 // 刻度标签右对齐于绘图区左侧
ctx.fillStyle = "#999999" ctx.fillStyle = root.axisTextColor
ctx.textAlign = "right" ctx.textAlign = "right"
ctx.fillText(root.formatAxisValue(yMax * g / 4, unit), pl - 8, gy) ctx.fillText(root.formatAxisValue(yMax * g / 4, unit), pl - 8, gy)
} }
@@ -379,7 +408,7 @@ Window {
// 5 分钟窗口用 -5m/-4m/-3m/-2m/-1m/now 共 6 个标签,比 4 个三分点 // 5 分钟窗口用 -5m/-4m/-3m/-2m/-1m/now 共 6 个标签,比 4 个三分点
// 的 -3m20s/-1m40s 更易读;循环按数组长度参数化,两端左/右对齐 // 的 -3m20s/-1m40s 更易读;循环按数组长度参数化,两端左/右对齐
var xLabels = ["-5m", "-4m", "-3m", "-2m", "-1m", "now"] var xLabels = ["-5m", "-4m", "-3m", "-2m", "-1m", "now"]
ctx.fillStyle = "#999999" ctx.fillStyle = root.axisTextColor
ctx.textBaseline = "alphabetic" ctx.textBaseline = "alphabetic"
for (i = 0; i < xLabels.length; i++) { for (i = 0; i < xLabels.length; i++) {
var lx = pl + pw * i / (xLabels.length - 1) var lx = pl + pw * i / (xLabels.length - 1)
@@ -390,7 +419,7 @@ Window {
// ---- 空状态:画完空网格后中央提示,不画折线(规范 §5)---- // ---- 空状态:画完空网格后中央提示,不画折线(规范 §5)----
if (n === 0) { if (n === 0) {
ctx.fillStyle = "#999999" ctx.fillStyle = root.axisTextColor
ctx.font = "13px sans-serif" ctx.font = "13px sans-serif"
ctx.textAlign = "center" ctx.textAlign = "center"
ctx.textBaseline = "middle" ctx.textBaseline = "middle"
@@ -466,7 +495,7 @@ Window {
if (hi >= 0 && hi < n) { if (hi >= 0 && hi < n) {
var hx = pl + ((dl[hi].x - tMin) / tRange) * pw var hx = pl + ((dl[hi].x - tMin) / tRange) * pw
// 竖直辅助线:虚线,避免与实线折线混淆 // 竖直辅助线:虚线,避免与实线折线混淆
ctx.strokeStyle = "#BBBBBB" ctx.strokeStyle = root.hoverLineColor
ctx.lineWidth = 1 ctx.lineWidth = 1
ctx.setLineDash([4, 3]) ctx.setLineDash([4, 3])
ctx.beginPath() ctx.beginPath()
@@ -474,12 +503,12 @@ Window {
ctx.lineTo(hx, pt + ph) ctx.lineTo(hx, pt + ph)
ctx.stroke() ctx.stroke()
ctx.setLineDash([]) ctx.setLineDash([])
// 圆点标记:芯 + 2px 彩色描边,在折线上形成清晰锚点 // 圆点标记:窗口底色芯 + 2px 彩色描边,在折线上形成清晰锚点
function drawDot(yVal, colorCss) { function drawDot(yVal, colorCss) {
var hy = pt + ph - (yVal / yMax) * ph var hy = pt + ph - (yVal / yMax) * ph
ctx.beginPath() ctx.beginPath()
ctx.arc(hx, hy, 4, 0, 2 * Math.PI) ctx.arc(hx, hy, 4, 0, 2 * Math.PI)
ctx.fillStyle = "#FFFFFF" ctx.fillStyle = root.dotCoreColor
ctx.fill() ctx.fill()
ctx.strokeStyle = colorCss ctx.strokeStyle = colorCss
ctx.lineWidth = 2 ctx.lineWidth = 2
@@ -553,7 +582,7 @@ Window {
text: root.hoverHint.length > 0 text: root.hoverHint.length > 0
? root.hoverHint : qsTr("鼠标移到曲线上查看详情") ? root.hoverHint : qsTr("鼠标移到曲线上查看详情")
font.pixelSize: 11 font.pixelSize: 11
color: root.hoverHint.length > 0 ? "#333333" : "#999999" color: root.hoverHint.length > 0 ? root.textPrimary : root.textTertiary
} }
} }
} }
+26 -11
View File
@@ -105,14 +105,24 @@ AppletItem {
} }
} }
// 任务栏与面板的颜色全部派生自 DockPalette.iconTextPalette // 任务栏图标颜色派生自 DTK 系统调色板(windowText),跟随系统主题适配。
// 这样在深色/浅色任务栏下自动适配,无需手动判断主题 // 设计原因:原用 DockPalette.iconTextPalette,但实测其不随系统深色主题变化,
property Palette basePalette: DockPalette.iconTextPalette // 深色模式下返回深色文字(黑底黑字)、浅色模式下返回浅色文字(白底白字),方向相反。
readonly property color primaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.95) // DTK.palette.windowText 在深色模式下为浅色、浅色模式下为深色,与任务栏背景匹配。
readonly property color secondaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.80) // 注意:仅用于任务栏图标区(speedTextColor 回退),弹窗和独立窗口各自派生颜色。
readonly property color tertiaryText: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.65) readonly property color baseTextColor: DTK.palette.windowText
readonly property color cardBackground: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.06) readonly property color primaryText: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.95)
readonly property color cardBorder: Qt.rgba(basePalette.r, basePalette.g, basePalette.b, 0.10) readonly property color secondaryText: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.80)
readonly property color tertiaryText: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.65)
readonly property color cardBackground: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.06)
readonly property color cardBorder: Qt.rgba(baseTextColor.r, baseTextColor.g, baseTextColor.b, 0.10)
// 深色模式检测:用 DTK 系统调色板的窗口背景亮度判定,而非 DockPalette。
// 设计原因:DockPalette.iconTextPalette 反映的是任务栏图标文字色,不随系统深色主题变化;
// DTK.palette.window 是系统主题的窗口背景色,深色模式下为深色(hslLightness < 0.5),
// 浅色模式下为浅色(hslLightness >= 0.5)。主题切换时 DTK.paletteChanged 自动触发重新求值。
// 检测结果通过属性注入各独立窗口(AboutWindow 等独立 Window 无法访问 dock 上下文的 DockPalette
readonly property bool isDarkMode: DTK.palette.window.hslLightness < 0.5
// 强调色:下载蓝、上传绿,是面板与任务栏的主视觉区分 // 强调色:下载蓝、上传绿,是面板与任务栏的主视觉区分
readonly property color accentBlue: Qt.rgba(20 / 255, 80 / 255, 160 / 255, 1) readonly property color accentBlue: Qt.rgba(20 / 255, 80 / 255, 160 / 255, 1)
@@ -135,7 +145,7 @@ AppletItem {
readonly property color uploadValueColor: accentGreen readonly property color uploadValueColor: accentGreen
// 任务栏网速数值字体色:用户自定义色优先(持久化),未设置时跟随系统主题 // 任务栏网速数值字体色:用户自定义色优先(持久化),未设置时跟随系统主题
// 设计原因:primaryText 派生自 DockPalette,深浅色任务栏自动适配; // 设计原因:primaryText 派生自 DTK.palette.windowText,深浅色系统主题自动适配;
// 用户主动选色后覆盖,空串回退到 primaryText 保持自适应 // 用户主动选色后覆盖,空串回退到 primaryText 保持自适应
readonly property color speedTextColor: (applet && applet.textColor.length > 0) ? applet.textColor : primaryText readonly property color speedTextColor: (applet && applet.textColor.length > 0) ? applet.textColor : primaryText
@@ -372,19 +382,23 @@ AppletItem {
} }
// 关于窗口:抽取为独立组件 package/components/AboutWindow.qml // 关于窗口:抽取为独立组件 package/components/AboutWindow.qml
// 依赖通过属性传入:accentColor = root.accentRedversion 取自 C++ 后端 applet.version // 依赖通过属性传入:accentColor = root.accentRedversion 取自 C++ 后端 applet.version
// isDarkMode 取自上方 DockPalette 检测结果
AboutWindow { AboutWindow {
id: aboutWindow id: aboutWindow
accentColor: root.accentRed accentColor: root.accentRed
version: root.applet ? root.applet.version : "1.0" version: root.applet ? root.applet.version : "1.0"
isDarkMode: root.isDarkMode
} }
// 流量波动图窗口:屏幕居中独立窗口,展示活动接口最近 30 分钟网速趋势 // 流量波动图窗口:屏幕居中独立窗口,展示活动接口最近 30 分钟网速趋势
// 依赖通过属性传入:accentColor = root.accentRedapplet = root.applet // 依赖通过属性传入:accentColor = root.accentRedapplet = root.applet
// isDarkMode 取自上方 DockPalette 检测结果
TrafficChartWindow { TrafficChartWindow {
id: trafficChartWindow id: trafficChartWindow
accentColor: root.accentRed accentColor: root.accentRed
applet: root.applet applet: root.applet
isDarkMode: root.isDarkMode
} }
// 设置窗口:独立顶层窗口,在桌面中间弹出 // 设置窗口:独立顶层窗口,在桌面中间弹出
@@ -396,6 +410,7 @@ AppletItem {
networkInterfaces: root.networkInterfaces networkInterfaces: root.networkInterfaces
activeInterface: root.activeInterface activeInterface: root.activeInterface
accentColor: root.accentRed accentColor: root.accentRed
isDarkMode: root.isDarkMode
} }
// 点击处理 // 点击处理