diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ProcessList/PerformanceView.qml')
| -rw-r--r-- | raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ProcessList/PerformanceView.qml | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ProcessList/PerformanceView.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ProcessList/PerformanceView.qml new file mode 100644 index 0000000..c793d92 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/ProcessList/PerformanceView.qml @@ -0,0 +1,304 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs.Common +import qs.Services +import qs.Widgets + +Item { + id: root + + readonly property int historySize: 60 + + property var cpuHistory: [] + property var memoryHistory: [] + property var networkRxHistory: [] + property var networkTxHistory: [] + property var diskReadHistory: [] + property var diskWriteHistory: [] + + function formatBytes(bytes) { + if (bytes < 1024) + return bytes.toFixed(0) + " B/s"; + if (bytes < 1024 * 1024) + return (bytes / 1024).toFixed(1) + " KB/s"; + if (bytes < 1024 * 1024 * 1024) + return (bytes / (1024 * 1024)).toFixed(1) + " MB/s"; + return (bytes / (1024 * 1024 * 1024)).toFixed(2) + " GB/s"; + } + + function addToHistory(arr, val) { + const newArr = arr.slice(); + newArr.push(val); + if (newArr.length > historySize) + newArr.shift(); + return newArr; + } + + function sampleData() { + cpuHistory = addToHistory(cpuHistory, DgopService.cpuUsage); + memoryHistory = addToHistory(memoryHistory, DgopService.memoryUsage); + networkRxHistory = addToHistory(networkRxHistory, DgopService.networkRxRate); + networkTxHistory = addToHistory(networkTxHistory, DgopService.networkTxRate); + diskReadHistory = addToHistory(diskReadHistory, DgopService.diskReadRate); + diskWriteHistory = addToHistory(diskWriteHistory, DgopService.diskWriteRate); + } + + Component.onCompleted: { + DgopService.addRef(["cpu", "memory", "network", "disk", "diskmounts", "system"]); + } + + Component.onDestruction: { + DgopService.removeRef(["cpu", "memory", "network", "disk", "diskmounts", "system"]); + } + + SystemClock { + id: sampleClock + precision: SystemClock.Seconds + onDateChanged: { + if (date.getSeconds() % 1 === 0) + root.sampleData(); + } + } + + ColumnLayout { + anchors.fill: parent + spacing: Theme.spacingM + + RowLayout { + Layout.fillWidth: true + Layout.preferredHeight: (root.height - Theme.spacingM * 2) / 2 + spacing: Theme.spacingM + + PerformanceCard { + Layout.fillWidth: true + Layout.fillHeight: true + title: "CPU" + icon: "memory" + value: DgopService.cpuUsage.toFixed(1) + "%" + subtitle: DgopService.cpuModel || (DgopService.cpuCores + " cores") + accentColor: Theme.primary + history: root.cpuHistory + maxValue: 100 + showSecondary: false + extraInfo: DgopService.cpuTemperature > 0 ? (DgopService.cpuTemperature.toFixed(0) + "°C") : "" + extraInfoColor: DgopService.cpuTemperature > 80 ? Theme.error : (DgopService.cpuTemperature > 60 ? Theme.warning : Theme.surfaceVariantText) + } + + PerformanceCard { + Layout.fillWidth: true + Layout.fillHeight: true + title: I18n.tr("Memory") + icon: "sd_card" + value: DgopService.memoryUsage.toFixed(1) + "%" + subtitle: DgopService.formatSystemMemory(DgopService.usedMemoryKB) + " / " + DgopService.formatSystemMemory(DgopService.totalMemoryKB) + accentColor: Theme.secondary + history: root.memoryHistory + maxValue: 100 + showSecondary: false + extraInfo: DgopService.totalSwapKB > 0 ? ("Swap: " + DgopService.formatSystemMemory(DgopService.usedSwapKB)) : "" + extraInfoColor: Theme.surfaceVariantText + } + } + + RowLayout { + Layout.fillWidth: true + Layout.preferredHeight: (root.height - Theme.spacingM * 2) / 2 + spacing: Theme.spacingM + + PerformanceCard { + Layout.fillWidth: true + Layout.fillHeight: true + title: I18n.tr("Network") + icon: "swap_horiz" + value: "↓ " + root.formatBytes(DgopService.networkRxRate) + subtitle: "↑ " + root.formatBytes(DgopService.networkTxRate) + accentColor: Theme.info + history: root.networkRxHistory + history2: root.networkTxHistory + maxValue: 0 + showSecondary: true + extraInfo: "" + extraInfoColor: Theme.surfaceVariantText + } + + PerformanceCard { + Layout.fillWidth: true + Layout.fillHeight: true + title: I18n.tr("Disk") + icon: "storage" + value: "R: " + root.formatBytes(DgopService.diskReadRate) + subtitle: "W: " + root.formatBytes(DgopService.diskWriteRate) + accentColor: Theme.warning + history: root.diskReadHistory + history2: root.diskWriteHistory + maxValue: 0 + showSecondary: true + extraInfo: { + const rootMount = DgopService.diskMounts.find(m => m.mountpoint === "/"); + if (rootMount) { + const usedPct = ((rootMount.used || 0) / Math.max(1, rootMount.total || 1) * 100).toFixed(0); + return "/ " + usedPct + "% used"; + } + return ""; + } + extraInfoColor: Theme.surfaceVariantText + } + } + } + + component PerformanceCard: Rectangle { + id: card + + property string title: "" + property string icon: "" + property string value: "" + property string subtitle: "" + property color accentColor: Theme.primary + property var history: [] + property var history2: null + property real maxValue: 100 + property bool showSecondary: false + property string extraInfo: "" + property color extraInfoColor: Theme.surfaceVariantText + + radius: Theme.cornerRadius + color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) + border.color: Theme.outlineLight + border.width: 1 + + Canvas { + id: graphCanvas + anchors.fill: parent + anchors.margins: 4 + renderStrategy: Canvas.Cooperative + + property var hist: card.history + property var hist2: card.history2 + + onHistChanged: requestPaint() + onHist2Changed: requestPaint() + onWidthChanged: requestPaint() + onHeightChanged: requestPaint() + + onPaint: { + const ctx = getContext("2d"); + ctx.reset(); + ctx.clearRect(0, 0, width, height); + + if (!hist || hist.length < 2) + return; + + let max = card.maxValue; + if (max <= 0) { + max = 1; + for (let k = 0; k < hist.length; k++) + max = Math.max(max, hist[k]); + if (hist2) { + for (let l = 0; l < hist2.length; l++) + max = Math.max(max, hist2[l]); + } + max *= 1.1; + } + + const c = card.accentColor; + const grad = ctx.createLinearGradient(0, 0, 0, height); + grad.addColorStop(0, Qt.rgba(c.r, c.g, c.b, 0.25)); + grad.addColorStop(1, Qt.rgba(c.r, c.g, c.b, 0.02)); + + ctx.fillStyle = grad; + ctx.beginPath(); + ctx.moveTo(0, height); + for (let i = 0; i < hist.length; i++) { + const x = (width / (root.historySize - 1)) * i; + const y = height - (hist[i] / max) * height * 0.8; + ctx.lineTo(x, y); + } + ctx.lineTo((width / (root.historySize - 1)) * (hist.length - 1), height); + ctx.closePath(); + ctx.fill(); + + ctx.strokeStyle = Qt.rgba(c.r, c.g, c.b, 0.8); + ctx.lineWidth = 2; + ctx.beginPath(); + for (let j = 0; j < hist.length; j++) { + const px = (width / (root.historySize - 1)) * j; + const py = height - (hist[j] / max) * height * 0.8; + j === 0 ? ctx.moveTo(px, py) : ctx.lineTo(px, py); + } + ctx.stroke(); + + if (hist2 && hist2.length >= 2 && card.showSecondary) { + ctx.strokeStyle = Qt.rgba(c.r, c.g, c.b, 0.4); + ctx.lineWidth = 1.5; + ctx.setLineDash([4, 4]); + ctx.beginPath(); + for (let m = 0; m < hist2.length; m++) { + const sx = (width / (root.historySize - 1)) * m; + const sy = height - (hist2[m] / max) * height * 0.8; + m === 0 ? ctx.moveTo(sx, sy) : ctx.lineTo(sx, sy); + } + ctx.stroke(); + ctx.setLineDash([]); + } + } + } + + ColumnLayout { + anchors.fill: parent + anchors.margins: Theme.spacingM + spacing: Theme.spacingXS + + RowLayout { + Layout.fillWidth: true + spacing: Theme.spacingS + + DankIcon { + name: card.icon + size: Theme.iconSize + color: card.accentColor + } + + StyledText { + text: card.title + font.pixelSize: Theme.fontSizeLarge + font.weight: Font.Bold + color: Theme.surfaceText + } + + Item { + Layout.fillWidth: true + } + + StyledText { + text: card.extraInfo + font.pixelSize: Theme.fontSizeSmall + font.family: SettingsData.monoFontFamily + color: card.extraInfoColor + visible: card.extraInfo.length > 0 + } + } + + Item { + Layout.fillHeight: true + } + + StyledText { + text: card.value + font.pixelSize: Theme.fontSizeXLarge + font.family: SettingsData.monoFontFamily + font.weight: Font.Bold + color: Theme.surfaceText + } + + StyledText { + text: card.subtitle + font.pixelSize: Theme.fontSizeSmall + font.family: SettingsData.monoFontFamily + color: Theme.surfaceVariantText + elide: Text.ElideRight + Layout.fillWidth: true + } + } + } +} |