On Thu, Apr 18, 2013 at 1:20 AM, Rafael Antognolli <[email protected]>wrote:
> On Wed, Apr 17, 2013 at 1:03 PM, Daniel Juyung Seo <[email protected]> > wrote: > > This patch broke at least two stuffs: > > > > 1. item movement with key arrow > > now up/down arrow scrolls genlist now move to upper/lower item. > > > > 2. item del routine. > > item del callbacks are called twice LOL. > > this also broke apps that use elm_fileselector_button which uses > > elm_genlist internally. > > > > Please fix them as soon as possible. > > This is very serious. > > Revert until fixed? > Well, yes. I just reverted this because it looks like TaeHwan Kim is away for a couple of days. Daniel Juyung Seo (SeoZ) > > > On Mon, Apr 15, 2013 at 12:00 PM, Tae-Hwan Kim - Enlightenment Git < > > [email protected]> wrote: > > > >> raster pushed a commit to branch master. > >> > >> commit cea8e755dbf9b062bb1e6d7a89fbf4c590b8f6b3 > >> Author: Tae-Hwan Kim <[email protected]> > >> Date: Mon Apr 15 12:00:43 2013 +0900 > >> > >> I removed it->generation, sd->generation, it->walking, sd->walking > >> flags. > >> This flags was used for deferring deletion of genlist items. > >> After deferred, items can be cleanup when _item_select() is called. > >> This flags was used for preventing crash when subitems are deleted > >> right > >> after one item is deleted. > >> > >> But this made genlist code too complicated and could hide internal > >> issues. One of the issues is incorrect use of EINA_INSTLIST_FOREACH > (or > >> forloop). Because sub items can be deleted when one item is > deleted, I > >> used whlie loop and EINA_INLIST_CONTAINER_GET(sd->items->last, xx) > and > >> not defer the deletion. This has no problem evenif inlist sd->items > is > >> changed inside the while-loop. > >> --- > >> src/lib/elm_genlist.c | 171 > >> +++++++++++++------------------------------ > >> src/lib/elm_widget_genlist.h | 5 -- > >> 2 files changed, 50 insertions(+), 126 deletions(-) > >> > >> diff --git a/src/lib/elm_genlist.c b/src/lib/elm_genlist.c > >> index d9317c3..44f1e90 100644 > >> --- a/src/lib/elm_genlist.c > >> +++ b/src/lib/elm_genlist.c > >> @@ -1075,8 +1075,7 @@ _decorate_all_item_realize(Elm_Gen_Item *it, > >> const char *stacking; > >> const char *stacking_even; > >> > >> - if ((!it) || (it->item->decorate_all_item_realized) || > >> - (it->generation < GL_IT(it)->wsd->generation)) > >> + if ((!it) || (it->item->decorate_all_item_realized)) > >> return; > >> > >> it->deco_all_view = > edje_object_add(evas_object_evas_get(WIDGET(it))); > >> @@ -1466,7 +1465,6 @@ _item_realize(Elm_Gen_Item *it, > >> char buf[1024]; > >> int tsize = 20; > >> > >> - if (it->generation < GL_IT(it)->wsd->generation) return; > >> if (it->realized) > >> { > >> if (it->item->order_num_in != in) > >> @@ -1988,8 +1986,7 @@ _item_block_position(Item_Block *itb, > >> > >> EINA_LIST_FOREACH(itb->items, l, it) > >> { > >> - if (it->generation < GL_IT(it)->wsd->generation) continue; > >> - else if (GL_IT(it)->wsd->reorder_it == it) > >> + if (GL_IT(it)->wsd->reorder_it == it) > >> continue; > >> > >> it->x = 0; > >> @@ -2287,7 +2284,7 @@ _item_single_select_up(Elm_Genlist_Smart_Data *sd) > >> if (!sd->selected) > >> { > >> prev = ELM_GEN_ITEM_FROM_INLIST(sd->items->last); > >> - while ((prev) && (prev->generation < sd->generation)) > >> + while (prev) > >> prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev); > >> } > >> else > >> @@ -2311,7 +2308,7 @@ _item_single_select_down(Elm_Genlist_Smart_Data > *sd) > >> if (!sd->selected) > >> { > >> next = ELM_GEN_ITEM_FROM_INLIST(sd->items); > >> - while ((next) && (next->generation < sd->generation)) > >> + while (next) > >> next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next); > >> } > >> else > >> @@ -2695,7 +2692,6 @@ _item_highlight(Elm_Gen_Item *it) > >> > >> if ((GL_IT(it)->wsd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || > >> (!GL_IT(it)->wsd->highlight) || > >> - (it->generation < GL_IT(it)->wsd->generation) || > >> (it->highlighted) || elm_widget_item_disabled_get(it) || > >> (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || > >> (it->item->deco_it_view) || > >> @@ -2721,7 +2717,7 @@ _item_highlight(Elm_Gen_Item *it) > >> static void > >> _item_unhighlight(Elm_Gen_Item *it) > >> { > >> - if ((it->generation < GL_IT(it)->wsd->generation) || > >> (!it->highlighted)) > >> + if (!it->highlighted) > >> return; > >> > >> edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm"); > >> @@ -2913,11 +2909,6 @@ static void > >> _elm_genlist_item_del_not_serious(Elm_Gen_Item *it) > >> { > >> elm_widget_item_pre_notify_del(it); > >> - it->generation = GL_IT(it)->wsd->generation - 1; /* This means that > >> - * the item is > >> - * deleted */ > >> - > >> - if (it->walking > 0) return; > >> > >> if (it->selected) > >> GL_IT(it)->wsd->selected = > >> @@ -2936,7 +2927,6 @@ _elm_genlist_item_del_serious(Elm_Gen_Item *it) > >> eina_inlist_remove(GL_IT(it)->wsd->items, EINA_INLIST_GET(it)); > >> if (it->tooltip.del_cb) > >> it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it); > >> - GL_IT(it)->wsd->walking -= it->walking; > >> if (it->long_timer) > >> { > >> ecore_timer_del(it->long_timer); > >> @@ -3013,7 +3003,6 @@ _item_del(Elm_Gen_Item *it) > >> static void > >> _item_unselect(Elm_Gen_Item *it) > >> { > >> - if ((it->generation < GL_IT(it)->wsd->generation)) return; > >> _item_unhighlight(it); /* unhighlight the item first */ > >> if (!it->selected) return; /* then check whether the item is > selected > >> */ > >> > >> @@ -4237,8 +4226,7 @@ _decorate_item_finished_signal_cb(void *data, > >> > >> te = evas_object_evas_get(obj); > >> > >> - if ((it->generation < GL_IT(it)->wsd->generation) || (!it->realized) > >> - || (!it->item->deco_it_view)) return; > >> + if ((!it->realized) || (!it->item->deco_it_view)) return; > >> > >> evas_event_freeze(te); > >> it->item->nocache_once = EINA_FALSE; > >> @@ -4375,7 +4363,6 @@ _item_block_recalc(Item_Block *itb, > >> itb->num = in; > >> EINA_LIST_FOREACH(itb->items, l, it) > >> { > >> - if (it->generation < GL_IT(it)->wsd->generation) continue; > >> show_me |= it->item->show_me; > >> if (!itb->realized) > >> { > >> @@ -4609,8 +4596,7 @@ _decorate_item_realize(Elm_Gen_Item *it) > >> char buf[1024]; > >> Evas_Object *obj = (GL_IT(it)->wsd)->obj; > >> > >> - if ((it->item->deco_it_view) || (it->generation < > >> - GL_IT(it)->wsd->generation)) > return; > >> + if (it->item->deco_it_view) return; > >> > >> evas_event_freeze(evas_object_evas_get(obj)); > >> it->item->deco_it_view = > >> edje_object_add(evas_object_evas_get(WIDGET(it))); > >> @@ -4750,8 +4736,6 @@ _elm_genlist_smart_add(Eo *obj, void *_pd, va_list > >> *list EINA_UNUSED) > >> elm_widget_can_focus_set(obj, EINA_TRUE); > >> elm_widget_on_show_region_hook_set(obj, _show_region_hook, NULL); > >> > >> - priv->generation = 1; > >> - > >> if (!elm_layout_theme_set > >> (obj, "genlist", "base", elm_widget_style_get(obj))) > >> CRITICAL("Failed to set layout!"); > >> @@ -4943,46 +4927,27 @@ _clear(Elm_Genlist_Smart_Data *sd) > >> } > >> > >> static void > >> -_elm_genlist_clear(Evas_Object *obj, > >> - Eina_Bool standby) > >> +_elm_genlist_clear(Evas_Object *obj) > >> { > >> - Eina_Inlist *next, *l; > >> + Elm_Gen_Item *it; > >> > >> ELM_GENLIST_DATA_GET(obj, sd); > >> > >> - if (!standby) sd->generation++; > >> - > >> if (sd->state) > >> { > >> eina_inlist_sorted_state_free(sd->state); > >> sd->state = NULL; > >> } > >> > >> - if (sd->walking > 0) > >> - { > >> - sd->clear_me = EINA_TRUE; > >> - return; > >> - } > >> - > >> evas_event_freeze(evas_object_evas_get(sd->obj)); > >> - for (l = sd->items, next = l ? l->next : NULL; > >> - l; > >> - l = next, next = next ? next->next : NULL) > >> + // Do not use EINA_INLIST_FOREACH or EINA_INLIST_FOREACH_SAFE > >> + // because sd->items can be modified inside elm_widget_item_del() > >> + while (sd->items) > >> { > >> - Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l); > >> - > >> - if (it->generation < sd->generation) > >> - { > >> - Elm_Gen_Item *itn = NULL; > >> - > >> - if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next); > >> - if (itn) itn->walking++; /* prevent early death of > subitem > >> */ > >> - it->del_cb(it); > >> - elm_widget_item_free(it); > >> - if (itn) itn->walking--; > >> - } > >> + it = EINA_INLIST_CONTAINER_GET(sd->items->last, Elm_Gen_Item); > >> + it->item->nocache_once = EINA_TRUE; > >> + elm_widget_item_del(it); > >> } > >> - sd->clear_me = EINA_FALSE; > >> sd->pan_changed = EINA_TRUE; > >> if (!sd->queue) > >> { > >> @@ -5017,8 +4982,7 @@ _item_select(Elm_Gen_Item *it) > >> { > >> Evas_Object *obj = WIDGET(it); > >> > >> - if ((it->generation < GL_IT(it)->wsd->generation) || > >> - (it->decorate_it_set) || > >> + if ((it->decorate_it_set) || > >> (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || > >> (GL_IT(it)->wsd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) > >> return; > >> @@ -5033,26 +4997,8 @@ _item_select(Elm_Gen_Item *it) > >> return; > >> > >> evas_object_ref(obj); > >> - it->walking++; > >> - GL_IT(it)->wsd->walking++; > >> if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), > >> it); > >> - if (it->generation == GL_IT(it)->wsd->generation) > >> - evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it); > >> - > >> - it->walking--; > >> - GL_IT(it)->wsd->walking--; > >> - if ((GL_IT(it)->wsd->clear_me) && (!GL_IT(it)->wsd->walking)) > >> - _elm_genlist_clear(WIDGET(it), EINA_TRUE); > >> - else > >> - { > >> - if ((!it->walking) && (it->generation < > >> GL_IT(it)->wsd->generation)) > >> - { > >> - it->del_cb(it); > >> - elm_widget_item_free(it); > >> - } > >> - else > >> - GL_IT(it)->wsd->last_selected_item = (Elm_Object_Item *)it; > >> - } > >> + evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it); > >> evas_object_unref(obj); > >> } > >> > >> @@ -5092,8 +5038,6 @@ _item_disable_hook(Elm_Object_Item *item) > >> Evas_Object *obj; > >> Elm_Gen_Item *it = (Elm_Gen_Item *)item; > >> > >> - if (it->generation < GL_IT(it)->wsd->generation) return; > >> - > >> if (it->selected) > >> elm_genlist_item_selected_set(item, EINA_FALSE); > >> > >> @@ -5123,38 +5067,33 @@ _item_del_pre_hook(Elm_Object_Item *item) > >> { > >> Elm_Gen_Item *it = (Elm_Gen_Item *)item; > >> > >> - if (it->walking > 0) > >> + // FIXME: relative will be better to be fixed. it is too harsh. > >> + if (it->item->rel) > >> + it->item->rel->item->rel_revs = > >> + eina_list_remove(it->item->rel->item->rel_revs, it); > >> + if (it->item->rel_revs) > >> + { > >> + Elm_Gen_Item *tmp; > >> + EINA_LIST_FREE(it->item->rel_revs, tmp) tmp->item->rel = NULL; > >> + } > >> + elm_genlist_item_subitems_clear(item); > >> + if (GL_IT(it)->wsd->show_item == it) > >> + GL_IT(it)->wsd->show_item = NULL; > >> + _elm_genlist_item_del_not_serious(it); > >> + if (it->item->block) > >> { > >> - // FIXME: relative will be better to be fixed. it is too harsh. > >> - if (it->item->rel) > >> - it->item->rel->item->rel_revs = > >> - eina_list_remove(it->item->rel->item->rel_revs, it); > >> - if (it->item->rel_revs) > >> - { > >> - Elm_Gen_Item *tmp; > >> - EINA_LIST_FREE(it->item->rel_revs, tmp) tmp->item->rel = > NULL; > >> - } > >> - elm_genlist_item_subitems_clear(item); > >> - if (GL_IT(it)->wsd->show_item == it) > >> - GL_IT(it)->wsd->show_item = NULL; > >> - > >> - _elm_genlist_item_del_not_serious(it); > >> - if (it->item->block) > >> - { > >> - if (it->realized) _elm_genlist_item_unrealize(it, > >> EINA_FALSE); > >> - it->item->block->changed = EINA_TRUE; > >> - if (GL_IT(it)->wsd->calc_job) > >> - ecore_job_del(GL_IT(it)->wsd->calc_job); > >> - GL_IT(it)->wsd->calc_job = > >> - ecore_job_add(_calc_job, GL_IT(it)->wsd); > >> - } > >> - if (it->parent) > >> - { > >> - it->parent->item->items = > >> - eina_list_remove(it->parent->item->items, it); > >> - it->parent = NULL; > >> - } > >> - return EINA_FALSE; > >> + if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE); > >> + it->item->block->changed = EINA_TRUE; > >> + if (GL_IT(it)->wsd->calc_job) > >> + ecore_job_del(GL_IT(it)->wsd->calc_job); > >> + GL_IT(it)->wsd->calc_job = > >> + ecore_job_add(_calc_job, GL_IT(it)->wsd); > >> + } > >> + if (it->parent) > >> + { > >> + it->parent->item->items = > >> + eina_list_remove(it->parent->item->items, it); > >> + it->parent = NULL; > >> } > >> > >> _item_del(it); > >> @@ -5186,7 +5125,6 @@ _elm_genlist_item_new(Elm_Genlist_Smart_Data *sd, > >> it = elm_widget_item_new(sd->obj, Elm_Gen_Item); > >> if (!it) return NULL; > >> > >> - it->generation = sd->generation; > >> it->itc = itc; > >> elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc); > >> > >> @@ -5641,7 +5579,7 @@ elm_genlist_clear(Evas_Object *obj) > >> static void > >> _clear_eo(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED) > >> { > >> - _elm_genlist_clear(obj, EINA_FALSE); > >> + _elm_genlist_clear(obj); > >> } > >> > >> EAPI void > >> @@ -5846,7 +5784,7 @@ _first_item_get(Eo *obj EINA_UNUSED, void *_pd, > >> va_list *list) > >> if (!sd->items) return; > >> > >> it = ELM_GEN_ITEM_FROM_INLIST(sd->items); > >> - while ((it) && (it->generation < sd->generation)) > >> + while (it) > >> it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next); > >> > >> *ret = (Elm_Object_Item *)it; > >> @@ -5874,7 +5812,7 @@ _last_item_get(Eo *obj EINA_UNUSED, void *_pd, > >> va_list *list) > >> if (!sd->items) return; > >> > >> it = ELM_GEN_ITEM_FROM_INLIST(sd->items->last); > >> - while ((it) && (it->generation < sd->generation)) > >> + while (it) > >> it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev); > >> > >> *ret = (Elm_Object_Item *)it; > >> @@ -5891,7 +5829,7 @@ elm_genlist_item_next_get(const Elm_Object_Item > >> *item) > >> while (it) > >> { > >> it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next); > >> - if ((it) && (it->generation == GL_IT(it)->wsd->generation)) > break; > >> + if (it) break; > >> } > >> > >> return (Elm_Object_Item *)it; > >> @@ -5908,7 +5846,7 @@ elm_genlist_item_prev_get(const Elm_Object_Item > >> *item) > >> while (it) > >> { > >> it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev); > >> - if ((it) && (it->generation == GL_IT(it)->wsd->generation)) > break; > >> + if (it) break; > >> } > >> > >> return (Elm_Object_Item *)it; > >> @@ -5959,7 +5897,7 @@ elm_genlist_item_selected_set(Elm_Object_Item > *item, > >> ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); > >> > >> sd = GL_IT(it)->wsd; > >> - if ((it->generation < sd->generation) || > >> elm_widget_item_disabled_get(it)) > >> + if (elm_widget_item_disabled_get(it)) > >> return; > >> selected = !!selected; > >> if (it->selected == selected) return; > >> @@ -6135,7 +6073,6 @@ _elm_genlist_item_coordinates_calc(Elm_Object_Item > >> *item, > >> Elm_Gen_Item *it = (Elm_Gen_Item *)item; > >> Evas_Coord gith = 0; > >> > >> - if (it->generation < GL_IT(it)->wsd->generation) return EINA_FALSE; > >> if (!((GL_IT(it)->wsd->homogeneous) && > >> (GL_IT(it)->wsd->mode == ELM_LIST_COMPRESS))) > >> { > >> @@ -6191,7 +6128,6 @@ elm_genlist_item_promote(Elm_Object_Item *item) > >> > >> ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); > >> > >> - if (it->generation < GL_IT(it)->wsd->generation) return; > >> _item_move_before > >> (it, (Elm_Gen_Item *)elm_genlist_first_item_get(WIDGET(it))); > >> } > >> @@ -6202,7 +6138,6 @@ elm_genlist_item_demote(Elm_Object_Item *item) > >> Elm_Gen_Item *it = (Elm_Gen_Item *)item; > >> > >> ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); > >> - if (it->generation < GL_IT(it)->wsd->generation) return; > >> _item_move_after(it, (Elm_Gen_Item > >> *)elm_genlist_last_item_get(WIDGET(it))); > >> } > >> > >> @@ -6258,7 +6193,6 @@ elm_genlist_item_update(Elm_Object_Item *item) > >> ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); > >> > >> if (!it->item->block) return; > >> - if (it->generation < GL_IT(it)->wsd->generation) return; > >> it->item->mincalcd = EINA_FALSE; > >> it->item->updateme = EINA_TRUE; > >> it->item->block->updateme = EINA_TRUE; > >> @@ -6276,7 +6210,6 @@ elm_genlist_item_fields_update(Elm_Object_Item > *item, > >> ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); > >> > >> if (!it->item->block) return; > >> - if (it->generation < GL_IT(it)->wsd->generation) return; > >> > >> if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT)) > >> { > >> @@ -6338,7 +6271,6 @@ elm_genlist_item_item_class_update(Elm_Object_Item > >> *item, > >> > >> if (!it->item->block) return; > >> EINA_SAFETY_ON_NULL_RETURN(itc); > >> - if (it->generation < GL_IT(it)->wsd->generation) return; > >> it->itc = itc; > >> it->item->nocache_once = EINA_TRUE; > >> > >> @@ -6378,7 +6310,6 @@ elm_genlist_item_item_class_get(const > >> Elm_Object_Item *item) > >> Elm_Gen_Item *it = (Elm_Gen_Item *)item; > >> > >> ELM_GENLIST_ITEM_CHECK_OR_RETURN(item, NULL); > >> - if (it->generation < GL_IT(it)->wsd->generation) return NULL; > >> > >> return it->itc; > >> } > >> @@ -6848,8 +6779,7 @@ elm_genlist_item_decorate_mode_set(Elm_Object_Item > >> *item, > >> sd = GL_IT(it)->wsd; > >> > >> if (!decorate_it_type) return; > >> - if ((it->generation < sd->generation) || > >> - elm_widget_item_disabled_get(it)) return; > >> + if (elm_widget_item_disabled_get(it)) return; > >> if (sd->decorate_all_mode) return; > >> > >> if ((sd->mode_item == it) && > >> @@ -7238,7 +7168,6 @@ elm_genlist_item_select_mode_set(Elm_Object_Item > >> *item, > >> > >> ELM_GENLIST_ITEM_CHECK_OR_RETURN(item); > >> if (!it) return; > >> - if (it->generation < GL_IT(it)->wsd->generation) return; > >> if (mode >= ELM_OBJECT_SELECT_MODE_MAX) > >> return; > >> if (it->select_mode != mode) > >> diff --git a/src/lib/elm_widget_genlist.h b/src/lib/elm_widget_genlist.h > >> index e27a74e..fadb71d 100644 > >> --- a/src/lib/elm_widget_genlist.h > >> +++ b/src/lib/elm_widget_genlist.h > >> @@ -46,7 +46,6 @@ struct _Elm_Genlist_Smart_Data > >> * repositioned */ > >> Elm_Object_Item *last_selected_item; > >> Ecore_Job *calc_job; > >> - int walking; > >> int item_width, item_height; > >> int group_item_width, > >> group_item_height; > >> int minw, minh; > >> @@ -112,9 +111,6 @@ struct _Elm_Genlist_Smart_Data > >> * default. this can be changed by > >> * elm_genlist_longpress_timeout_set() */ > >> double longpress_timeout; > >> - /* a generation of genlist. when genlist is cleared, this value > >> - * will be increased and a new generation will start */ > >> - int generation; > >> Eina_Compare_Cb item_compare_cb; > >> Eina_Compare_Cb item_compare_data_cb; > >> > >> @@ -160,7 +156,6 @@ struct _Elm_Genlist_Smart_Data > >> Eina_Bool highlight : 1; > >> /* a flag whether genlist is marked as to be cleared or not. if > >> * this flag is true, genlist clear was already deferred. */ > >> - Eina_Bool clear_me : 1; > >> Eina_Bool h_bounce : 1; > >> Eina_Bool v_bounce : 1; > >> Eina_Bool bring_in : 1; /* a flag to > >> > >> -- > >> > >> > >> > ------------------------------------------------------------------------------ > >> Precog is a next-generation analytics platform capable of advanced > >> analytics on semi-structured data. The platform includes APIs for > building > >> apps and a phenomenal toolset for data science. Developers can use > >> our toolset for easy data analysis & visualization. Get a free account! > >> http://www2.precog.com/precogplatform/slashdotnewsletter > >> > > > ------------------------------------------------------------------------------ > > Precog is a next-generation analytics platform capable of advanced > > analytics on semi-structured data. The platform includes APIs for > building > > apps and a phenomenal toolset for data science. Developers can use > > our toolset for easy data analysis & visualization. Get a free account! > > http://www2.precog.com/precogplatform/slashdotnewsletter > > _______________________________________________ > > enlightenment-devel mailing list > > [email protected] > > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel > > > > -- > Rafael Antognolli > http://antognolli.org/ > > > ------------------------------------------------------------------------------ > Precog is a next-generation analytics platform capable of advanced > analytics on semi-structured data. The platform includes APIs for building > apps and a phenomenal toolset for data science. Developers can use > our toolset for easy data analysis & visualization. Get a free account! > http://www2.precog.com/precogplatform/slashdotnewsletter > _______________________________________________ > enlightenment-devel mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel > ------------------------------------------------------------------------------ Precog is a next-generation analytics platform capable of advanced analytics on semi-structured data. The platform includes APIs for building apps and a phenomenal toolset for data science. Developers can use our toolset for easy data analysis & visualization. Get a free account! http://www2.precog.com/precogplatform/slashdotnewsletter _______________________________________________ enlightenment-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
