* all:
[modest] / src / maemo / 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, NULL); /* FIXME */
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                         ModestMailOperation *mail_op;
348
349                         header = TNY_HEADER (tny_iterator_get_current (iter));
350                         /* TODO: thick grain mail operation involving
351                            a list of objects. Composite pattern ??? */
352                         mail_op = modest_mail_operation_new ();
353
354                         /* Move to trash */
355                         modest_mail_operation_remove_msg (mail_op, header, TRUE);
356
357                         /* Remove from tree model */
358                         tny_list_remove (TNY_LIST (model), G_OBJECT (header));
359
360                         g_object_unref (G_OBJECT (mail_op));
361                         g_object_unref (header);
362                         tny_iterator_next (iter);
363
364                 } while (!tny_iterator_is_done (iter));
365         }
366 }
367
368
369 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
370 static GtkItemFactoryEntry menu_items[] = {
371         { "/_File",             NULL,                   NULL,           0, "<Branch>", NULL },
372         { "/File/_New",         "<control>N",           NULL,           0, "<StockItem>", GTK_STOCK_NEW },
373         { "/File/_Open",        "<control>O",           NULL,           0, "<StockItem>", GTK_STOCK_OPEN },
374         { "/File/_Save",        "<control>S",           NULL,           0, "<StockItem>", GTK_STOCK_SAVE },
375         { "/File/Save _As",     NULL,                   NULL,           0, "<Item>", NULL },
376         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>", NULL },
377         { "/File/_Quit",        "<CTRL>Q",              on_menu_quit,  0, "<StockItem>", GTK_STOCK_QUIT },
378
379         { "/_Edit",             NULL,                   NULL,           0, "<Branch>", NULL },
380         { "/Edit/_Undo",        "<CTRL>Z",              NULL,           0, "<StockItem>", GTK_STOCK_UNDO },
381         { "/Edit/_Redo",        "<shift><CTRL>Z",       NULL,           0, "<StockItem>", GTK_STOCK_REDO },
382         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>", NULL },
383         { "/Edit/Cut",          "<control>X",           NULL,           0, "<StockItem>", GTK_STOCK_CUT  },
384         { "/Edit/Copy",         "<CTRL>C",              NULL,           0, "<StockItem>", GTK_STOCK_COPY },
385         { "/Edit/Paste",        NULL,                   NULL,           0, "<StockItem>", GTK_STOCK_PASTE},
386         { "/Edit/sep1",         NULL,                   NULL,           0, "<Separator>", NULL },
387         { "/Edit/Delete",       "<CTRL>Q",              NULL,           0, "<Item>" ,NULL},
388         { "/Edit/Select all",   "<CTRL>A",              NULL,           0, "<Item>" ,NULL},
389         { "/Edit/Deelect all",  "<Shift><CTRL>A",       NULL,           0, "<Item>" ,NULL},
390
391         { "/_Actions",                NULL,             NULL,           0, "<Branch>" ,NULL},
392         { "/Actions/_New Message",    NULL,             on_menu_new_message,            0, "<Item>",NULL },
393         { "/Actions/_Reply",    NULL,                   on_menu_reply_forward,          1, "<Item>" ,NULL},
394         { "/Actions/_Forward",  NULL,                   on_menu_reply_forward,          3, "<Item>" ,NULL},
395         { "/Actions/_Bounce",   NULL,                   NULL,           0, "<Item>",NULL },     
396         
397         { "/_Options",           NULL,                  NULL,           0, "<Branch>" ,NULL},
398         { "/Options/_Accounts",  NULL,                  on_menu_accounts,0, "<Item>" ,NULL},
399         { "/Options/_Contacts",  NULL,                  NULL,           0, "<Item>" ,NULL },
400
401
402         { "/_Help",         NULL,                       NULL,           0, "<Branch>" ,NULL},
403         { "/_Help/About",   NULL,                       on_menu_about,  0, "<StockItem>", GTK_STOCK_ABOUT},
404 };
405
406 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
407
408
409 static GtkWidget *
410 menubar_new (ModestMainWindow *self)
411 {
412         GtkItemFactory *item_factory;
413         GtkAccelGroup *accel_group;
414         
415         /* Make an accelerator group (shortcut keys) */
416         accel_group = gtk_accel_group_new ();
417         
418         /* Make an ItemFactory (that makes a menubar) */
419         item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
420                                              accel_group);
421         
422         /* This function generates the menu items. Pass the item factory,
423            the number of items in the array, the array itself, and any
424            callback data for the the menu items. */
425         gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
426         
427         ///* Attach the new accelerator group to the window. */
428         gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
429         
430         /* Finally, return the actual menu bar created by the item factory. */
431         return gtk_item_factory_get_widget (item_factory, "<main>");
432 }
433
434
435
436
437 static ModestHeaderView*
438 header_view_new (ModestMainWindow *self)
439 {
440         int i;
441         GSList *columns = NULL;
442         ModestHeaderView *header_view;
443         ModestMainWindowPrivate *priv;
444         ModestHeaderViewColumn cols[] = {
445                 MODEST_HEADER_VIEW_COLUMN_MSGTYPE,
446                 MODEST_HEADER_VIEW_COLUMN_ATTACH,
447 /*              MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER, */
448                 MODEST_HEADER_VIEW_COLUMN_FROM,
449                 MODEST_HEADER_VIEW_COLUMN_SUBJECT,
450                 MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE
451         };
452         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
453         
454         for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i)
455                 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
456
457         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
458         modest_header_view_set_columns (header_view, columns);
459         g_slist_free (columns);
460
461         return header_view;
462 }
463
464 static void
465 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
466                            ModestMainWindow *self)
467 {
468         GtkTreeSelection *sel;
469         GtkTreeIter iter;
470         GtkTreeModel *model;
471         ModestMainWindowPrivate *priv;
472
473         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
474         
475         switch (button_id) {
476         case MODEST_TOOLBAR_BUTTON_NEW_MAIL:
477                 on_menu_new_message (self, 0, NULL);
478                 break;
479         case MODEST_TOOLBAR_BUTTON_REPLY:
480                 on_menu_reply_forward (self, 1, NULL);
481                 break;
482         case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
483                 on_menu_reply_forward (self, 2, NULL);
484                 break;
485         case MODEST_TOOLBAR_BUTTON_FORWARD:
486                 on_menu_reply_forward (self, 3, NULL);
487                 break;
488         case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
489                 
490
491         case MODEST_TOOLBAR_BUTTON_NEXT:
492                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->header_view));
493                 if (sel) {
494                         gtk_tree_selection_get_selected (sel, &model, &iter);
495                         gtk_tree_model_iter_next (model, &iter);
496                         gtk_tree_selection_select_iter (sel, &iter);
497                 }
498                 
499         case MODEST_TOOLBAR_BUTTON_PREV:
500         /*      if (sel) { */
501 /*                      gtk_tree_selection_get_selected (sel, &model, &iter); */
502 /*                      gtk_tree_model_iter_prev (model, &iter); */
503 /*                      gtk_tree_selection_select_iter (sel, &iter); */
504 /*              } */
505
506                 break;
507         case MODEST_TOOLBAR_BUTTON_DELETE:
508                 on_menu_delete (self, 0, GTK_WIDGET (toolbar));
509                 break;
510
511         default:
512                 g_printerr ("modest: key %d pressed\n", button_id);
513         }
514 }
515
516 static ModestToolbar*
517 toolbar_new (ModestMainWindow *self)
518 {
519         int i;
520         ModestToolbar *toolbar;
521         GSList *buttons = NULL;
522         ModestMainWindowPrivate *priv;
523
524         ModestToolbarButton button_ids[] = {
525                 MODEST_TOOLBAR_BUTTON_NEW_MAIL,
526                 MODEST_TOOLBAR_BUTTON_REPLY,
527                 MODEST_TOOLBAR_BUTTON_REPLY_ALL,
528                 MODEST_TOOLBAR_BUTTON_FORWARD,
529                 MODEST_TOOLBAR_SEPARATOR,
530                 MODEST_TOOLBAR_BUTTON_SEND_RECEIVE,
531                 MODEST_TOOLBAR_SEPARATOR,
532                 MODEST_TOOLBAR_BUTTON_PREV,
533                 MODEST_TOOLBAR_BUTTON_NEXT,
534                 MODEST_TOOLBAR_SEPARATOR,               
535                 MODEST_TOOLBAR_BUTTON_DELETE
536         };              
537         
538         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
539
540         for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
541                 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
542         
543         toolbar = modest_widget_factory_get_main_toolbar (priv->widget_factory, buttons);
544         g_slist_free (buttons);
545         
546         g_signal_connect (G_OBJECT(toolbar), "button_clicked",
547                           G_CALLBACK(on_toolbar_button_clicked), self);
548         
549         return toolbar;
550 }
551
552
553
554 static void
555 restore_sizes (ModestMainWindow *self)
556 {
557         ModestConf *conf;
558         ModestMainWindowPrivate *priv;
559         
560         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
561         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
562
563         modest_widget_memory_restore_settings (conf,GTK_WIDGET(self),
564                                                "modest-main-window");
565         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->folder_paned),
566                                                "modest-folder-paned");
567         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->msg_paned),
568                                                "modest-msg-paned");
569         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->main_paned),
570                                                "modest-main-paned");
571 }
572
573
574 static void
575 save_sizes (ModestMainWindow *self)
576 {
577         ModestMainWindowPrivate *priv;
578         ModestConf *conf;
579         
580         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
581         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
582         
583         modest_widget_memory_save_settings (conf,GTK_WIDGET(self),
584                                             "modest-main-window");
585         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->folder_paned),
586                                             "modest-folder-paned");
587         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->msg_paned),
588                                             "modest-msg-paned");
589         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->main_paned),
590                                             "modest-main-paned");
591 }
592
593 static GtkWidget*
594 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
595 {
596         GtkWidget *win;
597
598         win = gtk_scrolled_window_new (NULL, NULL);
599         gtk_scrolled_window_set_policy
600                 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
601                  GTK_POLICY_AUTOMATIC);
602         
603         if (needs_viewport)
604                 gtk_scrolled_window_add_with_viewport
605                         (GTK_SCROLLED_WINDOW(win), widget);
606         else
607                 gtk_container_add (GTK_CONTAINER(win),
608                                    widget);
609
610         return win;
611 }
612
613
614 static gboolean
615 on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self)
616 {
617         save_sizes (self);
618         return FALSE;
619 }
620
621 static GtkWidget*
622 favorites_view ()
623 {
624         GtkWidget *favorites;
625         GtkTreeStore *store;
626         GtkTreeViewColumn *col;
627
628         store = gtk_tree_store_new (1, G_TYPE_STRING);
629         favorites = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
630         col = gtk_tree_view_column_new_with_attributes (_("Favorites"),
631                                                         gtk_cell_renderer_text_new(),
632                                                         "text", 0, NULL);
633         
634         gtk_tree_view_append_column (GTK_TREE_VIEW(favorites), col);
635         gtk_widget_show_all (favorites);
636
637         g_object_unref (G_OBJECT(store));
638
639         return favorites;
640 }
641
642
643
644 GtkWidget*
645 modest_main_window_new (ModestWidgetFactory *widget_factory)
646 {
647         GObject *obj;
648         ModestMainWindowPrivate *priv;
649         
650         GtkWidget *main_vbox;
651         GtkWidget *status_hbox;
652         GtkWidget *header_win, *folder_win, *favorites_win;
653         
654         g_return_val_if_fail (widget_factory, NULL);
655
656         obj  = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
657         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
658
659         g_object_ref (widget_factory);
660         priv->widget_factory = widget_factory;
661
662         /* widgets from factory */
663         priv->folder_view = modest_widget_factory_get_folder_view (widget_factory);
664         priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
665         priv->msg_preview = modest_widget_factory_get_msg_preview (widget_factory);
666         
667         folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
668                                                  FALSE);
669         header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
670                                                  FALSE);                           
671         favorites_win = wrapped_in_scrolled_window (favorites_view(),FALSE);                       
672         
673         /* tool/menubar */
674         priv->menubar = menubar_new (MODEST_MAIN_WINDOW(obj));
675         priv->toolbar = GTK_WIDGET(toolbar_new (MODEST_MAIN_WINDOW(obj)));
676
677         /* paned */
678         priv->folder_paned = gtk_vpaned_new ();
679         priv->msg_paned = gtk_vpaned_new ();
680         priv->main_paned = gtk_hpaned_new ();
681         gtk_paned_add1 (GTK_PANED(priv->main_paned), priv->folder_paned);
682         gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
683         gtk_paned_add1 (GTK_PANED(priv->folder_paned), favorites_win);
684         gtk_paned_add2 (GTK_PANED(priv->folder_paned), folder_win);
685         gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
686         gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
687
688         gtk_widget_show (GTK_WIDGET(priv->header_view));
689         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
690
691         
692         /* status bar / progress */
693         status_hbox = gtk_hbox_new (FALSE, 0);
694         gtk_box_pack_start (GTK_BOX(status_hbox),
695                             modest_widget_factory_get_folder_info_label (widget_factory),
696                             FALSE,FALSE, 6);
697         gtk_box_pack_start (GTK_BOX(status_hbox),
698                             modest_widget_factory_get_status_bar(widget_factory),
699                             TRUE, TRUE, 0);
700         gtk_box_pack_start (GTK_BOX(status_hbox),
701                             modest_widget_factory_get_progress_bar(widget_factory),
702                             FALSE, FALSE, 0);
703         gtk_box_pack_start (GTK_BOX(status_hbox),
704                           modest_widget_factory_get_online_toggle(widget_factory),
705                           FALSE, FALSE, 0);
706
707         /* putting it all together... */
708         main_vbox = gtk_vbox_new (FALSE, 6);
709         gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
710         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
711         gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE,0);
712         gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 0);
713         
714         gtk_container_add (GTK_CONTAINER(obj), main_vbox);
715         restore_sizes (MODEST_MAIN_WINDOW(obj));        
716
717         gtk_window_set_title (GTK_WINDOW(obj), "Modest");
718         gtk_window_set_icon  (GTK_WINDOW(obj),
719                               modest_icon_factory_get_icon (MODEST_APP_ICON));
720         
721         gtk_widget_show_all (main_vbox);
722
723         g_signal_connect (G_OBJECT(obj), "delete-event",
724                           G_CALLBACK(on_delete_event), obj);
725         
726         return GTK_WIDGET(obj);
727 }