~mitya57/ubuntu/precise/nautilus/desktop-window-fixes

« back to all changes in this revision

Viewing changes to .pc/git_gsettings_signals.patch/src/nautilus-window.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher, Jeremy Bicha, Sebastien Bacher
  • Date: 2011-09-30 12:23:46 UTC
  • Revision ID: package-import@ubuntu.com-20110930122346-1ta7yqhz30g6fv9d
Tags: 1:3.2.0-0ubuntu5
[ Jeremy Bicha ]
* debian/patches/05_desktop_menu_export.patch:
  - Disable a few more items that don't work right in desktop mode

[ Sebastien Bacher ]
* git_handle_missing_icon.patch:
  - don't segfault on missing icon (lp: #860659)
* git_gsettings_signals.patch:
  - don't segfault on preferences changes (lp: #807234)
* git_no_typeahead_timeout_segfault.patch:
  - better handle the flush timeout, should avoid segfaults (lp: #804133) 
* git_dont_preview_empty_selection.patch:
  - check that the selection is non empty to avoid a segfault (lp: #812015)  
* git_correct_signal_handling.patch,
  git_no_signal_order_assert.patch,
  git_slot_closing.patch:
  - clean some signal handling issues leading to segfaults (lp: #795708)
* git_close_pane_cleaning.patch:
  - needed changes for the previous patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
 
 
3
/*
 
4
 *  Nautilus
 
5
 *
 
6
 *  Copyright (C) 1999, 2000, 2004 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
 *           Alexander Larsson <alexl@redhat.com>
 
26
 */
 
27
 
 
28
/* nautilus-window.c: Implementation of the main window object */
 
29
 
 
30
#include <config.h>
 
31
 
 
32
#include "nautilus-window-private.h"
 
33
 
 
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"
 
48
 
 
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>
 
53
#include <gdk/gdkx.h>
 
54
#include <gdk/gdkkeysyms.h>
 
55
#include <gtk/gtk.h>
 
56
#include <glib/gi18n.h>
 
57
#ifdef HAVE_X11_XF86KEYSYM_H
 
58
#include <X11/XF86keysym.h>
 
59
#endif
 
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>
 
69
 
 
70
#define DEBUG_FLAG NAUTILUS_DEBUG_WINDOW
 
71
#include <libnautilus-private/nautilus-debug.h>
 
72
 
 
73
#include <math.h>
 
74
#include <sys/time.h>
 
75
 
 
76
#define SIDE_PANE_MINIMUM_WIDTH 1
 
77
#define SIDE_PANE_MINIMUM_HEIGHT 400
 
78
 
 
79
/* dock items */
 
80
 
 
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"
 
84
 
 
85
#define MAX_TITLE_LENGTH 180
 
86
 
 
87
#define MENU_PATH_BOOKMARKS_PLACEHOLDER                 "/MenuBar/Other Menus/Bookmarks/Bookmarks Placeholder"
 
88
 
 
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;
 
93
 
 
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);
 
97
 
 
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?
 
104
 */
 
105
#define UPPER_MOUSE_LIMIT 14
 
106
 
 
107
enum {
 
108
        PROP_DISABLE_CHROME = 1,
 
109
        NUM_PROPERTIES,
 
110
};
 
111
 
 
112
enum {
 
113
        GO_UP,
 
114
        RELOAD,
 
115
        PROMPT_FOR_LOCATION,
 
116
        ZOOM_CHANGED,
 
117
        VIEW_AS_CHANGED,
 
118
        LOADING_URI,
 
119
        HIDDEN_FILES_MODE_CHANGED,
 
120
        LAST_SIGNAL
 
121
};
 
122
 
 
123
static guint signals[LAST_SIGNAL] = { 0 };
 
124
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
 
125
 
 
126
typedef struct  {
 
127
        NautilusWindow *window;
 
128
        char *id;
 
129
} ActivateViewData;
 
130
 
 
131
static void cancel_view_as_callback         (NautilusWindowSlot      *slot);
 
132
static void action_view_as_callback         (GtkAction               *action,
 
133
                                             ActivateViewData        *data);
 
134
 
 
135
G_DEFINE_TYPE (NautilusWindow, nautilus_window, GTK_TYPE_WINDOW);
 
136
 
 
137
static const struct {
 
138
        unsigned int keyval;
 
139
        const char *action;
 
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 }
 
156
 
 
157
#endif
 
158
};
 
159
 
 
160
/* Unconditionally synchronize the GtkUIManager of WINDOW. */
 
161
static void
 
162
nautilus_window_ui_update (NautilusWindow *window)
 
163
{
 
164
        g_assert (NAUTILUS_IS_WINDOW (window));
 
165
 
 
166
        gtk_ui_manager_ensure_update (window->details->ui_manager);
 
167
}
 
168
 
 
169
void
 
170
nautilus_window_push_status (NautilusWindow *window,
 
171
                             const char *text)
 
172
{
 
173
        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 
174
 
 
175
        /* clear any previous message, underflow is allowed */
 
176
        gtk_statusbar_pop (GTK_STATUSBAR (window->details->statusbar), 0);
 
177
 
 
178
        if (text != NULL && text[0] != '\0') {
 
179
                gtk_statusbar_push (GTK_STATUSBAR (window->details->statusbar), 0, text);
 
180
        }
 
181
}
 
182
 
 
183
void
 
184
nautilus_window_sync_status (NautilusWindow *window)
 
185
{
 
186
        NautilusWindowSlot *slot;
 
187
 
 
188
        slot = window->details->active_pane->active_slot;
 
189
        nautilus_window_push_status (window, slot->status_text);
 
190
}
 
191
 
 
192
void
 
193
nautilus_window_go_to (NautilusWindow *window, GFile *location)
 
194
{
 
195
        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 
196
 
 
197
        nautilus_window_slot_go_to (window->details->active_pane->active_slot, location, FALSE);
 
198
}
 
199
 
 
200
void
 
201
nautilus_window_go_to_full (NautilusWindow *window,
 
202
                            GFile          *location,
 
203
                            NautilusWindowGoToCallback callback,
 
204
                            gpointer        user_data)
 
205
{
 
206
        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 
207
 
 
208
        nautilus_window_slot_go_to_full (window->details->active_pane->active_slot, location, FALSE, callback, user_data);
 
209
}
 
210
 
 
211
static gboolean
 
212
nautilus_window_go_up_signal (NautilusWindow *window, gboolean close_behind)
 
213
{
 
214
        nautilus_window_slot_go_up (nautilus_window_get_active_slot (window),
 
215
                                    close_behind, FALSE);
 
216
 
 
217
        return TRUE;
 
218
}
 
219
 
 
220
void
 
221
nautilus_window_new_tab (NautilusWindow *window)
 
222
{
 
223
        NautilusWindowSlot *current_slot;
 
224
        NautilusWindowSlot *new_slot;
 
225
        NautilusWindowOpenFlags flags;
 
226
        GFile *location;
 
227
        int new_slot_position;
 
228
        char *scheme;
 
229
 
 
230
        current_slot = window->details->active_pane->active_slot;
 
231
        location = nautilus_window_slot_get_location (current_slot);
 
232
 
 
233
        if (location != NULL) {
 
234
                flags = 0;
 
235
 
 
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;
 
239
                }
 
240
 
 
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 ());
 
245
                }
 
246
                g_free (scheme);
 
247
 
 
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);
 
252
        }
 
253
}
 
254
 
 
255
void
 
256
nautilus_window_allow_up (NautilusWindow *window, gboolean allow)
 
257
{
 
258
        GtkAction *action;
 
259
        
 
260
        g_assert (NAUTILUS_IS_WINDOW (window));
 
261
 
 
262
        action = gtk_action_group_get_action (window->details->main_action_group,
 
263
                                              NAUTILUS_ACTION_UP);
 
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);
 
268
}
 
269
 
 
270
static void
 
271
update_cursor (NautilusWindow *window)
 
272
{
 
273
        NautilusWindowSlot *slot;
 
274
        GdkCursor *cursor;
 
275
 
 
276
        slot = window->details->active_pane->active_slot;
 
277
 
 
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);
 
282
        } else {
 
283
                gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
 
284
        }
 
285
}
 
286
 
 
287
void
 
288
nautilus_window_sync_allow_stop (NautilusWindow *window,
 
289
                                 NautilusWindowSlot *slot)
 
290
{
 
291
        GtkAction *action;
 
292
        gboolean allow_stop;
 
293
        NautilusNotebook *notebook;
 
294
 
 
295
        g_assert (NAUTILUS_IS_WINDOW (window));
 
296
 
 
297
        action = gtk_action_group_get_action (window->details->main_action_group,
 
298
                                              NAUTILUS_ACTION_STOP);
 
299
        allow_stop = gtk_action_get_sensitive (action);
 
300
 
 
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);
 
305
                }
 
306
 
 
307
                if (gtk_widget_get_realized (GTK_WIDGET (window))) {
 
308
                        update_cursor (window);
 
309
                }
 
