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