No issues found
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 |
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 }