GCC Code Coverage Report


Directory: ./
File: panels/power/cc-battery-row.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 134 0.0%
Functions: 0 11 0.0%
Branches: 0 61 0.0%

Line Branch Exec Source
1 /* cc-brightness-scale.c
2 *
3 * Copyright (C) 2010 Red Hat, Inc
4 * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
5 * Copyright (C) 2010,2015 Richard Hughes <richard@hughsie.com>
6 * Copyright (C) 2020 System76, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 *
21 * SPDX-License-Identifier: GPL-2.0-or-later
22 */
23
24 #include <glib/gi18n.h>
25
26 #include "cc-battery-row.h"
27
28 struct _CcBatteryRow {
29 GtkListBoxRow parent_instance;
30
31 GtkBox *battery_box;
32 GtkLabel *details_label;
33 GtkImage *icon;
34 GtkLevelBar *levelbar;
35 GtkLabel *name_label;
36 GtkLabel *percentage_label;
37 GtkBox *primary_bottom_box;
38 GtkLabel *primary_percentage_label;
39
40 UpDeviceKind kind;
41 gboolean primary;
42 };
43
44 G_DEFINE_TYPE (CcBatteryRow, cc_battery_row, GTK_TYPE_LIST_BOX_ROW)
45
46 static void
47 cc_battery_row_class_init (CcBatteryRowClass *klass)
48 {
49 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
50
51 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/power/cc-battery-row.ui");
52
53 gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, battery_box);
54 gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, details_label);
55 gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, icon);
56 gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, levelbar);
57 gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, name_label);
58 gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, percentage_label);
59 gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, primary_bottom_box);
60 gtk_widget_class_bind_template_child (widget_class, CcBatteryRow, primary_percentage_label);
61 }
62
63 static void
64 cc_battery_row_init (CcBatteryRow *self)
65 {
66 gtk_widget_init_template (GTK_WIDGET (self));
67 }
68
69 static gchar *
70 get_timestring (guint64 time_secs)
71 {
72 gchar* timestring = NULL;
73 gint hours;
74 gint minutes;
75
76 /* Add 0.5 to do rounding */
77 minutes = (int) ( ( time_secs / 60.0 ) + 0.5 );
78
79 if (minutes == 0)
80 return g_strdup (_("Unknown time"));
81
82 if (minutes < 60)
83 return timestring = g_strdup_printf (ngettext ("%i minute",
84 "%i minutes",
85 minutes), minutes);
86
87 hours = minutes / 60;
88 minutes = minutes % 60;
89
90 if (minutes == 0)
91 return timestring = g_strdup_printf (ngettext (
92 "%i hour",
93 "%i hours",
94 hours), hours);
95
96 /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
97 * Swap order with "%2$s %2$i %1$s %1$i if needed */
98 return timestring = g_strdup_printf (_("%i %s %i %s"),
99 hours, ngettext ("hour", "hours", hours),
100 minutes, ngettext ("minute", "minutes", minutes));
101 }
102
103 static gchar *
104 get_details_string (gdouble percentage, UpDeviceState state, guint64 time)
105 {
106 g_autofree gchar *details = NULL;
107
108 if (time > 0)
109 {
110 g_autofree gchar *time_string = NULL;
111
112 time_string = get_timestring (time);
113 switch (state)
114 {
115 case UP_DEVICE_STATE_CHARGING:
116 /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
117 details = g_strdup_printf (_("%s until fully charged"), time_string);
118 break;
119 case UP_DEVICE_STATE_DISCHARGING:
120 case UP_DEVICE_STATE_PENDING_DISCHARGE:
121 if (percentage < 20)
122 {
123 /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
124 details = g_strdup_printf (_("Caution: %s remaining"), time_string);
125 }
126 else
127 {
128 /* TRANSLATORS: %1 is a time string, e.g. "1 hour 5 minutes" */
129 details = g_strdup_printf (_("%s remaining"), time_string);
130 }
131 break;
132 case UP_DEVICE_STATE_FULLY_CHARGED:
133 /* TRANSLATORS: primary battery */
134 details = g_strdup (_("Fully charged"));
135 break;
136 case UP_DEVICE_STATE_PENDING_CHARGE:
137 /* TRANSLATORS: primary battery */
138 details = g_strdup (_("Not charging"));
139 break;
140 case UP_DEVICE_STATE_EMPTY:
141 /* TRANSLATORS: primary battery */
142 details = g_strdup (_("Empty"));
143 break;
144 default:
145 details = g_strdup_printf ("error: %s", up_device_state_to_string (state));
146 break;
147 }
148 }
149 else
150 {
151 switch (state)
152 {
153 case UP_DEVICE_STATE_CHARGING:
154 /* TRANSLATORS: primary battery */
155 details = g_strdup (_("Charging"));
156 break;
157 case UP_DEVICE_STATE_DISCHARGING:
158 case UP_DEVICE_STATE_PENDING_DISCHARGE:
159 /* TRANSLATORS: primary battery */
160 details = g_strdup (_("Discharging"));
161 break;
162 case UP_DEVICE_STATE_FULLY_CHARGED:
163 /* TRANSLATORS: primary battery */
164 details = g_strdup (_("Fully charged"));
165 break;
166 case UP_DEVICE_STATE_PENDING_CHARGE:
167 /* TRANSLATORS: primary battery */
168 details = g_strdup (_("Not charging"));
169 break;
170 case UP_DEVICE_STATE_EMPTY:
171 /* TRANSLATORS: primary battery */
172 details = g_strdup (_("Empty"));
173 break;
174 default:
175 details = g_strdup_printf ("error: %s",
176 up_device_state_to_string (state));
177 break;
178 }
179 }
180
181 return g_steal_pointer (&details);
182 }
183
184 static const char *
185 kind_to_description (UpDeviceKind kind)
186 {
187 switch (kind)
188 {
189 case UP_DEVICE_KIND_MOUSE:
190 /* TRANSLATORS: secondary battery */
191 return N_("Wireless mouse");
192 case UP_DEVICE_KIND_KEYBOARD:
193 /* TRANSLATORS: secondary battery */
194 return N_("Wireless keyboard");
195 case UP_DEVICE_KIND_UPS:
196 /* TRANSLATORS: secondary battery */
197 return N_("Uninterruptible power supply");
198 case UP_DEVICE_KIND_PDA:
199 /* TRANSLATORS: secondary battery */
200 return N_("Personal digital assistant");
201 case UP_DEVICE_KIND_PHONE:
202 /* TRANSLATORS: secondary battery */
203 return N_("Cellphone");
204 case UP_DEVICE_KIND_MEDIA_PLAYER:
205 /* TRANSLATORS: secondary battery */
206 return N_("Media player");
207 case UP_DEVICE_KIND_TABLET:
208 /* TRANSLATORS: secondary battery */
209 return N_("Tablet");
210 case UP_DEVICE_KIND_COMPUTER:
211 /* TRANSLATORS: secondary battery */
212 return N_("Computer");
213 case UP_DEVICE_KIND_GAMING_INPUT:
214 /* TRANSLATORS: secondary battery */
215 return N_("Gaming input device");
216 default:
217 /* TRANSLATORS: secondary battery, misc */
218 return N_("Battery");
219 }
220
221 g_assert_not_reached ();
222 }
223
224 CcBatteryRow*
225 cc_battery_row_new (UpDevice *device,
226 gboolean primary)
227 {
228 g_autofree gchar *details = NULL;
229 gdouble percentage;
230 UpDeviceKind kind;
231 UpDeviceState state;
232 g_autofree gchar *s = NULL;
233 g_autofree gchar *icon_name = NULL;
234 const gchar *name;
235 CcBatteryRow *self;
236 guint64 time_empty, time_full, time;
237 gdouble energy_full, energy_rate;
238 gboolean is_kind_battery;
239 UpDeviceLevel battery_level;
240
241 self = g_object_new (CC_TYPE_BATTERY_ROW, NULL);
242
243 g_object_get (device,
244 "kind", &kind,
245 "state", &state,
246 "model", &name,
247 "percentage", &percentage,
248 "icon-name", &icon_name,
249 "time-to-empty", &time_empty,
250 "time-to-full", &time_full,
251 "energy-full", &energy_full,
252 "energy-rate", &energy_rate,
253 "battery-level", &battery_level,
254 NULL);
255 if (state == UP_DEVICE_STATE_DISCHARGING)
256 time = time_empty;
257 else
258 time = time_full;
259
260 is_kind_battery = (kind == UP_DEVICE_KIND_BATTERY || kind == UP_DEVICE_KIND_UPS);
261
262 /* Name label */
263 if (is_kind_battery)
264 {
265 if (g_object_get_data (G_OBJECT (device), "is-main-battery") != NULL)
266 name = C_("Battery name", "Main");
267 else
268 name = C_("Battery name", "Extra");
269 }
270 else if (name == NULL || name[0] == '\0')
271 {
272 name = _(kind_to_description (kind));
273 }
274 gtk_label_set_text (self->name_label, name);
275
276 /* Icon */
277 if (is_kind_battery && icon_name != NULL && icon_name[0] != '\0')
278 {
279 gtk_image_set_from_icon_name (self->icon, icon_name);
280 gtk_widget_set_visible (GTK_WIDGET (self->icon), TRUE);
281 }
282 else
283 gtk_widget_set_visible (GTK_WIDGET (self->icon), FALSE);
284
285 /* Percentage label */
286 if (battery_level == UP_DEVICE_LEVEL_NONE)
287 {
288 /* 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 */
289 s = g_strdup_printf (_("%d %%"), (int)percentage);
290 gtk_label_set_text (self->percentage_label, s);
291 gtk_label_set_text (self->primary_percentage_label, s);
292 }
293
294 /* Level bar */
295 gtk_level_bar_set_value (self->levelbar, percentage / 100.0);
296
297 /* Details label (primary only) */
298 details = get_details_string (percentage, state, time);
299 gtk_label_set_text (self->details_label, details);
300
301 /* Handle "primary" row differently */
302 gtk_widget_set_visible (GTK_WIDGET (self->battery_box), !primary);
303 gtk_widget_set_visible (GTK_WIDGET (self->percentage_label), !primary);
304 gtk_widget_set_visible (GTK_WIDGET (self->primary_bottom_box), primary);
305 /*
306 gtk_accessible_update_relation (GTK_ACCESSIBLE (self->levelbar),
307 GTK_ACCESSIBLE_RELATION_LABELLED_BY, primary ? self->primary_percentage_label
308 : self->percentage_label,
309 NULL);
310 */
311
312 self->kind = kind;
313 self->primary = primary;
314
315 return self;
316 }
317
318
319
320 gboolean
321 cc_battery_row_get_primary (CcBatteryRow *self)
322 {
323 return self->primary;
324 }
325
326 UpDeviceKind
327 cc_battery_row_get_kind (CcBatteryRow *self)
328 {
329 return self->kind;
330 }
331