Make battery page interactive

This commit is contained in:
Stephen Horvath
2025-03-19 15:07:10 +10:00
parent 17307fc7d5
commit cf179ca9bd
3 changed files with 163 additions and 8 deletions

View File

@@ -91,7 +91,7 @@
</object> </object>
</child> </child>
<child> <child>
<object class="AdwPreferencesGroup"> <object class="AdwPreferencesGroup" id="bat-ext-group">
<property name="description">Preserve the battery lifespan by gradually lowering battery charge voltage automatically if the system is connected to AC for more than the set day limit.</property> <property name="description">Preserve the battery lifespan by gradually lowering battery charge voltage automatically if the system is connected to AC for more than the set day limit.</property>
<property name="margin-bottom">5</property> <property name="margin-bottom">5</property>
<property name="margin-end">5</property> <property name="margin-end">5</property>
@@ -99,7 +99,7 @@
<property name="margin-top">5</property> <property name="margin-top">5</property>
<property name="title">Battery Extender</property> <property name="title">Battery Extender</property>
<child> <child>
<object class="AdwSwitchRow"> <object class="AdwSwitchRow" id="bat-ext-enable">
<property name="title">Enable</property> <property name="title">Enable</property>
</object> </object>
</child> </child>

View File

@@ -62,13 +62,13 @@
(4,5,"GtkBox",None,4,None,None,None,0,None,None), (4,5,"GtkBox",None,4,None,None,None,0,None,None),
(4,6,"GtkScale","chg-limit-scale",5,None,None,None,0,None,None), (4,6,"GtkScale","chg-limit-scale",5,None,None,None,0,None,None),
(4,7,"GtkAdjustment",None,6,None,None,None,0,None,None), (4,7,"GtkAdjustment",None,6,None,None,None,0,None,None),
(4,13,"AdwPreferencesGroup",None,2,None,None,None,5,None,None), (4,13,"AdwPreferencesGroup","bat-ext-group",2,None,None,None,5,None,None),
(4,27,"AdwSpinRow","bat-ext-trigger",13,None,None,None,5,None,None), (4,27,"AdwSpinRow","bat-ext-trigger",13,None,None,None,5,None,None),
(4,28,"GtkAdjustment",None,27,None,None,None,0,None,None), (4,28,"GtkAdjustment",None,27,None,None,None,0,None,None),
(4,29,"AdwSpinRow","bat-ext-reset",13,None,None,None,6,None,None), (4,29,"AdwSpinRow","bat-ext-reset",13,None,None,None,6,None,None),
(4,30,"GtkAdjustment",None,29,None,None,None,0,None,None), (4,30,"GtkAdjustment",None,29,None,None,None,0,None,None),
(4,31,"AdwActionRow","bat-ext-stage",13,None,None,None,2,None,None), (4,31,"AdwActionRow","bat-ext-stage",13,None,None,None,2,None,None),
(4,32,"AdwSwitchRow",None,13,None,None,None,1,None,None), (4,32,"AdwSwitchRow","bat-ext-enable",13,None,None,None,1,None,None),
(4,33,"AdwActionRow","bat-limit",2,None,None,None,3,None,None), (4,33,"AdwActionRow","bat-limit",2,None,None,None,3,None,None),
(4,34,"GtkBox",None,33,None,None,None,0,None,None), (4,34,"GtkBox",None,33,None,None,None,0,None,None),
(4,35,"GtkScale","bat-limit-scale",34,None,None,None,0,None,None), (4,35,"GtkScale","bat-limit-scale",34,None,None,None,0,None,None),

View File

