1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6
* Copyright (C) 1999, 2000, 2004 Red Hat, Inc.
7
* Copyright (C) 1999, 2000, 2001 Eazel, Inc.
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.
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.
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.
23
* Authors: Elliot Lee <sopwith@redhat.com>
24
* John Sullivan <sullivan@eazel.com>
25
* Alexander Larsson <alexl@redhat.com>
28
/* nautilus-window.c: Implementation of the main window object */
32
#include "nautilus-window-private.h"
34
#include "nautilus-actions.h"
35
#include "nautilus-application.h"
36
#include "nautilus-bookmarks-window.h"
37
#include "nautilus-location-bar.h"
38
#include "nautilus-mime-actions.h"
39
#include "nautilus-notebook.h"
40
#include "nautilus-desktop-window.h"
41
#include "nautilus-places-sidebar.h"
42
#include "nautilus-search-bar.h"
43
#include "nautilus-tree-sidebar.h"
44
#include "nautilus-view-factory.h"
45
#include "nautilus-window-manage-views.h"
46
#include "nautilus-window-bookmarks.h"
47
#include "nautilus-window-slot.h"
49
#include <eel/eel-debug.h>
50
#include <eel/eel-gtk-extensions.h>
51
#include <eel/eel-string.h>
52
#include <gdk-pixbuf/gdk-pixbuf.h>
54
#include <gdk/gdkkeysyms.h>
56
#include <glib/gi18n.h>
57
#ifdef HAVE_X11_XF86KEYSYM_H
58
#include <X11/XF86keysym.h>
60
#include <libnautilus-private/nautilus-file-utilities.h>
61
#include <libnautilus-private/nautilus-file-attributes.h>
62
#include <libnautilus-private/nautilus-global-preferences.h>
63
#include <libnautilus-private/nautilus-metadata.h>
64
#include <libnautilus-private/nautilus-program-choosing.h>
65
#include <libnautilus-private/nautilus-clipboard.h>
66
#include <libnautilus-private/nautilus-undo.h>
67
#include <libnautilus-private/nautilus-search-directory.h>
68
#include <libnautilus-private/nautilus-signaller.h>
70
#define DEBUG_FLAG NAUTILUS_DEBUG_WINDOW
71
#include <libnautilus-private/nautilus-debug.h>
76
#define SIDE_PANE_MINIMUM_WIDTH 1
77
#define SIDE_PANE_MINIMUM_HEIGHT 400
81
#define NAUTILUS_MENU_PATH_EXTRA_VIEWER_PLACEHOLDER "/MenuBar/View/View Choices/Extra Viewer"
82
#define NAUTILUS_MENU_PATH_SHORT_LIST_PLACEHOLDER "/MenuBar/View/View Choices/Short List"
83
#define NAUTILUS_MENU_PATH_AFTER_SHORT_LIST_SEPARATOR "/MenuBar/View/View Choices/After Short List"
85
#define MAX_TITLE_LENGTH 180
87
#define MENU_PATH_BOOKMARKS_PLACEHOLDER "/MenuBar/Other Menus/Bookmarks/Bookmarks Placeholder"
89
/* Forward and back buttons on the mouse */
90
static gboolean mouse_extra_buttons = TRUE;
91
static int mouse_forward_button = 9;
92
static int mouse_back_button = 8;
94
static void mouse_back_button_changed (gpointer callback_data);
95
static void mouse_forward_button_changed (gpointer callback_data);
96
static void use_extra_mouse_buttons_changed (gpointer callback_data);
98
/* Sanity check: highest mouse button value I could find was 14. 5 is our
99
* lower threshold (well-documented to be the one of the button events for the
100
* scrollwheel), so it's hardcoded in the functions below. However, if you have
101
* a button that registers higher and want to map it, file a bug and
102
* we'll move the bar. Makes you wonder why the X guys don't have
103
* defined values for these like the XKB stuff, huh?
105
#define UPPER_MOUSE_LIMIT 14
108
PROP_DISABLE_CHROME = 1,
119
HIDDEN_FILES_MODE_CHANGED,
123
static guint signals[LAST_SIGNAL] = { 0 };
124
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
127
NautilusWindow *window;
131
static void cancel_view_as_callback (NautilusWindowSlot *slot);
132
static void action_view_as_callback (GtkAction *action,
133
ActivateViewData *data);
135
G_DEFINE_TYPE (NautilusWindow, nautilus_window, GTK_TYPE_WINDOW);
137
static const struct {
140
} extra_window_keybindings [] = {
141
#ifdef HAVE_X11_XF86KEYSYM_H
142
{ XF86XK_AddFavorite, NAUTILUS_ACTION_ADD_BOOKMARK },
143
{ XF86XK_Favorites, NAUTILUS_ACTION_EDIT_BOOKMARKS },
144
{ XF86XK_Go, NAUTILUS_ACTION_GO_TO_LOCATION },
145
{ XF86XK_HomePage, NAUTILUS_ACTION_GO_HOME },
146
{ XF86XK_OpenURL, NAUTILUS_ACTION_GO_TO_LOCATION },
147
{ XF86XK_Refresh, NAUTILUS_ACTION_RELOAD },
148
{ XF86XK_Reload, NAUTILUS_ACTION_RELOAD },
149
{ XF86XK_Search, NAUTILUS_ACTION_SEARCH },
150
{ XF86XK_Start, NAUTILUS_ACTION_GO_HOME },
151
{ XF86XK_Stop, NAUTILUS_ACTION_STOP },
152
{ XF86XK_ZoomIn, NAUTILUS_ACTION_ZOOM_IN },
153
{ XF86XK_ZoomOut, NAUTILUS_ACTION_ZOOM_OUT },
154
{ XF86XK_Back, NAUTILUS_ACTION_BACK },
155
{ XF86XK_Forward, NAUTILUS_ACTION_FORWARD }
160
/* Unconditionally synchronize the GtkUIManager of WINDOW. */
162
nautilus_window_ui_update (NautilusWindow *window)
164
g_assert (NAUTILUS_IS_WINDOW (window));
166
gtk_ui_manager_ensure_update (window->details->ui_manager);
170
nautilus_window_push_status (NautilusWindow *window,
173
g_return_if_fail (NAUTILUS_IS_WINDOW (window));
175
/* clear any previous message, underflow is allowed */
176
gtk_statusbar_pop (GTK_STATUSBAR (window->details->statusbar), 0);
178
if (text != NULL && text[0] != '\0') {
179
gtk_statusbar_push (GTK_STATUSBAR (window->details->statusbar), 0, text);
184
nautilus_window_sync_status (NautilusWindow *window)
186
NautilusWindowSlot *slot;
188
slot = window->details->active_pane->active_slot;
189
nautilus_window_push_status (window, slot->status_text);
193
nautilus_window_go_to (NautilusWindow *window, GFile *location)
195
g_return_if_fail (NAUTILUS_IS_WINDOW (window));
197
nautilus_window_slot_go_to (window->details->active_pane->active_slot, location, FALSE);
201
nautilus_window_go_to_full (NautilusWindow *window,
203
NautilusWindowGoToCallback callback,
206
g_return_if_fail (NAUTILUS_IS_WINDOW (window));
208
nautilus_window_slot_go_to_full (window->details->active_pane->active_slot, location, FALSE, callback, user_data);
212
nautilus_window_go_up_signal (NautilusWindow *window, gboolean close_behind)
214
nautilus_window_slot_go_up (nautilus_window_get_active_slot (window),
215
close_behind, FALSE);
221
nautilus_window_new_tab (NautilusWindow *window)
223
NautilusWindowSlot *current_slot;
224
NautilusWindowSlot *new_slot;
225
NautilusWindowOpenFlags flags;
227
int new_slot_position;
230
current_slot = window->details->active_pane->active_slot;
231
location = nautilus_window_slot_get_location (current_slot);
233
if (location != NULL) {
236
new_slot_position = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION);
237
if (new_slot_position == NAUTILUS_NEW_TAB_POSITION_END) {
238
flags = NAUTILUS_WINDOW_OPEN_SLOT_APPEND;
241
scheme = g_file_get_uri_scheme (location);
242
if (!strcmp (scheme, "x-nautilus-search")) {
243
g_object_unref (location);
244
location = g_file_new_for_path (g_get_home_dir ());
248
new_slot = nautilus_window_open_slot (current_slot->pane, flags);
249
nautilus_window_set_active_slot (window, new_slot);
250
nautilus_window_slot_go_to (new_slot, location, FALSE);
251
g_object_unref (location);
256
nautilus_window_allow_up (NautilusWindow *window, gboolean allow)
260
g_assert (NAUTILUS_IS_WINDOW (window));
262
action = gtk_action_group_get_action (window->details->main_action_group,
264
gtk_action_set_sensitive (action, allow);
265
action = gtk_action_group_get_action (window->details->main_action_group,
266
NAUTILUS_ACTION_UP_ACCEL);
267
gtk_action_set_sensitive (action, allow);
271
update_cursor (NautilusWindow *window)
273
NautilusWindowSlot *slot;
276
slot = window->details->active_pane->active_slot;
278
if (slot->allow_stop) {
279
cursor = gdk_cursor_new (GDK_WATCH);
280
gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), cursor);
281
g_object_unref (cursor);
283
gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
288
nautilus_window_sync_allow_stop (NautilusWindow *window,
289
NautilusWindowSlot *slot)
293
NautilusNotebook *notebook;
295
g_assert (NAUTILUS_IS_WINDOW (window));
297
action = gtk_action_group_get_action (window->details->main_action_group,
298
NAUTILUS_ACTION_STOP);
299
allow_stop = gtk_action_get_sensitive (action);
301
if (slot != window->details->active_pane->active_slot ||
302
allow_stop != slot->allow_stop) {
303
if (slot == window->details->active_pane->active_slot) {
304
gtk_action_set_sensitive (action, slot->allow_stop);
307
if (gtk_widget_get_realized (GTK_WIDGET (window))) {
308
update_cursor (window);
312
notebook = NAUTILUS_NOTEBOOK (slot->pane->notebook);
313
nautilus_notebook_sync_loading (notebook, slot);
318
nautilus_window_prompt_for_location (NautilusWindow *window,
321
NautilusWindowPane *pane;
323
g_return_if_fail (NAUTILUS_IS_WINDOW (window));
325
pane = window->details->active_pane;
326
nautilus_window_pane_ensure_location_bar (pane);
329
nautilus_location_bar_set_location (NAUTILUS_LOCATION_BAR (pane->location_bar),
334
/* Code should never force the window taller than this size.
335
* (The user can still stretch the window taller if desired).
338
get_max_forced_height (GdkScreen *screen)
340
return (gdk_screen_get_height (screen) * 90) / 100;
343
/* Code should never force the window wider than this size.
344
* (The user can still stretch the window wider if desired).
347
get_max_forced_width (GdkScreen *screen)
349
return (gdk_screen_get_width (screen) * 90) / 100;
352
/* This must be called when construction of NautilusWindow is finished,
353
* since it depends on the type of the argument, which isn't decided at
357
nautilus_window_set_initial_window_geometry (NautilusWindow *window)
360
guint max_width_for_screen, max_height_for_screen;
361
guint default_width, default_height;
363
screen = gtk_window_get_screen (GTK_WINDOW (window));
365
max_width_for_screen = get_max_forced_width (screen);
366
max_height_for_screen = get_max_forced_height (screen);
368
default_width = NAUTILUS_WINDOW_DEFAULT_WIDTH;
369
default_height = NAUTILUS_WINDOW_DEFAULT_HEIGHT;
371
gtk_window_set_default_size (GTK_WINDOW (window),
373
max_width_for_screen),
375
max_height_for_screen));
379
save_sidebar_width_cb (gpointer user_data)
381
NautilusWindow *window = user_data;
383
window->details->sidebar_width_handler_id = 0;
385
DEBUG ("Saving sidebar width: %d", window->details->side_pane_width);
387
g_settings_set_int (nautilus_window_state,
388
NAUTILUS_WINDOW_STATE_SIDEBAR_WIDTH,
389
window->details->side_pane_width);
394
/* side pane helpers */
396
side_pane_size_allocate_callback (GtkWidget *widget,
397
GtkAllocation *allocation,
400
NautilusWindow *window;
404
if (window->details->sidebar_width_handler_id != 0) {
405
g_source_remove (window->details->sidebar_width_handler_id);
406
window->details->sidebar_width_handler_id = 0;
409
if (allocation->width != window->details->side_pane_width &&
410
allocation->width > 1) {
411
window->details->side_pane_width = allocation->width;
413
window->details->sidebar_width_handler_id =
414
g_idle_add (save_sidebar_width_cb, window);
419
setup_side_pane_width (NautilusWindow *window)
421
g_return_if_fail (window->details->sidebar != NULL);
423
window->details->side_pane_width =
424
g_settings_get_int (nautilus_window_state,
425
NAUTILUS_WINDOW_STATE_SIDEBAR_WIDTH);
427
gtk_paned_set_position (GTK_PANED (window->details->content_paned),
428
window->details->side_pane_width);
432
sidebar_id_is_valid (const gchar *sidebar_id)
434
return (g_strcmp0 (sidebar_id, NAUTILUS_WINDOW_SIDEBAR_PLACES) == 0 ||
435
g_strcmp0 (sidebar_id, NAUTILUS_WINDOW_SIDEBAR_TREE) == 0);
439
nautilus_window_set_up_sidebar (NautilusWindow *window)
443
DEBUG ("Setting up sidebar id %s", window->details->sidebar_id);
445
window->details->sidebar = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
446
gtk_style_context_add_class (gtk_widget_get_style_context (window->details->sidebar),
447
GTK_STYLE_CLASS_SIDEBAR);
449
gtk_paned_pack1 (GTK_PANED (window->details->content_paned),
450
GTK_WIDGET (window->details->sidebar),
453
setup_side_pane_width (window);
454
g_signal_connect (window->details->sidebar,
456
G_CALLBACK (side_pane_size_allocate_callback),
459
if (g_strcmp0 (window->details->sidebar_id, NAUTILUS_WINDOW_SIDEBAR_PLACES) == 0) {
460
sidebar = nautilus_places_sidebar_new (window);
461
} else if (g_strcmp0 (window->details->sidebar_id, NAUTILUS_WINDOW_SIDEBAR_TREE) == 0) {
462
sidebar = nautilus_tree_sidebar_new (window);
464
g_assert_not_reached ();
467
gtk_box_pack_start (GTK_BOX (window->details->sidebar), sidebar, TRUE, TRUE, 0);
468
gtk_widget_show (sidebar);
469
gtk_widget_show (GTK_WIDGET (window->details->sidebar));
473
nautilus_window_tear_down_sidebar (NautilusWindow *window)
475
DEBUG ("Destroying sidebar");
477
gtk_widget_destroy (GTK_WIDGET (window->details->sidebar));
478
window->details->sidebar = NULL;
482
nautilus_window_hide_sidebar (NautilusWindow *window)
484
DEBUG ("Called hide_sidebar()");
486
if (window->details->sidebar == NULL) {
490
nautilus_window_tear_down_sidebar (window);
491
nautilus_window_update_show_hide_menu_items (window);
493
g_settings_set_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_START_WITH_SIDEBAR, FALSE);
497
nautilus_window_show_sidebar (NautilusWindow *window)
499
DEBUG ("Called show_sidebar()");
501
if (window->details->sidebar != NULL) {
505
if (window->details->disable_chrome) {
509
nautilus_window_set_up_sidebar (window);
510
nautilus_window_update_show_hide_menu_items (window);
511
g_settings_set_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_START_WITH_SIDEBAR, TRUE);
515
side_pane_id_changed (NautilusWindow *window)
519
sidebar_id = g_settings_get_string (nautilus_window_state,
520
NAUTILUS_WINDOW_STATE_SIDE_PANE_VIEW);
522
DEBUG ("Sidebar id changed to %s", sidebar_id);
524
if (g_strcmp0 (sidebar_id, window->details->sidebar_id) == 0) {
529
if (!sidebar_id_is_valid (sidebar_id)) {
534
g_free (window->details->sidebar_id);
535
window->details->sidebar_id = sidebar_id;
537
if (window->details->sidebar != NULL) {
538
/* refresh the sidebar setting */
539
nautilus_window_tear_down_sidebar (window);
540
nautilus_window_set_up_sidebar (window);
545
nautilus_window_disable_chrome_mapping (GValue *value,
549
NautilusWindow *window = user_data;
551
g_value_set_boolean (value,
552
g_variant_get_boolean (variant) &&
553
!window->details->disable_chrome);
559
nautilus_window_constructed (GObject *self)
561
NautilusWindow *window;
564
GtkWidget *statusbar;
567
NautilusWindowPane *pane;
568
NautilusWindowSlot *slot;
569
NautilusApplication *application;
571
window = NAUTILUS_WINDOW (self);
572
application = nautilus_application_get_singleton ();
574
G_OBJECT_CLASS (nautilus_window_parent_class)->constructed (self);
576
table = gtk_table_new (1, 6, FALSE);
577
window->details->table = table;
578
gtk_widget_show (table);
579
gtk_container_add (GTK_CONTAINER (window), table);
581
statusbar = gtk_statusbar_new ();
582
window->details->statusbar = statusbar;
583
window->details->help_message_cid = gtk_statusbar_get_context_id
584
(GTK_STATUSBAR (statusbar), "help_message");
585
/* Statusbar is packed in the subclasses */
587
nautilus_window_initialize_menus (window);
588
nautilus_window_initialize_actions (window);
590
menu = gtk_ui_manager_get_widget (window->details->ui_manager, "/MenuBar");
591
window->details->menubar = menu;
592
gtk_widget_show (menu);
593
gtk_table_attach (GTK_TABLE (table),
595
/* X direction */ /* Y direction */
597
GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0,
600
/* Register to menu provider extension signal managing menu updates */
601
g_signal_connect_object (nautilus_signaller_get_current (), "popup_menu_changed",
602
G_CALLBACK (nautilus_window_load_extension_menus), window, G_CONNECT_SWAPPED);
604
window->details->content_paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
605
gtk_table_attach (GTK_TABLE (window->details->table),
606
window->details->content_paned,
607
/* X direction */ /* Y direction */
609
GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_EXPAND | GTK_FILL | GTK_SHRINK,
611
gtk_widget_show (window->details->content_paned);
613
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
614
gtk_paned_pack2 (GTK_PANED (window->details->content_paned), vbox,
616
gtk_widget_show (vbox);
618
hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
619
gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
620
gtk_widget_show (hpaned);
621
window->details->split_view_hpane = hpaned;
623
gtk_box_pack_start (GTK_BOX (vbox), window->details->statusbar, FALSE, FALSE, 0);
625
g_settings_bind_with_mapping (nautilus_window_state,
626
NAUTILUS_WINDOW_STATE_START_WITH_STATUS_BAR,
627
window->details->statusbar,
629
G_SETTINGS_BIND_DEFAULT,
630
nautilus_window_disable_chrome_mapping, NULL,
633
pane = nautilus_window_pane_new (window);
634
window->details->panes = g_list_prepend (window->details->panes, pane);
636
gtk_paned_pack1 (GTK_PANED (hpaned), pane->widget, TRUE, FALSE);
637
gtk_widget_show (pane->widget);
639
/* this has to be done after the location bar has been set up,
640
* but before menu stuff is being called */
641
nautilus_window_set_active_pane (window, pane);
643
g_signal_connect_swapped (nautilus_window_state,
644
"changed::" NAUTILUS_WINDOW_STATE_SIDE_PANE_VIEW,
645
G_CALLBACK (side_pane_id_changed),
648
side_pane_id_changed (window);
650
nautilus_window_initialize_bookmarks_menu (window);
651
nautilus_window_set_initial_window_geometry (window);
652
nautilus_undo_manager_attach (application->undo_manager, G_OBJECT (window));
654
slot = nautilus_window_open_slot (window->details->active_pane, 0);
655
nautilus_window_set_active_slot (window, slot);
659
nautilus_window_set_property (GObject *object,
664
NautilusWindow *window;
666
window = NAUTILUS_WINDOW (object);
669
case PROP_DISABLE_CHROME:
670
window->details->disable_chrome = g_value_get_boolean (value);
673
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
679
nautilus_window_get_property (GObject *object,
684
NautilusWindow *window;
686
window = NAUTILUS_WINDOW (object);
689
case PROP_DISABLE_CHROME:
690
g_value_set_boolean (value, window->details->disable_chrome);
696
free_stored_viewers (NautilusWindow *window)
698
g_list_free_full (window->details->short_list_viewers, g_free);
699
window->details->short_list_viewers = NULL;
700
g_free (window->details->extra_viewer);
701
window->details->extra_viewer = NULL;
705
nautilus_window_destroy (GtkWidget *object)
707
NautilusWindow *window;
710
window = NAUTILUS_WINDOW (object);
712
window->details->content_paned = NULL;
713
window->details->split_view_hpane = NULL;
715
/* close all panes safely */
716
panes_copy = g_list_copy (window->details->panes);
717
g_list_foreach (panes_copy, (GFunc) nautilus_window_close_pane, NULL);
718
g_list_free (panes_copy);
720
/* the panes list should now be empty */
721
g_assert (window->details->panes == NULL);
722
g_assert (window->details->active_pane == NULL);
724
GTK_WIDGET_CLASS (nautilus_window_parent_class)->destroy (object);
728
nautilus_window_finalize (GObject *object)
730
NautilusWindow *window;
732
window = NAUTILUS_WINDOW (object);
734
if (window->details->sidebar_width_handler_id != 0) {
735
g_source_remove (window->details->sidebar_width_handler_id);
736
window->details->sidebar_width_handler_id = 0;
739
g_free (window->details->sidebar_id);
740
g_clear_object (&window->details->nav_state);
742
nautilus_window_remove_trash_monitor_callback (window);
743
free_stored_viewers (window);
745
if (window->details->bookmark_list != NULL) {
746
g_object_unref (window->details->bookmark_list);
749
g_signal_handlers_disconnect_by_func (nautilus_window_state,
750
side_pane_id_changed, window);
752
/* nautilus_window_close() should have run */
753
g_assert (window->details->panes == NULL);
755
g_object_unref (window->details->ui_manager);
757
G_OBJECT_CLASS (nautilus_window_parent_class)->finalize (object);
761
nautilus_window_show_window (NautilusWindow *window)
763
NautilusWindowSlot *slot;
764
NautilusWindowPane *pane;
767
for (walk = window->details->panes; walk; walk = walk->next) {
769
for (l = pane->slots; l != NULL; l = l->next) {
772
nautilus_window_slot_update_title (slot);
773
nautilus_window_slot_update_icon (slot);
777
gtk_widget_show (GTK_WIDGET (window));
779
slot = window->details->active_pane->active_slot;
783
nautilus_window_view_visible (NautilusWindow *window,
786
NautilusWindowSlot *slot;
787
NautilusWindowPane *pane;
790
g_return_if_fail (NAUTILUS_IS_WINDOW (window));
792
slot = nautilus_window_get_slot_for_view (window, view);
793
nautilus_view_set_is_active (view, slot->pane->is_active);
799
slot->visible = TRUE;
807
/* Look for other non-visible slots */
808
for (l = pane->slots; l != NULL; l = l->next) {
811
if (!slot->visible) {
816
/* None, this pane is visible */
817
nautilus_window_pane_show (pane);
819
/* Look for other non-visible panes */
820
for (walk = window->details->panes; walk; walk = walk->next) {
823
if (!pane->visible) {
828
nautilus_window_pane_grab_focus (window->details->active_pane);
830
/* All slots and panes visible, show window */
831
nautilus_window_show_window (window);
835
nautilus_window_save_geometry (NautilusWindow *window)
837
char *geometry_string;
838
gboolean is_maximized;
840
g_assert (NAUTILUS_IS_WINDOW (window));
842
if (gtk_widget_get_window (GTK_WIDGET (window))) {
843
geometry_string = eel_gtk_window_get_geometry_string (GTK_WINDOW (window));
844
is_maximized = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)))
845
& GDK_WINDOW_STATE_MAXIMIZED;
848
g_settings_set_string
849
(nautilus_window_state, NAUTILUS_WINDOW_STATE_GEOMETRY,
852
g_free (geometry_string);
854
g_settings_set_boolean
855
(nautilus_window_state, NAUTILUS_WINDOW_STATE_MAXIMIZED,
861
nautilus_window_close (NautilusWindow *window)
863
NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->close (window);
867
nautilus_window_open_slot (NautilusWindowPane *pane,
868
NautilusWindowOpenSlotFlags flags)
870
NautilusWindowSlot *slot;
872
g_assert (NAUTILUS_IS_WINDOW_PANE (pane));
873
g_assert (NAUTILUS_IS_WINDOW (pane->window));
875
slot = (NautilusWindowSlot *) g_object_new (NAUTILUS_TYPE_WINDOW_SLOT, NULL);
878
nautilus_window_pane_add_slot_in_tab (pane, slot, flags);
879
gtk_widget_show (slot->content_box);
881
pane->slots = g_list_append (pane->slots, slot);
887
nautilus_window_close_pane (NautilusWindowPane *pane)
889
NautilusWindow *window;
891
g_assert (NAUTILUS_IS_WINDOW_PANE (pane));
892
g_assert (NAUTILUS_IS_WINDOW (pane->window));
893
g_assert (g_list_find (pane->window->details->panes, pane) != NULL);
895
while (pane->slots != NULL) {
896
NautilusWindowSlot *slot = pane->slots->data;
898
nautilus_window_close_slot (slot);
901
window = pane->window;
903
/* If the pane was active, set it to NULL. The caller is responsible
904
* for setting a new active pane with nautilus_window_pane_switch_to()
905
* if it wants to continue using the window. */
906
if (window->details->active_pane == pane) {
907
window->details->active_pane = NULL;
910
window->details->panes = g_list_remove (window->details->panes, pane);
912
g_object_unref (pane);
916
nautilus_window_close_slot (NautilusWindowSlot *slot)
918
NautilusWindowPane *pane;
920
GtkNotebook *notebook;
922
g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
923
g_assert (NAUTILUS_IS_WINDOW_PANE(slot->pane));
924
g_assert (g_list_find (slot->pane->slots, slot) != NULL);
926
/* save pane because slot is not valid anymore after this call */
928
notebook = GTK_NOTEBOOK (pane->notebook);
930
page_num = gtk_notebook_page_num (notebook, slot->content_box);
931
g_assert (page_num >= 0);
933
nautilus_window_pane_remove_page (pane, page_num);
935
gtk_notebook_set_show_tabs (notebook,
936
gtk_notebook_get_n_pages (notebook) > 1);
938
nautilus_window_manage_views_close_slot (pane, slot);
939
cancel_view_as_callback (slot);
941
g_object_run_dispose (G_OBJECT (slot));
943
g_object_unref (slot);
944
pane->slots = g_list_remove (pane->slots, slot);
948
nautilus_window_get_active_pane (NautilusWindow *window)
950
g_assert (NAUTILUS_IS_WINDOW (window));
951
return window->details->active_pane;
955
real_set_active_pane (NautilusWindow *window, NautilusWindowPane *new_pane)
957
/* make old pane inactive, and new one active.
958
* Currently active pane may be NULL (after init). */
959
if (window->details->active_pane &&
960
window->details->active_pane != new_pane) {
961
nautilus_window_pane_set_active (new_pane->window->details->active_pane, FALSE);
963
nautilus_window_pane_set_active (new_pane, TRUE);
965
window->details->active_pane = new_pane;
968
/* Make the given pane the active pane of its associated window. This
969
* always implies making the containing active slot the active slot of
972
nautilus_window_set_active_pane (NautilusWindow *window,
973
NautilusWindowPane *new_pane)
975
g_assert (NAUTILUS_IS_WINDOW_PANE (new_pane));
976
if (new_pane->active_slot) {
977
nautilus_window_set_active_slot (window, new_pane->active_slot);
978
} else if (new_pane != window->details->active_pane) {
979
real_set_active_pane (window, new_pane);
983
/* Make both, the given slot the active slot and its corresponding
984
* pane the active pane of the associated window.
985
* new_slot may be NULL. */
987
nautilus_window_set_active_slot (NautilusWindow *window, NautilusWindowSlot *new_slot)
989
NautilusWindowSlot *old_slot;
991
g_assert (NAUTILUS_IS_WINDOW (window));
994
g_assert (NAUTILUS_IS_WINDOW_SLOT (new_slot));
995
g_assert (NAUTILUS_IS_WINDOW_PANE (new_slot->pane));
996
g_assert (window == new_slot->pane->window);
997
g_assert (g_list_find (new_slot->pane->slots, new_slot) != NULL);
1000
if (window->details->active_pane != NULL) {
1001
old_slot = window->details->active_pane->active_slot;
1006
if (old_slot == new_slot) {
1010
/* make old slot inactive if it exists (may be NULL after init, for example) */
1011
if (old_slot != NULL) {
1013
if (old_slot->content_view != NULL) {
1014
nautilus_window_disconnect_content_view (window, old_slot->content_view);
1017
/* inform slot & view */
1018
g_signal_emit_by_name (old_slot, "inactive");
1021
/* deal with panes */
1023
new_slot->pane != window->details->active_pane) {
1024
real_set_active_pane (window, new_slot->pane);
1027
window->details->active_pane->active_slot = new_slot;
1029
/* make new slot active, if it exists */
1031
/* inform sidebar panels */
1032
nautilus_window_report_location_change (window);
1033
/* TODO decide whether "selection-changed" should be emitted */
1035
if (new_slot->content_view != NULL) {
1037
nautilus_window_connect_content_view (window, new_slot->content_view);
1040
/* inform slot & view */
1041
g_signal_emit_by_name (new_slot, "active");
1046
nautilus_window_get_preferred_width (GtkWidget *widget,
1047
gint *minimal_width,
1048
gint *natural_width)
1051
gint max_w, min_w, default_w;
1053
screen = gtk_window_get_screen (GTK_WINDOW (widget));
1055
max_w = get_max_forced_width (screen);
1056
min_w = NAUTILUS_WINDOW_MIN_WIDTH;
1058
default_w = NAUTILUS_WINDOW_DEFAULT_WIDTH;
1060
*minimal_width = MIN (min_w, max_w);
1061
*natural_width = MIN (default_w, max_w);
1065
nautilus_window_get_preferred_height (GtkWidget *widget,
1066
gint *minimal_height,
1067
gint *natural_height)
1070
gint max_h, min_h, default_h;
1072
screen = gtk_window_get_screen (GTK_WINDOW (widget));
1074
max_h = get_max_forced_height (screen);
1076
min_h = NAUTILUS_WINDOW_MIN_HEIGHT;
1078
default_h = NAUTILUS_WINDOW_DEFAULT_HEIGHT;
1080
*minimal_height = MIN (min_h, max_h);
1081
*natural_height = MIN (default_h, max_h);
1085
nautilus_window_realize (GtkWidget *widget)
1087
GTK_WIDGET_CLASS (nautilus_window_parent_class)->realize (widget);
1088
update_cursor (NAUTILUS_WINDOW (widget));
1092
nautilus_window_key_press_event (GtkWidget *widget,
1095
NautilusWindow *window;
1096
NautilusWindowSlot *active_slot;
1100
window = NAUTILUS_WINDOW (widget);
1102
active_slot = nautilus_window_get_active_slot (window);
1103
view = active_slot->content_view;
1105
if (view != NULL && nautilus_view_get_is_renaming (view)) {
1106
/* if we're renaming, just forward the event to the
1107
* focused widget and return. We don't want to process the window
1108
* accelerator bindings, as they might conflict with the
1109
* editable widget bindings.
1111
if (gtk_window_propagate_key_event (GTK_WINDOW (window), event)) {
1116
for (i = 0; i < G_N_ELEMENTS (extra_window_keybindings); i++) {
1117
if (extra_window_keybindings[i].keyval == event->keyval) {
1118
const GList *action_groups;
1123
action_groups = gtk_ui_manager_get_action_groups (window->details->ui_manager);
1124
while (action_groups != NULL && action == NULL) {
1125
action = gtk_action_group_get_action (action_groups->data, extra_window_keybindings[i].action);
1126
action_groups = action_groups->next;
1129
g_assert (action != NULL);
1130
if (gtk_action_is_sensitive (action)) {
1131
gtk_action_activate (action);
1139
return GTK_WIDGET_CLASS (nautilus_window_parent_class)->key_press_event (widget, event);
1147
free_activate_view_data (gpointer data)
1149
ActivateViewData *activate_data;
1151
activate_data = data;
1153
g_free (activate_data->id);
1155
g_slice_free (ActivateViewData, activate_data);
1159
action_view_as_callback (GtkAction *action,
1160
ActivateViewData *data)
1162
NautilusWindow *window;
1163
NautilusWindowSlot *slot;
1165
window = data->window;
1167
if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
1168
slot = window->details->active_pane->active_slot;
1169
nautilus_window_slot_set_content_view (slot,
1174
static GtkRadioAction *
1175
add_view_as_menu_item (NautilusWindow *window,
1176
const char *placeholder_path,
1177
const char *identifier,
1178
int index, /* extra_viewer is always index 0 */
1181
const NautilusViewInfo *info;
1182
GtkRadioAction *action;
1183
char action_name[32];
1184
ActivateViewData *data;
1187
char accel_path[48];
1188
unsigned int accel_keyval;
1190
info = nautilus_view_factory_lookup (identifier);
1192
g_snprintf (action_name, sizeof (action_name), "view_as_%d", index);
1193
action = gtk_radio_action_new (action_name,
1194
_(info->view_menu_label_with_mnemonic),
1195
_(info->display_location_label),
1199
if (index >= 1 && index <= 9) {
1200
g_snprintf (accel, sizeof (accel), "%d", index);
1201
g_snprintf (accel_path, sizeof (accel_path), "<Nautilus-Window>/%s", action_name);
1203
accel_keyval = gdk_keyval_from_name (accel);
1204
g_assert (accel_keyval != GDK_KEY_VoidSymbol);
1206
gtk_accel_map_add_entry (accel_path, accel_keyval, GDK_CONTROL_MASK);
1207
gtk_action_set_accel_path (GTK_ACTION (action), accel_path);
1210
if (window->details->view_as_radio_action != NULL) {
1211
gtk_radio_action_set_group (action,
1212
gtk_radio_action_get_group (window->details->view_as_radio_action));
1213
} else if (index != 0) {
1214
/* Index 0 is the extra view, and we don't want to use that here,
1215
as it can get deleted/changed later */
1216
window->details->view_as_radio_action = action;
1219
if (NAUTILUS_IS_DESKTOP_WINDOW(window)) {
1220
gtk_action_set_visible(GTK_ACTION(action), FALSE);
1223
data = g_slice_new (ActivateViewData);
1224
data->window = window;
1225
data->id = g_strdup (identifier);
1226
g_signal_connect_data (action, "activate",
1227
G_CALLBACK (action_view_as_callback),
1228
data, (GClosureNotify) free_activate_view_data, 0);
1230
gtk_action_group_add_action (window->details->view_as_action_group,
1231
GTK_ACTION (action));
1232
g_object_unref (action);
1234
gtk_ui_manager_add_ui (window->details->ui_manager,
1239
GTK_UI_MANAGER_MENUITEM,
1242
return action; /* return value owned by group */
1245
/* Make a special first item in the "View as" option menu that represents
1246
* the current content view. This should only be called if the current
1247
* content view isn't already in the "View as" option menu.
1250
update_extra_viewer_in_view_as_menus (NautilusWindow *window,
1253
gboolean had_extra_viewer;
1255
had_extra_viewer = window->details->extra_viewer != NULL;
1258
if (!had_extra_viewer) {
1262
if (had_extra_viewer
1263
&& strcmp (window->details->extra_viewer, id) == 0) {
1267
g_free (window->details->extra_viewer);
1268
window->details->extra_viewer = g_strdup (id);
1270
if (window->details->extra_viewer_merge_id != 0) {
1271
gtk_ui_manager_remove_ui (window->details->ui_manager,
1272
window->details->extra_viewer_merge_id);
1273
window->details->extra_viewer_merge_id = 0;
1276
if (window->details->extra_viewer_radio_action != NULL) {
1277
gtk_action_group_remove_action (window->details->view_as_action_group,
1278
GTK_ACTION (window->details->extra_viewer_radio_action));
1279
window->details->extra_viewer_radio_action = NULL;
1283
window->details->extra_viewer_merge_id = gtk_ui_manager_new_merge_id (window->details->ui_manager);
1284
window->details->extra_viewer_radio_action =
1285
add_view_as_menu_item (window,
1286
NAUTILUS_MENU_PATH_EXTRA_VIEWER_PLACEHOLDER,
1287
window->details->extra_viewer,
1289
window->details->extra_viewer_merge_id);
1294
remove_extra_viewer_in_view_as_menus (NautilusWindow *window)
1296
update_extra_viewer_in_view_as_menus (window, NULL);
1300
replace_extra_viewer_in_view_as_menus (NautilusWindow *window)
1302
NautilusWindowSlot *slot;
1305
slot = window->details->active_pane->active_slot;
1307
id = nautilus_window_slot_get_content_view_id (slot);
1308
update_extra_viewer_in_view_as_menus (window, id);
1312
* nautilus_window_synch_view_as_menus:
1314
* Set the visible item of the "View as" option menu and
1315
* the marked "View as" item in the View menu to
1316
* match the current content view.
1318
* @window: The NautilusWindow whose "View as" option menu should be synched.
1321
nautilus_window_synch_view_as_menus (NautilusWindow *window)
1323
NautilusWindowSlot *slot;
1325
char action_name[32];
1329
g_assert (NAUTILUS_IS_WINDOW (window));
1331
slot = window->details->active_pane->active_slot;
1333
if (slot->content_view == NULL) {
1336
for (node = window->details->short_list_viewers, index = 1;
1338
node = node->next, ++index) {
1339
if (nautilus_window_slot_content_view_matches_iid (slot, (char *)node->data)) {
1344
replace_extra_viewer_in_view_as_menus (window);
1347
remove_extra_viewer_in_view_as_menus (window);
1350
g_snprintf (action_name, sizeof (action_name), "view_as_%d", index);
1351
action = gtk_action_group_get_action (window->details->view_as_action_group,
1354
/* Don't trigger the action callback when we're synchronizing */
1355
g_signal_handlers_block_matched (action,
1356
G_SIGNAL_MATCH_FUNC,
1359
action_view_as_callback,
1361
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1362
g_signal_handlers_unblock_matched (action,
1363
G_SIGNAL_MATCH_FUNC,
1366
action_view_as_callback,
1371
refresh_stored_viewers (NautilusWindow *window)
1373
NautilusWindowSlot *slot;
1375
char *uri, *mimetype;
1377
slot = window->details->active_pane->active_slot;
1379
uri = nautilus_file_get_uri (slot->viewed_file);
1380
mimetype = nautilus_file_get_mime_type (slot->viewed_file);
1381
viewers = nautilus_view_factory_get_views_for_uri (uri,
1382
nautilus_file_get_file_type (slot->viewed_file),
1387
free_stored_viewers (window);
1388
window->details->short_list_viewers = viewers;
1392
load_view_as_menu (NautilusWindow *window)
1398
if (window->details->short_list_merge_id != 0) {
1399
gtk_ui_manager_remove_ui (window->details->ui_manager,
1400
window->details->short_list_merge_id);
1401
window->details->short_list_merge_id = 0;
1403
if (window->details->extra_viewer_merge_id != 0) {
1404
gtk_ui_manager_remove_ui (window->details->ui_manager,
1405
window->details->extra_viewer_merge_id);
1406
window->details->extra_viewer_merge_id = 0;
1407
window->details->extra_viewer_radio_action = NULL;
1409
if (window->details->view_as_action_group != NULL) {
1410
gtk_ui_manager_remove_action_group (window->details->ui_manager,
1411
window->details->view_as_action_group);
1412
window->details->view_as_action_group = NULL;
1416
refresh_stored_viewers (window);
1418
merge_id = gtk_ui_manager_new_merge_id (window->details->ui_manager);
1419
window->details->short_list_merge_id = merge_id;
1420
window->details->view_as_action_group = gtk_action_group_new ("ViewAsGroup");
1421
gtk_action_group_set_translation_domain (window->details->view_as_action_group, GETTEXT_PACKAGE);
1422
window->details->view_as_radio_action = NULL;
1424
/* Add a menu item for each view in the preferred list for this location. */
1425
/* Start on 1, because extra_viewer gets index 0 */
1426
for (node = window->details->short_list_viewers, index = 1;
1428
node = node->next, ++index) {
1429
/* Menu item in View menu. */
1430
add_view_as_menu_item (window,
1431
NAUTILUS_MENU_PATH_SHORT_LIST_PLACEHOLDER,
1436
gtk_ui_manager_insert_action_group (window->details->ui_manager,
1437
window->details->view_as_action_group,
1439
g_object_unref (window->details->view_as_action_group); /* owned by ui_manager */
1441
nautilus_window_synch_view_as_menus (window);
1443
g_signal_emit (window, signals[VIEW_AS_CHANGED], 0);
1448
load_view_as_menus_callback (NautilusFile *file,
1449
gpointer callback_data)
1451
NautilusWindow *window;
1452
NautilusWindowSlot *slot;
1454
slot = callback_data;
1455
window = slot->pane->window;
1457
if (slot == window->details->active_pane->active_slot) {
1458
load_view_as_menu (window);
1463
cancel_view_as_callback (NautilusWindowSlot *slot)
1465
nautilus_file_cancel_call_when_ready (slot->viewed_file,
1466
load_view_as_menus_callback,
1471
nautilus_window_load_view_as_menus (NautilusWindow *window)
1473
NautilusWindowSlot *slot;
1474
NautilusFileAttributes attributes;
1476
g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1478
attributes = nautilus_mime_actions_get_required_file_attributes ();
1480
slot = window->details->active_pane->active_slot;
1482
cancel_view_as_callback (slot);
1483
nautilus_file_call_when_ready (slot->viewed_file,
1485
load_view_as_menus_callback,
1490
nautilus_window_sync_title (NautilusWindow *window,
1491
NautilusWindowSlot *slot)
1493
NautilusWindowPane *pane;
1494
NautilusNotebook *notebook;
1498
if (NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_title != NULL) {
1499
NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_title (window, slot);
1504
if (slot == window->details->active_pane->active_slot) {
1505
/* if spatial mode is default, we keep "File Browser" in the window title
1506
* to recognize browser windows. Otherwise, we default to the directory name.
1508
if (!g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_ALWAYS_USE_BROWSER)) {
1509
full_title = g_strdup_printf (_("%s - File Browser"), slot->title);
1510
window_title = eel_str_middle_truncate (full_title, MAX_TITLE_LENGTH);
1511
g_free (full_title);
1513
window_title = eel_str_middle_truncate (slot->title, MAX_TITLE_LENGTH);
1516
gtk_window_set_title (GTK_WINDOW (window), window_title);
1517
g_free (window_title);
1521
notebook = NAUTILUS_NOTEBOOK (pane->notebook);
1522
nautilus_notebook_sync_tab_label (notebook, slot);
1526
nautilus_window_sync_zoom_widgets (NautilusWindow *window)
1528
NautilusWindowSlot *slot;
1531
gboolean supports_zooming;
1532
gboolean can_zoom, can_zoom_in, can_zoom_out;
1533
NautilusZoomLevel zoom_level;
1535
slot = window->details->active_pane->active_slot;
1536
view = slot->content_view;
1539
supports_zooming = nautilus_view_supports_zooming (view);
1540
zoom_level = nautilus_view_get_zoom_level (view);
1541
can_zoom = supports_zooming &&
1542
zoom_level >= NAUTILUS_ZOOM_LEVEL_SMALLEST &&
1543
zoom_level <= NAUTILUS_ZOOM_LEVEL_LARGEST;
1544
can_zoom_in = can_zoom && nautilus_view_can_zoom_in (view);
1545
can_zoom_out = can_zoom && nautilus_view_can_zoom_out (view);
1547
zoom_level = NAUTILUS_ZOOM_LEVEL_STANDARD;
1548
supports_zooming = FALSE;
1550
can_zoom_in = FALSE;
1551
can_zoom_out = FALSE;
1554
action = gtk_action_group_get_action (window->details->main_action_group,
1555
NAUTILUS_ACTION_ZOOM_IN);
1556
gtk_action_set_visible (action, supports_zooming);
1557
gtk_action_set_sensitive (action, can_zoom_in);
1559
action = gtk_action_group_get_action (window->details->main_action_group,
1560
NAUTILUS_ACTION_ZOOM_OUT);
1561
gtk_action_set_visible (action, supports_zooming);
1562
gtk_action_set_sensitive (action, can_zoom_out);
1564
action = gtk_action_group_get_action (window->details->main_action_group,
1565
NAUTILUS_ACTION_ZOOM_NORMAL);
1566
gtk_action_set_visible (action, supports_zooming);
1567
gtk_action_set_sensitive (action, can_zoom);
1569
g_signal_emit (window, signals[ZOOM_CHANGED], 0,
1570
zoom_level, supports_zooming, can_zoom,
1571
can_zoom_in, can_zoom_out);
1575
zoom_level_changed_callback (NautilusView *view,
1576
NautilusWindow *window)
1578
g_assert (NAUTILUS_IS_WINDOW (window));
1580
/* This is called each time the component in
1581
* the active slot successfully completed
1582
* a zooming operation.
1584
nautilus_window_sync_zoom_widgets (window);
1589
* A) when switching the view within the active slot
1590
* B) when switching the active slot
1591
* C) when closing the active slot (disconnect)
1594
nautilus_window_connect_content_view (NautilusWindow *window,
1597
NautilusWindowSlot *slot;
1599
g_assert (NAUTILUS_IS_WINDOW (window));
1600
g_assert (NAUTILUS_IS_VIEW (view));
1602
slot = nautilus_window_get_slot_for_view (window, view);
1604
if (slot != nautilus_window_get_active_slot (window)) {
1608
g_signal_connect (view, "zoom-level-changed",
1609
G_CALLBACK (zoom_level_changed_callback),
1612
/* Update displayed view in menu. Only do this if we're not switching
1613
* locations though, because if we are switching locations we'll
1614
* install a whole new set of views in the menu later (the current
1615
* views in the menu are for the old location).
1617
if (slot->pending_location == NULL) {
1618
nautilus_window_load_view_as_menus (window);
1621
nautilus_view_grab_focus (view);
1625
nautilus_window_disconnect_content_view (NautilusWindow *window,
1628
NautilusWindowSlot *slot;
1630
g_assert (NAUTILUS_IS_WINDOW (window));
1631
g_assert (NAUTILUS_IS_VIEW (view));
1633
slot = nautilus_window_get_slot_for_view (window, view);
1635
if (slot != nautilus_window_get_active_slot (window)) {
1639
g_signal_handlers_disconnect_by_func (view, G_CALLBACK (zoom_level_changed_callback), window);
1643
* nautilus_window_show:
1644
* @widget: GtkWidget
1646
* Call parent and then show/hide window items
1647
* base on user prefs.
1650
nautilus_window_show (GtkWidget *widget)
1652
NautilusWindow *window;
1654
window = NAUTILUS_WINDOW (widget);
1656
if (g_settings_get_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_START_WITH_SIDEBAR)) {
1657
nautilus_window_show_sidebar (window);
1659
nautilus_window_hide_sidebar (window);
1662
GTK_WIDGET_CLASS (nautilus_window_parent_class)->show (widget);
1664
nautilus_window_ui_update (window);
1668
nautilus_window_get_ui_manager (NautilusWindow *window)
1670
g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), NULL);
1672
return window->details->ui_manager;
1675
NautilusWindowPane *
1676
nautilus_window_get_next_pane (NautilusWindow *window)
1678
NautilusWindowPane *next_pane;
1681
/* return NULL if there is only one pane */
1682
if (!window->details->panes || !window->details->panes->next) {
1686
/* get next pane in the (wrapped around) list */
1687
node = g_list_find (window->details->panes, window->details->active_pane);
1688
g_return_val_if_fail (node, NULL);
1690
next_pane = node->next->data;
1692
next_pane = window->details->panes->data;
1700
nautilus_window_slot_set_viewed_file (NautilusWindowSlot *slot,
1703
NautilusFileAttributes attributes;
1705
if (slot->viewed_file == file) {
1709
nautilus_file_ref (file);
1711
cancel_view_as_callback (slot);
1713
if (slot->viewed_file != NULL) {
1714
nautilus_file_monitor_remove (slot->viewed_file,
1720
NAUTILUS_FILE_ATTRIBUTE_INFO |
1721
NAUTILUS_FILE_ATTRIBUTE_LINK_INFO;
1722
nautilus_file_monitor_add (file, slot, attributes);
1725
nautilus_file_unref (slot->viewed_file);
1726
slot->viewed_file = file;
1729
NautilusWindowSlot *
1730
nautilus_window_get_slot_for_view (NautilusWindow *window,
1733
NautilusWindowSlot *slot;
1736
for (walk = window->details->panes; walk; walk = walk->next) {
1737
NautilusWindowPane *pane = walk->data;
1739
for (l = pane->slots; l != NULL; l = l->next) {
1741
if (slot->content_view == view ||
1742
slot->new_content_view == view) {
1752
nautilus_window_get_window_type (NautilusWindow *window)
1754
g_assert (NAUTILUS_IS_WINDOW (window));
1756
return NAUTILUS_WINDOW_GET_CLASS (window)->window_type;
1759
NautilusWindowShowHiddenFilesMode
1760
nautilus_window_get_hidden_files_mode (NautilusWindow *window)
1762
return window->details->show_hidden_files_mode;
1766
nautilus_window_set_hidden_files_mode (NautilusWindow *window,
1767
NautilusWindowShowHiddenFilesMode mode)
1769
window->details->show_hidden_files_mode = mode;
1771
g_signal_emit_by_name (window, "hidden_files_mode_changed");
1775
nautilus_window_set_initiated_unmount (NautilusWindow *window,
1776
gboolean initiated_unmount)
1778
window->details->initiated_unmount = initiated_unmount;
1781
NautilusWindowSlot *
1782
nautilus_window_get_active_slot (NautilusWindow *window)
1784
g_assert (NAUTILUS_IS_WINDOW (window));
1786
if (window->details->active_pane == NULL) {
1790
return window->details->active_pane->active_slot;
1793
NautilusWindowSlot *
1794
nautilus_window_get_extra_slot (NautilusWindow *window)
1796
NautilusWindowPane *extra_pane;
1799
g_assert (NAUTILUS_IS_WINDOW (window));
1802
/* return NULL if there is only one pane */
1803
if (window->details->panes == NULL ||
1804
window->details->panes->next == NULL) {
1808
/* get next pane in the (wrapped around) list */
1809
node = g_list_find (window->details->panes,
1810
window->details->active_pane);
1811
g_return_val_if_fail (node, FALSE);
1814
extra_pane = node->next->data;
1817
extra_pane = window->details->panes->data;
1820
return extra_pane->active_slot;
1824
window_set_search_action_text (NautilusWindow *window,
1828
NautilusWindowPane *pane;
1831
for (l = window->details->panes; l != NULL; l = l->next) {
1833
action = gtk_action_group_get_action (pane->action_group,
1834
NAUTILUS_ACTION_SEARCH);
1836
gtk_action_set_is_important (action, setting);
1840
static NautilusWindowSlot *
1841
create_extra_pane (NautilusWindow *window)
1843
NautilusWindowPane *pane;
1844
NautilusWindowSlot *slot;
1848
pane = nautilus_window_pane_new (window);
1849
window->details->panes = g_list_append (window->details->panes, pane);
1851
paned = GTK_PANED (window->details->split_view_hpane);
1852
if (gtk_paned_get_child1 (paned) == NULL) {
1853
gtk_paned_pack1 (paned, pane->widget, TRUE, FALSE);
1855
gtk_paned_pack2 (paned, pane->widget, TRUE, FALSE);
1859
slot = nautilus_window_open_slot (NAUTILUS_WINDOW_PANE (pane),
1860
NAUTILUS_WINDOW_OPEN_SLOT_APPEND);
1861
pane->active_slot = slot;
1867
nautilus_window_reload (NautilusWindow *window)
1869
NautilusWindowSlot *active_slot;
1871
active_slot = nautilus_window_get_active_slot (window);
1872
nautilus_window_slot_reload (active_slot);
1876
nautilus_window_state_event (GtkWidget *widget,
1877
GdkEventWindowState *event)
1879
if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
1880
g_settings_set_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_MAXIMIZED,
1881
event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED);
1884
if (GTK_WIDGET_CLASS (nautilus_window_parent_class)->window_state_event != NULL) {
1885
return GTK_WIDGET_CLASS (nautilus_window_parent_class)->window_state_event (widget, event);
1892
nautilus_window_go_back (NautilusWindow *window)
1894
nautilus_window_back_or_forward (window, TRUE, 0, FALSE);
1898
nautilus_window_go_forward (NautilusWindow *window)
1900
nautilus_window_back_or_forward (window, FALSE, 0, FALSE);
1904
nautilus_window_allow_back (NautilusWindow *window, gboolean allow)
1908
action = gtk_action_group_get_action (nautilus_navigation_state_get_master (window->details->nav_state),
1909
NAUTILUS_ACTION_BACK);
1911
gtk_action_set_sensitive (action, allow);
1915
nautilus_window_allow_forward (NautilusWindow *window, gboolean allow)
1919
action = gtk_action_group_get_action (nautilus_navigation_state_get_master (window->details->nav_state),
1920
NAUTILUS_ACTION_FORWARD);
1922
gtk_action_set_sensitive (action, allow);
1926
nautilus_window_button_press_event (GtkWidget *widget,
1927
GdkEventButton *event)
1929
NautilusWindow *window;
1933
window = NAUTILUS_WINDOW (widget);
1935
if (mouse_extra_buttons && (event->button == mouse_back_button)) {
1936
nautilus_window_go_back (window);
1938
} else if (mouse_extra_buttons && (event->button == mouse_forward_button)) {
1939
nautilus_window_go_forward (window);
1941
} else if (GTK_WIDGET_CLASS (nautilus_window_parent_class)->button_press_event) {
1942
handled = GTK_WIDGET_CLASS (nautilus_window_parent_class)->button_press_event (widget, event);
1950
mouse_back_button_changed (gpointer callback_data)
1952
int new_back_button;
1954
new_back_button = g_settings_get_int (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_BACK_BUTTON);
1956
/* Bounds checking */
1957
if (new_back_button < 6 || new_back_button > UPPER_MOUSE_LIMIT)
1960
mouse_back_button = new_back_button;
1964
mouse_forward_button_changed (gpointer callback_data)
1966
int new_forward_button;
1968
new_forward_button = g_settings_get_int (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_FORWARD_BUTTON);
1970
/* Bounds checking */
1971
if (new_forward_button < 6 || new_forward_button > UPPER_MOUSE_LIMIT)
1974
mouse_forward_button = new_forward_button;
1978
use_extra_mouse_buttons_changed (gpointer callback_data)
1980
mouse_extra_buttons = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS);
1989
nautilus_window_init (NautilusWindow *window)
1991
window->details = G_TYPE_INSTANCE_GET_PRIVATE (window, NAUTILUS_TYPE_WINDOW, NautilusWindowDetails);
1993
window->details->panes = NULL;
1994
window->details->active_pane = NULL;
1996
window->details->show_hidden_files_mode = NAUTILUS_WINDOW_SHOW_HIDDEN_FILES_DEFAULT;
1998
/* Set initial window title */
1999
gtk_window_set_title (GTK_WINDOW (window), _("Nautilus"));
2002
static NautilusIconInfo *
2003
real_get_icon (NautilusWindow *window,
2004
NautilusWindowSlot *slot)
2006
return nautilus_file_get_icon (slot->viewed_file, 48,
2007
NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING |
2008
NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON);
2012
real_window_close (NautilusWindow *window)
2014
g_return_if_fail (NAUTILUS_IS_WINDOW (window));
2016
nautilus_window_save_geometry (window);
2018
gtk_widget_destroy (GTK_WIDGET (window));
2022
nautilus_window_class_init (NautilusWindowClass *class)
2024
GtkBindingSet *binding_set;
2025
GObjectClass *oclass = G_OBJECT_CLASS (class);
2026
GtkWidgetClass *wclass = GTK_WIDGET_CLASS (class);
2028
oclass->finalize = nautilus_window_finalize;
2029
oclass->constructed = nautilus_window_constructed;
2030
oclass->get_property = nautilus_window_get_property;
2031
oclass->set_property = nautilus_window_set_property;
2033
wclass->destroy = nautilus_window_destroy;
2034
wclass->show = nautilus_window_show;
2035
wclass->get_preferred_width = nautilus_window_get_preferred_width;
2036
wclass->get_preferred_height = nautilus_window_get_preferred_height;
2037
wclass->realize = nautilus_window_realize;
2038
wclass->key_press_event = nautilus_window_key_press_event;
2039
wclass->window_state_event = nautilus_window_state_event;
2040
wclass->button_press_event = nautilus_window_button_press_event;
2042
class->window_type = NAUTILUS_WINDOW_NAVIGATION;
2043
class->bookmarks_placeholder = MENU_PATH_BOOKMARKS_PLACEHOLDER;
2044
class->get_icon = real_get_icon;
2045
class->close = real_window_close;
2047
properties[PROP_DISABLE_CHROME] =
2048
g_param_spec_boolean ("disable-chrome",
2050
"Disable window chrome, for the desktop",
2052
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
2053
G_PARAM_STATIC_STRINGS);
2056
g_signal_new ("go_up",
2057
G_TYPE_FROM_CLASS (class),
2058
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2059
G_STRUCT_OFFSET (NautilusWindowClass, go_up),
2060
g_signal_accumulator_true_handled, NULL,
2061
g_cclosure_marshal_generic,
2062
G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
2064
g_signal_new ("reload",
2065
G_TYPE_FROM_CLASS (class),
2066
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2067
G_STRUCT_OFFSET (NautilusWindowClass, reload),
2069
g_cclosure_marshal_VOID__VOID,
2071
signals[PROMPT_FOR_LOCATION] =
2072
g_signal_new ("prompt-for-location",
2073
G_TYPE_FROM_CLASS (class),
2074
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2075
G_STRUCT_OFFSET (NautilusWindowClass, prompt_for_location),
2077
g_cclosure_marshal_VOID__STRING,
2078
G_TYPE_NONE, 1, G_TYPE_STRING);
2079
signals[ZOOM_CHANGED] =
2080
g_signal_new ("zoom-changed",
2081
G_TYPE_FROM_CLASS (class),
2085
g_cclosure_marshal_generic,
2087
G_TYPE_INT, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN,
2088
G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
2089
signals[VIEW_AS_CHANGED] =
2090
g_signal_new ("view-as-changed",
2091
G_TYPE_FROM_CLASS (class),
2095
g_cclosure_marshal_VOID__VOID,
2098
signals[HIDDEN_FILES_MODE_CHANGED] =
2099
g_signal_new ("hidden_files_mode_changed",
2100
G_TYPE_FROM_CLASS (class),
2104
g_cclosure_marshal_VOID__VOID,
2107
signals[LOADING_URI] =
2108
g_signal_new ("loading_uri",
2109
G_TYPE_FROM_CLASS (class),
2113
g_cclosure_marshal_VOID__STRING,
2117
binding_set = gtk_binding_set_by_class (class);
2118
gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
2120
G_TYPE_BOOLEAN, FALSE);
2121
gtk_binding_entry_add_signal (binding_set, GDK_KEY_F5, 0,
2123
gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, 0,
2124
"prompt-for-location", 1,
2125
G_TYPE_STRING, "/");
2127
class->reload = nautilus_window_reload;
2128
class->go_up = nautilus_window_go_up_signal;
2129
class->prompt_for_location = nautilus_window_prompt_for_location;
2131
g_signal_connect_swapped (nautilus_preferences,
2132
"changed::" NAUTILUS_PREFERENCES_MOUSE_BACK_BUTTON,
2133
G_CALLBACK(mouse_back_button_changed),
2136
g_signal_connect_swapped (nautilus_preferences,
2137
"changed::" NAUTILUS_PREFERENCES_MOUSE_FORWARD_BUTTON,
2138
G_CALLBACK(mouse_forward_button_changed),
2141
g_signal_connect_swapped (nautilus_preferences,
2142
"changed::" NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS,
2143
G_CALLBACK(use_extra_mouse_buttons_changed),
2146
g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
2147
g_type_class_add_private (oclass, sizeof (NautilusWindowDetails));
2151
nautilus_window_split_view_on (NautilusWindow *window)
2153
NautilusWindowSlot *slot, *old_active_slot;
2156
old_active_slot = nautilus_window_get_active_slot (window);
2157
slot = create_extra_pane (window);
2160
if (old_active_slot != NULL) {
2161
location = nautilus_window_slot_get_location (old_active_slot);
2162
if (location != NULL) {
2163
if (g_file_has_uri_scheme (location, "x-nautilus-search")) {
2164
g_object_unref (location);
2169
if (location == NULL) {
2170
location = g_file_new_for_path (g_get_home_dir ());
2173
nautilus_window_slot_go_to (slot, location, FALSE);
2174
g_object_unref (location);
2176
window_set_search_action_text (window, FALSE);
2180
nautilus_window_split_view_off (NautilusWindow *window)
2182
NautilusWindowPane *pane, *active_pane;
2185
g_return_if_fail (window);
2187
active_pane = window->details->active_pane;
2189
/* delete all panes except the first (main) pane */
2190
for (l = window->details->panes; l != NULL; l = next) {
2193
if (pane != active_pane) {
2194
nautilus_window_close_pane (pane);
2198
nautilus_window_set_active_pane (window, active_pane);
2199
nautilus_navigation_state_set_master (window->details->nav_state,
2200
active_pane->action_group);
2202
nautilus_window_update_show_hide_menu_items (window);
2203
nautilus_window_update_split_view_actions_sensitivity (window);
2205
window_set_search_action_text (window, TRUE);
2209
nautilus_window_split_view_showing (NautilusWindow *window)
2211
return g_list_length (NAUTILUS_WINDOW (window)->details->panes) > 1;