[gtk+/filesystemmodel: 8/28] consolidate tree models for different browse modes



commit 7d6a0f197e1b3d34df1098e5db6da72c95b4a6f3
Author: Benjamin Otte <otte gnome org>
Date:   Thu Jun 18 23:45:50 2009 +0200

    consolidate tree models for different browse modes
    
    All tree models in browse mode now share the first 10 column types
    containing all the necessary information to display the model on screen.
    Therefor it is now easy to just operate on the tree model associated
    with the file tree view and in most cases it isn't necessary anymore to
    special case the browse modes.

 gtk/gtkfilechooserdefault.c | 1093 ++++++++++++++++---------------------------
 gtk/gtkfilesystemmodel.c    |   52 +--
 gtk/gtkfilesystemmodel.h    |    9 +-
 3 files changed, 429 insertions(+), 725 deletions(-)
---
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index f0afa40..9cb37a1 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -192,33 +192,32 @@ typedef enum {
 } ShortcutType;
 
 enum {
-  BROWSE_MODEL_COL_INFO,
-  BROWSE_MODEL_COL_DISPLAY_NAME,
-  BROWSE_MODEL_COL_NUM_COLUMNS
+  /* the first 3 must be these due to settings caching sort column */
+  MODEL_COL_NAME,
+  MODEL_COL_SIZE,
+  MODEL_COL_MTIME,
+  MODEL_COL_FILE,
+  MODEL_COL_NAME_COLLATED,
+  MODEL_COL_IS_FOLDER,
+  MODEL_COL_PIXBUF,
+  MODEL_COL_SIZE_TEXT,
+  MODEL_COL_MTIME_TEXT,
+  MODEL_COL_ELLIPSIZE,
+  MODEL_COL_NUM_COLUMNS
 };
 
 /* Column numbers for the search model.  
  * Keep this in sync with search_setup_model() 
  */
 enum {
-  SEARCH_MODEL_COL_FILE,
-  SEARCH_MODEL_COL_DISPLAY_NAME,
-  SEARCH_MODEL_COL_COLLATION_KEY,
-  SEARCH_MODEL_COL_MTIME,
-  SEARCH_MODEL_COL_SIZE,
-  SEARCH_MODEL_COL_CANCELLABLE,
-  SEARCH_MODEL_COL_PIXBUF,
+  SEARCH_MODEL_COL_CANCELLABLE = MODEL_COL_NUM_COLUMNS,
   SEARCH_MODEL_COL_MIME_TYPE,
-  SEARCH_MODEL_COL_IS_FOLDER,
   SEARCH_MODEL_COL_NUM_COLUMNS
 };
 
 enum {
-  RECENT_MODEL_COL_FILE,
-  RECENT_MODEL_COL_DISPLAY_NAME,
+  RECENT_MODEL_COL_CANCELLABLE = MODEL_COL_NUM_COLUMNS,
   RECENT_MODEL_COL_INFO,
-  RECENT_MODEL_COL_IS_FOLDER,
-  RECENT_MODEL_COL_CANCELLABLE,
   RECENT_MODEL_COL_NUM_COLUMNS
 };
 
@@ -799,7 +798,7 @@ _gtk_file_chooser_default_init (GtkFileChooserDefault *impl)
   impl->pending_select_files = NULL;
   impl->location_mode = LOCATION_MODE_PATH_BAR;
   impl->operation_mode = OPERATION_MODE_BROWSE;
-  impl->sort_column = FILE_LIST_COL_NAME;
+  impl->sort_column = MODEL_COL_NAME;
   impl->sort_order = GTK_SORT_ASCENDING;
   impl->recent_manager = gtk_recent_manager_get_default ();
 
@@ -2638,36 +2637,17 @@ add_bookmark_foreach_cb (GtkTreeModel *model,
 			 gpointer      data)
 {
   GtkFileChooserDefault *impl;
-  GtkFileSystemModel *fs_model;
-  GtkTreeIter child_iter;
   GFile *file;
 
   impl = (GtkFileChooserDefault *) data;
 
-  switch (impl->operation_mode)
-    {
-    case OPERATION_MODE_BROWSE:
-      fs_model = impl->browse_files_model;
-      gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, iter);
-      file = _gtk_file_system_model_get_file (fs_model, &child_iter);
-      break;
-
-    case OPERATION_MODE_SEARCH:
-      search_get_valid_child_iter (impl, &child_iter, iter);
-      gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
-                          SEARCH_MODEL_COL_FILE, &file,
-                          -1);
-      break;
-
-    case OPERATION_MODE_RECENT:
-      recent_get_valid_child_iter (impl, &child_iter, iter);
-      gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
-                          RECENT_MODEL_COL_FILE, &file,
-                          -1);
-      break;
-    }
+  gtk_tree_model_get (model, iter,
+                      MODEL_COL_FILE, &file,
+                      -1);
 
   shortcuts_add_bookmark_from_file (impl, file, -1);
+
+  g_object_unref (file);
 }
 
 /* Adds a bookmark from the currently selected item in the file list */
@@ -2789,14 +2769,14 @@ selection_check_foreach_cb (GtkTreeModel *model,
     case OPERATION_MODE_SEARCH:
       search_get_valid_child_iter (closure->impl, &child_iter, iter);
       gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->search_model), &child_iter,
-                          SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
+                          MODEL_COL_IS_FOLDER, &is_folder,
                           -1);
       break;
 
     case OPERATION_MODE_RECENT:
       recent_get_valid_child_iter (closure->impl, &child_iter, iter);
       gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->recent_model), &child_iter,
-                          RECENT_MODEL_COL_IS_FOLDER, &is_folder,
+                          MODEL_COL_IS_FOLDER, &is_folder,
                           -1);
       break;
     }
@@ -2863,14 +2843,14 @@ get_selected_file_foreach_cb (GtkTreeModel *model,
     case OPERATION_MODE_SEARCH:
       search_get_valid_child_iter (closure->impl, &child_iter, iter);
       gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->search_model), &child_iter,
-                          SEARCH_MODEL_COL_FILE, &closure->file,
+                          MODEL_COL_FILE, &closure->file,
                           -1);
       break;
 
     case OPERATION_MODE_RECENT:
       recent_get_valid_child_iter (closure->impl, &child_iter, iter);
       gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->recent_model), &child_iter,
-                          RECENT_MODEL_COL_FILE, &closure->file,
+                          MODEL_COL_FILE, &closure->file,
                           -1);
       break;
     }
@@ -2926,14 +2906,14 @@ update_tooltip (GtkTreeModel      *model,
         case OPERATION_MODE_SEARCH:
           search_get_valid_child_iter (udata->impl, &child_iter, iter);
           gtk_tree_model_get (GTK_TREE_MODEL (udata->impl->search_model), &child_iter,
-                              SEARCH_MODEL_COL_DISPLAY_NAME, &display_name,
+                              MODEL_COL_NAME, &display_name,
                               -1);
           break;
 
         case OPERATION_MODE_RECENT:
           recent_get_valid_child_iter (udata->impl, &child_iter, iter);
           gtk_tree_model_get (GTK_TREE_MODEL (udata->impl->recent_model), &child_iter,
-                              RECENT_MODEL_COL_DISPLAY_NAME, &display_name,
+                              MODEL_COL_NAME, &display_name,
                               -1);
           break;
         }
@@ -4462,64 +4442,13 @@ typedef struct {
   gint model_column;
 } ColumnMap;
 
-/* Sigh.  Each operation mode has different sort column IDs.  This table
- * translates between them.
- */
-static const ColumnMap column_map[] = {
-  { OPERATION_MODE_BROWSE, FILE_LIST_COL_NAME, FILE_LIST_COL_NAME },
-  { OPERATION_MODE_BROWSE, FILE_LIST_COL_SIZE, FILE_LIST_COL_SIZE },
-  { OPERATION_MODE_BROWSE, FILE_LIST_COL_MTIME, FILE_LIST_COL_MTIME },
-
-  { OPERATION_MODE_SEARCH, FILE_LIST_COL_NAME, SEARCH_MODEL_COL_FILE },
-  { OPERATION_MODE_SEARCH, FILE_LIST_COL_SIZE, SEARCH_MODEL_COL_SIZE },
-  { OPERATION_MODE_SEARCH, FILE_LIST_COL_MTIME, SEARCH_MODEL_COL_MTIME },
-
-  { OPERATION_MODE_RECENT, FILE_LIST_COL_NAME, RECENT_MODEL_COL_FILE },
-  { OPERATION_MODE_RECENT, FILE_LIST_COL_SIZE, 0 },
-  { OPERATION_MODE_RECENT, FILE_LIST_COL_MTIME, RECENT_MODEL_COL_INFO }
-};
-
-static gint
-general_column_to_model_column (GtkFileChooserDefault *impl, gint general_column)
-{
-  int i;
-
-  for (i = 0; i < G_N_ELEMENTS (column_map); i++)
-    if (column_map[i].operation_mode == impl->operation_mode
-	&& column_map[i].general_column == general_column)
-      return column_map[i].model_column;
-
-  g_assert_not_reached ();
-  return 0;
-}
-
-static gint
-model_column_to_general_column (GtkFileChooserDefault *impl, gint model_column)
-{
-  int i;
-
-  for (i = 0; i < G_N_ELEMENTS (column_map); i++)
-    if (column_map[i].operation_mode == impl->operation_mode
-	&& column_map[i].model_column == model_column)
-      return column_map[i].general_column;
-
-  g_assert_not_reached ();
-  return 0;
-}
-
 /* Sets the sort column IDs for the file list based on the operation mode */
 static void
 file_list_set_sort_column_ids (GtkFileChooserDefault *impl)
 {
-  int name_id, mtime_id, size_id;
-
-  name_id  = general_column_to_model_column (impl, FILE_LIST_COL_NAME);
-  mtime_id = general_column_to_model_column (impl, FILE_LIST_COL_MTIME);
-  size_id  = general_column_to_model_column (impl, FILE_LIST_COL_SIZE);
-
-  gtk_tree_view_column_set_sort_column_id (impl->list_name_column,  name_id);
-  gtk_tree_view_column_set_sort_column_id (impl->list_mtime_column, mtime_id);
-  gtk_tree_view_column_set_sort_column_id (impl->list_size_column,  size_id);
+  gtk_tree_view_column_set_sort_column_id (impl->list_name_column, MODEL_COL_NAME);
+  gtk_tree_view_column_set_sort_column_id (impl->list_mtime_column, MODEL_COL_MTIME);
+  gtk_tree_view_column_set_sort_column_id (impl->list_size_column, MODEL_COL_SIZE);
 }
 
 static gboolean
