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