]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkfilechooserdefault.c
GtkFileChooserDefault: Replace GtkTable by GtkGrid
[~andy/gtk] / gtk / gtkfilechooserdefault.c
index 24904d397a2429f45c61de74c0213f24940f4208..b49484089aff8fd2c5344ef7a56c2a564032df7a 100644 (file)
@@ -61,7 +61,7 @@
 #include "gtksizegroup.h"
 #include "gtksizerequest.h"
 #include "gtkstock.h"
-#include "gtktable.h"
+#include "gtkgrid.h"
 #include "gtktoolbar.h"
 #include "gtktoolbutton.h"
 #include "gtktooltip.h"
 #include <io.h>
 #endif
 
+/* Values for GtkSelection-related "info" fields */
+#define SELECTION_TEXT 0
+#define SELECTION_URI  1
+
 /* Profiling stuff */
 #undef PROFILE_FILE_CHOOSER
 #ifdef PROFILE_FILE_CHOOSER
 #endif
 
 #define PROFILE_INDENT 4
+
 static int profile_indent;
 
 static void
@@ -327,6 +332,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);
@@ -404,22 +411,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);
@@ -3708,7 +3716,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,
@@ -3784,6 +3792,7 @@ popup_menu_detach_cb (GtkWidget *attach_widget,
   impl->browse_files_popup_menu = NULL;
   impl->browse_files_popup_menu_add_shortcut_item = NULL;
   impl->browse_files_popup_menu_hidden_files_item = NULL;
+  impl->browse_files_popup_menu_copy_file_location_item = NULL;
 }
 
 /* Callback used when the "Add to Bookmarks" menu item is activated */
@@ -3794,6 +3803,97 @@ add_to_shortcuts_cb (GtkMenuItem           *item,
   bookmarks_add_selected_folder (impl);
 }
 
+/* callback used to set data to clipboard */
+static void
+copy_file_get_cb  (GtkClipboard     *clipboard,
+                   GtkSelectionData *selection_data,
+                   guint             info,
+                   gpointer          data)
+{
+  GSList *selected_files = data;
+
+  if (selected_files)
+    {
+      gint num_files = g_slist_length (selected_files);
+      gchar **uris;
+      gint i;
+      GSList *l;
+
+      uris = g_new (gchar *, num_files + 1);
+      uris[num_files] = NULL; /* null terminator */
+
+      i = 0;
+
+      for (l = selected_files; l; l = l->next)
+        {
+          GFile *file = (GFile *) l->data;
+
+         if (info == SELECTION_URI)
+           uris[i] = g_file_get_uri (file);
+         else /* if (info == SELECTION_TEXT) - let this be the fallback */
+           uris[i] = g_file_get_parse_name (file);
+
+          i++;
+        }
+
+      if (info == SELECTION_URI)
+       gtk_selection_data_set_uris (selection_data, uris);
+      else /* if (info == SELECTION_TEXT) - let this be the fallback */
+       {
+         char *str = g_strjoinv (" ", uris);
+         gtk_selection_data_set_text (selection_data, str, -1);
+         g_free (str);
+       }
+
+      g_strfreev (uris);
+    }
+}
+
+/* callback used to clear the clipboard data */
+static void
+copy_file_clear_cb (GtkClipboard *clipboard,
+                    gpointer      data)
+{
+  GSList *selected_files = data;
+
+  g_slist_foreach (selected_files, (GFunc) g_object_unref, NULL);
+  g_slist_free (selected_files);
+}
+
+/* Callback used when the "Copy file's location" menu item is activated */
+static void
+copy_file_location_cb (GtkMenuItem           *item,
+                       GtkFileChooserDefault *impl)
+{
+  GSList *selected_files = NULL;
+
+  selected_files = search_get_selected_files (impl);
+
+  if (selected_files)
+    {
+      GtkClipboard *clipboard;
+      GtkTargetList *target_list;
+      GtkTargetEntry *targets;
+      int n_targets;
+
+      clipboard = gtk_widget_get_clipboard (GTK_WIDGET (impl), GDK_SELECTION_CLIPBOARD);
+
+      target_list = gtk_target_list_new (NULL, 0);
+      gtk_target_list_add_text_targets (target_list, SELECTION_TEXT);
+      gtk_target_list_add_uri_targets (target_list, SELECTION_URI);
+
+      targets = gtk_target_table_new_from_list (target_list, &n_targets);
+      gtk_target_list_unref (target_list);
+
+      gtk_clipboard_set_with_data (clipboard, targets, n_targets,
+                                  copy_file_get_cb,
+                                   copy_file_clear_cb,
+                                  selected_files);
+
+      gtk_target_table_free (targets, n_targets);
+    }
+}
+
 /* Callback used when the "Show Hidden Files" menu item is toggled */
 static void
 show_hidden_toggled_cb (GtkCheckMenuItem      *item,
@@ -3981,6 +4081,24 @@ file_list_drag_motion_cb (GtkWidget             *widget,
   return TRUE;
 }
 
+/* Sensitizes the "Copy file's location" context menu item if there is actually
+ * a selection active.
+ */
+static void
+check_copy_file_location_sensitivity (GtkFileChooserDefault *impl)
+{
+  GtkTreeSelection *selection;
+  gboolean active;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+  if (gtk_tree_selection_count_selected_rows (selection) == 0)
+    active = FALSE;
+  else
+    active = TRUE;
+
+  gtk_widget_set_sensitive (impl->browse_files_popup_menu_copy_file_location_item, active);
+}
+
 /* Constructs the popup menu for the file list if needed */
 static void
 file_list_build_popup_menu (GtkFileChooserDefault *impl)
@@ -3995,6 +4113,15 @@ file_list_build_popup_menu (GtkFileChooserDefault *impl)
                             impl->browse_files_tree_view,
                             popup_menu_detach_cb);
 