@@ -4559,7 +4488,7 @@ file_list_query_tooltip_cb (GtkWidget  *widget,
 
       search_get_valid_child_iter (impl, &child_iter, &iter);
       gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
-                          SEARCH_MODEL_COL_FILE, &file,
+                          MODEL_COL_FILE, &file,
                           -1);
       break;
     
@@ -4572,7 +4501,7 @@ file_list_query_tooltip_cb (GtkWidget  *widget,
 
       recent_get_valid_child_iter (impl, &child_iter, &iter);
       gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
-                          RECENT_MODEL_COL_FILE, &file,
+                          MODEL_COL_FILE, &file,
                           -1);
       break;
 
@@ -6084,7 +6013,7 @@ set_sort_column (GtkFileChooserDefault *impl)
     }
 
   gtk_tree_sortable_set_sort_column_id (sortable,
-					general_column_to_model_column (impl, impl->sort_column),
+					impl->sort_column,
 					impl->sort_order);
 }
 
@@ -6304,19 +6233,10 @@ install_list_model_filter (GtkFileChooserDefault *impl)
 
 #define COMPARE_DIRECTORIES										       \
   GtkFileChooserDefault *impl = user_data;								       \
-  GFileInfo *info_a = _gtk_file_system_model_get_info (impl->browse_files_model, a);			       \
-  GFileInfo *info_b = _gtk_file_system_model_get_info (impl->browse_files_model, b);			       \
   gboolean dir_a, dir_b;										       \
 													       \
-  if (info_a)												       \
-    dir_a = _gtk_file_info_consider_as_directory (info_a);						       \
-  else													       \
-    return impl->list_sort_ascending ? -1 : 1;								       \
-													       \
-  if (info_b)												       \
-    dir_b = _gtk_file_info_consider_as_directory (info_b);						       \
-  else													       \
-    return impl->list_sort_ascending ? 1 : -1;  							       \
+  gtk_tree_model_get (model, a, MODEL_COL_IS_FOLDER, &dir_a, -1);                                              \
+  gtk_tree_model_get (model, b, MODEL_COL_IS_FOLDER, &dir_b, -1);                                              \
 													       \
   if (dir_a != dir_b)											       \
     return impl->list_sort_ascending ? (dir_a ? -1 : 1) : (dir_a ? 1 : -1) /* Directories *always* go first */
@@ -6334,9 +6254,17 @@ name_sort_func (GtkTreeModel *model,
       gchar *key_a, *key_b;
       gint result;
 
-      key_a = g_utf8_collate_key_for_filename (g_file_info_get_display_name (info_a), -1);
-      key_b = g_utf8_collate_key_for_filename (g_file_info_get_display_name (info_b), -1);
-      result = strcmp (key_a, key_b);
+      gtk_tree_model_get (model, a, MODEL_COL_NAME_COLLATED, &key_a, -1);
+      gtk_tree_model_get (model, b, MODEL_COL_NAME_COLLATED, &key_b, -1);
+
+      if (key_a && key_b)
+        result = strcmp (key_a, key_b);
+      else if (key_a)
+        return 1;
+      else if (key_b)
+        return -1;
+      else
+        return 0;
 
       g_free (key_a);
       g_free (key_b);
@@ -6355,8 +6283,10 @@ size_sort_func (GtkTreeModel *model,
   COMPARE_DIRECTORIES;
   else
     {
-      goffset size_a = g_file_info_get_size (info_a);
-      goffset size_b = g_file_info_get_size (info_b);
+      gint64 size_a, size_b;
+
+      gtk_tree_model_get (model, a, MODEL_COL_SIZE, &size_a, -1);
+      gtk_tree_model_get (model, b, MODEL_COL_SIZE, &size_b, -1);
 
       return size_a > size_b ? -1 : (size_a == size_b ? 0 : 1);
     }
@@ -6372,12 +6302,12 @@ mtime_sort_func (GtkTreeModel *model,
   COMPARE_DIRECTORIES;
   else
     {
-      GTimeVal ta, tb;
+      glong ta, tb;
 
-      g_file_info_get_modification_time (info_a, &ta);
-      g_file_info_get_modification_time (info_b, &tb);
+      gtk_tree_model_get (model, a, MODEL_COL_MTIME, &ta, -1);
+      gtk_tree_model_get (model, b, MODEL_COL_MTIME, &tb, -1);
 
-      return ta.tv_sec > tb.tv_sec ? -1 : (ta.tv_sec == tb.tv_sec ? 0 : 1);
+      return ta > tb ? -1 : (ta == tb ? 0 : 1);
     }
 }
 
@@ -6394,7 +6324,7 @@ list_sort_column_changed_cb (GtkTreeSortable       *sortable,
   if (gtk_tree_sortable_get_sort_column_id (sortable, &sort_column_id, &sort_type))
     {
       impl->list_sort_ascending = (sort_type == GTK_SORT_ASCENDING);
-      impl->sort_column = model_column_to_general_column (impl, sort_column_id);
+      impl->sort_column = sort_column_id;
       impl->sort_order = sort_type;
     }
 }
@@ -6436,9 +6366,9 @@ load_set_model (GtkFileChooserDefault *impl)
 
   profile_msg ("    gtk_tree_model_sort_new_with_model start", NULL);
   impl->sort_model = (GtkTreeModelSort *)gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (impl->browse_files_model));
-  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->sort_model), FILE_LIST_COL_NAME, name_sort_func, impl, NULL);
-  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->sort_model), FILE_LIST_COL_SIZE, size_sort_func, impl, NULL);
-  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->sort_model), FILE_LIST_COL_MTIME, mtime_sort_func, impl, NULL);
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->sort_model), MODEL_COL_NAME, name_sort_func, impl, NULL);
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->sort_model), MODEL_COL_SIZE, size_sort_func, impl, NULL);
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->sort_model), MODEL_COL_MTIME, mtime_sort_func, impl, NULL);
   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (impl->sort_model), NULL, NULL, NULL);
   set_sort_column (impl);
   impl->list_sort_ascending = TRUE;
@@ -6452,7 +6382,7 @@ load_set_model (GtkFileChooserDefault *impl)
 			   GTK_TREE_MODEL (impl->sort_model));
   gtk_tree_view_columns_autosize (GTK_TREE_VIEW (impl->browse_files_tree_view));
   gtk_tree_view_set_search_column (GTK_TREE_VIEW (impl->browse_files_tree_view),
-				   BROWSE_MODEL_COL_DISPLAY_NAME);
+				   MODEL_COL_NAME);
   profile_msg ("    gtk_tree_view_set_model end", NULL);
 
   profile_end ("end", NULL);
@@ -6805,20 +6735,171 @@ stop_loading_and_clear_list_model (GtkFileChooserDefault *impl)
   gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL);
 }
 
