Re: Say goodbye to those ugly ass add-to-panel submenu blues



Bugger...I knew there was something I forgot.

On Wed, 2003-11-19 at 23:04, iain wrote:
> Attached is a patch that removes the Add To Panel submenu from the panel
> submenu.
> 
> It replaces it with an Add to Panel dialog. I've had this patch in place
> for ages on my system, and it totally rocks. No more million level deep
> submenu. No more weird categorisations for applets.
> 
> Try out this new patch today, you'll love the results.
> 
> iain - trying to trigger as many spamassassin filters as possible :D
> (I also added myself to the about box, I hope no-one minded, look at it
> this way..."I fought menu.c and ... I won". If that was inappropriate,
> feel free to remove me, I don't really care)
-- 
"Miss Celine Dion sings lovesongs while our cities burn"
Index: menu.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/menu.c,v
retrieving revision 1.693
diff -U2 -r1.693 menu.c
--- menu.c	13 Nov 2003 00:38:52 -0000	1.693
+++ menu.c	19 Nov 2003 22:56:50 -0000
@@ -167,12 +167,63 @@
 	  PANEL_ACTION_RUN,
 	  "ACTION:run:NEW",
+	  TRUE },
+
+	{ N_("Custom Application Launcher"),
+	  N_("Special Items"),
+	  "Special Items",
+	  N_("Create a new launcher"),
+	  NULL,
+	  PANEL_STOCK_LAUNCHER,
+	  PANEL_ACTION_NONE,
+	  "LAUNCHER:ASK",
+	  TRUE },
+
+	{ N_("Application Launcher"),
+	  N_("Special Items"),
+	  "Special Items",
+	  N_("Launch a program that is already in the GNOME menu"),
+	  NULL,
+	  PANEL_STOCK_LAUNCHER,
+	  PANEL_ACTION_NONE,
+	  "LAUNCHER:MENU",
+	  TRUE },
+
+	{ N_("Main Menu"),
+	  N_("Special Items"),
+	  "Special Items",
+	  N_("The main GNOME menu"),
+	  NULL,
+	  PANEL_STOCK_MAIN_MENU,
+	  PANEL_ACTION_NONE,
+	  "MENU:MAIN",
+	  TRUE },
+
+	{ N_("Menu Bar"),
+	  N_("Special Items"),
+	  "Special Items",
+	  N_("A custom menu bar"),
+	  NULL,
+	  PANEL_STOCK_GNOME_LOGO,
+	  PANEL_ACTION_NONE,
+	  "MENUBAR:NEW",
+	  TRUE },
+	
+	{ N_("Drawer"),
+	  N_("Special Items"),
+	  "Special Items",
+	  N_("A pop out drawer to store other items in"),
+	  NULL,
+	  PANEL_STOCK_DRAWER,
+	  PANEL_ACTION_NONE,
+	  "DRAWER:NEW",
 	  TRUE }
 };
 
 static guint load_icons_id = 0;
+static guint add_icon_idle_id = 0;
 static GHashTable *loaded_icons = NULL;
 static GList *icons_to_load = NULL;
 static GList *icons_to_add = NULL;
-
+static GSList *add_icon_paths = NULL;
 static GSList *image_menu_items = NULL;
 
@@ -260,4 +311,5 @@
 		"George Lebl (jirka 5z com)",
 		"Glynn Foster (glynn foster sun com)",
+		"Iain Holmes (iain prettypeople org)",
 		"Ian Main (imain gtk org)",
 		"Ian McKellar <yakk yakk net>",
@@ -2403,89 +2455,4 @@
 }
 
