-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
power: System76 Charge Threshold profiles
- Loading branch information
Showing
10 changed files
with
677 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 == 48 && end == 60) | ||
return CHARGE_PROFILE_MAX_LIFESPAN; | ||
else if (start == 68 && end == 80) | ||
return CHARGE_PROFILE_BALANCED; | ||
else if (start == 88 && 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 = 48; | ||
*end = 60; | ||
break; | ||
case CHARGE_PROFILE_BALANCED: | ||
*start = 68; | ||
*end = 80; | ||
break; | ||
case CHARGE_PROFILE_FULL_CHARGE: | ||
default: | ||
*start = 88; | ||
*end = 100; | ||
break; | ||
} | ||
} | ||
|
||
const char *charge_profile_get_title (ChargeProfile profile) { | ||
switch (profile) { | ||
case CHARGE_PROFILE_MAX_LIFESPAN: | ||
return "Max lifespan"; | ||
case CHARGE_PROFILE_BALANCED: | ||
return "Balanced"; | ||
case CHARGE_PROFILE_FULL_CHARGE: | ||
return "Full Charge"; | ||
default: | ||
return "Undefined"; | ||
} | ||
} | ||
|
||
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <http://www.gnu.org/licenses/>. | ||
* | ||
* SPDX-License-Identifier: GPL-2.0-or-later | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <gtk/gtk.h> | ||
#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); | ||
const char *charge_profile_get_title (ChargeProfile profile); | ||
|
||
G_END_DECLS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<interface> | ||
<!-- interface-requires gtk+ 3.0 --> | ||
<template class="CcChargeThresholdDialog" parent="GtkDialog"> | ||
<property name="modal">True</property> | ||
<child internal-child="vbox"> | ||
<object class="GtkBox"> | ||
<property name="visible">True</property> | ||
<property name="margin">15</property> | ||
<property name="spacing">15</property> | ||
<child> | ||
<object class="GtkLabel"> | ||
<property name="visible">True</property> | ||
<property name="halign">start</property> | ||
<property name="wrap">True</property> | ||
<property name="width-chars">70</property> | ||
<property name="max-width-chars">70</property> | ||
<property name="label">Increase the lifespan of your battery by setting a maximum charge value below 100%. Recommended for users who prefer to keep their chargers plugged into their system.</property> | ||
</object> | ||
</child> | ||
<child> | ||
<object class="GtkFrame"> | ||
<property name="visible">True</property> | ||
<child> | ||
<object class="GtkListBox" id="listbox"> | ||
<property name="visible">True</property> | ||
<property name="selection-mode">GTK_SELECTION_BROWSE</property> | ||
<signal name="row-activated" handler="row_activated_cb" object="CcChargeThresholdDialog" swapped="yes" /> | ||
<child> | ||
<object class="CcChargeThresholdRow" id="full_charge_row"> | ||
<property name="visible">True</property> | ||
<property name="title">Full Charge</property> | ||
<property name="description">Battery is charged to its full capacity for longer use on battery power. Charging resumes when the battery falls below 88% charge.</property> | ||
<child internal-child="radio"> | ||
<object class="GtkRadioButton" id="full_charge_radio"> | ||
<property name="group">max_lifespan_radio</property> | ||
<signal name="toggled" handler="radio_toggled_cb" object="CcChargeThresholdDialog" swapped="yes" /> | ||
</object> | ||
</child> | ||
</object> | ||
</child> | ||
<child> | ||
<object class="CcChargeThresholdRow" id="balanced_row"> | ||
<property name="visible">True</property> | ||
<property name="title">Balanced</property> | ||
<property name="description">Use this threshold when charger can be unplugged at any time. Charging stops when battery reaches 80% charge, and resumes when battery falls below 68%.</property> | ||
<child internal-child="radio"> | ||
<object class="GtkRadioButton" id="balanced_radio"> | ||
<property name="group">max_lifespan_radio</property> | ||
<signal name="toggled" handler="radio_toggled_cb" object="CcChargeThresholdDialog" swapped="yes" /> | ||
</object> | ||
</child> | ||
</object> | ||
</child> | ||
<child> | ||
<object class="CcChargeThresholdRow" id="max_lifespan_row"> | ||
<property name="visible">True</property> | ||
<property name="title">Maximum Lifespan</property> | ||
<property name="description">Use this threshold if you keep your charger plugged in at all times. Charging stops when battery reaches 60% charge, and resumes when battery falls below 48%.</property> | ||
<child internal-child="radio"> | ||
<object class="GtkRadioButton" id="max_lifespan_radio"> | ||
<property name="group">max_lifespan_radio</property> | ||
<signal name="toggled" handler="radio_toggled_cb" object="CcChargeThresholdDialog" swapped="yes" /> | ||
</object> | ||
</child> | ||
</object> | ||
</child> | ||
</object> | ||
</child> | ||
</object> | ||
</child> | ||
<child> | ||
<!-- Hack to show no radio button selected when profile is undefined --> | ||
<object class="GtkRadioButton" id="hidden_radio"> | ||
<property name="visible">False</property> | ||
<property name="group">max_lifespan_radio</property> | ||
<signal name="toggled" handler="radio_toggled_cb" object="CcChargeThresholdDialog" swapped="yes" /> | ||
</object> | ||
</child> | ||
</object> | ||
</child> | ||
<child internal-child="headerbar"> | ||
<object class="GtkHeaderBar"> | ||
<property name="title">Battery Charge Thresholds</property> | ||
<property name="can_focus">False</property> | ||
<property name="show_close_button">True</property> | ||
</object> | ||
</child> | ||
</template> | ||
</interface> |
Oops, something went wrong.