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)
234 /* This is currently only implemented for Maemo,
235 * because it requires a providers preset file which is not publically available.
237 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
238 GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr());
239 gboolean accounts_exist = account_names != NULL;
240 g_slist_free (account_names);
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));
250 /* Show the list of accounts: */
251 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
252 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
253 gtk_dialog_run (account_win);
254 gtk_widget_destroy (GTK_WIDGET(account_win));
257 GtkWidget *dialog, *label;
259 /* Create the widgets */
261 dialog = gtk_dialog_new_with_buttons ("Message",
263 GTK_DIALOG_DESTROY_WITH_PARENT,
267 label = gtk_label_new ("Hello World!");
269 /* Ensure that the dialog box is destroyed when the user responds. */
271 g_signal_connect_swapped (dialog, "response",
272 G_CALLBACK (gtk_widget_destroy),
275 /* Add the label, and show everything we've added to the dialog. */
277 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
279 gtk_widget_show_all (dialog);
280 #endif /* MODEST_PLATFORM_MAEMO */
284 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
286 ModestWindow *msg_win;
288 TnyFolder *folder = NULL;
289 gchar *account_name = NULL;
290 gchar *from_str = NULL;
293 ModestWindowMgr *mgr;
295 account_name = g_strdup(modest_window_get_active_account (win));
297 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
299 account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
301 TNY_ACCOUNT_TYPE_STORE);
303 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
307 from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
309 msg = modest_tny_msg_new ("", from_str, "", "", "", "", NULL);
311 g_printerr ("modest: failed to create new msg\n");
315 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
317 g_printerr ("modest: failed to find Drafts folder\n");
321 tny_folder_add_msg (folder, msg, &err);
323 g_printerr ("modest: error adding msg to Drafts folder: %s",
329 /* Create and register edit window */
330 msg_win = modest_msg_edit_window_new (msg, account_name);
331 mgr = modest_runtime_get_window_mgr ();
332 modest_window_mgr_register_window (mgr, msg_win);
335 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
337 gtk_widget_show_all (GTK_WIDGET (msg_win));
340 g_free (account_name);
343 g_object_unref (G_OBJECT(account));
345 g_object_unref (G_OBJECT(msg));
347 g_object_unref (G_OBJECT(folder));
352 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
354 modest_runtime_not_implemented (GTK_WINDOW(win)); /* FIXME */
360 reply_forward_func (gpointer data, gpointer user_data)
362 TnyMsg *msg, *new_msg;
363 GetMsgAsyncHelper *helper;
364 ReplyForwardHelper *rf_helper;
365 ModestWindow *msg_win;
366 ModestEditType edit_type;
369 TnyFolder *folder = NULL;
370 TnyAccount *account = NULL;
371 ModestWindowMgr *mgr;
373 msg = TNY_MSG (data);
374 helper = (GetMsgAsyncHelper *) user_data;
375 rf_helper = (ReplyForwardHelper *) helper->user_data;
377 from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
378 rf_helper->account_name);
379 /* Create reply mail */
380 switch (rf_helper->action) {
383 modest_tny_msg_create_reply_msg (msg, from,
384 rf_helper->reply_forward_type,
385 MODEST_TNY_MSG_REPLY_MODE_SENDER);
387 case ACTION_REPLY_TO_ALL:
389 modest_tny_msg_create_reply_msg (msg, from, rf_helper->reply_forward_type,
390 MODEST_TNY_MSG_REPLY_MODE_ALL);
391 edit_type = MODEST_EDIT_TYPE_REPLY;
395 modest_tny_msg_create_forward_msg (msg, from, rf_helper->reply_forward_type);
396 edit_type = MODEST_EDIT_TYPE_FORWARD;
399 g_return_if_reached ();
404 g_printerr ("modest: failed to create message\n");
408 account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
409 rf_helper->account_name,
410 TNY_ACCOUNT_TYPE_STORE);
412 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
416 folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
418 g_printerr ("modest: failed to find Drafts folder\n");
422 tny_folder_add_msg (folder, msg, &err);
424 g_printerr ("modest: error adding msg to Drafts folder: %s",
430 /* Create and register the windows */
431 msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
432 mgr = modest_runtime_get_window_mgr ();
433 modest_window_mgr_register_window (mgr, msg_win);
435 /* Show edit window */
436 gtk_widget_show_all (GTK_WIDGET (msg_win));
440 g_object_unref (G_OBJECT (new_msg));
442 g_object_unref (G_OBJECT (folder));
444 g_object_unref (G_OBJECT (account));
446 g_free (rf_helper->account_name);
447 g_slice_free (ReplyForwardHelper, rf_helper);
450 * Common code for the reply and forward actions
453 reply_forward (ReplyForwardAction action, ModestWindow *win)
455 TnyList *header_list;
456 guint reply_forward_type;
459 GetMsgAsyncHelper *helper;
460 ReplyForwardHelper *rf_helper;
462 g_return_if_fail (MODEST_IS_WINDOW(win));
464 header_list = get_selected_headers (win);
468 reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
469 (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
471 /* We assume that we can only select messages of the
472 same folder and that we reply all of them from the
473 same account. In fact the interface currently only
474 allows single selection */
477 rf_helper = g_slice_new0 (ReplyForwardHelper);
478 rf_helper->reply_forward_type = reply_forward_type;
479 rf_helper->action = action;
481 rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
482 if (!rf_helper->account_name)
483 rf_helper->account_name =
484 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
486 helper = g_slice_new0 (GetMsgAsyncHelper);
487 helper->window = win;
488 helper->func = reply_forward_func;
489 helper->iter = tny_list_create_iterator (header_list);
490 helper->user_data = rf_helper;
492 if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
494 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
496 g_printerr ("modest: no message found\n");
499 reply_forward_func (msg, helper);
501 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
502 folder = tny_header_get_folder (header);
504 /* The callback will call it per each header */
505 tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
506 g_object_unref (G_OBJECT (folder));
508 g_printerr ("modest: no folder for header\n");
511 g_object_unref (G_OBJECT (header));
517 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
519 g_return_if_fail (MODEST_IS_WINDOW(win));
521 reply_forward (ACTION_REPLY, win);
525 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
527 g_return_if_fail (MODEST_IS_WINDOW(win));
529 reply_forward (ACTION_FORWARD, win);
533 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
535 g_return_if_fail (MODEST_IS_WINDOW(win));
537 reply_forward (ACTION_REPLY_TO_ALL, win);
541 modest_ui_actions_on_next (GtkAction *action,
542 ModestWindow *window)
544 if (MODEST_IS_MAIN_WINDOW (window)) {
545 GtkWidget *header_view;
547 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
548 MODEST_WIDGET_TYPE_HEADER_VIEW);
552 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view));
553 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
554 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
556 g_return_if_reached ();
561 modest_ui_actions_on_prev (GtkAction *action,
562 ModestWindow *window)
564 g_return_if_fail (MODEST_IS_WINDOW(window));
566 if (MODEST_IS_MAIN_WINDOW (window)) {
567 GtkWidget *header_view;
568 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
569 MODEST_WIDGET_TYPE_HEADER_VIEW);
573 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
574 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
575 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
577 g_return_if_reached ();
583 action_send (const gchar* account_name)
585 TnyAccount *tny_account;
586 ModestTnySendQueue *send_queue;
588 g_return_val_if_fail (account_name, FALSE);
591 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
593 TNY_ACCOUNT_TYPE_TRANSPORT);
595 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
598 send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
600 g_object_unref (G_OBJECT(tny_account));
601 g_printerr ("modest: cannot get send queue for %s\n", account_name);
605 //modest_tny_send_queue_flush (send_queue);
607 g_object_unref (G_OBJECT(send_queue));
608 g_object_unref (G_OBJECT(tny_account));
615 action_receive (const gchar* account_name)
617 TnyAccount *tny_account;
618 ModestMailOperation *mail_op;
620 g_return_val_if_fail (account_name, FALSE);
623 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
625 TNY_ACCOUNT_TYPE_STORE);
627 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
631 /* Create the mail operation */
632 mail_op = modest_mail_operation_new ();
633 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
634 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));
644 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
649 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
651 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
653 g_printerr ("modest: cannot get account\n");
657 if (!action_send(account_name))
658 g_printerr ("modest: failed to send\n");
659 if (!action_receive(account_name))
660 g_printerr ("modest: failed to receive\n");
666 modest_ui_actions_toggle_view (GtkAction *action, ModestMainWindow *main_window)
669 GtkWidget *header_view;
671 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
673 header_view = modest_main_window_get_child_widget (main_window,
674 MODEST_WIDGET_TYPE_HEADER_VIEW);
678 conf = modest_runtime_get_conf ();
680 /* what is saved/restored is depending on the style; thus; we save with
681 * old style, then update the style, and restore for this new style
683 modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
685 if (modest_header_view_get_style
686 (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
687 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
688 MODEST_HEADER_VIEW_STYLE_TWOLINES);
690 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
691 MODEST_HEADER_VIEW_STYLE_DETAILS);
693 modest_widget_memory_restore (conf, G_OBJECT(header_view),
700 * Marks a message as read and passes it to the msg preview widget
703 read_msg_func (gpointer data, gpointer user_data)
707 GetMsgAsyncHelper *helper;
708 TnyHeaderFlags header_flags;
709 GtkWidget *msg_preview;
711 msg = TNY_MSG (data);
712 helper = (GetMsgAsyncHelper *) user_data;
714 msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
715 MODEST_WIDGET_TYPE_MSG_PREVIEW);
719 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
720 header_flags = tny_header_get_flags (header);
721 tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
722 g_object_unref (G_OBJECT (header));
724 /* Set message on msg view */
725 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
729 * This function is a generic handler for the tny_folder_get_msg_async
730 * call. It expects as user_data a #GetMsgAsyncHelper. This helper
731 * contains a user provided function that is called inside this
732 * method. This will allow us to use this callback in many different
733 * places. This callback performs the common actions for the
734 * get_msg_async call, more specific actions will be done by the user
738 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
740 GetMsgAsyncHelper *helper;
742 helper = (GetMsgAsyncHelper *) user_data;
744 if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
745 modest_ui_actions_on_item_not_found (NULL,
746 MODEST_ITEM_TYPE_MESSAGE,
751 /* Call user function */
752 helper->func (msg, user_data);
754 /* Process next element (if exists) */
755 tny_iterator_next (helper->iter);
756 if (tny_iterator_is_done (helper->iter)) {
758 headers = tny_iterator_get_list (helper->iter);
760 g_object_unref (G_OBJECT (headers));
761 g_object_unref (G_OBJECT (helper->iter));
762 g_slice_free (GetMsgAsyncHelper, helper);
765 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
766 tny_folder_get_msg_async (folder, header,
768 g_object_unref (G_OBJECT(header));
773 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view,
775 ModestMainWindow *main_window)
777 GtkWidget *msg_preview;
779 GetMsgAsyncHelper *helper;
782 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
784 msg_preview = modest_main_window_get_child_widget(main_window,
785 MODEST_WIDGET_TYPE_MSG_PREVIEW);
789 /* when there's no header, clear the msgview */
791 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
795 folder = tny_header_get_folder (TNY_HEADER(header));
798 list = tny_simple_list_new ();
799 tny_list_prepend (list, G_OBJECT (header));
801 /* Fill helper data */
802 helper = g_slice_new0 (GetMsgAsyncHelper);
803 helper->window = MODEST_WINDOW (main_window);
804 helper->iter = tny_list_create_iterator (list);
805 helper->func = read_msg_func;
807 tny_folder_get_msg_async (TNY_FOLDER(folder),
812 g_object_unref (G_OBJECT (folder));
818 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
819 ModestMainWindow *main_window)
822 TnyFolder *folder = NULL;
824 gchar *account = NULL;
825 GtkTreeModel *model = NULL;
826 GtkTreeSelection *sel = NULL;
828 ModestWindowMgr *mgr;
830 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
835 folder = tny_header_get_folder (header);
837 g_printerr ("modest: cannot get folder for header\n");
841 /* FIXME: make async?; check error */
842 msg = tny_folder_get_msg (folder, header, NULL);
844 g_printerr ("modest: cannot get msg for header\n");
848 account = g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
850 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
852 /* Create and register message view window */
853 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
854 if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
855 win = modest_msg_view_window_new_with_header_model (msg, account, model, iter);
857 win = modest_msg_view_window_new (msg, account);
859 mgr = modest_runtime_get_window_mgr ();
860 modest_window_mgr_register_window (mgr, win);
862 gtk_window_set_transient_for (GTK_WINDOW (win),
863 GTK_WINDOW (main_window));
865 gtk_widget_show_all (GTK_WIDGET(win));
871 g_object_unref (G_OBJECT (folder));
873 g_object_unref (G_OBJECT (msg));
877 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
880 ModestMainWindow *main_window)
884 GtkWidget *header_view;
886 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
888 header_view = modest_main_window_get_child_widget(main_window,
889 MODEST_WIDGET_TYPE_HEADER_VIEW);
893 conf = modest_runtime_get_conf ();
895 if (!selected) { /* the folder was unselected; save it's settings */
896 modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
897 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
898 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
899 } else { /* the folder was selected */
900 if (folder) { /* folder may be NULL */
904 num = tny_folder_get_all_count (folder);
905 unread = tny_folder_get_unread_count (folder);
907 title = g_strdup_printf ("Modest: %s",
908 tny_folder_get_name (folder));
910 gtk_window_set_title (GTK_WINDOW(main_window), title);
913 txt = g_strdup_printf (_("%d %s, %d unread"),
914 num, num==1 ? _("item") : _("items"), unread);
915 //gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
918 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
919 modest_widget_memory_restore (conf, G_OBJECT(header_view),
925 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
932 item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
934 if (g_main_depth > 0)
935 gdk_threads_enter ();
936 online = tny_device_is_online (modest_runtime_get_device());
939 /* already online -- the item is simply not there... */
940 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
944 _("The %s you selected cannot be found"),
946 gtk_dialog_run (GTK_DIALOG(dialog));
948 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
956 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
957 "Do you want to get online?"), item);
958 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
959 gtk_label_new (txt), FALSE, FALSE, 0);
960 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
963 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
964 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
965 // tny_device_force_online (modest_runtime_get_device());
968 gtk_widget_destroy (dialog);
969 if (g_main_depth > 0)
970 gdk_threads_leave ();
974 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
977 g_message ("%s %s", __FUNCTION__, link);
982 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
985 modest_platform_activate_uri (link);
989 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
992 modest_platform_show_uri_popup (link);
996 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
999 g_message (__FUNCTION__);
1004 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1005 const gchar *address,
1008 g_message ("%s %s", __FUNCTION__, address);
1012 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1014 TnyTransportAccount *transport_account;
1015 ModestMailOperation *mail_operation;
1017 gchar *account_name, *from;
1018 ModestAccountMgr *account_mgr;
1020 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1022 data = modest_msg_edit_window_get_msg_data (edit_window);
1024 /* FIXME: Code added just for testing. The final version will
1025 use the send queue provided by tinymail and some
1027 account_mgr = modest_runtime_get_account_mgr();
1028 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1030 account_name = modest_account_mgr_get_default_account (account_mgr);
1031 if (!account_name) {
1032 g_printerr ("modest: no account found\n");
1033 modest_msg_edit_window_free_msg_data (edit_window, data);
1037 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1038 (modest_runtime_get_account_store(),
1040 TNY_ACCOUNT_TYPE_TRANSPORT));
1041 if (!transport_account) {
1042 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1043 g_free (account_name);
1044 modest_msg_edit_window_free_msg_data (edit_window, data);
1047 from = modest_account_mgr_get_from_string (account_mgr, account_name);
1049 /* Create the mail operation */
1050 mail_operation = modest_mail_operation_new ();
1051 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1053 modest_mail_operation_send_new_mail (mail_operation,
1065 g_free (account_name);
1066 g_object_unref (G_OBJECT (transport_account));
1067 g_object_unref (G_OBJECT (mail_operation));
1069 modest_msg_edit_window_free_msg_data (edit_window, data);
1071 /* Save settings and close the window */
1072 gtk_widget_destroy (GTK_WIDGET (edit_window));
1076 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1077 ModestMsgEditWindow *window)
1079 ModestMsgEditFormatState *format_state = NULL;
1081 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1082 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1084 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1087 format_state = modest_msg_edit_window_get_format_state (window);
1088 g_return_if_fail (format_state != NULL);
1090 format_state->bold = gtk_toggle_action_get_active (action);
1091 modest_msg_edit_window_set_format_state (window, format_state);
1092 g_free (format_state);
1097 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1098 ModestMsgEditWindow *window)
1100 ModestMsgEditFormatState *format_state = NULL;
1102 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1103 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1105 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1108 format_state = modest_msg_edit_window_get_format_state (window);
1109 g_return_if_fail (format_state != NULL);
1111 format_state->italics = gtk_toggle_action_get_active (action);
1112 modest_msg_edit_window_set_format_state (window, format_state);
1113 g_free (format_state);
1118 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1119 ModestMsgEditWindow *window)
1121 ModestMsgEditFormatState *format_state = NULL;
1123 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1124 g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1126 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1129 format_state = modest_msg_edit_window_get_format_state (window);
1130 g_return_if_fail (format_state != NULL);
1132 format_state->bullet = gtk_toggle_action_get_active (action);
1133 modest_msg_edit_window_set_format_state (window, format_state);
1134 g_free (format_state);
1139 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1140 GtkRadioAction *selected,
1141 ModestMsgEditWindow *window)
1143 ModestMsgEditFormatState *format_state = NULL;
1144 GtkJustification value;
1146 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1148 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1151 value = gtk_radio_action_get_current_value (selected);
1153 format_state = modest_msg_edit_window_get_format_state (window);
1154 g_return_if_fail (format_state != NULL);
1156 format_state->justification = value;
1157 modest_msg_edit_window_set_format_state (window, format_state);
1158 g_free (format_state);
1162 modest_ui_actions_on_select_editor_color (GtkAction *action,
1163 ModestMsgEditWindow *window)
1165 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1166 g_return_if_fail (GTK_IS_ACTION (action));
1168 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1171 modest_msg_edit_window_select_color (window);
1175 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1176 ModestMsgEditWindow *window)
1178 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1179 g_return_if_fail (GTK_IS_ACTION (action));
1181 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1184 modest_msg_edit_window_select_background_color (window);
1188 modest_ui_actions_on_insert_image (GtkAction *action,
1189 ModestMsgEditWindow *window)
1191 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1192 g_return_if_fail (GTK_IS_ACTION (action));
1194 if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1197 modest_msg_edit_window_insert_image (window);
1201 * Shows a dialog with an entry that asks for some text. The returned
1202 * value must be freed by the caller. The dialog window title will be
1206 ask_for_folder_name (GtkWindow *parent_window,
1209 GtkWidget *dialog, *entry;
1210 gchar *folder_name = NULL;
1212 /* Ask for folder name */
1213 dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1217 GTK_RESPONSE_REJECT,
1219 GTK_RESPONSE_ACCEPT,
1221 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1222 gtk_label_new(title),
1225 entry = gtk_entry_new_with_max_length (40);
1226 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
1230 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1232 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
1233 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1235 gtk_widget_destroy (dialog);
1241 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1243 TnyFolder *parent_folder;
1244 GtkWidget *folder_view;
1246 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1248 folder_view = modest_main_window_get_child_widget (main_window,
1249 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1253 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1255 if (parent_folder) {
1258 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1259 _("Please enter a name for the new folder"));
1261 if (folder_name != NULL && strlen (folder_name) > 0) {
1262 TnyFolder *new_folder;
1263 ModestMailOperation *mail_op;
1265 mail_op = modest_mail_operation_new ();
1266 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1269 new_folder = modest_mail_operation_create_folder (mail_op,
1270 TNY_FOLDER_STORE (parent_folder),
1271 (const gchar *) folder_name);
1273 g_object_unref (new_folder);
1274 g_object_unref (mail_op);
1275 g_free (folder_name);
1277 g_object_unref (parent_folder);
1282 modest_ui_actions_on_rename_folder (GtkAction *action,
1283 ModestMainWindow *main_window)
1286 GtkWidget *folder_view;
1288 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1290 folder_view = modest_main_window_get_child_widget (main_window,
1291 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1295 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1299 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1300 _("Please enter a new name for the folder"));
1302 if (folder_name != NULL && strlen (folder_name) > 0) {
1303 ModestMailOperation *mail_op;
1305 mail_op = modest_mail_operation_new ();
1306 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1309 modest_mail_operation_rename_folder (mail_op,
1311 (const gchar *) folder_name);
1313 g_object_unref (mail_op);
1314 g_free (folder_name);
1316 g_object_unref (folder);
1321 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
1324 ModestMailOperation *mail_op;
1325 GtkWidget *folder_view;
1327 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1329 folder_view = modest_main_window_get_child_widget (main_window,
1330 MODEST_WIDGET_TYPE_FOLDER_VIEW);
1334 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1336 mail_op = modest_mail_operation_new ();
1337 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1339 modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1341 g_object_unref (G_OBJECT (mail_op));
1342 g_object_unref (G_OBJECT (folder));
1346 modest_ui_actions_on_delete_folder (GtkAction *action,
1347 ModestMainWindow *main_window)
1349 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1351 delete_folder (main_window, FALSE);
1355 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1357 g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1359 delete_folder (main_window, TRUE);
1363 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
1364 const gchar* account_name,
1368 ModestMainWindow *main_window)
1371 GtkWidget *dialog, *entry, *remember_pass_check;
1373 dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1377 GTK_RESPONSE_REJECT,
1379 GTK_RESPONSE_ACCEPT,
1381 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1383 txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1384 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1388 entry = gtk_entry_new_with_max_length (40);
1389 gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1390 gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1392 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1395 remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1396 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1399 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1401 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1402 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1409 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1414 gtk_widget_destroy (dialog);
1418 modest_ui_actions_on_cut (GtkAction *action,
1419 ModestWindow *window)
1421 GtkWidget *focused_widget;
1423 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1424 if (GTK_IS_EDITABLE (focused_widget)) {
1425 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1426 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1427 GtkTextBuffer *buffer;
1428 GtkClipboard *clipboard;
1430 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1431 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1432 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1437 modest_ui_actions_on_copy (GtkAction *action,
1438 ModestWindow *window)
1440 GtkClipboard *clipboard;
1441 GtkWidget *focused_widget;
1443 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1444 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1445 if (GTK_IS_LABEL (focused_widget)) {
1446 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1447 } else if (GTK_IS_EDITABLE (focused_widget)) {
1448 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1449 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1450 GtkTextBuffer *buffer;
1452 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1453 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1458 modest_ui_actions_on_paste (GtkAction *action,
1459 ModestWindow *window)
1461 GtkWidget *focused_widget;
1463 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1464 if (GTK_IS_EDITABLE (focused_widget)) {
1465 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1466 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1467 GtkTextBuffer *buffer;
1468 GtkClipboard *clipboard;
1470 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1471 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1472 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1477 modest_ui_actions_on_select_all (GtkAction *action,
1478 ModestWindow *window)
1480 GtkWidget *focused_widget;
1482 focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1483 if (GTK_IS_LABEL (focused_widget)) {
1484 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1485 } else if (GTK_IS_EDITABLE (focused_widget)) {
1486 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1487 } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1488 GtkTextBuffer *buffer;
1489 GtkTextIter start, end;
1491 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1492 gtk_text_buffer_get_start_iter (buffer, &start);
1493 gtk_text_buffer_get_end_iter (buffer, &end);
1494 gtk_text_buffer_select_range (buffer, &start, &end);
1499 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1500 GtkRadioAction *selected,
1501 ModestWindow *window)
1505 value = gtk_radio_action_get_current_value (selected);
1506 if (MODEST_IS_WINDOW (window)) {
1507 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1512 modest_ui_actions_on_toggle_fullscreen (GtkToggleAction *toggle,
1513 ModestWindow *window)
1515 g_return_if_fail (MODEST_IS_WINDOW (window));
1517 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle))) {
1518 gtk_window_fullscreen (GTK_WINDOW (window));
1520 gtk_window_unfullscreen (GTK_WINDOW (window));
1525 modest_ui_actions_message_details_cb (gpointer msg_data,
1526 gpointer helper_data)
1529 TnyMsg *msg = (TnyMsg *) msg_data;
1531 GetMsgAsyncHelper *helper = (GetMsgAsyncHelper *) helper_data;
1533 header = tny_msg_get_header (msg);
1535 dialog = modest_msg_view_details_dialog_new (GTK_WINDOW (helper->window), header);
1536 g_object_unref (header);
1537 gtk_widget_show_all (dialog);
1539 gtk_dialog_run (GTK_DIALOG (dialog));
1541 gtk_widget_destroy (dialog);
1545 modest_ui_actions_on_message_details (GtkAction *action,
1548 TnyList * headers_list;
1549 GetMsgAsyncHelper *helper;
1551 headers_list = get_selected_headers (win);
1555 helper = g_slice_new0 (GetMsgAsyncHelper);
1556 helper->window = win;
1557 helper->func = modest_ui_actions_message_details_cb;
1558 helper->iter = tny_list_create_iterator (headers_list);
1559 helper->user_data = NULL;
1561 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1564 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1568 modest_ui_actions_message_details_cb (msg, helper);
1571 /* here we should add an implementation to run the message details dialog
1572 from the main window */
1573 g_return_if_reached ();