From 20c2f0ef3ef1920d9879c404a465b658821f35f1 Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Mon, 4 Sep 2006 16:56:18 +0000 Subject: [PATCH 1/1] 2006-09-04 [colin] 2.4.0cvs143 * src/messageview.c * src/summaryview.c * src/textview.c * src/textview.h Make loading of huge mails (lots of text and/or images) cancellable, so the GUI doesn't block --- ChangeLog | 9 ++++++ PATCHSETS | 1 + configure.ac | 2 +- src/messageview.c | 15 ++++++++-- src/summaryview.c | 35 ++++++++++++++++++++++ src/textview.c | 76 +++++++++++++++++++++++++++++++++++++++++++++-- src/textview.h | 2 ++ 7 files changed, 134 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index b64f73fd9..0b15ede3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2006-09-04 [colin] 2.4.0cvs143 + + * src/messageview.c + * src/summaryview.c + * src/textview.c + * src/textview.h + Make loading of huge mails (lots of text and/or + images) cancellable, so the GUI doesn't block + 2006-09-04 [colin] 2.4.0cvs142 * src/plugins/trayicon/trayicon.c diff --git a/PATCHSETS b/PATCHSETS index 50eb2461a..a2d4dbd0e 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -1834,3 +1834,4 @@ ( cvs diff -u -r 1.59.2.41 -r 1.59.2.42 src/prefs_filtering.c; ) > 2.4.0cvs140.patchset ( cvs diff -u -r 1.1.2.9 -r 1.1.2.10 src/gtk/icon_legend.c; ) > 2.4.0cvs141.patchset ( cvs diff -u -r 1.14.2.37 -r 1.14.2.38 src/plugins/trayicon/trayicon.c; ) > 2.4.0cvs142.patchset +( cvs diff -u -r 1.94.2.102 -r 1.94.2.103 src/messageview.c; cvs diff -u -r 1.395.2.242 -r 1.395.2.243 src/summaryview.c; cvs diff -u -r 1.96.2.144 -r 1.96.2.145 src/textview.c; cvs diff -u -r 1.12.2.12 -r 1.12.2.13 src/textview.h; ) > 2.4.0cvs143.patchset diff --git a/configure.ac b/configure.ac index a239389fc..2306a8a39 100644 --- a/configure.ac +++ b/configure.ac @@ -11,7 +11,7 @@ MINOR_VERSION=4 MICRO_VERSION=0 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=142 +EXTRA_VERSION=143 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/messageview.c b/src/messageview.c index 189163c9b..b1d065b05 100644 --- a/src/messageview.c +++ b/src/messageview.c @@ -830,6 +830,8 @@ gint messageview_show(MessageView *messageview, MsgInfo *msginfo, } headerview_show(messageview->headerview, messageview->msginfo); + messageview_set_position(messageview, 0); + textview_set_all_headers(messageview->mimeview->textview, messageview->all_headers); @@ -852,8 +854,6 @@ gint messageview_show(MessageView *messageview, MsgInfo *msginfo, g_free(subject); } - messageview_set_position(messageview, 0); - main_create_mailing_list_menu(messageview->mainwin, messageview->msginfo); if (messageview->msginfo->extradata @@ -917,8 +917,17 @@ void messageview_destroy(MessageView *messageview) } if (messageview->updating) { - debug_print("uh oh, better not touch that now\n"); + debug_print("uh oh, better not touch that now (fetching)\n"); + messageview->deferred_destroy = TRUE; + gtk_widget_hide(messageview->window); + return; + } + + if (messageview->mimeview->textview + && messageview->mimeview->textview->loading) { + debug_print("uh oh, better not touch that now (loading text)\n"); messageview->deferred_destroy = TRUE; + messageview->mimeview->textview->stop_loading = TRUE; gtk_widget_hide(messageview->window); return; } diff --git a/src/summaryview.c b/src/summaryview.c index 2b90ed70f..ccbb6aec0 100644 --- a/src/summaryview.c +++ b/src/summaryview.c @@ -849,6 +849,7 @@ static gboolean summaryview_quicksearch_recurse(gpointer data) main_window_cursor_normal(summaryview->mainwin); return FALSE; } + gboolean summary_show(SummaryView *summaryview, FolderItem *item) { GtkCTree *ctree = GTK_CTREE(summaryview->ctree); @@ -5307,12 +5308,46 @@ static void summary_unselected(GtkCTree *ctree, GtkCTreeNode *row, summary_status_show(summaryview); } +typedef struct _PostponedSelectData +{ + GtkCTree *ctree; + GtkCTreeNode *row; + gint column; + SummaryView *summaryview; +} PostponedSelectData; + +static gboolean summary_select_retry(void *data) +{ + PostponedSelectData *psdata = (PostponedSelectData *)data; + debug_print("trying again\n"); + summary_selected(psdata->ctree, psdata->row, + psdata->column, psdata->summaryview); + g_free(psdata); + return FALSE; +} + static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row, gint column, SummaryView *summaryview) { MsgInfo *msginfo; gboolean marked_unread = FALSE; + if (summary_is_locked(summaryview) + && !GTK_SCTREE(ctree)->selecting_range + && summaryview->messageview->mimeview + && summaryview->messageview->mimeview->type == MIMEVIEW_TEXT + && summaryview->messageview->mimeview->textview->loading) { + PostponedSelectData *data = g_new0(PostponedSelectData, 1); + summaryview->messageview->mimeview->textview->stop_loading = TRUE; + + data->ctree = ctree; + data->row = row; + data->column = column; + data->summaryview = summaryview; + debug_print("postponing open of message till end of load\n"); + g_timeout_add(100, summary_select_retry, data); + return; + } if (summary_is_locked(summaryview) || GTK_SCTREE(ctree)->selecting_range) { return; diff --git a/src/textview.c b/src/textview.c index 97b6aa431..3590ba7ba 100644 --- a/src/textview.c +++ b/src/textview.c @@ -537,11 +537,17 @@ void textview_reflect_prefs(TextView *textview) void textview_show_message(TextView *textview, MimeInfo *mimeinfo, const gchar *file) { + textview->loading = TRUE; + textview->stop_loading = FALSE; + textview_clear(textview); textview_add_parts(textview, mimeinfo); textview_set_position(textview, 0); + + textview->loading = FALSE; + textview->stop_loading = FALSE; } void textview_show_part(TextView *textview, MimeInfo *mimeinfo, FILE *fp) @@ -552,11 +558,19 @@ void textview_show_part(TextView *textview, MimeInfo *mimeinfo, FILE *fp) if ((mimeinfo->type == MIMETYPE_MULTIPART) || ((mimeinfo->type == MIMETYPE_MESSAGE) && !g_ascii_strcasecmp(mimeinfo->subtype, "rfc822"))) { + textview->loading = TRUE; + textview->stop_loading = FALSE; + textview_clear(textview); textview_add_parts(textview, mimeinfo); + + textview->loading = FALSE; + textview->stop_loading = FALSE; END_TIMING(); return; } + textview->loading = TRUE; + textview->stop_loading = FALSE; if (fseek(fp, mimeinfo->offset, SEEK_SET) < 0) perror("fseek"); @@ -567,6 +581,9 @@ void textview_show_part(TextView *textview, MimeInfo *mimeinfo, FILE *fp) textview_add_parts(textview, mimeinfo); else textview_write_body(textview, mimeinfo); + + textview->loading = FALSE; + textview->stop_loading = FALSE; END_TIMING(); } @@ -609,6 +626,9 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo) charcount = gtk_text_buffer_get_char_count(buffer); gtk_text_buffer_get_end_iter(buffer, &iter); + if (textview->stop_loading) { + return; + } if (mimeinfo->type == MIMETYPE_MULTIPART) { END_TIMING(); return; @@ -659,6 +679,7 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo) ClickableText *uri; gchar *uri_str; START_TIMING("inserting image"); + filename = procmime_get_tmp_file_name(mimeinfo); if (procmime_get_part(filename, mimeinfo) < 0) { @@ -716,6 +737,7 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo) g_object_unref(pixbuf); g_free(filename); END_TIMING(); + GTK_EVENTS_FLUSH(); } } else if (mimeinfo->type == MIMETYPE_TEXT) { if (prefs_common.display_header && (charcount > 0)) @@ -864,6 +886,7 @@ static void textview_write_body(TextView *textview, MimeInfo *mimeinfo) CodeConverter *conv; const gchar *charset, *p, *cmd; GSList *cur; + int lines = 0; if (textview->messageview->forced_charset) charset = textview->messageview->forced_charset; @@ -948,25 +971,47 @@ static void textview_write_body(TextView *textview, MimeInfo *mimeinfo) } close(pfd[1]); tmpfp = fdopen(pfd[0], "rb"); - while (fgets(buf, sizeof(buf), tmpfp)) + while (fgets(buf, sizeof(buf), tmpfp)) { textview_write_line(textview, buf, conv); + + lines++; + if (lines % 500 == 0) + GTK_EVENTS_FLUSH(); + if (textview->stop_loading) { + fclose(tmpfp); + waitpid(pid, pfd, 0); + unlink(fname); + return; + } + } + fclose(tmpfp); waitpid(pid, pfd, 0); unlink(fname); } else { textview_default: + lines = 0; tmpfp = g_fopen(mimeinfo->data.filename, "rb"); fseek(tmpfp, mimeinfo->offset, SEEK_SET); debug_print("Viewing text content of type: %s (length: %d)\n", mimeinfo->subtype, mimeinfo->length); while ((ftell(tmpfp) < mimeinfo->offset + mimeinfo->length) && - (fgets(buf, sizeof(buf), tmpfp) != NULL)) + (fgets(buf, sizeof(buf), tmpfp) != NULL)) { textview_write_line(textview, buf, conv); + lines++; + if (lines % 500 == 0) + GTK_EVENTS_FLUSH(); + if (textview->stop_loading) { + fclose(tmpfp); + return; + } + } fclose(tmpfp); } conv_code_converter_destroy(conv); procmime_force_encoding(0); + lines = 0; for (cur = textview->uri_list; cur; cur = cur->next) { ClickableText *uri = (ClickableText *)cur->data; if (!uri->is_quote) @@ -974,6 +1019,12 @@ textview_default: if (!prefs_common.hide_quotes || uri->quote_level+1 < prefs_common.hide_quotes) { textview_toggle_quote(textview, uri, TRUE); + lines++; + if (lines % 500 == 0) + GTK_EVENTS_FLUSH(); + if (textview->stop_loading) { + return; + } } } } @@ -983,6 +1034,7 @@ static void textview_show_html(TextView *textview, FILE *fp, { SC_HTMLParser *parser; gchar *str; + gint lines = 0; parser = sc_html_parser_new(fp, conv); g_return_if_fail(parser != NULL); @@ -1007,6 +1059,12 @@ static void textview_show_html(TextView *textview, FILE *fp, textview_write_link(textview, str, parser->href, NULL); } else textview_write_line(textview, str, NULL); + lines++; + if (lines % 500 == 0) + GTK_EVENTS_FLUSH(); + if (textview->stop_loading) { + return; + } } textview_write_line(textview, "\n", NULL); sc_html_parser_destroy(parser); @@ -1017,12 +1075,19 @@ static void textview_show_ertf(TextView *textview, FILE *fp, { ERTFParser *parser; gchar *str; + gint lines = 0; parser = ertf_parser_new(fp, conv); g_return_if_fail(parser != NULL); while ((str = ertf_parse(parser)) != NULL) { textview_write_line(textview, str, NULL); + lines++; + if (lines % 500 == 0) + GTK_EVENTS_FLUSH(); + if (textview->stop_loading) { + return; + } } ertf_parser_destroy(parser); @@ -1921,6 +1986,8 @@ static gboolean textview_motion_notify(GtkWidget *widget, GdkEventMotion *event, TextView *textview) { + if (textview->loading) + return FALSE; textview_uri_update(textview, event->x, event->y); gdk_window_get_pointer(widget->window, NULL, NULL, NULL); @@ -1931,6 +1998,8 @@ static gboolean textview_leave_notify(GtkWidget *widget, GdkEventCrossing *event, TextView *textview) { + if (textview->loading) + return FALSE; textview_uri_update(textview, -1, -1); return FALSE; @@ -1943,6 +2012,9 @@ static gboolean textview_visibility_notify(GtkWidget *widget, gint wx, wy; GdkWindow *window; + if (textview->loading) + return FALSE; + window = gtk_text_view_get_window(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_TEXT); diff --git a/src/textview.h b/src/textview.h index 000cc89c0..b23edc838 100644 --- a/src/textview.h +++ b/src/textview.h @@ -62,6 +62,8 @@ struct _TextView GtkTextIter uri_hover_start_iter; GtkTextIter uri_hover_end_iter; GtkWidget *image; + gboolean loading; + gboolean stop_loading; }; TextView *textview_create (void); -- 2.25.1