Index: gnome-cups-manager/gnome-printer-list.c
===================================================================
RCS file: /cvs/gnome/gnome-cups-manager/gnome-cups-manager/gnome-printer-list.c,v
retrieving revision 1.13
diff -p -u -B -r1.13 gnome-printer-list.c
--- gnome-cups-manager/gnome-printer-list.c	28 Feb 2005 19:05:22 -0000	1.13
+++ gnome-cups-manager/gnome-printer-list.c	14 Dec 2006 01:15:55 -0000
@@ -29,24 +29,35 @@
 #include "printer-properties.h"
 #include "view-queue.h"
 
+#include <glib.h>
+#include <glib/gi18n.h>
 #include <gtk/gtkmenu.h>
 #include <gtk/gtkimagemenuitem.h>
 #include <gtk/gtkseparatormenuitem.h>
 #include <gtk/gtkstock.h>
 #include <gtk/gtkicontheme.h>
-#include <glib.h>
-#include <glib/gi18n.h>
+#include <gtk/gtksettings.h>
+#include <gtk/gtkliststore.h>
+#include <gtk/gtktreemodel.h>
+#include <gtk/gtktreesortable.h>
+#include <gtk/gtktreemodelsort.h>
+#include <gtk/gtkcellrenderer.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkcellrendererpixbuf.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkiconfactory.h>
+#include <gtk/gtkmain.h>
 
 #include <libgnomecups/gnome-cups-printer.h>
 #include <libgnomecups/gnome-cups-ui-util.h>
 #include <libgnomecups/gnome-cups-permission.h>
 
 struct _GnomePrinterListDetails {
-	EggIconListItem *add_item;
+	GtkTreeModel *model;
+	GtkListStore *store;
 
-	GList *printers;
-	
-	guint new_printer_notify;
+	guint printer_added_id;
+	guint printer_removed_id;
 };
 
 /* Tool to help debug lifecycle */
@@ -58,140 +69,338 @@ struct _GnomePrinterListDetails {
 
 static void disconnect_printer (GnomePrinterList *list, GnomeCupsPrinter *printer);
 
-G_DEFINE_TYPE (GnomePrinterList, gnome_printer_list, egg_icon_list_get_type ())
-
-static GdkPixbuf *
-load_icon (GtkWidget *w, char const *icon_name)
-{
-	GError *err = NULL;
-	GdkPixbuf *res = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
-		icon_name, 48, 0, NULL);
-
-	if (res == NULL) {
-		if (err != NULL) {
-			g_warning ("%s", err->message);
-			g_error_free (err);
-			err = NULL;
-		}
-		res = gtk_widget_render_icon (w, icon_name, GTK_ICON_SIZE_DIALOG, NULL);
-
-		if (err != NULL) {
-			g_warning ("%s", err->message);
-			g_error_free (err);
-			return NULL;
-		}
-	}
-
-	return res;
-}
+G_DEFINE_TYPE (GnomePrinterList, gnome_printer_list, GTK_TYPE_ICON_VIEW);
 
 static void
-add_new_printer_icon (GnomePrinterList *list)
-{
-	EggIconListItem *item;
-	GdkPixbuf *pixbuf = load_icon (GTK_WIDGET (list), "gnome-dev-printer-new");
-	if (pixbuf == NULL)
-		pixbuf = load_icon (GTK_WIDGET (list), GTK_STOCK_PRINT);
-
-	item = egg_icon_list_item_new (pixbuf, _("New Printer"));
-	list->details->add_item = item;
-
-	g_object_unref (pixbuf);
-
-	egg_icon_list_append_item (EGG_ICON_LIST (list), item);
-}
-
-static GdkPixbuf *
-get_printer_icon (GtkWidget *list, GnomeCupsPrinter *printer)
+printer_get_pixbuf_func (GtkCellLayout *cell_layout,
+			 GtkCellRenderer *cell,
+			 GtkTreeModel *model,
+			 GtkTreeIter *iter,
+			 gpointer data)
 {
-	char *icon_name;
-	GList *ptr, *emblems;
-	GdkPixbuf *pixbuf, *emblem;
-	GError *err = NULL;
+	GtkWidget *widget;
+	GnomeCupsPrinter *printer = NULL;
+	GdkPixbuf *pixbuf;
+	GtkIconTheme *icon_theme;
+	char *icon_name = NULL;
+	GList *ptr, *emblems = NULL;
+	int width, height;
+
+	gtk_tree_model_get (model,
+			    iter,
+			    (int) 0, &printer,
+			    (int) -1);
+
+	d(g_print ("Getting pixbuf for printer %s\n", printer ? gnome_cups_printer_get_name (printer) : "NEW-PRINTER"););
+
+	if (printer == NULL) {
+		g_object_set (cell,
+			      "pixbuf", NULL,
+			      "icon-name", "gnome-dev-printer-new",
+			      NULL);
+		return;
+	}
 
 	gnome_cups_printer_get_icon (printer,
 				     &icon_name,
 				     &emblems);
-	pixbuf = load_icon (GTK_WIDGET (list), icon_name);
+
+	widget = GTK_WIDGET (cell_layout);
+	gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (widget),
+					   GTK_ICON_SIZE_DIALOG,
+					   &width, &height);
+
+	icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
+
+	pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name, width, 0, NULL);
 	g_free (icon_name);
