1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
2 
3    nemo-window-slot.c: Nemo window slot
4 
5    Copyright (C) 2008 Free Software Foundation, Inc.
6 
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16 
17    You should have received a copy of the GNU General Public
18    License along with this program; if not, write to the
19    Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
20    Boston, MA 02110-1335, USA.
21 
22    Author: Christian Neumair <cneumair@gnome.org>
23 */
24 
25 #include "config.h"
26 
27 #include "nemo-window-slot.h"
28 
29 #include "nemo-actions.h"
30 #include "nemo-desktop-window.h"
31 #include "nemo-floating-bar.h"
32 #include "nemo-window-private.h"
33 #include "nemo-window-manage-views.h"
34 #include "nemo-window-types.h"
35 
36 #include <glib/gi18n.h>
37 
38 #include <libnemo-private/nemo-file.h>
39 #include <libnemo-private/nemo-file-utilities.h>
40 #include <libnemo-private/nemo-global-preferences.h>
41 
42 #define DEBUG_FLAG NEMO_DEBUG_WINDOW
43 #include <libnemo-private/nemo-debug.h>
44 
45 #include <eel/eel-string.h>
46 
47 G_DEFINE_TYPE (NemoWindowSlot, nemo_window_slot, GTK_TYPE_BOX);
48 
49 enum {
50 	ACTIVE,
51 	INACTIVE,
52 	CHANGED_PANE,
53 	LOCATION_CHANGED,
54 	LAST_SIGNAL
55 };
56 
57 static guint signals[LAST_SIGNAL] = { 0 };
58 
59 static void
sync_search_directory(NemoWindowSlot * slot)60 sync_search_directory (NemoWindowSlot *slot)
61 {
62 	NemoDirectory *directory;
63 	NemoQuery *query;
64 
65 	g_assert (NEMO_IS_FILE (slot->viewed_file));
66 
67 	directory = nemo_directory_get_for_file (slot->viewed_file);
68 	g_assert (NEMO_IS_SEARCH_DIRECTORY (directory));
69 
70 	query = nemo_query_editor_get_query (slot->query_editor);
71 
72     if (query) {
73         nemo_query_set_show_hidden (query,
74                                     g_settings_get_boolean (nemo_preferences,
75                                                             NEMO_PREFERENCES_SHOW_HIDDEN_FILES));
76     }
77 
78 	nemo_search_directory_set_query (NEMO_SEARCH_DIRECTORY (directory),
79 					     query);
80 
81     g_clear_object (&query);
82 
83 	nemo_window_slot_force_reload (slot);
84 
85 	nemo_directory_unref (directory);
86 }
87 
88 static void
sync_search_location_cb(NemoWindow * window,GError * error,gpointer user_data)89 sync_search_location_cb (NemoWindow *window,
90 			 GError *error,
91 			 gpointer user_data)
92 {
93 	NemoWindowSlot *slot = user_data;
94 
95 	sync_search_directory (slot);
96 }
97 
98 static void
create_new_search(NemoWindowSlot * slot)99 create_new_search (NemoWindowSlot *slot)
100 {
101 	char *uri;
102 	NemoDirectory *directory;
103 	GFile *location;
104 
105 	uri = nemo_search_directory_generate_new_uri ();
106 	location = g_file_new_for_uri (uri);
107 
108 	directory = nemo_directory_get (location);
109 	g_assert (NEMO_IS_SEARCH_DIRECTORY (directory));
110 
111 	nemo_window_slot_open_location_full (slot, location, NEMO_WINDOW_OPEN_FLAG_SEARCH, NULL, sync_search_location_cb, slot);
112 
113 	nemo_directory_unref (directory);
114 	g_object_unref (location);
115 	g_free (uri);
116 }
117 
118 static void
query_editor_cancel_callback(NemoQueryEditor * editor,NemoWindowSlot * slot)119 query_editor_cancel_callback (NemoQueryEditor *editor,
120 			      NemoWindowSlot *slot)
121 {
122 	GtkAction *search;
123 
124 	search = gtk_action_group_get_action (slot->pane->toolbar_action_group,
125 					      NEMO_ACTION_SEARCH);
126 
127 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (search), FALSE);
128 }
129 
130 static void
query_editor_changed_callback(NemoQueryEditor * editor,NemoQuery * query,gboolean reload,NemoWindowSlot * slot)131 query_editor_changed_callback (NemoQueryEditor *editor,
132 			       NemoQuery *query,
133 			       gboolean reload,
134 			       NemoWindowSlot *slot)
135 {
136 	NemoDirectory *directory;
137 
138 	g_assert (NEMO_IS_FILE (slot->viewed_file));
139 
140 	directory = nemo_directory_get_for_file (slot->viewed_file);
141 	if (!NEMO_IS_SEARCH_DIRECTORY (directory)) {
142 		/* this is the first change from the query editor. we
143 		   ask for a location change to the search directory,
144 		   indicate the directory needs to be sync'd with the
145 		   current query. */
146 		create_new_search (slot);
147 		/* Focus is now on the new slot, move it back to query_editor */
148 		gtk_widget_grab_focus (GTK_WIDGET (slot->query_editor));
149 	} else {
150 		sync_search_directory (slot);
151 	}
152 
153 	nemo_directory_unref (directory);
154 }
155 
156 static void
update_query_editor(NemoWindowSlot * slot)157 update_query_editor (NemoWindowSlot *slot)
158 {
159 	NemoDirectory *directory;
160 	NemoSearchDirectory *search_directory;
161 
162 	directory = nemo_directory_get (slot->location);
163 
164 	if (NEMO_IS_SEARCH_DIRECTORY (directory)) {
165 		NemoQuery *query;
166 		search_directory = NEMO_SEARCH_DIRECTORY (directory);
167 		query = nemo_search_directory_get_query (search_directory);
168 		if (query != NULL) {
169 			nemo_query_editor_set_query (slot->query_editor,
170 							 query);
171 			g_object_unref (query);
172 		}
173 	} else {
174 		nemo_query_editor_set_location (slot->query_editor, slot->location);
175 	}
176 
177 	nemo_directory_unref (directory);
178 }
179 
180 static void
ensure_query_editor(NemoWindowSlot * slot)181 ensure_query_editor (NemoWindowSlot *slot)
182 {
183 	g_assert (slot->query_editor != NULL);
184 
185 	update_query_editor (slot);
186 
187     nemo_query_editor_set_active (NEMO_QUERY_EDITOR (slot->query_editor),
188                                   nemo_window_slot_get_location_uri (slot),
189                                   TRUE);
190 
191 	gtk_widget_grab_focus (GTK_WIDGET (slot->query_editor));
192 }
193 
194 void
nemo_window_slot_set_query_editor_visible(NemoWindowSlot * slot,gboolean visible)195 nemo_window_slot_set_query_editor_visible (NemoWindowSlot *slot,
196 					       gboolean            visible)
197 {
198 	if (visible) {
199 		ensure_query_editor (slot);
200 
201 		if (slot->qe_changed_id == 0)
202 			slot->qe_changed_id = g_signal_connect (slot->query_editor, "changed",
203 								G_CALLBACK (query_editor_changed_callback), slot);
204 		if (slot->qe_cancel_id == 0)
205 			slot->qe_cancel_id = g_signal_connect (slot->query_editor, "cancel",
206 							       G_CALLBACK (query_editor_cancel_callback), slot);
207 
208 	} else {
209         nemo_query_editor_set_active (NEMO_QUERY_EDITOR (slot->query_editor), NULL, FALSE);
210 
211         if (slot->qe_changed_id > 0) {
212             g_signal_handler_disconnect (slot->query_editor, slot->qe_changed_id);
213             slot->qe_changed_id = 0;
214         }
215 
216         if (slot->qe_cancel_id > 0) {
217             g_signal_handler_disconnect (slot->query_editor, slot->qe_cancel_id);
218             slot->qe_cancel_id = 0;
219         }
220 
221         nemo_query_editor_set_query (slot->query_editor, NULL);
222 	}
223 }
224 
225 static void
real_active(NemoWindowSlot * slot)226 real_active (NemoWindowSlot *slot)
227 {
228 	NemoWindow *window;
229 	NemoWindowPane *pane;
230 	int page_num;
231 
232 	window = nemo_window_slot_get_window (slot);
233 	pane = slot->pane;
234 	page_num = gtk_notebook_page_num (GTK_NOTEBOOK (pane->notebook),
235 					  GTK_WIDGET (slot));
236 	g_assert (page_num >= 0);
237 
238 	gtk_notebook_set_current_page (GTK_NOTEBOOK (pane->notebook), page_num);
239 
240 	/* sync window to new slot */
241 	nemo_window_push_status (window, slot->status_text);
242 	nemo_window_sync_allow_stop (window, slot);
243 	nemo_window_sync_title (window, slot);
244 	nemo_window_sync_zoom_widgets (window);
245     nemo_window_sync_bookmark_action (window);
246 	nemo_window_pane_sync_location_widgets (slot->pane);
247 	nemo_window_pane_sync_search_widgets (slot->pane);
248 	nemo_window_sync_thumbnail_action(window);
249 
250 	if (slot->viewed_file != NULL) {
251 		nemo_window_sync_view_type (window);
252 		nemo_window_load_extension_menus (window);
253 	}
254 }
255 
256 static void
real_inactive(NemoWindowSlot * slot)257 real_inactive (NemoWindowSlot *slot)
258 {
259 	NemoWindow *window;
260 
261 	window = nemo_window_slot_get_window (slot);
262 	g_assert (slot == nemo_window_get_active_slot (window));
263 }
264 
265 static void
floating_bar_action_cb(NemoFloatingBar * floating_bar,gint action,NemoWindowSlot * slot)266 floating_bar_action_cb (NemoFloatingBar *floating_bar,
267 			gint action,
268 			NemoWindowSlot *slot)
269 {
270 	if (action == NEMO_FLOATING_BAR_ACTION_ID_STOP) {
271 		nemo_window_slot_stop_loading (slot);
272 	}
273 }
274 
275 static void
nemo_window_slot_init(NemoWindowSlot * slot)276 nemo_window_slot_init (NemoWindowSlot *slot)
277 {
278 	GtkWidget *extras_vbox;
279 
280 	gtk_orientable_set_orientation (GTK_ORIENTABLE (slot),
281 					GTK_ORIENTATION_VERTICAL);
282 	gtk_widget_show (GTK_WIDGET (slot));
283 
284 	extras_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
285 	slot->extra_location_widgets = extras_vbox;
286 	gtk_box_pack_start (GTK_BOX (slot), extras_vbox, FALSE, FALSE, 0);
287 	gtk_widget_show (extras_vbox);
288 
289 	slot->query_editor = NEMO_QUERY_EDITOR (nemo_query_editor_new ());
290 
291 	nemo_window_slot_add_extra_location_widget (slot, GTK_WIDGET (slot->query_editor));
292 
293 	slot->view_overlay = gtk_overlay_new ();
294 	gtk_widget_add_events (slot->view_overlay,
295 			       GDK_ENTER_NOTIFY_MASK |
296 			       GDK_LEAVE_NOTIFY_MASK);
297 	gtk_box_pack_start (GTK_BOX (slot), slot->view_overlay, TRUE, TRUE, 0);
298 	gtk_widget_show (slot->view_overlay);
299 
300 	slot->floating_bar = nemo_floating_bar_new ("", FALSE);
301 	gtk_widget_set_halign (slot->floating_bar, GTK_ALIGN_END);
302 	gtk_widget_set_valign (slot->floating_bar, GTK_ALIGN_END);
303 	gtk_overlay_add_overlay (GTK_OVERLAY (slot->view_overlay),
304 				 slot->floating_bar);
305 
306 	g_signal_connect (slot->floating_bar, "action",
307 			  G_CALLBACK (floating_bar_action_cb), slot);
308 
309     slot->cache_bar = NULL;
310 
311 	slot->title = g_strdup (_("Loading..."));
312 }
313 
314 static void
view_end_loading_cb(NemoView * view,gboolean all_files_seen,NemoWindowSlot * slot)315 view_end_loading_cb (NemoView       *view,
316 		     		 gboolean        all_files_seen,
317 		     		 NemoWindowSlot *slot)
318 {
319 	if (slot->needs_reload) {
320 		nemo_window_slot_queue_reload (slot, FALSE);
321 		slot->needs_reload = FALSE;
322 	}
323 }
324 
325 static void
nemo_window_slot_dispose(GObject * object)326 nemo_window_slot_dispose (GObject *object)
327 {
328 	NemoWindowSlot *slot;
329 	GtkWidget *widget;
330 
331 	slot = NEMO_WINDOW_SLOT (object);
332 
333 	nemo_window_slot_clear_forward_list (slot);
334 	nemo_window_slot_clear_back_list (slot);
335     nemo_window_slot_remove_extra_location_widgets (slot);
336 
337 	if (slot->content_view) {
338 		widget = GTK_WIDGET (slot->content_view);
339 		gtk_widget_destroy (widget);
340 		g_object_unref (slot->content_view);
341 		slot->content_view = NULL;
342 	}
343 
344 	if (slot->new_content_view) {
345 		widget = GTK_WIDGET (slot->new_content_view);
346 		gtk_widget_destroy (widget);
347 		g_object_unref (slot->new_content_view);
348 		slot->new_content_view = NULL;
349 	}
350 
351 	if (slot->set_status_timeout_id != 0) {
352 		g_source_remove (slot->set_status_timeout_id);
353 		slot->set_status_timeout_id = 0;
354 	}
355 
356 	if (slot->loading_timeout_id != 0) {
357 		g_source_remove (slot->loading_timeout_id);
358 		slot->loading_timeout_id = 0;
359 	}
360 
361 	nemo_window_slot_set_viewed_file (slot, NULL);
362 	/* TODO? why do we unref here? the file is NULL.
363 	 * It was already here before the slot move, though */
364 	nemo_file_unref (slot->viewed_file);
365 
366 	if (slot->location) {
367 		/* TODO? why do we ref here, instead of unreffing?
368 		 * It was already here before the slot migration, though */
369 		g_object_ref (slot->location);
370 	}
371 
372 	g_list_free_full (slot->pending_selection, g_object_unref);
373 	slot->pending_selection = NULL;
374 
375 	g_clear_object (&slot->current_location_bookmark);
376 	g_clear_object (&slot->last_location_bookmark);
377 
378 	if (slot->find_mount_cancellable != NULL) {
379 		g_cancellable_cancel (slot->find_mount_cancellable);
380 		slot->find_mount_cancellable = NULL;
381 	}
382 
383 	slot->pane = NULL;
384 
385 	g_free (slot->title);
386 	slot->title = NULL;
387 
388 	g_free (slot->status_text);
389 	slot->status_text = NULL;
390 
391 	G_OBJECT_CLASS (nemo_window_slot_parent_class)->dispose (object);
392 }
393 
394 static void
nemo_window_slot_class_init(NemoWindowSlotClass * klass)395 nemo_window_slot_class_init (NemoWindowSlotClass *klass)
396 {
397 	GObjectClass *oclass = G_OBJECT_CLASS (klass);
398 
399 	klass->active = real_active;
400 	klass->inactive = real_inactive;
401 
402 	oclass->dispose = nemo_window_slot_dispose;
403 
404 	signals[ACTIVE] =
405 		g_signal_new ("active",
406 			      G_TYPE_FROM_CLASS (klass),
407 			      G_SIGNAL_RUN_LAST,
408 			      G_STRUCT_OFFSET (NemoWindowSlotClass, active),
409 			      NULL, NULL,
410 			      g_cclosure_marshal_VOID__VOID,
411 			      G_TYPE_NONE, 0);
412 
413 	signals[INACTIVE] =
414 		g_signal_new ("inactive",
415 			      G_TYPE_FROM_CLASS (klass),
416 			      G_SIGNAL_RUN_LAST,
417 			      G_STRUCT_OFFSET (NemoWindowSlotClass, inactive),
418 			      NULL, NULL,
419 			      g_cclosure_marshal_VOID__VOID,
420 			      G_TYPE_NONE, 0);
421 
422 	signals[CHANGED_PANE] =
423 		g_signal_new ("changed-pane",
424 			G_TYPE_FROM_CLASS (klass),
425 			G_SIGNAL_RUN_LAST,
426 			G_STRUCT_OFFSET (NemoWindowSlotClass, changed_pane),
427 			NULL, NULL,
428 			g_cclosure_marshal_VOID__VOID,
429 			G_TYPE_NONE, 0);
430 
431 	signals[LOCATION_CHANGED] =
432 		g_signal_new ("location-changed",
433 			      G_TYPE_FROM_CLASS (klass),
434 			      G_SIGNAL_RUN_LAST,
435 			      0,
436 			      NULL, NULL,
437 			      g_cclosure_marshal_generic,
438 			      G_TYPE_NONE, 2,
439 			      G_TYPE_STRING,
440 			      G_TYPE_STRING);
441 }
442 
443 GFile *
nemo_window_slot_get_location(NemoWindowSlot * slot)444 nemo_window_slot_get_location (NemoWindowSlot *slot)
445 {
446 	g_assert (slot != NULL);
447 
448 	if (slot->location != NULL) {
449 		return g_object_ref (slot->location);
450 	}
451 	return NULL;
452 }
453 
454 char *
nemo_window_slot_get_location_uri(NemoWindowSlot * slot)455 nemo_window_slot_get_location_uri (NemoWindowSlot *slot)
456 {
457 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
458 
459 	if (slot->location) {
460 		return g_file_get_uri (slot->location);
461 	}
462 	return NULL;
463 }
464 
465 void
nemo_window_slot_make_hosting_pane_active(NemoWindowSlot * slot)466 nemo_window_slot_make_hosting_pane_active (NemoWindowSlot *slot)
467 {
468 	g_assert (NEMO_IS_WINDOW_PANE (slot->pane));
469 
470 	nemo_window_set_active_slot (nemo_window_slot_get_window (slot),
471 					 slot);
472 }
473 
474 NemoWindow *
nemo_window_slot_get_window(NemoWindowSlot * slot)475 nemo_window_slot_get_window (NemoWindowSlot *slot)
476 {
477 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
478 	return slot->pane->window;
479 }
480 
481 /* nemo_window_slot_update_title:
482  *
483  * Re-calculate the slot title.
484  * Called when the location or view has changed.
485  * @slot: The NemoWindowSlot in question.
486  *
487  */
488 void
nemo_window_slot_update_title(NemoWindowSlot * slot)489 nemo_window_slot_update_title (NemoWindowSlot *slot)
490 {
491 	NemoWindow *window;
492 	char *title;
493 	gboolean do_sync = FALSE;
494 
495 	title = nemo_compute_title_for_location (slot->location);
496 	window = nemo_window_slot_get_window (slot);
497 
498 	if (g_strcmp0 (title, slot->title) != 0) {
499 		do_sync = TRUE;
500 
501 		g_free (slot->title);
502 		slot->title = title;
503 		title = NULL;
504 	}
505 
506 	if (strlen (slot->title) > 0 &&
507 	    slot->current_location_bookmark != NULL) {
508 		do_sync = TRUE;
509 	}
510 
511 	if (do_sync) {
512 		nemo_window_sync_title (window, slot);
513 	}
514 
515 	if (title != NULL) {
516 		g_free (title);
517 	}
518 }
519 
520 /* nemo_window_slot_update_icon:
521  *
522  * Re-calculate the slot icon
523  * Called when the location or view or icon set has changed.
524  * @slot: The NemoWindowSlot in question.
525  */
526 void
nemo_window_slot_update_icon(NemoWindowSlot * slot)527 nemo_window_slot_update_icon (NemoWindowSlot *slot)
528 {
529 	NemoWindow *window;
530 	NemoIconInfo *info;
531 	const char *icon_name;
532 	GdkPixbuf *pixbuf;
533 
534 	window = nemo_window_slot_get_window (slot);
535 	info = NEMO_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->get_icon (window, slot);
536 
537 	icon_name = NULL;
538 	if (info) {
539 		icon_name = nemo_icon_info_get_used_name (info);
540 		if (icon_name != NULL) {
541 			/* Gtk+ doesn't short circuit this (yet), so avoid lots of work
542 			 * if we're setting to the same icon. This happens a lot e.g. when
543 			 * the trash directory changes due to the file count changing.
544 			 */
545 			if (g_strcmp0 (icon_name, gtk_window_get_icon_name (GTK_WINDOW (window))) != 0) {
546 				gtk_window_set_icon_name (GTK_WINDOW (window), icon_name);
547 			}
548 		} else {
549 			pixbuf = nemo_icon_info_get_pixbuf_nodefault (info);
550 
551 			if (pixbuf) {
552 				gtk_window_set_icon (GTK_WINDOW (window), pixbuf);
553 				g_object_unref (pixbuf);
554 			}
555 		}
556 
557         nemo_icon_info_unref (info);
558 	}
559 }
560 
561 void
nemo_window_slot_set_show_thumbnails(NemoWindowSlot * slot,gboolean show_thumbnails)562 nemo_window_slot_set_show_thumbnails (NemoWindowSlot *slot,
563                                       gboolean show_thumbnails)
564 {
565   NemoDirectory *directory;
566 
567   directory = nemo_directory_get (slot->location);
568   nemo_directory_set_show_thumbnails(directory, show_thumbnails);
569 }
570 
571 void
nemo_window_slot_set_content_view_widget(NemoWindowSlot * slot,NemoView * new_view)572 nemo_window_slot_set_content_view_widget (NemoWindowSlot *slot,
573 					      NemoView *new_view)
574 {
575 	NemoWindow *window;
576 	GtkWidget *widget;
577 
578 	window = nemo_window_slot_get_window (slot);
579 
580 	if (slot->content_view != NULL) {
581 		/* disconnect old view */
582 		g_signal_handlers_disconnect_by_func (slot->content_view, G_CALLBACK (view_end_loading_cb), slot);
583 
584 		nemo_window_disconnect_content_view (window, slot->content_view);
585 
586 		widget = GTK_WIDGET (slot->content_view);
587 		gtk_widget_destroy (widget);
588 		g_object_unref (slot->content_view);
589 		slot->content_view = NULL;
590 	}
591 
592 	if (new_view != NULL) {
593 		widget = GTK_WIDGET (new_view);
594 		gtk_container_add (GTK_CONTAINER (slot->view_overlay), widget);
595 		gtk_widget_show (widget);
596 
597 		slot->content_view = new_view;
598 		g_object_ref (slot->content_view);
599 
600 		g_signal_connect (new_view, "end_loading", G_CALLBACK (view_end_loading_cb), slot);
601 
602 		/* connect new view */
603 		nemo_window_connect_content_view (window, new_view);
604 	}
605 }
606 
607 void
nemo_window_slot_set_allow_stop(NemoWindowSlot * slot,gboolean allow)608 nemo_window_slot_set_allow_stop (NemoWindowSlot *slot,
609 				     gboolean allow)
610 {
611 	NemoWindow *window;
612 
613 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
614 
615 	slot->allow_stop = allow;
616 
617 	window = nemo_window_slot_get_window (slot);
618 	nemo_window_sync_allow_stop (window, slot);
619 }
620 
621 static void
real_slot_set_short_status(NemoWindowSlot * slot,const gchar * status)622 real_slot_set_short_status (NemoWindowSlot *slot,
623 			    const gchar *status)
624 {
625 
626 	gboolean show_statusbar;
627 	gboolean disable_chrome;
628 
629 	nemo_floating_bar_cleanup_actions (NEMO_FLOATING_BAR (slot->floating_bar));
630 	nemo_floating_bar_set_show_spinner (NEMO_FLOATING_BAR (slot->floating_bar),
631 						FALSE);
632 
633 	show_statusbar = g_settings_get_boolean (nemo_window_state,
634 						 NEMO_WINDOW_STATE_START_WITH_STATUS_BAR);
635 
636 	g_object_get (nemo_window_slot_get_window (slot),
637 		      "disable-chrome", &disable_chrome,
638 		      NULL);
639 
640 	if (status == NULL || show_statusbar || disable_chrome) {
641 		gtk_widget_hide (slot->floating_bar);
642 		return;
643 	}
644 
645 	nemo_floating_bar_set_label (NEMO_FLOATING_BAR (slot->floating_bar), status);
646 	gtk_widget_show (slot->floating_bar);
647 }
648 
649 typedef struct {
650 	gchar *status;
651 	NemoWindowSlot *slot;
652 } SetStatusData;
653 
654 static void
set_status_data_free(gpointer data)655 set_status_data_free (gpointer data)
656 {
657 	SetStatusData *status_data = data;
658 
659 	g_free (status_data->status);
660 
661 	g_slice_free (SetStatusData, data);
662 }
663 
664 static gboolean
set_status_timeout_cb(gpointer data)665 set_status_timeout_cb (gpointer data)
666 {
667 	SetStatusData *status_data = data;
668 
669 	status_data->slot->set_status_timeout_id = 0;
670 	real_slot_set_short_status (status_data->slot, status_data->status);
671 
672 	return FALSE;
673 }
674 
675 static void
set_floating_bar_status(NemoWindowSlot * slot,const gchar * status)676 set_floating_bar_status (NemoWindowSlot *slot,
677 			 const gchar *status)
678 {
679 	GtkSettings *settings;
680 	gint double_click_time;
681 	SetStatusData *status_data;
682 
683 	if (slot->set_status_timeout_id != 0) {
684 		g_source_remove (slot->set_status_timeout_id);
685 		slot->set_status_timeout_id = 0;
686 	}
687 
688 	settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (slot->content_view)));
689 	g_object_get (settings,
690 		      "gtk-double-click-time", &double_click_time,
691 		      NULL);
692 
693 	status_data = g_slice_new0 (SetStatusData);
694 	status_data->status = g_strdup (status);
695 	status_data->slot = slot;
696 
697 	/* waiting for half of the double-click-time before setting
698 	 * the status seems to be a good approximation of not setting it
699 	 * too often and not delaying the statusbar too much.
700 	 */
701 	slot->set_status_timeout_id =
702 		g_timeout_add_full (G_PRIORITY_DEFAULT,
703 				    (guint) (double_click_time / 2),
704 				    set_status_timeout_cb,
705 				    status_data,
706 				    set_status_data_free);
707 }
708 
709 void
nemo_window_slot_set_status(NemoWindowSlot * slot,const char * status,const char * short_status)710 nemo_window_slot_set_status (NemoWindowSlot *slot,
711 				 const char *status,
712 				 const char *short_status)
713 {
714 	NemoWindow *window;
715 
716 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
717 
718 	g_free (slot->status_text);
719 	slot->status_text = g_strdup (status);
720 
721 	if (slot->content_view != NULL) {
722 		set_floating_bar_status (slot, short_status);
723 	}
724 
725 	window = nemo_window_slot_get_window (slot);
726 	if (slot == nemo_window_get_active_slot (window)) {
727 		nemo_window_push_status (window, slot->status_text);
728 	}
729 }
730 
731 static void
remove_all_extra_location_widgets(GtkWidget * widget,gpointer data)732 remove_all_extra_location_widgets (GtkWidget *widget,
733 				   gpointer data)
734 {
735 	NemoWindowSlot *slot = data;
736 	NemoDirectory *directory;
737 
738 	directory = nemo_directory_get (slot->location);
739 	if (widget != GTK_WIDGET (slot->query_editor)) {
740 		gtk_container_remove (GTK_CONTAINER (slot->extra_location_widgets), widget);
741 	}
742 
743 	nemo_directory_unref (directory);
744 }
745 
746 void
nemo_window_slot_remove_extra_location_widgets(NemoWindowSlot * slot)747 nemo_window_slot_remove_extra_location_widgets (NemoWindowSlot *slot)
748 {
749     gtk_container_foreach (GTK_CONTAINER (slot->extra_location_widgets),
750                            remove_all_extra_location_widgets,
751                            slot);
752 }
753 
754 void
nemo_window_slot_add_extra_location_widget(NemoWindowSlot * slot,GtkWidget * widget)755 nemo_window_slot_add_extra_location_widget (NemoWindowSlot *slot,
756 						GtkWidget *widget)
757 {
758 	gtk_box_pack_start (GTK_BOX (slot->extra_location_widgets),
759 			    widget, TRUE, TRUE, 0);
760 	gtk_widget_show (slot->extra_location_widgets);
761 }
762 
763 /* returns either the pending or the actual current uri */
764 char *
nemo_window_slot_get_current_uri(NemoWindowSlot * slot)765 nemo_window_slot_get_current_uri (NemoWindowSlot *slot)
766 {
767 	if (slot->pending_location != NULL) {
768 		return g_file_get_uri (slot->pending_location);
769 	}
770 
771 	if (slot->location != NULL) {
772 		return g_file_get_uri (slot->location);
773 	}
774 
775 	g_assert_not_reached ();
776 	return NULL;
777 }
778 
779 NemoView *
nemo_window_slot_get_current_view(NemoWindowSlot * slot)780 nemo_window_slot_get_current_view (NemoWindowSlot *slot)
781 {
782 	if (slot->content_view != NULL) {
783 		return slot->content_view;
784 	} else if (slot->new_content_view) {
785 		return slot->new_content_view;
786 	}
787 
788 	return NULL;
789 }
790 
791 void
nemo_window_slot_go_home(NemoWindowSlot * slot,NemoWindowOpenFlags flags)792 nemo_window_slot_go_home (NemoWindowSlot *slot,
793 			      NemoWindowOpenFlags flags)
794 {
795 	GFile *home;
796 
797 	g_return_if_fail (NEMO_IS_WINDOW_SLOT (slot));
798 
799 	home = g_file_new_for_path (g_get_home_dir ());
800 	nemo_window_slot_open_location (slot, home, flags);
801 	g_object_unref (home);
802 }
803 
804 void
nemo_window_slot_go_up(NemoWindowSlot * slot,NemoWindowOpenFlags flags)805 nemo_window_slot_go_up (NemoWindowSlot *slot,
806 			    NemoWindowOpenFlags flags)
807 {
808 	GFile *parent;
809 	char * uri;
810 
811 	if (slot->location == NULL) {
812 		return;
813 	}
814 
815 	parent = g_file_get_parent (slot->location);
816 	if (parent == NULL) {
817 		if (g_file_has_uri_scheme (slot->location, "smb")) {
818 			uri = g_file_get_uri (slot->location);
819 
820             DEBUG ("Starting samba URI for navigation: %s", uri);
821 
822 			if (g_strcmp0 ("smb:///", uri) == 0) {
823 				parent = g_file_new_for_uri ("network:///");
824 			}
825 			else {
826                 GString *gstr;
827                 char * temp;
828 
829                 gstr = g_string_new (uri);
830 
831 				// Remove last /
832                 if (g_str_has_suffix (gstr->str, "/")) {
833                     gstr = g_string_set_size (gstr, gstr->len - 1);
834                 }
835 
836 				// Remove last part of string after last remaining /
837 				temp = g_strrstr (gstr->str, "/") + 1;
838 				if (temp != NULL) {
839                     gstr = g_string_set_size (gstr, temp - gstr->str);
840 				}
841 
842                 // if we're going to end up with smb://, redirect it to network instead.
843                 if (g_strcmp0 ("smb://", gstr->str) == 0) {
844                     gstr = g_string_assign (gstr, "network:///");
845                 }
846 
847                 uri = g_string_free (gstr, FALSE);
848 
849 				parent = g_file_new_for_uri (uri);
850 
851                 DEBUG ("Ending samba URI for navigation: %s", uri);
852 			}
853 			g_free (uri);
854 		}
855 		else {
856 			return;
857 		}
858 	}
859 
860 	nemo_window_slot_open_location (slot, parent, flags);
861 	g_object_unref (parent);
862 }
863 
864 void
nemo_window_slot_clear_forward_list(NemoWindowSlot * slot)865 nemo_window_slot_clear_forward_list (NemoWindowSlot *slot)
866 {
867 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
868 
869 	g_list_free_full (slot->forward_list, g_object_unref);
870 	slot->forward_list = NULL;
871 }
872 
873 void
nemo_window_slot_clear_back_list(NemoWindowSlot * slot)874 nemo_window_slot_clear_back_list (NemoWindowSlot *slot)
875 {
876 	g_assert (NEMO_IS_WINDOW_SLOT (slot));
877 
878 	g_list_free_full (slot->back_list, g_object_unref);
879 	slot->back_list = NULL;
880 }
881 
882 gboolean
nemo_window_slot_should_close_with_mount(NemoWindowSlot * slot,GMount * mount)883 nemo_window_slot_should_close_with_mount (NemoWindowSlot *slot,
884 					      GMount *mount)
885 {
886 	GFile *mount_location;
887 	gboolean close_with_mount;
888 
889 	mount_location = g_mount_get_root (mount);
890 	close_with_mount =
891 		g_file_has_prefix (NEMO_WINDOW_SLOT (slot)->location, mount_location) ||
892 		g_file_equal (NEMO_WINDOW_SLOT (slot)->location, mount_location);
893 
894 	g_object_unref (mount_location);
895 
896 	return close_with_mount;
897 }
898 
899 NemoWindowSlot *
nemo_window_slot_new(NemoWindowPane * pane)900 nemo_window_slot_new (NemoWindowPane *pane)
901 {
902 	NemoWindowSlot *slot;
903 
904 	slot = g_object_new (NEMO_TYPE_WINDOW_SLOT, NULL);
905 	slot->pane = pane;
906 
907 	return slot;
908 }
909