glade3 r1987 - in trunk: . gladeui plugins/gtk+



Author: tvb
Date: Wed Oct 22 22:33:30 2008
New Revision: 1987
URL: http://svn.gnome.org/viewvc/glade3?rev=1987&view=rev

Log:

	* plugins/gtk+/Makefile.am, plugins/gtk+/glade-icon-sources.[ch]:
	new pspec and eprop for GtkIconSources in GtkIconFactories.

	* plugins/gtk+/glade-gtk.c, plugins/gtk+/gtk+.xml.in: Added load/save/set_property/string_from_value
	support for icon sources in icon factories.



Added:
   trunk/plugins/gtk+/glade-icon-sources.c
   trunk/plugins/gtk+/glade-icon-sources.h
Modified:
   trunk/ChangeLog
   trunk/gladeui/glade-editor-property.c
   trunk/plugins/gtk+/Makefile.am
   trunk/plugins/gtk+/glade-attributes.c
   trunk/plugins/gtk+/glade-gtk.c
   trunk/plugins/gtk+/glade-model-data.c
   trunk/plugins/gtk+/gtk+.xml.in

Modified: trunk/gladeui/glade-editor-property.c
==============================================================================
--- trunk/gladeui/glade-editor-property.c	(original)
+++ trunk/gladeui/glade-editor-property.c	Wed Oct 22 22:33:30 2008
@@ -290,7 +290,6 @@
 				   guint                  n_construct_properties,
 				   GObjectConstructParam *construct_properties)
 {
-	GtkRequisition       req = { -1, -1 };
 	GObject             *obj;
 	GladeEditorProperty *eprop;
 	GtkWidget           *hbox;
@@ -324,17 +323,13 @@
 	/* Create & setup label */
 	eprop->item_label = gtk_event_box_new ();
 	eprop->label      = gtk_label_new (NULL);
+	gtk_event_box_set_visible_window (GTK_EVENT_BOX (eprop->item_label), FALSE);
 
 	hbox = gtk_hbox_new (FALSE, 4);
 
 	gtk_label_set_line_wrap (GTK_LABEL(eprop->label), TRUE);
 	gtk_label_set_line_wrap_mode (GTK_LABEL(eprop->label), PANGO_WRAP_WORD_CHAR);
 
-	/* gtk_label_set_width_chars() was not working well :( */ 
-	gtk_label_set_text (GTK_LABEL (eprop->label), "xxxxxxxxxxxxxxx");
-	gtk_widget_size_request (eprop->label, &req);
-	gtk_widget_set_size_request(GTK_WIDGET(eprop->label), req.width, -1);
-
 	/* A Hack to that PANGO_WRAP_WORD_CHAR works nicely */
 	g_signal_connect (G_OBJECT (eprop->item_label), "size-request",
 			  G_CALLBACK (eprop_item_label_size_request), eprop);

Modified: trunk/plugins/gtk+/Makefile.am
==============================================================================
--- trunk/plugins/gtk+/Makefile.am	(original)
+++ trunk/plugins/gtk+/Makefile.am	Wed Oct 22 22:33:30 2008
@@ -24,14 +24,15 @@
 	$(AM_CFLAGS)
 
 libgladegtk_la_SOURCES     = glade-gtk.c glade-accels.c glade-attributes.c glade-convert.c fixed-bg.xpm \
-	glade-column-types.c  glade-model-data.c glade-text-button.c glade-cell-renderer-button.c
+	glade-column-types.c  glade-model-data.c glade-text-button.c glade-cell-renderer-button.c \
+	glade-icon-sources.c
 
 libgladegtk_la_LDFLAGS     = -module -avoid-version $(AM_LDFLAGS)
 libgladegtk_la_LIBADD      = $(libgladeui) $(GTK_LIBS)
 
 libgladegtkincludedir= $(includedir)/libgladeui-1.0/gladeui
 libgladegtkinclude_HEADERS = glade-gtk.h glade-accels.h glade-attributes.h glade-column-types.h glade-model-data.h \
-	glade-text-button.h glade-cell-renderer-button.h
+	glade-text-button.h glade-cell-renderer-button.h glade-icon-sources.h
 
 if PLATFORM_WIN32
 libgladegtk_la_LDFLAGS += -no-undefined

Modified: trunk/plugins/gtk+/glade-attributes.c
==============================================================================
--- trunk/plugins/gtk+/glade-attributes.c	(original)
+++ trunk/plugins/gtk+/glade-attributes.c	Wed Oct 22 22:33:30 2008
@@ -1012,7 +1012,6 @@
 	column = gtk_tree_view_column_new ();
 	gtk_tree_view_column_set_title (column, _("Value"));
 
-
 	/* Toggle renderer */
  	renderer = gtk_cell_renderer_toggle_new ();
 	g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
@@ -1024,7 +1023,8 @@
 	g_signal_connect (G_OBJECT (renderer), "toggled",
 			  G_CALLBACK (value_toggled), eprop);
 
-	/* Text renderer */
+
+	/* Button renderer */
  	renderer = glade_cell_renderer_button_new ();
 	g_object_set (G_OBJECT (renderer), 
 		      "editable", TRUE, 

Modified: trunk/plugins/gtk+/glade-gtk.c
==============================================================================
--- trunk/plugins/gtk+/glade-gtk.c	(original)
+++ trunk/plugins/gtk+/glade-gtk.c	Wed Oct 22 22:33:30 2008
@@ -30,6 +30,7 @@
 #include "glade-attributes.h"
 #include "glade-column-types.h"
 #include "glade-model-data.h"
+#include "glade-icon-sources.h"
 
 #include <gladeui/glade-editor-property.h>
 #include <gladeui/glade-base-editor.h>
@@ -8979,6 +8980,7 @@
 	g_value_init (&value, GLADE_TYPE_COLUMN_TYPE_LIST);
 	g_value_take_boxed (&value, g_list_reverse (types));
 	glade_property_set_value (property, &value);
+	g_value_unset (&value);
 }
 
 static void
@@ -9053,7 +9055,7 @@
 		}
 	}
 
-	if (data_tree->children && data_tree->children)
+	if (data_tree->children)
 		glade_widget_property_set (widget, "data", data_tree);
 
 	glade_model_data_tree_free (data_tree);
@@ -9076,7 +9078,6 @@
 }
 
 
-
 /*--------------------------- GtkTreeView ---------------------------------*/
 
 static void
@@ -9322,3 +9323,377 @@
 	column = GTK_TREE_VIEW_COLUMN (child);
 	gtk_tree_view_remove_column (view, column);
 }
