From 5e9e5e0229e64f7d4364c050274678cfe518af54 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 22 Sep 2020 11:19:43 -0700 Subject: [PATCH 1/7] power: Refactor battery row code into a `CcBatteryRow` type `set_primary()` and `add_primary()` had a lot of redundant code. This unifies them, and moves them to a custom widget called `CcBatteryRow`. This also decreases the somewhat excessive size of `cc-power-panel.c`, and makes it easier to see the layout of widgets, now that it's specified in xml. Before this, `warning-battery-offset` was set to `0.03` for a "primary" battery, and `0.05` otherwise. I expect this is a bug, so I've changed both to `0.03`. No other style or behavior change is intended. --- panels/power/cc-battery-row.c | 279 +++++++++++++++++++++++++++ panels/power/cc-battery-row.h | 46 +++++ panels/power/cc-battery-row.ui | 98 ++++++++++ panels/power/cc-power-panel.c | 314 ++----------------------------- panels/power/meson.build | 6 +- panels/power/power.gresource.xml | 1 + po/POTFILES.in | 1 + 7 files changed, 442 insertions(+), 303 deletions(-) create mode 100644 panels/power/cc-battery-row.c create mode 100644 panels/power/cc-battery-row.h create mode 100644 panels/power/cc-battery-row.ui diff --git a/panels/power/cc-battery-row.c b/panels/power/cc-battery-row.c new file mode 100644 index 0000000000..1ecf61f624 --- /dev/null +++ b/panels/power/cc-battery-row.c @@ -0,0 +1,279 @@ +/* cc-brightness-scale.c + * + * Copyright (C) 2010 Red Hat, Inc + * Copyright (C) 2008 William Jon McCann + * Copyright (C) 2010,2015 Richard Hughes + * Copyright (C) 2020 System76, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include + +#include "cc-battery-row.h" + +struct _CcBatteryRow { + GtkListBoxRow parent_instance; + + GtkBox *battery_box; + GtkLabel *details_label; + GtkImage *icon; + GtkLevelBar *levelbar; + GtkLabel *name_label; + GtkLabel *percentage_label; + GtkBox *primary_bottom_box; + GtkLabel *primary_percentage_label; +}; + +G_DEFINE_TYPE (CcBatteryRow, cc_battery_row, GTK_TYPE_LIST_BOX_ROW) + +static void +cc_battery_row_class_init (CcBatteryRowClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-battery-row.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, battery_box); + gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, details_label); + gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, icon); + gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, levelbar); + gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, name_label); + gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, percentage_label); + gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, primary_bottom_box); + gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, primary_percentage_label); +} + +static void +cc_battery_row_init (CcBatteryRow *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); +} + +static gchar * +get_timestring (guint64 time_secs) +{ + gchar* timestring = NULL; + gint hours; + gint minutes; + + /* Add 0.5 to do rounding */ + minutes = (int) ( ( time_secs / 60.0 ) + 0.5 ); + + if (minutes == 0) + return g_strdup (_("Unknown time")); + + if (minutes < 60) + return timestring = g_strdup_printf (ngettext ("%i minute", + "%i minutes", + minutes), minutes); + + hours = minutes / 60; + minutes = minutes % 60; + + if (minutes == 0) + return timestring = g_strdup_printf (ngettext ( + "%i hour", + "%i hours", + hours), hours); + + /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" + * Swap order with "%2$s %2$i %1$s %1$i if needed */ + return timestring = g_strdup_printf (_("%i %s %i %s"), + hours, ngettext ("hour", "hours", hours), + minutes, ngettext ("minute", "minutes", minutes)); +} + +static gchar * +get_details_string (gdouble percentage, UpDeviceState state, guint64 time) +{ + g_autofree gchar *details = NULL; + + if (time > 0) + { + g_autofree gchar *time_string = NULL; + + time_string = get_timestring (time); + switch (state) + { + case UP_DEVICE_STATE_CHARGING: + /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */ + details = g_strdup_printf (_("%s until fully charged"), time_string); + break; + case UP_DEVICE_STATE_DISCHARGING: + case UP_DEVICE_STATE_PENDING_DISCHARGE: + if (percentage < 20) + { + /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */ + details = g_strdup_printf (_("Caution: %s remaining"), time_string); + } + else + { + /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */ + details = g_strdup_printf (_("%s remaining"), time_string); + } + break; + case UP_DEVICE_STATE_FULLY_CHARGED: + /* TRANSLATORS: primary battery */ + details = g_strdup (_("Fully charged")); + break; + case UP_DEVICE_STATE_PENDING_CHARGE: + /* TRANSLATORS: primary battery */ + details = g_strdup (_("Not charging")); + break; + case UP_DEVICE_STATE_EMPTY: + /* TRANSLATORS: primary battery */ + details = g_strdup (_("Empty")); + break; + default: + details = g_strdup_printf ("error: %s", up_device_state_to_string (state)); + break; + } + } + else + { + switch (state) + { + case UP_DEVICE_STATE_CHARGING: + /* TRANSLATORS: primary battery */ + details = g_strdup (_("Charging")); + break; + case UP_DEVICE_STATE_DISCHARGING: + case UP_DEVICE_STATE_PENDING_DISCHARGE: + /* TRANSLATORS: primary battery */ + details = g_strdup (_("Discharging")); + break; + case UP_DEVICE_STATE_FULLY_CHARGED: + /* TRANSLATORS: primary battery */ + details = g_strdup (_("Fully charged")); + break; + case UP_DEVICE_STATE_PENDING_CHARGE: + /* TRANSLATORS: primary battery */ + details = g_strdup (_("Not charging")); + break; + case UP_DEVICE_STATE_EMPTY: + /* TRANSLATORS: primary battery */ + details = g_strdup (_("Empty")); + break; + default: + details = g_strdup_printf ("error: %s", + up_device_state_to_string (state)); + break; + } + } + + return g_steal_pointer (&details); +} + +CcBatteryRow* +cc_battery_row_new (UpDevice *device, + gboolean primary) +{ + g_autofree gchar *details = NULL; + gdouble percentage; + UpDeviceKind kind; + UpDeviceState state; + g_autofree gchar *s = NULL; + g_autofree gchar *icon_name = NULL; + const gchar *name; + CcBatteryRow *self; + guint64 time_empty, time_full, time; + gdouble energy_full, energy_rate; + + self = g_object_new (CC_TYPE_BATTERY_ROW, NULL); + + g_object_get (device, + "kind", &kind, + "state", &state, + "percentage", &percentage, + "icon-name", &icon_name, + "time-to-empty", &time_empty, + "time-to-full", &time_full, + "energy-full", &energy_full, + "energy-rate", &energy_rate, + NULL); + if (state == UP_DEVICE_STATE_DISCHARGING) + time = time_empty; + else + time = time_full; + + /* Name label */ + if (g_object_get_data (G_OBJECT (device), "is-main-battery") != NULL) + name = C_("Battery name", "Main"); + else + name = C_("Battery name", "Extra"); + gtk_label_set_text (self->name_label, name); + + /* Icon */ + if (icon_name != NULL && *icon_name != '\0') + gtk_image_set_from_icon_name (self->icon, icon_name, GTK_ICON_SIZE_BUTTON); + + /* Percentage label */ + s = g_strdup_printf ("%d%%", (int)percentage); + gtk_label_set_text (self->percentage_label, s); + gtk_label_set_text (self->primary_percentage_label, s); + + /* Level bar */ + gtk_level_bar_set_value (self->levelbar, percentage / 100.0); + + /* Details label (primary only) */ + details = get_details_string (percentage, state, time); + gtk_label_set_text (self->details_label, details); + + /* Handle "primary" row differently */ + gtk_widget_set_visible (GTK_WIDGET (self->battery_box), !primary); + gtk_widget_set_visible (GTK_WIDGET (self->percentage_label), !primary); + gtk_widget_set_visible (GTK_WIDGET (self->primary_bottom_box), primary); + atk_object_add_relationship (gtk_widget_get_accessible (GTK_WIDGET (self->levelbar)), + ATK_RELATION_LABELLED_BY, + gtk_widget_get_accessible (GTK_WIDGET (primary ? self->primary_percentage_label + : self->percentage_label))); + g_object_set_data (G_OBJECT (self), "primary", GINT_TO_POINTER (primary)); + + g_object_set_data (G_OBJECT (self), "kind", GINT_TO_POINTER (kind)); + + return self; +} + + + +void +cc_battery_row_set_level_sizegroup (CcBatteryRow *self, + GtkSizeGroup *sizegroup) +{ + gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->levelbar)); +} + +void +cc_battery_row_set_row_sizegroup (CcBatteryRow *self, + GtkSizeGroup *sizegroup) +{ + gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self)); +} + +void +cc_battery_row_set_charge_sizegroup (CcBatteryRow *self, + GtkSizeGroup *sizegroup) +{ + gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->percentage_label)); +} + +void +cc_battery_row_set_battery_sizegroup (CcBatteryRow *self, + GtkSizeGroup *sizegroup) +{ + gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->battery_box)); +} \ No newline at end of file diff --git a/panels/power/cc-battery-row.h b/panels/power/cc-battery-row.h new file mode 100644 index 0000000000..a4c27b629c --- /dev/null +++ b/panels/power/cc-battery-row.h @@ -0,0 +1,46 @@ +/* cc-brightness-scale.h + * + * Copyright (C) 2020 System76, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +#define CC_TYPE_BATTERY_ROW (cc_battery_row_get_type()) +G_DECLARE_FINAL_TYPE (CcBatteryRow, cc_battery_row, CC, BATTERY_ROW, GtkListBoxRow) + +CcBatteryRow* cc_battery_row_new (UpDevice *device, + gboolean primary); + +void cc_battery_row_set_level_sizegroup (CcBatteryRow *self, + GtkSizeGroup *sizegroup); + +void cc_battery_row_set_row_sizegroup (CcBatteryRow *self, + GtkSizeGroup *sizegroup); + +void cc_battery_row_set_charge_sizegroup (CcBatteryRow *self, + GtkSizeGroup *sizegroup); + +void cc_battery_row_set_battery_sizegroup (CcBatteryRow *self, + GtkSizeGroup *sizegroup); + +G_END_DECLS \ No newline at end of file diff --git a/panels/power/cc-battery-row.ui b/panels/power/cc-battery-row.ui new file mode 100644 index 0000000000..932e5d39f1 --- /dev/null +++ b/panels/power/cc-battery-row.ui @@ -0,0 +1,98 @@ + + + + + + diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index 044f633f9f..368cb657eb 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -31,6 +31,7 @@ #include "shell/cc-object-storage.h" #include "list-box-helper.h" +#include "cc-battery-row.h" #include "cc-brightness-scale.h" #include "cc-power-panel.h" #include "cc-power-resources.h" @@ -316,131 +317,6 @@ get_chassis_type (GCancellable *cancellable) return g_variant_dup_string (inner, NULL); } -static gchar * -get_timestring (guint64 time_secs) -{ - gchar* timestring = NULL; - gint hours; - gint minutes; - - /* Add 0.5 to do rounding */ - minutes = (int) ( ( time_secs / 60.0 ) + 0.5 ); - - if (minutes == 0) - { - timestring = g_strdup (_("Unknown time")); - return timestring; - } - - if (minutes < 60) - { - timestring = g_strdup_printf (ngettext ("%i minute", - "%i minutes", - minutes), minutes); - return timestring; - } - - hours = minutes / 60; - minutes = minutes % 60; - - if (minutes == 0) - { - timestring = g_strdup_printf (ngettext ( - "%i hour", - "%i hours", - hours), hours); - return timestring; - } - - /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes" - * Swap order with "%2$s %2$i %1$s %1$i if needed */ - timestring = g_strdup_printf (_("%i %s %i %s"), - hours, ngettext ("hour", "hours", hours), - minutes, ngettext ("minute", "minutes", minutes)); - return timestring; -} - -static gchar * -get_details_string (gdouble percentage, UpDeviceState state, guint64 time) -{ - gchar *details; - - if (time > 0) - { - g_autofree gchar *time_string = NULL; - - time_string = get_timestring (time); - switch (state) - { - case UP_DEVICE_STATE_CHARGING: - /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */ - details = g_strdup_printf (_("%s until fully charged"), time_string); - break; - case UP_DEVICE_STATE_DISCHARGING: - case UP_DEVICE_STATE_PENDING_DISCHARGE: - if (percentage < 20) - { - /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */ - details = g_strdup_printf (_("Caution: %s remaining"), time_string); - } - else - { - /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */ - details = g_strdup_printf (_("%s remaining"), time_string); - } - break; - case UP_DEVICE_STATE_FULLY_CHARGED: - /* TRANSLATORS: primary battery */ - details = g_strdup (_("Fully charged")); - break; - case UP_DEVICE_STATE_PENDING_CHARGE: - /* TRANSLATORS: primary battery */ - details = g_strdup (_("Not charging")); - break; - case UP_DEVICE_STATE_EMPTY: - /* TRANSLATORS: primary battery */ - details = g_strdup (_("Empty")); - break; - default: - details = g_strdup_printf ("error: %s", up_device_state_to_string (state)); - break; - } - } - else - { - switch (state) - { - case UP_DEVICE_STATE_CHARGING: - /* TRANSLATORS: primary battery */ - details = g_strdup (_("Charging")); - break; - case UP_DEVICE_STATE_DISCHARGING: - case UP_DEVICE_STATE_PENDING_DISCHARGE: - /* TRANSLATORS: primary battery */ - details = g_strdup (_("Discharging")); - break; - case UP_DEVICE_STATE_FULLY_CHARGED: - /* TRANSLATORS: primary battery */ - details = g_strdup (_("Fully charged")); - break; - case UP_DEVICE_STATE_PENDING_CHARGE: - /* TRANSLATORS: primary battery */ - details = g_strdup (_("Not charging")); - break; - case UP_DEVICE_STATE_EMPTY: - /* TRANSLATORS: primary battery */ - details = g_strdup (_("Empty")); - break; - default: - details = g_strdup_printf ("error: %s", - up_device_state_to_string (state)); - break; - } - } - - return details; -} - static void load_custom_css (CcPowerPanel *self) { @@ -455,181 +331,15 @@ load_custom_css (CcPowerPanel *self) } static void -set_primary (CcPowerPanel *panel, UpDevice *device) +add_battery (CcPowerPanel *panel, UpDevice *device, gboolean primary) { - g_autofree gchar *details = NULL; - gdouble percentage; - guint64 time_empty, time_full, time; - UpDeviceState state; - GtkWidget *box, *box2, *label; - GtkWidget *levelbar, *row; - g_autofree gchar *s = NULL; - gdouble energy_full, energy_rate; - - g_object_get (device, - "state", &state, - "percentage", &percentage, - "time-to-empty", &time_empty, - "time-to-full", &time_full, - "energy-full", &energy_full, - "energy-rate", &energy_rate, - NULL); - if (state == UP_DEVICE_STATE_DISCHARGING) - time = time_empty; - else - time = time_full; - - /* Sometimes the reported state is fully charged but battery is at 99%, - refusing to reach 100%. In these cases, just assume 100%. */ - if (state == UP_DEVICE_STATE_FULLY_CHARGED && (100.0 - percentage <= 1.0)) - percentage = 100.0; - - details = get_details_string (percentage, state, time); - - row = no_prelight_row_new (); - gtk_widget_show (row); - box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); - gtk_widget_show (box); - gtk_container_add (GTK_CONTAINER (row), box); - - gtk_widget_set_margin_start (box, 12); - gtk_widget_set_margin_end (box, 12); - gtk_widget_set_margin_top (box, 16); - gtk_widget_set_margin_bottom (box, 14); - - levelbar = gtk_level_bar_new (); - gtk_widget_show (levelbar); - gtk_level_bar_set_value (GTK_LEVEL_BAR (levelbar), percentage / 100.0); - gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "warning-battery-offset", 0.03); - gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "low-battery-offset", 0.1); - gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "high-battery-offset", 1.0); - gtk_widget_set_hexpand (levelbar, TRUE); - gtk_widget_set_halign (levelbar, GTK_ALIGN_FILL); - gtk_widget_set_valign (levelbar, GTK_ALIGN_CENTER); - gtk_box_pack_start (GTK_BOX (box), levelbar, TRUE, TRUE, 0); - - box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_widget_show (box2); - gtk_box_pack_start (GTK_BOX (box), box2, FALSE, TRUE, 0); - - label = gtk_label_new (details); - gtk_widget_show (label); - gtk_widget_set_halign (label, GTK_ALIGN_START); - gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); - gtk_label_set_xalign (GTK_LABEL (label), 0.0); - gtk_box_pack_start (GTK_BOX (box2), label, TRUE, TRUE, 0); - - s = g_strdup_printf ("%d%%", (int)(percentage + 0.5)); - label = gtk_label_new (s); - gtk_widget_show (label); - gtk_widget_set_halign (label, GTK_ALIGN_END); - gtk_style_context_add_class (gtk_widget_get_style_context (label), GTK_STYLE_CLASS_DIM_LABEL); - gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0); - - atk_object_add_relationship (gtk_widget_get_accessible (levelbar), - ATK_RELATION_LABELLED_BY, - gtk_widget_get_accessible (label)); - - gtk_container_add (GTK_CONTAINER (panel->battery_list), row); - gtk_size_group_add_widget (panel->battery_row_sizegroup, row); - - g_object_set_data (G_OBJECT (row), "primary", GINT_TO_POINTER (TRUE)); - - gtk_widget_set_visible (panel->battery_section, TRUE); -} - -static void -add_battery (CcPowerPanel *panel, UpDevice *device) -{ - gdouble percentage; - UpDeviceKind kind; - UpDeviceState state; - GtkWidget *row; - GtkWidget *box; - GtkWidget *box2; - GtkWidget *label; - GtkWidget *title; - GtkWidget *levelbar; - GtkWidget *widget; - g_autofree gchar *s = NULL; - g_autofree gchar *icon_name = NULL; - const gchar *name; - - g_object_get (device, - "kind", &kind, - "state", &state, - "percentage", &percentage, - "icon-name", &icon_name, - NULL); - - if (g_object_get_data (G_OBJECT (device), "is-main-battery") != NULL) - name = C_("Battery name", "Main"); - else - name = C_("Battery name", "Extra"); - - row = no_prelight_row_new (); - gtk_widget_show (row); - box = row_box_new (); - gtk_box_set_spacing (GTK_BOX (box), 10); - gtk_container_add (GTK_CONTAINER (row), box); - - gtk_widget_set_margin_start (box, 12); - gtk_widget_set_margin_end (box, 12); - gtk_widget_set_margin_top (box, 16); - gtk_widget_set_margin_bottom (box, 14); - - box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_widget_show (box2); - title = row_title_new (name, NULL, NULL); - gtk_size_group_add_widget (panel->battery_sizegroup, box2); - gtk_box_pack_start (GTK_BOX (box2), title, FALSE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (box), box2, FALSE, TRUE, 0); - -#if 1 - if (icon_name != NULL && *icon_name != '\0') - { - widget = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON); - gtk_widget_show (widget); - gtk_style_context_add_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_DIM_LABEL); - gtk_widget_set_halign (widget, GTK_ALIGN_END); - gtk_widget_set_valign (widget, GTK_ALIGN_CENTER); - gtk_box_pack_start (GTK_BOX (box2), widget, TRUE, TRUE, 0); - } -#endif - - box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_widget_show (box2); - - s = g_strdup_printf ("%d%%", (int)percentage); - label = gtk_label_new (s); - gtk_widget_show (label); - gtk_widget_set_halign (label, GTK_ALIGN_END); - gtk_style_context_add_class (gtk_widget_get_style_context (label), GTK_STYLE_CLASS_DIM_LABEL); - gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0); - gtk_size_group_add_widget (panel->charge_sizegroup, label); - - levelbar = gtk_level_bar_new (); - gtk_widget_show (levelbar); - gtk_level_bar_set_value (GTK_LEVEL_BAR (levelbar), percentage / 100.0); - gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "warning-battery-offset", 0.05); - gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "low-battery-offset", 0.1); - gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (levelbar), "high-battery-offset", 1.0); - gtk_widget_set_hexpand (levelbar, TRUE); - gtk_widget_set_halign (levelbar, GTK_ALIGN_FILL); - gtk_widget_set_valign (levelbar, GTK_ALIGN_CENTER); - gtk_box_pack_start (GTK_BOX (box2), levelbar, TRUE, TRUE, 0); - gtk_size_group_add_widget (panel->level_sizegroup, levelbar); - gtk_box_pack_start (GTK_BOX (box), box2, TRUE, TRUE, 0); - - atk_object_add_relationship (gtk_widget_get_accessible (levelbar), - ATK_RELATION_LABELLED_BY, - gtk_widget_get_accessible (label)); - - - g_object_set_data (G_OBJECT (row), "kind", GINT_TO_POINTER (kind)); - gtk_container_add (GTK_CONTAINER (panel->battery_list), row); - gtk_size_group_add_widget (panel->battery_row_sizegroup, row); + CcBatteryRow *row = cc_battery_row_new (device, primary); + cc_battery_row_set_level_sizegroup (row, panel->level_sizegroup); + cc_battery_row_set_row_sizegroup (row, panel->battery_row_sizegroup); + cc_battery_row_set_charge_sizegroup (row, panel->charge_sizegroup); + cc_battery_row_set_battery_sizegroup (row, panel->battery_sizegroup); + gtk_container_add (GTK_CONTAINER (panel->battery_list), GTK_WIDGET (row)); gtk_widget_set_visible (panel->battery_section, TRUE); } @@ -963,7 +673,7 @@ up_client_changed (CcPowerPanel *self) gtk_label_set_label (GTK_LABEL (self->battery_heading), s); if (!on_ups && n_batteries > 1) - set_primary (self, composite); + add_battery (self, composite, TRUE); for (i = 0; self->devices != NULL && i < self->devices->len; i++) { @@ -979,15 +689,15 @@ up_client_changed (CcPowerPanel *self) } else if (kind == UP_DEVICE_KIND_UPS && on_ups) { - set_primary (self, device); + add_battery (self, device, TRUE); } else if (kind == UP_DEVICE_KIND_BATTERY && is_power_supply && !on_ups && n_batteries == 1) { - set_primary (self, device); + add_battery (self, device, TRUE); } else if (kind == UP_DEVICE_KIND_BATTERY && is_power_supply) { - add_battery (self, device); + add_battery (self, device, FALSE); } else { diff --git a/panels/power/meson.build b/panels/power/meson.build index 1700c91e8c..45ff95d3d0 100644 --- a/panels/power/meson.build +++ b/panels/power/meson.build @@ -18,6 +18,7 @@ i18n.merge_file( ) sources = files( + 'cc-battery-row.c', 'cc-brightness-scale.c', 'cc-power-panel.c' ) @@ -26,7 +27,10 @@ sources += gnome.mkenums_simple( 'cc-brightness-scale-types', sources: ['cc-brightness-scale.h']) -resource_data = files('cc-power-panel.ui') +resource_data = files( + 'cc-battery-row.ui', + 'cc-power-panel.ui' +) sources += gnome.compile_resources( 'cc-' + cappletname + '-resources', diff --git a/panels/power/power.gresource.xml b/panels/power/power.gresource.xml index f0bcb1a628..3b0fed18c1 100644 --- a/panels/power/power.gresource.xml +++ b/panels/power/power.gresource.xml @@ -1,6 +1,7 @@ + cc-battery-row.ui cc-power-panel.ui battery-levels.css diff --git a/po/POTFILES.in b/po/POTFILES.in index 0f809aaf07..8c325a64ba 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -150,6 +150,7 @@ panels/notifications/gnome-notifications-panel.desktop.in.in panels/online-accounts/cc-online-accounts-panel.c panels/online-accounts/gnome-online-accounts-panel.desktop.in.in panels/online-accounts/online-accounts.ui +panels/power/cc-battery-row.c panels/power/cc-power-panel.c panels/power/cc-power-panel.ui panels/power/gnome-power-panel.desktop.in.in From 9c05cd54530f02302a1211013fa8a69f792de4a4 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 12 Oct 2020 10:06:41 -0700 Subject: [PATCH 2/7] power: Remove get_battery_level() This was added in 6c447dc14a2a3a98d25e8a71fb3d5e08ae8b6fe6 to deal with both older and newer UPower versions. It should be safe now to assume a UPower version with this property. --- panels/power/cc-power-panel.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index 368cb657eb..3d68df8873 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -383,18 +383,6 @@ kind_to_description (UpDeviceKind kind) g_assert_not_reached (); } -static UpDeviceLevel -get_battery_level (UpDevice *device) -{ - UpDeviceLevel battery_level; - - if (!g_object_class_find_property (G_OBJECT_CLASS (G_OBJECT_GET_CLASS (device)), "battery-level")) - return UP_DEVICE_LEVEL_NONE; - - g_object_get (device, "battery-level", &battery_level, NULL); - return battery_level; -} - static void add_device (CcPowerPanel *panel, UpDevice *device) { @@ -419,8 +407,8 @@ add_device (CcPowerPanel *panel, UpDevice *device) "state", &state, "model", &name, "is-present", &is_present, + "battery-level", &battery_level, NULL); - battery_level = get_battery_level (device); if (!is_present) return; From 94ee4f7dcb83723d90284e4354f870b3296f220d Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 12 Oct 2020 11:02:32 -0700 Subject: [PATCH 3/7] power: Remove unused `status` code in add_device It seems this was added in ee36b0df91, but the `status` variable has been unused since a9683772d9 (committed in 2012). Seems safe to remove if it's been unused since 2012. --- panels/power/cc-power-panel.c | 45 ----------------------------------- 1 file changed, 45 deletions(-) diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index 3d68df8873..ba286cdb94 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -393,11 +393,9 @@ add_device (CcPowerPanel *panel, UpDevice *device) GtkWidget *box2; GtkWidget *widget; GtkWidget *title; - g_autoptr(GString) status = NULL; g_autoptr(GString) description = NULL; gdouble percentage; g_autofree gchar *name = NULL; - gboolean show_caution = FALSE; gboolean is_present; UpDeviceLevel battery_level; @@ -413,54 +411,11 @@ add_device (CcPowerPanel *panel, UpDevice *device) if (!is_present) return; - if (kind == UP_DEVICE_KIND_UPS) - show_caution = TRUE; - if (name == NULL || *name == '\0') description = g_string_new (_(kind_to_description (kind))); else description = g_string_new (name); - switch (state) - { - case UP_DEVICE_STATE_CHARGING: - case UP_DEVICE_STATE_PENDING_CHARGE: - /* TRANSLATORS: secondary battery */ - status = g_string_new(C_("Battery power", "Charging")); - break; - case UP_DEVICE_STATE_DISCHARGING: - case UP_DEVICE_STATE_PENDING_DISCHARGE: - if (percentage < 10 && show_caution) - { - /* TRANSLATORS: secondary battery */ - status = g_string_new (C_("Battery power", "Caution")); - } - else if (percentage < 30) - { - /* TRANSLATORS: secondary battery */ - status = g_string_new (C_("Battery power", "Low")); - } - else - { - /* TRANSLATORS: secondary battery */ - status = g_string_new (C_("Battery power", "Good")); - } - break; - case UP_DEVICE_STATE_FULLY_CHARGED: - /* TRANSLATORS: primary battery */ - status = g_string_new (C_("Battery power", "Fully charged")); - break; - case UP_DEVICE_STATE_EMPTY: - /* TRANSLATORS: primary battery */ - status = g_string_new (C_("Battery power", "Empty")); - break; - default: - status = g_string_new (up_device_state_to_string (state)); - break; - } - g_string_prepend (status, ""); - g_string_append (status, ""); - /* create the new widget */ row = no_prelight_row_new (); gtk_widget_show (row); From 30e1be8fea457ca29c19494728fc437e8f7138de Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 12 Oct 2020 10:44:31 -0700 Subject: [PATCH 4/7] power: Use CcBatteryRow for devices section as well This had another slightly different version of the same code. --- panels/power/cc-battery-row.c | 91 +++++++++++++++++++--- panels/power/cc-battery-row.h | 3 + panels/power/cc-power-panel.c | 142 ++++------------------------------ 3 files changed, 99 insertions(+), 137 deletions(-) diff --git a/panels/power/cc-battery-row.c b/panels/power/cc-battery-row.c index 1ecf61f624..55d7584d71 100644 --- a/panels/power/cc-battery-row.c +++ b/panels/power/cc-battery-row.c @@ -36,6 +36,9 @@ struct _CcBatteryRow { GtkLabel *percentage_label; GtkBox *primary_bottom_box; GtkLabel *primary_percentage_label; + + UpDeviceKind kind; + gboolean primary; }; G_DEFINE_TYPE (CcBatteryRow, cc_battery_row, GTK_TYPE_LIST_BOX_ROW) @@ -178,6 +181,46 @@ get_details_string (gdouble percentage, UpDeviceState state, guint64 time) return g_steal_pointer (&details); } +static const char * +kind_to_description (UpDeviceKind kind) +{ + switch (kind) + { + case UP_DEVICE_KIND_MOUSE: + /* TRANSLATORS: secondary battery */ + return N_("Wireless mouse"); + case UP_DEVICE_KIND_KEYBOARD: + /* TRANSLATORS: secondary battery */ + return N_("Wireless keyboard"); + case UP_DEVICE_KIND_UPS: + /* TRANSLATORS: secondary battery */ + return N_("Uninterruptible power supply"); + case UP_DEVICE_KIND_PDA: + /* TRANSLATORS: secondary battery */ + return N_("Personal digital assistant"); + case UP_DEVICE_KIND_PHONE: + /* TRANSLATORS: secondary battery */ + return N_("Cellphone"); + case UP_DEVICE_KIND_MEDIA_PLAYER: + /* TRANSLATORS: secondary battery */ + return N_("Media player"); + case UP_DEVICE_KIND_TABLET: + /* TRANSLATORS: secondary battery */ + return N_("Tablet"); + case UP_DEVICE_KIND_COMPUTER: + /* TRANSLATORS: secondary battery */ + return N_("Computer"); + case UP_DEVICE_KIND_GAMING_INPUT: + /* TRANSLATORS: secondary battery */ + return N_("Gaming input device"); + default: + /* TRANSLATORS: secondary battery, misc */ + return N_("Battery"); + } + + g_assert_not_reached (); +} + CcBatteryRow* cc_battery_row_new (UpDevice *device, gboolean primary) @@ -192,39 +235,55 @@ cc_battery_row_new (UpDevice *device, CcBatteryRow *self; guint64 time_empty, time_full, time; gdouble energy_full, energy_rate; + gboolean is_kind_battery; + UpDeviceLevel battery_level; self = g_object_new (CC_TYPE_BATTERY_ROW, NULL); g_object_get (device, "kind", &kind, "state", &state, + "model", &name, "percentage", &percentage, "icon-name", &icon_name, "time-to-empty", &time_empty, "time-to-full", &time_full, "energy-full", &energy_full, "energy-rate", &energy_rate, + "battery-level", &battery_level, NULL); if (state == UP_DEVICE_STATE_DISCHARGING) time = time_empty; else time = time_full; + is_kind_battery = (kind == UP_DEVICE_KIND_BATTERY || kind == UP_DEVICE_KIND_UPS); + /* Name label */ - if (g_object_get_data (G_OBJECT (device), "is-main-battery") != NULL) - name = C_("Battery name", "Main"); - else - name = C_("Battery name", "Extra"); + if (is_kind_battery) + { + if (g_object_get_data (G_OBJECT (device), "is-main-battery") != NULL) + name = C_("Battery name", "Main"); + else + name = C_("Battery name", "Extra"); + } + else if (name == NULL || name[0] == '\0') + { + name = _(kind_to_description (kind)); + } gtk_label_set_text (self->name_label, name); /* Icon */ - if (icon_name != NULL && *icon_name != '\0') + if (is_kind_battery && icon_name != NULL && icon_name[0] != '\0') gtk_image_set_from_icon_name (self->icon, icon_name, GTK_ICON_SIZE_BUTTON); /* Percentage label */ - s = g_strdup_printf ("%d%%", (int)percentage); - gtk_label_set_text (self->percentage_label, s); - gtk_label_set_text (self->primary_percentage_label, s); + if (battery_level == UP_DEVICE_LEVEL_NONE) + { + s = g_strdup_printf ("%d%%", (int)percentage); + gtk_label_set_text (self->percentage_label, s); + gtk_label_set_text (self->primary_percentage_label, s); + } /* Level bar */ gtk_level_bar_set_value (self->levelbar, percentage / 100.0); @@ -241,9 +300,9 @@ cc_battery_row_new (UpDevice *device, ATK_RELATION_LABELLED_BY, gtk_widget_get_accessible (GTK_WIDGET (primary ? self->primary_percentage_label : self->percentage_label))); - g_object_set_data (G_OBJECT (self), "primary", GINT_TO_POINTER (primary)); - g_object_set_data (G_OBJECT (self), "kind", GINT_TO_POINTER (kind)); + self->kind = kind; + self->primary = primary; return self; } @@ -276,4 +335,16 @@ cc_battery_row_set_battery_sizegroup (CcBatteryRow *self, GtkSizeGroup *sizegroup) { gtk_size_group_add_widget (sizegroup, GTK_WIDGET (self->battery_box)); +} + +gboolean +cc_battery_row_get_primary (CcBatteryRow *self) +{ + return self->primary; +} + +UpDeviceKind +cc_battery_row_get_kind (CcBatteryRow *self) +{ + return self->kind; } \ No newline at end of file diff --git a/panels/power/cc-battery-row.h b/panels/power/cc-battery-row.h index a4c27b629c..e3b72feb25 100644 --- a/panels/power/cc-battery-row.h +++ b/panels/power/cc-battery-row.h @@ -43,4 +43,7 @@ void cc_battery_row_set_charge_sizegroup (CcBatteryRow *self, void cc_battery_row_set_battery_sizegroup (CcBatteryRow *self, GtkSizeGroup *sizegroup); +gboolean cc_battery_row_get_primary (CcBatteryRow *self); +UpDeviceKind cc_battery_row_get_kind (CcBatteryRow *self); + G_END_DECLS \ No newline at end of file diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index ba286cdb94..58f4fc6b13 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -343,128 +343,16 @@ add_battery (CcPowerPanel *panel, UpDevice *device, gboolean primary) gtk_widget_set_visible (panel->battery_section, TRUE); } -static const char * -kind_to_description (UpDeviceKind kind) -{ - switch (kind) - { - case UP_DEVICE_KIND_MOUSE: - /* TRANSLATORS: secondary battery */ - return N_("Wireless mouse"); - case UP_DEVICE_KIND_KEYBOARD: - /* TRANSLATORS: secondary battery */ - return N_("Wireless keyboard"); - case UP_DEVICE_KIND_UPS: - /* TRANSLATORS: secondary battery */ - return N_("Uninterruptible power supply"); - case UP_DEVICE_KIND_PDA: - /* TRANSLATORS: secondary battery */ - return N_("Personal digital assistant"); - case UP_DEVICE_KIND_PHONE: - /* TRANSLATORS: secondary battery */ - return N_("Cellphone"); - case UP_DEVICE_KIND_MEDIA_PLAYER: - /* TRANSLATORS: secondary battery */ - return N_("Media player"); - case UP_DEVICE_KIND_TABLET: - /* TRANSLATORS: secondary battery */ - return N_("Tablet"); - case UP_DEVICE_KIND_COMPUTER: - /* TRANSLATORS: secondary battery */ - return N_("Computer"); - case UP_DEVICE_KIND_GAMING_INPUT: - /* TRANSLATORS: secondary battery */ - return N_("Gaming input device"); - default: - /* TRANSLATORS: secondary battery, misc */ - return N_("Battery"); - } - - g_assert_not_reached (); -} - static void add_device (CcPowerPanel *panel, UpDevice *device) { - UpDeviceKind kind; - UpDeviceState state; - GtkWidget *row; - GtkWidget *hbox; - GtkWidget *box2; - GtkWidget *widget; - GtkWidget *title; - g_autoptr(GString) description = NULL; - gdouble percentage; - g_autofree gchar *name = NULL; - gboolean is_present; - UpDeviceLevel battery_level; - - g_object_get (device, - "kind", &kind, - "percentage", &percentage, - "state", &state, - "model", &name, - "is-present", &is_present, - "battery-level", &battery_level, - NULL); - - if (!is_present) - return; - - if (name == NULL || *name == '\0') - description = g_string_new (_(kind_to_description (kind))); - else - description = g_string_new (name); - - /* create the new widget */ - row = no_prelight_row_new (); - gtk_widget_show (row); - hbox = row_box_new (); - gtk_container_add (GTK_CONTAINER (row), hbox); - title = row_title_new (description->str, NULL, NULL); - gtk_box_pack_start (GTK_BOX (hbox), title, FALSE, TRUE, 0); - gtk_size_group_add_widget (panel->battery_sizegroup, title); - - box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_widget_show (box2); - - if (battery_level == UP_DEVICE_LEVEL_NONE) - { - g_autofree gchar *s = NULL; - - s = g_strdup_printf ("%d%%", (int)(percentage + 0.5)); - widget = gtk_label_new (s); - } - else - { - widget = gtk_label_new (""); - } - - gtk_widget_show (widget); - gtk_widget_set_halign (widget, GTK_ALIGN_END); - gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); - gtk_label_set_xalign (GTK_LABEL (widget), 0.0); - gtk_style_context_add_class (gtk_widget_get_style_context (widget), GTK_STYLE_CLASS_DIM_LABEL); - gtk_box_pack_start (GTK_BOX (box2), widget, FALSE, TRUE, 0); - gtk_size_group_add_widget (panel->charge_sizegroup, widget); - - widget = gtk_level_bar_new (); - gtk_widget_show (widget); - gtk_widget_set_halign (widget, TRUE); - gtk_widget_set_halign (widget, GTK_ALIGN_FILL); - gtk_widget_set_valign (widget, GTK_ALIGN_CENTER); - gtk_level_bar_set_value (GTK_LEVEL_BAR (widget), percentage / 100.0f); - gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (widget), "warning-battery-offset", 0.03); - gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (widget), "low-battery-offset", 0.1); - gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (widget), "high-battery-offset", 1.0); - gtk_box_pack_start (GTK_BOX (box2), widget, TRUE, TRUE, 0); - gtk_size_group_add_widget (panel->level_sizegroup, widget); - gtk_box_pack_start (GTK_BOX (hbox), box2, TRUE, TRUE, 0); - - gtk_container_add (GTK_CONTAINER (panel->device_list), row); - gtk_size_group_add_widget (panel->row_sizegroup, row); - g_object_set_data (G_OBJECT (row), "kind", GINT_TO_POINTER (kind)); + CcBatteryRow *row = cc_battery_row_new (device, FALSE); + cc_battery_row_set_level_sizegroup (row, panel->level_sizegroup); + cc_battery_row_set_row_sizegroup (row, panel->row_sizegroup); + cc_battery_row_set_charge_sizegroup (row, panel->charge_sizegroup); + cc_battery_row_set_battery_sizegroup (row, panel->battery_sizegroup); + gtk_container_add (GTK_CONTAINER (panel->device_list), GTK_WIDGET (row)); gtk_widget_set_visible (panel->device_section, TRUE); } @@ -1893,25 +1781,25 @@ add_general_section (CcPowerPanel *self) } static gint -battery_sort_func (gconstpointer a, gconstpointer b, gpointer data) +battery_sort_func (GtkListBoxRow *a, GtkListBoxRow *b, gpointer data) { - GObject *row_a = (GObject*)a; - GObject *row_b = (GObject*)b; + CcBatteryRow *row_a = CC_BATTERY_ROW (a); + CcBatteryRow *row_b = CC_BATTERY_ROW (b); gboolean a_primary; gboolean b_primary; - gint a_kind; - gint b_kind; + UpDeviceKind a_kind; + UpDeviceKind b_kind; - a_primary = GPOINTER_TO_INT (g_object_get_data (row_a, "primary")); - b_primary = GPOINTER_TO_INT (g_object_get_data (row_b, "primary")); + a_primary = cc_battery_row_get_primary(row_a); + b_primary = cc_battery_row_get_primary(row_b); if (a_primary) return -1; else if (b_primary) return 1; - a_kind = GPOINTER_TO_INT (g_object_get_data (row_a, "kind")); - b_kind = GPOINTER_TO_INT (g_object_get_data (row_b, "kind")); + a_kind = cc_battery_row_get_kind(row_a); + b_kind = cc_battery_row_get_kind(row_b); return a_kind - b_kind; } From 514eba9f319e805ebcfedcc1e77ca725dd4caba2 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 9 Nov 2020 13:55:20 -0800 Subject: [PATCH 5/7] power: System76 Charge Threshold profiles --- panels/power/cc-charge-threshold-dialog.c | 194 ++++++++++++++++++ panels/power/cc-charge-threshold-dialog.h | 42 ++++ panels/power/cc-charge-threshold-dialog.ui | 90 ++++++++ panels/power/cc-charge-threshold-row.c | 105 ++++++++++ panels/power/cc-charge-threshold-row.h | 30 +++ panels/power/cc-charge-threshold-row.ui | 49 +++++ panels/power/cc-power-panel.c | 112 +++++++++- .../power/data/com.system76.PowerDaemon.xml | 47 +++++ panels/power/meson.build | 14 ++ panels/power/power.gresource.xml | 2 + 10 files changed, 681 insertions(+), 4 deletions(-) create mode 100644 panels/power/cc-charge-threshold-dialog.c create mode 100644 panels/power/cc-charge-threshold-dialog.h create mode 100644 panels/power/cc-charge-threshold-dialog.ui create mode 100644 panels/power/cc-charge-threshold-row.c create mode 100644 panels/power/cc-charge-threshold-row.h create mode 100644 panels/power/cc-charge-threshold-row.ui create mode 100644 panels/power/data/com.system76.PowerDaemon.xml diff --git a/panels/power/cc-charge-threshold-dialog.c b/panels/power/cc-charge-threshold-dialog.c new file mode 100644 index 0000000000..5a5a19c43a --- /dev/null +++ b/panels/power/cc-charge-threshold-dialog.c @@ -0,0 +1,194 @@ +#include "cc-charge-threshold-dialog.h" +#include "cc-charge-threshold-row.h" +#include "list-box-helper.h" + +ChargeProfile charge_profile_from_thresholds (guchar start, guchar end) { + if (start == 50 && end == 60) + return CHARGE_PROFILE_MAX_LIFESPAN; + else if (start == 85 && end == 90) + return CHARGE_PROFILE_BALANCED; + else if (start == 96 && end == 100) + return CHARGE_PROFILE_FULL_CHARGE; + else + return CHARGE_PROFILE_UNDEFINED; +} + +void charge_profile_get_thresholds (ChargeProfile profile, guchar *start, guchar *end) { + switch (profile) { + case CHARGE_PROFILE_MAX_LIFESPAN: + *start = 50; + *end = 60; + break; + case CHARGE_PROFILE_BALANCED: + *start = 85; + *end = 90; + break; + case CHARGE_PROFILE_FULL_CHARGE: + default: + *start = 96; + *end = 100; + break; + } +} + +gchar *charge_profile_title_from_thresholds (guchar start, guchar end) { + switch (charge_profile_from_thresholds (start, end)) { + case CHARGE_PROFILE_MAX_LIFESPAN: + return g_strdup ("Max lifespan"); + case CHARGE_PROFILE_BALANCED: + return g_strdup ("Balanced"); + case CHARGE_PROFILE_FULL_CHARGE: + return g_strdup ("Full Charge"); + default: + return g_strdup_printf ("Custom (%d%% - %d%%)", start, end); + } +} + +struct _CcChargeThresholdDialog { + GtkDialog parent_instance; + + S76PowerDaemon *power_proxy; + GtkScale *scale; + GtkListBox *listbox; + GtkListBoxRow *max_lifespan_row; + GtkListBoxRow *balanced_row; + GtkListBoxRow *full_charge_row; + GtkRadioButton *max_lifespan_radio; + GtkRadioButton *balanced_radio; + GtkRadioButton *full_charge_radio; + GtkRadioButton *previous_radio; + GtkRadioButton *hidden_radio; +}; + +G_DEFINE_TYPE (CcChargeThresholdDialog, cc_charge_threshold_dialog, GTK_TYPE_DIALOG) + +static void radio_toggled_cb (CcChargeThresholdDialog *self, GtkRadioButton *radio); + +static void +set_charge_thresholds_ready(GObject *source_object, + GAsyncResult *res, + gpointer user_data) { + g_autoptr(GError) error = NULL; + CcChargeThresholdDialog *self = CC_CHARGE_THRESHOLD_DIALOG (user_data); + GtkRadioButton *previous_radio = self->previous_radio; + + s76_power_daemon_call_set_charge_thresholds_finish (self->power_proxy, res, &error); + if (error) { + g_signal_handlers_block_by_func (previous_radio, radio_toggled_cb, self); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (previous_radio), TRUE); + g_signal_handlers_unblock_by_func (previous_radio, radio_toggled_cb, self); + + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("Failed to call set-charge-thresholds: %s", error->message); + return; + } +} + +static void +radio_toggled_cb (CcChargeThresholdDialog *self, GtkRadioButton *radio) +{ + ChargeProfile profile; + guchar start, end; + GVariant *thresholds = NULL; + gboolean state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio)); + + if (!state) + { + self->previous_radio = radio; + return; + } + + if (radio == self->max_lifespan_radio) + profile = CHARGE_PROFILE_MAX_LIFESPAN; + else if (radio == self->balanced_radio) + profile = CHARGE_PROFILE_BALANCED; + else if (radio == self->full_charge_radio) + profile = CHARGE_PROFILE_FULL_CHARGE; + else + return; + + charge_profile_get_thresholds (profile, &start, &end); + thresholds = g_variant_new ("(yy)", start, end); + + s76_power_daemon_call_set_charge_thresholds (self->power_proxy, thresholds, NULL, set_charge_thresholds_ready, self); +} + +static void +row_activated_cb (CcChargeThresholdDialog *self, GtkListBoxRow *row) +{ + if (row == self->max_lifespan_row) + gtk_button_clicked (GTK_BUTTON (self->max_lifespan_radio)); + else if (row == self->balanced_row) + gtk_button_clicked (GTK_BUTTON (self->balanced_radio)); + else if (row == self->full_charge_row) + gtk_button_clicked (GTK_BUTTON (self->full_charge_radio)); +} + +static void +cc_charge_threshold_dialog_class_init (CcChargeThresholdDialogClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + g_type_ensure (CC_TYPE_CHARGE_THRESHOLD_ROW); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-charge-threshold-dialog.ui"); + + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, listbox); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, max_lifespan_row); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, balanced_row); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, full_charge_row); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, max_lifespan_radio); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, balanced_radio); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, full_charge_radio); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, hidden_radio); + + gtk_widget_class_bind_template_callback (widget_class, radio_toggled_cb); + gtk_widget_class_bind_template_callback (widget_class, row_activated_cb); +} + +static void +cc_charge_threshold_dialog_init (CcChargeThresholdDialog *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); + + self->power_proxy = NULL; + + gtk_list_box_set_header_func (self->listbox, cc_list_box_update_header_func, NULL, NULL); +} + +CcChargeThresholdDialog* +cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile profile) +{ + GtkRadioButton *radio = NULL; + CcChargeThresholdDialog *dialog = g_object_new (CC_TYPE_CHARGE_THRESHOLD_DIALOG, + "use-header-bar", 1, + NULL); + dialog->power_proxy = power_proxy; + + switch (profile) { + case CHARGE_PROFILE_MAX_LIFESPAN: + radio = dialog->max_lifespan_radio; + break; + case CHARGE_PROFILE_BALANCED: + radio = dialog->balanced_radio; + break; + case CHARGE_PROFILE_FULL_CHARGE: + radio = dialog->full_charge_radio; + break; + default: + break; + } + + if (radio) + { + g_signal_handlers_block_by_func (radio, radio_toggled_cb, dialog); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); + g_signal_handlers_unblock_by_func (radio, radio_toggled_cb, dialog); + } + else + { + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->hidden_radio), TRUE); + } + + return dialog; +} diff --git a/panels/power/cc-charge-threshold-dialog.h b/panels/power/cc-charge-threshold-dialog.h new file mode 100644 index 0000000000..93657ab6a6 --- /dev/null +++ b/panels/power/cc-charge-threshold-dialog.h @@ -0,0 +1,42 @@ +/* cc-brightness-scale.h + * + * Copyright (C) 2020 System76, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#pragma once + +#include +#include "cc-system76-power-generated.h" + +G_BEGIN_DECLS + +typedef enum { + CHARGE_PROFILE_MAX_LIFESPAN, + CHARGE_PROFILE_BALANCED, + CHARGE_PROFILE_FULL_CHARGE, + CHARGE_PROFILE_UNDEFINED, +} ChargeProfile; + +#define CC_TYPE_CHARGE_THRESHOLD_DIALOG (cc_charge_threshold_dialog_get_type()) +G_DECLARE_FINAL_TYPE (CcChargeThresholdDialog, cc_charge_threshold_dialog, CC, CHARGE_THRESHOLD_DIALOG, GtkDialog) +CcChargeThresholdDialog* cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile profile); +ChargeProfile charge_profile_from_thresholds (guchar start, guchar end); +void charge_profile_get_thresholds (ChargeProfile profile, guchar *start, guchar *end); +gchar *charge_profile_title_from_thresholds (guchar start, guchar end); + +G_END_DECLS diff --git a/panels/power/cc-charge-threshold-dialog.ui b/panels/power/cc-charge-threshold-dialog.ui new file mode 100644 index 0000000000..1bc41e06fa --- /dev/null +++ b/panels/power/cc-charge-threshold-dialog.ui @@ -0,0 +1,90 @@ + + + + + diff --git a/panels/power/cc-charge-threshold-row.c b/panels/power/cc-charge-threshold-row.c new file mode 100644 index 0000000000..3ea939b203 --- /dev/null +++ b/panels/power/cc-charge-threshold-row.c @@ -0,0 +1,105 @@ +#include "cc-charge-threshold-row.h" + +struct _CcChargeThresholdRow { + GtkListBoxRow parent_instance; + GtkRadioButton *radio; + char *title; + char *description; +}; + +G_DEFINE_TYPE (CcChargeThresholdRow, cc_charge_threshold_row, GTK_TYPE_LIST_BOX_ROW) + +enum +{ + PROP_0, + PROP_TITLE, + PROP_DESCRIPTION, + PROP_LAST +}; + +static void +finalize (GObject *object) +{ + CcChargeThresholdRow *self = CC_CHARGE_THRESHOLD_ROW (object); + g_free (self->title); + g_free (self->description); +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + CcChargeThresholdRow *self = CC_CHARGE_THRESHOLD_ROW (object); + + switch (prop_id) { + case PROP_TITLE: + self->title = g_value_dup_string (value); + break; + case PROP_DESCRIPTION: + self->description = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + CcChargeThresholdRow *self = CC_CHARGE_THRESHOLD_ROW (object); + + switch (prop_id) { + case PROP_TITLE: + g_value_set_string (value, self->title); + break; + case PROP_DESCRIPTION: + g_value_set_string (value, self->description); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +cc_charge_threshold_row_class_init (CcChargeThresholdRowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + g_object_class_install_property (object_class, + PROP_TITLE, + g_param_spec_string ("title", + "title", + "title", + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, + PROP_DESCRIPTION, + g_param_spec_string ("description", + "description", + "description", + NULL, + G_PARAM_READWRITE)); + + gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-charge-threshold-row.ui"); + + gtk_widget_class_bind_template_child_internal (widget_class, CcChargeThresholdRow, radio); +} + +static void +cc_charge_threshold_row_init (CcChargeThresholdRow *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); +} diff --git a/panels/power/cc-charge-threshold-row.h b/panels/power/cc-charge-threshold-row.h new file mode 100644 index 0000000000..3c92433d0b --- /dev/null +++ b/panels/power/cc-charge-threshold-row.h @@ -0,0 +1,30 @@ +/* cc-brightness-scale.h + * + * Copyright (C) 2020 System76, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#pragma once + +#include + +G_BEGIN_DECLS + +#define CC_TYPE_CHARGE_THRESHOLD_ROW (cc_charge_threshold_row_get_type()) +G_DECLARE_FINAL_TYPE (CcChargeThresholdRow, cc_charge_threshold_row, CC, CHARGE_THRESHOLD_ROW, GtkListBoxRow) + +G_END_DECLS diff --git a/panels/power/cc-charge-threshold-row.ui b/panels/power/cc-charge-threshold-row.ui new file mode 100644 index 0000000000..f3c4e64ecb --- /dev/null +++ b/panels/power/cc-charge-threshold-row.ui @@ -0,0 +1,49 @@ + + + + + diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index 58f4fc6b13..d694fd4d3e 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef HAVE_NETWORK_MANAGER #include @@ -33,6 +34,7 @@ #include "list-box-helper.h" #include "cc-battery-row.h" #include "cc-brightness-scale.h" +#include "cc-charge-threshold-dialog.h" #include "cc-power-panel.h" #include "cc-power-resources.h" #include "cc-util.h" @@ -102,6 +104,10 @@ struct _CcPowerPanel CcBrightnessScale *brightness_scale; GtkWidget *kbd_brightness_row; CcBrightnessScale *kbd_brightness_scale; + S76PowerDaemon *power_proxy; + GtkWidget* threshold_row; + GtkWidget* threshold_label; + ChargeProfile charge_profile; GtkWidget *automatic_suspend_row; GtkWidget *automatic_suspend_label; @@ -370,8 +376,10 @@ up_client_changed (CcPowerPanel *self) g_autofree gchar *s = NULL; battery_children = gtk_container_get_children (GTK_CONTAINER (self->battery_list)); - for (l = battery_children; l != NULL; l = l->next) - gtk_container_remove (GTK_CONTAINER (self->battery_list), l->data); + for (l = battery_children; l != NULL; l = l->next) { + if (CC_IS_BATTERY_ROW (l->data)) + gtk_container_remove (GTK_CONTAINER (self->battery_list), l->data); + } gtk_widget_hide (self->battery_section); device_children = gtk_container_get_children (GTK_CONTAINER (self->device_list)); @@ -1783,13 +1791,21 @@ add_general_section (CcPowerPanel *self) static gint battery_sort_func (GtkListBoxRow *a, GtkListBoxRow *b, gpointer data) { - CcBatteryRow *row_a = CC_BATTERY_ROW (a); - CcBatteryRow *row_b = CC_BATTERY_ROW (b); + CcBatteryRow *row_a; + CcBatteryRow *row_b; gboolean a_primary; gboolean b_primary; UpDeviceKind a_kind; UpDeviceKind b_kind; + if (!CC_IS_BATTERY_ROW (a)) + return 1; + else if (!CC_IS_BATTERY_ROW (b)) + return -1; + + row_a = CC_BATTERY_ROW (a); + row_b = CC_BATTERY_ROW (b); + a_primary = cc_battery_row_get_primary(row_a); b_primary = cc_battery_row_get_primary(row_b); @@ -1804,6 +1820,68 @@ battery_sort_func (GtkListBoxRow *a, GtkListBoxRow *b, gpointer data) return a_kind - b_kind; } +static void +charge_thresholds_ready(GObject *source_object, + GAsyncResult *res, + gpointer user_data) { + GVariant *thresholds = NULL; + g_autoptr(GError) error = NULL; + CcPowerPanel *self = CC_POWER_PANEL (user_data); + guchar start, end; + + s76_power_daemon_call_get_charge_thresholds_finish (self->power_proxy, &thresholds, res, &error); + if (!thresholds) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("Failed to call get-charge-thresholds: %s", error->message); + return; + } + + gtk_widget_show_all (self->threshold_row); + + g_variant_get(thresholds, "(yy)", &start, &end); + self->charge_profile = charge_profile_from_thresholds (start, end); + char *title = charge_profile_title_from_thresholds (start, end); + gtk_label_set_label (GTK_LABEL (self->threshold_label), title); + g_free (title); +} + +static void +load_charge_thresholds (CcPowerPanel *self) +{ + s76_power_daemon_call_get_charge_thresholds(self->power_proxy, cc_panel_get_cancellable (CC_PANEL (self)), charge_thresholds_ready, self); +} + +static void +power_proxy_ready(GObject *source_object, + GAsyncResult *res, + gpointer user_data) { + CcPowerPanel *self = CC_POWER_PANEL (user_data); + S76PowerDaemon *proxy; + g_autoptr(GError) error = NULL; + + proxy = s76_power_daemon_proxy_new_for_bus_finish (res, &error); + if (!proxy) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("Failed to get system76-power proxy: %s", error->message); + return; + } + + self->power_proxy = proxy; + + load_charge_thresholds (self); +} + +static void +battery_row_activated (CcPowerPanel *self) +{ + GtkWindow *toplevel; + CcChargeThresholdDialog *dialog = cc_charge_threshold_dialog_new (self->power_proxy, self->charge_profile); + toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))); + gtk_window_set_transient_for (GTK_WINDOW (dialog), toplevel); + g_signal_connect_object (G_OBJECT (dialog), "destroy", G_CALLBACK (load_charge_thresholds), self, G_CONNECT_SWAPPED); + gtk_widget_show (GTK_WIDGET (dialog)); +} + static void add_battery_section (CcPowerPanel *self) { @@ -1848,6 +1926,22 @@ add_battery_section (CcPowerPanel *self) gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); gtk_container_add (GTK_CONTAINER (frame), widget); gtk_box_pack_start (GTK_BOX (box), frame, FALSE, TRUE, 0); + + g_signal_connect_object(self->battery_list, "row-activated", G_CALLBACK (battery_row_activated), self, G_CONNECT_SWAPPED); + + // TODO add HdyActionRow + GtkWidget* image = gtk_image_new_from_icon_name ("go-next-symbolic", GTK_ICON_SIZE_BUTTON); + gtk_style_context_add_class (gtk_widget_get_style_context (image), "dim-label"); + GtkWidget* threshold_row = hdy_action_row_new (); + hdy_preferences_row_set_title (HDY_PREFERENCES_ROW (threshold_row), "Charge Threshold"); + hdy_action_row_set_subtitle (HDY_ACTION_ROW (threshold_row), "Adjust threshold to extend battery lifespan."); + gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (threshold_row), TRUE); + GtkWidget* threshold_label = gtk_label_new (NULL); + gtk_container_add (GTK_CONTAINER (threshold_row), threshold_label); + gtk_container_add (GTK_CONTAINER (threshold_row), image); + gtk_container_add (GTK_CONTAINER (self->battery_list), threshold_row); + self->threshold_row = threshold_row; + self->threshold_label = threshold_label; } static void @@ -1944,4 +2038,14 @@ cc_power_panel_init (CcPowerPanel *self) self->focus_adjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (self->main_scroll)); gtk_container_set_focus_vadjustment (GTK_CONTAINER (self->main_box), self->focus_adjustment); + + s76_power_daemon_proxy_new_for_bus ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "com.system76.PowerDaemon", + "/com/system76/PowerDaemon", + cc_panel_get_cancellable (CC_PANEL (self)), + power_proxy_ready, + self + ); } diff --git a/panels/power/data/com.system76.PowerDaemon.xml b/panels/power/data/com.system76.PowerDaemon.xml new file mode 100644 index 0000000000..71a0067b95 --- /dev/null +++ b/panels/power/data/com.system76.PowerDaemon.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/panels/power/meson.build b/panels/power/meson.build index 45ff95d3d0..5ee6bf4cba 100644 --- a/panels/power/meson.build +++ b/panels/power/meson.build @@ -20,6 +20,8 @@ i18n.merge_file( sources = files( 'cc-battery-row.c', 'cc-brightness-scale.c', + 'cc-charge-threshold-dialog.c', + 'cc-charge-threshold-row.c', 'cc-power-panel.c' ) @@ -29,6 +31,8 @@ sources += gnome.mkenums_simple( resource_data = files( 'cc-battery-row.ui', + 'cc-charge-threshold-dialog.ui', + 'cc-charge-threshold-row.ui', 'cc-power-panel.ui' ) @@ -40,6 +44,16 @@ sources += gnome.compile_resources( export: true ) +power_namespace = 'com.system76.PowerDaemon' + +sources += gnome.gdbus_codegen( + 'cc-system76-power-generated', + 'data/' + power_namespace + '.xml', + interface_prefix: 'com.system76', + namespace: 'S76', + object_manager: true, +) + deps = common_deps + [ gnome_settings_dep, upower_glib_dep diff --git a/panels/power/power.gresource.xml b/panels/power/power.gresource.xml index 3b0fed18c1..c1dd96b22f 100644 --- a/panels/power/power.gresource.xml +++ b/panels/power/power.gresource.xml @@ -2,6 +2,8 @@ cc-battery-row.ui + cc-charge-threshold-dialog.ui + cc-charge-threshold-row.ui cc-power-panel.ui battery-levels.css From c9f51cc058fefde20ffe7412930e7eeed805889b Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Fri, 22 Jan 2021 12:37:15 -0800 Subject: [PATCH 6/7] power: Get Charge Profiles over Dbus --- panels/power/cc-charge-threshold-dialog.c | 120 ++++---------- panels/power/cc-charge-threshold-dialog.h | 13 +- panels/power/cc-charge-threshold-dialog.ui | 40 ----- panels/power/cc-charge-threshold-row.c | 154 +++++++++--------- panels/power/cc-charge-threshold-row.h | 16 ++ panels/power/cc-charge-threshold-row.ui | 6 +- panels/power/cc-power-panel.c | 56 +++++-- .../power/data/com.system76.PowerDaemon.xml | 9 + 8 files changed, 182 insertions(+), 232 deletions(-) diff --git a/panels/power/cc-charge-threshold-dialog.c b/panels/power/cc-charge-threshold-dialog.c index 5a5a19c43a..b1f644b6a6 100644 --- a/panels/power/cc-charge-threshold-dialog.c +++ b/panels/power/cc-charge-threshold-dialog.c @@ -1,63 +1,14 @@ #include "cc-charge-threshold-dialog.h" -#include "cc-charge-threshold-row.h" #include "list-box-helper.h" -ChargeProfile charge_profile_from_thresholds (guchar start, guchar end) { - if (start == 50 && end == 60) - return CHARGE_PROFILE_MAX_LIFESPAN; - else if (start == 85 && end == 90) - return CHARGE_PROFILE_BALANCED; - else if (start == 96 && end == 100) - return CHARGE_PROFILE_FULL_CHARGE; - else - return CHARGE_PROFILE_UNDEFINED; -} - -void charge_profile_get_thresholds (ChargeProfile profile, guchar *start, guchar *end) { - switch (profile) { - case CHARGE_PROFILE_MAX_LIFESPAN: - *start = 50; - *end = 60; - break; - case CHARGE_PROFILE_BALANCED: - *start = 85; - *end = 90; - break; - case CHARGE_PROFILE_FULL_CHARGE: - default: - *start = 96; - *end = 100; - break; - } -} - -gchar *charge_profile_title_from_thresholds (guchar start, guchar end) { - switch (charge_profile_from_thresholds (start, end)) { - case CHARGE_PROFILE_MAX_LIFESPAN: - return g_strdup ("Max lifespan"); - case CHARGE_PROFILE_BALANCED: - return g_strdup ("Balanced"); - case CHARGE_PROFILE_FULL_CHARGE: - return g_strdup ("Full Charge"); - default: - return g_strdup_printf ("Custom (%d%% - %d%%)", start, end); - } -} - struct _CcChargeThresholdDialog { GtkDialog parent_instance; S76PowerDaemon *power_proxy; GtkScale *scale; GtkListBox *listbox; - GtkListBoxRow *max_lifespan_row; - GtkListBoxRow *balanced_row; - GtkListBoxRow *full_charge_row; - GtkRadioButton *max_lifespan_radio; - GtkRadioButton *balanced_radio; - GtkRadioButton *full_charge_radio; - GtkRadioButton *previous_radio; GtkRadioButton *hidden_radio; + GtkRadioButton *previous_radio; }; G_DEFINE_TYPE (CcChargeThresholdDialog, cc_charge_threshold_dialog, GTK_TYPE_DIALOG) @@ -87,9 +38,9 @@ set_charge_thresholds_ready(GObject *source_object, static void radio_toggled_cb (CcChargeThresholdDialog *self, GtkRadioButton *radio) { - ChargeProfile profile; - guchar start, end; + ChargeProfile *profile; GVariant *thresholds = NULL; + GtkWidget *row; gboolean state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radio)); if (!state) @@ -98,17 +49,12 @@ radio_toggled_cb (CcChargeThresholdDialog *self, GtkRadioButton *radio) return; } - if (radio == self->max_lifespan_radio) - profile = CHARGE_PROFILE_MAX_LIFESPAN; - else if (radio == self->balanced_radio) - profile = CHARGE_PROFILE_BALANCED; - else if (radio == self->full_charge_radio) - profile = CHARGE_PROFILE_FULL_CHARGE; - else + row = gtk_widget_get_ancestor (GTK_WIDGET (radio), CC_TYPE_CHARGE_THRESHOLD_ROW); + if (row == NULL) return; - charge_profile_get_thresholds (profile, &start, &end); - thresholds = g_variant_new ("(yy)", start, end); + profile = cc_charge_threshold_row_get_profile (CC_CHARGE_THRESHOLD_ROW (row)); + thresholds = g_variant_new ("(yy)", profile->start, profile->end); s76_power_daemon_call_set_charge_thresholds (self->power_proxy, thresholds, NULL, set_charge_thresholds_ready, self); } @@ -116,12 +62,9 @@ radio_toggled_cb (CcChargeThresholdDialog *self, GtkRadioButton *radio) static void row_activated_cb (CcChargeThresholdDialog *self, GtkListBoxRow *row) { - if (row == self->max_lifespan_row) - gtk_button_clicked (GTK_BUTTON (self->max_lifespan_radio)); - else if (row == self->balanced_row) - gtk_button_clicked (GTK_BUTTON (self->balanced_radio)); - else if (row == self->full_charge_row) - gtk_button_clicked (GTK_BUTTON (self->full_charge_radio)); + CcChargeThresholdRow *profile_row = CC_CHARGE_THRESHOLD_ROW (row); + GtkRadioButton *radio = cc_charge_threshold_row_get_radio (profile_row); + gtk_button_clicked (GTK_BUTTON (radio)); } static void @@ -134,12 +77,6 @@ cc_charge_threshold_dialog_class_init (CcChargeThresholdDialogClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-charge-threshold-dialog.ui"); gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, listbox); - gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, max_lifespan_row); - gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, balanced_row); - gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, full_charge_row); - gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, max_lifespan_radio); - gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, balanced_radio); - gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, full_charge_radio); gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, hidden_radio); gtk_widget_class_bind_template_callback (widget_class, radio_toggled_cb); @@ -157,33 +94,32 @@ cc_charge_threshold_dialog_init (CcChargeThresholdDialog *self) } CcChargeThresholdDialog* -cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile profile) +cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile **profiles, ChargeProfile *profile) { - GtkRadioButton *radio = NULL; + GtkRadioButton *selected_radio = NULL; CcChargeThresholdDialog *dialog = g_object_new (CC_TYPE_CHARGE_THRESHOLD_DIALOG, "use-header-bar", 1, NULL); dialog->power_proxy = power_proxy; - switch (profile) { - case CHARGE_PROFILE_MAX_LIFESPAN: - radio = dialog->max_lifespan_radio; - break; - case CHARGE_PROFILE_BALANCED: - radio = dialog->balanced_radio; - break; - case CHARGE_PROFILE_FULL_CHARGE: - radio = dialog->full_charge_radio; - break; - default: - break; - } + for (int i = 0; profiles[i] != NULL; i++) + { + CcChargeThresholdRow *row = cc_charge_threshold_row_new (profiles[i]); + gtk_container_add (GTK_CONTAINER (dialog->listbox), GTK_WIDGET (row)); + + GtkRadioButton *radio = cc_charge_threshold_row_get_radio (row); + gtk_radio_button_join_group (radio, dialog->hidden_radio); + g_signal_connect_object (radio, "toggled", G_CALLBACK (radio_toggled_cb), dialog, G_CONNECT_SWAPPED); + + if (profiles[i] == profile) + selected_radio = radio; + } - if (radio) + if (selected_radio) { - g_signal_handlers_block_by_func (radio, radio_toggled_cb, dialog); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE); - g_signal_handlers_unblock_by_func (radio, radio_toggled_cb, dialog); + g_signal_handlers_block_by_func (selected_radio, radio_toggled_cb, dialog); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (selected_radio), TRUE); + g_signal_handlers_unblock_by_func (selected_radio, radio_toggled_cb, dialog); } else { diff --git a/panels/power/cc-charge-threshold-dialog.h b/panels/power/cc-charge-threshold-dialog.h index 93657ab6a6..58e4c6673c 100644 --- a/panels/power/cc-charge-threshold-dialog.h +++ b/panels/power/cc-charge-threshold-dialog.h @@ -22,21 +22,12 @@ #include #include "cc-system76-power-generated.h" +#include "cc-charge-threshold-row.h" G_BEGIN_DECLS -typedef enum { - CHARGE_PROFILE_MAX_LIFESPAN, - CHARGE_PROFILE_BALANCED, - CHARGE_PROFILE_FULL_CHARGE, - CHARGE_PROFILE_UNDEFINED, -} ChargeProfile; - #define CC_TYPE_CHARGE_THRESHOLD_DIALOG (cc_charge_threshold_dialog_get_type()) G_DECLARE_FINAL_TYPE (CcChargeThresholdDialog, cc_charge_threshold_dialog, CC, CHARGE_THRESHOLD_DIALOG, GtkDialog) -CcChargeThresholdDialog* cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile profile); -ChargeProfile charge_profile_from_thresholds (guchar start, guchar end); -void charge_profile_get_thresholds (ChargeProfile profile, guchar *start, guchar *end); -gchar *charge_profile_title_from_thresholds (guchar start, guchar end); +CcChargeThresholdDialog* cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile **profiles, ChargeProfile *profile); G_END_DECLS diff --git a/panels/power/cc-charge-threshold-dialog.ui b/panels/power/cc-charge-threshold-dialog.ui index 1bc41e06fa..4bd36a8d83 100644 --- a/panels/power/cc-charge-threshold-dialog.ui +++ b/panels/power/cc-charge-threshold-dialog.ui @@ -26,45 +26,6 @@ True GTK_SELECTION_BROWSE - - - True - Full Charge (100%) - Battery is charged to its full capacity for the longest possible use on battery power. Charging resumes when the battery falls below 96% charge. - - - max_lifespan_radio - - - - - - - - True - Balanced (90%) - Use this threshold when you unplug frequently but don't need the full battery capacity. Charging stops when the battery reaches 90% capacity and resumes when the battery falls below 85%. - - - max_lifespan_radio - - - - - - - - True - Maximum Lifespan (60%) - Use this threshold if you rarely use the system on battery for extended periods. Charging stops when the battery reaches 60% capacity and resumes when the battery falls below 50%. - - - max_lifespan_radio - - - - - @@ -73,7 +34,6 @@ False - max_lifespan_radio diff --git a/panels/power/cc-charge-threshold-row.c b/panels/power/cc-charge-threshold-row.c index 3ea939b203..35cd1e6c04 100644 --- a/panels/power/cc-charge-threshold-row.c +++ b/panels/power/cc-charge-threshold-row.c @@ -3,99 +3,95 @@ struct _CcChargeThresholdRow { GtkListBoxRow parent_instance; GtkRadioButton *radio; - char *title; - char *description; + ChargeProfile *profile; + GtkLabel *title_label; + GtkLabel *description_label; }; G_DEFINE_TYPE (CcChargeThresholdRow, cc_charge_threshold_row, GTK_TYPE_LIST_BOX_ROW) -enum +ChargeProfile *charge_profiles_get (ChargeProfile **profiles, guchar start, guchar end) { - PROP_0, - PROP_TITLE, - PROP_DESCRIPTION, - PROP_LAST -}; - -static void -finalize (GObject *object) -{ - CcChargeThresholdRow *self = CC_CHARGE_THRESHOLD_ROW (object); - g_free (self->title); - g_free (self->description); + for (int i = 0; profiles[i] != NULL; i++) + if (profiles[i]->start == start && profiles[i]->end == end) + return profiles[i]; + return NULL; } -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +ChargeProfile **charge_profiles_from_variant (GVariant *variant) { - CcChargeThresholdRow *self = CC_CHARGE_THRESHOLD_ROW (object); - - switch (prop_id) { - case PROP_TITLE: - self->title = g_value_dup_string (value); - break; - case PROP_DESCRIPTION: - self->description = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + GVariantIter iter; + GVariant *dict; + ChargeProfile **profiles; + int i = 0; + gchar *id, *title, *description; + + profiles = g_malloc ((g_variant_n_children (variant) + 1) * sizeof (ChargeProfile*)); + + g_variant_iter_init (&iter, variant); + while ((dict = g_variant_iter_next_value (&iter))) + { + ChargeProfile *profile = g_malloc(sizeof (ChargeProfile)); + + gboolean success = TRUE; + success = success && g_variant_lookup (dict, "id", "s", &id); + success = success && g_variant_lookup (dict, "title", "s", &title); + success = success && g_variant_lookup (dict, "description", "s", &description); + success = success && g_variant_lookup (dict, "start", "y", &profile->start); + success = success && g_variant_lookup (dict, "end", "y", &profile->end); + + if (success) + { + profile->id = g_strdup(id); + profile->title = g_strdup(title); + profile->description = g_strdup(description); + profiles[i++] = profile; + } + else + { + g_warning ("Failed to parse charge profile"); + g_free (profile); + } + } + profiles[i] = NULL; + + return profiles; } -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +void charge_profiles_free (ChargeProfile **profiles) { - CcChargeThresholdRow *self = CC_CHARGE_THRESHOLD_ROW (object); - - switch (prop_id) { - case PROP_TITLE: - g_value_set_string (value, self->title); - break; - case PROP_DESCRIPTION: - g_value_set_string (value, self->description); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + for (int i = 0; profiles[i] != NULL; i++) + { + g_free (profiles[i]->id); + g_free (profiles[i]->title); + g_free (profiles[i]->description); + g_free (profiles[i]); + } + g_free (profiles); } static void cc_charge_threshold_row_class_init (CcChargeThresholdRowClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - - g_object_class_install_property (object_class, - PROP_TITLE, - g_param_spec_string ("title", - "title", - "title", - NULL, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, - PROP_DESCRIPTION, - g_param_spec_string ("description", - "description", - "description", - NULL, - G_PARAM_READWRITE)); - gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-charge-threshold-row.ui"); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdRow, radio); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdRow, title_label); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdRow, description_label); +} + +CcChargeThresholdRow* +cc_charge_threshold_row_new (ChargeProfile *profile) +{ + CcChargeThresholdRow *row; + + row = g_object_new(CC_TYPE_CHARGE_THRESHOLD_ROW, NULL); + row->profile = profile; + gtk_label_set_text (row->title_label, profile->title); + gtk_label_set_text (row->description_label, profile->description); - gtk_widget_class_bind_template_child_internal (widget_class, CcChargeThresholdRow, radio); + return row; } static void @@ -103,3 +99,15 @@ cc_charge_threshold_row_init (CcChargeThresholdRow *self) { gtk_widget_init_template (GTK_WIDGET (self)); } + +GtkRadioButton* +cc_charge_threshold_row_get_radio (CcChargeThresholdRow *self) +{ + return self->radio; +} + +ChargeProfile* +cc_charge_threshold_row_get_profile (CcChargeThresholdRow *self) +{ + return self->profile; +} diff --git a/panels/power/cc-charge-threshold-row.h b/panels/power/cc-charge-threshold-row.h index 3c92433d0b..9af0dd2453 100644 --- a/panels/power/cc-charge-threshold-row.h +++ b/panels/power/cc-charge-threshold-row.h @@ -24,7 +24,23 @@ G_BEGIN_DECLS +typedef struct { + gchar *id; + gchar *title; + gchar *description; + guchar start; + guchar end; +} ChargeProfile; + #define CC_TYPE_CHARGE_THRESHOLD_ROW (cc_charge_threshold_row_get_type()) G_DECLARE_FINAL_TYPE (CcChargeThresholdRow, cc_charge_threshold_row, CC, CHARGE_THRESHOLD_ROW, GtkListBoxRow) +CcChargeThresholdRow* cc_charge_threshold_row_new (ChargeProfile *profile); +GtkRadioButton* cc_charge_threshold_row_get_radio (CcChargeThresholdRow *self); +ChargeProfile* cc_charge_threshold_row_get_profile (CcChargeThresholdRow *self); + +ChargeProfile *charge_profiles_get (ChargeProfile **profiles, guchar start, guchar end); +ChargeProfile **charge_profiles_from_variant (GVariant *variant); +ChargeProfile **charge_profiles_from_variant (GVariant *variant); +void charge_profiles_free (ChargeProfile **profiles); G_END_DECLS diff --git a/panels/power/cc-charge-threshold-row.ui b/panels/power/cc-charge-threshold-row.ui index f3c4e64ecb..10ff0ac537 100644 --- a/panels/power/cc-charge-threshold-row.ui +++ b/panels/power/cc-charge-threshold-row.ui @@ -20,22 +20,20 @@ True vertical - + True start 0 - - + True start 0 True 70 70 - diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index d694fd4d3e..1ea5cddabc 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -105,9 +105,12 @@ struct _CcPowerPanel GtkWidget *kbd_brightness_row; CcBrightnessScale *kbd_brightness_scale; S76PowerDaemon *power_proxy; - GtkWidget* threshold_row; - GtkWidget* threshold_label; - ChargeProfile charge_profile; + GtkWidget* threshold_row; + GtkWidget* threshold_label; + ChargeProfile **charge_profiles; + ChargeProfile *charge_profile; + guint threshold_start; + guint threshold_end; GtkWidget *automatic_suspend_row; GtkWidget *automatic_suspend_label; @@ -1820,6 +1823,41 @@ battery_sort_func (GtkListBoxRow *a, GtkListBoxRow *b, gpointer data) return a_kind - b_kind; } +static void +charge_profiles_ready(GObject *source_object, + GAsyncResult *res, + gpointer user_data) { + g_autoptr(GError) error = NULL; + CcPowerPanel *self = CC_POWER_PANEL (user_data); + GVariant *profiles = NULL; + + s76_power_daemon_call_get_charge_profiles_finish (self->power_proxy, &profiles, res, &error); + if (error) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("Failed to call get-charge-profiles: %s", error->message); + return; + } + + ChargeProfile **charge_profiles = charge_profiles_from_variant (profiles); + ChargeProfile *profile = charge_profiles_get (charge_profiles, self->threshold_start, self->threshold_end); + if (profile != NULL) + gtk_label_set_label (GTK_LABEL (self->threshold_label), profile->title); + else + { + char *title = g_strdup_printf ("Custom (%d%% - %d%%)", self->threshold_start, self->threshold_end); + gtk_label_set_label (GTK_LABEL (self->threshold_label), title); + g_free (title); + } + if (self->charge_profiles != NULL) + charge_profiles_free (self->charge_profiles); + self->charge_profiles = charge_profiles; + self->charge_profile = profile; + + gtk_widget_show_all (self->threshold_row); + + g_variant_unref (profiles); +} + static void charge_thresholds_ready(GObject *source_object, GAsyncResult *res, @@ -1827,7 +1865,6 @@ charge_thresholds_ready(GObject *source_object, GVariant *thresholds = NULL; g_autoptr(GError) error = NULL; CcPowerPanel *self = CC_POWER_PANEL (user_data); - guchar start, end; s76_power_daemon_call_get_charge_thresholds_finish (self->power_proxy, &thresholds, res, &error); if (!thresholds) { @@ -1836,13 +1873,8 @@ charge_thresholds_ready(GObject *source_object, return; } - gtk_widget_show_all (self->threshold_row); - - g_variant_get(thresholds, "(yy)", &start, &end); - self->charge_profile = charge_profile_from_thresholds (start, end); - char *title = charge_profile_title_from_thresholds (start, end); - gtk_label_set_label (GTK_LABEL (self->threshold_label), title); - g_free (title); + g_variant_get(thresholds, "(yy)", &self->threshold_start, &self->threshold_end); + s76_power_daemon_call_get_charge_profiles(self->power_proxy, cc_panel_get_cancellable (CC_PANEL (self)), charge_profiles_ready, self); } static void @@ -1875,7 +1907,7 @@ static void battery_row_activated (CcPowerPanel *self) { GtkWindow *toplevel; - CcChargeThresholdDialog *dialog = cc_charge_threshold_dialog_new (self->power_proxy, self->charge_profile); + CcChargeThresholdDialog *dialog = cc_charge_threshold_dialog_new (self->power_proxy, self->charge_profiles, self->charge_profile); toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))); gtk_window_set_transient_for (GTK_WINDOW (dialog), toplevel); g_signal_connect_object (G_OBJECT (dialog), "destroy", G_CALLBACK (load_charge_thresholds), self, G_CONNECT_SWAPPED); diff --git a/panels/power/data/com.system76.PowerDaemon.xml b/panels/power/data/com.system76.PowerDaemon.xml index 71a0067b95..359264bf06 100644 --- a/panels/power/data/com.system76.PowerDaemon.xml +++ b/panels/power/data/com.system76.PowerDaemon.xml @@ -6,9 +6,18 @@ + + + + + + + + + From d3e922462cfac033636c8bf3dc9db8bf1259be9d Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Wed, 27 Jan 2021 13:02:34 -0800 Subject: [PATCH 7/7] power: Show text in dialog when threshold is custom --- panels/power/cc-charge-threshold-dialog.c | 12 ++++++++++-- panels/power/cc-charge-threshold-dialog.h | 2 +- panels/power/cc-charge-threshold-dialog.ui | 14 ++++++++++++++ panels/power/cc-power-panel.c | 4 +--- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/panels/power/cc-charge-threshold-dialog.c b/panels/power/cc-charge-threshold-dialog.c index b1f644b6a6..4d20b3f88c 100644 --- a/panels/power/cc-charge-threshold-dialog.c +++ b/panels/power/cc-charge-threshold-dialog.c @@ -9,6 +9,7 @@ struct _CcChargeThresholdDialog { GtkListBox *listbox; GtkRadioButton *hidden_radio; GtkRadioButton *previous_radio; + GtkLabel *custom_label; }; G_DEFINE_TYPE (CcChargeThresholdDialog, cc_charge_threshold_dialog, GTK_TYPE_DIALOG) @@ -76,6 +77,7 @@ cc_charge_threshold_dialog_class_init (CcChargeThresholdDialogClass *klass) gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-charge-threshold-dialog.ui"); + gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, custom_label); gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, listbox); gtk_widget_class_bind_template_child (widget_class, CcChargeThresholdDialog, hidden_radio); @@ -94,12 +96,13 @@ cc_charge_threshold_dialog_init (CcChargeThresholdDialog *self) } CcChargeThresholdDialog* -cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile **profiles, ChargeProfile *profile) +cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile **profiles, guint start, guint end) { GtkRadioButton *selected_radio = NULL; CcChargeThresholdDialog *dialog = g_object_new (CC_TYPE_CHARGE_THRESHOLD_DIALOG, "use-header-bar", 1, NULL); + g_autofree gchar *label = NULL; dialog->power_proxy = power_proxy; for (int i = 0; profiles[i] != NULL; i++) @@ -111,7 +114,7 @@ cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile **pro gtk_radio_button_join_group (radio, dialog->hidden_radio); g_signal_connect_object (radio, "toggled", G_CALLBACK (radio_toggled_cb), dialog, G_CONNECT_SWAPPED); - if (profiles[i] == profile) + if (profiles[i]->start == start && profiles[i]->end == end) selected_radio = radio; } @@ -124,6 +127,11 @@ cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile **pro else { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->hidden_radio), TRUE); + label = g_strdup_printf ("Custom battery charge threshold (%d%% – %d%%) " + "set via command line. Selecting one of the " + "profiles above will override custom setting.", + start, end); + gtk_label_set_text (dialog->custom_label, label); } return dialog; diff --git a/panels/power/cc-charge-threshold-dialog.h b/panels/power/cc-charge-threshold-dialog.h index 58e4c6673c..aad16c1dd0 100644 --- a/panels/power/cc-charge-threshold-dialog.h +++ b/panels/power/cc-charge-threshold-dialog.h @@ -28,6 +28,6 @@ G_BEGIN_DECLS #define CC_TYPE_CHARGE_THRESHOLD_DIALOG (cc_charge_threshold_dialog_get_type()) G_DECLARE_FINAL_TYPE (CcChargeThresholdDialog, cc_charge_threshold_dialog, CC, CHARGE_THRESHOLD_DIALOG, GtkDialog) -CcChargeThresholdDialog* cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile **profiles, ChargeProfile *profile); +CcChargeThresholdDialog* cc_charge_threshold_dialog_new (S76PowerDaemon *power_proxy, ChargeProfile **profiles, guint start, guint end); G_END_DECLS diff --git a/panels/power/cc-charge-threshold-dialog.ui b/panels/power/cc-charge-threshold-dialog.ui index 4bd36a8d83..14af64a0a8 100644 --- a/panels/power/cc-charge-threshold-dialog.ui +++ b/panels/power/cc-charge-threshold-dialog.ui @@ -12,6 +12,7 @@ True start + 0 True 70 70 @@ -30,6 +31,19 @@ + + + + 0 + start + True + 70 + 70 + + + + + diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index 1ea5cddabc..d32f7329d8 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -108,7 +108,6 @@ struct _CcPowerPanel GtkWidget* threshold_row; GtkWidget* threshold_label; ChargeProfile **charge_profiles; - ChargeProfile *charge_profile; guint threshold_start; guint threshold_end; @@ -1851,7 +1850,6 @@ charge_profiles_ready(GObject *source_object, if (self->charge_profiles != NULL) charge_profiles_free (self->charge_profiles); self->charge_profiles = charge_profiles; - self->charge_profile = profile; gtk_widget_show_all (self->threshold_row); @@ -1907,7 +1905,7 @@ static void battery_row_activated (CcPowerPanel *self) { GtkWindow *toplevel; - CcChargeThresholdDialog *dialog = cc_charge_threshold_dialog_new (self->power_proxy, self->charge_profiles, self->charge_profile); + CcChargeThresholdDialog *dialog = cc_charge_threshold_dialog_new (self->power_proxy, self->charge_profiles, self->threshold_start, self->threshold_end); toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self))); gtk_window_set_transient_for (GTK_WINDOW (dialog), toplevel); g_signal_connect_object (G_OBJECT (dialog), "destroy", G_CALLBACK (load_charge_thresholds), self, G_CONNECT_SWAPPED);