]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkfilechooserdefault.c
Set the location mode when changing the operation mode
[~andy/gtk] / gtk / gtkfilechooserdefault.c
index 8ffd758a05261d695fe51464ab2d4a05f035bdce..d24c3c110b7ee5bf53eec68af9c71e64848f0e82 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "gtkfilechooserdefault.h"
 
-#include "gtkalignment.h"
 #include "gtkbindings.h"
 #include "gtkcelllayout.h"
 #include "gtkcellrendererpixbuf.h"
 #include "gtkfilesystem.h"
 #include "gtkfilesystemmodel.h"
 #include "gtkframe.h"
-#include "gtkhbox.h"
-#include "gtkhpaned.h"
+#include "gtkpaned.h"
 #include "gtkiconfactory.h"
 #include "gtkicontheme.h"
 #include "gtkimage.h"
 #include "gtkimagemenuitem.h"
+#include "gtkinfobar.h"
 #include "gtklabel.h"
 #include "gtkmarshalers.h"
 #include "gtkmessagedialog.h"
 #include "gtksizerequest.h"
 #include "gtkstock.h"
 #include "gtktable.h"
+#include "gtktoolbar.h"
+#include "gtktoolbutton.h"
 #include "gtktooltip.h"
 #include "gtktreednd.h"
 #include "gtktreeprivate.h"
 #include "gtktreeselection.h"
-#include "gtkvbox.h"
+#include "gtkbox.h"
+#include "gtkorientable.h"
 #include "gtkintl.h"
 
 #include <errno.h>
@@ -147,7 +149,7 @@ typedef struct _GtkFileChooserDefaultClass GtkFileChooserDefaultClass;
 
 struct _GtkFileChooserDefaultClass
 {
-  GtkVBoxClass parent_class;
+  GtkBoxClass parent_class;
 };
 
 /* Signal IDs */
@@ -248,9 +250,9 @@ typedef enum {
 #define NUM_LINES 45
 #define NUM_CHARS 60
 
+#define SETTINGS_KEY_LAST_FOLDER_URI     "last-folder-uri"
 #define SETTINGS_KEY_LOCATION_MODE       "location-mode"
 #define SETTINGS_KEY_SHOW_HIDDEN         "show-hidden"
-#define SETTINGS_KEY_EXPAND_FOLDERS      "expand-folders"
 #define SETTINGS_KEY_SHOW_SIZE_COLUMN    "show-size-column"
 #define SETTINGS_KEY_SORT_COLUMN         "sort-column"
 #define SETTINGS_KEY_SORT_ORDER          "sort-order"
@@ -325,6 +327,8 @@ static void           gtk_file_chooser_default_get_default_size       (GtkFileCh
 static gboolean       gtk_file_chooser_default_should_respond         (GtkFileChooserEmbed *chooser_embed);
 static void           gtk_file_chooser_default_initial_focus          (GtkFileChooserEmbed *chooser_embed);
 
+static void add_selection_to_recent_list (GtkFileChooserDefault *impl);
+
 static void location_popup_handler  (GtkFileChooserDefault *impl,
                                     const gchar           *path);
 static void location_popup_on_paste_handler (GtkFileChooserDefault *impl);
@@ -390,8 +394,6 @@ static void add_bookmark_button_clicked_cb    (GtkButton             *button,
                                               GtkFileChooserDefault *impl);
 static void remove_bookmark_button_clicked_cb (GtkButton             *button,
                                               GtkFileChooserDefault *impl);
-static void save_folder_combo_changed_cb      (GtkComboBox           *combo,
-                                              GtkFileChooserDefault *impl);
 
 static void update_cell_renderer_attributes (GtkFileChooserDefault *impl);
 
@@ -404,22 +406,23 @@ static void location_switch_to_path_bar (GtkFileChooserDefault *impl);
 
 static void stop_loading_and_clear_list_model (GtkFileChooserDefault *impl,
                                                gboolean remove_from_treeview);
+
+static void     search_setup_widgets         (GtkFileChooserDefault *impl);
 static void     search_stop_searching        (GtkFileChooserDefault *impl,
                                               gboolean               remove_query);
 static void     search_clear_model           (GtkFileChooserDefault *impl, 
                                              gboolean               remove_from_treeview);
 static gboolean search_should_respond        (GtkFileChooserDefault *impl);
-static void     search_switch_to_browse_mode (GtkFileChooserDefault *impl);
 static GSList  *search_get_selected_files    (GtkFileChooserDefault *impl);
 static void     search_entry_activate_cb     (GtkEntry              *entry, 
                                              gpointer               data);
 static void     settings_load                (GtkFileChooserDefault *impl);
 
+static void     recent_start_loading         (GtkFileChooserDefault *impl);
 static void     recent_stop_loading          (GtkFileChooserDefault *impl);
 static void     recent_clear_model           (GtkFileChooserDefault *impl,
                                               gboolean               remove_from_treeview);
 static gboolean recent_should_respond        (GtkFileChooserDefault *impl);
-static void     recent_switch_to_browse_mode (GtkFileChooserDefault *impl);
 static GSList * recent_get_selected_files    (GtkFileChooserDefault *impl);
 static void     set_file_system_backend      (GtkFileChooserDefault *impl);
 static void     unset_file_system_backend    (GtkFileChooserDefault *impl);
@@ -457,12 +460,28 @@ static GtkTreeModel *shortcuts_pane_model_filter_new (GtkFileChooserDefault *imp
 
 \f
 
-G_DEFINE_TYPE_WITH_CODE (GtkFileChooserDefault, _gtk_file_chooser_default, GTK_TYPE_VBOX,
+G_DEFINE_TYPE_WITH_CODE (GtkFileChooserDefault, _gtk_file_chooser_default, GTK_TYPE_BOX,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER,
                                                gtk_file_chooser_default_iface_init)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER_EMBED,
                                                gtk_file_chooser_embed_default_iface_init));                                            
 
+
+static void
+add_normal_and_shifted_binding (GtkBindingSet  *binding_set,
+                               guint           keyval,
+                               GdkModifierType modifiers,
+                               const gchar    *signal_name)
+{
+  gtk_binding_entry_add_signal (binding_set,
+                               keyval, modifiers,
+                               signal_name, 0);
+
+  gtk_binding_entry_add_signal (binding_set,
+                               keyval, modifiers | GDK_SHIFT_MASK,
+                               signal_name, 0);
+}
+
 static void
 _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
 {
@@ -615,27 +634,25 @@ _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
                                GDK_KEY_v, GDK_CONTROL_MASK,
                                "location-popup-on-paste",
                                0);
-  gtk_binding_entry_add_signal (binding_set,
-                               GDK_KEY_Up, GDK_MOD1_MASK,
-                               "up-folder",
-                               0);
   gtk_binding_entry_add_signal (binding_set,
                                GDK_KEY_BackSpace, 0,
                                "up-folder",
                                0);
-  gtk_binding_entry_add_signal (binding_set,
-                               GDK_KEY_KP_Up, GDK_MOD1_MASK,
-                               "up-folder",
-                               0);
 
-  gtk_binding_entry_add_signal (binding_set,
-                               GDK_KEY_Down, GDK_MOD1_MASK,
-                               "down-folder",
-                               0);
-  gtk_binding_entry_add_signal (binding_set,
-                               GDK_KEY_KP_Down, GDK_MOD1_MASK,
-                               "down-folder",
-                               0);
+  add_normal_and_shifted_binding (binding_set,
+                                 GDK_KEY_Up, GDK_MOD1_MASK,
+                                 "up-folder");
+
+  add_normal_and_shifted_binding (binding_set,
+                                 GDK_KEY_KP_Up, GDK_MOD1_MASK,
+                                 "up-folder");
+
+  add_normal_and_shifted_binding (binding_set,
+                                 GDK_KEY_Down, GDK_MOD1_MASK,
+                                 "down-folder");
+  add_normal_and_shifted_binding (binding_set,
+                                 GDK_KEY_KP_Down, GDK_MOD1_MASK,
+                                 "down-folder");
 
   gtk_binding_entry_add_signal (binding_set,
                                GDK_KEY_Home, GDK_MOD1_MASK,
@@ -724,6 +741,8 @@ _gtk_file_chooser_default_init (GtkFileChooserDefault *impl)
   impl->recent_manager = gtk_recent_manager_get_default ();
   impl->create_folders = TRUE;
 
+  gtk_orientable_set_orientation (GTK_ORIENTABLE (impl),
+                                  GTK_ORIENTATION_VERTICAL);
   gtk_box_set_spacing (GTK_BOX (impl), 12);
 
   set_file_system_backend (impl);
@@ -747,7 +766,10 @@ shortcuts_free_row_data (GtkFileChooserDefault *impl,
                      -1);
 
   if (cancellable)
-    g_cancellable_cancel (cancellable);
+    {
+      g_cancellable_cancel (cancellable);
+      g_object_unref (cancellable);
+    }
 
   if (!(shortcut_type == SHORTCUT_TYPE_FILE || 
        shortcut_type == SHORTCUT_TYPE_VOLUME) ||
@@ -817,9 +839,6 @@ gtk_file_chooser_default_finalize (GObject *object)
   if (impl->shortcuts_pane_filter_model)
     g_object_unref (impl->shortcuts_pane_filter_model);
 
-  if (impl->shortcuts_combo_filter_model)
-    g_object_unref (impl->shortcuts_combo_filter_model);
-
   shortcuts_free (impl);
 
   g_free (impl->browse_files_last_selected_name);
@@ -1441,7 +1460,7 @@ get_file_info_finished (GCancellable *cancellable,
   GdkPixbuf *pixbuf;
   GtkTreePath *path;
   GtkTreeIter iter;
-  GCancellable *model_cancellable;
+  GCancellable *model_cancellable = NULL;
   struct ShortcutsInsertRequest *request = data;
 
   path = gtk_tree_row_reference_get_path (request->row_ref);
@@ -1508,32 +1527,6 @@ get_file_info_finished (GCancellable *cancellable,
   if (request->impl->shortcuts_pane_filter_model)
     gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (request->impl->shortcuts_pane_filter_model));
 
-  if (request->impl->shortcuts_combo_filter_model)
-    gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (request->impl->shortcuts_combo_filter_model));
-
-  if (request->type == SHORTCUTS_CURRENT_FOLDER &&
-      request->impl->save_folder_combo != NULL)
-    {
-      /* The current folder is updated via _activate_iter(), don't
-       * have save_folder_combo_changed_cb() call _activate_iter()
-       * again.
-       */
-      g_signal_handlers_block_by_func (request->impl->save_folder_combo,
-                                      G_CALLBACK (save_folder_combo_changed_cb),
-                                      request->impl);
-      
-      if (request->impl->has_search)
-        pos -= 1;
-
-      if (request->impl->has_recent)
-        pos -= 2;
-
-      gtk_combo_box_set_active (GTK_COMBO_BOX (request->impl->save_folder_combo), pos);
-      g_signal_handlers_unblock_by_func (request->impl->save_folder_combo,
-                                        G_CALLBACK (save_folder_combo_changed_cb),
-                                        request->impl);
-    }
-
   if (pixbuf)
     g_object_unref (pixbuf);
 
@@ -1544,7 +1537,8 @@ out:
   g_free (request->label_copy);
   g_free (request);
 
-  g_object_unref (cancellable);
+  if (model_cancellable)
+    g_object_unref (model_cancellable);
 }
 
 /* FIXME: GtkFileSystem needs a function to split a remote path
@@ -1718,33 +1712,6 @@ shortcuts_insert_file (GtkFileChooserDefault *impl,
   if (impl->shortcuts_pane_filter_model)
     gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model));
 
-  if (impl->shortcuts_combo_filter_model)
-    gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model));
-
-  if (type == SHORTCUTS_CURRENT_FOLDER && impl->save_folder_combo != NULL)
-    {
-      /* The current folder is updated via _activate_iter(), don't
-       * have save_folder_combo_changed_cb() call _activate_iter()
-       * again.
-       */
-      gint combo_pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER);
-
-      if (impl->has_search)
-        combo_pos -= 1;
-
-      if (impl->has_recent)
-        combo_pos -= 2;
-      
-      g_signal_handlers_block_by_func (impl->save_folder_combo,
-                                      G_CALLBACK (save_folder_combo_changed_cb),
-                                      impl);
-      
-      gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), combo_pos);
-      g_signal_handlers_unblock_by_func (impl->save_folder_combo,
-                                        G_CALLBACK (save_folder_combo_changed_cb),
-                                        impl);
-    }
-
   g_free (label_copy);
 
   if (pixbuf)
@@ -1797,8 +1764,6 @@ shortcuts_append_recent (GtkFileChooserDefault *impl)
   
   if (pixbuf)
     g_object_unref (pixbuf);
-
-  impl->has_recent = TRUE;
 }
 
 /* Appends an item for the user's home directory to the shortcuts model */
@@ -1914,12 +1879,12 @@ shortcuts_get_index (GtkFileChooserDefault *impl,
   if (where == SHORTCUTS_RECENT)
     goto out;
 
-  n += impl->has_recent ? 1 : 0;
+  n += 1; /* we always have the recently-used item */
 
   if (where == SHORTCUTS_RECENT_SEPARATOR)
     goto out;
 
-  n += impl->has_recent ? 1 : 0;
+  n += 1; /* we always have the separator after the recently-used item */
 
   if (where == SHORTCUTS_HOME)
     goto out;
@@ -2031,9 +1996,6 @@ shortcuts_add_volumes (GtkFileChooserDefault *impl)
   if (impl->shortcuts_pane_filter_model)
     gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model));
 
-  if (impl->shortcuts_combo_filter_model)
-    gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model));
-
   impl->changing_folder = old_changing_folders;
 
   profile_end ("end", NULL);
@@ -2069,7 +2031,6 @@ shortcuts_add_bookmarks (GtkFileChooserDefault *impl)
   gboolean old_changing_folders;
   GtkTreeIter iter;
   GFile *list_selected = NULL;
-  GFile *combo_selected = NULL;
   ShortcutType shortcut_type;
   gpointer col_data;
 
@@ -2090,25 +2051,6 @@ shortcuts_add_bookmarks (GtkFileChooserDefault *impl)
        list_selected = g_object_ref (col_data);
     }
 
