[glade] Move GladeWidgetAdaptor code for various classes into their own C files



commit 540acc17bbf41f0229acce71f35c0ef3089cbf1f
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Sat May 4 15:57:10 2013 +0900

    Move GladeWidgetAdaptor code for various classes into their own C files
    
    Moved GtkListStore, GtkCellRenderer, GtkCellLayout and GtkTreeView

 plugins/gtk+/Makefile.am               |    7 +
 plugins/gtk+/glade-gtk-cell-layout.c   |  512 ++++++++++
 plugins/gtk+/glade-gtk-cell-layout.h   |   45 +
 plugins/gtk+/glade-gtk-cell-renderer.c |  411 ++++++++
 plugins/gtk+/glade-gtk-cell-renderer.h |   33 +
 plugins/gtk+/glade-gtk-list-store.c    |  658 ++++++++++++
 plugins/gtk+/glade-gtk-tree-view.c     |  275 +++++
 plugins/gtk+/glade-gtk-tree-view.h     |   33 +
 plugins/gtk+/glade-gtk.c               | 1740 --------------------------------
 po/POTFILES.in                         |    4 +
 10 files changed, 1978 insertions(+), 1740 deletions(-)
---
diff --git a/plugins/gtk+/Makefile.am b/plugins/gtk+/Makefile.am
index 23d7c9a..1a25219 100644
--- a/plugins/gtk+/Makefile.am
+++ b/plugins/gtk+/Makefile.am
@@ -38,6 +38,8 @@ libgladegtk_la_SOURCES =              \
        glade-gtk-assistant.c           \
        glade-gtk-box.c                 \
        glade-gtk-button.c              \
+       glade-gtk-cell-layout.c         \
+       glade-gtk-cell-renderer.c       \
        glade-gtk-combo-box.c           \
        glade-gtk-combo-box-text.c      \
        glade-gtk-container.c           \
@@ -54,6 +56,7 @@ libgladegtk_la_SOURCES =              \
        glade-gtk-image-menu-item.c     \
        glade-gtk-info-bar.c            \
        glade-gtk-label.c               \
+       glade-gtk-list-store.c          \
        glade-gtk-menu.c                \
        glade-gtk-menu-bar.c            \
        glade-gtk-menu-item.c           \
@@ -76,6 +79,7 @@ libgladegtk_la_SOURCES =              \
        glade-gtk-tool-item-group.c     \
        glade-gtk-tool-palette.c        \
        glade-gtk-toolbar.c             \
+       glade-gtk-tree-view.c           \
        glade-gtk-widget.c              \
        glade-gtk-window.c              \
        glade-icon-factory-editor.c     \
@@ -108,11 +112,14 @@ noinst_HEADERS =                  \
        glade-gtk.h                     \
        glade-gtk-action-widgets.h      \
        glade-gtk-button.h              \
+       glade-gtk-cell-layout.h         \
+       glade-gtk-cell-renderer.h       \
        glade-gtk-dialog.h              \
        glade-gtk-frame.h               \
        glade-gtk-image.h               \
        glade-gtk-menu-shell.h          \
        glade-gtk-notebook.h            \
+       glade-gtk-tree-view.h           \
        glade-icon-factory-editor.h     \
        glade-icon-sources.h            \
        glade-image-editor.h            \
