From f409db7051a26c30cf7e49faa96ab97685963207 Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Tue, 22 Aug 2006 16:28:00 +0000 Subject: [PATCH] 2006-08-22 [colin] 2.4.0cvs73 * src/folder.c Set folder's mtime after writing its cache * src/folderview.c Add some timing * src/procmsg.c Don't do useless stuff if we don't thread by subject * src/summaryview.c Add some timing, don't deselect prior to selecting (gtksctree does it itself), remove crash avoidance hacks as it's been properly fixed since a while * src/common/utils.c Optimize to_human_readable(): _() is slow, do it only once, and avoid %f format for KB (the most common in a summaryview) * src/gtk/gtksctree.c Don't uselessly freeze/thaw (fixes flicker on next unread and friends), reduce number of g_list_nth/g_list_position where possible * src/gtk/gtkutils.c * src/gtk/gtkutils.h Reduce number of g_list_nth/g_list_position where possible. All of this makes loading as 70k folder 2.1 seconds instead of 3.2 (with hot FS caches). (1.3 seconds without Date and Size columns...) --- ChangeLog | 31 ++++++++++++++++++++++++++++ PATCHSETS | 1 + configure.ac | 2 +- src/common/utils.c | 46 +++++++++++++++++++++++++++++++---------- src/folder.c | 3 +++ src/folderview.c | 20 +++++++++++++----- src/gtk/gtksctree.c | 50 ++++++++++++++++++++++++++++++++++----------- src/gtk/gtkutils.c | 5 +++-- src/gtk/gtkutils.h | 3 ++- src/procmsg.c | 11 +++++++--- src/summaryview.c | 24 +++++++++------------- 11 files changed, 147 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8c37ca7f7..a7d4a209a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2006-08-22 [colin] 2.4.0cvs73 + + * src/folder.c + Set folder's mtime after writing its + cache + * src/folderview.c + Add some timing + * src/procmsg.c + Don't do useless stuff if we don't + thread by subject + * src/summaryview.c + Add some timing, don't deselect prior + to selecting (gtksctree does it itself), + remove crash avoidance hacks as it's been + properly fixed since a while + * src/common/utils.c + Optimize to_human_readable(): _() is slow, + do it only once, and avoid %f format for KB + (the most common in a summaryview) + * src/gtk/gtksctree.c + Don't uselessly freeze/thaw (fixes flicker + on next unread and friends), reduce number + of g_list_nth/g_list_position where possible + * src/gtk/gtkutils.c + * src/gtk/gtkutils.h + Reduce number of g_list_nth/g_list_position + where possible. + All of this makes loading as 70k folder 2.1 + seconds instead of 3.2 (with hot FS caches). + (1.3 seconds without Date and Size columns...) + 2006-08-22 [paul] 2.4.0cvs72 wrap documents and do some items from mones' MANUAL-TODO: diff --git a/PATCHSETS b/PATCHSETS index e2ab26adc..d3a2af650 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -1764,3 +1764,4 @@ ( cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/Makefile.am; cvs diff -u -r 1.60.2.61 -r 1.60.2.62 src/addressbook.c; cvs diff -u -r 1.3.2.42 -r 1.3.2.43 src/prefs_themes.c; cvs diff -u -r 1.5.2.37 -r 1.5.2.38 src/gtk/gtkutils.c; cvs diff -u -r 1.5.2.32 -r 1.5.2.33 src/gtk/pluginwindow.c; cvs diff -u -r 1.1.2.12 -r 1.1.2.13 src/plugins/pgpcore/prefs_gpg.c; cvs diff -u -r 1.1.2.26 -r 1.1.2.27 src/plugins/pgpcore/sgpgme.c; ) > 2.4.0cvs70.patchset ( cvs diff -u -r 1.5.2.33 -r 1.5.2.34 src/gtk/pluginwindow.c; ) > 2.4.0cvs71.patchset ( cvs diff -u -r 1.1.2.6 -r 1.1.2.7 manual/account.xml; cvs diff -u -r 1.1.2.9 -r 1.1.2.10 manual/faq.xml; cvs diff -u -r 1.1.2.8 -r 1.1.2.9 manual/handling.xml; ) > 2.4.0cvs72.patchset +( cvs diff -u -r 1.213.2.106 -r 1.213.2.107 src/folder.c; cvs diff -u -r 1.207.2.112 -r 1.207.2.113 src/folderview.c; cvs diff -u -r 1.150.2.73 -r 1.150.2.74 src/procmsg.c; cvs diff -u -r 1.395.2.230 -r 1.395.2.231 src/summaryview.c; cvs diff -u -r 1.36.2.75 -r 1.36.2.76 src/common/utils.c; cvs diff -u -r 1.1.4.21 -r 1.1.4.22 src/gtk/gtksctree.c; cvs diff -u -r 1.5.2.38 -r 1.5.2.39 src/gtk/gtkutils.c; cvs diff -u -r 1.4.2.23 -r 1.4.2.24 src/gtk/gtkutils.h; ) > 2.4.0cvs73.patchset diff --git a/configure.ac b/configure.ac index cf460118c..62bd591a3 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=72 +EXTRA_VERSION=73 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/common/utils.c b/src/common/utils.c index a069522f4..111c32969 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -334,20 +334,44 @@ gchar *itos(gint n) return itos_buf(nstr, n); } +#define divide(num,divisor,i,d) \ +{ \ + register int tmp; \ + i = num/divisor; \ + tmp = i*divisor; \ + d = num-tmp; \ + if (d > 1000) d /= 1000; \ + else if (d > 100) d /= 100; \ + else if (d > 10) d /= 10; \ +} + gchar *to_human_readable(off_t size) { static gchar str[14]; - - if (size < 1024) - g_snprintf(str, sizeof(str), _("%dB"), (gint)size); - else if (size >> 10 < 1024) - g_snprintf(str, sizeof(str), _("%.1fKB"), (gfloat)size / (1 << 10)); - else if (size >> 20 < 1024) - g_snprintf(str, sizeof(str), _("%.2fMB"), (gfloat)size / (1 << 20)); - else - g_snprintf(str, sizeof(str), _("%.2fGB"), (gfloat)size / (1 << 30)); - - return str; + static gchar *b_format = NULL, *kb_format = NULL, + *mb_format = NULL, *gb_format = NULL; + register int t = 0, r = 0; + if (b_format == NULL) { + b_format = _("%dB"); + kb_format = _("%d.%dKB"); + mb_format = _("%.2fMB"); + gb_format = _("%.2fGB"); + } + + if (size < 1024) { + g_snprintf(str, sizeof(str), b_format, (gint)size); + return str; + } else if (size >> 10 < 1024) { + divide(size, (1 << 10), t, r); + g_snprintf(str, sizeof(str), kb_format, t, r); + return str; + } else if (size >> 20 < 1024) { + g_snprintf(str, sizeof(str), mb_format, (gfloat)size / (1 << 20)); + return str; + } else { + g_snprintf(str, sizeof(str), gb_format, (gfloat)size / (1 << 30)); + return str; + } } /* strcmp with NULL-checking */ diff --git a/src/folder.c b/src/folder.c index 23b4ab9f7..8793a7539 100644 --- a/src/folder.c +++ b/src/folder.c @@ -2277,6 +2277,9 @@ void folder_item_write_cache(FolderItem *item) } } + if (FOLDER_TYPE(item->folder) == F_MH) + item->mtime = time(NULL); + g_free(cache_file); g_free(mark_file); } diff --git a/src/folderview.c b/src/folderview.c index d19528615..e905c1385 100644 --- a/src/folderview.c +++ b/src/folderview.c @@ -67,6 +67,7 @@ #include "filtering.h" #include "quicksearch.h" #include "manual.h" +#include "timing.h" #define COL_FOLDER_WIDTH 150 #define COL_NUM_WIDTH 32 @@ -2000,11 +2001,12 @@ static void folderview_selected(GtkCTree *ctree, GtkCTreeNode *row, FolderItem *item; gchar *buf; int res = 0; - + START_TIMING("--- folderview_selected"); folderview->selected = row; if (folderview->opened == row) { folderview->open_folder = FALSE; + END_TIMING(); return; } @@ -2013,13 +2015,19 @@ static void folderview_selected(GtkCTree *ctree, GtkCTreeNode *row, gtkut_ctree_set_focus_row(ctree, folderview->opened); gtk_ctree_select(ctree, folderview->opened); } + END_TIMING(); return; } - if (!folderview->open_folder) return; - + if (!folderview->open_folder) { + END_TIMING(); + return; + } item = gtk_ctree_node_get_row_data(ctree, row); - if (!item || item->no_select) return; + if (!item || item->no_select) { + END_TIMING(); + return; + } can_select = FALSE; @@ -2086,7 +2094,7 @@ static void folderview_selected(GtkCTree *ctree, GtkCTreeNode *row, folderview->open_folder = FALSE; can_select = TRUE; - + END_TIMING(); return; } else if (res == -2) { PostponedSelectData *data = g_new0(PostponedSelectData, 1); @@ -2099,6 +2107,7 @@ static void folderview_selected(GtkCTree *ctree, GtkCTreeNode *row, folderview->open_folder = FALSE; can_select = TRUE; g_timeout_add(500, postpone_select, data); + END_TIMING(); return; } @@ -2124,6 +2133,7 @@ static void folderview_selected(GtkCTree *ctree, GtkCTreeNode *row, folderview->open_folder = FALSE; can_select = TRUE; + END_TIMING(); } static void folderview_tree_expanded(GtkCTree *ctree, GtkCTreeNode *node, diff --git a/src/gtk/gtksctree.c b/src/gtk/gtksctree.c index 0926f4072..851c0eada 100644 --- a/src/gtk/gtksctree.c +++ b/src/gtk/gtksctree.c @@ -255,8 +255,11 @@ select_range (GtkSCTree *sctree, gint row) } /* Handles row selection according to the specified modifier state */ +/* in certain cases, we arrive here from a function knowing the GtkCTreeNode, and having + * already slowly found row using g_list_position. In which case, _node will be non-NULL + * to avoid this function having to slowly find it with g_list_nth. */ static void -select_row (GtkSCTree *sctree, gint row, gint col, guint state) +select_row (GtkSCTree *sctree, gint row, gint col, guint state, GtkCTreeNode *_node) { gboolean range, additive; g_return_if_fail (sctree != NULL); @@ -269,20 +272,41 @@ select_row (GtkSCTree *sctree, gint row, gint col, guint state) (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_SINGLE) && (GTK_CLIST(sctree)->selection_mode != GTK_SELECTION_BROWSE); - gtk_clist_freeze (GTK_CLIST (sctree)); + /* heavy GUI updates will be done only if we're selecting a range. + * additive selection is ctrl-click, where the user is the slow factor. + * So we only freeze the list if selecting a range (potentially thousands + * of lines. */ + if (range) + gtk_clist_freeze (GTK_CLIST (sctree)); GTK_CLIST(sctree)->focus_row = row; if (!additive) { - sctree->selecting_range = TRUE; + /* if this selection isn't additive, we have to unselect what + * is selected. Here, heavy GUI updates can occur if we have + * a big selection. See if more than one line is selected, in + * which case, freeze, else don't. */ + + gboolean should_freeze = FALSE; + if (GTK_CLIST(sctree)->selection + && GTK_CLIST(sctree)->selection->next) { + should_freeze = TRUE; + sctree->selecting_range = TRUE; + gtk_clist_freeze (GTK_CLIST (sctree)); + } + gtk_clist_unselect_all (GTK_CLIST (sctree)); - sctree->selecting_range = FALSE; + + if (should_freeze) { + gtk_clist_thaw (GTK_CLIST (sctree)); + sctree->selecting_range = FALSE; + } } if (!range) { GtkCTreeNode *node; - node = gtk_ctree_node_nth (GTK_CTREE(sctree), row); + node = _node ? _node : gtk_ctree_node_nth (GTK_CTREE(sctree), row); /*No need to manage overlapped list*/ if (additive) { @@ -301,7 +325,8 @@ select_row (GtkSCTree *sctree, gint row, gint col, guint state) } else select_range (sctree, row); - gtk_clist_thaw (GTK_CLIST (sctree)); + if (range) + gtk_clist_thaw (GTK_CLIST (sctree)); } /* Our handler for button_press events. We override all of GtkCList's broken @@ -360,7 +385,7 @@ gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event) sctree->dnd_select_pending_state = event->state; sctree->dnd_select_pending_row = row; } else { - select_row (sctree, row, col, event->state); + select_row (sctree, row, col, event->state, NULL); } } else { sctree->selecting_range = TRUE; @@ -373,7 +398,7 @@ gtk_sctree_button_press (GtkWidget *widget, GdkEventButton *event) /* Emit *_popup_menu signal*/ if (on_row) { if (!row_is_selected(sctree,row)) - select_row (sctree, row, col, 0); + select_row (sctree, row, col, 0, NULL); g_signal_emit (G_OBJECT (sctree), sctree_signals[ROW_POPUP_MENU], 0, event); @@ -445,7 +470,7 @@ gtk_sctree_button_release (GtkWidget *widget, GdkEventButton *event) if (on_row) { if (sctree->dnd_select_pending) { - select_row (sctree, row, col, sctree->dnd_select_pending_state); + select_row (sctree, row, col, sctree->dnd_select_pending_state, NULL); sctree->dnd_select_pending = FALSE; sctree->dnd_select_pending_state = 0; } @@ -492,7 +517,8 @@ gtk_sctree_motion (GtkWidget *widget, GdkEventMotion *event) select_row (sctree, sctree->dnd_select_pending_row, -1, - sctree->dnd_select_pending_state); + sctree->dnd_select_pending_state, + NULL); sctree->dnd_select_pending = FALSE; sctree->dnd_select_pending_state = 0; @@ -620,14 +646,14 @@ void gtk_sctree_select (GtkSCTree *sctree, GtkCTreeNode *node) { select_row(sctree, g_list_position(GTK_CLIST(sctree)->row_list, (GList *)node), - -1, 0); + -1, 0, node); } void gtk_sctree_select_with_state (GtkSCTree *sctree, GtkCTreeNode *node, int state) { select_row(sctree, g_list_position(GTK_CLIST(sctree)->row_list, (GList *)node), - -1, state); + -1, state, node); } void gtk_sctree_unselect_all (GtkSCTree *sctree) diff --git a/src/gtk/gtkutils.c b/src/gtk/gtkutils.c index a3df65462..a2b17af8a 100644 --- a/src/gtk/gtkutils.c +++ b/src/gtk/gtkutils.c @@ -275,7 +275,7 @@ ComboButton *gtkut_combo_button_create(GtkWidget *button, #define ROW_FROM_YPIXEL(clist, y) (((y) - (clist)->voffset) / \ ((clist)->row_height + CELL_SPACING)) -void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node) +void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node, gint _row) { GtkCList *clist = GTK_CLIST(ctree); gint row; @@ -284,7 +284,8 @@ void gtkut_ctree_node_move_if_on_the_edge(GtkCTree *ctree, GtkCTreeNode *node) g_return_if_fail(ctree != NULL); g_return_if_fail(node != NULL); - row = g_list_position(clist->row_list, (GList *)node); + row = (_row != -1 ? _row : g_list_position(clist->row_list, (GList *)node)); + if (row < 0 || row >= clist->rows || clist->row_height == 0) return; row_visibility = gtk_clist_row_is_visible(clist, row); prev_row_visibility = gtk_clist_row_is_visible(clist, row - 1); diff --git a/src/gtk/gtkutils.h b/src/gtk/gtkutils.h index ca8d884a2..25815a570 100644 --- a/src/gtk/gtkutils.h +++ b/src/gtk/gtkutils.h @@ -120,7 +120,8 @@ ComboButton *gtkut_combo_button_create (GtkWidget *button, void gtkut_ctree_node_move_if_on_the_edge (GtkCTree *ctree, - GtkCTreeNode *node); + GtkCTreeNode *node, + gint _row); gint gtkut_ctree_get_nth_from_node (GtkCTree *ctree, GtkCTreeNode *node); GtkCTreeNode *gtkut_ctree_node_next (GtkCTree *ctree, diff --git a/src/procmsg.c b/src/procmsg.c index 106963902..85c889e19 100644 --- a/src/procmsg.c +++ b/src/procmsg.c @@ -251,8 +251,11 @@ GNode *procmsg_get_thread_tree(GSList *mlist) START_TIMING("procmsg_get_thread_tree"); root = g_node_new(NULL); msgid_table = g_hash_table_new(g_str_hash, g_str_equal); - subject_relation = g_relation_new(2); - g_relation_index(subject_relation, 0, g_str_hash, g_str_equal); + + if (prefs_common.thread_by_subject) { + subject_relation = g_relation_new(2); + g_relation_index(subject_relation, 0, g_str_hash, g_str_equal); + } for (; mlist != NULL; mlist = mlist->next) { msginfo = (MsgInfo *)mlist->data; @@ -334,7 +337,9 @@ GNode *procmsg_get_thread_tree(GSList *mlist) END_TIMING(); } - g_relation_destroy(subject_relation); + if (prefs_common.thread_by_subject) + g_relation_destroy(subject_relation); + g_hash_table_destroy(msgid_table); END_TIMING(); return root; diff --git a/src/summaryview.c b/src/summaryview.c index 832332c45..d885d6fcf 100644 --- a/src/summaryview.c +++ b/src/summaryview.c @@ -854,7 +854,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item) if (!summaryview->mainwin) return FALSE; - +START_TIMING("--------- summary_show"); summaryview->last_displayed = NULL; summary_switch_from_to(summaryview, item); @@ -901,6 +901,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item) } else { summary_unlock(summaryview); inc_unlock(); + END_TIMING(); return FALSE; } if (changed || !quicksearch_is_active(summaryview->quicksearch)) @@ -933,7 +934,8 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item) summaryview->folderview, summaryview->folder_item); main_window_cursor_normal(summaryview->mainwin); - } + } + END_TIMING(); return TRUE; } g_free(buf); @@ -1018,6 +1020,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item) summary_unlock(summaryview); inc_unlock(); summary_show(summaryview, summaryview->folder_item); + END_TIMING(); return FALSE; } g_slist_free(mlist); @@ -1169,7 +1172,7 @@ gboolean summary_show(SummaryView *summaryview, FolderItem *item) main_window_cursor_normal(summaryview->mainwin); summary_unlock(summaryview); inc_unlock(); - + END_TIMING(); return TRUE; } @@ -1766,18 +1769,8 @@ void summary_select_node(SummaryView *summaryview, GtkCTreeNode *node, GTK_EVENTS_FLUSH(); summary_unlock(summaryview); gtk_widget_grab_focus(GTK_WIDGET(ctree)); - if (GTK_CTREE_ROW(node) == NULL) { - g_warning("crash avoidance hack 1\n"); - return; - } - if (((GtkCListRow *)(GTK_CTREE_ROW(node)))->state < GTK_STATE_NORMAL - || ((GtkCListRow *)(GTK_CTREE_ROW(node)))->state > GTK_STATE_INSENSITIVE) { - g_warning("crash avoidance hack 2\n"); - return; - } gtk_ctree_node_moveto(ctree, node, 0, 0.5, 0); } - summary_unselect_all(summaryview); if (display_msg && summaryview->displayed == node) summaryview->displayed = NULL; summaryview->display_msg = display_msg; @@ -2593,6 +2586,7 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[], else text[col_pos[S_COL_NUMBER]] = ""; + /* slow! */ if (summaryview->col_state[summaryview->col_pos[S_COL_SIZE]].visible) text[col_pos[S_COL_SIZE]] = to_human_readable(msginfo->size); else @@ -2603,6 +2597,7 @@ static void summary_set_header(SummaryView *summaryview, gchar *text[], else text[col_pos[S_COL_SCORE]] = ""; + /* slow! */ if (summaryview->col_state[summaryview->col_pos[S_COL_DATE]].visible) { if (msginfo->date_t) { procheader_date_get_localtime(date_modified, @@ -2849,7 +2844,8 @@ static void summary_display_msg_full(SummaryView *summaryview, val = messageview_show(msgview, msginfo, all_headers); if (GTK_CLIST(msgview->mimeview->ctree)->row_list == NULL) gtk_widget_grab_focus(summaryview->ctree); - gtkut_ctree_node_move_if_on_the_edge(ctree, row); + gtkut_ctree_node_move_if_on_the_edge(ctree, row, + GTK_CLIST(summaryview->ctree)->focus_row); } if (val == 0 && MSG_IS_UNREAD(msginfo->flags)) { -- 2.25.1