2006-08-22 [colin] 2.4.0cvs73
authorColin Leroy <colin@colino.net>
Tue, 22 Aug 2006 16:28:00 +0000 (16:28 +0000)
committerColin Leroy <colin@colino.net>
Tue, 22 Aug 2006 16:28:00 +0000 (16:28 +0000)
* 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
PATCHSETS
configure.ac
src/common/utils.c
src/folder.c
src/folderview.c
src/gtk/gtksctree.c
src/gtk/gtkutils.c
src/gtk/gtkutils.h
src/procmsg.c
src/summaryview.c

index 8c37ca7f730968c8900c3aae71a54e945960795b..a7d4a209a24ee95c8e8b643f6a3e85cca75637e5 100644 (file)
--- 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:
index e2ab26adced04f6b88a5fa267bafd1ae2ed6d625..d3a2af65064a1b75febf5b7d709fc35bbe3ad1b3 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( 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
index cf460118cf7a5670ff6d2d79494cec827eeae979..62bd591a388933fc94abd8a36e1e1e5a8aee28dc 100644 (file)
@@ -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=
 
index a069522f479afe6214735c6ae444262067bd4a82..111c3296964724c71bb979541bb8348278dea847 100644 (file)
@@ -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 */
index 23b4ab9f744d6d58eb33038695c2ec77a135363e..8793a75392feb648f141dbfa4ad0ed7156d61c87 100644 (file)
@@ -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);
 }
index d1952861585b3687753a5080ee5d31eb54054aa4..e905c13851e394417c8da634c616824f5821d0b6 100644 (file)
@@ -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,
index 0926f407285b26fd976e3036d752d87491065c30..851c0eadae1fc8705b1e479573a098035409c405 100644 (file)
@@ -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)
index a3df65462bf61c70c6f83b54c36ef32e1c2ba8a0..a2b17af8ab4e9253c0f40573d0796c4bc3423e14 100644 (file)
@@ -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);
index ca8d884a2538f5a8770cc0bebfeeb0385f531b7e..25815a570fda68c60aed347ab04fc26022cb65b7 100644 (file)
@@ -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,
index 1069639027265fb44a6c11ca62a6f32d4414dcd7..85c889e19812a8d5f6c46bc04c029405e3ed74af 100644 (file)
@@ -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;
index 832332c4562ce834a711b017365937d2618b6cf0..d885d6fcfd975ee36bd1540b0068df89c9c7ccdc 100644 (file)
@@ -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)) {