]> git.street.me.uk Git - andy/viking.git/blob - src/datasource_gps.c
Add support for acquiring OpenStreetMap Notes as GPX files.
[andy/viking.git] / src / datasource_gps.c
1 /*
2  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3  *
4  * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5  * Copyright (C) 2006, Alex Foobarian <foobarian@gmail.com>
6  * Copyright (C) 2012, Rob Norris <rw_norris@hotmail.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 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <string.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30
31 #include <glib/gstdio.h>
32 #include <glib/gprintf.h>
33 #include <glib/gi18n.h>
34
35 #include "datasource_gps.h"
36 #include "viking.h"
37 #include "babel.h"
38 #include "gpx.h"
39 #include "acquire.h"
40
41 static gboolean gps_acquire_in_progress = FALSE;
42
43 static gint last_active = -1;
44 static gboolean last_get_tracks = TRUE;
45 static gboolean last_get_routes = TRUE;
46 static gboolean last_get_waypoints = TRUE;
47
48 static gpointer datasource_gps_init_func ( acq_vik_t *avt );
49 static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file, gpointer not_used );
50 static void datasource_gps_cleanup ( gpointer user_data );
51 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
52 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
53 static void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data );
54 static void datasource_gps_off ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
55
56 VikDataSourceInterface vik_datasource_gps_interface = {
57   N_("Acquire from GPS"),
58   N_("Acquired from GPS"),
59   VIK_DATASOURCE_CREATENEWLAYER,
60   VIK_DATASOURCE_INPUTTYPE_NONE,
61   TRUE,
62   TRUE,
63   TRUE,
64   (VikDataSourceInitFunc)               datasource_gps_init_func,
65   (VikDataSourceCheckExistenceFunc)     NULL,
66   (VikDataSourceAddSetupWidgetsFunc)    datasource_gps_add_setup_widgets,
67   (VikDataSourceGetCmdStringFunc)       datasource_gps_get_cmd_string,
68   (VikDataSourceProcessFunc)        a_babel_convert_from,
69   (VikDataSourceProgressFunc)           datasource_gps_progress,
70   (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
71   (VikDataSourceCleanupFunc)            datasource_gps_cleanup,
72   (VikDataSourceOffFunc)                datasource_gps_off
73 };
74
75 /*********************************************************
76  * Definitions and routines for acquiring data from GPS
77  *********************************************************/
78
79 /* widgets in setup dialog specific to GPS */
80 /* widgets in progress dialog specific to GPS */
81 /* also counts needed for progress */
82 typedef struct {
83   /* setup dialog */
84   GtkWidget *proto_l;
85   GtkWidget *proto_b;
86   GtkWidget *ser_l;
87   GtkWidget *ser_b;
88   GtkWidget *off_request_l;
89   GtkCheckButton *off_request_b;
90   GtkWidget *get_tracks_l;
91   GtkCheckButton *get_tracks_b;
92   GtkWidget *get_routes_l;
93   GtkCheckButton *get_routes_b;
94   GtkWidget *get_waypoints_l;
95   GtkCheckButton *get_waypoints_b;
96
97   /* progress dialog */
98   GtkWidget *gps_label;
99   GtkWidget *ver_label;
100   GtkWidget *id_label;
101   GtkWidget *wp_label;
102   GtkWidget *trk_label;
103   GtkWidget *rte_label;
104   GtkWidget *progress_label;
105   vik_gps_xfer_type progress_type;
106
107   /* state */
108   int total_count;
109   int count;
110 } gps_user_data_t;
111
112 static gpointer datasource_gps_init_func ( acq_vik_t *avt )
113 {
114   return g_malloc (sizeof(gps_user_data_t));
115 }
116
117 /**
118  * datasource_gps_get_protocol:
119  *
120  * Method to get the communication protocol of the GPS device from the widget structure
121  */
122 gchar* datasource_gps_get_protocol ( gpointer user_data )
123 {
124   // Uses the list of supported devices
125   gps_user_data_t *w = (gps_user_data_t *)user_data;
126   last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
127   if (a_babel_device_list)
128     return ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
129
130   return NULL;
131 }
132
133 /**
134  * datasource_gps_get_descriptor:
135  *
136  * Method to get the descriptor from the widget structure
137  * "Everything is a file"
138  * Could actually be normal file or a serial port
139  */
140 gchar* datasource_gps_get_descriptor ( gpointer user_data )
141 {
142   gps_user_data_t *w = (gps_user_data_t *)user_data;
143
144 #if GTK_CHECK_VERSION (2, 24, 0)
145   return gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w->ser_b));
146 #else
147   return gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
148 #endif
149 }
150
151 /**
152  * datasource_gps_get_do_tracks:
153  *
154  * Method to get the track handling behaviour from the widget structure
155  */
156 gboolean datasource_gps_get_do_tracks ( gpointer user_data )
157 {
158   gps_user_data_t *w = (gps_user_data_t *)user_data;
159   last_get_tracks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_tracks_b));
160   return last_get_tracks;
161 }
162
163 /**
164  * datasource_gps_get_do_routes:
165  *
166  * Method to get the route handling behaviour from the widget structure
167  */
168 gboolean datasource_gps_get_do_routes ( gpointer user_data )
169 {
170   gps_user_data_t *w = (gps_user_data_t *)user_data;
171   last_get_routes = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_routes_b));
172   return last_get_routes;
173 }
174
175 /**
176  * datasource_gps_get_do_waypoints:
177  *
178  * Method to get the waypoint handling behaviour from the widget structure
179  */
180 gboolean datasource_gps_get_do_waypoints ( gpointer user_data )
181 {
182   gps_user_data_t *w = (gps_user_data_t *)user_data;
183   last_get_waypoints = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b));
184   return last_get_waypoints;
185 }
186
187 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file, gpointer not_used )
188 {
189   char *device = NULL;
190   char *tracks = NULL;
191   char *routes = NULL;
192   char *waypoints = NULL;
193
194   if (gps_acquire_in_progress) {
195     *babelargs = *input_file = NULL;
196   }
197   
198   gps_acquire_in_progress = TRUE;
199
200   device = datasource_gps_get_protocol ( user_data );
201
202   if ( datasource_gps_get_do_tracks ( user_data ) )
203     tracks = "-t";
204   else
205     tracks = "";
206
207   if ( datasource_gps_get_do_routes ( user_data ) )
208     routes = "-r";
209   else
210     routes = "";
211
212   if ( datasource_gps_get_do_waypoints ( user_data ) )
213     waypoints = "-w";
214   else
215     waypoints = "";
216
217   *babelargs = g_strdup_printf("-D 9 %s %s %s -i %s", tracks, routes, waypoints, device);
218   /* device points to static content => no free */
219   device = NULL;
220   tracks = NULL;
221   routes = NULL;
222   waypoints = NULL;
223
224   *input_file = g_strdup(datasource_gps_get_descriptor(user_data));
225
226   g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
227 }
228
229 /**
230  * datasource_gps_get_off:
231  *
232  * Method to get the off behaviour from the widget structure
233  */
234 gboolean datasource_gps_get_off ( gpointer user_data )
235 {
236   gps_user_data_t *w = (gps_user_data_t *)user_data;
237   return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b));
238 }
239
240 static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
241 {
242   char *ser = NULL;
243   char *device = NULL;
244   gps_user_data_t *w = (gps_user_data_t *)user_data;
245
246   if (gps_acquire_in_progress) {
247     *babelargs = *input_file = NULL;
248   }
249
250   /* See if we should turn off the device */
251   if (!datasource_gps_get_off ( user_data )){
252     return;
253   }
254   
255   if (!a_babel_device_list)
256     return;
257   last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
258   device = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
259   if (!strcmp(device, "garmin")) {
260     device = "garmin,power_off";
261   }
262   else if (!strcmp(device, "navilink")) {
263     device = "navilink,power_off";
264   }
265   else {
266     return;
267   }
268
269   *babelargs = g_strdup_printf("-i %s", device);
270   /* device points to static content => no free */
271   device = NULL;
272   
273 #if GTK_CHECK_VERSION (2, 24, 0)
274   ser = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w->ser_b));
275 #else
276   ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
277 #endif
278   *input_file = g_strdup(ser);
279 }
280
281
282 static void datasource_gps_cleanup ( gpointer user_data )
283 {
284   g_free ( user_data );
285   gps_acquire_in_progress = FALSE;
286 }
287
288 /**
289  * datasource_gps_clean_up:
290  *
291  * External method to tidy up
292  */
293 void datasource_gps_clean_up ( gpointer user_data )
294 {
295   datasource_gps_cleanup ( user_data );
296 }
297
298 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
299 {
300   gchar *s = NULL;
301   gdk_threads_enter();
302   if (w->running) {
303     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
304     const gchar *tmp_str;
305     switch (gps_data->progress_type) {
306     case WPT: tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt); gps_data->total_count = cnt; break;
307     case TRK: tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt); gps_data->total_count = cnt; break;
308     default:
309       {
310         // Maybe a gpsbabel bug/feature (upto at least v1.4.3 or maybe my Garmin device) but the count always seems x2 too many for routepoints
311         gint mycnt = (cnt / 2) + 1;
312         tmp_str = ngettext("Downloading %d routepoint...", "Downloading %d routepoints...", mycnt);
313         gps_data->total_count = mycnt;
314         break;
315       }
316     }
317     s = g_strdup_printf(tmp_str, cnt);
318     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
319     gtk_widget_show ( gps_data->progress_label );
320   }
321   g_free(s); s = NULL;
322   gdk_threads_leave();
323 }
324
325 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
326 {
327   gchar *s = NULL;
328   gdk_threads_enter();
329   if (w->running) {
330     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
331
332     if (cnt < gps_data->total_count) {
333       switch (gps_data->progress_type) {
334       case WPT: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "waypoints"); break;
335       case TRK: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "trackpoints"); break;
336       default: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "routepoints"); break;
337       }
338     } else {
339       switch (gps_data->progress_type) {
340       case WPT: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "waypoints"); break;
341       case TRK: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "trackpoints"); break;
342       default: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "routepoints"); break;
343       }
344     }
345     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
346   }
347   g_free(s); s = NULL;
348   gdk_threads_leave();
349 }
350
351 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
352 {
353   gchar *s = NULL;
354   gdk_threads_enter();
355   if (w->running) {
356     s = g_strdup_printf(_("GPS Device: %s"), info);
357     gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
358   }
359   g_free(s); s = NULL;
360   gdk_threads_leave();
361 }
362
363 /* 
364  * This routine relies on gpsbabel's diagnostic output to display the progress information. 
365  * These outputs differ when different GPS devices are used, so we will need to test
366  * them on several and add the corresponding support.
367  */
368 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
369 {
370   gchar *line;
371   gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
372
373   switch(c) {
374   case BABEL_DIAG_OUTPUT:
375     line = (gchar *)data;
376
377     gdk_threads_enter();
378     if (w->running) {
379       gtk_label_set_text ( GTK_LABEL(w->status), _("Status: Working...") );
380     }
381     gdk_threads_leave();
382
383     /* tells us the type of items that will follow */
384     if (strstr(line, "Xfer Wpt")) {
385       gps_data->progress_label = gps_data->wp_label;
386       gps_data->progress_type = WPT;
387     }
388     if (strstr(line, "Xfer Trk")) {
389       gps_data->progress_label = gps_data->trk_label;
390       gps_data->progress_type = TRK;
391     }
392     if (strstr(line, "Xfer Rte")) {
393       gps_data->progress_label = gps_data->rte_label;
394       gps_data->progress_type = RTE;
395     }
396
397     if (strstr(line, "PRDDAT")) {
398       gchar **tokens = g_strsplit(line, " ", 0);
399       gchar info[128];
400       int ilen = 0;
401       int i;
402       int n_tokens = 0;
403
404       while (tokens[n_tokens])
405         n_tokens++;
406
407       if (n_tokens > 8) {
408         for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
409           guint ch;
410           sscanf(tokens[i], "%x", &ch);
411           info[ilen++] = ch;
412         }
413         info[ilen++] = 0;
414         set_gps_info(info, w);
415       }
416       g_strfreev(tokens);
417     }
418     /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
419     if (strstr(line, "Unit:")) {
420       gchar **tokens = g_strsplit(line, "\t", 0);
421       int n_tokens = 0;
422       while (tokens[n_tokens])
423         n_tokens++;
424
425       if (n_tokens > 1) {
426         set_gps_info(tokens[1], w);
427       }
428       g_strfreev(tokens);
429     }
430     /* tells us how many items there will be */
431     if (strstr(line, "RECORD")) {
432       int lsb, msb, cnt;
433
434       if (strlen(line) > 20) {
435        sscanf(line+17, "%x", &lsb); 
436        sscanf(line+20, "%x", &msb);
437        cnt = lsb + msb * 256;
438        set_total_count(cnt, w);
439        gps_data->count = 0;
440       }
441     }
442     if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") || strstr(line, "RTEHDR") || strstr(line, "RTEWPT") ) {
443       gps_data->count++;
444       set_current_count(gps_data->count, w);
445     }
446     break;
447   case BABEL_DONE:
448     break;
449   default:
450     break;
451   }
452 }
453
454 void append_element (gpointer elem, gpointer user_data)
455 {
456   const gchar *text = ((BabelDevice*)elem)->label;
457   vik_combo_box_text_append (GTK_WIDGET(user_data), text);
458 }
459
460 static gint find_entry = -1;
461 static gint garmin_entry = -1;
462
463 static void find_garmin (gpointer elem, gpointer user_data)
464 {
465   const gchar *name = ((BabelDevice*)elem)->name;
466   find_entry++;
467   if (!strcmp(name, "garmin")) {
468     garmin_entry = find_entry;
469   }
470 }
471
472 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
473 {
474   gps_user_data_t *w = (gps_user_data_t *)user_data;
475   GtkTable *box, *data_type_box;
476
477   w->proto_l = gtk_label_new (_("GPS Protocol:"));
478   w->proto_b = vik_combo_box_text_new ();
479   g_list_foreach (a_babel_device_list, append_element, w->proto_b);
480
481   // Maintain default to Garmin devices (assumed most popular/numerous device)
482   if ( last_active < 0 ) {
483     find_entry = -1;
484     g_list_foreach (a_babel_device_list, find_garmin, NULL);
485     if ( garmin_entry < 0 )
486       // Not found - so set it to the first entry
487       last_active = 0;
488     else
489       // Found
490       last_active = garmin_entry;
491   }
492
493   gtk_combo_box_set_active (GTK_COMBO_BOX(w->proto_b), last_active);
494   g_object_ref(w->proto_b);
495
496   w->ser_l = gtk_label_new (_("Serial Port:"));
497 #if GTK_CHECK_VERSION (2, 24, 0)
498   w->ser_b = gtk_combo_box_text_new_with_entry ();
499 #else
500   w->ser_b = gtk_combo_box_entry_new_text ();
501 #endif
502 #ifdef WINDOWS
503   vik_combo_box_text_append (w->ser_b, "com1");
504 #else
505   /* Here just try to see if the device is available which gets passed onto gpsbabel
506      List USB devices first as these will generally only be present if autogenerated by udev or similar
507      User is still able to set their own free text entry */
508   if (g_access ("/dev/ttyUSB0", R_OK) == 0)
509     vik_combo_box_text_append (w->ser_b, "/dev/ttyUSB0");
510   if (g_access ("/dev/ttyUSB1", R_OK) == 0)
511     vik_combo_box_text_append (w->ser_b, "/dev/ttyUSB1");
512   if (g_access ("/dev/ttyS0", R_OK) == 0)
513     vik_combo_box_text_append (w->ser_b, "/dev/ttyS0");
514   if (g_access ("/dev/ttyS1", R_OK) == 0)
515     vik_combo_box_text_append (w->ser_b, "/dev/ttyS1");
516 #endif
517   vik_combo_box_text_append (w->ser_b, "usb:");
518   gtk_combo_box_set_active (GTK_COMBO_BOX(w->ser_b), 0);
519   g_object_ref(w->ser_b);
520
521   w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin/NAViLink Only)"));
522   w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
523
524   w->get_tracks_l = gtk_label_new (_("Tracks:"));
525   w->get_tracks_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
526   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_tracks_b), last_get_tracks);
527
528   w->get_routes_l = gtk_label_new (_("Routes:"));
529   w->get_routes_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
530   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_routes_b), last_get_routes);
531
532   w->get_waypoints_l = gtk_label_new (_("Waypoints:"));
533   w->get_waypoints_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
534   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b), last_get_waypoints);
535
536   box = GTK_TABLE(gtk_table_new(2, 4, FALSE));
537   data_type_box = GTK_TABLE(gtk_table_new(4, 1, FALSE));
538
539   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
540   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
541   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
542   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
543   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_l), 0, 1, 0, 1);
544   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_b), 1, 2, 0, 1);
545   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_l), 2, 3, 0, 1);
546   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_b), 3, 4, 0, 1);
547   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_l), 4, 5, 0, 1);
548   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_b), 5, 6, 0, 1);
549   gtk_table_attach_defaults(box, GTK_WIDGET(data_type_box), 0, 2, 2, 3);
550   gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 3, 4);
551   gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 3, 4);
552   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GTK_WIDGET(box), FALSE, FALSE, 5 );
553
554   gtk_widget_show_all ( dialog );
555 }
556
557 /**
558  * datasource_gps_setup:
559  * @dialog: The GTK dialog. The caller is responsible for managing the dialog creation/deletion
560  * @xfer: The default type of items enabled for transfer, others disabled.
561  * @xfer_all: When specified all items are enabled for transfer.
562  *
563  * Returns: A gpointer to the private structure for GPS progress/information widgets
564  *          Pass this pointer back into the other exposed datasource_gps_X functions
565  */
566 gpointer datasource_gps_setup ( GtkWidget *dialog, vik_gps_xfer_type xfer, gboolean xfer_all )
567 {
568   gps_user_data_t *w_gps = (gps_user_data_t *)datasource_gps_init_func ( NULL );
569   datasource_gps_add_setup_widgets ( dialog, NULL, w_gps );
570
571   gboolean way = xfer_all;
572   gboolean trk = xfer_all;
573   gboolean rte = xfer_all;
574
575   // Selectively turn bits on
576   if ( !xfer_all ) {
577     switch (xfer) {
578     case WPT: way = TRUE; break;
579     case RTE: rte = TRUE; break;
580     default: trk = TRUE; break;
581     }
582   }
583
584   // Apply
585   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_tracks_b), trk );
586   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_l), trk );
587   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_b), trk );
588
589   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_routes_b), rte );
590   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_l), rte );
591   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_b), rte );
592
593   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_waypoints_b), way );
594   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_l), way );
595   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_b), way );
596
597   return (gpointer)w_gps;
598 }
599
600 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
601 {
602   GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel, *rtelabel;
603
604   gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
605
606   gpslabel = gtk_label_new (_("GPS device: N/A"));
607   verlabel = gtk_label_new ("");
608   idlabel = gtk_label_new ("");
609   wplabel = gtk_label_new ("");
610   trklabel = gtk_label_new ("");
611   rtelabel = gtk_label_new ("");
612
613   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), gpslabel, FALSE, FALSE, 5 );
614   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), wplabel, FALSE, FALSE, 5 );
615   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), trklabel, FALSE, FALSE, 5 );
616   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), rtelabel, FALSE, FALSE, 5 );
617
618   gtk_widget_show_all ( dialog );
619
620   w_gps->gps_label = gpslabel;
621   w_gps->id_label = idlabel;
622   w_gps->ver_label = verlabel;
623   w_gps->progress_label = w_gps->wp_label = wplabel;
624   w_gps->trk_label = trklabel;
625   w_gps->rte_label = rtelabel;
626   w_gps->total_count = -1;
627 }