--- /dev/null	2007-04-21 01:08:51.000000000 +0200
+++ gladeui/glade-named-icon-chooser-dialog.c	2007-07-07 00:49:06.000000000 +0200
@@ -0,0 +1,1775 @@
+/*
+ * glade-named-icon-chooser-widget.c - Named icon chooser widget
+ *
+ * Copyright (C) 2007 Vincent Geddes
+ *
+ * Author:  Vincent Geddes <vgeddes@gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANNAMED_ICON_CHOOSERILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+
+#include "glade-named-icon-chooser-dialog.h"
+#include "icon-naming-spec.c"
+
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+#include <string.h>
+#include <errno.h>
+
+
+#define DEFAULT_SETTING_LIST_STANDARD_ONLY   TRUE
+
+#define GLADE_NAMED_ICON_CHOOSER_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o),     \
+							GLADE_TYPE_NAMED_ICON_CHOOSER_DIALOG, \
+							GladeNamedIconChooserDialogPrivate))
+
+enum
+{
+	CONTEXTS_ID_COLUMN,
+	CONTEXTS_NAME_COLUMN,
+	CONTEXTS_TITLE_COLUMN,
+	
+	CONTEXTS_N_COLUMS
+};
+
+enum
+{
+	ICONS_CONTEXT_COLUMN,
+	ICONS_STANDARD_COLUMN,
+	ICONS_NAME_COLUMN,
+	
+	ICONS_N_COLUMNS
+};
+
+enum
+{
+	GLADE_NAMED_ICON
+};
+
+enum {
+	ICON_ACTIVATED,
+	SELECTION_CHANGED,
+	
+	LAST_SIGNAL
+};
+
+struct _GladeNamedIconChooserDialogPrivate
+{
+	GtkWidget          *icons_view; 
+	GtkTreeModel       *filter_model;       /* filtering model  */
+	GtkListStore       *icons_store;        /* data store       */
+	GtkTreeSelection   *selection;
+
+	GtkWidget          *contexts_view;
+	GtkListStore       *contexts_store;
+	
+	GtkWidget          *entry;
+	GtkEntryCompletion *entry_completion;
+	
+	GtkWidget          *button;              /* list-standard-only checkbutton */
+	
+	gint                context_id;          /* current icon name context for icon filtering */
+	
+	gchar              *pending_select_name; /* an icon name for a pending treeview selection.
+	                                          * can only select name after model is loaded
+	                                          * and the widget is mapped */
+	
+	GtkIconTheme       *icon_theme;          /* the current icon theme */
+	guint               load_id;             /* id of the idle function for loading data into model */
+	
+	gboolean            settings_list_standard;   /* whether to list standard icon names only */
+	
+	GtkWidget          *last_focus_widget;
+	
+	gboolean            icons_loaded; /* whether the icons have been loaded into the model */
+};
+
+static GHashTable *standard_icon_quarks = NULL;
+
+static guint       dialog_signals[LAST_SIGNAL] = { 0, };
+
+
+gchar      *glade_named_icon_chooser_dialog_get_icon_name  (GladeNamedIconChooserDialog *dialog);
+
+void        glade_named_icon_chooser_dialog_set_icon_name  (GladeNamedIconChooserDialog *dialog,
+							    const gchar           *icon_name);
+
+gboolean    glade_named_icon_chooser_dialog_set_context    (GladeNamedIconChooserDialog *dialog,
+							    const gchar           *context);
+
+gchar      *glade_named_icon_chooser_dialog_get_context    (GladeNamedIconChooserDialog *dialog);
+
+static gboolean    should_respond                          (GladeNamedIconChooserDialog *dialog);
+
+static void        filter_icons_model                      (GladeNamedIconChooserDialog *dialog);
+
+static gboolean    scan_for_name_func                      (GtkTreeModel *model,
+ 							    GtkTreePath  *path,
+ 							    GtkTreeIter *iter,
+ 							    gpointer data);
+
+static gboolean    scan_for_context_func                   (GtkTreeModel *model,
+ 							    GtkTreePath  *path,
+ 							    GtkTreeIter *iter,
+ 							    gpointer data);
+ 								 
+static void        settings_load                           (GladeNamedIconChooserDialog *dialog);
+
+static void        settings_save                           (GladeNamedIconChooserDialog *dialog);
+
+
+G_DEFINE_TYPE (GladeNamedIconChooserDialog, glade_named_icon_chooser_dialog, GTK_TYPE_DIALOG);
+
+
+static void
+entry_set_name (GladeNamedIconChooserDialog *dialog, const gchar *name)
+{
+	/* Must disable completion before setting text, in order to avoid
+	 * spurious warnings (possible GTK+ bug).
+	 */
+	gtk_entry_set_completion (GTK_ENTRY (dialog->priv->entry), NULL);
+	
+	gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), name);
+	
+	gtk_entry_set_completion (GTK_ENTRY (dialog->priv->entry), dialog->priv->entry_completion);
+}
+
+static GtkIconTheme *
+get_icon_theme_for_widget (GtkWidget *widget)
+{
+	if (gtk_widget_has_screen (widget))
+		return gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
+
+	return gtk_icon_theme_get_default ();
+}
+
+/* validates name according to the icon naming spec (en_US.US_ASCII [a-z1-9_-.])  */
+static gboolean
+is_well_formed (const gchar *name)
+{
+	gchar *c = (gchar *) name;
+	for (; *c; c++)
+	{
+		if (g_ascii_isalnum (*c))
+		{
+			if (g_ascii_isalpha (*c) && !g_ascii_islower (*c))
+				return FALSE;
+		}
+		else if (*c != '_' && *c != '-' && *c != '.')
+		{
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+static void
+check_entry_text (GladeNamedIconChooserDialog *dialog,
+		  gchar   **name_ret,
+		  gboolean *is_wellformed_ret, 
+		  gboolean *is_empty_ret) 
+{
+	if (strlen (gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry))) == 0)
+	{
+		*name_ret = NULL;
+		*is_wellformed_ret = TRUE;
+		*is_empty_ret = TRUE;
+		
+		return;
+	}
+
+	*is_empty_ret = FALSE;
+
+	*is_wellformed_ret = is_well_formed (gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry)));
+
+	if (*is_wellformed_ret)
+		*name_ret = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry)));
+	else
+		*name_ret = NULL;
+}
+
+static void
+changed_text_handler (GtkEditable                 *editable,
+                      GladeNamedIconChooserDialog *dialog)
+{
+	g_signal_emit_by_name (dialog, "selection-changed", NULL);
+}   
+
+/* ensure that only valid text can be inserted into entry */
+static void
+insert_text_handler (GtkEditable *editable,
+                     const gchar *text,
+                     gint         length,
+                     gint        *position,
+                     GladeNamedIconChooserDialog *dialog)
+{
+	if (is_well_formed (text))
+	{
+
+		g_signal_handlers_block_by_func (editable, (gpointer) insert_text_handler, dialog);
+					         
+		gtk_editable_insert_text (editable, text, length, position);
+		
+		g_signal_handlers_unblock_by_func (editable, (gpointer) insert_text_handler, dialog);
+
+	}
+	else
+	{
+		gdk_display_beep (gtk_widget_get_display (GTK_WIDGET (dialog)));
+	}
+	
+	g_signal_stop_emission_by_name (editable, "insert-text"); 
+}
+
+typedef struct
+{
+	gchar *name;           /* the name of the icon or context */
+
+	guint found : 1;       /* whether an item matching `name' was found */
+	guint do_select : 1;   /* select the matched row */
+	guint do_cursor : 1;   /* put cursor at the matched row */
+	guint do_activate : 1; /* activate the matched row */
+
+	GladeNamedIconChooserDialog *dialog;
+} ForEachFuncData;
+
+void
+glade_named_icon_chooser_dialog_set_icon_name (GladeNamedIconChooserDialog *dialog,
+					       const gchar                 *name)
+{
+	ForEachFuncData *data;
+	gboolean located_in_theme;
+
+	g_return_if_fail (GLADE_IS_NAMED_ICON_CHOOSER_DIALOG (dialog));
+	g_return_if_fail (gtk_widget_has_screen (GTK_WIDGET (dialog)));
+	 
+	if (name == NULL)
+	{
+		gtk_tree_selection_unselect_all (dialog->priv->selection);
+		entry_set_name (dialog, "");	
+		return;
+	}
+	
+	located_in_theme = gtk_icon_theme_has_icon (get_icon_theme_for_widget (GTK_WIDGET (dialog)),
+		 				    name);
+
+	if (located_in_theme)
+	{
+		
+		if (dialog->priv->icons_loaded && dialog->priv->filter_model)
+		{
+
+			data = g_slice_new0(ForEachFuncData);
+			data->name = g_strdup (name);
+			data->found = FALSE;
+			data->do_activate = FALSE;
+			data->do_select  = TRUE;
+			data->do_cursor  = TRUE;
+			data->dialog = dialog;
+  
+			gtk_tree_model_foreach (dialog->priv->filter_model,
+						scan_for_name_func,
+						data);
+		
+			g_free (data->name);
+			g_slice_free (ForEachFuncData, data);
+		
+		}
+		else
+		{
+			dialog->priv->pending_select_name = g_strdup (name);
+		}
+		
+		/* selecting a treeview row will set the entry text,
+		 * but we must have this here in case the row has been filtered out
+		 */ 
+		entry_set_name (dialog, name);
+		
+	}
+	else if (is_well_formed (name))
+	{
+		
+		gtk_tree_selection_unselect_all (dialog->priv->selection);
+	
+		entry_set_name (dialog, name);
+	}
+	else
+	{
+		g_warning ("invalid icon name: '%s' is not well formed", name);
+	}
+}
+
+gboolean
+glade_named_icon_chooser_dialog_set_context (GladeNamedIconChooserDialog *dialog,
+					     const gchar                 *name)
+{
+	ForEachFuncData *data;
+
+	g_return_val_if_fail (GLADE_IS_NAMED_ICON_CHOOSER_DIALOG (dialog), FALSE);
+
+	data = g_slice_new0 (ForEachFuncData);
+	
+	if (name)	
+		data->name = g_strdup (name);
+	else
+		data->name = g_strdup ("All Contexts");
+
+	data->found = FALSE;
+	data->do_select = TRUE;
+	data->do_activate = FALSE;
+	data->do_cursor = FALSE;
+	data->dialog = dialog;
+	
+	gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->priv->contexts_store),
+				(GtkTreeModelForeachFunc) scan_for_context_func,
+				data);
+				
+	g_free (data->name);			
+	g_slice_free (ForEachFuncData, data);
+
+	return TRUE;
+}
+
+gchar *
+glade_named_icon_chooser_dialog_get_context (GladeNamedIconChooserDialog *dialog)
+{
+	GtkTreeSelection *sel;
+	GtkTreeIter iter;
+	gchar *context_name;
+
+	g_return_val_if_fail (GLADE_IS_NAMED_ICON_CHOOSER_DIALOG (dialog), NULL);
+
+	sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->contexts_view));
+
+	if (gtk_tree_selection_get_selected (sel, NULL, &iter))
+	{
+	
+		gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->contexts_store), &iter,
+				    CONTEXTS_NAME_COLUMN, &context_name,
+				    -1);
+	
+		/* if context_name is NULL, then it is the 'all categories' special context */
+		return context_name;
+	
+	}
+	else
+	{
+		return NULL;
+	}
+}
+
+static gchar *
+get_icon_name_from_selection (GladeNamedIconChooserDialog *dialog)
+{
+	GtkTreeIter  iter;
+	GtkTreeModel *model;
+	gchar        *name;
+
+	if (!gtk_tree_selection_get_selected (dialog->priv->selection, &model, &iter))
+		return NULL;
+	
+	gtk_tree_model_get (model, &iter,
+			    ICONS_NAME_COLUMN, &name,
+			    -1);
+
+	return name;
+}
+
+gchar*
+glade_named_icon_chooser_dialog_get_icon_name (GladeNamedIconChooserDialog *dialog)
+{
+	GtkWidget *current_focus;
+	gchar *name;
+
+	g_return_val_if_fail (GLADE_IS_NAMED_ICON_CHOOSER_DIALOG (dialog), NULL);
+
+	current_focus = gtk_window_get_focus (GTK_WINDOW (dialog));
+	
+	if (current_focus == dialog->priv->icons_view)
+	{
+		
+	view:	
+		name = get_icon_name_from_selection (dialog);
+
+		if (name == NULL)
+			goto entry;
+	
+	}
+	else if (current_focus == dialog->priv->entry)
+	{
+		gboolean is_wellformed, is_empty;	
+	entry:
+		check_entry_text (dialog, &name, &is_wellformed, &is_empty);
+
+		if (!is_wellformed || is_empty)
+			return NULL;
+	
+	}
+	else if (dialog->priv->last_focus_widget == dialog->priv->icons_view)
+	{
+		goto view;
+	}
+	else if (dialog->priv->last_focus_widget == dialog->priv->entry)
+	{
+		goto entry;	
+	}
+	else
+	{
+		goto view;
+	}
+	
+	return name;
+}
+
+static void
+set_busy_cursor (GladeNamedIconChooserDialog *dialog,
+		 gboolean                      busy)
+{
+	GdkDisplay *display;
+	GdkCursor  *cursor;
+
+	if (!GTK_WIDGET_REALIZED (dialog))
+		return;
+
+	display = gtk_widget_get_display (GTK_WIDGET (dialog));
+
+	if (busy)
+		cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+	else
+		cursor = NULL;
+
+	gdk_window_set_cursor (GTK_WIDGET (dialog)->window, cursor);
+	gdk_display_flush (display);
+
+	if (cursor)
+		gdk_cursor_unref (cursor);
+}
+
+static GtkListStore*
+populate_icon_contexts_model (void)
+{
+	GtkListStore *store;
+	GtkTreeIter iter;	
+	guint i;
+	
+  	store = gtk_list_store_new (CONTEXTS_N_COLUMS,
+  				    G_TYPE_INT,
+  	                            G_TYPE_STRING,
+  	                            G_TYPE_STRING);
+
+
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter,
+			    CONTEXTS_ID_COLUMN,    -1,
+			    CONTEXTS_NAME_COLUMN,  "All Contexts",
+			    CONTEXTS_TITLE_COLUMN, _("All Contexts"),
+		    	    -1);
+		    	    
+	gtk_list_store_append (store, &iter);
+	gtk_list_store_set (store, &iter,
+			    CONTEXTS_ID_COLUMN,     -1,
+			    CONTEXTS_NAME_COLUMN,   NULL,
+			    CONTEXTS_TITLE_COLUMN,   NULL,
+		    	    -1);
+				
+	for (i = 0; i < G_N_ELEMENTS (standard_contexts); i++)
+	{
+
+		gtk_list_store_append (store, &iter);
+		gtk_list_store_set (store, &iter,
+				    CONTEXTS_ID_COLUMN,    i,
+				    CONTEXTS_NAME_COLUMN,  standard_contexts[i].name,
+				    CONTEXTS_TITLE_COLUMN, _(standard_contexts[i].title),
+			    	    -1);
+	} 
+		
+	return store;	    
+}
+
+static void
+icons_row_activated_cb (GtkTreeView                  *view,
+			GtkTreePath                  *path,
+			GtkTreeViewColumn            *column,
+			GladeNamedIconChooserDialog *dialog)
+{
+	g_signal_emit_by_name (dialog, "icon-activated", NULL);
+}
+
+static void
+icons_selection_changed_cb (GtkTreeSelection             *selection,
+			    GladeNamedIconChooserDialog *dialog)
+{	
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gchar *name;
+
+	if (gtk_tree_selection_get_selected (selection, &model, &iter))
+	{
+		gtk_tree_model_get (model, &iter,
+				    ICONS_NAME_COLUMN, &name,
+				    -1);
+		if (name) 
+			entry_set_name (dialog, name);	
+
+		g_free (name);
+	}
+	else
+	{
+		/* entry_set_name (dialog, ""); */
+	}
+	
+	/* we emit "selection-changed" for chooser in insert_text_handler()
+	 * to avoid emitting the signal twice */
+}
+
+static void
+contexts_row_activated_cb (GtkTreeView                  *view,
+			   GtkTreePath                  *cpath,
+			   GtkTreeViewColumn            *column,
+			   GladeNamedIconChooserDialog *dialog)
+{
+	GtkTreeIter iter;
+	GtkTreePath *path;
+	
+	if (gtk_tree_model_get_iter_first (dialog->priv->filter_model, &iter))
+	{
+	
+		gtk_tree_selection_select_iter (dialog->priv->selection, &iter);
+		
+		path = gtk_tree_model_get_path (dialog->priv->filter_model, &iter);	
+			
+		gtk_tree_selection_select_path (dialog->priv->selection, path);
+		
+		gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (dialog->priv->icons_view), -1, 0);
+
+		gtk_tree_path_free (path);
+
+	}
+	gtk_widget_grab_focus (dialog->priv->icons_view);
+}
+
+static void
+contexts_selection_changed_cb (GtkTreeSelection *selection,
+			       GladeNamedIconChooserDialog *dialog)
+{
+	GtkTreeIter iter;
+	GtkTreeModel *model;
+	gboolean retval;
+	gint context_id;
+
+	retval = gtk_tree_selection_get_selected (selection, &model, &iter);
+
+	if (retval)
+	{	
+	
+		gtk_tree_model_get (model, &iter,
+				    CONTEXTS_ID_COLUMN, &context_id,
+				    -1);
+		
+		dialog->priv->context_id = context_id;			
+			
+		if (!dialog->priv->filter_model)
+			return;
+		
+		filter_icons_model (dialog);
+	}
+	
+	entry_set_name (dialog, "");
+
+}
+
+static gboolean
+row_separator_func (GtkTreeModel *model,
+		    GtkTreeIter  *iter,
+		    gpointer      unused)
+{
+	gboolean retval;
+	gchar *name, *title;
+
+	gtk_tree_model_get (model, iter,
+			    CONTEXTS_NAME_COLUMN, &name,
+			    CONTEXTS_TITLE_COLUMN, &title,
+			    -1);
+
+	retval = !name && !title;
+
+	g_free (name);
+	g_free (title);
+	
+	return retval;
+}
+
+static GtkWidget*
+create_contexts_view (GladeNamedIconChooserDialog *dialog)
+{
+	GtkTreeView *view;
+	GtkTreeViewColumn *column;
+	GtkTreePath *path;
+	
+	dialog->priv->contexts_store = populate_icon_contexts_model ();
+	
+	view = GTK_TREE_VIEW (gtk_tree_view_new_with_model (GTK_TREE_MODEL (dialog->priv->contexts_store)));
+	
+	column = gtk_tree_view_column_new_with_attributes (NULL,
+						           gtk_cell_renderer_text_new (), 
+						           "text",   CONTEXTS_TITLE_COLUMN,
+						           NULL);
+						           
+	gtk_tree_view_append_column (view, column);
+	gtk_tree_view_set_headers_visible (view, FALSE);
+	
+	gtk_tree_view_set_row_separator_func (view,
+					      (GtkTreeViewRowSeparatorFunc) row_separator_func,
+					      NULL,
+					      NULL);
+
+	gtk_tree_selection_set_mode (gtk_tree_view_get_selection (view), GTK_SELECTION_BROWSE);
+	
+	path = gtk_tree_path_new_from_indices (0, -1);
+	gtk_tree_selection_select_path (gtk_tree_view_get_selection (view), path);
+	gtk_tree_path_free (path);	
+	
+	g_signal_connect (view, "row-activated",
+			  G_CALLBACK (contexts_row_activated_cb),
+			  dialog);		
+	
+	g_signal_connect (gtk_tree_view_get_selection (view), "changed",
+			  G_CALLBACK (contexts_selection_changed_cb),
+			  dialog);
+	
+	gtk_widget_show (GTK_WIDGET (view));
+	
+	return GTK_WIDGET (view);
+}
+
+/* filters the icons model based on the current state */
+static void
+filter_icons_model (GladeNamedIconChooserDialog *dialog)
+{
+
+	set_busy_cursor (dialog, TRUE);
+	
+	g_object_ref (dialog->priv->filter_model);
+	gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->priv->icons_view), NULL);
+	gtk_entry_completion_set_model (dialog->priv->entry_completion, NULL);
+	
+	gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (dialog->priv->filter_model));
+
+	gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->priv->icons_view), dialog->priv->filter_model);
+	gtk_entry_completion_set_model (dialog->priv->entry_completion, GTK_TREE_MODEL (dialog->priv->icons_store));
+	gtk_entry_completion_set_text_column (dialog->priv->entry_completion, ICONS_NAME_COLUMN);
+	g_object_unref (dialog->priv->filter_model);
+
+	set_busy_cursor (dialog, FALSE);
+}
+
+static gboolean
+filter_visible_func (GtkTreeModel  *model,
+                     GtkTreeIter   *iter,
+                     GladeNamedIconChooserDialog *dialog)
+{
+	gboolean standard;
+	gint     context_id;
+
+	gtk_tree_model_get (model, iter,
+                            ICONS_CONTEXT_COLUMN,  &context_id,
+			    ICONS_STANDARD_COLUMN, &standard,
+                            -1);  
+
+	if (dialog->priv->context_id == -1)
+		return (dialog->priv->settings_list_standard) ? TRUE && standard : TRUE;
+
+	if (context_id == dialog->priv->context_id)
+		return (dialog->priv->settings_list_standard) ? TRUE && standard : TRUE;
+	else
+		return FALSE;
+}
+
+
+static gboolean
+search_equal_func (GtkTreeModel *model,
+                   gint column,
+                   const gchar *key,
+                   GtkTreeIter *iter,
+                   GladeNamedIconChooserDialog *dialog)
+{
+	gchar *name; 
+	gboolean retval;
+
+	gtk_tree_model_get (model, iter, 
+                            ICONS_NAME_COLUMN, &name,
+                            -1);
+        
+        retval = ! g_str_has_prefix (name, key);           
+
+	g_free (name);	
+	
+        return retval;
+
+}
+
+static gboolean
+scan_for_context_func (GtkTreeModel *model,
+                       GtkTreePath  *path,
+                       GtkTreeIter  *iter,
+                       gpointer      user_data)
+{
+	ForEachFuncData   *data = (ForEachFuncData *) user_data;
+	GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->dialog->priv->contexts_view));
+	gchar *name = NULL;
+
+	gtk_tree_model_get (model, iter, CONTEXTS_NAME_COLUMN, &name, -1);	    
+	if (!name)
+		return FALSE;
+			    
+	if (strcmp (name, data->name) == 0)
+	{
+	
+		data->found = TRUE;
+	
+		if (data->do_activate)
+			gtk_tree_view_row_activated (GTK_TREE_VIEW (data->dialog->priv->contexts_view),
+						     path,
+						     gtk_tree_view_get_column 
+						     	(GTK_TREE_VIEW (data->dialog->priv->contexts_view), 0));		
+
+		if (data->do_select)
+			gtk_tree_selection_select_path (selection, path);
+		else
+			gtk_tree_selection_unselect_path (selection, path);
+			
+		if (data->do_cursor)
+			gtk_tree_view_set_cursor (GTK_TREE_VIEW (data->dialog->priv->contexts_view),
+						  path, NULL, FALSE);
+
+		g_free (name);
+		
+		return TRUE;
+	}
+
+	g_free (name);
+
+	return FALSE;
+}
+
+gboolean
+scan_for_name_func (GtkTreeModel *model,
+                    GtkTreePath  *path,
+                    GtkTreeIter  *iter,
+                    gpointer      user_data)
+{
+	ForEachFuncData *data = (ForEachFuncData *) user_data;	
+	gchar *name = NULL;
+
+	gtk_tree_model_get (model, iter, ICONS_NAME_COLUMN, &name, -1);	    
+	if (!name)
+		return FALSE;
+			    
+	if (strcmp (name, data->name) == 0)
+	{
+	
+		data->found = TRUE;
+	
+		if (data->do_activate)
+			gtk_tree_view_row_activated (GTK_TREE_VIEW (data->dialog->priv->icons_view),
+						     path,
+						     gtk_tree_view_get_column 
+						     	(GTK_TREE_VIEW (data->dialog->priv->icons_view), 0));		
+
+		if (data->do_select)
+			gtk_tree_selection_select_path (data->dialog->priv->selection, path);
+		else
+			gtk_tree_selection_unselect_path (data->dialog->priv->selection, path);
+			
+		if (data->do_cursor)
+			gtk_tree_view_set_cursor (GTK_TREE_VIEW (data->dialog->priv->icons_view),
+						  path, NULL, FALSE);
+				
+		g_free (name);
+		
+		return TRUE;
+	}
+
+	g_free (name);
+
+	return FALSE;
+}
+
+static void
+centre_selected_row (GladeNamedIconChooserDialog *dialog)
+{
+	GList *l;
+	
+	g_assert (dialog->priv->icons_store != NULL);	
+	g_assert (dialog->priv->selection != NULL);
+	
+	l = gtk_tree_selection_get_selected_rows (dialog->priv->selection, NULL);
+	
+	if (l) {
+		g_assert (GTK_WIDGET_MAPPED (dialog));
+		g_assert (GTK_WIDGET_VISIBLE (dialog));
+		
+		gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (dialog->priv->icons_view),
+					      (GtkTreePath *) l->data,
+					      NULL,
+					      TRUE,
+					      0.5, 0.0);
+		
+/*		gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->priv->icons_view),
+					 (GtkTreePath *) l->data,
+					 0,
+					 FALSE);
+					 
+		gtk_widget_grab_focus (dialog->priv->icons_view);		
+*/					      
+		g_list_foreach (l, (GFunc) gtk_tree_path_free, NULL);
+		g_list_free (l);
+	}
+}
+
+static void
+select_first_row (GladeNamedIconChooserDialog *dialog)
+{
+	GtkTreePath *path;
+
+	if (!dialog->priv->filter_model)
+		return;
+
+	path = gtk_tree_path_new_from_indices (0, -1);
+	gtk_tree_view_set_cursor (GTK_TREE_VIEW (dialog->priv->icons_view), path, NULL, FALSE);
+	gtk_tree_path_free (path);
+}
+
+static void
+pending_select_name_process (GladeNamedIconChooserDialog *dialog)
+{
+	ForEachFuncData *data;
+
+	g_assert (dialog->priv->icons_store != NULL);	
+	g_assert (dialog->priv->selection != NULL);
+
+	if (dialog->priv->pending_select_name)
+	{
+		
+		data = g_slice_new0 (ForEachFuncData);
+		
+		data->name = dialog->priv->pending_select_name;
+		data->do_select = TRUE;
+		data->do_activate = FALSE;
+		data->dialog = dialog;
+		
+		gtk_tree_model_foreach (dialog->priv->filter_model,
+					scan_for_name_func,
+					data);
+		
+		g_free (dialog->priv->pending_select_name);
+		dialog->priv->pending_select_name = NULL;
+		
+		g_slice_free (ForEachFuncData, data);
+	
+	}
+	else
+	{
+		if (strlen (gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry))) == 0)
+		{
+			select_first_row (dialog);
+		}		
+	}
+	
+	centre_selected_row (dialog);
+}
+
+static gboolean
+is_standard_icon_name (const gchar *icon_name)
+{
+	GQuark quark;
+	
+	quark = g_quark_try_string (icon_name);
+	
+	if (quark == 0)
+		return FALSE;
+
+	return (g_hash_table_lookup (standard_icon_quarks, GUINT_TO_POINTER (quark)) != NULL);
+
+}
+
+static void
+cleanup_after_load (GladeNamedIconChooserDialog *dialog)
+{
+	GDK_THREADS_ENTER ();
+
+	dialog->priv->load_id = 0;
+	
+	pending_select_name_process (dialog);
+
+	set_busy_cursor (dialog, FALSE);
+	
+	GDK_THREADS_LEAVE ();
+}
+
+static void
+chooser_set_model (GladeNamedIconChooserDialog *dialog)
+{
+
+	/* filter model */
+	dialog->priv->filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (dialog->priv->icons_store), NULL);	
+	
+	gtk_tree_model_filter_set_visible_func  (GTK_TREE_MODEL_FILTER (dialog->priv->filter_model),
+						(GtkTreeModelFilterVisibleFunc) filter_visible_func,
+						 dialog,
+						 NULL);
+	
+	gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->priv->icons_view), dialog->priv->filter_model);
+	g_object_unref (dialog->priv->filter_model);
+	
+	gtk_entry_completion_set_model (dialog->priv->entry_completion, GTK_TREE_MODEL (dialog->priv->icons_store));
+	gtk_entry_completion_set_text_column (dialog->priv->entry_completion, ICONS_NAME_COLUMN);
+	
+	gtk_tree_view_set_search_column	(GTK_TREE_VIEW (dialog->priv->icons_view), ICONS_NAME_COLUMN);
+		 
+	dialog->priv->icons_loaded = TRUE;   
+}
+
+typedef struct
+{
+	gchar *name;
+	gint  context;
+} IconData;
+
+static gint
+icon_data_compare (IconData *a, IconData *b)
+{
+	return g_ascii_strcasecmp (a->name, b->name);
+}
+
+static gboolean
+reload_icons (GladeNamedIconChooserDialog *dialog)
+{
+	GtkListStore *store = dialog->priv->icons_store;
+	GtkTreeIter   iter;
+	guint         i;
+	GList        *l, *icons = NULL;
+
+	GDK_THREADS_ENTER ();
+
+	/* retrieve icon names from each context */
+	for (i = 0; i < G_N_ELEMENTS (standard_contexts); i++) {
+
+		GList *icons_in_context = gtk_icon_theme_list_icons (dialog->priv->icon_theme,
+								     standard_contexts[i].name);
+
+		for (l = icons_in_context; l; l = l->next) {
+
+			IconData *data = g_slice_new (IconData);
+
+			data->name = (gchar *) l->data;
+			data->context = i;
+
+			icons = g_list_prepend (icons, data);
+		}
+		
+		g_list_free (icons_in_context);
+	} 
+	
+	/* sort icon names */
+	icons = g_list_sort (icons, (GCompareFunc) icon_data_compare);
+
+	/* put into to model */
+	for (l = icons; l; l = l->next) {
+	
+		IconData *data = (IconData *) l->data;
+		
+		gtk_list_store_append (store, &iter);
+		gtk_list_store_set (store, &iter,
+				    ICONS_CONTEXT_COLUMN,  data->context,
+				    ICONS_STANDARD_COLUMN, is_standard_icon_name (data->name), 
+				    ICONS_NAME_COLUMN,     data->name,
+			    	    -1);
+		
+		g_free (data->name);
+		g_slice_free (IconData, data);
+	}	
+	
+	g_list_free (icons);
+	
+	chooser_set_model (dialog);	
+	
+	GDK_THREADS_LEAVE ();	
+	
+	return FALSE;
+}
+
+static void
+change_icon_theme (GladeNamedIconChooserDialog *dialog)
+{
+	if (dialog->priv->icon_theme == NULL)
+		dialog->priv->icon_theme = get_icon_theme_for_widget (GTK_WIDGET (dialog));
+
+	gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->priv->icons_view), NULL);
+	gtk_list_store_clear (dialog->priv->icons_store);
+
+	set_busy_cursor (dialog, TRUE);
+
+	dialog->priv->load_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 300,
+						 (GSourceFunc) reload_icons,
+						 dialog,
+						 (GDestroyNotify) cleanup_after_load);
+
+}
+
+static void
+glade_named_icon_chooser_dialog_screen_changed (GtkWidget *widget,
+					   	GdkScreen *previous_screen)
+{
+	GladeNamedIconChooserDialog *dialog;
+	
+	dialog = GLADE_NAMED_ICON_CHOOSER_DIALOG (widget);
+
+	if (GTK_WIDGET_CLASS (glade_named_icon_chooser_dialog_parent_class)->screen_changed)
+		GTK_WIDGET_CLASS (glade_named_icon_chooser_dialog_parent_class)->screen_changed (widget, previous_screen);
+
+	if (GTK_WIDGET_MAPPED (widget))
+		change_icon_theme (dialog);
+
+}
+
+static GtkWidget*
+create_icons_view (GladeNamedIconChooserDialog *dialog)
+{
+	GtkTreeView *view;
+	GtkTreeViewColumn *column;
+	GtkCellRenderer *pixbuf_renderer, *text_renderer;
+	
+	view = GTK_TREE_VIEW (gtk_tree_view_new ());
+	
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_min_width (column, 56);	
+	gtk_tree_view_column_set_title (column, NULL);
+	pixbuf_renderer = gtk_cell_renderer_pixbuf_new ();	
+
+	gtk_tree_view_column_pack_start (column,
+					 pixbuf_renderer,
+					 TRUE);
+					 
+	gtk_tree_view_column_set_attributes (column, 
+					     pixbuf_renderer,
+					     "icon-name", ICONS_NAME_COLUMN,
+					     NULL);
+
+	gtk_tree_view_append_column (view, column);	
+	g_object_set (pixbuf_renderer,
+		      "xpad", 2,
+		      "xalign", 1.0,
+		      "stock-size",GTK_ICON_SIZE_MENU,
+		      NULL);
+	
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_title (column, "Name");
+	text_renderer = gtk_cell_renderer_text_new ();
+	g_object_set (G_OBJECT (text_renderer),
+		      "ellipsize", PANGO_ELLIPSIZE_END, 
+		      "yalign", 0.0,
+		      NULL);
+	
+	gtk_tree_view_column_pack_start (column,
+					 text_renderer,
+					 TRUE);
+
+	gtk_tree_view_column_set_attributes (column, 
+					     text_renderer,
+					     "text", ICONS_NAME_COLUMN,
+					     NULL);	
+						   
+						           
+	gtk_tree_view_append_column (view, column);
+	gtk_tree_view_column_set_expand (column, TRUE);
+	gtk_tree_view_column_set_resizable (column, FALSE);
+	
+	gtk_tree_view_set_headers_visible (view, FALSE);
+	
+	gtk_tree_view_set_enable_search (view, TRUE);
+	gtk_tree_view_set_search_equal_func (view,
+					     (GtkTreeViewSearchEqualFunc) search_equal_func,
+					     dialog,
+					     NULL);
+	
+	g_signal_connect (view, "row-activated",
+			  G_CALLBACK (icons_row_activated_cb),
+			  dialog);	
+	
+	g_signal_connect (gtk_tree_view_get_selection (view), "changed",
+			  G_CALLBACK (icons_selection_changed_cb),
+			  dialog);
+			  
+	gtk_tree_selection_set_mode (gtk_tree_view_get_selection (view), GTK_SELECTION_BROWSE);
+	
+	dialog->priv->selection = gtk_tree_view_get_selection (view);
+	
+	gtk_tree_view_set_rules_hint (view, TRUE);	
+	
+	gtk_widget_show (GTK_WIDGET (view));
+	
+	return GTK_WIDGET (view);
+}
+
+/* sets the 'list-standard' state and refilters the icons model */
+static void
+button_toggled (GtkToggleButton *button, GladeNamedIconChooserDialog *dialog)
+{
+	dialog->priv->settings_list_standard = gtk_toggle_button_get_active (button);
+
+	if (dialog->priv->filter_model != NULL)
+		filter_icons_model (dialog);
+}
+
+static GHashTable*
+create_standard_icon_quarks ()
+{
+	GHashTable *table;
+	GQuark quark;
+	guint i;
+
+	table = g_hash_table_new (NULL, NULL);
+	
+	for (i = 0; i < G_N_ELEMENTS (standard_icon_names); i++)
+	{
+	
+		quark = g_quark_from_static_string (standard_icon_names[i]);
+	
+		g_hash_table_insert (table,
+				     GUINT_TO_POINTER (quark),
+				     GUINT_TO_POINTER (quark));
+	}
+	
+	return table;
+}
+
+static void
+glade_named_icon_chooser_dialog_style_set (GtkWidget *widget,
+			                   GtkStyle  *previous_style)
+{
+	if (gtk_widget_has_screen (widget) && GTK_WIDGET_MAPPED (widget))
+		change_icon_theme (GLADE_NAMED_ICON_CHOOSER_DIALOG (widget));
+}
+
+/* override GtkWidget::show_all since we have internal widgets we wish to keep
+ * hidden unless we decide otherwise, like the list-standard-icons-only checkbox.
+ */
+static void
+glade_named_icon_chooser_dialog_show_all (GtkWidget *widget)
+{
+	gtk_widget_show (widget);
+}
+
+/* Handler for GtkWindow::set-focus; this is where we save the last-focused
+ * widget on our toplevel.  See glade_named_icon_chooser_dialog_hierarchy_changed()
+ */
+static void
+glade_named_icon_chooser_dialog_set_focus (GtkWindow                    *window,
+					   GtkWidget                    *focus)
+{
+	
+	GTK_WINDOW_CLASS (glade_named_icon_chooser_dialog_parent_class)->set_focus (window, focus);
+
+	GLADE_NAMED_ICON_CHOOSER_DIALOG (window)->priv->last_focus_widget = gtk_window_get_focus (window);
+}
+
+static void
+glade_named_icon_chooser_dialog_finalize (GObject *object)
+{
+	GladeNamedIconChooserDialog *dialog = GLADE_NAMED_ICON_CHOOSER_DIALOG (object);
+	
+	if (dialog->priv->pending_select_name)
+	{
+		g_free (dialog->priv->pending_select_name);
+		dialog->priv->pending_select_name = NULL;
+	}
+	
+	G_OBJECT_CLASS (glade_named_icon_chooser_dialog_parent_class)->finalize (object);
+}
+
+static void
+glade_named_icon_chooser_dialog_map (GtkWidget *widget)
+{
+	GladeNamedIconChooserDialog *dialog = GLADE_NAMED_ICON_CHOOSER_DIALOG (widget);
+
+	GTK_WIDGET_CLASS (glade_named_icon_chooser_dialog_parent_class)->map (widget);
+	
+	settings_load (dialog);
+	
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->button),
+				      dialog->priv->settings_list_standard);
+
+	gtk_widget_grab_focus (dialog->priv->icons_view);
+}
+
+static void
+glade_named_icon_chooser_dialog_unmap (GtkWidget *widget)
+{
+	GladeNamedIconChooserDialog *dialog = GLADE_NAMED_ICON_CHOOSER_DIALOG (widget);
+
+	settings_save (dialog);
+
+	GTK_WIDGET_CLASS (glade_named_icon_chooser_dialog_parent_class)->unmap (widget);
+}
+
+/* we load the icons in expose() because we want the widget
+ * to be fully painted before loading begins
+ */ 
+static gboolean
+glade_named_icon_chooser_dialog_expose_event (GtkWidget      *widget,
+					      GdkEventExpose *event)
+{
+	GladeNamedIconChooserDialog *dialog = GLADE_NAMED_ICON_CHOOSER_DIALOG (widget);
+	gboolean retval;
+
+	retval = GTK_WIDGET_CLASS (glade_named_icon_chooser_dialog_parent_class)->expose_event (widget,
+												event);
+	if (!dialog->priv->icons_loaded)
+	{
+		change_icon_theme (GLADE_NAMED_ICON_CHOOSER_DIALOG (widget));
+		dialog->priv->icons_loaded = TRUE;
+	}
+
+	return retval;
+}
+
+static void
+response_cb (GtkDialog *dialog,
+	     gint       response_id)
+{
+	GladeNamedIconChooserDialogPrivate *priv;
+
+	priv = GLADE_NAMED_ICON_CHOOSER_DIALOG_GET_PRIVATE (dialog);
+
+	/* Act only on response IDs we recognize */
+	if (!(response_id == GTK_RESPONSE_ACCEPT
+	    || response_id == GTK_RESPONSE_OK
+	    || response_id == GTK_RESPONSE_YES
+	    || response_id == GTK_RESPONSE_APPLY))
+		return;
+		
+	if (!should_respond (GLADE_NAMED_ICON_CHOOSER_DIALOG (dialog)))
+	{
+		g_signal_stop_emission_by_name (dialog, "response");
+	}
+}
+
+/* we intercept the GladeNamedIconChooser::icon-activated signal and try to
+ * make the dialog emit a valid response signal
+ */
+static void
+icon_activated_cb (GladeNamedIconChooserDialog *dialog)
+{
+	GList *children, *l;
+
+	children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
+
+	for (l = children; l; l = l->next)
+	{
+		GtkWidget *widget;
+		gint response_id;
+
+		widget = GTK_WIDGET (l->data);
+		response_id = gtk_dialog_get_response_for_widget (GTK_DIALOG (dialog), widget);
+
+		if (response_id == GTK_RESPONSE_ACCEPT ||
+		    response_id == GTK_RESPONSE_OK     ||
+		    response_id == GTK_RESPONSE_YES    ||
+		    response_id == GTK_RESPONSE_APPLY)
+		{
+		        g_list_free (children);
+		        
+		        gtk_dialog_response (GTK_DIALOG (dialog), response_id);
+		        
+		        return;
+		}
+	}
+	g_list_free (children);
+}
+
+/* we intercept the GladeNamedIconChooser::selection-changed signal and try to
+ * make the affirmative response button insensitive when the selection is empty 
+ */
+static void
+selection_changed_cb (GladeNamedIconChooserDialog *dialog)
+{
+	GList *children, *l;
+	gchar *icon_name;
+
+	children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
+
+	for (l = children; l; l = l->next)
+	{
+		GtkWidget *widget;
+		gint response_id;
+
+		widget = GTK_WIDGET (l->data);
+		response_id = gtk_dialog_get_response_for_widget (GTK_DIALOG (dialog), widget);
+
+		if (response_id == GTK_RESPONSE_ACCEPT ||
+		    response_id == GTK_RESPONSE_OK     ||
+		    response_id == GTK_RESPONSE_YES    ||
+		    response_id == GTK_RESPONSE_APPLY)
+		{
+			icon_name = glade_named_icon_chooser_dialog_get_icon_name (dialog);
+			
+		        gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+		        				   response_id,
+		        				   icon_name != NULL);
+		        g_free (icon_name);
+		        g_list_free (children);	 
+		        return;
+		}
+	}
+	g_list_free (children);
+}
+
+static void
+glade_named_icon_chooser_dialog_init (GladeNamedIconChooserDialog *dialog)
+{
+	GtkWidget *contents;
+	GtkWidget *hbox;
+	GtkWidget *vbox;
+	GtkWidget *sw;
+	GtkWidget *label;
+	GtkWidget *hpaned;
+	GtkSizeGroup *group;
+	
+	dialog->priv = GLADE_NAMED_ICON_CHOOSER_DIALOG_GET_PRIVATE (dialog);
+	
+	dialog->priv->filter_model = NULL;
+	dialog->priv->icons_store = NULL;
+	dialog->priv->context_id = -1;
+	dialog->priv->pending_select_name = NULL;
+	dialog->priv->last_focus_widget = NULL;
+	dialog->priv->icons_loaded = FALSE;
+	
+
+	gtk_window_set_title (GTK_WINDOW (dialog), _("Named Icon Chooser"));
+	
+	gtk_window_set_default_size (GTK_WINDOW (dialog), 610, 480);
+	
+	gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);	
+
+	gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 12);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 12);
+	gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area), 0);
+	gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
+
+	/* We do a signal connection here rather than overriding the method in
+	 * class_init because GtkDialog::response is a RUN_LAST signal.  We want *our*
+	 * handler to be run *first*, regardless of whether the user installs response
+	 * handlers of his own.
+	*/	
+	g_signal_connect (dialog, "response",
+			 G_CALLBACK (response_cb),
+			 NULL);
+			 
+	g_signal_connect (dialog, "icon-activated",
+			  G_CALLBACK (icon_activated_cb),
+			  NULL);
+			  
+	g_signal_connect (dialog, "selection-changed",
+			  G_CALLBACK (selection_changed_cb),
+			  NULL);
+
+	
+	if (standard_icon_quarks == NULL)
+		standard_icon_quarks = create_standard_icon_quarks ();
+	
+	
+	gtk_widget_push_composite_child ();
+	
+	contents = gtk_vbox_new (FALSE, 6);
+	gtk_widget_show (contents);	
+	
+	label = gtk_label_new_with_mnemonic (_("Icon _Name:"));
+	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+	gtk_widget_show (label);
+	
+	dialog->priv->entry = gtk_entry_new ();
+	gtk_entry_set_activates_default (GTK_ENTRY (dialog->priv->entry), TRUE);
+	gtk_entry_set_width_chars (GTK_ENTRY (dialog->priv->entry), 40);
+	g_object_set (G_OBJECT (dialog->priv->entry), "truncate-multiline", TRUE, NULL);
+	g_signal_connect (G_OBJECT (dialog->priv->entry), "changed",
+			  G_CALLBACK (changed_text_handler), dialog);
+	g_signal_connect (G_OBJECT (dialog->priv->entry), "insert-text",
+			  G_CALLBACK (insert_text_handler), dialog);
+	gtk_widget_show (dialog->priv->entry);
+
+	dialog->priv->entry_completion = gtk_entry_completion_new ();
+	gtk_entry_set_completion (GTK_ENTRY (dialog->priv->entry), dialog->priv->entry_completion);
+	gtk_entry_completion_set_popup_completion (dialog->priv->entry_completion, FALSE);
+	gtk_entry_completion_set_inline_completion (dialog->priv->entry_completion, TRUE);
+	
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->priv->entry);
+	
+	hbox = gtk_hbox_new (FALSE, 12);
+	gtk_widget_show (hbox);
+	
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);	
+	gtk_box_pack_start (GTK_BOX (hbox), dialog->priv->entry, TRUE, TRUE, 0);	
+	gtk_box_pack_start (GTK_BOX (contents), hbox, FALSE, FALSE, 6);
+
+	hpaned = gtk_hpaned_new ();
+	gtk_paned_set_position (GTK_PANED (hpaned), 150);
+	gtk_widget_show (hpaned);	
+
+	dialog->priv->contexts_view = create_contexts_view (dialog);
+	dialog->priv->icons_view  = create_icons_view (dialog);
+	
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_widget_show (vbox);
+
+	group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+
+	label = gtk_label_new_with_mnemonic ("C_ontexts:");
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->priv->contexts_view);
+	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+	gtk_size_group_add_widget (group, label);
+	gtk_widget_show (label);	
+	
+	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);		
+	
+	sw = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); 
+	gtk_widget_show (sw);
+
+	gtk_container_add (GTK_CONTAINER (sw), dialog->priv->contexts_view);
+	gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);	
+	gtk_paned_pack1 (GTK_PANED (hpaned), vbox, FALSE, FALSE);
+	
+	
+	vbox = gtk_vbox_new (FALSE, 6);
+	gtk_widget_show (vbox);	
+	
+	label = gtk_label_new_with_mnemonic ("Icon Na_mes:");
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->priv->icons_view);
+	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+	gtk_size_group_add_widget (group, label);	
+	gtk_widget_show (label);
+	
+	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+	
+	sw = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN); 
+	gtk_widget_show (sw);
+	
+	gtk_container_add (GTK_CONTAINER (sw), dialog->priv->icons_view);
+	gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);	
+	gtk_paned_pack2 (GTK_PANED (hpaned), vbox, TRUE, FALSE);
+	
+	gtk_box_pack_start (GTK_BOX (contents), hpaned, TRUE, TRUE, 0);	
+	
+	
+	g_object_unref (G_OBJECT (group));
+	
+	dialog->priv->button = gtk_check_button_new_with_mnemonic (_("_List standard icons only"));
+	gtk_widget_show (dialog->priv->button);
+	
+	g_signal_connect (dialog->priv->button, "toggled",
+			  G_CALLBACK (button_toggled),
+			  dialog);
+	
+	gtk_box_pack_start (GTK_BOX (contents), dialog->priv->button, FALSE, FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), contents, TRUE, TRUE, 0);
+					
+	gtk_widget_pop_composite_child ();
+	
+	/* underlying model */
+  	dialog->priv->icons_store = gtk_list_store_new (ICONS_N_COLUMNS,
+  		                                        G_TYPE_UINT,
+  		                                        G_TYPE_BOOLEAN, 
+  		                                        G_TYPE_STRING);
+  	                                        
+                                       
+}
+
+static void
+glade_named_icon_chooser_dialog_class_init (GladeNamedIconChooserDialogClass *klass)
+{
+	GObjectClass   *object_class;
+	GtkWidgetClass *widget_class;	
+	GtkWindowClass *window_class;
+
+	object_class = G_OBJECT_CLASS (klass);
+	widget_class = GTK_WIDGET_CLASS (klass);
+	window_class = GTK_WINDOW_CLASS (klass);
+	
+	object_class->finalize           = glade_named_icon_chooser_dialog_finalize;
+	
+	widget_class->map                = glade_named_icon_chooser_dialog_map;
+	widget_class->unmap              = glade_named_icon_chooser_dialog_unmap;
+	widget_class->expose_event       = glade_named_icon_chooser_dialog_expose_event;
+	widget_class->show_all           = glade_named_icon_chooser_dialog_show_all;
+	widget_class->style_set          = glade_named_icon_chooser_dialog_style_set;
+	widget_class->screen_changed     = glade_named_icon_chooser_dialog_screen_changed;
+	
+	window_class->set_focus          = glade_named_icon_chooser_dialog_set_focus;
+
+	/**
+	 * GladeNamedIconChooserDialog::icon-activated
+	 * @chooser: the object which received the signal
+	 *
+	 * This signal is emitted when the user "activates" an icon
+	 * in the named icon chooser.  This can happen by double-clicking on an item
+	 * in the recently used resources list, or by pressing
+	 * <keycap>Enter</keycap>.
+	*/
+	dialog_signals[ICON_ACTIVATED] =
+		g_signal_new ("icon-activated",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GladeNamedIconChooserDialogClass, icon_activated),
+			      NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+
+	/**
+	 * GladeNamedIconChooserDialog::selection-changed
+	 * @chooser: the object which received the signal
+	 *
+	 * This signal is emitted when there is a change in the set of
+	 * selected icon names.  This can happen when a user
+	 * modifies the selection with the mouse or the keyboard, or when
+	 * explicitely calling functions to change the selection.
+	*/
+	dialog_signals[SELECTION_CHANGED] =
+		g_signal_new ("selection-changed",
+		              G_TYPE_FROM_CLASS (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (GladeNamedIconChooserDialogClass, selection_changed),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__VOID,
+		              G_TYPE_NONE, 0);	
+	
+	
+	g_type_class_add_private (klass, sizeof (GladeNamedIconChooserDialogPrivate));
+}
+
+static gboolean
+should_respond (GladeNamedIconChooserDialog *dialog)
+{
+	gchar *icon_name;
+	
+	/* is there an icon selected? */
+	icon_name = glade_named_icon_chooser_dialog_get_icon_name (dialog);
+	if (!icon_name)
+		return FALSE;
+	
+	g_free (icon_name);			
+	return TRUE;
+}
+
+/* get's the name of the configuration file */
+static gchar *
+get_config_filename (void)
+{
+	return g_build_filename (g_get_user_config_dir (), "gladeui", "config", NULL);
+}
+
+/* get's the name of the directory that contains the config file */
+static char *
+get_config_dirname (void)
+{
+	return g_build_filename (g_get_user_config_dir (), "gladeui", NULL);
+}
+
+/* loads the configuration settings */
+static void
+settings_load (GladeNamedIconChooserDialog *dialog)
+{
+	GKeyFile *keyfile;
+	gboolean  success, boolean_value;
+	gchar    *filename;
+	GError   *error = NULL;	
+
+	keyfile = g_key_file_new ();
+
+	filename = get_config_filename ();
+	success = g_key_file_load_from_file (keyfile,
+				 	     filename,
+					     G_KEY_FILE_NONE,
+					     &error);    
+	g_free (filename);
+					    
+	if (!success)
+	{
+	
+		dialog->priv->settings_list_standard = DEFAULT_SETTING_LIST_STANDARD_ONLY;
+		
+		g_clear_error (&error);
+		g_key_file_free (keyfile);
+		return;	
+	}
+	
+	
+	boolean_value = g_key_file_get_boolean (keyfile,
+						"Named Icon Chooser",
+						"ListStandardOnly",
+						&error);
+	if (error)
+	{
+		dialog->priv->settings_list_standard = DEFAULT_SETTING_LIST_STANDARD_ONLY;	
+		g_clear_error (&error);
+	}
+	else
+	{
+		dialog->priv->settings_list_standard = boolean_value;	
+	}
+	
+	g_key_file_free (keyfile);
+}
+
+/* creates a GKeyFile based on the current settings */
+static GKeyFile *
+settings_to_keyfile (GladeNamedIconChooserDialog *dialog)
+{
+	GKeyFile *keyfile;
+	gboolean  retval;
+	gchar    *filename;
+	
+	keyfile = g_key_file_new ();
+		
+	filename = get_config_filename ();
+	retval = g_key_file_load_from_file (keyfile,
+					    get_config_filename (),
+					    G_KEY_FILE_NONE,
+					    NULL);
+	g_free (filename);
+
+	g_key_file_set_boolean (keyfile,
+				"Named Icon Chooser",
+				"ListStandardOnly",
+				dialog->priv->settings_list_standard);
+	
+	return keyfile;
+}
+
+/* serializes the the current configuration to the config file */
+static void
+settings_save  (GladeNamedIconChooserDialog *dialog)
+{
+	GKeyFile *keyfile;
+	gchar    *contents;
+	gsize     contents_length;
+	gchar    *filename = NULL, *dirname = NULL;
+	GError   *error = NULL;
+
+	keyfile = settings_to_keyfile (dialog);
+
+	contents = g_key_file_to_data (keyfile,
+				       &contents_length,
+				       &error);
+
+	if (error)
+		goto out;
+
+	filename = get_config_filename ();
+
+	if (!g_file_set_contents (filename, contents, contents_length, NULL))
+	{
+		gchar *dirname;
+		gint saved_errno;
+
+		dirname = get_config_dirname ();
+		if (g_mkdir_with_parents (dirname, 0700) != 0) /* 0700 per the XDG basedir spec */
+		{
+		
+	  		saved_errno = errno;
+	  		g_set_error (&error,
+				     G_FILE_ERROR,
+				     g_file_error_from_errno (saved_errno),
+				     _("Could not create directory: %s"),
+				     dirname);
+	  		goto out;
+		}
+
+		if (!g_file_set_contents (filename, contents, contents_length, &error))
+		{
+			goto out;
+		}
+	}
+
+	out:
+
+	g_free (contents);
+	g_free (dirname);
+	g_free (filename);
+	g_clear_error (&error);
+	g_key_file_free (keyfile);
+}
+
+static GtkWidget *
+glade_named_icon_chooser_dialog_new_valist (const gchar      *title,
+					    GtkWindow        *parent,
+					    const gchar      *first_button_text,
+					    va_list           varargs)
+{
+	GtkWidget *result;
+	const char *button_text = first_button_text;
+	gint response_id;
+
+	result = g_object_new (GLADE_TYPE_NAMED_ICON_CHOOSER_DIALOG,
+	                       "title", title,
+	                       "transient-for", parent,
+	                       NULL);
+
+	while (button_text)
+	{
+		response_id = va_arg (varargs, gint);
+		gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
+		button_text = va_arg (varargs, const gchar *);
+	}
+
+	return result;
+}
+
+/**
+ * glade_named_icon_chooser_dialog_new:
+ * @title: Title of the dialog, or %NULL
+ * @parent: Transient parent of the dialog, or %NULL,
+ * @first_button_text: stock ID or text to go in the first button, or %NULL
+ * @Varargs: response ID for the first button, then additional (button, id)
+ *   pairs, ending with %NULL
+ *
+ * Creates a new #GladeNamedIconChooserDialog.  This function is analogous to
+ * gtk_dialog_new_with_buttons().
+ *
+ * Return value: a new #GladeNamedIconChooserDialog
+ */
+GtkWidget *
+glade_named_icon_chooser_dialog_new (const gchar      *title,
+				     GtkWindow        *parent,
+				     const gchar      *first_button_text,
+				     ...)
+{
+	GtkWidget *result;
+	va_list varargs;
+
+	va_start (varargs, first_button_text);
+	result = glade_named_icon_chooser_dialog_new_valist (title,
+						             parent,
+						             first_button_text,
+						             varargs);
+	va_end (varargs);
+
+	return result;
+}
--- /dev/null	2007-04-21 01:08:51.000000000 +0200
+++ gladeui/glade-named-icon-chooser-dialog.h	2007-07-07 00:29:21.000000000 +0200
@@ -0,0 +1,76 @@
+/*
+ * glade-named-icon-chooser-dialog.h - Named icon chooser dialog
+ *
+ * Copyright (C) 2007 Vincent Geddes
+ *
+ * Author:  Vincent Geddes <vgeddes@gnome.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANNAMED_ICON_CHOOSERILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GLADE_NAMED_ICON_CHOOSER_DIALOG_H__
+#define __GLADE_NAMED_ICON_CHOOSER_DIALOG_H__
+
+#include <gtk/gtkdialog.h>
+
+G_BEGIN_DECLS
+
+#define GLADE_TYPE_NAMED_ICON_CHOOSER_DIALOG		  (glade_named_icon_chooser_dialog_get_type ())
+#define GLADE_NAMED_ICON_CHOOSER_DIALOG(obj)		  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_NAMED_ICON_CHOOSER_DIALOG, GladeNamedIconChooserDialog))
+#define GLADE_IS_NAMED_ICON_CHOOSER_DIALOG(obj)		  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_NAMED_ICON_CHOOSER_DIALOG))
+#define GLADE_NAMED_ICON_CHOOSER_DIALOG_CLASS(klass)	  (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_NAMED_ICON_CHOOSER_DIALOG, GladeNamedIconChooserDialogClass))
+#define GLADE_IS_NAMED_ICON_CHOOSER_DIALOG_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_NAMED_ICON_CHOOSER_DIALOG))
+#define GLADE_NAMED_ICON_CHOOSER_DIALOG_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GLADE_TYPE_NAMED_ICON_CHOOSER_DIALOG, GladeNamedIconChooserDialogClass))
+
+typedef struct _GladeNamedIconChooserDialog        GladeNamedIconChooserDialog;
+typedef struct _GladeNamedIconChooserDialogPrivate GladeNamedIconChooserDialogPrivate;
+typedef struct _GladeNamedIconChooserDialogClass   GladeNamedIconChooserDialogClass;
+
+struct _GladeNamedIconChooserDialog
+{
+	GtkDialog parent_instance;
+  
+	GladeNamedIconChooserDialogPrivate *priv;
+};
+
+struct _GladeNamedIconChooserDialogClass
+{
+	GtkDialogClass parent_class;
+	
+	void  (* icon_activated)      (GladeNamedIconChooserDialog *dialog);
+	
+	void  (* selection_changed)   (GladeNamedIconChooserDialog *dialog);
+};
+
+GType       glade_named_icon_chooser_dialog_get_type       (void) G_GNUC_CONST;
+
+GtkWidget  *glade_named_icon_chooser_dialog_new            (const gchar      *title,
+					                    GtkWindow        *parent,
+					                    const gchar      *first_button_text,
+					                    ...) G_GNUC_NULL_TERMINATED;
+
+gchar      *glade_named_icon_chooser_dialog_get_icon_name  (GladeNamedIconChooserDialog *chooser);
+
+void        glade_named_icon_chooser_dialog_set_icon_name  (GladeNamedIconChooserDialog *chooser,
+						            const gchar                 *icon_name);
+
+gboolean    glade_named_icon_chooser_dialog_set_context    (GladeNamedIconChooserDialog *chooser,
+						            const gchar                 *context);
+
+gchar      *glade_named_icon_chooser_dialog_get_context    (GladeNamedIconChooserDialog *chooser);
+
+G_END_DECLS
+
+#endif /* __GLADE_NAMED_ICON_CHOOSER_DIALOG_H__ */
--- /dev/null	2007-04-21 01:08:51.000000000 +0200
+++ gladeui/icon-naming-spec.c	2007-07-07 00:54:24.000000000 +0200
@@ -0,0 +1,337 @@
+/*
+ * icon-naming-spec.c - freedesktop.org icon naming specification
+ *
+ * Copyright (C) 2007 Vincent Geddes
+ *
+ * Authors:  Vincent Geddes <vgeddes@gnome.org>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/* 
+ * Icon Naming Specification: http://standards.freedesktop.org/icon-naming-spec
+ *
+*/
+
+#include <glib/gi18n-lib.h>
+
+/* Standard Contexts */
+static const struct {
+	const char  *name;
+	const char  *title;
+} standard_contexts[] = {
+	{ "Actions",        N_("Actions")        },
+	{ "Applications",   N_("Applications")   },
+	{ "Categories",     N_("Categories")     },
+	{ "Devices",        N_("Devices")        },
+	{ "Emblems",        N_("Emblems")        },
+	{ "Emotes",         N_("Emotes")         },
+	{ "International",  N_("International")  },
+	{ "MimeTypes",      N_("MIME Types")     },
+	{ "Places",         N_("Places")         },
+	{ "Status",         N_("Status")         },
+};
+
+/* Standard Icon Names */
+static const char* const standard_icon_names[] =
+{  
+  /* Action Icons */
+  "address-book-new",
+  "application-exit",
+  "appointment-new",
+  "contact-new",
+  "dialog-cancel",
+  "dialog-close",
+  "dialog-ok",
+  "document-new",
+  "document-open",
+  "document-open-recent",
+  "document-page-setup",
+  "document-print",
+  "document-print-preview",
+  "document-properties",
+  "document-revert",
+  "document-save",
+  "document-save-as",
+  "edit-copy",
+  "edit-cut",
+  "edit-delete",
+  "edit-find",
+  "edit-find-replace",
+  "edit-paste",
+  "edit-redo",
+  "edit-select-all",
+  "edit-undo",
+  "folder-new",
+  "format-indent-less",
+  "format-indent-more",
+  "format-justify-center",
+  "format-justify-fill",
+  "format-justify-left",
+  "format-justify-right",
+  "format-text-direction-ltr",
+  "format-text-direction-rtl",
+  "format-text-bold",
+  "format-text-italic",
+  "format-text-underline",
+  "format-text-strikethrough",
+  "go-bottom",
+  "go-down",
+  "go-first",
+  "go-home",
+  "go-jump",
+  "go-last",
+  "go-next",
+  "go-previous",
+  "go-top",
+  "go-up",
+  "help-about",
+  "help-contents",
+  "help-faq",
+  "insert-image",
+  "insert-link",
+  "insert-object",
+  "insert-text",
+  "list-add",
+  "list-remove",
+  "mail-forward",
+  "mail-mark-important",
+  "mail-mark-junk",
+  "mail-mark-notjunk",
+  "mail-mark-read",
+  "mail-mark-unread",
+  "mail-message-new",
+  "mail-reply-all",
+  "mail-reply-sender",
+  "mail-send",
+  "mail-send-receive",
+  "media-eject",
+  "media-playback-pause",
+  "media-playback-start",
+  "media-playback-stop",
+  "media-record",
+  "media-seek-backward",
+  "media-seek-forward",
+  "media-skip-backward",
+  "media-skip-forward",
+  "object-flip-horizontal",
+  "object-flip-vertical",
+  "object-rotate-left",
+  "object-rotate-right",
+  "system-lock-screen",
+  "system-log-out",
+  "system-run",
+  "system-search",
+  "tools-check-spelling",
+  "view-fullscreen",
+  "view-refresh",
+  "view-restore", 
+  "view-sort-ascending",
+  "view-sort-descending",
+  "window-close",
+  "window-new",
+  "zoom-best-fit",
+  "zoom-in",
+  "zoom-original",
+  "zoom-out",
+
+  /* Application Icons */
+  "accessories-calculator",
+  "accessories-character-map",
+  "accessories-dictionary",
+  "accessories-text-editor",
+  "help-browser",
+  "multimedia-volume-control",
+  "preferences-desktop-accessibility",
+  "preferences-desktop-font",
+  "preferences-desktop-keyboard",
+  "preferences-desktop-locale",
+  "preferences-desktop-multimedia",
+  "preferences-desktop-screensaver",
+  "preferences-desktop-theme",
+  "preferences-desktop-wallpaper",
+  "system-file-manager",
+  "system-software-update",
+  "utilities-system-monitor",
+  "utilities-terminal",
+
+  /* Category Icons */
+  "applications-accessories",
+  "applications-development",
+  "applications-engineering",
+  "applications-games",
+  "applications-graphics",
+  "applications-internet",
+  "applications-multimedia",
+  "applications-office",
+  "applications-other",
+  "applications-science",
+  "applications-system",
+  "applications-utilities",
+  "preferences-desktop",
+  "preferences-desktop-peripherals",
+  "preferences-desktop-personal",
+  "preferences-other",
+  "preferences-system",
+  "preferences-system-network",
+  "system-help",
+
+  /* Device Icons */
+  "audio-card",
+  "audio-input-microphone",
+  "battery",
+  "camera-photo",
+  "camera-video",
+  "computer",
+  "drive-harddisk",
+  "drive-optical",
+  "drive-removable-media",
+  "input-gaming",
+  "input-keyboard",
+  "input-mouse",
+  "media-flash",
+  "media-floppy",
+  "media-optical", 
+  "media-tape",
+  "modem",
+  "multimedia-player",
+  "network-wired",
+  "network-wireless",
+  "printer",
+  "video-display",
+
+  /* Emblem Icons */
+  "emblem-default",
+  "emblem-documents",
+  "emblem-downloads",
+  "emblem-favorite",
+  "emblem-important",
+  "emblem-mail",
+  "emblem-photos",
+  "emblem-readonly",
+  "emblem-shared", 
+  "emblem-symbolic-link",
+  "emblem-synchronized",
+  "emblem-system",
+  "emblem-unreadable",
+
+  /* Emotion Icons */
+  "face-angel",
+  "face-crying",
+  "face-devil-grin",
+  "face-devil-sad",
+  "face-glasses",
+  "face-kiss",
+  "face-monkey",
+  "face-plain",
+  "face-sad",
+  "face-smile",
+  "face-smile-big",
+  "face-smirk",
+  "face-surprise",
+  "face-wink",
+
+  /* International Icons */
+  "flag-aa",
+
+  /* MIME Type Icons */
+  "application-x-executable",
+  "audio-x-generic",
+  "font-x-generic",
+  "image-x-generic",
+  "package-x-generic",
+  "text-html",
+  "text-x-generic",
+  "text-x-generic-template",
+  "text-x-script",
+  "video-x-generic",
+  "x-office-address-book",
+  "x-office-calendar",
+  "x-office-document",
+  "x-office-presentation",
+  "x-office-spreadsheet",
+
+  /* Place Icons */
+  "folder",
+  "folder-remote",
+  "network-server",
+  "network-workgroup",
+  "start-here",
+  "user-desktop",
+  "user-home",
+  "user-trash",
+
+  /* Status Icons */
+  "appointment-missed",
+  "appointment-soon",
+  "audio-volume-high",
+  "audio-volume-low",
+  "audio-volume-medium",
+  "audio-volume-muted",
+  "battery-caution",
+  "battery-low",
+  "dialog-error",
+  "dialog-information",
+  "dialog-password",
+  "dialog-question",
+  "dialog-warning",
+  "folder-drag-accept", 
+  "folder-open",
+  "folder-visiting",
+  "image-loading",
+  "image-missing",
+  "mail-attachment",
+  "mail-unread",
+  "mail-read",
+  "mail-replied",
+  "mail-signed",
+  "mail-signed-verified",
+  "media-playlist-repeat",
+  "media-playlist-shuffle",
+  "network-error", 
+  "network-idle",
+  "network-offline",
+  "network-receive",
+  "network-transmit",
+  "network-transmit-receive",
+  "printer-error",
+  "printer-printing",
+  "security-high",
+  "security-medium",
+  "security-low", 
+  "software-update-available",
+  "software-update-urgent",
+  "sync-error",
+  "sync-synchronizing",
+  "task-due",
+  "task-passed-due",
+  "user-away",
+  "user-idle",
+  "user-offline",
+  "user-online",
+  "user-trash-full",
+  "weather-clear",
+  "weather-clear-night",
+  "weather-few-clouds",
+  "weather-few-clouds-night",
+  "weather-fog",
+  "weather-overcast",
+  "weather-severe-alert",
+  "weather-showers",
+  "weather-showers-scattered",
+  "weather-snow",
+  "weather-storm",
+};
+
Index: gladeui/glade-editor-property.c
===================================================================
--- gladeui/glade-editor-property.c	(revision 1435)
+++ gladeui/glade-editor-property.c	(working copy)
@@ -38,6 +38,7 @@
 #include "glade-project.h"
 #include "glade-builtins.h"
 #include "glade-marshallers.h"
+#include "glade-named-icon-chooser-dialog.h"
 
 enum {
 	PROP_0,
@@ -1292,6 +1293,214 @@ glade_eprop_color_create_input (GladeEdi
 }
 
 /*******************************************************************************
+                        GladeEditorPropertyNamedIconClass
+ *******************************************************************************/
+typedef struct {
+	GladeEditorProperty  parent_instance;
+
+	GtkWidget           *entry;
+	gchar               *current_context;
+} GladeEPropNamedIcon;
+
+GLADE_MAKE_EPROP (GladeEPropNamedIcon, glade_eprop_named_icon)
+#define GLADE_TYPE_EPROP_NAMED_ICON            (glade_eprop_named_icon_get_type())
+#define GLADE_EPROP_NAMED_ICON(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_EPROP_NAMED_ICON, GladeEPropNamedIcon))
+#define GLADE_EPROP_NAMED_ICON_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_EPROP_NAMED_ICON, GladeEPropNamedIconClass))
+#define GLADE_IS_EPROP_NAMED_ICON(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_EPROP_NAMED_ICON))
+#define GLADE_IS_EPROP_NAMED_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_EPROP_NAMED_ICON))
+#define GLADE_EPROP_NAMED_ICON_GET_CLASS(o)    (G_TYPE_INSTANCE_GET_CLASS ((o), GLADE_EPROP_NAMED_ICON, GladeEPropNamedIconClass))
+
+
+static void
+glade_eprop_named_icon_finalize (GObject *object)
+{
+	/* Chain up */
+	G_OBJECT_CLASS (editor_property_class)->finalize (object);
+}
+
+static void
+glade_eprop_named_icon_load (GladeEditorProperty *eprop,
+			     GladeProperty       *property)
+{
+	GladeEPropNamedIcon *eprop_named_icon = GLADE_EPROP_NAMED_ICON (eprop);
+
+	/* Chain up first */
+	editor_property_class->load (eprop, property);
+	
+	if (property == NULL)
+		return;
+	
+	GtkEntry *entry = GTK_ENTRY (eprop_named_icon->entry);
+	const gchar *text = g_value_get_string (property->value);
+
+	gtk_entry_set_text (entry, text ? text : "");
+}
+
+static void
+glade_eprop_named_icon_changed_common (GladeEditorProperty *eprop,
+				       const gchar *text,
+				       gboolean use_command)
+{
+	GValue  *val;
+	gchar  *prop_text;
+
+	val = g_new0 (GValue, 1);
+	
+	g_value_init (val, G_TYPE_STRING);
+
+	glade_property_get (eprop->property, &prop_text);
+
+	/* Here we try not to modify the project state by not 
+	 * modifying a null value for an unchanged property.
+	 */
+	if (prop_text == NULL &&
+	    text && text[0] == '\0')
+		g_value_set_string (val, NULL);
+	else if (text == NULL &&
+		 prop_text && prop_text == '\0')
+		g_value_set_string (val, "");
+	else
+		g_value_set_string (val, text);
+
+	glade_editor_property_commit (eprop, val);
+	g_value_unset (val);
+	g_free (val);
+}
+
+static void
+glade_eprop_named_icon_changed (GtkWidget           *entry,
+			        GladeEditorProperty *eprop)
+{
+	gchar *text;
+
+	if (eprop->loading)
+		return;
+	
+	text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+	glade_eprop_named_icon_changed_common (eprop, text, eprop->use_command);
+	
+	g_free (text);
+}
+
+static gboolean
+glade_eprop_named_icon_focus_out (GtkWidget           *entry,
+				  GdkEventFocus       *event,
+				  GladeEditorProperty *eprop)
+{
+	glade_eprop_named_icon_changed (entry, eprop);
+	return FALSE;
+}
+
+static void 
+glade_eprop_named_icon_activate (GtkEntry *entry,
+				 GladeEPropNamedIcon *eprop)
+{
+	glade_eprop_named_icon_changed (GTK_WIDGET (entry), GLADE_EDITOR_PROPERTY (eprop));
+}
+
+static void
+chooser_response (GladeNamedIconChooserDialog *dialog,
+		  gint response_id,
+		  GladeEPropNamedIcon *eprop)
+{
+	gchar *icon_name;
+	
+	switch (response_id) {
+	
+	case GTK_RESPONSE_OK:
+	
+		g_free (eprop->current_context);
+		eprop->current_context = glade_named_icon_chooser_dialog_get_context (dialog);
+		icon_name = glade_named_icon_chooser_dialog_get_icon_name (dialog);
+		
+		gtk_entry_set_text (GTK_ENTRY (eprop->entry), icon_name);
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+					
+		g_free (icon_name);
+		
+		glade_eprop_named_icon_changed (eprop->entry, GLADE_EDITOR_PROPERTY (eprop));
+		
+		break;
+		
+	case GTK_RESPONSE_CANCEL:
+	
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+		break;
+	
+	case GTK_RESPONSE_HELP:
+	
+		break;
+		
+	case GTK_RESPONSE_DELETE_EVENT:
+		gtk_widget_destroy (GTK_WIDGET (dialog));
+	}		
+}
+
+
+static void
+glade_eprop_named_icon_show_chooser_dialog (GtkWidget           *button,
+				            GladeEditorProperty *eprop)
+{
+	GtkWidget *dialog;
+
+	dialog = glade_named_icon_chooser_dialog_new ("Select Named Icon",
+						       GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (eprop))),
+						       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+						       GTK_STOCK_OK, GTK_RESPONSE_OK,
+						       NULL);
+						       
+	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+	glade_named_icon_chooser_dialog_set_context   (GLADE_NAMED_ICON_CHOOSER_DIALOG (dialog), GLADE_EPROP_NAMED_ICON (eprop)->current_context);
+
+	glade_named_icon_chooser_dialog_set_icon_name (GLADE_NAMED_ICON_CHOOSER_DIALOG (dialog),
+						       gtk_entry_get_text (GTK_ENTRY (GLADE_EPROP_NAMED_ICON (eprop)->entry)));
+
+
+	g_signal_connect (dialog, "response",
+			  G_CALLBACK (chooser_response),
+			  eprop);	
+
+	gtk_widget_show (dialog);
+
+}
+
+static GtkWidget *
+glade_eprop_named_icon_create_input (GladeEditorProperty *eprop)
+{
+	GladeEPropNamedIcon *eprop_named_icon = GLADE_EPROP_NAMED_ICON (eprop);
+	GtkWidget       *hbox;
+
+	hbox = gtk_hbox_new (FALSE, 0);
+
+	eprop_named_icon->entry = gtk_entry_new ();
+	gtk_widget_show (eprop_named_icon->entry);
+	
+	eprop_named_icon->current_context = NULL;
+
+	gtk_box_pack_start (GTK_BOX (hbox), eprop_named_icon->entry, TRUE, TRUE, 0); 
+
+	g_signal_connect (G_OBJECT (eprop_named_icon->entry), "activate",
+			  G_CALLBACK (glade_eprop_named_icon_activate),
+			  eprop);
+	
+	g_signal_connect (G_OBJECT (eprop_named_icon->entry), "focus-out-event",
+			  G_CALLBACK (glade_eprop_named_icon_focus_out),
+			  eprop);
+
+	GtkWidget *button = gtk_button_new_with_label ("\342\200\246");
+	gtk_widget_show (button);
+	gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); 
+	g_signal_connect (button, "clicked",
+			  G_CALLBACK (glade_eprop_named_icon_show_chooser_dialog),
+			  eprop);
+
+	return hbox;
+}
+
+
+
+/*******************************************************************************
                         GladeEditorPropertyTextClass
  *******************************************************************************/
 typedef struct {
@@ -3740,7 +3949,11 @@ glade_editor_property_new (GladeProperty
 			 g_type_name (klass->pspec->value_type));
 
 	/* special case for resource specs which are hand specified in the catalog. */
-	if (klass->resource) type = GLADE_TYPE_EPROP_RESOURCE;
+	if (klass->resource)
+		type = GLADE_TYPE_EPROP_RESOURCE;
+	
+	if (strcmp (klass->id, "icon-name") == 0)
+		type = GLADE_TYPE_EPROP_NAMED_ICON;
 
 	/* Create and return the correct type of GladeEditorProperty */
 	eprop = g_object_new (type,
Index: gladeui/Makefile.am
===================================================================
--- gladeui/Makefile.am	(revision 1435)
+++ gladeui/Makefile.am	(working copy)
@@ -14,7 +14,7 @@ lib_LTLIBRARIES = libgladeui-1.la
 
 BUILT_SOURCES = glade-marshallers.c glade-marshallers.h
 
-EXTRA_DIST = glade-marshallers.list gladeui.rc.in
+EXTRA_DIST = glade-marshallers.list gladeui.rc.in icon-naming-spec.c
 
 # The glade-3 core library
 libgladeui_1_la_SOURCES = \
@@ -32,6 +32,8 @@ libgladeui_1_la_SOURCES = \
 	glade-palette-expander.c \
 	glade-design-layout.c \
 	glade-design-view.c \
+	glade-named-icon-chooser-dialog.c \
+	glade-named-icon-chooser-dialog.h \
 	glade-cursor.c \
 	glade-catalog.c \
 	glade-property.c \
Index: po/POTFILES.in
===================================================================
--- po/POTFILES.in	(revision 1435)
+++ po/POTFILES.in	(working copy)
@@ -36,6 +36,8 @@ gladeui/glade-widget-adaptor.c
 gladeui/glade-xml-utils.c
 gladeui/glade-inspector.c
 gladeui/glade-custom.c
+gladeui/glade-named-icon-chooser-dialog.c
+gladeui/icon-naming-spec.c
 
 # gtk plugin backend
 plugins/gtk+/glade-gtk.c
