1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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.
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.
30 #include <modest-widget-memory.h>
31 #include <modest-icon-factory.h>
33 #include <widgets/modest-toolbar.h>
35 #include "modest-main-window.h"
36 #include "modest-account-view-window.h"
37 #include "modest-edit-msg-window.h"
38 #include "modest-icon-names.h"
41 /* 'private'/'protected' functions */
42 static void modest_main_window_class_init (ModestMainWindowClass *klass);
43 static void modest_main_window_init (ModestMainWindow *obj);
44 static void modest_main_window_finalize (GObject *obj);
46 static void restore_sizes (ModestMainWindow *self);
47 static void save_sizes (ModestMainWindow *self);
56 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
57 struct _ModestMainWindowPrivate {
62 GtkWidget *folder_paned;
64 GtkWidget *main_paned;
66 ModestWidgetFactory *factory;
68 ModestAccountMgr *account_mgr;
70 ModestHeaderView *header_view;
71 ModestFolderView *folder_view;
72 ModestMsgView *msg_preview;
76 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
77 MODEST_TYPE_MAIN_WINDOW, \
78 ModestMainWindowPrivate))
80 static GtkWindowClass *parent_class = NULL;
82 /* uncomment the following if you have defined any signals */
83 /* static guint signals[LAST_SIGNAL] = {0}; */
86 modest_main_window_get_type (void)
88 static GType my_type = 0;
90 static const GTypeInfo my_info = {
91 sizeof(ModestMainWindowClass),
93 NULL, /* base finalize */
94 (GClassInitFunc) modest_main_window_class_init,
95 NULL, /* class finalize */
96 NULL, /* class data */
97 sizeof(ModestMainWindow),
99 (GInstanceInitFunc) modest_main_window_init,
102 my_type = g_type_register_static (GTK_TYPE_WINDOW,
110 modest_main_window_class_init (ModestMainWindowClass *klass)
112 GObjectClass *gobject_class;
113 gobject_class = (GObjectClass*) klass;
115 parent_class = g_type_class_peek_parent (klass);
116 gobject_class->finalize = modest_main_window_finalize;
118 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
120 /* signal definitions go here, e.g.: */
121 /* signals[MY_SIGNAL_1] = */
122 /* g_signal_new ("my_signal_1",....); */
123 /* signals[MY_SIGNAL_2] = */
124 /* g_signal_new ("my_signal_2",....); */
129 modest_main_window_init (ModestMainWindow *obj)
131 ModestMainWindowPrivate *priv;
133 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
135 priv->factory = NULL;
137 priv->account_mgr = NULL;
141 modest_main_window_finalize (GObject *obj)
143 ModestMainWindowPrivate *priv;
144 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
146 g_object_unref (G_OBJECT(priv->factory));
147 priv->factory = NULL;
150 g_object_unref (G_OBJECT(priv->conf));
154 if (priv->account_mgr) {
155 g_object_unref (G_OBJECT(priv->account_mgr));
156 priv->account_mgr = NULL;
159 G_OBJECT_CLASS(parent_class)->finalize (obj);
164 on_menu_about (GtkWidget *widget, gpointer data)
167 const gchar *authors[] = {
168 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
171 about = gtk_about_dialog_new ();
172 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
173 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
174 gtk_about_dialog_set_copyright (
175 GTK_ABOUT_DIALOG(about),
176 _("Copyright (c) 2006, Nokia Corporation\n"
177 "All rights reserved."));
178 gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG(about),
179 _("a modest e-mail client\n\n"
180 "design and implementation: Dirk-Jan C. Binnema\n"
181 "contributions from the fine people at KernelConcepts\n\n"
182 "uses the tinymail email framework written by Philip van Hoof"));
183 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
184 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
186 gtk_dialog_run (GTK_DIALOG (about));
187 gtk_widget_destroy(about);
192 on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget)
194 GtkWidget *account_win;
195 ModestMainWindowPrivate *priv;
197 g_return_if_fail (widget);
198 g_return_if_fail (self);
200 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
201 account_win = modest_account_view_window_new (priv->account_mgr,
204 gtk_window_set_transient_for (GTK_WINDOW(account_win),
207 gtk_widget_show (account_win);
212 on_menu_new_message (ModestMainWindow *self, guint action, GtkWidget *widget)
215 ModestMainWindowPrivate *priv;
217 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
219 msg_win = modest_edit_msg_window_new (priv->conf,
221 MODEST_EDIT_TYPE_NEW,
223 gtk_widget_show (msg_win);
227 on_menu_quit (ModestMainWindow *self, guint action, GtkWidget *widget)
230 gtk_widget_destroy (GTK_WIDGET(self));
234 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
235 static GtkItemFactoryEntry menu_items[] = {
236 { "/_File", NULL, NULL, 0, "<Branch>", NULL },
237 { "/File/_New", "<control>N", NULL, 0, "<StockItem>", GTK_STOCK_NEW },
238 { "/File/_Open", "<control>O", NULL, 0, "<StockItem>", GTK_STOCK_OPEN },
239 { "/File/_Save", "<control>S", NULL, 0, "<StockItem>", GTK_STOCK_SAVE },
240 { "/File/Save _As", NULL, NULL, 0, "<Item>", NULL },
241 { "/File/sep1", NULL, NULL, 0, "<Separator>", NULL },
242 { "/File/_Quit", "<CTRL>Q", on_menu_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
244 { "/_Edit", NULL, NULL, 0, "<Branch>", NULL },
245 { "/Edit/_Undo", "<CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_UNDO },
246 { "/Edit/_Redo", "<shift><CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_REDO },
247 { "/File/sep1", NULL, NULL, 0, "<Separator>", NULL },
248 { "/Edit/Cut", "<control>X", NULL, 0, "<StockItem>", GTK_STOCK_CUT },
249 { "/Edit/Copy", "<CTRL>C", NULL, 0, "<StockItem>", GTK_STOCK_COPY },
250 { "/Edit/Paste", NULL, NULL, 0, "<StockItem>", GTK_STOCK_PASTE},
251 { "/Edit/sep1", NULL, NULL, 0, "<Separator>", NULL },
252 { "/Edit/Delete", "<CTRL>Q", NULL, 0, "<Item>" ,NULL},
253 { "/Edit/Select all", "<CTRL>A", NULL, 0, "<Item>" ,NULL},
254 { "/Edit/Deelect all", "<Shift><CTRL>A", NULL, 0, "<Item>" ,NULL},
256 { "/_Actions", NULL, NULL, 0, "<Branch>" ,NULL},
257 { "/Actions/_New Message", NULL, on_menu_new_message, 0, "<Item>",NULL },
258 { "/Actions/_Reply", NULL, NULL, 0, "<Item>" ,NULL},
259 { "/Actions/_Forward", NULL, NULL, 0, "<Item>" ,NULL},
260 { "/Actions/_Bounce", NULL, NULL, 0, "<Item>",NULL },
262 { "/_Options", NULL, NULL, 0, "<Branch>" ,NULL},
263 { "/Options/_Accounts", NULL, on_menu_accounts,0, "<Item>" ,NULL},
264 { "/Options/_Contacts", NULL, NULL, 0, "<Item>" ,NULL },
267 { "/_Help", NULL, NULL, 0, "<Branch>" ,NULL},
268 { "/_Help/About", NULL, on_menu_about, 0, "<StockItem>", GTK_STOCK_ABOUT},
271 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
275 menubar_new (ModestMainWindow *self)
277 GtkItemFactory *item_factory;
278 GtkAccelGroup *accel_group;
280 /* Make an accelerator group (shortcut keys) */
281 accel_group = gtk_accel_group_new ();
283 /* Make an ItemFactory (that makes a menubar) */
284 item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
287 /* This function generates the menu items. Pass the item factory,
288 the number of items in the array, the array itself, and any
289 callback data for the the menu items. */
290 gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
292 ///* Attach the new accelerator group to the window. */
293 gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
295 /* Finally, return the actual menu bar created by the item factory. */
296 return gtk_item_factory_get_widget (item_factory, "<main>");
302 static ModestHeaderView*
303 header_view_new (ModestMainWindow *self)
306 GSList *columns = NULL;
307 ModestHeaderView *header_view;
308 ModestMainWindowPrivate *priv;
309 ModestHeaderViewColumn cols[] = {
310 MODEST_HEADER_VIEW_COLUMN_MSGTYPE,
311 MODEST_HEADER_VIEW_COLUMN_ATTACH,
312 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER
313 /* MODEST_HEADER_VIEW_COLUMN_FROM, */
314 /* MODEST_HEADER_VIEW_COLUMN_SUBJECT, */
315 /* MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE */
317 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
319 for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i)
320 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
322 header_view = modest_widget_factory_get_header_view (priv->factory);
323 modest_header_view_set_columns (header_view, columns);
324 g_slist_free (columns);
330 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
331 ModestMainWindow *self)
333 GtkTreeSelection *sel;
336 ModestMainWindowPrivate *priv;
338 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
341 case MODEST_TOOLBAR_BUTTON_NEW_MAIL:
342 on_menu_new_message (self, 0, NULL);
344 case MODEST_TOOLBAR_BUTTON_REPLY:
346 case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
348 case MODEST_TOOLBAR_BUTTON_FORWARD:
350 case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
353 case MODEST_TOOLBAR_BUTTON_NEXT:
354 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->header_view));
356 gtk_tree_selection_get_selected (sel, &model, &iter);
357 gtk_tree_model_iter_next (model, &iter);
358 gtk_tree_selection_select_iter (sel, &iter);
361 case MODEST_TOOLBAR_BUTTON_PREV:
363 /* gtk_tree_selection_get_selected (sel, &model, &iter); */
364 /* gtk_tree_model_iter_prev (model, &iter); */
365 /* gtk_tree_selection_select_iter (sel, &iter); */
369 case MODEST_TOOLBAR_BUTTON_DELETE:
372 g_printerr ("modest: key %d pressed\n", button_id);
376 static ModestToolbar*
377 toolbar_new (ModestMainWindow *self)
380 ModestToolbar *toolbar;
381 GSList *buttons = NULL;
382 ModestMainWindowPrivate *priv;
384 ModestToolbarButton button_ids[] = {
385 MODEST_TOOLBAR_BUTTON_NEW_MAIL,
386 MODEST_TOOLBAR_BUTTON_REPLY,
387 MODEST_TOOLBAR_BUTTON_REPLY_ALL,
388 MODEST_TOOLBAR_BUTTON_FORWARD,
389 MODEST_TOOLBAR_SEPARATOR,
390 MODEST_TOOLBAR_BUTTON_SEND_RECEIVE,
391 MODEST_TOOLBAR_SEPARATOR,
392 MODEST_TOOLBAR_BUTTON_PREV,
393 MODEST_TOOLBAR_BUTTON_NEXT,
394 MODEST_TOOLBAR_SEPARATOR,
395 MODEST_TOOLBAR_BUTTON_DELETE
398 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
400 for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
401 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
403 toolbar = modest_widget_factory_get_main_toolbar (priv->factory, buttons);
404 g_slist_free (buttons);
406 g_signal_connect (G_OBJECT(toolbar), "button_clicked",
407 G_CALLBACK(on_toolbar_button_clicked), self);
415 restore_sizes (ModestMainWindow *self)
417 ModestMainWindowPrivate *priv;
418 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
420 modest_widget_memory_restore_settings (priv->conf,GTK_WIDGET(self),
421 "modest-main-window");
422 modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(priv->folder_paned),
423 "modest-folder-paned");
424 modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(priv->msg_paned),
426 modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(priv->main_paned),
427 "modest-main-paned");
432 save_sizes (ModestMainWindow *self)
434 ModestMainWindowPrivate *priv;
436 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
438 modest_widget_memory_save_settings (priv->conf,GTK_WIDGET(self),
439 "modest-main-window");
440 modest_widget_memory_save_settings (priv->conf, GTK_WIDGET(priv->folder_paned),
441 "modest-folder-paned");
442 modest_widget_memory_save_settings (priv->conf, GTK_WIDGET(priv->msg_paned),
444 modest_widget_memory_save_settings (priv->conf, GTK_WIDGET(priv->main_paned),
445 "modest-main-paned");
449 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
453 win = gtk_scrolled_window_new (NULL, NULL);
454 gtk_scrolled_window_set_policy
455 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
456 GTK_POLICY_AUTOMATIC);
459 gtk_scrolled_window_add_with_viewport
460 (GTK_SCROLLED_WINDOW(win), widget);
462 gtk_container_add (GTK_CONTAINER(win),
470 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self)
479 GtkWidget *favorites;
481 GtkTreeViewColumn *col;
483 store = gtk_tree_store_new (1, G_TYPE_STRING);
484 favorites = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
485 col = gtk_tree_view_column_new_with_attributes (_("Favorites"),
486 gtk_cell_renderer_text_new(),
489 gtk_tree_view_append_column (GTK_TREE_VIEW(favorites), col);
490 gtk_widget_show_all (favorites);
492 g_object_unref (G_OBJECT(store));
500 modest_main_window_new (ModestConf *conf, ModestAccountMgr *account_mgr,
501 ModestWidgetFactory *factory)
504 ModestMainWindowPrivate *priv;
506 GtkWidget *main_vbox;
507 GtkWidget *status_hbox;
508 GtkWidget *header_win, *folder_win, *favorites_win;
510 g_return_val_if_fail (factory, NULL);
511 g_return_val_if_fail (conf, NULL);
513 obj = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
514 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
516 g_object_ref (factory);
517 priv->factory = factory;
522 g_object_ref (account_mgr);
523 priv->account_mgr = account_mgr;
525 /* widgets from factory */
526 priv->folder_view = modest_widget_factory_get_folder_view (factory);
527 priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
528 priv->msg_preview = modest_widget_factory_get_msg_preview (factory);
530 folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
532 header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
534 favorites_win = wrapped_in_scrolled_window (favorites_view(),FALSE);
537 priv->menubar = menubar_new (MODEST_MAIN_WINDOW(obj));
538 priv->toolbar = GTK_WIDGET(toolbar_new (MODEST_MAIN_WINDOW(obj)));
541 priv->folder_paned = gtk_vpaned_new ();
542 priv->msg_paned = gtk_vpaned_new ();
543 priv->main_paned = gtk_hpaned_new ();
544 gtk_paned_add1 (GTK_PANED(priv->main_paned), priv->folder_paned);
545 gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
546 gtk_paned_add1 (GTK_PANED(priv->folder_paned), favorites_win);
547 gtk_paned_add2 (GTK_PANED(priv->folder_paned), folder_win);
548 gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
549 gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
551 gtk_widget_show (GTK_WIDGET(priv->header_view));
552 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
555 /* status bar / progress */
556 status_hbox = gtk_hbox_new (FALSE, 0);
557 gtk_box_pack_start (GTK_BOX(status_hbox),
558 modest_widget_factory_get_folder_info_label (factory),
560 gtk_box_pack_start (GTK_BOX(status_hbox),
561 modest_widget_factory_get_status_bar(factory),
563 gtk_box_pack_start (GTK_BOX(status_hbox),
564 modest_widget_factory_get_progress_bar(factory),
566 gtk_box_pack_start (GTK_BOX(status_hbox),
567 modest_widget_factory_get_online_toggle(factory),
570 /* putting it all together... */
571 main_vbox = gtk_vbox_new (FALSE, 6);
572 gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
573 gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
574 gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE,0);
575 gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 0);
577 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
578 restore_sizes (MODEST_MAIN_WINDOW(obj));
580 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
581 gtk_window_set_icon (GTK_WINDOW(obj),
582 modest_icon_factory_get_icon (MODEST_APP_ICON));
584 gtk_widget_show_all (main_vbox);
586 g_signal_connect (G_OBJECT(obj), "delete-event",
587 G_CALLBACK(on_delete_event), obj);
589 return GTK_WIDGET(obj);