extract BatteryApplet from BatteryModule

This commit is contained in:
Damocles 2026-04-22 21:17:34 +02:00
parent 57d42d7ac3
commit a0cb1d991d
3 changed files with 284 additions and 269 deletions

View file

@ -2,6 +2,7 @@ import QtQuick
import Quickshell
import "." as M
import "../services" as S
import "../applets" as C
M.BarSection {
id: root
@ -57,7 +58,7 @@ M.BarSection {
if (S.BatteryService.charging)
return "\uDB80\uDC84";
const icons = ["\uDB80\uDC8E", "\uDB80\uDC7A", "\uDB80\uDC7B", "\uDB80\uDC7C", "\uDB80\uDC7D", "\uDB80\uDC7E", "\uDB80\uDC7F", "\uDB80\uDC80", "\uDB80\uDC81", "\uDB80\uDC82", "\uDB85\uDFE2"];
return icons[Math.min(10, Math.floor(S.BatteryService.pct / 10))];
return icons[Math.min(10, Math.floor(S.BatteryService.percent / 10))];
}
color: S.BatteryService.stateColor
opacity: root._blinkOpacity
@ -68,7 +69,7 @@ M.BarSection {
}
}
M.BarLabel {
label: Math.round(S.BatteryService.pct) + "%"
label: Math.round(S.BatteryService.percent) + "%"
minText: "100%"
color: S.BatteryService.stateColor
opacity: root._blinkOpacity
@ -89,273 +90,10 @@ M.BarSection {
panelTitle: "Battery"
contentWidth: 240
// Header - pct + time
Item {
width: parent.width
height: 28
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: {
const t = S.BatteryService.charging ? S.BatteryService.timeToFull : S.BatteryService.timeToEmpty;
const ts = S.BatteryService.fmtTime(t);
return Math.round(S.BatteryService.pct) + "%" + (ts ? " " + ts : "");
}
color: S.BatteryService.stateColor
font.pixelSize: S.Theme.fontSize
font.family: S.Theme.fontFamily
font.bold: true
}
}
// Progress bar
Item {
width: parent.width
height: 14
Item {
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: S.Theme.base02
radius: 3
}
Rectangle {
width: parent.width * Math.min(1, S.BatteryService.pct / 100)
height: parent.height
color: S.BatteryService.stateColor
radius: 3
Behavior on width {
enabled: root._showPanel
NumberAnimation {
duration: 300
easing.type: Easing.OutCubic
}
}
}
// Warning threshold marker
Rectangle {
x: parent.width * (S.BatteryService.warnThresh / 100) - 1
width: 1
height: parent.height + 4
anchors.verticalCenter: parent.verticalCenter
color: S.Theme.base0A
opacity: 0.6
}
// Critical threshold marker
Rectangle {
x: parent.width * (S.BatteryService.critThresh / 100) - 1
width: 1
height: parent.height + 4
anchors.verticalCenter: parent.verticalCenter
color: S.Theme.base08
opacity: 0.6
}
}
}
// 24h history sparkline (area chart)
Canvas {
id: _sparkline
anchors.left: parent.left
anchors.leftMargin: 12
anchors.right: parent.right
anchors.rightMargin: 12
height: 44
property var _hist: S.BatteryService.history
property color _col: S.BatteryService.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 < 2)
return;
const maxSamples = 1440;
const xScale = width / maxSamples;
const xOffset = (maxSamples - d.length) * xScale;
// Background tint
ctx.fillStyle = Qt.rgba(_col.r, _col.g, _col.b, 0.07).toString();
ctx.fillRect(0, 0, width, height);
// Warning threshold line
const warnY = height - height * (S.BatteryService.warnThresh / 100);
ctx.strokeStyle = S.Theme.base0A.toString();
ctx.globalAlpha = 0.3;
ctx.lineWidth = 1;
ctx.setLineDash([3, 3]);
ctx.beginPath();
ctx.moveTo(0, warnY);
ctx.lineTo(width, warnY);
ctx.stroke();
// Critical threshold line
const critY = height - height * (S.BatteryService.critThresh / 100);
ctx.strokeStyle = S.Theme.base08.toString();
ctx.beginPath();
ctx.moveTo(0, critY);
ctx.lineTo(width, critY);
ctx.stroke();
ctx.setLineDash([]);
ctx.globalAlpha = 1.0;
// Filled area under the curve
ctx.beginPath();
ctx.moveTo(xOffset, height);
for (let i = 0; i < d.length; i++) {
const x = xOffset + i * xScale;
const y = height - height * (d[i] / 100);
ctx.lineTo(x, y);
}
ctx.lineTo(xOffset + (d.length - 1) * xScale, height);
ctx.closePath();
ctx.fillStyle = Qt.rgba(_col.r, _col.g, _col.b, 0.18).toString();
ctx.fill();
// Top line
ctx.beginPath();
for (let i = 0; i < d.length; i++) {
const x = xOffset + i * xScale;
const y = height - height * (d[i] / 100);
if (i === 0)
ctx.moveTo(x, y);
else
ctx.lineTo(x, y);
}
ctx.strokeStyle = _col.toString();
ctx.lineWidth = 1.5;
ctx.stroke();
}
}
// Footer: thresholds + time label
Item {
width: parent.width
height: 16
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "warn " + S.BatteryService.warnThresh + "% crit " + S.BatteryService.critThresh + "%"
color: S.Theme.base03
font.pixelSize: S.Theme.fontSize - 3
font.family: S.Theme.fontFamily
font.letterSpacing: 0.5
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "24h"
color: S.Theme.base03
font.pixelSize: S.Theme.fontSize - 3
font.family: S.Theme.fontFamily
}
}
// Separator
Rectangle {
width: parent.width - 16
height: 1
anchors.horizontalCenter: parent.horizontalCenter
color: S.Theme.base03
}
// Rate row
Item {
width: parent.width
height: 20
visible: S.BatteryService.changeRate !== 0
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: S.BatteryService.charging ? "Charging" : "Discharging"
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: {
const r = Math.abs(S.BatteryService.changeRate);
return r > 0 ? r.toFixed(1) + " W" : "";
}
color: S.BatteryService.stateColor
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
}
}
// Health row
Item {
width: parent.width
height: 20
visible: S.BatteryService.healthSupported
Text {
anchors.left: parent.left
anchors.leftMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: "Health"
color: S.Theme.base04
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
}
Text {
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: Math.round(S.BatteryService.healthPct) + "%"
color: {
const h = S.BatteryService.healthPct;
return h < 50 ? S.Theme.base08 : h < 75 ? S.Theme.base0A : S.Theme.base0B;
}
font.pixelSize: S.Theme.fontSize - 2
font.family: S.Theme.fontFamily
}
}
Item {
width: 1
height: 4
C.BatteryApplet {
width: hoverPanel.contentWidth
active: root._showPanel
accentColor: root.accentColor
}
}
}