forked from Shinonome/dots-hyprland
109 lines
3.9 KiB
QML
109 lines
3.9 KiB
QML
pragma Singleton
|
|
|
|
import qs.services
|
|
import qs.modules.common
|
|
import Quickshell
|
|
import Quickshell.Services.UPower
|
|
import QtQuick
|
|
import Quickshell.Io
|
|
|
|
Singleton {
|
|
id: root
|
|
property bool available: UPower.displayDevice.isLaptopBattery
|
|
property var chargeState: UPower.displayDevice.state
|
|
property bool isCharging: chargeState == UPowerDeviceState.Charging
|
|
property bool isPluggedIn: isCharging || chargeState == UPowerDeviceState.PendingCharge
|
|
property real percentage: UPower.displayDevice?.percentage ?? 1
|
|
readonly property bool allowAutomaticSuspend: Config.options.battery.automaticSuspend
|
|
readonly property bool soundEnabled: Config.options.sounds.battery
|
|
|
|
property bool isLow: available && (percentage <= Config.options.battery.low / 100)
|
|
property bool isCritical: available && (percentage <= Config.options.battery.critical / 100)
|
|
property bool isSuspending: available && (percentage <= Config.options.battery.suspend / 100)
|
|
property bool isFull: available && (percentage >= Config.options.battery.full / 100)
|
|
|
|
property bool isLowAndNotCharging: isLow && !isCharging
|
|
property bool isCriticalAndNotCharging: isCritical && !isCharging
|
|
property bool isSuspendingAndNotCharging: allowAutomaticSuspend && isSuspending && !isCharging
|
|
property bool isFullAndCharging: isFull && isCharging
|
|
|
|
property real energyRate: UPower.displayDevice.changeRate
|
|
property real timeToEmpty: UPower.displayDevice.timeToEmpty
|
|
property real timeToFull: UPower.displayDevice.timeToFull
|
|
|
|
property real health: (function() {
|
|
const devList = UPower.devices.values;
|
|
for (let i = 0; i < devList.length; ++i) {
|
|
const dev = devList[i];
|
|
if (dev.isLaptopBattery && dev.healthSupported) {
|
|
const health = dev.healthPercentage;
|
|
if (health === 0) {
|
|
return 0.01;
|
|
} else if (health < 1) {
|
|
return health * 100;
|
|
} else {
|
|
return health;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
})()
|
|
|
|
|
|
onIsLowAndNotChargingChanged: {
|
|
if (!root.available || !isLowAndNotCharging) return;
|
|
Quickshell.execDetached([
|
|
"notify-send",
|
|
Translation.tr("Low battery"),
|
|
Translation.tr("Consider plugging in your device"),
|
|
"-u", "critical",
|
|
"-a", "Shell",
|
|
"--hint=int:transient:1",
|
|
])
|
|
|
|
if (root.soundEnabled) Audio.playSystemSound("dialog-warning");
|
|
}
|
|
|
|
onIsCriticalAndNotChargingChanged: {
|
|
if (!root.available || !isCriticalAndNotCharging) return;
|
|
Quickshell.execDetached([
|
|
"notify-send",
|
|
Translation.tr("Critically low battery"),
|
|
Translation.tr("Please charge!\nAutomatic suspend triggers at %1%").arg(Config.options.battery.suspend),
|
|
"-u", "critical",
|
|
"-a", "Shell",
|
|
"--hint=int:transient:1",
|
|
]);
|
|
|
|
if (root.soundEnabled) Audio.playSystemSound("suspend-error");
|
|
}
|
|
|
|
onIsSuspendingAndNotChargingChanged: {
|
|
if (root.available && isSuspendingAndNotCharging) {
|
|
Quickshell.execDetached(["bash", "-c", `systemctl suspend || loginctl suspend`]);
|
|
}
|
|
}
|
|
|
|
onIsFullAndChargingChanged: {
|
|
if (!root.available || !isFullAndCharging) return;
|
|
Quickshell.execDetached([
|
|
"notify-send",
|
|
Translation.tr("Battery full"),
|
|
Translation.tr("Please unplug the charger"),
|
|
"-a", "Shell",
|
|
"--hint=int:transient:1",
|
|
]);
|
|
|
|
if (root.soundEnabled) Audio.playSystemSound("complete");
|
|
}
|
|
|
|
onIsPluggedInChanged: {
|
|
if (!root.available || !root.soundEnabled) return;
|
|
if (isPluggedIn) {
|
|
Audio.playSystemSound("power-plug")
|
|
} else {
|
|
Audio.playSystemSound("power-unplug")
|
|
}
|
|
}
|
|
}
|