@@ -47,6 +47,7 @@ class YAFI(Adw.Application):
self._change_page(builder, thermals_root) self._change_page(builder, thermals_root)
# Fan control
fan_rpm = thermals_builder.get_object("fan-rpm") fan_rpm = thermals_builder.get_object("fan-rpm")
fan_mode = thermals_builder.get_object("fan-mode") fan_mode = thermals_builder.get_object("fan-mode")
fan_set_rpm = thermals_builder.get_object("fan-set-rpm") fan_set_rpm = thermals_builder.get_object("fan-set-rpm")
@@ -83,6 +84,7 @@ class YAFI(Adw.Application):
fan_set_rpm.connect("notify::text", lambda entry, _: handle_fan_rpm(entry)) fan_set_rpm.connect("notify::text", lambda entry, _: handle_fan_rpm(entry))
# Temperature sensors
temperatures = thermals_builder.get_object("temperatures") temperatures = thermals_builder.get_object("temperatures")
temp_items = [] temp_items = []
@@ -156,7 +158,9 @@ class YAFI(Adw.Application):
if supported_colours[i]: if supported_colours[i]:
strings.append(colour) strings.append(colour)
add_colours(led_pwr_colour_strings, ec_commands.leds.EcLedId.EC_LED_ID_POWER_LED) add_colours(
led_pwr_colour_strings, ec_commands.leds.EcLedId.EC_LED_ID_POWER_LED
)
def handle_led_colour(combobox, led_id): def handle_led_colour(combobox, led_id):
colour = combobox.get_selected() - 2 colour = combobox.get_selected() - 2
@@ -192,7 +196,9 @@ class YAFI(Adw.Application):
led_charge_colour = leds_builder.get_object("led-chg-colour") led_charge_colour = leds_builder.get_object("led-chg-colour")
led_charge_colour_strings = led_charge_colour.get_model() led_charge_colour_strings = led_charge_colour.get_model()
add_colours(led_charge_colour_strings, ec_commands.leds.EcLedId.EC_LED_ID_BATTERY_LED) add_colours(
led_charge_colour_strings, ec_commands.leds.EcLedId.EC_LED_ID_BATTERY_LED
)
led_charge_colour.connect( led_charge_colour.connect(
"notify::selected", "notify::selected",
@@ -201,6 +207,25 @@ class YAFI(Adw.Application):
), ),
) )
def _format_timedelta(self, timedelta):
days = f"{timedelta.days} days, " if timedelta.days else ""
hours, remainder = divmod(timedelta.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return days + f"{hours}:{minutes:02}:{seconds:02}"
def _update_battery(self, bat_ext_stage, bat_ext_trigger_time, bat_ext_reset_time):
ec_extender = ec_commands.framework_laptop.get_battery_extender(self.cros_ec)
bat_ext_stage.set_subtitle(str(ec_extender["current_stage"]))
bat_ext_trigger_time.set_subtitle(
self._format_timedelta(ec_extender["trigger_timedelta"])
)
bat_ext_reset_time.set_subtitle(
self._format_timedelta(ec_extender["reset_timedelta"])
)
return self.current_page == 2
def _battery_page(self, builder): def _battery_page(self, builder):
# Load the battery.ui file # Load the battery.ui file
battery_builder = Gtk.Builder() battery_builder = Gtk.Builder()
@@ -211,6 +236,136 @@ class YAFI(Adw.Application):
self._change_page(builder, battery_root) self._change_page(builder, battery_root)
# Charge limiter
chg_limit_enable = battery_builder.get_object("chg-limit-enable")
chg_limit = battery_builder.get_object("chg-limit")
chg_limit_scale = battery_builder.get_object("chg-limit-scale")
bat_limit = battery_builder.get_object("bat-limit")
bat_limit_scale = battery_builder.get_object("bat-limit-scale")
chg_limit_override = battery_builder.get_object("chg-limit-override")
chg_limit_override_btn = battery_builder.get_object("chg-limit-override-btn")
ec_limit = ec_commands.framework_laptop.get_charge_limit(self.cros_ec)
ec_limit_enabled = ec_limit != (0, 0)
chg_limit_enable.set_active(ec_limit_enabled)
if ec_limit_enabled:
chg_limit_scale.set_value(ec_limit[0])
bat_limit_scale.set_value(ec_limit[1])
chg_limit.set_sensitive(True)
bat_limit.set_sensitive(True)
chg_limit_override.set_sensitive(True)
def handle_chg_limit_change(min, max):
ec_commands.framework_laptop.set_charge_limit(
self.cros_ec, int(min), int(max)
)
def handle_chg_limit_enable(switch):
active = switch.get_active()
if active:
handle_chg_limit_change(
chg_limit_scale.get_value(), bat_limit_scale.get_value()
)
else:
ec_commands.framework_laptop.disable_charge_limit(self.cros_ec)
chg_limit.set_sensitive(active)
bat_limit.set_sensitive(active)
chg_limit_override.set_sensitive(active)
chg_limit_enable.connect(
"notify::active", lambda switch, _: handle_chg_limit_enable(switch)
)
chg_limit_scale.connect(
"value-changed",
lambda scale: handle_chg_limit_change(
scale.get_value(), bat_limit_scale.get_value()
),
)
bat_limit_scale.connect(
"value-changed",
lambda scale: handle_chg_limit_change(
chg_limit_scale.get_value(), scale.get_value()
),
)
chg_limit_override_btn.connect(
"clicked",
lambda _: ec_commands.framework_laptop.override_charge_limit(self.cros_ec),
)
# Battery Extender
bat_ext_group = battery_builder.get_object("bat-ext-group")
bat_ext_enable = battery_builder.get_object("bat-ext-enable")
bat_ext_stage = battery_builder.get_object("bat-ext-stage")
bat_ext_trigger_time = battery_builder.get_object("bat-ext-trigger-time")
bat_ext_reset_time = battery_builder.get_object("bat-ext-reset-time")
bat_ext_trigger = battery_builder.get_object("bat-ext-trigger")
bat_ext_reset = battery_builder.get_object("bat-ext-reset")
ec_extender = ec_commands.framework_laptop.get_battery_extender(self.cros_ec)
bat_ext_enable.set_active(not ec_extender["disable"])
bat_ext_stage.set_sensitive(not ec_extender["disable"])
bat_ext_trigger_time.set_sensitive(not ec_extender["disable"])
bat_ext_reset_time.set_sensitive(not ec_extender["disable"])
bat_ext_trigger.set_sensitive(not ec_extender["disable"])
bat_ext_reset.set_sensitive(not ec_extender["disable"])
bat_ext_stage.set_subtitle(str(ec_extender["current_stage"]))
bat_ext_trigger_time.set_subtitle(
self._format_timedelta(ec_extender["trigger_timedelta"])
)
bat_ext_reset_time.set_subtitle(
self._format_timedelta(ec_extender["reset_timedelta"])
)
bat_ext_trigger.set_value(ec_extender["trigger_days"])
bat_ext_reset.set_value(ec_extender["reset_minutes"])
def handle_extender_enable(switch):
active = switch.get_active()
ec_commands.framework_laptop.set_battery_extender(
self.cros_ec,
not active,
int(bat_ext_trigger.get_value()),
int(bat_ext_reset.get_value()),
)
bat_ext_stage.set_sensitive(active)
bat_ext_trigger_time.set_sensitive(active)
bat_ext_reset_time.set_sensitive(active)
bat_ext_trigger.set_sensitive(active)
bat_ext_reset.set_sensitive(active)
bat_ext_enable.connect(
"notify::active", lambda switch, _: handle_extender_enable(switch)
)
bat_ext_trigger.connect(
"notify::value",
lambda scale, _: ec_commands.framework_laptop.set_battery_extender(
self.cros_ec,
not bat_ext_enable.get_active(),
int(scale.get_value()),
int(bat_ext_reset.get_value()),
),
)
bat_ext_reset.connect(
"notify::value",
lambda scale, _: ec_commands.framework_laptop.set_battery_extender(
self.cros_ec,
not bat_ext_enable.get_active(),
int(bat_ext_trigger.get_value()),
int(scale.get_value()),
),
)
# Schedule _update_battery to run every second
GLib.timeout_add_seconds(
1,
self._update_battery,
bat_ext_stage,
bat_ext_trigger_time,
bat_ext_reset_time,
)
def _hardware_page(self, builder): def _hardware_page(self, builder):
# Load the hardware.ui file # Load the hardware.ui file
hardware_builder = Gtk.Builder() hardware_builder = Gtk.Builder()