-  if (impl->save_folder_combo &&
-      gtk_combo_box_get_active_iter (GTK_COMBO_BOX (impl->save_folder_combo), 
-                                    &iter))
-    {
-      GtkTreeIter child_iter;
-
-      gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER  (impl->shortcuts_combo_filter_model),
-                                                       &child_iter,
-                                                       &iter);
-      gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), 
-                         &child_iter, 
-                         SHORTCUTS_COL_DATA, &col_data,
-                         SHORTCUTS_COL_TYPE, &shortcut_type,
-                         -1);
-      
-      if (col_data && shortcut_type == SHORTCUT_TYPE_FILE)
-       combo_selected = g_object_ref (col_data);
-    }
-
   if (impl->num_bookmarks > 0)
     shortcuts_remove_rows (impl,
                           shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR),
@@ -2128,34 +2070,12 @@ shortcuts_add_bookmarks (GtkFileChooserDefault *impl)
   if (impl->shortcuts_pane_filter_model)
     gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model));
 
-  if (impl->shortcuts_combo_filter_model)
-    gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model));
-
   if (list_selected)
     {
       shortcuts_find_folder (impl, list_selected);
       g_object_unref (list_selected);
     }
 
-  if (combo_selected)
-    {
-      gint pos;
-
-      pos = shortcut_find_position (impl, combo_selected);
-      if (pos != -1)
-        {
-          if (impl->has_search)
-            pos -= 1;
-
-          if (impl->has_recent)
-            pos -= 2;
-
-         gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), pos);
-        }
-
-      g_object_unref (combo_selected);
-    }
-  
   impl->changing_folder = old_changing_folders;
 
   profile_end ("end", NULL);
@@ -2166,12 +2086,9 @@ static void
 shortcuts_add_current_folder (GtkFileChooserDefault *impl)
 {
   int pos;
-  gboolean success;
 
   g_assert (!impl->shortcuts_current_folder_active);
 
-  success = TRUE;
-
   g_assert (impl->current_folder != NULL);
 
   pos = shortcut_find_position (impl, impl->current_folder);
@@ -2181,36 +2098,24 @@ shortcuts_add_current_folder (GtkFileChooserDefault *impl)
       GFile *base_file;
 
       /* Separator */
-
       shortcuts_insert_separator (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
 
       /* Item */
-
       pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER);
 
       volume = _gtk_file_system_get_volume_for_file (impl->file_system, impl->current_folder);
       if (volume)
-       base_file = _gtk_file_system_volume_get_root (volume);
+        base_file = _gtk_file_system_volume_get_root (volume);
       else
-       base_file = NULL;
+        base_file = NULL;
 
       if (base_file && g_file_equal (base_file, impl->current_folder))
-       shortcuts_insert_file (impl, pos, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
+        shortcuts_insert_file (impl, pos, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
       else
-       shortcuts_insert_file (impl, pos, SHORTCUT_TYPE_FILE, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
+        shortcuts_insert_file (impl, pos, SHORTCUT_TYPE_FILE, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
 
       if (base_file)
-       g_object_unref (base_file);
-    }
-  else if (impl->save_folder_combo != NULL)
-    {
-      if (impl->has_search)
-        pos -= 1;
-
-      if (impl->has_recent)
-        pos -= 2; /* + separator */
-
-      gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), pos);
+        g_object_unref (base_file);
     }
 }
 
@@ -2456,27 +2361,27 @@ filter_create (GtkFileChooserDefault *impl)
 }
 
 static GtkWidget *
-button_new (GtkFileChooserDefault *impl,
-           const char            *text,
-           const char            *stock_id,
-           gboolean               sensitive,
-           gboolean               show,
-           GCallback              callback)
+toolbutton_new (GtkFileChooserDefault *impl,
+                GIcon                 *icon,
+                gboolean               sensitive,
+                gboolean               show,
+                GCallback              callback)
 {
-  GtkWidget *button;
+  GtkToolItem *item;
   GtkWidget *image;
 
-  button = gtk_button_new_with_mnemonic (text);
-  image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
-  gtk_button_set_image (GTK_BUTTON (button), image);
+  item = gtk_tool_button_new (NULL, NULL);
+  image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_SMALL_TOOLBAR);
+  gtk_widget_show (image);
+  gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (item), image);
 
-  gtk_widget_set_sensitive (button, sensitive);
-  g_signal_connect (button, "clicked", callback, impl);
+  gtk_widget_set_sensitive (GTK_WIDGET (item), sensitive);
+  g_signal_connect (item, "clicked", callback, impl);
 
   if (show)
-    gtk_widget_show (button);
+    gtk_widget_show (GTK_WIDGET (item));
 
-  return button;
+  return GTK_WIDGET (item);
 }
 
 /* Looks for a path among the shortcuts; returns its index or -1 if it doesn't exist */
@@ -3180,7 +3085,7 @@ shortcuts_reorder (GtkFileChooserDefault *impl,
   int bookmarks_index;
   GFile *file;
   GError *error;
-  gchar *name;
+  gchar *name = NULL;
 
   /* Get the selected path */
 
@@ -3226,6 +3131,7 @@ shortcuts_reorder (GtkFileChooserDefault *impl,
  out:
 
   g_object_unref (file);
+  g_free (name);
 }
 
 /* Callback used when we get the drag data for the bookmarks list.  We add the
@@ -3608,8 +3514,9 @@ shortcuts_list_create (GtkFileChooserDefault *impl)
   gtk_widget_show (swin);
 
   /* Tree */
-
   impl->browse_shortcuts_tree_view = gtk_tree_view_new ();
+  gtk_style_context_add_class (gtk_widget_get_style_context (impl->browse_shortcuts_tree_view),
+                               GTK_STYLE_CLASS_SIDEBAR);
   gtk_tree_view_set_enable_search (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), FALSE);
 #ifdef PROFILE_FILE_CHOOSER
   g_object_set_data (G_OBJECT (impl->browse_shortcuts_tree_view), "fmq-name", "shortcuts");
@@ -3704,10 +3611,13 @@ shortcuts_list_create (GtkFileChooserDefault *impl)
                                       NULL);
 
   renderer = gtk_cell_renderer_text_new ();
-  g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-  g_signal_connect (renderer, "edited", 
+  g_object_set (renderer,
+                "width-chars", 12,
+                "ellipsize", PANGO_ELLIPSIZE_END,
+                NULL);
+  g_signal_connect (renderer, "edited",
                    G_CALLBACK (shortcuts_edited), impl);
-  g_signal_connect (renderer, "editing-canceled", 
+  g_signal_connect (renderer, "editing-canceled",
                    G_CALLBACK (shortcuts_editing_canceled), impl);
   gtk_tree_view_column_pack_start (column, renderer, TRUE);
   gtk_tree_view_column_set_attributes (column, renderer,
@@ -3729,46 +3639,58 @@ shortcuts_pane_create (GtkFileChooserDefault *impl,
                       GtkSizeGroup          *size_group)
 {
   GtkWidget *vbox;
-  GtkWidget *hbox;
+  GtkWidget *toolbar;
   GtkWidget *widget;
+  GtkStyleContext *context;
+  GIcon *icon;
 
-  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
   gtk_widget_show (vbox);
 
   /* Shortcuts tree */
 
   widget = shortcuts_list_create (impl);
+
+  gtk_size_group_add_widget (size_group, widget);
+  context = gtk_widget_get_style_context (widget);
+  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
+
   gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
 
   /* Box for buttons */
 
-  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
-  gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
-  gtk_size_group_add_widget (size_group, hbox);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-  gtk_widget_show (hbox);
+  toolbar = gtk_toolbar_new ();
+  gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU);
 
-  /* Add bookmark button */
+  context = gtk_widget_get_style_context (toolbar);
+  gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_INLINE_TOOLBAR);
+  
+  gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
+  gtk_widget_show (toolbar);
 
-  impl->browse_shortcuts_add_button = button_new (impl,
-                                                 _("_Add"),
-                                                 GTK_STOCK_ADD,
-                                                 FALSE,
-                                                 TRUE,
-                                                 G_CALLBACK (add_bookmark_button_clicked_cb));
-  gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_add_button, TRUE, TRUE, 0);
+  /* Add bookmark button */
+  icon = g_themed_icon_new_with_default_fallbacks ("list-add-symbolic");
+  impl->browse_shortcuts_add_button = toolbutton_new (impl,
+                                                      icon,
+                                                      FALSE,
+                                                      TRUE,
+                                                      G_CALLBACK (add_bookmark_button_clicked_cb));
+  g_object_unref (icon);
+
+  gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (impl->browse_shortcuts_add_button), 0);
   gtk_widget_set_tooltip_text (impl->browse_shortcuts_add_button,
                                _("Add the selected folder to the Bookmarks"));
 
   /* Remove bookmark button */
-
-  impl->browse_shortcuts_remove_button = button_new (impl,
-                                                    _("_Remove"),
-                                                    GTK_STOCK_REMOVE,
-                                                    FALSE,
-                                                    TRUE,
-                                                    G_CALLBACK (remove_bookmark_button_clicked_cb));
-  gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_remove_button, TRUE, TRUE, 0);
+  icon = g_themed_icon_new_with_default_fallbacks ("list-remove-symbolic");
+  impl->browse_shortcuts_remove_button = toolbutton_new (impl,
+                                                         icon,
+                                                         FALSE,
+                                                         TRUE,
+                                                         G_CALLBACK (remove_bookmark_button_clicked_cb));
+  g_object_unref (icon);
+  gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (impl->browse_shortcuts_remove_button), 1);
   gtk_widget_set_tooltip_text (impl->browse_shortcuts_remove_button,
                                _("Remove the selected bookmark"));
 
@@ -3791,7 +3713,7 @@ key_is_left_or_right (GdkEventKey *event)
 
 /* Handles key press events on the file list, so that we can trap Enter to
  * activate the default button on our own.  Also, checks to see if '/' has been
- * pressed.  See comment by tree_view_keybinding_cb() for more details.
+ * pressed.
  */
 static gboolean
 browse_files_key_press_event_cb (GtkWidget   *widget,
@@ -3987,23 +3909,21 @@ out:
 }
 
 static void
-file_list_drag_data_received_cb (GtkWidget          *widget,
-                                GdkDragContext     *context,
-                                gint                x,
-                                gint                y,
-                                GtkSelectionData   *selection_data,
-                                guint               info,
-                                guint               time_,
-                                gpointer            data)
+file_list_drag_data_received_cb (GtkWidget        *widget,
+                                 GdkDragContext   *context,
+                                 gint              x,
+                                 gint              y,
+                                 GtkSelectionData *selection_data,
+                                 guint             info,
+                                 guint             time_,
+                                 gpointer          data)
 {
   GtkFileChooserDefault *impl;
-  GtkFileChooser *chooser;
   gchar **uris;
   char *uri;
   GFile *file;
 
   impl = GTK_FILE_CHOOSER_DEFAULT (data);
-  chooser = GTK_FILE_CHOOSER (data);
 
   /* Allow only drags from other widgets; see bug #533891. */
   if (gtk_drag_get_source_widget (context) == widget)
@@ -4027,13 +3947,13 @@ file_list_drag_data_received_cb (GtkWidget          *widget,
       data->file = file;
 
       if (impl->file_list_drag_data_received_cancellable)
-       g_cancellable_cancel (impl->file_list_drag_data_received_cancellable);
+        g_cancellable_cancel (impl->file_list_drag_data_received_cancellable);
 
       impl->file_list_drag_data_received_cancellable =
-       _gtk_file_system_get_info (impl->file_system, file,
-                                  "standard::type",
-                                  file_list_drag_data_received_get_info_cb,
-                                  data);
+        _gtk_file_system_get_info (impl->file_system, file,
+                                   "standard::type",
+                                   file_list_drag_data_received_get_info_cb,
+                                   data);
     }
 
   g_signal_stop_emission_by_name (widget, "drag-data-received");
@@ -4213,7 +4133,6 @@ list_button_press_event_cb (GtkWidget             *widget,
                            GtkFileChooserDefault *impl)
 {
   static gboolean in_press = FALSE;
-  gboolean handled;
 
   if (in_press)
     return FALSE;
@@ -4222,7 +4141,7 @@ list_button_press_event_cb (GtkWidget             *widget,
     return FALSE;
 
   in_press = TRUE;
-  handled = gtk_widget_event (impl->browse_files_tree_view, (GdkEvent *) event);
+  gtk_widget_event (impl->browse_files_tree_view, (GdkEvent *) event);
   in_press = FALSE;
 
   file_list_popup_menu (impl, event);
@@ -4235,7 +4154,9 @@ typedef struct {
   gint model_column;
 } ColumnMap;
 
-/* Sets the sort column IDs for the file list based on the operation mode */
+/* Sets the sort column IDs for the file list; needs to be done whenever we
+ * change the model on the treeview.
+ */
 static void
 file_list_set_sort_column_ids (GtkFileChooserDefault *impl)
 {
@@ -4429,17 +4350,6 @@ create_file_list (GtkFileChooserDefault *impl)
   return swin;
 }
 
-static GtkWidget *
-create_path_bar (GtkFileChooserDefault *impl)
-{
-  GtkWidget *path_bar;
-
-  path_bar = g_object_new (GTK_TYPE_PATH_BAR, NULL);
-  _gtk_path_bar_set_file_system (GTK_PATH_BAR (path_bar), impl->file_system);
-
-  return path_bar;
-}
-
 /* Creates the widgets for the files/folders pane */
 static GtkWidget *
 file_pane_create (GtkFileChooserDefault *impl,
@@ -4462,6 +4372,7 @@ file_pane_create (GtkFileChooserDefault *impl,
 
   widget = create_file_list (impl);
   gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
+  gtk_size_group_add_widget (size_group, widget);
 
   /* Preview */
 
@@ -4478,171 +4389,23 @@ file_pane_create (GtkFileChooserDefault *impl,
   gtk_widget_show (widget);
   gtk_box_pack_end (GTK_BOX (impl->filter_combo_hbox), widget, FALSE, FALSE, 0);
 
-  gtk_size_group_add_widget (size_group, impl->filter_combo_hbox);
   gtk_box_pack_end (GTK_BOX (vbox), impl->filter_combo_hbox, FALSE, FALSE, 0);
 
   return vbox;
 }
 
-/* Callback used when the "Browse for more folders" expander is toggled */
-static void
-expander_changed_cb (GtkExpander           *expander,
-                    GParamSpec            *pspec,
-                    GtkFileChooserDefault *impl)
-{
-  impl->expand_folders = gtk_expander_get_expanded(GTK_EXPANDER (impl->save_expander));
-  update_appearance (impl);
-}
-
-/* Callback used when the selection changes in the save folder combo box */
-static void
-save_folder_combo_changed_cb (GtkComboBox           *combo,
-                             GtkFileChooserDefault *impl)
-{
-  GtkTreeIter iter;
-
-  if (impl->changing_folder)
-    return;
-
-  if (gtk_combo_box_get_active_iter (combo, &iter))
-    {
-      GtkTreeIter child_iter;
-      
-      gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model),
-                                                       &child_iter,
-                                                       &iter);
-      shortcuts_activate_iter (impl, &child_iter);
-    }
-}
-
 static void
-save_folder_update_tooltip (GtkComboBox           *combo,
-                           GtkFileChooserDefault *impl)
-{
-  GtkTreeIter iter;
-  gchar *tooltip;
-
-  tooltip = NULL;
-
-  if (gtk_combo_box_get_active_iter (combo, &iter))
-    {
-      GtkTreeIter child_iter;
-      gpointer col_data;
-      ShortcutType shortcut_type;
-
-      gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model),
-                                                        &child_iter,
-                                                        &iter);
-      gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &child_iter,
-                          SHORTCUTS_COL_DATA, &col_data,
-                          SHORTCUTS_COL_TYPE, &shortcut_type,
-                          -1);
-
-      if (shortcut_type == SHORTCUT_TYPE_FILE)
-        tooltip = g_file_get_parse_name (G_FILE (col_data));
-   }
-
-  gtk_widget_set_tooltip_text (GTK_WIDGET (combo), tooltip);
-  gtk_widget_set_has_tooltip (GTK_WIDGET (combo),
-                              gtk_widget_get_sensitive (GTK_WIDGET (combo)));
-  g_free (tooltip);
-}
-
-/* Filter function used to filter out the Search item and its separator.  
- * Used for the "Save in folder" combo box, so that these items do not appear in it.
- */
-static gboolean
-shortcuts_combo_filter_func (GtkTreeModel *model,
-                            GtkTreeIter  *iter,
-                            gpointer      data)
-{
-  GtkFileChooserDefault *impl;
-  GtkTreePath *tree_path;
-  gint *indices;
-  int idx;
-  gboolean retval;
-
-  impl = GTK_FILE_CHOOSER_DEFAULT (data);
-
-  g_assert (model == GTK_TREE_MODEL (impl->shortcuts_model));
-
-  tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), iter);
-  g_assert (tree_path != NULL);
-
-  indices = gtk_tree_path_get_indices (tree_path);
-
-  retval = TRUE;
-
-  if (impl->has_search)
-    {
-      idx = shortcuts_get_index (impl, SHORTCUTS_SEARCH);
-      if (idx == indices[0])
-        retval = FALSE;
-    }
-  
-  if (impl->has_recent)
-    {
-      idx = shortcuts_get_index (impl, SHORTCUTS_RECENT);
-      if (idx == indices[0])
-        retval = FALSE;
-      else
-        {
-          idx = shortcuts_get_index (impl, SHORTCUTS_RECENT_SEPARATOR);
-          if (idx == indices[0])
-            retval = FALSE;
-        }
-     }
-
-  gtk_tree_path_free (tree_path);
-
-  return retval;
- }
-
-/* Creates the combo box with the save folders */
-static GtkWidget *
-save_folder_combo_create (GtkFileChooserDefault *impl)
+location_entry_create (GtkFileChooserDefault *impl)
 {
-  GtkWidget *combo;
-  GtkCellRenderer *cell;
-
-  impl->shortcuts_combo_filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->shortcuts_model), NULL);
-  gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model),
-                                         shortcuts_combo_filter_func,
-                                         impl,
-                                         NULL);
-
-  combo = g_object_new (GTK_TYPE_COMBO_BOX,
-                       "model", impl->shortcuts_combo_filter_model,
-                       "focus-on-click", FALSE,
-                        NULL);
-  gtk_widget_show (combo);
-
-  cell = gtk_cell_renderer_pixbuf_new ();
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE);
-  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
-                                 "pixbuf", SHORTCUTS_COL_PIXBUF,
-                                 "visible", SHORTCUTS_COL_PIXBUF_VISIBLE,
-                                 "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE,
-                                 NULL);
-
-  cell = gtk_cell_renderer_text_new ();
-  g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
-  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
-                                 "text", SHORTCUTS_COL_NAME,
-                                 "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE,
-                                 NULL);
-
-  gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo),
-                                       shortcuts_row_separator_func,
-                                       NULL, NULL);
+  if (!impl->location_entry)
+    impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
 
