1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-09 15:05:39 -05:00

Fixed battery status on laptops. Updated power profiles.

This commit is contained in:
purian23
2025-07-15 18:42:56 -04:00
parent 651cb87596
commit eb5950f8c8

View File

@@ -1,120 +1,182 @@
import QtQuick
import Quickshell
import Quickshell.Services.UPower
import Quickshell.Io
pragma Singleton
pragma ComponentBehavior: Bound
Singleton {
id: root
// Debug mode for testing on desktop systems without batteries
property bool debugMode: false // Set to true to enable fake battery for testing
// Debug mode for testing (disabled for now)
property bool debugMode: false
// Debug fake battery data
property int debugBatteryLevel: 65
property string debugBatteryStatus: "Discharging"
property int debugTimeRemaining: 7200 // 2 hours in seconds
property bool debugIsCharging: false
property int debugBatteryHealth: 88
property string debugBatteryTechnology: "Li-ion"
property int debugBatteryCapacity: 45000 // 45 Wh in mWh
// 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
property bool batteryAvailable: debugMode || (battery.ready && battery.isLaptopBattery)
property int batteryLevel: debugMode ? debugBatteryLevel : Math.round(battery.percentage)
property string batteryStatus: debugMode ? debugBatteryStatus : UPowerDeviceState.toString(battery.state)
property int timeRemaining: debugMode ? debugTimeRemaining : (battery.timeToEmpty || battery.timeToFull)
property bool isCharging: debugMode ? debugIsCharging : (battery.state === UPowerDeviceState.Charging)
property bool isLowBattery: debugMode ? (debugBatteryLevel <= 20) : (battery.percentage <= 20)
property int batteryHealth: debugMode ? debugBatteryHealth : (battery.healthSupported ? Math.round(battery.healthPercentage) : 100)
property string batteryTechnology: {
if (debugMode) return debugBatteryTechnology
/* 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"]
// Try to get technology from any available laptop battery
for (let i = 0; i < UPower.devices.length; i++) {
let device = UPower.devices[i]
if (device.isLaptopBattery && device.ready) {
// UPower doesn't expose technology directly, but we can get it from the model
let model = device.model || ""
if (model.toLowerCase().includes("li-ion") || model.toLowerCase().includes("lithium")) {
return "Li-ion"
} else if (model.toLowerCase().includes("li-po") || model.toLowerCase().includes("polymer")) {
return "Li-polymer"
} else if (model.toLowerCase().includes("nimh")) {
return "NiMH"
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)
}
}
}
}
return "Unknown"
}
property int cycleCount: 0 // UPower doesn't expose cycle count
property int batteryCapacity: debugMode ? debugBatteryCapacity : Math.round(battery.energyCapacity * 1000)
property var powerProfiles: availableProfiles
property string activePowerProfile: PowerProfile.toString(PowerProfiles.profile)
property var battery: UPower.displayDevice
property var availableProfiles: {
let profiles = []
if (PowerProfiles.profile !== undefined) {
profiles.push("power-saver")
profiles.push("balanced")
if (PowerProfiles.hasPerformanceProfile) {
profiles.push("performance")
onExited: (exitCode) => {
if (exitCode !== 0) {
console.warn("Battery process failed with exit code:", exitCode)
}
}
return profiles
}
// Timer to simulate battery changes in debug mode
// Timer to periodically check battery status
Timer {
id: debugTimer
interval: 5000 // Update every 5 seconds
running: debugMode
interval: 5000 // Check every 5 seconds
running: true
repeat: true
onTriggered: {
// Simulate battery discharge/charge
if (debugIsCharging) {
debugBatteryLevel = Math.min(100, debugBatteryLevel + 1)
if (debugBatteryLevel >= 100) {
debugBatteryStatus = "Full"
debugIsCharging = false
}
} else {
debugBatteryLevel = Math.max(0, debugBatteryLevel - 1)
if (debugBatteryLevel <= 15) {
debugBatteryStatus = "Charging"
debugIsCharging = true
}
}
// Update time remaining
debugTimeRemaining = debugIsCharging ?
Math.max(0, debugTimeRemaining - 300) : // 5 minutes less to full
Math.max(0, debugTimeRemaining - 300) // 5 minutes less remaining
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) {
let profile = PowerProfile.Balanced
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
if (profileName === "power-saver") {
profile = PowerProfile.PowerSaver
} else if (profileName === "balanced") {
profile = PowerProfile.Balanced
} else if (profileName === "performance") {
if (PowerProfiles.hasPerformanceProfile) {
profile = PowerProfile.Performance
onExited: (exitCode) => {
if (exitCode === 0) {
console.log("Power profile set successfully")
// Update current profile
getCurrentProfile()
} else {
console.warn("Performance profile not available")
return
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)
}
}
} else {
console.warn("Invalid power profile:", profileName)
return
}
console.log("Setting power profile to:", profileName)
PowerProfiles.profile = profile
onExited: (exitCode) => {
if (exitCode !== 0) {
console.warn("Failed to get current power profile, exit code:", exitCode)
}
}
}
function getCurrentProfile() {
getCurrentProfileProcess.running = true
}
function getBatteryIcon() {