Author: jannis
Date: 2007-01-10 23:04:24 +0000 (Wed, 10 Jan 2007)
New Revision: 24350
Modified:
libfrap/trunk/libfrap/menu/ChangeLog
libfrap/trunk/libfrap/menu/STATUS
libfrap/trunk/libfrap/menu/frap-menu-item-cache.c
libfrap/trunk/libfrap/menu/frap-menu-item-pool.c
libfrap/trunk/libfrap/menu/frap-menu-item.c
libfrap/trunk/libfrap/menu/frap-menu-item.h
libfrap/trunk/libfrap/menu/frap-menu.c
Log:
* frap-menu-item.{c,h}: Remove "allocated" property and replace it
with a kind of reference counter. Add frap_menu_item_ref/unref
methods to be used instead of frap_menu_item_set_allocated() which
has been removed. Use "guint ... : 1" notation for boolean values
in the structs belonging to FrapMenuItem.
* frap-menu-item-pool.c: Call frap_menu_item_ref when adding an item
to the pool of a menu (instead of setting the allocated value
directly).
* frap-menu.c: Use "guint ... : 1" notation for boolean values in
structs. Fix frap_menu_set_filename to make free'ing the filename
possible. Implement recursive (bottom -> top) collecting of
directory and legacy dirs (might be wrong for legacy dirs, I need
to verify this during the next days). Implement two-pass mechanism
to resolve menu items (in order to be able to handle
<OnlyUnallocated> elements). Only set menu parse state to
_STATE_ROOT if there are no other menus left on the stack.
* STATUS: Update implementation STATUS.
Modified: libfrap/trunk/libfrap/menu/ChangeLog
===================================================================
--- libfrap/trunk/libfrap/menu/ChangeLog 2007-01-10 22:58:45 UTC (rev
24349)
+++ libfrap/trunk/libfrap/menu/ChangeLog 2007-01-10 23:04:24 UTC (rev
24350)
@@ -1,3 +1,23 @@
+2007-01-11 Jannis Pohlmann <[EMAIL PROTECTED]>
+
+ * frap-menu-item.{c,h}: Remove "allocated" property and replace it
+ with a kind of reference counter. Add frap_menu_item_ref/unref
+ methods to be used instead of frap_menu_item_set_allocated() which
+ has been removed. Use "guint ... : 1" notation for boolean values
+ in the structs belonging to FrapMenuItem.
+ * frap-menu-item-pool.c: Call frap_menu_item_ref when adding an item
+ to the pool of a menu (instead of setting the allocated value
+ directly).
+ * frap-menu.c: Use "guint ... : 1" notation for boolean values in
+ structs. Fix frap_menu_set_filename to make free'ing the filename
+ possible. Implement recursive (bottom -> top) collecting of
+ directory and legacy dirs (might be wrong for legacy dirs, I need
+ to verify this during the next days). Implement two-pass mechanism
+ to resolve menu items (in order to be able to handle
+ <OnlyUnallocated> elements). Only set menu parse state to
+ _STATE_ROOT if there are no other menus left on the stack.
+ * STATUS: Update implementation STATUS.
+
2006-11-07 Jannis Pohlmann <[EMAIL PROTECTED]>
* frap-menu-item-pool.c: Fix backwards compatibility by passing
Modified: libfrap/trunk/libfrap/menu/STATUS
===================================================================
--- libfrap/trunk/libfrap/menu/STATUS 2007-01-10 22:58:45 UTC (rev 24349)
+++ libfrap/trunk/libfrap/menu/STATUS 2007-01-10 23:04:24 UTC (rev 24350)
@@ -25,6 +25,9 @@
[x] <Directory>
[x] <OnlyUnallocated> and <NotOnlyUnallocated>
+
+ Supported by using a two-pass resolving mechanism as stated
+ in the spec ("Generating the menus").
[x] <Deleted> and <NotDeleted>
@@ -61,8 +64,10 @@
[-] <LegacyDir>
- <LegacyDir> elements are parsed into a string list, but there is
- no further parsing or merging performed afterwards - not yet.
+ <LegacyDir> elements are parsed and added to the menus
+ which contain them in the menu file. Legacy menus are created
+ for legacy dirs with a .directory file. However, their desktop
+ files are not parsed yet.
[-] <DefaultLegacyDirs>
Modified: libfrap/trunk/libfrap/menu/frap-menu-item-cache.c
===================================================================
--- libfrap/trunk/libfrap/menu/frap-menu-item-cache.c 2007-01-10 22:58:45 UTC
(rev 24349)
+++ libfrap/trunk/libfrap/menu/frap-menu-item-cache.c 2007-01-10 23:04:24 UTC
(rev 24350)
@@ -277,7 +277,8 @@
/* Add item to the hash table */
g_hash_table_replace (cache->priv->items, g_strdup (filename), item);
- /* Grab a reference on the item */
+ /* Grab a reference on the item, but don't increase the allocation
+ * counter */
g_object_ref (G_OBJECT (item));
return item;
@@ -298,7 +299,7 @@
/* The file has been loaded, add the item to the hash table */
g_hash_table_replace (cache->priv->items, g_strdup (filename), item);
- /* Grab a reference on it */
+ /* Grab a reference on it but don't increase the allocation counter */
g_object_ref (G_OBJECT (item));
}
Modified: libfrap/trunk/libfrap/menu/frap-menu-item-pool.c
===================================================================
--- libfrap/trunk/libfrap/menu/frap-menu-item-pool.c 2007-01-10 22:58:45 UTC
(rev 24349)
+++ libfrap/trunk/libfrap/menu/frap-menu-item-pool.c 2007-01-10 23:04:24 UTC
(rev 24350)
@@ -158,11 +158,8 @@
/* Insert into the hash table and remove old item (if any) */
g_hash_table_replace (pool->priv->items, g_strdup
(frap_menu_item_get_desktop_id (item)), item);
- /* Set allocation state of the item */
- frap_menu_item_set_allocated (item, TRUE);
-
/* Grab a reference on the item */
- g_object_ref (G_OBJECT (item));
+ frap_menu_item_ref (item);
}
Modified: libfrap/trunk/libfrap/menu/frap-menu-item.c
===================================================================
--- libfrap/trunk/libfrap/menu/frap-menu-item.c 2007-01-10 22:58:45 UTC (rev
24349)
+++ libfrap/trunk/libfrap/menu/frap-menu-item.c 2007-01-10 23:04:24 UTC (rev
24350)
@@ -46,7 +46,6 @@
PROP_NAME,
PROP_ICON_NAME,
PROP_COMMAND,
- PROP_ALLOCATED,
};
@@ -83,13 +82,13 @@
GList *categories;
/* Whether this application requires a terminal to be started in */
- gboolean requires_terminal;
+ guint requires_terminal : 1;
/* Whether this menu item should be hidden */
- gboolean hidden;
+ guint hidden : 1;
/* Whether this application supports startup notification */
- gboolean supports_startup_notification;
+ guint supports_startup_notification : 1;
/* Name to be displayed for the menu item */
gchar *name;
@@ -100,8 +99,10 @@
/* Menu item icon name */
gchar *icon_name;
- /* Whether this menu item is allocated by a menu */
- gboolean allocated;
+ /* Counter keeping the number of menus which use this item. This works
+ * like a reference counter and should be increased / decreased by FrapMenu
+ * items whenever the item is added to or removed from the menu. */
+ guint num_allocated;
};
struct _FrapMenuItem
@@ -267,19 +268,6 @@
_("Name of the
application icon"),
NULL,
G_PARAM_READWRITE));
-
- /**
- * FrapMenuItem:allocated:
- *
- * Whether this item is allocated by a menu.
- **/
- g_object_class_install_property (gobject_class,
- PROP_ICON_NAME,
- g_param_spec_boolean ("allocated",
- _("Allocated"),
- _("Allocation state
of the item"),
- FALSE,
- G_PARAM_READWRITE));
}
@@ -294,6 +282,7 @@
item->priv->command = NULL;
item->priv->icon_name = NULL;
item->priv->categories = NULL;
+ item->priv->num_allocated = 0;
}
@@ -352,10 +341,6 @@
case PROP_ICON_NAME:
break;
- case PROP_ALLOCATED:
- g_value_set_boolean (value, frap_menu_item_get_allocated (item));
- break;
-
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -406,10 +391,6 @@
frap_menu_item_set_icon_name (item, g_value_get_string (value));
break;
- case PROP_ALLOCATED:
- frap_menu_item_set_allocated (item, g_value_get_boolean (value));
- break;
-
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -826,8 +807,28 @@
void
+frap_menu_item_ref (FrapMenuItem *item)
+{
+ g_return_if_fail (FRAP_IS_MENU_ITEM (item));
+
+ /* Increment the allocation counter */
+ frap_menu_item_increment_allocated (item);
+
+ /* Grab a reference on the object */
+ g_object_ref (G_OBJECT (item));
+}
+
+
+
+void
frap_menu_item_unref (FrapMenuItem *item)
{
+ g_return_if_fail (FRAP_IS_MENU_ITEM (item));
+
+ /* Decrement allocation counter */
+ frap_menu_item_decrement_allocated (item);
+
+ /* Decrement the reference counter */
g_object_unref (G_OBJECT (item));
}
@@ -837,21 +838,25 @@
frap_menu_item_get_allocated (FrapMenuItem *item)
{
g_return_val_if_fail (FRAP_IS_MENU_ITEM (item), FALSE);
- return item->priv->allocated;
+ return item->priv->num_allocated > 0;
}
void
-frap_menu_item_set_allocated (FrapMenuItem *item,
- gboolean allocated)
+frap_menu_item_increment_allocated (FrapMenuItem *item)
{
g_return_if_fail (FRAP_IS_MENU_ITEM (item));
+ item->priv->num_allocated++;
+}
- if (item->priv->allocated == allocated)
- return;
- item->priv->allocated = allocated;
- g_object_notify (G_OBJECT (item), "allocated");
+void
+frap_menu_item_decrement_allocated (FrapMenuItem *item)
+{
+ g_return_if_fail (FRAP_IS_MENU_ITEM (item));
+
+ if (item->priv->num_allocated > 0)
+ item->priv->num_allocated--;
}
Modified: libfrap/trunk/libfrap/menu/frap-menu-item.h
===================================================================
--- libfrap/trunk/libfrap/menu/frap-menu-item.h 2007-01-10 22:58:45 UTC (rev
24349)
+++ libfrap/trunk/libfrap/menu/frap-menu-item.h 2007-01-10 23:04:24 UTC (rev
24350)
@@ -73,10 +73,11 @@
GList *frap_menu_item_get_categories (FrapMenuItem
*item);
void frap_menu_item_set_categories (FrapMenuItem
*item,
GList
*categories);
+void frap_menu_item_ref (FrapMenuItem
*item);
void frap_menu_item_unref (FrapMenuItem
*item);
gboolean frap_menu_item_get_allocated (FrapMenuItem
*item);
-void frap_menu_item_set_allocated (FrapMenuItem
*item,
- gboolean
allocated);
+void frap_menu_item_increment_allocated (FrapMenuItem
*item);
+void frap_menu_item_decrement_allocated (FrapMenuItem
*item);
G_END_DECLS;
Modified: libfrap/trunk/libfrap/menu/frap-menu.c
===================================================================
--- libfrap/trunk/libfrap/menu/frap-menu.c 2007-01-10 22:58:45 UTC (rev
24349)
+++ libfrap/trunk/libfrap/menu/frap-menu.c 2007-01-10 23:04:24 UTC (rev
24350)
@@ -237,7 +237,8 @@
FrapMenuRules *rules);
static void frap_menu_add_move
(FrapMenu *menu,
FrapMenuMove *move);
-static void frap_menu_resolve_items
(FrapMenu *menu);
+static void frap_menu_resolve_items
(FrapMenu *menu,
+
gboolean only_unallocated);
static void frap_menu_resolve_items_from_path
(FrapMenu *menu,
const gchar *path,
const gchar *id_prefix);
@@ -273,10 +274,10 @@
GSList *app_dirs;
/* Only include desktop entries not used in other menus */
- gboolean only_unallocated;
+ guint only_unallocated : 1;
/* Whether this menu should be ignored or not */
- gboolean deleted;
+ guint deleted : 1;
/* Include/exclude rules */
GSList *rules;
@@ -674,12 +675,11 @@
frap_menu_set_filename (FrapMenu *menu, const gchar *filename)
{
g_return_if_fail (FRAP_IS_MENU (menu));
- g_return_if_fail (filename != NULL);
/* Abort if filenames are equal */
if (G_UNLIKELY (menu->priv->filename != NULL))
{
- if (G_UNLIKELY (g_utf8_collate (filename, menu->priv->filename) == 0))
+ if (G_UNLIKELY (filename != NULL && g_utf8_collate (filename,
menu->priv->filename) == 0))
return;
/* Free old filename */
@@ -828,9 +828,39 @@
GSList*
frap_menu_get_directory_dirs (FrapMenu *menu)
{
+ FrapMenu *current_menu;
+ GSList *directories = NULL;
+ GList *menus = NULL;
+ GList *iter;
+ GSList *iter2;
+
g_return_val_if_fail (FRAP_IS_MENU (menu), NULL);
- /* TODO collect directories from the bottom up to the root menu */
- return menu->priv->directory_dirs;
+
+ /* Collect all menus from menu -> parent -> ... -> root */
+ for (current_menu = menu; current_menu != NULL; current_menu =
current_menu->priv->parent)
+ menus = g_list_prepend (menus, current_menu);
+
+ /* Iterate over all menus from root -> parent -> ... -> menu */
+ for (iter = menus; iter != NULL; iter = g_list_next (iter))
+ {
+ /* Fetch current menu */
+ current_menu = FRAP_MENU (iter->data);
+
+ /* Iterate over all directory dirs */
+ for (iter2 = current_menu->priv->directory_dirs; iter2 != NULL; iter2 =
g_slist_next (iter2))
+ {
+ /* Append directory dir to the list */
+ directories = g_slist_append (directories, iter2->data);
+ }
+
+ /* Free the directory dir list */
+ g_slist_free (iter2);
+ }
+
+ /* Free menu list */
+ g_list_free (menus);
+
+ return directories;
}
@@ -838,11 +868,44 @@
GSList*
frap_menu_get_legacy_dirs (FrapMenu *menu)
{
+ /* FIXME: Collecting legacy dirs from the bottom up might be wrong. Perhaps
+ * only <Menu> items with <LegacyDir> elements are allowed to parse
+ * legacy menu hierarchies - verify this!
+ */
+
+ FrapMenu *current_menu;
+ GSList *directories = NULL;
+ GList *menus = NULL;
+ GList *iter;
+ GSList *iter2;
+
g_return_val_if_fail (FRAP_IS_MENU (menu), NULL);
- /* TODO collect directories from the bottom up to the root menu - does the
- * spec treat legacy dirs differently than app dirs and directory dirs?
- * */
- return menu->priv->legacy_dirs;
+
+ /* Collect all menus from menu -> parent -> ... -> root */
+ for (current_menu = menu; current_menu != NULL; current_menu =
current_menu->priv->parent)
+ menus = g_list_prepend (menus, current_menu);
+
+ /* Iterate over all menus from root -> parent -> ... -> menu */
+ for (iter = menus; iter != NULL; iter = g_list_next (iter))
+ {
+ /* Fetch current menu */
+ current_menu = FRAP_MENU (iter->data);
+
+ /* Iterate over all legacy directories */
+ for (iter2 = current_menu->priv->legacy_dirs; iter2 != NULL; iter2 =
g_slist_next (iter2))
+ {
+ /* Append legacy dir to the list */
+ directories = g_slist_append (directories, iter2->data);
+ }
+
+ /* Free the legacy dir list */
+ g_slist_free (iter2);
+ }
+
+ /* Free menu list */
+ g_list_free (menus);
+
+ return directories;
}
@@ -963,12 +1026,16 @@
g_list_free (menu_context.menu_stack);
g_list_free (menu_context.rule_stack);
+#if 0
frap_menu_resolve_legacy_menus (menu);
+#endif
frap_menu_remove_duplicates (menu);
frap_menu_resolve_directory (menu);
frap_menu_resolve_moves (menu);
frap_menu_resolve_deleted (menu);
- frap_menu_resolve_items (menu);
+
+ frap_menu_resolve_items (menu, FALSE);
+ frap_menu_resolve_items (menu, TRUE);
}
@@ -1068,11 +1135,8 @@
else if (g_utf8_collate (element_name, "Menu") == 0)
{
/* Create new menu */
- FrapMenu *menu = g_object_new (FRAP_TYPE_MENU, NULL);
+ FrapMenu *menu = g_object_new (FRAP_TYPE_MENU, "filename",
current_menu->priv->filename, NULL);
- /* Silently copy filename attribute from the current menu */
- menu->priv->filename = g_strdup (current_menu->priv->filename);
-
/* Add menu as submenu to the current menu */
frap_menu_add_menu (current_menu, menu);
@@ -1189,8 +1253,10 @@
/* Remove current menu from stack */
menu_context->menu_stack = g_list_delete_link
(menu_context->menu_stack, g_list_first (menu_context->menu_stack));
- /* Set parse state */
- menu_context->state = FRAP_MENU_PARSE_STATE_ROOT;
+ /* Set parse state to _STATE_ROOT only if there are no other menus
+ * left on the stack. Otherwise, we're still inside a <Menu>
element. */
+ if (G_LIKELY (g_list_length (menu_context->menu_stack) == 1))
+ menu_context->state = FRAP_MENU_PARSE_STATE_ROOT;
}
break;
@@ -1518,7 +1584,7 @@
gchar *kde_bin_dir = g_build_path (G_DIR_SEPARATOR_S, kde_dir,
"bin", NULL);
/* Expand PATH to include KDEDIR/bin - if necessary */
- gchar *occurence = g_strrstr (path, kde_bin_dir);
+ const gchar *occurence = g_strrstr (path, kde_bin_dir);
if (G_LIKELY (occurence == NULL))
{
/* PATH = $PATH:$KDEDIR/bin */
@@ -1530,8 +1596,6 @@
/* Free expanded PATH value */
g_free (kde_path);
}
- else
- g_free (occurence);
/* Free KDEDIR/bin */
g_free (kde_bin_dir);
@@ -1596,11 +1660,35 @@
{
int i;
gchar *path;
+ gchar *kde_data_dir;
+ const gchar *kde_dir;
const gchar * const *dirs;
g_return_if_fail (FRAP_IS_MENU (menu));
+ /* Append $KDEDIR/share/applications as a workaround for distributions
+ * not installing KDE menu files properly into $XDG_DATA_DIR */
+
+ /* Get KDEDIR environment variable */
+ kde_dir = g_getenv ("KDEDIR");
+
+ /* Check if this variable is set */
+ if (G_UNLIKELY (kde_dir != NULL))
+ {
+ /* Build KDE data dir */
+ kde_data_dir = g_build_filename (kde_dir, "share", "applications", NULL);
+
+ /* Add it as an app dir if it exists */
+ if (G_LIKELY (g_file_test (kde_data_dir, G_FILE_TEST_IS_DIR)))
+ frap_menu_add_app_dir (menu, kde_data_dir);
+
+ /* Free the KDE data dir */
+ g_free (kde_data_dir);
+ }
+
+ /* The $KDEDIR workaround ends here */
+
/* Append system-wide data dirs */
dirs = g_get_system_data_dirs ();
for (i = 0; dirs[i] != NULL; i++)
@@ -1747,10 +1835,14 @@
/* Build absolute filename for this entry */
absolute_filename = g_build_filename (path, filename, NULL);
- /* Check if we have a .directory entry */
- if (G_UNLIKELY (g_utf8_collate (".directory", filename) == 0))
+ if (g_file_test (absolute_filename, G_FILE_TEST_IS_DIR))
{
- /* Create the directory object for the legacy menu */
+ /* We have a subdir -> create another legacy menu for this
subdirectory */
+ frap_menu_resolve_legacy_menu (legacy_menu, absolute_filename);
+ }
+ else if (g_utf8_collate (".directory", filename) == 0)
+ {
+ /* We have a .directory file -> create the directory object for the
legacy menu */
directory = g_object_new (FRAP_TYPE_MENU_DIRECTORY, "filename",
absolute_filename, NULL);
}
}
@@ -1765,6 +1857,7 @@
/* Add legacy menu to its new parent */
frap_menu_add_menu (menu, legacy_menu);
}
+ else
{
/* Destroy the legacy menu again - no .directory file found */
g_object_unref (legacy_menu);
@@ -1848,6 +1941,8 @@
g_slist_foreach (submenu->priv->app_dirs, (GFunc)
frap_menu_merge_app_dir, merged_menu);
g_slist_foreach (submenu->priv->rules, (GFunc) frap_menu_merge_rule,
merged_menu);
+ /* TODO Merge submenus of submenu and merged_menu! */
+
/* Add merged menu to the new list of submenus if not included already */
if (g_slist_find (merged_submenus, merged_menu) == NULL)
merged_submenus = g_slist_append (merged_submenus, merged_menu);
@@ -2067,7 +2162,8 @@
static void
-frap_menu_resolve_items (FrapMenu *menu)
+frap_menu_resolve_items (FrapMenu *menu,
+ gboolean only_unallocated)
{
GSList *iter;
GDir *dir;
@@ -2077,21 +2173,28 @@
/* TODO Remove all items from the pool if there are no include rules! */
- /* Iterate over all application directories */
- for (iter = frap_menu_get_app_dirs (menu); iter != NULL; iter = g_slist_next
(iter))
+ /* Resolve items in this menu (if it matches the only_unallocated argument.
+ * This means that in the first pass, all items of menus without
+ * <OnlyUnallocated /> are resolved and in the second pass, only items of
+ * menus with <OnlyUnallocated /> are resolved */
+ if (menu->priv->only_unallocated == only_unallocated)
{
- /* Resolve items in the current directory */
- frap_menu_resolve_items_from_path (menu, iter->data, NULL);
+ /* Iterate over all application directories */
+ for (iter = frap_menu_get_app_dirs (menu); iter != NULL; iter =
g_slist_next (iter))
+ {
+ /* Resolve items in the current directory */
+ frap_menu_resolve_items_from_path (menu, iter->data, NULL);
+ }
+
+ /* Filter items according to the include/exclude rules */
+ frap_menu_item_pool_apply_rules (menu->priv->pool, menu->priv->rules);
}
- /* Filter items according to the include/exclude rules */
- frap_menu_item_pool_apply_rules (menu->priv->pool, menu->priv->rules);
-
/* Iterate over all submenus */
for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
{
/* Resolve items of the submenu */
- frap_menu_resolve_items (FRAP_MENU (iter->data));
+ frap_menu_resolve_items (FRAP_MENU (iter->data), only_unallocated);
}
}
@@ -2264,6 +2367,10 @@
/* Remove submenu from the submenu list */
menu->priv->submenus = g_slist_remove (menu->priv->submenus,
submenu);
+ /* TODO Merge submenus of submenu and target_submenu. Perhaps
even
+ * find a better way for merging menus as the current way is a)
+ * duplicated (see consolidate_child_menus) and b) buggy */
+
/* TODO Free the submenu - this introduces a strange item pool
* error ... */
/* g_object_unref (submenu); */
_______________________________________________
Xfce4-commits mailing list
[email protected]
http://foo-projects.org/mailman/listinfo/xfce4-commits