-	if (pixbuf == NULL)
-		pixbuf = load_icon (GTK_WIDGET (list), GTK_STOCK_PRINT);
+
+	/* FIXME: is this fallback really necessary? */
+	if (!pixbuf) {
+		pixbuf = gtk_widget_render_icon (widget,
+						 GTK_STOCK_PRINT,
+						 GTK_ICON_SIZE_DIALOG,
+						 NULL);
+	}
 
 	for (ptr = emblems; ptr != NULL; ptr = ptr->next) {
-		if (ptr->data == NULL)
+		const char *emblem_name = (const char *) ptr->data;
+		GdkPixbuf *emblem;
+
+		/* FIXME: can that really happen? Not according to the gnome_cups_printer_get_icon code in libgnomecups! */
+		if (!emblem_name)
 			continue;
-		emblem = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
-			ptr->data, 48, 0, &err);
-		if (emblem == NULL) {
-			g_warning ("unable to load emblem '%s'", (char *)ptr->data);
-			if (err != NULL) {
-				g_warning ("%s", err->message);
-				g_error_free (err);
-				err = NULL;
-			}
-		} else {
-			GdkPixbuf *res = gdk_pixbuf_copy (pixbuf);
-			gdk_pixbuf_composite (emblem,  res, 0, 0, 
-				gdk_pixbuf_get_width (res), gdk_pixbuf_get_height (res), 
-				0., 0., 1., 1., GDK_INTERP_NEAREST, 255);
+
+		emblem = gtk_icon_theme_load_icon (icon_theme, emblem_name,
+						   width, 0, NULL);
+		if (emblem != NULL) {
+			GdkPixbuf *copy;
+
+			copy = gdk_pixbuf_copy (pixbuf);
+
+			gdk_pixbuf_composite (emblem, copy,
+					      0, 0,
+					      gdk_pixbuf_get_width (copy),
+					      gdk_pixbuf_get_height (copy),
+					      0., 0., 1., 1.,
+					      GDK_INTERP_NEAREST, 255);
+			g_object_unref (emblem);
 			g_object_unref (pixbuf);
-			pixbuf = res;
+
+			pixbuf = copy;
 		}
 	}
+	g_list_foreach (emblems, (GFunc) g_free, NULL);
+	g_list_free (emblems);
+
+	g_object_set (cell,
+		      "icon-name", NULL,
+		      "pixbuf", pixbuf,
+		      NULL);
+	if (pixbuf) {
+		g_object_unref (pixbuf);
+	}
 
-	return pixbuf;
+	g_object_unref (printer);
 }
 
-static char *
-get_printer_label (GnomeCupsPrinter *printer)
-{
-	char const *name  = gnome_cups_printer_get_name (printer);
-	char const *state = gnome_cups_printer_get_state_name (printer);
-	int jobs = gnome_cups_printer_get_job_count (printer);
+static void
+printer_get_text_func (GtkCellLayout *cell_layout,
+		       GtkCellRenderer *cell,
+		       GtkTreeModel *model,
+		       GtkTreeIter *iter,
+		       gpointer data)
+{
+	GnomeCupsPrinter *printer = NULL;
+	char *text;
+	char const *name, *state;
+	int jobs;
+
+	gtk_tree_model_get (model,
+			    iter,
+			    (int) 0, &printer,
+			    (int) -1);
+
+	d(g_print ("Getting label for printer %s\n", printer ? gnome_cups_printer_get_name (printer) : "NEW-PRINTER"););
+
+	if (printer == NULL) {
+		g_object_set (cell,
+			      "text", _("New Printer"),
+			      NULL);
+		return;
+	}
+
+	name = gnome_cups_printer_get_name (printer);
+	state = gnome_cups_printer_get_state_name (printer);
+	jobs = gnome_cups_printer_get_job_count (printer);
 
 	/* FIXME: hard-coded additional text color */
 	if (jobs > 0) {
-		return g_strdup_printf ("%s\n<span color=\"#337F33\">%s\n%d Jobs</span>",
-			name, state, jobs);
+		char *jobs_text;
+
+		jobs_text = g_strdup_printf (ngettext ("%d Job", "%d Jobs", jobs), jobs);
+		text = g_strdup_printf ("%s\n<span color=\"#337F33\">%s\n%s</span>",
+					name, state, jobs_text);
+		g_free (jobs_text);
 	} else {
-		return g_strdup_printf ("%s\n<span color=\"#33337F\">%s\n</span>",
-			name, state);
+		text = g_strdup_printf ("%s\n<span color=\"#33337F\">%s\n</span>",
+					name, state);
 	}
+
+	g_object_set (cell,
+		      "markup", text,
+		      NULL);
+	g_free (text);
+
+	g_object_unref (printer);
 }
 
-static EggIconListItem *
-create_printer_item (GtkWidget *list, GnomeCupsPrinter *printer)
-{
-	EggIconListItem *item;
-	GdkPixbuf *pixbuf;
-	char *label;
-	
-	pixbuf = get_printer_icon (list, printer);
-	label = get_printer_label (printer);
-	
-	item = egg_icon_list_item_new (pixbuf, label);
+static void
+printer_activated_cb (GtkIconView *icon_view,
+		      GtkTreePath *path,
+		      GnomePrinterList *list)
+{
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
+	GnomeCupsPrinter *printer = NULL;
 
-	egg_icon_list_item_set_data (item, printer);
+	if (!gtk_tree_model_get_iter (details->model, &iter, path))
+		return;
 
-	g_object_unref (pixbuf);
-	g_free (label);
+	gtk_tree_model_get (details->model,
+			    &iter,
+			    (int) 0, &printer,
+			    (int) -1);
 
-	return item;
+	if (printer == NULL) {
+		gnome_printer_list_new_printer (list);
+	} else {
+		gnome_cups_manager_view_queue (printer);
+		g_object_unref (printer);
+	}
 }
 
 static void
-printer_activated_cb (GnomePrinterList *list,
-		      GnomeCupsPrinter *printer)
-{	
-	gnome_cups_manager_view_queue (printer);
+printer_pause_cb (GtkIconView *icon_view,
+		  GtkTreePath *path,
+		  GnomePrinterList *list)
+{
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
+	GnomeCupsPrinter *printer = NULL;
+	GError *error = NULL;
+
+	if (!gtk_tree_model_get_iter (details->model, &iter, path))
+		return;
+
+	gtk_tree_model_get (details->model,
+			    &iter,
+			    (int) 0, &printer,
+			    (int) -1);
+
+	if (printer == NULL)
+		return;
+
+	gnome_cups_printer_pause (printer, &error);
+	if (error) {
+		char *msg;
+		/* FIXME i18n! */
+		msg = g_strdup_printf ("Could not pause '%s'",
+				       gnome_cups_printer_get_name (printer));
+		gnome_cups_error_dialog (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (list))), msg, error);
+		g_free (msg);
+		g_error_free (error);
+	}
+
+	g_object_unref (printer);
 }
 
 static void
-item_activated_cb (GnomePrinterList *list,
-		   EggIconListItem *item,
-		   gpointer user_data)
-{
-	gnome_printer_list_selection_activate (list);
+printer_resume_cb (GtkIconView *icon_view,
+		  GtkTreePath *path,
+		  GnomePrinterList *list)
+{
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
+	GnomeCupsPrinter *printer = NULL;
+	GError *error = NULL;
+
+	if (!gtk_tree_model_get_iter (details->model, &iter, path))
+		return;
+
+	gtk_tree_model_get (details->model,
+			    &iter,
+			    (int) 0, &printer,
+			    (int) -1);
+
+	if (printer == NULL)
+		return;
+
+	gnome_cups_printer_resume (printer, &error);
+	if (error) {
+		char *msg;
+		/* FIXME i18n! */
+		msg = g_strdup_printf ("Could not resume '%s'",
+				       gnome_cups_printer_get_name (printer));
+		gnome_cups_error_dialog (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (list))), msg, error);
+		g_free (msg);
+		g_error_free (error);
+	}
+
+	g_object_unref (printer);
+}
+
+static void
+printer_set_default_cb (GtkIconView *icon_view,
+			GtkTreePath *path,
+			GnomePrinterList *list)
+{
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
+	GnomeCupsPrinter *printer = NULL;
+	GError *error = NULL;
+
+	if (!gtk_tree_model_get_iter (details->model, &iter, path))
+		return;
+
+	gtk_tree_model_get (details->model,
+			    &iter,
+			    (int) 0, &printer,
+			    (int) -1);
+
+	if (printer == NULL)
+		return;
+
+        gnome_cups_printer_set_default (printer, &error);
+	if (error) {
+		char *msg;
+		/* FIXME i18n! */
+                msg = g_strdup_printf ("Could not make '%s' the default printer", 
+                                       gnome_cups_printer_get_name (printer));
+		gnome_cups_error_dialog (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (list))), msg, error);
+		g_free (msg);
+		g_error_free (error);
+	}
+
+	g_object_unref (printer);
+}
+	
+static void
+printer_properties_cb (GtkIconView *icon_view,
+		       GtkTreePath *path,
+		       GnomePrinterList *list)
+{
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
+	GnomeCupsPrinter *printer = NULL;
+
+	if (!gtk_tree_model_get_iter (details->model, &iter, path))
+		return;
+
+	gtk_tree_model_get (details->model,
+			    &iter,
+			    (int) 0, &printer,
+			    (int) -1);
+
+	if (printer == NULL)
+		return;
+
+	gnome_cups_manager_printer_properties (printer);
+
+	g_object_unref (printer);
+}
+
+static void
+printer_remove_cb (GtkIconView *icon_view,
+		   GtkTreePath *path,
+		   GnomePrinterList *list)
+{
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
+	GnomeCupsPrinter *printer = NULL;
+	GError *error = NULL;
+
+	if (!gtk_tree_model_get_iter (details->model, &iter, path))
+		return;
+
+	gtk_tree_model_get (details->model,
+			    &iter,
+			    (int) 0, &printer,
+			    (int) -1);
+
+	if (printer == NULL)
+		return;
+
+	gnome_cups_printer_delete (printer, &error);
+	if (error) {
+		char *msg;
+		/* FIXME: i18n! */
+		msg = g_strdup_printf ("Could not delete '%s'",
+					gnome_cups_printer_get_name (printer));
+		gnome_cups_error_dialog (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (list))), msg, error);
+		g_free (msg);
+		g_error_free (error);
+	}
 }
 
 static void