-  g_signal_connect (combo, "changed",
-                   G_CALLBACK (save_folder_combo_changed_cb), impl);
-  g_signal_connect (combo, "changed",
-                   G_CALLBACK (save_folder_update_tooltip), impl);
-
-  return combo;
+  _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
+                                          impl->file_system);
+  _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->local_only);
+  _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
+  gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45);
+  gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
 }
 
 /* Creates the widgets specific to Save mode */
@@ -4650,9 +4413,7 @@ static void
 save_widgets_create (GtkFileChooserDefault *impl)
 {
   GtkWidget *vbox;
-  GtkWidget *table;
   GtkWidget *widget;
-  GtkWidget *alignment;
 
   if (impl->save_widgets != NULL)
     return;
@@ -4661,17 +4422,18 @@ save_widgets_create (GtkFileChooserDefault *impl)
 
   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
 
-  table = gtk_table_new (2, 2, FALSE);
-  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
-  gtk_widget_show (table);
-  gtk_table_set_row_spacings (GTK_TABLE (table), 12);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+  impl->save_widgets_table = gtk_table_new (2, 2, FALSE);
+  gtk_box_pack_start (GTK_BOX (vbox), impl->save_widgets_table, FALSE, FALSE, 0);
+  gtk_widget_show (impl->save_widgets_table);
+  gtk_table_set_row_spacings (GTK_TABLE (impl->save_widgets_table), 12);
+  gtk_table_set_col_spacings (GTK_TABLE (impl->save_widgets_table), 12);
 
   /* Label */
 
   widget = gtk_label_new_with_mnemonic (_("_Name:"));
-  gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
-  gtk_table_attach (GTK_TABLE (table), widget,
+  gtk_widget_set_halign (widget, GTK_ALIGN_START);
+  gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
+  gtk_table_attach (GTK_TABLE (impl->save_widgets_table), widget,
                    0, 1, 0, 1,
                    GTK_FILL, GTK_FILL,
                    0, 0);
@@ -4679,13 +4441,8 @@ save_widgets_create (GtkFileChooserDefault *impl)
 
   /* Location entry */
 
-  impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
-  _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
-                                          impl->file_system);
-  _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->local_only);
-  gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45);
-  gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
-  gtk_table_attach (GTK_TABLE (table), impl->location_entry,
+  location_entry_create (impl);
+  gtk_table_attach (GTK_TABLE (impl->save_widgets_table), impl->location_entry,
                    1, 2, 0, 1,
                    GTK_EXPAND | GTK_FILL, 0,
                    0, 0);
@@ -4694,31 +4451,14 @@ save_widgets_create (GtkFileChooserDefault *impl)
 
   /* Folder combo */
   impl->save_folder_label = gtk_label_new (NULL);
-  gtk_misc_set_alignment (GTK_MISC (impl->save_folder_label), 0.0, 0.5);
-  gtk_table_attach (GTK_TABLE (table), impl->save_folder_label,
+  gtk_widget_set_halign (impl->save_folder_label, GTK_ALIGN_START);
+  gtk_widget_set_valign (impl->save_folder_label, GTK_ALIGN_CENTER);
+  gtk_table_attach (GTK_TABLE (impl->save_widgets_table), impl->save_folder_label,
                    0, 1, 1, 2,
                    GTK_FILL, GTK_FILL,
                    0, 0);
   gtk_widget_show (impl->save_folder_label);
 
-  impl->save_folder_combo = save_folder_combo_create (impl);
-  gtk_table_attach (GTK_TABLE (table), impl->save_folder_combo,
-                   1, 2, 1, 2,
-                   GTK_EXPAND | GTK_FILL, GTK_FILL,
-                   0, 0);
-  gtk_label_set_mnemonic_widget (GTK_LABEL (impl->save_folder_label), impl->save_folder_combo);
-
-  /* Expander */
-  alignment = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
-  gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
-
-  impl->save_expander = gtk_expander_new_with_mnemonic (_("_Browse for other folders"));
-  gtk_container_add (GTK_CONTAINER (alignment), impl->save_expander);
-  g_signal_connect (impl->save_expander, "notify::expanded",
-                   G_CALLBACK (expander_changed_cb),
-                   impl);
-  gtk_widget_show_all (alignment);
-
   impl->save_widgets = vbox;
   gtk_box_pack_start (GTK_BOX (impl), impl->save_widgets, FALSE, FALSE, 0);
   gtk_box_reorder_child (GTK_BOX (impl), impl->save_widgets, 0);
@@ -4734,10 +4474,9 @@ save_widgets_destroy (GtkFileChooserDefault *impl)
 
   gtk_widget_destroy (impl->save_widgets);
   impl->save_widgets = NULL;
+  impl->save_widgets_table = NULL;
   impl->location_entry = NULL;
   impl->save_folder_label = NULL;
-  impl->save_folder_combo = NULL;
-  impl->save_expander = NULL;
 }
 
 /* Turns on the path bar widget.  Can be called even if we are already in that
@@ -4755,53 +4494,6 @@ location_switch_to_path_bar (GtkFileChooserDefault *impl)
   gtk_widget_hide (impl->location_entry_box);
 }
 
-/* Sets the full path of the current folder as the text in the location entry. */
-static void
-location_entry_set_initial_text (GtkFileChooserDefault *impl)
-{
-  gchar *text, *filename;
-
-  if (!impl->current_folder)
-    return;
-
-  filename = g_file_get_path (impl->current_folder);
-
-  if (filename)
-    {
-      text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
-      g_free (filename);
-    }
-  else
-    text = g_file_get_uri (impl->current_folder);
-
-  if (text)
-    {
-      gboolean need_slash;
-      int len;
-
-      len = strlen (text);
-      need_slash = (text[len - 1] != G_DIR_SEPARATOR);
-
-      if (need_slash)
-       {
-         char *slash_text;
-
-         slash_text = g_new (char, len + 2);
-         strcpy (slash_text, text);
-         slash_text[len] = G_DIR_SEPARATOR;
-         slash_text[len + 1] = 0;
-
-         g_free (text);
-         text = slash_text;
-       }
-
-      _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), text);
-      g_free (text);
-    }
-
-  g_free (filename);
-}
-
 /* Turns on the location entry.  Can be called even if we are already in that
  * mode.
  */
@@ -4817,7 +4509,10 @@ location_switch_to_filename_entry (GtkFileChooserDefault *impl)
     return;
 
   if (impl->location_entry)
-    gtk_widget_destroy (impl->location_entry);
+    {
+      gtk_widget_destroy (impl->location_entry);
+      impl->location_entry = NULL;
+    }
 
   /* Box */
 
@@ -4825,12 +4520,7 @@ location_switch_to_filename_entry (GtkFileChooserDefault *impl)
 
   /* Entry */
 
-  impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
-  _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
-                                          impl->file_system);
-  gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
-  _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
-
+  location_entry_create (impl);
   gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_entry, TRUE, TRUE, 0);
   gtk_label_set_mnemonic_widget (GTK_LABEL (impl->location_label), impl->location_entry);
 
@@ -4988,70 +4678,242 @@ location_button_create (GtkFileChooserDefault *impl)
   atk_object_set_name (gtk_widget_get_accessible (impl->location_button), str);
 }
 
-/* Creates the main hpaned with the widgets shared by Open and Save mode */
-static GtkWidget *
-browse_widgets_create (GtkFileChooserDefault *impl)
+typedef enum {
+  PATH_BAR_FOLDER_PATH,
+  PATH_BAR_SELECT_A_FOLDER,
+  PATH_BAR_ERROR_NO_FILENAME,
+  PATH_BAR_ERROR_NO_FOLDER,
+  PATH_BAR_RECENTLY_USED,
+  PATH_BAR_SEARCH
+} PathBarMode;
+
+/* Creates the info bar for informational messages or warnings, with its icon and label */
+static void
+info_bar_create (GtkFileChooserDefault *impl)
 {
-  GtkWidget *vbox;
-  GtkWidget *hpaned;
-  GtkWidget *widget;
-  GtkSizeGroup *size_group;
+  GtkWidget *content_area;
 
-  /* size group is used by the [+][-] buttons and the filter combo */
-  size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
-  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  impl->browse_select_a_folder_info_bar = gtk_info_bar_new ();
+  impl->browse_select_a_folder_icon = gtk_image_new_from_stock (GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
+  impl->browse_select_a_folder_label = gtk_label_new (NULL);
 
-  /* Location widgets */
-  impl->browse_path_bar_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-  gtk_box_pack_start (GTK_BOX (vbox), impl->browse_path_bar_hbox, FALSE, FALSE, 0);
-  gtk_widget_show (impl->browse_path_bar_hbox);
+  content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (impl->browse_select_a_folder_info_bar));
 
-  /* Size group that allows the path bar to be the same size between modes */
-  impl->browse_path_bar_size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
-  gtk_size_group_set_ignore_hidden (impl->browse_path_bar_size_group, FALSE);
+  gtk_box_pack_start (GTK_BOX (content_area), impl->browse_select_a_folder_icon, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (content_area), impl->browse_select_a_folder_label, FALSE, FALSE, 0);
 
-  /* Location button */
+  gtk_widget_show (impl->browse_select_a_folder_icon);
+  gtk_widget_show (impl->browse_select_a_folder_label);
+}
 