+static char *
+my_g_format_time_for_display (glong secs)
+{
+  GDate mtime, now;
+  gint days_diff;
+  struct tm tm_mtime;
+  time_t time_mtime, time_now;
+  const gchar *format;
+  gchar *locale_format = NULL;
+  gchar buf[256];
+  char *date_str = NULL;
+
+  time_mtime = secs;
+
+#ifdef HAVE_LOCALTIME_R
+  localtime_r ((time_t *) &time_mtime, &tm_mtime);
+#else
+  {
+    struct tm *ptm = localtime ((time_t *) &timeval.tv_sec);
+
+    if (!ptm)
+      {
+        g_warning ("ptm != NULL failed");
+        
+        return g_strdup (_("Unknown"));
+      }
+    else
+      memcpy ((void *) &tm_mtime, (void *) ptm, sizeof (struct tm));
+  }
+#endif /* HAVE_LOCALTIME_R */
+
+  g_date_set_time_t (&mtime, time_mtime);
+  time_now = time (NULL);
+  g_date_set_time_t (&now, time_now);
+
+  days_diff = g_date_get_julian (&now) - g_date_get_julian (&mtime);
+
+  /* Translators: %H means "hours" and %M means "minutes" */
+  if (days_diff == 0)
+    format = _("%H:%M");
+  else if (days_diff == 1)
+    format = _("Yesterday at %H:%M");
+  else
+    {
+      if (days_diff > 1 && days_diff < 7)
+        format = "%A"; /* Days from last week */
+      else
+        format = "%x"; /* Any other date */
+    }
+
+#ifdef G_OS_WIN32
+  /* g_locale_from_utf8() returns a string in the system
+   * code-page, which is not always the same as that used by the C
+   * library. For instance when running a GTK+ program with
+   * LANG=ko on an English version of Windows, the system
+   * code-page is 1252, but the code-page used by the C library is
+   * 949. (It's GTK+ itself that sets the C library locale when it
+   * notices the LANG environment variable. See gtkmain.c The
+   * Microsoft C library doesn't look at any locale environment
+   * variables.) We need to pass strftime() a string in the C
+   * library's code-page. See bug #509885.
+   */
+  locale = setlocale (LC_ALL, NULL);
+  if (locale != NULL)
+    dot = strchr (locale, '.');
+  if (dot != NULL)
+    {
+      codepage = g_ascii_strtoll (dot+1, NULL, 10);
+      
+      /* All codepages should fit in 16 bits AFAIK */
+      if (codepage > 0 && codepage < 65536)
+        {
+          sprintf (charset, "CP%u", (guint) codepage);
+          locale_format = g_convert (format, -1, charset, "UTF-8", NULL, NULL, NULL);
+        }
+    }
+#else
+  locale_format = g_locale_from_utf8 (format, -1, NULL, NULL, NULL);
+#endif
+  if (locale_format != NULL &&
+      strftime (buf, sizeof (buf), locale_format, &tm_mtime) != 0)
+    {
+#ifdef G_OS_WIN32
+      /* As above but in opposite direction... */
+      if (codepage > 0 && codepage < 65536)
+        date_str = g_convert (buf, -1, "UTF-8", charset, NULL, NULL, NULL);
+#else
+      date_str = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL);
+#endif
+    }
+
+  if (date_str == NULL)
+    date_str = g_strdup (_("Unknown"));
+
+  g_free (locale_format);
+  return date_str;
+}
+
 static void
 file_system_model_set (GtkFileSystemModel *model,
 		       GFile              *file,
                        GFileInfo          *info,
-                       GValue             *values,
-                       gpointer            unused)
+                       int                 column,
+                       GValue             *value,
+                       gpointer            data)
 {
-  g_value_set_object (&values[0], info);
-
-  if (info == NULL)
-    g_value_set_static_string (&values[1], "");
-  else
-    g_value_set_string (&values[1], g_file_info_get_display_name (info));
+  GtkFileChooserDefault *impl = data;
 
+  switch (column)
+    {
+    case MODEL_COL_FILE:
+      g_value_set_object (value, file);
+      break;
+    case MODEL_COL_NAME:
+      if (info == NULL)
+        g_value_set_string (value, DEFAULT_NEW_FOLDER_NAME);
+      else 
+        g_value_set_string (value, g_file_info_get_display_name (info));
+      break;
+    case MODEL_COL_NAME_COLLATED:
+      if (info == NULL)
+        g_value_take_string (value, g_utf8_collate_key_for_filename (DEFAULT_NEW_FOLDER_NAME, -1));
+      else 
+        g_value_take_string (value, g_utf8_collate_key_for_filename (g_file_info_get_display_name (info), -1));
+      break;
+    case MODEL_COL_IS_FOLDER:
+      g_value_set_boolean (value, info == NULL || _gtk_file_info_consider_as_directory (info));
+      break;
+    case MODEL_COL_PIXBUF:
+      if (info)
+        g_value_take_object (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), impl->icon_size));
+      else
+        g_value_set_object (value, NULL);
+      break;
+    case MODEL_COL_SIZE:
+      g_value_set_int64 (value, g_file_info_get_size (info));
+      break;
+    case MODEL_COL_SIZE_TEXT:
+      if (_gtk_file_info_consider_as_directory (info))
+        g_value_set_string (value, NULL);
+      else
+        g_value_take_string (value, g_format_size_for_display (g_file_info_get_size (info)));
+      break;
+    case MODEL_COL_MTIME:
+    case MODEL_COL_MTIME_TEXT:
+      {
+        GTimeVal tv;
+        if (info == NULL)
+          break;
+        g_file_info_get_modification_time (info, &tv);
+        if (column == MODEL_COL_MTIME)
+          g_value_set_long (value, tv.tv_sec);
+        else if (tv.tv_sec == 0)
+          g_value_set_static_string (value, _("Unknown"));
+        else
+          g_value_take_string (value, my_g_format_time_for_display (tv.tv_sec));
+        break;
+      }
+    case MODEL_COL_ELLIPSIZE:
+      g_value_set_enum (value, info ? PANGO_ELLIPSIZE_END : PANGO_ELLIPSIZE_NONE);
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
 }
 
 /* Gets rid of the old list model and creates a new one for the current folder */
@@ -6841,9 +6922,17 @@ set_list_model (GtkFileChooserDefault *impl,
 							 "standard,time,thumbnail",
                                                          file_system_model_set,
                                                          NULL,
-                                                         BROWSE_MODEL_COL_NUM_COLUMNS,
-                                                         G_TYPE_FILE_INFO,
-                                                         G_TYPE_STRING);
+                                                         MODEL_COL_NUM_COLUMNS,
+                                                         G_TYPE_STRING,
+                                                         G_TYPE_INT64,
+                                                         G_TYPE_LONG,
+                                                         G_TYPE_FILE,
+                                                         G_TYPE_STRING,
+                                                         G_TYPE_BOOLEAN,
+                                                         GDK_TYPE_PIXBUF,
+                                                         G_TYPE_STRING,
+                                                         G_TYPE_STRING,
+                                                         PANGO_TYPE_ELLIPSIZE_MODE);
   load_setup_timer (impl); /* This changes the state to LOAD_PRELOAD */
 
   g_signal_connect (impl->browse_files_model, "finished-loading",
@@ -8799,7 +8888,7 @@ search_selected_foreach_get_file_cb (GtkTreeModel *model,
 
   list = data;
 
-  gtk_tree_model_get (model, iter, SEARCH_MODEL_COL_FILE, &file, -1);
+  gtk_tree_model_get (model, iter, MODEL_COL_FILE, &file, -1);
   *list = g_slist_prepend (*list, g_object_ref (file));
 }
 
@@ -8853,10 +8942,9 @@ search_hit_get_info_cb (GCancellable *cancellable,
   GCancellable *model_cancellable;
   gboolean is_folder = FALSE;
   GTimeVal mtime;
-  guint64 modification_time = 0;
   goffset size;
-  char *mime_type;
-  char *display_name;
+  char *mime_type, *size_text, *mtime_text;
+  char *display_name, *collated_name;
   struct SearchHitInsertRequest *request = data;
 
   if (!request->impl->search_model)
@@ -8892,25 +8980,38 @@ search_hit_get_info_cb (GCancellable *cancellable,
     }
 
   display_name = g_strdup (g_file_info_get_display_name (info));
+  if (display_name)
+    collated_name = g_utf8_collate_key_for_filename (display_name, -1);
+  else
+    collated_name = NULL;
   mime_type = g_content_type_get_mime_type (g_file_info_get_content_type (info));
+  is_folder = _gtk_file_info_consider_as_directory (info);
   g_file_info_get_modification_time (info, &mtime);
-  modification_time = (guint64) mtime.tv_sec;
   size = g_file_info_get_size (info);
-  is_folder = _gtk_file_info_consider_as_directory (info);
+  size_text = is_folder ? NULL : g_format_size_for_display (size);
+  mtime_text = mtime.tv_sec ? my_g_format_time_for_display (mtime.tv_sec) : g_strdup (_("Unknown"));
   pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (request->impl),
 				       request->impl->icon_size);
 
   gtk_list_store_set (request->impl->search_model, &iter,
-                      SEARCH_MODEL_COL_PIXBUF, pixbuf,
-                      SEARCH_MODEL_COL_DISPLAY_NAME, display_name,
+                      MODEL_COL_NAME, display_name,
+                      MODEL_COL_NAME_COLLATED, collated_name,
+                      MODEL_COL_IS_FOLDER, is_folder,
+                      MODEL_COL_PIXBUF, pixbuf,
+                      MODEL_COL_SIZE, size,
+                      MODEL_COL_SIZE_TEXT, size_text,
+                      MODEL_COL_MTIME, mtime.tv_sec,
+                      MODEL_COL_MTIME_TEXT, mtime_text,
                       SEARCH_MODEL_COL_MIME_TYPE, mime_type,
-                      SEARCH_MODEL_COL_IS_FOLDER, is_folder,
-                      SEARCH_MODEL_COL_MTIME, modification_time,
-                      SEARCH_MODEL_COL_SIZE, size,
                       -1);
 
   if (pixbuf)
     g_object_unref (pixbuf);
+  g_free (display_name);
+  g_free (collated_name);
+  g_free (mime_type);
+  g_free (size_text);
+  g_free (mtime_text);
 
 out:
   g_object_unref (request->impl);
@@ -8927,8 +9028,6 @@ search_add_hit (GtkFileChooserDefault *impl,
 		gchar                 *uri)
 {
   GFile *file;
-  char *tmp;
-  char *collation_key;
   GtkTreeIter iter;
   GtkTreePath *p;
   GCancellable *cancellable;
@@ -8944,10 +9043,6 @@ search_add_hit (GtkFileChooserDefault *impl,
       return;
     }
 
-  tmp = g_file_get_parse_name (file);
-  collation_key = g_utf8_collate_key_for_filename (tmp, -1);
-  g_free (tmp);
-
   request = g_new0 (struct SearchHitInsertRequest, 1);
   request->impl = g_object_ref (impl);
   request->file = g_object_ref (file);
@@ -8969,10 +9064,13 @@ search_add_hit (GtkFileChooserDefault *impl,
 					   request);
 
   gtk_list_store_set (impl->search_model, &iter,
-                      SEARCH_MODEL_COL_FILE, file,
-                      SEARCH_MODEL_COL_COLLATION_KEY, collation_key,
+                      MODEL_COL_FILE, file, 
+                      MODEL_COL_ELLIPSIZE, PANGO_ELLIPSIZE_END,
                       SEARCH_MODEL_COL_CANCELLABLE, cancellable,
                       -1);
+
+  g_object_unref (file);
+  g_object_unref (cancellable);
 }
 
 /* Callback used from GtkSearchEngine when we get new hits */
@@ -9043,29 +9141,17 @@ static void
 search_clear_model_row (GtkTreeModel *model,
                         GtkTreeIter  *iter)
 {
-  GFile *file;
-  gchar *display_name;
-  gchar *collation_key;
   GCancellable *cancellable;
-  gchar *mime_type;
 
   gtk_tree_model_get (model, iter,
-                      SEARCH_MODEL_COL_FILE, &file,
-                      SEARCH_MODEL_COL_DISPLAY_NAME, &display_name,
-                      SEARCH_MODEL_COL_COLLATION_KEY, &collation_key,
                       SEARCH_MODEL_COL_CANCELLABLE, &cancellable,
-                      SEARCH_MODEL_COL_MIME_TYPE, &mime_type,
                       -1);
 
-  if (file)
-    g_object_unref (file);
-
-  g_free (display_name);
-  g_free (collation_key);
-  g_free (mime_type);
-           
   if (cancellable)
-    g_cancellable_cancel (cancellable);
+    {
+      g_cancellable_cancel (cancellable);
+      g_object_unref (cancellable);
+    }
 }
 
 /* Frees the data in the search_model */
@@ -9151,113 +9237,6 @@ search_switch_to_browse_mode (GtkFileChooserDefault *impl)
   file_list_set_sort_column_ids (impl);
 }
 
