diff options
-rw-r--r-- | libmessaging-menu/messaging-menu.c | 1 | ||||
-rw-r--r-- | src/app-section.c | 51 | ||||
-rw-r--r-- | src/app-section.h | 3 | ||||
-rw-r--r-- | src/ido-menu-item.c | 34 | ||||
-rw-r--r-- | src/messages-service.c | 125 | ||||
-rw-r--r-- | src/messages-service.xml | 1 |
6 files changed, 168 insertions, 47 deletions
diff --git a/libmessaging-menu/messaging-menu.c b/libmessaging-menu/messaging-menu.c index 1b2e694..8a95b0a 100644 --- a/libmessaging-menu/messaging-menu.c +++ b/libmessaging-menu/messaging-menu.c @@ -547,6 +547,7 @@ messaging_menu_app_set_status (MessagingMenuApp *app, return; indicator_messages_service_call_set_status (app->messages_service, + g_app_info_get_id (G_APP_INFO (app->appinfo)), status_ids [status], app->cancellable, NULL, NULL); diff --git a/src/app-section.c b/src/app-section.c index 523e249..6aac52a 100644 --- a/src/app-section.c +++ b/src/app-section.c @@ -50,6 +50,7 @@ struct _AppSectionPrivate gboolean draws_attention; gboolean uses_chat_status; + gchar *chat_status; guint name_watch_id; }; @@ -60,6 +61,7 @@ enum { PROP_ACTIONS, PROP_DRAWS_ATTENTION, PROP_USES_CHAT_STATUS, + PROP_CHAT_STATUS, NUM_PROPERTIES }; @@ -78,6 +80,7 @@ static void app_section_set_property (GObject *object, const GValue *value, GParamSpec *pspec); static void app_section_dispose (GObject *object); +static void app_section_finalize (GObject *object); static void activate_cb (GSimpleAction *action, GVariant *param, gpointer userdata); @@ -118,6 +121,7 @@ app_section_class_init (AppSectionClass *klass) object_class->get_property = app_section_get_property; object_class->set_property = app_section_set_property; object_class->dispose = app_section_dispose; + object_class->finalize = app_section_finalize; properties[PROP_APPINFO] = g_param_spec_object ("app-info", "AppInfo", @@ -143,6 +147,13 @@ app_section_class_init (AppSectionClass *klass) FALSE, G_PARAM_READABLE); + properties[PROP_CHAT_STATUS] = g_param_spec_string ("chat-status", + "Chat status", + "Current chat status of the application", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); destroy_signal = g_signal_new ("destroy", @@ -199,6 +210,10 @@ app_section_get_property (GObject *object, g_value_set_boolean (value, app_section_get_uses_chat_status (self)); break; + case PROP_CHAT_STATUS: + g_value_set_string (value, app_section_get_status (self)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -218,6 +233,10 @@ app_section_set_property (GObject *object, app_section_set_app_info (self, g_value_get_object (value)); break; + case PROP_CHAT_STATUS: + app_section_set_status (self, g_value_get_string (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -261,6 +280,16 @@ app_section_dispose (GObject *object) G_OBJECT_CLASS (app_section_parent_class)->dispose (object); } +static void +app_section_finalize (GObject *object) +{ + AppSection * self = APP_SECTION(object); + + g_free (self->priv->chat_status); + + G_OBJECT_CLASS (app_section_parent_class)->dispose (object); +} + /* Respond to one of the shortcuts getting clicked on. */ static void nick_activate_cb (GSimpleAction *action, @@ -668,10 +697,12 @@ app_section_unset_object_path (AppSection *self) } priv->draws_attention = FALSE; + g_clear_pointer (&priv->chat_status, g_free); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DRAWS_ATTENTION]); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHAT_STATUS]); g_action_group_change_action_state (G_ACTION_GROUP (priv->static_shortcuts), "launch", g_variant_new_boolean (FALSE)); @@ -763,3 +794,23 @@ app_section_get_uses_chat_status (AppSection *self) return priv->uses_chat_status; } + +const gchar * +app_section_get_status (AppSection *self) +{ + AppSectionPrivate * priv = self->priv; + + return priv->chat_status; +} + +void +app_section_set_status (AppSection *self, + const gchar *status) +{ + AppSectionPrivate * priv = self->priv; + + g_free (priv->chat_status); + priv->chat_status = g_strdup (status); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHAT_STATUS]); +} diff --git a/src/app-section.h b/src/app-section.h index 09697c5..7c39e8e 100644 --- a/src/app-section.h +++ b/src/app-section.h @@ -63,6 +63,9 @@ void app_section_set_object_path (AppSection *self, const gchar *object_path); void app_section_unset_object_path (AppSection *self); gboolean app_section_get_uses_chat_status (AppSection *self); +const gchar * app_section_get_status (AppSection *self); +void app_section_set_status (AppSection *self, + const gchar *status); G_END_DECLS diff --git a/src/ido-menu-item.c b/src/ido-menu-item.c index 6b19d2a..32044ff 100644 --- a/src/ido-menu-item.c +++ b/src/ido-menu-item.c @@ -99,8 +99,37 @@ ido_menu_item_set_state (IdoMenuItem *self, if (priv->target) { ido_menu_item_set_has_indicator (self, TRUE); + ido_menu_item_set_active (self, FALSE); gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (self), TRUE); - ido_menu_item_set_active (self, g_variant_equal (priv->target, state)); + gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (self), FALSE); + + if (g_variant_is_of_type (state, G_VARIANT_TYPE_STRING)) + { + ido_menu_item_set_active (self, g_variant_equal (priv->target, state)); + } + else if (g_variant_is_of_type (state, G_VARIANT_TYPE ("as")) && + g_variant_is_of_type (priv->target, G_VARIANT_TYPE_STRING)) + { + const gchar *target_str; + const gchar **state_strs; + const gchar **it; + + target_str = g_variant_get_string (priv->target, NULL); + state_strs = g_variant_get_strv (state, NULL); + + it = state_strs; + while (*it != NULL && !g_str_equal (*it, target_str)) + it++; + + if (*it != NULL) + { + ido_menu_item_set_active (self, TRUE); + gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (self), + g_strv_length ((gchar **)state_strs) > 1); + } + + g_free (state_strs); + } } else if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN)) { @@ -258,7 +287,8 @@ ido_menu_item_activate (GtkMenuItem *item) if (!priv->in_set_active && priv->action && priv->action_group) g_action_group_activate_action (priv->action_group, priv->action, priv->target); - GTK_MENU_ITEM_CLASS (ido_menu_item_parent_class)->activate (item); + if (priv->in_set_active) + GTK_MENU_ITEM_CLASS (ido_menu_item_parent_class)->activate (item); } static void diff --git a/src/messages-service.c b/src/messages-service.c index fd0bdcb..821598f 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -144,6 +144,52 @@ uses_chat_status_changed (GObject *object, update_chat_section (); } +static gboolean +strv_contains (const gchar **strv, + const gchar *needle) +{ + const gchar **it; + + it = strv; + while (*it != NULL && !g_str_equal (*it, needle)) + it++; + + return *it != NULL; +} + +static void +update_chat_status () +{ + GHashTableIter iter; + AppSection *section; + const gchar *statuses[] = { NULL, NULL, NULL, NULL, NULL, NULL }; + int pos = 0; + GAction *status; + + g_hash_table_iter_init (&iter, applications); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) §ion)) { + const gchar *status_str = NULL; + + status_str = app_section_get_status (section); + if (status_str != NULL && !strv_contains (statuses, status_str)) + statuses[pos++] = status_str; + } + + + status = g_simple_action_group_lookup (actions, "status"); + g_return_if_fail (status != NULL); + + g_simple_action_set_state (G_SIMPLE_ACTION (status), g_variant_new_strv (statuses, -1)); +} + +static void +chat_status_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + update_chat_status (); +} + static void remove_section (AppSection *section, const gchar *id) @@ -156,6 +202,7 @@ remove_section (AppSection *section, g_signal_handlers_disconnect_by_func (section, actions_changed, NULL); g_signal_handlers_disconnect_by_func (section, draws_attention_changed, NULL); g_signal_handlers_disconnect_by_func (section, uses_chat_status_changed, NULL); + g_signal_handlers_disconnect_by_func (section, chat_status_changed, NULL); g_signal_handlers_disconnect_by_func (section, remove_section, NULL); g_hash_table_remove (applications, id); @@ -165,6 +212,7 @@ remove_section (AppSection *section, g_menu_remove (toplevel_menu, 0); } + update_chat_status (); update_chat_section (); } @@ -197,6 +245,8 @@ add_application (const gchar *desktop_id) G_CALLBACK (draws_attention_changed), NULL); g_signal_connect (section, "notify::uses-chat-status", G_CALLBACK (uses_chat_status_changed), NULL); + g_signal_connect (section, "notify::chat-status", + G_CALLBACK (chat_status_changed), NULL); g_signal_connect_data (section, "destroy", G_CALLBACK (remove_section), g_strdup (id), @@ -322,48 +372,15 @@ clear_action_activate (GSimpleAction *simple, } static void -radio_item_activate (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) -{ - g_action_change_state (G_ACTION (action), parameter); -} - -static gboolean -g_action_state_equal (GAction *action, - GVariant *value) -{ - GVariant *state; - gboolean eq; - - state = g_action_get_state (action); - g_return_val_if_fail (state != NULL, FALSE); - - eq = g_variant_equal (state, value); - - g_variant_unref (state); - return eq; -} - -static void -change_status_action (GSimpleAction *action, - GVariant *value, - gpointer user_data) +status_action_activate (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) { const gchar *status; - g_variant_get (value, "&s", &status); + status = g_variant_get_string (parameter, NULL); - g_return_if_fail (g_str_equal (status, "available") || - g_str_equal (status, "away")|| - g_str_equal (status, "busy") || - g_str_equal (status, "invisible") || - g_str_equal (status, "offline")); - - if (!g_action_state_equal (G_ACTION (action), value)) { - g_simple_action_set_state (action, value); - indicator_messages_service_emit_status_changed (messages_service, status); - } + indicator_messages_service_emit_status_changed (messages_service, status); } static void @@ -405,17 +422,35 @@ unregister_application (IndicatorMessagesService *service, static void set_status (IndicatorMessagesService *service, GDBusMethodInvocation *invocation, + const gchar *desktop_id, const gchar *status_str, gpointer user_data) { - GAction *status; + GDesktopAppInfo *appinfo; + gchar *id; + AppSection *section; - status = g_simple_action_group_lookup (actions, "status"); - g_return_if_fail (status != NULL); + g_return_if_fail (g_str_equal (status_str, "available") || + g_str_equal (status_str, "away")|| + g_str_equal (status_str, "busy") || + g_str_equal (status_str, "invisible") || + g_str_equal (status_str, "offline")); - g_action_change_state (status, g_variant_new_string (status_str)); + appinfo = g_desktop_app_info_new (desktop_id); + if (!appinfo) { + g_warning ("could not set status for '%s', there's no desktop file with that id", desktop_id); + return; + } + + id = g_app_info_get_simple_id (G_APP_INFO (appinfo)); + section = g_hash_table_lookup (applications, id); + if (section != NULL) + app_section_set_status (section, status_str); indicator_messages_service_complete_set_status (service, invocation); + + g_free (id); + g_object_unref (appinfo); } static GSimpleActionGroup * @@ -425,6 +460,7 @@ create_action_group (void) GSimpleAction *messages; GSimpleAction *clear; GSimpleAction *status; + const gchar *default_status[] = { "offline", NULL }; actions = g_simple_action_group_new (); @@ -433,9 +469,8 @@ create_action_group (void) g_variant_new_boolean (FALSE)); status = g_simple_action_new_stateful ("status", G_VARIANT_TYPE ("s"), - g_variant_new ("s", "offline")); - g_signal_connect (status, "activate", G_CALLBACK (radio_item_activate), NULL); - g_signal_connect (status, "change-state", G_CALLBACK (change_status_action), NULL); + g_variant_new_strv (default_status, -1)); + g_signal_connect (status, "activate", G_CALLBACK (status_action_activate), NULL); clear = g_simple_action_new ("clear", NULL); g_simple_action_set_enabled (clear, FALSE); diff --git a/src/messages-service.xml b/src/messages-service.xml index edd47c7..00ae154 100644 --- a/src/messages-service.xml +++ b/src/messages-service.xml @@ -12,6 +12,7 @@ </method> <method name="SetStatus"> + <arg type="s" name="desktop_id" direction="in" /> <arg type="s" name="status" direction="in" /> </method> |