diff options
author | Bastien Nocera <hadess@hadess.net> | 2020-08-06 23:33:10 +0200 |
---|---|---|
committer | Bastien Nocera <hadess@hadess.net> | 2020-10-29 16:58:24 +0100 |
commit | f1bcaf1fbc1a103460fa807e07f01f961091ea63 (patch) | |
tree | 1f2c38dcb69787e6c0c9fdc489445ee81e2ac5a0 /panels | |
parent | 2def2718248cdc9d49f3d1eed289b898d6964944 (diff) | |
download | gnome-control-center-f1bcaf1fbc1a103460fa807e07f01f961091ea63.tar.gz |
power: Add "Power Mode" sectionwip/hadess/power-profiles
Use power-profiles-daemon[1] to implement switchable power profiles.
The performance profile will only be available on systems which provide
this functionality.
[1]: https://gitlab.freedesktop.org/hadess/power-profiles-daemon
Diffstat (limited to 'panels')
-rw-r--r-- | panels/power/cc-power-panel.c | 316 | ||||
-rw-r--r-- | panels/power/cc-power-profile-row.c | 403 | ||||
-rw-r--r-- | panels/power/cc-power-profile-row.h | 54 | ||||
-rw-r--r-- | panels/power/meson.build | 3 | ||||
-rw-r--r-- | panels/power/power-profiles.css | 7 | ||||
-rw-r--r-- | panels/power/power.gresource.xml | 1 |
6 files changed, 783 insertions, 1 deletions
diff --git a/panels/power/cc-power-panel.c b/panels/power/cc-power-panel.c index 92844e495..ab7695256 100644 --- a/panels/power/cc-power-panel.c +++ b/panels/power/cc-power-panel.c @@ -33,6 +33,7 @@ #include "list-box-helper.h" #include "cc-battery-row.h" #include "cc-brightness-scale.h" +#include "cc-power-profile-row.h" #include "cc-power-panel.h" #include "cc-power-resources.h" #include "cc-util.h" @@ -116,6 +117,11 @@ struct _CcPowerPanel GtkWidget *als_switch; GtkWidget *als_row; + GDBusProxy *power_profiles_proxy; + guint power_profiles_prop_id; + GtkWidget *power_profiles_row[NUM_CC_POWER_PROFILES]; + gboolean power_profiles_in_update; + GtkWidget *power_button_combo; GtkWidget *idle_delay_combo; @@ -320,6 +326,7 @@ load_custom_css (CcPowerPanel *self) /* use custom CSS */ provider = gtk_css_provider_new (); gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/power/battery-levels.css"); + gtk_css_provider_load_from_resource (provider, "/org/gnome/control-center/power/power-profiles.css"); gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); @@ -1656,6 +1663,314 @@ add_power_saving_section (CcPowerPanel *self) } static void +performance_profile_set_active (CcPowerPanel *self, + const char *profile_str) +{ + CcPowerProfile profile = cc_power_profile_from_str (profile_str); + GtkRadioButton *button; + + button = cc_power_profile_row_get_radio_button (CC_POWER_PROFILE_ROW (self->power_profiles_row[profile])); + g_assert (button); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); +} + +static void +performance_profile_set_inhibited (CcPowerPanel *self, + const char *performance_inhibited) +{ + GtkWidget *row; + + row = self->power_profiles_row[CC_POWER_PROFILE_PERFORMANCE]; + g_assert (row != NULL); + cc_power_profile_row_set_performance_inhibited (CC_POWER_PROFILE_ROW (row), + performance_inhibited); +} + +static void +power_profiles_row_activated_cb (GtkListBox *box, + GtkListBoxRow *box_row, + gpointer user_data) +{ + if (!gtk_widget_is_sensitive (GTK_WIDGET (box_row))) + return; + + cc_power_profile_row_set_active (CC_POWER_PROFILE_ROW(box_row), TRUE); +} + +static gint +perf_profile_list_box_sort (GtkListBoxRow *row1, + GtkListBoxRow *row2, + gpointer user_data) +{ + CcPowerProfile row1_profile, row2_profile; + + row1_profile = cc_power_profile_row_get_profile (CC_POWER_PROFILE_ROW (row1)); + row2_profile = cc_power_profile_row_get_profile (CC_POWER_PROFILE_ROW (row2)); + + if (row1_profile < row2_profile) + return -1; + if (row1_profile > row2_profile) + return 1; + return 0; +} + +static const char * +variant_lookup_string (GVariant *dict, + const char *key) +{ + GVariant *variant; + + variant = g_variant_lookup_value (dict, key, G_VARIANT_TYPE_STRING); + if (!variant) + return NULL; + return g_variant_get_string (variant, NULL); +} + +static void +power_profiles_properties_changed_cb (CcPowerPanel *self, + GVariant *changed_properties, + GStrv invalidated_properties, + GDBusProxy *proxy) +{ + g_autoptr(GVariantIter) iter = NULL; + const char *key; + g_autoptr(GVariant) value = NULL; + + g_variant_get (changed_properties, "a{sv}", &iter); + while (g_variant_iter_next (iter, "{&sv}", &key, &value)) + { + if (g_strcmp0 (key, "PerformanceInhibited") == 0) + { + performance_profile_set_inhibited (self, + g_variant_get_string (value, NULL)); + } + else if (g_strcmp0 (key, "ActiveProfile") == 0) + { + self->power_profiles_in_update = TRUE; + performance_profile_set_active (self, g_variant_get_string (value, NULL)); + self->power_profiles_in_update = FALSE; + } + else + { + g_debug ("Unhandled change on '%s' property", key); + } + } +} + +static void +set_active_profile_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GVariant) variant = NULL; + g_autoptr(GError) error = NULL; + + variant = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), + res, &error); + if (!variant) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("Could not set active profile: %s", error->message); + } +} + +static void +power_profile_button_toggled_cb (CcPowerProfileRow *row, + gpointer user_data) +{ + CcPowerPanel *self = user_data; + CcPowerProfile profile; + g_autoptr(GDBusConnection) connection = NULL; + g_autoptr(GError) error = NULL; + + if (!cc_power_profile_row_get_active (row)) + return; + if (self->power_profiles_in_update) + return; + + profile = cc_power_profile_row_get_profile (row); + + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, + cc_panel_get_cancellable (CC_PANEL (self)), + &error); + if (!connection) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("system bus not available: %s", error->message); + return; + } + + g_dbus_connection_call (connection, + "net.hadess.PowerProfiles", + "/net/hadess/PowerProfiles", + "org.freedesktop.DBus.Properties", + "Set", + g_variant_new ("(ssv)", + "net.hadess.PowerProfiles", + "ActiveProfile", + g_variant_new_string (cc_power_profile_to_str (profile))), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + cc_panel_get_cancellable (CC_PANEL (self)), + set_active_profile_cb, + NULL); +} + +static void +add_power_profiles_section (CcPowerPanel *self) +{ + GtkWidget *widget, *box, *label, *row; + g_autofree gchar *s = NULL; + g_autoptr(GDBusConnection) connection = NULL; + g_autoptr(GVariant) variant = NULL; + g_autoptr(GVariant) props = NULL; + guint i, num_children; + g_autoptr(GError) error = NULL; + const char *performance_inhibited; + const char *active_profile; + g_autoptr(GVariant) profiles = NULL; + GtkRadioButton *last_button; + + self->power_profiles_proxy = cc_object_storage_create_dbus_proxy_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "net.hadess.PowerProfiles", + "/net/hadess/PowerProfiles", + "net.hadess.PowerProfiles", + NULL, + &error); + + if (!self->power_profiles_proxy) + { + g_debug ("Could not create Power Profiles proxy: %s", error->message); + return; + } + + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, + cc_panel_get_cancellable (CC_PANEL (self)), + &error); + if (!connection) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("system bus not available: %s", error->message); + return; + } + + variant = g_dbus_connection_call_sync (connection, + "net.hadess.PowerProfiles", + "/net/hadess/PowerProfiles", + "org.freedesktop.DBus.Properties", + "GetAll", + g_variant_new ("(s)", + "net.hadess.PowerProfiles"), + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + + if (!variant) + { + g_debug ("Failed to get properties for Power Profiles: %s", + error->message); + g_clear_object (&self->power_profiles_proxy); + return; + } + + s = g_strdup_printf ("<b>%s</b>", _("Power Mode")); + label = gtk_label_new (s); + gtk_widget_show (label); + gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_label_set_use_markup (GTK_LABEL (label), TRUE); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_box_pack_start (GTK_BOX (self->vbox_power), label, FALSE, TRUE, 0); + + label = gtk_label_new (_("Affects system performance and power usage.")); + gtk_widget_show (label); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_widget_set_margin_bottom (label, 6); + gtk_box_pack_start (GTK_BOX (self->vbox_power), label, FALSE, TRUE, 0); + + widget = gtk_list_box_new (); + gtk_widget_show (widget); + self->boxes_reverse = g_list_prepend (self->boxes_reverse, widget); + g_signal_connect_object (widget, "keynav-failed", G_CALLBACK (keynav_failed), self, G_CONNECT_SWAPPED); + gtk_list_box_set_selection_mode (GTK_LIST_BOX (widget), GTK_SELECTION_NONE); + gtk_list_box_set_sort_func (GTK_LIST_BOX (widget), + perf_profile_list_box_sort, + NULL, NULL); + g_signal_connect_object (G_OBJECT (widget), "row-activated", + G_CALLBACK (power_profiles_row_activated_cb), NULL, 0); + gtk_list_box_set_header_func (GTK_LIST_BOX (widget), + cc_list_box_update_header_func, + NULL, NULL); + + atk_object_add_relationship (ATK_OBJECT (gtk_widget_get_accessible (label)), + ATK_RELATION_LABEL_FOR, + ATK_OBJECT (gtk_widget_get_accessible (widget))); + atk_object_add_relationship (ATK_OBJECT (gtk_widget_get_accessible (widget)), + ATK_RELATION_LABELLED_BY, + ATK_OBJECT (gtk_widget_get_accessible (label))); + + box = gtk_frame_new (NULL); + gtk_widget_show (box); + gtk_frame_set_shadow_type (GTK_FRAME (box), GTK_SHADOW_IN); + gtk_widget_set_margin_bottom (box, 32); + gtk_container_add (GTK_CONTAINER (box), widget); + gtk_box_pack_start (GTK_BOX (self->vbox_power), box, FALSE, TRUE, 0); + + props = g_variant_get_child_value (variant, 0); + performance_inhibited = variant_lookup_string (props, "PerformanceInhibited"); + active_profile = variant_lookup_string (props, "ActiveProfile"); + + last_button = NULL; + profiles = g_variant_lookup_value (props, "Profiles", NULL); + num_children = g_variant_n_children (profiles); + for (i = 0; i < num_children; i++) + { + g_autoptr(GVariant) profile_variant; + const char *name; + GtkRadioButton *button; + CcPowerProfile profile; + + profile_variant = g_variant_get_child_value (profiles, i); + if (!profile_variant || + !g_variant_is_of_type (profile_variant, G_VARIANT_TYPE ("a{sv}"))) + continue; + + name = variant_lookup_string (profile_variant, "Profile"); + if (!name) + continue; + g_debug ("Adding row for profile '%s' (driver: %s)", + name, variant_lookup_string (profile_variant, "Driver")); + + profile = cc_power_profile_from_str (name); + row = cc_power_profile_row_new (cc_power_profile_from_str (name), + performance_inhibited); + g_signal_connect_object (G_OBJECT (row), "button-toggled", + G_CALLBACK (power_profile_button_toggled_cb), self, + 0); + self->power_profiles_row[profile] = row; + gtk_widget_show (row); + gtk_container_add (GTK_CONTAINER (widget), row); + gtk_size_group_add_widget (self->row_sizegroup, row); + + /* Connect radio button to group */ + button = cc_power_profile_row_get_radio_button (CC_POWER_PROFILE_ROW (row)); + gtk_radio_button_join_group (button, last_button); + last_button = button; + } + + self->power_profiles_in_update = TRUE; + performance_profile_set_active (self, active_profile); + self->power_profiles_in_update = FALSE; + + self->power_profiles_prop_id = g_signal_connect_object (G_OBJECT (self->power_profiles_proxy), "g-properties-changed", + G_CALLBACK (power_profiles_properties_changed_cb), self, G_CONNECT_SWAPPED); +} + +static void add_battery_percentage (CcPowerPanel *self, GtkListBox *listbox) { @@ -1913,6 +2228,7 @@ cc_power_panel_init (CcPowerPanel *self) add_battery_section (self); add_device_section (self); + add_power_profiles_section (self); add_power_saving_section (self); add_general_section (self); diff --git a/panels/power/cc-power-profile-row.c b/panels/power/cc-power-profile-row.c new file mode 100644 index 000000000..c6934f27a --- /dev/null +++ b/panels/power/cc-power-profile-row.c @@ -0,0 +1,403 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* cc-list-row.c + * + * Copyright 2020 Red Hat 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 3 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 <http://www.gnu.org/licenses/>. + * + * Author(s): + * Bastien Nocera <hadess@hadess.net> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "cc-power-profile-row" + +#include <config.h> + +#include <glib/gi18n.h> +#include "cc-power-profile-row.h" + +struct _CcPowerProfileRow +{ + GtkListBoxRow parent_instance; + + CcPowerProfile power_profile; + char *performance_inhibited; + GtkRadioButton *button; + GtkWidget *subtext; +}; + +G_DEFINE_TYPE (CcPowerProfileRow, cc_power_profile_row, GTK_TYPE_LIST_BOX_ROW) + +enum { + PROP_0, + PROP_POWER_PROFILE, + PROP_PERFORMANCE_INHIBITED, + N_PROPS +}; + +enum { + BUTTON_TOGGLED, + N_SIGNALS +}; + +static GParamSpec *properties[N_PROPS]; +static guint signals[N_SIGNALS]; + +static const char * +get_performance_inhibited_text (const char *inhibited) +{ + if (!inhibited || *inhibited == '\0') + return NULL; + + if (g_str_equal (inhibited, "lap-detected")) + return _("Lap detected: performance mode unavailable"); + if (g_str_equal (inhibited, "high-operating-temperature")) + return _("High hardware temperature: performance mode unavailable"); + return _("Performance mode unavailable"); +} + +static void +performance_profile_set_inhibited (CcPowerProfileRow *row, + const char *performance_inhibited) +{ + const char *text; + gboolean inhibited = FALSE; + + if (row->power_profile != CC_POWER_PROFILE_PERFORMANCE) + return; + + gtk_style_context_remove_class (gtk_widget_get_style_context (row->subtext), + GTK_STYLE_CLASS_DIM_LABEL); + gtk_style_context_remove_class (gtk_widget_get_style_context (row->subtext), + GTK_STYLE_CLASS_ERROR); + + text = get_performance_inhibited_text (performance_inhibited); + if (text) + inhibited = TRUE; + else + text = _("High performance and power usage."); + gtk_label_set_text (GTK_LABEL (row->subtext), text); + + gtk_style_context_add_class (gtk_widget_get_style_context (row->subtext), + inhibited ? GTK_STYLE_CLASS_ERROR : GTK_STYLE_CLASS_DIM_LABEL); + gtk_widget_set_sensitive (GTK_WIDGET (row), !inhibited); +} + +static void +cc_power_profile_row_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + CcPowerProfileRow *self = (CcPowerProfileRow *)object; + + switch (prop_id) + { + case PROP_POWER_PROFILE: + g_value_set_int (value, self->power_profile); + break; + + case PROP_PERFORMANCE_INHIBITED: + g_value_set_string (value, self->performance_inhibited); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +cc_power_profile_row_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + CcPowerProfileRow *row = (CcPowerProfileRow *)object; + + switch (prop_id) + { + case PROP_POWER_PROFILE: + g_assert (row->power_profile == -1); + row->power_profile = g_value_get_int (value); + g_assert (row->power_profile != -1); + break; + + case PROP_PERFORMANCE_INHIBITED: + cc_power_profile_row_set_performance_inhibited (row, g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static GtkWidget * +performance_row_new (const gchar *title, + const gchar *icon_name, + const gchar *class_name, + const gchar *subtitle) +{ + PangoAttrList *attributes; + GtkWidget *grid, *button, *label, *image; + GtkStyleContext *context; + + grid = gtk_grid_new (); + g_object_set (G_OBJECT (grid), + "margin-top", 6, + "margin-bottom", 6, + NULL); + gtk_widget_show (grid); + + button = gtk_radio_button_new (NULL); + g_object_set (G_OBJECT (button), + "margin-end", 18, + "margin-start", 6, + NULL); + gtk_widget_show (button); + g_object_set_data (G_OBJECT (grid), "button", button); + gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 2); + + image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); + gtk_widget_set_margin_end (image, 6); + gtk_widget_show (image); + gtk_grid_attach (GTK_GRID (grid), image, 1, 0, 1, 1); + + context = gtk_widget_get_style_context (image); + gtk_style_context_add_class (context, "power-profile"); + if (class_name != NULL) + gtk_style_context_add_class (context, class_name); + + label = gtk_label_new (title); + g_object_set (G_OBJECT (label), + "ellipsize", PANGO_ELLIPSIZE_END, + "halign", GTK_ALIGN_START, + "expand", TRUE, + "use-markup", TRUE, + "use-underline", TRUE, + "visible", TRUE, + "xalign", 0.0, + NULL); + gtk_widget_show (label); + gtk_grid_attach (GTK_GRID (grid), label, 2, 0, 1, 1); + + attributes = pango_attr_list_new (); + pango_attr_list_insert (attributes, pango_attr_scale_new (0.9)); + + label = gtk_label_new (subtitle); + g_object_set (G_OBJECT (label), + "ellipsize", PANGO_ELLIPSIZE_END, + "halign", GTK_ALIGN_START, + "expand", TRUE, + "use-markup", TRUE, + "use-underline", TRUE, + "visible", TRUE, + "xalign", 0.0, + "attributes", attributes, + NULL); + gtk_style_context_add_class (gtk_widget_get_style_context (label), + GTK_STYLE_CLASS_DIM_LABEL); + g_object_set_data (G_OBJECT (grid), "subtext", label); + gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 2, 1); + + pango_attr_list_unref (attributes); + + return grid; +} + +static void +cc_power_profile_row_button_toggled_cb (GObject *row) +{ + g_signal_emit (row, signals[BUTTON_TOGGLED], 0); +} + +static void +cc_power_profile_row_constructed (GObject *object) +{ + CcPowerProfileRow *row; + GtkWidget *box, *title; + const char *text, *subtext, *icon_name, *class_name; + + row = CC_POWER_PROFILE_ROW (object); + + switch (row->power_profile) + { + case CC_POWER_PROFILE_PERFORMANCE: + text = _("Performance"); + subtext = _("High performance and power usage."); + icon_name = "power-profile-performance-symbolic"; + class_name = "performance"; + break; + case CC_POWER_PROFILE_BALANCED: + text = _("Balanced Power"); + subtext = _("Standard performance and power usage."); + icon_name = "power-profile-balanced-symbolic"; + class_name = NULL; + break; + case CC_POWER_PROFILE_POWER_SAVER: + text = _("Power Saver"); + subtext = _("Reduced performance and power usage."); + icon_name = "power-profile-power-saver-symbolic"; + class_name = "low-power"; + break; + default: + g_assert_not_reached (); + } + + gtk_list_box_row_set_selectable (GTK_LIST_BOX_ROW (row), FALSE); + gtk_widget_show (GTK_WIDGET (row)); + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + g_object_set (G_OBJECT (box), + "margin-end", 12, + "margin-start", 12, + "visible", TRUE, + NULL); + gtk_container_add (GTK_CONTAINER (row), box); + + title = performance_row_new (text, icon_name, class_name, subtext); + row->subtext = g_object_get_data (G_OBJECT (title), "subtext"); + row->button = g_object_get_data (G_OBJECT (title), "button"); + g_signal_connect_object (G_OBJECT (row->button), "toggled", + G_CALLBACK (cc_power_profile_row_button_toggled_cb), + row, G_CONNECT_SWAPPED); + if (row->power_profile == CC_POWER_PROFILE_PERFORMANCE) + performance_profile_set_inhibited (row, row->performance_inhibited); + gtk_box_pack_start (GTK_BOX (box), title, TRUE, TRUE, 0); +} + +static void +cc_power_profile_row_class_init (CcPowerProfileRowClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = cc_power_profile_row_get_property; + object_class->set_property = cc_power_profile_row_set_property; + object_class->constructed = cc_power_profile_row_constructed; + + properties[PROP_POWER_PROFILE] = + g_param_spec_int ("power-profile", + "Power Profile", + "Power profile for the row", + -1, CC_POWER_PROFILE_POWER_SAVER, + -1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); + + properties[PROP_PERFORMANCE_INHIBITED] = + g_param_spec_string ("performance-inhibited", + "Performance Inhibited", + "Performance inhibition reason", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + signals[BUTTON_TOGGLED] = + g_signal_new ("button-toggled", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + NULL, + G_TYPE_NONE, 0); + + g_object_class_install_properties (object_class, N_PROPS, properties); +} + +static void +cc_power_profile_row_init (CcPowerProfileRow *row) +{ + row->power_profile = -1; +} + +CcPowerProfile +cc_power_profile_row_get_profile (CcPowerProfileRow *row) +{ + g_return_val_if_fail (CC_IS_POWER_PROFILE_ROW (row), -1); + + return row->power_profile; +} + +GtkRadioButton * +cc_power_profile_row_get_radio_button (CcPowerProfileRow *row) +{ + g_return_val_if_fail (CC_IS_POWER_PROFILE_ROW (row), NULL); + + return row->button; +} + +void +cc_power_profile_row_set_active (CcPowerProfileRow *row, + gboolean active) +{ + g_return_if_fail (CC_IS_POWER_PROFILE_ROW (row)); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (row->button), active); +} + +void +cc_power_profile_row_set_performance_inhibited (CcPowerProfileRow *row, + const char *performance_inhibited) +{ + g_return_if_fail (CC_IS_POWER_PROFILE_ROW (row)); + + g_clear_pointer (&row->performance_inhibited, g_free); + row->performance_inhibited = g_strdup (performance_inhibited); + performance_profile_set_inhibited (row, row->performance_inhibited); +} + +gboolean +cc_power_profile_row_get_active (CcPowerProfileRow *self) +{ + g_return_val_if_fail (CC_IS_POWER_PROFILE_ROW (self), FALSE); + + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->button)); +} + +GtkWidget * +cc_power_profile_row_new (CcPowerProfile power_profile, + const char *performance_inhibited) +{ + return g_object_new (CC_TYPE_POWER_PROFILE_ROW, + "power-profile", power_profile, + "performance-inhibited", performance_inhibited, + NULL); +} + +CcPowerProfile +cc_power_profile_from_str (const char *profile) +{ + if (g_strcmp0 (profile, "power-saver") == 0) + return CC_POWER_PROFILE_POWER_SAVER; + if (g_strcmp0 (profile, "balanced") == 0) + return CC_POWER_PROFILE_BALANCED; + if (g_strcmp0 (profile, "performance") == 0) + return CC_POWER_PROFILE_PERFORMANCE; + + g_assert_not_reached (); +} + +const char * +cc_power_profile_to_str (CcPowerProfile profile) +{ + switch (profile) + { + case CC_POWER_PROFILE_POWER_SAVER: + return "power-saver"; + case CC_POWER_PROFILE_BALANCED: + return "balanced"; + case CC_POWER_PROFILE_PERFORMANCE: + return "performance"; + default: + g_assert_not_reached (); + } +} diff --git a/panels/power/cc-power-profile-row.h b/panels/power/cc-power-profile-row.h new file mode 100644 index 000000000..72b3df93f --- /dev/null +++ b/panels/power/cc-power-profile-row.h @@ -0,0 +1,54 @@ +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* cc-list-row.h + * + * Copyright 2020 Red Hat 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 3 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 <http://www.gnu.org/licenses/>. + * + * Author(s): + * Bastien Nocera <hadess@hadess.net> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include <gtk/gtk.h> + +G_BEGIN_DECLS + +typedef enum +{ + CC_POWER_PROFILE_PERFORMANCE = 0, + CC_POWER_PROFILE_BALANCED = 1, + CC_POWER_PROFILE_POWER_SAVER = 2, + NUM_CC_POWER_PROFILES +} CcPowerProfile; + +#define CC_TYPE_POWER_PROFILE_ROW (cc_power_profile_row_get_type()) +G_DECLARE_FINAL_TYPE (CcPowerProfileRow, cc_power_profile_row, CC, POWER_PROFILE_ROW, GtkListBoxRow) + +GtkWidget *cc_power_profile_row_new (CcPowerProfile power_profile, + const char *performance_inhibited); +CcPowerProfile cc_power_profile_row_get_profile (CcPowerProfileRow *row); +GtkRadioButton *cc_power_profile_row_get_radio_button (CcPowerProfileRow *row); +void cc_power_profile_row_set_active (CcPowerProfileRow *row, gboolean active); +gboolean cc_power_profile_row_get_active (CcPowerProfileRow *self); +void cc_power_profile_row_set_performance_inhibited (CcPowerProfileRow *row, + const char *performance_inhibited); + +CcPowerProfile cc_power_profile_from_str (const char *profile); +const char *cc_power_profile_to_str (CcPowerProfile profile); + +G_END_DECLS diff --git a/panels/power/meson.build b/panels/power/meson.build index 45ff95d3d..625059dd2 100644 --- a/panels/power/meson.build +++ b/panels/power/meson.build @@ -20,7 +20,8 @@ i18n.merge_file( sources = files( 'cc-battery-row.c', 'cc-brightness-scale.c', - 'cc-power-panel.c' + 'cc-power-panel.c', + 'cc-power-profile-row.c', ) sources += gnome.mkenums_simple( diff --git a/panels/power/power-profiles.css b/panels/power/power-profiles.css new file mode 100644 index 000000000..1c3149320 --- /dev/null +++ b/panels/power/power-profiles.css @@ -0,0 +1,7 @@ +.power-profile.low-power { + color: @success_color; +} + +.power-profile.performance { + color: @error_color; +} diff --git a/panels/power/power.gresource.xml b/panels/power/power.gresource.xml index 3b0fed18c..23cb3f8d7 100644 --- a/panels/power/power.gresource.xml +++ b/panels/power/power.gresource.xml @@ -4,5 +4,6 @@ <file preprocess="xml-stripblanks">cc-battery-row.ui</file> <file preprocess="xml-stripblanks">cc-power-panel.ui</file> <file>battery-levels.css</file> + <file>power-profiles.css</file> </gresource> </gresources> |