nautilus-3.6.3/src/nautilus-window-slot.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
  2 
  3    nautilus-window-slot.c: Nautilus 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., 59 Temple Place - Suite 330,
 20    Boston, MA 02111-1307, USA.
 21   
 22    Author: Christian Neumair <cneumair@gnome.org>
 23 */
 24 
 25 #include "config.h"
 26 
 27 #include "nautilus-window-slot.h"
 28 
 29 #include "nautilus-actions.h"
 30 #include "nautilus-toolbar.h"
 31 #include "nautilus-floating-bar.h"
 32 #include "nautilus-window-private.h"
 33 #include "nautilus-window-manage-views.h"
 34 #include "nautilus-desktop-window.h"
 35 
 36 #include <glib/gi18n.h>
 37 
 38 #include <libnautilus-private/nautilus-file.h>
 39 #include <libnautilus-private/nautilus-file-utilities.h>
 40 #include <libnautilus-private/nautilus-global-preferences.h>
 41 
 42 #include <eel/eel-string.h>
 43 
 44 G_DEFINE_TYPE (NautilusWindowSlot, nautilus_window_slot, GTK_TYPE_BOX);
 45 
 46 enum {
 47 	ACTIVE,
 48 	INACTIVE,
 49 	LOCATION_CHANGED,
 50 	LAST_SIGNAL
 51 };
 52 
 53 enum {
 54 	PROP_WINDOW = 1,
 55 	NUM_PROPERTIES
 56 };
 57 
 58 struct NautilusWindowSlotDetails {
 59 	NautilusWindow *window;
 60 
 61 	/* floating bar */
 62 	guint set_status_timeout_id;
 63 	guint loading_timeout_id;
 64 	GtkWidget *floating_bar;
 65 	GtkWidget *view_overlay;
 66 };
 67 
 68 static guint signals[LAST_SIGNAL] = { 0 };
 69 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
 70 
 71 gboolean
 72 nautilus_window_slot_handle_event (NautilusWindowSlot *slot,
 73 				   GdkEventKey        *event)
 74 {
 75 	NautilusWindow *window;
 76 
 77 	window = nautilus_window_slot_get_window (slot);
 78 	if (NAUTILUS_IS_DESKTOP_WINDOW (window))
 79 		return FALSE;
 80 	return nautilus_query_editor_handle_event (slot->query_editor, event);
 81 }
 82 
 83 static void
 84 sync_search_directory (NautilusWindowSlot *slot)
 85 {
 86 	NautilusDirectory *directory;
 87 	NautilusQuery *query;
 88 	gchar *text;
 89 	GFile *location;
 90 
 91 	g_assert (NAUTILUS_IS_FILE (slot->viewed_file));
 92 
 93 	directory = nautilus_directory_get_for_file (slot->viewed_file);
 94 	g_assert (NAUTILUS_IS_SEARCH_DIRECTORY (directory));
 95 
 96 	query = nautilus_query_editor_get_query (slot->query_editor);
 97 	text = nautilus_query_get_text (query);
 98 
 99 	if (!strlen (text)) {
100 		/* Prevent the location change from hiding the query editor in this case */
101 		slot->load_with_search = TRUE;
102 		location = nautilus_query_editor_get_location (slot->query_editor);
103 		nautilus_window_slot_open_location (slot, location, 0);
104 		g_object_unref (location);
105 	} else {
106 		nautilus_search_directory_set_query (NAUTILUS_SEARCH_DIRECTORY (directory),
107 						     query);
108 		nautilus_window_slot_force_reload (slot);
109 	}
110 
111 	g_free (text);
112 	g_object_unref (query);
113 	nautilus_directory_unref (directory);
114 }
115 
116 static void
117 create_new_search (NautilusWindowSlot *slot)
118 {
119 	char *uri;
120 	NautilusDirectory *directory;
121 	GFile *location;
122 	NautilusQuery *query;
123 
124 	uri = nautilus_search_directory_generate_new_uri ();
125 	location = g_file_new_for_uri (uri);
126 
127 	directory = nautilus_directory_get (location);
128 	g_assert (NAUTILUS_IS_SEARCH_DIRECTORY (directory));
129 
130 	query = nautilus_query_editor_get_query (slot->query_editor);
131 	nautilus_search_directory_set_query (NAUTILUS_SEARCH_DIRECTORY (directory), query);
132 
133 	nautilus_window_slot_open_location (slot, location, 0);
134 
135 	nautilus_directory_unref (directory);
136 	g_object_unref (query);
137 	g_object_unref (location);
138 	g_free (uri);
139 }
140 
141 static void
142 query_editor_cancel_callback (NautilusQueryEditor *editor,
143 			      NautilusWindowSlot *slot)
144 {
145 	nautilus_window_slot_set_search_visible (slot, FALSE);
146 }
147 
148 static void
149 query_editor_activated_callback (NautilusQueryEditor *editor,
150 				 NautilusWindowSlot *slot)
151 {
152 	if (slot->content_view != NULL) {
153 		nautilus_view_activate_selection (slot->content_view);
154 	}
155 }
156 
157 static void
158 query_editor_changed_callback (NautilusQueryEditor *editor,
159 			       NautilusQuery *query,
160 			       gboolean reload,
161 			       NautilusWindowSlot *slot)
162 {
163 	NautilusDirectory *directory;
164 
165 	g_assert (NAUTILUS_IS_FILE (slot->viewed_file));
166 
167 	directory = nautilus_directory_get_for_file (slot->viewed_file);
168 	if (!NAUTILUS_IS_SEARCH_DIRECTORY (directory)) {
169 		/* this is the first change from the query editor. we
170 		   ask for a location change to the search directory,
171 		   indicate the directory needs to be sync'd with the
172 		   current query. */
173 		create_new_search (slot);
174 	} else {
175 		sync_search_directory (slot);
176 	}
177 
178 	nautilus_directory_unref (directory);
179 }
180 
181 static void
182 hide_query_editor (NautilusWindowSlot *slot)
183 {
184 	gtk_widget_hide (GTK_WIDGET (slot->query_editor));
185 
186 	if (slot->qe_changed_id > 0) {
187 		g_signal_handler_disconnect (slot->query_editor, slot->qe_changed_id);
188 		slot->qe_changed_id = 0;
189 	}
190 	if (slot->qe_cancel_id > 0) {
191 		g_signal_handler_disconnect (slot->query_editor, slot->qe_cancel_id);
192 		slot->qe_cancel_id = 0;
193 	}
194 	if (slot->qe_activated_id > 0) {
195 		g_signal_handler_disconnect (slot->query_editor, slot->qe_activated_id);
196 		slot->qe_activated_id = 0;
197 	}
198 
199 	nautilus_query_editor_set_query (slot->query_editor, NULL);
200 }
201 
202 static void
203 show_query_editor (NautilusWindowSlot *slot)
204 {
205 	NautilusDirectory *directory;
206 	NautilusSearchDirectory *search_directory;
207 	GFile *location;
208 
209 	if (slot->location) {
210 		location = slot->location;
211 	} else {
212 		location = slot->pending_location;
213 	}
214 
215 	directory = nautilus_directory_get (location);
216 
217 	if (NAUTILUS_IS_SEARCH_DIRECTORY (directory)) {
218 		NautilusQuery *query;
219 		search_directory = NAUTILUS_SEARCH_DIRECTORY (directory);
220 		query = nautilus_search_directory_get_query (search_directory);
221 		if (query != NULL) {
222 			nautilus_query_editor_set_query (slot->query_editor,
223 							 query);
224 			g_object_unref (query);
225 		}
226 	} else {
227 		nautilus_query_editor_set_location (slot->query_editor, location);
228 	}
229 
230 	nautilus_directory_unref (directory);
231 
232 	gtk_widget_show (GTK_WIDGET (slot->query_editor));
233 	gtk_widget_grab_focus (GTK_WIDGET (slot->query_editor));
234 
235 	if (slot->qe_changed_id == 0) {
236 		slot->qe_changed_id = g_signal_connect (slot->query_editor, "changed",
237 							G_CALLBACK (query_editor_changed_callback), slot);
238 	}
239 	if (slot->qe_cancel_id == 0) {
240 		slot->qe_cancel_id = g_signal_connect (slot->query_editor, "cancel",
241 						       G_CALLBACK (query_editor_cancel_callback), slot);
242 	}
243 	if (slot->qe_activated_id == 0) {
244 		slot->qe_activated_id = g_signal_connect (slot->query_editor, "activated",
245 							  G_CALLBACK (query_editor_activated_callback), slot);
246 	}
247 }
248 
249 void
250 nautilus_window_slot_set_search_visible (NautilusWindowSlot *slot,
251 					 gboolean            visible)
252 {
253 	gboolean old_visible;
254 	GFile *return_location;
255 	GtkAction *action;
256 	gboolean active_slot;
257 
258 	old_visible = slot->search_visible;
259 	slot->search_visible = visible;
260 
261 	return_location = NULL;
262 	active_slot = (slot == nautilus_window_get_active_slot (slot->details->window));
263 
264 	if (visible) {
265 		show_query_editor (slot);
266 	} else {
267 		if (old_visible && active_slot && slot->query_editor != NULL) {
268 			/* Use the location bar as the return location */
269 			return_location = nautilus_query_editor_get_location (slot->query_editor);
270 
271 			/* Last try: use the home directory as the return location */
272 			if (return_location == NULL) {
273 				return_location = g_file_new_for_path (g_get_home_dir ());
274 			}
275 		}
276 
277 		if (active_slot) {
278 			nautilus_window_grab_focus (slot->details->window);
279 		}
280 
281 		hide_query_editor (slot);
282 	}
283 
284 	if (!active_slot) {
285 		return;
286 	}
287 
288 	action = gtk_action_group_get_action (nautilus_window_get_main_action_group (slot->details->window),
289 					      NAUTILUS_ACTION_SEARCH);
290 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
291 
292 	if (return_location != NULL) {
293 		nautilus_window_go_to (slot->details->window, return_location);
294 		g_object_unref (return_location);
295 	}
296 }
297 
298 static void
299 real_active (NautilusWindowSlot *slot)
300 {
301 	NautilusWindow *window;
302 	int page_num;
303 
304 	window = slot->details->window;
305 	page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->details->notebook),
306 					  GTK_WIDGET (slot));
307 	g_assert (page_num >= 0);
308 
309 	gtk_notebook_set_current_page (GTK_NOTEBOOK (window->details->notebook), page_num);
310 
311 	/* sync window to new slot */
312 	nautilus_window_sync_allow_stop (window, slot);
313 	nautilus_window_sync_title (window, slot);
314 	nautilus_window_sync_zoom_widgets (window);
315 	nautilus_window_sync_location_widgets (window);
316 	nautilus_window_sync_search_widgets (window);
317 
318 	if (slot->viewed_file != NULL) {
319 		nautilus_window_sync_view_as_menus (window);
320 		nautilus_window_load_extension_menus (window);
321 	}
322 }
323 
324 static void
325 real_inactive (NautilusWindowSlot *slot)
326 {
327 	NautilusWindow *window;
328 
329 	window = nautilus_window_slot_get_window (slot);
330 	g_assert (slot == nautilus_window_get_active_slot (window));
331 }
332 
333 static void
334 floating_bar_action_cb (NautilusFloatingBar *floating_bar,
335 			gint action,
336 			NautilusWindowSlot *slot)
337 {
338 	if (action == NAUTILUS_FLOATING_BAR_ACTION_ID_STOP) {
339 		nautilus_window_slot_stop_loading (slot);
340 	}
341 }
342 
343 static void
344 nautilus_window_slot_set_property (GObject *object,
345 				   guint property_id,
346 				   const GValue *value,
347 				   GParamSpec *pspec)
348 {
349 	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (object);
350 
351 	switch (property_id) {
352 	case PROP_WINDOW:
353 		nautilus_window_slot_set_window (slot, g_value_get_object (value));
354 		break;
355 	default:
356 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
357 		break;
358 	}
359 }
360 
361 static void
362 nautilus_window_slot_get_property (GObject *object,
363 				   guint property_id,
364 				   GValue *value,
365 				   GParamSpec *pspec)
366 {
367 	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (object);
368 
369 	switch (property_id) {
370 	case PROP_WINDOW:
371 		g_value_set_object (value, slot->details->window);
372 		break;
373 	default:
374 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
375 		break;
376 	}
377 }
378 
379 static void
380 nautilus_window_slot_constructed (GObject *object)
381 {
382 	NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (object);
383 	GtkWidget *extras_vbox;
384 
385 	G_OBJECT_CLASS (nautilus_window_slot_parent_class)->constructed (object);
386 
387 	gtk_orientable_set_orientation (GTK_ORIENTABLE (slot),
388 					GTK_ORIENTATION_VERTICAL);
389 	gtk_widget_show (GTK_WIDGET (slot));
390 
391 	extras_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
392 	slot->extra_location_widgets = extras_vbox;
393 	gtk_box_pack_start (GTK_BOX (slot), extras_vbox, FALSE, FALSE, 0);
394 	gtk_widget_show (extras_vbox);
395 
396 	slot->query_editor = NAUTILUS_QUERY_EDITOR (nautilus_query_editor_new ());
397 	nautilus_window_slot_add_extra_location_widget (slot, GTK_WIDGET (slot->query_editor));
398 	g_object_add_weak_pointer (G_OBJECT (slot->query_editor),
399 				   (gpointer *) &slot->query_editor);
400 
401 	slot->details->view_overlay = gtk_overlay_new ();
402 	gtk_widget_add_events (slot->details->view_overlay,
403 			       GDK_ENTER_NOTIFY_MASK |
404 			       GDK_LEAVE_NOTIFY_MASK);
405 	gtk_box_pack_start (GTK_BOX (slot), slot->details->view_overlay, TRUE, TRUE, 0);
406 	gtk_widget_show (slot->details->view_overlay);
407 
408 	slot->details->floating_bar = nautilus_floating_bar_new (NULL, NULL, FALSE);
409 	gtk_widget_set_halign (slot->details->floating_bar, GTK_ALIGN_END);
410 	gtk_widget_set_valign (slot->details->floating_bar, GTK_ALIGN_END);
411 	gtk_overlay_add_overlay (GTK_OVERLAY (slot->details->view_overlay),
412 				 slot->details->floating_bar);
413 
414 	g_signal_connect (slot->details->floating_bar, "action",
415 			  G_CALLBACK (floating_bar_action_cb), slot);
416 
417 	slot->title = g_strdup (_("Loading..."));
418 }
419 
420 static void
421 nautilus_window_slot_init (NautilusWindowSlot *slot)
422 {
423 	slot->details = G_TYPE_INSTANCE_GET_PRIVATE
424 		(slot, NAUTILUS_TYPE_WINDOW_SLOT, NautilusWindowSlotDetails);
425 }
426 
427 static void
428 remove_loading_floating_bar (NautilusWindowSlot *slot)
429 {
430 	if (slot->details->loading_timeout_id != 0) {
431 		g_source_remove (slot->details->loading_timeout_id);
432 		slot->details->loading_timeout_id = 0;
433 	}
434 
435 	gtk_widget_hide (slot->details->floating_bar);
436 	nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (slot->details->floating_bar));
437 }
438 
439 static void
440 view_end_loading_cb (NautilusView       *view,
441 		     gboolean            all_files_seen,
442 		     NautilusWindowSlot *slot)
443 {
444 	if (slot->needs_reload) {
445 		nautilus_window_slot_queue_reload (slot);
446 		slot->needs_reload = FALSE;
447 	}
448 
449 	remove_loading_floating_bar (slot);
450 }
451 
452 
453 static void
454 real_setup_loading_floating_bar (NautilusWindowSlot *slot)
455 {
456 	gboolean disable_chrome;
457 
458 	g_object_get (nautilus_window_slot_get_window (slot),
459 		      "disable-chrome", &disable_chrome,
460 		      NULL);
461 
462 	if (disable_chrome) {
463 		gtk_widget_hide (slot->details->floating_bar);
464 		return;
465 	}
466 
467 	nautilus_floating_bar_set_primary_label (NAUTILUS_FLOATING_BAR (slot->details->floating_bar),
468 						 NAUTILUS_IS_SEARCH_DIRECTORY (nautilus_view_get_model (slot->content_view)) ?
469 						 _("Searching...") : _("Loading..."));
470 	nautilus_floating_bar_set_details_label (NAUTILUS_FLOATING_BAR (slot->details->floating_bar), NULL);
471 	nautilus_floating_bar_set_show_spinner (NAUTILUS_FLOATING_BAR (slot->details->floating_bar),
472 						TRUE);
473 	nautilus_floating_bar_add_action (NAUTILUS_FLOATING_BAR (slot->details->floating_bar),
474 					  GTK_STOCK_STOP,
475 					  NAUTILUS_FLOATING_BAR_ACTION_ID_STOP);
476 
477 	gtk_widget_set_halign (slot->details->floating_bar, GTK_ALIGN_END);
478 	gtk_widget_show (slot->details->floating_bar);
479 }
480 
481 static gboolean
482 setup_loading_floating_bar_timeout_cb (gpointer user_data)
483 {
484 	NautilusWindowSlot *slot = user_data;
485 
486 	slot->details->loading_timeout_id = 0;
487 	real_setup_loading_floating_bar (slot);
488 
489 	return FALSE;
490 }
491 
492 static void
493 setup_loading_floating_bar (NautilusWindowSlot *slot)
494 {
495 	/* setup loading overlay */
496 	if (slot->details->set_status_timeout_id != 0) {
497 		g_source_remove (slot->details->set_status_timeout_id);
498 		slot->details->set_status_timeout_id = 0;
499 	}
500 
501 	if (slot->details->loading_timeout_id != 0) {
502 		g_source_remove (slot->details->loading_timeout_id);
503 		slot->details->loading_timeout_id = 0;
504 	}
505 
506 	slot->details->loading_timeout_id =
507 		g_timeout_add (500, setup_loading_floating_bar_timeout_cb, slot);
508 }
509 
510 static void
511 view_begin_loading_cb (NautilusView       *view,
512 		       NautilusWindowSlot *slot)
513 {
514 	setup_loading_floating_bar (slot);
515 }
516 
517 static void
518 nautilus_window_slot_dispose (GObject *object)
519 {
520 	NautilusWindowSlot *slot;
521 	GtkWidget *widget;
522 
523 	slot = NAUTILUS_WINDOW_SLOT (object);
524 
525 	nautilus_window_slot_clear_forward_list (slot);
526 	nautilus_window_slot_clear_back_list (slot);
527 
528 	if (slot->content_view) {
529 		widget = GTK_WIDGET (slot->content_view);
530 		gtk_widget_destroy (widget);
531 		g_object_unref (slot->content_view);
532 		slot->content_view = NULL;
533 	}
534 
535 	if (slot->new_content_view) {
536 		widget = GTK_WIDGET (slot->new_content_view);
537 		gtk_widget_destroy (widget);
538 		g_object_unref (slot->new_content_view);
539 		slot->new_content_view = NULL;
540 	}
541 
542 	if (slot->details->set_status_timeout_id != 0) {
543 		g_source_remove (slot->details->set_status_timeout_id);
544 		slot->details->set_status_timeout_id = 0;
545 	}
546 
547 	if (slot->details->loading_timeout_id != 0) {
548 		g_source_remove (slot->details->loading_timeout_id);
549 		slot->details->loading_timeout_id = 0;
550 	}
551 
552 	nautilus_window_slot_set_viewed_file (slot, NULL);
553 	/* TODO? why do we unref here? the file is NULL.
554 	 * It was already here before the slot move, though */
555 	nautilus_file_unref (slot->viewed_file);
556 
557 	if (slot->location) {
558 		/* TODO? why do we ref here, instead of unreffing?
559 		 * It was already here before the slot migration, though */
560 		g_object_ref (slot->location);
561 	}
562 
563 	g_list_free_full (slot->pending_selection, g_object_unref);
564 	slot->pending_selection = NULL;
565 
566 	g_clear_object (&slot->current_location_bookmark);
567 	g_clear_object (&slot->last_location_bookmark);
568 
569 	if (slot->find_mount_cancellable != NULL) {
570 		g_cancellable_cancel (slot->find_mount_cancellable);
571 		slot->find_mount_cancellable = NULL;
572 	}
573 
574 	slot->details->window = NULL;
575 
576 	g_free (slot->title);
577 	slot->title = NULL;
578 
579 	G_OBJECT_CLASS (nautilus_window_slot_parent_class)->dispose (object);
580 }
581 
582 static void
583 nautilus_window_slot_class_init (NautilusWindowSlotClass *klass)
584 {
585 	GObjectClass *oclass = G_OBJECT_CLASS (klass);
586 
587 	klass->active = real_active;
588 	klass->inactive = real_inactive;
589 
590 	oclass->dispose = nautilus_window_slot_dispose;
591 	oclass->constructed = nautilus_window_slot_constructed;
592 	oclass->set_property = nautilus_window_slot_set_property;
593 	oclass->get_property = nautilus_window_slot_get_property;
594 
595 	signals[ACTIVE] =
596 		g_signal_new ("active",
597 			      G_TYPE_FROM_CLASS (klass),
598 			      G_SIGNAL_RUN_LAST,
599 			      G_STRUCT_OFFSET (NautilusWindowSlotClass, active),
600 			      NULL, NULL,
601 			      g_cclosure_marshal_VOID__VOID,
602 			      G_TYPE_NONE, 0);
603 
604 	signals[INACTIVE] =
605 		g_signal_new ("inactive",
606 			      G_TYPE_FROM_CLASS (klass),
607 			      G_SIGNAL_RUN_LAST,
608 			      G_STRUCT_OFFSET (NautilusWindowSlotClass, inactive),
609 			      NULL, NULL,
610 			      g_cclosure_marshal_VOID__VOID,
611 			      G_TYPE_NONE, 0);
612 	signals[LOCATION_CHANGED] =
613 		g_signal_new ("location-changed",
614 			      G_TYPE_FROM_CLASS (klass),
615 			      G_SIGNAL_RUN_LAST,
616 			      0,
617 			      NULL, NULL,
618 			      g_cclosure_marshal_generic,
619 			      G_TYPE_NONE, 2,
620 			      G_TYPE_STRING,
621 			      G_TYPE_STRING);
622 
623 	properties[PROP_WINDOW] =
624 		g_param_spec_object ("window",
625 				     "The NautilusWindow",
626 				     "The NautilusWindow this slot is part of",
627 				     NAUTILUS_TYPE_WINDOW,
628 				     G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
629 
630 	g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
631 	g_type_class_add_private (klass, sizeof (NautilusWindowSlotDetails));
632 }
633 
634 GFile *
635 nautilus_window_slot_get_location (NautilusWindowSlot *slot)
636 {
637 	g_assert (slot != NULL);
638 
639 	if (slot->location != NULL) {
640 		return g_object_ref (slot->location);
641 	}
642 	return NULL;
643 }
644 
645 char *
646 nautilus_window_slot_get_location_uri (NautilusWindowSlot *slot)
647 {
648 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
649 
650 	if (slot->location) {
651 		return g_file_get_uri (slot->location);
652 	}
653 	return NULL;
654 }
655 
656 NautilusWindow *
657 nautilus_window_slot_get_window (NautilusWindowSlot *slot)
658 {
659 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
660 	return slot->details->window;
661 }
662 
663 void
664 nautilus_window_slot_set_window (NautilusWindowSlot *slot,
665 				 NautilusWindow *window)
666 {
667 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
668 	g_assert (NAUTILUS_IS_WINDOW (window));
669 
670 	if (slot->details->window != window) {
671 		slot->details->window = window;
672 		g_object_notify_by_pspec (G_OBJECT (slot), properties[PROP_WINDOW]);
673 	}
674 }
675 
676 /* nautilus_window_slot_update_title:
677  * 
678  * Re-calculate the slot title.
679  * Called when the location or view has changed.
680  * @slot: The NautilusWindowSlot in question.
681  * 
682  */
683 void
684 nautilus_window_slot_update_title (NautilusWindowSlot *slot)
685 {
686 	NautilusWindow *window;
687 	char *title;
688 	gboolean do_sync = FALSE;
689 
690 	title = nautilus_compute_title_for_location (slot->location);
691 	window = nautilus_window_slot_get_window (slot);
692 
693 	if (g_strcmp0 (title, slot->title) != 0) {
694 		do_sync = TRUE;
695 
696 		g_free (slot->title);
697 		slot->title = title;
698 		title = NULL;
699 	}
700 
701 	if (strlen (slot->title) > 0 &&
702 	    slot->current_location_bookmark != NULL) {
703 		do_sync = TRUE;
704 	}
705 
706 	if (do_sync) {
707 		nautilus_window_sync_title (window, slot);
708 	}
709 
710 	if (title != NULL) {
711 		g_free (title);
712 	}
713 }
714 
715 void
716 nautilus_window_slot_set_content_view_widget (NautilusWindowSlot *slot,
717 					      NautilusView *new_view)
718 {
719 	NautilusWindow *window;
720 	GtkWidget *widget;
721 
722 	window = nautilus_window_slot_get_window (slot);
723 
724 	if (slot->content_view != NULL) {
725 		/* disconnect old view */
726 		g_signal_handlers_disconnect_by_func (slot->content_view, G_CALLBACK (view_end_loading_cb), slot);
727 		g_signal_handlers_disconnect_by_func (slot->content_view, G_CALLBACK (view_begin_loading_cb), slot);
728 
729 		nautilus_window_disconnect_content_view (window, slot->content_view);
730 
731 		widget = GTK_WIDGET (slot->content_view);
732 		gtk_widget_destroy (widget);
733 		g_object_unref (slot->content_view);
734 		slot->content_view = NULL;
735 	}
736 
737 	if (new_view != NULL) {
738 		widget = GTK_WIDGET (new_view);
739 		gtk_container_add (GTK_CONTAINER (slot->details->view_overlay), widget);
740 		gtk_widget_show (widget);
741 
742 		slot->content_view = new_view;
743 		g_object_ref (slot->content_view);
744 
745 		g_signal_connect (new_view, "begin_loading", G_CALLBACK (view_begin_loading_cb), slot);
746 		g_signal_connect (new_view, "end_loading", G_CALLBACK (view_end_loading_cb), slot);
747 
748 		/* connect new view */
749 		nautilus_window_connect_content_view (window, new_view);
750 	}
751 }
752 
753 void
754 nautilus_window_slot_set_allow_stop (NautilusWindowSlot *slot,
755 				     gboolean allow)
756 {
757 	NautilusWindow *window;
758 
759 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
760 
761 	slot->allow_stop = allow;
762 
763 	window = nautilus_window_slot_get_window (slot);
764 	nautilus_window_sync_allow_stop (window, slot);
765 }
766 
767 static void
768 real_slot_set_short_status (NautilusWindowSlot *slot,
769 			    const gchar *primary_status,
770 			    const gchar *detail_status)
771 {
772 	gboolean disable_chrome;
773 
774 	nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (slot->details->floating_bar));
775 	nautilus_floating_bar_set_show_spinner (NAUTILUS_FLOATING_BAR (slot->details->floating_bar),
776 						FALSE);
777 
778 	g_object_get (nautilus_window_slot_get_window (slot),
779 		      "disable-chrome", &disable_chrome,
780 		      NULL);
781 
782 	if ((primary_status == NULL && detail_status == NULL) || disable_chrome) {
783 		gtk_widget_hide (slot->details->floating_bar);
784 		return;
785 	}
786 
787 	nautilus_floating_bar_set_labels (NAUTILUS_FLOATING_BAR (slot->details->floating_bar),
788 					  primary_status, detail_status);
789 	gtk_widget_show (slot->details->floating_bar);
790 }
791 
792 typedef struct {
793 	gchar *primary_status;
794 	gchar *detail_status;
795 	NautilusWindowSlot *slot;
796 } SetStatusData;
797 
798 static void
799 set_status_data_free (gpointer data)
800 {
801 	SetStatusData *status_data = data;
802 
803 	g_free (status_data->primary_status);
804 	g_free (status_data->detail_status);
805 
806 	g_slice_free (SetStatusData, data);
807 }
808 
809 static gboolean
810 set_status_timeout_cb (gpointer data)
811 {
812 	SetStatusData *status_data = data;
813 
814 	status_data->slot->details->set_status_timeout_id = 0;
815 	real_slot_set_short_status (status_data->slot,
816 				    status_data->primary_status,
817 				    status_data->detail_status);
818 
819 	return FALSE;
820 }
821 
822 static void
823 set_floating_bar_status (NautilusWindowSlot *slot,
824 			 const gchar *primary_status,
825 			 const gchar *detail_status)
826 {
827 	GtkSettings *settings;
828 	gint double_click_time;
829 	SetStatusData *status_data;
830 
831 	if (slot->details->set_status_timeout_id != 0) {
832 		g_source_remove (slot->details->set_status_timeout_id);
833 		slot->details->set_status_timeout_id = 0;
834 	}
835 
836 	settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (slot->content_view)));
837 	g_object_get (settings,
838 		      "gtk-double-click-time", &double_click_time,
839 		      NULL);
840 
841 	status_data = g_slice_new0 (SetStatusData);
842 	status_data->primary_status = g_strdup (primary_status);
843 	status_data->detail_status = g_strdup (detail_status);
844 	status_data->slot = slot;
845 
846 	/* waiting for half of the double-click-time before setting
847 	 * the status seems to be a good approximation of not setting it
848 	 * too often and not delaying the statusbar too much.
849 	 */
850 	slot->details->set_status_timeout_id =
851 		g_timeout_add_full (G_PRIORITY_DEFAULT,
852 				    (guint) (double_click_time / 2),
853 				    set_status_timeout_cb,
854 				    status_data,
855 				    set_status_data_free);
856 }
857 
858 void
859 nautilus_window_slot_set_status (NautilusWindowSlot *slot,
860 				 const char *primary_status,
861 				 const char *detail_status)
862 {
863 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
864 
865 	if (slot->content_view != NULL) {
866 		set_floating_bar_status (slot, primary_status, detail_status);
867 	}
868 }
869 
870 static void
871 remove_all_extra_location_widgets (GtkWidget *widget,
872 				   gpointer data)
873 {
874 	NautilusWindowSlot *slot = data;
875 	NautilusDirectory *directory;
876 
877 	directory = nautilus_directory_get (slot->location);
878 	if (widget != GTK_WIDGET (slot->query_editor)) {
879 		gtk_container_remove (GTK_CONTAINER (slot->extra_location_widgets), widget);
880 	}
881 
882 	nautilus_directory_unref (directory);
883 }
884 
885 void
886 nautilus_window_slot_remove_extra_location_widgets (NautilusWindowSlot *slot)
887 {
888 	gtk_container_foreach (GTK_CONTAINER (slot->extra_location_widgets),
889 			       remove_all_extra_location_widgets,
890 			       slot);
891 }
892 
893 void
894 nautilus_window_slot_add_extra_location_widget (NautilusWindowSlot *slot,
895 						GtkWidget *widget)
896 {
897 	gtk_box_pack_start (GTK_BOX (slot->extra_location_widgets),
898 			    widget, TRUE, TRUE, 0);
899 	gtk_widget_show (slot->extra_location_widgets);
900 }
901 
902 /* returns either the pending or the actual current uri */
903 char *
904 nautilus_window_slot_get_current_uri (NautilusWindowSlot *slot)
905 {
906 	if (slot->pending_location != NULL) {
907 		return g_file_get_uri (slot->pending_location);
908 	}
909 
910 	if (slot->location != NULL) {
911 		return g_file_get_uri (slot->location);
912 	}
913 
914 	return NULL;
915 }
916 
917 NautilusView *
918 nautilus_window_slot_get_current_view (NautilusWindowSlot *slot)
919 {
920 	if (slot->content_view != NULL) {
921 		return slot->content_view;
922 	} else if (slot->new_content_view) {
923 		return slot->new_content_view;
924 	}
925 
926 	return NULL;
927 }
928 
929 void
930 nautilus_window_slot_go_home (NautilusWindowSlot *slot,
931 			      NautilusWindowOpenFlags flags)
932 {			      
933 	GFile *home;
934 
935 	g_return_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot));
936 
937 	home = g_file_new_for_path (g_get_home_dir ());
938 	nautilus_window_slot_open_location (slot, home, flags);
939 	g_object_unref (home);
940 }
941 
942 void
943 nautilus_window_slot_go_up (NautilusWindowSlot *slot,
944 			    NautilusWindowOpenFlags flags)
945 {
946 	GFile *parent;
947 
948 	if (slot->location == NULL) {
949 		return;
950 	}
951 
952 	parent = g_file_get_parent (slot->location);
953 	if (parent == NULL) {
954 		return;
955 	}
956 
957 	nautilus_window_slot_open_location (slot, parent, flags);
958 	g_object_unref (parent);
959 }
960 
961 void
962 nautilus_window_slot_clear_forward_list (NautilusWindowSlot *slot)
963 {
964 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
965 
966 	g_list_free_full (slot->forward_list, g_object_unref);
967 	slot->forward_list = NULL;
968 }
969 
970 void
971 nautilus_window_slot_clear_back_list (NautilusWindowSlot *slot)
972 {
973 	g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
974 
975 	g_list_free_full (slot->back_list, g_object_unref);
976 	slot->back_list = NULL;
977 }
978 
979 NautilusWindowSlot *
980 nautilus_window_slot_new (NautilusWindow *window)
981 {
982 	return g_object_new (NAUTILUS_TYPE_WINDOW_SLOT,
983 			     "window", window,
984 			     NULL);
985 }