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