Index: ChangeLog =================================================================== RCS file: /cvs/gnome/gnome-menus/ChangeLog,v retrieving revision 1.75 diff -u -p -r1.75 ChangeLog --- ChangeLog 16 Mar 2005 08:09:02 -0000 1.75 +++ ChangeLog 22 Mar 2005 10:39:10 -0000 @@ -0,0 +1,24 @@ +2005-03-22 Mark McLoughlin + + Implement support for new "type" argument to + + * libmenu/menu-layout.[ch]: + (menu_layout_node_root_get_basedir): add basedir accessor. + (menu_layout_node_merge_file_get_type), + (menu_layout_node_merge_file_set_type): add type accessors. + (start_menu_child_element): read the attribute. + + * libmenu/menu-tree.c: + (load_merge_file): return a boolean indicating whether the + file was successfully loaded. + (load_merge_file_with_config_dir): load a merge file from a + config dir. + (compare_basedir_to_config_dir): check to see if a basedir + matches a given config dir. + (load_parent_merge_file): try to find the parent of the + current menu file and load it if found. + (resolve_merge_file): load the parent menu file if requested. + + * libmenu/menu-util.c: (append_to_string): output the "type" + attribute on + Index: libmenu/menu-layout.c =================================================================== RCS file: /cvs/gnome/gnome-menus/libmenu/menu-layout.c,v retrieving revision 1.2 diff -u -p -r1.2 menu-layout.c --- libmenu/menu-layout.c 11 Nov 2004 10:44:40 -0000 1.2 +++ libmenu/menu-layout.c 22 Mar 2005 10:39:11 -0000 @@ -35,6 +35,7 @@ typedef struct MenuLayoutNodeMenu MenuLayoutNodeMenu; typedef struct MenuLayoutNodeRoot MenuLayoutNodeRoot; typedef struct MenuLayoutNodeLegacyDir MenuLayoutNodeLegacyDir; +typedef struct MenuLayoutNodeMergeFile MenuLayoutNodeMergeFile; struct MenuLayoutNode { @@ -79,6 +80,13 @@ struct MenuLayoutNodeLegacyDir char *prefix; }; +struct MenuLayoutNodeMergeFile +{ + MenuLayoutNode node; + + MenuMergeFileType type; +}; + typedef struct { MenuLayoutNodeEntriesChangedFunc callback; @@ -219,6 +227,10 @@ menu_layout_node_new (MenuLayoutNodeType node = (MenuLayoutNode*) g_new0 (MenuLayoutNodeRoot, 1); break; + case MENU_LAYOUT_NODE_MERGE_FILE: + node = (MenuLayoutNode *) g_new0 (MenuLayoutNodeMergeFile, 1); + break; + default: node = g_new0 (MenuLayoutNode, 1); break; @@ -266,6 +278,15 @@ menu_layout_node_copy (MenuLayoutNode *n } break; + case MENU_LAYOUT_NODE_MERGE_FILE: + { + MenuLayoutNodeMergeFile *merge_file = (MenuLayoutNodeMergeFile *) node; + MenuLayoutNodeMergeFile *copy_merge_file = (MenuLayoutNodeMergeFile *) copy; + + copy_merge_file->type = merge_file->type; + } + break; + default: break; } @@ -580,6 +601,18 @@ menu_layout_node_root_get_name (MenuLayo } const char * +menu_layout_node_root_get_basedir (MenuLayoutNode *node) +{ + MenuLayoutNodeRoot *nr; + + g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_ROOT, NULL); + + nr = (MenuLayoutNodeRoot*) node; + + return nr->basedir; +} + +const char * menu_layout_node_menu_get_name (MenuLayoutNode *node) { MenuLayoutNodeMenu *nm; @@ -839,6 +872,31 @@ menu_layout_node_legacy_dir_set_prefix ( legacy->prefix = g_strdup (prefix); } +MenuMergeFileType +menu_layout_node_merge_file_get_type (MenuLayoutNode *node) +{ + MenuLayoutNodeMergeFile *merge_file; + + g_return_val_if_fail (node->type == MENU_LAYOUT_NODE_MERGE_FILE, FALSE); + + merge_file = (MenuLayoutNodeMergeFile *) node; + + return merge_file->type; +} + +void +menu_layout_node_merge_file_set_type (MenuLayoutNode *node, + MenuMergeFileType type) +{ + MenuLayoutNodeMergeFile *merge_file; + + g_return_if_fail (node->type == MENU_LAYOUT_NODE_MERGE_FILE); + + merge_file = (MenuLayoutNodeMergeFile *) node; + + merge_file->type = type; +} + void menu_layout_node_root_add_entries_monitor (MenuLayoutNode *node, MenuLayoutNodeEntriesChangedFunc callback, @@ -1203,6 +1261,25 @@ start_menu_child_element (MenuParser menu_layout_node_legacy_dir_set_prefix (parser->stack_top, prefix); } + else if (ELEMENT_IS ("MergeFile")) + { + const char *type; + + push_node (parser, MENU_LAYOUT_NODE_MERGE_FILE); + + if (!locate_attributes (context, element_name, + attribute_names, attribute_values, + error, + "type", &type, + NULL)) + return; + + if (type != NULL && strcmp (type, "parent") == 0) + { + menu_layout_node_merge_file_set_type (parser->stack_top, + MENU_MERGE_FILE_TYPE_PARENT); + } + } else if (ELEMENT_IS ("DefaultLayout")) { const char *show_empty; @@ -1282,10 +1359,6 @@ start_menu_child_element (MenuParser { push_node (parser, MENU_LAYOUT_NODE_EXCLUDE); } - else if (ELEMENT_IS ("MergeFile")) - { - push_node (parser, MENU_LAYOUT_NODE_MERGE_FILE); - } else if (ELEMENT_IS ("MergeDir")) { push_node (parser, MENU_LAYOUT_NODE_MERGE_DIR); @@ -1700,7 +1773,6 @@ end_element_handler (GMarkupParseContext case MENU_LAYOUT_NODE_DIRECTORY: case MENU_LAYOUT_NODE_FILENAME: case MENU_LAYOUT_NODE_CATEGORY: - case MENU_LAYOUT_NODE_MERGE_FILE: case MENU_LAYOUT_NODE_MERGE_DIR: case MENU_LAYOUT_NODE_LEGACY_DIR: case MENU_LAYOUT_NODE_OLD: @@ -1746,6 +1818,7 @@ end_element_handler (GMarkupParseContext case MENU_LAYOUT_NODE_DEFAULT_LAYOUT: case MENU_LAYOUT_NODE_SEPARATOR: case MENU_LAYOUT_NODE_MERGE: + case MENU_LAYOUT_NODE_MERGE_FILE: break; case MENU_LAYOUT_NODE_MOVE: Index: libmenu/menu-layout.h =================================================================== RCS file: /cvs/gnome/gnome-menus/libmenu/menu-layout.h,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 menu-layout.h --- libmenu/menu-layout.h 9 Nov 2004 15:06:30 -0000 1.1.1.1 +++ libmenu/menu-layout.h 22 Mar 2005 10:39:11 -0000 @@ -68,6 +68,13 @@ typedef enum MENU_LAYOUT_NODE_MERGE } MenuLayoutNodeType; +typedef enum +{ + MENU_MERGE_FILE_TYPE_PATH = 0, + MENU_MERGE_FILE_TYPE_PARENT +} MenuMergeFileType; + + MenuLayoutNode *menu_layout_load (const char *filename, GError **error); @@ -101,7 +108,8 @@ void menu_layout_node_set_content char *menu_layout_node_get_content_as_path (MenuLayoutNode *node); -const char *menu_layout_node_root_get_name (MenuLayoutNode *node); +const char *menu_layout_node_root_get_name (MenuLayoutNode *node); +const char *menu_layout_node_root_get_basedir (MenuLayoutNode *node); const char *menu_layout_node_menu_get_name (MenuLayoutNode *node); EntryDirectoryList *menu_layout_node_menu_get_app_dirs (MenuLayoutNode *node); @@ -113,6 +121,10 @@ const char *menu_layout_node_move_get_ne const char *menu_layout_node_legacy_dir_get_prefix (MenuLayoutNode *node); void menu_layout_node_legacy_dir_set_prefix (MenuLayoutNode *node, const char *prefix); + +MenuMergeFileType menu_layout_node_merge_file_get_type (MenuLayoutNode *node); +void menu_layout_node_merge_file_set_type (MenuLayoutNode *node, + MenuMergeFileType type); typedef void (* MenuLayoutNodeEntriesChangedFunc) (MenuLayoutNode *node, gpointer user_data); Index: libmenu/menu-tree.c =================================================================== RCS file: /cvs/gnome/gnome-menus/libmenu/menu-tree.c,v retrieving revision 1.15 diff -u -p -r1.15 menu-tree.c --- libmenu/menu-tree.c 16 Mar 2005 08:09:02 -0000 1.15 +++ libmenu/menu-tree.c 22 Mar 2005 10:39:12 -0000 @@ -1127,7 +1127,7 @@ merge_resolved_children (MenuTree } } -static void +static gboolean load_merge_file (MenuTree *tree, const char *filename, gboolean is_canonical, @@ -1150,7 +1150,7 @@ load_merge_file (MenuTree *tree, menu_verbose ("Failed to canonicalize merge file path \"%s\": %s\n", filename, g_strerror (errno)); - return; + return FALSE; } } else @@ -1165,7 +1165,7 @@ load_merge_file (MenuTree *tree, { menu_verbose ("No menu for file \"%s\" found when merging\n", canonical); - return; + return FALSE; } if (add_monitor) @@ -1179,6 +1179,121 @@ load_merge_file (MenuTree *tree, if (freeme) g_free (freeme); + + return TRUE; +} + +static gboolean +load_merge_file_with_config_dir (MenuTree *tree, + const char *menu_file, + const char *config_dir, + MenuLayoutNode *where) +{ + char *merge_file; + gboolean loaded; + + loaded = FALSE; + + merge_file = g_build_filename (config_dir, "menus", menu_file, NULL); + + if (load_merge_file (tree, merge_file, FALSE, TRUE, where)) + loaded = TRUE; + + g_free (merge_file); + + return loaded; +} + +static gboolean +compare_basedir_to_config_dir (const char *canonical_basedir, + const char *config_dir) +{ + char *dirname; + char *canonical_menus_dir; + gboolean retval; + + menu_verbose ("Checking to see if basedir '%s' is in '%s'\n", + canonical_basedir, config_dir); + + dirname = g_build_filename (config_dir, "menus", NULL); + + retval = FALSE; + + canonical_menus_dir = menu_canonicalize_file_name (dirname, FALSE); + if (canonical_menus_dir != NULL && + strcmp (canonical_basedir, canonical_menus_dir) == 0) + { + retval = TRUE; + } + + g_free (canonical_menus_dir); + g_free (dirname); + + return retval; +} + +static gboolean +load_parent_merge_file (MenuTree *tree, + MenuLayoutNode *layout) +{ + MenuLayoutNode *root; + const char *basedir; + const char *menu_name; + char *canonical_basedir; + char *menu_file; + gboolean found_basedir; + const char * const *system_config_dirs; + int i; + + root = menu_layout_node_get_root (layout); + + basedir = menu_layout_node_root_get_basedir (root); + menu_name = menu_layout_node_root_get_name (root); + + canonical_basedir = menu_canonicalize_file_name (basedir, FALSE); + if (canonical_basedir == NULL) + { + menu_verbose ("Menu basedir '%s' no longer exists, not merging parent\n", + basedir); + return FALSE; + } + + menu_file = g_strconcat (menu_name, ".menu", NULL); + + found_basedir = compare_basedir_to_config_dir (canonical_basedir, + g_get_user_config_dir ()); + + system_config_dirs = g_get_system_config_dirs (); + + i = 0; + while (system_config_dirs[i] != NULL) + { + if (!found_basedir) + { + found_basedir = compare_basedir_to_config_dir (canonical_basedir, + system_config_dirs[i]); + } + else + { + menu_verbose ("Looking for parent menu file '%s' in '%s'\n", + menu_file, system_config_dirs[i]); + + if (load_merge_file_with_config_dir (tree, + menu_file, + system_config_dirs[i], + layout)) + { + break; + } + } + + ++i; + } + + g_free (menu_file); + g_free (canonical_basedir); + + return found_basedir; } static void @@ -1235,6 +1350,12 @@ resolve_merge_file (MenuTree *tr MenuLayoutNode *layout) { char *filename; + + if (menu_layout_node_merge_file_get_type (layout) == MENU_MERGE_FILE_TYPE_PARENT) + { + if (load_parent_merge_file (tree, layout)) + return; + } filename = menu_layout_node_get_content_as_path (layout); if (filename == NULL) Index: libmenu/menu-util.c =================================================================== RCS file: /cvs/gnome/gnome-menus/libmenu/menu-util.c,v retrieving revision 1.1.1.1 diff -u -p -r1.1.1.1 menu-util.c --- libmenu/menu-util.c 9 Nov 2004 15:06:27 -0000 1.1.1.1 +++ libmenu/menu-util.c 22 Mar 2005 10:39:12 -0000 @@ -314,8 +314,16 @@ append_to_string (MenuLayoutNode *node, break; case MENU_LAYOUT_NODE_MERGE_FILE: - append_simple (node, depth, "MergeFile", str); - break; + { + MenuMergeFileType type; + + type = menu_layout_node_merge_file_get_type (node); + + append_simple_with_attr (node, depth, "MergeFile", + "type", type == MENU_MERGE_FILE_TYPE_PARENT ? "parent" : "path", + str); + break; + } case MENU_LAYOUT_NODE_MERGE_DIR: append_simple (node, depth, "MergeDir", str);