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 action_send (const gchar* account_name)
587 TnyAccount *tny_account;
588 ModestTnySendQueue *send_queue;
590 g_return_val_if_fail (account_name, FALSE);
593 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
595 TNY_ACCOUNT_TYPE_TRANSPORT);
597 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
600 send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
602 g_object_unref (G_OBJECT(tny_account));
603 g_printerr ("modest: cannot get send queue for %s\n", account_name);
607 //modest_tny_send_queue_flush (send_queue);
609 g_object_unref (G_OBJECT(send_queue));
610 g_object_unref (G_OBJECT(tny_account));
617 action_receive (const gchar* account_name)
619 TnyAccount *tny_account;
620 ModestMailOperation *mail_op;
622 g_return_val_if_fail (account_name, FALSE);
625 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
627 TNY_ACCOUNT_TYPE_STORE);
629 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
633 /* Create the mail operation */
634 mail_op = modest_mail_operation_new ();
635 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
636 modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
637 g_object_unref (G_OBJECT(tny_account));
638 g_object_unref (G_OBJECT (mail_op));
646 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
651 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
653 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
655 g_printerr ("modest: cannot get account\n");
659 if (!action_send(account_name))
660 g_printerr ("modest: failed to send\n");
661 if (!action_receive(account_name))
662 g_printerr ("modest: failed to receive\n");
668 modest_ui_actions_toggle_view (GtkAction *action, ModestMainWindow *main_window)
671 GtkWidget *header_view;
673 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
675 header_view = modest_main_window_get_child_widget (main_window,
676 MODEST_WIDGET_TYPE_HEADER_VIEW);
680 conf = modest_runtime_get_conf ();
682 /* what is saved/restored is depending on the style; thus; we save with
683 * old style, then update the style, and restore for this new style
685 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
687 if (modest_header_view_get_style
688 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
689 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
690 MODEST_HEADER_VIEW_STYLE_TWOLINES);
692 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
693 MODEST_HEADER_VIEW_STYLE_DETAILS);
695 modest_widget_memory_restore (conf, G_OBJECT(header_view),
702 * Marks a message as read and passes it to the msg preview widget
705 read_msg_func (gpointer data, gpointer user_data)
709 GetMsgAsyncHelper *helper;
710 TnyHeaderFlags header_flags;
711 GtkWidget *msg_preview;
713 msg = TNY_MSG (data);
714 helper = (GetMsgAsyncHelper *) user_data;
716 msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
717 MODEST_WIDGET_TYPE_MSG_PREVIEW);
721 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
722 header_flags = tny_header_get_flags (header);
723 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
724 g_object_unref (G_OBJECT (header));
726 /* Set message on msg view */
727 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
731 * This function is a generic handler for the tny_folder_get_msg_async
732 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
733 * contains a user provided function that is called inside this
734 * method. This will allow us to use this callback in many different
735 * places. This callback performs the common actions for the
736 * get_msg_async call, more specific actions will be done by the user
740 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
742 GetMsgAsyncHelper *helper;
744 helper = (GetMsgAsyncHelper *) user_data;
746 if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
747 modest_ui_actions_on_item_not_found (NULL,
748 MODEST_ITEM_TYPE_MESSAGE,
753 /* Call user function */
754 helper->func (msg, user_data);
756 /* Process next element (if exists) */
757 tny_iterator_next (helper->iter);
758 if (tny_iterator_is_done (helper->iter)) {
760 headers = tny_iterator_get_list (helper->iter);
762 g_object_unref (G_OBJECT (headers));
763 g_object_unref (G_OBJECT (helper->iter));
764 g_slice_free (GetMsgAsyncHelper, helper);
767 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
768 tny_folder_get_msg_async (folder, header,
770 g_object_unref (G_OBJECT(header));
775 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
777 ModestMainWindow *main_window)
779 GtkWidget *msg_preview;
781 GetMsgAsyncHelper *helper;
784 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
786 msg_preview = modest_main_window_get_child_widget(main_window,
787 MODEST_WIDGET_TYPE_MSG_PREVIEW);
791 /* when there's no header, clear the msgview */
793 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
797 folder = tny_header_get_folder (TNY_HEADER(header));
800 list = tny_simple_list_new ();
801 tny_list_prepend (list, G_OBJECT (header));
803 /* Fill helper data */
804 helper = g_slice_new0 (GetMsgAsyncHelper);
805 helper->window = MODEST_WINDOW (main_window);
806 helper->iter = tny_list_create_iterator (list);
807 helper->func = read_msg_func;
809 tny_folder_get_msg_async (TNY_FOLDER(folder),
814 g_object_unref (G_OBJECT (folder));
820 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
821 ModestMainWindow *main_window)
824 TnyFolder *folder = NULL;
826 gchar *account = NULL;
827 GtkTreeModel *model = NULL;
828 GtkTreeSelection *sel = NULL;
830 ModestWindowMgr *mgr;
832 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
837 folder = tny_header_get_folder (header);
839 g_printerr ("modest: cannot get folder for header\n");
843 /* FIXME: make async?; check error */
844 msg = tny_folder_get_msg (folder, header, NULL);
846 g_printerr ("modest: cannot get msg for header\n");
850 account = g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
852 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
854 /* Create and register message view window */
855 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
856 if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
857 win = modest_msg_view_window_new_with_header_model (msg, account, model, iter);
859 win = modest_msg_view_window_new (msg, account);
861 mgr = modest_runtime_get_window_mgr ();
862 modest_window_mgr_register_window (mgr, win);
864 gtk_window_set_transient_for (GTK_WINDOW (win),
865 GTK_WINDOW (main_window));
867 gtk_widget_show_all (GTK_WIDGET(win));
873 g_object_unref (G_OBJECT (folder));
875 g_object_unref (G_OBJECT (msg));
879 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
882 ModestMainWindow *main_window)
886 GtkWidget *header_view;
888 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
890 header_view = modest_main_window_get_child_widget(main_window,
891 MODEST_WIDGET_TYPE_HEADER_VIEW);
895 conf = modest_runtime_get_conf ();
897 if (!selected) { /* the folder was unselected; save it's settings */
898 modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
899 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
900 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
901 } else { /* the folder was selected */
902 if (folder) { /* folder may be NULL */
906 num = tny_folder_get_all_count (folder);
907 unread = tny_folder_get_unread_count (folder);
909 title = g_strdup_printf ("Modest: %s",
910 tny_folder_get_name (folder));
912 gtk_window_set_title (GTK_WINDOW(main_window), title);
915 txt = g_strdup_printf (_("%d %s, %d unread"),
916 num, num==1 ? _("item") : _("items"), unread);
917 //gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
920 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
921 modest_widget_memory_restore (conf, G_OBJECT(header_view),
927 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
934 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
936 if (g_main_depth > 0)
937 gdk_threads_enter ();
938 online = tny_device_is_online (modest_runtime_get_device());
941 /* already online -- the item is simply not there... */
942 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
946 _("The %s you selected cannot be found"),
948 gtk_dialog_run (GTK_DIALOG(dialog));
950 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
958 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
959 "Do you want to get online?"), item);
960 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
961 gtk_label_new (txt), FALSE, FALSE, 0);
962 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
965 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
966 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
967 // tny_device_force_online (modest_runtime_get_device());
970 gtk_widget_destroy (dialog);
971 if (g_main_depth > 0)
972 gdk_threads_leave ();
976 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
979 g_message ("%s %s", __FUNCTION__, link);
984 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
987 modest_platform_activate_uri (link);
991 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
994 modest_platform_show_uri_popup (link);
998 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1001 g_message (__FUNCTION__);
1006 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1007 const gchar *address,
1010 g_message ("%s %s", __FUNCTION__, address);
1014 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1016 TnyTransportAccount *transport_account;
1017 ModestMailOperation *mail_operation;
1019 gchar *account_name, *from;
1020 ModestAccountMgr *account_mgr;
1022 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1024 data = modest_msg_edit_window_get_msg_data (edit_window);
1026 /* FIXME: Code added just for testing. The final version will
1027 use the send queue provided by tinymail and some
1029 account_mgr = modest_runtime_get_account_mgr();
1030 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1032 account_name = modest_account_mgr_get_default_account (account_mgr);
1033 if (!account_name) {
1034 g_printerr ("modest: no account found\n");
1035 modest_msg_edit_window_free_msg_data (edit_window, data);
1039 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1040 (modest_runtime_get_account_store(),
1042 TNY_ACCOUNT_TYPE_TRANSPORT));
1043 if (!transport_account) {
1044 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1045 g_free (account_name);
1046 modest_msg_edit_window_free_msg_data (edit_window, data);
1049 from = modest_account_mgr_get_from_string (account_mgr, account_name);
1051 /* Create the mail operation */
1052 mail_operation = modest_mail_operation_new ();
1053 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1055 modest_mail_operation_send_new_mail (mail_operation,
1067 g_free (account_name);
1068 g_object_unref (G_OBJECT (transport_account));
1069 g_object_unref (G_OBJECT (mail_operation));
1071 modest_msg_edit_window_free_msg_data (edit_window, data);
1073 /* Save settings and close the window */
1074 gtk_widget_destroy (GTK_WIDGET (edit_window));
1078 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1079 ModestMsgEditWindow *window)
1081 ModestMsgEditFormatState *format_state = NULL;
1083 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1084 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1086 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1089 format_state = modest_msg_edit_window_get_format_state (window);
1090 g_return_if_fail (format_state != NULL);
1092 format_state->bold = gtk_toggle_action_get_active (action);
1093 modest_msg_edit_window_set_format_state (window, format_state);
1094 g_free (format_state);
1099 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1100 ModestMsgEditWindow *window)
1102 ModestMsgEditFormatState *format_state = NULL;
1104 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1105 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1107 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1110 format_state = modest_msg_edit_window_get_format_state (window);
1111 g_return_if_fail (format_state != NULL);
1113 format_state->italics = gtk_toggle_action_get_active (action);
1114 modest_msg_edit_window_set_format_state (window, format_state);
1115 g_free (format_state);
1120 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1121 ModestMsgEditWindow *window)
1123 ModestMsgEditFormatState *format_state = NULL;
1125 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1126 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1128 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1131 format_state = modest_msg_edit_window_get_format_state (window);
1132 g_return_if_fail (format_state != NULL);
1134 format_state->bullet = gtk_toggle_action_get_active (action);
1135 modest_msg_edit_window_set_format_state (window, format_state);
1136 g_free (format_state);
1141 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1142 GtkRadioAction *selected,
1143 ModestMsgEditWindow *window)
1145 ModestMsgEditFormatState *format_state = NULL;
1146 GtkJustification value;
1148 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1150 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1153 value = gtk_radio_action_get_current_value (selected);
1155 format_state = modest_msg_edit_window_get_format_state (window);
1156 g_return_if_fail (format_state != NULL);
1158 format_state->justification = value;
1159 modest_msg_edit_window_set_format_state (window, format_state);
1160 g_free (format_state);
1164 modest_ui_actions_on_select_editor_color (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_select_color (window);
1177 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1178 ModestMsgEditWindow *window)
1180 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1181 g_return_if_fail (GTK_IS_ACTION (action));
1183 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1186 modest_msg_edit_window_select_background_color (window);
1190 modest_ui_actions_on_insert_image (GtkAction *action,
1191 ModestMsgEditWindow *window)
1193 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1194 g_return_if_fail (GTK_IS_ACTION (action));
1196 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1199 modest_msg_edit_window_insert_image (window);
1203 * Shows a dialog with an entry that asks for some text. The returned
1204 * value must be freed by the caller. The dialog window title will be
1208 ask_for_folder_name (GtkWindow *parent_window,
1211 GtkWidget *dialog, *entry;
1212 gchar *folder_name = NULL;
1214 /* Ask for folder name */
1215 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1219 GTK_RESPONSE_REJECT,
1221 GTK_RESPONSE_ACCEPT,
1223 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1224 gtk_label_new(title),
1227 entry = gtk_entry_new_with_max_length (40);
1228 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1232 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1234 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1235 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1237 gtk_widget_destroy (dialog);
1243 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1245 TnyFolder *parent_folder;
1246 GtkWidget *folder_view;
1248 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1250 folder_view = modest_main_window_get_child_widget (main_window,
1251 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1255 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1257 if (parent_folder) {
1260 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1261 _("Please enter a name for the new folder"));
1263 if (folder_name != NULL && strlen (folder_name) > 0) {
1264 TnyFolder *new_folder;
1265 ModestMailOperation *mail_op;
1267 mail_op = modest_mail_operation_new ();
1268 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1271 new_folder = modest_mail_operation_create_folder (mail_op,
1272 TNY_FOLDER_STORE (parent_folder),
1273 (const gchar *) folder_name);
1275 g_object_unref (new_folder);
1276 g_object_unref (mail_op);
1277 g_free (folder_name);
1279 g_object_unref (parent_folder);
1284 modest_ui_actions_on_rename_folder (GtkAction *action,
1285 ModestMainWindow *main_window)
1288 GtkWidget *folder_view;
1290 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1292 folder_view = modest_main_window_get_child_widget (main_window,
1293 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1297 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1301 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1302 _("Please enter a new name for the folder"));
1304 if (folder_name != NULL && strlen (folder_name) > 0) {
1305 ModestMailOperation *mail_op;
1307 mail_op = modest_mail_operation_new ();
1308 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1311 modest_mail_operation_rename_folder (mail_op,
1313 (const gchar *) folder_name);
1315 g_object_unref (mail_op);
1316 g_free (folder_name);
1318 g_object_unref (folder);
1323 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
1326 ModestMailOperation *mail_op;
1327 GtkWidget *folder_view;
1329 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1331 folder_view = modest_main_window_get_child_widget (main_window,
1332 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1336 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1338 mail_op = modest_mail_operation_new ();
1339 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1341 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1343 g_object_unref (G_OBJECT (mail_op));
1344 g_object_unref (G_OBJECT (folder));
1348 modest_ui_actions_on_delete_folder (GtkAction *action,
1349 ModestMainWindow *main_window)
1351 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1353 delete_folder (main_window, FALSE);
1357 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1359 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1361 delete_folder (main_window, TRUE);
1365 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
1366 const gchar* account_name,
1370 ModestMainWindow *main_window)
1373 GtkWidget *dialog, *entry, *remember_pass_check;
1375 dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1379 GTK_RESPONSE_REJECT,
1381 GTK_RESPONSE_ACCEPT,
1383 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1385 txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1386 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1390 entry = gtk_entry_new_with_max_length (40);
1391 gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1392 gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1394 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1397 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1398 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1401 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1403 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1404 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1411 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1416 gtk_widget_destroy (dialog);
1420 modest_ui_actions_on_cut (GtkAction *action,
1421 ModestWindow *window)
1423 GtkWidget *focused_widget;
1425 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1426 if (GTK_IS_EDITABLE (focused_widget)) {
1427 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1428 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1429 GtkTextBuffer *buffer;
1430 GtkClipboard *clipboard;
1432 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1433 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1434 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1439 modest_ui_actions_on_copy (GtkAction *action,
1440 ModestWindow *window)
1442 GtkClipboard *clipboard;
1443 GtkWidget *focused_widget;
1445 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1446 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1447 if (GTK_IS_LABEL (focused_widget)) {
1448 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1449 } else if (GTK_IS_EDITABLE (focused_widget)) {
1450 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1451 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1452 GtkTextBuffer *buffer;
1454 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1455 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1460 modest_ui_actions_on_paste (GtkAction *action,
1461 ModestWindow *window)
1463 GtkWidget *focused_widget;
1465 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1466 if (GTK_IS_EDITABLE (focused_widget)) {
1467 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1468 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1469 GtkTextBuffer *buffer;
1470 GtkClipboard *clipboard;
1472 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1473 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1474 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1479 modest_ui_actions_on_select_all (GtkAction *action,
1480 ModestWindow *window)
1482 GtkWidget *focused_widget;
1484 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1485 if (GTK_IS_LABEL (focused_widget)) {
1486 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1487 } else if (GTK_IS_EDITABLE (focused_widget)) {
1488 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1489 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1490 GtkTextBuffer *buffer;
1491 GtkTextIter start, end;
1493 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1494 gtk_text_buffer_get_start_iter (buffer, &start);
1495 gtk_text_buffer_get_end_iter (buffer, &end);
1496 gtk_text_buffer_select_range (buffer, &start, &end);
1501 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1502 GtkRadioAction *selected,
1503 ModestWindow *window)
1507 value = gtk_radio_action_get_current_value (selected);
1508 if (MODEST_IS_WINDOW (window)) {
1509 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1514 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
1515 ModestWindow *window)
1517 g_return_if_fail (MODEST_IS_WINDOW (window));
1519 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle))) {
1520 gtk_window_fullscreen (GTK_WINDOW (window));
1522 gtk_window_unfullscreen (GTK_WINDOW (window));
1527 modest_ui_actions_message_details_cb (gpointer msg_data,
1528 gpointer helper_data)
1531 TnyMsg *msg = (TnyMsg *) msg_data;
1533 GetMsgAsyncHelper *helper = (GetMsgAsyncHelper *) helper_data;
1535 header = tny_msg_get_header (msg);
1537 dialog = modest_msg_view_details_dialog_new (GTK_WINDOW (helper->window), header);
1538 g_object_unref (header);
1539 gtk_widget_show_all (dialog);
1541 gtk_dialog_run (GTK_DIALOG (dialog));
1543 gtk_widget_destroy (dialog);
1547 modest_ui_actions_on_message_details (GtkAction *action,
1550 TnyList * headers_list;
1551 GetMsgAsyncHelper *helper;
1553 headers_list = get_selected_headers (win);
1557 helper = g_slice_new0 (GetMsgAsyncHelper);
1558 helper->window = win;
1559 helper->func = modest_ui_actions_message_details_cb;
1560 helper->iter = tny_list_create_iterator (headers_list);
1561 helper->user_data = NULL;
1563 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1566 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1570 modest_ui_actions_message_details_cb (msg, helper);
1573 /* here we should add an implementation to run the message details dialog
1574 from the main window */
1575 g_return_if_reached ();