310
 
 
311
 
 
312
                notebook = NAUTILUS_NOTEBOOK (slot->pane->notebook);
 
313
                nautilus_notebook_sync_loading (notebook, slot);
 
314
        }
 
315
}
 
316
 
 
317
void
 
318
nautilus_window_prompt_for_location (NautilusWindow *window,
 
319
                                     const char     *initial)
 
320
{       
 
321
        NautilusWindowPane *pane;
 
322
 
 
323
        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 
324
 
 
325
        pane = window->details->active_pane;
 
326
        nautilus_window_pane_ensure_location_bar (pane);
 
327
 
 
328
        if (initial) {
 
329
                nautilus_location_bar_set_location (NAUTILUS_LOCATION_BAR (pane->location_bar),
 
330
                                                    initial);
 
331
        }
 
332
}
 
333
 
 
334
/* Code should never force the window taller than this size.
 
335
 * (The user can still stretch the window taller if desired).
 
336
 */
 
337
static guint
 
338
get_max_forced_height (GdkScreen *screen)
 
339
{
 
340
        return (gdk_screen_get_height (screen) * 90) / 100;
 
341
}
 
342
 
 
343
/* Code should never force the window wider than this size.
 
344
 * (The user can still stretch the window wider if desired).
 
345
 */
 
346
static guint
 
347
get_max_forced_width (GdkScreen *screen)
 
348
{
 
349
        return (gdk_screen_get_width (screen) * 90) / 100;
 
350
}
 
351
 
 
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
 
354
 * construction time.
 
355
 */
 
356
static void
 
357
nautilus_window_set_initial_window_geometry (NautilusWindow *window)
 
358
{
 
359
        GdkScreen *screen;
 
360
        guint max_width_for_screen, max_height_for_screen;
 
361
        guint default_width, default_height;
 
362
 
 
363
        screen = gtk_window_get_screen (GTK_WINDOW (window));
 
364
        
 
365
        max_width_for_screen = get_max_forced_width (screen);
 
366
        max_height_for_screen = get_max_forced_height (screen);
 
367
        
 
368
        default_width = NAUTILUS_WINDOW_DEFAULT_WIDTH;
 
369
        default_height = NAUTILUS_WINDOW_DEFAULT_HEIGHT;
 
370
 
 
371
        gtk_window_set_default_size (GTK_WINDOW (window), 
 
372
                                     MIN (default_width, 
 
373
                                          max_width_for_screen), 
 
374
                                     MIN (default_height, 
 
375
                                          max_height_for_screen));
 
376
}
 
377
 
 
378
static gboolean
 
379
save_sidebar_width_cb (gpointer user_data)
 
380
{
 
381
        NautilusWindow *window = user_data;
 
382
 
 
383
        window->details->sidebar_width_handler_id = 0;
 
384
 
 
385
        DEBUG ("Saving sidebar width: %d", window->details->side_pane_width);
 
386
 
 
387
        g_settings_set_int (nautilus_window_state,
 
388
                            NAUTILUS_WINDOW_STATE_SIDEBAR_WIDTH,
 
389
                            window->details->side_pane_width);
 
390
 
 
391
        return FALSE;
 
392
}
 
393
 
 
394
/* side pane helpers */
 
395
static void
 
396
side_pane_size_allocate_callback (GtkWidget *widget,
 
397
                                  GtkAllocation *allocation,
 
398
                                  gpointer user_data)
 
399
{
 
400
        NautilusWindow *window;
 
401
 
 
402
        window = user_data;
 
403
 
 
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;
 
407
        }
 
408
 
 
409
        if (allocation->width != window->details->side_pane_width &&
 
410
            allocation->width > 1) {
 
411
                window->details->side_pane_width = allocation->width;
 
412
 
 
413
                window->details->sidebar_width_handler_id =
 
414
                        g_idle_add (save_sidebar_width_cb, window);
 
415
        }
 
416
}
 
417
 
 
418
static void
 
419
setup_side_pane_width (NautilusWindow *window)
 
420
{
 
421
        g_return_if_fail (window->details->sidebar != NULL);
 
422
 
 
423
        window->details->side_pane_width =
 
424
                g_settings_get_int (nautilus_window_state,
 
425
                                    NAUTILUS_WINDOW_STATE_SIDEBAR_WIDTH);
 
426
 
 
427
        gtk_paned_set_position (GTK_PANED (window->details->content_paned),
 
428
                                window->details->side_pane_width);
 
429
}
 
430
 
 
431
static gboolean
 
432
sidebar_id_is_valid (const gchar *sidebar_id)
 
433
{
 
434
        return (g_strcmp0 (sidebar_id, NAUTILUS_WINDOW_SIDEBAR_PLACES) == 0 ||
 
435
                g_strcmp0 (sidebar_id, NAUTILUS_WINDOW_SIDEBAR_TREE) == 0);
 
436
}
 
437
 
 
438
static void
 
439
nautilus_window_set_up_sidebar (NautilusWindow *window)
 
440
{
 
441
        GtkWidget *sidebar;
 
442
 
 
443
        DEBUG ("Setting up sidebar id %s", window->details->sidebar_id);
 
444
 
 
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);
 
448
 
 
449
        gtk_paned_pack1 (GTK_PANED (window->details->content_paned),
 
450
                         GTK_WIDGET (window->details->sidebar),
 
451
                         FALSE, FALSE);
 
452
 
 
453
        setup_side_pane_width (window);
 
454
        g_signal_connect (window->details->sidebar, 
 
455
                          "size_allocate",
 
456
                          G_CALLBACK (side_pane_size_allocate_callback),
 
457
                          window);
 
458
 
 
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);
 
463
        } else {
 
464
                g_assert_not_reached ();
 
465
        }
 
466
 
 
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));
 
470
}
 
471
 
 
472
static void
 
473
nautilus_window_tear_down_sidebar (NautilusWindow *window)
 
474
{
 
475
        DEBUG ("Destroying sidebar");
 
476
 
 
477
        gtk_widget_destroy (GTK_WIDGET (window->details->sidebar));
 
478
        window->details->sidebar = NULL;
 
479
}
 
480
 
 
481
void
 
482
nautilus_window_hide_sidebar (NautilusWindow *window)
 
483
{
 
484
        DEBUG ("Called hide_sidebar()");
 
485
 
 
486
        if (window->details->sidebar == NULL) {
 
487
                return;
 
488
        }
 
489
 
 
490
        nautilus_window_tear_down_sidebar (window);
 
491
        nautilus_window_update_show_hide_menu_items (window);
 
492
 
 
493
        g_settings_set_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_START_WITH_SIDEBAR, FALSE);
 
494
}
 
495
 
 
496
void
 
497
nautilus_window_show_sidebar (NautilusWindow *window)
 
498
{
 
499
        DEBUG ("Called show_sidebar()");
 
500
 
 
501
        if (window->details->sidebar != NULL) {
 
502
                return;
 
503
        }
 
504
 
 
505
        if (window->details->disable_chrome) {
 
506
                return;
 
507
        }
 
508
 
 
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);
 
512
}
 
513
 
 
514
static void
 
515
side_pane_id_changed (NautilusWindow *window)
 
516
{
 
517
        gchar *sidebar_id;
 
518
 
 
519
        sidebar_id = g_settings_get_string (nautilus_window_state,
 
520
                                            NAUTILUS_WINDOW_STATE_SIDE_PANE_VIEW);
 
521
 
 
522
        DEBUG ("Sidebar id changed to %s", sidebar_id);
 
523
 
 
524
        if (g_strcmp0 (sidebar_id, window->details->sidebar_id) == 0) {
 
525
                g_free (sidebar_id);
 
526
                return;
 
527
        }
 
528
 
 
529
        if (!sidebar_id_is_valid (sidebar_id)) {
 
530
                g_free (sidebar_id);
 
531
                return;
 
532
        }
 
533
 
 
534
        g_free (window->details->sidebar_id);
 
535
        window->details->sidebar_id = sidebar_id;
 
536
 
 
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);
 
541
        }
 
542
}
 
543
 
 
544
gboolean
 
545
nautilus_window_disable_chrome_mapping (GValue *value,
 
546
                                        GVariant *variant,
 
547
                                        gpointer user_data)
 
548
{
 
549
        NautilusWindow *window = user_data;
 
550
 
 
551
        g_value_set_boolean (value,
 
552
                             g_variant_get_boolean (variant) &&
 
553
                             !window->details->disable_chrome);
 
554
 
 
555
        return TRUE;
 
556
}
 
557
 
 
558
static void
 
559
nautilus_window_constructed (GObject *self)
 
560
{
 
561
        NautilusWindow *window;
 
562
        GtkWidget *table;
 
563
        GtkWidget *menu;
 
564
        GtkWidget *statusbar;
 
565
        GtkWidget *hpaned;
 
566
        GtkWidget *vbox;
 
567
        NautilusWindowPane *pane;
 
568
        NautilusWindowSlot *slot;
 
569
        NautilusApplication *application;
 
570
 
 
571
        window = NAUTILUS_WINDOW (self);
 
572
        application = nautilus_application_get_singleton ();
 
573
 
 
574
        G_OBJECT_CLASS (nautilus_window_parent_class)->constructed (self);
 
575
 
 
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);
 
