diff options
-rw-r--r-- | src/indicator-power.c | 344 | ||||
-rw-r--r-- | src/indicator-power.h | 6 | ||||
-rw-r--r-- | tests/test-indicator.cc | 31 |
3 files changed, 193 insertions, 188 deletions
diff --git a/src/indicator-power.c b/src/indicator-power.c index dc1c512..c2ace80 100644 --- a/src/indicator-power.c +++ b/src/indicator-power.c @@ -31,6 +31,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. /* upower */ #include <libupower-glib/upower.h> +#include "device.h" #include "indicator-power.h" #define ICON_POLICY_KEY "icon-policy" @@ -60,8 +61,8 @@ struct _IndicatorPowerPrivate GDBusProxy *proxy; guint watcher_id; - GVariant *devices; - GVariant *device; + GSList * devices; + IndicatorPowerDevice * device; GSettings *settings; }; @@ -140,20 +141,21 @@ indicator_power_init (IndicatorPower *self) } static void +dispose_devices (IndicatorPower * self) +{ + IndicatorPowerPrivate * priv = self->priv; + + g_slist_free_full (priv->devices, g_object_unref); + priv->devices = NULL; + g_clear_object (&priv->device); +} +static void indicator_power_dispose (GObject *object) { IndicatorPower *self = INDICATOR_POWER(object); IndicatorPowerPrivate * priv = self->priv; - if (priv->devices != NULL) { - g_variant_unref (priv->devices); - priv->devices = NULL; - } - - if (priv->device != NULL) { - g_variant_unref (priv->device); - priv->device = NULL; - } + dispose_devices (self); g_clear_object (&priv->proxy); g_clear_object (&priv->proxy_cancel); @@ -533,99 +535,78 @@ get_device_icon (UpDeviceKind kind, } -static void -menu_add_device (GtkMenu *menu, - GVariant *device) +static gboolean +menu_add_device (GtkMenu * menu, const IndicatorPowerDevice * device) { - UpDeviceKind kind; - UpDeviceState state; - GtkWidget *icon; - GtkWidget *item; - GtkWidget *details_label; - GtkWidget *grid; - GIcon *device_gicons; - const gchar *device_icon = NULL; - const gchar *object_path = NULL; - gdouble percentage; - guint64 time; - const gchar *device_name; - gchar *short_details = NULL; - gchar *details = NULL; - gchar *accessible_name = NULL; - AtkObject *atk_object; - - if (device == NULL) - return; - - g_variant_get (device, - "(&su&sdut)", - &object_path, - &kind, - &device_icon, - &percentage, - &state, - &time); - - g_debug ("%s: got data from object %s", G_STRFUNC, object_path); + gboolean added = FALSE; + const UpDeviceKind kind = indicator_power_device_get_kind (device); if (kind == UP_DEVICE_KIND_LINE_POWER) - return; - - /* Process the data */ - device_gicons = get_device_icon (kind, state, time, device_icon); - icon = gtk_image_new_from_gicon (device_gicons, - GTK_ICON_SIZE_SMALL_TOOLBAR); - g_clear_object (&device_gicons); - - device_name = device_kind_to_localised_string (kind); - - build_device_time_details (device_name, time, state, percentage, &short_details, &details, &accessible_name); - - /* Create menu item */ - item = gtk_image_menu_item_new (); - atk_object = gtk_widget_get_accessible(item); - if (atk_object != NULL) - atk_object_set_name (atk_object, accessible_name); - - grid = gtk_grid_new (); - gtk_grid_set_column_spacing (GTK_GRID (grid), 6); - gtk_grid_attach (GTK_GRID (grid), icon, 0, 0, 1, 1); - details_label = gtk_label_new (details); - gtk_grid_attach_next_to (GTK_GRID (grid), details_label, icon, GTK_POS_RIGHT, 1, 1); - gtk_container_add (GTK_CONTAINER (item), grid); - gtk_widget_show (grid); + { + GtkWidget *icon; + GtkWidget *item; + GtkWidget *details_label; + GtkWidget *grid; + GIcon *device_gicons; + const gchar *device_name; + gchar *short_details = NULL; + gchar *details = NULL; + gchar *accessible_name = NULL; + AtkObject *atk_object; + const time_t time = indicator_power_device_get_time (device); + const UpDeviceState state = indicator_power_device_get_state (device); + const gchar * device_icon = indicator_power_device_get_icon (device); + const gdouble percentage = indicator_power_device_get_percentage (device); + + /* Process the data */ + device_gicons = get_device_icon (kind, state, time, device_icon); + icon = gtk_image_new_from_gicon (device_gicons, + GTK_ICON_SIZE_SMALL_TOOLBAR); + g_clear_object (&device_gicons); + + device_name = device_kind_to_localised_string (kind); + + build_device_time_details (device_name, time, state, percentage, &short_details, &details, &accessible_name); + + /* Create menu item */ + item = gtk_image_menu_item_new (); + atk_object = gtk_widget_get_accessible(item); + if (atk_object != NULL) + atk_object_set_name (atk_object, accessible_name); + + grid = gtk_grid_new (); + gtk_grid_set_column_spacing (GTK_GRID (grid), 6); + gtk_grid_attach (GTK_GRID (grid), icon, 0, 0, 1, 1); + details_label = gtk_label_new (details); + gtk_grid_attach_next_to (GTK_GRID (grid), details_label, icon, GTK_POS_RIGHT, 1, 1); + gtk_container_add (GTK_CONTAINER (item), grid); + gtk_widget_show (grid); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + added = TRUE; - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + g_signal_connect (G_OBJECT (item), "activate", + G_CALLBACK (show_info_cb), NULL); - g_signal_connect (G_OBJECT (item), "activate", - G_CALLBACK (show_info_cb), NULL); + g_free (short_details); + g_free (details); + g_free (accessible_name); + } - g_free (short_details); - g_free (details); - g_free (accessible_name); + return added; } static gsize -menu_add_devices (GtkMenu *menu, - GVariant *devices) +menu_add_devices (GtkMenu * menu, GSList * devices) { - gsize n_devices; - guint i; - - if (devices == NULL) - return 0; + GSList * l; + gsize n_added = 0; - n_devices = g_variant_n_children (devices); - g_debug ("Num devices: '%" G_GSIZE_FORMAT "'\n", n_devices); + for (l=devices; l!=NULL; l=l->next) + if (menu_add_device (menu, l->data)) + ++n_added; - for (i = 0; i < n_devices; i++) - { - GVariant * device = g_variant_get_child_value (devices, i); - menu_add_device (menu, device); - g_variant_unref (device); - } - - return n_devices; + return n_added; } static gboolean @@ -680,39 +661,25 @@ build_menu (IndicatorPower *self) gtk_widget_show_all (GTK_WIDGET (priv->menu)); } -static GVariant * -get_primary_device (GVariant *devices) +static IndicatorPowerDevice* +get_primary_device (GSList * devices) { - gint primary_device_charging_index = -1; - gint primary_device_discharging_index = -1; - gint primary_device_index = -1; + IndicatorPowerDevice * primary_device = NULL; + IndicatorPowerDevice * primary_device_charging = NULL; + IndicatorPowerDevice * primary_device_discharging = NULL; gboolean charging = FALSE; gboolean discharging = FALSE; guint64 min_discharging_time = G_MAXUINT64; guint64 max_charging_time = 0; - guint i; + GSList * l; - const gsize n_devices = devices ? g_variant_n_children (devices) : 0; - g_debug ("Num devices: '%" G_GSIZE_FORMAT "'\n", n_devices); - - for (i = 0; i < n_devices; i++) + for (l=devices; l!=NULL; l=l->next) { - const gchar *object_path; - UpDeviceKind kind; - const gchar *device_icon; - gdouble percentage; - UpDeviceState state; - guint64 time = 0; - - g_variant_get_child (devices, i, "(&su&sdut)", - &object_path, - &kind, - &device_icon, - &percentage, - &state, - &time); - - g_debug ("%s: got data from object %s", G_STRFUNC, object_path); + IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE(l->data); + const UpDeviceKind kind = indicator_power_device_get_kind (device); + const UpDeviceState state = indicator_power_device_get_state (device); + const gdouble percentage = indicator_power_device_get_percentage (device); + const time_t time = indicator_power_device_get_time (device); /* Try to fix the case when we get a empty battery bay as a real battery */ if (state == UP_DEVICE_STATE_UNKNOWN && @@ -729,7 +696,7 @@ get_primary_device (GVariant *devices) if (time < min_discharging_time) { min_discharging_time = time; - primary_device_discharging_index = i; + primary_device_discharging = device; } } else if (state == UP_DEVICE_STATE_CHARGING) @@ -737,64 +704,49 @@ get_primary_device (GVariant *devices) charging = TRUE; if (time == 0) /* Battery broken */ { - primary_device_charging_index = i; + primary_device_charging = device; } if (time > max_charging_time) { max_charging_time = time; - primary_device_charging_index = i; + primary_device_charging = device; } } else { - primary_device_index = i; + primary_device = device; } } if (discharging) { - primary_device_index = primary_device_discharging_index; + primary_device = primary_device_discharging; } else if (charging) { - primary_device_index = primary_device_charging_index; + primary_device = primary_device_charging; } - if (primary_device_index >= 0) - return g_variant_get_child_value (devices, primary_device_index); + if (primary_device != NULL) + g_object_ref (primary_device); - return NULL; + return primary_device; } static void -put_primary_device (IndicatorPower *self, - GVariant *device) +put_primary_device (IndicatorPower *self, IndicatorPowerDevice *device) { - UpDeviceKind kind; - UpDeviceState state; GIcon *device_gicons; gchar *short_details = NULL; gchar *details = NULL; gchar *accessible_name = NULL; - const gchar *device_icon = NULL; - const gchar *object_path = NULL; - gdouble percentage; - guint64 time; const gchar *device_name; IndicatorPowerPrivate * priv = self->priv; - - /* set the icon and text */ - g_variant_get (device, - "(&su&sdut)", - &object_path, - &kind, - &device_icon, - &percentage, - &state, - &time); - - g_debug ("%s: got data from object %s", G_STRFUNC, object_path); - + const time_t time = indicator_power_device_get_time (device); + const UpDeviceKind kind = indicator_power_device_get_kind (device); + const UpDeviceState state = indicator_power_device_get_state (device); + const gchar * device_icon = indicator_power_device_get_icon (device); + const gdouble percentage = indicator_power_device_get_percentage (device); /* set icon */ device_gicons = get_device_icon (kind, state, time, device_icon); gtk_image_set_from_gicon (priv->status_image, @@ -819,47 +771,75 @@ put_primary_device (IndicatorPower *self, g_free (accessible_name); } +void +indicator_power_set_devices (IndicatorPower * self, + IndicatorPowerDevice ** devices, + gsize device_count) +{ + gsize i; + IndicatorPowerPrivate * priv; + + g_return_if_fail (IS_INDICATOR_POWER(self)); + priv = self->priv; + + /* clear out the previous values */ + dispose_devices (self); + + /* get the new devices */ + for (i=0; i<device_count; ++i) + priv->devices = g_slist_prepend (priv->devices, g_object_ref(devices[i])); + priv->devices = g_slist_reverse (priv->devices); + + /* get the new primary device */ + priv->device = get_primary_device (priv->devices); + if (priv->device) + put_primary_device (self, priv->device); + else + g_message ("Couldn't find primary device"); + + build_menu (self); + update_visibility (self); +} + static void -get_devices_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) +get_devices_cb (GObject * source_object, + GAsyncResult * res, + gpointer user_data) { + GError *error; + int device_count; + IndicatorPowerDevice ** devices; + GVariant * devices_container; IndicatorPower *self = INDICATOR_POWER (user_data); - IndicatorPowerPrivate * priv = self->priv; - GVariant *devices_container; - GError *error = NULL; + /* build an array of IndicatorPowerDevices from the DBus response */ + error = NULL; devices_container = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (devices_container == NULL) { g_message ("Couldn't get devices: %s\n", error->message); g_error_free (error); } - else /* update 'devices' */ + else { - if (priv->devices != NULL) - g_variant_unref (priv->devices); - priv->devices = g_variant_get_child_value (devices_container, 0); + gsize i; + GVariant * devices_variant = g_variant_get_child_value (devices_container, 0); + device_count = devices_variant ? g_variant_n_children (devices_variant) : 0; + devices = g_new0 (IndicatorPowerDevice*, device_count); - g_variant_unref (devices_container); - - if (priv->device != NULL) - g_variant_unref (priv->device); - priv->device = get_primary_device (priv->devices); - - if (priv->device == NULL) + for (i=0; i<device_count; i++) { - g_message ("Couldn't find primary device"); + GVariant * v = g_variant_get_child_value (devices_variant, i); + devices[i] = indicator_power_device_new_from_variant (v); + g_variant_unref (v); } - else - { - put_primary_device (self, priv->device); - } - } - build_menu (self); + g_variant_unref (devices_variant); + g_variant_unref (devices_container); + } - update_visibility (self); + indicator_power_set_devices (self, devices, device_count); + g_free (devices); } static void @@ -1017,28 +997,22 @@ get_name_hint (IndicatorObject *io) ***/ static void -count_batteries(GVariant *devices, int *total, int *inuse) +count_batteries (GSList * devices, int *total, int *inuse) { - const int n_devices = devices ? g_variant_n_children (devices) : 0; + GSList * l; - int i; - for (i=0; i<n_devices; i++) + for (l=devices; l!=NULL; l=l->next) { - GVariant * device = g_variant_get_child_value (devices, i); + const IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE(l->data); - UpDeviceKind kind; - g_variant_get_child (device, 1, "u", &kind); - if (kind == UP_DEVICE_KIND_BATTERY) + if (indicator_power_device_get_kind(device) == UP_DEVICE_KIND_BATTERY) { ++*total; - UpDeviceState state; - g_variant_get_child (device, 4, "u", &state); + const UpDeviceState state = indicator_power_device_get_state (device); if ((state == UP_DEVICE_STATE_CHARGING) || (state == UP_DEVICE_STATE_DISCHARGING)) ++*inuse; } - - g_variant_unref (device); } g_debug("count_batteries found %d batteries (%d are charging/discharging)", *total, *inuse); diff --git a/src/indicator-power.h b/src/indicator-power.h index 39ac0ca..bd47535 100644 --- a/src/indicator-power.h +++ b/src/indicator-power.h @@ -26,6 +26,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libindicator/indicator.h> #include <libindicator/indicator-object.h> +#include "device.h" + G_BEGIN_DECLS #define INDICATOR_POWER_TYPE (indicator_power_get_type ()) @@ -52,4 +54,8 @@ struct _IndicatorPower GType indicator_power_get_type (void) G_GNUC_CONST; +void indicator_power_set_devices (IndicatorPower * power, + IndicatorPowerDevice ** devices, + gsize deviceCount); + G_END_DECLS diff --git a/tests/test-indicator.cc b/tests/test-indicator.cc index af494ee..3e9d97b 100644 --- a/tests/test-indicator.cc +++ b/tests/test-indicator.cc @@ -48,15 +48,32 @@ class IndicatorTest : public ::testing::Test { protected: + IndicatorPowerDevice * ac_device; + IndicatorPowerDevice * battery_device; + virtual void SetUp() { ensure_glib_initialized (); + g_setenv( "GSETTINGS_SCHEMA_DIR", SCHEMA_DIR, TRUE); - g_message ("GSETTINGS_SCHEMA_DIR is %s", g_getenv("GSETTINGS_SCHEMA_DIR")); + + ac_device = indicator_power_device_new ( + "/org/freedesktop/UPower/devices/line_power_AC", + UP_DEVICE_KIND_LINE_POWER, + ". GThemedIcon ac-adapter-symbolic ac-adapter ", + 0.0, UP_DEVICE_STATE_UNKNOWN, 0); + + battery_device = indicator_power_device_new ( + "/org/freedesktop/UPower/devices/battery_BAT0", + UP_DEVICE_KIND_BATTERY, + ". GThemedIcon battery-good-symbolic gpm-battery-060 battery-good ", + 52.871712, UP_DEVICE_STATE_DISCHARGING, 8834); } virtual void TearDown() { + g_clear_object (&battery_device); + g_clear_object (&ac_device); } }; @@ -66,10 +83,18 @@ class IndicatorTest : public ::testing::Test TEST_F(IndicatorTest, GObjectNew) { - ensure_glib_initialized (); - GObject * o = G_OBJECT (g_object_new (INDICATOR_POWER_TYPE, NULL)); ASSERT_TRUE (o != NULL); ASSERT_TRUE (IS_INDICATOR_POWER(o)); g_object_unref (o); } + +TEST_F(IndicatorTest, SetDevices) +{ + IndicatorPower * power = INDICATOR_POWER(g_object_new (INDICATOR_POWER_TYPE, NULL)); + IndicatorPowerDevice * devices[] = { ac_device, battery_device }; + + indicator_power_set_devices (power, devices, G_N_ELEMENTS(devices)); + + g_object_unref (power); +} |