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