Updating branch refs/heads/jannis/global-monitoring to a45a599c89f2ef788f0d67d81d431aeea94285e9 (commit) from 76e190ae8d0d4e98f59ef59c00cf9d4c1e91eb8f (commit)
commit a45a599c89f2ef788f0d67d81d431aeea94285e9 Author: Jannis Pohlmann <jan...@xfce.org> Date: Mon Aug 30 14:57:06 2010 +0200 Squashme garcon/garcon-config.h | 10 +- garcon/garcon-config.h.in | 11 +- garcon/garcon-menu-item-pool.c | 3 - garcon/garcon-menu-item.c | 38 ++++- garcon/garcon-menu.c | 384 +++++++++++++++++++++++++++++---------- tests/test-display-menu.c | 44 +++++ 6 files changed, 374 insertions(+), 116 deletions(-) diff --git a/garcon/garcon-config.h b/garcon/garcon-config.h index ee4c119..27f2c35 100644 --- a/garcon/garcon-config.h +++ b/garcon/garcon-config.h @@ -1,7 +1,7 @@ /* $Id$ */ /* vi:set expandtab sw=2 sts=2: */ /*- - * Copyright (c) 2008 Jannis Pohlmann <jan...@xfce.org> + * Copyright (c) 2008-2010 Jannis Pohlmann <jan...@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -83,12 +83,12 @@ extern const guint garcon_major_version; extern const guint garcon_minor_version; extern const guint garcon_micro_version; -const gchar *garcon_check_version (guint required_major, - guint required_minor, - guint required_micro); +const gchar *garcon_check_version (guint required_major, + guint required_minor, + guint required_micro); -gchar **garcon_config_build_paths (const gchar *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; gchar *garcon_config_lookup (const gchar *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +gchar **garcon_config_build_paths (const gchar *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; G_END_DECLS diff --git a/garcon/garcon-config.h.in b/garcon/garcon-config.h.in index baae3b8..1cb70f8 100644 --- a/garcon/garcon-config.h.in +++ b/garcon/garcon-config.h.in @@ -1,7 +1,7 @@ /* $Id$ */ /* vi:set expandtab sw=2 sts=2: */ /*- - * Copyright (c) 2008 Jannis Pohlmann <jan...@xfce.org> + * Copyright (c) 2008-2010 Jannis Pohlmann <jan...@xfce.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -83,11 +83,12 @@ extern const guint garcon_major_version; extern const guint garcon_minor_version; extern const guint garcon_micro_version; -const gchar *garcon_check_version (guint required_major, - guint required_minor, - guint required_micro); +const gchar *garcon_check_version (guint required_major, + guint required_minor, + guint required_micro); -gchar *garcon_config_lookup (const gchar *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +gchar *garcon_config_lookup (const gchar *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +gchar **garcon_config_build_paths (const gchar *filename) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; G_END_DECLS diff --git a/garcon/garcon-menu-item-pool.c b/garcon/garcon-menu-item-pool.c index 5e55ff8..ccd2654 100644 --- a/garcon/garcon-menu-item-pool.c +++ b/garcon/garcon-menu-item-pool.c @@ -133,9 +133,6 @@ garcon_menu_item_pool_remove (GarconMenuItemPool *pool, /* Remove the item from the hash table */ g_hash_table_remove (pool->priv->items, garcon_menu_item_get_desktop_id (item)); - - /* Release the reference on the item */ - garcon_menu_item_unref (item); } diff --git a/garcon/garcon-menu-item.c b/garcon/garcon-menu-item.c index cc1b91c..f490f16 100644 --- a/garcon/garcon-menu-item.c +++ b/garcon/garcon-menu-item.c @@ -834,12 +834,16 @@ garcon_menu_item_reload_from_file (GarconMenuItem *item, GError **error) { GKeyFile *rc; - gchar *contents; - gsize length = 0; + gboolean boolean; gboolean succeed; + GList *categories = NULL; + gchar **mt; + gchar **str_list; + gchar *contents; gchar *string; - gboolean boolean; - gchar *name, *exec; + gchar *name; + gchar *exec; + gsize length = 0; g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE); g_return_val_if_fail (G_IS_FILE (file), FALSE); @@ -930,6 +934,32 @@ garcon_menu_item_reload_from_file (GarconMenuItem *item, boolean = GET_KEY (boolean, G_KEY_FILE_DESKTOP_KEY_HIDDEN); garcon_menu_item_set_hidden (item, boolean); + /* Determine the categories this application should be shown in */ + str_list = GET_STRING_LIST (G_KEY_FILE_DESKTOP_KEY_CATEGORIES); + if (G_LIKELY (str_list != NULL)) + { + for (mt = str_list; *mt != NULL; ++mt) + { + if (**mt != '\0') + categories = g_list_prepend (categories, g_strdup (*mt)); + } + + /* Free list */ + g_strfreev (str_list); + + /* Assign categories list to the menu item */ + garcon_menu_item_set_categories (item, categories); + } + else + { + /* Assign empty categories list to the menu item */ + garcon_menu_item_set_categories (item, NULL); + } + + /* Set the rest of the private data directly */ + item->priv->only_show_in = GET_STRING_LIST (G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN); + item->priv->not_show_in = GET_STRING_LIST (G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN); + /* Flush property notifications */ g_object_thaw_notify (G_OBJECT (item)); diff --git a/garcon/garcon-menu.c b/garcon/garcon-menu.c index a5d3782..902afb9 100644 --- a/garcon/garcon-menu.c +++ b/garcon/garcon-menu.c @@ -146,10 +146,13 @@ static void garcon_menu_resolve_items_by_rule (GarconM static void garcon_menu_resolve_item_by_rule (const gchar *desktop_id, const gchar *uri, GarconMenuPair *data); -static gchar *garcon_menu_collect_file_from_path (GarconMenu *menu, - GFile *file, +static gboolean garcon_menu_collect_file_from_path (GarconMenu *menu, GFile *dir, - const gchar *id_prefix); + const gchar *id_prefix, + GFile *wanted_file, + const gchar *wanted_desktop_id, + GFile **return_file, + gchar **return_desktop_id); #if 0 static gboolean garcon_menu_resolve_item_file (GarconMenu *menu, GFile *file, @@ -334,7 +337,7 @@ garcon_menu_class_init (GarconMenuClass *klass) NULL, garcon_marshal_VOID__OBJECT_UINT, G_TYPE_NONE, - 1, + 2, GARCON_TYPE_MENU_ITEM, G_TYPE_UINT); @@ -1302,6 +1305,8 @@ garcon_menu_resolve_items (GarconMenu *menu, garcon_menu_item_pool_apply_exclude_rule (menu->priv->pool, iter->data); } } + + g_list_free (rules); } /* Iterate over all submenus */ @@ -1371,82 +1376,84 @@ garcon_menu_resolve_item_by_rule (const gchar *desktop_id, -static gchar * +static gboolean garcon_menu_collect_file (GarconMenu *menu, - GFile *file) + GFile *wanted_file, + const gchar *wanted_desktop_id, + GFile **return_file, + gchar **return_desktop_id) { - GList *app_dirs = NULL; - GList *iter; - GFile *dir; - gchar *desktop_id = NULL; - - g_return_val_if_fail (GARCON_IS_MENU (menu), NULL); - g_return_val_if_fail (G_IS_FILE (file), NULL); + gboolean file_found = FALSE; + GList *app_dirs = NULL; + GList *iter; + GFile *dir; - g_debug ("collect file: menu = %s, file = %s", - garcon_menu_element_get_name (GARCON_MENU_ELEMENT (menu)), - g_file_get_path (file)); + g_return_val_if_fail (GARCON_IS_MENU (menu), FALSE); + g_return_val_if_fail (wanted_file == NULL || G_IS_FILE (wanted_file), FALSE); + g_return_val_if_fail (!(wanted_file != NULL && wanted_desktop_id != NULL), FALSE); app_dirs = garcon_menu_get_app_dirs (menu, FALSE); /* Collect desktop entry filenames */ - for (iter = app_dirs; desktop_id == NULL && iter != NULL; iter = g_list_next (iter)) + for (iter = app_dirs; !file_found && iter != NULL; iter = iter->next) { dir = g_file_new_for_uri (iter->data); - desktop_id = garcon_menu_collect_file_from_path (menu, file, dir, NULL); + file_found = garcon_menu_collect_file_from_path (menu, dir, NULL, + wanted_file, wanted_desktop_id, + return_file, return_desktop_id); g_object_unref (dir); } /* Free directory list */ g_list_free (app_dirs); - if (desktop_id == NULL) + if (!file_found) { /* Collect filenames for submenus */ - for (iter = menu->priv->submenus; - desktop_id == NULL && iter != NULL; - iter = g_list_next (iter)) + for (iter = menu->priv->submenus; !file_found && iter != NULL; iter = iter->next) { - desktop_id = garcon_menu_collect_file (iter->data, file); + file_found = garcon_menu_collect_file (iter->data, + wanted_file, wanted_desktop_id, + return_file, return_desktop_id); } } - return desktop_id; + return file_found; } -static gchar * +static gboolean garcon_menu_collect_file_from_path (GarconMenu *menu, - GFile *file, GFile *dir, - const gchar *id_prefix) + const gchar *id_prefix, + GFile *wanted_file, + const gchar *wanted_desktop_id, + GFile **return_file, + gchar **return_desktop_id) { GFileEnumerator *enumerator; GFileInfo *file_info; + gboolean file_found = FALSE; GFile *child_file; gchar *base_name; gchar *new_id_prefix; gchar *desktop_id = NULL; - g_return_val_if_fail (GARCON_IS_MENU (menu), NULL); - g_return_val_if_fail (G_IS_FILE (file), NULL); - g_return_val_if_fail (G_IS_FILE (dir), NULL); - - g_debug ("collect file from path: menu = %s, file = %s, dir = %s", - garcon_menu_element_get_name (GARCON_MENU_ELEMENT (menu)), - g_file_get_path (file), - g_file_get_path (dir)); + g_return_val_if_fail (GARCON_IS_MENU (menu), FALSE); + g_return_val_if_fail (G_IS_FILE (dir), FALSE); + g_return_val_if_fail (wanted_file == NULL || G_IS_FILE (wanted_file), FALSE); + g_return_val_if_fail (!(wanted_file != NULL && wanted_desktop_id != NULL), FALSE); /* Skip directory if it doesn't exist */ - if (G_UNLIKELY (!g_file_query_exists (dir, NULL))) - return NULL; + if (!g_file_query_exists (dir, NULL)) + return FALSE; /* Skip directory if it's not a directory */ - if (G_UNLIKELY (g_file_query_file_type (dir, G_FILE_QUERY_INFO_NONE, - NULL) != G_FILE_TYPE_DIRECTORY)) + if (g_file_query_file_type (dir, G_FILE_QUERY_INFO_NONE, + NULL) != G_FILE_TYPE_DIRECTORY) { - return NULL; + return FALSE; } /* Open directory for reading */ @@ -1454,15 +1461,15 @@ garcon_menu_collect_file_from_path (GarconMenu *menu, G_FILE_QUERY_INFO_NONE, NULL, NULL); /* Abort if directory cannot be opened */ - if (G_UNLIKELY (enumerator == NULL)) - return NULL; + if (enumerator == NULL) + return FALSE; /* Read file by file */ - while (TRUE && desktop_id == NULL) + while (!file_found) { file_info = g_file_enumerator_next_file (enumerator, NULL, NULL); - if (G_UNLIKELY (file_info == NULL)) + if (file_info == NULL) break; child_file = g_file_resolve_relative_path (dir, g_file_info_get_name (file_info)); @@ -1472,28 +1479,53 @@ garcon_menu_collect_file_from_path (GarconMenu *menu, if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) { /* Create new desktop-file id prefix */ - if (G_LIKELY (id_prefix == NULL)) + if (id_prefix == NULL) new_id_prefix = g_strdup (base_name); else new_id_prefix = g_strjoin ("-", id_prefix, base_name, NULL); /* Collect files in the directory */ - desktop_id = garcon_menu_collect_file_from_path (menu, file, child_file, - new_id_prefix); + file_found = garcon_menu_collect_file_from_path (menu, + child_file, new_id_prefix, + wanted_file, wanted_desktop_id, + return_file, return_desktop_id); /* Free id prefix */ g_free (new_id_prefix); } - else if (G_LIKELY (g_str_has_suffix (base_name, ".desktop"))) + else if (g_str_has_suffix (base_name, ".desktop")) { + /* Create desktop-file id */ + if (id_prefix == NULL) + desktop_id = g_strdup (base_name); + else + desktop_id = g_strjoin ("-", id_prefix, base_name, NULL); + /* Check if we have found the correct file */ - if (g_file_equal (child_file, file)) + if (wanted_file != NULL && g_file_equal (child_file, wanted_file)) { - /* Create desktop-file id */ - if (G_LIKELY (id_prefix == NULL)) - desktop_id = g_strdup (base_name); - else - desktop_id = g_strjoin ("-", id_prefix, base_name, NULL); + if (return_file != NULL) + *return_file = g_object_ref (child_file); + + if (return_desktop_id != NULL) + *return_desktop_id = desktop_id; + + file_found = TRUE; + } + else if (wanted_desktop_id != NULL + && g_strcmp0 (desktop_id, wanted_desktop_id) == 0) + { + if (return_file != NULL) + *return_file = g_object_ref (child_file); + + if (return_desktop_id != NULL) + *return_desktop_id = desktop_id; + + file_found = TRUE; + } + else + { + g_free (desktop_id); } } @@ -1509,34 +1541,128 @@ garcon_menu_collect_file_from_path (GarconMenu *menu, g_object_unref (enumerator); - return desktop_id; + return file_found; } -#if 0 static gboolean -garcon_menu_resolve_item_file (GarconMenu *menu, - GFile *file, - GarconMenuItem **item, - gchar **desktop_id) -{ +garcon_menu_update_item (GarconMenu *menu, + GarconMenuItem *item, + gboolean only_unallocated) +{ + GarconMenuItem *included_item; + const gchar *desktop_id; + gboolean menu_only_unallocated = FALSE; + gboolean to_be_included = FALSE; + gboolean included_somewhere = FALSE; + GList *rules = NULL; + GList *iter; + g_return_val_if_fail (GARCON_IS_MENU (menu), FALSE); - g_return_val_if_fail (G_IS_FILE (file), FALSE); - g_return_val_if_fail (item != NULL && *item == NULL, FALSE); - g_return_val_if_fail (desktop_id != NULL && *desktop_id == NULL, FALSE); - - /* TODO - * the menu item is unknown, so we need to load it and find to which - * menus it belongs. this involves: - * 1. finding out its desktop-file ID - * 2. loading it via the GarconMenuItemCache - * 3. resolving the item similar to how we do it with all items - * during the menu load process */ + g_return_val_if_fail (GARCON_IS_MENU_ITEM (item), FALSE); - return FALSE; + g_debug ("update item: menu=%s, item=%s", + garcon_menu_element_get_name (GARCON_MENU_ELEMENT (menu)), + garcon_menu_element_get_name (GARCON_MENU_ELEMENT (item))); + + menu_only_unallocated = garcon_menu_node_tree_get_boolean_child (menu->priv->tree, + GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED); + + if (menu_only_unallocated == only_unallocated) + { + desktop_id = garcon_menu_item_get_desktop_id (item); + included_item = garcon_menu_item_pool_lookup (menu->priv->pool, desktop_id); + + g_node_traverse (menu->priv->tree, G_IN_ORDER, G_TRAVERSE_ALL, 2, + (GNodeTraverseFunc) collect_rules, &rules); + + /* Iterate over all rules */ + for (iter = rules; iter != NULL; iter = g_list_next (iter)) + { + if (G_LIKELY (garcon_menu_node_tree_get_node_type (iter->data) == GARCON_MENU_NODE_TYPE_INCLUDE)) + { + if (garcon_menu_node_tree_rule_matches (iter->data, item)) + { + g_debug (" include rule matches"); + if (menu_only_unallocated) + { + g_debug (" item allocation counter: %d", garcon_menu_item_get_allocated (item)); + if (garcon_menu_item_get_allocated (item) == 0) + { + to_be_included = TRUE; + } + else if (garcon_menu_item_get_allocated (item) == 1) + { + if (included_item != NULL + && garcon_menu_element_equal (GARCON_MENU_ELEMENT (item), + GARCON_MENU_ELEMENT (included_item))) + { + g_debug (" included element and new element are equal, good"); + to_be_included = TRUE; + } + } + } + else + { + to_be_included = TRUE; + } + } + } + else + { + if (garcon_menu_node_tree_rule_matches (iter->data, item)) + to_be_included = FALSE; + } + } + + if (to_be_included) + { + g_debug (" to be included"); + if (included_item == NULL) + { + g_debug (" add"); + garcon_menu_item_pool_insert (menu->priv->pool, item); + + /* TODO set the position parameter properly according to the layout */ + g_signal_emit (menu, menu_signals[ITEM_ADDED], 0, item, 0); + } + else + { + g_debug (" already included"); + } + + included_somewhere = TRUE; + } + else + { + g_debug (" not to be included"); + if (included_item != NULL) + { + g_debug (" remove"); + garcon_menu_item_pool_remove (menu->priv->pool, item); + g_signal_emit (menu, menu_signals[ITEM_REMOVED], 0, item); + } + else + { + g_debug (" not included anyway"); + } + + included_somewhere = FALSE; + } + + g_list_free (rules); + } + + /* Iterate over all submenus */ + for (iter = menu->priv->submenus; iter != NULL; iter = g_list_next (iter)) + { + /* Resolve items of the submenu */ + included_somewhere = garcon_menu_update_item (GARCON_MENU (iter->data), item, only_unallocated) || included_somewhere; + } + + return included_somewhere; } -#endif @@ -2006,7 +2132,7 @@ garcon_menu_find_file_item (GarconMenu *menu, if (item != NULL) *menus = g_list_prepend (*menus, menu); - for (lp = menu->priv->submenus; lp != NULL; lp = lp->next) + for (lp = menu->priv->submenus; item == NULL && lp != NULL; lp = lp->next) item = garcon_menu_find_file_item (lp->data, file, menus); } else @@ -2418,9 +2544,12 @@ garcon_menu_app_dir_changed (GarconMenu *menu, { GarconMenuItem *item; GFileType file_type; + gboolean included_somewhere = FALSE; + GFile *replacement_file; GList *menus = NULL; GList *lp; gchar *desktop_id; + gchar *uri; g_return_if_fail (GARCON_IS_MENU (menu)); @@ -2447,10 +2576,17 @@ garcon_menu_app_dir_changed (GarconMenu *menu, /* try to reload the item */ if (garcon_menu_item_reload (item, NULL)) { - /* find out where to move the item (if it has to be moved at all) - * and move it, taking care of emitting item-changed/item-removed/item-added - * signals */ - g_debug (" successfully reloaded"); + /* insert the item into the appropriate menus, if there are any */ + included_somewhere = garcon_menu_update_item (menu, item, FALSE); + included_somewhere = garcon_menu_update_item (menu, item, TRUE) || included_somewhere; + + /* unload the item if it isn't included in any menus */ + if (!included_somewhere) + { + /* remove the item from the item cache, so we are forced to reload + * it from disk the next time it becomes available */ + garcon_menu_item_cache_remove_file (menu->priv->cache, file); + } } else { @@ -2471,22 +2607,31 @@ garcon_menu_app_dir_changed (GarconMenu *menu, } else { - desktop_id = garcon_menu_collect_file (menu, file); + /* determine the desktop ID for this file */ + if (garcon_menu_collect_file (menu, file, NULL, NULL, &desktop_id)) + { + uri = g_file_get_uri (file); - g_debug (" resolve item file => %s", desktop_id); + /* try to load the desktop file from the item cache */ + item = garcon_menu_item_cache_lookup (menu->priv->cache, uri, desktop_id); + if (item != NULL) + { + /* insert the item into the appropriate menus, if there are any */ + included_somewhere = garcon_menu_update_item (menu, item, FALSE); + included_somewhere = garcon_menu_update_item (menu, item, TRUE) || included_somewhere; + + /* unload the item if it isn't included in any menus */ + if (!included_somewhere) + { + /* remove the item from the item cache, so we are forced to reload + * it from disk the next time it becomes available */ + garcon_menu_item_cache_remove_file (menu->priv->cache, file); + } + } -#if 0 - if (garcon_menu_resolve_item_file (menu, file, &item, &desktop_id)) - { - /* TODO - * the menu item is unknown, so we need to load it and find to which - * menus it belongs. this involves: - * 1. finding out its desktop-file ID - * 2. loading it via the GarconMenuItemCache - * 3. resolving the item similar to how we do it with all items - * during the menu load process */ + g_free (uri); + g_free (desktop_id); } -#endif } /* free the menu list */ @@ -2506,6 +2651,7 @@ garcon_menu_app_dir_changed (GarconMenu *menu, * 'item-added' signals) * - monitor the newly created directory * 2) the new file is a regular file + * - remove items with the same desktop id * - load it into a GarconMenuItem * - find the correct menu(s) for it * - add it to those menus (make sure to emit 'item-added' @@ -2535,6 +2681,8 @@ garcon_menu_app_dir_changed (GarconMenu *menu, item = garcon_menu_find_file_item (menu, file, &menus); if (item != NULL) { + desktop_id = g_strdup (garcon_menu_item_get_desktop_id (item)); + /* reloading failed, remove the item from all menus and destroy it */ for (lp = menus; lp != NULL; lp = lp->next) { @@ -2548,15 +2696,53 @@ garcon_menu_app_dir_changed (GarconMenu *menu, /* remove the item from the item cache, so we are forced to reload it from * disk the next time it becomes available */ garcon_menu_item_cache_remove_file (menu->priv->cache, file); - } - /* TODO - * check if a file with the same desktop-file ID still exists - * and load that file instead. then resolve the file into the - * correct menus */ + /* free the menu list */ + g_list_free (menus); + + /* NOTE: at this point a desktop file has been deleted (e.g. in + * $HOME/.local/share/applications) but there may be a replacement + * for it (e.g. in /usr/local/share/applications) that was overloaded + * previously. so we now have to determine the desktop id again and then + * try to load the corresponding menu item. this makes sure the + * previously overloaded desktop file is picked up. */ + + /* NOTE: in theory we would have to do this even if the deleted file + * did not correspond to an existing item (e.g. empty files can override + * real desktop entries), but this is too complicated for now because + * then we'd have to find out the desktop ID by splitting up the path + * into segments and iterating through the app dirs, removing them from + * the path segments and then replacing all dir separators with a "-". + * We can do that later... */ + + /* determine the next-priority desktop file with the same desktop ID */ + if (garcon_menu_collect_file (menu, NULL, desktop_id, &replacement_file, NULL)) + { + uri = g_file_get_uri (replacement_file); - /* free the menu list */ - g_list_free (menus); + item = garcon_menu_item_cache_lookup (menu->priv->cache, uri, desktop_id); + if (item != NULL) + { + /* insert the item into the appropriate menus, if there are any */ + included_somewhere = garcon_menu_update_item (menu, item, FALSE); + included_somewhere = garcon_menu_update_item (menu, item, TRUE) || included_somewhere; + + /* unload the item if it isn't included in any menus */ + if (!included_somewhere) + { + /* remove the item from the item cache, so we are forced to reload + * it from disk the next time it becomes available */ + garcon_menu_item_cache_remove_file (menu->priv->cache, file); + } + } + + g_free (uri); + g_object_unref (replacement_file); + } + + g_free (desktop_id); + + } } } } diff --git a/tests/test-display-menu.c b/tests/test-display-menu.c index da3511a..fc9a615 100644 --- a/tests/test-display-menu.c +++ b/tests/test-display-menu.c @@ -146,6 +146,27 @@ create_item_icon (GarconMenuItem *item) static void +item_changed (GarconMenuItem *item, + GtkWidget *gtk_item) +{ + GdkPixbuf *icon; + GtkWidget *image; + + /* Try reloading the icon */ + icon = create_item_icon (item); + + if (icon != NULL) + image = gtk_image_new_from_pixbuf (icon); + else + image = gtk_image_new_from_icon_name ("applications-other", ICON_SIZE); + + gtk_menu_item_set_label (GTK_MENU_ITEM (gtk_item), garcon_menu_element_get_name (GARCON_MENU_ELEMENT (item))); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (gtk_item), image); +} + + + +static void create_item_widgets (GarconMenuItem *item, GtkWidget *parent_menu) { @@ -168,6 +189,9 @@ create_item_widgets (GarconMenuItem *item, g_object_set_data_full (G_OBJECT (gtk_item), "garcon-menu-item", g_object_ref (item), g_object_unref); + /* React to changes made to the item on disk */ + g_signal_connect (item, "changed", G_CALLBACK (item_changed), gtk_item); + /* Execute command if item is clicked */ g_signal_connect (gtk_item, "activate", G_CALLBACK (execute_item_command), item); } @@ -201,6 +225,18 @@ directory_changed (GarconMenu *menu, static void +item_added (GarconMenu *menu, + GarconMenuItem *item, + guint position, + GtkWidget *gtk_menu) +{ + /* Add menu item to the menu */ + create_item_widgets (item, gtk_menu); +} + + + +static void item_removed (GarconMenu *menu, GarconMenuItem *item, GtkWidget *gtk_menu) @@ -302,14 +338,22 @@ create_menu_widgets (GtkWidget *gtk_menu, /* g_signal_connect (submenu, "destroy", G_CALLBACK (menu_destroyed), gtk_item); */ /* Remove menu items if they are removed on disk */ + g_signal_connect (submenu, "item-added", G_CALLBACK (item_added), gtk_submenu); g_signal_connect (submenu, "item-removed", G_CALLBACK (item_removed), gtk_submenu); /* Create widgets for submenu */ create_menu_widgets (gtk_submenu, submenu); /* Destroy submenu if it is empty */ + /* FIXME destroying menus will not work with monitoring. if a menu is destroyed and + * an item is added to it at runtime, where should we add it...? instead, we should + * just hide the empty menu */ +#if 0 if (G_UNLIKELY (gtk_container_get_children (GTK_CONTAINER (gtk_submenu)) == NULL)) gtk_widget_destroy (gtk_item); +#endif + if (G_UNLIKELY (gtk_container_get_children (GTK_CONTAINER (gtk_submenu)) == NULL)) + gtk_widget_hide (gtk_item); } } _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits