* tests:
[modest] / src / modest-ui.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 <string.h>
36 #include <modest-runtime.h>
37 #include "modest-ui-priv.h"
38 #include "modest-ui.h"
39 #include "modest-ui-actions.h"
40 #include "modest-icon-names.h"
41 #include "modest-tny-platform-factory.h"
42 #include "modest-account-view-window.h"
43 #include "modest-account-mgr-helpers.h"
44 #include "modest-main-window.h"
45 #include "modest-mail-operation.h"
46 #include "modest-msg-view-window.h"
47 #include <modest-widget-memory.h>
48 #include <tny-error.h>
49 #include <tny-simple-list.h>
50 #include <tny-msg-view.h>
51 #include <tny-device.h>
52
53 #define MODEST_UI_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
54                                        MODEST_TYPE_UI, \
55                                        ModestUIPrivate))
56
57 typedef struct _GetMsgAsyncHelper {
58         ModestMainWindow *main_window;
59         TnyIterator *iter;
60         GFunc func;
61         gpointer user_data;
62 } GetMsgAsyncHelper;
63
64 typedef enum _ReplyForwardAction {
65         ACTION_REPLY,
66         ACTION_REPLY_TO_ALL,
67         ACTION_FORWARD
68 } ReplyForwardAction;
69
70 typedef struct _ReplyForwardHelper {
71         guint reply_forward_type;
72         ReplyForwardAction action;
73         gchar *from;
74 } ReplyForwardHelper;
75
76 /* globals */
77 static GObjectClass *parent_class = NULL;
78
79 /* 'private'/'protected' functions */
80 static void     modest_ui_class_init   (ModestUIClass *klass);
81 static void     modest_ui_init         (ModestUI *obj);
82 static void     modest_ui_finalize     (GObject *obj);
83
84 static void     register_stock_icons   ();
85 static void     connect_signals        (ModestUI *self);
86
87 static void     reply_forward_func     (gpointer data, 
88                                         gpointer user_data);
89 static void     read_msg_func          (gpointer data, 
90                                         gpointer user_data);
91 static void     get_msg_cb             (TnyFolder *folder, 
92                                         TnyMsg *msg, 
93                                         GError **err, 
94                                         gpointer user_data);
95
96 static void     reply_forward          (GtkWidget *widget,
97                                         ReplyForwardAction action,
98                                         ModestMainWindow *main_window);
99
100 static gchar*   ask_for_folder_name    (GtkWindow *parent_window,
101                                         const gchar *title);
102
103 static void     _modest_ui_actions_on_connection_changed    (TnyDevice *device,
104                                                              gboolean online,
105                                                              ModestUI *modest_ui);
106
107
108 static void     _modest_ui_actions_on_accounts_reloaded     (TnyAccountStore *store, 
109                                                              gpointer user_data);
110
111 static void     _modest_ui_actions_on_folder_moved          (ModestFolderView *folder_view,
112                                                              TnyFolder        *folder, 
113                                                              TnyFolderStore   *parent,
114                                                              gboolean         *done,
115                                                              gpointer          user_data);
116
117 GType
118 modest_ui_get_type (void)
119 {
120         static GType my_type = 0;
121         if (!my_type) {
122                 static const GTypeInfo my_info = {
123                         sizeof(ModestUIClass),
124                         NULL,           /* base init */
125                         NULL,           /* base finalize */
126                         (GClassInitFunc) modest_ui_class_init,
127                         NULL,           /* class finalize */
128                         NULL,           /* class data */
129                         sizeof(ModestUI),
130                         1,              /* n_preallocs */
131                         (GInstanceInitFunc) modest_ui_init,
132                         NULL
133                 };
134                 my_type = g_type_register_static (G_TYPE_OBJECT,
135                                                   "ModestUI",
136                                                   &my_info, 0);
137         }
138         return my_type;
139 }
140
141
142 static void
143 modest_ui_class_init (ModestUIClass *klass)
144 {
145         GObjectClass *gobject_class;
146         gobject_class = (GObjectClass*) klass;
147
148         parent_class            = g_type_class_peek_parent (klass);
149         gobject_class->finalize = modest_ui_finalize;
150
151         g_type_class_add_private (gobject_class, sizeof(ModestUIPrivate));
152
153 }
154
155
156 static void
157 modest_ui_init (ModestUI *obj)
158 {
159         ModestUIPrivate *priv;
160
161         priv = MODEST_UI_GET_PRIVATE(obj);
162
163         priv->main_window    = NULL;
164 }
165
166
167 static void
168 modest_ui_finalize (GObject *obj)
169 {
170         ModestUIPrivate *priv = MODEST_UI_GET_PRIVATE(obj);
171         
172         if (priv->ui_manager) {
173                 g_object_unref (G_OBJECT(priv->ui_manager));
174                 priv->ui_manager = NULL;
175         }
176
177         priv->main_window = NULL;
178
179         G_OBJECT_CLASS(parent_class)->finalize (obj);
180 }
181
182
183 ModestUI*
184 modest_ui_new (void)
185 {
186         GObject *obj;
187         ModestUIPrivate *priv;
188
189         obj  = g_object_new(MODEST_TYPE_UI, NULL);
190         priv = MODEST_UI_GET_PRIVATE(obj);
191         
192         /* Register our own icons as stock icons in order to
193            use them with the UI manager */
194         register_stock_icons ();
195                 
196         return MODEST_UI(obj);
197 }
198
199 static gboolean
200 on_main_window_destroy (GtkObject *widget, ModestUI *self)
201 {
202         /* FIXME: check if there any viewer/editing windows opened */
203         gtk_main_quit ();
204         return FALSE;
205 }
206
207
208 ModestWindow *
209 modest_ui_main_window (ModestUI *self)
210 {
211         ModestUIPrivate *priv;
212
213         g_return_val_if_fail (self, NULL);
214         priv = MODEST_UI_GET_PRIVATE(self);
215
216         if (!priv->main_window) {
217                 priv->main_window = modest_main_window_new ();
218                 connect_signals (self);
219         }
220                 
221         if (!priv->main_window)
222                 g_printerr ("modest: could not create main window\n");
223         
224         return priv->main_window;
225 }
226
227 ModestWindow *
228 modest_ui_edit_window (ModestUI *self, ModestEditType edit_type)
229 {
230         ModestUIPrivate *priv;
231         ModestWindow *edit_window;
232
233         g_return_val_if_fail (self, NULL);
234         priv = MODEST_UI_GET_PRIVATE(self);
235
236         /* Create window */
237         edit_window = modest_edit_msg_window_new (edit_type);
238         
239         /* Connect Edit Window signals */
240 /*      connect_edit_window_signals (self); */
241                 
242         return edit_window;
243 }
244
245 /* 
246  *  This function registers our custom toolbar icons, so they can be
247  *  themed. The idea of this function was taken from the gtk-demo
248  */
249 static void
250 register_stock_icons ()
251 {
252         static gboolean registered = FALSE;
253   
254         if (!registered) {
255                 GdkPixbuf *pixbuf;
256                 GtkIconFactory *factory;
257                 gint i;
258
259                 static GtkStockItem items[] = {
260                         { MODEST_STOCK_MAIL_SEND, "send mail", 0, 0, NULL },
261                         { MODEST_STOCK_NEW_MAIL, "new mail", 0, 0, NULL },
262                         { MODEST_STOCK_SEND_RECEIVE, "send receive", 0, 0, NULL },
263                         { MODEST_STOCK_REPLY, "reply", 0, 0, NULL },
264                         { MODEST_STOCK_REPLY_ALL, "reply all", 0, 0, NULL },
265                         { MODEST_STOCK_FORWARD, "forward", 0, 0, NULL },
266                         { MODEST_STOCK_DELETE, "delete", 0, 0, NULL },
267                         { MODEST_STOCK_NEXT, "next", 0, 0, NULL },
268                         { MODEST_STOCK_PREV, "prev", 0, 0, NULL },
269 /*                      { MODEST_STOCK_STOP, "stop", 0, 0, NULL } */
270                 };
271       
272                 static gchar *items_names [] = {
273                         MODEST_TOOLBAR_ICON_MAIL_SEND,
274                         MODEST_TOOLBAR_ICON_NEW_MAIL,           
275                         MODEST_TOOLBAR_ICON_SEND_RECEIVE,
276                         MODEST_TOOLBAR_ICON_REPLY,      
277                         MODEST_TOOLBAR_ICON_REPLY_ALL,
278                         MODEST_TOOLBAR_ICON_FORWARD,
279                         MODEST_TOOLBAR_ICON_DELETE,
280                         MODEST_TOOLBAR_ICON_NEXT,
281                         MODEST_TOOLBAR_ICON_PREV,
282 /*                      MODEST_TOOLBAR_ICON_STOP */
283                 };
284
285                 registered = TRUE;
286
287                 /* Register our stock items */
288                 gtk_stock_add (items, G_N_ELEMENTS (items));
289       
290                 /* Add our custom icon factory to the list of defaults */
291                 factory = gtk_icon_factory_new ();
292                 gtk_icon_factory_add_default (factory);
293
294                 /* Register icons to accompany stock items */
295                 for (i = 0; i < G_N_ELEMENTS (items); i++) {
296                         pixbuf = NULL;
297                         pixbuf = gdk_pixbuf_new_from_file (items_names[i], NULL);
298
299                         if (pixbuf != NULL) {
300                                 GtkIconSet *icon_set;
301                                 GdkPixbuf *transparent;
302
303                                 transparent = gdk_pixbuf_add_alpha (pixbuf, TRUE, 0xff, 0xff, 0xff);
304
305                                 icon_set = gtk_icon_set_new_from_pixbuf (transparent);
306                                 gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
307                                 gtk_icon_set_unref (icon_set);
308                                 g_object_unref (pixbuf);
309                                 g_object_unref (transparent);
310                         }
311                         else
312                                 g_warning ("failed to load %s icon", items_names[i]);
313                 }
314                 /* Drop our reference to the factory, GTK will hold a reference. */
315                 g_object_unref (factory);
316         }
317 }
318
319 /* FIXME: uninit these as well */
320 static void
321 connect_signals (ModestUI *self)
322 {
323         TnyDevice *device;
324         TnyAccountStore *account_store;
325         ModestUIPrivate *priv;
326         ModestFolderView *folder_view;
327         ModestHeaderView *header_view;
328         ModestMsgView *msg_view;
329         GtkWidget *toggle;
330         ModestWidgetFactory *widget_factory;
331         
332         priv = MODEST_UI_GET_PRIVATE(self);
333
334         widget_factory = modest_runtime_get_widget_factory (); 
335         
336         folder_view   = modest_widget_factory_get_folder_view (widget_factory);
337         header_view   = modest_widget_factory_get_header_view (widget_factory);
338         msg_view      = modest_widget_factory_get_msg_preview (widget_factory);
339         toggle        = modest_widget_factory_get_online_toggle (widget_factory);
340         account_store = TNY_ACCOUNT_STORE(modest_runtime_get_account_store());
341         device        = tny_account_store_get_device (account_store);
342
343         /* folder view */
344         g_signal_connect (G_OBJECT(folder_view), "folder_selection_changed",
345                           G_CALLBACK(_modest_ui_actions_on_folder_selection_changed),
346                           priv->main_window);
347         g_signal_connect (G_OBJECT(folder_view), "folder_moved",
348                           G_CALLBACK(_modest_ui_actions_on_folder_moved),
349                           NULL);
350
351         /* header view */
352         g_signal_connect (G_OBJECT(header_view), "status_update",
353                           G_CALLBACK(_modest_ui_actions_on_header_status_update), 
354                           priv->main_window);
355         g_signal_connect (G_OBJECT(header_view), "header_selected",
356                           G_CALLBACK(_modest_ui_actions_on_header_selected), 
357                           priv->main_window);
358         g_signal_connect (G_OBJECT(header_view), "header_activated",
359                           G_CALLBACK(_modest_ui_actions_on_header_activated), 
360                           priv->main_window);
361         g_signal_connect (G_OBJECT(header_view), "item_not_found",
362                           G_CALLBACK(_modest_ui_actions_on_item_not_found), 
363                           priv->main_window);
364         /* msg preview */
365         g_signal_connect (G_OBJECT(msg_view), "link_clicked",
366                           G_CALLBACK(_modest_ui_actions_on_msg_link_clicked), 
367                           priv->main_window);
368         g_signal_connect (G_OBJECT(msg_view), "link_hover",
369                           G_CALLBACK(_modest_ui_actions_on_msg_link_hover), 
370                           priv->main_window);
371         g_signal_connect (G_OBJECT(msg_view), "attachment_clicked",
372                           G_CALLBACK(_modest_ui_actions_on_msg_attachment_clicked), 
373                           priv->main_window);
374
375         /* Account store */
376         g_signal_connect (G_OBJECT (account_store), "accounts_reloaded",
377                           G_CALLBACK (_modest_ui_actions_on_accounts_reloaded),
378                           priv->main_window);
379
380         /* Device */
381         g_signal_connect (G_OBJECT(device), "connection_changed",
382                           G_CALLBACK(_modest_ui_actions_on_connection_changed), 
383                           self);
384
385         priv->toggle_button_signal=
386                 g_signal_connect (G_OBJECT(toggle), "toggled",
387                                   G_CALLBACK(_modest_ui_actions_on_online_toggle_toggled),
388                                   priv->main_window);
389                 
390         /* Destroy window */
391         g_signal_connect (G_OBJECT(priv->main_window), 
392                           "destroy",
393                           G_CALLBACK(on_main_window_destroy), 
394                           NULL);
395
396         /* Init toggle in correct state */
397         _modest_ui_actions_on_connection_changed (device,
398                                                  tny_device_is_online (device),
399                                                  self);
400 }
401
402
403 /* ***************************************************************** */
404 /*                M O D E S T    U I    A C T I O N S                */
405 /* ***************************************************************** */
406 void   
407 _modest_ui_actions_on_about (GtkWidget *widget, 
408                              ModestMainWindow *main_window)
409 {
410         GtkWidget *about;
411         const gchar *authors[] = {
412                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
413                 NULL
414         };
415         about = gtk_about_dialog_new ();
416         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
417         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
418         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
419                                         _("Copyright (c) 2006, Nokia Corporation\n"
420                                           "All rights reserved."));
421         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
422                                        _("a modest e-mail client\n\n"
423                                          "design and implementation: Dirk-Jan C. Binnema\n"
424                                          "contributions from the fine people at KernelConcepts and Igalia\n"
425                                          "uses the tinymail email framework written by Philip van Hoof"));
426         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
427         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
428
429         gtk_dialog_run (GTK_DIALOG (about));
430         gtk_widget_destroy(about);
431 }
432
433 void
434 _modest_ui_actions_on_delete (GtkWidget *widget, 
435                              ModestMainWindow *main_window)
436 {
437         ModestWidgetFactory *widget_factory;
438         ModestHeaderView *header_view;
439         TnyList *header_list;
440         TnyIterator *iter;
441         GtkTreeModel *model;
442
443         widget_factory = modest_runtime_get_widget_factory ();
444         header_view = modest_widget_factory_get_header_view (widget_factory);
445         header_list = modest_header_view_get_selected_headers (header_view);
446         
447         if (header_list) {
448                 iter = tny_list_create_iterator (header_list);
449                 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
450                 if (GTK_IS_TREE_MODEL_SORT (model))
451                         model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
452                 do {
453                         TnyHeader *header;
454                         ModestMailOperation *mail_op;
455
456                         header = TNY_HEADER (tny_iterator_get_current (iter));
457                         /* TODO: thick grain mail operation involving
458                            a list of objects. Composite pattern ??? */
459                         mail_op = modest_mail_operation_new ();
460
461                         /* TODO: add confirmation dialog */
462
463                         /* Move to trash */
464                         modest_mail_operation_remove_msg (mail_op, header, TRUE);
465
466                         /* Remove from tree model */
467                         if (modest_mail_operation_get_status (mail_op) == 
468                             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
469                                 tny_list_remove (TNY_LIST (model), G_OBJECT (header));
470                         else {
471                                 /* TODO: error handling management */
472                                 const GError *error;
473                                 error = modest_mail_operation_get_error (mail_op);
474                                 g_warning (error->message);
475                         }
476
477                         g_object_unref (G_OBJECT (mail_op));
478                         g_object_unref (header);
479                         tny_iterator_next (iter);
480
481                 } while (!tny_iterator_is_done (iter));
482         }
483 }
484
485 void
486 _modest_ui_actions_on_quit (GtkWidget *widget, 
487                            ModestMainWindow *main_window)
488 {
489         /* FIXME: save size of main window */
490 /*      save_sizes (main_window); */
491         gtk_widget_destroy (GTK_WIDGET (main_window));
492 }
493
494 void
495 _modest_ui_actions_on_accounts (GtkWidget *widget, 
496                                 ModestMainWindow *main_window)
497 {
498         GtkWidget *account_win;
499         account_win = modest_account_view_window_new (modest_runtime_get_widget_factory());
500
501         gtk_window_set_transient_for (GTK_WINDOW (account_win),
502                                       GTK_WINDOW (main_window));
503                                       
504         gtk_widget_show (account_win);
505 }
506
507 void
508 _modest_ui_actions_on_new_msg (GtkWidget *widget, 
509                                ModestMainWindow *main_window)
510 {
511         ModestWindow *msg_win;
512         msg_win = modest_edit_msg_window_new (MODEST_EDIT_TYPE_NEW);
513         gtk_widget_show_all (GTK_WIDGET (msg_win));
514 }
515
516
517 void
518 _modest_ui_actions_on_open (GtkWidget *widget,
519                             ModestMainWindow *main_window)
520 {
521         /* FIXME */
522         
523 }
524
525
526 static void
527 reply_forward_func (gpointer data, gpointer user_data)
528 {
529         TnyMsg *msg, *new_msg;
530         GetMsgAsyncHelper *helper;
531         ReplyForwardHelper *rf_helper;
532         ModestWindow *msg_win;
533         ModestEditType edit_type;
534
535         msg = TNY_MSG (data);
536         helper = (GetMsgAsyncHelper *) user_data;
537         rf_helper = (ReplyForwardHelper *) helper->user_data;
538
539         /* Create reply mail */
540         switch (rf_helper->action) {
541         case ACTION_REPLY:
542                 new_msg = 
543                         modest_mail_operation_create_reply_mail (msg, 
544                                                                  rf_helper->from, 
545                                                                  rf_helper->reply_forward_type,
546                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
547                 break;
548         case ACTION_REPLY_TO_ALL:
549                 new_msg = 
550                         modest_mail_operation_create_reply_mail (msg, rf_helper->from, rf_helper->reply_forward_type,
551                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
552                 edit_type = MODEST_EDIT_TYPE_REPLY;
553                 break;
554         case ACTION_FORWARD:
555                 new_msg = 
556                         modest_mail_operation_create_forward_mail (msg, rf_helper->from, rf_helper->reply_forward_type);
557                 edit_type = MODEST_EDIT_TYPE_FORWARD;
558                 break;
559         default:
560                 g_return_if_reached ();
561         }
562
563         if (!new_msg) {
564                 g_warning ("Unable to create a message");
565                 goto cleanup;
566         }
567                 
568         /* Show edit window */
569         msg_win = modest_edit_msg_window_new (MODEST_EDIT_TYPE_NEW);
570         modest_edit_msg_window_set_msg (MODEST_EDIT_MSG_WINDOW (msg_win),
571                                         new_msg);
572         gtk_widget_show_all (GTK_WIDGET (msg_win));
573         
574         /* Clean */
575         g_object_unref (G_OBJECT (new_msg));
576
577  cleanup:
578         g_free (rf_helper->from);
579         g_slice_free (ReplyForwardHelper, rf_helper);
580 }
581
582 /*
583  * Common code for the reply and forward actions
584  */
585 static void
586 reply_forward (GtkWidget *widget,
587                ReplyForwardAction action,
588                ModestMainWindow *main_window)
589 {
590         ModestHeaderView *header_view;
591         ModestAccountMgr *account_mgr;
592         TnyList *header_list;
593         guint reply_forward_type;
594         ModestConf *conf;       
595         ModestAccountData *default_account_data;
596         TnyHeader *header;
597         TnyFolder *folder;
598         gchar *from, *key, *default_account_name;
599         GetMsgAsyncHelper *helper;
600         ReplyForwardHelper *rf_helper;
601
602         conf = modest_runtime_get_conf ();
603         
604         /* Get reply or forward type */
605         key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE, 
606                                (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE);
607         reply_forward_type = modest_conf_get_int (conf, key, NULL);
608         g_free (key);
609
610         /* Get the list of headers */
611         header_view = modest_widget_factory_get_header_view (modest_runtime_get_widget_factory());
612         header_list = modest_header_view_get_selected_headers (header_view);    
613         if (!header_list)
614                 return;
615
616         /* We assume that we can only select messages of the
617            same folder and that we reply all of them from the
618            same account. In fact the interface currently only
619            allows single selection */
620         account_mgr = modest_runtime_get_account_mgr();
621         default_account_name = modest_account_mgr_get_default_account (account_mgr);
622         default_account_data = 
623                 modest_account_mgr_get_account_data (account_mgr,
624                                                      (const gchar*) default_account_name);
625         from = g_strdup (default_account_data->email);
626         modest_account_mgr_free_account_data (account_mgr, default_account_data);
627         g_free (default_account_name);
628         
629         /* Fill helpers */
630         rf_helper = g_slice_new0 (ReplyForwardHelper);
631         rf_helper->reply_forward_type = reply_forward_type;
632         rf_helper->action = action;
633         rf_helper->from = from;
634         
635         helper = g_slice_new0 (GetMsgAsyncHelper);
636         helper->main_window = main_window;
637         helper->func = reply_forward_func;
638         helper->iter = tny_list_create_iterator (header_list);
639         helper->user_data = rf_helper;
640         
641         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
642         folder = tny_header_get_folder (header);
643         
644         /* The callback will call it per each header */
645         tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
646         
647         /* Clean */
648         g_object_unref (G_OBJECT (header));
649         g_object_unref (G_OBJECT (folder));
650 }
651
652 void
653 _modest_ui_actions_on_reply (GtkWidget *widget,
654                             ModestMainWindow *main_window)
655 {
656         reply_forward (widget, ACTION_REPLY, main_window);
657 }
658
659 void
660 _modest_ui_actions_on_forward (GtkWidget *widget,
661                               ModestMainWindow *main_window)
662 {
663         reply_forward (widget, ACTION_FORWARD, main_window);
664 }
665
666 void
667 _modest_ui_actions_on_reply_all (GtkWidget *widget,
668                                 ModestMainWindow *main_window)
669 {
670         reply_forward (widget, ACTION_REPLY_TO_ALL, main_window);
671 }
672
673 void 
674 _modest_ui_actions_on_next (GtkWidget *widget, 
675                            ModestMainWindow *main_window)
676 {
677         ModestHeaderView *header_view;
678
679         header_view = modest_widget_factory_get_header_view
680                 (modest_runtime_get_widget_factory());
681
682         modest_header_view_select_next (header_view);
683 }
684
685 void
686 _modest_ui_actions_toggle_view (GtkWidget *widget,
687                                 ModestMainWindow *main_window)
688 {
689         ModestConf *conf;
690         ModestHeaderView *header_view;
691
692         header_view = modest_widget_factory_get_header_view
693                 (modest_runtime_get_widget_factory());
694
695         conf = modest_runtime_get_conf ();
696         
697         /* what is saved/restored is depending on the style; thus; we save with
698          * old style, then update the style, and restore for this new style*/
699         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
700         
701         if (modest_header_view_get_style (header_view) == MODEST_HEADER_VIEW_STYLE_DETAILS)
702                 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
703         else
704                 modest_header_view_set_style (header_view, MODEST_HEADER_VIEW_STYLE_DETAILS);
705
706         modest_widget_memory_restore (conf, G_OBJECT(header_view), "header-view");
707 }
708
709
710
711 /*
712  * Marks a message as read and passes it to the msg preview widget
713  */
714 static void
715 read_msg_func (gpointer data, gpointer user_data)
716 {
717         ModestMsgView *msg_view;
718         TnyMsg *msg;
719         TnyHeader *header;
720         GetMsgAsyncHelper *helper;
721         TnyHeaderFlags header_flags;
722
723         msg = TNY_MSG (data);
724         helper = (GetMsgAsyncHelper *) user_data;
725
726         /* mark message as seen; _set_flags crashes, bug in tinymail? */
727         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
728         header_flags = tny_header_get_flags (header);
729         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
730         g_object_unref (G_OBJECT (header));
731
732         /* Set message on msg view */
733         msg_view = modest_widget_factory_get_msg_preview
734                 (modest_runtime_get_widget_factory());
735         modest_msg_view_set_message (msg_view, msg);
736 }
737
738 /*
739  * This function is a generic handler for the tny_folder_get_msg_async
740  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
741  * contains a user provided function that is called inside this
742  * method. This will allow us to use this callback in many different
743  * places. This callback performs the common actions for the
744  * get_msg_async call, more specific actions will be done by the user
745  * function
746  */
747 static void
748 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
749 {
750         GetMsgAsyncHelper *helper;
751
752         helper = (GetMsgAsyncHelper *) user_data;
753
754         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
755                 ModestHeaderView *header_view;
756                 header_view = modest_widget_factory_get_header_view
757                         (modest_runtime_get_widget_factory());
758                 _modest_ui_actions_on_item_not_found (header_view,
759                                                       MODEST_ITEM_TYPE_MESSAGE,
760                                                       helper->main_window);
761                 return;
762         }
763
764         /* Call user function */
765         helper->func (msg, user_data);
766
767         /* Process next element (if exists) */
768         tny_iterator_next (helper->iter);
769         if (tny_iterator_is_done (helper->iter)) {
770                 TnyList *headers;
771                 headers = tny_iterator_get_list (helper->iter);
772                 /* Free resources */
773                 g_object_unref (G_OBJECT (headers));
774                 g_object_unref (G_OBJECT (helper->iter));
775                 g_slice_free (GetMsgAsyncHelper, helper);
776         } else {
777                 TnyHeader *header;
778                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
779                 tny_folder_get_msg_async (folder, header,                         
780                                           get_msg_cb, helper);
781                 g_object_unref (G_OBJECT(header));
782         }
783 }
784
785 void 
786 _modest_ui_actions_on_header_selected (ModestHeaderView *folder_view, 
787                                       TnyHeader *header,
788                                       ModestMainWindow *main_window)
789 {
790         TnyFolder *folder;
791         GetMsgAsyncHelper *helper;
792         TnyList *list;
793
794         /* when there's no header, clear the msgview */
795         if (!header) {
796                 ModestMsgView *msg_view;
797                 msg_view       = modest_widget_factory_get_msg_preview
798                         (modest_runtime_get_widget_factory());
799                 modest_msg_view_set_message (msg_view, NULL);
800                 return;
801         }
802
803         folder = tny_header_get_folder (TNY_HEADER(header));
804
805         /* Create list */
806         list = tny_simple_list_new ();
807         tny_list_prepend (list, G_OBJECT (header));
808
809         /* Fill helper data */
810         helper = g_slice_new0 (GetMsgAsyncHelper);
811         helper->main_window = main_window;
812         helper->iter = tny_list_create_iterator (list);
813         helper->func = read_msg_func;
814
815         tny_folder_get_msg_async (TNY_FOLDER(folder),
816                                   header, get_msg_cb,
817                                   helper);
818
819         /* Frees */
820         g_object_unref (G_OBJECT (folder));
821 }
822
823
824
825 void 
826 _modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, 
827                                         TnyHeader *header,
828                                         ModestMainWindow *main_window)
829 {
830         ModestWindow *win;
831         TnyFolder *folder = NULL;
832         TnyMsg    *msg    = NULL;
833         
834         if (!header)
835                 return;
836
837         folder = tny_header_get_folder (header);
838         if (!folder) {
839                 g_printerr ("modest: cannot get folder for header\n");
840                 goto cleanup;
841         }
842
843         /* FIXME: make async?; check error  */
844         msg = tny_folder_get_msg (folder, header, NULL);
845         if (!msg) {
846                 g_printerr ("modest: cannot get msg for header\n");
847                 goto cleanup;
848         }
849
850         win = modest_msg_view_window_new (msg);
851         gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (main_window));
852
853         gtk_widget_show_all (GTK_WIDGET(win));
854         
855 cleanup:
856         if (folder)
857                 g_object_unref (G_OBJECT (folder));
858         if (msg)
859                 g_object_unref (G_OBJECT (folder));
860 }
861
862
863
864
865
866 void 
867 _modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
868                                                TnyFolder *folder, 
869                                                gboolean selected,
870                                                ModestMainWindow *main_window)
871 {
872         GtkLabel *folder_info_label;
873         gchar *txt;     
874         ModestConf *conf;
875         ModestHeaderView *header_view;
876
877         folder_info_label = 
878                 GTK_LABEL (modest_widget_factory_get_folder_info_label
879                            (modest_runtime_get_widget_factory()));
880
881         if (!folder) {
882                 gtk_label_set_label (GTK_LABEL(folder_info_label), "");
883                 return;
884         }
885         
886         header_view = modest_widget_factory_get_header_view (modest_runtime_get_widget_factory());
887         conf = modest_runtime_get_conf ();
888
889         if (!selected) { /* the folder was unselected; save it's settings  */
890                 modest_widget_memory_save (conf, G_OBJECT (header_view),
891                                            "header-view");
892                 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
893                 modest_header_view_set_folder (header_view, NULL);
894         } else {  /* the folder was selected */
895                 if (folder) { /* folder may be NULL */
896                         guint num, unread;
897                         gchar *title;
898
899                         num    = tny_folder_get_all_count    (folder);
900                         unread = tny_folder_get_unread_count (folder);
901                         
902                         title = g_strdup_printf ("Modest: %s",
903                                                  tny_folder_get_name (folder));
904                         
905                         gtk_window_set_title (GTK_WINDOW(main_window), title);
906                         g_free (title);
907                         
908                         txt = g_strdup_printf (_("%d %s, %d unread"),
909                                        num, num==1 ? _("item") : _("items"), unread);           
910                         gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
911                         g_free (txt);
912                 }
913                 modest_header_view_set_folder (header_view, folder);
914                 modest_widget_memory_restore (conf, G_OBJECT(header_view),
915                                               "header-view");
916         }
917 }
918
919
920 /****************************************************/
921 /*
922  * below some stuff to clearup statusbar messages after 1,5 seconds....
923  */
924 static gboolean
925 progress_bar_clean (GtkWidget *bar)
926 {
927         if (GTK_IS_PROGRESS_BAR(bar)) {
928                 gtk_progress_bar_set_text     (GTK_PROGRESS_BAR(bar), "");
929                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
930         }
931         return FALSE;
932 }
933
934 static gboolean
935 statusbar_clean (GtkWidget *bar)
936 {
937         if (GTK_IS_STATUSBAR(bar))
938                 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
939         return FALSE;
940 }
941
942
943 static void
944 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
945 {
946         GtkWidget *status_bar, *progress_bar;
947         
948         if (!msg)
949                 return;
950
951         progress_bar = modest_widget_factory_get_progress_bar (factory);
952         status_bar   = modest_widget_factory_get_status_bar (factory);
953
954         gtk_widget_show (GTK_WIDGET(status_bar));
955         gtk_widget_show (GTK_WIDGET(progress_bar));
956
957         gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
958
959         g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
960         g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
961 }
962 /****************************************************************************/
963
964 static void
965 _modest_ui_actions_on_connection_changed (TnyDevice *device, 
966                                           gboolean online,
967                                           ModestUI *self)
968 {
969         GtkWidget *online_toggle;
970         ModestHeaderView *header_view;
971         ModestWidgetFactory *widget_factory;
972         ModestUIPrivate *priv;
973         GtkWidget *icon;
974         const gchar *icon_name;
975
976         g_return_if_fail (device);
977         g_return_if_fail (self);
978
979         priv = MODEST_UI_GET_PRIVATE (self);
980
981         icon_name = online ? GTK_STOCK_CONNECT : GTK_STOCK_DISCONNECT;
982         icon      = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
983
984         widget_factory = modest_runtime_get_widget_factory ();
985         header_view   = modest_widget_factory_get_header_view (widget_factory);
986         online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
987
988         /* Block handlers in order to avoid unnecessary calls */
989         g_signal_handler_block (G_OBJECT (online_toggle), priv->toggle_button_signal);
990         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle), online);
991         g_signal_handler_unblock (G_OBJECT (online_toggle), priv->toggle_button_signal);
992
993         gtk_button_set_image (GTK_BUTTON(online_toggle), icon);
994         statusbar_push (widget_factory, 0, 
995                         online ? _("Modest went online") : _("Modest went offline"));
996         
997         /* If Modest has became online and the header view has a
998            header selected then show it */
999         /* FIXME: there is a race condition if some account needs to
1000            ask the user for a password */
1001
1002 /*      if (online) { */
1003 /*              GtkTreeSelection *selected; */
1004
1005 /*              selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view)); */
1006 /*              _modest_header_view_change_selection (selected, header_view); */
1007 /*      } */
1008 }
1009
1010 void
1011 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
1012                                              ModestMainWindow *main_window)
1013 {
1014         gboolean online;
1015         TnyDevice *device;
1016
1017         device = tny_account_store_get_device
1018                 (TNY_ACCOUNT_STORE(modest_runtime_get_account_store()));
1019
1020         online  = gtk_toggle_button_get_active (toggle);
1021
1022         if (online)
1023                 tny_device_force_online (device);
1024         else
1025                 tny_device_force_offline (device);
1026
1027         g_object_unref (G_OBJECT (device));
1028 }
1029
1030 void 
1031 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
1032                                      ModestItemType type,
1033                                      ModestMainWindow *main_window)
1034 {
1035         GtkWidget *dialog;
1036         gchar *txt, *item;
1037         gboolean online;
1038         TnyDevice *device;
1039         TnyAccountStore *account_store;
1040
1041         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1042
1043         /* Get device. Do not ask the platform factory for it, because
1044            it returns always a new one */
1045         account_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store ());
1046         device = tny_account_store_get_device (account_store);
1047
1048         if (g_main_depth > 0)   
1049                 gdk_threads_enter ();
1050         online = tny_device_is_online (device);
1051
1052         if (online) {
1053                 /* already online -- the item is simply not there... */
1054                 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
1055                                                  GTK_DIALOG_MODAL,
1056                                                  GTK_MESSAGE_WARNING,
1057                                                  GTK_BUTTONS_OK,
1058                                                  _("The %s you selected cannot be found"),
1059                                                  item);
1060                 gtk_dialog_run (GTK_DIALOG(dialog));
1061         } else {
1062
1063                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1064                                                       GTK_WINDOW (main_window),
1065                                                       GTK_DIALOG_MODAL,
1066                                                       GTK_STOCK_CANCEL,
1067                                                       GTK_RESPONSE_REJECT,
1068                                                       GTK_STOCK_OK,
1069                                                       GTK_RESPONSE_ACCEPT,
1070                                                       NULL);
1071
1072                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1073                                          "Do you want to get online?"), item);
1074                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1075                                     gtk_label_new (txt), FALSE, FALSE, 0);
1076                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1077                 g_free (txt);
1078
1079                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1080                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1081                         tny_device_force_online (device);
1082                 }
1083         }
1084         gtk_widget_destroy (dialog);
1085         if (g_main_depth > 0)   
1086                 gdk_threads_leave ();
1087 }
1088
1089
1090
1091 void
1092 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view, 
1093                                             const gchar *msg,
1094                                             gint num, 
1095                                             gint total, 
1096                                             ModestMainWindow *main_window)
1097 {
1098         GtkWidget *progress_bar;
1099         char* txt;
1100         
1101         progress_bar = modest_widget_factory_get_progress_bar
1102                 (modest_runtime_get_widget_factory());
1103         if (total != 0)
1104                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1105                                                (gdouble)num/(gdouble)total);
1106         else
1107                 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1108
1109         txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1110         gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1111         g_free (txt);
1112         
1113         statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1114 }
1115
1116
1117
1118 void
1119 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, 
1120                                       const gchar* link,
1121                                       ModestMainWindow *main_window)
1122 {
1123         statusbar_push (modest_runtime_get_widget_factory(), 0, link);
1124
1125         /* TODO: do something */
1126 }       
1127
1128
1129 void
1130 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, 
1131                                         const gchar* link,
1132                                         ModestMainWindow *main_window)
1133 {
1134         gchar *msg;
1135
1136         msg = g_strdup_printf (_("Opening %s..."), link);
1137         statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1138         g_free (msg);
1139
1140         /* TODO: do something */
1141 }
1142
1143 void
1144 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, 
1145                                               int index,
1146                                               ModestMainWindow *main_window)
1147 {
1148         gchar *msg;
1149         
1150         msg = g_strdup_printf (_("Opening attachment %d..."), index);
1151         statusbar_push (modest_runtime_get_widget_factory(), 0, msg);
1152         
1153         g_free (msg);
1154         /* TODO: do something */
1155 }
1156
1157 void
1158 _modest_ui_actions_on_send (GtkWidget *widget, 
1159                             ModestEditMsgWindow *edit_window)
1160 {
1161         TnyTransportAccount *transport_account;
1162         ModestMailOperation *mail_operation;
1163         MsgData *data;
1164         gchar *account_name, *from;
1165         ModestAccountMgr *account_mgr;
1166         
1167         
1168         data = modest_edit_msg_window_get_msg_data (edit_window);
1169
1170         /* FIXME: Code added just for testing. The final version will
1171            use the send queue provided by tinymail and some
1172            classifier */
1173         account_mgr = modest_runtime_get_account_mgr();
1174         account_name = modest_account_mgr_get_default_account (account_mgr);
1175         if (!account_name) {
1176                 g_printerr ("modest: no default account found\n");
1177                 modest_edit_msg_window_free_msg_data (edit_window, data);
1178                 return;
1179         }
1180         transport_account =
1181                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1182                                       (modest_runtime_get_account_store(),
1183                                        account_name,
1184                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1185         if (!transport_account) {
1186                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1187                 g_free (account_name);
1188                 modest_edit_msg_window_free_msg_data (edit_window, data);
1189                 return;
1190         }
1191         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1192                 
1193         mail_operation = modest_mail_operation_new ();
1194         modest_mail_operation_send_new_mail (mail_operation,
1195                                              transport_account,
1196                                              from,
1197                                              data->to, 
1198                                              data->cc, 
1199                                              data->bcc,
1200                                              data->subject, 
1201                                              data->body, 
1202                                              NULL);
1203         /* Frees */
1204         g_free (from);
1205         g_free (account_name);
1206         g_object_unref (G_OBJECT (mail_operation));
1207         g_object_unref (G_OBJECT (transport_account));
1208
1209         modest_edit_msg_window_free_msg_data (edit_window, data);
1210
1211         /* Save settings and close the window */
1212         /* save_settings (edit_window) */
1213         gtk_widget_destroy (GTK_WIDGET (edit_window));
1214 }
1215
1216 /*
1217  * Shows a dialog with an entry that asks for some text. The returned
1218  * value must be freed by the caller. The dialog window title will be
1219  * set to @title.
1220  */
1221 static gchar *
1222 ask_for_folder_name (GtkWindow *parent_window,
1223                      const gchar *title)
1224 {
1225         GtkWidget *dialog, *entry;
1226         gchar *folder_name = NULL;
1227
1228         /* Ask for folder name */
1229         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1230                                               parent_window,
1231                                               GTK_DIALOG_MODAL,
1232                                               GTK_STOCK_CANCEL,
1233                                               GTK_RESPONSE_REJECT,
1234                                               GTK_STOCK_OK,
1235                                               GTK_RESPONSE_ACCEPT,
1236                                               NULL);
1237         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1238                             gtk_label_new(title),
1239                             FALSE, FALSE, 0);
1240                 
1241         entry = gtk_entry_new_with_max_length (40);
1242         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1243                             entry,
1244                             TRUE, FALSE, 0);    
1245         
1246         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1247         
1248         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1249                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1250
1251         gtk_widget_destroy (dialog);
1252
1253         return folder_name;
1254 }
1255         
1256 void 
1257 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1258                                   ModestMainWindow *main_window)
1259 {
1260         TnyFolder *parent_folder;
1261         ModestFolderView *folder_view;
1262
1263         folder_view = modest_widget_factory_get_folder_view
1264                 (modest_runtime_get_widget_factory());
1265         parent_folder = modest_folder_view_get_selected (folder_view);
1266         
1267         if (parent_folder) {
1268                 gchar *folder_name;
1269
1270                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1271                                                    _("Please enter a name for the new folder"));
1272
1273                 if (folder_name != NULL && strlen (folder_name) > 0) {
1274                         TnyFolder *new_folder;
1275                         ModestMailOperation *mail_op;
1276
1277                         mail_op = modest_mail_operation_new ();
1278                         new_folder = modest_mail_operation_create_folder (mail_op,
1279                                                                           TNY_FOLDER_STORE (parent_folder),
1280                                                                           (const gchar *) folder_name);
1281                         if (new_folder) {
1282                                 /* TODO: tinymail should do this. 
1283                                    Update view */
1284                                 modest_folder_view_add_subfolder (folder_view, new_folder);
1285
1286                                 /* Free new folder */
1287                                 g_object_unref (new_folder);
1288                         }
1289                         g_object_unref (mail_op);
1290                 }
1291                 g_object_unref (parent_folder);
1292         }
1293 }
1294
1295 void 
1296 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1297                                      ModestMainWindow *main_window)
1298 {
1299         TnyFolder *folder;
1300         ModestFolderView *folder_view;
1301         
1302         folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1303         folder = modest_folder_view_get_selected (folder_view);
1304
1305         if (folder) {
1306                 gchar *folder_name;
1307
1308                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1309                                                    _("Please enter a new name for the folder"));
1310
1311                 if (folder_name != NULL && strlen (folder_name) > 0) {
1312                         ModestMailOperation *mail_op;
1313                         const GError *error;
1314
1315                         mail_op = modest_mail_operation_new ();
1316                         modest_mail_operation_rename_folder (mail_op,
1317                                                              folder,
1318                                                              (const gchar *) folder_name);
1319
1320                         error = modest_mail_operation_get_error (mail_op);
1321                         if (!error)
1322                                 /* TODO: tinymail should do this. 
1323                                    Update view */
1324                                 modest_folder_view_rename (folder_view);
1325
1326                         /* TODO: else ? notify error ? */
1327
1328                         g_object_unref (mail_op);
1329                 }
1330                 g_object_unref (folder);
1331         }
1332 }
1333
1334 static void
1335 delete_folder (ModestMainWindow *main_window,
1336                gboolean move_to_trash) 
1337 {
1338         TnyFolder *folder;
1339         ModestFolderView *folder_view;
1340         ModestMailOperation *mail_op;
1341         
1342         folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1343         folder = modest_folder_view_get_selected (folder_view);
1344
1345         mail_op = modest_mail_operation_new ();
1346         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1347         g_object_unref (mail_op);
1348 }
1349
1350 void 
1351 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1352                                      ModestMainWindow *main_window)
1353 {
1354         delete_folder (main_window, FALSE);
1355 }
1356
1357 void 
1358 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1359                                             ModestMainWindow *main_window)
1360 {
1361         delete_folder (main_window, TRUE);
1362 }
1363
1364 static void
1365 _modest_ui_actions_on_accounts_reloaded (TnyAccountStore *store, gpointer user_data)
1366 {
1367         ModestFolderView *folder_view;
1368         
1369         folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory());
1370         modest_folder_view_update_model (folder_view, store);
1371 }
1372
1373 static void 
1374 _modest_ui_actions_on_folder_moved (ModestFolderView *folder_view,
1375                                     TnyFolder        *folder, 
1376                                     TnyFolderStore   *parent,
1377                                     gboolean         *done,
1378                                     gpointer          user_data)
1379 {
1380         ModestMailOperation *mail_op;
1381         const GError *error;
1382
1383         *done = TRUE;
1384
1385         /* Try to move the folder */    
1386         mail_op = modest_mail_operation_new ();
1387         modest_mail_operation_move_folder (mail_op, folder, parent);
1388
1389         error = modest_mail_operation_get_error (mail_op);
1390         if (error)
1391                 *done = FALSE;
1392
1393         g_object_unref (G_OBJECT (mail_op));
1394 }