From cc6cbf767baba6ab2b5f2ec32f0d9ff2a7f94cfa Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 22:44:30 +0200 Subject: Sync chat status from and to clients --- libmessaging-menu/messaging-menu.c | 74 +++++++++++++++++++++++++++++++++++++- libmessaging-menu/messaging-menu.h | 2 +- src/messages-service.c | 50 ++++++++++++++++++++++---- src/messages-service.xml | 9 +++++ 4 files changed, 126 insertions(+), 9 deletions(-) diff --git a/libmessaging-menu/messaging-menu.c b/libmessaging-menu/messaging-menu.c index eff3b4f..7ee455a 100644 --- a/libmessaging-menu/messaging-menu.c +++ b/libmessaging-menu/messaging-menu.c @@ -52,12 +52,19 @@ enum { enum { ACTIVATE_SOURCE, + STATUS_CHANGED, N_SIGNALS }; static GParamSpec *properties[N_PROPERTIES]; static guint signals[N_SIGNALS]; +static const gchar *status_ids[] = { "available", "away", "busy", "invisible", "offline" }; + +static void global_status_changed (IndicatorMessagesService *service, + const gchar *status_str, + gpointer user_data); + static void messaging_menu_app_set_property (GObject *object, guint prop_id, @@ -100,6 +107,14 @@ messaging_menu_app_dispose (GObject *object) app->cancellable = NULL; } + if (app->messages_service) + { + g_signal_handlers_disconnect_by_func (app->messages_service, + global_status_changed, + app); + g_clear_object (&app->messages_service); + } + g_clear_object (&app->appinfo); g_clear_object (&app->source_actions); g_clear_object (&app->menu); @@ -134,6 +149,14 @@ messaging_menu_app_class_init (MessagingMenuAppClass *class) NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + + signals[STATUS_CHANGED] = g_signal_new ("status-changed", + MESSAGING_MENU_TYPE_APP, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); } static void @@ -152,11 +175,15 @@ created_messages_service (GObject *source_object, return; } + g_signal_connect (app->messages_service, "status-changed", + G_CALLBACK (global_status_changed), app); + /* sync current status */ if (app->registered == TRUE) messaging_menu_app_register (app); else if (app->registered == FALSE) messaging_menu_app_unregister (app); + messaging_menu_app_set_status (app, app->status); } static void @@ -316,7 +343,52 @@ void messaging_menu_app_set_status (MessagingMenuApp *app, MessagingMenuStatus status) { - g_warning ("%s: not yet implemented", G_STRFUNC); + g_return_if_fail (MESSAGING_MENU_IS_APP (app)); + g_return_if_fail (status >= MESSAGING_MENU_STATUS_AVAILABLE && + status <= MESSAGING_MENU_STATUS_OFFLINE); + + app->status = status; + + /* state will be synced right after connecting to the service */ + if (!app->messages_service) + return; + + indicator_messages_service_call_set_status (app->messages_service, + status_ids [status], + app->cancellable, + NULL, NULL); +} + +static int +status_from_string (const gchar *s) +{ + int i; + + if (!s) + return -1; + + for (i = 0; i <= MESSAGING_MENU_STATUS_OFFLINE; i++) + { + if (g_str_equal (s, status_ids[i])) + return i; + } + + return -1; +} + +static void +global_status_changed (IndicatorMessagesService *service, + const gchar *status_str, + gpointer user_data) +{ + MessagingMenuApp *app = user_data; + int status; + + status = status_from_string (status_str); + g_return_if_fail (status >= 0); + + app->status = (MessagingMenuStatus)status; + g_signal_emit (app, signals[STATUS_CHANGED], 0, app->status); } static void diff --git a/libmessaging-menu/messaging-menu.h b/libmessaging-menu/messaging-menu.h index 7ce2981..e767099 100644 --- a/libmessaging-menu/messaging-menu.h +++ b/libmessaging-menu/messaging-menu.h @@ -33,7 +33,7 @@ typedef enum { MESSAGING_MENU_STATUS_AVAILABLE, MESSAGING_MENU_STATUS_AWAY, MESSAGING_MENU_STATUS_BUSY, - MESSAGING_MENU_STATUS_HIDDEN, + MESSAGING_MENU_STATUS_INVISIBLE, MESSAGING_MENU_STATUS_OFFLINE } MessagingMenuStatus; diff --git a/src/messages-service.c b/src/messages-service.c index ec36335..a12847f 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -246,10 +246,26 @@ radio_item_activate (GSimpleAction *action, 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 (GSimpleAction *action, - GVariant *value, - gpointer user_data) +change_status_action (GSimpleAction *action, + GVariant *value, + gpointer user_data) { const gchar *status; @@ -261,9 +277,11 @@ change_status (GSimpleAction *action, g_str_equal (status, "invisible") || g_str_equal (status, "offline")); - g_simple_action_set_state (action, value); - - g_message ("changing status to %s", g_variant_get_string (value, NULL)); + if (!g_action_state_equal (G_ACTION (action), value)) { + g_message ("%s", status); + g_simple_action_set_state (action, value); + indicator_messages_service_emit_status_changed (messages_service, status); + } } static void @@ -302,6 +320,22 @@ unregister_application (IndicatorMessagesService *service, indicator_messages_service_complete_unregister_application (service, invocation); } +static void +set_status (IndicatorMessagesService *service, + GDBusMethodInvocation *invocation, + const gchar *status_str, + gpointer user_data) +{ + GAction *status; + + status = g_simple_action_group_lookup (actions, "status"); + g_return_if_fail (status != NULL); + + g_action_change_state (status, g_variant_new_string (status_str)); + + indicator_messages_service_complete_set_status (service, invocation); +} + GSimpleActionGroup * create_action_group () { @@ -319,7 +353,7 @@ create_action_group () 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), NULL); + g_signal_connect (status, "change-state", G_CALLBACK (change_status_action), NULL); clear = g_simple_action_new ("clear", NULL); g_simple_action_set_enabled (clear, FALSE); @@ -427,6 +461,8 @@ main (int argc, char ** argv) G_CALLBACK (register_application), NULL); g_signal_connect (messages_service, "handle-unregister-application", G_CALLBACK (unregister_application), NULL); + g_signal_connect (messages_service, "handle-set-status", + G_CALLBACK (set_status), NULL); menu = g_menu_new (); status_items = create_status_section (); diff --git a/src/messages-service.xml b/src/messages-service.xml index 450d1fa..edd47c7 100644 --- a/src/messages-service.xml +++ b/src/messages-service.xml @@ -6,9 +6,18 @@ + + + + + + + + + -- cgit v1.2.3