mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-07 14:05:38 -05:00
Add Performance tab under Process monitor
This commit is contained in:
@@ -10,7 +10,7 @@ Singleton {
|
||||
// Process list properties
|
||||
property var processes: []
|
||||
property bool isUpdating: false
|
||||
property int processUpdateInterval: 1500
|
||||
property int processUpdateInterval: 3000
|
||||
|
||||
// Performance control - only run when process monitor is actually visible
|
||||
property bool monitoringEnabled: false
|
||||
@@ -24,6 +24,26 @@ Singleton {
|
||||
property real totalCpuUsage: 0.0
|
||||
property bool systemInfoAvailable: false
|
||||
|
||||
// Performance history for charts
|
||||
property var cpuHistory: []
|
||||
property var memoryHistory: []
|
||||
property var networkHistory: ({rx: [], tx: []})
|
||||
property var diskHistory: ({read: [], write: []})
|
||||
property int historySize: 60 // Keep 60 data points
|
||||
|
||||
// Per-core CPU usage
|
||||
property var perCoreCpuUsage: []
|
||||
|
||||
// Network stats
|
||||
property real networkRxRate: 0 // bytes/sec
|
||||
property real networkTxRate: 0 // bytes/sec
|
||||
property var lastNetworkStats: null
|
||||
|
||||
// Disk I/O stats
|
||||
property real diskReadRate: 0 // bytes/sec
|
||||
property real diskWriteRate: 0 // bytes/sec
|
||||
property var lastDiskStats: null
|
||||
|
||||
// Sorting options
|
||||
property string sortBy: "cpu" // "cpu", "memory", "name", "pid"
|
||||
property bool sortDescending: true
|
||||
@@ -33,12 +53,39 @@ Singleton {
|
||||
console.log("ProcessMonitorService: Starting initialization...")
|
||||
updateProcessList()
|
||||
console.log("ProcessMonitorService: Initialization complete")
|
||||
|
||||
// Test monitoring disabled - only monitor when explicitly enabled
|
||||
// testTimer.start()
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: testTimer
|
||||
interval: 3000
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
console.log("ProcessMonitorService: Starting test monitoring...")
|
||||
enableMonitoring(true)
|
||||
// Stop after 8 seconds
|
||||
stopTestTimer.start()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: stopTestTimer
|
||||
interval: 8000
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
console.log("ProcessMonitorService: Stopping test monitoring...")
|
||||
enableMonitoring(false)
|
||||
}
|
||||
}
|
||||
|
||||
// System information monitoring
|
||||
Process {
|
||||
id: systemInfoProcess
|
||||
command: ["bash", "-c", "cat /proc/meminfo; echo '---CPU---'; nproc; echo '---CPUSTAT---'; grep '^cpu ' /proc/stat"]
|
||||
command: ["bash", "-c", "cat /proc/meminfo; echo '---CPU---'; nproc; echo '---CPUSTAT---'; grep '^cpu' /proc/stat | head -" + (root.cpuCount + 1)]
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
@@ -57,6 +104,36 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
// Network monitoring process
|
||||
Process {
|
||||
id: networkStatsProcess
|
||||
command: ["bash", "-c", "cat /proc/net/dev | grep -E '(wlan|eth|enp|wlp|ens|eno)' | awk '{print $1,$2,$10}' | sed 's/:/ /'"]
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
if (text.trim()) {
|
||||
parseNetworkStats(text.trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disk I/O monitoring process
|
||||
Process {
|
||||
id: diskStatsProcess
|
||||
command: ["bash", "-c", "cat /proc/diskstats | grep -E ' (sd[a-z]+|nvme[0-9]+n[0-9]+|vd[a-z]+) ' | grep -v 'p[0-9]' | awk '{print $3,$6,$10}'"]
|
||||
running: false
|
||||
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
if (text.trim()) {
|
||||
parseDiskStats(text.trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process monitoring with ps command
|
||||
Process {
|
||||
id: processListProcess
|
||||
@@ -123,6 +200,8 @@ Singleton {
|
||||
if (root.monitoringEnabled) {
|
||||
updateSystemInfo()
|
||||
updateProcessList()
|
||||
updateNetworkStats()
|
||||
updateDiskStats()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,9 +218,29 @@ Singleton {
|
||||
console.log("ProcessMonitorService: Monitoring", enabled ? "enabled" : "disabled")
|
||||
root.monitoringEnabled = enabled
|
||||
if (enabled) {
|
||||
// Clear history when starting
|
||||
root.cpuHistory = []
|
||||
root.memoryHistory = []
|
||||
root.networkHistory = ({rx: [], tx: []})
|
||||
root.diskHistory = ({read: [], write: []})
|
||||
// Immediately update when enabled
|
||||
updateSystemInfo()
|
||||
updateProcessList()
|
||||
updateNetworkStats()
|
||||
updateDiskStats()
|
||||
// console.log("ProcessMonitorService: Initial data collection started")
|
||||
}
|
||||
}
|
||||
|
||||
function updateNetworkStats() {
|
||||
if (!networkStatsProcess.running && root.monitoringEnabled) {
|
||||
networkStatsProcess.running = true
|
||||
}
|
||||
}
|
||||
|
||||
function updateDiskStats() {
|
||||
if (!diskStatsProcess.running && root.monitoringEnabled) {
|
||||
diskStatsProcess.running = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,6 +343,7 @@ Singleton {
|
||||
function parseSystemInfo(text) {
|
||||
const lines = text.split('\n')
|
||||
let section = 'memory'
|
||||
const coreUsages = []
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i].trim()
|
||||
@@ -289,10 +389,103 @@ Singleton {
|
||||
const used = total - idle - iowait
|
||||
root.totalCpuUsage = total > 0 ? (used / total) * 100 : 0
|
||||
}
|
||||
} else if (line.match(/^cpu\d+/)) {
|
||||
const parts = line.split(/\s+/)
|
||||
if (parts.length >= 8) {
|
||||
const user = parseInt(parts[1])
|
||||
const nice = parseInt(parts[2])
|
||||
const system = parseInt(parts[3])
|
||||
const idle = parseInt(parts[4])
|
||||
const iowait = parseInt(parts[5])
|
||||
const irq = parseInt(parts[6])
|
||||
const softirq = parseInt(parts[7])
|
||||
|
||||
const total = user + nice + system + idle + iowait + irq + softirq
|
||||
const used = total - idle - iowait
|
||||
const usage = total > 0 ? (used / total) * 100 : 0
|
||||
coreUsages.push(usage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update per-core usage
|
||||
root.perCoreCpuUsage = coreUsages
|
||||
|
||||
// Update history
|
||||
addToHistory(root.cpuHistory, root.totalCpuUsage)
|
||||
const memoryPercent = root.totalMemoryKB > 0 ? (root.usedMemoryKB / root.totalMemoryKB) * 100 : 0
|
||||
addToHistory(root.memoryHistory, memoryPercent)
|
||||
|
||||
// console.log("ProcessMonitorService: Updated - CPU:", root.totalCpuUsage.toFixed(1) + "%", "Memory:", memoryPercent.toFixed(1) + "%", "History length:", root.cpuHistory.length)
|
||||
|
||||
root.systemInfoAvailable = true
|
||||
}
|
||||
|
||||
function parseNetworkStats(text) {
|
||||
const lines = text.split('\n')
|
||||
let totalRx = 0
|
||||
let totalTx = 0
|
||||
|
||||
for (const line of lines) {
|
||||
const parts = line.trim().split(/\s+/)
|
||||
if (parts.length >= 3) {
|
||||
const rx = parseInt(parts[1])
|
||||
const tx = parseInt(parts[2])
|
||||
if (!isNaN(rx) && !isNaN(tx)) {
|
||||
totalRx += rx
|
||||
totalTx += tx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (root.lastNetworkStats) {
|
||||
const timeDiff = root.processUpdateInterval / 1000
|
||||
root.networkRxRate = Math.max(0, (totalRx - root.lastNetworkStats.rx) / timeDiff)
|
||||
root.networkTxRate = Math.max(0, (totalTx - root.lastNetworkStats.tx) / timeDiff)
|
||||
|
||||
// Convert to KB/s for history
|
||||
addToHistory(root.networkHistory.rx, root.networkRxRate / 1024)
|
||||
addToHistory(root.networkHistory.tx, root.networkTxRate / 1024)
|
||||
}
|
||||
|
||||
root.lastNetworkStats = { rx: totalRx, tx: totalTx }
|
||||
}
|
||||
|
||||
function parseDiskStats(text) {
|
||||
const lines = text.split('\n')
|
||||
let totalRead = 0
|
||||
let totalWrite = 0
|
||||
|
||||
for (const line of lines) {
|
||||
const parts = line.trim().split(/\s+/)
|
||||
if (parts.length >= 3) {
|
||||
const readSectors = parseInt(parts[1])
|
||||
const writeSectors = parseInt(parts[2])
|
||||
if (!isNaN(readSectors) && !isNaN(writeSectors)) {
|
||||
totalRead += readSectors * 512 // Convert sectors to bytes
|
||||
totalWrite += writeSectors * 512
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (root.lastDiskStats) {
|
||||
const timeDiff = root.processUpdateInterval / 1000
|
||||
root.diskReadRate = Math.max(0, (totalRead - root.lastDiskStats.read) / timeDiff)
|
||||
root.diskWriteRate = Math.max(0, (totalWrite - root.lastDiskStats.write) / timeDiff)
|
||||
|
||||
// Convert to MB/s for history
|
||||
addToHistory(root.diskHistory.read, root.diskReadRate / (1024 * 1024))
|
||||
addToHistory(root.diskHistory.write, root.diskWriteRate / (1024 * 1024))
|
||||
}
|
||||
|
||||
root.lastDiskStats = { read: totalRead, write: totalWrite }
|
||||
}
|
||||
|
||||
function addToHistory(array, value) {
|
||||
array.push(value)
|
||||
if (array.length > root.historySize) {
|
||||
array.shift()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,10 +281,10 @@ PanelWindow {
|
||||
height: 80
|
||||
radius: Theme.cornerRadiusLarge
|
||||
color: ProcessMonitorService.totalSwapKB > 0 ?
|
||||
Qt.rgba(Theme.tertiary.r, Theme.tertiary.g, Theme.tertiary.b, 0.08) :
|
||||
Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.08) :
|
||||
Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.04)
|
||||
border.color: ProcessMonitorService.totalSwapKB > 0 ?
|
||||
Qt.rgba(Theme.tertiary.r, Theme.tertiary.g, Theme.tertiary.b, 0.2) :
|
||||
Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.2) :
|
||||
Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.12)
|
||||
border.width: 1
|
||||
|
||||
@@ -298,7 +298,7 @@ PanelWindow {
|
||||
text: "Swap"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: ProcessMonitorService.totalSwapKB > 0 ? Theme.tertiary : Theme.surfaceText
|
||||
color: ProcessMonitorService.totalSwapKB > 0 ? Theme.warning : Theme.surfaceText
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
|
||||
@@ -443,10 +443,10 @@ PanelWindow {
|
||||
height: 80
|
||||
radius: Theme.cornerRadiusLarge
|
||||
color: ProcessMonitorService.totalSwapKB > 0 ?
|
||||
Qt.rgba(Theme.tertiary.r, Theme.tertiary.g, Theme.tertiary.b, 0.08) :
|
||||
Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.08) :
|
||||
Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.04)
|
||||
border.color: ProcessMonitorService.totalSwapKB > 0 ?
|
||||
Qt.rgba(Theme.tertiary.r, Theme.tertiary.g, Theme.tertiary.b, 0.2) :
|
||||
Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.2) :
|
||||
Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.12)
|
||||
border.width: 1
|
||||
|
||||
@@ -460,7 +460,7 @@ PanelWindow {
|
||||
text: "Swap"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: ProcessMonitorService.totalSwapKB > 0 ? Theme.tertiary : Theme.surfaceText
|
||||
color: ProcessMonitorService.totalSwapKB > 0 ? Theme.warning : Theme.surfaceText
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
@@ -749,36 +749,365 @@ PanelWindow {
|
||||
// Define inline components for tabs
|
||||
Component {
|
||||
id: performanceTabComponent
|
||||
Rectangle {
|
||||
color: "transparent"
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingL
|
||||
anchors.fill: parent
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// CPU Section - Compact with per-core bars
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 200
|
||||
radius: Theme.cornerRadiusLarge
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
|
||||
border.width: 1
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// CPU Header with overall usage
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 32
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Text {
|
||||
text: "analytics"
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 48
|
||||
text: "CPU"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 80
|
||||
height: 24
|
||||
radius: Theme.cornerRadiusSmall
|
||||
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Text {
|
||||
text: ProcessMonitorService.totalCpuUsage.toFixed(1) + "%"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Bold
|
||||
color: Theme.primary
|
||||
opacity: 0.6
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: parent.width - 280; height: 1 }
|
||||
|
||||
Text {
|
||||
text: ProcessMonitorService.cpuCount + " cores"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
// Per-core CPU bars - Scrollable
|
||||
ScrollView {
|
||||
width: parent.width
|
||||
height: parent.height - 40
|
||||
clip: true
|
||||
ScrollBar.vertical.policy: ScrollBar.AsNeeded
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 6
|
||||
|
||||
Repeater {
|
||||
model: ProcessMonitorService.perCoreCpuUsage.length
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 20
|
||||
spacing: Theme.spacingS
|
||||
|
||||
// Core label
|
||||
Text {
|
||||
text: "C" + index
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: 24
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
// Usage bar
|
||||
Rectangle {
|
||||
width: parent.width - 80
|
||||
height: 6
|
||||
radius: 3
|
||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Rectangle {
|
||||
width: parent.width * Math.min(1.0, ProcessMonitorService.perCoreCpuUsage[index] / 100)
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
color: {
|
||||
const usage = ProcessMonitorService.perCoreCpuUsage[index]
|
||||
if (usage > 80) return Theme.error
|
||||
if (usage > 60) return Theme.warning
|
||||
return Theme.primary
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation { duration: Theme.shortDuration }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Usage percentage
|
||||
Text {
|
||||
text: ProcessMonitorService.perCoreCpuUsage[index] ?
|
||||
ProcessMonitorService.perCoreCpuUsage[index].toFixed(0) + "%" : "0%"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
width: 32
|
||||
horizontalAlignment: Text.AlignRight
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Memory Section - Simplified
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 80
|
||||
radius: Theme.cornerRadiusLarge
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
|
||||
border.width: 1
|
||||
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
text: "Memory"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Performance Monitoring"
|
||||
font.pixelSize: Theme.fontSizeLarge + 2
|
||||
text: ProcessMonitorService.formatSystemMemory(ProcessMonitorService.usedMemoryKB) +
|
||||
" / " + ProcessMonitorService.formatSystemMemory(ProcessMonitorService.totalMemoryKB)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: Theme.spacingL; height: 1 }
|
||||
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 4
|
||||
width: 200
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 16
|
||||
radius: 8
|
||||
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
|
||||
|
||||
Rectangle {
|
||||
width: ProcessMonitorService.totalMemoryKB > 0 ?
|
||||
parent.width * (ProcessMonitorService.usedMemoryKB / ProcessMonitorService.totalMemoryKB) : 0
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
color: {
|
||||
const usage = ProcessMonitorService.totalMemoryKB > 0 ?
|
||||
(ProcessMonitorService.usedMemoryKB / ProcessMonitorService.totalMemoryKB) : 0
|
||||
if (usage > 0.9) return Theme.error
|
||||
if (usage > 0.7) return Theme.warning
|
||||
return Theme.secondary
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
NumberAnimation { duration: Theme.mediumDuration }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: ProcessMonitorService.totalMemoryKB > 0 ?
|
||||
((ProcessMonitorService.usedMemoryKB / ProcessMonitorService.totalMemoryKB) * 100).toFixed(1) + "% used" :
|
||||
"No data"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: parent.width - 300; height: 1 }
|
||||
|
||||
// Swap info - compact
|
||||
Column {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 4
|
||||
visible: ProcessMonitorService.totalSwapKB > 0
|
||||
|
||||
Text {
|
||||
text: "Swap"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Bold
|
||||
color: Theme.warning
|
||||
}
|
||||
|
||||
Text {
|
||||
text: ProcessMonitorService.formatSystemMemory(ProcessMonitorService.usedSwapKB) +
|
||||
" / " + ProcessMonitorService.formatSystemMemory(ProcessMonitorService.totalSwapKB)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Network & Disk I/O - Combined compact view
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 80
|
||||
spacing: Theme.spacingM
|
||||
|
||||
// Network I/O
|
||||
Rectangle {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
height: 80
|
||||
radius: Theme.cornerRadiusLarge
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
|
||||
border.width: 1
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Text {
|
||||
text: "Network"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Real-time system performance charts\nwill be displayed here"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
text: "↓"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.info
|
||||
}
|
||||
|
||||
Text {
|
||||
text: formatNetworkSpeed(ProcessMonitorService.networkRxRate)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
text: "↑"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.error
|
||||
}
|
||||
|
||||
Text {
|
||||
text: formatNetworkSpeed(ProcessMonitorService.networkTxRate)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disk I/O
|
||||
Rectangle {
|
||||
width: (parent.width - Theme.spacingM) / 2
|
||||
height: 80
|
||||
radius: Theme.cornerRadiusLarge
|
||||
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.04)
|
||||
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.06)
|
||||
border.width: 1
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacingXS
|
||||
|
||||
Text {
|
||||
text: "Disk"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingS
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
text: "R"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.primary
|
||||
}
|
||||
|
||||
Text {
|
||||
text: formatDiskSpeed(ProcessMonitorService.diskReadRate)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
text: "W"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.warning
|
||||
}
|
||||
|
||||
Text {
|
||||
text: formatDiskSpeed(ProcessMonitorService.diskWriteRate)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Bold
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1168,4 +1497,27 @@ PanelWindow {
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions for formatting
|
||||
function formatNetworkSpeed(bytesPerSec) {
|
||||
if (bytesPerSec < 1024) {
|
||||
return bytesPerSec.toFixed(0) + " B/s"
|
||||
} else if (bytesPerSec < 1024 * 1024) {
|
||||
return (bytesPerSec / 1024).toFixed(1) + " KB/s"
|
||||
} else if (bytesPerSec < 1024 * 1024 * 1024) {
|
||||
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s"
|
||||
} else {
|
||||
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s"
|
||||
}
|
||||
}
|
||||
|
||||
function formatDiskSpeed(bytesPerSec) {
|
||||
if (bytesPerSec < 1024 * 1024) {
|
||||
return (bytesPerSec / 1024).toFixed(1) + " KB/s"
|
||||
} else if (bytesPerSec < 1024 * 1024 * 1024) {
|
||||
return (bytesPerSec / (1024 * 1024)).toFixed(1) + " MB/s"
|
||||
} else {
|
||||
return (bytesPerSec / (1024 * 1024 * 1024)).toFixed(1) + " GB/s"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user