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 }