-/* Sort callback from the path column */
-static gint
-search_column_path_sort_func (GtkTreeModel *model,
-			      GtkTreeIter  *a,
-			      GtkTreeIter  *b,
-			      gpointer      user_data)
-{
-  GtkFileChooserDefault *impl = user_data;
-  GtkTreeIter child_a, child_b;
-  const char *collation_key_a, *collation_key_b;
-  gboolean is_folder_a, is_folder_b;
-
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a);
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b);
-
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_a,
-                      SEARCH_MODEL_COL_IS_FOLDER, &is_folder_a,
-                      SEARCH_MODEL_COL_COLLATION_KEY, &collation_key_a,
-                      -1);
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_b,
-                      SEARCH_MODEL_COL_IS_FOLDER, &is_folder_b,
-                      SEARCH_MODEL_COL_COLLATION_KEY, &collation_key_b,
-                      -1);
-
-  if (!collation_key_a)
-    return 1;
-
-  if (!collation_key_b)
-    return -1;
-
-  /* always show folders first */
-  if (is_folder_a != is_folder_b)
-    return is_folder_a ? 1 : -1;
-
-  return strcmp (collation_key_a, collation_key_b);
-}
-
-/* Sort callback from the size column */
-static gint
-search_column_size_sort_func (GtkTreeModel *model,
-                              GtkTreeIter  *a,
-                              GtkTreeIter  *b,
-                              gpointer      user_data)
-{
-  GtkFileChooserDefault *impl = user_data;
-  GtkTreeIter child_a, child_b;
-  gboolean is_folder_a, is_folder_b;
-  goffset size_a, size_b;
-
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a);
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b);
-
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_a,
-                      SEARCH_MODEL_COL_IS_FOLDER, &is_folder_a,
-                      SEARCH_MODEL_COL_SIZE, &size_a,
-                      -1);
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_b,
-                      SEARCH_MODEL_COL_IS_FOLDER, &is_folder_b,
-                      SEARCH_MODEL_COL_SIZE, &size_b,
-                      -1);
-  
-  if (is_folder_a != is_folder_b)
-    return is_folder_a ? 1 : -1;
-
-  if (size_a < size_b)
-    return -1;
-  else if (size_a > size_b)
-    return 1;
-  else
-    return 0;
-}
-
-/* Sort callback from the modification time column */
-static gint
-search_column_mtime_sort_func (GtkTreeModel *model,
-			       GtkTreeIter  *a,
-			       GtkTreeIter  *b,
-			       gpointer      user_data)
-{
-  GtkFileChooserDefault *impl = user_data;
-  GtkTreeIter child_a, child_b;
-  gboolean is_folder_a, is_folder_b;
-  guint64 mtime_a, mtime_b;
-
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a);
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b);
-
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_a,
-                      SEARCH_MODEL_COL_IS_FOLDER, &is_folder_a,
-                      SEARCH_MODEL_COL_MTIME, &mtime_a,
-                      -1);
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_b,
-                      SEARCH_MODEL_COL_IS_FOLDER, &is_folder_b,
-                      SEARCH_MODEL_COL_MTIME, &mtime_b,
-                      -1);
-  
-  if (is_folder_a != is_folder_b)
-    return is_folder_a ? 1 : -1;
-
-  if (mtime_a < mtime_b)
-    return -1;
-  else if (mtime_a > mtime_b)
-    return 1;
-  else
-    return 0;
-}
-
 static gboolean
 search_get_is_filtered (GtkFileChooserDefault *impl,
 			GFile                 *file,
@@ -9315,25 +9294,29 @@ search_model_visible_func (GtkTreeModel *model,
   GtkFileChooserDefault *impl = user_data;
   GFile *file;
   gchar *display_name, *mime_type;
-  gboolean is_folder;
+  gboolean is_folder, result;
 
   if (!impl->current_filter)
     return TRUE;
 
   gtk_tree_model_get (model, iter,
-                      SEARCH_MODEL_COL_FILE, &file,
-                      SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
-                      SEARCH_MODEL_COL_DISPLAY_NAME, &display_name,
+                      MODEL_COL_FILE, &file,
+                      MODEL_COL_IS_FOLDER, &is_folder,
+                      MODEL_COL_NAME, &display_name,
                       SEARCH_MODEL_COL_MIME_TYPE, &mime_type,
                       -1);
 
   if (!display_name)
-    return TRUE;
+    result = TRUE;
+  else if (is_folder)
+    result = TRUE;
+  else
+    result = !search_get_is_filtered (impl, file, display_name, mime_type);
 
-  if (is_folder)
-    return TRUE;
+  g_free (display_name);
+  g_free (mime_type);
 
-  return !search_get_is_filtered (impl, file, display_name, mime_type);
+  return result;
 }
 
 /* Creates the search_model and puts it in the tree view */
@@ -9344,34 +9327,20 @@ search_setup_model (GtkFileChooserDefault *impl)
   g_assert (impl->search_model_filter == NULL);
   g_assert (impl->search_model_sort == NULL);
 
-  /* We store these columns in the search model:
-   *
-   * SEARCH_MODEL_COL_FILE - a GFile for the hit's URI, stored
-   *   as a pointer not as a G_TYPE_FILE
-   * SEARCH_MODEL_COL_DISPLAY_NAME - a string with the display name, stored
-   *   as a pointer not as a G_TYPE_STRING
-   * SEARCH_MODEL_COL_COLLATION_KEY - collation key for the filename, stored
-   *   as a pointer not as a G_TYPE_STRING
-   * SEARCH_MODEL_COL_MTIME - G_TYPE_UINT64 for the modification time
-   * SEARCH_MODEL_COL_SIZE - G_TYPE_INT64 for the size
-   * SEARCH_MODEL_COL_CANCELLABLE - cancellable used when getting the hit's info
-   * SEARCH_MODEL_COL_PIXBUF - GdkPixbuf for the hit's icon
-   * SEARCH_MODEL_COL_MIME_TYPE - a string with the hit's MIME type
-   * SEARCH_MODEL_COL_IS_FOLDER - a boolean flag for folders
-   *
-   * Keep this in sync with the enumeration defined near the beginning
-   * of this file.
-   */
   impl->search_model = gtk_list_store_new (SEARCH_MODEL_COL_NUM_COLUMNS,
-					   G_TYPE_POINTER, /* file */
-					   G_TYPE_POINTER, /* display-name */
-					   G_TYPE_POINTER, /* collation-key */
-					   G_TYPE_UINT64, /* mtime */
-                                           G_TYPE_INT64, /* size */
-                                           G_TYPE_POINTER, /* cancellable */
-                                           GDK_TYPE_PIXBUF, /* pixbuf */
-                                           G_TYPE_POINTER, /* mime-type */
-                                           G_TYPE_BOOLEAN /*is-folder */);
+                                           G_TYPE_STRING, /* MODEL_COL_NAME */
+                                           G_TYPE_INT64, /* MODEL_COL_SIZE */
+                                           G_TYPE_LONG, /* MODEL_COL_MTIME */
+                                           G_TYPE_FILE, /* MODEL_COL_FILE */
+                                           G_TYPE_STRING, /* MODEL_COL_NAME_COLLATED */
+                                           G_TYPE_BOOLEAN, /* MODEL_COL_IS_FOLDER */
+                                           GDK_TYPE_PIXBUF, /* MODEL_COL_PIXBUF */
+                                           G_TYPE_STRING, /* MODEL_COL_SIZE_TEXT */
+                                           G_TYPE_STRING, /* MODEL_COL_MTIME_TEXT */
+                                           PANGO_TYPE_ELLIPSIZE_MODE, /* MODEL_COL_ELLIPSIZE */
+                                           G_TYPE_CANCELLABLE, /* SEARCH_MODEL_COL_CANCELLABLE */
+                                           G_TYPE_STRING /* SEARCH_MODEL_COL_MIME_TYPE */
+                                          );
   
   impl->search_model_filter =
     GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->search_model), NULL));
