From cb936e93be75bae93fbd5a81f39376cd31142e71 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 16 Oct 2026 09:34:51 +0200 Subject: docs(spec): user details in the drawer A drawer row greets the login user and opens a page that edits name, email, avatar, language and location, written where other programs already read them: AccountsService (and through it the passwd GECOS LibreOffice reads), KDE's emaildefaults and the global git config, with the surname shortened to an initial for git. Co-Authored-By: Claude Opus 5.5 --- desktop/island/perf/PerfPanel.qml | 336 -------------------------------------- 1 file changed, 336 deletions(-) delete mode 100644 desktop/island/perf/PerfPanel.qml (limited to 'desktop/island/perf/PerfPanel.qml') diff --git a/desktop/island/perf/PerfPanel.qml b/desktop/island/perf/PerfPanel.qml deleted file mode 100644 index f149d82..0000000 --- a/desktop/island/perf/PerfPanel.qml +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright (C) 2026 Danilo M. -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2 as -// published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -import Quickshell -import QtQuick -import QtQuick.Layouts -import "../.." -import "Perf.js" as P - -// CPU, GPU, network and disks as cards in three columns: CPU down the left, -// GPU and network beside it, disks under those two. Numbers come from Perf; -// colours follow conky's bands, so they read as they did there. -GridLayout { - id: panel - - columns: 3 - columnSpacing: 8 - rowSpacing: 8 - - readonly property real col: (width - 2 * columnSpacing) / 3 - readonly property var gpuTemp: sensor("GPU") - readonly property var vramTemp: sensor("VRAM") - - function tone(v, warn, crit) { - const b = P.band(v, warn, crit); - return b === "crit" ? Theme.red : b === "warn" ? Theme.yellow : b === "ok" ? Theme.green : Theme.subtext; - } - function deg(v) { return v === null ? "--" : Math.round(v) + "°"; } - function sensor(label) { - return Perf.temps.find(t => t.label === label) || { value: null, warn: 0, crit: 0 }; - } - // Detailed sampling (per-core, network, VRAM, fan) runs while any panel - // exists. The island loads one only while open and the drawer page only - // while shown, so counting instances is the whole gate, and two of them - // never clear it under each other. - Component.onCompleted: Perf.viewers++ - Component.onDestruction: Perf.viewers-- - - function pct(part, whole) { return part === null || !whole ? null : 100 * part / whole; } - function last(list) { return list.length ? list[list.length - 1] : null; } - // Conky's glyphs, re-checked in Inconsolata Nerd Font. - function glyph(d) { - if (d.host) return String.fromCodePoint(0xF06F3); // network share - return String.fromCodePoint({ "/": 0xF318, "/home": 0xF015 }[d.mount] ?? 0xF02CA); - } - - component Label: Text { - font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } - color: Theme.text - } - - // A label left, a value right, an optional glyph before the label. - component Pair: Item { - property string glyph: "" - property string label: "" - property string value: "" - property color labelColor: Theme.subtext - property color valueColor: Theme.text - width: parent ? parent.width : 0 - implicitHeight: valueText.implicitHeight - - Row { - spacing: 6 - Text { - visible: text !== "" - text: parent.parent.glyph - font { family: Theme.iconFamily; pixelSize: Theme.fontSize - 2 } - color: parent.parent.labelColor - } - Label { text: parent.parent.label; color: parent.parent.labelColor } - } - Label { - id: valueText - anchors.right: parent.right - text: parent.value - color: parent.valueColor - } - } - - component Bar: Rectangle { - property real frac: 0 - property color fill: Theme.green - width: parent ? parent.width : 0 - height: 5 - radius: 3 - color: Theme.surfaceAlt - Rectangle { - width: parent.width * Math.max(0, Math.min(1, parent.frac)) - height: parent.height - radius: 3 - color: parent.fill - } - } - - component Card: Rectangle { - default property alias content: body.data - property string title: "" - property string headline: "" - property color headlineColor: Theme.text - radius: 10 - color: Qt.alpha(Theme.surface, 0.6) - implicitHeight: body.implicitHeight + 20 - Layout.fillHeight: true - - Column { - id: body - x: 10 - y: 10 - width: parent.width - 20 - spacing: 5 - - Item { - width: parent.width - height: Math.max(titleText.implicitHeight, headText.implicitHeight) - Text { - id: titleText - anchors.verticalCenter: parent.verticalCenter - text: parent.parent.parent.title - font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4; bold: true } - color: Theme.subtext - } - Text { - id: headText - anchors.right: parent.right - text: parent.parent.parent.headline - font { family: Theme.fontFamily; pixelSize: Theme.fontSize + 4; bold: true } - color: parent.parent.parent.headlineColor - } - } - } - } - - // --- CPU ---------------------------------------------------------------- - - Card { - Layout.row: 0 - Layout.column: 0 - Layout.rowSpan: 2 - Layout.preferredWidth: panel.col - title: "CPU" - headline: Perf.load === null ? "--" : Math.round(Perf.load) + "%" - headlineColor: panel.tone(Perf.load, 25, 75) - - Label { - width: parent.width - text: Perf.cpuModel - color: Theme.subtext - elide: Text.ElideRight - } - - // One bar per core, rising from a common baseline. - Row { - id: eq - width: parent.width - height: 40 - spacing: 2 - Repeater { - model: Perf.cores - delegate: Item { - required property var modelData - width: (eq.width - eq.spacing * (Perf.cores.length - 1)) / Perf.cores.length - height: eq.height - Rectangle { - anchors.bottom: parent.bottom - width: parent.width - height: Math.max(1, parent.height * modelData / 100) - radius: 1 - color: panel.tone(modelData, 25, 75) - } - } - } - } - - Pair { - label: "RAM" - value: Perf.mem ? P.bytes(Perf.mem.used) + " / " + P.bytes(Perf.mem.total) : "--" - } - Bar { - frac: Perf.mem ? Perf.mem.used / Perf.mem.total : 0 - fill: panel.tone(panel.pct(Perf.mem ? Perf.mem.used : null, Perf.mem ? Perf.mem.total : 0), 25, 75) - } - - Repeater { - model: Perf.temps.filter(t => t.label !== "GPU" && t.label !== "VRAM") - delegate: Pair { - required property var modelData - label: modelData.label - value: panel.deg(modelData.value) - valueColor: panel.tone(modelData.value, modelData.warn, modelData.crit) - } - } - } - - // --- GPU ---------------------------------------------------------------- - - // No utilisation: xe exposes no busy percentage. - Card { - Layout.row: 0 - Layout.column: 1 - Layout.preferredWidth: panel.col - title: "GPU · " + Perf.gpuName - headline: panel.deg(panel.gpuTemp.value) - headlineColor: panel.tone(panel.gpuTemp.value, panel.gpuTemp.warn, panel.gpuTemp.crit) - - Pair { - label: "VRAM" - value: Perf.vram === null ? "--" : P.bytes(Perf.vram) + " / " + P.bytes(Perf.vramTotal) - } - Bar { - frac: (Perf.vram ?? 0) / Perf.vramTotal - fill: panel.tone(panel.pct(Perf.vram, Perf.vramTotal), 25, 75) - } - Pair { - label: "VRAM temp" - value: panel.deg(panel.vramTemp.value) - valueColor: panel.tone(panel.vramTemp.value, panel.vramTemp.warn, panel.vramTemp.crit) - } - Pair { - label: "Fan" - value: Perf.fan === null ? "--" : Perf.fan + " rpm" - } - } - - // --- network ------------------------------------------------------------ - - Card { - Layout.row: 0 - Layout.column: 2 - Layout.preferredWidth: panel.col - title: "NET · " + Perf.iface - - Canvas { - id: graph - width: parent.width - height: 44 - onPaint: { - const ctx = getContext("2d"); - ctx.reset(); - const max = Math.max(1, ...Perf.rx, ...Perf.tx); - const line = (data, color) => { - ctx.strokeStyle = color; - ctx.lineWidth = 1.5; - ctx.beginPath(); - data.forEach((v, i) => { - const x = width * i / 59; - const y = height - 1 - (height - 2) * v / max; - if (i) ctx.lineTo(x, y); else ctx.moveTo(x, y); - }); - ctx.stroke(); - }; - line(Perf.rx, Theme.teal); - line(Perf.tx, Theme.peach); - } - Connections { - target: Perf - function onRxChanged() { graph.requestPaint(); } - function onTxChanged() { graph.requestPaint(); } - } - } - - Pair { - label: "↓ " + P.speed(panel.last(Perf.rx)) - labelColor: Theme.teal - value: "↑ " + P.speed(panel.last(Perf.tx)) - valueColor: Theme.peach - } - Pair { label: "LAN"; value: Perf.lan || "--" } - - // The public IP, red when it differs from the pinned one. The pin - // stores the address shown; it is lit while they are the same. - Item { - width: parent.width - height: pubText.implicitHeight - - Label { text: "Public"; color: Theme.subtext } - Label { - id: pubText - anchors { right: pin.left; rightMargin: 6 } - text: Perf.ip.ip || "--" - color: Perf.ip.mismatch ? Theme.red : Theme.text - } - Text { - id: pin - anchors { right: parent.right; verticalCenter: pubText.verticalCenter } - text: String.fromCodePoint(0xF0403) - font { family: Theme.iconFamily; pixelSize: Theme.fontSize - 2 } - color: Perf.ip.ip !== "" && Perf.ip.ip === Prefs.pinnedIp ? Theme.text : Theme.overlay - - MouseArea { - anchors.fill: parent - anchors.margins: -4 - enabled: Perf.ip.ip !== "" - cursorShape: Qt.PointingHandCursor - onClicked: Prefs.setPinnedIp(Perf.ip.ip) - } - } - } - } - - // --- disks -------------------------------------------------------------- - - Card { - Layout.row: 1 - Layout.column: 1 - Layout.columnSpan: 2 - Layout.preferredWidth: 2 * panel.col + panel.columnSpacing - title: "DISKS" - - Repeater { - model: Perf.disks - delegate: Column { - required property var modelData - width: parent.width - spacing: 2 - Pair { - glyph: panel.glyph(modelData) - label: modelData.host || modelData.mount - value: modelData.pct + "% · " + P.bytes(modelData.used) + " / " + P.bytes(modelData.size) - valueColor: panel.tone(modelData.pct, 25, 75) - } - Bar { - frac: modelData.pct / 100 - fill: panel.tone(modelData.pct, 25, 75) - } - } - } - } -} -- cgit v1.2.3