Changeset 1905
- Timestamp:
- 05/08/07 00:19:36
- Files:
-
- trunk/ChangeLog (modified) (1 diff)
- trunk/libtinymailui-gtk/tny-gtk-header-list-model.c (modified) (19 diffs)
- trunk/libtinymailui-gtk/tny-gtk-header-list-model.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/ChangeLog
r1898 r1905 1 2007-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 1 12 2007-05-07 Philip Van Hoof <pvanhoof@gnome.org> 2 13 trunk/libtinymailui-gtk/tny-gtk-header-list-model.c
r1904 r1905 90 90 { 91 91 TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 92 gint i ; gboolean retval=FALSE;92 gint i, tlen; gboolean retval=FALSE; 93 93 94 94 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE); … … 98 98 i = gtk_tree_path_get_indices (path)[0]; 99 99 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 } 109 112 } 110 113 … … 118 121 { 119 122 GtkTreePath *tree_path; 120 gint i = 0 ;123 gint i = 0, tlen; 121 124 TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 122 125 … … 129 132 i = (gint) iter->user_data; 130 133 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) { 132 139 g_static_rec_mutex_unlock (list_model->iterator_lock); 133 140 return NULL; … … 135 142 136 143 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); 138 145 139 146 g_static_rec_mutex_unlock (list_model->iterator_lock); … … 230 237 const gchar *str; 231 238 gchar *rdate = NULL; 232 int i;239 gint i; 233 240 234 241 if (iter->stamp != TNY_GTK_HEADER_LIST_MODEL (self)->stamp) … … 243 250 i = (gint) iter->user_data; 244 251 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) */ 245 255 if (i < 0 || i >= list_model->items->len) 246 256 { … … 345 355 iter->user_data = (gpointer) newv; 346 356 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); 348 360 349 361 if (!retval) { … … 379 391 380 392 if (G_LIKELY (!iter)) 381 retval = list_model->cur_len; /* list_model->items->len; */393 retval = list_model->cur_len; 382 394 383 395 g_static_rec_mutex_unlock (list_model->iterator_lock); … … 391 403 TnyGtkHeaderListModel *list_model = TNY_GTK_HEADER_LIST_MODEL (self); 392 404 gboolean retval = FALSE; 405 gint tlen; 393 406 394 407 if (G_UNLIKELY (parent)) … … 397 410 g_static_rec_mutex_lock (list_model->iterator_lock); 398 411 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) 400 417 { 401 418 iter->stamp = TNY_GTK_HEADER_LIST_MODEL (self)->stamp; … … 431 448 432 449 433 typedef struct 434 { 435 TnyGtkHeaderListModel *self; 450 static void 451 notify_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 465 static gboolean 466 notify_views_add (gpointer data) 467 { 468 TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*) data; 469 gint already_registered, going_tb_registered, i; 470 471 gboolean needmore = FALSE; 436 472 GtkTreePath *path; 437 473 GtkTreeIter iter; 438 } notify_views_data_t;439 440 441 static void442 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 gboolean458 notify_views_add (gpointer data)459 {460 TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*) data;461 gint updated, going_to_update, i, added;462 gboolean needmore = FALSE;463 474 464 475 g_mutex_lock (me->ra_lock); 465 476 me->updating_views++; 466 if (me->re cent_updated >= me->items->len) {477 if (me->registered >= me->items->len) { 467 478 g_mutex_unlock (me->ra_lock); 468 479 return FALSE; 469 480 } 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; 473 487 needmore = TRUE; 474 } else 475 going_t o_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; 478 492 479 493 if (me->updating_views < 2) 480 494 needmore = TRUE; 481 495 496 g_mutex_unlock (me->ra_lock); 497 482 498 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++) 486 501 { 487 GtkTreeIter iter;488 GtkTreePath *path;502 iter.stamp = me->stamp; 503 iter.user_data = (gpointer) i; 489 504 path = gtk_tree_path_new (); 490 505 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 } 499 512 } 500 513 gdk_threads_leave(); … … 502 515 return needmore; 503 516 } 517 518 504 519 505 520 /* This will be called often while you are in tny_folder_refresh(_async). It can … … 510 525 { 511 526 TnyGtkHeaderListModel *me = (TnyGtkHeaderListModel*)self; 512 gint depth = g_main_depth ();513 527 g_static_rec_mutex_lock (me->iterator_lock); 514 528 … … 555 569 556 570 571 typedef struct 572 { 573 TnyGtkHeaderListModel *self; 574 GObject *item; 575 } notify_views_data_t; 576 577 578 static void 579 notify_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 557 588 558 589 static gboolean … … 560 591 { 561 592 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; 589 599 590 600 for (i=0; i < me->items->len; i++) … … 595 605 } 596 606 597 /* Remove something from the list */598 599 607 if (found) 600 608 { 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 630 static void 631 tny_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; 614 640 } 615 641 … … 759 785 self->updating_views = -1; 760 786 self->ra_lock = g_mutex_new (); 761 self->re cent_updated = 0;787 self->registered = 0; 762 788 763 789 return; … … 787 813 } 788 814 789 self->recent_updated = 0;790 791 815 /* Set it to 1 as initial value, else you cause the length > 0 792 816 * assertion in gtk_tree_model_sort_build_level (I have no idea why the 793 817 * assertion is placed there, in stead of a normal return, though) */ 794 818 795 self->cur_len = 1;796 797 819 g_ptr_array_foreach (self->items, (GFunc)g_object_unref, NULL); 798 820 if (self->folder) trunk/libtinymailui-gtk/tny-gtk-header-list-model.h
r1904 r1905 66 66 GStaticRecMutex *iterator_lock; 67 67 TnyFolder *folder; 68 gint stamp, re cent_updated;68 gint stamp, registered; 69 69 gint updating_views; 70 70 GMutex *ra_lock;
