Add checks for some callbacks that are used with connect_and_perform: on_rename_folde...
[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-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44 #include "modest-protocol-info.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-camel-folder.h>
50 #include <tny-camel-imap-folder.h>
51 #include <tny-camel-pop-folder.h>
52
53 #ifdef MODEST_PLATFORM_MAEMO
54 #include "maemo/modest-osso-state-saving.h"
55 #include "maemo/modest-hildon-includes.h"
56 #include "maemo/modest-connection-specific-smtp-window.h"
57 #endif /* MODEST_PLATFORM_MAEMO */
58 #include <modest-utils.h>
59
60 #include "widgets/modest-ui-constants.h"
61 #include <widgets/modest-main-window.h>
62 #include <widgets/modest-msg-view-window.h>
63 #include <widgets/modest-account-view-window.h>
64 #include <widgets/modest-details-dialog.h>
65 #include <widgets/modest-attachments-view.h>
66 #include "widgets/modest-folder-view.h"
67 #include "widgets/modest-global-settings-dialog.h"
68 #include "modest-account-mgr-helpers.h"
69 #include "modest-mail-operation.h"
70 #include "modest-text-utils.h"
71
72 #ifdef MODEST_HAVE_EASYSETUP
73 #include "easysetup/modest-easysetup-wizard.h"
74 #endif /* MODEST_HAVE_EASYSETUP */
75
76 #include <modest-widget-memory.h>
77 #include <tny-error.h>
78 #include <tny-simple-list.h>
79 #include <tny-msg-view.h>
80 #include <tny-device.h>
81 #include <tny-merge-folder.h>
82
83 #include <gtkhtml/gtkhtml.h>
84
85 typedef struct _GetMsgAsyncHelper {     
86         ModestWindow *window;
87         ModestMailOperation *mail_op;
88         TnyIterator *iter;
89         guint num_ops;
90         GFunc func;     
91         gpointer user_data;
92 } GetMsgAsyncHelper;
93
94 typedef enum _ReplyForwardAction {
95         ACTION_REPLY,
96         ACTION_REPLY_TO_ALL,
97         ACTION_FORWARD
98 } ReplyForwardAction;
99
100 typedef struct _ReplyForwardHelper {
101         guint reply_forward_type;
102         ReplyForwardAction action;
103         gchar *account_name;
104         GtkWidget *parent_window;
105 } ReplyForwardHelper;
106
107 typedef struct _MoveToHelper {
108         GtkTreeRowReference *reference;
109         GtkWidget *banner;
110 } MoveToHelper;
111
112 typedef struct _PasteAsAttachmentHelper {
113         ModestMsgEditWindow *window;
114         GtkWidget *banner;
115 } PasteAsAttachmentHelper;
116
117
118 /*
119  * The do_headers_action uses this kind of functions to perform some
120  * action to each member of a list of headers
121  */
122 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
123
124 static void     do_headers_action     (ModestWindow *win, 
125                                        HeadersFunc func,
126                                        gpointer user_data);
127
128 static void     open_msg_cb            (ModestMailOperation *mail_op, 
129                                         TnyHeader *header, 
130                                         gboolean canceled,
131                                         TnyMsg *msg,
132                                         GError *err,
133                                         gpointer user_data);
134
135 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
136                                         TnyHeader *header, 
137                                         gboolean canceled,
138                                         TnyMsg *msg,
139                                         GError *err,
140                                         gpointer user_data);
141
142 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
143
144 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
145                                         TnyFolder *folder, 
146                                         gpointer user_data);
147
148 static void     on_send_receive_finished (ModestMailOperation  *mail_op, 
149                                           gpointer user_data);
150
151 static gint header_list_count_uncached_msgs (TnyList *header_list);
152
153 static gboolean connect_to_get_msg (ModestWindow *win,
154                                     gint num_of_uncached_msgs,
155                                     TnyAccount *account);
156
157 static gboolean remote_folder_is_pop (const TnyFolderStore *folder);
158
159 static gboolean msgs_already_deleted_from_server ( TnyList *headers,
160                                                    const TnyFolderStore *src_folder);
161
162
163 /*
164  * This function checks whether a TnyFolderStore is a pop account
165  */
166 static gboolean
167 remote_folder_is_pop (const TnyFolderStore *folder)
168 {
169         const gchar *proto = NULL;
170         TnyAccount *account = NULL;
171
172         g_return_val_if_fail (TNY_IS_FOLDER_STORE(folder), FALSE);
173
174         if (TNY_IS_ACCOUNT (folder)) {
175                 account = TNY_ACCOUNT(folder);
176                 g_object_ref(account);
177         } else if (TNY_IS_FOLDER (folder)) {
178                 account = tny_folder_get_account(TNY_FOLDER(folder));
179         }
180
181         if (!account && !TNY_IS_ACCOUNT(account)) {
182                 g_warning ("%s: could not get account", __FUNCTION__);
183                 return FALSE;
184         }
185         
186         proto = tny_account_get_proto(account);
187         g_object_unref (account);
188
189         return proto &&
190           (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
191 }
192
193 /*
194  * This functions checks whether if a list of messages are already
195  * deleted from the server: that is, if the server is a POP account
196  * and all messages are already cached.
197  */
198 static gboolean
199 msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_folder)
200 {
201         g_return_val_if_fail (TNY_IS_FOLDER_STORE(src_folder), FALSE);
202         g_return_val_if_fail (TNY_IS_LIST(headers), FALSE);
203
204         gboolean src_is_pop = remote_folder_is_pop (src_folder);
205         gint uncached_msgs = header_list_count_uncached_msgs (headers);
206
207         return (src_is_pop && !uncached_msgs);
208 }
209
210
211 /* FIXME: this should be merged with the similar code in modest-account-view-window */
212 /* Show the account creation wizard dialog.
213  * returns: TRUE if an account was created. FALSE if the user cancelled.
214  */
215 gboolean
216 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
217 {
218         gboolean result = FALSE;        
219         GtkWindow *dialog, *wizard;
220         gint dialog_response;
221
222         /* Show the easy-setup wizard: */       
223         dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
224         if (dialog) {
225                 /* old wizard is active already; 
226                  */
227                 gtk_window_present (GTK_WINDOW(dialog));
228                 return FALSE;
229         }
230         
231
232         /* there is no such wizard yet */       
233         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
234         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
235
236         /* always present a main window in the background 
237          * we do it here, so we cannot end up with two wizards (as this
238          * function might be called in modest_window_mgr_get_main_window as well */
239         if (!win) 
240                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
241                                                          TRUE);  /* create if not existent */
242         
243         /* make sure the mainwindow is visible */
244         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
245         gtk_widget_show_all (GTK_WIDGET(win));
246         gtk_window_present (GTK_WINDOW(win));
247         
248         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
249         gtk_widget_destroy (GTK_WIDGET (wizard));
250         if (gtk_events_pending ())
251                 gtk_main_iteration ();
252
253         if (dialog_response == GTK_RESPONSE_CANCEL) {
254                 result = FALSE;
255         } else {
256                 /* Check whether an account was created: */
257                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
258         }
259         return result;
260 }
261
262
263 void   
264 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
265 {
266         GtkWidget *about;
267         const gchar *authors[] = {
268                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
269                 NULL
270         };
271         about = gtk_about_dialog_new ();
272         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
273         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
274         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
275                                         _("Copyright (c) 2006, Nokia Corporation\n"
276                                           "All rights reserved."));
277         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
278                                        _("a modest e-mail client\n\n"
279                                          "design and implementation: Dirk-Jan C. Binnema\n"
280                                          "contributions from the fine people at KC and Ig\n"
281                                          "uses the tinymail email framework written by Philip van Hoof"));
282         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
283         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
284         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
285         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
286         
287         gtk_dialog_run (GTK_DIALOG (about));
288         gtk_widget_destroy(about);
289 }
290
291 /*
292  * Gets the list of currently selected messages. If the win is the
293  * main window, then it returns a newly allocated list of the headers
294  * selected in the header view. If win is the msg view window, then
295  * the value returned is a list with just a single header.
296  *
297  * The caller of this funcion must free the list.
298  */
299 static TnyList *
300 get_selected_headers (ModestWindow *win)
301 {
302         if (MODEST_IS_MAIN_WINDOW(win)) {
303                 GtkWidget *header_view;         
304                 
305                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
306                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
307                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
308                 
309         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
310                 /* for MsgViewWindows, we simply return a list with one element */
311                 TnyHeader *header;
312                 TnyList *list = NULL;
313                 
314                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
315                 if (header != NULL) {
316                         list = tny_simple_list_new ();
317                         tny_list_prepend (list, G_OBJECT(header));
318                         g_object_unref (G_OBJECT(header));
319                 }
320
321                 return list;
322
323         } else
324                 return NULL;
325 }
326
327 static GtkTreeRowReference *
328 get_next_after_selected_headers (ModestHeaderView *header_view)
329 {
330         GtkTreeSelection *sel;
331         GList *selected_rows, *node;
332         GtkTreePath *path;
333         GtkTreeRowReference *result;
334         GtkTreeModel *model;
335
336         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
337         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
338         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
339
340         if (selected_rows == NULL)
341                 return NULL;
342
343         node = g_list_last (selected_rows);
344         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
345         gtk_tree_path_next (path);
346
347         result = gtk_tree_row_reference_new (model, path);
348
349         gtk_tree_path_free (path);
350         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
351         g_list_free (selected_rows);
352
353         return result;
354 }
355
356 static void
357 headers_action_mark_as_read (TnyHeader *header,
358                              ModestWindow *win,
359                              gpointer user_data)
360 {
361         TnyHeaderFlags flags;
362
363         g_return_if_fail (TNY_IS_HEADER(header));
364
365         flags = tny_header_get_flags (header);
366         if (flags & TNY_HEADER_FLAG_SEEN) return;
367         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
368 }
369
370 static void
371 headers_action_mark_as_unread (TnyHeader *header,
372                                ModestWindow *win,
373                                gpointer user_data)
374 {
375         TnyHeaderFlags flags;
376
377         g_return_if_fail (TNY_IS_HEADER(header));
378
379         flags = tny_header_get_flags (header);
380         if (flags & TNY_HEADER_FLAG_SEEN)  {
381                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
382         }
383 }
384
385 /** After deleing a message that is currently visible in a window, 
386  * show the next message from the list, or close the window if there are no more messages.
387  **/
388 void 
389 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
390 {
391         /* Close msg view window or select next */
392         if (modest_msg_view_window_last_message_selected (win) &&
393                 modest_msg_view_window_first_message_selected (win)) {
394                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
395         } else if (!modest_msg_view_window_select_next_message (win)) {
396                 gboolean ret_value;
397                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
398         }
399 }
400
401
402 void
403 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
404 {
405         TnyList *header_list = NULL;
406         TnyIterator *iter = NULL;
407         TnyHeader *header = NULL;
408         gchar *message = NULL;
409         gchar *desc = NULL;
410         gint response;
411         ModestWindowMgr *mgr;
412         GtkWidget *header_view = NULL;
413
414         g_return_if_fail (MODEST_IS_WINDOW(win));
415         
416         /* Check first if the header view has the focus */
417         if (MODEST_IS_MAIN_WINDOW (win)) {
418                 header_view = 
419                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
420                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
421                 if (!gtk_widget_is_focus (header_view))
422                         return;
423         }
424         
425         /* Get the headers, either from the header view (if win is the main window),
426          * or from the message view window: */
427         header_list = get_selected_headers (win);
428         if (!header_list) return;
429                         
430         /* Check if any of the headers are already opened, or in the process of being opened */
431         if (MODEST_IS_MAIN_WINDOW (win)) {
432                 gint opened_headers = 0;
433
434                 iter = tny_list_create_iterator (header_list);
435                 mgr = modest_runtime_get_window_mgr ();
436                 while (!tny_iterator_is_done (iter)) {
437                         header = TNY_HEADER (tny_iterator_get_current (iter));
438                         if (header) {
439                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
440                                         opened_headers++;
441                                 g_object_unref (header);
442                         }
443                         tny_iterator_next (iter);
444                 }
445                 g_object_unref (iter);
446
447                 if (opened_headers > 0) {
448                         gchar *msg;
449
450                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
451                                                opened_headers);
452
453                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
454                         
455                         g_free (msg);
456                         g_object_unref (header_list);
457                         return;
458                 }
459         }
460
461         /* Select message */
462         if (tny_list_get_length(header_list) == 1) {
463                 iter = tny_list_create_iterator (header_list);
464                 header = TNY_HEADER (tny_iterator_get_current (iter));
465                 if (header) {
466                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
467                         g_object_unref (header);
468                 }
469
470                 g_object_unref (iter);
471         }
472         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
473                                            tny_list_get_length(header_list)), desc);
474
475         /* Confirmation dialog */
476         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
477                                                             message);
478         
479
480         if (response == GTK_RESPONSE_OK) {      
481                 ModestWindow *main_window = NULL;
482                 ModestWindowMgr *mgr = NULL;
483                 GtkTreeModel *model = NULL;
484                 GtkTreeSelection *sel = NULL;
485                 GList *sel_list = NULL, *tmp = NULL;
486                 GtkTreeRowReference *next_row_reference = NULL;
487                 GtkTreeRowReference *prev_row_reference = NULL;
488                 GtkTreePath *next_path = NULL;
489                 GtkTreePath *prev_path = NULL;
490                 ModestMailOperation *mail_op = NULL;
491
492                 /* Find last selected row */                    
493                 if (MODEST_IS_MAIN_WINDOW (win)) {
494                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
495                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
496                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
497                         for (tmp=sel_list; tmp; tmp=tmp->next) {
498                                 if (tmp->next == NULL) {
499                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
500                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
501
502                                         gtk_tree_path_prev (prev_path);
503                                         gtk_tree_path_next (next_path);
504
505                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
506                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
507                                 }
508                         }
509                 }
510                 
511                 /* Disable window dimming management */
512                 modest_window_disable_dimming (MODEST_WINDOW(win));
513
514                 /* Remove each header. If it's a view window header_view == NULL */
515                 mail_op = modest_mail_operation_new ((GObject *) win);
516                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
517                                                  mail_op);
518                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
519                 g_object_unref (mail_op);
520                 
521                 /* Enable window dimming management */
522                 if (sel != NULL) {
523                         gtk_tree_selection_unselect_all (sel);
524                 }
525                 modest_window_enable_dimming (MODEST_WINDOW(win));
526                 
527                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
528                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
529                         
530                         /* Get main window */
531                         mgr = modest_runtime_get_window_mgr ();
532                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
533                 } else {                        
534                         /* Move cursor to next row */
535                         main_window = win; 
536
537                         /* Select next or previous row */
538                         if (gtk_tree_row_reference_valid (next_row_reference)) {
539 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
540                                 gtk_tree_selection_select_path (sel, next_path);
541                         }
542                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
543                                 gtk_tree_selection_select_path (sel, prev_path);
544                         }
545
546                         /* Free */
547                         if (next_row_reference != NULL) 
548                                 gtk_tree_row_reference_free (next_row_reference);
549                         if (next_path != NULL) 
550                                 gtk_tree_path_free (next_path);                         
551                         if (prev_row_reference != NULL) 
552                                 gtk_tree_row_reference_free (prev_row_reference);
553                         if (prev_path != NULL) 
554                                 gtk_tree_path_free (prev_path);                         
555                 }
556                 
557                 /* Update toolbar dimming state */
558                 if (main_window)
559                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
560
561                 /* Free */
562                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
563                 g_list_free (sel_list);
564         }
565
566         /* Free*/
567         g_free(message);
568         g_free(desc);
569         g_object_unref (header_list);
570 }
571
572
573
574
575 /* delete either message or folder, based on where we are */
576 void
577 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
578 {
579         g_return_if_fail (MODEST_IS_WINDOW(win));
580         
581         /* Check first if the header view has the focus */
582         if (MODEST_IS_MAIN_WINDOW (win)) {
583                 GtkWidget *w;
584                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
585                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
586                 if (gtk_widget_is_focus (w)) {
587                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
588                         return;
589                 }
590         }
591         modest_ui_actions_on_delete_message (action, win);
592 }
593
594
595
596 void
597 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
598 {       
599         ModestWindowMgr *mgr = NULL;
600         
601 #ifdef MODEST_PLATFORM_MAEMO
602         modest_osso_save_state();
603 #endif /* MODEST_PLATFORM_MAEMO */
604
605         g_debug ("closing down, clearing %d item(s) from operation queue",
606                  modest_mail_operation_queue_num_elements
607                  (modest_runtime_get_mail_operation_queue()));
608
609         /* cancel all outstanding operations */
610         modest_mail_operation_queue_cancel_all 
611                 (modest_runtime_get_mail_operation_queue());
612         
613         g_debug ("queue has been cleared");
614
615
616         /* Check if there are opened editing windows */ 
617         mgr = modest_runtime_get_window_mgr ();
618         modest_window_mgr_close_all_windows (mgr);
619
620         /* note: when modest-tny-account-store is finalized,
621            it will automatically set all network connections
622            to offline */
623
624 /*      gtk_main_quit (); */
625 }
626
627 void
628 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
629 {
630         gboolean ret_value;
631
632         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
633
634 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
635 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
636 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
637 /*              gboolean ret_value; */
638 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
639 /*      } else if (MODEST_IS_WINDOW (win)) { */
640 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
641 /*      } else { */
642 /*              g_return_if_reached (); */
643 /*      } */
644 }
645
646 void
647 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
648 {
649         GtkClipboard *clipboard = NULL;
650         gchar *selection = NULL;
651
652         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
653         selection = gtk_clipboard_wait_for_text (clipboard);
654
655         /* Question: why is the clipboard being used here? 
656          * It doesn't really make a lot of sense. */
657
658         if (selection)
659         {
660                 modest_address_book_add_address (selection);
661                 g_free (selection);
662         }
663 }
664
665 void
666 modest_ui_actions_on_accounts (GtkAction *action, 
667                                ModestWindow *win)
668 {
669         /* This is currently only implemented for Maemo */
670         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
671                 if (!modest_ui_actions_run_account_setup_wizard (win)) 
672                         g_debug ("%s: wizard was already running", __FUNCTION__);
673                 
674                 return;
675         } else {
676                 /* Show the list of accounts */
677                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
678                 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
679                 
680                 /* The accounts dialog must be modal */
681                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
682                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win)); 
683         }
684 }
685
686 #ifdef MODEST_PLATFORM_MAEMO
687 static void
688 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
689 {
690         /* Save any changes. */
691         modest_connection_specific_smtp_window_save_server_accounts (
692                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
693         gtk_widget_destroy (GTK_WIDGET (window));
694 }
695 #endif
696
697
698 void
699 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
700 {
701         /* This is currently only implemented for Maemo,
702          * because it requires an API (libconic) to detect different connection 
703          * possiblities.
704          */
705 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
706         
707         /* Create the window if necessary: */
708         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
709         modest_connection_specific_smtp_window_fill_with_connections (
710                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
711                 modest_runtime_get_account_mgr());
712
713         /* Show the window: */  
714         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
715         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
716         gtk_widget_show (specific_window);
717     
718         /* Save changes when the window is hidden: */
719         g_signal_connect (specific_window, "hide", 
720                 G_CALLBACK (on_smtp_servers_window_hide), win);
721 #endif /* MODEST_PLATFORM_MAEMO */
722 }
723
724 void
725 modest_ui_actions_compose_msg(ModestWindow *win,
726                               const gchar *to_str,
727                               const gchar *cc_str,
728                               const gchar *bcc_str,
729                               const gchar *subject_str,
730                               const gchar *body_str,
731                               GSList *attachments)
732 {
733         gchar *account_name = NULL;
734         TnyMsg *msg = NULL;
735         TnyAccount *account = NULL;
736         TnyFolder *folder = NULL;
737         gchar *from_str = NULL, *signature = NULL, *body = NULL;
738         gboolean use_signature = FALSE;
739         ModestWindow *msg_win = NULL;
740         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
741         ModestTnyAccountStore *store = modest_runtime_get_account_store();
742
743         if (win) account_name = g_strdup (modest_window_get_active_account (win));
744         if (!account_name) account_name = modest_account_mgr_get_default_account(mgr);
745         if (!account_name) {
746                 g_printerr ("modest: no account found\n");
747                 goto cleanup;
748         }
749         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
750         if (!account) {
751                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
752                 goto cleanup;
753         }
754         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
755         if (!folder) {
756                 g_printerr ("modest: failed to find Drafts folder\n");
757                 goto cleanup;
758         }
759         from_str = modest_account_mgr_get_from_string (mgr, account_name);
760         if (!from_str) {
761                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
762                 goto cleanup;
763         }
764
765         signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
766         if (body_str != NULL) {
767                 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
768         } else {
769                 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
770         }
771
772         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
773         if (!msg) {
774                 g_printerr ("modest: failed to create new msg\n");
775                 goto cleanup;
776         }
777
778         /* Create and register edit window */
779         /* This is destroyed by TODO. */
780         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
781         while (attachments) {
782                 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
783                                                        attachments->data);
784                 attachments = g_slist_next(attachments);
785         }
786         modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
787
788         if (win) {
789                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
790                                               GTK_WINDOW (win));
791         }
792         gtk_widget_show_all (GTK_WIDGET (msg_win));
793
794 cleanup:
795         g_free (from_str);
796         g_free (signature);
797         g_free (body);
798         g_free (account_name);
799         if (account) g_object_unref (G_OBJECT(account));
800         if (folder) g_object_unref (G_OBJECT(folder));
801         if (msg_win) g_object_unref (G_OBJECT(msg_win));
802         if (msg) g_object_unref (G_OBJECT(msg));
803 }
804
805 void
806 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
807 {
808         /* if there are no accounts yet, just show the wizard */
809         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
810                 if (!modest_ui_actions_run_account_setup_wizard (win))
811                         return;
812                 
813         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL);
814 }
815
816 gboolean 
817 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
818                                        TnyHeader *header,
819                                        TnyMsg *msg)
820 {
821         ModestMailOperationStatus status;
822
823         /* If there is no message or the operation was not successful */
824         status = modest_mail_operation_get_status (mail_op);
825         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
826
827                 /* Remove the header from the preregistered uids */
828                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
829                                                      header);
830
831                 return FALSE;
832         }
833
834         return TRUE;
835 }
836
837 static void
838 open_msg_cb (ModestMailOperation *mail_op, 
839              TnyHeader *header,  
840              gboolean canceled,
841              TnyMsg *msg, 
842              GError *err,
843              gpointer user_data)
844 {
845         ModestWindowMgr *mgr = NULL;
846         ModestWindow *parent_win = NULL;
847         ModestWindow *win = NULL;
848         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
849         gchar *account = NULL;
850         TnyFolder *folder;
851         gboolean open_in_editor = FALSE;
852         
853         /* Do nothing if there was any problem with the mail
854            operation. The error will be shown by the error_handler of
855            the mail operation */
856         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
857                 return;
858
859         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
860         folder = tny_header_get_folder (header);
861
862         /* Mark header as read */
863         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
864
865         /* Gets folder type (OUTBOX headers will be opened in edit window */
866         if (modest_tny_folder_is_local_folder (folder)) {
867                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
868                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
869                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
870         }
871
872                 
873         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
874                 TnyTransportAccount *traccount = NULL;
875                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
876                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
877                 if (traccount) {
878                         ModestTnySendQueue *send_queue = NULL;
879                         ModestTnySendQueueStatus status;
880                         char *msg_id;
881                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
882                                                    TNY_ACCOUNT(traccount)));
883                         send_queue = modest_runtime_get_send_queue(traccount);
884                         msg_id = modest_tny_send_queue_get_msg_id (header);
885                         status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
886                         /* Only open messages in outbox with the editor if they are in Failed state */
887                         if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
888                                 open_in_editor = TRUE;
889                         }
890                         g_free(msg_id);
891                         g_object_unref(traccount);
892                 } else {
893                         g_warning("Cannot get transport account for message in outbox!!");
894                 }
895         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
896                 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
897         }
898
899         /* Get account */
900         if (!account)
901                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
902         if (!account)
903                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
904         
905         if (open_in_editor) {
906                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
907                 const gchar *from_header = NULL;
908
909                 from_header = tny_header_get_from (header);
910
911                 /* we cannot edit without a valid account... */
912                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
913                         if (!modest_ui_actions_run_account_setup_wizard(parent_win))
914                                 goto cleanup;
915                 }
916                 
917                 if (from_header) {
918                         GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
919                         GSList *node = NULL;
920                         for (node = accounts; node != NULL; node = g_slist_next (node)) {
921                                 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
922                                 
923                                 if (from && (strcmp (from_header, from) == 0)) {
924                                         g_free (account);
925                                         account = g_strdup (node->data);
926                                         g_free (from);
927                                         break;
928                                 }
929                                 g_free (from);
930                         }
931                         g_slist_foreach (accounts, (GFunc) g_free, NULL);
932                         g_slist_free (accounts);
933                 }
934
935                 win = modest_msg_edit_window_new (msg, account, TRUE);
936
937
938                 /* Show banner */
939                 modest_platform_information_banner_with_timeout
940                         (NULL, NULL, _("mail_ib_opening_draft_message"), 1200);
941
942         } else {
943                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
944                 
945                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
946                         GtkWidget *header_view;
947                         GtkTreeSelection *sel;
948                         GList *sel_list = NULL;
949                         GtkTreeModel *model;
950                         
951                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
952                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
953
954                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
955                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
956
957                         if (sel_list != NULL) {
958                                 GtkTreeRowReference *row_reference;
959
960                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
961                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
962                                 g_list_free (sel_list);
963                                 
964                                 win = modest_msg_view_window_new_with_header_model (
965                                                 msg, account, (const gchar*) uid,
966                                                 model, row_reference);
967                                 gtk_tree_row_reference_free (row_reference);
968                         } else {
969                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
970                         }
971                 } else {
972                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
973                 }
974                 g_free (uid);
975         }
976         
977         /* Register and show new window */
978         if (win != NULL) {
979                 mgr = modest_runtime_get_window_mgr ();
980                 modest_window_mgr_register_window (mgr, win);
981                 g_object_unref (win);
982                 gtk_widget_show_all (GTK_WIDGET(win));
983         }
984
985         /* Update toolbar dimming state */
986         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
987                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
988         }
989
990 cleanup:
991         /* Free */
992         g_free(account);
993         g_object_unref (parent_win);
994         g_object_unref (folder);
995 }
996
997 void
998 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
999                                                gpointer user_data)
1000 {
1001         const GError *error;
1002         GObject *win = NULL;
1003         const gchar *err_msg;
1004
1005         win = modest_mail_operation_get_source (mail_op);
1006         error = modest_mail_operation_get_error (mail_op);
1007  
1008         /* Select error message */
1009         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT)
1010                 err_msg = _("emev_ni_ui_imap_msg_size_exceed_error");
1011         else
1012                 err_msg = (const gchar *) user_data;
1013
1014         /* Show error */
1015         modest_platform_run_information_dialog ((GtkWindow *) win, err_msg);
1016
1017         if (win)
1018                 g_object_unref (win);
1019 }
1020
1021 /**
1022  * Returns the account a list of headers belongs to. It returns a
1023  * *new* reference so don't forget to unref it
1024  */
1025 static TnyAccount*
1026 get_account_from_header_list (TnyList *headers)
1027 {
1028         TnyAccount *account = NULL;
1029
1030         if (tny_list_get_length (headers) > 0) {
1031                 TnyIterator *iter = tny_list_create_iterator (headers);
1032                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1033                 TnyFolder *folder = tny_header_get_folder (header);
1034                 account = tny_folder_get_account (folder);
1035                 g_object_unref (folder);
1036                 g_object_unref (header);
1037                 g_object_unref (iter);
1038         }
1039         return account;
1040 }
1041
1042 static void
1043 open_msgs_performer(gboolean canceled, 
1044                     GError *err,
1045                     GtkWindow *parent_window,
1046                     TnyAccount *account,
1047                     gpointer user_data)
1048 {
1049         ModestMailOperation *mail_op = NULL;
1050         const gchar *proto_name;
1051         gchar *error_msg;
1052         ModestTransportStoreProtocol proto;
1053         TnyList *not_opened_headers;
1054         TnyConnectionStatus status;
1055
1056         not_opened_headers = TNY_LIST (user_data);
1057
1058         status = tny_account_get_connection_status (account);
1059         if (err || canceled) {
1060                 /* TODO: Show an error ? */
1061                 goto clean;
1062         }
1063
1064         /* Get the error message depending on the protocol */
1065         proto_name = tny_account_get_proto (account);
1066         if (proto_name != NULL) {
1067                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1068         } else {
1069                 proto = MODEST_PROTOCOL_STORE_MAILDIR;
1070         }
1071         
1072         /* Create the error messages */
1073         if (tny_list_get_length (not_opened_headers) == 1) {
1074                 if (proto == MODEST_PROTOCOL_STORE_POP) {
1075                         error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1076                 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1077                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1078                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1079                         error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1080                                                      tny_header_get_subject (header));
1081                         g_object_unref (header);
1082                         g_object_unref (iter);
1083                 } else {
1084                         error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1085                 }
1086         } else {
1087                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1088         }
1089
1090         /* Create the mail operation */
1091         mail_op = 
1092                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1093                                                                modest_ui_actions_get_msgs_full_error_handler,
1094                                                                error_msg, g_free);
1095         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1096                                          mail_op);
1097                 
1098         modest_mail_operation_get_msgs_full (mail_op,
1099                                              not_opened_headers,
1100                                              open_msg_cb,
1101                                              NULL,
1102                                              NULL);
1103
1104         /* Frees */
1105  clean:
1106         if (mail_op)
1107                 g_object_unref (mail_op);
1108         g_object_unref (not_opened_headers);
1109         g_object_unref (account);
1110 }
1111
1112 /*
1113  * This function is used by both modest_ui_actions_on_open and
1114  * modest_ui_actions_on_header_activated. This way we always do the
1115  * same when trying to open messages.
1116  */
1117 static void
1118 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1119 {
1120         ModestWindowMgr *mgr = NULL;
1121         TnyIterator *iter = NULL, *iter_not_opened = NULL;
1122         TnyList *not_opened_headers = NULL;
1123         TnyHeaderFlags flags = 0;
1124         TnyAccount *account;
1125         gint uncached_msgs = 0;
1126                 
1127         g_return_if_fail (headers != NULL);
1128
1129         /* Check that only one message is selected for opening */
1130         if (tny_list_get_length (headers) != 1) {
1131                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1132                                                         _("mcen_ib_select_one_message"));
1133                 return;
1134         }
1135
1136         mgr = modest_runtime_get_window_mgr ();
1137         iter = tny_list_create_iterator (headers);
1138
1139         /* Get the account */
1140         account = get_account_from_header_list (headers);
1141         
1142         /* Look if we already have a message view for each header. If
1143            true, then remove the header from the list of headers to
1144            open */
1145         not_opened_headers = tny_simple_list_new ();
1146         while (!tny_iterator_is_done (iter)) {
1147
1148                 ModestWindow *window = NULL;
1149                 TnyHeader *header = NULL;
1150                 gboolean found = FALSE;
1151                 
1152                 header = TNY_HEADER (tny_iterator_get_current (iter));
1153                 if (header)
1154                         flags = tny_header_get_flags (header);
1155
1156                 window = NULL;
1157                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1158                 
1159                 /* Do not open again the message and present the
1160                    window to the user */
1161                 if (found) {
1162                         if (window)
1163                                 gtk_window_present (GTK_WINDOW (window));
1164                         else
1165                                 /* the header has been registered already, we don't do
1166                                  * anything but wait for the window to come up*/
1167                                 g_debug ("header %p already registered, waiting for window", header);
1168                 } else {
1169                         tny_list_append (not_opened_headers, G_OBJECT (header));
1170                 }
1171
1172                 if (header)
1173                         g_object_unref (header);
1174
1175                 tny_iterator_next (iter);
1176         }
1177         g_object_unref (iter);
1178         iter = NULL;
1179
1180         /* Open each message */
1181         if (tny_list_get_length (not_opened_headers) == 0)
1182                 goto cleanup;
1183         
1184         /* If some messages would have to be downloaded, ask the user to 
1185          * make a connection. It's generally easier to do this here (in the mainloop) 
1186          * than later in a thread:
1187          */
1188         if (tny_list_get_length (not_opened_headers) > 0) {
1189                 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1190
1191                 if (uncached_msgs > 0) {
1192                         /* Allways download if we are online. */
1193                         if (!tny_device_is_online (modest_runtime_get_device ())) {
1194                                 gint response;
1195
1196                                 /* If ask for user permission to download the messages */
1197                                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1198                                                                                     ngettext("mcen_nc_get_msg",
1199                                                                                              "mcen_nc_get_msgs",
1200                                                                                              uncached_msgs));
1201
1202                                 /* End if the user does not want to continue */
1203                                 if (response == GTK_RESPONSE_CANCEL)
1204                                         goto cleanup;
1205                         }
1206                 }
1207         }
1208         
1209         /* Register the headers before actually creating the windows: */
1210         iter_not_opened = tny_list_create_iterator (not_opened_headers);
1211         while (!tny_iterator_is_done (iter_not_opened)) {
1212                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1213                 if (header) {
1214                         modest_window_mgr_register_header (mgr, header, NULL);
1215                         g_object_unref (header);
1216                 }
1217                 tny_iterator_next (iter_not_opened);
1218         }
1219         g_object_unref (iter_not_opened);
1220         iter_not_opened = NULL;
1221
1222         /* Connect to the account and perform */
1223         if (uncached_msgs > 0) {
1224                 modest_platform_connect_and_perform ((GtkWindow *) win, g_object_ref (account), 
1225                                                      open_msgs_performer, g_object_ref (not_opened_headers));
1226         } else {
1227                 /* Call directly the performer, do not need to connect */
1228                 open_msgs_performer (FALSE, NULL, (GtkWindow *) win, g_object_ref (account),
1229                                      g_object_ref (not_opened_headers));
1230         }
1231 cleanup:
1232         /* Clean */
1233         if (account)
1234                 g_object_unref (account);
1235         if (not_opened_headers)
1236                 g_object_unref (not_opened_headers);
1237 }
1238
1239 void
1240 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1241 {
1242         TnyList *headers;
1243
1244         /* Get headers */
1245         headers = get_selected_headers (win);
1246         if (!headers)
1247                 return;
1248
1249         /* Open them */
1250         open_msgs_from_headers (headers, win);
1251
1252         g_object_unref(headers);
1253 }
1254
1255
1256 static void
1257 free_reply_forward_helper (gpointer data)
1258 {
1259         ReplyForwardHelper *helper;
1260
1261         helper = (ReplyForwardHelper *) data;
1262         g_free (helper->account_name);
1263         g_slice_free (ReplyForwardHelper, helper);
1264 }
1265
1266 static void
1267 reply_forward_cb (ModestMailOperation *mail_op,  
1268                   TnyHeader *header, 
1269                   gboolean canceled,
1270                   TnyMsg *msg,
1271                   GError *err,
1272                   gpointer user_data)
1273 {
1274         TnyMsg *new_msg;
1275         ReplyForwardHelper *rf_helper;
1276         ModestWindow *msg_win = NULL;
1277         ModestEditType edit_type;
1278         gchar *from = NULL;
1279         TnyAccount *account = NULL;
1280         ModestWindowMgr *mgr = NULL;
1281         gchar *signature = NULL;
1282         gboolean use_signature;
1283
1284         /* If there was any error. The mail operation could be NULL,
1285            this means that we already have the message downloaded and
1286            that we didn't do a mail operation to retrieve it */
1287         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1288                 return;
1289                         
1290         g_return_if_fail (user_data != NULL);
1291         rf_helper = (ReplyForwardHelper *) user_data;
1292
1293         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1294                                                    rf_helper->account_name);
1295         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1296                                                       rf_helper->account_name, 
1297                                                       &use_signature);
1298
1299         /* Create reply mail */
1300         switch (rf_helper->action) {
1301         case ACTION_REPLY:
1302                 new_msg = 
1303                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1304                                                          rf_helper->reply_forward_type,
1305                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1306                 break;
1307         case ACTION_REPLY_TO_ALL:
1308                 new_msg = 
1309                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1310                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1311                 edit_type = MODEST_EDIT_TYPE_REPLY;
1312                 break;
1313         case ACTION_FORWARD:
1314                 new_msg = 
1315                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1316                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1317                 break;
1318         default:
1319                 g_return_if_reached ();
1320                 return;
1321         }
1322
1323         g_free (signature);
1324
1325         if (!new_msg) {
1326                 g_printerr ("modest: failed to create message\n");
1327                 goto cleanup;
1328         }
1329
1330         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1331                                                                        rf_helper->account_name,
1332                                                                        TNY_ACCOUNT_TYPE_STORE);
1333         if (!account) {
1334                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1335                 goto cleanup;
1336         }
1337
1338         /* Create and register the windows */
1339         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1340         mgr = modest_runtime_get_window_mgr ();
1341         modest_window_mgr_register_window (mgr, msg_win);
1342
1343         if (rf_helper->parent_window != NULL) {
1344                 gdouble parent_zoom;
1345
1346                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1347                 modest_window_set_zoom (msg_win, parent_zoom);
1348         }
1349
1350         /* Show edit window */
1351         gtk_widget_show_all (GTK_WIDGET (msg_win));
1352
1353 cleanup:
1354         if (msg_win)
1355                 g_object_unref (msg_win);
1356         if (new_msg)
1357                 g_object_unref (G_OBJECT (new_msg));
1358         if (account)
1359                 g_object_unref (G_OBJECT (account));
1360 /*      g_object_unref (msg); */
1361         free_reply_forward_helper (rf_helper);
1362 }
1363
1364 /* Checks a list of headers. If any of them are not currently
1365  * downloaded (CACHED) then returns TRUE else returns FALSE.
1366  */
1367 static gint
1368 header_list_count_uncached_msgs (TnyList *header_list)
1369 {
1370         TnyIterator *iter;
1371         gint uncached_messages = 0;
1372
1373         iter = tny_list_create_iterator (header_list);
1374         while (!tny_iterator_is_done (iter)) {
1375                 TnyHeader *header;
1376
1377                 header = TNY_HEADER (tny_iterator_get_current (iter));
1378                 if (header) {
1379                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1380                                 uncached_messages ++;
1381                         g_object_unref (header);
1382                 }
1383
1384                 tny_iterator_next (iter);
1385         }
1386         g_object_unref (iter);
1387
1388         return uncached_messages;
1389 }
1390
1391 /* Returns FALSE if the user does not want to download the
1392  * messages. Returns TRUE if the user allowed the download.
1393  */
1394 static gboolean
1395 connect_to_get_msg (ModestWindow *win,
1396                     gint num_of_uncached_msgs,
1397                     TnyAccount *account)
1398 {
1399         GtkResponseType response;
1400
1401         /* Allways download if we are online. */
1402         if (tny_device_is_online (modest_runtime_get_device ()))
1403                 return TRUE;
1404
1405         /* If offline, then ask for user permission to download the messages */
1406         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1407                         ngettext("mcen_nc_get_msg",
1408                         "mcen_nc_get_msgs",
1409                         num_of_uncached_msgs));
1410
1411         if (response == GTK_RESPONSE_CANCEL)
1412                 return FALSE;
1413
1414         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1415 }
1416
1417 /*
1418  * Common code for the reply and forward actions
1419  */
1420 static void
1421 reply_forward (ReplyForwardAction action, ModestWindow *win)
1422 {
1423         ModestMailOperation *mail_op = NULL;
1424         TnyList *header_list = NULL;
1425         ReplyForwardHelper *rf_helper = NULL;
1426         guint reply_forward_type;
1427         gboolean continue_download = TRUE;
1428         gboolean do_retrieve = TRUE;
1429         
1430         g_return_if_fail (MODEST_IS_WINDOW(win));
1431
1432         /* we need an account when editing */
1433         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1434                 if (!modest_ui_actions_run_account_setup_wizard (win))
1435                         return;
1436         }
1437         
1438         header_list = get_selected_headers (win);
1439         if (!header_list)
1440                 return;
1441
1442         reply_forward_type = 
1443                 modest_conf_get_int (modest_runtime_get_conf (),
1444                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1445                                      NULL);
1446
1447         /* check if we need to download msg before asking about it */
1448         do_retrieve = (action == ACTION_FORWARD) ||
1449                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1450
1451         if (do_retrieve){
1452                 gint num_of_unc_msgs;
1453
1454                 /* check that the messages have been previously downloaded */
1455                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1456                 /* If there are any uncached message ask the user
1457                  * whether he/she wants to download them. */
1458                 if (num_of_unc_msgs) {
1459                         TnyAccount *account = get_account_from_header_list (header_list);
1460                         continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1461                         g_object_unref (account);
1462                 }
1463         }
1464
1465         if (!continue_download) {
1466                 g_object_unref (header_list);
1467                 return;
1468         }
1469         
1470         /* We assume that we can only select messages of the
1471            same folder and that we reply all of them from the
1472            same account. In fact the interface currently only
1473            allows single selection */
1474         
1475         /* Fill helpers */
1476         rf_helper = g_slice_new0 (ReplyForwardHelper);
1477         rf_helper->reply_forward_type = reply_forward_type;
1478         rf_helper->action = action;
1479         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1480         
1481         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1482                 rf_helper->parent_window = GTK_WIDGET (win);
1483         if (!rf_helper->account_name)
1484                 rf_helper->account_name =
1485                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1486
1487         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1488                 TnyMsg *msg;
1489                 TnyHeader *header;
1490                 /* Get header and message. Do not free them here, the
1491                    reply_forward_cb must do it */
1492                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1493                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1494                 if (!msg || !header) {
1495                         if (msg)
1496                                 g_object_unref (msg);
1497                         g_printerr ("modest: no message found\n");
1498                         return;
1499                 } else {
1500                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1501                 }
1502                 if (header)
1503                         g_object_unref (header);
1504         } else {
1505                 TnyHeader *header;
1506                 TnyIterator *iter;
1507
1508                 /* Only reply/forward to one message */
1509                 iter = tny_list_create_iterator (header_list);
1510                 header = TNY_HEADER (tny_iterator_get_current (iter));
1511                 g_object_unref (iter);
1512
1513                 if (header) {
1514                         /* Retrieve messages */
1515                         if (do_retrieve) {
1516                                 mail_op = 
1517                                         modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1518                                                                                        modest_ui_actions_get_msgs_full_error_handler, 
1519                                                                                        NULL, NULL);
1520                                 modest_mail_operation_queue_add (
1521                                         modest_runtime_get_mail_operation_queue (), mail_op);
1522                                 
1523                                 modest_mail_operation_get_msg (mail_op,
1524                                                                header,
1525                                                                reply_forward_cb,
1526                                                                rf_helper);
1527                                 /* Clean */
1528                                 g_object_unref(mail_op);
1529                         } else {
1530                                 /* we put a ref here to prevent double unref as the reply
1531                                  * forward callback unrefs the header at its end */
1532                                 reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1533                         }
1534
1535
1536                         g_object_unref (header);
1537                 }
1538
1539         }
1540
1541         /* Free */
1542         g_object_unref (header_list);
1543 }
1544
1545 void
1546 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1547 {
1548         g_return_if_fail (MODEST_IS_WINDOW(win));
1549
1550         reply_forward (ACTION_REPLY, win);
1551 }
1552
1553 void
1554 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1555 {
1556         g_return_if_fail (MODEST_IS_WINDOW(win));
1557
1558         reply_forward (ACTION_FORWARD, win);
1559 }
1560
1561 void
1562 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1563 {
1564         g_return_if_fail (MODEST_IS_WINDOW(win));
1565
1566         reply_forward (ACTION_REPLY_TO_ALL, win);
1567 }
1568
1569 void 
1570 modest_ui_actions_on_next (GtkAction *action, 
1571                            ModestWindow *window)
1572 {
1573         if (MODEST_IS_MAIN_WINDOW (window)) {
1574                 GtkWidget *header_view;
1575
1576                 header_view = modest_main_window_get_child_widget (
1577                                 MODEST_MAIN_WINDOW(window),
1578                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1579                 if (!header_view)
1580                         return;
1581         
1582                 modest_header_view_select_next (
1583                                 MODEST_HEADER_VIEW(header_view)); 
1584         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1585                 modest_msg_view_window_select_next_message (
1586                                 MODEST_MSG_VIEW_WINDOW (window));
1587         } else {
1588                 g_return_if_reached ();
1589         }
1590 }
1591
1592 void 
1593 modest_ui_actions_on_prev (GtkAction *action, 
1594                            ModestWindow *window)
1595 {
1596         g_return_if_fail (MODEST_IS_WINDOW(window));
1597
1598         if (MODEST_IS_MAIN_WINDOW (window)) {
1599                 GtkWidget *header_view;
1600                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1601                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1602                 if (!header_view)
1603                         return;
1604                 
1605                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1606         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1607                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1608         } else {
1609                 g_return_if_reached ();
1610         }
1611 }
1612
1613 void 
1614 modest_ui_actions_on_sort (GtkAction *action, 
1615                            ModestWindow *window)
1616 {
1617         g_return_if_fail (MODEST_IS_WINDOW(window));
1618
1619         if (MODEST_IS_MAIN_WINDOW (window)) {
1620                 GtkWidget *header_view;
1621                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1622                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1623                 if (!header_view) {
1624                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1625
1626                         return;
1627                 }
1628
1629                 /* Show sorting dialog */
1630                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1631         }
1632 }
1633
1634 static void
1635 new_messages_arrived (ModestMailOperation *self, 
1636                       TnyList *new_headers,
1637                       gpointer user_data)
1638 {
1639         GObject *source;
1640
1641         source = modest_mail_operation_get_source (self);
1642
1643         /* Notify new messages have been downloaded. Do not notify if
1644            the send&receive was invoked by the user, i.e, if the mail
1645            operation has a source (the main window) */
1646         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0) && !source)
1647                 modest_platform_on_new_headers_received (new_headers);
1648
1649         if (source)
1650                 g_object_unref (source);
1651 }
1652
1653 gboolean
1654 retrieve_all_messages_cb (GObject *source,
1655                           guint num_msgs,
1656                           guint retrieve_limit)
1657 {
1658         GtkWindow *window;
1659         gchar *msg;
1660         gint response;
1661
1662         window = GTK_WINDOW (source);
1663         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"), 
1664                                num_msgs, retrieve_limit);
1665
1666         /* Ask the user if they want to retrieve all the messages */
1667         response = 
1668                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1669                                                                       _("mcen_bd_get_all"),
1670                                                                       _("mcen_bd_newest_only"));
1671         /* Free and return */
1672         g_free (msg);
1673         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1674 }
1675
1676 typedef struct {
1677         TnyAccount *account;
1678         ModestWindow *win;
1679         gchar *account_name;
1680 } SendReceiveInfo;
1681
1682 static void
1683 do_send_receive_performer (gboolean canceled, 
1684                            GError *err,
1685                            GtkWindow *parent_window, 
1686                            TnyAccount *account, 
1687                            gpointer user_data)
1688 {
1689         ModestMailOperation *mail_op;
1690         SendReceiveInfo *info;
1691
1692         info = (SendReceiveInfo *) user_data;
1693
1694         if (err || canceled) {
1695
1696                 goto clean;
1697         }
1698
1699         /* Set send/receive operation in progress */    
1700         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
1701                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1702         }
1703         
1704         mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
1705                                                                  modest_ui_actions_send_receive_error_handler,
1706                                                                  NULL, NULL);
1707
1708         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1709                 g_signal_connect (G_OBJECT(mail_op), "operation-finished", 
1710                                   G_CALLBACK (on_send_receive_finished), 
1711                                   info->win);
1712
1713         /* Send & receive. */
1714         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1715         modest_mail_operation_update_account (mail_op, info->account_name, (info->win) ? FALSE : TRUE,
1716                                               (info->win) ? retrieve_all_messages_cb : NULL, 
1717                                               new_messages_arrived, info->win);
1718         g_object_unref (G_OBJECT (mail_op));
1719         
1720  clean:
1721         /* Frees */
1722         if (info->account_name)
1723                 g_free (info->account_name);
1724         if (info->win)
1725                 g_object_unref (info->win);
1726         if (info->account)
1727                 g_object_unref (info->account);
1728         g_slice_free (SendReceiveInfo, info);
1729 }
1730
1731 /*
1732  * This function performs the send & receive required actions. The
1733  * window is used to create the mail operation. Typically it should
1734  * always be the main window, but we pass it as argument in order to
1735  * be more flexible.
1736  */
1737 void
1738 modest_ui_actions_do_send_receive (const gchar *account_name, 
1739                                    ModestWindow *win)
1740 {
1741         gchar *acc_name = NULL;
1742         SendReceiveInfo *info;
1743         ModestTnyAccountStore *acc_store;
1744
1745         /* If no account name was provided then get the current account, and if
1746            there is no current account then pick the default one: */
1747         if (!account_name) {
1748                 if (win)
1749                         acc_name = g_strdup (modest_window_get_active_account (win));
1750                 if (!acc_name)
1751                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1752                 if (!acc_name) {
1753                         g_printerr ("modest: cannot get default account\n");
1754                         return;
1755                 }
1756         } else {
1757                 acc_name = g_strdup (account_name);
1758         }
1759
1760         acc_store = modest_runtime_get_account_store ();
1761
1762         /* Create the info for the connect and perform */
1763         info = g_slice_new (SendReceiveInfo);
1764         info->account_name = acc_name;
1765         info->win = (win) ? g_object_ref (win) : NULL;
1766         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1767                                                                      TNY_ACCOUNT_TYPE_STORE);
1768
1769         /* Invoke the connect and perform */
1770         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, info->account, 
1771                                              do_send_receive_performer, info);
1772 }
1773
1774
1775 static void
1776 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1777                                   ModestWindow *win)
1778 {
1779         TnyTransportAccount *transport_account;
1780         TnySendQueue *send_queue = NULL;
1781         GError *error = NULL;
1782
1783         /* Get transport account */
1784         transport_account =
1785                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1786                                       (modest_runtime_get_account_store(),
1787                                        account_name,
1788                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1789         if (!transport_account) {
1790                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1791                 goto frees;
1792         }
1793
1794         /* Get send queue*/
1795         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1796         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1797                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1798                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1799                              "modest: could not find send queue for account\n");
1800         } else {
1801                 /* Keeep messages in outbox folder */
1802                 tny_send_queue_cancel (send_queue, FALSE, &error);
1803         }       
1804
1805  frees:
1806         if (transport_account != NULL) 
1807                 g_object_unref (G_OBJECT (transport_account));
1808 }
1809
1810 static void
1811 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1812 {
1813         GSList *account_names, *iter;
1814
1815         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1816                                                           TRUE);
1817
1818         iter = account_names;
1819         while (iter) {                  
1820                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1821                 iter = g_slist_next (iter);
1822         }
1823
1824         modest_account_mgr_free_account_names (account_names);
1825         account_names = NULL;
1826 }
1827
1828 void
1829 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1830
1831 {
1832         /* Check if accounts exist */
1833         gboolean accounts_exist = 
1834                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1835         
1836         /* If not, allow the user to create an account before trying to send/receive. */
1837         if (!accounts_exist)
1838                 modest_ui_actions_on_accounts (NULL, win);
1839         
1840         /* Cancel all sending operaitons */     
1841         modest_ui_actions_cancel_send_all (win);
1842 }
1843
1844 /*
1845  * Refreshes all accounts. This function will be used by automatic
1846  * updates
1847  */
1848 void
1849 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1850 {
1851         GSList *account_names, *iter;
1852
1853         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1854                                                           TRUE);
1855
1856         iter = account_names;
1857         while (iter) {                  
1858                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1859                 iter = g_slist_next (iter);
1860         }
1861
1862         modest_account_mgr_free_account_names (account_names);
1863         account_names = NULL;
1864 }
1865
1866 /*
1867  * Handler of the click on Send&Receive button in the main toolbar
1868  */
1869 void
1870 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1871 {
1872         /* Check if accounts exist */
1873         gboolean accounts_exist;
1874
1875         accounts_exist =
1876                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1877         
1878         /* If not, allow the user to create an account before trying to send/receive. */
1879         if (!accounts_exist)
1880                 modest_ui_actions_on_accounts (NULL, win);
1881         
1882         /* Refresh the current folder. The if is always TRUE it's just an extra check */
1883         if (MODEST_IS_MAIN_WINDOW (win)) {
1884                 GtkWidget *folder_view;
1885                 TnyFolderStore *folder_store;
1886
1887                 folder_view = 
1888                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1889                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1890                 if (!folder_view)
1891                         return;
1892                 
1893                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1894         
1895                 if (folder_store)
1896                         g_object_unref (folder_store);
1897         }       
1898         
1899         /* Refresh the active account */
1900         modest_ui_actions_do_send_receive (NULL, win);
1901 }
1902
1903
1904 void
1905 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1906 {
1907         ModestConf *conf;
1908         GtkWidget *header_view;
1909         
1910         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1911
1912         header_view = modest_main_window_get_child_widget (main_window,
1913                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1914         if (!header_view)
1915                 return;
1916
1917         conf = modest_runtime_get_conf ();
1918         
1919         /* what is saved/restored is depending on the style; thus; we save with
1920          * old style, then update the style, and restore for this new style
1921          */
1922         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1923         
1924         if (modest_header_view_get_style
1925             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1926                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1927                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1928         else
1929                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1930                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1931
1932         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1933                                       MODEST_CONF_HEADER_VIEW_KEY);
1934 }
1935
1936
1937 void 
1938 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1939                                       TnyHeader *header,
1940                                       ModestMainWindow *main_window)
1941 {
1942         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1943         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1944         
1945         /* in the case the folder is empty, show the empty folder message and focus
1946          * folder view */
1947         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1948                 if (modest_header_view_is_empty (header_view)) {
1949                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1950                         GtkWidget *folder_view = 
1951                                 modest_main_window_get_child_widget (main_window,
1952                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1953                         if (folder != NULL) 
1954                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1955                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1956                         return;
1957                 }
1958         }
1959         /* If no header has been selected then exit */
1960         if (!header)
1961                 return;
1962
1963         /* Update focus */
1964         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1965             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1966
1967         /* Update toolbar dimming state */
1968         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1969 }
1970
1971 void
1972 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1973                                        TnyHeader *header,
1974                                        ModestMainWindow *main_window)
1975 {
1976         TnyList *headers;
1977
1978         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1979         
1980         if (!header)
1981                 return;
1982
1983         if (modest_header_view_count_selected_headers (header_view) > 1) {
1984                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1985                 return;
1986         }
1987
1988
1989 /*      headers = tny_simple_list_new (); */
1990 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1991         headers = modest_header_view_get_selected_headers (header_view);
1992
1993         open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
1994
1995         g_object_unref (headers);
1996 }
1997
1998 static void
1999 set_active_account_from_tny_account (TnyAccount *account,
2000                                      ModestWindow *window)
2001 {
2002         const gchar *server_acc_name = tny_account_get_id (account);
2003         
2004         /* We need the TnyAccount provided by the
2005            account store because that is the one that
2006            knows the name of the Modest account */
2007         TnyAccount *modest_server_account = modest_server_account = 
2008                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2009                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
2010                                                              server_acc_name);
2011         if (!modest_server_account) {
2012                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2013                 return;
2014         }
2015
2016         /* Update active account, but only if it's not a pseudo-account */
2017         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2018             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2019                 const gchar *modest_acc_name = 
2020                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2021                 if (modest_acc_name)
2022                         modest_window_set_active_account (window, modest_acc_name);
2023         }
2024         
2025         g_object_unref (modest_server_account);
2026 }
2027
2028
2029 static void
2030 folder_refreshed_cb (ModestMailOperation *mail_op, 
2031                      TnyFolder *folder, 
2032                      gpointer user_data)
2033 {
2034         ModestMainWindow *win = NULL;
2035         GtkWidget *header_view;
2036         gboolean folder_empty = FALSE;
2037         gboolean all_marked_as_deleted = FALSE;
2038
2039         g_return_if_fail (TNY_IS_FOLDER (folder));
2040
2041         win = MODEST_MAIN_WINDOW (user_data);
2042         header_view = 
2043                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2044
2045         if (header_view) {
2046                 TnyFolder *current_folder;
2047
2048                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2049                 if (current_folder != NULL && folder != current_folder) {
2050                         g_object_unref (current_folder);
2051                         return;
2052                 }
2053                 g_object_unref (current_folder);
2054         }
2055
2056         /* Check if folder is empty and set headers view contents style */
2057         folder_empty = (tny_folder_get_all_count (folder) == 0);
2058         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
2059         if (folder_empty || all_marked_as_deleted)
2060                 modest_main_window_set_contents_style (win,
2061                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2062 }
2063
2064 void 
2065 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2066                                                TnyFolderStore *folder_store, 
2067                                                gboolean selected,
2068                                                ModestMainWindow *main_window)
2069 {
2070         ModestConf *conf;
2071         GtkWidget *header_view;
2072
2073         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2074
2075         header_view = modest_main_window_get_child_widget(main_window,
2076                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2077         if (!header_view)
2078                 return;
2079         
2080         conf = modest_runtime_get_conf ();
2081
2082         if (TNY_IS_ACCOUNT (folder_store)) {
2083                 if (selected) {
2084                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2085                         
2086                         /* Show account details */
2087                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2088                 }
2089         } else {
2090                 if (TNY_IS_FOLDER (folder_store) && selected) {
2091                         
2092                         /* Update the active account */
2093                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2094                         if (account) {
2095                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2096                                 g_object_unref (account);
2097                                 account = NULL;
2098                         }
2099
2100                         /* Set the header style by default, it could
2101                            be changed later by the refresh callback to
2102                            empty */
2103                         modest_main_window_set_contents_style (main_window, 
2104                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2105
2106                         /* Set folder on header view. This function
2107                            will call tny_folder_refresh_async so we
2108                            pass a callback that will be called when
2109                            finished. We use that callback to set the
2110                            empty view if there are no messages */
2111                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2112                                                        TNY_FOLDER (folder_store),
2113                                                        folder_refreshed_cb,
2114                                                        main_window);
2115                         
2116                         /* Restore configuration. We need to do this
2117                            *after* the set_folder because the widget
2118                            memory asks the header view about its
2119                            folder  */
2120                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2121                                                       G_OBJECT(header_view),
2122                                                       MODEST_CONF_HEADER_VIEW_KEY);
2123                 } else {
2124                         /* Update the active account */
2125                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2126                         /* Save only if we're seeing headers */
2127                         if (modest_main_window_get_contents_style (main_window) ==
2128                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2129                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2130                                                            MODEST_CONF_HEADER_VIEW_KEY);
2131                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2132                 }
2133         }
2134
2135         /* Update toolbar dimming state */
2136         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2137 }
2138
2139 void 
2140 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2141                                      ModestWindow *win)
2142 {
2143         GtkWidget *dialog;
2144         gchar *txt, *item;
2145         gboolean online;
2146
2147         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2148         
2149         online = tny_device_is_online (modest_runtime_get_device());
2150
2151         if (online) {
2152                 /* already online -- the item is simply not there... */
2153                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2154                                                  GTK_DIALOG_MODAL,
2155                                                  GTK_MESSAGE_WARNING,
2156                                                  GTK_BUTTONS_NONE,
2157                                                  _("The %s you selected cannot be found"),
2158                                                  item);
2159                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2160                 gtk_dialog_run (GTK_DIALOG(dialog));
2161         } else {
2162                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2163                                                       GTK_WINDOW (win),
2164                                                       GTK_DIALOG_MODAL,
2165                                                       _("mcen_bd_dialog_cancel"),
2166                                                       GTK_RESPONSE_REJECT,
2167                                                       _("mcen_bd_dialog_ok"),
2168                                                       GTK_RESPONSE_ACCEPT,
2169                                                       NULL);
2170                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2171                                          "Do you want to get online?"), item);
2172                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2173                                     gtk_label_new (txt), FALSE, FALSE, 0);
2174                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2175                 g_free (txt);
2176
2177                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2178                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2179                         /* TODO: Comment about why is this commented out: */
2180                         /* modest_platform_connect_and_wait (); */
2181                 }
2182         }
2183         gtk_widget_destroy (dialog);
2184 }
2185
2186 void
2187 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2188                                      ModestWindow *win)
2189 {
2190         /* g_message ("%s %s", __FUNCTION__, link); */
2191 }       
2192
2193
2194 void
2195 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2196                                         ModestWindow *win)
2197 {
2198         modest_platform_activate_uri (link);
2199 }
2200
2201 void
2202 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2203                                           ModestWindow *win)
2204 {
2205         modest_platform_show_uri_popup (link);
2206 }
2207
2208 void
2209 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2210                                              ModestWindow *win)
2211 {
2212         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2213 }
2214
2215 void
2216 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2217                                           const gchar *address,
2218                                           ModestWindow *win)
2219 {
2220         /* g_message ("%s %s", __FUNCTION__, address); */
2221 }
2222
2223 static void
2224 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2225                       TnyMsg *saved_draft,
2226                       gpointer user_data)
2227 {
2228         ModestMsgEditWindow *edit_window;
2229         ModestMainWindow *win;
2230
2231         /* FIXME. Make the header view sensitive again. This is a
2232          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2233          * for details */
2234         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2235                                          modest_runtime_get_window_mgr(), FALSE));
2236         if (win != NULL) {
2237                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2238                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2239                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2240         }
2241
2242         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2243
2244         /* If there was any error do nothing */
2245         if (modest_mail_operation_get_error (mail_op) != NULL)
2246                 return;
2247
2248         modest_msg_edit_window_set_draft (edit_window, saved_draft);
2249 }
2250
2251 void
2252 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2253 {
2254         TnyTransportAccount *transport_account;
2255         ModestMailOperation *mail_operation;
2256         MsgData *data;
2257         gchar *account_name, *from;
2258         ModestAccountMgr *account_mgr;
2259         char *info_text;
2260
2261         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2262         
2263         data = modest_msg_edit_window_get_msg_data (edit_window);
2264
2265         account_name = g_strdup (data->account_name);
2266         account_mgr = modest_runtime_get_account_mgr();
2267         if (!account_name)
2268                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2269         if (!account_name) 
2270                 account_name = modest_account_mgr_get_default_account (account_mgr);
2271         if (!account_name) {
2272                 g_printerr ("modest: no account found\n");
2273                 modest_msg_edit_window_free_msg_data (edit_window, data);
2274                 return;
2275         }
2276
2277         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2278                 account_name = g_strdup (data->account_name);
2279         }
2280
2281         transport_account =
2282                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2283                                       (modest_runtime_get_account_store(),
2284                                        account_name,
2285                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2286         if (!transport_account) {
2287                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2288                 g_free (account_name);
2289                 modest_msg_edit_window_free_msg_data (edit_window, data);
2290                 return;
2291         }
2292         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2293
2294         /* Create the mail operation */         
2295         mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2296         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2297
2298         modest_mail_operation_save_to_drafts (mail_operation,
2299                                               transport_account,
2300                                               data->draft_msg,
2301                                               from,
2302                                               data->to, 
2303                                               data->cc, 
2304                                               data->bcc,
2305                                               data->subject, 
2306                                               data->plain_body, 
2307                                               data->html_body,
2308                                               data->attachments,
2309                                               data->images,
2310                                               data->priority_flags,
2311                                               on_save_to_drafts_cb,
2312                                               edit_window);
2313         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2314         modest_platform_information_banner (NULL, NULL, info_text);
2315
2316         /* Frees */
2317         g_free (info_text);
2318         g_free (from);
2319         g_free (account_name);
2320         g_object_unref (G_OBJECT (transport_account));
2321         g_object_unref (G_OBJECT (mail_operation));
2322
2323         modest_msg_edit_window_free_msg_data (edit_window, data);
2324         modest_msg_edit_window_reset_modified (edit_window);
2325
2326         /* ** FIXME **
2327          * If the drafts folder is selected then make the header view
2328          * insensitive while the message is being saved to drafts
2329          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2330          * is not very clean but it avoids letting the drafts folder
2331          * in an inconsistent state: the user could edit the message
2332          * being saved and undesirable things would happen.
2333          * In the average case the user won't notice anything at
2334          * all. In the worst case (the user is editing a really big
2335          * file from Drafts) the header view will be insensitive
2336          * during the saving process (10 or 20 seconds, depending on
2337          * the message). Anyway this is just a quick workaround: once
2338          * we find a better solution it should be removed
2339          * See NB#65125 (commend #18) for details.
2340          */
2341         ModestMainWindow *win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2342                 modest_runtime_get_window_mgr(), FALSE));
2343         if (win != NULL) {
2344                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2345                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2346                 if (view != NULL) {
2347                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2348                         if (folder) {
2349                                 if (modest_tny_folder_is_local_folder(folder)) {
2350                                         TnyFolderType folder_type;
2351                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2352                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2353                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2354                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2355                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2356                                         }
2357                                 }
2358                         }
2359                         if (folder != NULL) g_object_unref(folder);
2360                 }
2361         }
2362 }
2363
2364 /* For instance, when clicking the Send toolbar button when editing a message: */
2365 void
2366 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2367 {
2368         TnyTransportAccount *transport_account = NULL;
2369
2370         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2371
2372         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2373                 return;
2374         
2375         /* FIXME: Code added just for testing. The final version will
2376            use the send queue provided by tinymail and some
2377            classifier */
2378         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2379
2380         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2381         gchar *account_name = g_strdup (data->account_name);
2382         if (!account_name)
2383                 g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2384
2385         if (!account_name) 
2386                 account_name = modest_account_mgr_get_default_account (account_mgr);
2387                 
2388         if (!account_name) {
2389                 modest_msg_edit_window_free_msg_data (edit_window, data);
2390                 /* Run account setup wizard */
2391                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window)))
2392                         return;
2393         }
2394         
2395         /* Get the currently-active transport account for this modest account: */
2396         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2397                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2398                                                           (modest_runtime_get_account_store(),
2399                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2400         }
2401         
2402         if (!transport_account) {
2403                 /* Run account setup wizard */
2404                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2405                         return;
2406         }
2407         
2408         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2409
2410         /* Create the mail operation */
2411         ModestMailOperation *mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2412         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2413
2414         modest_mail_operation_send_new_mail (mail_operation,
2415                                              transport_account,
2416                                              data->draft_msg,
2417                                              from,
2418                                              data->to, 
2419                                              data->cc, 
2420                                              data->bcc,
2421                                              data->subject, 
2422                                              data->plain_body, 
2423                                              data->html_body,
2424                                              data->attachments,
2425                                              data->images,
2426                                              data->priority_flags);
2427
2428         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2429                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2430
2431                                              
2432         /* Free data: */
2433         g_free (from);
2434         g_free (account_name);
2435         g_object_unref (G_OBJECT (transport_account));
2436         g_object_unref (G_OBJECT (mail_operation));
2437
2438         modest_msg_edit_window_free_msg_data (edit_window, data);
2439         modest_msg_edit_window_set_sent (edit_window, TRUE);
2440
2441         /* Save settings and close the window: */
2442         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2443 }
2444
2445 void 
2446 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2447                                   ModestMsgEditWindow *window)
2448 {
2449         ModestMsgEditFormatState *format_state = NULL;
2450
2451         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2452         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2453
2454         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2455                 return;
2456
2457         format_state = modest_msg_edit_window_get_format_state (window);
2458         g_return_if_fail (format_state != NULL);
2459
2460         format_state->bold = gtk_toggle_action_get_active (action);
2461         modest_msg_edit_window_set_format_state (window, format_state);
2462         g_free (format_state);
2463         
2464 }
2465
2466 void 
2467 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2468                                      ModestMsgEditWindow *window)
2469 {
2470         ModestMsgEditFormatState *format_state = NULL;
2471
2472         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2473         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2474
2475         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2476                 return;
2477
2478         format_state = modest_msg_edit_window_get_format_state (window);
2479         g_return_if_fail (format_state != NULL);
2480
2481         format_state->italics = gtk_toggle_action_get_active (action);
2482         modest_msg_edit_window_set_format_state (window, format_state);
2483         g_free (format_state);
2484         
2485 }
2486
2487 void 
2488 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2489                                      ModestMsgEditWindow *window)
2490 {
2491         ModestMsgEditFormatState *format_state = NULL;
2492
2493         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2494         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2495
2496         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2497                 return;
2498
2499         format_state = modest_msg_edit_window_get_format_state (window);
2500         g_return_if_fail (format_state != NULL);
2501
2502         format_state->bullet = gtk_toggle_action_get_active (action);
2503         modest_msg_edit_window_set_format_state (window, format_state);
2504         g_free (format_state);
2505         
2506 }
2507
2508 void 
2509 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2510                                      GtkRadioAction *selected,
2511                                      ModestMsgEditWindow *window)
2512 {
2513         ModestMsgEditFormatState *format_state = NULL;
2514         GtkJustification value;
2515
2516         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2517
2518         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2519                 return;
2520
2521         value = gtk_radio_action_get_current_value (selected);
2522
2523         format_state = modest_msg_edit_window_get_format_state (window);
2524         g_return_if_fail (format_state != NULL);
2525
2526         format_state->justification = value;
2527         modest_msg_edit_window_set_format_state (window, format_state);
2528         g_free (format_state);
2529 }
2530
2531 void 
2532 modest_ui_actions_on_select_editor_color (GtkAction *action,
2533                                           ModestMsgEditWindow *window)
2534 {
2535         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2536         g_return_if_fail (GTK_IS_ACTION (action));
2537
2538         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2539                 return;
2540
2541         modest_msg_edit_window_select_color (window);
2542 }
2543
2544 void 
2545 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2546                                                      ModestMsgEditWindow *window)
2547 {
2548         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2549         g_return_if_fail (GTK_IS_ACTION (action));
2550
2551         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2552                 return;
2553
2554         modest_msg_edit_window_select_background_color (window);
2555 }
2556
2557 void 
2558 modest_ui_actions_on_insert_image (GtkAction *action,
2559                                    ModestMsgEditWindow *window)
2560 {
2561         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2562         g_return_if_fail (GTK_IS_ACTION (action));
2563
2564         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2565                 return;
2566
2567         modest_msg_edit_window_insert_image (window);
2568 }
2569
2570 void 
2571 modest_ui_actions_on_attach_file (GtkAction *action,
2572                                   ModestMsgEditWindow *window)
2573 {
2574         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2575         g_return_if_fail (GTK_IS_ACTION (action));
2576
2577         modest_msg_edit_window_offer_attach_file (window);
2578 }
2579
2580 void 
2581 modest_ui_actions_on_remove_attachments (GtkAction *action,
2582                                          ModestMsgEditWindow *window)
2583 {
2584         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2585         g_return_if_fail (GTK_IS_ACTION (action));
2586
2587         modest_msg_edit_window_remove_attachments (window, NULL);
2588 }
2589
2590 static void
2591 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2592                                             gpointer user_data)
2593 {
2594         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2595         const GError *error = modest_mail_operation_get_error (mail_op);
2596
2597         if(error) {
2598                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2599                                                     _("mail_in_ui_folder_create_error"));
2600         }
2601 }
2602
2603 static void
2604 modest_ui_actions_create_folder(GtkWidget *parent_window,
2605                                 GtkWidget *folder_view)
2606 {
2607         TnyFolderStore *parent_folder;
2608
2609         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2610         
2611         if (parent_folder) {
2612                 gboolean finished = FALSE;
2613                 gint result;
2614                 gchar *folder_name = NULL, *suggested_name = NULL;
2615                 const gchar *proto_str = NULL;
2616                 TnyAccount *account;
2617
2618                 if (TNY_IS_ACCOUNT (parent_folder))
2619                         account = g_object_ref (parent_folder);
2620                 else
2621                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2622                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2623
2624                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2625                     MODEST_PROTOCOL_STORE_POP) {
2626                         finished = TRUE;
2627                         modest_platform_information_banner (NULL, NULL, _("mail_in_ui_folder_create_error"));
2628                 }
2629                 g_object_unref (account);
2630
2631                 /* Run the new folder dialog */
2632                 while (!finished) {
2633                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2634                                                                         parent_folder,
2635                                                                         suggested_name,
2636                                                                         &folder_name);
2637
2638                         g_free (suggested_name);
2639                         suggested_name = NULL;
2640
2641                         if (result == GTK_RESPONSE_ACCEPT) {
2642                                 ModestMailOperation *mail_op;
2643                                 TnyFolder *new_folder = NULL;
2644
2645                                 mail_op  = modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2646                                                                                           modest_ui_actions_new_folder_error_handler,
2647                                                                                           parent_window, NULL);
2648
2649                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2650                                                                  mail_op);
2651                                 new_folder = modest_mail_operation_create_folder (mail_op,
2652                                                                                   parent_folder,
2653                                                                                   (const gchar *) folder_name);
2654                                 if (new_folder) {
2655                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2656                                                                           new_folder, TRUE);
2657
2658                                         g_object_unref (new_folder);
2659                                         finished = TRUE;
2660                                 }
2661                                 g_object_unref (mail_op);
2662                         } else {
2663                                 finished = TRUE;
2664                         }
2665
2666                         suggested_name = folder_name;
2667                         folder_name = NULL;
2668                 }
2669
2670                 g_object_unref (parent_folder);
2671         }
2672 }
2673
2674 void 
2675 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2676 {
2677         GtkWidget *folder_view;
2678         
2679         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2680
2681         folder_view = modest_main_window_get_child_widget (main_window,
2682                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2683         if (!folder_view)
2684                 return;
2685
2686         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2687 }
2688
2689 static void
2690 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2691                                                gpointer user_data)
2692 {
2693         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2694         const GError *error = NULL;
2695         const gchar *message = NULL;
2696         
2697         /* Get error message */
2698         error = modest_mail_operation_get_error (mail_op);
2699         if (!error)
2700                 g_return_if_reached ();
2701
2702         switch (error->code) {
2703         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2704                 message = _CS("ckdg_ib_folder_already_exists");
2705                 break;
2706         default:
2707                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2708                            error->code, error->message);
2709                 return;
2710         }
2711
2712         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2713 }
2714
2715 typedef struct {
2716         TnyFolderStore *folder;
2717         gchar *new_name;
2718 } RenameFolderInfo;
2719
2720 static void
2721 on_rename_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
2722                 TnyAccount *account, gpointer user_data)
2723 {
2724         ModestMailOperation *mail_op = NULL;
2725         GtkTreeSelection *sel = NULL;
2726         GtkWidget *folder_view = NULL;
2727         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
2728
2729         if (!canceled && (err == NULL) && MODEST_IS_MAIN_WINDOW(parent_window)) {
2730
2731                 folder_view = modest_main_window_get_child_widget (
2732                                 MODEST_MAIN_WINDOW (parent_window),
2733                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2734
2735                 mail_op = 
2736                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2737                                         modest_ui_actions_rename_folder_error_handler,
2738                                         parent_window, NULL);
2739
2740                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2741                                 mail_op);
2742
2743                 /* Clear the headers view */
2744                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2745                 gtk_tree_selection_unselect_all (sel);
2746
2747                 /* Select *after* the changes */
2748                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2749                                 TNY_FOLDER(data->folder), TRUE);
2750
2751                 /* Actually rename the folder */
2752                 modest_mail_operation_rename_folder (mail_op,
2753                                 TNY_FOLDER (data->folder),
2754                                 (const gchar *) (data->new_name));
2755                 
2756                 /* TODO folder view filter refilter */
2757                 /* 
2758                 GtkTreeModel *tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view));
2759                 if (GTK_IS_TREE_MODEL_FILTER (tree_model))
2760                         gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (tree_model)); */
2761         }
2762
2763         g_object_unref (mail_op);
2764         g_free (data->new_name);
2765         g_free (data);
2766 }
2767
2768 void 
2769 modest_ui_actions_on_rename_folder (GtkAction *action,
2770                                      ModestMainWindow *main_window)
2771 {
2772         TnyFolderStore *folder;
2773         GtkWidget *folder_view;
2774         GtkWidget *header_view; 
2775
2776         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2777
2778         folder_view = modest_main_window_get_child_widget (main_window,
2779                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2780         if (!folder_view)
2781                 return;
2782
2783         header_view = modest_main_window_get_child_widget (main_window,
2784                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2785         
2786         if (!header_view)
2787                 return;
2788
2789         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2790
2791         if (!folder)
2792                 return;
2793
2794         if (TNY_IS_FOLDER (folder)) {
2795                 gchar *folder_name;
2796                 gint response;
2797                 const gchar *current_name;
2798                 TnyFolderStore *parent;
2799                 gboolean do_rename = TRUE;
2800
2801                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2802                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2803                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2804                                                                      parent, current_name, 
2805                                                                      &folder_name);
2806                 g_object_unref (parent);
2807
2808                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2809                         do_rename = FALSE;
2810                 } else {
2811                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
2812                         rename_folder_data->folder = folder;
2813                         rename_folder_data->new_name = folder_name;
2814                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), 
2815                                         folder, on_rename_folder_cb, rename_folder_data);
2816                 }
2817         }
2818         g_object_unref (folder);
2819 }
2820
2821 static void
2822 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2823                                                gpointer user_data)
2824 {
2825         GObject *win = modest_mail_operation_get_source (mail_op);
2826
2827         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2828                                                 _("mail_in_ui_folder_delete_error"));
2829         g_object_unref (win);
2830 }
2831
2832 typedef struct {
2833         TnyFolderStore *folder;
2834         gboolean move_to_trash;
2835 } DeleteFolderInfo;
2836
2837 static void
2838 on_delete_folder_cb (gboolean canceled, 
2839                   GError *err,
2840                   GtkWindow *parent_window, 
2841                   TnyAccount *account, 
2842                   gpointer user_data)
2843 {
2844         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
2845         GtkWidget *folder_view;
2846         ModestMailOperation *mail_op;
2847         GtkTreeSelection *sel;
2848         
2849         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
2850                 g_object_unref (G_OBJECT (info->folder));
2851                 g_free (info);
2852         }
2853         
2854         folder_view = modest_main_window_get_child_widget (
2855                         MODEST_MAIN_WINDOW (parent_window),
2856                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2857
2858         /* Unselect the folder before deleting it to free the headers */
2859         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2860         gtk_tree_selection_unselect_all (sel);
2861
2862         /* Create the mail operation */
2863         mail_op =
2864                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2865                                 modest_ui_actions_delete_folder_error_handler,
2866                                 NULL, NULL);
2867
2868         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2869                         mail_op);
2870         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
2871         
2872         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2873
2874         g_object_unref (G_OBJECT (mail_op));
2875         g_object_unref (G_OBJECT (info->folder));
2876         g_free (info);
2877 }
2878
2879 static void
2880 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
2881 {
2882         TnyFolderStore *folder;
2883         GtkWidget *folder_view;
2884         gint response;
2885         gchar *message;
2886         
2887         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2888
2889         folder_view = modest_main_window_get_child_widget (main_window,
2890                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2891         if (!folder_view)
2892                 return;
2893
2894         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2895
2896         /* Show an error if it's an account */
2897         if (!TNY_IS_FOLDER (folder)) {
2898                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2899                                                         _("mail_in_ui_folder_delete_error"));
2900                 g_object_unref (G_OBJECT (folder));
2901                 return;
2902         }
2903
2904         /* Ask the user */      
2905         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2906                                     tny_folder_get_name (TNY_FOLDER (folder)));
2907         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2908                                                             (const gchar *) message);
2909         g_free (message);
2910
2911         if (response == GTK_RESPONSE_OK) {
2912                 DeleteFolderInfo *info;
2913                 info = g_new0(DeleteFolderInfo, 1);
2914                 info->folder = folder;
2915                 info->move_to_trash = move_to_trash;
2916                 g_object_ref (G_OBJECT (info->folder));
2917                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2918                 modest_platform_connect_and_perform (GTK_WINDOW (main_window), 
2919                                 account, on_delete_folder_cb, info);
2920                 g_object_unref (account);
2921         }
2922         g_object_unref (G_OBJECT (folder));
2923 }
2924
2925 void 
2926 modest_ui_actions_on_delete_folder (GtkAction *action,
2927                                      ModestMainWindow *main_window)
2928 {
2929         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2930         
2931         delete_folder (main_window, FALSE);
2932 }
2933
2934 void 
2935 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2936 {
2937         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2938         
2939         delete_folder (main_window, TRUE);
2940 }
2941
2942
2943 static void
2944 show_error (GtkWidget *parent_widget, const gchar* text)
2945 {
2946         modest_platform_information_banner(parent_widget, NULL, text);
2947         
2948 #if 0
2949         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2950         /*
2951           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2952           (GtkDialogFlags)0,
2953           GTK_MESSAGE_ERROR,
2954           GTK_BUTTONS_OK,
2955           text ));
2956         */
2957                  
2958         gtk_dialog_run (dialog);
2959         gtk_widget_destroy (GTK_WIDGET (dialog));
2960 #endif
2961 }
2962
2963 void
2964 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2965                                          const gchar* server_account_name,
2966                                          gchar **username,
2967                                          gchar **password, 
2968                                          gboolean *cancel, 
2969                                          gboolean *remember,
2970                                          ModestMainWindow *main_window)
2971 {
2972         g_return_if_fail(server_account_name);
2973         
2974         /* Initalize output parameters: */
2975         if (cancel)
2976                 *cancel = FALSE;
2977                 
2978         if (remember)
2979                 *remember = TRUE;
2980                 
2981 #ifdef MODEST_PLATFORM_MAEMO
2982         /* Maemo uses a different (awkward) button order,
2983          * It should probably just use gtk_alternative_dialog_button_order ().
2984          */
2985         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2986                                               NULL,
2987                                               GTK_DIALOG_MODAL,
2988                                               _("mcen_bd_dialog_ok"),
2989                                               GTK_RESPONSE_ACCEPT,
2990                                               _("mcen_bd_dialog_cancel"),
2991                                               GTK_RESPONSE_REJECT,
2992                                               NULL);
2993 #else
2994         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2995                                               NULL,
2996                                               GTK_DIALOG_MODAL,
2997                                               GTK_STOCK_CANCEL,
2998                                               GTK_RESPONSE_REJECT,
2999                                               GTK_STOCK_OK,
3000                                               GTK_RESPONSE_ACCEPT,
3001                                               NULL);
3002 #endif /* MODEST_PLATFORM_MAEMO */
3003
3004         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3005         
3006         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3007                 modest_runtime_get_account_mgr(), server_account_name);
3008         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3009                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3010                 if (cancel)
3011                         *cancel = TRUE;
3012                 return;
3013         }
3014         
3015         /* This causes a warning because the logical ID has no %s in it, 
3016          * though the translation does, but there is not much we can do about that: */
3017         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3018         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3019                             FALSE, FALSE, 0);
3020         g_free (txt);
3021         g_free (server_name);
3022         server_name = NULL;
3023
3024         /* username: */
3025         gchar *initial_username = modest_account_mgr_get_server_account_username (
3026                 modest_runtime_get_account_mgr(), server_account_name);
3027         
3028         GtkWidget *entry_username = gtk_entry_new ();
3029         if (initial_username)
3030                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3031         /* Dim this if a connection has ever succeeded with this username,
3032          * as per the UI spec: */
3033         const gboolean username_known = 
3034                 modest_account_mgr_get_server_account_username_has_succeeded(
3035                         modest_runtime_get_account_mgr(), server_account_name);
3036         gtk_widget_set_sensitive (entry_username, !username_known);
3037         
3038 #ifdef MODEST_PLATFORM_MAEMO
3039         /* Auto-capitalization is the default, so let's turn it off: */
3040         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3041         
3042         /* Create a size group to be used by all captions.
3043          * Note that HildonCaption does not create a default size group if we do not specify one.
3044          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3045         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3046         
3047         GtkWidget *caption = hildon_caption_new (sizegroup, 
3048                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3049         gtk_widget_show (entry_username);
3050         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3051                 FALSE, FALSE, MODEST_MARGIN_HALF);
3052         gtk_widget_show (caption);
3053 #else 
3054         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3055                             TRUE, FALSE, 0);
3056 #endif /* MODEST_PLATFORM_MAEMO */      
3057                             
3058         /* password: */
3059         GtkWidget *entry_password = gtk_entry_new ();
3060         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3061         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3062         
3063 #ifdef MODEST_PLATFORM_MAEMO
3064         /* Auto-capitalization is the default, so let's turn it off: */
3065         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3066                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3067         
3068         caption = hildon_caption_new (sizegroup, 
3069                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3070         gtk_widget_show (entry_password);
3071         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3072                 FALSE, FALSE, MODEST_MARGIN_HALF);
3073         gtk_widget_show (caption);
3074         g_object_unref (sizegroup);
3075 #else 
3076         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3077                             TRUE, FALSE, 0);
3078 #endif /* MODEST_PLATFORM_MAEMO */      
3079
3080         if (initial_username != NULL)
3081                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3082                                 
3083 /* This is not in the Maemo UI spec:
3084         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3085         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3086                             TRUE, FALSE, 0);
3087 */
3088
3089         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3090         
3091         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3092                 if (username) {
3093                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3094                         
3095                         modest_account_mgr_set_server_account_username (
3096                                  modest_runtime_get_account_mgr(), server_account_name, 
3097                                  *username);
3098                                  
3099                         const gboolean username_was_changed = 
3100                                 (strcmp (*username, initial_username) != 0);
3101                         if (username_was_changed) {
3102                                 g_warning ("%s: tinymail does not yet support changing the "
3103                                         "username in the get_password() callback.\n", __FUNCTION__);
3104                         }
3105                 }
3106                         
3107                 if (password) {
3108                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3109                         
3110                         /* We do not save the password in the configuration, 
3111                          * because this function is only called for passwords that should 
3112                          * not be remembered:
3113                         modest_server_account_set_password (
3114                                  modest_runtime_get_account_mgr(), server_account_name, 
3115                                  *password);
3116                         */
3117                 }
3118                 
3119                 if (cancel)
3120                         *cancel   = FALSE;
3121                         
3122         } else {
3123                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
3124                 
3125                 if (username)
3126                         *username = NULL;
3127                         
3128                 if (password)
3129                         *password = NULL;
3130                         
3131                 if (cancel)
3132                         *cancel   = TRUE;
3133         }
3134
3135 /* This is not in the Maemo UI spec:
3136         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3137                 *remember = TRUE;
3138         else
3139                 *remember = FALSE;
3140 */
3141
3142         gtk_widget_destroy (dialog);
3143         
3144         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3145 }
3146
3147 void
3148 modest_ui_actions_on_cut (GtkAction *action,
3149                           ModestWindow *window)
3150 {
3151         GtkWidget *focused_widget;
3152         GtkClipboard *clipboard;
3153
3154         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3155         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3156         if (GTK_IS_EDITABLE (focused_widget)) {
3157                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3158                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3159                 gtk_clipboard_store (clipboard);
3160         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3161                 GtkTextBuffer *buffer;
3162
3163                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3164                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3165                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3166                 gtk_clipboard_store (clipboard);
3167         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3168                 TnyList *header_list = modest_header_view_get_selected_headers (
3169                                 MODEST_HEADER_VIEW (focused_widget));
3170                 gboolean continue_download = FALSE;
3171                 gint num_of_unc_msgs;
3172
3173                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3174
3175                 if (num_of_unc_msgs) {
3176                         TnyAccount *account = get_account_from_header_list (header_list);
3177                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3178                         g_object_unref (account);
3179                 }
3180
3181                 if (num_of_unc_msgs == 0 || continue_download) {
3182 /*                      modest_platform_information_banner (
3183                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3184                         modest_header_view_cut_selection (
3185                                         MODEST_HEADER_VIEW (focused_widget));
3186                 }
3187
3188                 g_object_unref (header_list);
3189         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3190                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3191         }
3192 }
3193
3194 void
3195 modest_ui_actions_on_copy (GtkAction *action,
3196                            ModestWindow *window)
3197 {
3198         GtkClipboard *clipboard;
3199         GtkWidget *focused_widget;
3200         gboolean copied = TRUE;
3201
3202         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3203         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3204
3205         if (GTK_IS_LABEL (focused_widget)) {
3206                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3207                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3208                 gtk_clipboard_store (clipboard);
3209         } else if (GTK_IS_EDITABLE (focused_widget)) {
3210                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3211                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3212                 gtk_clipboard_store (clipboard);
3213         } else if (GTK_IS_HTML (focused_widget)) {
3214                 gtk_html_copy (GTK_HTML (focused_widget));
3215                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3216                 gtk_clipboard_store (clipboard);
3217         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3218                 GtkTextBuffer *buffer;
3219                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3220                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3221                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3222                 gtk_clipboard_store (clipboard);
3223         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3224                 TnyList *header_list = modest_header_view_get_selected_headers (
3225                                 MODEST_HEADER_VIEW (focused_widget));
3226                 gboolean continue_download = FALSE;
3227                 gint num_of_unc_msgs;
3228
3229                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3230
3231                 if (num_of_unc_msgs) {
3232                         TnyAccount *account = get_account_from_header_list (header_list);
3233                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3234                         g_object_unref (account);
3235                 }
3236
3237                 if (num_of_unc_msgs == 0 || continue_download) {
3238                         modest_platform_information_banner (
3239                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3240                         modest_header_view_copy_selection (
3241                                         MODEST_HEADER_VIEW (focused_widget));
3242                 } else
3243                         copied = FALSE;
3244
3245                 g_object_unref (header_list);
3246
3247         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3248                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3249         }
3250
3251         /* Show information banner if there was a copy to clipboard */
3252         if(copied)
3253                 modest_platform_information_banner (
3254                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3255 }
3256
3257 void
3258 modest_ui_actions_on_undo (GtkAction *action,
3259                            ModestWindow *window)
3260 {
3261         ModestEmailClipboard *clipboard = NULL;
3262
3263         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3264                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3265         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3266                 /* Clear clipboard source */
3267                 clipboard = modest_runtime_get_email_clipboard ();
3268                 modest_email_clipboard_clear (clipboard);               
3269         }
3270         else {
3271                 g_return_if_reached ();
3272         }
3273 }
3274
3275 void
3276 modest_ui_actions_on_redo (GtkAction *action,
3277                            ModestWindow *window)
3278 {
3279         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3280                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3281         }
3282         else {
3283                 g_return_if_reached ();
3284         }
3285 }
3286
3287
3288 static void
3289 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3290 {
3291         /* destroy information note */
3292         gtk_widget_destroy (GTK_WIDGET(user_data));
3293 }
3294
3295
3296 static void
3297 paste_as_attachment_free (gpointer data)
3298 {
3299         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3300
3301         gtk_widget_destroy (helper->banner);
3302         g_object_unref (helper->banner);
3303         g_free (helper);
3304 }
3305
3306 static void
3307 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3308                             TnyHeader *header,
3309                             TnyMsg *msg,
3310                             gpointer userdata)
3311 {
3312         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3313         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3314
3315         if (msg == NULL)
3316                 return;
3317
3318         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3319         
3320 }
3321
3322 void
3323 modest_ui_actions_on_paste (GtkAction *action,
3324                             ModestWindow *window)
3325 {
3326         GtkWidget *focused_widget = NULL;
3327         GtkWidget *inf_note = NULL;
3328         ModestMailOperation *mail_op = NULL;
3329
3330         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3331         if (GTK_IS_EDITABLE (focused_widget)) {
3332                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3333         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3334                 ModestEmailClipboard *e_clipboard = NULL;
3335                 e_clipboard = modest_runtime_get_email_clipboard ();
3336                 if (modest_email_clipboard_cleared (e_clipboard)) {
3337                         GtkTextBuffer *buffer;
3338                         GtkClipboard *clipboard;
3339
3340                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3341                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3342                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3343                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3344                         ModestMailOperation *mail_op;
3345                         TnyFolder *src_folder;
3346                         TnyList *data;
3347                         gboolean delete;
3348                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3349                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3350                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3351                                                                            _CS("ckct_nw_pasting"));
3352                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3353                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3354                         if (helper->banner != NULL) {
3355                                 g_object_ref (G_OBJECT (helper->banner));
3356                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3357                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3358                         }
3359
3360                         if (data != NULL) {
3361                                 modest_mail_operation_get_msgs_full (mail_op, 
3362                                                                      data,
3363                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3364                                                                      helper,
3365                                                                      paste_as_attachment_free);
3366                         }
3367                 }
3368         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3369                 ModestEmailClipboard *clipboard = NULL;
3370                 TnyFolder *src_folder = NULL;
3371                 TnyFolderStore *folder_store = NULL;
3372                 TnyList *data = NULL;           
3373                 gboolean delete = FALSE;
3374                 
3375                 /* Check clipboard source */
3376                 clipboard = modest_runtime_get_email_clipboard ();
3377                 if (modest_email_clipboard_cleared (clipboard)) 
3378                         return;
3379                 
3380                 /* Get elements to paste */
3381                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3382
3383                 /* Create a new mail operation */
3384                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3385                 
3386                 /* Get destination folder */
3387                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3388
3389                 /* transfer messages  */
3390                 if (data != NULL) {
3391                         gint response = 0;
3392
3393                         /* Ask for user confirmation */
3394                         response = 
3395                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3396                                                                              TNY_FOLDER (folder_store), 
3397                                                                              delete,
3398                                                                              data);
3399                         
3400                         if (response == GTK_RESPONSE_OK) {
3401                                 /* Launch notification */
3402                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3403                                                                              _CS("ckct_nw_pasting"));
3404                                 if (inf_note != NULL)  {
3405                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3406                                         gtk_widget_show (GTK_WIDGET(inf_note));
3407                                 }
3408
3409                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3410                                 modest_mail_operation_xfer_msgs (mail_op, 
3411                                                                  data,
3412                                                                  TNY_FOLDER (folder_store),
3413                                                                  delete,
3414                                                                  destroy_information_note,
3415                                                                  inf_note);                             
3416                         } else {
3417                                 g_object_unref (mail_op);
3418                         }
3419                         
3420                 } else if (src_folder != NULL) {                        
3421                         /* Launch notification */
3422                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3423                                                                      _CS("ckct_nw_pasting"));
3424                         if (inf_note != NULL)  {
3425                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3426                                 gtk_widget_show (GTK_WIDGET(inf_note));
3427                         }
3428                         
3429                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3430                         modest_mail_operation_xfer_folder (mail_op, 
3431                                                            src_folder,
3432                                                            folder_store,
3433                                                            delete,
3434                                                            destroy_information_note,
3435                                                            inf_note);
3436                 }
3437
3438                 /* Free */
3439                 if (data != NULL) 
3440                         g_object_unref (data);
3441                 if (src_folder != NULL) 
3442                         g_object_unref (src_folder);
3443                 if (folder_store != NULL) 
3444                         g_object_unref (folder_store);
3445         }
3446 }
3447
3448
3449 void
3450 modest_ui_actions_on_select_all (GtkAction *action,
3451                                  ModestWindow *window)
3452 {
3453         GtkWidget *focused_widget;
3454
3455         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3456         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3457                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3458         } else if (GTK_IS_LABEL (focused_widget)) {
3459                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3460         } else if (GTK_IS_EDITABLE (focused_widget)) {
3461                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3462         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3463                 GtkTextBuffer *buffer;
3464                 GtkTextIter start, end;
3465
3466                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3467                 gtk_text_buffer_get_start_iter (buffer, &start);
3468                 gtk_text_buffer_get_end_iter (buffer, &end);
3469                 gtk_text_buffer_select_range (buffer, &start, &end);
3470         } else if (GTK_IS_HTML (focused_widget)) {
3471                 gtk_html_select_all (GTK_HTML (focused_widget));
3472         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3473                 GtkWidget *header_view = focused_widget;
3474                 GtkTreeSelection *selection = NULL;
3475                 
3476                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3477                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3478                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3479                 }
3480                                 
3481                 /* Disable window dimming management */
3482                 modest_window_disable_dimming (MODEST_WINDOW(window));
3483                 
3484                 /* Select all messages */
3485                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3486                 gtk_tree_selection_select_all (selection);
3487
3488                 /* Set focuse on header view */
3489                 gtk_widget_grab_focus (header_view);
3490
3491
3492                 /* Enable window dimming management */
3493                 modest_window_enable_dimming (MODEST_WINDOW(window));
3494                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3495         }
3496
3497 }
3498
3499 void
3500 modest_ui_actions_on_mark_as_read (GtkAction *action,
3501                                    ModestWindow *window)
3502 {       
3503         g_return_if_fail (MODEST_IS_WINDOW(window));
3504                 
3505         /* Mark each header as read */
3506         do_headers_action (window, headers_action_mark_as_read, NULL);
3507 }
3508
3509 void
3510 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3511                                      ModestWindow *window)
3512 {       
3513         g_return_if_fail (MODEST_IS_WINDOW(window));
3514                 
3515         /* Mark each header as read */
3516         do_headers_action (window, headers_action_mark_as_unread, NULL);
3517 }
3518
3519 void
3520 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3521                                   GtkRadioAction *selected,
3522                                   ModestWindow *window)
3523 {
3524         gint value;
3525
3526         value = gtk_radio_action_get_current_value (selected);
3527         if (MODEST_IS_WINDOW (window)) {
3528                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3529         }
3530 }
3531
3532 void
3533 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3534                                                GtkRadioAction *selected,
3535                                                ModestWindow *window)
3536 {
3537         TnyHeaderFlags flags;
3538         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3539
3540         flags = gtk_radio_action_get_current_value (selected);
3541         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3542 }
3543
3544 void
3545 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3546                                                   GtkRadioAction *selected,
3547                                                   ModestWindow *window)
3548 {
3549         gint file_format;
3550
3551         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3552
3553         file_format = gtk_radio_action_get_current_value (selected);
3554         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3555 }
3556
3557
3558 void
3559 modest_ui_actions_on_zoom_plus (GtkAction *action,
3560                                 ModestWindow *window)
3561 {
3562         g_return_if_fail (MODEST_IS_WINDOW (window));
3563
3564         modest_window_zoom_plus (MODEST_WINDOW (window));
3565 }
3566
3567 void     
3568 modest_ui_actions_on_zoom_minus (GtkAction *action,
3569                                  ModestWindow *window)
3570 {
3571         g_return_if_fail (MODEST_IS_WINDOW (window));
3572
3573         modest_window_zoom_minus (MODEST_WINDOW (window));
3574 }
3575
3576 void     
3577 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3578                                            ModestWindow *window)
3579 {
3580         ModestWindowMgr *mgr;
3581         gboolean fullscreen, active;
3582         g_return_if_fail (MODEST_IS_WINDOW (window));
3583
3584         mgr = modest_runtime_get_window_mgr ();
3585
3586         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3587         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3588
3589         if (active != fullscreen) {
3590                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3591                 gtk_window_present (GTK_WINDOW (window));
3592         }
3593 }
3594
3595 void
3596 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3597                                         ModestWindow *window)
3598 {
3599         ModestWindowMgr *mgr;
3600         gboolean fullscreen;
3601
3602         g_return_if_fail (MODEST_IS_WINDOW (window));
3603
3604         mgr = modest_runtime_get_window_mgr ();
3605         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3606         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3607
3608         gtk_window_present (GTK_WINDOW (window));
3609 }
3610
3611 /* 
3612  * Used by modest_ui_actions_on_details to call do_headers_action 
3613  */
3614 static void
3615 headers_action_show_details (TnyHeader *header, 
3616                              ModestWindow *window,
3617                              gpointer user_data)
3618
3619 {
3620         GtkWidget *dialog;
3621         
3622         /* Create dialog */
3623         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3624
3625         /* Run dialog */
3626         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3627         gtk_widget_show_all (dialog);
3628         gtk_dialog_run (GTK_DIALOG (dialog));
3629
3630         gtk_widget_destroy (dialog);
3631 }
3632
3633 /*
3634  * Show the folder details in a ModestDetailsDialog widget
3635  */
3636 static void
3637 show_folder_details (TnyFolder *folder, 
3638                      GtkWindow *window)
3639 {
3640         GtkWidget *dialog;
3641         
3642         /* Create dialog */
3643         dialog = modest_details_dialog_new_with_folder (window, folder);
3644
3645         /* Run dialog */
3646         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3647         gtk_widget_show_all (dialog);
3648         gtk_dialog_run (GTK_DIALOG (dialog));
3649
3650         gtk_widget_destroy (dialog);
3651 }
3652
3653 /*
3654  * Show the header details in a ModestDetailsDialog widget
3655  */
3656 void     
3657 modest_ui_actions_on_details (GtkAction *action, 
3658                               ModestWindow *win)
3659 {
3660         TnyList * headers_list;
3661         TnyIterator *iter;
3662         TnyHeader *header;              
3663
3664         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3665                 TnyMsg *msg;
3666
3667                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3668                 if (!msg)
3669                         return;
3670                 g_object_unref (msg);           
3671
3672                 headers_list = get_selected_headers (win);
3673                 if (!headers_list)
3674                         return;
3675
3676                 iter = tny_list_create_iterator (headers_list);
3677
3678                 header = TNY_HEADER (tny_iterator_get_current (iter));
3679                 if (header) {
3680                         headers_action_show_details (header, win, NULL);
3681                         g_object_unref (header);
3682                 }
3683
3684                 g_object_unref (iter);
3685                 g_object_unref (headers_list);
3686
3687         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3688                 GtkWidget *folder_view, *header_view;
3689
3690                 /* Check which widget has the focus */
3691                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3692                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3693                 if (gtk_widget_is_focus (folder_view)) {
3694                         TnyFolderStore *folder_store
3695                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3696                         if (!folder_store) {
3697                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3698                                 return; 
3699                         }
3700                         /* Show only when it's a folder */
3701                         /* This function should not be called for account items, 
3702                          * because we dim the menu item for them. */
3703                         if (TNY_IS_FOLDER (folder_store)) {
3704                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3705                         }
3706
3707                         g_object_unref (folder_store);
3708
3709                 } else {
3710                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3711                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3712                         /* Show details of each header */
3713                         do_headers_action (win, headers_action_show_details, header_view);
3714                 }
3715         }
3716 }
3717
3718 void     
3719 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3720                                      ModestMsgEditWindow *window)
3721 {
3722         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3723
3724         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3725 }
3726
3727 void     
3728 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3729                                       ModestMsgEditWindow *window)
3730 {
3731         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3732
3733         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3734 }
3735
3736 void
3737 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3738                                        ModestMainWindow *main_window)
3739 {
3740         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3741
3742         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3743                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3744         else
3745                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3746 }
3747
3748 void 
3749 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3750                                      ModestWindow *window)
3751 {
3752         gboolean active, fullscreen = FALSE;
3753         ModestWindowMgr *mgr;
3754
3755         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3756
3757         /* Check if we want to toggle the toolbar vuew in fullscreen
3758            or normal mode */
3759         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3760                      "ViewShowToolbarFullScreen")) {
3761                 fullscreen = TRUE;
3762         }
3763
3764         /* Toggle toolbar */
3765         mgr = modest_runtime_get_window_mgr ();
3766         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3767 }
3768
3769 void     
3770 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3771                                            ModestMsgEditWindow *window)
3772 {
3773         modest_msg_edit_window_select_font (window);
3774 }
3775
3776 void
3777 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3778                                                   const gchar *display_name,
3779                                                   GtkWindow *window)
3780 {
3781         /* This is usually used to change the title of the main window, which
3782          * is the one that holds the folder view. Note that this change can
3783          * happen even when the widget doesn't have the focus. */
3784         if (display_name)
3785                 gtk_window_set_title (window, display_name);
3786         else
3787                 gtk_window_set_title (window, " ");
3788 }
3789
3790 void
3791 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3792 {
3793         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3794         modest_msg_edit_window_select_contacts (window);
3795 }
3796
3797 void
3798 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3799 {
3800         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3801         modest_msg_edit_window_check_names (window, FALSE);
3802 }
3803
3804 static void
3805 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3806 {
3807         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3808                                          GTK_WIDGET (user_data));
3809 }
3810
3811 /*
3812  * This function is used to track changes in the selection of the
3813  * folder view that is inside the "move to" dialog to enable/disable
3814  * the OK button because we do not want the user to select a disallowed
3815  * destination for a folder.
3816  * The user also not desired to be able to use NEW button on items where
3817  * folder creation is not possibel.
3818  */
3819 static void
3820 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3821                                             TnyFolderStore *folder_store,
3822                                             gboolean selected,
3823                                             gpointer user_data)
3824 {
3825         GtkWidget *dialog = NULL;
3826         GtkWidget *ok_button = NULL, *new_button = NULL;
3827         GList *children = NULL;
3828         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3829         gboolean moving_folder = FALSE;
3830         gboolean is_local_account = TRUE;
3831         GtkWidget *folder_view = NULL;
3832         ModestTnyFolderRules rules;
3833
3834         if (!selected)
3835                 return;
3836
3837         /* Get the OK button */
3838         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3839         if (!dialog)
3840                 return;
3841
3842         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3843         ok_button = GTK_WIDGET (children->next->next->data);
3844         new_button = GTK_WIDGET (children->next->data);
3845         g_list_free (children);
3846
3847         /* check if folder_store is an remote account */
3848         if (TNY_IS_ACCOUNT (folder_store)) {
3849                 TnyAccount *local_account = NULL;
3850                 TnyAccount *mmc_account = NULL;
3851                 ModestTnyAccountStore *account_store = NULL;
3852
3853                 account_store = modest_runtime_get_account_store ();
3854                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3855                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
3856
3857                 if ((gpointer) local_account != (gpointer) folder_store &&
3858                     (gpointer) mmc_account != (gpointer) folder_store) {
3859                         is_local_account = FALSE;
3860                         /* New button should be dimmed on remote
3861                            account root */
3862                         new_sensitive = FALSE;
3863                 }
3864                 g_object_unref (local_account);
3865         }
3866
3867         /* Check the target folder rules */
3868         if (TNY_IS_FOLDER (folder_store)) {
3869                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3870                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3871                         ok_sensitive = FALSE;
3872                         new_sensitive = FALSE;
3873                         goto end;
3874                 }
3875         }
3876
3877         /* Check if we're moving a folder */
3878         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3879                 /* Get the widgets */
3880                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3881                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3882                 if (gtk_widget_is_focus (folder_view))
3883                         moving_folder = TRUE;
3884         }
3885
3886         if (moving_folder) {
3887                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3888
3889                 /* Get the folder to move */
3890                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3891                 
3892                 /* Check that we're not moving to the same folder */
3893                 if (TNY_IS_FOLDER (moved_folder)) {
3894                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3895                         if (parent == folder_store)
3896                                 ok_sensitive = FALSE;
3897                         g_object_unref (parent);
3898                 } 
3899
3900                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3901                         /* Do not allow to move to an account unless it's the
3902                            local folders account */
3903                         if (!is_local_account)
3904                                 ok_sensitive = FALSE;
3905                 } 
3906
3907                 if (ok_sensitive && (moved_folder == folder_store)) {
3908                         /* Do not allow to move to itself */
3909                         ok_sensitive = FALSE;
3910                 }
3911                 g_object_unref (moved_folder);
3912         } else {
3913                 TnyHeader *header = NULL;
3914                 TnyFolder *src_folder = NULL;
3915
3916                 /* Moving a message */
3917                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3918                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3919                         src_folder = tny_header_get_folder (header);
3920                         g_object_unref (header);
3921                 } else {
3922                         src_folder = 
3923                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3924                 }
3925
3926                 /* Do not allow to move the msg to the same folder */
3927                 /* Do not allow to move the msg to an account */
3928                 if ((gpointer) src_folder == (gpointer) folder_store ||
3929                     TNY_IS_ACCOUNT (folder_store))
3930                         ok_sensitive = FALSE;
3931                 g_object_unref (src_folder);
3932         }
3933
3934  end:
3935         /* Set sensitivity of the OK button */
3936         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3937         /* Set sensitivity of the NEW button */
3938         gtk_widget_set_sensitive (new_button, new_sensitive);
3939 }
3940
3941 static GtkWidget*
3942 create_move_to_dialog (GtkWindow *win,
3943                        GtkWidget *folder_view,
3944                        GtkWidget **tree_view)
3945 {
3946         GtkWidget *dialog, *scroll;
3947         GtkWidget *new_button;
3948
3949         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3950                                               GTK_WINDOW (win),
3951                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3952                                               NULL);
3953
3954         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3955         /* We do this manually so GTK+ does not associate a response ID for
3956          * the button. */
3957         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3958         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3959         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3960
3961         /* Create scrolled window */
3962         scroll = gtk_scrolled_window_new (NULL, NULL);
3963         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3964                                          GTK_POLICY_AUTOMATIC,
3965                                          GTK_POLICY_AUTOMATIC);
3966
3967         /* Create folder view */
3968         *tree_view = modest_platform_create_folder_view (NULL);
3969
3970         /* Track changes in the selection to
3971          * disable the OK button whenever "Move to" is not possible
3972          * disbale NEW button whenever New is not possible */
3973         g_signal_connect (*tree_view,
3974                           "folder_selection_changed",
3975                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3976                           win);
3977
3978         /* Listen to clicks on New button */
3979         g_signal_connect (G_OBJECT (new_button), 
3980                           "clicked", 
3981                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3982                           *tree_view);
3983
3984         /* It could happen that we're trying to move a message from a
3985            window (msg window for example) after the main window was
3986            closed, so we can not just get the model of the folder
3987            view */
3988         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3989                 const gchar *visible_id = NULL;
3990
3991                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3992                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3993                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3994                                                MODEST_FOLDER_VIEW(*tree_view));
3995
3996                 visible_id = 
3997                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3998
3999                 /* Show the same account than the one that is shown in the main window */
4000                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4001                                                                              visible_id);
4002         } else {
4003                 const gchar *active_account_name = NULL;
4004                 ModestAccountMgr *mgr = NULL;
4005                 ModestAccountSettings *settings = NULL;
4006                 ModestServerAccountSettings *store_settings = NULL;
4007
4008                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4009                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4010                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4011                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4012
4013                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4014                 mgr = modest_runtime_get_account_mgr ();
4015                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4016
4017                 if (settings) {
4018                         const gchar *store_account_name;
4019                         store_settings = modest_account_settings_get_store_settings (settings);
4020                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4021
4022                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4023                                                                                      store_account_name);
4024                         g_object_unref (store_settings);
4025                         g_object_unref (settings);
4026                 }
4027         }
4028
4029         /* Hide special folders */
4030         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4031         
4032         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4033
4034         /* Add scroll to dialog */
4035         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4036                             scroll, TRUE, TRUE, 0);
4037
4038         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4039         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4040
4041         return dialog;
4042 }
4043
4044 /*
4045  * Returns TRUE if at least one of the headers of the list belongs to
4046  * a message that has been fully retrieved.
4047  */
4048 #if 0 /* no longer in use. delete in 2007.10 */
4049 static gboolean
4050 has_retrieved_msgs (TnyList *list)
4051 {
4052         TnyIterator *iter;
4053         gboolean found = FALSE;
4054
4055         iter = tny_list_create_iterator (list);
4056         while (!tny_iterator_is_done (iter) && !found) {
4057                 TnyHeader *header;
4058                 TnyHeaderFlags flags = 0;
4059
4060                 header = TNY_HEADER (tny_iterator_get_current (iter));
4061                 if (header) {
4062                         flags = tny_header_get_flags (header);
4063                         if (flags & TNY_HEADER_FLAG_CACHED)
4064 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
4065                                 found = TRUE;
4066
4067                         g_object_unref (header);
4068                 }
4069
4070                 if (!found)
4071                         tny_iterator_next (iter);
4072         }
4073         g_object_unref (iter);
4074
4075         return found;
4076 }
4077 #endif /* 0 */
4078
4079
4080 /*
4081  * Shows a confirmation dialog to the user when we're moving messages
4082  * from a remote server to the local storage. Returns the dialog
4083  * response. If it's other kind of movement then it always returns
4084  * GTK_RESPONSE_OK
4085  *
4086  * This one is used by the next functions:
4087  *      modest_ui_actions_on_paste                      - commented out
4088  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4089  */
4090 gint
4091 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4092                                              TnyFolder *dest_folder,
4093                                              gboolean delete,
4094                                              TnyList *headers)
4095 {
4096         gint response = GTK_RESPONSE_OK;
4097         TnyAccount *account = NULL;
4098         TnyFolder *src_folder = NULL;
4099         TnyIterator *iter = NULL;
4100         TnyHeader *header = NULL;
4101
4102         /* return with OK if the destination is a remote folder */
4103         if (modest_tny_folder_is_remote_folder (dest_folder))
4104                 return GTK_RESPONSE_OK;
4105
4106         /* Get source folder */
4107         iter = tny_list_create_iterator (headers);
4108         header = TNY_HEADER (tny_iterator_get_current (iter));
4109         if (header) {
4110                 src_folder = tny_header_get_folder (header);
4111                 g_object_unref (header);
4112         }
4113         g_object_unref (iter);
4114
4115         /* if no src_folder, message may be an attahcment */
4116         if (src_folder == NULL) 
4117                 return GTK_RESPONSE_CANCEL;
4118
4119         /* If the source is a local or MMC folder */
4120         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4121                 g_object_unref (src_folder);
4122                 return GTK_RESPONSE_OK;
4123         }
4124
4125         /* Get the account */
4126         account = tny_folder_get_account (src_folder);
4127
4128         /* now if offline we ask the user */
4129         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4130                 response = GTK_RESPONSE_OK;
4131         else
4132                 response = GTK_RESPONSE_CANCEL;
4133
4134         /* Frees */
4135         g_object_unref (src_folder);
4136         g_object_unref (account);
4137
4138         return response;
4139 }
4140
4141
4142
4143 static void
4144 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
4145 {
4146         MoveToHelper *helper = (MoveToHelper *) user_data;
4147
4148         /* Note that the operation could have failed, in that case do
4149            nothing */
4150         if (modest_mail_operation_get_status (mail_op) == 
4151             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4152
4153                 GObject *object = modest_mail_operation_get_source (mail_op);
4154                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4155                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4156
4157                         if (!modest_msg_view_window_select_next_message (self))
4158                                 if (!modest_msg_view_window_select_previous_message (self))
4159                                         /* No more messages to view, so close this window */
4160                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4161                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4162                         GtkWidget *header_view;
4163                         GtkTreePath *path;
4164                         GtkTreeSelection *sel;
4165
4166                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4167                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4168                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4169                         path = gtk_tree_row_reference_get_path (helper->reference);
4170                         gtk_tree_selection_select_path (sel, path);
4171                         gtk_tree_path_free (path);
4172                 }
4173                 g_object_unref (object);
4174         }
4175
4176         /* Close the "Pasting" information banner */
4177         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4178         if (helper->reference != NULL)
4179                 gtk_tree_row_reference_free (helper->reference);
4180         g_free (helper);
4181 }
4182
4183 void
4184 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4185                                              gpointer user_data)
4186 {
4187         ModestWindow *main_window = NULL;
4188         GObject *win = NULL;
4189         
4190         /* Disable next automatic folder selection */
4191         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4192                                                          FALSE); /* don't create */
4193         if (main_window) {
4194                 GtkWidget *folder_view = NULL;
4195         
4196                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4197                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4198                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4199                 
4200                 if (user_data && TNY_IS_FOLDER (user_data)) {
4201                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4202                                                           TNY_FOLDER (user_data), FALSE);
4203                 }
4204         }
4205
4206         /* Show notification dialog */
4207         win = modest_mail_operation_get_source (mail_op);
4208         modest_platform_run_information_dialog ((GtkWindow *) win, _("mail_in_ui_folder_move_target_error"));
4209         if (win)
4210                 g_object_unref (win);
4211 }
4212
4213 void
4214 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4215                                               gpointer user_data)
4216 {
4217         GObject *win = modest_mail_operation_get_source (mail_op);
4218         const GError *error = modest_mail_operation_get_error (mail_op);
4219
4220         g_return_if_fail (error != NULL);
4221         if (error->message != NULL)             
4222                 g_printerr ("modest: %s\n", error->message);
4223         else
4224                 g_printerr ("modest: unkonw error on send&receive operation");
4225
4226         /* Show error message */
4227 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4228 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4229 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4230 /*      else  */
4231 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4232 /*                                                      _CS("sfil_ib_unable_to_send")); */
4233         g_object_unref (win);
4234 }
4235
4236 static void
4237 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4238                        TnyHeader *header, 
4239                        gboolean canceled,
4240                        TnyMsg *msg, 
4241                        GError *err,
4242                        gpointer user_data)
4243 {
4244         TnyList *parts;
4245         TnyIterator *iter;
4246         gint pending_purges = 0;
4247         gboolean some_purged = FALSE;
4248         ModestWindow *win = MODEST_WINDOW (user_data);
4249         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4250
4251         /* If there was any error */
4252         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4253                 modest_window_mgr_unregister_header (mgr, header);
4254                 return;
4255         }
4256
4257         /* Once the message has been retrieved for purging, we check if
4258          * it's all ok for purging */
4259
4260         parts = tny_simple_list_new ();
4261         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4262         iter = tny_list_create_iterator (parts);
4263
4264         while (!tny_iterator_is_done (iter)) {
4265                 TnyMimePart *part;
4266                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4267                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4268                         if (tny_mime_part_is_purged (part))
4269                                 some_purged = TRUE;
4270                         else
4271                                 pending_purges++;
4272                 }
4273
4274                 if (part)
4275                         g_object_unref (part);
4276
4277                 tny_iterator_next (iter);
4278         }
4279         g_object_unref (iter);
4280         
4281
4282         if (pending_purges>0) {
4283                 gint response;
4284                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4285
4286                 if (response == GTK_RESPONSE_OK) {
4287                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4288                         iter = tny_list_create_iterator (parts);
4289                         while (!tny_iterator_is_done (iter)) {
4290                                 TnyMimePart *part;
4291                                 
4292                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4293                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4294                                         tny_mime_part_set_purged (part);
4295
4296                                 if (part)
4297                                         g_object_unref (part);
4298
4299                                 tny_iterator_next (iter);
4300                         }
4301                         
4302                         tny_msg_rewrite_cache (msg);
4303                 }
4304      /* } else { */
4305                 /* This string no longer exists, refer to NB#75415 for more info */
4306                 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4307         }
4308         g_object_unref (iter);
4309
4310         modest_window_mgr_unregister_header (mgr, header);
4311
4312         g_object_unref (parts);
4313 }
4314
4315 static void
4316 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4317                                                      ModestMainWindow *win)
4318 {
4319         GtkWidget *header_view;
4320         TnyList *header_list;
4321         TnyIterator *iter;
4322         TnyHeader *header;
4323         TnyHeaderFlags flags;
4324         ModestWindow *msg_view_window =  NULL;
4325         gboolean found;
4326
4327         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4328
4329         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4330                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4331
4332         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4333         if (!header_list) {
4334                 g_warning ("%s: no header selected", __FUNCTION__);
4335                 return;
4336         }
4337         
4338         if (tny_list_get_length (header_list) == 1) {
4339                 iter = tny_list_create_iterator (header_list);
4340                 header = TNY_HEADER (tny_iterator_get_current (iter));
4341                 g_object_unref (iter);
4342         } else
4343                 return;
4344         
4345         if (!header || !TNY_IS_HEADER(header)) {
4346                 g_warning ("%s: header is not valid", __FUNCTION__);
4347                 return;
4348         }
4349         
4350         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4351                                                           header, &msg_view_window);
4352         flags = tny_header_get_flags (header);
4353         if (!(flags & TNY_HEADER_FLAG_CACHED))
4354                 return;
4355         if (found) {
4356                 if (msg_view_window != NULL) 
4357                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4358                 else {
4359                         /* do nothing; uid was registered before, so window is probably on it's way */
4360                         g_warning ("debug: header %p has already been registered", header);
4361                 }
4362         } else {
4363                 ModestMailOperation *mail_op = NULL;
4364                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4365                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4366                                                                          modest_ui_actions_get_msgs_full_error_handler,
4367                                                                          NULL, NULL);
4368                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4369                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4370                 
4371                 g_object_unref (mail_op);
4372         }
4373         if (header)
4374                 g_object_unref (header);
4375         if (header_list)
4376                 g_object_unref (header_list);
4377 }
4378
4379 /**
4380  * Utility function that transfer messages from both the main window
4381  * and the msg view window when using the "Move to" dialog
4382  */
4383 static void
4384 xfer_messages_from_move_to_cb  (gboolean canceled, GError *err,
4385                 GtkWindow *parent_window, 
4386                 TnyAccount *account, gpointer user_data)
4387 {
4388         TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
4389         ModestWindow *win = MODEST_WINDOW (parent_window);
4390         TnyList *headers = NULL;
4391         TnyAccount *dst_account = NULL;
4392         const gchar *proto_str = NULL;
4393         gboolean dst_is_pop = FALSE;
4394
4395         if (canceled || err) {
4396                 g_object_unref (dst_folder);
4397                 return;
4398         }
4399         
4400         if (!TNY_IS_FOLDER (dst_folder)) {
4401                 modest_platform_information_banner (GTK_WIDGET (win),
4402                                                     NULL,
4403                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4404                 return;
4405         }
4406
4407         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4408         proto_str = tny_account_get_proto (dst_account);
4409
4410         /* tinymail will return NULL for local folders it seems */
4411         dst_is_pop = proto_str &&
4412                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4413                  MODEST_PROTOCOL_STORE_POP);
4414
4415         g_object_unref (dst_account);
4416
4417         /* Get selected headers */
4418         headers = get_selected_headers (MODEST_WINDOW (win));
4419         if (!headers) {
4420                 g_warning ("%s: no headers selected", __FUNCTION__);
4421                 return;
4422         }
4423
4424
4425         if (dst_is_pop) {
4426                 modest_platform_information_banner (GTK_WIDGET (win),
4427                                                     NULL,
4428                                                     ngettext("mail_in_ui_folder_move_target_error",
4429                                                              "mail_in_ui_folder_move_targets_error",
4430                                                              tny_list_get_length (headers)));
4431                 g_object_unref (headers);
4432                 return;
4433         }
4434
4435         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4436         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4437                                                            _CS("ckct_nw_pasting"));
4438         if (helper->banner != NULL)  {
4439                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4440                 gtk_widget_show (GTK_WIDGET(helper->banner));
4441         }
4442
4443         if (MODEST_IS_MAIN_WINDOW (win)) {
4444                 GtkWidget *header_view = 
4445                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4446                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4447                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4448         }
4449
4450         ModestMailOperation *mail_op = 
4451                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4452                                                                modest_ui_actions_move_folder_error_handler,
4453                                                                NULL, NULL);
4454         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4455                                          mail_op);
4456
4457         modest_mail_operation_xfer_msgs (mail_op, 
4458                                          headers,
4459                                          TNY_FOLDER (dst_folder),
4460                                          TRUE,
4461                                          move_to_cb,
4462                                          helper);
4463
4464         g_object_unref (G_OBJECT (mail_op));
4465         g_object_unref (headers);
4466         g_object_unref (dst_folder);
4467 }
4468
4469 typedef struct {
4470         TnyFolder *src_folder;
4471         TnyFolderStore *dst_folder;
4472         gboolean delete_original;
4473         GtkWidget *folder_view;
4474 } MoveFolderInfo;
4475
4476 static void
4477 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
4478                 TnyAccount *account, gpointer user_data)
4479 {
4480         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4481         GtkTreeSelection *sel;
4482         ModestMailOperation *mail_op = NULL;
4483         
4484         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
4485                 g_object_unref (G_OBJECT (info->src_folder));
4486                 g_object_unref (G_OBJECT (info->dst_folder));
4487                 g_free (info);
4488                 return;
4489         }
4490         
4491         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4492         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4493                         _CS("ckct_nw_pasting"));
4494         if (helper->banner != NULL)  {
4495                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4496                 gtk_widget_show (GTK_WIDGET(helper->banner));
4497         }
4498         /* Clean folder on header view before moving it */
4499         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4500         gtk_tree_selection_unselect_all (sel);
4501
4502         /* Let gtk events run. We need that the folder
4503            view frees its reference to the source
4504            folder *before* issuing the mail operation
4505            so we need the signal handler of selection
4506            changed to happen before the mail
4507            operation 
4508         while (gtk_events_pending ())
4509                 gtk_main_iteration ();   */
4510
4511         mail_op =
4512                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4513                                 modest_ui_actions_move_folder_error_handler,
4514                                 info->src_folder, NULL);
4515         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4516                         mail_op);
4517
4518         /* Select *after* the changes */
4519         /* TODO: this function hangs UI after transfer */ 
4520         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4521         /*                                                        TNY_FOLDER (src_folder), TRUE); */
4522
4523         modest_mail_operation_xfer_folder (mail_op,
4524                         TNY_FOLDER (info->src_folder),
4525                         info->dst_folder,
4526                         info->delete_original, 
4527                         move_to_cb, 
4528                         helper);
4529         
4530         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
4531                         TNY_FOLDER (info->dst_folder), TRUE);
4532         
4533         /* Unref mail operation */
4534         g_object_unref (G_OBJECT (mail_op));
4535         g_object_unref (G_OBJECT (info->src_folder));
4536         g_object_unref (G_OBJECT (info->dst_folder));
4537         g_free (user_data);
4538 }
4539
4540 /*
4541  * UI handler for the "Move to" action when invoked from the
4542  * ModestMainWindow
4543  */
4544 static void 
4545 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4546                                           GtkWidget *folder_view,
4547                                           TnyFolderStore *dst_folder,
4548                                           ModestMainWindow *win)
4549 {
4550         ModestHeaderView *header_view = NULL;
4551         TnyFolderStore *src_folder;
4552         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4553
4554         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4555
4556         /* Get the source folder */
4557         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4558
4559         /* Get header view */
4560         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4561
4562         /* Get folder or messages to transfer */
4563         if (gtk_widget_is_focus (folder_view)) {
4564                 gboolean do_xfer = TRUE;
4565
4566                 /* Allow only to transfer folders to the local root folder */
4567                 if (TNY_IS_ACCOUNT (dst_folder) && 
4568                                 !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4569                                         do_xfer = FALSE;
4570                 } else if (!TNY_IS_FOLDER (src_folder)) {
4571                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4572                         do_xfer = FALSE;
4573                 } /* else if (!online && modest_tny_folder_store_is_remote(src_folder)) {
4574                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER (src_folder));
4575                         TnyAccount *account = tny_folder_get_account (TNY_FOLDER (src_folder));
4576                         if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4577                                 do_xfer = FALSE;
4578                         g_object_unref (account);
4579                 }*/
4580
4581                 if (do_xfer) {
4582                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
4583                         info->src_folder = TNY_FOLDER (src_folder);
4584                         info->dst_folder = dst_folder;
4585                         info->delete_original = TRUE;
4586                         info->folder_view = folder_view;
4587                         g_object_ref (G_OBJECT (info->src_folder));
4588                         g_object_ref (G_OBJECT (info->dst_folder));
4589                         modest_platform_connect_if_remote_and_perform(GTK_WINDOW (win), 
4590                                     TNY_FOLDER_STORE (dst_folder), on_move_folder_cb, info);
4591                 }
4592         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4593                 gboolean do_xfer = TRUE;
4594                 /* Ask for confirmation if the source folder is remote and we're not connected */
4595                 if (!online && modest_tny_folder_store_is_remote(src_folder)) {
4596                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4597                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4598                                 guint num_headers = tny_list_get_length(headers);
4599                                 TnyAccount *account = get_account_from_header_list (headers);
4600                                 if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4601                                         do_xfer = FALSE;
4602                                 g_object_unref (account);
4603                         }
4604                         g_object_unref(headers);
4605                 }
4606                 if (do_xfer) /* Transfer messages */ {
4607                         g_object_ref (dst_folder);
4608                         modest_platform_connect_if_remote_and_perform(GTK_WINDOW (win), 
4609                                         TNY_FOLDER_STORE (dst_folder), xfer_messages_from_move_to_cb, dst_folder);
4610                 }
4611         }
4612
4613         if (src_folder)
4614                 g_object_unref (src_folder);
4615 }
4616
4617
4618 /*
4619  * UI handler for the "Move to" action when invoked from the
4620  * ModestMsgViewWindow
4621  */
4622 static void 
4623 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4624                                               TnyFolderStore *dst_folder,
4625                                               ModestMsgViewWindow *win)
4626 {
4627         TnyHeader *header = NULL;
4628         TnyFolder *src_folder = NULL;
4629         TnyAccount *account = NULL;
4630         gboolean do_xfer = FALSE;
4631
4632         /* Create header list */
4633         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4634         src_folder = TNY_FOLDER (tny_header_get_folder(header));
4635         g_object_unref (header);
4636
4637         account = tny_folder_get_account (src_folder);
4638         if (!modest_tny_folder_store_is_remote(TNY_FOLDER_STORE(src_folder))) {
4639                 /* Transfer if the source folder is local */
4640                 do_xfer = TRUE;
4641         } else if (remote_folder_is_pop(TNY_FOLDER_STORE(src_folder))) {
4642                 /* Transfer if the source folder is POP (as it means
4643                  * that the message is already downloaded) */
4644                 do_xfer = TRUE;
4645         } else if (connect_to_get_msg(MODEST_WINDOW(win), 1, account)) {
4646                 /* Transfer after asking confirmation */
4647                 do_xfer = TRUE;
4648         }
4649
4650         if (do_xfer) {
4651                 g_object_ref (dst_folder);
4652                 modest_platform_connect_if_remote_and_perform(GTK_WINDOW (win), 
4653                                 TNY_FOLDER_STORE (dst_folder), xfer_messages_from_move_to_cb, dst_folder);
4654         }
4655         g_object_unref (account);
4656         g_object_unref (src_folder);
4657 }
4658
4659 void 
4660 modest_ui_actions_on_move_to (GtkAction *action, 
4661                               ModestWindow *win)
4662 {
4663         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4664         gint result = 0;
4665         TnyFolderStore *dst_folder = NULL;
4666         ModestMainWindow *main_window;
4667
4668         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4669                           MODEST_IS_MSG_VIEW_WINDOW (win));
4670
4671         /* Get the main window if exists */
4672         if (MODEST_IS_MAIN_WINDOW (win))
4673                 main_window = MODEST_MAIN_WINDOW (win);
4674         else
4675                 main_window = 
4676                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4677                                                                                FALSE)); /* don't create */
4678
4679         /* Get the folder view widget if exists */
4680         if (main_window)
4681                 folder_view = modest_main_window_get_child_widget (main_window,
4682                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4683         else
4684                 folder_view = NULL;
4685
4686         /* Create and run the dialog */
4687         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4688         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4689         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4690         result = gtk_dialog_run (GTK_DIALOG(dialog));
4691         g_object_ref (tree_view);
4692         gtk_widget_destroy (dialog);
4693
4694         if (result != GTK_RESPONSE_ACCEPT)
4695                 return;
4696
4697         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4698         /* Do window specific stuff */
4699         if (MODEST_IS_MAIN_WINDOW (win)) {
4700                 modest_ui_actions_on_main_window_move_to (action,
4701                                 folder_view,
4702                                 dst_folder,
4703                                 MODEST_MAIN_WINDOW (win));
4704         } else {
4705                 modest_ui_actions_on_msg_view_window_move_to (action,
4706                                 dst_folder,
4707                                 MODEST_MSG_VIEW_WINDOW (win));
4708         }
4709
4710         if (dst_folder)
4711                 g_object_unref (dst_folder);
4712 }
4713
4714 /*
4715  * Calls #HeadersFunc for each header already selected in the main
4716  * window or the message currently being shown in the msg view window
4717  */
4718 static void
4719 do_headers_action (ModestWindow *win, 
4720                    HeadersFunc func,
4721                    gpointer user_data)
4722 {
4723         TnyList *headers_list = NULL;
4724         TnyIterator *iter = NULL;
4725         TnyHeader *header = NULL;
4726         TnyFolder *folder = NULL;
4727
4728         /* Get headers */
4729         headers_list = get_selected_headers (win);
4730         if (!headers_list)
4731                 return;
4732
4733         /* Get the folder */
4734         iter = tny_list_create_iterator (headers_list);
4735         header = TNY_HEADER (tny_iterator_get_current (iter));
4736         if (header) {
4737                 folder = tny_header_get_folder (header);
4738                 g_object_unref (header);
4739         }
4740
4741         /* Call the function for each header */
4742         while (!tny_iterator_is_done (iter)) {
4743                 header = TNY_HEADER (tny_iterator_get_current (iter));
4744                 func (header, win, user_data);
4745                 g_object_unref (header);
4746                 tny_iterator_next (iter);
4747         }
4748
4749         /* Trick: do a poke status in order to speed up the signaling
4750            of observers */
4751         tny_folder_poke_status (folder);
4752
4753         /* Frees */
4754         g_object_unref (folder);
4755         g_object_unref (iter);
4756         g_object_unref (headers_list);
4757 }
4758
4759 void 
4760 modest_ui_actions_view_attachment (GtkAction *action,
4761                                    ModestWindow *window)
4762 {
4763         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4764                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4765         } else {
4766                 /* not supported window for this action */
4767                 g_return_if_reached ();
4768         }
4769 }
4770
4771 void
4772 modest_ui_actions_save_attachments (GtkAction *action,
4773                                     ModestWindow *window)
4774 {
4775         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4776                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4777         } else {
4778                 /* not supported window for this action */
4779                 g_return_if_reached ();
4780         }
4781 }
4782
4783 void
4784 modest_ui_actions_remove_attachments (GtkAction *action,
4785                                       ModestWindow *window)
4786 {
4787         if (MODEST_IS_MAIN_WINDOW (window)) {
4788                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4789         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4790                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4791         } else {
4792                 /* not supported window for this action */
4793                 g_return_if_reached ();
4794         }
4795 }
4796
4797 void 
4798 modest_ui_actions_on_settings (GtkAction *action, 
4799                                ModestWindow *win)
4800 {
4801         GtkWidget *dialog;
4802
4803         dialog = modest_platform_get_global_settings_dialog ();
4804         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4805         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4806         gtk_widget_show_all (dialog);
4807
4808         gtk_dialog_run (GTK_DIALOG (dialog));
4809
4810         gtk_widget_destroy (dialog);
4811 }
4812
4813 void 
4814 modest_ui_actions_on_help (GtkAction *action, 
4815                            GtkWindow *win)
4816 {
4817         const gchar *help_id;
4818
4819         g_return_if_fail (action);
4820         g_return_if_fail (win && GTK_IS_WINDOW(win));
4821         
4822         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
4823         
4824         if (help_id)
4825                 modest_platform_show_help (GTK_WINDOW (win), help_id);
4826         else
4827                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
4828 }
4829
4830 static void
4831 retrieve_msg_contents_performer (gboolean canceled, 
4832                                  GError *err,
4833                                  GtkWindow *parent_window, 
4834                                  TnyAccount *account, 
4835                                  gpointer user_data)
4836 {
4837         ModestMailOperation *mail_op;
4838         TnyList *headers = TNY_LIST (user_data);
4839
4840         if (err || canceled) {
4841                 /* Show an error ? */
4842                 goto out;
4843         }
4844
4845         /* Create mail operation */
4846         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
4847                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4848                                                                  NULL, NULL);
4849         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4850         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4851
4852         /* Frees */
4853         g_object_unref (mail_op);
4854  out:
4855         g_object_unref (headers);
4856         g_object_unref (account);
4857 }
4858
4859 void 
4860 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4861                                             ModestWindow *window)
4862 {
4863         TnyList *headers = NULL;
4864         TnyAccount *account = NULL;
4865         TnyIterator *iter = NULL;
4866         TnyHeader *header = NULL;
4867         TnyFolder *folder = NULL;
4868
4869         /* Get headers */
4870         headers = get_selected_headers (window);
4871         if (!headers)
4872                 return;
4873
4874         /* Pick the account */
4875         iter = tny_list_create_iterator (headers);
4876         header = TNY_HEADER (tny_iterator_get_current (iter));
4877         folder = tny_header_get_folder (header);
4878         account = tny_folder_get_account (folder);
4879         g_object_unref (folder);
4880         g_object_unref (header);
4881         g_object_unref (iter);
4882
4883         /* Connect and perform the message retrieval */
4884         modest_platform_connect_and_perform ((GtkWindow *) window, 
4885                                              g_object_ref (account), 
4886                                              retrieve_msg_contents_performer, 
4887                                              g_object_ref (headers));
4888
4889         /* Frees */
4890         g_object_unref (account);
4891         g_object_unref (headers);
4892 }
4893
4894 void
4895 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4896                                           ModestWindow *window)
4897 {
4898         g_return_if_fail (MODEST_IS_WINDOW (window));
4899         
4900         /* Update dimmed */     
4901         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4902 }
4903
4904 void
4905 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4906                                           ModestWindow *window)
4907 {
4908         g_return_if_fail (MODEST_IS_WINDOW (window));
4909
4910         /* Update dimmed */     
4911         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4912 }
4913
4914 void
4915 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4916                                           ModestWindow *window)
4917 {
4918         g_return_if_fail (MODEST_IS_WINDOW (window));
4919
4920         /* Update dimmed */     
4921         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4922 }
4923
4924 void
4925 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4926                                             ModestWindow *window)
4927 {
4928         g_return_if_fail (MODEST_IS_WINDOW (window));
4929
4930         /* Update dimmed */     
4931         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4932 }
4933
4934 void
4935 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4936                                           ModestWindow *window)
4937 {
4938         g_return_if_fail (MODEST_IS_WINDOW (window));
4939
4940         /* Update dimmed */     
4941         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4942 }
4943
4944 void
4945 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4946                                           ModestWindow *window)
4947 {
4948         g_return_if_fail (MODEST_IS_WINDOW (window));
4949
4950         /* Update dimmed */     
4951         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4952 }
4953
4954 void
4955 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4956                                                  ModestWindow *window)
4957 {
4958         g_return_if_fail (MODEST_IS_WINDOW (window));
4959
4960         /* Update dimmed */     
4961         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4962 }
4963
4964 void
4965 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4966                                                      ModestWindow *window)
4967 {
4968         g_return_if_fail (MODEST_IS_WINDOW (window));
4969
4970         /* Update dimmed */     
4971         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4972 }
4973
4974 void
4975 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4976                                                      ModestWindow *window)
4977 {
4978         g_return_if_fail (MODEST_IS_WINDOW (window));
4979
4980         /* Update dimmed */     
4981         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4982 }
4983
4984 void
4985 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4986 {
4987         g_return_if_fail (MODEST_IS_WINDOW (window));
4988
4989         /* Update dimmed */     
4990         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4991 }
4992
4993 void
4994 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4995 {
4996         g_return_if_fail (MODEST_IS_WINDOW (window));
4997
4998         modest_platform_show_search_messages (GTK_WINDOW (window));
4999 }
5000
5001 void     
5002 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5003 {
5004         g_return_if_fail (MODEST_IS_WINDOW (win));
5005         modest_platform_show_addressbook (GTK_WINDOW (win));
5006 }
5007
5008
5009 void
5010 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5011                                           ModestWindow *window)
5012 {
5013         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5014
5015         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5016 }
5017
5018 static void 
5019 on_send_receive_finished (ModestMailOperation  *mail_op, 
5020                            gpointer user_data)
5021 {
5022         GtkWidget *header_view, *folder_view;
5023         TnyFolderStore *folder_store;
5024         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5025
5026         /* Set send/receive operation finished */       
5027         modest_main_window_notify_send_receive_completed (main_win);
5028
5029         /* Don't refresh the current folder if there were any errors */
5030         if (modest_mail_operation_get_status (mail_op) !=
5031             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5032                 return;
5033         
5034         /* Refresh the current folder if we're viewing a window. We do
5035            this because the user won't be able to see the new mails in
5036            the selected folder after a Send&Receive because it only
5037            performs a poke_status, i.e, only the number of read/unread
5038            messages is updated, but the new headers are not
5039            downloaded */
5040         folder_view = modest_main_window_get_child_widget (main_win, 
5041                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5042         if (!folder_view)
5043                 return;
5044
5045         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5046         
5047         /* Do not need to refresh INBOX again because the
5048            update_account does it always automatically */
5049         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5050             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5051                 ModestMailOperation *refresh_op;
5052
5053                 header_view = modest_main_window_get_child_widget (main_win,
5054                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5055                 
5056                 /* We do not need to set the contents style
5057                    because it hasn't changed. We also do not
5058                    need to save the widget status. Just force
5059                    a refresh */
5060                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5061                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5062                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5063                                                       folder_refreshed_cb, main_win);
5064                 g_object_unref (refresh_op);
5065         }
5066         
5067         if (folder_store)
5068                 g_object_unref (folder_store);
5069 }
5070
5071
5072 void 
5073 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5074                                                 TnyHeader *header, 
5075                                                 TnyMsg *msg, 
5076                                                 GError *err, 
5077                                                 gpointer user_data)
5078 {
5079         const gchar* server_name = NULL;
5080         TnyTransportAccount *server_account;
5081         gchar *message = NULL;
5082
5083         /* Don't show anything if the user cancelled something */
5084         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
5085                 return;
5086
5087         /* Get the server name: */
5088         server_account = 
5089                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5090         if (server_account) {
5091                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5092                         
5093                 g_object_unref (server_account);
5094                 server_account = NULL;
5095         }
5096         
5097         g_return_if_fail (server_name);
5098
5099         /* Show the appropriate message text for the GError: */
5100         switch (err->code) {
5101         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
5102                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5103                 break;
5104         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
5105                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5106                 break;
5107         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
5108                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5109                 break;
5110         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
5111                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5112                 break;
5113         default:
5114                 g_return_if_reached ();
5115         }
5116         
5117         /* TODO if the username or the password where not defined we
5118            should show the Accounts Settings dialog or the Connection
5119            specific SMTP server window */
5120
5121         modest_platform_run_information_dialog (NULL, message);
5122         g_free (message);
5123 }
5124
5125 void
5126 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5127                                                 gchar *msg_id, 
5128                                                 guint status,
5129                                                 gpointer user_data)
5130 {
5131         ModestMainWindow *main_window = NULL;
5132         ModestWindowMgr *mgr = NULL;
5133         GtkWidget *folder_view = NULL, *header_view = NULL;
5134         TnyFolderStore *selected_folder = NULL;
5135         TnyFolderType folder_type;
5136
5137         mgr = modest_runtime_get_window_mgr ();
5138         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5139                                                                              FALSE));/* don't create */
5140         if (!main_window)
5141                 return;
5142
5143         /* Check if selected folder is OUTBOX */
5144         folder_view = modest_main_window_get_child_widget (main_window,
5145                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5146         header_view = modest_main_window_get_child_widget (main_window,
5147                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5148
5149         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5150         if (!TNY_IS_FOLDER (selected_folder)) 
5151                 goto frees;
5152
5153         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5154 #if GTK_CHECK_VERSION(2, 8, 0) 
5155         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
5156         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
5157                 GtkTreeViewColumn *tree_column;
5158
5159                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
5160                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5161                 gtk_tree_view_column_queue_resize (tree_column);
5162         }
5163 #else
5164         gtk_widget_queue_draw (header_view);
5165 #endif          
5166         
5167         /* Free */
5168  frees:
5169         if (selected_folder != NULL)
5170                 g_object_unref (selected_folder);
5171 }
5172
5173 void 
5174 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5175                                                TnyAccount *account)
5176 {
5177         ModestTransportStoreProtocol proto;
5178         const gchar *proto_name;
5179         gchar *error_note = NULL;
5180         
5181         proto_name = tny_account_get_proto (account);
5182         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5183         
5184         switch (proto) {
5185         case MODEST_PROTOCOL_STORE_POP:
5186                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
5187                                               tny_account_get_hostname (account));
5188                 break;
5189         case MODEST_PROTOCOL_STORE_IMAP:
5190                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
5191                                               tny_account_get_hostname (account));
5192                 break;
5193         case MODEST_PROTOCOL_STORE_MAILDIR:
5194         case MODEST_PROTOCOL_STORE_MBOX:
5195                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5196                 break;
5197         default:
5198                 g_warning ("%s: This should not be reached", __FUNCTION__);
5199         }
5200
5201         if (error_note) {
5202                 modest_platform_run_information_dialog (parent_window, error_note);
5203                 g_free (error_note);
5204         }
5205 }