1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
* Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
5
* Licensed under the GNU General Public License Version 2
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
#include <glib/gi18n.h>
25
#include <devkit-power-gobject/devicekit-power.h>
27
#include "egg-debug.h"
28
#include "egg-precision.h"
30
#include "gpm-upower.h"
31
#include "gpm-common.h"
33
#define GPM_DKP_TIME_PRECISION 5*60
34
#define GPM_DKP_TEXT_MIN_TIME 120
37
* gpm_upower_get_device_icon_index:
38
* @percent: The charge of the device
40
* The index value depends on the percentage charge:
48
* Return value: The character string for the filename suffix.
51
gpm_upower_get_device_icon_index (DkpDevice *device)
54
/* get device properties */
55
g_object_get (device, "percentage", &percentage, NULL);
58
else if (percentage < 30)
60
else if (percentage < 50)
62
else if (percentage < 70)
64
else if (percentage < 90)
70
* gpm_upower_get_device_icon:
72
* Need to free the return value
76
gpm_upower_get_device_icon (DkpDevice *device)
78
gchar *filename = NULL;
79
const gchar *prefix = NULL;
80
const gchar *index_str;
86
g_return_val_if_fail (device != NULL, NULL);
88
/* get device properties */
92
"percentage", &percentage,
93
"is-present", &is_present,
96
/* get correct icon prefix */
97
prefix = dkp_device_type_to_text (type);
99
/* get the icon from some simple rules */
100
if (type == DKP_DEVICE_TYPE_LINE_POWER) {
101
filename = g_strdup ("gpm-ac-adapter");
102
} else if (type == DKP_DEVICE_TYPE_MONITOR) {
103
filename = g_strdup ("gpm-monitor");
104
} else if (type == DKP_DEVICE_TYPE_UPS) {
106
/* battery missing */
107
filename = g_strdup_printf ("gpm-%s-missing", prefix);
109
} else if (state == DKP_DEVICE_STATE_FULLY_CHARGED) {
110
filename = g_strdup_printf ("gpm-%s-100", prefix);
112
} else if (state == DKP_DEVICE_STATE_CHARGING) {
113
index_str = gpm_upower_get_device_icon_index (device);
114
filename = g_strdup_printf ("gpm-%s-%s-charging", prefix, index_str);
116
} else if (state == DKP_DEVICE_STATE_DISCHARGING) {
117
index_str = gpm_upower_get_device_icon_index (device);
118
filename = g_strdup_printf ("gpm-%s-%s", prefix, index_str);
120
} else if (type == DKP_DEVICE_TYPE_BATTERY) {
122
/* battery missing */
123
filename = g_strdup_printf ("gpm-%s-missing", prefix);
125
} else if (state == DKP_DEVICE_STATE_EMPTY) {
126
filename = g_strdup_printf ("gpm-%s-empty", prefix);
128
} else if (state == DKP_DEVICE_STATE_FULLY_CHARGED) {
129
filename = g_strdup_printf ("gpm-%s-charged", prefix);
131
#if !DKP_CHECK_VERSION(0x009)
132
} else if (state == DKP_DEVICE_STATE_UNKNOWN && percentage > 95.0f) {
133
egg_warning ("fixing up unknown %f", percentage);
134
filename = g_strdup_printf ("gpm-%s-charged", prefix);
137
} else if (state == DKP_DEVICE_STATE_CHARGING) {
138
index_str = gpm_upower_get_device_icon_index (device);
139
filename = g_strdup_printf ("gpm-%s-%s-charging", prefix, index_str);
141
} else if (state == DKP_DEVICE_STATE_DISCHARGING) {
142
index_str = gpm_upower_get_device_icon_index (device);
143
filename = g_strdup_printf ("gpm-%s-%s", prefix, index_str);
145
#if !DKP_CHECK_VERSION(0x009)
146
/* the battery isn't charging or discharging, it's just
147
* sitting there half full doing nothing */
152
/* get battery status */
153
client = dkp_client_new ();
154
g_object_get (client,
155
"on-battery", &on_battery,
157
g_object_unref (client);
159
/* try to find a suitable icon depending on AC state */
161
index_str = gpm_upower_get_device_icon_index (device);
162
filename = g_strdup_printf ("gpm-%s-%s", prefix, index_str);
164
index_str = gpm_upower_get_device_icon_index (device);
165
filename = g_strdup_printf ("gpm-%s-%s-charging", prefix, index_str);
168
} else if (state == DKP_DEVICE_STATE_PENDING_CHARGE) {
169
index_str = gpm_upower_get_device_icon_index (device);
170
/* FIXME: do new grey icons */
171
filename = g_strdup_printf ("gpm-%s-%s-charging", prefix, index_str);
173
} else if (state == DKP_DEVICE_STATE_PENDING_DISCHARGE) {
174
index_str = gpm_upower_get_device_icon_index (device);
175
filename = g_strdup_printf ("gpm-%s-%s", prefix, index_str);
177
filename = g_strdup ("gpm-battery-missing");
181
} else if (type == DKP_DEVICE_TYPE_MOUSE ||
182
type == DKP_DEVICE_TYPE_KEYBOARD ||
183
type == DKP_DEVICE_TYPE_PHONE) {
185
/* battery missing */
186
filename = g_strdup_printf ("gpm-%s-000", prefix);
188
} else if (state == DKP_DEVICE_STATE_FULLY_CHARGED) {
189
filename = g_strdup_printf ("gpm-%s-100", prefix);
191
} else if (state == DKP_DEVICE_STATE_DISCHARGING) {
192
index_str = gpm_upower_get_device_icon_index (device);
193
filename = g_strdup_printf ("gpm-%s-%s", prefix, index_str);
197
/* nothing matched */
198
if (filename == NULL) {
199
egg_warning ("nothing matched, falling back to default icon");
200
filename = g_strdup ("dialog-warning");
203
egg_debug ("got filename: %s", filename);
208
* gpm_upower_get_device_summary:
211
gpm_upower_get_device_summary (DkpDevice *device)
213
const gchar *type_desc = NULL;
214
gchar *description = NULL;
215
guint time_to_full_round;
216
guint time_to_empty_round;
217
gchar *time_to_full_str;
218
gchar *time_to_empty_str;
220
DkpDeviceState state;
224
gint64 time_to_empty;
226
/* get device properties */
227
g_object_get (device,
230
"percentage", &percentage,
231
"is-present", &is_present,
232
"time-to-full", &time_to_full,
233
"time-to-empty", &time_to_empty,
239
type_desc = gpm_device_type_to_localised_text (type, 1);
241
/* don't display all the extra stuff for keyboards and mice */
242
if (type == DKP_DEVICE_TYPE_MOUSE ||
243
type == DKP_DEVICE_TYPE_KEYBOARD ||
244
type == DKP_DEVICE_TYPE_PDA)
245
return g_strdup_printf ("%s (%.1f%%)", type_desc, percentage);
247
/* we care if we are on AC */
248
if (type == DKP_DEVICE_TYPE_PHONE) {
249
if (state == DKP_DEVICE_STATE_CHARGING || !state == DKP_DEVICE_STATE_DISCHARGING) {
250
/* TRANSLATORS: a phone is charging */
251
return g_strdup_printf (_("%s charging (%.1f%%)"), type_desc, percentage);
253
return g_strdup_printf ("%s (%.1f%%)", type_desc, percentage);
256
/* precalculate so we don't get Unknown time remaining */
257
time_to_full_round = egg_precision_round_down (time_to_full, GPM_DKP_TIME_PRECISION);
258
time_to_empty_round = egg_precision_round_down (time_to_empty, GPM_DKP_TIME_PRECISION);
260
/* we always display "Laptop battery 16 minutes remaining" as we need to clarify what device we are refering to */
261
if (state == DKP_DEVICE_STATE_FULLY_CHARGED) {
263
if (type == DKP_DEVICE_TYPE_BATTERY && time_to_empty_round > GPM_DKP_TEXT_MIN_TIME) {
264
time_to_empty_str = gpm_get_timestring (time_to_empty_round);
265
/* TRANSLATORS: The laptop battery is fully charged, and we know a time */
266
description = g_strdup_printf (_("Battery is fully charged.\nProvides %s laptop runtime"),
268
g_free (time_to_empty_str);
270
/* TRANSLATORS: the device is fully charged */
271
description = g_strdup_printf (_("%s is fully charged"), type_desc);
274
} else if (state == DKP_DEVICE_STATE_DISCHARGING) {
276
if (time_to_empty_round > GPM_DKP_TEXT_MIN_TIME) {
277
time_to_empty_str = gpm_get_timestring (time_to_empty_round);
278
/* TRANSLATORS: the device is discharging, and we have a time remaining */
279
description = g_strdup_printf (_("%s %s remaining (%.1f%%)"),
280
type_desc, time_to_empty_str, percentage);
281
g_free (time_to_empty_str);
283
/* TRANSLATORS: the device is discharging, but we only have a percentage */
284
description = g_strdup_printf (_("%s discharging (%.1f%%)"),
285
type_desc, percentage);
288
} else if (state == DKP_DEVICE_STATE_CHARGING) {
290
if (time_to_full_round > GPM_DKP_TEXT_MIN_TIME &&
291
time_to_empty_round > GPM_DKP_TEXT_MIN_TIME) {
293
/* display both discharge and charge time */
294
time_to_full_str = gpm_get_timestring (time_to_full_round);
295
time_to_empty_str = gpm_get_timestring (time_to_empty_round);
297
/* TRANSLATORS: the device is charging, and we have a time to full and empty */
298
description = g_strdup_printf (_("%s %s until charged (%.1f%%)\nProvides %s battery runtime"),
299
type_desc, time_to_full_str, percentage, time_to_empty_str);
300
g_free (time_to_full_str);
301
g_free (time_to_empty_str);
303
} else if (time_to_full_round > GPM_DKP_TEXT_MIN_TIME) {
305
/* display only charge time */
306
time_to_full_str = gpm_get_timestring (time_to_full_round);
308
/* TRANSLATORS: device is charging, and we have a time to full and a percentage */
309
description = g_strdup_printf (_("%s %s until charged (%.1f%%)"),
310
type_desc, time_to_full_str, percentage);
311
g_free (time_to_full_str);
314
/* TRANSLATORS: device is charging, but we only have a percentage */
315
description = g_strdup_printf (_("%s charging (%.1f%%)"),
316
type_desc, percentage);
319
#if DKP_CHECK_VERSION(0x009)
320
} else if (state == DKP_DEVICE_STATE_PENDING_DISCHARGE) {
322
/* TRANSLATORS: this is only shown for laptops with multiple batteries */
323
description = g_strdup_printf (_("%s waiting to discharge (%.1f%%)"),
324
type_desc, percentage);
326
} else if (state == DKP_DEVICE_STATE_PENDING_CHARGE) {
328
/* TRANSLATORS: this is only shown for laptops with multiple batteries */
329
description = g_strdup_printf (_("%s waiting to charge (%.1f%%)"), type_desc, percentage);
333
egg_warning ("in an undefined state we are not charging or "
334
"discharging and the batteries are also not charged");
335
description = g_strdup_printf ("%s (%.1f%%)", type_desc, percentage);
341
* gpm_upower_get_device_description:
344
gpm_upower_get_device_description (DkpDevice *device)
350
DkpDeviceState state;
351
DkpDeviceTechnology technology;
356
gdouble energy_full_design;
360
gint64 time_to_empty;
361
gchar *vendor = NULL;
362
gchar *serial = NULL;
365
g_return_val_if_fail (device != NULL, NULL);
367
/* get device properties */
368
g_object_get (device,
371
"percentage", &percentage,
372
"is-present", &is_present,
373
"time-to-full", &time_to_full,
374
"time-to-empty", &time_to_empty,
375
"technology", &technology,
376
"capacity", &capacity,
378
"energy-full", &energy_full,
379
"energy-full-design", &energy_full_design,
380
"energy-rate", &energy_rate,
386
details = g_string_new ("");
387
text = gpm_device_type_to_localised_text (type, 1);
388
/* TRANSLATORS: the type of data, e.g. Laptop battery */
389
g_string_append_printf (details, "<b>%s</b> %s\n", _("Product:"), text);
392
/* TRANSLATORS: device is missing */
393
g_string_append_printf (details, "<b>%s</b> %s\n", _("Status:"), _("Missing"));
394
} else if (state == DKP_DEVICE_STATE_FULLY_CHARGED) {
395
/* TRANSLATORS: device is charged */
396
g_string_append_printf (details, "<b>%s</b> %s\n", _("Status:"), _("Charged"));
397
} else if (state == DKP_DEVICE_STATE_CHARGING) {
398
/* TRANSLATORS: device is charging */
399
g_string_append_printf (details, "<b>%s</b> %s\n", _("Status:"), _("Charging"));
400
} else if (state == DKP_DEVICE_STATE_DISCHARGING) {
401
/* TRANSLATORS: device is discharging */
402
g_string_append_printf (details, "<b>%s</b> %s\n", _("Status:"), _("Discharging"));
405
if (percentage >= 0) {
406
/* TRANSLATORS: percentage */
407
g_string_append_printf (details, "<b>%s</b> %.1f%%\n", _("Percentage charge:"), percentage);
410
/* TRANSLATORS: manufacturer */
411
g_string_append_printf (details, "<b>%s</b> %s\n", _("Vendor:"), vendor);
413
if (technology != DKP_DEVICE_TECHNOLOGY_UNKNOWN) {
414
text = gpm_device_technology_to_localised_text (technology);
415
/* TRANSLATORS: how the battery is made, e.g. Lithium Ion */
416
g_string_append_printf (details, "<b>%s</b> %s\n", _("Technology:"), text);
419
/* TRANSLATORS: serial number of the battery */
420
g_string_append_printf (details, "<b>%s</b> %s\n", _("Serial number:"), serial);
423
/* TRANSLATORS: model number of the battery */
424
g_string_append_printf (details, "<b>%s</b> %s\n", _("Model:"), model);
426
if (time_to_full > 0) {
427
time_str = gpm_get_timestring (time_to_full);
428
/* TRANSLATORS: time to fully charged */
429
g_string_append_printf (details, "<b>%s</b> %s\n", _("Charge time:"), time_str);
432
if (time_to_empty > 0) {
433
time_str = gpm_get_timestring (time_to_empty);
434
/* TRANSLATORS: time to empty */
435
g_string_append_printf (details, "<b>%s</b> %s\n", _("Discharge time:"), time_str);
439
const gchar *condition;
441
/* TRANSLATORS: Excellent, Good, Fair and Poor are all related to battery Capacity */
442
condition = _("Excellent");
443
} else if (capacity > 90) {
444
condition = _("Good");
445
} else if (capacity > 70) {
446
condition = _("Fair");
448
condition = _("Poor");
450
/* TRANSLATORS: %.1f is a percentage and %s the condition (Excellent, Good, ...) */
451
g_string_append_printf (details, "<b>%s</b> %.1f%% (%s)\n",
452
_("Capacity:"), capacity, condition);
454
if (type == DKP_DEVICE_TYPE_BATTERY) {
456
/* TRANSLATORS: current charge */
457
g_string_append_printf (details, "<b>%s</b> %.1f Wh\n",
458
_("Current charge:"), energy);
460
if (energy_full > 0 &&
461
energy_full_design != energy_full) {
462
/* TRANSLATORS: last full is the charge the battery was seen to charge to */
463
g_string_append_printf (details, "<b>%s</b> %.1f Wh\n",
464
_("Last full charge:"), energy_full);
466
if (energy_full_design > 0) {
468
/* TRANSLATORS: Design charge is the amount of charge the battery is designed to have when brand new */
469
g_string_append_printf (details, "<b>%s</b> %.1f Wh\n",
470
_("Design charge:"), energy_full_design);
472
if (energy_rate > 0) {
473
/* TRANSLATORS: the charge or discharge rate */
474
g_string_append_printf (details, "<b>%s</b> %.1f W\n",
475
_("Charge rate:"), energy_rate);
478
if (type == DKP_DEVICE_TYPE_MOUSE ||
479
type == DKP_DEVICE_TYPE_KEYBOARD) {
481
/* TRANSLATORS: the current charge for CSR devices */
482
g_string_append_printf (details, "<b>%s</b> %.0f/7\n",
483
_("Current charge:"), energy);
485
if (energy_full_design > 0) {
486
/* TRANSLATORS: the design charge for CSR devices */
487
g_string_append_printf (details, "<b>%s</b> %.0f/7\n",
488
_("Design charge:"), energy_full_design);
491
/* remove the last \n */
492
g_string_truncate (details, details->len-1);
497
return g_string_free (details, FALSE);
501
* gpm_device_type_to_localised_text:
504
gpm_device_type_to_localised_text (DkpDeviceType type, guint number)
506
const gchar *text = NULL;
508
case DKP_DEVICE_TYPE_LINE_POWER:
509
/* TRANSLATORS: system power cord */
510
text = ngettext ("AC adapter", "AC adapters", number);
512
case DKP_DEVICE_TYPE_BATTERY:
513
/* TRANSLATORS: laptop primary battery */
514
text = ngettext ("Laptop battery", "Laptop batteries", number);
516
case DKP_DEVICE_TYPE_UPS:
517
/* TRANSLATORS: battery-backed AC power source */
518
text = ngettext ("UPS", "UPSs", number);
520
case DKP_DEVICE_TYPE_MONITOR:
521
/* TRANSLATORS: a monitor is a device to measure voltage and current */
522
text = ngettext ("Monitor", "Monitors", number);
524
case DKP_DEVICE_TYPE_MOUSE:
525
/* TRANSLATORS: wireless mice with internal batteries */
526
text = ngettext ("Wireless mouse", "Wireless mice", number);
528
case DKP_DEVICE_TYPE_KEYBOARD:
529
/* TRANSLATORS: wireless keyboard with internal battery */
530
text = ngettext ("Wireless keyboard", "Wireless keyboards", number);
532
case DKP_DEVICE_TYPE_PDA:
533
/* TRANSLATORS: portable device */
534
text = ngettext ("PDA", "PDAs", number);
536
case DKP_DEVICE_TYPE_PHONE:
537
/* TRANSLATORS: cell phone (mobile...) */
538
text = ngettext ("Cell phone", "Cell phones", number);
541
egg_warning ("enum unrecognised: %i", type);
542
text = dkp_device_type_to_text (type);
548
* gpm_device_type_to_icon:
551
gpm_device_type_to_icon (DkpDeviceType type)
553
const gchar *icon = NULL;
555
case DKP_DEVICE_TYPE_LINE_POWER:
556
icon = "gpm-ac-adapter";
558
case DKP_DEVICE_TYPE_BATTERY:
561
case DKP_DEVICE_TYPE_UPS:
562
icon = "network-wired";
564
case DKP_DEVICE_TYPE_MONITOR:
565
icon = "application-certificate";
567
case DKP_DEVICE_TYPE_MOUSE:
570
case DKP_DEVICE_TYPE_KEYBOARD:
571
icon = "input-keyboard";
573
case DKP_DEVICE_TYPE_PDA:
574
icon = "input-gaming";
576
case DKP_DEVICE_TYPE_PHONE:
577
icon = "camera-video";
580
egg_warning ("enum unrecognised: %i", type);
587
* gpm_device_technology_to_localised_text:
590
gpm_device_technology_to_localised_text (DkpDeviceTechnology technology_enum)
592
const gchar *technology = NULL;
593
switch (technology_enum) {
594
case DKP_DEVICE_TECHNOLOGY_LITHIUM_ION:
595
/* TRANSLATORS: battery technology */
596
technology = _("Lithium Ion");
598
case DKP_DEVICE_TECHNOLOGY_LITHIUM_POLYMER:
599
/* TRANSLATORS: battery technology */
600
technology = _("Lithium Polymer");
602
case DKP_DEVICE_TECHNOLOGY_LITHIUM_IRON_PHOSPHATE:
603
/* TRANSLATORS: battery technology */
604
technology = _("Lithium Iron Phosphate");
606
case DKP_DEVICE_TECHNOLOGY_LEAD_ACID:
607
/* TRANSLATORS: battery technology */
608
technology = _("Lead acid");
610
case DKP_DEVICE_TECHNOLOGY_NICKEL_CADMIUM:
611
/* TRANSLATORS: battery technology */
612
technology = _("Nickel Cadmium");
614
case DKP_DEVICE_TECHNOLOGY_NICKEL_METAL_HYDRIDE:
615
/* TRANSLATORS: battery technology */
616
technology = _("Nickel metal hydride");
618
case DKP_DEVICE_TECHNOLOGY_UNKNOWN:
619
/* TRANSLATORS: battery technology */
620
technology = _("Unknown technology");
623
g_assert_not_reached ();