Changeset 1708
- Timestamp:
- 03/06/07 22:31:02
- Files:
-
- trunk/ChangeLog (modified) (1 diff)
- trunk/libtinymail-camel/camel-lite/camel/providers/local/camel-maildir-summary.c (modified) (1 diff)
- trunk/libtinymailui-gtk/tny-gtk-header-list-iterator-priv.h (modified) (2 diffs)
- trunk/libtinymailui-gtk/tny-gtk-header-list-iterator.c (modified) (9 diffs)
- trunk/libtinymailui-gtk/tny-gtk-header-list-model.c (modified) (23 diffs)
- trunk/libtinymailui-gtk/tny-gtk-header-list-model.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/ChangeLog
r1700 r1708 1 2007-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 1 9 2007-03-05 Philip Van Hoof <pvanhoof@gnome.org> 2 10 trunk/libtinymail-camel/camel-lite/camel/providers/local/camel-maildir-summary.c
r1706 r1708 605 605 const char *filename; 606 606 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 609 609 camel_maildir_summary_add(cls, d->d_name, forceindex); 610 } 610 }*/ 611 611 612 612 mdi = (CamelMaildirMessageInfo *)info; trunk/libtinymailui-gtk/tny-gtk-header-list-iterator-priv.h
r906 r1708 44 44 GObject parent; 45 45 TnyGtkHeaderListModel *model; 46 GList *current;46 guint current; 47 47 }; 48 48 … … 52 52 }; 53 53 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); 54 TnyIterator* _tny_gtk_header_list_iterator_new (TnyGtkHeaderListModel *model); 56 55 57 56 gboolean _tny_gtk_header_list_iterator_is_done_nl (TnyGtkHeaderListIterator *self); trunk/libtinymailui-gtk/tny-gtk-header-list-iterator.c
r1705 r1708 30 30 31 31 32 void33 _tny_gtk_header_list_iterator_set_model (TnyGtkHeaderListIterator *self, TnyGtkHeaderListModel *model , gboolean lock)32 static void 33 _tny_gtk_header_list_iterator_set_model (TnyGtkHeaderListIterator *self, TnyGtkHeaderListModel *model) 34 34 { 35 35 self->model = model; … … 42 42 the first node in the list. */ 43 43 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; 51 45 52 46 return; … … 56 50 57 51 TnyIterator* 58 _tny_gtk_header_list_iterator_new (TnyGtkHeaderListModel *model , gboolean lock)52 _tny_gtk_header_list_iterator_new (TnyGtkHeaderListModel *model) 59 53 { 60 54 TnyGtkHeaderListIterator *self = g_object_new (TNY_TYPE_GTK_HEADER_LIST_ITERATOR, NULL); 61 55 62 _tny_gtk_header_list_iterator_set_model (self, model , lock);56 _tny_gtk_header_list_iterator_set_model (self, model); 63 57 64 58 return TNY_ITERATOR (self); … … 71 65 72 66 self->model = NULL; 73 self->current = NULL;67 self->current = 0; 74 68 75 69 return; … … 88 82 _tny_gtk_header_list_iterator_next_nl (TnyGtkHeaderListIterator *me) 89 83 { 90 me->current = me->current?g_list_next (me->current):NULL; 91 84 me->current++; 92 85 return; 93 86 } … … 98 91 TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 99 92 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 105 void 106 _tny_gtk_header_list_iterator_prev_nl (TnyGtkHeaderListIterator *me) 107 { 108 me->current--; 109 return; 110 } 111 112 static void 113 tny_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 129 gboolean 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 138 static gboolean 139 tny_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 155 void 156 _tny_gtk_header_list_iterator_first_nl (TnyGtkHeaderListIterator *me) 157 { 158 me->current = 0; 159 160 return; 161 } 162 163 static void 164 tny_gtk_header_list_iterator_first (TnyIterator *self) 165 { 166 TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; 167 100 168 if (G_UNLIKELY (!me || !me->current || !me->model)) 101 169 return; 102 170 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 111 178 112 179 void 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 186 static void 187 tny_gtk_header_list_iterator_nth (TnyIterator *self, guint nth) 122 188 { 123 189 TnyGtkHeaderListIterator *me = (TnyGtkHeaderListIterator*) self; … … 126 192 return; 127 193 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; 216 196 g_static_rec_mutex_unlock (me->model->iterator_lock); 217 197 … … 223 203 _tny_gtk_header_list_iterator_get_current_nl (TnyGtkHeaderListIterator *me) 224 204 { 225 return me-> current?me->current->data:NULL;205 return me->model->items->pdata[me->current]; 226 206 } 227 207 … … 238 218 239 219 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]; 241 221 g_static_rec_mutex_unlock (me->model->iterator_lock); 242 222 trunk/libtinymailui-gtk/tny-gtk-header-list-model.c
r1705 r1708 39 39 #include "tny-gtk-header-list-iterator-priv.h" 40 40 41 /* The function is locked, so this is secure (and might cause less42 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 only50 add operation the prepend has happened more than INDEX_THRESHOLD times.51 This will trigger on folders larger than INDEX_THRESHOLD headers that have52 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 else77 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 beginning91 of the list: We know the first location, so ... (faster to start92 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 else116 {117 /* This is a strange case, but it means that we must118 be at the first item */119 120 self->current = self->model->first;121 break;122 }123 }124 }125 126 return;127 }128 41 129 42 static guint … … 177 90 { 178 91 TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 179 gint i; gpointer ptr; 180 gboolean retval=FALSE; 92 gint i; gboolean retval=FALSE; 181 93 182 94 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE); 183 95 184 96 g_mutex_lock (list_model->folder_lock); 185 186 /* Fill an GtkTreeIter (this is not a TnyIterator!) using a path */187 188 97 g_static_rec_mutex_lock (list_model->iterator_lock); 189 98 190 99 i = gtk_tree_path_get_indices (path)[0]; 191 100 192 if (G_UNLIKELY (i >= list_model->length)) 193 { 101 if (i >= list_model->items->len) { 194 102 g_static_rec_mutex_unlock (list_model->iterator_lock); 195 103 g_mutex_unlock (list_model->folder_lock); … … 197 105 } 198 106 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 } 211 112 212 113 g_static_rec_mutex_unlock (list_model->iterator_lock); … … 231 132 g_static_rec_mutex_lock (list_model->iterator_lock); 232 133 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 248 134 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); 250 136 251 137 g_static_rec_mutex_unlock (list_model->iterator_lock); 252 253 138 g_mutex_unlock (list_model->folder_lock); 254 139 … … 288 173 tny_gtk_header_list_model_received_date_sort_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) 289 174 { 175 TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (model); 176 290 177 TnyHeader *hdr_a, *hdr_b; 291 178 time_t recv_a, recv_b; 292 179 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]; 295 182 296 183 recv_a = tny_header_get_date_received (hdr_a); … … 314 201 tny_gtk_header_list_model_sent_date_sort_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) 315 202 { 203 TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (model); 204 316 205 TnyHeader *hdr_a, *hdr_b; 317 206 time_t recv_a, recv_b; 318 207 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]; 321 210 322 211 recv_a = tny_header_get_date_sent (hdr_a); … … 334 223 gchar *rdate = NULL; 335 224 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; 339 227 340 228 g_mutex_lock (list_model->folder_lock); 341 229 g_static_rec_mutex_lock (list_model->iterator_lock); 342 230 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]; 347 232 348 233 if (((GObject*)header)->ref_count <= 0) 349 234 { 235 g_warning ("GtkTreeModel in invalid state\n"); 350 236 g_static_rec_mutex_unlock (list_model->iterator_lock); 351 237 g_mutex_unlock (list_model->folder_lock); … … 433 319 gboolean retval; 434 320 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; 441 325 442 326 g_mutex_lock (list_model->folder_lock); 443 327 g_static_rec_mutex_lock (list_model->iterator_lock); 444 328 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); 452 335 453 336 g_static_rec_mutex_unlock (list_model->iterator_lock); … … 477 360 478 361 if (G_LIKELY (!iter)) 479 retval = list_model-> length;362 retval = list_model->items->len; 480 363 481 364 g_static_rec_mutex_unlock (list_model->iterator_lock); … … 488 371 tny_gtk_header_list_model_iter_nth_child (GtkTreeModel *self, GtkTreeIter *iter, GtkTreeIter *parent, gint n) 489 372 { 490 GList *child;491 373 TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 492 GList *restore;374 gboolean retval = FALSE; 493 375 494 376 if (G_UNLIKELY (parent)) … … 498 380 g_static_rec_mutex_lock (list_model->iterator_lock); 499 381 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) 507 383 { 508 list_model->last_nth = n;509 384 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; 516 387 } 517 518 ((TnyGtkHeaderListIterator*)list_model->iterator)->current = restore;519 388 520 389 g_static_rec_mutex_unlock (list_model->iterator_lock); 521 390 g_mutex_unlock (list_model->folder_lock); 522 391 523 return FALSE;392 return retval; 524 393 } 525 394 … … 555 424 gtk_tree_path_append_index (path, 0); 556 425 iter.stamp = me->stamp; 557 iter.user_data = item;426 iter.user_data = (gpointer) me->items->len; 558 427 559 428 /* Prepend something to the list */ 560 429 561 430 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); 574 432 575 433 /* Letting the observers know about this (the GtkTreeView) */ … … 579 437 g_static_rec_mutex_unlock (me->iterator_lock); 580 438 439 return; 581 440 } 582 441 583 442 static void 584 443 tny_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 449 static guint 450 tny_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 462 static void 463 tny_gtk_header_list_model_remove (TnyList *self, GObject* item) 585 464 { 586 465 TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*)self; 587 466 GtkTreePath *path; 588 467 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; 639 469 640 470 g_return_if_fail (G_IS_OBJECT (item)); … … 643 473 g_static_rec_mutex_lock (me->iterator_lock); 644 474 475 for (i=0; i < me->items->len; i++) 476 if (me->items->pdata[i] == item) 477 { 478 found = TRUE; 479 break; 480 } 481 645 482 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; 648 484 649 485 /* Remove something from the list */ 650 486 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 } 665 495 666 496 g_object_unref (G_OBJECT (item)); 667 497 668 498 g_static_rec_mutex_unlock (me->iterator_lock); 669 670 499 } 671 500 … … 677 506 /* Return a new iterator */ 678 507 679 return _tny_gtk_header_list_iterator_new (me, TRUE); 508 return _tny_gtk_header_list_iterator_new (me); 509 } 510 511 static void 512 copy_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; 680 517 } 681 518 … … 696 533 g_static_rec_mutex_lock (me->iterator_lock); 697 534 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; 702 538 703 539 g_static_rec_mutex_unlock (me->iterator_lock); … … 715 551 g_static_rec_mutex_lock (me->iterator_lock); 716 552 717 g_ list_foreach (me->first, func, user_data);553 g_ptr_array_foreach (me->items, func, user_data); 718 554 719 555 g_static_rec_mutex_unlock (me->iterator_lock); … … 736 572 } 737 573 738 /* The "relaxed performers" uses g_idle to in a relax way perform a certain739 function on each item in the list of headers */740 741 typedef struct742 {743 GList *list;744 GFunc relaxed_func, final_func;745 gpointer ffdata, ffudata;746 } RelaxedData;747 748 749 static void750 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 gboolean765 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 void792 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 void804 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 uses809 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 void824 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 void839 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 }861 574 862 575 static void … … 864 577 { 865 578 TnyGtkHeaderListModel *self = (TnyGtkHeaderListModel *)object; 866 ToDestroy *info = g_slice_new (ToDestroy);867 579 868 580 g_mutex_lock (self->folder_lock); 869 581 g_static_rec_mutex_lock (self->iterator_lock); 870 582 583 g_ptr_array_foreach (self->items, (GFunc)g_object_unref, NULL); 871 584 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; 910 588 911 589 g_static_rec_mutex_unlock (self->iterator_lock); … … 944 622 self->iterator_lock = g_new0 (GStaticRecMutex, 1); 945 623 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); 952 625 953 626 return; … … 971 644 972 645 iter.stamp = self->stamp; 973 iter.user_data = self->first;646 iter.user_data = (gpointer) 0; 974 647 path = tny_gtk_header_list_model_get_path (GTK_TREE_MODEL (self), &iter); 975 648 … … 977 650 g_static_rec_mutex_lock (self->iterator_lock); 978 651
