2006-09-04 [colin] 2.4.0cvs143
authorColin Leroy <colin@colino.net>
Mon, 4 Sep 2006 16:56:18 +0000 (16:56 +0000)
committerColin Leroy <colin@colino.net>
Mon, 4 Sep 2006 16:56:18 +0000 (16:56 +0000)
* 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
PATCHSETS
configure.ac
src/messageview.c
src/summaryview.c
src/textview.c
src/textview.h

index b64f73fd987be35b16f6c8d2dd6e4808e8f11d38..0b15ede3f0ca10f681cf96404461a741b97d425e 100644 (file)
--- 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
index 50eb2461ac3710191abb66ae047cc6d6f575639b..a2d4dbd0ea251c059e2def0cb0cb346bca999270 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( 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
index a239389fcf68ef38469e50066fb152fd4f957cce..2306a8a39538d0d2fb184c6342aab0c65d4d7c4f 100644 (file)
@@ -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=
 
index 189163c9b5f0c3eb79c373e19ecc70cab10b08cf..b1d065b05c37b201be883c2949c38d7fc4b3fd24 100644 (file)
@@ -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;
        }
index 2b90ed70f0027336ceb2b36eaca26cebb5f209ca..ccbb6aec033f26dfee33914a7b882a51cf3a87ce 100644 (file)
@@ -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;
index 97b6aa43138051e2821dbb34f9d0a5f87f19ca20..3590ba7baecc494f5653c7cd759ff250b6945187 100644 (file)
@@ -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);
 
index 000cc89c01022416ba3ee67ae63c5146682b7990..b23edc838cd171366f456fefa0d566881c37b98b 100644 (file)
@@ -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);