@@ -237,16 +446,20 @@ properties_activated_cb (GtkWidget *menu
 }
 
 /* This is so lame */
-void
-gnome_printer_list_get_command_sensitivities (GnomePrinterList *list,
-					      gboolean *activate,
-					      gboolean *pause,
-					      gboolean *resume,
-					      gboolean *make_default,
-					      gboolean *del,
-					      gboolean *properties,
-					      gboolean *status)
-{
+static void
+get_command_sensitivities (GnomePrinterList *list,
+			   gboolean *activate,
+			   gboolean *pause,
+			   gboolean *resume,
+			   gboolean *make_default,
+			   gboolean *del,
+			   gboolean *properties,
+			   gboolean *status,
+			   gboolean *new_selected)
+{
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
+	GnomeCupsPrinter *printer = NULL;
 	GList *l;
 	GList *selection;
 	int num_selected;
@@ -255,7 +468,7 @@ gnome_printer_list_get_command_sensitivi
 	gboolean has_default;
 	gboolean all_running;
 
-	selection = egg_icon_list_get_selected (EGG_ICON_LIST (list));
+	selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (list));
 	
 	num_selected = g_list_length (selection);
 
@@ -291,16 +504,19 @@ gnome_printer_list_get_command_sensitivi
 	has_default = FALSE;
 
 	for (l = selection; l != NULL; l = l->next) {
-		EggIconListItem *item;
-		
-		item = l->data;
-		
-		if (item == list->details->add_item) {
+		GtkTreePath *path = (GtkTreePath *) l->data;
+
+		if (!gtk_tree_model_get_iter (details->model, &iter, path))
+			return;
+
+		gtk_tree_model_get (details->model,
+					&iter,
+					(int) 0, &printer,
+					(int) -1);
+
+		if (printer == NULL) {
 			new_printer_selected = TRUE;
 		} else {
-			GnomeCupsPrinter *printer;
-
-			printer = GNOME_CUPS_PRINTER (egg_icon_list_item_get_data (item));
 			if (gnome_cups_printer_get_state (printer) == IPP_PRINTER_STOPPED) {
 				all_running = FALSE;
 			} else {
@@ -310,6 +526,8 @@ gnome_printer_list_get_command_sensitivi
 			if (gnome_cups_printer_get_is_default (printer)) {
 				has_default = TRUE;
 			}
+
+			g_object_unref (printer);
 		}
 	}
 	
@@ -341,15 +559,35 @@ gnome_printer_list_get_command_sensitivi
 		*status = !new_printer_selected;
 	}
 
+	if (new_selected) {
+		*new_selected = num_selected == 1 && new_printer_selected;
+	}
+
+	g_list_foreach (selection, (GFunc) gtk_tree_path_free, NULL);
 	g_list_free (selection);
 }
 
+/* This is so lame */
+void
+gnome_printer_list_get_command_sensitivities (GnomePrinterList *list,
+					      gboolean *activate,
+					      gboolean *pause,
+					      gboolean *resume,
+					      gboolean *make_default,
+					      gboolean *del,
+					      gboolean *properties,
+					      gboolean *status)
+{
+	get_command_sensitivities (list, activate, pause, resume,
+				  make_default, del, properties,
+				  status, NULL);
+}
+
 static GtkWidget *
 create_selection_menu (GnomePrinterList *list)
 {
 	GtkWidget *menu;
 	GtkWidget *item;
-	GList *selection;
 	gboolean activate;
 	gboolean pause;
 	gboolean resume;
@@ -357,19 +595,16 @@ create_selection_menu (GnomePrinterList 
 	gboolean del;
 	gboolean properties;
 	gboolean status;
+	gboolean new_selected;
 
-	gnome_printer_list_get_command_sensitivities (list,
+	get_command_sensitivities (list,
 		&activate, &pause, &resume, &make_default,
-		&del, &properties, &status);
+		&del, &properties, &status, &new_selected);
 	
-	selection = egg_icon_list_get_selected (EGG_ICON_LIST (list));
-
 	menu = gtk_menu_new ();
 	gtk_widget_show (menu);
 
-	if (g_list_length (selection) == 1 && selection->data == list->details->add_item) {
-		g_list_free (selection);
-
+	if (new_selected) {
 		item = gtk_image_menu_item_new_from_stock (GTK_STOCK_ADD, NULL);
 		gtk_widget_show (item);
 		g_signal_connect (item, "activate", 
@@ -379,7 +614,6 @@ create_selection_menu (GnomePrinterList 
 
 		return menu;
 	}
-	g_list_free (selection);
 
 	item = gtk_menu_item_new_with_label (_("Jobs"));
 	gtk_widget_show (item);
@@ -443,86 +677,127 @@ create_selection_menu (GnomePrinterList 
 	return menu;
 }
 
-static void
-context_menu_popup (GnomePrinterList *list,
-		    GdkEventButton *event)
+static gboolean
+button_press_cb (GnomePrinterList *list,
+		 GdkEventButton *event,
+		 gpointer data)
 {
+	GtkIconView *icon_view;
+	GtkTreePath *path;
 	GtkWidget *menu;
-	
+
+	if (event->button != 3 ||
+	    event->type != GDK_BUTTON_PRESS)
+		return FALSE;
+
+	icon_view = GTK_ICON_VIEW (list);
+	path = gtk_icon_view_get_path_at_pos (icon_view, event->x, event->y);
+	if (!path)
+		return FALSE;
+
+	if (!gtk_icon_view_path_is_selected (icon_view, path)) {
+		gtk_icon_view_select_path (icon_view, path);
+	}
+
+	gtk_tree_path_free (path);
+
 	menu = create_selection_menu (list);
+	gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+			NULL, NULL,
+			event->button, event->time);
 
-	gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, event->button, event->time);
+	return TRUE;
 }
 
 static gboolean
-button_press_event_cb (GnomePrinterList *list,
-		       GdkEventButton *event,
-		       gpointer user_data)
+popup_menu_cb (GnomePrinterList *list,
+	       gpointer data)
 {
-	if (event->button == 3) {
-		EggIconListItem *item;
-		
-		item = egg_icon_list_get_item_at_pos (EGG_ICON_LIST (list), 
-						      event->x, event->y);
-		if (!item) {
-			return FALSE;
-		}
+	GtkWidget *menu;
+
+	menu = create_selection_menu (list);
+	gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
+			/* FIXME: GtkIconView should provide a position_menu function!! */
+			NULL, NULL,
+			0, gtk_get_current_event_time ());
+
+	return TRUE;
+}
 
-		if (!egg_icon_list_item_is_selected (item)) {
-			egg_icon_list_unselect_all (EGG_ICON_LIST (list));
-			egg_icon_list_select_item (EGG_ICON_LIST (list),
-						   item);
+static gboolean
+get_row_for_printer (GtkTreeModel *model,
+		     GnomeCupsPrinter *printer,
+		     GtkTreeIter *_iter)
+{
+        GtkTreeIter iter;
+	gboolean retval = FALSE;
+
+        if (!gtk_tree_model_get_iter_first (model, &iter))
+		return FALSE;
+
+	do
+	{
+		GnomeCupsPrinter *data = NULL;
+
+		gtk_tree_model_get (model,
+				    &iter,
+				    (int) 0, &data,
+				    (int) -1);
+
+		if (data)
+			g_object_unref (data);
+
+		if (data == printer) {
+			*_iter = iter;
+			retval = TRUE;
+			break;
 		}
-		
-		context_menu_popup (list, event);
-		
-		return TRUE;
 	}
+	while (gtk_tree_model_iter_next (model, &iter));
 
-	return FALSE;
+	return retval;
 }
 
 static void
 printer_changed_cb (GnomeCupsPrinter *printer,
 		    GnomePrinterList *list)
 {
-	EggIconListItem *item;
-	GdkPixbuf *pixbuf;
-	char *label;
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
+	GtkTreePath *path;
 
-	d (g_warning ("changed %s", gnome_cups_printer_get_name (printer)););
+	d (g_print ("changed %s\n", gnome_cups_printer_get_name (printer)););
 
-	item = g_object_get_data (G_OBJECT (printer), "icon_item");
-	
-	pixbuf = get_printer_icon (GTK_WIDGET (list), printer);
-	label = get_printer_label (printer);
-	
-	egg_icon_list_item_set_icon (item, pixbuf);
-	egg_icon_list_item_set_label (item, label);
-
-	g_signal_emit_by_name (list, "selection_changed");
+	if (!get_row_for_printer (details->model, printer, &iter)) {
+		d (g_print ("Changed printer not in model!?\n"););
+		return;
+	}
 
-	g_object_unref (pixbuf);
-	g_free (label);
+	path = gtk_tree_model_get_path (details->model, &iter);
+	gtk_tree_model_row_changed (details->model, path, &iter);
+	gtk_tree_path_free (path);
 }
 
 static void
 printer_gone_cb (GnomeCupsPrinter *printer,
-		 gpointer user_data)
+		 GnomePrinterList *list)
 {
-	GnomePrinterList *list;
-	EggIconListItem *item;
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
 
-	d (g_warning ("removed %s", gnome_cups_printer_get_name (printer)););
+	d (g_print ("removed %s\n", gnome_cups_printer_get_name (printer)););
 
-	list = GNOME_PRINTER_LIST (user_data);
-	item = g_object_get_data (G_OBJECT (printer), "icon_item");
+	disconnect_printer (list, printer);
 
-	egg_icon_list_remove_item (EGG_ICON_LIST (list), item);
-	
-	list->details->printers = g_list_remove (list->details->printers, printer);
+	if (!get_row_for_printer (details->model, printer, &iter)) {
+		d (g_print ("Removed printer not in model!?\n"););
+		return;
+	}
 
-	disconnect_printer (list, printer);
+	gtk_list_store_remove (details->store, &iter);
+
+	// FIXMEchpe?
+	//g_object_unref (printer);
 }
 
 static void
@@ -531,83 +806,115 @@ disconnect_printer (GnomePrinterList *li
 {
         g_signal_handlers_disconnect_by_func (printer,
                                               G_CALLBACK (printer_changed_cb),
-                                              printer);
+                                              list);
         g_signal_handlers_disconnect_by_func (printer,
                                               G_CALLBACK (printer_gone_cb),
-                                              printer);
+                                              list);
         g_object_unref (printer);
 }
 
 static void
-watch_printer (GnomePrinterList *list,
-	       const char *printer_name)
+add_printer (GnomePrinterList *list,
+	     const char *printer_name)
 {
-	EggIconListItem *item;
-	GnomeCupsPrinter *printer = gnome_cups_printer_get (printer_name);
+	GnomePrinterListDetails *details = list->details;
+	GtkTreeIter iter;
+	GnomeCupsPrinter *printer;
+
+	printer = gnome_cups_printer_get (printer_name);
 
 	if (!printer)
 		return;
 
-	list->details->printers = g_list_append (list->details->printers, 
-						 printer);
+	//FIXMEchpe ?
 	g_object_ref (printer);
 	
-	item = create_printer_item (GTK_WIDGET (list), printer);
-	g_object_set_data_full (G_OBJECT (printer), "icon_item", item,
-		(GDestroyNotify)egg_icon_list_item_unref);
+//	item = create_printer_item (GTK_WIDGET (list), printer);
+//	g_object_set_data_full (G_OBJECT (printer), "icon_item", item,
+//		(GDestroyNotify)egg_icon_list_item_unref);
 
-	egg_icon_list_append_item (EGG_ICON_LIST (list), item);
-
-	g_signal_connect_object (printer, "is_default_changed",
+	g_signal_connect_object (printer, "is-default-changed",
 				 G_CALLBACK (printer_changed_cb),
 				 list, 0);
-	g_signal_connect_object (printer, "attributes_changed",
+	g_signal_connect_object (printer, "attributes-changed",
 				 G_CALLBACK (printer_changed_cb),
 				 list, 0);
 	g_signal_connect_object (printer, "gone",
 				 G_CALLBACK (printer_gone_cb),
 				 list, 0);
-	printer_changed_cb (printer, list);
+
+	gtk_list_store_insert_with_values (details->store,
+					   &iter,
+					   -1 /* position */,
+					   (int) 0, printer,
+					   (int) -1);
 }
 
 static void
-printer_added_cb (const char *name, gpointer user_data)
+printer_added_cb (const char *name,
+		  gpointer user_data)
 {
-	GnomePrinterList *list;
+	GnomePrinterList *list = GNOME_PRINTER_LIST (user_data);
 	
-	list = GNOME_PRINTER_LIST (user_data);
-	
-	d (g_warning ("added %s", name););
-	watch_printer (list, name);
+	d (g_print ("added %s\n", name););
+	add_printer (list, name);
 }
 
-static int
-icon_compare (EggIconList *icon_list,
-	      EggIconListItem *a,
-	      EggIconListItem *b,
-	      gpointer user_data)
+static void
+printer_removed_cb (const char *printer_name,
+		    gpointer user_data)
 {
-	GnomePrinterList *list = GNOME_PRINTER_LIST (icon_list);
-	GnomeCupsPrinter *printer_a;
-	GnomeCupsPrinter *printer_b;
-	
-	if (a == b) {
-		return 0;
-	}
+	GnomePrinterList *list = GNOME_PRINTER_LIST (user_data);
+	GnomeCupsPrinter *printer;
 
-	if (a == list->details->add_item) {
-		return -1;
-	}
-	
-	if (b == list->details->add_item) {
-		return 1;
-	}
+	d (g_print ("removed %s\n", printer_name););
+
+	printer = gnome_cups_printer_get (printer_name);
+	if (!printer)
+		return;
 
-	printer_a = egg_icon_list_item_get_data (a);
-	printer_b = egg_icon_list_item_get_data (b);
+	printer_gone_cb (printer, list);
+}
 
-	return strcmp (gnome_cups_printer_get_name (printer_a),
-		       gnome_cups_printer_get_name (printer_b));
+static gint
+printer_compare_func (GtkTreeModel *model,
+		      GtkTreeIter *iter_a,
+		      GtkTreeIter *iter_b,
+		      gpointer data)
+{
+	GnomeCupsPrinter *printer_a = NULL, *printer_b = NULL;
+	gint retval;
+
+	gtk_tree_model_get (model,
+			    iter_a,
+			    (int) 0, &printer_a,
+			    (int) -1);
+	gtk_tree_model_get (model,
+			    iter_b,
+			    (int) 0, &printer_b,
+			    (int) -1);
+
+	if (printer_a != NULL && printer_b != NULL) {
+		const char *name_a, *name_b;
+
+		name_a = gnome_cups_printer_get_name (printer_a);
+		name_b = gnome_cups_printer_get_name (printer_b);
+
+		retval = g_utf8_collate (name_a, name_b);
+
+		g_object_unref (printer_a);
+		g_object_unref (printer_b);
+	} else if (printer_a != NULL) {
+		retval = 1;
+		g_object_unref (printer_a);
+	} else if (printer_b != NULL) {
+		retval = -1;
+		g_object_unref (printer_b);
+	} else {
+		retval = 0;
+	}
+		
+	return retval;
 }
 
 void
@@ -622,176 +929,52 @@ gnome_printer_list_new_printer (GnomePri
 void
 gnome_printer_list_selection_activate (GnomePrinterList *list)
 {
-	GList *selection;
-	GList *l;
-	
-	selection = egg_icon_list_get_selected (EGG_ICON_LIST (list));
-
-	for (l = selection; l != NULL; l = l->next) {
-		EggIconListItem *item = l->data;
-
-		if (item == list->details->add_item) {
-			gnome_printer_list_new_printer (list);
-		} else {
-			GnomeCupsPrinter *printer;
-			
-			printer = egg_icon_list_item_get_data (item);
-			printer_activated_cb (list, printer);
-		}
-	}
-
-	g_list_free (selection);
+	gtk_icon_view_selected_foreach (GTK_ICON_VIEW (list),
+					(GtkIconViewForeachFunc) printer_activated_cb,
+					list);
 }
 
 void
 gnome_printer_list_selection_pause (GnomePrinterList *list)
 {
-	GList *selection;
-	GList *l;
-	
-	selection = egg_icon_list_get_selected (EGG_ICON_LIST (list));
-
-	for (l = selection; l != NULL; l = l->next) {
-		EggIconListItem *item = l->data;
-
-		if (item != list->details->add_item) {
-			GnomeCupsPrinter *printer;
-			GError *error = NULL;
-			
-			printer = egg_icon_list_item_get_data (item);
-
-			gnome_cups_printer_pause (printer, &error);
-			if (error) {
-				char *msg;
-				msg = g_strdup_printf ("Could not pause '%s'", 
-						       gnome_cups_printer_get_name (printer));
-				gnome_cups_error_dialog (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (list))), msg, error);
-				g_free (msg);
-				g_error_free (error);
-			}
-		}
-	}
-
-	g_list_free (selection);
+	gtk_icon_view_selected_foreach (GTK_ICON_VIEW (list),
+					(GtkIconViewForeachFunc) printer_pause_cb,
+					list);
 }
 
 void
 gnome_printer_list_selection_resume (GnomePrinterList *list)
 {
-	GList *selection;
-	GList *l;
-	
-	selection = egg_icon_list_get_selected (EGG_ICON_LIST (list));
-
-	for (l = selection; l != NULL; l = l->next) {
-		EggIconListItem *item = l->data;
-
-		if (item != list->details->add_item) {
-			GnomeCupsPrinter *printer;
-			GError *error = NULL;
-			
-			printer = egg_icon_list_item_get_data (item);
-
-			gnome_cups_printer_resume (printer, &error);
-			if (error) {
-				char *msg;
-				msg = g_strdup_printf ("Could not resume '%s'", 
-						       gnome_cups_printer_get_name (printer));
-				gnome_cups_error_dialog (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (list))), msg, error);
-				g_free (msg);
-				g_error_free (error);
-			}
-		}
-	}
-
-	g_list_free (selection);
+	gtk_icon_view_selected_foreach (GTK_ICON_VIEW (list),
+					(GtkIconViewForeachFunc) printer_resume_cb,
+					list);
 }
 
 void
 gnome_printer_list_selection_make_default (GnomePrinterList *list)
 {
-	
-	GList *selection;
-	GnomeCupsPrinter *printer;
-	EggIconListItem *item;
-	GError *error = NULL;
-
-	selection = egg_icon_list_get_selected (EGG_ICON_LIST (list));
-        g_return_if_fail (g_list_length (selection) == 1);
-
-	item = selection->data;
-        g_return_if_fail (item != list->details->add_item);
-
-	printer = GNOME_CUPS_PRINTER (egg_icon_list_item_get_data (item));
-        gnome_cups_printer_set_default (printer, &error);
-        if (error) {
-                char *msg;
-                msg = g_strdup_printf ("Could not make '%s' the default printer", 
-                                       gnome_cups_printer_get_name (printer));
-				gnome_cups_error_dialog (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (list))), msg, error);
-                g_free (msg);
-                g_error_free (error);
-        }
-
-	g_list_free (selection);
+	/* We will in fact have only one selected item here, but this is more convenient */
+	gtk_icon_view_selected_foreach (GTK_ICON_VIEW (list),
+					(GtkIconViewForeachFunc) printer_set_default_cb,
+					list);
 }
 
 void
 gnome_printer_list_selection_properties (GnomePrinterList *list)
 {
-	GList *selection;
-	GList *l;
-	
-	selection = egg_icon_list_get_selected (EGG_ICON_LIST (list));
-
-	for (l = selection; l != NULL; l = l->next) {
-		EggIconListItem *item = l->data;
-
-		if (item != list->details->add_item) {
-			GnomeCupsPrinter *printer;
-			
-			printer = egg_icon_list_item_get_data (item);
-
-			gnome_cups_manager_printer_properties (printer);
-		}
-	}
-
-	g_list_free (selection);
+	gtk_icon_view_selected_foreach (GTK_ICON_VIEW (list),
+					(GtkIconViewForeachFunc) printer_properties_cb,
+					list);
 }
 
 void
 gnome_printer_list_selection_delete (GnomePrinterList *list)
 {
-	GList *selection;
-	GList *l;
-
-	selection = egg_icon_list_get_selected (EGG_ICON_LIST (list));
-
-	for (l = selection; l != NULL; l = l->next) {
-		EggIconListItem *item = l->data;
-
-		if (item != list->details->add_item) {
-			GnomeCupsPrinter *printer;
-			GError *error = NULL;
-			
-			printer = egg_icon_list_item_get_data (item);
-
-			gnome_cups_printer_delete (printer, &error);
-			if (error) {
-				char *msg;
-				msg = g_strdup_printf ("Could not delete '%s'", 
-						       gnome_cups_printer_get_name (printer));
-				gnome_cups_error_dialog (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (list))), msg, error);
-				g_free (msg);
-				g_error_free (error);
-			}
-		}
-	}
-
-	g_list_free (selection);
+	gtk_icon_view_selected_foreach (GTK_ICON_VIEW (list),
+					(GtkIconViewForeachFunc) printer_remove_cb,
+					list);
 }
 
