No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-mail-shell-backend.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-mail-shell-backend.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * e-mail-shell-backend.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 *
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "e-mail-shell-backend.h"
27
28 #include <glib/gi18n.h>
29
30 #include <e-util/e-import.h>
31 #include <e-util/e-util.h>
32
33 #include <shell/e-shell.h>
34 #include <shell/e-shell-window.h>
35
36 #include <composer/e-msg-composer.h>
37
38 #include <widgets/misc/e-preferences-window.h>
39 #include <widgets/misc/e-web-view.h>
40
41 #include <libemail-engine/e-mail-folder-utils.h>
42 #include <libemail-engine/e-mail-session.h>
43 #include <libemail-engine/mail-config.h>
44 #include <libemail-engine/mail-ops.h>
45
46 #include <mail/e-mail-browser.h>
47 #include <mail/e-mail-config-assistant.h>
48 #include <mail/e-mail-config-window.h>
49 #include <mail/e-mail-reader.h>
50 #include <mail/em-composer-utils.h>
51 #include <mail/em-folder-utils.h>
52 #include <mail/em-utils.h>
53 #include <mail/mail-send-recv.h>
54 #include <mail/mail-vfolder-ui.h>
55 #include <mail/importers/mail-importer.h>
56 #include <mail/e-mail-ui-session.h>
57
58 #include <em-format/e-mail-parser.h>
59 #include <em-format/e-mail-formatter.h>
60 #include <em-format/e-mail-part-utils.h>
61
62 #include "e-mail-shell-settings.h"
63 #include "e-mail-shell-sidebar.h"
64 #include "e-mail-shell-view.h"
65 #include "em-account-prefs.h"
66 #include "em-composer-prefs.h"
67 #include "em-mailer-prefs.h"
68 #include "em-network-prefs.h"
69
70 #define E_MAIL_SHELL_BACKEND_GET_PRIVATE(obj) \
71 (G_TYPE_INSTANCE_GET_PRIVATE \
72 ((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendPrivate))
73
74 #define E_MAIL_SHELL_BACKEND_GET_PRIVATE(obj) \
75 (G_TYPE_INSTANCE_GET_PRIVATE \
76 ((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendPrivate))
77
78 #define BACKEND_NAME "mail"
79
80 struct _EMailShellBackendPrivate {
81 gint mail_sync_in_progress;
82 guint mail_sync_source_id;
83 gpointer assistant; /* weak pointer, when adding new mail account */
84 gpointer editor; /* weak pointer, when editing a mail account */
85 };
86
87 static void mbox_create_preview_cb (GObject *preview, GtkWidget **preview_widget);
88 static void mbox_fill_preview_cb (GObject *preview, CamelMimeMessage *msg);
89
90 G_DEFINE_DYNAMIC_TYPE (
91 EMailShellBackend,
92 e_mail_shell_backend,
93 E_TYPE_MAIL_BACKEND)
94
95 static void
96 mail_shell_backend_init_importers (void)
97 {
98 EImportClass *import_class;
99 EImportImporter *importer;
100
101 import_class = g_type_class_ref (e_import_get_type ());
102
103 importer = mbox_importer_peek ();
104 e_import_class_add_importer (import_class, importer, NULL, NULL);
105 mbox_importer_set_preview_funcs (
106 mbox_create_preview_cb, mbox_fill_preview_cb);
107
108 importer = elm_importer_peek ();
109 e_import_class_add_importer (import_class, importer, NULL, NULL);
110
111 importer = pine_importer_peek ();
112 e_import_class_add_importer (import_class, importer, NULL, NULL);
113 }
114
115 static void
116 mail_shell_backend_mail_icon_cb (EShellWindow *shell_window,
117 const gchar *icon_name)
118 {
119 GtkAction *action;
120
121 action = e_shell_window_get_shell_view_action (
122 shell_window, BACKEND_NAME);
123 gtk_action_set_icon_name (action, icon_name);
124 }
125
126 static void
127 action_mail_folder_new_cb (GtkAction *action,
128 EShellWindow *shell_window)
129 {
130 EMFolderTree *folder_tree = NULL;
131 EMailShellSidebar *mail_shell_sidebar;
132 EMailSession *session;
133 EShellSidebar *shell_sidebar;
134 EShellView *shell_view;
135 const gchar *view_name;
136
137 /* Take care not to unnecessarily load the mail shell view. */
138 view_name = e_shell_window_get_active_view (shell_window);
139 if (g_strcmp0 (view_name, BACKEND_NAME) != 0) {
140 EShell *shell;
141 EShellBackend *shell_backend;
142 EMailBackend *backend;
143
144 shell = e_shell_window_get_shell (shell_window);
145
146 shell_backend =
147 e_shell_get_backend_by_name (shell, BACKEND_NAME);
148 g_return_if_fail (E_IS_MAIL_BACKEND (shell_backend));
149
150 backend = E_MAIL_BACKEND (shell_backend);
151 session = e_mail_backend_get_session (backend);
152
153 goto exit;
154 }
155
156 shell_view = e_shell_window_get_shell_view (shell_window, view_name);
157 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
158
159 mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar);
160 folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
161 session = em_folder_tree_get_session (folder_tree);
162
163 exit:
164 em_folder_utils_create_folder (
165 GTK_WINDOW (shell_window), session, folder_tree, NULL);
166 }
167
168 static void
169 action_mail_account_new_cb (GtkAction *action,
170 EShellWindow *shell_window)
171 {
172 EShell *shell;
173 EShellBackend *shell_backend;
174
175 g_return_if_fail (shell_window != NULL);
176
177 shell = e_shell_window_get_shell (shell_window);
178 shell_backend = e_shell_get_backend_by_name (shell, BACKEND_NAME);
179 g_return_if_fail (E_IS_MAIL_SHELL_BACKEND (shell_backend));
180
181 e_mail_shell_backend_new_account (
182 E_MAIL_SHELL_BACKEND (shell_backend),
183 GTK_WINDOW (shell_window));
184 }
185
186 static void
187 action_mail_message_new_cb (GtkAction *action,
188 EShellWindow *shell_window)
189 {
190 EMailShellSidebar *mail_shell_sidebar;
191 EShellSidebar *shell_sidebar;
192 EShellView *shell_view;
193 EShell *shell;
194 ESourceRegistry *registry;
195 EMFolderTree *folder_tree;
196 CamelFolder *folder = NULL;
197 CamelStore *store;
198 GList *list;
199 const gchar *extension_name;
200 const gchar *view_name;
201 gboolean no_transport_defined;
202 gchar *folder_name;
203
204 shell = e_shell_window_get_shell (shell_window);
205 registry = e_shell_get_registry (shell);
206
207 extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT;
208 list = e_source_registry_list_sources (registry, extension_name);
209 no_transport_defined = (list == NULL);
210 g_list_free_full (list, (GDestroyNotify) g_object_unref);
211
212 if (no_transport_defined)
213 return;
214
215 /* Take care not to unnecessarily load the mail shell view. */
216 view_name = e_shell_window_get_active_view (shell_window);
217 if (g_strcmp0 (view_name, BACKEND_NAME) != 0)
218 goto exit;
219
220 shell_view = e_shell_window_get_shell_view (shell_window, view_name);
221 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
222
223 mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar);
224 folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
225
226 if (em_folder_tree_get_selected (folder_tree, &store, &folder_name)) {
227
228 /* FIXME This blocks and is not cancellable. */
229 folder = camel_store_get_folder_sync (
230 store, folder_name, 0, NULL, NULL);
231
232 g_object_unref (store);
233 g_free (folder_name);
234 }
235
236 exit:
237 em_utils_compose_new_message (shell, folder);
238 }
239
240 static GtkActionEntry item_entries[] = {
241
242 { "mail-message-new",
243 "mail-message-new",
244 NC_("New", "_Mail Message"),
245 "<Shift><Control>m",
246 N_("Compose a new mail message"),
247 G_CALLBACK (action_mail_message_new_cb) }
248 };
249
250 static GtkActionEntry source_entries[] = {
251
252 { "mail-account-new",
253 "evolution-mail",
254 NC_("New", "Mail Acco_unt"),
255 NULL,
256 N_("Create a new mail account"),
257 G_CALLBACK (action_mail_account_new_cb) },
258
259 { "mail-folder-new",
260 "folder-new",
261 NC_("New", "Mail _Folder"),
262 NULL,
263 N_("Create a new mail folder"),
264 G_CALLBACK (action_mail_folder_new_cb) }
265 };
266
267 static void
268 mail_shell_backend_sync_store_done_cb (CamelStore *store,
269 gpointer user_data)
270 {
271 EMailShellBackend *mail_shell_backend = user_data;
272
273 mail_shell_backend->priv->mail_sync_in_progress--;
274 }
275
276 static gboolean
277 mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend)
278 {
279 EShell *shell;
280 EShellBackend *shell_backend;
281 EMailBackend *backend;
282 EMailSession *session;
283 GList *list, *link;
284
285 shell_backend = E_SHELL_BACKEND (mail_shell_backend);
286 shell = e_shell_backend_get_shell (shell_backend);
287
288 /* Obviously we can only sync in online mode. */
289 if (!e_shell_get_online (shell))
290 goto exit;
291
292 /* If a sync is still in progress, skip this round. */
293 if (mail_shell_backend->priv->mail_sync_in_progress)
294 goto exit;
295
296 backend = E_MAIL_BACKEND (mail_shell_backend);
297 session = e_mail_backend_get_session (backend);
298
299 list = camel_session_list_services (CAMEL_SESSION (session));
300
301 for (link = list; link != NULL; link = g_list_next (link)) {
302 CamelService *service;
303
304 service = CAMEL_SERVICE (link->data);
305
306 if (!CAMEL_IS_STORE (service))
307 continue;
308
309 mail_shell_backend->priv->mail_sync_in_progress++;
310
311 mail_sync_store (
312 CAMEL_STORE (service), FALSE,
313 mail_shell_backend_sync_store_done_cb,
314 mail_shell_backend);
315 }
316
317 g_list_free_full (list, (GDestroyNotify) g_object_unref);
318
319 exit:
320 return TRUE;
321 }
322
323 static gboolean
324 mail_shell_backend_handle_uri_cb (EShell *shell,
325 const gchar *uri,
326 EMailShellBackend *mail_shell_backend)
327 {
328 gboolean handled = FALSE;
329
330 if (g_str_has_prefix (uri, "mailto:")) {
331 em_utils_compose_new_message_with_mailto (shell, uri, NULL);
332 handled = TRUE;
333 }
334
335 return handled;
336 }
337
338 static void
339 mail_shell_backend_prepare_for_quit_cb (EShell *shell,
340 EActivity *activity,
341 EShellBackend *shell_backend)
342 {
343 EMailShellBackendPrivate *priv;
344
345 priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (shell_backend);
346
347 /* Prevent a sync from starting while trying to shutdown. */
348 if (priv->mail_sync_source_id > 0) {
349 g_source_remove (priv->mail_sync_source_id);
350 priv->mail_sync_source_id = 0;
351 }
352 }
353
354 static void
355 mail_shell_backend_window_weak_notify_cb (EShell *shell,
356 GObject *where_the_object_was)
357 {
358 g_signal_handlers_disconnect_by_func (
359 shell, mail_shell_backend_mail_icon_cb,
360 where_the_object_was);
361 }
362
363 static void
364 mail_shell_backend_window_added_cb (GtkApplication *application,
365 GtkWindow *window,
366 EShellBackend *shell_backend)
367 {
368 EShell *shell = E_SHELL (application);
369 EMailBackend *backend;
370 EMailSession *session;
371 const gchar *backend_name;
372
373 backend = E_MAIL_BACKEND (shell_backend);
374 session = e_mail_backend_get_session (backend);
375
376 /* This applies to both the composer and signature editor. */
377 if (GTKHTML_IS_EDITOR (window)) {
378 EShellSettings *shell_settings;
379 GList *spell_languages;
380 gboolean active = TRUE;
381
382 spell_languages = e_load_spell_languages ();
383 gtkhtml_editor_set_spell_languages (
384 GTKHTML_EDITOR (window), spell_languages);
385 g_list_free (spell_languages);
386
387 shell_settings = e_shell_get_shell_settings (shell);
388
389 /* Express mode does not honor this setting. */
390 if (!e_shell_get_express_mode (shell))
391 active = e_shell_settings_get_boolean (
392 shell_settings, "composer-format-html");
393
394 gtkhtml_editor_set_html_mode (GTKHTML_EDITOR (window), active);
395 }
396
397 if (E_IS_MSG_COMPOSER (window)) {
398 /* Start the mail backend if it isn't already. This
399 * may be necessary when opening a new composer window
400 * from a shell view other than mail. */
401 e_shell_backend_start (shell_backend);
402
403 /* Integrate the new composer into the mail module. */
404 em_configure_new_composer (
405 E_MSG_COMPOSER (window), session);
406 return;
407 }
408
409 if (!E_IS_SHELL_WINDOW (window))
410 return;
411
412 backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name;
413
414 e_shell_window_register_new_item_actions (
415 E_SHELL_WINDOW (window), backend_name,
416 item_entries, G_N_ELEMENTS (item_entries));
417
418 e_shell_window_register_new_source_actions (
419 E_SHELL_WINDOW (window), backend_name,
420 source_entries, G_N_ELEMENTS (source_entries));
421
422 g_signal_connect_swapped (
423 shell, "event::mail-icon",
424 G_CALLBACK (mail_shell_backend_mail_icon_cb), window);
425
426 g_object_weak_ref (
427 G_OBJECT (window), (GWeakNotify)
428 mail_shell_backend_window_weak_notify_cb, shell);
429 }
430
431 static void
432 mail_shell_backend_disconnect_done_cb (GObject *source_object,
433 GAsyncResult *result,
434 gpointer user_data)
435 {
436 CamelService *service;
437 EActivity *activity;
438 EAlertSink *alert_sink;
439 GError *error = NULL;
440
441 service = CAMEL_SERVICE (source_object);
442 activity = E_ACTIVITY (user_data);
443
444 alert_sink = e_activity_get_alert_sink (activity);
445
446 camel_service_disconnect_finish (service, result, &error);
447
448 if (e_activity_handle_cancellation (activity, error)) {
449 g_error_free (error);
450
451 } else if (error != NULL) {
452 e_alert_submit (
453 alert_sink,
454 "mail:disconnect",
455 camel_service_get_display_name (service),
456 error->message, NULL);
457 g_error_free (error);
458
459 } else {
460 e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
461 }
462
463 g_object_unref (activity);
464 }
465
466 static void
467 mail_shell_backend_changes_committed_cb (EMailConfigWindow *window,
468 EMailShellBackend *mail_shell_backend)
469 {
470 EMailSession *session;
471 EShell *shell;
472 EShellBackend *shell_backend;
473 ESource *original_source;
474 CamelService *service;
475 EActivity *activity;
476 GCancellable *cancellable;
477 GList *list, *link;
478 const gchar *uid;
479
480 session = e_mail_config_window_get_session (window);
481 original_source = e_mail_config_window_get_original_source (window);
482
483 uid = e_source_get_uid (original_source);
484 service = camel_session_ref_service (CAMEL_SESSION (session), uid);
485 g_return_if_fail (service != NULL);
486
487 shell_backend = E_SHELL_BACKEND (mail_shell_backend);
488
489 shell = e_shell_backend_get_shell (shell_backend);
490 list = gtk_application_get_windows (GTK_APPLICATION (shell));
491
492 activity = e_activity_new ();
493
494 /* Find an EShellWindow to serve as an EAlertSink. */
495 for (link = list; link != NULL; link = g_list_next (link)) {
496 GtkWindow *window = GTK_WINDOW (link->data);
497
498 if (E_IS_SHELL_WINDOW (window)) {
499 EAlertSink *alert_sink = E_ALERT_SINK (window);
500 e_activity_set_alert_sink (activity, alert_sink);
501 }
502 }
503
504 cancellable = camel_operation_new ();
505 e_activity_set_cancellable (activity, cancellable);
506
507 e_shell_backend_add_activity (shell_backend, activity);
508
509 camel_service_disconnect (
510 service, TRUE, G_PRIORITY_DEFAULT, cancellable,
511 mail_shell_backend_disconnect_done_cb, activity);
512
513 g_object_unref (cancellable);
514
515 g_object_unref (service);
516 }
517
518 static void
519 mail_shell_backend_constructed (GObject *object)
520 {
521 EShell *shell;
522 EShellSettings *shell_settings;
523 EShellBackend *shell_backend;
524 EMailSession *mail_session;
525 CamelService *vstore;
526 GtkWidget *preferences_window;
527
528 shell_backend = E_SHELL_BACKEND (object);
529 shell = e_shell_backend_get_shell (shell_backend);
530 shell_settings = e_shell_get_shell_settings (shell);
531
532 /* Chain up to parent's constructed() method. */
533 G_OBJECT_CLASS (e_mail_shell_backend_parent_class)->constructed (object);
534
535 mail_shell_backend_init_importers ();
536
537 g_signal_connect (
538 shell, "handle-uri",
539 G_CALLBACK (mail_shell_backend_handle_uri_cb),
540 shell_backend);
541
542 g_signal_connect (
543 shell, "prepare-for-quit",
544 G_CALLBACK (mail_shell_backend_prepare_for_quit_cb),
545 shell_backend);
546
547 g_signal_connect (
548 shell, "window-added",
549 G_CALLBACK (mail_shell_backend_window_added_cb),
550 shell_backend);
551
552 e_mail_shell_settings_init (shell_backend);
553
554 /* Setup preference widget factories */
555 preferences_window = e_shell_get_preferences_window (shell);
556
557 e_preferences_window_add_page (
558 E_PREFERENCES_WINDOW (preferences_window),
559 "mail-accounts",
560 "preferences-mail-accounts",
561 _("Mail Accounts"),
562 "mail-account-management",
563 em_account_prefs_new,
564 100);
565
566 e_preferences_window_add_page (
567 E_PREFERENCES_WINDOW (preferences_window),
568 "mail",
569 "preferences-mail",
570 _("Mail Preferences"),
571 "index#mail-basic",
572 em_mailer_prefs_new,
573 300);
574
575 e_preferences_window_add_page (
576 E_PREFERENCES_WINDOW (preferences_window),
577 "composer",
578 "preferences-composer",
579 _("Composer Preferences"),
580 "index#mail-composing",
581 em_composer_prefs_new,
582 400);
583
584 e_preferences_window_add_page (
585 E_PREFERENCES_WINDOW (preferences_window),
586 "system-network-proxy",
587 "preferences-system-network-proxy",
588 _("Network Preferences"),
589 NULL,
590 em_network_prefs_new,
591 500);
592
593 mail_session = e_mail_backend_get_session (E_MAIL_BACKEND (object));
594 vstore = camel_session_ref_service (
595 CAMEL_SESSION (mail_session), E_MAIL_SESSION_VFOLDER_UID);
596 g_return_if_fail (vstore != NULL);
597
598 g_object_bind_property (
599 shell_settings, "mail-enable-unmatched-search-folder",
600 vstore, "unmatched-enabled",
601 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
602
603 g_object_unref (vstore);
604 }
605
606 static void
607 mail_shell_backend_start (EShellBackend *shell_backend)
608 {
609 EMailShellBackendPrivate *priv;
610 EMailBackend *backend;
611 EMailSession *session;
612 EMailAccountStore *account_store;
613 GError *error = NULL;
614
615 priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (shell_backend);
616
617 backend = E_MAIL_BACKEND (shell_backend);
618 session = e_mail_backend_get_session (backend);
619 account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session));
620
621 /* XXX Should we be calling this unconditionally? */
622 vfolder_load_storage (session);
623
624 if (!e_mail_account_store_load_sort_order (account_store, &error)) {
625 g_warning ("%s: %s", G_STRFUNC, error->message);
626 g_error_free (error);
627 }
628
629 if (g_getenv ("CAMEL_FLUSH_CHANGES") != NULL)
630 priv->mail_sync_source_id = g_timeout_add_seconds (
631 mail_config_get_sync_timeout (),
632 (GSourceFunc) mail_shell_backend_mail_sync,
633 shell_backend);
634 }
635
636 static gboolean
637 mail_shell_backend_delete_junk_policy_decision (EMailBackend *backend)
638 {
639 EShell *shell;
640 EShellSettings *shell_settings;
641 GSettings *settings;
642 gboolean delete_junk;
643 gint empty_date;
644 gint empty_days;
645 gint now;
646
647 shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
648
649 settings = g_settings_new ("org.gnome.evolution.mail");
650 shell_settings = e_shell_get_shell_settings (shell);
651
652 now = time (NULL) / 60 / 60 / 24;
653
654 delete_junk = e_shell_settings_get_boolean (
655 shell_settings, "mail-empty-junk-on-exit");
656
657 /* XXX No EShellSettings properties for these keys. */
658
659 empty_date = empty_days = 0;
660
661 if (delete_junk) {
662 empty_days = g_settings_get_int (settings, "junk-empty-on-exit-days");
663 empty_date = g_settings_get_int (settings, "junk-empty-date");
664 }
665
666 delete_junk &= (empty_days == 0) || (empty_date + empty_days <= now);
667
668 if (delete_junk) {
669 g_settings_set_int (settings, "junk-empty-date", now);
670 }
671
672 g_object_unref (settings);
673
674 return delete_junk;
675 }
676
677 static gboolean
678 mail_shell_backend_empty_trash_policy_decision (EMailBackend *backend)
679 {
680 EShell *shell;
681 EShellSettings *shell_settings;
682 GSettings *settings;
683 gboolean empty_trash;
684 gint empty_date;
685 gint empty_days;
686 gint now;
687
688 shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
689
690 settings = g_settings_new ("org.gnome.evolution.mail");
691 shell_settings = e_shell_get_shell_settings (shell);
692
693 now = time (NULL) / 60 / 60 / 24;
694
695 empty_trash = e_shell_settings_get_boolean (
696 shell_settings, "mail-empty-trash-on-exit");
697
698 /* XXX No EShellSettings properties for these keys. */
699
700 empty_date = empty_days = 0;
701
702 if (empty_trash) {
703 empty_days = g_settings_get_int (settings, "trash-empty-on-exit-days");
704 empty_date = g_settings_get_int (settings, "trash-empty-date");
705 }
706
707 empty_trash &= (empty_days == 0) || (empty_date + empty_days <= now);
708
709 if (empty_trash) {
710 g_settings_set_int (settings, "trash-empty-date", now);
711 }
712
713 g_object_unref (settings);
714
715 return empty_trash;
716 }
717
718 static void
719 mail_shell_backend_dispose (GObject *object)
720 {
721 EMailShellBackendPrivate *priv;
722
723 priv = E_MAIL_SHELL_BACKEND (object)->priv;
724
725 if (priv->assistant != NULL) {
726 g_object_remove_weak_pointer (
727 G_OBJECT (priv->assistant), &priv->assistant);
728 priv->assistant = NULL;
729 }
730
731 if (priv->editor != NULL) {
732 g_object_remove_weak_pointer (
733 G_OBJECT (priv->editor), &priv->editor);
734 priv->editor = NULL;
735 }
736
737 /* Chain up to parent's dispose() method. */
738 G_OBJECT_CLASS (e_mail_shell_backend_parent_class)->dispose (object);
739 }
740
741 static void
742 e_mail_shell_backend_class_init (EMailShellBackendClass *class)
743 {
744 GObjectClass *object_class;
745 EShellBackendClass *shell_backend_class;
746 EMailBackendClass *mail_backend_class;
747
748 g_type_class_add_private (class, sizeof (EMailShellBackendPrivate));
749
750 object_class = G_OBJECT_CLASS (class);
751 object_class->constructed = mail_shell_backend_constructed;
752 object_class->dispose = mail_shell_backend_dispose;
753
754 shell_backend_class = E_SHELL_BACKEND_CLASS (class);
755 shell_backend_class->shell_view_type = E_TYPE_MAIL_SHELL_VIEW;
756 shell_backend_class->name = BACKEND_NAME;
757 shell_backend_class->aliases = "";
758 shell_backend_class->schemes = "mailto:email";
759 shell_backend_class->sort_order = 200;
760 shell_backend_class->preferences_page = "mail-accounts";
761 shell_backend_class->start = mail_shell_backend_start;
762
763 mail_backend_class = E_MAIL_BACKEND_CLASS (class);
764 mail_backend_class->delete_junk_policy_decision =
765 mail_shell_backend_delete_junk_policy_decision;
766 mail_backend_class->empty_trash_policy_decision =
767 mail_shell_backend_empty_trash_policy_decision;
768 }
769
770 static void
771 e_mail_shell_backend_class_finalize (EMailShellBackendClass *class)
772 {
773 }
774
775 static void
776 e_mail_shell_backend_init (EMailShellBackend *mail_shell_backend)
777 {
778 mail_shell_backend->priv =
779 E_MAIL_SHELL_BACKEND_GET_PRIVATE (mail_shell_backend);
780 }
781
782 void
783 e_mail_shell_backend_type_register (GTypeModule *type_module)
784 {
785 /* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
786 * function, so we have to wrap it with a public function in
787 * order to register types from a separate compilation unit. */
788 e_mail_shell_backend_register_type (type_module);
789 }
790
791 void
792 e_mail_shell_backend_new_account (EMailShellBackend *mail_shell_backend,
793 GtkWindow *parent)
794 {
795 GtkWidget *assistant;
796 EMailBackend *backend;
797 EMailSession *session;
798
799 g_return_if_fail (mail_shell_backend != NULL);
800 g_return_if_fail (E_IS_MAIL_SHELL_BACKEND (mail_shell_backend));
801
802 assistant = mail_shell_backend->priv->assistant;
803
804 if (assistant != NULL) {
805 gtk_window_present (GTK_WINDOW (assistant));
806 return;
807 }
808
809 backend = E_MAIL_BACKEND (mail_shell_backend);
810 session = e_mail_backend_get_session (backend);
811
812 if (assistant == NULL)
813 assistant = e_mail_config_assistant_new (session);
814
815 gtk_window_set_transient_for (GTK_WINDOW (assistant), parent);
816 gtk_widget_show (assistant);
817
818 mail_shell_backend->priv->assistant = assistant;
819
820 g_object_add_weak_pointer (
821 G_OBJECT (mail_shell_backend->priv->assistant),
822 &mail_shell_backend->priv->assistant);
823 }
824
825 void
826 e_mail_shell_backend_edit_account (EMailShellBackend *mail_shell_backend,
827 GtkWindow *parent,
828 ESource *mail_account)
829 {
830 EMailShellBackendPrivate *priv;
831 EMailBackend *backend;
832 EMailSession *session;
833
834 g_return_if_fail (E_IS_MAIL_SHELL_BACKEND (mail_shell_backend));
835 g_return_if_fail (E_IS_SOURCE (mail_account));
836
837 priv = mail_shell_backend->priv;
838
839 backend = E_MAIL_BACKEND (mail_shell_backend);
840 session = e_mail_backend_get_session (backend);
841
842 if (priv->editor != NULL) {
843 gtk_window_present (GTK_WINDOW (priv->editor));
844 return;
845 }
846
847 priv->editor = e_mail_config_window_new (session, mail_account);
848 gtk_window_set_transient_for (GTK_WINDOW (priv->editor), parent);
849 g_object_add_weak_pointer (G_OBJECT (priv->editor), &priv->editor);
850
851 g_signal_connect (
852 priv->editor, "changes-committed",
853 G_CALLBACK (mail_shell_backend_changes_committed_cb),
854 mail_shell_backend);
855
856 gtk_widget_show (priv->editor);
857 }
858
859 /******************* Code below here belongs elsewhere. *******************/
860
861 #include "filter/e-filter-option.h"
862 #include "shell/e-shell-settings.h"
863
864 static GSList *
865 mail_labels_get_filter_options (gboolean include_none)
866 {
867 EShell *shell;
868 EShellBackend *shell_backend;
869 EMailBackend *backend;
870 EMailSession *session;
871 EMailLabelListStore *label_store;
872 GtkTreeModel *model;
873 GtkTreeIter iter;
874 GSList *list = NULL;
875 gboolean valid;
876
877 shell = e_shell_get_default ();
878 shell_backend = e_shell_get_backend_by_name (shell, "mail");
879
880 backend = E_MAIL_BACKEND (shell_backend);
881 session = e_mail_backend_get_session (backend);
882 label_store = e_mail_ui_session_get_label_store (
883 E_MAIL_UI_SESSION (session));
884
885 if (include_none) {
886 struct _filter_option *option;
887
888 option = g_new0 (struct _filter_option, 1);
889 /* Translators: The first item in the list, to be able to set rule: [Label] [is/is-not] [None] */
890 option->title = g_strdup (C_("label", "None"));
891 option->value = g_strdup ("");
892 list = g_slist_prepend (list, option);
893 }
894
895 model = GTK_TREE_MODEL (label_store);
896 valid = gtk_tree_model_get_iter_first (model, &iter);
897
898 while (valid) {
899 struct _filter_option *option;
900 gchar *name, *tag;
901
902 name = e_mail_label_list_store_get_name (label_store, &iter);
903 tag = e_mail_label_list_store_get_tag (label_store, &iter);
904
905 if (g_str_has_prefix (tag, "$Label")) {
906 gchar *tmp = tag;
907
908 tag = g_strdup (tag + 6);
909
910 g_free (tmp);
911 }
912
913 option = g_new0 (struct _filter_option, 1);
914 option->title = e_str_without_underscores (name);
915 option->value = tag; /* takes ownership */
916 list = g_slist_prepend (list, option);
917
918 g_free (name);
919
920 valid = gtk_tree_model_iter_next (model, &iter);
921 }
922
923 return g_slist_reverse (list);
924 }
925
926 GSList *
927 e_mail_labels_get_filter_options (void)
928 {
929 return mail_labels_get_filter_options (TRUE);
930 }
931
932 GSList *
933 e_mail_labels_get_filter_options_without_none (void)
934 {
935 return mail_labels_get_filter_options (FALSE);
936 }
937
938 static const gchar *
939 get_filter_option_value (EFilterPart *part,
940 const gchar *name)
941 {
942 EFilterElement *elem;
943 EFilterOption *opt;
944
945 g_return_val_if_fail (part != NULL, NULL);
946 g_return_val_if_fail (name != NULL, NULL);
947
948 elem = e_filter_part_find_element (part, name);
949 g_return_val_if_fail (elem != NULL, NULL);
950 g_return_val_if_fail (E_IS_FILTER_OPTION (elem), NULL);
951
952 opt = E_FILTER_OPTION (elem);
953 return e_filter_option_get_current (opt);
954 }
955
956 static void
957 append_one_label_expr (GString *out,
958 const gchar *versus)
959 {
960 GString *encoded;
961
962 g_return_if_fail (out != NULL);
963 g_return_if_fail (versus != NULL);
964
965 encoded = g_string_new ("");
966 camel_sexp_encode_string (encoded, versus);
967
968 g_string_append_printf (
969 out,
970 " (= (user-tag \"label\") %s) (user-flag (+ \"$Label\" %s)) (user-flag %s)",
971 encoded->str, encoded->str, encoded->str);
972
973 g_string_free (encoded, TRUE);
974 }
975
976 void
977 e_mail_labels_get_filter_code (EFilterElement *element,
978 GString *out,
979 EFilterPart *part)
980 {
981 const gchar *label_type, *versus;
982 gboolean is_not;
983
984 label_type = get_filter_option_value (part, "label-type");
985 versus = get_filter_option_value (part, "versus");
986
987 g_return_if_fail (label_type != NULL);
988 g_return_if_fail (versus != NULL);
989
990 is_not = g_str_equal (label_type, "is-not");
991
992 if (!g_str_equal (label_type, "is") && !is_not) {
993 g_warning ("%s: Unknown label-type: '%s'", G_STRFUNC, label_type);
994 return;
995 }
996
997 /* the 'None' item has 'is-not' inverted */
998 if (!*versus)
999 is_not = !is_not;
1000
1001 g_string_append (out, " (match-all (");
1002 if (is_not)
1003 g_string_append (out, " not (");
1004 g_string_append (out, "or");
1005
1006 /* the 'None' item; "is None" means "has not set any label" */
1007 if (!*versus) {
1008 EShell *shell;
1009 EShellBackend *shell_backend;
1010 EMailBackend *backend;
1011 EMailSession *session;
1012 EMailLabelListStore *label_store;
1013 GtkTreeModel *model;
1014 GtkTreeIter iter;
1015 gboolean valid;
1016
1017 shell = e_shell_get_default ();
1018 shell_backend = e_shell_get_backend_by_name (shell, "mail");
1019
1020 backend = E_MAIL_BACKEND (shell_backend);
1021 session = e_mail_backend_get_session (backend);
1022 label_store = e_mail_ui_session_get_label_store (E_MAIL_UI_SESSION (session));
1023
1024 model = GTK_TREE_MODEL (label_store);
1025 valid = gtk_tree_model_get_iter_first (model, &iter);
1026
1027 while (valid) {
1028 gchar *tag;
1029
1030 tag = e_mail_label_list_store_get_tag (label_store, &iter);
1031
1032 if (g_str_has_prefix (tag, "$Label")) {
1033 gchar *tmp = tag;
1034
1035 tag = g_strdup (tag + 6);
1036
1037 g_free (tmp);
1038 }
1039
1040 append_one_label_expr (out, tag);
1041
1042 g_free (tag);
1043
1044 valid = gtk_tree_model_iter_next (model, &iter);
1045 }
1046 } else {
1047 append_one_label_expr (out, versus);
1048 }
1049
1050 if (is_not)
1051 g_string_append (out, ")");
1052 g_string_append (out, " ))");
1053 }
1054
1055 static void
1056 message_parsed_cb (GObject *source_object,
1057 GAsyncResult *res,
1058 gpointer user_data)
1059 {
1060 EMailParser *parser = E_MAIL_PARSER (source_object);
1061 EMailPartList *parts_list;
1062 GObject *preview = user_data;
1063 EMailDisplay *display;
1064 SoupSession *soup_session;
1065 GHashTable *mails;
1066 gchar *mail_uri;
1067
1068 display = g_object_get_data (preview, "mbox-imp-display");
1069
1070 parts_list = e_mail_parser_parse_finish (parser, res, NULL);
1071
1072 soup_session = webkit_get_default_session ();
1073 mails = g_object_get_data (G_OBJECT (soup_session), "mails");
1074 if (!mails) {
1075 mails = g_hash_table_new_full (
1076 g_str_hash, g_str_equal,
1077 (GDestroyNotify) g_free, NULL);
1078 g_object_set_data (
1079 G_OBJECT (soup_session), "mails", mails);
1080 }
1081 mail_uri = e_mail_part_build_uri (
1082 parts_list->folder, parts_list->message_uid, NULL, NULL);
1083
1084 g_hash_table_insert (mails, mail_uri, parts_list);
1085
1086 e_mail_display_set_parts_list (display, parts_list);
1087 e_mail_display_load (display, NULL);
1088
1089 g_object_unref (parts_list);
1090 }
1091
1092 /* utility functions for mbox importer */
1093 static void
1094 mbox_create_preview_cb (GObject *preview,
1095 GtkWidget **preview_widget)
1096 {
1097 EMailDisplay *display;
1098
1099 g_return_if_fail (preview != NULL);
1100 g_return_if_fail (preview_widget != NULL);
1101
1102 display = g_object_new (E_TYPE_MAIL_DISPLAY, NULL);
1103 g_object_set_data_full (
1104 preview, "mbox-imp-display",
1105 g_object_ref (display), g_object_unref);
1106
1107 *preview_widget = GTK_WIDGET (display);
1108 }
1109
1110 static void
1111 mbox_fill_preview_cb (GObject *preview,
1112 CamelMimeMessage *msg)
1113 {
1114 EShell *shell;
1115 EMailDisplay *display;
1116 EMailParser *parser;
1117 EMailSession *mail_session;
1118 ESourceRegistry *registry;
1119
1120 g_return_if_fail (preview != NULL);
1121 g_return_if_fail (msg != NULL);
1122
1123 display = g_object_get_data (preview, "mbox-imp-display");
1124 g_return_if_fail (display != NULL);
1125
1126 shell = e_shell_get_default ();
1127 registry = e_shell_get_registry (shell);
1128 mail_session = e_mail_session_new (registry);
1129
1130 parser = e_mail_parser_new (CAMEL_SESSION (mail_session));
1131 e_mail_parser_parse (
1132 parser, NULL, msg->message_id, msg,
1133 message_parsed_cb, NULL, preview);
1134
1135 g_object_unref (mail_session);
1136 }