@@ -9382,16 +9351,16 @@ search_setup_model (GtkFileChooserDefault *impl)
   impl->search_model_sort =
     GTK_TREE_MODEL_SORT (search_model_sort_new (impl, GTK_TREE_MODEL (impl->search_model_filter)));
   gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->search_model_sort),
-				   SEARCH_MODEL_COL_FILE,
-				   search_column_path_sort_func,
+				   MODEL_COL_NAME,
+				   name_sort_func,
 				   impl, NULL);
   gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->search_model_sort),
-				   SEARCH_MODEL_COL_MTIME,
-				   search_column_mtime_sort_func,
+				   MODEL_COL_MTIME,
+				   mtime_sort_func,
 				   impl, NULL);
   gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->search_model_sort),
-				   SEARCH_MODEL_COL_SIZE,
-				   search_column_size_sort_func,
+				   MODEL_COL_SIZE,
+				   size_sort_func,
 				   impl, NULL);
   set_sort_column (impl);
 
@@ -9646,8 +9615,8 @@ recent_clear_model (GtkFileChooserDefault *impl,
           gchar *display_name;
 
           gtk_tree_model_get (model, &iter,
-                              RECENT_MODEL_COL_DISPLAY_NAME, &display_name,
-                              RECENT_MODEL_COL_FILE, &file,
+                              MODEL_COL_NAME, &display_name,
+                              MODEL_COL_FILE, &file,
                               RECENT_MODEL_COL_CANCELLABLE, &cancellable,
                               RECENT_MODEL_COL_INFO, &recent_info,
                               -1);
@@ -9718,83 +9687,6 @@ recent_switch_to_browse_mode (GtkFileChooserDefault *impl)
   file_list_set_sort_column_ids (impl);
 }
 
-/* Sort callback from the modification time column */
-static gint
-recent_column_mtime_sort_func (GtkTreeModel *model,
-			       GtkTreeIter  *a,
-			       GtkTreeIter  *b,
-			       gpointer      user_data)
-{
-  GtkFileChooserDefault *impl = user_data;
-  GtkTreeIter child_a, child_b;
-  GtkRecentInfo *info_a, *info_b;
-  gboolean is_folder_a, is_folder_b;
-
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a);
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b);
-
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_a,
-                      RECENT_MODEL_COL_IS_FOLDER, &is_folder_a,
-                      RECENT_MODEL_COL_INFO, &info_a,
-                      -1);
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_b,
-                      RECENT_MODEL_COL_IS_FOLDER, &is_folder_b,
-                      RECENT_MODEL_COL_INFO, &info_b,
-                      -1);
-  
-  if (!info_a)
-    return 1;
-
-  if (!info_b)
-    return -1;
-
-  /* folders always go first */
-  if (is_folder_a != is_folder_b)
-    return is_folder_a ? 1 : -1;
-
-  if (gtk_recent_info_get_modified (info_a) < gtk_recent_info_get_modified (info_b))
-    return -1;
-  else if (gtk_recent_info_get_modified (info_a) > gtk_recent_info_get_modified (info_b))
-    return 1;
-  else
-    return 0;
-}
-
-static gint
-recent_column_path_sort_func (GtkTreeModel *model,
-                              GtkTreeIter  *a,
-                              GtkTreeIter  *b,
-                              gpointer      user_data)
-{
-  GtkFileChooserDefault *impl = user_data;
-  GtkTreeIter child_a, child_b;
-  gboolean is_folder_a, is_folder_b;
-  gchar *name_a, *name_b;
-
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a);
-  gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b);
-
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_a,
-                      RECENT_MODEL_COL_IS_FOLDER, &is_folder_a,
-                      RECENT_MODEL_COL_DISPLAY_NAME, &name_a,
-                      -1);
-  gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_b,
-                      RECENT_MODEL_COL_IS_FOLDER, &is_folder_b,
-                      RECENT_MODEL_COL_DISPLAY_NAME, &name_b,
-                      -1);
-
-  if (!name_a)
-    return 1;
-
-  if (!name_b)
-    return -1;
-
-  if (is_folder_a != is_folder_b)
-    return is_folder_a ? 1 : -1;
-
-  return strcmp (name_a, name_b);
-}
-
 static gboolean
 recent_get_is_filtered (GtkFileChooserDefault *impl,
 			GFile                 *file,
@@ -9857,8 +9749,8 @@ recent_model_visible_func (GtkTreeModel *model,
 
   gtk_tree_model_get (model, iter,
                       RECENT_MODEL_COL_INFO, &recent_info,
-                      RECENT_MODEL_COL_FILE, &file,
-                      RECENT_MODEL_COL_IS_FOLDER, &is_folder,
+                      MODEL_COL_FILE, &file,
+                      MODEL_COL_IS_FOLDER, &is_folder,
                       -1);
 
   if (!recent_info)
@@ -9877,27 +9769,20 @@ recent_setup_model (GtkFileChooserDefault *impl)
   g_assert (impl->recent_model_filter == NULL);
   g_assert (impl->recent_model_sort == NULL);
 
-  /* We store these columns in the search model:
-   *
-   * RECENT_MODEL_COL_FILE - a pointer to GFile for the hit's URI,
-   *   stored as a pointer and not as a G_TYPE_FILE;
-   * RECENT_MODEL_COL_DISPLAY_NAME - a string with the display name,
-   *   stored as a pointer and not as a G_TYPE_STRING;
-   * RECENT_MODEL_COL_INFO - GtkRecentInfo, stored as a pointer and not
-   *   as a GTK_TYPE_RECENT_INFO;
-   * RECENT_MODEL_COL_IS_FOLDER - boolean flag;
-   * RECENT_MODEL_COL_CANCELLABLE - GCancellable, stored as a pointer
-   *   and not as a G_TYPE_CANCELLABLE;
-   *
-   * Keep this in sync with the enumeration defined near the beginning of
-   * this file.
-   */
   impl->recent_model = gtk_list_store_new (RECENT_MODEL_COL_NUM_COLUMNS,
-					   G_TYPE_POINTER,
-					   G_TYPE_POINTER,
-					   G_TYPE_POINTER,
-                                           G_TYPE_BOOLEAN,
-                                           G_TYPE_POINTER);
+                                           G_TYPE_STRING, /* MODEL_COL_NAME */
+                                           G_TYPE_INT64, /* MODEL_COL_SIZE */
+                                           G_TYPE_LONG, /* MODEL_COL_MTIME */
+                                           G_TYPE_FILE, /* MODEL_COL_FILE */
+                                           G_TYPE_STRING, /* MODEL_COL_NAME_COLLATED */
+                                           G_TYPE_BOOLEAN, /* MODEL_COL_IS_FOLDER */
+                                           GDK_TYPE_PIXBUF, /* MODEL_COL_PIXBUF */
+                                           G_TYPE_STRING, /* MODEL_COL_SIZE_TEXT */
+                                           G_TYPE_STRING, /* MODEL_COL_MTIME_TEXT */
+                                           PANGO_TYPE_ELLIPSIZE_MODE, /* MODEL_COL_ELLIPSIZE */
+                                           G_TYPE_CANCELLABLE, /* RECENT_MODEL_COL_CANCELLABLE */
+                                           G_TYPE_POINTER /* RECENT_MODEL_COL_INFO */
+                                          );
 
   impl->recent_model_filter =
     GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->recent_model), NULL));
