No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | e-mail-shell-view-private.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None | |
clang-analyzer | no-output-found | e-mail-shell-view-private.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /*
2 * e-mail-shell-view-private.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-view-private.h"
27
28 #include "widgets/menus/gal-view-factory-etable.h"
29 #include "widgets/misc/e-menu-tool-button.h"
30
31 #include "e-util/e-util-private.h"
32
33 typedef struct _AsyncContext AsyncContext;
34
35 struct _AsyncContext {
36 EActivity *activity;
37 EMailReader *reader;
38 EShellView *shell_view;
39 };
40
41 static void
42 async_context_free (AsyncContext *context)
43 {
44 if (context->activity != NULL)
45 g_object_unref (context->activity);
46
47 if (context->reader != NULL)
48 g_object_unref (context->reader);
49
50 if (context->shell_view != NULL)
51 g_object_unref (context->shell_view);
52
53 g_slice_free (AsyncContext, context);
54 }
55
56 static void
57 mail_shell_view_got_folder_cb (CamelStore *store,
58 GAsyncResult *result,
59 AsyncContext *context)
60 {
61 EAlertSink *alert_sink;
62 CamelFolder *folder;
63 GError *error = NULL;
64
65 alert_sink = e_activity_get_alert_sink (context->activity);
66
67 folder = camel_store_get_folder_finish (store, result, &error);
68
69 if (e_activity_handle_cancellation (context->activity, error)) {
70 g_warn_if_fail (folder == NULL);
71 async_context_free (context);
72 g_error_free (error);
73 return;
74
75 } else if (error != NULL) {
76 g_warn_if_fail (folder == NULL);
77 e_alert_submit (
78 alert_sink, "mail:folder-open",
79 error->message, NULL);
80 async_context_free (context);
81 g_error_free (error);
82 return;
83 }
84
85 e_mail_reader_set_folder (context->reader, folder);
86 e_shell_view_update_actions (context->shell_view);
87
88 g_object_unref (folder);
89
90 async_context_free (context);
91 }
92
93 static void
94 mail_shell_view_folder_tree_selected_cb (EMailShellView *mail_shell_view,
95 CamelStore *store,
96 const gchar *folder_name,
97 CamelFolderInfoFlags flags,
98 EMFolderTree *folder_tree)
99 {
100 EMailShellContent *mail_shell_content;
101 EShellView *shell_view;
102 EMailReader *reader;
103 EMailView *mail_view;
104 GCancellable *cancellable;
105 AsyncContext *context;
106 EActivity *activity;
107
108 shell_view = E_SHELL_VIEW (mail_shell_view);
109
110 mail_shell_content = mail_shell_view->priv->mail_shell_content;
111 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
112
113 reader = E_MAIL_READER (mail_view);
114
115 /* Cancel any unfinished open folder operations. */
116 if (mail_shell_view->priv->opening_folder != NULL) {
117 g_cancellable_cancel (mail_shell_view->priv->opening_folder);
118 g_object_unref (mail_shell_view->priv->opening_folder);
119 mail_shell_view->priv->opening_folder = NULL;
120 }
121
122 /* If we are to clear the message list, do so immediately. */
123 if ((flags & CAMEL_FOLDER_NOSELECT) || folder_name == NULL) {
124 e_mail_reader_set_folder (reader, NULL);
125 e_shell_view_update_actions (shell_view);
126 return;
127 }
128
129 g_warn_if_fail (CAMEL_IS_STORE (store));
130
131 /* Open the selected folder asynchronously. */
132
133 activity = e_mail_reader_new_activity (reader);
134 cancellable = e_activity_get_cancellable (activity);
135 mail_shell_view->priv->opening_folder = g_object_ref (cancellable);
136
137 context = g_slice_new0 (AsyncContext);
138 context->activity = activity;
139 context->reader = g_object_ref (reader);
140 context->shell_view = g_object_ref (shell_view);
141
142 camel_store_get_folder (
143 store, folder_name, 0, G_PRIORITY_DEFAULT, cancellable,
144 (GAsyncReadyCallback) mail_shell_view_got_folder_cb, context);
145 }
146
147 static gboolean
148 mail_shell_view_folder_tree_key_press_event_cb (EMailShellView *mail_shell_view,
149 GdkEventKey *event)
150 {
151 EMailShellContent *mail_shell_content;
152 EMailView *mail_view;
153 gboolean handled = FALSE;
154
155 mail_shell_content = mail_shell_view->priv->mail_shell_content;
156 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
157
158 if ((event->state & GDK_CONTROL_MASK) != 0)
159 goto ctrl;
160
161 /* <keyval> alone */
162 switch (event->keyval) {
163 case GDK_KEY_period:
164 case GDK_KEY_comma:
165 case GDK_KEY_bracketleft:
166 case GDK_KEY_bracketright:
167 goto emit;
168
169 default:
170 goto exit;
171 }
172
173 ctrl:
174 /* Ctrl + <keyval> */
175 switch (event->keyval) {
176 case GDK_KEY_period:
177 case GDK_KEY_comma:
178 goto emit;
179
180 default:
181 goto exit;
182 }
183
184 /* All branches jump past this. */
185 g_return_val_if_reached (FALSE);
186
187 emit:
188 /* Forward the key press to the EMailReader interface. */
189 g_signal_emit_by_name (mail_view, "key-press-event", event, &handled);
190
191 exit:
192 return handled;
193 }
194
195 static void
196 mail_shell_view_folder_tree_selection_done_cb (EMailShellView *mail_shell_view,
197 GtkWidget *menu)
198 {
199 EMailShellContent *mail_shell_content;
200 EMailShellSidebar *mail_shell_sidebar;
201 EMFolderTree *folder_tree;
202 GtkWidget *message_list;
203 EMailReader *reader;
204 EMailView *mail_view;
205 CamelFolder *folder;
206 gchar *list_uri;
207 gchar *tree_uri;
208
209 mail_shell_content = mail_shell_view->priv->mail_shell_content;
210 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
211
212 mail_shell_sidebar = mail_shell_view->priv->mail_shell_sidebar;
213 folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
214
215 reader = E_MAIL_READER (mail_view);
216 message_list = e_mail_reader_get_message_list (reader);
217
218 /* Don't use e_mail_reader_get_folder() here. The fact that the
219 * method gets the folder from the message list is supposed to be
220 * a hidden implementation detail, and we want to explicitly get
221 * the folder URI from the message list here. */
222 folder = MESSAGE_LIST (message_list)->folder;
223 if (folder)
224 list_uri = e_mail_folder_uri_from_folder (folder);
225 else
226 list_uri = NULL;
227 tree_uri = em_folder_tree_get_selected_uri (folder_tree);
228
229 /* If the folder tree and message list disagree on the current
230 * folder, reset the folder tree to match the message list. */
231 if (list_uri && g_strcmp0 (tree_uri, list_uri) != 0)
232 em_folder_tree_set_selected (folder_tree, list_uri, FALSE);
233
234 g_free (list_uri);
235 g_free (tree_uri);
236
237 /* Disconnect from the "selection-done" signal. */
238 g_signal_handlers_disconnect_by_func (
239 menu, mail_shell_view_folder_tree_selection_done_cb,
240 mail_shell_view);
241 }
242
243 static void
244 mail_shell_view_folder_tree_popup_event_cb (EShellView *shell_view,
245 GdkEventButton *event)
246 {
247 GtkWidget *menu;
248 const gchar *widget_path;
249
250 widget_path = "/mail-folder-popup";
251 menu = e_shell_view_show_popup_menu (shell_view, widget_path, event);
252
253 g_signal_connect_object (
254 menu, "selection-done",
255 G_CALLBACK (mail_shell_view_folder_tree_selection_done_cb),
256 shell_view, G_CONNECT_SWAPPED);
257 }
258
259 #if !WEBKIT_CHECK_VERSION(1,10,0)
260 static WebKitDOMDocument *
261 find_dom_for_frame (WebKitDOMDocument *document,
262 const gchar *frame_name)
263 {
264 WebKitDOMNodeList *frames;
265 gulong ii, length;
266
267 g_return_val_if_fail (frame_name != NULL, NULL);
268
269 if (!WEBKIT_DOM_IS_DOCUMENT (document))
270 return NULL;
271
272 frames = webkit_dom_document_get_elements_by_tag_name (
273 document, "iframe");
274 length = webkit_dom_node_list_get_length (frames);
275 for (ii = 0; ii < length; ii++) {
276 WebKitDOMHTMLIFrameElement *iframe;
277 WebKitDOMDocument *frame_doc;
278 gchar *name;
279
280 iframe = WEBKIT_DOM_HTML_IFRAME_ELEMENT (
281 webkit_dom_node_list_item (frames, ii));
282
283 frame_doc = webkit_dom_html_iframe_element_get_content_document (iframe);
284 name = webkit_dom_html_iframe_element_get_name (iframe);
285
286 if (g_strcmp0 (name, frame_name) == 0) {
287 g_free (name);
288 return frame_doc;
289 }
290
291 g_free (name);
292
293 frame_doc = find_dom_for_frame (frame_doc, frame_name);
294 if (frame_doc)
295 return frame_doc;
296 }
297
298 return NULL;
299 }
300 #endif
301
302 static gboolean
303 mail_shell_view_mail_display_needs_key (EMailDisplay *mail_display,
304 gboolean with_input)
305 {
306 gboolean needs_key = FALSE;
307
308 if (gtk_widget_has_focus (GTK_WIDGET (mail_display))) {
309 WebKitWebFrame *frame;
310 WebKitDOMDocument *dom;
311 WebKitDOMElement *element;
312 gchar *name = NULL;
313
314 frame = webkit_web_view_get_focused_frame (WEBKIT_WEB_VIEW (mail_display));
315 #if WEBKIT_CHECK_VERSION(1,10,0)
316 dom = webkit_web_frame_get_dom_document (frame);
317 #else
318 dom = find_dom_for_frame (
319 webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (mail_display)),
320 webkit_web_frame_get_name (frame));
321 #endif
322 /* intentionally used "static_cast" */
323 element = webkit_dom_html_document_get_active_element ((WebKitDOMHTMLDocument *) dom);
324
325 if (element)
326 name = webkit_dom_node_get_node_name (WEBKIT_DOM_NODE (element));
327
328 /* if INPUT or TEXTAREA has focus, then any key press should go there */
329 if (name && ((with_input && g_ascii_strcasecmp (name, "INPUT") == 0) || g_ascii_strcasecmp (name, "TEXTAREA") == 0)) {
330 needs_key = TRUE;
331 }
332
333 g_free (name);
334 }
335
336 return needs_key;
337 }
338
339 static gboolean
340 mail_shell_view_key_press_event_cb (EMailShellView *mail_shell_view,
341 GdkEventKey *event)
342 {
343 EShellView *shell_view;
344 EShellWindow *shell_window;
345 EShellContent *shell_content;
346 EMailView *mail_view;
347 EMailReader *reader;
348 EMailDisplay *mail_display;
349 GtkAction *action;
350
351 shell_view = E_SHELL_VIEW (mail_shell_view);
352 shell_window = e_shell_view_get_shell_window (shell_view);
353
354 if ((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)) != 0)
355 return FALSE;
356
357 shell_content = e_shell_view_get_shell_content (shell_view);
358 mail_view = e_mail_shell_content_get_mail_view (E_MAIL_SHELL_CONTENT (shell_content));
359 reader = E_MAIL_READER (mail_view);
360 mail_display = e_mail_reader_get_mail_display (reader);
361
362 switch (event->keyval) {
363 case GDK_KEY_space:
364 action = ACTION (MAIL_SMART_FORWARD);
365 break;
366
367 case GDK_KEY_BackSpace:
368 action = ACTION (MAIL_SMART_BACKWARD);
369 break;
370
371 case GDK_KEY_Home:
372 case GDK_KEY_Left:
373 case GDK_KEY_Up:
374 case GDK_KEY_Right:
375 case GDK_KEY_Down:
376 case GDK_KEY_Prior:
377 case GDK_KEY_Next:
378 case GDK_KEY_End:
379 case GDK_KEY_Begin:
380 if (!mail_shell_view_mail_display_needs_key (mail_display, FALSE) &&
381 webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (mail_display)) !=
382 webkit_web_view_get_focused_frame (WEBKIT_WEB_VIEW (mail_display))) {
383 WebKitDOMDocument *document;
384 WebKitDOMDOMWindow *window;
385
386 document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (mail_display));
387 window = webkit_dom_document_get_default_view (document);
388
389 /* Workaround WebKit bug for key navigation, when inner IFRAME is focused.
390 * EMailView's inner IFRAMEs have disabled scrolling, but WebKit doesn't post
391 * key navigation events to parent's frame, thus the view doesn't scroll.
392 * This is a poor workaround for this issue, the main frame is focused,
393 * which has scrolling enabled.
394 */
395 webkit_dom_dom_window_focus (window);
396 }
397
398 return FALSE;
399 default:
400 return FALSE;
401 }
402
403 if (mail_shell_view_mail_display_needs_key (mail_display, TRUE))
404 return FALSE;
405
406 gtk_action_activate (action);
407
408 return TRUE;
409 }
410
411 static gboolean
412 mail_shell_view_message_list_key_press_cb (EMailShellView *mail_shell_view,
413 gint row,
414 ETreePath path,
415 gint col,
416 GdkEvent *event)
417 {
418 return mail_shell_view_key_press_event_cb (
419 mail_shell_view, &event->key);
420 }
421
422 static gboolean
423 mail_shell_view_message_list_popup_menu_cb (EShellView *shell_view)
424 {
425 const gchar *widget_path;
426
427 widget_path = "/mail-message-popup";
428 e_shell_view_show_popup_menu (shell_view, widget_path, NULL);
429
430 return TRUE;
431 }
432
433 static gboolean
434 mail_shell_view_message_list_right_click_cb (EShellView *shell_view,
435 gint row,
436 ETreePath path,
437 gint col,
438 GdkEventButton *event)
439 {
440 const gchar *widget_path;
441
442 widget_path = "/mail-message-popup";
443 e_shell_view_show_popup_menu (shell_view, widget_path, event);
444
445 return TRUE;
446 }
447
448 static gboolean
449 mail_shell_view_popup_event_cb (EMailShellView *mail_shell_view,
450 GdkEventButton *event,
451 const gchar *uri)
452 {
453 EMailShellContent *mail_shell_content;
454 EMailDisplay *display;
455 EShellView *shell_view;
456 EMailReader *reader;
457 EMailView *mail_view;
458 GtkMenu *menu;
459
460 if (uri != NULL)
461 return FALSE;
462
463 mail_shell_content = mail_shell_view->priv->mail_shell_content;
464 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
465
466 reader = E_MAIL_READER (mail_view);
467 display = e_mail_reader_get_mail_display (reader);
468
469 if (e_web_view_get_cursor_image (E_WEB_VIEW (display)) != NULL)
470 return FALSE;
471
472 menu = e_mail_reader_get_popup_menu (reader);
473 shell_view = E_SHELL_VIEW (mail_shell_view);
474 e_shell_view_update_actions (shell_view);
475
476 if (event == NULL)
477 gtk_menu_popup (
478 menu, NULL, NULL, NULL, NULL,
479 0, gtk_get_current_event_time ());
480 else
481 gtk_menu_popup (
482 menu, NULL, NULL, NULL, NULL,
483 event->button, event->time);
484
485 return TRUE;
486 }
487
488 static void
489 mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view,
490 EMailReader *reader)
491 {
492 GtkWidget *message_list;
493 EMailDisplay *display;
494 EShellView *shell_view;
495 EShellTaskbar *shell_taskbar;
496
497 shell_view = E_SHELL_VIEW (mail_shell_view);
498 shell_taskbar = e_shell_view_get_shell_taskbar (shell_view);
499
500 display = e_mail_reader_get_mail_display (reader);
501 message_list = e_mail_reader_get_message_list (reader);
502
503 e_shell_view_update_actions (E_SHELL_VIEW (mail_shell_view));
504 e_mail_shell_view_update_sidebar (mail_shell_view);
505
506 /* Connect if its not connected already */
507 if (g_signal_handler_find (
508 message_list, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
509 mail_shell_view_message_list_key_press_cb, NULL))
510 return;
511
512 g_signal_connect_object (
513 message_list, "key-press",
514 G_CALLBACK (mail_shell_view_message_list_key_press_cb),
515 mail_shell_view, G_CONNECT_SWAPPED);
516
517 g_signal_connect_object (
518 message_list, "popup-menu",
519 G_CALLBACK (mail_shell_view_message_list_popup_menu_cb),
520 mail_shell_view, G_CONNECT_SWAPPED);
521
522 g_signal_connect_object (
523 message_list, "right-click",
524 G_CALLBACK (mail_shell_view_message_list_right_click_cb),
525 mail_shell_view, G_CONNECT_SWAPPED);
526
527 g_signal_connect_object (
528 display, "key-press-event",
529 G_CALLBACK (mail_shell_view_key_press_event_cb),
530 mail_shell_view, G_CONNECT_SWAPPED);
531
532 g_signal_connect_object (
533 display, "popup-event",
534 G_CALLBACK (mail_shell_view_popup_event_cb),
535 mail_shell_view, G_CONNECT_SWAPPED);
536
537 g_signal_connect_object (
538 display, "status-message",
539 G_CALLBACK (e_shell_taskbar_set_message),
540 shell_taskbar, G_CONNECT_SWAPPED);
541 }
542
543 static void
544 mail_shell_view_reader_update_actions_cb (EMailReader *reader,
545 guint32 state,
546 EMailShellView *mail_shell_view)
547 {
548 EMailShellContent *mail_shell_content;
549
550 g_return_if_fail (mail_shell_view != NULL);
551 g_return_if_fail (mail_shell_view->priv != NULL);
552
553 mail_shell_content = mail_shell_view->priv->mail_shell_content;
554 e_mail_reader_update_actions (E_MAIL_READER (mail_shell_content), state);
555 }
556
557 static void
558 mail_shell_view_prepare_for_quit_done_cb (CamelFolder *folder,
559 gpointer user_data)
560 {
561 g_object_unref (E_ACTIVITY (user_data));
562 }
563
564 static void
565 mail_shell_view_prepare_for_quit_cb (EMailShellView *mail_shell_view,
566 EActivity *activity)
567 {
568 EMailShellContent *mail_shell_content;
569 CamelFolder *folder;
570 EMailReader *reader;
571 EMailView *mail_view;
572 GtkWidget *message_list;
573
574 /* If we got here, it means the application is shutting down
575 * and this is the last EMailShellView instance. Synchronize
576 * the currently selected folder before we terminate. */
577
578 mail_shell_content = mail_shell_view->priv->mail_shell_content;
579 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
580
581 reader = E_MAIL_READER (mail_view);
582 folder = e_mail_reader_get_folder (reader);
583 message_list = e_mail_reader_get_message_list (reader);
584
585 message_list_save_state (MESSAGE_LIST (message_list));
586
587 if (folder == NULL)
588 return;
589
590 mail_sync_folder (
591 folder,
592 mail_shell_view_prepare_for_quit_done_cb,
593 g_object_ref (activity));
594 }
595
596 static void
597 mail_shell_view_load_view_collection (EShellViewClass *shell_view_class)
598 {
599 GalViewCollection *collection;
600 GalViewFactory *factory;
601 ETableSpecification *spec;
602 const gchar *base_dir;
603 gchar *filename;
604
605 collection = shell_view_class->view_collection;
606
607 base_dir = EVOLUTION_ETSPECDIR;
608 spec = e_table_specification_new ();
609 filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL);
610 if (!e_table_specification_load_from_file (spec, filename))
611 g_critical (
612 "Unable to load ETable specification file "
613 "for mail");
614 g_free (filename);
615
616 factory = gal_view_factory_etable_new (spec);
617 gal_view_collection_add_factory (collection, factory);
618 g_object_unref (factory);
619 g_object_unref (spec);
620
621 gal_view_collection_load (collection);
622 }
623
624 static void
625 mail_shell_view_notify_view_id_cb (EMailShellView *mail_shell_view)
626 {
627 EMailShellContent *mail_shell_content;
628 GalViewInstance *view_instance;
629 EMailView *mail_view;
630 const gchar *view_id;
631
632 mail_shell_content = mail_shell_view->priv->mail_shell_content;
633 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
634
635 view_instance = e_mail_view_get_view_instance (mail_view);
636 view_id = e_shell_view_get_view_id (E_SHELL_VIEW (mail_shell_view));
637
638 /* A NULL view ID implies we're in a custom view. But you can
639 * only get to a custom view via the "Define Views" dialog, which
640 * would have already modified the view instance appropriately.
641 * Furthermore, there's no way to refer to a custom view by ID
642 * anyway, since custom views have no IDs. */
643 if (view_id == NULL)
644 return;
645
646 gal_view_instance_set_current_view_id (view_instance, view_id);
647 }
648
649 static void
650 mail_shell_view_search_filter_changed_cb (EMailShellView *mail_shell_view)
651 {
652 EMailShellContent *mail_shell_content;
653 EMailView *mail_view;
654
655 g_return_if_fail (mail_shell_view != NULL);
656 g_return_if_fail (mail_shell_view->priv != NULL);
657
658 if (e_shell_view_is_execute_search_blocked (E_SHELL_VIEW (mail_shell_view)))
659 return;
660
661 mail_shell_content = mail_shell_view->priv->mail_shell_content;
662 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
663
664 e_mail_reader_avoid_next_mark_as_seen (E_MAIL_READER (mail_view));
665 }
666
667 void
668 e_mail_shell_view_private_init (EMailShellView *mail_shell_view,
669 EShellViewClass *shell_view_class)
670 {
671 if (!gal_view_collection_loaded (shell_view_class->view_collection))
672 mail_shell_view_load_view_collection (shell_view_class);
673
674 g_signal_connect (
675 mail_shell_view, "notify::view-id",
676 G_CALLBACK (mail_shell_view_notify_view_id_cb), NULL);
677 }
678
679 void
680 e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view)
681 {
682 EMailShellViewPrivate *priv = mail_shell_view->priv;
683 EMailShellContent *mail_shell_content;
684 EMailShellSidebar *mail_shell_sidebar;
685 EShell *shell;
686 EShellView *shell_view;
687 EShellBackend *shell_backend;
688 EShellContent *shell_content;
689 EShellSidebar *shell_sidebar;
690 EShellTaskbar *shell_taskbar;
691 EShellWindow *shell_window;
692 EShellSearchbar *searchbar;
693 EMFolderTree *folder_tree;
694 EActionComboBox *combo_box;
695 ERuleContext *context;
696 EFilterRule *rule = NULL;
697 GtkTreeSelection *selection;
698 GtkUIManager *ui_manager;
699 GtkWidget *message_list;
700 EMailLabelListStore *label_store;
701 EMailBackend *backend;
702 EMailSession *session;
703 EMailReader *reader;
704 EMailView *mail_view;
705 EMailDisplay *display;
706 const gchar *source;
707 guint merge_id;
708 gint ii = 0;
709
710 shell_view = E_SHELL_VIEW (mail_shell_view);
711 shell_backend = e_shell_view_get_shell_backend (shell_view);
712 shell_content = e_shell_view_get_shell_content (shell_view);
713 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
714 shell_taskbar = e_shell_view_get_shell_taskbar (shell_view);
715 shell_window = e_shell_view_get_shell_window (shell_view);
716
717 ui_manager = e_shell_window_get_ui_manager (shell_window);
718
719 shell = e_shell_window_get_shell (shell_window);
720
721 backend = E_MAIL_BACKEND (shell_backend);
722 session = e_mail_backend_get_session (backend);
723 label_store = e_mail_ui_session_get_label_store (
724 E_MAIL_UI_SESSION (session));
725
726 e_shell_window_add_action_group (shell_window, "mail");
727 e_shell_window_add_action_group (shell_window, "mail-filter");
728 e_shell_window_add_action_group (shell_window, "mail-label");
729 e_shell_window_add_action_group (shell_window, "search-folders");
730
731 merge_id = gtk_ui_manager_new_merge_id (ui_manager);
732 priv->label_merge_id = merge_id;
733
734 /* Cache these to avoid lots of awkward casting. */
735 priv->mail_shell_backend = g_object_ref (shell_backend);
736 priv->mail_shell_content = g_object_ref (shell_content);
737 priv->mail_shell_sidebar = g_object_ref (shell_sidebar);
738
739 mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar);
740 folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
741 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_tree));
742
743 mail_shell_content = E_MAIL_SHELL_CONTENT (shell_content);
744 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
745 searchbar = e_mail_shell_content_get_searchbar (mail_shell_content);
746 combo_box = e_shell_searchbar_get_scope_combo_box (searchbar);
747
748 reader = E_MAIL_READER (shell_content);
749 display = e_mail_reader_get_mail_display (reader);
750 message_list = e_mail_reader_get_message_list (reader);
751
752 em_folder_tree_set_selectable_widget (folder_tree, message_list);
753
754 /* The folder tree and scope combo box are both insensitive
755 * when searching beyond the currently selected folder. */
756 g_object_bind_property (
757 folder_tree, "sensitive",
758 combo_box, "sensitive",
759 G_BINDING_BIDIRECTIONAL |
760 G_BINDING_SYNC_CREATE);
761
762 combo_box = e_shell_searchbar_get_filter_combo_box (searchbar);
763 g_signal_connect_object (
764 combo_box, "changed",
765 G_CALLBACK (mail_shell_view_search_filter_changed_cb),
766 mail_shell_view, G_CONNECT_SWAPPED);
767
768 g_signal_connect_object (
769 folder_tree, "folder-selected",
770 G_CALLBACK (mail_shell_view_folder_tree_selected_cb),
771 mail_shell_view, G_CONNECT_SWAPPED);
772
773 g_signal_connect_object (
774 folder_tree, "key-press-event",
775 G_CALLBACK (mail_shell_view_folder_tree_key_press_event_cb),
776 mail_shell_view, G_CONNECT_SWAPPED);
777
778 g_signal_connect_object (
779 folder_tree, "popup-event",
780 G_CALLBACK (mail_shell_view_folder_tree_popup_event_cb),
781 mail_shell_view, G_CONNECT_SWAPPED);
782
783 g_signal_connect_object (
784 message_list, "key-press",
785 G_CALLBACK (mail_shell_view_message_list_key_press_cb),
786 mail_shell_view, G_CONNECT_SWAPPED);
787
788 g_signal_connect_object (
789 message_list, "popup-menu",
790 G_CALLBACK (mail_shell_view_message_list_popup_menu_cb),
791 mail_shell_view, G_CONNECT_SWAPPED);
792
793 g_signal_connect_object (
794 message_list, "right-click",
795 G_CALLBACK (mail_shell_view_message_list_right_click_cb),
796 mail_shell_view, G_CONNECT_SWAPPED);
797
798 g_signal_connect_object (
799 reader, "changed",
800 G_CALLBACK (mail_shell_view_reader_changed_cb),
801 mail_shell_view, G_CONNECT_SWAPPED);
802
803 g_signal_connect_object (
804 mail_view, "update-actions",
805 G_CALLBACK (mail_shell_view_reader_update_actions_cb),
806 mail_shell_view, 0);
807
808 g_signal_connect_object (
809 reader, "folder-loaded",
810 G_CALLBACK (e_mail_view_update_view_instance),
811 mail_view, G_CONNECT_SWAPPED);
812
813 /* Use the same callback as "changed". */
814 g_signal_connect_object (
815 reader, "folder-loaded",
816 G_CALLBACK (mail_shell_view_reader_changed_cb),
817 mail_shell_view, G_CONNECT_SWAPPED);
818
819 g_signal_connect_object (
820 reader, "folder-loaded",
821 G_CALLBACK (e_mail_shell_view_restore_state),
822 mail_shell_view, G_CONNECT_SWAPPED);
823
824 g_signal_connect_object (
825 label_store, "row-changed",
826 G_CALLBACK (e_mail_shell_view_update_search_filter),
827 mail_shell_view, G_CONNECT_SWAPPED);
828
829 g_signal_connect_object (
830 label_store, "row-deleted",
831 G_CALLBACK (e_mail_shell_view_update_search_filter),
832 mail_shell_view, G_CONNECT_SWAPPED);
833
834 g_signal_connect_object (
835 label_store, "row-inserted",
836 G_CALLBACK (e_mail_shell_view_update_search_filter),
837 mail_shell_view, G_CONNECT_SWAPPED);
838
839 g_signal_connect_object (
840 display, "key-press-event",
841 G_CALLBACK (mail_shell_view_key_press_event_cb),
842 mail_shell_view, G_CONNECT_SWAPPED);
843
844 g_signal_connect_object (
845 display, "popup-event",
846 G_CALLBACK (mail_shell_view_popup_event_cb),
847 mail_shell_view, G_CONNECT_SWAPPED);
848
849 g_signal_connect_object (
850 display, "status-message",
851 G_CALLBACK (e_shell_taskbar_set_message),
852 shell_taskbar, G_CONNECT_SWAPPED);
853
854 g_signal_connect_object (
855 mail_shell_view, "toggled",
856 G_CALLBACK (e_mail_shell_view_update_send_receive_menus),
857 mail_shell_view, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
858
859 /* Need to keep the handler ID so we can disconnect it in
860 * dispose(). The shell outlives us and we don't want it
861 * invoking callbacks on finalized shell views. */
862 priv->prepare_for_quit_handler_id =
863 g_signal_connect_object (
864 shell, "prepare-for-quit",
865 G_CALLBACK (mail_shell_view_prepare_for_quit_cb),
866 mail_shell_view, G_CONNECT_SWAPPED);
867
868 e_mail_reader_init (reader, TRUE, FALSE);
869 e_mail_shell_view_actions_init (mail_shell_view);
870 e_mail_shell_view_update_search_filter (mail_shell_view);
871
872 /* This binding must come after e_mail_reader_init(). */
873 g_object_bind_property (
874 shell_content, "group-by-threads",
875 mail_view, "group-by-threads",
876 G_BINDING_BIDIRECTIONAL |
877 G_BINDING_SYNC_CREATE);
878
879 /* Populate built-in rules for search entry popup menu.
880 * Keep the assertions, please. If the conditions aren't
881 * met we're going to crash anyway, just more mysteriously. */
882 context = E_SHELL_VIEW_GET_CLASS (shell_view)->search_context;
883 source = E_FILTER_SOURCE_DEMAND;
884 while ((rule = e_rule_context_next_rule (context, rule, source))) {
885 if (!rule->system)
886 continue;
887 g_assert (ii < MAIL_NUM_SEARCH_RULES);
888 priv->search_rules[ii++] = g_object_ref (rule);
889 }
890 g_assert (ii == MAIL_NUM_SEARCH_RULES);
891
892 /* Now that we're all set up, simulate selecting a folder. */
893 g_signal_emit_by_name (selection, "changed");
894 }
895
896 void
897 e_mail_shell_view_private_dispose (EMailShellView *mail_shell_view)
898 {
899 EMailShellViewPrivate *priv = mail_shell_view->priv;
900 gint ii;
901
902 /* XXX It's a little awkward to have to dig up the
903 * shell this late in the game. Should we just
904 * keep a direct reference to it? Not sure. */
905 if (priv->prepare_for_quit_handler_id > 0) {
906 EShellBackend *shell_backend;
907 EShell *shell;
908
909 shell_backend = E_SHELL_BACKEND (priv->mail_shell_backend);
910 shell = e_shell_backend_get_shell (shell_backend);
911
912 g_signal_handler_disconnect (
913 shell, priv->prepare_for_quit_handler_id);
914 priv->prepare_for_quit_handler_id = 0;
915 }
916
917 DISPOSE (priv->mail_shell_backend);
918 DISPOSE (priv->mail_shell_content);
919 DISPOSE (priv->mail_shell_sidebar);
920
921 for (ii = 0; ii < MAIL_NUM_SEARCH_RULES; ii++)
922 DISPOSE (priv->search_rules[ii]);
923
924 if (priv->opening_folder != NULL) {
925 g_cancellable_cancel (priv->opening_folder);
926 g_object_unref (priv->opening_folder);
927 priv->opening_folder = NULL;
928 }
929
930 if (priv->search_account_all != NULL) {
931 g_object_unref (priv->search_account_all);
932 priv->search_account_all = NULL;
933 }
934
935 if (priv->search_account_current != NULL) {
936 g_object_unref (priv->search_account_current);
937 priv->search_account_current = NULL;
938 }
939
940 if (priv->search_account_cancel != NULL) {
941 g_object_unref (priv->search_account_cancel);
942 priv->search_account_cancel = NULL;
943 }
944 }
945
946 void
947 e_mail_shell_view_private_finalize (EMailShellView *mail_shell_view)
948 {
949 /* XXX Nothing to do? */
950 }
951
952 void
953 e_mail_shell_view_restore_state (EMailShellView *mail_shell_view)
954 {
955 EMailShellContent *mail_shell_content;
956 EShellSearchbar *searchbar;
957 EMailReader *reader;
958 EMailView *mail_view;
959 CamelFolder *folder;
960 CamelVeeFolder *vee_folder;
961 const gchar *old_state_group;
962 gchar *folder_uri;
963 gchar *new_state_group;
964
965 /* XXX Move this to EMailShellContent. */
966
967 g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
968
969 mail_shell_content = mail_shell_view->priv->mail_shell_content;
970 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
971 searchbar = e_mail_shell_content_get_searchbar (mail_shell_content);
972
973 reader = E_MAIL_READER (mail_view);
974 folder = e_mail_reader_get_folder (reader);
975
976 if (folder == NULL) {
977 if (e_shell_searchbar_get_state_group (searchbar)) {
978 e_shell_searchbar_set_state_group (searchbar, NULL);
979 e_shell_searchbar_load_state (searchbar);
980 }
981 return;
982 }
983
984 /* Do not restore state if we're running a "Current Account"
985 * or "All Accounts" search, since we don't want the search
986 * criteria to be destroyed in those cases. */
987
988 vee_folder = mail_shell_view->priv->search_account_all;
989 if (vee_folder != NULL && folder == CAMEL_FOLDER (vee_folder))
990 return;
991
992 vee_folder = mail_shell_view->priv->search_account_current;
993 if (vee_folder != NULL && folder == CAMEL_FOLDER (vee_folder))
994 return;
995
996 folder_uri = e_mail_folder_uri_from_folder (folder);
997 new_state_group = g_strdup_printf ("Folder %s", folder_uri);
998 old_state_group = e_shell_searchbar_get_state_group (searchbar);
999 g_free (folder_uri);
1000
1001 /* Avoid loading search state unnecessarily. */
1002 if (g_strcmp0 (new_state_group, old_state_group) != 0) {
1003 e_shell_searchbar_set_state_group (searchbar, new_state_group);
1004 e_shell_searchbar_load_state (searchbar);
1005 }
1006
1007 g_free (new_state_group);
1008 }
1009
1010 void
1011 e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view)
1012 {
1013 EMailShellContent *mail_shell_content;
1014 EShellBackend *shell_backend;
1015 EShellSidebar *shell_sidebar;
1016 EShellView *shell_view;
1017 EShell *shell;
1018 EMailReader *reader;
1019 EMailView *mail_view;
1020 ESourceRegistry *registry;
1021 CamelStore *parent_store;
1022 CamelFolder *folder;
1023 GPtrArray *uids;
1024 GString *buffer;
1025 gboolean store_is_local;
1026 const gchar *display_name;
1027 const gchar *folder_name;
1028 const gchar *uid;
1029 gchar *title;
1030 guint32 num_deleted;
1031 guint32 num_junked;
1032 guint32 num_junked_not_deleted;
1033 guint32 num_unread;
1034 guint32 num_visible;
1035
1036 g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
1037
1038 mail_shell_content = mail_shell_view->priv->mail_shell_content;
1039 mail_view = e_mail_shell_content_get_mail_view (mail_shell_content);
1040
1041 shell_view = E_SHELL_VIEW (mail_shell_view);
1042 shell_backend = e_shell_view_get_shell_backend (shell_view);
1043 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
1044
1045 shell = e_shell_backend_get_shell (shell_backend);
1046 registry = e_shell_get_registry (shell);
1047
1048 reader = E_MAIL_READER (mail_view);
1049 folder = e_mail_reader_get_folder (reader);
1050
1051 /* If no folder is selected, reset the sidebar banners
1052 * to their default values and stop. */
1053 if (folder == NULL) {
1054 GtkAction *action;
1055 gchar *label;
1056
1057 action = e_shell_view_get_action (shell_view);
1058
1059 g_object_get (action, "label", &label, NULL);
1060 e_shell_sidebar_set_secondary_text (shell_sidebar, NULL);
1061 e_shell_view_set_title (shell_view, label);
1062 g_free (label);
1063
1064 return;
1065 }
1066
1067 folder_name = camel_folder_get_display_name (folder);
1068 parent_store = camel_folder_get_parent_store (folder);
1069
1070 num_deleted = camel_folder_summary_get_deleted_count (folder->summary);
1071 num_junked = camel_folder_summary_get_junk_count (folder->summary);
1072 num_junked_not_deleted =
1073 camel_folder_summary_get_junk_not_deleted_count (folder->summary);
1074 num_unread = camel_folder_summary_get_unread_count (folder->summary);
1075 num_visible = camel_folder_summary_get_visible_count (folder->summary);
1076
1077 buffer = g_string_sized_new (256);
1078 uids = e_mail_reader_get_selected_uids (reader);
1079
1080 if (uids->len > 1)
1081 g_string_append_printf (
1082 buffer, ngettext ("%d selected, ", "%d selected, ",
1083 uids->len), uids->len);
1084
1085 if (CAMEL_IS_VTRASH_FOLDER (folder)) {
1086 CamelVTrashFolder *trash_folder;
1087
1088 trash_folder = (CamelVTrashFolder *) folder;
1089
1090 /* "Trash" folder */
1091 if (trash_folder->type == CAMEL_VTRASH_FOLDER_TRASH)
1092 g_string_append_printf (
1093 buffer, ngettext ("%d deleted",
1094 "%d deleted", num_deleted), num_deleted);
1095
1096 /* "Junk" folder (hide deleted messages) */
1097 else if (e_mail_reader_get_hide_deleted (reader))
1098 g_string_append_printf (
1099 buffer, ngettext ("%d junk",
1100 "%d junk", num_junked_not_deleted),
1101 num_junked_not_deleted);
1102
1103 /* "Junk" folder (show deleted messages) */
1104 else
1105 g_string_append_printf (
1106 buffer, ngettext ("%d junk", "%d junk",
1107 num_junked), num_junked);
1108
1109 /* "Drafts" folder */
1110 } else if (em_utils_folder_is_drafts (registry, folder)) {
1111 g_string_append_printf (
1112 buffer, ngettext ("%d draft", "%d drafts",
1113 num_visible), num_visible);
1114
1115 /* "Outbox" folder */
1116 } else if (em_utils_folder_is_outbox (registry, folder)) {
1117 g_string_append_printf (
1118 buffer, ngettext ("%d unsent", "%d unsent",
1119 num_visible), num_visible);
1120
1121 /* "Sent" folder */
1122 } else if (em_utils_folder_is_sent (registry, folder)) {
1123 g_string_append_printf (
1124 buffer, ngettext ("%d sent", "%d sent",
1125 num_visible), num_visible);
1126
1127 /* Normal folder */
1128 } else {
1129 if (!e_mail_reader_get_hide_deleted (reader))
1130 num_visible +=
1131 num_deleted - num_junked +
1132 num_junked_not_deleted;
1133
1134 if (num_unread > 0 && uids->len <= 1)
1135 g_string_append_printf (
1136 buffer, ngettext ("%d unread, ",
1137 "%d unread, ", num_unread), num_unread);
1138 g_string_append_printf (
1139 buffer, ngettext ("%d total", "%d total",
1140 num_visible), num_visible);
1141 }
1142
1143 em_utils_uids_free (uids);
1144
1145 uid = camel_service_get_uid (CAMEL_SERVICE (parent_store));
1146 store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0);
1147
1148 /* Choose a suitable folder name for displaying. */
1149 display_name = folder_name;
1150 if (store_is_local) {
1151 if (strcmp (folder_name, "Drafts") == 0)
1152 display_name = _("Drafts");
1153 else if (strcmp (folder_name, "Inbox") == 0)
1154 display_name = _("Inbox");
1155 else if (strcmp (folder_name, "Outbox") == 0)
1156 display_name = _("Outbox");
1157 else if (strcmp (folder_name, "Sent") == 0)
1158 display_name = _("Sent");
1159 else if (strcmp (folder_name, "Templates") == 0)
1160 display_name = _("Templates");
1161 else if (strcmp (folder_name, "Trash") == 0)
1162 display_name = _("Trash");
1163 }
1164 if (strcmp (folder_name, "INBOX") == 0)
1165 display_name = _("Inbox");
1166
1167 title = g_strdup_printf ("%s (%s)", display_name, buffer->str);
1168 e_shell_sidebar_set_secondary_text (shell_sidebar, buffer->str);
1169 e_shell_view_set_title (shell_view, title);
1170 g_free (title);
1171
1172 g_string_free (buffer, TRUE);
1173 }
1174
1175 typedef struct {
1176 GtkMenuShell *menu;
1177 CamelSession *session;
1178 EMailAccountStore *account_store;
1179
1180 /* GtkMenuItem -> CamelService */
1181 GHashTable *menu_items;
1182
1183 /* Signal handlers */
1184 gulong service_added_id;
1185 gulong service_removed_id;
1186 gulong service_enabled_id;
1187 gulong service_disabled_id;
1188 } SendReceiveData;
1189
1190 static gboolean
1191 send_receive_can_use_service (EMailAccountStore *account_store,
1192 CamelService *service,
1193 GtkTreeIter *piter)
1194 {
1195 GtkTreeModel *model;
1196 GtkTreeIter iter;
1197 gboolean found = FALSE, enabled = FALSE, builtin = TRUE;
1198
1199 if (!CAMEL_IS_STORE (service))
1200 return FALSE;
1201
1202 model = GTK_TREE_MODEL (account_store);
1203
1204 if (piter) {
1205 found = TRUE;
1206 iter = *piter;
1207 } else if (gtk_tree_model_get_iter_first (model, &iter)) {
1208 CamelService *adept;
1209
1210 do {
1211 adept = NULL;
1212
1213 gtk_tree_model_get (
1214 model, &iter,
1215 E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, &adept,
1216 -1);
1217
1218 if (service == adept) {
1219 found = TRUE;
1220 g_object_unref (adept);
1221 break;
1222 }
1223
1224 if (adept)
1225 g_object_unref (adept);
1226 } while (gtk_tree_model_iter_next (model, &iter));
1227 }
1228
1229 if (!found)
1230 return FALSE;
1231
1232 gtk_tree_model_get (
1233 model, &iter,
1234 E_MAIL_ACCOUNT_STORE_COLUMN_ENABLED, &enabled,
1235 E_MAIL_ACCOUNT_STORE_COLUMN_BUILTIN, &builtin,
1236 -1);
1237
1238 return enabled && !builtin;
1239 }
1240
1241 static GtkMenuItem *
1242 send_receive_find_menu_item (SendReceiveData *data,
1243 gpointer service)
1244 {
1245 GHashTableIter iter;
1246 gpointer menu_item;
1247 gpointer candidate;
1248
1249 g_hash_table_iter_init (&iter, data->menu_items);
1250
1251 while (g_hash_table_iter_next (&iter, &menu_item, &candidate))
1252 if (service == candidate)
1253 return GTK_MENU_ITEM (menu_item);
1254
1255 return NULL;
1256 }
1257
1258 static void
1259 send_receive_account_item_activate_cb (GtkMenuItem *menu_item,
1260 SendReceiveData *data)
1261 {
1262 CamelService *service;
1263
1264 service = g_hash_table_lookup (data->menu_items, menu_item);
1265 g_return_if_fail (CAMEL_IS_SERVICE (service));
1266
1267 mail_receive_service (service);
1268 }
1269
1270 static void
1271 send_receive_add_to_menu (SendReceiveData *data,
1272 CamelService *service,
1273 gint position)
1274 {
1275 GtkWidget *menu_item;
1276
1277 if (send_receive_find_menu_item (data, service) != NULL)
1278 return;
1279
1280 menu_item = gtk_menu_item_new ();
1281 gtk_widget_show (menu_item);
1282
1283 g_object_bind_property (
1284 service, "display-name",
1285 menu_item, "label",
1286 G_BINDING_SYNC_CREATE);
1287
1288 g_hash_table_insert (
1289 data->menu_items, menu_item,
1290 g_object_ref (service));
1291
1292 g_signal_connect (
1293 menu_item, "activate",
1294 G_CALLBACK (send_receive_account_item_activate_cb), data);
1295
1296 /* Position is with respect to the sorted list of CamelService-s,
1297 * not menu item position. */
1298 if (position < 0)
1299 gtk_menu_shell_append (data->menu, menu_item);
1300 else
1301 gtk_menu_shell_insert (data->menu, menu_item, position + 4);
1302 }
1303
1304 static void
1305 send_receive_gather_services (gpointer menu_item,
1306 gpointer service,
1307 gpointer queue)
1308 {
1309 g_queue_push_head (queue, service);
1310 }
1311
1312 static gint
1313 sort_services_cb (gconstpointer service1,
1314 gconstpointer service2,
1315 gpointer account_store)
1316 {
1317 return e_mail_account_store_compare_services (account_store, CAMEL_SERVICE (service1), CAMEL_SERVICE (service2));
1318 }
1319
1320 static void
1321 send_receive_menu_service_added_cb (EMailAccountStore *account_store,
1322 CamelService *service,
1323 SendReceiveData *data)
1324 {
1325 GQueue *services;
1326
1327 if (!send_receive_can_use_service (account_store, service, NULL))
1328 return;
1329
1330 services = g_queue_new ();
1331
1332 g_queue_push_head (services, service);
1333 g_hash_table_foreach (data->menu_items, send_receive_gather_services, services);
1334 g_queue_sort (services, sort_services_cb, account_store);
1335
1336 send_receive_add_to_menu (data, service, g_queue_index (services, service));
1337
1338 g_queue_free (services);
1339 }
1340
1341 static void
1342 send_receive_menu_service_removed_cb (EMailAccountStore *account_store,
1343 CamelService *service,
1344 SendReceiveData *data)
1345 {
1346 GtkMenuItem *menu_item;
1347
1348 menu_item = send_receive_find_menu_item (data, service);
1349 if (menu_item == NULL)
1350 return;
1351
1352 g_hash_table_remove (data->menu_items, menu_item);
1353
1354 gtk_container_remove (
1355 GTK_CONTAINER (data->menu),
1356 GTK_WIDGET (menu_item));
1357 }
1358
1359 static void
1360 send_receive_data_free (SendReceiveData *data)
1361 {
1362 g_signal_handler_disconnect (data->account_store, data->service_added_id);
1363 g_signal_handler_disconnect (data->account_store, data->service_removed_id);
1364 g_signal_handler_disconnect (data->account_store, data->service_enabled_id);
1365 g_signal_handler_disconnect (data->account_store, data->service_disabled_id);
1366
1367 g_object_unref (data->session);
1368 g_object_unref (data->account_store);
1369
1370 g_hash_table_destroy (data->menu_items);
1371
1372 g_slice_free (SendReceiveData, data);
1373 }
1374
1375 static SendReceiveData *
1376 send_receive_data_new (EMailShellView *mail_shell_view,
1377 GtkWidget *menu)
1378 {
1379 SendReceiveData *data;
1380 EShellView *shell_view;
1381 EShellBackend *shell_backend;
1382 EMailAccountStore *account_store;
1383 EMailBackend *backend;
1384 EMailSession *session;
1385
1386 shell_view = E_SHELL_VIEW (mail_shell_view);
1387 shell_backend = e_shell_view_get_shell_backend (shell_view);
1388
1389 backend = E_MAIL_BACKEND (shell_backend);
1390 session = e_mail_backend_get_session (backend);
1391 account_store = e_mail_ui_session_get_account_store (
1392 E_MAIL_UI_SESSION (session));
1393
1394 data = g_slice_new0 (SendReceiveData);
1395 data->menu = GTK_MENU_SHELL (menu); /* do not reference */
1396 data->session = g_object_ref (session);
1397 data->account_store = g_object_ref (account_store);
1398
1399 data->menu_items = g_hash_table_new_full (
1400 (GHashFunc) g_direct_hash,
1401 (GEqualFunc) g_direct_equal,
1402 (GDestroyNotify) NULL,
1403 (GDestroyNotify) g_object_unref);
1404
1405 data->service_added_id = g_signal_connect (
1406 account_store, "service-added",
1407 G_CALLBACK (send_receive_menu_service_added_cb), data);
1408 data->service_removed_id = g_signal_connect (
1409 account_store, "service-removed",
1410 G_CALLBACK (send_receive_menu_service_removed_cb), data);
1411 data->service_enabled_id = g_signal_connect (
1412 account_store, "service-enabled",
1413 G_CALLBACK (send_receive_menu_service_added_cb), data);
1414 data->service_disabled_id = g_signal_connect (
1415 account_store, "service-disabled",
1416 G_CALLBACK (send_receive_menu_service_removed_cb), data);
1417
1418 g_object_weak_ref (
1419 G_OBJECT (menu), (GWeakNotify)
1420 send_receive_data_free, data);
1421
1422 return data;
1423 }
1424
1425 static GtkWidget *
1426 create_send_receive_submenu (EMailShellView *mail_shell_view)
1427 {
1428 EShellView *shell_view;
1429 EShellWindow *shell_window;
1430 EShellBackend *shell_backend;
1431 EMailAccountStore *account_store;
1432 EMailBackend *backend;
1433 EMailSession *session;
1434 GtkWidget *menu;
1435 GtkAccelGroup *accel_group;
1436 GtkUIManager *ui_manager;
1437 GtkAction *action;
1438 GtkTreeModel *model;
1439 GtkTreeIter iter;
1440 SendReceiveData *data;
1441
1442 g_return_val_if_fail (mail_shell_view != NULL, NULL);
1443
1444 shell_view = E_SHELL_VIEW (mail_shell_view);
1445 shell_window = e_shell_view_get_shell_window (shell_view);
1446 shell_backend = e_shell_view_get_shell_backend (shell_view);
1447
1448 backend = E_MAIL_BACKEND (shell_backend);
1449 session = e_mail_backend_get_session (backend);
1450 account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session));
1451
1452 menu = gtk_menu_new ();
1453 ui_manager = e_shell_window_get_ui_manager (shell_window);
1454 accel_group = gtk_ui_manager_get_accel_group (ui_manager);
1455
1456 action = e_shell_window_get_action (shell_window, "mail-send-receive");
1457 gtk_action_set_accel_group (action, accel_group);
1458 gtk_menu_shell_append (
1459 GTK_MENU_SHELL (menu),
1460 gtk_action_create_menu_item (action));
1461
1462 action = e_shell_window_get_action (
1463 shell_window, "mail-send-receive-receive-all");
1464 gtk_action_set_accel_group (action, accel_group);
1465 gtk_menu_shell_append (
1466 GTK_MENU_SHELL (menu),
1467 gtk_action_create_menu_item (action));
1468
1469 action = e_shell_window_get_action (
1470 shell_window, "mail-send-receive-send-all");
1471 gtk_action_set_accel_group (action, accel_group);
1472 gtk_menu_shell_append (
1473 GTK_MENU_SHELL (menu),
1474 gtk_action_create_menu_item (action));
1475
1476 gtk_menu_shell_append (
1477 GTK_MENU_SHELL (menu),
1478 gtk_separator_menu_item_new ());
1479
1480 data = send_receive_data_new (mail_shell_view, menu);
1481
1482 model = GTK_TREE_MODEL (account_store);
1483 if (gtk_tree_model_get_iter_first (model, &iter)) {
1484 CamelService *service;
1485
1486 do {
1487 service = NULL;
1488
1489 gtk_tree_model_get (
1490 model, &iter,
1491 E_MAIL_ACCOUNT_STORE_COLUMN_SERVICE, &service,
1492 -1);
1493
1494 if (send_receive_can_use_service (account_store, service, &iter))
1495 send_receive_add_to_menu (data, service, -1);
1496
1497 if (service)
1498 g_object_unref (service);
1499 } while (gtk_tree_model_iter_next (model, &iter));
1500 }
1501
1502 gtk_widget_show_all (menu);
1503
1504 return menu;
1505 }
1506
1507 void
1508 e_mail_shell_view_update_send_receive_menus (EMailShellView *mail_shell_view)
1509 {
1510 EMailShellViewPrivate *priv;
1511 EShellWindow *shell_window;
1512 EShellView *shell_view;
1513 GtkWidget *widget;
1514 const gchar *widget_path;
1515
1516 g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view));
1517
1518 priv = E_MAIL_SHELL_VIEW_GET_PRIVATE (mail_shell_view);
1519
1520 shell_view = E_SHELL_VIEW (mail_shell_view);
1521 shell_window = e_shell_view_get_shell_window (shell_view);
1522
1523 if (!e_shell_view_is_active (shell_view)) {
1524 if (priv->send_receive_tool_item) {
1525 GtkWidget *toolbar;
1526
1527 toolbar = e_shell_window_get_managed_widget (
1528 shell_window, "/main-toolbar");
1529 g_return_if_fail (toolbar != NULL);
1530
1531 gtk_container_remove (
1532 GTK_CONTAINER (toolbar),
1533 GTK_WIDGET (priv->send_receive_tool_item));
1534 gtk_container_remove (
1535 GTK_CONTAINER (toolbar),
1536 GTK_WIDGET (priv->send_receive_tool_separator));
1537
1538 priv->send_receive_tool_item = NULL;
1539 priv->send_receive_tool_separator = NULL;
1540 }
1541
1542 return;
1543 }
1544
1545 widget_path =
1546 "/main-menu/file-menu"
1547 "/mail-send-receiver/mail-send-receive-submenu";
1548 widget = e_shell_window_get_managed_widget (shell_window, widget_path);
1549 if (widget != NULL)
1550 gtk_menu_item_set_submenu (
1551 GTK_MENU_ITEM (widget),
1552 create_send_receive_submenu (mail_shell_view));
1553
1554 if (!priv->send_receive_tool_item) {
1555 GtkWidget *toolbar;
1556 GtkToolItem *tool_item;
1557 gint index;
1558
1559 toolbar = e_shell_window_get_managed_widget (
1560 shell_window, "/main-toolbar");
1561 g_return_if_fail (toolbar != NULL);
1562
1563 widget_path =
1564 "/main-toolbar/toolbar-actions/mail-send-receiver";
1565 widget = e_shell_window_get_managed_widget (
1566 shell_window, widget_path);
1567 g_return_if_fail (widget != NULL);
1568
1569 index = gtk_toolbar_get_item_index (
1570 GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (widget));
1571
1572 tool_item = gtk_separator_tool_item_new ();
1573 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), tool_item, index);
1574 gtk_widget_show (GTK_WIDGET (tool_item));
1575 priv->send_receive_tool_separator = tool_item;
1576
1577 tool_item = GTK_TOOL_ITEM (
1578 e_menu_tool_button_new (_("Send / Receive")));
1579 gtk_tool_item_set_is_important (tool_item, TRUE);
1580 gtk_toolbar_insert (GTK_TOOLBAR (toolbar), tool_item, index);
1581 gtk_widget_show (GTK_WIDGET (tool_item));
1582 priv->send_receive_tool_item = tool_item;
1583
1584 g_object_bind_property (
1585 ACTION (MAIL_SEND_RECEIVE), "sensitive",
1586 tool_item, "sensitive",
1587 G_BINDING_SYNC_CREATE);
1588 }
1589
1590 if (priv->send_receive_tool_item)
1591 gtk_menu_tool_button_set_menu (
1592 GTK_MENU_TOOL_BUTTON (priv->send_receive_tool_item),
1593 create_send_receive_submenu (mail_shell_view));
1594 }