summaryrefslogtreecommitdiff
path: root/raveos-plasma-theme/theme-data/sddm/sddm-rave-theme/Components/BatteryIndicator.qml
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-plasma-theme/theme-data/sddm/sddm-rave-theme/Components/BatteryIndicator.qml')
-rw-r--r--raveos-plasma-theme/theme-data/sddm/sddm-rave-theme/Components/BatteryIndicator.qml257
1 files changed, 257 insertions, 0 deletions
diff --git a/raveos-plasma-theme/theme-data/sddm/sddm-rave-theme/Components/BatteryIndicator.qml b/raveos-plasma-theme/theme-data/sddm/sddm-rave-theme/Components/BatteryIndicator.qml
new file mode 100644
index 0000000..5497911
--- /dev/null
+++ b/raveos-plasma-theme/theme-data/sddm/sddm-rave-theme/Components/BatteryIndicator.qml
@@ -0,0 +1,257 @@
+import QtQuick 2.15
+import Qt.labs.folderlistmodel 2.15
+
+Row {
+ id: batteryIndicator
+
+ height: root.font.pointSize * 1.6
+ spacing: root.font.pointSize * 0.5
+
+ // -1 = nincs akkumulátor / nem laptop
+ property int batteryLevel: -1
+ property bool isCharging: false
+ property bool isFull: false
+ property string batteryPath: ""
+
+ visible: batteryLevel >= 0
+
+ // Ismert akksi elérési utak
+ property var tryPaths: [
+ "/sys/class/power_supply/BAT0/",
+ "/sys/class/power_supply/BAT1/",
+ "/sys/class/power_supply/BAT2/",
+ "/sys/class/power_supply/battery/",
+ "/sys/class/power_supply/BATT/"
+ ]
+
+ // Dinamikus akkumulátor kereső (pl. kontroller, UPS, egyéb külső akkuk észleléséhez)
+ FolderListModel {
+ id: powerSupplyScanner
+ folder: "file:///sys/class/power_supply"
+ showDirs: true
+ showFiles: false
+
+ onCountChanged: scan()
+ onFolderChanged: scan()
+
+ function scan() {
+ var defaults = [
+ "/sys/class/power_supply/BAT0/",
+ "/sys/class/power_supply/BAT1/",
+ "/sys/class/power_supply/BAT2/",
+ "/sys/class/power_supply/battery/",
+ "/sys/class/power_supply/BATT/"
+ ]
+ for (var i = 0; i < count; i++) {
+ var name = get(i, "fileName")
+ if (name && name !== "." && name !== "..") {
+ // Csak a tipikus laptop akkumulátor elnevezések (pl. BAT0, BAT1, BATT, battery)
+ var isLaptopBat = /^bat/i.test(name) || /^battery/i.test(name)
+ if (isLaptopBat) {
+ var fullPath = "/sys/class/power_supply/" + name + "/"
+ if (defaults.indexOf(fullPath) === -1) {
+ defaults.push(fullPath)
+ }
+ }
+ }
+ }
+ tryPaths = defaults
+ detectBattery(0)
+ }
+ }
+
+ // ── Fájl olvasó ──────────────────────────────────────────────────────────
+ function readFile(path, cb) {
+ var xhr = new XMLHttpRequest()
+ xhr.open("GET", "file://" + path, true)
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === XMLHttpRequest.DONE)
+ cb(xhr.responseText && xhr.responseText.trim() !== "" ? xhr.responseText.trim() : null)
+ }
+ xhr.send()
+ }
+
+ // ── Akkumulátor keresés és frissítés ─────────────────────────────────────
+ function detectBattery(idx) {
+ if (idx >= tryPaths.length) { batteryLevel = -1; return }
+ readFile(tryPaths[idx] + "capacity", function(cap) {
+ if (cap !== null) {
+ batteryPath = tryPaths[idx]
+ batteryLevel = Math.max(0, Math.min(100, parseInt(cap) || 0))
+ readFile(batteryPath + "status", function(st) {
+ var s = st ? st.toLowerCase() : ""
+ isFull = (s === "full")
+ isCharging = (s === "charging") || isFull
+ batteryCanvas.requestPaint()
+ })
+ } else {
+ detectBattery(idx + 1)
+ }
+ })
+ }
+
+ // ── Akkumulátor frissítés ────────────────────────────────────────────────
+ function refresh() {
+ if (batteryPath !== "") {
+ readFile(batteryPath + "capacity", function(cap) {
+ if (cap !== null) {
+ batteryLevel = Math.max(0, Math.min(100, parseInt(cap) || 0))
+ readFile(batteryPath + "status", function(st) {
+ var s = st ? st.toLowerCase() : ""
+ isFull = (s === "full")
+ isCharging = (s === "charging") || isFull
+ batteryCanvas.requestPaint()
+ })
+ }
+ })
+ } else {
+ powerSupplyScanner.scan()
+ }
+ }
+
+ Component.onCompleted: powerSupplyScanner.scan()
+
+ Timer {
+ interval: 30000
+ repeat: true
+ running: true
+ onTriggered: batteryIndicator.refresh()
+ }
+
+ // ── Szín a töltési szint alapján ─────────────────────────────────────────
+ function levelColor(lvl, charging) {
+ if (charging) return "#4ade80" // zöld – tölt
+ if (lvl > 60) return "#ffffff" // fehér – ok
+ if (lvl > 30) return "#facc15" // sárga – közepes
+ if (lvl > 15) return "#fb923c" // narancs – alacsony
+ return "#f87171" // piros – kritikus
+ }
+
+ // ── UI ───────────────────────────────────────────────────────────────────
+ Canvas {
+ id: batteryCanvas
+ width: root.font.pointSize * 3.2
+ height: root.font.pointSize * 1.6
+ anchors.verticalCenter: parent.verticalCenter
+
+ onPaint: {
+ var ctx = getContext("2d")
+ ctx.clearRect(0, 0, width, height)
+
+ // Qt Canvas nem támogatja ctx.roundRect() – saját helper
+ function rr(c, x, y, w, h, r) {
+ r = Math.min(Math.max(r, 0), Math.min(w, h) / 2)
+ c.beginPath()
+ c.moveTo(x + r, y)
+ c.arcTo(x + w, y, x + w, y + h, r)
+ c.arcTo(x + w, y + h, x, y + h, r)
+ c.arcTo(x, y + h, x, y, r)
+ c.arcTo(x, y, x + w, y, r)
+ c.closePath()
+ }
+
+ var lvl = batteryIndicator.batteryLevel
+ var charging = batteryIndicator.isCharging
+ var full = batteryIndicator.isFull
+ var col = batteryIndicator.levelColor(lvl, charging)
+
+ var bw = width * 0.84 // akksi test szélessége
+ var bh = height * 0.72 // akksi test magassága
+ var bx = 0
+ var by = (height - bh) / 2
+ var r = bh * 0.22 // sarokkerekítés
+ var tw = width * 0.07 // terminál szélessége
+ var th = bh * 0.44 // terminál magassága
+ var tx = bw // terminál x
+ var ty = (height - th) / 2
+
+ // Terminál (+ pólus)
+ rr(ctx, tx, ty, tw, th, 2)
+ ctx.fillStyle = col
+ ctx.globalAlpha = 0.7
+ ctx.fill()
+ ctx.globalAlpha = 1.0
+
+ // Keret (akksi test)
+ rr(ctx, bx, by, bw, bh, r)
+ ctx.strokeStyle = col
+ ctx.lineWidth = 1.5
+ ctx.stroke()
+
+ // Töltési szint kitöltés
+ var padding = 3
+ var fillW = Math.max(0, (bw - padding * 2) * lvl / 100)
+ if (fillW > 0) {
+ rr(ctx, bx + padding, by + padding,
+ fillW, bh - padding * 2,
+ Math.max(0, r - padding * 0.5))
+ ctx.fillStyle = col
+ ctx.globalAlpha = 0.85
+ ctx.fill()
+ ctx.globalAlpha = 1.0
+ }
+
+ // Villám jel (töltés közben)
+ if (charging && !full) {
+ var cx = bw / 2
+ var cy = height / 2
+ var s = bh * 0.52
+ ctx.beginPath()
+ ctx.moveTo(cx + s * 0.18, cy - s * 0.5)
+ ctx.lineTo(cx - s * 0.08, cy + s * 0.05)
+ ctx.lineTo(cx + s * 0.10, cy + s * 0.05)
+ ctx.lineTo(cx - s * 0.18, cy + s * 0.5)
+ ctx.lineTo(cx + s * 0.08, cy - s * 0.05)
+ ctx.lineTo(cx - s * 0.10, cy - s * 0.05)
+ ctx.closePath()
+ ctx.fillStyle = "#ffffff"
+ ctx.globalAlpha = 0.95
+ ctx.fill()
+ ctx.globalAlpha = 1.0
+ }
+
+ // Tele jel (checkbox-szerű pipával)
+ if (full) {
+ ctx.beginPath()
+ ctx.moveTo(bw * 0.32, by + bh / 2)
+ ctx.lineTo(bw * 0.46, by + bh * 0.68)
+ ctx.lineTo(bw * 0.68, by + bh * 0.28)
+ ctx.strokeStyle = "#ffffff"
+ ctx.lineWidth = 1.8
+ ctx.lineCap = "round"
+ ctx.lineJoin = "round"
+ ctx.globalAlpha = 0.95
+ ctx.stroke()
+ ctx.globalAlpha = 1.0
+ }
+ }
+ }
+
+ // Százalék szöveg
+ Text {
+ id: batteryText
+ anchors.verticalCenter: parent.verticalCenter
+ text: {
+ if (batteryIndicator.isFull) return "100%"
+ if (batteryIndicator.isCharging) return batteryIndicator.batteryLevel + "% ↑"
+ return batteryIndicator.batteryLevel + "%"
+ }
+ color: batteryIndicator.levelColor(batteryIndicator.batteryLevel, batteryIndicator.isCharging)
+ font.pointSize: root.font.pointSize * 0.82
+ font.family: root.font.family
+ font.bold: batteryIndicator.batteryLevel <= 15 && !batteryIndicator.isCharging
+
+ // Pulzáló animáció kritikus töltésnél
+ SequentialAnimation on opacity {
+ running: batteryIndicator.batteryLevel <= 15 && !batteryIndicator.isCharging
+ loops: Animation.Infinite
+ NumberAnimation { to: 0.3; duration: 700; easing.type: Easing.InOutSine }
+ NumberAnimation { to: 1.0; duration: 700; easing.type: Easing.InOutSine }
+ }
+ }
+
+ // Szint változáskor újrafest
+ onBatteryLevelChanged: batteryCanvas.requestPaint()
+ onIsChargingChanged: batteryCanvas.requestPaint()
+ onIsFullChanged: batteryCanvas.requestPaint()
+}