1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 
3 /*
4  *  Nemo
5  *
6  *  Copyright (C) 1999, 2000 Red Hat, Inc.
7  *  Copyright (C) 1999, 2000, 2001 Eazel, Inc.
8  *
9  *  Nemo 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  *  Nemo 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., 51 Franklin Street, Suite 500, MA 02110-1335, 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 "nemo-window-manage-views.h"
30 
31 #include "nemo-actions.h"
32 #include "nemo-application.h"
33 #include "nemo-floating-bar.h"
34 #include "nemo-location-bar.h"
35 #include "nemo-pathbar.h"
36 #include "nemo-window-private.h"
37 #include "nemo-window-slot.h"
38 #include "nemo-trash-bar.h"
39 #include "nemo-view-factory.h"
40 #include "nemo-x-content-bar.h"
41 #include "nemo-interesting-folder-bar.h"
42 #include "nemo-thumbnail-problem-bar.h"
43 #include <eel/eel-accessibility.h>
44 #include <eel/eel-debug.h>
45 #include <eel/eel-glib-extensions.h>
46 #include <eel/eel-stock-dialogs.h>
47 #include <eel/eel-string.h>
48 #include <eel/eel-vfs-extensions.h>
49 #include <gtk/gtk.h>
50 #include <gdk/gdkx.h>
51 #include <glib/gi18n.h>
52 #include <libnemo-extension/nemo-location-widget-provider.h>
53 #include <libnemo-private/nemo-desktop-directory.h>
54 #include <libnemo-private/nemo-file-attributes.h>
55 #include <libnemo-private/nemo-file-utilities.h>
56 #include <libnemo-private/nemo-file.h>
57 #include <libnemo-private/nemo-global-preferences.h>
58 #include <libnemo-private/nemo-metadata.h>
59 #include <libnemo-private/nemo-module.h>
60 #include <libnemo-private/nemo-monitor.h>
61 #include <libnemo-private/nemo-search-directory.h>
62 
63 #define DEBUG_FLAG NEMO_DEBUG_WINDOW
64 #include <libnemo-private/nemo-debug.h>
65 
66 /* FIXME bugzilla.gnome.org 41243:
67  * We should use inheritance instead of these special cases
68  * for the desktop window.
69  */
70 #include "nemo-desktop-window.h"
71 
72 /* This number controls a maximum character count for a URL that is
73  * displayed as part of a dialog. It's fairly arbitrary -- big enough
74  * to allow most "normal" URIs to display in full, but small enough to
75  * prevent the dialog from getting insanely wide.
76  */
77 #define MAX_URI_IN_DIALOG_LENGTH 60
78 
79 static void begin_location_change                     (NemoWindowSlot         *slot,
80                                                        GFile                      *location,
81                                                        GFile                      *previous_location,
82                                                        GList                      *new_selection,
83                                                        NemoLocationChangeType  type,
84                                                        guint                       distance,
85                                                        const char                 *scroll_pos,
86                                                        gboolean                    mount,
87                                                        NemoWindowGoToCallback      callback,
88                                                        gpointer                    user_data);
89 static void free_location_change                      (NemoWindowSlot         *slot);
90 static void end_location_change                       (NemoWindowSlot         *slot);
91 static void cancel_location_change                    (NemoWindowSlot         *slot);
92 static void got_file_info_for_view_selection_callback (NemoFile               *file,
93 						       gpointer                    callback_data);
94 static void create_content_view                       (NemoWindowSlot         *slot,
95 						       const char                 *view_id);
96 static void display_view_selection_failure            (NemoWindow             *window,
97 						       NemoFile               *file,
98 						       GFile                      *location,
99 						       GError                     *error);
100 static void load_new_location                         (NemoWindowSlot         *slot,
101 						       GFile                      *location,
102 						       GList                      *selection,
103 						       gboolean                    tell_current_content_view,
104 						       gboolean                    tell_new_content_view);
105 static void location_has_really_changed               (NemoWindowSlot         *slot);
106 static void update_for_new_location                   (NemoWindowSlot         *slot);
107 
108 /* set_displayed_location:
109  */
110 static void
set_displayed_location(NemoWindowSlot * slot,GFile * location)111 set_displayed_location (NemoWindowSlot *slot, GFile *location)
112 {
113         GFile *bookmark_location;
114         gboolean recreate;
115 
116         if (slot->current_location_bookmark == NULL || location == NULL) {
117                 recreate = TRUE;
118         } else {
119                 bookmark_location = nemo_bookmark_get_location (slot->current_location_bookmark);
120                 recreate = !g_file_equal (bookmark_location, location);
121                 g_object_unref (bookmark_location);
122         }
123 
124     if (recreate) {
125         /* We've changed locations, must recreate bookmark for current location. */
126         g_clear_object (&slot->last_location_bookmark);
127 
128         slot->last_location_bookmark = slot->current_location_bookmark;
129         slot->current_location_bookmark = (location == NULL) ?
130                             NULL : nemo_bookmark_new (location, NULL, NULL, NULL);
131     }
132 }
133 
134 static void
check_bookmark_location_matches(NemoBookmark * bookmark,GFile * location)135 check_bookmark_location_matches (NemoBookmark *bookmark, GFile *location)
136 {
137         GFile *bookmark_location;
138         char *bookmark_uri, *uri;
139 
140 	bookmark_location = nemo_bookmark_get_location (bookmark);
141 	if (!g_file_equal (location, bookmark_location)) {
142 		bookmark_uri = g_file_get_uri (bookmark_location);
143 		uri = g_file_get_uri (location);
144 		g_warning ("bookmark uri is %s, but expected %s", bookmark_uri, uri);
145 		g_free (uri);
146 		g_free (bookmark_uri);
147 	}
148 	g_object_unref (bookmark_location);
149 }
150 
151 /* Debugging function used to verify that the last_location_bookmark
152  * is in the state we expect when we're about to use it to update the
153  * Back or Forward list.
154  */
155 static void
check_last_bookmark_location_matches_slot(NemoWindowSlot * slot)156 check_last_bookmark_location_matches_slot (NemoWindowSlot *slot)
157 {
158 	check_bookmark_location_matches (slot->last_location_bookmark,
159 					 slot->location);
160 }
161 
162 static void
handle_go_back(NemoWindowSlot * slot,GFile * location)163 handle_go_back (NemoWindowSlot *slot,
164 		GFile *location)
165 {
166 	guint i;
167 	GList *link;
168 	NemoBookmark *bookmark;
169 
170 	/* Going back. Move items from the back list to the forward list. */
171 	g_assert (g_list_length (slot->back_list) > slot->location_change_distance);
172 	check_bookmark_location_matches (NEMO_BOOKMARK (g_list_nth_data (slot->back_list,
173 									     slot->location_change_distance)),
174 					 location);
175 	g_assert (slot->location != NULL);
176 
177 	/* Move current location to Forward list */
178 
179 	check_last_bookmark_location_matches_slot (slot);
180 
181 	/* Use the first bookmark in the history list rather than creating a new one. */
182 	slot->forward_list = g_list_prepend (slot->forward_list,
183 					     slot->last_location_bookmark);
184 	g_object_ref (slot->forward_list->data);
185 
186 	/* Move extra links from Back to Forward list */
187 	for (i = 0; i < slot->location_change_distance; ++i) {
188 		bookmark = NEMO_BOOKMARK (slot->back_list->data);
189 		slot->back_list =
190 			g_list_remove (slot->back_list, bookmark);
191 		slot->forward_list =
192 			g_list_prepend (slot->forward_list, bookmark);
193 	}
194 
195 	/* One bookmark falls out of back/forward lists and becomes viewed location */
196 	link = slot->back_list;
197 	slot->back_list = g_list_remove_link (slot->back_list, link);
198 	g_object_unref (link->data);
199 	g_list_free_1 (link);
200 }
201 
202 static void
handle_go_forward(NemoWindowSlot * slot,GFile * location)203 handle_go_forward (NemoWindowSlot *slot,
204 		   GFile *location)
205 {
206 	guint i;
207 	GList *link;
208 	NemoBookmark *bookmark;
209 
210 	/* Going forward. Move items from the forward list to the back list. */
211 	g_assert (g_list_length (slot->forward_list) > slot->location_change_distance);
212 	check_bookmark_location_matches (NEMO_BOOKMARK (g_list_nth_data (slot->forward_list,
213 									     slot->location_change_distance)),
214 					 location);
215 	g_assert (slot->location != NULL);
216 
217 	/* Move current location to Back list */
218 	check_last_bookmark_location_matches_slot (slot);
219 
220 	/* Use the first bookmark in the history list rather than creating a new one. */
221 	slot->back_list = g_list_prepend (slot->back_list,
222 						     slot->last_location_bookmark);
223 	g_object_ref (slot->back_list->data);
224 
225 	/* Move extra links from Forward to Back list */
226 	for (i = 0; i < slot->location_change_distance; ++i) {
227 		bookmark = NEMO_BOOKMARK (slot->forward_list->data);
228 		slot->forward_list =
229 			g_list_remove (slot->back_list, bookmark);
230 		slot->back_list =
231 			g_list_prepend (slot->forward_list, bookmark);
232 	}
233 
234 	/* One bookmark falls out of back/forward lists and becomes viewed location */
235 	link = slot->forward_list;
236 	slot->forward_list = g_list_remove_link (slot->forward_list, link);
237 	g_object_unref (link->data);
238 	g_list_free_1 (link);
239 }
240 
241 static void
handle_go_elsewhere(NemoWindowSlot * slot,GFile * location)242 handle_go_elsewhere (NemoWindowSlot *slot,
243 		     GFile *location)
244 {
245 	/* Clobber the entire forward list, and move displayed location to back list */
246 	nemo_window_slot_clear_forward_list (slot);
247 
248 	if (slot->location != NULL) {
249 		/* If we're returning to the same uri somehow, don't put this uri on back list.
250 		 * This also avoids a problem where set_displayed_location
251 		 * didn't update last_location_bookmark since the uri didn't change.
252 		 */
253 		if (!g_file_equal (slot->location, location)) {
254 			/* Store bookmark for current location in back list, unless there is no current location */
255 			check_last_bookmark_location_matches_slot (slot);
256 			/* Use the first bookmark in the history list rather than creating a new one. */
257 			slot->back_list = g_list_prepend (slot->back_list,
258 							  slot->last_location_bookmark);
259 			g_object_ref (slot->back_list->data);
260 		}
261 	}
262 }
263 
264 static void
viewed_file_changed_callback(NemoFile * file,NemoWindowSlot * slot)265 viewed_file_changed_callback (NemoFile *file,
266                               NemoWindowSlot *slot)
267 {
268         GFile *new_location;
269 	gboolean is_in_trash, was_in_trash;
270 
271         g_assert (NEMO_IS_FILE (file));
272 	g_assert (NEMO_IS_WINDOW_PANE (slot->pane));
273 	g_assert (file == slot->viewed_file);
274 
275         if (!nemo_file_is_not_yet_confirmed (file)) {
276                 slot->viewed_file_seen = TRUE;
277         }
278 
279 	was_in_trash = slot->viewed_file_in_trash;
280 
281 	slot->viewed_file_in_trash = is_in_trash = nemo_file_is_in_trash (file);
282 
283     /* Close window if the file it's viewing has been deleted or moved to trash. */
284     if (nemo_file_is_gone (file) || (is_in_trash && !was_in_trash)) {
285         if (slot->back_list == NULL) {
286             end_location_change (slot);
287             gtk_widget_destroy (GTK_WIDGET (slot->content_view));
288             nemo_window_close (nemo_window_slot_get_window (slot));
289             return;
290         }
291 
292         /* Don't close the window in the case where the
293         * file was never seen in the first place.
294         */
295         if (slot->viewed_file_seen) {
296             /* auto-show existing parent. */
297             GFile *go_to_file, *parent, *location;
298 
299             /* Detecting a file is gone may happen in the
300             * middle of a pending location change, we
301             * need to cancel it before closing the window
302             * or things break.
303             */
304             /* FIXME: It makes no sense that this call is
305             * needed. When the window is destroyed, it
306             * calls nemo_window_manage_views_destroy,
307             * which calls free_location_change, which
308             * should be sufficient. Also, if this was
309             * really needed, wouldn't it be needed for
310             * all other nemo_window_close callers?
311             */
312             end_location_change (slot);
313 
314             go_to_file = NULL;
315             location =  nemo_file_get_location (file);
316             parent = g_file_get_parent (location);
317             g_object_unref (location);
318 
319             if (parent) {
320                 go_to_file = nemo_find_existing_uri_in_hierarchy (parent);
321                 g_object_unref (parent);
322             }
323 
324             if (go_to_file != NULL) {
325                 /* the path bar URI will be set to go_to_uri immediately
326                 * in begin_location_change, but we don't want the
327                 * inexistant children to show up anymore */
328                 if (slot == slot->pane->active_slot) {
329                     /* multiview-TODO also update NemoWindowSlot
330                     * [which as of writing doesn't save/store any path bar state]
331                     */
332                     nemo_path_bar_clear_buttons (NEMO_PATH_BAR (slot->pane->path_bar));
333                 }
334 
335                 nemo_window_slot_open_location (slot, go_to_file, 0);
336                 g_object_unref (go_to_file);
337             } else {
338                 nemo_window_slot_go_home (slot, FALSE);
339             }
340         }
341     } else {
342         new_location = nemo_file_get_location (file);
343 
344         /* If the file was renamed, update location and/or
345          * title. */
346         if (!g_file_equal (new_location, slot->location)) {
347             g_object_unref (slot->location);
348             slot->location = new_location;
349 
350             if (slot == slot->pane->active_slot) {
351                 nemo_window_pane_sync_location_widgets (slot->pane);
352             }
353         } else {
354             /* TODO?
355             *   why do we update title & icon at all in this case? */
356             g_object_unref (new_location);
357         }
358 
359         nemo_window_slot_update_title (slot);
360         nemo_window_slot_update_icon (slot);
361     }
362 }
363 
364 static void
update_history(NemoWindowSlot * slot,NemoLocationChangeType type,GFile * new_location)365 update_history (NemoWindowSlot *slot,
366                 NemoLocationChangeType type,
367                 GFile *new_location)
368 {
369         switch (type) {
370         case NEMO_LOCATION_CHANGE_STANDARD:
371 		handle_go_elsewhere (slot, new_location);
372                 return;
373         case NEMO_LOCATION_CHANGE_RELOAD:
374                 /* for reload there is no work to do */
375                 return;
376         case NEMO_LOCATION_CHANGE_BACK:
377                 handle_go_back (slot, new_location);
378                 return;
379         case NEMO_LOCATION_CHANGE_FORWARD:
380                 handle_go_forward (slot, new_location);
381                 return;
382         default:
383             break;
384         }
385 	g_return_if_fail (FALSE);
386 }
387 
388 static void
cancel_viewed_file_changed_callback(NemoWindowSlot * slot)389 cancel_viewed_file_changed_callback (NemoWindowSlot *slot)
390 {
391         NemoFile *file;
392 
393         file = slot->viewed_file;
394         if (file != NULL) {
395                 g_signal_handlers_disconnect_by_func (G_OBJECT (file),
396                                                       G_CALLBACK (viewed_file_changed_callback),
397 						      slot);
398                 nemo_file_monitor_remove (file, &slot->viewed_file);
399         }
400 }
401 
402 static void
new_window_show_callback(GtkWidget * widget,gpointer user_data)403 new_window_show_callback (GtkWidget *widget,
404 			  gpointer user_data){
405 	NemoWindow *window;
406 
407 	window = NEMO_WINDOW (user_data);
408 	nemo_window_close (window);
409 
410 	g_signal_handlers_disconnect_by_func (widget,
411 					      G_CALLBACK (new_window_show_callback),
412 					      user_data);
413 }
414 
415 void
nemo_window_slot_open_location_full(NemoWindowSlot * slot,GFile * location,NemoWindowOpenFlags flags,GList * new_selection,NemoWindowGoToCallback callback,gpointer user_data)416 nemo_window_slot_open_location_full (NemoWindowSlot *slot,
417 					 GFile *location,
418 					 NemoWindowOpenFlags flags,
419 					 GList *new_selection,
420 					 NemoWindowGoToCallback callback,
421 					 gpointer user_data)
422 {
423 	NemoWindow *window;
424         NemoWindow *target_window;
425         NemoWindowPane *pane;
426         NemoWindowSlot *target_slot;
427 	NemoWindowOpenFlags slot_flags;
428 	GFile *old_location;
429 	char *old_uri, *new_uri;
430 	int new_slot_position;
431 	GList *l;
432 	gboolean use_same;
433 	gboolean is_desktop;
434 	NemoApplication *app;
435 
436 	window = nemo_window_slot_get_window (slot);
437 
438         target_window = NULL;
439 	target_slot = NULL;
440 	use_same = FALSE;
441 
442 	/* this happens at startup */
443 	old_uri = nemo_window_slot_get_location_uri (slot);
444 	if (old_uri == NULL) {
445 		old_uri = g_strdup ("(none)");
446 		use_same = TRUE;
447 	}
448 	new_uri = g_file_get_uri (location);
449 
450 	DEBUG ("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 = NEMO_IS_DESKTOP_WINDOW (window);
456 
457 	if (is_desktop) {
458 		use_same = !nemo_desktop_window_loaded (NEMO_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 & NEMO_WINDOW_OPEN_FLAG_NEW_TAB) {
464 			flags ^= NEMO_WINDOW_OPEN_FLAG_NEW_TAB;
465 			flags |= NEMO_WINDOW_OPEN_FLAG_NEW_WINDOW;
466 		}
467 	} else {
468 		use_same |= g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_ALWAYS_USE_BROWSER);
469 	}
470 
471 	g_assert (!((flags & NEMO_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 &&
472 		    (flags & NEMO_WINDOW_OPEN_FLAG_NEW_TAB) != 0));
473 
474 	/* and if the flags specify so, this is overridden */
475 	if ((flags & NEMO_WINDOW_OPEN_FLAG_SEARCH) != 0) {
476 		use_same = TRUE;
477 	}
478 	else if ((flags & NEMO_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0) {
479 		use_same = FALSE;
480 	}
481 
482 	/* now get/create the window */
483 	if (use_same) {
484 		target_window = window;
485 	} else {
486 		app = nemo_application_get_singleton ();
487         target_window = nemo_application_create_window (app, gtk_window_get_screen (GTK_WINDOW (window)));
488 	}
489 
490     old_location = nemo_window_slot_get_location (slot);
491 
492     g_assert (target_window != NULL);
493 
494 	/* if the flags say we want a new tab, open a slot in the current window */
495 	if ((flags & NEMO_WINDOW_OPEN_FLAG_NEW_TAB) != 0) {
496 		g_assert (target_window == window);
497 
498 		slot_flags = 0;
499 
500 		new_slot_position = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_NEW_TAB_POSITION);
501 		if (new_slot_position == NEMO_NEW_TAB_POSITION_END) {
502 			slot_flags = NEMO_WINDOW_OPEN_SLOT_APPEND;
503 		}
504 
505 		target_slot = nemo_window_pane_open_slot (nemo_window_get_active_pane (window),
506 							      slot_flags);
507 	}
508 
509 	/* close the current window if the flags say so */
510 	if ((flags & NEMO_WINDOW_OPEN_FLAG_CLOSE_BEHIND) != 0) {
511 		if (!is_desktop) {
512 			if (gtk_widget_get_visible (GTK_WIDGET (target_window))) {
513 				nemo_window_close (window);
514 			} else {
515 				g_signal_connect_object (target_window,
516 							 "show",
517 							 G_CALLBACK (new_window_show_callback),
518 							 window,
519 							 G_CONNECT_AFTER);
520 			}
521 		}
522 	}
523 
524 	if (target_slot == NULL) {
525 		if (target_window == window) {
526 			target_slot = slot;
527 		} else {
528 			target_slot = nemo_window_get_active_slot (target_window);
529 		}
530 	}
531 
532     if (target_window == window && target_slot == slot &&
533         old_location && g_file_equal (old_location, location) &&
534         !is_desktop) {
535 
536         if (callback != NULL) {
537         	callback (window, NULL, user_data);
538         }
539 
540         g_object_unref (old_location);
541             return;
542     }
543 
544     begin_location_change (target_slot,
545                            location,
546                            old_location,
547                            new_selection,
548                            NEMO_LOCATION_CHANGE_STANDARD,
549                            0, NULL,
550                            (flags & NEMO_WINDOW_OPEN_FLAG_MOUNT),
551                            callback,
552                            user_data);
553 
554     /* Additionally, load this in all slots that have no location, this means
555     we load both panes in e.g. a newly opened dual pane window. */
556     for (l = target_window->details->panes; l != NULL; l = l->next) {
557         pane = l->data;
558         slot = pane->active_slot;
559 
560         if (slot->location == NULL && slot->pending_location == NULL) {
561             begin_location_change (slot,
562                                    location,
563                                    old_location,
564                                    new_selection,
565                                    NEMO_LOCATION_CHANGE_STANDARD,
566                                    0, NULL,
567                                    (flags & NEMO_WINDOW_OPEN_FLAG_MOUNT),
568                                    NULL,
569                                    NULL);
570         }
571     }
572 
573     g_clear_object (&old_location);
574 }
575 
576 const char *
nemo_window_slot_get_content_view_id(NemoWindowSlot * slot)577 nemo_window_slot_get_content_view_id (NemoWindowSlot *slot)
578 {
579 	if (slot->content_view == NULL) {
580 		return NULL;
581 	}
582 	return nemo_view_get_view_id (slot->content_view);
583 }
584 
585 gboolean
nemo_window_slot_content_view_matches_iid(NemoWindowSlot * slot,const char * iid)586 nemo_window_slot_content_view_matches_iid (NemoWindowSlot *slot,
587 					       const char *iid)
588 {
589 	if (slot->content_view == NULL) {
590 		return FALSE;
591 	}
592 	return g_strcmp0 (nemo_view_get_view_id (slot->content_view), iid) == 0;
593 }
594 
595 static gboolean
report_callback(NemoWindowSlot * slot,GError * error)596 report_callback (NemoWindowSlot *slot,
597 		 GError *error)
598 {
599 	if (slot->open_callback != NULL) {
600 		slot->open_callback (nemo_window_slot_get_window (slot),
601 				     error, slot->open_callback_user_data);
602 		slot->open_callback = NULL;
603 		slot->open_callback_user_data = NULL;
604 
605 		return TRUE;
606 	}
607 
608 	return FALSE;
609 }
610 
611 /*
612  * begin_location_change
613  *
614  * Change a window slot's location.
615  * @window: The NemoWindow whose location should be changed.
616  * @location: A url specifying the location to load
617  * @previous_location: The url that was previously shown in the window that initialized the change, if any
618  * @new_selection: The initial selection to present after loading the location
619  * @type: Which type of location change is this? Standard, back, forward, or reload?
620  * @distance: If type is back or forward, the index into the back or forward chain. If
621  * type is standard or reload, this is ignored, and must be 0.
622  * @scroll_pos: The file to scroll to when the location is loaded.
623  * @mount: is a mount (always force a reload).
624  * @callback: function to be called when the location is changed.
625  * @user_data: data for @callback.
626  *
627  * This is the core function for changing the location of a window. Every change to the
628  * location begins here.
629  */
630 static void
begin_location_change(NemoWindowSlot * slot,GFile * location,GFile * previous_location,GList * new_selection,NemoLocationChangeType type,guint distance,const char * scroll_pos,gboolean mount,NemoWindowGoToCallback callback,gpointer user_data)631 begin_location_change (NemoWindowSlot        *slot,
632                        GFile                 *location,
633                        GFile                 *previous_location,
634                        GList                 *new_selection,
635                        NemoLocationChangeType type,
636                        guint                  distance,
637                        const char            *scroll_pos,
638                        gboolean               mount,
639                        NemoWindowGoToCallback callback,
640                        gpointer               user_data)
641 {
642         NemoDirectory *directory;
643         NemoFile *file;
644 	gboolean force_reload;
645         char *current_pos;
646 	GFile *from_folder, *parent;
647 	GList *parent_selection = NULL;
648 
649 	g_assert (slot != NULL);
650         g_assert (location != NULL);
651         g_assert (type == NEMO_LOCATION_CHANGE_BACK
652                   || type == NEMO_LOCATION_CHANGE_FORWARD
653                   || distance == 0);
654 
655 	/* If there is no new selection and the new location is
656 	 * a (grand)parent of the old location then we automatically
657 	 * select the folder the previous location was in */
658 	if (new_selection == NULL && previous_location != NULL &&
659 	    g_file_has_prefix (previous_location, location)) {
660 		from_folder = g_object_ref (previous_location);
661 		parent = g_file_get_parent (from_folder);
662 		while (parent != NULL && !g_file_equal (parent, location)) {
663 			g_object_unref (from_folder);
664 			from_folder = parent;
665 			parent = g_file_get_parent (from_folder);
666 		}
667 
668 		if (parent != NULL) {
669 			new_selection = parent_selection =
670 				g_list_prepend (NULL, nemo_file_get (from_folder));
671 			g_object_unref (parent);
672 		}
673 
674 		g_object_unref (from_folder);
675 	}
676 
677 	end_location_change (slot);
678 
679 	nemo_window_slot_set_allow_stop (slot, TRUE);
680 	nemo_window_slot_set_status (slot, " ", NULL);
681 
682 	g_assert (slot->pending_location == NULL);
683 	g_assert (slot->pending_selection == NULL);
684 
685 	slot->pending_location = g_object_ref (location);
686         slot->location_change_type = type;
687         slot->location_change_distance = distance;
688 	slot->tried_mount = FALSE;
689 	slot->pending_selection = eel_g_object_list_copy (new_selection);
690 
691 	slot->pending_scroll_to = g_strdup (scroll_pos);
692 
693 	slot->open_callback = callback;
694 	slot->open_callback_user_data = user_data;
695 
696     directory = nemo_directory_get (location);
697 
698 	/* The code to force a reload is here because if we do it
699 	 * after determining an initial view (in the components), then
700 	 * we end up fetching things twice.
701 	 */
702 	if (type == NEMO_LOCATION_CHANGE_RELOAD || mount) {
703 		force_reload = TRUE;
704 	} else if (!nemo_monitor_active ()) {
705 		force_reload = TRUE;
706 	} else {
707 		force_reload = !nemo_directory_is_local (directory);
708 	}
709 
710 	if (force_reload) {
711         file = nemo_directory_get_corresponding_file (directory);
712         nemo_file_invalidate_all_attributes (file);
713         nemo_file_unref (file);
714 
715         nemo_directory_force_reload (directory);
716 
717 	}
718 
719         nemo_directory_unref (directory);
720 
721 	if (parent_selection != NULL) {
722 		g_list_free_full (parent_selection, g_object_unref);
723 	}
724 
725         /* Set current_bookmark scroll pos */
726         if (slot->current_location_bookmark != NULL &&
727             slot->content_view != NULL) {
728                 current_pos = nemo_view_get_first_visible_file (slot->content_view);
729                 nemo_bookmark_set_scroll_pos (slot->current_location_bookmark, current_pos);
730                 g_free (current_pos);
731         }
732 
733 	/* Get the info needed for view selection */
734 
735         slot->determine_view_file = nemo_file_get (location);
736 	g_assert (slot->determine_view_file != NULL);
737 
738 	/* if the currently viewed file is marked gone while loading the new location,
739 	 * this ensures that the window isn't destroyed */
740         cancel_viewed_file_changed_callback (slot);
741 
742 	nemo_file_call_when_ready (slot->determine_view_file,
743 				       NEMO_FILE_ATTRIBUTE_INFO |
744 				       NEMO_FILE_ATTRIBUTE_MOUNT,
745                                        got_file_info_for_view_selection_callback,
746 				       slot);
747 }
748 
749 typedef struct {
750 	GCancellable *cancellable;
751 	NemoWindowSlot *slot;
752 } MountNotMountedData;
753 
754 static void
mount_not_mounted_callback(GObject * source_object,GAsyncResult * res,gpointer user_data)755 mount_not_mounted_callback (GObject *source_object,
756 			    GAsyncResult *res,
757 			    gpointer user_data)
758 {
759 	MountNotMountedData *data;
760 	NemoWindowSlot *slot;
761 	GError *error;
762 	GCancellable *cancellable;
763 
764 	data = user_data;
765 	slot = data->slot;
766 	cancellable = data->cancellable;
767 	g_free (data);
768 
769 	if (g_cancellable_is_cancelled (cancellable)) {
770 		/* Cancelled, don't call back */
771 		g_object_unref (cancellable);
772 		return;
773 	}
774 
775 	slot->mount_cancellable = NULL;
776 
777 	slot->determine_view_file = nemo_file_get (slot->pending_location);
778 
779 	error = NULL;
780 	if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object), res, &error)) {
781 		slot->mount_error = error;
782 		got_file_info_for_view_selection_callback (slot->determine_view_file, slot);
783 		slot->mount_error = NULL;
784 		g_error_free (error);
785 	} else {
786 		nemo_file_invalidate_all_attributes (slot->determine_view_file);
787 		nemo_file_call_when_ready (slot->determine_view_file,
788 					       NEMO_FILE_ATTRIBUTE_INFO,
789 					       got_file_info_for_view_selection_callback,
790 					       slot);
791 	}
792 
793 	g_object_unref (cancellable);
794 }
795 
796 static void
got_file_info_for_view_selection_callback(NemoFile * file,gpointer callback_data)797 got_file_info_for_view_selection_callback (NemoFile *file,
798 					   gpointer callback_data)
799 {
800         GError *error;
801 	char *view_id;
802 	char *mimetype;
803 	NemoWindow *window;
804 	NemoWindowSlot *slot;
805 	NemoFile *parent_file, *tmp;
806 	GFile *location;
807 	GMountOperation *mount_op;
808 	MountNotMountedData *data;
809 	NemoApplication *app;
810 
811 	slot = callback_data;
812 	window = nemo_window_slot_get_window (slot);
813 
814 	g_assert (slot->determine_view_file == file);
815 	slot->determine_view_file = NULL;
816 
817 	if (slot->mount_error) {
818 		error = slot->mount_error;
819 	} else {
820 		error = nemo_file_get_file_info_error (file);
821 	}
822 
823 	if (error && error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_MOUNTED &&
824 	    !slot->tried_mount) {
825 		slot->tried_mount = TRUE;
826 
827 		mount_op = gtk_mount_operation_new (GTK_WINDOW (window));
828 		g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
829 		location = nemo_file_get_location (file);
830 		data = g_new0 (MountNotMountedData, 1);
831 		data->cancellable = g_cancellable_new ();
832 		data->slot = slot;
833 		slot->mount_cancellable = data->cancellable;
834 		g_file_mount_enclosing_volume (location, 0, mount_op, slot->mount_cancellable,
835 					       mount_not_mounted_callback, data);
836 		g_object_unref (location);
837 		g_object_unref (mount_op);
838 
839 		nemo_file_unref (file);
840 
841 		return;
842 	}
843 
844 	parent_file = nemo_file_get_parent (file);
845 	if ((parent_file != NULL) &&
846 	    nemo_file_get_file_type (file) == G_FILE_TYPE_REGULAR) {
847 		if (slot->pending_selection != NULL) {
848 			g_list_free_full (slot->pending_selection, (GDestroyNotify) nemo_file_unref);
849 		}
850 
851 		g_clear_object (&slot->pending_location);
852 		g_free (slot->pending_scroll_to);
853 
854 		slot->pending_location = nemo_file_get_parent_location (file);
855 		slot->pending_selection = g_list_prepend (NULL, nemo_file_ref (file));
856 		slot->determine_view_file = parent_file;
857 		slot->pending_scroll_to = nemo_file_get_uri (file);
858 
859 		nemo_file_invalidate_all_attributes (slot->determine_view_file);
860 		nemo_file_call_when_ready (slot->determine_view_file,
861 					       NEMO_FILE_ATTRIBUTE_INFO,
862 					       got_file_info_for_view_selection_callback,
863 					       slot);
864 
865 		nemo_file_unref (file);
866 
867 		return;
868 	}
869 
870 	nemo_file_unref (parent_file);
871 	location = slot->pending_location;
872 
873 	view_id = NULL;
874 
875         if (error == NULL ||
876 	    (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_SUPPORTED)) {
877 		/* We got the information we need, now pick what view to use: */
878 
879 		mimetype = nemo_file_get_mime_type (file);
880 
881 		/* Look in metadata for view */
882 		if (nemo_global_preferences_get_inherit_folder_viewer_preference ()) {
883         if (nemo_global_preferences_get_ignore_view_metadata ()) {
884         view_id = g_strdup (nemo_window_get_ignore_meta_view_id (window));
885         } else {
886             parent_file = file;
887             nemo_file_ref(parent_file); // Do this once for the initial file
888             while (parent_file) {
889                 view_id = nemo_file_get_metadata (parent_file, NEMO_METADATA_KEY_DEFAULT_VIEW, NULL);
890                 tmp = nemo_file_get_parent (parent_file);
891                 nemo_file_unref(parent_file);
892                 if (view_id != NULL) {
893                     parent_file = NULL;
894                 } else {
895                     parent_file = tmp;
896                 }
897             }
898         }
899     } else {
900         view_id = nemo_global_preferences_get_ignore_view_metadata () ? g_strdup (nemo_window_get_ignore_meta_view_id (window)) :
901                                                                         nemo_file_get_metadata (file, NEMO_METADATA_KEY_DEFAULT_VIEW, NULL);
902     }
903 
904     if (view_id != NULL &&
905 		    !nemo_view_factory_view_supports_uri (view_id,
906 							      location,
907 							      nemo_file_get_file_type (file),
908 							      mimetype)) {
909 			g_free (view_id);
910 			view_id = NULL;
911 		}
912 
913 		/* Otherwise, use default */
914 		if (view_id == NULL) {
915             gchar *name, *uri;
916             name = nemo_file_get_name (file);
917             uri = nemo_file_get_uri (file);
918 
919             if (g_strcmp0 (name, "x-nemo-search") == 0) {
920                 view_id = g_strdup (NEMO_LIST_VIEW_IID);
921             } else if (eel_uri_is_desktop (uri)) {
922                 view_id = nemo_global_preferences_get_desktop_iid ();
923             } else {
924                 view_id = nemo_global_preferences_get_default_folder_viewer_preference_as_iid ();
925             }
926 
927             g_free (uri);
928             g_free (name);
929 
930 			if (view_id != NULL &&
931 			    !nemo_view_factory_view_supports_uri (view_id,
932 								      location,
933 								      nemo_file_get_file_type (file),
934 								      mimetype)) {
935 				g_free (view_id);
936 				view_id = NULL;
937 			}
938 		}
939 
940 		g_free (mimetype);
941 	}
942 
943 	if (view_id != NULL) {
944 		create_content_view (slot, view_id);
945 		g_free (view_id);
946 
947 		report_callback (slot, NULL);
948 	} else {
949 		if (!report_callback (slot, error)) {
950 			display_view_selection_failure (window, file,
951 							location, error);
952 		}
953 
954 		if (!gtk_widget_get_visible (GTK_WIDGET (window))) {
955 			/* Destroy never-had-a-chance-to-be-seen window. This case
956 			 * happens when a new window cannot display its initial URI.
957 			 */
958 			/* if this is the only window, we don't want to quit, so we redirect it to home */
959 
960 			app = nemo_application_get_singleton ();
961 
962 			if (g_list_length (gtk_application_get_windows (GTK_APPLICATION (app))) == 1) {
963 				/* the user could have typed in a home directory that doesn't exist,
964 				   in which case going home would cause an infinite loop, so we
965 				   better test for that */
966 
967 				if (!nemo_is_root_directory (location)) {
968 					if (!nemo_is_home_directory (location)) {
969 						nemo_window_slot_go_home (slot, FALSE);
970 					} else {
971 						GFile *root;
972 
973 						root = g_file_new_for_path ("/");
974 						/* the last fallback is to go to a known place that can't be deleted! */
975 						nemo_window_slot_open_location (slot, location, 0);
976 						g_object_unref (root);
977 					}
978 				} else {
979 					gtk_widget_destroy (GTK_WIDGET (window));
980 				}
981 			} else {
982 				/* Since this is a window, destroying it will also unref it. */
983 				gtk_widget_destroy (GTK_WIDGET (window));
984 			}
985 		} else {
986 			/* Clean up state of already-showing window */
987 			end_location_change (slot);
988 
989 			/* TODO? shouldn't we call
990 			 *   cancel_viewed_file_changed_callback (slot);
991 			 * at this point, or in end_location_change()
992 			 */
993 			/* We're missing a previous location (if opened location
994 			 * in a new tab) so close it and return */
995 			if (slot->location == NULL) {
996 				nemo_window_pane_close_slot (slot->pane, slot);
997 			} else {
998 				/* We disconnected this, so we need to re-connect it */
999 				NemoFile *viewed_file;
1000 				viewed_file = nemo_file_get (slot->location);
1001 				nemo_window_slot_set_viewed_file (slot, viewed_file);
1002 				nemo_file_monitor_add (viewed_file, &slot->viewed_file, 0);
1003 				g_signal_connect_object (viewed_file, "changed",
1004 							 G_CALLBACK (viewed_file_changed_callback), slot, 0);
1005 				nemo_file_unref (viewed_file);
1006 
1007 				/* Leave the location bar showing the bad location that the user
1008 				 * typed (or maybe achieved by dragging or something). Many times
1009 				 * the mistake will just be an easily-correctable typo. The user
1010 				 * can choose "Refresh" to get the original URI back in the location bar.
1011 				 */
1012 			}
1013 		}
1014 	}
1015 
1016 	nemo_file_unref (file);
1017 }
1018 
1019 /* Load a view into the window, either reusing the old one or creating
1020  * a new one. This happens when you want to load a new location, or just
1021  * switch to a different view.
1022  * If pending_location is set we're loading a new location and
1023  * pending_location/selection will be used. If not, we're just switching
1024  * view, and the current location will be used.
1025  */
1026 static void
create_content_view(NemoWindowSlot * slot,const char * view_id)1027 create_content_view (NemoWindowSlot *slot,
1028                      const char     *view_id)
1029 {
1030     NemoWindow *window;
1031     NemoView *view;
1032     GList *selection;
1033 
1034     window = nemo_window_slot_get_window (slot);
1035 
1036     if (slot->content_view != NULL &&
1037         g_strcmp0 (nemo_view_get_view_id (slot->content_view),
1038         view_id) == 0) {
1039         /* reuse existing content view */
1040         view = slot->content_view;
1041         slot->new_content_view = view;
1042         g_object_ref (view);
1043     } else {
1044         /* create a new content view */
1045         view = nemo_view_factory_create (view_id, slot);
1046         slot->new_content_view = view;
1047         nemo_window_connect_content_view (window, slot->new_content_view);
1048     }
1049 
1050     if (NEMO_IS_DESKTOP_WINDOW (window)) {
1051         NemoDesktopDirectory *directory;
1052 
1053         directory = NEMO_DESKTOP_DIRECTORY (nemo_directory_get (slot->pending_location));
1054         directory->display_number = nemo_desktop_window_get_monitor (NEMO_DESKTOP_WINDOW (window));
1055 
1056         nemo_directory_unref (NEMO_DIRECTORY (directory));
1057     }
1058 
1059     /* Actually load the pending location and selection: */
1060 
1061     if (slot->pending_location != NULL) {
1062         load_new_location (slot,
1063                            slot->pending_location,
1064                            slot->pending_selection,
1065                            FALSE,
1066                            TRUE);
1067 
1068         g_list_free_full (slot->pending_selection, g_object_unref);
1069         slot->pending_selection = NULL;
1070     } else if (slot->location != NULL) {
1071         selection = nemo_view_get_selection (slot->content_view);
1072         load_new_location (slot,
1073                            slot->location,
1074                            selection,
1075                            FALSE,
1076                            TRUE);
1077         g_list_free_full (selection, g_object_unref);
1078     } else {
1079         /* Something is busted, there was no location to load.
1080            Just load the homedir. */
1081         nemo_window_slot_go_home (slot, FALSE);
1082 
1083     }
1084 }
1085 
1086 static void
load_new_location(NemoWindowSlot * slot,GFile * location,GList * selection,gboolean tell_current_content_view,gboolean tell_new_content_view)1087 load_new_location (NemoWindowSlot *slot,
1088 		   GFile *location,
1089 		   GList *selection,
1090 		   gboolean tell_current_content_view,
1091 		   gboolean tell_new_content_view)
1092 {
1093 	GList *selection_copy;
1094 	NemoView *view;
1095 
1096 	g_assert (slot != NULL);
1097 	g_assert (location != NULL);
1098 
1099 	selection_copy = eel_g_object_list_copy (selection);
1100 	view = NULL;
1101 
1102 	/* Note, these may recurse into report_load_underway */
1103         if (slot->content_view != NULL && tell_current_content_view) {
1104 		view = slot->content_view;
1105 		nemo_view_load_location (slot->content_view, location);
1106         }
1107 
1108         if (slot->new_content_view != NULL && tell_new_content_view &&
1109 	    (!tell_current_content_view ||
1110 	     slot->new_content_view != slot->content_view) ) {
1111 		view = slot->new_content_view;
1112 		nemo_view_load_location (slot->new_content_view, location);
1113         }
1114 	if (view != NULL) {
1115 		/* slot->new_content_view might have changed here if
1116 		   report_load_underway was called from load_location */
1117 		nemo_view_set_selection (view, selection_copy);
1118 	}
1119 
1120 	g_list_free_full (selection_copy, g_object_unref);
1121 }
1122 
1123 /* A view started to load the location its viewing, either due to
1124  * a load_location request, or some internal reason. Expect
1125  * a matching load_compete later
1126  */
1127 void
nemo_window_report_load_underway(NemoWindow * window,NemoView * view)1128 nemo_window_report_load_underway (NemoWindow *window,
1129 				      NemoView *view)
1130 {
1131 	NemoWindowSlot *slot;
1132 
1133 	g_assert (NEMO_IS_WINDOW (window));
1134 
1135 	if (window->details->temporarily_ignore_view_signals) {
1136 		return;
1137 	}
1138 
1139 	slot = nemo_window_get_slot_for_view (window, view);
1140 	g_assert (slot != NULL);
1141 
1142 	if (view == slot->new_content_view) {
1143 		location_has_really_changed (slot);
1144 	} else {
1145 		nemo_window_slot_set_allow_stop (slot, TRUE);
1146 	}
1147 }
1148 
1149 static void
nemo_window_emit_location_change(NemoWindow * window,GFile * location)1150 nemo_window_emit_location_change (NemoWindow *window,
1151 				      GFile *location)
1152 {
1153 	char *uri;
1154 
1155 	uri = g_file_get_uri (location);
1156 	g_signal_emit_by_name (window, "loading_uri", uri);
1157 	g_free (uri);
1158 }
1159 
1160 static void
nemo_window_slot_emit_location_change(NemoWindowSlot * slot,GFile * from,GFile * to)1161 nemo_window_slot_emit_location_change (NemoWindowSlot *slot,
1162 					   GFile *from,
1163 					   GFile *to)
1164 {
1165 	char *from_uri = NULL;
1166 	char *to_uri = NULL;
1167 
1168 	if (from != NULL)
1169 		from_uri = g_file_get_uri (from);
1170 	if (to != NULL)
1171 		to_uri = g_file_get_uri (to);
1172 	g_signal_emit_by_name (slot, "location-changed", from_uri, to_uri);
1173 	g_free (to_uri);
1174 	g_free (from_uri);
1175 }
1176 
1177 /* reports location change to window's "loading-uri" clients, i.e.
1178  * sidebar panels [used when switching tabs]. It will emit the pending
1179  * location, or the existing location if none is pending.
1180  */
1181 void
nemo_window_report_location_change(NemoWindow * window)1182 nemo_window_report_location_change (NemoWindow *window)
1183 {
1184 	NemoWindowSlot *slot;
1185 	GFile *location;
1186 
1187 	slot = nemo_window_get_active_slot (window);
1188 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
1189 
1190 	location = NULL;
1191 
1192 	if (slot->pending_location != NULL) {
1193 		location = slot->pending_location;
1194 	}
1195 
1196 	if (location == NULL && slot->location != NULL) {
1197 		location = slot->location;
1198 	}
1199 
1200 	if (location != NULL) {
1201 		nemo_window_emit_location_change (window, location);
1202 	}
1203 }
1204 
1205 static void
real_setup_loading_floating_bar(NemoWindowSlot * slot)1206 real_setup_loading_floating_bar (NemoWindowSlot *slot)
1207 {
1208 	gboolean disable_chrome;
1209 
1210 	g_object_get (nemo_window_slot_get_window (slot),
1211 		      "disable-chrome", &disable_chrome,
1212 		      NULL);
1213 
1214 	if (disable_chrome) {
1215 		gtk_widget_hide (slot->floating_bar);
1216 		return;
1217 	}
1218 
1219 	nemo_floating_bar_set_label (NEMO_FLOATING_BAR (slot->floating_bar),
1220 					 NEMO_IS_SEARCH_DIRECTORY (nemo_view_get_model (slot->content_view)) ?
1221 					 _("Searching...") : _("Loading..."));
1222 	nemo_floating_bar_set_show_spinner (NEMO_FLOATING_BAR (slot->floating_bar),
1223 						TRUE);
1224 	nemo_floating_bar_add_action (NEMO_FLOATING_BAR (slot->floating_bar),
1225 					  GTK_STOCK_STOP,
1226 					  NEMO_FLOATING_BAR_ACTION_ID_STOP);
1227 
1228 	gtk_widget_set_halign (slot->floating_bar, GTK_ALIGN_END);
1229 	gtk_widget_show (slot->floating_bar);
1230 }
1231 
1232 static gboolean
setup_loading_floating_bar_timeout_cb(gpointer user_data)1233 setup_loading_floating_bar_timeout_cb (gpointer user_data)
1234 {
1235 	NemoWindowSlot *slot = user_data;
1236 
1237 	slot->loading_timeout_id = 0;
1238 	real_setup_loading_floating_bar (slot);
1239 
1240 	return FALSE;
1241 }
1242 
1243 static void
setup_loading_floating_bar(NemoWindowSlot * slot)1244 setup_loading_floating_bar (NemoWindowSlot *slot)
1245 {
1246 	/* setup loading overlay */
1247 	if (slot->set_status_timeout_id != 0) {
1248 		g_source_remove (slot->set_status_timeout_id);
1249 		slot->set_status_timeout_id = 0;
1250 	}
1251 
1252 	if (slot->loading_timeout_id != 0) {
1253 		g_source_remove (slot->loading_timeout_id);
1254 		slot->loading_timeout_id = 0;
1255 	}
1256 
1257 	slot->loading_timeout_id =
1258 		g_timeout_add (500, setup_loading_floating_bar_timeout_cb, slot);
1259 }
1260 
1261 /* This is called when we have decided we can actually change to the new view/location situation. */
1262 static void
location_has_really_changed(NemoWindowSlot * slot)1263 location_has_really_changed (NemoWindowSlot *slot)
1264 {
1265 	NemoWindow *window;
1266 	GtkWidget *widget;
1267 	GFile *location_copy;
1268 
1269 	window = nemo_window_slot_get_window (slot);
1270 
1271 	if (slot->new_content_view != NULL) {
1272 		widget = GTK_WIDGET (slot->new_content_view);
1273 		/* Switch to the new content view. */
1274 		if (gtk_widget_get_parent (widget) == NULL) {
1275 			nemo_window_slot_set_content_view_widget (slot, slot->new_content_view);
1276 		}
1277 		g_object_unref (slot->new_content_view);
1278 		slot->new_content_view = NULL;
1279 	}
1280 
1281       if (slot->pending_location != NULL) {
1282 		/* Tell the window we are finished. */
1283 		update_for_new_location (slot);
1284 	}
1285 
1286 	location_copy = NULL;
1287 	if (slot->location != NULL) {
1288 		location_copy = g_object_ref (slot->location);
1289 	}
1290 
1291 	free_location_change (slot);
1292 
1293 	if (location_copy != NULL) {
1294 		if (slot == nemo_window_get_active_slot (window)) {
1295 			nemo_window_emit_location_change (window, location_copy);
1296 		}
1297 
1298 		g_object_unref (location_copy);
1299 	}
1300 
1301 	setup_loading_floating_bar (slot);
1302 }
1303 
1304 static void
slot_add_extension_extra_widgets(NemoWindowSlot * slot)1305 slot_add_extension_extra_widgets (NemoWindowSlot *slot)
1306 {
1307 	GList *providers, *l;
1308 	GtkWidget *widget;
1309 	char *uri;
1310 	NemoWindow *window;
1311 
1312 	providers = nemo_module_get_extensions_for_type (NEMO_TYPE_LOCATION_WIDGET_PROVIDER);
1313 	window = nemo_window_slot_get_window (slot);
1314 
1315 	uri = g_file_get_uri (slot->location);
1316 	for (l = providers; l != NULL; l = l->next) {
1317 		NemoLocationWidgetProvider *provider;
1318 
1319 		provider = NEMO_LOCATION_WIDGET_PROVIDER (l->data);
1320 		widget = nemo_location_widget_provider_get_widget (provider, uri, GTK_WIDGET (window));
1321 		if (widget != NULL) {
1322 			nemo_window_slot_add_extra_location_widget (slot, widget);
1323 		}
1324 	}
1325 	g_free (uri);
1326 
1327 	nemo_module_extension_list_free (providers);
1328 }
1329 
1330 static void
nemo_window_slot_show_x_content_bar(NemoWindowSlot * slot,GMount * mount,const char ** x_content_types)1331 nemo_window_slot_show_x_content_bar (NemoWindowSlot *slot, GMount *mount, const char **x_content_types)
1332 {
1333 	unsigned int n;
1334 
1335 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
1336 
1337 	for (n = 0; x_content_types[n] != NULL; n++) {
1338 		GAppInfo *default_app;
1339 
1340 		/* skip blank media; the burn:/// location will provide it's own cluebar */
1341 		if (g_str_has_prefix (x_content_types[n], "x-content/blank-")) {
1342 			continue;
1343 		}
1344 
1345 		/* don't show the cluebar for windows software */
1346 		if (g_content_type_is_a (x_content_types[n], "x-content/win32-software")) {
1347 			continue;
1348 		}
1349 
1350 		/* only show the cluebar if a default app is available */
1351 		default_app = g_app_info_get_default_for_type (x_content_types[n], FALSE);
1352 		if (default_app != NULL)  {
1353 			GtkWidget *bar;
1354 			bar = nemo_x_content_bar_new (mount, x_content_types[n]);
1355 			gtk_widget_show (bar);
1356 			nemo_window_slot_add_extra_location_widget (slot, bar);
1357 			g_object_unref (default_app);
1358 		}
1359 	}
1360 }
1361 
1362 static void
nemo_window_slot_show_trash_bar(NemoWindowSlot * slot)1363 nemo_window_slot_show_trash_bar (NemoWindowSlot *slot)
1364 {
1365 	GtkWidget *bar;
1366 	NemoView *view;
1367 
1368 	view = nemo_window_slot_get_current_view (slot);
1369 	bar = nemo_trash_bar_new (view);
1370 	gtk_widget_show (bar);
1371 
1372 	nemo_window_slot_add_extra_location_widget (slot, bar);
1373 }
1374 
1375 static void
maybe_show_interesting_folder_bar(NemoWindowSlot * slot)1376 maybe_show_interesting_folder_bar (NemoWindowSlot *slot)
1377 {
1378     GtkWidget *bar = nemo_interesting_folder_bar_new_for_location (nemo_window_slot_get_current_view(slot),
1379                                                                    slot->location);
1380 
1381     if (bar) {
1382         gtk_widget_show (bar);
1383         nemo_window_slot_add_extra_location_widget (slot, bar);
1384     }
1385 }
1386 
1387 typedef struct {
1388 	NemoWindowSlot *slot;
1389 	GCancellable *cancellable;
1390 	GMount *mount;
1391 } FindMountData;
1392 
1393 static void
found_content_type_cb(const char ** x_content_types,gpointer user_data)1394 found_content_type_cb (const char **x_content_types,
1395 		       gpointer user_data)
1396 {
1397 	NemoWindowSlot *slot;
1398 	FindMountData *data = user_data;
1399 
1400 	if (g_cancellable_is_cancelled (data->cancellable)) {
1401 		goto out;
1402 	}
1403 
1404 	slot = data->slot;
1405 
1406 	if (x_content_types != NULL && x_content_types[0] != NULL) {
1407 		nemo_window_slot_show_x_content_bar (slot, data->mount, x_content_types);
1408 	}
1409 
1410 	slot->find_mount_cancellable = NULL;
1411 
1412  out:
1413 	g_object_unref (data->mount);
1414 	g_object_unref (data->cancellable);
1415 	g_free (data);
1416 }
1417 
1418 static void
found_mount_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1419 found_mount_cb (GObject *source_object,
1420 		GAsyncResult *res,
1421 		gpointer user_data)
1422 {
1423 	FindMountData *data = user_data;
1424 	GMount *mount;
1425 
1426 	if (g_cancellable_is_cancelled (data->cancellable)) {
1427 		goto out;
1428 	}
1429 
1430 	mount = g_file_find_enclosing_mount_finish (G_FILE (source_object),
1431 						    res,
1432 						    NULL);
1433 	if (mount != NULL) {
1434 		data->mount = mount;
1435 		nemo_get_x_content_types_for_mount_async (mount,
1436 							      found_content_type_cb,
1437 							      data->cancellable,
1438 							      data);
1439 		return;
1440 	}
1441 
1442 	data->slot->find_mount_cancellable = NULL;
1443 
1444  out:
1445 	g_object_unref (data->cancellable);
1446 	g_free (data);
1447 }
1448 
1449 /* Handle the changes for the NemoWindow itself. */
1450 static void
update_for_new_location(NemoWindowSlot * slot)1451 update_for_new_location (NemoWindowSlot *slot)
1452 {
1453 	NemoWindow *window;
1454         GFile *new_location;
1455         NemoFile *file;
1456 	NemoDirectory *directory;
1457 	gboolean location_really_changed;
1458 	FindMountData *data;
1459 
1460 	window = nemo_window_slot_get_window (slot);
1461 	new_location = slot->pending_location;
1462 	slot->pending_location = NULL;
1463 
1464 	set_displayed_location (slot, new_location);
1465 
1466 	update_history (slot, slot->location_change_type, new_location);
1467 
1468 	location_really_changed =
1469 		slot->location == NULL ||
1470 		!g_file_equal (slot->location, new_location);
1471 
1472 	nemo_window_slot_emit_location_change (slot, slot->location, new_location);
1473 
1474         /* Set the new location. */
1475 	g_clear_object (&slot->location);
1476 	slot->location = new_location;
1477 
1478         /* Create a NemoFile for this location, so we can catch it
1479          * if it goes away.
1480          */
1481 	cancel_viewed_file_changed_callback (slot);
1482 	file = nemo_file_get (slot->location);
1483 	nemo_window_slot_set_viewed_file (slot, file);
1484 	slot->viewed_file_seen = !nemo_file_is_not_yet_confirmed (file);
1485 	slot->viewed_file_in_trash = nemo_file_is_in_trash (file);
1486 	nemo_file_monitor_add (file, &slot->viewed_file, 0);
1487 	g_signal_connect_object (file, "changed",
1488 				 G_CALLBACK (viewed_file_changed_callback), slot, 0);
1489         nemo_file_unref (file);
1490 
1491 	if (slot == nemo_window_get_active_slot (window)) {
1492 		/* Sync up and zoom action states */
1493 		nemo_window_sync_up_button (window);
1494 		nemo_window_sync_zoom_widgets (window);
1495         nemo_window_sync_bookmark_action (window);
1496         nemo_window_sync_view_type (window);
1497         nemo_window_sync_thumbnail_action(window);
1498 
1499 		/* Load menus from nemo extensions for this location */
1500 		nemo_window_load_extension_menus (window);
1501 	}
1502 
1503 	if (location_really_changed) {
1504 		nemo_window_slot_remove_extra_location_widgets (slot);
1505 
1506 		directory = nemo_directory_get (slot->location);
1507 
1508 		if (nemo_directory_is_in_trash (directory)) {
1509 			nemo_window_slot_show_trash_bar (slot);
1510 		}
1511 
1512         maybe_show_interesting_folder_bar (slot);
1513 
1514         nemo_window_slot_check_bad_cache_bar (slot);
1515 
1516 		/* need the mount to determine if we should put up the x-content cluebar */
1517 		if (slot->find_mount_cancellable != NULL) {
1518 			g_cancellable_cancel (slot->find_mount_cancellable);
1519 			slot->find_mount_cancellable = NULL;
1520 		}
1521 
1522 		data = g_new (FindMountData, 1);
1523 		data->slot = slot;
1524 		data->cancellable = g_cancellable_new ();
1525 		data->mount = NULL;
1526 
1527 		slot->find_mount_cancellable = data->cancellable;
1528 		g_file_find_enclosing_mount_async (slot->location,
1529 						   G_PRIORITY_DEFAULT,
1530 						   data->cancellable,
1531 						   found_mount_cb,
1532 						   data);
1533 
1534 		nemo_directory_unref (directory);
1535 
1536 		slot_add_extension_extra_widgets (slot);
1537 	}
1538 
1539 	nemo_window_slot_update_title (slot);
1540 	nemo_window_slot_update_icon (slot);
1541 
1542 	if (slot == slot->pane->active_slot) {
1543 		nemo_window_pane_sync_location_widgets (slot->pane);
1544 
1545 		if (location_really_changed) {
1546 			nemo_window_pane_sync_search_widgets (slot->pane);
1547 		}
1548 	}
1549 
1550     nemo_window_sync_menu_bar (window);
1551 }
1552 
1553 /* A location load previously announced by load_underway
1554  * has been finished */
1555 void
nemo_window_report_load_complete(NemoWindow * window,NemoView * view)1556 nemo_window_report_load_complete (NemoWindow *window,
1557 				      NemoView *view)
1558 {
1559 	NemoWindowSlot *slot;
1560 
1561 	g_assert (NEMO_IS_WINDOW (window));
1562 
1563 	if (window->details->temporarily_ignore_view_signals) {
1564 		return;
1565 	}
1566 
1567 	slot = nemo_window_get_slot_for_view (window, view);
1568 	g_assert (slot != NULL);
1569 
1570 	/* Only handle this if we're expecting it.
1571 	 * Don't handle it if its from an old view we've switched from */
1572 	if (view == slot->content_view) {
1573 		if (slot->pending_scroll_to != NULL) {
1574 			nemo_view_scroll_to_file (slot->content_view,
1575 						      slot->pending_scroll_to);
1576 		}
1577 		end_location_change (slot);
1578 	}
1579 }
1580 
1581 static void
remove_loading_floating_bar(NemoWindowSlot * slot)1582 remove_loading_floating_bar (NemoWindowSlot *slot)
1583 {
1584 	if (slot->loading_timeout_id != 0) {
1585 		g_source_remove (slot->loading_timeout_id);
1586 		slot->loading_timeout_id = 0;
1587 	}
1588 
1589 	gtk_widget_hide (slot->floating_bar);
1590 	nemo_floating_bar_cleanup_actions (NEMO_FLOATING_BAR (slot->floating_bar));
1591 }
1592 
1593 static void
end_location_change(NemoWindowSlot * slot)1594 end_location_change (NemoWindowSlot *slot)
1595 {
1596 	char *uri;
1597 
1598 	uri = nemo_window_slot_get_location_uri (slot);
1599 	if (uri) {
1600 		DEBUG ("Finished loading window for uri %s", uri);
1601 		g_free (uri);
1602 	}
1603 
1604 	nemo_window_slot_set_allow_stop (slot, FALSE);
1605 	remove_loading_floating_bar (slot);
1606 
1607         /* Now we can free pending_scroll_to, since the load_complete
1608          * callback already has been emitted.
1609          */
1610 	g_free (slot->pending_scroll_to);
1611 	slot->pending_scroll_to = NULL;
1612 
1613 	free_location_change (slot);
1614 }
1615 
1616 static void
free_location_change(NemoWindowSlot * slot)1617 free_location_change (NemoWindowSlot *slot)
1618 {
1619 	NemoWindow *window;
1620 
1621 	window = nemo_window_slot_get_window (slot);
1622 
1623 	g_clear_object (&slot->pending_location);
1624 	g_list_free_full (slot->pending_selection, g_object_unref);
1625 	slot->pending_selection = NULL;
1626 
1627         /* Don't free pending_scroll_to, since thats needed until
1628          * the load_complete callback.
1629          */
1630 
1631 	if (slot->mount_cancellable != NULL) {
1632 		g_cancellable_cancel (slot->mount_cancellable);
1633 		slot->mount_cancellable = NULL;
1634 	}
1635 
1636         if (slot->determine_view_file != NULL) {
1637 		nemo_file_cancel_call_when_ready
1638 			(slot->determine_view_file,
1639 			 got_file_info_for_view_selection_callback, slot);
1640                 slot->determine_view_file = NULL;
1641         }
1642 
1643         if (slot->new_content_view != NULL) {
1644 		window->details->temporarily_ignore_view_signals = TRUE;
1645 		nemo_view_stop_loading (slot->new_content_view);
1646 		window->details->temporarily_ignore_view_signals = FALSE;
1647 
1648 		nemo_window_disconnect_content_view (window, slot->new_content_view);
1649         	g_object_unref (slot->new_content_view);
1650                 slot->new_content_view = NULL;
1651         }
1652 }
1653 
1654 static void
cancel_location_change(NemoWindowSlot * slot)1655 cancel_location_change (NemoWindowSlot *slot)
1656 {
1657 	GList *selection;
1658 
1659         if (slot->pending_location != NULL
1660             && slot->location != NULL
1661             && slot->content_view != NULL) {
1662 
1663                 /* No need to tell the new view - either it is the
1664                  * same as the old view, in which case it will already
1665                  * be told, or it is the very pending change we wish
1666                  * to cancel.
1667                  */
1668 		selection = nemo_view_get_selection (slot->content_view);
1669                 load_new_location (slot,
1670 				   slot->location,
1671 				   selection,
1672 				   TRUE,
1673 				   FALSE);
1674 		g_list_free_full (selection, g_object_unref);
1675         }
1676 
1677         end_location_change (slot);
1678 }
1679 
1680 static void
display_view_selection_failure(NemoWindow * window,NemoFile * file,GFile * location,GError * error)1681 display_view_selection_failure (NemoWindow *window, NemoFile *file,
1682 				GFile *location, GError *error)
1683 {
1684 	char *full_uri_for_display;
1685 	char *uri_for_display;
1686 	char *error_message;
1687 	char *detail_message;
1688 	char *scheme_string;
1689 
1690 	/* Some sort of failure occurred. How 'bout we tell the user? */
1691 	full_uri_for_display = g_file_get_parse_name (location);
1692 	/* Truncate the URI so it doesn't get insanely wide. Note that even
1693 	 * though the dialog uses wrapped text, if the URI doesn't contain
1694 	 * white space then the text-wrapping code is too stupid to wrap it.
1695 	 */
1696 	uri_for_display = eel_str_middle_truncate
1697 		(full_uri_for_display, MAX_URI_IN_DIALOG_LENGTH);
1698 	g_free (full_uri_for_display);
1699 
1700 	error_message = NULL;
1701 	detail_message = NULL;
1702 	if (error == NULL) {
1703 		if (nemo_file_is_directory (file)) {
1704 			error_message = g_strdup_printf
1705 				(_("Could not display \"%s\"."),
1706 				 uri_for_display);
1707 			detail_message = g_strdup
1708 				(_("Nemo has no installed viewer capable of displaying the folder."));
1709 		} else {
1710 			error_message = g_strdup_printf
1711 				(_("Could not display \"%s\"."),
1712 				 uri_for_display);
1713 			detail_message = g_strdup
1714 				(_("The location is not a folder."));
1715 		}
1716 	} else if (error->domain == G_IO_ERROR) {
1717 		switch (error->code) {
1718 		case G_IO_ERROR_NOT_FOUND:
1719 			error_message = g_strdup_printf
1720 				(_("Could not find \"%s\"."),
1721 				 uri_for_display);
1722 			detail_message = g_strdup
1723 				(_("Please check the spelling and try again."));
1724 			break;
1725 		case G_IO_ERROR_NOT_SUPPORTED:
1726 			scheme_string = g_file_get_uri_scheme (location);
1727 
1728 			error_message = g_strdup_printf (_("Could not display \"%s\"."),
1729 							 uri_for_display);
1730 			if (scheme_string != NULL) {
1731 				detail_message = g_strdup_printf (_("Nemo cannot handle \"%s\" locations."),
1732 								  scheme_string);
1733 			} else {
1734 				detail_message = g_strdup (_("Nemo cannot handle this kind of location."));
1735 			}
1736 			g_free (scheme_string);
1737 			break;
1738 		case G_IO_ERROR_NOT_MOUNTED:
1739 			error_message = g_strdup_printf (_("Could not display \"%s\"."),
1740 							 uri_for_display);
1741 			detail_message = g_strdup (_("Unable to mount the location."));
1742 			break;
1743 
1744 		case G_IO_ERROR_PERMISSION_DENIED:
1745 			error_message = g_strdup_printf (_("Could not display \"%s\"."),
1746 							 uri_for_display);
1747 			detail_message = g_strdup (_("Access was denied."));
1748 			break;
1749 
1750 		case G_IO_ERROR_HOST_NOT_FOUND:
1751 			/* This case can be hit for user-typed strings like "foo" due to
1752 			 * the code that guesses web addresses when there's no initial "/".
1753 			 * But this case is also hit for legitimate web addresses when
1754 			 * the proxy is set up wrong.
1755 			 */
1756 			error_message = g_strdup_printf (_("Could not display \"%s\", because the host could not be found."),
1757 							 uri_for_display);
1758 			detail_message = g_strdup (_("Check that the spelling is correct and that your proxy settings are correct."));
1759 			break;
1760 		case G_IO_ERROR_CANCELLED:
1761 		case G_IO_ERROR_FAILED_HANDLED:
1762 			g_free (uri_for_display);
1763 			return;
1764 
1765 		default:
1766 			break;
1767 		}
1768 	}
1769 
1770 	if (error_message == NULL) {
1771 		error_message = g_strdup_printf (_("Could not display \"%s\"."),
1772 						 uri_for_display);
1773 		detail_message = g_strdup_printf (_("Error: %s\nPlease select another viewer and try again."), error->message);
1774 	}
1775 
1776 	eel_show_error_dialog (error_message, detail_message, NULL);
1777 
1778 	g_free (uri_for_display);
1779 	g_free (error_message);
1780 	g_free (detail_message);
1781 }
1782 
1783 
1784 void
nemo_window_slot_stop_loading(NemoWindowSlot * slot)1785 nemo_window_slot_stop_loading (NemoWindowSlot *slot)
1786 {
1787 	NemoWindow *window;
1788 
1789 	window = nemo_window_slot_get_window (slot);
1790 
1791 	nemo_view_stop_loading (slot->content_view);
1792 
1793 	if (slot->new_content_view != NULL) {
1794 		window->details->temporarily_ignore_view_signals = TRUE;
1795 		nemo_view_stop_loading (slot->new_content_view);
1796 		window->details->temporarily_ignore_view_signals = FALSE;
1797 	}
1798 
1799         cancel_location_change (slot);
1800 }
1801 
1802 void
nemo_window_slot_set_content_view(NemoWindowSlot * slot,const char * id)1803 nemo_window_slot_set_content_view (NemoWindowSlot *slot,
1804 				       const char *id)
1805 {
1806 	NemoFile *file;
1807 	char *uri;
1808 
1809 	g_assert (slot != NULL);
1810 	g_assert (slot->location != NULL);
1811 	g_assert (id != NULL);
1812 
1813 	uri = nemo_window_slot_get_location_uri (slot);
1814 	DEBUG ("Change view of window %s to %s", uri, id);
1815 	g_free (uri);
1816 
1817 	if (nemo_window_slot_content_view_matches_iid (slot, id)) {
1818         	return;
1819         }
1820 
1821         end_location_change (slot);
1822 
1823 	file = nemo_file_get (slot->location);
1824 
1825     if (nemo_global_preferences_get_ignore_view_metadata ()) {
1826         nemo_window_set_ignore_meta_view_id (nemo_window_slot_get_window (slot), id);
1827     } else {
1828         nemo_file_set_metadata (file, NEMO_METADATA_KEY_DEFAULT_VIEW, NULL, id);
1829     }
1830 
1831     nemo_file_unref (file);
1832 
1833     nemo_window_slot_set_allow_stop (slot, TRUE);
1834 
1835     if (nemo_view_get_selection_count (slot->content_view) == 0) {
1836             /* If there is no selection, queue a scroll to the same icon that
1837              * is currently visible */
1838             slot->pending_scroll_to = nemo_view_get_first_visible_file (slot->content_view);
1839     }
1840 	slot->location_change_type = NEMO_LOCATION_CHANGE_RELOAD;
1841 
1842         create_content_view (slot, id);
1843 }
1844 
1845 void
nemo_window_manage_views_close_slot(NemoWindowSlot * slot)1846 nemo_window_manage_views_close_slot (NemoWindowSlot *slot)
1847 {
1848 	if (slot->content_view != NULL) {
1849 		nemo_window_disconnect_content_view (nemo_window_slot_get_window (slot),
1850 							 slot->content_view);
1851 	}
1852 
1853 	free_location_change (slot);
1854 	cancel_viewed_file_changed_callback (slot);
1855 }
1856 
1857 void
nemo_window_back_or_forward(NemoWindow * window,gboolean back,guint distance,NemoWindowOpenFlags flags)1858 nemo_window_back_or_forward (NemoWindow *window,
1859 				 gboolean back,
1860 				 guint distance,
1861 				 NemoWindowOpenFlags flags)
1862 {
1863 	NemoWindowSlot *slot;
1864 	GList *list;
1865 	GFile *location;
1866         guint len;
1867         NemoBookmark *bookmark;
1868 	GFile *old_location;
1869 
1870 	slot = nemo_window_get_active_slot (window);
1871 	list = back ? slot->back_list : slot->forward_list;
1872 
1873         len = (guint) g_list_length (list);
1874 
1875         /* If we can't move in the direction at all, just return. */
1876         if (len == 0)
1877                 return;
1878 
1879         /* If the distance to move is off the end of the list, go to the end
1880            of the list. */
1881         if (distance >= len)
1882                 distance = len - 1;
1883 
1884         bookmark = g_list_nth_data (list, distance);
1885 	location = nemo_bookmark_get_location (bookmark);
1886 
1887 	if (flags != 0) {
1888 		nemo_window_slot_open_location (slot, location, flags);
1889 	} else {
1890 		char *scroll_pos;
1891 
1892 		old_location = nemo_window_slot_get_location (slot);
1893 		scroll_pos = nemo_bookmark_get_scroll_pos (bookmark);
1894 		begin_location_change
1895 			(slot,
1896 			 location, old_location, NULL,
1897 			 back ? NEMO_LOCATION_CHANGE_BACK : NEMO_LOCATION_CHANGE_FORWARD,
1898 			 distance,
1899 			 scroll_pos,
1900              FALSE,
1901 			 NULL, NULL);
1902 
1903 		g_clear_object (&old_location);
1904 		g_free (scroll_pos);
1905 	}
1906 
1907 	g_object_unref (location);
1908 }
1909 
1910 /* reload the contents of the window */
1911 void
nemo_window_slot_force_reload(NemoWindowSlot * slot)1912 nemo_window_slot_force_reload (NemoWindowSlot *slot)
1913 {
1914 	GFile *location;
1915         char *current_pos;
1916 	GList *selection;
1917 
1918 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
1919 
1920 	if (slot->location == NULL) {
1921 		return;
1922 	}
1923 
1924 	/* peek_slot_field (window, location) can be free'd during the processing
1925 	 * of begin_location_change, so make a copy
1926 	 */
1927 	location = g_object_ref (slot->location);
1928 	current_pos = NULL;
1929 	selection = NULL;
1930 	if (slot->content_view != NULL) {
1931 		current_pos = nemo_view_get_first_visible_file (slot->content_view);
1932 		selection = nemo_view_get_selection (slot->content_view);
1933 	}
1934 	begin_location_change
1935 		(slot, location, location, selection,
1936 		 NEMO_LOCATION_CHANGE_RELOAD, 0, current_pos,
1937 		 FALSE, NULL, NULL);
1938         g_free (current_pos);
1939 	g_object_unref (location);
1940 	g_list_free_full (selection, g_object_unref);
1941 }
1942 
1943 static void
clear_thumbnails_for_view(NemoView * view)1944 clear_thumbnails_for_view (NemoView *view)
1945 {
1946     NemoDirectory *directory;
1947     GList *file_list, *l;
1948 
1949     directory = nemo_view_get_model (view);
1950 
1951     file_list = nemo_directory_get_file_list (directory);
1952 
1953     for (l = file_list; l != NULL; l = l->next) {
1954         NemoFile *file = NEMO_FILE (l->data);
1955 
1956         nemo_file_delete_thumbnail (file);
1957     }
1958 
1959     nemo_file_list_free (file_list);
1960 
1961     nemo_icon_info_clear_caches ();
1962 }
1963 
1964 void
nemo_window_slot_queue_reload(NemoWindowSlot * slot,gboolean clear_thumbs)1965 nemo_window_slot_queue_reload (NemoWindowSlot *slot,
1966                                gboolean        clear_thumbs)
1967 {
1968 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
1969 
1970 	if (slot->location == NULL) {
1971 		return;
1972 	}
1973 
1974 	if (slot->pending_location != NULL
1975 	    || slot->content_view == NULL
1976 	    || nemo_view_get_loading (slot->content_view)) {
1977 		/* there is a reload in flight */
1978 		slot->needs_reload = TRUE;
1979 		return;
1980 	}
1981 
1982     if (clear_thumbs && !nemo_file_is_in_favorites (slot->viewed_file)) {
1983         clear_thumbnails_for_view (slot->content_view);
1984     }
1985 
1986 	nemo_window_slot_force_reload (slot);
1987 }
1988 
1989 void
nemo_window_slot_check_bad_cache_bar(NemoWindowSlot * slot)1990 nemo_window_slot_check_bad_cache_bar (NemoWindowSlot *slot)
1991 {
1992     int show_image_thumbs;
1993     if (NEMO_IS_DESKTOP_WINDOW (nemo_window_slot_get_window (slot)))
1994         return;
1995 
1996     show_image_thumbs = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS);
1997     if (show_image_thumbs != NEMO_SPEED_TRADEOFF_NEVER &&
1998         nemo_application_get_cache_bad (nemo_application_get_singleton ()) &&
1999         !nemo_application_get_cache_problem_ignored (nemo_application_get_singleton ())) {
2000         if (slot->cache_bar != NULL) {
2001             gtk_widget_show (slot->cache_bar);
2002         } else {
2003             GtkWidget *bad_bar = nemo_thumbnail_problem_bar_new (nemo_window_slot_get_current_view (slot));
2004             if (bad_bar) {
2005                 gtk_widget_show (bad_bar);
2006                 nemo_window_slot_add_extra_location_widget (slot, bad_bar);
2007                 slot->cache_bar = bad_bar;
2008 
2009                 g_object_add_weak_pointer (G_OBJECT (bad_bar), (gpointer) &slot->cache_bar);
2010             }
2011         }
2012     } else {
2013         if (slot->cache_bar != NULL) {
2014             gtk_widget_hide (slot->cache_bar);
2015         }
2016     }
2017 }
2018