* Fixes NB#78357, new mail sound is played now with IMAP IDLE events
[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