+  item = gtk_image_menu_item_new_with_mnemonic (_("_Copy file's location"));
+  impl->browse_files_popup_menu_copy_file_location_item = item;
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
+                                 gtk_image_new_from_stock (GTK_STOCK_COPY, GTK_ICON_SIZE_MENU));
+  g_signal_connect (item, "activate",
+                    G_CALLBACK (copy_file_location_cb), impl);
+  gtk_widget_show (item);
+  gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
+
   item = gtk_image_menu_item_new_with_mnemonic (_("_Add to Bookmarks"));
   impl->browse_files_popup_menu_add_shortcut_item = item;
   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
@@ -4023,6 +4150,7 @@ file_list_build_popup_menu (GtkFileChooserDefault *impl)
   gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
 
   bookmarks_check_add_sensitivity (impl);
+  check_copy_file_location_sensitivity (impl);
 }
 
 /* Updates the popup menu for the file list, creating it if necessary */
@@ -4149,7 +4277,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)
 {
@@ -4387,6 +4517,20 @@ file_pane_create (GtkFileChooserDefault *impl,
   return vbox;
 }
 
+static void
+location_entry_create (GtkFileChooserDefault *impl)
+{
+  if (!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_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 */
 static void
 save_widgets_create (GtkFileChooserDefault *impl)
@@ -4401,35 +4545,25 @@ save_widgets_create (GtkFileChooserDefault *impl)
 
   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
 
-  impl->save_widgets_table = gtk_table_new (2, 2, FALSE);
+  impl->save_widgets_table = gtk_grid_new ();
   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);
+  gtk_grid_set_row_spacing (GTK_GRID (impl->save_widgets_table), 12);
+  gtk_grid_set_column_spacing (GTK_GRID (impl->save_widgets_table), 12);
 
   /* Label */
 
   widget = gtk_label_new_with_mnemonic (_("_Name:"));
   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);
+  gtk_grid_attach (GTK_GRID (impl->save_widgets_table), widget, 0, 0, 1, 1);
   gtk_widget_show (widget);
 
   /* 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 (impl->save_widgets_table), impl->location_entry,
-                   1, 2, 0, 1,
-                   GTK_EXPAND | GTK_FILL, 0,
-                   0, 0);
+  location_entry_create (impl);
+  gtk_widget_set_hexpand (impl->location_entry, TRUE);
+  gtk_grid_attach (GTK_GRID (impl->save_widgets_table), impl->location_entry, 1, 0, 1, 1);
   gtk_widget_show (impl->location_entry);
   gtk_label_set_mnemonic_widget (GTK_LABEL (widget), impl->location_entry);
 
@@ -4437,10 +4571,7 @@ save_widgets_create (GtkFileChooserDefault *impl)
   impl->save_folder_label = gtk_label_new (NULL);
   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_grid_attach (GTK_GRID (impl->save_widgets_table), impl->save_folder_label, 0, 1, 1, 1);
   gtk_widget_show (impl->save_folder_label);
 
   impl->save_widgets = vbox;
@@ -4478,53 +4609,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.
  */
@@ -4540,7 +4624,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 */
 
@@ -4548,19 +4635,13 @@ 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);
 
   /* Configure the entry */
 
   _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->current_folder);