-static const char *
-applet_menu_get_category_icon (const char *untranslated_category)
-{
-	static GHashTable *hash = NULL;
-
-	if (!hash) {
-		hash = g_hash_table_new (g_str_hash, g_str_equal);
-		g_hash_table_insert (hash, "Accessories", PANEL_STOCK_ACCESSORIES); 
-		g_hash_table_insert (hash, "Amusements", PANEL_STOCK_AMUSEMENTS);
-		g_hash_table_insert (hash, "Multimedia", PANEL_STOCK_MULTIMEDIA);
-		g_hash_table_insert (hash, "Internet",   PANEL_STOCK_INTERNET);
-		g_hash_table_insert (hash, "Utility",    PANEL_STOCK_UTILITY);
-		g_hash_table_insert (hash, "Actions",	 PANEL_STOCK_ACTION);
-	}
-
-	return g_hash_table_lookup (hash, untranslated_category);
-}
-
-static GtkWidget *
-applet_menu_append (GtkWidget  *menu,
-		    AppletMenuInfo *applet,
-		    gboolean applets_writable,
-		    gboolean objects_writable)
-{
-	GtkWidget *menuitem;
-
-	menuitem = gtk_image_menu_item_new ();
-
-	if (applet->icon || applet->stock_icon)
-		panel_load_menu_image_deferred (
-			menuitem, GTK_ICON_SIZE_MENU, applet->stock_icon, applet->icon, NULL, FALSE);
-	
-	setup_menuitem (menuitem, GTK_ICON_SIZE_MENU, NULL, applet->name, TRUE);
-
-	gtk_widget_show_all (menuitem);
-
-	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
-	if (applet->description)
-		gtk_tooltips_set_tip (panel_tooltips, menuitem, applet->description, NULL);
-	
-	if (applet->action_type != PANEL_ACTION_NONE) {
-		/* only allow dragging objects if we can add objects */
-		if (panel_profile_list_is_writable (PANEL_GCONF_OBJECTS))
-			setup_internal_applet_drag (menuitem, applet->drag_data);
-
-		g_signal_connect (menuitem, "activate",
-				  G_CALLBACK (add_action_button_to_panel),
-				  GINT_TO_POINTER (applet->action_type));
-		gtk_widget_set_sensitive (menuitem, objects_writable);
-	} else {
-		/* only allow dragging applets if we can add applets */
-		if (panel_profile_list_is_writable (PANEL_GCONF_APPLETS))
-			setup_applet_drag (menuitem, applet->drag_data);
-		
-		g_signal_connect_data (menuitem, "activate", G_CALLBACK (add_bonobo_applet),
-				       g_strdup (applet->drag_data), (GClosureNotify) g_free, 0);
-		gtk_widget_set_sensitive (menuitem, applets_writable);
-	}
-
-	return menuitem;
-}
-
-static GtkWidget *
-applet_menu_append_category (GtkWidget *menu,
-                             const char *category,
-			     const char *stock_icon)
-{
-	GtkWidget *menuitem;
-
-	menuitem = gtk_image_menu_item_new ();
-
-	if (stock_icon)
-		panel_load_menu_image_deferred (
-			menuitem, GTK_ICON_SIZE_MENU, stock_icon, NULL, NULL, FALSE);
-
-	setup_menuitem (menuitem, GTK_ICON_SIZE_MENU, NULL, category, TRUE);
-
-	gtk_widget_show_all (menuitem);
-
-	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
-	return menuitem;
-}
-
 static void
 add_bonobo_applet (GtkWidget  *item,
@@ -2517,140 +2484,8 @@
 	};
 
-typedef struct {
-	Bonobo_ServerInfoList *applet_list;
-	GtkMenuItem           *item;
-	GtkWidget             *menu;
-	int                    timeout_id;
-} ReloadData;
-
-static gboolean
-Bonobo_ServerInfoList_equals (Bonobo_ServerInfoList *l1,
-			      Bonobo_ServerInfoList *l2)
-{
-	CORBA_any         a1, a2;
-	CORBA_Environment env;
-	gboolean          retval;
-
-	CORBA_exception_init (&env);
-
-	a1._release = FALSE;
-	a1._type    = TC_Bonobo_ServerInfoList;
-	a1._value   = l1;
-
-	a2._release = FALSE;
-	a2._type    = TC_Bonobo_ServerInfoList;
-	a2._value   = l2;
-
-	retval = ORBit_any_equivalent (&a1, &a2, &env);
-	if (BONOBO_EX (&env)) {
-		g_warning ("comparison returned exception %s\n", BONOBO_EX_REPOID (&env));
-		CORBA_exception_free (&env);
-		return FALSE;
-	}
-
-	return retval;
-}
-
-static gboolean
-recheck_applet_list (ReloadData *reload_data)
-{
-	Bonobo_ServerInfoList *applet_list;
-	CORBA_Environment      env;
-
-	if (GTK_WIDGET_VISIBLE (reload_data->menu))
-		return TRUE;
-
-	CORBA_exception_init (&env);
-
-	applet_list = bonobo_activation_query (applet_requirements,
-					       applet_sort_criteria,
-					       &env);
-	if (BONOBO_EX (&env)) {
-		g_warning (_("query returned exception %s\n"), BONOBO_EX_REPOID (&env));
-		CORBA_exception_free (&env);
-		return TRUE;
-	}
-
-	CORBA_exception_free (&env);
-
-	if (Bonobo_ServerInfoList_equals (applet_list, reload_data->applet_list)) {
-		CORBA_free (applet_list);
-		return TRUE;
-	}
-
-	gtk_widget_destroy (reload_data->menu);
-	g_object_unref (reload_data->menu);
-
-	reload_data->menu = menu_new ();
-	gtk_menu_item_set_submenu (reload_data->item, reload_data->menu);
-
-	CORBA_free (reload_data->applet_list);
-	reload_data->applet_list = applet_list;
-
-	make_add_submenu (reload_data->menu, applet_list);
-
-	return TRUE;
-}
-
-static void
-menu_item_destroyed (GtkMenuItem *item,
-		     ReloadData  *reload_data)
-{
-	g_source_remove (reload_data->timeout_id);
-
-	g_object_unref (reload_data->menu);
-
-	CORBA_free (reload_data->applet_list);
-
-	g_free (reload_data);
-}
-
-static Bonobo_ServerInfoList *
-instrument_add_submenu_for_reload (GtkMenuItem *item,
-				   GtkWidget   *menu)
-{
-	CORBA_Environment  env;
-	ReloadData        *reload_data;
-
-	reload_data = g_new0 (ReloadData, 1);
-
-	CORBA_exception_init (&env);
-
-	reload_data->applet_list =
-		bonobo_activation_query (applet_requirements,
-					 applet_sort_criteria,
-					 &env);
-	if (BONOBO_EX (&env)) {
-		g_warning (_("query returned exception %s\n"), BONOBO_EX_REPOID (&env));
-
-		CORBA_exception_free (&env);
-		g_free (reload_data);
-
-		return NULL;
-	}
-
-	reload_data->timeout_id =
-		g_timeout_add (5 * 1000, (GSourceFunc) recheck_applet_list, reload_data);
-
-	reload_data->item = item;
-	reload_data->menu = g_object_ref (menu);
-
-	g_signal_connect (item, "destroy",
-			  G_CALLBACK (menu_item_destroyed), reload_data);
-
-	CORBA_exception_free (&env);
-
-	return reload_data->applet_list;
-}
-
 static int
 applet_info_sort_func (AppletMenuInfo *a,
                        AppletMenuInfo *b)
 {
-	int c;
-
-	if ((c = strcmp (a->category, b->category)))
-		return c;
-
 	return strcmp (a->name, b->name);
 }
