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 "modest-hildon-includes.h"
35 #include "modest-defs.h"
38 #include "widgets/modest-main-window.h"
39 #include "widgets/modest-msg-edit-window.h"
40 #include "widgets/modest-account-view-window.h"
41 #include "modest-runtime.h"
42 #include "modest-account-mgr-helpers.h"
43 #include "modest-platform.h"
44 #include "modest-widget-memory.h"
45 #include "modest-window-priv.h"
46 #include "modest-main-window-ui.h"
47 #include "modest-account-mgr.h"
48 #include "modest-tny-account.h"
49 #include "modest-conf.h"
50 #include <modest-maemo-utils.h>
51 #include "modest-tny-platform-factory.h"
52 #include "modest-tny-msg.h"
53 #include "modest-mail-operation.h"
54 #include "modest-icon-names.h"
55 #include "modest-progress-bar-widget.h"
56 #include "modest-text-utils.h"
57 #include "maemo/modest-osso-state-saving.h"
59 #ifdef MODEST_HILDON_VERSION_0
60 #include <hildon-widgets/hildon-program.h>
62 #include <hildon/hildon-program.h>
63 #endif /*MODEST_HILDON_VERSION_0*/
65 #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions"
67 /* 'private'/'protected' functions */
68 static void modest_main_window_class_init (ModestMainWindowClass *klass);
69 static void modest_main_window_init (ModestMainWindow *obj);
70 static void modest_main_window_finalize (GObject *obj);
71 static gboolean modest_main_window_window_state_event (GtkWidget *widget,
72 GdkEventWindowState *event,
75 static void connect_signals (ModestMainWindow *self);
77 static void restore_settings (ModestMainWindow *self);
78 static void save_state (ModestWindow *self);
80 static void modest_main_window_show_toolbar (ModestWindow *window,
81 gboolean show_toolbar);
83 static void cancel_progressbar (GtkToolButton *toolbutton,
84 ModestMainWindow *self);
86 static void on_queue_changed (ModestMailOperationQueue *queue,
87 ModestMailOperation *mail_op,
88 ModestMailOperationQueueNotification type,
89 ModestMainWindow *self);
91 static void on_account_update (TnyAccountStore *account_store,
92 const gchar *account_name,
95 static gboolean on_inner_widgets_key_pressed (GtkWidget *widget,
99 static void on_configuration_key_changed (ModestConf* conf,
101 ModestConfEvent event,
102 ModestMainWindow *self);
104 static void set_toolbar_mode (ModestMainWindow *self,
105 ModestToolBarModes mode);
107 static gboolean set_toolbar_transfer_mode (ModestMainWindow *self);
109 static void on_show_account_action_activated (GtkAction *action,
112 static void on_send_receive_csm_activated (GtkMenuItem *item,
114 /* list my signals */
122 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
123 struct _ModestMainWindowPrivate {
124 GtkWidget *msg_paned;
125 GtkWidget *main_paned;
126 GtkWidget *main_vbox;
127 GtkWidget *contents_widget;
129 /* Progress observers */
130 GtkWidget *progress_bar;
131 GSList *progress_widgets;
134 GtkWidget *progress_toolitem;
135 GtkWidget *cancel_toolitem;
136 GtkWidget *sort_toolitem;
137 GtkWidget *refresh_toolitem;
138 ModestToolBarModes current_toolbar_mode;
140 /* Merge ids used to add/remove accounts to the ViewMenu*/
141 GByteArray *merge_ids;
143 /* On-demand widgets */
144 GtkWidget *accounts_popup;
145 GtkWidget *details_widget;
147 /* Optimized view enabled */
148 gboolean optimized_view;
150 ModestHeaderView *header_view;
151 ModestFolderView *folder_view;
153 ModestMainWindowStyle style;
154 ModestMainWindowContentsStyle contents_style;
156 guint progress_bar_timeout;
159 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
160 MODEST_TYPE_MAIN_WINDOW, \
161 ModestMainWindowPrivate))
163 typedef struct _GetMsgAsyncHelper {
164 ModestMainWindowPrivate *main_window_private;
166 ModestTnyMsgReplyType reply_type;
167 ModestTnyMsgForwardType forward_type;
174 static GtkWindowClass *parent_class = NULL;
177 /* Private actions */
178 /* This is the context sensitive menu: */
179 static const GtkActionEntry modest_folder_view_action_entries [] = {
181 /* Folder View CSM actions */
182 { "FolderViewCSMNewFolder", NULL, N_("mcen_ti_new_folder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_new_folder) },
183 { "FolderViewCSMRenameFolder", NULL, N_("mcen_me_user_renamefolder"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_rename_folder) },
184 { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, NULL },
185 { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) },
186 { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, NULL },
187 { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, NULL },
191 static const GtkToggleActionEntry modest_main_window_toggle_action_entries [] = {
192 { "ToolbarToggleView", MODEST_STOCK_SPLIT_VIEW, N_("gqn_toolb_rss_fldonoff"), "<CTRL>t", NULL, G_CALLBACK (modest_ui_actions_toggle_folders_view), FALSE },
195 /************************************************************************/
198 modest_main_window_get_type (void)
200 static GType my_type = 0;
202 static const GTypeInfo my_info = {
203 sizeof(ModestMainWindowClass),
204 NULL, /* base init */
205 NULL, /* base finalize */
206 (GClassInitFunc) modest_main_window_class_init,
207 NULL, /* class finalize */
208 NULL, /* class data */
209 sizeof(ModestMainWindow),
211 (GInstanceInitFunc) modest_main_window_init,
214 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
222 modest_main_window_class_init (ModestMainWindowClass *klass)
224 GObjectClass *gobject_class;
225 gobject_class = (GObjectClass*) klass;
226 ModestWindowClass *modest_window_class = (ModestWindowClass *) klass;
228 parent_class = g_type_class_peek_parent (klass);
229 gobject_class->finalize = modest_main_window_finalize;
231 g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
233 modest_window_class->show_toolbar_func = modest_main_window_show_toolbar;
234 modest_window_class->save_state_func = save_state;
238 modest_main_window_init (ModestMainWindow *obj)
240 ModestMainWindowPrivate *priv;
242 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
244 priv->msg_paned = NULL;
245 priv->main_paned = NULL;
246 priv->main_vbox = NULL;
247 priv->header_view = NULL;
248 priv->folder_view = NULL;
249 priv->contents_widget = NULL;
250 priv->accounts_popup = NULL;
251 priv->details_widget = NULL;
253 priv->progress_widgets = NULL;
254 priv->progress_bar = NULL;
255 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
257 priv->style = MODEST_MAIN_WINDOW_STYLE_SPLIT;
258 priv->contents_style = MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS;
260 priv->merge_ids = NULL;
262 priv->optimized_view = FALSE;
263 priv->progress_bar_timeout = 0;
267 modest_main_window_finalize (GObject *obj)
269 ModestMainWindowPrivate *priv;
271 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
273 g_slist_free (priv->progress_widgets);
275 g_byte_array_free (priv->merge_ids, TRUE);
277 if (priv->progress_bar_timeout > 0) {
278 g_source_remove (priv->progress_bar_timeout);
279 priv->progress_bar_timeout = 0;
282 G_OBJECT_CLASS(parent_class)->finalize (obj);
286 modest_main_window_get_child_widget (ModestMainWindow *self,
287 ModestWidgetType widget_type)
289 ModestMainWindowPrivate *priv;
292 g_return_val_if_fail (self, NULL);
293 g_return_val_if_fail (widget_type >= 0 && widget_type < MODEST_WIDGET_TYPE_NUM,
296 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
298 switch (widget_type) {
299 case MODEST_WIDGET_TYPE_HEADER_VIEW:
300 widget = (GtkWidget*)priv->header_view; break;
301 case MODEST_WIDGET_TYPE_FOLDER_VIEW:
302 widget = (GtkWidget*)priv->folder_view; break;
307 return widget ? GTK_WIDGET(widget) : NULL;
313 restore_settings (ModestMainWindow *self)
316 ModestMainWindowPrivate *priv;
318 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
320 conf = modest_runtime_get_conf ();
322 modest_widget_memory_restore (conf, G_OBJECT(self),
323 MODEST_CONF_MAIN_WINDOW_KEY);
324 modest_widget_memory_restore (conf, G_OBJECT(priv->main_paned),
325 MODEST_CONF_MAIN_PANED_KEY);
326 modest_widget_memory_restore (conf, G_OBJECT(priv->header_view),
327 MODEST_CONF_HEADER_VIEW_KEY);
332 save_state (ModestWindow *window)
335 ModestMainWindow* self = MODEST_MAIN_WINDOW(window);
336 ModestMainWindowPrivate *priv;
338 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
339 conf = modest_runtime_get_conf ();
341 modest_widget_memory_save (conf,G_OBJECT(self),
342 MODEST_CONF_MAIN_WINDOW_KEY);
343 modest_widget_memory_save (conf, G_OBJECT(priv->main_paned),
344 MODEST_CONF_MAIN_PANED_KEY);
345 modest_widget_memory_save (conf, G_OBJECT(priv->header_view),
346 MODEST_CONF_HEADER_VIEW_KEY);
350 wrap_in_scrolled_window (GtkWidget *win, GtkWidget *widget)
352 if (!gtk_widget_set_scroll_adjustments (widget, NULL, NULL))
353 gtk_scrolled_window_add_with_viewport
354 (GTK_SCROLLED_WINDOW(win), widget);
356 gtk_container_add (GTK_CONTAINER(win),
362 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMainWindow *self)
364 modest_window_save_state (MODEST_WINDOW(self));
370 on_account_store_connecting_finished (TnyAccountStore *store, ModestMainWindow *self)
372 /* When going online, do the equivalent of pressing the send/receive button,
373 * as per the specification:
374 * (without the check for >0 accounts, though that is not specified): */
375 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (self));
381 connect_signals (ModestMainWindow *self)
383 ModestWindowPrivate *parent_priv;
384 ModestMainWindowPrivate *priv;
387 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
388 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
391 g_signal_connect (G_OBJECT(priv->folder_view), "key-press-event",
392 G_CALLBACK(on_inner_widgets_key_pressed), self);
393 g_signal_connect (G_OBJECT(priv->folder_view), "folder_selection_changed",
394 G_CALLBACK(modest_ui_actions_on_folder_selection_changed), self);
395 g_signal_connect (G_OBJECT(priv->folder_view), "folder-display-name-changed",
396 G_CALLBACK(modest_ui_actions_on_folder_display_name_changed), self);
398 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/FolderViewCSM");
399 gtk_widget_tap_and_hold_setup (GTK_WIDGET (priv->folder_view), menu, NULL, 0);
402 /* g_signal_connect (G_OBJECT(priv->header_view), "status_update", */
403 /* G_CALLBACK(modest_ui_actions_on_header_status_update), self); */
404 g_signal_connect (G_OBJECT(priv->header_view), "header_selected",
405 G_CALLBACK(modest_ui_actions_on_header_selected), self);
406 g_signal_connect (G_OBJECT(priv->header_view), "header_activated",
407 G_CALLBACK(modest_ui_actions_on_header_activated), self);
408 g_signal_connect (G_OBJECT(priv->header_view), "item_not_found",
409 G_CALLBACK(modest_ui_actions_on_item_not_found), self);
410 g_signal_connect (G_OBJECT(priv->header_view), "key-press-event",
411 G_CALLBACK(on_inner_widgets_key_pressed), self);
414 g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
415 g_signal_connect (G_OBJECT (self), "window-state-event",
416 G_CALLBACK (modest_main_window_window_state_event),
418 g_signal_connect (G_OBJECT(self), "delete-event", G_CALLBACK(on_delete_event), self);
420 /* Mail Operation Queue */
421 g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
423 G_CALLBACK (on_queue_changed),
426 /* Track changes in the device name */
427 g_signal_connect (G_OBJECT(modest_runtime_get_conf ()),
429 G_CALLBACK (on_configuration_key_changed),
432 /* Track account changes. We need to refresh the toolbar */
433 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
435 G_CALLBACK (on_account_update),
439 g_signal_connect (G_OBJECT (modest_runtime_get_account_store()), "password_requested",
440 G_CALLBACK (modest_ui_actions_on_password_requested), self);
443 g_signal_connect (G_OBJECT(modest_runtime_get_account_store()), "connecting-finished",
444 G_CALLBACK(on_account_store_connecting_finished), self);
448 /** Idle handler, to send/receive at startup .*/
450 sync_accounts_cb (ModestMainWindow *win)
452 modest_ui_actions_do_send_receive (NULL, MODEST_WINDOW (win));
453 return FALSE; /* Do not call this idle handler again. */
457 static void on_hildon_program_is_topmost_notify(GObject *self,
458 GParamSpec *propert_param, gpointer user_data)
460 HildonProgram *app = HILDON_PROGRAM (self);
463 ModestWindow* self = MODEST_WINDOW(user_data);
466 /* Note that use of hildon_program_set_can_hibernate()
467 * is generally referred to as "setting the killable flag",
468 * though hibernation does not seem equal to death.
471 if (hildon_program_get_is_topmost (app)) {
472 /* Prevent hibernation when the progam comes to the foreground,
473 * because hibernation should only happen when the application
474 * is in the background: */
475 hildon_program_set_can_hibernate (app, FALSE);
477 /* Allow hibernation if the program has gone to the background: */
479 /* However, prevent hibernation while the settings are being changed: */
480 const gboolean hibernation_prevented =
481 modest_window_mgr_get_hibernation_is_prevented (
482 modest_runtime_get_window_mgr ());
484 if (hibernation_prevented)
485 hildon_program_set_can_hibernate (app, FALSE);
487 /* Allow hibernation, after saving the state: */
488 modest_osso_save_state();
489 hildon_program_set_can_hibernate (app, TRUE);
498 modest_main_window_new (void)
500 ModestMainWindow *self;
501 ModestMainWindowPrivate *priv;
502 ModestWindowPrivate *parent_priv;
503 GtkWidget *folder_win;
504 GtkActionGroup *action_group;
505 GError *error = NULL;
506 TnyFolderStoreQuery *query;
507 GdkPixbuf *window_icon;
511 self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL));
512 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
513 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
515 parent_priv->ui_manager = gtk_ui_manager_new();
516 action_group = gtk_action_group_new ("ModestMainWindowActions");
517 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
519 /* Add common actions */
520 gtk_action_group_add_actions (action_group,
521 modest_action_entries,
522 G_N_ELEMENTS (modest_action_entries),
525 gtk_action_group_add_actions (action_group,
526 modest_folder_view_action_entries,
527 G_N_ELEMENTS (modest_folder_view_action_entries),
530 gtk_action_group_add_toggle_actions (action_group,
531 modest_toggle_action_entries,
532 G_N_ELEMENTS (modest_toggle_action_entries),
535 gtk_action_group_add_toggle_actions (action_group,
536 modest_main_window_toggle_action_entries,
537 G_N_ELEMENTS (modest_main_window_toggle_action_entries),
540 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
541 g_object_unref (action_group);
543 /* Load the UI definition */
544 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
545 MODEST_UIDIR "modest-main-window-ui.xml", &error);
547 g_warning ("Could not merge modest-ui.xml: %s", error->message);
548 g_error_free (error);
552 /* Add accelerators */
553 gtk_window_add_accel_group (GTK_WINDOW (self),
554 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
556 /* Menubar. Update the state of some toggles */
557 parent_priv->menubar = modest_maemo_utils_menubar_to_menu (parent_priv->ui_manager);
558 conf = modest_runtime_get_conf ();
559 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
560 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarNormalScreenMenu");
561 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
562 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL));
563 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
564 "/MenuBar/ViewMenu/ViewShowToolbarMainMenu/ViewShowToolbarFullScreenMenu");
565 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
566 modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL));
567 hildon_window_set_menu (HILDON_WINDOW (self), GTK_MENU (parent_priv->menubar));
569 /* Get device name */
570 modest_maemo_utils_get_device_name ();
573 query = tny_folder_store_query_new ();
574 tny_folder_store_query_add_item (query, NULL,
575 TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
576 priv->folder_view = MODEST_FOLDER_VIEW(modest_folder_view_new (query));
577 if (!priv->folder_view)
578 g_printerr ("modest: cannot instantiate folder view\n");
579 g_object_unref (G_OBJECT (query));
580 modest_folder_view_set_style (priv->folder_view,
581 MODEST_FOLDER_VIEW_STYLE_SHOW_ONE);
585 MODEST_HEADER_VIEW(modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS));
586 if (!priv->header_view)
587 g_printerr ("modest: cannot instantiate header view\n");
588 modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES);
590 /* Create scrolled windows */
591 folder_win = gtk_scrolled_window_new (NULL, NULL);
592 priv->contents_widget = gtk_scrolled_window_new (NULL, NULL);
593 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (folder_win),
595 GTK_POLICY_AUTOMATIC);
596 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->contents_widget),
598 GTK_POLICY_AUTOMATIC);
600 wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view));
601 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET(priv->header_view));
604 priv->main_paned = gtk_hpaned_new ();
605 gtk_paned_add1 (GTK_PANED(priv->main_paned), folder_win);
606 gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->contents_widget);
607 gtk_widget_show (GTK_WIDGET(priv->header_view));
608 gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
610 /* putting it all together... */
611 priv->main_vbox = gtk_vbox_new (FALSE, 6);
612 gtk_box_pack_start (GTK_BOX(priv->main_vbox), priv->main_paned, TRUE, TRUE,0);
614 gtk_container_add (GTK_CONTAINER(self), priv->main_vbox);
615 restore_settings (MODEST_MAIN_WINDOW(self));
617 /* Set window icon */
618 window_icon = modest_platform_get_icon (MODEST_APP_ICON);
619 gtk_window_set_icon (GTK_WINDOW (self), window_icon);
621 /* Connect signals */
622 connect_signals (self);
624 /* Set account store */
625 tny_account_store_view_set_account_store (TNY_ACCOUNT_STORE_VIEW (priv->folder_view),
626 TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
628 /* Do send & receive when we are idle */
629 /* TODO: Enable this again. I have commented it out because,
630 * at least in scratchbox, this can cause us to start a second
631 * update (in response to a connection change) when we are already
632 * doing an update (started here, at startup). Tinymail doesn't like that.
635 /* g_idle_add ((GSourceFunc)sync_accounts_cb, self); */
637 HildonProgram *app = hildon_program_get_instance ();
638 hildon_program_add_window (app, HILDON_WINDOW (self));
640 /* Register HildonProgram signal handlers: */
641 /* These are apparently deprecated, according to the
642 * "HildonApp/HildonAppView to HildonProgram/HildonWindow migration guide",
643 * though the API reference does not mention that:
645 g_signal_connect (G_OBJECT(app), "topmost_status_lose",
646 G_CALLBACK (on_hildon_program_save_state), self);
647 g_signal_connect (G_OBJECT(app), "topmost_status_acquire",
648 G_CALLBACK (on_hildon_program_status_acquire), self);
650 g_signal_connect (G_OBJECT(app), "notify::is-topmost",
651 G_CALLBACK (on_hildon_program_is_topmost_notify), self);
653 /* Load previous osso state, for instance if we are being restored from
655 modest_osso_load_state();
657 return MODEST_WINDOW(self);
661 modest_main_window_close_all (ModestMainWindow *self)
664 GtkResponseType response;
666 /* Create the confirmation dialog MSG-NOT308 */
667 note = hildon_note_new_confirmation_add_buttons (GTK_WINDOW (self),
668 _("emev_nc_close_windows"),
669 _("mcen_bd_yes"), GTK_RESPONSE_YES,
670 _("mcen_bd_no"), GTK_RESPONSE_NO,
673 response = gtk_dialog_run (GTK_DIALOG (note));
674 gtk_widget_destroy (GTK_WIDGET (note));
676 if (response == GTK_RESPONSE_YES)
684 modest_main_window_set_style (ModestMainWindow *self,
685 ModestMainWindowStyle style)
687 ModestMainWindowPrivate *priv;
688 ModestWindowPrivate *parent_priv;
691 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
693 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
694 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
696 /* no change -> nothing to do */
697 if (priv->style == style)
700 /* Get toggle button */
701 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarToggleView");
706 case MODEST_MAIN_WINDOW_STYLE_SIMPLE:
707 /* Remove main paned */
708 g_object_ref (priv->main_paned);
709 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
711 /* Reparent the contents widget to the main vbox */
712 gtk_widget_reparent (priv->contents_widget, priv->main_vbox);
714 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
715 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
716 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
719 case MODEST_MAIN_WINDOW_STYLE_SPLIT:
720 /* Remove header view */
721 g_object_ref (priv->contents_widget);
722 gtk_container_remove (GTK_CONTAINER (priv->main_vbox), priv->contents_widget);
724 /* Reparent the main paned */
725 gtk_paned_add2 (GTK_PANED (priv->main_paned), priv->contents_widget);
726 gtk_container_add (GTK_CONTAINER (priv->main_vbox), priv->main_paned);
728 g_signal_handlers_block_by_func (action, modest_ui_actions_toggle_folders_view, self);
729 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE);
730 g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self);
734 g_return_if_reached ();
737 /* Let header view grab the focus if it's being shown */
738 if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
739 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
741 gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget));
744 gtk_widget_show_all (GTK_WIDGET (priv->main_vbox));
747 ModestMainWindowStyle
748 modest_main_window_get_style (ModestMainWindow *self)
750 ModestMainWindowPrivate *priv;
752 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), -1);
754 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
761 modest_main_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
763 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
764 ModestWindowPrivate *parent_priv;
765 ModestWindowMgr *mgr;
766 gboolean is_fullscreen;
767 GtkAction *fs_toggle_action;
770 mgr = modest_runtime_get_window_mgr ();
772 is_fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
774 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
776 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
777 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
778 if (is_fullscreen != active) {
779 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
788 set_homogeneous (GtkWidget *widget,
791 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
792 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
796 modest_main_window_show_toolbar (ModestWindow *self,
797 gboolean show_toolbar)
799 ModestMainWindowPrivate *priv = NULL;
800 ModestWindowPrivate *parent_priv = NULL;
801 GtkWidget *reply_button = NULL, *menu = NULL;
802 GtkWidget *placeholder = NULL;
805 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
806 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
807 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
809 /* Set optimized view status */
810 priv->optimized_view = !show_toolbar;
812 if (!parent_priv->toolbar) {
813 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
816 /* Set homogeneous toolbar */
817 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
818 set_homogeneous, NULL);
820 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
821 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
822 priv->refresh_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
823 priv->sort_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
824 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
825 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
826 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
827 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
829 /* Add ProgressBar (Transfer toolbar) */
830 priv->progress_bar = modest_progress_bar_widget_new ();
831 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
832 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressBarView");
833 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
834 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
835 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
837 /* Connect cancel 'clicked' signal to abort progress mode */
838 g_signal_connect(priv->cancel_toolitem, "clicked",
839 G_CALLBACK(cancel_progressbar),
842 /* Add it to the observers list */
843 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
846 hildon_window_add_toolbar (HILDON_WINDOW (self),
847 GTK_TOOLBAR (parent_priv->toolbar));
849 /* Set reply button tap and hold menu */
850 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
851 "/ToolBar/ToolbarMessageReply");
852 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
854 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
856 /* Set send & receive button tap and hold menu */
857 on_account_update (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()),
862 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
863 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
864 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
866 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
867 set_toolbar_mode (MODEST_MAIN_WINDOW(self), TOOLBAR_MODE_NORMAL);
869 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
874 compare_display_names (ModestAccountData *a,
875 ModestAccountData *b)
877 return strcmp (a->display_name, b->display_name);
881 on_account_update (TnyAccountStore *account_store,
882 const gchar *account_name,
885 GSList *account_names, *iter, *accounts;
886 ModestMainWindow *self;
887 ModestMainWindowPrivate *priv;
888 ModestWindowPrivate *parent_priv;
889 ModestAccountMgr *mgr;
890 gint i, num_accounts;
891 GtkActionGroup *action_group;
893 gchar *default_account;
894 GtkWidget *send_receive_button, *item;
896 self = MODEST_MAIN_WINDOW (user_data);
897 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self);
898 parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
900 /* Get enabled account IDs */
901 mgr = modest_runtime_get_account_mgr ();
902 account_names = modest_account_mgr_account_names (mgr, TRUE);
903 iter = account_names;
907 ModestAccountData *account_data =
908 modest_account_mgr_get_account_data (mgr, (gchar*) iter->data);
909 accounts = g_slist_prepend (accounts, account_data);
913 g_slist_free (account_names);
915 /* Order the list of accounts by its display name */
916 accounts = g_slist_sort (accounts, (GCompareFunc) compare_display_names);
917 num_accounts = g_slist_length (accounts);
919 /* Delete old send&receive popup items. We can not just do a
920 menu_detach because it does not work well with
922 if (priv->accounts_popup)
923 gtk_container_foreach (GTK_CONTAINER (priv->accounts_popup), (GtkCallback) gtk_widget_destroy, NULL);
925 /* Delete old entries in the View menu. Do not free groups, it
927 groups = gtk_ui_manager_get_action_groups (parent_priv->ui_manager);
929 if (!strcmp (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS,
930 gtk_action_group_get_name (GTK_ACTION_GROUP (groups->data)))) {
931 gtk_ui_manager_remove_action_group (parent_priv->ui_manager,
932 GTK_ACTION_GROUP (groups->data));
935 if (priv->merge_ids) {
936 for (i = 0; i < priv->merge_ids->len; i++)
937 gtk_ui_manager_remove_ui (parent_priv->ui_manager, priv->merge_ids->data[i]);
938 g_byte_array_free (priv->merge_ids, TRUE);
940 /* We need to call this in order to ensure
941 that the new actions are added in the right
942 order (alphabetical */
943 gtk_ui_manager_ensure_update (parent_priv->ui_manager);
945 groups = g_list_next (groups);
947 priv->merge_ids = g_byte_array_sized_new (num_accounts);
949 /* Get send receive button */
950 send_receive_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
951 "/ToolBar/ToolbarSendReceive");
953 /* Create the menu */
954 if (num_accounts > 1) {
955 if (!priv->accounts_popup)
956 priv->accounts_popup = gtk_menu_new ();
957 item = gtk_menu_item_new_with_label (_("mcen_me_toolbar_sendreceive_all"));
958 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
959 g_signal_connect (G_OBJECT (item),
961 G_CALLBACK (on_send_receive_csm_activated),
963 item = gtk_separator_menu_item_new ();
964 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
967 /* Create a new action group */
968 default_account = modest_account_mgr_get_default_account (mgr);
969 action_group = gtk_action_group_new (MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS);
970 for (i = 0; i < num_accounts; i++) {
971 GtkAction *new_action = NULL;
972 gchar *display_name = NULL;
974 ModestAccountData *account_data = (ModestAccountData *) g_slist_nth_data (accounts, i);
976 /* Create display name. The default account is shown differently */
977 if (default_account && account_data->account_name &&
978 !(strcmp (default_account, account_data->account_name) == 0)) {
979 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_default"),
980 account_data->display_name);
983 display_name = g_strdup_printf (_("mcen_me_toolbar_sendreceive_mailbox_n"),
984 account_data->display_name);
987 /* Create action and add it to the action group. The
988 action name must be the account name, this way we
989 could know in the handlers the account to show */
990 if(account_data->account_name) {
991 new_action = gtk_action_new (account_data->account_name, display_name, NULL, NULL);
992 gtk_action_group_add_action (action_group, new_action);
994 /* Add ui from account data. We allow 2^9-1 account
995 changes in a single execution because we're
996 downcasting the guint to a guint8 in order to use a
997 GByteArray, it should be enough */
998 gchar* item_name = g_strconcat (account_data->account_name, "Menu", NULL);
999 guint8 merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager);
1000 priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1);
1001 gtk_ui_manager_add_ui (parent_priv->ui_manager,
1003 "/MenuBar/ViewMenu/ViewMenuAdditions",
1005 account_data->account_name,
1006 GTK_UI_MANAGER_MENUITEM,
1009 /* Connect the action signal "activate" */
1010 g_signal_connect (G_OBJECT (new_action),
1012 G_CALLBACK (on_show_account_action_activated),
1015 /* Create item and add it to the send&receive CSM */
1016 /* TODO: Why is this sometimes NULL? murrayc */
1017 if (priv->accounts_popup) {
1018 item = gtk_menu_item_new_with_label (display_name);
1019 gtk_menu_shell_append (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item));
1020 g_signal_connect_data (G_OBJECT (item),
1022 G_CALLBACK (on_send_receive_csm_activated),
1023 g_strdup (account_data->account_name),
1024 (GClosureNotify) g_free,
1032 g_free (display_name);
1033 modest_account_mgr_free_account_data (mgr, account_data);
1035 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 1);
1037 if (priv->accounts_popup) {
1038 /* Mandatory in order to view the menu contents */
1039 gtk_widget_show_all (priv->accounts_popup);
1041 /* Setup tap_and_hold just if was not done before*/
1042 if (!gtk_menu_get_attach_widget (GTK_MENU (priv->accounts_popup)))
1043 gtk_widget_tap_and_hold_setup (send_receive_button, priv->accounts_popup, NULL, 0);
1047 g_slist_free (accounts);
1048 g_free (default_account);
1052 * This function manages the key events used to navigate between
1053 * header and folder views (when the window is in split view)
1056 * -------------------------------------------------
1057 * HeaderView GDK_Left Move focus to folder view
1058 * FolderView GDK_Right Move focus to header view
1060 * There is no need to scroll to selected row, the widgets will be the
1061 * responsibles of doing that (probably managing the focus-in event
1064 on_inner_widgets_key_pressed (GtkWidget *widget,
1068 ModestMainWindowPrivate *priv;
1070 priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data);
1072 /* Do nothing if we're in SIMPLE style */
1073 if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE)
1076 if (MODEST_IS_HEADER_VIEW (widget) && event->keyval == GDK_Left)
1077 gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view));
1078 else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right)
1079 gtk_widget_grab_focus (GTK_WIDGET (priv->header_view));
1085 set_alignment (GtkWidget *widget,
1088 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0);
1089 gtk_misc_set_padding (GTK_MISC (widget), 0, 0);
1093 create_details_widget (TnyAccount *account)
1098 vbox = gtk_vbox_new (FALSE, 0);
1100 /* Account description */
1101 if (!strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1104 /* Get device name */
1105 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1106 MODEST_CONF_DEVICE_NAME, NULL);
1108 label = g_strdup_printf (_("mcen_fi_localroot_description"),
1110 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1111 g_free (device_name);
1113 } else if (!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1115 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("FIXME: MMC ?"), FALSE, FALSE, 0);
1119 /* Put proto in uppercase */
1120 proto = g_string_new (tny_account_get_proto (account));
1121 proto = g_string_ascii_up (proto);
1123 label = g_strdup_printf ("%s %s: %s",
1125 _("mcen_fi_remoteroot_account"),
1126 tny_account_get_name (account));
1127 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1128 g_string_free (proto, TRUE);
1133 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_messages"),
1134 modest_tny_account_get_message_count (account));
1135 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1139 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_folders"),
1140 modest_tny_account_get_folder_count (account));
1141 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1145 if (!strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1146 /* FIXME: format size */
1147 label = g_strdup_printf ("%s: %d", _("mcen_fi_rootfolder_size"),
1148 modest_tny_account_get_local_size (account));
1149 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1151 } else if (!strcmp (tny_account_get_id (account), MODEST_MMC_ACCOUNT_ID)) {
1152 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("FIXME: MMC ?"), FALSE, FALSE, 0);
1154 time_t last_updated;
1155 gchar *last_updated_string;
1156 /* Get last updated from configuration */
1157 last_updated = modest_account_mgr_get_int (modest_runtime_get_account_mgr (),
1158 tny_account_get_id (account),
1159 MODEST_ACCOUNT_LAST_UPDATED,
1161 if (last_updated > 0)
1162 last_updated_string = modest_text_utils_get_display_date(last_updated);
1164 last_updated_string = g_strdup (_("FIXME: Never"));
1166 label = g_strdup_printf ("%s: %s", _("mcen_ti_lastupdated"), last_updated_string);
1167 gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new (label), FALSE, FALSE, 0);
1168 g_free (last_updated_string);
1173 gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL);
1179 modest_main_window_set_contents_style (ModestMainWindow *self,
1180 ModestMainWindowContentsStyle style)
1182 ModestMainWindowPrivate *priv;
1184 TnyAccount *account;
1186 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1188 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1190 /* We allow to set the same content style than the previously
1191 set if there are details, because it could happen when we're
1192 selecting different accounts consecutively */
1193 if ((priv->contents_style == style) &&
1194 (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS))
1197 /* Remove previous child. Delete it if it was an account
1199 content = gtk_bin_get_child (GTK_BIN (priv->contents_widget));
1200 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1201 g_object_ref (content);
1202 gtk_container_remove (GTK_CONTAINER (priv->contents_widget), content);
1204 priv->contents_style = style;
1206 switch (priv->contents_style) {
1207 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS:
1208 wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view));
1210 case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS:
1211 /* TODO: show here account details */
1212 account = TNY_ACCOUNT (modest_folder_view_get_selected (priv->folder_view));
1213 priv->details_widget = create_details_widget (account);
1215 wrap_in_scrolled_window (priv->contents_widget,
1216 priv->details_widget);
1219 g_return_if_reached ();
1223 gtk_widget_show_all (priv->contents_widget);
1227 on_configuration_key_changed (ModestConf* conf,
1229 ModestConfEvent event,
1230 ModestMainWindow *self)
1232 ModestMainWindowPrivate *priv;
1233 TnyAccount *account;
1235 if (!key || strcmp (key, MODEST_CONF_DEVICE_NAME))
1238 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1240 if (priv->contents_style != MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS)
1243 account = (TnyAccount *) modest_folder_view_get_selected (priv->folder_view);
1244 if (TNY_IS_ACCOUNT (account) &&
1245 !strcmp (tny_account_get_id (account), MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1248 const gchar *device_name;
1252 children = gtk_container_get_children (GTK_CONTAINER (priv->details_widget));
1253 label = GTK_LABEL (children->data);
1255 device_name = modest_conf_get_string (modest_runtime_get_conf(),
1256 MODEST_CONF_DEVICE_NAME, NULL);
1258 new_text = g_strdup_printf ("%s: %s",
1259 _("mcen_fi_localroot_description"),
1262 gtk_label_set_text (label, new_text);
1263 gtk_widget_show (GTK_WIDGET (label));
1266 g_list_free (children);
1271 set_toolbar_transfer_mode (ModestMainWindow *self)
1273 ModestMainWindowPrivate *priv = NULL;
1275 g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (self), FALSE);
1277 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1279 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
1281 if (priv->progress_bar_timeout > 0) {
1282 g_source_remove (priv->progress_bar_timeout);
1283 priv->progress_bar_timeout = 0;
1290 set_toolbar_mode (ModestMainWindow *self,
1291 ModestToolBarModes mode)
1293 ModestWindowPrivate *parent_priv = NULL;
1294 ModestMainWindowPrivate *priv = NULL;
1295 GtkAction *sort_action = NULL, *refresh_action = NULL, *cancel_action = NULL;
1297 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1299 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1300 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1302 g_return_if_fail (GTK_IS_TOOLBAR(parent_priv->toolbar));
1304 sort_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSort");
1305 refresh_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSendReceive");
1306 cancel_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1308 /* Sets current toolbar mode */
1309 priv->current_toolbar_mode = mode;
1311 /* Show and hide toolbar items */
1313 case TOOLBAR_MODE_NORMAL:
1315 gtk_action_set_visible (sort_action, TRUE);
1317 gtk_action_set_visible (refresh_action, TRUE);
1318 if (priv->progress_toolitem) {
1319 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
1320 gtk_widget_hide (priv->progress_toolitem);
1322 if (priv->progress_bar)
1323 gtk_widget_hide (priv->progress_bar);
1326 gtk_action_set_visible (cancel_action, FALSE);
1328 /* Hide toolbar if optimized view is enabled */
1329 if (priv->optimized_view)
1330 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
1332 case TOOLBAR_MODE_TRANSFER:
1334 gtk_action_set_visible (sort_action, FALSE);
1336 gtk_action_set_visible (refresh_action, FALSE);
1338 gtk_action_set_visible (cancel_action, TRUE);
1339 if (priv->progress_toolitem) {
1340 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1341 gtk_widget_show (priv->progress_toolitem);
1343 if (priv->progress_bar)
1344 gtk_widget_show (priv->progress_bar);
1346 /* Show toolbar if it's hiden (optimized view ) */
1347 if (priv->optimized_view)
1348 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1351 g_return_if_reached ();
1356 cancel_progressbar (GtkToolButton *toolbutton,
1357 ModestMainWindow *self)
1360 ModestMainWindowPrivate *priv;
1362 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1364 /* Get operation observers and cancel its current operation */
1365 tmp = priv->progress_widgets;
1367 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1368 tmp=g_slist_next(tmp);
1373 observers_empty (ModestMainWindow *self)
1376 ModestMainWindowPrivate *priv;
1377 gboolean is_empty = TRUE;
1378 guint pending_ops = 0;
1380 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1381 tmp = priv->progress_widgets;
1383 /* Check all observers */
1384 while (tmp && is_empty) {
1385 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1386 is_empty = pending_ops == 0;
1388 tmp = g_slist_next(tmp);
1395 on_queue_changed (ModestMailOperationQueue *queue,
1396 ModestMailOperation *mail_op,
1397 ModestMailOperationQueueNotification type,
1398 ModestMainWindow *self)
1400 ModestMainWindowPrivate *priv;
1401 ModestMailOperationId op_id;
1402 ModestToolBarModes mode;
1404 gboolean mode_changed = FALSE;
1405 ModestMailOperationStatus status;
1407 g_return_if_fail (MODEST_IS_MAIN_WINDOW (self));
1408 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1410 /* Get toolbar mode from operation id*/
1411 op_id = modest_mail_operation_get_id (mail_op);
1413 case MODEST_MAIL_OPERATION_ID_SEND:
1414 case MODEST_MAIL_OPERATION_ID_RECEIVE:
1415 mode = TOOLBAR_MODE_TRANSFER;
1416 if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL)
1417 mode_changed = TRUE;
1420 mode = TOOLBAR_MODE_NORMAL;
1425 /* Add operation observers and change toolbar if neccessary*/
1426 tmp = priv->progress_widgets;
1428 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1429 if (mode == TOOLBAR_MODE_TRANSFER) {
1431 set_toolbar_transfer_mode(self);
1433 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1435 tmp = g_slist_next (tmp);
1439 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1440 /* If mail_op is mine, check errors */
1441 status = modest_mail_operation_get_status (mail_op);
1442 if (status != MODEST_MAIL_OPERATION_STATUS_SUCCESS)
1443 modest_mail_operation_execute_error_handler (mail_op);
1445 /* Change toolbar mode */
1446 if (mode == TOOLBAR_MODE_TRANSFER) {
1448 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1450 tmp = g_slist_next (tmp);
1453 /* If no more operations are being observed, NORMAL mode is enabled again */
1454 if (observers_empty (self)) {
1455 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1466 on_show_account_action_activated (GtkAction *action,
1469 ModestAccountData *acc_data;
1470 ModestMainWindow *self;
1471 ModestMainWindowPrivate *priv;
1472 ModestAccountMgr *mgr;
1473 const gchar *acc_name;
1475 self = MODEST_MAIN_WINDOW (user_data);
1476 priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
1478 /* Get account data */
1479 acc_name = gtk_action_get_name (action);
1480 mgr = modest_runtime_get_account_mgr ();
1481 acc_data = modest_account_mgr_get_account_data (mgr, acc_name);
1483 /* Set the new visible & active account */
1484 if (acc_data->store_account) {
1485 modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view,
1486 acc_data->store_account->account_name);
1487 modest_window_set_active_account (MODEST_WINDOW (self), acc_data->account_name);
1491 modest_account_mgr_free_account_data (mgr, acc_data);
1495 on_send_receive_csm_activated (GtkMenuItem *item,
1500 win = MODEST_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
1502 /* If user_data == NULL, we must update all (CSM option All) */
1504 modest_ui_actions_do_send_receive_all (win);
1506 modest_ui_actions_do_send_receive ((const gchar *)user_data, win);