-  _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->local_only);
 
   /* Done */
 
@@ -4913,9 +4994,13 @@ browse_widgets_create (GtkFileChooserDefault *impl)
   GtkWidget *widget;
   GtkSizeGroup *size_group;
 
-  /* size group is used by the scrolled windows of the panes */
-  size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
   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);
@@ -4923,12 +5008,15 @@ browse_widgets_create (GtkFileChooserDefault *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 (impl->browse_widgets_box), 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);
@@ -4967,7 +5055,6 @@ gtk_file_chooser_default_constructor (GType                  type,
 
   /* The browse widgets */
   browse_widgets_create (impl);
-  gtk_box_pack_start (GTK_BOX (impl), impl->browse_widgets_box, TRUE, TRUE, 0);
 
   /* Alignment to hold extra widget */
   impl->extra_align = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
@@ -5140,16 +5227,14 @@ 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_widgets_box), impl->browse_path_bar_hbox, FALSE, FALSE, 0);
-      gtk_box_reorder_child (GTK_BOX (impl->browse_widgets_box), impl->browse_path_bar_hbox, 0);
+      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_widget_set_hexpand (impl->browse_path_bar_hbox, TRUE);
+      gtk_grid_attach (GTK_GRID (impl->save_widgets_table), impl->browse_path_bar_hbox, 1, 1, 1, 1);
       gtk_label_set_mnemonic_widget (GTK_LABEL (impl->save_folder_label), impl->browse_path_bar);
     }
   else
@@ -5223,6 +5308,140 @@ path_bar_update (GtkFileChooserDefault *impl)
   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
@@ -5260,7 +5479,6 @@ update_appearance (GtkFileChooserDefault *impl)
     {
       gtk_widget_show (impl->location_button);
       save_widgets_destroy (impl);
-      gtk_widget_show (impl->browse_widgets_box);
       location_mode_set (impl, impl->location_mode, TRUE);
     }
 
@@ -6095,6 +6313,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;
@@ -6643,7 +6862,7 @@ file_system_model_set (GtkFileSystemModel *model,
       if (info == NULL || _gtk_file_info_consider_as_directory (info))
         g_value_set_string (value, NULL);
       else
-        g_value_take_string (value, g_format_size_for_display (g_file_info_get_size (info)));
+        g_value_take_string (value, g_format_size (g_file_info_get_size (info)));
       break;
     case MODEL_COL_MTIME:
     case MODEL_COL_MTIME_TEXT:
@@ -7120,17 +7339,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))
     {
@@ -8127,6 +8336,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,
@@ -8153,7 +8372,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);
@@ -8253,7 +8472,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)
         {
@@ -8271,10 +8490,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)
@@ -8290,7 +8509,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);
         }
@@ -8357,7 +8576,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 */
        }
@@ -8388,7 +8607,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);
@@ -8466,18 +8685,46 @@ location_popup_on_paste_handler (GtkFileChooserDefault *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)
@@ -8512,14 +8759,20 @@ 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)
        {
          if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
            goto save_entry;
          else
-           return recent_should_respond (impl);
+           {
+             retval = recent_should_respond (impl);
+             goto out;
+           }
        }
 
       selection_check (impl, &num_selected, &all_files, &all_folders);
@@ -8537,7 +8790,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);
@@ -8548,17 +8802,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;
@@ -8572,7 +8834,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;
 
@@ -8630,7 +8891,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)
@@ -8643,7 +8903,6 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
          else
            {
              g_assert_not_reached ();
-             retval = FALSE;
            }
        }
       else
@@ -8671,14 +8930,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)
     {
@@ -8706,9 +8963,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() */
@@ -8841,6 +9102,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 */
@@ -8910,34 +9172,6 @@ search_stop_searching (GtkFileChooserDefault *impl,
     }
 }
 
