feat: 弹窗 IPv4/IPv6 地址旁加一键复制图标

接口信息区每个 IP 地址后加 ⧉ 复制图标,点击写入剪贴板,
复制后短暂显示 ✓ 反馈(2 秒后恢复),hover 图标变蓝提示可交互
This commit is contained in:
2026-08-08 21:00:50 +08:00
parent 7ebfa5b74e
commit 98f88c05c5
+93 -9
View File
@@ -69,6 +69,9 @@ Control {
readonly property real fontScale: (applet && applet.fontScale !== undefined) readonly property real fontScale: (applet && applet.fontScale !== undefined)
? applet.fontScale : 1.0 ? applet.fontScale : 1.0
// 复制反馈状态:记录刚复制的字段("ipv4"/"ipv6"/""),用于图标切换为 ✓
property string copiedField: ""
// 排序后的接口列表:物理网卡在前,虚拟网卡在后,各自按名称排序 // 排序后的接口列表:物理网卡在前,虚拟网卡在后,各自按名称排序
// 设计原因:保持稳定排序,活动接口不再移到最前,避免切换网卡时 chip 顺序跳动; // 设计原因:保持稳定排序,活动接口不再移到最前,避免切换网卡时 chip 顺序跳动;
// 活动 chip 若被截断,由 chipFlickable 自动滚动露出完整样式; // 活动 chip 若被截断,由 chipFlickable 自动滚动露出完整样式;
@@ -92,6 +95,14 @@ Control {
chipFlickable.scrollToActiveChip(animated) chipFlickable.scrollToActiveChip(animated)
} }
// 一键复制:用隐藏 TextEdit 的 selectAll()+copy() 写入系统剪贴板
// QML 无直接剪贴板 API,此为项目既定模式(SettingsWindow/AboutWindow 同模式)
function copyToClipboard(text) {
clipboardHelper.text = text
clipboardHelper.selectAll()
clipboardHelper.copy()
}
padding: 12 padding: 12
contentItem: ColumnLayout { contentItem: ColumnLayout {
@@ -157,25 +168,60 @@ Control {
color: popup.primaryText color: popup.primaryText
} }
// IPv4 地址:次要色,与接口名区分层次 // IPv4 地址 + 分隔点 + 复制图标
RowLayout {
spacing: 4
visible: popup.ipAddress !== ""
Text { Text {
text: popup.ipAddress ? "· " + popup.ipAddress : "" text: "·"
font.pixelSize: Math.round(13 * popup.fontScale)
color: popup.tertiaryText
}
Text {
text: popup.ipAddress
font.pixelSize: Math.round(13 * popup.fontScale) font.pixelSize: Math.round(13 * popup.fontScale)
color: popup.secondaryText color: popup.secondaryText
visible: popup.ipAddress !== "" }
// 一键复制图标:点击复制 IPv4 到剪贴板,复制后短暂显示 ✓
Text {
text: popup.copiedField === "ipv4" ? "✓" : "⧉"
font.pixelSize: Math.round(11 * popup.fontScale)
color: popup.copiedField === "ipv4"
? popup.accentGreen
: (ipv4CopyMouse.containsMouse ? popup.accentBlue : popup.tertiaryText)
MouseArea {
id: ipv4CopyMouse
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
popup.copyToClipboard(popup.ipAddress)
popup.copiedField = "ipv4"
copyFeedbackTimer.restart()
}
}
}
} }
} }
// 行2:IPv6 地址(超长截断 + hover tooltip 显示完整地址) // 行2:IPv6 地址 + 复制图标(超长截断 + hover tooltip 显示完整地址)
Text { RowLayout {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: 300 Layout.maximumWidth: 320
horizontalAlignment: Text.AlignHCenter spacing: 4
visible: popup.ipv6Address !== ""
Text {
text: qsTr("IPv6: ") + popup.ipv6Address
font.pixelSize: Math.round(12 * popup.fontScale) font.pixelSize: Math.round(12 * popup.fontScale)
color: popup.tertiaryText color: popup.tertiaryText
visible: popup.ipv6Address !== ""
text: popup.ipv6Address ? qsTr("IPv6: ") + popup.ipv6Address : ""
elide: Text.ElideRight elide: Text.ElideRight
Layout.fillWidth: true
horizontalAlignment: Text.AlignRight
ToolTip.text: popup.ipv6Address ToolTip.text: popup.ipv6Address
ToolTip.visible: ipv6Mouse.containsMouse && popup.ipv6Address !== "" ToolTip.visible: ipv6Mouse.containsMouse && popup.ipv6Address !== ""
@@ -188,6 +234,28 @@ Control {
cursorShape: Qt.IBeamCursor cursorShape: Qt.IBeamCursor
} }
} }
// 一键复制图标:点击复制 IPv6 到剪贴板,复制后短暂显示 ✓
Text {
text: popup.copiedField === "ipv6" ? "✓" : "⧉"
font.pixelSize: Math.round(11 * popup.fontScale)
color: popup.copiedField === "ipv6"
? popup.accentGreen
: (ipv6CopyMouse.containsMouse ? popup.accentBlue : popup.tertiaryText)
MouseArea {
id: ipv6CopyMouse
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onClicked: {
popup.copyToClipboard(popup.ipv6Address)
popup.copiedField = "ipv6"
copyFeedbackTimer.restart()
}
}
}
}
} }
} }
@@ -505,4 +573,20 @@ Control {
// 填充剩余空间,将内容推至顶部 // 填充剩余空间,将内容推至顶部
Item { Layout.fillHeight: true } Item { Layout.fillHeight: true }
} }
// 隐藏的 TextEdit 用于复制 IP 地址到剪贴板
// QML 没有直接剪贴板 API,用 TextEdit.selectAll()+copy() 实现
//(与 SettingsWindow/AboutWindow 中 clipboardHelper 同模式)
TextEdit {
id: clipboardHelper
visible: false
text: ""
}
// 复制反馈定时器:2 秒后将 copiedField 清空,图标从 ✓ 恢复为 ⧉
Timer {
id: copyFeedbackTimer
interval: 2000
onTriggered: popup.copiedField = ""
}
} }