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