-  location_button_create (impl);
-  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->location_button, FALSE, FALSE, 0);
-  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->location_button);
+/* Sets the info bar to show the appropriate informational or warning message */
+static void
+info_bar_set (GtkFileChooserDefault *impl, PathBarMode mode)
+{
+  char *str;
+  gboolean free_str;
+  GtkMessageType message_type;
 
-  /* Path bar */
+  free_str = FALSE;
+
+  switch (mode)
+    {
+    case PATH_BAR_SELECT_A_FOLDER:
+      str = g_strconcat ("<i>", _("Please select a folder below"), "</i>", NULL);
+      free_str = TRUE;
+      message_type = GTK_MESSAGE_OTHER;
+      break;
 
-  impl->browse_path_bar = create_path_bar (impl);
+    case PATH_BAR_ERROR_NO_FILENAME:
+      str = _("Please type a file name");
+      message_type = GTK_MESSAGE_WARNING;
+      break;
+
+    case PATH_BAR_ERROR_NO_FOLDER:
+      str = _("Please select a folder below");
+      message_type = GTK_MESSAGE_WARNING;
+      break;
+
+    default:
+      g_assert_not_reached ();
+      return;
+    }
+
+  gtk_info_bar_set_message_type (GTK_INFO_BAR (impl->browse_select_a_folder_info_bar), message_type);
+  gtk_image_set_from_stock (GTK_IMAGE (impl->browse_select_a_folder_icon),
+                           (message_type == GTK_MESSAGE_WARNING) ? GTK_STOCK_DIALOG_WARNING : GTK_STOCK_DIRECTORY,
+                           GTK_ICON_SIZE_MENU);
+  gtk_label_set_markup (GTK_LABEL (impl->browse_select_a_folder_label), str);
+
+  if (free_str)
+    g_free (str);
+}
+
+/* Creates the icon and label used to show that the file chooser is in Search or Recently-used mode */
+static void
+special_mode_widgets_create (GtkFileChooserDefault *impl)
+{
+  impl->browse_special_mode_icon = gtk_image_new ();
+  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_special_mode_icon);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_special_mode_icon, FALSE, FALSE, 0);
+
+  impl->browse_special_mode_label = gtk_label_new (NULL);
+  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_special_mode_label);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_special_mode_label, FALSE, FALSE, 0);
+}
+
+/* Creates the path bar's container and eveyrthing that goes in it: location button, pathbar, info bar, and Create Folder button */
+static void
+path_bar_widgets_create (GtkFileChooserDefault *impl)
+{
+  /* Location widgets - note browse_path_bar_hbox is packed in the right place until switch_path_bar() */
+  impl->browse_path_bar_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_widget_show (impl->browse_path_bar_hbox);
+
+  /* Size group that allows the path bar to be the same size between modes */
+  impl->browse_path_bar_size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+  gtk_size_group_set_ignore_hidden (impl->browse_path_bar_size_group, FALSE);
+
+  /* Location button */
+  location_button_create (impl);
+  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->location_button);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->location_button, FALSE, FALSE, 0);
+
+  /* Path bar */
+  impl->browse_path_bar = g_object_new (GTK_TYPE_PATH_BAR, NULL);
+  _gtk_path_bar_set_file_system (GTK_PATH_BAR (impl->browse_path_bar), impl->file_system);
   g_signal_connect (impl->browse_path_bar, "path-clicked", G_CALLBACK (path_bar_clicked), impl);
-  gtk_widget_show_all (impl->browse_path_bar);
-  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_path_bar, TRUE, TRUE, 0);
+
   gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_path_bar);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_path_bar, TRUE, TRUE, 0);
+
+  /* Info bar */
+  info_bar_create (impl);
+  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_select_a_folder_info_bar);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_select_a_folder_info_bar, TRUE, TRUE, 0);
+
+  /* Widgets for special modes (recently-used in Open mode, Search mode) */
+  special_mode_widgets_create (impl);
 
   /* Create Folder */
   impl->browse_new_folder_button = gtk_button_new_with_mnemonic (_("Create Fo_lder"));
   g_signal_connect (impl->browse_new_folder_button, "clicked",
                    G_CALLBACK (new_folder_button_clicked), impl);
+  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_new_folder_button);
   gtk_box_pack_end (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_new_folder_button, FALSE, FALSE, 0);
+}
+
+/* Sets the path bar's mode to show a label, the actual folder path, or a
+ * warning message.  You may call this function with PATH_BAR_ERROR_* directly
+ * if the pathbar is already showing the widgets you expect; otherwise, call
+ * path_bar_update() instead to set the appropriate widgets automatically.
+ */
+static void
+path_bar_set_mode (GtkFileChooserDefault *impl, PathBarMode mode)
+{
+  gboolean path_bar_visible            = FALSE;
+  gboolean special_mode_widgets_visible = FALSE;
+  gboolean info_bar_visible            = FALSE;
+  gboolean create_folder_visible        = FALSE;
+
+  char *tmp;
+
+  switch (mode)
+    {
+    case PATH_BAR_FOLDER_PATH:
+      path_bar_visible = TRUE;
+      break;
+
+    case PATH_BAR_SELECT_A_FOLDER:
+    case PATH_BAR_ERROR_NO_FILENAME:
+    case PATH_BAR_ERROR_NO_FOLDER:
+      info_bar_set (impl, mode);
+      info_bar_visible = TRUE;
+      break;
+
+    case PATH_BAR_RECENTLY_USED:
+      gtk_image_set_from_icon_name (GTK_IMAGE (impl->browse_special_mode_icon), "document-open-recent", GTK_ICON_SIZE_BUTTON);
+
+      tmp = g_strdup_printf ("<b>%s</b>", _("Recently Used"));
+      gtk_label_set_markup (GTK_LABEL (impl->browse_special_mode_label), tmp);
+      g_free (tmp);
+
+      special_mode_widgets_visible = TRUE;
+      break;
+
+    case PATH_BAR_SEARCH:
+      gtk_image_set_from_stock (GTK_IMAGE (impl->browse_special_mode_icon), GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON);
+
+      tmp = g_strdup_printf ("<b>%s</b>", _("Search:"));
+      gtk_label_set_markup (GTK_LABEL (impl->browse_special_mode_label), tmp);
+      g_free (tmp);
+
+      special_mode_widgets_visible = TRUE;
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  gtk_widget_set_visible (impl->browse_path_bar,                       path_bar_visible);
+  gtk_widget_set_visible (impl->browse_special_mode_icon,              special_mode_widgets_visible);
+  gtk_widget_set_visible (impl->browse_special_mode_label,             special_mode_widgets_visible);
+  gtk_widget_set_visible (impl->browse_select_a_folder_info_bar,       info_bar_visible);
+
+  if (path_bar_visible)
+    {
+      if (impl->create_folders
+         && impl->action != GTK_FILE_CHOOSER_ACTION_OPEN
+         && impl->operation_mode != OPERATION_MODE_RECENT)
+       create_folder_visible = TRUE;
+    }
+
+  gtk_widget_set_visible (impl->browse_new_folder_button,              create_folder_visible);
+}
+
+/* Creates the main hpaned with the widgets shared by Open and Save mode */
+static void
+browse_widgets_create (GtkFileChooserDefault *impl)
+{
+  GtkWidget *hpaned;
+  GtkWidget *widget;
+  GtkSizeGroup *size_group;
+
+  impl->browse_widgets_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  gtk_box_pack_start (GTK_BOX (impl), impl->browse_widgets_box, TRUE, TRUE, 0);
+  gtk_widget_show (impl->browse_widgets_box);
+
+  impl->browse_header_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  gtk_box_pack_start (GTK_BOX (impl->browse_widgets_box), impl->browse_header_box, FALSE, FALSE, 0);
+  gtk_widget_show (impl->browse_header_box);
+
+  /* Path bar, info bar, and their respective machinery - the browse_path_bar_hbox will get packed elsewhere */
+  path_bar_widgets_create (impl);
 
   /* Box for the location label and entry */
 
   impl->location_entry_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-  gtk_box_pack_start (GTK_BOX (vbox), impl->location_entry_box, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (impl->browse_header_box), impl->location_entry_box, FALSE, FALSE, 0);
 
   impl->location_label = gtk_label_new_with_mnemonic (_("_Location:"));
   gtk_widget_show (impl->location_label);
   gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_label, FALSE, FALSE, 0);
 
+  /* size group is used by the scrolled windows of the panes */
+  size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+
   /* Paned widget */
+
   hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
   gtk_widget_show (hpaned);
-  gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (impl->browse_widgets_box), hpaned, TRUE, TRUE, 0);
 
   widget = shortcuts_pane_create (impl, size_group);
   gtk_paned_pack1 (GTK_PANED (hpaned), widget, FALSE, FALSE);
   widget = file_pane_create (impl, size_group);
   gtk_paned_pack2 (GTK_PANED (hpaned), widget, TRUE, FALSE);
-
+  gtk_paned_set_position (GTK_PANED (hpaned), 148);
   g_object_unref (size_group);
-
-  return vbox;
 }
 
 static GObject*
@@ -5077,11 +4939,12 @@ gtk_file_chooser_default_constructor (GType                  type,
   shortcuts_model_create (impl);
 
   /* The browse widgets */
-  impl->browse_widgets = browse_widgets_create (impl);
-  gtk_box_pack_start (GTK_BOX (impl), impl->browse_widgets, TRUE, TRUE, 0);
+  browse_widgets_create (impl);
 
   /* Alignment to hold extra widget */
-  impl->extra_align = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
+  impl->extra_align = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_set_halign (impl->extra_align, GTK_ALIGN_START);
+  gtk_widget_set_valign (impl->extra_align, GTK_ALIGN_CENTER);
   gtk_box_pack_start (GTK_BOX (impl), impl->extra_align, FALSE, FALSE, 0);
 
   gtk_widget_pop_composite_child ();
@@ -5222,6 +5085,250 @@ unset_file_system_backend (GtkFileChooserDefault *impl)
   impl->file_system = NULL;
 }
 
