[Xfce4-commits] <garcon:jannis/global-monitoring> Squashme
Jannis Pohlmann
noreply at xfce.org
Sun Sep 5 14:50:22 CEST 2010
Updating branch refs/heads/jannis/global-monitoring
to a45a599c89f2ef788f0d67d81d431aeea94285e9 (commit)
from 76e190ae8d0d4e98f59ef59c00cf9d4c1e91eb8f (commit)
commit a45a599c89f2ef788f0d67d81d431aeea94285e9
Author: Jannis Pohlmann <jannis at 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 <jannis at xfce.org>
+ * Copyright (c) 2008-2010 Jannis Pohlmann <jannis at 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 <jannis at xfce.org>
+ * Copyright (c) 2008-2010 Jannis Pohlmann <jannis at 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);
}
}
More information about the Xfce4-commits
mailing list