aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmessaging-menu/messaging-menu.c1
-rw-r--r--src/app-section.c51
-rw-r--r--src/app-section.h3
-rw-r--r--src/ido-menu-item.c34
-rw-r--r--src/messages-service.c125
-rw-r--r--src/messages-service.xml1
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) &section)) {
+ 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>