import QtQuick import Quickshell import Quickshell.Io import Quickshell.Services.UPower import "BatteryModel.js" as BatteryModel Item { id: root property var shell: null property string omarchyPath: Quickshell.env("OMARCHY_PATH") readonly property int batteryThreshold: 10 property string pendingPowerSource: "" property string activePowerProfile: "" readonly property bool powerSaverOnBattery: UPower.onBattery && activePowerProfile === "power-saver" PersistentProperties { id: persisted reloadableId: "omarchy-battery" property bool notifiedLowBattery: false } function batteryPercentage() { return BatteryModel.batteryPercentage(UPower.displayDevice) } function isDischarging() { return BatteryModel.isDischarging(UPower.displayDevice, UPower.onBattery, UPowerDeviceState.Discharging) } function checkBattery() { var state = BatteryModel.shouldWarnLowBattery(UPower.displayDevice, UPower.onBattery, UPowerDeviceState.Discharging, batteryThreshold, persisted.notifiedLowBattery) persisted.notifiedLowBattery = state.notifiedLowBattery if (state.notify) sendLowBatteryWarning(state.level) } function sendLowBatteryWarning(level) { if (warningProcess.running) return warningProcess.command = [ "omarchy-battery-low", String(level) ] warningProcess.running = true } function applyPowerProfile() { pendingPowerSource = UPower.onBattery ? "battery" : "ac" if (!powerProfileProcess.running) runPendingPowerProfile() } function runPendingPowerProfile() { powerProfileProcess.command = ["omarchy-powerprofiles-set", pendingPowerSource] pendingPowerSource = "" powerProfileProcess.running = true } function refreshPowerProfile() { if (!powerProfileReadProcess.running) powerProfileReadProcess.running = true } Process { id: warningProcess } Process { id: powerProfileProcess onExited: { if (root.pendingPowerSource !== "") root.runPendingPowerProfile() root.refreshPowerProfile() } } Process { id: powerProfileReadProcess command: ["powerprofilesctl", "get"] stdout: StdioCollector { waitForEnd: true onStreamFinished: root.activePowerProfile = String(text || "").trim() } } Timer { // powerprofilesctl has no portable monitor subcommand; keep profile changes // visible to consumers such as the wallpaper service without requiring the // power panel to be open. interval: 2000 running: true repeat: true triggeredOnStart: true onTriggered: root.refreshPowerProfile() } Timer { interval: 30000 running: true repeat: true triggeredOnStart: true onTriggered: root.checkBattery() } Connections { target: UPower function onOnBatteryChanged() { root.checkBattery() root.applyPowerProfile() root.refreshPowerProfile() } } Component.onCompleted: root.refreshPowerProfile() }