Changeset 1708

Show
Ignore:
Timestamp:
03/06/07 22:31:02
Author:
pvanhoof
Message:

Second batch of cruft removals and reimplementations

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ChangeLog

    r1700 r1708  
     12007-03-06  Philip Van Hoof  <pvanhoof@gnome.org> 
     2 
     3        * Bugfixes for summary items and writing them to disk, keeping the 
     4        local array in sync with that is on disk 
     5        * Reimplementation of the TnyGtkHeaderListModel, to use a GPtrArray in 
     6        stead of a GList: should be both faster and less memory consuming 
     7        * Removed some non-used camel-lite functionality and symbols 
     8 
    192007-03-05  Philip Van Hoof  <pvanhoof@gnome.org> 
    210 
  • trunk/libtinymail-camel/camel-lite/camel/providers/local/camel-maildir-summary.c

    r1706 r1708  
    605605                        const char *filename; 
    606606 
    607                         if (cls->index && (!camel_index_has_name(cls->index, uid))) { 
    608                                 /* message_info_new will handle duplicates */ 
     607                        /*if (cls->index && (!camel_index_has_name(cls->index, uid))) { 
     608                                message_info_new will handle duplicates  
    609609                                camel_maildir_summary_add(cls, d->d_name, forceindex); 
    610                         } 
     610                        }*/ 
    611611 
    612612                        mdi = (CamelMaildirMessageInfo *)info; 
  • trunk/libtinymailui-gtk/tny-gtk-header-list-iterator-priv.h

    r906 r1708  
    4444        GObject parent; 
    4545        TnyGtkHeaderListModel *model; 
    46         GList *current; 
     46        guint current; 
    4747}; 
    4848 
     
    5252}; 
    5353 
    54 void _tny_gtk_header_list_iterator_set_model (TnyGtkHeaderListIterator *self, TnyGtkHeaderListModel *model, gboolean lock); 
    55 TnyIterator* _tny_gtk_header_list_iterator_new (TnyGtkHeaderListModel *model, gboolean lock); 
     54TnyIterator* _tny_gtk_header_list_iterator_new (TnyGtkHeaderListModel *model); 
    5655 
    5756gboolean _tny_gtk_header_list_iterator_is_done_nl (TnyGtkHeaderListIterator *self); 
  • trunk/libtinymailui-gtk/tny-gtk-header-list-iterator.c

    r1705 r1708  
    3030 
    3131 
    32 void  
    33 _tny_gtk_header_list_iterator_set_model (TnyGtkHeaderListIterator *self, TnyGtkHeaderListModel *model, gboolean lock
     32static void  
     33_tny_gtk_header_list_iterator_set_model (TnyGtkHeaderListIterator *self, TnyGtkHeaderListModel *model
    3434{ 
    3535        self->model = model; 
     
    4242           the first node in the list. */ 
    4343 
    44         if (lock) 
    45                 g_static_rec_mutex_lock (self->model->iterator_lock); 
    46  
    47         self->current = model->first; 
    48  
    49         if (lock) 
    50                 g_static_rec_mutex_unlock (self->model->iterator_lock); 
     44        self->current = 0; 
    5145 
    5246        return; 
     
    5650 
    5751TnyIterator* 
    58 _tny_gtk_header_list_iterator_new (TnyGtkHeaderListModel *model, gboolean lock
     52_tny_gtk_header_list_iterator_new (TnyGtkHeaderListModel *model
    5953{ 
    6054        TnyGtkHeaderListIterator *self = g_object_new (TNY_TYPE_GTK_HEADER_LIST_ITERATOR, NULL); 
    6155 
    62         _tny_gtk_header_list_iterator_set_model (self, model, lock); 
     56        _tny_gtk_header_list_iterator_set_model (self, model); 
    6357 
    6458        return TNY_ITERATOR (self); 
     
    7165 
    7266        self->model = NULL; 
    73         self->current = NULL
     67        self->current = 0
    7468 
    7569        return; 
     
    8882_tny_gtk_header_list_iterator_next_nl (TnyGtkHeaderListIterator *me) 
    8983{ 
    90         me->current = me->current?g_list_next (me->current):NULL; 
    91  
     84        me->current++; 
    9285        return; 
    9386} 
     
    9891        TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 
    9992 
     93        if (G_UNLIKELY (!me || !me->model)) 
     94                return; 
     95 
     96        /* Move the iterator to the next node */ 
     97 
     98        g_static_rec_mutex_lock (me->model->iterator_lock); 
     99        me->current++; 
     100        g_static_rec_mutex_unlock (me->model->iterator_lock); 
     101 
     102        return; 
     103} 
     104 
     105void 
     106_tny_gtk_header_list_iterator_prev_nl (TnyGtkHeaderListIterator *me) 
     107{ 
     108        me->current--; 
     109        return; 
     110} 
     111 
     112static void 
     113tny_gtk_header_list_iterator_prev (TnyIterator *self) 
     114{ 
     115        TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 
     116 
     117        if (G_UNLIKELY (!me || !me->model)) 
     118                return; 
     119 
     120        /* Move the iterator to the previous node */ 
     121 
     122        g_static_rec_mutex_lock (me->model->iterator_lock); 
     123        me->current--; 
     124        g_static_rec_mutex_unlock (me->model->iterator_lock); 
     125 
     126        return; 
     127} 
     128 
     129gboolean  
     130_tny_gtk_header_list_iterator_is_done_nl (TnyGtkHeaderListIterator *me) 
     131{ 
     132        if (G_UNLIKELY (!me  || !me->model)) 
     133                return TRUE; 
     134 
     135        return (me->current < 0 || me->current >= me->model->items->len); 
     136} 
     137 
     138static gboolean  
     139tny_gtk_header_list_iterator_is_done (TnyIterator *self) 
     140{ 
     141        TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 
     142        gboolean retval = FALSE; 
     143 
     144        if (G_UNLIKELY (!me || !me->model)) 
     145                return FALSE; 
     146 
     147        g_static_rec_mutex_lock (me->model->iterator_lock); 
     148        retval = (me->current < 0 || me->current >= me->model->items->len); 
     149        g_static_rec_mutex_unlock (me->model->iterator_lock); 
     150 
     151        return retval; 
     152} 
     153 
     154 
     155void 
     156_tny_gtk_header_list_iterator_first_nl (TnyGtkHeaderListIterator *me) 
     157{ 
     158        me->current = 0; 
     159 
     160        return; 
     161} 
     162 
     163static void 
     164tny_gtk_header_list_iterator_first (TnyIterator *self) 
     165{ 
     166        TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 
     167 
    100168        if (G_UNLIKELY (!me || !me->current || !me->model)) 
    101169                return; 
    102170 
    103         /* Move the iterator to the next node */ 
    104  
    105         g_static_rec_mutex_lock (me->model->iterator_lock); 
    106         me->current = g_list_next (me->current); 
    107         g_static_rec_mutex_unlock (me->model->iterator_lock); 
    108  
    109         return; 
    110 
     171        g_static_rec_mutex_lock (me->model->iterator_lock); 
     172        me->current = 0; 
     173        g_static_rec_mutex_unlock (me->model->iterator_lock); 
     174 
     175        return; 
     176
     177 
    111178 
    112179void 
    113 _tny_gtk_header_list_iterator_prev_nl (TnyGtkHeaderListIterator *me) 
    114 
    115         me->current = me->current?g_list_previous (me->current):NULL; 
    116  
    117         return; 
    118 
    119  
    120 static void 
    121 tny_gtk_header_list_iterator_prev (TnyIterator *self) 
     180_tny_gtk_header_list_iterator_nth_nl (TnyGtkHeaderListIterator *me, guint nth) 
     181
     182        me->current = nth; 
     183        return; 
     184
     185 
     186static void  
     187tny_gtk_header_list_iterator_nth (TnyIterator *self, guint nth) 
    122188{ 
    123189        TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 
     
    126192                return; 
    127193 
    128         /* Move the iterator to the previous node */ 
    129  
    130         g_static_rec_mutex_lock (me->model->iterator_lock); 
    131         me->current = g_list_previous (me->current); 
    132         g_static_rec_mutex_unlock (me->model->iterator_lock); 
    133  
    134         return; 
    135 
    136  
    137 gboolean  
    138 _tny_gtk_header_list_iterator_is_done_nl (TnyGtkHeaderListIterator *me) 
    139 
    140         if (G_UNLIKELY (!me  || !me->model)) 
    141                 return TRUE; 
    142  
    143         return me->current == NULL; 
    144 
    145  
    146 static gboolean  
    147 tny_gtk_header_list_iterator_is_done (TnyIterator *self) 
    148 
    149         TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 
    150         gboolean retval = FALSE; 
    151  
    152         g_static_rec_mutex_lock (me->model->iterator_lock); 
    153  
    154         if (G_UNLIKELY (!me  || !me->model)) { 
    155                 g_static_rec_mutex_unlock (me->model->iterator_lock); 
    156                 return TRUE; 
    157         } 
    158  
    159         retval = (me->current == NULL); 
    160         g_static_rec_mutex_unlock (me->model->iterator_lock); 
    161  
    162         return retval; 
    163 
    164  
    165  
    166 void 
    167 _tny_gtk_header_list_iterator_first_nl (TnyGtkHeaderListIterator *me) 
    168 
    169         me->current = me->model?me->model->first:NULL; 
    170  
    171         return; 
    172 
    173  
    174 static void 
    175 tny_gtk_header_list_iterator_first (TnyIterator *self) 
    176 
    177         TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 
    178  
    179         if (G_UNLIKELY (!me || !me->current || !me->model)) 
    180                 return; 
    181  
    182         /* Move the iterator to the first node. We know that model always  
    183            keeps a reference to the first node, there's nothing wrong with  
    184            using that one. */ 
    185  
    186         g_static_rec_mutex_lock (me->model->iterator_lock); 
    187         me->current = me->model->first; 
    188         g_static_rec_mutex_unlock (me->model->iterator_lock); 
    189  
    190         return; 
    191 
    192  
    193  
    194 void 
    195 _tny_gtk_header_list_iterator_nth_nl (TnyGtkHeaderListIterator *me, guint nth) 
    196 
    197         me->current = me->model?g_list_nth (me->model->first, nth):NULL; 
    198  
    199         return; 
    200 
    201  
    202 static void  
    203 tny_gtk_header_list_iterator_nth (TnyIterator *self, guint nth) 
    204 
    205         TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 
    206  
    207         if (G_UNLIKELY (!me || !me->current || !me->model)) 
    208                 return; 
    209  
    210         /* Move the iterator to the nth node. We'll count from zero, 
    211            so we start with the first node of which we know the model 
    212            stored a reference. */ 
    213  
    214         g_static_rec_mutex_lock (me->model->iterator_lock); 
    215         me->current = g_list_nth (me->model->first, nth); 
     194        g_static_rec_mutex_lock (me->model->iterator_lock); 
     195        me->current = nth; 
    216196        g_static_rec_mutex_unlock (me->model->iterator_lock); 
    217197 
     
    223203_tny_gtk_header_list_iterator_get_current_nl (TnyGtkHeaderListIterator *me) 
    224204{ 
    225         return me->current?me->current->data:NULL
     205        return me->model->items->pdata[me->current]
    226206} 
    227207 
     
    238218 
    239219        g_static_rec_mutex_lock (me->model->iterator_lock); 
    240         retval = (G_UNLIKELY (me->current)) ? me->current->data : NULL
     220        retval = me->model->items->pdata[me->current]
    241221        g_static_rec_mutex_unlock (me->model->iterator_lock); 
    242222 
  • trunk/libtinymailui-gtk/tny-gtk-header-list-model.c

    r1705 r1708  
    3939#include "tny-gtk-header-list-iterator-priv.h" 
    4040 
    41 /* The function is locked, so this is secure (and might cause less 
    42 stack allocations)? It's probably a naïve manual optimization.*/ 
    43  
    44  
    45 void /* When sorting, this method is called a gazillion times */ 
    46 _tny_gtk_header_list_iterator_travel_to_nth_nl (TnyGtkHeaderListIterator *self, guint cur, guint nth) 
    47 { 
    48  
    49   /* If we have a usable index table, we'll use it. This happens when as only 
    50      add operation the prepend has happened more than INDEX_THRESHOLD times. 
    51      This will trigger on folders larger than INDEX_THRESHOLD headers that have 
    52      never had appends nor removes of headers. 
    53  
    54      Therefore, TODO: rapidly update the index table on append and remove. ;-)  
    55  
    56      Currently, the only adder that keeps the index correct is the prepend. 
    57      The other ones will set usable_index FALSE. Hev phun .. */ 
    58  
    59   if G_UNLIKELY (self->model->usable_index) 
    60   { 
    61         /* register guint idx = nth / INDEX_OFFSET, remain = nth % INDEX_OFFSET, cidx = 0; */ 
    62         guint idx = nth >> 6, remain = nth & 0x3F, cidx = 0; 
    63         GList *start = self->model->index, *ret; 
    64  
    65         /* Math seems faster than walking a next pointer 1000ths of times */ 
    66  
    67         if G_LIKELY (idx) 
    68         { 
    69                 /* If destination is not in the beginning of the list */ 
    70  
    71                 while G_LIKELY (cidx++ < idx-1 && start) 
    72                         start = start->next; 
    73  
    74                 if G_LIKELY (start) 
    75                         ret = start->data; 
    76                 else  
    77                         ret = self->model->first; 
    78  
    79         } else  ret = self->model->first; 
    80  
    81         /* So we are now at 0 or at (50 * index), walk the remainder */ 
    82  
    83         while G_LIKELY (remain--) 
    84                 ret = ret->next; 
    85  
    86         self->current = ret; 
    87  
    88   } else { 
    89          
    90         /* First we check whether we are walking somewhere in the beginning  
    91            of the list: We know the first location, so ... (faster to start  
    92            from the first than from the current) */ 
    93  
    94  
    95         if (G_UNLIKELY (nth - cur < nth) || G_UNLIKELY (nth == 0)) 
    96         { 
    97                 self->current = self->model->first; 
    98                 cur = 0; 
    99         } 
    100  
    101         /* If nth is 0, then we are fine. Leave it then. */ 
    102         if (G_LIKELY (nth != 0)) 
    103         { 
    104  
    105                 /* If the current location is less than the destination location */ 
    106                 if G_LIKELY (cur < nth) 
    107                         while G_LIKELY (cur++ < nth) 
    108                                 self->current = self->current->next; 
    109  
    110                 /* And if not ... */ 
    111                 else if G_LIKELY (cur > nth) 
    112                         while G_LIKELY (cur-- > nth) 
    113                                 if (G_LIKELY (self->current)) 
    114                                         self->current = self->current->prev; 
    115                                 else  
    116                                 {        
    117                                         /* This is a strange case, but it means that we must  
    118                                            be at the first item */ 
    119  
    120                                         self->current = self->model->first;  
    121                                         break;  
    122                                 } 
    123         } 
    124   } 
    125  
    126   return; 
    127 } 
    12841 
    12942static guint 
     
    17790{ 
    17891        TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 
    179         gint i; gpointer ptr; 
    180         gboolean retval=FALSE; 
     92        gint i; gboolean retval=FALSE; 
    18193 
    18294        g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE); 
    18395 
    18496        g_mutex_lock (list_model->folder_lock); 
    185  
    186         /* Fill an GtkTreeIter (this is not a TnyIterator!) using a path */ 
    187  
    18897        g_static_rec_mutex_lock (list_model->iterator_lock); 
    18998 
    19099        i = gtk_tree_path_get_indices (path)[0]; 
    191100 
    192         if (G_UNLIKELY (i >= list_model->length)) 
    193         { 
     101        if (i >= list_model->items->len) { 
    194102                g_static_rec_mutex_unlock (list_model->iterator_lock); 
    195103                g_mutex_unlock (list_model->folder_lock); 
     
    197105        } 
    198106 
    199         /* We walk the iter to the nth position and we store the current postition */ 
    200         _tny_gtk_header_list_iterator_travel_to_nth_nl 
    201                 ((TnyGtkHeaderListIterator*)list_model->iterator,  
    202                 list_model->last_nth, i); 
    203  
    204         /* We will store this as user_data of the GtkTreeIter */ 
    205         /* don't unref */        
    206         ptr = _tny_gtk_header_list_iterator_get_current_nl ((TnyGtkHeaderListIterator*)list_model->iterator); 
    207         list_model->last_nth = i; 
    208         iter->stamp = list_model->stamp; 
    209         iter->user_data = ptr; 
    210         retval = (iter->user_data != NULL); 
     107        if (i >= 0 && i < list_model->items->len) { 
     108                iter->stamp = list_model->stamp; 
     109                iter->user_data = (gpointer) i; 
     110                retval = TRUE; 
     111        } 
    211112 
    212113        g_static_rec_mutex_unlock (list_model->iterator_lock); 
     
    231132        g_static_rec_mutex_lock (list_model->iterator_lock); 
    232133 
    233         while (!_tny_gtk_header_list_iterator_is_done_nl ((TnyGtkHeaderListIterator*)list_model->iterator)) 
    234         { 
    235                 /* header list iterator does not need to be unref'd */ 
    236                 if (_tny_gtk_header_list_iterator_get_current_nl ((TnyGtkHeaderListIterator*)list_model->iterator) == iter->user_data) 
    237                         break; 
    238                  
    239                 _tny_gtk_header_list_iterator_next_nl ((TnyGtkHeaderListIterator*)list_model->iterator); 
    240  
    241                 i++; 
    242         } 
    243  
    244         /* Reset the internal iterator */ 
    245         ((TnyGtkHeaderListIterator*)list_model->iterator)->current = list_model->first; 
    246         list_model->last_nth = 0; 
    247  
    248134        tree_path = gtk_tree_path_new (); 
    249         gtk_tree_path_append_index (tree_path, i); 
     135        gtk_tree_path_append_index (tree_path, (gint) iter->user_data); 
    250136 
    251137        g_static_rec_mutex_unlock (list_model->iterator_lock); 
    252  
    253138        g_mutex_unlock (list_model->folder_lock); 
    254139 
     
    288173tny_gtk_header_list_model_received_date_sort_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) 
    289174{ 
     175        TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (model); 
     176 
    290177        TnyHeader *hdr_a, *hdr_b; 
    291178        time_t recv_a, recv_b; 
    292179 
    293         hdr_a = a->user_data
    294         hdr_b = b->user_data
     180        hdr_a = list_model->items->pdata[(gint)a->user_data]
     181        hdr_b = list_model->items->pdata[(gint)b->user_data]
    295182 
    296183        recv_a = tny_header_get_date_received (hdr_a); 
     
    314201tny_gtk_header_list_model_sent_date_sort_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) 
    315202{ 
     203        TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (model); 
     204 
    316205        TnyHeader *hdr_a, *hdr_b; 
    317206        time_t recv_a, recv_b; 
    318207 
    319         hdr_a = a->user_data
    320         hdr_b = b->user_data
     208        hdr_a = list_model->items->pdata[(gint)a->user_data]
     209        hdr_b = list_model->items->pdata[(gint)b->user_data]
    321210 
    322211        recv_a = tny_header_get_date_sent (hdr_a); 
     
    334223        gchar *rdate = NULL; 
    335224 
    336         g_return_if_fail (iter->stamp == TNY_GTK_HEADER_LIST_MODEL (self)->stamp); 
    337         g_return_if_fail (iter->user_data != NULL); 
    338         g_return_if_fail (TNY_IS_HEADER (iter->user_data)); 
     225        if (iter->stamp != TNY_GTK_HEADER_LIST_MODEL (self)->stamp) 
     226                return; 
    339227 
    340228        g_mutex_lock (list_model->folder_lock); 
    341229        g_static_rec_mutex_lock (list_model->iterator_lock); 
    342230 
    343         /* Remember the ptr we've set above? Get the header instance out of the 
    344            token and return the asked-for column as a GValue instance. */ 
    345  
    346         header = iter->user_data; 
     231        header = list_model->items->pdata[(gint) iter->user_data]; 
    347232 
    348233        if (((GObject*)header)->ref_count <= 0) 
    349234        { 
     235                g_warning ("GtkTreeModel in invalid state\n"); 
    350236                g_static_rec_mutex_unlock (list_model->iterator_lock); 
    351237                g_mutex_unlock (list_model->folder_lock); 
     
    433319        gboolean retval; 
    434320        TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 
    435         gpointer ptr; 
    436  
    437         /* Move the GtkTreeIter to the next item */ 
    438  
    439         g_return_val_if_fail (iter->stamp == TNY_GTK_HEADER_LIST_MODEL  
    440                 (self)->stamp, FALSE); 
     321        gint newv; 
     322 
     323        if (iter->stamp != TNY_GTK_HEADER_LIST_MODEL (self)->stamp, FALSE) 
     324                return FALSE; 
    441325 
    442326        g_mutex_lock (list_model->folder_lock); 
    443327        g_static_rec_mutex_lock (list_model->iterator_lock); 
    444328 
    445         /* We simply move the iterator and get the value */ 
    446         _tny_gtk_header_list_iterator_next_nl ((TnyGtkHeaderListIterator*)list_model->iterator); 
    447         /* the ptr needs not to be unref'd... */ 
    448         ptr = _tny_gtk_header_list_iterator_get_current_nl ((TnyGtkHeaderListIterator*)list_model->iterator); 
    449         list_model->last_nth++; 
    450         iter->user_data = ptr; 
    451         retval = (iter->user_data != NULL); 
     329        newv = ((gint)iter->user_data); 
     330        newv++; 
     331 
     332        iter->user_data = (gpointer) newv; 
     333 
     334        retval = (((gint)iter->user_data) >=0 && ((gint)iter->user_data) < list_model->items->len); 
    452335 
    453336        g_static_rec_mutex_unlock (list_model->iterator_lock); 
     
    477360 
    478361        if (G_LIKELY (!iter)) 
    479                 retval = list_model->length
     362                retval = list_model->items->len
    480363 
    481364        g_static_rec_mutex_unlock (list_model->iterator_lock); 
     
    488371tny_gtk_header_list_model_iter_nth_child (GtkTreeModel *self, GtkTreeIter *iter, GtkTreeIter *parent, gint n) 
    489372{ 
    490         GList *child; 
    491373        TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 
    492         GList *restore
     374        gboolean retval = FALSE
    493375 
    494376        if (G_UNLIKELY (parent)) 
     
    498380        g_static_rec_mutex_lock (list_model->iterator_lock); 
    499381 
    500         restore = ((TnyGtkHeaderListIterator*)list_model->iterator)->current; 
    501         /* Move the GtkTreeIter to the nth child */ 
    502         _tny_gtk_header_list_iterator_nth_nl ((TnyGtkHeaderListIterator*)list_model->iterator, n); 
    503         /* child needs not to be unref'd */ 
    504         child = _tny_gtk_header_list_iterator_get_current_nl ((TnyGtkHeaderListIterator*)list_model->iterator); 
    505           
    506         if (G_LIKELY (child)) 
     382        if (n >= 0 && n < list_model->items->len)  
    507383        { 
    508                 list_model->last_nth = n; 
    509384                iter->stamp = TNY_GTK_HEADER_LIST_MODEL (self)->stamp; 
    510                 iter->user_data = child; 
    511  
    512                 g_static_rec_mutex_unlock (list_model->iterator_lock); 
    513                 g_mutex_unlock (list_model->folder_lock); 
    514  
    515                 return TRUE; 
     385                iter->user_data = (gpointer) n; 
     386                retval = TRUE; 
    516387        } 
    517  
    518         ((TnyGtkHeaderListIterator*)list_model->iterator)->current = restore; 
    519388 
    520389        g_static_rec_mutex_unlock (list_model->iterator_lock); 
    521390        g_mutex_unlock (list_model->folder_lock); 
    522391 
    523         return FALSE
     392        return retval
    524393} 
    525394 
     
    555424        gtk_tree_path_append_index (path, 0); 
    556425        iter.stamp = me->stamp; 
    557         iter.user_data = item
     426        iter.user_data = (gpointer) me->items->len
    558427 
    559428        /* Prepend something to the list */ 
    560429 
    561430        g_object_ref (G_OBJECT (item)); 
    562         me->first = g_list_prepend (me->first, item); 
    563         me->length++; 
    564  
    565         if G_UNLIKELY (me->length % INDEX_OFFSET == 0) 
    566                 me->index = g_list_append (me->index, me->first); 
    567  
    568         if G_UNLIKELY (!me->usable_index && me->length >= INDEX_THRESHOLD) 
    569                 me->usable_index = TRUE; 
    570  
    571         /* Reset the internal iterator */ 
    572         ((TnyGtkHeaderListIterator*)me->iterator)->current = me->first; 
    573         me->last_nth = 0; 
     431        g_ptr_array_add (me->items, item); 
    574432 
    575433        /* Letting the observers know about this (the GtkTreeView) */ 
     
    579437        g_static_rec_mutex_unlock (me->iterator_lock); 
    580438 
     439        return; 
    581440} 
    582441 
    583442static void 
    584443tny_gtk_header_list_model_append (TnyList *self, GObject* item) 
     444{ 
     445        /* Not really correct, but what the heck */ 
     446        tny_gtk_header_list_model_prepend (self, item); 
     447} 
     448 
     449static guint 
     450tny_gtk_header_list_model_get_length (TnyList *self) 
     451{ 
     452        TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*)self; 
     453        guint retval = 0; 
     454 
     455        g_static_rec_mutex_lock (me->iterator_lock); 
     456        retval = me->items->len; 
     457        g_static_rec_mutex_unlock (me->iterator_lock); 
     458 
     459        return retval; 
     460} 
     461 
     462static void 
     463tny_gtk_header_list_model_remove (TnyList *self, GObject* item) 
    585464{ 
    586465        TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*)self; 
    587466        GtkTreePath *path; 
    588467        GtkTreeIter iter; 
    589  
    590         g_static_rec_mutex_lock (me->iterator_lock); 
    591  
    592         path = gtk_tree_path_new (); 
    593         iter.stamp = me->stamp; 
    594         iter.user_data = item; 
    595  
    596         /* Append something to the list */ 
    597  
    598         g_object_ref (G_OBJECT (item)); 
    599         me->first = g_list_append (me->first, item); 
    600         me->length++; 
    601  
    602         me->usable_index = FALSE; 
    603         if (me->index) 
    604                 g_list_free (me->index); 
    605         me->index = NULL; 
    606  
    607         /* Reset the internal iterator */ 
    608         ((TnyGtkHeaderListIterator*)me->iterator)->current = me->first; 
    609         me->last_nth = 0; 
    610  
    611         /* Letting the observers know about this (the GtkTreeView) */ 
    612         gtk_tree_path_append_index (path, me->length-1); 
    613         gtk_tree_model_row_inserted (GTK_TREE_MODEL (me), path, &iter); 
    614         gtk_tree_path_free (path); 
    615  
    616         g_static_rec_mutex_unlock (me->iterator_lock); 
    617  
    618 
    619  
    620 static guint 
    621 tny_gtk_header_list_model_get_length (TnyList *self) 
    622 
    623         TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*)self; 
    624         guint retval = 0; 
    625  
    626         g_static_rec_mutex_lock (me->iterator_lock); 
    627         retval = me->first?g_list_length (me->first):0; 
    628         g_static_rec_mutex_unlock (me->iterator_lock); 
    629  
    630         return retval; 
    631 
    632  
    633 static void 
    634 tny_gtk_header_list_model_remove (TnyList *self, GObject* item) 
    635 
    636         TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*)self; 
    637         GtkTreePath *path; 
    638         GtkTreeIter iter; 
     468        gint i; gboolean found = FALSE; 
    639469 
    640470        g_return_if_fail (G_IS_OBJECT (item)); 
     
    643473        g_static_rec_mutex_lock (me->iterator_lock); 
    644474 
     475        for (i=0; i < me->items->len; i++) 
     476                if (me->items->pdata[i] == item) 
     477                { 
     478                        found = TRUE; 
     479                        break; 
     480                } 
     481 
    645482        iter.stamp = me->stamp; 
    646         iter.user_data = item; 
    647         path = tny_gtk_header_list_model_get_path (GTK_TREE_MODEL (me), &iter); 
     483        iter.user_data = (gpointer) i; 
    648484 
    649485        /* Remove something from the list */ 
    650486 
    651         me->first = g_list_remove (me->first, (gconstpointer)item); 
    652         me->length--; 
    653         me->usable_index = FALSE; 
    654         if (me->index) 
    655                 g_list_free (me->index); 
    656         me->index = NULL; 
    657  
    658         /* Reset the internal iterator */ 
    659         ((TnyGtkHeaderListIterator*)me->iterator)->current = me->first; 
    660         me->last_nth = 0; 
    661  
    662         /* Letting the observers know about this (the GtkTreeView) */ 
    663         gtk_tree_model_row_deleted (GTK_TREE_MODEL (me), path); 
    664         gtk_tree_path_free (path); 
     487        if (found) 
     488        { 
     489                path = tny_gtk_header_list_model_get_path (GTK_TREE_MODEL (me), &iter); 
     490                g_ptr_array_remove (me->items, item); 
     491                /* Letting the observers know about this (the GtkTreeView) */ 
     492                gtk_tree_model_row_deleted (GTK_TREE_MODEL (me), path); 
     493                gtk_tree_path_free (path); 
     494        } 
    665495 
    666496        g_object_unref (G_OBJECT (item)); 
    667497 
    668498        g_static_rec_mutex_unlock (me->iterator_lock); 
    669  
    670499} 
    671500 
     
    677506        /* Return a new iterator */ 
    678507 
    679         return _tny_gtk_header_list_iterator_new (me, TRUE); 
     508        return _tny_gtk_header_list_iterator_new (me); 
     509
     510 
     511static void 
     512copy_it (gpointer data, gpointer user_data) 
     513
     514        GPtrArray *items = user_data; 
     515        g_ptr_array_add (items, g_object_ref (G_OBJECT (data))); 
     516        return; 
    680517} 
    681518 
     
    696533        g_static_rec_mutex_lock (me->iterator_lock); 
    697534 
    698         GList *list_copy = g_list_copy (me->first); 
    699         g_list_foreach (list_copy, (GFunc)g_object_ref, NULL); 
    700         copy->first = list_copy; 
    701         copy->usable_index = FALSE; 
     535        GPtrArray *items_copy = g_ptr_array_sized_new (me->items->len); 
     536        g_ptr_array_foreach (me->items, copy_it, items_copy); 
     537        copy->items = items_copy; 
    702538 
    703539        g_static_rec_mutex_unlock (me->iterator_lock); 
     
    715551        g_static_rec_mutex_lock (me->iterator_lock); 
    716552 
    717         g_list_foreach (me->first, func, user_data); 
     553        g_ptr_array_foreach (me->items, func, user_data); 
    718554 
    719555        g_static_rec_mutex_unlock (me->iterator_lock); 
     
    736572} 
    737573 
    738 /* The "relaxed performers" uses g_idle to in a relax way perform a certain 
    739    function on each item in the list of headers  */ 
    740  
    741 typedef struct 
    742 { 
    743         GList *list; 
    744         GFunc relaxed_func, final_func; 
    745         gpointer ffdata, ffudata; 
    746 } RelaxedData; 
    747  
    748  
    749 static void 
    750 tny_gtk_header_list_model_relaxed_data_destroyer (gpointer data) 
    751 { 
    752         RelaxedData *d = data; 
    753  
    754         /* The destroyer */ 
    755  
    756         g_list_free (d->list); 
    757         d->list = NULL; 
    758         d->final_func (d->ffdata, d->ffudata); 
    759         g_slice_free (RelaxedData, d); 
    760  
    761         return; 
    762 } 
    763  
    764 static gboolean 
    765 tny_gtk_header_list_model_relaxed_performer (gpointer data) 
    766 { 
    767         RelaxedData *d = data; 
    768         GList *list = d->list; 
    769         gint count = 0; 
    770  
    771         /* The performer itself */ 
    772  
    773         while ((count < 5) && list) 
    774         { 
    775                 GList *element = list; 
    776                 if (element && element->data) 
    777                         d->relaxed_func (element->data, NULL); 
    778                 list = g_list_remove_link (list, element); 
    779                 g_list_free (element); 
    780                 count++; 
    781         } 
    782         d->list = list; 
    783  
    784         if (count <= 1) 
    785                 return FALSE; 
    786  
    787         return TRUE; 
    788 } 
    789  
    790  
    791 static void 
    792 proxy_destroy_func (gpointer data, gpointer user_data) 
    793 { 
    794         if (data) 
    795                 g_object_unref (G_OBJECT (data)); 
    796         data = NULL; 
    797  
    798         return; 
    799 } 
    800  
    801  
    802  
    803 static void  
    804 tny_gtk_header_list_model_hdr_cache_remover_copy (TnyGtkHeaderListModel *self, GFunc final_func, gpointer ffdata, gpointer ffudata) 
    805 { 
    806         RelaxedData *d = g_slice_new (RelaxedData); 
    807  
    808         /* This one will perform a destruction of each item in the list. It uses  
    809            a copy of the list. */ 
    810  
    811         d->relaxed_func = (GFunc)proxy_destroy_func; 
    812         d->list = g_list_copy (self->first); 
    813         d->final_func = final_func; 
    814         d->ffdata = ffdata; 
    815         d->ffudata = ffudata; 
    816  
    817         g_idle_add_full (G_PRIORITY_LOW, tny_gtk_header_list_model_relaxed_performer,  
    818                 d, tny_gtk_header_list_model_relaxed_data_destroyer); 
    819  
    820         return; 
    821 }  
    822  
    823 static void 
    824 folder_overwrite_destruction (gpointer data, gpointer udata) 
    825 { 
    826         TnyGtkHeaderListModel *self = data; 
    827  
    828         /* Unreference the folder instance */ 
    829         if (self->folder)  
    830                 g_object_unref (G_OBJECT (self->folder)); 
    831 } 
    832  
    833 typedef struct { 
    834         TnyFolder *folder; 
    835         TnyIterator *iterator; 
    836 } ToDestroy; 
    837  
    838 static void 
    839 final_destruction (gpointer data, gpointer udata) 
    840 { 
    841         ToDestroy *info = data; 
    842  
    843         /* Unreference the folder instance */ 
    844          
    845         /* Both the async added one and the final one */ 
    846  
    847         if (info->folder && G_IS_OBJECT (info->folder))  
    848         { 
    849                 g_object_unref (G_OBJECT (info->folder)); 
    850                 g_object_unref (G_OBJECT (info->folder)); 
    851         } 
    852  
    853         if (info->iterator && G_IS_OBJECT (info->iterator))  
    854         { 
    855                 g_object_unref (G_OBJECT (info->iterator)); 
    856                 g_object_unref (G_OBJECT (info->iterator)); 
    857         } 
    858  
    859         g_slice_free (ToDestroy, info); 
    860 } 
    861574 
    862575static void 
     
    864577{ 
    865578        TnyGtkHeaderListModel *self = (TnyGtkHeaderListModel *)object; 
    866         ToDestroy *info = g_slice_new (ToDestroy); 
    867579 
    868580        g_mutex_lock (self->folder_lock); 
    869581        g_static_rec_mutex_lock (self->iterator_lock); 
    870582 
     583        g_ptr_array_foreach (self->items, (GFunc)g_object_unref, NULL); 
    871584        if (self->folder) 
    872                 info->folder = g_object_ref (G_OBJECT (self->folder)); 
    873         else 
    874                 info->folder = NULL; 
    875  
    876         if (self->iterator) 
    877                 info->iterator = g_object_ref (G_OBJECT (self->iterator)); 
    878         else 
    879                 info->iterator = NULL; 
    880  
    881         self->usable_index = FALSE; 
    882  
    883         /* Reset the internal iterator */ 
    884         self->length = 0; 
    885         ((TnyGtkHeaderListIterator*)self->iterator)->current = self->first; 
    886         self->last_nth = 0; 
    887  
    888         /* Unreference the headers */ 
    889         if (self->first) 
    890         { 
    891                 /* TNY TODO: For debugging reasons disabled */ 
    892                 if (/* FALSE && */ G_LIKELY (g_main_depth () > 0)) 
    893                         tny_gtk_header_list_model_hdr_cache_remover_copy ( 
    894                                 self, final_destruction, info, NULL); 
    895                 else { 
    896                         g_list_foreach (self->first, (GFunc)g_object_unref, NULL); 
    897                         final_destruction (info, NULL); 
    898                 } 
    899                 g_list_free (self->first); 
    900                 self->first = NULL; 
    901         } else  
    902                 final_destruction (info, NULL); 
    903  
    904         if (self->index) 
    905         { 
    906                 g_list_free (self->index); 
    907                 self->index = NULL; 
    908         } 
    909  
     585                g_object_unref (G_OBJECT (self->folder)); 
     586        g_ptr_array_free (self->items, TRUE); 
     587        self->items = NULL; 
    910588 
    911589        g_static_rec_mutex_unlock (self->iterator_lock); 
     
    944622        self->iterator_lock = g_new0 (GStaticRecMutex, 1); 
    945623        g_static_rec_mutex_init (self->iterator_lock); 
    946         self->first = NULL; 
    947         self->length = 0; 
    948         self->usable_index = FALSE; 
    949  
    950         /* This is an internal iterator used by this GtkTreeModel implementation */ 
    951         self->iterator = _tny_gtk_header_list_iterator_new (self, FALSE); 
     624        self->items = g_ptr_array_sized_new (1000); 
    952625 
    953626        return; 
     
    971644 
    972645        iter.stamp = self->stamp; 
    973         iter.user_data = self->first
     646        iter.user_data = (gpointer) 0
    974647        path = tny_gtk_header_list_model_get_path (GTK_TREE_MODEL (self), &iter); 
    975648 
     
    977650        g_static_rec_mutex_lock (self->iterator_lock); 
    978651