+/* Saves the widgets around the pathbar so they can be reparented later
+ * in the correct place.  This function must be called paired with
+ * restore_path_bar().
+ */
+static void
+save_path_bar (GtkFileChooserDefault *impl)
+{
+  GtkWidget *parent;
+
+  g_object_ref (impl->browse_path_bar_hbox);
+
+  parent = gtk_widget_get_parent (impl->browse_path_bar_hbox);
+  if (parent)
+    gtk_container_remove (GTK_CONTAINER (parent), impl->browse_path_bar_hbox);
+}
+
+/* Reparents the path bar and the "Create folder" button to the right place:
+ * Above the file list in Open mode, or to the right of the "Save in folder:"
+ * label in Save mode.  The save_path_bar() function must be called before this
+ * one.
+ */
+static void
+restore_path_bar (GtkFileChooserDefault *impl)
+{
+  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
+      || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+    {
+      gtk_box_pack_start (GTK_BOX (impl->browse_header_box), impl->browse_path_bar_hbox, FALSE, FALSE, 0);
+      gtk_box_reorder_child (GTK_BOX (impl->browse_header_box), impl->browse_path_bar_hbox, 0);
+    }
+  else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+          || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+    {
+      gtk_table_attach (GTK_TABLE (impl->save_widgets_table), impl->browse_path_bar_hbox,
+                       1, 2, 1, 2,
+                       GTK_EXPAND | GTK_FILL, GTK_FILL,
+                       0, 0);
+      gtk_label_set_mnemonic_widget (GTK_LABEL (impl->save_folder_label), impl->browse_path_bar);
+    }
+  else
+    g_assert_not_reached ();
+
+  g_object_unref (impl->browse_path_bar_hbox);
+}
+
+/* Takes the folder stored in a row in the recent_model, and puts it in the pathbar */
+static void
+put_recent_folder_in_pathbar (GtkFileChooserDefault *impl, GtkTreeIter *iter)
+{
+  GFile *file;
+
+  gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), iter,
+                     MODEL_COL_FILE, &file,
+                     -1);
+  _gtk_path_bar_set_file (GTK_PATH_BAR (impl->browse_path_bar), file, FALSE, NULL); /* NULL-GError */
+  g_object_unref (file);
+}
+
+/* Sets the pathbar in the appropriate mode according to the current operation mode and action.  This is the central function for
+ * dealing with the pathbar's widgets; as long as impl->action and impl->operation_mode are set correctly, then calling this
+ * function will update all the pathbar's widgets.
+ */
+static void
+path_bar_update (GtkFileChooserDefault *impl)
+{
+  PathBarMode mode;
+
+  switch (impl->operation_mode)
+    {
+    case OPERATION_MODE_BROWSE:
+      mode = PATH_BAR_FOLDER_PATH;
+      break;
+
+    case OPERATION_MODE_RECENT:
+      if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+       {
+         GtkTreeSelection *selection;
+         gboolean have_selected;
+         GtkTreeIter iter;
+
+         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+
+         /* Save mode means single-selection mode, so the following is valid */
+         have_selected = gtk_tree_selection_get_selected (selection, NULL, &iter);
+
+         if (have_selected)
+           {
+             mode = PATH_BAR_FOLDER_PATH;
+             put_recent_folder_in_pathbar (impl, &iter);
+           }
+         else
+           mode = PATH_BAR_SELECT_A_FOLDER;
+       }
+      else
+       mode = PATH_BAR_RECENTLY_USED;
+
+      break;
+
+    case OPERATION_MODE_SEARCH:
+      mode = PATH_BAR_SEARCH;
+      break;
+
+    default:
+      g_assert_not_reached ();
+      return;
+    }
+
+  path_bar_set_mode (impl, mode);
+}
+
+static void
+operation_mode_discard_search_widgets (GtkFileChooserDefault *impl)
+{
+  if (impl->search_hbox)
+    {
+      gtk_widget_destroy (impl->search_hbox);
+
+      impl->search_hbox = NULL;
+      impl->search_entry = NULL;
+    }
+}
+
+/* Stops running operations like populating the browse model, searches, and the recent-files model */
+static void
+operation_mode_stop (GtkFileChooserDefault *impl, OperationMode mode)
+{
+  switch (mode)
+    {
+    case OPERATION_MODE_BROWSE:
+      stop_loading_and_clear_list_model (impl, TRUE);
+      break;
+
+    case OPERATION_MODE_SEARCH:
+      search_stop_searching (impl, FALSE);
+      search_clear_model (impl, TRUE);
+
+      operation_mode_discard_search_widgets (impl);
+      break;
+
+    case OPERATION_MODE_RECENT:
+      recent_stop_loading (impl);
+      recent_clear_model (impl, TRUE);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+operation_mode_set_browse (GtkFileChooserDefault *impl)
+{
+  path_bar_update (impl);
+
+  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+    {
+      gtk_widget_show (impl->location_button);
+      location_mode_set (impl, impl->location_mode, TRUE);
+
+      if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
+       gtk_widget_show (impl->location_entry_box);
+    }
+}
+
+static void
+operation_mode_set_search (GtkFileChooserDefault *impl)
+{
+  g_assert (impl->search_hbox == NULL);
+  g_assert (impl->search_entry == NULL);
+  g_assert (impl->search_model == NULL);
+
+  search_setup_widgets (impl);
+}
+
+static void
+operation_mode_set_recent (GtkFileChooserDefault *impl)
+{
+  path_bar_update (impl);
+
+  /* Hide the location widgets temporarily */
+  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+    {
+      gtk_widget_hide (impl->location_button);
+      gtk_widget_hide (impl->location_entry_box);
+    }
+
+  recent_start_loading (impl);
+}
+
+/* Sometimes we need to frob the selection in the shortcuts list manually */
+static void
+shortcuts_select_item_without_activating (GtkFileChooserDefault *impl, int pos)
+{
+  GtkTreeSelection *selection;
+  GtkTreePath *path;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
+
+  g_signal_handlers_block_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
+
+  path = gtk_tree_path_new_from_indices (pos, -1);
+  gtk_tree_selection_select_path (selection, path);
+  gtk_tree_path_free (path);
+
+  g_signal_handlers_unblock_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
+}
+
+static void
+operation_mode_set (GtkFileChooserDefault *impl, OperationMode mode)
+{
+  ShortcutsIndex shortcut_to_select;
+
+  operation_mode_stop (impl, impl->operation_mode);
+
+  impl->operation_mode = mode;
+
+  switch (impl->operation_mode)
+    {
+    case OPERATION_MODE_BROWSE:
+      operation_mode_set_browse (impl);
+      shortcut_to_select = SHORTCUTS_CURRENT_FOLDER;
+      break;
+
+    case OPERATION_MODE_SEARCH:
+      operation_mode_set_search (impl);
+      shortcut_to_select = SHORTCUTS_SEARCH;
+      break;
+
+    case OPERATION_MODE_RECENT:
+      operation_mode_set_recent (impl);
+      shortcut_to_select = SHORTCUTS_RECENT;
+      break;
+
+    default:
+      g_assert_not_reached ();
+      return;
+    }
+
+  if (shortcut_to_select != SHORTCUTS_CURRENT_FOLDER)
+    shortcuts_select_item_without_activating (impl, shortcuts_get_index (impl, shortcut_to_select));
+}
+
 /* This function is basically a do_all function.
  *
  * It sets the visibility on all the widgets based on the current state, and
@@ -5230,6 +5337,8 @@ unset_file_system_backend (GtkFileChooserDefault *impl)
 static void
 update_appearance (GtkFileChooserDefault *impl)
 {
+  save_path_bar (impl);
+
   if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
       impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
     {
@@ -5245,21 +5354,6 @@ update_appearance (GtkFileChooserDefault *impl)
 
       gtk_label_set_text_with_mnemonic (GTK_LABEL (impl->save_folder_label), text);
 
-      if (gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander)))
-       {
-         gtk_widget_set_sensitive (impl->save_folder_label, FALSE);
-         gtk_widget_set_sensitive (impl->save_folder_combo, FALSE);
-         gtk_widget_set_has_tooltip (impl->save_folder_combo, FALSE);
-         gtk_widget_show (impl->browse_widgets);
-       }
-      else
-       {
-         gtk_widget_set_sensitive (impl->save_folder_label, TRUE);
-         gtk_widget_set_sensitive (impl->save_folder_combo, TRUE);
-         gtk_widget_set_has_tooltip (impl->save_folder_combo, TRUE);
-         gtk_widget_hide (impl->browse_widgets);
-       }
-
       if (impl->select_multiple)
        {
          g_warning ("Save mode cannot be set in conjunction with multiple selection mode.  "
@@ -5272,17 +5366,14 @@ update_appearance (GtkFileChooserDefault *impl)
     {
       gtk_widget_show (impl->location_button);
       save_widgets_destroy (impl);
-      gtk_widget_show (impl->browse_widgets);
       location_mode_set (impl, impl->location_mode, TRUE);
     }
 
   if (impl->location_entry)
     _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
 
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || !impl->create_folders)
-    gtk_widget_hide (impl->browse_new_folder_button);
-  else
-    gtk_widget_show (impl->browse_new_folder_button);
+  restore_path_bar (impl);
+  path_bar_update (impl);
 
   /* This *is* needed; we need to redraw the file list because the "sensitivity"
    * of files may change depending whether we are in a file or folder-only mode.
@@ -5465,33 +5556,11 @@ gtk_file_chooser_default_get_property (GObject    *object,
     }
 }
 
-/* Removes the settings signal handler.  It's safe to call multiple times */
-static void
-remove_settings_signal (GtkFileChooserDefault *impl,
-                       GdkScreen             *screen)
-{
-  if (impl->settings_signal_id)
-    {
-      GtkSettings *settings;
-
-      settings = gtk_settings_get_for_screen (screen);
-      g_signal_handler_disconnect (settings,
-                                  impl->settings_signal_id);
-      impl->settings_signal_id = 0;
-    }
-}
-
+/* This cancels everything that may be going on in the background. */
 static void
-gtk_file_chooser_default_dispose (GObject *object)
+cancel_all_operations (GtkFileChooserDefault *impl)
 {
   GSList *l;
-  GtkFileChooserDefault *impl = (GtkFileChooserDefault *) object;
-
-  if (impl->extra_widget)
-    {
-      g_object_unref (impl->extra_widget);
-      impl->extra_widget = NULL;
-    }
 
   pending_select_files_free (impl);
 
@@ -5541,27 +5610,57 @@ gtk_file_chooser_default_dispose (GObject *object)
       impl->update_current_folder_cancellable = NULL;
     }
 
-  if (impl->should_respond_get_info_cancellable)
-    {
-      g_cancellable_cancel (impl->should_respond_get_info_cancellable);
-      impl->should_respond_get_info_cancellable = NULL;
-    }
+  if (impl->should_respond_get_info_cancellable)
+    {
+      g_cancellable_cancel (impl->should_respond_get_info_cancellable);
+      impl->should_respond_get_info_cancellable = NULL;
+    }
+
+  if (impl->update_from_entry_cancellable)
+    {
+      g_cancellable_cancel (impl->update_from_entry_cancellable);
+      impl->update_from_entry_cancellable = NULL;
+    }
+
+  if (impl->shortcuts_activate_iter_cancellable)
+    {
+      g_cancellable_cancel (impl->shortcuts_activate_iter_cancellable);
+      impl->shortcuts_activate_iter_cancellable = NULL;
+    }
+
+  search_stop_searching (impl, TRUE);
+  recent_stop_loading (impl);
+}
+
+/* Removes the settings signal handler.  It's safe to call multiple times */
+static void
+remove_settings_signal (GtkFileChooserDefault *impl,
+                       GdkScreen             *screen)
+{
+  if (impl->settings_signal_id)
+    {
+      GtkSettings *settings;
+
+      settings = gtk_settings_get_for_screen (screen);
+      g_signal_handler_disconnect (settings,
+                                  impl->settings_signal_id);
+      impl->settings_signal_id = 0;
+    }
+}
+
+static void
+gtk_file_chooser_default_dispose (GObject *object)
+{
+  GtkFileChooserDefault *impl = (GtkFileChooserDefault *) object;
 
-  if (impl->update_from_entry_cancellable)
-    {
-      g_cancellable_cancel (impl->update_from_entry_cancellable);
-      impl->update_from_entry_cancellable = NULL;
-    }
+  cancel_all_operations (impl);
 
-  if (impl->shortcuts_activate_iter_cancellable)
+  if (impl->extra_widget)
     {
-      g_cancellable_cancel (impl->shortcuts_activate_iter_cancellable);
-      impl->shortcuts_activate_iter_cancellable = NULL;
+      g_object_unref (impl->extra_widget);
+      impl->extra_widget = NULL;
     }
 
-  search_stop_searching (impl, TRUE);
-  recent_stop_loading (impl);
-
   remove_settings_signal (impl, gtk_widget_get_screen (GTK_WIDGET (impl)));
 
   G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->dispose (object);
@@ -5747,12 +5846,8 @@ gtk_file_chooser_default_screen_changed (GtkWidget *widget,
 
 static void
 gtk_file_chooser_default_size_allocate (GtkWidget     *widget,
-                                       GtkAllocation *allocation)
+                                        GtkAllocation *allocation)
 {
-  GtkFileChooserDefault *impl;
-
-  impl = GTK_FILE_CHOOSER_DEFAULT (widget);
-
   GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->size_allocate (widget, allocation);
 }
 
@@ -5762,6 +5857,7 @@ set_sort_column (GtkFileChooserDefault *impl)
   GtkTreeSortable *sortable;
 
   sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view)));
+
   /* can happen when we're still populating the model */
   if (sortable == NULL)
     return;
@@ -5787,14 +5883,12 @@ settings_load (GtkFileChooserDefault *impl)
 {
   LocationMode location_mode;
   gboolean show_hidden;
-  gboolean expand_folders;
   gboolean show_size_column;
   gint sort_column;
   GtkSortType sort_order;
 
   settings_ensure (impl);
 
-  expand_folders = g_settings_get_boolean (impl->settings, SETTINGS_KEY_EXPAND_FOLDERS);
   location_mode = g_settings_get_enum (impl->settings, SETTINGS_KEY_LOCATION_MODE);
   show_hidden = g_settings_get_boolean (impl->settings, SETTINGS_KEY_SHOW_HIDDEN);
   show_size_column = g_settings_get_boolean (impl->settings, SETTINGS_KEY_SHOW_SIZE_COLUMN);
@@ -5805,10 +5899,6 @@ settings_load (GtkFileChooserDefault *impl)
 
   gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (impl), show_hidden);
 
-  impl->expand_folders = expand_folders;
-  if (impl->save_expander)
-    gtk_expander_set_expanded (GTK_EXPANDER (impl->save_expander), expand_folders);
-
   impl->show_size_column = show_size_column;
   gtk_tree_view_column_set_visible (impl->list_size_column, show_size_column);
 
@@ -5826,14 +5916,6 @@ save_dialog_geometry (GtkFileChooserDefault *impl)
   GtkWindow *toplevel;
   int x, y, width, height;
 
-  /* We don't save the geometry in non-expanded "save" mode, so that the "little
-   * dialog" won't make future Open dialogs too small.
-   */
-  if (!(impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
-       || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
-       || impl->expand_folders))
-    return;
-
   toplevel = get_toplevel (GTK_WIDGET (impl));
 
   if (!(toplevel && GTK_IS_FILE_CHOOSER_DIALOG (toplevel)))
@@ -5849,10 +5931,25 @@ save_dialog_geometry (GtkFileChooserDefault *impl)
 static void
 settings_save (GtkFileChooserDefault *impl)
 {
+  char *current_folder_uri;
+
   settings_ensure (impl);
 
+  /* Current folder */
+
+  if (impl->current_folder)
+    current_folder_uri = g_file_get_uri (impl->current_folder);
+  else
+    current_folder_uri = "";
+
+  g_settings_set_string (impl->settings, SETTINGS_KEY_LAST_FOLDER_URI, current_folder_uri);
+
+  if (impl->current_folder)
+    g_free (current_folder_uri);
+
+  /* All the other state */
+
   g_settings_set_enum (impl->settings, SETTINGS_KEY_LOCATION_MODE, impl->location_mode);
-  g_settings_set_boolean (impl->settings, SETTINGS_KEY_EXPAND_FOLDERS, impl->expand_folders);
   g_settings_set_boolean (impl->settings, SETTINGS_KEY_SHOW_HIDDEN,
                           gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl)));
   g_settings_set_boolean (impl->settings, SETTINGS_KEY_SHOW_SIZE_COLUMN, impl->show_size_column);
@@ -5881,12 +5978,34 @@ gtk_file_chooser_default_realize (GtkWidget *widget)
   emit_default_size_changed (impl);
 }
 
+static GFile *
+get_file_for_last_folder_opened (GtkFileChooserDefault *impl)
+{
+  char *last_folder_uri;
+  GFile *file;
+
+  settings_ensure (impl);
+
+  last_folder_uri = g_settings_get_string (impl->settings, SETTINGS_KEY_LAST_FOLDER_URI);
+
+  /* If no last folder is set, we use the user's home directory, since
+   * this is the starting point for most documents.
+   */
+  if (last_folder_uri[0] == '\0')
+    file = g_file_new_for_path (g_get_home_dir ());
+  else
+    file = g_file_new_for_uri (last_folder_uri);
+
+  g_free (last_folder_uri);
+
+  return file;
+}
+
 /* GtkWidget::map method */
 static void
 gtk_file_chooser_default_map (GtkWidget *widget)
 {
   GtkFileChooserDefault *impl;
-  char *current_working_dir;
 
   profile_start ("start", NULL);
 
@@ -5899,13 +6018,7 @@ gtk_file_chooser_default_map (GtkWidget *widget)
       switch (impl->reload_state)
         {
         case RELOAD_EMPTY:
-          /* The user didn't explicitly give us a folder to
-           * display, so we'll use the cwd
-           */
-          current_working_dir = g_get_current_dir ();
-          gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (impl),
-                                               current_working_dir);
-          g_free (current_working_dir);
+         recent_shortcut_handler (impl);
           break;
         
         case RELOAD_HAS_FOLDER:
@@ -5936,6 +6049,9 @@ gtk_file_chooser_default_unmap (GtkWidget *widget)
 
   settings_save (impl);
 
+  cancel_all_operations (impl);
+  impl->reload_state = RELOAD_EMPTY;
+
   GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->unmap (widget);
 }
 
@@ -6084,6 +6200,7 @@ load_set_model (GtkFileChooserDefault *impl)
   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),
                                   MODEL_COL_NAME);
+  file_list_set_sort_column_ids (impl);
   set_sort_column (impl);
   profile_msg ("    gtk_tree_view_set_model end", NULL);
   impl->list_sort_ascending = TRUE;
@@ -6209,20 +6326,25 @@ show_and_select_files (GtkFileChooserDefault *impl,
 {
   GtkTreeSelection *selection;
   GtkFileSystemModel *fsmodel;
-  gboolean can_have_hidden, can_have_filtered, selected_a_file;
+  gboolean enabled_hidden, removed_filters;
+  gboolean selected_a_file;
   GSList *walk;
 
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
   fsmodel = GTK_FILE_SYSTEM_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view)));
-  can_have_hidden = !impl->show_hidden;
-  can_have_filtered = impl->current_filter != NULL;
+
+  enabled_hidden = impl->show_hidden;
+  removed_filters = (impl->current_filter == NULL);
+
   selected_a_file = FALSE;
 