580
 
 
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 */
 
586
 
 
587
        nautilus_window_initialize_menus (window);
 
588
        nautilus_window_initialize_actions (window);
 
589
 
 
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),
 
594
                          menu, 
 
595
                          /* X direction */                   /* Y direction */
 
596
                          0, 1,                               0, 1,
 
597
                          GTK_EXPAND | GTK_FILL | GTK_SHRINK, 0,
 
598
                          0,                                  0);
 
599
 
 
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);
 
603
 
 
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 */
 
608
                          0, 1,                               3, 4,
 
609
                          GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_EXPAND | GTK_FILL | GTK_SHRINK,
 
610
                          0,                                  0);
 
611
        gtk_widget_show (window->details->content_paned);
 
612
 
 
613
        vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
 
614
        gtk_paned_pack2 (GTK_PANED (window->details->content_paned), vbox,
 
615
                         TRUE, FALSE);
 
616
        gtk_widget_show (vbox);
 
617
 
 
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;
 
622
 
 
623
        gtk_box_pack_start (GTK_BOX (vbox), window->details->statusbar, FALSE, FALSE, 0);
 
624
 
 
625
        g_settings_bind_with_mapping (nautilus_window_state,
 
626
                                      NAUTILUS_WINDOW_STATE_START_WITH_STATUS_BAR,
 
627
                                      window->details->statusbar,
 
628
                                      "visible",
 
629
                                      G_SETTINGS_BIND_DEFAULT,
 
630
                                      nautilus_window_disable_chrome_mapping, NULL,
 
631
                                      window, NULL);
 
632
 
 
633
        pane = nautilus_window_pane_new (window);
 
634
        window->details->panes = g_list_prepend (window->details->panes, pane);
 
635
 
 
636
        gtk_paned_pack1 (GTK_PANED (hpaned), pane->widget, TRUE, FALSE);
 
637
        gtk_widget_show (pane->widget);
 
638
 
 
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);
 
642
 
 
643
        g_signal_connect_swapped (nautilus_window_state,
 
644
                                  "changed::" NAUTILUS_WINDOW_STATE_SIDE_PANE_VIEW,
 
645
                                  G_CALLBACK (side_pane_id_changed),
 
646
                                  window);
 
647
 
 
648
        side_pane_id_changed (window);
 
649
 
 
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));
 
653
 
 
654
        slot = nautilus_window_open_slot (window->details->active_pane, 0);
 
655
        nautilus_window_set_active_slot (window, slot);
 
656
}
 
657
 
 
658
static void
 
659
nautilus_window_set_property (GObject *object,
 
660
                              guint arg_id,
 
661
                              const GValue *value,
 
662
                              GParamSpec *pspec)
 
663
{
 
664
        NautilusWindow *window;
 
665
 
 
666
        window = NAUTILUS_WINDOW (object);
 
667
        
 
668
        switch (arg_id) {
 
669
        case PROP_DISABLE_CHROME:
 
670
                window->details->disable_chrome = g_value_get_boolean (value);
 
671
                break;
 
672
        default:
 
673
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
 
674
                break;
 
675
        }
 
676
}
 
677
 
 
678
static void
 
679
nautilus_window_get_property (GObject *object,
 
680
                              guint arg_id,
 
681
                              GValue *value,
 
682
                              GParamSpec *pspec)
 
683
{
 
684
        NautilusWindow *window;
 
685
 
 
686
        window = NAUTILUS_WINDOW (object);
 
687
 
 
688
        switch (arg_id) {
 
689
        case PROP_DISABLE_CHROME:
 
690
                g_value_set_boolean (value, window->details->disable_chrome);
 
691
                break;
 
692
        }
 
693
}
 
694
 
 
695
static void
 
696
free_stored_viewers (NautilusWindow *window)
 
697
{
 
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;
 
702
}
 
703
 
 
704
static void
 
705
nautilus_window_destroy (GtkWidget *object)
 
706
{
 
707
        NautilusWindow *window;
 
708
        GList *panes_copy;
 
709
 
 
710
        window = NAUTILUS_WINDOW (object);
 
711
 
 
712
        window->details->content_paned = NULL;
 
713
        window->details->split_view_hpane = NULL;
 
714
 
 
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);
 
719
 
 
720
        /* the panes list should now be empty */
 
721
        g_assert (window->details->panes == NULL);
 
722
        g_assert (window->details->active_pane == NULL);
 
723
 
 
724
        GTK_WIDGET_CLASS (nautilus_window_parent_class)->destroy (object);
 
725
}
 
726
 
 
727
static void
 
728
nautilus_window_finalize (GObject *object)
 
729
{
 
730
        NautilusWindow *window;
 
731
 
 
732
        window = NAUTILUS_WINDOW (object);
 
733
 
 
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;
 
737
        }
 
738
 
 
739
        g_free (window->details->sidebar_id);
 
740
        g_clear_object (&window->details->nav_state);
 
741
 
 
742
        nautilus_window_remove_trash_monitor_callback (window);
 
743
        free_stored_viewers (window);
 
744
 
 
745
        if (window->details->bookmark_list != NULL) {
 
746
                g_object_unref (window->details->bookmark_list);
 
747
        }
 
748
 
 
749
        g_signal_handlers_disconnect_by_func (nautilus_window_state,
 
750
                                              side_pane_id_changed, window);
 
751
 
 
752
        /* nautilus_window_close() should have run */
 
753
        g_assert (window->details->panes == NULL);
 
754
 
 
755
        g_object_unref (window->details->ui_manager);
 
756
 
 
757
        G_OBJECT_CLASS (nautilus_window_parent_class)->finalize (object);
 
758
}
 
759
 
 
760
void
 
761
nautilus_window_show_window (NautilusWindow    *window)
 
762
{
 
763
        NautilusWindowSlot *slot;
 
764
        NautilusWindowPane *pane;
 
765
        GList *l, *walk;
 
766
 
 
767
        for (walk = window->details->panes; walk; walk = walk->next) {
 
768
                pane = walk->data;
 
769
                for (l = pane->slots; l != NULL; l = l->next) {
 
770
                        slot = l->data;
 
771
 
 
772
                        nautilus_window_slot_update_title (slot);
 
773
                        nautilus_window_slot_update_icon (slot);
 
774
                }
 
775
        }
 
776
 
 
777
        gtk_widget_show (GTK_WIDGET (window));
 
778
 
 
779
        slot = window->details->active_pane->active_slot;
 
780
}
 
781
 
 
782
void
 
783
nautilus_window_view_visible (NautilusWindow *window,
 
784
                              NautilusView *view)
 
785
{
 
786
        NautilusWindowSlot *slot;
 
787
        NautilusWindowPane *pane;
 
788
        GList *l, *walk;
 
789
 
 
790
        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 
791
 
 
792
        slot = nautilus_window_get_slot_for_view (window, view);
 
793
        nautilus_view_set_is_active (view, slot->pane->is_active);
 
794
 
 
795
        if (slot->visible) {
 
796
                return;
 
797
        }
 
798
 
 
799
        slot->visible = TRUE;
 
800
 
 
801
        pane = slot->pane;
 
802
 
 
803
        if (pane->visible) {
 
804
                return;
 
805
        }
 
806
 
 
807
        /* Look for other non-visible slots */
 
808
        for (l = pane->slots; l != NULL; l = l->next) {
 
809
                slot = l->data;
 
810
 
 
811
                if (!slot->visible) {
 
812
                        return;
 
813
                }
 
814
        }
 
815
 
 
816
        /* None, this pane is visible */
 
817
        nautilus_window_pane_show (pane);
 
818
 
 
819
        /* Look for other non-visible panes */
 
820
        for (walk = window->details->panes; walk; walk = walk->next) {
 
821
                pane = walk->data;
 
822
 
 
823
                if (!pane->visible) {
 
824
                        return;
 
825
                }
 
826
        }
 
827
 
 
828
        nautilus_window_pane_grab_focus (window->details->active_pane);
 
829
 
 
830
        /* All slots and panes visible, show window */
 
831
        nautilus_window_show_window (window);
 
832
}
 
833
 
 
834
static void
 
835
nautilus_window_save_geometry (NautilusWindow *window)
 
836
{
 
837
        char *geometry_string;
 
838
        gboolean is_maximized;
 
839
 
 
840
        g_assert (NAUTILUS_IS_WINDOW (window));
 
841
 
 
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;
 
846
 
 
847
                if (!is_maximized) {
 
848
                        g_settings_set_string
 
849
                                (nautilus_window_state, NAUTILUS_WINDOW_STATE_GEOMETRY,
 
850
                                 geometry_string);
 
851
                }
 
852
                g_free (geometry_string);
 
853
 
 
854
                g_settings_set_boolean
 
855
                        (nautilus_window_state, NAUTILUS_WINDOW_STATE_MAXIMIZED,
 
856
                         is_maximized);
 
857
        }
 