+
+
+/*--------------------------- GtkIconFactory ---------------------------------*/
+#define GLADE_TAG_SOURCES   "sources"
+#define GLADE_TAG_SOURCE    "source"
+
+#define GLADE_TAG_STOCK_ID  "stock-id"
+#define GLADE_TAG_FILENAME  "filename"
+#define GLADE_TAG_DIRECTION "direction"
+#define GLADE_TAG_STATE     "state"
+#define GLADE_TAG_SIZE      "size"
+
+void
+glade_gtk_icon_factory_post_create (GladeWidgetAdaptor *adaptor,
+				    GObject *object, 
+				    GladeCreateReason reason)
+{
+	gtk_icon_factory_add_default (GTK_ICON_FACTORY (object));
+}
+
+static void
+glade_gtk_icon_factory_read_sources (GladeWidget  *widget, 
+				     GladeXmlNode *node)
+{
+	GladeIconSources *sources;
+	GtkIconSource    *source;
+	GladeXmlNode     *sources_node, *source_node;
+	GValue           *value;
+	GList            *list;
+	gchar            *current_icon_name = NULL;
+	GdkPixbuf        *pixbuf;
+
+	if ((sources_node = glade_xml_search_child (node, GLADE_TAG_SOURCES)) == NULL)
+		return;
+
+	sources = glade_icon_sources_new ();
+
+	/* Here we expect all icon sets to remain together in the list. */
+	for (source_node = glade_xml_node_get_children (sources_node); source_node;
+	     source_node = glade_xml_node_next (source_node))
+	{
+		gchar *icon_name;
+		gchar *str;
+
+		if (!glade_xml_node_verify (source_node, GLADE_TAG_SOURCE)) 
+			continue;
+
+		if (!(icon_name = 
+		      glade_xml_get_property_string_required (source_node, GLADE_TAG_STOCK_ID, NULL)))
+			continue;
+
+		if (!(str = glade_xml_get_property_string_required (source_node, GLADE_TAG_FILENAME, NULL)))
+		{
+			g_free (icon_name);
+			continue;
+		}
+
+		if (!current_icon_name || strcmp (current_icon_name, icon_name) != 0)
+			current_icon_name = (g_free (current_icon_name), g_strdup (icon_name));
+
+		source = gtk_icon_source_new ();
+		
+		/* Deal with the filename... */
+		value = glade_utils_value_from_string (GDK_TYPE_PIXBUF, str,
+						       widget->project, widget);
+		pixbuf = g_value_dup_object (value);
+		g_value_unset (value);
+		g_free (value);
+
+		gtk_icon_source_set_pixbuf (source, pixbuf);
+		g_object_unref (G_OBJECT (pixbuf));
+		g_free (str);
+
+		/* Now the attributes... */
+		if ((str = glade_xml_get_property_string (source_node, GLADE_TAG_DIRECTION)) != NULL)
+		{
+			GtkTextDirection direction =
+				glade_utils_enum_value_from_string (GTK_TYPE_TEXT_DIRECTION, str);
+			gtk_icon_source_set_direction_wildcarded (source, FALSE);
+			gtk_icon_source_set_direction (source, direction);
+			g_free (str);
+		}
+
+		if ((str = glade_xml_get_property_string (source_node, GLADE_TAG_SIZE)) != NULL)
+		{
+			GtkIconSize size = 
+				glade_utils_enum_value_from_string (GTK_TYPE_ICON_SIZE, str);
+			gtk_icon_source_set_size_wildcarded (source, FALSE);
+			gtk_icon_source_set_size (source, size);
+			g_free (str);
+		}
+
+		if ((str = glade_xml_get_property_string (source_node, GLADE_TAG_STATE)) != NULL)
+		{
+			GtkStateType state =
+				glade_utils_enum_value_from_string (GTK_TYPE_STATE_TYPE, str);
+			gtk_icon_source_set_state_wildcarded (source, FALSE);
+			gtk_icon_source_set_state (source, state);
+			g_free (str);
+		}
+
+		if ((list = g_hash_table_lookup (sources->sources, g_strdup (current_icon_name))) != NULL)
+			list = g_list_prepend (list, source);
+		else
+		{
+			list = g_list_append (NULL, source);
+			g_hash_table_insert (sources->sources, g_strdup (current_icon_name), list);
+		}
+	}
+
+	if (g_hash_table_size (sources->sources) > 0)
+		glade_widget_property_set (widget, "sources", sources);
+
+	glade_icon_sources_free (sources);
+}
+
+void
+glade_gtk_icon_factory_read_widget (GladeWidgetAdaptor *adaptor,
+				    GladeWidget        *widget,
+				    GladeXmlNode       *node)
+{
+	if (!glade_xml_node_verify 
+	    (node, GLADE_XML_TAG_WIDGET (glade_project_get_format (widget->project))))
+		return;
+
+	/* First chain up and read in any normal properties.. */
+        GWA_GET_CLASS (G_TYPE_OBJECT)->read_widget (adaptor, widget, node);
+
+	glade_gtk_icon_factory_read_sources (widget, node);
+}
+
+typedef struct {
+	GladeXmlContext *context;
+	GladeXmlNode    *node;
+} SourceWriteTab;
+
+static void
+write_icon_sources (gchar          *icon_name,
+		    GList          *sources,
+		    SourceWriteTab *tab)
+{
+	GladeXmlNode  *source_node;
+	GtkIconSource *source;
+	GList         *l;
+	gchar         *string;
+
+	GdkPixbuf     *pixbuf;
+
+	for (l = sources; l; l = l->next)
+	{
+		source = l->data;
+
+		source_node = glade_xml_node_new (tab->context, GLADE_TAG_SOURCE);
+		glade_xml_node_append_child (tab->node, source_node);
+
+		glade_xml_node_set_property_string (source_node, GLADE_TAG_STOCK_ID, icon_name);
+
+		if (!gtk_icon_source_get_direction_wildcarded (source))
+		{
+			GtkTextDirection direction = gtk_icon_source_get_direction (source);
+			string = glade_utils_enum_string_from_value (GTK_TYPE_TEXT_DIRECTION, direction);
+			glade_xml_node_set_property_string (source_node, GLADE_TAG_DIRECTION, string);
+			g_free (string);
+		}
+
+		if (!gtk_icon_source_get_size_wildcarded (source))
+		{
+			GtkIconSize size = gtk_icon_source_get_size (source);
+			string = glade_utils_enum_string_from_value (GTK_TYPE_ICON_SIZE, size);
+			glade_xml_node_set_property_string (source_node, GLADE_TAG_SIZE, string);
+			g_free (string);
+		}
+
+		if (!gtk_icon_source_get_state_wildcarded (source))
+		{
+			GtkStateType state = gtk_icon_source_get_size (source);
+			string = glade_utils_enum_string_from_value (GTK_TYPE_STATE_TYPE, state);
+			glade_xml_node_set_property_string (source_node, GLADE_TAG_STATE, string);
+			g_free (string);
+		}
+
+		pixbuf = gtk_icon_source_get_pixbuf (source);
+		string = g_object_get_data (G_OBJECT (pixbuf), "GladeFileName");
+
+		glade_xml_node_set_property_string (source_node, 
+						    GLADE_TAG_FILENAME, 
+						    string);
+	}
+}
+
+
+static void
+glade_gtk_icon_factory_write_sources (GladeWidget      *widget, 
+				      GladeXmlContext  *context,
+				      GladeXmlNode     *node)
+{
+	GladeXmlNode     *sources_node;
+	GladeIconSources *sources = NULL;
+	SourceWriteTab    tab;
+
+	glade_widget_property_get (widget, "sources", &sources);
+	if (!sources)
+		return;
+
+	sources_node = glade_xml_node_new (context, GLADE_TAG_SOURCES);
+
+	tab.context = context;
+	tab.node    = sources_node;
+	g_hash_table_foreach (sources->sources, (GHFunc)write_icon_sources, &tab);
+
+	if (!glade_xml_node_get_children (sources_node))
+		glade_xml_node_delete (sources_node);
+	else
+		glade_xml_node_append_child (node, sources_node);
+
+}
+
+
+void
+glade_gtk_icon_factory_write_widget (GladeWidgetAdaptor *adaptor,
+				     GladeWidget        *widget,
+				     GladeXmlContext    *context,
+				     GladeXmlNode       *node)
+{
+	if (!glade_xml_node_verify
+	    (node, GLADE_XML_TAG_WIDGET (glade_project_get_format (widget->project))))
+		return;
+
+	/* First chain up and write all the normal properties.. */
+        GWA_GET_CLASS (G_TYPE_OBJECT)->write_widget (adaptor, widget, context, node);
+
+	glade_gtk_icon_factory_write_sources (widget, context, node);
+}
+
+static void
+apply_icon_sources (gchar          *icon_name,
+		    GList          *sources,
+		    GtkIconFactory *factory)
+{
+	GtkIconSource *source;
+	GtkIconSet    *set;
+	GList         *l;
+
+	set = gtk_icon_set_new ();
+
+	for (l = sources; l; l = l->next)
+	{
+		source = gtk_icon_source_copy ((GtkIconSource *)l->data);
+		gtk_icon_set_add_source (set, source);
+	}
+
+	gtk_icon_factory_add (factory, icon_name, set);
+}
+
+static void
+glade_gtk_icon_factory_set_sources (GObject *object, const GValue *value)
+{
+	GladeIconSources *sources = g_value_get_boxed (value);
+	if (sources)
+		g_hash_table_foreach (sources->sources, (GHFunc)apply_icon_sources, object);
+}
+
+
+void
+glade_gtk_icon_factory_set_property (GladeWidgetAdaptor *adaptor,
+				     GObject *object,
+				     const gchar *property_name,
+				     const GValue *value)
+{
+	if (strcmp (property_name, "sources") == 0)
+	{
+		glade_gtk_icon_factory_set_sources (object, value);
+	} 
+	else
+		/* Chain Up */
+		GWA_GET_CLASS (G_TYPE_OBJECT)->set_property (adaptor,
+							     object,
+							     property_name, 
+							     value);
+}
+
+static void
+serialize_icon_sources (gchar          *icon_name,
+			GList          *sources,
+			GString        *string)
+{	
+	GList *l;
+	
+	for (l = sources; l; l = g_list_next (l))
+	{
+		GtkIconSource *source = l->data;
+		GdkPixbuf     *pixbuf;
+		gchar         *str;
+
+		pixbuf = gtk_icon_source_get_pixbuf (source);
+		str    = g_object_get_data (G_OBJECT (pixbuf), "GladeFileName");
+
+		g_string_append_printf (string, "%s[%s] ", icon_name, str);
+
+		if (!gtk_icon_source_get_direction_wildcarded (source))
+		{
+			GtkTextDirection direction = gtk_icon_source_get_direction (source);
+			str = glade_utils_enum_string_from_value (GTK_TYPE_TEXT_DIRECTION, direction);
+			g_string_append_printf (string, "%s ", str);
+			g_free (str);
+		}
+
+		if (!gtk_icon_source_get_size_wildcarded (source))
+		{
+			GtkIconSize size = gtk_icon_source_get_size (source);
+			str = glade_utils_enum_string_from_value (GTK_TYPE_ICON_SIZE, size);
+			g_string_append_printf (string, "%s ", str);
+			g_free (str);
+		}
+
+		if (!gtk_icon_source_get_state_wildcarded (source))
+		{
+			GtkStateType state = gtk_icon_source_get_size (source);
+			str = glade_utils_enum_string_from_value (GTK_TYPE_STATE_TYPE, state);
+			g_string_append_printf (string, "%s ", str);
+			g_free (str);
+		}
+		
+		g_string_append_printf (string, "| ");
+	}
+}
+
+gchar *
+glade_gtk_icon_factory_string_from_value (GladeWidgetAdaptor *adaptor,
+					  GladePropertyClass *klass,
+					  const GValue       *value,
+					  GladeProjectFormat  fmt)
+{
+	GString *string;
+
+	if (GLADE_IS_PARAM_SPEC_ICON_SOURCES (klass->pspec))
+	{
+		GladeIconSources *sources = g_value_get_boxed (value);
+		if (!sources)
+			return g_strdup ("");
+
+		string = g_string_new ("");		
+		g_hash_table_foreach (sources->sources, (GHFunc)serialize_icon_sources, string);
+		return g_string_free (string, FALSE);
+	}
+	else
+		return GWA_GET_CLASS 
+			(G_TYPE_OBJECT)->string_from_value (adaptor, 
+							    klass, 
+							    value,
+							    fmt);
+}
+
+
+GladeEditorProperty *
+glade_gtk_icon_factory_create_eprop (GladeWidgetAdaptor *adaptor,
+				     GladePropertyClass *klass,
+				     gboolean            use_command)
+{
+	GladeEditorProperty *eprop;
+
+	/* chain up.. */
+	if (GLADE_IS_PARAM_SPEC_ICON_SOURCES (klass->pspec))
+		eprop = g_object_new (GLADE_TYPE_EPROP_ICON_SOURCES,
+				      "property-class", klass, 
+				      "use-command", use_command,
+				      NULL);				
+	else
+		eprop = GWA_GET_CLASS 
+			(G_TYPE_OBJECT)->create_eprop (adaptor, 
+						       klass, 
+						       use_command);
+	return eprop;
+}