diff --git a/plugins/gtk+/glade-gtk-cell-layout.c b/plugins/gtk+/glade-gtk-cell-layout.c
new file mode 100644
index 0000000..ba5ae1f
--- /dev/null
+++ b/plugins/gtk+/glade-gtk-cell-layout.c
@@ -0,0 +1,512 @@
+/*
+ * glade-gtk-cell-layout.c - GladeWidgetAdaptor for GtkCellLayout
+ *
+ * Copyright (C) 2013 Tristan Van Berkom
+ *
+ * Authors:
+ *      Tristan Van Berkom <tristan van berkom gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 <glib/gi18n-lib.h>
+#include <gladeui/glade.h>
+
+#include "glade-gtk.h"
+#include "glade-gtk-cell-renderer.h"
+#include "glade-gtk-tree-view.h"
+#include "glade-cell-renderer-editor.h"
+#include "glade-treeview-editor.h"
+
+gboolean
+glade_gtk_cell_layout_add_verify (GladeWidgetAdaptor *adaptor,
+                                 GtkWidget          *container,
+                                 GtkWidget          *child,
+                                 gboolean            user_feedback)
+{
+  if (!GTK_IS_CELL_RENDERER (child))
+    {
+      if (user_feedback)
+       {
+         GladeWidgetAdaptor *cell_adaptor = 
+           glade_widget_adaptor_get_by_type (GTK_TYPE_CELL_RENDERER);
+
+         glade_util_ui_message (glade_app_get_window (),
+                                GLADE_UI_INFO, NULL,
+                                ONLY_THIS_GOES_IN_THAT_MSG,
+                                glade_widget_adaptor_get_title (cell_adaptor),
+                                glade_widget_adaptor_get_title (adaptor));
+       }
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+void
+glade_gtk_cell_layout_add_child (GladeWidgetAdaptor * adaptor,
+                                 GObject * container, GObject * child)
+{
+  GladeWidget *gmodel = NULL;
+  GladeWidget *grenderer = glade_widget_get_from_gobject (child);
+
+  if (GTK_IS_ICON_VIEW (container) &&
+      (gmodel = glade_cell_renderer_get_model (grenderer)) != NULL)
+    gtk_icon_view_set_model (GTK_ICON_VIEW (container), NULL);
+
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (container),
+                              GTK_CELL_RENDERER (child), TRUE);
+
+  if (gmodel)
+    gtk_icon_view_set_model (GTK_ICON_VIEW (container),
+                             GTK_TREE_MODEL (glade_widget_get_object (gmodel)));
+
+  glade_gtk_cell_renderer_sync_attributes (child);
+}
+
+void
+glade_gtk_cell_layout_remove_child (GladeWidgetAdaptor * adaptor,
+                                    GObject * container, GObject * child)
+{
+  GtkCellLayout *layout = GTK_CELL_LAYOUT (container);
+  GList *l, *children = gtk_cell_layout_get_cells (layout);
+
+  /* Add a reference to every cell except the one we want to remove */
+  for (l = children; l; l = g_list_next (l))
+    if (l->data != child)
+      g_object_ref (l->data);
+    else
+      l->data = NULL;
+
+  /* remove every cell */
+  gtk_cell_layout_clear (layout);
+
+  /* pack others cell renderers */
+  for (l = children; l; l = g_list_next (l))
+    {
+      if (l->data == NULL)
+        continue;
+
+      gtk_cell_layout_pack_start (layout, GTK_CELL_RENDERER (l->data), TRUE);
+
+      /* Remove our transient reference */
+      g_object_unref (l->data);
+    }
+
+  g_list_free (children);
+}
+
+GList *
+glade_gtk_cell_layout_get_children (GladeWidgetAdaptor * adaptor,
+                                    GObject * container)
+{
+  return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (container));
+}
+
+
+void
+glade_gtk_cell_layout_get_child_property (GladeWidgetAdaptor * adaptor,
+                                          GObject * container,
+                                          GObject * child,
+                                          const gchar * property_name,
+                                          GValue * value)
+{
+  if (strcmp (property_name, "position") == 0)
+    {
+      GList *cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (container));
+
+      /* We have to fake it, assume we are loading and always return the last item */
+      g_value_set_int (value, g_list_length (cells) - 1);
+
+      g_list_free (cells);
+    }
+  else
+    /* Chain Up */
+    GWA_GET_CLASS
+        (GTK_TYPE_CONTAINER)->child_get_property (adaptor,
+                                                  container, child,
+                                                  property_name, value);
+}
+
+void
+glade_gtk_cell_layout_set_child_property (GladeWidgetAdaptor * adaptor,
+                                          GObject * container,
+                                          GObject * child,
+                                          const gchar * property_name,
+                                          const GValue * value)
+{
+  if (strcmp (property_name, "position") == 0)
+    {
+      /* Need verify on position property !!! XXX */
+      gtk_cell_layout_reorder (GTK_CELL_LAYOUT (container),
+                               GTK_CELL_RENDERER (child),
+                               g_value_get_int (value));
+    }
+  else
+    /* Chain Up */
+    GWA_GET_CLASS
+        (GTK_TYPE_CONTAINER)->child_set_property (adaptor,
+                                                  container, child,
+                                                  property_name, value);
+}
+
+static void
+glade_gtk_cell_renderer_read_attributes (GladeWidget * widget,
+                                         GladeXmlNode * node)
+{
+  GladeXmlNode *attrs_node;
+  GladeProperty *attr_prop, *use_attr_prop;
+  GladeXmlNode *prop;
+  gchar *name, *column_str, *attr_prop_name, *use_attr_name;
+
+  if ((attrs_node =
+       glade_xml_search_child (node, GLADE_TAG_ATTRIBUTES)) == NULL)
+    return;
+
+  for (prop = glade_xml_node_get_children (attrs_node); prop;
+       prop = glade_xml_node_next (prop))
+    {
+
+      if (!glade_xml_node_verify_silent (prop, GLADE_TAG_ATTRIBUTE))
+        continue;
+
+      name =
+          glade_xml_get_property_string_required (prop, GLADE_TAG_NAME, NULL);
+      column_str = glade_xml_get_content (prop);
+      attr_prop_name = g_strdup_printf ("attr-%s", name);
+      use_attr_name = g_strdup_printf ("use-attr-%s", name);
+
+      attr_prop = glade_widget_get_property (widget, attr_prop_name);
+      use_attr_prop = glade_widget_get_property (widget, use_attr_name);
+
+      if (attr_prop && use_attr_prop)
+        {
+          gboolean use_attribute = FALSE;
+          glade_property_get (use_attr_prop, &use_attribute);
+
+          if (use_attribute)
+            glade_property_set (attr_prop,
+                                g_ascii_strtoll (column_str, NULL, 10));
+        }
+
+      g_free (name);
+      g_free (column_str);
+      g_free (attr_prop_name);
+      g_free (use_attr_name);
+
+    }
+}
+
+void
+glade_gtk_cell_layout_read_child (GladeWidgetAdaptor * adaptor,
+                                  GladeWidget * widget, GladeXmlNode * node)
+{
+  GladeXmlNode *widget_node;
+  GladeWidget *child_widget;
+  gchar *internal_name;
+
+  if (!glade_xml_node_verify (node, GLADE_XML_TAG_CHILD))
+    return;
+
+  internal_name =
+      glade_xml_get_property_string (node, GLADE_XML_TAG_INTERNAL_CHILD);
+
+  if ((widget_node =
+       glade_xml_search_child (node, GLADE_XML_TAG_WIDGET)) != NULL)
+    {
+
+      /* Combo box is a special brand of cell-layout, it can also have the internal entry */
+      if ((child_widget = glade_widget_read (glade_widget_get_project (widget),
+                                             widget, widget_node,
+                                             internal_name)) != NULL)
+        {
+          /* Dont set any packing properties on internal children here,
+           * its possible but just not relevant for known celllayouts...
+           * i.e. maybe GtkTreeViewColumn will expose the internal button ?
+           * but no need for packing properties there either.
+           */
+          if (!internal_name)
+            {
+              glade_widget_add_child (widget, child_widget, FALSE);
+
+              glade_gtk_cell_renderer_read_attributes (child_widget, node);
+
+              g_idle_add ((GSourceFunc) glade_gtk_cell_renderer_sync_attributes,
+                          glade_widget_get_object (child_widget));
+            }
+        }
+    }
+  g_free (internal_name);
+}
+
+static void
+glade_gtk_cell_renderer_write_attributes (GladeWidget * widget,
+                                          GladeXmlContext * context,
+                                          GladeXmlNode * node)
+{
+  GladeProperty *property;
+  GladePropertyClass *pclass;
+  GladeXmlNode *attrs_node;
+  gchar *attr_name;
+  GList *l;
+  static gint attr_len = 0;
+
+  if (!attr_len)
+    attr_len = strlen ("attr-");
+
+  attrs_node = glade_xml_node_new (context, GLADE_TAG_ATTRIBUTES);
+
+  for (l = glade_widget_get_properties (widget); l; l = l->next)
+    {
+      property = l->data;
+      pclass   = glade_property_get_class (property);
+
+      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) == 0)
+        {
+          GladeXmlNode *attr_node;
+          gchar *column_str, *use_attr_str;
+          gboolean use_attr = FALSE;
+
+          use_attr_str = g_strdup_printf ("use-%s", glade_property_class_id (pclass));
+          glade_widget_property_get (widget, use_attr_str, &use_attr);
+
+          if (use_attr && g_value_get_int (glade_property_inline_value (property)) >= 0)
+            {
+              column_str =
+                  g_strdup_printf ("%d", g_value_get_int (glade_property_inline_value (property)));
+              attr_name = (gchar *)&glade_property_class_id (pclass)[attr_len];
+
+              attr_node = glade_xml_node_new (context, GLADE_TAG_ATTRIBUTE);
+              glade_xml_node_append_child (attrs_node, attr_node);
+              glade_xml_node_set_property_string (attr_node, GLADE_TAG_NAME,
+                                                  attr_name);
+              glade_xml_set_content (attr_node, column_str);
+              g_free (column_str);
+            }
+          g_free (use_attr_str);
+        }
+    }
+
+  if (!glade_xml_node_get_children (attrs_node))
+    glade_xml_node_delete (attrs_node);
+  else
+    glade_xml_node_append_child (node, attrs_node);
+}
+
+void
+glade_gtk_cell_layout_write_child (GladeWidgetAdaptor * adaptor,
+                                   GladeWidget * widget,
+                                   GladeXmlContext * context,
+                                   GladeXmlNode * node)
+{
+  GladeXmlNode *child_node;
+
+  child_node = glade_xml_node_new (context, GLADE_XML_TAG_CHILD);
+  glade_xml_node_append_child (node, child_node);
+
+  /* ComboBox can have an internal entry */
+  if (glade_widget_get_internal (widget))
+    glade_xml_node_set_property_string (child_node,
+                                        GLADE_XML_TAG_INTERNAL_CHILD,
+                                        glade_widget_get_internal (widget));
+
+  /* Write out the widget */
+  glade_widget_write (widget, context, child_node);
+
+  glade_gtk_cell_renderer_write_attributes (widget, context, child_node);
+}
+
+gchar *
+glade_gtk_cell_layout_get_display_name (GladeBaseEditor * editor,
+                                        GladeWidget * gchild,
+                                        gpointer user_data)
+{
+  GObject *child = glade_widget_get_object (gchild);
+  gchar *name;
+
+  if (GTK_IS_TREE_VIEW_COLUMN (child))
+    glade_widget_property_get (gchild, "title", &name);
+  else
+    name = (gchar *)glade_widget_get_name (gchild);
+
+  return g_strdup (name);
+}
+
+void
+glade_gtk_cell_layout_child_selected (GladeBaseEditor * editor,
+                                      GladeWidget * gchild, gpointer data)
+{
+  GObject *child = glade_widget_get_object (gchild);
+
+  glade_base_editor_add_label (editor, GTK_IS_TREE_VIEW_COLUMN (child) ?
+                               _("Tree View Column") : _("Cell Renderer"));
+
+  glade_base_editor_add_default_properties (editor, gchild);
+
+  glade_base_editor_add_label (editor, GTK_IS_TREE_VIEW_COLUMN (child) ?
+                               _("Properties") :
+                               _("Properties and Attributes"));
+  glade_base_editor_add_editable (editor, gchild, GLADE_PAGE_GENERAL);
+
+  if (GTK_IS_CELL_RENDERER (child))
+    {
+      glade_base_editor_add_label (editor,
+                                   _("Common Properties and Attributes"));
+      glade_base_editor_add_editable (editor, gchild, GLADE_PAGE_COMMON);
+    }
+}
+
+gboolean
+glade_gtk_cell_layout_move_child (GladeBaseEditor * editor,
+                                  GladeWidget * gparent,
+                                  GladeWidget * gchild, gpointer data)
+{
+  GObject *parent = glade_widget_get_object (gparent);
+  GObject *child = glade_widget_get_object (gchild);
+  GList list = { 0, };
+
+  if (GTK_IS_TREE_VIEW (parent) && !GTK_IS_TREE_VIEW_COLUMN (child))
+    return FALSE;
+  if (GTK_IS_CELL_LAYOUT (parent) && !GTK_IS_CELL_RENDERER (child))
+    return FALSE;
+  if (GTK_IS_CELL_RENDERER (parent))
+    return FALSE;
+
+  if (gparent != glade_widget_get_parent (gchild))
+    {
+      list.data = gchild;
+      glade_command_dnd (&list, gparent, NULL);
+    }
+
+  return TRUE;
+}
+
+static void
+glade_gtk_cell_layout_launch_editor (GObject *layout, gchar *window_name)
+{
+  GladeWidget        *widget  = glade_widget_get_from_gobject (layout);
+  GladeWidgetAdaptor *adaptor = glade_widget_get_adaptor (widget);
+  GladeBaseEditor    *editor;
+  GladeEditable      *layout_editor;
+  GtkWidget          *window;
+
+  layout_editor = glade_widget_adaptor_create_editable (adaptor, GLADE_PAGE_GENERAL);
+  layout_editor = (GladeEditable *) glade_tree_view_editor_new (adaptor, layout_editor);
+
+  /* Editor */
+  editor = glade_base_editor_new (layout, layout_editor,
+                                  _("Text"), GTK_TYPE_CELL_RENDERER_TEXT,
+                                  _("Accelerator"), GTK_TYPE_CELL_RENDERER_ACCEL,
+                                  _("Combo"), GTK_TYPE_CELL_RENDERER_COMBO,
+                                  _("Spin"), GTK_TYPE_CELL_RENDERER_SPIN,
+                                  _("Pixbuf"), GTK_TYPE_CELL_RENDERER_PIXBUF,
+                                  _("Progress"), GTK_TYPE_CELL_RENDERER_PROGRESS,
+                                  _("Toggle"), GTK_TYPE_CELL_RENDERER_TOGGLE,
+                                  _("Spinner"), GTK_TYPE_CELL_RENDERER_SPINNER,
+                                  NULL);
+
+  g_signal_connect (editor, "get-display-name",
+                    G_CALLBACK (glade_gtk_cell_layout_get_display_name), NULL);
+  g_signal_connect (editor, "child-selected",
+                    G_CALLBACK (glade_gtk_cell_layout_child_selected), NULL);
+  g_signal_connect (editor, "move-child",
+                    G_CALLBACK (glade_gtk_cell_layout_move_child), NULL);
+
+  gtk_widget_show (GTK_WIDGET (editor));
+
+  window = glade_base_editor_pack_new_window (editor, window_name, NULL);
+  gtk_widget_show (window);
+}
+
+
+static void
+glade_gtk_cell_layout_launch_editor_action (GObject * object)
+{
+  GladeWidget *w = glade_widget_get_from_gobject (object);
+
+  do
+    {
+      GObject *obj = glade_widget_get_object (w);
+
+      if (GTK_IS_TREE_VIEW (obj))
+        {
+          glade_gtk_treeview_launch_editor (obj);
+          break;
+        }
+      else if (GTK_IS_ICON_VIEW (obj))
+        {
+          glade_gtk_cell_layout_launch_editor (obj, _("Icon View Editor"));
+          break;
+        }
+      else if (GTK_IS_COMBO_BOX (obj))
+        {
+          glade_gtk_cell_layout_launch_editor (obj, _("Combo Editor"));
+          break;
+        }
+      else if (GTK_IS_ENTRY_COMPLETION (obj))
+        {
+          glade_gtk_cell_layout_launch_editor (obj, _("Entry Completion Editor"));
+          break;
+        }
+    }
+  while ((w = glade_widget_get_parent (w)));
+}
+
+void
+glade_gtk_cell_layout_action_activate (GladeWidgetAdaptor * adaptor,
+                                       GObject * object,
+                                       const gchar * action_path)
+{
+  if (strcmp (action_path, "launch_editor") == 0)
+    glade_gtk_cell_layout_launch_editor_action (object);
+  else
+    GWA_GET_CLASS (G_TYPE_OBJECT)->action_activate (adaptor,
+                                                    object, action_path);
+}
+
+void
+glade_gtk_cell_layout_action_activate_as_widget (GladeWidgetAdaptor * adaptor,
+                                                 GObject * object,
+                                                 const gchar * action_path)
+{
+  if (strcmp (action_path, "launch_editor") == 0)
+    glade_gtk_cell_layout_launch_editor_action (object);
+  else
+    GWA_GET_CLASS (GTK_TYPE_WIDGET)->action_activate (adaptor,
+                                                      object, action_path);
+}
+
+gboolean
+glade_gtk_cell_layout_sync_attributes (GObject * layout)
+{
+  GladeWidget *gwidget = glade_widget_get_from_gobject (layout);
+  GObject *cell;
+  GList *children, *l;
+
+  children = glade_widget_get_children (gwidget);
+  for (l = children; l; l = l->next)
+    {
+      cell = l->data;
+      if (!GTK_IS_CELL_RENDERER (cell))
+        continue;
+
+      glade_gtk_cell_renderer_sync_attributes (cell);
+    }
+  g_list_free (children);
+
+  return FALSE;
+}
diff --git a/plugins/gtk+/glade-gtk-cell-layout.h b/plugins/gtk+/glade-gtk-cell-layout.h
new file mode 100644
index 0000000..5fe3eb6
--- /dev/null
+++ b/plugins/gtk+/glade-gtk-cell-layout.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2013 Tristan Van Berkom.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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_GTK_CELL_LAYOUT_H_
+#define _GLADE_GTK_CELL_LAYOUT_H_
+
+#include <gtk/gtk.h>
+#include <gladeui/glade.h>
+
+G_BEGIN_DECLS
+
+gboolean glade_gtk_cell_layout_sync_attributes (GObject * layout);
+
+/* Base editor handlers */
+gchar   *glade_gtk_cell_layout_get_display_name (GladeBaseEditor * editor,
+                                                GladeWidget * gchild,
+                                                gpointer user_data);
+void     glade_gtk_cell_layout_child_selected   (GladeBaseEditor * editor,
+                                                GladeWidget * gchild,
+                                                gpointer data);
+gboolean glade_gtk_cell_layout_move_child       (GladeBaseEditor * editor,
+                                                GladeWidget * gparent,
+                                                GladeWidget * gchild,
+                                                gpointer data); 
+
+G_END_DECLS
+
+#endif  /* _GLADE_GTK_CELL_LAYOUT_H_ */
diff --git a/plugins/gtk+/glade-gtk-cell-renderer.c b/plugins/gtk+/glade-gtk-cell-renderer.c
new file mode 100644
index 0000000..7eab9d4
--- /dev/null
+++ b/plugins/gtk+/glade-gtk-cell-renderer.c
@@ -0,0 +1,411 @@
+/*
+ * glade-gtk-cell-renderer.c - GladeWidgetAdaptor for GtkCellRenderer
+ *
+ * Copyright (C) 2013 Tristan Van Berkom
+ *
+ * Authors:
+ *      Tristan Van Berkom <tristan van berkom gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 <glib/gi18n-lib.h>
+#include <gladeui/glade.h>
+
+#include "glade-gtk-image.h" /* For GtkIconSize serialization */
+#include "glade-gtk-tree-view.h"
+#include "glade-gtk-cell-renderer.h"
+#include "glade-cell-renderer-editor.h"
+#include "glade-column-types.h"
+
+void
+glade_gtk_cell_renderer_action_activate (GladeWidgetAdaptor * adaptor,
+                                         GObject * object,
+                                         const gchar * action_path)
+{
+  if (strcmp (action_path, "launch_editor") == 0)
+    {
+      GladeWidget *w = glade_widget_get_from_gobject (object);
+
+      while ((w = glade_widget_get_parent (w)))
+        {
+         GObject *object = glade_widget_get_object (w);
+
+          if (GTK_IS_TREE_VIEW (object))
+            {
+              glade_gtk_treeview_launch_editor (object);
+              break;
+            }
+        }
+    }
+  else
+    GWA_GET_CLASS (G_TYPE_OBJECT)->action_activate (adaptor, object, action_path);
+}
+
+void
+glade_gtk_cell_renderer_deep_post_create (GladeWidgetAdaptor * adaptor,
+                                          GObject * object,
+                                          GladeCreateReason reason)
+{
+  GladePropertyClass *pclass;
+  GladeProperty *property;
+  GladeWidget *widget;
+  const GList *l;
+
+  widget = glade_widget_get_from_gobject (object);
+
+  for (l = glade_widget_adaptor_get_properties (adaptor); l; l = l->next)
+    {
+      pclass = l->data;
+
+      if (strncmp (glade_property_class_id (pclass), "use-attr-", strlen ("use-attr-")) == 0)
+        {
+          property = glade_widget_get_property (widget, glade_property_class_id (pclass));
+          glade_property_sync (property);
+        }
+    }
+
+  g_idle_add ((GSourceFunc) glade_gtk_cell_renderer_sync_attributes, object);
+}
+
+GladeEditorProperty *
+glade_gtk_cell_renderer_create_eprop (GladeWidgetAdaptor * adaptor,
+                                      GladePropertyClass * klass,
+                                      gboolean use_command)
+{
+  GladeEditorProperty *eprop;
+
+  if (strncmp (glade_property_class_id (klass), "attr-", strlen ("attr-")) == 0)
+    eprop = g_object_new (GLADE_TYPE_EPROP_CELL_ATTRIBUTE,
+                          "property-class", klass,
+                          "use-command", use_command, NULL);
+  else
+    eprop = GWA_GET_CLASS
+        (G_TYPE_OBJECT)->create_eprop (adaptor, klass, use_command);
+  return eprop;
+}
+
+
+GladeEditable *
+glade_gtk_cell_renderer_create_editable (GladeWidgetAdaptor * adaptor,
+                                         GladeEditorPageType type)
+{
+  GladeEditable *editable;
+
+  /* Get base editable */
+  editable = GWA_GET_CLASS (G_TYPE_OBJECT)->create_editable (adaptor, type);
+
+  if (type == GLADE_PAGE_GENERAL || type == GLADE_PAGE_COMMON)
+    return (GladeEditable *) glade_cell_renderer_editor_new (adaptor, type,
+                                                             editable);
+
+  return editable;
+}
+
+static void
+glade_gtk_cell_renderer_set_use_attribute (GObject * object,
+                                           const gchar * property_name,
+                                           const GValue * value)
+{
+  GladeWidget *widget = glade_widget_get_from_gobject (object);
+  gchar *attr_prop_name, *prop_msg, *attr_msg;
+
+  attr_prop_name = g_strdup_printf ("attr-%s", property_name);
+
+  prop_msg = g_strdup_printf (_("%s is set to load %s from the model"),
+                              glade_widget_get_name (widget), property_name);
+  attr_msg = g_strdup_printf (_("%s is set to manipulate %s directly"),
+                              glade_widget_get_name (widget), attr_prop_name);
+
+  glade_widget_property_set_sensitive (widget, property_name, FALSE, prop_msg);
+  glade_widget_property_set_sensitive (widget, attr_prop_name, FALSE, attr_msg);
+
+  if (g_value_get_boolean (value))
+    glade_widget_property_set_sensitive (widget, attr_prop_name, TRUE, NULL);
+  else
+    {
+      GladeProperty *property =
+          glade_widget_get_property (widget, property_name);
+
+      glade_property_set_sensitive (property, TRUE, NULL);
+      glade_property_sync (property);
+    }
+
+  g_free (prop_msg);
+  g_free (attr_msg);
+  g_free (attr_prop_name);
+}
+
+static GladeProperty *
+glade_gtk_cell_renderer_attribute_switch (GladeWidget * gwidget,
+                                          const gchar * property_name)
+{
+  GladeProperty *property;
+  gchar *use_attr_name = g_strdup_printf ("use-attr-%s", property_name);
+
+  property = glade_widget_get_property (gwidget, use_attr_name);
+  g_free (use_attr_name);
+
+  return property;
+}
+
+static gboolean
+glade_gtk_cell_renderer_property_enabled (GObject * object,
+                                          const gchar * property_name)
+{
+  GladeProperty *property;
+  GladeWidget *gwidget = glade_widget_get_from_gobject (object);
+  gboolean use_attr = TRUE;
+
+  if ((property =
+       glade_gtk_cell_renderer_attribute_switch (gwidget,
+                                                 property_name)) != NULL)
+    glade_property_get (property, &use_attr);
+
+  return !use_attr;
+}
+
+
+void
+glade_gtk_cell_renderer_set_property (GladeWidgetAdaptor * adaptor,
+                                      GObject * object,
+                                      const gchar * property_name,
+                                      const GValue * value)
+{
+  static gint use_attr_len = 0;
+  static gint attr_len = 0;
+
+  if (!attr_len)
+    {
+      use_attr_len = strlen ("use-attr-");
+      attr_len = strlen ("attr-");
+    }
+
+  if (strncmp (property_name, "use-attr-", use_attr_len) == 0)
+    glade_gtk_cell_renderer_set_use_attribute (object,
+                                               &property_name[use_attr_len],
+                                               value);
+  else if (strncmp (property_name, "attr-", attr_len) == 0)
+    glade_gtk_cell_renderer_sync_attributes (object);
+  else if (glade_gtk_cell_renderer_property_enabled (object, property_name))
+    /* Chain Up */
+    GWA_GET_CLASS (G_TYPE_OBJECT)->set_property (adaptor,
+                                                 object, property_name, value);
+}
+
+static void
+glade_gtk_cell_renderer_write_properties (GladeWidget * widget,
+                                          GladeXmlContext * context,
+                                          GladeXmlNode * node)
+{
+  GladeProperty *property, *prop;
+  GladePropertyClass *pclass;
+  gchar *attr_name;
+  GList *l;
+  static gint attr_len = 0;
+
+  if (!attr_len)
+    attr_len = strlen ("attr-");
+
+  for (l = glade_widget_get_properties (widget); l; l = l->next)
+    {
+      property = l->data;
+      pclass   = glade_property_get_class (property);
+
+      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) == 0)
+        {
+          gchar *use_attr_str;
+          gboolean use_attr = FALSE;
+
+          use_attr_str = g_strdup_printf ("use-%s", glade_property_class_id (pclass));
+          glade_widget_property_get (widget, use_attr_str, &use_attr);
+
+          attr_name = (gchar *)&glade_property_class_id (pclass)[attr_len];
+          prop = glade_widget_get_property (widget, attr_name);
+
+          if (!use_attr && prop)
+           {
+             /* Special case to write GtkCellRendererPixbuf:stock-size */
+             if (strcmp (attr_name, "stock-size") == 0)
+               glade_gtk_write_icon_size (widget, context, node, "stock-size");
+             else
+               glade_property_write (prop, context, node);
+           }
+
+          g_free (use_attr_str);
+        }
+    }
+}
+
+void
+glade_gtk_cell_renderer_write_widget (GladeWidgetAdaptor * adaptor,
+                                      GladeWidget * widget,
+                                      GladeXmlContext * context,
+                                      GladeXmlNode * node)
+{
+  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
+       glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
+    return;
+
+  /* Write our normal properties, then chain up to write any other normal properties,
+   * then attributes 
+   */
+  glade_gtk_cell_renderer_write_properties (widget, context, node);
+
+  GWA_GET_CLASS (G_TYPE_OBJECT)->write_widget (adaptor, widget, context, node);
+}
+
+static void
+glade_gtk_cell_renderer_parse_finished (GladeProject * project,
+                                        GladeWidget * widget)
+{
+  GladeProperty *property;
+  GList *l;
+  static gint attr_len = 0, use_attr_len = 0;
+
+  /* Set "use-attr-*" everywhere that the object property is non-default 
+   *
+   * We do this in the finished handler because some properties may be
+   * object type properties (which may be anywhere in the glade file).
+   */
+  if (!attr_len)
+    {
+      attr_len = strlen ("attr-");
+      use_attr_len = strlen ("use-attr-");
+    }
+
+  for (l = glade_widget_get_properties (widget); l; l = l->next)
+    {
+      GladeProperty *switch_prop;
+      GladePropertyClass *pclass;
+
+      property = l->data;
+      pclass   = glade_property_get_class (property);
+
+      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) != 0 &&
+          strncmp (glade_property_class_id (pclass), "use-attr-", use_attr_len) != 0 &&
+          (switch_prop =
+           glade_gtk_cell_renderer_attribute_switch (widget,
+                                                     glade_property_class_id (pclass))) != NULL)
+        {
+          if (glade_property_original_default (property))
+            glade_property_set (switch_prop, TRUE);
+          else
+            glade_property_set (switch_prop, FALSE);
+        }
+    }
+}
+
+void
+glade_gtk_cell_renderer_read_widget (GladeWidgetAdaptor * adaptor,
+                                     GladeWidget * widget, GladeXmlNode * node)
+{
+  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
+       glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
+    return;
+
+  /* First chain up and read in all the properties... */
+  GWA_GET_CLASS (G_TYPE_OBJECT)->read_widget (adaptor, widget, node);
+
+  g_signal_connect (glade_widget_get_project (widget), "parse-finished",
+                    G_CALLBACK (glade_gtk_cell_renderer_parse_finished),
+                    widget);
+}
+
+static gboolean
+glade_gtk_cell_layout_has_renderer (GtkCellLayout * layout,
+                                    GtkCellRenderer * renderer)
+{
+  GList *cells = gtk_cell_layout_get_cells (layout);
+  gboolean has_renderer;
+
+  has_renderer = (g_list_find (cells, renderer) != NULL);
+
+  g_list_free (cells);
+
+  return has_renderer;
+}
+
+gboolean
+glade_gtk_cell_renderer_sync_attributes (GObject * object)
+{
+
+  GtkCellLayout *layout;
+  GtkCellRenderer *cell;
+  GladeWidget *widget;
+  GladeWidget *parent;
+  GladeWidget *gmodel;
+  GladeProperty *property;
+  GladePropertyClass *pclass;
+  gchar *attr_prop_name;
+  GList *l, *column_list = NULL;
+  gint columns = 0;
+  static gint attr_len = 0;
+
+  if (!attr_len)
+    attr_len = strlen ("attr-");
+
+  /* Apply attributes to renderer when bound to a model in runtime */
+  widget = glade_widget_get_from_gobject (object);
+
+  parent = glade_widget_get_parent (widget);
+  if (parent == NULL)
+    return FALSE;
+
+  /* When creating widgets, sometimes the parent is set before parenting happens,
+   * here we have to be careful for that..
+   */
+  layout = GTK_CELL_LAYOUT (glade_widget_get_object (parent));
+  cell   = GTK_CELL_RENDERER (object);
+
+  if (!glade_gtk_cell_layout_has_renderer (layout, cell))
+    return FALSE;
+
+  if ((gmodel = glade_cell_renderer_get_model (widget)) == NULL)
+    return FALSE;
+
+  glade_widget_property_get (gmodel, "columns", &column_list);
+  columns = g_list_length (column_list);
+
+  gtk_cell_layout_clear_attributes (layout, cell);
+
+  for (l = glade_widget_get_properties (widget); l; l = l->next)
+    {
+      property = l->data;
+      pclass   = glade_property_get_class (property);
+
+      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) == 0)
+        {
+          gint column = g_value_get_int (glade_property_inline_value (property));
+
+          attr_prop_name = (gchar *)&glade_property_class_id (pclass)[attr_len];
+
+          if (column >= 0 && column < columns)
+            {
+              GladeColumnType *column_type =
+                  (GladeColumnType *) g_list_nth_data (column_list, column);
+              GType column_gtype = g_type_from_name (column_type->type_name);
+             GParamSpec *pspec = glade_property_class_get_pspec (pclass);
+
+              if (column_gtype &&
+                  g_value_type_transformable (column_gtype, pspec->value_type))
+                gtk_cell_layout_add_attribute (layout, cell, attr_prop_name, column);
+            }
+        }
+    }
+
+  return FALSE;
+}
diff --git a/plugins/gtk+/glade-gtk-cell-renderer.h b/plugins/gtk+/glade-gtk-cell-renderer.h
new file mode 100644
index 0000000..6b2a4dd
--- /dev/null
+++ b/plugins/gtk+/glade-gtk-cell-renderer.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 Tristan Van Berkom.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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_GTK_CELL_RENDERER_H_
+#define _GLADE_GTK_CELL_RENDERER_H_
+
+#include <gtk/gtk.h>
+#include <gladeui/glade.h>
+
+G_BEGIN_DECLS
+
+gboolean glade_gtk_cell_renderer_sync_attributes (GObject * object);
+
+G_END_DECLS
+
+#endif  /* _GLADE_GTK_CELL_RENDERER_H_ */
diff --git a/plugins/gtk+/glade-gtk-list-store.c b/plugins/gtk+/glade-gtk-list-store.c
new file mode 100644
index 0000000..785ebfa
--- /dev/null
+++ b/plugins/gtk+/glade-gtk-list-store.c
@@ -0,0 +1,658 @@
+/*
+ * glade-gtk-list-store.c - GladeWidgetAdaptor for GtkListStore
+ *
+ * Copyright (C) 2013 Tristan Van Berkom
+ *
+ * Authors:
+ *      Tristan Van Berkom <tristan van berkom gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 <glib/gi18n-lib.h>
+#include <gladeui/glade.h>
+
+#include "glade-cell-renderer-editor.h"
+#include "glade-store-editor.h"
+#include "glade-column-types.h"
+#include "glade-model-data.h"
+#include "glade-gtk-cell-layout.h"
+
+#define GLADE_TAG_COLUMNS      "columns"
+#define GLADE_TAG_COLUMN       "column"
+#define GLADE_TAG_TYPE         "type"
+
+#define GLADE_TAG_ROW           "row"
+#define GLADE_TAG_DATA          "data"
+#define GLADE_TAG_COL           "col"
+
+static void
+glade_gtk_store_set_columns (GObject * object, const GValue * value)
+{
+  GList *l;
+  gint i, n;
+  GType *types;
+
+  for (i = 0, l = g_value_get_boxed (value), n = g_list_length (l), types =
+       g_new (GType, n); l; l = g_list_next (l), i++)
+    {
+      GladeColumnType *data = l->data;
+
+      if (g_type_from_name (data->type_name) != G_TYPE_INVALID)
+        types[i] = g_type_from_name (data->type_name);
+      else
+        types[i] = G_TYPE_POINTER;
+    }
+
+  if (GTK_IS_LIST_STORE (object))
+    gtk_list_store_set_column_types (GTK_LIST_STORE (object), n, types);
+  else
+    gtk_tree_store_set_column_types (GTK_TREE_STORE (object), n, types);
+
+  g_free (types);
+}
+
+static void
+glade_gtk_store_set_data (GObject * object, const GValue * value)
+{
+  GladeWidget *gwidget = glade_widget_get_from_gobject (object);
+  GList *columns = NULL;
+  GNode *data_tree, *row, *iter;
+  gint colnum;
+  GtkTreeIter row_iter;
+  GladeModelData *data;
+  GType column_type;
+
+  if (GTK_IS_LIST_STORE (object))
+    gtk_list_store_clear (GTK_LIST_STORE (object));
+  else
+    gtk_tree_store_clear (GTK_TREE_STORE (object));
+
+  glade_widget_property_get (gwidget, "columns", &columns);
+  data_tree = g_value_get_boxed (value);
+
+  /* Nothing to enter without columns defined */
+  if (!data_tree || !columns)
+    return;
+
+  for (row = data_tree->children; row; row = row->next)
+    {
+      if (GTK_IS_LIST_STORE (object))
+        gtk_list_store_append (GTK_LIST_STORE (object), &row_iter);
+      else
+        /* (for now no child data... ) */
+        gtk_tree_store_append (GTK_TREE_STORE (object), &row_iter, NULL);
+
+      for (colnum = 0, iter = row->children; iter; colnum++, iter = iter->next)
+        {
+          data = iter->data;
+
+          if (!g_list_nth (columns, colnum))
+            break;
+
+          /* Abort if theres a type mismatch, the widget's being rebuilt
+           * and a sync will come soon with the right values
+           */
+          column_type =
+              gtk_tree_model_get_column_type (GTK_TREE_MODEL (object), colnum);
+          if (G_VALUE_TYPE (&data->value) != column_type)
+            continue;
+
+          if (GTK_IS_LIST_STORE (object))
+            gtk_list_store_set_value (GTK_LIST_STORE (object),
+                                      &row_iter, colnum, &data->value);
+          else
+            gtk_tree_store_set_value (GTK_TREE_STORE (object),
+                                      &row_iter, colnum, &data->value);
+        }
+    }
+}
+
+void
+glade_gtk_store_set_property (GladeWidgetAdaptor * adaptor,
+                              GObject * object,
+                              const gchar * property_name, const GValue * value)
+{
+  if (strcmp (property_name, "columns") == 0)
+    {
+      glade_gtk_store_set_columns (object, value);
+    }
+  else if (strcmp (property_name, "data") == 0)
+    {
+      glade_gtk_store_set_data (object, value);
+    }
+  else
+    /* Chain Up */
+    GWA_GET_CLASS (G_TYPE_OBJECT)->set_property (adaptor,
+                                                 object, property_name, value);
+}
+
+GladeEditorProperty *
+glade_gtk_store_create_eprop (GladeWidgetAdaptor * adaptor,
+                              GladePropertyClass * klass, gboolean use_command)
+{
+  GladeEditorProperty *eprop;
+  GParamSpec          *pspec;
+
+  pspec = glade_property_class_get_pspec (klass);
+
+  /* chain up.. */
+  if (pspec->value_type == GLADE_TYPE_COLUMN_TYPE_LIST)
+    eprop = g_object_new (GLADE_TYPE_EPROP_COLUMN_TYPES,
+                          "property-class", klass,
+                          "use-command", use_command, NULL);
+  else if (pspec->value_type == GLADE_TYPE_MODEL_DATA_TREE)
+    eprop = g_object_new (GLADE_TYPE_EPROP_MODEL_DATA,
+                          "property-class", klass,
+                          "use-command", use_command, NULL);
+  else
+    eprop = GWA_GET_CLASS
+        (G_TYPE_OBJECT)->create_eprop (adaptor, klass, use_command);
+  return eprop;
+}
+
+
+static void
+glade_gtk_store_columns_changed (GladeProperty * property,
+                                 GValue * old_value,
+                                 GValue * new_value, GladeWidget * store)
+{
+  GList *l, *list, *children, *prop_refs;
+
+  /* Reset the attributes for all cell renderers referring to this store */
+  prop_refs = glade_widget_list_prop_refs (store);
+  for (l = prop_refs; l; l = l->next)
+    {
+      GladeWidget *referring_widget = glade_property_get_widget (GLADE_PROPERTY (l->data));
+      GObject     *referring_object = glade_widget_get_object (referring_widget);
+
+      if (GTK_IS_CELL_LAYOUT (referring_object))
+        glade_gtk_cell_layout_sync_attributes (referring_object);
+      else if (GTK_IS_TREE_VIEW (referring_object))
+        {
+          children = glade_widget_get_children (referring_widget);
+
+          for (list = children; list; list = list->next)
+            {
+              /* Clear the GtkTreeViewColumns... */
+              if (GTK_IS_CELL_LAYOUT (list->data))
+                glade_gtk_cell_layout_sync_attributes (G_OBJECT (list->data));
+            }
+
+          g_list_free (children);
+        }
+    }
+  g_list_free (prop_refs);
+}
+
+void
+glade_gtk_store_post_create (GladeWidgetAdaptor * adaptor,
+                             GObject * object, GladeCreateReason reason)
+{
+  GladeWidget *gwidget;
+  GladeProperty *property;
+
+  if (reason == GLADE_CREATE_REBUILD)
+    return;
+
+  gwidget = glade_widget_get_from_gobject (object);
+  property = glade_widget_get_property (gwidget, "columns");
+
+  /* Here we watch the value-changed signal on the "columns" property, we need
+   * to reset all the Cell Renderer attributes when the underlying "columns" change,
+   * the reason we do it from "value-changed" is because GladeWidget prop references
+   * are unavailable while rebuilding an object, and the liststore needs to be rebuilt
+   * in order to set the columns.
+   *
+   * This signal will be envoked after applying the new column types to the store
+   * and before the views get any signal to update themselves from the changed model,
+   * perfect time to reset the attributes.
+   */
+  g_signal_connect (G_OBJECT (property), "value-changed",
+                    G_CALLBACK (glade_gtk_store_columns_changed), gwidget);
+}
+
+GladeEditable *
+glade_gtk_store_create_editable (GladeWidgetAdaptor * adaptor,
+                                 GladeEditorPageType type)
+{
+  GladeEditable *editable;
+
+  /* Get base editable */
+  editable = GWA_GET_CLASS (G_TYPE_OBJECT)->create_editable (adaptor, type);
+
+  if (type == GLADE_PAGE_GENERAL)
+    return (GladeEditable *) glade_store_editor_new (adaptor, editable);
+
+  return editable;
+}
+
+gchar *
+glade_gtk_store_string_from_value (GladeWidgetAdaptor * adaptor,
+                                   GladePropertyClass * klass,
+                                   const GValue * value)
+{
+  GString *string;
+  GParamSpec *pspec;
+
+  pspec = glade_property_class_get_pspec (klass);
+
+  if (pspec->value_type == GLADE_TYPE_COLUMN_TYPE_LIST)
+    {
+      GList *l;
+      string = g_string_new ("");
+      for (l = g_value_get_boxed (value); l; l = g_list_next (l))
+        {
+          GladeColumnType *data = l->data;
+          g_string_append_printf (string,
+                                  (g_list_next (l)) ? "%s:%s|" : "%s:%s",
+                                  data->type_name, data->column_name);
+        }
+      return g_string_free (string, FALSE);
+    }
+  else if (pspec->value_type == GLADE_TYPE_MODEL_DATA_TREE)
+    {
+      GladeModelData *data;
+      GNode *data_tree, *row, *iter;
+      gint rownum;
+      gchar *str;
+      gboolean is_last;
+
+      /* Return a unique string for the backend to compare */
+      data_tree = g_value_get_boxed (value);
+
+      if (!data_tree || !data_tree->children)
+        return g_strdup ("");
+
+      string = g_string_new ("");
+      for (rownum = 0, row = data_tree->children; row;
+           rownum++, row = row->next)
+        {
+          for (iter = row->children; iter; iter = iter->next)
+            {
+              data = iter->data;
+
+              if (!G_VALUE_TYPE (&data->value) ||
+                  G_VALUE_TYPE (&data->value) == G_TYPE_INVALID)
+                str = g_strdup ("(virtual)");
+              else if (G_VALUE_TYPE (&data->value) != G_TYPE_POINTER)
+                str = glade_utils_string_from_value (&data->value);
+              else
+                str = g_strdup ("(null)");
+
+              is_last = !row->next && !iter->next;
+              g_string_append_printf (string, "%s[%d]:%s",
+                                      data->name, rownum, str);
+
+              if (data->i18n_translatable)
+                g_string_append_printf (string, " translatable");
+              if (data->i18n_context)
+                g_string_append_printf (string, " i18n-context:%s",
+                                        data->i18n_context);
+              if (data->i18n_comment)
+                g_string_append_printf (string, " i18n-comment:%s",
+                                        data->i18n_comment);
+
+              if (!is_last)
+                g_string_append_printf (string, "|");
+
+              g_free (str);
+            }
+        }
+      return g_string_free (string, FALSE);
+    }
+  else
+    return GWA_GET_CLASS
+        (G_TYPE_OBJECT)->string_from_value (adaptor, klass, value);
+}
+
+static void
+glade_gtk_store_write_columns (GladeWidget * widget,
+                               GladeXmlContext * context, GladeXmlNode * node)
+{
+  GladeXmlNode *columns_node;
+  GladeProperty *prop;
+  GList *l;
+
+  prop = glade_widget_get_property (widget, "columns");
+
+  columns_node = glade_xml_node_new (context, GLADE_TAG_COLUMNS);
+
+  for (l = g_value_get_boxed (glade_property_inline_value (prop)); l; l = g_list_next (l))
+    {
+      GladeColumnType *data = l->data;
+      GladeXmlNode *column_node, *comment_node;
+
+      /* Write column names in comments... */
+      gchar *comment = g_strdup_printf (" column-name %s ", data->column_name);
+      comment_node = glade_xml_node_new_comment (context, comment);
+      glade_xml_node_append_child (columns_node, comment_node);
+      g_free (comment);
+
+      column_node = glade_xml_node_new (context, GLADE_TAG_COLUMN);
+      glade_xml_node_append_child (columns_node, column_node);
+      glade_xml_node_set_property_string (column_node, GLADE_TAG_TYPE,
+                                          data->type_name);
+    }
+
+  if (!glade_xml_node_get_children (columns_node))
+    glade_xml_node_delete (columns_node);
+  else
+    glade_xml_node_append_child (node, columns_node);
+
+}
+
+static void
+glade_gtk_store_write_data (GladeWidget * widget,
+                            GladeXmlContext * context, GladeXmlNode * node)
+{
+  GladeXmlNode *data_node, *col_node, *row_node;
+  GList *columns = NULL;
+  GladeModelData *data;
+  GNode *data_tree = NULL, *row, *iter;
+  gint colnum;
+
+  glade_widget_property_get (widget, "data", &data_tree);
+  glade_widget_property_get (widget, "columns", &columns);
+
+  /* XXX log errors about data not fitting columns here when
+   * loggin is available
+   */
+  if (!data_tree || !columns)
+    return;
+
+  data_node = glade_xml_node_new (context, GLADE_TAG_DATA);
+
+  for (row = data_tree->children; row; row = row->next)
+    {
+      row_node = glade_xml_node_new (context, GLADE_TAG_ROW);
+      glade_xml_node_append_child (data_node, row_node);
+
+      for (colnum = 0, iter = row->children; iter; colnum++, iter = iter->next)
+        {
+          gchar *string, *column_number;
+
+          data = iter->data;
+
+          /* Skip non-serializable data */
+          if (G_VALUE_TYPE (&data->value) == 0 ||
+              G_VALUE_TYPE (&data->value) == G_TYPE_POINTER)
+            continue;
+
+          string = glade_utils_string_from_value (&data->value);
+
+          /* XXX Log error: data col j exceeds columns on row i */
+          if (!g_list_nth (columns, colnum))
+            break;
+
+          column_number = g_strdup_printf ("%d", colnum);
+
+          col_node = glade_xml_node_new (context, GLADE_TAG_COL);
+          glade_xml_node_append_child (row_node, col_node);
+          glade_xml_node_set_property_string (col_node, GLADE_TAG_ID,
+                                              column_number);
+          glade_xml_set_content (col_node, string);
+
+          if (data->i18n_translatable)
+            glade_xml_node_set_property_string (col_node,
+                                                GLADE_TAG_TRANSLATABLE,
+                                                GLADE_XML_TAG_I18N_TRUE);
+          if (data->i18n_context)
+            glade_xml_node_set_property_string (col_node,
+                                                GLADE_TAG_CONTEXT,
+                                                data->i18n_context);
+          if (data->i18n_comment)
+            glade_xml_node_set_property_string (col_node,
+                                                GLADE_TAG_COMMENT,
+                                                data->i18n_comment);
+
+
+          g_free (column_number);
+          g_free (string);
+        }
+    }
+
+  if (!glade_xml_node_get_children (data_node))
+    glade_xml_node_delete (data_node);
+  else
+    glade_xml_node_append_child (node, data_node);
+}
+
+
+void
+glade_gtk_store_write_widget (GladeWidgetAdaptor * adaptor,
+                              GladeWidget * widget,
+                              GladeXmlContext * context, GladeXmlNode * node)
+{
+  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
+       glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
+    return;
+
+  /* First chain up and write all the normal properties.. */
+  GWA_GET_CLASS (G_TYPE_OBJECT)->write_widget (adaptor, widget, context, node);
+
+  glade_gtk_store_write_columns (widget, context, node);
+  glade_gtk_store_write_data (widget, context, node);
+}
+
+static void
+glade_gtk_store_read_columns (GladeWidget * widget, GladeXmlNode * node)
+{
+  GladeNameContext *context;
+  GladeXmlNode *columns_node;
+  GladeProperty *property;
+  GladeXmlNode *prop;
+  GList *types = NULL;
+  GValue value = { 0, };
+  gchar column_name[256];
+
+  column_name[0] = '\0';
+  column_name[255] = '\0';
+
+  if ((columns_node = glade_xml_search_child (node, GLADE_TAG_COLUMNS)) == NULL)
+    return;
+
+  context = glade_name_context_new ();
+
+  for (prop = glade_xml_node_get_children_with_comments (columns_node); prop;
+       prop = glade_xml_node_next_with_comments (prop))
+    {
+      GladeColumnType *data;
+      gchar *type, *comment_str, buffer[256];
+
+      if (!glade_xml_node_verify_silent (prop, GLADE_TAG_COLUMN) &&
+          !glade_xml_node_is_comment (prop))
+        continue;
+
+      if (glade_xml_node_is_comment (prop))
+        {
+          comment_str = glade_xml_get_content (prop);
+          if (sscanf (comment_str, " column-name %s", buffer) == 1)
+            strncpy (column_name, buffer, 255);
+
+          g_free (comment_str);
+          continue;
+        }
+
+      type =
+          glade_xml_get_property_string_required (prop, GLADE_TAG_TYPE, NULL);
+
+      if (!column_name[0])
+       {
+         gchar *cname = g_ascii_strdown (type, -1);
+
+         data = glade_column_type_new (type, cname);
+
+         g_free (cname);
+       }
+      else
+       data = glade_column_type_new (type, column_name);
+
+      if (glade_name_context_has_name (context, data->column_name))
+        {
+          gchar *name =
+              glade_name_context_new_name (context, data->column_name);
+          g_free (data->column_name);
+          data->column_name = name;
+        }
+      glade_name_context_add_name (context, data->column_name);
+
+      types = g_list_prepend (types, data);
+      g_free (type);
+
+      column_name[0] = '\0';
+    }
+
+  glade_name_context_destroy (context);
+
+  property = glade_widget_get_property (widget, "columns");
+  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
+glade_gtk_store_read_data (GladeWidget * widget, GladeXmlNode * node)
+{
+  GladeXmlNode *data_node, *row_node, *col_node;
+  GNode *data_tree, *row, *item;
+  GladeModelData *data;
+  GValue *value;
+  GList *column_types = NULL;
+  GladeColumnType *column_type;
+  gint colnum;
+
+  if ((data_node = glade_xml_search_child (node, GLADE_TAG_DATA)) == NULL)
+    return;
+
+  /* XXX FIXME: Warn that columns werent there when parsing */
+  if (!glade_widget_property_get (widget, "columns", &column_types) ||
+      !column_types)
+    return;
+
+  /* Create root... */
+  data_tree = g_node_new (NULL);
+
+  for (row_node = glade_xml_node_get_children (data_node); row_node;
+       row_node = glade_xml_node_next (row_node))
+    {
+      gchar *value_str;
+
+      if (!glade_xml_node_verify (row_node, GLADE_TAG_ROW))
+        continue;
+
+      row = g_node_new (NULL);
+      g_node_append (data_tree, row);
+
+      /* XXX FIXME: we are assuming that the columns are listed in order */
+      for (colnum = 0, col_node = glade_xml_node_get_children (row_node);
+           col_node; col_node = glade_xml_node_next (col_node))
+        {
+          gint read_column;
+
+          if (!glade_xml_node_verify (col_node, GLADE_TAG_COL))
+            continue;
+
+          read_column = glade_xml_get_property_int (col_node, GLADE_TAG_ID, -1);
+          if (read_column < 0)
+            {
+              g_critical ("Parsed negative column id");
+              continue;
+            }
+
+          /* Catch up for gaps in the list where unserializable types are involved */
+          while (colnum < read_column)
+            {
+              column_type = g_list_nth_data (column_types, colnum);
+
+              data =
+                  glade_model_data_new (G_TYPE_INVALID,
+                                        column_type->column_name);
+
+              item = g_node_new (data);
+              g_node_append (row, item);
+
+              colnum++;
+            }
+
+          if (!(column_type = g_list_nth_data (column_types, colnum)))
+            /* XXX Log this too... */
+            continue;
+
+          /* Ignore unloaded column types for the workspace */
+          if (g_type_from_name (column_type->type_name) != G_TYPE_INVALID)
+            {
+              /* XXX Do we need object properties to somehow work at load time here ??
+               * should we be doing this part in "finished" ? ... todo thinkso...
+               */
+              value_str = glade_xml_get_content (col_node);
+              value = glade_utils_value_from_string (g_type_from_name (column_type->type_name), value_str,
+                                                    glade_widget_get_project (widget));
+              g_free (value_str);
+
+              data = glade_model_data_new (g_type_from_name (column_type->type_name),
+                                          column_type->column_name);
+
+              g_value_copy (value, &data->value);
+              g_value_unset (value);
+              g_free (value);
+            }
+          else
+            {
+              data =
+                  glade_model_data_new (G_TYPE_INVALID,
+                                        column_type->column_name);
+            }
+
+          data->i18n_translatable =
+              glade_xml_get_property_boolean (col_node, GLADE_TAG_TRANSLATABLE,
+                                              FALSE);
+          data->i18n_context =
+              glade_xml_get_property_string (col_node, GLADE_TAG_CONTEXT);
+          data->i18n_comment =
+              glade_xml_get_property_string (col_node, GLADE_TAG_COMMENT);
+
+          item = g_node_new (data);
+          g_node_append (row, item);
+
+          /* dont increment colnum on invalid xml tags... */
+          colnum++;
+        }
+    }
+
+  if (data_tree->children)
+    glade_widget_property_set (widget, "data", data_tree);
+
+  glade_model_data_tree_free (data_tree);
+}
+
+void
+glade_gtk_store_read_widget (GladeWidgetAdaptor * adaptor,
+                             GladeWidget * widget, GladeXmlNode * node)
+{
+  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
+       glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
+    return;
+
+  /* First chain up and read in all the normal properties.. */
+  GWA_GET_CLASS (G_TYPE_OBJECT)->read_widget (adaptor, widget, node);
+
+  glade_gtk_store_read_columns (widget, node);
+
+  if (GTK_IS_LIST_STORE (glade_widget_get_object (widget)))
+    glade_gtk_store_read_data (widget, node);
+}
diff --git a/plugins/gtk+/glade-gtk-tree-view.c b/plugins/gtk+/glade-gtk-tree-view.c
new file mode 100644
index 0000000..b38a1f3
--- /dev/null
+++ b/plugins/gtk+/glade-gtk-tree-view.c
@@ -0,0 +1,275 @@
+/*
+ * glade-gtk-tree-view.c - GladeWidgetAdaptor for GtkTreeView
+ *
+ * Copyright (C) 2013 Tristan Van Berkom
+ *
+ * Authors:
+ *      Tristan Van Berkom <tristan van berkom gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public 
+ * License along with this program; if not, write to the Free Softwarel
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+#include <glib/gi18n-lib.h>
+#include <gladeui/glade.h>
+
+#include "glade-gtk.h"
+#include "glade-gtk-tree-view.h"
+#include "glade-gtk-cell-layout.h"
+
+#include "glade-treeview-editor.h"
+
+gboolean
+glade_gtk_treeview_add_verify (GladeWidgetAdaptor *adaptor,
+                              GtkWidget          *container,
+                              GtkWidget          *child,
+                              gboolean            user_feedback)
+{
+  if (!GTK_IS_TREE_VIEW_COLUMN (child))
+    {
+      if (user_feedback)
+       {
+         GladeWidgetAdaptor *cell_adaptor = 
+           glade_widget_adaptor_get_by_type (GTK_TYPE_TREE_VIEW_COLUMN);
+
+         glade_util_ui_message (glade_app_get_window (),
+                                GLADE_UI_INFO, NULL,
+                                ONLY_THIS_GOES_IN_THAT_MSG,
+                                glade_widget_adaptor_get_title (cell_adaptor),
+                                glade_widget_adaptor_get_title (adaptor));
+       }
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+void
+glade_gtk_treeview_launch_editor (GObject * treeview)
+{
+  GladeWidget        *widget  = glade_widget_get_from_gobject (treeview);
+  GladeWidgetAdaptor *adaptor = glade_widget_get_adaptor (widget);
+  GladeBaseEditor    *editor;
+  GladeEditable      *treeview_editor;
+  GtkWidget          *window;
+
+  treeview_editor = glade_widget_adaptor_create_editable (adaptor, GLADE_PAGE_GENERAL);
+  treeview_editor = (GladeEditable *) glade_tree_view_editor_new (adaptor, treeview_editor);
+
+  /* Editor */
+  editor = glade_base_editor_new (treeview, treeview_editor,
+                                  _("Column"), GTK_TYPE_TREE_VIEW_COLUMN, NULL);
+
+  glade_base_editor_append_types (editor, GTK_TYPE_TREE_VIEW_COLUMN,
+                                  _("Text"), GTK_TYPE_CELL_RENDERER_TEXT,
+                                  _("Accelerator"),
+                                  GTK_TYPE_CELL_RENDERER_ACCEL, _("Combo"),
+                                  GTK_TYPE_CELL_RENDERER_COMBO, _("Spin"),
+                                  GTK_TYPE_CELL_RENDERER_SPIN, _("Pixbuf"),
+                                  GTK_TYPE_CELL_RENDERER_PIXBUF, _("Progress"),
+                                  GTK_TYPE_CELL_RENDERER_PROGRESS, _("Toggle"),
+                                  GTK_TYPE_CELL_RENDERER_TOGGLE, _("Spinner"),
+                                  GTK_TYPE_CELL_RENDERER_SPINNER, NULL);
+
+  g_signal_connect (editor, "get-display-name",
+                    G_CALLBACK (glade_gtk_cell_layout_get_display_name), NULL);
+  g_signal_connect (editor, "child-selected",
+                    G_CALLBACK (glade_gtk_cell_layout_child_selected), NULL);
+  g_signal_connect (editor, "move-child",
+                    G_CALLBACK (glade_gtk_cell_layout_move_child), NULL);
+
+  gtk_widget_show (GTK_WIDGET (editor));
+
+  window =
+      glade_base_editor_pack_new_window (editor, _("Tree View Editor"), NULL);
+  gtk_widget_show (window);
+}
+
+void
+glade_gtk_treeview_action_activate (GladeWidgetAdaptor * adaptor,
+                                    GObject * object, const gchar * action_path)
+{
+  if (strcmp (action_path, "launch_editor") == 0)
+    {
+      glade_gtk_treeview_launch_editor (object);
+    }
+  else
+    GWA_GET_CLASS (GTK_TYPE_CONTAINER)->action_activate (adaptor,
+                                                         object, action_path);
+}
+
+static gint
+glade_gtk_treeview_get_column_index (GtkTreeView * view,
+                                     GtkTreeViewColumn * column)
+{
+  GtkTreeViewColumn *iter;
+  gint i;
+
+  for (i = 0; (iter = gtk_tree_view_get_column (view, i)) != NULL; i++)
+    if (iter == column)
+      return i;
+
+  return -1;
+}
+
+void
+glade_gtk_treeview_get_child_property (GladeWidgetAdaptor * adaptor,
+                                       GObject * container,
+                                       GObject * child,
+                                       const gchar * property_name,
+                                       GValue * value)
+{
+  if (strcmp (property_name, "position") == 0)
+    g_value_set_int (value,
+                     glade_gtk_treeview_get_column_index (GTK_TREE_VIEW
+                                                          (container),
+                                                          GTK_TREE_VIEW_COLUMN
+                                                          (child)));
+  else
+    /* Chain Up */
+    GWA_GET_CLASS
+        (GTK_TYPE_CONTAINER)->child_get_property (adaptor,
+                                                  container, child,
+                                                  property_name, value);
+}
+
+void
+glade_gtk_treeview_set_child_property (GladeWidgetAdaptor * adaptor,
+                                       GObject * container,
+                                       GObject * child,
+                                       const gchar * property_name,
+                                       const GValue * value)
+{
+  if (strcmp (property_name, "position") == 0)
+    {
+
+      gtk_tree_view_remove_column (GTK_TREE_VIEW (container),
+                                   GTK_TREE_VIEW_COLUMN (child));
+      gtk_tree_view_insert_column (GTK_TREE_VIEW (container),
+                                   GTK_TREE_VIEW_COLUMN (child),
+                                   g_value_get_int (value));
+    }
+  else
+    /* Chain Up */
+    GWA_GET_CLASS
+        (GTK_TYPE_CONTAINER)->child_set_property (adaptor,
+                                                  container, child,
+                                                  property_name, value);
+}
+
+GList *
+glade_gtk_treeview_get_children (GladeWidgetAdaptor * adaptor,
+                                 GtkTreeView * view)
+{
+  GList *children;
+
+  children = gtk_tree_view_get_columns (view);
+  children = g_list_prepend (children, gtk_tree_view_get_selection (view));
+
+  return children;
+}
+
+/* XXX FIXME: We should hide the actual "fixed-height-mode" setting from
+ * treeview editors and provide a custom control that sets all its columns
+ * to fixed size and then control the column's sensitivity accordingly.
+ */
+#define INSENSITIVE_COLUMN_SIZING_MSG \
+       _("Columns must have a fixed size inside a treeview with fixed height mode set")
+
+void
+glade_gtk_treeview_add_child (GladeWidgetAdaptor * adaptor,
+                              GObject * container, GObject * child)
+{
+  GtkTreeView *view = GTK_TREE_VIEW (container);
+  GtkTreeViewColumn *column;
+  GladeWidget *gcolumn;
+
+  if (!GTK_IS_TREE_VIEW_COLUMN (child))
+    return;
+
+  if (gtk_tree_view_get_fixed_height_mode (view))
+    {
+      gcolumn = glade_widget_get_from_gobject (child);
+      glade_widget_property_set (gcolumn, "sizing", GTK_TREE_VIEW_COLUMN_FIXED);
+      glade_widget_property_set_sensitive (gcolumn, "sizing", FALSE,
+                                           INSENSITIVE_COLUMN_SIZING_MSG);
+    }
+
+  column = GTK_TREE_VIEW_COLUMN (child);
+  gtk_tree_view_append_column (view, column);
+
+  glade_gtk_cell_layout_sync_attributes (G_OBJECT (column));
+}
+
+void
+glade_gtk_treeview_remove_child (GladeWidgetAdaptor * adaptor,
+                                 GObject * container, GObject * child)
+{
+  GtkTreeView *view = GTK_TREE_VIEW (container);
+  GtkTreeViewColumn *column;
+
+  if (!GTK_IS_TREE_VIEW_COLUMN (child))
+    return;
+
+  column = GTK_TREE_VIEW_COLUMN (child);
+  gtk_tree_view_remove_column (view, column);
+}
+
+void
+glade_gtk_treeview_replace_child (GladeWidgetAdaptor * adaptor,
+                                  GObject * container,
+                                  GObject * current, GObject * new_column)
+{
+  GtkTreeView *view = GTK_TREE_VIEW (container);
+  GList *columns;
+  GtkTreeViewColumn *column;
+  GladeWidget *gcolumn;
+  gint index;
+
+  if (!GTK_IS_TREE_VIEW_COLUMN (current))
+    return;
+
+  column = GTK_TREE_VIEW_COLUMN (current);
+
+  columns = gtk_tree_view_get_columns (view);
+  index = g_list_index (columns, column);
+  g_list_free (columns);
+
+  gtk_tree_view_remove_column (view, column);
+  column = GTK_TREE_VIEW_COLUMN (new_column);
+
+  gtk_tree_view_insert_column (view, column, index);
+
+  if (gtk_tree_view_get_fixed_height_mode (view))
+    {
+      gcolumn = glade_widget_get_from_gobject (column);
+      glade_widget_property_set (gcolumn, "sizing", GTK_TREE_VIEW_COLUMN_FIXED);
+      glade_widget_property_set_sensitive (gcolumn, "sizing", FALSE,
+                                           INSENSITIVE_COLUMN_SIZING_MSG);
+    }
+
+  glade_gtk_cell_layout_sync_attributes (G_OBJECT (column));
+}
+
+gboolean
+glade_gtk_treeview_depends (GladeWidgetAdaptor * adaptor,
+                            GladeWidget * widget, GladeWidget * another)
+{
+  if (GTK_IS_TREE_MODEL (glade_widget_get_object (another)))
+    return TRUE;
+
+  return GWA_GET_CLASS (GTK_TYPE_CONTAINER)->depends (adaptor, widget, another);
+}
diff --git a/plugins/gtk+/glade-gtk-tree-view.h b/plugins/gtk+/glade-gtk-tree-view.h
new file mode 100644
index 0000000..100f846
--- /dev/null
+++ b/plugins/gtk+/glade-gtk-tree-view.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2013 Tristan Van Berkom.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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_GTK_TREE_VIEW_H_
+#define _GLADE_GTK_TREE_VIEW_H_
+
+#include <gtk/gtk.h>
+#include <gladeui/glade.h>
+
+G_BEGIN_DECLS
+
+void glade_gtk_treeview_launch_editor (GObject * treeview);
+
+G_END_DECLS
+
+#endif  /* _GLADE_GTK_TREE_VIEW_H_ */
diff --git a/plugins/gtk+/glade-gtk.c b/plugins/gtk+/glade-gtk.c
index 71ffbef..82b4016 100644
--- a/plugins/gtk+/glade-gtk.c
+++ b/plugins/gtk+/glade-gtk.c
@@ -78,1746 +78,6 @@ glade_gtk_init (const gchar * name)
 {
 }
 
