mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Battery: further refactor
This commit is contained in:
@@ -52,17 +52,7 @@ Item {
|
||||
readonly property bool testPluggedIn: false
|
||||
|
||||
readonly property string deviceNativePath: widgetSettings.deviceNativePath !== undefined ? widgetSettings.deviceNativePath : widgetMetadata.deviceNativePath
|
||||
readonly property var selectedBattery: BatteryService.findUPowerDevice(deviceNativePath)
|
||||
readonly property var selectedBluetoothDevice: BatteryService.findBluetoothDevice(deviceNativePath)
|
||||
readonly property var selectedDevice: {
|
||||
if (BatteryService.isDevicePresent(selectedBluetoothDevice)) {
|
||||
return selectedBluetoothDevice;
|
||||
}
|
||||
if (BatteryService.isDevicePresent(selectedBattery)) {
|
||||
return selectedBattery;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
readonly property var selectedDevice: BatteryService.isDevicePresent(BatteryService.findDevice(deviceNativePath)) ? BatteryService.findDevice(deviceNativePath) : null
|
||||
|
||||
// Check if selected device is actually present/connected
|
||||
readonly property bool isPresent: testMode ? true : BatteryService.isDevicePresent(selectedDevice)
|
||||
@@ -92,7 +82,7 @@ Item {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: selectedDevice?.type === UPowerDeviceType.Battery ? selectedDevice : null
|
||||
target: selectedDevice
|
||||
|
||||
function onPercentageChanged() {
|
||||
maybeNotify(BatteryService.getPercentage(selectedDevice), isCharging, isPluggedIn, isReady);
|
||||
@@ -105,14 +95,6 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: selectedDevice?.batteryAvailable ? selectedDevice : null
|
||||
|
||||
function onBatteryChanged() {
|
||||
maybeNotify(BatteryService.getPercentage(selectedDevice), isCharging, isPluggedIn, isReady);
|
||||
}
|
||||
}
|
||||
|
||||
NPopupContextMenu {
|
||||
id: contextMenu
|
||||
|
||||
@@ -177,7 +159,7 @@ Item {
|
||||
|
||||
// If we are showing the main laptop battery, append external devices
|
||||
if (isInternal) {
|
||||
var external = BatteryService.externalBatteries;
|
||||
var external = BatteryService.bluetoothBatteries;
|
||||
if (external.length > 0) {
|
||||
if (lines.length > 0)
|
||||
lines.push(""); // Separator
|
||||
|
||||
@@ -14,88 +14,16 @@ import qs.Widgets
|
||||
SmartPanel {
|
||||
id: root
|
||||
|
||||
property ShellScreen screen
|
||||
|
||||
preferredWidth: Math.round(440 * Style.uiScaleRatio)
|
||||
preferredHeight: Math.round(460 * Style.uiScaleRatio)
|
||||
|
||||
onOpened: {
|
||||
BatteryService.refreshHealth();
|
||||
}
|
||||
|
||||
panelContent: Item {
|
||||
id: panelContent
|
||||
|
||||
property real contentPreferredHeight: mainLayout.implicitHeight + Style.marginL * 2
|
||||
|
||||
readonly property string deviceNativePath: resolveWidgetSetting("deviceNativePath", "__default__")
|
||||
readonly property var selectedBattery: BatteryService.findUPowerDevice(deviceNativePath)
|
||||
readonly property var selectedBluetoothDevice: BatteryService.findBluetoothDevice(deviceNativePath)
|
||||
readonly property var selectedDevice: {
|
||||
if (BatteryService.isDevicePresent(selectedBluetoothDevice)) {
|
||||
return selectedBluetoothDevice;
|
||||
}
|
||||
if (BatteryService.isDevicePresent(selectedBattery)) {
|
||||
return selectedBattery;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if selected device is actually present/connected
|
||||
readonly property bool isPresent: BatteryService.isDevicePresent(selectedDevice)
|
||||
readonly property bool isReady: BatteryService.isDeviceReady(selectedDevice)
|
||||
|
||||
readonly property int percent: isReady ? Math.round(BatteryService.getPercentage(selectedDevice)) : -1
|
||||
readonly property bool isCharging: isReady ? BatteryService.isCharging(selectedDevice) : false
|
||||
readonly property bool isPluggedIn: isReady ? BatteryService.isPluggedIn(selectedDevice) : false
|
||||
readonly property bool healthAvailable: (isReady && selectedBattery && selectedBattery.healthSupported) || (selectedBattery && BatteryService.healthAvailable)
|
||||
readonly property int healthPercent: (isReady && selectedBattery && selectedBattery.healthSupported) ? Math.round(selectedBattery.healthPercentage) : BatteryService.healthPercent
|
||||
|
||||
readonly property string deviceName: BatteryService.getDeviceName(selectedDevice)
|
||||
readonly property string panelTitle: deviceName ? `${deviceName}` : I18n.tr("common.battery")
|
||||
|
||||
readonly property var allDevices: {
|
||||
var list = [];
|
||||
var seenPaths = new Set();
|
||||
|
||||
// Add UPower batteries
|
||||
if (UPower.devices) {
|
||||
var upowerArray = UPower.devices.values || [];
|
||||
for (var i = 0; i < upowerArray.length; i++) {
|
||||
var d = upowerArray[i];
|
||||
if (BatteryService.isDevicePresent(d) && d.type === UPowerDeviceType.Battery) {
|
||||
if (d.nativePath && !seenPaths.has(d.nativePath)) {
|
||||
list.push(d);
|
||||
seenPaths.add(d.nativePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add Bluetooth batteries
|
||||
if (BluetoothService.devices) {
|
||||
var btArray = BluetoothService.devices.values || [];
|
||||
for (var j = 0; j < btArray.length; j++) {
|
||||
var btd = btArray[j];
|
||||
if (BatteryService.isDevicePresent(btd) && btd.batteryAvailable) {
|
||||
// Bluetooth devices use address as unique ID
|
||||
if (btd.address && !seenPaths.has(btd.address)) {
|
||||
list.push(btd);
|
||||
seenPaths.add(btd.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: if no specific batteries found but display device is a battery, use it
|
||||
if (list.length === 0 && UPower.displayDevice && UPower.displayDevice.type === UPowerDeviceType.Battery && BatteryService.isDevicePresent(UPower.displayDevice)) {
|
||||
list.push(UPower.displayDevice);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
readonly property var laptopBatteries: allDevices.filter(d => !BatteryService.isBluetoothDevice(d))
|
||||
readonly property var otherDevices: allDevices.filter(d => BatteryService.isBluetoothDevice(d))
|
||||
|
||||
readonly property string iconName: BatteryService.getIcon(percent, isCharging, isPluggedIn, isReady)
|
||||
|
||||
property var batteryWidgetInstance: BarService.lookupWidget("Battery", screen ? screen.name : null)
|
||||
readonly property var batteryWidgetSettings: batteryWidgetInstance ? batteryWidgetInstance.widgetSettings : null
|
||||
readonly property var batteryWidgetMetadata: BarWidgetRegistry.widgetMetadata["Battery"]
|
||||
@@ -106,6 +34,8 @@ SmartPanel {
|
||||
readonly property bool showPowerProfiles: resolveWidgetSetting("showPowerProfiles", false)
|
||||
readonly property bool showNoctaliaPerformance: resolveWidgetSetting("showNoctaliaPerformance", false)
|
||||
|
||||
readonly property var primaryDevice: BatteryService.primaryDevice
|
||||
|
||||
function profileToIndex(p) {
|
||||
return powerProfiles.indexOf(p) ?? 1;
|
||||
}
|
||||
@@ -161,8 +91,8 @@ SmartPanel {
|
||||
|
||||
NIcon {
|
||||
pointSize: Style.fontSizeXXL
|
||||
color: (isCharging || isPluggedIn) ? Color.mPrimary : Color.mOnSurface
|
||||
icon: iconName
|
||||
color: (BatteryService.isCharging(primaryDevice) || BatteryService.isPluggedIn(primaryDevice)) ? Color.mPrimary : Color.mOnSurface
|
||||
icon: BatteryService.getIcon(BatteryService.getPercentage(primaryDevice), BatteryService.isCharging(primaryDevice), BatteryService.isPluggedIn(primaryDevice), BatteryService.isDeviceReady(primaryDevice))
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
@@ -170,21 +100,13 @@ SmartPanel {
|
||||
Layout.fillWidth: true
|
||||
|
||||
NText {
|
||||
text: panelTitle
|
||||
text: I18n.tr("common.battery")
|
||||
pointSize: Style.fontSizeL
|
||||
font.weight: Style.fontWeightBold
|
||||
color: Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
NText {
|
||||
text: BatteryService.getTimeRemainingText(selectedDevice)
|
||||
pointSize: Style.fontSizeS
|
||||
color: Color.mOnSurfaceVariant
|
||||
wrapMode: Text.Wrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
NIconButton {
|
||||
@@ -200,7 +122,7 @@ SmartPanel {
|
||||
NBox {
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: chargeLayout.implicitHeight + Style.marginL * 2
|
||||
visible: allDevices.length > 0
|
||||
visible: BatteryService.laptopBatteries.length > 0 || BatteryService.bluetoothBatteries.length > 0
|
||||
|
||||
ColumnLayout {
|
||||
id: chargeLayout
|
||||
@@ -210,7 +132,7 @@ SmartPanel {
|
||||
|
||||
// Laptop batteries section
|
||||
Repeater {
|
||||
model: laptopBatteries
|
||||
model: BatteryService.laptopBatteries
|
||||
delegate: ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
@@ -225,8 +147,8 @@ SmartPanel {
|
||||
|
||||
RowLayout {
|
||||
NIcon {
|
||||
color: (isCharging || isPluggedIn) ? Color.mPrimary : Color.mOnSurface
|
||||
icon: iconName
|
||||
color: (BatteryService.isCharging(modelData) || BatteryService.isPluggedIn(modelData)) ? Color.mPrimary : Color.mOnSurface
|
||||
icon: BatteryService.getIcon(BatteryService.getPercentage(modelData), BatteryService.isCharging(modelData), BatteryService.isPluggedIn(modelData), BatteryService.isDeviceReady(modelData))
|
||||
}
|
||||
|
||||
NText {
|
||||
@@ -234,6 +156,13 @@ SmartPanel {
|
||||
text: dName ? dName : I18n.tr("common.battery")
|
||||
color: Color.mOnSurface
|
||||
pointSize: Style.fontSizeS
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NText {
|
||||
text: BatteryService.getTimeRemainingText(modelData)
|
||||
pointSize: Style.fontSizeS
|
||||
color: Color.mOnSurfaceVariant
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +187,7 @@ SmartPanel {
|
||||
color: Color.mPrimary
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
Layout.preferredWidth: 40 * Style.uiScaleRatio
|
||||
horizontalAlignment: Text.AlignRight
|
||||
@@ -274,7 +204,7 @@ SmartPanel {
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
visible: modelData.healthSupported || (modelData === selectedBattery && BatteryService.healthAvailable)
|
||||
visible: modelData.healthSupported
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
@@ -305,14 +235,14 @@ SmartPanel {
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
width: {
|
||||
var h = modelData.healthSupported ? modelData.healthPercentage : (modelData === selectedBattery ? BatteryService.healthPercent : 0);
|
||||
var h = modelData.healthPercentage;
|
||||
if (h <= 0)
|
||||
return 0;
|
||||
var ratio = Math.max(0, Math.min(1, h / 100));
|
||||
return parent.width * ratio;
|
||||
}
|
||||
color: {
|
||||
var h = modelData.healthSupported ? modelData.healthPercentage : (modelData === selectedBattery ? BatteryService.healthPercent : 0);
|
||||
var h = modelData.healthPercentage;
|
||||
return h >= 80 ? Color.mPrimary : (h >= 50 ? Color.mTertiary : Color.mError);
|
||||
}
|
||||
}
|
||||
@@ -321,7 +251,7 @@ SmartPanel {
|
||||
Layout.preferredWidth: 40 * Style.uiScaleRatio
|
||||
horizontalAlignment: Text.AlignRight
|
||||
|
||||
readonly property int h: modelData.healthSupported ? Math.round(modelData.healthPercentage) : (modelData === selectedBattery ? BatteryService.healthPercent : -1)
|
||||
readonly property int h: Math.round(modelData.healthPercentage)
|
||||
text: h >= 0 ? `${h}%` : "--"
|
||||
color: Color.mOnSurface
|
||||
pointSize: Style.fontSizeS
|
||||
@@ -334,12 +264,12 @@ SmartPanel {
|
||||
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
visible: laptopBatteries.length > 0 && otherDevices.length > 0
|
||||
visible: BatteryService.laptopBatteries.length > 0 && BatteryService.bluetoothBatteries.length > 0
|
||||
}
|
||||
|
||||
// Other devices (Bluetooth) section
|
||||
Repeater {
|
||||
model: otherDevices
|
||||
model: BatteryService.bluetoothBatteries
|
||||
delegate: ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
spacing: Style.marginS
|
||||
@@ -380,6 +310,7 @@ SmartPanel {
|
||||
color: Color.mPrimary
|
||||
}
|
||||
}
|
||||
|
||||
NText {
|
||||
Layout.preferredWidth: 40 * Style.uiScaleRatio
|
||||
horizontalAlignment: Text.AlignRight
|
||||
@@ -418,6 +349,7 @@ SmartPanel {
|
||||
color: Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NText {
|
||||
text: PowerProfileService.getName(profileIndex)
|
||||
color: Color.mOnSurfaceVariant
|
||||
@@ -452,12 +384,14 @@ SmartPanel {
|
||||
pointSize: Style.fontSizeS
|
||||
color: PowerProfileService.getIcon() === "powersaver" ? Color.mPrimary : Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "balanced"
|
||||
pointSize: Style.fontSizeS
|
||||
color: PowerProfileService.getIcon() === "balanced" ? Color.mPrimary : Color.mOnSurfaceVariant
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: "performance"
|
||||
pointSize: Style.fontSizeS
|
||||
@@ -483,11 +417,13 @@ SmartPanel {
|
||||
color: Color.mOnSurface
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
NIcon {
|
||||
icon: PowerProfileService.noctaliaPerformanceMode ? "rocket" : "rocket-off"
|
||||
pointSize: Style.fontSizeL
|
||||
color: PowerProfileService.noctaliaPerformanceMode ? Color.mPrimary : Color.mOnSurfaceVariant
|
||||
}
|
||||
|
||||
NToggle {
|
||||
checked: PowerProfileService.noctaliaPerformanceMode
|
||||
onToggled: checked => PowerProfileService.noctaliaPerformanceMode = checked
|
||||
|
||||
@@ -11,7 +11,6 @@ import qs.Services.UI
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
// MARK: BatteryService
|
||||
// Primary battery device (prioritizes laptop over Bluetooth)
|
||||
readonly property var primaryDevice: _laptopBattery || _bluetoothBattery || null
|
||||
// Whether the primary device is a laptop battery
|
||||
@@ -22,58 +21,22 @@ Singleton {
|
||||
readonly property bool batteryReady: isDeviceReady(primaryDevice)
|
||||
readonly property bool batteryPresent: isDevicePresent(primaryDevice)
|
||||
|
||||
property bool healthAvailable: false
|
||||
property int healthPercent: -1
|
||||
|
||||
readonly property var _laptopBattery: {
|
||||
if (!UPower.devices) {
|
||||
return UPower.displayDevice;
|
||||
}
|
||||
|
||||
var devices = UPower.devices.values || [];
|
||||
|
||||
// 1. Explicitly look for BAT0 first
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
var d = devices[i];
|
||||
if (d && (d.nativePath === "BAT0" || d.objectPath === "/org/freedesktop/UPower/devices/battery_BAT0")) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fallback to displayDevice if it's a laptop battery
|
||||
if (UPower.displayDevice && UPower.displayDevice.isLaptopBattery) {
|
||||
return UPower.displayDevice;
|
||||
}
|
||||
|
||||
// 3. Any other device marked as a laptop battery
|
||||
for (var j = 0; j < devices.length; j++) {
|
||||
var device = devices[j];
|
||||
if (device && device.type === UPowerDeviceType.Battery && device.isLaptopBattery) {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
if (UPower.displayDevice.isPresent) {
|
||||
return UPower.displayDevice;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
readonly property var externalBatteries: {
|
||||
readonly property var laptopBatteries: UPower.devices.values.filter(d => d.isLaptopBattery)
|
||||
readonly property var bluetoothBatteries: {
|
||||
var list = [];
|
||||
var devices = BluetoothService.devices ? (BluetoothService.devices.values || []) : [];
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
var device = devices[i];
|
||||
if (device && device.connected && device.batteryAvailable) {
|
||||
list.push(device);
|
||||
var btArray = BluetoothService.devices?.values || [];
|
||||
for (var i = 0; i < btArray.length; i++) {
|
||||
var btd = btArray[i];
|
||||
if (btd && btd.connected && btd.batteryAvailable) {
|
||||
list.push(btd);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
return list
|
||||
}
|
||||
|
||||
readonly property var _bluetoothBattery: externalBatteries.length > 0 ? externalBatteries[0] : null
|
||||
readonly property var _laptopBattery: UPower.displayDevice.isPresent ? UPower.displayDevice : null
|
||||
readonly property var _bluetoothBattery: bluetoothBatteries.length > 0 ? bluetoothBatteries[0] : null
|
||||
|
||||
// MARK: BatterySettings
|
||||
property var deviceModel: {
|
||||
var model = [
|
||||
{
|
||||
@@ -81,7 +44,6 @@ Singleton {
|
||||
"name": I18n.tr("bar.battery.device-default")
|
||||
}
|
||||
];
|
||||
// UPower Devices
|
||||
const devices = UPower.devices?.values || [];
|
||||
for (let d of devices) {
|
||||
if (!d || d.type === UPowerDeviceType.LinePower) {
|
||||
@@ -95,53 +57,28 @@ Singleton {
|
||||
return model;
|
||||
}
|
||||
|
||||
// MARK: findUPowerDevice
|
||||
function findUPowerDevice(nativePath) {
|
||||
if (!nativePath || nativePath === "__default__" || nativePath === "DisplayDevice") {
|
||||
return _laptopBattery;
|
||||
}
|
||||
function findDevice(nativePath) {
|
||||
if (!nativePath || nativePath === "__default__" || nativePath === "DisplayDevice") {
|
||||
return _laptopBattery;
|
||||
}
|
||||
|
||||
if (!UPower.devices) {
|
||||
return null;
|
||||
}
|
||||
if (!UPower.devices) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var deviceArray = UPower.devices.values || [];
|
||||
for (var i = 0; i < deviceArray.length; i++) {
|
||||
var device = deviceArray[i];
|
||||
if (device && device.nativePath === nativePath) {
|
||||
if (device.type === UPowerDeviceType.LinePower) {
|
||||
continue;
|
||||
}
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
var deviceArray = UPower.devices.values || [];
|
||||
for (var i = 0; i < deviceArray.length; i++) {
|
||||
var device = deviceArray[i];
|
||||
if (device && device.nativePath === nativePath) {
|
||||
if (device.type === UPowerDeviceType.LinePower) {
|
||||
continue;
|
||||
}
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// MARK: findBluetoothDevice
|
||||
function findBluetoothDevice(nativePath) {
|
||||
if (!nativePath || !BluetoothService.devices) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var macMatch = nativePath.match(/([0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2})/);
|
||||
if (!macMatch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var macAddress = macMatch[1].toUpperCase();
|
||||
var deviceArray = BluetoothService.devices.values || [];
|
||||
|
||||
for (var i = 0; i < deviceArray.length; i++) {
|
||||
var device = deviceArray[i];
|
||||
if (device && device.address && device.address.toUpperCase() === macAddress) {
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// MARK: isDevicePresent
|
||||
function isDevicePresent(device) {
|
||||
if (!device) {
|
||||
return false;
|
||||
@@ -163,7 +100,6 @@ Singleton {
|
||||
return false;
|
||||
}
|
||||
|
||||
// MARK: isDeviceReady
|
||||
function isDeviceReady(device) {
|
||||
if (!isDevicePresent(device)) {
|
||||
return false;
|
||||
@@ -174,7 +110,6 @@ Singleton {
|
||||
return device.ready && device.percentage !== undefined;
|
||||
}
|
||||
|
||||
// MARK: getPercentage
|
||||
function getPercentage(device) {
|
||||
if (!device) {
|
||||
return -1;
|
||||
@@ -185,7 +120,6 @@ Singleton {
|
||||
return (device.percentage || 0) * 100;
|
||||
}
|
||||
|
||||
// MARK: isCharging
|
||||
function isCharging(device) {
|
||||
if (!device || isBluetoothDevice(device)) {
|
||||
// Tracking bluetooth devices can charge or not is a loop hole, none of my devices has it, even if it possible?!
|
||||
@@ -197,7 +131,6 @@ Singleton {
|
||||
return false;
|
||||
}
|
||||
|
||||
// MARK: isPluggedIn
|
||||
function isPluggedIn(device) {
|
||||
if (!device || isBluetoothDevice(device)) {
|
||||
// Tracking bluetooth devices can charge or not is a loop hole, none of my devices has it, even if it possible?!
|
||||
@@ -209,12 +142,10 @@ Singleton {
|
||||
return false;
|
||||
}
|
||||
|
||||
// MARK: isBluetoothDevice
|
||||
function isBluetoothDevice(device) {
|
||||
return device && device.batteryAvailable !== undefined;
|
||||
}
|
||||
|
||||
// MARK: getDeviceName
|
||||
function getDeviceName(device) {
|
||||
if (!isDeviceReady(device)) {
|
||||
return "";
|
||||
@@ -236,46 +167,6 @@ Singleton {
|
||||
return "";
|
||||
}
|
||||
|
||||
// MARK: refreshHealth
|
||||
function refreshHealth() {
|
||||
if (!isLaptopBattery) {
|
||||
healthAvailable = false;
|
||||
healthPercent = -1;
|
||||
return;
|
||||
}
|
||||
healthProcess.running = true;
|
||||
}
|
||||
|
||||
Process {
|
||||
id: healthProcess
|
||||
command: ["sh", "-c", `upower -i ${primaryDevice && primaryDevice.nativePath ? "/org/freedesktop/UPower/devices/battery_" + primaryDevice.nativePath : "$(upower -e | grep battery | head -n 1)"} 2>/dev/null | grep -iE 'capacity'`]
|
||||
environment: ({
|
||||
"LC_ALL": "C"
|
||||
})
|
||||
|
||||
stdout: SplitParser {
|
||||
onRead: function (data) {
|
||||
var line = data.trim();
|
||||
if (line === "") {
|
||||
return;
|
||||
}
|
||||
var capacityMatch = line.match(/^\s*capacity:\s*(\d+(?:\.\d+)?)\s*%/i);
|
||||
if (capacityMatch) {
|
||||
root.healthPercent = Math.round(parseFloat(capacityMatch[1]));
|
||||
root.healthAvailable = true;
|
||||
Logger.d("Battery", "Health retrieved from CLI:", root.healthPercent + "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (isLaptopBattery) {
|
||||
Qt.callLater(refreshHealth);
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: getIcon
|
||||
function getIcon(percent, charging, pluggedIn, isReady) {
|
||||
if (!isReady) {
|
||||
return "battery-exclamation";
|
||||
@@ -304,13 +195,10 @@ Singleton {
|
||||
return "battery-off"; // New fallback icon clearly represent if nothing is true here.
|
||||
}
|
||||
|
||||
// MARK: hasAnyBattery
|
||||
function hasAnyBattery() {
|
||||
return primaryDevice !== null;
|
||||
}
|
||||
|
||||
// MARK: Battery
|
||||
// MARK: getRateText
|
||||
function getRateText(device) {
|
||||
if (!device || device.changeRate === undefined) {
|
||||
return "";
|
||||
@@ -330,7 +218,6 @@ Singleton {
|
||||
return I18n.tr("common.idle");
|
||||
}
|
||||
|
||||
// MARK: getTimeRemainingText
|
||||
function getTimeRemainingText(device) {
|
||||
if (!isDeviceReady(device)) {
|
||||
return I18n.tr("battery.no-battery-detected");
|
||||
|
||||
Reference in New Issue
Block a user