Added: trunk/plugins/gtk+/glade-icon-sources.c
==============================================================================
--- (empty file)
+++ trunk/plugins/gtk+/glade-icon-sources.c	Wed Oct 22 22:33:30 2008
@@ -0,0 +1,885 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Tristan Van Berkom.
+ *
+ * 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.
+ *
+ * Authors:
+ *   Tristan Van Berkom <tvb gnome org>
+ */
+
+#include <config.h>
+
+#include <gladeui/glade.h>
+#include <gtk/gtk.h>
+#include <glib/gi18n-lib.h>
+#include <string.h>
+
+#include "glade-icon-sources.h"
+
+static void
+icon_set_free (GList *list)
+{
+	g_list_foreach (list, (GFunc)gtk_icon_source_free, NULL);
+	g_list_free (list);
+}
+
+GladeIconSources *
+glade_icon_sources_new (void)
+{
+	GladeIconSources *sources = g_new0 (GladeIconSources, 1);
+
+	sources->sources = g_hash_table_new_full (g_str_hash, g_str_equal,
+						  (GDestroyNotify)g_free,
+						  (GDestroyNotify)icon_set_free);
+	return sources;
+}
+
+
+static void
+icon_sources_dup (gchar               *icon_name,
+		  GList               *set,
+		  GladeIconSources    *dup)
+{
+	GList *dup_set = NULL, *l;
+	GtkIconSource *source;
+	
+	for (l = set; l; l = l->next)
+	{
+		source = gtk_icon_source_copy ((GtkIconSource *)l->data);
+		dup_set = g_list_prepend (dup_set, source);
+	}
+	g_hash_table_insert (dup->sources, g_strdup (icon_name), g_list_reverse (dup_set));
+}
+
+GladeIconSources *
+glade_icon_sources_copy (GladeIconSources *sources)
+{
+	if (!sources)
+		return NULL;
+
+	GladeIconSources *dup = glade_icon_sources_new ();
+
+	g_hash_table_foreach (sources->sources, (GHFunc)icon_sources_dup, dup);
+
+	return dup;
+}
+
+void
+glade_icon_sources_free (GladeIconSources *sources)
+{
+	if (sources)
+	{
+		g_hash_table_destroy (sources->sources);
+		g_free (sources);
+	}
+}
+
+GType
+glade_icon_sources_get_type (void)
+{
+	static GType type_id = 0;
+
+	if (!type_id)
+		type_id = g_boxed_type_register_static
+			("GladeIconSources", 
+			 (GBoxedCopyFunc) glade_icon_sources_copy,
+			 (GBoxedFreeFunc) glade_icon_sources_free);
+	return type_id;
+}
+
+/********************** GladeParamIconSources  ***********************/
+
+struct _GladeParamIconSources
+{
+	GParamSpec parent_instance;
+};
+
+static gint
+param_values_cmp (GParamSpec *pspec, const GValue *value1, const GValue *value2)
+{
+	GladeIconSources *s1, *s2;
+	gint retval;
+	
+	s1 = g_value_get_boxed (value1);
+	s2 = g_value_get_boxed (value2);
+	
+	if (s1 == NULL && s2 == NULL) return 0;
+	
+	if (s1 == NULL || s2 == NULL) return s1 - s2;
+	
+	if ((retval = 
+	     g_hash_table_size (s1->sources) - g_hash_table_size (s2->sources)))
+		return retval;
+	else
+		/* XXX We could do alot better here... but right now we are using strings
+		 * and ignoring changes somehow... need to fix that.
+		 */
+		return GPOINTER_TO_INT (s1->sources) - GPOINTER_TO_INT (s2->sources);
+}
+
+GType
+glade_param_icon_sources_get_type (void)
+{
+	static GType icon_sources_type = 0;
+
+	if (icon_sources_type == 0)
+	{
+		 GParamSpecTypeInfo pspec_info = {
+			 sizeof (GladeParamIconSources),  /* instance_size */
+			 16,   /* n_preallocs */
+			 NULL, /* instance_init */
+			 0,    /* value_type, assigned further down */
+			 NULL, /* finalize */
+			 NULL, /* value_set_default */
+			 NULL, /* value_validate */
+			 param_values_cmp, /* values_cmp */
+		 };
+		 pspec_info.value_type = GLADE_TYPE_ICON_SOURCES;
+		 
+		 icon_sources_type = g_param_type_register_static
+			 ("GladeParamIconSources", &pspec_info);
+	}
+	return icon_sources_type;
+}
+
+GParamSpec *
+glade_standard_icon_sources_spec (void)
+{
+	GladeParamIconSources *pspec;
+
+	pspec = g_param_spec_internal (GLADE_TYPE_PARAM_ICON_SOURCES,
+				       "icon-sources", _("Icon Sources"), 
+				       _("A list of sources for an icon factory"),
+				       G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+	return G_PARAM_SPEC (pspec);
+}
+
+/**************************** GladeEditorProperty *****************************/
+enum {
+	COLUMN_TEXT,             /* Used for display/editing purposes */
+	COLUMN_TEXT_WEIGHT,      /* Whether the text is bold (icon-name parent rows) */
+	COLUMN_TEXT_EDITABLE,    /* parent icon-name displays are not editable */
+	COLUMN_ICON_NAME,        /* store the icon name regardless */
+	COLUMN_LIST_INDEX,       /* denotes the position in the GList of the actual property value (or -1) */
+	COLUMN_DIRECTION_ACTIVE,
+	COLUMN_DIRECTION,
+	COLUMN_SIZE_ACTIVE,
+	COLUMN_SIZE,
+	COLUMN_STATE_ACTIVE,
+	COLUMN_STATE,
+	NUM_COLUMNS
+};
+
+typedef struct
+{
+	GladeEditorProperty parent_instance;
+
+	GtkTreeView       *view;
+	GtkTreeStore      *store;
+	GtkListStore      *icon_names_store;
+	GtkTreeViewColumn *filename_column;
+	GtkWidget         *combo;
+
+	GladeIconSources  *pending_sources;
+} GladeEPropIconSources;
+
+GLADE_MAKE_EPROP (GladeEPropIconSources, glade_eprop_icon_sources)
+#define GLADE_EPROP_ICON_SOURCES(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_EPROP_ICON_SOURCES, GladeEPropIconSources))
+#define GLADE_EPROP_ICON_SOURCES_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_EPROP_ICON_SOURCES, GladeEPropIconSourcesClass))
+#define GLADE_IS_EPROP_ICON_SOURCES(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_EPROP_ICON_SOURCES))
+#define GLADE_IS_EPROP_ICON_SOURCES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_EPROP_ICON_SOURCES))
+#define GLADE_EPROP_ICON_SOURCES_GET_CLASS(o)    (G_TYPE_INSTANCE_GET_CLASS ((o), GLADE_EPROP_ICON_SOURCES, GladeEPropIconSourcesClass))
+
+static void
+glade_eprop_icon_sources_finalize (GObject *object)
+{
+	/* Chain up */
+	GObjectClass *parent_class = g_type_class_peek_parent (G_OBJECT_GET_CLASS (object));
+	GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (object);
+
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+populate_store_foreach (const gchar           *icon_name,
+			GList                 *sources,
+			GladeEPropIconSources *eprop_sources)
+{
+	GtkIconSource *source; 
+	GtkTreeIter    parent_iter, iter;
+	GList         *l;
+
+	/* Update the comboboxentry's store here... */
+	gtk_list_store_append (eprop_sources->icon_names_store, &iter);
+	gtk_list_store_set (eprop_sources->icon_names_store, &iter, 0, icon_name, -1);
+	gtk_combo_box_set_active_iter (GTK_COMBO_BOX (eprop_sources->combo), &iter);
+
+	/* Dont set COLUMN_ICON_NAME here */
+	gtk_tree_store_append (eprop_sources->store, &parent_iter, NULL);
+	gtk_tree_store_set (eprop_sources->store, &parent_iter, 
+			    COLUMN_TEXT, icon_name,
+			    COLUMN_TEXT_EDITABLE, FALSE, 
+			    COLUMN_TEXT_WEIGHT, PANGO_WEIGHT_BOLD,
+			    -1);
+
+	for (l = sources; l; l = l->next)
+	{
+		GdkPixbuf       *pixbuf;
+		gchar           *str;
+
+		source = l->data;
+		pixbuf = gtk_icon_source_get_pixbuf (source);
+		str    = g_object_get_data (G_OBJECT (pixbuf), "GladeFileName");
+
+		gtk_tree_store_append (eprop_sources->store, &iter, &parent_iter);
+		gtk_tree_store_set (eprop_sources->store, &iter, 
+				    COLUMN_ICON_NAME, icon_name,
+				    COLUMN_LIST_INDEX, g_list_index (sources, source),
+				    COLUMN_TEXT, str,
+				    COLUMN_TEXT_EDITABLE, TRUE,
+				    COLUMN_TEXT_WEIGHT, PANGO_WEIGHT_NORMAL,
+				    -1);
+
+		if (!gtk_icon_source_get_direction_wildcarded (source))
+		{
+			GtkTextDirection direction = gtk_icon_source_get_direction (source);
+			str = glade_utils_enum_string_from_value (GTK_TYPE_TEXT_DIRECTION, direction);
+			gtk_tree_store_set (eprop_sources->store, &iter, 
+					    COLUMN_DIRECTION_ACTIVE, TRUE,
+					    COLUMN_DIRECTION, str,
+					    -1);
+			g_free (str);
+		}
+
+		if (!gtk_icon_source_get_size_wildcarded (source))
+		{
+			GtkIconSize size = gtk_icon_source_get_size (source);
+			str = glade_utils_enum_string_from_value (GTK_TYPE_ICON_SIZE, size);
+			gtk_tree_store_set (eprop_sources->store, &iter, 
+					    COLUMN_SIZE_ACTIVE, TRUE,
+					    COLUMN_SIZE, str,
+					    -1);
+			g_free (str);
+		}
+
+		if (!gtk_icon_source_get_state_wildcarded (source))
+		{
+			GtkStateType state = gtk_icon_source_get_size (source);
+			str = glade_utils_enum_string_from_value (GTK_TYPE_STATE_TYPE, state);
+			gtk_tree_store_set (eprop_sources->store, &iter, 
+					    COLUMN_STATE_ACTIVE, TRUE,
+					    COLUMN_STATE, str,
+					    -1);
+			g_free (str);
+		}
+
+		/* Make sure its all expanded */
+		if (!l->next)
+		{
+			GtkTreePath *tree_path =
+				gtk_tree_model_get_path (GTK_TREE_MODEL (eprop_sources->store), &iter);
+			gtk_tree_view_expand_to_path (eprop_sources->view, tree_path);
+		}
+	}
+}
+
+static void
+populate_store (GladeEPropIconSources *eprop_sources)
+{
+	GladeIconSources *sources = NULL;
+
+	gtk_tree_store_clear (eprop_sources->store);
+	gtk_list_store_clear (eprop_sources->icon_names_store);
+
+	glade_property_get (GLADE_EDITOR_PROPERTY (eprop_sources)->property, &sources);
+
+	if (sources)
+		g_hash_table_foreach (sources->sources, (GHFunc)populate_store_foreach, eprop_sources);
+}
+
+static void
+glade_eprop_icon_sources_load (GladeEditorProperty *eprop, 
+			       GladeProperty       *property)
+{
+	GladeEditorPropertyClass *parent_class = 
+		g_type_class_peek_parent (GLADE_EDITOR_PROPERTY_GET_CLASS (eprop));
+	GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
+
+	/* Chain up in a clean state... */
+	parent_class->load (eprop, property);
+
+	populate_store (eprop_sources);
+
+	gtk_widget_queue_draw (GTK_WIDGET (eprop_sources->view));
+}
+
+
+static void
+add_clicked (GtkWidget *button, 
+	     GladeEPropIconSources *eprop_sources)
+{
+	/* Remember to set focus on the cell and activate it ! */
+	GtkTreeIter *parent_iter = NULL, iter, new_parent_iter;
+	GtkTreePath *new_item_path;
+	gchar       *icon_name;
+	gchar       *selected_icon_name;
+
+	if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (eprop_sources->combo), &iter))
+		gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->icon_names_store), &iter,
+				    0, &selected_icon_name, -1);
+
+	if (!selected_icon_name)
+		return;
+
+	/* Find the right parent iter to add a child to... */
+	if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (eprop_sources->store), &iter))
+	{
+		do {
+			gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
+					    COLUMN_TEXT, &icon_name,
+					    -1);
+
+			if (icon_name && 
+			    strcmp (icon_name, selected_icon_name) == 0)
+				parent_iter = gtk_tree_iter_copy (&iter);
+
+			g_free (icon_name);
+
+		} while (parent_iter == NULL &&
+			 gtk_tree_model_iter_next (GTK_TREE_MODEL (eprop_sources->store), &iter));
+	}
+
+	if (!parent_iter)
+	{
+		/* Dont set COLUMN_ICON_NAME here */
+		gtk_tree_store_append (eprop_sources->store, &new_parent_iter, NULL);
+		gtk_tree_store_set (eprop_sources->store, &new_parent_iter, 
+				    COLUMN_TEXT, selected_icon_name,
+				    COLUMN_TEXT_EDITABLE, FALSE, 
+				    COLUMN_TEXT_WEIGHT, PANGO_WEIGHT_BOLD,
+				    -1);
+		parent_iter = gtk_tree_iter_copy (&new_parent_iter);
+	}
+
+	gtk_tree_store_append (eprop_sources->store, &iter, parent_iter);
+	gtk_tree_store_set (eprop_sources->store, &iter, 
+			    COLUMN_ICON_NAME, selected_icon_name,
+			    COLUMN_TEXT_EDITABLE, TRUE,
+			    COLUMN_TEXT_WEIGHT, PANGO_WEIGHT_NORMAL,
+			    -1);
+
+	new_item_path = gtk_tree_model_get_path (GTK_TREE_MODEL (eprop_sources->store), &iter);
+
+	gtk_widget_grab_focus (GTK_WIDGET (eprop_sources->view));
+	gtk_tree_view_expand_to_path (eprop_sources->view, new_item_path);
+	gtk_tree_view_set_cursor (eprop_sources->view, new_item_path,
+				  eprop_sources->filename_column, TRUE);
+
+	g_free (selected_icon_name);
+	gtk_tree_iter_free (parent_iter);
+}
+
+static GtkIconSource *
+get_icon_source (GladeIconSources *sources,
+		 const gchar      *icon_name,
+		 gint              index)
+{
+	GList *source_list =
+		g_hash_table_lookup (sources->sources, icon_name);
+
+	if (source_list)
+	{
+		if (index < 0)
+			return (GtkIconSource *)source_list->data;
+		else 
+			return (GtkIconSource *)g_list_nth_data (source_list, index);
+	}
+	return NULL;
+}
+
+static void
+delete_clicked (GtkWidget *button, 
+		GladeEPropIconSources *eprop_sources)
+{
+
+}
+
+static gboolean
+update_icon_sources_idle (GladeEditorProperty *eprop)
+{
+	GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
+	GValue                 value = { 0, };
+	
+	g_value_init (&value, GLADE_TYPE_ICON_SOURCES);
+	g_value_take_boxed (&value, eprop_sources->pending_sources);
+	glade_editor_property_commit (eprop, &value);
+	g_value_unset (&value);
+
+	eprop_sources->pending_sources = NULL;
+	return FALSE;
+}
+
+static gboolean
+reload_icon_sources_idle (GladeEditorProperty *eprop)
+{
+	glade_editor_property_load (eprop, eprop->property);
+	return FALSE;
+}
+
+static void
+value_filename_edited (GtkCellRendererText *cell,
+		       const gchar         *path,
+		       const gchar         *new_text,
+		       GladeEditorProperty *eprop)
+{
+	GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
+	GtkTreeIter            iter;
+	GladeIconSources      *icon_sources = NULL;
+	GtkIconSource         *source;
+	gchar                 *icon_name;
+	gint                   index;
+	GValue                *value;
+	GdkPixbuf             *pixbuf;
+	GList                 *source_list;
+
+	if (!new_text || !new_text[0])
+	{
+		g_idle_add ((GSourceFunc)reload_icon_sources_idle, eprop);
+		return;
+	}
+
+	if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (eprop_sources->store), &iter, path))
+		return;
+
+	gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
+			    COLUMN_ICON_NAME, &icon_name,
+			    COLUMN_LIST_INDEX, &index,
+			    -1);
+
+	/* get new pixbuf value... */
+	value = glade_utils_value_from_string (GDK_TYPE_PIXBUF, new_text,
+					       eprop->property->widget->project,
+					       eprop->property->widget);
+	pixbuf = g_value_get_object (value);
+
+
+	glade_property_get (eprop->property, &icon_sources);
+	if (icon_sources)
+	{
+		icon_sources = glade_icon_sources_copy (icon_sources);
+		if ((source = get_icon_source (icon_sources, icon_name, index)) != NULL)
+			gtk_icon_source_set_pixbuf (source, pixbuf);
+		else
+		{
+			source = gtk_icon_source_new ();
+			gtk_icon_source_set_pixbuf (source, pixbuf);
+
+			if ((source_list = g_hash_table_lookup (icon_sources->sources,
+								icon_name)) != NULL)
+				source_list = g_list_prepend (source_list, source);
+			else
+			{
+				source_list = g_list_prepend (NULL, source);
+				g_hash_table_insert (icon_sources->sources, g_strdup (icon_name), source_list);
+			}
+		}
+	}
+	else
+	{
+		icon_sources = glade_icon_sources_new ();
+		source = gtk_icon_source_new ();
+		gtk_icon_source_set_pixbuf (source, pixbuf);
+
+		source_list = g_list_prepend (NULL, source);
+		g_hash_table_insert (icon_sources->sources, g_strdup (icon_name), source_list);
+	}
+
+	g_value_unset (value);
+	g_free (value);
+
+	if (eprop_sources->pending_sources)
+		glade_icon_sources_free (eprop_sources->pending_sources);
+
+	eprop_sources->pending_sources = icon_sources;
+	g_idle_add ((GSourceFunc)update_icon_sources_idle, eprop);
+}
+
+static void
+value_attribute_toggled (GtkCellRendererToggle *cell_renderer,
+			 gchar                 *path,
+			 GladeEditorProperty   *eprop)
+{
+	GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
+	GtkTreeIter            iter;
+	GladeIconSources      *icon_sources = NULL;
+	GtkIconSource         *source;
+	gchar                 *icon_name;
+	gint                   index, edit_column;
+	gboolean               edit_column_active = FALSE;
+
+	if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (eprop_sources->store), &iter, path))
+		return;
+
+	edit_column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell_renderer), "attribute-column"));
+	gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
+			    COLUMN_ICON_NAME, &icon_name,
+			    COLUMN_LIST_INDEX, &index,
+			    edit_column, &edit_column_active,
+			    -1);
+
+	glade_property_get (eprop->property, &icon_sources);
+
+	if (icon_sources)
+		icon_sources = glade_icon_sources_copy (icon_sources);
+
+	if (icon_sources && (source = get_icon_source (icon_sources, icon_name, index)) != NULL)
+	{
+		/* Note the reverse meaning of active toggles vs. wildcarded sources... */
+		switch (edit_column)
+		{
+		case COLUMN_DIRECTION_ACTIVE:
+			gtk_icon_source_set_direction_wildcarded (source, edit_column_active);
+			break;
+		case COLUMN_SIZE_ACTIVE:
+			gtk_icon_source_set_size_wildcarded (source, edit_column_active);
+			break;
+		case COLUMN_STATE_ACTIVE:
+			gtk_icon_source_set_state_wildcarded (source, edit_column_active);
+			break;
+		default:
+			break;
+		}
+
+		if (eprop_sources->pending_sources)
+			glade_icon_sources_free (eprop_sources->pending_sources);
+
+		eprop_sources->pending_sources = icon_sources;
+		g_idle_add ((GSourceFunc)update_icon_sources_idle, eprop);
+
+		g_free (icon_name);
+		return;
+	}
+	
+	if (icon_sources)
+		glade_icon_sources_free (icon_sources);
+	g_free (icon_name);
+	return;
+}
+
+static void
+value_attribute_edited (GtkCellRendererText *cell,
+			const gchar         *path,
+			const gchar         *new_text,
+			GladeEditorProperty *eprop)
+{
+	GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
+	GtkTreeIter            iter;
+	GladeIconSources      *icon_sources = NULL;
+	GtkIconSource         *source;
+	gchar                 *icon_name;
+	gint                   index, edit_column;
+	gboolean               edit_column_active = FALSE;
+
+	if (!new_text || !new_text[0])
+		return;
+
+	if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (eprop_sources->store), &iter, path))
+		return;
+
+	edit_column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "attribute-column"));
+	gtk_tree_model_get (GTK_TREE_MODEL (eprop_sources->store), &iter,
+			    COLUMN_ICON_NAME, &icon_name,
+			    COLUMN_LIST_INDEX, &index,
+			    edit_column, &edit_column_active,
+			    -1);
+
+	glade_property_get (eprop->property, &icon_sources);
+
+	if (icon_sources)
+		icon_sources = glade_icon_sources_copy (icon_sources);
+
+	if (icon_sources && (source = get_icon_source (icon_sources, icon_name, index)) != NULL)
+	{
+		GtkTextDirection direction;
+		GtkIconSize size;
+		GtkStateType state;
+
+		switch (edit_column)
+		{
+		case COLUMN_DIRECTION:
+			direction = glade_utils_enum_value_from_string (GTK_TYPE_TEXT_DIRECTION, new_text);
+			gtk_icon_source_set_direction (source, direction);
+			break;
+		case COLUMN_SIZE:
+			size = glade_utils_enum_value_from_string (GTK_TYPE_ICON_SIZE, new_text);
+			gtk_icon_source_set_size (source, size);
+			break;
+		case COLUMN_STATE:
+			state = glade_utils_enum_value_from_string (GTK_TYPE_STATE_TYPE, new_text);
+			gtk_icon_source_set_state (source, state);
+			break;
+		default:
+			break;
+		}
+
+		if (eprop_sources->pending_sources)
+			glade_icon_sources_free (eprop_sources->pending_sources);
+
+		eprop_sources->pending_sources = icon_sources;
+		g_idle_add ((GSourceFunc)update_icon_sources_idle, eprop);
+
+		g_free (icon_name);
+		return;
+	}
+	
+	if (icon_sources)
+		glade_icon_sources_free (icon_sources);
+	g_free (icon_name);
+	return;
+}
+
+static GtkTreeView *
+build_view (GladeEditorProperty *eprop)
+{
+	GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
+	static GtkListStore   *direction_store = NULL, *size_store = NULL, *state_store = NULL;
+	GtkTreeView           *view = (GtkTreeView *)gtk_tree_view_new ();
+	GtkCellRenderer       *renderer;
+	GtkTreeViewColumn     *column;
+
+	if (!direction_store)
+	{
+		direction_store = glade_utils_liststore_from_enum_type (GTK_TYPE_TEXT_DIRECTION, FALSE);
+		size_store      = glade_utils_liststore_from_enum_type (GTK_TYPE_ICON_SIZE, FALSE);
+		state_store     = glade_utils_liststore_from_enum_type (GTK_TYPE_STATE_TYPE, FALSE);
+	}
+
+	/* Filename / icon name column/renderer */
+ 	renderer = gtk_cell_renderer_text_new ();
+	g_object_set (G_OBJECT (renderer), "editable", FALSE, NULL);
+	g_signal_connect (G_OBJECT (renderer), "edited",
+			  G_CALLBACK (value_filename_edited), eprop);
+
+	eprop_sources->filename_column = 
+		gtk_tree_view_column_new_with_attributes (_("File Name"),  renderer, 
+							  "text", COLUMN_TEXT, 
+							  "weight", COLUMN_TEXT_WEIGHT,
+							  "editable", COLUMN_TEXT_EDITABLE,
+							  NULL);
+	gtk_tree_view_column_set_expand (eprop_sources->filename_column, TRUE);
+ 	gtk_tree_view_append_column (GTK_TREE_VIEW (view), eprop_sources->filename_column);
+
+	/********************* Direction *********************/
+	/* Attribute active portion */
+ 	renderer = gtk_cell_renderer_toggle_new ();
+	g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
+	g_object_set_data (G_OBJECT (renderer), "attribute-column", 
+			   GINT_TO_POINTER (COLUMN_DIRECTION_ACTIVE));
+	g_signal_connect (G_OBJECT (renderer), "toggled",
+			  G_CALLBACK (value_attribute_toggled), eprop);
+	
+	column = gtk_tree_view_column_new_with_attributes
+		("dummy",  renderer, 
+		 "visible", COLUMN_TEXT_EDITABLE,
+		 "active", COLUMN_DIRECTION_ACTIVE,
+		 NULL);
+ 	gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+	/* Attribute portion */
+ 	renderer = gtk_cell_renderer_combo_new ();
+	g_object_set (G_OBJECT (renderer), "editable", TRUE, "has-entry", FALSE, 
+		      "text-column", 0, "model", direction_store, NULL);
+	g_object_set_data (G_OBJECT (renderer), "attribute-column", 
+			   GINT_TO_POINTER (COLUMN_DIRECTION));
+	g_signal_connect (G_OBJECT (renderer), "edited",
+			  G_CALLBACK (value_attribute_edited), eprop);
+
+	column = gtk_tree_view_column_new_with_attributes
+		("dummy",  renderer, 
+		 "visible", COLUMN_TEXT_EDITABLE,
+		 "editable", COLUMN_DIRECTION_ACTIVE,
+		 "text", COLUMN_DIRECTION,
+		 NULL);
+ 	gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+	/********************* Size *********************/
+	/* Attribute active portion */
+ 	renderer = gtk_cell_renderer_toggle_new ();
+	g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
+	g_object_set_data (G_OBJECT (renderer), "attribute-column", 
+			   GINT_TO_POINTER (COLUMN_SIZE_ACTIVE));
+	g_signal_connect (G_OBJECT (renderer), "toggled",
+			  G_CALLBACK (value_attribute_toggled), eprop);
+	
+	column = gtk_tree_view_column_new_with_attributes
+		("dummy",  renderer, 
+		 "visible", COLUMN_TEXT_EDITABLE,
+		 "active", COLUMN_SIZE_ACTIVE,
+		 NULL);
+ 	gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+	/* Attribute portion */
+ 	renderer = gtk_cell_renderer_combo_new ();
+	g_object_set (G_OBJECT (renderer), "editable", TRUE, "has-entry", FALSE, 
+		      "text-column", 0, "model", size_store, NULL);
+	g_object_set_data (G_OBJECT (renderer), "attribute-column", 
+			   GINT_TO_POINTER (COLUMN_SIZE));
+	g_signal_connect (G_OBJECT (renderer), "edited",
+			  G_CALLBACK (value_attribute_edited), eprop);
+
+	column = gtk_tree_view_column_new_with_attributes
+		("dummy",  renderer, 
+		 "visible", COLUMN_TEXT_EDITABLE,
+		 "editable", COLUMN_SIZE_ACTIVE,
+		 "text", COLUMN_SIZE,
+		 NULL);
+ 	gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+	
+
+	/********************* State *********************/
+	/* Attribute active portion */
+ 	renderer = gtk_cell_renderer_toggle_new ();
+	g_object_set (G_OBJECT (renderer), "activatable", TRUE, NULL);
+	g_object_set_data (G_OBJECT (renderer), "attribute-column", 
+			   GINT_TO_POINTER (COLUMN_STATE_ACTIVE));
+	g_signal_connect (G_OBJECT (renderer), "toggled",
+			  G_CALLBACK (value_attribute_toggled), eprop);
+	
+	column = gtk_tree_view_column_new_with_attributes
+		("dummy",  renderer, 
+		 "visible", COLUMN_TEXT_EDITABLE,
+		 "active", COLUMN_STATE_ACTIVE,
+		 NULL);
+ 	gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+	/* Attribute portion */
+ 	renderer = gtk_cell_renderer_combo_new ();
+	g_object_set (G_OBJECT (renderer), "editable", TRUE, "has-entry", FALSE, 
+		      "text-column", 0, "model", state_store, NULL);
+	g_object_set_data (G_OBJECT (renderer), "attribute-column", 
+			   GINT_TO_POINTER (COLUMN_STATE));
+	g_signal_connect (G_OBJECT (renderer), "edited",
+			  G_CALLBACK (value_attribute_edited), eprop);
+
+	column = gtk_tree_view_column_new_with_attributes
+		("dummy",  renderer, 
+		 "visible", COLUMN_TEXT_EDITABLE,
+		 "editable", COLUMN_STATE_ACTIVE,
+		 "text", COLUMN_STATE,
+		 NULL);
+ 	gtk_tree_view_append_column (GTK_TREE_VIEW (view), column);
+
+	/* Connect ::query-tooltip here for fancy tooltips... */
+	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
+	gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (view), FALSE);
+
+	return view;
+}
+
+static void
+icon_name_entry_activated (GtkEntry *entry, 
+			   GladeEPropIconSources *eprop_sources)
+{
+	GtkTreeIter  iter;
+	const gchar *text = gtk_entry_get_text (entry);
+
+	if (!text || !text[0])
+		return;
+
+	gtk_list_store_append (eprop_sources->icon_names_store, &iter);
+	gtk_list_store_set (eprop_sources->icon_names_store, &iter, 
+			    0, text, -1);
+	gtk_combo_box_set_active_iter (GTK_COMBO_BOX (eprop_sources->combo), &iter);
+}
+
+static GtkWidget *
+glade_eprop_icon_sources_create_input (GladeEditorProperty *eprop)
+{
+	GladeEPropIconSources *eprop_sources = GLADE_EPROP_ICON_SOURCES (eprop);
+	GtkWidget *vbox, *hbox, *button, *swin, *label;
+	gchar *string;
+
+	vbox = gtk_vbox_new (FALSE, 2);
+
+	/* The label... */
+	string = g_strdup_printf ("<b>%s</b>", _("Add and remove icon sources:"));
+	label = gtk_label_new (string);
+	g_free (string);
+	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+	gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+	gtk_misc_set_padding (GTK_MISC (label), 2, 0);
+	gtk_box_pack_start (GTK_BOX (vbox), label,  FALSE, TRUE, 0);
+
+	hbox = gtk_hbox_new (FALSE, 4);
+
+	/* hbox with comboboxentry add/remove source buttons on the right... */
+	gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+	eprop_sources->icon_names_store = gtk_list_store_new (1, G_TYPE_STRING);
+	eprop_sources->combo = gtk_combo_box_entry_new_with_model 
+		(GTK_TREE_MODEL (eprop_sources->icon_names_store), 0);
+	g_signal_connect (G_OBJECT (GTK_BIN (eprop_sources->combo)->child), "activate",
+			  G_CALLBACK (icon_name_entry_activated), eprop);
+
+	gtk_box_pack_start (GTK_BOX (hbox), eprop_sources->combo,  TRUE, TRUE, 0);
+	button = gtk_button_new ();
+	gtk_button_set_image (GTK_BUTTON (button),
+			      gtk_image_new_from_stock (GTK_STOCK_ADD,
+							GTK_ICON_SIZE_BUTTON));
+	gtk_box_pack_start (GTK_BOX (hbox), button,  FALSE, FALSE, 0);
+	g_signal_connect (G_OBJECT (button), "clicked",
+			  G_CALLBACK (add_clicked), 
+			  eprop_sources);
+	
+	button = gtk_button_new ();
+	gtk_button_set_image (GTK_BUTTON (button),
+			      gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_BUTTON));
+	gtk_box_pack_start (GTK_BOX (hbox), button,  FALSE, FALSE, 0);
+
+	g_signal_connect (G_OBJECT (button), "clicked",
+			  G_CALLBACK (delete_clicked), 
+			  eprop_sources);
+
+	/* Pack treeview/swindow on the left... */
+	swin = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin), GTK_SHADOW_IN);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+	gtk_box_pack_start (GTK_BOX (vbox), swin, TRUE, TRUE, 0);
+
+	eprop_sources->view = build_view (eprop);
+	gtk_container_add (GTK_CONTAINER (swin), GTK_WIDGET (eprop_sources->view));
+
+	g_object_set (G_OBJECT (vbox), "height-request", 350, NULL);
+
+	eprop_sources->store = gtk_tree_store_new (NUM_COLUMNS,    
+						   G_TYPE_STRING,  // COLUMN_TEXT
+						   G_TYPE_INT,     // COLUMN_TEXT_WEIGHT
+						   G_TYPE_BOOLEAN, // COLUMN_TEXT_EDITABLE
+						   G_TYPE_STRING,  // COLUMN_ICON_NAME
+						   G_TYPE_INT,     // COLUMN_LIST_INDEX
+						   G_TYPE_BOOLEAN, // COLUMN_DIRECTION_ACTIVE
+						   G_TYPE_STRING,  // COLUMN_DIRECTION
+						   G_TYPE_BOOLEAN, // COLUMN_SIZE_ACTIVE
+						   G_TYPE_STRING,  // COLUMN_SIZE
+						   G_TYPE_BOOLEAN, // COLUMN_STATE_ACTIVE,
+						   G_TYPE_STRING); // COLUMN_STATE
+
+	gtk_tree_view_set_model (eprop_sources->view, GTK_TREE_MODEL (eprop_sources->store));
+	g_object_unref (G_OBJECT (eprop_sources->store)); // <-- pass ownership here
+	
+	gtk_widget_show_all (vbox);
+	return vbox;
+}

