? INSTALL
? depcomp
? eel-2.0-uninstalled.pc
? install-sh
? missing
? mkinstalldirs
? stamp-h1
? eel/eel-accessibility.lo
? eel/eel-alert-dialog.lo
? eel/eel-art-extensions.lo
? eel/eel-art-gtk-extensions.lo
? eel/eel-background-box.lo
? eel/eel-background.lo
? eel/eel-canvas-rect-ellipse.lo
? eel/eel-canvas-util.lo
? eel/eel-canvas.lo
? eel/eel-cell-renderer-pixbuf-list.lo
? eel/eel-dateedit-extensions.lo
? eel/eel-debug-drawing.lo
? eel/eel-debug.lo
? eel/eel-editable-label.lo
? eel/eel-ellipsizing-label.lo
? eel/eel-enumeration.lo
? eel/eel-features.lo
? eel/eel-gconf-extensions.lo
? eel/eel-gdk-extensions.lo
? eel/eel-gdk-pixbuf-extensions.lo
? eel/eel-glib-extensions.lo
? eel/eel-gnome-extensions.lo
? eel/eel-graphic-effects.lo
? eel/eel-gtk-container.lo
? eel/eel-gtk-extensions.lo
? eel/eel-i18n.lo
? eel/eel-image-table.lo
? eel/eel-labeled-image.lo
? eel/eel-lib-self-check-functions.lo
? eel/eel-mime-application-chooser.lo
? eel/eel-mime-extensions.lo
? eel/eel-open-with-dialog.lo
? eel/eel-pango-extensions.lo
? eel/eel-preferences-glade.lo
? eel/eel-preferences.lo
? eel/eel-self-checks.lo
? eel/eel-stock-dialogs.lo
? eel/eel-string-list.lo
? eel/eel-string.lo
? eel/eel-types.lo
? eel/eel-vfs-extensions.lo
? eel/eel-wrap-table.lo
? eel/eel-xml-extensions.lo
? eel/libeel-2.la
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/eel/ChangeLog,v
retrieving revision 1.736
diff -u -u -r1.736 ChangeLog
--- ChangeLog	14 Nov 2005 17:03:39 -0000	1.736
+++ ChangeLog	30 Nov 2005 09:25:28 -0000
@@ -1,3 +1,15 @@
+2005-11-30  Luca Cavalli  <loopback@slackit.org>
+
+	* eel/eel-open-with-dialog.c: (eel_open_with_dialog_finalize),
+	(eel_open_with_dialog_add_icon_idle), (compare_menu_entries),
+	(get_all_applications_from_dir), (get_all_applications),
+	(get_all_directories), (eel_open_with_dialog_add_items_idle),
+	(program_tree_selection_is_directory),
+	(program_tree_selection_changed),
+	(program_tree_selection_activated), (expander_toggled),
+	(eel_open_with_dialog_instance_init): Show applications list in
+	'Open With' dialog using a tree instead of a list. (#322816)
+
 2005-11-14  Alexander Larsson  <alexl@redhat.com>
 
 	* configure.in:
Index: eel/eel-open-with-dialog.c
===================================================================
RCS file: /cvs/gnome/eel/eel/eel-open-with-dialog.c,v
retrieving revision 1.17
diff -u -u -r1.17 eel-open-with-dialog.c
--- eel/eel-open-with-dialog.c	27 Oct 2005 15:03:37 -0000	1.17
+++ eel/eel-open-with-dialog.c	30 Nov 2005 09:25:30 -0000
@@ -30,6 +30,7 @@
 #include "eel-stock-dialogs.h"
 
 #include <string.h>
+#include <glib.h>
 #include <glib/gi18n-lib.h>
 #include <gtk/gtkalignment.h>
 #include <gtk/gtkbox.h>
@@ -44,6 +45,7 @@
 #include <gtk/gtklabel.h>
 #include <gtk/gtkscrolledwindow.h>
 #include <gtk/gtkstock.h>
+#include <gtk/gtktreestore.h>
 #include <gtk/gtktreeview.h>
 #include <gtk/gtktreeselection.h>
 #include <gtk/gtkcellrenderertext.h>
@@ -75,8 +77,9 @@
 
 	GtkWidget *open_label;
 
-	GtkWidget     *program_list;
-	GtkListStore  *program_list_store;
+	GtkWidget     *program_tree;
+	GtkTreeStore  *program_tree_store;
+	GHashTable    *directories_hash_table;
 	GSList	      *add_icon_paths;
 	gint	       add_items_idle_id;
 	gint	       add_icons_idle_id;
@@ -118,7 +121,11 @@
 	if (dialog->details->add_items_idle_id) {
 		g_source_remove (dialog->details->add_items_idle_id);
 	}
-	
+
+	if (dialog->details->directories_hash_table) {
+		g_hash_table_destroy (dialog->details->directories_hash_table);
+	}
+
 	g_free (dialog->details->uri);
 	g_free (dialog->details->mime_type);
 	g_free (dialog->details->mime_description);
@@ -461,7 +468,7 @@
 		dialog->details->add_icon_paths = g_slist_delete_link (dialog->details->add_icon_paths,
 								       dialog->details->add_icon_paths);
 
-		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (dialog->details->program_list_store),
+		if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (dialog->details->program_tree_store),
 					      &iter, path)) {
 			gtk_tree_path_free (path);
 			continue;
@@ -469,7 +476,7 @@
 		
 		gtk_tree_path_free (path);
 
-		gtk_tree_model_get (GTK_TREE_MODEL (dialog->details->program_list_store), &iter,
+		gtk_tree_model_get (GTK_TREE_MODEL (dialog->details->program_tree_store), &iter,
 				    COLUMN_ICON_FILE, &file, -1);
 
 		if (file == NULL) {
@@ -497,7 +504,7 @@
 			long_operation = TRUE;
 		}
 		if (pixbuf) {
-			gtk_list_store_set (dialog->details->program_list_store, &iter, COLUMN_ICON, pixbuf, -1);
+			gtk_tree_store_set (dialog->details->program_tree_store, &iter, COLUMN_ICON, pixbuf, -1);
 			g_object_unref (pixbuf);
 		}
 		g_free (file);
@@ -509,7 +516,7 @@
 }
 
 static int
-compare_applications (GMenuTreeEntry *a,
+compare_menu_entries (GMenuTreeEntry *a,
 		      GMenuTreeEntry *b)
 {
 	return g_utf8_collate (gmenu_tree_entry_get_name (a),
@@ -531,7 +538,6 @@
 		switch (gmenu_tree_item_get_type (item)) {
 			case GMENU_TREE_ITEM_DIRECTORY:
 				list = get_all_applications_from_dir (GMENU_TREE_DIRECTORY (item), list);
-				gmenu_tree_item_unref (item);
 				break;
 
 			case GMENU_TREE_ITEM_ENTRY:
@@ -548,7 +554,6 @@
 	return list;
 }
 
-
 static GSList *
 get_all_applications (void)
 {
@@ -566,23 +571,67 @@
 	gmenu_tree_unref (tree);
 
 	retval = g_slist_sort (retval,
-			       (GCompareFunc) compare_applications);
+			       (GCompareFunc) compare_menu_entries);
 
 	return retval;
 }
 
+static GSList *
+get_all_directories (void)
+{
+	GMenuTree          *tree;
+	GMenuTreeDirectory *root;
+	GSList             *retval = NULL;
+        GSList             *contents;
+        GSList             *l;
+
+	tree = gmenu_tree_lookup ("applications.menu", GMENU_TREE_FLAGS_NONE);
+
+	root = gmenu_tree_get_root_directory (tree);
+
+	contents = gmenu_tree_directory_get_contents (root);
+
+	for (l = contents; l; l = l->next) {
+		GMenuTreeItem *item = l->data;
+
+		switch (gmenu_tree_item_get_type (item)) {
+			case GMENU_TREE_ITEM_DIRECTORY:
+				retval = g_slist_prepend (retval, item);
+				break;
+
+		default:
+			break;
+		}
+	}
+
+	g_slist_free (contents);
+
+	gmenu_tree_item_unref (root);
+	gmenu_tree_unref (tree);
+
+	retval = g_slist_sort (retval,
+			       (GCompareFunc) compare_menu_entries);
+
+	return retval;
+}
 
 static gboolean
 eel_open_with_dialog_add_items_idle (EelOpenWithDialog *dialog)
 {
 	GtkCellRenderer   *renderer;
 	GtkTreeViewColumn *column;
+	GSList            *all_directories;
 	GSList            *all_applications;
 	GSList            *l;
 	const char        *prev_name;
 
+	dialog->details->directories_hash_table = g_hash_table_new_full (g_str_hash,
+									 g_str_equal,
+									 g_free,
+									 g_free);
+
 	/* create list store */
-	dialog->details->program_list_store = gtk_list_store_new (NUM_COLUMNS,
+	dialog->details->program_tree_store = gtk_tree_store_new (NUM_COLUMNS,
 								  GDK_TYPE_PIXBUF,
 								  G_TYPE_STRING,
 								  G_TYPE_STRING,
@@ -590,21 +639,63 @@
 								  G_TYPE_STRING,
 								  G_TYPE_STRING);
 
+	all_directories = get_all_directories ();
+
+	prev_name = NULL;
+	for (l = all_directories; l; l = l->next) {
+		GMenuTreeDirectory *dir = l->data;
+		GtkTreeIter         iter;
+		GtkTreePath        *path;
+
+		if (prev_name && strcmp (gmenu_tree_directory_get_name (dir), prev_name) == 0) {
+			gmenu_tree_item_unref (GMENU_TREE_ITEM (dir));
+			continue;
+		}
+
+		gtk_tree_store_append (dialog->details->program_tree_store, &iter, NULL);
+		gtk_tree_store_set (dialog->details->program_tree_store, &iter,
+				    COLUMN_ICON,      NULL,
+				    COLUMN_ICON_FILE, gmenu_tree_directory_get_icon (dir),
+				    COLUMN_NAME,      gmenu_tree_directory_get_name (dir),
+				    COLUMN_COMMENT,   gmenu_tree_directory_get_comment (dir),
+				    COLUMN_PATH,      gmenu_tree_entry_get_desktop_file_path (GMENU_TREE_ENTRY (dir)),
+				    -1);
+
+		path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->details->program_tree_store), &iter);
+		if (path != NULL) {
+			dialog->details->add_icon_paths = g_slist_prepend (dialog->details->add_icon_paths, path);
+
+			g_hash_table_insert (dialog->details->directories_hash_table,
+					     g_strdup (gmenu_tree_directory_get_name (dir)),
+					     gtk_tree_path_to_string (path));
+		}
+
+		prev_name = gmenu_tree_directory_get_name (dir);
+		gmenu_tree_item_unref (GMENU_TREE_ITEM (dir));
+	}
+	g_slist_free (all_directories);
+
 	all_applications = get_all_applications ();
 	
 	prev_name = NULL;
 	for (l = all_applications; l; l = l->next) {
 		GMenuTreeEntry *entry = l->data;
-		GtkTreeIter     iter;
+		GtkTreeIter     parent, iter;
 		GtkTreePath    *path;
+		const char     *path_str, *key;
 
 		if (prev_name && strcmp (gmenu_tree_entry_get_name (entry), prev_name) == 0) {
-			gmenu_tree_item_unref (entry);
+			gmenu_tree_item_unref (GMENU_TREE_ITEM (entry));
 			continue;
 		}
 
-		gtk_list_store_append (dialog->details->program_list_store, &iter);
-		gtk_list_store_set (dialog->details->program_list_store, &iter,
+		key = gmenu_tree_directory_get_name (gmenu_tree_item_get_parent (GMENU_TREE_ITEM (entry)));
+		path_str = g_hash_table_lookup (dialog->details->directories_hash_table, key);
+		gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dialog->details->program_tree_store),
+                                                     &parent, path_str);
+
+		gtk_tree_store_append (dialog->details->program_tree_store, &iter, &parent);
+		gtk_tree_store_set (dialog->details->program_tree_store, &iter,
 				    COLUMN_ICON,      NULL,
 				    COLUMN_ICON_FILE, gmenu_tree_entry_get_icon (entry),
 				    COLUMN_NAME,      gmenu_tree_entry_get_name (entry),
@@ -612,18 +703,18 @@
 				    COLUMN_PATH,      gmenu_tree_entry_get_desktop_file_path (entry),
 				    -1);
 
-		path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->details->program_list_store), &iter);
+		path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->details->program_tree_store), &iter);
 		if (path != NULL) {
 			dialog->details->add_icon_paths = g_slist_prepend (dialog->details->add_icon_paths, path);
 		}
 
 		prev_name = gmenu_tree_entry_get_name (entry);
