k8s-widget: add KubernetesPopout and complete bar wiring

This commit is contained in:
2026-04-22 01:49:40 +02:00
parent 7261824837
commit e868eb29aa
2 changed files with 283 additions and 1 deletions

View File

@@ -144,7 +144,7 @@ Scope {
required property var modelData
screen: modelData
visible: modelData.name === Shared.Config.monitor && (popoutOpen || notifSlot.animating || mediaSlot.animating || weatherSlot.animating || datetimeSlot.animating || systemSlot.animating)
visible: modelData.name === Shared.Config.monitor && (popoutOpen || notifSlot.animating || mediaSlot.animating || weatherSlot.animating || datetimeSlot.animating || systemSlot.animating || kubernetesSlot.animating)
WlrLayershell.namespace: "quickshell:popout"
surfaceFormat { opaque: false }
@@ -212,6 +212,13 @@ Scope {
verticalAnchor: "bottom"
sourceComponent: Popouts.SystemPopout { panelWindow: popoutWindow }
}
PopoutSlot {
id: kubernetesSlot
name: "kubernetes"
verticalAnchor: "bottom"
sourceComponent: Popouts.KubernetesPopout {}
}
}
// PopoutSlot — anchored to triggering icon, MD3 animation

View File

@@ -0,0 +1,275 @@
import Quickshell
import QtQuick
import QtQuick.Layouts
import "../../shared" as Shared
Item {
id: root
implicitWidth: Shared.Theme.popoutWidth
implicitHeight: col.implicitHeight + Shared.Theme.popoutPadding * 2
PopoutBackground { anchors.fill: parent }
MouseArea { anchors.fill: parent }
component QuotaBar: Column {
property string rowLabel: ""
property string valueLabel: ""
property real fill: 0
property color barColor: Shared.Theme.green
property real barOpacity: 1.0
Layout.fillWidth: true
width: parent.width
spacing: 3
RowLayout {
width: parent.width
Text {
text: rowLabel
color: Shared.Theme.overlay0
font.pixelSize: 9
font.family: Shared.Theme.fontFamily
}
Item { Layout.fillWidth: true }
Text {
text: valueLabel
color: Shared.Theme.subtext0
font.pixelSize: 9
font.family: Shared.Theme.fontFamily
}
Text {
text: Math.round(fill * 100) + "%"
color: barColor
font.pixelSize: 9
font.family: Shared.Theme.fontFamily
}
}
Rectangle {
width: parent.width
height: 4
color: Shared.Theme.surface1
radius: 2
Rectangle {
width: Math.max(0, Math.min(1, parent.parent.fill)) * parent.width
height: parent.height
color: parent.parent.barColor
opacity: parent.parent.barOpacity
radius: 2
}
}
}
ColumnLayout {
id: col
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Shared.Theme.popoutPadding
spacing: 8
// ── Header ────────────────────────────────────────────
RowLayout {
Layout.fillWidth: true
Text {
text: "K8s — " + Shared.Config.kubeNamespace
color: Shared.Theme.text
font.pixelSize: 16
font.family: Shared.Theme.fontFamily
font.bold: true
Layout.fillWidth: true
}
Text {
text: "\u{f03be}"
color: {
let s = Shared.Kubernetes.status;
if (s === "ok") return Shared.Theme.green;
if (s === "degraded") return Shared.Theme.yellow;
if (s === "error") return Shared.Theme.red;
if (s === "stale") return Shared.Theme.overlay0;
return Shared.Theme.blue;
}
font.pixelSize: 20
font.family: Shared.Theme.iconFont
}
}
// ── Pods section ──────────────────────────────────────
Text {
text: "PODS"
color: Shared.Theme.overlay0
font.pixelSize: 9
font.family: Shared.Theme.fontFamily
font.letterSpacing: 1
}
RowLayout {
Layout.fillWidth: true
spacing: 4
Item { Layout.fillWidth: true }
Text { text: "CPU"; color: Shared.Theme.overlay0; font.pixelSize: 8; font.family: Shared.Theme.fontFamily; Layout.preferredWidth: 44; horizontalAlignment: Text.AlignRight }
Text { text: "MEM"; color: Shared.Theme.overlay0; font.pixelSize: 8; font.family: Shared.Theme.fontFamily; Layout.preferredWidth: 52; horizontalAlignment: Text.AlignRight }
Text { text: "STATUS"; color: Shared.Theme.overlay0; font.pixelSize: 8; font.family: Shared.Theme.fontFamily; Layout.preferredWidth: 62; horizontalAlignment: Text.AlignRight }
}
Repeater {
model: Shared.Kubernetes.pods
delegate: Rectangle {
required property var modelData
Layout.fillWidth: true
implicitHeight: 28
color: Shared.Theme.surface0
radius: Shared.Theme.radiusSmall
RowLayout {
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10
spacing: 4
Text {
text: modelData.app
color: Shared.Theme.text
font.pixelSize: 11
font.family: Shared.Theme.fontFamily
Layout.fillWidth: true
elide: Text.ElideRight
}
Text {
text: modelData.cpuM === -1 ? "—" : modelData.cpuM + "m"
color: Shared.Theme.sky
font.pixelSize: 11
font.family: Shared.Theme.fontFamily
Layout.preferredWidth: 44
horizontalAlignment: Text.AlignRight
}
Text {
text: modelData.memMi === -1 ? "—" : modelData.memMi + "Mi"
color: Shared.Theme.mauve
font.pixelSize: 11
font.family: Shared.Theme.fontFamily
Layout.preferredWidth: 52
horizontalAlignment: Text.AlignRight
}
RowLayout {
spacing: 3
Layout.preferredWidth: 62
layoutDirection: Qt.RightToLeft
Text {
text: modelData.ready ? "Ready" : "NotReady"
color: modelData.ready ? Shared.Theme.green : Shared.Theme.red
font.pixelSize: 10
font.family: Shared.Theme.fontFamily
}
Text {
text: "●"
color: modelData.ready ? Shared.Theme.green : Shared.Theme.red
font.pixelSize: 9
}
}
}
}
}
// ── Quota section ─────────────────────────────────────
Text {
text: "QUOTA"
color: Shared.Theme.overlay0
font.pixelSize: 9
font.family: Shared.Theme.fontFamily
font.letterSpacing: 1
topPadding: 4
}
Rectangle {
Layout.fillWidth: true
color: Shared.Theme.surface0
radius: Shared.Theme.radiusSmall
implicitHeight: cpuCardCol.implicitHeight + 20
Column {
id: cpuCardCol
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 12
anchors.verticalCenter: parent.verticalCenter
spacing: 6
RowLayout {
width: parent.width
Text { text: "CPU"; color: Shared.Theme.sky; font.pixelSize: 10; font.family: Shared.Theme.fontFamily; font.bold: true }
Item { Layout.fillWidth: true }
Text {
text: Shared.Kubernetes.quota ? Shared.Kubernetes.quota.cpuActualM + "m actual" : "—"
color: Shared.Theme.text
font.pixelSize: 10
font.family: Shared.Theme.fontFamily
}
}
QuotaBar {
rowLabel: "%REQ"
valueLabel: Shared.Kubernetes.quota?.cpuReqLabel ?? ""
fill: Shared.Kubernetes.quota?.cpuReqPct ?? 0
barColor: Shared.Theme.green
}
QuotaBar {
rowLabel: "%LIM"
valueLabel: Shared.Kubernetes.quota?.cpuLimLabel ?? ""
fill: Shared.Kubernetes.quota?.cpuLimPct ?? 0
barColor: Shared.Theme.yellow
barOpacity: 0.6
}
}
}
Rectangle {
Layout.fillWidth: true
color: Shared.Theme.surface0
radius: Shared.Theme.radiusSmall
implicitHeight: memCardCol.implicitHeight + 20
Column {
id: memCardCol
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: 12
anchors.verticalCenter: parent.verticalCenter
spacing: 6
RowLayout {
width: parent.width
Text { text: "MEM"; color: Shared.Theme.mauve; font.pixelSize: 10; font.family: Shared.Theme.fontFamily; font.bold: true }
Item { Layout.fillWidth: true }
Text {
text: Shared.Kubernetes.quota ? Shared.Kubernetes.quota.memActualMi + "Mi actual" : "—"
color: Shared.Theme.text
font.pixelSize: 10
font.family: Shared.Theme.fontFamily
}
}
QuotaBar {
rowLabel: "%REQ"
valueLabel: Shared.Kubernetes.quota?.memReqLabel ?? ""
fill: Shared.Kubernetes.quota?.memReqPct ?? 0
barColor: Shared.Theme.mauve
}
QuotaBar {
rowLabel: "%LIM"
valueLabel: Shared.Kubernetes.quota?.memLimLabel ?? ""
fill: Shared.Kubernetes.quota?.memLimPct ?? 0
barColor: Shared.Theme.mauve
barOpacity: 0.6
}
}
}
// ── Footer ────────────────────────────────────────────
Text {
text: "Updated " + Shared.Kubernetes.lastUpdatedSecs + "s ago"
color: Shared.Theme.overlay0
font.pixelSize: 9
font.family: Shared.Theme.fontFamily
Layout.alignment: Qt.AlignRight
}
}
}