[nautilus] slot: restructure window slot loading



commit 15d056a712cf3f6935bcb95003881aea01475693
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Sun Oct 21 21:53:58 2012 -0400

    slot: restructure window slot loading
    
    Move all the code related to loading a new slot from
    nautilus-window-manage-views.c to nautilus-window-slot.c or
    nautilus-window.c; then restructure loading to avoid having the view
    call back into the window.
    Instead, use the begin-loading and end-loading signals on the view.

 src/Makefile.am                    |    2 -
 src/nautilus-application.c         |    1 -
 src/nautilus-notebook.c            |    9 +-
 src/nautilus-view.c                |   10 +-
 src/nautilus-window-manage-views.c | 1806 -------------------------------
 src/nautilus-window-manage-views.h |   38 -
 src/nautilus-window-menus.c        |    1 -
 src/nautilus-window-private.h      |    6 -
 src/nautilus-window-slot.c         | 2080 ++++++++++++++++++++++++++++++++----
 src/nautilus-window-slot.h         |   29 +-
 src/nautilus-window.c              |   95 +-
 src/nautilus-window.h              |    5 -
 12 files changed, 1948 insertions(+), 2134 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 74f2e50..f3a0ed4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -195,8 +195,6 @@ nautilus_SOURCES = \
 	nautilus-view-dnd.h			\
 	nautilus-view-factory.c 		\
 	nautilus-view-factory.h 		\
-	nautilus-window-manage-views.c		\
-	nautilus-window-manage-views.h		\
 	nautilus-window-menus.c         	\
 	nautilus-window-private.h		\
 	nautilus-window-slot.c			\
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index 4ae2264..faa403b 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -47,7 +47,6 @@
 #include "nautilus-progress-ui-handler.h"
 #include "nautilus-self-check-functions.h"
 #include "nautilus-window.h"
-#include "nautilus-window-manage-views.h"
 #include "nautilus-window-private.h"
 #include "nautilus-window-slot.h"
 
diff --git a/src/nautilus-notebook.c b/src/nautilus-notebook.c
index 458aacd..aaabf8b 100644
--- a/src/nautilus-notebook.c
+++ b/src/nautilus-notebook.c
@@ -29,7 +29,6 @@
 #include "nautilus-notebook.h"
 
 #include "nautilus-window.h"
-#include "nautilus-window-manage-views.h"
 #include "nautilus-window-private.h"
 #include "nautilus-window-slot.h"
 #include "nautilus-window-slot-dnd.h"
@@ -291,6 +290,7 @@ nautilus_notebook_sync_tab_label (NautilusNotebook *notebook,
 {
 	GtkWidget *hbox, *label;
 	char *location_name;
+	GFile *location;
 
 	g_return_if_fail (NAUTILUS_IS_NOTEBOOK (notebook));
 	g_return_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot));
