nautilus-3.6.3/src/nautilus-window-manage-views.c

No issues found

Incomplete coverage

Tool Failure ID Location Function Message Data
clang-analyzer no-output-found nautilus-window-manage-views.c Message(text='Unable to locate XML output from invoke-clang-analyzer') None
Failure running clang-analyzer ('no-output-found')
Message
Unable to locate XML output from invoke-clang-analyzer
   1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
   2 
   3 /*
   4  *  Nautilus
   5  *
   6  *  Copyright (C) 1999, 2000 Red Hat, Inc.
   7  *  Copyright (C) 1999, 2000, 2001 Eazel, Inc.
   8  *
   9  *  Nautilus is free software; you can redistribute it and/or
  10  *  modify it under the terms of the GNU General Public
  11  *  License as published by the Free Software Foundation; either
  12  *  version 2 of the License, or (at your option) any later version.
  13  *
  14  *  Nautilus is distributed in the hope that it will be useful,
  15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17  *  General Public License for more details.
  18  *
  19  *  You should have received a copy of the GNU General Public
  20  *  License along with this program; if not, write to the Free
  21  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22  *
  23  *  Authors: Elliot Lee <sopwith@redhat.com>
  24  *           John Sullivan <sullivan@eazel.com>
  25  *           Darin Adler <darin@bentspoon.com>
  26  */
  27 
  28 #include <config.h>
  29 #include "nautilus-window-manage-views.h"
  30 
  31 #include "nautilus-actions.h"
  32 #include "nautilus-application.h"
  33 #include "nautilus-pathbar.h"
  34 #include "nautilus-window-private.h"
  35 #include "nautilus-window-slot.h"
  36 #include "nautilus-special-location-bar.h"
  37 #include "nautilus-trash-bar.h"
  38 #include "nautilus-toolbar.h"
  39 #include "nautilus-view-factory.h"
  40 #include "nautilus-x-content-bar.h"
  41 #include <eel/eel-accessibility.h>
  42 #include <eel/eel-debug.h>
  43 #include <eel/eel-glib-extensions.h>
  44 #include <eel/eel-stock-dialogs.h>
  45 #include <gtk/gtk.h>
  46 #include <gdk/gdkx.h>
  47 #include <glib/gi18n.h>
  48 #include <libnautilus-extension/nautilus-location-widget-provider.h>
  49 #include <libnautilus-private/nautilus-file-attributes.h>
  50 #include <libnautilus-private/nautilus-file-utilities.h>
  51 #include <libnautilus-private/nautilus-file.h>
  52 #include <libnautilus-private/nautilus-global-preferences.h>
  53 #include <libnautilus-private/nautilus-metadata.h>
  54 #include <libnautilus-private/nautilus-module.h>
  55 #include <libnautilus-private/nautilus-monitor.h>
  56 #include <libnautilus-private/nautilus-profile.h>
  57 #include <libnautilus-private/nautilus-search-directory.h>
  58 
  59 #define DEBUG_FLAG NAUTILUS_DEBUG_WINDOW
  60 #include <libnautilus-private/nautilus-debug.h>
  61 
  62 /* FIXME bugzilla.gnome.org 41243: 
  63  * We should use inheritance instead of these special cases
  64  * for the desktop window.
  65  */
  66 #include "nautilus-desktop-window.h"
  67 
  68 /* This number controls a maximum character count for a URL that is
  69  * displayed as part of a dialog. It's fairly arbitrary -- big enough
  70  * to allow most "normal" URIs to display in full, but small enough to
  71  * prevent the dialog from getting insanely wide.
  72  */
  73 #define MAX_URI_IN_DIALOG_LENGTH 60
  74 
  75 static void begin_location_change                     (NautilusWindowSlot         *slot,
  76 						       GFile                      *location,
  77 						       GFile                      *previous_location,
  78 						       GList                      *new_selection,
  79 						       NautilusLocationChangeType  type,
  80 						       guint                       distance,
  81 						       const char                 *scroll_pos,
  82 						       NautilusWindowGoToCallback  callback,
  83 						       gpointer                    user_data);
  84 static void free_location_change                      (NautilusWindowSlot         *slot);
  85 static void end_location_change                       (NautilusWindowSlot         *slot);
  86 static void cancel_location_change                    (NautilusWindowSlot         *slot);
  87 static void got_file_info_for_view_selection_callback (NautilusFile               *file,
  88 						       gpointer                    callback_data);
  89 static gboolean create_content_view                   (NautilusWindowSlot         *slot,
  90 						       const char                 *view_id,
  91 						       GError                    **error);
  92 static void display_view_selection_failure            (NautilusWindow             *window,
  93 						       NautilusFile               *file,
  94 						       GFile                      *location,
  95 						       GError                     *error);
  96 static void load_new_location                         (NautilusWindowSlot         *slot,
  97 						       GFile                      *location,
  98 						       GList                      *selection,
  99 						       gboolean                    tell_current_content_view,
 100 						       gboolean                    tell_new_content_view);
 101 static void location_has_really_changed               (NautilusWindowSlot         *slot);
 102 static void update_for_new_location                   (NautilusWindowSlot         *slot);
 103 
 104 static void
 105 set_displayed_file (NautilusWindowSlot *slot, NautilusFile *file)
 106 {
 107         gboolean recreate;
 108 	GFile *new_location = NULL;
 109 
 110 	if (file != NULL) {
 111 		new_location = nautilus_file_get_location (file);
 112 	}
 113 
 114         if (slot->current_location_bookmark == NULL || file == NULL) {
 115                 recreate = TRUE;
 116         } else {
 117 		GFile *bookmark_location;
 118                 bookmark_location = nautilus_bookmark_get_location (slot->current_location_bookmark);
 119                 recreate = !g_file_equal (bookmark_location, new_location);
 120                 g_object_unref (bookmark_location);
 121         }
 122 
 123         if (recreate) {
 124 		char *display_name = NULL;
 125 
 126                 /* We've changed locations, must recreate bookmark for current location. */
 127 		g_clear_object (&slot->last_location_bookmark);
 128 
 129 		if (file != NULL) {
 130 			display_name = nautilus_file_get_display_name (file);
 131 		}
 132 		slot->last_location_bookmark = slot->current_location_bookmark;
 133 		if (new_location == NULL) {
 134 			slot->current_location_bookmark = NULL;
 135 		} else {
 136 			slot->current_location_bookmark = nautilus_bookmark_new (new_location, display_name);
 137 		}
 138 		g_free (display_name);
 139         }
 140 
 141 	g_clear_object (&new_location);
 142 }
 143 
 144 static void
 145 check_bookmark_location_matches (NautilusBookmark *bookmark, GFile *location)
 146 {
 147         GFile *bookmark_location;
 148         char *bookmark_uri, *uri;
 149 
 150 	bookmark_location = nautilus_bookmark_get_location (bookmark);
 151 	if (!g_file_equal (location, bookmark_location)) {
 152 		bookmark_uri = g_file_get_uri (bookmark_location);
 153 		uri = g_file_get_uri (location);
 154 		g_warning ("bookmark uri is %s, but expected %s", bookmark_uri, uri);
 155 		g_free (uri);
 156 		g_free (bookmark_uri);
 157 	}
 158 	g_object_unref (bookmark_location);
 159 }
 160 
 161 /* Debugging function used to verify that the last_location_bookmark
 162  * is in the state we expect when we're about to use it to update the
 163  * Back or Forward list.
 164  */
 165 static void
 166 check_last_bookmark_location_matches_slot (NautilusWindowSlot *slot)
 167 {
 168 	check_bookmark_location_matches (slot->last_location_bookmark,
 169 					 slot->location);
 170 }
 171 
 172 static void
 173 handle_go_back (NautilusWindowSlot *slot,
 174 		GFile *location)
 175 {
 176 	guint i;
 177 	GList *link;
 178 	NautilusBookmark *bookmark;
 179 
 180 	/* Going back. Move items from the back list to the forward list. */
 181 	g_assert (g_list_length (slot->back_list) > slot->location_change_distance);
 182 	check_bookmark_location_matches (NAUTILUS_BOOKMARK (g_list_nth_data (slot->back_list,
 183 									     slot->location_change_distance)),
 184 					 location);
 185 	g_assert (slot->location != NULL);
 186 	
 187 	/* Move current location to Forward list */
 188 
 189 	check_last_bookmark_location_matches_slot (slot);
 190 
 191 	/* Use the first bookmark in the history list rather than creating a new one. */
 192 	slot->forward_list = g_list_prepend (slot->forward_list,
 193 					     slot->last_location_bookmark);
 194 	g_object_ref (slot->forward_list->data);
 195 				
 196 	/* Move extra links from Back to Forward list */
 197 	for (i = 0; i < slot->location_change_distance; ++i) {
 198 		bookmark = NAUTILUS_BOOKMARK (slot->back_list->data);
 199 		slot->back_list =
 200 			g_list_remove (slot->back_list, bookmark);
 201 		slot->forward_list =
 202 			g_list_prepend (slot->forward_list, bookmark);
 203 	}
 204 	
 205 	/* One bookmark falls out of back/forward lists and becomes viewed location */
 206 	link = slot->back_list;
 207 	slot->back_list = g_list_remove_link (slot->back_list, link);
 208 	g_object_unref (link->data);
 209 	g_list_free_1 (link);
 210 }
 211 
 212 static void
 213 handle_go_forward (NautilusWindowSlot *slot,
 214 		   GFile *location)
 215 {
 216 	guint i;
 217 	GList *link;
 218 	NautilusBookmark *bookmark;
 219 
 220 	/* Going forward. Move items from the forward list to the back list. */
 221 	g_assert (g_list_length (slot->forward_list) > slot->location_change_distance);
 222 	check_bookmark_location_matches (NAUTILUS_BOOKMARK (g_list_nth_data (slot->forward_list,
 223 									     slot->location_change_distance)),
 224 					 location);
 225 	g_assert (slot->location != NULL);
 226 				
 227 	/* Move current location to Back list */
 228 	check_last_bookmark_location_matches_slot (slot);
 229 	
 230 	/* Use the first bookmark in the history list rather than creating a new one. */
 231 	slot->back_list = g_list_prepend (slot->back_list,
 232 						     slot->last_location_bookmark);
 233 	g_object_ref (slot->back_list->data);
 234 	
 235 	/* Move extra links from Forward to Back list */
 236 	for (i = 0; i < slot->location_change_distance; ++i) {
 237 		bookmark = NAUTILUS_BOOKMARK (slot->forward_list->data);
 238 		slot->forward_list =
 239 			g_list_remove (slot->back_list, bookmark);
 240 		slot->back_list =
 241 			g_list_prepend (slot->forward_list, bookmark);
 242 	}
 243 	
 244 	/* One bookmark falls out of back/forward lists and becomes viewed location */
 245 	link = slot->forward_list;
 246 	slot->forward_list = g_list_remove_link (slot->forward_list, link);
 247 	g_object_unref (link->data);
 248 	g_list_free_1 (link);
 249 }
 250 
 251 static void
 252 handle_go_elsewhere (NautilusWindowSlot *slot,
 253 		     GFile *location)
 254 {
 255 	/* Clobber the entire forward list, and move displayed location to back list */
 256 	nautilus_window_slot_clear_forward_list (slot);
 257 		
 258 	if (slot->location != NULL) {
 259 		/* If we're returning to the same uri somehow, don't put this uri on back list. 
 260 		 * This also avoids a problem where set_displayed_location
 261 		 * didn't update last_location_bookmark since the uri didn't change.
 262 		 */
 263 		if (!g_file_equal (slot->location, location)) {
 264 			/* Store bookmark for current location in back list, unless there is no current location */
 265 			check_last_bookmark_location_matches_slot (slot);
 266 			/* Use the first bookmark in the history list rather than creating a new one. */
 267 			slot->back_list = g_list_prepend (slot->back_list,
 268 							  slot->last_location_bookmark);
 269 			g_object_ref (slot->back_list->data);
 270 		}
 271 	}
 272 }
 273 
 274 static void
 275 viewed_file_changed_callback (NautilusFile *file,
 276                               NautilusWindowSlot *slot)
 277 {
 278         GFile *new_location;
 279 	gboolean is_in_trash, was_in_trash;
 280 	NautilusWindow *window;
 281 
 282         g_assert (NAUTILUS_IS_FILE (file));
 283 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
 284 	g_assert (file == slot->viewed_file);
 285 
 286 	window = nautilus_window_slot_get_window (slot);
 287 
 288         if (!nautilus_file_is_not_yet_confirmed (file)) {
 289                 slot->viewed_file_seen = TRUE;
 290         }
 291 
 292 	was_in_trash = slot->viewed_file_in_trash;
 293 
 294 	slot->viewed_file_in_trash = is_in_trash = nautilus_file_is_in_trash (file);
 295 
 296 	if (nautilus_file_is_gone (file) || (is_in_trash && !was_in_trash)) {
 297 
 298                 if (slot->viewed_file_seen) {
 299 			/* auto-show existing parent. */
 300 			GFile *go_to_file;
 301 			GFile *parent;
 302 			GFile *location;
 303 			GMount *mount;
 304 
 305                         /* Detecting a file is gone may happen in the
 306                          * middle of a pending location change, we
 307                          * need to cancel it before closing the window
 308                          * or things break.
 309                          */
 310                         /* FIXME: It makes no sense that this call is
 311                          * needed. When the window is destroyed, it
 312                          * calls nautilus_window_manage_views_destroy,
 313                          * which calls free_location_change, which
 314                          * should be sufficient. Also, if this was
 315                          * really needed, wouldn't it be needed for
 316                          * all other nautilus_window_close callers?
 317                          */
 318 			end_location_change (slot);
 319 
 320 			parent = NULL;
 321 			location = nautilus_file_get_location (file);
 322 
 323 			if (g_file_is_native (location)) {
 324 				mount = nautilus_get_mounted_mount_for_root (location);
 325 
 326 				if (mount == NULL) {
 327 					parent = g_file_get_parent (location);
 328 				}
 329 
 330 				g_clear_object (&mount);
 331 			}
 332 
 333 			if (parent != NULL) {
 334 				/* auto-show existing parent */
 335 				go_to_file = nautilus_find_existing_uri_in_hierarchy (parent);
 336 			} else {
 337 				go_to_file = g_file_new_for_path (g_get_home_dir ());
 338 			}
 339 
 340 			nautilus_window_slot_open_location (slot, go_to_file, 0);
 341 
 342 			g_clear_object (&parent);
 343 			g_object_unref (go_to_file);
 344 			g_object_unref (location);
 345                 }
 346 	} else {
 347                 new_location = nautilus_file_get_location (file);
 348 
 349                 /* If the file was renamed, update location and/or
 350                  * title. */
 351                 if (!g_file_equal (new_location,
 352 				   slot->location)) {
 353                         g_object_unref (slot->location);
 354                         slot->location = new_location;
 355 			if (slot == nautilus_window_get_active_slot (window)) {
 356 				nautilus_window_sync_location_widgets (window);
 357 			}
 358                 } else {
 359 			/* TODO?
 360  			 *   why do we update title at all in this case? */
 361                         g_object_unref (new_location);
 362                 }
 363 
 364                 nautilus_window_slot_update_title (slot);
 365         }
 366 }
 367 
 368 static void
 369 update_history (NautilusWindowSlot *slot,
 370                 NautilusLocationChangeType type,
 371                 GFile *new_location)
 372 {
 373         switch (type) {
 374         case NAUTILUS_LOCATION_CHANGE_STANDARD:
 375 		handle_go_elsewhere (slot, new_location);
 376                 return;
 377         case NAUTILUS_LOCATION_CHANGE_RELOAD:
 378                 /* for reload there is no work to do */
 379                 return;
 380         case NAUTILUS_LOCATION_CHANGE_BACK:
 381                 handle_go_back (slot, new_location);
 382                 return;
 383         case NAUTILUS_LOCATION_CHANGE_FORWARD:
 384                 handle_go_forward (slot, new_location);
 385                 return;
 386         }
 387 	g_return_if_fail (FALSE);
 388 }
 389 
 390 static void
 391 cancel_viewed_file_changed_callback (NautilusWindowSlot *slot)
 392 {
 393         NautilusFile *file;
 394 
 395         file = slot->viewed_file;
 396         if (file != NULL) {
 397                 g_signal_handlers_disconnect_by_func (G_OBJECT (file),
 398                                                       G_CALLBACK (viewed_file_changed_callback),
 399 						      slot);
 400                 nautilus_file_monitor_remove (file, &slot->viewed_file);
 401         }
 402 }
 403 
 404 static void
 405 new_window_show_callback (GtkWidget *widget,
 406 			  gpointer user_data){
 407 	NautilusWindow *window;
 408 
 409 	window = NAUTILUS_WINDOW (user_data);
 410 	nautilus_window_close (window);
 411 
 412 	g_signal_handlers_disconnect_by_func (widget,
 413 					      G_CALLBACK (new_window_show_callback),
 414 					      user_data);
 415 }
 416 
 417 void
 418 nautilus_window_slot_open_location_full (NautilusWindowSlot *slot,
 419 					 GFile *location,
 420 					 NautilusWindowOpenFlags flags,
 421 					 GList *new_selection,
 422 					 NautilusWindowGoToCallback callback,
 423 					 gpointer user_data)
 424 {
 425 	NautilusWindow *window;
 426         NautilusWindow *target_window;
 427         NautilusWindowSlot *target_slot;
 428 	NautilusWindowOpenFlags slot_flags;
 429 	GFile *old_location;
 430 	char *old_uri, *new_uri;
 431 	int new_slot_position;
 432 	gboolean use_same;
 433 	gboolean is_desktop;
 434 
 435 	window = nautilus_window_slot_get_window (slot);
 436 
 437         target_window = NULL;
 438 	target_slot = NULL;
 439 	use_same = TRUE;
 440 
 441 	/* this happens at startup */
 442 	old_uri = nautilus_window_slot_get_location_uri (slot);
 443 	if (old_uri == NULL) {
 444 		old_uri = g_strdup ("(none)");
 445 		use_same = TRUE;
 446 	}
 447 	new_uri = g_file_get_uri (location);
 448 
 449 	DEBUG ("Opening location, old: %s, new: %s", old_uri, new_uri);
 450 	nautilus_profile_start ("Opening location, old: %s, new: %s", old_uri, new_uri);
 451 
 452 	g_free (old_uri);
 453 	g_free (new_uri);
 454 
 455 	is_desktop = NAUTILUS_IS_DESKTOP_WINDOW (window);
 456 
 457 	if (is_desktop) {
 458 		use_same = !nautilus_desktop_window_loaded (NAUTILUS_DESKTOP_WINDOW (window));
 459 
 460 		/* if we're requested to open a new tab on the desktop, open a window
 461 		 * instead.
 462 		 */
 463 		if (flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) {
 464 			flags ^= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
 465 			flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
 466 		}
 467 	}
 468 
 469 	g_assert (!((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 &&
 470 		    (flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0));
 471 
 472 	/* and if the flags specify so, this is overridden */
 473 	if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0) {
 474 		use_same = FALSE;
 475 	}
 476 
 477 	old_location = nautilus_window_slot_get_location (slot);
 478 
 479 	/* now get/create the window */
 480 	if (use_same) {
 481 		target_window = window;
 482 	} else {
 483 		target_window = nautilus_application_create_window
 484 			(NAUTILUS_APPLICATION (g_application_get_default ()),
 485 			 gtk_window_get_screen (GTK_WINDOW (window)));
 486 	}
 487 
 488         g_assert (target_window != NULL);
 489 
 490 	/* if the flags say we want a new tab, open a slot in the current window */
 491 	if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0) {
 492 		g_assert (target_window == window);
 493 
 494 		slot_flags = 0;
 495 
 496 		new_slot_position = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION);
 497 		if (new_slot_position == NAUTILUS_NEW_TAB_POSITION_END) {
 498 			slot_flags = NAUTILUS_WINDOW_OPEN_SLOT_APPEND;
 499 		}
 500 
 501 		target_slot = nautilus_window_open_slot (window,
 502 							 slot_flags);
 503 	}
 504 
 505 	/* close the current window if the flags say so */
 506 	if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_CLOSE_BEHIND) != 0) {
 507 		if (!is_desktop) {
 508 			if (gtk_widget_get_visible (GTK_WIDGET (target_window))) {
 509 				nautilus_window_close (window);
 510 			} else {
 511 				g_signal_connect_object (target_window,
 512 							 "show",
 513 							 G_CALLBACK (new_window_show_callback),
 514 							 window,
 515 							 G_CONNECT_AFTER);
 516 			}
 517 		}
 518 	}
 519 
 520 	if (target_slot == NULL) {
 521 		if (target_window == window) {
 522 			target_slot = slot;
 523 		} else {
 524 			target_slot = nautilus_window_get_active_slot (target_window);
 525 		}
 526 	}
 527 
 528         if (target_window == window && target_slot == slot &&
 529 	    old_location && g_file_equal (old_location, location) &&
 530 	    !is_desktop) {
 531 
 532 		if (callback != NULL) {
 533 			callback (window, location, NULL, user_data);
 534 		}
 535 
 536 		goto done;
 537         }
 538 
 539 	slot->pending_use_default_location = ((flags & NAUTILUS_WINDOW_OPEN_FLAG_USE_DEFAULT_LOCATION) != 0);
 540         begin_location_change (target_slot, location, old_location, new_selection,
 541 			       NAUTILUS_LOCATION_CHANGE_STANDARD, 0, NULL, callback, user_data);
 542 
 543  done:
 544 	g_clear_object (&old_location);
 545 
 546 	nautilus_profile_end (NULL);
 547 }
 548 
 549 const char *
 550 nautilus_window_slot_get_content_view_id (NautilusWindowSlot *slot)
 551 {
 552 	if (slot->content_view == NULL) {
 553 		return NULL;
 554 	}
 555 	return nautilus_view_get_view_id (slot->content_view);
 556 }
 557 
 558 gboolean
 559 nautilus_window_slot_content_view_matches_iid (NautilusWindowSlot *slot, 
 560 					       const char *iid)
 561 {
 562 	if (slot->content_view == NULL) {
 563 		return FALSE;
 564 	}
 565 	return g_strcmp0 (nautilus_view_get_view_id (slot->content_view), iid) == 0;
 566 }
 567 
 568 static gboolean
 569 report_callback (NautilusWindowSlot *slot,
 570 		 GError *error)
 571 {
 572 	if (slot->open_callback != NULL) {
 573 		gboolean res;
 574 		res = slot->open_callback (nautilus_window_slot_get_window (slot),
 575 					   slot->pending_location,
 576 					   error, slot->open_callback_user_data);
 577 		slot->open_callback = NULL;
 578 		slot->open_callback_user_data = NULL;
 579 
 580 		return res;
 581 	}
 582 
 583 	return FALSE;
 584 }
 585 
 586 /*
 587  * begin_location_change
 588  * 
 589  * Change a window slot's location.
 590  * @window: The NautilusWindow whose location should be changed.
 591  * @location: A url specifying the location to load
 592  * @previous_location: The url that was previously shown in the window that initialized the change, if any
 593  * @new_selection: The initial selection to present after loading the location
 594  * @type: Which type of location change is this? Standard, back, forward, or reload?
 595  * @distance: If type is back or forward, the index into the back or forward chain. If
 596  * type is standard or reload, this is ignored, and must be 0.
 597  * @scroll_pos: The file to scroll to when the location is loaded.
 598  * @callback: function to be called when the location is changed.
 599  * @user_data: data for @callback.
 600  *
 601  * This is the core function for changing the location of a window. Every change to the
 602  * location begins here.
 603  */
 604 static void
 605 begin_location_change (NautilusWindowSlot *slot,
 606                        GFile *location,
 607                        GFile *previous_location,
 608 		       GList *new_selection,
 609                        NautilusLocationChangeType type,
 610                        guint distance,
 611                        const char *scroll_pos,
 612 		       NautilusWindowGoToCallback callback,
 613 		       gpointer user_data)
 614 {
 615         NautilusDirectory *directory;
 616         NautilusFile *file;
 617 	gboolean force_reload;
 618         char *current_pos;
 619 	GFile *from_folder, *parent;
 620 	GList *parent_selection = NULL;
 621 
 622 	g_assert (slot != NULL);
 623         g_assert (location != NULL);
 624         g_assert (type == NAUTILUS_LOCATION_CHANGE_BACK
 625                   || type == NAUTILUS_LOCATION_CHANGE_FORWARD
 626                   || distance == 0);
 627 
 628 	nautilus_profile_start (NULL);
 629 
 630 	/* If there is no new selection and the new location is
 631 	 * a (grand)parent of the old location then we automatically
 632 	 * select the folder the previous location was in */
 633 	if (new_selection == NULL && previous_location != NULL &&
 634 	    g_file_has_prefix (previous_location, location)) {
 635 		from_folder = g_object_ref (previous_location);
 636 		parent = g_file_get_parent (from_folder);
 637 		while (parent != NULL && !g_file_equal (parent, location)) {
 638 			g_object_unref (from_folder);
 639 			from_folder = parent;
 640 			parent = g_file_get_parent (from_folder);
 641 		}
 642 
 643 		if (parent != NULL) {
 644 			new_selection = parent_selection = 
 645 				g_list_prepend (NULL, nautilus_file_get (from_folder));
 646 			g_object_unref (parent);
 647 		}
 648 
 649 		g_object_unref (from_folder);
 650 	}
 651 
 652 	end_location_change (slot);
 653 
 654 	nautilus_window_slot_set_allow_stop (slot, TRUE);
 655 	nautilus_window_slot_set_status (slot, NULL, NULL);
 656 
 657 	g_assert (slot->pending_location == NULL);
 658 	g_assert (slot->pending_selection == NULL);
 659 	
 660 	slot->pending_location = g_object_ref (location);
 661         slot->location_change_type = type;
 662         slot->location_change_distance = distance;
 663 	slot->tried_mount = FALSE;
 664 	slot->pending_selection = eel_g_object_list_copy (new_selection);
 665 
 666 	slot->pending_scroll_to = g_strdup (scroll_pos);
 667 
 668 	slot->open_callback = callback;
 669 	slot->open_callback_user_data = user_data;
 670 
 671         directory = nautilus_directory_get (location);
 672 
 673 	/* The code to force a reload is here because if we do it
 674 	 * after determining an initial view (in the components), then
 675 	 * we end up fetching things twice.
 676 	 */
 677 	if (type == NAUTILUS_LOCATION_CHANGE_RELOAD) {
 678 		force_reload = TRUE;
 679 	} else if (!nautilus_monitor_active ()) {
 680 		force_reload = TRUE;
 681 	} else {
 682 		force_reload = !nautilus_directory_is_local (directory);
 683 	}
 684 
 685 	if (force_reload) {
 686 		nautilus_directory_force_reload (directory);
 687 		file = nautilus_directory_get_corresponding_file (directory);
 688 		nautilus_file_invalidate_all_attributes (file);
 689 		nautilus_file_unref (file);
 690 	}
 691 
 692         nautilus_directory_unref (directory);
 693 
 694 	if (parent_selection != NULL) {
 695 		g_list_free_full (parent_selection, g_object_unref);
 696 	}
 697 
 698         /* Set current_bookmark scroll pos */
 699         if (slot->current_location_bookmark != NULL &&
 700             slot->content_view != NULL) {
 701                 current_pos = nautilus_view_get_first_visible_file (slot->content_view);
 702                 nautilus_bookmark_set_scroll_pos (slot->current_location_bookmark, current_pos);
 703                 g_free (current_pos);
 704         }
 705 
 706 	/* Get the info needed for view selection */
 707 	
 708         slot->determine_view_file = nautilus_file_get (location);
 709 	g_assert (slot->determine_view_file != NULL);
 710 
 711 	/* if the currently viewed file is marked gone while loading the new location,
 712 	 * this ensures that the window isn't destroyed */
 713         cancel_viewed_file_changed_callback (slot);
 714 
 715 	nautilus_file_call_when_ready (slot->determine_view_file,
 716 				       NAUTILUS_FILE_ATTRIBUTE_INFO |
 717 				       NAUTILUS_FILE_ATTRIBUTE_MOUNT,
 718                                        got_file_info_for_view_selection_callback,
 719 				       slot);
 720 
 721 	nautilus_profile_end (NULL);
 722 }
 723 
 724 typedef struct {
 725 	GCancellable *cancellable;
 726 	NautilusWindowSlot *slot;
 727 } MountNotMountedData;
 728 
 729 static void 
 730 mount_not_mounted_callback (GObject *source_object,
 731 			    GAsyncResult *res,
 732 			    gpointer user_data)
 733 {
 734 	MountNotMountedData *data;
 735 	NautilusWindowSlot *slot;
 736 	GError *error;
 737 	GCancellable *cancellable;
 738 
 739 	data = user_data;
 740 	slot = data->slot;
 741 	cancellable = data->cancellable;
 742 	g_free (data);
 743 
 744 	if (g_cancellable_is_cancelled (cancellable)) {
 745 		/* Cancelled, don't call back */
 746 		g_object_unref (cancellable);
 747 		return;
 748 	}
 749 
 750 	slot->mount_cancellable = NULL;
 751 
 752 	slot->determine_view_file = nautilus_file_get (slot->pending_location);
 753 	
 754 	error = NULL;
 755 	if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object), res, &error)) {
 756 		slot->mount_error = error;
 757 		got_file_info_for_view_selection_callback (slot->determine_view_file, slot);
 758 		slot->mount_error = NULL;
 759 		g_error_free (error);
 760 	} else {
 761 		nautilus_file_invalidate_all_attributes (slot->determine_view_file);
 762 		nautilus_file_call_when_ready (slot->determine_view_file,
 763 					       NAUTILUS_FILE_ATTRIBUTE_INFO |
 764 					       NAUTILUS_FILE_ATTRIBUTE_MOUNT,
 765 					       got_file_info_for_view_selection_callback,
 766 					       slot);
 767 	}
 768 
 769 	g_object_unref (cancellable);
 770 }
 771 
 772 static void
 773 got_file_info_for_view_selection_callback (NautilusFile *file,
 774 					   gpointer callback_data)
 775 {
 776         GError *error = NULL;
 777 	char *view_id;
 778 	char *mimetype;
 779 	NautilusWindow *window;
 780 	NautilusWindowSlot *slot;
 781 	NautilusFile *viewed_file, *parent_file;
 782 	GFile *location, *default_location;
 783 	GMountOperation *mount_op;
 784 	MountNotMountedData *data;
 785 	GtkApplication *app;
 786 	GMount *mount;
 787 
 788 	slot = callback_data;
 789 	window = nautilus_window_slot_get_window (slot);
 790 
 791 	g_assert (slot->determine_view_file == file);
 792 	slot->determine_view_file = NULL;
 793 
 794 	nautilus_profile_start (NULL);
 795 
 796 	if (slot->mount_error) {
 797 		error = g_error_copy (slot->mount_error);
 798 	} else if (nautilus_file_get_file_info_error (file) != NULL) {
 799 		error = g_error_copy (nautilus_file_get_file_info_error (file));
 800 	}
 801 
 802 	if (error && error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_MOUNTED &&
 803 	    !slot->tried_mount) {
 804 		slot->tried_mount = TRUE;
 805 
 806 		mount_op = gtk_mount_operation_new (GTK_WINDOW (window));
 807 		g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
 808 		location = nautilus_file_get_location (file);
 809 		data = g_new0 (MountNotMountedData, 1);
 810 		data->cancellable = g_cancellable_new ();
 811 		data->slot = slot;
 812 		slot->mount_cancellable = data->cancellable;
 813 		g_file_mount_enclosing_volume (location, 0, mount_op, slot->mount_cancellable,
 814 					       mount_not_mounted_callback, data);
 815 		g_object_unref (location);
 816 		g_object_unref (mount_op);
 817 
 818 		goto done;
 819 	}
 820 
 821 	mount = NULL;
 822 	default_location = NULL;
 823 
 824 	if (slot->pending_use_default_location) {
 825 		mount = nautilus_file_get_mount (file);
 826 		slot->pending_use_default_location = FALSE;
 827 	}
 828 
 829 	if (mount != NULL) {
 830 		default_location = g_mount_get_default_location (mount);
 831 		g_object_unref (mount);
 832 	}
 833 
 834 	if (default_location != NULL &&
 835 	    !g_file_equal (slot->pending_location, default_location)) {
 836 		g_clear_object (&slot->pending_location);
 837 		slot->pending_location = default_location;
 838 		slot->determine_view_file = nautilus_file_get (default_location);
 839 
 840 		nautilus_file_invalidate_all_attributes (slot->determine_view_file);
 841 		nautilus_file_call_when_ready (slot->determine_view_file,
 842 					       NAUTILUS_FILE_ATTRIBUTE_INFO |
 843 					       NAUTILUS_FILE_ATTRIBUTE_MOUNT,
 844 					       got_file_info_for_view_selection_callback,
 845 					       slot);
 846 
 847 		goto done;
 848 	}
 849 
 850 	parent_file = nautilus_file_get_parent (file);
 851 	if ((parent_file != NULL) &&
 852 	    nautilus_file_get_file_type (file) == G_FILE_TYPE_REGULAR) {
 853 		if (slot->pending_selection != NULL) {
 854 			g_list_free_full (slot->pending_selection, (GDestroyNotify) nautilus_file_unref);
 855 		}
 856 
 857 		g_clear_object (&slot->pending_location);
 858 		g_free (slot->pending_scroll_to);
 859 	
 860 		slot->pending_location = nautilus_file_get_parent_location (file);
 861 		slot->pending_selection = g_list_prepend (NULL, nautilus_file_ref (file));
 862 		slot->determine_view_file = parent_file;
 863 		slot->pending_scroll_to = nautilus_file_get_uri (file);
 864 
 865 		nautilus_file_invalidate_all_attributes (slot->determine_view_file);
 866 		nautilus_file_call_when_ready (slot->determine_view_file,
 867 					       NAUTILUS_FILE_ATTRIBUTE_INFO |
 868 					       NAUTILUS_FILE_ATTRIBUTE_MOUNT,
 869 					       got_file_info_for_view_selection_callback,
 870 					       slot);		
 871 
 872 		goto done;
 873 	}
 874 
 875 	nautilus_file_unref (parent_file);
 876 	location = slot->pending_location;
 877 	
 878 	view_id = NULL;
 879 	
 880         if (error == NULL ||
 881 	    (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_SUPPORTED)) {
 882 		/* We got the information we need, now pick what view to use: */
 883 
 884 		mimetype = nautilus_file_get_mime_type (file);
 885 
 886 		/* Try to use the existing view */
 887 		view_id = g_strdup (nautilus_window_slot_get_content_view_id (slot));
 888 
 889 		/* Otherwise, use default */
 890 		if (view_id == NULL) {
 891 			view_id = nautilus_global_preferences_get_default_folder_viewer_preference_as_iid ();
 892 
 893 			if (view_id != NULL && 
 894 			    !nautilus_view_factory_view_supports_uri (view_id,
 895 								      location,
 896 								      nautilus_file_get_file_type (file),
 897 								      mimetype)) {
 898 				g_free (view_id);
 899 				view_id = NULL;
 900 			}
 901 		}
 902 		
 903 		g_free (mimetype);
 904 	}
 905 
 906 	if (view_id != NULL) {
 907 		GError *err = NULL;
 908 
 909 		create_content_view (slot, view_id, &err);
 910 		g_free (view_id);
 911 
 912 		report_callback (slot, err);
 913 		g_clear_error (&err);
 914 	} else {
 915 		if (error == NULL) {
 916 			error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
 917 					     _("Unable to load location"));
 918 		}
 919 		if (!report_callback (slot, error)) {
 920 			display_view_selection_failure (window, file,
 921 							location, error);
 922 		}
 923 
 924 		if (!gtk_widget_get_visible (GTK_WIDGET (window))) {
 925 			/* Destroy never-had-a-chance-to-be-seen window. This case
 926 			 * happens when a new window cannot display its initial URI. 
 927 			 */
 928 			/* if this is the only window, we don't want to quit, so we redirect it to home */
 929 
 930 			app = GTK_APPLICATION (g_application_get_default ());
 931 
 932 			if (g_list_length (gtk_application_get_windows (app)) == 1) {
 933 				/* the user could have typed in a home directory that doesn't exist,
 934 				   in which case going home would cause an infinite loop, so we
 935 				   better test for that */
 936 
 937 				if (!nautilus_is_root_directory (location)) {
 938 					if (!nautilus_is_home_directory (location)) {	
 939 						nautilus_window_slot_go_home (slot, FALSE);
 940 					} else {
 941 						GFile *root;
 942 
 943 						root = g_file_new_for_path ("/");
 944 						/* the last fallback is to go to a known place that can't be deleted! */
 945 						nautilus_window_slot_open_location (slot, location, 0);
 946 						g_object_unref (root);
 947 					}
 948 				} else {
 949 					gtk_widget_destroy (GTK_WIDGET (window));
 950 				}
 951 			} else {
 952 				/* Since this is a window, destroying it will also unref it. */
 953 				gtk_widget_destroy (GTK_WIDGET (window));
 954 			}
 955 		} else {
 956 			/* Clean up state of already-showing window */
 957 			end_location_change (slot);
 958 
 959 			/* TODO? shouldn't we call
 960 			 *   cancel_viewed_file_changed_callback (slot);
 961 			 * at this point, or in end_location_change()
 962 			 */
 963 			/* We're missing a previous location (if opened location
 964 			 * in a new tab) so close it and return */
 965 			if (slot->location == NULL) {
 966 				nautilus_window_slot_close (window, slot);
 967 			} else {
 968 				/* We disconnected this, so we need to re-connect it */
 969 				viewed_file = nautilus_file_get (slot->location);
 970 				nautilus_window_slot_set_viewed_file (slot, viewed_file);
 971 				nautilus_file_monitor_add (viewed_file, &slot->viewed_file, 0);
 972 				g_signal_connect_object (viewed_file, "changed",
 973 							 G_CALLBACK (viewed_file_changed_callback), slot, 0);
 974 				nautilus_file_unref (viewed_file);
 975 			
 976 				/* Leave the location bar showing the bad location that the user
 977 				 * typed (or maybe achieved by dragging or something). Many times
 978 				 * the mistake will just be an easily-correctable typo. The user
 979 				 * can choose "Refresh" to get the original URI back in the location bar.
 980 				 */
 981 			}
 982 		}
 983 	}
 984 
 985  done:
 986 	g_clear_error (&error);
 987 
 988 	nautilus_file_unref (file);
 989 
 990 	nautilus_profile_end (NULL);
 991 }
 992 
 993 /* Load a view into the window, either reusing the old one or creating
 994  * a new one. This happens when you want to load a new location, or just
 995  * switch to a different view.
 996  * If pending_location is set we're loading a new location and
 997  * pending_location/selection will be used. If not, we're just switching
 998  * view, and the current location will be used.
 999  */