-/*--------------------------- GtkListStore/GtkTreeStore ---------------------------------*/
-
-#define GLADE_TAG_COLUMNS      "columns"
-#define GLADE_TAG_COLUMN       "column"
-#define GLADE_TAG_TYPE         "type"
-
-#define GLADE_TAG_ROW           "row"
-#define GLADE_TAG_DATA          "data"
-#define GLADE_TAG_COL           "col"
-
-
-static gboolean
-glade_gtk_cell_layout_has_renderer (GtkCellLayout * layout,
-                                    GtkCellRenderer * renderer)
-{
-  GList *cells = gtk_cell_layout_get_cells (layout);
-  gboolean has_renderer;
-
-  has_renderer = (g_list_find (cells, renderer) != NULL);
-
-  g_list_free (cells);
-
-  return has_renderer;
-}
-
-static gboolean
-glade_gtk_cell_renderer_sync_attributes (GObject * object)
-{
-
-  GtkCellLayout *layout;
-  GtkCellRenderer *cell;
-  GladeWidget *widget;
-  GladeWidget *parent;
-  GladeWidget *gmodel;
-  GladeProperty *property;
-  GladePropertyClass *pclass;
-  gchar *attr_prop_name;
-  GList *l, *column_list = NULL;
-  gint columns = 0;
-  static gint attr_len = 0;
-
-  if (!attr_len)
-    attr_len = strlen ("attr-");
-
-  /* Apply attributes to renderer when bound to a model in runtime */
-  widget = glade_widget_get_from_gobject (object);
-
-  parent = glade_widget_get_parent (widget);
-  if (parent == NULL)
-    return FALSE;
-
-  /* When creating widgets, sometimes the parent is set before parenting happens,
-   * here we have to be careful for that..
-   */
-  layout = GTK_CELL_LAYOUT (glade_widget_get_object (parent));
-  cell   = GTK_CELL_RENDERER (object);
-
-  if (!glade_gtk_cell_layout_has_renderer (layout, cell))
-    return FALSE;
-
-  if ((gmodel = glade_cell_renderer_get_model (widget)) == NULL)
-    return FALSE;
-
-  glade_widget_property_get (gmodel, "columns", &column_list);
-  columns = g_list_length (column_list);
-
-  gtk_cell_layout_clear_attributes (layout, cell);
-
-  for (l = glade_widget_get_properties (widget); l; l = l->next)
-    {
-      property = l->data;
-      pclass   = glade_property_get_class (property);
-
-      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) == 0)
-        {
-          gint column = g_value_get_int (glade_property_inline_value (property));
-
-          attr_prop_name = (gchar *)&glade_property_class_id (pclass)[attr_len];
-
-          if (column >= 0 && column < columns)
-            {
-              GladeColumnType *column_type =
-                  (GladeColumnType *) g_list_nth_data (column_list, column);
-              GType column_gtype = g_type_from_name (column_type->type_name);
-             GParamSpec *pspec = glade_property_class_get_pspec (pclass);
-
-              if (column_gtype &&
-                  g_value_type_transformable (column_gtype, pspec->value_type))
-                gtk_cell_layout_add_attribute (layout, cell, attr_prop_name, column);
-            }
-        }
-    }
-
-  return FALSE;
-}
-
-
-static gboolean
-glade_gtk_cell_layout_sync_attributes (GObject * layout)
-{
-  GladeWidget *gwidget = glade_widget_get_from_gobject (layout);
-  GObject *cell;
-  GList *children, *l;
-
-  children = glade_widget_get_children (gwidget);
-  for (l = children; l; l = l->next)
-    {
-      cell = l->data;
-      if (!GTK_IS_CELL_RENDERER (cell))
-        continue;
-
-      glade_gtk_cell_renderer_sync_attributes (cell);
-    }
-  g_list_free (children);
-
-  return FALSE;
-}
-
-static void
-glade_gtk_store_set_columns (GObject * object, const GValue * value)
-{
-  GList *l;
-  gint i, n;
-  GType *types;
-
-  for (i = 0, l = g_value_get_boxed (value), n = g_list_length (l), types =
-       g_new (GType, n); l; l = g_list_next (l), i++)
-    {
-      GladeColumnType *data = l->data;
-
-      if (g_type_from_name (data->type_name) != G_TYPE_INVALID)
-        types[i] = g_type_from_name (data->type_name);
-      else
-        types[i] = G_TYPE_POINTER;
-    }
-
-  if (GTK_IS_LIST_STORE (object))
-    gtk_list_store_set_column_types (GTK_LIST_STORE (object), n, types);
-  else
-    gtk_tree_store_set_column_types (GTK_TREE_STORE (object), n, types);
-
-  g_free (types);
-}
-
-static void
-glade_gtk_store_set_data (GObject * object, const GValue * value)
-{
-  GladeWidget *gwidget = glade_widget_get_from_gobject (object);
-  GList *columns = NULL;
-  GNode *data_tree, *row, *iter;
-  gint colnum;
-  GtkTreeIter row_iter;
-  GladeModelData *data;
-  GType column_type;
-
-  if (GTK_IS_LIST_STORE (object))
-    gtk_list_store_clear (GTK_LIST_STORE (object));
-  else
-    gtk_tree_store_clear (GTK_TREE_STORE (object));
-
-  glade_widget_property_get (gwidget, "columns", &columns);
-  data_tree = g_value_get_boxed (value);
-
-  /* Nothing to enter without columns defined */
-  if (!data_tree || !columns)
-    return;
-
-  for (row = data_tree->children; row; row = row->next)
-    {
-      if (GTK_IS_LIST_STORE (object))
-        gtk_list_store_append (GTK_LIST_STORE (object), &row_iter);
-      else
-        /* (for now no child data... ) */
-        gtk_tree_store_append (GTK_TREE_STORE (object), &row_iter, NULL);
-
-      for (colnum = 0, iter = row->children; iter; colnum++, iter = iter->next)
-        {
-          data = iter->data;
-
-          if (!g_list_nth (columns, colnum))
-            break;
-
-          /* Abort if theres a type mismatch, the widget's being rebuilt
-           * and a sync will come soon with the right values
-           */
-          column_type =
-              gtk_tree_model_get_column_type (GTK_TREE_MODEL (object), colnum);
-          if (G_VALUE_TYPE (&data->value) != column_type)
-            continue;
-
-          if (GTK_IS_LIST_STORE (object))
-            gtk_list_store_set_value (GTK_LIST_STORE (object),
-                                      &row_iter, colnum, &data->value);
-          else
-            gtk_tree_store_set_value (GTK_TREE_STORE (object),
-                                      &row_iter, colnum, &data->value);
-        }
-    }
-}
-
-void
-glade_gtk_store_set_property (GladeWidgetAdaptor * adaptor,
-                              GObject * object,
-                              const gchar * property_name, const GValue * value)
-{
-  if (strcmp (property_name, "columns") == 0)
-    {
-      glade_gtk_store_set_columns (object, value);
-    }
-  else if (strcmp (property_name, "data") == 0)
-    {
-      glade_gtk_store_set_data (object, value);
-    }
-  else
-    /* Chain Up */
-    GWA_GET_CLASS (G_TYPE_OBJECT)->set_property (adaptor,
-                                                 object, property_name, value);
-}
-
-GladeEditorProperty *
-glade_gtk_store_create_eprop (GladeWidgetAdaptor * adaptor,
-                              GladePropertyClass * klass, gboolean use_command)
-{
-  GladeEditorProperty *eprop;
-  GParamSpec          *pspec;
-
-  pspec = glade_property_class_get_pspec (klass);
-
-  /* chain up.. */
-  if (pspec->value_type == GLADE_TYPE_COLUMN_TYPE_LIST)
-    eprop = g_object_new (GLADE_TYPE_EPROP_COLUMN_TYPES,
-                          "property-class", klass,
-                          "use-command", use_command, NULL);
-  else if (pspec->value_type == GLADE_TYPE_MODEL_DATA_TREE)
-    eprop = g_object_new (GLADE_TYPE_EPROP_MODEL_DATA,
-                          "property-class", klass,
-                          "use-command", use_command, NULL);
-  else
-    eprop = GWA_GET_CLASS
-        (G_TYPE_OBJECT)->create_eprop (adaptor, klass, use_command);
-  return eprop;
-}
-
-
-static void
-glade_gtk_store_columns_changed (GladeProperty * property,
-                                 GValue * old_value,
-                                 GValue * new_value, GladeWidget * store)
-{
-  GList *l, *list, *children, *prop_refs;
-
-  /* Reset the attributes for all cell renderers referring to this store */
-  prop_refs = glade_widget_list_prop_refs (store);
-  for (l = prop_refs; l; l = l->next)
-    {
-      GladeWidget *referring_widget = glade_property_get_widget (GLADE_PROPERTY (l->data));
-      GObject     *referring_object = glade_widget_get_object (referring_widget);
-
-      if (GTK_IS_CELL_LAYOUT (referring_object))
-        glade_gtk_cell_layout_sync_attributes (referring_object);
-      else if (GTK_IS_TREE_VIEW (referring_object))
-        {
-          children = glade_widget_get_children (referring_widget);
-
-          for (list = children; list; list = list->next)
-            {
-              /* Clear the GtkTreeViewColumns... */
-              if (GTK_IS_CELL_LAYOUT (list->data))
-                glade_gtk_cell_layout_sync_attributes (G_OBJECT (list->data));
-            }
-
-          g_list_free (children);
-        }
-    }
-  g_list_free (prop_refs);
-}
-
-void
-glade_gtk_store_post_create (GladeWidgetAdaptor * adaptor,
-                             GObject * object, GladeCreateReason reason)
-{
-  GladeWidget *gwidget;
-  GladeProperty *property;
-
-  if (reason == GLADE_CREATE_REBUILD)
-    return;
-
-  gwidget = glade_widget_get_from_gobject (object);
-  property = glade_widget_get_property (gwidget, "columns");
-
-  /* Here we watch the value-changed signal on the "columns" property, we need
-   * to reset all the Cell Renderer attributes when the underlying "columns" change,
-   * the reason we do it from "value-changed" is because GladeWidget prop references
-   * are unavailable while rebuilding an object, and the liststore needs to be rebuilt
-   * in order to set the columns.
-   *
-   * This signal will be envoked after applying the new column types to the store
-   * and before the views get any signal to update themselves from the changed model,
-   * perfect time to reset the attributes.
-   */
-  g_signal_connect (G_OBJECT (property), "value-changed",
-                    G_CALLBACK (glade_gtk_store_columns_changed), gwidget);
-}
-
-GladeEditable *
-glade_gtk_store_create_editable (GladeWidgetAdaptor * adaptor,
-                                 GladeEditorPageType type)
-{
-  GladeEditable *editable;
-
-  /* Get base editable */
-  editable = GWA_GET_CLASS (G_TYPE_OBJECT)->create_editable (adaptor, type);
-
-  if (type == GLADE_PAGE_GENERAL)
-    return (GladeEditable *) glade_store_editor_new (adaptor, editable);
-
-  return editable;
-}
-
-gchar *
-glade_gtk_store_string_from_value (GladeWidgetAdaptor * adaptor,
-                                   GladePropertyClass * klass,
-                                   const GValue * value)
-{
-  GString *string;
-  GParamSpec *pspec;
-
-  pspec = glade_property_class_get_pspec (klass);
-
-  if (pspec->value_type == GLADE_TYPE_COLUMN_TYPE_LIST)
-    {
-      GList *l;
-      string = g_string_new ("");
-      for (l = g_value_get_boxed (value); l; l = g_list_next (l))
-        {
-          GladeColumnType *data = l->data;
-          g_string_append_printf (string,
-                                  (g_list_next (l)) ? "%s:%s|" : "%s:%s",
-                                  data->type_name, data->column_name);
-        }
-      return g_string_free (string, FALSE);
-    }
-  else if (pspec->value_type == GLADE_TYPE_MODEL_DATA_TREE)
-    {
-      GladeModelData *data;
-      GNode *data_tree, *row, *iter;
-      gint rownum;
-      gchar *str;
-      gboolean is_last;
-
-      /* Return a unique string for the backend to compare */
-      data_tree = g_value_get_boxed (value);
-
-      if (!data_tree || !data_tree->children)
-        return g_strdup ("");
-
-      string = g_string_new ("");
-      for (rownum = 0, row = data_tree->children; row;
-           rownum++, row = row->next)
-        {
-          for (iter = row->children; iter; iter = iter->next)
-            {
-              data = iter->data;
-
-              if (!G_VALUE_TYPE (&data->value) ||
-                  G_VALUE_TYPE (&data->value) == G_TYPE_INVALID)
-                str = g_strdup ("(virtual)");
-              else if (G_VALUE_TYPE (&data->value) != G_TYPE_POINTER)
-                str = glade_utils_string_from_value (&data->value);
-              else
-                str = g_strdup ("(null)");
-
-              is_last = !row->next && !iter->next;
-              g_string_append_printf (string, "%s[%d]:%s",
-                                      data->name, rownum, str);
-
-              if (data->i18n_translatable)
-                g_string_append_printf (string, " translatable");
-              if (data->i18n_context)
-                g_string_append_printf (string, " i18n-context:%s",
-                                        data->i18n_context);
-              if (data->i18n_comment)
-                g_string_append_printf (string, " i18n-comment:%s",
-                                        data->i18n_comment);
-
-              if (!is_last)
-                g_string_append_printf (string, "|");
-
-              g_free (str);
-            }
-        }
-      return g_string_free (string, FALSE);
-    }
-  else
-    return GWA_GET_CLASS
-        (G_TYPE_OBJECT)->string_from_value (adaptor, klass, value);
-}
-
-static void
-glade_gtk_store_write_columns (GladeWidget * widget,
-                               GladeXmlContext * context, GladeXmlNode * node)
-{
-  GladeXmlNode *columns_node;
-  GladeProperty *prop;
-  GList *l;
-
-  prop = glade_widget_get_property (widget, "columns");
-
-  columns_node = glade_xml_node_new (context, GLADE_TAG_COLUMNS);
-
-  for (l = g_value_get_boxed (glade_property_inline_value (prop)); l; l = g_list_next (l))
-    {
-      GladeColumnType *data = l->data;
-      GladeXmlNode *column_node, *comment_node;
-
-      /* Write column names in comments... */
-      gchar *comment = g_strdup_printf (" column-name %s ", data->column_name);
-      comment_node = glade_xml_node_new_comment (context, comment);
-      glade_xml_node_append_child (columns_node, comment_node);
-      g_free (comment);
-
-      column_node = glade_xml_node_new (context, GLADE_TAG_COLUMN);
-      glade_xml_node_append_child (columns_node, column_node);
-      glade_xml_node_set_property_string (column_node, GLADE_TAG_TYPE,
-                                          data->type_name);
-    }
-
-  if (!glade_xml_node_get_children (columns_node))
-    glade_xml_node_delete (columns_node);
-  else
-    glade_xml_node_append_child (node, columns_node);
-
-}
-
-static void
-glade_gtk_store_write_data (GladeWidget * widget,
-                            GladeXmlContext * context, GladeXmlNode * node)
-{
-  GladeXmlNode *data_node, *col_node, *row_node;
-  GList *columns = NULL;
-  GladeModelData *data;
-  GNode *data_tree = NULL, *row, *iter;
-  gint colnum;
-
-  glade_widget_property_get (widget, "data", &data_tree);
-  glade_widget_property_get (widget, "columns", &columns);
-
-  /* XXX log errors about data not fitting columns here when
-   * loggin is available
-   */
-  if (!data_tree || !columns)
-    return;
-
-  data_node = glade_xml_node_new (context, GLADE_TAG_DATA);
-
-  for (row = data_tree->children; row; row = row->next)
-    {
-      row_node = glade_xml_node_new (context, GLADE_TAG_ROW);
-      glade_xml_node_append_child (data_node, row_node);
-
-      for (colnum = 0, iter = row->children; iter; colnum++, iter = iter->next)
-        {
-          gchar *string, *column_number;
-
-          data = iter->data;
-
-          /* Skip non-serializable data */
-          if (G_VALUE_TYPE (&data->value) == 0 ||
-              G_VALUE_TYPE (&data->value) == G_TYPE_POINTER)
-            continue;
-
-          string = glade_utils_string_from_value (&data->value);
-
-          /* XXX Log error: data col j exceeds columns on row i */
-          if (!g_list_nth (columns, colnum))
-            break;
-
-          column_number = g_strdup_printf ("%d", colnum);
-
-          col_node = glade_xml_node_new (context, GLADE_TAG_COL);
-          glade_xml_node_append_child (row_node, col_node);
-          glade_xml_node_set_property_string (col_node, GLADE_TAG_ID,
-                                              column_number);
-          glade_xml_set_content (col_node, string);
-
-          if (data->i18n_translatable)
-            glade_xml_node_set_property_string (col_node,
-                                                GLADE_TAG_TRANSLATABLE,
-                                                GLADE_XML_TAG_I18N_TRUE);
-          if (data->i18n_context)
-            glade_xml_node_set_property_string (col_node,
-                                                GLADE_TAG_CONTEXT,
-                                                data->i18n_context);
-          if (data->i18n_comment)
-            glade_xml_node_set_property_string (col_node,
-                                                GLADE_TAG_COMMENT,
-                                                data->i18n_comment);
-
-
-          g_free (column_number);
-          g_free (string);
-        }
-    }
-
-  if (!glade_xml_node_get_children (data_node))
-    glade_xml_node_delete (data_node);
-  else
-    glade_xml_node_append_child (node, data_node);
-}
-
-
-void
-glade_gtk_store_write_widget (GladeWidgetAdaptor * adaptor,
-                              GladeWidget * widget,
-                              GladeXmlContext * context, GladeXmlNode * node)
-{
-  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
-       glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
-    return;
-
-  /* First chain up and write all the normal properties.. */
-  GWA_GET_CLASS (G_TYPE_OBJECT)->write_widget (adaptor, widget, context, node);
-
-  glade_gtk_store_write_columns (widget, context, node);
-  glade_gtk_store_write_data (widget, context, node);
-}
-
-static void
-glade_gtk_store_read_columns (GladeWidget * widget, GladeXmlNode * node)
-{
-  GladeNameContext *context;
-  GladeXmlNode *columns_node;
-  GladeProperty *property;
-  GladeXmlNode *prop;
-  GList *types = NULL;
-  GValue value = { 0, };
-  gchar column_name[256];
-
-  column_name[0] = '\0';
-  column_name[255] = '\0';
-
-  if ((columns_node = glade_xml_search_child (node, GLADE_TAG_COLUMNS)) == NULL)
-    return;
-
-  context = glade_name_context_new ();
-
-  for (prop = glade_xml_node_get_children_with_comments (columns_node); prop;
-       prop = glade_xml_node_next_with_comments (prop))
-    {
-      GladeColumnType *data;
-      gchar *type, *comment_str, buffer[256];
-
-      if (!glade_xml_node_verify_silent (prop, GLADE_TAG_COLUMN) &&
-          !glade_xml_node_is_comment (prop))
-        continue;
-
-      if (glade_xml_node_is_comment (prop))
-        {
-          comment_str = glade_xml_get_content (prop);
-          if (sscanf (comment_str, " column-name %s", buffer) == 1)
-            strncpy (column_name, buffer, 255);
-
-          g_free (comment_str);
-          continue;
-        }
-
-      type =
-          glade_xml_get_property_string_required (prop, GLADE_TAG_TYPE, NULL);
-
-      if (!column_name[0])
-       {
-         gchar *cname = g_ascii_strdown (type, -1);
-
-         data = glade_column_type_new (type, cname);
-
-         g_free (cname);
-       }
-      else
-       data = glade_column_type_new (type, column_name);
-
-      if (glade_name_context_has_name (context, data->column_name))
-        {
-          gchar *name =
-              glade_name_context_new_name (context, data->column_name);
-          g_free (data->column_name);
-          data->column_name = name;
-        }
-      glade_name_context_add_name (context, data->column_name);
-
-      types = g_list_prepend (types, data);
-      g_free (type);
-
-      column_name[0] = '\0';
-    }
-
-  glade_name_context_destroy (context);
-
-  property = glade_widget_get_property (widget, "columns");
-  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
-glade_gtk_store_read_data (GladeWidget * widget, GladeXmlNode * node)
-{
-  GladeXmlNode *data_node, *row_node, *col_node;
-  GNode *data_tree, *row, *item;
-  GladeModelData *data;
-  GValue *value;
-  GList *column_types = NULL;
-  GladeColumnType *column_type;
-  gint colnum;
-
-  if ((data_node = glade_xml_search_child (node, GLADE_TAG_DATA)) == NULL)
-    return;
-
-  /* XXX FIXME: Warn that columns werent there when parsing */
-  if (!glade_widget_property_get (widget, "columns", &column_types) ||
-      !column_types)
-    return;
-
-  /* Create root... */
-  data_tree = g_node_new (NULL);
-
-  for (row_node = glade_xml_node_get_children (data_node); row_node;
-       row_node = glade_xml_node_next (row_node))
-    {
-      gchar *value_str;
-
-      if (!glade_xml_node_verify (row_node, GLADE_TAG_ROW))
-        continue;
-
-      row = g_node_new (NULL);
-      g_node_append (data_tree, row);
-
-      /* XXX FIXME: we are assuming that the columns are listed in order */
-      for (colnum = 0, col_node = glade_xml_node_get_children (row_node);
-           col_node; col_node = glade_xml_node_next (col_node))
-        {
-          gint read_column;
-
-          if (!glade_xml_node_verify (col_node, GLADE_TAG_COL))
-            continue;
-
-          read_column = glade_xml_get_property_int (col_node, GLADE_TAG_ID, -1);
-          if (read_column < 0)
-            {
-              g_critical ("Parsed negative column id");
-              continue;
-            }
-
-          /* Catch up for gaps in the list where unserializable types are involved */
-          while (colnum < read_column)
-            {
-              column_type = g_list_nth_data (column_types, colnum);
-
-              data =
-                  glade_model_data_new (G_TYPE_INVALID,
-                                        column_type->column_name);
-
-              item = g_node_new (data);
-              g_node_append (row, item);
-
-              colnum++;
-            }
-
-          if (!(column_type = g_list_nth_data (column_types, colnum)))
-            /* XXX Log this too... */
-            continue;
-
-          /* Ignore unloaded column types for the workspace */
-          if (g_type_from_name (column_type->type_name) != G_TYPE_INVALID)
-            {
-              /* XXX Do we need object properties to somehow work at load time here ??
-               * should we be doing this part in "finished" ? ... todo thinkso...
-               */
-              value_str = glade_xml_get_content (col_node);
-              value = glade_utils_value_from_string (g_type_from_name (column_type->type_name), value_str,
-                                                    glade_widget_get_project (widget));
-              g_free (value_str);
-
-              data = glade_model_data_new (g_type_from_name (column_type->type_name),
-                                          column_type->column_name);
-
-              g_value_copy (value, &data->value);
-              g_value_unset (value);
-              g_free (value);
-            }
-          else
-            {
-              data =
-                  glade_model_data_new (G_TYPE_INVALID,
-                                        column_type->column_name);
-            }
-
-          data->i18n_translatable =
-              glade_xml_get_property_boolean (col_node, GLADE_TAG_TRANSLATABLE,
-                                              FALSE);
-          data->i18n_context =
-              glade_xml_get_property_string (col_node, GLADE_TAG_CONTEXT);
-          data->i18n_comment =
-              glade_xml_get_property_string (col_node, GLADE_TAG_COMMENT);
-
-          item = g_node_new (data);
-          g_node_append (row, item);
-
-          /* dont increment colnum on invalid xml tags... */
-          colnum++;
-        }
-    }
-
-  if (data_tree->children)
-    glade_widget_property_set (widget, "data", data_tree);
-
-  glade_model_data_tree_free (data_tree);
-}
-
-void
-glade_gtk_store_read_widget (GladeWidgetAdaptor * adaptor,
-                             GladeWidget * widget, GladeXmlNode * node)
-{
-  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
-       glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
-    return;
-
-  /* First chain up and read in all the normal properties.. */
-  GWA_GET_CLASS (G_TYPE_OBJECT)->read_widget (adaptor, widget, node);
-
-  glade_gtk_store_read_columns (widget, node);
-
-  if (GTK_IS_LIST_STORE (glade_widget_get_object (widget)))
-    glade_gtk_store_read_data (widget, node);
-}
-
-/*--------------------------- GtkCellRenderer ---------------------------------*/
-static void glade_gtk_treeview_launch_editor (GObject * treeview);
-
-void
-glade_gtk_cell_renderer_action_activate (GladeWidgetAdaptor * adaptor,
-                                         GObject * object,
-                                         const gchar * action_path)
-{
-  if (strcmp (action_path, "launch_editor") == 0)
-    {
-      GladeWidget *w = glade_widget_get_from_gobject (object);
-
-      while ((w = glade_widget_get_parent (w)))
-        {
-         GObject *object = glade_widget_get_object (w);
-
-          if (GTK_IS_TREE_VIEW (object))
-            {
-              glade_gtk_treeview_launch_editor (object);
-              break;
-            }
-        }
-    }
-  else
-    GWA_GET_CLASS (G_TYPE_OBJECT)->action_activate (adaptor, object, action_path);
-}
-
-void
-glade_gtk_cell_renderer_deep_post_create (GladeWidgetAdaptor * adaptor,
-                                          GObject * object,
-                                          GladeCreateReason reason)
-{
-  GladePropertyClass *pclass;
-  GladeProperty *property;
-  GladeWidget *widget;
-  const GList *l;
-
-  widget = glade_widget_get_from_gobject (object);
-
-  for (l = glade_widget_adaptor_get_properties (adaptor); l; l = l->next)
-    {
-      pclass = l->data;
-
-      if (strncmp (glade_property_class_id (pclass), "use-attr-", strlen ("use-attr-")) == 0)
-        {
-          property = glade_widget_get_property (widget, glade_property_class_id (pclass));
-          glade_property_sync (property);
-        }
-    }
-
-  g_idle_add ((GSourceFunc) glade_gtk_cell_renderer_sync_attributes, object);
-}
-
-GladeEditorProperty *
-glade_gtk_cell_renderer_create_eprop (GladeWidgetAdaptor * adaptor,
-                                      GladePropertyClass * klass,
-                                      gboolean use_command)
-{
-  GladeEditorProperty *eprop;
-
-  if (strncmp (glade_property_class_id (klass), "attr-", strlen ("attr-")) == 0)
-    eprop = g_object_new (GLADE_TYPE_EPROP_CELL_ATTRIBUTE,
-                          "property-class", klass,
-                          "use-command", use_command, NULL);
-  else
-    eprop = GWA_GET_CLASS
-        (G_TYPE_OBJECT)->create_eprop (adaptor, klass, use_command);
-  return eprop;
-}
-
-
-GladeEditable *
-glade_gtk_cell_renderer_create_editable (GladeWidgetAdaptor * adaptor,
-                                         GladeEditorPageType type)
-{
-  GladeEditable *editable;
-
-  /* Get base editable */
-  editable = GWA_GET_CLASS (G_TYPE_OBJECT)->create_editable (adaptor, type);
-
-  if (type == GLADE_PAGE_GENERAL || type == GLADE_PAGE_COMMON)
-    return (GladeEditable *) glade_cell_renderer_editor_new (adaptor, type,
-                                                             editable);
-
-  return editable;
-}
-
-static void
-glade_gtk_cell_renderer_set_use_attribute (GObject * object,
-                                           const gchar * property_name,
-                                           const GValue * value)
-{
-  GladeWidget *widget = glade_widget_get_from_gobject (object);
-  gchar *attr_prop_name, *prop_msg, *attr_msg;
-
-  attr_prop_name = g_strdup_printf ("attr-%s", property_name);
-
-  prop_msg = g_strdup_printf (_("%s is set to load %s from the model"),
-                              glade_widget_get_name (widget), property_name);
-  attr_msg = g_strdup_printf (_("%s is set to manipulate %s directly"),
-                              glade_widget_get_name (widget), attr_prop_name);
-
-  glade_widget_property_set_sensitive (widget, property_name, FALSE, prop_msg);
-  glade_widget_property_set_sensitive (widget, attr_prop_name, FALSE, attr_msg);
-
-  if (g_value_get_boolean (value))
-    glade_widget_property_set_sensitive (widget, attr_prop_name, TRUE, NULL);
-  else
-    {
-      GladeProperty *property =
-          glade_widget_get_property (widget, property_name);
-
-      glade_property_set_sensitive (property, TRUE, NULL);
-      glade_property_sync (property);
-    }
-
-  g_free (prop_msg);
-  g_free (attr_msg);
-  g_free (attr_prop_name);
-}
-
-static GladeProperty *
-glade_gtk_cell_renderer_attribute_switch (GladeWidget * gwidget,
-                                          const gchar * property_name)
-{
-  GladeProperty *property;
-  gchar *use_attr_name = g_strdup_printf ("use-attr-%s", property_name);
-
-  property = glade_widget_get_property (gwidget, use_attr_name);
-  g_free (use_attr_name);
-
-  return property;
-}
-
-static gboolean
-glade_gtk_cell_renderer_property_enabled (GObject * object,
-                                          const gchar * property_name)
-{
-  GladeProperty *property;
-  GladeWidget *gwidget = glade_widget_get_from_gobject (object);
-  gboolean use_attr = TRUE;
-
-  if ((property =
-       glade_gtk_cell_renderer_attribute_switch (gwidget,
-                                                 property_name)) != NULL)
-    glade_property_get (property, &use_attr);
-
-  return !use_attr;
-}
-
-
-void
-glade_gtk_cell_renderer_set_property (GladeWidgetAdaptor * adaptor,
-                                      GObject * object,
-                                      const gchar * property_name,
-                                      const GValue * value)
-{
-  static gint use_attr_len = 0;
-  static gint attr_len = 0;
-
-  if (!attr_len)
-    {
-      use_attr_len = strlen ("use-attr-");
-      attr_len = strlen ("attr-");
-    }
-
-  if (strncmp (property_name, "use-attr-", use_attr_len) == 0)
-    glade_gtk_cell_renderer_set_use_attribute (object,
-                                               &property_name[use_attr_len],
-                                               value);
-  else if (strncmp (property_name, "attr-", attr_len) == 0)
-    glade_gtk_cell_renderer_sync_attributes (object);
-  else if (glade_gtk_cell_renderer_property_enabled (object, property_name))
-    /* Chain Up */
-    GWA_GET_CLASS (G_TYPE_OBJECT)->set_property (adaptor,
-                                                 object, property_name, value);
-}
-
-static void
-glade_gtk_cell_renderer_write_properties (GladeWidget * widget,
-                                          GladeXmlContext * context,
-                                          GladeXmlNode * node)
-{
-  GladeProperty *property, *prop;
-  GladePropertyClass *pclass;
-  gchar *attr_name;
-  GList *l;
-  static gint attr_len = 0;
-
-  if (!attr_len)
-    attr_len = strlen ("attr-");
-
-  for (l = glade_widget_get_properties (widget); l; l = l->next)
-    {
-      property = l->data;
-      pclass   = glade_property_get_class (property);
-
-      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) == 0)
-        {
-          gchar *use_attr_str;
-          gboolean use_attr = FALSE;
-
-          use_attr_str = g_strdup_printf ("use-%s", glade_property_class_id (pclass));
-          glade_widget_property_get (widget, use_attr_str, &use_attr);
-
-          attr_name = (gchar *)&glade_property_class_id (pclass)[attr_len];
-          prop = glade_widget_get_property (widget, attr_name);
-
-          if (!use_attr && prop)
-           {
-             /* Special case to write GtkCellRendererPixbuf:stock-size */
-             if (strcmp (attr_name, "stock-size") == 0)
-               glade_gtk_write_icon_size (widget, context, node, "stock-size");
-             else
-               glade_property_write (prop, context, node);
-           }
-
-          g_free (use_attr_str);
-        }
-    }
-}
-
-void
-glade_gtk_cell_renderer_write_widget (GladeWidgetAdaptor * adaptor,
-                                      GladeWidget * widget,
-                                      GladeXmlContext * context,
-                                      GladeXmlNode * node)
-{
-  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
-       glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
-    return;
-
-  /* Write our normal properties, then chain up to write any other normal properties,
-   * then attributes 
-   */
-  glade_gtk_cell_renderer_write_properties (widget, context, node);
-
-  GWA_GET_CLASS (G_TYPE_OBJECT)->write_widget (adaptor, widget, context, node);
-}
-
-static void
-glade_gtk_cell_renderer_parse_finished (GladeProject * project,
-                                        GladeWidget * widget)
-{
-  GladeProperty *property;
-  GList *l;
-  static gint attr_len = 0, use_attr_len = 0;
-
-  /* Set "use-attr-*" everywhere that the object property is non-default 
-   *
-   * We do this in the finished handler because some properties may be
-   * object type properties (which may be anywhere in the glade file).
-   */
-  if (!attr_len)
-    {
-      attr_len = strlen ("attr-");
-      use_attr_len = strlen ("use-attr-");
-    }
-
-  for (l = glade_widget_get_properties (widget); l; l = l->next)
-    {
-      GladeProperty *switch_prop;
-      GladePropertyClass *pclass;
-
-      property = l->data;
-      pclass   = glade_property_get_class (property);
-
-      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) != 0 &&
-          strncmp (glade_property_class_id (pclass), "use-attr-", use_attr_len) != 0 &&
-          (switch_prop =
-           glade_gtk_cell_renderer_attribute_switch (widget,
-                                                     glade_property_class_id (pclass))) != NULL)
-        {
-          if (glade_property_original_default (property))
-            glade_property_set (switch_prop, TRUE);
-          else
-            glade_property_set (switch_prop, FALSE);
-        }
-    }
-}
-
-void
-glade_gtk_cell_renderer_read_widget (GladeWidgetAdaptor * adaptor,
-                                     GladeWidget * widget, GladeXmlNode * node)
-{
-  if (!(glade_xml_node_verify_silent (node, GLADE_XML_TAG_WIDGET) ||
-       glade_xml_node_verify_silent (node, GLADE_XML_TAG_TEMPLATE)))
-    return;
-
-  /* First chain up and read in all the properties... */
-  GWA_GET_CLASS (G_TYPE_OBJECT)->read_widget (adaptor, widget, node);
-
-  g_signal_connect (glade_widget_get_project (widget), "parse-finished",
-                    G_CALLBACK (glade_gtk_cell_renderer_parse_finished),
-                    widget);
-}
-
-/*--------------------------- GtkCellLayout ---------------------------------*/
-gboolean
-glade_gtk_cell_layout_add_verify (GladeWidgetAdaptor *adaptor,
-                                 GtkWidget          *container,
-                                 GtkWidget          *child,
-                                 gboolean            user_feedback)
-{
-  if (!GTK_IS_CELL_RENDERER (child))
-    {
-      if (user_feedback)
-       {
-         GladeWidgetAdaptor *cell_adaptor = 
-           glade_widget_adaptor_get_by_type (GTK_TYPE_CELL_RENDERER);
-
-         glade_util_ui_message (glade_app_get_window (),
-                                GLADE_UI_INFO, NULL,
-                                ONLY_THIS_GOES_IN_THAT_MSG,
-                                glade_widget_adaptor_get_title (cell_adaptor),
-                                glade_widget_adaptor_get_title (adaptor));
-       }
-
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-void
-glade_gtk_cell_layout_add_child (GladeWidgetAdaptor * adaptor,
-                                 GObject * container, GObject * child)
-{
-  GladeWidget *gmodel = NULL;
-  GladeWidget *grenderer = glade_widget_get_from_gobject (child);
-
-  if (GTK_IS_ICON_VIEW (container) &&
-      (gmodel = glade_cell_renderer_get_model (grenderer)) != NULL)
-    gtk_icon_view_set_model (GTK_ICON_VIEW (container), NULL);
-
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (container),
-                              GTK_CELL_RENDERER (child), TRUE);
-
-  if (gmodel)
-    gtk_icon_view_set_model (GTK_ICON_VIEW (container),
-                             GTK_TREE_MODEL (glade_widget_get_object (gmodel)));
-
-  glade_gtk_cell_renderer_sync_attributes (child);
-}
-
-void
-glade_gtk_cell_layout_remove_child (GladeWidgetAdaptor * adaptor,
-                                    GObject * container, GObject * child)
-{
-  GtkCellLayout *layout = GTK_CELL_LAYOUT (container);
-  GList *l, *children = gtk_cell_layout_get_cells (layout);
-
-  /* Add a reference to every cell except the one we want to remove */
-  for (l = children; l; l = g_list_next (l))
-    if (l->data != child)
-      g_object_ref (l->data);
-    else
-      l->data = NULL;
-
-  /* remove every cell */
-  gtk_cell_layout_clear (layout);
-
-  /* pack others cell renderers */
-  for (l = children; l; l = g_list_next (l))
-    {
-      if (l->data == NULL)
-        continue;
-
-      gtk_cell_layout_pack_start (layout, GTK_CELL_RENDERER (l->data), TRUE);
-
-      /* Remove our transient reference */
-      g_object_unref (l->data);
-    }
-
-  g_list_free (children);
-}
-
-GList *
-glade_gtk_cell_layout_get_children (GladeWidgetAdaptor * adaptor,
-                                    GObject * container)
-{
-  return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (container));
-}
-
-
-void
-glade_gtk_cell_layout_get_child_property (GladeWidgetAdaptor * adaptor,
-                                          GObject * container,
-                                          GObject * child,
-                                          const gchar * property_name,
-                                          GValue * value)
-{
-  if (strcmp (property_name, "position") == 0)
-    {
-      GList *cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (container));
-
-      /* We have to fake it, assume we are loading and always return the last item */
-      g_value_set_int (value, g_list_length (cells) - 1);
-
-      g_list_free (cells);
-    }
-  else
-    /* Chain Up */
-    GWA_GET_CLASS
-        (GTK_TYPE_CONTAINER)->child_get_property (adaptor,
-                                                  container, child,
-                                                  property_name, value);
-}
-
-void
-glade_gtk_cell_layout_set_child_property (GladeWidgetAdaptor * adaptor,
-                                          GObject * container,
-                                          GObject * child,
-                                          const gchar * property_name,
-                                          const GValue * value)
-{
-  if (strcmp (property_name, "position") == 0)
-    {
-      /* Need verify on position property !!! XXX */
-      gtk_cell_layout_reorder (GTK_CELL_LAYOUT (container),
-                               GTK_CELL_RENDERER (child),
-                               g_value_get_int (value));
-    }
-  else
-    /* Chain Up */
-    GWA_GET_CLASS
-        (GTK_TYPE_CONTAINER)->child_set_property (adaptor,
-                                                  container, child,
-                                                  property_name, value);
-}
-
-static void
-glade_gtk_cell_renderer_read_attributes (GladeWidget * widget,
-                                         GladeXmlNode * node)
-{
-  GladeXmlNode *attrs_node;
-  GladeProperty *attr_prop, *use_attr_prop;
-  GladeXmlNode *prop;
-  gchar *name, *column_str, *attr_prop_name, *use_attr_name;
-
-  if ((attrs_node =
-       glade_xml_search_child (node, GLADE_TAG_ATTRIBUTES)) == NULL)
-    return;
-
-  for (prop = glade_xml_node_get_children (attrs_node); prop;
-       prop = glade_xml_node_next (prop))
-    {
-
-      if (!glade_xml_node_verify_silent (prop, GLADE_TAG_ATTRIBUTE))
-        continue;
-
-      name =
-          glade_xml_get_property_string_required (prop, GLADE_TAG_NAME, NULL);
-      column_str = glade_xml_get_content (prop);
-      attr_prop_name = g_strdup_printf ("attr-%s", name);
-      use_attr_name = g_strdup_printf ("use-attr-%s", name);
-
-      attr_prop = glade_widget_get_property (widget, attr_prop_name);
-      use_attr_prop = glade_widget_get_property (widget, use_attr_name);
-
-      if (attr_prop && use_attr_prop)
-        {
-          gboolean use_attribute = FALSE;
-          glade_property_get (use_attr_prop, &use_attribute);
-
-          if (use_attribute)
-            glade_property_set (attr_prop,
-                                g_ascii_strtoll (column_str, NULL, 10));
-        }
-
-      g_free (name);
-      g_free (column_str);
-      g_free (attr_prop_name);
-      g_free (use_attr_name);
-
-    }
-}
-
-void
-glade_gtk_cell_layout_read_child (GladeWidgetAdaptor * adaptor,
-                                  GladeWidget * widget, GladeXmlNode * node)
-{
-  GladeXmlNode *widget_node;
-  GladeWidget *child_widget;
-  gchar *internal_name;
-
-  if (!glade_xml_node_verify (node, GLADE_XML_TAG_CHILD))
-    return;
-
-  internal_name =
-      glade_xml_get_property_string (node, GLADE_XML_TAG_INTERNAL_CHILD);
-
-  if ((widget_node =
-       glade_xml_search_child (node, GLADE_XML_TAG_WIDGET)) != NULL)
-    {
-
-      /* Combo box is a special brand of cell-layout, it can also have the internal entry */
-      if ((child_widget = glade_widget_read (glade_widget_get_project (widget),
-                                             widget, widget_node,
-                                             internal_name)) != NULL)
-        {
-          /* Dont set any packing properties on internal children here,
-           * its possible but just not relevant for known celllayouts...
-           * i.e. maybe GtkTreeViewColumn will expose the internal button ?
-           * but no need for packing properties there either.
-           */
-          if (!internal_name)
-            {
-              glade_widget_add_child (widget, child_widget, FALSE);
-
-              glade_gtk_cell_renderer_read_attributes (child_widget, node);
-
-              g_idle_add ((GSourceFunc) glade_gtk_cell_renderer_sync_attributes,
-                          glade_widget_get_object (child_widget));
-            }
-        }
-    }
-  g_free (internal_name);
-}
-
-static void
-glade_gtk_cell_renderer_write_attributes (GladeWidget * widget,
-                                          GladeXmlContext * context,
-                                          GladeXmlNode * node)
-{
-  GladeProperty *property;
-  GladePropertyClass *pclass;
-  GladeXmlNode *attrs_node;
-  gchar *attr_name;
-  GList *l;
-  static gint attr_len = 0;
-
-  if (!attr_len)
-    attr_len = strlen ("attr-");
-
-  attrs_node = glade_xml_node_new (context, GLADE_TAG_ATTRIBUTES);
-
-  for (l = glade_widget_get_properties (widget); l; l = l->next)
-    {
-      property = l->data;
-      pclass   = glade_property_get_class (property);
-
-      if (strncmp (glade_property_class_id (pclass), "attr-", attr_len) == 0)
-        {
-          GladeXmlNode *attr_node;
-          gchar *column_str, *use_attr_str;
-          gboolean use_attr = FALSE;
-
-          use_attr_str = g_strdup_printf ("use-%s", glade_property_class_id (pclass));
-          glade_widget_property_get (widget, use_attr_str, &use_attr);
-
-          if (use_attr && g_value_get_int (glade_property_inline_value (property)) >= 0)
-            {
-              column_str =
-                  g_strdup_printf ("%d", g_value_get_int (glade_property_inline_value (property)));
-              attr_name = (gchar *)&glade_property_class_id (pclass)[attr_len];
-
-              attr_node = glade_xml_node_new (context, GLADE_TAG_ATTRIBUTE);
-              glade_xml_node_append_child (attrs_node, attr_node);
-              glade_xml_node_set_property_string (attr_node, GLADE_TAG_NAME,
-                                                  attr_name);
-              glade_xml_set_content (attr_node, column_str);
-              g_free (column_str);
-            }
-          g_free (use_attr_str);
-        }
-    }
-
-  if (!glade_xml_node_get_children (attrs_node))
-    glade_xml_node_delete (attrs_node);
-  else
-    glade_xml_node_append_child (node, attrs_node);
-}
-
-void
-glade_gtk_cell_layout_write_child (GladeWidgetAdaptor * adaptor,
-                                   GladeWidget * widget,
-                                   GladeXmlContext * context,
-                                   GladeXmlNode * node)
-{
-  GladeXmlNode *child_node;
-
-  child_node = glade_xml_node_new (context, GLADE_XML_TAG_CHILD);
-  glade_xml_node_append_child (node, child_node);
-
-  /* ComboBox can have an internal entry */
-  if (glade_widget_get_internal (widget))
-    glade_xml_node_set_property_string (child_node,
-                                        GLADE_XML_TAG_INTERNAL_CHILD,
-                                        glade_widget_get_internal (widget));
-
-  /* Write out the widget */
-  glade_widget_write (widget, context, child_node);
-
-  glade_gtk_cell_renderer_write_attributes (widget, context, child_node);
-}
-
-static gchar *
-glade_gtk_cell_layout_get_display_name (GladeBaseEditor * editor,
-                                        GladeWidget * gchild,
-                                        gpointer user_data)
-{
-  GObject *child = glade_widget_get_object (gchild);
-  gchar *name;
-
-  if (GTK_IS_TREE_VIEW_COLUMN (child))
-    glade_widget_property_get (gchild, "title", &name);
-  else
-    name = (gchar *)glade_widget_get_name (gchild);
-
-  return g_strdup (name);
-}
-
-static void
-glade_gtk_cell_layout_child_selected (GladeBaseEditor * editor,
-                                      GladeWidget * gchild, gpointer data)
-{
-  GObject *child = glade_widget_get_object (gchild);
-
-  glade_base_editor_add_label (editor, GTK_IS_TREE_VIEW_COLUMN (child) ?
-                               _("Tree View Column") : _("Cell Renderer"));
-
-  glade_base_editor_add_default_properties (editor, gchild);
-
-  glade_base_editor_add_label (editor, GTK_IS_TREE_VIEW_COLUMN (child) ?
-                               _("Properties") :
-                               _("Properties and Attributes"));
-  glade_base_editor_add_editable (editor, gchild, GLADE_PAGE_GENERAL);
-
-  if (GTK_IS_CELL_RENDERER (child))
-    {
-      glade_base_editor_add_label (editor,
-                                   _("Common Properties and Attributes"));
-      glade_base_editor_add_editable (editor, gchild, GLADE_PAGE_COMMON);
-    }
-}
-
-static gboolean
-glade_gtk_cell_layout_move_child (GladeBaseEditor * editor,
-                                  GladeWidget * gparent,
-                                  GladeWidget * gchild, gpointer data)
-{
-  GObject *parent = glade_widget_get_object (gparent);
-  GObject *child = glade_widget_get_object (gchild);
-  GList list = { 0, };
-
-  if (GTK_IS_TREE_VIEW (parent) && !GTK_IS_TREE_VIEW_COLUMN (child))
-    return FALSE;
-  if (GTK_IS_CELL_LAYOUT (parent) && !GTK_IS_CELL_RENDERER (child))
-    return FALSE;
-  if (GTK_IS_CELL_RENDERER (parent))
-    return FALSE;
-
-  if (gparent != glade_widget_get_parent (gchild))
-    {
-      list.data = gchild;
-      glade_command_dnd (&list, gparent, NULL);
-    }
-
-  return TRUE;
-}
-
-static void
-glade_gtk_cell_layout_launch_editor (GObject *layout, gchar *window_name)
-{
-  GladeWidget        *widget  = glade_widget_get_from_gobject (layout);
-  GladeWidgetAdaptor *adaptor = glade_widget_get_adaptor (widget);
-  GladeBaseEditor    *editor;
-  GladeEditable      *layout_editor;
-  GtkWidget          *window;
-
-  layout_editor = glade_widget_adaptor_create_editable (adaptor, GLADE_PAGE_GENERAL);
-  layout_editor = (GladeEditable *) glade_tree_view_editor_new (adaptor, layout_editor);
-
-  /* Editor */
-  editor = glade_base_editor_new (layout, layout_editor,
-                                  _("Text"), GTK_TYPE_CELL_RENDERER_TEXT,
-                                  _("Accelerator"), GTK_TYPE_CELL_RENDERER_ACCEL,
-                                  _("Combo"), GTK_TYPE_CELL_RENDERER_COMBO,
-                                  _("Spin"), GTK_TYPE_CELL_RENDERER_SPIN,
-                                  _("Pixbuf"), GTK_TYPE_CELL_RENDERER_PIXBUF,
-                                  _("Progress"), GTK_TYPE_CELL_RENDERER_PROGRESS,
-                                  _("Toggle"), GTK_TYPE_CELL_RENDERER_TOGGLE,
-                                  _("Spinner"), GTK_TYPE_CELL_RENDERER_SPINNER,
-                                  NULL);
-
-  g_signal_connect (editor, "get-display-name",
-                    G_CALLBACK (glade_gtk_cell_layout_get_display_name), NULL);
-  g_signal_connect (editor, "child-selected",
-                    G_CALLBACK (glade_gtk_cell_layout_child_selected), NULL);
-  g_signal_connect (editor, "move-child",
-                    G_CALLBACK (glade_gtk_cell_layout_move_child), NULL);
-
-  gtk_widget_show (GTK_WIDGET (editor));
-
-  window = glade_base_editor_pack_new_window (editor, window_name, NULL);
-  gtk_widget_show (window);
-}
-
-
-static void
-glade_gtk_cell_layout_launch_editor_action (GObject * object)
-{
-  GladeWidget *w = glade_widget_get_from_gobject (object);
-
-  do
-    {
-      GObject *obj = glade_widget_get_object (w);
-
-      if (GTK_IS_TREE_VIEW (obj))
-        {
-          glade_gtk_treeview_launch_editor (obj);
-          break;
-        }
-      else if (GTK_IS_ICON_VIEW (obj))
-        {
-          glade_gtk_cell_layout_launch_editor (obj, _("Icon View Editor"));
-          break;
-        }
-      else if (GTK_IS_COMBO_BOX (obj))
-        {
-          glade_gtk_cell_layout_launch_editor (obj, _("Combo Editor"));
-          break;
-        }
-      else if (GTK_IS_ENTRY_COMPLETION (obj))
-        {
-          glade_gtk_cell_layout_launch_editor (obj, _("Entry Completion Editor"));
-          break;
-        }
-    }
-  while ((w = glade_widget_get_parent (w)));
-}
-
-void
-glade_gtk_cell_layout_action_activate (GladeWidgetAdaptor * adaptor,
-                                       GObject * object,
-                                       const gchar * action_path)
-{
-  if (strcmp (action_path, "launch_editor") == 0)
-    glade_gtk_cell_layout_launch_editor_action (object);
-  else
-    GWA_GET_CLASS (G_TYPE_OBJECT)->action_activate (adaptor,
-                                                    object, action_path);
-}
-
-void
-glade_gtk_cell_layout_action_activate_as_widget (GladeWidgetAdaptor * adaptor,
-                                                 GObject * object,
-                                                 const gchar * action_path)
-{
-  if (strcmp (action_path, "launch_editor") == 0)
-    glade_gtk_cell_layout_launch_editor_action (object);
-  else
-    GWA_GET_CLASS (GTK_TYPE_WIDGET)->action_activate (adaptor,
-                                                      object, action_path);
-}
-
-
-
-/*--------------------------- GtkTreeView ---------------------------------*/
-
-gboolean
-glade_gtk_treeview_add_verify (GladeWidgetAdaptor *adaptor,
-                              GtkWidget          *container,
-                              GtkWidget          *child,
-                              gboolean            user_feedback)
-{
-  if (!GTK_IS_TREE_VIEW_COLUMN (child))
-    {
-      if (user_feedback)
-       {
-         GladeWidgetAdaptor *cell_adaptor = 
-           glade_widget_adaptor_get_by_type (GTK_TYPE_TREE_VIEW_COLUMN);
-
-         glade_util_ui_message (glade_app_get_window (),
-                                GLADE_UI_INFO, NULL,
-                                ONLY_THIS_GOES_IN_THAT_MSG,
-                                glade_widget_adaptor_get_title (cell_adaptor),
-                                glade_widget_adaptor_get_title (adaptor));
-       }
-
-      return FALSE;
-    }
-
-  return TRUE;
-}
-
-static void
-glade_gtk_treeview_launch_editor (GObject * treeview)
-{
-  GladeWidget        *widget  = glade_widget_get_from_gobject (treeview);
-  GladeWidgetAdaptor *adaptor = glade_widget_get_adaptor (widget);
-  GladeBaseEditor    *editor;
-  GladeEditable      *treeview_editor;
-  GtkWidget          *window;
-
-  treeview_editor = glade_widget_adaptor_create_editable (adaptor, GLADE_PAGE_GENERAL);
-  treeview_editor = (GladeEditable *) glade_tree_view_editor_new (adaptor, treeview_editor);
-
-  /* Editor */
-  editor = glade_base_editor_new (treeview, treeview_editor,
-                                  _("Column"), GTK_TYPE_TREE_VIEW_COLUMN, NULL);
-
-  glade_base_editor_append_types (editor, GTK_TYPE_TREE_VIEW_COLUMN,
-                                  _("Text"), GTK_TYPE_CELL_RENDERER_TEXT,
-                                  _("Accelerator"),
-                                  GTK_TYPE_CELL_RENDERER_ACCEL, _("Combo"),
-                                  GTK_TYPE_CELL_RENDERER_COMBO, _("Spin"),
-                                  GTK_TYPE_CELL_RENDERER_SPIN, _("Pixbuf"),
-                                  GTK_TYPE_CELL_RENDERER_PIXBUF, _("Progress"),
-                                  GTK_TYPE_CELL_RENDERER_PROGRESS, _("Toggle"),
-                                  GTK_TYPE_CELL_RENDERER_TOGGLE, _("Spinner"),
-                                  GTK_TYPE_CELL_RENDERER_SPINNER, NULL);
-
-  g_signal_connect (editor, "get-display-name",
-                    G_CALLBACK (glade_gtk_cell_layout_get_display_name), NULL);
-  g_signal_connect (editor, "child-selected",
-                    G_CALLBACK (glade_gtk_cell_layout_child_selected), NULL);
-  g_signal_connect (editor, "move-child",
-                    G_CALLBACK (glade_gtk_cell_layout_move_child), NULL);
-
-  gtk_widget_show (GTK_WIDGET (editor));
-
-  window =
-      glade_base_editor_pack_new_window (editor, _("Tree View Editor"), NULL);
-  gtk_widget_show (window);
-}
-
-void
-glade_gtk_treeview_action_activate (GladeWidgetAdaptor * adaptor,
-                                    GObject * object, const gchar * action_path)
-{
-  if (strcmp (action_path, "launch_editor") == 0)
-    {
-      glade_gtk_treeview_launch_editor (object);
-    }
-  else
-    GWA_GET_CLASS (GTK_TYPE_CONTAINER)->action_activate (adaptor,
-                                                         object, action_path);
-}
-
-static gint
-glade_gtk_treeview_get_column_index (GtkTreeView * view,
-                                     GtkTreeViewColumn * column)
-{
-  GtkTreeViewColumn *iter;
-  gint i;
-
-  for (i = 0; (iter = gtk_tree_view_get_column (view, i)) != NULL; i++)
-    if (iter == column)
-      return i;
-
-  return -1;
-}
-
-void
-glade_gtk_treeview_get_child_property (GladeWidgetAdaptor * adaptor,
-                                       GObject * container,
-                                       GObject * child,
-                                       const gchar * property_name,
-                                       GValue * value)
-{
-  if (strcmp (property_name, "position") == 0)
-    g_value_set_int (value,
-                     glade_gtk_treeview_get_column_index (GTK_TREE_VIEW
-                                                          (container),
-                                                          GTK_TREE_VIEW_COLUMN
-                                                          (child)));
-  else
-    /* Chain Up */
-    GWA_GET_CLASS
-        (GTK_TYPE_CONTAINER)->child_get_property (adaptor,
-                                                  container, child,
-                                                  property_name, value);
-}
-
-void
-glade_gtk_treeview_set_child_property (GladeWidgetAdaptor * adaptor,
-                                       GObject * container,
-                                       GObject * child,
-                                       const gchar * property_name,
-                                       const GValue * value)
-{
-  if (strcmp (property_name, "position") == 0)
-    {
-
-      gtk_tree_view_remove_column (GTK_TREE_VIEW (container),
-                                   GTK_TREE_VIEW_COLUMN (child));
-      gtk_tree_view_insert_column (GTK_TREE_VIEW (container),
-                                   GTK_TREE_VIEW_COLUMN (child),
-                                   g_value_get_int (value));
-    }
-  else
-    /* Chain Up */
-    GWA_GET_CLASS
-        (GTK_TYPE_CONTAINER)->child_set_property (adaptor,
-                                                  container, child,
-                                                  property_name, value);
-}
-
-GList *
-glade_gtk_treeview_get_children (GladeWidgetAdaptor * adaptor,
-                                 GtkTreeView * view)
-{
-  GList *children;
-
-  children = gtk_tree_view_get_columns (view);
-  children = g_list_prepend (children, gtk_tree_view_get_selection (view));
-
-  return children;
-}
-
-/* XXX FIXME: We should hide the actual "fixed-height-mode" setting from
- * treeview editors and provide a custom control that sets all its columns
- * to fixed size and then control the column's sensitivity accordingly.
- */
-#define INSENSITIVE_COLUMN_SIZING_MSG \
-       _("Columns must have a fixed size inside a treeview with fixed height mode set")
-
-void
-glade_gtk_treeview_add_child (GladeWidgetAdaptor * adaptor,
-                              GObject * container, GObject * child)
-{
-  GtkTreeView *view = GTK_TREE_VIEW (container);
-  GtkTreeViewColumn *column;
-  GladeWidget *gcolumn;
-
-  if (!GTK_IS_TREE_VIEW_COLUMN (child))
-    return;
-
-  if (gtk_tree_view_get_fixed_height_mode (view))
-    {
-      gcolumn = glade_widget_get_from_gobject (child);
-      glade_widget_property_set (gcolumn, "sizing", GTK_TREE_VIEW_COLUMN_FIXED);
-      glade_widget_property_set_sensitive (gcolumn, "sizing", FALSE,
-                                           INSENSITIVE_COLUMN_SIZING_MSG);
-    }
-
-  column = GTK_TREE_VIEW_COLUMN (child);
-  gtk_tree_view_append_column (view, column);
-
-  glade_gtk_cell_layout_sync_attributes (G_OBJECT (column));
-}
-
-void
-glade_gtk_treeview_remove_child (GladeWidgetAdaptor * adaptor,
-                                 GObject * container, GObject * child)
-{
-  GtkTreeView *view = GTK_TREE_VIEW (container);
-  GtkTreeViewColumn *column;
-
-  if (!GTK_IS_TREE_VIEW_COLUMN (child))
-    return;
-
-  column = GTK_TREE_VIEW_COLUMN (child);
-  gtk_tree_view_remove_column (view, column);
-}
-
-void
-glade_gtk_treeview_replace_child (GladeWidgetAdaptor * adaptor,
-                                  GObject * container,
-                                  GObject * current, GObject * new_column)
-{
-  GtkTreeView *view = GTK_TREE_VIEW (container);
-  GList *columns;
-  GtkTreeViewColumn *column;
-  GladeWidget *gcolumn;
-  gint index;
-
-  if (!GTK_IS_TREE_VIEW_COLUMN (current))
-    return;
-
-  column = GTK_TREE_VIEW_COLUMN (current);
-
-  columns = gtk_tree_view_get_columns (view);
-  index = g_list_index (columns, column);
-  g_list_free (columns);
-
-  gtk_tree_view_remove_column (view, column);
-  column = GTK_TREE_VIEW_COLUMN (new_column);
-
-  gtk_tree_view_insert_column (view, column, index);
-
-  if (gtk_tree_view_get_fixed_height_mode (view))
-    {
-      gcolumn = glade_widget_get_from_gobject (column);
-      glade_widget_property_set (gcolumn, "sizing", GTK_TREE_VIEW_COLUMN_FIXED);
-      glade_widget_property_set_sensitive (gcolumn, "sizing", FALSE,
-                                           INSENSITIVE_COLUMN_SIZING_MSG);
-    }
-
-  glade_gtk_cell_layout_sync_attributes (G_OBJECT (column));
-}
-
-gboolean
-glade_gtk_treeview_depends (GladeWidgetAdaptor * adaptor,
-                            GladeWidget * widget, GladeWidget * another)
-{
-  if (GTK_IS_TREE_MODEL (glade_widget_get_object (another)))
-    return TRUE;
-
-  return GWA_GET_CLASS (GTK_TYPE_CONTAINER)->depends (adaptor, widget, another);
-}
-
 /*--------------------------- GtkAdjustment ---------------------------------*/
 void
 glade_gtk_adjustment_write_widget (GladeWidgetAdaptor * adaptor,
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 624c729..ed636a2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -67,6 +67,8 @@ plugins/gtk+/glade-gtk-action-widgets.c
 plugins/gtk+/glade-gtk-assistant.c
 plugins/gtk+/glade-gtk-box.c
 plugins/gtk+/glade-gtk-button.c
+plugins/gtk+/glade-gtk-cell-layout.c
+plugins/gtk+/glade-gtk-cell-renderer.c
 plugins/gtk+/glade-gtk-combo-box.c
 plugins/gtk+/glade-gtk-combo-box-text.c
 plugins/gtk+/glade-gtk-container.c
@@ -83,6 +85,7 @@ plugins/gtk+/glade-gtk-image.c
 plugins/gtk+/glade-gtk-image-menu-item.c
 plugins/gtk+/glade-gtk-info-bar.c
 plugins/gtk+/glade-gtk-label.c
+plugins/gtk+/glade-gtk-list-store.c
 plugins/gtk+/glade-gtk-menu.c
 plugins/gtk+/glade-gtk-menu-bar.c
 plugins/gtk+/glade-gtk-menu-item.c
@@ -105,6 +108,7 @@ plugins/gtk+/glade-gtk-tool-item.c
 plugins/gtk+/glade-gtk-tool-item-group.c
 plugins/gtk+/glade-gtk-tool-palette.c
 plugins/gtk+/glade-gtk-toolbar.c
+plugins/gtk+/glade-gtk-tree-view.c
 plugins/gtk+/glade-gtk-widget.c
 plugins/gtk+/glade-gtk-window.c
 plugins/gtk+/glade-icon-factory-editor.c


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