* Added a missing break
[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 static gboolean
913 progress_bar_clean (GtkWidget *bar)
914 {
915         if (GTK_IS_PROGRESS_BAR(bar)) {
916                 gtk_progress_bar_set_text     (GTK_PROGRESS_BAR(bar), "");
917                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
918         }
919         return FALSE;
920 }
921 static gboolean
922 statusbar_clean (GtkWidget *bar)
923 {
924         if (GTK_IS_STATUSBAR(bar))
925                 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
926         return FALSE;
927 }
928
929
930 static void
931 statusbar_push (ModestWidgetFactory *factory, guint context_id, const gchar *msg)
932 {
933         GtkWidget *status_bar, *progress_bar;
934         
935         if (!msg)
936                 return;
937
938         progress_bar = modest_widget_factory_get_progress_bar (factory);
939         status_bar   = modest_widget_factory_get_status_bar (factory);
940
941         gtk_widget_show (GTK_WIDGET(status_bar));
942         gtk_widget_show (GTK_WIDGET(progress_bar));
943
944         gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
945
946         g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
947         g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
948 }
949 /****************************************************************************/
950
951 void
952 _modest_ui_actions_on_connection_changed (TnyDevice *device, 
953                                          gboolean online,
954                                          ModestMainWindow *main_window)
955 {
956         GtkWidget *online_toggle;
957         ModestHeaderView *header_view;
958         ModestWidgetFactory *widget_factory;
959         
960         widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
961         header_view   = modest_widget_factory_get_header_view (widget_factory);
962         online_toggle = modest_widget_factory_get_online_toggle (widget_factory);
963
964         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(online_toggle),
965                                       online);
966         gtk_button_set_label (GTK_BUTTON(online_toggle),
967                               online ? _("Online") : _("Offline"));
968
969         statusbar_push (widget_factory, 0, 
970                         online ? _("Modest went online") : _("Modest went offline"));
971         g_object_unref (G_OBJECT (widget_factory));
972
973         /* If Modest has became online and the header view has a
974            header selected then show it */
975         if (online) {
976                 GtkTreeSelection *selected;
977
978                 selected = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
979                 _modest_header_view_change_selection (selected, header_view);
980         }
981 }
982
983 void
984 _modest_ui_actions_on_online_toggle_toggled (GtkToggleButton *toggle,
985                                              ModestMainWindow *main_window)
986 {
987         gboolean online;
988         TnyDevice *device;
989         TnyPlatformFactory *factory;
990         TnyAccountStore *account_store;
991
992         /* Get device. Do not ask the platform factory for it, because
993            it returns always a new one */
994         factory = modest_tny_platform_factory_get_instance ();
995         account_store = tny_platform_factory_new_account_store (factory);
996         device = tny_account_store_get_device (account_store);
997
998         online  = gtk_toggle_button_get_active (toggle);
999
1000         if (online)
1001                 tny_device_force_online (device);
1002         else
1003                 tny_device_force_offline (device);
1004 }
1005
1006 void 
1007 _modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,
1008                                      ModestItemType type,
1009                                      ModestMainWindow *main_window)
1010 {
1011         GtkWidget *dialog;
1012         gchar *txt, *item;
1013         gboolean online;
1014         TnyDevice *device;
1015         TnyPlatformFactory *factory;
1016         TnyAccountStore *account_store;
1017
1018         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1019
1020         /* Get device. Do not ask the platform factory for it, because
1021            it returns always a new one */
1022         factory = modest_tny_platform_factory_get_instance ();
1023         account_store = tny_platform_factory_new_account_store (factory);
1024         device = tny_account_store_get_device (account_store);
1025
1026         if (g_main_depth > 0)   
1027                 gdk_threads_enter ();
1028         online = tny_device_is_online (device);
1029
1030         if (online) {
1031                 /* already online -- the item is simply not there... */
1032                 dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
1033                                                  GTK_DIALOG_MODAL,
1034                                                  GTK_MESSAGE_WARNING,
1035                                                  GTK_BUTTONS_OK,
1036                                                  _("The %s you selected cannot be found"),
1037                                                  item);
1038                 gtk_dialog_run (GTK_DIALOG(dialog));
1039         } else {
1040
1041                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1042                                                       GTK_WINDOW (main_window),
1043                                                       GTK_DIALOG_MODAL,
1044                                                       GTK_STOCK_CANCEL,
1045                                                       GTK_RESPONSE_REJECT,
1046                                                       GTK_STOCK_OK,
1047                                                       GTK_RESPONSE_ACCEPT,
1048                                                       NULL);
1049
1050                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1051                                          "Do you want to get online?"), item);
1052                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1053                                     gtk_label_new (txt), FALSE, FALSE, 0);
1054                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1055                 g_free (txt);
1056
1057                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1058                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1059                         tny_device_force_online (device);
1060                 }
1061         }
1062         gtk_widget_destroy (dialog);
1063         if (g_main_depth > 0)   
1064                 gdk_threads_leave ();
1065 }
1066
1067
1068
1069 void
1070 _modest_ui_actions_on_header_status_update (ModestHeaderView *header_view, 
1071                                             const gchar *msg,
1072                                             gint num, 
1073                                             gint total, 
1074                                             ModestMainWindow *main_window)
1075 {
1076         GtkWidget *progress_bar;
1077         ModestWidgetFactory *widget_factory;
1078         char* txt;
1079         
1080         widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1081         progress_bar = modest_widget_factory_get_progress_bar (widget_factory);
1082
1083         if (total != 0)
1084                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
1085                                                (gdouble)num/(gdouble)total);
1086         else
1087                 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
1088
1089         txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
1090         gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
1091         g_free (txt);
1092         
1093         statusbar_push (widget_factory, 0, msg);
1094         
1095         /* Free */
1096         g_object_unref (G_OBJECT (widget_factory));
1097 }
1098
1099
1100
1101 void
1102 _modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, 
1103                                       const gchar* link,
1104                                       ModestMainWindow *main_window)
1105 {
1106         ModestWidgetFactory *widget_factory;
1107
1108         widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1109         statusbar_push (widget_factory, 0, link);
1110         g_object_unref (G_OBJECT (widget_factory));     
1111
1112         /* TODO: do something */
1113 }       
1114
1115
1116 void
1117 _modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, 
1118                                         const gchar* link,
1119                                         ModestMainWindow *main_window)
1120 {
1121         gchar *msg;
1122         ModestWidgetFactory *widget_factory;
1123
1124         msg = g_strdup_printf (_("Opening %s..."), link);
1125         widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1126         statusbar_push (widget_factory, 0, msg);
1127
1128         g_object_unref (G_OBJECT (widget_factory));     
1129
1130         g_free (msg);
1131
1132         /* TODO: do something */
1133 }
1134
1135 void
1136 _modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, 
1137                                               int index,
1138                                               ModestMainWindow *main_window)
1139 {
1140         gchar *msg;
1141         ModestWidgetFactory *widget_factory;
1142         
1143         msg = g_strdup_printf (_("Opening attachment %d..."), index);
1144         widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1145         statusbar_push (widget_factory, 0, msg);
1146         
1147         g_free (msg);
1148         g_object_unref (G_OBJECT (widget_factory));
1149         /* TODO: do something */
1150 }
1151
1152 void
1153 _modest_ui_actions_on_send (GtkWidget *widget, 
1154                             ModestEditMsgWindow *edit_window)
1155 {
1156         TnyTransportAccount *transport_account;
1157         ModestMailOperation *mail_operation;
1158         MsgData *data;
1159
1160         data = modest_edit_msg_window_get_msg_data (edit_window);
1161
1162         /* FIXME: Code added just for testing. The final version will
1163            use the send queue provided by tinymail and some
1164            classifier */
1165         {
1166                 TnyList *accounts;
1167                 TnyIterator *iter;
1168                 TnyAccountStore *account_store;
1169
1170                 accounts = TNY_LIST(tny_simple_list_new ());
1171                 account_store = modest_window_get_account_store (MODEST_WINDOW (edit_window));
1172                 tny_account_store_get_accounts (account_store, accounts,
1173                                                 TNY_ACCOUNT_STORE_TRANSPORT_ACCOUNTS);
1174                 g_object_unref (G_OBJECT (account_store));
1175
1176                 iter = tny_list_create_iterator(accounts);
1177                 tny_iterator_first (iter);
1178                 if (tny_iterator_is_done (iter)) {
1179                         /* FIXME: Add error handling through mail operation */
1180                         g_printerr("modest: no transport accounts defined\n");
1181                         modest_edit_msg_window_free_msg_data (edit_window, data);
1182                         return;
1183                 }
1184                 transport_account = TNY_TRANSPORT_ACCOUNT (tny_iterator_get_current(iter));
1185                 g_object_ref (transport_account);
1186
1187                 tny_list_foreach (accounts, (GFunc) g_object_unref, NULL);
1188                 g_object_unref (G_OBJECT (accounts));
1189                 g_object_unref (G_OBJECT (iter));
1190         }
1191
1192         mail_operation = modest_mail_operation_new ();
1193
1194         modest_mail_operation_send_new_mail (mail_operation,
1195                                              transport_account,
1196                                              data->from, 
1197                                              data->to, 
1198                                              data->cc, 
1199                                              data->bcc,
1200                                              data->subject, 
1201                                              data->body, 
1202                                              NULL);
1203         /* Frees */
1204         g_object_unref (G_OBJECT (mail_operation));
1205         g_object_unref (G_OBJECT (transport_account));
1206         modest_edit_msg_window_free_msg_data (edit_window, data);
1207
1208         /* Save settings and close the window */
1209         /* save_settings (edit_window) */
1210         gtk_widget_destroy (GTK_WIDGET (edit_window));
1211 }
1212
1213 /*
1214  * Shows a dialog with an entry that asks for some text. The returned
1215  * value must be freed by the caller. The dialog window title will be
1216  * set to @title.
1217  */
1218 static gchar *
1219 ask_for_folder_name (GtkWindow *parent_window,
1220                      const gchar *title)
1221 {
1222         GtkWidget *dialog, *entry;
1223         gchar *folder_name = NULL;
1224
1225         /* Ask for folder name */
1226         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1227                                               parent_window,
1228                                               GTK_DIALOG_MODAL,
1229                                               GTK_STOCK_CANCEL,
1230                                               GTK_RESPONSE_REJECT,
1231                                               GTK_STOCK_OK,
1232                                               GTK_RESPONSE_ACCEPT,
1233                                               NULL);
1234         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1235                             gtk_label_new(title),
1236                             FALSE, FALSE, 0);
1237                 
1238         entry = gtk_entry_new_with_max_length (40);
1239         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1240                             entry,
1241                             TRUE, FALSE, 0);    
1242         
1243         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1244         
1245         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1246                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1247
1248         gtk_widget_destroy (dialog);
1249
1250         return folder_name;
1251 }
1252         
1253 void 
1254 _modest_ui_actions_on_new_folder (GtkWidget *widget,
1255                                   ModestMainWindow *main_window)
1256 {
1257         TnyFolder *parent_folder;
1258         ModestFolderView *folder_view;
1259         ModestWidgetFactory *widget_factory;
1260
1261         widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1262         folder_view = modest_widget_factory_get_folder_view (widget_factory);
1263         parent_folder = modest_folder_view_get_selected (folder_view);
1264
1265         if (parent_folder) {
1266                 gchar *folder_name;
1267
1268                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1269                                                    _("Please enter a name for the new folder"));
1270
1271                 if (folder_name != NULL && strlen (folder_name) > 0) {
1272                         TnyFolder *new_folder;
1273                         ModestMailOperation *mail_op;
1274
1275                         mail_op = modest_mail_operation_new ();
1276                         new_folder = modest_mail_operation_create_folder (mail_op,
1277                                                                           TNY_FOLDER_STORE (parent_folder),
1278                                                                           (const gchar *) folder_name);
1279                         if (new_folder) {
1280                                 /* Do anything more? The model
1281                                    is automatically updated */
1282                                 g_object_unref (new_folder);
1283                         }
1284                         g_object_unref (mail_op);
1285                 }
1286                 g_object_unref (parent_folder);
1287         }
1288         g_object_unref (G_OBJECT (widget_factory));
1289 }
1290
1291 void 
1292 _modest_ui_actions_on_rename_folder (GtkWidget *widget,
1293                                      ModestMainWindow *main_window)
1294 {
1295         TnyFolder *folder;
1296         ModestFolderView *folder_view;
1297         ModestWidgetFactory *widget_factory;
1298
1299         widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1300         folder_view = modest_widget_factory_get_folder_view (widget_factory);
1301         folder = modest_folder_view_get_selected (folder_view);
1302
1303         if (folder) {
1304                 gchar *folder_name;
1305
1306                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1307                                                    _("Please enter a new name for the folder"));
1308
1309                 if (folder_name != NULL && strlen (folder_name) > 0) {
1310                         ModestMailOperation *mail_op;
1311
1312                         mail_op = modest_mail_operation_new ();
1313                         modest_mail_operation_rename_folder (mail_op,
1314                                                              folder,
1315                                                              (const gchar *) folder_name);
1316                         g_object_unref (mail_op);
1317                 }
1318                 g_object_unref (folder);
1319         }
1320         g_object_unref (G_OBJECT (widget_factory));
1321 }
1322
1323 static void
1324 delete_folder (ModestMainWindow *main_window,
1325                gboolean move_to_trash) 
1326 {
1327         TnyFolder *folder;
1328         ModestFolderView *folder_view;
1329         ModestWidgetFactory *widget_factory;
1330         ModestMailOperation *mail_op;
1331                         
1332         widget_factory = modest_window_get_widget_factory (MODEST_WINDOW (main_window));
1333         folder_view = modest_widget_factory_get_folder_view (widget_factory);
1334         folder = modest_folder_view_get_selected (folder_view);
1335
1336         mail_op = modest_mail_operation_new ();
1337         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1338         g_object_unref (mail_op);
1339 }
1340
1341 void 
1342 _modest_ui_actions_on_delete_folder (GtkWidget *widget,
1343                                      ModestMainWindow *main_window)
1344 {
1345         delete_folder (main_window, FALSE);
1346 }
1347
1348 void 
1349 _modest_ui_actions_on_move_to_trash_folder (GtkWidget *widget,
1350                                             ModestMainWindow *main_window)
1351 {
1352         delete_folder (main_window, TRUE);
1353 }