@@ -9917,12 +9802,16 @@ recent_setup_model (GtkFileChooserDefault *impl)
   impl->recent_model_sort =
     GTK_TREE_MODEL_SORT (recent_model_sort_new (impl, GTK_TREE_MODEL (impl->recent_model_filter)));
   gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort),
-				   RECENT_MODEL_COL_FILE,
-				   recent_column_path_sort_func,
+				   MODEL_COL_NAME,
+				   name_sort_func,
 				   impl, NULL);
   gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort),
-                                   RECENT_MODEL_COL_INFO,
-                                   recent_column_mtime_sort_func,
+                                   MODEL_COL_SIZE,
+                                   size_sort_func,
+                                   impl, NULL);
+  gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort),
+                                   MODEL_COL_MTIME,
+                                   mtime_sort_func,
                                    impl, NULL);
   set_sort_column (impl);
 }
@@ -9977,6 +9866,8 @@ recent_item_get_info_cb (GCancellable *cancellable,
   GCancellable *model_cancellable;
   gboolean is_folder = FALSE;
   struct RecentItemInsertRequest *request = data;
+  char *size_text;
+  gint64 size;
 
   if (!request->impl->recent_model)
     goto out;
@@ -9992,6 +9883,7 @@ recent_item_get_info_cb (GCancellable *cancellable,
   gtk_tree_model_get (GTK_TREE_MODEL (request->impl->recent_model), &iter,
                       RECENT_MODEL_COL_CANCELLABLE, &model_cancellable,
                       -1);
+  g_object_unref (model_cancellable);
   if (cancellable != model_cancellable)
     goto out;
 
@@ -10009,11 +9901,17 @@ recent_item_get_info_cb (GCancellable *cancellable,
     }
 
   is_folder = _gtk_file_info_consider_as_directory (info);
+  size = g_file_info_get_size (info);
+  size_text = is_folder ? g_format_size_for_display (size) : g_strdup ("");
 
   gtk_list_store_set (request->impl->recent_model, &iter,
-                      RECENT_MODEL_COL_IS_FOLDER, is_folder,
+                      MODEL_COL_IS_FOLDER, is_folder,
+                      MODEL_COL_SIZE, size,
+                      MODEL_COL_SIZE_TEXT, size_text,
                       -1);
 
+  g_free (size_text);
+
 out:
   g_object_unref (request->impl);
   g_object_unref (request->file);
@@ -10057,7 +9955,8 @@ recent_idle_load (gpointer data)
   GtkTreeIter iter;
   GtkTreePath *p;
   GtkRecentInfo *info;
-  const gchar *uri, *display_name;
+  const gchar *uri, *display_name, *mtime_text, *collated_name;
+  glong mtime;
   GFile *file;
   GCancellable *cancellable;
   struct RecentItemInsertRequest *request;
@@ -10127,15 +10026,24 @@ recent_idle_load (gpointer data)
   gtk_tree_path_free (p);
 
   cancellable = _gtk_file_system_get_info (impl->file_system, file,
-					   "standard::type",
+					   "standard::type,standard::size",
 					   recent_item_get_info_cb,
 					   request);
 
+  collated_name = g_utf8_collate_key_for_filename (gtk_recent_info_get_display_name (info), -1);
+  mtime = gtk_recent_info_get_modified (info);
+  mtime_text = mtime ? my_g_format_time_for_display (mtime) : g_strdup (_("Unknown"));
+
   gtk_list_store_set (impl->recent_model, &iter,
-                      RECENT_MODEL_COL_FILE, file,
-                      RECENT_MODEL_COL_DISPLAY_NAME, g_strdup (display_name),
-                      RECENT_MODEL_COL_INFO, gtk_recent_info_ref (info),
+                      MODEL_COL_FILE, file,
+                      MODEL_COL_NAME, gtk_recent_info_get_display_name (info),
+                      MODEL_COL_NAME_COLLATED, collated_name,
+                      MODEL_COL_PIXBUF, gtk_recent_info_get_icon (info, impl->icon_size),
+                      MODEL_COL_MTIME, mtime,
+                      MODEL_COL_MTIME_TEXT, mtime_text,
+                      MODEL_COL_ELLIPSIZE, PANGO_ELLIPSIZE_END,
                       RECENT_MODEL_COL_CANCELLABLE, cancellable,
+                      RECENT_MODEL_COL_INFO, gtk_recent_info_ref (info),
                       -1);
 
   load_data->n_loaded_items += 1;
@@ -10190,8 +10098,8 @@ recent_selected_foreach_get_file_cb (GtkTreeModel *model,
 
   list = data;
 
-  gtk_tree_model_get (model, iter, RECENT_MODEL_COL_FILE, &file, -1);
-  *list = g_slist_prepend (*list, g_object_ref (file));
+  gtk_tree_model_get (model, iter, MODEL_COL_FILE, &file, -1);
+  *list = g_slist_prepend (*list, file);
 }
 
 /* Constructs a list of the selected paths in recent files mode */
@@ -10366,61 +10274,27 @@ check_preview_change (GtkFileChooserDefault *impl)
 {
   GtkTreePath *cursor_path;
   GFile *new_file;
-  const char *new_display_name;
+  char *new_display_name;
+  GtkTreeModel *model;
 
   gtk_tree_view_get_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), &cursor_path, NULL);
-  new_file = NULL;
-  new_display_name = NULL;
+  model = gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view));
   if (cursor_path)
     {
-      GtkTreeIter child_iter;
-
-      if (impl->operation_mode == OPERATION_MODE_BROWSE)
-	{
-	  if (impl->sort_model)
-	    {
-	      GtkTreeIter iter;
-	      GFileInfo *new_info;
-
-	      gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, cursor_path);
-	      gtk_tree_path_free (cursor_path);
-
-	      gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter);
-
-	      new_file = _gtk_file_system_model_get_file (impl->browse_files_model, &child_iter);
-	      new_info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
-              if (new_info)
-	        new_display_name = g_file_info_get_display_name (new_info);
-	    }
-	}
-      else if (impl->operation_mode == OPERATION_MODE_SEARCH)
-	{
-	  GtkTreeIter iter;
-
-	  gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort),
-                                   &iter, cursor_path);
-	  gtk_tree_path_free (cursor_path);
-
-	  search_get_valid_child_iter (impl, &child_iter, &iter);
-          gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
-			      SEARCH_MODEL_COL_FILE, &new_file,
-			      SEARCH_MODEL_COL_DISPLAY_NAME, &new_display_name,
-			      -1);
-	}
-      else if (impl->operation_mode == OPERATION_MODE_RECENT)
-        {
-          GtkTreeIter iter;
-
-          gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort),
-                                   &iter, cursor_path);
-          gtk_tree_path_free (cursor_path);
+      GtkTreeIter iter;
 
-          recent_get_valid_child_iter (impl, &child_iter, &iter);
-          gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
-                              RECENT_MODEL_COL_FILE, &new_file,
-                              RECENT_MODEL_COL_DISPLAY_NAME, &new_display_name,
-                              -1);
-        }
+      gtk_tree_model_get_iter (model, &iter, cursor_path);
+      gtk_tree_model_get (model, &iter,
+                          MODEL_COL_FILE, &new_file,
+                          MODEL_COL_NAME, &new_display_name,
+                          -1);
+      
+      gtk_tree_path_free (cursor_path);
+    }
+  else
+    {
+      new_file = NULL;
+      new_display_name = NULL;
     }
 
   if (new_file != impl->preview_file &&
@@ -10435,13 +10309,14 @@ check_preview_change (GtkFileChooserDefault *impl)
 
       if (new_file)
 	{
-	  impl->preview_file = g_object_ref (new_file);
-	  impl->preview_display_name = g_strdup (new_display_name);
+	  impl->preview_file = new_file;
+	  impl->preview_display_name = new_display_name;
 	}
       else
 	{
 	  impl->preview_file = NULL;
 	  impl->preview_display_name = NULL;
+          g_free (new_display_name);
 	}
 
       if (impl->use_preview_label && impl->preview_label)
@@ -10768,7 +10643,7 @@ list_select_func  (GtkTreeSelection  *selection,
 
             search_get_valid_child_iter (impl, &child_iter, &iter);
             gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
-                                SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
+                                MODEL_COL_IS_FOLDER, &is_folder,
                                 -1);
             if (!is_folder)
               return FALSE;
@@ -10784,7 +10659,7 @@ list_select_func  (GtkTreeSelection  *selection,
 
             recent_get_valid_child_iter (impl, &child_iter, &iter);
             gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
-                                RECENT_MODEL_COL_IS_FOLDER, &is_folder,
+                                MODEL_COL_IS_FOLDER, &is_folder,
                                 -1);
             if (!is_folder)
               return FALSE;
@@ -10847,103 +10722,33 @@ list_row_activated (GtkTreeView           *tree_view,
 		    GtkTreeViewColumn     *column,
 		    GtkFileChooserDefault *impl)
 {
+  GFile *file;
   GtkTreeIter iter;
-  GtkTreeIter child_iter;
-
-  switch (impl->operation_mode)
-    {
-    case OPERATION_MODE_SEARCH:
-      {
-	GFile *file;
-        gboolean is_folder;
-
-        if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort), &iter, path))
-          return;
-
-        search_get_valid_child_iter (impl, &child_iter, &iter);
-        gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
-                            SEARCH_MODEL_COL_FILE, &file,
-                            SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
-                            -1);
-        
-        if (is_folder)
-          {
-            change_folder_and_display_error (impl, file, FALSE);
-            return;
-          }
-
-        g_signal_emit_by_name (impl, "file-activated");
-      }
-      break;
-
-    case OPERATION_MODE_RECENT:
-      {
-	GFile *file;
-        gboolean is_folder;
+  GtkTreeModel *model;
+  gboolean is_folder;
 
-        if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, path))
-          return;
-        
-        recent_get_valid_child_iter (impl, &child_iter, &iter);
-        gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
-                            RECENT_MODEL_COL_FILE, &file,
-                            RECENT_MODEL_COL_IS_FOLDER, &is_folder,
-                            -1);
+  model = gtk_tree_view_get_model (tree_view);
 
