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