1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #endif /*HAVE_CONFIG_H*/
34 #include <glib/gi18n.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-msg.h>
38 #include <modest-tny-account.h>
39 #include <modest-address-book.h>
41 #include "modest-ui-actions.h"
43 #include "modest-tny-platform-factory.h"
44 #include "modest-platform.h"
46 #include <widgets/modest-main-window.h>
47 #include <widgets/modest-msg-view-window.h>
48 #include <widgets/modest-account-view-window.h>
49 #include <widgets/modest-msg-view-details-dialog.h>
51 #include "modest-account-mgr-helpers.h"
52 #include "modest-mail-operation.h"
54 #ifdef MODEST_HAVE_EASYSETUP
55 #include "easysetup/modest-easysetup-wizard.h"
56 #endif /*MODEST_HAVE_EASYSETUP*/
58 #include <modest-widget-memory.h>
59 #include <tny-error.h>
60 #include <tny-simple-list.h>
61 #include <tny-msg-view.h>
62 #include <tny-device.h>
65 typedef struct _GetMsgAsyncHelper {
72 typedef enum _ReplyForwardAction {
78 typedef struct _ReplyForwardHelper {
79 guint reply_forward_type;
80 ReplyForwardAction action;
85 static void reply_forward_func (gpointer data, gpointer user_data);
86 static void read_msg_func (gpointer data, gpointer user_data);
87 static void get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err,
89 static void reply_forward (ReplyForwardAction action, ModestWindow *win);
90 static void modest_ui_actions_message_details_cb (gpointer msg_data,
91 gpointer helper_data);
92 static gchar* ask_for_folder_name (GtkWindow *parent_window, const gchar *title);
96 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
99 const gchar *authors[] = {
100 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
103 about = gtk_about_dialog_new ();
104 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
105 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
106 gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
107 _("Copyright (c) 2006, Nokia Corporation\n"
108 "All rights reserved."));
109 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
110 _("a modest e-mail client\n\n"
111 "design and implementation: Dirk-Jan C. Binnema\n"
112 "contributions from the fine people at KernelConcepts and Igalia\n"
113 "uses the tinymail email framework written by Philip van Hoof"));
114 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
115 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
117 gtk_dialog_run (GTK_DIALOG (about));
118 gtk_widget_destroy(about);
123 get_selected_headers (ModestWindow *win)
125 if (MODEST_IS_MAIN_WINDOW(win)) {
126 GtkWidget *header_view;
128 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
129 MODEST_WIDGET_TYPE_HEADER_VIEW);
130 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
132 } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
133 /* for MsgViewWindows, we simply return a list with one element */
136 TnyList *list = NULL;
138 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
140 header = tny_msg_get_header (msg);
141 list = tny_simple_list_new ();
142 tny_list_prepend (list, G_OBJECT(header));
143 g_object_unref (G_OBJECT(header));
152 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
154 TnyList *header_list;
157 g_return_if_fail (MODEST_IS_WINDOW(win));
159 header_list = get_selected_headers (win);
162 iter = tny_list_create_iterator (header_list);
165 ModestMailOperation *mail_op;
167 header = TNY_HEADER (tny_iterator_get_current (iter));
168 /* TODO: thick grain mail operation involving
169 a list of objects. Composite pattern ??? */
170 /* TODO: add confirmation dialog */
171 mail_op = modest_mail_operation_new ();
172 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
175 /* Always delete. TODO: Move to trash still not supported */
176 modest_mail_operation_remove_msg (mail_op, header, FALSE);
179 g_object_unref (G_OBJECT (mail_op));
180 g_object_unref (G_OBJECT (header));
182 tny_iterator_next (iter);
184 } while (!tny_iterator_is_done (iter));
187 g_object_unref (G_OBJECT (iter));
190 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
191 gtk_widget_destroy (GTK_WIDGET(win));
197 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
199 /* FIXME: save size of main window */
200 /* save_sizes (main_window); */
201 /* gtk_widget_destroy (GTK_WIDGET (win)); */
206 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
208 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
209 gtk_widget_destroy (GTK_WIDGET (win));
210 } else if (MODEST_IS_WINDOW (win)) {
211 gtk_widget_destroy (GTK_WIDGET (win));
213 g_return_if_reached ();
218 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
220 GtkClipboard *clipboard = NULL;
221 gchar *selection = NULL;
223 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
224 selection = gtk_clipboard_wait_for_text (clipboard);
226 modest_address_book_add_address (selection);
231 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
233 GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr());
235 gboolean accounts_exist = account_names != NULL;
236 g_slist_free (account_names);
238 /* This is currently only implemented for Maemo,
239 * because it requires a providers preset file which is not publically available.
241 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
242 /* To test, while modest_account_mgr_account_names() is broken: accounts_exist = TRUE; */
243 if (!accounts_exist) {
244 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
245 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
246 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
247 gtk_dialog_run (GTK_DIALOG (wizard));
248 gtk_widget_destroy (GTK_WIDGET (wizard));
252 /* Show the list of accounts: */
253 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
254 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
255 gtk_dialog_run (account_win);
256 gtk_widget_destroy (GTK_WIDGET(account_win));
259 GtkWidget *dialog, *label;
261 /* Create the widgets */
263 dialog = gtk_dialog_new_with_buttons ("Message",
265 GTK_DIALOG_DESTROY_WITH_PARENT,
269 label = gtk_label_new ("Hello World!");
271 /* Ensure that the dialog box is destroyed when the user responds. */
273 g_signal_connect_swapped (dialog, "response",
274 G_CALLBACK (gtk_widget_destroy),
277 /* Add the label, and show everything we've added to the dialog. */
279 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
281 gtk_widget_show_all (dialog);
282 #endif /* MODEST_PLATFORM_MAEMO */
286 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
288 ModestWindow *msg_win;
290 TnyFolder *folder = NULL;
291 gchar *account_name = NULL;
292 gchar *from_str = NULL;
295 ModestWindowMgr *mgr;
297 account_name = g_strdup(modest_window_get_active_account (win));
299 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
301 account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
303 TNY_ACCOUNT_TYPE_STORE);
305 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
309 from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
311 msg = modest_tny_msg_new ("", from_str, "", "", "", "", NULL);
313 g_printerr ("modest: failed to create new msg\n");
317 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
319 g_printerr ("modest: failed to find Drafts folder\n");
323 tny_folder_add_msg (folder, msg, &err);
325 g_printerr ("modest: error adding msg to Drafts folder: %s",
331 /* Create and register edit window */
332 msg_win = modest_msg_edit_window_new (msg, account_name);
333 mgr = modest_runtime_get_window_mgr ();
334 modest_window_mgr_register_window (mgr, msg_win);
337 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
339 gtk_widget_show_all (GTK_WIDGET (msg_win));
342 g_free (account_name);
345 g_object_unref (G_OBJECT(account));
347 g_object_unref (G_OBJECT(msg));
349 g_object_unref (G_OBJECT(folder));
354 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
356 modest_runtime_not_implemented (GTK_WINDOW(win)); /* FIXME */
362 reply_forward_func (gpointer data, gpointer user_data)
364 TnyMsg *msg, *new_msg;
365 GetMsgAsyncHelper *helper;
366 ReplyForwardHelper *rf_helper;
367 ModestWindow *msg_win;
368 ModestEditType edit_type;
371 TnyFolder *folder = NULL;
372 TnyAccount *account = NULL;
373 ModestWindowMgr *mgr;
375 msg = TNY_MSG (data);
376 helper = (GetMsgAsyncHelper *) user_data;
377 rf_helper = (ReplyForwardHelper *) helper->user_data;
379 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
380 rf_helper->account_name);
381 /* Create reply mail */
382 switch (rf_helper->action) {
385 modest_tny_msg_create_reply_msg (msg, from,
386 rf_helper->reply_forward_type,
387 MODEST_TNY_MSG_REPLY_MODE_SENDER);
389 case ACTION_REPLY_TO_ALL:
391 modest_tny_msg_create_reply_msg (msg, from, rf_helper->reply_forward_type,
392 MODEST_TNY_MSG_REPLY_MODE_ALL);
393 edit_type = MODEST_EDIT_TYPE_REPLY;
397 modest_tny_msg_create_forward_msg (msg, from, rf_helper->reply_forward_type);
398 edit_type = MODEST_EDIT_TYPE_FORWARD;
401 g_return_if_reached ();
406 g_printerr ("modest: failed to create message\n");
410 account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
411 rf_helper->account_name,
412 TNY_ACCOUNT_TYPE_STORE);
414 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
418 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
420 g_printerr ("modest: failed to find Drafts folder\n");
424 tny_folder_add_msg (folder, msg, &err);
426 g_printerr ("modest: error adding msg to Drafts folder: %s",
432 /* Create and register the windows */
433 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
434 mgr = modest_runtime_get_window_mgr ();
435 modest_window_mgr_register_window (mgr, msg_win);
437 /* Show edit window */
438 gtk_widget_show_all (GTK_WIDGET (msg_win));
442 g_object_unref (G_OBJECT (new_msg));
444 g_object_unref (G_OBJECT (folder));
446 g_object_unref (G_OBJECT (account));
448 g_free (rf_helper->account_name);
449 g_slice_free (ReplyForwardHelper, rf_helper);
452 * Common code for the reply and forward actions
455 reply_forward (ReplyForwardAction action, ModestWindow *win)
457 TnyList *header_list;
458 guint reply_forward_type;
461 GetMsgAsyncHelper *helper;
462 ReplyForwardHelper *rf_helper;
464 g_return_if_fail (MODEST_IS_WINDOW(win));
466 header_list = get_selected_headers (win);
470 reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
471 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
473 /* We assume that we can only select messages of the
474 same folder and that we reply all of them from the
475 same account. In fact the interface currently only
476 allows single selection */
479 rf_helper = g_slice_new0 (ReplyForwardHelper);
480 rf_helper->reply_forward_type = reply_forward_type;
481 rf_helper->action = action;
483 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
484 if (!rf_helper->account_name)
485 rf_helper->account_name =
486 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
488 helper = g_slice_new0 (GetMsgAsyncHelper);
489 helper->window = win;
490 helper->func = reply_forward_func;
491 helper->iter = tny_list_create_iterator (header_list);
492 helper->user_data = rf_helper;
494 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
496 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
498 g_printerr ("modest: no message found\n");
501 reply_forward_func (msg, helper);
503 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
504 folder = tny_header_get_folder (header);
506 /* The callback will call it per each header */
507 tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
508 g_object_unref (G_OBJECT (folder));
510 g_printerr ("modest: no folder for header\n");
513 g_object_unref (G_OBJECT (header));
519 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
521 g_return_if_fail (MODEST_IS_WINDOW(win));
523 reply_forward (ACTION_REPLY, win);
527 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
529 g_return_if_fail (MODEST_IS_WINDOW(win));
531 reply_forward (ACTION_FORWARD, win);
535 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
537 g_return_if_fail (MODEST_IS_WINDOW(win));
539 reply_forward (ACTION_REPLY_TO_ALL, win);
543 modest_ui_actions_on_next (GtkAction *action,
544 ModestWindow *window)
546 if (MODEST_IS_MAIN_WINDOW (window)) {
547 GtkWidget *header_view;
549 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
550 MODEST_WIDGET_TYPE_HEADER_VIEW);
554 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view));
555 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
556 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
558 g_return_if_reached ();
563 modest_ui_actions_on_prev (GtkAction *action,
564 ModestWindow *window)
566 g_return_if_fail (MODEST_IS_WINDOW(window));
568 if (MODEST_IS_MAIN_WINDOW (window)) {
569 GtkWidget *header_view;
570 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
571 MODEST_WIDGET_TYPE_HEADER_VIEW);
575 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
576 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
577 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
579 g_return_if_reached ();
585 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
588 TnyAccount *tny_account;
589 ModestTnySendQueue *send_queue;
590 ModestMailOperation *mail_op;
593 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
595 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
597 g_printerr ("modest: cannot get account\n");
602 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
604 TNY_ACCOUNT_TYPE_TRANSPORT);
606 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
609 send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
611 g_object_unref (G_OBJECT(tny_account));
612 g_printerr ("modest: cannot get send queue for %s\n", account_name);
615 //modest_tny_send_queue_flush (send_queue);
617 g_object_unref (G_OBJECT(send_queue));
618 g_object_unref (G_OBJECT(tny_account));
621 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
623 TNY_ACCOUNT_TYPE_STORE);
625 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
629 /* Create the mail operation */
630 mail_op = modest_mail_operation_new ();
631 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
632 modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
635 g_object_unref (G_OBJECT (tny_account));
636 g_object_unref (G_OBJECT (mail_op));
642 modest_ui_actions_toggle_view (GtkAction *action, ModestMainWindow *main_window)
645 GtkWidget *header_view;
647 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
649 header_view = modest_main_window_get_child_widget (main_window,
650 MODEST_WIDGET_TYPE_HEADER_VIEW);
654 conf = modest_runtime_get_conf ();
656 /* what is saved/restored is depending on the style; thus; we save with
657 * old style, then update the style, and restore for this new style
659 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
661 if (modest_header_view_get_style
662 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
663 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
664 MODEST_HEADER_VIEW_STYLE_TWOLINES);
666 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
667 MODEST_HEADER_VIEW_STYLE_DETAILS);
669 modest_widget_memory_restore (conf, G_OBJECT(header_view),
676 * Marks a message as read and passes it to the msg preview widget
679 read_msg_func (gpointer data, gpointer user_data)
683 GetMsgAsyncHelper *helper;
684 TnyHeaderFlags header_flags;
685 GtkWidget *msg_preview;
687 msg = TNY_MSG (data);
688 helper = (GetMsgAsyncHelper *) user_data;
690 msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
691 MODEST_WIDGET_TYPE_MSG_PREVIEW);
695 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
696 header_flags = tny_header_get_flags (header);
697 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
698 g_object_unref (G_OBJECT (header));
700 /* Set message on msg view */
701 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
705 * This function is a generic handler for the tny_folder_get_msg_async
706 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
707 * contains a user provided function that is called inside this
708 * method. This will allow us to use this callback in many different
709 * places. This callback performs the common actions for the
710 * get_msg_async call, more specific actions will be done by the user
714 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
716 GetMsgAsyncHelper *helper;
718 helper = (GetMsgAsyncHelper *) user_data;
720 if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
721 modest_ui_actions_on_item_not_found (NULL,
722 MODEST_ITEM_TYPE_MESSAGE,
727 /* Call user function */
728 helper->func (msg, user_data);
730 /* Process next element (if exists) */
731 tny_iterator_next (helper->iter);
732 if (tny_iterator_is_done (helper->iter)) {
734 headers = tny_iterator_get_list (helper->iter);
736 g_object_unref (G_OBJECT (headers));
737 g_object_unref (G_OBJECT (helper->iter));
738 g_slice_free (GetMsgAsyncHelper, helper);
741 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
742 tny_folder_get_msg_async (folder, header,
744 g_object_unref (G_OBJECT(header));
749 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
751 ModestMainWindow *main_window)
753 GtkWidget *msg_preview;
755 GetMsgAsyncHelper *helper;
758 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
760 msg_preview = modest_main_window_get_child_widget(main_window,
761 MODEST_WIDGET_TYPE_MSG_PREVIEW);
765 /* when there's no header, clear the msgview */
767 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
771 folder = tny_header_get_folder (TNY_HEADER(header));
774 list = tny_simple_list_new ();
775 tny_list_prepend (list, G_OBJECT (header));
777 /* Fill helper data */
778 helper = g_slice_new0 (GetMsgAsyncHelper);
779 helper->window = MODEST_WINDOW (main_window);
780 helper->iter = tny_list_create_iterator (list);
781 helper->func = read_msg_func;
783 tny_folder_get_msg_async (TNY_FOLDER(folder),
788 g_object_unref (G_OBJECT (folder));
794 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
795 ModestMainWindow *main_window)
798 TnyFolder *folder = NULL;
800 gchar *account = NULL;
801 GtkTreeModel *model = NULL;
802 GtkTreeSelection *sel = NULL;
804 ModestWindowMgr *mgr;
806 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
811 folder = tny_header_get_folder (header);
813 g_printerr ("modest: cannot get folder for header\n");
817 /* FIXME: make async?; check error */
818 msg = tny_folder_get_msg (folder, header, NULL);
820 g_printerr ("modest: cannot get msg for header\n");
824 account = g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
826 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
828 /* Create and register message view window */
829 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
830 if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
831 win = modest_msg_view_window_new_with_header_model (msg, account, model, iter);
833 win = modest_msg_view_window_new (msg, account);
835 mgr = modest_runtime_get_window_mgr ();
836 modest_window_mgr_register_window (mgr, win);
838 gtk_window_set_transient_for (GTK_WINDOW (win),
839 GTK_WINDOW (main_window));
841 gtk_widget_show_all (GTK_WIDGET(win));
847 g_object_unref (G_OBJECT (folder));
849 g_object_unref (G_OBJECT (msg));
853 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
856 ModestMainWindow *main_window)
860 GtkWidget *header_view;
862 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
864 header_view = modest_main_window_get_child_widget(main_window,
865 MODEST_WIDGET_TYPE_HEADER_VIEW);
869 conf = modest_runtime_get_conf ();
871 if (!selected) { /* the folder was unselected; save it's settings */
872 modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
873 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
874 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
875 } else { /* the folder was selected */
876 if (folder) { /* folder may be NULL */
880 num = tny_folder_get_all_count (folder);
881 unread = tny_folder_get_unread_count (folder);
883 title = g_strdup_printf ("Modest: %s",
884 tny_folder_get_name (folder));
886 gtk_window_set_title (GTK_WINDOW(main_window), title);
889 txt = g_strdup_printf (_("%d %s, %d unread"),
890 num, num==1 ? _("item") : _("items"), unread);
891 //gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
894 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
895 modest_widget_memory_restore (conf, G_OBJECT(header_view),
901 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
908 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
910 if (g_main_depth > 0)
911 gdk_threads_enter ();
912 online = tny_device_is_online (modest_runtime_get_device());
915 /* already online -- the item is simply not there... */
916 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
920 _("The %s you selected cannot be found"),
922 gtk_dialog_run (GTK_DIALOG(dialog));
924 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
932 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
933 "Do you want to get online?"), item);
934 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
935 gtk_label_new (txt), FALSE, FALSE, 0);
936 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
939 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
940 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
941 // tny_device_force_online (modest_runtime_get_device());
944 gtk_widget_destroy (dialog);
945 if (g_main_depth > 0)
946 gdk_threads_leave ();
950 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
953 g_message ("%s %s", __FUNCTION__, link);
958 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
961 modest_platform_activate_uri (link);
965 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
968 modest_platform_show_uri_popup (link);
972 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
975 g_message (__FUNCTION__);
980 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
981 const gchar *address,
984 g_message ("%s %s", __FUNCTION__, address);
988 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
990 TnyTransportAccount *transport_account;
991 ModestMailOperation *mail_operation;
993 gchar *account_name, *from;
994 ModestAccountMgr *account_mgr;
996 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
998 data = modest_msg_edit_window_get_msg_data (edit_window);
1000 /* FIXME: Code added just for testing. The final version will
1001 use the send queue provided by tinymail and some
1003 account_mgr = modest_runtime_get_account_mgr();
1004 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1006 account_name = modest_account_mgr_get_default_account (account_mgr);
1007 if (!account_name) {
1008 g_printerr ("modest: no account found\n");
1009 modest_msg_edit_window_free_msg_data (edit_window, data);
1013 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1014 (modest_runtime_get_account_store(),
1016 TNY_ACCOUNT_TYPE_TRANSPORT));
1017 if (!transport_account) {
1018 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1019 g_free (account_name);
1020 modest_msg_edit_window_free_msg_data (edit_window, data);
1023 from = modest_account_mgr_get_from_string (account_mgr, account_name);
1025 /* Create the mail operation */
1026 mail_operation = modest_mail_operation_new ();
1027 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1029 modest_mail_operation_send_new_mail (mail_operation,
1041 g_free (account_name);
1042 g_object_unref (G_OBJECT (transport_account));
1043 g_object_unref (G_OBJECT (mail_operation));
1045 modest_msg_edit_window_free_msg_data (edit_window, data);
1047 /* Save settings and close the window */
1048 gtk_widget_destroy (GTK_WIDGET (edit_window));
1052 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1053 ModestMsgEditWindow *window)
1055 ModestMsgEditFormatState *format_state = NULL;
1057 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1058 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1060 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1063 format_state = modest_msg_edit_window_get_format_state (window);
1064 g_return_if_fail (format_state != NULL);
1066 format_state->bold = gtk_toggle_action_get_active (action);
1067 modest_msg_edit_window_set_format_state (window, format_state);
1068 g_free (format_state);
1073 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1074 ModestMsgEditWindow *window)
1076 ModestMsgEditFormatState *format_state = NULL;
1078 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1079 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1081 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1084 format_state = modest_msg_edit_window_get_format_state (window);
1085 g_return_if_fail (format_state != NULL);
1087 format_state->italics = gtk_toggle_action_get_active (action);
1088 modest_msg_edit_window_set_format_state (window, format_state);
1089 g_free (format_state);
1094 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1095 ModestMsgEditWindow *window)
1097 ModestMsgEditFormatState *format_state = NULL;
1099 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1100 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1102 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1105 format_state = modest_msg_edit_window_get_format_state (window);
1106 g_return_if_fail (format_state != NULL);
1108 format_state->bullet = gtk_toggle_action_get_active (action);
1109 modest_msg_edit_window_set_format_state (window, format_state);
1110 g_free (format_state);
1115 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1116 GtkRadioAction *selected,
1117 ModestMsgEditWindow *window)
1119 ModestMsgEditFormatState *format_state = NULL;
1120 GtkJustification value;
1122 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1124 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1127 value = gtk_radio_action_get_current_value (selected);
1129 format_state = modest_msg_edit_window_get_format_state (window);
1130 g_return_if_fail (format_state != NULL);
1132 format_state->justification = value;
1133 modest_msg_edit_window_set_format_state (window, format_state);
1134 g_free (format_state);
1138 modest_ui_actions_on_select_editor_color (GtkAction *action,
1139 ModestMsgEditWindow *window)
1141 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1142 g_return_if_fail (GTK_IS_ACTION (action));
1144 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1147 modest_msg_edit_window_select_color (window);
1151 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1152 ModestMsgEditWindow *window)
1154 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1155 g_return_if_fail (GTK_IS_ACTION (action));
1157 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1160 modest_msg_edit_window_select_background_color (window);
1164 modest_ui_actions_on_insert_image (GtkAction *action,
1165 ModestMsgEditWindow *window)
1167 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1168 g_return_if_fail (GTK_IS_ACTION (action));
1170 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1173 modest_msg_edit_window_insert_image (window);
1177 * Shows a dialog with an entry that asks for some text. The returned
1178 * value must be freed by the caller. The dialog window title will be
1182 ask_for_folder_name (GtkWindow *parent_window,
1185 GtkWidget *dialog, *entry;
1186 gchar *folder_name = NULL;
1188 /* Ask for folder name */
1189 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1193 GTK_RESPONSE_REJECT,
1195 GTK_RESPONSE_ACCEPT,
1197 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1198 gtk_label_new(title),
1201 entry = gtk_entry_new_with_max_length (40);
1202 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1206 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1208 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1209 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1211 gtk_widget_destroy (dialog);
1217 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1219 TnyFolder *parent_folder;
1220 GtkWidget *folder_view;
1222 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1224 folder_view = modest_main_window_get_child_widget (main_window,
1225 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1229 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1231 if (parent_folder) {
1234 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1235 _("Please enter a name for the new folder"));
1237 if (folder_name != NULL && strlen (folder_name) > 0) {
1238 TnyFolder *new_folder;
1239 ModestMailOperation *mail_op;
1241 mail_op = modest_mail_operation_new ();
1242 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1245 new_folder = modest_mail_operation_create_folder (mail_op,
1246 TNY_FOLDER_STORE (parent_folder),
1247 (const gchar *) folder_name);
1249 g_object_unref (new_folder);
1250 g_object_unref (mail_op);
1251 g_free (folder_name);
1253 g_object_unref (parent_folder);
1258 modest_ui_actions_on_rename_folder (GtkAction *action,
1259 ModestMainWindow *main_window)
1262 GtkWidget *folder_view;
1264 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1266 folder_view = modest_main_window_get_child_widget (main_window,
1267 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1271 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1275 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1276 _("Please enter a new name for the folder"));
1278 if (folder_name != NULL && strlen (folder_name) > 0) {
1279 ModestMailOperation *mail_op;
1281 mail_op = modest_mail_operation_new ();
1282 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1285 modest_mail_operation_rename_folder (mail_op,
1287 (const gchar *) folder_name);
1289 g_object_unref (mail_op);
1290 g_free (folder_name);
1292 g_object_unref (folder);
1297 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
1300 ModestMailOperation *mail_op;
1301 GtkWidget *folder_view;
1303 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1305 folder_view = modest_main_window_get_child_widget (main_window,
1306 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1310 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1312 mail_op = modest_mail_operation_new ();
1313 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1315 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1317 g_object_unref (G_OBJECT (mail_op));
1318 g_object_unref (G_OBJECT (folder));
1322 modest_ui_actions_on_delete_folder (GtkAction *action,
1323 ModestMainWindow *main_window)
1325 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1327 delete_folder (main_window, FALSE);
1331 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1333 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1335 delete_folder (main_window, TRUE);
1339 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
1340 const gchar* account_name,
1344 ModestMainWindow *main_window)
1347 GtkWidget *dialog, *entry, *remember_pass_check;
1349 dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1353 GTK_RESPONSE_REJECT,
1355 GTK_RESPONSE_ACCEPT,
1357 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1359 txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1360 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1364 entry = gtk_entry_new_with_max_length (40);
1365 gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1366 gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1368 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1371 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1372 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1375 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1377 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1378 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1385 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1390 gtk_widget_destroy (dialog);
1394 modest_ui_actions_on_cut (GtkAction *action,
1395 ModestWindow *window)
1397 GtkWidget *focused_widget;
1399 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1400 if (GTK_IS_EDITABLE (focused_widget)) {
1401 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1402 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1403 GtkTextBuffer *buffer;
1404 GtkClipboard *clipboard;
1406 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1407 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1408 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1413 modest_ui_actions_on_copy (GtkAction *action,
1414 ModestWindow *window)
1416 GtkClipboard *clipboard;
1417 GtkWidget *focused_widget;
1419 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1420 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1421 if (GTK_IS_LABEL (focused_widget)) {
1422 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1423 } else if (GTK_IS_EDITABLE (focused_widget)) {
1424 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1425 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1426 GtkTextBuffer *buffer;
1428 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1429 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1434 modest_ui_actions_on_paste (GtkAction *action,
1435 ModestWindow *window)
1437 GtkWidget *focused_widget;
1439 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1440 if (GTK_IS_EDITABLE (focused_widget)) {
1441 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1442 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1443 GtkTextBuffer *buffer;
1444 GtkClipboard *clipboard;
1446 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1447 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1448 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1453 modest_ui_actions_on_select_all (GtkAction *action,
1454 ModestWindow *window)
1456 GtkWidget *focused_widget;
1458 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1459 if (GTK_IS_LABEL (focused_widget)) {
1460 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1461 } else if (GTK_IS_EDITABLE (focused_widget)) {
1462 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1463 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1464 GtkTextBuffer *buffer;
1465 GtkTextIter start, end;
1467 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1468 gtk_text_buffer_get_start_iter (buffer, &start);
1469 gtk_text_buffer_get_end_iter (buffer, &end);
1470 gtk_text_buffer_select_range (buffer, &start, &end);
1475 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1476 GtkRadioAction *selected,
1477 ModestWindow *window)
1481 value = gtk_radio_action_get_current_value (selected);
1482 if (MODEST_IS_WINDOW (window)) {
1483 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1488 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
1489 ModestWindow *window)
1491 g_return_if_fail (MODEST_IS_WINDOW (window));
1493 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle))) {
1494 gtk_window_fullscreen (GTK_WINDOW (window));
1496 gtk_window_unfullscreen (GTK_WINDOW (window));
1501 modest_ui_actions_message_details_cb (gpointer msg_data,
1502 gpointer helper_data)
1505 TnyMsg *msg = (TnyMsg *) msg_data;
1507 GetMsgAsyncHelper *helper = (GetMsgAsyncHelper *) helper_data;
1509 header = tny_msg_get_header (msg);
1511 dialog = modest_msg_view_details_dialog_new (GTK_WINDOW (helper->window), header);
1512 g_object_unref (header);
1513 gtk_widget_show_all (dialog);
1515 gtk_dialog_run (GTK_DIALOG (dialog));
1517 gtk_widget_destroy (dialog);
1521 modest_ui_actions_on_message_details (GtkAction *action,
1524 TnyList * headers_list;
1525 GetMsgAsyncHelper *helper;
1527 headers_list = get_selected_headers (win);
1531 helper = g_slice_new0 (GetMsgAsyncHelper);
1532 helper->window = win;
1533 helper->func = modest_ui_actions_message_details_cb;
1534 helper->iter = tny_list_create_iterator (headers_list);
1535 helper->user_data = NULL;
1537 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1540 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1544 modest_ui_actions_message_details_cb (msg, helper);
1547 /* here we should add an implementation to run the message details dialog
1548 from the main window */
1549 g_return_if_reached ();