-        if (is_folder)
-          {
-            change_folder_and_display_error (impl, file, FALSE);
-            return;
-          }
-        
-        g_signal_emit_by_name (impl, "file-activated");
-      }
-      break;
-    
-    case OPERATION_MODE_BROWSE:
-      {
-        GFileInfo *info;
+  if (!gtk_tree_model_get_iter (model, &iter, path))
+    return;
 
-        if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path))
-          return;
+  gtk_tree_model_get (model, &iter,
+                      MODEL_COL_FILE, &file,
+                      MODEL_COL_IS_FOLDER, &is_folder,
+                      -1);
         
-        gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
-                                                        &child_iter, &iter);
-        info = _gtk_file_system_model_get_info (impl->browse_files_model,
-                                                &child_iter);
-
-        if (_gtk_file_info_consider_as_directory (info))
-          {
-	    GFile *file, *target_file;
-	    const gchar *target_uri;
+  if (is_folder && file)
+    {
+      change_folder_and_display_error (impl, file, FALSE);
+      return;
+    }
 
-            file = _gtk_file_system_model_get_file (impl->browse_files_model, &child_iter);
-            if (g_file_info_get_file_type (info) == G_FILE_TYPE_MOUNTABLE ||
-                g_file_info_get_file_type (info) == G_FILE_TYPE_SHORTCUT) 
-              {
-                target_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI);
-                if (target_uri)
-                  {
-                    target_file = g_file_new_for_uri (target_uri);
-                    if (target_file)
-                      {
-                        g_object_unref (file);
-                        file = target_file;
-                      }
-                  }  
-              }
-            
-            
-            change_folder_and_display_error (impl, file, FALSE);
-            return;
-          }
+  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+      impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+    g_signal_emit_by_name (impl, "file-activated");
 
-        if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
-            impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
-          g_signal_emit_by_name (impl, "file-activated");
-      }
-      break;
-    }
+  if (file)
+    g_object_unref (file);
 }
 
 static void
@@ -11003,8 +10808,8 @@ list_icon_data_func (GtkTreeViewColumn *tree_column,
 
         search_get_valid_child_iter (impl, &child_iter, iter);
         gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
-                            SEARCH_MODEL_COL_PIXBUF, &pixbuf,
-                            SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
+                            MODEL_COL_PIXBUF, &pixbuf,
+                            MODEL_COL_IS_FOLDER, &is_folder,
                             -1);
         
         if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
@@ -11022,7 +10827,7 @@ list_icon_data_func (GtkTreeViewColumn *tree_column,
         recent_get_valid_child_iter (impl, &child_iter, iter);
         gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
                             RECENT_MODEL_COL_INFO, &info,
-                            RECENT_MODEL_COL_IS_FOLDER, &is_folder,
+                            MODEL_COL_IS_FOLDER, &is_folder,
                             -1);
         
         pixbuf = gtk_recent_info_get_icon (info, impl->icon_size);
@@ -11096,8 +10901,8 @@ list_name_data_func (GtkTreeViewColumn *tree_column,
 
       search_get_valid_child_iter (impl, &child_iter, iter);
       gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
-                          SEARCH_MODEL_COL_DISPLAY_NAME, &display_name,
-                          SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
+                          MODEL_COL_NAME, &display_name,
+                          MODEL_COL_IS_FOLDER, &is_folder,
 			  -1);
 
       if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
@@ -11125,7 +10930,7 @@ list_name_data_func (GtkTreeViewColumn *tree_column,
       recent_get_valid_child_iter (impl, &child_iter, iter);
       gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
                           RECENT_MODEL_COL_INFO, &recent_info,
-                          RECENT_MODEL_COL_IS_FOLDER, &is_folder,
+                          MODEL_COL_IS_FOLDER, &is_folder,
                           -1);
       
       display_name = gtk_recent_info_get_short_name (recent_info);
@@ -11198,8 +11003,8 @@ list_size_data_func (GtkTreeViewColumn *tree_column,
 
       search_get_valid_child_iter (impl, &child_iter, iter);
       gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
-                          SEARCH_MODEL_COL_SIZE, &size,
-                          SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
+                          MODEL_COL_SIZE, &size,
+                          MODEL_COL_IS_FOLDER, &is_folder,
 			  -1);
 
       if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