@@ -2685,127 +2520,4 @@
 }	
 
-static GtkWidget *
-create_applets_menu (GtkWidget             *menu,
-		     Bonobo_ServerInfoList *applet_list)
-{
-	GtkWidget         *prev_menu = NULL;
-	const char        *prev_category = NULL;
-	int                i;
-	const GList       *langs_glist;
-	GSList            *langs_gslist;
-	GSList            *applets = NULL;
-	GSList		  *item = NULL;
-	GSList            *disabled_applets;
-	gboolean           applets_writable;
-	gboolean           objects_writable;
-
-	if (!applet_list)
-		return NULL;
-
-	applets_writable = panel_profile_list_is_writable (PANEL_GCONF_APPLETS);
-	objects_writable = panel_profile_list_is_writable (PANEL_GCONF_OBJECTS);
-
-	if (!menu)
-		menu = menu_new ();
-
-	g_signal_connect (G_OBJECT (menu), "destroy", G_CALLBACK (menu_destroy), NULL);
-
-	/* Evil evil evil evil, we need to convert to
-	 * a GSList from a GList */
-	langs_glist = gnome_i18n_get_language_list ("LC_MESSAGES");
-	langs_gslist = NULL;
-	while (langs_glist != NULL) {
-		langs_gslist = g_slist_append (langs_gslist, langs_glist->data);
-		langs_glist = langs_glist->next;
-	}
-
-	disabled_applets = panel_profile_get_disabled_applets ();
-
-	for (i = 0; i < applet_list->_length; i++) {
-		Bonobo_ServerInfo *info;
-		AppletMenuInfo    *applet;
-		const char        *name;
-		const char        *description;
-		const char        *icon;
-		const char        *category;
-		const char        *untranslated_category;
-
-		info = &applet_list->_buffer [i];
-
-		if (g_slist_find_custom (disabled_applets, info->iid, (GCompareFunc)strcmp) != NULL)
-			continue;
-
-		name        = bonobo_server_info_prop_lookup (info, "name", langs_gslist);
-		category    = bonobo_server_info_prop_lookup (info, "panel:category", langs_gslist);
-	        description = bonobo_server_info_prop_lookup (info, "description", langs_gslist);
-		icon        = bonobo_server_info_prop_lookup (info, "panel:icon", NULL);
-
-		untranslated_category =
-			bonobo_server_info_prop_lookup (info, "panel:category", NULL);
-
-		if (!name)
-			continue;
-
-		applet = g_new0 (AppletMenuInfo, 1);
-		applet->name = name;
-		applet->category = category;
-		applet->untranslated_category = untranslated_category;
-		applet->description = description;
-		applet->icon = icon;
-		applet->drag_data = info->iid;
-
-		applets = g_slist_append (applets, applet);
-	}
-	
-	/* add internal action buttons */
-	applets = append_internal_applets (applets);	
-	
-	/* sort by category, then name */
-	applets = g_slist_sort (applets, (GCompareFunc) applet_info_sort_func);
-
-	item = applets;
-	while (item != NULL) {
-		GtkWidget         *menuitem;		
-		AppletMenuInfo        *applet;
-		
-		applet = (AppletMenuInfo *) item->data;
-		item = item->next;
-		
-		if (string_empty (applet->category)) {
-			applet_menu_append (menu, applet,
-					    applets_writable,
-					    objects_writable);
-			continue;
-		}
-
-		if (!prev_category || strcmp (prev_category, applet->untranslated_category)) {
-			const char *cat_icon;
-
-			prev_category = applet->untranslated_category;
-			prev_menu = menu_new ();
-
-			cat_icon = applet_menu_get_category_icon (applet->untranslated_category);
-
-			menuitem = applet_menu_append_category (menu, applet->category, cat_icon);
-
-			gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), prev_menu);
-		}
-
-		applet_menu_append (prev_menu, applet,
-				    applets_writable,
-				    objects_writable);
-		
-		if (!applet->static_data)
-			g_free (applet);
-	}
-	
-	g_slist_free (langs_gslist);
-	g_slist_free (applets);
-
-	panel_g_slist_deep_free	(disabled_applets);
-	
-	return menu;
-}
-
 static void
 create_new_panel (GtkWidget *menuitem)