@@ -301,13 +301,14 @@ nautilus_notebook_sync_tab_label (NautilusNotebook *notebook,
 	label = GTK_WIDGET (g_object_get_data (G_OBJECT (hbox), "label"));
 	g_return_if_fail (GTK_IS_WIDGET (label));
 
-	gtk_label_set_text (GTK_LABEL (label), slot->title);
+	gtk_label_set_text (GTK_LABEL (label), nautilus_window_slot_get_title (slot));
+	location = nautilus_window_slot_get_location (slot);
 
-	if (slot->location != NULL) {
+	if (location != NULL) {
 		/* Set the tooltip on the label's parent (the tab label hbox),
 		 * so it covers all of the tab label.
 		 */
-		location_name = g_file_get_parse_name (slot->location);
+		location_name = g_file_get_parse_name (location);
 		gtk_widget_set_tooltip_text (gtk_widget_get_parent (label), location_name);
 		g_free (location_name);
 	} else {
diff --git a/src/nautilus-view.c b/src/nautilus-view.c
index cc4471a..c39d27e 100644
--- a/src/nautilus-view.c
+++ b/src/nautilus-view.c
@@ -3046,10 +3046,6 @@ done_loading (NautilusView *view,
 	 * is no NautilusWindow any more.
 	 */
 	if (window != NULL) {
-		if (all_files_seen) {
-			nautilus_window_report_load_complete (window, NAUTILUS_VIEW (view));
-		}
-
 		schedule_update_menus (view);
 		schedule_update_status (view);
 		reset_update_interval (view);
@@ -9156,13 +9152,9 @@ static void
 finish_loading (NautilusView *view)
 {
 	NautilusFileAttributes attributes;
-	NautilusWindow *window;
 
 	nautilus_profile_start (NULL);
 
-	window = nautilus_view_get_window (view);
-	nautilus_window_report_load_underway (window, NAUTILUS_VIEW (view));
-
 	/* Tell interested parties that we've begun loading this directory now.
 	 * Subclasses use this to know that the new metadata is now available.
 	 */
@@ -9171,7 +9163,7 @@ finish_loading (NautilusView *view)
 	nautilus_profile_end ("BEGIN_LOADING");
 
 	/* Assume we have now all information to show window */
-	nautilus_window_view_visible  (window, NAUTILUS_VIEW (view));
+	nautilus_window_view_visible  (nautilus_view_get_window (view), NAUTILUS_VIEW (view));
 
 	if (nautilus_directory_are_all_files_seen (view->details->model)) {
 		/* Unschedule a pending update and schedule a new one with the minimal
diff --git a/src/nautilus-window-menus.c b/src/nautilus-window-menus.c
index 0c7b0d0..5d1a703 100644
--- a/src/nautilus-window-menus.c
+++ b/src/nautilus-window-menus.c
@@ -36,7 +36,6 @@
 #include "nautilus-file-management-properties.h"
 #include "nautilus-list-view.h"
 #include "nautilus-notebook.h"
-#include "nautilus-window-manage-views.h"
 #include "nautilus-window-private.h"
 #include "nautilus-desktop-window.h"
 #include "nautilus-properties-window.h"
diff --git a/src/nautilus-window-private.h b/src/nautilus-window-private.h
index 25a629e..44fdbde 100644
--- a/src/nautilus-window-private.h
+++ b/src/nautilus-window-private.h
@@ -44,12 +44,6 @@ struct NautilusWindowDetails
         guint extensions_menu_merge_id;
         GtkActionGroup *extensions_menu_action_group;
 
-	/* Ensures that we do not react on signals of a
-	 * view that is re-used as new view when its loading
-	 * is cancelled
-	 */
-	gboolean temporarily_ignore_view_signals;
-
         GtkWidget *notebook;
 
         /* available slots, and active slot.
diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c
index 620ca70..68e18f3 100644
--- a/src/nautilus-window-slot.c
+++ b/src/nautilus-window-slot.c
@@ -27,19 +27,26 @@
 #include "nautilus-window-slot.h"
 
 #include "nautilus-actions.h"
-#include "nautilus-toolbar.h"
+#include "nautilus-application.h"
+#include "nautilus-desktop-window.h"
 #include "nautilus-floating-bar.h"
+#include "nautilus-special-location-bar.h"
+#include "nautilus-toolbar.h"
+#include "nautilus-trash-bar.h"
+#include "nautilus-view-factory.h"
 #include "nautilus-window-private.h"
-#include "nautilus-window-manage-views.h"
-#include "nautilus-desktop-window.h"
+#include "nautilus-x-content-bar.h"
 
 #include <glib/gi18n.h>
+#include <eel/eel-stock-dialogs.h>
 
 #include <libnautilus-private/nautilus-file.h>
 #include <libnautilus-private/nautilus-file-utilities.h>
 #include <libnautilus-private/nautilus-global-preferences.h>
-
-#include <eel/eel-string.h>
+#include <libnautilus-private/nautilus-module.h>
+#include <libnautilus-private/nautilus-monitor.h>
+#include <libnautilus-private/nautilus-profile.h>
+#include <libnautilus-extension/nautilus-location-widget-provider.h>
 
 G_DEFINE_TYPE (NautilusWindowSlot, nautilus_window_slot, GTK_TYPE_BOX);
 
@@ -63,11 +70,35 @@ struct NautilusWindowSlotDetails {
 	guint loading_timeout_id;
 	GtkWidget *floating_bar;
 	GtkWidget *view_overlay;
+
+	/* slot contains
+	 *  1) an vbox containing extra_location_widgets
+	 *  2) the view
+	 */
+	GtkWidget *extra_location_widgets;
+
+	/* Current location. */
+	GFile *location;
+	gchar *title;
+
+        /* Load state */
+	GCancellable *find_mount_cancellable;
+	gboolean needs_reload;
+
+	/* Ensures that we do not react on signals of a
+	 * view that is re-used as new view when its loading
+	 * is cancelled
+	 */
+	gboolean temporarily_ignore_view_signals;
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
 
+static void nautilus_window_slot_force_reload (NautilusWindowSlot *slot);
+static void location_has_really_changed (NautilusWindowSlot *slot);
+static void nautilus_window_slot_connect_new_content_view (NautilusWindowSlot *slot);
+
 gboolean
 nautilus_window_slot_handle_event (NautilusWindowSlot *slot,
 				   GdkEventKey        *event)
@@ -218,8 +249,8 @@ show_query_editor (NautilusWindowSlot *slot)
 	 * nautilus_window_sync_search_widgets() from hiding it again when
 	 * loading has completed.
 	 */
-	if (slot->location) {
-		location = slot->location;
+	if (slot->details->location) {
+		location = slot->details->location;
 	} else {
 		location = slot->pending_location;
 		slot->load_with_search = TRUE;
@@ -306,109 +337,1730 @@ real_inactive (NautilusWindowSlot *slot)
 }
 
 static void
-floating_bar_action_cb (NautilusFloatingBar *floating_bar,
-			gint action,
-			NautilusWindowSlot *slot)
+floating_bar_action_cb (NautilusFloatingBar *floating_bar,
+			gint action,
+			NautilusWindowSlot *slot)
+{
+	if (action == NAUTILUS_FLOATING_BAR_ACTION_ID_STOP) {
+		nautilus_window_slot_stop_loading (slot);
+	}
+}
+
+static void
+remove_all_extra_location_widgets (GtkWidget *widget,
+				   gpointer data)
+{
+	NautilusWindowSlot *slot = data;
+	NautilusDirectory *directory;
+
+	directory = nautilus_directory_get (slot->details->location);
+	if (widget != GTK_WIDGET (slot->query_editor)) {
+		gtk_container_remove (GTK_CONTAINER (slot->details->extra_location_widgets), widget);
+	}
+
+	nautilus_directory_unref (directory);
+}
+
+static void
+nautilus_window_slot_remove_extra_location_widgets (NautilusWindowSlot *slot)
+{
+	gtk_container_foreach (GTK_CONTAINER (slot->details->extra_location_widgets),
+			       remove_all_extra_location_widgets,
+			       slot);
+}
+
+static void
+nautilus_window_slot_add_extra_location_widget (NautilusWindowSlot *slot,
+						GtkWidget *widget)
+{
+	gtk_box_pack_start (GTK_BOX (slot->details->extra_location_widgets),
+			    widget, TRUE, TRUE, 0);
+	gtk_widget_show (slot->details->extra_location_widgets);
+}
+
+static void
+nautilus_window_slot_set_property (GObject *object,
+				   guint property_id,
+				   const GValue *value,
+				   GParamSpec *pspec)
+{
+	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (object);
+
+	switch (property_id) {
+	case PROP_WINDOW:
+		nautilus_window_slot_set_window (slot, g_value_get_object (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+		break;
+	}
+}
+
+static void
+nautilus_window_slot_get_property (GObject *object,
+				   guint property_id,
+				   GValue *value,
+				   GParamSpec *pspec)
+{
+	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (object);
+
+	switch (property_id) {
+	case PROP_WINDOW:
+		g_value_set_object (value, slot->details->window);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+		break;
+	}
+}
+
+static void
+nautilus_window_slot_constructed (GObject *object)
+{
+	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (object);
+	GtkWidget *extras_vbox;
+
+	G_OBJECT_CLASS (nautilus_window_slot_parent_class)->constructed (object);
+
+	gtk_orientable_set_orientation (GTK_ORIENTABLE (slot),
+					GTK_ORIENTATION_VERTICAL);
+	gtk_widget_show (GTK_WIDGET (slot));
+
+	extras_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+	slot->details->extra_location_widgets = extras_vbox;
+	gtk_box_pack_start (GTK_BOX (slot), extras_vbox, FALSE, FALSE, 0);
+	gtk_widget_show (extras_vbox);
+
+	slot->query_editor = NAUTILUS_QUERY_EDITOR (nautilus_query_editor_new ());
+	nautilus_window_slot_add_extra_location_widget (slot, GTK_WIDGET (slot->query_editor));
+	g_object_add_weak_pointer (G_OBJECT (slot->query_editor),
+				   (gpointer *) &slot->query_editor);
+
+	slot->details->view_overlay = gtk_overlay_new ();
+	gtk_widget_add_events (slot->details->view_overlay,
+			       GDK_ENTER_NOTIFY_MASK |
+			       GDK_LEAVE_NOTIFY_MASK);
+	gtk_box_pack_start (GTK_BOX (slot), slot->details->view_overlay, TRUE, TRUE, 0);
+	gtk_widget_show (slot->details->view_overlay);
+
+	slot->details->floating_bar = nautilus_floating_bar_new (NULL, NULL, FALSE);
+	gtk_widget_set_halign (slot->details->floating_bar, GTK_ALIGN_END);
+	gtk_widget_set_valign (slot->details->floating_bar, GTK_ALIGN_END);
+	gtk_overlay_add_overlay (GTK_OVERLAY (slot->details->view_overlay),
+				 slot->details->floating_bar);
+
+	g_signal_connect (slot->details->floating_bar, "action",
+			  G_CALLBACK (floating_bar_action_cb), slot);
+
+	slot->details->title = g_strdup (_("Loading..."));
+}
+
+static void
+nautilus_window_slot_init (NautilusWindowSlot *slot)
+{
+	slot->details = G_TYPE_INSTANCE_GET_PRIVATE
+		(slot, NAUTILUS_TYPE_WINDOW_SLOT, NautilusWindowSlotDetails);
+}
+
+static void
+remove_loading_floating_bar (NautilusWindowSlot *slot)
+{
+	if (slot->details->loading_timeout_id != 0) {
+		g_source_remove (slot->details->loading_timeout_id);
+		slot->details->loading_timeout_id = 0;
+	}
+
+	gtk_widget_hide (slot->details->floating_bar);
+	nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (slot->details->floating_bar));
+}
+
+#define DEBUG_FLAG NAUTILUS_DEBUG_WINDOW
+#include <libnautilus-private/nautilus-debug.h>
+
+/* FIXME bugzilla.gnome.org 41243:
+ * We should use inheritance instead of these special cases
+ * for the desktop window.
+ */
+#include "nautilus-desktop-window.h"
+
+/* This number controls a maximum character count for a URL that is
+ * displayed as part of a dialog. It's fairly arbitrary -- big enough
+ * to allow most "normal" URIs to display in full, but small enough to
+ * prevent the dialog from getting insanely wide.
+ */
+#define MAX_URI_IN_DIALOG_LENGTH 60
+
+static void begin_location_change                     (NautilusWindowSlot         *slot,
+						       GFile                      *location,
+						       GFile                      *previous_location,
+						       GList                      *new_selection,
+						       NautilusLocationChangeType  type,
+						       guint                       distance,
+						       const char                 *scroll_pos,
+						       NautilusWindowGoToCallback  callback,
+						       gpointer                    user_data);
+static void free_location_change                      (NautilusWindowSlot         *slot);
+static void end_location_change                       (NautilusWindowSlot         *slot);
+static void cancel_location_change                    (NautilusWindowSlot         *slot);
+static void got_file_info_for_view_selection_callback (NautilusFile               *file,
+						       gpointer                    callback_data);
+static gboolean create_content_view                   (NautilusWindowSlot         *slot,
+						       const char                 *view_id,
+						       GError                    **error);
+static void display_view_selection_failure            (NautilusWindow             *window,
+						       NautilusFile               *file,
+						       GFile                      *location,
+						       GError                     *error);
+static void load_new_location                         (NautilusWindowSlot         *slot,
+						       GFile                      *location,
+						       GList                      *selection,
+						       gboolean                    tell_current_content_view,
+						       gboolean                    tell_new_content_view);
+
+static void
+new_window_show_callback (GtkWidget *widget,
+			  gpointer user_data){
+	NautilusWindow *window;
+
+	window = NAUTILUS_WINDOW (user_data);
+	nautilus_window_close (window);
+
+	g_signal_handlers_disconnect_by_func (widget,
+					      G_CALLBACK (new_window_show_callback),
+					      user_data);
+}
+
+void
+nautilus_window_slot_open_location_full (NautilusWindowSlot *slot,
+					 GFile *location,
+					 NautilusWindowOpenFlags flags,
+					 GList *new_selection,
+					 NautilusWindowGoToCallback callback,
+					 gpointer user_data)
+{
+	NautilusWindow *window;
+        NautilusWindow *target_window;
+        NautilusWindowSlot *target_slot;
+	NautilusWindowOpenFlags slot_flags;
+	GFile *old_location;
+	char *old_uri, *new_uri;
+	int new_slot_position;
+	gboolean use_same;
+	gboolean is_desktop;
+
+	window = nautilus_window_slot_get_window (slot);
+
+        target_window = NULL;
+	target_slot = NULL;
+	use_same = TRUE;
+
+	/* this happens at startup */
+	old_uri = nautilus_window_slot_get_location_uri (slot);
+	if (old_uri == NULL) {
+		old_uri = g_strdup ("(none)");
+		use_same = TRUE;
+	}
+	new_uri = g_file_get_uri (location);
+
+	DEBUG ("Opening location, old: %s, new: %s", old_uri, new_uri);
+	nautilus_profile_start ("Opening location, old: %s, new: %s", old_uri, new_uri);
+
+	g_free (old_uri);
+	g_free (new_uri);
+
+	is_desktop = NAUTILUS_IS_DESKTOP_WINDOW (window);
+
+	if (is_desktop) {
+		use_same = !nautilus_desktop_window_loaded (NAUTILUS_DESKTOP_WINDOW (window));
+
+		/* if we're requested to open a new tab on the desktop, open a window
+		 * instead.
+		 */
+		if (flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) {
+			flags ^= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
+			flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
+		}
+	}
+
+	g_assert (!((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 &&
+		    (flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0));
+
+	/* and if the flags specify so, this is overridden */
+	if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0) {
+		use_same = FALSE;
+	}
+
+	old_location = nautilus_window_slot_get_location (slot);
+
+	/* now get/create the window */
+	if (use_same) {
+		target_window = window;
+	} else {
+		target_window = nautilus_application_create_window
+			(NAUTILUS_APPLICATION (g_application_get_default ()),
+			 gtk_window_get_screen (GTK_WINDOW (window)));
+	}
+
+        g_assert (target_window != NULL);
+
+	/* if the flags say we want a new tab, open a slot in the current window */
+	if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0) {
+		g_assert (target_window == window);
+
+		slot_flags = 0;
+
+		new_slot_position = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION);
+		if (new_slot_position == NAUTILUS_NEW_TAB_POSITION_END) {
+			slot_flags = NAUTILUS_WINDOW_OPEN_SLOT_APPEND;
+		}
+
+		target_slot = nautilus_window_open_slot (window,
+							 slot_flags);
+	}
+
+	/* close the current window if the flags say so */
+	if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_CLOSE_BEHIND) != 0) {
+		if (!is_desktop) {
+			if (gtk_widget_get_visible (GTK_WIDGET (target_window))) {
+				nautilus_window_close (window);
+			} else {
+				g_signal_connect_object (target_window,
+							 "show",
+							 G_CALLBACK (new_window_show_callback),
+							 window,
+							 G_CONNECT_AFTER);
+			}
+		}
+	}
+
+	if (target_slot == NULL) {
+		if (target_window == window) {
+			target_slot = slot;
+		} else {
+			target_slot = nautilus_window_get_active_slot (target_window);
+		}
+	}
+
+        if (target_window == window && target_slot == slot &&
+	    old_location && g_file_equal (old_location, location) &&
+	    !is_desktop) {
+
+		if (callback != NULL) {
+			callback (window, NULL, user_data);
+		}
+
+		goto done;
+        }
+
+        begin_location_change (target_slot, location, old_location, new_selection,
+			       NAUTILUS_LOCATION_CHANGE_STANDARD, 0, NULL, callback, user_data);
+
+ done:
+	nautilus_profile_end (NULL);
+}
+
+static gboolean
+report_callback (NautilusWindowSlot *slot,
+		 GError *error)
+{
+	if (slot->open_callback != NULL) {
+		gboolean res;
+		res = slot->open_callback (nautilus_window_slot_get_window (slot),
+					   error, slot->open_callback_user_data);
+		slot->open_callback = NULL;
+		slot->open_callback_user_data = NULL;
+
+		return res;
+	}
+
+	return FALSE;
+}
+
+/*
+ * begin_location_change
+ *
+ * Change a window slot's location.
+ * @window: The NautilusWindow whose location should be changed.
+ * @location: A url specifying the location to load
+ * @previous_location: The url that was previously shown in the window that initialized the change, if any
+ * @new_selection: The initial selection to present after loading the location
+ * @type: Which type of location change is this? Standard, back, forward, or reload?
+ * @distance: If type is back or forward, the index into the back or forward chain. If
+ * type is standard or reload, this is ignored, and must be 0.
+ * @scroll_pos: The file to scroll to when the location is loaded.
+ * @callback: function to be called when the location is changed.
+ * @user_data: data for @callback.
+ *
+ * This is the core function for changing the location of a window. Every change to the
+ * location begins here.
+ */
+static void
+begin_location_change (NautilusWindowSlot *slot,
+                       GFile *location,
+                       GFile *previous_location,
+		       GList *new_selection,
+                       NautilusLocationChangeType type,
+                       guint distance,
+                       const char *scroll_pos,
+		       NautilusWindowGoToCallback callback,
+		       gpointer user_data)
+{
+        NautilusDirectory *directory;
+        NautilusFile *file;
+	gboolean force_reload;
+        char *current_pos;
+	GFile *from_folder, *parent;
+	GList *parent_selection = NULL;
+
+	g_assert (slot != NULL);
+        g_assert (location != NULL);
+        g_assert (type == NAUTILUS_LOCATION_CHANGE_BACK
+                  || type == NAUTILUS_LOCATION_CHANGE_FORWARD
+                  || distance == 0);
+
+	nautilus_profile_start (NULL);
+
+	/* If there is no new selection and the new location is
+	 * a (grand)parent of the old location then we automatically
+	 * select the folder the previous location was in */
+	if (new_selection == NULL && previous_location != NULL &&
+	    g_file_has_prefix (previous_location, location)) {
+		from_folder = g_object_ref (previous_location);
+		parent = g_file_get_parent (from_folder);
+		while (parent != NULL && !g_file_equal (parent, location)) {
+			g_object_unref (from_folder);
+			from_folder = parent;
+			parent = g_file_get_parent (from_folder);
+		}
+
+		if (parent != NULL) {
+			new_selection = parent_selection =
+				g_list_prepend (NULL, nautilus_file_get (from_folder));
+			g_object_unref (parent);
+		}
+
+		g_object_unref (from_folder);
+	}
+
+	end_location_change (slot);
+
+	nautilus_window_slot_set_allow_stop (slot, TRUE);
+	nautilus_window_slot_set_status (slot, NULL, NULL);
+
+	g_assert (slot->details->pending_location == NULL);
+	g_assert (slot->details->pending_selection == NULL);
+
+	slot->details->pending_location = g_object_ref (location);
+	slot->details->location_change_type = type;
+	slot->details->location_change_distance = distance;
+	slot->details->tried_mount = FALSE;
+	slot->details->pending_selection = eel_g_object_list_copy (new_selection);
+
+	slot->pending_scroll_to = g_strdup (scroll_pos);
+
+	slot->open_callback = callback;
+	slot->open_callback_user_data = user_data;
+
+        directory = nautilus_directory_get (location);
+
+	/* The code to force a reload is here because if we do it
+	 * after determining an initial view (in the components), then
+	 * we end up fetching things twice.
+	 */
+	if (type == NAUTILUS_LOCATION_CHANGE_RELOAD) {
+		force_reload = TRUE;
+	} else if (!nautilus_monitor_active ()) {
+		force_reload = TRUE;
+	} else {
+		force_reload = !nautilus_directory_is_local (directory);
+	}
+
+	if (force_reload) {
+		nautilus_directory_force_reload (directory);
+		file = nautilus_directory_get_corresponding_file (directory);
+		nautilus_file_invalidate_all_attributes (file);
+		nautilus_file_unref (file);
+	}
+
+        nautilus_directory_unref (directory);
+
+	if (parent_selection != NULL) {
+		g_list_free_full (parent_selection, g_object_unref);
+	}
+
+        /* Set current_bookmark scroll pos */
+        if (slot->current_location_bookmark != NULL &&
+            slot->content_view != NULL) {
+                current_pos = nautilus_view_get_first_visible_file (slot->content_view);
+                nautilus_bookmark_set_scroll_pos (slot->current_location_bookmark, current_pos);
+                g_free (current_pos);
+        }
+
+	/* Get the info needed for view selection */
+	
+        slot->determine_view_file = nautilus_file_get (location);
+	g_assert (slot->determine_view_file != NULL);
+
+	nautilus_file_call_when_ready (slot->determine_view_file,
+				       NAUTILUS_FILE_ATTRIBUTE_INFO |
+				       NAUTILUS_FILE_ATTRIBUTE_MOUNT,
+                                       got_file_info_for_view_selection_callback,
+				       slot);
+
+	nautilus_profile_end (NULL);
+}
+
+static void
+nautilus_window_slot_set_location (NautilusWindowSlot *slot,
+				   GFile *location)
+{
+	if (slot->details->location &&
+	    g_file_equal (location, slot->details->location)) {
+		return;
+	}
+
+	if (slot->details->location) {
+		g_object_unref (slot->details->location);
+	}
+	slot->details->location = g_object_ref (location);
+
+	if (slot == nautilus_window_get_active_slot (slot->details->window)) {
+		nautilus_window_sync_location_widgets (slot->details->window);
+		nautilus_window_slot_update_title (slot);
+	}
+}
+
+static void
+viewed_file_changed_callback (NautilusFile *file,
+                              NautilusWindowSlot *slot)
+{
+        GFile *new_location;
+	gboolean is_in_trash, was_in_trash;
+
+        g_assert (NAUTILUS_IS_FILE (file));
+	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
+	g_assert (file == slot->viewed_file);
+
+        if (!nautilus_file_is_not_yet_confirmed (file)) {
+                slot->viewed_file_seen = TRUE;
+        }
+
+	was_in_trash = slot->viewed_file_in_trash;
+
+	slot->viewed_file_in_trash = is_in_trash = nautilus_file_is_in_trash (file);
+
+	if (nautilus_file_is_gone (file) || (is_in_trash && !was_in_trash)) {
+                if (slot->viewed_file_seen) {
+			/* auto-show existing parent. */
+			GFile *go_to_file;
+			GFile *parent;
+			GFile *location;
+			GMount *mount;
+
+                        /* Detecting a file is gone may happen in the
+                         * middle of a pending location change, we
+                         * need to cancel it before closing the window
+                         * or things break.
+                         */
+			go_to_file = NULL;
+			parent = NULL;
+
+			location = nautilus_file_get_location (file);
+			mount = nautilus_get_mounted_mount_for_root (location);
+			if (mount != NULL) {
+				parent = g_file_get_parent (location);
+				g_object_unref (mount);
+			}
+			g_object_unref (location);
+
+			if (parent != NULL) {
+				go_to_file = nautilus_find_existing_uri_in_hierarchy (parent);
+				g_object_unref (parent);
+			}
+
+			if (go_to_file != NULL) {
+				nautilus_window_slot_open_location (slot, go_to_file, 0);
+				g_object_unref (go_to_file);
+			} else {
+				nautilus_window_slot_go_home (slot, FALSE);
+			}
+                }
+	} else {
+                new_location = nautilus_file_get_location (file);
+		nautilus_window_slot_set_location (slot, new_location);
+		g_object_unref (new_location);
+        }
+}
+
+static void
+nautilus_window_slot_set_viewed_file (NautilusWindowSlot *slot,
+				      NautilusFile *file)
+{
+	NautilusFileAttributes attributes;
+
+	if (slot->viewed_file == file) {
+		return;
+	}
+
+	nautilus_file_ref (file);
+
+	if (slot->viewed_file != NULL) {
+                g_signal_handlers_disconnect_by_func (slot->viewed_file,
+                                                      G_CALLBACK (viewed_file_changed_callback),
+						      slot);
+		nautilus_file_monitor_remove (slot->viewed_file,
+					      slot);
+	}
+
+	if (file != NULL) {
+		attributes =
+			NAUTILUS_FILE_ATTRIBUTE_INFO |
+			NAUTILUS_FILE_ATTRIBUTE_LINK_INFO;
+		nautilus_file_monitor_add (file, slot, attributes);
+
+		g_signal_connect_object (file, "changed",
+					 G_CALLBACK (viewed_file_changed_callback), slot, 0);
+	}
+
+	nautilus_file_unref (slot->viewed_file);
+	slot->viewed_file = file;
+}
+
+typedef struct {
+	GCancellable *cancellable;
+	NautilusWindowSlot *slot;
+} MountNotMountedData;
+
+static void
+mount_not_mounted_callback (GObject *source_object,
+			    GAsyncResult *res,
+			    gpointer user_data)
+{
+	MountNotMountedData *data;
+	NautilusWindowSlot *slot;
+	GError *error;
+	GCancellable *cancellable;
+
+	data = user_data;
+	slot = data->slot;
+	cancellable = data->cancellable;
+	g_free (data);
+
+	if (g_cancellable_is_cancelled (cancellable)) {
+		/* Cancelled, don't call back */
+		g_object_unref (cancellable);
+		return;
+	}
+
+	slot->mount_cancellable = NULL;
+
+	slot->details->determine_view_file = nautilus_file_get (slot->details->pending_location);
+
+	error = NULL;
+	if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object), res, &error)) {
+		slot->mount_error = error;
+		got_file_info_for_view_selection_callback (slot->determine_view_file, slot);
+		slot->mount_error = NULL;
+		g_error_free (error);
+	} else {
+		nautilus_file_invalidate_all_attributes (slot->determine_view_file);
+		nautilus_file_call_when_ready (slot->determine_view_file,
+					       NAUTILUS_FILE_ATTRIBUTE_INFO,
+					       got_file_info_for_view_selection_callback,
+					       slot);
+	}
+
+	g_object_unref (cancellable);
+}
+
+static void
+got_file_info_for_view_selection_callback (NautilusFile *file,
+					   gpointer callback_data)
+{
+        GError *error = NULL;
+	char *view_id;
+	char *mimetype;
+	NautilusWindow *window;
+	NautilusWindowSlot *slot;
+	NautilusFile *viewed_file, *parent_file;
+	GFile *location;
+	GMountOperation *mount_op;
+	MountNotMountedData *data;
+	GtkApplication *app;
+
+	slot = callback_data;
+	window = nautilus_window_slot_get_window (slot);
+
+	g_assert (slot->determine_view_file == file);
+	slot->determine_view_file = NULL;
+
+	nautilus_profile_start (NULL);
+
+	if (slot->mount_error) {
+		error = g_error_copy (slot->mount_error);
+	} else if (nautilus_file_get_file_info_error (file) != NULL) {
+		error = g_error_copy (nautilus_file_get_file_info_error (file));
+	}
+
+	if (error && error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_MOUNTED &&
+	    !slot->tried_mount) {
+		slot->tried_mount = TRUE;
+
+		mount_op = gtk_mount_operation_new (GTK_WINDOW (window));
+		g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
+		location = nautilus_file_get_location (file);
+		data = g_new0 (MountNotMountedData, 1);
+		data->cancellable = g_cancellable_new ();
+		data->slot = slot;
+		slot->mount_cancellable = data->cancellable;
+		g_file_mount_enclosing_volume (location, 0, mount_op, slot->mount_cancellable,
+					       mount_not_mounted_callback, data);
+		g_object_unref (location);
+		g_object_unref (mount_op);
+
+		goto done;
+	}
+
+	parent_file = nautilus_file_get_parent (file);
+	if ((parent_file != NULL) &&
+	    nautilus_file_get_file_type (file) == G_FILE_TYPE_REGULAR) {
+		if (slot->pending_selection != NULL) {
+			g_list_free_full (slot->pending_selection, (GDestroyNotify) nautilus_file_unref);
+		}
+
+		g_clear_object (&slot->details->pending_location);
+		g_free (slot->details->pending_scroll_to);
+
+		slot->details->pending_location = nautilus_file_get_parent_location (file);
+		slot->details->pending_selection = g_list_prepend (NULL, nautilus_file_ref (file));
+		slot->details->determine_view_file = parent_file;
+		slot->details->pending_scroll_to = nautilus_file_get_uri (file);
+
+		nautilus_file_invalidate_all_attributes (slot->determine_view_file);
+		nautilus_file_call_when_ready (slot->determine_view_file,
+					       NAUTILUS_FILE_ATTRIBUTE_INFO,
+					       got_file_info_for_view_selection_callback,
+					       slot);
+
+		goto done;
+	}
+
+	nautilus_file_unref (parent_file);
+	location = slot->details->pending_location;
+
+	view_id = NULL;
+
+        if (error == NULL ||
+	    (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_SUPPORTED)) {
+		/* We got the information we need, now pick what view to use: */
+
+		mimetype = nautilus_file_get_mime_type (file);
+
+		/* Otherwise, use default */
+		if (slot->details->content_view != NULL) {
+			view_id = g_strdup (nautilus_view_get_view_id (slot->details->content_view));
+		}
+
+		if (view_id == NULL) {
+			view_id = nautilus_global_preferences_get_default_folder_viewer_preference_as_iid ();
+
+			if (view_id != NULL &&
+			    !nautilus_view_factory_view_supports_uri (view_id,
+								      location,
+								      nautilus_file_get_file_type (file),
+								      mimetype)) {
+				g_free (view_id);
+				view_id = NULL;
+			}
+		}
+
+		g_free (mimetype);
+	}
+
+	if (view_id != NULL) {
+		GError *err = NULL;
+
+		create_content_view (slot, view_id, &err);
+		g_free (view_id);
+
+		report_callback (slot, err);
+		g_clear_error (&err);
+	} else {
+		if (error == NULL) {
+			error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+					     _("Unable to load location"));
+		}
+		if (!report_callback (slot, error)) {
+			display_view_selection_failure (window, file,
+							location, error);
+		}
+
+		if (!gtk_widget_get_visible (GTK_WIDGET (window))) {
+			/* Destroy never-had-a-chance-to-be-seen window. This case
+			 * happens when a new window cannot display its initial URI.
+			 */
+			/* if this is the only window, we don't want to quit, so we redirect it to home */
+
+			app = GTK_APPLICATION (g_application_get_default ());
+
+			if (g_list_length (gtk_application_get_windows (app)) == 1) {
+				/* the user could have typed in a home directory that doesn't exist,
+				   in which case going home would cause an infinite loop, so we
+				   better test for that */
+
+				if (!nautilus_is_root_directory (location)) {
+					if (!nautilus_is_home_directory (location)) {
+						nautilus_window_slot_go_home (slot, FALSE);
+					} else {
+						GFile *root;
+
+						root = g_file_new_for_path ("/");
+						/* the last fallback is to go to a known place that can't be deleted! */
+						nautilus_window_slot_open_location (slot, location, 0);
+						g_object_unref (root);
+					}
+				} else {
+					gtk_widget_destroy (GTK_WIDGET (window));
+				}
+			} else {
+				/* Since this is a window, destroying it will also unref it. */
+				gtk_widget_destroy (GTK_WIDGET (window));
+			}
+		} else {
+			GFile *slot_location;
+
+			/* Clean up state of already-showing window */
+			end_location_change (slot);
+			slot_location = nautilus_window_slot_get_location (slot);
+
+			/* We're missing a previous location (if opened location
+			 * in a new tab) so close it and return */
+			if (slot_location == NULL) {
+				nautilus_window_slot_close (window, slot);
+			} else {
+				/* We disconnected this, so we need to re-connect it */
+				viewed_file = nautilus_file_get (slot_location);
+				nautilus_window_slot_set_viewed_file (slot, viewed_file);
+				nautilus_file_unref (viewed_file);
+
+				/* Leave the location bar showing the bad location that the user
+				 * typed (or maybe achieved by dragging or something). Many times
+				 * the mistake will just be an easily-correctable typo. The user
+				 * can choose "Refresh" to get the original URI back in the location bar.
+				 */
+			}
+		}
+	}
+
+ done:
+	g_clear_error (&error);
+
+	nautilus_file_unref (file);
+
+	nautilus_profile_end (NULL);
+}
+
+/* Load a view into the window, either reusing the old one or creating
+ * a new one. This happens when you want to load a new location, or just
+ * switch to a different view.
+ * If pending_location is set we're loading a new location and
+ * pending_location/selection will be used. If not, we're just switching
+ * view, and the current location will be used.
+ */
+static gboolean
+create_content_view (NautilusWindowSlot *slot,
+		     const char *view_id,
+		     GError **error_out)
+{
+	NautilusWindow *window;
+        NautilusView *view;
+	GList *selection;
+	gboolean ret = TRUE;
+	GError *error = NULL;
+	NautilusDirectory *old_directory, *new_directory;
+	GFile *old_location;
+
+	window = nautilus_window_slot_get_window (slot);
+
+	nautilus_profile_start (NULL);
+
+	/* FIXME bugzilla.gnome.org 41243:
+	 * We should use inheritance instead of these special cases
+	 * for the desktop window.
+	 */
+	if (NAUTILUS_IS_DESKTOP_WINDOW (window)) {
+		/* We force the desktop to use a desktop_icon_view. It's simpler
+		 * to fix it here than trying to make it pick the right view in
+		 * the first place.
+		 */
+		view_id = NAUTILUS_DESKTOP_ICON_VIEW_IID;
+	}
+
+        if (slot->details->content_view != NULL &&
+	    g_strcmp0 (nautilus_view_get_view_id (slot->details->content_view),
+			view_id) == 0) {
+                /* reuse existing content view */
+                view = slot->details->content_view;
+                slot->details->new_content_view = view;
+		g_object_ref (view);
+        } else {
+                /* create a new content view */
+		view = nautilus_view_factory_create (view_id, slot);
+
+                slot->new_content_view = view;
+		nautilus_window_slot_connect_new_content_view (slot);
+        }
+
+	/* Forward search selection and state before loading the new model */
+	old_location = nautilus_window_slot_get_location (slot);
+	old_directory = nautilus_directory_get (old_location);
+	new_directory = nautilus_directory_get (slot->pending_location);
+
+	if (NAUTILUS_IS_SEARCH_DIRECTORY (new_directory) &&
+	    !NAUTILUS_IS_SEARCH_DIRECTORY (old_directory)) {
+		nautilus_search_directory_set_base_model (NAUTILUS_SEARCH_DIRECTORY (new_directory), old_directory);
+	}
+
+	if (NAUTILUS_IS_SEARCH_DIRECTORY (old_directory) &&
+	    !NAUTILUS_IS_SEARCH_DIRECTORY (new_directory) &&
+	    slot->pending_selection == NULL) {
+		slot->pending_selection = nautilus_view_get_selection (slot->content_view);
+	}
+
+	/* Actually load the pending location and selection: */
+
+        if (slot->pending_location != NULL) {
+		load_new_location (slot,
+				   slot->pending_location,
+				   slot->pending_selection,
+				   FALSE,
+				   TRUE);
+
+		g_list_free_full (slot->pending_selection, g_object_unref);
+		slot->pending_selection = NULL;
+	} else if (old_location != NULL) {
+		selection = nautilus_view_get_selection (slot->content_view);
+		load_new_location (slot,
+				   old_location,
+				   selection,
+				   FALSE,
+				   TRUE);
+		g_list_free_full (selection, g_object_unref);
+	} else {
+		/* Something is busted, there was no location to load. */
+		ret = FALSE;
+		error = g_error_new (G_IO_ERROR,
+				     G_IO_ERROR_NOT_FOUND,
+				     _("Unable to load location"));
+	}
+
+	if (error != NULL) {
+		g_propagate_error (error_out, error);
+	}
+
+	nautilus_profile_end (NULL);
+
+	return ret;
+}
+
+static void
+load_new_location (NautilusWindowSlot *slot,
+		   GFile *location,
+		   GList *selection,
+		   gboolean tell_current_content_view,
+		   gboolean tell_new_content_view)
+{
+	GList *selection_copy;
+	NautilusView *view;
+
+	g_assert (slot != NULL);
+	g_assert (location != NULL);
+
+	selection_copy = eel_g_object_list_copy (selection);
+	view = NULL;
+
+	nautilus_profile_start (NULL);
+	/* Note, these may recurse into report_load_underway */
+        if (slot->content_view != NULL && tell_current_content_view) {
+		view = slot->content_view;
+		nautilus_view_load_location (slot->content_view, location);
+        }
+
+        if (slot->new_content_view != NULL && tell_new_content_view &&
+	    (!tell_current_content_view ||
+	     slot->new_content_view != slot->content_view) ) {
+		view = slot->new_content_view;
+		nautilus_view_load_location (slot->new_content_view, location);
+        }
+	if (view != NULL) {
+		/* slot->new_content_view might have changed here if
+		   report_load_underway was called from load_location */
+		nautilus_view_set_selection (view, selection_copy);
+	}
+
+	g_list_free_full (selection_copy, g_object_unref);
+
+	nautilus_profile_end (NULL);
+}
+
+static void
+end_location_change (NautilusWindowSlot *slot)
+{
+	char *uri;
+
+	uri = nautilus_window_slot_get_location_uri (slot);
+	if (uri) {
+		DEBUG ("Finished loading window for uri %s", uri);
+		g_free (uri);
+	}
+
+	nautilus_window_slot_set_allow_stop (slot, FALSE);
+
+        /* Now we can free pending_scroll_to, since the load_complete
+         * callback already has been emitted.
+         */
+	g_free (slot->pending_scroll_to);
+	slot->pending_scroll_to = NULL;
+
+	free_location_change (slot);
+}
+
+static void
+free_location_change (NautilusWindowSlot *slot)
+{
+	NautilusWindow *window;
+
+	window = nautilus_window_slot_get_window (slot);
+
+	g_clear_object (&slot->pending_location);
+	g_list_free_full (slot->pending_selection, g_object_unref);
+	slot->pending_selection = NULL;
+
+        /* Don't free pending_scroll_to, since thats needed until
+         * the load_complete callback.
+         */
+
+	if (slot->mount_cancellable != NULL) {
+		g_cancellable_cancel (slot->mount_cancellable);
+		slot->mount_cancellable = NULL;
+	}
+
+        if (slot->determine_view_file != NULL) {
+		nautilus_file_cancel_call_when_ready
+			(slot->determine_view_file,
+			 got_file_info_for_view_selection_callback, slot);
+                slot->determine_view_file = NULL;
+        }
+
+        if (slot->new_content_view != NULL) {
+		slot->details->temporarily_ignore_view_signals = TRUE;
+		nautilus_view_stop_loading (slot->new_content_view);
+		slot->details->temporarily_ignore_view_signals = FALSE;
+
+		nautilus_window_disconnect_content_view (window, slot->new_content_view);
+        	g_object_unref (slot->new_content_view);
+                slot->new_content_view = NULL;
+        }
+}
+
+static void
+cancel_location_change (NautilusWindowSlot *slot)
+{
+	GList *selection;
+	GFile *location;
+
+	location = nautilus_window_slot_get_location (slot);
+        if (slot->details->pending_location != NULL
+            && location != NULL
+            && slot->content_view != NULL) {
+
+                /* No need to tell the new view - either it is the
+                 * same as the old view, in which case it will already
+                 * be told, or it is the very pending change we wish
+                 * to cancel.
+                 */
+		selection = nautilus_view_get_selection (slot->content_view);
+                load_new_location (slot,
+				   location,
+				   selection,
+				   TRUE,
+				   FALSE);
+		g_list_free_full (selection, g_object_unref);
+        }
+
+        end_location_change (slot);
+}
+
+static void
+display_view_selection_failure (NautilusWindow *window, NautilusFile *file,
+				GFile *location, GError *error)
+{
+	char *error_message;
+	char *detail_message;
+	char *scheme_string;
+
+	/* Some sort of failure occurred. How 'bout we tell the user? */
+
+	error_message = g_strdup (_("Oops! Something went wrong."));
+	detail_message = NULL;
+	if (error == NULL) {
+		if (nautilus_file_is_directory (file)) {
+			detail_message = g_strdup (_("Unable to display the contents of this folder."));
+		} else {
+			detail_message = g_strdup (_("This location doesn't appear to be a folder."));
+		}
+	} else if (error->domain == G_IO_ERROR) {
+		switch (error->code) {
+		case G_IO_ERROR_NOT_FOUND:
+			error_message = g_strdup (_("Unable to find the requested file. Please check the spelling and try again."));
+			break;
+		case G_IO_ERROR_NOT_SUPPORTED:
+			scheme_string = g_file_get_uri_scheme (location);
+			if (scheme_string != NULL) {
+				detail_message = g_strdup_printf (_("â%sâ locations are not supported."),
+								  scheme_string);
+			} else {
+				detail_message = g_strdup (_("Unable to handle this kind of location."));
+			}
+			g_free (scheme_string);
+			break;
+		case G_IO_ERROR_NOT_MOUNTED:
+			detail_message = g_strdup (_("Unable to access the requested location."));
+			break;
+		case G_IO_ERROR_PERMISSION_DENIED:
+			detail_message = g_strdup (_("Don't have permission to access the requested location."));
+			break;
+		case G_IO_ERROR_HOST_NOT_FOUND:
+			/* This case can be hit for user-typed strings like "foo" due to
+			 * the code that guesses web addresses when there's no initial "/".
+			 * But this case is also hit for legitimate web addresses when
+			 * the proxy is set up wrong.
+			 */
+			detail_message = g_strdup (_("Unable to find the requested location. Please check the spelling or the network settings."));
+			break;
+		case G_IO_ERROR_CANCELLED:
+		case G_IO_ERROR_FAILED_HANDLED:
+			goto done;
+		default:
+			break;
+		}
+	}
+
+	if (detail_message == NULL) {
+		detail_message = g_strdup_printf (_("Unhandled error message: %s"), error->message);
+	}
+
+	eel_show_error_dialog (error_message, detail_message, GTK_WINDOW (window));
+ done:
+	g_free (error_message);
+	g_free (detail_message);
+}
+
+
+void
+nautilus_window_slot_stop_loading (NautilusWindowSlot *slot)
+{
+	nautilus_view_stop_loading (slot->content_view);
+	
+	if (slot->new_content_view != NULL) {
+		slot->details->temporarily_ignore_view_signals = TRUE;
+		nautilus_view_stop_loading (slot->new_content_view);
+		slot->details->temporarily_ignore_view_signals = FALSE;
+	}
+
+        cancel_location_change (slot);
+}
+
+void
+nautilus_window_slot_set_content_view (NautilusWindowSlot *slot,
+				       const char *id)
+{
+	char *uri;
+
+	g_assert (slot != NULL);
+	g_assert (id != NULL);
+
+	uri = nautilus_window_slot_get_location_uri (slot);
+	DEBUG ("Change view of window %s to %s", uri, id);
+	g_free (uri);
+
+	if (nautilus_window_slot_content_view_matches_iid (slot, id)) {
+		return;
+        }
+
+        end_location_change (slot);
+
+        nautilus_window_slot_set_allow_stop (slot, TRUE);
+
+        if (nautilus_view_get_selection_count (slot->content_view) == 0) {
+                /* If there is no selection, queue a scroll to the same icon that
+                 * is currently visible */
+                slot->pending_scroll_to = nautilus_view_get_first_visible_file (slot->content_view);
+        }
+	slot->details->location_change_type = NAUTILUS_LOCATION_CHANGE_RELOAD;
+
+	if (!create_content_view (slot, id, NULL)) {
+		/* Just load the homedir. */
+		nautilus_window_slot_go_home (slot, FALSE);
+	}
+}
+
+void
+nautilus_window_back_or_forward (NautilusWindow *window,
+				 gboolean back,
+				 guint distance,
+				 NautilusWindowOpenFlags flags)
+{
+	NautilusWindowSlot *slot;
+	GList *list;
+	GFile *location;
+	guint len;
+	NautilusBookmark *bookmark;
+	GFile *old_location;
+
+	slot = nautilus_window_get_active_slot (window);
+	list = back ? slot->back_list : slot->forward_list;
+
+        len = (guint) g_list_length (list);
+
+        /* If we can't move in the direction at all, just return. */
+        if (len == 0)
+                return;
+
+        /* If the distance to move is off the end of the list, go to the end
+           of the list. */
+        if (distance >= len)
+                distance = len - 1;
+
+        bookmark = g_list_nth_data (list, distance);
+	location = nautilus_bookmark_get_location (bookmark);
+
+	if (flags != 0) {
+		nautilus_window_slot_open_location (slot, location, flags);
+	} else {
+		char *scroll_pos;
+
+		old_location = nautilus_window_slot_get_location (slot);
+		scroll_pos = nautilus_bookmark_get_scroll_pos (bookmark);
+		begin_location_change
+			(slot,
+			 location, old_location, NULL,
+			 back ? NAUTILUS_LOCATION_CHANGE_BACK : NAUTILUS_LOCATION_CHANGE_FORWARD,
+			 distance,
+			 scroll_pos,
+			 NULL, NULL);
+
+		g_free (scroll_pos);
+	}
+
+	g_object_unref (location);
+}
+
+/* reload the contents of the window */
+static void
+nautilus_window_slot_force_reload (NautilusWindowSlot *slot)
+{
+	GFile *location;
+        char *current_pos;
+	GList *selection;
+
+	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
+
+	location = nautilus_window_slot_get_location (slot);
+	if (location == NULL) {
+		return;
+	}
+
+	/* peek_slot_field (window, location) can be free'd during the processing
+	 * of begin_location_change, so make a copy
+	 */
+	g_object_ref (location);
+	current_pos = NULL;
+	selection = NULL;
+	if (slot->content_view != NULL) {
+		current_pos = nautilus_view_get_first_visible_file (slot->content_view);
+		selection = nautilus_view_get_selection (slot->content_view);
+	}
+	begin_location_change
+		(slot, location, location, selection,
+		 NAUTILUS_LOCATION_CHANGE_RELOAD, 0, current_pos,
+		 NULL, NULL);
+        g_free (current_pos);
+	g_object_unref (location);
+	g_list_free_full (selection, g_object_unref);
+}
+
+void
+nautilus_window_slot_queue_reload (NautilusWindowSlot *slot)
+{
+	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
+
+	if (nautilus_window_slot_get_location (slot) == NULL) {
+		return;
+	}
+
+	if (slot->pending_location != NULL
+	    || slot->content_view == NULL
+	    || nautilus_view_get_loading (slot->content_view)) {
+		/* there is a reload in flight */
+		slot->details->needs_reload = TRUE;
+		return;
+	}
+
+	nautilus_window_slot_force_reload (slot);
+}
+
+static void
+nautilus_window_slot_clear_forward_list (NautilusWindowSlot *slot)
+{
+	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
+
+	g_list_free_full (slot->forward_list, g_object_unref);
+	slot->forward_list = NULL;
+}
+
+static void
+nautilus_window_slot_clear_back_list (NautilusWindowSlot *slot)
+{
+	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
+
+	g_list_free_full (slot->back_list, g_object_unref);
+	slot->back_list = NULL;
+}
+
+static void
+set_displayed_file (NautilusWindowSlot *slot, NautilusFile *file)
+{
+        gboolean recreate;
+	GFile *new_location = NULL;
+
+	if (file != NULL) {
+		new_location = nautilus_file_get_location (file);
+	}
+
+        if (slot->current_location_bookmark == NULL || file == NULL) {
+                recreate = TRUE;
+        } else {
+		GFile *bookmark_location;
+                bookmark_location = nautilus_bookmark_get_location (slot->current_location_bookmark);
+                recreate = !g_file_equal (bookmark_location, new_location);
+                g_object_unref (bookmark_location);
+        }
+
+        if (recreate) {
+		char *display_name = NULL;
+
+                /* We've changed locations, must recreate bookmark for current location. */
+		g_clear_object (&slot->last_location_bookmark);
+
+		if (file != NULL) {
+			display_name = nautilus_file_get_display_name (file);
+		}
+		slot->last_location_bookmark = slot->current_location_bookmark;
+		if (new_location == NULL) {
+			slot->current_location_bookmark = NULL;
+		} else {
+			slot->current_location_bookmark = nautilus_bookmark_new (new_location, display_name);
+		}
+		g_free (display_name);
+        }
+
+	g_clear_object (&new_location);
+}
+
+static void
+check_bookmark_location_matches (NautilusBookmark *bookmark, GFile *location)
+{
+        GFile *bookmark_location;
+        char *bookmark_uri, *uri;
+
+	bookmark_location = nautilus_bookmark_get_location (bookmark);
+	if (!g_file_equal (location, bookmark_location)) {
+		bookmark_uri = g_file_get_uri (bookmark_location);
+		uri = g_file_get_uri (location);
+		g_warning ("bookmark uri is %s, but expected %s", bookmark_uri, uri);
+		g_free (uri);
+		g_free (bookmark_uri);
+	}
+	g_object_unref (bookmark_location);
+}
+
+/* Debugging function used to verify that the last_location_bookmark
+ * is in the state we expect when we're about to use it to update the
+ * Back or Forward list.
+ */
+static void
+check_last_bookmark_location_matches_slot (NautilusWindowSlot *slot)
+{
+	check_bookmark_location_matches (slot->last_location_bookmark,
+					 nautilus_window_slot_get_location (slot));
+}
+
+static void
+handle_go_back (NautilusWindowSlot *slot,
+		GFile *location)
+{
+	guint i;
+	GList *link;
+	NautilusBookmark *bookmark;
+
+	/* Going back. Move items from the back list to the forward list. */
+	g_assert (g_list_length (slot->back_list) > slot->location_change_distance);
+	check_bookmark_location_matches (NAUTILUS_BOOKMARK (g_list_nth_data (slot->back_list,
+									     slot->location_change_distance)),
+					 location);
+	g_assert (nautilus_window_slot_get_location (slot) != NULL);
+
+	/* Move current location to Forward list */
+
+	check_last_bookmark_location_matches_slot (slot);
+
+	/* Use the first bookmark in the history list rather than creating a new one. */
+	slot->details->forward_list = g_list_prepend (slot->details->forward_list,
+						      slot->details->last_location_bookmark);
+	g_object_ref (slot->details->forward_list->data);
+
+	/* Move extra links from Back to Forward list */
+	for (i = 0; i < slot->location_change_distance; ++i) {
+		bookmark = NAUTILUS_BOOKMARK (slot->back_list->data);
+		slot->back_list =
+			g_list_remove (slot->back_list, bookmark);
+		slot->forward_list =
+			g_list_prepend (slot->forward_list, bookmark);
+	}
+
+	/* One bookmark falls out of back/forward lists and becomes viewed location */
+	link = slot->back_list;
+	slot->back_list = g_list_remove_link (slot->back_list, link);
+	g_object_unref (link->data);
+	g_list_free_1 (link);
+}
+
+static void
+handle_go_forward (NautilusWindowSlot *slot,
+		   GFile *location)
+{
+	guint i;
+	GList *link;
+	NautilusBookmark *bookmark;
+
+	/* Going forward. Move items from the forward list to the back list. */
+	g_assert (g_list_length (slot->forward_list) > slot->location_change_distance);
+	check_bookmark_location_matches (NAUTILUS_BOOKMARK (g_list_nth_data (slot->forward_list,
+									     slot->location_change_distance)),
+					 location);
+	g_assert (nautilus_window_slot_get_location (slot) != NULL);
+
+	/* Move current location to Back list */
+	check_last_bookmark_location_matches_slot (slot);
+
+	/* Use the first bookmark in the history list rather than creating a new one. */
+	slot->details->back_list = g_list_prepend (slot->details->back_list,
+						   slot->details->last_location_bookmark);
+	g_object_ref (slot->details->back_list->data);
+
+	/* Move extra links from Forward to Back list */
+	for (i = 0; i < slot->location_change_distance; ++i) {
+		bookmark = NAUTILUS_BOOKMARK (slot->forward_list->data);
+		slot->forward_list =
+			g_list_remove (slot->back_list, bookmark);
+		slot->back_list =
+			g_list_prepend (slot->forward_list, bookmark);
+	}
+
+	/* One bookmark falls out of back/forward lists and becomes viewed location */
+	link = slot->forward_list;
+	slot->forward_list = g_list_remove_link (slot->forward_list, link);
+	g_object_unref (link->data);
+	g_list_free_1 (link);
+}
+
+static void
+handle_go_elsewhere (NautilusWindowSlot *slot,
+		     GFile *location)
+{
+	GFile *slot_location;
+
+	/* Clobber the entire forward list, and move displayed location to back list */
+	nautilus_window_slot_clear_forward_list (slot);
+	slot_location = nautilus_window_slot_get_location (slot);
+
+	if (slot_location != NULL) {
+		/* If we're returning to the same uri somehow, don't put this uri on back list.
+		 * This also avoids a problem where set_displayed_location
+		 * didn't update last_location_bookmark since the uri didn't change.
+		 */
+		if (!g_file_equal (slot_location, location)) {
+			/* Store bookmark for current location in back list, unless there is no current location */
+			check_last_bookmark_location_matches_slot (slot);
+			/* Use the first bookmark in the history list rather than creating a new one. */
+			slot->back_list = g_list_prepend (slot->back_list,
+							  slot->last_location_bookmark);
+			g_object_ref (slot->back_list->data);
+		}
+	}
+}
+
+static void
+update_history (NautilusWindowSlot *slot,
+                NautilusLocationChangeType type,
+                GFile *new_location)
+{
+        switch (type) {
+        case NAUTILUS_LOCATION_CHANGE_STANDARD:
+		handle_go_elsewhere (slot, new_location);
+                return;
+        case NAUTILUS_LOCATION_CHANGE_RELOAD:
+                /* for reload there is no work to do */
+                return;
+        case NAUTILUS_LOCATION_CHANGE_BACK:
+                handle_go_back (slot, new_location);
+                return;
+        case NAUTILUS_LOCATION_CHANGE_FORWARD:
+                handle_go_forward (slot, new_location);
+                return;
+        }
+	g_return_if_fail (FALSE);
+}
+
+typedef struct {
+	NautilusWindowSlot *slot;
+	GCancellable *cancellable;
+	GMount *mount;
+} FindMountData;
+
+static void
+nautilus_window_slot_show_x_content_bar (NautilusWindowSlot *slot, GMount *mount, const char **x_content_types)
+{
+	GtkWidget *bar;
+
+	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
+
+	bar = nautilus_x_content_bar_new (mount, x_content_types);
+	gtk_widget_show (bar);
+	nautilus_window_slot_add_extra_location_widget (slot, bar);
+}
+
+static void
+found_content_type_cb (const char **x_content_types,
+		       gpointer user_data)
+{
+	NautilusWindowSlot *slot;
+	FindMountData *data = user_data;
+
+	if (g_cancellable_is_cancelled (data->cancellable)) {
+		goto out;
+	}
+
+	slot = data->slot;
+
+	if (x_content_types != NULL && x_content_types[0] != NULL) {
+		nautilus_window_slot_show_x_content_bar (slot, data->mount, x_content_types);
+	}
+
+	slot->details->find_mount_cancellable = NULL;
+
+ out:
+	g_object_unref (data->mount);
+	g_object_unref (data->cancellable);
+	g_free (data);
+}
+
+static void
+found_mount_cb (GObject *source_object,
+		GAsyncResult *res,
+		gpointer user_data)
+{
+	FindMountData *data = user_data;
+	GMount *mount;
+
+	if (g_cancellable_is_cancelled (data->cancellable)) {
+		goto out;
+	}
+
+	mount = g_file_find_enclosing_mount_finish (G_FILE (source_object),
+						    res,
+						    NULL);
+	if (mount != NULL) {
+		data->mount = mount;
+		nautilus_get_x_content_types_for_mount_async (mount,
+							      found_content_type_cb,
+							      data->cancellable,
+							      data);
+		return;
+	}
+
+	data->slot->details->find_mount_cancellable = NULL;
+
+ out:
+	g_object_unref (data->cancellable);
+	g_free (data);
+}
+
+static void
+nautilus_window_slot_emit_location_change (NautilusWindowSlot *slot,
+					   GFile *from,
+					   GFile *to)
+{
+	char *from_uri = NULL;
+	char *to_uri = NULL;
+
+	if (from != NULL)
+		from_uri = g_file_get_uri (from);
+	if (to != NULL)
+		to_uri = g_file_get_uri (to);
+	g_signal_emit_by_name (slot, "location-changed", from_uri, to_uri);
+	g_free (to_uri);
+	g_free (from_uri);
+}
+
+static void
+nautilus_window_slot_show_trash_bar (NautilusWindowSlot *slot)
 {
-	if (action == NAUTILUS_FLOATING_BAR_ACTION_ID_STOP) {
-		nautilus_window_slot_stop_loading (slot);
-	}
+	GtkWidget *bar;
+	NautilusView *view;
+
+	view = nautilus_window_slot_get_current_view (slot);
+	bar = nautilus_trash_bar_new (view);
+	gtk_widget_show (bar);
+
+	nautilus_window_slot_add_extra_location_widget (slot, bar);
 }
 
 static void
-nautilus_window_slot_set_property (GObject *object,
-				   guint property_id,
-				   const GValue *value,
-				   GParamSpec *pspec)
+nautilus_window_slot_show_special_location_bar (NautilusWindowSlot     *slot,
+						NautilusSpecialLocation special_location)
 {
-	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (object);
+	GtkWidget *bar;
 
-	switch (property_id) {
-	case PROP_WINDOW:
-		nautilus_window_slot_set_window (slot, g_value_get_object (value));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-		break;
-	}
+	bar = nautilus_special_location_bar_new (special_location);
+	gtk_widget_show (bar);
+
+	nautilus_window_slot_add_extra_location_widget (slot, bar);
 }
 
 static void
-nautilus_window_slot_get_property (GObject *object,
-				   guint property_id,
-				   GValue *value,
-				   GParamSpec *pspec)
+slot_add_extension_extra_widgets (NautilusWindowSlot *slot)
 {
-	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (object);
+	GList *providers, *l;
+	GtkWidget *widget;
+	char *uri;
+	NautilusWindow *window;
 
-	switch (property_id) {
-	case PROP_WINDOW:
-		g_value_set_object (value, slot->details->window);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-		break;
+	providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_LOCATION_WIDGET_PROVIDER);
+	window = nautilus_window_slot_get_window (slot);
+
+	uri = nautilus_window_slot_get_location_uri (slot);
+	for (l = providers; l != NULL; l = l->next) {
+		NautilusLocationWidgetProvider *provider;
+
+		provider = NAUTILUS_LOCATION_WIDGET_PROVIDER (l->data);
+		widget = nautilus_location_widget_provider_get_widget (provider, uri, GTK_WIDGET (window));
+		if (widget != NULL) {
+			nautilus_window_slot_add_extra_location_widget (slot, widget);
+		}
 	}
+	g_free (uri);
+
+	nautilus_module_extension_list_free (providers);
 }
 
 static void
-nautilus_window_slot_constructed (GObject *object)
+nautilus_window_slot_update_for_new_location (NautilusWindowSlot *slot)
 {
-	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (object);
-	GtkWidget *extras_vbox;
+	NautilusWindow *window;
+        GFile *new_location, *old_location;
+        NautilusFile *file;
+	NautilusDirectory *directory;
+	gboolean location_really_changed;
+	FindMountData *data;
 
-	G_OBJECT_CLASS (nautilus_window_slot_parent_class)->constructed (object);
+	window = nautilus_window_slot_get_window (slot);
+	new_location = slot->pending_location;
+	slot->pending_location = NULL;
 
-	gtk_orientable_set_orientation (GTK_ORIENTABLE (slot),
-					GTK_ORIENTATION_VERTICAL);
-	gtk_widget_show (GTK_WIDGET (slot));
+	file = nautilus_file_get (new_location);
+	set_displayed_file (slot, file);
 
-	extras_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-	slot->extra_location_widgets = extras_vbox;
-	gtk_box_pack_start (GTK_BOX (slot), extras_vbox, FALSE, FALSE, 0);
-	gtk_widget_show (extras_vbox);
+	update_history (slot, slot->location_change_type, new_location);
+	old_location = nautilus_window_slot_get_location (slot);
 
-	slot->query_editor = NAUTILUS_QUERY_EDITOR (nautilus_query_editor_new ());
-	nautilus_window_slot_add_extra_location_widget (slot, GTK_WIDGET (slot->query_editor));
-	g_object_add_weak_pointer (G_OBJECT (slot->query_editor),
-				   (gpointer *) &slot->query_editor);
+	location_really_changed =
+		old_location == NULL ||
+		!g_file_equal (old_location, new_location);
 
-	slot->details->view_overlay = gtk_overlay_new ();
-	gtk_widget_add_events (slot->details->view_overlay,
-			       GDK_ENTER_NOTIFY_MASK |
-			       GDK_LEAVE_NOTIFY_MASK);
-	gtk_box_pack_start (GTK_BOX (slot), slot->details->view_overlay, TRUE, TRUE, 0);
-	gtk_widget_show (slot->details->view_overlay);
+        /* Create a NautilusFile for this location, so we can catch it
+         * if it goes away.
+         */
+	nautilus_window_slot_set_viewed_file (slot, file);
+	slot->viewed_file_seen = !nautilus_file_is_not_yet_confirmed (file);
+	slot->viewed_file_in_trash = nautilus_file_is_in_trash (file);
+        nautilus_file_unref (file);
 
-	slot->details->floating_bar = nautilus_floating_bar_new (NULL, NULL, FALSE);
-	gtk_widget_set_halign (slot->details->floating_bar, GTK_ALIGN_END);
-	gtk_widget_set_valign (slot->details->floating_bar, GTK_ALIGN_END);
-	gtk_overlay_add_overlay (GTK_OVERLAY (slot->details->view_overlay),
-				 slot->details->floating_bar);
+	nautilus_window_slot_emit_location_change (slot, old_location, new_location);
+	nautilus_window_slot_set_location (slot, new_location);
 
-	g_signal_connect (slot->details->floating_bar, "action",
-			  G_CALLBACK (floating_bar_action_cb), slot);
+	if (slot == nautilus_window_get_active_slot (window)) {
+		/* Sync up and zoom action states */
+		nautilus_window_sync_up_button (window);
+		nautilus_window_sync_zoom_widgets (window);
 
-	slot->title = g_strdup (_("Loading..."));
-}
+		/* Sync the content view menu for this new location. */
+		nautilus_window_sync_view_as_menus (window);
 
-static void
-nautilus_window_slot_init (NautilusWindowSlot *slot)
-{
-	slot->details = G_TYPE_INSTANCE_GET_PRIVATE
-		(slot, NAUTILUS_TYPE_WINDOW_SLOT, NautilusWindowSlotDetails);
-}
+		/* Load menus from nautilus extensions for this location */
+		nautilus_window_load_extension_menus (window);
+	}
 
-static void
-remove_loading_floating_bar (NautilusWindowSlot *slot)
-{
-	if (slot->details->loading_timeout_id != 0) {
-		g_source_remove (slot->details->loading_timeout_id);
-		slot->details->loading_timeout_id = 0;
+	if (location_really_changed) {
+		nautilus_window_slot_remove_extra_location_widgets (slot);
+
+		directory = nautilus_directory_get (new_location);
+
+		if (nautilus_directory_is_in_trash (directory)) {
+			nautilus_window_slot_show_trash_bar (slot);
+		} else {
+			GFile *scripts_file;
+			char *scripts_path = nautilus_get_scripts_directory_path ();
+			scripts_file = g_file_new_for_path (scripts_path);
+			g_free (scripts_path);
+			if (nautilus_should_use_templates_directory () &&
+			    nautilus_file_is_user_special_directory (file, G_USER_DIRECTORY_TEMPLATES)) {
+				nautilus_window_slot_show_special_location_bar (slot, NAUTILUS_SPECIAL_LOCATION_TEMPLATES);
+			} else if (g_file_equal (new_location, scripts_file)) {
+				nautilus_window_slot_show_special_location_bar (slot, NAUTILUS_SPECIAL_LOCATION_SCRIPTS);
+			}
+			g_object_unref (scripts_file);
+		}
+
+		/* need the mount to determine if we should put up the x-content cluebar */
+		if (slot->details->find_mount_cancellable != NULL) {
+			g_cancellable_cancel (slot->details->find_mount_cancellable);
+			slot->details->find_mount_cancellable = NULL;
+		}
+
+		data = g_new (FindMountData, 1);
+		data->slot = slot;
+		data->cancellable = g_cancellable_new ();
+		data->mount = NULL;
+
+		slot->details->find_mount_cancellable = data->cancellable;
+		g_file_find_enclosing_mount_async (new_location,
+						   G_PRIORITY_DEFAULT,
+						   data->cancellable,
+						   found_mount_cb,
+						   data);
+
+		nautilus_directory_unref (directory);
+
+		slot_add_extension_extra_widgets (slot);
 	}
 
-	gtk_widget_hide (slot->details->floating_bar);
-	nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (slot->details->floating_bar));
+	if (slot == nautilus_window_get_active_slot (window)) {
+		if (location_really_changed) {
+			nautilus_window_sync_search_widgets (window);
+		}
+	}
 }
 
 static void
@@ -416,15 +2068,28 @@ view_end_loading_cb (NautilusView       *view,
 		     gboolean            all_files_seen,
 		     NautilusWindowSlot *slot)
 {
-	if (slot->needs_reload) {
+	if (slot->details->temporarily_ignore_view_signals) {
+		return;
+	}
+
+	/* Only handle this if we're expecting it.
+	 * Don't handle it if its from an old view we've switched from */
+	if (view == slot->content_view && all_files_seen) {
+		if (slot->pending_scroll_to != NULL) {
+			nautilus_view_scroll_to_file (slot->content_view,
+						      slot->pending_scroll_to);
+		}
+		end_location_change (slot);
+	}
+
+	if (slot->details->needs_reload) {
 		nautilus_window_slot_queue_reload (slot);
-		slot->needs_reload = FALSE;
+		slot->details->needs_reload = FALSE;
 	}
 
 	remove_loading_floating_bar (slot);
 }
 
-
 static void
 real_setup_loading_floating_bar (NautilusWindowSlot *slot)
 {
@@ -486,7 +2151,106 @@ static void
 view_begin_loading_cb (NautilusView       *view,
 		       NautilusWindowSlot *slot)
 {
+	if (slot->details->temporarily_ignore_view_signals) {
+		return;
+	}
+
+	nautilus_profile_start (NULL);
+
+	if (view == slot->new_content_view) {
+		location_has_really_changed (slot);
+	} else {
+		nautilus_window_slot_set_allow_stop (slot, TRUE);
+	}
+
 	setup_loading_floating_bar (slot);
+
+	nautilus_profile_end (NULL);
+}
+
+static void
+nautilus_window_slot_connect_new_content_view (NautilusWindowSlot *slot)
+{
+	if (slot->content_view != NULL) {
+		/* disconnect old view */
+		g_signal_handlers_disconnect_by_func (slot->content_view, G_CALLBACK (view_end_loading_cb), slot);
+		g_signal_handlers_disconnect_by_func (slot->content_view, G_CALLBACK (view_begin_loading_cb), slot);
+	}
+
+	if (slot->new_content_view != NULL) {
+		g_signal_connect (slot->new_content_view, "begin-loading", G_CALLBACK (view_begin_loading_cb), slot);
+		g_signal_connect (slot->new_content_view, "end-loading", G_CALLBACK (view_end_loading_cb), slot);
+	}
+}
+
+static void
+nautilus_window_slot_switch_new_content_view (NautilusWindowSlot *slot)
+{
+	NautilusWindow *window;
+	GtkWidget *widget;
+
+	if ((slot->new_content_view == NULL) ||
+	    gtk_widget_get_parent (GTK_WIDGET (slot->new_content_view)) != NULL) {
+		return;
+	}
+
+	window = nautilus_window_slot_get_window (slot);
+
+	if (slot->content_view != NULL) {
+		nautilus_window_disconnect_content_view (window, slot->content_view);
+
+		widget = GTK_WIDGET (slot->content_view);
+		gtk_widget_destroy (widget);
+		g_object_unref (slot->content_view);
+		slot->content_view = NULL;
+	}
+
+	if (slot->new_content_view != NULL) {
+		slot->content_view = slot->new_content_view;
+		slot->new_content_view = NULL;
+
+		widget = GTK_WIDGET (slot->content_view);
+		gtk_container_add (GTK_CONTAINER (slot->details->view_overlay), widget);
+		gtk_widget_show (widget);
+
+		/* connect new view */
+		nautilus_window_connect_content_view (slot->details->window, slot->content_view);
+	}
+}
+
+/* This is called when we have decided we can actually change to the new view/location situation. */
+static void
+location_has_really_changed (NautilusWindowSlot *slot)
+{
+	NautilusWindow *window;
+	GFile *location;
+
+	window = nautilus_window_slot_get_window (slot);
+
+	/* Switch to the new content view. */
+	nautilus_window_slot_switch_new_content_view (slot);
+
+	if (slot->pending_location != NULL) {
+		/* Tell the window we are finished. */
+		nautilus_window_slot_update_for_new_location (slot);
+	}
+
+	location = nautilus_window_slot_get_location (slot);
+	if (location != NULL) {
+		g_object_ref (location);
+	}
+
+	if (location != NULL) {
+		if (slot == nautilus_window_get_active_slot (window)) {
+			char *uri;
+
+			uri = g_file_get_uri (location);
+			g_signal_emit_by_name (window, "loading-uri", uri);
+			g_free (uri);
+		}
+
+		g_object_unref (location);
+	}
 }
 
 static void
@@ -500,7 +2264,10 @@ nautilus_window_slot_dispose (GObject *object)
 	nautilus_window_slot_clear_forward_list (slot);
 	nautilus_window_slot_clear_back_list (slot);
 
-	if (slot->content_view) {
+	if (slot->details->content_view) {
+		nautilus_window_disconnect_content_view (nautilus_window_slot_get_window (slot),
+							 slot->details->content_view);
+
 		widget = GTK_WIDGET (slot->content_view);
 		gtk_widget_destroy (widget);
 		g_object_unref (slot->content_view);
@@ -529,10 +2296,10 @@ nautilus_window_slot_dispose (GObject *object)
 	 * It was already here before the slot move, though */
 	nautilus_file_unref (slot->viewed_file);
 
-	if (slot->location) {
+	if (slot->details->location) {
 		/* TODO? why do we ref here, instead of unreffing?
 		 * It was already here before the slot migration, though */
-		g_object_ref (slot->location);
+		g_object_ref (slot->details->location);
 	}
 
 	g_list_free_full (slot->pending_selection, g_object_unref);
@@ -541,15 +2308,17 @@ nautilus_window_slot_dispose (GObject *object)
 	g_clear_object (&slot->current_location_bookmark);
 	g_clear_object (&slot->last_location_bookmark);
 
-	if (slot->find_mount_cancellable != NULL) {
-		g_cancellable_cancel (slot->find_mount_cancellable);
-		slot->find_mount_cancellable = NULL;
+	if (slot->details->find_mount_cancellable != NULL) {
+		g_cancellable_cancel (slot->details->find_mount_cancellable);
+		slot->details->find_mount_cancellable = NULL;
 	}
 
 	slot->details->window = NULL;
 
-	g_free (slot->title);
-	slot->title = NULL;
+	g_free (slot->details->title);
+	slot->details->title = NULL;
+
+	free_location_change (slot);
 
 	G_OBJECT_CLASS (nautilus_window_slot_parent_class)->dispose (object);
 }
@@ -611,10 +2380,13 @@ nautilus_window_slot_get_location (NautilusWindowSlot *slot)
 {
 	g_assert (slot != NULL);
 
-	if (slot->location != NULL) {
-		return g_object_ref (slot->location);
-	}
-	return NULL;
+	return slot->details->location;
+}
+
+const gchar *
+nautilus_window_slot_get_title (NautilusWindowSlot *slot)
+{
+	return slot->details->title;
 }
 
 char *
@@ -622,8 +2394,8 @@ nautilus_window_slot_get_location_uri (NautilusWindowSlot *slot)
 {
 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
 
-	if (slot->location) {
-		return g_file_get_uri (slot->location);
+	if (slot->details->location) {
+		return g_file_get_uri (slot->details->location);
 	}
 	return NULL;
 }
@@ -662,18 +2434,18 @@ nautilus_window_slot_update_title (NautilusWindowSlot *slot)
 	char *title;
 	gboolean do_sync = FALSE;
 
-	title = nautilus_compute_title_for_location (slot->location);
+	title = nautilus_compute_title_for_location (slot->details->location);
 	window = nautilus_window_slot_get_window (slot);
 
-	if (g_strcmp0 (title, slot->title) != 0) {
+	if (g_strcmp0 (title, slot->details->title) != 0) {
 		do_sync = TRUE;
 
-		g_free (slot->title);
-		slot->title = title;
+		g_free (slot->details->title);
+		slot->details->title = title;
 		title = NULL;
 	}
 
-	if (strlen (slot->title) > 0 &&
+	if (strlen (slot->details->title) > 0 &&
 	    slot->current_location_bookmark != NULL) {
 		do_sync = TRUE;
 	}
@@ -688,44 +2460,6 @@ nautilus_window_slot_update_title (NautilusWindowSlot *slot)
 }
 
 void
-nautilus_window_slot_set_content_view_widget (NautilusWindowSlot *slot,
-					      NautilusView *new_view)
-{
-	NautilusWindow *window;
-	GtkWidget *widget;
-
-	window = nautilus_window_slot_get_window (slot);
-
-	if (slot->content_view != NULL) {
-		/* disconnect old view */
-		g_signal_handlers_disconnect_by_func (slot->content_view, G_CALLBACK (view_end_loading_cb), slot);
-		g_signal_handlers_disconnect_by_func (slot->content_view, G_CALLBACK (view_begin_loading_cb), slot);
-
-		nautilus_window_disconnect_content_view (window, slot->content_view);
-
-		widget = GTK_WIDGET (slot->content_view);
-		gtk_widget_destroy (widget);
-		g_object_unref (slot->content_view);
-		slot->content_view = NULL;
-	}
-
-	if (new_view != NULL) {
-		widget = GTK_WIDGET (new_view);
-		gtk_container_add (GTK_CONTAINER (slot->details->view_overlay), widget);
-		gtk_widget_show (widget);
-
-		slot->content_view = new_view;
-		g_object_ref (slot->content_view);
-
-		g_signal_connect (new_view, "begin_loading", G_CALLBACK (view_begin_loading_cb), slot);
-		g_signal_connect (new_view, "end_loading", G_CALLBACK (view_end_loading_cb), slot);
-
-		/* connect new view */
-		nautilus_window_connect_content_view (window, new_view);
-	}
-}
-
-void
 nautilus_window_slot_set_allow_stop (NautilusWindowSlot *slot,
 				     gboolean allow)
 {
@@ -842,38 +2576,6 @@ nautilus_window_slot_set_status (NautilusWindowSlot *slot,
 	}
 }
 
-static void
-remove_all_extra_location_widgets (GtkWidget *widget,
-				   gpointer data)
-{
-	NautilusWindowSlot *slot = data;
-	NautilusDirectory *directory;
-
-	directory = nautilus_directory_get (slot->location);
-	if (widget != GTK_WIDGET (slot->query_editor)) {
-		gtk_container_remove (GTK_CONTAINER (slot->extra_location_widgets), widget);
-	}
-
-	nautilus_directory_unref (directory);
-}
-
-void
-nautilus_window_slot_remove_extra_location_widgets (NautilusWindowSlot *slot)
-{
-	gtk_container_foreach (GTK_CONTAINER (slot->extra_location_widgets),
-			       remove_all_extra_location_widgets,
-			       slot);
-}
-
-void
-nautilus_window_slot_add_extra_location_widget (NautilusWindowSlot *slot,
-						GtkWidget *widget)
-{
-	gtk_box_pack_start (GTK_BOX (slot->extra_location_widgets),
-			    widget, TRUE, TRUE, 0);
-	gtk_widget_show (slot->extra_location_widgets);
-}
-
 /* returns either the pending or the actual current uri */
 char *
 nautilus_window_slot_get_current_uri (NautilusWindowSlot *slot)
@@ -882,8 +2584,8 @@ nautilus_window_slot_get_current_uri (NautilusWindowSlot *slot)
 		return g_file_get_uri (slot->pending_location);
 	}
 
-	if (slot->location != NULL) {
-		return g_file_get_uri (slot->location);
+	if (slot->details->location != NULL) {
+		return g_file_get_uri (slot->details->location);
 	}
 
 	g_assert_not_reached ();
@@ -921,11 +2623,11 @@ nautilus_window_slot_go_up (NautilusWindowSlot *slot,
 {
 	GFile *parent;
 
-	if (slot->location == NULL) {
+	if (slot->details->location == NULL) {
 		return;
 	}
 
-	parent = g_file_get_parent (slot->location);
+	parent = g_file_get_parent (slot->details->location);
 	if (parent == NULL) {
 		return;
 	}
@@ -934,22 +2636,14 @@ nautilus_window_slot_go_up (NautilusWindowSlot *slot,
 	g_object_unref (parent);
 }
 
-void
-nautilus_window_slot_clear_forward_list (NautilusWindowSlot *slot)
-{
-	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
-
-	g_list_free_full (slot->forward_list, g_object_unref);
-	slot->forward_list = NULL;
-}
-
-void
-nautilus_window_slot_clear_back_list (NautilusWindowSlot *slot)
+gboolean
+nautilus_window_slot_content_view_matches_iid (NautilusWindowSlot *slot,
+					       const char *iid)
 {
-	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
-
-	g_list_free_full (slot->back_list, g_object_unref);
-	slot->back_list = NULL;
+	if (slot->content_view == NULL) {
+		return FALSE;
+	}
+	return g_strcmp0 (nautilus_view_get_view_id (slot->content_view), iid) == 0;
 }
 
 NautilusWindowSlot *
diff --git a/src/nautilus-window-slot.h b/src/nautilus-window-slot.h
index cd9c4ea..7a7c14c 100644
--- a/src/nautilus-window-slot.h
+++ b/src/nautilus-window-slot.h
@@ -61,12 +61,6 @@ struct NautilusWindowSlot {
 
 	NautilusWindowSlotDetails *details;
 
-	/* slot contains
- 	 *  1) an event box containing extra_location_widgets
- 	 *  2) the view box for the content view
- 	 */
-	GtkWidget *extra_location_widgets;
-
 	NautilusView *content_view;
 	NautilusView *new_content_view;
 
@@ -74,10 +68,6 @@ struct NautilusWindowSlot {
 	NautilusBookmark *current_location_bookmark;
 	NautilusBookmark *last_location_bookmark;
 
-	/* Current location. */
-	GFile *location;
-	char *title;
-
 	NautilusFile *viewed_file;
 	gboolean viewed_file_seen;
 	gboolean viewed_file_in_trash;
@@ -103,10 +93,6 @@ struct NautilusWindowSlot {
 	gpointer open_callback_user_data;
 	gboolean load_with_search;
 
-	gboolean needs_reload;
-
-	GCancellable *find_mount_cancellable;
-
 	gboolean visible;
 
 	/* Back/Forward chain, and history list. 
@@ -132,8 +118,9 @@ gboolean nautilus_window_slot_handle_event       	   (NautilusWindowSlot *slot,
 GFile * nautilus_window_slot_get_location		   (NautilusWindowSlot *slot);
 char *  nautilus_window_slot_get_location_uri		   (NautilusWindowSlot *slot);
 
+const gchar *nautilus_window_slot_get_title                (NautilusWindowSlot *slot);
+
 void    nautilus_window_slot_queue_reload		   (NautilusWindowSlot *slot);
-void    nautilus_window_slot_force_reload		   (NautilusWindowSlot *slot);
 
 /* convenience wrapper without selection and callback/user_data */
 #define nautilus_window_slot_open_location(slot, location, flags)\
@@ -150,7 +137,6 @@ void			nautilus_window_slot_stop_loading	      (NautilusWindowSlot	*slot);
 
 void			nautilus_window_slot_set_content_view	      (NautilusWindowSlot	*slot,
 								       const char		*id);
-const char	       *nautilus_window_slot_get_content_view_id      (NautilusWindowSlot	*slot);
 gboolean		nautilus_window_slot_content_view_matches_iid (NautilusWindowSlot	*slot,
 								       const char		*iid);
 
@@ -159,24 +145,13 @@ void    nautilus_window_slot_go_home			   (NautilusWindowSlot *slot,
 void    nautilus_window_slot_go_up                         (NautilusWindowSlot *slot,
 							    NautilusWindowOpenFlags flags);
 
-void    nautilus_window_slot_set_content_view_widget	   (NautilusWindowSlot *slot,
-							    NautilusView       *content_view);
-void    nautilus_window_slot_set_viewed_file		   (NautilusWindowSlot *slot,
-							    NautilusFile      *file);
 void    nautilus_window_slot_set_allow_stop		   (NautilusWindowSlot *slot,
 							    gboolean	    allow_stop);
 void    nautilus_window_slot_set_status			   (NautilusWindowSlot *slot,
 							    const char         *primary_status,
 							    const char         *detail_status);
 
-void    nautilus_window_slot_add_extra_location_widget     (NautilusWindowSlot *slot,
-							    GtkWidget       *widget);
-void    nautilus_window_slot_remove_extra_location_widgets (NautilusWindowSlot *slot);
-
 NautilusView * nautilus_window_slot_get_current_view     (NautilusWindowSlot *slot);
 char           * nautilus_window_slot_get_current_uri      (NautilusWindowSlot *slot);
 
-void nautilus_window_slot_clear_forward_list (NautilusWindowSlot *slot);
-void nautilus_window_slot_clear_back_list    (NautilusWindowSlot *slot);
-
 #endif /* NAUTILUS_WINDOW_SLOT_H */
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index 5f43c72..2557e1b 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -42,7 +42,6 @@
 #include "nautilus-pathbar.h"
 #include "nautilus-toolbar.h"
 #include "nautilus-view-factory.h"
-#include "nautilus-window-manage-views.h"
 #include "nautilus-window-slot.h"
 #include "nautilus-list-view.h"
 #include "nautilus-canvas-view.h"
@@ -312,7 +311,6 @@ close_slot (NautilusWindow     *window,
 
 	DEBUG ("Closing slot %p", slot);
 
-	nautilus_window_manage_views_close_slot (slot);
 	window->details->slots = g_list_remove (window->details->slots, slot);
 
 	g_signal_emit (window, signals[SLOT_REMOVED], 0, slot);
@@ -379,10 +377,12 @@ nautilus_window_new_tab (NautilusWindow *window)
 		}
 
 		scheme = g_file_get_uri_scheme (location);
-		if (!strcmp (scheme, "x-nautilus-search")) {
-			g_object_unref (location);
+		if (strcmp (scheme, "x-nautilus-search") == 0) {
 			location = g_file_new_for_path (g_get_home_dir ());
+		} else {
+			g_object_ref (location);
 		}
+
 		g_free (scheme);
 
 		new_slot = nautilus_window_open_slot (window, flags);
@@ -675,13 +675,15 @@ nautilus_window_sync_bookmarks (NautilusWindow *window)
 	NautilusWindowSlot *slot;
 	NautilusBookmarkList *bookmarks;
 	GtkAction *action;
+	GFile *location;
 
 	slot = window->details->active_slot;
+	location = nautilus_window_slot_get_location (slot);
 
-	if (slot->location != NULL) {
+	if (location != NULL) {
 		bookmarks = nautilus_application_get_bookmarks
 			(NAUTILUS_APPLICATION (gtk_window_get_application (GTK_WINDOW (window))));
-		can_bookmark = nautilus_bookmark_list_can_bookmark_location (bookmarks, slot->location);
+		can_bookmark = nautilus_bookmark_list_can_bookmark_location (bookmarks, location);
 	}
 
 	action = gtk_action_group_get_action (nautilus_window_get_main_action_group (window),
@@ -707,11 +709,13 @@ nautilus_window_sync_search_widgets (NautilusWindow *window)
 	NautilusDirectory *directory;
 	NautilusSearchDirectory *search_directory;
 	NautilusWindowSlot *slot;
+	GFile *location;
 
 	search_directory = NULL;
 	slot = window->details->active_slot;
+	location = nautilus_window_slot_get_location (slot);
 
-	directory = nautilus_directory_get (slot->location);
+	directory = nautilus_directory_get (location);
 	if (NAUTILUS_IS_SEARCH_DIRECTORY (directory)) {
 		search_directory = NAUTILUS_SEARCH_DIRECTORY (directory);
 	}
@@ -731,21 +735,23 @@ void
 nautilus_window_sync_location_widgets (NautilusWindow *window)
 {
 	NautilusWindowSlot *slot, *active_slot;
+	GFile *location;
 	GtkActionGroup *action_group;
 	GtkAction *action;
 
 	slot = window->details->active_slot;
+	location = nautilus_window_slot_get_location (slot);
 
 	/* Change the location bar and path bar to match the current location. */
-	if (slot->location != NULL) {
+	if (location != NULL) {
 		GtkWidget *location_entry;
 		GtkWidget *path_bar;
 
 		location_entry = nautilus_toolbar_get_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar));
-		nautilus_location_entry_set_location (NAUTILUS_LOCATION_ENTRY (location_entry), slot->location);
+		nautilus_location_entry_set_location (NAUTILUS_LOCATION_ENTRY (location_entry), location);
 
 		path_bar = nautilus_toolbar_get_path_bar (NAUTILUS_TOOLBAR (window->details->toolbar));
-		nautilus_path_bar_set_path (NAUTILUS_PATH_BAR (path_bar), slot->location);
+		nautilus_path_bar_set_path (NAUTILUS_PATH_BAR (path_bar), location);
 	}
 
 	nautilus_window_sync_up_button (window);
@@ -1417,6 +1423,38 @@ nautilus_window_close (NautilusWindow *window)
 	NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->close (window);
 }
 
+/* reports location change to window's "loading-uri" clients, i.e.
+ * sidebar panels [used when switching tabs]. It will emit the pending
+ * location, or the existing location if none is pending.
+ */
+static void
+nautilus_window_report_location_change (NautilusWindow *window)
+{
+	NautilusWindowSlot *slot;
+	GFile *location;
+
+	slot = nautilus_window_get_active_slot (window);
+	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
+
+	location = NULL;
+
+	if (slot->pending_location != NULL) {
+		location = slot->pending_location;
+	}
+
+	if (location == NULL) {
+		location = nautilus_window_slot_get_location (slot);
+	}
+
+	if (location != NULL) {
+		char *uri;
+
+		uri = g_file_get_uri (location);
+		g_signal_emit_by_name (window, "loading-uri", uri);
+		g_free (uri);
+	}
+}
+
 void
 nautilus_window_set_active_slot (NautilusWindow *window, NautilusWindowSlot *new_slot)
 {
@@ -1637,13 +1675,14 @@ nautilus_window_sync_up_button (NautilusWindow *window)
 	GtkActionGroup *action_group;
 	NautilusWindowSlot *slot;
 	gboolean allowed;
-	GFile *parent;
+	GFile *parent, *location;
 
 	slot = nautilus_window_get_active_slot (window);
+	location = nautilus_window_slot_get_location (slot);
 
 	allowed = FALSE;
-	if (slot->location != NULL) {
-		parent = g_file_get_parent (slot->location);
+	if (location != NULL) {
+		parent = g_file_get_parent (location);
 		allowed = parent != NULL;
 
 		g_clear_object (&parent);
@@ -1667,7 +1706,7 @@ nautilus_window_sync_title (NautilusWindow *window,
 	}
 
 	if (slot == nautilus_window_get_active_slot (window)) {
-		gtk_window_set_title (GTK_WINDOW (window), slot->title);
+		gtk_window_set_title (GTK_WINDOW (window), nautilus_window_slot_get_title (slot));
 	}
 
 	nautilus_notebook_sync_tab_label (NAUTILUS_NOTEBOOK (window->details->notebook), slot);
@@ -1838,34 +1877,6 @@ nautilus_window_get_main_action_group (NautilusWindow *window)
 	return window->details->main_action_group;
 }
 
-void
-nautilus_window_slot_set_viewed_file (NautilusWindowSlot *slot,
-				      NautilusFile *file)
-{
-	NautilusFileAttributes attributes;
-
-	if (slot->viewed_file == file) {
-		return;
-	}
-
-	nautilus_file_ref (file);
-
-	if (slot->viewed_file != NULL) {
-		nautilus_file_monitor_remove (slot->viewed_file,
-					      slot);
-	}
-
-	if (file != NULL) {
-		attributes =
-			NAUTILUS_FILE_ATTRIBUTE_INFO |
-			NAUTILUS_FILE_ATTRIBUTE_LINK_INFO;
-		nautilus_file_monitor_add (file, slot, attributes);
-	}
-
-	nautilus_file_unref (slot->viewed_file);
-	slot->viewed_file = file;
-}
-
 NautilusWindowSlot *
 nautilus_window_get_slot_for_view (NautilusWindow *window,
 				   NautilusView *view)
diff --git a/src/nautilus-window.h b/src/nautilus-window.h
index b914896..748132c 100644
--- a/src/nautilus-window.h
+++ b/src/nautilus-window.h
@@ -106,11 +106,6 @@ void             nautilus_window_new_tab              (NautilusWindow    *window
 GtkUIManager *   nautilus_window_get_ui_manager       (NautilusWindow    *window);
 GtkActionGroup * nautilus_window_get_main_action_group (NautilusWindow   *window);
 
-void                 nautilus_window_report_load_complete     (NautilusWindow *window,
-                                                               NautilusView *view);
-
-void                 nautilus_window_report_load_underway  (NautilusWindow *window,
-                                                            NautilusView *view);
 void                 nautilus_window_view_visible          (NautilusWindow *window,
                                                             NautilusView *view);
 NautilusWindowSlot * nautilus_window_get_active_slot       (NautilusWindow *window);



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