-  for (walk = files; walk && (can_have_hidden || can_have_filtered); walk = walk->next)
+  for (walk = files; walk; walk = walk->next)
     {
       GFile *file = walk->data;
       GtkTreeIter iter;
 
+      /* Is it a hidden file? */
+
       if (!_gtk_file_system_model_get_iter_for_file (fsmodel, &iter, file))
         continue;
 
@@ -6230,21 +6352,35 @@ show_and_select_files (GtkFileChooserDefault *impl,
         {
           GFileInfo *info = _gtk_file_system_model_get_info (fsmodel, &iter);
 
-          if (can_have_hidden &&
+          if (!enabled_hidden &&
               (g_file_info_get_is_hidden (info) ||
                g_file_info_get_is_backup (info)))
             {
               g_object_set (impl, "show-hidden", TRUE, NULL);
-              can_have_hidden = FALSE;
-            }
-
-          if (can_have_filtered)
-            {
-              set_current_filter (impl, NULL);
-              can_have_filtered = FALSE;
+              enabled_hidden = TRUE;
             }
         }
+
+      /* Is it a filtered file? */
+
+      if (!_gtk_file_system_model_get_iter_for_file (fsmodel, &iter, file))
+        continue; /* re-get the iter as it may change when the model refilters */
+
+      if (!_gtk_file_system_model_iter_is_visible (fsmodel, &iter))
+        {
+         /* Maybe we should have a way to ask the fsmodel if it had filtered a file */
+         if (!removed_filters)
+           {
+             set_current_filter (impl, NULL);
+             removed_filters = TRUE;
+           }
+       }
+
+      /* Okay, can we select the file now? */
           
+      if (!_gtk_file_system_model_get_iter_for_file (fsmodel, &iter, file))
+        continue;
+
       if (_gtk_file_system_model_iter_is_visible (fsmodel, &iter))
         {
           GtkTreePath *path;
@@ -6501,11 +6637,16 @@ file_system_model_got_thumbnail (GObject *object, GAsyncResult *res, gpointer da
   if (queried == NULL)
     return;
 
+  GDK_THREADS_ENTER ();
+
   /* now we know model is valid */
 
   /* file was deleted */
   if (!_gtk_file_system_model_get_iter_for_file (model, &iter, file))
-    return;
+    {
+      GDK_THREADS_LEAVE ();
+      return;
+    }
 
   info = g_file_info_dup (_gtk_file_system_model_get_info (model, &iter));
 
@@ -6516,6 +6657,8 @@ file_system_model_got_thumbnail (GObject *object, GAsyncResult *res, gpointer da
   _gtk_file_system_model_update_file (model, file, info, FALSE);
 
   g_object_unref (info);
+
+  GDK_THREADS_LEAVE ();
 }
 
 static gboolean
@@ -6721,19 +6864,17 @@ update_chooser_entry (GtkFileChooserDefault *impl)
 {
   GtkTreeSelection *selection;
   struct update_chooser_entry_selected_foreach_closure closure;
-  const char *file_part;
 
   /* no need to update the file chooser's entry if there's no entry */
   if (impl->operation_mode == OPERATION_MODE_SEARCH ||
-      impl->operation_mode == OPERATION_MODE_RECENT ||
       !impl->location_entry)
     return;
 
   if (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
-       || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
-       || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
-            || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
-           && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)))
+        || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
+        || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
+             || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+            && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)))
     return;
 
   g_assert (impl->location_entry != NULL);
@@ -6742,11 +6883,12 @@ update_chooser_entry (GtkFileChooserDefault *impl)
   closure.num_selected = 0;
   gtk_tree_selection_selected_foreach (selection, update_chooser_entry_selected_foreach, &closure);
 
-  file_part = NULL;
-
   if (closure.num_selected == 0)
     {
-      goto maybe_clear_entry;
+      if (impl->operation_mode == OPERATION_MODE_RECENT)
+       _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), NULL);
+      else
+       goto maybe_clear_entry;
     }
   else if (closure.num_selected == 1)
     {
@@ -6757,7 +6899,7 @@ update_chooser_entry (GtkFileChooserDefault *impl)
 
           info = _gtk_file_system_model_get_info (impl->browse_files_model, &closure.first_selected_iter);
 
-          /* If the cursor moved to the row of the newly created folder, 
+          /* If the cursor moved to the row of the newly created folder,
            * retrieving info will return NULL.
            */
           if (!info)
@@ -6769,13 +6911,13 @@ update_chooser_entry (GtkFileChooserDefault *impl)
 
           if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
               impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
-             impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
-           {
-             /* We don't want the name to change when clicking on a folder... */
-             change_entry = (! _gtk_file_info_consider_as_directory (info));
-           }
+              impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+            {
+              /* Don't change the name when clicking on a folder... */
+              change_entry = (! _gtk_file_info_consider_as_directory (info));
+            }
           else
-           change_entry = TRUE; /* ... unless we are in SELECT_FOLDER mode */
+            change_entry = TRUE; /* ... unless we are in SELECT_FOLDER mode */
 
           if (change_entry)
             {
@@ -6787,14 +6929,27 @@ update_chooser_entry (GtkFileChooserDefault *impl)
 
           return;
         }
+      else if (impl->operation_mode == OPERATION_MODE_RECENT
+              && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+       {
+         GFile *folder;
+
+         /* Set the base folder on the name entry, so it will do completion relative to the correct recent-folder */
+
+         gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &closure.first_selected_iter,
+                             MODEL_COL_FILE, &folder,
+                             -1);
+         _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), folder);
+         g_object_unref (folder);
+         return;
+       }
     }
   else
     {
       g_assert (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
-                 impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER));
+                  impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER));
 
       /* Multiple selection, so just clear the entry. */
-
       g_free (impl->browse_files_last_selected_name);
       impl->browse_files_last_selected_name = NULL;
 
@@ -6814,26 +6969,26 @@ update_chooser_entry (GtkFileChooserDefault *impl)
       entry_text = gtk_entry_get_text (GTK_ENTRY (impl->location_entry));
       len = strlen (entry_text);
       if (len != 0)
-       {
-         /* The file chooser entry may have appended a "/" to its text.  So
-          * take it out, and compare the result to the old selection.
-          */
-         if (entry_text[len - 1] == G_DIR_SEPARATOR)
-           {
-             char *tmp;
+        {
+          /* The file chooser entry may have appended a "/" to its text.
+           * So take it out, and compare the result to the old selection.
+           */
+          if (entry_text[len - 1] == G_DIR_SEPARATOR)
+            {
+              gchar *tmp;
 
-             tmp = g_strndup (entry_text, len - 1);
-             clear_entry = (compare_utf8_filenames (impl->browse_files_last_selected_name, tmp) == 0);
-             g_free (tmp);
-           }
-         else
-           clear_entry = (compare_utf8_filenames (impl->browse_files_last_selected_name, entry_text) == 0);
-       }
+              tmp = g_strndup (entry_text, len - 1);
+              clear_entry = (compare_utf8_filenames (impl->browse_files_last_selected_name, tmp) == 0);
+              g_free (tmp);
+            }
+          else
+            clear_entry = (compare_utf8_filenames (impl->browse_files_last_selected_name, entry_text) == 0);
+        }
       else
-       clear_entry = FALSE;
+        clear_entry = FALSE;
 
       if (clear_entry)
-       _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
+        _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
     }
 }
 