-		gmenu_tree_item_unref (entry);
+		gmenu_tree_item_unref (GMENU_TREE_ITEM (entry));
 	}
 	g_slist_free (all_applications);
 
-	gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->details->program_list), 
-				 GTK_TREE_MODEL (dialog->details->program_list_store));
+	gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->details->program_tree), 
+				 GTK_TREE_MODEL (dialog->details->program_tree_store));
 
 	renderer = gtk_cell_renderer_pixbuf_new ();
 	column = gtk_tree_view_column_new ();
@@ -638,7 +729,7 @@
                                              "text", COLUMN_NAME,
                                              NULL);
 					          
-	gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->details->program_list), column);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->details->program_tree), column);
 
 	dialog->details->add_icon_paths = g_slist_reverse (dialog->details->add_icon_paths);
 
@@ -692,8 +783,48 @@
 	return retval;
 }
 
+static gboolean
+program_tree_selection_is_directory (GtkTreeSelection  *selection)
+{
+	GtkTreeModel     *model;
+	GtkTreeIter       iter;
+	char             *path, *type;
+	GKeyFile         *keyfile;
+	gboolean          res;
+
+	if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+		return TRUE;
+	}
+
+	path = NULL;
+	gtk_tree_model_get (model, &iter,
+			    COLUMN_PATH, &path,
+			    -1);
+				  
+	if (path == NULL)
+		return TRUE;
+
+	keyfile = g_key_file_new ();
+	if (!g_key_file_load_from_file (keyfile, path, 0, NULL)) {
+		g_free (path);
+		g_key_file_free (keyfile);
+		return TRUE;
+	}
+
+	type =  g_key_file_get_string (keyfile, DESKTOP_ENTRY_GROUP,
+				       GNOME_DESKTOP_ITEM_TYPE, NULL);
+	if (strcmp (type, "Directory") == 0)
+		res = TRUE;
+	else
+		res = FALSE;
+
+	g_free (type);
+
+	return res;
+}
+
 static void
