11 Commits
Author SHA1 Message Date
Jokul 6b59848f0a 更新 README.md 2026-09-12 00:20:19 +08:00
Jokul 8ad2ad71c3 docs: 重写 CHANGELOG 去除开发过程 bug 修复
版本更新清单只保留新功能、优化、重构,不包含新功能自身的调试修复
2026-08-09 09:34:28 +08:00
Jokul 0bf771b6b0 release: v2.1.0 版本更新
修复会话总量与今日累计不一致、流量统计裁剪上限调整
2026-08-09 09:27:15 +08:00
Jokul 83f1a2002a fix: 流量统计裁剪上限改为按日30天、按月12个月
MAX_DAY_ENTRIES 90->30, MAX_MONTH_ENTRIES 24->12
2026-08-09 09:22:24 +08:00
Jokul f50a3fe8e5 fix: 会话总量改回本次运行累计(累加差值)
网卡开机累计值与今日累计不一致让用户困惑,改回累加差值模式:
本次会话 = dde-shell 启动至今的流量,重启清零,不再超过今日累计
2026-08-09 09:19:20 +08:00
Jokul b27f96b31d release: v2.0.0 版本更新
弹窗重新设计、日/月流量统计、TCP连接清单、链路速率/WiFi信号/包统计、
可配置刷新间隔、流量图时间窗口、性能优化、架构重构、多项 bug 修复
2026-08-09 09:12:51 +08:00
Jokul 8a984eac59 fix: TCP连接清单刷新间隔文案改为动态显示
'每5秒刷新'写死改为读取 applet.refreshInterval 动态显示实际间隔
2026-08-09 09:09:02 +08:00
Jokul e75f56a0ba fix: 流量统计和TCP连接清单刷新间隔去掉5倍降频
直接使用用户设置的刷新间隔,不再叠加5倍降频
2026-08-09 09:06:49 +08:00
Jokul 4186357380 style: 右键菜单顺序调整,设置移到 TCP 连接下面
新顺序:流量波动图 -> 流量统计 -> TCP 连接 -> 设置 -> 分隔线 -> 关于
2026-08-09 09:01:48 +08:00
Jokul 3bec5b156e fix: 右键菜单 TCP Connections 国际化 + 刷新间隔影响所有定时
补全 networkview context 中缺失的 TCP Connections 翻译;
TrafficStatsWindow 和 TcpConnectionsWindow 的数据刷新 Timer 改为
跟随 applet.refreshInterval(5 倍降频),设置中改刷新间隔后所有定时同步生效
2026-08-09 08:59:09 +08:00
Jokul c61542574c fix: 补全 TCP 连接清单窗口国际化翻译
新增 12 条翻译:TCP Connections/Active connections/Search/Local Address
/Remote Address/State/Process/No active/No matching/Total/connections
等,中文系统下不再显示英文
2026-08-09 08:54:06 +08:00
9 changed files with 155 additions and 35 deletions
+49
View File
@@ -0,0 +1,49 @@
# 更新日志
## v2.1.0 - 2026-08-09
v2.0.0 后的优化版本。
### 优化
- 流量统计裁剪上限调整:按日保留 30 天,按月保留 12 个月
## v2.0.0 - 2026-08-09
本次为大版本更新,涵盖弹窗重新设计、多个新功能窗口、性能优化和架构重构。
### 新功能
- **左键弹窗重新设计**:通透分区布局(分隔线+留白),速度数字 24px 视觉锚点,适配 Deepin 原生毛玻璃风格
- **IPv4/IPv6 一键复制**:地址旁加复制图标,点击写入剪贴板,复制后显示 ✓ 反馈
- **日/月流量统计**(持久化):右键菜单新增"流量统计"窗口,按日/按月展示累计流量,跨重启累加,JSON 持久化到磁盘
- **TCP 连接清单**:右键菜单新增"TCP 连接"窗口,展示所有 ESTABLISHED 连接的本地/远程地址端口、状态、进程名,支持搜索筛选
- **链路速率显示**:弹窗接口信息区显示协商速率(Gbps/Mbps)
- **WiFi 信号强度**:无线接口显示信号 dBm
- **包统计/错误/丢包**:弹窗累计流量区展示收发包数、错误数、丢包数
- **TCP 连接数**:弹窗显示整机活跃 TCP 连接数
- **可配置刷新间隔**:设置窗口新增 1/2/5 秒刷新间隔选项,影响全项目所有定时器
- **流量波动图时间窗口**:1/5/30 分钟可切换
- **任务栏数值小数点对齐**:双行网速数值小数点垂直对齐,箭头间距固定
### 优化
- 弹窗文字颜色改用 dock 上下文调色板,深色模式文字清晰可见
- 弹窗高度固定,切换网卡时不再跳动
- IPv4/IPv6 地址行固定宽度标签对齐,不再随地址长度错位
- 流量波动图曲线 5 点滑动平均,抑制亚秒混叠尖峰
- C++ 后端性能优化:正则预编译、信号脏标记、IP 检测降频、历史 QVariantList 缓存
- TCP 进程名反查改用 ss 命令(netlink),不受 /proc 权限限制
### 重构
- 提取 WindowTheme + TitleBar 组件,消除三个独立窗口约 150 行样板重复
- 提取 interfaceIcon/interfaceDescription 到 NetCommon,消除跨组件重复
- 清理 fontScale 死代码,移除 30+ 处乘法噪声
- CMake Test 改为可选依赖,解决无 Qt6 Test 开发包环境构建失败
### 其他
- 右键菜单顺序调整:流量波动图 -> 流量统计 -> TCP 连接 -> 设置 -> 关于
- 全项目国际化翻译补全(77 条翻译)
- 任务栏数值右侧留边距
+1 -1
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
project(JNetApplet VERSION 1.2.0 LANGUAGES CXX) project(JNetApplet VERSION 2.1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
+7
View File
@@ -1,3 +1,10 @@
> **📦 本仓库已迁移至 GitHub:[GershonWang/JNetApplet](https://github.com/GershonWang/JNetApplet)**
>
> 此仓库代码已停止更新,最新源码、Issue 与版本发布请前往:
> <https://github.com/GershonWang/JNetApplet>
---
# JNetApplet # JNetApplet
基于 dde-shell 的**深度系统任务栏网络速率监控插件**,使用 C++ 后端采集数据、 基于 dde-shell 的**深度系统任务栏网络速率监控插件**,使用 C++ 后端采集数据、
+3 -3
View File
@@ -106,10 +106,10 @@ Window {
} }
} }
// 定时刷新:窗口可见时每 5 秒重建清单(与 C++ 后端降频周期一致), // 定时刷新:窗口可见时按刷新间隔的 5 倍重建清单(与 C++ 后端降频周期一致),
// 不依赖 C++ 信号;关闭时停止,兼顾实时性与性能 // 不依赖 C++ 信号;关闭时停止,兼顾实时性与性能
Timer { Timer {
interval: 5000 interval: root.applet ? root.applet.refreshInterval : 1000
repeat: true repeat: true
running: root.visible running: root.visible
onTriggered: refreshModel() onTriggered: refreshModel()
@@ -187,7 +187,7 @@ Window {
Item { Layout.fillWidth: true } Item { Layout.fillWidth: true }
Text { Text {
text: qsTr("Refreshes every 5 seconds") text: qsTr("Refreshes every ") + ((root.applet ? root.applet.refreshInterval : 1000) / 1000) + qsTr(" seconds")
font.pixelSize: 11 font.pixelSize: 11
color: theme.textTertiary color: theme.textTertiary
} }
+3 -3
View File
@@ -116,11 +116,11 @@ Window {
onCurrentTabChanged: buildStatsModel() onCurrentTabChanged: buildStatsModel()
Component.onCompleted: buildStatsModel() Component.onCompleted: buildStatsModel()
// 定时刷新:窗口可见时每 5 秒重建表格,不依赖 C++ 30 秒信号 // 定时刷新:窗口可见时按刷新间隔的 5 倍重建表格,不依赖 C++ 30 秒信号
// 设计原因:C++ 降频 30 秒通知,用户打开窗口期间看不到实时更新; // 设计原因:C++ 降频 30 秒通知,用户打开窗口期间看不到实时更新;
// 窗口可见时主动 5 秒刷新,关闭时停止,兼顾实时性与性能 // 窗口可见时主动刷新,间隔跟随设置中的刷新间隔(5 倍降频),关闭时停止
Timer { Timer {
interval: 5000 interval: root.applet ? root.applet.refreshInterval : 1000
repeat: true repeat: true
running: root.visible running: root.visible
onTriggered: buildStatsModel() onTriggered: buildStatsModel()
+9 -9
View File
@@ -355,15 +355,6 @@ AppletItem {
Platform.Menu { Platform.Menu {
id: contextMenu id: contextMenu
Platform.MenuItem {
text: qsTr("Settings")
onTriggered: {
settingsWindow.show()
settingsWindow.raise()
settingsWindow.requestActivate()
}
}
// 流量波动图:屏幕居中独立窗口,展示活动接口最近 30 分钟网速趋势 // 流量波动图:屏幕居中独立窗口,展示活动接口最近 30 分钟网速趋势
Platform.MenuItem { Platform.MenuItem {
text: qsTr("Traffic Chart") text: qsTr("Traffic Chart")
@@ -394,6 +385,15 @@ AppletItem {
} }
} }
Platform.MenuItem {
text: qsTr("Settings")
onTriggered: {
settingsWindow.show()
settingsWindow.raise()
settingsWindow.requestActivate()
}
}
Platform.MenuSeparator {} Platform.MenuSeparator {}
Platform.MenuItem { Platform.MenuItem {
+6 -15
View File
@@ -545,11 +545,11 @@ void NetworkMonitorApplet::calculateSpeed()
const qint64 txDeltaClamped = txDelta > 0 ? txDelta : 0; const qint64 txDeltaClamped = txDelta > 0 ? txDelta : 0;
m_downloadSpeed = rxDeltaClamped / elapsedSec; m_downloadSpeed = rxDeltaClamped / elapsedSec;
m_uploadSpeed = txDeltaClamped / elapsedSec; m_uploadSpeed = txDeltaClamped / elapsedSec;
// 会话总量:直接读取活动接口累计字节数(开机至今),而非累加差值 // 会话总量:累加差值(dde-shell 启动至今的流量),重启清零
// 设计原因:用户期望"本次会话"显示当前网卡从开机起的累计流量, // 设计原因:用户期望"本次会话"是本次 dde-shell 运行期间的流量,
// 切换网卡后立即显示新网卡的累计值,无流量网卡显示 0 // 与流量统计窗口的"今日累计"(从0点起)区分,数值不会超过今日累计
m_totalDownload = currentRxBytes; m_totalDownload += rxDeltaClamped;
m_totalUpload = currentTxBytes; m_totalUpload += txDeltaClamped;
// 累加日/月流量日志(仅活动接口增量,与速度计算口径一致) // 累加日/月流量日志(仅活动接口增量,与速度计算口径一致)
appendToTrafficLog(rxDeltaClamped, txDeltaClamped); appendToTrafficLog(rxDeltaClamped, txDeltaClamped);
m_lastRxBytes = currentRxBytes; m_lastRxBytes = currentRxBytes;
@@ -573,15 +573,6 @@ void NetworkMonitorApplet::calculateSpeed()
m_rxDropped = static_cast<quint64>(iface.rxDropped); m_rxDropped = static_cast<quint64>(iface.rxDropped);
m_txDropped = static_cast<quint64>(iface.txDropped); m_txDropped = static_cast<quint64>(iface.txDropped);
emit packetStatsChanged(); emit packetStatsChanged();
// 接口切换后立即更新会话总量为新网卡的累计字节数(开机至今)
// 设计原因:会话总量改为读取活动接口累计值,切换后应立即显示新网卡数据,
// 无需等下一次 calculateSpeed(1 秒后)才更新
if (m_interfaces.contains(m_activeInterface)) {
m_totalDownload = m_interfaces[m_activeInterface].rxBytes;
m_totalUpload = m_interfaces[m_activeInterface].txBytes;
emit totalChanged();
}
} }
} }
@@ -1036,7 +1027,7 @@ void NetworkMonitorApplet::appendToTrafficLog(qint64 rxDelta, qint64 txDelta)
m_trafficLog[QStringLiteral("byMonth")] = byMonth; m_trafficLog[QStringLiteral("byMonth")] = byMonth;
} }
// 裁剪超期记录:按日最多 90 天、按月最多 24 个月,超出删除最旧记录 // 裁剪超期记录:按日最多 30 天、按月最多 12 个月,超出删除最旧记录
// 日期/月份均为 ISO 格式("yyyy-MM-dd"/"yyyy-MM"),字典序即时间序, // 日期/月份均为 ISO 格式("yyyy-MM-dd"/"yyyy-MM"),字典序即时间序,
// 排序后取最小的超量个删除,保证始终保留最近的记录 // 排序后取最小的超量个删除,保证始终保留最近的记录
void NetworkMonitorApplet::pruneTrafficLog() void NetworkMonitorApplet::pruneTrafficLog()
+4 -4
View File
@@ -212,7 +212,7 @@ private:
void saveTrafficLog(); void saveTrafficLog();
// 将本次流量增量累加到当日/当月/当前活动接口的日志记录中(每秒调用,内存操作) // 将本次流量增量累加到当日/当月/当前活动接口的日志记录中(每秒调用,内存操作)
void appendToTrafficLog(qint64 rxDelta, qint64 txDelta); void appendToTrafficLog(qint64 rxDelta, qint64 txDelta);
// 裁剪超期记录:按日最多 90 天、按月最多 24 个月,超出删除最旧记录 // 裁剪超期记录:按日最多 30 天、按月最多 12 个月,超出删除最旧记录
void pruneTrafficLog(); void pruneTrafficLog();
QTimer *m_refreshTimer; QTimer *m_refreshTimer;
@@ -303,9 +303,9 @@ private:
// 降频保存计数器:每 30 秒(按刷新间隔折算)写盘一次并通知 QML, // 降频保存计数器:每 30 秒(按刷新间隔折算)写盘一次并通知 QML,
// 避免每秒磁盘 IO 与 QML 重绘;析构函数再兜底保存一次 // 避免每秒磁盘 IO 与 QML 重绘;析构函数再兜底保存一次
int m_trafficSaveCounter; int m_trafficSaveCounter;
// 按日记录最多保留 90 天、按月最多保留 24 个月,超出自动裁剪最旧记录 // 按日记录最多保留 30 天、按月最多保留 12 个月,超出自动裁剪最旧记录
static constexpr int MAX_DAY_ENTRIES = 90; static constexpr int MAX_DAY_ENTRIES = 30;
static constexpr int MAX_MONTH_ENTRIES = 24; static constexpr int MAX_MONTH_ENTRIES = 12;
// ---- TCP 连接清单成员 ---- // ---- TCP 连接清单成员 ----
// TCP 连接详情列表(QVariantList of QVariantMap),供 QML 连接清单窗口读取 // TCP 连接详情列表(QVariantList of QVariantMap),供 QML 连接清单窗口读取
+73
View File
@@ -275,6 +275,11 @@
<source>Traffic Statistics</source> <source>Traffic Statistics</source>
<translation>流量统计</translation> <translation>流量统计</translation>
</message> </message>
<message>
<location filename="../package/networkview.qml" line="389"/>
<source>TCP Connections</source>
<translation>TCP 连接</translation>
</message>
</context> </context>
<context> <context>
<name>TrafficStatsWindow</name> <name>TrafficStatsWindow</name>
@@ -339,4 +344,72 @@
<translation>暂无流量记录</translation> <translation>暂无流量记录</translation>
</message> </message>
</context> </context>
<context>
<name>TcpConnectionsWindow</name>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="132"/>
<source>TCP Connections</source>
<translation>TCP 连接</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="148"/>
<source>Active connections: </source>
<translation>活跃连接:</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="159"/>
<source>Search address, port, process...</source>
<translation>搜索地址、端口、进程...</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="191"/>
<source>Refreshes every </source>
<translation>每 </translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="190"/>
<source> seconds</source>
<translation> 秒刷新</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="204"/>
<source>Local Address:Port</source>
<translation>本地地址:端口</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="211"/>
<source>Remote Address:Port</source>
<translation>远程地址:端口</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="218"/>
<source>State</source>
<translation>状态</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="225"/>
<source>Process</source>
<translation>进程</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="265"/>
<source>No active TCP connections</source>
<translation>无活跃 TCP 连接</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="265"/>
<source>No matching connections</source>
<translation>无匹配连接</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="340"/>
<source>Total: </source>
<translation>共计:</translation>
</message>
<message>
<location filename="../package/components/TcpConnectionsWindow.qml" line="340"/>
<source> connections</source>
<translation> 个连接</translation>
</message>
</context>
</TS> </TS>