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