Files
homelab/dotfiles/quickshell/widgets/bar/DenseBarContent.qml
T
darmanandClaude Opus 5 01bc169180 refactor(quickshell): rework the panel chrome, extract it as StatusBarPanel
The dense bar's panel chrome gets a squarer outline (top-right and bottom-left
chamfers only, square on the other two corners) and a second accent line in
the lower right to balance the existing upper-left one.

The chrome then moves out of DenseBarContent's inline `component
TelemetryPanel` into its own file. The call sites are unchanged apart from the
name -- children still come from the default property -- and the widgets they
pass in (RadarGauge, NetworkTrace, MetricBlock) stay declared in
DenseBarContent, so their scope is unaffected by moving only the definition.

Two things could not come along and had to be reproduced locally, because a
component in its own file has no access to the enclosing scope:

  - the palette and the two font families, previously read off `root`. They
    are properties with defaults matching DenseBarContent's, which is this
    repo's per-component convention. Duplicated on purpose for now; a shared
    theme singleton is the place to collapse it.
  - MicroText, which is an *inline* component of DenseBarContent and so
    invisible from another file. Expanded to the Text it desugars to.

Also qualified the bare offsetY/chamfer/accentLineThickness references as
panel.*; they resolved through the component scope before, but being explicit
avoids ComponentBehavior: Bound warnings in the new file.

Verified the move was verbatim by normalising the old inline block and the new
file body and diffing them -- the only differences are the relocated property
block, the panel.* qualification and the MicroText expansion. Loads clean both
headlessly and in the real layer-shell shell.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgcWkm3t6BDQktYHQvb8Hx
2026-08-28 07:55:59 +02:00

697 lines
25 KiB
QML

pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Shapes
// Renderable visual core for the desktop telemetry rail. Runtime services stay
// in DenseBar.qml so this Item can be exercised without Wayland or Hyprland.
Item {
id: root
implicitWidth: 1920
implicitHeight: 164
readonly property color voidColor: "#0a0a0a"
readonly property color inkColor: "#dedede"
readonly property color mutedColor: "#858585"
readonly property color accentColor: "#e8722a"
readonly property color hairColor: Qt.rgba(0.87, 0.87, 0.87, 0.28)
readonly property bool compact: width <= 1400
readonly property string displayFont: "DepartureMono Nerd Font"
readonly property string microFont: "DejaVu Sans Mono"
property bool autoClock: true
property date now: new Date()
property string hostName: "LOCAL"
property bool telemetryReady: false
property bool ratesReady: false
property real cpuFraction: 0
property int cpuThreads: 0
property real memoryFraction: 0
property string memoryUsedText: "--"
property real temperatureCelsius: NaN
property string networkInterface: "NET"
property string networkRxText: "--"
property string networkTxText: "--"
property real storageFraction: 0
property string storageFreeText: "-- FREE"
property var workspaceIds: [1, 2, 3, 4]
property int activeWorkspaceId: 1
property int trayCount: 0
property real audioFraction: 0
property bool audioMuted: false
signal workspaceActivated(int workspaceId)
function pct(value, ready) {
return ready ? Math.round(Math.max(0, Math.min(1, value)) * 100) : 0;
}
function two(value) {
return value < 10 ? "0" + value : String(value);
}
function timeText(value) {
return root.two(value.getHours()) + ":" + root.two(value.getMinutes());
}
function dateText(value) {
const days = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
const months = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
return days[value.getDay()] + " // " + root.two(value.getDate()) + " " + months[value.getMonth()];
}
Timer {
interval: 30000
running: root.autoClock
repeat: true
triggeredOnStart: true
onTriggered: root.now = new Date()
}
// Faint drafting grid; no gradient and deliberately subordinate to data.
Repeater {
model: Math.ceil(root.width / 40)
Rectangle {
required property int index
x: index * 40
width: 1
height: root.height
color: root.inkColor
opacity: 0.018
}
}
Repeater {
model: Math.ceil(root.height / 40)
Rectangle {
required property int index
y: index * 40
width: root.width
height: 1
color: root.inkColor
opacity: 0.018
}
}
Item {
id: array
x: 12
y: 8
width: root.width - 24
height: 92
readonly property real identityWidth: root.compact ? 250 : 320
readonly property real radarWidth: root.compact ? 130 : 164
readonly property real stateWidth: root.compact ? 210 : 250
readonly property real flexWidth: Math.max(250, (width - identityWidth - radarWidth - stateWidth - 32) / 2)
Row {
anchors.fill: parent
spacing: 8
StatusBarPanel {
width: array.identityWidth
height: array.height
panelId: "001"
title: "COMMAND LAYER"
Text {
x: 12
y: 34
text: root.hostName.toUpperCase()
color: root.inkColor
font.family: root.displayFont
font.pixelSize: root.compact ? 20 : 25
font.bold: true
font.letterSpacing: 2
elide: Text.ElideRight
width: parent.width - 92
}
Text {
x: 13
y: 63
text: "STATUS ARRAY // " + (root.telemetryReady ? "LIVE" : "STANDBY")
color: root.accentColor
font.family: root.microFont
font.pixelSize: 7
font.letterSpacing: 1.4
}
Rectangle {
x: parent.width - 75
y: 36
width: 1
height: 43
color: root.hairColor
}
Rectangle {
x: parent.width - 62
y: 42
width: 5
height: 5
color: root.accentColor
opacity: root.telemetryReady ? 1 : 0.35
}
Text {
x: parent.width - 50
y: 38
text: root.telemetryReady ? "ONLINE" : "LOCAL"
color: root.accentColor
font.family: root.microFont
font.pixelSize: 7
}
Text {
x: parent.width - 63
y: 57
text: "NODE // " + (root.hostName || "--").toUpperCase().slice(0, 7)
color: root.mutedColor
font.family: root.microFont
font.pixelSize: 6
}
Shape {
x: parent.width - 63
y: 71
width: 48
height: 10
ShapePath {
fillColor: "transparent"
strokeColor: root.accentColor
strokeWidth: 1
startX: 0; startY: 6
PathLine { x: 11; y: 6 }
PathLine { x: 16; y: 1 }
PathLine { x: 22; y: 9 }
PathLine { x: 27; y: 6 }
PathLine { x: 48; y: 6 }
}
}
}
StatusBarPanel {
width: array.flexWidth
height: array.height
panelId: "02"
title: "RESOURCE LATTICE"
meta: root.telemetryReady ? "REALTIME" : "FALLBACK"
Row {
x: 11
y: 32
width: parent.width - 22
height: 51
spacing: root.compact ? 7 : 12
MetricBlock {
width: (parent.width - parent.spacing * (root.compact ? 1 : 2)) / (root.compact ? 2 : 3)
label: "CPU"
value: root.cpuFraction
ready: root.ratesReady
readout: root.ratesReady ? root.pct(root.cpuFraction, true) + "%" : "--"
detailLeft: "CORE:" + (root.cpuThreads || "--")
detailRight: root.ratesReady ? "BUSY" : "PRIME"
}
MetricBlock {
width: (parent.width - parent.spacing * (root.compact ? 1 : 2)) / (root.compact ? 2 : 3)
label: "MEM"
value: root.memoryFraction
ready: root.telemetryReady
readout: root.telemetryReady ? root.pct(root.memoryFraction, true) + "%" : "--"
detailLeft: "ALLOC"
detailRight: root.memoryUsedText
}
MetricBlock {
visible: !root.compact
width: (parent.width - parent.spacing * 2) / 3
label: "THERM"
value: isFinite(root.temperatureCelsius) ? root.temperatureCelsius / 100 : 0
ready: isFinite(root.temperatureCelsius)
readout: isFinite(root.temperatureCelsius) ? Math.round(root.temperatureCelsius) + "°C" : "--"
detailLeft: "ZONE:01"
detailRight: isFinite(root.temperatureCelsius) && root.temperatureCelsius >= 85 ? "HOT" : "NOMINAL"
}
}
}
StatusBarPanel {
width: array.radarWidth
height: array.height
panelId: "03"
title: "SCAN"
RadarGauge {
anchors.horizontalCenter: parent.horizontalCenter
y: 28
size: 57
level: root.cpuFraction
}
}
StatusBarPanel {
width: array.flexWidth
height: array.height
panelId: "04"
title: "CARRIER UPLINK"
meta: root.networkInterface.toUpperCase()
NetworkTrace {
x: 12
y: 43
width: parent.width - (root.compact ? 117 : 145)
height: 33
level: root.ratesReady ? root.cpuFraction : 0.25
}
Column {
anchors.right: parent.right
anchors.rightMargin: 14
y: 34
width: root.compact ? 92 : 116
spacing: 1
Text {
width: parent.width
text: root.networkRxText
horizontalAlignment: Text.AlignRight
color: root.accentColor
font.family: root.displayFont
font.pixelSize: root.compact ? 11 : 13
font.bold: true
elide: Text.ElideLeft
}
MicroText { width: parent.width; text: "RX // DOWN"; horizontalAlignment: Text.AlignRight }
Text {
width: parent.width
text: root.networkTxText
horizontalAlignment: Text.AlignRight
color: root.inkColor
font.family: root.displayFont
font.pixelSize: root.compact ? 11 : 13
font.bold: true
elide: Text.ElideLeft
}
MicroText { width: parent.width; text: "TX // UP"; horizontalAlignment: Text.AlignRight }
}
}
StatusBarPanel {
width: array.stateWidth
height: array.height
panelId: "05"
title: "SYSTEM STATE"
Row {
x: 10
y: 35
spacing: 6
StateCell { code: "N"; active: root.ratesReady; label: "NET" }
StateCell { code: root.audioMuted ? "M" : "A"; active: !root.audioMuted; label: "AUD" }
StateCell { visible: !root.compact; code: String(root.trayCount); active: root.trayCount > 0; label: "TRAY" }
}
Rectangle {
x: root.compact ? 101 : 151
y: 33
width: 1
height: 46
color: root.hairColor
}
Column {
anchors.right: parent.right
anchors.rightMargin: 12
y: 34
width: root.compact ? 91 : 82
spacing: 2
Text {
width: parent.width
text: root.timeText(root.now)
horizontalAlignment: Text.AlignRight
color: root.inkColor
font.family: root.displayFont
font.pixelSize: root.compact ? 20 : 22
font.bold: true
font.letterSpacing: 1
}
Text {
width: parent.width
text: root.dateText(root.now)
horizontalAlignment: Text.AlignRight
color: root.accentColor
font.family: root.microFont
font.pixelSize: 6
elide: Text.ElideLeft
}
MicroText { width: parent.width; text: "LOCAL TIME"; horizontalAlignment: Text.AlignRight }
}
}
}
}
StatusBarPanel {
id: rail
x: 12
y: 108
width: root.width - 24
height: 34
showHeader: false
chamfer: 10
Row {
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10
RailSection {
width: root.compact ? 252 : 310
Text {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: "06 // DESKTOP"
color: root.accentColor
font.family: root.microFont
font.pixelSize: 7
font.letterSpacing: 1
}
Row {
anchors.right: parent.right
anchors.rightMargin: 8
anchors.verticalCenter: parent.verticalCenter
spacing: 3
Repeater {
model: root.workspaceIds.slice(0, root.compact ? 4 : 6)
Rectangle {
required property var modelData
width: 24
height: 17
color: Number(modelData) === root.activeWorkspaceId ? Qt.rgba(0.91, 0.45, 0.16, 0.18) : "transparent"
border.width: 1
border.color: Number(modelData) === root.activeWorkspaceId ? root.accentColor : root.hairColor
Text {
anchors.centerIn: parent
text: root.two(Number(parent.modelData))
color: Number(parent.modelData) === root.activeWorkspaceId ? root.accentColor : root.mutedColor
font.family: root.microFont
font.pixelSize: 7
}
MouseArea {
anchors.fill: parent
onClicked: root.workspaceActivated(Number(parent.modelData))
}
}
}
}
}
RailSection {
width: root.compact ? 260 : 410
MicroText { x: 9; anchors.verticalCenter: parent.verticalCenter; text: "PROCESS" }
Text {
x: 76
anchors.verticalCenter: parent.verticalCenter
text: "COMPOSITOR // NODE_EXPORTER // SHELL"
color: root.telemetryReady ? root.inkColor : root.mutedColor
font.family: root.microFont
font.pixelSize: 7
elide: Text.ElideRight
width: parent.width - 84
}
}
RailSection {
width: root.compact ? 300 : 385
MicroText { x: 9; anchors.verticalCenter: parent.verticalCenter; text: "VOL // ROOT" }
Text {
x: 93
anchors.verticalCenter: parent.verticalCenter
text: root.storageFreeText
color: root.inkColor
font.family: root.microFont
font.pixelSize: 8
}
SegmentMeter {
anchors.right: parent.right
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
width: root.compact ? 95 : 170
height: 7
segments: root.compact ? 10 : 16
value: root.storageFraction
ready: root.telemetryReady
}
}
RailSection {
visible: !root.compact
width: 350
MicroText { x: 9; anchors.verticalCenter: parent.verticalCenter; text: "AUDIO BUS" }
Text {
x: 89
anchors.verticalCenter: parent.verticalCenter
text: root.audioMuted ? "MUTED" : Math.round(root.audioFraction * 100) + "%"
color: root.audioMuted ? root.mutedColor : root.accentColor
font.family: root.microFont
font.pixelSize: 8
}
SegmentMeter {
anchors.right: parent.right
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
width: 155
height: 7
segments: 16
value: root.audioFraction
ready: true
}
}
RailSection {
width: Math.max(150, rail.width - (root.compact ? 812 : 1455) - 20)
borderVisible: false
MicroText { x: 9; anchors.verticalCenter: parent.verticalCenter; text: root.compact ? "SYS // " + root.timeText(root.now) : "EVENTS" }
Text {
anchors.right: parent.right
anchors.rightMargin: 8
anchors.verticalCenter: parent.verticalCenter
text: root.telemetryReady ? "WARN:00 // ERR:00" : "TELEMETRY WAIT"
color: root.telemetryReady ? root.mutedColor : root.accentColor
font.family: root.microFont
font.pixelSize: 7
elide: Text.ElideLeft
width: parent.width - 64
horizontalAlignment: Text.AlignRight
}
}
}
}
// Bottom routing trace and caution hatch.
Shape {
x: 12
y: 150
width: root.width - 24
height: 12
ShapePath {
fillColor: "transparent"
strokeColor: Qt.rgba(0.91, 0.45, 0.16, 0.55)
strokeWidth: 1
startX: 0; startY: 1
PathLine { x: 220; y: 1 }
PathLine { x: 232; y: 11 }
PathLine { x: 330; y: 11 }
}
}
Row {
x: 360
y: 151
width: root.width - 372
height: 3
spacing: 5
clip: true
Repeater {
model: Math.ceil(parent.width / 10)
Rectangle {
required property int index
width: 5
height: 3
color: index % 2 === 0 ? root.accentColor : "transparent"
opacity: 0.58
}
}
}
component MicroText: Text {
color: root.mutedColor
font.family: root.microFont
font.pixelSize: 6
font.letterSpacing: 0.7
}
component RailSection: Item {
property bool borderVisible: true
height: rail.height
Rectangle {
visible: parent.borderVisible
anchors.right: parent.right
width: 1
height: parent.height
color: root.hairColor
opacity: 0.65
}
}
component MetricBlock: Item {
id: metric
property string label: ""
property real value: 0
property bool ready: false
property string readout: "--"
property string detailLeft: ""
property string detailRight: ""
height: 51
MicroText { x: 0; y: 1; text: metric.label; font.pixelSize: 7 }
Text {
anchors.right: parent.right
y: -3
text: metric.readout
color: root.inkColor
font.family: root.displayFont
font.pixelSize: root.compact ? 14 : 17
font.bold: true
}
SegmentMeter {
x: 0; y: 19
width: parent.width
height: 9
segments: 10
value: metric.value
ready: metric.ready
}
MicroText { x: 0; y: 34; text: metric.detailLeft }
MicroText { anchors.right: parent.right; y: 34; text: metric.detailRight; horizontalAlignment: Text.AlignRight }
}
component SegmentMeter: Row {
id: meter
property int segments: 10
property real value: 0
property bool ready: false
spacing: 2
Repeater {
model: meter.segments
Rectangle {
required property int index
width: Math.max(2, (meter.width - (meter.segments - 1) * meter.spacing) / meter.segments)
height: meter.height
readonly property bool on: meter.ready && index < Math.round(Math.max(0, Math.min(1, meter.value)) * meter.segments)
color: on ? root.accentColor : Qt.rgba(0.87, 0.87, 0.87, 0.06)
border.width: 1
border.color: on ? root.accentColor : Qt.rgba(0.87, 0.87, 0.87, 0.18)
}
}
}
component StateCell: Item {
id: state
property string code: "--"
property string label: ""
property bool active: false
width: root.compact ? 39 : 43
height: 42
Shape {
anchors.fill: parent
ShapePath {
fillColor: state.active ? Qt.rgba(0.91, 0.45, 0.16, 0.18) : "transparent"
strokeColor: state.active ? root.accentColor : root.hairColor
strokeWidth: 1
startX: 1; startY: 1
PathLine { x: parent.width - 7; y: 1 }
PathLine { x: parent.width - 1; y: 7 }
PathLine { x: parent.width - 1; y: parent.height - 1 }
PathLine { x: 7; y: parent.height - 1 }
PathLine { x: 1; y: parent.height - 7 }
PathLine { x: 1; y: 1 }
}
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
y: 7
text: state.code
color: state.active ? root.accentColor : root.inkColor
font.family: root.displayFont
font.pixelSize: 13
font.bold: true
}
MicroText { anchors.horizontalCenter: parent.horizontalCenter; y: 27; text: state.label }
}
component RadarGauge: Item {
id: radar
property real size: 58
property real level: 0
width: size
height: size
Repeater {
model: [1, 0.72, 0.36]
Rectangle {
required property int index
required property var modelData
anchors.centerIn: parent
width: radar.size * Number(modelData)
height: width
radius: width / 2
color: "transparent"
border.width: 1
border.color: index === 0 ? root.accentColor : root.hairColor
}
}
Rectangle { x: 0; y: parent.height / 2; width: parent.width; height: 1; color: root.hairColor }
Rectangle { x: parent.width / 2; y: 0; width: 1; height: parent.height; color: root.hairColor }
Rectangle { x: 12; y: 18; width: 4; height: 4; color: root.accentColor }
Rectangle { x: parent.width - 14; y: parent.height - 20; width: 4; height: 4; color: root.accentColor }
Rectangle { x: parent.width / 2; y: parent.height - 11; width: 4; height: 4; color: root.accentColor }
MicroText { anchors.right: parent.right; y: 3; text: "R:" + Math.round(radar.level * 99); color: root.accentColor }
}
component NetworkTrace: Item {
id: trace
property real level: 0
Rectangle { x: 0; y: parent.height - 1; width: parent.width; height: 1; color: root.hairColor }
Rectangle { x: 0; y: 0; width: 1; height: parent.height; color: root.hairColor }
Shape {
anchors.fill: parent
ShapePath {
fillColor: "transparent"
strokeColor: root.accentColor
strokeWidth: 1.2
startX: 0; startY: trace.height * 0.65
PathLine { x: trace.width * 0.10; y: trace.height * 0.65 }
PathLine { x: trace.width * 0.15; y: trace.height * (0.25 + trace.level * 0.15) }
PathLine { x: trace.width * 0.21; y: trace.height * 0.78 }
PathLine { x: trace.width * 0.31; y: trace.height * 0.56 }
PathLine { x: trace.width * 0.43; y: trace.height * 0.62 }
PathLine { x: trace.width * 0.49; y: trace.height * 0.18 }
PathLine { x: trace.width * 0.57; y: trace.height * 0.82 }
PathLine { x: trace.width * 0.68; y: trace.height * 0.58 }
PathLine { x: trace.width * 0.79; y: trace.height * 0.62 }
PathLine { x: trace.width * 0.85; y: trace.height * 0.34 }
PathLine { x: trace.width * 0.91; y: trace.height * 0.75 }
PathLine { x: trace.width; y: trace.height * 0.60 }
}
}
}
}