import QtQuick import "../services" as S Column { id: root required property color accentColor property bool active: true readonly property color _stateColor: S.BatteryService.charging ? S.Theme.base0B : S.BatteryService.critical ? S.Theme.base09 : S.BatteryService.percent < S.BatteryService.warnThresh ? S.Theme.base0A : root.accentColor // 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.percent) + "%" + (ts ? " " + ts : ""); } color: root._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.percent / 100) height: parent.height color: root._stateColor radius: 3 Behavior on width { enabled: root.active 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) SparklineCanvas { anchors.left: parent.left anchors.leftMargin: 12 anchors.right: parent.right anchors.rightMargin: 12 height: 44 history: S.BatteryService.history color: root._stateColor active: root.active maxSamples: 1440 backgroundTint: 0.07 areaMode: true thresholds: [ { value: S.BatteryService.warnThresh, color: S.Theme.base0A }, { value: S.BatteryService.critThresh, color: S.Theme.base08 } ] } // 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 {} // Rate row InfoRow { visible: S.BatteryService.changeRate !== 0 height: 20 label: S.BatteryService.charging ? "Charging" : "Discharging" value: { const r = Math.abs(S.BatteryService.changeRate); return r > 0 ? r.toFixed(1) + " W" : ""; } valueColor: root._stateColor } // Wattage history sparkline SparklineCanvas { visible: S.BatteryService.rateHistory.length > 1 anchors.left: parent.left anchors.leftMargin: 12 anchors.right: parent.right anchors.rightMargin: 12 height: 24 history: S.BatteryService.rateHistory color: root._stateColor active: root.active maxSamples: 60 maxValue: null minValue: null backgroundTint: 0.08 colorFunction: v => v >= 0 ? S.Theme.base0B : root._stateColor } // Health row InfoRow { visible: S.BatteryService.healthSupported height: 20 label: "Health" value: Math.round(S.BatteryService.healthPercent) + "%" valueColor: { const h = S.BatteryService.healthPercent; return h < 50 ? S.Theme.base08 : h < 75 ? S.Theme.base0A : S.Theme.base0B; } } Item { width: 1 height: 4 } }