No issues found
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-desktop-window.h"
38 #include "nautilus-location-entry.h"
39 #include "nautilus-mime-actions.h"
40 #include "nautilus-notebook.h"
41 #include "nautilus-places-sidebar.h"
42 #include "nautilus-pathbar.h"
43 #include "nautilus-toolbar.h"
44 #include "nautilus-view-factory.h"
45 #include "nautilus-window-manage-views.h"
46 #include "nautilus-window-slot.h"
47 #include "nautilus-list-view.h"
48 #include "nautilus-canvas-view.h"
49
50 #include <eel/eel-debug.h>
51 #include <eel/eel-gtk-extensions.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-profile.h>
65 #include <libnautilus-private/nautilus-clipboard.h>
66 #include <libnautilus-private/nautilus-search-directory.h>
67 #include <libnautilus-private/nautilus-signaller.h>
68
69 #define DEBUG_FLAG NAUTILUS_DEBUG_WINDOW
70 #include <libnautilus-private/nautilus-debug.h>
71
72 #include <math.h>
73 #include <sys/time.h>
74
75 /* dock items */
76 #define MAX_TITLE_LENGTH 180
77
78 /* Forward and back buttons on the mouse */
79 static gboolean mouse_extra_buttons = TRUE;
80 static int mouse_forward_button = 9;
81 static int mouse_back_button = 8;
82
83 static void mouse_back_button_changed (gpointer callback_data);
84 static void mouse_forward_button_changed (gpointer callback_data);
85 static void use_extra_mouse_buttons_changed (gpointer callback_data);
86
87 /* Sanity check: highest mouse button value I could find was 14. 5 is our
88 * lower threshold (well-documented to be the one of the button events for the
89 * scrollwheel), so it's hardcoded in the functions below. However, if you have
90 * a button that registers higher and want to map it, file a bug and
91 * we'll move the bar. Makes you wonder why the X guys don't have
92 * defined values for these like the XKB stuff, huh?
93 */
94 #define UPPER_MOUSE_LIMIT 14
95
96 enum {
97 PROP_DISABLE_CHROME = 1,
98 NUM_PROPERTIES,
99 };
100
101 enum {
102 LOADING_URI,
103 SLOT_ADDED,
104 SLOT_REMOVED,
105 LAST_SIGNAL
106 };
107
108 static guint signals[LAST_SIGNAL] = { 0 };
109 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
110
111 G_DEFINE_TYPE (NautilusWindow, nautilus_window, GTK_TYPE_APPLICATION_WINDOW);
112
113 static const struct {
114 unsigned int keyval;
115 const char *action;
116 } extra_window_keybindings [] = {
117 #ifdef HAVE_X11_XF86KEYSYM_H
118 { XF86XK_AddFavorite, NAUTILUS_ACTION_ADD_BOOKMARK },
119 { XF86XK_Favorites, NAUTILUS_ACTION_EDIT_BOOKMARKS },
120 { XF86XK_Go, NAUTILUS_ACTION_ENTER_LOCATION },
121 { XF86XK_HomePage, NAUTILUS_ACTION_GO_HOME },
122 { XF86XK_OpenURL, NAUTILUS_ACTION_ENTER_LOCATION },
123 { XF86XK_Refresh, NAUTILUS_ACTION_RELOAD },
124 { XF86XK_Reload, NAUTILUS_ACTION_RELOAD },
125 { XF86XK_Search, NAUTILUS_ACTION_SEARCH },
126 { XF86XK_Start, NAUTILUS_ACTION_GO_HOME },
127 { XF86XK_Stop, NAUTILUS_ACTION_STOP },
128 { XF86XK_ZoomIn, NAUTILUS_ACTION_ZOOM_IN },
129 { XF86XK_ZoomOut, NAUTILUS_ACTION_ZOOM_OUT },
130 { XF86XK_Back, NAUTILUS_ACTION_BACK },
131 { XF86XK_Forward, NAUTILUS_ACTION_FORWARD }
132
133 #endif
134 };
135
136 void
137 nautilus_window_go_to (NautilusWindow *window, GFile *location)
138 {
139 g_return_if_fail (NAUTILUS_IS_WINDOW (window));
140
141 nautilus_window_slot_open_location (nautilus_window_get_active_slot (window),
142 location, 0);
143 }
144
145 void
146 nautilus_window_go_to_full (NautilusWindow *window,
147 GFile *location,
148 NautilusWindowGoToCallback callback,
149 gpointer user_data)
150 {
151 g_return_if_fail (NAUTILUS_IS_WINDOW (window));
152
153 nautilus_window_slot_open_location_full (nautilus_window_get_active_slot (window),
154 location, 0, NULL, callback, user_data);
155 }
156
157 static int
158 bookmark_list_get_uri_index (GList *list, GFile *location)
159 {
160 NautilusBookmark *bookmark;
161 GList *l;
162 GFile *tmp;
163 int i;
164
165 g_return_val_if_fail (location != NULL, -1);
166
167 for (i = 0, l = list; l != NULL; i++, l = l->next) {
168 bookmark = NAUTILUS_BOOKMARK (l->data);
169
170 tmp = nautilus_bookmark_get_location (bookmark);
171 if (g_file_equal (location, tmp)) {
172 g_object_unref (tmp);
173 return i;
174 }
175 g_object_unref (tmp);
176 }
177
178 return -1;
179 }
180
181 static void
182 unset_focus_widget (NautilusWindow *window)
183 {
184 if (window->details->last_focus_widget != NULL) {
185 g_object_remove_weak_pointer (G_OBJECT (window->details->last_focus_widget),
186 (gpointer *) &window->details->last_focus_widget);
187 window->details->last_focus_widget = NULL;
188 }
189 }
190
191 static void
192 remember_focus_widget (NautilusWindow *window)
193 {
194 GtkWidget *focus_widget;
195
196 focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
197 if (focus_widget != NULL) {
198 unset_focus_widget (window);
199
200 window->details->last_focus_widget = focus_widget;
201 g_object_add_weak_pointer (G_OBJECT (focus_widget),
202 (gpointer *) &(window->details->last_focus_widget));
203 }
204 }
205
206 void
207 nautilus_window_grab_focus (NautilusWindow *window)
208 {
209 if (NAUTILUS_IS_WINDOW (window) &&
210 window->details->active_slot &&
211 window->details->active_slot->content_view) {
212 nautilus_view_grab_focus (window->details->active_slot->content_view);
213 }
214 }
215
216 static void
217 restore_focus_widget (NautilusWindow *window)
218 {
219 if (window->details->last_focus_widget != NULL) {
220 if (NAUTILUS_IS_VIEW (window->details->last_focus_widget)) {
221 nautilus_view_grab_focus (NAUTILUS_VIEW (window->details->last_focus_widget));
222 } else {
223 gtk_widget_grab_focus (window->details->last_focus_widget);
224 }
225
226 unset_focus_widget (window);
227 }
228 }
229
230 static void
231 location_entry_cancel_callback (GtkWidget *widget,
232 NautilusWindow *window)
233 {
234 nautilus_toolbar_set_show_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar), FALSE);
235
236 restore_focus_widget (window);
237 }
238
239 static void
240 location_entry_location_changed_callback (GtkWidget *widget,
241 GFile *location,
242 NautilusWindow *window)
243 {
244 nautilus_toolbar_set_show_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar), FALSE);
245
246 restore_focus_widget (window);
247
248 nautilus_window_slot_open_location (window->details->active_slot, location, 0);
249 }
250
251 static gboolean
252 notebook_switch_page_cb (GtkNotebook *notebook,
253 GtkWidget *page,
254 unsigned int page_num,
255 NautilusWindow *window)
256 {
257 NautilusWindowSlot *slot;
258 GtkWidget *widget;
259
260 widget = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->details->notebook), page_num);
261 g_assert (widget != NULL);
262
263 /* find slot corresponding to the target page */
264 slot = NAUTILUS_WINDOW_SLOT (widget);
265 g_assert (slot != NULL);
266
267 nautilus_window_set_active_slot (nautilus_window_slot_get_window (slot),
268 slot);
269
270 return FALSE;
271 }
272
273 static void
274 close_slot (NautilusWindow *window,
275 NautilusWindowSlot *slot,
276 gboolean remove_from_notebook)
277 {
278 int page_num;
279 GtkNotebook *notebook;
280
281 g_assert (NAUTILUS_IS_WINDOW_SLOT (slot));
282
283 DEBUG ("Closing slot %p", slot);
284
285 nautilus_window_manage_views_close_slot (slot);
286 window->details->slots = g_list_remove (window->details->slots, slot);
287
288 g_signal_emit (window, signals[SLOT_REMOVED], 0, slot);
289
290 notebook = GTK_NOTEBOOK (window->details->notebook);
291
292 if (remove_from_notebook) {
293 page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (slot));
294 g_assert (page_num >= 0);
295
296 /* this will call gtk_widget_destroy on the slot */
297 gtk_notebook_remove_page (notebook, page_num);
298 }
299 }
300
301 NautilusWindowSlot *
302 nautilus_window_open_slot (NautilusWindow *window,
303 NautilusWindowOpenSlotFlags flags)
304 {
305 NautilusWindowSlot *slot;
306
307 g_assert (NAUTILUS_IS_WINDOW (window));
308
309 slot = nautilus_window_slot_new (window);
310
311 g_signal_handlers_block_by_func (window->details->notebook,
312 G_CALLBACK (notebook_switch_page_cb),
313 window);
314 nautilus_notebook_add_tab (NAUTILUS_NOTEBOOK (window->details->notebook),
315 slot,
316 (flags & NAUTILUS_WINDOW_OPEN_SLOT_APPEND) != 0 ?
317 -1 :
318 gtk_notebook_get_current_page (GTK_NOTEBOOK (window->details->notebook)) + 1,
319 FALSE);
320 g_signal_handlers_unblock_by_func (window->details->notebook,
321 G_CALLBACK (notebook_switch_page_cb),
322 window);
323
324 window->details->slots = g_list_append (window->details->slots, slot);
325 g_signal_emit (window, signals[SLOT_ADDED], 0, slot);
326
327 return slot;
328 }
329
330 void
331 nautilus_window_new_tab (NautilusWindow *window)
332 {
333 NautilusWindowSlot *current_slot;
334 NautilusWindowSlot *new_slot;
335 NautilusWindowOpenFlags flags;
336 GFile *location;
337 int new_slot_position;
338 char *scheme;
339
340 current_slot = nautilus_window_get_active_slot (window);
341 location = nautilus_window_slot_get_location (current_slot);
342
343 if (location != NULL) {
344 flags = 0;
345
346 new_slot_position = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION);
347 if (new_slot_position == NAUTILUS_NEW_TAB_POSITION_END) {
348 flags = NAUTILUS_WINDOW_OPEN_SLOT_APPEND;
349 }
350
351 scheme = g_file_get_uri_scheme (location);
352 if (!strcmp (scheme, "x-nautilus-search")) {
353 g_object_unref (location);
354 location = g_file_new_for_path (g_get_home_dir ());
355 }
356 g_free (scheme);
357
358 new_slot = nautilus_window_open_slot (window, flags);
359 nautilus_window_set_active_slot (window, new_slot);
360 nautilus_window_slot_open_location (new_slot, location, 0);
361 g_object_unref (location);
362 }
363 }
364
365 static void
366 update_cursor (NautilusWindow *window)
367 {
368 NautilusWindowSlot *slot;
369 GdkCursor *cursor;
370
371 slot = nautilus_window_get_active_slot (window);
372
373 if (slot->allow_stop) {
374 cursor = gdk_cursor_new (GDK_WATCH);
375 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), cursor);
376 g_object_unref (cursor);
377 } else {
378 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
379 }
380 }
381
382 void
383 nautilus_window_sync_allow_stop (NautilusWindow *window,
384 NautilusWindowSlot *slot)
385 {
386 GtkAction *stop_action;
387 GtkAction *reload_action;
388 gboolean allow_stop, slot_is_active;
389
390 stop_action = gtk_action_group_get_action (nautilus_window_get_main_action_group (window),
391 NAUTILUS_ACTION_STOP);
392 reload_action = gtk_action_group_get_action (nautilus_window_get_main_action_group (window),
393 NAUTILUS_ACTION_RELOAD);
394 allow_stop = gtk_action_get_sensitive (stop_action);
395
396 slot_is_active = (slot == nautilus_window_get_active_slot (window));
397
398 if (!slot_is_active ||
399 allow_stop != slot->allow_stop) {
400 if (slot_is_active) {
401 gtk_action_set_visible (stop_action, slot->allow_stop);
402 gtk_action_set_visible (reload_action, !slot->allow_stop);
403 }
404
405 if (gtk_widget_get_realized (GTK_WIDGET (window))) {
406 update_cursor (window);
407 }
408
409 nautilus_notebook_sync_loading (NAUTILUS_NOTEBOOK (window->details->notebook), slot);
410 }
411 }
412
413 void
414 nautilus_window_prompt_for_location (NautilusWindow *window,
415 const char *initial)
416 {
417 GtkWidget *entry;
418
419 g_return_if_fail (NAUTILUS_IS_WINDOW (window));
420
421 entry = nautilus_window_ensure_location_entry (window);
422
423 if (initial) {
424 nautilus_location_entry_set_uri (NAUTILUS_LOCATION_ENTRY (entry),
425 initial);
426 }
427 }
428
429 /* Code should never force the window taller than this size.
430 * (The user can still stretch the window taller if desired).
431 */
432 static guint
433 get_max_forced_height (GdkScreen *screen)
434 {
435 return (gdk_screen_get_height (screen) * 90) / 100;
436 }
437
438 /* Code should never force the window wider than this size.
439 * (The user can still stretch the window wider if desired).
440 */
441 static guint
442 get_max_forced_width (GdkScreen *screen)
443 {
444 return (gdk_screen_get_width (screen) * 90) / 100;
445 }
446
447 /* This must be called when construction of NautilusWindow is finished,
448 * since it depends on the type of the argument, which isn't decided at
449 * construction time.
450 */
451 static void
452 nautilus_window_set_initial_window_geometry (NautilusWindow *window)
453 {
454 GdkScreen *screen;
455 guint max_width_for_screen, max_height_for_screen;
456 guint default_width, default_height;
457
458 screen = gtk_window_get_screen (GTK_WINDOW (window));
459
460 max_width_for_screen = get_max_forced_width (screen);
461 max_height_for_screen = get_max_forced_height (screen);
462
463 default_width = NAUTILUS_WINDOW_DEFAULT_WIDTH;
464 default_height = NAUTILUS_WINDOW_DEFAULT_HEIGHT;
465
466 gtk_window_set_default_size (GTK_WINDOW (window),
467 MIN (default_width,
468 max_width_for_screen),
469 MIN (default_height,
470 max_height_for_screen));
471 }
472
473 static gboolean
474 save_sidebar_width_cb (gpointer user_data)
475 {
476 NautilusWindow *window = user_data;
477
478 window->details->sidebar_width_handler_id = 0;
479
480 DEBUG ("Saving sidebar width: %d", window->details->side_pane_width);
481
482 g_settings_set_int (nautilus_window_state,
483 NAUTILUS_WINDOW_STATE_SIDEBAR_WIDTH,
484 window->details->side_pane_width);
485
486 return FALSE;
487 }
488
489 /* side pane helpers */
490 static void
491 side_pane_size_allocate_callback (GtkWidget *widget,
492 GtkAllocation *allocation,
493 gpointer user_data)
494 {
495 NautilusWindow *window;
496
497 window = user_data;
498
499 if (window->details->sidebar_width_handler_id != 0) {
500 g_source_remove (window->details->sidebar_width_handler_id);
501 window->details->sidebar_width_handler_id = 0;
502 }
503
504 if (allocation->width != window->details->side_pane_width &&
505 allocation->width > 1) {
506 window->details->side_pane_width = allocation->width;
507
508 window->details->sidebar_width_handler_id =
509 g_idle_add (save_sidebar_width_cb, window);
510 }
511 }
512
513 static void
514 setup_side_pane_width (NautilusWindow *window)
515 {
516 g_return_if_fail (window->details->sidebar != NULL);
517
518 window->details->side_pane_width =
519 g_settings_get_int (nautilus_window_state,
520 NAUTILUS_WINDOW_STATE_SIDEBAR_WIDTH);
521
522 gtk_paned_set_position (GTK_PANED (window->details->content_paned),
523 window->details->side_pane_width);
524 }
525
526 static void
527 nautilus_window_set_up_sidebar (NautilusWindow *window)
528 {
529 GtkWidget *sidebar;
530
531 window->details->sidebar = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
532 gtk_style_context_add_class (gtk_widget_get_style_context (window->details->sidebar),
533 GTK_STYLE_CLASS_SIDEBAR);
534
535 gtk_paned_pack1 (GTK_PANED (window->details->content_paned),
536 GTK_WIDGET (window->details->sidebar),
537 FALSE, FALSE);
538
539 setup_side_pane_width (window);
540 g_signal_connect (window->details->sidebar,
541 "size_allocate",
542 G_CALLBACK (side_pane_size_allocate_callback),
543 window);
544
545 sidebar = nautilus_places_sidebar_new (window);
546 gtk_box_pack_start (GTK_BOX (window->details->sidebar), sidebar, TRUE, TRUE, 0);
547 gtk_widget_show (sidebar);
548 gtk_widget_show (GTK_WIDGET (window->details->sidebar));
549 }
550
551 static void
552 nautilus_window_tear_down_sidebar (NautilusWindow *window)
553 {
554 DEBUG ("Destroying sidebar");
555
556 if (window->details->sidebar != NULL) {
557 gtk_widget_destroy (GTK_WIDGET (window->details->sidebar));
558 window->details->sidebar = NULL;
559 }
560 }
561
562 void
563 nautilus_window_hide_sidebar (NautilusWindow *window)
564 {
565 DEBUG ("Called hide_sidebar()");
566
567 if (window->details->sidebar == NULL) {
568 return;
569 }
570
571 nautilus_window_tear_down_sidebar (window);
572 }
573
574 void
575 nautilus_window_show_sidebar (NautilusWindow *window)
576 {
577 DEBUG ("Called show_sidebar()");
578
579 if (window->details->sidebar != NULL) {
580 return;
581 }
582
583 if (window->details->disable_chrome) {
584 return;
585 }
586
587 nautilus_window_set_up_sidebar (window);
588 }
589
590 gboolean
591 nautilus_window_disable_chrome_mapping (GValue *value,
592 GVariant *variant,
593 gpointer user_data)
594 {
595 NautilusWindow *window = user_data;
596
597 g_value_set_boolean (value,
598 g_variant_get_boolean (variant) &&
599 !window->details->disable_chrome);
600
601 return TRUE;
602 }
603
604 static inline NautilusWindowSlot *
605 get_first_inactive_slot (NautilusWindow *window)
606 {
607 GList *l;
608 NautilusWindowSlot *slot;
609
610 for (l = window->details->slots; l != NULL; l = l->next) {
611 slot = NAUTILUS_WINDOW_SLOT (l->data);
612 if (slot != window->details->active_slot) {
613 return slot;
614 }
615 }
616
617 return NULL;
618 }
619
620 void
621 nautilus_window_slot_close (NautilusWindow *window,
622 NautilusWindowSlot *slot)
623 {
624 NautilusWindowSlot *next_slot;
625
626 DEBUG ("Requesting to remove slot %p from window %p", slot, window);
627 if (window == NULL)
628 return;
629
630 if (window->details->active_slot == slot) {
631 next_slot = get_first_inactive_slot (window);
632 nautilus_window_set_active_slot (window, next_slot);
633 }
634
635 close_slot (window, slot, TRUE);
636
637 /* If that was the last slot in the window, close the window. */
638 if (window->details->slots == NULL) {
639 DEBUG ("Last slot removed, closing the window");
640 nautilus_window_close (window);
641 }
642 }
643
644 void
645 nautilus_window_sync_search_widgets (NautilusWindow *window)
646 {
647 NautilusDirectory *directory;
648 NautilusWindowSlot *slot;
649 gboolean visible;
650
651 slot = window->details->active_slot;
652 visible = slot->search_visible;
653
654 directory = nautilus_directory_get (slot->location);
655 if (NAUTILUS_IS_SEARCH_DIRECTORY (directory)) {
656 visible = TRUE;
657 }
658
659 nautilus_window_slot_set_search_visible (slot, visible);
660 nautilus_directory_unref (directory);
661 }
662
663 void
664 nautilus_window_sync_location_widgets (NautilusWindow *window)
665 {
666 NautilusWindowSlot *slot, *active_slot;
667 GtkActionGroup *action_group;
668 GtkAction *action;
669
670 slot = window->details->active_slot;
671
672 /* Change the location bar and path bar to match the current location. */
673 if (slot->location != NULL) {
674 char *uri;
675 GtkWidget *location_entry;
676 GtkWidget *path_bar;
677
678 location_entry = nautilus_toolbar_get_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar));
679 path_bar = nautilus_toolbar_get_path_bar (NAUTILUS_TOOLBAR (window->details->toolbar));
680
681 /* this may be NULL if we just created the slot */
682 uri = nautilus_window_slot_get_location_uri (slot);
683 nautilus_location_entry_set_uri (NAUTILUS_LOCATION_ENTRY (location_entry), uri);
684 g_free (uri);
685 nautilus_path_bar_set_path (NAUTILUS_PATH_BAR (path_bar), slot->location);
686 }
687
688 nautilus_window_sync_up_button (window);
689
690 /* Check if the back and forward buttons need enabling or disabling. */
691 active_slot = nautilus_window_get_active_slot (window);
692 action_group = nautilus_window_get_main_action_group (window);
693
694 action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_BACK);
695 gtk_action_set_sensitive (action, active_slot->back_list != NULL);
696
697 action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_FORWARD);
698 gtk_action_set_sensitive (action, active_slot->forward_list != NULL);
699 }
700
701 GtkWidget *
702 nautilus_window_ensure_location_entry (NautilusWindow *window)
703 {
704 GtkWidget *location_entry;
705
706 remember_focus_widget (window);
707
708 nautilus_toolbar_set_show_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar), TRUE);
709
710 location_entry = nautilus_toolbar_get_location_entry (NAUTILUS_TOOLBAR (window->details->toolbar));
711 nautilus_location_entry_focus (NAUTILUS_LOCATION_ENTRY (location_entry));
712
713 return location_entry;
714 }
715
716 static void
717 path_bar_location_changed_callback (GtkWidget *widget,
718 GFile *location,
719 NautilusWindow *window)
720 {
721 NautilusWindowSlot *slot;
722 int i;
723
724 slot = window->details->active_slot;
725 /* check whether we already visited the target location */
726 i = bookmark_list_get_uri_index (slot->back_list, location);
727 if (i >= 0) {
728 nautilus_window_back_or_forward (window, TRUE, i, 0);
729 } else {
730 nautilus_window_slot_open_location (slot, location, 0);
731 }
732 }
733
734 static void
735 path_bar_path_event_callback (NautilusPathBar *path_bar,
736 GFile *location,
737 GdkEventButton *event,
738 NautilusWindow *window)
739 {
740 NautilusWindowSlot *slot;
741 NautilusWindowOpenFlags flags;
742 int mask;
743 NautilusView *view;
744 char *uri;
745
746 if (event->type == GDK_BUTTON_RELEASE) {
747 mask = event->state & gtk_accelerator_get_default_mod_mask ();
748 flags = 0;
749
750 if (event->button == 2 && mask == 0) {
751 flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
752 } else if (event->button == 1 && mask == GDK_CONTROL_MASK) {
753 flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW;
754 }
755
756 if (flags != 0) {
757 slot = nautilus_window_get_active_slot (window);
758 nautilus_window_slot_open_location (slot, location, flags);
759 }
760 } else if (event->button == 3) {
761 slot = nautilus_window_get_active_slot (window);
762 view = slot->content_view;
763 if (view != NULL) {
764 uri = g_file_get_uri (location);
765 nautilus_view_pop_up_location_context_menu (view, event, uri);
766 g_free (uri);
767 }
768 }
769 }
770
771 static void
772 notebook_popup_menu_new_tab_cb (GtkMenuItem *menuitem,
773 gpointer user_data)
774 {
775 NautilusWindow *window = user_data;
776
777 nautilus_window_new_tab (window);
778 }
779
780 static void
781 notebook_popup_menu_move_left_cb (GtkMenuItem *menuitem,
782 gpointer user_data)
783 {
784 NautilusWindow *window = user_data;
785
786 nautilus_notebook_reorder_current_child_relative (NAUTILUS_NOTEBOOK (window->details->notebook), -1);
787 }
788
789 static void
790 notebook_popup_menu_move_right_cb (GtkMenuItem *menuitem,
791 gpointer user_data)
792 {
793 NautilusWindow *window = user_data;
794
795 nautilus_notebook_reorder_current_child_relative (NAUTILUS_NOTEBOOK (window->details->notebook), 1);
796 }
797
798 static void
799 notebook_popup_menu_close_cb (GtkMenuItem *menuitem,
800 gpointer user_data)
801 {
802 NautilusWindow *window = user_data;
803 NautilusWindowSlot *slot;
804
805 slot = window->details->active_slot;
806 nautilus_window_slot_close (window, slot);
807 }
808
809 static void
810 notebook_popup_menu_show (NautilusWindow *window,
811 GdkEventButton *event)
812 {
813 GtkWidget *popup;
814 GtkWidget *item;
815 GtkWidget *image;
816 int button, event_time;
817 gboolean can_move_left, can_move_right;
818 NautilusNotebook *notebook;
819
820 notebook = NAUTILUS_NOTEBOOK (window->details->notebook);
821
822 can_move_left = nautilus_notebook_can_reorder_current_child_relative (notebook, -1);
823 can_move_right = nautilus_notebook_can_reorder_current_child_relative (notebook, 1);
824
825 popup = gtk_menu_new ();
826
827 item = gtk_menu_item_new_with_mnemonic (_("_New Tab"));
828 g_signal_connect (item, "activate",
829 G_CALLBACK (notebook_popup_menu_new_tab_cb),
830 window);
831 gtk_menu_shell_append (GTK_MENU_SHELL (popup),
832 item);
833
834 gtk_menu_shell_append (GTK_MENU_SHELL (popup),
835 gtk_separator_menu_item_new ());
836
837 item = gtk_menu_item_new_with_mnemonic (_("Move Tab _Left"));
838 g_signal_connect (item, "activate",
839 G_CALLBACK (notebook_popup_menu_move_left_cb),
840 window);
841 gtk_menu_shell_append (GTK_MENU_SHELL (popup),
842 item);
843 gtk_widget_set_sensitive (item, can_move_left);
844
845 item = gtk_menu_item_new_with_mnemonic (_("Move Tab _Right"));
846 g_signal_connect (item, "activate",
847 G_CALLBACK (notebook_popup_menu_move_right_cb),
848 window);
849 gtk_menu_shell_append (GTK_MENU_SHELL (popup),
850 item);
851 gtk_widget_set_sensitive (item, can_move_right);
852
853 gtk_menu_shell_append (GTK_MENU_SHELL (popup),
854 gtk_separator_menu_item_new ());
855
856 item = gtk_image_menu_item_new_with_mnemonic (_("_Close Tab"));
857 image = gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
858 gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
859 g_signal_connect (item, "activate",
860 G_CALLBACK (notebook_popup_menu_close_cb), window);
861 gtk_menu_shell_append (GTK_MENU_SHELL (popup),
862 item);
863
864 gtk_widget_show_all (popup);
865
866 if (event) {
867 button = event->button;
868 event_time = event->time;
869 } else {
870 button = 0;
871 event_time = gtk_get_current_event_time ();
872 }
873
874 /* TODO is this correct? */
875 gtk_menu_attach_to_widget (GTK_MENU (popup),
876 window->details->notebook,
877 NULL);
878
879 gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
880 button, event_time);
881 }
882
883 /* emitted when the user clicks the "close" button of tabs */
884 static void
885 notebook_tab_close_requested (NautilusNotebook *notebook,
886 NautilusWindowSlot *slot,
887 NautilusWindow *window)
888 {
889 nautilus_window_slot_close (window, slot);
890 }
891
892 static gboolean
893 notebook_button_press_cb (GtkWidget *widget,
894 GdkEventButton *event,
895 gpointer user_data)
896 {
897 NautilusWindow *window = user_data;
898
899 if (GDK_BUTTON_PRESS == event->type && 3 == event->button) {
900 notebook_popup_menu_show (window, event);
901 return TRUE;
902 }
903
904 return FALSE;
905 }
906
907 static gboolean
908 notebook_popup_menu_cb (GtkWidget *widget,
909 gpointer user_data)
910 {
911 NautilusWindow *window = user_data;
912 notebook_popup_menu_show (window, NULL);
913 return TRUE;
914 }
915
916 static GtkWidget *
917 create_toolbar (NautilusWindow *window)
918 {
919 GtkSizeGroup *header_size_group;
920 GtkWidget *toolbar;
921 GtkWidget *path_bar;
922 GtkWidget *location_entry;
923
924 header_size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
925 gtk_size_group_set_ignore_hidden (header_size_group, FALSE);
926
927 /* build the toolbar */
928 toolbar = nautilus_toolbar_new (NAUTILUS_WINDOW (window));
929
930 g_object_bind_property (window, "disable-chrome",
931 toolbar, "visible",
932 G_BINDING_INVERT_BOOLEAN);
933
934 /* connect to the pathbar signals */
935 path_bar = nautilus_toolbar_get_path_bar (NAUTILUS_TOOLBAR (toolbar));
936 gtk_size_group_add_widget (header_size_group, path_bar);
937
938 g_signal_connect_object (path_bar, "path-clicked",
939 G_CALLBACK (path_bar_location_changed_callback), window, 0);
940 g_signal_connect_object (path_bar, "path-event",
941 G_CALLBACK (path_bar_path_event_callback), window, 0);
942
943 /* connect to the location entry signals */
944 location_entry = nautilus_toolbar_get_location_entry (NAUTILUS_TOOLBAR (toolbar));
945 gtk_size_group_add_widget (header_size_group, location_entry);
946
947 nautilus_clipboard_set_up_editable (GTK_EDITABLE (location_entry),
948 nautilus_window_get_ui_manager (NAUTILUS_WINDOW (window)),
949 TRUE);
950
951 g_signal_connect_object (location_entry, "location-changed",
952 G_CALLBACK (location_entry_location_changed_callback), window, 0);
953 g_signal_connect_object (location_entry, "cancel",
954 G_CALLBACK (location_entry_cancel_callback), window, 0);
955
956 g_object_unref (header_size_group);
957
958 return toolbar;
959 }
960
961 static void
962 notebook_num_pages_changed (NautilusWindow *window)
963 {
964 NautilusView *view;
965 NautilusWindowSlot *active_slot;
966
967 active_slot = nautilus_window_get_active_slot (window);
968 if (active_slot == NULL) {
969 return;
970 }
971 view = nautilus_window_slot_get_current_view (active_slot);
972 if (view == NULL) {
973 return;
974 }
975
976 /* Only add a shadow to the scrolled window when we're in a tabless
977 * notebook, since when the notebook has tabs, it will draw its own
978 * border.
979 */
980 if (g_list_length (window->details->slots) > 1 ||
981 NAUTILUS_IS_DESKTOP_WINDOW (window)) {
982 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view), GTK_SHADOW_NONE);
983 } else {
984 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view), GTK_SHADOW_IN);
985 }
986 }
987
988 static void
989 notebook_page_removed_cb (GtkNotebook *notebook,
990 GtkWidget *page,
991 guint page_num,
992 gpointer user_data)
993 {
994 NautilusWindow *window = user_data;
995 NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (page), *next_slot;
996 gboolean dnd_slot;
997
998 notebook_num_pages_changed (window);
999
1000 dnd_slot = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (slot), "dnd-window-slot"));
1001 if (!dnd_slot) {
1002 return;
1003 }
1004
1005 if (window->details->active_slot == slot) {
1006 next_slot = get_first_inactive_slot (window);
1007 nautilus_window_set_active_slot (window, next_slot);
1008 }
1009
1010 close_slot (window, slot, FALSE);
1011 }
1012
1013 static void
1014 notebook_page_added_cb (GtkNotebook *notebook,
1015 GtkWidget *page,
1016 guint page_num,
1017 gpointer user_data)
1018 {
1019 NautilusWindow *window = user_data;
1020 NautilusWindowSlot *slot = NAUTILUS_WINDOW_SLOT (page);
1021 NautilusWindowSlot *dummy_slot;
1022 gboolean dnd_slot;
1023
1024 /* It's too early here to call notebook_num_pages_changed(),
1025 * since the view might not be associagted to the slot yet.
1026 * Defer the call to nautilus_window_connect_content_view().
1027 */
1028
1029 dnd_slot = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (slot), "dnd-window-slot"));
1030 if (!dnd_slot) {
1031 return;
1032 }
1033
1034 g_object_set_data (G_OBJECT (page), "dnd-window-slot",
1035 GINT_TO_POINTER (FALSE));
1036
1037 nautilus_window_slot_set_window (slot, window);
1038 window->details->slots = g_list_append (window->details->slots, slot);
1039 g_signal_emit (window, signals[SLOT_ADDED], 0, slot);
1040
1041 nautilus_window_set_active_slot (window, slot);
1042
1043 dummy_slot = g_list_nth_data (window->details->slots, 0);
1044 if (dummy_slot != NULL) {
1045 close_slot (window, dummy_slot, TRUE);
1046 }
1047
1048 gtk_widget_show (GTK_WIDGET (window));
1049 }
1050
1051 static GtkNotebook *
1052 notebook_create_window_cb (GtkNotebook *notebook,
1053 GtkWidget *page,
1054 gint x,
1055 gint y,
1056 gpointer user_data)
1057 {
1058 NautilusApplication *app;
1059 NautilusWindow *new_window;
1060 NautilusWindowSlot *slot;
1061
1062 if (!NAUTILUS_IS_WINDOW_SLOT (page)) {
1063 return NULL;
1064 }
1065
1066 app = NAUTILUS_APPLICATION (g_application_get_default ());
1067 new_window = nautilus_application_create_window
1068 (app, gtk_widget_get_screen (GTK_WIDGET (notebook)));
1069
1070 slot = NAUTILUS_WINDOW_SLOT (page);
1071 g_object_set_data (G_OBJECT (slot), "dnd-window-slot",
1072 GINT_TO_POINTER (TRUE));
1073
1074 gtk_window_set_position (GTK_WINDOW (new_window), GTK_WIN_POS_MOUSE);
1075
1076 return GTK_NOTEBOOK (new_window->details->notebook);
1077 }
1078
1079 static GtkWidget *
1080 create_notebook (NautilusWindow *window)
1081 {
1082 GtkWidget *notebook;
1083
1084 notebook = g_object_new (NAUTILUS_TYPE_NOTEBOOK, NULL);
1085 g_signal_connect (notebook, "tab-close-request",
1086 G_CALLBACK (notebook_tab_close_requested),
1087 window);
1088 g_signal_connect (notebook, "popup-menu",
1089 G_CALLBACK (notebook_popup_menu_cb),
1090 window);
1091 g_signal_connect (notebook, "switch-page",
1092 G_CALLBACK (notebook_switch_page_cb),
1093 window);
1094 g_signal_connect (notebook, "create-window",
1095 G_CALLBACK (notebook_create_window_cb),
1096 window);
1097 g_signal_connect (notebook, "page-added",
1098 G_CALLBACK (notebook_page_added_cb),
1099 window);
1100 g_signal_connect (notebook, "page-removed",
1101 G_CALLBACK (notebook_page_removed_cb),
1102 window);
1103 g_signal_connect_after (notebook, "button-press-event",
1104 G_CALLBACK (notebook_button_press_cb),
1105 window);
1106
1107 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
1108 gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
1109 gtk_widget_show (notebook);
1110 gtk_container_set_border_width (GTK_CONTAINER (notebook), 0);
1111
1112 gtk_box_pack_start (GTK_BOX (window->details->main_view),
1113 notebook,
1114 TRUE, TRUE, 0);
1115
1116 return notebook;
1117 }
1118
1119 static void
1120 nautilus_window_constructed (GObject *self)
1121 {
1122 NautilusWindow *window;
1123 GtkWidget *grid;
1124 NautilusWindowSlot *slot;
1125
1126 window = NAUTILUS_WINDOW (self);
1127
1128 nautilus_profile_start (NULL);
1129
1130 G_OBJECT_CLASS (nautilus_window_parent_class)->constructed (self);
1131
1132 /* disable automatic menubar handling, since we show our regular
1133 * menubar together with the app menu.
1134 */
1135 gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (self), FALSE);
1136
1137 grid = gtk_grid_new ();
1138 gtk_orientable_set_orientation (GTK_ORIENTABLE (grid), GTK_ORIENTATION_VERTICAL);
1139 gtk_widget_show (grid);
1140 gtk_container_add (GTK_CONTAINER (window), grid);
1141
1142 nautilus_window_initialize_menus (window);
1143 nautilus_window_initialize_actions (window);
1144
1145 /* Register to menu provider extension signal managing menu updates */
1146 g_signal_connect_object (nautilus_signaller_get_current (), "popup_menu_changed",
1147 G_CALLBACK (nautilus_window_load_extension_menus), window, G_CONNECT_SWAPPED);
1148 window->details->toolbar = create_toolbar (window);
1149 gtk_container_add (GTK_CONTAINER (grid), window->details->toolbar);
1150 gtk_widget_set_hexpand (window->details->toolbar, TRUE);
1151 gtk_widget_set_vexpand (window->details->toolbar, FALSE);
1152 gtk_widget_show (window->details->toolbar);
1153
1154 window->details->content_paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
1155 gtk_widget_set_hexpand (window->details->content_paned, TRUE);
1156 gtk_widget_set_vexpand (window->details->content_paned, TRUE);
1157
1158 gtk_container_add (GTK_CONTAINER (grid), window->details->content_paned);
1159 gtk_widget_show (window->details->content_paned);
1160
1161 window->details->main_view = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1162 gtk_paned_pack2 (GTK_PANED (window->details->content_paned), window->details->main_view,
1163 TRUE, FALSE);
1164 gtk_widget_show (window->details->main_view);
1165
1166 window->details->notebook = create_notebook (window);
1167 nautilus_window_set_initial_window_geometry (window);
1168
1169 slot = nautilus_window_open_slot (window, 0);
1170 nautilus_window_set_active_slot (window, slot);
1171
1172 if (g_settings_get_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_START_WITH_SIDEBAR)) {
1173 nautilus_window_show_sidebar (window);
1174 } else {
1175 nautilus_window_hide_sidebar (window);
1176 }
1177
1178 nautilus_profile_end (NULL);
1179 }
1180
1181 static void
1182 nautilus_window_set_property (GObject *object,
1183 guint arg_id,
1184 const GValue *value,
1185 GParamSpec *pspec)
1186 {
1187 NautilusWindow *window;
1188
1189 window = NAUTILUS_WINDOW (object);
1190
1191 switch (arg_id) {
1192 case PROP_DISABLE_CHROME:
1193 window->details->disable_chrome = g_value_get_boolean (value);
1194 break;
1195 default:
1196 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
1197 break;
1198 }
1199 }
1200
1201 static void
1202 nautilus_window_get_property (GObject *object,
1203 guint arg_id,
1204 GValue *value,
1205 GParamSpec *pspec)
1206 {
1207 NautilusWindow *window;
1208
1209 window = NAUTILUS_WINDOW (object);
1210
1211 switch (arg_id) {
1212 case PROP_DISABLE_CHROME:
1213 g_value_set_boolean (value, window->details->disable_chrome);
1214 break;
1215 }
1216 }
1217
1218 static void
1219 destroy_slots_foreach (gpointer data,
1220 gpointer user_data)
1221 {
1222 NautilusWindowSlot *slot = data;
1223 NautilusWindow *window = user_data;
1224
1225 close_slot (window, slot, TRUE);
1226 }
1227
1228 static void
1229 nautilus_window_destroy (GtkWidget *object)
1230 {
1231 NautilusWindow *window;
1232 GList *slots_copy;
1233
1234 window = NAUTILUS_WINDOW (object);
1235
1236 DEBUG ("Destroying window");
1237
1238 /* close the sidebar first */
1239 nautilus_window_tear_down_sidebar (window);
1240
1241 /* close all slots safely */
1242 slots_copy = g_list_copy (window->details->slots);
1243 g_list_foreach (slots_copy, (GFunc) destroy_slots_foreach, window);
1244 g_list_free (slots_copy);
1245
1246 /* the slots list should now be empty */
1247 g_assert (window->details->slots == NULL);
1248
1249 window->details->active_slot = NULL;
1250
1251 GTK_WIDGET_CLASS (nautilus_window_parent_class)->destroy (object);
1252 }
1253
1254 static void
1255 nautilus_window_finalize (GObject *object)
1256 {
1257 NautilusWindow *window;
1258
1259 window = NAUTILUS_WINDOW (object);
1260
1261 if (window->details->sidebar_width_handler_id != 0) {
1262 g_source_remove (window->details->sidebar_width_handler_id);
1263 window->details->sidebar_width_handler_id = 0;
1264 }
1265
1266 nautilus_window_finalize_menus (window);
1267
1268 g_clear_object (&window->details->ui_manager);
1269
1270 /* nautilus_window_close() should have run */
1271 g_assert (window->details->slots == NULL);
1272
1273 G_OBJECT_CLASS (nautilus_window_parent_class)->finalize (object);
1274 }
1275
1276 void
1277 nautilus_window_view_visible (NautilusWindow *window,
1278 NautilusView *view)
1279 {
1280 NautilusWindowSlot *slot;
1281 GList *l;
1282
1283 g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1284
1285 slot = nautilus_window_get_slot_for_view (window, view);
1286
1287 if (slot->visible) {
1288 return;
1289 }
1290
1291 slot->visible = TRUE;
1292
1293 /* Look for other non-visible slots */
1294 for (l = window->details->slots; l != NULL; l = l->next) {
1295 slot = l->data;
1296
1297 if (!slot->visible) {
1298 return;
1299 }
1300 }
1301
1302 /* Look for other non-visible slots */
1303 for (l = window->details->slots; l != NULL; l = l->next) {
1304 slot = l->data;
1305
1306 nautilus_window_slot_update_title (slot);
1307 }
1308
1309 nautilus_window_grab_focus (window);
1310
1311 /* All slots, show window */
1312 gtk_widget_show (GTK_WIDGET (window));
1313 }
1314
1315 static void
1316 nautilus_window_save_geometry (NautilusWindow *window)
1317 {
1318 char *geometry_string;
1319 gboolean is_maximized;
1320
1321 g_assert (NAUTILUS_IS_WINDOW (window));
1322
1323 if (gtk_widget_get_window (GTK_WIDGET (window))) {
1324 geometry_string = eel_gtk_window_get_geometry_string (GTK_WINDOW (window));
1325 is_maximized = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)))
1326 & GDK_WINDOW_STATE_MAXIMIZED;
1327
1328 if (!is_maximized) {
1329 g_settings_set_string
1330 (nautilus_window_state, NAUTILUS_WINDOW_STATE_GEOMETRY,
1331 geometry_string);
1332 }
1333 g_free (geometry_string);
1334
1335 g_settings_set_boolean
1336 (nautilus_window_state, NAUTILUS_WINDOW_STATE_MAXIMIZED,
1337 is_maximized);
1338 }
1339 }
1340
1341 void
1342 nautilus_window_close (NautilusWindow *window)
1343 {
1344 NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->close (window);
1345 }
1346
1347 void
1348 nautilus_window_set_active_slot (NautilusWindow *window, NautilusWindowSlot *new_slot)
1349 {
1350 NautilusWindowSlot *old_slot;
1351
1352 g_assert (NAUTILUS_IS_WINDOW (window));
1353
1354 DEBUG ("Setting new slot %p as active", new_slot);
1355
1356 if (new_slot) {
1357 g_assert ((window == nautilus_window_slot_get_window (new_slot)));
1358 }
1359
1360 old_slot = nautilus_window_get_active_slot (window);
1361
1362 if (old_slot == new_slot) {
1363 return;
1364 }
1365
1366 /* make old slot inactive if it exists (may be NULL after init, for example) */
1367 if (old_slot != NULL) {
1368 /* inform window */
1369 if (old_slot->content_view != NULL) {
1370 nautilus_window_disconnect_content_view (window, old_slot->content_view);
1371 }
1372
1373 /* inform slot & view */
1374 g_signal_emit_by_name (old_slot, "inactive");
1375 }
1376
1377 window->details->active_slot = new_slot;
1378
1379 /* make new slot active, if it exists */
1380 if (new_slot) {
1381 /* inform sidebar panels */
1382 nautilus_window_report_location_change (window);
1383 /* TODO decide whether "selection-changed" should be emitted */
1384
1385 if (new_slot->content_view != NULL) {
1386 /* inform window */
1387 nautilus_window_connect_content_view (window, new_slot->content_view);
1388 }
1389
1390 /* inform slot & view */
1391 g_signal_emit_by_name (new_slot, "active");
1392 }
1393 }
1394
1395 static void
1396 nautilus_window_get_preferred_width (GtkWidget *widget,
1397 gint *minimal_width,
1398 gint *natural_width)
1399 {
1400 GdkScreen *screen;
1401 gint max_w, min_w, default_w;
1402
1403 screen = gtk_window_get_screen (GTK_WINDOW (widget));
1404
1405 max_w = get_max_forced_width (screen);
1406 min_w = NAUTILUS_WINDOW_MIN_WIDTH;
1407
1408 default_w = NAUTILUS_WINDOW_DEFAULT_WIDTH;
1409
1410 *minimal_width = MIN (min_w, max_w);
1411 *natural_width = MIN (default_w, max_w);
1412 }
1413
1414 static void
1415 nautilus_window_get_preferred_height (GtkWidget *widget,
1416 gint *minimal_height,
1417 gint *natural_height)
1418 {
1419 GdkScreen *screen;
1420 gint max_h, min_h, default_h;
1421
1422 screen = gtk_window_get_screen (GTK_WINDOW (widget));
1423
1424 max_h = get_max_forced_height (screen);
1425
1426 min_h = NAUTILUS_WINDOW_MIN_HEIGHT;
1427
1428 default_h = NAUTILUS_WINDOW_DEFAULT_HEIGHT;
1429
1430 *minimal_height = MIN (min_h, max_h);
1431 *natural_height = MIN (default_h, max_h);
1432 }
1433
1434 static void
1435 nautilus_window_realize (GtkWidget *widget)
1436 {
1437 GTK_WIDGET_CLASS (nautilus_window_parent_class)->realize (widget);
1438 update_cursor (NAUTILUS_WINDOW (widget));
1439 }
1440
1441 static gboolean
1442 nautilus_window_key_press_event (GtkWidget *widget,
1443 GdkEventKey *event)
1444 {
1445 NautilusWindow *window;
1446 NautilusWindowSlot *active_slot;
1447 NautilusView *view;
1448 GtkWidget *focus_widget;
1449 int i;
1450
1451 window = NAUTILUS_WINDOW (widget);
1452
1453 active_slot = nautilus_window_get_active_slot (window);
1454 view = active_slot->content_view;
1455
1456 if (view != NULL && nautilus_view_get_is_renaming (view)) {
1457 /* if we're renaming, just forward the event to the
1458 * focused widget and return. We don't want to process the window
1459 * accelerator bindings, as they might conflict with the
1460 * editable widget bindings.
1461 */
1462 if (gtk_window_propagate_key_event (GTK_WINDOW (window), event)) {
1463 return TRUE;
1464 }
1465 }
1466
1467 focus_widget = gtk_window_get_focus (GTK_WINDOW (window));
1468 if (view != NULL && focus_widget != NULL &&
1469 GTK_IS_EDITABLE (focus_widget)) {
1470 /* if we have input focus on a GtkEditable (e.g. a GtkEntry), forward
1471 * the event to it before activating accelerator bindings too.
1472 */
1473 if (gtk_window_propagate_key_event (GTK_WINDOW (window), event)) {
1474 return TRUE;
1475 }
1476 }
1477
1478 for (i = 0; i < G_N_ELEMENTS (extra_window_keybindings); i++) {
1479 if (extra_window_keybindings[i].keyval == event->keyval) {
1480 const GList *action_groups;
1481 GtkAction *action;
1482
1483 action = NULL;
1484
1485 action_groups = gtk_ui_manager_get_action_groups (window->details->ui_manager);
1486 while (action_groups != NULL && action == NULL) {
1487 action = gtk_action_group_get_action (action_groups->data, extra_window_keybindings[i].action);
1488 action_groups = action_groups->next;
1489 }
1490
1491 g_assert (action != NULL);
1492 if (gtk_action_is_sensitive (action)) {
1493 gtk_action_activate (action);
1494 return TRUE;
1495 }
1496
1497 break;
1498 }
1499 }
1500
1501 if (GTK_WIDGET_CLASS (nautilus_window_parent_class)->key_press_event (widget, event)) {
1502 return TRUE;
1503 }
1504
1505 if (nautilus_window_slot_handle_event (window->details->active_slot, event)) {
1506 nautilus_window_slot_set_search_visible (window->details->active_slot, TRUE);
1507 return TRUE;
1508 }
1509
1510 return FALSE;
1511 }
1512
1513 /*
1514 * Main API
1515 */
1516
1517 static void
1518 real_sync_view_as_menus (NautilusWindow *window)
1519 {
1520 NautilusWindowSlot *slot;
1521 GtkActionGroup *action_group;
1522 GtkAction *action;
1523
1524 g_assert (NAUTILUS_IS_WINDOW (window));
1525
1526 slot = nautilus_window_get_active_slot (window);
1527
1528 if (slot->content_view == NULL || slot->new_content_view != NULL) {
1529 return;
1530 }
1531
1532 action_group = nautilus_window_get_main_action_group (window);
1533
1534 if (nautilus_window_slot_content_view_matches_iid (slot, NAUTILUS_LIST_VIEW_ID)) {
1535 action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_VIEW_LIST);
1536 } else {
1537 action = gtk_action_group_get_action (action_group, NAUTILUS_ACTION_VIEW_GRID);
1538 }
1539
1540 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1541 }
1542
1543 /**
1544 * nautilus_window_sync_view_as_menus:
1545 *
1546 * Set the visible item of the "View as" option menu and
1547 * the marked "View as" item in the View menu to
1548 * match the current content view.
1549 *
1550 * @window: The NautilusWindow whose "View as" option menu should be synched.
1551 */
1552 void
1553 nautilus_window_sync_view_as_menus (NautilusWindow *window)
1554 {
1555 if (NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_view_as_menus != NULL) {
1556 NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_view_as_menus (window);
1557 }
1558 }
1559
1560 void
1561 nautilus_window_sync_up_button (NautilusWindow *window)
1562 {
1563 GtkAction *action;
1564 GtkActionGroup *action_group;
1565 NautilusWindowSlot *slot;
1566 gboolean allowed;
1567 GFile *parent;
1568
1569 slot = nautilus_window_get_active_slot (window);
1570
1571 allowed = FALSE;
1572 if (slot->location != NULL) {
1573 parent = g_file_get_parent (slot->location);
1574 allowed = parent != NULL;
1575
1576 g_clear_object (&parent);
1577 }
1578
1579 action_group = nautilus_window_get_main_action_group (window);
1580
1581 action = gtk_action_group_get_action (action_group,
1582 NAUTILUS_ACTION_UP);
1583 gtk_action_set_sensitive (action, allowed);
1584 }
1585
1586 void
1587 nautilus_window_sync_title (NautilusWindow *window,
1588 NautilusWindowSlot *slot)
1589 {
1590 if (NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_title != NULL) {
1591 NAUTILUS_WINDOW_CLASS (G_OBJECT_GET_CLASS (window))->sync_title (window, slot);
1592
1593 return;
1594 }
1595
1596 if (slot == nautilus_window_get_active_slot (window)) {
1597 gtk_window_set_title (GTK_WINDOW (window), slot->title);
1598 }
1599
1600 nautilus_notebook_sync_tab_label (NAUTILUS_NOTEBOOK (window->details->notebook), slot);
1601 }
1602
1603 void
1604 nautilus_window_sync_zoom_widgets (NautilusWindow *window)
1605 {
1606 NautilusWindowSlot *slot;
1607 NautilusView *view;
1608 GtkActionGroup *action_group;
1609 GtkAction *action;
1610 gboolean supports_zooming;
1611 gboolean can_zoom, can_zoom_in, can_zoom_out;
1612 NautilusZoomLevel zoom_level;
1613
1614 slot = nautilus_window_get_active_slot (window);
1615 view = slot->content_view;
1616
1617 if (view != NULL) {
1618 supports_zooming = nautilus_view_supports_zooming (view);
1619 zoom_level = nautilus_view_get_zoom_level (view);
1620 can_zoom = supports_zooming &&
1621 zoom_level >= NAUTILUS_ZOOM_LEVEL_SMALLEST &&
1622 zoom_level <= NAUTILUS_ZOOM_LEVEL_LARGEST;
1623 can_zoom_in = can_zoom && nautilus_view_can_zoom_in (view);
1624 can_zoom_out = can_zoom && nautilus_view_can_zoom_out (view);
1625 } else {
1626 supports_zooming = FALSE;
1627 can_zoom = FALSE;
1628 can_zoom_in = FALSE;
1629 can_zoom_out = FALSE;
1630 }
1631
1632 action_group = nautilus_window_get_main_action_group (window);
1633
1634 action = gtk_action_group_get_action (action_group,
1635 NAUTILUS_ACTION_ZOOM_IN);
1636 gtk_action_set_visible (action, supports_zooming);
1637 gtk_action_set_sensitive (action, can_zoom_in);
1638
1639 action = gtk_action_group_get_action (action_group,
1640 NAUTILUS_ACTION_ZOOM_OUT);
1641 gtk_action_set_visible (action, supports_zooming);
1642 gtk_action_set_sensitive (action, can_zoom_out);
1643
1644 action = gtk_action_group_get_action (action_group,
1645 NAUTILUS_ACTION_ZOOM_NORMAL);
1646 gtk_action_set_visible (action, supports_zooming);
1647 gtk_action_set_sensitive (action, can_zoom);
1648 }
1649
1650 static void
1651 zoom_level_changed_callback (NautilusView *view,
1652 NautilusWindow *window)
1653 {
1654 g_assert (NAUTILUS_IS_WINDOW (window));
1655
1656 /* This is called each time the component in
1657 * the active slot successfully completed
1658 * a zooming operation.
1659 */
1660 nautilus_window_sync_zoom_widgets (window);
1661 }
1662
1663
1664 /* These are called
1665 * A) when switching the view within the active slot
1666 * B) when switching the active slot
1667 * C) when closing the active slot (disconnect)
1668 */
1669 void
1670 nautilus_window_connect_content_view (NautilusWindow *window,
1671 NautilusView *view)
1672 {
1673 NautilusWindowSlot *slot;
1674 NautilusDirectory *directory;
1675
1676 g_assert (NAUTILUS_IS_WINDOW (window));
1677 g_assert (NAUTILUS_IS_VIEW (view));
1678
1679 slot = nautilus_window_get_slot_for_view (window, view);
1680
1681 if (slot != nautilus_window_get_active_slot (window)) {
1682 return;
1683 }
1684
1685 g_signal_connect (view, "zoom-level-changed",
1686 G_CALLBACK (zoom_level_changed_callback),
1687 window);
1688
1689 /* See the comment in notebook_page_added_cb() */
1690 notebook_num_pages_changed (window);
1691
1692 /* Update displayed view in menu. Only do this if we're not switching
1693 * locations though, because if we are switching locations we'll
1694 * install a whole new set of views in the menu later (the current
1695 * views in the menu are for the old location).
1696 */
1697 if (slot->pending_location == NULL) {
1698 nautilus_window_sync_view_as_menus (window);
1699 } else {
1700 directory = nautilus_directory_get (slot->pending_location);
1701 if (!NAUTILUS_IS_SEARCH_DIRECTORY (directory)) {
1702 nautilus_view_grab_focus (view);
1703 }
1704
1705 nautilus_directory_unref (directory);
1706 }
1707 }
1708
1709 void
1710 nautilus_window_disconnect_content_view (NautilusWindow *window,
1711 NautilusView *view)
1712 {
1713 NautilusWindowSlot *slot;
1714
1715 g_assert (NAUTILUS_IS_WINDOW (window));
1716 g_assert (NAUTILUS_IS_VIEW (view));
1717
1718 slot = nautilus_window_get_slot_for_view (window, view);
1719
1720 if (slot != nautilus_window_get_active_slot (window)) {
1721 return;
1722 }
1723
1724 g_signal_handlers_disconnect_by_func (view, G_CALLBACK (zoom_level_changed_callback), window);
1725 }
1726
1727 /**
1728 * nautilus_window_show:
1729 * @widget: GtkWidget
1730 *
1731 * Call parent and then show/hide window items
1732 * base on user prefs.
1733 */
1734 static void
1735 nautilus_window_show (GtkWidget *widget)
1736 {
1737 NautilusWindow *window;
1738
1739 window = NAUTILUS_WINDOW (widget);
1740
1741 GTK_WIDGET_CLASS (nautilus_window_parent_class)->show (widget);
1742
1743 gtk_ui_manager_ensure_update (window->details->ui_manager);
1744 }
1745
1746 GtkUIManager *
1747 nautilus_window_get_ui_manager (NautilusWindow *window)
1748 {
1749 g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), NULL);
1750
1751 return window->details->ui_manager;
1752 }
1753
1754 GtkActionGroup *
1755 nautilus_window_get_main_action_group (NautilusWindow *window)
1756 {
1757 g_return_val_if_fail (NAUTILUS_IS_WINDOW (window), NULL);
1758
1759 return window->details->main_action_group;
1760 }
1761
1762 void
1763 nautilus_window_slot_set_viewed_file (NautilusWindowSlot *slot,
1764 NautilusFile *file)
1765 {
1766 NautilusFileAttributes attributes;
1767
1768 if (slot->viewed_file == file) {
1769 return;
1770 }
1771
1772 nautilus_file_ref (file);
1773
1774 if (slot->viewed_file != NULL) {
1775 nautilus_file_monitor_remove (slot->viewed_file,
1776 slot);
1777 }
1778
1779 if (file != NULL) {
1780 attributes =
1781 NAUTILUS_FILE_ATTRIBUTE_INFO |
1782 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO;
1783 nautilus_file_monitor_add (file, slot, attributes);
1784 }
1785
1786 nautilus_file_unref (slot->viewed_file);
1787 slot->viewed_file = file;
1788 }
1789
1790 NautilusWindowSlot *
1791 nautilus_window_get_slot_for_view (NautilusWindow *window,
1792 NautilusView *view)
1793 {
1794 NautilusWindowSlot *slot;
1795 GList *l;
1796
1797 slot = NULL;
1798 for (l = window->details->slots; l; l = l->next) {
1799 NautilusWindowSlot *tmp = l->data;
1800
1801 if (tmp->content_view == view ||
1802 tmp->new_content_view == view) {
1803 slot = tmp;
1804 break;
1805 }
1806 }
1807
1808 return slot;
1809 }
1810
1811 NautilusWindowSlot *
1812 nautilus_window_get_active_slot (NautilusWindow *window)
1813 {
1814 g_assert (NAUTILUS_IS_WINDOW (window));
1815
1816 return window->details->active_slot;
1817 }
1818
1819 GList *
1820 nautilus_window_get_slots (NautilusWindow *window)
1821 {
1822 g_assert (NAUTILUS_IS_WINDOW (window));
1823
1824 return window->details->slots;
1825 }
1826
1827 static gboolean
1828 nautilus_window_state_event (GtkWidget *widget,
1829 GdkEventWindowState *event)
1830 {
1831 if (event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) {
1832 g_settings_set_boolean (nautilus_window_state, NAUTILUS_WINDOW_STATE_MAXIMIZED,
1833 event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED);
1834 }
1835
1836 if (GTK_WIDGET_CLASS (nautilus_window_parent_class)->window_state_event != NULL) {
1837 return GTK_WIDGET_CLASS (nautilus_window_parent_class)->window_state_event (widget, event);
1838 }
1839
1840 return FALSE;
1841 }
1842
1843 static gboolean
1844 nautilus_window_delete_event (GtkWidget *widget,
1845 GdkEventAny *event)
1846 {
1847 nautilus_window_close (NAUTILUS_WINDOW (widget));
1848 return FALSE;
1849 }
1850
1851 static gboolean
1852 nautilus_window_button_press_event (GtkWidget *widget,
1853 GdkEventButton *event)
1854 {
1855 NautilusWindow *window;
1856 gboolean handled;
1857
1858 window = NAUTILUS_WINDOW (widget);
1859
1860 if (mouse_extra_buttons && (event->button == mouse_back_button)) {
1861 nautilus_window_back_or_forward (window, TRUE, 0, 0);
1862 handled = TRUE;
1863 } else if (mouse_extra_buttons && (event->button == mouse_forward_button)) {
1864 nautilus_window_back_or_forward (window, FALSE, 0, 0);
1865 handled = TRUE;
1866 } else if (GTK_WIDGET_CLASS (nautilus_window_parent_class)->button_press_event) {
1867 handled = GTK_WIDGET_CLASS (nautilus_window_parent_class)->button_press_event (widget, event);
1868 } else {
1869 handled = FALSE;
1870 }
1871 return handled;
1872 }
1873
1874 static void
1875 mouse_back_button_changed (gpointer callback_data)
1876 {
1877 int new_back_button;
1878
1879 new_back_button = g_settings_get_int (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_BACK_BUTTON);
1880
1881 /* Bounds checking */
1882 if (new_back_button < 6 || new_back_button > UPPER_MOUSE_LIMIT)
1883 return;
1884
1885 mouse_back_button = new_back_button;
1886 }
1887
1888 static void
1889 mouse_forward_button_changed (gpointer callback_data)
1890 {
1891 int new_forward_button;
1892
1893 new_forward_button = g_settings_get_int (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_FORWARD_BUTTON);
1894
1895 /* Bounds checking */
1896 if (new_forward_button < 6 || new_forward_button > UPPER_MOUSE_LIMIT)
1897 return;
1898
1899 mouse_forward_button = new_forward_button;
1900 }
1901
1902 static void
1903 use_extra_mouse_buttons_changed (gpointer callback_data)
1904 {
1905 mouse_extra_buttons = g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS);
1906 }
1907
1908
1909 /*
1910 * Main API
1911 */
1912
1913 static void
1914 nautilus_window_init (NautilusWindow *window)
1915 {
1916 GtkWindowGroup *window_group;
1917
1918 window->details = G_TYPE_INSTANCE_GET_PRIVATE (window, NAUTILUS_TYPE_WINDOW, NautilusWindowDetails);
1919
1920 window->details->slots = NULL;
1921 window->details->active_slot = NULL;
1922
1923 window_group = gtk_window_group_new ();
1924 gtk_window_group_add_window (window_group, GTK_WINDOW (window));
1925 g_object_unref (window_group);
1926
1927 /* Set initial window title */
1928 gtk_window_set_title (GTK_WINDOW (window), _("Files"));
1929 gtk_window_set_icon_name (GTK_WINDOW (window), "system-file-manager");
1930 gtk_window_set_hide_titlebar_when_maximized (GTK_WINDOW (window), TRUE);
1931 }
1932
1933 static NautilusIconInfo *
1934 real_get_icon (NautilusWindow *window,
1935 NautilusWindowSlot *slot)
1936 {
1937 return nautilus_file_get_icon (slot->viewed_file, 48,
1938 NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING |
1939 NAUTILUS_FILE_ICON_FLAGS_USE_MOUNT_ICON);
1940 }
1941
1942 static void
1943 real_window_close (NautilusWindow *window)
1944 {
1945 g_return_if_fail (NAUTILUS_IS_WINDOW (window));
1946
1947 nautilus_window_save_geometry (window);
1948
1949 gtk_widget_destroy (GTK_WIDGET (window));
1950 }
1951
1952 static void
1953 nautilus_window_class_init (NautilusWindowClass *class)
1954 {
1955 GObjectClass *oclass = G_OBJECT_CLASS (class);
1956 GtkWidgetClass *wclass = GTK_WIDGET_CLASS (class);
1957
1958 oclass->finalize = nautilus_window_finalize;
1959 oclass->constructed = nautilus_window_constructed;
1960 oclass->get_property = nautilus_window_get_property;
1961 oclass->set_property = nautilus_window_set_property;
1962
1963 wclass->destroy = nautilus_window_destroy;
1964 wclass->show = nautilus_window_show;
1965 wclass->get_preferred_width = nautilus_window_get_preferred_width;
1966 wclass->get_preferred_height = nautilus_window_get_preferred_height;
1967 wclass->realize = nautilus_window_realize;
1968 wclass->key_press_event = nautilus_window_key_press_event;
1969 wclass->window_state_event = nautilus_window_state_event;
1970 wclass->button_press_event = nautilus_window_button_press_event;
1971 wclass->delete_event = nautilus_window_delete_event;
1972
1973 class->get_icon = real_get_icon;
1974 class->close = real_window_close;
1975 class->sync_view_as_menus = real_sync_view_as_menus;
1976
1977 properties[PROP_DISABLE_CHROME] =
1978 g_param_spec_boolean ("disable-chrome",
1979 "Disable chrome",
1980 "Disable window chrome, for the desktop",
1981 FALSE,
1982 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
1983 G_PARAM_STATIC_STRINGS);
1984
1985 signals[LOADING_URI] =
1986 g_signal_new ("loading_uri",
1987 G_TYPE_FROM_CLASS (class),
1988 G_SIGNAL_RUN_LAST,
1989 0,
1990 NULL, NULL,
1991 g_cclosure_marshal_VOID__STRING,
1992 G_TYPE_NONE, 1,
1993 G_TYPE_STRING);
1994 signals[SLOT_ADDED] =
1995 g_signal_new ("slot-added",
1996 G_TYPE_FROM_CLASS (class),
1997 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1998 0,
1999 NULL, NULL,
2000 g_cclosure_marshal_VOID__OBJECT,
2001 G_TYPE_NONE, 1, NAUTILUS_TYPE_WINDOW_SLOT);
2002 signals[SLOT_REMOVED] =
2003 g_signal_new ("slot-removed",
2004 G_TYPE_FROM_CLASS (class),
2005 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2006 0,
2007 NULL, NULL,
2008 g_cclosure_marshal_VOID__OBJECT,
2009 G_TYPE_NONE, 1, NAUTILUS_TYPE_WINDOW_SLOT);
2010
2011 g_signal_connect_swapped (nautilus_preferences,
2012 "changed::" NAUTILUS_PREFERENCES_MOUSE_BACK_BUTTON,
2013 G_CALLBACK(mouse_back_button_changed),
2014 NULL);
2015
2016 g_signal_connect_swapped (nautilus_preferences,
2017 "changed::" NAUTILUS_PREFERENCES_MOUSE_FORWARD_BUTTON,
2018 G_CALLBACK(mouse_forward_button_changed),
2019 NULL);
2020
2021 g_signal_connect_swapped (nautilus_preferences,
2022 "changed::" NAUTILUS_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS,
2023 G_CALLBACK(use_extra_mouse_buttons_changed),
2024 NULL);
2025
2026 g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
2027 g_type_class_add_private (oclass, sizeof (NautilusWindowDetails));
2028 }
2029
2030 NautilusWindow *
2031 nautilus_window_new (GtkApplication *application,
2032 GdkScreen *screen)
2033 {
2034 return g_object_new (NAUTILUS_TYPE_WINDOW,
2035 "application", application,
2036 "screen", screen,
2037 NULL);
2038 }
2039
2040 NautilusWindowOpenFlags
2041 nautilus_event_get_window_open_flags (void)
2042 {
2043 NautilusWindowOpenFlags flags = 0;
2044 GdkEvent *event;
2045
2046 event = gtk_get_current_event ();
2047
2048 if (event == NULL) {
2049 return flags;
2050 }
2051
2052 if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) &&
2053 (event->button.button == 2)) {
2054 flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB;
2055 }
2056
2057 gdk_event_free (event);
2058
2059 return flags;
2060 }
2061
2062 void
2063 nautilus_window_show_about_dialog (NautilusWindow *window)
2064 {
2065 const gchar *authors[] = {
2066 "Alexander Larsson",
2067 "Ali Abdin",
2068 "Anders Carlsson",
2069 "Andrew Walton",
2070 "Andy Hertzfeld",
2071 "Arlo Rose",
2072 "Christian Neumair",
2073 "Cosimo Cecchi",
2074 "Darin Adler",
2075 "David Camp",
2076 "Eli Goldberg",
2077 "Elliot Lee",
2078 "Eskil Heyn Olsen",
2079 "Ettore Perazzoli",
2080 "Gene Z. Ragan",
2081 "George Lebl",
2082 "Ian McKellar",
2083 "J Shane Culpepper",
2084 "James Willcox",
2085 "Jan Arne Petersen",
2086 "John Harper",
2087 "John Sullivan",
2088 "Josh Barrow",
2089 "Maciej Stachowiak",
2090 "Mark McLoughlin",
2091 "Mathieu Lacage",
2092 "Mike Engber",
2093 "Mike Fleming",
2094 "Pavel Cisler",
2095 "Ramiro Estrugo",
2096 "Raph Levien",
2097 "Rebecca Schulman",
2098 "Robey Pointer",
2099 "Robin * Slomkowski",
2100 "Seth Nickell",
2101 "Susan Kare",
2102 "Tomas Bzatek",
2103 "William Jon McCann",
2104 NULL
2105 };
2106 const gchar *documenters[] = {
2107 "GNOME Documentation Team",
2108 "Sun Microsystems",
2109 NULL
2110 };
2111 const gchar *license[] = {
2112 N_("Files is free software; you can redistribute it and/or modify "
2113 "it under the terms of the GNU General Public License as published by "
2114 "the Free Software Foundation; either version 2 of the License, or "
2115 "(at your option) any later version."),
2116 N_("Files is distributed in the hope that it will be useful, "
2117 "but WITHOUT ANY WARRANTY; without even the implied warranty of "
2118 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
2119 "GNU General Public License for more details."),
2120 N_("You should have received a copy of the GNU General Public License "
2121 "along with Nautilus; if not, write to the Free Software Foundation, Inc., "
2122 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA")
2123 };
2124 gchar *license_trans, *copyright_str;
2125 GDateTime *date;
2126
2127 license_trans = g_strjoin ("\n\n", _(license[0]), _(license[1]),
2128 _(license[2]), NULL);
2129
2130 date = g_date_time_new_now_local ();
2131
2132 /* Translators: these two strings here indicate the copyright time span,
2133 * e.g. 1999-2011.
2134 */
2135 copyright_str = g_strdup_printf (_("Copyright \xC2\xA9 %Id\xE2\x80\x93%Id "
2136 "The Files authors"), 1999, g_date_time_get_year (date));
2137
2138 gtk_show_about_dialog (window ? GTK_WINDOW (window) : NULL,
2139 "program-name", _("Files"),
2140 "version", VERSION,
2141 "comments", _("Access and organize your files."),
2142 "copyright", copyright_str,
2143 "license", license_trans,
2144 "wrap-license", TRUE,
2145 "authors", authors,
2146 "documenters", documenters,
2147 /* Translators should localize the following string
2148 * which will be displayed at the bottom of the about
2149 * box to give credit to the translator(s).
2150 */
2151 "translator-credits", _("translator-credits"),
2152 "logo-icon-name", "system-file-manager",
2153 NULL);
2154
2155 g_free (license_trans);
2156 g_free (copyright_str);
2157 g_date_time_unref (date);
2158 }