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