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 <glib/gi18n.h>
31 #include <gtk/gtkaboutdialog.h>
32 #include <gtk/gtktreeviewcolumn.h>
34 #include <modest-widget-memory.h>
35 #include <modest-icon-factory.h>
37 #include <widgets/modest-toolbar.h>
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-mail-operation.h"
48 /* 'private'/'protected' functions */
49 static void modest_main_window_class_init (ModestMainWindowClass *klass);
50 static void modest_main_window_init (ModestMainWindow *obj);
51 static void modest_main_window_finalize (GObject *obj);
53 static void restore_sizes (ModestMainWindow *self);
54 static void save_sizes (ModestMainWindow *self);
63 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
64 struct _ModestMainWindowPrivate {
69 GtkWidget *folder_paned;
71 GtkWidget *main_paned;
73 ModestWidgetFactory *widget_factory;
74 TnyPlatformFactory *factory;
76 ModestHeaderView *header_view;
77 ModestFolderView *folder_view;
78 ModestMsgView *msg_preview;
82 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
83 MODEST_TYPE_MAIN_WINDOW, \
84 ModestMainWindowPrivate))
86 static GtkWindowClass *parent_class = NULL;
88 /* uncomment the following if you have defined any signals */
89 /* static guint signals[LAST_SIGNAL] = {0}; */
92 modest_main_window_get_type (void)
94 static GType my_type = 0;
96 static const GTypeInfo my_info = {
97 sizeof(ModestMainWindowClass),
99 NULL, /* base finalize */
100 (GClassInitFunc) modest_main_window_class_init,
101 NULL, /* class finalize */
102 NULL, /* class data */
103 sizeof(ModestMainWindow),
105 (GInstanceInitFunc) modest_main_window_init,
108 my_type = g_type_register_static (GTK_TYPE_WINDOW,
116 modest_main_window_class_init (ModestMainWindowClass *klass)
118 GObjectClass *gobject_class;
119 gobject_class = (GObjectClass*) klass;
121 parent_class = g_type_class_peek_parent (klass);
122 gobject_class->finalize = modest_main_window_finalize;
124 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
126 /* signal definitions go here, e.g.: */
127 /* signals[MY_SIGNAL_1] = */
128 /* g_signal_new ("my_signal_1",....); */
129 /* signals[MY_SIGNAL_2] = */
130 /* g_signal_new ("my_signal_2",....); */
135 modest_main_window_init (ModestMainWindow *obj)
137 ModestMainWindowPrivate *priv;
139 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
141 priv->factory = modest_tny_platform_factory_get_instance ();
145 modest_main_window_finalize (GObject *obj)
147 ModestMainWindowPrivate *priv;
148 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
149 if (priv->widget_factory) {
150 g_object_unref (G_OBJECT(priv->widget_factory));
151 priv->widget_factory = NULL;
154 G_OBJECT_CLASS(parent_class)->finalize (obj);
159 on_menu_about (GtkWidget *widget, gpointer data)
162 const gchar *authors[] = {
163 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
166 about = gtk_about_dialog_new ();
167 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
168 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
169 gtk_about_dialog_set_copyright (
170 GTK_ABOUT_DIALOG(about),
171 _("Copyright (c) 2006, Nokia Corporation\n"
172 "All rights reserved."));
173 gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG(about),
174 _("a modest e-mail client\n\n"
175 "design and implementation: Dirk-Jan C. Binnema\n"
176 "contributions from the fine people at KernelConcepts\n\n"
177 "uses the tinymail email framework written by Philip van Hoof"));
178 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
179 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
181 gtk_dialog_run (GTK_DIALOG (about));
182 gtk_widget_destroy(about);
187 on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget)
189 GtkWidget *account_win;
190 ModestMainWindowPrivate *priv;
192 g_return_if_fail (widget);
193 g_return_if_fail (self);
195 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
196 account_win = modest_account_view_window_new (priv->widget_factory);
198 gtk_window_set_transient_for (GTK_WINDOW(account_win),
201 gtk_widget_show (account_win);
206 on_menu_new_message (ModestMainWindow *self, guint action, GtkWidget *widget)
209 ModestMainWindowPrivate *priv;
211 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
213 msg_win = modest_edit_msg_window_new (priv->widget_factory,
214 MODEST_EDIT_TYPE_NEW,
216 gtk_widget_show (msg_win);
220 on_menu_reply_forward (ModestMainWindow *self, guint action, GtkWidget *widget)
223 ModestMainWindowPrivate *priv;
224 ModestHeaderView *header_view;
225 TnyList *header_list;
228 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
230 header_view = modest_widget_factory_get_header_view (priv->widget_factory);
231 header_list = modest_header_view_get_selected_headers (header_view);
234 iter = tny_list_create_iterator (header_list);
238 TnyMsg *msg, *new_msg;
239 ModestEditType edit_type;
241 /* Get msg from header */
242 header = TNY_HEADER (tny_iterator_get_current (iter));
243 folder = tny_header_get_folder (header);
244 msg = tny_folder_get_msg (folder, header);
246 /* FIXME: select proper action */
249 /* TODO: get reply type from config */
251 modest_mail_operation_create_reply_mail (msg,
252 MODEST_MAIL_OPERATION_REPLY_TYPE_CITE,
253 MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
254 edit_type = MODEST_EDIT_TYPE_REPLY;
257 /* TODO: get reply type from config */
259 modest_mail_operation_create_reply_mail (msg,
260 MODEST_MAIL_OPERATION_REPLY_TYPE_QUOTE,
261 MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
262 edit_type = MODEST_EDIT_TYPE_REPLY;
265 /* TODO: get forward type from config */
267 modest_mail_operation_create_forward_mail (msg,
268 MODEST_MAIL_OPERATION_FORWARD_TYPE_INLINE);
269 edit_type = MODEST_EDIT_TYPE_FORWARD;
272 /* Show edit window */
273 msg_win = modest_edit_msg_window_new (priv->widget_factory,
276 gtk_widget_show (msg_win);
278 /* Clean and go on */
279 g_object_unref (new_msg);
280 tny_iterator_next (iter);
282 } while (!tny_iterator_is_done (iter));
287 on_menu_quit (ModestMainWindow *self, guint action, GtkWidget *widget)
290 gtk_widget_destroy (GTK_WIDGET(self));
294 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
295 static GtkItemFactoryEntry menu_items[] = {
296 { "/_File", NULL, NULL, 0, "<Branch>", NULL },
297 { "/File/_New", "<control>N", NULL, 0, "<StockItem>", GTK_STOCK_NEW },
298 { "/File/_Open", "<control>O", NULL, 0, "<StockItem>", GTK_STOCK_OPEN },
299 { "/File/_Save", "<control>S", NULL, 0, "<StockItem>", GTK_STOCK_SAVE },
300 { "/File/Save _As", NULL, NULL, 0, "<Item>", NULL },
301 { "/File/sep1", NULL, NULL, 0, "<Separator>", NULL },
302 { "/File/_Quit", "<CTRL>Q", on_menu_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
304 { "/_Edit", NULL, NULL, 0, "<Branch>", NULL },
305 { "/Edit/_Undo", "<CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_UNDO },
306 { "/Edit/_Redo", "<shift><CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_REDO },
307 { "/File/sep1", NULL, NULL, 0, "<Separator>", NULL },
308 { "/Edit/Cut", "<control>X", NULL, 0, "<StockItem>", GTK_STOCK_CUT },
309 { "/Edit/Copy", "<CTRL>C", NULL, 0, "<StockItem>", GTK_STOCK_COPY },
310 { "/Edit/Paste", NULL, NULL, 0, "<StockItem>", GTK_STOCK_PASTE},
311 { "/Edit/sep1", NULL, NULL, 0, "<Separator>", NULL },
312 { "/Edit/Delete", "<CTRL>Q", NULL, 0, "<Item>" ,NULL},
313 { "/Edit/Select all", "<CTRL>A", NULL, 0, "<Item>" ,NULL},
314 { "/Edit/Deelect all", "<Shift><CTRL>A", NULL, 0, "<Item>" ,NULL},
316 { "/_Actions", NULL, NULL, 0, "<Branch>" ,NULL},
317 { "/Actions/_New Message", NULL, on_menu_new_message, 0, "<Item>",NULL },
318 { "/Actions/_Reply", NULL, NULL, 0, "<Item>" ,NULL},
319 { "/Actions/_Forward", NULL, NULL, 0, "<Item>" ,NULL},
320 { "/Actions/_Bounce", NULL, NULL, 0, "<Item>",NULL },
322 { "/_Options", NULL, NULL, 0, "<Branch>" ,NULL},
323 { "/Options/_Accounts", NULL, on_menu_accounts,0, "<Item>" ,NULL},
324 { "/Options/_Contacts", NULL, NULL, 0, "<Item>" ,NULL },
327 { "/_Help", NULL, NULL, 0, "<Branch>" ,NULL},
328 { "/_Help/About", NULL, on_menu_about, 0, "<StockItem>", GTK_STOCK_ABOUT},
331 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
335 menubar_new (ModestMainWindow *self)
337 GtkItemFactory *item_factory;
338 GtkAccelGroup *accel_group;
340 /* Make an accelerator group (shortcut keys) */
341 accel_group = gtk_accel_group_new ();
343 /* Make an ItemFactory (that makes a menubar) */
344 item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
347 /* This function generates the menu items. Pass the item factory,
348 the number of items in the array, the array itself, and any
349 callback data for the the menu items. */
350 gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
352 ///* Attach the new accelerator group to the window. */
353 gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
355 /* Finally, return the actual menu bar created by the item factory. */
356 return gtk_item_factory_get_widget (item_factory, "<main>");
362 static ModestHeaderView*
363 header_view_new (ModestMainWindow *self)
366 GSList *columns = NULL;
367 ModestHeaderView *header_view;
368 ModestMainWindowPrivate *priv;
369 ModestHeaderViewColumn cols[] = {
370 MODEST_HEADER_VIEW_COLUMN_MSGTYPE,
371 MODEST_HEADER_VIEW_COLUMN_ATTACH,
372 /* MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER, */
373 MODEST_HEADER_VIEW_COLUMN_FROM,
374 MODEST_HEADER_VIEW_COLUMN_SUBJECT,
375 MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE
377 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
379 for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i)
380 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
382 header_view = modest_widget_factory_get_header_view (priv->widget_factory);
383 modest_header_view_set_columns (header_view, columns);
384 g_slist_free (columns);
390 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
391 ModestMainWindow *self)
393 GtkTreeSelection *sel;
396 ModestMainWindowPrivate *priv;
398 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
401 case MODEST_TOOLBAR_BUTTON_NEW_MAIL:
402 on_menu_new_message (self, 0, NULL);
404 case MODEST_TOOLBAR_BUTTON_REPLY:
405 on_menu_reply_forward (self, 1, NULL);
407 case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
408 on_menu_reply_forward (self, 2, NULL);
410 case MODEST_TOOLBAR_BUTTON_FORWARD:
411 on_menu_reply_forward (self, 3, NULL);
413 case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
416 case MODEST_TOOLBAR_BUTTON_NEXT:
417 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->header_view));
419 gtk_tree_selection_get_selected (sel, &model, &iter);
420 gtk_tree_model_iter_next (model, &iter);
421 gtk_tree_selection_select_iter (sel, &iter);
424 case MODEST_TOOLBAR_BUTTON_PREV:
426 /* gtk_tree_selection_get_selected (sel, &model, &iter); */
427 /* gtk_tree_model_iter_prev (model, &iter); */
428 /* gtk_tree_selection_select_iter (sel, &iter); */
432 case MODEST_TOOLBAR_BUTTON_DELETE:
435 g_printerr ("modest: key %d pressed\n", button_id);
439 static ModestToolbar*
440 toolbar_new (ModestMainWindow *self)
443 ModestToolbar *toolbar;
444 GSList *buttons = NULL;
445 ModestMainWindowPrivate *priv;
447 ModestToolbarButton button_ids[] = {
448 MODEST_TOOLBAR_BUTTON_NEW_MAIL,
449 MODEST_TOOLBAR_BUTTON_REPLY,
450 MODEST_TOOLBAR_BUTTON_REPLY_ALL,
451 MODEST_TOOLBAR_BUTTON_FORWARD,
452 MODEST_TOOLBAR_SEPARATOR,
453 MODEST_TOOLBAR_BUTTON_SEND_RECEIVE,
454 MODEST_TOOLBAR_SEPARATOR,
455 MODEST_TOOLBAR_BUTTON_PREV,
456 MODEST_TOOLBAR_BUTTON_NEXT,
457 MODEST_TOOLBAR_SEPARATOR,
458 MODEST_TOOLBAR_BUTTON_DELETE
461 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
463 for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
464 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
466 toolbar = modest_widget_factory_get_main_toolbar (priv->widget_factory, buttons);
467 g_slist_free (buttons);
469 g_signal_connect (G_OBJECT(toolbar), "button_clicked",
470 G_CALLBACK(on_toolbar_button_clicked), self);
478 restore_sizes (ModestMainWindow *self)
481 ModestMainWindowPrivate *priv;
483 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
484 conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
486 modest_widget_memory_restore_settings (conf,GTK_WIDGET(self),
487 "modest-main-window");
488 modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->folder_paned),
489 "modest-folder-paned");
490 modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->msg_paned),
492 modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->main_paned),
493 "modest-main-paned");
498 save_sizes (ModestMainWindow *self)
500 ModestMainWindowPrivate *priv;
503 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
504 conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
506 modest_widget_memory_save_settings (conf,GTK_WIDGET(self),
507 "modest-main-window");
508 modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->folder_paned),
509 "modest-folder-paned");
510 modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->msg_paned),
512 modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->main_paned),
513 "modest-main-paned");
517 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
521 win = gtk_scrolled_window_new (NULL, NULL);
522 gtk_scrolled_window_set_policy
523 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
524 GTK_POLICY_AUTOMATIC);
527 gtk_scrolled_window_add_with_viewport
528 (GTK_SCROLLED_WINDOW(win), widget);
530 gtk_container_add (GTK_CONTAINER(win),
538 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self)
547 GtkWidget *favorites;
549 GtkTreeViewColumn *col;
551 store = gtk_tree_store_new (1, G_TYPE_STRING);
552 favorites = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
553 col = gtk_tree_view_column_new_with_attributes (_("Favorites"),
554 gtk_cell_renderer_text_new(),
557 gtk_tree_view_append_column (GTK_TREE_VIEW(favorites), col);
558 gtk_widget_show_all (favorites);
560 g_object_unref (G_OBJECT(store));
568 modest_main_window_new (ModestWidgetFactory *widget_factory)
571 ModestMainWindowPrivate *priv;
573 GtkWidget *main_vbox;
574 GtkWidget *status_hbox;
575 GtkWidget *header_win, *folder_win, *favorites_win;
577 g_return_val_if_fail (widget_factory, NULL);
579 obj = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
580 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
582 g_object_ref (widget_factory);
583 priv->widget_factory = widget_factory;
585 /* widgets from factory */
586 priv->folder_view = modest_widget_factory_get_folder_view (widget_factory);
587 priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
588 priv->msg_preview = modest_widget_factory_get_msg_preview (widget_factory);
590 folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
592 header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
594 favorites_win = wrapped_in_scrolled_window (favorites_view(),FALSE);
597 priv->menubar = menubar_new (MODEST_MAIN_WINDOW(obj));
598 priv->toolbar = GTK_WIDGET(toolbar_new (MODEST_MAIN_WINDOW(obj)));
601 priv->folder_paned = gtk_vpaned_new ();
602 priv->msg_paned = gtk_vpaned_new ();
603 priv->main_paned = gtk_hpaned_new ();
604 gtk_paned_add1 (GTK_PANED(priv->main_paned), priv->folder_paned);
605 gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
606 gtk_paned_add1 (GTK_PANED(priv->folder_paned), favorites_win);
607 gtk_paned_add2 (GTK_PANED(priv->folder_paned), folder_win);
608 gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
609 gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
611 gtk_widget_show (GTK_WIDGET(priv->header_view));
612 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
615 /* status bar / progress */
616 status_hbox = gtk_hbox_new (FALSE, 0);
617 gtk_box_pack_start (GTK_BOX(status_hbox),
618 modest_widget_factory_get_folder_info_label (widget_factory),
620 gtk_box_pack_start (GTK_BOX(status_hbox),
621 modest_widget_factory_get_status_bar(widget_factory),
623 gtk_box_pack_start (GTK_BOX(status_hbox),
624 modest_widget_factory_get_progress_bar(widget_factory),
626 gtk_box_pack_start (GTK_BOX(status_hbox),
627 modest_widget_factory_get_online_toggle(widget_factory),
630 /* putting it all together... */
631 main_vbox = gtk_vbox_new (FALSE, 6);
632 gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
633 gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
634 gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE,0);
635 gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 0);
637 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
638 restore_sizes (MODEST_MAIN_WINDOW(obj));
640 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
641 gtk_window_set_icon (GTK_WINDOW(obj),
642 modest_icon_factory_get_icon (MODEST_APP_ICON));
644 gtk_widget_show_all (main_vbox);
646 g_signal_connect (G_OBJECT(obj), "delete-event",
647 G_CALLBACK(on_delete_event), obj);
649 return GTK_WIDGET(obj);