1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-09 23:15:38 -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 QtQuick
import Quickshell import Quickshell
import Quickshell.Services.UPower import Quickshell.Services.UPower
import Quickshell.Io
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
Singleton { Singleton {
id: root id: root
// Debug mode for testing on desktop systems without batteries // Debug mode for testing (disabled for now)
property bool debugMode: false // Set to true to enable fake battery for testing property bool debugMode: false
// Debug fake battery data // Battery properties - using shell command method (native UPower API commented out due to issues)
property int debugBatteryLevel: 65 property bool batteryAvailable: systemBatteryPercentage > 0
property string debugBatteryStatus: "Discharging" property int batteryLevel: systemBatteryPercentage
property int debugTimeRemaining: 7200 // 2 hours in seconds property string batteryStatus: {
property bool debugIsCharging: false return systemBatteryState === "charging" ? "Charging" :
property int debugBatteryHealth: 88 systemBatteryState === "discharging" ? "Discharging" :
property string debugBatteryTechnology: "Li-ion" systemBatteryState === "fully-charged" ? "Full" :
property int debugBatteryCapacity: 45000 // 45 Wh in mWh 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) /* Native UPower API (commented out - not working correctly, returns 1% instead of actual values)
property int batteryLevel: debugMode ? debugBatteryLevel : Math.round(battery.percentage) property bool batteryAvailable: (UPower.displayDevice && UPower.displayDevice.ready && UPower.displayDevice.percentage > 0) || systemBatteryPercentage > 0
property string batteryStatus: debugMode ? debugBatteryStatus : UPowerDeviceState.toString(battery.state) property int batteryLevel: {
property int timeRemaining: debugMode ? debugTimeRemaining : (battery.timeToEmpty || battery.timeToFull) if (UPower.displayDevice && UPower.displayDevice.ready && UPower.displayDevice.percentage > 0) {
property bool isCharging: debugMode ? debugIsCharging : (battery.state === UPowerDeviceState.Charging) return Math.round(UPower.displayDevice.percentage)
property bool isLowBattery: debugMode ? (debugBatteryLevel <= 20) : (battery.percentage <= 20) }
property int batteryHealth: debugMode ? debugBatteryHealth : (battery.healthSupported ? Math.round(battery.healthPercentage) : 100) return systemBatteryPercentage
property string batteryTechnology: { }
if (debugMode) return debugBatteryTechnology property string batteryStatus: {
if (UPower.displayDevice && UPower.displayDevice.ready) {
// Try to get technology from any available laptop battery switch(UPower.displayDevice.state) {
for (let i = 0; i < UPower.devices.length; i++) { case UPowerDeviceState.Charging: return "Charging"
let device = UPower.devices[i] case UPowerDeviceState.Discharging: return "Discharging"
if (device.isLaptopBattery && device.ready) { case UPowerDeviceState.FullyCharged: return "Full"
// UPower doesn't expose technology directly, but we can get it from the model case UPowerDeviceState.Empty: return "Empty"
let model = device.model || "" case UPowerDeviceState.PendingCharge: return "Pending Charge"
if (model.toLowerCase().includes("li-ion") || model.toLowerCase().includes("lithium")) { case UPowerDeviceState.PendingDischarge: return "Pending Discharge"
return "Li-ion" case UPowerDeviceState.Unknown:
} else if (model.toLowerCase().includes("li-po") || model.toLowerCase().includes("polymer")) { default: return "Unknown"
return "Li-polymer"
} else if (model.toLowerCase().includes("nimh")) {
return "NiMH"
} }
} }
return systemBatteryState === "charging" ? "Charging" :
systemBatteryState === "discharging" ? "Discharging" :
systemBatteryState === "fully-charged" ? "Full" :
systemBatteryState === "empty" ? "Empty" : "Unknown"
} }
return "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
} }
property int cycleCount: 0 // UPower doesn't expose cycle count return systemBatteryState === "charging"
property int batteryCapacity: debugMode ? debugBatteryCapacity : Math.round(battery.energyCapacity * 1000) }
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 var powerProfiles: availableProfiles
property string activePowerProfile: PowerProfile.toString(PowerProfiles.profile) property string activePowerProfile: "balanced" // Default fallback
property var battery: UPower.displayDevice // 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
property var availableProfiles: { // Shell command fallback for battery info
let profiles = [] Process {
if (PowerProfiles.profile !== undefined) { id: batteryProcess
profiles.push("power-saver") running: false
profiles.push("balanced") command: ["upower", "-i", "/org/freedesktop/UPower/devices/battery_BAT1"]
if (PowerProfiles.hasPerformanceProfile) {
profiles.push("performance") 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 profiles
} }
// Timer to simulate battery changes in debug mode onExited: (exitCode) => {
if (exitCode !== 0) {
console.warn("Battery process failed with exit code:", exitCode)
}
}
}
// Timer to periodically check battery status
Timer { Timer {
id: debugTimer interval: 5000 // Check every 5 seconds
interval: 5000 // Update every 5 seconds running: true
running: debugMode
repeat: true repeat: true
onTriggered: { onTriggered: {
// Simulate battery discharge/charge batteryProcess.running = true
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 Component.onCompleted: {
debugTimeRemaining = debugIsCharging ? // Initial battery check
Math.max(0, debugTimeRemaining - 300) : // 5 minutes less to full batteryProcess.running = true
Math.max(0, debugTimeRemaining - 300) // 5 minutes less remaining // 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) { function setBatteryProfile(profileName) {
let profile = PowerProfile.Balanced
if (profileName === "power-saver") {
profile = PowerProfile.PowerSaver
} else if (profileName === "balanced") {
profile = PowerProfile.Balanced
} else if (profileName === "performance") {
if (PowerProfiles.hasPerformanceProfile) {
profile = PowerProfile.Performance
} else {
console.warn("Performance profile not available")
return
}
} else {
console.warn("Invalid power profile:", profileName)
return
}
console.log("Setting power profile to:", profileName) console.log("Setting power profile to:", profileName)
PowerProfiles.profile = profile 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() { function getBatteryIcon() {