From af9183664c534c39d12e34b5c8e7c14ea189ce8b Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 5 Sep 2012 15:21:16 +0200 Subject: Watch desktop files for changes This introduces a slightly clumsy "destroy" signal for AppSection to notify outsiders that the desktop file was deleted. This will do for now, but a larger refactoring which pulls all the desktop-file-reading code out of appsection is in order. --- src/app-section.c | 121 ++++++++++++++++++++++++++++++++++++++++++------- src/messages-service.c | 34 ++++++++++---- 2 files changed, 129 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/app-section.c b/src/app-section.c index bed1302..58f1612 100644 --- a/src/app-section.c +++ b/src/app-section.c @@ -37,6 +37,7 @@ with this program. If not, see . struct _AppSectionPrivate { GDesktopAppInfo * appinfo; + GFileMonitor *desktop_file_monitor; guint unreadcount; IndicatorDesktopShortcuts * ids; @@ -64,6 +65,7 @@ enum { }; static GParamSpec *properties[NUM_PROPERTIES]; +guint destroy_signal; /* Prototypes */ static void app_section_class_init (AppSectionClass *klass); @@ -98,6 +100,11 @@ static void action_removed (GActionGroup *group, const gchar *action_name, gpointer user_data); static gboolean action_draws_attention (GVariant *state); +static void desktop_file_changed_cb (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event, + gpointer user_data); /* GObject Boilerplate */ G_DEFINE_TYPE (AppSection, app_section, G_TYPE_OBJECT); @@ -138,6 +145,14 @@ app_section_class_init (AppSectionClass *klass) G_PARAM_READABLE); g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); + + destroy_signal = g_signal_new ("destroy", + APP_SECTION_TYPE, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -209,12 +224,18 @@ app_section_set_property (GObject *object, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } + static void app_section_dispose (GObject *object) { AppSection * self = APP_SECTION(object); AppSectionPrivate * priv = self->priv; + if (priv->desktop_file_monitor) { + g_signal_handlers_disconnect_by_func (priv->desktop_file_monitor, desktop_file_changed_cb, self); + g_clear_object (&priv->desktop_file_monitor); + } + g_clear_object (&priv->menu); g_clear_object (&priv->static_shortcuts); @@ -289,6 +310,9 @@ keyfile_loaded (GObject *source_object, G_KEY_FILE_DESKTOP_GROUP, "X-MessagingMenu-UsesChatSection", &error); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]); + if (error) { if (error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) { g_warning ("could not read X-MessagingMenu-UsesChatSection: %s", @@ -298,34 +322,48 @@ keyfile_loaded (GObject *source_object, goto out; } - if (self->priv->uses_chat_status) - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]); - out: g_key_file_free (keyfile); g_free (contents); } static void -app_section_set_app_info (AppSection *self, - GDesktopAppInfo *appinfo) +g_menu_clear (GMenu *menu) +{ + gint n_items = g_menu_model_get_n_items (G_MENU_MODEL (menu)); + + while (n_items--) + g_menu_remove (menu, 0); +} + +static void +g_simple_action_group_clear (GSimpleActionGroup *group) +{ + gchar **actions; + gchar **it; + + actions = g_action_group_list_actions (G_ACTION_GROUP (group)); + for (it = actions; *it; it++) + g_simple_action_group_remove (group, *it); + + g_strfreev (actions); +} + +static void +app_section_update_menu (AppSection *self) { AppSectionPrivate *priv = self->priv; GSimpleAction *launch; GFile *keyfile; GMenuItem *item; gchar *iconstr; + gboolean is_running; - g_return_if_fail (priv->appinfo == NULL); + g_menu_clear (priv->menu); + g_simple_action_group_clear (priv->static_shortcuts); - if (appinfo == NULL) { - g_warning ("appinfo must not be NULL"); - return; - } - - priv->appinfo = g_object_ref (appinfo); - - launch = g_simple_action_new_stateful ("launch", NULL, g_variant_new_boolean (FALSE)); + is_running = priv->name_watch_id > 0; + launch = g_simple_action_new_stateful ("launch", NULL, g_variant_new_boolean (is_running)); g_signal_connect (launch, "activate", G_CALLBACK (activate_cb), self); g_signal_connect (launch, "change-state", G_CALLBACK (launch_action_change_state), self); g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (launch)); @@ -366,14 +404,65 @@ app_section_set_app_info (AppSection *self, keyfile = g_file_new_for_path (g_desktop_app_info_get_filename (priv->appinfo)); g_file_load_contents_async (keyfile, NULL, keyfile_loaded, self); - g_object_unref (keyfile); - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APPINFO]); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]); + g_object_unref (keyfile); g_object_unref (launch); } +static void +desktop_file_changed_cb (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event, + gpointer user_data) +{ + AppSection *self = user_data; + + if (event == G_FILE_MONITOR_EVENT_CHANGED) { + app_section_update_menu (self); + } + else if (event == G_FILE_MONITOR_EVENT_DELETED || + event == G_FILE_MONITOR_EVENT_UNMOUNTED) { + g_signal_emit (self, destroy_signal, 0); + } +} + +static void +app_section_set_app_info (AppSection *self, + GDesktopAppInfo *appinfo) +{ + AppSectionPrivate *priv = self->priv; + GFile *desktop_file; + GError *error = NULL; + + g_return_if_fail (priv->appinfo == NULL); + g_return_if_fail (priv->desktop_file_monitor == NULL); + + if (appinfo == NULL) { + g_warning ("appinfo must not be NULL"); + return; + } + + priv->appinfo = g_object_ref (appinfo); + + desktop_file = g_file_new_for_path (g_desktop_app_info_get_filename (appinfo)); + priv->desktop_file_monitor = g_file_monitor (desktop_file, G_FILE_MONITOR_SEND_MOVED, NULL, &error); + if (priv->desktop_file_monitor == NULL) { + g_warning ("unable to watch desktop file: %s", error->message); + g_error_free (error); + } + g_signal_connect (priv->desktop_file_monitor, "changed", + G_CALLBACK (desktop_file_changed_cb), self); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APPINFO]); + + app_section_update_menu (self); + + g_object_unref (desktop_file); +} + AppSection * app_section_new (GDesktopAppInfo *appinfo) { diff --git a/src/messages-service.c b/src/messages-service.c index 15c5123..ed9bfe4 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -45,7 +45,6 @@ static GMenu *menu; static GMenuModel *chat_section; static GSettings *settings; - static gchar * g_app_info_get_simple_id (GAppInfo *appinfo) { @@ -138,6 +137,23 @@ uses_chat_status_changed (GObject *object, g_object_unref (first_section); } +static void +remove_section (AppSection *section, + const gchar *id) +{ + int pos = g_menu_find_section (menu, app_section_get_menu (section)); + if (pos >= 0) + g_menu_remove (menu, pos); + g_action_muxer_remove (action_muxer, id); + + g_signal_handlers_disconnect_by_func (section, actions_changed, NULL); + g_signal_handlers_disconnect_by_func (section, draws_attention_changed, NULL); + g_signal_handlers_disconnect_by_func (section, uses_chat_status_changed, NULL); + g_signal_handlers_disconnect_by_func (section, remove_section, NULL); + + g_hash_table_remove (applications, id); +} + static AppSection * add_application (const gchar *desktop_id) { @@ -167,6 +183,11 @@ add_application (const gchar *desktop_id) G_CALLBACK (draws_attention_changed), NULL); g_signal_connect (section, "notify::uses-chat-status", G_CALLBACK (uses_chat_status_changed), NULL); + g_signal_connect_data (section, "destroy", + G_CALLBACK (remove_section), + g_strdup (id), + (GClosureNotify) g_free, + 0); /* TODO insert it at the right position (alphabetically by application name) */ menuitem = g_menu_item_new_section (NULL, app_section_get_menu (section)); @@ -197,20 +218,13 @@ remove_application (const char *desktop_id) section = g_hash_table_lookup (applications, id); if (section) { - int pos = g_menu_find_section (menu, app_section_get_menu (section)); - if (pos >= 0) - g_menu_remove (menu, pos); - g_action_muxer_remove (action_muxer, id); - - g_signal_handlers_disconnect_by_func (section, actions_changed, NULL); - g_signal_handlers_disconnect_by_func (section, draws_attention_changed, NULL); - g_signal_handlers_disconnect_by_func (section, uses_chat_status_changed, NULL); + remove_section (section, id); } else { + g_hash_table_remove (applications, id); g_warning ("could not remove '%s', it's not registered", desktop_id); } - g_hash_table_remove (applications, id); g_free (id); g_object_unref (appinfo); } -- cgit v1.2.3 From 45adbc05cf2b51986f8cfc085fe71d061c7fc406 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 5 Sep 2012 15:27:09 +0200 Subject: app-section: remove unused private member --- src/app-section.c | 10 ---------- src/app-section.h | 1 - 2 files changed, 11 deletions(-) (limited to 'src') diff --git a/src/app-section.c b/src/app-section.c index 58f1612..df79582 100644 --- a/src/app-section.c +++ b/src/app-section.c @@ -38,7 +38,6 @@ struct _AppSectionPrivate { GDesktopAppInfo * appinfo; GFileMonitor *desktop_file_monitor; - guint unreadcount; IndicatorDesktopShortcuts * ids; @@ -166,7 +165,6 @@ app_section_init (AppSection *self) priv = self->priv; priv->appinfo = NULL; - priv->unreadcount = 0; priv->menu = g_menu_new (); priv->static_shortcuts = g_simple_action_group_new (); @@ -496,14 +494,6 @@ launch_action_change_state (GSimpleAction *action, g_simple_action_set_state (action, value); } -guint -app_section_get_count (AppSection * self) -{ - AppSectionPrivate * priv = self->priv; - - return priv->unreadcount; -} - const gchar * app_section_get_name (AppSection * self) { diff --git a/src/app-section.h b/src/app-section.h index 711fdc9..32ebbf0 100644 --- a/src/app-section.h +++ b/src/app-section.h @@ -51,7 +51,6 @@ struct _AppSection { GType app_section_get_type (void); AppSection * app_section_new (GDesktopAppInfo *appinfo); -guint app_section_get_count (AppSection * appitem); const gchar * app_section_get_name (AppSection * appitem); const gchar * app_section_get_desktop (AppSection * appitem); GActionGroup * app_section_get_actions (AppSection *self); -- cgit v1.2.3 From 10d5f6214a815d401db7a3ca3f9fc3de8d68cd16 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 5 Sep 2012 21:11:39 +0200 Subject: app-section.c: make destroy_signal static --- src/app-section.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/app-section.c b/src/app-section.c index df79582..9bf5087 100644 --- a/src/app-section.c +++ b/src/app-section.c @@ -64,7 +64,7 @@ enum { }; static GParamSpec *properties[NUM_PROPERTIES]; -guint destroy_signal; +static guint destroy_signal; /* Prototypes */ static void app_section_class_init (AppSectionClass *klass); -- cgit v1.2.3 From d1da13ed474cfe3053d65833bb4ec2e61f47b440 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 5 Sep 2012 21:13:07 +0200 Subject: app-section.c: remove unused function app_section_get_name --- src/app-section.c | 11 ----------- src/app-section.h | 1 - 2 files changed, 12 deletions(-) (limited to 'src') diff --git a/src/app-section.c b/src/app-section.c index 9bf5087..523e249 100644 --- a/src/app-section.c +++ b/src/app-section.c @@ -494,17 +494,6 @@ launch_action_change_state (GSimpleAction *action, g_simple_action_set_state (action, value); } -const gchar * -app_section_get_name (AppSection * self) -{ - AppSectionPrivate * priv = self->priv; - - if (priv->appinfo) { - return g_app_info_get_name(G_APP_INFO(priv->appinfo)); - } - return NULL; -} - const gchar * app_section_get_desktop (AppSection * self) { diff --git a/src/app-section.h b/src/app-section.h index 32ebbf0..09697c5 100644 --- a/src/app-section.h +++ b/src/app-section.h @@ -51,7 +51,6 @@ struct _AppSection { GType app_section_get_type (void); AppSection * app_section_new (GDesktopAppInfo *appinfo); -const gchar * app_section_get_name (AppSection * appitem); const gchar * app_section_get_desktop (AppSection * appitem); GActionGroup * app_section_get_actions (AppSection *self); GMenuModel * app_section_get_menu (AppSection *appitem); -- cgit v1.2.3 From bdf943c3c2d9aef1511d24e928e9d8652a17e703 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 5 Sep 2012 21:25:28 +0200 Subject: messages-service.c: remove redundant g_hash_table_remove --- src/messages-service.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/messages-service.c b/src/messages-service.c index ed9bfe4..acf4995 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -221,7 +221,6 @@ remove_application (const char *desktop_id) remove_section (section, id); } else { - g_hash_table_remove (applications, id); g_warning ("could not remove '%s', it's not registered", desktop_id); } -- cgit v1.2.3