-/* 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;
-
-  impl->operation_mode = OPERATION_MODE_BROWSE;
-  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);
-
-      if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
-       gtk_widget_show (impl->location_entry_box);
-    }
-
-  file_list_set_sort_column_ids (impl);
-}
-
 /* Creates the search_model and puts it in the tree view */
 static void
 search_setup_model (GtkFileChooserDefault *impl)
@@ -8968,6 +9202,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 */
@@ -9117,79 +9352,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);
-      break;
-    }
-}
-
-/* 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);
-}
-
-/* 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;
-
-  shortcuts_select_item_without_activating (impl, shortcuts_get_index (impl, SHORTCUTS_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
  */
@@ -9222,34 +9384,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);
-
-  impl->operation_mode = OPERATION_MODE_BROWSE;
-  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);
-
-      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);
-
-  file_list_set_sort_column_ids (impl);
-}
-
 static void
 recent_setup_model (GtkFileChooserDefault *impl)
 {
@@ -9280,7 +9414,6 @@ typedef struct
 {
   GtkFileChooserDefault *impl;
   GList *items;
-  guint needs_sorting : 1;
 } RecentLoadData;
 
 static void
@@ -9291,6 +9424,8 @@ 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);
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->recent_model), MODEL_COL_MTIME, GTK_SORT_DESCENDING);
 
   set_busy_cursor (impl, FALSE);
   
@@ -9299,16 +9434,6 @@ recent_idle_cleanup (gpointer data)
   g_free (load_data);
 }
 
-static gint
-recent_sort_mru (gconstpointer a,
-                 gconstpointer b)
-{
-  GtkRecentInfo *info_a = (GtkRecentInfo *) a;
-  GtkRecentInfo *info_b = (GtkRecentInfo *) b;
-
-  return (gtk_recent_info_get_modified (info_b) - gtk_recent_info_get_modified (info_a));
-}
-
 static gint
 get_recent_files_limit (GtkWidget *widget)
 {
@@ -9384,32 +9509,18 @@ recent_idle_load (gpointer data)
   if (!impl->recent_manager)
     return FALSE;
 
-  /* first iteration: load all the items */
+  load_data->items = gtk_recent_manager_get_items (impl->recent_manager);
   if (!load_data->items)
-    {
-      load_data->items = gtk_recent_manager_get_items (impl->recent_manager);
-      if (!load_data->items)
-        return FALSE;
-
-      load_data->needs_sorting = TRUE;
-
-      return TRUE;
-    }
-  
-  /* second iteration: MRU sorting and clamping, and populating the model */
-  if (load_data->needs_sorting)
-    {
-      load_data->items = g_list_sort (load_data->items, recent_sort_mru);
+    return FALSE;
 
-      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);
+  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);
 
-      g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL);
-      g_list_free (load_data->items);
-      load_data->items = NULL;
-    }
+  g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL);
+  g_list_free (load_data->items);
+  load_data->items = NULL;
 
   return FALSE;
 }
@@ -9429,7 +9540,6 @@ recent_start_loading (GtkFileChooserDefault *impl)
   load_data = g_new (RecentLoadData, 1);
   load_data->impl = impl;
   load_data->items = NULL;
-  load_data->needs_sorting = TRUE;
 
   /* begin lazy loading the recent files into the model */
   impl->load_recent_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
@@ -9483,45 +9593,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)
-{
-  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);
-    }
-}
-
-/* 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;
-
-  shortcuts_select_item_without_activating (impl, shortcuts_get_index (impl, SHORTCUTS_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)
@@ -9695,17 +9766,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.
@@ -9812,7 +9873,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), "");
@@ -9836,6 +9900,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)
@@ -9843,6 +9909,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);
@@ -9874,11 +9942,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);
     }
 }
 
@@ -9991,6 +10059,7 @@ list_selection_changed (GtkTreeSelection      *selection,
 
   check_preview_change (impl);
   bookmarks_check_add_sensitivity (impl);
+  check_copy_file_location_sensitivity (impl);
 
   g_signal_emit_by_name (impl, "selection-changed", 0);
 }
@@ -10142,21 +10211,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);
 
@@ -10172,34 +10229,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)