858
}
 
859
 
 
860
void
 
861
nautilus_window_close (NautilusWindow *window)
 
862
{
 
863
        NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->close (window);
 
864
}
 
865
 
 
866
NautilusWindowSlot *
 
867
nautilus_window_open_slot (NautilusWindowPane *pane,
 
868
                           NautilusWindowOpenSlotFlags flags)
 
869
{
 
870
        NautilusWindowSlot *slot;
 
871
 
 
872
        g_assert (NAUTILUS_IS_WINDOW_PANE (pane));
 
873
        g_assert (NAUTILUS_IS_WINDOW (pane->window));
 
874
 
 
875
        slot = (NautilusWindowSlot *) g_object_new (NAUTILUS_TYPE_WINDOW_SLOT, NULL);
 
876
        slot->pane = pane;
 
877
 
 
878
        nautilus_window_pane_add_slot_in_tab (pane, slot, flags);
 
879
        gtk_widget_show (slot->content_box);
 
880
 
 
881
        pane->slots = g_list_append (pane->slots, slot);
 
882
 
 
883
        return slot;
 
884
}
 
885
 
 
886
void
 
887
nautilus_window_close_pane (NautilusWindowPane *pane)
 
888
{
 
889
        NautilusWindow *window;
 
890
 
 
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);
 
894
 
 
895
        while (pane->slots != NULL) {
 
896
                NautilusWindowSlot *slot = pane->slots->data;
 
897
 
 
898
                nautilus_window_close_slot (slot);
 
899
        }
 
900
 
 
901
        window = pane->window;
 
902
 
 
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;
 
908
        }
 
909
 
 
910
        window->details->panes = g_list_remove (window->details->panes, pane);
 
911
 
 
912
        g_object_unref (pane);
 
913
}
 
914
 
 
915
void
 
916
nautilus_window_close_slot (NautilusWindowSlot *slot)
 
917
{
 
918
        NautilusWindowPane *pane;
 
919
        int page_num;
 
920
        GtkNotebook *notebook;
 
921
 
 
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);
 
925
 
 
926
        /* save pane because slot is not valid anymore after this call */
 
927
        pane = slot->pane;
 
928
        notebook = GTK_NOTEBOOK (pane->notebook);
 
929
 
 
930
        page_num = gtk_notebook_page_num (notebook, slot->content_box);
 
931
        g_assert (page_num >= 0);
 
932
 
 
933
        nautilus_window_pane_remove_page (pane, page_num);
 
934
 
 
935
        gtk_notebook_set_show_tabs (notebook,
 
936
                                    gtk_notebook_get_n_pages (notebook) > 1);
 
937
 
 
938
        nautilus_window_manage_views_close_slot (pane, slot);
 
939
        cancel_view_as_callback (slot);
 
940
 
 
941
        g_object_run_dispose (G_OBJECT (slot));
 
942
        slot->pane = NULL;
 
943
        g_object_unref (slot);
 
944
        pane->slots = g_list_remove (pane->slots, slot);
 
945
}
 
946
 
 
947
NautilusWindowPane*
 
948
nautilus_window_get_active_pane (NautilusWindow *window)
 
949
{
 
950
        g_assert (NAUTILUS_IS_WINDOW (window));
 
951
        return window->details->active_pane;
 
952
}
 
953
 
 
954
static void
 
955
real_set_active_pane (NautilusWindow *window, NautilusWindowPane *new_pane)
 
956
{
 
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);
 
962
        }
 
963
        nautilus_window_pane_set_active (new_pane, TRUE);
 
964
 
 
965
        window->details->active_pane = new_pane;
 
966
}
 
967
 
 
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
 
970
 * the window. */
 
971
void
 
972
nautilus_window_set_active_pane (NautilusWindow *window,
 
973
                                 NautilusWindowPane *new_pane)
 
974
{
 
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);
 
980
        }
 
981
}
 
982
 
 
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. */
 
986
void
 
987
nautilus_window_set_active_slot (NautilusWindow *window, NautilusWindowSlot *new_slot)
 
988
{
 
989
        NautilusWindowSlot *old_slot;
 
990
 
 
991
        g_assert (NAUTILUS_IS_WINDOW (window));
 
992
 
 
993
        if (new_slot) {
 
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);
 
998
        }
 
999
 
 
1000
        if (window->details->active_pane != NULL) {
 
1001
                old_slot = window->details->active_pane->active_slot;
 
1002
        } else {
 
1003
                old_slot = NULL;
 
1004
        }
 
1005
 
 
1006
        if (old_slot == new_slot) {
 
1007
                return;
 
1008
        }
 
1009
 
 
1010
        /* make old slot inactive if it exists (may be NULL after init, for example) */
 
1011
        if (old_slot != NULL) {
 
1012
                /* inform window */
 
1013
                if (old_slot->content_view != NULL) {
 
1014
                        nautilus_window_disconnect_content_view (window, old_slot->content_view);
 
1015
                }
 
1016
 
 
1017
                /* inform slot & view */
 
1018
                g_signal_emit_by_name (old_slot, "inactive");
 
1019
        }
 
1020
 
 
1021
        /* deal with panes */
 
1022
        if (new_slot &&
 
1023
            new_slot->pane != window->details->active_pane) {
 
1024
                real_set_active_pane (window, new_slot->pane);
 
1025
        }
 
1026
 
 
1027
        window->details->active_pane->active_slot = new_slot;
 
1028
 
 
1029
        /* make new slot active, if it exists */
 
1030
        if (new_slot) {
 
1031
                /* inform sidebar panels */
 
1032
                nautilus_window_report_location_change (window);
 
1033
                /* TODO decide whether "selection-changed" should be emitted */
 
1034
 
 
1035
                if (new_slot->content_view != NULL) {
 
1036
                        /* inform window */
 
1037
                        nautilus_window_connect_content_view (window, new_slot->content_view);
 
1038
                }
 
1039
 
 
1040
                /* inform slot & view */
 
1041
                g_signal_emit_by_name (new_slot, "active");
 
1042
        }
 
1043
}
 
1044
 
 
1045
static void
 
1046
nautilus_window_get_preferred_width (GtkWidget *widget,
 
1047
                                     gint *minimal_width,
 
1048
                                     gint *natural_width)
 
1049
{
 
1050
        GdkScreen *screen;
 
1051
        gint max_w, min_w, default_w;
 
1052
 
 
1053
        screen = gtk_window_get_screen (GTK_WINDOW (widget));   
 
1054
 
 
1055
        max_w = get_max_forced_width (screen);
 
1056
        min_w = NAUTILUS_WINDOW_MIN_WIDTH;
 
1057
 
 
1058
        default_w = NAUTILUS_WINDOW_DEFAULT_WIDTH;
 
1059
 
 
1060
        *minimal_width = MIN (min_w, max_w);
 
1061
        *natural_width = MIN (default_w, max_w);
 
1062
}
 
1063
 
 
1064
static void
 
1065
nautilus_window_get_preferred_height (GtkWidget *widget,
 
1066
                                      gint *minimal_height,
 
1067
                                      gint *natural_height)
 
1068
{
 
1069
        GdkScreen *screen;
 
1070
        gint max_h, min_h, default_h;
 
1071
 
 
1072
        screen = gtk_window_get_screen (GTK_WINDOW (widget));   
 
1073
 
 
1074
        max_h = get_max_forced_height (screen);
 
1075
 
 
1076
        min_h = NAUTILUS_WINDOW_MIN_HEIGHT;
 
1077
 
 
1078
        default_h = NAUTILUS_WINDOW_DEFAULT_HEIGHT;
 
1079
 
 
1080
        *minimal_height = MIN (min_h, max_h);
 
1081
        *natural_height = MIN (default_h, max_h);
 
1082
}
 
1083
 
 
1084
static void
 
1085
nautilus_window_realize (GtkWidget *widget)
 
1086
{
 
1087
        GTK_WIDGET_CLASS (nautilus_window_parent_class)->realize (widget);
 
1088
        update_cursor (NAUTILUS_WINDOW (widget));
 
1089
}
 
1090
 
 
1091
static gboolean
 
1092
nautilus_window_key_press_event (GtkWidget *widget,
 
1093
                                 GdkEventKey *event)
 
1094
{
 
1095
        NautilusWindow *window;
 
1096
        NautilusWindowSlot *active_slot;
 
1097
        NautilusView *view;
 
1098
        int i;
 
1099
 
 
1100
        window = NAUTILUS_WINDOW (widget);
 
1101
 
 
1102
        active_slot = nautilus_window_get_active_slot (window);
 
1103
        view = active_slot->content_view;
 
1104
 
 
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.
 
1110
                 */
 
1111
                if (gtk_window_propagate_key_event (GTK_WINDOW (window), event)) {
 
1112
                        return TRUE;
 
1113
                }
 
1114
        }
 