-
 static void
 gnome_printer_list_init (GnomePrinterList *list)
 {
@@ -795,76 +978,173 @@ gnome_printer_list_selection_delete (Gno
 static void
 gnome_printer_list_init (GnomePrinterList *list)
 {
-	GList *printer_names;
-	GList *l;
-	
-	list->details = g_new0 (GnomePrinterListDetails, 1);
-
+	list->details = G_TYPE_INSTANCE_GET_PRIVATE (list, GNOME_TYPE_PRINTER_LIST, GnomePrinterListDetails);
+}
 
-	egg_icon_list_set_sort_func (EGG_ICON_LIST (list),
-				     icon_compare,
-				     list,
-				     NULL);
-	egg_icon_list_set_sorted (EGG_ICON_LIST (list), TRUE);
+static GObject *
+gnome_printer_list_constructor (GType type,
+	                        guint n_construct_properties,
+        	                GObjectConstructParam *construct_params)
 
-	add_new_printer_icon (list);
+{
+	GObject *object;
+	GtkIconView *icon_view;
+	GtkCellLayout *cell_layout;
+	GnomePrinterList *list;
+	GnomePrinterListDetails *details;
+	GList *printer_names;
+	GList *l;
+	GtkListStore *store;
+	GtkTreeModel *sortmodel;
+	GtkTreeIter iter;
+	GtkCellRenderer *renderer;
+	
+        object = G_OBJECT_CLASS (gnome_printer_list_parent_class)->constructor
+			(type, n_construct_properties, construct_params);
+
+	icon_view = GTK_ICON_VIEW (object);
+	cell_layout = GTK_CELL_LAYOUT (icon_view);
+	list = GNOME_PRINTER_LIST (icon_view);
+	details = list->details;
+
+	g_signal_connect (list, "button-press-event",
+			  G_CALLBACK (button_press_cb), NULL);
+	g_signal_connect (list, "popup-menu",
+			  G_CALLBACK (popup_menu_cb), NULL);
+	g_signal_connect (list, "item-activated",
+			  G_CALLBACK (printer_activated_cb), list);
+
+	/* The store owns one refernce to each printer */
+	store = details->store = gtk_list_store_new (1, GNOME_CUPS_TYPE_PRINTER);
+	details->model = GTK_TREE_MODEL (store);
+
+	/* Add NULL row which represents the "New Printer" icon */
+	gtk_list_store_insert_with_values (store,
+					   &iter,
+					   (int) 0 /* position */,
+					   (int) 0, NULL,
+					   (int) -1);
 	
+	/* Now add the printers */
 	printer_names = gnome_cups_get_printers ();
 	for (l = printer_names; l != NULL; l = l->next) {
-		watch_printer (list, l->data);
+		add_printer (list, l->data);
 	}
 	gnome_cups_printer_list_free (printer_names);
 
-	list->details->new_printer_notify = 
+	sortmodel = gtk_tree_model_sort_new_with_model (details->model);
+	g_object_unref (details->model);
+
+	gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sortmodel),
+						 printer_compare_func,
+						 NULL, NULL);
+
+	gtk_icon_view_set_model (icon_view, sortmodel);
+	g_object_unref (sortmodel);
+
+	gtk_icon_view_set_selection_mode (icon_view, GTK_SELECTION_MULTIPLE);
+
+	/* Cell renderers */
+	renderer = gtk_cell_renderer_pixbuf_new ();
+	gtk_cell_layout_pack_start (cell_layout, renderer, FALSE);
+	g_object_set (renderer,
+		      "follow-state", (gboolean) TRUE,
+		      "stock-size", (glong) GTK_ICON_SIZE_DIALOG,
+		      NULL);
+	gtk_cell_layout_set_cell_data_func (cell_layout,
+					    renderer,
+					    printer_get_pixbuf_func,
+					    list, NULL);
+
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_cell_layout_pack_end (cell_layout, renderer, FALSE);
+	g_object_set (renderer,
+		      "editable", FALSE,
+		      "xalign", 0.5,
+		      "wrap-mode", PANGO_WRAP_WORD_CHAR,
+		      "wrap-width", 100,
+		      NULL);
+	gtk_cell_layout_set_cell_data_func (cell_layout,
+					    renderer,
+					    printer_get_text_func,
+					    list, NULL);
+
+	/* Printer list changes */
+	details->printer_added_id =
 		gnome_cups_printer_new_printer_notify_add (printer_added_cb,
 							   list);
+	details->printer_removed_id =
+		gnome_cups_printer_printer_removed_notify_add (printer_removed_cb,
+							       list);
 
-	egg_icon_list_set_selection_mode (EGG_ICON_LIST (list),
-					  GTK_SELECTION_MULTIPLE);
+	return object;
+}
+
+static gboolean
+foreach_disconnect (GtkTreeModel *model,
+		    GtkTreePath *path,
+		    GtkTreeIter *iter,
+		    GnomePrinterList *list)
+{
+	GnomeCupsPrinter *printer = NULL;
 
-	g_signal_connect (list, "item_activated", 
-			  G_CALLBACK (item_activated_cb), NULL);
+	gtk_tree_model_get (model,
+			    iter,
+			    (int) 0, &printer,
+			    (int) -1);
 
-	g_signal_connect (list, "button_press_event",
-			  G_CALLBACK (button_press_event_cb), NULL);
+	if (printer == NULL)
+		return FALSE;
+
+	disconnect_printer (list, printer);
+
+	/* It's ok to unref here since we're not the model of the icon view anymore */
+	g_object_unref (printer);
+
+	/* continue */
+	return FALSE;
 }
 
 static void
 gnome_printer_list_destroy (GtkObject *object)
 {
-	GnomePrinterList *list;
-	GList *l;
-
-	list = GNOME_PRINTER_LIST (object);
+	GnomePrinterList *list = GNOME_PRINTER_LIST (object);
+	GnomePrinterListDetails *details = list->details;
 
-	for (l = list->details->printers; l != NULL; l = l->next) {
-		disconnect_printer (list, GNOME_CUPS_PRINTER (l->data));
+	if (details->model) {
+		g_object_ref (details->model);
+		gtk_icon_view_set_model (GTK_ICON_VIEW (list), NULL);
+		gtk_tree_model_foreach (details->model,
+					(GtkTreeModelForeachFunc) foreach_disconnect,
+					list);
+		gtk_list_store_clear (details->store);
+		g_object_unref (details->model);
+		details->model = NULL;
 	}
 
-	g_list_free (list->details->printers);
-	list->details->printers = NULL;
-	
-	if (list->details->new_printer_notify) {
-		gnome_cups_printer_new_printer_notify_remove (list->details->new_printer_notify);
-		list->details->new_printer_notify = 0;
+	if (details->printer_added_id != 0) {
+		gnome_cups_printer_new_printer_notify_remove (details->printer_added_id);
+		details->printer_added_id = 0;
 	}
-	
-        GTK_OBJECT_CLASS (gnome_printer_list_parent_class)-> destroy, (object);
+	if (details->printer_removed_id != 0) {
+		gnome_cups_printer_printer_removed_notify_remove (details->printer_removed_id);
+		details->printer_removed_id = 0;
+	}
+
+        GTK_OBJECT_CLASS (gnome_printer_list_parent_class)->destroy (object);
 }
 
 static void
-gnome_printer_list_finalize (GObject *object)
+gnome_printer_list_class_init (GnomePrinterListClass *klass)
 {
-	GnomePrinterList *list = GNOME_PRINTER_LIST (object);
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass);
 
-	g_free (list->details);
-}
+	gobject_class->constructor = gnome_printer_list_constructor;
 
-static void
-gnome_printer_list_class_init (GnomePrinterListClass *class)
-{
-	GTK_OBJECT_CLASS (class)->destroy = gnome_printer_list_destroy;
-	G_OBJECT_CLASS (class)->finalize = gnome_printer_list_finalize;
+	gtkobject_class->destroy = gnome_printer_list_destroy;
+
+	g_type_class_add_private (gobject_class, sizeof (GnomePrinterListDetails));
 }
 
 GtkWidget *
Index: gnome-cups-manager/gnome-printer-list.h
===================================================================
RCS file: /cvs/gnome/gnome-cups-manager/gnome-cups-manager/gnome-printer-list.h,v
retrieving revision 1.2
diff -p -u -B -r1.2 gnome-printer-list.h
--- gnome-cups-manager/gnome-printer-list.h	13 Sep 2004 20:04:13 -0000	1.2
+++ gnome-cups-manager/gnome-printer-list.h	14 Dec 2006 01:15:55 -0000
@@ -1,10 +1,7 @@
 #ifndef GNOME_PRINTER_LIST_H
 #define GNOME_PRINTER_LIST_H
 
-#include <glib.h>
-#include <glib-object.h>
-
-#include "eggiconlist.h"
+#include <gtk/gtkiconview.h>
 
 G_BEGIN_DECLS
 
@@ -20,13 +17,13 @@ typedef struct _GnomePrinterListClass   
 typedef struct _GnomePrinterListDetails GnomePrinterListDetails;
 
 struct _GnomePrinterList {
-	EggIconList parent;
+	GtkIconView parent;
 	
 	GnomePrinterListDetails *details;
 };
 
 struct _GnomePrinterListClass {
-	EggIconListClass parent_class;
+	GtkIconViewClass parent_class;
 };
 
 GType      gnome_printer_list_get_type                  (void);
Index: gnome-cups-manager/view-printers.c
===================================================================
RCS file: /cvs/gnome/gnome-cups-manager/gnome-cups-manager/view-printers.c,v
retrieving revision 1.9
diff -p -u -B -r1.9 view-printers.c
--- gnome-cups-manager/view-printers.c	1 Oct 2004 19:10:03 -0000	1.9
+++ gnome-cups-manager/view-printers.c	14 Dec 2006 01:15:55 -0000
@@ -247,7 +247,7 @@ update_menus (GladeXML *xml)
 }
 
 static void
-selection_changed_cb (EggIconList *list,
+selection_changed_cb (GnomePrinterList *list,
 		      gpointer user_data)
 {
 	update_menus (GLADE_XML (user_data));