Added: trunk/plugins/gtk+/glade-icon-sources.h
==============================================================================
--- (empty file)
+++ trunk/plugins/gtk+/glade-icon-sources.h	Wed Oct 22 22:33:30 2008
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Tristan Van Berkom.
+ *
+ * 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.
+ *
+ * Authors:
+ *   Tristan Van Berkom <tvb gnome org>
+ */
+#ifndef _GLADE_ICON_SOURCES_H_
+#define _STV_CAP_H_
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+struct _GladeIconSources
+{
+	GHashTable *sources;
+
+};
+
+typedef struct _GladeIconSources         GladeIconSources;
+typedef struct _GladeParamIconSources    GladeParamIconSources;
+
+#define	GLADE_TYPE_ICON_SOURCES       (glade_icon_sources_get_type())
+#define	GLADE_TYPE_PARAM_ICON_SOURCES (glade_param_icon_sources_get_type())
+#define GLADE_TYPE_EPROP_ICON_SOURCES (glade_eprop_icon_sources_get_type())
+
+#define GLADE_IS_PARAM_SPEC_ICON_SOURCES(pspec) \
+	(G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GLADE_TYPE_PARAM_ICON_SOURCES))
+#define GLADE_PARAM_SPEC_ICON_SOURCES(pspec)    \
+	(G_TYPE_CHECK_INSTANCE_CAST ((pspec), GLADE_TYPE_PARAM_ICON_SOURCES, GladeParamSpecIconSources))
+
+GType             glade_icon_sources_get_type          (void) G_GNUC_CONST;
+GType             glade_param_icon_sources_get_type    (void) G_GNUC_CONST;
+GType             glade_eprop_icon_sources_get_type    (void) G_GNUC_CONST;
+
+GParamSpec       *glade_standard_icon_sources_spec     (void);
+
+GladeIconSources *glade_icon_sources_new               (void);
+GladeIconSources *glade_icon_sources_copy              (GladeIconSources *sources);
+void              glade_icon_sources_free              (GladeIconSources *sources);
+
+G_END_DECLS
+
+#endif /* _GLADE_ICON_SOURCE_H_ */