@@ -11250,7 +11055,7 @@ list_size_data_func (GtkTreeViewColumn *tree_column,
 /* Tree column data callback for the file list; fetches the mtime of a file */
 static void
 list_mtime_data_func (GtkTreeViewColumn *tree_column,
-		      GtkCellRenderer   *cell,
+                  GtkCellRenderer   *cell,
 		      GtkTreeModel      *tree_model,
 		      GtkTreeIter       *iter,
 		      gpointer           data)
@@ -11276,8 +11081,8 @@ list_mtime_data_func (GtkTreeViewColumn *tree_column,
 
       search_get_valid_child_iter (impl, &child_iter, iter);
       gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
-                          SEARCH_MODEL_COL_MTIME, &mtime,
-                          SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
+                          MODEL_COL_MTIME, &mtime,
+                          MODEL_COL_IS_FOLDER, &is_folder,
 			  -1);
 
       time_mtime = (time_t) mtime;
@@ -11295,7 +11100,7 @@ list_mtime_data_func (GtkTreeViewColumn *tree_column,
       recent_get_valid_child_iter (impl, &child_iter, iter);
       gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
                           RECENT_MODEL_COL_INFO, &info,
-                          RECENT_MODEL_COL_IS_FOLDER, &is_folder,
+                          MODEL_COL_IS_FOLDER, &is_folder,
                           -1);
 
       if (info)
@@ -11332,101 +11137,7 @@ list_mtime_data_func (GtkTreeViewColumn *tree_column,
   if (G_UNLIKELY (time_mtime == 0))
     date_str = g_strdup (_("Unknown"));
   else
-    {
-      GDate mtime, now;
-      gint days_diff;
-      struct tm tm_mtime;
-      time_t time_now;
-      const gchar *format;
-      gchar *locale_format = NULL;
-      gchar buf[256];
-
-#ifdef HAVE_LOCALTIME_R
-      localtime_r ((time_t *) &time_mtime, &tm_mtime);
-#else
-      {
-        struct tm *ptm = localtime ((time_t *) &timeval.tv_sec);
-
-        if (!ptm)
-          {
-            g_warning ("ptm != NULL failed");
-            
-            g_object_set (cell,
-                          "text", _("Unknown"),
-                          "sensitive", sensitive,
-                          NULL);
-            return;
-          }
-        else
-          memcpy ((void *) &tm_mtime, (void *) ptm, sizeof (struct tm));
-      }
-#endif /* HAVE_LOCALTIME_R */
-
-      g_date_set_time_t (&mtime, time_mtime);
-      time_now = time (NULL);
-      g_date_set_time_t (&now, time_now);
-
-      days_diff = g_date_get_julian (&now) - g_date_get_julian (&mtime);
-
-      /* Translators: %H means "hours" and %M means "minutes" */
-      if (days_diff == 0)
-        format = _("%H:%M");
-      else if (days_diff == 1)
-	format = _("Yesterday at %H:%M");
-      else
-	{
-	  if (days_diff > 1 && days_diff < 7)
-	    format = "%A"; /* Days from last week */
-	  else
-	    format = "%x"; /* Any other date */
-	}
-
-#ifdef G_OS_WIN32
-      /* g_locale_from_utf8() returns a string in the system
-       * code-page, which is not always the same as that used by the C
-       * library. For instance when running a GTK+ program with
-       * LANG=ko on an English version of Windows, the system
-       * code-page is 1252, but the code-page used by the C library is
-       * 949. (It's GTK+ itself that sets the C library locale when it
-       * notices the LANG environment variable. See gtkmain.c The
-       * Microsoft C library doesn't look at any locale environment
-       * variables.) We need to pass strftime() a string in the C
-       * library's code-page. See bug #509885.
-       */
-      locale = setlocale (LC_ALL, NULL);
-      if (locale != NULL)
-	dot = strchr (locale, '.');
-      if (dot != NULL)
-	{
-	  codepage = g_ascii_strtoll (dot+1, NULL, 10);
-	  
-	  /* All codepages should fit in 16 bits AFAIK */
-	  if (codepage > 0 && codepage < 65536)
-	    {
-	      sprintf (charset, "CP%u", (guint) codepage);
-	      locale_format = g_convert (format, -1, charset, "UTF-8", NULL, NULL, NULL);
-	    }
-	}
-#else
-      locale_format = g_locale_from_utf8 (format, -1, NULL, NULL, NULL);
-#endif
-      if (locale_format != NULL &&
-	  strftime (buf, sizeof (buf), locale_format, &tm_mtime) != 0)
-        {
-#ifdef G_OS_WIN32
-	  /* As above but in opposite direction... */
-	  if (codepage > 0 && codepage < 65536)
-	    date_str = g_convert (buf, -1, "UTF-8", charset, NULL, NULL, NULL);
-#else
-	  date_str = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL);
-#endif
-	}
-
-      if (date_str == NULL)
-	date_str = g_strdup (_("Unknown"));
-
-      g_free (locale_format);
-    }
+    date_str = my_g_format_time_for_display (time_mtime);
 
   g_object_set (cell,
 		"text", date_str,
@@ -11719,7 +11430,7 @@ recent_model_sort_row_draggable (GtkTreeDragSource *drag_source,
 
   recent_get_valid_child_iter (model->impl, &child_iter, &iter);
   gtk_tree_model_get (GTK_TREE_MODEL (model->impl->recent_model), &child_iter,
-                      RECENT_MODEL_COL_IS_FOLDER, &is_folder,
+                      MODEL_COL_IS_FOLDER, &is_folder,
                       -1);
 
   return is_folder;
@@ -11741,7 +11452,7 @@ recent_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
 
   recent_get_valid_child_iter (model->impl, &child_iter, &iter);
   gtk_tree_model_get (GTK_TREE_MODEL (model->impl->recent_model), &child_iter,
-                      RECENT_MODEL_COL_FILE, &file,
+                      MODEL_COL_FILE, &file,
                       -1);
   g_assert (file != NULL);
 
@@ -11751,6 +11462,7 @@ recent_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
   gtk_selection_data_set_uris (selection_data, uris);
 
   g_free (uris[0]);
+  g_object_unref (file);
 
   return TRUE;
 }
@@ -11804,7 +11516,7 @@ search_model_sort_row_draggable (GtkTreeDragSource *drag_source,
 
   search_get_valid_child_iter (model->impl, &child_iter, &iter);
   gtk_tree_model_get (GTK_TREE_MODEL (model->impl->search_model), &child_iter,
-                      SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
+                      MODEL_COL_IS_FOLDER, &is_folder,
                       -1);
 
   return is_folder;
@@ -11826,7 +11538,7 @@ search_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
 
   search_get_valid_child_iter (model->impl, &child_iter, &iter);
   gtk_tree_model_get (GTK_TREE_MODEL (model->impl->search_model), &child_iter,
-                      RECENT_MODEL_COL_FILE, &file,
+                      MODEL_COL_FILE, &file,
                       -1);
   g_assert (file != NULL);
 
@@ -11836,6 +11548,7 @@ search_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
   gtk_selection_data_set_uris (selection_data, uris);
 
   g_free (uris[0]);
+  g_object_unref (file);
 
   return TRUE;
 }
diff --git a/gtk/gtkfilesystemmodel.c b/gtk/gtkfilesystemmodel.c
index a9a88fa..22ca25a 100644
--- a/gtk/gtkfilesystemmodel.c
+++ b/gtk/gtkfilesystemmodel.c
@@ -72,8 +72,8 @@ struct _GtkFileSystemModel
 
   guint                 n_columns;      /* number of columns */
   GType *               column_types;   /* types of each column */
-  GtkFileSystemModelSet set_func;       /* function to call to fill in values in columns */
-  gpointer              set_data;       /* data to pass to set_func */
+  GtkFileSystemModelGetValue get_func;  /* function to call to fill in values in columns */
+  gpointer              get_data;       /* data to pass to get_func */
 
   GtkFileSystemModelFilter filter_func; /* filter to use for deciding which nodes are visible */
   gpointer              filter_data;    /* data to pass to filter_func */
@@ -166,18 +166,6 @@ gtk_tree_path_new_from_node (GtkFileSystemModel *model, guint id)
 }
 
 static void
-node_ensure_values_set (GtkFileSystemModel *model, guint id)
-{
-  FileModelNode *node = get_node (model, id);
-
-  if (node->values_set)
-    return;
-
-  model->set_func (model, node->file, node->info, node->values, model->set_data);
-  node->values_set = TRUE;
-}
-
-static void
 node_set_visible (GtkFileSystemModel *model, guint id, gboolean visible)
 {
   FileModelNode *node = get_node (model, id);
@@ -342,12 +330,11 @@ gtk_file_system_model_get_path (GtkTreeModel *tree_model,
 static void
 gtk_file_system_model_get_value (GtkTreeModel *tree_model,
 				 GtkTreeIter  *iter,
-				 gint          i_can_has_uint,
+				 gint          column,
 				 GValue       *value)
 {
   GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
   FileModelNode *node;
-  guint column = i_can_has_uint;
   
   g_return_if_fail (column < model->n_columns);
   g_return_if_fail (ITER_IS_VALID (model, iter));
@@ -355,7 +342,16 @@ gtk_file_system_model_get_value (GtkTreeModel *tree_model,
   node = get_node (model, ITER_INDEX (iter));
   g_assert (node->visible);
   
-  node_ensure_values_set (model, ITER_INDEX (iter));
+  if (!G_VALUE_TYPE (&node->values[column]))
+    {
+      g_value_init (&node->values[column], model->column_types[column]);
+      model->get_func (model, 
+                       node->file, 
+                       node->info, 
+                       column, 
+                       &node->values[column],
+                       model->get_data);
+    }
 
   g_value_init (value, model->column_types[column]);
   g_value_copy (&node->values[column], value);
@@ -575,16 +571,10 @@ static void
 gtk_file_system_model_add_node (GtkFileSystemModel *model, GFile *file, GFileInfo *info)
 {
   FileModelNode *node = g_slice_alloc0 (NODE_SIZE (model));
-  guint i;
 
   node->file = file;
   node->info = info;
 
-  for (i = 0; i < model->n_columns; i++)
-    {
-      g_value_init (&node->values[i], model->column_types[i]);
-    }
-
   g_array_append_vals (model->files, node, 1);
   g_slice_free1 (NODE_SIZE (model), node);
 }
@@ -747,12 +737,12 @@ gtk_file_system_model_set_n_columns (GtkFileSystemModel *model,
  * was an error.
  **/
 GtkFileSystemModel *
-_gtk_file_system_model_new (GFile *               dir,
-			    const gchar *         attributes,
-			    const gchar *         full_attributes,
-                            GtkFileSystemModelSet set_func,
-                            gpointer              set_data,
-                            guint                 n_columns,
+_gtk_file_system_model_new (GFile *                    dir,
+			    const gchar *              attributes,
+			    const gchar *              full_attributes,
+                            GtkFileSystemModelGetValue get_func,
+                            gpointer                   get_data,
+                            guint                      n_columns,
                             ...)
 {
   GtkFileSystemModel *model;
@@ -764,8 +754,8 @@ _gtk_file_system_model_new (GFile *               dir,
   model->dir = g_object_ref (dir);
   model->attributes = g_strdup (attributes);
   model->full_attributes = g_strdup (full_attributes);
-  model->set_func = set_func;
-  model->set_data = set_data;
+  model->get_func = get_func;
+  model->get_data = get_data;
 
   va_start (args, n_columns);
   gtk_file_system_model_set_n_columns (model, n_columns, args);
diff --git a/gtk/gtkfilesystemmodel.h b/gtk/gtkfilesystemmodel.h
index dabd6a5..89c6f6a 100644
--- a/gtk/gtkfilesystemmodel.h
+++ b/gtk/gtkfilesystemmodel.h
@@ -34,17 +34,18 @@ typedef struct _GtkFileSystemModel      GtkFileSystemModel;
 
 GType _gtk_file_system_model_get_type (void) G_GNUC_CONST;
 
-typedef void (*GtkFileSystemModelSet)        (GtkFileSystemModel *model,
+typedef void (*GtkFileSystemModelGetValue)   (GtkFileSystemModel *model,
 					      GFile              *file,
 					      GFileInfo          *info,
-                                              GValue             *values,
+                                              int                 column,
+                                              GValue             *value,
 					      gpointer            user_data);
 
 GtkFileSystemModel *_gtk_file_system_model_new              (GFile *             dir,
                                                              const gchar *       attributes,
                                                              const gchar *       full_attributes,
-                                                             GtkFileSystemModelSet set_func,
-                                                             gpointer            set_data,
+                                                             GtkFileSystemModelGetValue get_func,
+                                                             gpointer            get_data,
                                                              guint               n_columns,
                                                              ...);
 GFileInfo *         _gtk_file_system_model_get_info         (GtkFileSystemModel *model,



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