1115
 
 
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;
 
1119
                        GtkAction *action;
 
1120
 
 
1121
                        action = NULL;
 
1122
 
 
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;
 
1127
                        }
 
1128
 
 
1129
                        g_assert (action != NULL);
 
1130
                        if (gtk_action_is_sensitive (action)) {
 
1131
                                gtk_action_activate (action);
 
1132
                                return TRUE;
 
1133
                        }
 
1134
 
 
1135
                        break;
 
1136
                }
 
1137
        }
 
1138
 
 
1139
        return GTK_WIDGET_CLASS (nautilus_window_parent_class)->key_press_event (widget, event);
 
1140
}
 
1141
 
 
1142
/*
 
1143
 * Main API
 
1144
 */
 
1145
 
 
1146
static void
 
1147
free_activate_view_data (gpointer data)
 
1148
{
 
1149
        ActivateViewData *activate_data;
 
1150
 
 
1151
        activate_data = data;
 
1152
 
 
1153
        g_free (activate_data->id);
 
1154
 
 
1155
        g_slice_free (ActivateViewData, activate_data);
 
1156
}
 
1157
 
 
1158
static void
 
1159
action_view_as_callback (GtkAction *action,
 
1160
                         ActivateViewData *data)
 
1161
{
 
1162
        NautilusWindow *window;
 
1163
        NautilusWindowSlot *slot;
 
1164
 
 
1165
        window = data->window;
 
1166
 
 
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,
 
1170
                                                       data->id);
 
1171
        }
 
1172
}
 
1173
 
 
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 */
 
1179
                       guint merge_id)
 
1180
{
 
1181
        const NautilusViewInfo *info;
 
1182
        GtkRadioAction *action;
 
1183
        char action_name[32];
 
1184
        ActivateViewData *data;
 
1185
 
 
1186
        char accel[32];
 
1187
        char accel_path[48];
 
1188
        unsigned int accel_keyval;
 
1189
 
 
1190
        info = nautilus_view_factory_lookup (identifier);
 
1191
        
 
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),
 
1196
                                       NULL,
 
1197
                                       0);
 
1198
 
 
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);
 
1202
 
 
1203
                accel_keyval = gdk_keyval_from_name (accel);
 
1204
                g_assert (accel_keyval != GDK_KEY_VoidSymbol);
 
1205
 
 
1206
                gtk_accel_map_add_entry (accel_path, accel_keyval, GDK_CONTROL_MASK);
 
1207
                gtk_action_set_accel_path (GTK_ACTION (action), accel_path);
 
1208
        }
 
1209
 
 
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;
 
1217
        }
 
1218
 
 
1219
        if (NAUTILUS_IS_DESKTOP_WINDOW(window)) {
 
1220
                gtk_action_set_visible(GTK_ACTION(action), FALSE);
 
1221
        }
 
1222
 
 
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);
 
1229
        
 
1230
        gtk_action_group_add_action (window->details->view_as_action_group,
 
1231
                                     GTK_ACTION (action));
 
1232
        g_object_unref (action);
 
1233
 
 
1234
        gtk_ui_manager_add_ui (window->details->ui_manager,
 
1235
                               merge_id,
 
1236
                               placeholder_path,
 
1237
                               action_name,
 
1238
                               action_name,
 
1239
                               GTK_UI_MANAGER_MENUITEM,
 
1240
                               FALSE);
 
1241
 
 
1242
        return action; /* return value owned by group */
 
1243
}
 
1244
 
 
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.
 
1248
 */
 
1249
static void
 
1250
update_extra_viewer_in_view_as_menus (NautilusWindow *window,
 
1251
                                      const char *id)
 
1252
{
 
1253
        gboolean had_extra_viewer;
 
1254
 
 
1255
        had_extra_viewer = window->details->extra_viewer != NULL;
 
1256
 
 
1257
        if (id == NULL) {
 
1258
                if (!had_extra_viewer) {
 
1259
                        return;
 
1260
                }
 
1261
        } else {
 
1262
                if (had_extra_viewer
 
1263
                    && strcmp (window->details->extra_viewer, id) == 0) {
 
1264
                        return;
 
1265
                }
 
1266
        }
 
1267
        g_free (window->details->extra_viewer);
 
1268
        window->details->extra_viewer = g_strdup (id);
 
1269
 
 
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;
 
1274
        }
 
1275
        
 
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;
 
1280
        }
 
1281
        
 
1282
        if (id != 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, 
 
1288
                                               0,
 
1289
                                               window->details->extra_viewer_merge_id);
 
1290
        }
 
1291
}
 
1292
 
 
1293
static void
 
1294
remove_extra_viewer_in_view_as_menus (NautilusWindow *window)
 
1295
{
 
1296
        update_extra_viewer_in_view_as_menus (window, NULL);
 
1297
}
 
1298
 
 
1299
static void
 
1300
replace_extra_viewer_in_view_as_menus (NautilusWindow *window)
 
1301
{
 
1302
        NautilusWindowSlot *slot;
 
1303
        const char *id;
 
1304
 
 
1305
        slot = window->details->active_pane->active_slot;
 
1306
 
 
1307
        id = nautilus_window_slot_get_content_view_id (slot);
 
1308
        update_extra_viewer_in_view_as_menus (window, id);
 
1309
}
 
1310
 
 
1311
/**
 
1312
 * nautilus_window_synch_view_as_menus:
 
1313
 * 
 
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.
 
1317
 * 
 
1318
 * @window: The NautilusWindow whose "View as" option menu should be synched.
 
1319
 */
 
1320
static void
 
1321
nautilus_window_synch_view_as_menus (NautilusWindow *window)
 
1322
{
 
1323
        NautilusWindowSlot *slot;
 
1324
        int index;
 
1325
        char action_name[32];
 
1326
        GList *node;
 
1327
        GtkAction *action;
 
1328
 
 
1329
        g_assert (NAUTILUS_IS_WINDOW (window));
 
1330
 
 
1331
        slot = window->details->active_pane->active_slot;
 
1332
 
 
1333
        if (slot->content_view == NULL) {
 
1334
                return;
 
1335
        }
 
1336
        for (node = window->details->short_list_viewers, index = 1;
 
1337
             node != NULL;
 
1338
             node = node->next, ++index) {
 
1339
                if (nautilus_window_slot_content_view_matches_iid (slot, (char *)node->data)) {
 
1340
                        break;
 
1341
                }
 
1342
        }
 
1343
        if (node == NULL) {
 
1344
                replace_extra_viewer_in_view_as_menus (window);
 
1345
                index = 0;
 
1346
        } else {
 
1347
                remove_extra_viewer_in_view_as_menus (window);
 
1348
        }
 
1349
 
 
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,
 
1352
                                              action_name);
 
1353
 
 
1354
        /* Don't trigger the action callback when we're synchronizing */
 
1355
        g_signal_handlers_block_matched (action,
 
1356
                                         G_SIGNAL_MATCH_FUNC,
 
1357
                                         0, 0,
 
1358
                                         NULL,
 
1359
                                         action_view_as_callback,
 
1360
                                         NULL);
 
1361
        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
 
1362
        g_signal_handlers_unblock_matched (action,
 
1363
                                           G_SIGNAL_MATCH_FUNC,
 
1364
                                           0, 0,
 
1365
                                           NULL,
 
1366
                                           action_view_as_callback,
 
1367
                                           NULL);
 
1368
}
 
1369
 
 
1370
static void
 
1371
refresh_stored_viewers (NautilusWindow *window)
 
1372
{
 
1373
        NautilusWindowSlot *slot;
 
1374
        GList *viewers;
 
1375
        char *uri, *mimetype;
 
1376
 
 
1377
        slot = window->details->active_pane->active_slot;
 
1378
 
 
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),
 
1383
                                                           mimetype);
 
1384
        g_free (uri);
 
1385
        g_free (mimetype);
 
1386
 
 
1387
        free_stored_viewers (window);
 
1388
        window->details->short_list_viewers = viewers;
 
1389
}
 
1390
 
 
1391
static void
 
1392
load_view_as_menu (NautilusWindow *window)
 
1393
{
 
1394
        GList *node;
 
1395
        int index;
 
1396
        guint merge_id;
 
1397
 
 
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;
 
1402
        }
 
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;
 
1408
        }
 
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;
 
1413
        }
 
1414
 
 
1415
        
 
1416
        refresh_stored_viewers (window);
 
1417
 
 
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;
 
1423
        
 
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; 
 
1427
             node != NULL; 
 
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, 
 
1432
                                       node->data, 
 
1433
                                       index,
 
1434
                                       merge_id);
 
1435
        }
 
1436
        gtk_ui_manager_insert_action_group (window->details->ui_manager,
 
1437
                                            window->details->view_as_action_group,
 
1438
                                            -1);
 
1439
        g_object_unref (window->details->view_as_action_group); /* owned by ui_manager */
 
