]> git.street.me.uk Git - andy/viking.git/blob - src/viktrwlayer_export.c
SF Bugs#128: Fix Crash when loading broken .vik file
[andy/viking.git] / src / viktrwlayer_export.c
1
2 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 /*
4  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
5  *
6  * Copyright (C) 2013, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <glib.h>
27 #include <glib/gstdio.h>
28 #include <glib/gi18n.h>
29
30 #include "babel.h"
31 #include "babel_ui.h"
32 #include "viking.h"
33 #include "viktrwlayer_export.h"
34 #include "gpx.h"
35
36 static gchar *last_folder_uri = NULL;
37
38 void vik_trw_layer_export ( VikTrwLayer *vtl, const gchar *title, const gchar* default_name, VikTrack* trk, VikFileType_t file_type )
39 {
40   GtkWidget *file_selector;
41   const gchar *fn;
42   gboolean failed = FALSE;
43   file_selector = gtk_file_chooser_dialog_new (title,
44                                                NULL,
45                                                GTK_FILE_CHOOSER_ACTION_SAVE,
46                                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
47                                                GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
48                                                NULL);
49   if ( last_folder_uri )
50     gtk_file_chooser_set_current_folder_uri ( GTK_FILE_CHOOSER(file_selector), last_folder_uri );
51
52   gtk_file_chooser_set_current_name ( GTK_FILE_CHOOSER(file_selector), default_name );
53
54   while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT )
55   {
56     fn = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER(file_selector) );
57     if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE ||
58          a_dialog_yes_or_no ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
59     {
60       g_free ( last_folder_uri );
61       last_folder_uri = gtk_file_chooser_get_current_folder_uri ( GTK_FILE_CHOOSER(file_selector) );
62
63       gtk_widget_hide ( file_selector );
64       vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );
65       // Don't Export invisible items - unless requested on this specific track
66       failed = ! a_file_export ( vtl, fn, file_type, trk, trk ? TRUE : FALSE );
67       vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );
68       break;
69     }
70   }
71   gtk_widget_destroy ( file_selector );
72   if ( failed )
73     a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("The filename you requested could not be opened for writing.") );
74 }
75
76
77 /**
78  * Convert the given TRW layer into a temporary GPX file and open it with the specified program
79  *
80  */
81 void vik_trw_layer_export_external_gpx ( VikTrwLayer *vtl, const gchar* external_program )
82 {
83   // Don't Export invisible items
84   static GpxWritingOptions options = { TRUE, TRUE, FALSE, FALSE };
85   gchar *name_used = a_gpx_write_tmp_file ( vtl, &options );
86
87   if ( name_used ) {
88     GError *err = NULL;
89     gchar *quoted_file = g_shell_quote ( name_used );
90     gchar *cmd = g_strdup_printf ( "%s %s", external_program, quoted_file );
91     g_free ( quoted_file );
92     if ( ! g_spawn_command_line_async ( cmd, &err ) ) {
93       a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_LAYER( vtl), _("Could not launch %s."), external_program );
94       g_error_free ( err );
95     }
96     g_free ( cmd );
97     util_add_to_deletion_list ( name_used );
98     g_free ( name_used );
99   }
100   else
101     a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Could not create temporary file for export.") );
102 }
103
104
105 void vik_trw_layer_export_gpsbabel ( VikTrwLayer *vtl, const gchar *title, const gchar* default_name )
106 {
107   BabelMode mode = { 0, 0, 0, 0, 0, 0 };
108   if ( g_hash_table_size (vik_trw_layer_get_routes(vtl)) ) {
109       mode.routesWrite = 1;
110   }
111   if ( g_hash_table_size (vik_trw_layer_get_tracks(vtl)) ) {
112       mode.tracksWrite = 1;
113   }
114   if ( g_hash_table_size (vik_trw_layer_get_waypoints(vtl)) ) {
115       mode.waypointsWrite = 1;
116   }
117
118   GtkWidget *file_selector;
119   const gchar *fn;
120   gboolean failed = FALSE;
121   file_selector = gtk_file_chooser_dialog_new (title,
122                                                NULL,
123                                                GTK_FILE_CHOOSER_ACTION_SAVE,
124                                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
125                                                GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
126                                                NULL);
127   gchar *cwd = g_get_current_dir();
128   if ( cwd ) {
129     gtk_file_chooser_set_current_folder ( GTK_FILE_CHOOSER(file_selector), cwd );
130     g_free ( cwd );
131   }
132
133   /* Build the extra part of the widget */
134   GtkWidget *babel_selector = a_babel_ui_file_type_selector_new ( mode );
135   GtkWidget *label = gtk_label_new(_("File format:"));
136   GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
137   gtk_box_pack_start ( GTK_BOX(hbox), label, TRUE, TRUE, 0 );
138   gtk_box_pack_start ( GTK_BOX(hbox), babel_selector, TRUE, TRUE, 0 );
139   gtk_widget_show (babel_selector);
140   gtk_widget_show (label);
141   gtk_widget_show_all (hbox);
142
143   gtk_widget_set_tooltip_text( babel_selector, _("Select the file format.") );
144
145   GtkWidget *babel_modes = a_babel_ui_modes_new(mode.tracksWrite, mode.routesWrite, mode.waypointsWrite);
146   gtk_widget_show (babel_modes);
147
148   gtk_widget_set_tooltip_text( babel_modes, _("Select the information to process.\n"
149       "Warning: the behavior of these switches is highly dependent of the file format selected.\n"
150       "Please, refer to GPSbabel if unsure.") );
151
152   GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
153   gtk_box_pack_start ( GTK_BOX(vbox), hbox, TRUE, TRUE, 0 );
154   gtk_box_pack_start ( GTK_BOX(vbox), babel_modes, TRUE, TRUE, 0 );
155   gtk_widget_show_all (vbox);
156
157   gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER(file_selector), vbox);
158
159   /* Add some dynamic: only allow dialog's validation when format selection is done */
160   g_signal_connect (babel_selector, "changed", G_CALLBACK(a_babel_ui_type_selector_dialog_sensitivity_cb), file_selector);
161   /* Manually call the callback to fix the state */
162   a_babel_ui_type_selector_dialog_sensitivity_cb ( GTK_COMBO_BOX(babel_selector), file_selector);
163
164   /* Set possible name of the file */
165   gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(file_selector), default_name);
166
167   while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT )
168   {
169     fn = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(file_selector) );
170     if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE ||
171          a_dialog_yes_or_no ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
172     {
173       BabelFile *active = a_babel_ui_file_type_selector_get(babel_selector);
174       if (active == NULL) {
175           a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("You did not select a valid file format.") );
176       } else {
177         gtk_widget_hide ( file_selector );
178         vik_window_set_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );
179         gboolean tracks, routes, waypoints;
180         a_babel_ui_modes_get( babel_modes, &tracks, &routes, &waypoints );
181         failed = ! a_file_export_babel ( vtl, fn, active->name, tracks, routes, waypoints );
182         vik_window_clear_busy_cursor ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)) );
183         break;
184       }
185     }
186   }
187   //babel_ui_selector_destroy(babel_selector);
188   gtk_widget_destroy ( file_selector );
189   if ( failed )
190     a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("The filename you requested could not be opened for writing.") );
191 }