diff options
author | Milan Crha <mcrha@redhat.com> | 2013-08-20 17:25:06 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2013-08-20 17:25:06 +0800 |
commit | b7e728dd46329cd4a932af75c99b65aa2f211bd0 (patch) | |
tree | 6e4e661f37d035f1791ce3a3ee066cbdffcd9f3b | |
parent | bb6ab693783cc17f36d1e8da7f07d488611bffad (diff) | |
download | gsoc2013-evolution-b7e728dd46329cd4a932af75c99b65aa2f211bd0.tar.gz gsoc2013-evolution-b7e728dd46329cd4a932af75c99b65aa2f211bd0.tar.zst gsoc2013-evolution-b7e728dd46329cd4a932af75c99b65aa2f211bd0.zip |
Bug #682277 - Multiselect of messages causes slow UI update
-rw-r--r-- | mail/message-list.c | 40 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-view-private.c | 20 | ||||
-rw-r--r-- | shell/e-shell-view.c | 50 | ||||
-rw-r--r-- | shell/e-shell-view.h | 2 |
4 files changed, 76 insertions, 36 deletions
diff --git a/mail/message-list.c b/mail/message-list.c index d7682042bb..b0082f9995 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -4672,17 +4672,20 @@ static void on_selection_changed_cmd (ETree *tree, MessageList *message_list) { - GPtrArray *uids; + GPtrArray *uids = NULL; const gchar *newuid; + guint selected_count; GNode *cursor; - /* not sure if we could just ignore this for the cursor, i think sometimes you - * only get a selection changed when you should also get a cursor activated? */ - uids = message_list_get_selected (message_list); + selected_count = message_list_selected_count (message_list); + if (selected_count == 1) { + uids = message_list_get_selected (message_list); - if (uids->len == 1) - newuid = g_ptr_array_index (uids, 0); - else if ((cursor = e_tree_get_cursor (tree))) + if (uids->len == 1) + newuid = g_ptr_array_index (uids, 0); + else + newuid = NULL; + } else if ((cursor = e_tree_get_cursor (tree))) newuid = (gchar *) camel_message_info_uid (cursor->data); else newuid = NULL; @@ -4690,8 +4693,8 @@ on_selection_changed_cmd (ETree *tree, /* If the selection isn't empty, then we ignore the no-uid check, since this event * is also used for other updating. If it is empty, it might just be a setup event * from etree which we do need to ignore */ - if ((newuid == NULL && message_list->cursor_uid == NULL && uids->len == 0) || - (message_list->last_sel_single && uids->len == 1 && newuid != NULL && message_list->cursor_uid != NULL && !strcmp (message_list->cursor_uid, newuid))) { + if ((newuid == NULL && message_list->cursor_uid == NULL && selected_count == 0) || + (message_list->last_sel_single && selected_count == 1 && newuid != NULL && message_list->cursor_uid != NULL && !strcmp (message_list->cursor_uid, newuid))) { /* noop */ } else { g_free (message_list->cursor_uid); @@ -4703,9 +4706,10 @@ on_selection_changed_cmd (ETree *tree, message_list, NULL); } - message_list->last_sel_single = uids->len == 1; + message_list->last_sel_single = selected_count == 1; - g_ptr_array_unref (uids); + if (uids) + g_ptr_array_unref (uids); } static gint @@ -4963,27 +4967,15 @@ message_list_count (MessageList *message_list) return data.count; } -static void -ml_getselcount_cb (gint model_row, - gpointer user_data) -{ - struct ml_count_data *data = user_data; - - data->count++; -} - guint message_list_selected_count (MessageList *message_list) { ESelectionModel *selection; - struct ml_count_data data = { message_list, 0 }; g_return_val_if_fail (IS_MESSAGE_LIST (message_list), 0); selection = e_tree_get_selection_model (E_TREE (message_list)); - e_selection_model_foreach (selection, ml_getselcount_cb, &data); - - return data.count; + return e_selection_model_selected_count (selection); } void diff --git a/modules/mail/e-mail-shell-view-private.c b/modules/mail/e-mail-shell-view-private.c index f33c6fe07e..be250ff6b2 100644 --- a/modules/mail/e-mail-shell-view-private.c +++ b/modules/mail/e-mail-shell-view-private.c @@ -80,7 +80,7 @@ mail_shell_view_got_folder_cb (CamelStore *store, } e_mail_reader_set_folder (context->reader, folder); - e_shell_view_update_actions (context->shell_view); + e_shell_view_update_actions_in_idle (context->shell_view); g_object_unref (folder); @@ -119,7 +119,7 @@ mail_shell_view_folder_tree_selected_cb (EMailShellView *mail_shell_view, /* If we are to clear the message list, do so immediately. */ if ((flags & CAMEL_FOLDER_NOSELECT) || folder_name == NULL) { e_mail_reader_set_folder (reader, NULL); - e_shell_view_update_actions (shell_view); + e_shell_view_update_actions_in_idle (shell_view); return; } @@ -444,7 +444,7 @@ mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view, display = e_mail_reader_get_mail_display (reader); message_list = e_mail_reader_get_message_list (reader); - e_shell_view_update_actions (E_SHELL_VIEW (mail_shell_view)); + e_shell_view_update_actions_in_idle (E_SHELL_VIEW (mail_shell_view)); e_mail_shell_view_update_sidebar (mail_shell_view); /* Connect if its not connected already */ @@ -934,7 +934,8 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) ESourceRegistry *registry; CamelStore *parent_store; CamelFolder *folder; - GPtrArray *uids; + MessageList *message_list; + guint selected_count; GString *buffer; gboolean store_is_local; const gchar *display_name; @@ -989,12 +990,13 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) num_visible = camel_folder_summary_get_visible_count (folder->summary); buffer = g_string_sized_new (256); - uids = e_mail_reader_get_selected_uids (reader); + message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader)); + selected_count = message_list_selected_count (message_list); - if (uids->len > 1) + if (selected_count > 1) g_string_append_printf ( buffer, ngettext ("%d selected, ", "%d selected, ", - uids->len), uids->len); + selected_count), selected_count); /* "Trash" folder (virtual or real) */ if (folder->folder_flags & CAMEL_FOLDER_IS_TRASH) { @@ -1063,7 +1065,7 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) num_deleted - num_junked + num_junked_not_deleted; - if (num_unread > 0 && uids->len <= 1) + if (num_unread > 0 && selected_count <= 1) g_string_append_printf ( buffer, ngettext ("%d unread, ", "%d unread, ", num_unread), num_unread); @@ -1072,8 +1074,6 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) num_visible), num_visible); } - g_ptr_array_unref (uids); - uid = camel_service_get_uid (CAMEL_SERVICE (parent_store)); store_is_local = (g_strcmp0 (uid, E_MAIL_SESSION_LOCAL_UID) == 0); diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index a7aa4e8541..e5ba407d7b 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -74,6 +74,8 @@ struct _EShellViewPrivate { GtkWidget *preferences_window; gulong preferences_hide_handler_id; + + guint update_actions_idle_id; }; enum { @@ -515,6 +517,11 @@ shell_view_dispose (GObject *object) shell_view_save_state (E_SHELL_VIEW (object), TRUE); } + if (priv->update_actions_idle_id > 0) { + g_source_remove (priv->update_actions_idle_id); + priv->update_actions_idle_id = 0; + } + if (priv->state_save_activity != NULL) { g_object_remove_weak_pointer ( G_OBJECT (priv->state_save_activity), @@ -625,7 +632,7 @@ shell_view_constructed (GObject *object) shell_view->priv->preferences_window = g_object_ref (widget); handler_id = g_signal_connect_swapped ( shell_view->priv->preferences_window, "hide", - G_CALLBACK (e_shell_view_update_actions), shell_view); + G_CALLBACK (e_shell_view_update_actions_in_idle), shell_view); shell_view->priv->preferences_hide_handler_id = handler_id; e_extensible_load_extensions (E_EXTENSIBLE (object)); @@ -1822,8 +1829,47 @@ e_shell_view_update_actions (EShellView *shell_view) { g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); - if (e_shell_view_is_active (shell_view)) + if (e_shell_view_is_active (shell_view)) { + if (shell_view->priv->update_actions_idle_id > 0) { + g_source_remove (shell_view->priv->update_actions_idle_id); + shell_view->priv->update_actions_idle_id = 0; + } + g_signal_emit (shell_view, signals[UPDATE_ACTIONS], 0); + } +} + +static gboolean +shell_view_call_update_actions_idle (gpointer user_data) +{ + EShellView *shell_view = user_data; + + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); + + shell_view->priv->update_actions_idle_id = 0; + e_shell_view_update_actions (shell_view); + + return FALSE; +} + +/** + * e_shell_view_update_actions_in_idle: + * @shell_view: an #EShellView + * + * Schedules e_shell_view_update_actions() call on idle. + * + * Since: 3.10 + **/ +void +e_shell_view_update_actions_in_idle (EShellView *shell_view) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + if (!e_shell_view_is_active (shell_view)) + return; + + if (shell_view->priv->update_actions_idle_id == 0) + shell_view->priv->update_actions_idle_id = g_idle_add (shell_view_call_update_actions_idle, shell_view); } /** diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h index db51c31ca8..7ccbacc659 100644 --- a/shell/e-shell-view.h +++ b/shell/e-shell-view.h @@ -234,6 +234,8 @@ void e_shell_view_unblock_execute_search gboolean e_shell_view_is_execute_search_blocked (EShellView *shell_view); void e_shell_view_update_actions (EShellView *shell_view); +void e_shell_view_update_actions_in_idle + (EShellView *shell_view); GtkWidget * e_shell_view_show_popup_menu (EShellView *shell_view, const gchar *widget_path, GdkEvent *button_event); |