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) |
|---|
-
navit/gui/internal/gui_internal.c
2245 2245 type_none}}, 2246 2246 }; 2247 2247 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 2253 static char * 2254 removecase(char *s) 2255 { 2256 char *r; 2257 r=g_utf8_casefold(s,-1); 2258 return r; 2259 } 2260 2261 struct poi_param { 2251 2262 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 */ 2253 2265 }; 2254 2266 2267 2268 /** 2269 * @brief Free poi_param structure. 2270 * 2271 * @param p reference to the object to be freed. 2272 */ 2273 static void 2274 gui_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 */ 2289 static struct poi_param * 2290 gui_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 2255 2307 static void gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data); 2308 static void gui_internal_cmd_pois_filter(struct gui_priv *this, struct widget *wm, void *data); 2256 2309 2310 2257 2311 static struct widget * 2258 2312 gui_internal_cmd_pois_selector(struct gui_priv *this, struct pcoord *c, int pagenb) 2259 2313 { … … 2269 2323 nrows=nitems/wl->cols + (nitems%wl->cols>0); 2270 2324 wl->h=this->icon_l*nrows; 2271 2325 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; 2277 2333 gui_internal_widget_append(wl, wb=gui_internal_button_new_with_callback(this, NULL, 2278 2334 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)); 2280 2336 wb->c=*c; 2337 wb->data_free=gui_internal_poi_param_free; 2281 2338 wb->bt=10; 2282 2339 } 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 2283 2347 gui_internal_widget_pack(this,wl); 2284 2348 return wl; 2285 2349 } … … 2334 2398 } 2335 2399 2336 2400 static int 2337 gui_internal_cmd_pois_item_selected(struct selector *sel, enum item_type type)2401 gui_internal_cmd_pois_item_selected(struct poi_param *param, struct item *item) 2338 2402 { 2339 2403 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) 2341 2409 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; 2348 2419 } 2349 types+=2;2350 2420 } 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; 2352 2444 } 2353 2445 2354 2446 struct item_data { … … 2372 2464 w->data=wm->data; 2373 2465 w->c=wm->c; 2374 2466 w->w=wm->w; 2467 wm->data_free=NULL; 2375 2468 gui_internal_back(this, NULL, NULL); 2376 gui_internal_cmd_pois(this, w, NULL);2469 gui_internal_cmd_pois(this, w, w->data); 2377 2470 free(w); 2378 2471 } 2379 2472 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 */ 2480 static void 2481 gui_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); 2380 2509 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 */ 2381 2522 static void 2523 gui_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 */ 2560 static void 2382 2561 gui_internal_cmd_pois(struct gui_priv *this, struct widget *wm, void *data) 2383 2562 { 2384 2563 struct map_selection *sel,*selm; … … 2389 2568 struct item *item; 2390 2569 struct widget *wi,*w,*w2,*wb, *wtable, *row; 2391 2570 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; 2397 2577 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; 2400 2580 struct fibheap* fh = fh_makekeyheap(); 2401 2581 int cnt = 0; 2402 2582 struct table_data *td; 2403 2583 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); 2406 2603 2407 2604 wb=gui_internal_menu(this, isel ? isel->name : _("POIs")); 2408 2605 w=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill); 2409 2606 gui_internal_widget_append(wb, w); 2410 if (!isel )2607 if (!isel && !param->filter) 2411 2608 gui_internal_widget_append(w, gui_internal_cmd_pois_selector(this,&wm->c,pagenb)); 2412 2609 w2=gui_internal_box_new(this, gravity_top_center|orientation_vertical|flags_expand|flags_fill); 2413 2610 gui_internal_widget_append(w, w2); … … 2422 2619 dbg(2,"mr=%p\n", mr); 2423 2620 if (mr) { 2424 2621 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) && 2426 2623 item_coord_get_pro(item, &c, 1, pro) && 2427 2624 coord_rect_contains(&sel->u.c_rect, &c) && 2428 2625 (idist=transform_distance(pro, ¢er, &c)) < dist) { … … 2504 2701 // Add an entry for more POI 2505 2702 struct widget *wl,*wt; 2506 2703 char buffer[32]; 2704 struct poi_param *paramnew; 2705 paramnew=gui_internal_poi_param_clone(param); 2507 2706 wl=gui_internal_box_new(this, gravity_left_center|orientation_horizontal|flags_fill); 2508 2707 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); 2511 2710 } 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)); 2514 2713 } 2515 2714 wt=gui_internal_label_new(this, buffer); 2516 2715 gui_internal_widget_append(wl, wt); 2517 2716 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; 2519 2719 wl->state |= STATE_SENSITIVE; 2520 2720 wl->c = wm->c; 2521 2721 row = gui_internal_widget_table_row_new(this, … … 2537 2737 } 2538 2738 } 2539 2739 gui_internal_menu_render(this); 2540 2740 if(param_free) 2741 g_free(param); 2541 2742 } 2542 2743 #endif /* _MSC_VER */ 2543 2744