@@ -2980,10 +2692,631 @@
 }
 
+enum {
+	COL_PIXBUF,
+	COL_TEXT,
+	COL_DATA,
+	NUM_COLUMNS
+};
+	
+struct _add_to_panel_data {
+	PanelWidget *panel_widget;
+
+	GtkWidget *dialog;
+	GtkWidget *tree_view;
+	GtkWidget *special;
+	
+	GtkTreeModel *model;
+};
+
+static GtkWidget *
+make_title_label (const char *text)
+{
+	GtkWidget *label;
+	char *full;
+
+	full = g_strdup_printf ("<span weight=\"bold\">%s</span>", text);
+	label = gtk_label_new_with_mnemonic (full);
+	g_free (full);
+
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+
+	return label;
+}
+
+static char *
+make_text (const char *name,
+	   const char *desc)
+{
+	if (desc != NULL) {
+		return g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s",
+					name, desc);
+	} else {
+		return g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>",
+					name);
+	}
+}
+
+static GdkPixbuf *
+make_pixbuf (const char *filename,
+	     int size)
+{
+	char *file;
+	GdkPixbuf *pb;
+
+	file = gnome_desktop_item_find_icon (panel_icon_theme,
+					     filename, size, 0);
+	
+	pb = gdk_pixbuf_new_from_file (file, NULL);
+
+	g_free (file);
+	return pb;
+}
+
+static GtkTreeModel *
+make_applet_list (struct _add_to_panel_data *pd)
+{
+	GtkListStore *model;
+	GtkTreeIter iter;
+	Bonobo_ServerInfoList *applet_list;
+	CORBA_Environment  env;
+	const GList *langs_glist;
+	GSList *langs_gslist;
+	GSList *applets = NULL, *item = NULL;
+	int i;
+
+	CORBA_exception_init (&env);
+
+	applet_list = bonobo_activation_query (applet_requirements,
+					       applet_sort_criteria,
+					       &env);
+	if (BONOBO_EX (&env)) {
+		g_warning (_("query returned exception %s\n"), BONOBO_EX_REPOID (&env));
+		
+		CORBA_exception_free (&env);
+
+		return NULL;
+	}
+
+	CORBA_exception_free (&env);
+
+	model = gtk_list_store_new (NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
+	
+	/* Evil evil evil evil, we need to convery from a
+	   GList to a GSList */
+	langs_glist = gnome_i18n_get_language_list ("LC_MESSAGES");
+	langs_gslist = NULL;
+	while (langs_glist != NULL) {
+		langs_gslist = g_slist_append (langs_gslist, langs_glist->data);
+		langs_glist = langs_glist->next;
+	}
+	
+	for (i = 0; i < applet_list->_length; i++) {
+		Bonobo_ServerInfo *info;
+		const char *name, *description, *icon;
+		const char *category, *untranslated_category;
+		AppletMenuInfo *applet;
+		
+		info = &applet_list->_buffer[i];
+
+		name = bonobo_server_info_prop_lookup (info, "name", langs_gslist);
+		category = bonobo_server_info_prop_lookup (info, "panel:category", langs_gslist);
+		description = bonobo_server_info_prop_lookup (info, "description", langs_gslist);
+		icon = bonobo_server_info_prop_lookup (info, "panel:icon", NULL);
+
+		untranslated_category = bonobo_server_info_prop_lookup (info, "panel:category", NULL);
+
+		if (!name) {
+			continue;
+		}
+
+		applet = g_new0 (AppletMenuInfo, 1);
+		applet->name = name;
+		applet->category = category;
+		applet->untranslated_category = untranslated_category;
+		applet->description = description;
+		applet->icon = icon;
+		applet->drag_data = info->iid;
+
+		applets = g_slist_append (applets, applet);
+	}
+
+	applets = append_internal_applets (applets);
+
+	applets = g_slist_sort (applets, (GCompareFunc) applet_info_sort_func);
+
+	item = applets;
+	while (item != NULL) {
+		AppletMenuInfo *applet;
+		char *text;
+		GdkPixbuf *pixbuf;
+		
+		applet = (AppletMenuInfo *) item->data;
+		item = item->next;
+
+		if (applet->icon != NULL) {
+			pixbuf = make_pixbuf (applet->icon, PANEL_DEFAULT_MENU_ICON_SIZE);
+		} else {
+			pixbuf = gtk_widget_render_icon (GTK_WIDGET (pd->panel_widget),
+							 applet->stock_icon,
+							 GTK_ICON_SIZE_DIALOG, NULL);
+		}
+		
+		gtk_list_store_append (model, &iter);
+
+		text = make_text (applet->name, applet->description);
+		
+		gtk_list_store_set (model, &iter, COL_PIXBUF, pixbuf, COL_TEXT, text, COL_DATA, applet->drag_data, -1);
+
+		if (!applet->static_data) {
+			g_free (applet);
+		}
+	}
+
+	g_slist_free (langs_gslist);
+	g_slist_free (applets);
+
+	return (GtkTreeModel *) model;
+}
+
+static void
+add_action (PanelWidget *panel_widget,
+	    const char *item_id)
+{
+	static char *act[PANEL_ACTION_LAST] = {
+		"",
+		"logout:NEW",
+		"lock:NEW",
+		"force-quit:NEW",
+		"search:NEW",
+		"screenshot:NEW",
+		"run:NEW",
+	};
+	int i;
+
+	for (i = PANEL_ACTION_NONE; i < PANEL_ACTION_LAST; i++) {
+		if (strcmp (item_id, act[i]) == 0) {
+			break;
+		}
+	}
+
+	if (i == PANEL_ACTION_LAST) {
+		return;
+	}
+	
+	panel_action_button_create (panel_widget->toplevel, -1, i);
+}
+
+struct _get_application_data {
+	PanelWidget *panel_widget;
+
+	GtkWidget *dialog;
+	GtkWidget *tree_view;
+	GtkTreeModel *app_list;
+};
+
+enum {
+	COLUMN_ICON,
+	COLUMN_ICON_FILE,
+	COLUMN_FULLNAME,
+	COLUMN_DESKTOP_FILE,
+	NUMBER_COLUMNS
+};
+
+static gboolean
+add_icon_idle (GtkListStore *list)
+{
+	GtkTreeIter iter;
+	GtkTreePath *path;
+	GdkPixbuf *pixbuf;
+	char *file;
+	int icon_height;
+	gboolean long_operation;
+	
+	do {
+		if (add_icon_paths == NULL) {
+			add_icon_idle_id = 0;
+			return FALSE;
+		}
+
+		path = add_icon_paths->data;
+		add_icon_paths->data = NULL;
+		add_icon_paths = g_slist_delete_link (add_icon_paths,
+						      add_icon_paths);
+
+		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (list),
+					      &iter, path)) {
+			gtk_tree_path_free (path);
+			continue;
+		}
+
+		gtk_tree_path_free (path);
+
+		gtk_tree_model_get (GTK_TREE_MODEL (list), &iter,
+				    COLUMN_ICON_FILE, &file, -1);
+
+		if (!gtk_icon_size_lookup (panel_menu_icon_get_size (), NULL, &icon_height)) {
+			icon_height = PANEL_DEFAULT_MENU_ICON_SIZE;
+		}
+
+		pixbuf = panel_make_menu_icon (file, NULL, icon_height, &long_operation);
+		if (pixbuf) {
+			gtk_list_store_set (list, &iter, COLUMN_ICON, pixbuf, -1);
+			g_object_unref (pixbuf);
+		}
+	} while (!long_operation);
+
+	if (add_icon_paths == NULL) {
+		add_icon_idle_id = 0;
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static GtkTreeModel *
+make_application_model (struct _get_application_data *gad)
+{
+	GSList *tmp, *files, *prev;
+	char *prev_name;
+	GtkListStore *store;
+	FileRec *all_dir;
+
+	store = gtk_list_store_new (NUMBER_COLUMNS,
+				    GDK_TYPE_PIXBUF,
+				    G_TYPE_STRING,
+				    G_TYPE_STRING,
+				    G_TYPE_STRING);
+
+	all_dir = fr_get_dir ("all-applications:/");
+	if (all_dir != NULL) {
+		files = g_slist_copy (((DirRec *)all_dir)->recs);
+	} else {
+		files = NULL;
+	}
+
+	/* Collate */
+	files = g_slist_sort (files, (GCompareFunc) fr_compare);
+
+	/* Strip duplicates */
+	tmp = files;
+	prev = NULL;
+	prev_name = NULL;
+	while (tmp) {
+		FileRec *fr;
+
+		fr = tmp->data;
+		if (prev_name && strcmp (fr->fullname, prev_name) == 0) {
+			prev->next = tmp->next;
+			tmp->data = NULL;
+			g_slist_free_1 (tmp);
+			tmp = prev->next;
+		} else {
+			prev = tmp;
+			prev_name = fr->fullname;
+			tmp = tmp->next;
+		}
+	}
+
+	tmp = files;
+	while (tmp != NULL) {
+		GtkTreeIter iter;
+		FileRec *fr;
+		GtkTreePath *path;
+		char *text;
+		
+		fr = tmp->data;
+		gtk_list_store_append (store, &iter);
+
+		text = make_text (fr->fullname ? fr->fullname : "(empty)",
+				  fr->comment ? fr->comment : NULL);
+		
+		gtk_list_store_set (store, &iter,
+				    COLUMN_ICON, NULL,
+				    COLUMN_ICON_FILE, fr->icon ? fr->icon : "",
+				    COLUMN_FULLNAME, text,
+				    COLUMN_DESKTOP_FILE, fr->name,
+				    -1);
+
+		path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
+		if (path != NULL) {
+			add_icon_paths = g_slist_prepend (add_icon_paths, path);
+		}
+		
+		g_free (text);
+		tmp = tmp->next;
+	}
+
+	g_slist_free (files);
+
+	add_icon_paths = g_slist_reverse (add_icon_paths);
+	if (add_icon_idle_id == 0) {
+		add_icon_idle_id = g_idle_add_full (G_PRIORITY_LOW,
+						    (GSourceFunc) add_icon_idle,
+						    store, NULL);
+	}
+	
+	return GTK_TREE_MODEL (store);
+}
+	
+static void
+add_application_response (GtkDialog *dialog,
+			  guint response_id,
+			  struct _get_application_data *gad)
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	
+	switch (response_id) {
+	case GTK_RESPONSE_OK:
+		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gad->tree_view));
+		if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+			char *name;
+
+			gtk_tree_model_get (model, &iter, COLUMN_DESKTOP_FILE,
+					    &name, -1);
+			panel_launcher_create (gad->panel_widget->toplevel,
+					       -1, name);
+			g_free (name);
+		}
+		break;
+
+	case GTK_RESPONSE_HELP:
+
+		/* FIXME need help */
+		return;
+
+	case GTK_RESPONSE_CANCEL:
+	default:
+		break;
+	}
+		
+	gtk_widget_destroy (GTK_WIDGET (dialog));
+	g_slist_foreach (add_icon_paths, (GFunc) gtk_tree_path_free, NULL);
+	g_slist_free (add_icon_paths);
+	add_icon_paths = NULL;
+
+	if (add_icon_idle_id) {
+		g_source_remove (add_icon_idle_id);
+		add_icon_idle_id = 0;
+	}
+	
+	g_free (gad);
+}
+
+static void
+get_application (PanelWidget *panel_widget)
+{
+	struct _get_application_data *gad;
+	GtkWidget *vbox, *inner_vbox, *label, *sw;
+	GtkCellRenderer *renderer;
+	
+	gad = g_new (struct _get_application_data, 1);
+	gad->panel_widget = panel_widget;
+	
+	gad->dialog = gtk_dialog_new ();
+	gtk_window_set_title (GTK_WINDOW (gad->dialog), _("Add application to panel"));
+	gtk_dialog_set_has_separator (GTK_DIALOG (gad->dialog), FALSE);
+	gtk_window_set_default_size (GTK_WINDOW (gad->dialog), 560, 490);
+
+	g_signal_connect (G_OBJECT (gad->dialog), "response",
+			  G_CALLBACK (add_application_response), gad);
+
+	vbox = gtk_vbox_new (FALSE, 12);
+	gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+	gtk_widget_show (vbox);
+	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (gad->dialog)->vbox), vbox);
+
+	inner_vbox = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), inner_vbox, TRUE, TRUE, 0);
+
+	label = make_title_label (_("Select an _application to add to the panel:"));
+	gtk_box_pack_start (GTK_BOX (inner_vbox), label, FALSE, FALSE, 0);
+
+	gad->app_list = make_application_model (gad);
+
+	sw = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+					GTK_POLICY_AUTOMATIC,
+					GTK_POLICY_AUTOMATIC);
+	gtk_box_pack_start (GTK_BOX (inner_vbox), sw, TRUE, TRUE, 0);
+
+	gad->tree_view = gtk_tree_view_new_with_model (gad->app_list);
+	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (gad->tree_view), FALSE);
+
+	renderer = g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF,
+				 "xpad", 4,
+				 "ypad", 4,
+				 NULL);
+	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (gad->tree_view),
+						     -1, NULL,
+						     renderer,
+						     "pixbuf", COLUMN_ICON,
+						     NULL);
+
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (gad->tree_view),
+						     -1, NULL,
+						     renderer,
+						     "markup", COLUMN_FULLNAME,
+						     NULL);
+	gtk_container_add (GTK_CONTAINER (sw), gad->tree_view);
+
+	gtk_dialog_add_button (GTK_DIALOG (gad->dialog),
+			       GTK_STOCK_CANCEL,
+			       GTK_RESPONSE_CANCEL);
+	gtk_dialog_add_button (GTK_DIALOG (gad->dialog),
+			       _("Add Application"),
+			       GTK_RESPONSE_OK);
+	gtk_dialog_add_button (GTK_DIALOG (gad->dialog),
+			       GTK_STOCK_HELP,
+			       GTK_RESPONSE_HELP);
+
+	gtk_widget_show_all (gad->dialog);
+}
+	
+static void
+add_item (PanelWidget *panel_widget,
+	  const char *item_id)
+{
+	if (strncmp (item_id, "OAFIID:", 7) == 0) {
+		/* Applet */
+		panel_applet_frame_create (panel_widget->toplevel, -1, item_id);
+		return;
+	}
+
+	if (strncmp (item_id, "ACTION:", 7) == 0) {
+		/* Action */
+		add_action (panel_widget, item_id + 7);
+		return;
+	}
+
+	if (strncmp (item_id, "LAUNCHER:", 9) == 0) {
+		/* Launcher */
+		if (strcmp (item_id + 9, "ASK") == 0) {
+			ask_about_launcher (NULL, panel_widget, -1, FALSE);
+		} else {
+			get_application (panel_widget);
+		}
+
+		return;
+	}
+
+	if (strcmp (item_id, "MENU:MAIN") == 0) {
+		panel_menu_button_create (panel_widget->toplevel, -1,
+					  NULL, FALSE, NULL);
+		return;
+	}
+
+	if (strcmp (item_id, "MENUBAR:NEW") == 0) {
+		panel_menu_bar_create (panel_widget->toplevel, -1);
+		return;
+	}
+
+	if (strcmp (item_id, "DRAWER:NEW") == 0) {
+		panel_drawer_create (panel_widget->toplevel, -1, NULL, FALSE, NULL);
+		return;
+	}
+}
+
+
+static void
+add_to_panel_response (GtkWidget *dialog,
+		       guint response_id,
+		       struct _add_to_panel_data *pd)
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	
+	switch (response_id) {
+	case GTK_RESPONSE_HELP:
+		/* Do help */
+		return;
+
+	case GTK_RESPONSE_OK:
+		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pd->tree_view));
+		if (gtk_tree_selection_get_selected (selection,
+						     &model, &iter) == TRUE) {
+			char *iid;
+
+			gtk_tree_model_get (model, &iter, COL_DATA, &iid, -1);
+
+			if (iid != NULL) {
+				add_item (pd->panel_widget, iid);
+			}
+		}
+		break;
+
+	case GTK_RESPONSE_CANCEL:
+	default:
+		break;
+	}
+
+	gtk_widget_destroy (dialog);
+	g_free (pd);
+}
+		
+static void
+add_to_panel_cb (GtkMenuItem *item,
+		 PanelWidget *panel_widget)
+{
+	struct _add_to_panel_data *pd;
+	GtkWidget *vbox, *inner_vbox, *label;
+	GtkWidget *sw;
+	GtkCellRenderer *renderer;
+	
+	pd = g_new0 (struct _add_to_panel_data, 1);
+	pd->panel_widget = panel_widget;
+
+	pd->dialog = gtk_dialog_new ();
+	gtk_window_set_title (GTK_WINDOW (pd->dialog), _("Add To Panel"));
+	gtk_dialog_set_has_separator (GTK_DIALOG (pd->dialog), FALSE);
+	gtk_window_set_default_size (GTK_WINDOW (pd->dialog), 560, 490);
+
+	g_signal_connect (G_OBJECT (pd->dialog), "response",
+			  G_CALLBACK (add_to_panel_response), pd);
+	
+	vbox = gtk_vbox_new (FALSE, 12);
+	gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
+	gtk_widget_show (vbox);
+	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (pd->dialog)->vbox), vbox);
+
+	inner_vbox = gtk_vbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (vbox), inner_vbox, TRUE, TRUE, 0);
+
+	label = make_title_label (_("Add an _item to the panel:"));
+	gtk_box_pack_start (GTK_BOX (inner_vbox), label, FALSE, FALSE, 0);
+
+	pd->model = make_applet_list (pd);
+	
+	sw = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+					GTK_POLICY_AUTOMATIC,
+					GTK_POLICY_AUTOMATIC);
+	gtk_box_pack_start (GTK_BOX (inner_vbox), sw, TRUE, TRUE, 0);
+
+	pd->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (pd->model));
+	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (pd->tree_view), FALSE);
+	gtk_tree_view_expand_all (GTK_TREE_VIEW (pd->tree_view));
+	
+	renderer = g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF,
+				 "xpad", 4,
+				 "ypad", 4,
+				 NULL);
+
+	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (pd->tree_view),
+						     -1, NULL,
+						     renderer,
+						     "pixbuf", COL_PIXBUF,
+						     NULL);
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (pd->tree_view),
+						     -1, NULL,
+						     renderer,
+						     "markup", COL_TEXT,
+						     NULL);
+	gtk_container_add (GTK_CONTAINER (sw), pd->tree_view);
+	gtk_widget_show_all (sw);
+
+	gtk_dialog_add_button (GTK_DIALOG (pd->dialog),
+			       GTK_STOCK_CANCEL,
+			       GTK_RESPONSE_CANCEL);
+	gtk_dialog_add_button (GTK_DIALOG (pd->dialog),
+			       _("Add To Panel"),
+			       GTK_RESPONSE_OK);
+	gtk_dialog_add_button (GTK_DIALOG (pd->dialog),
+			       GTK_STOCK_HELP,
+			       GTK_RESPONSE_HELP);
+
+	gtk_widget_show_all (pd->dialog);
+}
+
 static void
 make_panel_submenu (PanelWidget *panel_widget,
 		    GtkWidget   *menu)
 {
-	Bonobo_ServerInfoList *applet_list;
-	GtkWidget             *menuitem, *submenu;
+	GtkWidget             *menuitem;
 
 	if ( ! panel_toplevel_get_locked_down (panel_widget->toplevel)) {
@@ -2995,21 +3328,7 @@
 				FALSE);
 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-
-		submenu = menu_new ();
-		gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem),
-					   submenu);
-
-		applet_list = instrument_add_submenu_for_reload (GTK_MENU_ITEM (menuitem), submenu);
-
-		if ( ! panel_profile_list_is_writable (PANEL_GCONF_APPLETS) &&
-		     ! panel_profile_list_is_writable (PANEL_GCONF_OBJECTS)) {
-			/* if we can't write neither applets nor objects, just
-			   completely ignore this and make the whole submenu
-			   insensitive */
-			gtk_widget_set_sensitive (menuitem, FALSE);
-		} else {
-			make_add_submenu (submenu, applet_list);
-		}
-
+	        g_signal_connect (G_OBJECT (menuitem), "activate",
+		      	       	  G_CALLBACK (add_to_panel_cb), panel_widget);
+	
 		menuitem = gtk_image_menu_item_new ();
 
