? Doxyfile
? gtk.kdevelop
? treeview_simpler_api.patch
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gtk+/ChangeLog,v
retrieving revision 1.6286.2.181
diff -u -p -r1.6286.2.181 ChangeLog
--- ChangeLog	9 Apr 2005 23:54:04 -0000	1.6286.2.181
+++ ChangeLog	11 Apr 2005 02:24:15 -0000
@@ -1,3 +1,17 @@
+2005-04-11  Murray Cumming, <murrayc@murrayc.com>
+
+	* gtk/gtktreeview.c:
+	* gtk/gtktreeview.h:
+	Added gtk_tree_view_append_column_default_renderer(),
+	which creates an appropriate default cellrenderer for a 
+	model column an configures it appropriately.
+	Added gtk_tree_view_append_column_default_renderer_editable(),
+	which does the same, plus it writes user-inputted values 
+	back into the model, using a default conversion.
+	* gtk/gtktreeviewcolumn.c:
+	* gtk/gtktreeviewcolumn.h:
+	Added gtk_tree_view_column_pack_start_default_renderer().
+
 2005-04-09  Matthias Clasen  <mclasen@redhat.com>
 
 	* gdk/x11/gdkinput-xfree.c:
Index: gtk/gtktreeview.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktreeview.c,v
retrieving revision 1.429.2.20
diff -u -p -r1.429.2.20 gtktreeview.c
--- gtk/gtktreeview.c	8 Apr 2005 12:53:44 -0000	1.429.2.20
+++ gtk/gtktreeview.c	11 Apr 2005 02:24:26 -0000
@@ -41,7 +41,12 @@
 #include "gtkentry.h"
 #include "gtkframe.h"
 #include "gtktreemodelsort.h"
+#include "gtkcellrenderertext.h"
+#include "gtkcellrenderertoggle.h"
+#include "gtkliststore.h"
+#include "gtktreestore.h"
 #include "gtkalias.h"
+#include "stdlib.h" /* For atoi(). */
 
 #define GTK_TREE_VIEW_PRIORITY_VALIDATE (GDK_PRIORITY_REDRAW + 5)
 #define GTK_TREE_VIEW_PRIORITY_SCROLL_SYNC (GTK_TREE_VIEW_PRIORITY_VALIDATE + 2)
@@ -9727,6 +9732,223 @@ gtk_tree_view_append_column (GtkTreeView
   return gtk_tree_view_insert_column (tree_view, column, -1);
 }
 
