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