@@ -7071,17 +7226,7 @@ gtk_file_chooser_default_update_current_folder (GtkFileChooser    *chooser,
 
   g_object_ref (file);
 
-  switch (impl->operation_mode)
-    {
-    case OPERATION_MODE_SEARCH:
-      search_switch_to_browse_mode (impl);
-      break;
-    case OPERATION_MODE_RECENT:
-      recent_switch_to_browse_mode (impl);
-      break;
-    case OPERATION_MODE_BROWSE:
-      break;
-    }
+  operation_mode_set (impl, OPERATION_MODE_BROWSE);
 
   if (impl->local_only && !g_file_is_native (file))
     {
@@ -7131,17 +7276,12 @@ gtk_file_chooser_default_get_current_folder (GtkFileChooser *chooser)
  
   if (impl->reload_state == RELOAD_EMPTY)
     {
-      char *current_working_dir;
-      GFile *file;
-
-      /* We are unmapped, or we had an error while loading the last folder.  We'll return
-       * the $cwd since once we get (re)mapped, we'll load $cwd anyway unless the caller
-       * explicitly calls set_current_folder() on us.
+      /* We are unmapped, or we had an error while loading the last folder.
+       * We'll return the folder used by the last invocation of the file chooser
+       * since once we get (re)mapped, we'll load *that* folder anyway unless
+       * the caller explicitly calls set_current_folder() on us.
        */
-      current_working_dir = g_get_current_dir ();
-      file = g_file_new_for_path (current_working_dir);
-      g_free (current_working_dir);
-      return file;
+      return get_file_for_last_folder_opened (impl);
     }
 
   if (impl->current_folder)
@@ -7416,15 +7556,23 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
   GtkWidget *current_focus;
   gboolean file_list_seen;
 
+  info.impl = impl;
+  info.result = NULL;
+  info.file_from_entry = NULL;
+
   if (impl->operation_mode == OPERATION_MODE_SEARCH)
     return search_get_selected_files (impl);
 
   if (impl->operation_mode == OPERATION_MODE_RECENT)
-    return recent_get_selected_files (impl);
-
-  info.impl = impl;
-  info.result = NULL;
-  info.file_from_entry = NULL;
+    {
+      if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+       {
+         file_list_seen = TRUE;
+         goto file_entry;
+       }
+      else
+       return recent_get_selected_files (impl);
+    }
 
   toplevel = get_toplevel (GTK_WIDGET (impl));
   if (toplevel)
@@ -7850,10 +7998,9 @@ gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser)
 /* Guesses a size based upon font sizes */
 static void
 find_good_size_from_style (GtkWidget *widget,
-                          gint      *width,
-                          gint      *height)
+                           gint      *width,
+                           gint      *height)
 {
-  GtkFileChooserDefault *impl;
   GtkStyleContext *context;
   GtkStateFlags state;
   int font_size;
@@ -7863,14 +8010,12 @@ find_good_size_from_style (GtkWidget *widget,
   context = gtk_widget_get_style_context (widget);
   state = gtk_widget_get_state_flags (widget);
 
-  impl = GTK_FILE_CHOOSER_DEFAULT (widget);
-
   screen = gtk_widget_get_screen (widget);
   if (screen)
     {
       resolution = gdk_screen_get_resolution (screen);
       if (resolution < 0.0) /* will be -1 if the resolution is not defined in the GdkScreen */
-       resolution = 96.0;
+        resolution = 96.0;
     }
   else
     resolution = 96.0; /* wheeee */
@@ -7889,52 +8034,39 @@ gtk_file_chooser_default_get_default_size (GtkFileChooserEmbed *chooser_embed,
 {
   GtkFileChooserDefault *impl;
   GtkRequisition req;
+  int x, y, width, height;
 
   impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
 
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
-      || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
-      || impl->expand_folders)
-    {
-      int x, y, width, height;
-
-      settings_ensure (impl);
-
-      g_settings_get (impl->settings, SETTINGS_KEY_WINDOW_POSITION, "(ii)", &x, &y);
-      g_settings_get (impl->settings, SETTINGS_KEY_WINDOW_SIZE, "(ii)", &width, &height);
+  settings_ensure (impl);
 
-      if (x >= 0 && y >= 0 && width > 0 && height > 0)
-       {
-         *default_width = width;
-         *default_height = height;
-         return;
-       }
+  g_settings_get (impl->settings, SETTINGS_KEY_WINDOW_POSITION, "(ii)", &x, &y);
+  g_settings_get (impl->settings, SETTINGS_KEY_WINDOW_SIZE, "(ii)", &width, &height);
 
-      find_good_size_from_style (GTK_WIDGET (chooser_embed), default_width, default_height);
+  if (x >= 0 && y >= 0 && width > 0 && height > 0)
+    {
+      *default_width = width;
+      *default_height = height;
+      return;
+    }
 
-      if (impl->preview_widget_active &&
-         impl->preview_widget &&
-         gtk_widget_get_visible (impl->preview_widget))
-       {
-          gtk_widget_get_preferred_size (impl->preview_box,
-                                         &req, NULL);
-         *default_width += PREVIEW_HBOX_SPACING + req.width;
-       }
+  find_good_size_from_style (GTK_WIDGET (chooser_embed), default_width, default_height);
 
-      if (impl->extra_widget &&
-         gtk_widget_get_visible (impl->extra_widget))
-       {
-          gtk_widget_get_preferred_size (impl->extra_align,
-                                         &req, NULL);
-         *default_height += gtk_box_get_spacing (GTK_BOX (chooser_embed)) + req.height;
-       }
+  if (impl->preview_widget_active &&
+      impl->preview_widget &&
+      gtk_widget_get_visible (impl->preview_widget))
+    {
+      gtk_widget_get_preferred_size (impl->preview_box,
+                                    &req, NULL);
+      *default_width += PREVIEW_HBOX_SPACING + req.width;
     }
-  else
+
+  if (impl->extra_widget &&
+      gtk_widget_get_visible (impl->extra_widget))
     {
-      gtk_widget_get_preferred_size (GTK_WIDGET (impl),
-                                     &req, NULL);
-      *default_width = req.width;
-      *default_height = req.height;
+      gtk_widget_get_preferred_size (impl->extra_align,
+                                    &req, NULL);
+      *default_height += gtk_box_get_spacing (GTK_BOX (chooser_embed)) + req.height;
     }
 }
 
@@ -8091,6 +8223,16 @@ struct GetDisplayNameData
   gchar *file_part;
 };
 
+/* Every time we request a response explicitly, we need to save the selection to the recently-used list,
+ * as requesting a response means, "the dialog is confirmed".
+ */
+static void
+request_response_and_add_to_recent_list (GtkFileChooserDefault *impl)
+{
+  g_signal_emit_by_name (impl, "response-requested");
+  add_selection_to_recent_list (impl);
+}
+
 static void
 confirmation_confirm_get_info_cb (GCancellable *cancellable,
                                  GFileInfo    *info,
@@ -8117,7 +8259,7 @@ confirmation_confirm_get_info_cb (GCancellable *cancellable,
 
   set_busy_cursor (data->impl, FALSE);
   if (should_respond)
-    g_signal_emit_by_name (data->impl, "response-requested");
+    request_response_and_add_to_recent_list (data->impl);
 
 out:
   g_object_unref (data->impl);
@@ -8217,7 +8359,7 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
     {
       if (data->impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
        {
-         g_signal_emit_by_name (data->impl, "response-requested"); /* even if the file doesn't exist, apps can make good use of that (e.g. Emacs) */
+         request_response_and_add_to_recent_list (data->impl); /* even if the file doesn't exist, apps can make good use of that (e.g. Emacs) */
        }
       else if (data->impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
         {
@@ -8235,10 +8377,10 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
               g_free (file_part);
 
              if (retval)
-               g_signal_emit_by_name (data->impl, "response-requested");
+               request_response_and_add_to_recent_list (data->impl);
            }
          else
-           g_signal_emit_by_name (data->impl, "response-requested");
+           request_response_and_add_to_recent_list (data->impl);
        }
       else if (data->impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
               || data->impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
@@ -8254,7 +8396,7 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
          set_busy_cursor (data->impl, FALSE);
 
          if (!mkdir_error)
-           g_signal_emit_by_name (data->impl, "response-requested");
+           request_response_and_add_to_recent_list (data->impl);
          else
            error_creating_folder_dialog (data->impl, data->file, mkdir_error);
         }
@@ -8321,7 +8463,7 @@ file_exists_get_info_cb (GCancellable *cancellable,
       else
        {
          if (file_exists)
-           g_signal_emit_by_name (data->impl, "response-requested"); /* user typed an existing filename; we are done */
+           request_response_and_add_to_recent_list (data->impl); /* user typed an existing filename; we are done */
          else
            needs_parent_check = TRUE; /* file doesn't exist; see if its parent exists */
        }
@@ -8352,7 +8494,7 @@ file_exists_get_info_cb (GCancellable *cancellable,
          if (is_folder)
            {
              /* User typed a folder; we are done */
-             g_signal_emit_by_name (data->impl, "response-requested");
+             request_response_and_add_to_recent_list (data->impl);
            }
          else
            error_selecting_folder_over_existing_file_dialog (data->impl, data->file);
@@ -8429,20 +8571,47 @@ location_popup_on_paste_handler (GtkFileChooserDefault *impl)
                              impl);
 }
 
-
 /* Implementation for GtkFileChooserEmbed::should_respond() */
+static void
+add_selection_to_recent_list (GtkFileChooserDefault *impl)
+{
+  GSList *files;
+  GSList *l;
+
+  files = gtk_file_chooser_default_get_files (GTK_FILE_CHOOSER (impl));
+
+  for (l = files; l; l = l->next)
+    {
+      GFile *file = l->data;
+      char *uri;
+
+      uri = g_file_get_uri (file);
+      if (uri)
+       {
+         gtk_recent_manager_add_item (impl->recent_manager, uri);
+         g_free (uri);
+       }
+    }
+
+  g_slist_foreach (files, (GFunc) g_object_unref, NULL);
+  g_slist_free (files);
+}
+
 static gboolean
 gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
 {
   GtkFileChooserDefault *impl;
   GtkWidget *toplevel;
   GtkWidget *current_focus;
+  gboolean retval;
 
   impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
 
   toplevel = gtk_widget_get_toplevel (GTK_WIDGET (impl));
   g_assert (GTK_IS_WINDOW (toplevel));
 
+  retval = FALSE;
+
   current_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
 
   if (current_focus == impl->browse_files_tree_view)
@@ -8477,10 +8646,21 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
       g_assert (impl->action >= GTK_FILE_CHOOSER_ACTION_OPEN && impl->action <= GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
 
       if (impl->operation_mode == OPERATION_MODE_SEARCH)
-       return search_should_respond (impl);
+       {
+         retval = search_should_respond (impl);
+         goto out;
+       }
 
       if (impl->operation_mode == OPERATION_MODE_RECENT)
-        return recent_should_respond (impl);
+       {
+         if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+           goto save_entry;
+         else
+           {
+             retval = recent_should_respond (impl);
+             goto out;
+           }
+       }
 
       selection_check (impl, &num_selected, &all_files, &all_folders);
 
@@ -8497,7 +8677,8 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
          return FALSE;
 
        case RESPOND:
-         return TRUE;
+         retval = TRUE;
+         goto out;
 
        case RESPOND_OR_SWITCH:
          g_assert (num_selected == 1);
@@ -8508,17 +8689,25 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
              return FALSE;
            }
          else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
-           return should_respond_after_confirm_overwrite (impl,
-                                                          get_display_name_from_file_list (impl),
-                                                          impl->current_folder);
+           {
+             retval = should_respond_after_confirm_overwrite (impl,
+                                                              get_display_name_from_file_list (impl),
+                                                              impl->current_folder);
+             goto out;
+           }
          else
-           return TRUE;
+           {
+             retval = TRUE;
+             goto out;
+           }
 
        case ALL_FILES:
-         return all_files;
+         retval = all_files;
+         goto out;
 
        case ALL_FOLDERS:
-         return all_folders;
+         retval = all_folders;
+         goto out;
 
        case SAVE_ENTRY:
          goto save_entry;
@@ -8532,7 +8721,6 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
       GFile *file;
       gboolean is_well_formed, is_empty, is_file_part_empty;
       gboolean is_folder;
-      gboolean retval;
       GtkFileChooserEntry *entry;
       GError *error;
 
@@ -8548,12 +8736,35 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
       check_save_entry (impl, &file, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder);
 
       if (!is_well_formed)
-        return FALSE;
+       {
+         if (!is_empty
+             && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+             && impl->operation_mode == OPERATION_MODE_RECENT)
+           {
+             path_bar_set_mode (impl, PATH_BAR_ERROR_NO_FOLDER);
+#if 0
+             /* We'll #ifdef this out, as the fucking treeview selects its first row,
+              * thus changing our assumption that no selection is present - setting
+              * a selection causes the error message from path_bar_set_mode() to go away,
+              * but we want the user to see that message!
+              */
+             gtk_widget_grab_focus (impl->browse_files_tree_view);
+#endif
+           }
+         /* FIXME: else show an "invalid filename" error as the pathbar mode? */
+
+         return FALSE;
+       }
 
       if (is_empty)
         {
-          if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
-            return FALSE;
+          if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+             || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+           {
+             path_bar_set_mode (impl, PATH_BAR_ERROR_NO_FILENAME);
+             gtk_widget_grab_focus (impl->location_entry);
+             return FALSE;
+           }
 
           goto file_list;
         }
@@ -8567,7 +8778,6 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
              impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
            {
              change_folder_and_display_error (impl, file, TRUE);
-             retval = FALSE;
            }
          else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
                   impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
@@ -8580,7 +8790,6 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
          else
            {
              g_assert_not_reached ();
-             retval = FALSE;
            }
        }
       else
@@ -8608,14 +8817,12 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
                                       data);
 
          set_busy_cursor (impl, TRUE);
-         retval = FALSE;
 
          if (error != NULL)
            g_error_free (error);
        }
 
       g_object_unref (file);
-      return retval;
     }
   else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
     {
@@ -8643,9 +8850,13 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
       goto save_entry;
     else
       goto file_list; 
-  
-  g_assert_not_reached ();
-  return FALSE;
+
+ out:
+
+  if (retval)
+    add_selection_to_recent_list (impl);
+
+  return retval;
 }
 
 /* Implementation for GtkFileChooserEmbed::initial_focus() */
@@ -8691,7 +8902,7 @@ search_selected_foreach_get_file_cb (GtkTreeModel *model,
   list = data;
 
   gtk_tree_model_get (model, iter, MODEL_COL_FILE, &file, -1);
-  *list = g_slist_prepend (*list, g_object_ref (file));
+  *list = g_slist_prepend (*list, file); /* The file already has a new ref courtesy of gtk_tree_model_get(); this will be unreffed by the caller */
 }
 
 /* Constructs a list of the selected paths in search mode */
@@ -8778,6 +8989,7 @@ search_engine_finished_cb (GtkSearchEngine *engine,
    */
   gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
                            GTK_TREE_MODEL (impl->search_model));
+  file_list_set_sort_column_ids (impl);
 #endif
 
   /* FMQ: if search was empty, say that we got no hits */
@@ -8829,56 +9041,22 @@ search_clear_model (GtkFileChooserDefault *impl,
 
 /* Stops any ongoing searches; does not touch the search_model */
 static void
-search_stop_searching (GtkFileChooserDefault *impl,
-                       gboolean               remove_query)
-{
-  if (remove_query && impl->search_query)
-    {
-      g_object_unref (impl->search_query);
-      impl->search_query = NULL;
-    }
-  
-  if (impl->search_engine)
-    {
-      _gtk_search_engine_stop (impl->search_engine);
-      
-      g_object_unref (impl->search_engine);
-      impl->search_engine = NULL;
-    }
-}
-
-/* Stops any pending searches, clears the file list, and switches back to OPERATION_MODE_BROWSE */
-static void
-search_switch_to_browse_mode (GtkFileChooserDefault *impl)
-{
-  g_assert (impl->operation_mode != OPERATION_MODE_BROWSE);
-
-  search_stop_searching (impl, FALSE);
-  search_clear_model (impl, TRUE);
-
-  gtk_widget_destroy (impl->search_hbox);
-  impl->search_hbox = NULL;
-  impl->search_entry = NULL;
-
-  gtk_widget_show (impl->browse_path_bar);
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || !impl->create_folders)
-    gtk_widget_hide (impl->browse_new_folder_button);
-  else
-    gtk_widget_show (impl->browse_new_folder_button);
-
-
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
-      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+search_stop_searching (GtkFileChooserDefault *impl,
+                       gboolean               remove_query)
+{
+  if (remove_query && impl->search_query)
     {
-      gtk_widget_show (impl->location_button);
-
-      if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
-       gtk_widget_show (impl->location_entry_box);
+      g_object_unref (impl->search_query);
+      impl->search_query = NULL;
+    }
+  
+  if (impl->search_engine)
+    {
+      _gtk_search_engine_stop (impl->search_engine);
+      
+      g_object_unref (impl->search_engine);
+      impl->search_engine = NULL;
     }
-
-  impl->operation_mode = OPERATION_MODE_BROWSE;
-
-  file_list_set_sort_column_ids (impl);
 }
 
 /* Creates the search_model and puts it in the tree view */
@@ -8911,6 +9089,7 @@ search_setup_model (GtkFileChooserDefault *impl)
    */
   gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
                            GTK_TREE_MODEL (impl->search_model));
+  file_list_set_sort_column_ids (impl);
 }
 
 /* Creates a new query with the specified text and launches it */
@@ -9012,29 +9191,11 @@ focus_search_entry_in_idle (GtkFileChooserDefault *impl)
 static void
 search_setup_widgets (GtkFileChooserDefault *impl)
 {
-  GtkWidget *label;
-  GtkWidget *image;
-  gchar *tmp;
-
   impl->search_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
 
-  /* Image */
-
-  image = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON);
-  gtk_box_pack_start (GTK_BOX (impl->search_hbox), image, FALSE, FALSE, 5);
-
-  /* Label */
-
-  label = gtk_label_new (NULL);
-  tmp = g_strdup_printf ("<b>%s</b>", _("Search:"));
-  gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), tmp);
-  gtk_box_pack_start (GTK_BOX (impl->search_hbox), label, FALSE, FALSE, 0);
-  g_free (tmp);
-
-  /* Entry */
+  path_bar_update (impl);
 
   impl->search_entry = gtk_entry_new ();
-  gtk_label_set_mnemonic_widget (GTK_LABEL (label), impl->search_entry);
   g_signal_connect (impl->search_entry, "activate",
                    G_CALLBACK (search_entry_activate_cb),
                    impl);
@@ -9059,9 +9220,6 @@ search_setup_widgets (GtkFileChooserDefault *impl)
         }
     }
 
-  gtk_widget_hide (impl->browse_path_bar);
-  gtk_widget_hide (impl->browse_new_folder_button);
-
   /* Box for search widgets */
   gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->search_hbox, TRUE, TRUE, 0);
   gtk_widget_show_all (impl->search_hbox);
@@ -9081,62 +9239,6 @@ search_setup_widgets (GtkFileChooserDefault *impl)
   /* FMQ: hide the filter combo? */
 }
 
-/* Stops running operations like populating the browse model, searches, and the recent-files model */
-static void
-stop_operation (GtkFileChooserDefault *impl, OperationMode mode)
-{
-  switch (mode)
-    {
-    case OPERATION_MODE_BROWSE:
-      stop_loading_and_clear_list_model (impl, TRUE);
-      break;
-
-    case OPERATION_MODE_SEARCH:
-      search_stop_searching (impl, FALSE);
-      search_clear_model (impl, TRUE);
-
-      gtk_widget_destroy (impl->search_hbox);
-      impl->search_hbox = NULL;
-      impl->search_entry = NULL;
-      break;
-
-    case OPERATION_MODE_RECENT:
-      recent_stop_loading (impl);
-      recent_clear_model (impl, TRUE);
-
-      gtk_widget_destroy (impl->recent_hbox);
-      impl->recent_hbox = NULL;
-      break;
-    }
-}
-
-/* Main entry point to the searching functions; this gets called when the user
- * activates the Search shortcut.
- */
-static void
-search_activate (GtkFileChooserDefault *impl)
-{
-  OperationMode previous_mode;
-  
-  if (impl->operation_mode == OPERATION_MODE_SEARCH)
-    {
-      focus_search_entry_in_idle (impl);
-      return;
-    }
-
-  previous_mode = impl->operation_mode;
-  impl->operation_mode = OPERATION_MODE_SEARCH;
-
-  stop_operation (impl, previous_mode);
-
-  g_assert (impl->search_hbox == NULL);
-  g_assert (impl->search_entry == NULL);
-  g_assert (impl->search_model == NULL);
-
-  search_setup_widgets (impl);
-  file_list_set_sort_column_ids (impl);
-}
-
 /*
  * Recent files support
  */
@@ -9146,13 +9248,9 @@ static void
 recent_clear_model (GtkFileChooserDefault *impl,
                     gboolean               remove_from_treeview)
 {
-  GtkTreeModel *model;
-
   if (!impl->recent_model)
     return;
 
-  model = GTK_TREE_MODEL (impl->recent_model);
-  
   if (remove_from_treeview)
     gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL);
 
@@ -9173,42 +9271,6 @@ recent_stop_loading (GtkFileChooserDefault *impl)
     }
 }
 
