Changeset 1905

Show
Ignore:
Timestamp:
05/08/07 00:19:36
Author:
pvanhoof
Message:

The real fix

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ChangeLog

    r1898 r1905  
     12007-05-08  Philip Van Hoof  <pvanhoof@gnome.org> 
     2 
     3        * Real fix for a gtk_tree_model_row_inserted oddity 
     4        * The problem was that me->cur_len was set to 1 to avoid an assertion 
     5        in gtktreemodelsort.c (in gtk_tree_model_sort_build_level). The real 
     6        fix was to check for list_model->cur_len in various GtkTreeModel 
     7        implementations, rather than the list_model->items->len (only 
     8        registered items are valid for GtkTreeModel, while registering is 
     9        slower than simple appends or prepend, as registered requires the 
     10        registration event to happen in the mainloop) 
     11 
    1122007-05-07  Philip Van Hoof  <pvanhoof@gnome.org> 
    213 
  • trunk/libtinymailui-gtk/tny-gtk-header-list-model.c

    r1904 r1905  
    9090{ 
    9191        TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 
    92         gint i; gboolean retval=FALSE; 
     92        gint i, tlen; gboolean retval=FALSE; 
    9393 
    9494        g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE); 
     
    9898        i = gtk_tree_path_get_indices (path)[0]; 
    9999 
    100         if (i >= list_model->items->len) { 
    101                 g_static_rec_mutex_unlock (list_model->iterator_lock); 
    102                 return FALSE; 
    103         } 
    104  
    105         if (i >= 0 && i < list_model->items->len) { 
    106                 iter->stamp = list_model->stamp; 
    107                 iter->user_data = (gpointer) i; 
    108                 retval = TRUE; 
     100        g_mutex_lock (list_model->ra_lock); 
     101        tlen = list_model->cur_len; 
     102        g_mutex_unlock (list_model->ra_lock); 
     103 
     104        if (i >= tlen) 
     105                retval = FALSE; 
     106        else { 
     107                if (i >= 0 && i < tlen) { 
     108                        iter->stamp = list_model->stamp; 
     109                        iter->user_data = (gpointer) i; 
     110                        retval = TRUE; 
     111                } 
    109112        } 
    110113 
     
    118121{ 
    119122        GtkTreePath *tree_path; 
    120         gint i = 0
     123        gint i = 0, tlen
    121124        TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 
    122125 
     
    129132        i = (gint) iter->user_data; 
    130133 
    131         if (i < 0 || i >= list_model->items->len) { 
     134        g_mutex_lock (list_model->ra_lock); 
     135        tlen = list_model->cur_len; 
     136        g_mutex_unlock (list_model->ra_lock); 
     137 
     138        if (i < 0 || i >= tlen) { 
    132139                g_static_rec_mutex_unlock (list_model->iterator_lock); 
    133140                return NULL; 
     
    135142 
    136143        tree_path = gtk_tree_path_new (); 
    137         gtk_tree_path_append_index (tree_path, (gint) iter->user_data); 
     144        gtk_tree_path_append_index (tree_path, i); 
    138145 
    139146        g_static_rec_mutex_unlock (list_model->iterator_lock); 
     
    230237        const gchar *str; 
    231238        gchar *rdate = NULL; 
    232         int i; 
     239        gint i; 
    233240 
    234241        if (iter->stamp != TNY_GTK_HEADER_LIST_MODEL (self)->stamp) 
     
    243250        i = (gint) iter->user_data; 
    244251 
     252        /* Exception on list_model->cur_len (this one truly allows the full  
     253         * length of the available data in the array, not only the registered 
     254         * length, although in 99.999999% of the cases it's the same) */ 
    245255        if (i < 0 || i >= list_model->items->len) 
    246256        { 
     
    345355        iter->user_data = (gpointer) newv; 
    346356 
    347         retval = (newv >= 0 && newv < list_model->items->len); 
     357        g_mutex_lock (list_model->ra_lock); 
     358        retval = (newv >= 0 && newv < list_model->cur_len); 
     359        g_mutex_unlock (list_model->ra_lock); 
    348360 
    349361        if (!retval) { 
     
    379391 
    380392        if (G_LIKELY (!iter)) 
    381                 retval = list_model->cur_len; /* list_model->items->len; */ 
     393                retval = list_model->cur_len; 
    382394 
    383395        g_static_rec_mutex_unlock (list_model->iterator_lock); 
     
    391403        TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 
    392404        gboolean retval = FALSE; 
     405        gint tlen; 
    393406 
    394407        if (G_UNLIKELY (parent)) 
     
    397410        g_static_rec_mutex_lock (list_model->iterator_lock); 
    398411 
    399         if (n >= 0 && n < list_model->items->len)  
     412        g_mutex_lock (list_model->ra_lock); 
     413        tlen = list_model->cur_len; 
     414        g_mutex_unlock (list_model->ra_lock); 
     415 
     416        if (n >= 0 && n < tlen)  
    400417        { 
    401418                iter->stamp = TNY_GTK_HEADER_LIST_MODEL (self)->stamp; 
     
    431448 
    432449 
    433 typedef struct 
    434 
    435         TnyGtkHeaderListModel *self; 
     450static void 
     451notify_views_add_destroy (gpointer data) 
     452
     453        TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*) data; 
     454 
     455        g_mutex_lock (me->ra_lock); 
     456        me->updating_views = -1; 
     457        me->registered = 0; 
     458        g_mutex_unlock (me->ra_lock); 
     459        g_object_unref (me); 
     460        me->add_timeout = 0; 
     461 
     462        return; 
     463
     464 
     465static gboolean 
     466notify_views_add (gpointer data) 
     467
     468        TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*) data; 
     469        gint already_registered, going_tb_registered, i; 
     470  
     471        gboolean needmore = FALSE; 
    436472        GtkTreePath *path; 
    437473        GtkTreeIter iter; 
    438 } notify_views_data_t; 
    439  
    440  
    441 static void 
    442 notify_views_add_destroy (gpointer data) 
    443 { 
    444         TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*) data; 
    445  
    446         g_mutex_lock (me->ra_lock); 
    447         me->updating_views = -1; 
    448         g_mutex_unlock (me->ra_lock); 
    449  
    450         g_object_unref (me); 
    451  
    452         me->add_timeout = 0; 
    453  
    454         return; 
    455 } 
    456  
    457 static gboolean 
    458 notify_views_add (gpointer data) 
    459 { 
    460         TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*) data; 
    461         gint updated, going_to_update, i, added;  
    462         gboolean needmore = FALSE; 
    463474 
    464475        g_mutex_lock (me->ra_lock); 
    465476        me->updating_views++; 
    466         if (me->recent_updated >= me->items->len) { 
     477        if (me->registered >= me->items->len) { 
    467478                g_mutex_unlock (me->ra_lock); 
    468479                return FALSE; 
    469480        } 
    470         updated = me->recent_updated; 
    471         if (me->items->len - me->recent_updated > 600) { 
    472                 going_to_update = me->recent_updated + 600; 
     481 
     482        already_registered = me->registered; 
     483 
     484        if (me->items->len - already_registered > 600)  
     485        { 
     486                going_tb_registered = already_registered + 600; 
    473487                needmore = TRUE; 
    474         } else  
    475                 going_to_update = me->items->len - 1
    476         me->recent_updated = going_to_update; 
    477         g_mutex_unlock (me->ra_lock)
     488        } else 
     489                going_tb_registered = me->items->len
     490 
     491        me->registered = going_tb_registered
    478492 
    479493        if (me->updating_views < 2) 
    480494                needmore = TRUE; 
    481495 
     496        g_mutex_unlock (me->ra_lock); 
     497 
    482498        gdk_threads_enter(); 
    483 /* printf ("updated=%d, goingto=%d\n", updated, going_to_update); */ 
    484  
    485         for (i = updated; i < going_to_update; i++) 
     499 
     500        for (i = already_registered; i < going_tb_registered; i++) 
    486501        { 
    487                 GtkTreeIter iter
    488                 GtkTreePath *path
     502                iter.stamp = me->stamp
     503                iter.user_data = (gpointer) i
    489504                path = gtk_tree_path_new (); 
    490505                gtk_tree_path_append_index (path, i); 
    491                 iter.stamp = me->stamp; 
    492                 iter.user_data = (gpointer) i; 
    493                 me->cur_len = i+1; 
    494 /* printf ("cur_len=%d\n", me->cur_len); */ 
    495  
    496                 gtk_tree_model_row_inserted ((GtkTreeModel *)me, path, &iter); 
    497  
    498                 gtk_tree_path_free (path); 
     506                if (G_LIKELY (path)) 
     507                { 
     508                        me->cur_len = i+1; 
     509                        gtk_tree_model_row_inserted ((GtkTreeModel *)me, path, &iter); 
     510                        gtk_tree_path_free (path); 
     511                } 
    499512        } 
    500513        gdk_threads_leave(); 
     
    502515        return needmore; 
    503516} 
     517 
     518 
    504519 
    505520/* This will be called often while you are in tny_folder_refresh(_async). It can 
     
    510525{ 
    511526        TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*)self; 
    512         gint depth = g_main_depth (); 
    513527        g_static_rec_mutex_lock (me->iterator_lock); 
    514528 
     
    555569 
    556570 
     571typedef struct 
     572{ 
     573        TnyGtkHeaderListModel *self; 
     574        GObject *item; 
     575} notify_views_data_t; 
     576 
     577 
     578static void  
     579notify_views_delete_destroy (gpointer data) 
     580{ 
     581        notify_views_data_t *stuff = data; 
     582        g_object_unref (stuff->item); 
     583        g_object_unref (stuff->self); 
     584        g_slice_free (notify_views_data_t, data); 
     585        return; 
     586} 
     587 
    557588 
    558589static gboolean 
     
    560591{ 
    561592        notify_views_data_t *stuff = data; 
    562  
    563         stuff->path = tny_gtk_header_list_model_get_path (GTK_TREE_MODEL (stuff->self), &(stuff->iter)); 
    564         if (stuff->path) 
    565         { 
    566                 gtk_tree_model_row_deleted (GTK_TREE_MODEL (stuff->self), stuff->path); 
    567                 gtk_tree_path_free (stuff->path); 
    568         } 
    569         g_object_unref (G_OBJECT (stuff->self)); 
    570         g_slice_free (notify_views_data_t, data); 
    571  
    572         return FALSE; 
    573 
    574  
    575  
    576 /* TNY TODO: massive removals would be slow due to the g_timeout_add being 
    577  * called often. Take a look at the prepend to see how this can be solved. */ 
    578 static void 
    579 tny_gtk_header_list_model_remove (TnyList *self, GObject* item) 
    580 
    581         TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*)self; 
    582         GtkTreePath *path = NULL; 
    583         gint i; gboolean found = FALSE; 
    584  
    585         g_return_if_fail (G_IS_OBJECT (item)); 
    586         g_return_if_fail (G_IS_OBJECT (me)); 
    587  
    588         g_static_rec_mutex_lock (me->iterator_lock); 
     593        GObject *item = stuff->item; 
     594        TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*) stuff->self; 
     595        GtkTreePath *path; 
     596        GtkTreeIter iter; 
     597        gint i; 
     598        gboolean found = FALSE; 
    589599 
    590600        for (i=0; i < me->items->len; i++) 
     
    595605                } 
    596606 
    597         /* Remove something from the list */ 
    598  
    599607        if (found) 
    600608        { 
    601                 notify_views_data_t *stuff; 
    602  
    603                 stuff = g_slice_new (notify_views_data_t); 
    604                 stuff->iter.stamp = me->stamp; 
    605                 stuff->iter.user_data = (gpointer) i; 
    606                 stuff->self = g_object_ref (G_OBJECT (self)); 
    607                 g_timeout_add (0, notify_views_delete, stuff); 
    608  
    609                 g_ptr_array_remove (me->items, item); 
    610         } 
    611  
    612         g_static_rec_mutex_unlock (me->iterator_lock); 
    613         g_object_unref (G_OBJECT (item)); 
     609                iter.stamp = me->stamp; 
     610                iter.user_data = (gpointer) i; 
     611                path = gtk_tree_path_new (); 
     612                gtk_tree_path_append_index (path, i); 
     613                if (G_LIKELY (path)) 
     614                { 
     615                        gtk_tree_model_row_deleted (GTK_TREE_MODEL (me), path); 
     616                        me->cur_len--; 
     617                        gtk_tree_path_free (path); 
     618                } 
     619 
     620                g_static_rec_mutex_lock (me->iterator_lock); 
     621                item = g_ptr_array_remove_index (me->items, i); 
     622                g_static_rec_mutex_unlock (me->iterator_lock); 
     623                if (G_LIKELY (item))  
     624                        g_object_unref (item); 
     625        } 
     626 
     627        return FALSE; 
     628
     629 
     630static void 
     631tny_gtk_header_list_model_remove (TnyList *self, GObject* item) 
     632
     633        notify_views_data_t *stuff; 
     634        stuff = g_slice_new (notify_views_data_t); 
     635        stuff->self = g_object_ref (G_OBJECT (self)); 
     636        stuff->item = g_object_ref (item); 
     637        g_timeout_add_full (0, G_PRIORITY_DEFAULT_IDLE,  
     638                notify_views_delete, stuff, notify_views_delete_destroy); 
     639        return; 
    614640} 
    615641 
     
    759785        self->updating_views = -1; 
    760786        self->ra_lock = g_mutex_new (); 
    761         self->recent_updated = 0; 
     787        self->registered = 0; 
    762788 
    763789        return; 
     
    787813        } 
    788814 
    789         self->recent_updated = 0; 
    790  
    791815        /* Set it to 1 as initial value, else you cause the length > 0  
    792816         * assertion in gtk_tree_model_sort_build_level (I have no idea why the 
    793817         * assertion is placed there, in stead of a normal return, though) */ 
    794818  
    795         self->cur_len = 1;  
    796  
    797819        g_ptr_array_foreach (self->items, (GFunc)g_object_unref, NULL); 
    798820        if (self->folder) 
  • trunk/libtinymailui-gtk/tny-gtk-header-list-model.h

    r1904 r1905  
    6666        GStaticRecMutex *iterator_lock; 
    6767        TnyFolder *folder; 
    68         gint stamp, recent_updated; 
     68        gint stamp, registered; 
    6969        gint updating_views; 
    7070        GMutex *ra_lock;