-program_list_selection_changed (GtkTreeSelection  *selection,
+program_tree_selection_changed (GtkTreeSelection  *selection,
 				EelOpenWithDialog *dialog)
 {
 	GtkTreeModel     *model;
@@ -740,7 +871,11 @@
 					     GNOME_DESKTOP_ITEM_COMMENT, NULL, NULL);
 	gtk_label_set_text (GTK_LABEL (dialog->details->desc_label), sure_string (temp));
 	g_free (temp);
-	gtk_widget_set_sensitive (dialog->details->button, TRUE);
+
+	if (program_tree_selection_is_directory (selection))
+		gtk_widget_set_sensitive (dialog->details->button, FALSE);
+	else
+		gtk_widget_set_sensitive (dialog->details->button, TRUE);
 
 	g_free (dialog->details->desktop_file);
 	dialog->details->desktop_file = g_strdup (path);
@@ -750,7 +885,7 @@
 }
 
 static void
-program_list_selection_activated (GtkTreeView       *view,
+program_tree_selection_activated (GtkTreeView       *view,
 				  GtkTreePath       *path,
 				  GtkTreeViewColumn *column,
 				  EelOpenWithDialog *dialog)
@@ -758,10 +893,17 @@
 	GtkTreeSelection *selection;
 
 	/* update the entry with the info from the selection */
-	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->details->program_list));	
-	program_list_selection_changed (selection, dialog);
-	
-	gtk_dialog_response (GTK_DIALOG (&dialog->parent), RESPONSE_OPEN);
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->details->program_tree));	
+	program_tree_selection_changed (selection, dialog);
+
+	if (program_tree_selection_is_directory (selection)) {
+		if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (dialog->details->program_tree), path))
+			gtk_tree_view_collapse_row (GTK_TREE_VIEW (dialog->details->program_tree), path);
+		else
+			gtk_tree_view_expand_row (GTK_TREE_VIEW (dialog->details->program_tree),
+						  path, FALSE);
+	} else
+		gtk_dialog_response (GTK_DIALOG (&dialog->parent), RESPONSE_OPEN);
 }
 
 static void
