1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-08 06:25:37 -05:00
Files
DankMaterialShell/Services/BatteryService.qml

218 lines
8.2 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Services.UPower
import Quickshell.Io
pragma Singleton
pragma ComponentBehavior: Bound
Singleton {
id: root
// Debug mode for testing (disabled for now)
property bool debugMode: false
// Battery properties - using shell command method (native UPower API commented out due to issues)
property bool batteryAvailable: systemBatteryPercentage > 0
property int batteryLevel: systemBatteryPercentage
property string batteryStatus: {
return systemBatteryState === "charging" ? "Charging" :
systemBatteryState === "discharging" ? "Discharging" :
systemBatteryState === "fully-charged" ? "Full" :
systemBatteryState === "empty" ? "Empty" : "Unknown"
}
property int timeRemaining: 0 // Not implemented for shell fallback
property bool isCharging: systemBatteryState === "charging"
property bool isLowBattery: systemBatteryPercentage <= 20
/* Native UPower API (commented out - not working correctly, returns 1% instead of actual values)
property bool batteryAvailable: (UPower.displayDevice && UPower.displayDevice.ready && UPower.displayDevice.percentage > 0) || systemBatteryPercentage > 0
property int batteryLevel: {
if (UPower.displayDevice && UPower.displayDevice.ready && UPower.displayDevice.percentage > 0) {
return Math.round(UPower.displayDevice.percentage)
}
return systemBatteryPercentage
}
property string batteryStatus: {
if (UPower.displayDevice && UPower.displayDevice.ready) {
switch(UPower.displayDevice.state) {
case UPowerDeviceState.Charging: return "Charging"
case UPowerDeviceState.Discharging: return "Discharging"
case UPowerDeviceState.FullyCharged: return "Full"
case UPowerDeviceState.Empty: return "Empty"
case UPowerDeviceState.PendingCharge: return "Pending Charge"
case UPowerDeviceState.PendingDischarge: return "Pending Discharge"
case UPowerDeviceState.Unknown:
default: return "Unknown"
}
}
return systemBatteryState === "charging" ? "Charging" :
systemBatteryState === "discharging" ? "Discharging" :
systemBatteryState === "fully-charged" ? "Full" :
systemBatteryState === "empty" ? "Empty" : "Unknown"
}
property int timeRemaining: (UPower.displayDevice && UPower.displayDevice.ready) ? (UPower.displayDevice.timeToEmpty || UPower.displayDevice.timeToFull || 0) : 0
property bool isCharging: {
if (UPower.displayDevice && UPower.displayDevice.ready) {
return UPower.displayDevice.state === UPowerDeviceState.Charging
}
return systemBatteryState === "charging"
}
property bool isLowBattery: {
if (UPower.displayDevice && UPower.displayDevice.ready) {
return UPower.displayDevice.percentage <= 20
}
return systemBatteryPercentage <= 20
}
*/
property int batteryHealth: 100 // Default fallback
property string batteryTechnology: "Li-ion" // Default fallback
property int cycleCount: 0 // Not implemented for shell fallback
property int batteryCapacity: 45000 // Default fallback
property var powerProfiles: availableProfiles
property string activePowerProfile: "balanced" // Default fallback
// System battery info from shell command (primary source)
property int systemBatteryPercentage: 100 // Default value, will be updated by shell command
property string systemBatteryState: "charging" // Default value, will be updated by shell command
// Shell command fallback for battery info
Process {
id: batteryProcess
running: false
command: ["upower", "-i", "/org/freedesktop/UPower/devices/battery_BAT1"]
stdout: StdioCollector {
onStreamFinished: {
if (text.trim()) {
let output = text.trim()
let percentageMatch = output.match(/percentage:\s*(\d+)%/)
let stateMatch = output.match(/state:\s*(\w+)/)
if (percentageMatch) {
root.systemBatteryPercentage = parseInt(percentageMatch[1])
console.log("Battery percentage updated to:", root.systemBatteryPercentage)
}
if (stateMatch) {
root.systemBatteryState = stateMatch[1]
console.log("Battery state updated to:", root.systemBatteryState)
}
}
}
}
onExited: (exitCode) => {
if (exitCode !== 0) {
console.warn("Battery process failed with exit code:", exitCode)
}
}
}
// Timer to periodically check battery status
Timer {
interval: 5000 // Check every 5 seconds
running: true
repeat: true
onTriggered: {
batteryProcess.running = true
}
}
Component.onCompleted: {
// Initial battery check
batteryProcess.running = true
// Get current power profile
getCurrentProfile()
console.log("BatteryService initialized with shell command approach")
}
property var availableProfiles: {
// Try to use power-profiles-daemon via shell command
return ["power-saver", "balanced", "performance"]
}
function setBatteryProfile(profileName) {
console.log("Setting power profile to:", profileName)
powerProfileProcess.command = ["powerprofilesctl", "set", profileName]
powerProfileProcess.running = true
}
// Process to set power profile
Process {
id: powerProfileProcess
running: false
onExited: (exitCode) => {
if (exitCode === 0) {
console.log("Power profile set successfully")
// Update current profile
getCurrentProfile()
} else {
console.warn("Failed to set power profile, exit code:", exitCode)
}
}
}
// Process to get current power profile
Process {
id: getCurrentProfileProcess
running: false
command: ["powerprofilesctl", "get"]
stdout: StdioCollector {
onStreamFinished: {
if (text.trim()) {
root.activePowerProfile = text.trim()
console.log("Current power profile:", root.activePowerProfile)
}
}
}
onExited: (exitCode) => {
if (exitCode !== 0) {
console.warn("Failed to get current power profile, exit code:", exitCode)
}
}
}
function getCurrentProfile() {
getCurrentProfileProcess.running = true
}
function getBatteryIcon() {
if (!root.batteryAvailable) return "power"
let level = root.batteryLevel
let charging = root.isCharging
if (charging) {
if (level >= 90) return "battery_charging_full"
if (level >= 60) return "battery_charging_90"
if (level >= 30) return "battery_charging_60"
if (level >= 20) return "battery_charging_30"
return "battery_charging_20"
} else {
if (level >= 90) return "battery_full"
if (level >= 60) return "battery_6_bar"
if (level >= 50) return "battery_5_bar"
if (level >= 40) return "battery_4_bar"
if (level >= 30) return "battery_3_bar"
if (level >= 20) return "battery_2_bar"
if (level >= 10) return "battery_1_bar"
return "battery_alert"
}
}
function formatTimeRemaining() {
if (root.timeRemaining <= 0) return "Unknown"
let hours = Math.floor(root.timeRemaining / 3600)
let minutes = Math.floor((root.timeRemaining % 3600) / 60)
if (hours > 0) {
return hours + "h " + minutes + "m"
} else {
return minutes + "m"
}
}
}