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-main-window.h"
31 #include "modest-account-view-window.h"
32 #include "modest-msg-window.h"
34 /* 'private'/'protected' functions */
35 static void modest_main_window_class_init (ModestMainWindowClass *klass);
36 static void modest_main_window_init (ModestMainWindow *obj);
37 static void modest_main_window_finalize (GObject *obj);
46 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
47 struct _ModestMainWindowPrivate {
50 GtkWidget *progress_bar;
51 GtkWidget *status_bar;
52 GtkWidget *folder_paned;
55 ModestWidgetFactory *widget_factory;
58 ModestTnyHeaderTreeView *header_view;
59 ModestTnyFolderTreeView *folder_view;
60 ModestTnyMsgView *msg_preview;
64 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
65 MODEST_TYPE_MAIN_WINDOW, \
66 ModestMainWindowPrivate))
68 static GtkWindowClass *parent_class = NULL;
70 /* uncomment the following if you have defined any signals */
71 /* static guint signals[LAST_SIGNAL] = {0}; */
74 modest_main_window_get_type (void)
76 static GType my_type = 0;
78 static const GTypeInfo my_info = {
79 sizeof(ModestMainWindowClass),
81 NULL, /* base finalize */
82 (GClassInitFunc) modest_main_window_class_init,
83 NULL, /* class finalize */
84 NULL, /* class data */
85 sizeof(ModestMainWindow),
87 (GInstanceInitFunc) modest_main_window_init,
89 my_type = g_type_register_static (GTK_TYPE_WINDOW,
97 modest_main_window_class_init (ModestMainWindowClass *klass)
99 GObjectClass *gobject_class;
100 gobject_class = (GObjectClass*) klass;
102 parent_class = g_type_class_peek_parent (klass);
103 gobject_class->finalize = modest_main_window_finalize;
105 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
107 /* signal definitions go here, e.g.: */
108 /* signals[MY_SIGNAL_1] = */
109 /* g_signal_new ("my_signal_1",....); */
110 /* signals[MY_SIGNAL_2] = */
111 /* g_signal_new ("my_signal_2",....); */
116 modest_main_window_init (ModestMainWindow *obj)
118 ModestMainWindowPrivate *priv;
120 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
122 priv->widget_factory = NULL;
126 modest_main_window_finalize (GObject *obj)
128 ModestMainWindowPrivate *priv;
130 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
132 if (priv->widget_factory) {
133 g_object_unref (G_OBJECT(priv->widget_factory));
134 priv->widget_factory = NULL;
138 g_object_unref (G_OBJECT(priv->conf));
141 G_OBJECT_CLASS(parent_class)->finalize (obj);
146 on_menu_about (GtkWidget *widget, gpointer data)
150 about = gtk_about_dialog_new ();
151 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
152 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
153 gtk_about_dialog_set_copyright (
154 GTK_ABOUT_DIALOG(about),
155 _("Copyright (c) 2006, Nokia Corporation\n"
156 "All rights reserved."));
157 gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG(about),
158 _("a modest e-mail client"));
159 gtk_dialog_run (GTK_DIALOG (about));
160 gtk_widget_destroy(about);
165 on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget)
167 GtkWidget *account_win;
168 ModestMainWindowPrivate *priv;
169 ModestAccountMgr *account_mgr;
171 g_return_if_fail (widget);
172 g_return_if_fail (self);
174 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
175 account_win = modest_account_view_window_new (priv->conf,
176 priv->widget_factory);
177 gtk_widget_show (account_win);
182 on_menu_new_message (ModestMainWindow *self, guint action, GtkWidget *widget)
186 msg_win = modest_msg_window_new (MODEST_MSG_WINDOW_TYPE_NEW,
189 gtk_widget_show (msg_win);
194 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
195 static GtkItemFactoryEntry menu_items[] = {
196 { "/_File", NULL, NULL, 0, "<Branch>" },
197 { "/File/_New", "<control>N", NULL, 0, "<StockItem>", GTK_STOCK_NEW },
198 { "/File/_Open", "<control>O", NULL, 0, "<StockItem>", GTK_STOCK_OPEN },
199 { "/File/_Save", "<control>S", NULL, 0, "<StockItem>", GTK_STOCK_SAVE },
200 { "/File/Save _As", NULL, NULL, 0, "<Item>" },
201 { "/File/sep1", NULL, NULL, 0, "<Separator>" },
202 { "/File/_Quit", "<CTRL>Q", gtk_main_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
204 { "/_Edit", NULL, NULL, 0, "<Branch>" },
205 { "/Edit/_Undo", "<CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_UNDO },
206 { "/Edit/_Redo", "<shift><CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_REDO },
207 { "/File/sep1", NULL, NULL, 0, "<Separator>" },
208 { "/Edit/Cut", "<control>X", NULL, 0, "<StockItem>", GTK_STOCK_CUT },
209 { "/Edit/Copy", "<CTRL>C", NULL, 0, "<StockItem>", GTK_STOCK_COPY },
210 { "/Edit/Paste", NULL, NULL, 0, "<StockItem>", GTK_STOCK_PASTE},
211 { "/Edit/sep1", NULL, NULL, 0, "<Separator>" },
212 { "/Edit/Delete", "<CTRL>Q", NULL, 0, "<Item>" },
213 { "/Edit/Select all", "<CTRL>A", NULL, 0, "<Item>" },
214 { "/Edit/Deelect all", "<Shift><CTRL>A", NULL, 0, "<Item>" },
216 { "/_Actions", NULL, NULL, 0, "<Branch>" },
217 { "/Actions/_New Message", NULL, on_menu_new_message, 0, "<Item>" },
218 { "/Actions/_Reply", NULL, NULL, 0, "<Item>" },
219 { "/Actions/_Forward", NULL, NULL, 0, "<Item>" },
220 { "/Actions/_Bounce", NULL, NULL, 0, "<Item>" },
222 { "/_Options", NULL, NULL, 0, "<Branch>" },
223 { "/Options/_Accounts", NULL, on_menu_accounts,0, "<Item>" },
224 { "/Options/_Contacts", NULL, NULL, 0, "<Item>" },
227 { "/_Help", NULL, NULL, 0, "<Branch>" },
228 { "/_Help/About", NULL, on_menu_about, 0, "<StockItem>", GTK_STOCK_ABOUT},
231 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
235 menubar_new (ModestMainWindow *self)
237 GtkItemFactory *item_factory;
238 GtkAccelGroup *accel_group;
240 /* Make an accelerator group (shortcut keys) */
241 accel_group = gtk_accel_group_new ();
243 /* Make an ItemFactory (that makes a menubar) */
244 item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
247 /* This function generates the menu items. Pass the item factory,
248 the number of items in the array, the array itself, and any
249 callback data for the the menu items. */
250 gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
252 ///* Attach the new accelerator group to the window. */
253 gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
255 /* Finally, return the actual menu bar created by the item factory. */
256 return gtk_item_factory_get_widget (item_factory, "<main>");
262 static ModestTnyHeaderTreeView*
263 header_view_new (ModestMainWindow *self)
266 GSList *columns = NULL;
267 ModestTnyHeaderTreeView *header_view;
268 ModestMainWindowPrivate *priv;
269 ModestTnyHeaderTreeViewColumn cols[] = {
270 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_MSGTYPE,
271 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_ATTACH,
272 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_FROM,
273 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_SUBJECT,
274 MODEST_TNY_HEADER_TREE_VIEW_COLUMN_RECEIVED_DATE
277 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
279 for (i = 0 ; i != sizeof(cols) / sizeof(ModestTnyHeaderTreeViewColumn); ++i)
280 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
282 header_view = modest_widget_factory_get_header_tree_widget (priv->widget_factory);
283 modest_tny_header_tree_view_set_columns (header_view, columns);
284 g_slist_free (columns);
291 set_sizes (ModestMainWindow *self)
293 ModestMainWindowPrivate *priv;
299 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
301 /* size of the whole window */
302 win_x = modest_conf_get_int_or_default (priv->conf,
303 MODEST_MAIN_WINDOW_WIDTH,
304 MODEST_MAIN_WINDOW_WIDTH_DEFAULT);
305 win_y = modest_conf_get_int_or_default (priv->conf,
306 MODEST_MAIN_WINDOW_HEIGHT,
307 MODEST_MAIN_WINDOW_HEIGHT_DEFAULT);
308 gtk_window_set_default_size (GTK_WINDOW(self), win_x, win_y);
310 /* size of the folder pane */
311 fol_x = modest_conf_get_int_or_default (priv->conf,
312 MODEST_FOLDER_PANED_WIDTH,
313 MODEST_FOLDER_PANED_WIDTH_DEFAULT);
314 fol_pos = modest_conf_get_int_or_default (priv->conf,
315 MODEST_FOLDER_PANED_DIVIDER_POS,
316 MODEST_FOLDER_PANED_DIVIDER_POS_DEFAULT);
317 if (1 > fol_x || fol_x > win_x || 1 > fol_pos || fol_pos > win_y) {
318 g_printerr ("modest: folder paned <x,pos> out of range: <%d,%d>\n",
321 /* slightly off... */
322 gtk_widget_set_size_request (priv->folder_paned, fol_x, win_y);
323 gtk_paned_set_position (GTK_PANED(priv->folder_paned),
327 /* size of the folder pane */
328 msg_x = modest_conf_get_int_or_default (priv->conf,
329 MODEST_MSG_PANED_WIDTH,
330 MODEST_MSG_PANED_WIDTH_DEFAULT);
331 msg_pos = modest_conf_get_int_or_default (priv->conf,
332 MODEST_MSG_PANED_DIVIDER_POS,
333 MODEST_MSG_PANED_DIVIDER_POS_DEFAULT);
334 if (1 > msg_x || msg_x > win_x || 1 > msg_pos || msg_pos > win_y) {
335 g_printerr ("modest: msg paned <x,pos> out of range: <%d,%d>\n",
338 /* slightly off... */
339 gtk_widget_set_size_request (priv->msg_paned,
341 gtk_paned_set_position (GTK_PANED(priv->msg_paned),
349 save_sizes (ModestMainWindow *self, ModestConf *conf)
351 ModestMainWindowPrivate *priv;
355 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
363 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
367 win = gtk_scrolled_window_new (NULL, NULL);
368 gtk_scrolled_window_set_policy
369 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
370 GTK_POLICY_AUTOMATIC);
373 gtk_scrolled_window_add_with_viewport
374 (GTK_SCROLLED_WINDOW(win), widget);
376 gtk_container_add (GTK_CONTAINER(win),
383 modest_main_window_new (ModestWidgetFactory *factory, ModestConf *conf)
386 ModestMainWindowPrivate *priv;
388 GtkWidget *main_vbox;
389 GtkWidget *main_paned;
390 GtkWidget *status_hbox;
391 GtkWidget *header_win, *folder_win;
393 g_return_val_if_fail (factory, NULL);
394 g_return_val_if_fail (conf, NULL);
396 obj = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
397 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
399 g_object_ref (factory);
400 priv->widget_factory = factory;
405 /* widgets from factory */
406 priv->folder_view = modest_widget_factory_get_folder_tree_widget (factory);
407 priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
408 priv->msg_preview = modest_widget_factory_get_msg_preview_widget (factory);
410 folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
412 header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
415 priv->menubar = menubar_new (MODEST_MAIN_WINDOW(obj));
416 priv->toolbar = gtk_toolbar_new ();
419 priv->folder_paned = gtk_vpaned_new ();
420 priv->msg_paned = gtk_vpaned_new ();
421 main_paned = gtk_hpaned_new ();
422 gtk_paned_add1 (GTK_PANED(main_paned), priv->folder_paned);
423 gtk_paned_add2 (GTK_PANED(main_paned), priv->msg_paned);
424 gtk_paned_add1 (GTK_PANED(priv->folder_paned),
425 gtk_label_new (_("Favorites")));
426 gtk_paned_add2 (GTK_PANED(priv->folder_paned), folder_win);
427 gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
428 gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
430 gtk_widget_show (GTK_WIDGET(priv->header_view));
432 /* status bar / progress */
433 priv->status_bar = gtk_statusbar_new ();
434 priv->progress_bar = gtk_progress_bar_new ();
435 status_hbox = gtk_hbox_new (TRUE, 5);
436 gtk_box_pack_start (GTK_BOX(status_hbox), priv->progress_bar, FALSE, TRUE, 5);
437 gtk_box_pack_start (GTK_BOX(status_hbox), priv->status_bar, FALSE, TRUE, 5);
439 /* putting it all together... */
440 main_vbox = gtk_vbox_new (FALSE, 2);
441 gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 2);
442 gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, TRUE, 5);
443 gtk_box_pack_start (GTK_BOX(main_vbox), main_paned, TRUE, TRUE, 2);
444 gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 5);
446 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
447 gtk_widget_show_all (main_vbox);
449 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
451 set_sizes (MODEST_MAIN_WINDOW(obj));
452 return GTK_WIDGET(obj);