extract panel contents into reusable content/ components

This commit is contained in:
Damocles 2026-04-17 21:44:44 +02:00
parent b27bb533da
commit e939a6b096
15 changed files with 1718 additions and 1547 deletions

View file

@ -1,6 +1,7 @@
import QtQuick
import Quickshell
import "." as M
import "content" as C
M.BarSection {
id: root
@ -45,15 +46,6 @@ M.BarSection {
onTriggered: root._pinned = false
}
// Returns a color interpolated greenyellowred for a given celsius value
function _tempColor(celsius) {
const t = Math.max(0, Math.min(100, celsius)) / 100;
const a = t < 0.5 ? M.Theme.base0B : M.Theme.base0A;
const b = t < 0.5 ? M.Theme.base0A : M.Theme.base08;
const u = t < 0.5 ? t * 2 : (t - 0.5) * 2;
return Qt.rgba(a.r + (b.r - a.r) * u, a.g + (b.g - a.g) * u, a.b + (b.b - a.b) * u, 1);
}
M.BarIcon {
icon: "\uF2C9"
color: root._stateColor
@ -84,243 +76,16 @@ M.BarSection {
panelTitle: "Temperature"
contentWidth: 220
// Header current temp
Item {
width: parent.width
height: 28
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: root._temp + "\u00B0C"
color: root._stateColor
font.pixelSize: M.Theme.fontSize
font.family: M.Theme.fontFamily
font.bold: true
width: _tempSizer.implicitWidth
horizontalAlignment: Text.AlignRight
Text {
id: _tempSizer
visible: false
text: "100\u00B0C"
font: parent.font
}
}
}
// Gauge bar (0100°C), with warm/hot threshold markers
Item {
width: parent.width
height: 16
Item {
id: _gaugeBar
anchors.left: parent.left
anchors.leftMargin: 12
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
height: 6
Rectangle {
anchors.fill: parent
color: M.Theme.base02
radius: 3
}
Rectangle {
width: parent.width * Math.min(1, root._temp / 100)
height: parent.height
color: root._stateColor
radius: 3
Behavior on width {
enabled: root._showPanel
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
}
// Warm threshold marker
Rectangle {
x: parent.width * (root._warm / 100) - 1
width: 1
height: parent.height + 4
anchors.verticalCenter: parent.verticalCenter
color: M.Theme.base0A
opacity: 0.6
}
// Hot threshold marker
Rectangle {
x: parent.width * (root._hot / 100) - 1
width: 1
height: parent.height + 4
anchors.verticalCenter: parent.verticalCenter
color: M.Theme.base08
opacity: 0.6
}
}
}
// History sparkline (~10 min @ 4s per sample)
Canvas {
id: _sparkline
anchors.left: parent.left
anchors.leftMargin: 12
anchors.right: parent.right
anchors.rightMargin: 12
height: 40
property var _hist: M.SystemStats.tempHistory
property color _col: root._stateColor
on_HistChanged: if (root._showPanel)
requestPaint()
on_ColChanged: if (root._showPanel)
requestPaint()
Connections {
target: root
function on_ShowPanelChanged() {
if (root._showPanel)
_sparkline.requestPaint();
}
}
onPaint: {
const ctx = getContext("2d");
if (!ctx)
return;
ctx.clearRect(0, 0, width, height);
const d = _hist;
if (!d.length)
return;
const maxSamples = 150;
const bw = width / maxSamples;
// Background tint
ctx.fillStyle = Qt.rgba(_col.r, _col.g, _col.b, 0.08).toString();
ctx.fillRect(0, 0, width, height);
// Warm threshold line
const warmY = height - height * (root._warm / 100);
ctx.strokeStyle = M.Theme.base0A.toString();
ctx.globalAlpha = 0.3;
ctx.lineWidth = 1;
ctx.setLineDash([3, 3]);
ctx.beginPath();
ctx.moveTo(0, warmY);
ctx.lineTo(width, warmY);
ctx.stroke();
// Hot threshold line
const hotY = height - height * (root._hot / 100);
ctx.strokeStyle = M.Theme.base08.toString();
ctx.beginPath();
ctx.moveTo(0, hotY);
ctx.lineTo(width, hotY);
ctx.stroke();
ctx.setLineDash([]);
ctx.globalAlpha = 1.0;
// Bars
const offset = maxSamples - d.length;
for (let i = 0; i < d.length; i++) {
const barH = Math.max(1, height * d[i] / 100);
const barColor = d[i] > root._hot ? M.Theme.base08 : d[i] > root._warm ? M.Theme.base0A : _col;
ctx.fillStyle = barColor.toString();
ctx.fillRect((offset + i) * bw, height - barH, Math.max(1, bw - 0.5), barH);
}
}
}
// Threshold labels
Item {
width: parent.width
height: 16
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "warm " + root._warm + "\u00B0 hot " + root._hot + "\u00B0"
color: M.Theme.base03
font.pixelSize: M.Theme.fontSize - 3
font.family: M.Theme.fontFamily
font.letterSpacing: 0.5
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "10 min"
color: M.Theme.base03
font.pixelSize: M.Theme.fontSize - 3
font.family: M.Theme.fontFamily
}
}
// Per-device breakdown
Rectangle {
width: parent.width - 16
height: 1
anchors.horizontalCenter: parent.horizontalCenter
color: M.Theme.base03
visible: M.SystemStats.tempDevices.length > 0
}
Repeater {
model: M.SystemStats.tempDevices
delegate: Item {
required property var modelData
width: hoverPanel.contentWidth
height: 22
readonly property bool _isActive: root._deviceFilter === modelData.name
Rectangle {
anchors.fill: parent
anchors.leftMargin: 8
anchors.rightMargin: 8
color: _isActive ? Qt.rgba(root.accentColor.r, root.accentColor.g, root.accentColor.b, 0.12) : "transparent"
radius: 3
}
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: modelData.name
color: _isActive ? root.accentColor : M.Theme.base04
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
elide: Text.ElideRight
width: parent.width - 80
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: modelData.celsius + "\u00B0C"
color: root._tempColor(modelData.celsius)
font.pixelSize: M.Theme.fontSize - 2
font.family: M.Theme.fontFamily
font.bold: _isActive
}
}
}
Item {
width: 1
height: 4
C.TemperatureContent {
width: hoverPanel.contentWidth
temp: root._temp
warm: root._warm
hot: root._hot
history: M.SystemStats.tempHistory
devices: M.SystemStats.tempDevices
accentColor: root.accentColor
deviceFilter: root._deviceFilter
active: root._showPanel
}
}
}