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/im-application-list.c | 348 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 src/im-application-list.c (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c new file mode 100644 index 0000000..33f06ab --- /dev/null +++ b/src/im-application-list.c @@ -0,0 +1,348 @@ +/* + * Copyright 2012 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Lars Uebernickel + */ + +#include "im-application-list.h" + +#include "indicator-messages-application.h" +#include "gactionmuxer.h" + +#include + +typedef GObjectClass ImApplicationListClass; + +struct _ImApplicationList +{ + GObject parent; + + GHashTable *applications; + GActionMuxer *muxer; +}; + +G_DEFINE_TYPE (ImApplicationList, im_application_list, G_TYPE_OBJECT); + +enum +{ + SOURCE_ADDED, + MESSAGE_ADDED, + N_SIGNALS +}; + +static guint signals[N_SIGNALS]; + +typedef struct +{ + ImApplicationList *list; + GDesktopAppInfo *info; + IndicatorMessagesApplication *proxy; + GSimpleActionGroup *actions; + GCancellable *cancellable; +} Application; + +static void +application_free (gpointer data) +{ + Application *app = data; + + if (!app) + return; + + g_clear_object (&app->info); + + if (app->cancellable) + { + g_cancellable_cancel (app->cancellable); + g_clear_object (&app->cancellable); + } + + if (app->proxy) + g_object_unref (app->proxy); + + if (app->actions) + g_object_unref (app->actions); + + g_slice_free (Application, app); +} + +static void +im_application_list_dispose (GObject *object) +{ + ImApplicationList *list = IM_APPLICATION_LIST (object); + + g_clear_pointer (&list->applications, g_hash_table_unref); + g_clear_object (&list->muxer); + + G_OBJECT_CLASS (im_application_list_parent_class)->dispose (object); +} + +static void +im_application_list_finalize (GObject *object) +{ + G_OBJECT_CLASS (im_application_list_parent_class)->finalize (object); +} + +static void +im_application_list_class_init (ImApplicationListClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = im_application_list_dispose; + object_class->finalize = im_application_list_finalize; + + signals[SOURCE_ADDED] = g_signal_new ("source-added", + IM_TYPE_APPLICATION_LIST, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 8, + G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_UINT, + G_TYPE_INT64, + G_TYPE_STRING, + G_TYPE_BOOLEAN); + + signals[MESSAGE_ADDED] = g_signal_new ("message-added", + IM_TYPE_APPLICATION_LIST, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 8, + G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_INT64, + G_TYPE_BOOLEAN); +} + +static void +im_application_list_init (ImApplicationList *list) +{ + list->applications = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, application_free); + list->muxer = g_action_muxer_new (); +} + +ImApplicationList * +im_application_list_new (void) +{ + return g_object_new (IM_TYPE_APPLICATION_LIST, NULL); +} + +gboolean +im_application_list_add (ImApplicationList *list, + const gchar *desktop_id) +{ + GDesktopAppInfo *info; + Application *app; + const gchar *id; + + g_return_val_if_fail (IM_IS_APPLICATION_LIST (list), FALSE); + g_return_val_if_fail (desktop_id != NULL, FALSE); + + if (g_hash_table_contains (list->applications, desktop_id)) + { + g_warning ("an application with id '%s' already exists", desktop_id); + return FALSE; + } + + info = g_desktop_app_info_new (desktop_id); + if (!info) + { + g_warning ("application with id '%s' already exists", desktop_id); + return FALSE; + } + + id = g_app_info_get_id (G_APP_INFO (info)); + + app = g_slice_new0 (Application); + app->list = list; + app->info = info; + app->actions = g_simple_action_group_new (); + + g_hash_table_insert (list->applications, (gpointer) id, app); + g_action_muxer_insert (list->muxer, id, G_ACTION_GROUP (app->actions)); + + return TRUE; +} + +void +im_application_list_remove (ImApplicationList *list, + const gchar *id) +{ + g_return_if_fail (IM_IS_APPLICATION_LIST (list)); + + g_hash_table_remove (list->applications, id); + g_action_muxer_remove (list->muxer, id); +} + +static void +im_application_list_sources_listed (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + Application *app = user_data; + GVariant *sources; + GError *error = NULL; + + if (indicator_messages_application_call_list_sources_finish (app->proxy, &sources, result, &error)) + { + GVariantIter iter; + const gchar *id; + const gchar *label; + const gchar *iconstr; + guint32 count; + gint64 time; + const gchar *string; + gboolean draws_attention; + + g_variant_iter_init (&iter, sources); + while (g_variant_iter_next (&iter, "(&s&s&sux&sb)", &id, &label, &iconstr, &count, + &time, &string, &draws_attention)) + { + GSimpleAction *action; + + action = g_simple_action_new_stateful (id, NULL, g_variant_new_uint32 (count)); + g_simple_action_group_insert (app->actions, G_ACTION (action)); + + g_signal_emit (app->list, signals[SOURCE_ADDED], 0, + app->info, id, label, iconstr, count, time, string, draws_attention); + + g_object_unref (action); + } + g_variant_unref (sources); + } + else + { + g_warning ("could not fetch the list of sources: %s", error->message); + g_error_free (error); + } +} + +static void +im_application_list_messages_listed (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + Application *app = user_data; + GVariant *messages; + GError *error = NULL; + + if (indicator_messages_application_call_list_messages_finish (app->proxy, &messages, result, &error)) + { + GVariantIter iter; + const gchar *id; + const gchar *iconstr; + const gchar *title; + const gchar *subtitle; + const gchar *body; + gint64 time; + gboolean draws_attention; + + 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)) + { + GSimpleAction *action; + + action = g_simple_action_new (id, NULL); + g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app->actions), G_ACTION (action)); + + g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, + app->info, id, iconstr, title, subtitle, body, time, draws_attention); + + g_object_unref (action); + } + + g_variant_unref (messages); + } + else + { + g_warning ("could not fetch the list of messages: %s", error->message); + g_error_free (error); + } +} + +static void +im_application_list_proxy_created (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + Application *app = user_data; + GError *error = NULL; + + app->proxy = indicator_messages_application_proxy_new_finish (result, &error); + if (!app) + { + g_warning ("could not create application proxy: %s", error->message); + g_error_free (error); + return; + } + + indicator_messages_application_call_list_sources (app->proxy, app->cancellable, + im_application_list_sources_listed, app); + indicator_messages_application_call_list_messages (app->proxy, app->cancellable, + im_application_list_messages_listed, app); +} + +void +im_application_list_set_remote (ImApplicationList *list, + const gchar *id, + GDBusConnection *connection, + const gchar *unique_bus_name, + const gchar *object_path) +{ + Application *app; + + g_return_if_fail (IM_IS_APPLICATION_LIST (list)); + + app = g_hash_table_lookup (list->applications, id); + if (!app) + { + g_warning ("'%s' is not a registered appliction", id); + return; + } + + if (app->proxy || app->cancellable) + { + g_warning ("application '%s' is already running on '%s'", + id, g_dbus_proxy_get_name_owner (G_DBUS_PROXY (app->proxy))); + return; + } + + app->cancellable = g_cancellable_new (); + indicator_messages_application_proxy_new (connection, G_DBUS_PROXY_FLAGS_NONE, + unique_bus_name, object_path, app->cancellable, + im_application_list_proxy_created, app); +} + +GActionGroup * +im_application_list_get_action_group (ImApplicationList *list) +{ + g_return_val_if_fail (IM_IS_APPLICATION_LIST (list), NULL); + + return G_ACTION_GROUP (list->muxer); +} -- 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/im-application-list.c | 185 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 149 insertions(+), 36 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 33f06ab..920626d 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -39,7 +39,10 @@ G_DEFINE_TYPE (ImApplicationList, im_application_list, G_TYPE_OBJECT); enum { SOURCE_ADDED, + SOURCE_CHANGED, + SOURCE_REMOVED, MESSAGE_ADDED, + MESSAGE_REMOVED, N_SIGNALS }; @@ -121,6 +124,34 @@ im_application_list_class_init (ImApplicationListClass *klass) G_TYPE_STRING, G_TYPE_BOOLEAN); + signals[SOURCE_CHANGED] = g_signal_new ("source-changed", + IM_TYPE_APPLICATION_LIST, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 8, + G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_UINT, + G_TYPE_INT64, + G_TYPE_STRING, + G_TYPE_BOOLEAN); + + signals[SOURCE_REMOVED] = g_signal_new ("source-removed", + IM_TYPE_APPLICATION_LIST, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 2, + G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING); + signals[MESSAGE_ADDED] = g_signal_new ("message-added", IM_TYPE_APPLICATION_LIST, G_SIGNAL_RUN_FIRST, @@ -137,6 +168,17 @@ im_application_list_class_init (ImApplicationListClass *klass) G_TYPE_STRING, G_TYPE_INT64, G_TYPE_BOOLEAN); + + signals[MESSAGE_REMOVED] = g_signal_new ("message-removed", + IM_TYPE_APPLICATION_LIST, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 2, + G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING); } static void @@ -199,6 +241,63 @@ im_application_list_remove (ImApplicationList *list, g_action_muxer_remove (list->muxer, id); } +static void +im_application_list_source_added (Application *app, + guint position, + GVariant *source) +{ + const gchar *id; + const gchar *label; + const gchar *iconstr; + guint32 count; + gint64 time; + const gchar *string; + gboolean draws_attention; + GSimpleAction *action; + + g_variant_get (source, "(&s&s&sux&sb)", + &id, &label, &iconstr, &count, &time, &string, &draws_attention); + + action = g_simple_action_new_stateful (id, NULL, g_variant_new_uint32 (count)); + g_simple_action_group_insert (app->actions, G_ACTION (action)); + + g_signal_emit (app->list, signals[SOURCE_ADDED], 0, + app->info, id, label, iconstr, count, time, string, draws_attention); + + g_object_unref (action); +} + +static void +im_application_list_source_changed (Application *app, + GVariant *source) +{ + const gchar *id; + const gchar *label; + const gchar *iconstr; + guint32 count; + gint64 time; + const gchar *string; + gboolean draws_attention; + + g_variant_get (source, "(&s&s&sux&sb)", + &id, &label, &iconstr, &count, &time, &string, &draws_attention); + + g_action_group_change_action_state (G_ACTION_GROUP (app->actions), id, + g_variant_new_uint32 (count)); + + g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, + app->info, id, label, iconstr, count, time, string, draws_attention); +} + +static void +im_application_list_source_removed (Application *app, + const gchar *id) +{ + g_simple_action_group_remove (app->actions, id); + + g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->info, id); +} + static void im_application_list_sources_listed (GObject *source_object, GAsyncResult *result, @@ -211,28 +310,16 @@ im_application_list_sources_listed (GObject *source_object, if (indicator_messages_application_call_list_sources_finish (app->proxy, &sources, result, &error)) { GVariantIter iter; - const gchar *id; - const gchar *label; - const gchar *iconstr; - guint32 count; - gint64 time; - const gchar *string; - gboolean draws_attention; + GVariant *source; + guint i = 0; g_variant_iter_init (&iter, sources); - while (g_variant_iter_next (&iter, "(&s&s&sux&sb)", &id, &label, &iconstr, &count, - &time, &string, &draws_attention)) + while ((source = g_variant_iter_next_value (&iter))) { - GSimpleAction *action; - - action = g_simple_action_new_stateful (id, NULL, g_variant_new_uint32 (count)); - g_simple_action_group_insert (app->actions, G_ACTION (action)); - - g_signal_emit (app->list, signals[SOURCE_ADDED], 0, - app->info, id, label, iconstr, count, time, string, draws_attention); - - g_object_unref (action); + im_application_list_source_added (app, i++, source); + g_variant_unref (source); } + g_variant_unref (sources); } else @@ -242,6 +329,40 @@ im_application_list_sources_listed (GObject *source_object, } } +static void +im_application_list_message_added (Application *app, + GVariant *message) +{ + const gchar *id; + const gchar *iconstr; + const gchar *title; + const gchar *subtitle; + const gchar *body; + gint64 time; + gboolean draws_attention; + GSimpleAction *action; + + g_variant_get (message, "(&s&s&s&s&sxb)", + &id, &iconstr, &title, &subtitle, &body, &time, &draws_attention); + + action = g_simple_action_new (id, NULL); + g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app->actions), G_ACTION (action)); + + g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, + app->info, id, iconstr, title, subtitle, body, time, draws_attention); + + g_object_unref (action); +} + +static void +im_application_list_message_removed (Application *app, + const gchar *id) +{ + g_simple_action_group_remove (app->actions, id); + + g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->info, id); +} + static void im_application_list_messages_listed (GObject *source_object, GAsyncResult *result, @@ -254,27 +375,13 @@ im_application_list_messages_listed (GObject *source_object, if (indicator_messages_application_call_list_messages_finish (app->proxy, &messages, result, &error)) { GVariantIter iter; - const gchar *id; - const gchar *iconstr; - const gchar *title; - const gchar *subtitle; - const gchar *body; - gint64 time; - gboolean draws_attention; + GVariant *message; 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)) + while ((message = g_variant_iter_next_value (&iter))) { - GSimpleAction *action; - - action = g_simple_action_new (id, NULL); - g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app->actions), G_ACTION (action)); - - g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, - app->info, id, iconstr, title, subtitle, body, time, draws_attention); - - g_object_unref (action); + im_application_list_message_added (app, message); + g_variant_unref (message); } g_variant_unref (messages); @@ -306,6 +413,12 @@ im_application_list_proxy_created (GObject *source_object, im_application_list_sources_listed, app); indicator_messages_application_call_list_messages (app->proxy, app->cancellable, im_application_list_messages_listed, app); + + g_signal_connect_swapped (app->proxy, "source-added", G_CALLBACK (im_application_list_source_added), app); + g_signal_connect_swapped (app->proxy, "source-changed", G_CALLBACK (im_application_list_source_changed), app); + g_signal_connect_swapped (app->proxy, "source-removed", G_CALLBACK (im_application_list_source_removed), app); + g_signal_connect_swapped (app->proxy, "message-added", G_CALLBACK (im_application_list_message_added), app); + g_signal_connect_swapped (app->proxy, "message-removed", G_CALLBACK (im_application_list_message_removed), app); } void -- 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/im-application-list.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 920626d..6da2950 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -43,6 +43,7 @@ enum SOURCE_REMOVED, MESSAGE_ADDED, MESSAGE_REMOVED, + APP_STOPPED, N_SIGNALS }; @@ -179,6 +180,16 @@ im_application_list_class_init (ImApplicationListClass *klass) 2, G_TYPE_DESKTOP_APP_INFO, G_TYPE_STRING); + + signals[APP_STOPPED] = g_signal_new ("app-stopped", + IM_TYPE_APPLICATION_LIST, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + G_TYPE_DESKTOP_APP_INFO); } static void @@ -393,6 +404,31 @@ im_application_list_messages_listed (GObject *source_object, } } +static void +im_application_list_app_vanished (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + Application *app = user_data; + + if (app->cancellable) + { + g_cancellable_cancel (app->cancellable); + g_clear_object (&app->cancellable); + } + g_clear_object (&app->proxy); + + /* clear actions by creating a new action group and overriding it in + * the muxer */ + g_object_unref (app->actions); + app->actions = g_simple_action_group_new (); + g_action_muxer_insert (app->list->muxer, + g_app_info_get_id (G_APP_INFO (app->info)), + G_ACTION_GROUP (app->actions)); + + g_signal_emit (app->list, signals[APP_STOPPED], 0, app->info); +} + static void im_application_list_proxy_created (GObject *source_object, GAsyncResult *result, @@ -419,6 +455,12 @@ im_application_list_proxy_created (GObject *source_object, g_signal_connect_swapped (app->proxy, "source-removed", G_CALLBACK (im_application_list_source_removed), app); g_signal_connect_swapped (app->proxy, "message-added", G_CALLBACK (im_application_list_message_added), app); g_signal_connect_swapped (app->proxy, "message-removed", G_CALLBACK (im_application_list_message_removed), app); + + g_bus_watch_name_on_connection (g_dbus_proxy_get_connection (G_DBUS_PROXY (app->proxy)), + g_dbus_proxy_get_name (G_DBUS_PROXY (app->proxy)), + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, im_application_list_app_vanished, + app, NULL); } void -- 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/im-application-list.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 6da2950..3221413 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -205,7 +205,7 @@ im_application_list_new (void) return g_object_new (IM_TYPE_APPLICATION_LIST, NULL); } -gboolean +void im_application_list_add (ImApplicationList *list, const gchar *desktop_id) { @@ -213,20 +213,18 @@ im_application_list_add (ImApplicationList *list, Application *app; const gchar *id; - g_return_val_if_fail (IM_IS_APPLICATION_LIST (list), FALSE); - g_return_val_if_fail (desktop_id != NULL, FALSE); + g_return_if_fail (IM_IS_APPLICATION_LIST (list)); + g_return_if_fail (desktop_id != NULL); - if (g_hash_table_contains (list->applications, desktop_id)) - { - g_warning ("an application with id '%s' already exists", desktop_id); - return FALSE; - } + app = g_hash_table_lookup (list->applications, desktop_id); + if (app) + return; info = g_desktop_app_info_new (desktop_id); if (!info) { - g_warning ("application with id '%s' already exists", desktop_id); - return FALSE; + g_warning ("an application with id '%s' is no installed", desktop_id); + return; } id = g_app_info_get_id (G_APP_INFO (info)); @@ -238,8 +236,6 @@ im_application_list_add (ImApplicationList *list, g_hash_table_insert (list->applications, (gpointer) id, app); g_action_muxer_insert (list->muxer, id, G_ACTION_GROUP (app->actions)); - - return TRUE; } void @@ -483,9 +479,11 @@ im_application_list_set_remote (ImApplicationList *list, if (app->proxy || app->cancellable) { - g_warning ("application '%s' is already running on '%s'", - id, g_dbus_proxy_get_name_owner (G_DBUS_PROXY (app->proxy))); - return; + g_warning ("replacing '%s' at %s with %s", id, unique_bus_name, + g_dbus_proxy_get_name_owner (G_DBUS_PROXY (app->proxy))); + g_cancellable_cancel (app->cancellable); + g_object_unref (app->cancellable); + g_clear_object (&app->proxy); } app->cancellable = g_cancellable_new (); -- cgit v1.2.3 From 0a9533c90d46c4bfda4e0527f5475ce8c22c08e7 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 21 Nov 2012 00:28:12 +0100 Subject: Remove application messages when it unregisters itself --- src/im-application-list.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 3221413..9e9df9d 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -242,10 +242,19 @@ void im_application_list_remove (ImApplicationList *list, const gchar *id) { + Application *app; + g_return_if_fail (IM_IS_APPLICATION_LIST (list)); - g_hash_table_remove (list->applications, id); - g_action_muxer_remove (list->muxer, id); + app = g_hash_table_lookup (list->applications, id); + if (app) + { + if (app->proxy || app->cancellable) + g_signal_emit (app->list, signals[APP_STOPPED], 0, app->info); + + g_hash_table_remove (list->applications, id); + g_action_muxer_remove (list->muxer, id); + } } static void @@ -401,11 +410,11 @@ im_application_list_messages_listed (GObject *source_object, } static void -im_application_list_app_vanished (GDBusConnection *connection, - const gchar *name, - gpointer user_data) +im_application_list_unset_remote (Application *app) { - Application *app = user_data; + gboolean was_running; + + was_running = app->proxy || app->cancellable; if (app->cancellable) { @@ -422,7 +431,18 @@ im_application_list_app_vanished (GDBusConnection *connection, g_app_info_get_id (G_APP_INFO (app->info)), G_ACTION_GROUP (app->actions)); - g_signal_emit (app->list, signals[APP_STOPPED], 0, app->info); + if (was_running) + g_signal_emit (app->list, signals[APP_STOPPED], 0, app->info); +} + +static void +im_application_list_app_vanished (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + Application *app = user_data; + + im_application_list_unset_remote (app); } static void @@ -481,9 +501,7 @@ im_application_list_set_remote (ImApplicationList *list, { g_warning ("replacing '%s' at %s with %s", id, unique_bus_name, g_dbus_proxy_get_name_owner (G_DBUS_PROXY (app->proxy))); - g_cancellable_cancel (app->cancellable); - g_object_unref (app->cancellable); - g_clear_object (&app->proxy); + im_application_list_unset_remote (app); } app->cancellable = g_cancellable_new (); -- cgit v1.2.3 From 7d78b08907c94be166da15adc9b7dad3c282d0f2 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 21 Nov 2012 11:25:20 +0100 Subject: ImApplicationList: no need to include the dynamic data in the signals This data can (and should) always be retrieved via actions. --- src/im-application-list.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 9e9df9d..05d3a52 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -115,15 +115,11 @@ im_application_list_class_init (ImApplicationListClass *klass) NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 8, + 4, G_TYPE_DESKTOP_APP_INFO, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_UINT, - G_TYPE_INT64, - G_TYPE_STRING, - G_TYPE_BOOLEAN); + G_TYPE_STRING); signals[SOURCE_CHANGED] = g_signal_new ("source-changed", IM_TYPE_APPLICATION_LIST, @@ -132,15 +128,11 @@ im_application_list_class_init (ImApplicationListClass *klass) NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 8, + 4, G_TYPE_DESKTOP_APP_INFO, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_UINT, - G_TYPE_INT64, - G_TYPE_STRING, - G_TYPE_BOOLEAN); + G_TYPE_STRING); signals[SOURCE_REMOVED] = g_signal_new ("source-removed", IM_TYPE_APPLICATION_LIST, @@ -277,8 +269,7 @@ im_application_list_source_added (Application *app, action = g_simple_action_new_stateful (id, NULL, g_variant_new_uint32 (count)); g_simple_action_group_insert (app->actions, G_ACTION (action)); - g_signal_emit (app->list, signals[SOURCE_ADDED], 0, - app->info, id, label, iconstr, count, time, string, draws_attention); + g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->info, id, label, iconstr); g_object_unref (action); } @@ -301,8 +292,7 @@ im_application_list_source_changed (Application *app, g_action_group_change_action_state (G_ACTION_GROUP (app->actions), id, g_variant_new_uint32 (count)); - g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, - app->info, id, label, iconstr, count, time, string, draws_attention); + g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->info, id, label, iconstr); } static void -- cgit v1.2.3 From e8eda4af8432d36d82b1124a4bad0f5eee876188 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 21 Nov 2012 13:40:11 +0100 Subject: ImApplicationList: fix typos Thanks Olivier! --- src/im-application-list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 05d3a52..732a117 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -215,7 +215,7 @@ im_application_list_add (ImApplicationList *list, info = g_desktop_app_info_new (desktop_id); if (!info) { - g_warning ("an application with id '%s' is no installed", desktop_id); + g_warning ("an application with id '%s' is not installed", desktop_id); return; } @@ -483,7 +483,7 @@ im_application_list_set_remote (ImApplicationList *list, app = g_hash_table_lookup (list->applications, id); if (!app) { - g_warning ("'%s' is not a registered appliction", id); + g_warning ("'%s' is not a registered application", id); return; } -- cgit v1.2.3 From a7ca54762c465cd5d26f9eafe11beb3e205a97ab Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 22 Nov 2012 11:58:58 +0100 Subject: ImApplicationList: use specified state for source actions (uxsb) --- src/im-application-list.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 732a117..acd6e2b 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -261,12 +261,14 @@ im_application_list_source_added (Application *app, gint64 time; const gchar *string; gboolean draws_attention; + GVariant *state; GSimpleAction *action; g_variant_get (source, "(&s&s&sux&sb)", &id, &label, &iconstr, &count, &time, &string, &draws_attention); - action = g_simple_action_new_stateful (id, NULL, g_variant_new_uint32 (count)); + state = g_variant_new ("(uxsb)", count, time, string, draws_attention); + action = g_simple_action_new_stateful (id, NULL, state); g_simple_action_group_insert (app->actions, G_ACTION (action)); g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->info, id, label, iconstr); @@ -290,7 +292,7 @@ im_application_list_source_changed (Application *app, &id, &label, &iconstr, &count, &time, &string, &draws_attention); g_action_group_change_action_state (G_ACTION_GROUP (app->actions), id, - g_variant_new_uint32 (count)); + g_variant_new ("(uxsb)", count, time, string, draws_attention)); g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->info, id, label, iconstr); } -- cgit v1.2.3 From 979a9b32a625adb29af3b5bd6bfe324268a51b2c Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 26 Nov 2012 11:34:50 +0100 Subject: Canonicalize application ids Remove trailing '.desktop' and replace all dots by underscores to make GActionMuxer work (which uses the dot as a separator). In order to contain the canonicalization to ImApplicationList, its signals now contain string parameters to id and icon name instead of GDesktopAppInfo pointers. --- src/im-application-list.c | 87 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 24 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index acd6e2b..24df19e 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -23,6 +23,7 @@ #include "gactionmuxer.h" #include +#include typedef GObjectClass ImApplicationListClass; @@ -53,6 +54,7 @@ typedef struct { ImApplicationList *list; GDesktopAppInfo *info; + gchar *id; IndicatorMessagesApplication *proxy; GSimpleActionGroup *actions; GCancellable *cancellable; @@ -66,7 +68,8 @@ application_free (gpointer data) if (!app) return; - g_clear_object (&app->info); + g_object_unref (app->info); + g_free (app->id); if (app->cancellable) { @@ -116,7 +119,7 @@ im_application_list_class_init (ImApplicationListClass *klass) g_cclosure_marshal_generic, G_TYPE_NONE, 4, - G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); @@ -129,7 +132,7 @@ im_application_list_class_init (ImApplicationListClass *klass) g_cclosure_marshal_generic, G_TYPE_NONE, 4, - G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); @@ -142,7 +145,7 @@ im_application_list_class_init (ImApplicationListClass *klass) g_cclosure_marshal_generic, G_TYPE_NONE, 2, - G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING, G_TYPE_STRING); signals[MESSAGE_ADDED] = g_signal_new ("message-added", @@ -153,7 +156,7 @@ im_application_list_class_init (ImApplicationListClass *klass) g_cclosure_marshal_generic, G_TYPE_NONE, 8, - G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, @@ -170,7 +173,7 @@ im_application_list_class_init (ImApplicationListClass *klass) g_cclosure_marshal_generic, G_TYPE_NONE, 2, - G_TYPE_DESKTOP_APP_INFO, + G_TYPE_STRING, G_TYPE_STRING); signals[APP_STOPPED] = g_signal_new ("app-stopped", @@ -181,7 +184,7 @@ im_application_list_class_init (ImApplicationListClass *klass) g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - G_TYPE_DESKTOP_APP_INFO); + G_TYPE_STRING); } static void @@ -197,6 +200,37 @@ im_application_list_new (void) return g_object_new (IM_TYPE_APPLICATION_LIST, NULL); } +static gchar * +im_application_list_canonical_id (const gchar *id) +{ + gchar *str; + gchar *p; + + str = g_strndup (id, strlen (id) - g_str_has_suffix (id, ".desktop") ? 7 : 0); + + for (p = str; *p; p++) + { + if (*p == '.') + *p = '_'; + } + + return str; +} + +static Application * +im_application_list_lookup (ImApplicationList *list, + const gchar *desktop_id) +{ + gchar *id; + Application *app; + + id = im_application_list_canonical_id (desktop_id); + app = g_hash_table_lookup (list->applications, id); + + g_free (id); + return app; +} + void im_application_list_add (ImApplicationList *list, const gchar *desktop_id) @@ -208,8 +242,7 @@ im_application_list_add (ImApplicationList *list, g_return_if_fail (IM_IS_APPLICATION_LIST (list)); g_return_if_fail (desktop_id != NULL); - app = g_hash_table_lookup (list->applications, desktop_id); - if (app) + if (im_application_list_lookup (list, desktop_id)) return; info = g_desktop_app_info_new (desktop_id); @@ -220,14 +253,16 @@ im_application_list_add (ImApplicationList *list, } id = g_app_info_get_id (G_APP_INFO (info)); + g_return_if_fail (id != NULL); app = g_slice_new0 (Application); - app->list = list; app->info = info; + app->id = im_application_list_canonical_id (id); + app->list = list; app->actions = g_simple_action_group_new (); - g_hash_table_insert (list->applications, (gpointer) id, app); - g_action_muxer_insert (list->muxer, id, G_ACTION_GROUP (app->actions)); + g_hash_table_insert (list->applications, (gpointer) app->id, app); + g_action_muxer_insert (list->muxer, app->id, G_ACTION_GROUP (app->actions)); } void @@ -238,11 +273,11 @@ im_application_list_remove (ImApplicationList *list, g_return_if_fail (IM_IS_APPLICATION_LIST (list)); - app = g_hash_table_lookup (list->applications, id); + app = im_application_list_lookup (list, id); if (app) { if (app->proxy || app->cancellable) - g_signal_emit (app->list, signals[APP_STOPPED], 0, app->info); + g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id); g_hash_table_remove (list->applications, id); g_action_muxer_remove (list->muxer, id); @@ -271,7 +306,7 @@ im_application_list_source_added (Application *app, action = g_simple_action_new_stateful (id, NULL, state); g_simple_action_group_insert (app->actions, G_ACTION (action)); - g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->info, id, label, iconstr); + g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, id, label, iconstr); g_object_unref (action); } @@ -294,7 +329,7 @@ im_application_list_source_changed (Application *app, g_action_group_change_action_state (G_ACTION_GROUP (app->actions), id, g_variant_new ("(uxsb)", count, time, string, draws_attention)); - g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->info, id, label, iconstr); + g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, id, label, iconstr); } static void @@ -303,7 +338,7 @@ im_application_list_source_removed (Application *app, { g_simple_action_group_remove (app->actions, id); - g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->info, id); + g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id); } static void @@ -349,16 +384,22 @@ im_application_list_message_added (Application *app, gint64 time; gboolean draws_attention; GSimpleAction *action; + GIcon *app_icon; + gchar *app_iconstr; g_variant_get (message, "(&s&s&s&s&sxb)", &id, &iconstr, &title, &subtitle, &body, &time, &draws_attention); + app_icon = g_app_info_get_icon (G_APP_INFO (app->info)); + app_iconstr = app_icon ? g_icon_to_string (app_icon) : NULL; + action = g_simple_action_new (id, NULL); g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app->actions), G_ACTION (action)); g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, - app->info, id, iconstr, title, subtitle, body, time, draws_attention); + app->id, app_iconstr, id, iconstr, title, subtitle, body, time, draws_attention); + g_free (app_iconstr); g_object_unref (action); } @@ -368,7 +409,7 @@ im_application_list_message_removed (Application *app, { g_simple_action_group_remove (app->actions, id); - g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->info, id); + g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id); } static void @@ -419,12 +460,10 @@ im_application_list_unset_remote (Application *app) * the muxer */ g_object_unref (app->actions); app->actions = g_simple_action_group_new (); - g_action_muxer_insert (app->list->muxer, - g_app_info_get_id (G_APP_INFO (app->info)), - G_ACTION_GROUP (app->actions)); + g_action_muxer_insert (app->list->muxer, app->id, G_ACTION_GROUP (app->actions)); if (was_running) - g_signal_emit (app->list, signals[APP_STOPPED], 0, app->info); + g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id); } static void @@ -482,7 +521,7 @@ im_application_list_set_remote (ImApplicationList *list, g_return_if_fail (IM_IS_APPLICATION_LIST (list)); - app = g_hash_table_lookup (list->applications, id); + app = im_application_list_lookup (list, id); if (!app) { g_warning ("'%s' is not a registered application", id); -- cgit v1.2.3 From 629b28e7f86d13eb78274c51a9164bdcac4e2cd7 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 26 Nov 2012 11:49:17 +0100 Subject: ImApplicationList: listen to activate signal --- src/im-application-list.c | 76 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 18 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 24df19e..dc8c146 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -86,6 +86,60 @@ application_free (gpointer data) g_slice_free (Application, app); } +static void +im_application_list_source_removed (Application *app, + const gchar *id) +{ + g_simple_action_group_remove (app->actions, id); + + g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id); +} + +static void +im_application_list_source_activated (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + Application *app = user_data; + const gchar *source_id; + + source_id = g_action_get_name (G_ACTION (action)); + + indicator_messages_application_call_activate_source (app->proxy, + source_id, + app->cancellable, + NULL, NULL); + + im_application_list_source_removed (app, source_id); +} + +static void +im_application_list_message_removed (Application *app, + const gchar *id) +{ + g_simple_action_group_remove (app->actions, id); + + g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id); +} + +static void +im_application_list_message_activated (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + Application *app = user_data; + const gchar *message_id; + + message_id = g_action_get_name (G_ACTION (action)); + + indicator_messages_application_call_activate_message (app->proxy, + message_id, + app->cancellable, + NULL, NULL); + + im_application_list_message_removed (app, message_id); +} + static void im_application_list_dispose (GObject *object) { @@ -304,6 +358,8 @@ im_application_list_source_added (Application *app, state = g_variant_new ("(uxsb)", count, time, string, draws_attention); action = g_simple_action_new_stateful (id, NULL, state); + g_signal_connect (action, "activate", G_CALLBACK (im_application_list_source_activated), app); + g_simple_action_group_insert (app->actions, G_ACTION (action)); g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, id, label, iconstr); @@ -332,15 +388,6 @@ im_application_list_source_changed (Application *app, g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, id, label, iconstr); } -static void -im_application_list_source_removed (Application *app, - const gchar *id) -{ - g_simple_action_group_remove (app->actions, id); - - g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id); -} - static void im_application_list_sources_listed (GObject *source_object, GAsyncResult *result, @@ -394,6 +441,8 @@ im_application_list_message_added (Application *app, app_iconstr = app_icon ? g_icon_to_string (app_icon) : NULL; action = g_simple_action_new (id, NULL); + g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app); + g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app->actions), G_ACTION (action)); g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, @@ -403,15 +452,6 @@ im_application_list_message_added (Application *app, g_object_unref (action); } -static void -im_application_list_message_removed (Application *app, - const gchar *id) -{ - g_simple_action_group_remove (app->actions, id); - - g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id); -} - static void im_application_list_messages_listed (GObject *source_object, GAsyncResult *result, -- cgit v1.2.3 From eeb48cb2ecc059080ef6c079d1527eebe88da42f Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 26 Nov 2012 13:36:43 +0100 Subject: ImApplicationList: give message and source actions a boolean parameter The application will only be notified about the activation when this parameter is true. False denotes a dismissed item. --- src/im-application-list.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index dc8c146..644051f 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -105,10 +105,13 @@ im_application_list_source_activated (GSimpleAction *action, source_id = g_action_get_name (G_ACTION (action)); - indicator_messages_application_call_activate_source (app->proxy, - source_id, - app->cancellable, - NULL, NULL); + if (g_variant_get_boolean (parameter)) + { + indicator_messages_application_call_activate_source (app->proxy, + source_id, + app->cancellable, + NULL, NULL); + } im_application_list_source_removed (app, source_id); } @@ -132,10 +135,13 @@ im_application_list_message_activated (GSimpleAction *action, message_id = g_action_get_name (G_ACTION (action)); - indicator_messages_application_call_activate_message (app->proxy, - message_id, - app->cancellable, - NULL, NULL); + if (g_variant_get_boolean (parameter)) + { + indicator_messages_application_call_activate_message (app->proxy, + message_id, + app->cancellable, + NULL, NULL); + } im_application_list_message_removed (app, message_id); } @@ -357,7 +363,7 @@ im_application_list_source_added (Application *app, &id, &label, &iconstr, &count, &time, &string, &draws_attention); state = g_variant_new ("(uxsb)", count, time, string, draws_attention); - action = g_simple_action_new_stateful (id, NULL, state); + action = g_simple_action_new_stateful (id, G_VARIANT_TYPE_BOOLEAN, state); g_signal_connect (action, "activate", G_CALLBACK (im_application_list_source_activated), app); g_simple_action_group_insert (app->actions, G_ACTION (action)); @@ -440,7 +446,7 @@ im_application_list_message_added (Application *app, app_icon = g_app_info_get_icon (G_APP_INFO (app->info)); app_iconstr = app_icon ? g_icon_to_string (app_icon) : NULL; - action = g_simple_action_new (id, NULL); + action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN); g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app); g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app->actions), G_ACTION (action)); -- cgit v1.2.3 From 76da35f3747a9efaa509d54d92b5511e6a0b69d0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 26 Nov 2012 16:15:55 +0100 Subject: Namespace actions with 'src' and 'msg' for sources and messages --- src/im-application-list.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 644051f..71100d4 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -56,7 +56,9 @@ typedef struct GDesktopAppInfo *info; gchar *id; IndicatorMessagesApplication *proxy; - GSimpleActionGroup *actions; + GActionMuxer *actions; + GSimpleActionGroup *source_actions; + GSimpleActionGroup *message_actions; GCancellable *cancellable; } Application; @@ -81,7 +83,11 @@ application_free (gpointer data) g_object_unref (app->proxy); if (app->actions) - g_object_unref (app->actions); + { + g_object_unref (app->actions); + g_object_unref (app->source_actions); + g_object_unref (app->message_actions); + } g_slice_free (Application, app); } @@ -90,7 +96,7 @@ static void im_application_list_source_removed (Application *app, const gchar *id) { - g_simple_action_group_remove (app->actions, id); + g_simple_action_group_remove (app->source_actions, id); g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id); } @@ -120,7 +126,7 @@ static void im_application_list_message_removed (Application *app, const gchar *id) { - g_simple_action_group_remove (app->actions, id); + g_simple_action_group_remove (app->message_actions, id); g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id); } @@ -319,7 +325,12 @@ im_application_list_add (ImApplicationList *list, app->info = info; app->id = im_application_list_canonical_id (id); app->list = list; - app->actions = g_simple_action_group_new (); + app->actions = g_action_muxer_new (); + app->source_actions = g_simple_action_group_new (); + app->message_actions = g_simple_action_group_new (); + + g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions)); + g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions)); g_hash_table_insert (list->applications, (gpointer) app->id, app); g_action_muxer_insert (list->muxer, app->id, G_ACTION_GROUP (app->actions)); @@ -366,7 +377,7 @@ im_application_list_source_added (Application *app, action = g_simple_action_new_stateful (id, G_VARIANT_TYPE_BOOLEAN, state); g_signal_connect (action, "activate", G_CALLBACK (im_application_list_source_activated), app); - g_simple_action_group_insert (app->actions, G_ACTION (action)); + g_simple_action_group_insert (app->source_actions, G_ACTION (action)); g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, id, label, iconstr); @@ -388,7 +399,7 @@ im_application_list_source_changed (Application *app, g_variant_get (source, "(&s&s&sux&sb)", &id, &label, &iconstr, &count, &time, &string, &draws_attention); - g_action_group_change_action_state (G_ACTION_GROUP (app->actions), id, + g_action_group_change_action_state (G_ACTION_GROUP (app->source_actions), id, g_variant_new ("(uxsb)", count, time, string, draws_attention)); g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, id, label, iconstr); @@ -449,7 +460,7 @@ im_application_list_message_added (Application *app, action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN); g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app); - g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app->actions), G_ACTION (action)); + g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app->message_actions), G_ACTION (action)); g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, app->id, app_iconstr, id, iconstr, title, subtitle, body, time, draws_attention); @@ -504,9 +515,12 @@ im_application_list_unset_remote (Application *app) /* clear actions by creating a new action group and overriding it in * the muxer */ - g_object_unref (app->actions); - app->actions = g_simple_action_group_new (); - g_action_muxer_insert (app->list->muxer, app->id, G_ACTION_GROUP (app->actions)); + g_object_unref (app->source_actions); + g_object_unref (app->message_actions); + app->source_actions = g_simple_action_group_new (); + app->message_actions = g_simple_action_group_new (); + g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions)); + g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions)); if (was_running) g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id); -- cgit v1.2.3 From f758143a4c818e23b2e410d5bf63305c84a07590 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 26 Nov 2012 16:26:25 +0100 Subject: Add "Clear All" --- src/im-application-list.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 71100d4..c3be647 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -152,6 +152,33 @@ im_application_list_message_activated (GSimpleAction *action, im_application_list_message_removed (app, message_id); } +static void +im_application_list_remove_all (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + ImApplicationList *list = user_data; + GHashTableIter iter; + Application *app; + + g_hash_table_iter_init (&iter, list->applications); + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &app)) + { + gchar **actions; + gchar **it; + + actions = g_action_group_list_actions (G_ACTION_GROUP (app->source_actions)); + for (it = actions; *it; it++) + im_application_list_source_removed (app, *it); + g_strfreev (actions); + + actions = g_action_group_list_actions (G_ACTION_GROUP (app->message_actions)); + for (it = actions; *it; it++) + im_application_list_message_removed (app, *it); + g_strfreev (actions); + } +} + static void im_application_list_dispose (GObject *object) { @@ -256,8 +283,23 @@ im_application_list_class_init (ImApplicationListClass *klass) static void im_application_list_init (ImApplicationList *list) { + GSimpleActionGroup *actions; + GSimpleAction *remove_all_action; + list->applications = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, application_free); list->muxer = g_action_muxer_new (); + + actions = g_simple_action_group_new (); + + remove_all_action = g_simple_action_new ("remove-all", NULL); + g_signal_connect (remove_all_action, "activate", G_CALLBACK (im_application_list_remove_all), list); + + g_simple_action_group_insert (actions, G_ACTION (remove_all_action)); + + g_action_muxer_insert (list->muxer, NULL, G_ACTION_GROUP (actions)); + + g_object_unref (remove_all_action); + g_object_unref (actions); } ImApplicationList * @@ -460,7 +502,7 @@ im_application_list_message_added (Application *app, action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN); g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app); - g_simple_action_group_insert (G_SIMPLE_ACTION_GROUP (app->message_actions), G_ACTION (action)); + g_simple_action_group_insert (app->message_actions, G_ACTION (action)); g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, app->id, app_iconstr, id, iconstr, title, subtitle, body, time, draws_attention); -- cgit v1.2.3 From 9287c2e6577e71d8f68d9c9e7d393a4f8524ab10 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 26 Nov 2012 20:12:13 +0100 Subject: Tell applications when messages and sources are dismissed Right now, this is only used to clean up internal data structures in libmessaging-menu. It's not exposed to the application itself. --- src/im-application-list.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index c3be647..d766f24 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -118,6 +118,13 @@ im_application_list_source_activated (GSimpleAction *action, app->cancellable, NULL, NULL); } + else + { + const gchar *sources[] = { source_id, NULL }; + const gchar *messages[] = { NULL }; + indicator_messages_application_call_dismiss (app->proxy, sources, messages, + app->cancellable, NULL, NULL); + } im_application_list_source_removed (app, source_id); } @@ -148,6 +155,13 @@ im_application_list_message_activated (GSimpleAction *action, app->cancellable, NULL, NULL); } + else + { + const gchar *sources[] = { NULL }; + const gchar *messages[] = { message_id, NULL }; + indicator_messages_application_call_dismiss (app->proxy, sources, messages, + app->cancellable, NULL, NULL); + } im_application_list_message_removed (app, message_id); } @@ -164,18 +178,25 @@ im_application_list_remove_all (GSimpleAction *action, g_hash_table_iter_init (&iter, list->applications); while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &app)) { - gchar **actions; + gchar **source_actions; + gchar **message_actions; gchar **it; - actions = g_action_group_list_actions (G_ACTION_GROUP (app->source_actions)); - for (it = actions; *it; it++) + source_actions = g_action_group_list_actions (G_ACTION_GROUP (app->source_actions)); + for (it = source_actions; *it; it++) im_application_list_source_removed (app, *it); - g_strfreev (actions); - actions = g_action_group_list_actions (G_ACTION_GROUP (app->message_actions)); - for (it = actions; *it; it++) + message_actions = g_action_group_list_actions (G_ACTION_GROUP (app->message_actions)); + for (it = message_actions; *it; it++) im_application_list_message_removed (app, *it); - g_strfreev (actions); + + indicator_messages_application_call_dismiss (app->proxy, + (const gchar * const *) source_actions, + (const gchar * const *) message_actions, + app->cancellable, NULL, NULL); + + g_strfreev (source_actions); + g_strfreev (message_actions); } } -- cgit v1.2.3 From e8e99703ef0c565f07a9d1eba03c1003d82ff697 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 27 Nov 2012 15:14:26 +0100 Subject: Allow adding actions to MessagingMenuMessage --- src/im-application-list.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index d766f24..4eaaed0 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -509,13 +509,14 @@ im_application_list_message_added (Application *app, const gchar *subtitle; const gchar *body; gint64 time; + GVariantIter *action_iter; gboolean draws_attention; GSimpleAction *action; GIcon *app_icon; gchar *app_iconstr; - g_variant_get (message, "(&s&s&s&s&sxb)", - &id, &iconstr, &title, &subtitle, &body, &time, &draws_attention); + g_variant_get (message, "(&s&s&s&s&sxa(ssgav)b)", + &id, &iconstr, &title, &subtitle, &body, &time, &action_iter, &draws_attention); app_icon = g_app_info_get_icon (G_APP_INFO (app->info)); app_iconstr = app_icon ? g_icon_to_string (app_icon) : NULL; @@ -528,6 +529,7 @@ im_application_list_message_added (Application *app, g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, app->id, app_iconstr, id, iconstr, title, subtitle, body, time, draws_attention); + g_variant_iter_free (action_iter); g_free (app_iconstr); g_object_unref (action); } -- cgit v1.2.3 From ced173aa7ea78c76922e07c84743d5b7f76c265e Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 27 Nov 2012 16:40:38 +0100 Subject: Pass message action and its parameter through to the application --- src/im-application-list.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 4eaaed0..7c53e69 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -152,6 +152,8 @@ im_application_list_message_activated (GSimpleAction *action, { indicator_messages_application_call_activate_message (app->proxy, message_id, + "", + g_variant_new_array (G_VARIANT_TYPE_VARIANT, NULL, 0), app->cancellable, NULL, NULL); } -- 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/im-application-list.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index d766f24..c5e34b7 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -304,22 +304,21 @@ im_application_list_class_init (ImApplicationListClass *klass) static void im_application_list_init (ImApplicationList *list) { + const GActionEntry action_entries[] = { + { "messages", NULL, NULL, "('', 'indicator-messages', 'Messages', true)", NULL }, + { "remove-all", im_application_list_remove_all } + }; + GSimpleActionGroup *actions; - GSimpleAction *remove_all_action; list->applications = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, application_free); - list->muxer = g_action_muxer_new (); actions = g_simple_action_group_new (); + g_simple_action_group_add_entries (actions, action_entries, G_N_ELEMENTS (action_entries), list); - remove_all_action = g_simple_action_new ("remove-all", NULL); - g_signal_connect (remove_all_action, "activate", G_CALLBACK (im_application_list_remove_all), list); - - g_simple_action_group_insert (actions, G_ACTION (remove_all_action)); - + list->muxer = g_action_muxer_new (); g_action_muxer_insert (list->muxer, NULL, G_ACTION_GROUP (actions)); - g_object_unref (remove_all_action); g_object_unref (actions); } -- cgit v1.2.3 From 235a7edc5c2fc2435c837f8a3d427dd0755f966d Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 28 Nov 2012 17:24:31 +0100 Subject: Use aa{sv} instead of a(ssgav) to communicate actions to the service --- src/im-application-list.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 7c53e69..1f901ec 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -511,14 +511,14 @@ im_application_list_message_added (Application *app, const gchar *subtitle; const gchar *body; gint64 time; - GVariantIter *action_iter; + GVariant *actions; gboolean draws_attention; GSimpleAction *action; GIcon *app_icon; gchar *app_iconstr; - g_variant_get (message, "(&s&s&s&s&sxa(ssgav)b)", - &id, &iconstr, &title, &subtitle, &body, &time, &action_iter, &draws_attention); + g_variant_get (message, "(&s&s&s&s&sx@aa{sv}b)", + &id, &iconstr, &title, &subtitle, &body, &time, &actions, &draws_attention); app_icon = g_app_info_get_icon (G_APP_INFO (app->info)); app_iconstr = app_icon ? g_icon_to_string (app_icon) : NULL; @@ -531,7 +531,7 @@ im_application_list_message_added (Application *app, g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, app->id, app_iconstr, id, iconstr, title, subtitle, body, time, draws_attention); - g_variant_iter_free (action_iter); + g_variant_unref (actions); g_free (app_iconstr); g_object_unref (action); } -- cgit v1.2.3 From e6930c0df67ab53fcb2f7183741dee1bc0d599d4 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 28 Nov 2012 17:39:14 +0100 Subject: Expose message actions in the phone menu And use com.canonical.indicator.messages.snapdecision as widget type if the message has actions. --- src/im-application-list.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 1f901ec..c446d12 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -271,13 +271,15 @@ im_application_list_class_init (ImApplicationListClass *klass) NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 8, + 10, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_VARIANT, G_TYPE_INT64, G_TYPE_BOOLEAN); @@ -529,7 +531,7 @@ im_application_list_message_added (Application *app, g_simple_action_group_insert (app->message_actions, G_ACTION (action)); g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, - app->id, app_iconstr, id, iconstr, title, subtitle, body, time, draws_attention); + app->id, app_iconstr, id, iconstr, title, subtitle, body, actions, time, draws_attention); g_variant_unref (actions); g_free (app_iconstr); -- cgit v1.2.3 From 4bfe4198605a873fdede8b7cf454b4134ce2ce52 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 29 Nov 2012 20:44:38 +0100 Subject: ImApplicationList: specify right number of args for 'message-added' This fixes a crash on arm, because g_signal_emit was called with one argument too many. --- src/im-application-list.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index c5e34b7..f0bf362 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -269,7 +269,8 @@ im_application_list_class_init (ImApplicationListClass *klass) NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 8, + 9, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, -- cgit v1.2.3 From 16aeadbeb7f0b108c2ba5e68a6ad0d96766380ba Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 30 Nov 2012 18:35:53 +0100 Subject: Expose message actions on the bus (as GActions) --- src/im-application-list.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index c446d12..70d288c 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -59,6 +59,7 @@ typedef struct GActionMuxer *actions; GSimpleActionGroup *source_actions; GSimpleActionGroup *message_actions; + GActionMuxer *message_sub_actions; GCancellable *cancellable; } Application; @@ -87,6 +88,7 @@ application_free (gpointer data) g_object_unref (app->actions); g_object_unref (app->source_actions); g_object_unref (app->message_actions); + g_object_unref (app->message_sub_actions); } g_slice_free (Application, app); @@ -134,6 +136,7 @@ im_application_list_message_removed (Application *app, const gchar *id) { g_simple_action_group_remove (app->message_actions, id); + g_action_muxer_remove (app->message_sub_actions, id); g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id); } @@ -168,6 +171,34 @@ im_application_list_message_activated (GSimpleAction *action, im_application_list_message_removed (app, message_id); } +static void +im_application_list_sub_message_activated (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + Application *app = user_data; + const gchar *message_id; + const gchar *action_id; + GVariantBuilder builder; + + message_id = g_object_get_data (G_OBJECT (action), "message"); + action_id = g_action_get_name (G_ACTION (action)); + + g_variant_builder_init (&builder, G_VARIANT_TYPE ("av")); + if (parameter) + g_variant_builder_add (&builder, "v", parameter); + + indicator_messages_application_call_activate_message (app->proxy, + message_id, + action_id, + g_variant_builder_end (&builder), + app->cancellable, + NULL, NULL); + + im_application_list_message_removed (app, message_id); +} + + static void im_application_list_remove_all (GSimpleAction *action, GVariant *parameter, @@ -395,9 +426,11 @@ im_application_list_add (ImApplicationList *list, app->actions = g_action_muxer_new (); app->source_actions = g_simple_action_group_new (); app->message_actions = g_simple_action_group_new (); + app->message_sub_actions = g_action_muxer_new (); g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions)); g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions)); + g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions)); g_hash_table_insert (list->applications, (gpointer) app->id, app); g_action_muxer_insert (list->muxer, app->id, G_ACTION_GROUP (app->actions)); @@ -527,9 +560,52 @@ im_application_list_message_added (Application *app, action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN); g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app); - g_simple_action_group_insert (app->message_actions, G_ACTION (action)); + { + GVariantIter iter; + GVariant *entry; + GSimpleActionGroup *action_group; + + action_group = g_simple_action_group_new (); + + g_variant_iter_init (&iter, actions); + while ((entry = g_variant_iter_next_value (&iter))) + { + const gchar *name; + GSimpleAction *action; + GVariant *label; + const gchar *type = NULL; + GVariant *hint; + + if (!g_variant_lookup (entry, "name", "&s", &name)) + { + g_warning ("action dictionary for message '%s' is missing 'name' key", id); + continue; + } + + label = g_variant_lookup_value (entry, "label", G_VARIANT_TYPE_STRING); + g_variant_lookup (entry, "parameter-type", "&g", &type); + hint = g_variant_lookup_value (entry, "parameter-hint", NULL); + + action = g_simple_action_new (name, type ? G_VARIANT_TYPE (type) : NULL); + g_object_set_data_full (G_OBJECT (action), "message", g_strdup (id), g_free); + g_signal_connect (action, "activate", G_CALLBACK (im_application_list_sub_message_activated), app); + g_simple_action_group_insert (action_group, G_ACTION (action)); + + g_object_unref (action); + if (label) + g_variant_unref (label); + if (hint) + g_variant_unref (hint); + g_variant_unref (entry); + } + + g_action_muxer_insert (app->message_sub_actions, id, G_ACTION_GROUP (action_group)); + + g_object_unref (action_group); + } + g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, app->id, app_iconstr, id, iconstr, title, subtitle, body, actions, time, draws_attention); @@ -586,10 +662,13 @@ im_application_list_unset_remote (Application *app) * the muxer */ g_object_unref (app->source_actions); g_object_unref (app->message_actions); + g_object_unref (app->message_sub_actions); app->source_actions = g_simple_action_group_new (); app->message_actions = g_simple_action_group_new (); + app->message_sub_actions = g_action_muxer_new (); g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions)); g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions)); + g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions)); if (was_running) g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id); -- cgit v1.2.3 From 4e8bff91265ee85f00793bbfd065e5832e436954 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 3 Dec 2012 17:21:39 +0000 Subject: Prefix message action names with the right namespace --- src/im-application-list.c | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index d4c5687..c41c858 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -545,14 +545,15 @@ im_application_list_message_added (Application *app, const gchar *subtitle; const gchar *body; gint64 time; - GVariant *actions; + GVariantIter *action_iter; gboolean draws_attention; GSimpleAction *action; GIcon *app_icon; gchar *app_iconstr; + GVariant *actions = NULL; - g_variant_get (message, "(&s&s&s&s&sx@aa{sv}b)", - &id, &iconstr, &title, &subtitle, &body, &time, &actions, &draws_attention); + g_variant_get (message, "(&s&s&s&s&sxaa{sv}b)", + &id, &iconstr, &title, &subtitle, &body, &time, &action_iter, &draws_attention); app_icon = g_app_info_get_icon (G_APP_INFO (app->info)); app_iconstr = app_icon ? g_icon_to_string (app_icon) : NULL; @@ -562,20 +563,22 @@ im_application_list_message_added (Application *app, g_simple_action_group_insert (app->message_actions, G_ACTION (action)); { - GVariantIter iter; GVariant *entry; GSimpleActionGroup *action_group; + GVariantBuilder actions_builder; + g_variant_builder_init (&actions_builder, G_VARIANT_TYPE ("aa{sv}")); action_group = g_simple_action_group_new (); - g_variant_iter_init (&iter, actions); - while ((entry = g_variant_iter_next_value (&iter))) + while ((entry = g_variant_iter_next_value (action_iter))) { const gchar *name; GSimpleAction *action; GVariant *label; const gchar *type = NULL; GVariant *hint; + GVariantBuilder dict_builder; + gchar *prefixed_name; if (!g_variant_lookup (entry, "name", "&s", &name)) { @@ -592,15 +595,35 @@ im_application_list_message_added (Application *app, g_signal_connect (action, "activate", G_CALLBACK (im_application_list_sub_message_activated), app); g_simple_action_group_insert (action_group, G_ACTION (action)); - g_object_unref (action); + g_variant_builder_init (&dict_builder, G_VARIANT_TYPE ("a{sv}")); + + prefixed_name = g_strjoin (".", app->id, "msg-actions", id, name, NULL); + g_variant_builder_add (&dict_builder, "{sv}", "name", g_variant_new_string (prefixed_name)); + if (label) - g_variant_unref (label); + { + g_variant_builder_add (&dict_builder, "{sv}", "label", label); + g_variant_unref (label); + } + + if (type) + g_variant_builder_add (&dict_builder, "{sv}", "parameter-type", g_variant_new_string (type)); + if (hint) - g_variant_unref (hint); + { + g_variant_builder_add (&dict_builder, "{sv}", "parameter-hint", hint); + g_variant_unref (hint); + } + + g_variant_builder_add (&actions_builder, "a{sv}", &dict_builder); + + g_object_unref (action); g_variant_unref (entry); + g_free (prefixed_name); } g_action_muxer_insert (app->message_sub_actions, id, G_ACTION_GROUP (action_group)); + actions = g_variant_builder_end (&actions_builder); g_object_unref (action_group); } @@ -608,7 +631,7 @@ im_application_list_message_added (Application *app, g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, app->id, app_iconstr, id, iconstr, title, subtitle, body, actions, time, draws_attention); - g_variant_unref (actions); + g_variant_iter_free (action_iter); g_free (app_iconstr); g_object_unref (action); } -- cgit v1.2.3 From af58f8e28e5ab5ed29de518bd921f8ae699ac972 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 4 Dec 2012 12:31:33 +0000 Subject: Export symbolic application icons on messages This is implemented by appending '-symbolic' to the first icon name. The old icon name is kept as a fallback in case there's no symbolic icon installed. This doesn't work yet for applications that specify their icon as a filename. --- src/im-application-list.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index c41c858..77c0e47 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -302,7 +302,8 @@ im_application_list_class_init (ImApplicationListClass *klass) NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 10, + 11, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, @@ -535,6 +536,33 @@ im_application_list_sources_listed (GObject *source_object, } } +static gchar * +get_symbolic_app_icon_string (GIcon *icon) +{ + const gchar * const *names; + gchar *symbolic_name; + GIcon *symbolic_icon; + gchar *str; + + if (!G_IS_THEMED_ICON (icon)) + return NULL; + + names = g_themed_icon_get_names (G_THEMED_ICON (icon)); + if (!names || !names[0]) + return NULL; + + symbolic_icon = g_themed_icon_new_from_names ((gchar **) names, -1); + + symbolic_name = g_strconcat (names[0], "-symbolic", NULL); + g_themed_icon_prepend_name (G_THEMED_ICON (symbolic_icon), symbolic_name); + + str = g_icon_to_string (symbolic_icon); + + g_free (symbolic_name); + g_object_unref (symbolic_icon); + return str; +} + static void im_application_list_message_added (Application *app, GVariant *message) @@ -550,13 +578,18 @@ im_application_list_message_added (Application *app, GSimpleAction *action; GIcon *app_icon; gchar *app_iconstr; + gchar *symbolic_app_iconstr; GVariant *actions = NULL; g_variant_get (message, "(&s&s&s&s&sxaa{sv}b)", &id, &iconstr, &title, &subtitle, &body, &time, &action_iter, &draws_attention); app_icon = g_app_info_get_icon (G_APP_INFO (app->info)); - app_iconstr = app_icon ? g_icon_to_string (app_icon) : NULL; + if (app_icon) + { + app_iconstr = g_icon_to_string (app_icon); + symbolic_app_iconstr = get_symbolic_app_icon_string (app_icon); + } action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN); g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app); @@ -629,10 +662,12 @@ im_application_list_message_added (Application *app, } g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, - app->id, app_iconstr, id, iconstr, title, subtitle, body, actions, time, draws_attention); + app->id, app_iconstr, symbolic_app_iconstr, id, + iconstr, title, subtitle, body, actions, time, draws_attention); g_variant_iter_free (action_iter); g_free (app_iconstr); + g_free (symbolic_app_iconstr); g_object_unref (action); } -- cgit v1.2.3 From af3d39b6cc447fad30e97ecdc715e0496e971d85 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 4 Dec 2012 13:58:23 +0000 Subject: im-application-list: initialize local variables with NULL They are not set in every code path but freed at the end of the function. --- src/im-application-list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 77c0e47..da78813 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -577,8 +577,8 @@ im_application_list_message_added (Application *app, gboolean draws_attention; GSimpleAction *action; GIcon *app_icon; - gchar *app_iconstr; - gchar *symbolic_app_iconstr; + gchar *app_iconstr = NULL; + gchar *symbolic_app_iconstr = NULL; GVariant *actions = NULL; g_variant_get (message, "(&s&s&s&s&sxaa{sv}b)", -- cgit v1.2.3 From 40b99f3e6fc6170da525c88cf79186cd9cb565de Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 4 Dec 2012 18:33:55 +0000 Subject: Only expose one application icon (the -symbolic one) --- src/im-application-list.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index da78813..64b15e3 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -302,8 +302,7 @@ im_application_list_class_init (ImApplicationListClass *klass) NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 11, - G_TYPE_STRING, + 10, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, @@ -578,7 +577,6 @@ im_application_list_message_added (Application *app, GSimpleAction *action; GIcon *app_icon; gchar *app_iconstr = NULL; - gchar *symbolic_app_iconstr = NULL; GVariant *actions = NULL; g_variant_get (message, "(&s&s&s&s&sxaa{sv}b)", @@ -586,10 +584,7 @@ im_application_list_message_added (Application *app, app_icon = g_app_info_get_icon (G_APP_INFO (app->info)); if (app_icon) - { - app_iconstr = g_icon_to_string (app_icon); - symbolic_app_iconstr = get_symbolic_app_icon_string (app_icon); - } + app_iconstr = get_symbolic_app_icon_string (app_icon); action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN); g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app); @@ -662,12 +657,11 @@ im_application_list_message_added (Application *app, } g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, - app->id, app_iconstr, symbolic_app_iconstr, id, - iconstr, title, subtitle, body, actions, time, draws_attention); + app->id, app_iconstr, id, iconstr, title, + subtitle, body, actions, time, draws_attention); g_variant_iter_free (action_iter); g_free (app_iconstr); - g_free (symbolic_app_iconstr); g_object_unref (action); } -- cgit v1.2.3 From ae7c525208acc860a5bcd035fc37801f33488c67 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 4 Dec 2012 20:07:50 +0000 Subject: Change icon when there are any messages in the menu --- src/im-application-list.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index da78813..255049f 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -131,6 +131,47 @@ im_application_list_source_activated (GSimpleAction *action, im_application_list_source_removed (app, source_id); } +static guint +g_action_group_get_n_actions (GActionGroup *group) +{ + guint len; + gchar **actions; + + actions = g_action_group_list_actions (group); + len = g_strv_length (actions); + + g_strfreev (actions); + return len; +} + +static gboolean +application_draws_attention (gpointer key, + gpointer value, + gpointer user_data) +{ + Application *app = value; + + return (g_action_group_get_n_actions (G_ACTION_GROUP (app->source_actions)) + + g_action_group_get_n_actions (G_ACTION_GROUP (app->message_actions))) > 0; +} + +static void +im_application_list_update_draws_attention (ImApplicationList *list) +{ + const gchar *icon_name; + GVariant *state; + GActionGroup *main_actions; + + if (g_hash_table_find (list->applications, application_draws_attention, NULL)) + icon_name = "indicator-messages-new"; + else + icon_name = "indicator-messages"; + + main_actions = g_action_muxer_get_group (list->muxer, NULL); + state = g_variant_new ("(sssb)", "", "Messages", icon_name, TRUE); + g_action_group_change_action_state (main_actions, "messages", state); +} + static void im_application_list_message_removed (Application *app, const gchar *id) @@ -138,6 +179,8 @@ im_application_list_message_removed (Application *app, g_simple_action_group_remove (app->message_actions, id); g_action_muxer_remove (app->message_sub_actions, id); + im_application_list_update_draws_attention (app->list); + g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id); } @@ -661,6 +704,8 @@ im_application_list_message_added (Application *app, g_object_unref (action_group); } + im_application_list_update_draws_attention (app->list); + g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, app->id, app_iconstr, symbolic_app_iconstr, id, iconstr, title, subtitle, body, actions, time, draws_attention); @@ -727,6 +772,8 @@ im_application_list_unset_remote (Application *app) g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions)); g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions)); + im_application_list_update_draws_attention (app->list); + if (was_running) g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id); } -- cgit v1.2.3 From 69ee426c0e5d81b95b2907fc8cc1bd7ed2ef559c Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 4 Dec 2012 20:18:34 +0000 Subject: Switch accessible name and icon-name (see last commit) --- src/im-application-list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 255049f..b936859 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -168,7 +168,7 @@ im_application_list_update_draws_attention (ImApplicationList *list) icon_name = "indicator-messages"; main_actions = g_action_muxer_get_group (list->muxer, NULL); - state = g_variant_new ("(sssb)", "", "Messages", icon_name, TRUE); + state = g_variant_new ("(sssb)", "", icon_name, "Messages", TRUE); g_action_group_change_action_state (main_actions, "messages", state); } -- cgit v1.2.3 From 0a1d7c1844dc6104eefe43b38400f3d94868428b Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 5 Dec 2012 10:37:16 +0000 Subject: Don't shorten the app id to seven characters --- src/im-application-list.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 607b0fc..5a7f768 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -411,8 +411,13 @@ im_application_list_canonical_id (const gchar *id) { gchar *str; gchar *p; + int len; - str = g_strndup (id, strlen (id) - g_str_has_suffix (id, ".desktop") ? 7 : 0); + len = strlen (id); + if (g_str_has_suffix (id, ".desktop")) + len -= 8; + + str = g_strndup (id, len); for (p = str; *p; p++) { -- cgit v1.2.3 From c46e38d7ab03589a7c7d4fd5fa52ef0bb5f1a9d5 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 14 Dec 2012 10:56:00 +0100 Subject: im_application_list_proxy_created: fix error condition Also, don't print a warning when the proy couldn't be created because the operation was cancelled. This only happens when the service is shutting down or when one application replaces another one with the same desktop file (in which case we already warn with a more descriptive message). --- src/im-application-list.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 5a7f768..d3d8dad 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -796,9 +796,10 @@ im_application_list_proxy_created (GObject *source_object, GError *error = NULL; app->proxy = indicator_messages_application_proxy_new_finish (result, &error); - if (!app) + if (!app->proxy) { - g_warning ("could not create application proxy: %s", error->message); + if (error->code != G_IO_ERROR_CANCELLED) + g_warning ("could not create application proxy: %s", error->message); g_error_free (error); return; } -- cgit v1.2.3 From 12c0fb327dfef1f778de252c715f3b61bfcaea28 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 14 Dec 2012 10:59:23 +0100 Subject: im_application_list_set_remote: robuster check for running async operation This fixes the case when app->proxy is still NULL but another application with the same desktop file replaces it. This should never happen in practice, but turned up while testing multiple processes which used the same desktop file. Their proxy_create async functions raced each other because the first one's wasn't properly cancelled. Also fixes a small memory leak. --- src/im-application-list.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index d3d8dad..959a820 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -840,11 +840,17 @@ im_application_list_set_remote (ImApplicationList *list, return; } - if (app->proxy || app->cancellable) + if (app->cancellable) { - g_warning ("replacing '%s' at %s with %s", id, unique_bus_name, - g_dbus_proxy_get_name_owner (G_DBUS_PROXY (app->proxy))); + gchar *name_owner = NULL; + + if (app->proxy) + name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (app->proxy)); + g_warning ("replacing '%s' at %s with %s", id, name_owner, unique_bus_name); + im_application_list_unset_remote (app); + + g_free (name_owner); } app->cancellable = g_cancellable_new (); -- 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/im-application-list.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 959a820..9a673c9 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -45,6 +45,7 @@ enum MESSAGE_ADDED, MESSAGE_REMOVED, APP_STOPPED, + REMOVE_ALL, N_SIGNALS }; @@ -251,6 +252,8 @@ im_application_list_remove_all (GSimpleAction *action, GHashTableIter iter; Application *app; + g_signal_emit (list, signals[REMOVE_ALL], 0); + g_hash_table_iter_init (&iter, list->applications); while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &app)) { @@ -377,6 +380,15 @@ im_application_list_class_init (ImApplicationListClass *klass) G_TYPE_NONE, 1, G_TYPE_STRING); + + signals[REMOVE_ALL] = g_signal_new ("remove-all", + IM_TYPE_APPLICATION_LIST, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); } static void -- 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/im-application-list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 9a673c9..3944f3f 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -685,7 +685,7 @@ im_application_list_message_added (Application *app, g_variant_builder_init (&dict_builder, G_VARIANT_TYPE ("a{sv}")); - prefixed_name = g_strjoin (".", app->id, "msg-actions", id, name, NULL); + prefixed_name = g_strjoin (".", "indicator", app->id, "msg-actions", id, name, NULL); g_variant_builder_add (&dict_builder, "{sv}", "name", g_variant_new_string (prefixed_name)); if (label) -- 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/im-application-list.c | 84 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 11 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 3944f3f..8eaa601 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -44,6 +44,7 @@ enum SOURCE_REMOVED, MESSAGE_ADDED, MESSAGE_REMOVED, + APP_ADDED, APP_STOPPED, REMOVE_ALL, N_SIGNALS @@ -57,7 +58,8 @@ typedef struct GDesktopAppInfo *info; gchar *id; IndicatorMessagesApplication *proxy; - GActionMuxer *actions; + GActionMuxer *muxer; + GSimpleActionGroup *actions; GSimpleActionGroup *source_actions; GSimpleActionGroup *message_actions; GActionMuxer *message_sub_actions; @@ -84,9 +86,9 @@ application_free (gpointer data) if (app->proxy) g_object_unref (app->proxy); - if (app->actions) + if (app->muxer) { - g_object_unref (app->actions); + g_object_unref (app->muxer); g_object_unref (app->source_actions); g_object_unref (app->message_actions); g_object_unref (app->message_sub_actions); @@ -371,6 +373,17 @@ im_application_list_class_init (ImApplicationListClass *klass) G_TYPE_STRING, G_TYPE_STRING); + signals[APP_ADDED] = g_signal_new ("app-added", + IM_TYPE_APPLICATION_LIST, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_DESKTOP_APP_INFO); + signals[APP_STOPPED] = g_signal_new ("app-stopped", IM_TYPE_APPLICATION_LIST, G_SIGNAL_RUN_FIRST, @@ -454,6 +467,21 @@ im_application_list_lookup (ImApplicationList *list, return app; } +void +im_application_list_activate_launch (ImApplicationList *list, + GVariant *parameter, + gpointer user_data) +{ + Application *app = user_data; + GError *error = NULL; + + if (!g_app_info_launch (G_APP_INFO (app->info), NULL, NULL, &error)) + { + g_warning ("unable to launch application: %s", error->message); + g_error_free (error); + } +} + void im_application_list_add (ImApplicationList *list, const gchar *desktop_id) @@ -461,6 +489,8 @@ im_application_list_add (ImApplicationList *list, GDesktopAppInfo *info; Application *app; const gchar *id; + GSimpleActionGroup *actions; + GSimpleAction *launch_action; g_return_if_fail (IM_IS_APPLICATION_LIST (list)); g_return_if_fail (desktop_id != NULL); @@ -482,17 +512,29 @@ im_application_list_add (ImApplicationList *list, app->info = info; app->id = im_application_list_canonical_id (id); app->list = list; - app->actions = g_action_muxer_new (); + app->muxer = g_action_muxer_new (); app->source_actions = g_simple_action_group_new (); app->message_actions = g_simple_action_group_new (); app->message_sub_actions = g_action_muxer_new (); - g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions)); - g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions)); - g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions)); + launch_action = g_simple_action_new_stateful ("launch", NULL, g_variant_new_boolean (FALSE)); + g_signal_connect (launch_action, "activate", G_CALLBACK (im_application_list_activate_launch), app); + + actions = g_simple_action_group_new (); + g_action_map_add_action (G_ACTION_MAP (actions), G_ACTION (launch_action)); + + g_action_muxer_insert (app->muxer, NULL, G_ACTION_GROUP (actions)); + g_action_muxer_insert (app->muxer, "src", G_ACTION_GROUP (app->source_actions)); + g_action_muxer_insert (app->muxer, "msg", G_ACTION_GROUP (app->message_actions)); + g_action_muxer_insert (app->muxer, "msg-actions", G_ACTION_GROUP (app->message_sub_actions)); g_hash_table_insert (list->applications, (gpointer) app->id, app); - g_action_muxer_insert (list->muxer, app->id, G_ACTION_GROUP (app->actions)); + g_action_muxer_insert (list->muxer, app->id, G_ACTION_GROUP (app->muxer)); + + g_signal_emit (app->list, signals[APP_ADDED], 0, app->id, app->info); + + g_object_unref (launch_action); + g_object_unref (actions); } void @@ -779,9 +821,9 @@ im_application_list_unset_remote (Application *app) app->source_actions = g_simple_action_group_new (); app->message_actions = g_simple_action_group_new (); app->message_sub_actions = g_action_muxer_new (); - g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions)); - g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions)); - g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions)); + g_action_muxer_insert (app->muxer, "src", G_ACTION_GROUP (app->source_actions)); + g_action_muxer_insert (app->muxer, "msg", G_ACTION_GROUP (app->message_actions)); + g_action_muxer_insert (app->muxer, "msg-actions", G_ACTION_GROUP (app->message_sub_actions)); im_application_list_update_draws_attention (app->list); @@ -878,3 +920,23 @@ im_application_list_get_action_group (ImApplicationList *list) return G_ACTION_GROUP (list->muxer); } + +GList * +im_application_list_get_applications (ImApplicationList *list) +{ + g_return_val_if_fail (IM_IS_APPLICATION_LIST (list), NULL); + + return g_hash_table_get_keys (list->applications); +} + +GDesktopAppInfo * +im_application_list_get_application (ImApplicationList *list, + const gchar *id) +{ + Application *app; + + g_return_val_if_fail (IM_IS_APPLICATION_LIST (list), NULL); + + app = g_hash_table_lookup (list->applications, id); + return app ? app->info : NULL; +} -- cgit v1.2.3 From 2cd06d6f970df9f9f8f8ae67905f88f6518ea25b Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 13 Aug 2013 10:06:59 +0200 Subject: Add application actions --- src/im-application-list.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 8eaa601..95a9cd0 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -468,9 +468,9 @@ im_application_list_lookup (ImApplicationList *list, } void -im_application_list_activate_launch (ImApplicationList *list, - GVariant *parameter, - gpointer user_data) +im_application_list_activate_launch (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) { Application *app = user_data; GError *error = NULL; @@ -482,6 +482,16 @@ im_application_list_activate_launch (ImApplicationList *list, } } +void +im_application_list_activate_app_action (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + Application *app = user_data; + + g_desktop_app_info_launch_action (app->info, g_action_get_name (G_ACTION (action)), NULL); +} + void im_application_list_add (ImApplicationList *list, const gchar *desktop_id) @@ -517,12 +527,27 @@ im_application_list_add (ImApplicationList *list, app->message_actions = g_simple_action_group_new (); app->message_sub_actions = g_action_muxer_new (); + actions = g_simple_action_group_new (); + launch_action = g_simple_action_new_stateful ("launch", NULL, g_variant_new_boolean (FALSE)); g_signal_connect (launch_action, "activate", G_CALLBACK (im_application_list_activate_launch), app); - - actions = g_simple_action_group_new (); g_action_map_add_action (G_ACTION_MAP (actions), G_ACTION (launch_action)); + { + const gchar *const *app_actions; + + for (app_actions = g_desktop_app_info_list_actions (app->info); *app_actions; app_actions++) + { + GSimpleAction *action; + + action = g_simple_action_new (*app_actions, NULL); + g_signal_connect (action, "activate", G_CALLBACK (im_application_list_activate_app_action), app); + g_action_map_add_action (G_ACTION_MAP (actions), G_ACTION (action)); + + g_object_unref (action); + } + } + g_action_muxer_insert (app->muxer, NULL, G_ACTION_GROUP (actions)); g_action_muxer_insert (app->muxer, "src", G_ACTION_GROUP (app->source_actions)); g_action_muxer_insert (app->muxer, "msg", G_ACTION_GROUP (app->message_actions)); -- cgit v1.2.3 From a545cafca29ffcd2044cc69dc5e9871f9e21f0f8 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 13 Aug 2013 13:33:22 +0200 Subject: application list: update draws-attention when necessary --- src/im-application-list.c | 84 ++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 37 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 95a9cd0..f87fcec 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -97,43 +97,6 @@ application_free (gpointer data) g_slice_free (Application, app); } -static void -im_application_list_source_removed (Application *app, - const gchar *id) -{ - g_simple_action_group_remove (app->source_actions, id); - - g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id); -} - -static void -im_application_list_source_activated (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) -{ - Application *app = user_data; - const gchar *source_id; - - source_id = g_action_get_name (G_ACTION (action)); - - if (g_variant_get_boolean (parameter)) - { - indicator_messages_application_call_activate_source (app->proxy, - source_id, - app->cancellable, - NULL, NULL); - } - else - { - const gchar *sources[] = { source_id, NULL }; - const gchar *messages[] = { NULL }; - indicator_messages_application_call_dismiss (app->proxy, sources, messages, - app->cancellable, NULL, NULL); - } - - im_application_list_source_removed (app, source_id); -} - static guint g_action_group_get_n_actions (GActionGroup *group) { @@ -175,6 +138,45 @@ im_application_list_update_draws_attention (ImApplicationList *list) g_action_group_change_action_state (main_actions, "messages", state); } +static void +im_application_list_source_removed (Application *app, + const gchar *id) +{ + g_simple_action_group_remove (app->source_actions, id); + + g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id); + + im_application_list_update_draws_attention (app->list); +} + +static void +im_application_list_source_activated (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + Application *app = user_data; + const gchar *source_id; + + source_id = g_action_get_name (G_ACTION (action)); + + if (g_variant_get_boolean (parameter)) + { + indicator_messages_application_call_activate_source (app->proxy, + source_id, + app->cancellable, + NULL, NULL); + } + else + { + const gchar *sources[] = { source_id, NULL }; + const gchar *messages[] = { NULL }; + indicator_messages_application_call_dismiss (app->proxy, sources, messages, + app->cancellable, NULL, NULL); + } + + im_application_list_source_removed (app, source_id); +} + static void im_application_list_message_removed (Application *app, const gchar *id) @@ -279,6 +281,8 @@ im_application_list_remove_all (GSimpleAction *action, g_strfreev (source_actions); g_strfreev (message_actions); } + + im_application_list_update_draws_attention (list); } static void @@ -578,6 +582,8 @@ im_application_list_remove (ImApplicationList *list, g_hash_table_remove (list->applications, id); g_action_muxer_remove (list->muxer, id); + + im_application_list_update_draws_attention (list); } } @@ -607,6 +613,8 @@ im_application_list_source_added (Application *app, g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, id, label, iconstr); + im_application_list_update_draws_attention (app->list); + g_object_unref (action); } @@ -629,6 +637,8 @@ im_application_list_source_changed (Application *app, g_variant_new ("(uxsb)", count, time, string, draws_attention)); g_signal_emit (app->list, signals[SOURCE_CHANGED], 0, app->id, id, label, iconstr); + + im_application_list_update_draws_attention (app->list); } static void -- 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/im-application-list.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index f87fcec..dd868df 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -861,6 +861,7 @@ im_application_list_unset_remote (Application *app) g_action_muxer_insert (app->muxer, "msg-actions", G_ACTION_GROUP (app->message_sub_actions)); im_application_list_update_draws_attention (app->list); + g_action_group_change_action_state (G_ACTION_GROUP (app->muxer), "launch", g_variant_new_boolean (FALSE)); if (was_running) g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id); @@ -904,6 +905,8 @@ im_application_list_proxy_created (GObject *source_object, g_signal_connect_swapped (app->proxy, "message-added", G_CALLBACK (im_application_list_message_added), app); g_signal_connect_swapped (app->proxy, "message-removed", G_CALLBACK (im_application_list_message_removed), app); + g_action_group_change_action_state (G_ACTION_GROUP (app->muxer), "launch", g_variant_new_boolean (TRUE)); + g_bus_watch_name_on_connection (g_dbus_proxy_get_connection (G_DBUS_PROXY (app->proxy)), g_dbus_proxy_get_name (G_DBUS_PROXY (app->proxy)), G_BUS_NAME_WATCHER_FLAGS_NONE, -- 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/im-application-list.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index dd868df..33b9d4a 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -978,3 +978,12 @@ im_application_list_get_application (ImApplicationList *list, app = g_hash_table_lookup (list->applications, id); return app ? app->info : NULL; } + +void +im_application_list_set_status (ImApplicationList * list, const gchar * id, const gchar *status) +{ + + + return; +} + -- cgit v1.2.3 From 02ba00aad4d9755c96b5706301af60e73eb3786a Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 15 Aug 2013 13:39:42 -0500 Subject: Create a status action --- src/im-application-list.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 33b9d4a..810886a 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -33,6 +33,9 @@ struct _ImApplicationList GHashTable *applications; GActionMuxer *muxer; + + GSimpleActionGroup * globalactions; + GSimpleAction * statusaction; }; G_DEFINE_TYPE (ImApplicationList, im_application_list, G_TYPE_OBJECT); @@ -290,6 +293,9 @@ im_application_list_dispose (GObject *object) { ImApplicationList *list = IM_APPLICATION_LIST (object); + g_clear_object (&list->statusaction); + g_clear_object (&list->globalactions); + g_clear_pointer (&list->applications, g_hash_table_unref); g_clear_object (&list->muxer); @@ -416,17 +422,17 @@ im_application_list_init (ImApplicationList *list) { "remove-all", im_application_list_remove_all } }; - GSimpleActionGroup *actions; - list->applications = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, application_free); - actions = g_simple_action_group_new (); - g_simple_action_group_add_entries (actions, action_entries, G_N_ELEMENTS (action_entries), list); + list->globalactions = g_simple_action_group_new (); + g_simple_action_group_add_entries (list->globalactions, action_entries, G_N_ELEMENTS (action_entries), list); + + list->statusaction = g_simple_action_new_stateful("status", G_VARIANT_TYPE_STRING, g_variant_new_string("offline")); + g_simple_action_group_insert(list->globalactions, G_ACTION(list->statusaction)); list->muxer = g_action_muxer_new (); - g_action_muxer_insert (list->muxer, NULL, G_ACTION_GROUP (actions)); + g_action_muxer_insert (list->muxer, NULL, G_ACTION_GROUP (list->globalactions)); - g_object_unref (actions); } ImApplicationList * -- cgit v1.2.3 From 5ca1b7a06fe94cb7e2d760d9a5a98de022e5376b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 15 Aug 2013 14:29:00 -0500 Subject: Tracking application status --- src/im-application-list.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 810886a..d9b3e2f 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -36,6 +36,8 @@ struct _ImApplicationList GSimpleActionGroup * globalactions; GSimpleAction * statusaction; + + GHashTable *app_status; }; G_DEFINE_TYPE (ImApplicationList, im_application_list, G_TYPE_OBJECT); @@ -295,6 +297,7 @@ im_application_list_dispose (GObject *object) g_clear_object (&list->statusaction); g_clear_object (&list->globalactions); + g_clear_pointer (&list->app_status, g_hash_table_unref); g_clear_pointer (&list->applications, g_hash_table_unref); g_clear_object (&list->muxer); @@ -423,6 +426,7 @@ im_application_list_init (ImApplicationList *list) }; list->applications = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, application_free); + list->app_status = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); list->globalactions = g_simple_action_group_new (); g_simple_action_group_add_entries (list->globalactions, action_entries, G_N_ELEMENTS (action_entries), list); @@ -988,7 +992,11 @@ im_application_list_get_application (ImApplicationList *list, void im_application_list_set_status (ImApplicationList * list, const gchar * id, const gchar *status) { + g_return_if_fail (IM_IS_APPLICATION_LIST (list)); + + g_hash_table_insert(list->app_status, im_application_list_canonical_id(id), g_strdup(status)); + /* TODO: Update status */ return; } -- cgit v1.2.3 From 1f28cf89abf224957c3e9eb60e103d4204958fcc Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 15 Aug 2013 15:21:52 -0500 Subject: Setting up a callback on the activation to set the state and update the applications --- src/im-application-list.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index d9b3e2f..8083704 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -71,6 +71,12 @@ typedef struct GCancellable *cancellable; } Application; + +/* Prototypes */ +static void status_activated (GSimpleAction * action, + GVariant * param, + gpointer user_data); + static void application_free (gpointer data) { @@ -432,6 +438,7 @@ im_application_list_init (ImApplicationList *list) g_simple_action_group_add_entries (list->globalactions, action_entries, G_N_ELEMENTS (action_entries), list); list->statusaction = g_simple_action_new_stateful("status", G_VARIANT_TYPE_STRING, g_variant_new_string("offline")); + g_signal_connect(list->statusaction, "activate", G_CALLBACK(status_activated), list); g_simple_action_group_insert(list->globalactions, G_ACTION(list->statusaction)); list->muxer = g_action_muxer_new (); @@ -989,6 +996,24 @@ im_application_list_get_application (ImApplicationList *list, return app ? app->info : NULL; } +static void +status_activated (GSimpleAction * action, GVariant * param, gpointer user_data) +{ + g_return_if_fail (IM_IS_APPLICATION_LIST(user_data)); + ImApplicationList * list = IM_APPLICATION_LIST(user_data); + + g_simple_action_set_state(action, param); + + /* We assume all the applications are now seeing our status + and updating. We don't need to track their status until + they tell us different. */ + g_hash_table_remove_all(list->app_status); + + /* TODO: Emit a state change */ + + return; +} + void im_application_list_set_status (ImApplicationList * list, const gchar * id, const gchar *status) { -- cgit v1.2.3 From 86cedd8ccb7c779436f5d9cf0caec90dfef97dd7 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 15 Aug 2013 15:28:10 -0500 Subject: Adding a set status signal --- src/im-application-list.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 8083704..878e57f 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -52,6 +52,7 @@ enum APP_ADDED, APP_STOPPED, REMOVE_ALL, + STATUS_SET, N_SIGNALS }; @@ -421,6 +422,16 @@ im_application_list_class_init (ImApplicationListClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + signals[STATUS_SET] = g_signal_new ("status-set", + IM_TYPE_APPLICATION_LIST, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 1, + G_TYPE_STRING); } static void @@ -1009,7 +1020,8 @@ status_activated (GSimpleAction * action, GVariant * param, gpointer user_data) they tell us different. */ g_hash_table_remove_all(list->app_status); - /* TODO: Emit a state change */ + const gchar * status = g_variant_get_string(param, NULL); + g_signal_emit (list, signals[STATUS_SET], 0, status); return; } -- cgit v1.2.3 From 04aad431b226943042233a11aa98e30b9e82c820 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 15 Aug 2013 16:02:00 -0500 Subject: Setting the status of the menu based on the aggregate application status --- src/im-application-list.c | 49 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 878e57f..b23923a 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -1026,15 +1026,56 @@ status_activated (GSimpleAction * action, GVariant * param, gpointer user_data) return; } +#define STATUS_ID_OFFLINE (G_N_ELEMENTS(status_ids) - 1) +static const gchar *status_ids[] = { "available", "away", "busy", "invisible", "offline" }; + +static guint +status2val (const gchar * string) +{ + if (string == NULL) return STATUS_ID_OFFLINE; + + guint i; + for (i = 0; i < G_N_ELEMENTS(status_ids); i++) { + if (g_strcmp0(status_ids[i], string) == 0) { + break; + } + } + + if (i > STATUS_ID_OFFLINE) + i = STATUS_ID_OFFLINE; + + return i; +} + void im_application_list_set_status (ImApplicationList * list, const gchar * id, const gchar *status) { - g_return_if_fail (IM_IS_APPLICATION_LIST (list)); + g_return_if_fail (IM_IS_APPLICATION_LIST (list)); - g_hash_table_insert(list->app_status, im_application_list_canonical_id(id), g_strdup(status)); + g_hash_table_insert(list->app_status, im_application_list_canonical_id(id), g_strdup(status)); - /* TODO: Update status */ + GVariant * action_state = NULL; + g_object_get(list->statusaction, "state", &action_state, NULL); - return; + guint final_status = STATUS_ID_OFFLINE; + + if (action_state != NULL) { + final_status = status2val(g_variant_get_string(action_state, NULL)); + g_variant_unref(action_state); + } + + GList * statuses = g_hash_table_get_values(list->app_status); + GList * statusentry; + + for (statusentry = statuses; statusentry != NULL; statusentry = g_list_next(statusentry)) { + guint statusval = status2val((gchar *)statusentry->data); + final_status = MIN(final_status, statusval); + } + + g_list_free(statuses); + + g_simple_action_set_state(list->statusaction, g_variant_new_string(status_ids[final_status])); + + return; } -- cgit v1.2.3 From 922fb55f693e3ac2523414a150b667bd0236138a Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 15 Aug 2013 16:13:49 -0500 Subject: Couldn't make that assumption, instead assume they're all listening and adjust themselves or tell us otherwise --- src/im-application-list.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index b23923a..aaa1c38 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -1012,15 +1012,21 @@ status_activated (GSimpleAction * action, GVariant * param, gpointer user_data) { g_return_if_fail (IM_IS_APPLICATION_LIST(user_data)); ImApplicationList * list = IM_APPLICATION_LIST(user_data); + const gchar * status = g_variant_get_string(param, NULL); g_simple_action_set_state(action, param); - /* We assume all the applications are now seeing our status - and updating. We don't need to track their status until - they tell us different. */ - g_hash_table_remove_all(list->app_status); + GList * appshash = g_hash_table_get_keys(list->app_status); + GList * appsfree = g_list_copy_deep(appshash, (GCopyFunc)g_strdup, NULL); + GList * app; + + for (app = appsfree; app != NULL; app = g_list_next(app)) { + g_hash_table_insert(list->app_status, app->data, g_strdup(status)); + } + + g_list_free(appshash); + g_list_free(appsfree); - const gchar * status = g_variant_get_string(param, NULL); g_signal_emit (list, signals[STATUS_SET], 0, status); return; @@ -1054,16 +1060,8 @@ im_application_list_set_status (ImApplicationList * list, const gchar * id, cons g_hash_table_insert(list->app_status, im_application_list_canonical_id(id), g_strdup(status)); - GVariant * action_state = NULL; - g_object_get(list->statusaction, "state", &action_state, NULL); - guint final_status = STATUS_ID_OFFLINE; - if (action_state != NULL) { - final_status = status2val(g_variant_get_string(action_state, NULL)); - g_variant_unref(action_state); - } - GList * statuses = g_hash_table_get_values(list->app_status); GList * statusentry; -- cgit v1.2.3 From b0626bc33d3ec1b0580869045c1b2c5ff295d05c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 16 Aug 2013 09:24:22 -0500 Subject: Making it so that we cache the draw attention state in the app --- src/im-application-list.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index aaa1c38..2be470e 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -70,6 +70,7 @@ typedef struct GSimpleActionGroup *message_actions; GActionMuxer *message_sub_actions; GCancellable *cancellable; + gboolean draws_attention; } Application; @@ -109,19 +110,6 @@ application_free (gpointer data) g_slice_free (Application, app); } -static guint -g_action_group_get_n_actions (GActionGroup *group) -{ - guint len; - gchar **actions; - - actions = g_action_group_list_actions (group); - len = g_strv_length (actions); - - g_strfreev (actions); - return len; -} - static gboolean application_draws_attention (gpointer key, gpointer value, @@ -129,8 +117,7 @@ application_draws_attention (gpointer key, { Application *app = value; - return (g_action_group_get_n_actions (G_ACTION_GROUP (app->source_actions)) + - g_action_group_get_n_actions (G_ACTION_GROUP (app->message_actions))) > 0; + return app->draws_attention; } static void @@ -558,6 +545,7 @@ im_application_list_add (ImApplicationList *list, app->source_actions = g_simple_action_group_new (); app->message_actions = g_simple_action_group_new (); app->message_sub_actions = g_action_muxer_new (); + app->draws_attention = FALSE; actions = g_simple_action_group_new (); @@ -641,6 +629,9 @@ im_application_list_source_added (Application *app, g_signal_emit (app->list, signals[SOURCE_ADDED], 0, app->id, id, label, iconstr); + if (draws_attention) + app->draws_attention = TRUE; + im_application_list_update_draws_attention (app->list); g_object_unref (action); -- cgit v1.2.3 From 201482b9190f616031e1db01a648d3d943f6fa5f Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 16 Aug 2013 09:25:56 -0500 Subject: Forgot to draw attention for new messages --- src/im-application-list.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 2be470e..d9426f9 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -812,6 +812,9 @@ im_application_list_message_added (Application *app, g_object_unref (action_group); } + if (draws_attention) + app->draws_attention = TRUE; + im_application_list_update_draws_attention (app->list); g_signal_emit (app->list, signals[MESSAGE_ADDED], 0, -- cgit v1.2.3 From 4c8c9dc742282e4bf63c2931c61dff5b89ea5cb9 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 16 Aug 2013 09:55:54 -0500 Subject: Stop removing sources, just set them to no longer draw attention --- src/im-application-list.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index d9426f9..2acb3d9 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -245,6 +245,53 @@ im_application_list_sub_message_activated (GSimpleAction *action, im_application_list_message_removed (app, message_id); } +/* If a source has a draw_attention state set, this clears it so that it + doesn't get calculated to draw attention */ +static void +im_application_list_source_clear_attention (Application * app, + gchar * source_name) +{ + GVariant * action_value = NULL; + GVariant * action_state = g_action_group_get_action_state(G_ACTION_GROUP(app->source_actions), source_name); + + /* If it doesn't draw attention, we're done */ + action_value = g_variant_get_child_value(action_state, 3); + if (!g_variant_get_boolean(action_value)) + { + g_variant_unref(action_value); + g_variant_unref(action_state); + return; + } + + g_variant_unref(action_value); + + /* We need to build a new state without the draw attention */ + GVariantBuilder new_state_builder; + g_variant_builder_init(&new_state_builder, G_VARIANT_TYPE_TUPLE); + + /* Count */ + action_value = g_variant_get_child_value(action_state, 0); + g_variant_builder_add_value(&new_state_builder, action_value); + g_variant_unref(action_value); + + /* Time */ + action_value = g_variant_get_child_value(action_state, 1); + g_variant_builder_add_value(&new_state_builder, action_value); + g_variant_unref(action_value); + + /* String */ + action_value = g_variant_get_child_value(action_state, 2); + g_variant_builder_add_value(&new_state_builder, action_value); + g_variant_unref(action_value); + + /* Draws Attention */ + g_variant_builder_add_value(&new_state_builder, g_variant_new_boolean(FALSE)); + + g_action_group_change_action_state(G_ACTION_GROUP(app->source_actions), source_name, g_variant_builder_end(&new_state_builder)); + + g_variant_unref(action_state); + return; +} static void im_application_list_remove_all (GSimpleAction *action, @@ -266,7 +313,7 @@ im_application_list_remove_all (GSimpleAction *action, source_actions = g_action_group_list_actions (G_ACTION_GROUP (app->source_actions)); for (it = source_actions; *it; it++) - im_application_list_source_removed (app, *it); + im_application_list_source_clear_attention (app, *it); message_actions = g_action_group_list_actions (G_ACTION_GROUP (app->message_actions)); for (it = message_actions; *it; it++) @@ -279,6 +326,8 @@ im_application_list_remove_all (GSimpleAction *action, g_strfreev (source_actions); g_strfreev (message_actions); + + app->draws_attention = FALSE; } im_application_list_update_draws_attention (list); -- cgit v1.2.3 From 234e9dd70074a0eb4734ced3a271447d44a29a8b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 16 Aug 2013 10:16:10 -0500 Subject: Only dismiss if there is a proxy connected and the application is remote --- src/im-application-list.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 2acb3d9..47d81ce 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -319,10 +319,14 @@ im_application_list_remove_all (GSimpleAction *action, for (it = message_actions; *it; it++) im_application_list_message_removed (app, *it); - indicator_messages_application_call_dismiss (app->proxy, - (const gchar * const *) source_actions, - (const gchar * const *) message_actions, - app->cancellable, NULL, NULL); + if (app->proxy != NULL) /* If it is remote, we tell the app we've cleared */ + { + gchar * null_list[1] = { NULL }; + indicator_messages_application_call_dismiss (app->proxy, + (const gchar * const *) null_list, + (const gchar * const *) message_actions, + app->cancellable, NULL, NULL); + } g_strfreev (source_actions); g_strfreev (message_actions); -- cgit v1.2.3 From cacbeac6d8aafa701a80a57475a768bab54b8b2b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 16 Aug 2013 10:22:09 -0500 Subject: Whitespace --- src/im-application-list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 47d81ce..7d75c84 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -321,7 +321,7 @@ im_application_list_remove_all (GSimpleAction *action, if (app->proxy != NULL) /* If it is remote, we tell the app we've cleared */ { - gchar * null_list[1] = { NULL }; + gchar * null_list[1] = { NULL }; indicator_messages_application_call_dismiss (app->proxy, (const gchar * const *) null_list, (const gchar * const *) message_actions, -- cgit v1.2.3 From 08739c5fe918d9aef5b3f2f8b0e86a2fbed08a7f Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 16 Aug 2013 14:01:36 -0500 Subject: Dropping indicator prefixes as they're set up with the base namespace of the section --- src/im-application-list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 7d75c84..5a56df3 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -834,7 +834,7 @@ im_application_list_message_added (Application *app, g_variant_builder_init (&dict_builder, G_VARIANT_TYPE ("a{sv}")); - prefixed_name = g_strjoin (".", "indicator", app->id, "msg-actions", id, name, NULL); + prefixed_name = g_strjoin (".", app->id, "msg-actions", id, name, NULL); g_variant_builder_add (&dict_builder, "{sv}", "name", g_variant_new_string (prefixed_name)); if (label) -- cgit v1.2.3 From 341152a55798c18a4116f6940bbe6a3aaf28355c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sun, 18 Aug 2013 22:50:15 -0500 Subject: clearing the sources on remove all --- src/im-application-list.c | 53 ++--------------------------------------------- 1 file changed, 2 insertions(+), 51 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 5a56df3..5884048 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -245,54 +245,6 @@ im_application_list_sub_message_activated (GSimpleAction *action, im_application_list_message_removed (app, message_id); } -/* If a source has a draw_attention state set, this clears it so that it - doesn't get calculated to draw attention */ -static void -im_application_list_source_clear_attention (Application * app, - gchar * source_name) -{ - GVariant * action_value = NULL; - GVariant * action_state = g_action_group_get_action_state(G_ACTION_GROUP(app->source_actions), source_name); - - /* If it doesn't draw attention, we're done */ - action_value = g_variant_get_child_value(action_state, 3); - if (!g_variant_get_boolean(action_value)) - { - g_variant_unref(action_value); - g_variant_unref(action_state); - return; - } - - g_variant_unref(action_value); - - /* We need to build a new state without the draw attention */ - GVariantBuilder new_state_builder; - g_variant_builder_init(&new_state_builder, G_VARIANT_TYPE_TUPLE); - - /* Count */ - action_value = g_variant_get_child_value(action_state, 0); - g_variant_builder_add_value(&new_state_builder, action_value); - g_variant_unref(action_value); - - /* Time */ - action_value = g_variant_get_child_value(action_state, 1); - g_variant_builder_add_value(&new_state_builder, action_value); - g_variant_unref(action_value); - - /* String */ - action_value = g_variant_get_child_value(action_state, 2); - g_variant_builder_add_value(&new_state_builder, action_value); - g_variant_unref(action_value); - - /* Draws Attention */ - g_variant_builder_add_value(&new_state_builder, g_variant_new_boolean(FALSE)); - - g_action_group_change_action_state(G_ACTION_GROUP(app->source_actions), source_name, g_variant_builder_end(&new_state_builder)); - - g_variant_unref(action_state); - return; -} - static void im_application_list_remove_all (GSimpleAction *action, GVariant *parameter, @@ -313,7 +265,7 @@ im_application_list_remove_all (GSimpleAction *action, source_actions = g_action_group_list_actions (G_ACTION_GROUP (app->source_actions)); for (it = source_actions; *it; it++) - im_application_list_source_clear_attention (app, *it); + im_application_list_source_removed (app, *it); message_actions = g_action_group_list_actions (G_ACTION_GROUP (app->message_actions)); for (it = message_actions; *it; it++) @@ -321,9 +273,8 @@ im_application_list_remove_all (GSimpleAction *action, if (app->proxy != NULL) /* If it is remote, we tell the app we've cleared */ { - gchar * null_list[1] = { NULL }; indicator_messages_application_call_dismiss (app->proxy, - (const gchar * const *) null_list, + (const gchar * const *) source_actions, (const gchar * const *) message_actions, app->cancellable, NULL, NULL); } -- cgit v1.2.3 From 2673fba29a0f3bd090dc3a8dc0002d91ebf401a1 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sun, 18 Aug 2013 23:13:51 -0500 Subject: Starting to regen the draw attention flag from the source actions --- src/im-application-list.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 5884048..8078582 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -137,6 +137,47 @@ im_application_list_update_draws_attention (ImApplicationList *list) g_action_group_change_action_state (main_actions, "messages", state); } +/* Check a source action to see if it draws */ +static gboolean +app_source_action_check_draw (Application * app, const gchar * action_name) +{ + + return FALSE; +} + +/* Check a message action to see if it draws */ +static gboolean +app_message_action_check_draw (Application * app, const gchar * action_name) +{ + + return FALSE; +} + +/* Regenerate the draw attention flag based on the sources and messages + that we have in the action groups */ +static void +app_check_draw_attention (Application * app) +{ + gchar **source_actions = NULL; + gchar **message_actions = NULL; + gchar **it; + + source_actions = g_action_group_list_actions (G_ACTION_GROUP (app->source_actions)); + for (it = source_actions; *it && !app->draws_attention; it++) + app->draws_attention = app_source_action_check_draw (app, *it); + + message_actions = g_action_group_list_actions (G_ACTION_GROUP (app->message_actions)); + for (it = message_actions; *it; it++) + app->draws_attention = app_message_action_check_draw (app, *it); + + g_strfreev (source_actions); + g_strfreev (message_actions); + + return; +} + +/* Remove a source from an application, signal up and update the status + of the draws attention flag. */ static void im_application_list_source_removed (Application *app, const gchar *id) @@ -145,6 +186,12 @@ im_application_list_source_removed (Application *app, g_signal_emit (app->list, signals[SOURCE_REMOVED], 0, app->id, id); + if (app->draws_attention) + { + app->draws_attention = FALSE; + app_check_draw_attention(app); + } + im_application_list_update_draws_attention (app->list); } @@ -263,6 +310,8 @@ im_application_list_remove_all (GSimpleAction *action, gchar **message_actions; gchar **it; + app->draws_attention = FALSE; + source_actions = g_action_group_list_actions (G_ACTION_GROUP (app->source_actions)); for (it = source_actions; *it; it++) im_application_list_source_removed (app, *it); @@ -281,8 +330,6 @@ im_application_list_remove_all (GSimpleAction *action, g_strfreev (source_actions); g_strfreev (message_actions); - - app->draws_attention = FALSE; } im_application_list_update_draws_attention (list); -- cgit v1.2.3 From a48ab9b84578f6d3f22d7be310d8e32be779c0e0 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sun, 18 Aug 2013 23:17:35 -0500 Subject: Check the action state to get whether it's drawing or not --- src/im-application-list.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index 8078582..fedd9e1 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -141,14 +141,27 @@ im_application_list_update_draws_attention (ImApplicationList *list) static gboolean app_source_action_check_draw (Application * app, const gchar * action_name) { + gboolean retval = FALSE; + GVariant * state; + GVariant * draw; - return FALSE; + state = g_action_group_get_action_state (G_ACTION_GROUP(app->source_actions), action_name); + + /* uxsb */ + draw = g_variant_get_child_value(state, 3); + retval = g_variant_get_boolean(draw); + + g_variant_unref(draw); + g_variant_unref(state); + + return retval; } /* Check a message action to see if it draws */ static gboolean app_message_action_check_draw (Application * app, const gchar * action_name) { + /* TODO: Not stored currently */ return FALSE; } -- cgit v1.2.3 From 00d61143f54e7b0e2551f6db54b8c6ba4deef250 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sun, 18 Aug 2013 23:25:05 -0500 Subject: Save the draws attention for messages and react to that --- src/im-application-list.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/im-application-list.c') diff --git a/src/im-application-list.c b/src/im-application-list.c index fedd9e1..bba7972 100644 --- a/src/im-application-list.c +++ b/src/im-application-list.c @@ -41,6 +41,7 @@ struct _ImApplicationList }; G_DEFINE_TYPE (ImApplicationList, im_application_list, G_TYPE_OBJECT); +G_DEFINE_QUARK (draws_attention, message_action_draws_attention); enum { @@ -161,9 +162,9 @@ app_source_action_check_draw (Application * app, const gchar * action_name) static gboolean app_message_action_check_draw (Application * app, const gchar * action_name) { - /* TODO: Not stored currently */ - - return FALSE; + GAction * action = NULL; + action = g_simple_action_group_lookup (app->message_actions, action_name); + return GPOINTER_TO_INT(g_object_get_qdata(G_OBJECT(action), message_action_draws_attention_quark())); } /* Regenerate the draw attention flag based on the sources and messages @@ -807,6 +808,7 @@ im_application_list_message_added (Application *app, app_iconstr = get_symbolic_app_icon_string (app_icon); action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN); + g_object_set_qdata(G_OBJECT(action), message_action_draws_attention_quark(), GINT_TO_POINTER(draws_attention)); g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app); g_simple_action_group_insert (app->message_actions, G_ACTION (action)); -- cgit v1.2.3