No issues found
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Ettore Perazzoli <ettore@ximian.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #include <config.h>
24
25 #include <gtk/gtk.h>
26 #include <glib/gi18n.h>
27 #include <glib/gstdio.h>
28
29 #ifdef G_OS_UNIX
30 #include <glib-unix.h>
31 #endif
32
33 #ifdef WITH_CONTACT_MAPS
34 #include <clutter-gtk/clutter-gtk.h>
35 #endif
36
37 #ifdef G_OS_WIN32
38 #define WIN32_LEAN_AND_MEAN
39 #ifdef DATADIR
40 #undef DATADIR
41 #endif
42 #define _WIN32_WINNT 0x0601
43 #include <windows.h>
44 #include <conio.h>
45 #include <io.h>
46 #ifndef PROCESS_DEP_ENABLE
47 #define PROCESS_DEP_ENABLE 0x00000001
48 #endif
49 #ifndef PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
50 #define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
51 #endif
52 #endif
53
54 #include <libxml/xmlmemory.h>
55 #include <libxml/parser.h>
56 #include <libxml/tree.h>
57
58 #include <libedataserverui/libedataserverui.h>
59
60 #include <webkit/webkit.h>
61
62 #include "e-shell.h"
63 #include "e-shell-migrate.h"
64 #include "e-shell-meego.h"
65 #include "es-event.h"
66
67 #include "e-util/e-dialog-utils.h"
68 #include "e-util/e-import.h"
69 #include "e-util/e-plugin.h"
70 #include "e-util/e-plugin-ui.h"
71 #include "e-util/e-util-private.h"
72 #include "e-util/e-util.h"
73 #ifdef G_OS_WIN32
74 #include "e-util/e-win32-defaults.h"
75 #endif
76
77 #include <fcntl.h>
78 #include <signal.h>
79 #include <string.h>
80 #include <sys/types.h>
81 #include <sys/stat.h>
82 #include <unistd.h>
83
84 #ifdef HAVE_ICAL_UNKNOWN_TOKEN_HANDLING
85 #include <libical/ical.h>
86 #endif
87
88 #define APPLICATION_ID "org.gnome.Evolution"
89
90 /* STABLE_VERSION is only defined for development versions. */
91 #ifdef STABLE_VERSION
92 #define DEVELOPMENT 1
93 #endif
94
95 /* Command-line options. */
96 #ifdef G_OS_WIN32
97 static gboolean register_handlers = FALSE;
98 static gboolean reinstall = FALSE;
99 static gboolean show_icons = FALSE;
100 static gboolean hide_icons = FALSE;
101 static gboolean unregister_handlers = FALSE;
102 #endif /* G_OS_WIN32 */
103 static gboolean express_mode = FALSE;
104 static gboolean force_online = FALSE;
105 static gboolean start_online = FALSE;
106 static gboolean start_offline = FALSE;
107 static gboolean setup_only = FALSE;
108 static gboolean force_shutdown = FALSE;
109 static gboolean disable_eplugin = FALSE;
110 static gboolean disable_preview = FALSE;
111 static gboolean import_uris = FALSE;
112 static gboolean quit = FALSE;
113
114 static gchar *geometry = NULL;
115 static gchar *requested_view = NULL;
116 static gchar **remaining_args;
117
118 /* Forward declarations */
119 void e_convert_local_mail (EShell *shell);
120
121 static void
122 categories_icon_theme_hack (void)
123 {
124 GtkIconTheme *icon_theme;
125 const gchar *category_name;
126 const gchar *filename;
127 gchar *dirname;
128
129 /* XXX Allow the category icons to be referenced as named
130 * icons, since GtkAction does not support GdkPixbufs. */
131
132 /* Get the icon file for some default category. Doesn't matter
133 * which, so long as it has an icon. We're just interested in
134 * the directory components. */
135 category_name = _("Birthday");
136 filename = e_categories_get_icon_file_for (category_name);
137 g_return_if_fail (filename != NULL && *filename != '\0');
138
139 /* Extract the directory components. */
140 dirname = g_path_get_dirname (filename);
141
142 /* Add it to the icon theme's search path. This relies on
143 * GtkIconTheme's legacy feature of using image files found
144 * directly in the search path. */
145 icon_theme = gtk_icon_theme_get_default ();
146 gtk_icon_theme_append_search_path (icon_theme, dirname);
147
148 g_free (dirname);
149 }
150
151 #ifdef DEVELOPMENT
152
153 /* Warning dialog to scare people off a little bit. */
154
155 static gboolean
156 show_development_warning (void)
157 {
158 GtkWidget *action_area;
159 GtkWidget *content_area;
160 GtkWidget *vbox;
161 GtkWidget *label;
162 GtkWidget *warning_dialog;
163 GtkWidget *checkbox;
164 GtkWidget *alignment;
165 gboolean skip;
166 gchar *text;
167
168 warning_dialog = gtk_dialog_new ();
169 gtk_window_set_title (
170 GTK_WINDOW (warning_dialog), "Evolution " VERSION);
171 gtk_window_set_modal (
172 GTK_WINDOW (warning_dialog), TRUE);
173 gtk_dialog_add_button (
174 GTK_DIALOG (warning_dialog),
175 GTK_STOCK_OK, GTK_RESPONSE_OK);
176
177 action_area = gtk_dialog_get_action_area (GTK_DIALOG (warning_dialog));
178 content_area = gtk_dialog_get_content_area (GTK_DIALOG (warning_dialog));
179
180 gtk_container_set_border_width (GTK_CONTAINER (action_area), 12);
181 gtk_container_set_border_width (GTK_CONTAINER (content_area), 0);
182
183 vbox = gtk_vbox_new (FALSE, 12);
184 gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
185 gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
186
187 text = g_strdup_printf (
188 /* xgettext:no-c-format */
189 /* Preview/Alpha/Beta version warning message */
190 _("Hi. Thanks for taking the time to download this preview release\n"
191 "of the Evolution groupware suite.\n"
192 "\n"
193 "This version of Evolution is not yet complete. It is getting close,\n"
194 "but some features are either unfinished or do not work properly.\n"
195 "\n"
196 "If you want a stable version of Evolution, we urge you to uninstall\n"
197 "this version, and install version %s instead.\n"
198 "\n"
199 "If you find bugs, please report them to us at bugzilla.gnome.org.\n"
200 "This product comes with no warranty and is not intended for\n"
201 "individuals prone to violent fits of anger.\n"
202 "\n"
203 "We hope that you enjoy the results of our hard work, and we\n"
204 "eagerly await your contributions!\n"),
205 STABLE_VERSION);
206 label = gtk_label_new (text);
207 g_free (text);
208
209 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
210 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
211
212 gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
213
214 label = gtk_label_new (_("Thanks\nThe Evolution Team\n"));
215 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
216 gtk_misc_set_alignment (GTK_MISC (label), 1, .5);
217
218 gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
219
220 checkbox = gtk_check_button_new_with_label (_("Do not tell me again"));
221
222 alignment = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
223
224 gtk_container_add (GTK_CONTAINER (alignment), checkbox);
225 gtk_box_pack_start (GTK_BOX (vbox), alignment, TRUE, TRUE, 0);
226
227 gtk_widget_show_all (warning_dialog);
228
229 gtk_dialog_run (GTK_DIALOG (warning_dialog));
230
231 skip = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
232
233 gtk_widget_destroy (warning_dialog);
234
235 return skip;
236 }
237
238 #endif /* DEVELOPMENT */
239
240 /* This is for doing stuff that requires the GTK+ loop to be running already. */
241
242 static gboolean
243 idle_cb (const gchar * const *uris)
244 {
245 EShell *shell;
246
247 shell = e_shell_get_default ();
248
249 /* These calls do the right thing when another Evolution
250 * process is running. */
251 if (uris != NULL && *uris != NULL) {
252 if (e_shell_handle_uris (shell, uris, import_uris) == 0)
253 gtk_main_quit ();
254 } else {
255 if (express_mode && requested_view == NULL)
256 requested_view = (gchar *) "mail";
257 e_shell_create_shell_window (shell, requested_view);
258 }
259
260 /* If another Evolution process is running, we're done. */
261 if (g_application_get_is_remote (G_APPLICATION (shell)))
262 gtk_main_quit ();
263
264 return FALSE;
265 }
266
267 #ifdef G_OS_UNIX
268 static gboolean
269 handle_term_signal (gpointer data)
270 {
271 EShell *shell;
272
273 g_print ("Received terminate signal...\n");
274
275 shell = e_shell_get_default ();
276
277 if (shell != NULL)
278 e_shell_quit (shell, E_SHELL_QUIT_OPTION);
279
280 return FALSE;
281 }
282 #endif
283
284 G_GNUC_NORETURN static gboolean
285 option_version_cb (const gchar *option_name,
286 const gchar *option_value,
287 gpointer data,
288 GError **error)
289 {
290 g_print ("%s\n", PACKAGE_STRING);
291
292 exit (0);
293 }
294
295 static GOptionEntry entries[] = {
296 #ifdef G_OS_WIN32
297 { "register-handlers", '\0', G_OPTION_FLAG_HIDDEN,
298 G_OPTION_ARG_NONE, ®ister_handlers, NULL, NULL },
299 { "reinstall", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &reinstall,
300 NULL, NULL },
301 { "show-icons", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &show_icons,
302 NULL, NULL },
303 { "hide-icons", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &hide_icons,
304 NULL, NULL },
305 { "unregister-handlers", '\0', G_OPTION_FLAG_HIDDEN,
306 G_OPTION_ARG_NONE, &unregister_handlers, NULL, NULL },
307 #endif /* G_OS_WIN32 */
308 { "component", 'c', 0, G_OPTION_ARG_STRING, &requested_view,
309 /* Translators: Do NOT translate the five component
310 * names, they MUST remain in English! */
311 N_("Start Evolution showing the specified component. "
312 "Available options are 'mail', 'calendar', 'contacts', "
313 "'tasks', and 'memos'"), NULL },
314 { "geometry", 'g', 0, G_OPTION_ARG_STRING, &geometry,
315 N_("Apply the given geometry to the main window"), "GEOMETRY" },
316 { "offline", '\0', 0, G_OPTION_ARG_NONE, &start_offline,
317 N_("Start in offline mode"), NULL },
318 { "online", '\0', 0, G_OPTION_ARG_NONE, &start_online,
319 N_("Start in online mode"), NULL },
320 { "force-online", '\0', 0, G_OPTION_ARG_NONE, &force_online,
321 N_("Ignore network availability"), NULL },
322 { "express", '\0', 0, G_OPTION_ARG_NONE, &express_mode,
323 N_("Start in \"express\" mode"), NULL },
324 #ifdef KILL_PROCESS_CMD
325 { "force-shutdown", '\0', 0, G_OPTION_ARG_NONE, &force_shutdown,
326 N_("Forcibly shut down Evolution"), NULL },
327 #endif
328 { "disable-eplugin", '\0', 0, G_OPTION_ARG_NONE, &disable_eplugin,
329 N_("Disable loading of any plugins."), NULL },
330 { "disable-preview", '\0', 0, G_OPTION_ARG_NONE, &disable_preview,
331 N_("Disable preview pane of Mail, Contacts and Tasks."), NULL },
332 { "setup-only", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE,
333 &setup_only, NULL, NULL },
334 { "import", 'i', 0, G_OPTION_ARG_NONE, &import_uris,
335 N_("Import URIs or filenames given as rest of arguments."), NULL },
336 { "quit", 'q', 0, G_OPTION_ARG_NONE, &quit,
337 N_("Request a running Evolution process to quit"), NULL },
338 { "version", 'v', G_OPTION_FLAG_HIDDEN | G_OPTION_FLAG_NO_ARG,
339 G_OPTION_ARG_CALLBACK, option_version_cb, NULL, NULL },
340 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY,
341 &remaining_args, NULL, NULL },
342 { NULL }
343 };
344
345 static void G_GNUC_NORETURN
346 shell_force_shutdown (void)
347 {
348 gchar *filename;
349
350 filename = g_build_filename (EVOLUTION_TOOLSDIR, "killev", NULL);
351 execl (filename, "killev", NULL);
352
353 g_assert_not_reached ();
354 }
355
356 static EShell *
357 create_default_shell (void)
358 {
359 EShell *shell;
360 GSettings *settings;
361 GApplicationFlags flags;
362 gboolean online = TRUE;
363 gboolean is_meego = FALSE;
364 gboolean small_screen = FALSE;
365 GError *error = NULL;
366
367 settings = g_settings_new ("org.gnome.evolution.shell");
368
369 /* Requesting online or offline mode from the command-line
370 * should be persistent, just like selecting it in the UI. */
371
372 if (start_online || force_online) {
373 online = TRUE;
374 g_settings_set_boolean (settings, "start-offline", FALSE);
375 } else if (start_offline) {
376 online = FALSE;
377 g_settings_set_boolean (settings, "start-offline", TRUE);
378 } else {
379 gboolean value;
380
381 value = g_settings_get_boolean (settings, "start-offline");
382 if (error == NULL)
383 online = !value;
384 }
385
386 if (error != NULL) {
387 g_warning ("%s", error->message);
388 g_clear_error (&error);
389 }
390
391 /* Determine whether to run Evolution in "express" mode. */
392
393 if (!express_mode)
394 express_mode = g_settings_get_boolean (settings, "express-mode");
395
396 if (!express_mode)
397 e_shell_detect_meego (&is_meego, &small_screen);
398
399 if (is_meego)
400 express_mode = TRUE;
401
402 if (error != NULL) {
403 g_warning ("%s", error->message);
404 g_clear_error (&error);
405 }
406
407 flags = G_APPLICATION_HANDLES_OPEN |
408 G_APPLICATION_HANDLES_COMMAND_LINE;
409
410 shell = g_initable_new (
411 E_TYPE_SHELL, NULL, &error,
412 "application-id", APPLICATION_ID,
413 "flags", flags,
414 "geometry", geometry,
415 "module-directory", EVOLUTION_MODULEDIR,
416 "meego-mode", is_meego,
417 "express-mode", express_mode,
418 "small-screen-mode", small_screen,
419 "online", online,
420 NULL);
421
422 /* Failure to register is fatal. */
423 if (error != NULL) {
424 g_warning (
425 "Cannot start Evolution. Another Evolution "
426 "instance may be unresponsive. System error: %s",
427 error->message);
428 g_clear_error (&error);
429 }
430
431 if (force_online && shell)
432 e_shell_lock_network_available (shell);
433
434 g_object_unref (settings);
435
436 return shell;
437 }
438
439 /* this workarounds https://bugzilla.gnome.org/show_bug.cgi?id=683548
440 * and is a replacement of g_type_ensure(), which is part of GLib 2.34,
441 * on which Evolution doesn't depend yet
442 */
443 static void
444 e_ensure_type (GType type)
445 {
446 if (G_UNLIKELY (type == (GType) -1))
447 g_warning ("can't happen");
448 }
449
450 gint
451 main (gint argc,
452 gchar **argv)
453 {
454 EShell *shell;
455 GSettings *settings;
456 #ifdef DEVELOPMENT
457 gboolean skip_warning_dialog;
458 #endif
459 GError *error = NULL;
460
461 #ifdef G_OS_WIN32
462 gchar *path;
463
464 /* Reduce risks */
465 {
466 typedef BOOL (WINAPI *t_SetDllDirectoryA) (LPCSTR lpPathName);
467 t_SetDllDirectoryA p_SetDllDirectoryA;
468
469 p_SetDllDirectoryA = GetProcAddress (
470 GetModuleHandle ("kernel32.dll"),
471 "SetDllDirectoryA");
472 if (p_SetDllDirectoryA)
473 (*p_SetDllDirectoryA) ("");
474 }
475 #ifndef _WIN64
476 {
477 typedef BOOL (WINAPI *t_SetProcessDEPPolicy) (DWORD dwFlags);
478 t_SetProcessDEPPolicy p_SetProcessDEPPolicy;
479
480 p_SetProcessDEPPolicy = GetProcAddress (
481 GetModuleHandle ("kernel32.dll"),
482 "SetProcessDEPPolicy");
483 if (p_SetProcessDEPPolicy)
484 (*p_SetProcessDEPPolicy) (
485 PROCESS_DEP_ENABLE |
486 PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION);
487 }
488 #endif
489
490 if (fileno (stdout) != -1 && _get_osfhandle (fileno (stdout)) != -1) {
491 /* stdout is fine, presumably redirected to a file or pipe */
492 } else {
493 typedef BOOL (* WINAPI AttachConsole_t) (DWORD);
494
495 AttachConsole_t p_AttachConsole =
496 (AttachConsole_t) GetProcAddress (
497 GetModuleHandle ("kernel32.dll"), "AttachConsole");
498
499 if (p_AttachConsole && p_AttachConsole (ATTACH_PARENT_PROCESS)) {
500 freopen ("CONOUT$", "w", stdout);
501 dup2 (fileno (stdout), 1);
502 freopen ("CONOUT$", "w", stderr);
503 dup2 (fileno (stderr), 2);
504 }
505 }
506 #endif
507
508 /* Make ElectricFence work. */
509 free (malloc (10));
510
511 bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR);
512 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
513 textdomain (GETTEXT_PACKAGE);
514
515 g_type_init ();
516
517 /* do not require Gtk+ for --force-shutdown */
518 if (argc == 2 && argv[1] && g_str_equal (argv[1], "--force-shutdown")) {
519 shell_force_shutdown ();
520
521 return 0;
522 }
523
524 /* The contact maps feature uses clutter-gtk. */
525 #ifdef WITH_CONTACT_MAPS
526 gtk_clutter_init_with_args (
527 &argc, &argv,
528 _("- The Evolution PIM and Email Client"),
529 entries, (gchar *) GETTEXT_PACKAGE, &error);
530 #else
531 gtk_init_with_args (
532 &argc, &argv,
533 _("- The Evolution PIM and Email Client"),
534 entries, (gchar *) GETTEXT_PACKAGE, &error);
535 #endif /* WITH_CONTACT_MAPS */
536
537 if (error != NULL) {
538 g_printerr ("%s\n", error->message);
539 g_error_free (error);
540 exit (1);
541 }
542
543 #ifdef HAVE_ICAL_UNKNOWN_TOKEN_HANDLING
544 ical_set_unknown_token_handling_setting (ICAL_DISCARD_TOKEN);
545 #endif
546
547 e_gdbus_templates_init_main_thread ();
548
549 #ifdef G_OS_WIN32
550 path = g_build_path (";", _e_get_bindir (), g_getenv ("PATH"), NULL);
551
552 if (!g_setenv ("PATH", path, TRUE))
553 g_warning ("Could not set PATH for Evolution and its child processes");
554
555 g_free (path);
556
557 if (register_handlers || reinstall || show_icons) {
558 _e_win32_register_mailer ();
559 _e_win32_register_addressbook ();
560 }
561
562 if (register_handlers)
563 exit (0);
564
565 if (reinstall) {
566 _e_win32_set_default_mailer ();
567 exit (0);
568 }
569
570 if (show_icons) {
571 _e_win32_set_default_mailer ();
572 exit (0);
573 }
574
575 if (hide_icons) {
576 _e_win32_unset_default_mailer ();
577 exit (0);
578 }
579
580 if (unregister_handlers) {
581 _e_win32_unregister_mailer ();
582 _e_win32_unregister_addressbook ();
583 exit (0);
584 }
585
586 if (strcmp (gettext (""), "") == 0) {
587 /* No message catalog installed for the current locale
588 * language, so don't bother with the localisations
589 * provided by other things then either. Reset thread
590 * locale to "en-US" and C library locale to "C". */
591 SetThreadLocale (
592 MAKELCID (MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US),
593 SORT_DEFAULT));
594 setlocale (LC_ALL, "C");
595 }
596 #endif
597
598 if (start_online && start_offline) {
599 g_printerr (
600 _("%s: --online and --offline cannot be used "
601 "together.\n Run '%s --help' for more "
602 "information.\n"), argv[0], argv[0]);
603 exit (1);
604 } else if (force_online && start_offline) {
605 g_printerr (
606 _("%s: --force-online and --offline cannot be used "
607 "together.\n Run '%s --help' for more "
608 "information.\n"), argv[0], argv[0]);
609 exit (1);
610 }
611
612 if (force_shutdown)
613 shell_force_shutdown ();
614
615 if (disable_preview) {
616 settings = g_settings_new ("org.gnome.evolution.mail");
617 g_settings_set_boolean (settings, "safe-list", TRUE);
618 g_object_unref (settings);
619
620 settings = g_settings_new ("org.gnome.evolution.addressbook");
621 g_settings_set_boolean (settings, "show-preview", FALSE);
622 g_object_unref (settings);
623
624 settings = g_settings_new ("org.gnome.evolution.calendar");
625 g_settings_set_boolean (settings, "show-memo-preview", FALSE);
626 g_settings_set_boolean (settings, "show-task-preview", FALSE);
627 g_object_unref (settings);
628 }
629
630 #ifdef G_OS_UNIX
631 g_unix_signal_add_full (
632 G_PRIORITY_DEFAULT, SIGTERM,
633 handle_term_signal, NULL, NULL);
634 #endif
635
636 e_passwords_init ();
637
638 gtk_window_set_default_icon_name ("evolution");
639
640 if (setup_only)
641 exit (0);
642
643 categories_icon_theme_hack ();
644 gtk_accel_map_load (e_get_accels_filename ());
645
646 #ifdef DEVELOPMENT
647 settings = g_settings_new ("org.gnome.evolution.shell");
648 skip_warning_dialog = g_settings_get_boolean (
649 settings, "skip-warning-dialog");
650
651 if (!skip_warning_dialog && !getenv ("EVOLVE_ME_HARDER"))
652 g_settings_set_boolean (
653 settings, "skip-warning-dialog",
654 show_development_warning ());
655
656 g_object_unref (settings);
657 #endif
658
659 /* Workaround https://bugzilla.gnome.org/show_bug.cgi?id=683548 */
660 if (!quit)
661 e_ensure_type (WEBKIT_TYPE_WEB_VIEW);
662
663 shell = create_default_shell ();
664 if (!shell)
665 return 1;
666
667 if (quit) {
668 e_shell_quit (shell, E_SHELL_QUIT_OPTION);
669 goto exit;
670 }
671
672 /* This routine converts the local mail store from mbox format to
673 * Maildir format as needed. The reason the code is here and not
674 * in the mail module is because we inform the user at startup of
675 * the impending mail conversion by displaying a popup dialog and
676 * waiting for confirmation before proceeding.
677 *
678 * This has to be done before we load modules because some of the
679 * EShellBackends immediately add GMainContext sources that would
680 * otherwise get dispatched during gtk_dialog_run(), and we don't
681 * want them dispatched until after the conversion is complete. */
682 e_convert_local_mail (shell);
683
684 e_shell_load_modules (shell);
685
686 if (!disable_eplugin) {
687 /* Register built-in plugin hook types. */
688 es_event_hook_get_type ();
689 e_import_hook_get_type ();
690 e_plugin_ui_hook_get_type ();
691
692 /* All EPlugin and EPluginHook subclasses should be
693 * registered in GType now, so load plugins now. */
694 e_plugin_load_plugins ();
695 }
696
697 if (requested_view)
698 e_shell_set_startup_view (shell, requested_view);
699 else if (express_mode)
700 e_shell_set_startup_view (shell, "mail");
701
702 /* Attempt migration -after- loading all modules and plugins,
703 * as both shell backends and certain plugins hook into this. */
704 e_shell_migrate_attempt (shell);
705
706 /* This is an alternative to the "upgrade.done" EEvent. */
707 e_shell_event (shell, "ready-to-start", NULL);
708
709 g_idle_add ((GSourceFunc) idle_cb, remaining_args);
710
711 gtk_main ();
712
713 exit:
714 /* Drop what should be the last reference to the shell.
715 * That will cause e_shell_get_default() to henceforth
716 * return NULL. Use that to check for reference leaks. */
717 g_object_unref (shell);
718
719 if (e_shell_get_default () != NULL)
720 g_warning ("Shell not finalized on exit");
721
722 gtk_accel_map_save (e_get_accels_filename ());
723
724 return 0;
725 }