From f0f290f1afecfecbb92394008c33de3ea4969d77 Mon Sep 17 00:00:00 2001 From: Kaj-Michael Lang Date: Thu, 21 Feb 2008 13:51:19 +0200 Subject: [PATCH] Add OSM import function directly in the UI. - Use a thread to do the import in the background. - Very simple import dialog.. would need some love. --- src/Makefile.am | 1 + src/cb.c | 8 ++++ src/cb.h | 1 + src/import-gui.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ src/osm-db-import.c | 99 +++++++++++++++++++++++++++++++++++---- src/osm-db-import.h | 13 ++++++ src/ui-common.c | 3 +- 7 files changed, 225 insertions(+), 11 deletions(-) create mode 100644 src/import-gui.c diff --git a/src/Makefile.am b/src/Makefile.am index f25cf07..a09595d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -57,6 +57,7 @@ mapper_SOURCES = \ filter.c \ filter.h \ filter-gui.c \ + import-gui.c \ gps-browse.c \ gps-panels.c \ gps-panels.h \ diff --git a/src/cb.c b/src/cb.c index 955e1ea..e01851a 100644 --- a/src/cb.c +++ b/src/cb.c @@ -527,6 +527,14 @@ settings_dialog_osm(); return TRUE; } +gboolean +menu_cb_import_osm(GtkAction * action) +{ +osm_import_dialog(_window); +return TRUE; +} + + gboolean menu_cb_help(GtkAction * action) { diff --git a/src/cb.h b/src/cb.h index 00e7d3a..8a2ebaa 100644 --- a/src/cb.h +++ b/src/cb.h @@ -72,6 +72,7 @@ gboolean menu_cb_settings(GtkAction * action); gboolean menu_cb_settings_gps(GtkAction * action); gboolean menu_cb_settings_osm(GtkAction * action); gboolean menu_cb_settings_colors(GtkAction * action); +gboolean menu_cb_import_osm(GtkAction * action); gboolean menu_cb_help(GtkAction * action); gboolean menu_cb_about(GtkAction * action); diff --git a/src/import-gui.c b/src/import-gui.c new file mode 100644 index 0000000..a0bc5c2 --- /dev/null +++ b/src/import-gui.c @@ -0,0 +1,111 @@ +/* + * This file is part of mapper + * + * Copyright (C) 2007 Kaj-Michael Lang + * + * Default map data provided by http://www.openstreetmap.org/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hildon-mapper.h" +#include "utils.h" +#include "osm-db-import.h" +#include "dialogs.h" + +static GtkWidget *progress; +static GtkWidget *import_dialog; + +static gboolean +osm_import_progress_cb(gpointer data) +{ +gtk_progress_bar_pulse(progress); +return TRUE; +} + +static gboolean +osm_import_done_cb(gpointer data) +{ +gint ret; + +ret=osm_import_join_bg(); + +if (ret!=0) + popup_error(import_dialog, _("OSM Data import failed!")); + +progress_dialog_remove(import_dialog); +return FALSE; +} + +gboolean +osm_import_dialog(GtkWidget *window) +{ +GtkWidget *dialog; +GtkWidget *vbox; +GtkWidget *picker_planet; +GtkWidget *entry_db; + +dialog = gtk_dialog_new_with_buttons(_("OSM Data import"), + GTK_WINDOW(window), + GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); + +gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox = gtk_vbox_new (FALSE, 3), TRUE, TRUE, 0); + +picker_planet=gtk_file_chooser_button_new(_("OSM Planet file"), GTK_FILE_CHOOSER_ACTION_OPEN); +entry_db=gtk_entry_new(); + +gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new("OSM Planet"), TRUE, TRUE, 0); +gtk_box_pack_start(GTK_BOX(vbox), picker_planet, TRUE, TRUE, 0); + +gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new("Destination database"), TRUE, TRUE, 0); +gtk_box_pack_start(GTK_BOX(vbox), entry_db, TRUE, TRUE, 0); + +gtk_widget_show_all(dialog); + +if (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { + gchar *planet, *db; + + planet=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(picker_planet)); + db=gtk_entry_get_text(GTK_ENTRY(entry_db)); + + if (planet && db) { + progress=gtk_progress_bar_new(); + import_dialog=progress_dialog(window, "Importing OSM data...", progress); + + if (osm_import_bg(planet, db, osm_import_progress_cb, osm_import_done_cb)==TRUE) + gtk_widget_destroy(dialog); + else + popup_error(dialog, _("Failed to start import thread.")); + } else { + popup_error(dialog, _("Missing file selection!")); + } +} else { + gtk_widget_destroy(dialog); +} +return TRUE; +} diff --git a/src/osm-db-import.c b/src/osm-db-import.c index ce05fd4..a7bffb1 100644 --- a/src/osm-db-import.c +++ b/src/osm-db-import.c @@ -72,6 +72,12 @@ static guint dbnode_cnt=0; static guint dbnoded_cnt=0; static guint dbway_cnt=0; +/* For threaded importing */ +static GThread* import_thread=NULL; +static GSourceFunc osm_import_progress_cb=NULL; +static osm_import_data_req osm_import_req; +static guint import_sid=0; + static gboolean is_update=FALSE; static XML_Parser xp; @@ -384,7 +390,7 @@ sqlite3_finalize(sql.delete_way_names_nls); sqlite3_finalize(sql.insert_way_names_nls); } -void +static void db_prepare(sqlite3 *db) { /* Way nodes */ @@ -1657,8 +1663,8 @@ osm_planet_parse_buffer(gchar *buffer, size_t r) { if (XML_Parse(xp, buffer, r, r>0 ? 0:1) == XML_STATUS_ERROR) { g_printerr("Parse error at line %d:\n%s\n", - XML_GetCurrentLineNumber(xp), - XML_ErrorString(XML_GetErrorCode(xp))); + (gint)XML_GetCurrentLineNumber(xp), + XML_ErrorString(XML_GetErrorCode(xp))); return FALSE; } return TRUE; @@ -1720,6 +1726,16 @@ g_printf("Skipping data outside of box: %f,%f - %f,%f\n", bbox.lat_min, bbox.lon_min, bbox.lat_max, bbox.lon_max); } +static void +osm_print_import_stats(void) +{ +g_printf("Total nodes %d, POIs: %d and Ways %d.\n", node_cnt, noded_cnt, way_cnt); +g_printf("Cities/Towns: %d\n", g_hash_table_size(osm_place_city)); +g_printf("Villages/Hamlets: %d\n", g_hash_table_size(osm_place_village)); +g_printf("Suburbs: %d\n", g_hash_table_size(osm_place_suburb)); +g_printf("Nodes: %d\n", g_hash_table_size(osm_nodes)); +} + /** * Simple helper to do all preparations and importing from planet -> database * @@ -1735,7 +1751,6 @@ if (db_connect(&db, database)!=TRUE) { db_create_tables(db); db_create_indexes(db); db_prepare(db); - osm_planet_parser_init(); if (osm_planet_parse_file(planet)==FALSE) { @@ -1743,16 +1758,82 @@ if (osm_planet_parse_file(planet)==FALSE) { return FALSE; } -g_printf("Total nodes %d, POIs: %d and Ways %d.\n", node_cnt, noded_cnt, way_cnt); -g_printf("Cities/Towns: %d\n", g_hash_table_size(osm_place_city)); -g_printf("Villages/Hamlets: %d\n", g_hash_table_size(osm_place_village)); -g_printf("Suburbs: %d\n", g_hash_table_size(osm_place_suburb)); -g_printf("Nodes: %d\n", g_hash_table_size(osm_nodes)); +osm_print_import_stats(); osm_planet_save_all_nodes(); osm_planet_save_all_ways(); osm_planet_parser_deinit(); +db_finalize(); db_close(&db); +g_printf("All done.\n"); return TRUE; } +static gpointer +osm_import_thread(gpointer user_data) +{ +gboolean r; +osm_import_data_req *req=(osm_import_data_req *)user_data; + +g_assert(req); +g_assert(req->planet); +g_assert(req->db); + +osm_import_progress_cb=req->progress_cb!=NULL ? req->progress_cb : NULL; + +r=osm_import(req->planet, req->db); +g_debug("OSM import result: %d", r); + +g_free(req->planet); +g_free(req->db); + +if (req->done_cb!=NULL) + g_idle_add(req->done_cb, GINT_TO_POINTER(r==TRUE ? 0 : 1)); + +return r==TRUE ? 0 : 1; +} + +/** + * Helper to start an import in the background using a thread. + * + * Two callback can be given, one for progress feedback and one when the operation is done. + * Done callback must call the join function. + * Only one import thread can run at a time. + * + */ +gboolean +osm_import_bg(const gchar *planet, const gchar *database, GSourceFunc progress_cb, GSourceFunc done_cb) +{ +GError *error=NULL; + +g_return_val_if_fail(import_thread==NULL, FALSE); + +osm_import_req.planet=g_strdup(planet); +osm_import_req.db=g_strdup(database); +osm_import_req.progress_cb=progress_cb; +osm_import_req.done_cb=done_cb; + +import_thread=g_thread_create(osm_import_thread, &osm_import_req, TRUE, &error); +if (import_thread==NULL) { + g_free(osm_import_req.planet); + g_free(osm_import_req.db); + g_printerr("Import thread creation failed.\n"); + return FALSE; +} +if (osm_import_progress_cb!=NULL) + import_sid=g_timeout_add(1000, osm_import_progress_cb, NULL); +return TRUE; +} + +gint +osm_import_join_bg(void) +{ +gint ret; +g_assert(import_thread!=NULL); + +if (import_sid!=0) + g_source_remove(import_sid); +ret=g_thread_join(import_thread); +import_thread=NULL; +return ret; +} diff --git a/src/osm-db-import.h b/src/osm-db-import.h index 42c0059..fefacf9 100644 --- a/src/osm-db-import.h +++ b/src/osm-db-import.h @@ -3,6 +3,8 @@ #include +#include "osm.h" + /* POI or Place node extra data */ typedef struct _node_data node_data; struct _node_data { @@ -56,7 +58,18 @@ struct map_bbox { gdouble lon_max; }; +/* Struct with import request */ +typedef struct _osm_import_data_req osm_import_data_req; +struct _osm_import_data_req { + gchar *planet; + gchar *db; + GSourceFunc progress_cb; + GSourceFunc done_cb; +}; + void osm_import_set_bbox(gboolean use_bb, gdouble latmin, gdouble lonmin, gdouble latmax, gdouble lonmax); gboolean osm_import(const gchar *planet, const gchar *database); +gboolean osm_import_bg(const gchar *planet, const gchar *database, GSourceFunc progress_cb, GSourceFunc done_cb); +gint osm_import_join_bg(void); #endif diff --git a/src/ui-common.c b/src/ui-common.c index 75243a6..7d8039d 100644 --- a/src/ui-common.c +++ b/src/ui-common.c @@ -87,9 +87,7 @@ static const gchar *mapper_ui = " " " " " " -#if 0 " " -#endif " " " " " " @@ -217,6 +215,7 @@ static GtkActionEntry ui_entries[] = { {"file_settings_colors", NULL, N_("_Colors..."), NULL, NULL, G_CALLBACK(menu_cb_settings_colors) }, {"file_settings_gps", NULL, N_("_Gps..."), NULL, NULL, G_CALLBACK(menu_cb_settings_gps) }, {"file_settings_osm", NULL, N_("_Map info..."), NULL, NULL, G_CALLBACK(menu_cb_settings_osm) }, + {"file_import_osm", NULL, N_("_Import OSM data..."), NULL, NULL, G_CALLBACK(menu_cb_import_osm) }, {"file_quit", GTK_STOCK_QUIT, N_("_Quit"), "Q", NULL, G_CALLBACK(mapper_cb_quit) }, {"help", NULL, N_("_Help"), NULL, NULL, NULL }, -- 2.39.5