Modified: trunk/plugins/gtk+/glade-model-data.c
==============================================================================
--- trunk/plugins/gtk+/glade-model-data.c	(original)
+++ trunk/plugins/gtk+/glade-model-data.c	Wed Oct 22 22:33:30 2008
@@ -502,10 +502,7 @@
 {
 	/* Chain up */
 	GObjectClass *parent_class = g_type_class_peek_parent (G_OBJECT_GET_CLASS (object));
-	GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (object);
-
-	if (eprop_data->store)
-		g_object_unref (G_OBJECT (eprop_data->store));
+	//GladeEPropModelData *eprop_data = GLADE_EPROP_MODEL_DATA (object);
 
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }

Modified: trunk/plugins/gtk+/gtk+.xml.in
==============================================================================
--- trunk/plugins/gtk+/gtk+.xml.in	(original)
+++ trunk/plugins/gtk+/gtk+.xml.in	Wed Oct 22 22:33:30 2008
@@ -1743,11 +1743,25 @@
 			libglade-unsupported="True" toplevel="True"/>
     <glade-widget-class name="GtkEntryCompletion" generic-name="entrycompletion" _title="Entry Completion" 
 			libglade-unsupported="True" toplevel="True"/>
-    <glade-widget-class name="GtkIconFactory" generic-name="iconfactory" _title="Icon Factory" 
-			libglade-unsupported="True" toplevel="True"/>
     <glade-widget-class name="GtkUIManager" generic-name="uimanager" _title="UI Manager" 
 			libglade-unsupported="True" toplevel="True"/>
 
+    <glade-widget-class name="GtkIconFactory" generic-name="iconfactory" _title="Icon Factory" 
+			libglade-unsupported="True" toplevel="True">
+      <post-create-function>glade_gtk_icon_factory_post_create</post-create-function>
+      <read-widget-function>glade_gtk_icon_factory_read_widget</read-widget-function>
+      <write-widget-function>glade_gtk_icon_factory_write_widget</write-widget-function>
+      <set-property-function>glade_gtk_icon_factory_set_property</set-property-function>
+      <string-from-value-function>glade_gtk_icon_factory_string_from_value</string-from-value-function>
+      <create-editor-property-function>glade_gtk_icon_factory_create_eprop</create-editor-property-function>
+      <properties>
+	<property id="sources" _name="Icon Sources" save="False">
+	  <_tooltip>A list of sources for this icon factory</_tooltip>
+	  <spec>glade_standard_icon_sources_spec</spec>
+	</property>
+      </properties>
+    </glade-widget-class>
+
     <glade-widget-class name="GtkTreeView" generic-name="treeview" _title="Tree View">
       <post-create-function>empty</post-create-function>
       <child-set-property-function>glade_gtk_treeview_set_child_property</child-set-property-function>



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