[gtk+] Consolidate tree models for different browse modes



commit a5390ad49e53522dedc6bbb894e715e7eef91f7f
Author: Benjamin Otte <otte gnome org>
Date:   Tue Jun 30 21:24:52 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 | 1087 ++++++++++++++++---------------------------
 1 files changed, 397 insertions(+), 690 deletions(-)
---
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index 56aaa6f..2d643c5 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -191,37 +191,36 @@ typedef enum {
   SHORTCUT_TYPE_RECENT
 } ShortcutType;
 
+enum {
+  /* 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
 };
 
-typedef enum {
-  GTK_FILE_SYSTEM_MODEL_INFO,
-  GTK_FILE_SYSTEM_MODEL_DISPLAY_NAME,
-  GTK_FILE_SYSTEM_MODEL_N_COLUMNS
-} GtkFileSystemModelColumns;
-
 /* Identifiers for target types */
 enum {
   GTK_TREE_MODEL_ROW,
@@ -804,7 +803,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 ();
   impl->create_folders = TRUE;
@@ -2644,36 +2643,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 */
@@ -2795,14 +2775,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;
     }
@@ -2869,14 +2849,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;
     }
@@ -2932,14 +2912,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;
         }
@@ -4516,64 +4496,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
@@ -4613,7 +4542,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;
     
@@ -4626,7 +4555,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;
 
@@ -6181,7 +6110,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);
 }
 
@@ -6401,19 +6330,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 */
@@ -6431,9 +6351,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);
@@ -6452,8 +6380,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);
     }
@@ -6469,12 +6399,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);
     }
 }
 
@@ -6491,7 +6421,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;
     }
 }
@@ -6533,9 +6463,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;
@@ -6549,7 +6479,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),
-				   GTK_FILE_SYSTEM_MODEL_DISPLAY_NAME);
+				   MODEL_COL_NAME);
   profile_msg ("    gtk_tree_view_set_model end", NULL);
 
   profile_end ("end", NULL);
@@ -6904,25 +6834,170 @@ 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 gboolean 
 file_system_model_set (GtkFileSystemModel *model,
                        GFile              *file,
                        GFileInfo          *info,
                        int                 column,
                        GValue             *value,
-                       gpointer            user_data)
+                       gpointer            data)
 {
+  GtkFileChooserDefault *impl = data;
+ 
   switch (column)
     {
-    case GTK_FILE_SYSTEM_MODEL_INFO:
-      g_value_set_object (value, info);
+    case MODEL_COL_FILE:
+      g_value_set_object (value, file);
       break;
-    case GTK_FILE_SYSTEM_MODEL_DISPLAY_NAME:
+    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_set_string (value, g_file_info_get_display_name (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, info ? g_file_info_get_size (info) : 0);
+      break;
+    case MODEL_COL_SIZE_TEXT:
+      if (info == NULL || _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;
     }
 
   return TRUE;
@@ -6947,9 +7022,17 @@ set_list_model (GtkFileChooserDefault *impl,
         "standard,time,thumbnail::*",
         file_system_model_set,
         impl,
-        GTK_FILE_SYSTEM_MODEL_N_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 */
 
@@ -8922,7 +9005,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));
 }
 
@@ -8976,10 +9059,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)
@@ -9015,25 +9097,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);
@@ -9050,8 +9145,6 @@ search_add_hit (GtkFileChooserDefault *impl,
 		gchar                 *uri)
 {
   GFile *file;
-  char *tmp;
-  char *collation_key;
   GtkTreeIter iter;
   GtkTreePath *p;
   GCancellable *cancellable;
@@ -9067,10 +9160,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);
@@ -9092,10 +9181,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 */
@@ -9166,29 +9258,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 */
@@ -9278,113 +9358,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,
@@ -9442,25 +9415,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 */
@@ -9471,34 +9448,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));
@@ -9509,16 +9472,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);
 
@@ -9776,8 +9739,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);
@@ -9851,83 +9814,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,
@@ -9990,8 +9876,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)
@@ -10010,27 +9896,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));
@@ -10050,12 +9929,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);
 }
@@ -10110,6 +9993,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;
@@ -10125,6 +10010,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;
 
@@ -10142,11 +10028,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);
@@ -10190,7 +10082,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;
@@ -10260,15 +10153,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;
@@ -10323,8 +10225,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 */
@@ -10506,61 +10408,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 &&
@@ -10575,13 +10443,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)
@@ -10914,7 +10783,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;
@@ -10930,7 +10799,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;
@@ -10993,103 +10862,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
@@ -11149,8 +10948,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 ||
@@ -11168,7 +10967,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);
@@ -11242,8 +11041,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 ||
@@ -11271,7 +11070,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);
@@ -11344,8 +11143,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 ||
@@ -11396,7 +11195,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)
@@ -11422,8 +11221,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;
@@ -11441,7 +11240,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)
@@ -11478,101 +11277,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,
@@ -11865,7 +11570,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;
@@ -11887,7 +11592,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);
 
@@ -11897,6 +11602,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;
 }
@@ -11950,7 +11656,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;
@@ -11972,7 +11678,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);
 
@@ -11982,6 +11688,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;
 }



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