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/gtktreeviewcolumn.h>
32 #include <tny-account-store-view.h>
33 #include <tny-simple-list.h>
34 #include <tny-maemo-conic-device.h>
35 #include "modest-hildon-includes.h"
36 #include "modest-defs.h"
39 #include "widgets/modest-main-window.h"
40 #include "widgets/modest-msg-edit-window.h"
41 #include "widgets/modest-account-view-window.h"
42 #include "modest-runtime.h"
43 #include "modest-account-mgr-helpers.h"
44 #include "modest-platform.h"
45 #include "modest-widget-memory.h"
46 #include "modest-window-priv.h"
47 #include "modest-main-window-ui.h"
48 #include "modest-main-window-ui-dimming.h"
49 #include "modest-account-mgr.h"
50 #include "modest-tny-account.h"
51 #include "modest-conf.h"
52 #include <modest-maemo-utils.h>
53 #include "modest-tny-platform-factory.h"
54 #include "modest-tny-msg.h"
55 #include "modest-mail-operation.h"
56 #include "modest-icon-names.h"
57 #include "modest-progress-bar-widget.h"
58 #include "modest-text-utils.h"
59 #include "modest-ui-dimming-manager.h"
60 #include "maemo/modest-osso-state-saving.h"
62 #ifdef MODEST_HILDON_VERSION_0
63 #include <hildon-widgets/hildon-program.h>
65 #include <hildon/hildon-program.h>
66 #endif /*MODEST_HILDON_VERSION_0*/
68 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
75 /* 'private'/'protected' functions */
76 static void modest_main_window_class_init (ModestMainWindowClass *klass);
77 static void modest_main_window_init (ModestMainWindow *obj);
78 static void modest_main_window_finalize (GObject *obj);
79 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
80 GdkEventWindowState *event,
83 static void connect_signals (ModestMainWindow *self);
85 static void restore_settings (ModestMainWindow *self);
86 static void save_state (ModestWindow *self);
88 static void modest_main_window_show_toolbar (ModestWindow *window,
89 gboolean show_toolbar);
91 static void cancel_progressbar (GtkToolButton *toolbutton,
92 ModestMainWindow *self);
94 static void on_queue_changed (ModestMailOperationQueue *queue,
95 ModestMailOperation *mail_op,
96 ModestMailOperationQueueNotification type,
97 ModestMainWindow *self);
99 static void on_account_update (TnyAccountStore *account_store,
100 const gchar *account_name,
103 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
107 static void on_configuration_key_changed (ModestConf* conf,
109 ModestConfEvent event,
110 ModestMainWindow *self);
112 static void set_toolbar_mode (ModestMainWindow *self,
113 ModestToolBarModes mode);
115 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
117 static void on_show_account_action_activated (GtkAction *action,
120 static void on_refresh_account_action_activated (GtkAction *action,
123 static void on_send_receive_csm_activated (GtkMenuItem *item,
127 static GtkWidget * create_empty_view (void);
129 /* list my signals */
137 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
138 struct _ModestMainWindowPrivate {
139 GtkWidget *msg_paned;
140 GtkWidget *main_paned;
141 GtkWidget *main_vbox;
142 GtkWidget *contents_widget;
143 GtkWidget *empty_view;
145 /* Progress observers */
146 GtkWidget *progress_bar;
147 GSList *progress_widgets;
150 GtkWidget *progress_toolitem;
151 GtkWidget *cancel_toolitem;
152 GtkWidget *sort_toolitem;
153 GtkWidget *refresh_toolitem;
154 ModestToolBarModes current_toolbar_mode;
156 /* Merge ids used to add/remove accounts to the ViewMenu*/
157 GByteArray *merge_ids;
159 /* On-demand widgets */
160 GtkWidget *accounts_popup;
161 GtkWidget *details_widget;
163 /* Optimized view enabled */
164 gboolean optimized_view;
166 /* Optimized view enabled */
167 gboolean send_receive_in_progress;
169 ModestHeaderView *header_view;
170 ModestFolderView *folder_view;
172 ModestMainWindowStyle style;
173 ModestMainWindowContentsStyle contents_style;
175 guint progress_bar_timeout;
178 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
179 MODEST_TYPE_MAIN_WINDOW, \
180 ModestMainWindowPrivate))
182 typedef struct _GetMsgAsyncHelper {
183 ModestMainWindowPrivate *main_window_private;
185 ModestTnyMsgReplyType reply_type;
186 ModestTnyMsgForwardType forward_type;
193 static GtkWindowClass *parent_class = NULL;
196 /* Private actions */
197 /* This is the context sensitive menu: */
198 static const GtkActionEntry modest_folder_view_action_entries [] = {
200 /* Folder View CSM actions */
201 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
202 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
203 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, NULL },
204 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
205 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) },
206 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
209 static const GtkActionEntry modest_header_view_action_entries [] = {
211 /* Header View CSM actions */
212 { "HeaderViewCSMOpen", NULL, N_("mcen_me_inbox_open"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
213 { "HeaderViewCSMReply", NULL, N_("mcen_me_inbox_reply"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply) },
214 { "HeaderViewCSMReplyAll", NULL, N_("mcen_me_inbox_replytoall"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_reply_all) },
215 { "HeaderViewCSMForward", NULL, N_("mcen_me_inbox_forward"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_forward) },
216 { "HeaderViewCSMCut", NULL, N_("mcen_me_inbox_cut"), "<CTRL>X", NULL, G_CALLBACK (modest_ui_actions_on_cut) },
217 { "HeaderViewCSMCopy", NULL, N_("mcen_me_inbox_copy"), "<CTRL>C", NULL, G_CALLBACK (modest_ui_actions_on_copy) },
218 { "HeaderViewCSMPaste", NULL, N_("mcen_me_inbox_paste"), "<CTRL>V", NULL, G_CALLBACK (modest_ui_actions_on_paste) },
219 { "HeaderViewCSMDelete", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete) },
220 { "HeaderViewCSMCancelSending", NULL, N_("mcen_me_outbox_cancelsend"), NULL, NULL, NULL },
221 { "HeaderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) },
224 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
225 { "ToolbarToggleView", MODEST_STOCK_SPLIT_VIEW, N_("gqn_toolb_rss_fldonoff"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), FALSE },
228 /************************************************************************/
231 modest_main_window_get_type (void)
233 static GType my_type = 0;
235 static const GTypeInfo my_info = {
236 sizeof(ModestMainWindowClass),
237 NULL, /* base init */
238 NULL, /* base finalize */
239 (GClassInitFunc) modest_main_window_class_init,
240 NULL, /* class finalize */
241 NULL, /* class data */
242 sizeof(ModestMainWindow),
244 (GInstanceInitFunc) modest_main_window_init,
247 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
255 modest_main_window_class_init (ModestMainWindowClass *klass)
257 GObjectClass *gobject_class;
258 gobject_class = (GObjectClass*) klass;
259 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
261 parent_class = g_type_class_peek_parent (klass);
262 gobject_class->finalize = modest_main_window_finalize;
264 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
266 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
267 modest_window_class->save_state_func = save_state;
271 modest_main_window_init (ModestMainWindow *obj)
273 ModestMainWindowPrivate *priv;
275 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
277 priv->msg_paned = NULL;
278 priv->main_paned = NULL;
279 priv->main_vbox = NULL;
280 priv->header_view = NULL;
281 priv->folder_view = NULL;
282 priv->contents_widget = NULL;
283 priv->accounts_popup = NULL;
284 priv->details_widget = NULL;
285 priv->empty_view = NULL;
287 priv->progress_widgets = NULL;
288 priv->progress_bar = NULL;
289 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
291 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
292 priv->contents_style = MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS;
294 priv->merge_ids = NULL;
296 priv->optimized_view = FALSE;
297 priv->send_receive_in_progress = FALSE;
298 priv->progress_bar_timeout = 0;
302 modest_main_window_finalize (GObject *obj)
304 ModestMainWindowPrivate *priv;
306 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
308 g_slist_free (priv->progress_widgets);
310 g_byte_array_free (priv->merge_ids, TRUE);
312 if (priv->progress_bar_timeout > 0) {
313 g_source_remove (priv->progress_bar_timeout);
314 priv->progress_bar_timeout = 0;
317 G_OBJECT_CLASS(parent_class)->finalize (obj);
321 modest_main_window_get_child_widget (ModestMainWindow *self,
322 ModestWidgetType widget_type)
324 ModestMainWindowPrivate *priv;
327 g_return_val_if_fail (self, NULL);
328 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
331 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
333 switch (widget_type) {
334 case MODEST_WIDGET_TYPE_HEADER_VIEW:
335 widget = (GtkWidget*)priv->header_view; break;
336 case MODEST_WIDGET_TYPE_FOLDER_VIEW:
337 widget = (GtkWidget*)priv->folder_view; break;
342 return widget ? GTK_WIDGET(widget) : NULL;
347 restore_settings (ModestMainWindow *self)
350 ModestMainWindowPrivate *priv;
352 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
354 conf = modest_runtime_get_conf ();
356 modest_widget_memory_restore (conf, G_OBJECT(self),
357 MODEST_CONF_MAIN_WINDOW_KEY);
358 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
359 MODEST_CONF_HEADER_VIEW_KEY);
360 modest_widget_memory_restore (conf, G_OBJECT(priv->folder_view),
361 MODEST_CONF_FOLDER_VIEW_KEY);
362 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
363 MODEST_CONF_MAIN_PANED_KEY);
365 /* We need to force a redraw here in order to get the right
366 position of the horizontal paned separator */
367 gtk_widget_show (GTK_WIDGET (self));
372 save_state (ModestWindow *window)
375 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
376 ModestMainWindowPrivate *priv;
378 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
379 conf = modest_runtime_get_conf ();
381 modest_widget_memory_save (conf,G_OBJECT(self),
382 MODEST_CONF_MAIN_WINDOW_KEY);
383 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
384 MODEST_CONF_MAIN_PANED_KEY);
385 modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
386 MODEST_CONF_HEADER_VIEW_KEY);
387 modest_widget_memory_save (conf, G_OBJECT(priv->folder_view),
388 MODEST_CONF_FOLDER_VIEW_KEY);
392 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
394 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
395 gtk_scrolled_window_add_with_viewport
396 (GTK_SCROLLED_WINDOW(win), widget);
398 gtk_container_add (GTK_CONTAINER(win),
404 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self)
406 modest_window_save_state (MODEST_WINDOW(self));
412 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
414 /* When going online, do the equivalent of pressing the send/receive button,
415 * as per the specification:
416 * (without the check for >0 accounts, though that is not specified): */
418 TnyDevice *device = tny_account_store_get_device (store);
420 /* Check that we are really online.
421 * This signal should not be emitted when we are not connected,
422 * but it seems to happen sometimes: */
423 if (!tny_device_is_online (device))
426 const gchar *iap_id = tny_maemo_conic_device_get_current_iap_id (TNY_MAEMO_CONIC_DEVICE (device));
427 printf ("DEBUG: %s: connection id=%s\n", __FUNCTION__, iap_id);
429 /* Stop the existing send queues: */
430 modest_runtime_remove_all_send_queues ();
432 /* Create the send queues again, using the appropriate transport accounts
433 * for this new connection.
434 * This could be the first time that they are created if this is the first
436 /* TODO: Does this really destroy the TnySendQueues and their threads
437 * We do not want 2 TnySendQueues to exist with the same underlying
438 * outbox directory. */
439 GSList *account_names = modest_account_mgr_account_names (
440 modest_runtime_get_account_mgr(),
441 TRUE /* enabled accounts only */);
442 GSList *iter = account_names;
444 const gchar *account_name = (const gchar*)(iter->data);
446 TnyTransportAccount *account = TNY_TRANSPORT_ACCOUNT (
447 modest_tny_account_store_get_transport_account_for_open_connection
448 (modest_runtime_get_account_store(), account_name));
450 printf ("debug: %s:\n Transport account for %s: %s\n", __FUNCTION__, account_name,
451 tny_account_get_id(TNY_ACCOUNT(account)));
452 modest_runtime_get_send_queue (account);
456 iter = g_slist_next (iter);
459 g_slist_free (account_names);
462 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
466 _folder_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
468 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
471 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
475 _header_view_csm_menu_activated (GtkWidget *widget, gpointer user_data)
477 g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
479 /* Update visibility */
482 modest_window_check_dimming_rules_group (MODEST_WINDOW (user_data), "ModestMenuDimmingRules");
486 connect_signals (ModestMainWindow *self)
488 ModestWindowPrivate *parent_priv;
489 ModestMainWindowPrivate *priv;
492 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
493 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
496 g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
497 G_CALLBACK(on_inner_widgets_key_pressed), self);
498 g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
499 G_CALLBACK(modest_ui_actions_on_folder_selection_changed), self);
500 g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
501 G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
503 /* Folder view CSM */
504 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
505 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
506 g_signal_connect (G_OBJECT(priv->folder_view), "tap-and-hold",
507 G_CALLBACK(_folder_view_csm_menu_activated),
510 /* g_signal_connect (G_OBJECT(priv->header_view), "status_update", */
511 /* G_CALLBACK(modest_ui_actions_on_header_status_update), self); */
512 g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
513 G_CALLBACK(modest_ui_actions_on_header_selected), self);
514 g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
515 G_CALLBACK(modest_ui_actions_on_header_activated), self);
516 g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
517 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
518 g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
519 G_CALLBACK(on_inner_widgets_key_pressed), self);
521 /* Header view CSM */
522 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/HeaderViewCSM");
523 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->header_view), menu, NULL, 0);
524 g_signal_connect (G_OBJECT(priv->header_view), "tap-and-hold",
525 G_CALLBACK(_header_view_csm_menu_activated),
529 g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
530 g_signal_connect (G_OBJECT (self), "window-state-event",
531 G_CALLBACK (modest_main_window_window_state_event),
533 g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
535 /* Mail Operation Queue */
536 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
538 G_CALLBACK (on_queue_changed),
541 /* Track changes in the device name */
542 g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
544 G_CALLBACK (on_configuration_key_changed),
547 /* Track account changes. We need to refresh the toolbar */
548 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
550 G_CALLBACK (on_account_update),
554 g_signal_connect (G_OBJECT (modest_runtime_get_account_store()), "password_requested",
555 G_CALLBACK (modest_ui_actions_on_password_requested), self);
558 g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), "connecting-finished",
559 G_CALLBACK(on_account_store_connecting_finished), self);
563 /** Idle handler, to send/receive at startup .*/
565 sync_accounts_cb (ModestMainWindow *win)
567 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
568 return FALSE; /* Do not call this idle handler again. */
572 static void on_hildon_program_is_topmost_notify(GObject *self,
573 GParamSpec *propert_param, gpointer user_data)
575 HildonProgram *app = HILDON_PROGRAM (self);
578 ModestWindow* self = MODEST_WINDOW(user_data);
581 /* Note that use of hildon_program_set_can_hibernate()
582 * is generally referred to as "setting the killable flag",
583 * though hibernation does not seem equal to death.
586 if (hildon_program_get_is_topmost (app)) {
587 /* Prevent hibernation when the progam comes to the foreground,
588 * because hibernation should only happen when the application
589 * is in the background: */
590 hildon_program_set_can_hibernate (app, FALSE);
592 /* Allow hibernation if the program has gone to the background: */
594 /* However, prevent hibernation while the settings are being changed: */
595 const gboolean hibernation_prevented =
596 modest_window_mgr_get_hibernation_is_prevented (
597 modest_runtime_get_window_mgr ());
599 if (hibernation_prevented)
600 hildon_program_set_can_hibernate (app, FALSE);
602 /* Allow hibernation, after saving the state: */
603 modest_osso_save_state();
604 hildon_program_set_can_hibernate (app, TRUE);
613 modest_main_window_new (void)
615 ModestMainWindow *self = NULL;
616 ModestMainWindowPrivate *priv = NULL;
617 ModestWindowPrivate *parent_priv = NULL;
618 GtkWidget *folder_win = NULL;
619 ModestDimmingRulesGroup *menu_rules_group = NULL;
620 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
621 GtkActionGroup *action_group = NULL;
622 GError *error = NULL;
623 TnyFolderStoreQuery *query = NULL;
624 GdkPixbuf *window_icon = NULL;
625 ModestConf *conf = NULL;
626 GtkAction *action = NULL;
628 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
629 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
630 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
632 parent_priv->ui_manager = gtk_ui_manager_new();
633 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
635 action_group = gtk_action_group_new ("ModestMainWindowActions");
636 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
638 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules");
639 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules");
641 /* Add common actions */
642 gtk_action_group_add_actions (action_group,
643 modest_action_entries,
644 G_N_ELEMENTS (modest_action_entries),
647 gtk_action_group_add_actions (action_group,
648 modest_folder_view_action_entries,
649 G_N_ELEMENTS (modest_folder_view_action_entries),
652 gtk_action_group_add_actions (action_group,
653 modest_header_view_action_entries,
654 G_N_ELEMENTS (modest_header_view_action_entries),
657 gtk_action_group_add_toggle_actions (action_group,
658 modest_toggle_action_entries,
659 G_N_ELEMENTS (modest_toggle_action_entries),
662 gtk_action_group_add_toggle_actions (action_group,
663 modest_main_window_toggle_action_entries,
664 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
667 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
668 g_object_unref (action_group);
670 /* Load the UI definition */
671 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
672 MODEST_UIDIR "modest-main-window-ui.xml", &error);
674 g_warning ("Could not merge modest-ui.xml: %s", error->message);
675 g_error_free (error);
679 /* Add common dimming rules */
680 modest_dimming_rules_group_add_rules (menu_rules_group,
681 modest_main_window_menu_dimming_entries,
682 G_N_ELEMENTS (modest_main_window_menu_dimming_entries),
684 modest_dimming_rules_group_add_rules (toolbar_rules_group,
685 modest_main_window_toolbar_dimming_entries,
686 G_N_ELEMENTS (modest_main_window_toolbar_dimming_entries),
689 /* Insert dimming rules group for this window */
690 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
691 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
692 g_object_unref (menu_rules_group);
693 g_object_unref (toolbar_rules_group);
695 /* Add accelerators */
696 gtk_window_add_accel_group (GTK_WINDOW (self),
697 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
699 /* Menubar. Update the state of some toggles */
700 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
701 conf = modest_runtime_get_conf ();
702 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
703 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
704 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
705 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
706 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
707 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
708 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
709 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
710 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
712 /* Get device name */
713 modest_maemo_utils_get_device_name ();
716 query = tny_folder_store_query_new ();
717 tny_folder_store_query_add_item (query, NULL,
718 TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
719 priv->folder_view = MODEST_FOLDER_VIEW(modest_folder_view_new (query));
720 if (!priv->folder_view)
721 g_printerr ("modest: cannot instantiate folder view\n");
722 g_object_unref (G_OBJECT (query));
723 modest_folder_view_set_style (priv->folder_view,
724 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
728 MODEST_HEADER_VIEW(modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
729 if (!priv->header_view)
730 g_printerr ("modest: cannot instantiate header view\n");
731 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
734 priv->empty_view = create_empty_view ();
736 /* Create scrolled windows */
737 folder_win = gtk_scrolled_window_new (NULL, NULL);
738 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
739 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
741 GTK_POLICY_AUTOMATIC);
742 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
744 GTK_POLICY_AUTOMATIC);
746 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
747 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view));
750 priv->main_paned = gtk_hpaned_new ();
751 gtk_paned_pack1 (GTK_PANED(priv->main_paned), folder_win, TRUE, TRUE);
752 gtk_paned_pack2 (GTK_PANED(priv->main_paned), priv->contents_widget, TRUE, TRUE);
753 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
755 /* putting it all together... */
756 priv->main_vbox = gtk_vbox_new (FALSE, 6);
757 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
759 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
761 /* Set window icon */
762 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
763 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
765 /* Connect signals */
766 connect_signals (self);
768 /* Set account store */
769 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
770 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
772 /* Do send & receive when we are idle */
773 /* TODO: Enable this again. I have commented it out because,
774 * at least in scratchbox, this can cause us to start a second
775 * update (in response to a connection change) when we are already
776 * doing an update (started here, at startup). Tinymail doesn't like that.
779 /* g_idle_add ((GSourceFunc)sync_accounts_cb, self); */
781 HildonProgram *app = hildon_program_get_instance ();
782 hildon_program_add_window (app, HILDON_WINDOW (self));
784 /* Register HildonProgram signal handlers: */
785 /* These are apparently deprecated, according to the
786 * "HildonApp/HildonAppView to HildonProgram/HildonWindow migration guide",
787 * though the API reference does not mention that:
789 g_signal_connect (G_OBJECT(app), "topmost_status_lose",
790 G_CALLBACK (on_hildon_program_save_state), self);
791 g_signal_connect (G_OBJECT(app), "topmost_status_acquire",
792 G_CALLBACK (on_hildon_program_status_acquire), self);
794 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
795 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
797 /* Load previous osso state, for instance if we are being restored from
799 modest_osso_load_state();
801 /* Restore window & widget settings */
802 restore_settings (MODEST_MAIN_WINDOW(self));
804 return MODEST_WINDOW(self);
808 modest_main_window_close_all (ModestMainWindow *self)
811 GtkResponseType response;
813 /* Create the confirmation dialog MSG-NOT308 */
814 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
815 _("emev_nc_close_windows"),
816 _("mcen_bd_yes"), GTK_RESPONSE_YES,
817 _("mcen_bd_no"), GTK_RESPONSE_NO,
820 response = gtk_dialog_run (GTK_DIALOG (note));
821 gtk_widget_destroy (GTK_WIDGET (note));
823 if (response == GTK_RESPONSE_YES)
831 modest_main_window_set_style (ModestMainWindow *self,
832 ModestMainWindowStyle style)
834 ModestMainWindowPrivate *priv;
835 ModestWindowPrivate *parent_priv;
838 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
840 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
841 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
843 /* no change -> nothing to do */
844 if (priv->style == style)
847 /* Get toggle button */
848 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarToggleView");
852 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
853 /* Remove main paned */
854 g_object_ref (priv->main_paned);
855 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
857 /* Reparent the contents widget to the main vbox */
858 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
860 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
861 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
862 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
865 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
866 /* Remove header view */
867 g_object_ref (priv->contents_widget);
868 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
870 /* Reparent the main paned */
871 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
872 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
874 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
875 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
876 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
880 g_return_if_reached ();
883 /* Let header view grab the focus if it's being shown */
884 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
885 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
887 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
890 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
893 ModestMainWindowStyle
894 modest_main_window_get_style (ModestMainWindow *self)
896 ModestMainWindowPrivate *priv;
898 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
900 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
907 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
909 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
910 ModestWindowPrivate *parent_priv;
911 ModestWindowMgr *mgr;
912 gboolean is_fullscreen;
913 GtkAction *fs_toggle_action;
916 mgr = modest_runtime_get_window_mgr ();
918 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
920 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
922 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
923 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
924 if (is_fullscreen != active) {
925 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
934 set_homogeneous (GtkWidget *widget,
937 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
938 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
942 modest_main_window_show_toolbar (ModestWindow *self,
943 gboolean show_toolbar)
945 ModestMainWindowPrivate *priv = NULL;
946 ModestWindowPrivate *parent_priv = NULL;
947 GtkWidget *reply_button = NULL, *menu = NULL;
948 GtkWidget *placeholder = NULL;
951 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
952 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
953 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
955 /* Set optimized view status */
956 priv->optimized_view = !show_toolbar;
958 if (!parent_priv->toolbar) {
959 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
962 /* Set homogeneous toolbar */
963 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
964 set_homogeneous, NULL);
966 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
967 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
968 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
969 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
970 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
971 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
972 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
973 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
975 /* Add ProgressBar (Transfer toolbar) */
976 priv->progress_bar = modest_progress_bar_widget_new ();
977 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
978 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
979 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
980 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
981 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
983 /* Connect cancel 'clicked' signal to abort progress mode */
984 g_signal_connect(priv->cancel_toolitem, "clicked",
985 G_CALLBACK(cancel_progressbar),
988 /* Add it to the observers list */
989 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
992 hildon_window_add_toolbar (HILDON_WINDOW (self),
993 GTK_TOOLBAR (parent_priv->toolbar));
995 /* Set reply button tap and hold menu */
996 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
997 "/ToolBar/ToolbarMessageReply");
998 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1000 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1002 /* Set send & receive button tap and hold menu */
1003 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
1008 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1009 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1010 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1012 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1013 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
1015 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1020 compare_display_names (ModestAccountData *a,
1021 ModestAccountData *b)
1023 return strcmp (a->display_name, b->display_name);
1027 on_account_update (TnyAccountStore *account_store,
1028 const gchar *account_name,
1031 GSList *account_names, *iter, *accounts;
1032 ModestMainWindow *self;
1033 ModestMainWindowPrivate *priv;
1034 ModestWindowPrivate *parent_priv;
1035 ModestAccountMgr *mgr;
1036 gint i, num_accounts;
1037 GtkActionGroup *action_group;
1039 gchar *default_account;
1040 GtkWidget *send_receive_button, *item;
1042 self = MODEST_MAIN_WINDOW (user_data);
1043 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
1044 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
1046 /* Get enabled account IDs */
1047 mgr = modest_runtime_get_account_mgr ();
1048 account_names = modest_account_mgr_account_names (mgr, TRUE);
1049 iter = account_names;
1053 ModestAccountData *account_data =
1054 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
1055 accounts = g_slist_prepend (accounts, account_data);
1059 g_slist_free (account_names);
1061 /* Order the list of accounts by its display name */
1062 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
1063 num_accounts = g_slist_length (accounts);
1065 /* Delete old send&receive popup items. We can not just do a
1066 menu_detach because it does not work well with
1068 if (priv->accounts_popup)
1069 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup),
1070 (GtkCallback) gtk_widget_destroy, NULL);
1072 /* Delete old entries in the View menu. Do not free groups, it
1074 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
1076 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
1077 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
1078 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
1079 GTK_ACTION_GROUP (groups->data));
1082 if (priv->merge_ids) {
1083 for (i = 0; i < priv->merge_ids->len; i++)
1084 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
1085 g_byte_array_free (priv->merge_ids, TRUE);
1087 /* We need to call this in order to ensure
1088 that the new actions are added in the right
1089 order (alphabetical */
1090 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
1092 groups = g_list_next (groups);
1094 priv->merge_ids = g_byte_array_sized_new (num_accounts);
1096 /* Get send receive button */
1097 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1098 "/ToolBar/ToolbarSendReceive");
1100 /* Create the menu */
1101 if (num_accounts > 1) {
1102 if (!priv->accounts_popup)
1103 priv->accounts_popup = gtk_menu_new ();
1104 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
1105 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1106 g_signal_connect (G_OBJECT (item),
1108 G_CALLBACK (on_send_receive_csm_activated),
1110 item = gtk_separator_menu_item_new ();
1111 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1114 /* Create a new action group */
1115 default_account = modest_account_mgr_get_default_account (mgr);
1116 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
1117 for (i = 0; i < num_accounts; i++) {
1118 gchar *display_name = NULL;
1120 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
1122 /* Create display name. The default account is shown differently */
1123 if (default_account && account_data->account_name &&
1124 !(strcmp (default_account, account_data->account_name) == 0)) {
1125 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
1126 account_data->display_name);
1129 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
1130 account_data->display_name);
1133 /* Create action and add it to the action group. The
1134 action name must be the account name, this way we
1135 could know in the handlers the account to show */
1136 if(account_data->account_name) {
1137 gchar* item_name, *refresh_action_name;
1139 GtkAction *view_account_action, *refresh_account_action;
1141 view_account_action = gtk_action_new (account_data->account_name,
1142 display_name, NULL, NULL);
1143 gtk_action_group_add_action (action_group, view_account_action);
1145 /* Add ui from account data. We allow 2^9-1 account
1146 changes in a single execution because we're
1147 downcasting the guint to a guint8 in order to use a
1148 GByteArray, it should be enough */
1149 item_name = g_strconcat (account_data->account_name, "Menu", NULL);
1150 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1151 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1152 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1154 "/MenuBar/ViewMenu/ViewMenuAdditions",
1156 account_data->account_name,
1157 GTK_UI_MANAGER_MENUITEM,
1160 /* Connect the action signal "activate" */
1161 g_signal_connect (G_OBJECT (view_account_action),
1163 G_CALLBACK (on_show_account_action_activated),
1166 /* Create the items for the Tools->Send&Receive submenu */
1167 refresh_action_name = g_strconcat ("SendReceive", account_data->account_name, NULL);
1168 refresh_account_action = gtk_action_new ((const gchar*) refresh_action_name,
1169 display_name, NULL, NULL);
1170 gtk_action_group_add_action (action_group, refresh_account_action);
1172 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1173 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1174 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1176 "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions",
1178 refresh_action_name,
1179 GTK_UI_MANAGER_MENUITEM,
1181 g_free (refresh_action_name);
1183 g_signal_connect_data (G_OBJECT (refresh_account_action),
1185 G_CALLBACK (on_refresh_account_action_activated),
1186 g_strdup (account_data->account_name),
1187 (GClosureNotify) g_free,
1190 /* Create item and add it to the send&receive
1191 CSM. If there is only one account then
1193 if (priv->accounts_popup) {
1194 item = gtk_menu_item_new_with_label (display_name);
1195 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1196 g_signal_connect_data (G_OBJECT (item),
1198 G_CALLBACK (on_send_receive_csm_activated),
1199 g_strdup (account_data->account_name),
1200 (GClosureNotify) g_free,
1207 g_free (display_name);
1208 modest_account_mgr_free_account_data (mgr, account_data);
1210 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1212 if (priv->accounts_popup) {
1213 /* Mandatory in order to view the menu contents */
1214 gtk_widget_show_all (priv->accounts_popup);
1216 /* Setup tap_and_hold just if was not done before*/
1217 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1218 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1222 g_slist_free (accounts);
1223 g_free (default_account);
1227 * This function manages the key events used to navigate between
1228 * header and folder views (when the window is in split view)
1231 * -------------------------------------------------
1232 * HeaderView GDK_Left Move focus to folder view
1233 * FolderView GDK_Right Move focus to header view
1235 * There is no need to scroll to selected row, the widgets will be the
1236 * responsibles of doing that (probably managing the focus-in event
1239 on_inner_widgets_key_pressed (GtkWidget *widget,
1243 ModestMainWindowPrivate *priv;
1245 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1247 /* Do nothing if we're in SIMPLE style */
1248 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1251 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1252 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1253 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1254 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1260 set_alignment (GtkWidget *widget,
1263 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1264 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1268 create_empty_view (void)
1270 GtkLabel *label = NULL;
1271 GtkWidget *align = NULL;
1273 align = gtk_alignment_new(XALIGN, YALIGN, XSPACE, YSPACE);
1274 label = GTK_LABEL(gtk_label_new (_("mcen_ia_nomessages")));
1275 gtk_label_set_justify (label, GTK_JUSTIFY_CENTER);
1276 gtk_container_add (GTK_CONTAINER (align), GTK_WIDGET(label));
1278 return GTK_WIDGET(align);
1282 create_details_widget (TnyAccount *account)
1287 vbox = gtk_vbox_new (FALSE, 0);
1289 /* Account description: */
1291 if (modest_tny_account_is_virtual_local_folders (account)) {
1292 /* Local folders: */
1294 /* Get device name */
1295 gchar *device_name = modest_conf_get_string (modest_runtime_get_conf(),
1296 MODEST_CONF_DEVICE_NAME, NULL);
1298 label = g_strdup_printf (_("mcen_fi_localroot_description"),
1300 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1301 g_free (device_name);
1304 if(!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1305 gtk_box_pack_start (GTK_BOX (vbox),
1306 gtk_label_new (tny_account_get_name (account)),
1309 /* Other accounts, such as IMAP and POP: */
1314 /* Put proto in uppercase */
1315 proto = g_string_new (tny_account_get_proto (account));
1316 proto = g_string_ascii_up (proto);
1318 /* note: mcen_fi_localroot_description is something like "%s account"
1319 * however, we should display "%s account: %s"... therefore, ugly tmp */
1320 tmp = g_strdup_printf (_("mcen_fi_remoteroot_account"),proto->str);
1321 label = g_strdup_printf ("%s: %s", tmp,tny_account_get_name (account));
1324 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1325 g_string_free (proto, TRUE);
1331 TnyFolderStore *folder_store = TNY_FOLDER_STORE (account);
1332 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_messages"),
1333 modest_tny_folder_store_get_message_count (folder_store));
1334 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1338 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_folders"),
1339 modest_tny_folder_store_get_folder_count (folder_store));
1340 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1344 if (modest_tny_account_is_virtual_local_folders (account)) {
1345 /* FIXME: format size */
1346 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_size"),
1347 modest_tny_folder_store_get_local_size (folder_store));
1348 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1350 } else if (TNY_IS_ACCOUNT(folder_store)) {
1351 TnyAccount *account = TNY_ACCOUNT(folder_store);
1353 time_t last_updated;
1354 gchar *last_updated_string;
1355 /* Get last updated from configuration */
1356 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1357 tny_account_get_id (account),
1358 MODEST_ACCOUNT_LAST_UPDATED,
1360 if (last_updated > 0)
1361 last_updated_string = modest_text_utils_get_display_date(last_updated);
1363 last_updated_string = g_strdup (_("FIXME: Never"));
1365 label = g_strdup_printf ("%s: %s", _("mcen_ti_lastupdated"), last_updated_string);
1366 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1367 g_free (last_updated_string);
1372 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1378 modest_main_window_notify_send_receive_initied (ModestMainWindow *self)
1380 GtkAction *action = NULL;
1381 GtkWidget *widget = NULL;
1383 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1385 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1386 gtk_action_set_sensitive (action, FALSE);
1387 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");
1388 gtk_action_set_sensitive (action, FALSE);
1389 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1390 gtk_widget_set_sensitive (widget, FALSE);
1394 modest_main_window_notify_send_receive_completed (ModestMainWindow *self)
1396 GtkAction *action = NULL;
1397 GtkWidget *widget = NULL;
1399 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1401 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu");
1402 gtk_action_set_sensitive (action, TRUE);
1403 action = modest_window_get_action (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveCancelSendingMenu");
1404 gtk_action_set_sensitive (action, TRUE);
1405 widget = modest_window_get_action_widget (MODEST_WINDOW(self), "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsMenuAdditions");
1406 gtk_widget_set_sensitive (widget, TRUE);
1411 modest_main_window_set_contents_style (ModestMainWindow *self,
1412 ModestMainWindowContentsStyle style)
1414 ModestMainWindowPrivate *priv;
1416 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1418 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1420 /* We allow to set the same content style than the previously
1421 set if there are details, because it could happen when we're
1422 selecting different accounts consecutively */
1423 if ((priv->contents_style == style) &&
1424 (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS))
1427 /* Remove previous child. Delete it if it was an account
1429 GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1431 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1432 g_object_ref (content);
1433 else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1434 g_object_ref (priv->empty_view);
1435 gtk_container_remove (GTK_CONTAINER (content), priv->empty_view);
1438 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1441 priv->contents_style = style;
1443 switch (priv->contents_style) {
1444 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1445 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1447 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1449 /* TODO: show here account details */
1450 TnyFolderStore *selected_folderstore =
1451 modest_folder_view_get_selected (priv->folder_view);
1452 if (TNY_IS_ACCOUNT (selected_folderstore)) {
1453 priv->details_widget = create_details_widget (
1454 TNY_ACCOUNT (selected_folderstore));
1456 wrap_in_scrolled_window (priv->contents_widget,
1457 priv->details_widget);
1461 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY:
1462 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view));
1465 g_return_if_reached ();
1469 gtk_widget_show_all (priv->contents_widget);
1473 on_configuration_key_changed (ModestConf* conf,
1475 ModestConfEvent event,
1476 ModestMainWindow *self)
1478 ModestMainWindowPrivate *priv;
1479 TnyAccount *account;
1481 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1484 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1486 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1489 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1490 if (TNY_IS_ACCOUNT (account) &&
1491 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1494 const gchar *device_name;
1498 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1499 label = GTK_LABEL (children->data);
1501 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1502 MODEST_CONF_DEVICE_NAME, NULL);
1504 new_text = g_strdup_printf ("%s: %s",
1505 _("mcen_fi_localroot_description"),
1508 gtk_label_set_text (label, new_text);
1509 gtk_widget_show (GTK_WIDGET (label));
1512 g_list_free (children);
1517 set_toolbar_transfer_mode (ModestMainWindow *self)
1519 ModestMainWindowPrivate *priv = NULL;
1521 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1523 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1525 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1527 if (priv->progress_bar_timeout > 0) {
1528 g_source_remove (priv->progress_bar_timeout);
1529 priv->progress_bar_timeout = 0;
1536 set_toolbar_mode (ModestMainWindow *self,
1537 ModestToolBarModes mode)
1539 ModestWindowPrivate *parent_priv = NULL;
1540 ModestMainWindowPrivate *priv = NULL;
1541 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1543 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1545 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1546 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1548 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1550 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1551 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1552 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1554 /* Sets current toolbar mode */
1555 priv->current_toolbar_mode = mode;
1557 /* Show and hide toolbar items */
1559 case TOOLBAR_MODE_NORMAL:
1561 gtk_action_set_visible (sort_action, TRUE);
1563 gtk_action_set_visible (refresh_action, TRUE);
1564 if (priv->progress_toolitem) {
1565 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1566 gtk_widget_hide (priv->progress_toolitem);
1568 if (priv->progress_bar)
1569 gtk_widget_hide (priv->progress_bar);
1572 gtk_action_set_visible (cancel_action, FALSE);
1574 /* Hide toolbar if optimized view is enabled */
1575 if (priv->optimized_view)
1576 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1578 case TOOLBAR_MODE_TRANSFER:
1580 gtk_action_set_visible (sort_action, FALSE);
1582 gtk_action_set_visible (refresh_action, FALSE);
1584 gtk_action_set_visible (cancel_action, TRUE);
1585 if (priv->progress_toolitem) {
1586 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1587 gtk_widget_show (priv->progress_toolitem);
1589 if (priv->progress_bar)
1590 gtk_widget_show (priv->progress_bar);
1592 /* Show toolbar if it's hiden (optimized view ) */
1593 if (priv->optimized_view)
1594 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1597 g_return_if_reached ();
1602 cancel_progressbar (GtkToolButton *toolbutton,
1603 ModestMainWindow *self)
1606 ModestMainWindowPrivate *priv;
1608 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1610 /* Get operation observers and cancel its current operation */
1611 tmp = priv->progress_widgets;
1613 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1614 tmp=g_slist_next(tmp);
1619 observers_empty (ModestMainWindow *self)
1622 ModestMainWindowPrivate *priv;
1623 gboolean is_empty = TRUE;
1624 guint pending_ops = 0;
1626 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1627 tmp = priv->progress_widgets;
1629 /* Check all observers */
1630 while (tmp && is_empty) {
1631 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1632 is_empty = pending_ops == 0;
1634 tmp = g_slist_next(tmp);
1641 on_queue_changed (ModestMailOperationQueue *queue,
1642 ModestMailOperation *mail_op,
1643 ModestMailOperationQueueNotification type,
1644 ModestMainWindow *self)
1646 ModestMainWindowPrivate *priv;
1647 ModestMailOperationTypeOperation op_type;
1648 ModestToolBarModes mode;
1650 gboolean mode_changed = FALSE;
1651 /* ModestMailOperationStatus status; */
1653 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1654 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1656 /* Get toolbar mode from operation id*/
1657 op_type = modest_mail_operation_get_type_operation (mail_op);
1659 case MODEST_MAIL_OPERATION_TYPE_SEND:
1660 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1661 mode = TOOLBAR_MODE_TRANSFER;
1662 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1663 mode_changed = TRUE;
1666 mode = TOOLBAR_MODE_NORMAL;
1671 /* Add operation observers and change toolbar if neccessary*/
1672 tmp = priv->progress_widgets;
1674 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1675 if (mode == TOOLBAR_MODE_TRANSFER) {
1677 set_toolbar_transfer_mode(self);
1679 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1681 tmp = g_slist_next (tmp);
1685 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1686 /* Change toolbar mode */
1687 if (mode == TOOLBAR_MODE_TRANSFER) {
1689 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1691 tmp = g_slist_next (tmp);
1694 /* If no more operations are being observed, NORMAL mode is enabled again */
1695 if (observers_empty (self)) {
1696 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1707 on_show_account_action_activated (GtkAction *action,
1710 ModestAccountData *acc_data;
1711 ModestMainWindow *self;
1712 ModestMainWindowPrivate *priv;
1713 ModestAccountMgr *mgr;
1714 const gchar *acc_name;
1716 self = MODEST_MAIN_WINDOW (user_data);
1717 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1719 /* Get account data */
1720 acc_name = gtk_action_get_name (action);
1721 mgr = modest_runtime_get_account_mgr ();
1722 acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
1724 /* Set the new visible & active account */
1725 if (acc_data->store_account) {
1726 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
1727 acc_data->store_account->account_name);
1728 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
1732 modest_account_mgr_free_account_data (mgr, acc_data);
1736 refresh_account (const gchar *account_name)
1740 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
1742 /* If account_name == NULL, we must update all (option All) */
1744 modest_ui_actions_do_send_receive_all (win);
1746 modest_ui_actions_do_send_receive (account_name, win);
1750 on_refresh_account_action_activated (GtkAction *action,
1753 refresh_account ((const gchar*) user_data);
1757 on_send_receive_csm_activated (GtkMenuItem *item,
1760 refresh_account ((const gchar*) user_data);