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