2020-09-22 11:19:43 -07:00
/* cc-brightness-scale.c
*
* Copyright ( C ) 2010 Red Hat , Inc
* Copyright ( C ) 2008 William Jon McCann < jmccann @ redhat . com >
* Copyright ( C ) 2010 , 2015 Richard Hughes < richard @ hughsie . com >
* 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
*/
# include <glib/gi18n.h>
# 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 ;
2020-10-12 10:44:31 -07:00
UpDeviceKind kind ;
gboolean primary ;
2020-09-22 11:19:43 -07:00
} ;
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 ) ;
}
2020-10-12 10:44:31 -07:00
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 ( ) ;
}
2020-09-22 11:19:43 -07:00
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 ;
2020-10-12 10:44:31 -07:00
gboolean is_kind_battery ;
UpDeviceLevel battery_level ;
2020-09-22 11:19:43 -07:00
self = g_object_new ( CC_TYPE_BATTERY_ROW , NULL ) ;
g_object_get ( device ,
" kind " , & kind ,
" state " , & state ,
2020-10-12 10:44:31 -07:00
" model " , & name ,
2020-09-22 11:19:43 -07:00
" percentage " , & percentage ,
" icon-name " , & icon_name ,
" time-to-empty " , & time_empty ,
" time-to-full " , & time_full ,
" energy-full " , & energy_full ,
" energy-rate " , & energy_rate ,
2020-10-12 10:44:31 -07:00
" battery-level " , & battery_level ,
2020-09-22 11:19:43 -07:00
NULL ) ;
if ( state = = UP_DEVICE_STATE_DISCHARGING )
time = time_empty ;
else
time = time_full ;
2020-10-12 10:44:31 -07:00
is_kind_battery = ( kind = = UP_DEVICE_KIND_BATTERY | | kind = = UP_DEVICE_KIND_UPS ) ;
2020-09-22 11:19:43 -07:00
/* Name label */
2020-10-12 10:44:31 -07:00
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 ) ) ;
}
2020-09-22 11:19:43 -07:00
gtk_label_set_text ( self - > name_label , name ) ;
/* Icon */
2020-10-12 10:44:31 -07:00
if ( is_kind_battery & & icon_name ! = NULL & & icon_name [ 0 ] ! = ' \0 ' )
2021-01-08 16:29:18 +01:00
{
2021-10-20 23:07:53 -03:00
gtk_image_set_from_icon_name ( self - > icon , icon_name ) ;
2022-12-30 17:27:39 +01:00
gtk_widget_set_visible ( GTK_WIDGET ( self - > icon ) , TRUE ) ;
2021-01-08 16:29:18 +01:00
}
else
2022-12-30 17:27:39 +01:00
gtk_widget_set_visible ( GTK_WIDGET ( self - > icon ) , FALSE ) ;
2020-09-22 11:19:43 -07:00
/* Percentage label */
2020-10-12 10:44:31 -07:00
if ( battery_level = = UP_DEVICE_LEVEL_NONE )
{
2023-09-07 14:38:52 +02:00
/* TRANSLATORS: This is the battery charge level percentage (e.g. 50%). This could be localized to account for local Percent sign formatting guidelines. See https://en.wikipedia.org/wiki/Percent_sign#Correct_style */
s = g_strdup_printf ( _ ( " %d %% " ) , ( int ) percentage ) ;
2020-10-12 10:44:31 -07:00
gtk_label_set_text ( self - > percentage_label , s ) ;
gtk_label_set_text ( self - > primary_percentage_label , s ) ;
}
2020-09-22 11:19:43 -07:00
/* 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 ) ;
2021-10-20 23:07:53 -03:00
/*
gtk_accessible_update_relation ( GTK_ACCESSIBLE ( self - > levelbar ) ,
GTK_ACCESSIBLE_RELATION_LABELLED_BY , primary ? self - > primary_percentage_label
: self - > percentage_label ,
NULL ) ;
*/
2020-09-22 11:19:43 -07:00
2020-10-12 10:44:31 -07:00
self - > kind = kind ;
self - > primary = primary ;
2020-09-22 11:19:43 -07:00
return self ;
}
2020-10-12 10:44:31 -07:00
gboolean
cc_battery_row_get_primary ( CcBatteryRow * self )
{
return self - > primary ;
}
UpDeviceKind
cc_battery_row_get_kind ( CcBatteryRow * self )
{
return self - > kind ;
2021-01-08 16:29:18 +01:00
}