If no header available and we have to show error fetching message, show
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
16  *
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.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-defs.h>
39 #include <modest-tny-folder.h>
40 #include <modest-tny-msg.h>
41 #include <modest-tny-account.h>
42 #include <modest-address-book.h>
43 #include "modest-error.h"
44 #include "modest-ui-actions.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-error.h>
50 #include <tny-camel-folder.h>
51 #include <tny-camel-imap-folder.h>
52 #include <tny-camel-pop-folder.h>
53 #ifdef MODEST_TOOLKIT_HILDON2
54 #include <modest-accounts-window.h>
55 #include <hildon/hildon-gtk.h>
56 #include <modest-header-window.h>
57 #include <modest-folder-window.h>
58 #include <modest-maemo-utils.h>
59 #endif
60 #include "modest-utils.h"
61 #include "widgets/modest-connection-specific-smtp-window.h"
62 #include "widgets/modest-ui-constants.h"
63 #include <widgets/modest-main-window.h>
64 #include <widgets/modest-msg-view-window.h>
65 #include <widgets/modest-account-view-window.h>
66 #include <widgets/modest-details-dialog.h>
67 #include <widgets/modest-attachments-view.h>
68 #include "widgets/modest-folder-view.h"
69 #include "widgets/modest-global-settings-dialog.h"
70 #include "modest-account-mgr-helpers.h"
71 #include "modest-mail-operation.h"
72 #include "modest-text-utils.h"
73 #include <modest-widget-memory.h>
74 #include <tny-error.h>
75 #include <tny-simple-list.h>
76 #include <tny-msg-view.h>
77 #include <tny-device.h>
78 #include <tny-merge-folder.h>
79
80 #include <gtkhtml/gtkhtml.h>
81
82 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
83
84 typedef struct _GetMsgAsyncHelper {
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         gchar *mailbox;
104         GtkWidget *parent_window;
105         TnyHeader *header;
106 } ReplyForwardHelper;
107
108 typedef struct _MoveToHelper {
109         GtkTreeRowReference *reference;
110         GtkWidget *banner;
111 } MoveToHelper;
112
113 typedef struct _PasteAsAttachmentHelper {
114         ModestMsgEditWindow *window;
115         GtkWidget *banner;
116 } PasteAsAttachmentHelper;
117
118 typedef struct {
119         TnyList *list;
120         ModestWindow *win;
121 } MoveToInfo;
122
123 /*
124  * The do_headers_action uses this kind of functions to perform some
125  * action to each member of a list of headers
126  */
127 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
128
129 static void     do_headers_action     (ModestWindow *win,
130                                        HeadersFunc func,
131                                        gpointer user_data);
132
133 static void     open_msg_cb            (ModestMailOperation *mail_op,
134                                         TnyHeader *header,
135                                         gboolean canceled,
136                                         TnyMsg *msg,
137                                         GError *err,
138                                         gpointer user_data);
139
140 static void     reply_forward_cb       (ModestMailOperation *mail_op,
141                                         TnyHeader *header,
142                                         gboolean canceled,
143                                         TnyMsg *msg,
144                                         GError *err,
145                                         gpointer user_data);
146
147 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
148
149 #ifndef MODEST_TOOLKIT_HILDON2
150 static void     folder_refreshed_cb    (ModestMailOperation *mail_op,
151                                         TnyFolder *folder,
152                                         gpointer user_data);
153
154 static void     on_send_receive_finished (ModestMailOperation  *mail_op,
155                                           gpointer user_data);
156 #endif
157
158 static gint header_list_count_uncached_msgs (TnyList *header_list);
159
160 static gboolean connect_to_get_msg (ModestWindow *win,
161                                     gint num_of_uncached_msgs,
162                                     TnyAccount *account);
163
164 static gboolean remote_folder_has_leave_on_server (TnyFolderStore *folder);
165
166 static void     do_create_folder (GtkWindow *window,
167                                   TnyFolderStore *parent_folder,
168                                   const gchar *suggested_name);
169
170 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
171
172 #ifndef MODEST_TOOLKIT_HILDON2
173 static void modest_ui_actions_on_main_window_move_to (GtkAction *action,
174                                                       GtkWidget *folder_view,
175                                                       TnyFolderStore *dst_folder,
176                                                       ModestMainWindow *win);
177
178 #else
179 static void modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
180                                                         TnyFolderStore *dst_folder,
181                                                         TnyList *selection,
182                                                         GtkWindow *win);
183 #endif
184
185 static void modest_ui_actions_on_window_move_to (GtkAction *action,
186                                                  TnyList *list_to_move,
187                                                  TnyFolderStore *dst_folder,
188                                                  ModestWindow *win);
189
190 /*
191  * This function checks whether a TnyFolderStore is a pop account
192  */
193 static gboolean
194 remote_folder_has_leave_on_server (TnyFolderStore *folder)
195 {
196         TnyAccount *account;
197         gboolean result;
198
199         g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
200
201         account = get_account_from_folder_store (folder);
202         result = (modest_protocol_registry_protocol_type_has_leave_on_server (modest_runtime_get_protocol_registry (),
203                                                                               modest_tny_account_get_protocol_type (account)));
204         g_object_unref (account);
205
206         return result;
207 }
208
209 /* FIXME: this should be merged with the similar code in modest-account-view-window */
210 /* Show the account creation wizard dialog.
211  * returns: TRUE if an account was created. FALSE if the user cancelled.
212  */
213 gboolean
214 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
215 {
216         gboolean result = FALSE;
217         GtkWindow *wizard;
218         gint dialog_response;
219
220         /* there is no such wizard yet */
221         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
222         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (wizard), (GtkWindow *) win);
223
224 #ifndef MODEST_TOOLKIT_HILDON2
225         /* always present a main window in the background
226          * we do it here, so we cannot end up with two wizards (as this
227          * function might be called in modest_window_mgr_get_main_window as well */
228         if (!win)
229                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
230                                                          TRUE);  /* create if not existent */
231 #else
232         if (!win) {
233                 GList *window_list;
234                 ModestWindowMgr *mgr;
235
236                 mgr = modest_runtime_get_window_mgr ();
237
238                 window_list = modest_window_mgr_get_window_list (mgr);
239                 if (window_list == NULL) {
240                         win = MODEST_WINDOW (modest_accounts_window_new ());
241                         if (modest_window_mgr_register_window (mgr, win, NULL)) {
242                                 gtk_widget_show_all (GTK_WIDGET (win));
243                         } else {
244                                 gtk_widget_destroy (GTK_WIDGET (win));
245                                 win = NULL;
246                         }
247
248                 } else {
249                         g_list_free (window_list);
250                 }
251         }
252 #endif
253
254         if (win)
255                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
256
257         /* make sure the mainwindow is visible. We need to present the
258            wizard again to give it the focus back. show_all are needed
259            in order to get the widgets properly drawn (MainWindow main
260            paned won't be in its right position and the dialog will be
261            missplaced */
262 #ifndef MODEST_TOOLKIT_HILDON2
263         gtk_widget_show_all (GTK_WIDGET (win));
264         gtk_widget_show_all (GTK_WIDGET (wizard));
265         gtk_window_present (GTK_WINDOW (win));
266         gtk_window_present (GTK_WINDOW (wizard));
267 #endif
268
269         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
270         gtk_widget_destroy (GTK_WIDGET (wizard));
271         if (gtk_events_pending ())
272                 gtk_main_iteration ();
273
274         if (dialog_response == GTK_RESPONSE_CANCEL) {
275                 result = FALSE;
276         } else {
277                 /* Check whether an account was created: */
278                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
279         }
280         return result;
281 }
282
283
284 void
285 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
286 {
287         GtkWidget *about;
288         const gchar *authors[] = {
289                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
290                 NULL
291         };
292         about = gtk_about_dialog_new ();
293         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
294         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
295         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
296                                         _("Copyright (c) 2006, Nokia Corporation\n"
297                                           "All rights reserved."));
298         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
299                                        _("a modest e-mail client\n\n"
300                                          "design and implementation: Dirk-Jan C. Binnema\n"
301                                          "contributions from the fine people at KC and Ig\n"
302                                          "uses the tinymail email framework written by Philip van Hoof"));
303         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
304         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
305         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
306         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
307
308         gtk_dialog_run (GTK_DIALOG (about));
309         gtk_widget_destroy(about);
310 }
311
312 /*
313  * Gets the list of currently selected messages. If the win is the
314  * main window, then it returns a newly allocated list of the headers
315  * selected in the header view. If win is the msg view window, then
316  * the value returned is a list with just a single header.
317  *
318  * The caller of this funcion must free the list.
319  */
320 static TnyList *
321 get_selected_headers (ModestWindow *win)
322 {
323         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
324                 /* for MsgViewWindows, we simply return a list with one element */
325                 TnyHeader *header;
326                 TnyList *list = NULL;
327
328                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
329                 if (header != NULL) {
330                         list = tny_simple_list_new ();
331                         tny_list_prepend (list, G_OBJECT(header));
332                         g_object_unref (G_OBJECT(header));
333                 }
334
335                 return list;
336 #ifndef MODEST_TOOLKIT_HILDON2
337         } else if (MODEST_IS_MAIN_WINDOW(win)) {
338                 GtkWidget *header_view;
339
340                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
341                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
342                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
343 #else
344         } else if (MODEST_IS_HEADER_WINDOW (win)) {
345                 GtkWidget *header_view;
346
347                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
348                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
349 #endif
350         } else {
351                 return NULL;
352         }
353 }
354
355 #ifndef MODEST_TOOLKIT_HILDON2
356 static GtkTreeRowReference *
357 get_next_after_selected_headers (ModestHeaderView *header_view)
358 {
359         GtkTreeSelection *sel;
360         GList *selected_rows, *node;
361         GtkTreePath *path;
362         GtkTreeRowReference *result;
363         GtkTreeModel *model;
364
365         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
366         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
367         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
368
369         if (selected_rows == NULL)
370                 return NULL;
371
372         node = g_list_last (selected_rows);
373         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
374         gtk_tree_path_next (path);
375
376         result = gtk_tree_row_reference_new (model, path);
377
378         gtk_tree_path_free (path);
379         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
380         g_list_free (selected_rows);
381
382         return result;
383 }
384 #endif
385
386 static void
387 headers_action_mark_as_read (TnyHeader *header,
388                              ModestWindow *win,
389                              gpointer user_data)
390 {
391         TnyHeaderFlags flags;
392
393         g_return_if_fail (TNY_IS_HEADER(header));
394
395         flags = tny_header_get_flags (header);
396         if (flags & TNY_HEADER_FLAG_SEEN) return;
397         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
398 }
399
400 static void
401 headers_action_mark_as_unread (TnyHeader *header,
402                                ModestWindow *win,
403                                gpointer user_data)
404 {
405         TnyHeaderFlags flags;
406
407         g_return_if_fail (TNY_IS_HEADER(header));
408
409         flags = tny_header_get_flags (header);
410         if (flags & TNY_HEADER_FLAG_SEEN)  {
411                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
412         }
413 }
414
415 /** After deleing a message that is currently visible in a window,
416  * show the next message from the list, or close the window if there are no more messages.
417  **/
418 void
419 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
420 {
421         /* Close msg view window or select next */
422         if (!modest_msg_view_window_select_next_message (win) &&
423             !modest_msg_view_window_select_previous_message (win)) {
424                 gboolean ret_value;
425                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
426         }
427 }
428
429
430 void
431 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
432 {
433         modest_ui_actions_on_edit_mode_delete_message (win);
434 }
435
436 gboolean
437 modest_ui_actions_on_edit_mode_delete_message (ModestWindow *win)
438 {
439         TnyList *header_list = NULL;
440         TnyIterator *iter = NULL;
441         TnyHeader *header = NULL;
442         gchar *message = NULL;
443         gchar *desc = NULL;
444         gint response;
445         ModestWindowMgr *mgr;
446         gboolean retval = TRUE;
447
448         g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
449
450 #ifndef MODEST_TOOLKIT_HILDON2
451         /* Check first if the header view has the focus */
452         if (MODEST_IS_MAIN_WINDOW (win)) {
453                 GtkWidget *header_view = NULL;
454
455                 header_view =
456                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
457                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
458                 if (!gtk_widget_is_focus (header_view))
459                         return FALSE;
460         }
461 #endif
462         /* Get the headers, either from the header view (if win is the main window),
463          * or from the message view window: */
464         header_list = get_selected_headers (win);
465         if (!header_list) return FALSE;
466
467         /* Check if any of the headers are already opened, or in the process of being opened */
468 #ifndef MODEST_TOOLKIT_HILDON2
469         if (MODEST_IS_MAIN_WINDOW (win)) {
470                 gint opened_headers = 0;
471
472                 iter = tny_list_create_iterator (header_list);
473                 mgr = modest_runtime_get_window_mgr ();
474                 while (!tny_iterator_is_done (iter)) {
475                         header = TNY_HEADER (tny_iterator_get_current (iter));
476                         if (header) {
477                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
478                                         opened_headers++;
479                                 g_object_unref (header);
480                         }
481                         tny_iterator_next (iter);
482                 }
483                 g_object_unref (iter);
484
485                 if (opened_headers > 0) {
486                         gchar *msg;
487
488                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
489                                                opened_headers);
490
491                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
492
493                         g_free (msg);
494                         g_object_unref (header_list);
495                         return FALSE;
496                 }
497         }
498 #endif
499
500         /* Select message */
501         if (tny_list_get_length(header_list) == 1) {
502                 iter = tny_list_create_iterator (header_list);
503                 header = TNY_HEADER (tny_iterator_get_current (iter));
504                 if (header) {
505                         gchar *subject;
506                         subject = tny_header_dup_subject (header);
507                         if (!subject)
508                                 subject = g_strdup (_("mail_va_no_subject"));
509                         desc = g_strdup_printf ("%s", subject);
510                         g_free (subject);
511                         g_object_unref (header);
512                 }
513
514                 g_object_unref (iter);
515         }
516         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
517                                            tny_list_get_length(header_list)), desc);
518
519         /* Confirmation dialog */
520         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
521                                                             message);
522
523         if (response == GTK_RESPONSE_OK) {
524                 GtkTreeSelection *sel = NULL;
525                 GList *sel_list = NULL;
526                 ModestMailOperation *mail_op = NULL;
527
528                 /* Find last selected row */
529 #ifndef MODEST_TOOLKIT_HILDON2
530                 if (MODEST_IS_MAIN_WINDOW (win)) {
531                         GList *tmp = NULL;
532                         ModestWindowMgr *mgr = NULL;
533                         GtkTreeModel *model = NULL;
534                         GtkTreeRowReference *next_row_reference = NULL, *prev_row_reference = NULL;
535                         GtkTreePath *next_path = NULL, *prev_path = NULL;
536
537                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
538                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
539                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
540                         for (tmp=sel_list; tmp; tmp=tmp->next) {
541                                 if (tmp->next == NULL) {
542                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
543                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
544
545                                         gtk_tree_path_prev (prev_path);
546                                         gtk_tree_path_next (next_path);
547
548                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
549                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
550                                 }
551                         }
552                 }
553 #endif
554
555                 /* Disable window dimming management */
556                 modest_window_disable_dimming (win);
557
558                 /* Remove each header. If it's a view window header_view == NULL */
559                 mail_op = modest_mail_operation_new ((GObject *) win);
560                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
561                                                  mail_op);
562                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
563                 g_object_unref (mail_op);
564
565                 /* Enable window dimming management */
566                 if (sel != NULL) {
567                         gtk_tree_selection_unselect_all (sel);
568                 }
569                 modest_window_enable_dimming (win);
570
571                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
572                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
573
574                         /* Get main window */
575                         mgr = modest_runtime_get_window_mgr ();
576 #ifndef MODEST_TOOLKIT_HILDON2
577                 } else if (MODEST_IS_MAIN_WINDOW (win)) {
578                         /* Select next or previous row */
579                         if (gtk_tree_row_reference_valid (next_row_reference)) {
580                                 gtk_tree_selection_select_path (sel, next_path);
581                         }
582                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {
583                                 gtk_tree_selection_select_path (sel, prev_path);
584                         }
585
586                         /* Free */
587                         if (gtk_tree_row_reference_valid (next_row_reference))
588                                 gtk_tree_row_reference_free (next_row_reference);
589                         if (next_path != NULL)
590                                 gtk_tree_path_free (next_path);
591                         if (gtk_tree_row_reference_valid (prev_row_reference))
592                                 gtk_tree_row_reference_free (prev_row_reference);
593                         if (prev_path != NULL)
594                                 gtk_tree_path_free (prev_path);
595 #endif
596                 }
597
598                 /* Update toolbar dimming state */
599                 modest_ui_actions_check_menu_dimming_rules (win);
600                 modest_ui_actions_check_toolbar_dimming_rules (win);
601
602                 /* Free */
603                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
604                 g_list_free (sel_list);
605                 retval = TRUE;
606         } else {
607                 retval = FALSE;
608         }
609
610         /* Free*/
611         g_free(message);
612         g_free(desc);
613         g_object_unref (header_list);
614
615         return retval;
616 }
617
618
619
620
621 /* delete either message or folder, based on where we are */
622 void
623 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
624 {
625         g_return_if_fail (MODEST_IS_WINDOW(win));
626
627         /* Check first if the header view has the focus */
628 #ifndef MODEST_TOOLKIT_HILDON2
629         if (MODEST_IS_MAIN_WINDOW (win)) {
630                 GtkWidget *w;
631                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
632                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
633                 if (gtk_widget_is_focus (w)) {
634                         modest_ui_actions_on_delete_folder (action, MODEST_WINDOW(win));
635                         return;
636                 }
637         }
638 #endif
639         modest_ui_actions_on_delete_message (action, win);
640 }
641
642 void
643 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
644 {
645         ModestWindowMgr *mgr = NULL;
646
647 #ifdef MODEST_PLATFORM_MAEMO
648         modest_window_mgr_save_state_for_all_windows (modest_runtime_get_window_mgr ());
649 #endif /* MODEST_PLATFORM_MAEMO */
650
651         g_debug ("closing down, clearing %d item(s) from operation queue",
652                  modest_mail_operation_queue_num_elements
653                  (modest_runtime_get_mail_operation_queue()));
654
655         /* cancel all outstanding operations */
656         modest_mail_operation_queue_cancel_all
657                 (modest_runtime_get_mail_operation_queue());
658
659         g_debug ("queue has been cleared");
660
661
662         /* Check if there are opened editing windows */
663         mgr = modest_runtime_get_window_mgr ();
664         modest_window_mgr_close_all_windows (mgr);
665
666         /* note: when modest-tny-account-store is finalized,
667            it will automatically set all network connections
668            to offline */
669
670 /*      gtk_main_quit (); */
671 }
672
673 void
674 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
675 {
676         gboolean ret_value;
677
678         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
679
680 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
681 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
682 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
683 /*              gboolean ret_value; */
684 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
685 /*      } else if (MODEST_IS_WINDOW (win)) { */
686 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
687 /*      } else { */
688 /*              g_return_if_reached (); */
689 /*      } */
690 }
691
692 void
693 modest_ui_actions_add_to_contacts (GtkAction *action, ModestWindow *win)
694 {
695         if (MODEST_IS_MSG_VIEW_WINDOW (win))
696                 modest_msg_view_window_add_to_contacts (MODEST_MSG_VIEW_WINDOW (win));
697         else if (MODEST_IS_MSG_EDIT_WINDOW (win))
698                 modest_msg_edit_window_add_to_contacts (MODEST_MSG_EDIT_WINDOW (win));
699 }
700
701 void
702 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
703 {
704         GtkClipboard *clipboard = NULL;
705         gchar *selection = NULL;
706
707         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
708         selection = gtk_clipboard_wait_for_text (clipboard);
709
710         if (selection) {
711                 modest_address_book_add_address (selection, (GtkWindow *) win);
712                 g_free (selection);
713         }
714 }
715
716 void
717 modest_ui_actions_on_new_account (GtkAction *action,
718                                   ModestWindow *window)
719 {
720         if (!modest_ui_actions_run_account_setup_wizard (window)) {
721                 g_debug ("%s: wizard was already running", __FUNCTION__);
722         }
723 }
724
725 void
726 modest_ui_actions_on_accounts (GtkAction *action,
727                                ModestWindow *win)
728 {
729         /* This is currently only implemented for Maemo */
730         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
731                 if (!modest_ui_actions_run_account_setup_wizard (win))
732                         g_debug ("%s: wizard was already running", __FUNCTION__);
733
734                 return;
735         } else {
736                 /* Show the list of accounts */
737                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
738
739                 /* The accounts dialog must be modal */
740                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (account_win), (GtkWindow *) win);
741                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
742         }
743 }
744
745 void
746 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
747 {
748         /* This is currently only implemented for Maemo,
749          * because it requires an API (libconic) to detect different connection
750          * possiblities.
751          */
752 #ifndef MODEST_TOOLKIT_GTK /* Defined in config.h */
753
754         /* Create the window if necessary: */
755         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
756         modest_connection_specific_smtp_window_fill_with_connections (
757                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
758                 modest_runtime_get_account_mgr());
759
760         /* Show the window: */
761         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
762                                      GTK_WINDOW (specific_window), (GtkWindow *) win);
763         gtk_widget_show (specific_window);
764 #endif /* !MODEST_TOOLKIT_GTK */
765 }
766
767 static guint64
768 count_part_size (const gchar *part)
769 {
770         GnomeVFSURI *vfs_uri;
771         gchar *escaped_filename;
772         gchar *filename;
773         GnomeVFSFileInfo *info;
774         guint64 result;
775
776         /* Estimation of attachment size if we cannot get it from file info */
777         result = 32768;
778
779         vfs_uri = gnome_vfs_uri_new (part);
780
781         escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
782         filename = gnome_vfs_unescape_string_for_display (escaped_filename);
783         g_free (escaped_filename);
784         gnome_vfs_uri_unref (vfs_uri);
785
786         info = gnome_vfs_file_info_new ();
787         
788         if (gnome_vfs_get_file_info (part, 
789                                      info, 
790                                      GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
791             == GNOME_VFS_OK) {
792                 if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
793                         result = info->size;
794                 }
795         }
796         g_free (filename);
797         gnome_vfs_file_info_unref (info);
798
799         return result;
800 }
801
802 static guint64 
803 count_parts_size (GSList *parts)
804 {
805         GSList *node;
806         guint64 result = 0;
807
808         for (node = parts; node != NULL; node = g_slist_next (node)) {
809                 result += count_part_size ((const gchar *) node->data);
810         }
811
812         return result;
813 }
814
815 void
816 modest_ui_actions_compose_msg(ModestWindow *win,
817                               const gchar *to_str,
818                               const gchar *cc_str,
819                               const gchar *bcc_str,
820                               const gchar *subject_str,
821                               const gchar *body_str,
822                               GSList *attachments,
823                               gboolean set_as_modified)
824 {
825         gchar *account_name = NULL;
826         const gchar *mailbox;
827         TnyMsg *msg = NULL;
828         TnyAccount *account = NULL;
829         TnyFolder *folder = NULL;
830         gchar *from_str = NULL, *signature = NULL, *body = NULL;
831         gchar *recipient = NULL;
832         gboolean use_signature = FALSE;
833         ModestWindow *msg_win = NULL;
834         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
835         ModestTnyAccountStore *store = modest_runtime_get_account_store();
836         GnomeVFSFileSize total_size, allowed_size;
837         guint64 available_disk, expected_size, parts_size;
838         guint parts_count;
839
840         /* we check for low-mem */
841         if (modest_platform_check_memory_low (win, TRUE))
842                 goto cleanup;
843
844         available_disk = modest_utils_get_available_space (NULL);
845         parts_count = g_slist_length (attachments);
846         parts_size = count_parts_size (attachments);
847         expected_size = modest_tny_msg_estimate_size (body, NULL, parts_count, parts_size);
848
849         /* Double check: disk full condition or message too big */
850         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
851             expected_size > available_disk) {
852                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
853                 modest_platform_system_banner (NULL, NULL, msg);
854                 g_free (msg);
855
856                 return;
857         }
858
859         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
860                 modest_platform_run_information_dialog (
861                         GTK_WINDOW(win),
862                         _("mail_ib_error_attachment_size"),
863                         TRUE);
864                 return;
865         }
866
867
868 #ifdef MODEST_TOOLKIT_HILDON2
869         if (win)
870                 account_name = g_strdup (modest_window_get_active_account(win));
871 #endif
872         if (!account_name) {
873                 account_name = modest_account_mgr_get_default_account(mgr);
874         }
875         if (!account_name) {
876                 g_printerr ("modest: no account found\n");
877                 goto cleanup;
878         }
879
880         if (win)
881                 mailbox = modest_window_get_active_mailbox (win);
882         else
883                 mailbox = NULL;
884         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
885         if (!account) {
886                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
887                 goto cleanup;
888         }
889         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
890         if (!folder) {
891                 g_printerr ("modest: failed to find Drafts folder\n");
892                 goto cleanup;
893         }
894         from_str = modest_account_mgr_get_from_string (mgr, account_name, mailbox);
895         if (!from_str) {
896                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
897                 goto cleanup;
898         }
899
900         recipient = modest_text_utils_get_email_address (from_str);
901         signature = modest_account_mgr_get_signature_from_recipient (mgr, recipient, &use_signature);
902         g_free (recipient);
903         if (body_str != NULL) {
904                 body = use_signature ? g_strconcat(body_str, "\n",
905                                                    MODEST_TEXT_UTILS_SIGNATURE_MARKER,
906                                                    "\n", signature, NULL) : g_strdup(body_str);
907         } else {
908                 body = use_signature ? g_strconcat("\n", MODEST_TEXT_UTILS_SIGNATURE_MARKER,
909                                                    "\n", signature, NULL) : g_strdup("");
910         }
911
912         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, NULL, NULL, body, NULL, NULL, NULL);
913         if (!msg) {
914                 g_printerr ("modest: failed to create new msg\n");
915                 goto cleanup;
916         }
917
918         /* Create and register edit window */
919         /* This is destroyed by TODO. */
920         total_size = 0;
921         allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
922         msg_win = modest_msg_edit_window_new (msg, account_name, mailbox, FALSE);
923
924         if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, win)) {
925                 gtk_widget_destroy (GTK_WIDGET (msg_win));
926                 goto cleanup;
927         }
928         modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
929         gtk_widget_show_all (GTK_WIDGET (msg_win));
930
931         while (attachments) {
932                 GnomeVFSFileSize att_size;
933                 att_size =
934                         modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
935                                                                attachments->data, allowed_size);
936                 total_size += att_size;
937
938                 if (att_size > allowed_size) {
939                         g_debug ("%s: total size: %u",
940                                  __FUNCTION__, (unsigned int)total_size);
941                         break;
942                 }
943                 allowed_size -= att_size;
944
945                 attachments = g_slist_next(attachments);
946         }
947
948 cleanup:
949         g_free (from_str);
950         g_free (signature);
951         g_free (body);
952         g_free (account_name);
953         if (account)
954                 g_object_unref (G_OBJECT(account));
955         if (folder)
956                 g_object_unref (G_OBJECT(folder));
957         if (msg)
958                 g_object_unref (G_OBJECT(msg));
959 }
960
961 void
962 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
963 {
964         /* if there are no accounts yet, just show the wizard */
965         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
966                 if (!modest_ui_actions_run_account_setup_wizard (win))
967                         return;
968
969         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
970 }
971
972
973 gboolean
974 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
975                                        TnyHeader *header,
976                                        TnyMsg *msg)
977 {
978         ModestMailOperationStatus status;
979
980         /* If there is no message or the operation was not successful */
981         status = modest_mail_operation_get_status (mail_op);
982         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
983                 const GError *error;
984
985                 /* If it's a memory low issue, then show a banner */
986                 error = modest_mail_operation_get_error (mail_op);
987                 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
988                     error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
989                         GObject *source = modest_mail_operation_get_source (mail_op);
990                         modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
991                                                                 _KR("memr_ib_operation_disabled"),
992                                                                 TRUE);
993                         g_object_unref (source);
994                 }
995
996                 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
997                               error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
998                         gchar *subject, *msg, *format = NULL;
999                         TnyAccount *account;
1000
1001                         subject = (header) ? tny_header_dup_subject (header) : NULL;
1002                         if (!subject)
1003                                 subject = g_strdup (_("mail_va_no_subject"));
1004
1005                         account = modest_mail_operation_get_account (mail_op);
1006                         if (account) {
1007                                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
1008                                 ModestProtocol *protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), proto);
1009
1010                                 if (protocol) {
1011                                         if (tny_account_get_connection_status (account) ==
1012                                             TNY_CONNECTION_STATUS_CONNECTED) {
1013                                                 if (header) {
1014                                                         format = modest_protocol_get_translation (protocol,
1015                                                                                                   MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE,
1016                                                                                                   subject);
1017                                                 } else {
1018                                                         format = modest_protocol_get_translation (protocol,
1019                                                                                                   MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE_LOST_HEADER);
1020                                                 }
1021                                         } else {
1022                                                 format = g_strdup_printf (_("mail_ib_backend_server_invalid"),
1023                                                                           tny_account_get_hostname (account));
1024                                         }
1025                                 }
1026                                 g_object_unref (account);
1027                         }
1028
1029                         if (!format)
1030                                 format = g_strdup (_("emev_ni_ui_imap_message_not_available_in_server"));
1031
1032                         msg = g_strdup_printf (format, subject);
1033                         modest_platform_run_information_dialog (NULL, msg, FALSE);
1034                         g_free (msg);
1035                         g_free (format);
1036                         g_free (subject);
1037                 }
1038
1039                 /* Remove the header from the preregistered uids */
1040                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1041                                                      header);
1042
1043                 return FALSE;
1044         }
1045
1046         return TRUE;
1047 }
1048
1049 typedef struct {
1050         guint idle_handler;
1051         gchar *message;
1052         GtkWidget *banner;
1053 } OpenMsgBannerInfo;
1054
1055 typedef struct {
1056         GtkTreeModel *model;
1057         TnyHeader *header;
1058         ModestWindow *caller_window;
1059         OpenMsgBannerInfo *banner_info;
1060         GtkTreeRowReference *rowref;
1061 } OpenMsgHelper;
1062
1063 gboolean
1064 open_msg_banner_idle (gpointer userdata)
1065 {
1066         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
1067
1068         gdk_threads_enter ();
1069         banner_info->idle_handler = 0;
1070         banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
1071         if (banner_info->banner)
1072                 g_object_ref (banner_info->banner);
1073
1074         gdk_threads_leave ();
1075
1076         return FALSE;
1077 }
1078
1079 static GtkWidget *
1080 get_header_view_from_window (ModestWindow *window)
1081 {
1082         GtkWidget *header_view;
1083
1084 #ifndef MODEST_TOOLKIT_HILDON2
1085         if (MODEST_IS_MAIN_WINDOW (window)) {
1086                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
1087                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1088 #else
1089         if (MODEST_IS_HEADER_WINDOW (window)){
1090                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
1091 #endif
1092         } else {
1093                 header_view = NULL;
1094         }
1095
1096         return header_view;
1097 }
1098
1099 static gchar *
1100 get_info_from_header (TnyHeader *header, gboolean *is_draft, gboolean *can_open)
1101 {
1102         TnyFolder *folder;
1103         gchar *account = NULL;
1104         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1105
1106         *is_draft = FALSE;
1107         *can_open = TRUE;
1108
1109         folder = tny_header_get_folder (header);
1110         /* Gets folder type (OUTBOX headers will be opened in edit window */
1111         if (modest_tny_folder_is_local_folder (folder)) {
1112                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1113                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1114                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1115         }
1116
1117         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1118                 TnyTransportAccount *traccount = NULL;
1119                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
1120                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
1121                 if (traccount) {
1122                         ModestTnySendQueue *send_queue = NULL;
1123                         ModestTnySendQueueStatus status;
1124                         gchar *msg_id;
1125                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
1126                                                    TNY_ACCOUNT(traccount)));
1127                         send_queue = modest_runtime_get_send_queue(traccount, TRUE);
1128                         if (TNY_IS_SEND_QUEUE (send_queue)) {
1129                                 msg_id = modest_tny_send_queue_get_msg_id (header);
1130                                 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
1131                                 g_free (msg_id);
1132                                 /* Only open messages in outbox with the editor if they are in Failed state */
1133                                 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
1134                                         *is_draft = TRUE;
1135                                 }
1136 #ifdef MODEST_TOOLKIT_HILDON2
1137                                 else {
1138                                         /* In Fremantle we can not
1139                                            open any message from
1140                                            outbox which is not in
1141                                            failed state */
1142                                         *can_open = FALSE;
1143                                 }
1144 #endif
1145                         }
1146                         g_object_unref(traccount);
1147                 } else {
1148                         g_warning("Cannot get transport account for message in outbox!!");
1149                 }
1150         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
1151                 *is_draft = TRUE; /* Open in editor if the message is in the Drafts folder */
1152         }
1153
1154         if (!account) {
1155                 TnyAccount *acc = tny_folder_get_account (folder);
1156                 if (acc) {
1157                         account =
1158                                 g_strdup (modest_tny_account_get_parent_modest_account_name_for_server_account (acc));
1159                         g_object_unref (acc);
1160                 }
1161         }
1162
1163         g_object_unref (folder);
1164
1165         return account;
1166 }
1167
1168 static void
1169 open_msg_cb (ModestMailOperation *mail_op,
1170              TnyHeader *header,
1171              gboolean canceled,
1172              TnyMsg *msg,
1173              GError *err,
1174              gpointer user_data)
1175 {
1176         ModestWindowMgr *mgr = NULL;
1177         ModestWindow *parent_win = NULL;
1178         ModestWindow *win = NULL;
1179         gchar *account = NULL;
1180         gboolean open_in_editor = FALSE;
1181         gboolean can_open;
1182         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1183
1184         /* Do nothing if there was any problem with the mail
1185            operation. The error will be shown by the error_handler of
1186            the mail operation */
1187         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1188                 return;
1189
1190         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
1191
1192         /* Mark header as read */
1193         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
1194
1195         account = get_info_from_header (header, &open_in_editor, &can_open);
1196
1197         /* Get account */
1198         if (!account)
1199                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
1200         if (!account)
1201                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1202
1203         if (open_in_editor) {
1204                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
1205                 gchar *from_header = NULL, *acc_name;
1206                 gchar *mailbox = NULL;
1207
1208                 from_header = tny_header_dup_from (header);
1209
1210                 /* we cannot edit without a valid account... */
1211                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
1212                         if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
1213                                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1214                                                                      header);
1215                                 g_free (from_header);
1216                                 goto cleanup;
1217                         }
1218                 }
1219
1220                 acc_name = modest_utils_get_account_name_from_recipient (from_header, &mailbox);
1221                 g_free (from_header);
1222                 if (acc_name) {
1223                         g_free (account);
1224                         account = acc_name;
1225                 }
1226
1227                 win = modest_msg_edit_window_new (msg, account, mailbox, TRUE);
1228                 if (mailbox)
1229                         g_free (mailbox);
1230         } else {
1231                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
1232                 const gchar *mailbox = NULL;
1233
1234                 if (parent_win && MODEST_IS_WINDOW (parent_win))
1235                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_win));
1236
1237                 if (helper->rowref && helper->model) {
1238                         win = modest_msg_view_window_new_with_header_model (msg, account, mailbox, (const gchar*) uid,
1239                                                                             helper->model, helper->rowref);
1240                 } else {
1241                         win = modest_msg_view_window_new_for_attachment (msg, account, mailbox, (const gchar*) uid);
1242                 }
1243                 g_free (uid);
1244         }
1245
1246         /* Register and show new window */
1247         if (win != NULL) {
1248                 mgr = modest_runtime_get_window_mgr ();
1249                 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1250                         gtk_widget_destroy (GTK_WIDGET (win));
1251                         goto cleanup;
1252                 }
1253                 gtk_widget_show_all (GTK_WIDGET(win));
1254         }
1255
1256 #ifndef MODEST_TOOLKIT_HILDON2
1257         /* Update toolbar dimming state */
1258         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1259                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1260         }
1261 #endif
1262
1263 cleanup:
1264         /* Free */
1265         g_free(account);
1266         g_object_unref (parent_win);
1267 }
1268
1269 void
1270 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1271                                                  gpointer user_data)
1272 {
1273         const GError *error;
1274         GObject *win = NULL;
1275         ModestMailOperationStatus status;
1276
1277         win = modest_mail_operation_get_source (mail_op);
1278         error = modest_mail_operation_get_error (mail_op);
1279         status = modest_mail_operation_get_status (mail_op);
1280
1281         /* If the mail op has been cancelled then it's not an error:
1282            don't show any message */
1283         if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1284                 TnyAccount *account = modest_mail_operation_get_account (mail_op);
1285                 if (modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
1286                                                                  (GError *) error, account)) {
1287                         gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
1288                         modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
1289                         g_free (msg);
1290                 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1291                         modest_platform_information_banner ((GtkWidget *) win,
1292                                                             NULL, _("emev_ui_imap_inbox_select_error"));
1293                 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1294                            error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1295                         modest_platform_information_banner ((GtkWidget *) win,
1296                                                             NULL, _CS ("sfil_ni_unable_to_open_file_not_found"));
1297                 } else if (user_data) {
1298                         modest_platform_information_banner ((GtkWidget *) win,
1299                                                             NULL, user_data);
1300                 }
1301                 if (account)
1302                         g_object_unref (account);
1303         }
1304
1305         if (win)
1306                 g_object_unref (win);
1307 }
1308
1309 /**
1310  * Returns the account a list of headers belongs to. It returns a
1311  * *new* reference so don't forget to unref it
1312  */
1313 static TnyAccount*
1314 get_account_from_header_list (TnyList *headers)
1315 {
1316         TnyAccount *account = NULL;
1317
1318         if (tny_list_get_length (headers) > 0) {
1319                 TnyIterator *iter = tny_list_create_iterator (headers);
1320                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1321                 TnyFolder *folder = tny_header_get_folder (header);
1322
1323                 if (!folder) {
1324                         g_object_unref (header);
1325
1326                         while (!tny_iterator_is_done (iter)) {
1327                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1328                                 folder = tny_header_get_folder (header);
1329                                 if (folder)
1330                                         break;
1331                                 g_object_unref (header);
1332                                 header = NULL;
1333                                 tny_iterator_next (iter);
1334                         }
1335                 }
1336
1337                 if (folder) {
1338                         account = tny_folder_get_account (folder);
1339                         g_object_unref (folder);
1340                 }
1341
1342                 if (header)
1343                         g_object_unref (header);
1344
1345                 g_object_unref (iter);
1346         }
1347         return account;
1348 }
1349
1350 static TnyAccount*
1351 get_account_from_header (TnyHeader *header)
1352 {
1353         TnyAccount *account = NULL;
1354         TnyFolder *folder;
1355
1356         folder = tny_header_get_folder (header);
1357
1358         if (folder) {
1359                 account = tny_folder_get_account (folder);
1360                 g_object_unref (folder);
1361         }
1362         return account;
1363 }
1364
1365 static void
1366 caller_win_destroyed (OpenMsgHelper *helper, GObject *object)
1367 {
1368         if (helper->caller_window)
1369                 helper->caller_window = NULL;
1370 }
1371
1372 static void
1373 open_msg_helper_destroyer (gpointer user_data)
1374 {
1375         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1376
1377         if (helper->caller_window) {
1378                 g_object_weak_unref ((GObject *) helper->caller_window, (GWeakNotify) caller_win_destroyed, helper);
1379                 helper->caller_window = NULL;
1380         }
1381
1382         if (helper->banner_info) {
1383                 g_free (helper->banner_info->message);
1384                 if (helper->banner_info->idle_handler > 0) {
1385                         g_source_remove (helper->banner_info->idle_handler);
1386                         helper->banner_info->idle_handler = 0;
1387                 }
1388                 if (helper->banner_info->banner != NULL) {
1389                         gtk_widget_destroy (helper->banner_info->banner);
1390                         g_object_unref (helper->banner_info->banner);
1391                         helper->banner_info->banner = NULL;
1392                 }
1393                 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1394                 helper->banner_info = NULL;
1395         }
1396         g_object_unref (helper->model);
1397         g_object_unref (helper->header);
1398         gtk_tree_row_reference_free (helper->rowref);
1399         g_slice_free (OpenMsgHelper, helper);
1400 }
1401
1402 static void
1403 open_msg_performer(gboolean canceled,
1404                     GError *err,
1405                     GtkWindow *parent_window,
1406                     TnyAccount *account,
1407                     gpointer user_data)
1408 {
1409         ModestMailOperation *mail_op = NULL;
1410         gchar *error_msg = NULL;
1411         ModestProtocolType proto;
1412         TnyConnectionStatus status;
1413         OpenMsgHelper *helper = NULL;
1414         ModestProtocol *protocol;
1415         ModestProtocolRegistry *protocol_registry;
1416         gchar *subject;
1417
1418         helper = (OpenMsgHelper *) user_data;
1419
1420         status = tny_account_get_connection_status (account);
1421         if (err || canceled || helper->caller_window == NULL) {
1422                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1423                 /* Free the helper */
1424                 open_msg_helper_destroyer (helper);
1425
1426                 /* In disk full conditions we could get this error here */
1427                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
1428                                                                 (GtkWidget *) parent_window, err,
1429                                                                 account, NULL);
1430
1431                 goto clean;
1432         }
1433
1434         /* Get the error message depending on the protocol */
1435         proto = modest_tny_account_get_protocol_type (account);
1436         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1437                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1438         }
1439
1440         protocol_registry = modest_runtime_get_protocol_registry ();
1441         subject = tny_header_dup_subject (helper->header);
1442
1443         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1444         error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1445         if (subject)
1446                 g_free (subject);
1447
1448         if (error_msg == NULL) {
1449                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1450         }
1451
1452 #ifndef MODEST_TOOLKIT_HILDON2
1453         gboolean show_open_draft = FALSE;
1454         if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1455                                                             proto,
1456                                                             MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) {
1457                 TnyFolder *folder;
1458                 TnyFolderType folder_type;
1459
1460                 folder = tny_header_get_folder (helper->header);
1461                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1462                 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1463                 g_object_unref (folder);
1464         }
1465 #endif
1466
1467 #ifdef MODEST_TOOLKIT_HILDON2
1468         gboolean is_draft;
1469         gboolean can_open;
1470         gchar *account_name = get_info_from_header (helper->header, &is_draft, &can_open);
1471
1472         if (!can_open) {
1473                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1474                 g_free (account_name);
1475                 open_msg_helper_destroyer (helper);
1476                 goto clean;
1477         }
1478
1479         if (!is_draft) {
1480                 ModestWindow *window;
1481                 GtkWidget *header_view;
1482                 gchar *uid;
1483
1484                 header_view = get_header_view_from_window (MODEST_WINDOW (parent_window));
1485                 uid = modest_tny_folder_get_header_unique_id (helper->header);
1486                 if (header_view) {
1487                         const gchar *mailbox = NULL;
1488                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_window));
1489                         window = modest_msg_view_window_new_from_header_view 
1490                                 (MODEST_HEADER_VIEW (header_view), account_name, mailbox, uid, helper->rowref);
1491                         if (window != NULL) {
1492                                 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
1493                                                                         window, NULL)) {
1494                                         gtk_widget_destroy (GTK_WIDGET (window));
1495                                 } else {
1496                                         gtk_widget_show_all (GTK_WIDGET(window));
1497                                 }
1498                         }
1499                 }
1500                 g_free (account_name);
1501                 g_free (uid);
1502                 open_msg_helper_destroyer (helper);
1503                 goto clean;
1504         }
1505         g_free (account_name);
1506 #endif
1507         /* Create the mail operation */
1508         mail_op =
1509                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1510                                                                modest_ui_actions_disk_operations_error_handler,
1511                                                                g_strdup (error_msg), g_free);
1512         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1513                                          mail_op);
1514
1515
1516 #ifndef MODEST_TOOLKIT_HILDON2
1517         if (show_open_draft) {
1518                 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1519                 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1520                 helper->banner_info->banner = NULL;
1521                 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1522                                                                    helper->banner_info);
1523         }
1524 #endif
1525
1526
1527         TnyList *headers;
1528         headers = TNY_LIST (tny_simple_list_new ());
1529         tny_list_prepend (headers, G_OBJECT (helper->header));
1530         modest_mail_operation_get_msgs_full (mail_op,
1531                                              headers,
1532                                              open_msg_cb,
1533                                              helper,
1534                                              open_msg_helper_destroyer);
1535         g_object_unref (headers);
1536
1537         /* Frees */
1538  clean:
1539         if (error_msg)
1540                 g_free (error_msg);
1541         if (mail_op)
1542                 g_object_unref (mail_op);
1543         g_object_unref (account);
1544 }
1545
1546 /*
1547  * This function is used by both modest_ui_actions_on_open and
1548  * modest_ui_actions_on_header_activated. This way we always do the
1549  * same when trying to open messages.
1550  */
1551 static void
1552 open_msg_from_header (TnyHeader *header, GtkTreeRowReference *rowref, ModestWindow *win)
1553 {
1554         ModestWindowMgr *mgr = NULL;
1555         TnyAccount *account;
1556         gboolean cached = FALSE;
1557         gboolean found;
1558         GtkWidget *header_view = NULL;
1559         OpenMsgHelper *helper;
1560         ModestWindow *window;
1561
1562         g_return_if_fail (header != NULL && rowref != NULL && gtk_tree_row_reference_valid (rowref));
1563
1564         mgr = modest_runtime_get_window_mgr ();
1565
1566         /* get model */
1567         header_view = get_header_view_from_window (MODEST_WINDOW (win));
1568         if (header_view == NULL)
1569                 return;
1570
1571         /* Get the account */
1572         account = get_account_from_header (header);
1573         if (!account)
1574                 return;
1575
1576         window = NULL;
1577         found = modest_window_mgr_find_registered_header (mgr, header, &window);
1578
1579         /* Do not open again the message and present the
1580            window to the user */
1581         if (found) {
1582                 if (window) {
1583 #ifndef MODEST_TOOLKIT_HILDON2
1584                         gtk_window_present (GTK_WINDOW (window));
1585 #endif
1586                 } else {
1587                         /* the header has been registered already, we don't do
1588                          * anything but wait for the window to come up*/
1589                         g_debug ("header %p already registered, waiting for window", header);
1590                 }
1591                 goto cleanup;
1592         }
1593
1594         /* Open each message */
1595         cached = tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED;
1596         if (!cached) {
1597                 /* Allways download if we are online. */
1598                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1599                         gint response;
1600
1601                         /* If ask for user permission to download the messages */
1602                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1603                                                                             _("mcen_nc_get_msg"));
1604
1605                         /* End if the user does not want to continue */
1606                         if (response == GTK_RESPONSE_CANCEL) {
1607                                 goto cleanup;
1608                         }
1609                 }
1610         }
1611
1612         /* We register the window for opening */
1613         modest_window_mgr_register_header (mgr, header, NULL);
1614
1615         /* Create the helper. We need to get a reference to the model
1616            here because it could change while the message is readed
1617            (the user could switch between folders) */
1618         helper = g_slice_new (OpenMsgHelper);
1619         helper->model = g_object_ref (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
1620         helper->caller_window = win;
1621         g_object_weak_ref ((GObject *) helper->caller_window, (GWeakNotify) caller_win_destroyed, helper);
1622         helper->header = g_object_ref (header);
1623         helper->rowref = gtk_tree_row_reference_copy (rowref);
1624         helper->banner_info = NULL;
1625
1626         /* Connect to the account and perform */
1627         if (!cached) {
1628                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1629                                                      open_msg_performer, helper);
1630         } else {
1631                 /* Call directly the performer, do not need to connect */
1632                 open_msg_performer (FALSE, NULL, (GtkWindow *) win,
1633                                     g_object_ref (account), helper);
1634         }
1635 cleanup:
1636         /* Clean */
1637         if (account)
1638                 g_object_unref (account);
1639 }
1640
1641 void
1642 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1643 {
1644         TnyList *headers;
1645         TnyHeader *header;
1646         gint headers_count;
1647         TnyIterator *iter;
1648
1649         /* we check for low-mem; in that case, show a warning, and don't allow
1650          * opening
1651          */
1652         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1653                 return;
1654
1655         /* Get headers */
1656         headers = get_selected_headers (win);
1657         if (!headers)
1658                 return;
1659
1660         headers_count = tny_list_get_length (headers);
1661         if (headers_count != 1) {
1662                 if (headers_count > 1) {
1663                         /* Don't allow activation if there are more than one message selected */
1664                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1665                 }
1666
1667                 g_object_unref (headers);
1668                 return;
1669         }
1670
1671         iter = tny_list_create_iterator (headers);
1672         header = TNY_HEADER (tny_iterator_get_current (iter));
1673         g_object_unref (iter);
1674
1675         /* Open them */
1676         if (header) {
1677                 open_msg_from_header (header, NULL, win);
1678                 g_object_unref (header);
1679         }
1680
1681         g_object_unref(headers);
1682 }
1683
1684 static void
1685 rf_helper_window_closed (gpointer data,
1686                          GObject *object)
1687 {
1688         ReplyForwardHelper *helper = (ReplyForwardHelper *) data;
1689
1690         helper->parent_window = NULL;
1691 }
1692
1693 static ReplyForwardHelper*
1694 create_reply_forward_helper (ReplyForwardAction action,
1695                              ModestWindow *win,
1696                              guint reply_forward_type,
1697                              TnyHeader *header)
1698 {
1699         ReplyForwardHelper *rf_helper = NULL;
1700         const gchar *active_acc = modest_window_get_active_account (win);
1701         const gchar *active_mailbox = modest_window_get_active_mailbox (win);
1702
1703         rf_helper = g_slice_new0 (ReplyForwardHelper);
1704         rf_helper->reply_forward_type = reply_forward_type;
1705         rf_helper->action = action;
1706         rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1707         rf_helper->header = (header) ? g_object_ref (header) : NULL;
1708         rf_helper->account_name = (active_acc) ?
1709                 g_strdup (active_acc) :
1710                 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1711         rf_helper->mailbox = g_strdup (active_mailbox);
1712
1713         /* Note that window could be destroyed just AFTER calling
1714            register_window so we must ensure that this pointer does
1715            not hold invalid references */
1716         if (rf_helper->parent_window)
1717                 g_object_weak_ref (G_OBJECT (rf_helper->parent_window),
1718                                    rf_helper_window_closed, rf_helper);
1719
1720         return rf_helper;
1721 }
1722
1723 static void
1724 free_reply_forward_helper (gpointer data)
1725 {
1726         ReplyForwardHelper *helper;
1727
1728         helper = (ReplyForwardHelper *) data;
1729         g_free (helper->account_name);
1730         g_free (helper->mailbox);
1731         if (helper->header)
1732                 g_object_unref (helper->header);
1733         if (helper->parent_window)
1734                 g_object_weak_unref (G_OBJECT (helper->parent_window),
1735                                      rf_helper_window_closed, helper);
1736         g_slice_free (ReplyForwardHelper, helper);
1737 }
1738
1739 static void
1740 reply_forward_cb (ModestMailOperation *mail_op,
1741                   TnyHeader *header,
1742                   gboolean canceled,
1743                   TnyMsg *msg,
1744                   GError *err,
1745                   gpointer user_data)
1746 {
1747         TnyMsg *new_msg = NULL;
1748         ReplyForwardHelper *rf_helper;
1749         ModestWindow *msg_win = NULL;
1750         ModestEditType edit_type;
1751         gchar *from = NULL;
1752         TnyAccount *account = NULL;
1753         ModestWindowMgr *mgr = NULL;
1754         gchar *signature = NULL;
1755         gboolean use_signature;
1756         gchar *recipient;
1757
1758         /* If there was any error. The mail operation could be NULL,
1759            this means that we already have the message downloaded and
1760            that we didn't do a mail operation to retrieve it */
1761         rf_helper = (ReplyForwardHelper *) user_data;
1762         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1763                 goto cleanup;
1764
1765         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1766                                                    rf_helper->account_name, rf_helper->mailbox);
1767         recipient = modest_text_utils_get_email_address (from);
1768         signature = modest_account_mgr_get_signature_from_recipient (modest_runtime_get_account_mgr(), 
1769                                                                      recipient, 
1770                                                                      &use_signature);
1771         g_free (recipient);
1772
1773         /* Create reply mail */
1774         switch (rf_helper->action) {
1775                 /* Use the msg_header to ensure that we have all the
1776                    information. The summary can lack some data */
1777                 TnyHeader *msg_header;
1778         case ACTION_REPLY:
1779                 msg_header = tny_msg_get_header (msg);
1780                 new_msg =
1781                         modest_tny_msg_create_reply_msg (msg, msg_header, from,
1782                                                          (use_signature) ? signature : NULL,
1783                                                          rf_helper->reply_forward_type,
1784                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1785                 g_object_unref (msg_header);
1786                 break;
1787         case ACTION_REPLY_TO_ALL:
1788                 msg_header = tny_msg_get_header (msg);
1789                 new_msg =
1790                         modest_tny_msg_create_reply_msg (msg, msg_header, from,
1791                                                          (use_signature) ? signature : NULL,
1792                                                          rf_helper->reply_forward_type,
1793                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1794                 edit_type = MODEST_EDIT_TYPE_REPLY;
1795                 g_object_unref (msg_header);
1796                 break;
1797         case ACTION_FORWARD:
1798                 new_msg =
1799                         modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1800                                                            rf_helper->reply_forward_type);
1801                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1802                 break;
1803         default:
1804                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1805                                                      header);
1806                 g_return_if_reached ();
1807                 return;
1808         }
1809
1810         g_free (from);
1811         g_free (signature);
1812
1813         if (!new_msg) {
1814                 g_warning ("%s: failed to create message\n", __FUNCTION__);
1815                 goto cleanup;
1816         }
1817
1818         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1819                                                                        rf_helper->account_name,
1820                                                                        TNY_ACCOUNT_TYPE_STORE);
1821         if (!account) {
1822                 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1823                 goto cleanup;
1824         }
1825
1826         /* Create and register the windows */
1827         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, rf_helper->mailbox, FALSE);
1828         mgr = modest_runtime_get_window_mgr ();
1829         modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1830
1831         /* Note that register_window could have deleted the account */
1832         if (MODEST_IS_WINDOW (rf_helper->parent_window)) {
1833                 gdouble parent_zoom;
1834
1835                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1836                 modest_window_set_zoom (msg_win, parent_zoom);
1837         }
1838
1839         /* Show edit window */
1840         gtk_widget_show_all (GTK_WIDGET (msg_win));
1841
1842 cleanup:
1843         /* We always unregister the header because the message is
1844            forwarded or replied so the original one is no longer
1845            opened */
1846         modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1847                                              header);
1848         if (new_msg)
1849                 g_object_unref (G_OBJECT (new_msg));
1850         if (account)
1851                 g_object_unref (G_OBJECT (account));
1852         free_reply_forward_helper (rf_helper);
1853 }
1854
1855 /* Checks a list of headers. If any of them are not currently
1856  * downloaded (CACHED) then returns TRUE else returns FALSE.
1857  */
1858 static gint
1859 header_list_count_uncached_msgs (TnyList *header_list)
1860 {
1861         TnyIterator *iter;
1862         gint uncached_messages = 0;
1863
1864         iter = tny_list_create_iterator (header_list);
1865         while (!tny_iterator_is_done (iter)) {
1866                 TnyHeader *header;
1867
1868                 header = TNY_HEADER (tny_iterator_get_current (iter));
1869                 if (header) {
1870                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1871                                 uncached_messages ++;
1872                         g_object_unref (header);
1873                 }
1874
1875                 tny_iterator_next (iter);
1876         }
1877         g_object_unref (iter);
1878
1879         return uncached_messages;
1880 }
1881
1882 /* Returns FALSE if the user does not want to download the
1883  * messages. Returns TRUE if the user allowed the download.
1884  */
1885 static gboolean
1886 connect_to_get_msg (ModestWindow *win,
1887                     gint num_of_uncached_msgs,
1888                     TnyAccount *account)
1889 {
1890         GtkResponseType response;
1891
1892         /* Allways download if we are online. */
1893         if (tny_device_is_online (modest_runtime_get_device ()))
1894                 return TRUE;
1895
1896         /* If offline, then ask for user permission to download the messages */
1897         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1898                         ngettext("mcen_nc_get_msg",
1899                         "mcen_nc_get_msgs",
1900                         num_of_uncached_msgs));
1901
1902         if (response == GTK_RESPONSE_CANCEL)
1903                 return FALSE;
1904
1905         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1906 }
1907
1908 static void
1909 reply_forward_performer (gboolean canceled,
1910                          GError *err,
1911                          GtkWindow *parent_window,
1912                          TnyAccount *account,
1913                          gpointer user_data)
1914 {
1915         ReplyForwardHelper *rf_helper = NULL;
1916         ModestMailOperation *mail_op;
1917
1918         rf_helper = (ReplyForwardHelper *) user_data;
1919
1920         if (canceled || err) {
1921                 free_reply_forward_helper (rf_helper);
1922                 return;
1923         }
1924
1925         /* Retrieve the message */
1926         modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1927         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1928                                                                  modest_ui_actions_disk_operations_error_handler,
1929                                                                  NULL, NULL);
1930         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1931         modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1932
1933         /* Frees */
1934         g_object_unref(mail_op);
1935 }
1936
1937 /*
1938  * Common code for the reply and forward actions
1939  */
1940 static void
1941 reply_forward (ReplyForwardAction action, ModestWindow *win)
1942 {
1943         ReplyForwardHelper *rf_helper = NULL;
1944         guint reply_forward_type;
1945
1946         g_return_if_fail (win && MODEST_IS_WINDOW(win));
1947
1948         /* we check for low-mem; in that case, show a warning, and don't allow
1949          * reply/forward (because it could potentially require a lot of memory */
1950         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1951                 return;
1952
1953
1954         /* we need an account when editing */
1955         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1956                 if (!modest_ui_actions_run_account_setup_wizard (win))
1957                         return;
1958         }
1959
1960         reply_forward_type =
1961                 modest_conf_get_int (modest_runtime_get_conf (),
1962                                      (action == ACTION_FORWARD) ?
1963                                      MODEST_CONF_FORWARD_TYPE :
1964                                      MODEST_CONF_REPLY_TYPE,
1965                                      NULL);
1966
1967         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1968                 TnyMsg *msg = NULL;
1969                 TnyHeader *header = NULL;
1970                 /* Get header and message. Do not free them here, the
1971                    reply_forward_cb must do it */
1972                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1973                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1974
1975                 if (msg && header) {
1976                         /* Create helper */
1977                         rf_helper = create_reply_forward_helper (action, win,
1978                                                                  reply_forward_type, header);
1979                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1980                 } else {
1981                         g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1982                 }
1983
1984                 if (msg)
1985                         g_object_unref (msg);
1986                 if (header)
1987                         g_object_unref (header);
1988         } else {
1989                 TnyHeader *header = NULL;
1990                 TnyIterator *iter;
1991                 gboolean do_retrieve = TRUE;
1992                 TnyList *header_list = NULL;
1993
1994                 header_list = get_selected_headers (win);
1995                 if (!header_list)
1996                         return;
1997                 /* Check that only one message is selected for replying */
1998                 if (tny_list_get_length (header_list) != 1) {
1999                         modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
2000                                                             NULL, _("mcen_ib_select_one_message"));
2001                         g_object_unref (header_list);
2002                         return;
2003                 }
2004
2005                 /* Only reply/forward to one message */
2006                 iter = tny_list_create_iterator (header_list);
2007                 header = TNY_HEADER (tny_iterator_get_current (iter));
2008                 g_object_unref (iter);
2009
2010                 /* Retrieve messages */
2011                 do_retrieve = (action == ACTION_FORWARD) ||
2012                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
2013
2014                 if (do_retrieve) {
2015                         TnyAccount *account = NULL;
2016                         TnyFolder *folder = NULL;
2017                         gdouble download = TRUE;
2018                         guint uncached_msgs = 0;
2019
2020                         folder = tny_header_get_folder (header);
2021                         if (!folder)
2022                                 goto do_retrieve_frees;
2023                         account = tny_folder_get_account (folder);
2024                         if (!account)
2025                                 goto do_retrieve_frees;
2026
2027                         uncached_msgs = header_list_count_uncached_msgs (header_list);
2028
2029                         if (uncached_msgs > 0) {
2030                                 /* Allways download if we are online. */
2031                                 if (!tny_device_is_online (modest_runtime_get_device ())) {
2032                                         gint response;
2033
2034                                         /* If ask for user permission to download the messages */
2035                                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2036                                                                                             ngettext("mcen_nc_get_msg",
2037                                                                                                      "mcen_nc_get_msgs",
2038                                                                                                      uncached_msgs));
2039
2040                                         /* End if the user does not want to continue */
2041                                         if (response == GTK_RESPONSE_CANCEL)
2042                                                 download = FALSE;
2043                                 }
2044                         }
2045
2046                         if (download) {
2047                                 /* Create helper */
2048                                 rf_helper = create_reply_forward_helper (action, win,
2049                                                                          reply_forward_type, header);
2050                                 if (uncached_msgs > 0) {
2051                                         modest_platform_connect_and_perform (GTK_WINDOW (win),
2052                                                                              TRUE, account,
2053                                                                              reply_forward_performer,
2054                                                                              rf_helper);
2055                                 } else {
2056                                         reply_forward_performer (FALSE, NULL, GTK_WINDOW (win),
2057                                                                  account, rf_helper);
2058                                 }
2059                         }
2060                 do_retrieve_frees:
2061                         if (account)
2062                                 g_object_unref (account);
2063                         if (folder)
2064                                 g_object_unref (folder);
2065                 } else {
2066                         reply_forward_cb (NULL, header, FALSE, NULL, NULL, NULL);
2067                 }
2068                 /* Frees */
2069                 g_object_unref (header_list);
2070                 g_object_unref (header);
2071         }
2072 }
2073
2074 void
2075 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
2076 {
2077         g_return_if_fail (MODEST_IS_WINDOW(win));
2078
2079         reply_forward (ACTION_REPLY, win);
2080 }
2081
2082 void
2083 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
2084 {
2085         g_return_if_fail (MODEST_IS_WINDOW(win));
2086
2087         reply_forward (ACTION_FORWARD, win);
2088 }
2089
2090 void
2091 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
2092 {
2093         g_return_if_fail (MODEST_IS_WINDOW(win));
2094
2095         reply_forward (ACTION_REPLY_TO_ALL, win);
2096 }
2097
2098 void
2099 modest_ui_actions_on_next (GtkAction *action,
2100                            ModestWindow *window)
2101 {
2102 #ifndef MODEST_TOOLKIT_HILDON2
2103         if (MODEST_IS_MAIN_WINDOW (window)) {
2104                 GtkWidget *header_view;
2105
2106                 header_view = modest_main_window_get_child_widget (
2107                                 MODEST_MAIN_WINDOW(window),
2108                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2109                 if (!header_view)
2110                         return;
2111
2112                 modest_header_view_select_next (
2113                                 MODEST_HEADER_VIEW(header_view));
2114 #else
2115         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2116                 modest_msg_view_window_select_next_message (
2117                                 MODEST_MSG_VIEW_WINDOW (window));
2118 #endif
2119         } else {
2120                 g_return_if_reached ();
2121         }
2122 }
2123
2124 void
2125 modest_ui_actions_on_prev (GtkAction *action,
2126                            ModestWindow *window)
2127 {
2128         g_return_if_fail (MODEST_IS_WINDOW(window));
2129
2130 #ifndef MODEST_TOOLKIT_HILDON2
2131         if (MODEST_IS_MAIN_WINDOW (window)) {
2132                 GtkWidget *header_view;
2133                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2134                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2135                 if (!header_view)
2136                         return;
2137
2138                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
2139 #else
2140         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2141                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
2142 #endif
2143         } else {
2144                 g_return_if_reached ();
2145         }
2146 }
2147
2148 void
2149 modest_ui_actions_on_sort (GtkAction *action,
2150                            ModestWindow *window)
2151 {
2152         GtkWidget *header_view = NULL;
2153
2154         g_return_if_fail (MODEST_IS_WINDOW(window));
2155
2156 #ifndef MODEST_TOOLKIT_HILDON2
2157         if (MODEST_IS_MAIN_WINDOW (window)) {
2158                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2159                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2160 #else
2161         if (MODEST_IS_HEADER_WINDOW (window)) {
2162                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
2163 #endif
2164         }
2165
2166         if (!header_view) {
2167                 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
2168
2169                 return;
2170         }
2171
2172         /* Show sorting dialog */
2173         modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
2174 }
2175
2176 static void
2177 sync_folder_cb (ModestMailOperation *mail_op,
2178                 TnyFolder *folder,
2179                 gpointer user_data)
2180 {
2181         ModestHeaderView *header_view = (ModestHeaderView *) user_data;
2182
2183         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
2184                 ModestWindow *parent = (ModestWindow *) modest_mail_operation_get_source (mail_op);
2185
2186                 /* We must clear first, because otherwise set_folder will ignore */
2187                 /*    the change as the folders are the same */
2188                 modest_header_view_clear (header_view);
2189                 modest_header_view_set_folder (header_view, folder, TRUE, parent, NULL, NULL);
2190
2191                 g_object_unref (parent);
2192         }
2193
2194         g_object_unref (header_view);
2195 }
2196
2197 static gboolean
2198 idle_refresh_folder (gpointer source)
2199 {
2200         ModestHeaderView *header_view = NULL;
2201
2202         /* If the window still exists */
2203         if (!GTK_IS_WIDGET (source) ||
2204             !GTK_WIDGET_VISIBLE (source))
2205                 return FALSE;
2206
2207         /* Refresh the current view */
2208 #ifdef MODEST_TOOLKIT_HILDON2
2209         if (MODEST_IS_HEADER_WINDOW (source))
2210                 header_view = modest_header_window_get_header_view ((ModestHeaderWindow *) source);
2211 #else
2212         if (MODEST_IS_MAIN_WINDOW (source))
2213                 header_view = MODEST_HEADER_VIEW (modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source),
2214                                                                                        MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
2215 #endif
2216         if (header_view) {
2217                 TnyFolder *folder = modest_header_view_get_folder (header_view);
2218                 if (folder) {
2219                         /* Sync the folder status */
2220                         ModestMailOperation *mail_op = modest_mail_operation_new (source);
2221                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2222                         modest_mail_operation_sync_folder (mail_op, folder, FALSE, sync_folder_cb, g_object_ref (header_view));
2223                         g_object_unref (folder);
2224                         g_object_unref (mail_op);
2225                 }
2226         }
2227
2228         return FALSE;
2229 }
2230
2231 static void
2232 update_account_cb (ModestMailOperation *self,
2233                    TnyList *new_headers,
2234                    gpointer user_data)
2235 {
2236         ModestWindow *top;
2237         gboolean show_visual_notifications;
2238
2239         top = modest_window_mgr_get_current_top (modest_runtime_get_window_mgr ());
2240         show_visual_notifications = (top) ? FALSE : TRUE;
2241
2242         /* Notify new messages have been downloaded. If the
2243            send&receive was invoked by the user then do not show any
2244            visual notification, only play a sound and activate the LED
2245            (for the Maemo version) */
2246         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2247
2248                 /* We only notify about really new messages (not seen) we get */
2249                 TnyList *actually_new_list;
2250                 TnyIterator *iterator;
2251                 actually_new_list = TNY_LIST (tny_simple_list_new ());
2252                 for (iterator = tny_list_create_iterator (new_headers);
2253                      !tny_iterator_is_done (iterator);
2254                      tny_iterator_next (iterator)) {
2255                         TnyHeader *header;
2256                         TnyHeaderFlags flags;
2257                         header = TNY_HEADER (tny_iterator_get_current (iterator));
2258                         flags = tny_header_get_flags (header);
2259
2260                         if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2261                                 /* Messages are ordered from most
2262                                    recent to oldest. But we want to
2263                                    show notifications starting from
2264                                    the oldest message. That's why we
2265                                    reverse the list */
2266                                 tny_list_prepend (actually_new_list, G_OBJECT (header));
2267                         }
2268                         g_object_unref (header);
2269                 }
2270                 g_object_unref (iterator);
2271
2272                 if (tny_list_get_length (actually_new_list) > 0) {
2273                         GList *new_headers_list = NULL;
2274
2275                         new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2276
2277                         /* Send notifications */
2278                         if (new_headers_list) {
2279                                 modest_platform_on_new_headers_received (new_headers_list,
2280                                                                          show_visual_notifications);
2281                                 /* Free the list */
2282                                 modest_utils_free_notification_list (new_headers_list);
2283                         }
2284                 }
2285                 g_object_unref (actually_new_list);
2286         }
2287
2288         if (top) {
2289                 /* Refresh the current folder in an idle. We do this
2290                    in order to avoid refresh cancelations if the
2291                    currently viewed folder is the inbox */
2292                 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
2293                                  idle_refresh_folder,
2294                                  g_object_ref (top),
2295                                  g_object_unref);
2296         }
2297 }
2298
2299 typedef struct {
2300         TnyAccount *account;
2301         ModestWindow *win;
2302         gchar *account_name;
2303         gboolean poke_status;
2304         gboolean interactive;
2305         ModestMailOperation *mail_op;
2306 } SendReceiveInfo;
2307
2308 static void
2309 do_send_receive_performer (gboolean canceled,
2310                            GError *err,
2311                            GtkWindow *parent_window,
2312                            TnyAccount *account,
2313                            gpointer user_data)
2314 {
2315         SendReceiveInfo *info;
2316
2317         info = (SendReceiveInfo *) user_data;
2318
2319         if (err || canceled) {
2320                 /* In disk full conditions we could get this error here */
2321                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2322                                                                 (GtkWidget *) parent_window, err,
2323                                                                 account, NULL);
2324
2325                 if (info->mail_op) {
2326                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2327                                                             info->mail_op);
2328                 }
2329                 goto clean;
2330         }
2331
2332 #ifndef MODEST_TOOLKIT_HILDON2
2333         /* Set send/receive operation in progress */
2334         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2335                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2336         }
2337
2338         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2339                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2340                                   G_CALLBACK (on_send_receive_finished),
2341                                   info->win);
2342 #endif
2343
2344         /* Send & receive. */
2345         modest_mail_operation_update_account (info->mail_op, info->account_name,
2346                                               info->poke_status, info->interactive,
2347                                               update_account_cb, info->win);
2348
2349  clean:
2350         /* Frees */
2351         if (info->mail_op)
2352                 g_object_unref (G_OBJECT (info->mail_op));
2353         if (info->account_name)
2354                 g_free (info->account_name);
2355         if (info->win)
2356                 g_object_unref (info->win);
2357         if (info->account)
2358                 g_object_unref (info->account);
2359         g_slice_free (SendReceiveInfo, info);
2360 }
2361
2362 /*
2363  * This function performs the send & receive required actions. The
2364  * window is used to create the mail operation. Typically it should
2365  * always be the main window, but we pass it as argument in order to
2366  * be more flexible.
2367  */
2368 void
2369 modest_ui_actions_do_send_receive (const gchar *account_name,
2370                                    gboolean force_connection,
2371                                    gboolean poke_status,
2372                                    gboolean interactive,
2373                                    ModestWindow *win)
2374 {
2375         gchar *acc_name = NULL;
2376         SendReceiveInfo *info;
2377         ModestTnyAccountStore *acc_store;
2378         TnyAccount *account;
2379
2380         /* If no account name was provided then get the current account, and if
2381            there is no current account then pick the default one: */
2382         if (!account_name) {
2383                 if (win)
2384                         acc_name = g_strdup (modest_window_get_active_account (win));
2385                 if (!acc_name)
2386                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2387                 if (!acc_name) {
2388                         modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2389                         return;
2390                 }
2391         } else {
2392                 acc_name = g_strdup (account_name);
2393         }
2394
2395         acc_store = modest_runtime_get_account_store ();
2396         account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2397
2398         if (!account) {
2399                 g_free (acc_name);
2400                 modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2401                 return;
2402         }
2403
2404         /* Do not automatically refresh accounts that are flagged as
2405            NO_AUTO_UPDATE. This could be useful for accounts that
2406            handle their own update times */
2407         if (!interactive) {
2408                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2409                 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2410                         const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2411                         ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2412
2413                         if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2414                                 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2415                                 g_object_unref (account);
2416                                 g_free (acc_name);
2417                                 return;
2418                         }
2419                 }
2420         }
2421
2422         /* Create the info for the connect and perform */
2423         info = g_slice_new (SendReceiveInfo);
2424         info->account_name = acc_name;
2425         info->win = (win) ? g_object_ref (win) : NULL;
2426         info->poke_status = poke_status;
2427         info->interactive = interactive;
2428         info->account = account;
2429         /* We need to create the operation here, because otherwise it
2430            could happen that the queue emits the queue-empty signal
2431            while we're trying to connect the account */
2432         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2433                                                                        modest_ui_actions_disk_operations_error_handler,
2434                                                                        NULL, NULL);
2435         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2436
2437         /* Invoke the connect and perform */
2438         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2439                                              force_connection, info->account,
2440                                              do_send_receive_performer, info);
2441 }
2442
2443
2444 static void
2445 modest_ui_actions_do_cancel_send (const gchar *account_name,
2446                                   ModestWindow *win)
2447 {
2448         TnyTransportAccount *transport_account;
2449         TnySendQueue *send_queue = NULL;
2450         GError *error = NULL;
2451
2452         /* Get transport account */
2453         transport_account =
2454                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2455                                       (modest_runtime_get_account_store(),
2456                                        account_name,
2457                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2458         if (!transport_account) {
2459                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2460                 goto frees;
2461         }
2462
2463         /* Get send queue*/
2464         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2465         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2466                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2467                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2468                              "modest: could not find send queue for account\n");
2469         } else {
2470                 /* Cancel the current send */
2471                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2472
2473                 /* Suspend all pending messages */
2474                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2475         }
2476
2477  frees:
2478         if (transport_account != NULL)
2479                 g_object_unref (G_OBJECT (transport_account));
2480 }
2481
2482 static void
2483 modest_ui_actions_cancel_send_all (ModestWindow *win)
2484 {
2485         GSList *account_names, *iter;
2486
2487         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2488                                                           TRUE);
2489
2490         iter = account_names;
2491         while (iter) {
2492                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2493                 iter = g_slist_next (iter);
2494         }
2495
2496         modest_account_mgr_free_account_names (account_names);
2497         account_names = NULL;
2498 }
2499
2500 void
2501 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2502
2503 {
2504         /* Check if accounts exist */
2505         gboolean accounts_exist =
2506                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2507
2508         /* If not, allow the user to create an account before trying to send/receive. */
2509         if (!accounts_exist)
2510                 modest_ui_actions_on_accounts (NULL, win);
2511
2512         /* Cancel all sending operaitons */
2513         modest_ui_actions_cancel_send_all (win);
2514 }
2515
2516 /*
2517  * Refreshes all accounts. This function will be used by automatic
2518  * updates
2519  */
2520 void
2521 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2522                                        gboolean force_connection,
2523                                        gboolean poke_status,
2524                                        gboolean interactive)
2525 {
2526         GSList *account_names, *iter;
2527
2528         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2529                                                           TRUE);
2530
2531         iter = account_names;
2532         while (iter) {
2533                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2534                                                    force_connection,
2535                                                    poke_status, interactive, win);
2536                 iter = g_slist_next (iter);
2537         }
2538
2539         modest_account_mgr_free_account_names (account_names);
2540         account_names = NULL;
2541 }
2542
2543 /*
2544  * Handler of the click on Send&Receive button in the main toolbar
2545  */
2546 void
2547 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2548 {
2549         /* Check if accounts exist */
2550         gboolean accounts_exist;
2551
2552         accounts_exist =
2553                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2554
2555         /* If not, allow the user to create an account before trying to send/receive. */
2556         if (!accounts_exist)
2557                 modest_ui_actions_on_accounts (NULL, win);
2558
2559         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2560 #ifndef MODEST_TOOLKIT_HILDON2
2561         if (MODEST_IS_MAIN_WINDOW (win)) {
2562                 GtkWidget *folder_view;
2563                 TnyFolderStore *folder_store;
2564
2565                 folder_view =
2566                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2567                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2568                 if (!folder_view)
2569                         return;
2570
2571                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2572
2573                 if (folder_store)
2574                         g_object_unref (folder_store);
2575                 /* Refresh the active account. Force the connection if needed
2576                    and poke the status of all folders */
2577                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2578 #else
2579         if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2580                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2581 #endif
2582         } else {
2583                 const gchar *active_account;
2584                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2585
2586                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2587         }
2588
2589 }
2590
2591 #ifndef MODEST_TOOLKIT_HILDON2
2592 void
2593 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2594 {
2595         ModestConf *conf;
2596         GtkWidget *header_view;
2597
2598         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2599
2600         header_view = modest_main_window_get_child_widget (main_window,
2601                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2602         if (!header_view)
2603                 return;
2604
2605         conf = modest_runtime_get_conf ();
2606
2607         /* what is saved/restored is depending on the style; thus; we save with
2608          * old style, then update the style, and restore for this new style
2609          */
2610         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2611
2612         if (modest_header_view_get_style
2613             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2614                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2615                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2616         else
2617                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2618                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2619
2620         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2621                                       MODEST_CONF_HEADER_VIEW_KEY);
2622 }
2623
2624 void
2625 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2626                                       TnyHeader *header,
2627                                       ModestMainWindow *main_window)
2628 {
2629         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2630         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2631
2632         /* in the case the folder is empty, show the empty folder message and focus
2633          * folder view */
2634         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2635                 if (modest_header_view_is_empty (header_view)) {
2636                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2637                         GtkWidget *folder_view =
2638                                 modest_main_window_get_child_widget (main_window,
2639                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2640                         if (folder != NULL) {
2641                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2642                                 g_object_unref (folder);
2643                         }
2644                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2645                         return;
2646                 }
2647         }
2648         /* If no header has been selected then exit */
2649         if (!header)
2650                 return;
2651
2652         /* Update focus */
2653         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2654             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2655
2656         /* Update toolbar dimming state */
2657         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2658         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2659 }
2660 #endif
2661
2662 void
2663 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2664                                        TnyHeader *header,
2665                                        GtkTreePath *path,
2666                                        ModestWindow *window)
2667 {
2668         GtkTreeRowReference *rowref;
2669
2670         g_return_if_fail (MODEST_IS_WINDOW(window));
2671         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2672         g_return_if_fail (TNY_IS_HEADER (header));
2673
2674         if (modest_header_view_count_selected_headers (header_view) > 1) {
2675                 /* Don't allow activation if there are more than one message selected */
2676                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2677                 return;
2678         }
2679
2680         /* we check for low-mem; in that case, show a warning, and don't allow
2681          * activating headers
2682          */
2683         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2684                 return;
2685
2686 #ifndef MODEST_TOOLKIT_HILDON2
2687         GtkWidget *open_widget;
2688         if (MODEST_IS_MAIN_WINDOW (window)) {
2689                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2690                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2691                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2692                         return;
2693         }
2694 #endif
2695
2696         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2697         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2698         gtk_tree_row_reference_free (rowref);
2699 }
2700
2701 #ifndef MODEST_TOOLKIT_HILDON2
2702 static void
2703 set_active_account_from_tny_account (TnyAccount *account,
2704                                      ModestWindow *window)
2705 {
2706         const gchar *server_acc_name = tny_account_get_id (account);
2707
2708         /* We need the TnyAccount provided by the
2709            account store because that is the one that
2710            knows the name of the Modest account */
2711         TnyAccount *modest_server_account =
2712                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2713                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2714                                                              server_acc_name);
2715         if (!modest_server_account) {
2716                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2717                 return;
2718         }
2719
2720         /* Update active account, but only if it's not a pseudo-account */
2721         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2722             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2723                 const gchar *modest_acc_name =
2724                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2725                 if (modest_acc_name)
2726                         modest_window_set_active_account (window, modest_acc_name);
2727         }
2728
2729         g_object_unref (modest_server_account);
2730 }
2731
2732 static void
2733 folder_refreshed_cb (ModestMailOperation *mail_op,
2734                      TnyFolder *folder,
2735                      gpointer user_data)
2736 {
2737         ModestMainWindow *win = NULL;
2738         GtkWidget *folder_view, *header_view;
2739         const GError *error;
2740
2741         g_return_if_fail (TNY_IS_FOLDER (folder));
2742
2743         win = MODEST_MAIN_WINDOW (user_data);
2744
2745         /* Check if the operation failed due to memory low conditions */
2746         error = modest_mail_operation_get_error (mail_op);
2747         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2748             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2749                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2750                                                         _KR("memr_ib_operation_disabled"),
2751                                                         TRUE);
2752                 return;
2753         }
2754
2755         folder_view =
2756                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2757         header_view =
2758                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2759
2760         if (folder_view) {
2761                 TnyFolderStore *current_folder;
2762
2763                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2764                 if (current_folder) {
2765                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2766                         g_object_unref (current_folder);
2767                         if (different)
2768                                 return;
2769                 }
2770         }
2771
2772         /* Check if folder is empty and set headers view contents style */
2773         if ((tny_folder_get_all_count (folder) == 0) ||
2774             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2775                 modest_main_window_set_contents_style (win,
2776                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2777 }
2778
2779 void
2780 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2781                                                TnyFolderStore *folder_store,
2782                                                gboolean selected,
2783                                                ModestMainWindow *main_window)
2784 {
2785         GtkWidget *header_view;
2786
2787         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2788
2789         header_view = modest_main_window_get_child_widget(main_window,
2790                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2791         if (!header_view)
2792                 return;
2793
2794
2795         if (TNY_IS_ACCOUNT (folder_store)) {
2796                 if (selected) {
2797                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2798
2799                         /* Show account details */
2800                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2801                 }
2802         } else {
2803                 if (TNY_IS_FOLDER (folder_store) && selected) {
2804                         TnyAccount *account;
2805
2806                         /* Update the active account */
2807                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2808                         if (account) {
2809                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2810                                 g_object_unref (account);
2811                                 account = NULL;
2812                         }
2813
2814                         /* Set the header style by default, it could
2815                            be changed later by the refresh callback to
2816                            empty */
2817                         modest_main_window_set_contents_style (main_window,
2818                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2819
2820                         /* Set folder on header view. This function
2821                            will call tny_folder_refresh_async so we
2822                            pass a callback that will be called when
2823                            finished. We use that callback to set the
2824                            empty view if there are no messages */
2825                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2826                                                        TNY_FOLDER (folder_store),
2827                                                        TRUE,
2828                                                        MODEST_WINDOW (main_window),
2829                                                        folder_refreshed_cb,
2830                                                        main_window);
2831
2832                         /* Restore configuration. We need to do this
2833                            *after* the set_folder because the widget
2834                            memory asks the header view about its
2835                            folder  */
2836                         modest_widget_memory_restore (modest_runtime_get_conf (),
2837                                                       G_OBJECT(header_view),
2838                                                       MODEST_CONF_HEADER_VIEW_KEY);
2839                 } else {
2840                         /* No need to save the header view
2841                            configuration for Maemo because it only
2842                            saves the sorting stuff and that it's
2843                            already being done by the sort
2844                            dialog. Remove it when the GNOME version
2845                            has the same behaviour */
2846 #ifdef MODEST_TOOLKIT_GTK
2847                         if (modest_main_window_get_contents_style (main_window) ==
2848                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2849                                 modest_widget_memory_save (modest_runtime_get_conf (), 
2850                                                            G_OBJECT (header_view),
2851                                                            MODEST_CONF_HEADER_VIEW_KEY);
2852 #endif
2853                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2854                 }
2855         }
2856
2857         /* Update dimming state */
2858         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2859         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2860 }
2861 #endif
2862
2863 void
2864 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2865                                      ModestWindow *win)
2866 {
2867         GtkWidget *dialog;
2868         gchar *txt, *item;
2869         gboolean online;
2870
2871         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2872
2873         online = tny_device_is_online (modest_runtime_get_device());
2874
2875         if (online) {
2876                 /* already online -- the item is simply not there... */
2877                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2878                                                  GTK_DIALOG_MODAL,
2879                                                  GTK_MESSAGE_WARNING,
2880                                                  GTK_BUTTONS_NONE,
2881                                                  _("The %s you selected cannot be found"),
2882                                                  item);
2883                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2884                 gtk_dialog_run (GTK_DIALOG(dialog));
2885         } else {
2886                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2887                                                       GTK_WINDOW (win),
2888                                                       GTK_DIALOG_MODAL,
2889                                                       _("mcen_bd_dialog_cancel"),
2890                                                       GTK_RESPONSE_REJECT,
2891                                                       _("mcen_bd_dialog_ok"),
2892                                                       GTK_RESPONSE_ACCEPT,
2893                                                       NULL);
2894                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2895                                          "Do you want to get online?"), item);
2896                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2897                                     gtk_label_new (txt), FALSE, FALSE, 0);
2898                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2899                 g_free (txt);
2900
2901                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2902                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2903                         /* TODO: Comment about why is this commented out: */
2904                         /* modest_platform_connect_and_wait (); */
2905                 }
2906         }
2907         gtk_widget_destroy (dialog);
2908 }
2909
2910 void
2911 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2912                                      ModestWindow *win)
2913 {
2914         /* g_debug ("%s %s", __FUNCTION__, link); */
2915 }
2916
2917
2918 void
2919 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2920                                         ModestWindow *win)
2921 {
2922         modest_platform_activate_uri (link);
2923 }
2924
2925 void
2926 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2927                                           ModestWindow *win)
2928 {
2929         modest_platform_show_uri_popup (link);
2930 }
2931
2932 void
2933 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2934                                              ModestWindow *win)
2935 {
2936         /* we check for low-mem; in that case, show a warning, and don't allow
2937          * viewing attachments
2938          */
2939         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2940                 return;
2941
2942         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2943 }
2944
2945 void
2946 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2947                                           const gchar *address,
2948                                           ModestWindow *win)
2949 {
2950         /* g_debug ("%s %s", __FUNCTION__, address); */
2951 }
2952
2953 static void
2954 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2955                       TnyMsg *saved_draft,
2956                       gpointer user_data)
2957 {
2958         ModestMsgEditWindow *edit_window;
2959
2960         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2961 #ifndef MODEST_TOOLKIT_HILDON2
2962         ModestMainWindow *win;
2963
2964         /* FIXME. Make the header view sensitive again. This is a
2965          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2966          * for details */
2967         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2968                                          modest_runtime_get_window_mgr(), FALSE));
2969         if (win != NULL) {
2970                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2971                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2972                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2973         }
2974 #endif
2975
2976         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2977
2978         /* Set draft is there was no error */
2979         if (!modest_mail_operation_get_error (mail_op))
2980                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2981
2982         g_object_unref(edit_window);
2983 }
2984
2985 static gboolean
2986 enough_space_for_message (ModestMsgEditWindow *edit_window,
2987                           MsgData *data)
2988 {
2989         guint64 available_disk, expected_size;
2990         gint parts_count;
2991         guint64 parts_size;
2992
2993         /* Check size */
2994         available_disk = modest_utils_get_available_space (NULL);
2995         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2996         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2997                                                       data->html_body,
2998                                                       parts_count,
2999                                                       parts_size);
3000
3001         /* Double check: disk full condition or message too big */
3002         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
3003             expected_size > available_disk) {
3004                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3005                 modest_platform_information_banner (NULL, NULL, msg);
3006                 g_free (msg);
3007
3008                 return FALSE;
3009         }
3010
3011         /*
3012          * djcb: if we're in low-memory state, we only allow for
3013          * saving messages smaller than
3014          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
3015          * should still allow for sending anything critical...
3016          */
3017         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
3018             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
3019                 return FALSE;
3020
3021         /*
3022          * djcb: we also make sure that the attachments are smaller than the max size
3023          * this is for the case where we'd try to forward a message with attachments
3024          * bigger than our max allowed size, or sending an message from drafts which
3025          * somehow got past our checks when attaching.
3026          */
3027         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
3028                 modest_platform_run_information_dialog (
3029                         GTK_WINDOW(edit_window),
3030                         _("mail_ib_error_attachment_size"),
3031                         TRUE);
3032                 return FALSE;
3033         }
3034
3035         return TRUE;
3036 }
3037
3038 gboolean
3039 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3040 {
3041         TnyTransportAccount *transport_account;
3042         ModestMailOperation *mail_operation;
3043         MsgData *data;
3044         gchar *account_name;
3045         ModestAccountMgr *account_mgr;
3046         gboolean had_error = FALSE;
3047
3048         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
3049
3050         data = modest_msg_edit_window_get_msg_data (edit_window);
3051
3052         /* Check size */
3053         if (!enough_space_for_message (edit_window, data)) {
3054                 modest_msg_edit_window_free_msg_data (edit_window, data);
3055                 return FALSE;
3056         }
3057
3058         account_name = g_strdup (data->account_name);
3059         account_mgr = modest_runtime_get_account_mgr();
3060         if (!account_name)
3061                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3062         if (!account_name)
3063                 account_name = modest_account_mgr_get_default_account (account_mgr);
3064         if (!account_name) {
3065                 g_printerr ("modest: no account found\n");
3066                 modest_msg_edit_window_free_msg_data (edit_window, data);
3067                 return FALSE;
3068         }
3069
3070         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
3071                 account_name = g_strdup (data->account_name);
3072         }
3073
3074         transport_account =
3075                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3076                                       (modest_runtime_get_account_store (),
3077                                        account_name,
3078                                        TNY_ACCOUNT_TYPE_TRANSPORT));
3079         if (!transport_account) {
3080                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
3081                 g_free (account_name);
3082                 modest_msg_edit_window_free_msg_data (edit_window, data);
3083                 return FALSE;
3084         }
3085
3086         /* Create the mail operation */
3087         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
3088                                                                         NULL, NULL);
3089         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3090
3091         modest_mail_operation_save_to_drafts (mail_operation,
3092                                               transport_account,
3093                                               data->draft_msg,
3094                                               data->from,
3095                                               data->to, 
3096                                               data->cc, 
3097                                               data->bcc,
3098                                               data->subject,
3099                                               data->plain_body,
3100                                               data->html_body,
3101                                               data->attachments,
3102                                               data->images,
3103                                               data->priority_flags,
3104                                               data->references,
3105                                               data->in_reply_to,
3106                                               on_save_to_drafts_cb,
3107                                               g_object_ref(edit_window));
3108
3109 #ifdef MODEST_TOOLKIT_HILDON2
3110         /* In hildon2 we always show the information banner on saving to drafts.
3111          * It will be a system information banner in this case.
3112          */
3113         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3114         modest_platform_information_banner (NULL, NULL, text);
3115         g_free (text);
3116 #else
3117         ModestMainWindow *win = NULL;
3118
3119         /* Use the main window as the parent of the banner, if the
3120            main window does not exist it won't be shown, if the parent
3121            window exists then it's properly shown. We don't use the
3122            editor window because it could be closed (save to drafts
3123            could happen after closing the window */
3124         win = (ModestMainWindow *)
3125                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3126         if (win) {
3127                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3128                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3129                 g_free (text);
3130         }
3131 #endif
3132         modest_msg_edit_window_set_modified (edit_window, FALSE);
3133
3134         /* Frees */
3135         g_free (account_name);
3136         g_object_unref (G_OBJECT (transport_account));
3137         g_object_unref (G_OBJECT (mail_operation));
3138
3139         modest_msg_edit_window_free_msg_data (edit_window, data);
3140
3141 #ifndef MODEST_TOOLKIT_HILDON2
3142         /* ** FIXME **
3143          * If the drafts folder is selected then make the header view
3144          * insensitive while the message is being saved to drafts
3145          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3146          * is not very clean but it avoids letting the drafts folder
3147          * in an inconsistent state: the user could edit the message
3148          * being saved and undesirable things would happen.
3149          * In the average case the user won't notice anything at
3150          * all. In the worst case (the user is editing a really big
3151          * file from Drafts) the header view will be insensitive
3152          * during the saving process (10 or 20 seconds, depending on
3153          * the message). Anyway this is just a quick workaround: once
3154          * we find a better solution it should be removed
3155          * See NB#65125 (commend #18) for details.
3156          */
3157         if (!had_error && win != NULL) {
3158                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3159                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3160                 if (view != NULL) {
3161                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3162                         if (folder) {
3163                                 if (modest_tny_folder_is_local_folder(folder)) {
3164                                         TnyFolderType folder_type;
3165                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3166                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3167                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3168                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3169                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3170                                         }
3171                                 }
3172                         }
3173                         if (folder != NULL) g_object_unref(folder);
3174                 }
3175         }
3176 #endif
3177
3178         return !had_error;
3179 }
3180
3181 /* For instance, when clicking the Send toolbar button when editing a message: */
3182 gboolean
3183 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3184 {
3185         TnyTransportAccount *transport_account = NULL;
3186         gboolean had_error = FALSE;
3187         MsgData *data;
3188         ModestAccountMgr *account_mgr;
3189         gchar *account_name;
3190         ModestMailOperation *mail_operation;
3191         gchar *recipients;
3192
3193         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3194
3195         /* Check names but do not automatically add them to addressbook */
3196         if (!modest_msg_edit_window_check_names (edit_window, FALSE))
3197                 return TRUE;
3198
3199         data = modest_msg_edit_window_get_msg_data (edit_window);
3200
3201         recipients = g_strconcat (data->to?data->to:"", 
3202                                   data->cc?data->cc:"",
3203                                   data->bcc?data->bcc:"",
3204                                   NULL);
3205         if (recipients == NULL || recipients[0] == '\0') {
3206                 /* Empty subject -> no send */
3207                 g_free (recipients);
3208                 modest_msg_edit_window_free_msg_data (edit_window, data);
3209                 return FALSE;
3210         }
3211         g_free (recipients);
3212
3213         /* Check size */
3214         if (!enough_space_for_message (edit_window, data)) {
3215                 modest_msg_edit_window_free_msg_data (edit_window, data);
3216                 return FALSE;
3217         }
3218
3219         account_mgr = modest_runtime_get_account_mgr();
3220         account_name = g_strdup (data->account_name);
3221         if (!account_name)
3222                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3223
3224         if (!account_name)
3225                 account_name = modest_account_mgr_get_default_account (account_mgr);
3226
3227         if (!account_name) {
3228                 modest_msg_edit_window_free_msg_data (edit_window, data);
3229                 /* Run account setup wizard */
3230                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3231                         return TRUE;
3232                 }
3233         }
3234
3235         /* Get the currently-active transport account for this modest account: */
3236         if (account_name && strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3237                 transport_account =
3238                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3239                                               (modest_runtime_get_account_store (),
3240                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3241         }
3242
3243         if (!transport_account) {
3244                 modest_msg_edit_window_free_msg_data (edit_window, data);
3245                 /* Run account setup wizard */
3246                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3247                         return TRUE;
3248         }
3249
3250
3251         /* Create the mail operation */
3252         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3253         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3254
3255         modest_mail_operation_send_new_mail (mail_operation,
3256                                              transport_account,
3257                                              data->draft_msg,
3258                                              data->from,
3259                                              data->to,
3260                                              data->cc,
3261                                              data->bcc,
3262                                              data->subject,
3263                                              data->plain_body,
3264                                              data->html_body,
3265                                              data->attachments,
3266                                              data->images,
3267                                              data->references,
3268                                              data->in_reply_to,
3269                                              data->priority_flags);
3270
3271         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3272                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3273
3274         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3275                 const GError *error = modest_mail_operation_get_error (mail_operation);
3276                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3277                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3278                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3279                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3280                         had_error = TRUE;
3281                 }
3282         }
3283
3284         /* Free data: */
3285         g_free (account_name);
3286         g_object_unref (G_OBJECT (transport_account));
3287         g_object_unref (G_OBJECT (mail_operation));
3288
3289         modest_msg_edit_window_free_msg_data (edit_window, data);
3290
3291         if (!had_error) {
3292                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3293
3294                 /* Save settings and close the window: */
3295                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3296         }
3297
3298         return !had_error;
3299 }
3300
3301 void
3302 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3303                                   ModestMsgEditWindow *window)
3304 {
3305         ModestMsgEditFormatState *format_state = NULL;
3306
3307         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3308         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3309
3310         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3311                 return;
3312
3313         format_state = modest_msg_edit_window_get_format_state (window);
3314         g_return_if_fail (format_state != NULL);
3315
3316         format_state->bold = gtk_toggle_action_get_active (action);
3317         modest_msg_edit_window_set_format_state (window, format_state);
3318         g_free (format_state);
3319
3320 }
3321
3322 void
3323 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3324                                      ModestMsgEditWindow *window)
3325 {
3326         ModestMsgEditFormatState *format_state = NULL;
3327
3328         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3329         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3330
3331         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3332                 return;
3333
3334         format_state = modest_msg_edit_window_get_format_state (window);
3335         g_return_if_fail (format_state != NULL);
3336
3337         format_state->italics = gtk_toggle_action_get_active (action);
3338         modest_msg_edit_window_set_format_state (window, format_state);
3339         g_free (format_state);
3340
3341 }
3342
3343 void
3344 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3345                                      ModestMsgEditWindow *window)
3346 {
3347         ModestMsgEditFormatState *format_state = NULL;
3348
3349         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3350         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3351
3352         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3353                 return;
3354
3355         format_state = modest_msg_edit_window_get_format_state (window);
3356         g_return_if_fail (format_state != NULL);
3357
3358         format_state->bullet = gtk_toggle_action_get_active (action);
3359         modest_msg_edit_window_set_format_state (window, format_state);
3360         g_free (format_state);
3361
3362 }
3363
3364 void
3365 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3366                                      GtkRadioAction *selected,
3367                                      ModestMsgEditWindow *window)
3368 {
3369         ModestMsgEditFormatState *format_state = NULL;
3370         GtkJustification value;
3371
3372         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3373
3374         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3375                 return;
3376
3377         value = gtk_radio_action_get_current_value (selected);
3378
3379         format_state = modest_msg_edit_window_get_format_state (window);
3380         g_return_if_fail (format_state != NULL);
3381
3382         format_state->justification = value;
3383         modest_msg_edit_window_set_format_state (window, format_state);
3384         g_free (format_state);
3385 }
3386
3387 void
3388 modest_ui_actions_on_select_editor_color (GtkAction *action,
3389                                           ModestMsgEditWindow *window)
3390 {
3391         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3392         g_return_if_fail (GTK_IS_ACTION (action));
3393
3394         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3395                 return;
3396
3397         modest_msg_edit_window_select_color (window);
3398 }
3399
3400 void
3401 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3402                                                      ModestMsgEditWindow *window)
3403 {
3404         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3405         g_return_if_fail (GTK_IS_ACTION (action));
3406
3407         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3408                 return;
3409
3410         modest_msg_edit_window_select_background_color (window);
3411 }
3412
3413 void
3414 modest_ui_actions_on_insert_image (GObject *object,
3415                                    ModestMsgEditWindow *window)
3416 {
3417         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3418
3419
3420         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3421                 return;
3422
3423         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3424                 return;
3425
3426         modest_msg_edit_window_insert_image (window);
3427 }
3428
3429 void
3430 modest_ui_actions_on_attach_file (GtkAction *action,
3431                                   ModestMsgEditWindow *window)
3432 {
3433         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3434         g_return_if_fail (GTK_IS_ACTION (action));
3435
3436         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3437                 return;
3438
3439         modest_msg_edit_window_offer_attach_file (window);
3440 }
3441
3442 void
3443 modest_ui_actions_on_remove_attachments (GtkAction *action,
3444                                          ModestMsgEditWindow *window)
3445 {
3446         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3447
3448         modest_msg_edit_window_remove_attachments (window, NULL);
3449 }
3450
3451 static void
3452 do_create_folder_cb (ModestMailOperation *mail_op,
3453                      TnyFolderStore *parent_folder,
3454                      TnyFolder *new_folder,
3455                      gpointer user_data)
3456 {
3457         gchar *suggested_name = (gchar *) user_data;
3458         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3459         const GError *error;
3460
3461         error = modest_mail_operation_get_error (mail_op);
3462         if (error) {
3463                 gboolean disk_full = FALSE;
3464                 TnyAccount *account;
3465                 /* Show an error. If there was some problem writing to
3466                    disk, show it, otherwise show the generic folder
3467                    create error. We do it here and not in an error
3468                    handler because the call to do_create_folder will
3469                    stop the main loop in a gtk_dialog_run and then,
3470                    the message won't be shown until that dialog is
3471                    closed */
3472                 account = modest_mail_operation_get_account (mail_op);
3473                 if (account) {
3474                         disk_full =
3475                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3476                                                                                 (GtkWidget *) source_win,
3477                                                                                 (GError *) error,
3478                                                                                 account,
3479                                                                                 _("mail_in_ui_folder_create_error_memory"));
3480                         g_object_unref (account);
3481                 }
3482                 if (!disk_full) {
3483                         /* Show an error and try again if there is no
3484                            full memory condition */
3485                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3486                                                             _("mail_in_ui_folder_create_error"));
3487                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3488                 }
3489
3490         } else {
3491                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3492                  * FIXME: any other? */
3493                 GtkWidget *folder_view;
3494
3495 #ifndef MODEST_TOOLKIT_HILDON2
3496                 if (MODEST_IS_MAIN_WINDOW(source_win))
3497                         folder_view =
3498                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3499                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3500                 else
3501 #endif
3502                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3503                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3504
3505                 /* Select the newly created folder. It could happen
3506                    that the widget is no longer there (i.e. the window
3507                    has been destroyed, so we need to check this */
3508                 if (folder_view)
3509                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3510                                                           new_folder, FALSE);
3511                 g_object_unref (new_folder);
3512         }
3513         /* Free. Note that the first time it'll be NULL so noop */
3514         g_free (suggested_name);
3515         g_object_unref (source_win);
3516 }
3517
3518 typedef struct {
3519         gchar *folder_name;
3520         TnyFolderStore *parent;
3521 } CreateFolderConnect;
3522
3523 static void
3524 do_create_folder_performer (gboolean canceled,
3525                          GError *err,
3526                          GtkWindow *parent_window,
3527                          TnyAccount *account,
3528                          gpointer user_data)
3529 {
3530         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3531         ModestMailOperation *mail_op;
3532
3533         if (canceled || err) {
3534                 /* In disk full conditions we could get this error here */
3535                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3536                                                                 (GtkWidget *) parent_window, err,
3537                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
3538
3539                 /* This happens if we have selected the outbox folder
3540                    as the parent */
3541                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3542                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3543                         /* Show an error and retry */
3544                         modest_platform_information_banner ((GtkWidget *) parent_window,
3545                                                             NULL,
3546                                                             _("mail_in_ui_folder_create_error"));
3547
3548                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3549                 }
3550
3551                 goto frees;
3552         }
3553
3554         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3555         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3556                                          mail_op);
3557         modest_mail_operation_create_folder (mail_op,
3558                                              helper->parent,
3559                                              (const gchar *) helper->folder_name,
3560                                              do_create_folder_cb,
3561                                              g_strdup (helper->folder_name));
3562         g_object_unref (mail_op);
3563
3564  frees:
3565         if (helper->parent)
3566                 g_object_unref (helper->parent);
3567         if (helper->folder_name)
3568                 g_free (helper->folder_name);
3569         g_slice_free (CreateFolderConnect, helper);
3570 }
3571
3572
3573 static void
3574 do_create_folder (GtkWindow *parent_window,
3575                   TnyFolderStore *suggested_parent,
3576                   const gchar *suggested_name)
3577 {
3578         gint result;
3579         gchar *folder_name = NULL;
3580         TnyFolderStore *parent_folder = NULL;
3581
3582         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3583                                                         suggested_parent,
3584                                                         (gchar *) suggested_name,
3585                                                         &folder_name,
3586                                                         &parent_folder);
3587
3588         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3589                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3590                 helper->folder_name = g_strdup (folder_name);
3591                 helper->parent = g_object_ref (parent_folder);
3592
3593                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3594                                                                TRUE,
3595                                                                parent_folder,
3596                                                                do_create_folder_performer,
3597                                                                helper);
3598         }
3599
3600         if (folder_name)
3601                 g_free (folder_name);
3602         if (parent_folder)
3603                 g_object_unref (parent_folder);
3604 }
3605
3606 static void
3607 modest_ui_actions_create_folder(GtkWidget *parent_window,
3608                                 GtkWidget *folder_view,
3609                                 TnyFolderStore *parent_folder)
3610 {
3611         if (!parent_folder) {
3612 #ifdef MODEST_TOOLKIT_HILDON2
3613                 ModestTnyAccountStore *acc_store;
3614
3615                 acc_store = modest_runtime_get_account_store ();
3616
3617                 parent_folder = (TnyFolderStore *)
3618                         modest_tny_account_store_get_local_folders_account (acc_store);
3619 #else
3620                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3621 #endif
3622         }
3623
3624         if (parent_folder) {
3625                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3626                 g_object_unref (parent_folder);
3627         }
3628 }
3629
3630 void
3631 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3632 {
3633
3634         g_return_if_fail (MODEST_IS_WINDOW(window));
3635
3636 #ifndef MODEST_TOOLKIT_HILDON2
3637         if (MODEST_IS_MAIN_WINDOW (window)) {
3638                 GtkWidget *folder_view;
3639
3640                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3641                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3642                 if (!folder_view)
3643                         return;
3644
3645                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3646 #else
3647         if (MODEST_IS_FOLDER_WINDOW (window)) {
3648                 GtkWidget *folder_view;
3649
3650                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3651                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3652 #endif
3653         } else {
3654                 g_assert_not_reached ();
3655         }
3656 }
3657
3658 static void
3659 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3660                                                gpointer user_data)
3661 {
3662         const GError *error = NULL;
3663         gchar *message = NULL;
3664         gboolean mem_full;
3665         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3666
3667         /* Get error message */
3668         error = modest_mail_operation_get_error (mail_op);
3669         if (!error)
3670                 g_return_if_reached ();
3671
3672         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3673                                                                 (GError *) error, account);
3674         if (mem_full) {
3675                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3676         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3677                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3678                 message = _CS("ckdg_ib_folder_already_exists");
3679         } else if (error->domain == TNY_ERROR_DOMAIN &&
3680                    error->code == TNY_SERVICE_ERROR_STATE) {
3681                 /* This means that the folder is already in use (a
3682                    message is opened for example */
3683                 message = _("emev_ni_internal_error");
3684         } else {
3685                 message = _CS("ckdg_ib_unable_to_rename");
3686         }
3687
3688         /* We don't set a parent for the dialog because the dialog
3689            will be destroyed so the banner won't appear */
3690         modest_platform_information_banner (NULL, NULL, message);
3691
3692         if (account)
3693                 g_object_unref (account);
3694         if (mem_full)
3695                 g_free (message);
3696 }
3697
3698 typedef struct {
3699         TnyFolderStore *folder;
3700         gchar *new_name;
3701 } RenameFolderInfo;
3702
3703 static void
3704 on_rename_folder_cb (ModestMailOperation *mail_op,
3705                      TnyFolder *new_folder,
3706                      gpointer user_data)
3707 {
3708         ModestFolderView *folder_view;
3709
3710         /* If the window was closed when renaming a folder, or if
3711          * it's not a main window this will happen */
3712         if (!MODEST_IS_FOLDER_VIEW (user_data))
3713                 return;
3714
3715         folder_view = MODEST_FOLDER_VIEW (user_data);
3716         /* Note that if the rename fails new_folder will be NULL */
3717         if (new_folder) {
3718                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3719 #ifndef MODEST_TOOLKIT_HILDON2
3720         } else {
3721                 modest_folder_view_select_first_inbox_or_local (folder_view);
3722 #endif
3723         }
3724         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3725 }
3726
3727 static void
3728 on_rename_folder_performer (gboolean canceled,
3729                             GError *err,
3730                             GtkWindow *parent_window,
3731                             TnyAccount *account,
3732                             gpointer user_data)
3733 {
3734         ModestMailOperation *mail_op = NULL;
3735         GtkTreeSelection *sel = NULL;
3736         GtkWidget *folder_view = NULL;
3737         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3738
3739         if (canceled || err) {
3740                 /* In disk full conditions we could get this error here */
3741                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3742                                                                 (GtkWidget *) parent_window, err,
3743                                                                 account, NULL);
3744         } else {
3745
3746                 mail_op =
3747                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3748                                         modest_ui_actions_rename_folder_error_handler,
3749                                         parent_window, NULL);
3750
3751                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3752                                 mail_op);
3753 #ifndef MODEST_TOOLKIT_HILDON2
3754                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3755
3756                         folder_view = modest_main_window_get_child_widget (
3757                                 MODEST_MAIN_WINDOW (parent_window),
3758                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3759                 }
3760 #else
3761                 if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3762                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3763                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3764                 }
3765 #endif
3766
3767                 /* Clear the folders view */
3768                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3769                 gtk_tree_selection_unselect_all (sel);
3770
3771                 /* Actually rename the folder */
3772                 modest_mail_operation_rename_folder (mail_op,
3773                                                      TNY_FOLDER (data->folder),
3774                                                      (const gchar *) (data->new_name),
3775                                                      on_rename_folder_cb,
3776                                                      folder_view);
3777                 g_object_unref (mail_op);
3778         }
3779
3780         g_object_unref (data->folder);
3781         g_free (data->new_name);
3782         g_free (data);
3783 }
3784
3785 void
3786 modest_ui_actions_on_rename_folder (GtkAction *action,
3787                                      ModestWindow *window)
3788 {
3789         modest_ui_actions_on_edit_mode_rename_folder (window);
3790 }
3791
3792 gboolean
3793 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3794 {
3795         TnyFolderStore *folder;
3796         GtkWidget *folder_view;
3797         gboolean do_rename = TRUE;
3798
3799         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3800
3801 #ifndef MODEST_TOOLKIT_HILDON2
3802         if (MODEST_IS_MAIN_WINDOW (window)) {
3803                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3804                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3805                 if (!folder_view)
3806                         return FALSE;
3807 #else
3808         if (MODEST_IS_FOLDER_WINDOW (window)) {
3809                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3810 #endif
3811         } else {
3812                 return FALSE;
3813         }
3814
3815         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3816
3817         if (!folder)
3818                 return FALSE;
3819
3820         if (TNY_IS_FOLDER (folder)) {
3821                 gchar *folder_name = NULL;
3822                 gint response;
3823                 const gchar *current_name;
3824                 TnyFolderStore *parent;
3825
3826                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3827                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3828                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3829                                                                      parent, current_name,
3830                                                                      &folder_name);
3831                 g_object_unref (parent);
3832
3833                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3834                         do_rename = FALSE;
3835                 } else {
3836                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3837                         rename_folder_data->folder = g_object_ref (folder);
3838                         rename_folder_data->new_name = folder_name;
3839                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3840                                         folder, on_rename_folder_performer, rename_folder_data);
3841                 }
3842         }
3843         g_object_unref (folder);
3844         return do_rename;
3845 }
3846
3847 static void
3848 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3849                                                gpointer user_data)
3850 {
3851         GObject *win = modest_mail_operation_get_source (mail_op);
3852
3853         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3854                                                 _("mail_in_ui_folder_delete_error"),
3855                                                 FALSE);
3856         g_object_unref (win);
3857 }
3858
3859 typedef struct {
3860         TnyFolderStore *folder;
3861         gboolean move_to_trash;
3862 } DeleteFolderInfo;
3863
3864 static void
3865 on_delete_folder_cb (gboolean canceled,
3866                   GError *err,
3867                   GtkWindow *parent_window,
3868                   TnyAccount *account,
3869                   gpointer user_data)
3870 {
3871         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3872         GtkWidget *folder_view;
3873         ModestMailOperation *mail_op;
3874         GtkTreeSelection *sel;
3875
3876         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3877                 /* Note that the connection process can fail due to
3878                    memory low conditions as it can not successfully
3879                    store the summary */
3880                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3881                                                                      (GtkWidget*) parent_window, err,
3882                                                                      account, NULL))
3883                         g_debug ("Error connecting when trying to delete a folder");
3884                 g_object_unref (G_OBJECT (info->folder));
3885                 g_free (info);
3886                 return;
3887         }
3888
3889 #ifndef MODEST_TOOLKIT_HILDON2
3890         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3891                 folder_view = modest_main_window_get_child_widget (
3892                         MODEST_MAIN_WINDOW (parent_window),
3893                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3894 #else
3895         if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3896                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3897 #endif
3898         } else {
3899                 g_object_unref (G_OBJECT (info->folder));
3900                 g_free (info);
3901                 return;
3902         }
3903
3904         /* Unselect the folder before deleting it to free the headers */
3905         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3906         gtk_tree_selection_unselect_all (sel);
3907
3908         /* Create the mail operation */
3909         mail_op =
3910                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3911                                 modest_ui_actions_delete_folder_error_handler,
3912                                 NULL, NULL);
3913
3914         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3915                         mail_op);
3916         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3917
3918 #ifndef MODEST_TOOLKIT_HILDON2
3919         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3920 #endif
3921
3922         g_object_unref (mail_op);
3923         g_object_unref (info->folder);
3924         g_free (info);
3925 }
3926
3927 static gboolean
3928 delete_folder (ModestWindow *window, gboolean move_to_trash)
3929 {
3930         TnyFolderStore *folder;
3931         GtkWidget *folder_view;
3932         gint response;
3933         gchar *message;
3934
3935         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3936
3937 #ifndef MODEST_TOOLKIT_HILDON2
3938         if (MODEST_IS_MAIN_WINDOW (window)) {
3939
3940                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3941                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3942 #else
3943         if (MODEST_IS_FOLDER_WINDOW (window)) {
3944                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3945 #endif
3946         } else {
3947                 return FALSE;
3948         }
3949         if (!folder_view)
3950                 return FALSE;
3951
3952         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3953
3954         if (!folder)
3955                 return FALSE;
3956
3957         /* Show an error if it's an account */
3958         if (!TNY_IS_FOLDER (folder)) {
3959                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3960                                                         _("mail_in_ui_folder_delete_error"),
3961                                                         FALSE);
3962                 g_object_unref (G_OBJECT (folder));
3963                 return FALSE;
3964         }
3965
3966         /* Ask the user */
3967         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3968                                     tny_folder_get_name (TNY_FOLDER (folder)));
3969         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3970                                                             (const gchar *) message);
3971         g_free (message);
3972
3973         if (response == GTK_RESPONSE_OK) {
3974                 TnyAccount *account = NULL;
3975                 DeleteFolderInfo *info = NULL;
3976                 info = g_new0(DeleteFolderInfo, 1);
3977                 info->folder = g_object_ref (folder);
3978                 info->move_to_trash = move_to_trash;
3979
3980                 account = tny_folder_get_account (TNY_FOLDER (folder));
3981                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3982                                                                TRUE,
3983                                                                TNY_FOLDER_STORE (account),
3984                                                                on_delete_folder_cb, info);
3985                 g_object_unref (account);
3986                 g_object_unref (folder);
3987                 return TRUE;
3988         } else {
3989                 return FALSE;
3990         }
3991 }
3992
3993 void
3994 modest_ui_actions_on_delete_folder (GtkAction *action,
3995                                     ModestWindow *window)
3996 {
3997         modest_ui_actions_on_edit_mode_delete_folder (window);
3998 }
3999
4000 gboolean
4001 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
4002 {
4003         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
4004
4005         return delete_folder (window, FALSE);
4006 }
4007
4008 #ifndef MODEST_TOOLKIT_HILDON2
4009 void
4010 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
4011 {
4012         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4013
4014         delete_folder (MODEST_WINDOW (main_window), TRUE);
4015 }
4016 #endif
4017
4018 typedef struct _PasswordDialogFields {
4019         GtkWidget *username;
4020         GtkWidget *password;
4021         GtkWidget *dialog;
4022 } PasswordDialogFields;
4023
4024 static void
4025 password_dialog_check_field (GtkEditable *editable,
4026                              PasswordDialogFields *fields)
4027 {
4028         const gchar *value;
4029         gboolean any_value_empty = FALSE;
4030
4031         value = modest_entry_get_text (fields->username);
4032         if ((value == NULL) || value[0] == '\0') {
4033                 any_value_empty = TRUE;
4034         }
4035         value = modest_entry_get_text (fields->password);
4036         if ((value == NULL) || value[0] == '\0') {
4037                 any_value_empty = TRUE;
4038         }
4039         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
4040 }
4041
4042 void
4043 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
4044                                          const gchar* server_account_name,
4045                                          gchar **username,
4046                                          gchar **password,
4047                                          gboolean *cancel,
4048                                          gboolean *remember,
4049                                          ModestMainWindow *main_window)
4050 {
4051         g_return_if_fail(server_account_name);
4052         gboolean completed = FALSE;
4053         PasswordDialogFields *fields = NULL;
4054
4055         /* Initalize output parameters: */
4056         if (cancel)
4057                 *cancel = FALSE;
4058
4059         if (remember)
4060                 *remember = TRUE;
4061
4062 #ifndef MODEST_TOOLKIT_GTK
4063         /* Maemo uses a different (awkward) button order,
4064          * It should probably just use gtk_alternative_dialog_button_order ().
4065          */
4066 #ifdef MODEST_TOOLKIT_HILDON2
4067         GtkWidget *dialog =
4068                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4069                                              NULL,
4070                                              GTK_DIALOG_MODAL,
4071                                              _HL("wdgt_bd_done"),
4072                                              GTK_RESPONSE_ACCEPT,
4073                                              NULL);
4074         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
4075                                         HILDON_MARGIN_DOUBLE);
4076 #else
4077         GtkWidget *dialog =
4078                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4079                                              NULL,
4080                                              GTK_DIALOG_MODAL,
4081                                              _("mcen_bd_dialog_ok"),
4082                                              GTK_RESPONSE_ACCEPT,
4083                                              _("mcen_bd_dialog_cancel"),
4084                                              GTK_RESPONSE_REJECT,
4085                                              NULL);
4086 #endif /* MODEST_TOOLKIT_HILDON2 */
4087 #else
4088         GtkWidget *dialog =
4089                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4090                                              NULL,
4091                                              GTK_DIALOG_MODAL,
4092                                              GTK_STOCK_CANCEL,
4093                                              GTK_RESPONSE_REJECT,
4094                                              GTK_STOCK_OK,
4095                                              GTK_RESPONSE_ACCEPT,
4096                                              NULL);
4097 #endif /* MODEST_TOOLKIT_GTK */
4098
4099         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
4100
4101         gchar *server_name = modest_account_mgr_get_server_account_hostname (
4102                 modest_runtime_get_account_mgr(), server_account_name);
4103         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
4104                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
4105                 if (cancel)
4106                         *cancel = TRUE;
4107                 gtk_widget_destroy (dialog);
4108                 return;
4109         }
4110
4111         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4112         GtkWidget *label = gtk_label_new (txt);
4113         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4114         g_free (txt);
4115         g_free (server_name);
4116         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4117                             FALSE, FALSE, 0);
4118         server_name = NULL;
4119
4120         /* username: */
4121         gchar *initial_username = modest_account_mgr_get_server_account_username (
4122                 modest_runtime_get_account_mgr(), server_account_name);
4123
4124         GtkWidget *entry_username = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
4125         if (initial_username)
4126                 modest_entry_set_text (entry_username, initial_username);
4127
4128         /* Dim this if a connection has ever succeeded with this username,
4129          * as per the UI spec: */
4130         /* const gboolean username_known =  */
4131         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4132         /*              modest_runtime_get_account_mgr(), server_account_name); */
4133         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4134
4135         /* We drop the username sensitive code and disallow changing it here
4136          * as tinymail does not support really changing the username in the callback
4137          */
4138         gtk_widget_set_sensitive (entry_username, FALSE);
4139
4140 #ifndef MODEST_TOOLKIT_GTK
4141         /* Auto-capitalization is the default, so let's turn it off: */
4142         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4143
4144         /* Create a size group to be used by all captions.
4145          * Note that HildonCaption does not create a default size group if we do not specify one.
4146          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4147         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4148
4149 #ifdef MODEST_TOOLKIT_HILDON2
4150         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4151                                                                   _("mail_fi_username"), FALSE,
4152                                                                   entry_username);
4153 #else
4154         GtkWidget *caption = hildon_caption_new (sizegroup,
4155                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
4156 #endif
4157         gtk_widget_show (entry_username);
4158         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4159                 FALSE, FALSE, MODEST_MARGIN_HALF);
4160         gtk_widget_show (caption);
4161 #else
4162         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
4163                             TRUE, FALSE, 0);
4164 #endif /* !MODEST_TOOLKIT_GTK */
4165
4166         /* password: */
4167         GtkWidget *entry_password = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
4168         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4169         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4170
4171 #ifndef MODEST_TOOLKIT_GTK
4172         /* Auto-capitalization is the default, so let's turn it off: */
4173         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4174                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4175
4176         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4177                                                        _("mail_fi_password"), FALSE,
4178                                                        entry_password);
4179         gtk_widget_show (entry_password);
4180         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4181                 FALSE, FALSE, MODEST_MARGIN_HALF);
4182         gtk_widget_show (caption);
4183         g_object_unref (sizegroup);
4184 #else
4185         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4186                             TRUE, FALSE, 0);
4187 #endif /* !MODEST_TOOLKIT_GTK */
4188
4189         if (initial_username != NULL)
4190                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4191
4192 /* This is not in the Maemo UI spec:
4193         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4194         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4195                             TRUE, FALSE, 0);
4196 */
4197
4198         fields = g_slice_new0 (PasswordDialogFields);
4199         fields->username = entry_username;
4200         fields->password = entry_password;
4201         fields->dialog = dialog;
4202
4203         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4204         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4205         password_dialog_check_field (NULL, fields);
4206
4207         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4208
4209         while (!completed) {
4210
4211                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4212                         if (username) {
4213                                 *username = g_strdup (modest_entry_get_text (entry_username));
4214
4215                                 /* Note that an empty field becomes the "" string */
4216                                 if (*username && strlen (*username) > 0) {
4217                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4218                                                                                         server_account_name,
4219                                                                                         *username);
4220                                         completed = TRUE;
4221
4222                                         const gboolean username_was_changed =
4223                                                 (strcmp (*username, initial_username) != 0);
4224                                         if (username_was_changed) {
4225                                                 g_warning ("%s: tinymail does not yet support changing the "
4226                                                            "username in the get_password() callback.\n", __FUNCTION__);
4227                                         }
4228                                 } else {
4229                                         g_free (*username);
4230                                         *username = NULL;
4231                                         /* Show error */
4232                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4233                                                                             _("mcen_ib_username_pw_incorrect"));
4234                                         completed = FALSE;
4235                                 }
4236                         }
4237
4238                         if (password) {
4239                                 *password = g_strdup (modest_entry_get_text (entry_password));
4240
4241                                 /* We do not save the password in the configuration,
4242                                  * because this function is only called for passwords that should
4243                                  * not be remembered:
4244                                  modest_server_account_set_password (
4245                                  modest_runtime_get_account_mgr(), server_account_name,
4246                                  *password);
4247                                  */
4248                         }
4249                         if (cancel)
4250                                 *cancel   = FALSE;
4251                 } else {
4252 #ifndef MODEST_TOOLKIT_HILDON2
4253                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4254                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4255 #endif
4256                         completed = TRUE;
4257                         if (username)
4258                                 *username = NULL;
4259                         if (password)
4260                                 *password = NULL;
4261                         if (cancel)
4262                                 *cancel   = TRUE;
4263                 }
4264         }
4265
4266 /* This is not in the Maemo UI spec:
4267         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4268                 *remember = TRUE;
4269         else
4270                 *remember = FALSE;
4271 */
4272
4273         g_free (initial_username);
4274         gtk_widget_destroy (dialog);
4275         g_slice_free (PasswordDialogFields, fields);
4276
4277         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4278 }
4279
4280 void
4281 modest_ui_actions_on_cut (GtkAction *action,
4282                           ModestWindow *window)
4283 {
4284         GtkWidget *focused_widget;
4285         GtkClipboard *clipboard;
4286
4287         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4288         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4289         if (GTK_IS_EDITABLE (focused_widget)) {
4290                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4291                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4292                 gtk_clipboard_store (clipboard);
4293         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4294                 GtkTextBuffer *buffer;
4295
4296                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4297                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4298                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4299                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4300                         gtk_clipboard_store (clipboard);
4301                 }
4302         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4303                 TnyList *header_list = modest_header_view_get_selected_headers (
4304                                 MODEST_HEADER_VIEW (focused_widget));
4305                 gboolean continue_download = FALSE;
4306                 gint num_of_unc_msgs;
4307
4308                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4309
4310                 if (num_of_unc_msgs) {
4311                         TnyAccount *account = get_account_from_header_list (header_list);
4312                         if (account) {
4313                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4314                                 g_object_unref (account);
4315                         }
4316                 }
4317
4318                 if (num_of_unc_msgs == 0 || continue_download) {
4319 /*                      modest_platform_information_banner (
4320                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4321                         modest_header_view_cut_selection (
4322                                         MODEST_HEADER_VIEW (focused_widget));
4323                 }
4324
4325                 g_object_unref (header_list);
4326         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4327                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4328         }
4329 }
4330
4331 void
4332 modest_ui_actions_on_copy (GtkAction *action,
4333                            ModestWindow *window)
4334 {
4335         GtkClipboard *clipboard;
4336         GtkWidget *focused_widget;
4337         gboolean copied = TRUE;
4338
4339         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4340         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4341
4342         if (GTK_IS_LABEL (focused_widget)) {
4343                 gchar *selection;
4344                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4345                 gtk_clipboard_set_text (clipboard, selection, -1);
4346                 g_free (selection);
4347                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4348                 gtk_clipboard_store (clipboard);
4349         } else if (GTK_IS_EDITABLE (focused_widget)) {
4350                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4351                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4352                 gtk_clipboard_store (clipboard);
4353         } else if (GTK_IS_HTML (focused_widget)) {
4354                 const gchar *sel;
4355                 int len = -1;
4356                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4357                 if ((sel == NULL) || (sel[0] == '\0')) {
4358                         copied = FALSE;
4359                 } else {
4360                         gtk_html_copy (GTK_HTML (focused_widget));
4361                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4362                         gtk_clipboard_store (clipboard);
4363                 }
4364         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4365                 GtkTextBuffer *buffer;
4366                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4367                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4368                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4369                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4370                         gtk_clipboard_store (clipboard);
4371                 }
4372         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4373                 TnyList *header_list = modest_header_view_get_selected_headers (
4374                                 MODEST_HEADER_VIEW (focused_widget));
4375                 gboolean continue_download = FALSE;
4376                 gint num_of_unc_msgs;
4377
4378                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4379
4380                 if (num_of_unc_msgs) {
4381                         TnyAccount *account = get_account_from_header_list (header_list);
4382                         if (account) {
4383                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4384                                 g_object_unref (account);
4385                         }
4386                 }
4387
4388                 if (num_of_unc_msgs == 0 || continue_download) {
4389                         modest_platform_information_banner (
4390                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4391                         modest_header_view_copy_selection (
4392                                         MODEST_HEADER_VIEW (focused_widget));
4393                 } else
4394                         copied = FALSE;
4395
4396                 g_object_unref (header_list);
4397
4398         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4399                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4400         }
4401
4402         /* Show information banner if there was a copy to clipboard */
4403         if(copied)
4404                 modest_platform_information_banner (
4405                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4406 }
4407
4408 void
4409 modest_ui_actions_on_undo (GtkAction *action,
4410                            ModestWindow *window)
4411 {
4412         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4413                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4414 #ifndef MODEST_TOOLKIT_HILDON2
4415         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4416                 ModestEmailClipboard *clipboard = NULL;
4417                 /* Clear clipboard source */
4418                 clipboard = modest_runtime_get_email_clipboard ();
4419                 modest_email_clipboard_clear (clipboard);
4420 #endif
4421         } else {
4422                 g_return_if_reached ();
4423         }
4424 }
4425
4426 void
4427 modest_ui_actions_on_redo (GtkAction *action,
4428                            ModestWindow *window)
4429 {
4430         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4431                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4432         }
4433         else {
4434                 g_return_if_reached ();
4435         }
4436 }
4437
4438
4439 static void
4440 destroy_information_note (ModestMailOperation *mail_op,
4441                           gpointer user_data)
4442 {
4443         /* destroy information note */
4444         gtk_widget_destroy (GTK_WIDGET(user_data));
4445 }
4446
4447 static void
4448 destroy_folder_information_note (ModestMailOperation *mail_op,
4449                                  TnyFolder *new_folder,
4450                                  gpointer user_data)
4451 {
4452         /* destroy information note */
4453         gtk_widget_destroy (GTK_WIDGET(user_data));
4454 }
4455
4456
4457 static void
4458 paste_as_attachment_free (gpointer data)
4459 {
4460         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4461
4462         if (helper->banner) {
4463                 gtk_widget_destroy (helper->banner);
4464                 g_object_unref (helper->banner);
4465         }
4466         g_free (helper);
4467 }
4468
4469 static void
4470 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4471                             TnyHeader *header,
4472                             TnyMsg *msg,
4473                             gpointer userdata)
4474 {
4475         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4476         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4477
4478         if (msg == NULL)
4479                 return;
4480
4481         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4482
4483 }
4484
4485 void
4486 modest_ui_actions_on_paste (GtkAction *action,
4487                             ModestWindow *window)
4488 {
4489         GtkWidget *focused_widget = NULL;
4490         GtkWidget *inf_note = NULL;
4491         ModestMailOperation *mail_op = NULL;
4492
4493         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4494         if (GTK_IS_EDITABLE (focused_widget)) {
4495                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4496         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4497                 ModestEmailClipboard *e_clipboard = NULL;
4498                 e_clipboard = modest_runtime_get_email_clipboard ();
4499                 if (modest_email_clipboard_cleared (e_clipboard)) {
4500                         GtkTextBuffer *buffer;
4501                         GtkClipboard *clipboard;
4502
4503                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4504                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4505                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4506                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4507                         ModestMailOperation *mail_op;
4508                         TnyFolder *src_folder = NULL;
4509                         TnyList *data = NULL;
4510                         gboolean delete;
4511                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4512                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4513                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4514                                                                            _CS("ckct_nw_pasting"));
4515                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4516                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4517                         if (helper->banner != NULL) {
4518                                 g_object_ref (G_OBJECT (helper->banner));
4519                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4520                         }
4521
4522                         if (data != NULL) {
4523                                 modest_mail_operation_get_msgs_full (mail_op,
4524                                                                      data,
4525                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4526                                                                      helper,
4527                                                                      paste_as_attachment_free);
4528                         }
4529                         /* Free */
4530                         if (data)
4531                                 g_object_unref (data);
4532                         if (src_folder)
4533                                 g_object_unref (src_folder);
4534
4535                 }
4536         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4537                 ModestEmailClipboard *clipboard = NULL;
4538                 TnyFolder *src_folder = NULL;
4539                 TnyFolderStore *folder_store = NULL;
4540                 TnyList *data = NULL;
4541                 gboolean delete = FALSE;
4542
4543                 /* Check clipboard source */
4544                 clipboard = modest_runtime_get_email_clipboard ();
4545                 if (modest_email_clipboard_cleared (clipboard))
4546                         return;
4547
4548                 /* Get elements to paste */
4549                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4550
4551                 /* Create a new mail operation */
4552                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4553
4554                 /* Get destination folder */
4555                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4556
4557                 /* transfer messages  */
4558                 if (data != NULL) {
4559                         gint response = 0;
4560
4561                         /* Ask for user confirmation */
4562                         response =
4563                                 modest_ui_actions_msgs_move_to_confirmation (window,
4564                                                                              TNY_FOLDER (folder_store),
4565                                                                              delete,
4566                                                                              data);
4567
4568                         if (response == GTK_RESPONSE_OK) {
4569                                 /* Launch notification */
4570                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4571                                                                              _CS("ckct_nw_pasting"));
4572                                 if (inf_note != NULL)  {
4573                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4574                                         gtk_widget_show (GTK_WIDGET(inf_note));
4575                                 }
4576
4577                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4578                                 modest_mail_operation_xfer_msgs (mail_op,
4579                                                                  data,
4580                                                                  TNY_FOLDER (folder_store),
4581                                                                  delete,
4582                                                                  destroy_information_note,
4583                                                                  inf_note);
4584                         } else {
4585                                 g_object_unref (mail_op);
4586                         }
4587
4588                 } else if (src_folder != NULL) {
4589                         /* Launch notification */
4590                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4591                                                                      _CS("ckct_nw_pasting"));
4592                         if (inf_note != NULL)  {
4593                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4594                                 gtk_widget_show (GTK_WIDGET(inf_note));
4595                         }
4596
4597                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4598                         modest_mail_operation_xfer_folder (mail_op,
4599                                                            src_folder,
4600                                                            folder_store,
4601                                                            delete,
4602                                                            destroy_folder_information_note,
4603                                                            inf_note);
4604                 }
4605
4606                 /* Free */
4607                 if (data != NULL)
4608                         g_object_unref (data);
4609                 if (src_folder != NULL)
4610                         g_object_unref (src_folder);
4611                 if (folder_store != NULL)
4612                         g_object_unref (folder_store);
4613         }
4614 }
4615
4616
4617 void
4618 modest_ui_actions_on_select_all (GtkAction *action,
4619                                  ModestWindow *window)
4620 {
4621         GtkWidget *focused_widget;
4622
4623         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4624         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4625                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4626         } else if (GTK_IS_LABEL (focused_widget)) {
4627                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4628         } else if (GTK_IS_EDITABLE (focused_widget)) {
4629                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4630         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4631                 GtkTextBuffer *buffer;
4632                 GtkTextIter start, end;
4633
4634                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4635                 gtk_text_buffer_get_start_iter (buffer, &start);
4636                 gtk_text_buffer_get_end_iter (buffer, &end);
4637                 gtk_text_buffer_select_range (buffer, &start, &end);
4638         } else if (GTK_IS_HTML (focused_widget)) {
4639                 gtk_html_select_all (GTK_HTML (focused_widget));
4640 #ifndef MODEST_TOOLKIT_HILDON2
4641         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4642                 GtkWidget *header_view = focused_widget;
4643                 GtkTreeSelection *selection = NULL;
4644
4645                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4646                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4647                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4648                 }
4649
4650                 /* Disable window dimming management */
4651                 modest_window_disable_dimming (MODEST_WINDOW(window));
4652
4653                 /* Select all messages */
4654                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4655                 gtk_tree_selection_select_all (selection);
4656
4657                 /* Set focuse on header view */
4658                 gtk_widget_grab_focus (header_view);
4659
4660                 /* Enable window dimming management */
4661                 modest_window_enable_dimming (MODEST_WINDOW(window));
4662                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4663                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4664 #endif
4665         }
4666
4667 }
4668
4669 void
4670 modest_ui_actions_on_mark_as_read (GtkAction *action,
4671                                    ModestWindow *window)
4672 {
4673         g_return_if_fail (MODEST_IS_WINDOW(window));
4674
4675         /* Mark each header as read */
4676         do_headers_action (window, headers_action_mark_as_read, NULL);
4677 }
4678
4679 void
4680 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4681                                      ModestWindow *window)
4682 {
4683         g_return_if_fail (MODEST_IS_WINDOW(window));
4684
4685         /* Mark each header as read */
4686         do_headers_action (window, headers_action_mark_as_unread, NULL);
4687 }
4688
4689 void
4690 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4691                                   GtkRadioAction *selected,
4692                                   ModestWindow *window)
4693 {
4694         gint value;
4695
4696         value = gtk_radio_action_get_current_value (selected);
4697         if (MODEST_IS_WINDOW (window)) {
4698                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4699         }
4700 }
4701
4702 void
4703 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4704                                                GtkRadioAction *selected,
4705                                                ModestWindow *window)
4706 {
4707         TnyHeaderFlags flags;
4708         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4709
4710         flags = gtk_radio_action_get_current_value (selected);
4711         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4712 }
4713
4714 void
4715 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4716                                                   GtkRadioAction *selected,
4717                                                   ModestWindow *window)
4718 {
4719         gint file_format;
4720
4721         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4722
4723         file_format = gtk_radio_action_get_current_value (selected);
4724         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4725 }
4726
4727
4728 void
4729 modest_ui_actions_on_zoom_plus (GtkAction *action,
4730                                 ModestWindow *window)
4731 {
4732         g_return_if_fail (MODEST_IS_WINDOW (window));
4733
4734         modest_window_zoom_plus (MODEST_WINDOW (window));
4735 }
4736
4737 void
4738 modest_ui_actions_on_zoom_minus (GtkAction *action,
4739                                  ModestWindow *window)
4740 {
4741         g_return_if_fail (MODEST_IS_WINDOW (window));
4742
4743         modest_window_zoom_minus (MODEST_WINDOW (window));
4744 }
4745
4746 void
4747 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4748                                            ModestWindow *window)
4749 {
4750         ModestWindowMgr *mgr;
4751         gboolean fullscreen, active;
4752         g_return_if_fail (MODEST_IS_WINDOW (window));
4753
4754         mgr = modest_runtime_get_window_mgr ();
4755
4756         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4757         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4758
4759         if (active != fullscreen) {
4760                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4761 #ifndef MODEST_TOOLKIT_HILDON2
4762                 gtk_window_present (GTK_WINDOW (window));
4763 #endif
4764         }
4765 }
4766
4767 void
4768 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4769                                         ModestWindow *window)
4770 {
4771         ModestWindowMgr *mgr;
4772         gboolean fullscreen;
4773
4774         g_return_if_fail (MODEST_IS_WINDOW (window));
4775
4776         mgr = modest_runtime_get_window_mgr ();
4777         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4778         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4779
4780 #ifndef MODEST_TOOLKIT_HILDON2
4781         gtk_window_present (GTK_WINDOW (window));
4782 #endif
4783 }
4784
4785 /*
4786  * Used by modest_ui_actions_on_details to call do_headers_action
4787  */
4788 static void
4789 headers_action_show_details (TnyHeader *header,
4790                              ModestWindow *window,
4791                              gpointer user_data)
4792
4793 {
4794         gboolean async_retrieval;
4795         TnyMsg *msg = NULL;
4796
4797         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4798                 async_retrieval = TRUE;
4799                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4800         } else {
4801                 async_retrieval = FALSE;
4802         }
4803         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4804         if (msg)
4805                 g_object_unref (msg);
4806 }
4807
4808 /*
4809  * Show the header details in a ModestDetailsDialog widget
4810  */
4811 void
4812 modest_ui_actions_on_details (GtkAction *action,
4813                               ModestWindow *win)
4814 {
4815         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4816                 TnyMsg *msg;
4817                 TnyHeader *header;
4818
4819                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4820                 if (!msg)
4821                         return;
4822
4823                 header = tny_msg_get_header (msg);
4824                 if (header) {
4825                         headers_action_show_details (header, win, NULL);
4826                         g_object_unref (header);
4827                 }
4828                 g_object_unref (msg);
4829 #ifndef MODEST_TOOLKIT_HILDON2
4830         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4831                 GtkWidget *folder_view, *header_view;
4832
4833                 /* Check which widget has the focus */
4834                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4835                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4836                 if (gtk_widget_is_focus (folder_view)) {
4837                         TnyFolderStore *folder_store
4838                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4839                         if (!folder_store) {
4840                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4841                                 return;
4842                         }
4843                         /* Show only when it's a folder */
4844                         /* This function should not be called for account items,
4845                          * because we dim the menu item for them. */
4846                         if (TNY_IS_FOLDER (folder_store)) {
4847                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4848                                                                            TNY_FOLDER (folder_store));
4849                         }
4850
4851                         g_object_unref (folder_store);
4852
4853                 } else {
4854                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4855                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4856                         /* Show details of each header */
4857                         do_headers_action (win, headers_action_show_details, header_view);
4858                 }
4859 #else
4860         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4861                 TnyFolder *folder;
4862                 GtkWidget *header_view;
4863
4864                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4865                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4866                 if (folder) {
4867                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4868                                                                    folder);
4869                         g_object_unref (folder);
4870                 }
4871 #endif
4872         }
4873 }
4874
4875 void
4876 modest_ui_actions_on_limit_error (GtkAction *action,
4877                                   ModestWindow *win)
4878 {
4879         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
4880
4881         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
4882
4883 }
4884
4885 void
4886 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4887                                      ModestMsgEditWindow *window)
4888 {
4889         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4890
4891         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4892 }
4893
4894 void
4895 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4896                                       ModestMsgEditWindow *window)
4897 {
4898         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4899
4900         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4901 }
4902
4903 #ifndef MODEST_TOOLKIT_HILDON2
4904 void
4905 modest_ui_actions_toggle_folders_view (GtkAction *action,
4906                                        ModestMainWindow *main_window)
4907 {
4908         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4909
4910         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4911                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4912         else
4913                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4914 }
4915 #endif
4916
4917 void
4918 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4919                                      ModestWindow *window)
4920 {
4921         gboolean active, fullscreen = FALSE;
4922         ModestWindowMgr *mgr;
4923
4924         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4925
4926         /* Check if we want to toggle the toolbar view in fullscreen
4927            or normal mode */
4928         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4929                      "ViewShowToolbarFullScreen")) {
4930                 fullscreen = TRUE;
4931         }
4932
4933         /* Toggle toolbar */
4934         mgr = modest_runtime_get_window_mgr ();
4935         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4936 }
4937
4938 void
4939 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4940                                            ModestMsgEditWindow *window)
4941 {
4942         modest_msg_edit_window_select_font (window);
4943 }
4944
4945
4946 void
4947 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4948                                                   const gchar *display_name,
4949                                                   GtkWindow *window)
4950 {
4951         /* don't update the display name if it was already set;
4952          * updating the display name apparently is expensive */
4953         const gchar* old_name = gtk_window_get_title (window);
4954
4955         if (display_name == NULL)
4956                 display_name = " ";
4957
4958         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4959                 return; /* don't do anything */
4960
4961         /* This is usually used to change the title of the main window, which
4962          * is the one that holds the folder view. Note that this change can
4963          * happen even when the widget doesn't have the focus. */
4964         gtk_window_set_title (window, display_name);
4965
4966 }
4967
4968 void
4969 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4970 {
4971         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4972         modest_msg_edit_window_select_contacts (window);
4973 }
4974
4975 void
4976 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4977 {
4978         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4979         modest_msg_edit_window_check_names (window, FALSE);
4980 }
4981
4982 #ifndef MODEST_TOOLKIT_HILDON2
4983 /*
4984  * This function is used to track changes in the selection of the
4985  * folder view that is inside the "move to" dialog to enable/disable
4986  * the OK button because we do not want the user to select a disallowed
4987  * destination for a folder.
4988  * The user also not desired to be able to use NEW button on items where
4989  * folder creation is not possibel.
4990  */
4991 static void
4992 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4993                                             TnyFolderStore *folder_store,
4994                                             gboolean selected,
4995                                             gpointer user_data)
4996 {
4997         GtkWidget *dialog = NULL;
4998         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4999         gboolean moving_folder = FALSE;
5000         gboolean is_local_account = TRUE;
5001         GtkWidget *folder_view = NULL;
5002         ModestTnyFolderRules rules;
5003
5004         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
5005
5006         if (!selected)
5007                 return;
5008
5009         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
5010         if (!dialog)
5011                 return;
5012
5013         /* check if folder_store is an remote account */
5014         if (TNY_IS_ACCOUNT (folder_store)) {
5015                 TnyAccount *local_account = NULL;
5016                 TnyAccount *mmc_account = NULL;
5017                 ModestTnyAccountStore *account_store = NULL;
5018
5019                 account_store = modest_runtime_get_account_store ();
5020                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
5021                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
5022
5023                 if ((gpointer) local_account != (gpointer) folder_store &&
5024                     (gpointer) mmc_account != (gpointer) folder_store) {
5025                         ModestProtocolType proto;
5026                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
5027                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
5028                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
5029                         }
5030                         is_local_account = FALSE;
5031                         /* New button should be dimmed on remote
5032                            POP account root */
5033                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5034                                                                                          proto,
5035                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
5036                 }
5037                 g_object_unref (local_account);
5038
5039                 /* It could not exist */
5040                 if (mmc_account)
5041                         g_object_unref (mmc_account);
5042         }
5043
5044         /* Check the target folder rules */
5045         if (TNY_IS_FOLDER (folder_store)) {
5046                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
5047                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
5048                         ok_sensitive = FALSE;
5049                         new_sensitive = FALSE;
5050                         goto end;
5051                 }
5052         }
5053
5054         /* Check if we're moving a folder */
5055         if (MODEST_IS_MAIN_WINDOW (user_data)) {
5056                 /* Get the widgets */
5057                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
5058                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5059                 if (gtk_widget_is_focus (folder_view))
5060                         moving_folder = TRUE;
5061         }
5062
5063         if (moving_folder) {
5064                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
5065
5066                 /* Get the folder to move */
5067                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5068
5069                 /* Check that we're not moving to the same folder */
5070                 if (TNY_IS_FOLDER (moved_folder)) {
5071                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
5072                         if (parent == folder_store)
5073                                 ok_sensitive = FALSE;
5074                         g_object_unref (parent);
5075                 }
5076
5077                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
5078                         /* Do not allow to move to an account unless it's the
5079                            local folders account */
5080                         if (!is_local_account)
5081                                 ok_sensitive = FALSE;
5082                 }
5083
5084                 if (ok_sensitive && (moved_folder == folder_store)) {
5085                         /* Do not allow to move to itself */
5086                         ok_sensitive = FALSE;
5087                 }
5088                 g_object_unref (moved_folder);
5089         } else {
5090                 TnyFolder *src_folder = NULL;
5091
5092                 /* Moving a message */
5093                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
5094
5095                         TnyHeader *header = NULL;
5096                         header = modest_msg_view_window_get_header
5097                                 (MODEST_MSG_VIEW_WINDOW (user_data));
5098                         if (!TNY_IS_HEADER(header))
5099                                 g_warning ("%s: could not get source header", __FUNCTION__);
5100                         else
5101                                 src_folder = tny_header_get_folder (header);
5102
5103                         if (header)
5104                                 g_object_unref (header);
5105                 } else {
5106                         src_folder =
5107                                 TNY_FOLDER (modest_folder_view_get_selected
5108                                             (MODEST_FOLDER_VIEW (folder_view)));
5109                 }
5110
5111                 if (TNY_IS_FOLDER(src_folder)) {
5112                         /* Do not allow to move the msg to the same folder */
5113                         /* Do not allow to move the msg to an account */
5114                         if ((gpointer) src_folder == (gpointer) folder_store ||
5115                             TNY_IS_ACCOUNT (folder_store))
5116                                 ok_sensitive = FALSE;
5117                         g_object_unref (src_folder);
5118                 } else
5119                         g_warning ("%s: could not get source folder", __FUNCTION__);
5120         }
5121
5122  end:
5123         /* Set sensitivity of the OK and NEW button */
5124         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5125         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5126 }
5127 #endif
5128
5129 static void
5130 on_move_to_dialog_response (GtkDialog *dialog,
5131                             gint       response,
5132                             gpointer   user_data)
5133 {
5134         GtkWidget *parent_win;
5135         MoveToInfo *helper = NULL;
5136         ModestFolderView *folder_view;
5137         gboolean unset_edit_mode = FALSE;
5138
5139         helper = (MoveToInfo *) user_data;
5140
5141         parent_win = (GtkWidget *) helper->win;
5142         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5143                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5144         switch (response) {
5145                 TnyFolderStore *dst_folder;
5146                 TnyFolderStore *selected;
5147
5148         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5149                 selected = modest_folder_view_get_selected (folder_view);
5150                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5151                 g_object_unref (selected);
5152                 return;
5153         case GTK_RESPONSE_NONE:
5154         case GTK_RESPONSE_CANCEL:
5155         case GTK_RESPONSE_DELETE_EVENT:
5156                 break;
5157         case GTK_RESPONSE_OK:
5158                 dst_folder = modest_folder_view_get_selected (folder_view);
5159
5160 #ifndef MODEST_TOOLKIT_HILDON2
5161                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5162                         /* Clean list to move used for filtering */
5163                         modest_folder_view_set_list_to_move (folder_view, NULL);
5164
5165                         modest_ui_actions_on_main_window_move_to (NULL,
5166                                                                   GTK_WIDGET (folder_view),
5167                                                                   dst_folder,
5168                                                                   MODEST_MAIN_WINDOW (parent_win));
5169 #else
5170                 if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5171                         /* Clean list to move used for filtering */
5172                         modest_folder_view_set_list_to_move (folder_view, NULL);
5173
5174                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5175                                                                     dst_folder,
5176                                                                     helper->list,
5177                                                                     GTK_WINDOW (parent_win));
5178 #endif
5179                 } else {
5180                         /* if the user selected a root folder
5181                            (account) then do not perform any action */
5182                         if (TNY_IS_ACCOUNT (dst_folder)) {
5183                                 g_signal_stop_emission_by_name (dialog, "response");
5184                                 return;
5185                         }
5186
5187                         /* Clean list to move used for filtering */
5188                         modest_folder_view_set_list_to_move (folder_view, NULL);
5189
5190                         /* Moving from headers window in edit mode */
5191                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5192                                                              dst_folder,
5193                                                              MODEST_WINDOW (parent_win));
5194                 }
5195
5196                 if (dst_folder)
5197                         g_object_unref (dst_folder);
5198
5199                 unset_edit_mode = TRUE;
5200                 break;
5201         default:
5202                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5203         }
5204
5205         /* Free the helper and exit */
5206         if (helper->list)
5207                 g_object_unref (helper->list);
5208         if (unset_edit_mode) {
5209 #ifdef MODEST_TOOLKIT_HILDON2
5210                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5211 #endif
5212         }
5213         g_slice_free (MoveToInfo, helper);
5214         gtk_widget_destroy (GTK_WIDGET (dialog));
5215 }
5216
5217 static GtkWidget*
5218 create_move_to_dialog (GtkWindow *win,
5219                        GtkWidget *folder_view,
5220                        TnyList *list_to_move)
5221 {
5222         GtkWidget *dialog, *tree_view = NULL;
5223
5224         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5225
5226 #ifndef MODEST_TOOLKIT_HILDON2
5227         /* Track changes in the selection to
5228          * disable the OK button whenever "Move to" is not possible
5229          * disbale NEW button whenever New is not possible */
5230         g_signal_connect (tree_view,
5231                           "folder_selection_changed",
5232                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5233                           win);
5234 #endif
5235
5236         /* It could happen that we're trying to move a message from a
5237            window (msg window for example) after the main window was
5238            closed, so we can not just get the model of the folder
5239            view */
5240         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5241                 const gchar *visible_id = NULL;
5242
5243                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5244                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5245                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5246                                                MODEST_FOLDER_VIEW(tree_view));
5247
5248                 visible_id =
5249                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5250
5251                 /* Show the same account than the one that is shown in the main window */
5252                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5253                                                                              visible_id);
5254         } else {
5255                 const gchar *active_account_name = NULL;
5256                 ModestAccountMgr *mgr = NULL;
5257                 ModestAccountSettings *settings = NULL;
5258                 ModestServerAccountSettings *store_settings = NULL;
5259
5260                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5261                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5262                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
5263                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
5264
5265                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5266                 mgr = modest_runtime_get_account_mgr ();
5267                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5268
5269                 if (settings) {
5270                         const gchar *store_account_name;
5271                         store_settings = modest_account_settings_get_store_settings (settings);
5272                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5273
5274                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5275                                                                                      store_account_name);
5276                         g_object_unref (store_settings);
5277                         g_object_unref (settings);
5278                 }
5279         }
5280
5281         /* we keep a pointer to the embedded folder view, so we can
5282          *   retrieve it with get_folder_view_from_move_to_dialog (see
5283          *   above) later (needed for focus handling)
5284          */
5285         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5286
5287         /* Hide special folders */
5288 #ifndef MODEST_TOOLKIT_HILDON2
5289         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5290 #endif
5291         if (list_to_move)
5292                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5293 #ifndef MODEST_TOOLKIT_HILDON2
5294         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5295 #endif
5296
5297         gtk_widget_show (GTK_WIDGET (tree_view));
5298
5299         return dialog;
5300 }
5301
5302 /*
5303  * Shows a confirmation dialog to the user when we're moving messages
5304  * from a remote server to the local storage. Returns the dialog
5305  * response. If it's other kind of movement then it always returns
5306  * GTK_RESPONSE_OK
5307  *
5308  * This one is used by the next functions:
5309  *      modest_ui_actions_on_paste                      - commented out
5310  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5311  */
5312 gint
5313 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5314                                              TnyFolder *dest_folder,
5315                                              gboolean delete,
5316                                              TnyList *headers)
5317 {
5318         gint response = GTK_RESPONSE_OK;
5319         TnyAccount *account = NULL;
5320         TnyFolder *src_folder = NULL;
5321         TnyIterator *iter = NULL;
5322         TnyHeader *header = NULL;
5323
5324         /* return with OK if the destination is a remote folder */
5325         if (modest_tny_folder_is_remote_folder (dest_folder))
5326                 return GTK_RESPONSE_OK;
5327
5328         /* Get source folder */
5329         iter = tny_list_create_iterator (headers);
5330         header = TNY_HEADER (tny_iterator_get_current (iter));
5331         if (header) {
5332                 src_folder = tny_header_get_folder (header);
5333                 g_object_unref (header);
5334         }
5335         g_object_unref (iter);
5336
5337         /* if no src_folder, message may be an attahcment */
5338         if (src_folder == NULL)
5339                 return GTK_RESPONSE_CANCEL;
5340
5341         /* If the source is a local or MMC folder */
5342         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5343                 g_object_unref (src_folder);
5344                 return GTK_RESPONSE_OK;
5345         }
5346
5347         /* Get the account */
5348         account = tny_folder_get_account (src_folder);
5349
5350         /* now if offline we ask the user */
5351         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5352                 response = GTK_RESPONSE_OK;
5353         else
5354                 response = GTK_RESPONSE_CANCEL;
5355
5356         /* Frees */
5357         g_object_unref (src_folder);
5358         g_object_unref (account);
5359
5360         return response;
5361 }
5362
5363 static void
5364 move_to_helper_destroyer (gpointer user_data)
5365 {
5366         MoveToHelper *helper = (MoveToHelper *) user_data;
5367
5368         /* Close the "Pasting" information banner */
5369         if (helper->banner) {
5370                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5371                 g_object_unref (helper->banner);
5372         }
5373         if (gtk_tree_row_reference_valid (helper->reference)) {
5374                 gtk_tree_row_reference_free (helper->reference);
5375                 helper->reference = NULL;
5376         }
5377         g_free (helper);
5378 }
5379
5380 static void
5381 move_to_cb (ModestMailOperation *mail_op,
5382             gpointer user_data)
5383 {
5384         MoveToHelper *helper = (MoveToHelper *) user_data;
5385         GObject *object = modest_mail_operation_get_source (mail_op);
5386
5387         /* Note that the operation could have failed, in that case do
5388            nothing */
5389         if (modest_mail_operation_get_status (mail_op) !=
5390             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5391                 goto frees;
5392
5393         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5394                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5395
5396                 if (!modest_msg_view_window_select_next_message (self) &&
5397                     !modest_msg_view_window_select_previous_message (self)) {
5398                         /* No more messages to view, so close this window */
5399                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5400                 }
5401 #ifndef MODEST_TOOLKIT_HILDON2
5402         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5403                    gtk_tree_row_reference_valid (helper->reference)) {
5404                 GtkWidget *header_view;
5405                 GtkTreePath *path;
5406                 GtkTreeSelection *sel;
5407
5408                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5409                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5410                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5411                 path = gtk_tree_row_reference_get_path (helper->reference);
5412                 /* We need to unselect the previous one
5413                    because we could be copying instead of
5414                    moving */
5415                 gtk_tree_selection_unselect_all (sel);
5416                 gtk_tree_selection_select_path (sel, path);
5417                 gtk_tree_path_free (path);
5418 #endif
5419         }
5420         g_object_unref (object);
5421
5422  frees:
5423         /* Destroy the helper */
5424         move_to_helper_destroyer (helper);
5425 }
5426
5427 static void
5428 folder_move_to_cb (ModestMailOperation *mail_op,
5429                    TnyFolder *new_folder,
5430                    gpointer user_data)
5431 {
5432         GObject *object;
5433
5434         object = modest_mail_operation_get_source (mail_op);
5435 #ifndef MODEST_TOOLKIT_HILDON2
5436         if (MODEST_IS_MAIN_WINDOW (object)) {
5437                 GtkWidget *folder_view;
5438                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5439                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5440                 g_object_ref (folder_view);
5441                 g_object_unref (object);
5442                 move_to_cb (mail_op, user_data);
5443                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5444                 g_object_unref (folder_view);
5445         } else {
5446 #else
5447                 {
5448 #endif
5449                 move_to_cb (mail_op, user_data);
5450         }
5451 }
5452
5453 static void
5454 msgs_move_to_cb (ModestMailOperation *mail_op,
5455                  gpointer user_data)
5456 {
5457         move_to_cb (mail_op, user_data);
5458 }
5459
5460 void
5461 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5462                                              gpointer user_data)
5463 {
5464         GObject *win = NULL;
5465         const GError *error;
5466         TnyAccount *account = NULL;
5467
5468 #ifndef MODEST_TOOLKIT_HILDON2
5469         ModestWindow *main_window = NULL;
5470
5471         /* Disable next automatic folder selection */
5472         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5473                                                          FALSE); /* don't create */
5474
5475         /* Show notification dialog only if the main window exists */
5476         if (main_window) {
5477                 GtkWidget *folder_view = NULL;
5478
5479                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5480                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5481                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5482
5483                 if (user_data && TNY_IS_FOLDER (user_data)) {
5484                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5485                                                           TNY_FOLDER (user_data), FALSE);
5486                 }
5487         }
5488 #endif
5489         win = modest_mail_operation_get_source (mail_op);
5490         error = modest_mail_operation_get_error (mail_op);
5491
5492         if (TNY_IS_FOLDER (user_data))
5493                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
5494         else if (TNY_IS_ACCOUNT (user_data))
5495                 account = g_object_ref (user_data);
5496
5497         /* If it's not a disk full error then show a generic error */
5498         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5499                                                              (GtkWidget *) win, (GError *) error,
5500                                                              account, NULL))
5501                 modest_platform_run_information_dialog ((GtkWindow *) win,
5502                                                         _("mail_in_ui_folder_move_target_error"),
5503                                                         FALSE);
5504         if (account)
5505                 g_object_unref (account);
5506         if (win)
5507                 g_object_unref (win);
5508 }
5509
5510 #ifndef MODEST_TOOLKIT_HILDON2
5511 static void
5512 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5513                        TnyHeader *header,
5514                        gboolean canceled,
5515                        TnyMsg *msg,
5516                        GError *err,
5517                        gpointer user_data)
5518 {
5519         TnyList *parts;
5520         TnyIterator *iter;
5521         gint pending_purges = 0;
5522         gboolean some_purged = FALSE;
5523         ModestWindow *win = MODEST_WINDOW (user_data);
5524         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5525
5526         /* If there was any error */
5527         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5528                 modest_window_mgr_unregister_header (mgr, header);
5529                 return;
5530         }
5531
5532         /* Once the message has been retrieved for purging, we check if
5533          * it's all ok for purging */
5534
5535         parts = tny_simple_list_new ();
5536         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5537         iter = tny_list_create_iterator (parts);
5538
5539         while (!tny_iterator_is_done (iter)) {
5540                 TnyMimePart *part;
5541                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5542                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5543                         if (tny_mime_part_is_purged (part))
5544                                 some_purged = TRUE;
5545                         else
5546                                 pending_purges++;
5547                 }
5548
5549                 if (part)
5550                         g_object_unref (part);
5551
5552                 tny_iterator_next (iter);
5553         }
5554         g_object_unref (iter);
5555
5556
5557         if (pending_purges>0) {
5558                 gint response;
5559                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5560
5561                 if (response == GTK_RESPONSE_OK) {
5562                         GtkWidget *info;
5563                         info =
5564                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5565                         iter = tny_list_create_iterator (parts);
5566                         while (!tny_iterator_is_done (iter)) {
5567                                 TnyMimePart *part;
5568
5569                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5570                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5571                                         tny_mime_part_set_purged (part);
5572
5573                                 if (part)
5574                                         g_object_unref (part);
5575
5576                                 tny_iterator_next (iter);
5577                         }
5578                         g_object_unref (iter);
5579
5580                         tny_msg_rewrite_cache (msg);
5581
5582                         gtk_widget_destroy (info);
5583                 }
5584         }
5585
5586         modest_window_mgr_unregister_header (mgr, header);
5587
5588         g_object_unref (parts);
5589 }
5590
5591 static void
5592 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5593                                                      ModestMainWindow *win)
5594 {
5595         GtkWidget *header_view;
5596         TnyList *header_list;
5597         TnyHeader *header;
5598         TnyHeaderFlags flags;
5599         ModestWindow *msg_view_window =  NULL;
5600         gboolean found;
5601
5602         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5603
5604         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5605                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5606
5607         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5608         if (!header_list) {
5609                 g_warning ("%s: no header selected", __FUNCTION__);
5610                 return;
5611         }
5612
5613         if (tny_list_get_length (header_list) == 1) {
5614                 TnyIterator *iter = tny_list_create_iterator (header_list);
5615                 header = TNY_HEADER (tny_iterator_get_current (iter));
5616                 g_object_unref (iter);
5617         } else
5618                 return;
5619
5620         if (!header || !TNY_IS_HEADER(header)) {
5621                 g_warning ("%s: header is not valid", __FUNCTION__);
5622                 return;
5623         }
5624
5625         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5626                                                           header, &msg_view_window);
5627         flags = tny_header_get_flags (header);
5628         if (!(flags & TNY_HEADER_FLAG_CACHED))
5629                 return;
5630         if (found) {
5631                 if (msg_view_window != NULL)
5632                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5633                 else {
5634                         /* do nothing; uid was registered before, so window is probably on it's way */
5635                         g_debug ("header %p has already been registered", header);
5636                 }
5637         } else {
5638                 ModestMailOperation *mail_op = NULL;
5639                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5640                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5641                                                                          modest_ui_actions_disk_operations_error_handler,
5642                                                                          NULL, NULL);
5643                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5644                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5645
5646                 g_object_unref (mail_op);
5647         }
5648         if (header)
5649                 g_object_unref (header);
5650         if (header_list)
5651                 g_object_unref (header_list);
5652 }
5653 #endif
5654
5655 /*
5656  * Checks if we need a connection to do the transfer and if the user
5657  * wants to connect to complete it
5658  */
5659 static void
5660 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5661                                        TnyFolderStore *src_folder,
5662                                        TnyList *headers,
5663                                        TnyFolder *dst_folder,
5664                                        gboolean delete_originals,
5665                                        gboolean *need_connection,
5666                                        gboolean *do_xfer)
5667 {
5668         TnyAccount *src_account;
5669         gint uncached_msgs = 0;
5670
5671         /* We don't need any further check if
5672          *
5673          * 1- the source folder is local OR
5674          * 2- the device is already online
5675          */
5676         if (!modest_tny_folder_store_is_remote (src_folder) ||
5677             tny_device_is_online (modest_runtime_get_device())) {
5678                 *need_connection = FALSE;
5679                 *do_xfer = TRUE;
5680                 return;
5681         }
5682
5683         /* We must ask for a connection when
5684          *
5685          *   - the message(s) is not already cached   OR
5686          *   - the message(s) is cached but the leave_on_server setting
5687          * is FALSE (because we need to sync the source folder to
5688          * delete the message from the server (for IMAP we could do it
5689          * offline, it'll take place the next time we get a
5690          * connection)
5691          */
5692         uncached_msgs = header_list_count_uncached_msgs (headers);
5693         src_account = get_account_from_folder_store (src_folder);
5694         if (uncached_msgs > 0) {
5695                 guint num_headers;
5696                 const gchar *msg;
5697
5698                 *need_connection = TRUE;
5699                 num_headers = tny_list_get_length (headers);
5700                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5701
5702                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5703                     GTK_RESPONSE_CANCEL) {
5704                         *do_xfer = FALSE;
5705                 } else {
5706                         *do_xfer = TRUE;
5707                 }
5708         } else {
5709                 /* The transfer is possible and the user wants to */
5710                 *do_xfer = TRUE;
5711
5712                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5713                         const gchar *account_name;
5714                         gboolean leave_on_server;
5715
5716                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5717                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5718                                                                                   account_name);
5719
5720                         if (leave_on_server == TRUE) {
5721                                 *need_connection = FALSE;
5722                         } else {
5723                                 *need_connection = TRUE;
5724                         }
5725                 } else {
5726                         *need_connection = FALSE;
5727                 }
5728         }
5729
5730         /* Frees */
5731         g_object_unref (src_account);
5732 }
5733
5734 static void
5735 xfer_messages_error_handler (ModestMailOperation *mail_op,
5736                              gpointer user_data)
5737 {
5738         GObject *win;
5739         const GError *error;
5740         TnyAccount *account;
5741
5742         win = modest_mail_operation_get_source (mail_op);
5743         error = modest_mail_operation_get_error (mail_op);
5744
5745         /* We cannot get the account from the mail op as that is the
5746            source account and for checking memory full conditions we
5747            need the destination one */
5748         account = TNY_ACCOUNT (user_data);
5749
5750         if (error &&
5751             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5752                                                              (GtkWidget *) win, (GError*) error,
5753                                                              account, _KR("cerm_memory_card_full"))) {
5754                 modest_platform_run_information_dialog ((GtkWindow *) win,
5755                                                         _("mail_in_ui_folder_move_target_error"),
5756                                                         FALSE);
5757         }
5758         if (win)
5759                 g_object_unref (win);
5760 }
5761
5762 typedef struct {
5763         TnyFolderStore *dst_folder;
5764         TnyList *headers;
5765 } XferMsgsHelper;
5766
5767 /**
5768  * Utility function that transfer messages from both the main window
5769  * and the msg view window when using the "Move to" dialog
5770  */
5771 static void
5772 xfer_messages_performer  (gboolean canceled,
5773                           GError *err,
5774                           GtkWindow *parent_window,
5775                           TnyAccount *account,
5776                           gpointer user_data)
5777 {
5778         ModestWindow *win = MODEST_WINDOW (parent_window);
5779         TnyAccount *dst_account = NULL;
5780         gboolean dst_forbids_message_add = FALSE;
5781         XferMsgsHelper *helper;
5782         MoveToHelper *movehelper;
5783         ModestMailOperation *mail_op;
5784
5785         helper = (XferMsgsHelper *) user_data;
5786
5787         if (canceled || err) {
5788                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5789                                                                      (GtkWidget *) parent_window, err,
5790                                                                      account, NULL)) {
5791                         /* Show the proper error message */
5792                         modest_ui_actions_on_account_connection_error (parent_window, account);
5793                 }
5794                 goto end;
5795         }
5796
5797         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5798
5799         /* tinymail will return NULL for local folders it seems */
5800         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5801                                                                                   modest_tny_account_get_protocol_type (dst_account),
5802                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
5803
5804         if (dst_forbids_message_add) {
5805                 modest_platform_information_banner (GTK_WIDGET (win),
5806                                                     NULL,
5807                                                     ngettext("mail_in_ui_folder_move_target_error",
5808                                                              "mail_in_ui_folder_move_targets_error",
5809                                                              tny_list_get_length (helper->headers)));
5810                 goto end;
5811         }
5812
5813         movehelper = g_new0 (MoveToHelper, 1);
5814
5815 #ifndef MODEST_TOOLKIT_HILDON2
5816         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5817                                                                _CS("ckct_nw_pasting"));
5818         if (movehelper->banner != NULL)  {
5819                 g_object_ref (movehelper->banner);
5820                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5821         }
5822
5823         if (MODEST_IS_MAIN_WINDOW (win)) {
5824                 GtkWidget *header_view =
5825                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5826                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5827                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5828         }
5829 #endif
5830
5831         /* Perform the mail operation */
5832         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5833                                                                  xfer_messages_error_handler,
5834                                                                  g_object_ref (dst_account),
5835                                                                  g_object_unref);
5836         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5837                                          mail_op);
5838
5839         modest_mail_operation_xfer_msgs (mail_op,
5840                                          helper->headers,
5841                                          TNY_FOLDER (helper->dst_folder),
5842                                          TRUE,
5843                                          msgs_move_to_cb,
5844                                          movehelper);
5845
5846         g_object_unref (G_OBJECT (mail_op));
5847  end:
5848         if (dst_account)
5849                 g_object_unref (dst_account);
5850         g_object_unref (helper->dst_folder);
5851         g_object_unref (helper->headers);
5852         g_slice_free (XferMsgsHelper, helper);
5853 }
5854
5855 typedef struct {
5856         TnyFolder *src_folder;
5857         TnyFolderStore *dst_folder;
5858         gboolean delete_original;
5859         GtkWidget *folder_view;
5860 } MoveFolderInfo;
5861
5862 static void
5863 on_move_folder_cb (gboolean canceled,
5864                    GError *err,
5865                    GtkWindow *parent_window,
5866                    TnyAccount *account,
5867                    gpointer user_data)
5868 {
5869         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5870         GtkTreeSelection *sel;
5871         ModestMailOperation *mail_op = NULL;
5872
5873         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5874                 /* Note that the connection process can fail due to
5875                    memory low conditions as it can not successfully
5876                    store the summary */
5877                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5878                                                                      (GtkWidget*) parent_window, err,
5879                                                                      account, NULL))
5880                         g_debug ("Error connecting when trying to move a folder");
5881
5882                 g_object_unref (G_OBJECT (info->src_folder));
5883                 g_object_unref (G_OBJECT (info->dst_folder));
5884                 g_free (info);
5885                 return;
5886         }
5887
5888         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5889 #ifndef MODEST_TOOLKIT_HILDON2
5890         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5891                         _CS("ckct_nw_pasting"));
5892         if (helper->banner != NULL)  {
5893                 g_object_ref (helper->banner);
5894                 gtk_widget_show (GTK_WIDGET(helper->banner));
5895         }
5896 #endif
5897         /* Clean folder on header view before moving it */
5898         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5899         gtk_tree_selection_unselect_all (sel);
5900
5901         /* Let gtk events run. We need that the folder
5902            view frees its reference to the source
5903            folder *before* issuing the mail operation
5904            so we need the signal handler of selection
5905            changed to happen before the mail
5906            operation
5907         while (gtk_events_pending ())
5908                 gtk_main_iteration ();   */
5909
5910         mail_op =
5911                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5912                                                                modest_ui_actions_move_folder_error_handler,
5913                                                                g_object_ref (info->dst_folder), g_object_unref);
5914         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5915                                          mail_op);
5916
5917 #ifndef MODEST_TOOLKIT_HILDON2
5918         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5919                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5920                                                   TNY_FOLDER (info->dst_folder), TRUE);
5921         }
5922 #endif
5923         modest_mail_operation_xfer_folder (mail_op,
5924                         TNY_FOLDER (info->src_folder),
5925                         info->dst_folder,
5926                         info->delete_original,
5927                         folder_move_to_cb,
5928                         helper);
5929         g_object_unref (G_OBJECT (info->src_folder));
5930
5931         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5932         /* } */
5933
5934         /* Unref mail operation */
5935         g_object_unref (G_OBJECT (mail_op));
5936         g_object_unref (G_OBJECT (info->dst_folder));
5937         g_free (user_data);
5938 }
5939
5940 static TnyAccount *
5941 get_account_from_folder_store (TnyFolderStore *folder_store)
5942 {
5943         if (TNY_IS_ACCOUNT (folder_store))
5944                 return g_object_ref (folder_store);
5945         else
5946                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5947 }
5948
5949 #ifndef MODEST_TOOLKIT_HILDON2
5950 /*
5951  * UI handler for the "Move to" action when invoked from the
5952  * ModestMainWindow
5953  */
5954 static void
5955 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5956                                           GtkWidget *folder_view,
5957                                           TnyFolderStore *dst_folder,
5958                                           ModestMainWindow *win)
5959 {
5960         ModestHeaderView *header_view = NULL;
5961         TnyFolderStore *src_folder = NULL;
5962
5963         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5964
5965         /* Get the source folder */
5966         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5967
5968         /* Get header view */
5969         header_view = (ModestHeaderView *)
5970                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5971
5972         /* Get folder or messages to transfer */
5973         if (gtk_widget_is_focus (folder_view)) {
5974                 gboolean do_xfer = TRUE;
5975
5976                 /* Allow only to transfer folders to the local root folder */
5977                 if (TNY_IS_ACCOUNT (dst_folder) &&
5978                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5979                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5980                         do_xfer = FALSE;
5981                 } else if (!TNY_IS_FOLDER (src_folder)) {
5982                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5983                         do_xfer = FALSE;
5984                 }
5985
5986                 if (do_xfer) {
5987                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5988                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5989
5990                         info->src_folder = g_object_ref (src_folder);
5991                         info->dst_folder = g_object_ref (dst_folder);
5992                         info->delete_original = TRUE;
5993                         info->folder_view = folder_view;
5994
5995                         connect_info->callback = on_move_folder_cb;
5996                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5997                         connect_info->data = info;
5998
5999                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6000                                                                    TNY_FOLDER_STORE (src_folder),
6001                                                                    connect_info);
6002                 }
6003         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
6004                 TnyList *headers;
6005
6006                 headers = modest_header_view_get_selected_headers(header_view);
6007
6008                 /* Transfer the messages */
6009                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
6010                                                             headers, TNY_FOLDER (dst_folder));
6011
6012                 g_object_unref (headers);
6013         }
6014
6015         /* Frees */
6016         g_object_unref (src_folder);
6017 }
6018 #endif
6019
6020 #ifdef MODEST_TOOLKIT_HILDON2
6021 /*
6022  * UI handler for the "Move to" action when invoked from the
6023  * ModestFolderWindow
6024  */
6025 static void
6026 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
6027                                             TnyFolderStore *dst_folder,
6028                                             TnyList *selection,
6029                                             GtkWindow *win)
6030 {
6031         TnyFolderStore *src_folder = NULL;
6032         TnyIterator *iterator;
6033
6034         if (tny_list_get_length (selection) != 1)
6035                 return;
6036
6037         iterator = tny_list_create_iterator (selection);
6038         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
6039         g_object_unref (iterator);
6040
6041
6042         gboolean do_xfer = TRUE;
6043
6044         /* Allow only to transfer folders to the local root folder */
6045         if (TNY_IS_ACCOUNT (dst_folder) &&
6046             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
6047             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
6048                 do_xfer = FALSE;
6049                 /* Show an error */
6050                 modest_platform_run_information_dialog (win,
6051                                                         _("mail_in_ui_folder_move_target_error"),
6052                                                         FALSE);
6053         } else if (!TNY_IS_FOLDER (src_folder)) {
6054                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6055                 do_xfer = FALSE;
6056         }
6057
6058         if (do_xfer) {
6059                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6060                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6061
6062                 info->src_folder = g_object_ref (src_folder);
6063                 info->dst_folder = g_object_ref (dst_folder);
6064                 info->delete_original = TRUE;
6065                 info->folder_view = folder_view;
6066
6067                 connect_info->callback = on_move_folder_cb;
6068                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6069                 connect_info->data = info;
6070
6071                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6072                                                            TNY_FOLDER_STORE (src_folder),
6073                                                            connect_info);
6074         }
6075
6076         /* Frees */
6077         g_object_unref (src_folder);
6078 }
6079 #endif
6080
6081
6082 void
6083 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
6084                                             TnyFolder *src_folder,
6085                                             TnyList *headers,
6086                                             TnyFolder *dst_folder)
6087 {
6088         gboolean need_connection = TRUE;
6089         gboolean do_xfer = TRUE;
6090         XferMsgsHelper *helper;
6091
6092         g_return_if_fail (TNY_IS_FOLDER (src_folder));
6093         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6094         g_return_if_fail (TNY_IS_LIST (headers));
6095
6096         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
6097                                                headers, TNY_FOLDER (dst_folder),
6098                                                TRUE, &need_connection,
6099                                                &do_xfer);
6100
6101         /* If we don't want to transfer just return */
6102         if (!do_xfer)
6103                 return;
6104
6105         /* Create the helper */
6106         helper = g_slice_new (XferMsgsHelper);
6107         helper->dst_folder = g_object_ref (dst_folder);
6108         helper->headers = g_object_ref (headers);
6109
6110         if (need_connection) {
6111                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6112                 connect_info->callback = xfer_messages_performer;
6113                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
6114                 connect_info->data = helper;
6115
6116                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6117                                                            TNY_FOLDER_STORE (src_folder),
6118                                                            connect_info);
6119         } else {
6120                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
6121                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
6122                                          src_account, helper);
6123                 g_object_unref (src_account);
6124         }
6125 }
6126
6127 /*
6128  * UI handler for the "Move to" action when invoked from the
6129  * ModestMsgViewWindow
6130  */
6131 static void
6132 modest_ui_actions_on_window_move_to (GtkAction *action,
6133                                      TnyList *headers,
6134                                      TnyFolderStore *dst_folder,
6135                                      ModestWindow *win)
6136 {
6137         TnyFolder *src_folder = NULL;
6138
6139         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6140
6141         if (headers) {
6142                 TnyHeader *header = NULL;
6143                 TnyIterator *iter;
6144
6145                 iter = tny_list_create_iterator (headers);
6146                 header = (TnyHeader *) tny_iterator_get_current (iter);
6147                 src_folder = tny_header_get_folder (header);
6148
6149                 /* Transfer the messages */
6150                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6151                                                             headers,
6152                                                             TNY_FOLDER (dst_folder));
6153
6154                 /* Frees */
6155                 g_object_unref (header);
6156                 g_object_unref (iter);
6157                 g_object_unref (src_folder);
6158         }
6159 }
6160
6161 void
6162 modest_ui_actions_on_move_to (GtkAction *action,
6163                               ModestWindow *win)
6164 {
6165         modest_ui_actions_on_edit_mode_move_to (win);
6166 }
6167
6168 gboolean
6169 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6170 {
6171         GtkWidget *dialog = NULL;
6172         MoveToInfo *helper = NULL;
6173         TnyList *list_to_move;
6174
6175         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6176
6177 #ifndef MODEST_TOOLKIT_HILDON2
6178         /* Get the main window if exists */
6179         ModestMainWindow *main_window;
6180         if (MODEST_IS_MAIN_WINDOW (win))
6181                 main_window = MODEST_MAIN_WINDOW (win);
6182         else
6183                 main_window =
6184                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6185                                                                                FALSE)); /* don't create */
6186 #endif
6187
6188         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6189
6190         if (!list_to_move)
6191                 return FALSE;
6192
6193         if (tny_list_get_length (list_to_move) < 1) {
6194                 g_object_unref (list_to_move);
6195                 return FALSE;
6196         }
6197
6198         /* Create and run the dialog */
6199         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6200         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6201                                      GTK_WINDOW (dialog),
6202                                      (GtkWindow *) win);
6203
6204         /* Create helper */
6205         helper = g_slice_new0 (MoveToInfo);
6206         helper->list = list_to_move;
6207         helper->win = win;
6208
6209         /* Listen to response signal */
6210         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6211
6212         /* Show the dialog */
6213         gtk_widget_show (dialog);
6214
6215         return FALSE;
6216 }
6217
6218 /*
6219  * Calls #HeadersFunc for each header already selected in the main
6220  * window or the message currently being shown in the msg view window
6221  */
6222 static void
6223 do_headers_action (ModestWindow *win,
6224                    HeadersFunc func,
6225                    gpointer user_data)
6226 {
6227         TnyList *headers_list = NULL;
6228         TnyIterator *iter = NULL;
6229         TnyHeader *header = NULL;
6230         TnyFolder *folder = NULL;
6231
6232         /* Get headers */
6233         headers_list = get_selected_headers (win);
6234         if (!headers_list)
6235                 return;
6236
6237         /* Get the folder */
6238         iter = tny_list_create_iterator (headers_list);
6239         header = TNY_HEADER (tny_iterator_get_current (iter));
6240         if (header) {
6241                 folder = tny_header_get_folder (header);
6242                 g_object_unref (header);
6243         }
6244
6245         /* Call the function for each header */
6246         while (!tny_iterator_is_done (iter)) {
6247                 header = TNY_HEADER (tny_iterator_get_current (iter));
6248                 func (header, win, user_data);
6249                 g_object_unref (header);
6250                 tny_iterator_next (iter);
6251         }
6252
6253         /* Trick: do a poke status in order to speed up the signaling
6254            of observers */
6255         if (folder) {
6256                 tny_folder_poke_status (folder);
6257                 g_object_unref (folder);
6258         }
6259
6260         /* Frees */
6261         g_object_unref (iter);
6262         g_object_unref (headers_list);
6263 }
6264
6265 void
6266 modest_ui_actions_view_attachment (GtkAction *action,
6267                                    ModestWindow *window)
6268 {
6269         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6270                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6271         } else {
6272                 /* not supported window for this action */
6273                 g_return_if_reached ();
6274         }
6275 }
6276
6277 void
6278 modest_ui_actions_save_attachments (GtkAction *action,
6279                                     ModestWindow *window)
6280 {
6281         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6282
6283                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6284                         return;
6285
6286                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6287         } else {
6288                 /* not supported window for this action */
6289                 g_return_if_reached ();
6290         }
6291 }
6292
6293 void
6294 modest_ui_actions_remove_attachments (GtkAction *action,
6295                                       ModestWindow *window)
6296 {
6297 #ifndef MODEST_TOOLKIT_HILDON2
6298         if (MODEST_IS_MAIN_WINDOW (window)) {
6299                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6300         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6301 #else
6302         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6303 #endif
6304                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6305         } else {
6306                 /* not supported window for this action */
6307                 g_return_if_reached ();
6308         }
6309 }
6310
6311 void
6312 modest_ui_actions_on_settings (GtkAction *action,
6313                                ModestWindow *win)
6314 {
6315         GtkWidget *dialog;
6316
6317         dialog = modest_platform_get_global_settings_dialog ();
6318         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6319         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6320         gtk_widget_show_all (dialog);
6321
6322         gtk_dialog_run (GTK_DIALOG (dialog));
6323
6324         gtk_widget_destroy (dialog);
6325 }
6326
6327 void
6328 modest_ui_actions_on_help (GtkAction *action,
6329                            GtkWindow *win)
6330 {
6331         /* Help app is not available at all in fremantle */
6332 #ifndef MODEST_TOOLKIT_HILDON2
6333         const gchar *help_id;
6334
6335         g_return_if_fail (win && GTK_IS_WINDOW(win));
6336
6337         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6338
6339         if (help_id)
6340                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6341 #endif
6342 }
6343
6344 void
6345 modest_ui_actions_on_csm_help (GtkAction *action,
6346                                GtkWindow *win)
6347 {
6348         /* Help app is not available at all in fremantle */
6349 #ifndef MODEST_TOOLKIT_HILDON2
6350
6351         const gchar* help_id = NULL;
6352         GtkWidget *folder_view;
6353         TnyFolderStore *folder_store;
6354
6355         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6356
6357         /* Get selected folder */
6358         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6359                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6360         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6361
6362         /* Switch help_id */
6363         if (folder_store && TNY_IS_FOLDER (folder_store))
6364                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6365
6366         if (folder_store)
6367                 g_object_unref (folder_store);
6368
6369         if (help_id)
6370                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6371         else
6372                 modest_ui_actions_on_help (action, win);
6373 #endif
6374 }
6375
6376 static void
6377 retrieve_contents_cb (ModestMailOperation *mail_op,
6378                       TnyHeader *header,
6379                       gboolean canceled,
6380                       TnyMsg *msg,
6381                       GError *err,
6382                       gpointer user_data)
6383 {
6384         /* We only need this callback to show an error in case of
6385            memory low condition */
6386         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6387                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6388         }
6389 }
6390
6391 static void
6392 retrieve_msg_contents_performer (gboolean canceled,
6393                                  GError *err,
6394                                  GtkWindow *parent_window,
6395                                  TnyAccount *account,
6396                                  gpointer user_data)
6397 {
6398         ModestMailOperation *mail_op;
6399         TnyList *headers = TNY_LIST (user_data);
6400
6401         if (err || canceled) {
6402                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6403                                                                 (GtkWidget *) parent_window, err,
6404                                                                 account, NULL);
6405                 goto out;
6406         }
6407
6408         /* Create mail operation */
6409         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6410                                                                  modest_ui_actions_disk_operations_error_handler,
6411                                                                  NULL, NULL);
6412         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6413         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6414
6415         /* Frees */
6416         g_object_unref (mail_op);
6417  out:
6418         g_object_unref (headers);
6419         g_object_unref (account);
6420 }
6421
6422 void
6423 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6424                                             ModestWindow *window)
6425 {
6426         TnyList *headers = NULL;
6427         TnyAccount *account = NULL;
6428         TnyIterator *iter = NULL;
6429         TnyHeader *header = NULL;
6430         TnyFolder *folder = NULL;
6431
6432         /* Get headers */
6433         headers = get_selected_headers (window);
6434         if (!headers)
6435                 return;
6436
6437         /* Pick the account */
6438         iter = tny_list_create_iterator (headers);
6439         header = TNY_HEADER (tny_iterator_get_current (iter));
6440         folder = tny_header_get_folder (header);
6441         account = tny_folder_get_account (folder);
6442         g_object_unref (folder);
6443         g_object_unref (header);
6444         g_object_unref (iter);
6445
6446         /* Connect and perform the message retrieval */
6447         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6448                                              g_object_ref (account),
6449                                              retrieve_msg_contents_performer,
6450                                              g_object_ref (headers));
6451
6452         /* Frees */
6453         g_object_unref (account);
6454         g_object_unref (headers);
6455 }
6456
6457 void
6458 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6459 {
6460         g_return_if_fail (MODEST_IS_WINDOW (window));
6461
6462         /* Update dimmed */
6463         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6464 }
6465
6466 void
6467 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6468 {
6469         g_return_if_fail (MODEST_IS_WINDOW (window));
6470
6471         /* Update dimmed */
6472         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6473 }
6474
6475 void
6476 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6477                                           ModestWindow *window)
6478 {
6479         g_return_if_fail (MODEST_IS_WINDOW (window));
6480
6481         /* Update dimmed */
6482         modest_ui_actions_check_menu_dimming_rules (window);
6483 }
6484
6485 void
6486 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6487                                           ModestWindow *window)
6488 {
6489         g_return_if_fail (MODEST_IS_WINDOW (window));
6490
6491         /* Update dimmed */
6492         modest_ui_actions_check_menu_dimming_rules (window);
6493 }
6494
6495 void
6496 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6497                                           ModestWindow *window)
6498 {
6499         g_return_if_fail (MODEST_IS_WINDOW (window));
6500
6501         /* Update dimmed */
6502         modest_ui_actions_check_menu_dimming_rules (window);
6503 }
6504
6505 void
6506 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6507                                             ModestWindow *window)
6508 {
6509         g_return_if_fail (MODEST_IS_WINDOW (window));
6510
6511         /* Update dimmed */
6512         modest_ui_actions_check_menu_dimming_rules (window);
6513 }
6514
6515 void
6516 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6517                                           ModestWindow *window)
6518 {
6519         g_return_if_fail (MODEST_IS_WINDOW (window));
6520
6521         /* Update dimmed */
6522         modest_ui_actions_check_menu_dimming_rules (window);
6523 }
6524
6525 void
6526 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6527                                           ModestWindow *window)
6528 {
6529         g_return_if_fail (MODEST_IS_WINDOW (window));
6530
6531         /* Update dimmed */
6532         modest_ui_actions_check_menu_dimming_rules (window);
6533 }
6534
6535 void
6536 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6537                                                  ModestWindow *window)
6538 {
6539         g_return_if_fail (MODEST_IS_WINDOW (window));
6540
6541         /* Update dimmed */
6542         modest_ui_actions_check_menu_dimming_rules (window);
6543 }
6544
6545 void
6546 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6547                                                      ModestWindow *window)
6548 {
6549         g_return_if_fail (MODEST_IS_WINDOW (window));
6550
6551         /* Update dimmed */
6552         modest_ui_actions_check_menu_dimming_rules (window);
6553 }
6554
6555 void
6556 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6557                                                      ModestWindow *window)
6558 {
6559         g_return_if_fail (MODEST_IS_WINDOW (window));
6560
6561         /* Update dimmed */
6562         modest_ui_actions_check_menu_dimming_rules (window);
6563 }
6564
6565 void
6566 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6567 {
6568         g_return_if_fail (MODEST_IS_WINDOW (window));
6569
6570         /* we check for low-mem; in that case, show a warning, and don't allow
6571          * searching
6572          */
6573         if (modest_platform_check_memory_low (window, TRUE))
6574                 return;
6575
6576         modest_platform_show_search_messages (GTK_WINDOW (window));
6577 }
6578
6579 void
6580 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6581 {
6582         g_return_if_fail (MODEST_IS_WINDOW (win));
6583
6584
6585         /* we check for low-mem; in that case, show a warning, and don't allow
6586          * for the addressbook
6587          */
6588         if (modest_platform_check_memory_low (win, TRUE))
6589                 return;
6590
6591
6592         modest_platform_show_addressbook (GTK_WINDOW (win));
6593 }
6594
6595
6596 void
6597 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6598                                           ModestWindow *window)
6599 {
6600         gboolean active;
6601         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6602
6603         if (GTK_IS_TOGGLE_ACTION (action))
6604                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6605         else
6606                 active = TRUE;
6607
6608         modest_msg_edit_window_toggle_isearch_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6609                                                        active);
6610 }
6611
6612 #ifndef MODEST_TOOLKIT_HILDON2
6613 static void
6614 on_send_receive_finished (ModestMailOperation  *mail_op,
6615                            gpointer user_data)
6616 {
6617         GtkWidget *header_view, *folder_view;
6618         TnyFolderStore *folder_store;
6619         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6620
6621         /* Set send/receive operation finished */
6622         modest_main_window_notify_send_receive_completed (main_win);
6623
6624         /* Don't refresh the current folder if there were any errors */
6625         if (modest_mail_operation_get_status (mail_op) !=
6626             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6627                 return;
6628
6629         /* Refresh the current folder if we're viewing a window. We do
6630            this because the user won't be able to see the new mails in
6631            the selected folder after a Send&Receive because it only
6632            performs a poke_status, i.e, only the number of read/unread
6633            messages is updated, but the new headers are not
6634            downloaded */
6635         folder_view = modest_main_window_get_child_widget (main_win,
6636                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6637         if (!folder_view)
6638                 return;
6639
6640         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6641
6642         /* Do not need to refresh INBOX again because the
6643            update_account does it always automatically */
6644         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6645             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6646                 ModestMailOperation *refresh_op;
6647
6648                 header_view = modest_main_window_get_child_widget (main_win,
6649                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6650
6651                 /* We do not need to set the contents style
6652                    because it hasn't changed. We also do not
6653                    need to save the widget status. Just force
6654                    a refresh */
6655                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6656                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6657                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6658                                                       folder_refreshed_cb, main_win);
6659                 g_object_unref (refresh_op);
6660         }
6661
6662         if (folder_store)
6663                 g_object_unref (folder_store);
6664 }
6665 #endif
6666
6667 void
6668 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6669                                                 TnyHeader *header,
6670                                                 TnyMsg *msg,
6671                                                 GError *err,
6672                                                 gpointer user_data)
6673 {
6674         const gchar* server_name = NULL;
6675         TnyTransportAccount *transport;
6676         gchar *message = NULL;
6677         ModestProtocol *protocol;
6678
6679         /* Don't show anything if the user cancelled something or the
6680          * send receive request is not interactive. Authentication
6681          * errors are managed by the account store so no need to show
6682          * a dialog here again */
6683         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6684             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6685             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6686                 return;
6687
6688
6689         /* Get the server name. Note that we could be using a
6690            connection specific transport account */
6691         transport = (TnyTransportAccount *)
6692                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6693         if (transport) {
6694                 ModestTnyAccountStore *acc_store;
6695                 const gchar *acc_name;
6696                 TnyTransportAccount *conn_specific;
6697
6698                 acc_store = modest_runtime_get_account_store();
6699                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6700                 conn_specific = (TnyTransportAccount *)
6701                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6702                 if (conn_specific) {
6703                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6704                         g_object_unref (conn_specific);
6705                 } else {
6706                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6707                 }
6708                 g_object_unref (transport);
6709         }
6710
6711         /* Get protocol */
6712         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6713                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6714                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6715         if (!protocol) {
6716                 g_warning ("%s: Account with no proto", __FUNCTION__);
6717                 return;
6718         }
6719
6720         /* Show the appropriate message text for the GError: */
6721         switch (err->code) {
6722         case TNY_SERVICE_ERROR_CONNECT:
6723                 message = modest_protocol_get_translation (protocol,
6724                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6725                                                            server_name);
6726                 break;
6727         case TNY_SERVICE_ERROR_SEND:
6728                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6729                 break;
6730         case TNY_SERVICE_ERROR_UNAVAILABLE:
6731                 message = modest_protocol_get_translation (protocol,
6732                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6733                                                            server_name);
6734                 break;
6735         default:
6736                 g_warning ("%s: unexpected ERROR %d",
6737                            __FUNCTION__, err->code);
6738                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6739                 break;
6740         }
6741
6742         modest_platform_run_information_dialog (NULL, message, FALSE);
6743         g_free (message);
6744 }
6745
6746 void
6747 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6748                                                 gchar *msg_id,
6749                                                 guint status,
6750                                                 gpointer user_data)
6751 {
6752         ModestWindow *top_window = NULL;
6753         ModestWindowMgr *mgr = NULL;
6754         GtkWidget *header_view = NULL;
6755         TnyFolder *selected_folder = NULL;
6756         TnyFolderType folder_type;
6757
6758         mgr = modest_runtime_get_window_mgr ();
6759         top_window = modest_window_mgr_get_current_top (mgr);
6760
6761         if (!top_window)
6762                 return;
6763
6764 #ifndef MODEST_TOOLKIT_HILDON2
6765         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6766                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6767                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6768         }
6769 #else
6770         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6771                 header_view = (GtkWidget *)
6772                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6773         }
6774 #endif
6775
6776         /* Get selected folder */
6777         if (header_view)
6778                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6779         if (!selected_folder)
6780                 return;
6781
6782         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6783 #if GTK_CHECK_VERSION(2, 8, 0)
6784         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6785         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6786                 GtkTreeViewColumn *tree_column;
6787
6788                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6789                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6790                 if (tree_column)
6791                         gtk_tree_view_column_queue_resize (tree_column);
6792                 }
6793 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6794         gtk_widget_queue_draw (header_view);
6795 #endif
6796
6797 #ifndef MODEST_TOOLKIT_HILDON2
6798         /* Rerun dimming rules, because the message could become deletable for example */
6799         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6800                                                  MODEST_DIMMING_RULES_TOOLBAR);
6801         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6802                                                  MODEST_DIMMING_RULES_MENU);
6803 #endif
6804
6805         /* Free */
6806         g_object_unref (selected_folder);
6807 }
6808
6809 void
6810 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6811                                                TnyAccount *account)
6812 {
6813         ModestProtocolType protocol_type;
6814         ModestProtocol *protocol;
6815         gchar *error_note = NULL;
6816
6817         protocol_type = modest_tny_account_get_protocol_type (account);
6818         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6819                                                                   protocol_type);
6820
6821         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6822         if (error_note == NULL) {
6823                 g_warning ("%s: This should not be reached", __FUNCTION__);
6824         } else {
6825                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6826                 g_free (error_note);
6827         }
6828 }
6829
6830 gchar *
6831 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6832 {
6833         gchar *msg = NULL;
6834         gchar *subject;
6835         TnyFolderStore *folder = NULL;
6836         TnyAccount *account = NULL;
6837         ModestProtocolType proto;
6838         ModestProtocol *protocol;
6839         TnyHeader *header = NULL;
6840
6841 #ifndef MODEST_TOOLKIT_HILDON2
6842         if (MODEST_IS_MAIN_WINDOW (win)) {
6843                 GtkWidget *header_view;
6844                 TnyList* headers = NULL;
6845                 TnyIterator *iter;
6846                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6847                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6848                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6849                 if (!headers || tny_list_get_length (headers) == 0) {
6850                         if (headers)
6851                                 g_object_unref (headers);
6852                         return NULL;
6853                 }
6854                 iter = tny_list_create_iterator (headers);
6855                 header = TNY_HEADER (tny_iterator_get_current (iter));
6856                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6857                 g_object_unref (iter);
6858                 g_object_unref (headers);
6859 #else
6860         if (MODEST_IS_HEADER_WINDOW (win)) {
6861                 GtkWidget *header_view;
6862                 TnyList* headers = NULL;
6863                 TnyIterator *iter;
6864                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6865                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6866                 if (!headers || tny_list_get_length (headers) == 0) {
6867                         if (headers)
6868                                 g_object_unref (headers);
6869                         return NULL;
6870                 }
6871                 iter = tny_list_create_iterator (headers);
6872                 header = TNY_HEADER (tny_iterator_get_current (iter));
6873                 if (header) {
6874                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6875                 } else {
6876                         g_warning ("List should contain headers");
6877                 }
6878                 g_object_unref (iter);
6879                 g_object_unref (headers);
6880 #endif
6881         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6882                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6883                 if (header)
6884                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6885         }
6886
6887         if (!header || !folder)
6888                 goto frees;
6889
6890         /* Get the account type */
6891         account = tny_folder_get_account (TNY_FOLDER (folder));
6892         proto = modest_tny_account_get_protocol_type (account);
6893         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6894                                                                   proto);
6895
6896         subject = tny_header_dup_subject (header);
6897         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6898         if (subject)
6899                 g_free (subject);
6900         if (msg == NULL) {
6901                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6902         }
6903
6904  frees:
6905         /* Frees */
6906         if (account)
6907                 g_object_unref (account);
6908         if (folder)
6909                 g_object_unref (folder);
6910         if (header)
6911                 g_object_unref (header);
6912
6913         return msg;
6914 }
6915
6916 gboolean
6917 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6918                                      const gchar *account_name,
6919                                      const gchar *account_title)
6920 {
6921         ModestAccountMgr *account_mgr;
6922         gchar *txt = NULL;
6923         gint response;
6924         ModestProtocol *protocol;
6925         gboolean removed = FALSE;
6926
6927         g_return_val_if_fail (account_name, FALSE);
6928         g_return_val_if_fail (account_title, FALSE);
6929
6930         account_mgr = modest_runtime_get_account_mgr();
6931
6932         /* The warning text depends on the account type: */
6933         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6934                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6935                                                                                                          account_name));
6936         txt = modest_protocol_get_translation (protocol,
6937                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6938                                                account_title);
6939         if (txt == NULL)
6940                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6941
6942         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6943         g_free (txt);
6944         txt = NULL;
6945
6946         if (response == GTK_RESPONSE_OK) {
6947                 /* Remove account. If it succeeds then it also removes
6948                    the account from the ModestAccountView: */
6949                 gboolean is_default = FALSE;
6950                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6951                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6952                         is_default = TRUE;
6953                 g_free (default_account_name);
6954
6955                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6956                 if (removed) {
6957                         /* Close all email notifications, we cannot
6958                            distinguish if the notification belongs to
6959                            this account or not, so for safety reasons
6960                            we remove them all */
6961                         modest_platform_remove_new_mail_notifications (FALSE);
6962                 } else {
6963                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6964                 }
6965         }
6966         return removed;
6967 }
6968
6969 static void
6970 on_fetch_images_performer (gboolean canceled,
6971                            GError *err,
6972                            GtkWindow *parent_window,
6973                            TnyAccount *account,
6974                            gpointer user_data)
6975 {
6976         if (err || canceled) {
6977                 /* Show an unable to retrieve images ??? */
6978                 return;
6979         }
6980
6981         /* Note that the user could have closed the window while connecting */
6982         if (GTK_WIDGET_VISIBLE (parent_window))
6983                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
6984         g_object_unref ((GObject *) user_data);
6985 }
6986
6987 void
6988 modest_ui_actions_on_fetch_images (GtkAction *action,
6989                                    ModestWindow *window)
6990 {
6991         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6992
6993         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
6994                                              NULL,
6995                                              on_fetch_images_performer, 
6996                                              g_object_ref (window));
6997 }
6998
6999 void
7000 modest_ui_actions_on_reload_message (const gchar *msg_id)
7001 {
7002         ModestWindow *window = NULL;
7003
7004         g_return_if_fail (msg_id && msg_id[0] != '\0');
7005         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
7006                                                             msg_id,
7007                                                             &window))
7008                 return;
7009
7010
7011         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
7012                 return;
7013
7014         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
7015 }
7016
7017 /** Check whether any connections are active, and cancel them if 
7018  * the user wishes.
7019  * Returns TRUE is there was no problem, 
7020  * or if an operation was cancelled so we can continue.
7021  * Returns FALSE if the user chose to cancel his request instead.
7022  */
7023
7024 gboolean
7025 modest_ui_actions_check_for_active_account (ModestWindow *self,
7026                                             const gchar* account_name)
7027 {
7028         ModestTnySendQueue *send_queue;
7029         ModestTnyAccountStore *acc_store;
7030         ModestMailOperationQueue* queue;
7031         TnyConnectionStatus store_conn_status;
7032         TnyAccount *store_account = NULL, *transport_account = NULL;
7033         gboolean retval = TRUE, sending = FALSE;
7034
7035         acc_store = modest_runtime_get_account_store ();
7036         queue = modest_runtime_get_mail_operation_queue ();
7037
7038         store_account = 
7039                 modest_tny_account_store_get_server_account (acc_store,
7040                                                              account_name,
7041                                                              TNY_ACCOUNT_TYPE_STORE);
7042
7043         /* This could happen if the account was deleted before the
7044            call to this function */
7045         if (!store_account)
7046                 return FALSE;
7047
7048         transport_account = 
7049                 modest_tny_account_store_get_server_account (acc_store,
7050                                                              account_name,
7051                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
7052
7053         /* This could happen if the account was deleted before the
7054            call to this function */
7055         if (!transport_account) {
7056                 g_object_unref (store_account);
7057                 return FALSE;
7058         }
7059
7060         /* If the transport account was not used yet, then the send
7061            queue could not exist (it's created on demand) */
7062         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
7063         if (TNY_IS_SEND_QUEUE (send_queue))
7064                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
7065
7066         store_conn_status = tny_account_get_connection_status (store_account);
7067         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
7068                 gint response;
7069
7070                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
7071                                                                 _("emev_nc_disconnect_account"));
7072                 if (response == GTK_RESPONSE_OK) {
7073                         retval = TRUE;
7074                 } else {
7075                         retval = FALSE;
7076                 }
7077         }
7078
7079         if (retval) {
7080
7081                 /* FIXME: We should only cancel those of this account */
7082                 modest_mail_operation_queue_cancel_all (queue);
7083
7084                 /* Also disconnect the account */
7085                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
7086                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
7087                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
7088                                                       FALSE, NULL, NULL);
7089                 }
7090                 if (sending) {
7091                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
7092                                                       FALSE, NULL, NULL);
7093                 }
7094         }
7095                 
7096         /* Frees */
7097         g_object_unref (store_account);
7098         g_object_unref (transport_account);
7099         
7100         return retval;
7101 }