diff options
author | Lars Uebernickel <lars.uebernickel@canonical.com> | 2013-06-07 11:33:03 -0400 |
---|---|---|
committer | Lars Uebernickel <lars.uebernickel@canonical.com> | 2013-06-07 11:33:03 -0400 |
commit | 12cc75fba26176cef0eb2ed8b98d0b377e10519f (patch) | |
tree | ac3e6cbb55a0fd8d303c2165df65c36ef5365ef9 /libindicator | |
parent | 060711f83ffb9fbcb85410ee9cb045b9c4d8d47c (diff) | |
parent | 0d3ebcb5cf74eef75f2153400b7b8a1d450573a5 (diff) | |
download | libayatana-indicator-12cc75fba26176cef0eb2ed8b98d0b377e10519f.tar.gz libayatana-indicator-12cc75fba26176cef0eb2ed8b98d0b377e10519f.tar.bz2 libayatana-indicator-12cc75fba26176cef0eb2ed8b98d0b377e10519f.zip |
Merge lp:~larsu/new-indicator-file-format
IndicatorNg: update indicator file format
The old file format had some shortcomings:
(1) It was impossible to efficiently reuse a menu for different profiles,
because the profile name was implicit in the object path. The only way to do
this was to export the same menu twice. Now, object paths have to be set
explicitly in the indicator file.
(2) The well-known dbus name of a service and the name of its service file were
similar but slightly different (com.canonical.indicator.test vs
com.canonical.test.indicator), which caused some confusion on when to use
which. Now, the file name *is* the bus name, and the `BusName` key has been
dropped.
The new file format is documented in README.
Diffstat (limited to 'libindicator')
-rw-r--r-- | libindicator/indicator-ng.c | 91 |
1 files changed, 60 insertions, 31 deletions
diff --git a/libindicator/indicator-ng.c b/libindicator/indicator-ng.c index fd78662..88db31c 100644 --- a/libindicator/indicator-ng.c +++ b/libindicator/indicator-ng.c @@ -29,6 +29,7 @@ struct _IndicatorNg gchar *service_file; gchar *name; gchar *object_path; + gchar *menu_object_path; gchar *bus_name; gchar *profile; gchar *header_action; @@ -152,6 +153,7 @@ indicator_ng_finalize (GObject *object) g_free (self->service_file); g_free (self->name); g_free (self->object_path); + g_free (self->menu_object_path); g_free (self->bus_name); g_free (self->accessible_desc); g_free (self->header_action); @@ -254,15 +256,12 @@ indicator_ng_update_entry (IndicatorNg *self) state = g_action_group_get_action_state (self->actions, self->header_action); if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("(sssb)"))) { - gchar *iconstr = NULL; + const gchar *iconstr = NULL; g_variant_get (state, "(&s&s&sb)", &label, &iconstr, &accessible_desc, &visible); if (iconstr) - { - icon = g_variant_ref_sink (g_variant_new_string (iconstr)); - g_free (iconstr); - } + icon = g_variant_ref_sink (g_variant_new_string (iconstr)); } else if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("a{sv}"))) { @@ -362,11 +361,13 @@ indicator_ng_service_appeared (GDBusConnection *connection, gpointer user_data) { IndicatorNg *self = user_data; - gchar *menu_object_path; g_assert (!self->actions); g_assert (!self->menu); + /* watch is not established when menu_object_path == NULL */ + g_assert (self->menu_object_path); + self->session_bus = g_object_ref (connection); self->actions = G_ACTION_GROUP (g_dbus_action_group_get (connection, name_owner, self->object_path)); @@ -375,15 +376,12 @@ indicator_ng_service_appeared (GDBusConnection *connection, g_signal_connect_swapped (self->actions, "action-removed", G_CALLBACK (indicator_ng_update_entry), self); g_signal_connect_swapped (self->actions, "action-state-changed", G_CALLBACK (indicator_ng_update_entry), self); - menu_object_path = g_strconcat (self->object_path, "/", self->profile, NULL); - self->menu = G_MENU_MODEL (g_dbus_menu_model_get (connection, name_owner, menu_object_path)); + self->menu = G_MENU_MODEL (g_dbus_menu_model_get (connection, name_owner, self->menu_object_path)); g_signal_connect (self->menu, "items-changed", G_CALLBACK (indicator_ng_menu_changed), self); if (g_menu_model_get_n_items (self->menu)) indicator_ng_menu_changed (self->menu, 0, 0, 1, self); indicator_ng_update_entry (self); - - g_free (menu_object_path); } static void @@ -460,39 +458,70 @@ indicator_ng_service_vanished (GDBusConnection *connection, } static gboolean +indicator_ng_load_from_keyfile (IndicatorNg *self, + GKeyFile *keyfile, + GError **error) +{ + g_assert (self->name == NULL); + g_assert (self->object_path == NULL); + g_assert (self->menu_object_path == NULL); + + self->name = g_key_file_get_string (keyfile, "Indicator Service", "Name", error); + if (self->name == NULL) + return FALSE; + + self->object_path = g_key_file_get_string (keyfile, "Indicator Service", "ObjectPath", error); + if (self->object_path == NULL) + return FALSE; + + /* + * Don't throw an error when the profile doesn't exist. Non-existant + * profiles are silently ignored by not showing an indicator at all. + */ + if (g_key_file_has_group (keyfile, self->profile)) + { + /* however, if the profile exists, it must have "ObjectPath" */ + self->menu_object_path = g_key_file_get_string (keyfile, self->profile, "ObjectPath", error); + if (self->menu_object_path == NULL) + return FALSE; + } + + return TRUE; +} + +static gboolean indicator_ng_initable_init (GInitable *initable, GCancellable *cancellable, GError **error) { IndicatorNg *self = INDICATOR_NG (initable); GKeyFile *keyfile; + gboolean success; - keyfile = g_key_file_new (); - if (!g_key_file_load_from_file (keyfile, self->service_file, G_KEY_FILE_NONE, error)) - goto out; - - if (!(self->name = g_key_file_get_string (keyfile, "Indicator Service", "Name", error))) - goto out; - - self->entry.name_hint = self->name; + self->bus_name = g_path_get_basename (self->service_file); - if (!(self->bus_name = g_key_file_get_string (keyfile, "Indicator Service", "BusName", error))) - goto out; + keyfile = g_key_file_new (); + if (g_key_file_load_from_file (keyfile, self->service_file, G_KEY_FILE_NONE, error) && + indicator_ng_load_from_keyfile (self, keyfile, error)) + { + self->entry.name_hint = self->name; - if (!(self->object_path = g_key_file_get_string (keyfile, "Indicator Service", "ObjectPath", error))) - goto out; + /* only watch the service when it supports the proile we're interested in */ + if (self->menu_object_path) + { + self->name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, + self->bus_name, + G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + indicator_ng_service_appeared, + indicator_ng_service_vanished, + self, NULL); + } - self->name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, - self->bus_name, - G_BUS_NAME_WATCHER_FLAGS_AUTO_START, - indicator_ng_service_appeared, - indicator_ng_service_vanished, - self, NULL); + success = TRUE; + } -out: g_key_file_free (keyfile); - - return self->name_watch_id > 0; + return success; } static void |