X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/2b19a25515bc1cad49a8e5f6b6f2d2a0fcdd362c..dade5f874b05c2263bbbe668a77021d487b0761b:/src/geonamessearch.c?ds=sidebyside diff --git a/src/geonamessearch.c b/src/geonamessearch.c index a63165f1..3af6426a 100644 --- a/src/geonamessearch.c +++ b/src/geonamessearch.c @@ -39,11 +39,22 @@ #define g_mapped_file_unref g_mapped_file_free #endif -#define GEONAMES_WIKIPEDIA_URL_FMT "http://ws.geonames.org/wikipediaBoundingBoxJSON?formatted=true&north=%s&south=%s&east=%s&west=%s" +/** + * See http://www.geonames.org/export/wikipedia-webservice.html#wikipediaBoundingBox + */ +// Translators may wish to change this setting as appropriate to get Wikipedia articles in that language +#define GEONAMES_LANG N_("en") +// TODO - offer configuration of this value somewhere +// ATM decided it's not essential enough to warrant putting in the preferences +#define GEONAMES_MAX_ENTRIES 20 + +#define GEONAMES_WIKIPEDIA_URL_FMT "http://ws.geonames.org/wikipediaBoundingBoxJSON?formatted=true&north=%s&south=%s&east=%s&west=%s&lang=%s&maxRows=%d" + #define GEONAMES_FEATURE_PATTERN "\"feature\": \"" #define GEONAMES_LONGITUDE_PATTERN "\"lng\": " #define GEONAMES_NAME_PATTERN "\"name\": \"" #define GEONAMES_LATITUDE_PATTERN "\"lat\": " +#define GEONAMES_ELEVATION_PATTERN "\"elevation\": " #define GEONAMES_TITLE_PATTERN "\"title\": \"" #define GEONAMES_WIKIPEDIAURL_PATTERN "\"wikipediaUrl\": \"" #define GEONAMES_THUMBNAILIMG_PATTERN "\"thumbnailImg\": \"" @@ -55,6 +66,7 @@ typedef struct { gchar *name; gchar *feature; struct LatLon ll; + gdouble elevation; gchar *cmt; gchar *desc; } found_geoname; @@ -70,7 +82,8 @@ static found_geoname *new_found_geoname() ret->desc = NULL; ret->ll.lat = 0.0; ret->ll.lon = 0.0; - return(ret); + ret->elevation = VIK_DEFAULT_ALTITUDE; + return ret; } static found_geoname *copy_found_geoname(found_geoname *src) @@ -80,6 +93,7 @@ static found_geoname *copy_found_geoname(found_geoname *src) dest->feature = g_strdup(src->feature); dest->ll.lat = src->ll.lat; dest->ll.lon = src->ll.lon; + dest->elevation = src->elevation; dest->cmt = g_strdup(src->cmt); dest->desc = g_strdup(src->desc); return(dest); @@ -123,7 +137,6 @@ static GList *a_select_geoname_from_list(GtkWindow *parent, GList *geonames, gbo found_geoname *geoname; gchar *latlon_string; int column_runner; - gboolean to_copy; GtkWidget *dialog = gtk_dialog_new_with_buttons (title, parent, @@ -141,69 +154,91 @@ static GList *a_select_geoname_from_list(GtkWindow *parent, GList *geonames, gbo response_w = gtk_dialog_get_widget_for_response ( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT ); #endif GtkWidget *label = gtk_label_new ( msg ); - GtkTreeStore *store; - { - store = gtk_tree_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); - } + GtkTreeStore *store = gtk_tree_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + GList *geoname_runner = geonames; while (geoname_runner) { geoname = (found_geoname *)geoname_runner->data; latlon_string = g_strdup_printf("(%f,%f)", geoname->ll.lat, geoname->ll.lon); gtk_tree_store_append(store, &iter, NULL); - { - gtk_tree_store_set(store, &iter, 0, geoname->name, 1, geoname->feature, 2, latlon_string, -1); - } + gtk_tree_store_set(store, &iter, 0, geoname->name, 1, geoname->feature, 2, latlon_string, -1); geoname_runner = g_list_next(geoname_runner); g_free(latlon_string); } + view = gtk_tree_view_new(); renderer = gtk_cell_renderer_text_new(); column_runner = 0; - gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW(view), -1, _("Name"), renderer, "text", column_runner, NULL); + GtkTreeViewColumn *column; + // NB could allow columns to be shifted around by doing this after each new + // gtk_tree_view_column_set_reorderable ( column, TRUE ); + // However I don't think is that useful, so I haven't put it in + column = gtk_tree_view_column_new_with_attributes( _("Name"), renderer, "text", column_runner, NULL); + gtk_tree_view_column_set_sort_column_id (column, column_runner); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + column_runner++; - gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW(view), -1, _("Feature"), renderer, "text", column_runner, NULL); + column = gtk_tree_view_column_new_with_attributes( _("Feature"), renderer, "text", column_runner, NULL); + gtk_tree_view_column_set_sort_column_id (column, column_runner); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + column_runner++; - gtk_tree_view_insert_column_with_attributes( GTK_TREE_VIEW(view), -1, _("Lat/Lon"), renderer, "text", column_runner, NULL); - gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(view), TRUE); + column = gtk_tree_view_column_new_with_attributes( _("Lat/Lon"), renderer, "text", column_runner, NULL); + gtk_tree_view_column_set_sort_column_id (column, column_runner); + gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); + gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); gtk_tree_selection_set_mode( gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), multiple_selection_allowed ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_BROWSE ); g_object_unref(store); + GtkWidget *scrolledwindow = gtk_scrolled_window_new ( NULL, NULL ); + gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW(scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC ); + gtk_container_add ( GTK_CONTAINER(scrolledwindow), view ); + gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label, FALSE, FALSE, 0); - gtk_widget_show ( label ); - gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), view, FALSE, FALSE, 0); - gtk_widget_show ( view ); + gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), scrolledwindow, TRUE, TRUE, 0); + + // Ensure a reasonable number of items are shown, but let the width be automatically sized + gtk_widget_set_size_request ( dialog, -1, 400) ; + gtk_widget_show_all ( dialog ); + if ( response_w ) gtk_widget_grab_focus ( response_w ); + while ( gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT ) { GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); GList *selected_geonames = NULL; - gtk_tree_model_get_iter_first( GTK_TREE_MODEL(store), &iter); - geoname_runner = geonames; - while (geoname_runner) - { - to_copy = FALSE; - { - if (gtk_tree_selection_iter_is_selected(selection, &iter)) - { - to_copy = TRUE; + // Possibily not the fastest method but we don't have thousands of entries to process... + if ( gtk_tree_model_get_iter_first( GTK_TREE_MODEL(store), &iter) ) { + do { + if ( gtk_tree_selection_iter_is_selected ( selection, &iter ) ) { + // For every selected item, + // compare the name from the displayed view to every geoname entry to find the geoname this selection represents + gchar* name; + gtk_tree_model_get (GTK_TREE_MODEL(store), &iter, 0, &name, -1 ); + // I believe the name of these items to be always unique + geoname_runner = geonames; + while ( geoname_runner ) { + if ( !strcmp ( ((found_geoname*)geoname_runner->data)->name, name ) ) { + found_geoname *copied = copy_found_geoname(geoname_runner->data); + selected_geonames = g_list_prepend(selected_geonames, copied); + break; + } + geoname_runner = g_list_next(geoname_runner); + } } } - if (to_copy) { - found_geoname *copied = copy_found_geoname(geoname_runner->data); - selected_geonames = g_list_prepend(selected_geonames, copied); - } - geoname_runner = g_list_next(geoname_runner); - gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); + while ( gtk_tree_model_iter_next ( GTK_TREE_MODEL(store), &iter ) ); } + if (selected_geonames) { gtk_widget_destroy ( dialog ); - return (selected_geonames); + return selected_geonames; } a_dialog_error_msg(parent, _("Nothing was selected")); } @@ -217,7 +252,7 @@ static GList *get_entries_from_file(gchar *file_name) GMappedFile *mf; gsize len; gboolean more = TRUE; - gchar lat_buf[32], lon_buf[32]; + gchar lat_buf[32], lon_buf[32], elev_buf[32]; gchar *s; gint fragment_len; GList *found_places = NULL; @@ -228,10 +263,11 @@ static GList *get_entries_from_file(gchar *file_name) gchar *wikipedia_url = NULL; gchar *thumbnail_url = NULL; - lat_buf[0] = lon_buf[0] = '\0'; + lat_buf[0] = lon_buf[0] = elev_buf[0] = '\0'; if ((mf = g_mapped_file_new(file_name, FALSE, NULL)) == NULL) { g_critical(_("couldn't map temp file")); + return NULL; } len = g_mapped_file_get_length(mf); text = g_mapped_file_get_contents(mf); @@ -273,6 +309,17 @@ static GList *get_entries_from_file(gchar *file_name) } geoname->ll.lon = g_ascii_strtod(lon_buf, NULL); } + if ((pat = g_strstr_len(entry, strlen(entry), GEONAMES_ELEVATION_PATTERN))) { + pat += strlen(GEONAMES_ELEVATION_PATTERN); + s = elev_buf; + if (*pat == '-') + *s++ = *pat++; + while ((s < (elev_buf + sizeof(elev_buf))) && (pat < (text + len)) && + (g_ascii_isdigit(*pat) || (*pat == '.'))) + *s++ = *pat++; + *s = '\0'; + geoname->elevation = g_ascii_strtod(elev_buf, NULL); + } if ((pat = g_strstr_len(entry, strlen(entry), GEONAMES_NAME_PATTERN))) { pat += strlen(GEONAMES_NAME_PATTERN); fragment_len = 0; @@ -381,7 +428,7 @@ void a_geonames_wikipedia_box ( VikWindow *vw, VikTrwLayer *vtl, struct LatLon m gchar *south = a_coords_dtostr(maxmin[1].lat); gchar *east = a_coords_dtostr(maxmin[0].lon); gchar *west = a_coords_dtostr(maxmin[1].lon); - uri = g_strdup_printf(GEONAMES_WIKIPEDIA_URL_FMT, north, south, east, west); + uri = g_strdup_printf ( GEONAMES_WIKIPEDIA_URL_FMT, north, south, east, west, GEONAMES_LANG, GEONAMES_MAX_ENTRIES ); g_free(north); north = NULL; g_free(south); south = NULL; g_free(east); east = NULL; @@ -403,8 +450,24 @@ void a_geonames_wikipedia_box ( VikWindow *vw, VikTrwLayer *vtl, struct LatLon m wiki_wp = vik_waypoint_new(); wiki_wp->visible = TRUE; vik_coord_load_from_latlon(&(wiki_wp->coord), vik_trw_layer_get_coord_mode ( vtl ), &(wiki_geoname->ll)); + wiki_wp->altitude = wiki_geoname->elevation; vik_waypoint_set_comment(wiki_wp, wiki_geoname->cmt); vik_waypoint_set_description(wiki_wp, wiki_geoname->desc); + // Use the featue type to generate a suitable waypoint icon + // http://www.geonames.org/wikipedia/wikipedia_features.html + // Only a few values supported as only a few symbols make sense + if ( wiki_geoname->feature ) { + if ( !strcmp (wiki_geoname->feature, "city") ) + vik_waypoint_set_symbol(wiki_wp, "city (medium)"); + if ( !strcmp (wiki_geoname->feature, "edu") ) + vik_waypoint_set_symbol(wiki_wp, "school"); + if ( !strcmp (wiki_geoname->feature, "airport") ) + vik_waypoint_set_symbol(wiki_wp, "airport"); + if ( !strcmp (wiki_geoname->feature, "mountain") ) + vik_waypoint_set_symbol(wiki_wp, "summit"); + if ( !strcmp (wiki_geoname->feature, "forest") ) + vik_waypoint_set_symbol(wiki_wp, "forest"); + } vik_trw_layer_filein_add_waypoint ( vtl, wiki_geoname->name, wiki_wp ); wp_runner = g_list_next(wp_runner); }