+/**
+ * gtk_tree_view_append_column_default_renderer:
+ * @tree_view: A #GtkTreeView.
+ * @model: The #GtkTreeModel for this #GtkTreeView.
+ * @column_index: The index of the model column that should be renderered by the new view column.
+ *
+ * This convenience functino creates a view column with an appropriate renderer and appends it
+ * to the list of columns. Alternatively, you can explicitly create a #GtkTreeViewColumn and set
+ * its title, create a particular #GtkCellRenderer, pack the #GtkCellRenderer into the
+ * #GtkTreeViewColumn, and specify the particular renderer property that should render the model
+ * column.
+ *
+ * Return value: The number of columns in @tree_view after appending.
+ **/
+gint
+gtk_tree_view_append_column_default_renderer (GtkTreeView       *tree_view,
+           const char*   view_column_title,
+           GtkTreeModel *model,
+           gint          column_index)
+{
+  GtkTreeViewColumn* view_column = 0;
+
+  view_column = gtk_tree_view_column_new ();
+  gtk_tree_view_column_set_title (view_column, view_column_title);
+
+  gtk_tree_view_column_pack_start_default_renderer (view_column, model, column_index, TRUE /* expand */);
+
+  return gtk_tree_view_append_column (tree_view, view_column);
+}
+
+typedef struct
+{
+  GtkTreeModel* model;
+  int model_column_index;
+} DefaultRendererCallbackInfo;
+
+static void default_renderer_text_cell_edited_callback (GtkCellRendererText *cell,
+                                  gchar               *path_string,
+                                  gchar               *new_text,
+                                  gpointer             user_data)
+{
+  GtkTreeIter iter;
+  GValue value;
+  DefaultRendererCallbackInfo* callback_info = (DefaultRendererCallbackInfo*)user_data;
+  GType value_type = gtk_tree_model_get_column_type (callback_info->model, callback_info->model_column_index);
+
+  g_value_init (&value, value_type);
+
+  if(value_type == G_TYPE_STRING)
+    g_value_set_string (&value, new_text);
+  else if(value_type == G_TYPE_INT)
+    {
+      gint value_number = atoi (new_text);
+      g_value_set_int (&value, value_number);
+    }
+  else if(value_type == G_TYPE_UINT)
+    {
+      guint value_number = atoi (new_text); /* TODO: Is there some atoui()? */
+      g_value_set_uint (&value, value_number);
+    }
+  else if(value_type == G_TYPE_LONG)
+    {
+      glong value_number = atol (new_text);
+      g_value_set_long (&value, value_number);
+    }
+  else if(value_type == G_TYPE_ULONG)
+    {
+      gulong value_number = atol (new_text); /* TODO: Is there some atoul()? */
+      g_value_set_ulong (&value, value_number);
+    }
+  else
+    {
+      /* TODO: If we registered G_TYPE_STRING-to-numerictypes transform functions then this simpler code would work for all the above cases instead. */
+
+      /* The model column might be a numeric type, though we only have a decimal text representation of it here.
+      * So we use the built-in glib GValue conversions to get the appropriate numeric value if necessary.
+      * That might be gint, guint, etc.
+      * This code is based on the code found in g_object_get_property().
+      */
+      if (!g_value_type_transformable (G_TYPE_STRING, value_type))
+      {
+        g_warning ("Can't convert text input to value of type `%s'", g_type_name (value_type) );
+      }
+      else
+      {
+        GValue value_string;
+        g_value_init (&value_string, G_TYPE_STRING);
+        g_value_set_string (&value, new_text);
+
+        g_value_transform (&value_string, &value);
+        g_value_unset (&value_string);
+      }
+
+    }
+
+  gboolean iter_found = gtk_tree_model_get_iter_from_string (callback_info->model, &iter, path_string);
+  g_assert(iter_found);
+
+  /* Store the user's new value in the model:
+   * TODO: It would be easier if there was a virtual gtk_tree_model_set(), like so
+   *   gtk_tree_model_set (callback_info->model, &iter, callback_info->model_column_index, value, -1);
+   */
+  if (GTK_IS_LIST_STORE(callback_info->model))
+    {
+      gtk_list_store_set_value (GTK_LIST_STORE(callback_info->model), &iter,
+        callback_info->model_column_index, &value);
+    }
+  else if (GTK_IS_TREE_STORE(callback_info->model))
+    {
+      gtk_tree_store_set_value (GTK_TREE_STORE(callback_info->model), &iter,
+        callback_info->model_column_index, &value);
+    }
+
+  g_value_unset(&value);
+}
+
+static void default_renderer_toggle_cell_edited_callback (GtkCellRendererText *cell,
+                                  const gchar*         path_string,
+                                  gpointer             user_data)
+{
+  GtkTreeIter iter;
+  gboolean value = FALSE;
+  DefaultRendererCallbackInfo* callback_info = (DefaultRendererCallbackInfo*)user_data;
+
+  gboolean iter_found = gtk_tree_model_get_iter_from_string (callback_info->model, &iter, path_string);
+  g_assert(iter_found);
+
+  /* Get the current value in the model, and invert it: */
+  gtk_tree_model_get (callback_info->model, &iter, callback_info->model_column_index, &value, -1);
+  value = !value;
+
+  /* Store the user's new value in the model:
+   * TODO: It would be easier if there was a virtual gtk_tree_model_set(), like so
+   *   gtk_tree_model_set (callback_info->model, &iter, callback_info->model_column_index, value, -1);
+   */
+  if (GTK_IS_LIST_STORE(callback_info->model))
+    {
+      gtk_list_store_set (GTK_LIST_STORE(callback_info->model), &iter,
+        callback_info->model_column_index, value, -1);
+    }
+  else if (GTK_IS_TREE_STORE(callback_info->model))
+    {
+      gtk_tree_store_set (GTK_TREE_STORE(callback_info->model), &iter,
+        callback_info->model_column_index, value, -1);
+    }
+}
+
+static void default_renderer_destroy_user_data_callback (GtkCellRendererText *cell,
+                                  gpointer             user_data)
+{
+  DefaultRendererCallbackInfo* callback_info = (DefaultRendererCallbackInfo*)user_data;
+  g_free(callback_info);
+}
+
+
+/**
+ * gtk_tree_view_append_column_default_renderer_editable:
+ * @tree_view: A #GtkTreeView.
+ * @model: The #GtkTreeModel for this #GtkTreeView.
+ * @column_index: The index of the model column that should be renderered by the new view column.
+ *
+ * Like gtk_tree_view_append_column_default_renderer(), but the #GtkCellRenderer will also
+ * be editable by the user, with edited values stored automatically in the model.
+ *
+ * Return value: The number of columns in @tree_view after appending.
+ **/
+gint
+gtk_tree_view_append_column_default_renderer_editable (GtkTreeView       *tree_view,
+           const char*   view_column_title,
+           GtkTreeModel *model,
+           gint          column_index)
+{
+  int view_columns_count = 0;
+  GtkCellRenderer *cell_renderer = 0;
+  /* GtkCellRendererText *cell_renderer_text = 0;
+  GtkCellRendererToggle *cell_renderer_toggle = 0; */
+  GtkTreeViewColumn *view_column = 0;
+  GList* list_renderers = 0;
+
+  /* Create the view column: */
+  view_columns_count = gtk_tree_view_append_column_default_renderer (tree_view, view_column_title, model, column_index);
+  /* Make the column editable: */
+  view_column = gtk_tree_view_get_column (tree_view, view_columns_count - 1);
+
+  list_renderers = gtk_tree_view_column_get_cell_renderers (view_column);
+  cell_renderer = GTK_CELL_RENDERER(list_renderers->data); /* The first cell renderer in the GList. */
+  g_list_free(list_renderers);
+  list_renderers = 0;
+
+  /* Set the appropriate property to make the cell renderer editable.
+   * TODO: It would be nice if, instead, this was a virtual method of GtkCellRenderer.
+   */
+  if (GTK_IS_CELL_RENDERER_TEXT (cell_renderer))
+    {
+      g_object_set(cell_renderer, "editable", TRUE, NULL);
+
+      DefaultRendererCallbackInfo* user_data = g_new0(DefaultRendererCallbackInfo, 1);
+      user_data->model = model;
+      user_data->model_column_index = column_index;
+
+      g_signal_connect(cell_renderer, "edited", (GCallback) default_renderer_text_cell_edited_callback, user_data);
+      g_signal_connect(cell_renderer, "destroy", (GCallback) default_renderer_destroy_user_data_callback, user_data); /* TODO: Is this the best way to do this? */
+    }
+  else if (GTK_IS_CELL_RENDERER_TOGGLE (cell_renderer))
+    {
+      g_object_set(cell_renderer, "activatable", TRUE, NULL);
+
+      DefaultRendererCallbackInfo* user_data = g_new0(DefaultRendererCallbackInfo, 1);
+      user_data->model = model;
+      user_data->model_column_index = column_index;
+
+      g_signal_connect(cell_renderer, "toggled", (GCallback) default_renderer_toggle_cell_edited_callback, user_data);
+      g_signal_connect(cell_renderer, "destroy", (GCallback) default_renderer_destroy_user_data_callback, user_data); /* TODO: Is this the best way to do this? */
+    }
+
+  return view_columns_count;
+}
 
 /**
  * gtk_tree_view_remove_column:
Index: gtk/gtktreeview.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktreeview.h,v
retrieving revision 1.62
diff -u -p -r1.62 gtktreeview.h
--- gtk/gtktreeview.h	23 Nov 2004 20:02:15 -0000	1.62
+++ gtk/gtktreeview.h	11 Apr 2005 02:24:26 -0000
@@ -157,7 +157,15 @@ gboolean               gtk_tree_view_get
 
 /* Column funtions */
 gint                   gtk_tree_view_append_column                 (GtkTreeView               *tree_view,
-								    GtkTreeViewColumn         *column);
+                    GtkTreeViewColumn         *column);
+gint                   gtk_tree_view_append_column_default_renderer (GtkTreeView               *tree_view,
+                    const char*                view_column_title,
+                    GtkTreeModel              *model,
+                    gint                       column_index);
+gint                   gtk_tree_view_append_column_default_renderer_editable (GtkTreeView               *tree_view,
+                    const char*                view_column_title,
+                    GtkTreeModel              *model,
+                    gint                       column_index);
 gint                   gtk_tree_view_remove_column                 (GtkTreeView               *tree_view,
 								    GtkTreeViewColumn         *column);
 gint                   gtk_tree_view_insert_column                 (GtkTreeView               *tree_view,
Index: gtk/gtktreeviewcolumn.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktreeviewcolumn.c,v
retrieving revision 1.160.2.4
diff -u -p -r1.160.2.4 gtktreeviewcolumn.c
--- gtk/gtktreeviewcolumn.c	7 Apr 2005 05:09:33 -0000	1.160.2.4
+++ gtk/gtktreeviewcolumn.c	11 Apr 2005 02:24:27 -0000
@@ -29,6 +29,9 @@
 #include "gtkhbox.h"
 #include "gtkmarshalers.h"
 #include "gtkarrow.h"
+#include "gtkcellrenderertext.h"
+#include "gtkcellrendererpixbuf.h"
+#include "gtkcellrenderertoggle.h"
 #include "gtkintl.h"
 #include "gtkalias.h"
 
@@ -3658,6 +3661,61 @@ gtk_tree_view_column_cell_get_position (
     }
 
   return found_cell;
+}
+
+/**
+ * gtk_tree_view_column_pack_start_default_renderer:
+ * @tree_column: A #GtkTreeViewColumn.
+ * @model: The #GtkTreeModel for which a CellRenderer should be created and added.
+ * @model_index: The index of the column in the @model for which a CellRenderer should be created and added.
+ * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
+ *
+ * Creates an appropriate CellRenderer for the model column's data type, and
+ * packs the @cell into the beginning of the column. If @expand is %FALSE, then
+ * the @cell is allocated no more space than it needs. Any unused space is divided
+ * evenly between cells for which @expand is %TRUE.
+ *
+ * Return value: The instantiated #GtkCellRenderer, or %NULL if no CellRenderer could render the model column's type.
+ **/
+GtkCellRenderer*
+gtk_tree_view_column_pack_start_default_renderer (GtkTreeViewColumn *tree_column,
+         GtkTreeModel      *model,
+         gint               model_index,
+         gboolean           expand)
+{
+  GtkCellRenderer* renderer = 0;
+  GType model_column_type = 0;
+  char* renderable_property_name = 0;  /* TODO: gtkmm has a CellRenderer::_property_renderable() vfunc for this, so we don't need to change a big if/else block when we add a CellRenderer class. */
+
+  /* Discover the column's type: */
+  model_column_type = gtk_tree_model_get_column_type (model, model_index);
+
+  /* Instantiate an appropriate derived CellRenderer: */
+  if(model_column_type == GDK_TYPE_PIXBUF)
+    {
+      renderer = gtk_cell_renderer_pixbuf_new ();
+      renderable_property_name = "pixbuf";
+    }
+  else if(model_column_type == G_TYPE_BOOLEAN)
+    {
+      renderer = gtk_cell_renderer_toggle_new ();
+      renderable_property_name = "active";
+    }
+  else
+    {
+      /* The GtkCellRenderer can convert various data types, including numbers, to decimal text representations, using GValue. */
+      renderer = gtk_cell_renderer_text_new ();
+      renderable_property_name = "text";
+    }
+
+  /* Add the CellRender to the View column: */
+  gtk_tree_view_column_pack_start (tree_column, renderer, expand);
+
+  /* Tell the View column to render the model columns as the appropriate property of this renderer: */
+  gtk_tree_view_column_add_attribute (tree_column,
+    renderer, renderable_property_name, model_index);
+
+  return renderer;
 }
 
 #define __GTK_TREE_VIEW_COLUMN_C__
Index: gtk/gtktreeviewcolumn.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtktreeviewcolumn.h,v
retrieving revision 1.54
diff -u -p -r1.54 gtktreeviewcolumn.h
--- gtk/gtktreeviewcolumn.h	23 Nov 2004 20:02:15 -0000	1.54
+++ gtk/gtktreeviewcolumn.h	11 Apr 2005 02:24:27 -0000
@@ -232,6 +232,12 @@ gboolean                gtk_tree_view_co
 					                          gint                    *width);
 
 
+/* Convenience API */
+GtkCellRenderer*        gtk_tree_view_column_pack_start_default_renderer (GtkTreeViewColumn *tree_column,
+                  GtkTreeModel            *model,
+                  gint                     model_index,
+                  gboolean                 expand);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
