source: trunk/third/nautilus/src/nautilus-window.c @ 18663

Revision 18663, 62.1 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18662, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3/*
4 *  Nautilus
5 *
6 *  Copyright (C) 1999, 2000 Red Hat, Inc.
7 *  Copyright (C) 1999, 2000, 2001 Eazel, Inc.
8 *
9 *  Nautilus is free software; you can redistribute it and/or
10 *  modify it under the terms of the GNU General Public
11 *  License as published by the Free Software Foundation; either
12 *  version 2 of the License, or (at your option) any later version.
13 *
14 *  Nautilus is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 *  General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public
20 *  License along with this program; if not, write to the Free
21 *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  Authors: Elliot Lee <sopwith@redhat.com>
24 *           John Sullivan <sullivan@eazel.com>
25 *
26 */
27
28/* nautilus-window.c: Implementation of the main window object */
29
30#include <config.h>
31#include "nautilus-window-private.h"
32
33#include "nautilus-application.h"
34#include "nautilus-bookmarks-window.h"
35#include "nautilus-information-panel.h"
36#include "nautilus-main.h"
37#include "nautilus-signaller.h"
38#include "nautilus-switchable-navigation-bar.h"
39#include "nautilus-window-manage-views.h"
40#include "nautilus-zoom-control.h"
41#include <bonobo/bonobo-exception.h>
42#include <bonobo/bonobo-property-bag-client.h>
43#include <bonobo/bonobo-ui-util.h>
44#include <eel/eel-debug.h>
45#include <eel/eel-gdk-extensions.h>
46#include <eel/eel-gdk-pixbuf-extensions.h>
47#include <eel/eel-generous-bin.h>
48#include <eel/eel-gtk-extensions.h>
49#include <eel/eel-gtk-macros.h>
50#include <eel/eel-string.h>
51#include <gdk-pixbuf/gdk-pixbuf.h>
52#include <gdk/gdkx.h>
53#include <gtk/gtkmain.h>
54#include <gtk/gtkmenubar.h>
55#include <gtk/gtkmenuitem.h>
56#include <gtk/gtkoptionmenu.h>
57#include <gtk/gtktogglebutton.h>
58#include <gtk/gtkvbox.h>
59#include <libgnome/gnome-i18n.h>
60#include <libgnome/gnome-macros.h>
61#include <libgnome/gnome-util.h>
62#include <libgnomeui/gnome-messagebox.h>
63#include <libgnomeui/gnome-uidefs.h>
64#include <libgnomeui/gnome-window-icon.h>
65#include <libgnomevfs/gnome-vfs-uri.h>
66#include <libgnomevfs/gnome-vfs-utils.h>
67#include <libnautilus-private/nautilus-bonobo-extensions.h>
68#include <libnautilus-private/nautilus-drag-window.h>
69#include <libnautilus-private/nautilus-file-utilities.h>
70#include <libnautilus-private/nautilus-file-attributes.h>
71#include <libnautilus-private/nautilus-global-preferences.h>
72#include <libnautilus-private/nautilus-horizontal-splitter.h>
73#include <libnautilus-private/nautilus-icon-factory.h>
74#include <libnautilus-private/nautilus-metadata.h>
75#include <libnautilus-private/nautilus-mime-actions.h>
76#include <libnautilus-private/nautilus-program-choosing.h>
77#include <libnautilus-private/nautilus-sidebar-functions.h>
78#include <libnautilus/nautilus-bonobo-ui.h>
79#include <libnautilus/nautilus-clipboard.h>
80#include <libnautilus/nautilus-undo.h>
81#include <math.h>
82#include <sys/time.h>
83
84/* FIXME bugzilla.gnome.org 41243:
85 * We should use inheritance instead of these special cases
86 * for the desktop window.
87 */
88#include "nautilus-desktop-window.h"
89
90#define MAX_HISTORY_ITEMS 50
91
92/* FIXME bugzilla.gnome.org 41245: hardwired sizes */
93#define SIDE_PANE_MINIMUM_WIDTH 1
94#define SIDE_PANE_MINIMUM_HEIGHT 400
95
96/* dock items */
97#define LOCATION_BAR_PATH       "/Location Bar"
98#define TOOLBAR_PATH            "/Toolbar"
99#define STATUS_BAR_PATH         "/status"
100#define MENU_BAR_PATH           "/menu"
101
102#define COMMAND_PREFIX                          "/commands/"
103#define NAUTILUS_COMMAND_TOGGLE_FIND_MODE       "/commands/Toggle Find Mode"
104#define NAUTILUS_COMMAND_VIEW_AS                "/commands/View as"
105
106#define NAUTILUS_MENU_PATH_EXTRA_VIEWER_PLACEHOLDER     "/menu/View/View Choices/Extra Viewer"
107#define NAUTILUS_MENU_PATH_BEFORE_SHORT_LIST_SEPARATOR  "/menu/View/View Choices/Before Short List"
108#define NAUTILUS_MENU_PATH_SHORT_LIST_PLACEHOLDER       "/menu/View/View Choices/Short List"
109#define NAUTILUS_MENU_PATH_AFTER_SHORT_LIST_SEPARATOR   "/menu/View/View Choices/After Short List"
110
111enum {
112        ARG_0,
113        ARG_APP_ID,
114        ARG_APP
115};
116
117static GList *history_list;
118static int side_pane_width_auto_value = SIDE_PANE_MINIMUM_WIDTH;
119
120static void add_sidebar_panels                  (NautilusWindow *window);
121static void cancel_view_as_callback             (NautilusWindow *window);
122
123GNOME_CLASS_BOILERPLATE (NautilusWindow, nautilus_window,
124                         BonoboWindow, BONOBO_TYPE_WINDOW)
125
126static void
127set_up_default_icon_list (void)
128{
129        GList *icon_list;
130        guint i;
131        GdkPixbuf *pixbuf;
132        char *path;
133        const char *icon_filenames[] = { "nautilus-mini-logo.png", "nautilus-launch-icon.png" };
134
135        icon_list = NULL;
136        for (i = 0; i < G_N_ELEMENTS (icon_filenames); i++) {
137                path = nautilus_pixmap_file (icon_filenames[i]);
138
139                if (path == NULL) {
140                        continue;
141                }
142               
143                pixbuf = gdk_pixbuf_new_from_file (path, NULL);
144                g_free (path);
145               
146                if (pixbuf != NULL) {
147                        icon_list = g_list_prepend (icon_list, pixbuf);
148                }
149        }
150
151        gtk_window_set_default_icon_list (icon_list);
152
153        eel_g_list_free_deep_custom (icon_list, (GFunc) g_object_unref, NULL);
154}
155
156static void
157icons_changed_callback (GObject *factory, NautilusWindow *window)
158{
159        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
160
161        nautilus_window_update_icon (window);
162}
163
164static void
165nautilus_window_instance_init (NautilusWindow *window)
166{
167        window->details = g_new0 (NautilusWindowDetails, 1);
168
169        /* CORBA and Bonobo setup, which must be done before the location bar setup */
170        window->details->ui_container = bonobo_window_get_ui_container (BONOBO_WINDOW (window));
171        bonobo_object_ref (window->details->ui_container);
172
173        window->details->tooltips = gtk_tooltips_new ();
174        g_object_ref (G_OBJECT (window->details->tooltips));
175        gtk_object_sink (GTK_OBJECT (window->details->tooltips));
176
177        /* Set last geometry to NULL */
178        window->last_geometry = NULL;
179
180        /* Set initial window title */
181        gtk_window_set_title (GTK_WINDOW (window), _("Nautilus"));
182
183        window->details->shell_ui = bonobo_ui_component_new ("Nautilus Shell");
184        bonobo_ui_component_set_container
185                (window->details->shell_ui,
186                 nautilus_window_get_ui_container (window),
187                 NULL);
188
189        /* Register IconFactory callback to update the window border icon
190         * when the icon-theme is changed.
191         */
192        g_signal_connect_object (nautilus_icon_factory_get (), "icons_changed",
193                                 G_CALLBACK (icons_changed_callback), window,
194                                 0);
195
196        /* Create a separate component so when we remove the status
197         * we don't loose the status bar
198         */
199        window->details->status_ui = bonobo_ui_component_new ("Status Component"); 
200        bonobo_ui_component_set_container
201                (window->details->status_ui,
202                 nautilus_window_get_ui_container (window),
203                 NULL);
204
205        gtk_quit_add_destroy (1, GTK_OBJECT (window));
206
207        /* Keep the main event loop alive as long as the window exists */
208        nautilus_main_event_loop_register (GTK_OBJECT (window));
209}
210
211static gint
212ui_idle_handler (gpointer data)
213{
214        NautilusWindow *window;
215        gboolean old_updating_bonobo_state;
216
217        window = data;
218
219        g_assert (NAUTILUS_IS_WINDOW (window));
220        g_object_ref (data);
221
222        g_assert (window->details->ui_change_depth == 0);
223
224        /* Simulate an extra freeze/thaw so that calling window_ui_freeze
225         * and thaw from within the idle handler doesn't try to remove it
226         * (the already running idle handler)
227         */
228        window->details->ui_change_depth++;
229        old_updating_bonobo_state = window->details->updating_bonobo_state;
230
231        if (window->details->ui_pending_initialize_menus_part_2) {
232                nautilus_window_initialize_menus_part_2 (window);
233                window->details->ui_pending_initialize_menus_part_2 = FALSE;
234        }
235
236        if (window->details->ui_is_frozen) {
237                window->details->updating_bonobo_state = TRUE;
238                bonobo_ui_engine_thaw (bonobo_ui_container_get_engine (window->details->ui_container));
239                window->details->ui_is_frozen = FALSE;
240                window->details->updating_bonobo_state = old_updating_bonobo_state;
241        }
242
243        window->details->ui_change_depth--;
244
245        window->details->ui_idle_id = 0;
246
247        g_object_unref (data);
248
249        return FALSE;
250}
251
252static inline void
253ui_install_idle_handler (NautilusWindow *window)
254{
255        if (window->details->ui_idle_id == 0) {
256                window->details->ui_idle_id = g_idle_add_full (G_PRIORITY_LOW, ui_idle_handler, window, NULL);
257        }
258}
259
260static inline void
261ui_remove_idle_handler (NautilusWindow *window)
262{
263        if (window->details->ui_idle_id != 0) {
264                g_source_remove (window->details->ui_idle_id);
265                window->details->ui_idle_id = 0;
266        }
267}
268
269/* Register that BonoboUI changes are going to be made to WINDOW. The UI
270 * won't actually be synchronised until some arbitrary date in the future.
271 */
272void
273nautilus_window_ui_freeze (NautilusWindow *window)
274{
275        if (window->details->ui_change_depth == 0) {
276                ui_remove_idle_handler (window);
277        }
278
279        if (!window->details->ui_is_frozen) {
280                bonobo_ui_engine_freeze (bonobo_ui_container_get_engine (window->details->ui_container));
281                window->details->ui_is_frozen = TRUE;
282        }
283
284        window->details->ui_change_depth++;
285}
286
287/* Register that the BonoboUI changes for WINDOW have finished. There _must_
288 * be one and only one call to this function for every call to
289 * starting_ui_change ()
290 */
291void
292nautilus_window_ui_thaw (NautilusWindow *window)
293{
294        window->details->ui_change_depth--;
295
296        g_assert (window->details->ui_change_depth >= 0);
297
298        if (window->details->ui_change_depth == 0
299            && (window->details->ui_is_frozen
300                || window->details->ui_pending_initialize_menus_part_2)) {
301                ui_install_idle_handler (window);
302        }
303}
304
305/* Unconditionally synchronize the BonoboUI of WINDOW. */
306static void
307nautilus_window_ui_update (NautilusWindow *window)
308{
309        BonoboUIEngine *engine;
310        gboolean old_updating_bonobo_state;
311
312        engine = bonobo_ui_container_get_engine (window->details->ui_container);
313        old_updating_bonobo_state = window->details->updating_bonobo_state;
314
315        window->details->updating_bonobo_state = TRUE;
316        if (window->details->ui_is_frozen) {
317                bonobo_ui_engine_thaw (engine);
318                if (window->details->ui_change_depth == 0) {
319                        window->details->ui_is_frozen = FALSE;
320                        if (!window->details->ui_pending_initialize_menus_part_2) {
321                                ui_remove_idle_handler (window);
322                        }
323                } else {
324                        bonobo_ui_engine_freeze (engine);
325                }
326        } else {
327                bonobo_ui_engine_update (engine);
328        }
329        window->details->updating_bonobo_state = old_updating_bonobo_state;
330}
331
332static gboolean
333nautilus_window_clear_status (gpointer callback_data)
334{
335        NautilusWindow *window;
336
337        window = NAUTILUS_WINDOW (callback_data);
338
339        bonobo_ui_component_set_status (window->details->status_ui, NULL, NULL);
340
341        return FALSE;
342}
343
344void
345nautilus_window_set_status (NautilusWindow *window, const char *text)
346{
347        if (text != NULL && text[0] != '\0') {
348                bonobo_ui_component_set_status (window->details->status_ui, text, NULL);
349        } else {
350                nautilus_window_clear_status (window);
351        }
352}
353
354void
355nautilus_window_go_to (NautilusWindow *window, const char *uri)
356{
357        nautilus_window_open_location (window, uri);
358}
359
360char *
361nautilus_window_get_location (NautilusWindow *window)
362{
363        g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), NULL);
364
365        return g_strdup (window->details->location);
366}
367
368static void
369go_to_callback (GtkWidget *widget,
370                const char *uri,
371                NautilusWindow *window)
372{
373        g_assert (NAUTILUS_IS_WINDOW (window));
374
375        nautilus_window_go_to (window, uri);
376}
377
378static void
379navigation_bar_location_changed_callback (GtkWidget *widget,
380                                          const char *uri,
381                                          NautilusWindow *window)
382{
383        g_assert (NAUTILUS_IS_WINDOW (window));
384
385        if (window->details->temporary_navigation_bar) {
386                if (nautilus_window_location_bar_showing (window)) {
387                        nautilus_window_hide_location_bar (window);
388                }
389                window->details->temporary_navigation_bar = FALSE;
390        }
391
392        nautilus_window_go_to (window, uri);
393}
394
395static void
396navigation_bar_mode_changed_callback (GtkWidget *widget,
397                                      NautilusSwitchableNavigationBarMode mode,
398                                      NautilusWindow *window)
399{
400        window->details->updating_bonobo_state = TRUE;
401
402        g_assert (mode == NAUTILUS_SWITCHABLE_NAVIGATION_BAR_MODE_LOCATION
403                  || mode == NAUTILUS_SWITCHABLE_NAVIGATION_BAR_MODE_SEARCH);
404
405        nautilus_window_ui_freeze (window);
406
407        nautilus_bonobo_set_toggle_state (window->details->shell_ui,
408                                          NAUTILUS_COMMAND_TOGGLE_FIND_MODE,
409                                          mode == NAUTILUS_SWITCHABLE_NAVIGATION_BAR_MODE_SEARCH);
410       
411        window->details->updating_bonobo_state = FALSE;
412
413        nautilus_window_ui_thaw (window);
414}
415
416void
417nautilus_window_zoom_in (NautilusWindow *window)
418{
419        if (window->content_view != NULL) {
420                nautilus_view_frame_zoom_in (window->content_view);
421        }
422}
423
424void
425nautilus_window_zoom_to_level (NautilusWindow *window, float level)
426{
427        if (window->content_view != NULL) {
428                nautilus_view_frame_set_zoom_level (window->content_view, level);
429        }
430}
431
432void
433nautilus_window_zoom_out (NautilusWindow *window)
434{
435        if (window->content_view != NULL) {
436                nautilus_view_frame_zoom_out (window->content_view);
437        }
438}
439
440void
441nautilus_window_zoom_to_fit (NautilusWindow *window)
442{
443        if (window->content_view != NULL) {
444                nautilus_view_frame_zoom_to_fit (window->content_view);
445        }
446}
447
448/* Code should never force the window taller than this size.
449 * (The user can still stretch the window taller if desired).
450 */
451static guint
452get_max_forced_height (GdkScreen *screen)
453{
454        return (gdk_screen_get_height (screen) * 90) / 100;
455}
456
457/* Code should never force the window wider than this size.
458 * (The user can still stretch the window wider if desired).
459 */
460static guint
461get_max_forced_width (GdkScreen *screen)
462{
463        return (gdk_screen_get_width (screen) * 90) / 100;
464}
465
466static void
467set_initial_window_geometry (NautilusWindow *window)
468{
469        GdkScreen *screen;
470        guint max_width_for_screen, max_height_for_screen;
471
472        screen = gtk_window_get_screen (GTK_WINDOW (window));
473       
474        /* Don't let GTK determine the minimum size
475         * automatically. It will insist that the window be
476         * really wide based on some misguided notion about
477         * the content view area. Also, it might start the
478         * window wider (or taller) than the screen, which
479         * is evil. So we choose semi-arbitrary initial and
480         * minimum widths instead of letting GTK decide.
481         */
482        /* FIXME - the above comment suggests that the size request
483         * of the content view area is wrong, probably because of
484         * another stupid set_usize someplace. If someone gets the
485         * content view area's size request right then we can
486         * probably remove this broken set_size_request() here.
487         * - hp@redhat.com
488         */
489
490        max_width_for_screen = get_max_forced_width (screen);
491        max_height_for_screen = get_max_forced_height (screen);
492
493        gtk_widget_set_size_request (GTK_WIDGET (window),
494                                     MIN (NAUTILUS_WINDOW_MIN_WIDTH,
495                                          max_width_for_screen),
496                                     MIN (NAUTILUS_WINDOW_MIN_HEIGHT,
497                                          max_height_for_screen));
498
499        gtk_window_set_default_size (GTK_WINDOW (window),
500                                     MIN (NAUTILUS_WINDOW_DEFAULT_WIDTH,
501                                          max_width_for_screen),
502                                     MIN (NAUTILUS_WINDOW_DEFAULT_HEIGHT,
503                                          max_height_for_screen));
504}
505
506/* Add a dummy menu with a "View as ..." item when we first create the
507 * view_as_option_menu -- without this the menu draws empty and shrunk,
508 * once we populate it it grows and forces the toolbar and all the other
509 * views to re-layout.
510 */
511static void
512set_dummy_initial_view_as_menu (NautilusWindow *window)
513{
514        GtkWidget *new_menu;
515        GtkWidget *menu_item;
516
517        new_menu = gtk_menu_new ();
518        menu_item = gtk_menu_item_new_with_label (_("View as..."));
519        gtk_widget_show (menu_item);
520        gtk_menu_shell_append (GTK_MENU_SHELL (new_menu), menu_item);
521
522        gtk_option_menu_set_menu (GTK_OPTION_MENU (window->view_as_option_menu),
523                                  new_menu);
524}
525
526static void
527side_pane_close_requested_callback (GtkWidget *widget,
528                                    gpointer user_data)
529{
530        NautilusWindow *window;
531       
532        window = NAUTILUS_WINDOW (user_data);
533
534        nautilus_window_hide_sidebar (window);
535}
536
537static void
538side_pane_size_allocate_callback (GtkWidget *widget,
539                                  GtkAllocation *allocation,
540                                  gpointer user_data)
541{
542        NautilusWindow *window;
543       
544        window = NAUTILUS_WINDOW (user_data);
545       
546        if (allocation->width != window->details->side_pane_width) {
547                window->details->side_pane_width = allocation->width;
548                eel_preferences_set_integer
549                        (NAUTILUS_PREFERENCES_SIDEBAR_WIDTH,
550                         allocation->width);
551        }
552}
553
554static void
555setup_side_pane_width (NautilusWindow *window)
556{
557        static gboolean setup_auto_value= TRUE;
558
559        g_return_if_fail (window->sidebar != NULL);
560       
561        if (setup_auto_value) {
562                setup_auto_value = FALSE;
563                eel_preferences_add_auto_integer
564                        (NAUTILUS_PREFERENCES_SIDEBAR_WIDTH,
565                         &side_pane_width_auto_value);
566        }
567
568        window->details->side_pane_width = side_pane_width_auto_value;
569
570        /* FIXME bugzilla.gnome.org 41245: Saved in pixels instead of in %? */
571        /* FIXME bugzilla.gnome.org 41245: No reality check on the value? */
572       
573        gtk_paned_set_position (GTK_PANED (window->content_hbox),
574                                side_pane_width_auto_value);
575}
576
577static void
578side_panel_set_open (GtkWidget *view,
579                     gboolean open)
580{
581        CORBA_Environment ev;
582        Bonobo_PropertyBag property_bag;
583        Bonobo_Control control;
584       
585        if (!view || !NAUTILUS_IS_VIEW_FRAME (view)) {
586                return;
587        }
588
589        control = nautilus_view_frame_get_control (NAUTILUS_VIEW_FRAME (view));
590       
591        if (control != CORBA_OBJECT_NIL) {
592                CORBA_exception_init (&ev);
593                property_bag = Bonobo_Control_getProperties (control, &ev);
594                if (!BONOBO_EX (&ev) && property_bag != CORBA_OBJECT_NIL) {
595                        /* For some reason this was implemented as 'close'
596                         * before, but open seems more natural */
597                        bonobo_property_bag_client_set_value_gboolean
598                                (property_bag, "close", !open, &ev);
599                        bonobo_object_release_unref (property_bag, NULL);
600                }
601        }
602}
603
604static void
605side_pane_switch_page_callback (NautilusSidePane *side_pane,
606                                GtkWidget *panel,
607                                NautilusWindow *window)
608{
609        if (window->details->current_side_panel) {
610                side_panel_set_open (window->details->current_side_panel,
611                                     FALSE);
612                eel_remove_weak_pointer (&window->details->current_side_panel);
613        }
614
615        side_panel_set_open (panel, TRUE);     
616        window->details->current_side_panel = panel;
617        eel_add_weak_pointer (&window->details->current_side_panel);
618}
619
620static void
621nautilus_window_set_up_sidebar (NautilusWindow *window)
622{
623        window->sidebar = nautilus_side_pane_new ();
624
625        g_signal_connect (window->sidebar,
626                          "close_requested",
627                          G_CALLBACK (side_pane_close_requested_callback),
628                          window);
629
630        g_signal_connect (window->sidebar,
631                          "switch_page",
632                          G_CALLBACK (side_pane_switch_page_callback),
633                          window);
634
635        gtk_paned_pack1 (GTK_PANED (window->content_hbox),
636                         GTK_WIDGET (window->sidebar),
637                         FALSE, TRUE);
638
639        setup_side_pane_width (window);
640        g_signal_connect (window->sidebar,
641                          "size_allocate",
642                          G_CALLBACK (side_pane_size_allocate_callback),
643                          window);
644       
645        window->information_panel = nautilus_information_panel_new ();
646       
647        if (window->details->location != NULL &&
648            window->details->title != NULL) {
649                nautilus_information_panel_set_uri (window->information_panel,
650                                                    window->details->location,
651                                                    window->details->title);
652        }
653
654        g_signal_connect_object (window->information_panel, "location_changed",
655                                 G_CALLBACK (go_to_callback), window, 0);
656
657        gtk_widget_show (GTK_WIDGET (window->information_panel));
658
659        nautilus_side_pane_add_panel (NAUTILUS_SIDE_PANE (window->sidebar),
660                                      GTK_WIDGET (window->information_panel),
661                                      _("Information"));
662
663        /* Set up the sidebar panels. */
664        add_sidebar_panels (window);
665       
666        gtk_widget_show (GTK_WIDGET (window->sidebar));
667}
668
669static void
670nautilus_window_tear_down_sidebar (NautilusWindow *window)
671{
672        nautilus_window_set_sidebar_panels (window, NULL);
673        gtk_widget_destroy (GTK_WIDGET (window->sidebar));
674        window->sidebar = NULL;
675        window->information_panel = NULL;
676}
677
678static void
679nautilus_window_constructed (NautilusWindow *window)
680{
681        GtkWidget *location_bar_box;
682        GtkWidget *view_as_menu_vbox;
683        BonoboControl *location_bar_wrapper;
684       
685        nautilus_window_ui_freeze (window);
686
687        /* Load the user interface from the XML file. */
688        bonobo_ui_util_set_ui (window->details->shell_ui,
689                               DATADIR,
690                               "nautilus-shell-ui.xml",
691                               "nautilus", NULL);
692       
693        /* set up location bar */
694        location_bar_box = gtk_hbox_new (FALSE, GNOME_PAD);
695        gtk_container_set_border_width (GTK_CONTAINER (location_bar_box), GNOME_PAD_SMALL);
696       
697        window->navigation_bar = nautilus_switchable_navigation_bar_new (window);
698        gtk_widget_show (GTK_WIDGET (window->navigation_bar));
699
700        g_signal_connect_object (window->navigation_bar, "location_changed",
701                                 G_CALLBACK (navigation_bar_location_changed_callback), window, 0);
702        g_signal_connect_object (window->navigation_bar, "mode_changed",
703                                 G_CALLBACK (navigation_bar_mode_changed_callback), window, 0);
704
705        gtk_box_pack_start (GTK_BOX (location_bar_box), window->navigation_bar,
706                            TRUE, TRUE, GNOME_PAD_SMALL);
707
708        /* Option menu for content view types; it's empty here, filled in when a uri is set.
709         * Pack it into vbox so it doesn't grow vertically when location bar does.
710         */
711        view_as_menu_vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
712        gtk_widget_show (view_as_menu_vbox);
713        gtk_box_pack_end (GTK_BOX (location_bar_box), view_as_menu_vbox, FALSE, FALSE, 0);
714       
715        window->view_as_option_menu = gtk_option_menu_new ();
716        gtk_box_pack_end (GTK_BOX (view_as_menu_vbox), window->view_as_option_menu, TRUE, FALSE, 0);
717        gtk_widget_show (window->view_as_option_menu);
718        /* Make sure there is something in the option menu to prevent it from
719         * growing later.
720         */
721        set_dummy_initial_view_as_menu (window);
722       
723        /* Allocate the zoom control and place on the right next to the menu.
724         * It gets shown later, if the view-frame contains something zoomable.
725         */
726        window->zoom_control = nautilus_zoom_control_new ();
727        g_signal_connect_object (window->zoom_control, "zoom_in",
728                                 G_CALLBACK (nautilus_window_zoom_in),
729                                 window, G_CONNECT_SWAPPED);
730        g_signal_connect_object (window->zoom_control, "zoom_out",
731                                 G_CALLBACK (nautilus_window_zoom_out),
732                                 window, G_CONNECT_SWAPPED);
733        g_signal_connect_object (window->zoom_control, "zoom_to_level",
734                                 G_CALLBACK (nautilus_window_zoom_to_level),
735                                 window, G_CONNECT_SWAPPED);
736        g_signal_connect_object (window->zoom_control, "zoom_to_fit",
737                                 G_CALLBACK (nautilus_window_zoom_to_fit),
738                                 window, G_CONNECT_SWAPPED);
739        gtk_box_pack_end (GTK_BOX (location_bar_box), window->zoom_control, FALSE, FALSE, 0);
740       
741        gtk_widget_show (location_bar_box);
742       
743        /* FIXME bugzilla.gnome.org 41243:
744         * We should use inheritance instead of these special cases
745         * for the desktop window.
746         */
747        if (NAUTILUS_IS_DESKTOP_WINDOW (window)) {
748                window->content_hbox = gtk_widget_new (EEL_TYPE_GENEROUS_BIN, NULL);
749        } else {
750                set_initial_window_geometry (window);
751       
752                window->content_hbox = nautilus_horizontal_splitter_new ();
753
754                if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_START_WITH_SIDEBAR)) {
755                        nautilus_window_set_up_sidebar (window);
756                }
757        }
758
759        gtk_widget_show (window->content_hbox);
760        bonobo_window_set_contents (BONOBO_WINDOW (window), window->content_hbox);
761       
762        bonobo_ui_component_freeze (window->details->shell_ui, NULL);
763
764        /* FIXME bugzilla.gnome.org 41243:
765         * We should use inheritance instead of these special cases
766         * for the desktop window.
767         */
768        if (NAUTILUS_IS_DESKTOP_WINDOW (window)) {
769                nautilus_bonobo_set_hidden (window->details->shell_ui,
770                                            LOCATION_BAR_PATH, TRUE);
771                nautilus_bonobo_set_hidden (window->details->shell_ui,
772                                            TOOLBAR_PATH, TRUE);
773                nautilus_bonobo_set_hidden (window->details->shell_ui,
774                                            STATUS_BAR_PATH, TRUE);
775                nautilus_bonobo_set_hidden (window->details->shell_ui,
776                                            MENU_BAR_PATH, TRUE);
777        }
778
779        /* Wrap the location bar in a control and set it up. */
780        location_bar_wrapper = bonobo_control_new (location_bar_box);
781        bonobo_ui_component_object_set (window->details->shell_ui,
782                                        "/Location Bar/Wrapper",
783                                        BONOBO_OBJREF (location_bar_wrapper),
784                                        NULL);
785        bonobo_ui_component_thaw (window->details->shell_ui, NULL);
786        bonobo_object_unref (location_bar_wrapper);
787
788        /* initalize the menus and toolbars */
789        nautilus_window_initialize_menus_part_1 (window);
790        nautilus_window_initialize_toolbars (window);
791
792        /* We'll do the second part later (bookmarks and go menus) */
793        window->details->ui_pending_initialize_menus_part_2 = TRUE;
794       
795        /* Set initial sensitivity of some buttons & menu items
796         * now that they're all created.
797         */
798        nautilus_window_allow_back (window, FALSE);
799        nautilus_window_allow_forward (window, FALSE);
800        nautilus_window_allow_stop (window, FALSE);
801
802        /* Set up undo manager */
803        nautilus_undo_manager_attach (window->application->undo_manager, G_OBJECT (window));   
804
805        /* Register that things may be dragged from this window */
806        nautilus_drag_window_register (GTK_WINDOW (window));
807
808        nautilus_window_ui_thaw (window);
809}
810
811static void
812nautilus_window_set_property (GObject *object,
813                              guint arg_id,
814                              const GValue *value,
815                              GParamSpec *pspec)
816{
817        char *old_name;
818        NautilusWindow *window;
819
820        window = NAUTILUS_WINDOW (object);
821       
822        switch (arg_id) {
823        case ARG_APP_ID:
824                if (g_value_get_string (value) == NULL) {
825                        return;
826                }
827                old_name = bonobo_window_get_name (BONOBO_WINDOW (window));
828                bonobo_window_set_name (BONOBO_WINDOW (window), g_value_get_string (value));
829                /* This hack of using the time when the name first
830                 * goes non-NULL to be window-constructed time is
831                 * completely lame. But it works, so for now we leave
832                 * it alone.
833                 */
834                if (old_name == NULL) {
835                        nautilus_window_constructed (window);
836                }
837                g_free (old_name);
838                break;
839        case ARG_APP:
840                window->application = NAUTILUS_APPLICATION (g_value_get_object (value));
841                break;
842        }
843}
844
845static void
846nautilus_window_get_property (GObject *object,
847                              guint arg_id,
848                              GValue *value,
849                              GParamSpec *pspec)
850{
851        switch (arg_id) {
852        case ARG_APP_ID:
853                g_value_set_string_take_ownership (
854                        value,
855                        bonobo_window_get_name (BONOBO_WINDOW (object)));
856                break;
857        case ARG_APP:
858                g_value_set_object (value, NAUTILUS_WINDOW (object)->application);
859                break;
860        }
861}
862
863static void
864free_stored_viewers (NautilusWindow *window)
865{
866        eel_g_list_free_deep_custom (window->details->short_list_viewers,
867                                     (GFunc) nautilus_view_identifier_free,
868                                     NULL);
869        window->details->short_list_viewers = NULL;
870        nautilus_view_identifier_free (window->details->extra_viewer);
871        window->details->extra_viewer = NULL;
872}
873
874static void
875nautilus_window_unrealize (GtkWidget *widget)
876{
877        NautilusWindow *window;
878       
879        window = NAUTILUS_WINDOW (widget);
880
881        if (window->details->throbber_property_bag != CORBA_OBJECT_NIL) {
882                bonobo_object_release_unref (window->details->throbber_property_bag, NULL);
883                window->details->throbber_property_bag = CORBA_OBJECT_NIL;
884        }
885
886        GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
887}
888
889static void
890nautilus_window_destroy (GtkObject *object)
891{
892        NautilusWindow *window;
893       
894        window = NAUTILUS_WINDOW (object);
895
896        nautilus_window_manage_views_destroy (window);
897
898        window->sidebar = NULL;
899        eel_g_object_list_free (window->sidebar_panels);
900        window->sidebar_panels = NULL;
901
902        window->view_as_option_menu = NULL;
903        window->navigation_bar = NULL;
904        window->content_hbox = NULL;
905        window->zoom_control = NULL;
906
907        if (window->content_view) {
908                gtk_object_destroy (GTK_OBJECT (window->content_view));
909                window->content_view = NULL;
910        }
911
912        if (window->details->tooltips) {
913                g_object_unref (G_OBJECT (window->details->tooltips));
914                window->details->tooltips = NULL;
915        }
916
917        GTK_OBJECT_CLASS (parent_class)->destroy (object);
918}
919
920static void
921nautilus_window_finalize (GObject *object)
922{
923        NautilusWindow *window;
924       
925        window = NAUTILUS_WINDOW (object);
926
927        nautilus_window_manage_views_finalize (window);
928
929        nautilus_window_set_viewed_file (window, NULL);
930        nautilus_window_remove_bookmarks_menu_callback (window);
931        nautilus_window_remove_go_menu_callback (window);
932
933        if (window->details->ui_idle_id != 0) {
934                gtk_idle_remove (window->details->ui_idle_id);
935        }
936
937        if (window->details->shell_ui != NULL) {
938                bonobo_ui_component_unset_container (window->details->shell_ui, NULL);
939                bonobo_object_unref (window->details->shell_ui);
940        }
941
942        if (window->details->status_ui != NULL) {
943                bonobo_ui_component_unset_container (window->details->status_ui, NULL);
944                bonobo_object_unref (window->details->status_ui);
945        }
946
947        nautilus_file_unref (window->details->viewed_file);
948
949        free_stored_viewers (window);
950
951        g_free (window->details->location);
952        eel_g_list_free_deep (window->details->selection);
953        eel_g_list_free_deep (window->details->pending_selection);
954
955        nautilus_window_clear_back_list (window);
956        nautilus_window_clear_forward_list (window);
957
958        if (window->current_location_bookmark != NULL) {
959                g_object_unref (window->current_location_bookmark);
960        }
961        if (window->last_location_bookmark != NULL) {
962                g_object_unref (window->last_location_bookmark);
963        }
964
965        bonobo_object_unref (window->details->ui_container);
966
967        if (window->details->location_change_at_idle_id != 0) {
968                gtk_idle_remove (window->details->location_change_at_idle_id);
969        }
970
971        g_free (window->details->title);
972       
973        g_free (window->details);
974
975        G_OBJECT_CLASS (parent_class)->finalize (object);
976}
977
978void
979nautilus_window_save_geometry (NautilusWindow *window)
980{
981        char *geometry_string;
982
983        g_assert (NAUTILUS_IS_WINDOW (window));
984
985        geometry_string = eel_gtk_window_get_geometry_string (GTK_WINDOW (window));
986
987        nautilus_file_set_metadata (window->details->viewed_file,
988                                    NAUTILUS_METADATA_KEY_WINDOW_GEOMETRY,
989                                    NULL,
990                                    geometry_string);
991                                   
992        g_free (geometry_string);
993}
994
995void
996nautilus_window_close (NautilusWindow *window)
997{
998        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
999
1000        gtk_widget_destroy (GTK_WIDGET (window));
1001}
1002
1003static void
1004nautilus_window_size_request (GtkWidget         *widget,
1005                              GtkRequisition    *requisition)
1006{
1007        GdkScreen *screen;
1008        guint max_width;
1009        guint max_height;
1010
1011        g_assert (NAUTILUS_IS_WINDOW (widget));
1012        g_assert (requisition != NULL);
1013
1014        GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
1015
1016        screen = gtk_window_get_screen (GTK_WINDOW (widget));
1017
1018        /* Limit the requisition to be within 90% of the available screen
1019         * real state.
1020         *
1021         * This way the user will have a fighting chance of getting
1022         * control of their window back if for whatever reason one of the
1023         * window's descendants decide they want to be 4000 pixels wide.
1024         *
1025         * Note that the user can still make the window really huge by hand.
1026         *
1027         * Bugs in components or other widgets that cause such huge geometries
1028         * to be requested, should still be fixed.  This code is here only to
1029         * prevent the extremely frustrating consequence of such bugs.
1030         */
1031        max_width = get_max_forced_width (screen);
1032        max_height = get_max_forced_height (screen);
1033
1034        if (requisition->width > (int) max_width) {
1035                requisition->width = max_width;
1036        }
1037       
1038        if (requisition->height > (int) max_height) {
1039                requisition->height = max_height;
1040        }
1041}
1042
1043
1044/*
1045 * Main API
1046 */
1047
1048static void
1049activate_nth_short_list_item (NautilusWindow *window, guint index)
1050{
1051        g_assert (NAUTILUS_IS_WINDOW (window));
1052        g_assert (index < g_list_length (window->details->short_list_viewers));
1053
1054        nautilus_window_set_content_view (window,
1055                                          g_list_nth_data (window->details->short_list_viewers, index));
1056}
1057
1058static void
1059activate_extra_viewer (NautilusWindow *window)
1060{
1061        g_assert (NAUTILUS_IS_WINDOW (window));
1062        g_assert (window->details->extra_viewer != NULL);
1063       
1064        nautilus_window_set_content_view (window, window->details->extra_viewer);       
1065}
1066
1067static void
1068handle_view_as_item_from_bonobo_menu (NautilusWindow *window, const char *id)
1069{
1070        char *container_path;
1071
1072        container_path = nautilus_bonobo_get_numbered_menu_item_container_path_from_command (id);
1073
1074        if (eel_strcmp (container_path, NAUTILUS_MENU_PATH_SHORT_LIST_PLACEHOLDER) == 0) {
1075                activate_nth_short_list_item
1076                        (window,
1077                         nautilus_bonobo_get_numbered_menu_item_index_from_command (id));
1078        } else if (eel_strcmp (container_path, NAUTILUS_MENU_PATH_EXTRA_VIEWER_PLACEHOLDER) == 0) {
1079                g_return_if_fail
1080                        (nautilus_bonobo_get_numbered_menu_item_index_from_command (id) == 0);
1081                activate_extra_viewer (window);
1082        }
1083
1084        g_free (container_path);
1085}
1086
1087void
1088nautilus_window_handle_ui_event_callback (BonoboUIComponent *ui,
1089                                          const char *id,
1090                                          Bonobo_UIComponent_EventType type,
1091                                          const char *state,
1092                                          NautilusWindow *window)
1093{
1094        if (!window->details->updating_bonobo_state
1095            && type == Bonobo_UIComponent_STATE_CHANGED
1096            && strcmp (state, "1") == 0) {
1097                handle_view_as_item_from_bonobo_menu (window, id);
1098        }
1099}               
1100
1101static void
1102view_as_menu_switch_views_callback (GtkWidget *widget, gpointer data)
1103{
1104        NautilusWindow *window;
1105        int viewer_index;
1106       
1107        g_assert (GTK_IS_MENU_ITEM (widget));
1108        g_assert (NAUTILUS_IS_WINDOW (data));
1109
1110        window = NAUTILUS_WINDOW (data);
1111
1112        if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "extra viewer")) == TRUE) {
1113                activate_extra_viewer (window);
1114        } else {
1115                viewer_index = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "viewer index"));
1116                activate_nth_short_list_item (window, viewer_index);
1117        }
1118}
1119
1120static GtkWidget *
1121create_view_as_menu_item (NautilusWindow *window,
1122                          NautilusViewIdentifier *identifier,
1123                          guint index)
1124{
1125        GtkWidget *menu_item;
1126        char *menu_label;
1127
1128        menu_label = g_strdup (_(identifier->view_as_label));
1129        menu_item = gtk_menu_item_new_with_mnemonic (menu_label);
1130        g_free (menu_label);
1131
1132        g_signal_connect_object (menu_item, "activate",
1133                                 G_CALLBACK (view_as_menu_switch_views_callback),
1134                                 window, 0);
1135
1136        g_object_set_data (G_OBJECT (menu_item), "viewer index", GINT_TO_POINTER (index));
1137
1138        gtk_widget_show (menu_item);
1139
1140        return menu_item;
1141}
1142
1143static GtkWidget *
1144new_gtk_separator (void)
1145{
1146        GtkWidget *result;
1147       
1148        result = gtk_menu_item_new ();
1149        gtk_widget_show (result);
1150        gtk_widget_set_sensitive (result, FALSE);
1151
1152        return result;
1153}
1154
1155static void
1156add_view_as_bonobo_menu_item (NautilusWindow *window,
1157                              const char *placeholder_path,
1158                              NautilusViewIdentifier *identifier,
1159                              int index)
1160{
1161        char *tip;
1162        char *item_path;
1163
1164        nautilus_bonobo_add_numbered_radio_menu_item
1165                (window->details->shell_ui,
1166                 placeholder_path,
1167                 index,
1168                 identifier->view_as_label_with_mnemonic,
1169                 "viewers group");
1170
1171        tip = g_strdup_printf (_("Display this location with \"%s\""),
1172                               identifier->viewer_label);
1173        item_path = nautilus_bonobo_get_numbered_menu_item_path
1174                (window->details->shell_ui,
1175                 placeholder_path,
1176                 index);
1177        nautilus_bonobo_set_tip (window->details->shell_ui, item_path, tip);
1178        g_free (item_path);
1179        g_free (tip);
1180}
1181
1182static void
1183remove_first_child (GtkContainer *container)
1184{
1185        gtk_container_remove (container,
1186                              eel_gtk_container_get_first_child (container));
1187}
1188
1189/* Make a special first item in the "View as" option menu that represents
1190 * the current content view. This should only be called if the current
1191 * content view isn't already in the "View as" option menu.
1192 */
1193static void
1194update_extra_viewer_in_view_as_menus (NautilusWindow *window,
1195                                      const NautilusViewIdentifier *id)
1196{
1197        GtkWidget *menu;
1198        GtkWidget *new_menu_item;
1199        gboolean had_extra_viewer;
1200
1201        had_extra_viewer = window->details->extra_viewer != NULL;
1202
1203        if (id == NULL) {
1204                if (!had_extra_viewer) {
1205                        return;
1206                }
1207        } else {
1208                if (had_extra_viewer
1209                    && nautilus_view_identifier_compare (window->details->extra_viewer, id) == 0) {
1210                        return;
1211                }
1212        }
1213        nautilus_view_identifier_free (window->details->extra_viewer);
1214        window->details->extra_viewer = nautilus_view_identifier_copy (id);
1215
1216        /* Update the View As option menu */   
1217        menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (window->view_as_option_menu));
1218
1219        /* Remove menu before changing contents so it is resized properly
1220         * when reattached later in this function.
1221         */
1222        g_object_ref (menu);
1223        gtk_option_menu_remove_menu (GTK_OPTION_MENU (window->view_as_option_menu));
1224
1225        /* Remove old menu item, and either remove or add separator. */
1226        if (had_extra_viewer) {
1227                remove_first_child (GTK_CONTAINER (menu));
1228                if (id == NULL) {
1229                        remove_first_child (GTK_CONTAINER (menu));
1230                }
1231        } else {
1232                if (id != NULL) {
1233                        gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), new_gtk_separator ());
1234                }
1235        }
1236
1237        /* Add new menu item. */
1238        if (id != NULL) {
1239                new_menu_item = create_view_as_menu_item (window, window->details->extra_viewer, 0);
1240                g_object_set_data (G_OBJECT (new_menu_item), "extra viewer", GINT_TO_POINTER (TRUE));
1241                gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), new_menu_item);
1242        }
1243
1244        gtk_option_menu_set_menu (GTK_OPTION_MENU (window->view_as_option_menu), menu);
1245        g_object_unref (menu);
1246
1247        /* Also update the Bonobo View menu item */
1248        if (id == NULL) {
1249                        nautilus_bonobo_remove_menu_items_and_commands
1250                                (window->details->shell_ui, NAUTILUS_MENU_PATH_EXTRA_VIEWER_PLACEHOLDER);
1251        } else {
1252                add_view_as_bonobo_menu_item (window,
1253                                              NAUTILUS_MENU_PATH_EXTRA_VIEWER_PLACEHOLDER,
1254                                              window->details->extra_viewer,
1255                                              0);
1256        }
1257}
1258
1259static void
1260remove_extra_viewer_in_view_as_menus (NautilusWindow *window)
1261{
1262        update_extra_viewer_in_view_as_menus (window, NULL);
1263}
1264
1265static void
1266replace_extra_viewer_in_view_as_menus (NautilusWindow *window)
1267{
1268        NautilusViewIdentifier *id;
1269
1270        id = nautilus_window_get_content_view_id (window);
1271        update_extra_viewer_in_view_as_menus (window, id);
1272        nautilus_view_identifier_free (id);
1273}
1274
1275/**
1276 * nautilus_window_synch_view_as_menus:
1277 *
1278 * Set the visible item of the "View as" option menu and
1279 * the marked "View as" item in the View menu to
1280 * match the current content view.
1281 *
1282 * @window: The NautilusWindow whose "View as" option menu should be synched.
1283 */
1284void
1285nautilus_window_synch_view_as_menus (NautilusWindow *window)
1286{
1287        int index;
1288        char *verb_name, *command_path;
1289        GList *node;
1290        const char *numbered_menu_item_container_path;
1291
1292        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1293
1294        if (window->content_view == NULL) {
1295                return;
1296        }
1297
1298        for (node = window->details->short_list_viewers, index = 0;
1299             node != NULL;
1300             node = node->next, ++index) {
1301                if (nautilus_window_content_view_matches_iid (window, ((NautilusViewIdentifier *)node->data)->iid)) {
1302                        break;
1303                }
1304        }
1305        if (node == NULL) {
1306                replace_extra_viewer_in_view_as_menus (window);
1307                index = 0;
1308                numbered_menu_item_container_path = NAUTILUS_MENU_PATH_EXTRA_VIEWER_PLACEHOLDER;
1309        } else {
1310                remove_extra_viewer_in_view_as_menus (window);
1311                numbered_menu_item_container_path = NAUTILUS_MENU_PATH_SHORT_LIST_PLACEHOLDER;
1312        }
1313
1314        g_assert (numbered_menu_item_container_path != NULL);
1315
1316        /* Make option menu show the right item */
1317        gtk_option_menu_set_history (GTK_OPTION_MENU (window->view_as_option_menu), index);
1318
1319        /* Make View menu in menu bar mark the right item */
1320        verb_name = nautilus_bonobo_get_numbered_menu_item_command
1321                (window->details->shell_ui,
1322                 numbered_menu_item_container_path, index);
1323        command_path = g_strconcat (COMMAND_PREFIX, verb_name, NULL);
1324        nautilus_bonobo_set_toggle_state (window->details->shell_ui, command_path, TRUE);
1325        g_free (command_path);
1326        g_free (verb_name);
1327}
1328
1329static void
1330chose_component_callback (NautilusViewIdentifier *identifier, gpointer callback_data)
1331{
1332        NautilusWindow *window;
1333
1334        window = NAUTILUS_WINDOW (callback_data);
1335        if (identifier != NULL) {
1336                nautilus_window_set_content_view (window, identifier);
1337        }
1338       
1339        /* FIXME bugzilla.gnome.org 41334: There should be some global
1340         * way to signal that the file type associations have changed,
1341         * so that the places that display these lists can react. For
1342         * now, hardwire this case, which is the most obvious one by
1343         * far.
1344         */
1345        nautilus_window_load_view_as_menus (window);
1346}
1347
1348static void
1349cancel_chose_component_callback (NautilusWindow *window)
1350{
1351        if (window->details->viewed_file != NULL) {
1352                nautilus_cancel_choose_component_for_file (window->details->viewed_file,
1353                                                           chose_component_callback,
1354                                                           window);
1355        }
1356}
1357
1358void
1359nautilus_window_show_view_as_dialog (NautilusWindow *window)
1360{
1361        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1362
1363        /* Call back when the user chose the component. */
1364        cancel_chose_component_callback (window);
1365        nautilus_choose_component_for_file (window->details->viewed_file,
1366                                            GTK_WINDOW (window),
1367                                            chose_component_callback,
1368                                            window);
1369}
1370
1371static void
1372view_as_menu_choose_view_callback (GtkWidget *widget, gpointer data)
1373{
1374        NautilusWindow *window;
1375       
1376        g_assert (GTK_IS_MENU_ITEM (widget));
1377        g_assert (NAUTILUS_IS_WINDOW (data));
1378       
1379        window = NAUTILUS_WINDOW (data);
1380
1381        /* Set the option menu back to its previous setting (Don't
1382         * leave it on this dialog-producing "View as..."
1383         * setting). If the menu choice causes a content view change,
1384         * this will be updated again later, in
1385         * nautilus_window_load_view_as_menus. Do this right away so
1386         * the user never sees the option menu set to "View as
1387         * Other...".
1388         */
1389        nautilus_window_synch_view_as_menus (window);
1390
1391        nautilus_window_show_view_as_dialog (window);
1392}
1393
1394static void
1395refresh_stored_viewers (NautilusWindow *window)
1396{
1397        GList *components, *node, *viewers;
1398        NautilusViewIdentifier *identifier;
1399
1400        components = nautilus_mime_get_short_list_components_for_file (window->details->viewed_file);
1401        viewers = NULL;
1402        for (node = components; node != NULL; node = node->next) {
1403                identifier = nautilus_view_identifier_new_from_content_view (node->data);
1404                viewers = g_list_prepend (viewers, identifier);
1405        }
1406        gnome_vfs_mime_component_list_free (components);
1407
1408        free_stored_viewers (window);
1409        window->details->short_list_viewers = g_list_reverse (viewers);
1410}
1411
1412static void
1413load_view_as_menus_callback (NautilusFile *file,
1414                            gpointer callback_data)
1415{       
1416        GtkWidget *new_menu;
1417        GtkWidget *menu_item;
1418        GList *node;
1419        NautilusWindow *window;
1420        int index;
1421
1422        window = NAUTILUS_WINDOW (callback_data);
1423
1424        g_assert (GTK_IS_OPTION_MENU (window->view_as_option_menu));
1425
1426        /* Clear out the menu items created last time. For the option menu, we need do
1427         * nothing since we replace the entire menu. For the View menu, we have
1428         * to do this explicitly.
1429         */
1430        nautilus_bonobo_remove_menu_items_and_commands
1431                (window->details->shell_ui, NAUTILUS_MENU_PATH_SHORT_LIST_PLACEHOLDER);
1432        nautilus_bonobo_remove_menu_items_and_commands
1433                (window->details->shell_ui, NAUTILUS_MENU_PATH_EXTRA_VIEWER_PLACEHOLDER);
1434
1435        refresh_stored_viewers (window);
1436
1437        new_menu = gtk_menu_new ();
1438       
1439        /* Add a menu item for each view in the preferred list for this location. */
1440        for (node = window->details->short_list_viewers, index = 0;
1441             node != NULL;
1442             node = node->next, ++index) {
1443                /* Menu item in option menu. This doesn't use Bonobo, for various
1444                 * historical and technical reasons.
1445                 */
1446                menu_item = create_view_as_menu_item (window, node->data, index);
1447                gtk_menu_shell_append (GTK_MENU_SHELL (new_menu), menu_item);
1448
1449                /* Menu item in View menu. */
1450                add_view_as_bonobo_menu_item (window,
1451                                              NAUTILUS_MENU_PATH_SHORT_LIST_PLACEHOLDER,
1452                                              node->data,
1453                                              index);
1454        }
1455
1456        /* Add/Show separator before "View as..." if there are any other viewers in menu. */
1457        if (window->details->short_list_viewers != NULL) {
1458                gtk_menu_shell_append (GTK_MENU_SHELL (new_menu), new_gtk_separator ());
1459        }
1460        nautilus_bonobo_set_hidden (window->details->shell_ui,
1461                                    NAUTILUS_MENU_PATH_AFTER_SHORT_LIST_SEPARATOR,
1462                                    window->details->short_list_viewers == NULL);
1463
1464        /* Add "View as..." extra bonus choice. */
1465        menu_item = gtk_menu_item_new_with_label (_("View as..."));
1466        g_signal_connect_object (menu_item, "activate",
1467                                 G_CALLBACK (view_as_menu_choose_view_callback), window, 0);
1468        gtk_widget_show (menu_item);
1469        gtk_menu_shell_append (GTK_MENU_SHELL (new_menu), menu_item);
1470
1471        /* We create and attach a new menu here because adding/removing
1472         * items from existing menu screws up the size of the option menu.
1473         */
1474        gtk_option_menu_set_menu (GTK_OPTION_MENU (window->view_as_option_menu),
1475                                  new_menu);
1476
1477        nautilus_window_synch_view_as_menus (window);
1478}
1479
1480static void
1481cancel_view_as_callback (NautilusWindow *window)
1482{
1483        nautilus_file_cancel_call_when_ready (window->details->viewed_file,
1484                                              load_view_as_menus_callback,
1485                                              window);
1486}
1487
1488void
1489nautilus_window_load_view_as_menus (NautilusWindow *window)
1490{
1491        GList *attributes;
1492
1493        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1494
1495        attributes = nautilus_mime_actions_get_full_file_attributes ();
1496
1497        cancel_view_as_callback (window);
1498        nautilus_file_call_when_ready (window->details->viewed_file,
1499                                       attributes,
1500                                       load_view_as_menus_callback,
1501                                       window);
1502
1503        g_list_free (attributes);
1504}
1505
1506void
1507nautilus_window_add_sidebar_panel (NautilusWindow *window,
1508                                   NautilusViewFrame *sidebar_panel)
1509{
1510        char *label;
1511
1512        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1513        g_return_if_fail (NAUTILUS_IS_VIEW_FRAME (sidebar_panel));
1514        g_return_if_fail (NAUTILUS_IS_SIDE_PANE (window->sidebar));
1515        g_return_if_fail (g_list_find (window->sidebar_panels, sidebar_panel) == NULL);
1516       
1517        label = nautilus_view_frame_get_label (sidebar_panel);
1518       
1519        nautilus_side_pane_add_panel (window->sidebar,
1520                                      GTK_WIDGET (sidebar_panel),
1521                                      label);
1522
1523        g_free (label);
1524
1525        g_object_ref (sidebar_panel);
1526        window->sidebar_panels = g_list_prepend (window->sidebar_panels, sidebar_panel);
1527}
1528
1529void
1530nautilus_window_remove_sidebar_panel (NautilusWindow *window, NautilusViewFrame *sidebar_panel)
1531{
1532        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1533        g_return_if_fail (NAUTILUS_IS_VIEW_FRAME (sidebar_panel));
1534
1535        if (g_list_find (window->sidebar_panels, sidebar_panel) == NULL) {
1536                return;
1537        }
1538       
1539        nautilus_side_pane_remove_panel (window->sidebar,
1540                                         GTK_WIDGET (sidebar_panel));
1541        window->sidebar_panels = g_list_remove (window->sidebar_panels, sidebar_panel);
1542        g_object_unref (sidebar_panel);
1543}
1544
1545void
1546nautilus_window_go_back (NautilusWindow *window)
1547{
1548        nautilus_window_back_or_forward (window, TRUE, 0);
1549}
1550
1551void
1552nautilus_window_go_forward (NautilusWindow *window)
1553{
1554        nautilus_window_back_or_forward (window, FALSE, 0);
1555}
1556
1557void
1558nautilus_window_go_up (NautilusWindow *window)
1559{
1560        GnomeVFSURI *current_uri;
1561        GnomeVFSURI *parent_uri;
1562        GList *selection;
1563        char *parent_uri_string;
1564       
1565        if (window->details->location == NULL) {
1566                return;
1567        }
1568       
1569        current_uri = gnome_vfs_uri_new (window->details->location);
1570        parent_uri = gnome_vfs_uri_get_parent (current_uri);
1571        gnome_vfs_uri_unref (current_uri);
1572
1573        if (parent_uri == NULL) {
1574                g_warning ("Can't go Up from here. The UI should have prevented us from getting this far.");
1575                return;
1576        }
1577       
1578        parent_uri_string = gnome_vfs_uri_to_string (parent_uri, GNOME_VFS_URI_HIDE_NONE);
1579        gnome_vfs_uri_unref (parent_uri);
1580
1581        selection = g_list_prepend (NULL, g_strdup (window->details->location));
1582       
1583        nautilus_window_open_location_with_selection (window, parent_uri_string, selection);
1584       
1585        g_free (parent_uri_string);
1586        eel_g_list_free_deep (selection);
1587}
1588
1589void
1590nautilus_window_set_search_mode (NautilusWindow *window,
1591                                 gboolean search_mode)
1592{
1593        nautilus_switchable_navigation_bar_set_mode
1594                (NAUTILUS_SWITCHABLE_NAVIGATION_BAR (window->navigation_bar),
1595                 search_mode
1596                 ? NAUTILUS_SWITCHABLE_NAVIGATION_BAR_MODE_SEARCH
1597                 : NAUTILUS_SWITCHABLE_NAVIGATION_BAR_MODE_LOCATION);
1598
1599       
1600}
1601
1602gboolean
1603nautilus_window_get_search_mode (NautilusWindow *window)
1604{
1605        return nautilus_switchable_navigation_bar_get_mode
1606                (NAUTILUS_SWITCHABLE_NAVIGATION_BAR (window->navigation_bar))
1607        == NAUTILUS_SWITCHABLE_NAVIGATION_BAR_MODE_SEARCH;
1608}
1609
1610void
1611nautilus_window_go_home (NautilusWindow *window)
1612{
1613        char *home_uri;
1614
1615        nautilus_window_set_search_mode (window, FALSE);
1616
1617#ifdef WEB_NAVIGATION_ENABLED
1618        home_uri = eel_preferences_get (NAUTILUS_PREFERENCES_HOME_URI);
1619#else
1620        home_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ());
1621#endif
1622       
1623        g_assert (home_uri != NULL);
1624        nautilus_window_go_to (window, home_uri);
1625        g_free (home_uri);
1626}
1627
1628void
1629nautilus_window_allow_back (NautilusWindow *window, gboolean allow)
1630{
1631        nautilus_window_ui_freeze (window);
1632
1633        nautilus_bonobo_set_sensitive (window->details->shell_ui,
1634                                       NAUTILUS_COMMAND_BACK, allow);
1635        /* Have to handle non-standard Back button explicitly (it's
1636         * non-standard to support right-click menu).
1637         */
1638        gtk_widget_set_sensitive
1639                (GTK_WIDGET (window->details->back_button_item), allow);
1640
1641        nautilus_window_ui_thaw (window);
1642}
1643
1644void
1645nautilus_window_allow_forward (NautilusWindow *window, gboolean allow)
1646{
1647        nautilus_window_ui_freeze (window);
1648
1649        nautilus_bonobo_set_sensitive (window->details->shell_ui,
1650                                       NAUTILUS_COMMAND_FORWARD, allow);
1651        /* Have to handle non-standard Forward button explicitly (it's
1652         * non-standard to support right-click menu).
1653         */
1654        gtk_widget_set_sensitive
1655                (GTK_WIDGET (window->details->forward_button_item), allow);
1656
1657        nautilus_window_ui_thaw (window);
1658}
1659
1660void
1661nautilus_window_allow_up (NautilusWindow *window, gboolean allow)
1662{
1663        nautilus_window_ui_freeze (window);
1664
1665        /* Because of verbs, we set the sensitivity of the menu to
1666         * control both the menu and toolbar.
1667         */
1668        nautilus_bonobo_set_sensitive (window->details->shell_ui,
1669                                       NAUTILUS_COMMAND_UP, allow);
1670
1671        nautilus_window_ui_thaw (window);
1672}
1673
1674void
1675nautilus_window_allow_reload (NautilusWindow *window, gboolean allow)
1676{
1677        nautilus_window_ui_freeze (window);
1678
1679        /* Because of verbs, we set the sensitivity of the menu to
1680         * control both the menu and toolbar.
1681         */
1682        nautilus_bonobo_set_sensitive (window->details->shell_ui,
1683                                       NAUTILUS_COMMAND_RELOAD, allow);
1684
1685        nautilus_window_ui_thaw (window);
1686}
1687
1688void
1689nautilus_send_history_list_changed (void)
1690{
1691        g_signal_emit_by_name (nautilus_signaller_get_current (),
1692                               "history_list_changed");
1693}
1694
1695static void
1696free_history_list (void)
1697{
1698        eel_g_object_list_free (history_list);
1699        history_list = NULL;
1700}
1701
1702/* Remove the this URI from the history list.
1703 * Do not sent out a change notice.
1704 * We pass in a bookmark for convenience.
1705 */
1706static void
1707remove_from_history_list (NautilusBookmark *bookmark)
1708{
1709        GList *node;
1710
1711        /* Compare only the uris here. Comparing the names also is not
1712         * necessary and can cause problems due to the asynchronous
1713         * nature of when the title of the window is set.
1714         */
1715        node = g_list_find_custom (history_list,
1716                                   bookmark,
1717                                   nautilus_bookmark_compare_uris);
1718       
1719        /* Remove any older entry for this same item. There can be at most 1. */
1720        if (node != NULL) {
1721                history_list = g_list_remove_link (history_list, node);
1722                g_object_unref (node->data);
1723                g_list_free_1 (node);
1724        }
1725}
1726
1727static void
1728add_to_history_list (NautilusBookmark *bookmark)
1729{
1730        /* Note that the history is shared amongst all windows so
1731         * this is not a NautilusWindow function. Perhaps it belongs
1732         * in its own file.
1733         */
1734        int i;
1735        GList *l, *next;
1736        static gboolean free_history_list_is_set_up;
1737
1738        g_assert (NAUTILUS_IS_BOOKMARK (bookmark));
1739
1740        if (!free_history_list_is_set_up) {
1741                eel_debug_call_at_shutdown (free_history_list);
1742                free_history_list_is_set_up = TRUE;
1743        }
1744
1745/*      g_warning ("Add to history list '%s' '%s'",
1746                   nautilus_bookmark_get_name (bookmark),
1747                   nautilus_bookmark_get_uri (bookmark)); */
1748
1749        if (!history_list ||
1750            nautilus_bookmark_compare_uris (history_list->data, bookmark)) {
1751                g_object_ref (bookmark);
1752                remove_from_history_list (bookmark);
1753                history_list = g_list_prepend (history_list, bookmark);
1754
1755                for (i = 0, l = history_list; l; l = next) {
1756                        next = l->next;
1757                       
1758                        if (i++ >= MAX_HISTORY_ITEMS) {
1759                                g_object_unref (l->data);
1760                                history_list = g_list_delete_link (history_list, l);
1761                        }
1762                }
1763
1764                nautilus_send_history_list_changed ();
1765        }
1766}
1767
1768void
1769nautilus_remove_from_history_list_no_notify (const char *uri)
1770{
1771        NautilusBookmark *bookmark;
1772
1773        bookmark = nautilus_bookmark_new (uri, "");
1774        remove_from_history_list (bookmark);
1775        g_object_unref (bookmark);
1776}
1777
1778static void
1779real_add_current_location_to_history_list (NautilusWindow *window)
1780{
1781        g_assert (NAUTILUS_IS_WINDOW (window));
1782
1783        add_to_history_list (window->current_location_bookmark);
1784}
1785
1786void
1787nautilus_window_add_current_location_to_history_list (NautilusWindow *window)
1788{
1789        g_assert (NAUTILUS_IS_WINDOW (window));
1790
1791        EEL_CALL_METHOD (NAUTILUS_WINDOW_CLASS, window,
1792                         add_current_location_to_history_list, (window));
1793}
1794
1795void
1796nautilus_window_clear_forward_list (NautilusWindow *window)
1797{
1798        eel_g_object_list_free (window->forward_list);
1799        window->forward_list = NULL;
1800}
1801
1802void
1803nautilus_window_clear_back_list (NautilusWindow *window)
1804{
1805        eel_g_object_list_free (window->back_list);
1806        window->back_list = NULL;
1807}
1808
1809void
1810nautilus_forget_history (void)
1811{
1812        GList *window_node;
1813        NautilusWindow *window;
1814
1815        /* Clear out each window's back & forward lists. Also, remove
1816         * each window's current location bookmark from history list
1817         * so it doesn't get clobbered.
1818         */
1819        for (window_node = nautilus_application_get_window_list ();
1820             window_node != NULL;
1821             window_node = window_node->next) {
1822
1823                window = NAUTILUS_WINDOW (window_node->data);
1824
1825                nautilus_window_clear_back_list (window);
1826                nautilus_window_clear_forward_list (window);
1827
1828                nautilus_window_allow_back (window, FALSE);
1829                nautilus_window_allow_forward (window, FALSE);
1830
1831                history_list = g_list_remove (history_list, window->current_location_bookmark);
1832        }
1833
1834        /* Clobber history list. */
1835        free_history_list ();
1836
1837        /* Re-add each window's current location to history list. */
1838        for (window_node = nautilus_application_get_window_list ();
1839             window_node != NULL;
1840             window_node = window_node->next) {
1841
1842                window = NAUTILUS_WINDOW (window_node->data);
1843                nautilus_window_add_current_location_to_history_list (window);
1844        }
1845}
1846
1847GList *
1848nautilus_get_history_list (void)
1849{
1850        return history_list;
1851}
1852
1853void
1854nautilus_window_display_error (NautilusWindow *window, const char *error_msg)
1855{
1856        GtkWidget *dialog;
1857       
1858        dialog = gtk_message_dialog_new (GTK_WINDOW (window), 0, GTK_MESSAGE_ERROR,
1859                                         GTK_BUTTONS_CLOSE, error_msg, NULL);
1860        gtk_widget_show (dialog);
1861}
1862
1863void
1864nautilus_window_set_content_view_widget (NautilusWindow *window,
1865                                         NautilusViewFrame *new_view)
1866{
1867        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1868        g_return_if_fail (new_view == NULL || NAUTILUS_IS_VIEW_FRAME (new_view));
1869       
1870        if (new_view == window->content_view) {
1871                return;
1872        }
1873       
1874        if (window->content_view != NULL) {
1875                gtk_object_destroy (GTK_OBJECT (window->content_view));
1876                window->content_view = NULL;
1877        }
1878
1879        if (new_view != NULL) {
1880                gtk_widget_show (GTK_WIDGET (new_view));
1881
1882                /* When creating the desktop window the UI needs to
1883                 * be in sync. Otherwise I get failed assertions in
1884                 * bonobo while trying to reference something called
1885                 * `/commands/Unmount Volume Conditional'
1886                 */
1887                nautilus_window_ui_update (window);
1888
1889                /* FIXME bugzilla.gnome.org 41243:
1890                 * We should use inheritance instead of these special cases
1891                 * for the desktop window.
1892                 */
1893                if (!GTK_IS_PANED (window->content_hbox)) {
1894                        gtk_container_add (GTK_CONTAINER (window->content_hbox),
1895                                           GTK_WIDGET (new_view));
1896                } else {
1897                        nautilus_horizontal_splitter_pack2 (
1898                                NAUTILUS_HORIZONTAL_SPLITTER (window->content_hbox),
1899                                GTK_WIDGET (new_view));
1900                }
1901        }
1902
1903        /* Display or hide zoom control */
1904        if (new_view != NULL && nautilus_view_frame_get_is_zoomable (new_view)) {
1905                gtk_widget_show (window->zoom_control);
1906        } else {
1907                gtk_widget_hide (window->zoom_control);
1908        }
1909
1910        window->content_view = new_view;
1911}
1912
1913/**
1914 * add_sidebar_panels:
1915 * @window:     A NautilusWindow
1916 *
1917 * Adds all sidebars available
1918 *
1919 */
1920static void
1921add_sidebar_panels (NautilusWindow *window)
1922{
1923        GList *identifier_list;
1924
1925        g_assert (NAUTILUS_IS_WINDOW (window));
1926
1927        if (window->sidebar == NULL) {
1928                return;
1929        }
1930
1931        identifier_list = nautilus_sidebar_get_all_sidebar_panel_view_identifiers ();
1932        nautilus_window_set_sidebar_panels (window, identifier_list);
1933        nautilus_view_identifier_list_free (identifier_list);
1934}
1935
1936static void
1937show_dock_item (NautilusWindow *window, const char *dock_item_path)
1938{
1939        if (NAUTILUS_IS_DESKTOP_WINDOW (window)) {
1940                return;
1941        }
1942
1943        nautilus_window_ui_freeze (window);
1944
1945        nautilus_bonobo_set_hidden (window->details->shell_ui,
1946                                    dock_item_path,
1947                                    FALSE);
1948        nautilus_window_update_show_hide_menu_items (window);
1949
1950        nautilus_window_ui_thaw (window);
1951}
1952
1953static void
1954hide_dock_item (NautilusWindow *window, const char *dock_item_path)
1955{
1956        nautilus_window_ui_freeze (window);
1957
1958        nautilus_bonobo_set_hidden (window->details->shell_ui,
1959                                    dock_item_path,
1960                                    TRUE);
1961        nautilus_window_update_show_hide_menu_items (window);
1962
1963        nautilus_window_ui_thaw (window);
1964}
1965
1966static gboolean
1967dock_item_showing (NautilusWindow *window, const char *dock_item_path)
1968{
1969        return !nautilus_bonobo_get_hidden (window->details->shell_ui,
1970                                            dock_item_path);
1971}
1972
1973void
1974nautilus_window_hide_location_bar (NautilusWindow *window)
1975{
1976        window->details->temporary_navigation_bar = FALSE;
1977        hide_dock_item (window, LOCATION_BAR_PATH);
1978        eel_preferences_set_boolean (NAUTILUS_PREFERENCES_START_WITH_LOCATION_BAR, FALSE);
1979}
1980
1981void
1982nautilus_window_show_location_bar (NautilusWindow *window)
1983{
1984        show_dock_item (window, LOCATION_BAR_PATH);
1985        eel_preferences_set_boolean (NAUTILUS_PREFERENCES_START_WITH_LOCATION_BAR, TRUE);
1986}
1987
1988gboolean
1989nautilus_window_location_bar_showing (NautilusWindow *window)
1990{
1991        return dock_item_showing (window, LOCATION_BAR_PATH);
1992}
1993
1994void
1995nautilus_window_hide_toolbar (NautilusWindow *window)
1996{
1997        hide_dock_item (window, TOOLBAR_PATH);
1998        eel_preferences_set_boolean (NAUTILUS_PREFERENCES_START_WITH_TOOLBAR, FALSE);
1999}
2000
2001void
2002nautilus_window_show_toolbar (NautilusWindow *window)
2003{
2004        nautilus_window_activate_throbber (window);
2005        show_dock_item (window, TOOLBAR_PATH);
2006        eel_preferences_set_boolean (NAUTILUS_PREFERENCES_START_WITH_TOOLBAR, TRUE);
2007}
2008
2009gboolean
2010nautilus_window_toolbar_showing (NautilusWindow *window)
2011{
2012        return dock_item_showing (window, TOOLBAR_PATH);
2013}
2014
2015void
2016nautilus_window_hide_sidebar (NautilusWindow *window)
2017{
2018        if (NAUTILUS_IS_DESKTOP_WINDOW (window) || window->sidebar == NULL) {
2019                return;
2020        }
2021
2022        nautilus_window_tear_down_sidebar (window);
2023        nautilus_window_update_show_hide_menu_items (window);
2024        eel_preferences_set_boolean (NAUTILUS_PREFERENCES_START_WITH_SIDEBAR, FALSE);
2025}
2026
2027void
2028nautilus_window_show_sidebar (NautilusWindow *window)
2029{
2030        if (NAUTILUS_IS_DESKTOP_WINDOW (window) || window->sidebar != NULL) {
2031                return;
2032        }
2033
2034        nautilus_window_set_up_sidebar (window);
2035        nautilus_window_update_show_hide_menu_items (window);
2036        eel_preferences_set_boolean (NAUTILUS_PREFERENCES_START_WITH_SIDEBAR, TRUE);
2037}
2038
2039gboolean
2040nautilus_window_sidebar_showing (NautilusWindow *window)
2041{
2042        g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), FALSE);
2043
2044        return (window->sidebar != NULL) && GTK_IS_PANED (window->content_hbox)
2045                && nautilus_horizontal_splitter_is_hidden (NAUTILUS_HORIZONTAL_SPLITTER (window->content_hbox));
2046}
2047
2048void
2049nautilus_window_hide_status_bar (NautilusWindow *window)
2050{
2051        hide_dock_item (window, STATUS_BAR_PATH);
2052
2053        nautilus_window_update_show_hide_menu_items (window);
2054        eel_preferences_set_boolean (NAUTILUS_PREFERENCES_START_WITH_STATUS_BAR, FALSE);
2055}
2056
2057void
2058nautilus_window_show_status_bar (NautilusWindow *window)
2059{
2060        show_dock_item (window, STATUS_BAR_PATH);
2061
2062        nautilus_window_update_show_hide_menu_items (window);
2063        eel_preferences_set_boolean (NAUTILUS_PREFERENCES_START_WITH_STATUS_BAR, TRUE);
2064}
2065
2066gboolean
2067nautilus_window_status_bar_showing (NautilusWindow *window)
2068{
2069        return dock_item_showing (window, STATUS_BAR_PATH);
2070}
2071
2072/**
2073 * nautilus_window_get_base_page_index:
2074 * @window:     Window to get index from
2075 *
2076 * Returns the index of the base page in the history list.
2077 * Base page is not the currently displayed page, but the page
2078 * that acts as the base from which the back and forward commands
2079 * navigate from.
2080 */
2081gint
2082nautilus_window_get_base_page_index (NautilusWindow *window)
2083{
2084        gint forward_count;
2085       
2086        forward_count = g_list_length (window->forward_list);
2087
2088        /* If forward is empty, the base it at the top of the list */
2089        if (forward_count == 0) {
2090                return 0;
2091        }
2092
2093        /* The forward count indicate the relative postion of the base page
2094         * in the history list
2095         */
2096        return forward_count;
2097}
2098
2099/**
2100 * nautilus_window_show:
2101 * @widget:     GtkWidget
2102 *
2103 * Call parent and then show/hide window items
2104 * base on user prefs.
2105 */
2106static void
2107nautilus_window_show (GtkWidget *widget)
2108{       
2109        NautilusWindow *window;
2110
2111        window = NAUTILUS_WINDOW (widget);
2112
2113        GTK_WIDGET_CLASS (parent_class)->show (widget);
2114       
2115        /* Initially show or hide views based on preferences; once the window is displayed
2116         * these can be controlled on a per-window basis from View menu items.
2117         */
2118        if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_START_WITH_TOOLBAR)) {
2119                nautilus_window_show_toolbar (window);
2120        } else {
2121                nautilus_window_hide_toolbar (window);
2122        }
2123
2124        if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_START_WITH_LOCATION_BAR)) {
2125                nautilus_window_show_location_bar (window);
2126        } else {
2127                nautilus_window_hide_location_bar (window);
2128        }
2129
2130        if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_START_WITH_STATUS_BAR)) {
2131                nautilus_window_show_status_bar (window);
2132        } else {
2133                nautilus_window_hide_status_bar (window);
2134        }
2135
2136        if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_START_WITH_SIDEBAR)) {
2137                nautilus_window_show_sidebar (window);
2138        } else {
2139                nautilus_window_hide_sidebar (window);
2140        }
2141
2142        nautilus_window_ui_update (window);
2143}
2144
2145Bonobo_UIContainer
2146nautilus_window_get_ui_container (NautilusWindow *window)
2147{
2148        g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), CORBA_OBJECT_NIL);
2149
2150        return BONOBO_OBJREF (window->details->ui_container);
2151}
2152
2153void
2154nautilus_window_set_viewed_file (NautilusWindow *window,
2155                                 NautilusFile *file)
2156{
2157        GList *attributes;
2158
2159        if (window->details->viewed_file == file) {
2160                return;
2161        }
2162
2163        nautilus_file_ref (file);
2164
2165        cancel_view_as_callback (window);
2166        cancel_chose_component_callback (window);
2167
2168        if (window->details->viewed_file != NULL) {
2169                nautilus_file_monitor_remove (window->details->viewed_file,
2170                                              window);
2171        }
2172
2173        if (file != NULL) {
2174                attributes = g_list_prepend (NULL, NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME);
2175                nautilus_file_monitor_add (file, window, attributes);
2176                g_list_free (attributes);
2177        }
2178
2179        nautilus_file_unref (window->details->viewed_file);
2180        window->details->viewed_file = file;
2181}
2182
2183static void
2184nautilus_window_class_init (NautilusWindowClass *class)
2185{
2186        G_OBJECT_CLASS (class)->finalize = nautilus_window_finalize;
2187        G_OBJECT_CLASS (class)->get_property = nautilus_window_get_property;
2188        G_OBJECT_CLASS (class)->set_property = nautilus_window_set_property;
2189        GTK_OBJECT_CLASS (class)->destroy = nautilus_window_destroy;
2190        GTK_WIDGET_CLASS (class)->show = nautilus_window_show;
2191        GTK_WIDGET_CLASS (class)->unrealize = nautilus_window_unrealize;
2192        GTK_WIDGET_CLASS (class)->size_request = nautilus_window_size_request;
2193        class->add_current_location_to_history_list = real_add_current_location_to_history_list;
2194       
2195        g_object_class_install_property (G_OBJECT_CLASS (class),
2196                                         ARG_APP_ID,
2197                                         g_param_spec_string ("app_id",
2198                                                              _("Application ID"),
2199                                                              _("The application ID of the window."),
2200                                                              NULL,
2201                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
2202        g_object_class_install_property (G_OBJECT_CLASS (class),
2203                                         ARG_APP,
2204                                         g_param_spec_object ("app",
2205                                                              _("Application"),
2206                                                              _("The NautilusApplication associated with this window."),
2207                                                              NAUTILUS_TYPE_APPLICATION,
2208                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
2209       
2210        /* Set default for all windows. This probably should be done
2211         * in main or NautilusApplication rather than here in case
2212         * some other window is created before the first
2213         * NautilusWindow. Also, do we really want this icon for
2214         * dialogs?
2215         */
2216        set_up_default_icon_list ();
2217}
Note: See TracBrowser for help on using the repository browser.