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>
32 #include <gtk/gtkaboutdialog.h>
33 #include <gtk/gtktreeviewcolumn.h>
35 #include <modest-widget-memory.h>
36 #include <modest-icon-factory.h>
38 #include <widgets/modest-toolbar.h>
40 #include "modest-main-window.h"
41 #include "modest-account-view-window.h"
42 #include "modest-account-mgr.h"
43 #include "modest-conf.h"
44 #include "modest-edit-msg-window.h"
45 #include "modest-icon-names.h"
46 #include "modest-tny-platform-factory.h"
47 #include "modest-tny-msg-actions.h"
48 #include "modest-mail-operation.h"
50 /* 'private'/'protected' functions */
51 static void modest_main_window_class_init (ModestMainWindowClass *klass);
52 static void modest_main_window_init (ModestMainWindow *obj);
53 static void modest_main_window_finalize (GObject *obj);
55 static void restore_sizes (ModestMainWindow *self);
56 static void save_sizes (ModestMainWindow *self);
65 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
66 struct _ModestMainWindowPrivate {
68 GtkUIManager *ui_manager;
73 GtkWidget *folder_paned;
75 GtkWidget *main_paned;
77 ModestWidgetFactory *widget_factory;
78 TnyPlatformFactory *factory;
80 ModestHeaderView *header_view;
81 ModestFolderView *folder_view;
82 ModestMsgView *msg_preview;
86 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
87 MODEST_TYPE_MAIN_WINDOW, \
88 ModestMainWindowPrivate))
90 static GtkWindowClass *parent_class = NULL;
92 /* uncomment the following if you have defined any signals */
93 /* static guint signals[LAST_SIGNAL] = {0}; */
96 modest_main_window_get_type (void)
98 static GType my_type = 0;
100 static const GTypeInfo my_info = {
101 sizeof(ModestMainWindowClass),
102 NULL, /* base init */
103 NULL, /* base finalize */
104 (GClassInitFunc) modest_main_window_class_init,
105 NULL, /* class finalize */
106 NULL, /* class data */
107 sizeof(ModestMainWindow),
109 (GInstanceInitFunc) modest_main_window_init,
112 my_type = g_type_register_static (HILDON_TYPE_WINDOW,
120 modest_main_window_class_init (ModestMainWindowClass *klass)
122 GObjectClass *gobject_class;
123 gobject_class = (GObjectClass*) klass;
125 parent_class = g_type_class_peek_parent (klass);
126 gobject_class->finalize = modest_main_window_finalize;
128 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
130 /* signal definitions go here, e.g.: */
131 /* signals[MY_SIGNAL_1] = */
132 /* g_signal_new ("my_signal_1",....); */
133 /* signals[MY_SIGNAL_2] = */
134 /* g_signal_new ("my_signal_2",....); */
139 modest_main_window_init (ModestMainWindow *obj)
141 ModestMainWindowPrivate *priv;
143 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
145 priv->factory = modest_tny_platform_factory_get_instance ();
149 modest_main_window_finalize (GObject *obj)
151 ModestMainWindowPrivate *priv;
152 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
153 if (priv->widget_factory) {
154 g_object_unref (G_OBJECT(priv->widget_factory));
155 priv->widget_factory = NULL;
158 G_OBJECT_CLASS(parent_class)->finalize (obj);
163 on_menu_about (GtkWidget *widget, gpointer data)
166 const gchar *authors[] = {
167 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
170 about = gtk_about_dialog_new ();
171 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
172 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
173 gtk_about_dialog_set_copyright (
174 GTK_ABOUT_DIALOG(about),
175 _("Copyright (c) 2006, Nokia Corporation\n"
176 "All rights reserved."));
177 gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG(about),
178 _("a modest e-mail client\n\n"
179 "design and implementation: Dirk-Jan C. Binnema\n"
180 "contributions from the fine people at KernelConcepts\n\n"
181 "uses the tinymail email framework written by Philip van Hoof"));
182 gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
183 gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
185 gtk_dialog_run (GTK_DIALOG (about));
186 gtk_widget_destroy(about);
191 on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget)
193 GtkWidget *account_win;
194 ModestMainWindowPrivate *priv;
196 g_return_if_fail (widget);
197 g_return_if_fail (self);
199 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
200 account_win = modest_account_view_window_new (priv->widget_factory);
202 gtk_window_set_transient_for (GTK_WINDOW(account_win),
205 gtk_widget_show (account_win);
210 on_menu_new_message (ModestMainWindow *self, guint action, GtkWidget *widget)
213 ModestMainWindowPrivate *priv;
215 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
217 msg_win = modest_edit_msg_window_new (priv->widget_factory,
218 MODEST_EDIT_TYPE_NEW,
220 gtk_widget_show (msg_win);
224 on_menu_reply_forward (ModestMainWindow *self, guint action, GtkWidget *widget)
227 ModestMainWindowPrivate *priv;
228 ModestHeaderView *header_view;
229 TnyList *header_list;
232 gchar *reply_key, *forward_key;
233 ModestMailOperationReplyType reply_type;
234 ModestMailOperationForwardType forward_type;
238 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
239 conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
241 header_view = modest_widget_factory_get_header_view (priv->widget_factory);
242 header_list = modest_header_view_get_selected_headers (header_view);
244 /* Get reply and forward types */
246 reply_key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE, MODEST_CONF_REPLY_TYPE);
247 reply_type = modest_conf_get_int (conf, reply_key, &error);
249 g_warning ("key %s not defined", reply_key);
250 reply_type = MODEST_MAIL_OPERATION_REPLY_TYPE_CITE;
251 g_error_free (error);
256 forward_key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE, MODEST_CONF_FORWARD_TYPE);
257 forward_type = modest_conf_get_int (conf, forward_key, NULL);
259 g_warning ("key %s not defined", forward_key);
260 reply_type = MODEST_MAIL_OPERATION_FORWARD_TYPE_INLINE;
261 g_error_free (error);
263 g_free (forward_key);
266 iter = tny_list_create_iterator (header_list);
268 TnyHeader *header, *new_header;
270 TnyMsg *msg, *new_msg;
271 ModestEditType edit_type;
273 /* Get msg from header */
274 header = TNY_HEADER (tny_iterator_get_current (iter));
275 folder = tny_header_get_folder (header);
276 msg = tny_folder_get_msg (folder, header, NULL); /* FIXME */
278 from = modest_folder_view_get_selected_account (priv->folder_view);
280 /* FIXME: select proper action */
284 modest_mail_operation_create_reply_mail (msg, from, reply_type,
285 MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
286 edit_type = MODEST_EDIT_TYPE_REPLY;
290 modest_mail_operation_create_reply_mail (msg, from, reply_type,
291 MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
292 edit_type = MODEST_EDIT_TYPE_REPLY;
296 modest_mail_operation_create_forward_mail (msg, from, forward_type);
297 edit_type = MODEST_EDIT_TYPE_FORWARD;
300 g_warning ("unexpected action type: %d", action);
304 new_header = tny_msg_get_header (new_msg);
305 tny_header_set_from (new_header,
306 modest_folder_view_get_selected_account (priv->folder_view));
308 /* Show edit window */
309 msg_win = modest_edit_msg_window_new (priv->widget_factory,
312 gtk_widget_show (msg_win);
314 /* Clean and go on */
315 g_object_unref (new_msg);
316 tny_iterator_next (iter);
318 } while (!tny_iterator_is_done (iter));
323 on_menu_quit (ModestMainWindow *self, guint action, GtkWidget *widget)
326 gtk_widget_destroy (GTK_WIDGET(self));
330 on_menu_delete (ModestMainWindow *self, guint action, GtkWidget *widget)
332 ModestMainWindowPrivate *priv;
333 ModestHeaderView *header_view;
334 TnyList *header_list;
338 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
340 header_view = modest_widget_factory_get_header_view (priv->widget_factory);
341 header_list = modest_header_view_get_selected_headers (header_view);
344 iter = tny_list_create_iterator (header_list);
345 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
346 if (GTK_IS_TREE_MODEL_SORT (model))
347 model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
350 ModestMailOperation *mail_op;
352 header = TNY_HEADER (tny_iterator_get_current (iter));
353 /* TODO: thick grain mail operation involving
354 a list of objects. Composite pattern ??? */
355 mail_op = modest_mail_operation_new ();
358 modest_mail_operation_remove_msg (mail_op, header, TRUE);
360 /* Remove from tree model */
361 tny_list_remove (TNY_LIST (model), G_OBJECT (header));
363 g_object_unref (G_OBJECT (mail_op));
364 g_object_unref (header);
365 tny_iterator_next (iter);
367 } while (!tny_iterator_is_done (iter));
372 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
373 static const gchar* UI_DEF=
374 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
377 " <menu name=\"Message\" \"MenuMessage\">"
378 " <menuitem name=\"New\" action=\"on_menu_new_message\" />"
380 // " <menu name=\"JustifyMenu\" action=\"JustifyMenuAction\">"
381 // " <menuitem name=\"Left\" action=\"justify-left\"/>"
382 // " <menuitem name=\"Centre\" action=\"justify-center\"/>"
383 // " <menuitem name=\"Right\" action=\"justify-right\"/>"
384 // " <menuitem name=\"Fill\" action=\"justify-fill\"/>"
390 get_menu (ModestMainWindow *self)
395 ModestMainWindowPrivate *priv;
396 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
398 priv->ui_manager = gtk_ui_manager_new ();
400 gtk_ui_manager_add_ui_from_string (priv->ui_manager,
401 UI_DEF, strlen(UI_DEF),
404 w = gtk_ui_manager_get_widget (priv->ui_manager, "/popup");
405 g_warning ("==> GtkMenu? ==> %s", GTK_IS_MENU(w) ? "yes" : "no");
412 static ModestHeaderView*
413 header_view_new (ModestMainWindow *self)
416 GSList *columns = NULL;
417 ModestHeaderView *header_view;
418 ModestMainWindowPrivate *priv;
419 ModestHeaderViewColumn cols[] = {
420 MODEST_HEADER_VIEW_COLUMN_MSGTYPE,
421 MODEST_HEADER_VIEW_COLUMN_ATTACH,
422 /* MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER, */
423 MODEST_HEADER_VIEW_COLUMN_FROM,
424 MODEST_HEADER_VIEW_COLUMN_SUBJECT,
425 MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE
427 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
429 for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i)
430 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
432 header_view = modest_widget_factory_get_header_view (priv->widget_factory);
433 modest_header_view_set_columns (header_view, columns);
434 g_slist_free (columns);
440 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
441 ModestMainWindow *self)
443 GtkTreeSelection *sel;
446 ModestMainWindowPrivate *priv;
448 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
451 case MODEST_TOOLBAR_BUTTON_NEW_MAIL:
452 on_menu_new_message (self, 0, NULL);
454 case MODEST_TOOLBAR_BUTTON_REPLY:
455 on_menu_reply_forward (self, 1, NULL);
457 case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
458 on_menu_reply_forward (self, 2, NULL);
460 case MODEST_TOOLBAR_BUTTON_FORWARD:
461 on_menu_reply_forward (self, 3, NULL);
463 case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
466 case MODEST_TOOLBAR_BUTTON_NEXT:
467 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->header_view));
469 gtk_tree_selection_get_selected (sel, &model, &iter);
470 gtk_tree_model_iter_next (model, &iter);
471 gtk_tree_selection_select_iter (sel, &iter);
474 case MODEST_TOOLBAR_BUTTON_PREV:
476 /* gtk_tree_selection_get_selected (sel, &model, &iter); */
477 /* gtk_tree_model_iter_prev (model, &iter); */
478 /* gtk_tree_selection_select_iter (sel, &iter); */
482 case MODEST_TOOLBAR_BUTTON_DELETE:
483 on_menu_delete (self, 0, GTK_WIDGET (toolbar));
487 g_printerr ("modest: key %d pressed\n", button_id);
491 static ModestToolbar*
492 toolbar_new (ModestMainWindow *self)
495 ModestToolbar *toolbar;
496 GSList *buttons = NULL;
497 ModestMainWindowPrivate *priv;
499 ModestToolbarButton button_ids[] = {
500 MODEST_TOOLBAR_BUTTON_NEW_MAIL,
501 MODEST_TOOLBAR_BUTTON_REPLY,
502 MODEST_TOOLBAR_BUTTON_REPLY_ALL,
503 MODEST_TOOLBAR_BUTTON_FORWARD,
504 MODEST_TOOLBAR_SEPARATOR,
505 MODEST_TOOLBAR_BUTTON_SEND_RECEIVE,
506 MODEST_TOOLBAR_SEPARATOR,
507 MODEST_TOOLBAR_BUTTON_PREV,
508 MODEST_TOOLBAR_BUTTON_NEXT,
509 MODEST_TOOLBAR_SEPARATOR,
510 MODEST_TOOLBAR_BUTTON_DELETE
513 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
515 for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
516 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
518 toolbar = modest_widget_factory_get_main_toolbar (priv->widget_factory, buttons);
519 g_slist_free (buttons);
521 g_signal_connect (G_OBJECT(toolbar), "button_clicked",
522 G_CALLBACK(on_toolbar_button_clicked), self);
530 restore_sizes (ModestMainWindow *self)
533 ModestMainWindowPrivate *priv;
535 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
536 conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
538 modest_widget_memory_restore_settings (conf,GTK_WIDGET(self),
539 "modest-main-window");
540 modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->folder_paned),
541 "modest-folder-paned");
542 modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->msg_paned),
544 modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->main_paned),
545 "modest-main-paned");
550 save_sizes (ModestMainWindow *self)
552 ModestMainWindowPrivate *priv;
555 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
556 conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
558 modest_widget_memory_save_settings (conf,GTK_WIDGET(self),
559 "modest-main-window");
560 modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->folder_paned),
561 "modest-folder-paned");
562 modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->msg_paned),
564 modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->main_paned),
565 "modest-main-paned");
569 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
573 win = gtk_scrolled_window_new (NULL, NULL);
574 gtk_scrolled_window_set_policy
575 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
576 GTK_POLICY_AUTOMATIC);
579 gtk_scrolled_window_add_with_viewport
580 (GTK_SCROLLED_WINDOW(win), widget);
582 gtk_container_add (GTK_CONTAINER(win),
590 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self)
599 GtkWidget *favorites;
601 GtkTreeViewColumn *col;
603 store = gtk_tree_store_new (1, G_TYPE_STRING);
604 favorites = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
605 col = gtk_tree_view_column_new_with_attributes (_("Favorites"),
606 gtk_cell_renderer_text_new(),
609 gtk_tree_view_append_column (GTK_TREE_VIEW(favorites), col);
610 gtk_widget_show_all (favorites);
612 g_object_unref (G_OBJECT(store));
620 modest_main_window_new (ModestWidgetFactory *widget_factory)
623 ModestMainWindowPrivate *priv;
625 GtkWidget *main_vbox;
626 GtkWidget *status_hbox;
627 GtkWidget *header_win, *folder_win, *favorites_win;
629 g_return_val_if_fail (widget_factory, NULL);
631 obj = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
632 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
634 g_object_ref (widget_factory);
635 priv->widget_factory = widget_factory;
637 /* widgets from factory */
638 priv->folder_view = modest_widget_factory_get_folder_view (widget_factory);
639 priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
640 priv->msg_preview = modest_widget_factory_get_msg_preview (widget_factory);
642 folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
644 header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
647 priv->menu = get_menu (MODEST_MAIN_WINDOW(obj));
648 hildon_window_set_menu (HILDON_WINDOW(obj), GTK_MENU(priv->menu));
650 priv->toolbar = GTK_WIDGET(toolbar_new (MODEST_MAIN_WINDOW(obj)));
653 priv->msg_paned = gtk_vpaned_new ();
654 priv->main_paned = gtk_hpaned_new ();
656 gtk_paned_add1 (GTK_PANED(priv->main_paned), folder_win);
657 gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
659 gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
660 gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
662 gtk_widget_show (GTK_WIDGET(priv->header_view));
663 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
665 /* status bar / progress */
666 status_hbox = gtk_hbox_new (FALSE, 0);
667 gtk_box_pack_start (GTK_BOX(status_hbox),
668 modest_widget_factory_get_folder_info_label (widget_factory),
670 gtk_box_pack_start (GTK_BOX(status_hbox),
671 modest_widget_factory_get_status_bar(widget_factory),
673 gtk_box_pack_start (GTK_BOX(status_hbox),
674 modest_widget_factory_get_progress_bar(widget_factory),
676 gtk_box_pack_start (GTK_BOX(status_hbox),
677 modest_widget_factory_get_online_toggle(widget_factory),
680 /* putting it all together... */
681 main_vbox = gtk_vbox_new (FALSE, 6);
682 gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE,0);
683 gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
684 gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 0);
686 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
687 restore_sizes (MODEST_MAIN_WINDOW(obj));
689 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
690 gtk_window_set_icon (GTK_WINDOW(obj),
691 modest_icon_factory_get_icon (MODEST_APP_ICON));
693 gtk_widget_show_all (main_vbox);
695 g_signal_connect (G_OBJECT(obj), "delete-event",
696 G_CALLBACK(on_delete_event), obj);
698 return GTK_WIDGET(obj);