3
A simple Device structure used internally by indicator-power
5
Copyright 2012 Canonical Ltd.
8
Charles Kerr <charles.kerr@canonical.com>
10
This library is free software; you can redistribute it and/or
11
modify it under the terms of the GNU General Public License
12
version 3.0 as published by the Free Software Foundation.
14
This library is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License version 3.0 for more details.
19
You should have received a copy of the GNU General Public
20
License along with this library. If not, see
21
<http://www.gnu.org/licenses/>.
28
#include <glib/gi18n.h>
32
struct _IndicatorPowerDevicePrivate
41
#define INDICATOR_POWER_DEVICE_GET_PRIVATE(o) (INDICATOR_POWER_DEVICE(o)->priv)
44
/* Enum for the properties so that they can be quickly found and looked up. */
55
static GParamSpec * properties[N_PROPERTIES];
58
static void indicator_power_device_class_init (IndicatorPowerDeviceClass *klass);
59
static void indicator_power_device_init (IndicatorPowerDevice *self);
60
static void indicator_power_device_dispose (GObject *object);
61
static void indicator_power_device_finalize (GObject *object);
62
static void set_property (GObject*, guint prop_id, const GValue*, GParamSpec* );
63
static void get_property (GObject*, guint prop_id, GValue*, GParamSpec* );
66
G_DEFINE_TYPE (IndicatorPowerDevice, indicator_power_device, G_TYPE_OBJECT);
70
indicator_power_device_class_init (IndicatorPowerDeviceClass *klass)
72
GObjectClass *object_class = G_OBJECT_CLASS (klass);
74
g_type_class_add_private (klass, sizeof (IndicatorPowerDevicePrivate));
76
object_class->dispose = indicator_power_device_dispose;
77
object_class->finalize = indicator_power_device_finalize;
78
object_class->set_property = set_property;
79
object_class->get_property = get_property;
81
properties[PROP_KIND] = g_param_spec_int (INDICATOR_POWER_DEVICE_KIND,
83
"The device's UpDeviceKind",
84
UP_DEVICE_KIND_UNKNOWN, UP_DEVICE_KIND_LAST,
85
UP_DEVICE_KIND_UNKNOWN,
86
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
88
properties[PROP_STATE] = g_param_spec_int (INDICATOR_POWER_DEVICE_STATE,
90
"The device's UpDeviceState",
91
UP_DEVICE_STATE_UNKNOWN, UP_DEVICE_STATE_LAST,
92
UP_DEVICE_STATE_UNKNOWN,
93
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
95
properties[PROP_OBJECT_PATH] = g_param_spec_string (INDICATOR_POWER_DEVICE_OBJECT_PATH,
97
"The device's DBus object path",
99
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
101
properties[PROP_PERCENTAGE] = g_param_spec_double (INDICATOR_POWER_DEVICE_PERCENTAGE,
106
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
108
properties[PROP_TIME] = g_param_spec_uint64 (INDICATOR_POWER_DEVICE_TIME,
113
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
115
g_object_class_install_properties (object_class, N_PROPERTIES, properties);
118
/* Initialize an instance */
120
indicator_power_device_init (IndicatorPowerDevice *self)
122
IndicatorPowerDevicePrivate * priv;
124
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_POWER_DEVICE_TYPE,
125
IndicatorPowerDevicePrivate);
126
priv->kind = UP_DEVICE_KIND_UNKNOWN;
127
priv->state = UP_DEVICE_STATE_UNKNOWN;
128
priv->object_path = NULL;
129
priv->percentage = 0.0;
136
indicator_power_device_dispose (GObject *object)
138
G_OBJECT_CLASS (indicator_power_device_parent_class)->dispose (object);
142
indicator_power_device_finalize (GObject *object)
144
IndicatorPowerDevice * self = INDICATOR_POWER_DEVICE(object);
145
IndicatorPowerDevicePrivate * priv = self->priv;
147
g_clear_pointer (&priv->object_path, g_free);
149
G_OBJECT_CLASS (indicator_power_device_parent_class)->finalize (object);
157
get_property (GObject * o, guint prop_id, GValue * value, GParamSpec * pspec)
159
IndicatorPowerDevice * self = INDICATOR_POWER_DEVICE(o);
160
IndicatorPowerDevicePrivate * priv = self->priv;
165
g_value_set_int (value, priv->kind);
169
g_value_set_int (value, priv->state);
172
case PROP_OBJECT_PATH:
173
g_value_set_string (value, priv->object_path);
176
case PROP_PERCENTAGE:
177
g_value_set_double (value, priv->percentage);
181
g_value_set_uint64 (value, priv->time);
185
G_OBJECT_WARN_INVALID_PROPERTY_ID(o, prop_id, pspec);
191
set_property (GObject * o, guint prop_id, const GValue * value, GParamSpec * pspec)
193
IndicatorPowerDevice * self = INDICATOR_POWER_DEVICE(o);
194
IndicatorPowerDevicePrivate * priv = self->priv;
199
priv->kind = g_value_get_int (value);
203
priv->state = g_value_get_int (value);
206
case PROP_OBJECT_PATH:
207
g_free (priv->object_path);
208
priv->object_path = g_value_dup_string (value);
211
case PROP_PERCENTAGE:
212
priv->percentage = g_value_get_double (value);
216
priv->time = g_value_get_uint64(value);
220
G_OBJECT_WARN_INVALID_PROPERTY_ID(o, prop_id, pspec);
230
indicator_power_device_get_kind (const IndicatorPowerDevice * device)
232
/* LCOV_EXCL_START */
233
g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_KIND_UNKNOWN);
236
return device->priv->kind;
240
indicator_power_device_get_state (const IndicatorPowerDevice * device)
242
/* LCOV_EXCL_START */
243
g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), UP_DEVICE_STATE_UNKNOWN);
246
return device->priv->state;
250
indicator_power_device_get_object_path (const IndicatorPowerDevice * device)
252
/* LCOV_EXCL_START */
253
g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), NULL);
256
return device->priv->object_path;
260
indicator_power_device_get_percentage (const IndicatorPowerDevice * device)
262
/* LCOV_EXCL_START */
263
g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), 0.0);
266
return device->priv->percentage;
270
indicator_power_device_get_time (const IndicatorPowerDevice * device)
272
/* LCOV_EXCL_START */
273
g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), (time_t)0);
276
return device->priv->time;
285
get_device_icon_suffix (gdouble percentage)
287
if (percentage >= 60) return "full";
288
if (percentage >= 30) return "good";
289
if (percentage >= 10) return "low";
294
get_device_icon_index (gdouble percentage)
296
if (percentage >= 90) return "100";
297
if (percentage >= 70) return "080";
298
if (percentage >= 50) return "060";
299
if (percentage >= 30) return "040";
300
if (percentage >= 10) return "020";
305
indicator_power_device_get_icon_names:
306
@device: #IndicatorPowerDevice from which to generate the icon names
308
This function's logic differs from GSD's power plugin in some ways:
310
1. All charging batteries use the same icon regardless of progress.
311
<https://bugs.launchpad.net/indicator-power/+bug/824629/comments/7>
313
2. For discharging batteries, we decide whether or not to use the 'caution'
314
icon based on whether or not we have <= 30 minutes remaining, rather than
315
looking at the battery's percentage left.
316
<https://bugs.launchpad.net/indicator-power/+bug/743823>
318
See also indicator_power_device_get_gicon().
320
Return value: (array zero-terminated=1) (transfer full):
321
A GStrv of icon names suitable for passing to g_themed_icon_new_from_names().
322
Free with g_strfreev() when done.
325
indicator_power_device_get_icon_names (const IndicatorPowerDevice * device)
327
const gchar *suffix_str;
328
const gchar *index_str;
330
/* LCOV_EXCL_START */
331
g_return_val_if_fail (INDICATOR_IS_POWER_DEVICE(device), NULL);
334
gdouble percentage = indicator_power_device_get_percentage (device);
335
const UpDeviceKind kind = indicator_power_device_get_kind (device);
336
const UpDeviceState state = indicator_power_device_get_state (device);
337
const gchar * kind_str = kind_str = up_device_kind_to_string (kind);
339
GPtrArray * names = g_ptr_array_new ();
341
if (kind == UP_DEVICE_KIND_LINE_POWER)
343
g_ptr_array_add (names, g_strdup("ac-adapter-symbolic"));
344
g_ptr_array_add (names, g_strdup("ac-adapter"));
346
else if (kind == UP_DEVICE_KIND_MONITOR)
348
g_ptr_array_add (names, g_strdup("gpm-monitor-symbolic"));
349
g_ptr_array_add (names, g_strdup("gpm-monitor"));
353
case UP_DEVICE_STATE_EMPTY:
354
g_ptr_array_add (names, g_strdup("battery-empty-symbolic"));
355
g_ptr_array_add (names, g_strdup_printf("gpm-%s-empty", kind_str));
356
g_ptr_array_add (names, g_strdup_printf("gpm-%s-000", kind_str));
357
g_ptr_array_add (names, g_strdup("battery-empty"));
360
case UP_DEVICE_STATE_FULLY_CHARGED:
361
g_ptr_array_add (names, g_strdup("battery-full-charged-symbolic"));
362
g_ptr_array_add (names, g_strdup("battery-full-charging-symbolic"));
363
g_ptr_array_add (names, g_strdup_printf("gpm-%s-full", kind_str));
364
g_ptr_array_add (names, g_strdup_printf("gpm-%s-100", kind_str));
365
g_ptr_array_add (names, g_strdup("battery-full-charged"));
366
g_ptr_array_add (names, g_strdup("battery-full-charging"));
369
case UP_DEVICE_STATE_CHARGING:
370
case UP_DEVICE_STATE_PENDING_CHARGE:
371
/* When charging, always use the same icon regardless of percentage.
372
<http://bugs.launchpad.net/indicator-power/+bug/824629> */
375
suffix_str = get_device_icon_suffix (percentage);
376
index_str = get_device_icon_index (percentage);
377
g_ptr_array_add (names, g_strdup_printf ("battery-%s-charging-symbolic", suffix_str));
378
g_ptr_array_add (names, g_strdup_printf ("gpm-%s-%s-charging", kind_str, index_str));
379
g_ptr_array_add (names, g_strdup_printf ("battery-%s-charging", suffix_str));
382
case UP_DEVICE_STATE_DISCHARGING:
383
case UP_DEVICE_STATE_PENDING_DISCHARGE:
384
/* Don't show the caution/red icons unless we have <=30 min left.
385
<https://bugs.launchpad.net/indicator-power/+bug/743823>
386
Themes use the caution color when the percentage is 0% or 20%,
387
so if we have >30 min left, use 30% as the icon's percentage floor */
388
if (indicator_power_device_get_time (device) > (30*60))
389
percentage = MAX(percentage, 30);
391
suffix_str = get_device_icon_suffix (percentage);
392
index_str = get_device_icon_index (percentage);
393
g_ptr_array_add (names, g_strdup_printf ("battery-%s-symbolic", suffix_str));
394
g_ptr_array_add (names, g_strdup_printf ("gpm-%s-%s", kind_str, index_str));
395
g_ptr_array_add (names, g_strdup_printf ("battery-%s", suffix_str));
399
g_ptr_array_add (names, g_strdup("battery-missing-symbolic"));
400
g_ptr_array_add (names, g_strdup("gpm-battery-missing"));
401
g_ptr_array_add (names, g_strdup("battery-missing"));
404
g_ptr_array_add (names, NULL); /* terminates the strv */
405
return (GStrv) g_ptr_array_free (names, FALSE);
409
indicator_power_device_get_gicon:
410
@device: #IndicatorPowerDevice to generate the icon names from
412
A convenience function to call g_themed_icon_new_from_names()
413
with the names returned by indicator_power_device_get_icon_names()
415
Return value: (transfer full): A themed GIcon
418
indicator_power_device_get_gicon (const IndicatorPowerDevice * device)
420
GStrv names = indicator_power_device_get_icon_names (device);
421
GIcon * icon = g_themed_icon_new_from_names (names, -1);
431
get_timestring (guint64 time_secs,
432
gchar **short_timestring,
433
gchar **detailed_timestring)
438
/* Add 0.5 to do rounding */
439
minutes = (int) ( ( time_secs / 60.0 ) + 0.5 );
443
*short_timestring = g_strdup (_("Unknown time"));
444
*detailed_timestring = g_strdup (_("Unknown time"));
451
*short_timestring = g_strdup_printf ("0:%.2i", minutes);
452
*detailed_timestring = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE, "%i minute",
458
hours = minutes / 60;
459
minutes = minutes % 60;
461
*short_timestring = g_strdup_printf ("%i:%.2i", hours, minutes);
465
*detailed_timestring = g_strdup_printf (g_dngettext (GETTEXT_PACKAGE,
472
/* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
473
* Swap order with "%2$s %2$i %1$s %1$i if needed */
474
*detailed_timestring = g_strdup_printf (_("%i %s %i %s"),
475
hours, g_dngettext (GETTEXT_PACKAGE, "hour", "hours", hours),
476
minutes, g_dngettext (GETTEXT_PACKAGE, "minute", "minutes", minutes));
481
device_kind_to_localised_string (UpDeviceKind kind)
483
const gchar *text = NULL;
486
case UP_DEVICE_KIND_LINE_POWER:
487
/* TRANSLATORS: system power cord */
488
text = _("AC Adapter");
490
case UP_DEVICE_KIND_BATTERY:
491
/* TRANSLATORS: laptop primary battery */
494
case UP_DEVICE_KIND_UPS:
495
/* TRANSLATORS: battery-backed AC power source */
498
case UP_DEVICE_KIND_MONITOR:
499
/* TRANSLATORS: a monitor is a device to measure voltage and current */
502
case UP_DEVICE_KIND_MOUSE:
503
/* TRANSLATORS: wireless mice with internal batteries */
506
case UP_DEVICE_KIND_KEYBOARD:
507
/* TRANSLATORS: wireless keyboard with internal battery */
508
text = _("Keyboard");
510
case UP_DEVICE_KIND_PDA:
511
/* TRANSLATORS: portable device */
514
case UP_DEVICE_KIND_PHONE:
515
/* TRANSLATORS: cell phone (mobile...) */
516
text = _("Cell phone");
518
case UP_DEVICE_KIND_MEDIA_PLAYER:
519
/* TRANSLATORS: media player, mp3 etc */
520
text = _("Media player");
522
case UP_DEVICE_KIND_TABLET:
523
/* TRANSLATORS: tablet device */
526
case UP_DEVICE_KIND_COMPUTER:
527
/* TRANSLATORS: tablet device */
528
text = _("Computer");
531
g_warning ("enum unrecognised: %i", kind);
532
text = up_device_kind_to_string (kind);
539
indicator_power_device_get_time_details (const IndicatorPowerDevice * device,
540
gchar ** short_details,
542
gchar ** accessible_name)
544
if (!INDICATOR_IS_POWER_DEVICE(device))
546
*short_details = NULL;
548
*accessible_name = NULL;
549
g_warning ("%s: %p is not an IndicatorPowerDevice", G_STRFUNC, device);
553
const time_t time = indicator_power_device_get_time (device);
554
const UpDeviceState state = indicator_power_device_get_state (device);
555
const gdouble percentage = indicator_power_device_get_percentage (device);
556
const UpDeviceKind kind = indicator_power_device_get_kind (device);
557
const gchar * device_name = device_kind_to_localised_string (kind);
561
gchar *short_timestring = NULL;
562
gchar *detailed_timestring = NULL;
564
get_timestring (time,
566
&detailed_timestring);
568
if (state == UP_DEVICE_STATE_CHARGING)
570
/* TRANSLATORS: %2 is a time string, e.g. "1 hour 5 minutes" */
571
*accessible_name = g_strdup_printf (_("%s (%s to charge (%.0lf%%))"), device_name, detailed_timestring, percentage);
572
*details = g_strdup_printf (_("%s (%s to charge)"), device_name, short_timestring);
573
*short_details = g_strdup_printf ("(%s)", short_timestring);
575
else if ((state == UP_DEVICE_STATE_DISCHARGING) && (time > (60*60*12)))
577
*accessible_name = g_strdup_printf (_("%s"), device_name);
578
*details = g_strdup_printf (_("%s"), device_name);
579
*short_details = g_strdup (short_timestring);
583
/* TRANSLATORS: %2 is a time string, e.g. "1 hour 5 minutes" */
584
*accessible_name = g_strdup_printf (_("%s (%s left (%.0lf%%))"), device_name, detailed_timestring, percentage);
585
*details = g_strdup_printf (_("%s (%s left)"), device_name, short_timestring);
586
*short_details = g_strdup (short_timestring);
589
g_free (short_timestring);
590
g_free (detailed_timestring);
592
else if (state == UP_DEVICE_STATE_FULLY_CHARGED)
594
*details = g_strdup_printf (_("%s (charged)"), device_name);
595
*accessible_name = g_strdup (*details);
596
*short_details = g_strdup ("");
598
else if (percentage > 0)
600
/* TRANSLATORS: %2 is a percentage value. Note: this string is only
601
* used when we don't have a time value */
602
*details = g_strdup_printf (_("%s (%.0lf%%)"), device_name, percentage);
603
*accessible_name = g_strdup (*details);
604
*short_details = g_strdup_printf (_("(%.0lf%%)"), percentage);
606
else if (kind == UP_DEVICE_KIND_LINE_POWER)
608
*details = g_strdup (device_name);
609
*accessible_name = g_strdup (device_name);
610
*short_details = g_strdup (device_name);
614
*details = g_strdup_printf (_("%s (not present)"), device_name);
615
*accessible_name = g_strdup (*details);
616
*short_details = g_strdup (_("(not present)"));
624
IndicatorPowerDevice *
625
indicator_power_device_new (const gchar * object_path,
631
GObject * o = g_object_new (INDICATOR_POWER_DEVICE_TYPE,
632
INDICATOR_POWER_DEVICE_KIND, kind,
633
INDICATOR_POWER_DEVICE_STATE, state,
634
INDICATOR_POWER_DEVICE_OBJECT_PATH, object_path,
635
INDICATOR_POWER_DEVICE_PERCENTAGE, percentage,
636
INDICATOR_POWER_DEVICE_TIME, (guint64)timestamp,
638
return INDICATOR_POWER_DEVICE(o);
641
IndicatorPowerDevice *
642
indicator_power_device_new_from_variant (GVariant * v)
644
g_return_val_if_fail (g_variant_is_of_type (v, G_VARIANT_TYPE("(susdut)")), NULL);
646
UpDeviceKind kind = UP_DEVICE_KIND_UNKNOWN;
647
UpDeviceState state = UP_DEVICE_STATE_UNKNOWN;
648
const gchar * icon = NULL;
649
const gchar * object_path = NULL;
650
gdouble percentage = 0;
653
g_variant_get (v, "(&su&sdut)",
661
return indicator_power_device_new (object_path,