From 17720e63b8f29a0909212c9cd13cc71c848c9097 Mon Sep 17 00:00:00 2001 From: Guilhem Bonnefille Date: Mon, 4 Nov 2013 23:31:23 +0100 Subject: [PATCH] SF Feature#49: Export via GPSBabel Allow to export data in all formats supported by gpsbabel. Signed-off-by: Guilhem Bonnefille --- help/C/viking.xml | 2 +- src/babel.c | 10 ++--- src/file.c | 16 ++++++++ src/file.h | 2 + src/viktrwlayer.c | 10 +++++ src/viktrwlayer_export.c | 89 ++++++++++++++++++++++++++++++++++++++++ src/viktrwlayer_export.h | 2 + 7 files changed, 125 insertions(+), 6 deletions(-) diff --git a/help/C/viking.xml b/help/C/viking.xml index 0c314fc9..be4b5542 100644 --- a/help/C/viking.xml +++ b/help/C/viking.xml @@ -754,7 +754,7 @@ You are probably better off expanding the waypoint list and directly start typin
Export Layer -The layer (all tracks, routes and waypoints) can be exported to a file GPX, GPSPoint, GPSMapper or Google's KML format. +The layer (all tracks, routes and waypoints) can be exported to a file GPX, GPSPoint, GPSMapper, Google's KML format or any other format supported by GPSbabel. Version1.1+: An individual track can be exported to a GPX file via the track menu. diff --git a/src/babel.c b/src/babel.c index c9622926..93ad52e3 100644 --- a/src/babel.c +++ b/src/babel.c @@ -555,11 +555,11 @@ static void load_feature_parse_line (gchar *line) file->label = g_strdup (tokens[4]); a_babel_file_list = g_list_append (a_babel_file_list, file); g_debug ("New gpsbabel file: %s, %d%d%d%d%d%d(%s)", - file->name, - file->mode.waypointsRead, file->mode.waypointsWrite, - file->mode.tracksRead, file->mode.tracksWrite, - file->mode.routesRead, file->mode.routesWrite, - tokens[1]); + file->name, + file->mode.waypointsRead, file->mode.waypointsWrite, + file->mode.tracksRead, file->mode.tracksWrite, + file->mode.routesRead, file->mode.routesWrite, + tokens[1]); } else { g_warning ( "Unexpected gpsbabel format string: %s", line); } diff --git a/src/file.c b/src/file.c index ce935d87..ec9e4f33 100644 --- a/src/file.c +++ b/src/file.c @@ -866,6 +866,22 @@ gboolean a_file_export ( VikTrwLayer *vtl, const gchar *filename, VikFileType_t return FALSE; } +/** + * a_file_export_babel: + */ +gboolean a_file_export_babel ( VikTrwLayer *vtl, const gchar *filename, const gchar *format, + gboolean tracks, gboolean routes, gboolean waypoints ) +{ + gchar *args = g_strdup_printf("%s %s %s -o %s", + tracks ? "-t" : "", + routes ? "-r" : "", + waypoints ? "-w" : "", + format); + gboolean result = a_babel_convert_to ( vtl, NULL, args, filename, NULL, NULL ); + g_free(args); + return result; +} + /** * Just a wrapper around realpath, which itself is platform dependent */ diff --git a/src/file.h b/src/file.h index 5370f688..48a05c65 100644 --- a/src/file.h +++ b/src/file.h @@ -62,6 +62,8 @@ VikLoadType_t a_file_load ( VikAggregateLayer *top, VikViewport *vp, const gchar gboolean a_file_save ( VikAggregateLayer *top, gpointer vp, const gchar *filename ); /* Only need to define VikTrack if the file type is FILE_TYPE_GPX_TRACK */ gboolean a_file_export ( VikTrwLayer *vtl, const gchar *filename, VikFileType_t file_type, VikTrack *trk, gboolean write_hidden ); +gboolean a_file_export_babel ( VikTrwLayer *vtl, const gchar *filename, const gchar *format, + gboolean tracks, gboolean routes, gboolean waypoints ); void file_write_layer_param ( FILE *f, const gchar *name, VikLayerParamType type, VikLayerParamData data ); diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c index c085e720..7c9d81a3 100644 --- a/src/viktrwlayer.c +++ b/src/viktrwlayer.c @@ -3281,6 +3281,11 @@ static void trw_layer_export_kml ( menu_array_layer values ) g_free ( auto_save_name ); } +static void trw_layer_export_babel ( gpointer layer_and_vlp[2] ) +{ + gchar *auto_save_name = vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])); + vik_trw_layer_export_gpsbabel ( VIK_TRW_LAYER (layer_and_vlp[0]), _("Export Layer"), auto_save_name ); +} static void trw_layer_export_external_gpx_1 ( menu_array_layer values ) { @@ -3936,6 +3941,11 @@ static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item); gtk_widget_show ( item ); + item = gtk_menu_item_new_with_mnemonic ( _("Export via GPSbabel...") ); + g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_babel), pass_along ); + gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item); + gtk_widget_show ( item ); + gchar* external1 = g_strdup_printf ( _("Open with External Program_1: %s"), a_vik_get_external_gpx_program_1() ); item = gtk_menu_item_new_with_mnemonic ( external1 ); g_free ( external1 ); diff --git a/src/viktrwlayer_export.c b/src/viktrwlayer_export.c index 0dd5e9bb..d89f833b 100644 --- a/src/viktrwlayer_export.c +++ b/src/viktrwlayer_export.c @@ -28,6 +28,7 @@ #include #include "babel.h" +#include "babel_ui.h" #include "viking.h" #include "viktrwlayer_export.h" @@ -105,3 +106,91 @@ void vik_trw_layer_export_external_gpx ( VikTrwLayer *vtl, const gchar* external } } + +void vik_trw_layer_export_gpsbabel ( VikTrwLayer *vtl, const gchar *title, const gchar* default_name ) +{ + BabelMode mode = { 0, 0, 0, 0, 0, 0 }; + if ( g_hash_table_size (vik_trw_layer_get_routes(vtl)) ) { + mode.routesWrite = 1; + } + if ( g_hash_table_size (vik_trw_layer_get_tracks(vtl)) ) { + mode.tracksWrite = 1; + } + if ( g_hash_table_size (vik_trw_layer_get_waypoints(vtl)) ) { + mode.waypointsWrite = 1; + } + + GtkWidget *file_selector; + const gchar *fn; + gboolean failed = FALSE; + file_selector = gtk_file_chooser_dialog_new (title, + NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + gchar *cwd = g_get_current_dir(); + if ( cwd ) { + gtk_file_chooser_set_current_folder ( GTK_FILE_CHOOSER(file_selector), cwd ); + g_free ( cwd ); + } + + /* Build the extra part of the widget */ + GtkWidget *babel_selector = a_babel_ui_file_type_selector_new ( mode ); + GtkWidget *label = gtk_label_new(_("File format:")); + GtkWidget *hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start ( GTK_BOX(hbox), label, TRUE, TRUE, 0 ); + gtk_box_pack_start ( GTK_BOX(hbox), babel_selector, TRUE, TRUE, 0 ); + gtk_widget_show (babel_selector); + gtk_widget_show (label); + gtk_widget_show_all (hbox); + + gtk_widget_set_tooltip_text( babel_selector, _("Select the file format.") ); + + GtkWidget *babel_modes = a_babel_ui_modes_new(mode.tracksWrite, mode.routesWrite, mode.waypointsWrite); + gtk_widget_show (babel_modes); + + gtk_widget_set_tooltip_text( babel_modes, _("Select the information to process.\n" + "Warning: the behavior of these switches is highly dependent of the file format selected.\n" + "Please, refer to GPSbabel if unsure.") ); + + GtkWidget *vbox = gtk_vbox_new(FALSE, 0); + gtk_box_pack_start ( GTK_BOX(vbox), hbox, TRUE, TRUE, 0 ); + gtk_box_pack_start ( GTK_BOX(vbox), babel_modes, TRUE, TRUE, 0 ); + gtk_widget_show_all (vbox); + + gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(file_selector), vbox); + + /* Add some dynamic: only allow dialog's validation when format selection is done */ + g_signal_connect (babel_selector, "changed", G_CALLBACK(a_babel_ui_type_selector_dialog_sensitivity_cb), file_selector); + /* Manually call the callback to fix the state */ + a_babel_ui_type_selector_dialog_sensitivity_cb (babel_selector, file_selector); + + /* Set possible name of the file */ + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(file_selector), default_name); + + while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT ) + { + fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file_selector) ); + if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE || + a_dialog_yes_or_no ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) ) + { + BabelFile *active = a_babel_ui_file_type_selector_get(babel_selector); + if (active == NULL) { + a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("You did not select a valid file format.") ); + } else { + gtk_widget_hide ( file_selector ); + vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) ); + gboolean tracks, routes, waypoints; + a_babel_ui_modes_get( babel_modes, &tracks, &routes, &waypoints ); + failed = ! a_file_export_babel ( vtl, fn, active->name, tracks, routes, waypoints ); + vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) ); + break; + } + } + } + //babel_ui_selector_destroy(babel_selector); + gtk_widget_destroy ( file_selector ); + if ( failed ) + a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("The filename you requested could not be opened for writing.") ); +} diff --git a/src/viktrwlayer_export.h b/src/viktrwlayer_export.h index 05cc2c75..0d745b21 100644 --- a/src/viktrwlayer_export.h +++ b/src/viktrwlayer_export.h @@ -31,6 +31,8 @@ void vik_trw_layer_export ( VikTrwLayer *vtl, const gchar *title, const gchar* d void vik_trw_layer_export_external_gpx ( VikTrwLayer *vtl, const gchar* external_program ); +void vik_trw_layer_export_gpsbabel ( VikTrwLayer *vtl, const gchar *title, const gchar* default_name ); + G_END_DECLS #endif -- 2.39.5