1440
 
 
1441
        nautilus_window_synch_view_as_menus (window);
 
1442
 
 
1443
        g_signal_emit (window, signals[VIEW_AS_CHANGED], 0);
 
1444
 
 
1445
}
 
1446
 
 
1447
static void
 
1448
load_view_as_menus_callback (NautilusFile *file, 
 
1449
                            gpointer callback_data)
 
1450
{
 
1451
        NautilusWindow *window;
 
1452
        NautilusWindowSlot *slot;
 
1453
 
 
1454
        slot = callback_data;
 
1455
        window = slot->pane->window;
 
1456
 
 
1457
        if (slot == window->details->active_pane->active_slot) {
 
1458
                load_view_as_menu (window);
 
1459
        }
 
1460
}
 
1461
 
 
1462
static void
 
1463
cancel_view_as_callback (NautilusWindowSlot *slot)
 
1464
{
 
1465
        nautilus_file_cancel_call_when_ready (slot->viewed_file, 
 
1466
                                              load_view_as_menus_callback,
 
1467
                                              slot);
 
1468
}
 
1469
 
 
1470
void
 
1471
nautilus_window_load_view_as_menus (NautilusWindow *window)
 
1472
{
 
1473
        NautilusWindowSlot *slot;
 
1474
        NautilusFileAttributes attributes;
 
1475
 
 
1476
        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 
1477
 
 
1478
        attributes = nautilus_mime_actions_get_required_file_attributes ();
 
1479
 
 
1480
        slot = window->details->active_pane->active_slot;
 
1481
 
 
1482
        cancel_view_as_callback (slot);
 
1483
        nautilus_file_call_when_ready (slot->viewed_file,
 
1484
                                       attributes, 
 
1485
                                       load_view_as_menus_callback,
 
1486
                                       slot);
 
1487
}
 
1488
 
 
1489
void
 
1490
nautilus_window_sync_title (NautilusWindow *window,
 
1491
                            NautilusWindowSlot *slot)
 
1492
{
 
1493
        NautilusWindowPane *pane;
 
1494
        NautilusNotebook *notebook;
 
1495
        char *full_title;
 
1496
        char *window_title;
 
1497
 
 
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);
 
1500
 
 
1501
                return;
 
1502
        }
 
1503
 
 
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.
 
1507
                 */
 
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);
 
1512
                } else {
 
1513
                        window_title = eel_str_middle_truncate (slot->title, MAX_TITLE_LENGTH);
 
1514
                }
 
1515
 
 
1516
                gtk_window_set_title (GTK_WINDOW (window), window_title);
 
1517
                g_free (window_title);
 
1518
        }
 
1519
 
 
1520
        pane = slot->pane;
 
1521
        notebook = NAUTILUS_NOTEBOOK (pane->notebook);
 
1522
        nautilus_notebook_sync_tab_label (notebook, slot);
 
1523
}
 
1524
 
 
1525
void
 
1526
nautilus_window_sync_zoom_widgets (NautilusWindow *window)
 
1527
{
 
1528
        NautilusWindowSlot *slot;
 
1529
        NautilusView *view;
 
1530
        GtkAction *action;
 
1531
        gboolean supports_zooming;
 
1532
        gboolean can_zoom, can_zoom_in, can_zoom_out;
 
1533
        NautilusZoomLevel zoom_level;
 
1534
 
 
1535
        slot = window->details->active_pane->active_slot;
 
1536
        view = slot->content_view;
 
1537
 
 
1538
        if (view != NULL) {
 
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);
 
1546
        } else {
 
1547
                zoom_level = NAUTILUS_ZOOM_LEVEL_STANDARD;
 
1548
                supports_zooming = FALSE;
 
1549
                can_zoom = FALSE;
 
1550
                can_zoom_in = FALSE;
 
1551
                can_zoom_out = FALSE;
 
1552
        }
 
1553
 
 
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);
 
1558
        
 
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);
 
1563
 
 
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);
 
1568
 
 
1569
        g_signal_emit (window, signals[ZOOM_CHANGED], 0,
 
1570
                       zoom_level, supports_zooming, can_zoom,
 
1571
                       can_zoom_in, can_zoom_out);
 
1572
}
 
1573
 
 
1574
static void
 
1575
zoom_level_changed_callback (NautilusView *view,
 
1576
                             NautilusWindow *window)
 
1577
{
 
1578
        g_assert (NAUTILUS_IS_WINDOW (window));
 
1579
 
 
1580
        /* This is called each time the component in
 
1581
         * the active slot successfully completed
 
1582
         * a zooming operation.
 
1583
         */
 
1584
        nautilus_window_sync_zoom_widgets (window);
 
1585
}
 
1586
 
 
1587
 
 
1588
/* These are called
 
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)
 
1592
*/
 
1593
void
 
1594
nautilus_window_connect_content_view (NautilusWindow *window,
 
1595
                                      NautilusView *view)
 
1596
{
 
1597
        NautilusWindowSlot *slot;
 
1598
 
 
1599
        g_assert (NAUTILUS_IS_WINDOW (window));
 
1600
        g_assert (NAUTILUS_IS_VIEW (view));
 
1601
 
 
1602
        slot = nautilus_window_get_slot_for_view (window, view);
 
1603
 
 
1604
        if (slot != nautilus_window_get_active_slot (window)) {
 
1605
                return;
 
1606
        }
 
1607
 
 
1608
        g_signal_connect (view, "zoom-level-changed",
 
1609
                          G_CALLBACK (zoom_level_changed_callback),
 
1610
                          window);
 
1611
 
 
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).
 
1616
       */
 
1617
        if (slot->pending_location == NULL) {
 
1618
                nautilus_window_load_view_as_menus (window);
 
1619
        }
 
1620
 
 
1621
        nautilus_view_grab_focus (view);
 
1622
}
 
1623
 
 
1624
void
 
1625
nautilus_window_disconnect_content_view (NautilusWindow *window,
 
1626
                                         NautilusView *view)
 
1627
{
 
1628
        NautilusWindowSlot *slot;
 
1629
 
 
1630
        g_assert (NAUTILUS_IS_WINDOW (window));
 
1631
        g_assert (NAUTILUS_IS_VIEW (view));
 
1632
 
 
1633
        slot = nautilus_window_get_slot_for_view (window, view);
 
1634
 
 
1635
        if (slot != nautilus_window_get_active_slot (window)) {
 
1636
                return;
 
1637
        }
 
1638
 
 
1639
        g_signal_handlers_disconnect_by_func (view, G_CALLBACK (zoom_level_changed_callback), window);
 
1640
}
 
1641
 
 
1642
/**
 
1643
 * nautilus_window_show:
 
1644
 * @widget:     GtkWidget
 
1645
 *
 
1646
 * Call parent and then show/hide window items
 
1647
 * base on user prefs.
 
1648
 */
 
1649
static void
 
1650
nautilus_window_show (GtkWidget *widget)
 
1651
{       
 
1652
        NautilusWindow *window;
 
1653
 
 
1654
        window = NAUTILUS_WINDOW (widget);
 
1655
 
 
1656
        if (g_settings_get_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_START_WITH_SIDEBAR)) {
 
1657
                nautilus_window_show_sidebar (window);
 
1658
        } else {
 
1659
                nautilus_window_hide_sidebar (window);
 
1660
        }
 
1661
 
 
1662
        GTK_WIDGET_CLASS (nautilus_window_parent_class)->show (widget); 
 
1663
        
 
1664
        nautilus_window_ui_update (window);
 
1665
}
 
1666
 
 
1667
GtkUIManager *
 
1668
nautilus_window_get_ui_manager (NautilusWindow *window)
 
1669
{
 
1670
        g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), NULL);
 
1671
 
 
1672
        return window->details->ui_manager;
 
1673
}
 
1674
 
 
1675
NautilusWindowPane *
 
1676
nautilus_window_get_next_pane (NautilusWindow *window)
 
1677
{
 
1678
       NautilusWindowPane *next_pane;
 
1679
       GList *node;
 
1680
 
 
1681
       /* return NULL if there is only one pane */
 
1682
       if (!window->details->panes || !window->details->panes->next) {
 
1683
               return NULL;
 
1684
       }
 
1685
 
 
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);
 
1689
       if (node->next) {
 
1690
               next_pane = node->next->data;
 
1691
       } else {
 
1692
               next_pane =  window->details->panes->data;
 
1693
       }
 
1694
 
 
1695
       return next_pane;
 
1696
}
 
1697
 
 
1698
 
 
1699
void
 
1700
nautilus_window_slot_set_viewed_file (NautilusWindowSlot *slot,
 
1701
                                      NautilusFile *file)
 
