mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-29 14:37:47 -04:00
feat(battery): scale battery level display (#4012)
port 2.0
(cherry picked from commit d254f40acd)
This commit is contained in:
1 parent
2b5bf15e76
commit
74b4175876
13 files changed
+167
-48
No files matched your search
@@ -736,6 +736,8 @@ Singleton {
|
||||
property string batteryProfileName: Spec.SPEC.batteryProfileName.def
|
||||
property int batteryPostLockMonitorTimeout: Spec.SPEC.batteryPostLockMonitorTimeout.def
|
||||
property int batteryChargeLimit: Spec.SPEC.batteryChargeLimit.def
|
||||
property bool batteryScaleToChargeLimit: Spec.SPEC.batteryScaleToChargeLimit.def
|
||||
property bool batteryScaleAlertThresholds: Spec.SPEC.batteryScaleAlertThresholds.def
|
||||
property bool batteryNotifyChargeLimit: Spec.SPEC.batteryNotifyChargeLimit.def
|
||||
property int batteryCriticalThreshold: Spec.SPEC.batteryCriticalThreshold.def
|
||||
property bool batteryCriticalAnimation: Spec.SPEC.batteryCriticalAnimation.def
|
||||
|
||||
@@ -1081,6 +1081,12 @@ var LOCAL_SPEC = {
|
||||
batteryChargeLimit: {
|
||||
def: 100
|
||||
},
|
||||
batteryScaleToChargeLimit: {
|
||||
def: false
|
||||
},
|
||||
batteryScaleAlertThresholds: {
|
||||
def: false
|
||||
},
|
||||
batteryNotifyChargeLimit: {
|
||||
def: false
|
||||
},
|
||||
|
||||
@@ -28,12 +28,12 @@ CcTile {
|
||||
if (!available)
|
||||
return I18n.tr("Not available");
|
||||
if (BatteryService.isCharging)
|
||||
return `${BatteryService.batteryLevel}% • ` + I18n.tr("Charging");
|
||||
return `${BatteryService.displayBatteryLevelText}% • ` + I18n.tr("Charging");
|
||||
if (BatteryService.isPluggedIn)
|
||||
return `${BatteryService.batteryLevel}% • ` + I18n.tr("Plugged in");
|
||||
return `${BatteryService.batteryLevel}%`;
|
||||
return `${BatteryService.displayBatteryLevelText}% • ` + I18n.tr("Plugged in");
|
||||
return `${BatteryService.displayBatteryLevelText}%`;
|
||||
}
|
||||
denseTitle: available && !showsMeter ? I18n.tr("Battery") + ` • ${BatteryService.batteryLevel}%` : ""
|
||||
denseTitle: available && !showsMeter ? I18n.tr("Battery") + ` • ${BatteryService.displayBatteryLevelText}%` : ""
|
||||
|
||||
function syncBatteryRef(wanted) {
|
||||
if (wanted === batteryRefHeld)
|
||||
|
||||
@@ -204,7 +204,7 @@ Item {
|
||||
width: Theme.iconButtonSize + Theme.spacingM
|
||||
height: width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
value: BatteryService.hasBatteryReading ? BatteryService.batteryLevel / 100 : -1
|
||||
value: BatteryService.hasBatteryReading ? BatteryService.displayBatteryLevel / 100 : -1
|
||||
trackGap: Theme.spacingXXS
|
||||
ringColor: root.levelLow ? Theme.error : Theme.primary
|
||||
animated: root.active
|
||||
@@ -224,7 +224,7 @@ Item {
|
||||
|
||||
StyledText {
|
||||
width: parent.width
|
||||
text: root.formatPercent(BatteryService.batteryLevel)
|
||||
text: root.formatPercent(BatteryService.displayBatteryLevelText)
|
||||
visible: BatteryService.hasBatteryReading
|
||||
font.pixelSize: Theme.fontSizeXXLarge
|
||||
color: root.levelColor
|
||||
|
||||
@@ -96,7 +96,7 @@ BasePill {
|
||||
readonly property string horizontalDisplayText: {
|
||||
const parts = [];
|
||||
if (showPercent) {
|
||||
parts.push(`${BatteryService.batteryLevel}%`);
|
||||
parts.push(`${BatteryService.displayBatteryLevelText}%`);
|
||||
}
|
||||
if (showTime && batteryTimeText) {
|
||||
parts.push(showPercent ? `(${batteryTimeText})` : batteryTimeText);
|
||||
@@ -114,7 +114,7 @@ BasePill {
|
||||
}
|
||||
const parts = [];
|
||||
if (showPercent && batteryStyle === "duo") {
|
||||
parts.push(`${BatteryService.batteryLevel}%`);
|
||||
parts.push(`${BatteryService.displayBatteryLevelText}%`);
|
||||
}
|
||||
if (showTime && batteryTimeText) {
|
||||
parts.push(batteryTimeText);
|
||||
@@ -128,7 +128,7 @@ BasePill {
|
||||
readonly property string verticalDisplayText: {
|
||||
const lines = [];
|
||||
if (showPercent) {
|
||||
lines.push(BatteryService.batteryLevel.toString());
|
||||
lines.push(BatteryService.displayBatteryLevelText);
|
||||
}
|
||||
if (showTime && batteryTimeText) {
|
||||
lines.push(verticalBatteryTimeText);
|
||||
|
||||
@@ -502,7 +502,7 @@ BasePill {
|
||||
case "bluetooth":
|
||||
return BluetoothService.connected ? "bluetooth_connected" : "bluetooth";
|
||||
case "battery":
|
||||
return Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable);
|
||||
return Theme.getBatteryIcon(BatteryService.displayBatteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable);
|
||||
case "printer":
|
||||
return "print";
|
||||
case "idleInhibitor":
|
||||
@@ -687,7 +687,7 @@ BasePill {
|
||||
case "bluetooth":
|
||||
return BluetoothService.connected ? "bluetooth_connected" : "bluetooth";
|
||||
case "battery":
|
||||
return Theme.getBatteryIcon(BatteryService.batteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable);
|
||||
return Theme.getBatteryIcon(BatteryService.displayBatteryLevel, BatteryService.isCharging, BatteryService.batteryAvailable);
|
||||
case "printer":
|
||||
return "print";
|
||||
case "idleInhibitor":
|
||||
|
||||
@@ -13,7 +13,7 @@ Card {
|
||||
|
||||
readonly property bool wide: width >= DashMetrics.gridRowUnit * 2
|
||||
readonly property bool tall: height >= DashMetrics.gridRowUnit * 2
|
||||
readonly property string levelText: Math.round(BatteryService.batteryLevel) + "%"
|
||||
readonly property string levelText: Math.round(BatteryService.displayBatteryLevel) + "%"
|
||||
readonly property string meterStyle: options.style ?? "solid"
|
||||
readonly property bool levelColors: options.color !== "theme"
|
||||
readonly property string healthText: options.health === true && BatteryService.batteryHealth.endsWith("%") ? I18n.tr("Health %1", "battery health, %1 is a percentage").arg(BatteryService.batteryHealth) : ""
|
||||
|
||||
@@ -112,7 +112,7 @@ QtObject {
|
||||
}
|
||||
|
||||
function chargingValue() {
|
||||
const level = Math.round(BatteryService.batteryLevel) + "%";
|
||||
const level = Math.round(BatteryService.displayBatteryLevel) + "%";
|
||||
const seconds = BatteryService.estimatedSeconds();
|
||||
if (!seconds)
|
||||
return level;
|
||||
|
||||
@@ -376,7 +376,7 @@ Row {
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: BatteryService.batteryLevel + "%"
|
||||
text: BatteryService.displayBatteryLevelText + "%"
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Theme.fontWeight
|
||||
color: root.contentColor
|
||||
|
||||
@@ -106,7 +106,7 @@ done
|
||||
width: parent.width
|
||||
|
||||
StyledText {
|
||||
text: BatteryService.batteryAvailable ? `${BatteryService.batteryLevel}%` : ""
|
||||
text: BatteryService.batteryAvailable ? `${BatteryService.displayBatteryLevelText}%` : ""
|
||||
font.pixelSize: Theme.fontSizeXLarge
|
||||
font.weight: Theme.fontWeightMedium
|
||||
color: root.batteryStatusColor
|
||||
@@ -145,7 +145,7 @@ done
|
||||
|
||||
Rectangle {
|
||||
anchors.left: parent.left
|
||||
width: parent.width * Math.max(0, Math.min(1, BatteryService.batteryLevel / 100))
|
||||
width: parent.width * Math.max(0, Math.min(1, BatteryService.displayBatteryLevel / 100))
|
||||
height: parent.height
|
||||
radius: Theme.fullRadius(width, height)
|
||||
color: root.batteryStatusColor
|
||||
@@ -252,6 +252,23 @@ done
|
||||
onSliderValueChanged: newValue => SettingsData.set("batteryChargeLimit", newValue)
|
||||
}
|
||||
|
||||
SettingsToggleRow {
|
||||
settingKey: "batteryScaleToChargeLimit"
|
||||
text: I18n.tr("Scale battery level to charge limit", "battery settings: toggle to scale the displayed percentage so the charge limit represents 100%")
|
||||
description: I18n.tr("Scale the displayed battery level to the configured charge limit", "battery settings: explains that the displayed battery percentage is scaled relative to the charge limit")
|
||||
checked: SettingsData.batteryScaleToChargeLimit
|
||||
onToggled: checked => SettingsData.set("batteryScaleToChargeLimit", checked)
|
||||
}
|
||||
|
||||
SettingsToggleRow {
|
||||
settingKey: "batteryScaleAlertThresholds"
|
||||
text: I18n.tr("Scale low and critical alert thresholds", "battery settings: toggle to apply low and critical alert thresholds to the charge-limit-scaled battery percentage")
|
||||
description: I18n.tr("Use the scaled battery level for alert thresholds and percentages", "battery settings: explains that low and critical alerts trigger and report percentages on the scaled battery level")
|
||||
checked: SettingsData.batteryScaleAlertThresholds
|
||||
visible: SettingsData.batteryScaleToChargeLimit
|
||||
onToggled: checked => SettingsData.set("batteryScaleAlertThresholds", checked)
|
||||
}
|
||||
|
||||
SettingsRow {
|
||||
visible: Qt.platform.os === "linux" && BatteryService.batteryAvailable && !root.chargeLimitSupported
|
||||
body: StyledText {
|
||||
|
||||
@@ -353,6 +353,9 @@ Singleton {
|
||||
const live = _liveChargePercent();
|
||||
return live > 0 ? live : _lastBatteryLevel;
|
||||
}
|
||||
readonly property real displayBatteryLevel: displayLevelForChargeLimit(batteryLevel, SettingsData.batteryChargeLimit, SettingsData.batteryScaleToChargeLimit)
|
||||
readonly property string displayBatteryLevelText: SettingsData.batteryScaleToChargeLimit ? Math.round(displayBatteryLevel).toString() : displayBatteryLevel.toString()
|
||||
readonly property real batteryAlertLevel: batteryAlertLevelForDisplay(batteryLevel, displayBatteryLevel, SettingsData.batteryScaleToChargeLimit, SettingsData.batteryScaleAlertThresholds)
|
||||
|
||||
readonly property bool isCharging: (isBSD && freebsdBatteryAvailable) ? freebsdIsCharging : (_hasKnownChargingState ? _currentIsCharging : _lastIsCharging)
|
||||
|
||||
@@ -360,12 +363,28 @@ Singleton {
|
||||
readonly property bool isPluggedIn: (isBSD && freebsdBatteryAvailable) ? freebsdPluggedIn : !UPower.onBattery
|
||||
|
||||
readonly property bool hasBatteryReading: batteryAvailable && batteryLevel > 0
|
||||
readonly property bool isLowBattery: hasBatteryReading && batteryLevel <= SettingsData.batteryLowThreshold
|
||||
readonly property bool isCriticalBattery: hasBatteryReading && batteryLevel <= SettingsData.batteryCriticalThreshold
|
||||
readonly property bool isLowBattery: hasBatteryReading && isBatteryLevelAtOrBelow(batteryLevel, SettingsData.batteryLowThreshold)
|
||||
readonly property bool isCriticalBattery: hasBatteryReading && isBatteryLevelAtOrBelow(batteryLevel, SettingsData.batteryCriticalThreshold)
|
||||
readonly property bool isLowBatteryAlert: hasBatteryReading && isBatteryLevelAtOrBelow(batteryAlertLevel, SettingsData.batteryLowThreshold)
|
||||
readonly property bool isCriticalBatteryAlert: hasBatteryReading && isBatteryLevelAtOrBelow(batteryAlertLevel, SettingsData.batteryCriticalThreshold)
|
||||
|
||||
readonly property color levelCautionColor: "#FFC107"
|
||||
readonly property color levelCriticalColor: "#F44336"
|
||||
|
||||
function displayLevelForChargeLimit(level, chargeLimit, enabled) {
|
||||
if (!enabled || chargeLimit <= 0 || chargeLimit >= 100)
|
||||
return level;
|
||||
return Math.max(0, Math.min(100, level / chargeLimit * 100));
|
||||
}
|
||||
|
||||
function isBatteryLevelAtOrBelow(level, threshold) {
|
||||
return level > 0 && level <= threshold;
|
||||
}
|
||||
|
||||
function batteryAlertLevelForDisplay(actualLevel, scaledLevel, scaleDisplayEnabled, scaleAlertsEnabled) {
|
||||
return scaleDisplayEnabled && scaleAlertsEnabled ? scaledLevel : actualLevel;
|
||||
}
|
||||
|
||||
readonly property color levelColor: {
|
||||
if (isCharging)
|
||||
return Theme.success;
|
||||
@@ -393,6 +412,23 @@ Singleton {
|
||||
|
||||
on_HasKnownChargingStateChanged: _syncLastIsCharging()
|
||||
on_CurrentIsChargingChanged: _syncLastIsCharging()
|
||||
onBatteryAlertLevelChanged: updateBatteryWarnings()
|
||||
|
||||
Connections {
|
||||
target: SettingsData
|
||||
function onBatteryLowThresholdChanged() {
|
||||
root.updateBatteryWarnings();
|
||||
}
|
||||
function onBatteryCriticalThresholdChanged() {
|
||||
root.updateBatteryWarnings();
|
||||
}
|
||||
function onBatteryScaleToChargeLimitChanged() {
|
||||
root.updateBatteryWarnings();
|
||||
}
|
||||
function onBatteryScaleAlertThresholdsChanged() {
|
||||
root.updateBatteryWarnings();
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
Qt.callLater(root.updateFreeBsdBatteryFallback);
|
||||
@@ -436,7 +472,10 @@ Singleton {
|
||||
} else if (!isCharging || batteryLevel < SettingsData.batteryChargeLimit - 2) {
|
||||
_hasNotifiedChargeLimit = false;
|
||||
}
|
||||
updateBatteryWarnings();
|
||||
}
|
||||
|
||||
function updateBatteryWarnings() {
|
||||
if (isCharging) {
|
||||
_hasNotifiedLowBattery = false;
|
||||
_hasNotifiedCriticalBattery = false;
|
||||
@@ -444,34 +483,35 @@ Singleton {
|
||||
}
|
||||
|
||||
// Critical battery check (higher priority)
|
||||
if (isCriticalBattery) {
|
||||
if (isCriticalBatteryAlert) {
|
||||
if (!_hasNotifiedCriticalBattery && SettingsData.batteryNotifyCritical) {
|
||||
_hasNotifiedCriticalBattery = true;
|
||||
|
||||
sendAlert(I18n.tr("Critical Battery"), I18n.tr("Battery is at %1% - Connect charger immediately!", "critical battery notification body, %1 is the battery percentage").arg(batteryLevel), "critical", "material:battery_alert", SettingsData.batteryCriticalNotificationType);
|
||||
sendAlert(I18n.tr("Critical Battery"), I18n.tr("Battery is at %1% - Connect charger immediately!", "critical battery notification body, %1 is the battery percentage").arg(Math.round(batteryAlertLevel)), "critical", "material:battery_alert", SettingsData.batteryCriticalNotificationType);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (batteryLevel > SettingsData.batteryCriticalThreshold)
|
||||
if (batteryAlertLevel > SettingsData.batteryCriticalThreshold)
|
||||
_hasNotifiedCriticalBattery = false;
|
||||
|
||||
// Low battery check
|
||||
if (isLowBattery) {
|
||||
if (isLowBatteryAlert) {
|
||||
if (!_hasNotifiedLowBattery && SettingsData.batteryNotifyLow) {
|
||||
_hasNotifiedLowBattery = true;
|
||||
|
||||
sendAlert(I18n.tr("Low Battery"), I18n.tr("Battery is at %1% - Consider charging soon", "low battery notification body, %1 is the battery percentage").arg(batteryLevel), "warning", "material:battery_0_bar", SettingsData.batteryLowNotificationType);
|
||||
sendAlert(I18n.tr("Low Battery"), I18n.tr("Battery is at %1% - Consider charging soon", "low battery notification body, %1 is the battery percentage").arg(Math.round(batteryAlertLevel)), "warning", "material:battery_0_bar", SettingsData.batteryLowNotificationType);
|
||||
}
|
||||
|
||||
if (SettingsData.batteryAutoPowerSaver && PowerProfileWatcher.available) {
|
||||
if (PowerProfileWatcher.currentProfile !== PowerProfile.PowerSaver)
|
||||
PowerProfileWatcher.applyProfile(PowerProfile.PowerSaver);
|
||||
}
|
||||
}
|
||||
|
||||
if (batteryLevel > SettingsData.batteryLowThreshold)
|
||||
if (isLowBattery && SettingsData.batteryAutoPowerSaver && PowerProfileWatcher.available) {
|
||||
if (PowerProfileWatcher.currentProfile !== PowerProfile.PowerSaver)
|
||||
PowerProfileWatcher.applyProfile(PowerProfile.PowerSaver);
|
||||
}
|
||||
|
||||
if (batteryAlertLevel > SettingsData.batteryLowThreshold)
|
||||
_hasNotifiedLowBattery = false;
|
||||
}
|
||||
|
||||
@@ -486,6 +526,7 @@ Singleton {
|
||||
_hasNotifiedCriticalBattery = false;
|
||||
} else {
|
||||
_hasNotifiedChargeLimit = false;
|
||||
updateBatteryWarnings();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -827,50 +868,50 @@ Singleton {
|
||||
return "power";
|
||||
|
||||
if (isCharging) {
|
||||
if (batteryLevel >= 90)
|
||||
if (displayBatteryLevel >= 90)
|
||||
return "battery_charging_full";
|
||||
if (batteryLevel >= 80)
|
||||
if (displayBatteryLevel >= 80)
|
||||
return "battery_charging_90";
|
||||
if (batteryLevel >= 60)
|
||||
if (displayBatteryLevel >= 60)
|
||||
return "battery_charging_80";
|
||||
if (batteryLevel >= 50)
|
||||
if (displayBatteryLevel >= 50)
|
||||
return "battery_charging_60";
|
||||
if (batteryLevel >= 30)
|
||||
if (displayBatteryLevel >= 30)
|
||||
return "battery_charging_50";
|
||||
if (batteryLevel >= 20)
|
||||
if (displayBatteryLevel >= 20)
|
||||
return "battery_charging_30";
|
||||
|
||||
return "battery_charging_20";
|
||||
}
|
||||
|
||||
if (isPluggedIn) {
|
||||
if (batteryLevel >= 90)
|
||||
if (displayBatteryLevel >= 90)
|
||||
return "battery_charging_full";
|
||||
if (batteryLevel >= 80)
|
||||
if (displayBatteryLevel >= 80)
|
||||
return "battery_charging_90";
|
||||
if (batteryLevel >= 60)
|
||||
if (displayBatteryLevel >= 60)
|
||||
return "battery_charging_80";
|
||||
if (batteryLevel >= 50)
|
||||
if (displayBatteryLevel >= 50)
|
||||
return "battery_charging_60";
|
||||
if (batteryLevel >= 30)
|
||||
if (displayBatteryLevel >= 30)
|
||||
return "battery_charging_50";
|
||||
if (batteryLevel >= 20)
|
||||
if (displayBatteryLevel >= 20)
|
||||
return "battery_charging_30";
|
||||
|
||||
return "battery_charging_20";
|
||||
}
|
||||
|
||||
if (batteryLevel >= 95)
|
||||
if (displayBatteryLevel >= 95)
|
||||
return "battery_full";
|
||||
if (batteryLevel >= 85)
|
||||
if (displayBatteryLevel >= 85)
|
||||
return "battery_6_bar";
|
||||
if (batteryLevel >= 70)
|
||||
if (displayBatteryLevel >= 70)
|
||||
return "battery_5_bar";
|
||||
if (batteryLevel >= 55)
|
||||
if (displayBatteryLevel >= 55)
|
||||
return "battery_4_bar";
|
||||
if (batteryLevel >= 40)
|
||||
if (displayBatteryLevel >= 40)
|
||||
return "battery_3_bar";
|
||||
if (batteryLevel >= 25)
|
||||
if (displayBatteryLevel >= 25)
|
||||
return "battery_2_bar";
|
||||
|
||||
return "battery_1_bar";
|
||||
|
||||
@@ -29,9 +29,9 @@ Item {
|
||||
readonly property bool circular: root.ring || root.duo
|
||||
readonly property real arcStart: root.duo ? 150 : -90
|
||||
readonly property real arcSpan: root.duo ? 240 : 360
|
||||
readonly property real chargeTarget: Math.max(root.level, Math.min(100, SettingsData.batteryChargeLimit))
|
||||
readonly property real chargeTarget: SettingsData.batteryScaleToChargeLimit ? 100 : Math.max(root.level, Math.min(100, SettingsData.batteryChargeLimit))
|
||||
readonly property real unit: root.thickness / 14
|
||||
readonly property real level: Math.max(0, Math.min(100, BatteryService.batteryLevel))
|
||||
readonly property real level: Math.max(0, Math.min(100, BatteryService.displayBatteryLevel))
|
||||
readonly property bool charging: BatteryService.batteryAvailable && BatteryService.isCharging
|
||||
readonly property bool lowState: BatteryService.batteryAvailable && BatteryService.isLowBattery && !BatteryService.isCharging
|
||||
readonly property color fillColor: {
|
||||
|
||||
@@ -14342,6 +14342,59 @@
|
||||
],
|
||||
"parentLabel": "Power & battery"
|
||||
},
|
||||
{
|
||||
"section": "batteryScaleToChargeLimit",
|
||||
"label": "Scale battery level to charge limit",
|
||||
"tabIndex": 42,
|
||||
"category": "Battery",
|
||||
"keywords": [
|
||||
"battery",
|
||||
"charge",
|
||||
"charging",
|
||||
"configured",
|
||||
"displayed",
|
||||
"hibernate",
|
||||
"level",
|
||||
"limit",
|
||||
"power",
|
||||
"reboot",
|
||||
"restart",
|
||||
"scale",
|
||||
"shutdown",
|
||||
"sleep",
|
||||
"suspend"
|
||||
],
|
||||
"parentLabel": "Power & battery",
|
||||
"description": "Scale the displayed battery level to the configured charge limit"
|
||||
},
|
||||
{
|
||||
"section": "batteryScaleAlertThresholds",
|
||||
"label": "Scale low and critical alert thresholds",
|
||||
"tabIndex": 42,
|
||||
"category": "Battery",
|
||||
"keywords": [
|
||||
"alert",
|
||||
"battery",
|
||||
"charge",
|
||||
"charging",
|
||||
"critical",
|
||||
"hibernate",
|
||||
"level",
|
||||
"low",
|
||||
"percentages",
|
||||
"power",
|
||||
"reboot",
|
||||
"restart",
|
||||
"scale",
|
||||
"scaled",
|
||||
"shutdown",
|
||||
"sleep",
|
||||
"suspend",
|
||||
"thresholds"
|
||||
],
|
||||
"parentLabel": "Power & battery",
|
||||
"description": "Use the scaled battery level for alert thresholds and percentages"
|
||||
},
|
||||
{
|
||||
"section": "batteryStatusCard",
|
||||
"label": "Status",
|
||||
|
||||
Reference in new issue
Block a user