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);
39 static void restore_sizes (ModestMainWindow *self);
40 static void save_sizes (ModestMainWindow *self);
49 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
50 struct _ModestMainWindowPrivate {
54 GtkWidget *folder_paned;
56 GtkWidget *main_paned;
58 ModestWidgetFactory *widget_factory;
61 ModestHeaderView *header_view;
62 ModestFolderView *folder_view;
63 ModestMsgView *msg_preview;
67 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
68 MODEST_TYPE_MAIN_WINDOW, \
69 ModestMainWindowPrivate))
71 static GtkWindowClass *parent_class = NULL;
73 /* uncomment the following if you have defined any signals */
74 /* static guint signals[LAST_SIGNAL] = {0}; */
77 modest_main_window_get_type (void)
79 static GType my_type = 0;
81 static const GTypeInfo my_info = {
82 sizeof(ModestMainWindowClass),
84 NULL, /* base finalize */
85 (GClassInitFunc) modest_main_window_class_init,
86 NULL, /* class finalize */
87 NULL, /* class data */
88 sizeof(ModestMainWindow),
90 (GInstanceInitFunc) modest_main_window_init,
92 my_type = g_type_register_static (GTK_TYPE_WINDOW,
100 modest_main_window_class_init (ModestMainWindowClass *klass)
102 GObjectClass *gobject_class;
103 gobject_class = (GObjectClass*) klass;
105 parent_class = g_type_class_peek_parent (klass);
106 gobject_class->finalize = modest_main_window_finalize;
108 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
110 /* signal definitions go here, e.g.: */
111 /* signals[MY_SIGNAL_1] = */
112 /* g_signal_new ("my_signal_1",....); */
113 /* signals[MY_SIGNAL_2] = */
114 /* g_signal_new ("my_signal_2",....); */
119 modest_main_window_init (ModestMainWindow *obj)
121 ModestMainWindowPrivate *priv;
123 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
125 priv->widget_factory = NULL;
129 modest_main_window_finalize (GObject *obj)
131 ModestMainWindowPrivate *priv;
133 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
135 if (priv->widget_factory) {
136 g_object_unref (G_OBJECT(priv->widget_factory));
137 priv->widget_factory = NULL;
141 g_object_unref (G_OBJECT(priv->conf));
144 G_OBJECT_CLASS(parent_class)->finalize (obj);
149 on_menu_about (GtkWidget *widget, gpointer data)
153 about = gtk_about_dialog_new ();
154 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
155 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
156 gtk_about_dialog_set_copyright (
157 GTK_ABOUT_DIALOG(about),
158 _("Copyright (c) 2006, Nokia Corporation\n"
159 "All rights reserved."));
160 gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG(about),
161 _("a modest e-mail client"));
162 gtk_dialog_run (GTK_DIALOG (about));
163 gtk_widget_destroy(about);
168 on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget)
170 GtkWidget *account_win;
171 ModestMainWindowPrivate *priv;
173 g_return_if_fail (widget);
174 g_return_if_fail (self);
176 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
177 account_win = modest_account_view_window_new (priv->conf,
178 priv->widget_factory);
179 gtk_widget_show (account_win);
184 on_menu_new_message (ModestMainWindow *self, guint action, GtkWidget *widget)
188 msg_win = modest_msg_window_new (MODEST_MSG_WINDOW_TYPE_NEW,
191 gtk_widget_show (msg_win);
195 on_menu_quit (ModestMainWindow *self, guint action, GtkWidget *widget)
203 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
204 static GtkItemFactoryEntry menu_items[] = {
205 { "/_File", NULL, NULL, 0, "<Branch>" },
206 { "/File/_New", "<control>N", NULL, 0, "<StockItem>", GTK_STOCK_NEW },
207 { "/File/_Open", "<control>O", NULL, 0, "<StockItem>", GTK_STOCK_OPEN },
208 { "/File/_Save", "<control>S", NULL, 0, "<StockItem>", GTK_STOCK_SAVE },
209 { "/File/Save _As", NULL, NULL, 0, "<Item>" },
210 { "/File/sep1", NULL, NULL, 0, "<Separator>" },
211 { "/File/_Quit", "<CTRL>Q", on_menu_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
213 { "/_Edit", NULL, NULL, 0, "<Branch>" },
214 { "/Edit/_Undo", "<CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_UNDO },
215 { "/Edit/_Redo", "<shift><CTRL>Z", NULL, 0, "<StockItem>", GTK_STOCK_REDO },
216 { "/File/sep1", NULL, NULL, 0, "<Separator>" },
217 { "/Edit/Cut", "<control>X", NULL, 0, "<StockItem>", GTK_STOCK_CUT },
218 { "/Edit/Copy", "<CTRL>C", NULL, 0, "<StockItem>", GTK_STOCK_COPY },
219 { "/Edit/Paste", NULL, NULL, 0, "<StockItem>", GTK_STOCK_PASTE},
220 { "/Edit/sep1", NULL, NULL, 0, "<Separator>" },
221 { "/Edit/Delete", "<CTRL>Q", NULL, 0, "<Item>" },
222 { "/Edit/Select all", "<CTRL>A", NULL, 0, "<Item>" },
223 { "/Edit/Deelect all", "<Shift><CTRL>A", NULL, 0, "<Item>" },
225 { "/_Actions", NULL, NULL, 0, "<Branch>" },
226 { "/Actions/_New Message", NULL, on_menu_new_message, 0, "<Item>" },
227 { "/Actions/_Reply", NULL, NULL, 0, "<Item>" },
228 { "/Actions/_Forward", NULL, NULL, 0, "<Item>" },
229 { "/Actions/_Bounce", NULL, NULL, 0, "<Item>" },
231 { "/_Options", NULL, NULL, 0, "<Branch>" },
232 { "/Options/_Accounts", NULL, on_menu_accounts,0, "<Item>" },
233 { "/Options/_Contacts", NULL, NULL, 0, "<Item>" },
236 { "/_Help", NULL, NULL, 0, "<Branch>" },
237 { "/_Help/About", NULL, on_menu_about, 0, "<StockItem>", GTK_STOCK_ABOUT},
240 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
244 menubar_new (ModestMainWindow *self)
246 GtkItemFactory *item_factory;
247 GtkAccelGroup *accel_group;
249 /* Make an accelerator group (shortcut keys) */
250 accel_group = gtk_accel_group_new ();
252 /* Make an ItemFactory (that makes a menubar) */
253 item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
256 /* This function generates the menu items. Pass the item factory,
257 the number of items in the array, the array itself, and any
258 callback data for the the menu items. */
259 gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
261 ///* Attach the new accelerator group to the window. */
262 gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
264 /* Finally, return the actual menu bar created by the item factory. */
265 return gtk_item_factory_get_widget (item_factory, "<main>");
271 static ModestHeaderView*
272 header_view_new (ModestMainWindow *self)
275 GSList *columns = NULL;
276 ModestHeaderView *header_view;
277 ModestMainWindowPrivate *priv;
278 ModestHeaderViewColumn cols[] = {
279 MODEST_HEADER_VIEW_COLUMN_MSGTYPE,
280 MODEST_HEADER_VIEW_COLUMN_ATTACH,
281 MODEST_HEADER_VIEW_COLUMN_FROM,
282 MODEST_HEADER_VIEW_COLUMN_SUBJECT,
283 MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE
286 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
288 for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i)
289 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
291 header_view = modest_widget_factory_get_header_view (priv->widget_factory);
292 modest_header_view_set_columns (header_view, columns);
293 g_slist_free (columns);
300 restore_sizes (ModestMainWindow *self)
302 ModestMainWindowPrivate *priv;
308 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
310 /* heigth of the main paned */
311 main_y = modest_conf_get_int_or_default (priv->conf,
312 MODEST_MAIN_PANED_HEIGHT,
313 MODEST_MAIN_PANED_HEIGHT_DEFAULT);
314 /* size of the folder pane */
315 fol_x = modest_conf_get_int_or_default (priv->conf,
316 MODEST_FOLDER_PANED_WIDTH,
317 MODEST_FOLDER_PANED_WIDTH_DEFAULT);
318 fol_pos = modest_conf_get_int_or_default (priv->conf,
319 MODEST_FOLDER_PANED_DIVIDER_POS,
320 MODEST_FOLDER_PANED_DIVIDER_POS_DEFAULT);
321 gtk_paned_set_position (GTK_PANED(priv->folder_paned), fol_pos);
323 /* size of the msg pane */
324 msg_x = modest_conf_get_int_or_default (priv->conf,
325 MODEST_MSG_PANED_WIDTH,
326 MODEST_MSG_PANED_WIDTH_DEFAULT);
327 msg_pos = modest_conf_get_int_or_default (priv->conf,
328 MODEST_MSG_PANED_DIVIDER_POS,
329 MODEST_MSG_PANED_DIVIDER_POS_DEFAULT);
330 gtk_paned_set_position (GTK_PANED(priv->msg_paned), msg_pos);
332 g_message ("(%d, %d, %d %d, %d)", main_y, fol_x, fol_pos, msg_x, msg_pos);
334 //gtk_widget_set_size_request (GTK_WIDGET(self), fol_x + msg_x, main_y+50);
335 gtk_widget_set_size_request (priv->main_paned, fol_x + msg_x, main_y);
336 gtk_paned_set_position (GTK_PANED(priv->main_paned), fol_x);
341 save_sizes (ModestMainWindow *self)
343 ModestMainWindowPrivate *priv;
344 int fol_pos, msg_pos;
347 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
349 height = GTK_WIDGET(priv->main_paned)->allocation.height;
350 modest_conf_set_int (priv->conf, MODEST_MAIN_PANED_HEIGHT, height, NULL);
352 width = GTK_WIDGET(priv->folder_paned)->allocation.width;
353 fol_pos = gtk_paned_get_position (GTK_PANED(priv->folder_paned));
354 modest_conf_set_int (priv->conf, MODEST_FOLDER_PANED_WIDTH, width, NULL);
355 modest_conf_set_int (priv->conf, MODEST_FOLDER_PANED_DIVIDER_POS, fol_pos, NULL);
357 width = GTK_WIDGET(priv->msg_paned)->allocation.width;
358 msg_pos = gtk_paned_get_position (GTK_PANED(priv->msg_paned));
359 modest_conf_set_int (priv->conf, MODEST_MSG_PANED_WIDTH, width, NULL);
360 modest_conf_set_int (priv->conf, MODEST_MSG_PANED_DIVIDER_POS, msg_pos, NULL);
365 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
369 win = gtk_scrolled_window_new (NULL, NULL);
370 gtk_scrolled_window_set_policy
371 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
372 GTK_POLICY_AUTOMATIC);
375 gtk_scrolled_window_add_with_viewport
376 (GTK_SCROLLED_WINDOW(win), widget);
378 gtk_container_add (GTK_CONTAINER(win),
385 modest_main_window_new (ModestWidgetFactory *factory, ModestConf *conf)
388 ModestMainWindowPrivate *priv;
390 GtkWidget *main_vbox;
391 GtkWidget *status_hbox;
392 GtkWidget *header_win, *folder_win;
394 g_return_val_if_fail (factory, NULL);
395 g_return_val_if_fail (conf, NULL);
397 obj = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
398 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
400 g_object_ref (factory);
401 priv->widget_factory = factory;
406 /* widgets from factory */
407 priv->folder_view = modest_widget_factory_get_folder_view (factory);
408 priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
409 priv->msg_preview = modest_widget_factory_get_msg_preview (factory);
411 folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
413 header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
416 priv->menubar = menubar_new (MODEST_MAIN_WINDOW(obj));
417 priv->toolbar = gtk_toolbar_new ();
420 priv->folder_paned = gtk_vpaned_new ();
421 priv->msg_paned = gtk_vpaned_new ();
422 priv->main_paned = gtk_hpaned_new ();
423 gtk_paned_add1 (GTK_PANED(priv->main_paned), priv->folder_paned);
424 gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
425 gtk_paned_add1 (GTK_PANED(priv->folder_paned),
426 gtk_label_new (_("Favorites")));
427 gtk_paned_add2 (GTK_PANED(priv->folder_paned), folder_win);
428 gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
429 gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
431 gtk_widget_show (GTK_WIDGET(priv->header_view));
433 /* status bar / progress */
434 status_hbox = gtk_hbox_new (TRUE, 5);
435 gtk_box_pack_start (GTK_BOX(status_hbox),
436 modest_widget_factory_get_status_bar(factory),
438 gtk_box_pack_start (GTK_BOX(status_hbox),
439 modest_widget_factory_get_progress_bar(factory),
442 /* putting it all together... */
443 main_vbox = gtk_vbox_new (FALSE, 2);
444 gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 2);
445 gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, TRUE, 5);
446 gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE, 2);
447 gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 5);
449 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
450 gtk_widget_show_all (main_vbox);
452 gtk_window_set_title (GTK_WINDOW(obj), "Modest");
454 restore_sizes (MODEST_MAIN_WINDOW(obj));
456 return GTK_WIDGET(obj);