60ffaea990246699fed408843665acef4bc5c7f9
[modest] / src / gtk / modest-main-window.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 #include <glib/gi18n.h>
31 #include <gtk/gtkaboutdialog.h>
32 #include <gtk/gtktreeviewcolumn.h>
33
34 #include <modest-widget-memory.h>
35 #include <modest-icon-factory.h>
36
37 #include <widgets/modest-toolbar.h>
38
39 #include "modest-main-window.h"
40 #include "modest-account-view-window.h"
41 #include "modest-account-mgr.h"
42 #include "modest-conf.h"
43 #include "modest-edit-msg-window.h"
44 #include "modest-icon-names.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-tny-msg-actions.h"
47 #include "modest-mail-operation.h"
48
49 /* 'private'/'protected' functions */
50 static void modest_main_window_class_init    (ModestMainWindowClass *klass);
51 static void modest_main_window_init          (ModestMainWindow *obj);
52 static void modest_main_window_finalize      (GObject *obj);
53
54 static void restore_sizes (ModestMainWindow *self);
55 static void save_sizes (ModestMainWindow *self);
56
57 /* list my signals */
58 enum {
59         /* MY_SIGNAL_1, */
60         /* MY_SIGNAL_2, */
61         LAST_SIGNAL
62 };
63
64 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
65 struct _ModestMainWindowPrivate {
66
67         GtkWidget *toolbar;
68         GtkWidget *menubar;
69
70         GtkWidget *folder_paned;
71         GtkWidget *msg_paned;
72         GtkWidget *main_paned;
73         
74         ModestWidgetFactory *widget_factory;
75         TnyPlatformFactory *factory;
76   
77         ModestHeaderView *header_view;
78         ModestFolderView *folder_view;
79         ModestMsgView    *msg_preview;
80 };
81
82
83 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
84                                                 MODEST_TYPE_MAIN_WINDOW, \
85                                                 ModestMainWindowPrivate))
86 /* globals */
87 static GtkWindowClass *parent_class = NULL;
88
89 /* uncomment the following if you have defined any signals */
90 /* static guint signals[LAST_SIGNAL] = {0}; */
91
92 GType
93 modest_main_window_get_type (void)
94 {
95         static GType my_type = 0;
96         if (!my_type) {
97                 static const GTypeInfo my_info = {
98                         sizeof(ModestMainWindowClass),
99                         NULL,           /* base init */
100                         NULL,           /* base finalize */
101                         (GClassInitFunc) modest_main_window_class_init,
102                         NULL,           /* class finalize */
103                         NULL,           /* class data */
104                         sizeof(ModestMainWindow),
105                         1,              /* n_preallocs */
106                         (GInstanceInitFunc) modest_main_window_init,
107                         NULL
108                 };
109                 my_type = g_type_register_static (GTK_TYPE_WINDOW,
110                                                   "ModestMainWindow",
111                                                   &my_info, 0);
112         }
113         return my_type;
114 }
115
116 static void
117 modest_main_window_class_init (ModestMainWindowClass *klass)
118 {
119         GObjectClass *gobject_class;
120         gobject_class = (GObjectClass*) klass;
121
122         parent_class            = g_type_class_peek_parent (klass);
123         gobject_class->finalize = modest_main_window_finalize;
124
125         g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
126
127         /* signal definitions go here, e.g.: */
128 /*      signals[MY_SIGNAL_1] = */
129 /*              g_signal_new ("my_signal_1",....); */
130 /*      signals[MY_SIGNAL_2] = */
131 /*              g_signal_new ("my_signal_2",....); */
132 /*      etc. */
133 }
134
135 static void
136 modest_main_window_init (ModestMainWindow *obj)
137 {
138         ModestMainWindowPrivate *priv;
139
140         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
141         
142         priv->factory = modest_tny_platform_factory_get_instance ();
143 }
144
145 static void
146 modest_main_window_finalize (GObject *obj)
147 {
148         ModestMainWindowPrivate *priv;  
149         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
150         if (priv->widget_factory) {
151                 g_object_unref (G_OBJECT(priv->widget_factory));
152                 priv->widget_factory = NULL;
153         }
154
155         G_OBJECT_CLASS(parent_class)->finalize (obj);
156 }
157
158
159 static void
160 on_menu_about (GtkWidget *widget, gpointer data)
161 {
162         GtkWidget *about;
163         const gchar *authors[] = {
164                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
165                 NULL
166         };      
167         about = gtk_about_dialog_new ();
168         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
169         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
170         gtk_about_dialog_set_copyright (
171                 GTK_ABOUT_DIALOG(about),
172                 _("Copyright (c) 2006, Nokia Corporation\n"
173                   "All rights reserved."));
174         gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG(about),
175                 _("a modest e-mail client\n\n"
176                   "design and implementation: Dirk-Jan C. Binnema\n"
177                   "contributions from the fine people at KernelConcepts\n\n"
178                   "uses the tinymail email framework written by Philip van Hoof"));
179         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
180         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
181
182         gtk_dialog_run (GTK_DIALOG (about));
183         gtk_widget_destroy(about);
184 }
185
186
187 static void
188 on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget)
189 {
190         GtkWidget *account_win;
191         ModestMainWindowPrivate *priv;
192
193         g_return_if_fail (widget);
194         g_return_if_fail (self);
195         
196         priv        = MODEST_MAIN_WINDOW_GET_PRIVATE(self);     
197         account_win = modest_account_view_window_new (priv->widget_factory);
198
199         gtk_window_set_transient_for (GTK_WINDOW(account_win),
200                                       GTK_WINDOW(self));
201                                       
202         gtk_widget_show (account_win);
203 }
204
205
206 static void
207 on_menu_new_message (ModestMainWindow *self, guint action, GtkWidget *widget)
208 {
209         GtkWidget *msg_win;
210         ModestMainWindowPrivate *priv;
211
212         priv  = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
213
214         msg_win = modest_edit_msg_window_new (priv->widget_factory,
215                                               MODEST_EDIT_TYPE_NEW,
216                                               NULL);
217         gtk_widget_show (msg_win);
218 }
219
220 static void
221 on_menu_reply_forward (ModestMainWindow *self, guint action, GtkWidget *widget)
222 {
223         GtkWidget *msg_win;
224         ModestMainWindowPrivate *priv;
225         ModestHeaderView *header_view;
226         TnyList *header_list;
227         TnyIterator *iter;
228         const gchar *from;
229         gchar *reply_key, *forward_key;
230         ModestMailOperationReplyType reply_type;
231         ModestMailOperationForwardType forward_type;
232         ModestConf *conf;
233         GError *error;
234
235         priv  = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
236         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
237
238         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
239         header_list = modest_header_view_get_selected_headers (header_view);
240
241         /* Get reply and forward types */
242         error = NULL;
243         reply_key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE, MODEST_CONF_REPLY_TYPE);
244         reply_type = modest_conf_get_int (conf, reply_key, &error);
245         if (error) {
246                 g_warning ("key %s not defined", reply_key);
247                 reply_type = MODEST_MAIL_OPERATION_REPLY_TYPE_CITE;
248                 g_error_free (error);
249                 error = NULL;
250         }
251         g_free (reply_key);
252         
253         forward_key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE, MODEST_CONF_FORWARD_TYPE);
254         forward_type = modest_conf_get_int (conf, forward_key, NULL);
255         if (error) {
256                 g_warning ("key %s not defined", forward_key);
257                 reply_type = MODEST_MAIL_OPERATION_FORWARD_TYPE_INLINE;
258                 g_error_free (error);
259         }
260         g_free (forward_key);
261         
262         if (header_list) {
263                 iter = tny_list_create_iterator (header_list);
264                 do {
265                         TnyHeader *header, *new_header;
266                         TnyFolder *folder;
267                         TnyMsg    *msg, *new_msg;
268                         ModestEditType edit_type;
269
270                         /* Get msg from header */
271                         header = TNY_HEADER (tny_iterator_get_current (iter));
272                         folder = tny_header_get_folder (header);
273                         msg = tny_folder_get_msg (folder, header);
274
275                         from = modest_folder_view_get_selected_account (priv->folder_view);
276
277                         /* FIXME: select proper action */
278                         switch (action) {
279                         case 1:
280                                 new_msg = 
281                                         modest_mail_operation_create_reply_mail (msg, from, reply_type,
282                                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
283                                 edit_type = MODEST_EDIT_TYPE_REPLY;
284                                 break;
285                         case 2:
286                                 new_msg = 
287                                         modest_mail_operation_create_reply_mail (msg, from, reply_type,
288                                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
289                                 edit_type = MODEST_EDIT_TYPE_REPLY;
290                                 break;
291                         case 3:
292                                 new_msg = 
293                                         modest_mail_operation_create_forward_mail (msg, from, forward_type);
294                                 edit_type = MODEST_EDIT_TYPE_FORWARD;
295                                 break;
296                         default:
297                                 g_warning ("unexpected action type: %d", action);
298                         }
299
300                         /* Set from */
301                         new_header = tny_msg_get_header (new_msg);
302                         tny_header_set_from (new_header, 
303                                              modest_folder_view_get_selected_account (priv->folder_view));
304
305                         /* Show edit window */
306                         msg_win = modest_edit_msg_window_new (priv->widget_factory,
307                                                               edit_type,
308                                                               new_msg);
309                         gtk_widget_show (msg_win);
310
311                         /* Clean and go on */
312                         g_object_unref (new_msg);
313                         tny_iterator_next (iter);
314
315                 } while (!tny_iterator_is_done (iter));
316         }
317 }
318
319 static void
320 on_menu_quit (ModestMainWindow *self, guint action, GtkWidget *widget)
321 {
322         save_sizes (self);
323         gtk_widget_destroy (GTK_WIDGET(self));
324 }
325
326 static void
327 on_menu_delete (ModestMainWindow *self, guint action, GtkWidget *widget)
328 {
329         ModestMainWindowPrivate *priv;
330         ModestHeaderView *header_view;
331         TnyList *header_list;
332         TnyIterator *iter;
333         GtkTreeModel *model;
334
335         priv  = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
336
337         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
338         header_list = modest_header_view_get_selected_headers (header_view);
339         
340         if (header_list) {
341                 iter = tny_list_create_iterator (header_list);
342                 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
343                 if (GTK_IS_TREE_MODEL_SORT (model))
344                         model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
345                 do {
346                         TnyHeader *header;
347
348                         header = TNY_HEADER (tny_iterator_get_current (iter));
349
350                         /* Remove from tree model */
351                         tny_list_remove (TNY_LIST (model), G_OBJECT (header));
352
353                         /* Remove from server */
354                         modest_tny_msg_actions_remove (header);
355
356                         g_object_unref (header);
357                         tny_iterator_next (iter);
358
359                 } while (!tny_iterator_is_done (iter));
360         }
361 }
362
363
364 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
365 static GtkItemFactoryEntry menu_items[] = {
366         { "/_File",             NULL,                   NULL,           0, "<Branch>", NULL },
367         { "/File/_New",         "<control>N",           NULL,           0, "<StockItem>", GTK_STOCK_NEW },
368         { "/File/_Open",        "<control>O",           NULL,           0, "<StockItem>", GTK_STOCK_OPEN },
369         { "/File/_Save",        "<control>S",           NULL,           0, "<StockItem>", GTK_STOCK_SAVE },
370         { "/File/Save _As",     NULL,                   NULL,           0, "<Item>", NULL },
371         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>", NULL },
372         { "/File/_Quit",        "<CTRL>Q",              on_menu_quit,  0, "<StockItem>", GTK_STOCK_QUIT },
373
374         { "/_Edit",             NULL,                   NULL,           0, "<Branch>", NULL },
375         { "/Edit/_Undo",        "<CTRL>Z",              NULL,           0, "<StockItem>", GTK_STOCK_UNDO },
376         { "/Edit/_Redo",        "<shift><CTRL>Z",       NULL,           0, "<StockItem>", GTK_STOCK_REDO },
377         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>", NULL },
378         { "/Edit/Cut",          "<control>X",           NULL,           0, "<StockItem>", GTK_STOCK_CUT  },
379         { "/Edit/Copy",         "<CTRL>C",              NULL,           0, "<StockItem>", GTK_STOCK_COPY },
380         { "/Edit/Paste",        NULL,                   NULL,           0, "<StockItem>", GTK_STOCK_PASTE},
381         { "/Edit/sep1",         NULL,                   NULL,           0, "<Separator>", NULL },
382         { "/Edit/Delete",       "<CTRL>Q",              NULL,           0, "<Item>" ,NULL},
383         { "/Edit/Select all",   "<CTRL>A",              NULL,           0, "<Item>" ,NULL},
384         { "/Edit/Deelect all",  "<Shift><CTRL>A",       NULL,           0, "<Item>" ,NULL},
385
386         { "/_Actions",                NULL,             NULL,           0, "<Branch>" ,NULL},
387         { "/Actions/_New Message",    NULL,             on_menu_new_message,            0, "<Item>",NULL },
388         { "/Actions/_Reply",    NULL,                   on_menu_reply_forward,          1, "<Item>" ,NULL},
389         { "/Actions/_Forward",  NULL,                   on_menu_reply_forward,          3, "<Item>" ,NULL},
390         { "/Actions/_Bounce",   NULL,                   NULL,           0, "<Item>",NULL },     
391         
392         { "/_Options",           NULL,                  NULL,           0, "<Branch>" ,NULL},
393         { "/Options/_Accounts",  NULL,                  on_menu_accounts,0, "<Item>" ,NULL},
394         { "/Options/_Contacts",  NULL,                  NULL,           0, "<Item>" ,NULL },
395
396
397         { "/_Help",         NULL,                       NULL,           0, "<Branch>" ,NULL},
398         { "/_Help/About",   NULL,                       on_menu_about,  0, "<StockItem>", GTK_STOCK_ABOUT},
399 };
400
401 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
402
403
404 static GtkWidget *
405 menubar_new (ModestMainWindow *self)
406 {
407         GtkItemFactory *item_factory;
408         GtkAccelGroup *accel_group;
409         
410         /* Make an accelerator group (shortcut keys) */
411         accel_group = gtk_accel_group_new ();
412         
413         /* Make an ItemFactory (that makes a menubar) */
414         item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
415                                              accel_group);
416         
417         /* This function generates the menu items. Pass the item factory,
418            the number of items in the array, the array itself, and any
419            callback data for the the menu items. */
420         gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
421         
422         ///* Attach the new accelerator group to the window. */
423         gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
424         
425         /* Finally, return the actual menu bar created by the item factory. */
426         return gtk_item_factory_get_widget (item_factory, "<main>");
427 }
428
429
430
431
432 static ModestHeaderView*
433 header_view_new (ModestMainWindow *self)
434 {
435         int i;
436         GSList *columns = NULL;
437         ModestHeaderView *header_view;
438         ModestMainWindowPrivate *priv;
439         ModestHeaderViewColumn cols[] = {
440                 MODEST_HEADER_VIEW_COLUMN_MSGTYPE,
441                 MODEST_HEADER_VIEW_COLUMN_ATTACH,
442 /*              MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER, */
443                 MODEST_HEADER_VIEW_COLUMN_FROM,
444                 MODEST_HEADER_VIEW_COLUMN_SUBJECT,
445                 MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE
446         };
447         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
448         
449         for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i)
450                 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
451
452         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
453         modest_header_view_set_columns (header_view, columns);
454         g_slist_free (columns);
455
456         return header_view;
457 }
458
459 static void
460 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
461                            ModestMainWindow *self)
462 {
463         GtkTreeSelection *sel;
464         GtkTreeIter iter;
465         GtkTreeModel *model;
466         ModestMainWindowPrivate *priv;
467
468         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
469         
470         switch (button_id) {
471         case MODEST_TOOLBAR_BUTTON_NEW_MAIL:
472                 on_menu_new_message (self, 0, NULL);
473                 break;
474         case MODEST_TOOLBAR_BUTTON_REPLY:
475                 on_menu_reply_forward (self, 1, NULL);
476                 break;
477         case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
478                 on_menu_reply_forward (self, 2, NULL);
479                 break;
480         case MODEST_TOOLBAR_BUTTON_FORWARD:
481                 on_menu_reply_forward (self, 3, NULL);
482                 break;
483         case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
484                 
485
486         case MODEST_TOOLBAR_BUTTON_NEXT:
487                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->header_view));
488                 if (sel) {
489                         gtk_tree_selection_get_selected (sel, &model, &iter);
490                         gtk_tree_model_iter_next (model, &iter);
491                         gtk_tree_selection_select_iter (sel, &iter);
492                 }
493                 
494         case MODEST_TOOLBAR_BUTTON_PREV:
495         /*      if (sel) { */
496 /*                      gtk_tree_selection_get_selected (sel, &model, &iter); */
497 /*                      gtk_tree_model_iter_prev (model, &iter); */
498 /*                      gtk_tree_selection_select_iter (sel, &iter); */
499 /*              } */
500
501                 break;
502         case MODEST_TOOLBAR_BUTTON_DELETE:
503                 on_menu_delete (self, 0, GTK_WIDGET (toolbar));
504                 break;
505
506         default:
507                 g_printerr ("modest: key %d pressed\n", button_id);
508         }
509 }
510
511 static ModestToolbar*
512 toolbar_new (ModestMainWindow *self)
513 {
514         int i;
515         ModestToolbar *toolbar;
516         GSList *buttons = NULL;
517         ModestMainWindowPrivate *priv;
518
519         ModestToolbarButton button_ids[] = {
520                 MODEST_TOOLBAR_BUTTON_NEW_MAIL,
521                 MODEST_TOOLBAR_BUTTON_REPLY,
522                 MODEST_TOOLBAR_BUTTON_REPLY_ALL,
523                 MODEST_TOOLBAR_BUTTON_FORWARD,
524                 MODEST_TOOLBAR_SEPARATOR,
525                 MODEST_TOOLBAR_BUTTON_SEND_RECEIVE,
526                 MODEST_TOOLBAR_SEPARATOR,
527                 MODEST_TOOLBAR_BUTTON_PREV,
528                 MODEST_TOOLBAR_BUTTON_NEXT,
529                 MODEST_TOOLBAR_SEPARATOR,               
530                 MODEST_TOOLBAR_BUTTON_DELETE
531         };              
532         
533         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
534
535         for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
536                 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
537         
538         toolbar = modest_widget_factory_get_main_toolbar (priv->widget_factory, buttons);
539         g_slist_free (buttons);
540         
541         g_signal_connect (G_OBJECT(toolbar), "button_clicked",
542                           G_CALLBACK(on_toolbar_button_clicked), self);
543         
544         return toolbar;
545 }
546
547
548
549 static void
550 restore_sizes (ModestMainWindow *self)
551 {
552         ModestConf *conf;
553         ModestMainWindowPrivate *priv;
554         
555         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
556         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
557
558         modest_widget_memory_restore_settings (conf,GTK_WIDGET(self),
559                                                "modest-main-window");
560         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->folder_paned),
561                                                "modest-folder-paned");
562         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->msg_paned),
563                                                "modest-msg-paned");
564         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->main_paned),
565                                                "modest-main-paned");
566 }
567
568
569 static void
570 save_sizes (ModestMainWindow *self)
571 {
572         ModestMainWindowPrivate *priv;
573         ModestConf *conf;
574         
575         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
576         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
577         
578         modest_widget_memory_save_settings (conf,GTK_WIDGET(self),
579                                             "modest-main-window");
580         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->folder_paned),
581                                             "modest-folder-paned");
582         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->msg_paned),
583                                             "modest-msg-paned");
584         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->main_paned),
585                                             "modest-main-paned");
586 }
587
588 static GtkWidget*
589 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
590 {
591         GtkWidget *win;
592
593         win = gtk_scrolled_window_new (NULL, NULL);
594         gtk_scrolled_window_set_policy
595                 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
596                  GTK_POLICY_AUTOMATIC);
597         
598         if (needs_viewport)
599                 gtk_scrolled_window_add_with_viewport
600                         (GTK_SCROLLED_WINDOW(win), widget);
601         else
602                 gtk_container_add (GTK_CONTAINER(win),
603                                    widget);
604
605         return win;
606 }
607
608
609 static gboolean
610 on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self)
611 {
612         save_sizes (self);
613         return FALSE;
614 }
615
616 static GtkWidget*
617 favorites_view ()
618 {
619         GtkWidget *favorites;
620         GtkTreeStore *store;
621         GtkTreeViewColumn *col;
622
623         store = gtk_tree_store_new (1, G_TYPE_STRING);
624         favorites = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
625         col = gtk_tree_view_column_new_with_attributes (_("Favorites"),
626                                                         gtk_cell_renderer_text_new(),
627                                                         "text", 0, NULL);
628         
629         gtk_tree_view_append_column (GTK_TREE_VIEW(favorites), col);
630         gtk_widget_show_all (favorites);
631
632         g_object_unref (G_OBJECT(store));
633
634         return favorites;
635 }
636
637
638
639 GtkWidget*
640 modest_main_window_new (ModestWidgetFactory *widget_factory)
641 {
642         GObject *obj;
643         ModestMainWindowPrivate *priv;
644         
645         GtkWidget *main_vbox;
646         GtkWidget *status_hbox;
647         GtkWidget *header_win, *folder_win, *favorites_win;
648         
649         g_return_val_if_fail (widget_factory, NULL);
650
651         obj  = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
652         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
653
654         g_object_ref (widget_factory);
655         priv->widget_factory = widget_factory;
656
657         /* widgets from factory */
658         priv->folder_view = modest_widget_factory_get_folder_view (widget_factory);
659         priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
660         priv->msg_preview = modest_widget_factory_get_msg_preview (widget_factory);
661         
662         folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
663                                                  FALSE);
664         header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
665                                                  FALSE);                           
666         favorites_win = wrapped_in_scrolled_window (favorites_view(),FALSE);                       
667         
668         /* tool/menubar */
669         priv->menubar = menubar_new (MODEST_MAIN_WINDOW(obj));
670         priv->toolbar = GTK_WIDGET(toolbar_new (MODEST_MAIN_WINDOW(obj)));
671
672         /* paned */
673         priv->folder_paned = gtk_vpaned_new ();
674         priv->msg_paned = gtk_vpaned_new ();
675         priv->main_paned = gtk_hpaned_new ();
676         gtk_paned_add1 (GTK_PANED(priv->main_paned), priv->folder_paned);
677         gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
678         gtk_paned_add1 (GTK_PANED(priv->folder_paned), favorites_win);
679         gtk_paned_add2 (GTK_PANED(priv->folder_paned), folder_win);
680         gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
681         gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
682
683         gtk_widget_show (GTK_WIDGET(priv->header_view));
684         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
685
686         
687         /* status bar / progress */
688         status_hbox = gtk_hbox_new (FALSE, 0);
689         gtk_box_pack_start (GTK_BOX(status_hbox),
690                             modest_widget_factory_get_folder_info_label (widget_factory),
691                             FALSE,FALSE, 6);
692         gtk_box_pack_start (GTK_BOX(status_hbox),
693                             modest_widget_factory_get_status_bar(widget_factory),
694                             TRUE, TRUE, 0);
695         gtk_box_pack_start (GTK_BOX(status_hbox),
696                             modest_widget_factory_get_progress_bar(widget_factory),
697                             FALSE, FALSE, 0);
698         gtk_box_pack_start (GTK_BOX(status_hbox),
699                           modest_widget_factory_get_online_toggle(widget_factory),
700                           FALSE, FALSE, 0);
701
702         /* putting it all together... */
703         main_vbox = gtk_vbox_new (FALSE, 6);
704         gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
705         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
706         gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE,0);
707         gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 0);
708         
709         gtk_container_add (GTK_CONTAINER(obj), main_vbox);
710         restore_sizes (MODEST_MAIN_WINDOW(obj));        
711
712         gtk_window_set_title (GTK_WINDOW(obj), "Modest");
713         gtk_window_set_icon  (GTK_WINDOW(obj),
714                               modest_icon_factory_get_icon (MODEST_APP_ICON));
715         
716         gtk_widget_show_all (main_vbox);
717
718         g_signal_connect (G_OBJECT(obj), "delete-event",
719                           G_CALLBACK(on_delete_event), obj);
720         
721         return GTK_WIDGET(obj);
722 }