Ticket #859: poi_filter.diff

File poi_filter.diff, 10.6 KB (added by https://wiki.navit-project.org/index.php/user:tryagain, 12 months ago)

Try this patch for gui_internal. There's a new lamp button added to POI dialog. By pressing it you can search POI by its type name (as defined in item_def.h) and by the name attached to the POI (if any). Everithing on the map is considered a POI so you can find not just points but also lines and polygons - streets, parkings marked as polygons etc. For now I don't care and use first point of polygon found to calculate distance to it.

  • navit/gui/internal/gui_internal.c

     
    22452245                type_none}}, 
    22462246}; 
    22472247 
    2248 union poi_param { 
    2249         guint i; 
    2250         struct { 
     2248 
     2249/* 
     2250 *  Get a utf-8 string, return the same prepared for case insensetive search. Result shoud be g_free()d after use. 
     2251 */ 
     2252 
     2253static char * 
     2254removecase(char *s)  
     2255{ 
     2256        char *r; 
     2257        r=g_utf8_casefold(s,-1); 
     2258        return r; 
     2259} 
     2260 
     2261struct poi_param { 
    22512262                unsigned char sel, selnb, pagenb, dist; 
    2252         } p; 
     2263                char *filterstr; /* Filter string, casefold()ed and divided into substrings at the spaces, which are replaced by ASCII 0*/ 
     2264                GList *filter; /* list of pointers to individual substrings of filterstr */ 
    22532265}; 
    22542266 
     2267 
     2268/** 
     2269 * @brief Free poi_param structure. 
     2270 * 
     2271 * @param p reference to the object to be freed. 
     2272 */ 
     2273static void 
     2274gui_internal_poi_param_free(void *p)  
     2275{ 
     2276        if(((struct poi_param *)p)->filterstr) 
     2277           g_free(((struct poi_param *)p)->filterstr); 
     2278        if(((struct poi_param *)p)->filter) 
     2279           g_list_free(((struct poi_param *)p)->filter); 
     2280        g_free(p); 
     2281}; 
     2282 
     2283/** 
     2284 * @brief Clone poi_param structure. 
     2285 * 
     2286 * @param p reference to the object to be cloned. 
     2287 * @return  Cloned object reference. 
     2288 */ 
     2289static struct poi_param * 
     2290gui_internal_poi_param_clone(struct poi_param *p)  
     2291{ 
     2292        struct poi_param *r=g_new(struct poi_param,1); 
     2293        GList *l=p->filter; 
     2294        memcpy(r,p,sizeof(struct poi_param)); 
     2295        r->filter=NULL; 
     2296        r->filterstr=NULL; 
     2297        if(p->filterstr) 
     2298                r->filterstr=g_strdup(p->filterstr); 
     2299        while(l) { 
     2300                r->filter=g_list_append(r->filter, r->filterstr + ((char*)(l->data) - p->filterstr) ); 
     2301                l=g_list_next(l); 
     2302        } 
     2303        return r; 
     2304}; 
     2305 
     2306 
    22552307static void gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data); 
     2308static void gui_internal_cmd_pois_filter(struct gui_priv *this, struct widget *wm, void *data); 
    22562309 
     2310 
    22572311static struct widget * 
    22582312gui_internal_cmd_pois_selector(struct gui_priv *this, struct pcoord *c, int pagenb) 
    22592313{ 
     
    22692323        nrows=nitems/wl->cols + (nitems%wl->cols>0); 
    22702324        wl->h=this->icon_l*nrows; 
    22712325        for (i = 0 ; i < nitems ; i++) { 
    2272                 union poi_param p; 
    2273                 p.p.sel = 1; 
    2274                 p.p.selnb = i; 
    2275                 p.p.pagenb = pagenb; 
    2276                 p.p.dist = 0; 
     2326                struct poi_param *p=g_new(struct poi_param,1); 
     2327                p->sel = 1; 
     2328                p->selnb = i; 
     2329                p->pagenb = pagenb; 
     2330                p->dist = 0; 
     2331                p->filter=NULL; 
     2332                p->filterstr=NULL; 
    22772333                gui_internal_widget_append(wl, wb=gui_internal_button_new_with_callback(this, NULL, 
    22782334                        image_new_s(this, selectors[i].icon), gravity_left_center|orientation_vertical, 
    2279                         gui_internal_cmd_pois, GUINT_TO_POINTER(p.i))); 
     2335                        gui_internal_cmd_pois, p)); 
    22802336                wb->c=*c; 
     2337                wb->data_free=gui_internal_poi_param_free; 
    22812338                wb->bt=10; 
    22822339        } 
     2340 
     2341        gui_internal_widget_append(wl, wb=gui_internal_button_new_with_callback(this, NULL, 
     2342                        image_new_s(this, "gui_about"), gravity_left_center|orientation_vertical, 
     2343                        gui_internal_cmd_pois_filter, NULL)); 
     2344        wb->c=*c; 
     2345        wb->bt=10; 
     2346         
    22832347        gui_internal_widget_pack(this,wl); 
    22842348        return wl; 
    22852349} 
     
    23342398} 
    23352399 
    23362400static int 
    2337 gui_internal_cmd_pois_item_selected(struct selector *sel, enum item_type type) 
     2401gui_internal_cmd_pois_item_selected(struct poi_param *param, struct item *item) 
    23382402{ 
    23392403        enum item_type *types; 
    2340         if (type >= type_line) 
     2404        struct selector *sel = param->sel? &selectors[param->selnb]: NULL; 
     2405        enum item_type type=item->type; 
     2406        struct attr attr; 
     2407        int match=0; 
     2408        if (type >= type_line && param->filter==NULL) 
    23412409                return 0; 
    2342         if (! sel || !sel->types) 
    2343                 return 1; 
    2344         types=sel->types; 
    2345         while (*types != type_none) { 
    2346                 if (type >= types[0] && type <= types[1]) { 
    2347                         return 1; 
     2410        if (! sel || !sel->types) { 
     2411                match=1; 
     2412        } else { 
     2413                types=sel->types; 
     2414                while (*types != type_none) { 
     2415                        if (item->type >= types[0] && item->type <= types[1]) { 
     2416                                return 1; 
     2417                        } 
     2418                        types+=2; 
    23482419                } 
    2349                 types+=2; 
    23502420        } 
    2351         return 0; 
     2421        if (param->filter) { 
     2422                char *long_name, *s; 
     2423                GList *f; 
     2424                 
     2425                if (item_attr_get(item, attr_label, &attr))  
     2426                        s=g_strdup_printf("%s %s", item_to_name(item->type), attr.u.str); 
     2427                else 
     2428                        s=g_strdup(item_to_name(item->type)); 
     2429                long_name=removecase(s); 
     2430                g_free(s); 
     2431                item_attr_rewind(item); 
     2432                 
     2433                for(s=long_name,f=param->filter;f && s;f=g_list_next(f)) { 
     2434                        s=strstr(s,f->data); 
     2435                        if(!s)  
     2436                                break; 
     2437                        s=g_utf8_strchr(s,-1,' '); 
     2438                } 
     2439                if(f) 
     2440                        match=0; 
     2441                g_free(long_name); 
     2442        } 
     2443        return match; 
    23522444} 
    23532445 
    23542446struct item_data { 
     
    23722464        w->data=wm->data; 
    23732465        w->c=wm->c; 
    23742466        w->w=wm->w; 
     2467        wm->data_free=NULL; 
    23752468        gui_internal_back(this, NULL, NULL); 
    2376         gui_internal_cmd_pois(this, w, NULL); 
     2469        gui_internal_cmd_pois(this, w, w->data); 
    23772470        free(w); 
    23782471} 
    23792472 
     2473/** 
     2474 * @brief apply POIs text filter. 
     2475 * 
     2476 * @param this The graphics context. 
     2477 * @param wm called widget. 
     2478 * @param data event data (pointer to editor widget containg filter text). 
     2479 */ 
     2480static void 
     2481gui_internal_cmd_pois_filter_do(struct gui_priv *this, struct widget *wm, void *data)  
     2482{ 
     2483        struct widget *w=data; 
     2484        struct poi_param *param; 
     2485        char *s1, *s2; 
     2486         
     2487        if(!w->text) 
     2488                return; 
     2489         
     2490        if(w->data) { 
     2491                param=gui_internal_poi_param_clone(w->data); 
     2492                param->pagenb=0; 
     2493        } else { 
     2494                param=g_new0(struct poi_param,1); 
     2495        } 
     2496        param->filterstr=removecase(w->text); 
     2497        s1=param->filterstr; 
     2498        do { 
     2499                s2=g_utf8_strchr(s1,-1,' '); 
     2500                if(s2) 
     2501                        *s2++=0; 
     2502                param->filter=g_list_append(param->filter,s1); 
     2503                if(s2) { 
     2504                        while(*s2==' ') 
     2505                                s2++; 
     2506                } 
     2507                s1=s2; 
     2508        } while(s2 && *s2); 
    23802509 
     2510        gui_internal_cmd_pois(this,w,param); 
     2511        gui_internal_poi_param_free(param); 
     2512} 
     2513 
     2514 
     2515/** 
     2516 * @brief POIs filter dialog. 
     2517 * 
     2518 * @param this The graphics context. 
     2519 * @param wm called widget. 
     2520 * @param data event data. 
     2521 */ 
    23812522static void 
     2523gui_internal_cmd_pois_filter(struct gui_priv *this, struct widget *wm, void *data)  
     2524{ 
     2525        struct widget *wb, *w, *wr, *wk, *we, *wc; 
     2526        int keyboard_mode=2; 
     2527        wb=gui_internal_menu(this,"Filter"); 
     2528        w=gui_internal_box_new(this, gravity_center|orientation_vertical|flags_expand|flags_fill); 
     2529        gui_internal_widget_append(wb, w); 
     2530        wr=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill); 
     2531        gui_internal_widget_append(w, wr); 
     2532        we=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill); 
     2533        gui_internal_widget_append(wr, we); 
     2534 
     2535        gui_internal_widget_append(we, wk=gui_internal_label_new(this, NULL)); 
     2536        wk->state |= STATE_EDIT|STATE_EDITABLE; 
     2537        wk->background=this->background; 
     2538        wk->flags |= flags_expand|flags_fill; 
     2539        wk->name=g_strdup("POIsFilter"); 
     2540        wk->c=wm->c; 
     2541        gui_internal_widget_append(we, wb=gui_internal_image_new(this, image_new_xs(this, "gui_active"))); 
     2542         
     2543        wb->state |= STATE_SENSITIVE; 
     2544        wb->func = gui_internal_cmd_pois_filter_do; 
     2545        wb->data=wk; 
     2546        if (this->keyboard) 
     2547                gui_internal_widget_append(w, gui_internal_keyboard(this,keyboard_mode)); 
     2548        gui_internal_menu_render(this); 
     2549 
     2550 
     2551} 
     2552 
     2553/** 
     2554 * @brief Do POI search specified by poi_param and display POIs found 
     2555 * 
     2556 * @param this The graphics context. 
     2557 * @param wm called widget. 
     2558 * @param data event data, reference to poi_param or NULL. 
     2559 */ 
     2560static void 
    23822561gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data) 
    23832562{ 
    23842563        struct map_selection *sel,*selm; 
     
    23892568        struct item *item; 
    23902569        struct widget *wi,*w,*w2,*wb, *wtable, *row; 
    23912570        enum projection pro=wm->c.pro; 
    2392         union poi_param param = {.i = GPOINTER_TO_UINT(wm->data)}; 
    2393         int idist,dist=10000*(param.p.dist+1); 
    2394         struct selector *isel = param.p.sel? &selectors[param.p.selnb]: NULL; 
    2395         int pagenb = param.p.pagenb; 
    2396         int prevdist=param.p.dist*10000; 
     2571        struct poi_param *param; 
     2572        int param_free=0; 
     2573        int idist,dist; 
     2574        struct selector *isel; 
     2575        int pagenb; 
     2576        int prevdist; 
    23972577        const int pagesize = 50; // Starting value and increment of count of items to be extracted 
    2398         int maxitem = pagesize*(pagenb+1), it = 0, i; 
    2399         struct item_data *items= g_new0( struct item_data, maxitem); 
     2578        int maxitem, it = 0, i; 
     2579        struct item_data *items; 
    24002580        struct fibheap* fh = fh_makekeyheap(); 
    24012581        int cnt = 0; 
    24022582        struct table_data *td; 
    24032583        int width=wm->w; 
    2404         dbg(2, "Params: sel = %i, selnb = %i, pagenb = %i, dist = %i\n", 
    2405                 param.p.sel, param.p.selnb, param.p.pagenb, param.p.dist); 
     2584         
     2585         
     2586        if(data) { 
     2587          param = data; 
     2588        } else { 
     2589          param = g_new0(struct poi_param,1); 
     2590          param_free=1; 
     2591        } 
     2592         
     2593        dist=10000*(param->dist+1); 
     2594        isel = param->sel? &selectors[param->selnb]: NULL; 
     2595        pagenb = param->pagenb; 
     2596        prevdist=param->dist*10000; 
     2597        maxitem = pagesize*(pagenb+1); 
     2598        items= g_new0( struct item_data, maxitem); 
     2599         
     2600         
     2601        dbg(0, "Params: sel = %i, selnb = %i, pagenb = %i, dist = %i, filterstr = %s\n", 
     2602                param->sel, param->selnb, param->pagenb, param->dist, param->filterstr); 
    24062603 
    24072604        wb=gui_internal_menu(this, isel ? isel->name : _("POIs")); 
    24082605        w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill); 
    24092606        gui_internal_widget_append(wb, w); 
    2410         if (!isel) 
     2607        if (!isel && !param->filter) 
    24112608                gui_internal_widget_append(w, gui_internal_cmd_pois_selector(this,&wm->c,pagenb)); 
    24122609        w2=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill); 
    24132610        gui_internal_widget_append(w, w2); 
     
    24222619                dbg(2,"mr=%p\n", mr); 
    24232620                if (mr) { 
    24242621                        while ((item=map_rect_get_item(mr))) { 
    2425                                 if (gui_internal_cmd_pois_item_selected(isel, item->type) && 
     2622                                if (gui_internal_cmd_pois_item_selected(param, item) && 
    24262623                                    item_coord_get_pro(item, &c, 1, pro) && 
    24272624                                    coord_rect_contains(&sel->u.c_rect, &c)  && 
    24282625                                    (idist=transform_distance(pro, &center, &c)) < dist) { 
     
    25042701        // Add an entry for more POI 
    25052702        struct widget *wl,*wt; 
    25062703        char buffer[32]; 
     2704        struct poi_param *paramnew; 
     2705        paramnew=gui_internal_poi_param_clone(param); 
    25072706        wl=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill); 
    25082707        if (it == maxitem) { 
    2509                 param.p.pagenb++; 
    2510                 snprintf(buffer, sizeof(buffer), "Get more (up to %d items)...", (param.p.pagenb+1)*pagesize); 
     2708                paramnew->pagenb++; 
     2709                snprintf(buffer, sizeof(buffer), "Get more (up to %d items)...", (paramnew->pagenb+1)*pagesize); 
    25112710        } else { 
    2512                 param.p.dist++; 
    2513                 snprintf(buffer, sizeof(buffer), "Set search distance to %i km", 10*(param.p.dist+1)); 
     2711                paramnew->dist++; 
     2712                snprintf(buffer, sizeof(buffer), "Set search distance to %i km", 10*(paramnew->dist+1)); 
    25142713        } 
    25152714        wt=gui_internal_label_new(this, buffer); 
    25162715        gui_internal_widget_append(wl, wt); 
    25172716        wl->func=gui_internal_cmd_pois_more; 
    2518         wl->data=GUINT_TO_POINTER(param.i); 
     2717        wl->data=paramnew; 
     2718        wl->data_free=gui_internal_poi_param_free; 
    25192719        wl->state |= STATE_SENSITIVE; 
    25202720        wl->c = wm->c; 
    25212721        row = gui_internal_widget_table_row_new(this, 
     
    25372737                } 
    25382738        } 
    25392739        gui_internal_menu_render(this); 
    2540  
     2740        if(param_free) 
     2741                g_free(param); 
    25412742} 
    25422743#endif /* _MSC_VER */ 
    25432744