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