1702
{
 
1703
        NautilusFileAttributes attributes;
 
1704
 
 
1705
        if (slot->viewed_file == file) {
 
1706
                return;
 
1707
        }
 
1708
 
 
1709
        nautilus_file_ref (file);
 
1710
 
 
1711
        cancel_view_as_callback (slot);
 
1712
 
 
1713
        if (slot->viewed_file != NULL) {
 
1714
                nautilus_file_monitor_remove (slot->viewed_file,
 
1715
                                              slot);
 
1716
        }
 
1717
 
 
1718
        if (file != NULL) {
 
1719
                attributes =
 
1720
                        NAUTILUS_FILE_ATTRIBUTE_INFO |
 
1721
                        NAUTILUS_FILE_ATTRIBUTE_LINK_INFO;
 
1722
                nautilus_file_monitor_add (file, slot, attributes);
 
1723
        }
 
1724
 
 
1725
        nautilus_file_unref (slot->viewed_file);
 
1726
        slot->viewed_file = file;
 
1727
}
 
1728
 
 
1729
NautilusWindowSlot *
 
1730
nautilus_window_get_slot_for_view (NautilusWindow *window,
 
1731
                                   NautilusView *view)
 
1732
{
 
1733
        NautilusWindowSlot *slot;
 
1734
        GList *l, *walk;
 
1735
 
 
1736
        for (walk = window->details->panes; walk; walk = walk->next) {
 
1737
                NautilusWindowPane *pane = walk->data;
 
1738
 
 
1739
                for (l = pane->slots; l != NULL; l = l->next) {
 
1740
                        slot = l->data;
 
1741
                        if (slot->content_view == view ||
 
1742
                            slot->new_content_view == view) {
 
1743
                                return slot;
 
1744
                        }
 
1745
                }
 
1746
        }
 
1747
 
 
1748
        return NULL;
 
1749
}
 
1750
 
 
1751
NautilusWindowType
 
1752
nautilus_window_get_window_type (NautilusWindow *window)
 
1753
{
 
1754
        g_assert (NAUTILUS_IS_WINDOW (window));
 
1755
 
 
1756
        return NAUTILUS_WINDOW_GET_CLASS (window)->window_type;
 
1757
}
 
1758
 
 
1759
NautilusWindowShowHiddenFilesMode
 
1760
nautilus_window_get_hidden_files_mode (NautilusWindow *window)
 
1761
{
 
1762
        return window->details->show_hidden_files_mode;
 
1763
}
 
1764
 
 
1765
void
 
1766
nautilus_window_set_hidden_files_mode (NautilusWindow *window,
 
1767
                                       NautilusWindowShowHiddenFilesMode  mode)
 
1768
{
 
1769
        window->details->show_hidden_files_mode = mode;
 
1770
 
 
1771
        g_signal_emit_by_name (window, "hidden_files_mode_changed");
 
1772
}
 
1773
 
 
1774
void
 
1775
nautilus_window_set_initiated_unmount (NautilusWindow *window,
 
1776
                                       gboolean initiated_unmount)
 
1777
{
 
1778
        window->details->initiated_unmount = initiated_unmount;
 
1779
}
 
1780
 
 
1781
NautilusWindowSlot *
 
1782
nautilus_window_get_active_slot (NautilusWindow *window)
 
1783
{
 
1784
        g_assert (NAUTILUS_IS_WINDOW (window));
 
1785
 
 
1786
        if (window->details->active_pane == NULL) {
 
1787
                return NULL;
 
1788
        }
 
1789
 
 
1790
        return window->details->active_pane->active_slot;
 
1791
}
 
1792
 
 
1793
NautilusWindowSlot *
 
1794
nautilus_window_get_extra_slot (NautilusWindow *window)
 
1795
{
 
1796
        NautilusWindowPane *extra_pane;
 
1797
        GList *node;
 
1798
 
 
1799
        g_assert (NAUTILUS_IS_WINDOW (window));
 
1800
 
 
1801
 
 
1802
        /* return NULL if there is only one pane */
 
1803
        if (window->details->panes == NULL ||
 
1804
            window->details->panes->next == NULL) {
 
1805
                return NULL;
 
1806
        }
 
1807
 
 
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);
 
1812
 
 
1813
        if (node->next) {
 
1814
                extra_pane = node->next->data;
 
1815
        }
 
1816
        else {
 
1817
                extra_pane =  window->details->panes->data;
 
1818
        }
 
1819
 
 
1820
        return extra_pane->active_slot;
 
1821
}
 
1822
 
 
1823
static void
 
1824
window_set_search_action_text (NautilusWindow *window,
 
1825
                               gboolean setting)
 
1826
{
 
1827
        GtkAction *action;
 
1828
        NautilusWindowPane *pane;
 
1829
        GList *l;
 
1830
 
 
1831
        for (l = window->details->panes; l != NULL; l = l->next) {
 
1832
                pane = l->data;
 
1833
                action = gtk_action_group_get_action (pane->action_group,
 
1834
                                                      NAUTILUS_ACTION_SEARCH);
 
1835
 
 
1836
                gtk_action_set_is_important (action, setting);
 
1837
        }
 
1838
}
 
1839
 
 
1840
static NautilusWindowSlot *
 
1841
create_extra_pane (NautilusWindow *window)
 
1842
{
 
1843
        NautilusWindowPane *pane;
 
1844
        NautilusWindowSlot *slot;
 
1845
        GtkPaned *paned;
 
1846
 
 
1847
        /* New pane */
 
1848
        pane = nautilus_window_pane_new (window);
 
1849
        window->details->panes = g_list_append (window->details->panes, pane);
 
1850
 
 
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);
 
1854
        } else {
 
1855
                gtk_paned_pack2 (paned, pane->widget, TRUE, FALSE);
 
1856
        }
 
1857
 
 
1858
        /* slot */
 
1859
        slot = nautilus_window_open_slot (NAUTILUS_WINDOW_PANE (pane),
 
1860
                                          NAUTILUS_WINDOW_OPEN_SLOT_APPEND);
 
1861
        pane->active_slot = slot;
 
1862
 
 
1863
        return slot;
 
1864
}
 
1865
 
 
1866
static void
 
1867
nautilus_window_reload (NautilusWindow *window)
 
1868
{
 
1869
        NautilusWindowSlot *active_slot;
 
1870
 
 
1871
        active_slot = nautilus_window_get_active_slot (window);
 
1872
        nautilus_window_slot_reload (active_slot);
 
1873
}
 
1874
 
 
1875
static gboolean
 
1876
nautilus_window_state_event (GtkWidget *widget,
 
1877
                             GdkEventWindowState *event)
 
1878
{
 
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);
 
1882
        }
 
1883
 
 
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);
 
1886
        }
 
1887
 
 
1888
        return FALSE;
 
1889
}
 
1890
 
 
1891
static void
 
1892
nautilus_window_go_back (NautilusWindow *window)
 
1893
{
 
1894
        nautilus_window_back_or_forward (window, TRUE, 0, FALSE);
 
1895
}
 
1896
 
 
1897
static void
 
1898
nautilus_window_go_forward (NautilusWindow *window)
 
1899
{
 
1900
        nautilus_window_back_or_forward (window, FALSE, 0, FALSE);
 
1901
}
 
1902
 
 
1903
void
 
1904
nautilus_window_allow_back (NautilusWindow *window, gboolean allow)
 
1905
{
 
1906
        GtkAction *action;
 
1907
 
 
1908
        action = gtk_action_group_get_action (nautilus_navigation_state_get_master (window->details->nav_state),
 
1909
                                              NAUTILUS_ACTION_BACK);
 
1910
 
 
1911
        gtk_action_set_sensitive (action, allow);
 
1912
}
 
1913
 
 
1914
void
 
1915
nautilus_window_allow_forward (NautilusWindow *window, gboolean allow)
 
1916
{
 
1917
        GtkAction *action;
 
1918
 
 
1919
        action = gtk_action_group_get_action (nautilus_navigation_state_get_master (window->details->nav_state),
 
1920
                                              NAUTILUS_ACTION_FORWARD);
 
1921
 
 
1922
        gtk_action_set_sensitive (action, allow);
 
1923
}
 
1924
 
 
1925
static gboolean
 
1926
nautilus_window_button_press_event (GtkWidget *widget,
 
1927
                                    GdkEventButton *event)
 
1928
{
 
1929
        NautilusWindow *window;
 
1930
        gboolean handled;
 
1931
 
 
1932
        handled = FALSE;
 
1933
        window = NAUTILUS_WINDOW (widget);
 
1934
 
 
1935
        if (mouse_extra_buttons && (event->button == mouse_back_button)) {
 
1936
                nautilus_window_go_back (window);
 
1937
                handled = TRUE; 
 
1938
        } else if (mouse_extra_buttons && (event->button == mouse_forward_button)) {
 
1939
                nautilus_window_go_forward (window);
 
1940
                handled = TRUE;
 
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);
 
1943
        } else {
 
1944
                handled = FALSE;
 
1945
        }
 
1946
        return handled;
 
1947
}
 
1948
 
 
1949
static void
 
1950
mouse_back_button_changed (gpointer callback_data)
 
