refactor: 提取 WindowTheme 和 TitleBar 消除三窗口样板重复
This commit is contained in:
@@ -8,13 +8,21 @@
|
||||
// 深/浅主题由 isDarkMode 切换(networkview.qml 依据 DockPalette 检测任务栏深浅后传入),
|
||||
// 默认浅色,保证组件独立预览时与原版视觉一致
|
||||
// 对外依赖:accentColor、isDarkMode,由 networkview.qml 实例化时传入,触发方式为 show()/raise()/requestActivate()
|
||||
// 公共能力复用:主题色取自 WindowTheme,标题栏/圆角卡片取自 TitleBar,消除三窗口样板重复
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Window 2.15
|
||||
import "."
|
||||
|
||||
Window {
|
||||
id: root
|
||||
|
||||
// 公共主题色:集中定义于 WindowTheme.qml,随 isDarkMode 切换深浅
|
||||
WindowTheme {
|
||||
id: theme
|
||||
isDarkMode: root.isDarkMode
|
||||
}
|
||||
|
||||
// 对外依赖:关闭按钮 hover 态文字高亮色,由父组件传入
|
||||
// 默认值与 networkview.qml 中 root.accentRed 一致,确保独立可用
|
||||
property color accentColor: Qt.rgba(220 / 255, 38 / 255, 38 / 255, 1)
|
||||
@@ -27,14 +35,6 @@ Window {
|
||||
// 默认 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 时复制图标变绿并显示"已复制"提示,
|
||||
// 2 秒后由 copyResetTimer 复位
|
||||
property bool copied: false
|
||||
@@ -58,66 +58,22 @@ Window {
|
||||
// 窗口主体:圆角卡片(背景与边框随 isDarkMode 切换深浅),1px 边框模拟 DTK 窗口描边
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.winBg
|
||||
color: theme.winBg
|
||||
radius: 12
|
||||
border.width: 1
|
||||
border.color: root.lineColor
|
||||
border.color: theme.lineColor
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
// 自定义标题栏:左侧"关于"标题 + 右侧圆形关闭按钮,整栏可拖动窗口
|
||||
Rectangle {
|
||||
// 公共标题栏:标题文字 + 圆形关闭按钮,整栏可拖动
|
||||
TitleBar {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 44
|
||||
color: "transparent"
|
||||
|
||||
// 拖动层:声明在关闭按钮之前(位于其下方),避免遮挡按钮点击与 hover
|
||||
// 用 startSystemMove() 系统级窗口拖动(drag.target 对 Window 无效,
|
||||
// 与 SettingsWindow/TrafficChartWindow 一致)
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.OpenHandCursor
|
||||
onPressed: root.startSystemMove()
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: qsTr("About")
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Bold
|
||||
color: root.textPrimary
|
||||
}
|
||||
|
||||
// 关闭按钮:28x28 圆形,hover 时淡红底 + 红色 ×(颜色由 accentColor 决定)
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 28
|
||||
height: 28
|
||||
radius: 14
|
||||
color: aboutCloseMouse.containsMouse ? Qt.rgba(220 / 255, 38 / 255, 38 / 255, 0.15) : "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "×"
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
color: aboutCloseMouse.containsMouse ? accentColor : root.textSecondary
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: aboutCloseMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.hide()
|
||||
}
|
||||
}
|
||||
titleText: qsTr("About")
|
||||
textColor: theme.textPrimary
|
||||
secondaryTextColor: theme.textSecondary
|
||||
closeHoverColor: root.accentColor
|
||||
}
|
||||
|
||||
// 标题区上方间距
|
||||
@@ -136,7 +92,7 @@ Window {
|
||||
text: qsTr("Network Speed Monitor")
|
||||
font.pixelSize: 18
|
||||
font.weight: Font.Bold
|
||||
color: root.textPrimary
|
||||
color: theme.textPrimary
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
@@ -144,7 +100,7 @@ Window {
|
||||
Text {
|
||||
text: "JNetApplet"
|
||||
font.pixelSize: 12
|
||||
color: root.textTertiary
|
||||
color: theme.textTertiary
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
@@ -161,7 +117,7 @@ Window {
|
||||
Layout.leftMargin: 24
|
||||
Layout.rightMargin: 24
|
||||
Layout.preferredHeight: 1
|
||||
color: root.lineColor
|
||||
color: theme.lineColor
|
||||
}
|
||||
|
||||
// 信息区上方间距
|
||||
@@ -192,7 +148,7 @@ Window {
|
||||
Text {
|
||||
text: version
|
||||
font.pixelSize: 12
|
||||
color: root.textPrimary
|
||||
color: theme.textPrimary
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
@@ -213,7 +169,7 @@ Window {
|
||||
Text {
|
||||
text: "Jokul"
|
||||
font.pixelSize: 12
|
||||
color: root.textPrimary
|
||||
color: theme.textPrimary
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
@@ -234,7 +190,7 @@ Window {
|
||||
Text {
|
||||
text: qsTr("Monitor network speed and traffic")
|
||||
font.pixelSize: 12
|
||||
color: root.textPrimary
|
||||
color: theme.textPrimary
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
@@ -256,7 +212,7 @@ Window {
|
||||
Text {
|
||||
text: "git.jokul.space/Jokul/JNetApplet"
|
||||
font.pixelSize: 11
|
||||
color: root.textTertiary
|
||||
color: theme.textTertiary
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WrapAnywhere
|
||||
}
|
||||
@@ -277,7 +233,7 @@ Window {
|
||||
width: copiedHintText.implicitWidth + 10
|
||||
height: 18
|
||||
radius: 4
|
||||
color: root.cardBg
|
||||
color: theme.cardBg
|
||||
border.width: 1
|
||||
border.color: "#22A34A"
|
||||
|
||||
@@ -313,9 +269,9 @@ Window {
|
||||
width: 10
|
||||
height: 10
|
||||
radius: 2
|
||||
color: root.cardBg
|
||||
color: theme.cardBg
|
||||
border.width: 1
|
||||
border.color: copyRepoMouse.containsMouse ? root.textPrimary : root.textTertiary
|
||||
border.color: copyRepoMouse.containsMouse ? theme.textPrimary : theme.textTertiary
|
||||
}
|
||||
|
||||
// 前层矩形(左上),复制成功时边框短暂变绿
|
||||
@@ -325,9 +281,9 @@ Window {
|
||||
width: 10
|
||||
height: 10
|
||||
radius: 2
|
||||
color: root.cardBg
|
||||
color: theme.cardBg
|
||||
border.width: 1
|
||||
border.color: copied ? "#22A34A" : (copyRepoMouse.containsMouse ? root.textPrimary : root.textTertiary)
|
||||
border.color: copied ? "#22A34A" : (copyRepoMouse.containsMouse ? theme.textPrimary : theme.textTertiary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
// 对外依赖:applet(C++ 后端对象)、networkInterfaces(接口列表)、activeInterface(当前接口)、
|
||||
// accentColor(强调色)、isDarkMode(深色模式标记),由 networkview.qml 实例化时传入,
|
||||
// 触发方式为 show()/raise()/requestActivate()
|
||||
// 公共能力复用:主题色取自 WindowTheme(本窗口 winBg 浅色 #F5F5F5、lineColor 浅色
|
||||
// #E0E0E0 与其他窗口不同,通过覆盖 WindowTheme 的浅色对实现),标题栏/圆角卡片取自 TitleBar
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
@@ -22,6 +24,15 @@ Window {
|
||||
// 与 NetworkPopup 共享同一份实现,消除跨组件重复定义
|
||||
NetCommon { id: common }
|
||||
|
||||
// 公共主题色:集中定义于 WindowTheme.qml,随 isDarkMode 切换深浅。
|
||||
// 本窗口 winBg 浅色 #F5F5F5、lineColor 浅色 #E0E0E0 与默认值不同,在此覆盖
|
||||
WindowTheme {
|
||||
id: theme
|
||||
isDarkMode: root.isDarkMode
|
||||
lightWinBg: "#F5F5F5"
|
||||
lightLineColor: "#E0E0E0"
|
||||
}
|
||||
|
||||
// 对外依赖:C++ 后端对象,用于获取/设置接口、字体颜色等
|
||||
property var applet: null
|
||||
|
||||
@@ -39,15 +50,8 @@ Window {
|
||||
// 默认 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"
|
||||
@@ -83,76 +87,30 @@ Window {
|
||||
// 主容器:提供不透明背景(随 isDarkMode 切换深浅)+ 圆角 + 边框
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.winBg
|
||||
color: theme.winBg
|
||||
radius: 12
|
||||
border.width: 1
|
||||
border.color: root.lineColor
|
||||
border.color: theme.lineColor
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 0
|
||||
spacing: 0
|
||||
|
||||
// 自定义标题栏(可拖动)
|
||||
Rectangle {
|
||||
// 公共标题栏:标题文字 + 圆形关闭按钮,整栏可拖动
|
||||
TitleBar {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 44
|
||||
color: "transparent"
|
||||
|
||||
// 拖动层:声明在关闭按钮之前(位于其下方),避免遮挡按钮点击与 hover
|
||||
// 用 startSystemMove() 系统级窗口拖动,由窗口管理器接管移动,
|
||||
// 这是 frameless Window 的正确做法,pressed 即触发,丝滑无抖动
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.OpenHandCursor
|
||||
onPressed: root.startSystemMove()
|
||||
}
|
||||
|
||||
// 标题文字
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: qsTr("Settings")
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Bold
|
||||
color: root.textPrimary
|
||||
}
|
||||
|
||||
// 关闭按钮
|
||||
Rectangle {
|
||||
id: closeButton
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 28
|
||||
height: 28
|
||||
radius: 14
|
||||
color: closeMouse.containsMouse ? Qt.rgba(220/255, 38/255, 38/255, 0.15) : "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "×"
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
color: closeMouse.containsMouse ? accentColor : root.textSecondary
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.hide()
|
||||
}
|
||||
}
|
||||
titleText: qsTr("Settings")
|
||||
textColor: theme.textPrimary
|
||||
secondaryTextColor: theme.textSecondary
|
||||
closeHoverColor: root.accentColor
|
||||
}
|
||||
|
||||
// 分隔线
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 1
|
||||
color: root.lineColor
|
||||
color: theme.lineColor
|
||||
}
|
||||
|
||||
// 内容区域
|
||||
@@ -170,7 +128,7 @@ Window {
|
||||
text: qsTr("Network Interface")
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Bold
|
||||
color: root.textSecondary
|
||||
color: theme.textSecondary
|
||||
}
|
||||
|
||||
// 接口列表容器:最多显示约 5 行(160px),超出部分垂直滚动
|
||||
@@ -181,10 +139,10 @@ Window {
|
||||
Layout.preferredHeight: networkInterfaces.length > 0
|
||||
? Math.min(ifaceColumn.implicitHeight, 160) + 20
|
||||
: 80
|
||||
color: root.cardBg
|
||||
color: theme.cardBg
|
||||
radius: 10
|
||||
border.width: 1
|
||||
border.color: root.lineColor
|
||||
border.color: theme.lineColor
|
||||
|
||||
// 用 ScrollView 而非裸 Flickable:自带滚轮滚动支持,
|
||||
// 且滚动条显示时自动让出内容宽度,不会遮挡行内文字
|
||||
@@ -209,8 +167,8 @@ Window {
|
||||
implicitWidth: 4
|
||||
radius: 2
|
||||
// 按压/悬停加深、默认稍淡,保证滚动条在卡片背景上可见
|
||||
color: ifaceScrollBar.pressed ? root.textSecondary
|
||||
: (ifaceScrollBar.hovered ? root.textSecondary : root.textTertiary)
|
||||
color: ifaceScrollBar.pressed ? theme.textSecondary
|
||||
: (ifaceScrollBar.hovered ? theme.textSecondary : theme.textTertiary)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +197,7 @@ Window {
|
||||
// 背景优先级:选中 > hover;选中行 hover 时稍加深以保留交互反馈
|
||||
color: isActive
|
||||
? (hovered ? root.selBgHover : root.selBg)
|
||||
: (hovered ? root.hoverBg : "transparent")
|
||||
: (hovered ? theme.hoverBg : "transparent")
|
||||
// 选中行加细边框增强视觉;未选中保持透明边框占位,避免切换时出现 1px 抖动
|
||||
border.width: 1
|
||||
border.color: isActive ? root.selBorder : "transparent"
|
||||
@@ -267,7 +225,7 @@ Window {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: common.interfaceIcon(modelData)
|
||||
font.pixelSize: 14
|
||||
color: ifaceRow.isActive ? ifaceRow.activeColor : root.iconGray
|
||||
color: ifaceRow.isActive ? ifaceRow.activeColor : theme.iconGray
|
||||
}
|
||||
|
||||
// 自绘单选圆点:替代 RadioButton 作纯视觉指示器,
|
||||
@@ -281,7 +239,7 @@ Window {
|
||||
color: "transparent"
|
||||
border.width: 2
|
||||
border.color: ifaceRow.isActive ? ifaceRow.activeColor
|
||||
: (ifaceRow.hovered ? root.textSecondary : root.textTertiary)
|
||||
: (ifaceRow.hovered ? theme.textSecondary : theme.textTertiary)
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
@@ -300,7 +258,7 @@ Window {
|
||||
text: modelData
|
||||
font.pixelSize: 13
|
||||
font.weight: ifaceRow.isActive ? Font.Medium : Font.Normal
|
||||
color: ifaceRow.isActive ? ifaceRow.activeColor : root.textPrimary
|
||||
color: ifaceRow.isActive ? ifaceRow.activeColor : theme.textPrimary
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
@@ -309,7 +267,7 @@ Window {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: common.interfaceDescription(modelData)
|
||||
font.pixelSize: 12
|
||||
color: root.textTertiary
|
||||
color: theme.textTertiary
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -322,7 +280,7 @@ Window {
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("No network interface detected")
|
||||
font.pixelSize: 12
|
||||
color: root.textTertiary
|
||||
color: theme.textTertiary
|
||||
visible: networkInterfaces.length === 0
|
||||
}
|
||||
}
|
||||
@@ -334,7 +292,7 @@ Window {
|
||||
text: qsTr("Font Color")
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Bold
|
||||
color: root.textSecondary
|
||||
color: theme.textSecondary
|
||||
}
|
||||
|
||||
TextColorPicker {
|
||||
@@ -353,7 +311,7 @@ Window {
|
||||
text: qsTr("Refresh Interval")
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Bold
|
||||
color: root.textSecondary
|
||||
color: theme.textSecondary
|
||||
}
|
||||
|
||||
// 三个间隔选项按钮:1 秒 / 2 秒 / 5 秒
|
||||
@@ -371,17 +329,17 @@ Window {
|
||||
radius: 8
|
||||
// 选中态蓝色填充边框,未选中态卡片背景,hover 态加深
|
||||
color: applet && applet.refreshInterval === modelData
|
||||
? root.selBg : (intervalMouse.containsMouse ? root.hoverBg : root.cardBg)
|
||||
? root.selBg : (intervalMouse.containsMouse ? theme.hoverBg : theme.cardBg)
|
||||
border.width: 1
|
||||
border.color: applet && applet.refreshInterval === modelData
|
||||
? root.selBorder : root.lineColor
|
||||
? root.selBorder : theme.lineColor
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: (modelData / 1000) + "s"
|
||||
font.pixelSize: 13
|
||||
color: applet && applet.refreshInterval === modelData
|
||||
? root.selText : root.textPrimary
|
||||
? root.selText : theme.textPrimary
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
@@ -455,10 +413,10 @@ Window {
|
||||
y: (root.height - height) / 2
|
||||
|
||||
background: Rectangle {
|
||||
color: root.winBg
|
||||
color: theme.winBg
|
||||
radius: 12
|
||||
border.width: 1
|
||||
border.color: root.lineColor
|
||||
border.color: theme.lineColor
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
@@ -477,7 +435,7 @@ Window {
|
||||
Text {
|
||||
text: qsTr("The following command uninstalls the plugin and restarts dde-shell. Please copy and run it in terminal:")
|
||||
font.pixelSize: 12
|
||||
color: root.textPrimary
|
||||
color: theme.textPrimary
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
@@ -497,7 +455,7 @@ Window {
|
||||
text: "sudo rm -rf /usr/share/dde-shell/space.jokul.JNetApplet/ && systemctl --user restart dde-shell@DDE"
|
||||
font.pixelSize: 10
|
||||
font.family: "monospace"
|
||||
color: root.textSecondary
|
||||
color: theme.textSecondary
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
@@ -513,16 +471,16 @@ Window {
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 36
|
||||
color: cancelUninstallMouse.containsMouse ? root.hoverBg : root.cardBg
|
||||
color: cancelUninstallMouse.containsMouse ? theme.hoverBg : theme.cardBg
|
||||
radius: 8
|
||||
border.width: 1
|
||||
border.color: root.lineColor
|
||||
border.color: theme.lineColor
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Cancel")
|
||||
font.pixelSize: 13
|
||||
color: root.textPrimary
|
||||
color: theme.textPrimary
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// SPDX-FileCopyrightText: 2026 Jokul
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
// 独立窗口公共自定义标题栏
|
||||
// 消除 AboutWindow / SettingsWindow / TrafficChartWindow 三个独立顶层窗口之间的
|
||||
// 标题栏样板重复(此前各窗口各持一份"拖动层 + 标题文字 + 圆形关闭按钮"的拷贝)。
|
||||
// 现提取为本组件,各窗口在圆角卡片顶部的 ColumnLayout 中实例化 TitleBar 即可。
|
||||
// 对外能力:
|
||||
// - titleText:标题栏文字
|
||||
// - textColor / secondaryTextColor:标题文字色与关闭按钮默认文字色(取主题色)
|
||||
// - closeHoverColor:关闭按钮 hover 态文字高亮色(accentColor,默认红色)
|
||||
// - 拖动:整栏按住调用 Window.window.startSystemMove() 系统级拖动(frameless
|
||||
// Window 的正确做法,drag.target 对 Window 无效);拖动层声明在按钮下方,
|
||||
// 不遮挡关闭/额外按钮的点击与 hover
|
||||
// - 关闭按钮:28x28 圆形,hover 时淡红底 + 红色 ×,点击 Window.window.hide()
|
||||
// - extraActions:default property,供子窗口在关闭按钮左侧填充额外按钮
|
||||
// (如 TrafficChartWindow 的"置顶"按钮),其逻辑仍保留在子窗口内
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Window 2.15
|
||||
|
||||
Item {
|
||||
id: titleBar
|
||||
|
||||
// 标题栏文字,由子窗口传入(qsTr 文案在子窗口侧)
|
||||
property string titleText: ""
|
||||
|
||||
// 标题文字颜色:取主题色 textPrimary
|
||||
property color textColor: "#333333"
|
||||
|
||||
// 关闭按钮默认文字色:取主题色 textSecondary
|
||||
property color secondaryTextColor: "#666666"
|
||||
|
||||
// 关闭按钮 hover 态文字高亮色:取子窗口 accentColor(默认红色)
|
||||
property color closeHoverColor: Qt.rgba(220 / 255, 38 / 255, 38 / 255, 1)
|
||||
|
||||
// 额外右侧按钮容器:default property 让子窗口直接把按钮写进标题栏,
|
||||
// 按钮将布局在关闭按钮左侧(用于置顶按钮等)
|
||||
default property alias extraActions: actionHost.data
|
||||
|
||||
implicitHeight: 44
|
||||
|
||||
// 拖动层:声明在关闭/额外按钮之前(位于其下方),避免遮挡按钮点击与 hover
|
||||
// 用 startSystemMove() 系统级窗口拖动,由窗口管理器接管移动,
|
||||
// 这是 frameless Window 的正确做法,pressed 即触发,丝滑无抖动
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.OpenHandCursor
|
||||
onPressed: Window.window.startSystemMove()
|
||||
}
|
||||
|
||||
// 标题文字
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: titleBar.titleText
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Bold
|
||||
color: titleBar.textColor
|
||||
}
|
||||
|
||||
// 额外右侧按钮容器:右缘贴关闭按钮左侧,高度与标题栏一致
|
||||
Item {
|
||||
id: actionHost
|
||||
anchors.right: closeButton.left
|
||||
anchors.rightMargin: 4
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
|
||||
// 关闭按钮:28x28 圆形,hover 时淡红底 + 红色 ×(颜色由 closeHoverColor 决定)
|
||||
Rectangle {
|
||||
id: closeButton
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 28
|
||||
height: 28
|
||||
radius: 14
|
||||
color: closeMouse.containsMouse ? Qt.rgba(220 / 255, 38 / 255, 38 / 255, 0.15) : "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "×"
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
color: closeMouse.containsMouse ? titleBar.closeHoverColor : titleBar.secondaryTextColor
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Window.window.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@
|
||||
// - 数据通过属性注入:applet 即 networkview.qml 的 root.applet(C++ 后端对象),
|
||||
// 为 null 时组件可独立预览(Canvas 显示"暂无历史数据"空状态)
|
||||
// 触发方式:右键菜单"流量波动图" -> show()/raise()/requestActivate()
|
||||
// 公共能力复用:主题色取自 WindowTheme,标题栏(含置顶/关闭按钮)取自 TitleBar,
|
||||
// 消除三窗口样板重复
|
||||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtQuick.Window 2.15
|
||||
@@ -25,6 +27,12 @@ Window {
|
||||
// 与 networkview.qml、NetworkPopup 共享同一份实现,消除跨组件重复定义
|
||||
NetCommon { id: common }
|
||||
|
||||
// 公共主题色:集中定义于 WindowTheme.qml,随 isDarkMode 切换深浅
|
||||
WindowTheme {
|
||||
id: theme
|
||||
isDarkMode: root.isDarkMode
|
||||
}
|
||||
|
||||
// 对外依赖:关闭按钮 hover 态文字高亮色,由父组件传入
|
||||
// 默认值与 networkview.qml 中 root.accentRed 一致,确保独立可用
|
||||
property color accentColor: Qt.rgba(220 / 255, 38 / 255, 38 / 255, 1)
|
||||
@@ -39,16 +47,10 @@ Window {
|
||||
// 默认 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 底色:浅色用淡黑、深色用淡白,保证两种卡片背景上均可见
|
||||
// 置顶按钮 hover 底色(本窗口特有):浅色用淡黑、深色用淡白,保证两种卡片背景上均可见
|
||||
readonly property color pinHoverBg: isDarkMode ? Qt.rgba(1, 1, 1, 0.10) : Qt.rgba(0, 0, 0, 0.06)
|
||||
|
||||
// 图表绘制色:声明为 string 供 Canvas 2D 上下文直接使用
|
||||
// 图表绘制色(本窗口特有):声明为 string 供 Canvas 2D 上下文直接使用
|
||||
//(QML color 类型含 alpha 时序列化为 #AARRGGBB,Canvas 无法正确解析,故不用 color 类型)
|
||||
readonly property string gridBaselineColor: isDarkMode ? "#383838" : "#DDDDDD"
|
||||
readonly property string gridLineColor: isDarkMode ? "#2A2A2A" : "#E5E5E5"
|
||||
@@ -148,47 +150,29 @@ Window {
|
||||
// 窗口主体:圆角卡片(背景与边框随 isDarkMode 切换深浅),1px 边框模拟 DTK 窗口描边(与 AboutWindow 一致)
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: root.winBg
|
||||
color: theme.winBg
|
||||
radius: 12
|
||||
border.width: 1
|
||||
border.color: root.lineColor
|
||||
border.color: theme.lineColor
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
// 自定义标题栏:左侧"流量波动图"标题 + 右侧置顶/关闭按钮,整栏可拖动窗口
|
||||
Rectangle {
|
||||
// 公共标题栏:标题文字 + 置顶/关闭按钮,整栏可拖动。
|
||||
// 置顶按钮通过 TitleBar 的额外按钮槽(extraActions)注入,逻辑仍在本窗口
|
||||
TitleBar {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 44
|
||||
color: "transparent"
|
||||
|
||||
// 拖动层:声明在关闭/置顶按钮之前(位于其下方),避免遮挡按钮点击与 hover
|
||||
// 注意:drag.target 只对 Item 生效,对 Window 无效(原实现拖动不工作);
|
||||
// 改用 startSystemMove() 系统级窗口拖动,这是 frameless Window 的正确做法,
|
||||
// pressed 即触发,由窗口管理器接管移动,不干扰按钮的 hover/click
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.OpenHandCursor
|
||||
onPressed: root.startSystemMove()
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: qsTr("Traffic Chart")
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Bold
|
||||
color: root.textPrimary
|
||||
}
|
||||
titleText: qsTr("Traffic Chart")
|
||||
textColor: theme.textPrimary
|
||||
secondaryTextColor: theme.textSecondary
|
||||
closeHoverColor: root.accentColor
|
||||
|
||||
// 置顶按钮:28x28 圆形(与关闭按钮一致),位于关闭按钮左侧
|
||||
// 三态视觉:未置顶=灰色图钉轮廓;置顶=deepin 蓝填充 + 淡蓝底;
|
||||
// hover=淡灰底(置顶时淡蓝底优先)
|
||||
Rectangle {
|
||||
anchors.right: chartCloseButton.left
|
||||
anchors.rightMargin: 4
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 28
|
||||
height: 28
|
||||
@@ -256,34 +240,6 @@ Window {
|
||||
onClicked: root.pinned = !root.pinned
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭按钮:28x28 圆形,hover 时淡红底 + 红色 ×(颜色由 accentColor 决定)
|
||||
Rectangle {
|
||||
id: chartCloseButton
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 28
|
||||
height: 28
|
||||
radius: 14
|
||||
color: chartCloseMouse.containsMouse ? Qt.rgba(220 / 255, 38 / 255, 38 / 255, 0.15) : "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "×"
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
color: chartCloseMouse.containsMouse ? root.accentColor : root.textSecondary
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: chartCloseMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 顶部状态条:实时下行/上行速度(箭头颜色与折线一致,兼作图例)
|
||||
@@ -306,7 +262,7 @@ Window {
|
||||
// applet 为空时兜底为 0,保证独立预览不报错
|
||||
text: common.formatSpeed(root.applet ? root.applet.downloadSpeed : 0)
|
||||
font.pixelSize: 12
|
||||
color: root.textPrimary
|
||||
color: theme.textPrimary
|
||||
}
|
||||
|
||||
Item { Layout.preferredWidth: 10 }
|
||||
@@ -321,7 +277,7 @@ Window {
|
||||
Text {
|
||||
text: common.formatSpeed(root.applet ? root.applet.uploadSpeed : 0)
|
||||
font.pixelSize: 12
|
||||
color: root.textPrimary
|
||||
color: theme.textPrimary
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
@@ -330,7 +286,7 @@ Window {
|
||||
text: (root.applet && root.applet.activeInterface
|
||||
? root.applet.activeInterface : "—") + " · 5min"
|
||||
font.pixelSize: 12
|
||||
color: root.textTertiary
|
||||
color: theme.textTertiary
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,7 +548,7 @@ Window {
|
||||
text: root.hoverHint.length > 0
|
||||
? root.hoverHint : qsTr("Hover over the curve for details")
|
||||
font.pixelSize: 11
|
||||
color: root.hoverHint.length > 0 ? root.textPrimary : root.textTertiary
|
||||
color: root.hoverHint.length > 0 ? theme.textPrimary : theme.textTertiary
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// SPDX-FileCopyrightText: 2026 Jokul
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
// 独立窗口公共主题色提供者
|
||||
// 消除 AboutWindow / SettingsWindow / TrafficChartWindow 三个独立顶层窗口之间的
|
||||
// 主题颜色样板重复(此前各窗口各持一份 isDarkMode ? 深 : 浅 的颜色定义,
|
||||
// 改一处需同步多处)。现集中到本文件,各窗口实例化 WindowTheme { id: theme } 后
|
||||
// 统一经 theme.xxx 访问,仅需向 theme.isDarkMode 传入深色模式标记。
|
||||
// 设计原因:
|
||||
// - 深/浅主题由 networkview.qml 依据 DockPalette 检测任务栏深浅后通过 isDarkMode 传入,
|
||||
// 浅色取值与原各窗口硬编码完全一致,保证独立预览时视觉不变。
|
||||
// - 个别窗口存在差异值(如 SettingsWindow 的 winBg 浅色为 #F5F5F5、lineColor 为
|
||||
// #E0E0E0),因此每个颜色拆成 light/dark 一对可覆盖属性,派生色由它们计算,
|
||||
// 差异窗口仅需覆盖对应浅/深值即可,无需整体重写。
|
||||
import QtQuick 2.15
|
||||
|
||||
QtObject {
|
||||
id: theme
|
||||
|
||||
// 输入:深色模式标记,由父窗口从 networkview.qml 传入
|
||||
property bool isDarkMode: false
|
||||
|
||||
// ---- 浅色/深色取色对(默认值与 AboutWindow/TrafficChartWindow 一致,个别窗口可覆盖差异值)----
|
||||
property color lightWinBg: "#FFFFFF"
|
||||
property color darkWinBg: "#202020"
|
||||
property color lightCardBg: "#FFFFFF"
|
||||
property color darkCardBg: "#2A2A2A"
|
||||
property color lightLineColor: "#E8E8E8"
|
||||
property color darkLineColor: "#383838"
|
||||
property color lightTextPrimary: "#333333"
|
||||
property color darkTextPrimary: "#E0E0E0"
|
||||
property color lightTextSecondary: "#666666"
|
||||
property color darkTextSecondary: "#AAAAAA"
|
||||
property color lightTextTertiary: "#999999"
|
||||
property color darkTextTertiary: "#888888"
|
||||
property color lightIconGray: "#777777"
|
||||
property color darkIconGray: "#AAAAAA"
|
||||
property color lightHoverBg: "#F0F0F0"
|
||||
property color darkHoverBg: "#353535"
|
||||
|
||||
// ---- 派生主题色:isDarkMode 为 false 时取值与原浅色硬编码完全一致 ----
|
||||
readonly property color winBg: isDarkMode ? darkWinBg : lightWinBg
|
||||
readonly property color cardBg: isDarkMode ? darkCardBg : lightCardBg
|
||||
readonly property color lineColor: isDarkMode ? darkLineColor : lightLineColor
|
||||
readonly property color textPrimary: isDarkMode ? darkTextPrimary : lightTextPrimary
|
||||
readonly property color textSecondary: isDarkMode ? darkTextSecondary : lightTextSecondary
|
||||
readonly property color textTertiary: isDarkMode ? darkTextTertiary : lightTextTertiary
|
||||
readonly property color iconGray: isDarkMode ? darkIconGray : lightIconGray
|
||||
readonly property color hoverBg: isDarkMode ? darkHoverBg : lightHoverBg
|
||||
}
|
||||
Reference in New Issue
Block a user