@@ -3138,68 +3457,4 @@
 
 	ask_about_launcher (NULL, panel_widget, insertion_pos, FALSE);
-}
-
-static void
-make_add_submenu (GtkWidget             *menu,
-		  Bonobo_ServerInfoList *applet_list)
-{
-	GtkWidget *menuitem, *m;
-	gboolean objects_writable;
-
-	objects_writable = panel_profile_list_is_writable (PANEL_GCONF_OBJECTS);
-
-	/* Add Menu */
-
-	create_applets_menu (menu, applet_list);
-
-	if ( ! panel_profile_get_inhibit_command_line ()) {
-		menuitem = gtk_image_menu_item_new ();
-		setup_stock_menu_item (
-				       menuitem, GTK_ICON_SIZE_MENU, PANEL_STOCK_LAUNCHER, _("Launcher..."), TRUE);
-		gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-		g_signal_connect (G_OBJECT(menuitem), "activate",
-				  G_CALLBACK(ask_about_launcher_cb),NULL);
-		setup_internal_applet_drag(menuitem, "LAUNCHER:ASK");
-		gtk_widget_set_sensitive (menuitem, objects_writable);
-	}
-
-	menuitem = gtk_image_menu_item_new ();
-	setup_stock_menu_item (
-		menuitem, GTK_ICON_SIZE_MENU, PANEL_STOCK_LAUNCHER, _("Launcher from menu"), TRUE);
-	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-	m = create_add_launcher_menu (NULL, TRUE);
-	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), m);
-	g_signal_connect (G_OBJECT (m),"show",
-			  G_CALLBACK (submenu_to_display), NULL);
-	gtk_widget_set_sensitive (menuitem, objects_writable);
-
-  	menuitem = gtk_image_menu_item_new ();
-	setup_stock_menu_item (
-		menuitem, GTK_ICON_SIZE_MENU, PANEL_STOCK_MAIN_MENU, _("Main Menu"), TRUE);
-	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-	g_signal_connect (G_OBJECT(menuitem), "activate",
-			   G_CALLBACK(add_menu_to_panel),
-			   NULL);
-	setup_internal_applet_drag(menuitem, "MENU:MAIN");
-	gtk_widget_set_sensitive (menuitem, objects_writable);
-
-	menuitem = gtk_image_menu_item_new ();
-	setup_stock_menu_item (
-		menuitem, GTK_ICON_SIZE_MENU, PANEL_STOCK_GNOME_LOGO, _("Menu Bar"), TRUE);
-	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-	g_signal_connect (menuitem, "activate",
-			  G_CALLBACK (add_menu_bar_to_panel), NULL);
-	setup_internal_applet_drag (menuitem, "MENUBAR:NEW");
-	gtk_widget_set_sensitive (menuitem, objects_writable);
-
-	menuitem = gtk_image_menu_item_new ();
-	setup_stock_menu_item (
-		menuitem, GTK_ICON_SIZE_MENU, PANEL_STOCK_DRAWER, _("Drawer"), TRUE);
-	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-	g_signal_connect (G_OBJECT(menuitem), "activate",
-			   (GtkSignalFunc) add_drawer_to_panel,
-			   NULL);
-	setup_internal_applet_drag(menuitem, "DRAWER:NEW");
-	gtk_widget_set_sensitive (menuitem, objects_writable);
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]