1951
{
 
1952
        int new_back_button;
 
1953
 
 
1954
        new_back_button = g_settings_get_int (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_BACK_BUTTON);
 
1955
 
 
1956
        /* Bounds checking */
 
1957
        if (new_back_button < 6 || new_back_button > UPPER_MOUSE_LIMIT)
 
1958
                return;
 
1959
 
 
1960
        mouse_back_button = new_back_button;
 
1961
}
 
1962
 
 
1963
static void
 
1964
mouse_forward_button_changed (gpointer callback_data)
 
1965
{
 
1966
        int new_forward_button;
 
1967
 
 
1968
        new_forward_button = g_settings_get_int (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_FORWARD_BUTTON);
 
1969
 
 
1970
        /* Bounds checking */
 
1971
        if (new_forward_button < 6 || new_forward_button > UPPER_MOUSE_LIMIT)
 
1972
                return;
 
1973
 
 
1974
        mouse_forward_button = new_forward_button;
 
1975
}
 
1976
 
 
1977
static void
 
1978
use_extra_mouse_buttons_changed (gpointer callback_data)
 
1979
{
 
1980
        mouse_extra_buttons = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS);
 
1981
}
 
1982
 
 
1983
 
 
1984
/*
 
1985
 * Main API
 
1986
 */
 
1987
 
 
1988
static void
 
1989
nautilus_window_init (NautilusWindow *window)
 
1990
{
 
1991
        window->details = G_TYPE_INSTANCE_GET_PRIVATE (window, NAUTILUS_TYPE_WINDOW, NautilusWindowDetails);
 
1992
 
 
1993
        window->details->panes = NULL;
 
1994
        window->details->active_pane = NULL;
 
1995
 
 
1996
        window->details->show_hidden_files_mode = NAUTILUS_WINDOW_SHOW_HIDDEN_FILES_DEFAULT;
 
1997
 
 
1998
        /* Set initial window title */
 
1999
        gtk_window_set_title (GTK_WINDOW (window), _("Nautilus"));
 
2000
}
 
2001
 
 
2002
static NautilusIconInfo *
 
2003
real_get_icon (NautilusWindow *window,
 
2004
               NautilusWindowSlot *slot)
 
2005
{
 
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);
 
2009
}
 
2010
 
 
2011
static void
 
2012
real_window_close (NautilusWindow *window)
 
2013
{
 
2014
        g_return_if_fail (NAUTILUS_IS_WINDOW (window));
 
2015
 
 
2016
        nautilus_window_save_geometry (window);
 
2017
 
 
2018
        gtk_widget_destroy (GTK_WIDGET (window));
 
2019
}
 
2020
 
 
2021
static void
 
2022
nautilus_window_class_init (NautilusWindowClass *class)
 
2023
{
 
2024
        GtkBindingSet *binding_set;
 
2025
        GObjectClass *oclass = G_OBJECT_CLASS (class);
 
2026
        GtkWidgetClass *wclass = GTK_WIDGET_CLASS (class);
 
2027
 
 
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;
 
2032
 
 
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;
 
2041
 
 
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;
 
2046
 
 
2047
        properties[PROP_DISABLE_CHROME] =
 
2048
                g_param_spec_boolean ("disable-chrome",
 
2049
                                      "Disable chrome",
 
2050
                                      "Disable window chrome, for the desktop",
 
2051
                                      FALSE,
 
2052
                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
 
2053
                                      G_PARAM_STATIC_STRINGS);
 
2054
 
 
2055
        signals[GO_UP] =
 
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);
 
2063
        signals[RELOAD] =
 
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),
 
2068
                              NULL, NULL,
 
2069
                              g_cclosure_marshal_VOID__VOID,
 
2070
                              G_TYPE_NONE, 0);
 
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),
 
2076
                              NULL, NULL,
 
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),
 
2082
                              G_SIGNAL_RUN_LAST,
 
2083
                              0,
 
2084
                              NULL, NULL,
 
2085
                              g_cclosure_marshal_generic,
 
2086
                              G_TYPE_NONE, 5,
 
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),
 
2092
                              G_SIGNAL_RUN_LAST,
 
2093
                              0,
 
2094
                              NULL, NULL,
 
2095
                              g_cclosure_marshal_VOID__VOID,
 
2096
                              G_TYPE_NONE, 0);
 
2097
 
 
2098
        signals[HIDDEN_FILES_MODE_CHANGED] =
 
2099
                g_signal_new ("hidden_files_mode_changed",
 
2100
                              G_TYPE_FROM_CLASS (class),
 
2101
                              G_SIGNAL_RUN_LAST,
 
2102
                              0,
 
2103
                              NULL, NULL,
 
2104
                              g_cclosure_marshal_VOID__VOID,
 
2105
                              G_TYPE_NONE, 0);
 
2106
 
 
2107
        signals[LOADING_URI] =
 
2108
                g_signal_new ("loading_uri",
 
2109
                              G_TYPE_FROM_CLASS (class),
 
2110
                              G_SIGNAL_RUN_LAST,
 
2111
                              0,
 
2112
                              NULL, NULL,
 
2113
                              g_cclosure_marshal_VOID__STRING,
 
2114
                              G_TYPE_NONE, 1,
 
2115
                              G_TYPE_STRING);
 
2116
 
 
2117
        binding_set = gtk_binding_set_by_class (class);
 
2118
        gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
 
2119
                                      "go_up", 1,
 
2120
                                      G_TYPE_BOOLEAN, FALSE);
 
2121
        gtk_binding_entry_add_signal (binding_set, GDK_KEY_F5, 0,
 
2122
                                      "reload", 0);
 
2123
        gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, 0,
 
2124
                                      "prompt-for-location", 1,
 
2125
                                      G_TYPE_STRING, "/");
 
2126
 
 
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;
 
2130
 
 
2131
        g_signal_connect_swapped (nautilus_preferences,
 
2132
                                  "changed::" NAUTILUS_PREFERENCES_MOUSE_BACK_BUTTON,
 
2133
                                  G_CALLBACK(mouse_back_button_changed),
 
2134
                                  NULL);
 
2135
 
 
2136
        g_signal_connect_swapped (nautilus_preferences,
 
2137
                                  "changed::" NAUTILUS_PREFERENCES_MOUSE_FORWARD_BUTTON,
 
2138
                                  G_CALLBACK(mouse_forward_button_changed),
 
2139
                                  NULL);
 
2140
 
 
2141
        g_signal_connect_swapped (nautilus_preferences,
 
2142
                                  "changed::" NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS,
 
2143
                                  G_CALLBACK(use_extra_mouse_buttons_changed),
 
2144
                                  NULL);
 
2145
 
 
2146
        g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
 
2147
        g_type_class_add_private (oclass, sizeof (NautilusWindowDetails));
 
2148
}
 
2149
 
 
2150
void
 
2151
nautilus_window_split_view_on (NautilusWindow *window)
 
2152
{
 
2153
        NautilusWindowSlot *slot, *old_active_slot;
 
2154
        GFile *location;
 
2155
 
 
2156
        old_active_slot = nautilus_window_get_active_slot (window);
 
2157
        slot = create_extra_pane (window);
 
2158
 
 
2159
        location = NULL;
 
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);
 
2165
                                location = NULL;
 
2166
                        }
 
2167
                }
 
2168
        }
 
2169
        if (location == NULL) {
 
2170
                location = g_file_new_for_path (g_get_home_dir ());
 
2171
        }
 
2172
 
 
2173
        nautilus_window_slot_go_to (slot, location, FALSE);
 
2174
        g_object_unref (location);
 
2175
 
 
2176
        window_set_search_action_text (window, FALSE);
 
2177
}
 
2178
 
 
2179
void
 
2180
nautilus_window_split_view_off (NautilusWindow *window)
 
2181
{
 
2182
        NautilusWindowPane *pane, *active_pane;
 
2183
        GList *l, *next;
 
2184
 
 
2185
        g_return_if_fail (window);
 
2186
 
 
2187
        active_pane = window->details->active_pane;
 
2188
 
 
2189
        /* delete all panes except the first (main) pane */
 
2190
        for (l = window->details->panes; l != NULL; l = next) {
 
2191
                next = l->next;
 
2192
                pane = l->data;
 
2193
                if (pane != active_pane) {
 
2194
                        nautilus_window_close_pane (pane);
 
2195
                }
 
2196
        }
 
2197
 
 
2198
        nautilus_window_set_active_pane (window, active_pane);
 
2199
        nautilus_navigation_state_set_master (window->details->nav_state,
 
2200
                                              active_pane->action_group);
 
2201
 
 
2202
        nautilus_window_update_show_hide_menu_items (window);
 
2203
        nautilus_window_update_split_view_actions_sensitivity (window);
 
2204
 
 
2205
        window_set_search_action_text (window, TRUE);
 
2206
}
 
2207
 
 
2208
gboolean
 
2209
nautilus_window_split_view_showing (NautilusWindow *window)
 
2210
{
 
2211
        return g_list_length (NAUTILUS_WINDOW (window)->details->panes) > 1;
 
2212
}