1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-08-02 11:38:30 -04:00
Files
bbedward 90291bd627 freebsd: add initial support for running on FreeBSD, excluding Bluez,
ppd, and some things. Add a simple wpa_supplicant backend
2026-07-19 10:31:48 -04:00

374 lines
16 KiB
QML

import QtQuick
import Quickshell.Io
import qs.Common
import qs.Services
import qs.Widgets
import qs.Modules.Settings.Widgets
Item {
id: root
Process {
id: applyLimitProcess
command: ["pkexec", "sh", "-c", "
for bat in /sys/class/power_supply/BAT*; do
if [ -f \"$bat/charge_control_limit_max\" ]; then
echo " + SettingsData.batteryChargeLimit + " > \"$bat/charge_control_limit_max\"
elif [ -f \"$bat/charge_stop_threshold\" ]; then
echo " + SettingsData.batteryChargeLimit + " > \"$bat/charge_stop_threshold\"
elif [ -f \"$bat/charge_control_end_threshold\" ]; then
echo " + SettingsData.batteryChargeLimit + " > \"$bat/charge_control_end_threshold\"
fi
done
"]
running: false
onExited: exitCode => {
if (exitCode !== 0) {
ToastService.showError(I18n.tr("Failed to apply charge limit to system"), I18n.tr("Process exited with code %1").arg(exitCode));
} else {
ToastService.showInfo(I18n.tr("Charge limit applied successfully"), I18n.tr("Limit set to %1%").arg(SettingsData.batteryChargeLimit));
}
}
}
DankFlickable {
anchors.fill: parent
clip: true
contentHeight: mainColumn.height + Theme.spacingXL
contentWidth: width
Column {
id: mainColumn
topPadding: 4
width: Math.min(550, parent.width - Theme.spacingL * 2)
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingXL
// 1. Information Card
SettingsCard {
width: parent.width
iconName: "battery_charging_full"
title: I18n.tr("Status")
settingKey: "batteryStatusCard"
tags: ["battery", "status", "charge", "health"]
Column {
width: parent.width - Theme.spacingM * 2
x: Theme.spacingM
spacing: Theme.spacingM
SettingsDivider {}
Row {
width: parent.width
StyledText {
text: I18n.tr("Power source")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
StyledText {
text: BatteryService.isPluggedIn ? I18n.tr("AC Adapter (Plugged In)") : I18n.tr("Battery Power")
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
}
SettingsDivider {}
Row {
width: parent.width
StyledText {
text: I18n.tr("Charge Level")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
StyledText {
text: `${BatteryService.batteryLevel}%`
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
}
SettingsDivider {}
Row {
width: parent.width
StyledText {
text: I18n.tr("Status")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
StyledText {
text: BatteryService.batteryStatus
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
}
SettingsDivider {}
Row {
width: parent.width
StyledText {
text: I18n.tr("Estimated Time")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
StyledText {
text: BatteryService.formatTimeRemaining()
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
}
SettingsDivider {}
Row {
width: parent.width
StyledText {
text: I18n.tr("Battery Health")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
StyledText {
text: BatteryService.batteryHealth
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
width: parent.width / 2
horizontalAlignment: Text.AlignLeft
}
}
}
}
// 2. Threshold & Limits Card
SettingsCard {
width: parent.width
iconName: "tune"
title: I18n.tr("Protection")
settingKey: "batteryProtection"
tags: ["battery", "protection", "charge", "limit"]
SettingsSliderRow {
settingKey: "batteryChargeLimit"
text: I18n.tr("Battery Charge Limit")
description: I18n.tr("Limit the maximum battery charge level to extend lifespan.")
value: SettingsData.batteryChargeLimit
minimum: 50
maximum: 100
defaultValue: 100
onSliderValueChanged: newValue => SettingsData.set("batteryChargeLimit", newValue)
}
Row {
// charge_control_* live in Linux sysfs; no BSD equivalent
visible: Qt.platform.os === "linux"
width: parent.width
height: applyButton.height
layoutDirection: I18n.isRtl ? Qt.LeftToRight : Qt.RightToLeft
Item {
width: Theme.spacingM
height: 1
}
DankButton {
id: applyButton
text: I18n.tr("Apply to Hardware")
iconName: "lock"
backgroundColor: Theme.primary
textColor: Theme.onPrimary
onClicked: {
applyLimitProcess.running = true;
}
}
}
SettingsToggleRow {
settingKey: "batteryNotifyChargeLimit"
text: I18n.tr("Notify when limit is reached")
description: I18n.tr("Show a notification when battery reaches the charge limit.")
checked: SettingsData.batteryNotifyChargeLimit
onToggled: checked => SettingsData.set("batteryNotifyChargeLimit", checked)
}
SettingsButtonGroupRow {
settingKey: "batteryChargeLimitNotificationType"
text: I18n.tr("Notification Type")
description: I18n.tr("Choose how to be notified when charge limit is reached.")
model: [I18n.tr("Toast"), I18n.tr("Notification")]
visible: SettingsData.batteryNotifyChargeLimit
currentIndex: SettingsData.batteryChargeLimitNotificationType
onSelectionChanged: (index, selected) => {
if (selected) {
SettingsData.set("batteryChargeLimitNotificationType", index);
}
}
}
}
// 3. Battery Alerts Card
SettingsCard {
width: parent.width
iconName: "notifications"
title: I18n.tr("Alerts")
settingKey: "batteryAlerts"
tags: ["battery", "alerts", "low", "warning"]
SettingsSliderRow {
settingKey: "batteryLowThreshold"
text: I18n.tr("Low Battery Threshold")
description: I18n.tr("Set the percentage at which the battery is considered low.")
value: SettingsData.batteryLowThreshold
minimum: 5
maximum: 40
defaultValue: 20
onSliderValueChanged: newValue => SettingsData.set("batteryLowThreshold", newValue)
}
SettingsToggleRow {
settingKey: "batteryNotifyLow"
text: I18n.tr("Low Battery Notifications")
description: I18n.tr("Show a warning popup when battery is running low.")
checked: SettingsData.batteryNotifyLow
onToggled: checked => SettingsData.set("batteryNotifyLow", checked)
}
SettingsButtonGroupRow {
settingKey: "batteryLowNotificationType"
text: I18n.tr("Notification Type")
description: I18n.tr("Choose how to be notified about low battery alerts.")
model: [I18n.tr("Toast"), I18n.tr("Notification")]
visible: SettingsData.batteryNotifyLow
currentIndex: SettingsData.batteryLowNotificationType
onSelectionChanged: (index, selected) => {
if (selected) {
SettingsData.set("batteryLowNotificationType", index);
}
}
}
SettingsDivider {}
StyledText {
text: I18n.tr("Critical Battery Alert")
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.DemiBold
color: Theme.surfaceText
x: Theme.spacingM
width: parent.width - Theme.spacingM * 2
topPadding: Theme.spacingS
}
SettingsSliderRow {
settingKey: "batteryCriticalThreshold"
text: I18n.tr("Critical Threshold")
description: I18n.tr("Battery percentage to trigger a critical alert.")
value: SettingsData.batteryCriticalThreshold
minimum: 1
maximum: 30
defaultValue: 10
onSliderValueChanged: newValue => SettingsData.set("batteryCriticalThreshold", newValue)
}
SettingsToggleRow {
settingKey: "batteryNotifyCritical"
text: I18n.tr("Critical Battery Notifications")
description: I18n.tr("Show an urgent alert when battery reaches critical level.")
checked: SettingsData.batteryNotifyCritical
onToggled: checked => SettingsData.set("batteryNotifyCritical", checked)
}
SettingsButtonGroupRow {
settingKey: "batteryCriticalNotificationType"
text: I18n.tr("Notification Type")
description: I18n.tr("Choose how to be notified about critical battery alerts.")
model: [I18n.tr("Toast"), I18n.tr("Notification")]
visible: SettingsData.batteryNotifyCritical
currentIndex: SettingsData.batteryCriticalNotificationType
onSelectionChanged: (index, selected) => {
if (selected) {
SettingsData.set("batteryCriticalNotificationType", index);
}
}
}
}
// 4. Power Profiles & Saving Card
SettingsCard {
width: parent.width
iconName: "power"
title: I18n.tr("Power Profiles & Saving")
settingKey: "powerProfilesSaving"
SettingsToggleRow {
settingKey: "batteryAutoPowerSaver"
text: I18n.tr("Auto Power Saver")
description: I18n.tr("Automatically turn on Power Saver profile when battery is low.")
checked: SettingsData.batteryAutoPowerSaver
onToggled: checked => SettingsData.set("batteryAutoPowerSaver", checked)
}
SettingsDivider {}
SettingsDropdownRow {
settingKey: "acProfileName"
text: I18n.tr("Profile when Plugged In (AC)")
options: [I18n.tr("Don't Change"), Theme.getPowerProfileLabel(0), Theme.getPowerProfileLabel(1), Theme.getPowerProfileLabel(2)]
currentValue: {
const val = SettingsData.acProfileName;
const idx = ["", "0", "1", "2"].indexOf(val);
return idx >= 0 ? options[idx] : options[0];
}
onValueChanged: value => {
const idx = options.indexOf(value);
if (idx >= 0) {
SettingsData.set("acProfileName", ["", "0", "1", "2"][idx]);
}
}
}
SettingsDropdownRow {
settingKey: "batteryProfileName"
text: I18n.tr("Profile when on Battery")
options: [I18n.tr("Don't Change"), Theme.getPowerProfileLabel(0), Theme.getPowerProfileLabel(1), Theme.getPowerProfileLabel(2)]
currentValue: {
const val = SettingsData.batteryProfileName;
const idx = ["", "0", "1", "2"].indexOf(val);
return idx >= 0 ? options[idx] : options[0];
}
onValueChanged: value => {
const idx = options.indexOf(value);
if (idx >= 0) {
SettingsData.set("batteryProfileName", ["", "0", "1", "2"][idx]);
}
}
}
}
}
}
}