X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fmaemo%2Fmodest-main-window.c;h=ce89897b2369163fd10120b26081a4faa2b4dce6;hp=99efb7f695d64a5a5a539e2aa1496f1ca5431e7d;hb=247b5f9e1d7a9557e94b96ac6d50adcef6beb5bd;hpb=560694ccca949ae2163180050581a9e1dbff0c2a diff --git a/src/maemo/modest-main-window.c b/src/maemo/modest-main-window.c index 99efb7f..ce89897 100644 --- a/src/maemo/modest-main-window.c +++ b/src/maemo/modest-main-window.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include "modest-hildon-includes.h" #include "modest-defs.h" @@ -65,6 +64,9 @@ #include "maemo/modest-osso-state-saving.h" #include "modest-text-utils.h" #include "modest-signal-mgr.h" +#ifdef MODEST_USE_LIBTIME +#include +#endif #define MODEST_MAIN_WINDOW_ACTION_GROUP_ADDITIONS "ModestMainWindowActionAdditions" @@ -176,7 +178,14 @@ static void on_updating_msg_list (ModestHeaderView *header_view, static gboolean restore_paned_timeout_handler (gpointer *data); -static gboolean show_retrieving_banner (gpointer user_data); +static gboolean show_opening_banner (gpointer user_data); + +static void on_window_destroy (GtkObject *widget, + gpointer userdata); + +static void on_window_hide (GObject *gobject, + GParamSpec *arg1, + gpointer user_data); typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate; struct _ModestMainWindowPrivate { @@ -229,9 +238,9 @@ struct _ModestMainWindowPrivate { GtkWidget *updating_banner; guint updating_banner_timeout; - /* "Retrieving" banner for header view */ - GtkWidget *retrieving_banner; - guint retrieving_banner_timeout; + /* "Opening" banner for header view */ + GtkWidget *opening_banner; + guint opening_banner_timeout; /* Display state */ osso_display_state_t display_state; @@ -264,7 +273,7 @@ static const GtkActionEntry modest_folder_view_action_entries [] = { { "FolderViewCSMPasteMsgs", NULL, N_("mcen_me_inbox_paste"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_paste)}, { "FolderViewCSMDeleteFolder", NULL, N_("mcen_me_inbox_delete"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_delete_folder) }, { "FolderViewCSMSearchMessages", NULL, N_("mcen_me_inbox_search"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_search_messages) }, - { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_help) }, + { "FolderViewCSMHelp", NULL, N_("mcen_me_inbox_help"), NULL, NULL, G_CALLBACK (modest_ui_actions_on_csm_help) }, }; static const GtkActionEntry modest_header_view_action_entries [] = { @@ -362,8 +371,8 @@ modest_main_window_init (ModestMainWindow *obj) priv->sighandlers = NULL; priv->updating_banner = NULL; priv->updating_banner_timeout = 0; - priv->retrieving_banner = NULL; - priv->retrieving_banner_timeout = 0; + priv->opening_banner = NULL; + priv->opening_banner_timeout = 0; priv->display_state = OSSO_DISPLAY_ON; modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(), @@ -382,6 +391,16 @@ modest_main_window_finalize (GObject *obj) call this function before */ modest_main_window_disconnect_signals (MODEST_WINDOW (obj)); modest_main_window_cleanup_queue_error_signals ((ModestMainWindow *) obj); + + if (priv->empty_view) { + g_object_unref (priv->empty_view); + priv->empty_view = NULL; + } + + if (priv->header_view) { + g_object_unref (priv->header_view); + priv->header_view = NULL; + } g_slist_free (priv->progress_widgets); @@ -402,14 +421,14 @@ modest_main_window_finalize (GObject *obj) priv->updating_banner = NULL; } - if (priv->retrieving_banner_timeout > 0) { - g_source_remove (priv->retrieving_banner_timeout); - priv->retrieving_banner_timeout = 0; + if (priv->opening_banner_timeout > 0) { + g_source_remove (priv->opening_banner_timeout); + priv->opening_banner_timeout = 0; } - if (priv->retrieving_banner) { - gtk_widget_destroy (priv->retrieving_banner); - priv->retrieving_banner = NULL; + if (priv->opening_banner) { + gtk_widget_destroy (priv->opening_banner); + priv->opening_banner = NULL; } if (priv->restore_paned_timeout > 0) { @@ -442,7 +461,9 @@ modest_main_window_get_child_widget (ModestMainWindow *self, return NULL; } - return widget ? GTK_WIDGET(widget) : NULL; + /* Note that the window could have been destroyed, and so + their children, but still have some references */ + return (widget && GTK_IS_WIDGET(widget)) ? GTK_WIDGET(widget) : NULL; } static gboolean @@ -520,8 +541,9 @@ static gint compare_display_names (ModestAccountSettings *a, ModestAccountSettings *b) { - return strcmp (modest_account_settings_get_display_name (a), - modest_account_settings_get_display_name (b)); + return g_utf8_collate (modest_account_settings_get_display_name (a), + modest_account_settings_get_display_name (b)); + } /* We use this function to prevent the send&receive CSM to be shown @@ -682,7 +704,7 @@ update_menus (ModestMainWindow* self) /* Add ui from account data. We allow 2^9-1 account changes in a single execution because we're downcasting the guint to a guint8 in order to use a - GByteArray. It should be enough. */ + GByteArray. It should be enough :-) */ item_name = g_strconcat (account_name, "Menu", NULL); merge_id = (guint8) gtk_ui_manager_new_merge_id (parent_priv->ui_manager); priv->merge_ids = g_byte_array_append (priv->merge_ids, &merge_id, 1); @@ -741,7 +763,8 @@ update_menus (ModestMainWindow* self) item = gtk_menu_item_new (); gtk_container_add (GTK_CONTAINER (item), label); - gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), GTK_WIDGET (item)); + gtk_menu_shell_prepend (GTK_MENU_SHELL (priv->accounts_popup), + GTK_WIDGET (item)); g_signal_connect_data (G_OBJECT (item), "activate", G_CALLBACK (on_send_receive_csm_activated), @@ -991,6 +1014,11 @@ connect_signals (ModestMainWindow *self) modest_signal_mgr_connect (priv->sighandlers,G_OBJECT (self), "window-state-event", G_CALLBACK (modest_main_window_window_state_event), NULL); + /* we don't register this in sighandlers, as it should be run after disconnecting all signals, + * in destroy stage */ + g_signal_connect (G_OBJECT (self), "destroy", G_CALLBACK (on_window_destroy), NULL); + + g_signal_connect (G_OBJECT (self), "notify::visible", G_CALLBACK (on_window_hide), NULL); /* Mail Operation Queue */ priv->sighandlers = @@ -1037,13 +1065,6 @@ connect_signals (ModestMainWindow *self) "account_changed", G_CALLBACK (on_account_changed), self); - - priv->sighandlers = - modest_signal_mgr_connect (priv->sighandlers, - G_OBJECT (modest_runtime_get_account_store()), - "password_requested", - G_CALLBACK (modest_ui_actions_on_password_requested), - self); } static void @@ -1084,12 +1105,20 @@ on_hildon_program_is_topmost_notify(GObject *self, } } +typedef struct +{ + GtkWidget *folder_win; + gulong handler_id; +} ShowHelper; + static void modest_main_window_on_show (GtkWidget *self, gpointer user_data) { - GtkWidget *folder_win = (GtkWidget *) user_data; + ShowHelper *helper = (ShowHelper *) user_data; + GtkWidget *folder_win = helper->folder_win; ModestMainWindowPrivate *priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); - + ModestAccountMgr *mgr; + priv->folder_view = MODEST_FOLDER_VIEW (modest_platform_create_folder_view (NULL)); wrap_in_scrolled_window (folder_win, GTK_WIDGET(priv->folder_view)); @@ -1111,26 +1140,16 @@ modest_main_window_on_show (GtkWidget *self, gpointer user_data) restore_settings (MODEST_MAIN_WINDOW(self), TRUE); priv->wait_for_settings = FALSE; - /* Check if accounts exist and show the account wizard if not */ - gboolean accounts_exist = - modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE); - - if (!accounts_exist) { - /* This is necessary to have the main window shown behind the dialog - It's an ugly hack... jschmid */ - gtk_widget_show_all(GTK_WIDGET(self)); - modest_ui_actions_on_accounts (NULL, MODEST_WINDOW(self)); - } else { - GSList *accounts; - GtkAction *send_receive_all; - ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self); - accounts = modest_account_mgr_account_names (modest_runtime_get_account_mgr (), TRUE); - send_receive_all = gtk_ui_manager_get_action (parent_priv->ui_manager, - "/MenuBar/ToolsMenu/ToolsSendReceiveMainMenu/ToolsSendReceiveAllMenu"); - gtk_action_set_visible (send_receive_all, g_slist_length (accounts) > 0); - modest_account_mgr_free_account_names (accounts); + /* Update the menus if there are accounts */ + mgr = modest_runtime_get_account_mgr(); + if (modest_account_mgr_has_accounts(mgr, TRUE)) update_menus (MODEST_MAIN_WINDOW (self)); - } + + /* Never call this function again (NOTE that it could happen + as we hide the main window instead of closing it while + there are operations ongoing) and free the helper */ + g_signal_handler_disconnect (self, helper->handler_id); + g_slice_free (ShowHelper, helper); } static void @@ -1161,6 +1180,7 @@ modest_main_window_new (void) ModestConf *conf = NULL; GtkAction *action = NULL; GdkPixbuf *window_icon; + ShowHelper *helper; self = MODEST_MAIN_WINDOW(g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL)); priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); @@ -1253,6 +1273,7 @@ modest_main_window_new (void) /* header view */ priv->header_view = MODEST_HEADER_VIEW (modest_header_view_new (NULL, MODEST_HEADER_VIEW_STYLE_DETAILS)); + g_object_ref (priv->header_view); if (!priv->header_view) g_printerr ("modest: cannot instantiate header view\n"); modest_header_view_set_style (priv->header_view, MODEST_HEADER_VIEW_STYLE_TWOLINES); @@ -1268,6 +1289,7 @@ modest_main_window_new (void) /* Empty view */ priv->empty_view = create_empty_view (); gtk_widget_show (priv->empty_view); + g_object_ref (priv->empty_view); /* Create scrolled windows */ folder_win = gtk_scrolled_window_new (NULL, NULL); @@ -1299,9 +1321,14 @@ modest_main_window_new (void) g_signal_connect (G_OBJECT(app), "notify::is-topmost", G_CALLBACK (on_hildon_program_is_topmost_notify), self); - g_signal_connect (G_OBJECT(self), "show", - G_CALLBACK (modest_main_window_on_show), folder_win); - + /* Connect to "show" action. We delay the creation of some + elements until that moment */ + helper = g_slice_new0 (ShowHelper); + helper->folder_win = folder_win; + helper->handler_id = g_signal_connect (G_OBJECT(self), "show", + G_CALLBACK (modest_main_window_on_show), + helper); + /* Set window icon */ window_icon = modest_platform_get_icon (MODEST_APP_ICON, MODEST_ICON_SIZE_BIG); if (window_icon) { @@ -1332,7 +1359,9 @@ modest_main_window_set_style (ModestMainWindow *self, ModestWindowPrivate *parent_priv; GtkAction *action; gboolean active; - + GtkTreeSelection *sel; + GList *rows, *list; + g_return_if_fail (MODEST_IS_MAIN_WINDOW (self)); priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self); @@ -1354,6 +1383,11 @@ modest_main_window_set_style (ModestMainWindow *self, g_signal_handlers_unblock_by_func (action, modest_ui_actions_toggle_folders_view, self); } + /* We need to store the selection because it's lost when the + widget is reparented */ + sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view)); + rows = gtk_tree_selection_get_selected_rows (sel, NULL); + priv->style = style; switch (style) { case MODEST_MAIN_WINDOW_STYLE_SIMPLE: @@ -1382,14 +1416,40 @@ modest_main_window_set_style (ModestMainWindow *self, break; default: + g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL); + g_list_free (rows); g_return_if_reached (); } + /* Reselect the previously selected folders. We disable the + dimming rules execution during that time because there is + no need to work out it again and it could take a lot of + time if all the headers are selected */ + list = rows; + modest_window_disable_dimming (MODEST_WINDOW (self)); + while (list) { + gtk_tree_selection_select_path (sel, (GtkTreePath *) list->data); + list = g_list_next (list); + } + modest_window_enable_dimming (MODEST_WINDOW (self)); + + /* Free */ + g_list_foreach (rows, (GFunc) gtk_tree_path_free, NULL); + g_list_free (rows); + /* Let header view grab the focus if it's being shown */ - if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) + if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) { gtk_widget_grab_focus (GTK_WIDGET (priv->header_view)); - else - gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget)); + } else { + if (priv->style == MODEST_MAIN_WINDOW_STYLE_SPLIT) + gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view)); + else + gtk_widget_grab_focus (GTK_WIDGET (priv->contents_widget)); + } + + /* Check dimming rules */ + modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self)); + modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self)); /* Show changes */ gtk_widget_show_all (GTK_WIDGET (priv->main_vbox)); @@ -1583,8 +1643,10 @@ on_account_inserted (TnyAccountStore *accoust_store, /* Transport accounts and local ones (MMC and the Local folders account do now cause menu changes */ if (TNY_IS_STORE_ACCOUNT (account) && - modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) + modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) { + /* Update menus */ update_menus (MODEST_MAIN_WINDOW (user_data)); + } } static void @@ -1612,18 +1674,18 @@ on_account_changed (TnyAccountStore *account_store, gpointer user_data) { ModestMainWindow *win = MODEST_MAIN_WINDOW (user_data); - - /* We need to refresh the details widget because it could have changed */ - if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS) { - modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS); - } - /* Update the menus as well, the account name could be - changed. Transport accounts and local ones (MMC and the - Local folders account do now cause menu changes */ - if (TNY_IS_STORE_ACCOUNT (account) && - modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) - update_menus (MODEST_MAIN_WINDOW (user_data)); + /* Transport accounts and local ones (MMC and the Local + folders account do now cause menu changes */ + if (TNY_IS_STORE_ACCOUNT (account)) { + /* We need to refresh the details widget because it could have changed */ + if (modest_main_window_get_contents_style(win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS) + modest_main_window_set_contents_style (win, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS); + + /* Update the menus as well, name could change */ + if (modest_tny_folder_store_is_remote (TNY_FOLDER_STORE (account))) + update_menus (MODEST_MAIN_WINDOW (user_data)); + } } /* @@ -1645,6 +1707,9 @@ on_inner_widgets_key_pressed (GtkWidget *widget, { ModestMainWindowPrivate *priv; + if (event->type == GDK_KEY_RELEASE) + return FALSE; + priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data); /* Do nothing if we're in SIMPLE style */ @@ -1652,17 +1717,69 @@ on_inner_widgets_key_pressed (GtkWidget *widget, return FALSE; if (MODEST_IS_HEADER_VIEW (widget)) { - if (event->keyval == GDK_Left) + if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) gtk_widget_grab_focus (GTK_WIDGET (priv->folder_view)); else if ((event->keyval == GDK_Return)||(event->keyval == GDK_KP_Enter)) { guint selected_headers = modest_header_view_count_selected_headers (MODEST_HEADER_VIEW (widget)); if (selected_headers > 1) { hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message")); return TRUE; + } else { + GtkTreePath * cursor_path; + gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &cursor_path, NULL); + if (cursor_path == NULL) { + GtkTreeSelection *selection; + GList *list; + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); + list = gtk_tree_selection_get_selected_rows (selection, NULL); + + if (list != NULL) + gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget), (GtkTreePath *) list->data, NULL, FALSE); + g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL); + g_list_free (list); + } + } + } + } else if (MODEST_IS_FOLDER_VIEW (widget) && + (event->keyval == GDK_Right || event->keyval == GDK_KP_Right || event->keyval == GDK_Left || event->keyval == GDK_KP_Left)) { +#if GTK_CHECK_VERSION(2, 8, 0) /* TODO: gtk_tree_view_get_visible_range() is only available in GTK+ 2.8 */ + GtkTreePath *selected_path = NULL; + GtkTreePath *start_path = NULL; + GtkTreePath *end_path = NULL; + GList *selected; + GtkTreeSelection *selection; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->header_view)); + selected = gtk_tree_selection_get_selected_rows (selection, NULL); + if (selected != NULL) { + selected_path = (GtkTreePath *) selected->data; + if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->header_view), + &start_path, + &end_path)) { + + if ((gtk_tree_path_compare (start_path, selected_path) != -1) || + (gtk_tree_path_compare (end_path, selected_path) != 1)) { + + /* Scroll to first path */ + gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->header_view), + selected_path, + NULL, + TRUE, + 0.5, + 0.0); + } } + if (start_path) + gtk_tree_path_free (start_path); + if (end_path) + gtk_tree_path_free (end_path); + g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); + g_list_free (selected); } - } else if (MODEST_IS_FOLDER_VIEW (widget) && event->keyval == GDK_Right) +#endif /* GTK_CHECK_VERSION */ + /* fix scroll */ gtk_widget_grab_focus (GTK_WIDGET (priv->header_view)); + } return FALSE; } @@ -1733,6 +1850,75 @@ create_device_name_visual_string (const gchar *device_name, return label; } +typedef struct +{ + GtkWidget *count_label; + GtkWidget *msg_count_label; + GtkWidget *size_label; + gchar *color_markup; +} DetailsWidgets; + +static gchar * +create_uint_label (const gchar *markup, + const gchar *name, + guint count) +{ + return g_markup_printf_escaped ("%s: %d", markup, name, count); +} + +static gchar * +create_gchar_label (const gchar *markup, + const gchar *name, + gchar *count) +{ + return g_markup_printf_escaped ("%s: %s", markup, name, count); +} + +static void +update_folder_stats_status_cb (ModestFolderStats stats, + gpointer user_data) +{ + DetailsWidgets *widgets = (DetailsWidgets *) user_data; + gchar *label, *tmp; + + label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_folders"), stats.folders); + gtk_label_set_markup (GTK_LABEL (widgets->count_label), label); + g_free (label); + + label = create_uint_label (widgets->color_markup, _("mcen_fi_rootfolder_messages"), stats.msg_count); + gtk_label_set_markup (GTK_LABEL (widgets->msg_count_label), label); + g_free (label); + + if (widgets->size_label) { + tmp = modest_text_utils_get_display_size (stats.local_size); + label = create_gchar_label (widgets->color_markup, _("mcen_fi_rootfolder_size"), tmp); + gtk_label_set_markup (GTK_LABEL (widgets->size_label), label); + g_free (label); + g_free (tmp); + } +} + +static void +update_folder_stats_cb (ModestFolderStats stats, + gpointer user_data) +{ + DetailsWidgets *widgets = (DetailsWidgets *) user_data; + + /* refresh data */ + update_folder_stats_status_cb (stats, user_data); + + /* frees. Note that the widgets could have been destroyed but + we still keep a reference */ + g_free (widgets->color_markup); + if (widgets->count_label) + g_object_unref (widgets->count_label); + if (widgets->msg_count_label) + g_object_unref (widgets->msg_count_label); + if (widgets->size_label) + g_object_unref (widgets->size_label); + g_slice_free (DetailsWidgets, widgets); +} + static GtkWidget * create_details_widget (GtkWidget *styled_widget, TnyAccount *account) { @@ -1742,10 +1928,13 @@ create_details_widget (GtkWidget *styled_widget, TnyAccount *account) GtkWidget *label_w; gchar *label; gchar *gray_color_markup; + DetailsWidgets *widgets; vbox = gtk_vbox_new (FALSE, 0); + widgets = g_slice_new0 (DetailsWidgets); gray_color_markup = get_gray_color_markup (styled_widget); + widgets->color_markup = g_strdup (gray_color_markup); /* Account description: */ if (modest_tny_account_is_virtual_local_folders (account) @@ -1800,43 +1989,39 @@ create_details_widget (GtkWidget *styled_widget, TnyAccount *account) /* Message count */ TnyFolderStore *folder_store = TNY_FOLDER_STORE (account); - label = g_markup_printf_escaped ("%s: %d", - gray_color_markup, _("mcen_fi_rootfolder_messages"), - modest_tny_folder_store_get_message_count (folder_store)); + label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_messages"), 0); label_w = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label_w), label); gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END); gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0); g_free (label); + widgets->msg_count_label = g_object_ref (label_w); + /* Folder count */ - label = g_markup_printf_escaped ("%s: %d", - gray_color_markup, - _("mcen_fi_rootfolder_folders"), - modest_tny_folder_store_get_folder_count (folder_store)); + label = create_uint_label (gray_color_markup, _("mcen_fi_rootfolder_folders"), 0); label_w = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label_w), label); gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END); gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0); g_free (label); + widgets->count_label = g_object_ref (label_w); + /* Size / Date */ if (modest_tny_account_is_virtual_local_folders (account) || modest_tny_account_is_memory_card_account (account)) { - gchar *size = modest_text_utils_get_display_size ( - modest_tny_folder_store_get_local_size (folder_store)); - - label = g_markup_printf_escaped ("%s: %s", - gray_color_markup, _("mcen_fi_rootfolder_size"), - size); - g_free (size); + label = create_gchar_label (gray_color_markup, _("mcen_fi_rootfolder_size"), "0"); label_w = gtk_label_new (NULL); gtk_label_set_markup (GTK_LABEL (label_w), label); gtk_label_set_ellipsize (GTK_LABEL (label_w), PANGO_ELLIPSIZE_END); gtk_box_pack_start (GTK_BOX (vbox), label_w, FALSE, FALSE, 0); g_free (label); + + widgets->size_label = g_object_ref (label_w); + } else if (TNY_IS_ACCOUNT(folder_store)) { TnyAccount *account = TNY_ACCOUNT(folder_store); @@ -1846,6 +2031,16 @@ create_details_widget (GtkWidget *styled_widget, TnyAccount *account) last_updated = modest_account_mgr_get_last_updated (modest_runtime_get_account_mgr (), tny_account_get_id (account)); +#ifdef MODEST_USE_LIBTIME + /* If we use libtime, we are storing the time in UTC so we have to convert to currently + * selected time */ + time_t now; + struct tm *localtime_tm; + time (&now); + localtime_tm = localtime (&now); + last_updated -= time_get_utc_offset (localtime_tm->tm_zone); +#endif + if (last_updated > 0) last_updated_string = modest_text_utils_get_display_date(last_updated); else @@ -1862,6 +2057,12 @@ create_details_widget (GtkWidget *styled_widget, TnyAccount *account) g_free (gray_color_markup); + /* Refresh folder stats asynchronously */ + modest_tny_folder_store_get_folder_stats (TNY_FOLDER_STORE (account), + update_folder_stats_cb, + update_folder_stats_status_cb, + widgets); + /* Set alignment */ gtk_container_foreach (GTK_CONTAINER (vbox), (GtkCallback) set_alignment, NULL); @@ -1997,10 +2198,7 @@ modest_main_window_set_contents_style (ModestMainWindow *self, details widget */ GtkWidget *content = gtk_bin_get_child (GTK_BIN (priv->contents_widget)); if (content) { - if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS) - g_object_ref (content); - else if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) { - g_object_ref (priv->empty_view); + if (priv->contents_style == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) { gtk_container_remove (GTK_CONTAINER (content), priv->empty_view); } @@ -2014,6 +2212,8 @@ modest_main_window_set_contents_style (ModestMainWindow *self, wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->header_view)); modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget), TRUE); + if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) + gtk_widget_grab_focus (GTK_WIDGET (priv->header_view)); break; case MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS: { @@ -2029,16 +2229,21 @@ modest_main_window_set_contents_style (ModestMainWindow *self, wrap_in_scrolled_window (priv->contents_widget, priv->details_widget); } - g_object_unref (selected_folderstore); + if (selected_folderstore) + g_object_unref (selected_folderstore); modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget), FALSE); } + if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) + gtk_widget_grab_focus (GTK_WIDGET (priv->details_widget)); break; } case MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY: wrap_in_scrolled_window (priv->contents_widget, GTK_WIDGET (priv->empty_view)); modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->contents_widget), FALSE); + if (priv->style == MODEST_MAIN_WINDOW_STYLE_SIMPLE) + gtk_widget_grab_focus (GTK_WIDGET (priv->empty_view)); break; default: g_return_if_reached (); @@ -2046,6 +2251,10 @@ modest_main_window_set_contents_style (ModestMainWindow *self, /* Show */ gtk_widget_show_all (priv->contents_widget); + + /* Recompute dimming rules */ + modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self)); + modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self)); } ModestMainWindowContentsStyle @@ -2153,6 +2362,7 @@ set_toolbar_mode (ModestMainWindow *self, /* Checks the dimming rules */ modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self)); + modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self)); /* Show and hide toolbar items */ switch (mode) { @@ -2268,7 +2478,6 @@ get_toolbar_mode_from_mail_operation (ModestMainWindow *self, switch (modest_mail_operation_get_type_operation (mail_op)) { case MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE: case MODEST_MAIL_OPERATION_TYPE_RECEIVE: - case MODEST_MAIL_OPERATION_TYPE_OPEN: mode = TOOLBAR_MODE_TRANSFER; if (priv->current_toolbar_mode == TOOLBAR_MODE_NORMAL) *mode_changed = TRUE; @@ -2289,7 +2498,7 @@ on_mail_operation_started (ModestMailOperation *mail_op, ModestToolBarModes mode; GSList *tmp; gboolean mode_changed = FALSE; - TnyAccount *account; + TnyAccount *account = NULL; self = MODEST_MAIN_WINDOW (user_data); priv = MODEST_MAIN_WINDOW_GET_PRIVATE (self); @@ -2298,7 +2507,7 @@ on_mail_operation_started (ModestMailOperation *mail_op, account is the local account or the MMC one */ op_type = modest_mail_operation_get_type_operation (mail_op); account = modest_mail_operation_get_account (mail_op); - if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) { + if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) { gboolean is_remote; is_remote = !(modest_tny_account_is_virtual_local_folders (account) || @@ -2309,15 +2518,18 @@ on_mail_operation_started (ModestMailOperation *mail_op, } /* Show information banner. Remove old timeout */ - if (priv->retrieving_banner_timeout > 0) { - g_source_remove (priv->retrieving_banner_timeout); - priv->retrieving_banner_timeout = 0; + if (priv->opening_banner_timeout > 0) { + g_source_remove (priv->opening_banner_timeout); + priv->opening_banner_timeout = 0; } /* Create a new timeout */ - priv->retrieving_banner_timeout = - g_timeout_add (2000, show_retrieving_banner, self); + priv->opening_banner_timeout = + g_timeout_add (2000, show_opening_banner, self); } - g_object_unref (account); + + /* Not every mail operation has account, noop does not */ + if (account) + g_object_unref (account); /* Get toolbar mode from operation id*/ mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed); @@ -2354,7 +2566,7 @@ on_mail_operation_finished (ModestMailOperation *mail_op, GSList *tmp = NULL; ModestMainWindow *self; gboolean mode_changed; - TnyAccount *account; + TnyAccount *account = NULL; ModestMainWindowPrivate *priv; self = MODEST_MAIN_WINDOW (user_data); @@ -2364,7 +2576,7 @@ on_mail_operation_finished (ModestMailOperation *mail_op, the account was the local account or the MMC one */ op_type = modest_mail_operation_get_type_operation (mail_op); account = modest_mail_operation_get_account (mail_op); - if (account && op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) { + if (account && op_type == MODEST_MAIL_OPERATION_TYPE_OPEN) { gboolean is_remote; is_remote = !(modest_tny_account_is_virtual_local_folders (account) || @@ -2375,18 +2587,21 @@ on_mail_operation_finished (ModestMailOperation *mail_op, } /* Remove old timeout */ - if (priv->retrieving_banner_timeout > 0) { - g_source_remove (priv->retrieving_banner_timeout); - priv->retrieving_banner_timeout = 0; + if (priv->opening_banner_timeout > 0) { + g_source_remove (priv->opening_banner_timeout); + priv->opening_banner_timeout = 0; } /* Remove the banner if exists */ - if (priv->retrieving_banner) { - gtk_widget_destroy (priv->retrieving_banner); - priv->retrieving_banner = NULL; + if (priv->opening_banner) { + gtk_widget_destroy (priv->opening_banner); + priv->opening_banner = NULL; } } - g_object_unref (account); + + /* Not every mail operation has account, noop does not */ + if (account) + g_object_unref (account); /* Get toolbar mode from operation id*/ mode = get_toolbar_mode_from_mail_operation (self, mail_op, &mode_changed); @@ -2462,7 +2677,9 @@ set_account_visible(ModestMainWindow *self, const gchar *acc_name) modest_folder_view_set_account_id_of_visible_server_account (priv->folder_view, modest_server_account_settings_get_account_name (store_settings)); + modest_folder_view_select_first_inbox_or_local (priv->folder_view); modest_window_set_active_account (MODEST_WINDOW (self), account_name); + action = gtk_action_group_get_action (priv->view_additions_group, account_name); if (action != NULL) { if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) { @@ -2473,9 +2690,6 @@ set_account_visible(ModestMainWindow *self, const gchar *acc_name) } } - modest_folder_view_select_first_inbox_or_local (priv->folder_view); - - /* Free */ if (settings) { g_object_unref (store_settings); @@ -2539,9 +2753,9 @@ refresh_account (const gchar *account_name) /* If account_name == NULL, we must update all (option All) */ if (!account_name) - modest_ui_actions_do_send_receive_all (win, TRUE); + modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE); else - modest_ui_actions_do_send_receive (account_name, TRUE, win); + modest_ui_actions_do_send_receive (account_name, TRUE, TRUE, TRUE, win); } @@ -2564,7 +2778,8 @@ on_zoom_minus_plus_not_implemented (ModestWindow *window) { g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (window), FALSE); - hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here")); + hildon_banner_show_information (NULL, NULL, + _CS("ckct_ib_cannot_zoom_here")); return FALSE; } @@ -2579,6 +2794,7 @@ on_folder_view_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer userd /* Update toolbar dimming state */ modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window)); + modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window)); return FALSE; } @@ -2596,6 +2812,7 @@ on_header_view_focus_in (GtkWidget *widget, /* Update toolbar dimming state */ modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window)); + modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window)); return FALSE; } @@ -2694,6 +2911,17 @@ modest_main_window_on_msg_view_window_msg_changed (ModestMsgViewWindow *view_win return TRUE; } +static void +updating_banner_destroyed (gpointer data, + GObject *where_the_object_was) +{ + ModestMainWindowPrivate *priv = NULL; + + priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data); + + priv->updating_banner = NULL; +} + static gboolean show_updating_banner (gpointer user_data) { @@ -2708,6 +2936,13 @@ show_updating_banner (gpointer user_data) priv->updating_banner = modest_platform_animation_banner (GTK_WIDGET (user_data), NULL, _CS ("ckdg_pb_updating")); + + /* We need this because banners in Maemo could be + destroyed by dialogs so we need to properly update + our reference to it */ + g_object_weak_ref (G_OBJECT (priv->updating_banner), + updating_banner_destroyed, + user_data); gdk_threads_leave (); } @@ -2764,24 +2999,118 @@ modest_main_window_screen_is_on (ModestMainWindow *self) return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE; } +static void +remove_banners (ModestMainWindow *window) +{ + ModestMainWindowPrivate *priv; + + priv = MODEST_MAIN_WINDOW_GET_PRIVATE (window); + + if (priv->opening_banner_timeout > 0) { + g_source_remove (priv->opening_banner_timeout); + priv->opening_banner_timeout = 0; + } + + if (priv->opening_banner != NULL) { + gtk_widget_destroy (priv->opening_banner); + priv->opening_banner = NULL; + } + + if (priv->updating_banner_timeout > 0) { + g_source_remove (priv->updating_banner_timeout); + priv->updating_banner_timeout = 0; + } + + if (priv->updating_banner != NULL) { + gtk_widget_destroy (priv->updating_banner); + priv->updating_banner = NULL; + } +} + + +static void +on_window_hide (GObject *gobject, + GParamSpec *arg1, + gpointer user_data) +{ + g_return_if_fail (MODEST_IS_MAIN_WINDOW (gobject)); + + if (!GTK_WIDGET_VISIBLE (gobject)) { + TnyFolderStore *folder_store; + ModestMainWindowPrivate *priv; + + /* Remove the currently shown banners */ + remove_banners (MODEST_MAIN_WINDOW (gobject)); + + /* Force the folder view to sync the currently selected folder + to save the read/unread status and to expunge messages */ + priv = MODEST_MAIN_WINDOW_GET_PRIVATE (gobject); + folder_store = modest_folder_view_get_selected (priv->folder_view); + if (TNY_IS_FOLDER (folder_store)) { + ModestMailOperation *mail_op; + + mail_op = modest_mail_operation_new (NULL); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); + modest_mail_operation_sync_folder (mail_op, TNY_FOLDER (folder_store), FALSE); + g_object_unref (mail_op); + g_object_unref (folder_store); + } + } +} + +static void +on_window_destroy (GtkObject *widget, + gpointer user_data) +{ + g_return_if_fail (MODEST_IS_MAIN_WINDOW (widget)); + + remove_banners (MODEST_MAIN_WINDOW (widget)); +} + +static void +opening_banner_destroyed (gpointer data, + GObject *where_the_object_was) +{ + ModestMainWindowPrivate *priv = NULL; + + priv = MODEST_MAIN_WINDOW_GET_PRIVATE (data); + + priv->opening_banner = NULL; +} + static gboolean -show_retrieving_banner (gpointer user_data) +show_opening_banner (gpointer user_data) { ModestMainWindowPrivate *priv = NULL; priv = MODEST_MAIN_WINDOW_GET_PRIVATE (user_data); - if (priv->retrieving_banner == NULL) { + if (priv->opening_banner == NULL) { /* We're outside the main lock */ gdk_threads_enter (); - priv->retrieving_banner = + priv->opening_banner = modest_platform_animation_banner (GTK_WIDGET (user_data), NULL, - _("mcen_ib_getting_items")); + _("mail_me_opening")); + + /* We need this because banners in Maemo could be + destroyed by dialogs so we need to properly update + our reference to it */ + g_object_weak_ref (G_OBJECT (priv->opening_banner), + opening_banner_destroyed, + user_data); + + /* We need this because banners in Maemo could be + destroyed by dialogs so we need to properly update + our reference to it */ + g_object_weak_ref (G_OBJECT (priv->updating_banner), + updating_banner_destroyed, + user_data); gdk_threads_leave (); } /* Remove timeout */ - priv->retrieving_banner_timeout = 0; + priv->opening_banner_timeout = 0; return FALSE; }