@@ -774,9 +916,9 @@
 	else {
 		GtkTreeSelection *selection;
 
-		gtk_widget_grab_focus (dialog->details->program_list);
-		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->details->program_list));
-		program_list_selection_changed (selection, dialog);
+		gtk_widget_grab_focus (dialog->details->program_tree);
+		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->details->program_tree));
+		program_tree_selection_changed (selection, dialog);
 	}
 }
 
@@ -818,10 +960,10 @@
 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
 					GTK_POLICY_AUTOMATIC,
 					GTK_POLICY_AUTOMATIC);
-	dialog->details->program_list = gtk_tree_view_new ();
-	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dialog->details->program_list),
+	dialog->details->program_tree = gtk_tree_view_new ();
+	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dialog->details->program_tree),
 					   FALSE);
-	gtk_container_add (GTK_CONTAINER (scrolled_window), dialog->details->program_list);
+	gtk_container_add (GTK_CONTAINER (scrolled_window), dialog->details->program_tree);
 	
 	gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
 
@@ -832,13 +974,13 @@
 	gtk_label_set_single_line_mode (GTK_LABEL (dialog->details->desc_label), FALSE);
 	gtk_box_pack_start (GTK_BOX (vbox), dialog->details->desc_label, FALSE, FALSE, 0);
 	
-	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->details->program_list));
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->details->program_tree));
 	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
 	g_signal_connect (selection, "changed",
-			  G_CALLBACK (program_list_selection_changed),
+			  G_CALLBACK (program_tree_selection_changed),
 			  dialog);
-	g_signal_connect (dialog->details->program_list, "row-activated",
-			  G_CALLBACK (program_list_selection_activated),
+	g_signal_connect (dialog->details->program_tree, "row-activated",
+			  G_CALLBACK (program_tree_selection_activated),
 			  dialog);
 
 	dialog->details->add_items_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
