r1164: Do UTF-8 conversions for globicons, as we now do for pinboards and panels.
[rox-filer.git] / ROX-Filer / src / appmenu.c
blob4ad89926484091657198ccdb6974c4729d527a44
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2002, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* appmenu.c - handles application-specific menus read from XMLwrapper.xml */
24 #include "config.h"
26 #include <gtk/gtk.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <ctype.h>
32 #include <parser.h>
34 #include "global.h"
36 #include "fscache.h"
37 #include "gui_support.h"
38 #include "support.h"
39 #include "menu.h"
40 #include "filer.h"
41 #include "appmenu.h"
42 #include "dir.h"
43 #include "type.h"
44 #include "appinfo.h"
46 /* Static prototypes */
47 static void apprun_menu(GtkWidget *item, gpointer data);
48 static GtkWidget *create_menu_item(xmlNode *node);
50 /* There can only be one menu open at a time... we store: */
51 static GtkWidget *current_menu = NULL; /* The GtkMenu */
52 static guchar *current_app_path = NULL; /* The path of the application */
53 static GList *current_items = NULL; /* The GtkMenuItems we added directly
54 * to it --- not submenu items.
57 /****************************************************************
58 * EXTERNAL INTERFACE *
59 ****************************************************************/
61 /* Removes all appmenu menu items */
62 void appmenu_remove(void)
64 GList *next;
66 if (!current_menu)
67 return;
69 for (next = current_items; next; next = next->next)
70 gtk_widget_destroy((GtkWidget *) next->data);
72 g_free(current_app_path);
73 current_app_path = NULL;
74 current_menu = NULL;
76 g_list_free(current_items);
77 current_items = NULL;
80 /* Add AppMenu entries to 'menu', if appropriate.
81 * This function modifies the menu stored in "menu".
82 * 'app_dir' is the pathname of the application directory, and 'item'
83 * is the corresponding DirItem.
84 * Call appmenu_remove() to undo the effect.
86 void appmenu_add(guchar *app_dir, DirItem *item, GtkWidget *menu)
88 XMLwrapper *ai;
89 xmlNode *node;
90 GList *next;
91 GtkWidget *sep;
93 g_return_if_fail(menu != NULL);
95 /* Should have called appmenu_remove() already... */
96 g_return_if_fail(current_menu == NULL);
98 ai = appinfo_get(app_dir, item);
99 if (!ai)
100 return; /* No appmenu (or invalid XML) */
102 /* OK, we've got a valid info file and parsed it.
103 * Now build the GtkMenuItem widgets and add them to the menu
104 * (if there are any).
107 node = appinfo_get_section(ai, "AppMenu");
108 if (!node)
109 return;
111 g_return_if_fail(current_items == NULL);
113 /* Add the menu entries */
114 for (node = node->xmlChildrenNode; node; node = node->next)
116 GtkWidget *item;
118 item = create_menu_item(node);
120 if (item)
121 current_items = g_list_prepend(current_items, item);
124 sep = gtk_menu_item_new();
125 current_items = g_list_prepend(current_items, sep);
126 gtk_widget_show(sep);
128 for (next = current_items; next; next = next->next)
129 gtk_menu_shell_prepend(GTK_MENU_SHELL(menu),
130 GTK_WIDGET(next->data));
132 current_menu = menu;
133 current_app_path = g_strdup(app_dir);
136 /****************************************************************
137 * INTERNAL FUNCTIONS *
138 ****************************************************************/
140 /* Create a new menu and return it */
141 static GtkWidget *appmenu_add_submenu(xmlNode *subm_node)
143 xmlNode *node;
144 GtkWidget *sub_menu;
146 /* Create the new submenu */
147 sub_menu = gtk_menu_new();
149 /* Add the menu entries */
150 for (node = subm_node->xmlChildrenNode; node; node = node->next)
152 GtkWidget *item;
154 item = create_menu_item(node);
155 if (item)
156 gtk_menu_append(GTK_MENU(sub_menu), item);
159 return sub_menu;
162 /* Create and return a menu item */
163 static GtkWidget *create_menu_item(xmlNode *node)
165 GtkWidget *item;
166 guchar *label, *option = NULL;
167 gboolean is_submenu;
169 if (node->type != XML_ELEMENT_NODE)
170 return NULL;
172 if (strcmp(node->name, "Item") == 0)
174 is_submenu = FALSE;
175 option = xmlGetProp(node, "option");
177 else if (strcmp(node->name, "AppMenu") == 0)
178 is_submenu = TRUE;
179 else
180 return NULL;
182 /* Create the item */
183 label = xmlGetProp(node, "label");
184 if (!label)
185 label = g_strdup(_("<missing label>"));
186 item = gtk_menu_item_new_with_label(label);
187 #ifdef GTK2
188 gtk_widget_set_accel_path(item, NULL, NULL);
189 #else
190 gtk_widget_lock_accelerators(item);
191 #endif
193 g_free(label);
195 if (is_submenu)
197 /* Add submenu items */
199 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item),
200 appmenu_add_submenu(node));
202 else
204 /* Set up callback */
206 if (option)
208 gtk_object_set_data_full(GTK_OBJECT(item), "option",
209 g_strdup(option),
210 g_free);
211 g_free(option);
214 gtk_signal_connect(GTK_OBJECT(item), "activate",
215 GTK_SIGNAL_FUNC(apprun_menu),
216 NULL);
219 gtk_widget_show(item);
221 return item;
224 /* Function called to execute an AppMenu item */
225 static void apprun_menu(GtkWidget *item, gpointer data)
227 guchar *option;
228 char *argv[3];
230 g_return_if_fail(current_app_path != NULL);
232 option = gtk_object_get_data(GTK_OBJECT(item), "option");
234 argv[0] = g_strconcat(current_app_path, "/AppRun", NULL);
235 argv[1] = option; /* (may be NULL) */
236 argv[2] = NULL;
238 rox_spawn(NULL, argv);
240 g_free(argv[0]);