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>" },
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>" },
241 { "/File/sep1", NULL, NULL, 0, "<Separator>" },
242 { "/File/_Quit", "<CTRL>Q", on_menu_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
244 { "/_Edit", NULL, NULL, 0, "<Branch>" },
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>" },
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>" },
252 { "/Edit/Delete", "<CTRL>Q", NULL, 0, "<Item>" },
253 { "/Edit/Select all", "<CTRL>A", NULL, 0, "<Item>" },
254 { "/Edit/Deelect all", "<Shift><CTRL>A", NULL, 0, "<Item>" },
256 { "/_Actions", NULL, NULL, 0, "<Branch>" },
257 { "/Actions/_New Message", NULL, on_menu_new_message, 0, "<Item>" },
258 { "/Actions/_Reply", NULL, NULL, 0, "<Item>" },
259 { "/Actions/_Forward", NULL, NULL, 0, "<Item>" },
260 { "/Actions/_Bounce", NULL, NULL, 0, "<Item>" },
262 { "/_Options", NULL, NULL, 0, "<Branch>" },
263 { "/Options/_Accounts", NULL, on_menu_accounts,0, "<Item>" },
264 { "/Options/_Contacts", NULL, NULL, 0, "<Item>" },
267 { "/_Help", NULL, NULL, 0, "<Branch>" },
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)
334 case MODEST_TOOLBAR_BUTTON_NEW_MAIL:
335 on_menu_new_message (self, 0, NULL);
338 case MODEST_TOOLBAR_BUTTON_REPLY:
339 case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
340 case MODEST_TOOLBAR_BUTTON_FORWARD:
341 case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
342 case MODEST_TOOLBAR_BUTTON_NEXT:
343 case MODEST_TOOLBAR_BUTTON_PREV:
344 case MODEST_TOOLBAR_BUTTON_DELETE:
347 g_printerr ("modest: key %d pressed\n", button_id);
351 static ModestToolbar*
352 toolbar_new (ModestMainWindow *self)
355 ModestToolbar *toolbar;
356 GSList *buttons = NULL;
357 ModestMainWindowPrivate *priv;
359 ModestToolbarButton button_ids[] = {
360 MODEST_TOOLBAR_BUTTON_NEW_MAIL,
361 MODEST_TOOLBAR_BUTTON_REPLY,
362 MODEST_TOOLBAR_BUTTON_REPLY_ALL,
363 MODEST_TOOLBAR_BUTTON_FORWARD,
364 MODEST_TOOLBAR_SEPARATOR,
365 MODEST_TOOLBAR_BUTTON_SEND_RECEIVE,
366 MODEST_TOOLBAR_SEPARATOR,
367 MODEST_TOOLBAR_BUTTON_NEXT,
368 MODEST_TOOLBAR_BUTTON_PREV,
369 MODEST_TOOLBAR_SEPARATOR,
370 MODEST_TOOLBAR_BUTTON_DELETE
373 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
375 for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
376 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
378 toolbar = modest_widget_factory_get_main_toolbar (priv->factory, buttons);
379 g_slist_free (buttons);
381 g_signal_connect (G_OBJECT(toolbar), "button_clicked",
382 G_CALLBACK(on_toolbar_button_clicked), self);
390 restore_sizes (ModestMainWindow *self)
392 ModestMainWindowPrivate *priv;
393 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
395 modest_widget_memory_restore_settings (priv->conf,GTK_WIDGET(self),
396 "modest-main-window");
397 modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(priv->folder_paned),
398 "modest-folder-paned");
399 modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(priv->msg_paned),
401 modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(priv->main_paned),
402 "modest-main-paned");
407 save_sizes (ModestMainWindow *self)
409 ModestMainWindowPrivate *priv;
411 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
413 modest_widget_memory_save_settings (priv->conf,GTK_WIDGET(self),
414 "modest-main-window");
415 modest_widget_memory_save_settings (priv->conf, GTK_WIDGET(priv->folder_paned),
416 "modest-folder-paned");
417 modest_widget_memory_save_settings (priv->conf, GTK_WIDGET(priv->msg_paned),
419 modest_widget_memory_save_settings (priv->conf, GTK_WIDGET(priv->main_paned),
420 "modest-main-paned");
424 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
428 win = gtk_scrolled_window_new (NULL, NULL);
429 gtk_scrolled_window_set_policy
430 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
431 GTK_POLICY_AUTOMATIC);
434 gtk_scrolled_window_add_with_viewport
435 (GTK_SCROLLED_WINDOW(win), widget);
437 gtk_container_add (GTK_CONTAINER(win),
445 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self)
454 GtkWidget *favorites;
456 GtkTreeViewColumn *col;
458 store = gtk_tree_store_new (1, G_TYPE_STRING);
459 favorites = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
460 col = gtk_tree_view_column_new_with_attributes (_("Favorites"),
461 gtk_cell_renderer_text_new(),
464 gtk_tree_view_append_column (GTK_TREE_VIEW(favorites), col);
465 gtk_widget_show_all (favorites);
467 g_object_unref (G_OBJECT(store));
475 modest_main_window_new (ModestConf *conf, ModestAccountMgr *account_mgr,
476 ModestWidgetFactory *factory)
479 ModestMainWindowPrivate *priv;
481 GtkWidget *main_vbox;
482 GtkWidget *status_hbox;
483 GtkWidget *header_win, *folder_win, *favorites_win;
485 g_return_val_if_fail (factory, NULL);
486 g_return_val_if_fail (conf, NULL);
488 obj = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
489 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
491 g_object_ref (factory);
492 priv->factory = factory;
497 g_object_ref (account_mgr);
498 priv->account_mgr = account_mgr;
500 /* widgets from factory */
501 priv->folder_view = modest_widget_factory_get_folder_view (factory);
502 priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
503 priv->msg_preview = modest_widget_factory_get_msg_preview (factory);
505 folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
507 header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
509 favorites_win = wrapped_in_scrolled_window (favorites_view(),FALSE);
512 priv->menubar = menubar_new (MODEST_MAIN_WINDOW(obj));
513 priv->toolbar = GTK_WIDGET(toolbar_new (MODEST_MAIN_WINDOW(obj)));
516 priv->folder_paned = gtk_vpaned_new ();
517 priv->msg_paned = gtk_vpaned_new ();
518 priv->main_paned = gtk_hpaned_new ();
519 gtk_paned_add1 (GTK_PANED(priv->main_paned), priv->folder_paned);
520 gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
521 gtk_paned_add1 (GTK_PANED(priv->folder_paned), favorites_win);
522 gtk_paned_add2 (GTK_PANED(priv->folder_paned), folder_win);
523 gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
524 gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
526 gtk_widget_show (GTK_WIDGET(priv->header_view));
527 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
530 /* status bar / progress */
531 status_hbox = gtk_hbox_new (FALSE, 0);
532 gtk_box_pack_start (GTK_BOX(status_hbox),
533 modest_widget_factory_get_folder_info_label (factory),
535 gtk_box_pack_start (GTK_BOX(status_hbox),
536 modest_widget_factory_get_status_bar(factory),
538 gtk_box_pack_start (GTK_BOX(status_hbox),
539 modest_widget_factory_get_progress_bar(factory),
541 gtk_box_pack_start (GTK_BOX(status_hbox),
542 modest_widget_factory_get_online_toggle(factory),
545 /* putting it all together... */
546 main_vbox = gtk_vbox_new (FALSE, 6);
547 gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
548 gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
549 gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE,0);
550 gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 0);
552 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
553 restore_sizes (MODEST_MAIN_WINDOW(obj));
555 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
556 gtk_window_set_icon (GTK_WINDOW(obj),
557 modest_icon_factory_get_icon (MODEST_APP_ICON));
559 gtk_widget_show_all (main_vbox);
561 g_signal_connect (G_OBJECT(obj), "delete-event",
562 G_CALLBACK(on_delete_event), obj);
564 return GTK_WIDGET(obj);