Location | Tool | Test ID | Function | Issue |
---|---|---|---|---|
nautilus-application.c:379:6 | clang-analyzer | Value stored to 'res' is never read | ||
nautilus-application.c:1192:19 | clang-analyzer | Array access (from variable 'files') results in a null pointer dereference |
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * nautilus-application: main Nautilus application class.
4 *
5 * Copyright (C) 1999, 2000 Red Hat, Inc.
6 * Copyright (C) 2000, 2001 Eazel, Inc.
7 * Copyright (C) 2010, Cosimo Cecchi <cosimoc@gnome.org>
8 *
9 * Nautilus is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * 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 License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 * Authors: Elliot Lee <sopwith@redhat.com>,
24 * Darin Adler <darin@bentspoon.com>
25 * Cosimo Cecchi <cosimoc@gnome.org>
26 *
27 */
28
29 #include <config.h>
30
31 #include "nautilus-application.h"
32
33 #if ENABLE_EMPTY_VIEW
34 #include "nautilus-empty-view.h"
35 #endif /* ENABLE_EMPTY_VIEW */
36
37 #include "nautilus-bookmarks-window.h"
38 #include "nautilus-connect-server-dialog.h"
39 #include "nautilus-desktop-canvas-view.h"
40 #include "nautilus-desktop-window.h"
41 #include "nautilus-file-management-properties.h"
42 #include "nautilus-freedesktop-dbus.h"
43 #include "nautilus-canvas-view.h"
44 #include "nautilus-image-properties-page.h"
45 #include "nautilus-list-view.h"
46 #include "nautilus-previewer.h"
47 #include "nautilus-progress-ui-handler.h"
48 #include "nautilus-self-check-functions.h"
49 #include "nautilus-window.h"
50 #include "nautilus-window-manage-views.h"
51 #include "nautilus-window-private.h"
52 #include "nautilus-window-slot.h"
53
54 #include <libnautilus-private/nautilus-dbus-manager.h>
55 #include <libnautilus-private/nautilus-desktop-link-monitor.h>
56 #include <libnautilus-private/nautilus-directory-private.h>
57 #include <libnautilus-private/nautilus-file-utilities.h>
58 #include <libnautilus-private/nautilus-file-operations.h>
59 #include <libnautilus-private/nautilus-global-preferences.h>
60 #include <libnautilus-private/nautilus-lib-self-check-functions.h>
61 #include <libnautilus-private/nautilus-module.h>
62 #include <libnautilus-private/nautilus-profile.h>
63 #include <libnautilus-private/nautilus-signaller.h>
64 #include <libnautilus-private/nautilus-ui-utilities.h>
65 #include <libnautilus-extension/nautilus-menu-provider.h>
66
67 #define DEBUG_FLAG NAUTILUS_DEBUG_APPLICATION
68 #include <libnautilus-private/nautilus-debug.h>
69
70 #include <sys/types.h>
71 #include <sys/stat.h>
72 #include <fcntl.h>
73 #include <glib/gstdio.h>
74 #include <glib/gi18n.h>
75 #include <gio/gio.h>
76 #include <eel/eel-gtk-extensions.h>
77 #include <eel/eel-stock-dialogs.h>
78 #include <libnotify/notify.h>
79 #include <gdk/gdkx.h>
80 #include <gtk/gtk.h>
81
82 /* Keep window from shrinking down ridiculously small; numbers are somewhat arbitrary */
83 #define APPLICATION_WINDOW_MIN_WIDTH 300
84 #define APPLICATION_WINDOW_MIN_HEIGHT 100
85
86 #define START_STATE_CONFIG "start-state"
87
88 #define NAUTILUS_ACCEL_MAP_SAVE_DELAY 30
89
90 /* Keeps track of all the desktop windows. */
91 static GList *nautilus_application_desktop_windows;
92
93 /* The saving of the accelerator map was requested */
94 static gboolean save_of_accel_map_requested = FALSE;
95
96 static void desktop_changed_callback (gpointer user_data);
97 static void mount_added_callback (GVolumeMonitor *monitor,
98 GMount *mount,
99 NautilusApplication *application);
100
101 G_DEFINE_TYPE (NautilusApplication, nautilus_application, GTK_TYPE_APPLICATION);
102
103 struct _NautilusApplicationPriv {
104 GVolumeMonitor *volume_monitor;
105 NautilusProgressUIHandler *progress_handler;
106
107 gboolean no_desktop;
108 gchar *geometry;
109
110 NotifyNotification *unmount_notify;
111
112 NautilusBookmarkList *bookmark_list;
113
114 GtkWidget *connect_server_window;
115 };
116
117 NautilusBookmarkList *
118 nautilus_application_get_bookmarks (NautilusApplication *application)
119 {
120 return application->priv->bookmark_list;
121 }
122
123 void
124 nautilus_application_edit_bookmarks (NautilusApplication *application,
125 NautilusWindow *window)
126 {
127 GtkWindow *bookmarks_window;
128
129 bookmarks_window = nautilus_bookmarks_window_new (window);
130 gtk_window_present (bookmarks_window);
131 }
132
133 void
134 nautilus_application_notify_unmount_done (NautilusApplication *application,
135 const gchar *message)
136 {
137 if (application->priv->unmount_notify) {
138 notify_notification_close (application->priv->unmount_notify, NULL);
139 g_clear_object (&application->priv->unmount_notify);
140 }
141
142 if (message != NULL) {
143 NotifyNotification *unplug;
144 gchar **strings;
145
146 strings = g_strsplit (message, "\n", 0);
147 unplug = notify_notification_new (strings[0], strings[1],
148 "media-removable");
149
150 notify_notification_show (unplug, NULL);
151 g_object_unref (unplug);
152 g_strfreev (strings);
153 }
154 }
155
156 void
157 nautilus_application_notify_unmount_show (NautilusApplication *application,
158 const gchar *message)
159 {
160 gchar **strings;
161
162 strings = g_strsplit (message, "\n", 0);
163
164 if (!application->priv->unmount_notify) {
165 application->priv->unmount_notify =
166 notify_notification_new (strings[0], strings[1],
167 "media-removable");
168
169 notify_notification_set_hint (application->priv->unmount_notify,
170 "transient", g_variant_new_boolean (TRUE));
171 notify_notification_set_urgency (application->priv->unmount_notify,
172 NOTIFY_URGENCY_CRITICAL);
173 } else {
174 notify_notification_update (application->priv->unmount_notify,
175 strings[0], strings[1],
176 "media-removable");
177 }
178
179 notify_notification_show (application->priv->unmount_notify, NULL);
180 g_strfreev (strings);
181 }
182
183 static gboolean
184 check_required_directories (NautilusApplication *application)
185 {
186 char *user_directory;
187 char *desktop_directory;
188 GSList *directories;
189 gboolean ret;
190
191 g_assert (NAUTILUS_IS_APPLICATION (application));
192
193 nautilus_profile_start (NULL);
194
195 ret = TRUE;
196
197 user_directory = nautilus_get_user_directory ();
198 desktop_directory = nautilus_get_desktop_directory ();
199
200 directories = NULL;
201
202 if (!g_file_test (user_directory, G_FILE_TEST_IS_DIR)) {
203 directories = g_slist_prepend (directories, user_directory);
204 }
205
206 if (!g_file_test (desktop_directory, G_FILE_TEST_IS_DIR)) {
207 directories = g_slist_prepend (directories, desktop_directory);
208 }
209
210 if (directories != NULL) {
211 int failed_count;
212 GString *directories_as_string;
213 GSList *l;
214 char *error_string;
215 const char *detail_string;
216 GtkDialog *dialog;
217
218 ret = FALSE;
219
220 failed_count = g_slist_length (directories);
221
222 directories_as_string = g_string_new ((const char *)directories->data);
223 for (l = directories->next; l != NULL; l = l->next) {
224 g_string_append_printf (directories_as_string, ", %s", (const char *)l->data);
225 }
226
227 error_string = _("Oops! Something went wrong.");
228 if (failed_count == 1) {
229 detail_string = g_strdup_printf (_("Unable to create a required folder. "
230 "Please create the following folder, or "
231 "set permissions such that it can be created:\n%s"),
232 directories_as_string->str);
233 } else {
234 detail_string = g_strdup_printf (_("Unable to create required folders. "
235 "Please create the following folders, or "
236 "set permissions such that they can be created:\n%s"),
237 directories_as_string->str);
238 }
239
240 dialog = eel_show_error_dialog (error_string, detail_string, NULL);
241 /* We need the main event loop so the user has a chance to see the dialog. */
242 gtk_application_add_window (GTK_APPLICATION (application),
243 GTK_WINDOW (dialog));
244
245 g_string_free (directories_as_string, TRUE);
246 }
247
248 g_slist_free (directories);
249 g_free (user_directory);
250 g_free (desktop_directory);
251 nautilus_profile_end (NULL);
252
253 return ret;
254 }
255
256 static void
257 menu_provider_items_updated_handler (NautilusMenuProvider *provider, GtkWidget* parent_window, gpointer data)
258 {
259
260 g_signal_emit_by_name (nautilus_signaller_get_current (),
261 "popup_menu_changed");
262 }
263
264 static void
265 menu_provider_init_callback (void)
266 {
267 GList *providers;
268 GList *l;
269
270 providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_MENU_PROVIDER);
271
272 for (l = providers; l != NULL; l = l->next) {
273 NautilusMenuProvider *provider = NAUTILUS_MENU_PROVIDER (l->data);
274
275 g_signal_connect_after (G_OBJECT (provider), "items_updated",
276 (GCallback)menu_provider_items_updated_handler,
277 NULL);
278 }
279
280 nautilus_module_extension_list_free (providers);
281 }
282
283 static void
284 mark_desktop_files_trusted (void)
285 {
286 char *do_once_file;
287 GFile *f, *c;
288 GFileEnumerator *e;
289 GFileInfo *info;
290 const char *name;
291 int fd;
292
293 do_once_file = g_build_filename (g_get_user_data_dir (),
294 ".converted-launchers", NULL);
295
296 if (g_file_test (do_once_file, G_FILE_TEST_EXISTS)) {
297 goto out;
298 }
299
300 f = nautilus_get_desktop_location ();
301 e = g_file_enumerate_children (f,
302 G_FILE_ATTRIBUTE_STANDARD_TYPE ","
303 G_FILE_ATTRIBUTE_STANDARD_NAME ","
304 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE
305 ,
306 G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
307 NULL, NULL);
308 if (e == NULL) {
309 goto out2;
310 }
311
312 while ((info = g_file_enumerator_next_file (e, NULL, NULL)) != NULL) {
313 name = g_file_info_get_name (info);
314
315 if (g_str_has_suffix (name, ".desktop") &&
316 !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) {
317 c = g_file_get_child (f, name);
318 nautilus_file_mark_desktop_file_trusted (c,
319 NULL, FALSE,
320 NULL, NULL);
321 g_object_unref (c);
322 }
323 g_object_unref (info);
324 }
325
326 g_object_unref (e);
327 out2:
328 fd = g_creat (do_once_file, 0666);
329 close (fd);
330
331 g_object_unref (f);
332 out:
333 g_free (do_once_file);
334 }
335
336 static void
337 do_upgrades_once (NautilusApplication *self)
338 {
339 char *metafile_dir, *updated, *nautilus_dir, *xdg_dir;
340 const gchar *message;
341 int fd, res;
342
343 if (!self->priv->no_desktop) {
344 mark_desktop_files_trusted ();
345 }
346
347 metafile_dir = g_build_filename (g_get_home_dir (),
348 ".nautilus/metafiles", NULL);
349 if (g_file_test (metafile_dir, G_FILE_TEST_IS_DIR)) {
350 updated = g_build_filename (metafile_dir, "migrated-to-gvfs", NULL);
351 if (!g_file_test (updated, G_FILE_TEST_EXISTS)) {
352 g_spawn_command_line_async (LIBEXECDIR"/nautilus-convert-metadata --quiet", NULL);
353 fd = g_creat (updated, 0600);
354 if (fd != -1) {
355 close (fd);
356 }
357 }
358 g_free (updated);
359 }
360 g_free (metafile_dir);
361
362 nautilus_dir = g_build_filename (g_get_home_dir (),
363 ".nautilus", NULL);
364 xdg_dir = nautilus_get_user_directory ();
365 if (g_file_test (nautilus_dir, G_FILE_TEST_IS_DIR)) {
366 /* test if we already attempted to migrate first */
367 updated = g_build_filename (nautilus_dir, "DEPRECATED-DIRECTORY", NULL);
368 message = _("Nautilus 3.0 deprecated this directory and tried migrating "
369 "this configuration to ~/.config/nautilus");
370 if (!g_file_test (updated, G_FILE_TEST_EXISTS)) {
371 /* rename() works fine if the destination directory is
372 * empty.
373 */
374 res = g_rename (nautilus_dir, xdg_dir);
375
376 if (res == -1) {
377 fd = g_creat (updated, 0600);
378 if (fd != -1) {
379 res = write (fd, message, strlen (message));
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
380 close (fd);
381 }
382 }
383 }
384
385 g_free (updated);
386 }
387
388 g_free (nautilus_dir);
389 g_free (xdg_dir);
390 }
391
392 static void
393 selection_get_cb (GtkWidget *widget,
394 GtkSelectionData *selection_data,
395 guint info,
396 guint time)
397 {
398 /* No extra targets atm */
399 }
400
401 static GtkWidget *
402 get_desktop_manager_selection (GdkDisplay *display, int screen)
403 {
404 char selection_name[32];
405 GdkAtom selection_atom;
406 Window selection_owner;
407 GtkWidget *selection_widget;
408
409 g_snprintf (selection_name, sizeof (selection_name), "_NET_DESKTOP_MANAGER_S%d", screen);
410 selection_atom = gdk_atom_intern (selection_name, FALSE);
411
412 selection_owner = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
413 gdk_x11_atom_to_xatom_for_display (display,
414 selection_atom));
415 if (selection_owner != None) {
416 return NULL;
417 }
418
419 selection_widget = gtk_invisible_new_for_screen (gdk_display_get_screen (display, screen));
420 /* We need this for gdk_x11_get_server_time() */
421 gtk_widget_add_events (selection_widget, GDK_PROPERTY_CHANGE_MASK);
422
423 if (gtk_selection_owner_set_for_display (display,
424 selection_widget,
425 selection_atom,
426 gdk_x11_get_server_time (gtk_widget_get_window (selection_widget)))) {
427
428 g_signal_connect (selection_widget, "selection_get",
429 G_CALLBACK (selection_get_cb), NULL);
430 return selection_widget;
431 }
432
433 gtk_widget_destroy (selection_widget);
434
435 return NULL;
436 }
437
438 static void
439 desktop_unrealize_cb (GtkWidget *widget,
440 GtkWidget *selection_widget)
441 {
442 gtk_widget_destroy (selection_widget);
443 }
444
445 static gboolean
446 selection_clear_event_cb (GtkWidget *widget,
447 GdkEventSelection *event,
448 NautilusDesktopWindow *window)
449 {
450 gtk_widget_destroy (GTK_WIDGET (window));
451
452 nautilus_application_desktop_windows =
453 g_list_remove (nautilus_application_desktop_windows, window);
454
455 return TRUE;
456 }
457
458 static void
459 nautilus_application_create_desktop_windows (NautilusApplication *application)
460 {
461 GdkDisplay *display;
462 NautilusDesktopWindow *window;
463 GtkWidget *selection_widget;
464 int screens, i;
465
466 display = gdk_display_get_default ();
467 screens = gdk_display_get_n_screens (display);
468
469 for (i = 0; i < screens; i++) {
470
471 DEBUG ("Creating a desktop window for screen %d", i);
472
473 selection_widget = get_desktop_manager_selection (display, i);
474 if (selection_widget != NULL) {
475 window = nautilus_desktop_window_new (GTK_APPLICATION (application),
476 gdk_display_get_screen (display, i));
477
478 g_signal_connect (selection_widget, "selection_clear_event",
479 G_CALLBACK (selection_clear_event_cb), window);
480
481 g_signal_connect (window, "unrealize",
482 G_CALLBACK (desktop_unrealize_cb), selection_widget);
483
484 /* We realize it immediately so that the NAUTILUS_DESKTOP_WINDOW_ID
485 property is set so gnome-settings-daemon doesn't try to set the
486 background. And we do a gdk_flush() to be sure X gets it. */
487 gtk_widget_realize (GTK_WIDGET (window));
488 gdk_flush ();
489
490 nautilus_application_desktop_windows =
491 g_list_prepend (nautilus_application_desktop_windows, window);
492 }
493 }
494 }
495
496 static gboolean
497 another_navigation_window_already_showing (NautilusApplication *application,
498 NautilusWindow *the_window)
499 {
500 GList *list, *item;
501
502 list = gtk_application_get_windows (GTK_APPLICATION (application));
503 for (item = list; item != NULL; item = item->next) {
504 if (item->data != the_window) {
505 return TRUE;
506 }
507 }
508
509 return FALSE;
510 }
511
512 NautilusWindow *
513 nautilus_application_create_window (NautilusApplication *application,
514 GdkScreen *screen)
515 {
516 NautilusWindow *window;
517 char *geometry_string;
518 gboolean maximized;
519
520 g_return_val_if_fail (NAUTILUS_IS_APPLICATION (application), NULL);
521 nautilus_profile_start (NULL);
522
523 window = nautilus_window_new (GTK_APPLICATION (application), screen);
524
525 maximized = g_settings_get_boolean
526 (nautilus_window_state, NAUTILUS_WINDOW_STATE_MAXIMIZED);
527 if (maximized) {
528 gtk_window_maximize (GTK_WINDOW (window));
529 } else {
530 gtk_window_unmaximize (GTK_WINDOW (window));
531 }
532
533 geometry_string = g_settings_get_string
534 (nautilus_window_state, NAUTILUS_WINDOW_STATE_GEOMETRY);
535 if (geometry_string != NULL &&
536 geometry_string[0] != 0) {
537 /* Ignore saved window position if a window with the same
538 * location is already showing. That way the two windows
539 * wont appear at the exact same location on the screen.
540 */
541 eel_gtk_window_set_initial_geometry_from_string
542 (GTK_WINDOW (window),
543 geometry_string,
544 NAUTILUS_WINDOW_MIN_WIDTH,
545 NAUTILUS_WINDOW_MIN_HEIGHT,
546 another_navigation_window_already_showing (application, window));
547 }
548 g_free (geometry_string);
549
550 DEBUG ("Creating a new navigation window");
551 nautilus_profile_end (NULL);
552
553 return window;
554 }
555
556 static void
557 mount_added_callback (GVolumeMonitor *monitor,
558 GMount *mount,
559 NautilusApplication *application)
560 {
561 NautilusDirectory *directory;
562 GFile *root;
563 gchar *uri;
564
565 root = g_mount_get_root (mount);
566 uri = g_file_get_uri (root);
567
568 DEBUG ("Added mount at uri %s", uri);
569 g_free (uri);
570
571 directory = nautilus_directory_get_existing (root);
572 g_object_unref (root);
573 if (directory != NULL) {
574 nautilus_directory_force_reload (directory);
575 nautilus_directory_unref (directory);
576 }
577 }
578
579 static void
580 open_window (NautilusApplication *application,
581 GFile *location, GdkScreen *screen, const char *geometry)
582 {
583 NautilusWindow *window;
584 gchar *uri;
585
586 uri = g_file_get_uri (location);
587 DEBUG ("Opening new window at uri %s", uri);
588 nautilus_profile_start (NULL);
589 window = nautilus_application_create_window (application,
590 screen);
591 nautilus_window_go_to (window, location);
592
593 if (geometry != NULL && !gtk_widget_get_visible (GTK_WIDGET (window))) {
594 /* never maximize windows opened from shell if a
595 * custom geometry has been requested.
596 */
597 gtk_window_unmaximize (GTK_WINDOW (window));
598 eel_gtk_window_set_initial_geometry_from_string (GTK_WINDOW (window),
599 geometry,
600 APPLICATION_WINDOW_MIN_WIDTH,
601 APPLICATION_WINDOW_MIN_HEIGHT,
602 FALSE);
603 }
604
605 nautilus_profile_end (NULL);
606
607 g_free (uri);
608 }
609
610 static void
611 open_windows (NautilusApplication *application,
612 GFile **files,
613 gint n_files,
614 GdkScreen *screen,
615 const char *geometry)
616 {
617 guint i;
618
619 if (files == NULL || files[0] == NULL) {
620 /* Open a window pointing at the default location. */
621 open_window (application, NULL, screen, geometry);
622 } else {
623 /* Open windows at each requested location. */
624 for (i = 0; i < n_files; i++) {
625 open_window (application, files[i], screen, geometry);
626 }
627 }
628 }
629
630 void
631 nautilus_application_open_location (NautilusApplication *application,
632 GFile *location,
633 GFile *selection,
634 const char *startup_id)
635 {
636 NautilusWindow *window;
637 GList *sel_list = NULL;
638
639 nautilus_profile_start (NULL);
640
641 window = nautilus_application_create_window (application, gdk_screen_get_default ());
642 gtk_window_set_startup_id (GTK_WINDOW (window), startup_id);
643
644 if (selection != NULL) {
645 sel_list = g_list_prepend (sel_list, nautilus_file_get (selection));
646 }
647
648 nautilus_window_slot_open_location_full (nautilus_window_get_active_slot (window), location,
649 0, sel_list, NULL, NULL);
650
651 if (sel_list != NULL) {
652 nautilus_file_list_free (sel_list);
653 }
654
655 nautilus_profile_end (NULL);
656 }
657
658 static void
659 nautilus_application_open (GApplication *app,
660 GFile **files,
661 gint n_files,
662 const gchar *hint)
663 {
664 NautilusApplication *self = NAUTILUS_APPLICATION (app);
665
666 DEBUG ("Open called on the GApplication instance; %d files", n_files);
667
668 open_windows (self, files, n_files,
669 gdk_screen_get_default (),
670 self->priv->geometry);
671 }
672
673 static GtkWindow *
674 get_focus_window (GtkApplication *application)
675 {
676 GList *windows;
677 GtkWindow *window = NULL;
678
679 /* the windows are ordered with the last focused first */
680 windows = gtk_application_get_windows (application);
681
682 if (windows != NULL) {
683 window = g_list_nth_data (windows, 0);
684 }
685
686 return window;
687 }
688
689 static void
690 action_new_window (GSimpleAction *action,
691 GVariant *parameter,
692 gpointer user_data)
693 {
694 GtkApplication *application = user_data;
695 NautilusWindow *window;
696 GtkWindow *cur_window;
697
698 cur_window = get_focus_window (application);
699 window = nautilus_application_create_window (NAUTILUS_APPLICATION (application),
700 cur_window ?
701 gtk_window_get_screen (cur_window) :
702 gdk_screen_get_default ());
703
704 nautilus_window_slot_go_home (nautilus_window_get_active_slot (window), 0);
705 }
706
707 static gboolean
708 go_to_server_cb (NautilusWindow *window,
709 GFile *location,
710 GError *error,
711 gpointer user_data)
712 {
713 gboolean retval;
714
715 if (error == NULL) {
716 GBookmarkFile *bookmarks;
717 GError *error = NULL;
718 char *datadir;
719 char *filename;
720 char *uri;
721 char *title;
722 NautilusFile *file;
723 gboolean safe_to_save = TRUE;
724
725 file = nautilus_file_get_existing (location);
726
727 bookmarks = g_bookmark_file_new ();
728 datadir = g_build_filename (g_get_user_config_dir (), "nautilus", NULL);
729 filename = g_build_filename (datadir, "servers", NULL);
730 g_mkdir_with_parents (datadir, 0700);
731 g_free (datadir);
732 g_bookmark_file_load_from_file (bookmarks,
733 filename,
734 &error);
735 if (error != NULL) {
736 if (! g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
737 /* only warn if the file exists */
738 g_warning ("Unable to open server bookmarks: %s", error->message);
739 safe_to_save = FALSE;
740 }
741 g_error_free (error);
742 }
743
744 if (safe_to_save) {
745 uri = nautilus_file_get_uri (file);
746 title = nautilus_file_get_display_name (file);
747 g_bookmark_file_set_title (bookmarks, uri, title);
748 g_bookmark_file_set_visited (bookmarks, uri, -1);
749 g_bookmark_file_add_application (bookmarks, uri, NULL, NULL);
750 g_free (uri);
751 g_free (title);
752
753 g_bookmark_file_to_file (bookmarks, filename, NULL);
754 }
755
756 g_free (filename);
757 g_bookmark_file_free (bookmarks);
758
759 retval = TRUE;
760 } else {
761 retval = FALSE;
762 }
763
764 return retval;
765 }
766
767 static void
768 on_connect_server_response (GtkDialog *dialog,
769 int response,
770 GtkApplication *application)
771 {
772 if (response == GTK_RESPONSE_OK) {
773 GFile *location;
774 NautilusWindow *window = NAUTILUS_WINDOW (get_focus_window (application));
775
776 location = nautilus_connect_server_dialog_get_location (NAUTILUS_CONNECT_SERVER_DIALOG (dialog));
777 if (location != NULL) {
778 nautilus_window_slot_open_location_full (nautilus_window_get_active_slot (window),
779 location,
780 NAUTILUS_WINDOW_OPEN_FLAG_USE_DEFAULT_LOCATION,
781 NULL, go_to_server_cb, application);
782 }
783 }
784
785 gtk_widget_destroy (GTK_WIDGET (dialog));
786 }
787
788 static void
789 nautilus_application_connect_server (NautilusApplication *application,
790 NautilusWindow *window)
791 {
792 GtkWidget *dialog;
793
794 dialog = application->priv->connect_server_window;
795
796 if (dialog == NULL) {
797 dialog = nautilus_connect_server_dialog_new (window);
798 g_signal_connect (dialog, "response", G_CALLBACK (on_connect_server_response), application);
799 application->priv->connect_server_window = GTK_WIDGET (dialog);
800
801 g_object_add_weak_pointer (G_OBJECT (dialog),
802 (gpointer *) &application->priv->connect_server_window);
803 }
804
805 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
806 gtk_window_set_screen (GTK_WINDOW (dialog), gtk_window_get_screen (GTK_WINDOW (window)));
807 gtk_window_present (GTK_WINDOW (dialog));
808 }
809
810 static void
811 action_connect_to_server (GSimpleAction *action,
812 GVariant *parameter,
813 gpointer user_data)
814 {
815 GtkApplication *application = user_data;
816
817 nautilus_application_connect_server (NAUTILUS_APPLICATION (application), NAUTILUS_WINDOW (get_focus_window (application)));
818 }
819
820 static void
821 action_enter_location (GSimpleAction *action,
822 GVariant *parameter,
823 gpointer user_data)
824 {
825 GtkApplication *application = user_data;
826 NautilusWindow *window;
827 GtkWindow *cur_window;
828
829 cur_window = get_focus_window (application);
830 window = NAUTILUS_WINDOW (cur_window);
831 nautilus_window_ensure_location_entry (window);
832 }
833
834 static void
835 action_bookmarks (GSimpleAction *action,
836 GVariant *parameter,
837 gpointer user_data)
838 {
839 GtkApplication *application = user_data;
840
841 nautilus_application_edit_bookmarks (NAUTILUS_APPLICATION (application), NAUTILUS_WINDOW (get_focus_window (application)));
842 }
843
844 static void
845 action_preferences (GSimpleAction *action,
846 GVariant *parameter,
847 gpointer user_data)
848 {
849 GtkApplication *application = user_data;
850 nautilus_file_management_properties_dialog_show (get_focus_window (application));
851 }
852
853 static void
854 action_about (GSimpleAction *action,
855 GVariant *parameter,
856 gpointer user_data)
857 {
858 GtkApplication *application = user_data;
859
860 nautilus_window_show_about_dialog (NAUTILUS_WINDOW (get_focus_window (application)));
861 }
862
863 static void
864 action_help (GSimpleAction *action,
865 GVariant *parameter,
866 gpointer user_data)
867 {
868 GtkWindow *window;
869 GtkWidget *dialog;
870 GtkApplication *application = user_data;
871 GError *error = NULL;
872
873 window = get_focus_window (application);
874 gtk_show_uri (window ?
875 gtk_window_get_screen (GTK_WINDOW (window)) :
876 gdk_screen_get_default (),
877 "help:gnome-help/files",
878 gtk_get_current_event_time (), &error);
879
880 if (error) {
881 dialog = gtk_message_dialog_new (window ? GTK_WINDOW (window) : NULL,
882 GTK_DIALOG_MODAL,
883 GTK_MESSAGE_ERROR,
884 GTK_BUTTONS_OK,
885 _("There was an error displaying help: \n%s"),
886 error->message);
887 g_signal_connect (G_OBJECT (dialog), "response",
888 G_CALLBACK (gtk_widget_destroy),
889 NULL);
890
891 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
892 gtk_widget_show (dialog);
893 g_error_free (error);
894 }
895 }
896
897 static void
898 action_kill (GSimpleAction *action,
899 GVariant *parameter,
900 gpointer user_data)
901 {
902 GtkApplication *application = user_data;
903 GList *windows;
904
905 /* this will also destroy the desktop windows */
906 windows = gtk_application_get_windows (application);
907 g_list_foreach (windows, (GFunc) gtk_widget_destroy, NULL);
908 }
909
910 static void
911 action_quit (GSimpleAction *action,
912 GVariant *parameter,
913 gpointer user_data)
914 {
915 GtkApplication *application = user_data;
916 GList *windows;
917
918 /* nautilus_window_close() doesn't do anything for desktop windows */
919 windows = gtk_application_get_windows (application);
920 g_list_foreach (windows, (GFunc) nautilus_window_close, NULL);
921 }
922
923 static GActionEntry app_entries[] = {
924 { "new-window", action_new_window, NULL, NULL, NULL },
925 { "connect-to-server", action_connect_to_server, NULL, NULL, NULL },
926 { "enter-location", action_enter_location, NULL, NULL, NULL },
927 { "bookmarks", action_bookmarks, NULL, NULL, NULL },
928 { "preferences", action_preferences, NULL, NULL, NULL },
929 { "about", action_about, NULL, NULL, NULL },
930 { "help", action_help, NULL, NULL, NULL },
931 { "quit", action_quit, NULL, NULL, NULL },
932 { "kill", action_kill, NULL, NULL, NULL },
933 };
934
935 static void
936 nautilus_application_init_actions (NautilusApplication *self)
937 {
938 GtkBuilder *builder;
939 GError *error = NULL;
940 const gchar *debug_no_app_menu;
941
942 g_action_map_add_action_entries (G_ACTION_MAP (self),
943 app_entries, G_N_ELEMENTS (app_entries),
944 self);
945 gtk_application_add_accelerator (GTK_APPLICATION (self), "F10", "win.gear-menu", NULL);
946
947 builder = gtk_builder_new ();
948 gtk_builder_add_from_resource (builder, "/org/gnome/nautilus/nautilus-app-menu.ui", &error);
949
950 if (error == NULL) {
951 gtk_application_set_app_menu (GTK_APPLICATION (self),
952 G_MENU_MODEL (gtk_builder_get_object (builder, "app-menu")));
953 } else {
954 g_critical ("Unable to add the application menu: %s\n", error->message);
955 g_error_free (error);
956 }
957
958 g_object_unref (builder);
959
960 debug_no_app_menu = g_getenv ("NAUTILUS_DEBUG_NO_APP_MENU");
961 if (debug_no_app_menu) {
962 DEBUG ("Disabling app menu GtkSetting as requested...");
963 g_object_set (gtk_settings_get_default (),
964 "gtk-shell-shows-app-menu", FALSE,
965 NULL);
966 }
967 }
968
969 static void
970 nautilus_application_init (NautilusApplication *application)
971 {
972 application->priv =
973 G_TYPE_INSTANCE_GET_PRIVATE (application, NAUTILUS_TYPE_APPLICATION,
974 NautilusApplicationPriv);
975 }
976
977 static void
978 nautilus_application_finalize (GObject *object)
979 {
980 NautilusApplication *application;
981
982 application = NAUTILUS_APPLICATION (object);
983
984 g_clear_object (&application->priv->volume_monitor);
985 g_clear_object (&application->priv->progress_handler);
986 g_clear_object (&application->priv->bookmark_list);
987
988 g_free (application->priv->geometry);
989
990 nautilus_dbus_manager_stop ();
991 nautilus_freedesktop_dbus_stop ();
992 notify_uninit ();
993
994 G_OBJECT_CLASS (nautilus_application_parent_class)->finalize (object);
995 }
996
997 static gboolean
998 do_cmdline_sanity_checks (NautilusApplication *self,
999 gboolean perform_self_check,
1000 gboolean version,
1001 gboolean kill_shell,
1002 gchar **remaining)
1003 {
1004 gboolean retval = FALSE;
1005
1006 if (perform_self_check && (remaining != NULL || kill_shell)) {
1007 g_printerr ("%s\n",
1008 _("--check cannot be used with other options."));
1009 goto out;
1010 }
1011
1012 if (kill_shell && remaining != NULL) {
1013 g_printerr ("%s\n",
1014 _("--quit cannot be used with URIs."));
1015 goto out;
1016 }
1017
1018 if (self->priv->geometry != NULL &&
1019 remaining != NULL && remaining[0] != NULL && remaining[1] != NULL) {
1020 g_printerr ("%s\n",
1021 _("--geometry cannot be used with more than one URI."));
1022 goto out;
1023 }
1024
1025 retval = TRUE;
1026
1027 out:
1028 return retval;
1029 }
1030
1031 static void
1032 do_perform_self_checks (gint *exit_status)
1033 {
1034 #ifndef NAUTILUS_OMIT_SELF_CHECK
1035 gtk_init (NULL, NULL);
1036
1037 nautilus_profile_start (NULL);
1038 /* Run the checks (each twice) for nautilus and libnautilus-private. */
1039
1040 nautilus_run_self_checks ();
1041 nautilus_run_lib_self_checks ();
1042 eel_exit_if_self_checks_failed ();
1043
1044 nautilus_run_self_checks ();
1045 nautilus_run_lib_self_checks ();
1046 eel_exit_if_self_checks_failed ();
1047 nautilus_profile_end (NULL);
1048 #endif
1049
1050 *exit_status = EXIT_SUCCESS;
1051 }
1052
1053 static gboolean
1054 nautilus_application_local_command_line (GApplication *application,
1055 gchar ***arguments,
1056 gint *exit_status)
1057 {
1058 gboolean perform_self_check = FALSE;
1059 gboolean version = FALSE;
1060 gboolean browser = FALSE;
1061 gboolean kill_shell = FALSE;
1062 gboolean no_default_window = FALSE;
1063 gchar **remaining = NULL;
1064 NautilusApplication *self = NAUTILUS_APPLICATION (application);
1065
1066 const GOptionEntry options[] = {
1067 #ifndef NAUTILUS_OMIT_SELF_CHECK
1068 { "check", 'c', 0, G_OPTION_ARG_NONE, &perform_self_check,
1069 N_("Perform a quick set of self-check tests."), NULL },
1070 #endif
1071 /* dummy, only for compatibility reasons */
1072 { "browser", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &browser,
1073 NULL, NULL },
1074 { "version", '\0', 0, G_OPTION_ARG_NONE, &version,
1075 N_("Show the version of the program."), NULL },
1076 { "geometry", 'g', 0, G_OPTION_ARG_STRING, &self->priv->geometry,
1077 N_("Create the initial window with the given geometry."), N_("GEOMETRY") },
1078 { "no-default-window", 'n', 0, G_OPTION_ARG_NONE, &no_default_window,
1079 N_("Only create windows for explicitly specified URIs."), NULL },
1080 { "no-desktop", '\0', 0, G_OPTION_ARG_NONE, &self->priv->no_desktop,
1081 N_("Do not manage the desktop (ignore the preference set in the preferences dialog)."), NULL },
1082 { "quit", 'q', 0, G_OPTION_ARG_NONE, &kill_shell,
1083 N_("Quit Nautilus."), NULL },
1084 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &remaining, NULL, N_("[URI...]") },
1085
1086 { NULL }
1087 };
1088 GOptionContext *context;
1089 GError *error = NULL;
1090 gint argc = 0;
1091 gchar **argv = NULL;
1092
1093 *exit_status = EXIT_SUCCESS;
1094
1095 nautilus_profile_start (NULL);
1096
1097 context = g_option_context_new (_("\n\nBrowse the file system with the file manager"));
1098 g_option_context_add_main_entries (context, options, NULL);
1099 g_option_context_add_group (context, gtk_get_option_group (FALSE));
1100
1101 argv = *arguments;
1102 argc = g_strv_length (argv);
1103
1104 if (!g_option_context_parse (context, &argc, &argv, &error)) {
1105 /* Translators: this is a fatal error quit message printed on the
1106 * command line */
1107 g_printerr ("%s: %s\n", _("Could not parse arguments"), error->message);
1108 g_error_free (error);
1109
1110 *exit_status = EXIT_FAILURE;
1111 goto out;
1112 }
1113
1114 if (version) {
1115 g_print ("GNOME nautilus " PACKAGE_VERSION "\n");
1116 goto out;
1117 }
1118
1119 if (!do_cmdline_sanity_checks (self, perform_self_check,
1120 version, kill_shell, remaining)) {
1121 *exit_status = EXIT_FAILURE;
1122 goto out;
1123 }
1124
1125 if (perform_self_check) {
1126 do_perform_self_checks (exit_status);
1127 goto out;
1128 }
1129
1130 DEBUG ("Parsing local command line, no_default_window %d, quit %d, "
1131 "self checks %d, no_desktop %d",
1132 no_default_window, kill_shell, perform_self_check, self->priv->no_desktop);
1133
1134 g_application_register (application, NULL, &error);
1135
1136 if (error != NULL) {
1137 /* Translators: this is a fatal error quit message printed on the
1138 * command line */
1139 g_printerr ("%s: %s\n", _("Could not register the application"), error->message);
1140 g_error_free (error);
1141
1142 *exit_status = EXIT_FAILURE;
1143 goto out;
1144 }
1145
1146 if (kill_shell) {
1147 DEBUG ("Killing application, as requested");
1148 g_action_group_activate_action (G_ACTION_GROUP (application),
1149 "kill", NULL);
1150 goto out;
1151 }
1152
1153 GFile **files;
1154 gint idx, len;
1155
1156 len = 0;
1157 files = NULL;
1158
1159 /* Convert args to GFiles */
1160 if (remaining != NULL) {
1161 GFile *file;
1162 GPtrArray *file_array;
1163
1164 file_array = g_ptr_array_new ();
1165
1166 for (idx = 0; remaining[idx] != NULL; idx++) {
1167 file = g_file_new_for_commandline_arg (remaining[idx]);
1168 if (file != NULL) {
1169 g_ptr_array_add (file_array, file);
1170 }
1171 }
1172
1173 len = file_array->len;
1174 files = (GFile **) g_ptr_array_free (file_array, FALSE);
1175 g_strfreev (remaining);
1176 }
1177
1178 if (files == NULL && !no_default_window) {
1179 files = g_malloc0 (2 * sizeof (GFile *));
1180 len = 1;
1181
1182 files[0] = g_file_new_for_path (g_get_home_dir ());
1183 files[1] = NULL;
1184 }
1185
1186 /* Invoke "Open" to create new windows */
1187 if (len > 0) {
1188 g_application_open (application, files, len, "");
1189 }
1190
1191 for (idx = 0; idx < len; idx++) {
1192 g_object_unref (files[idx]);
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
1193 }
1194 g_free (files);
1195
1196 out:
1197 g_option_context_free (context);
1198 nautilus_profile_end (NULL);
1199
1200 return TRUE;
1201 }
1202
1203 static void
1204 init_icons_and_styles (void)
1205 {
1206 /* initialize search path for custom icons */
1207 gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
1208 NAUTILUS_DATADIR G_DIR_SEPARATOR_S "icons");
1209 }
1210
1211 static void
1212 nautilus_application_open_desktop (NautilusApplication *application)
1213 {
1214 /* Initialize the desktop link monitor singleton */
1215 nautilus_desktop_link_monitor_get ();
1216
1217 if (nautilus_application_desktop_windows == NULL) {
1218 nautilus_application_create_desktop_windows (application);
1219 }
1220 }
1221
1222 static void
1223 nautilus_application_close_desktop (void)
1224 {
1225 if (nautilus_application_desktop_windows != NULL) {
1226 g_list_foreach (nautilus_application_desktop_windows,
1227 (GFunc) gtk_widget_destroy, NULL);
1228 g_list_free (nautilus_application_desktop_windows);
1229 nautilus_application_desktop_windows = NULL;
1230 }
1231 nautilus_desktop_link_monitor_shutdown ();
1232 }
1233
1234 /* callback for showing or hiding the desktop based on the user's preference */
1235 static void
1236 desktop_changed_callback (gpointer user_data)
1237 {
1238 NautilusApplication *application;
1239
1240 application = NAUTILUS_APPLICATION (user_data);
1241 if (g_settings_get_boolean (gnome_background_preferences, NAUTILUS_PREFERENCES_SHOW_DESKTOP)) {
1242 nautilus_application_open_desktop (application);
1243 } else {
1244 nautilus_application_close_desktop ();
1245 }
1246 }
1247
1248 static void
1249 init_desktop (NautilusApplication *self)
1250 {
1251 if (!self->priv->no_desktop &&
1252 !g_settings_get_boolean (gnome_background_preferences,
1253 NAUTILUS_PREFERENCES_SHOW_DESKTOP)) {
1254 self->priv->no_desktop = TRUE;
1255 }
1256
1257 if (!self->priv->no_desktop) {
1258 nautilus_application_open_desktop (self);
1259 }
1260
1261 /* Monitor the preference to show or hide the desktop */
1262 g_signal_connect_swapped (gnome_background_preferences, "changed::" NAUTILUS_PREFERENCES_SHOW_DESKTOP,
1263 G_CALLBACK (desktop_changed_callback),
1264 self);
1265 }
1266
1267 static gboolean
1268 nautilus_application_save_accel_map (gpointer data)
1269 {
1270 if (save_of_accel_map_requested) {
1271 char *accel_map_filename;
1272 accel_map_filename = nautilus_get_accel_map_file ();
1273 if (accel_map_filename) {
1274 gtk_accel_map_save (accel_map_filename);
1275 g_free (accel_map_filename);
1276 }
1277 save_of_accel_map_requested = FALSE;
1278 }
1279
1280 return FALSE;
1281 }
1282
1283 static void
1284 queue_accel_map_save_callback (GtkAccelMap *object, gchar *accel_path,
1285 guint accel_key, GdkModifierType accel_mods,
1286 gpointer user_data)
1287 {
1288 if (!save_of_accel_map_requested) {
1289 save_of_accel_map_requested = TRUE;
1290 g_timeout_add_seconds (NAUTILUS_ACCEL_MAP_SAVE_DELAY,
1291 nautilus_application_save_accel_map, NULL);
1292 }
1293 }
1294
1295 static void
1296 update_accel_due_to_scripts_migration (gpointer data, const gchar *accel_path, guint accel_key,
1297 GdkModifierType accel_mods, gboolean changed)
1298 {
1299 char *old_scripts_location_esc = data;
1300 char *old_scripts_pt;
1301
1302 old_scripts_pt = strstr (accel_path, old_scripts_location_esc);
1303
1304 if (old_scripts_pt != NULL) {
1305 /* There's a mention of the deprecated scripts directory in the accel. Remove it, and
1306 * add a migrated one. */
1307 char *tmp;
1308 char *tmp2;
1309 GString *new_accel_path;
1310
1311 /* base part of accel */
1312 tmp = g_strndup (accel_path, old_scripts_pt - accel_path);
1313 new_accel_path = g_string_new (tmp);
1314 g_free (tmp);
1315
1316 /* new script directory, escaped */
1317 tmp = nautilus_get_scripts_directory_path ();
1318 tmp2 = nautilus_escape_action_name (tmp, "");
1319 g_free (tmp);
1320 g_string_append (new_accel_path, tmp2);
1321 g_free (tmp2);
1322
1323 /* script path relative to scripts directory */
1324 g_string_append (new_accel_path, old_scripts_pt + strlen (old_scripts_location_esc));
1325
1326 /* exchange entry */
1327 gtk_accel_map_change_entry (accel_path, 0, 0, FALSE);
1328 gtk_accel_map_change_entry (new_accel_path->str, accel_key, accel_mods, TRUE);
1329
1330 g_string_free (new_accel_path, TRUE);
1331 }
1332 }
1333
1334 static void
1335 init_gtk_accels (void)
1336 {
1337 char *accel_map_filename;
1338 gboolean performed_migration = FALSE;
1339 char *old_scripts_directory_path = NULL;
1340
1341 accel_map_filename = nautilus_get_accel_map_file ();
1342
1343 /* If the accel map file doesn't exist, try to migrate from
1344 * former locations. */
1345 if (!g_file_test (accel_map_filename, G_FILE_TEST_IS_REGULAR)) {
1346 char *old_accel_map_filename;
1347 const gchar *override;
1348
1349 override = g_getenv ("GNOME22_USER_DIR");
1350 if (override) {
1351 old_accel_map_filename = g_build_filename (override,
1352 "accels", "nautilus", NULL);
1353 old_scripts_directory_path = g_build_filename (override,
1354 "nautilus-scripts",
1355 NULL);
1356 } else {
1357 old_accel_map_filename = g_build_filename (g_get_home_dir (),
1358 ".gnome2", "accels", "nautilus", NULL);
1359 old_scripts_directory_path = g_build_filename (g_get_home_dir (),
1360 ".gnome2",
1361 "nautilus-scripts",
1362 NULL);
1363 }
1364
1365 if (g_file_test (old_accel_map_filename, G_FILE_TEST_IS_REGULAR)) {
1366 char *parent_dir;
1367
1368 parent_dir = g_path_get_dirname (accel_map_filename);
1369 if (g_mkdir_with_parents (parent_dir, 0700) == 0) {
1370 GFile *accel_map_file;
1371 GFile *old_accel_map_file;
1372
1373 accel_map_file = g_file_new_for_path (accel_map_filename);
1374 old_accel_map_file = g_file_new_for_path (old_accel_map_filename);
1375
1376 /* If the move fails, it's safer to not read any accel map
1377 * on startup instead of reading the old one and possibly
1378 * being stuck with it. */
1379 performed_migration = g_file_move (old_accel_map_file, accel_map_file, 0, NULL, NULL, NULL, NULL);
1380
1381 g_object_unref (accel_map_file);
1382 g_object_unref (old_accel_map_file);
1383 }
1384 g_free (parent_dir);
1385 }
1386
1387 g_free (old_accel_map_filename);
1388 }
1389
1390 /* load accelerator map, and register save callback */
1391 gtk_accel_map_load (accel_map_filename);
1392 g_free (accel_map_filename);
1393
1394 if (performed_migration) {
1395 /* Migrate accels pointing to scripts */
1396 char *old_scripts_location_esc;
1397
1398 old_scripts_location_esc = nautilus_escape_action_name (old_scripts_directory_path, "");
1399 gtk_accel_map_foreach (old_scripts_location_esc, update_accel_due_to_scripts_migration);
1400 g_free (old_scripts_location_esc);
1401 /* save map immediately */
1402 save_of_accel_map_requested = TRUE;
1403 nautilus_application_save_accel_map (NULL);
1404 }
1405
1406 g_signal_connect (gtk_accel_map_get (), "changed",
1407 G_CALLBACK (queue_accel_map_save_callback), NULL);
1408
1409 g_free (old_scripts_directory_path);
1410 }
1411
1412 static void
1413 nautilus_application_startup (GApplication *app)
1414 {
1415 NautilusApplication *self = NAUTILUS_APPLICATION (app);
1416
1417 nautilus_profile_start (NULL);
1418
1419 /* chain up to the GTK+ implementation early, so gtk_init()
1420 * is called for us.
1421 */
1422 G_APPLICATION_CLASS (nautilus_application_parent_class)->startup (app);
1423
1424 gtk_window_set_default_icon_name ("system-file-manager");
1425
1426 /* initialize the previewer singleton */
1427 nautilus_previewer_get_singleton ();
1428
1429 /* create DBus manager */
1430 nautilus_dbus_manager_start (app);
1431 nautilus_freedesktop_dbus_start (self);
1432
1433 /* initialize preferences and create the global GSettings objects */
1434 nautilus_global_preferences_init ();
1435
1436 /* register views */
1437 nautilus_profile_start ("Register views");
1438 nautilus_canvas_view_register ();
1439 nautilus_desktop_canvas_view_register ();
1440 nautilus_list_view_register ();
1441 #if ENABLE_EMPTY_VIEW
1442 nautilus_empty_view_register ();
1443 #endif
1444 nautilus_profile_end ("Register views");
1445
1446 /* register property pages */
1447 nautilus_image_properties_page_register ();
1448
1449 /* initialize theming */
1450 init_icons_and_styles ();
1451 init_gtk_accels ();
1452
1453 /* initialize nautilus modules */
1454 nautilus_profile_start ("Modules");
1455 nautilus_module_setup ();
1456 nautilus_profile_end ("Modules");
1457
1458 /* attach menu-provider module callback */
1459 menu_provider_init_callback ();
1460
1461 /* Initialize the UI handler singleton for file operations */
1462 notify_init (GETTEXT_PACKAGE);
1463 self->priv->progress_handler = nautilus_progress_ui_handler_new ();
1464
1465 self->priv->volume_monitor = g_volume_monitor_get ();
1466 g_signal_connect_object (self->priv->volume_monitor, "mount_added",
1467 G_CALLBACK (mount_added_callback), self, 0);
1468
1469 self->priv->bookmark_list = nautilus_bookmark_list_new ();
1470
1471 /* Check the user's .nautilus directories and post warnings
1472 * if there are problems.
1473 */
1474 check_required_directories (self);
1475 init_desktop (self);
1476
1477 do_upgrades_once (self);
1478
1479 nautilus_application_init_actions (self);
1480
1481 nautilus_profile_end (NULL);
1482 }
1483
1484 static void
1485 nautilus_application_quit_mainloop (GApplication *app)
1486 {
1487 DEBUG ("Quitting mainloop");
1488
1489 nautilus_icon_info_clear_caches ();
1490 nautilus_application_save_accel_map (NULL);
1491
1492 nautilus_application_notify_unmount_done (NAUTILUS_APPLICATION (app), NULL);
1493
1494 G_APPLICATION_CLASS (nautilus_application_parent_class)->quit_mainloop (app);
1495 }
1496
1497 static void
1498 nautilus_application_window_removed (GtkApplication *app,
1499 GtkWindow *window)
1500 {
1501 NautilusPreviewer *previewer;
1502
1503 /* chain to parent */
1504 GTK_APPLICATION_CLASS (nautilus_application_parent_class)->window_removed (app, window);
1505
1506 /* if this was the last window, close the previewer */
1507 if (g_list_length (gtk_application_get_windows (app)) == 0) {
1508 previewer = nautilus_previewer_get_singleton ();
1509 nautilus_previewer_call_close (previewer);
1510 }
1511 }
1512
1513 static void
1514 nautilus_application_class_init (NautilusApplicationClass *class)
1515 {
1516 GObjectClass *object_class;
1517 GApplicationClass *application_class;
1518 GtkApplicationClass *gtkapp_class;
1519
1520 object_class = G_OBJECT_CLASS (class);
1521 object_class->finalize = nautilus_application_finalize;
1522
1523 application_class = G_APPLICATION_CLASS (class);
1524 application_class->startup = nautilus_application_startup;
1525 application_class->quit_mainloop = nautilus_application_quit_mainloop;
1526 application_class->open = nautilus_application_open;
1527 application_class->local_command_line = nautilus_application_local_command_line;
1528
1529 gtkapp_class = GTK_APPLICATION_CLASS (class);
1530 gtkapp_class->window_removed = nautilus_application_window_removed;
1531
1532 g_type_class_add_private (class, sizeof (NautilusApplicationPriv));
1533 }