-/* Stops any pending load, clears the file list, and switches
- * back to OPERATION_MODE_BROWSE
- */
-static void
-recent_switch_to_browse_mode (GtkFileChooserDefault *impl)
-{
-  g_assert (impl->operation_mode != OPERATION_MODE_BROWSE);
-
-  recent_stop_loading (impl);
-  recent_clear_model (impl, TRUE);
-
-  gtk_widget_destroy (impl->recent_hbox);
-  impl->recent_hbox = NULL;
-
-  gtk_widget_show (impl->browse_path_bar);
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || !impl->create_folders)
-    gtk_widget_hide (impl->browse_new_folder_button);
-  else
-    gtk_widget_show (impl->browse_new_folder_button);
-
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
-      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
-    {
-      gtk_widget_show (impl->location_button);
-
-      if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
-       gtk_widget_show (impl->location_entry_box);
-    }
-
-  gtk_tree_view_column_set_visible (impl->list_size_column, impl->show_size_column);
-
-  impl->operation_mode = OPERATION_MODE_BROWSE;
-
-  file_list_set_sort_column_ids (impl);
-}
-
 static void
 recent_setup_model (GtkFileChooserDefault *impl)
 {
@@ -9239,8 +9301,6 @@ typedef struct
 {
   GtkFileChooserDefault *impl;
   GList *items;
-  gint n_items;
-  gint n_loaded_items;
   guint needs_sorting : 1;
 } RecentLoadData;
 
@@ -9252,17 +9312,12 @@ recent_idle_cleanup (gpointer data)
 
   gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
                            GTK_TREE_MODEL (impl->recent_model));
+  file_list_set_sort_column_ids (impl);
 
   set_busy_cursor (impl, FALSE);
   
   impl->load_recent_id = 0;
   
-  if (load_data->items)
-    {
-      g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL);
-      g_list_free (load_data->items);
-    }
-
   g_free (load_data);
 }
 
@@ -9292,13 +9347,61 @@ get_recent_files_limit (GtkWidget *widget)
   return limit;
 }
 
+/* Populates the file system model with the GtkRecentInfo* items in the provided list; frees the items */
+static void
+populate_model_with_recent_items (GtkFileChooserDefault *impl, GList *items)
+{
+  gint limit;
+  GList *l;
+  int n;
+
+  limit = get_recent_files_limit (GTK_WIDGET (impl));
+
+  n = 0;
+
+  for (l = items; l; l = l->next)
+    {
+      GtkRecentInfo *info = l->data;
+      GFile *file;
+
+      file = g_file_new_for_uri (gtk_recent_info_get_uri (info));
+      _gtk_file_system_model_add_and_query_file (impl->recent_model,
+                                                 file,
+                                                 MODEL_ATTRIBUTES);
+      g_object_unref (file);
+
+      n++;
+      if (limit != -1 && n >= limit)
+       break;
+    }
+}
+
+static void
+populate_model_with_folders (GtkFileChooserDefault *impl, GList *items)
+{
+  GList *folders;
+  GList *l;
+
+  folders = _gtk_file_chooser_extract_recent_folders (items);
+
+  for (l = folders; l; l = l->next)
+    {
+      GFile *folder = l->data;
+
+      _gtk_file_system_model_add_and_query_file (impl->recent_model,
+                                                 folder,
+                                                 MODEL_ATTRIBUTES);
+    }
+
+  g_list_foreach (folders, (GFunc) g_object_unref, NULL);
+  g_list_free (folders);
+}
+
 static gboolean
 recent_idle_load (gpointer data)
 {
   RecentLoadData *load_data = data;
   GtkFileChooserDefault *impl = load_data->impl;
-  GList *walk;
-  GFile *file;
 
   if (!impl->recent_manager)
     return FALSE;
@@ -9315,55 +9418,21 @@ recent_idle_load (gpointer data)
       return TRUE;
     }
   
-  /* second iteration: preliminary MRU sorting and clamping */
+  /* second iteration: MRU sorting and clamping, and populating the model */
   if (load_data->needs_sorting)
     {
-      gint limit;
-
       load_data->items = g_list_sort (load_data->items, recent_sort_mru);
-      load_data->n_items = g_list_length (load_data->items);
-
-      limit = get_recent_files_limit (GTK_WIDGET (impl));
-      
-      if (limit != -1 && (load_data->n_items > limit))
-        {
-          GList *clamp, *l;
-
-          clamp = g_list_nth (load_data->items, limit - 1);
-          if (G_LIKELY (clamp))
-            {
-              l = clamp->next;
-              clamp->next = NULL;
-
-              g_list_foreach (l, (GFunc) gtk_recent_info_unref, NULL);
-              g_list_free (l);
-
-              load_data->n_items = limit;
-            }
-         }
-
-      load_data->n_loaded_items = 0;
-      load_data->needs_sorting = FALSE;
-
-      return TRUE;
-    }
 
-  /* finished loading items */
-  for (walk = load_data->items; walk; walk = walk->next)
-    {
-      GtkRecentInfo *info = walk->data;
-      file = g_file_new_for_uri (gtk_recent_info_get_uri (info));
+      if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
+       populate_model_with_recent_items (impl, load_data->items);
+      else
+       populate_model_with_folders (impl, load_data->items);
 
-      _gtk_file_system_model_add_and_query_file (impl->recent_model,
-                                                 file,
-                                                 MODEL_ATTRIBUTES);
-      gtk_recent_info_unref (walk->data);
-      g_object_unref (file);
+      g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL);
+      g_list_free (load_data->items);
+      load_data->items = NULL;
     }
 
-  g_list_free (load_data->items);
-  load_data->items = NULL;
-
   return FALSE;
 }
 
@@ -9382,8 +9451,6 @@ recent_start_loading (GtkFileChooserDefault *impl)
   load_data = g_new (RecentLoadData, 1);
   load_data->impl = impl;
   load_data->items = NULL;
-  load_data->n_items = 0;
-  load_data->n_loaded_items = 0;
   load_data->needs_sorting = TRUE;
 
   /* begin lazy loading the recent files into the model */
@@ -9438,66 +9505,6 @@ recent_should_respond (GtkFileChooserDefault *impl)
   return (gtk_tree_selection_count_selected_rows (selection) != 0);
 }
 
-/* Hide the location widgets temporarily */
-static void
-recent_hide_entry (GtkFileChooserDefault *impl)
-{
-  GtkWidget *label;
-  GtkWidget *image;
-  gchar *tmp;
-
-  impl->recent_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-
-  /* Image */
-  image = gtk_image_new_from_icon_name ("document-open-recent", GTK_ICON_SIZE_BUTTON);
-  gtk_box_pack_start (GTK_BOX (impl->recent_hbox), image, FALSE, FALSE, 5);
-
-  /* Label */
-  label = gtk_label_new (NULL);
-  tmp = g_strdup_printf ("<b>%s</b>", _("Recently Used"));
-  gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), tmp);
-  gtk_box_pack_start (GTK_BOX (impl->recent_hbox), label, FALSE, FALSE, 0);
-  g_free (tmp);
-
-  gtk_widget_hide (impl->browse_path_bar);
-  gtk_widget_hide (impl->browse_new_folder_button);
-  
-  /* Box for recent widgets */
-  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->recent_hbox, TRUE, TRUE, 0);
-  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->recent_hbox);
-  gtk_widget_show_all (impl->recent_hbox);
-
-  /* Hide the location widgets temporarily */
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
-      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
-    {
-      gtk_widget_hide (impl->location_button);
-      gtk_widget_hide (impl->location_entry_box);
-    }
-}
-
-/* Main entry point to the recent files functions; this gets called when
- * the user activates the Recently Used shortcut.
- */
-static void
-recent_activate (GtkFileChooserDefault *impl)
-{
-  OperationMode previous_mode;
-
-  if (impl->operation_mode == OPERATION_MODE_RECENT)
-    return;
-
-  previous_mode = impl->operation_mode;
-  impl->operation_mode = OPERATION_MODE_RECENT;
-
-  stop_operation (impl, previous_mode);
-
-  recent_hide_entry (impl);
-
-  file_list_set_sort_column_ids (impl);
-  recent_start_loading (impl);
-}
-
 static void
 set_current_filter (GtkFileChooserDefault *impl,
                    GtkFileFilter         *filter)
@@ -9602,6 +9609,13 @@ check_preview_change (GtkFileChooserDefault *impl)
 
       g_signal_emit_by_name (impl, "update-preview");
     }
+  else
+    {
+      if (new_file)
+        g_object_unref (new_file);
+
+      g_free (new_display_name);
+    }
 }
 
 static void
@@ -9664,17 +9678,7 @@ shortcuts_activate_volume (GtkFileChooserDefault *impl,
 {
   GFile *file;
 
-  switch (impl->operation_mode)
-    {
-    case OPERATION_MODE_BROWSE:
-      break;
-    case OPERATION_MODE_SEARCH:
-      search_switch_to_browse_mode (impl);
-      break;
-    case OPERATION_MODE_RECENT:
-      recent_switch_to_browse_mode (impl);
-      break;
-    }
+  operation_mode_set (impl, OPERATION_MODE_BROWSE);
 
   /* We ref the file chooser since volume_mount() may run a main loop, and the
    * user could close the file chooser window in the meantime.
@@ -9781,7 +9785,10 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl,
   gpointer col_data;
   ShortcutType shortcut_type;
 
-  if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY
+  /* In the Save modes, we want to preserve what the uesr typed in the filename
+   * entry, so that he may choose another folder without erasing his typed name.
+   */
+  if (impl->location_entry
       && !(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
           || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
     _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
@@ -9805,6 +9812,8 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl,
 
       volume = col_data;
 
+      operation_mode_set (impl, OPERATION_MODE_BROWSE);
+
       shortcuts_activate_volume (impl, volume);
     }
   else if (shortcut_type == SHORTCUT_TYPE_FILE)
@@ -9812,6 +9821,8 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl,
       struct ShortcutsActivateData *data;
       GtkFileSystemVolume *volume;
 
+      operation_mode_set (impl, OPERATION_MODE_BROWSE);
+
       volume = _gtk_file_system_get_volume_for_file (impl->file_system, col_data);
 
       data = g_new0 (struct ShortcutsActivateData, 1);
@@ -9843,11 +9854,11 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl,
     }
   else if (shortcut_type == SHORTCUT_TYPE_SEARCH)
     {
-      search_activate (impl);
+      operation_mode_set (impl, OPERATION_MODE_SEARCH);
     }
   else if (shortcut_type == SHORTCUT_TYPE_RECENT)
     {
-      recent_activate (impl);
+      operation_mode_set (impl, OPERATION_MODE_RECENT);
     }
 }
 
@@ -9956,6 +9967,8 @@ list_selection_changed (GtkTreeSelection      *selection,
   if (impl->location_entry)
     update_chooser_entry (impl);
 
+  path_bar_update (impl);
+
   check_preview_change (impl);
   bookmarks_check_add_sensitivity (impl);
 
@@ -9987,13 +10000,16 @@ list_row_activated (GtkTreeView           *tree_view,
   if (is_folder && file)
     {
       change_folder_and_display_error (impl, file, FALSE);
-      return;
+      g_object_unref (file);
+      goto out;
     }
 
   if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
       impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
     g_signal_emit_by_name (impl, "file-activated");
 
+ out:
+
   if (file)
     g_object_unref (file);
 }
@@ -10106,21 +10122,9 @@ location_popup_handler (GtkFileChooserDefault *impl,
   if (impl->operation_mode != OPERATION_MODE_BROWSE)
     {
       GtkWidget *widget_to_focus;
-      
-      /* This will give us the location widgets back */
-      switch (impl->operation_mode)
-        {
-        case OPERATION_MODE_SEARCH:
-          search_switch_to_browse_mode (impl);
-          break;
-        case OPERATION_MODE_RECENT:
-          recent_switch_to_browse_mode (impl);
-          break;
-        case OPERATION_MODE_BROWSE:
-          g_assert_not_reached ();
-          break;
-        }
 
+      operation_mode_set (impl, OPERATION_MODE_BROWSE);
+      
       if (impl->current_folder)
         change_folder_and_display_error (impl, impl->current_folder, FALSE);
 
@@ -10136,34 +10140,11 @@ location_popup_handler (GtkFileChooserDefault *impl,
   if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
       impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
     {
-      LocationMode new_mode;
-
-      if (path != NULL)
-       {
-         /* since the user typed something, we unconditionally want to turn on the entry */
-         new_mode = LOCATION_MODE_FILENAME_ENTRY;
-       }
-      else if (impl->location_mode == LOCATION_MODE_PATH_BAR)
-       new_mode = LOCATION_MODE_FILENAME_ENTRY;
-      else if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
-       new_mode = LOCATION_MODE_PATH_BAR;
-      else
-       {
-         g_assert_not_reached ();
-         return;
-       }
+      if (!path)
+       return;
 
-      location_mode_set (impl, new_mode, TRUE);
-      if (new_mode == LOCATION_MODE_FILENAME_ENTRY)
-       {
-         if (path != NULL)
-           location_set_user_text (impl, path);
-         else
-           {
-             location_entry_set_initial_text (impl);
-             gtk_editable_select_region (GTK_EDITABLE (impl->location_entry), 0, -1);
-           }
-       }
+      location_mode_set (impl, LOCATION_MODE_FILENAME_ENTRY, TRUE);
+      location_set_user_text (impl, path);
     }
   else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
           impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
@@ -10239,8 +10220,7 @@ search_shortcut_handler (GtkFileChooserDefault *impl)
 static void
 recent_shortcut_handler (GtkFileChooserDefault *impl)
 {
-  if (impl->has_recent)
-    switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_RECENT));
+  switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_RECENT));
 }
 
 static void
@@ -10303,16 +10283,14 @@ shortcuts_pane_model_filter_row_draggable (GtkTreeDragSource *drag_source,
   return (pos >= bookmarks_pos && pos < bookmarks_pos + model->impl->num_bookmarks);
 }
 
-/* GtkTreeDragSource::drag_data_get implementation for the shortcuts filter model */
+/* GtkTreeDragSource::drag_data_get implementation for the shortcuts
+ * filter model
+ */
 static gboolean
 shortcuts_pane_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
-                                          GtkTreePath       *path,
-                                          GtkSelectionData  *selection_data)
+                                           GtkTreePath       *path,
+                                           GtkSelectionData  *selection_data)
 {
-  ShortcutsPaneModelFilter *model;
-
-  model = SHORTCUTS_PANE_MODEL_FILTER (drag_source);
-
   /* FIXME */
 
   return FALSE;