summaryrefslogtreecommitdiff
path: root/src/lib/elementary
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-02-21 21:48:11 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-02-22 14:46:28 +0900
commitfe6bdf30cdf3e21cc3c17ea7546eca3cc5e2c6cb (patch)
tree5625aa2aeb06dc6f38cf8975cf29befb14ff7298 /src/lib/elementary
parent75f772c898fcf91c947691e40b5dde86888a7889 (diff)
genlist: Fix sorted_insert with tree
This fixes the test case "Genlist Tree, Insert Sorted". This is a pretty ugly patch... but the genlist code is already pretty ugly, as it keeps a flat inlist of items (sd->items) as well as a tree structure in parallel. Before this patch, the following configuration led to issues: 1 3 - A - B Adding item "2" led to a crash. Adding item 4 led to this: 1 3 4 - A - B Items A and B lost their parent "3". Subsequent sorted inserts would lead to insane bahaviour, where for instance "8" would appear before "3". This patch fixes all sorted inserts, at the cost of performance (an optimized code path is avoided). Subsequent patches will increase the robustness of the tree structure. NOTE: This is a behaviour break! Fixes T4850
Diffstat (limited to 'src/lib/elementary')
-rw-r--r--src/lib/elementary/elm_genlist.c87
-rw-r--r--src/lib/elementary/elm_widget_genlist.h1
2 files changed, 68 insertions, 20 deletions
diff --git a/src/lib/elementary/elm_genlist.c b/src/lib/elementary/elm_genlist.c
index 8b6ef4e07c..a04edbbd80 100644
--- a/src/lib/elementary/elm_genlist.c
+++ b/src/lib/elementary/elm_genlist.c
@@ -6419,9 +6419,11 @@ _elm_genlist_item_insert_before(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist
6419EOLIAN static Elm_Object_Item* 6419EOLIAN static Elm_Object_Item*
6420_elm_genlist_item_sorted_insert(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Genlist_Item_Type type, Eina_Compare_Cb comp, Evas_Smart_Cb func, const void *func_data) 6420_elm_genlist_item_sorted_insert(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *eo_parent, Elm_Genlist_Item_Type type, Eina_Compare_Cb comp, Evas_Smart_Cb func, const void *func_data)
6421{ 6421{
6422 Elm_Object_Item *eo_rel = NULL;
6422 Elm_Gen_Item *rel = NULL; 6423 Elm_Gen_Item *rel = NULL;
6423 Elm_Gen_Item *it; 6424 Elm_Gen_Item *it;
6424 6425
6426 EINA_SAFETY_ON_NULL_RETURN_VAL(comp, NULL);
6425 if (eo_parent) 6427 if (eo_parent)
6426 { 6428 {
6427 ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent); 6429 ELM_GENLIST_ITEM_DATA_GET(eo_parent, parent);
@@ -6438,8 +6440,7 @@ _elm_genlist_item_sorted_insert(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist
6438 6440
6439 if (it->parent) 6441 if (it->parent)
6440 { 6442 {
6441 Elm_Object_Item *eo_rel = NULL; 6443 Eina_List *l;
6442 Eina_List *l, *last;
6443 int cmp_result; 6444 int cmp_result;
6444 6445
6445 l = eina_list_search_sorted_near_list 6446 l = eina_list_search_sorted_near_list
@@ -6465,8 +6466,7 @@ _elm_genlist_item_sorted_insert(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist
6465 (it->parent->item->items, eo_it, l); 6466 (it->parent->item->items, eo_it, l);
6466 if (rel->item->items && rel->item->expanded) 6467 if (rel->item->items && rel->item->expanded)
6467 { 6468 {
6468 last = eina_list_last(rel->item->items); 6469 eo_rel = eina_list_last_data_get(rel->item->items);
6469 eo_rel = eina_list_data_get(last);
6470 rel = efl_data_scope_get(eo_rel, ELM_GENLIST_ITEM_CLASS); 6470 rel = efl_data_scope_get(eo_rel, ELM_GENLIST_ITEM_CLASS);
6471 } 6471 }
6472 sd->items = eina_inlist_append_relative 6472 sd->items = eina_inlist_append_relative
@@ -6478,17 +6478,20 @@ _elm_genlist_item_sorted_insert(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist
6478 { 6478 {
6479 rel = it->parent; 6479 rel = it->parent;
6480 6480
6481 // ignoring the comparison 6481 it->parent->item->items = eina_list_prepend
6482 it->parent->item->items = eina_list_prepend_relative_list 6482 (it->parent->item->items, eo_it);
6483 (it->parent->item->items, eo_it, l); 6483 sd->items = eina_inlist_append_relative
6484 sd->items = eina_inlist_prepend_relative 6484 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6485 (sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6486 it->item->before = EINA_FALSE; 6485 it->item->before = EINA_FALSE;
6486 it->parent->item->expanded = EINA_TRUE;
6487 } 6487 }
6488
6489 sd->has_tree_items = EINA_TRUE;
6490 ELM_SAFE_FREE(sd->state, eina_inlist_sorted_state_free);
6488 } 6491 }
6489 else 6492 else
6490 { 6493 {
6491 if (!sd->state) 6494 if (!sd->state && !sd->has_tree_items)
6492 { 6495 {
6493 sd->state = eina_inlist_sorted_state_new(); 6496 sd->state = eina_inlist_sorted_state_new();
6494 eina_inlist_sorted_state_init(sd->state, sd->items); 6497 eina_inlist_sorted_state_init(sd->state, sd->items);
@@ -6498,19 +6501,63 @@ _elm_genlist_item_sorted_insert(Eo *obj, Elm_Genlist_Data *sd, const Elm_Genlist
6498 if (GL_IT(it)->type == ELM_GENLIST_ITEM_GROUP) 6501 if (GL_IT(it)->type == ELM_GENLIST_ITEM_GROUP)
6499 sd->group_items = eina_list_append(sd->group_items, it); 6502 sd->group_items = eina_list_append(sd->group_items, it);
6500 6503
6501 sd->items = eina_inlist_sorted_state_insert 6504 if (!sd->items) sd->has_tree_items = EINA_FALSE;
6502 (sd->items, EINA_INLIST_GET(it), _elm_genlist_item_compare, 6505 if (!sd->has_tree_items)
6503 sd->state);
6504
6505 if (EINA_INLIST_GET(it)->next)
6506 { 6506 {
6507 rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next); 6507 sd->items = eina_inlist_sorted_state_insert
6508 it->item->before = EINA_TRUE; 6508 (sd->items, EINA_INLIST_GET(it), _elm_genlist_item_compare,
6509 sd->state);
6510
6511 if (EINA_INLIST_GET(it)->next)
6512 {
6513 rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
6514 it->item->before = EINA_TRUE;
6515 }
6516 else if (EINA_INLIST_GET(it)->prev)
6517 {
6518 rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
6519 it->item->before = EINA_FALSE;
6520 }
6509 } 6521 }
6510 else if (EINA_INLIST_GET(it)->prev) 6522 else
6511 { 6523 {
6512 rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev); 6524 // Inlist is not sorted!
6513 it->item->before = EINA_FALSE; 6525 Elm_Gen_Item *prev_rel = NULL;
6526 int cmp;
6527
6528 EINA_INLIST_FOREACH(sd->items, rel)
6529 {
6530 cmp = comp(EO_OBJ(it), EO_OBJ(rel));
6531 if (cmp < 0) break;
6532 prev_rel = rel;
6533 if (rel->item->items && rel->item->expanded)
6534 {
6535 eo_rel = eina_list_last_data_get(rel->item->items);
6536 rel = efl_data_scope_get(eo_rel, ELM_GENLIST_ITEM_CLASS);
6537 }
6538 if (!EINA_INLIST_GET(rel)->next)
6539 {
6540 cmp = 1;
6541 break;
6542 }
6543 }
6544
6545 if (!rel)
6546 {
6547 sd->items = eina_inlist_prepend_relative(sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(prev_rel));
6548 it->item->before = EINA_TRUE;
6549 rel = prev_rel;
6550 }
6551 else if (cmp >= 0)
6552 {
6553 sd->items = eina_inlist_append_relative(sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6554 it->item->before = EINA_FALSE;
6555 }
6556 else
6557 {
6558 sd->items = eina_inlist_prepend_relative(sd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
6559 it->item->before = EINA_TRUE;
6560 }
6514 } 6561 }
6515 } 6562 }
6516 6563
diff --git a/src/lib/elementary/elm_widget_genlist.h b/src/lib/elementary/elm_widget_genlist.h
index f0cc097411..fbc9695673 100644
--- a/src/lib/elementary/elm_widget_genlist.h
+++ b/src/lib/elementary/elm_widget_genlist.h
@@ -200,6 +200,7 @@ struct _Elm_Genlist_Data
200 Eina_Bool item_looping_on : 1; 200 Eina_Bool item_looping_on : 1;
201 201
202 Eina_Bool tree_effect_animator : 1; 202 Eina_Bool tree_effect_animator : 1;
203 Eina_Bool has_tree_items : 1; // FIXME: count up & down
203}; 204};
204 205
205typedef struct _Item_Block Item_Block; 206typedef struct _Item_Block Item_Block;