1000 static gboolean
1001 create_content_view (NautilusWindowSlot *slot,
1002 		     const char *view_id,
1003 		     GError **error_out)
1004 {
1005 	NautilusWindow *window;
1006         NautilusView *view;
1007 	GList *selection;
1008 	gboolean ret = TRUE;
1009 	GError *error = NULL;
1010 	NautilusDirectory *old_directory, *new_directory;
1011 
1012 	window = nautilus_window_slot_get_window (slot);
1013 
1014 	nautilus_profile_start (NULL);
1015 
1016  	/* FIXME bugzilla.gnome.org 41243: 
1017 	 * We should use inheritance instead of these special cases
1018 	 * for the desktop window.
1019 	 */
1020         if (NAUTILUS_IS_DESKTOP_WINDOW (window)) {
1021         	/* We force the desktop to use a desktop_icon_view. It's simpler
1022         	 * to fix it here than trying to make it pick the right view in
1023         	 * the first place.
1024         	 */
1025 		view_id = NAUTILUS_DESKTOP_ICON_VIEW_IID;
1026 	} 
1027         
1028         if (slot->content_view != NULL &&
1029 	    g_strcmp0 (nautilus_view_get_view_id (slot->content_view),
1030 			view_id) == 0) {
1031                 /* reuse existing content view */
1032                 view = slot->content_view;
1033                 slot->new_content_view = view;
1034         	g_object_ref (view);
1035         } else {
1036                 /* create a new content view */
1037 		view = nautilus_view_factory_create (view_id, slot);
1038 
1039                 slot->new_content_view = view;
1040 		nautilus_window_connect_content_view (window, slot->new_content_view);
1041         }
1042 
1043 	/* Forward search selection and state before loading the new model */
1044 	new_directory = nautilus_directory_get (slot->pending_location);
1045 	old_directory = nautilus_directory_get (slot->location);
1046 
1047 	if (NAUTILUS_IS_SEARCH_DIRECTORY (new_directory) &&
1048 	    !NAUTILUS_IS_SEARCH_DIRECTORY (old_directory)) {
1049 		nautilus_search_directory_set_base_model (NAUTILUS_SEARCH_DIRECTORY (new_directory), old_directory);
1050 	}
1051 
1052 	if (NAUTILUS_IS_SEARCH_DIRECTORY (old_directory) &&
1053 	    !NAUTILUS_IS_SEARCH_DIRECTORY (new_directory)) {
1054 		/* Reset the search_visible state when going out of a search directory,
1055 		 * before nautilus_window_slot_sync_search_widgets() is called
1056 		 * if we're not being loaded with search visible.
1057 		 */
1058 		if (!slot->load_with_search) {
1059 			slot->search_visible = FALSE;
1060 		}
1061 
1062 		slot->load_with_search = FALSE;
1063 
1064 		if (slot->pending_selection == NULL) {
1065 			slot->pending_selection = nautilus_view_get_selection (slot->content_view);
1066 		}
1067 	}
1068 
1069 	/* Actually load the pending location and selection: */
1070 
1071         if (slot->pending_location != NULL) {
1072 		load_new_location (slot,
1073 				   slot->pending_location,
1074 				   slot->pending_selection,
1075 				   FALSE,
1076 				   TRUE);
1077 
1078 		g_list_free_full (slot->pending_selection, g_object_unref);
1079 		slot->pending_selection = NULL;
1080 	} else if (slot->location != NULL) {
1081 		selection = nautilus_view_get_selection (slot->content_view);
1082 		load_new_location (slot,
1083 				   slot->location,
1084 				   selection,
1085 				   FALSE,
1086 				   TRUE);
1087 		g_list_free_full (selection, g_object_unref);
1088 	} else {
1089 		/* Something is busted, there was no location to load. */
1090 		ret = FALSE;
1091 		error = g_error_new (G_IO_ERROR,
1092 				     G_IO_ERROR_NOT_FOUND,
1093 				     _("Unable to load location"));
1094 	}
1095 
1096 	if (error != NULL) {
1097 		g_propagate_error (error_out, error);
1098 	}
1099 
1100 	nautilus_profile_end (NULL);
1101 
1102 	return ret;
1103 }
1104 
1105 static void
1106 load_new_location (NautilusWindowSlot *slot,
1107 		   GFile *location,
1108 		   GList *selection,
1109 		   gboolean tell_current_content_view,
1110 		   gboolean tell_new_content_view)
1111 {
1112 	GList *selection_copy;
1113 	NautilusView *view;
1114 
1115 	g_assert (slot != NULL);
1116 	g_assert (location != NULL);
1117 
1118 	selection_copy = eel_g_object_list_copy (selection);
1119 	view = NULL;
1120 
1121 	nautilus_profile_start (NULL);
1122 	/* Note, these may recurse into report_load_underway */
1123         if (slot->content_view != NULL && tell_current_content_view) {
1124 		view = slot->content_view;
1125 		nautilus_view_load_location (slot->content_view, location);
1126         }
1127 	
1128         if (slot->new_content_view != NULL && tell_new_content_view &&
1129 	    (!tell_current_content_view ||
1130 	     slot->new_content_view != slot->content_view) ) {
1131 		view = slot->new_content_view;
1132 		nautilus_view_load_location (slot->new_content_view, location);
1133         }
1134 	if (view != NULL) {
1135 		/* slot->new_content_view might have changed here if
1136 		   report_load_underway was called from load_location */
1137 		nautilus_view_set_selection (view, selection_copy);
1138 	}
1139 
1140 	g_list_free_full (selection_copy, g_object_unref);
1141 
1142 	nautilus_profile_end (NULL);
1143 }
1144 
1145 /* A view started to load the location its viewing, either due to
1146  * a load_location request, or some internal reason. Expect
1147  * a matching load_compete later
1148  */
1149 void
1150 nautilus_window_report_load_underway (NautilusWindow *window,
1151 				      NautilusView *view)
1152 {
1153 	NautilusWindowSlot *slot;
1154 
1155 	g_assert (NAUTILUS_IS_WINDOW (window));
1156 
1157 	nautilus_profile_start (NULL);
1158 
1159 	if (window->details->temporarily_ignore_view_signals) {
1160 		return;
1161 	}
1162 
1163 	slot = nautilus_window_get_slot_for_view (window, view);
1164 	g_assert (slot != NULL);
1165 
1166 	if (view == slot->new_content_view) {
1167 		location_has_really_changed (slot);
1168 	} else {
1169 		nautilus_window_slot_set_allow_stop (slot, TRUE);
1170 	}
1171 
1172 	nautilus_profile_end (NULL);
1173 }
1174 
1175 static void
1176 nautilus_window_emit_location_change (NautilusWindow *window,
1177 				      GFile *location)
1178 {
1179 	char *uri;
1180 
1181 	uri = g_file_get_uri (location);
1182 	g_signal_emit_by_name (window, "loading_uri", uri);
1183 	g_free (uri);
1184 }
1185 
1186 static void
1187 nautilus_window_slot_emit_location_change (NautilusWindowSlot *slot,
1188 					   GFile *from,
1189 					   GFile *to)
1190 {
1191 	char *from_uri = NULL;
1192 	char *to_uri = NULL;
1193 
1194 	if (from != NULL)
1195 		from_uri = g_file_get_uri (from);
1196 	if (to != NULL)
1197 		to_uri = g_file_get_uri (to);
1198 	g_signal_emit_by_name (slot, "location-changed", from_uri, to_uri);
1199 	g_free (to_uri);
1200 	g_free (from_uri);
1201 }
1202 
1203 /* reports location change to window's "loading-uri" clients, i.e.
1204  * sidebar panels [used when switching tabs]. It will emit the pending
1205  * location, or the existing location if none is pending.
1206  */
1207 void
1208 nautilus_window_report_location_change (NautilusWindow *window)
1209 {
1210 	NautilusWindowSlot *slot;
1211 	GFile *location;
1212 
1213 	slot = nautilus_window_get_active_slot (window);
1214 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
1215 
1216 	location = NULL;
1217 
1218 	if (slot->pending_location != NULL) {
1219 		location = slot->pending_location;
1220 	}
1221 
1222 	if (location == NULL && slot->location != NULL) {
1223 		location = slot->location;
1224 	}
1225 
1226 	if (location != NULL) {
1227 		nautilus_window_emit_location_change (window, location);
1228 	}
1229 }
1230 
1231 /* This is called when we have decided we can actually change to the new view/location situation. */
1232 static void
1233 location_has_really_changed (NautilusWindowSlot *slot)
1234 {
1235 	NautilusWindow *window;
1236 	GtkWidget *widget;
1237 	GFile *location_copy;
1238 
1239 	window = nautilus_window_slot_get_window (slot);
1240 
1241 	if (slot->new_content_view != NULL) {
1242 		widget = GTK_WIDGET (slot->new_content_view);
1243 		/* Switch to the new content view. */
1244 		if (gtk_widget_get_parent (widget) == NULL) {
1245 			nautilus_window_slot_set_content_view_widget (slot, slot->new_content_view);
1246 		}
1247 		g_object_unref (slot->new_content_view);
1248 		slot->new_content_view = NULL;
1249 	}
1250 
1251       if (slot->pending_location != NULL) {
1252 		/* Tell the window we are finished. */
1253 		update_for_new_location (slot);
1254 	}
1255 
1256 	location_copy = NULL;
1257 	if (slot->location != NULL) {
1258 		location_copy = g_object_ref (slot->location);
1259 	}
1260 
1261 	free_location_change (slot);
1262 
1263 	if (location_copy != NULL) {
1264 		if (slot == nautilus_window_get_active_slot (window)) {
1265 			nautilus_window_emit_location_change (window, location_copy);
1266 		}
1267 
1268 		g_object_unref (location_copy);
1269 	}
1270 }
1271 
1272 static void
1273 slot_add_extension_extra_widgets (NautilusWindowSlot *slot)
1274 {
1275 	GList *providers, *l;
1276 	GtkWidget *widget;
1277 	char *uri;
1278 	NautilusWindow *window;
1279 	
1280 	providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_LOCATION_WIDGET_PROVIDER);
1281 	window = nautilus_window_slot_get_window (slot);
1282 
1283 	uri = g_file_get_uri (slot->location);
1284 	for (l = providers; l != NULL; l = l->next) {
1285 		NautilusLocationWidgetProvider *provider;
1286 		
1287 		provider = NAUTILUS_LOCATION_WIDGET_PROVIDER (l->data);
1288 		widget = nautilus_location_widget_provider_get_widget (provider, uri, GTK_WIDGET (window));
1289 		if (widget != NULL) {
1290 			nautilus_window_slot_add_extra_location_widget (slot, widget);
1291 		}
1292 	}
1293 	g_free (uri);
1294 
1295 	nautilus_module_extension_list_free (providers);
1296 }
1297 
1298 static void
1299 nautilus_window_slot_show_x_content_bar (NautilusWindowSlot *slot, GMount *mount, const char **x_content_types)
1300 {
1301 	GtkWidget *bar;
1302 
1303 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
1304 
1305 	bar = nautilus_x_content_bar_new (mount, x_content_types);
1306 	gtk_widget_show (bar);
1307 	nautilus_window_slot_add_extra_location_widget (slot, bar);
1308 }
1309 
1310 static void
1311 nautilus_window_slot_show_special_location_bar (NautilusWindowSlot     *slot,
1312 						NautilusSpecialLocation special_location)
1313 {
1314 	GtkWidget *bar;
1315 
1316 	bar = nautilus_special_location_bar_new (special_location);
1317 	gtk_widget_show (bar);
1318 
1319 	nautilus_window_slot_add_extra_location_widget (slot, bar);
1320 }
1321 
1322 static void
1323 nautilus_window_slot_show_trash_bar (NautilusWindowSlot *slot)
1324 {
1325 	GtkWidget *bar;
1326 	NautilusView *view;
1327 
1328 	view = nautilus_window_slot_get_current_view (slot);
1329 	bar = nautilus_trash_bar_new (view);
1330 	gtk_widget_show (bar);
1331 
1332 	nautilus_window_slot_add_extra_location_widget (slot, bar);
1333 }
1334 
1335 typedef struct {
1336 	NautilusWindowSlot *slot;
1337 	GCancellable *cancellable;
1338 	GMount *mount;
1339 } FindMountData;
1340 
1341 static void
1342 found_content_type_cb (const char **x_content_types,
1343 		       gpointer user_data)
1344 {
1345 	NautilusWindowSlot *slot;
1346 	FindMountData *data = user_data;
1347 	
1348 	if (g_cancellable_is_cancelled (data->cancellable)) {
1349 		goto out;
1350 	}
1351 
1352 	slot = data->slot;
1353 
1354 	if (x_content_types != NULL && x_content_types[0] != NULL) {
1355 		nautilus_window_slot_show_x_content_bar (slot, data->mount, x_content_types);
1356 	}
1357 
1358 	slot->find_mount_cancellable = NULL;
1359 
1360  out:
1361 	g_object_unref (data->mount);
1362 	g_object_unref (data->cancellable);
1363 	g_free (data);
1364 }
1365 
1366 static void
1367 found_mount_cb (GObject *source_object,
1368 		GAsyncResult *res,
1369 		gpointer user_data)
1370 {
1371 	FindMountData *data = user_data;
1372 	GMount *mount;
1373 
1374 	if (g_cancellable_is_cancelled (data->cancellable)) {
1375 		goto out;
1376 	}
1377 
1378 	mount = g_file_find_enclosing_mount_finish (G_FILE (source_object),
1379 						    res,
1380 						    NULL);
1381 	if (mount != NULL) {
1382 		data->mount = mount;
1383 		nautilus_get_x_content_types_for_mount_async (mount,
1384 							      found_content_type_cb,
1385 							      data->cancellable,
1386 							      data);
1387 		return;
1388 	}
1389 	
1390 	data->slot->find_mount_cancellable = NULL;
1391 
1392  out:
1393 	g_object_unref (data->cancellable);
1394 	g_free (data);
1395 }
1396 
1397 /* Handle the changes for the NautilusWindow itself. */
1398 static void
1399 update_for_new_location (NautilusWindowSlot *slot)
1400 {
1401 	NautilusWindow *window;
1402         GFile *new_location;
1403         NautilusFile *file;
1404 	NautilusDirectory *directory;
1405 	gboolean location_really_changed;
1406 	FindMountData *data;
1407 
1408 	window = nautilus_window_slot_get_window (slot);
1409 	new_location = slot->pending_location;
1410 	slot->pending_location = NULL;
1411 
1412 	file = nautilus_file_get (new_location);
1413 	set_displayed_file (slot, file);
1414 
1415 	update_history (slot, slot->location_change_type, new_location);
1416 
1417 	location_really_changed =
1418 		slot->location == NULL ||
1419 		!g_file_equal (slot->location, new_location);
1420 
1421 	nautilus_window_slot_emit_location_change (slot, slot->location, new_location);
1422 
1423         /* Set the new location. */
1424 	g_clear_object (&slot->location);
1425 	slot->location = new_location;
1426 
1427         /* Create a NautilusFile for this location, so we can catch it
1428          * if it goes away.
1429          */
1430 	cancel_viewed_file_changed_callback (slot);
1431 	nautilus_window_slot_set_viewed_file (slot, file);
1432 	slot->viewed_file_seen = !nautilus_file_is_not_yet_confirmed (file);
1433 	slot->viewed_file_in_trash = nautilus_file_is_in_trash (file);
1434 	nautilus_file_monitor_add (file, &slot->viewed_file, 0);
1435 	g_signal_connect_object (file, "changed",
1436 				 G_CALLBACK (viewed_file_changed_callback), slot, 0);
1437         nautilus_file_unref (file);
1438 
1439 	if (slot == nautilus_window_get_active_slot (window)) {
1440 		/* Sync up and zoom action states */
1441 		nautilus_window_sync_up_button (window);
1442 		nautilus_window_sync_zoom_widgets (window);
1443 
1444 		/* Sync the content view menu for this new location. */
1445 		nautilus_window_sync_view_as_menus (window);
1446 
1447 		/* Load menus from nautilus extensions for this location */
1448 		nautilus_window_load_extension_menus (window);
1449 	}
1450 
1451 	if (location_really_changed) {
1452 		nautilus_window_slot_remove_extra_location_widgets (slot);
1453 		
1454 		directory = nautilus_directory_get (slot->location);
1455 
1456 		if (nautilus_directory_is_in_trash (directory)) {
1457 			nautilus_window_slot_show_trash_bar (slot);
1458 		} else {
1459 			GFile *scripts_file;
1460 			char *scripts_path = nautilus_get_scripts_directory_path ();
1461 			scripts_file = g_file_new_for_path (scripts_path);
1462 			g_free (scripts_path);
1463 			if (nautilus_should_use_templates_directory () &&
1464 			    nautilus_file_is_user_special_directory (file, G_USER_DIRECTORY_TEMPLATES)) {
1465 				nautilus_window_slot_show_special_location_bar (slot, NAUTILUS_SPECIAL_LOCATION_TEMPLATES);
1466 			} else if (g_file_equal (slot->location, scripts_file)) {
1467 				nautilus_window_slot_show_special_location_bar (slot, NAUTILUS_SPECIAL_LOCATION_SCRIPTS);
1468 			}
1469 			g_object_unref (scripts_file);
1470 		}
1471 
1472 		/* need the mount to determine if we should put up the x-content cluebar */
1473 		if (slot->find_mount_cancellable != NULL) {
1474 			g_cancellable_cancel (slot->find_mount_cancellable);
1475 			slot->find_mount_cancellable = NULL;
1476 		}
1477 		
1478 		data = g_new (FindMountData, 1);
1479 		data->slot = slot;
1480 		data->cancellable = g_cancellable_new ();
1481 		data->mount = NULL;
1482 
1483 		slot->find_mount_cancellable = data->cancellable;
1484 		g_file_find_enclosing_mount_async (slot->location,
1485 						   G_PRIORITY_DEFAULT, 
1486 						   data->cancellable,
1487 						   found_mount_cb,
1488 						   data);
1489 
1490 		nautilus_directory_unref (directory);
1491 
1492 		slot_add_extension_extra_widgets (slot);
1493 	}
1494 
1495 	nautilus_window_slot_update_title (slot);
1496 
1497 	if (slot == nautilus_window_get_active_slot (window)) {
1498 		nautilus_window_sync_location_widgets (window);
1499 
1500 		if (location_really_changed) {
1501 			nautilus_window_sync_search_widgets (window);
1502 		}
1503 	}
1504 }
1505 
1506 /* A location load previously announced by load_underway
1507  * has been finished */
1508 void
1509 nautilus_window_report_load_complete (NautilusWindow *window,
1510 				      NautilusView *view)
1511 {
1512 	NautilusWindowSlot *slot;
1513 
1514 	g_assert (NAUTILUS_IS_WINDOW (window));
1515 
1516 	if (window->details->temporarily_ignore_view_signals) {
1517 		return;
1518 	}
1519 
1520 	slot = nautilus_window_get_slot_for_view (window, view);
1521 	g_assert (slot != NULL);
1522 
1523 	/* Only handle this if we're expecting it.
1524 	 * Don't handle it if its from an old view we've switched from */
1525 	if (view == slot->content_view) {
1526 		if (slot->pending_scroll_to != NULL) {
1527 			nautilus_view_scroll_to_file (slot->content_view,
1528 						      slot->pending_scroll_to);
1529 		}
1530 		end_location_change (slot);
1531 	}
1532 }
1533 
1534 static void
1535 end_location_change (NautilusWindowSlot *slot)
1536 {
1537 	char *uri;
1538 
1539 	uri = nautilus_window_slot_get_location_uri (slot);
1540 	if (uri) {
1541 		DEBUG ("Finished loading window for uri %s", uri);
1542 		g_free (uri);
1543 	}
1544 
1545 	nautilus_window_slot_set_allow_stop (slot, FALSE);
1546 
1547         /* Now we can free pending_scroll_to, since the load_complete
1548          * callback already has been emitted.
1549          */
1550 	g_free (slot->pending_scroll_to);
1551 	slot->pending_scroll_to = NULL;
1552 
1553 	free_location_change (slot);
1554 }
1555 
1556 static void
1557 free_location_change (NautilusWindowSlot *slot)
1558 {
1559 	NautilusWindow *window;
1560 
1561 	window = nautilus_window_slot_get_window (slot);
1562 
1563 	g_clear_object (&slot->pending_location);
1564 	g_list_free_full (slot->pending_selection, g_object_unref);
1565 	slot->pending_selection = NULL;
1566 
1567         /* Don't free pending_scroll_to, since thats needed until
1568          * the load_complete callback.
1569          */
1570 
1571 	if (slot->mount_cancellable != NULL) {
1572 		g_cancellable_cancel (slot->mount_cancellable);
1573 		slot->mount_cancellable = NULL;
1574 	}
1575 
1576         if (slot->determine_view_file != NULL) {
1577 		nautilus_file_cancel_call_when_ready
1578 			(slot->determine_view_file,
1579 			 got_file_info_for_view_selection_callback, slot);
1580                 slot->determine_view_file = NULL;
1581         }
1582 
1583         if (slot->new_content_view != NULL) {
1584 		window->details->temporarily_ignore_view_signals = TRUE;
1585 		nautilus_view_stop_loading (slot->new_content_view);
1586 		window->details->temporarily_ignore_view_signals = FALSE;
1587 
1588 		nautilus_window_disconnect_content_view (window, slot->new_content_view);
1589         	g_object_unref (slot->new_content_view);
1590                 slot->new_content_view = NULL;
1591         }
1592 }
1593 
1594 static void
1595 cancel_location_change (NautilusWindowSlot *slot)
1596 {
1597 	GList *selection;
1598 	
1599         if (slot->pending_location != NULL
1600             && slot->location != NULL
1601             && slot->content_view != NULL) {
1602 
1603                 /* No need to tell the new view - either it is the
1604                  * same as the old view, in which case it will already
1605                  * be told, or it is the very pending change we wish
1606                  * to cancel.
1607                  */
1608 		selection = nautilus_view_get_selection (slot->content_view);
1609                 load_new_location (slot,
1610 				   slot->location,
1611 				   selection,
1612 				   TRUE,
1613 				   FALSE);
1614 		g_list_free_full (selection, g_object_unref);
1615         }
1616 
1617         end_location_change (slot);
1618 }
1619 
1620 static void
1621 display_view_selection_failure (NautilusWindow *window, NautilusFile *file,
1622 				GFile *location, GError *error)
1623 {
1624 	char *error_message;
1625 	char *detail_message;
1626 	char *scheme_string;
1627 
1628 	/* Some sort of failure occurred. How 'bout we tell the user? */
1629 
1630 	error_message = g_strdup (_("Oops! Something went wrong."));
1631 	detail_message = NULL;
1632 	if (error == NULL) {
1633 		if (nautilus_file_is_directory (file)) {
1634 			detail_message = g_strdup (_("Unable to display the contents of this folder."));
1635 		} else {
1636 			detail_message = g_strdup (_("This location doesn't appear to be a folder."));
1637 		}
1638 	} else if (error->domain == G_IO_ERROR) {
1639 		switch (error->code) {
1640 		case G_IO_ERROR_NOT_FOUND:
1641 			error_message = g_strdup (_("Unable to find the requested file. Please check the spelling and try again."));
1642 			break;
1643 		case G_IO_ERROR_NOT_SUPPORTED:
1644 			scheme_string = g_file_get_uri_scheme (location);
1645 			if (scheme_string != NULL) {
1646 				detail_message = g_strdup_printf (_("“%s” locations are not supported."),
1647 								  scheme_string);
1648 			} else {
1649 				detail_message = g_strdup (_("Unable to handle this kind of location."));
1650 			}
1651 			g_free (scheme_string);
1652 			break;
1653 		case G_IO_ERROR_NOT_MOUNTED:
1654 			detail_message = g_strdup (_("Unable to access the requested location."));
1655 			break;
1656 		case G_IO_ERROR_PERMISSION_DENIED:
1657 			detail_message = g_strdup (_("Don't have permission to access the requested location."));
1658 			break;
1659 		case G_IO_ERROR_HOST_NOT_FOUND:
1660 			/* This case can be hit for user-typed strings like "foo" due to
1661 			 * the code that guesses web addresses when there's no initial "/".
1662 			 * But this case is also hit for legitimate web addresses when
1663 			 * the proxy is set up wrong.
1664 			 */
1665 			detail_message = g_strdup (_("Unable to find the requested location. Please check the spelling or the network settings."));
1666 			break;
1667 		case G_IO_ERROR_CANCELLED:
1668 		case G_IO_ERROR_FAILED_HANDLED:
1669 			goto done;
1670 		default:
1671 			break;
1672 		}
1673 	}
1674 	
1675 	if (detail_message == NULL) {
1676 		detail_message = g_strdup_printf (_("Unhandled error message: %s"), error->message);
1677 	}
1678 	
1679 	eel_show_error_dialog (error_message, detail_message, GTK_WINDOW (window));
1680  done:
1681 	g_free (error_message);
1682 	g_free (detail_message);
1683 }
1684 
1685 
1686 void
1687 nautilus_window_slot_stop_loading (NautilusWindowSlot *slot)
1688 {
1689 	NautilusWindow *window;
1690 
1691 	window = nautilus_window_slot_get_window (slot);
1692 
1693 	nautilus_view_stop_loading (slot->content_view);
1694 	
1695 	if (slot->new_content_view != NULL) {
1696 		window->details->temporarily_ignore_view_signals = TRUE;
1697 		nautilus_view_stop_loading (slot->new_content_view);
1698 		window->details->temporarily_ignore_view_signals = FALSE;
1699 	}
1700 
1701         cancel_location_change (slot);
1702 }
1703 
1704 void
1705 nautilus_window_slot_set_content_view (NautilusWindowSlot *slot,
1706 				       const char *id)
1707 {
1708 	char *uri;
1709 
1710 	g_assert (slot != NULL);
1711 	g_assert (slot->location != NULL);
1712 	g_assert (id != NULL);
1713 
1714 	uri = nautilus_window_slot_get_location_uri (slot);
1715 	DEBUG ("Change view of window %s to %s", uri, id);
1716 	g_free (uri);
1717 
1718 	if (nautilus_window_slot_content_view_matches_iid (slot, id)) {
1719         	return;
1720         }
1721 
1722         end_location_change (slot);
1723 
1724         nautilus_window_slot_set_allow_stop (slot, TRUE);
1725 
1726         if (nautilus_view_get_selection_count (slot->content_view) == 0) {
1727                 /* If there is no selection, queue a scroll to the same icon that
1728                  * is currently visible */
1729                 slot->pending_scroll_to = nautilus_view_get_first_visible_file (slot->content_view);
1730         }
1731 	slot->location_change_type = NAUTILUS_LOCATION_CHANGE_RELOAD;
1732 	
1733         if (!create_content_view (slot, id, NULL)) {
1734 		/* Just load the homedir. */
1735 		nautilus_window_slot_go_home (slot, FALSE);
1736 	}
1737 }
1738 
1739 void
1740 nautilus_window_manage_views_close_slot (NautilusWindowSlot *slot)
1741 {
1742 	if (slot->content_view != NULL) {
1743 		nautilus_window_disconnect_content_view (nautilus_window_slot_get_window (slot), 
1744 							 slot->content_view);
1745 	}
1746 
1747 	free_location_change (slot);
1748 	cancel_viewed_file_changed_callback (slot);
1749 }
1750 
1751 void
1752 nautilus_window_back_or_forward (NautilusWindow *window, 
1753 				 gboolean back,
1754 				 guint distance,
1755 				 NautilusWindowOpenFlags flags)
1756 {
1757 	NautilusWindowSlot *slot;
1758 	GList *list;
1759 	GFile *location;
1760         guint len;
1761         NautilusBookmark *bookmark;
1762 	GFile *old_location;
1763 
1764 	slot = nautilus_window_get_active_slot (window);
1765 	list = back ? slot->back_list : slot->forward_list;
1766 
1767         len = (guint) g_list_length (list);
1768 
1769         /* If we can't move in the direction at all, just return. */
1770         if (len == 0)
1771                 return;
1772 
1773         /* If the distance to move is off the end of the list, go to the end
1774            of the list. */
1775         if (distance >= len)
1776                 distance = len - 1;
1777 
1778         bookmark = g_list_nth_data (list, distance);
1779 	location = nautilus_bookmark_get_location (bookmark);
1780 
1781 	if (flags != 0) {
1782 		nautilus_window_slot_open_location (slot, location, flags);
1783 	} else {
1784 		char *scroll_pos;
1785 
1786 		old_location = nautilus_window_slot_get_location (slot);
1787 		scroll_pos = nautilus_bookmark_get_scroll_pos (bookmark);
1788 		begin_location_change
1789 			(slot,
1790 			 location, old_location, NULL,
1791 			 back ? NAUTILUS_LOCATION_CHANGE_BACK : NAUTILUS_LOCATION_CHANGE_FORWARD,
1792 			 distance,
1793 			 scroll_pos,
1794 			 NULL, NULL);
1795 
1796 		g_clear_object (&old_location);
1797 		g_free (scroll_pos);
1798 	}
1799 
1800 	g_object_unref (location);
1801 }
1802 
1803 /* reload the contents of the window */
1804 void
1805 nautilus_window_slot_force_reload (NautilusWindowSlot *slot)
1806 {
1807 	GFile *location;
1808         char *current_pos;
1809 	GList *selection;
1810 
1811 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
1812 
1813 	if (slot->location == NULL) {
1814 		return;
1815 	}
1816 
1817 	/* peek_slot_field (window, location) can be free'd during the processing
1818 	 * of begin_location_change, so make a copy
1819 	 */
1820 	location = g_object_ref (slot->location);
1821 	current_pos = NULL;
1822 	selection = NULL;
1823 	if (slot->content_view != NULL) {
1824 		current_pos = nautilus_view_get_first_visible_file (slot->content_view);
1825 		selection = nautilus_view_get_selection (slot->content_view);
1826 	}
1827 	begin_location_change
1828 		(slot, location, location, selection,
1829 		 NAUTILUS_LOCATION_CHANGE_RELOAD, 0, current_pos,
1830 		 NULL, NULL);
1831         g_free (current_pos);
1832 	g_object_unref (location);
1833 	g_list_free_full (selection, g_object_unref);
1834 }
1835 
1836 void
1837 nautilus_window_slot_queue_reload (NautilusWindowSlot *slot)
1838 {
1839 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
1840 
1841 	if (slot->location == NULL) {
1842 		return;
1843 	}
1844 
1845 	if (slot->pending_location != NULL
1846 	    || slot->content_view == NULL
1847 	    || nautilus_view_get_loading (slot->content_view)) {
1848 		/* there is a reload in flight */
1849 		slot->needs_reload = TRUE;
1850 		return;
1851 	}
1852 
1853 	nautilus_window_slot_force_reload (slot);
1854 }