From b55e637321b0c3fdcb5e8aafab9614f80a3228d3 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 16 Nov 2012 14:41:50 +0100 Subject: Export menu for the phone client This is a rough first draft: It only fetched the sources and messages from applications once and doesn't listen for further changes. This removes all code for the desktop menu for now. --- src/messages-service.c | 551 ++++++++++++++----------------------------------- 1 file changed, 157 insertions(+), 394 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index b36a0a2..9d64412 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -28,12 +28,12 @@ with this program. If not, see . #include #include -#include "app-section.h" #include "dbus-data.h" #include "gactionmuxer.h" #include "gsettingsstrv.h" #include "gmenuutils.h" #include "indicator-messages-service.h" +#include "indicator-messages-application.h" #define NUM_STATUSES 5 @@ -44,7 +44,8 @@ static GSimpleActionGroup *actions; static GActionMuxer *action_muxer; static GMenu *toplevel_menu; static GMenu *menu; -static GMenuModel *chat_section; +static GMenu *messages_section; +static GMenu *sources_section; static GSettings *settings; static gboolean draws_attention; static const gchar *global_status[6]; /* max 5: available, away, busy, invisible, offline */ @@ -82,358 +83,173 @@ indicator_messages_get_icon_name () return iconstr; } -static void -indicator_messages_update_icon () -{ - GSimpleAction *messages; - gchar *icon; - - messages = G_SIMPLE_ACTION (g_simple_action_group_lookup (actions, "messages")); - g_return_if_fail (messages != NULL); - - icon = indicator_messages_get_icon_name (); - g_simple_action_set_state (messages, g_variant_new_string (icon)); - - g_free (icon); -} - -static gchar * -g_app_info_get_simple_id (GAppInfo *appinfo) -{ - const gchar *id; - - id = g_app_info_get_id (appinfo); - if (!id) - return NULL; - - if (g_str_has_suffix (id, ".desktop")) - return g_strndup (id, strlen (id) - 8); - else - return g_strdup (id); -} - -static void -actions_changed (GObject *object, - GParamSpec *pspec, - gpointer user_data) +static void +service_shutdown (IndicatorService * service, gpointer user_data) { - AppSection *section = APP_SECTION (object); - gchar *id; - GActionGroup *actions; - - id = g_app_info_get_simple_id (app_section_get_app_info (section)); - actions = app_section_get_actions (section); - - g_action_muxer_insert (action_muxer, id, actions); - g_free (id); -} - + GMainLoop *mainloop = user_data; -static gboolean -app_section_draws_attention (gpointer key, - gpointer value, - gpointer user_data) -{ - AppSection *section = value; - return app_section_get_draws_attention (section); + g_warning("Shutting down service!"); + g_main_loop_quit(mainloop); } static void -draws_attention_changed (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - GSimpleAction *clear; - - clear = G_SIMPLE_ACTION (g_simple_action_group_lookup (actions, "clear")); - g_return_if_fail (clear != NULL); - - draws_attention = g_hash_table_find (applications, app_section_draws_attention, NULL) != NULL; - - g_simple_action_set_enabled (clear, draws_attention); - - indicator_messages_update_icon (); -} - -static gboolean -app_section_uses_chat (gpointer key, - gpointer value, +clear_action_activate (GSimpleAction *simple, + GVariant *param, gpointer user_data) { - AppSection *section = value; - return app_section_get_uses_chat_status (section); + /* TODO */ } static void -update_chat_section () +status_action_activate (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) { - gboolean show_chat; - GMenuModel *first_section; - - show_chat = g_hash_table_find (applications, app_section_uses_chat, NULL) != NULL; - - first_section = g_menu_model_get_item_link (G_MENU_MODEL (menu), 0, G_MENU_LINK_SECTION); - if (first_section == chat_section) { - if (!show_chat) - g_menu_remove (menu, 0); - } - else { - if (show_chat) - g_menu_insert_section (menu, 0, NULL, chat_section); - } + const gchar *status; - if (first_section != NULL) - g_object_unref (first_section); + status = g_variant_get_string (parameter, NULL); - indicator_messages_update_icon (); + indicator_messages_service_emit_status_changed (messages_service, status); } static void -uses_chat_status_changed (GObject *object, - GParamSpec *pspec, - gpointer user_data) +sources_listed (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - 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; -} + gchar *app_id = user_data; + GVariant *sources; + GVariantIter iter; + const gchar *id; + const gchar *label; + const gchar *iconstr; + guint32 count; + gint64 time; + const gchar *string; + gboolean draws_attention; + GError *error = NULL; -static void -update_chat_status () -{ - GHashTableIter iter; - AppSection *section; - int pos; - GAction *status; - - for (pos = 0; pos < G_N_ELEMENTS (global_status); pos++) - global_status[pos] = NULL; - - pos = 0; - g_hash_table_iter_init (&iter, applications); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) §ion) && - pos < G_N_ELEMENTS (global_status)) + if (!indicator_messages_application_call_list_sources_finish (INDICATOR_MESSAGES_APPLICATION (source_object), + &sources, result, &error)) { - const gchar *status_str = NULL; - - status_str = app_section_get_status (section); - if (status_str != NULL && !strv_contains (global_status, status_str)) - global_status[pos++] = status_str; - } - - if (pos == 0) - global_status[0] = "offline"; - - 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 (global_status, -1)); - - indicator_messages_update_icon (); -} - -static void -chat_status_changed (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - update_chat_status (); -} - -static void -remove_section (AppSection *section, - const gchar *id) -{ - int pos = g_menu_find_section (menu, app_section_get_menu (section)); - if (pos >= 0) - g_menu_remove (menu, pos); - g_action_muxer_remove (action_muxer, id); - - 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); - - if (g_hash_table_size (applications) == 0 && - g_menu_model_get_n_items (G_MENU_MODEL (toplevel_menu)) == 1) { - g_menu_remove (toplevel_menu, 0); - } - - update_chat_status (); - update_chat_section (); -} - -static AppSection * -add_application (const gchar *desktop_id) -{ - GDesktopAppInfo *appinfo; - gchar *id; - AppSection *section; - - appinfo = g_desktop_app_info_new (desktop_id); - if (!appinfo) { - g_warning ("could not add '%s', there's no desktop file with that id", desktop_id); - return NULL; - } - - id = g_app_info_get_simple_id (G_APP_INFO (appinfo)); - section = g_hash_table_lookup (applications, id); - - if (!section) { - GMenuItem *menuitem; - - section = app_section_new(appinfo); - g_hash_table_insert (applications, g_strdup (id), section); - - g_action_muxer_insert (action_muxer, id, app_section_get_actions (section)); - g_signal_connect (section, "notify::actions", - G_CALLBACK (actions_changed), NULL); - g_signal_connect (section, "notify::draws-attention", - 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), - (GClosureNotify) g_free, - 0); - - /* TODO insert it at the right position (alphabetically by application name) */ - menuitem = g_menu_item_new_section (NULL, app_section_get_menu (section)); - g_menu_item_set_attribute (menuitem, "action-namespace", "s", id); - g_menu_insert_item (menu, g_menu_model_get_n_items (G_MENU_MODEL (menu)) -1, menuitem); - g_object_unref (menuitem); + g_warning ("could not fetch the list of sources: %s", error->message); + g_error_free (error); + g_free (app_id); + return; } - if (g_menu_model_get_n_items (G_MENU_MODEL (toplevel_menu)) == 0) { - GMenuItem *header; - - header = g_menu_item_new (NULL, "messages"); - g_menu_item_set_submenu (header, G_MENU_MODEL (menu)); - g_menu_item_set_attribute (header, "x-canonical-accessible-description", "s", _("Messages")); - g_menu_append_item (toplevel_menu, header); - - g_object_unref (header); + g_variant_iter_init (&iter, sources); + while (g_variant_iter_next (&iter, "(&s&s&sux&sb)", &id, &label, &iconstr, &count, + &time, &string, &draws_attention)) + { + GMenuItem *item; + GActionGroup *app_actions; + GSimpleAction *action; + gchar *action_name; + + app_actions = g_action_muxer_get_group (action_muxer, app_id); + g_assert (app_actions); + action = g_simple_action_new_stateful (id, NULL, g_variant_new_uint32 (count)); + g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app_actions), G_ACTION (action)); + + action_name = g_strconcat (app_id, ".", id, NULL); + item = g_menu_item_new (label, action_name); + g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.messages.sourceitem"); + if (iconstr && *iconstr) + g_menu_item_set_attribute (item, "x-canonical-icon", "s", iconstr); + g_menu_append_item (sources_section, item); + + g_object_unref (action); + g_free (action_name); + g_object_unref (item); } - g_free (id); - g_object_unref (appinfo); - return section; + g_variant_unref (sources); + g_free (app_id); } static void -remove_application (const char *desktop_id) +messages_listed (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - GDesktopAppInfo *appinfo; - gchar *id; - AppSection *section; - - appinfo = g_desktop_app_info_new (desktop_id); - if (!appinfo) { - g_warning ("could not remove '%s', there's no desktop file with that id", desktop_id); + gchar *app_id = user_data; + GVariant *messages; + GError *error = NULL; + GVariantIter iter; + const gchar *id; + const gchar *iconstr; + const gchar *title; + const gchar *subtitle; + const gchar *body; + gint64 time; + gboolean draws_attention; + + if (!indicator_messages_application_call_list_messages_finish (INDICATOR_MESSAGES_APPLICATION (source_object), + &messages, result, &error)) + { + g_warning ("could not fetch the list of messages: %s", error->message); + g_error_free (error); + g_free (app_id); return; } - id = g_app_info_get_simple_id (G_APP_INFO (appinfo)); - - section = g_hash_table_lookup (applications, id); - if (section) { - remove_section (section, id); - } - else { - g_warning ("could not remove '%s', it's not registered", desktop_id); - } - - g_free (id); - g_object_unref (appinfo); -} - -/* This function turns a specific desktop id into a menu - item and registers it appropriately with everyone */ -static gboolean -build_launcher (gpointer data) -{ - gchar *desktop_id = data; - - add_application (desktop_id); - - g_free (desktop_id); - return FALSE; -} - -/* This function goes through all the launchers that we're - supposed to be grabbing and decides to show turn them - into menu items or not. It doens't do the work, but it - makes the decision. */ -static gboolean -build_launchers (gpointer data) -{ - gchar **applications = g_settings_get_strv (settings, "applications"); - gchar **app; - - g_return_val_if_fail (applications != NULL, FALSE); - - for (app = applications; *app; app++) + g_variant_iter_init (&iter, messages); + while (g_variant_iter_next (&iter, "(&s&s&s&s&sxb)", &id, &iconstr, &title, &subtitle, &body, + &time, &draws_attention)) { - g_idle_add(build_launcher, g_strdup (*app)); + GMenuItem *item; + GActionGroup *app_actions; + GSimpleAction *action; + gchar *action_name; + + app_actions = g_action_muxer_get_group (action_muxer, app_id); + g_assert (app_actions); + action = g_simple_action_new (id, NULL); + g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app_actions), G_ACTION (action)); + + action_name = g_strconcat (app_id, ".", id, NULL); + item = g_menu_item_new (NULL, action_name); + g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.messages.messageitem"); + g_menu_item_set_attribute (item, "x-canonical-message-id", "s", id); + g_menu_item_set_attribute (item, "x-canonical-sender", "s", title); + g_menu_item_set_attribute (item, "x-canonical-subject", "s", subtitle); + g_menu_item_set_attribute (item, "x-canonical-body", "s", body); + g_menu_item_set_attribute (item, "x-canonical-time", "x", time); + if (iconstr && *iconstr) + g_menu_item_set_attribute (item, "x-canonical-avatar", "s", iconstr); + g_menu_append_item (messages_section, item); + + g_object_unref (action); + g_free (action_name); + g_object_unref (item); } - g_strfreev (applications); - return FALSE; -} - -static void -service_shutdown (IndicatorService * service, gpointer user_data) -{ - GMainLoop *mainloop = user_data; - - g_warning("Shutting down service!"); - g_main_loop_quit(mainloop); + g_variant_unref (messages); + g_free (app_id); } static void -app_section_remove_attention (gpointer key, - gpointer value, - gpointer user_data) +app_proxy_created (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - AppSection *section = value; - app_section_clear_draws_attention (section); -} - -static void -clear_action_activate (GSimpleAction *simple, - GVariant *param, - gpointer user_data) -{ - g_hash_table_foreach (applications, app_section_remove_attention, NULL); -} + gchar *desktop_id = user_data; + IndicatorMessagesApplication *app_proxy; + GError *error = NULL; -static void -status_action_activate (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) -{ - const gchar *status; + app_proxy = indicator_messages_application_proxy_new_finish (result, &error); + if (!app_proxy) { + g_warning ("could not create application proxy: %s", error->message); + g_error_free (error); + return; + } - status = g_variant_get_string (parameter, NULL); + /* hash table takes ownership of desktop_id and app_proxy */ + g_hash_table_insert (applications, desktop_id, app_proxy); - indicator_messages_service_emit_status_changed (messages_service, status); + indicator_messages_application_call_list_sources (app_proxy, NULL, sources_listed, g_strdup (desktop_id)); + indicator_messages_application_call_list_messages (app_proxy, NULL, messages_listed, g_strdup (desktop_id)); } static void @@ -443,21 +259,33 @@ register_application (IndicatorMessagesService *service, const gchar *menu_path, gpointer user_data) { - AppSection *section; GDBusConnection *bus; const gchar *sender; + GSimpleActionGroup *app_actions; - section = add_application (desktop_id); - if (!section) + if (g_hash_table_lookup (applications, desktop_id)) { + g_warning ("application with id '%s' already exists", desktop_id); + g_dbus_method_invocation_return_dbus_error (invocation, + "com.canonical.indicator.messages.ApplicationAlreadyRegistered", + "another application is already registered with this id"); return; + } bus = g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (service)); sender = g_dbus_method_invocation_get_sender (invocation); - app_section_set_object_path (section, bus, sender, menu_path); + indicator_messages_application_proxy_new (bus, G_DBUS_PROXY_FLAGS_NONE, + sender, menu_path, NULL, + app_proxy_created, g_strdup (desktop_id)); + + app_actions = g_simple_action_group_new (); + g_action_muxer_insert (action_muxer, desktop_id, G_ACTION_GROUP (app_actions)); + g_settings_strv_append_unique (settings, "applications", desktop_id); indicator_messages_service_complete_register_application (service, invocation); + + g_object_unref (app_actions); } static void @@ -466,44 +294,15 @@ unregister_application (IndicatorMessagesService *service, const gchar *desktop_id, gpointer user_data) { - remove_application (desktop_id); - g_settings_strv_remove (settings, "applications", desktop_id); + if (g_hash_table_remove (applications, desktop_id)) { - indicator_messages_service_complete_unregister_application (service, invocation); -} + /* TODO remove menu items that refer to this application */ + g_action_muxer_remove (action_muxer, desktop_id); -static void -set_status (IndicatorMessagesService *service, - GDBusMethodInvocation *invocation, - const gchar *desktop_id, - const gchar *status_str, - gpointer user_data) -{ - GDesktopAppInfo *appinfo; - gchar *id; - AppSection *section; - - 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")); - - 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; + g_settings_strv_remove (settings, "applications", desktop_id); } - 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); + indicator_messages_service_complete_unregister_application (service, invocation); } static GSimpleActionGroup * @@ -539,40 +338,6 @@ create_action_group (void) return actions; } -static GMenuModel * -create_status_section (void) -{ - GMenu *menu; - GMenuItem *item; - struct status_item { - gchar *label; - gchar *action; - gchar *icon_name; - } status_items[] = { - { _("Available"), "status::available", "user-available" }, - { _("Away"), "status::away", "user-away" }, - { _("Busy"), "status::busy", "user-busy" }, - { _("Invisible"), "status::invisible", "user-invisible" }, - { _("Offline"), "status::offline", "user-offline" } - }; - int i; - - menu = g_menu_new (); - - item = g_menu_item_new (NULL, NULL); - g_menu_item_set_attribute (item, "x-canonical-type", "s", "IdoMenuItem"); - - for (i = 0; i < G_N_ELEMENTS (status_items); i++) { - g_menu_item_set_label (item, status_items[i].label); - g_menu_item_set_detailed_action (item, status_items[i].action); - g_menu_item_set_attribute (item, "x-canonical-icon", "s", status_items[i].icon_name); - g_menu_append_item (menu, item); - } - - g_object_unref (item); - return G_MENU_MODEL (menu); -} - static void got_bus (GObject *object, GAsyncResult * res, @@ -596,7 +361,7 @@ got_bus (GObject *object, return; } - g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT, + g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT "/phone", G_MENU_MODEL (toplevel_menu), &error); if (error) { g_warning ("unable to export menu on dbus: %s", error->message); @@ -651,26 +416,24 @@ 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 (); - chat_section = create_status_section (); - g_menu_append (menu, _("Clear"), "clear"); + sources_section = g_menu_new (); + messages_section = g_menu_new (); + g_menu_append_section (menu, NULL, G_MENU_MODEL (sources_section)); + g_menu_append_section (menu, NULL, G_MENU_MODEL (messages_section)); toplevel_menu = g_menu_new (); + g_menu_append_submenu (toplevel_menu, NULL, G_MENU_MODEL (menu)); settings = g_settings_new ("com.canonical.indicator.messages"); applications = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - g_idle_add(build_launchers, NULL); - g_main_loop_run(mainloop); /* Clean up */ g_object_unref (messages_service); - g_object_unref (chat_section); g_object_unref (settings); g_hash_table_unref (applications); return 0; -- cgit v1.2.3 From f371bb64a0c6d57d496def504327047ff63b11e2 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 16 Nov 2012 15:05:39 +0100 Subject: Use different menu attributes for the phone menu --- src/messages-service.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 9d64412..81b7f0b 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -209,15 +209,14 @@ messages_listed (GObject *source_object, g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app_actions), G_ACTION (action)); action_name = g_strconcat (app_id, ".", id, NULL); - item = g_menu_item_new (NULL, action_name); + item = g_menu_item_new (title, action_name); g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.messages.messageitem"); g_menu_item_set_attribute (item, "x-canonical-message-id", "s", id); - g_menu_item_set_attribute (item, "x-canonical-sender", "s", title); - g_menu_item_set_attribute (item, "x-canonical-subject", "s", subtitle); - g_menu_item_set_attribute (item, "x-canonical-body", "s", body); + g_menu_item_set_attribute (item, "x-canonical-subtitle", "s", subtitle); + g_menu_item_set_attribute (item, "x-canonical-text", "s", body); g_menu_item_set_attribute (item, "x-canonical-time", "x", time); if (iconstr && *iconstr) - g_menu_item_set_attribute (item, "x-canonical-avatar", "s", iconstr); + g_menu_item_set_attribute (item, "x-canonical-icon", "s", iconstr); g_menu_append_item (messages_section, item); g_object_unref (action); @@ -362,7 +361,7 @@ got_bus (GObject *object, } g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT "/phone", - G_MENU_MODEL (toplevel_menu), &error); + G_MENU_MODEL (menu), &error); if (error) { g_warning ("unable to export menu on dbus: %s", error->message); g_error_free (error); -- cgit v1.2.3 From 6f990698f610eb444845f36a70cad04bca2415f3 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 20 Nov 2012 15:45:03 +0100 Subject: messages-serivce: move menu creation into separate class --- src/messages-service.c | 81 ++++++++++++++++++++------------------------------ 1 file changed, 33 insertions(+), 48 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 81b7f0b..9cd7298 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -34,6 +34,7 @@ with this program. If not, see . #include "gmenuutils.h" #include "indicator-messages-service.h" #include "indicator-messages-application.h" +#include "im-phone-menu.h" #define NUM_STATUSES 5 @@ -43,9 +44,7 @@ static IndicatorMessagesService *messages_service; static GSimpleActionGroup *actions; static GActionMuxer *action_muxer; static GMenu *toplevel_menu; -static GMenu *menu; -static GMenu *messages_section; -static GMenu *sources_section; +static ImPhoneMenu *menu; static GSettings *settings; static gboolean draws_attention; static const gchar *global_status[6]; /* max 5: available, away, busy, invisible, offline */ @@ -117,7 +116,7 @@ sources_listed (GObject *source_object, GAsyncResult *result, gpointer user_data) { - gchar *app_id = user_data; + GDesktopAppInfo *app = user_data; GVariant *sources; GVariantIter iter; const gchar *id; @@ -134,7 +133,7 @@ sources_listed (GObject *source_object, { g_warning ("could not fetch the list of sources: %s", error->message); g_error_free (error); - g_free (app_id); + g_object_unref (app); return; } @@ -142,30 +141,21 @@ sources_listed (GObject *source_object, while (g_variant_iter_next (&iter, "(&s&s&sux&sb)", &id, &label, &iconstr, &count, &time, &string, &draws_attention)) { - GMenuItem *item; GActionGroup *app_actions; GSimpleAction *action; - gchar *action_name; - app_actions = g_action_muxer_get_group (action_muxer, app_id); + app_actions = g_action_muxer_get_group (action_muxer, g_app_info_get_id (G_APP_INFO (app))); g_assert (app_actions); action = g_simple_action_new_stateful (id, NULL, g_variant_new_uint32 (count)); g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app_actions), G_ACTION (action)); - action_name = g_strconcat (app_id, ".", id, NULL); - item = g_menu_item_new (label, action_name); - g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.messages.sourceitem"); - if (iconstr && *iconstr) - g_menu_item_set_attribute (item, "x-canonical-icon", "s", iconstr); - g_menu_append_item (sources_section, item); + im_phone_menu_add_source (menu, app, id, label, iconstr, count, time, string); g_object_unref (action); - g_free (action_name); - g_object_unref (item); } g_variant_unref (sources); - g_free (app_id); + g_object_unref (app); } static void @@ -173,7 +163,7 @@ messages_listed (GObject *source_object, GAsyncResult *result, gpointer user_data) { - gchar *app_id = user_data; + GDesktopAppInfo *app = user_data; GVariant *messages; GError *error = NULL; GVariantIter iter; @@ -190,7 +180,7 @@ messages_listed (GObject *source_object, { g_warning ("could not fetch the list of messages: %s", error->message); g_error_free (error); - g_free (app_id); + g_object_unref (app); return; } @@ -198,34 +188,21 @@ messages_listed (GObject *source_object, while (g_variant_iter_next (&iter, "(&s&s&s&s&sxb)", &id, &iconstr, &title, &subtitle, &body, &time, &draws_attention)) { - GMenuItem *item; GActionGroup *app_actions; GSimpleAction *action; - gchar *action_name; - app_actions = g_action_muxer_get_group (action_muxer, app_id); + app_actions = g_action_muxer_get_group (action_muxer, g_app_info_get_id (G_APP_INFO (app))); g_assert (app_actions); action = g_simple_action_new (id, NULL); g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app_actions), G_ACTION (action)); - action_name = g_strconcat (app_id, ".", id, NULL); - item = g_menu_item_new (title, action_name); - g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.messages.messageitem"); - g_menu_item_set_attribute (item, "x-canonical-message-id", "s", id); - g_menu_item_set_attribute (item, "x-canonical-subtitle", "s", subtitle); - g_menu_item_set_attribute (item, "x-canonical-text", "s", body); - g_menu_item_set_attribute (item, "x-canonical-time", "x", time); - if (iconstr && *iconstr) - g_menu_item_set_attribute (item, "x-canonical-icon", "s", iconstr); - g_menu_append_item (messages_section, item); + im_phone_menu_add_message (menu, app, id, iconstr, title, subtitle, body, time); g_object_unref (action); - g_free (action_name); - g_object_unref (item); } g_variant_unref (messages); - g_free (app_id); + g_object_unref (app); } static void @@ -233,7 +210,7 @@ app_proxy_created (GObject *source_object, GAsyncResult *result, gpointer user_data) { - gchar *desktop_id = user_data; + GDesktopAppInfo *app = user_data; IndicatorMessagesApplication *app_proxy; GError *error = NULL; @@ -244,11 +221,12 @@ app_proxy_created (GObject *source_object, return; } - /* hash table takes ownership of desktop_id and app_proxy */ - g_hash_table_insert (applications, desktop_id, app_proxy); + g_hash_table_insert (applications, (gpointer) g_app_info_get_id (G_APP_INFO (app)), app_proxy); - indicator_messages_application_call_list_sources (app_proxy, NULL, sources_listed, g_strdup (desktop_id)); - indicator_messages_application_call_list_messages (app_proxy, NULL, messages_listed, g_strdup (desktop_id)); + indicator_messages_application_call_list_sources (app_proxy, NULL, sources_listed, g_object_ref (app)); + indicator_messages_application_call_list_messages (app_proxy, NULL, messages_listed, g_object_ref (app)); + + g_object_unref (app); } static void @@ -261,6 +239,7 @@ register_application (IndicatorMessagesService *service, GDBusConnection *bus; const gchar *sender; GSimpleActionGroup *app_actions; + GDesktopAppInfo *app; if (g_hash_table_lookup (applications, desktop_id)) { g_warning ("application with id '%s' already exists", desktop_id); @@ -270,12 +249,21 @@ register_application (IndicatorMessagesService *service, return; } + app = g_desktop_app_info_new (desktop_id); + if (!app) { + g_warning ("application with id '%s' already exists", desktop_id); + g_dbus_method_invocation_return_dbus_error (invocation, + "com.canonical.indicator.messages.UnknownApplication", + "an application with the given id doesn't exist"); + return; + } + bus = g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (service)); sender = g_dbus_method_invocation_get_sender (invocation); indicator_messages_application_proxy_new (bus, G_DBUS_PROXY_FLAGS_NONE, sender, menu_path, NULL, - app_proxy_created, g_strdup (desktop_id)); + app_proxy_created, g_object_ref (app)); app_actions = g_simple_action_group_new (); g_action_muxer_insert (action_muxer, desktop_id, G_ACTION_GROUP (app_actions)); @@ -285,6 +273,7 @@ register_application (IndicatorMessagesService *service, indicator_messages_service_complete_register_application (service, invocation); g_object_unref (app_actions); + g_object_unref (app); } static void @@ -361,7 +350,7 @@ got_bus (GObject *object, } g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT "/phone", - G_MENU_MODEL (menu), &error); + im_phone_menu_get_model (menu), &error); if (error) { g_warning ("unable to export menu on dbus: %s", error->message); g_error_free (error); @@ -416,14 +405,10 @@ main (int argc, char ** argv) g_signal_connect (messages_service, "handle-unregister-application", G_CALLBACK (unregister_application), NULL); - menu = g_menu_new (); - sources_section = g_menu_new (); - messages_section = g_menu_new (); - g_menu_append_section (menu, NULL, G_MENU_MODEL (sources_section)); - g_menu_append_section (menu, NULL, G_MENU_MODEL (messages_section)); + menu = im_phone_menu_new (); toplevel_menu = g_menu_new (); - g_menu_append_submenu (toplevel_menu, NULL, G_MENU_MODEL (menu)); + g_menu_append_submenu (toplevel_menu, NULL, im_phone_menu_get_model (menu)); settings = g_settings_new ("com.canonical.indicator.messages"); -- cgit v1.2.3 From 2021da310c84d28efcf9bb359b7a8f7065743267 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 20 Nov 2012 22:20:23 +0100 Subject: messages-service: move app handling into separate class Add ImApplicationList, a class that manages the list of applictions that are currently registered with the messaging menu. It creates dbus proxies for running applications and sends signals when the app adds messages or sources. --- src/messages-service.c | 176 +++++-------------------------------------------- 1 file changed, 16 insertions(+), 160 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 9cd7298..a65e2d8 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -25,24 +25,22 @@ with this program. If not, see . #include #include #include -#include #include #include "dbus-data.h" -#include "gactionmuxer.h" #include "gsettingsstrv.h" #include "gmenuutils.h" #include "indicator-messages-service.h" #include "indicator-messages-application.h" #include "im-phone-menu.h" +#include "im-application-list.h" #define NUM_STATUSES 5 -static GHashTable *applications; +static ImApplicationList *applications; static IndicatorMessagesService *messages_service; static GSimpleActionGroup *actions; -static GActionMuxer *action_muxer; static GMenu *toplevel_menu; static ImPhoneMenu *menu; static GSettings *settings; @@ -111,124 +109,6 @@ status_action_activate (GSimpleAction *action, indicator_messages_service_emit_status_changed (messages_service, status); } -static void -sources_listed (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - GDesktopAppInfo *app = user_data; - GVariant *sources; - GVariantIter iter; - const gchar *id; - const gchar *label; - const gchar *iconstr; - guint32 count; - gint64 time; - const gchar *string; - gboolean draws_attention; - GError *error = NULL; - - if (!indicator_messages_application_call_list_sources_finish (INDICATOR_MESSAGES_APPLICATION (source_object), - &sources, result, &error)) - { - g_warning ("could not fetch the list of sources: %s", error->message); - g_error_free (error); - g_object_unref (app); - return; - } - - g_variant_iter_init (&iter, sources); - while (g_variant_iter_next (&iter, "(&s&s&sux&sb)", &id, &label, &iconstr, &count, - &time, &string, &draws_attention)) - { - GActionGroup *app_actions; - GSimpleAction *action; - - app_actions = g_action_muxer_get_group (action_muxer, g_app_info_get_id (G_APP_INFO (app))); - g_assert (app_actions); - action = g_simple_action_new_stateful (id, NULL, g_variant_new_uint32 (count)); - g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app_actions), G_ACTION (action)); - - im_phone_menu_add_source (menu, app, id, label, iconstr, count, time, string); - - g_object_unref (action); - } - - g_variant_unref (sources); - g_object_unref (app); -} - -static void -messages_listed (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - GDesktopAppInfo *app = user_data; - GVariant *messages; - GError *error = NULL; - GVariantIter iter; - const gchar *id; - const gchar *iconstr; - const gchar *title; - const gchar *subtitle; - const gchar *body; - gint64 time; - gboolean draws_attention; - - if (!indicator_messages_application_call_list_messages_finish (INDICATOR_MESSAGES_APPLICATION (source_object), - &messages, result, &error)) - { - g_warning ("could not fetch the list of messages: %s", error->message); - g_error_free (error); - g_object_unref (app); - return; - } - - g_variant_iter_init (&iter, messages); - while (g_variant_iter_next (&iter, "(&s&s&s&s&sxb)", &id, &iconstr, &title, &subtitle, &body, - &time, &draws_attention)) - { - GActionGroup *app_actions; - GSimpleAction *action; - - app_actions = g_action_muxer_get_group (action_muxer, g_app_info_get_id (G_APP_INFO (app))); - g_assert (app_actions); - action = g_simple_action_new (id, NULL); - g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app_actions), G_ACTION (action)); - - im_phone_menu_add_message (menu, app, id, iconstr, title, subtitle, body, time); - - g_object_unref (action); - } - - g_variant_unref (messages); - g_object_unref (app); -} - -static void -app_proxy_created (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - GDesktopAppInfo *app = user_data; - IndicatorMessagesApplication *app_proxy; - GError *error = NULL; - - app_proxy = indicator_messages_application_proxy_new_finish (result, &error); - if (!app_proxy) { - g_warning ("could not create application proxy: %s", error->message); - g_error_free (error); - return; - } - - g_hash_table_insert (applications, (gpointer) g_app_info_get_id (G_APP_INFO (app)), app_proxy); - - indicator_messages_application_call_list_sources (app_proxy, NULL, sources_listed, g_object_ref (app)); - indicator_messages_application_call_list_messages (app_proxy, NULL, messages_listed, g_object_ref (app)); - - g_object_unref (app); -} - static void register_application (IndicatorMessagesService *service, GDBusMethodInvocation *invocation, @@ -238,42 +118,21 @@ register_application (IndicatorMessagesService *service, { GDBusConnection *bus; const gchar *sender; - GSimpleActionGroup *app_actions; - GDesktopAppInfo *app; - - if (g_hash_table_lookup (applications, desktop_id)) { - g_warning ("application with id '%s' already exists", desktop_id); - g_dbus_method_invocation_return_dbus_error (invocation, - "com.canonical.indicator.messages.ApplicationAlreadyRegistered", - "another application is already registered with this id"); - return; - } - app = g_desktop_app_info_new (desktop_id); - if (!app) { - g_warning ("application with id '%s' already exists", desktop_id); + if (!im_application_list_add (applications, desktop_id)) { g_dbus_method_invocation_return_dbus_error (invocation, - "com.canonical.indicator.messages.UnknownApplication", - "an application with the given id doesn't exist"); + "com.canonical.indicator.messages.RegistrationFailed", + "registration failed"); return; } bus = g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (service)); sender = g_dbus_method_invocation_get_sender (invocation); - indicator_messages_application_proxy_new (bus, G_DBUS_PROXY_FLAGS_NONE, - sender, menu_path, NULL, - app_proxy_created, g_object_ref (app)); - - app_actions = g_simple_action_group_new (); - g_action_muxer_insert (action_muxer, desktop_id, G_ACTION_GROUP (app_actions)); - + im_application_list_set_remote (applications, desktop_id, bus, sender, menu_path); g_settings_strv_append_unique (settings, "applications", desktop_id); indicator_messages_service_complete_register_application (service, invocation); - - g_object_unref (app_actions); - g_object_unref (app); } static void @@ -282,13 +141,8 @@ unregister_application (IndicatorMessagesService *service, const gchar *desktop_id, gpointer user_data) { - if (g_hash_table_remove (applications, desktop_id)) { - - /* TODO remove menu items that refer to this application */ - g_action_muxer_remove (action_muxer, desktop_id); - - g_settings_strv_remove (settings, "applications", desktop_id); - } + im_application_list_remove (applications, desktop_id); + g_settings_strv_remove (settings, "applications", desktop_id); indicator_messages_service_complete_unregister_application (service, invocation); } @@ -342,7 +196,8 @@ got_bus (GObject *object, } g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT, - G_ACTION_GROUP (action_muxer), &error); + im_application_list_get_action_group (applications), + &error); if (error) { g_warning ("unable to export action group on dbus: %s", error->message); g_error_free (error); @@ -397,9 +252,6 @@ main (int argc, char ** argv) actions = create_action_group (); - action_muxer = g_action_muxer_new (); - g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); - g_signal_connect (messages_service, "handle-register-application", G_CALLBACK (register_application), NULL); g_signal_connect (messages_service, "handle-unregister-application", @@ -412,13 +264,17 @@ main (int argc, char ** argv) settings = g_settings_new ("com.canonical.indicator.messages"); - applications = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + applications = im_application_list_new (); + g_signal_connect_swapped (applications, "source-added", + G_CALLBACK (im_phone_menu_add_source), menu); + g_signal_connect_swapped (applications, "message-added", + G_CALLBACK (im_phone_menu_add_message), menu); g_main_loop_run(mainloop); /* Clean up */ g_object_unref (messages_service); g_object_unref (settings); - g_hash_table_unref (applications); + g_object_unref (applications); return 0; } -- cgit v1.2.3 From 717f9be0d9319ed4aa680c77aa2a30318da10fda Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 20 Nov 2012 23:14:48 +0100 Subject: ImApplicationList: listen for added and removed signals --- src/messages-service.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index a65e2d8..467224d 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -267,8 +267,12 @@ main (int argc, char ** argv) applications = im_application_list_new (); g_signal_connect_swapped (applications, "source-added", G_CALLBACK (im_phone_menu_add_source), menu); + g_signal_connect_swapped (applications, "source-removed", + G_CALLBACK (im_phone_menu_remove_source), menu); g_signal_connect_swapped (applications, "message-added", G_CALLBACK (im_phone_menu_add_message), menu); + g_signal_connect_swapped (applications, "message-removed", + G_CALLBACK (im_phone_menu_remove_message), menu); g_main_loop_run(mainloop); -- cgit v1.2.3 From d22b49e5fee5ae352ec6050e63181850a857fb3a Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 21 Nov 2012 00:02:12 +0100 Subject: Remove applications from the menu when the disappear from the bus --- src/messages-service.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 467224d..18f3d0a 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -273,6 +273,8 @@ main (int argc, char ** argv) G_CALLBACK (im_phone_menu_add_message), menu); g_signal_connect_swapped (applications, "message-removed", G_CALLBACK (im_phone_menu_remove_message), menu); + g_signal_connect_swapped (applications, "app-stopped", + G_CALLBACK (im_phone_menu_remove_application), menu); g_main_loop_run(mainloop); -- cgit v1.2.3 From 1d96aab069071bd6f73b3be8beb40ca25d37fa86 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 21 Nov 2012 00:16:44 +0100 Subject: Replace app when another process is registering with the same id --- src/messages-service.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 18f3d0a..b3731a8 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -119,12 +119,7 @@ register_application (IndicatorMessagesService *service, GDBusConnection *bus; const gchar *sender; - if (!im_application_list_add (applications, desktop_id)) { - g_dbus_method_invocation_return_dbus_error (invocation, - "com.canonical.indicator.messages.RegistrationFailed", - "registration failed"); - return; - } + im_application_list_add (applications, desktop_id); bus = g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (service)); sender = g_dbus_method_invocation_get_sender (invocation); -- cgit v1.2.3 From 83598a9e4fe059703faa806e7a9cdab1e6cb293c Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 28 Nov 2012 13:29:15 +0100 Subject: Add root menu item The action for that root item lives in ImApplicationList for now, because it owns the action group (which should probably factored into its own class at some point). --- src/messages-service.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index b3731a8..62abc81 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -200,7 +200,7 @@ got_bus (GObject *object, } g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT "/phone", - im_phone_menu_get_model (menu), &error); + G_MENU_MODEL (toplevel_menu), &error); if (error) { g_warning ("unable to export menu on dbus: %s", error->message); g_error_free (error); @@ -224,6 +224,7 @@ main (int argc, char ** argv) { GMainLoop * mainloop = NULL; IndicatorService * service = NULL; + GMenuItem *root; /* Glib init */ g_type_init(); @@ -255,7 +256,9 @@ main (int argc, char ** argv) menu = im_phone_menu_new (); toplevel_menu = g_menu_new (); - g_menu_append_submenu (toplevel_menu, NULL, im_phone_menu_get_model (menu)); + root = g_menu_item_new (NULL, "messages"); + g_menu_item_set_submenu (root, im_phone_menu_get_model (menu)); + g_menu_append_item (toplevel_menu, root); settings = g_settings_new ("com.canonical.indicator.messages"); @@ -274,6 +277,7 @@ main (int argc, char ** argv) g_main_loop_run(mainloop); /* Clean up */ + g_object_unref (root); g_object_unref (messages_service); g_object_unref (settings); g_object_unref (applications); -- cgit v1.2.3 From 8ff464d1a1d99e016b4719f090816c2c6f712abb Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 28 Nov 2012 13:42:34 +0100 Subject: messages-service.c: remove chat status action It isn't used right now (the action group wasn't even exported on the bus) and would need to be refactored anyway once chat status is added back in. --- src/messages-service.c | 91 -------------------------------------------------- 1 file changed, 91 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 62abc81..6b8f26b 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -40,45 +40,9 @@ with this program. If not, see . static ImApplicationList *applications; static IndicatorMessagesService *messages_service; -static GSimpleActionGroup *actions; static GMenu *toplevel_menu; static ImPhoneMenu *menu; static GSettings *settings; -static gboolean draws_attention; -static const gchar *global_status[6]; /* max 5: available, away, busy, invisible, offline */ - -static gchar * -indicator_messages_get_icon_name () -{ - GString *name; - GIcon *icon; - gchar *iconstr; - - name = g_string_new ("indicator-messages"); - - if (global_status[0] != NULL) - { - if (global_status[1] != NULL) - g_string_append (name, "-mixed"); - else - g_string_append_printf (name, "-%s", global_status[0]); - } - - if (draws_attention) - g_string_append (name, "-new"); - - icon = g_themed_icon_new (name->str); - g_themed_icon_append_name (G_THEMED_ICON (icon), - draws_attention ? "indicator-messages-new" - : "indicator-messages"); - - iconstr = g_icon_to_string (icon); - - g_object_unref (icon); - g_string_free (name, TRUE); - - return iconstr; -} static void service_shutdown (IndicatorService * service, gpointer user_data) @@ -89,26 +53,6 @@ service_shutdown (IndicatorService * service, gpointer user_data) g_main_loop_quit(mainloop); } -static void -clear_action_activate (GSimpleAction *simple, - GVariant *param, - gpointer user_data) -{ - /* TODO */ -} - -static void -status_action_activate (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) -{ - const gchar *status; - - status = g_variant_get_string (parameter, NULL); - - indicator_messages_service_emit_status_changed (messages_service, status); -} - static void register_application (IndicatorMessagesService *service, GDBusMethodInvocation *invocation, @@ -142,39 +86,6 @@ unregister_application (IndicatorMessagesService *service, indicator_messages_service_complete_unregister_application (service, invocation); } -static GSimpleActionGroup * -create_action_group (void) -{ - GSimpleActionGroup *actions; - GSimpleAction *messages; - GSimpleAction *clear; - GSimpleAction *status; - const gchar *default_status[] = { "offline", NULL }; - gchar *icon; - - actions = g_simple_action_group_new (); - - /* state of the messages action is its icon name */ - icon = indicator_messages_get_icon_name (); - messages = g_simple_action_new_stateful ("messages", G_VARIANT_TYPE ("s"), - g_variant_new_string (icon)); - - status = g_simple_action_new_stateful ("status", G_VARIANT_TYPE ("s"), - 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); - g_signal_connect (clear, "activate", G_CALLBACK (clear_action_activate), NULL); - - g_simple_action_group_insert (actions, G_ACTION (messages)); - g_simple_action_group_insert (actions, G_ACTION (status)); - g_simple_action_group_insert (actions, G_ACTION (clear)); - - g_free (icon); - return actions; -} - static void got_bus (GObject *object, GAsyncResult * res, @@ -246,8 +157,6 @@ main (int argc, char ** argv) g_bus_get (G_BUS_TYPE_SESSION, NULL, got_bus, NULL); - actions = create_action_group (); - g_signal_connect (messages_service, "handle-register-application", G_CALLBACK (register_application), NULL); g_signal_connect (messages_service, "handle-unregister-application", -- cgit v1.2.3 From 5c7569e03d770c5f29b0011b2b0ad04f0be2ff88 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 28 Nov 2012 14:09:26 +0100 Subject: Add x-canonical-type to the root item --- src/messages-service.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 6b8f26b..61e786f 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -166,6 +166,7 @@ main (int argc, char ** argv) toplevel_menu = g_menu_new (); root = g_menu_item_new (NULL, "messages"); + g_menu_item_set_attribute (root, "x-canonical-type", "s", "com.canonical.indicator.root"); g_menu_item_set_submenu (root, im_phone_menu_get_model (menu)); g_menu_append_item (toplevel_menu, root); -- cgit v1.2.3 From c21c6e9a3e204bccae7b9a30c56845cbc45661ff Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 3 Dec 2012 15:42:46 +0000 Subject: Stop using IndicatorService This doesn't require every consumer ("panel") to know about IndicatorServiceManager's protocol. Also, it ensures that objects are exported before the name is acquired, getting rid of a race condition (when a consumer tries to access objects in NameAppeared before they're exported). This patch also adds a --replace command line option -- replacing the INDICATOR_SERVICE_REPLACE_MODE environment variable. --- src/messages-service.c | 47 ++++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 61e786f..d10e98a 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -23,7 +23,6 @@ with this program. If not, see . #include #include -#include #include #include @@ -44,15 +43,6 @@ static GMenu *toplevel_menu; static ImPhoneMenu *menu; static GSettings *settings; -static void -service_shutdown (IndicatorService * service, gpointer user_data) -{ - GMainLoop *mainloop = user_data; - - g_warning("Shutting down service!"); - g_main_loop_quit(mainloop); -} - static void register_application (IndicatorMessagesService *service, GDBusMethodInvocation *invocation, @@ -87,20 +77,12 @@ unregister_application (IndicatorMessagesService *service, } static void -got_bus (GObject *object, - GAsyncResult * res, - gpointer user_data) +on_bus_acquired (GDBusConnection *bus, + const gchar *name, + gpointer user_data) { - GDBusConnection *bus; GError *error = NULL; - bus = g_bus_get_finish (res, &error); - if (!bus) { - g_warning ("unable to connect to the session bus: %s", error->message); - g_error_free (error); - return; - } - g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT, im_application_list_get_action_group (applications), &error); @@ -130,22 +112,28 @@ got_bus (GObject *object, g_object_unref (bus); } +static void +on_name_lost (GDBusConnection *bus, + const gchar *name, + gpointer user_data) +{ + GMainLoop *mainloop = user_data; + + g_main_loop_quit (mainloop); +} + int main (int argc, char ** argv) { GMainLoop * mainloop = NULL; - IndicatorService * service = NULL; GMenuItem *root; + GBusNameOwnerFlags flags; /* Glib init */ g_type_init(); mainloop = g_main_loop_new (NULL, FALSE); - /* Create the Indicator Service interface */ - service = indicator_service_new_version(INDICATOR_MESSAGES_DBUS_NAME, 1); - g_signal_connect(service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), mainloop); - /* Setting up i18n and gettext. Apparently, we need all of these. */ setlocale (LC_ALL, ""); @@ -155,7 +143,12 @@ main (int argc, char ** argv) /* Bring up the service DBus interface */ messages_service = indicator_messages_service_skeleton_new (); - g_bus_get (G_BUS_TYPE_SESSION, NULL, got_bus, NULL); + flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; + if (argc >= 2 && g_str_equal (argv[1], "--replace")) + flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; + + g_bus_own_name (G_BUS_TYPE_SESSION, "com.canonical.indicator.messages", flags, + on_bus_acquired, NULL, on_name_lost, mainloop, NULL); g_signal_connect (messages_service, "handle-register-application", G_CALLBACK (register_application), NULL); -- cgit v1.2.3 From e5caa5032da9e5cd41876934f9073e1f3646edd5 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 10 Dec 2012 14:30:10 +0100 Subject: Don't show sources in the phone menu --- src/messages-service.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index d10e98a..27bce4e 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -166,10 +166,6 @@ main (int argc, char ** argv) settings = g_settings_new ("com.canonical.indicator.messages"); applications = im_application_list_new (); - g_signal_connect_swapped (applications, "source-added", - G_CALLBACK (im_phone_menu_add_source), menu); - g_signal_connect_swapped (applications, "source-removed", - G_CALLBACK (im_phone_menu_remove_source), menu); g_signal_connect_swapped (applications, "message-added", G_CALLBACK (im_phone_menu_add_message), menu); g_signal_connect_swapped (applications, "message-removed", -- cgit v1.2.3 From dd756106c02cabc79c7429e42ff6658bd37bba6c Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 20 Dec 2012 17:46:15 +0100 Subject: ImApplicationList: add "remove-all" signal This is a temporary hack to work around a crash in QMenuModel. --- src/messages-service.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 27bce4e..c2ca1a0 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -172,6 +172,8 @@ main (int argc, char ** argv) G_CALLBACK (im_phone_menu_remove_message), menu); g_signal_connect_swapped (applications, "app-stopped", G_CALLBACK (im_phone_menu_remove_application), menu); + g_signal_connect_swapped (applications, "remove-all", + G_CALLBACK (im_phone_menu_remove_all), menu); g_main_loop_run(mainloop); -- cgit v1.2.3 From 5e3abf725e0628673c1bb16869edc67dfa7e2729 Mon Sep 17 00:00:00 2001 From: Sergio Schvezov Date: Fri, 22 Mar 2013 16:54:38 -0300 Subject: Adding glib version guard to g_type_init --- src/messages-service.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index c2ca1a0..5f320fc 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -130,7 +130,9 @@ main (int argc, char ** argv) GBusNameOwnerFlags flags; /* Glib init */ +#if G_ENCODE_VERSION(GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION) <= GLIB_VERSION_2_34 g_type_init(); +#endif mainloop = g_main_loop_new (NULL, FALSE); -- cgit v1.2.3 From 769affeef08a04881a5a84aa5c2db2caedf70646 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 31 Jul 2013 09:55:32 +0200 Subject: Prefix action names with "indicator." --- src/messages-service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 5f320fc..94d6d29 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -160,7 +160,7 @@ main (int argc, char ** argv) menu = im_phone_menu_new (); toplevel_menu = g_menu_new (); - root = g_menu_item_new (NULL, "messages"); + root = g_menu_item_new (NULL, "indicator.messages"); g_menu_item_set_attribute (root, "x-canonical-type", "s", "com.canonical.indicator.root"); g_menu_item_set_submenu (root, im_phone_menu_get_model (menu)); g_menu_append_item (toplevel_menu, root); -- cgit v1.2.3 From ff4aefe6c8d9c36881f26c2cf8514c2ce1f3edca Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 12 Aug 2013 21:19:42 +0200 Subject: Add ImMenu A base class for all messaging menus. ImPhoneMenu already subclasses from it, with a desktop version coming up. --- src/messages-service.c | 45 +++++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 26 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 94d6d29..781e261 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -39,8 +39,7 @@ with this program. If not, see . static ImApplicationList *applications; static IndicatorMessagesService *messages_service; -static GMenu *toplevel_menu; -static ImPhoneMenu *menu; +static GHashTable *menus; static GSettings *settings; static void @@ -82,6 +81,9 @@ on_bus_acquired (GDBusConnection *bus, gpointer user_data) { GError *error = NULL; + GHashTableIter it; + const gchar *profile; + ImMenu *menu; g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT, im_application_list_get_action_group (applications), @@ -92,12 +94,17 @@ on_bus_acquired (GDBusConnection *bus, return; } - g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT "/phone", - G_MENU_MODEL (toplevel_menu), &error); - if (error) { - g_warning ("unable to export menu on dbus: %s", error->message); - g_error_free (error); - return; + g_hash_table_iter_init (&it, menus); + while (g_hash_table_iter_next (&it, (gpointer *) &profile, (gpointer *) &menu)) { + gchar *object_path; + + object_path = g_strconcat (INDICATOR_MESSAGES_DBUS_OBJECT, "/", profile, NULL); + if (!im_menu_export (menu, bus, object_path, &error)) { + g_warning ("unable to export menu for profile '%s': %s", profile, error->message); + g_clear_error (&error); + } + + g_free (object_path); } g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (messages_service), @@ -126,7 +133,6 @@ int main (int argc, char ** argv) { GMainLoop * mainloop = NULL; - GMenuItem *root; GBusNameOwnerFlags flags; /* Glib init */ @@ -157,30 +163,17 @@ main (int argc, char ** argv) g_signal_connect (messages_service, "handle-unregister-application", G_CALLBACK (unregister_application), NULL); - menu = im_phone_menu_new (); - - toplevel_menu = g_menu_new (); - root = g_menu_item_new (NULL, "indicator.messages"); - g_menu_item_set_attribute (root, "x-canonical-type", "s", "com.canonical.indicator.root"); - g_menu_item_set_submenu (root, im_phone_menu_get_model (menu)); - g_menu_append_item (toplevel_menu, root); - settings = g_settings_new ("com.canonical.indicator.messages"); applications = im_application_list_new (); - g_signal_connect_swapped (applications, "message-added", - G_CALLBACK (im_phone_menu_add_message), menu); - g_signal_connect_swapped (applications, "message-removed", - G_CALLBACK (im_phone_menu_remove_message), menu); - g_signal_connect_swapped (applications, "app-stopped", - G_CALLBACK (im_phone_menu_remove_application), menu); - g_signal_connect_swapped (applications, "remove-all", - G_CALLBACK (im_phone_menu_remove_all), menu); + + menus = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); + g_hash_table_insert (menus, "phone", im_phone_menu_new (applications)); g_main_loop_run(mainloop); /* Clean up */ - g_object_unref (root); + g_hash_table_unref (menus); g_object_unref (messages_service); g_object_unref (settings); g_object_unref (applications); -- cgit v1.2.3 From 046ef6f5581ab2634d5ef097e6c449316c2404bf Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 13 Aug 2013 09:43:22 +0200 Subject: Add desktop menu Only shows application launchers right now. --- src/messages-service.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 781e261..efe9602 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -32,6 +32,7 @@ with this program. If not, see . #include "indicator-messages-service.h" #include "indicator-messages-application.h" #include "im-phone-menu.h" +#include "im-desktop-menu.h" #include "im-application-list.h" #define NUM_STATUSES 5 @@ -169,6 +170,7 @@ main (int argc, char ** argv) menus = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); g_hash_table_insert (menus, "phone", im_phone_menu_new (applications)); + g_hash_table_insert (menus, "desktop", im_desktop_menu_new (applications)); g_main_loop_run(mainloop); -- cgit v1.2.3 From ed16f39ed4e571bb75005453b5af33ab737deb6c Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 13 Aug 2013 16:04:34 +0200 Subject: application list: show non-running applications --- src/messages-service.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index efe9602..3d4bcca 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -164,9 +164,19 @@ main (int argc, char ** argv) g_signal_connect (messages_service, "handle-unregister-application", G_CALLBACK (unregister_application), NULL); + applications = im_application_list_new (); + settings = g_settings_new ("com.canonical.indicator.messages"); + { + gchar **app_ids; + gchar **id; - applications = im_application_list_new (); + app_ids = g_settings_get_strv (settings, "applications"); + for (id = app_ids; *id; id++) + im_application_list_add (applications, *id); + + g_strfreev (app_ids); + } menus = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); g_hash_table_insert (menus, "phone", im_phone_menu_new (applications)); -- cgit v1.2.3 From 3baa8097f77fc731b3cbbc83f766d90020b32d6e Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Wed, 14 Aug 2013 23:06:23 -0500 Subject: React to the set-status call on dbus and pass that down to the menus --- src/messages-service.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 3d4bcca..92a3f99 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -76,6 +76,44 @@ unregister_application (IndicatorMessagesService *service, indicator_messages_service_complete_unregister_application (service, invocation); } +static void +set_status (IndicatorMessagesService *service, + GDBusMethodInvocation *invocation, + const gchar *desktop_id, + const gchar *status_str, + gpointer user_data) +{ + GDesktopAppInfo *appinfo; + const gchar *id; + GList * menulist, * menu; + + 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")); + + 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_id (G_APP_INFO (appinfo)); + + menulist = g_hash_table_get_values(menus); + for (menu = menulist; menu != NULL; menu = g_list_next(menu)) { + ImMenu * immenu = IM_MENU(menu->data); + im_menu_set_status(immenu, id, status_str); + } + + indicator_messages_service_complete_set_status (service, invocation); + + g_object_unref (appinfo); + g_list_free(menulist); +} + + static void on_bus_acquired (GDBusConnection *bus, const gchar *name, @@ -163,6 +201,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); applications = im_application_list_new (); -- cgit v1.2.3 From 194c8bf9e07b10fb4857aeb5366b3aaee07dd9a2 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 15 Aug 2013 12:50:16 -0500 Subject: Really we should set status on the application list --- src/messages-service.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 92a3f99..6423cd5 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -85,7 +85,6 @@ set_status (IndicatorMessagesService *service, { GDesktopAppInfo *appinfo; const gchar *id; - GList * menulist, * menu; g_return_if_fail (g_str_equal (status_str, "available") || g_str_equal (status_str, "away")|| @@ -101,16 +100,11 @@ set_status (IndicatorMessagesService *service, id = g_app_info_get_id (G_APP_INFO (appinfo)); - menulist = g_hash_table_get_values(menus); - for (menu = menulist; menu != NULL; menu = g_list_next(menu)) { - ImMenu * immenu = IM_MENU(menu->data); - im_menu_set_status(immenu, id, status_str); - } + im_application_list_set_status(applications, id, status_str); indicator_messages_service_complete_set_status (service, invocation); g_object_unref (appinfo); - g_list_free(menulist); } -- cgit v1.2.3 From 190841b5d7262d9619c618e19bcb08e30968fd41 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 15 Aug 2013 15:32:36 -0500 Subject: Emit to dbus when the status changes --- src/messages-service.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 6423cd5..71fa09b 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -107,6 +107,13 @@ set_status (IndicatorMessagesService *service, g_object_unref (appinfo); } +/* The status has been set by the user, let's tell the world! */ +static void +status_set_by_user (ImApplicationList * list, const gchar * status, gpointer user_data) +{ + indicator_messages_service_emit_status_changed(messages_service, status); + return; +} static void on_bus_acquired (GDBusConnection *bus, @@ -199,6 +206,8 @@ main (int argc, char ** argv) G_CALLBACK (set_status), NULL); applications = im_application_list_new (); + g_signal_connect (applications, "status-set", + G_CALLBACK (status_set_by_user), NULL); settings = g_settings_new ("com.canonical.indicator.messages"); { -- cgit v1.2.3