Contents of /trunk/src/geotoad.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 252 - (hide annotations)
Thu Feb 4 20:15:19 2010 UTC (14 years, 3 months ago) by harbaum
File MIME type: text/plain
File size: 19211 byte(s)
Geotoad fixes
1 harbaum 193 /*
2     * Copyright (C) 2009 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of GPXView.
5     *
6     * GPXView is free software: you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * GPXView is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with GPXView. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include "gpxview.h"
21    
22 harbaum 206 #define __USE_GNU
23     #include <string.h>
24    
25 harbaum 193 #include <fcntl.h>
26     #include <sys/types.h>
27     #include <sys/wait.h>
28     #include <errno.h>
29 harbaum 198 #include <math.h>
30 harbaum 193
31 harbaum 198 #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)
32     #include <hildon/hildon-entry.h>
33     #endif
34    
35 harbaum 196 #define GEOTOAD "/usr/bin/geotoad"
36    
37 harbaum 195 #define COLOR_ERR "red"
38     #define COLOR_OK "darkgreen"
39     #define COLOR_SYSTEM "darkblue"
40 harbaum 194
41 harbaum 195 #define BUFFER_SIZE 256
42 harbaum 193
43 harbaum 206 typedef enum {
44     GT_STATE_ILLEGAL = 0,
45     GT_STATE_STARTED,
46     GT_STATE_PREMATURE_END,
47     GT_STATE_SAVE_FOUND,
48     } gt_state_t;
49    
50 harbaum 193 typedef struct {
51 harbaum 194 appdata_t *appdata;
52 harbaum 206
53     GPtrArray *argv;
54 harbaum 207 gchar *info, *color;
55 harbaum 206 GMutex *update_mutex;
56     GCond *update_cond;
57 harbaum 194
58 harbaum 206 gt_state_t state;
59    
60 harbaum 198 GtkWidget *dialog;
61    
62 harbaum 206 long pid;
63 harbaum 193
64 harbaum 194 struct log_s {
65     GtkTextBuffer *buffer;
66     GtkWidget *view;
67     } log;
68 harbaum 196
69 harbaum 233 GtkWidget *username, *password;
70 harbaum 252 GtkWidget *lat, *lon, *dst, *no_of;
71 harbaum 233 char *filename;
72 harbaum 208
73     int use_cnt;
74 harbaum 194
75 harbaum 193 } gt_context_t;
76    
77 harbaum 206 static void arg_free(gpointer data, gpointer user_data) {
78     if(data) g_free(data);
79     }
80    
81     static void context_free(gt_context_t *context) {
82 harbaum 208 context->use_cnt--;
83    
84     if(context->use_cnt > 0)
85     printf("still in use by %d, keeping context\n", context->use_cnt);
86     else {
87     printf("freeing context\n");
88 harbaum 206
89 harbaum 208 if(context->info) g_free(context->info);
90 harbaum 206
91 harbaum 212 if(context->argv) {
92     g_ptr_array_foreach(context->argv, arg_free, NULL);
93     g_ptr_array_free (context->argv, TRUE);
94     }
95 harbaum 206
96 harbaum 233 if(context->filename) g_free(context->filename);
97    
98 harbaum 208 g_free(context);
99     }
100 harbaum 206 }
101    
102 harbaum 194 static void appendf(struct log_s *log, char *colname,
103     const char *fmt, ...) {
104     va_list args;
105     va_start( args, fmt );
106     char *buf = g_strdup_vprintf(fmt, args);
107     va_end( args );
108    
109 harbaum 207 // printf("append: %s", buf);
110 harbaum 195
111 harbaum 194 GtkTextTag *tag = NULL;
112     if(colname)
113     tag = gtk_text_buffer_create_tag(log->buffer, NULL,
114     "foreground", colname,
115     NULL);
116    
117     GtkTextIter end;
118     gtk_text_buffer_get_end_iter(log->buffer, &end);
119     if(tag)
120     gtk_text_buffer_insert_with_tags(log->buffer, &end, buf, -1, tag, NULL);
121     else
122     gtk_text_buffer_insert(log->buffer, &end, buf, -1);
123    
124     g_free(buf);
125    
126     gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(log->view),
127 harbaum 211 &end, 0.0, TRUE, 1.0, 1.0);
128 harbaum 194 }
129    
130 harbaum 206 // This function receives a requst from a worker thread asking to
131     // update the gui with the required info.
132     gboolean cb_update_job(gt_context_t *context) {
133     if (context->info) {
134 harbaum 207
135     /* check if client reports "saved to ..." */
136     if(strstr(context->info, "Saved to "))
137 harbaum 206 context->state = GT_STATE_SAVE_FOUND;
138 harbaum 193
139 harbaum 207 appendf(&context->log, context->color, context->info);
140 harbaum 206
141     g_free(context->info);
142     context->info = NULL;
143     }
144    
145     // Indicate that the update is done
146     g_mutex_lock(context->update_mutex);
147     g_cond_signal(context->update_cond);
148     g_mutex_unlock(context->update_mutex);
149    
150     return FALSE;
151     }
152 harbaum 193
153 harbaum 206 // A helper function run in the job thread receiving the string that
154     // should be displayed in the textview.
155 harbaum 207 void append_parentf(gt_context_t *context, char *colname,
156     const char *fmt, ...) {
157     va_list args;
158     va_start( args, fmt );
159     context->info = g_strdup_vprintf(fmt, args);
160     va_end( args );
161    
162     if(colname)
163     context->color = colname;
164     else
165     context->color = NULL;
166    
167 harbaum 206 // Lock mutex to make sure that we will receive the condition signal
168     g_mutex_lock(context->update_mutex);
169 harbaum 207
170 harbaum 206 g_idle_add((GSourceFunc)cb_update_job, context);
171    
172     // Wait for cb_update_job to tell me that the update is done
173 harbaum 207 g_cond_wait(context->update_cond, context->update_mutex);
174 harbaum 206 g_mutex_unlock(context->update_mutex);
175 harbaum 193 }
176    
177 harbaum 206 /* custom version of popen to get access to the pid and to be able */
178     /* to slaughter the child process */
179 harbaum 207 static FILE *gt_popen(gt_context_t *context, char **args,
180     const char *type, long *tid) {
181 harbaum 206 int p[2];
182     FILE *fp;
183    
184     if (*type != 'r' && *type != 'w')
185     return NULL;
186    
187     if (pipe(p) < 0)
188     return NULL;
189    
190     if ((*tid = fork()) > 0) { /* then we are the parent */
191     if (*type == 'r') {
192     close(p[1]);
193     fp = fdopen(p[0], type);
194     } else {
195     close(p[0]);
196     fp = fdopen(p[1], type);
197     }
198    
199     return fp;
200     } else if (*tid == 0) { /* we're the child */
201 harbaum 193
202 harbaum 206 /* make our thread id the process group leader */
203     setpgid(0, 0);
204 harbaum 193
205 harbaum 206 if (*type == 'r') {
206     fflush(stdout);
207     fflush(stderr);
208     close(1);
209     if (dup(p[1]) < 0)
210     perror("dup of write side of pipe failed");
211     close(2);
212     if (dup(p[1]) < 0)
213     perror("dup of write side of pipe failed");
214     } else {
215     close(0);
216     if (dup(p[0]) < 0)
217     perror("dup of read side of pipe failed");
218 harbaum 193 }
219 harbaum 206
220     close(p[0]); /* close since we dup()'ed what we needed */
221     close(p[1]);
222    
223     execve(args[0], args, NULL);
224    
225 harbaum 207 /* this printf will actually be redirected through the pipe */
226     printf("Error: Failed to execute!\n");
227 harbaum 210 exit(1);
228 harbaum 206 } else { /* we're having major problems... */
229     close(p[0]);
230     close(p[1]);
231 harbaum 207
232 harbaum 208 /* this printf will actually be redirected through the pipe??? No! */
233 harbaum 207 printf("Error: Failed to fork!\n");
234 harbaum 206 }
235    
236     return NULL;
237     }
238 harbaum 193
239 harbaum 206 // The thread entry point. It will do the job, send the data to the
240     // GUI and self destruct when it is done.
241     static gpointer thread_worker(gt_context_t *context)
242     {
243     FILE *fh;
244     GIOStatus status;
245     GError *error = NULL;
246     gsize length;
247     gsize terminator_pos;
248     gchar *str_return;
249 harbaum 193
250 harbaum 207 fh = gt_popen(context, (char**)(context->argv->pdata),"r", &context->pid);
251 harbaum 206 if(!fh) {
252 harbaum 208 printf("fail free\n");
253     context_free(context);
254     // g_thread_exit(NULL);
255 harbaum 206 return NULL;
256 harbaum 193 }
257    
258 harbaum 208 /* the client is running */
259     printf("client inc use_cnt\n");
260     context->use_cnt++;
261    
262 harbaum 206 /* switch to line buffered mode */
263     if(setvbuf(fh, NULL, _IOLBF, 0))
264     perror("setvbuf(_IOLBF)");
265    
266     GIOChannel *gh = g_io_channel_unix_new(fileno(fh));
267 harbaum 193
268 harbaum 206 while( (status = g_io_channel_read_line(gh,
269     &str_return,
270     &length,
271     &terminator_pos,
272     &error)) == G_IO_STATUS_NORMAL) {
273 harbaum 207 char *color = NULL;
274     if(strstr(str_return, "Saved to ")) color = COLOR_OK;
275     if(strcasestr(str_return, "error")) color = COLOR_ERR;
276    
277     append_parentf(context, color, str_return);
278 harbaum 206 g_free(str_return);
279     }
280    
281     g_io_channel_unref(gh);
282     pclose(fh);
283 harbaum 207 append_parentf(context, COLOR_SYSTEM, "Job done!");
284 harbaum 208
285 harbaum 206 context_free(context);
286    
287 harbaum 210 g_thread_exit(NULL);
288 harbaum 206 return NULL;
289 harbaum 200 }
290    
291 harbaum 206
292 harbaum 200 static void arg_dsp(gpointer data, gpointer user_data) {
293     gt_context_t *context = (gt_context_t*)user_data;
294    
295     if(data)
296     appendf(&context->log, COLOR_SYSTEM, "%s\n", data);
297     }
298    
299 harbaum 194 static void run(gt_context_t *context) {
300 harbaum 206 GError *error = NULL;
301 harbaum 200
302 harbaum 194 /* build list of arguments to call geotoad */
303 harbaum 206 context->argv = g_ptr_array_new();
304 harbaum 210 g_ptr_array_add (context->argv, g_strdup_printf(GEOTOAD));
305     g_ptr_array_add (context->argv,
306 harbaum 252 g_strdup_printf("--distanceMax=%u",
307     (int)ceil(context->appdata->gt.distance)));
308 harbaum 210 g_ptr_array_add (context->argv,
309     g_strdup_printf("--output=%s", context->appdata->gt.filename));
310     g_ptr_array_add (context->argv,
311     g_strdup_printf("--password=%s", context->appdata->gt.password));
312     g_ptr_array_add (context->argv,
313     g_strdup_printf("--queryType=coord"));
314     g_ptr_array_add (context->argv,
315     g_strdup_printf("--user=%s", context->appdata->username));
316 harbaum 194
317 harbaum 252 if(context->appdata->gt.no_owned_found) {
318     g_ptr_array_add (context->argv,
319     g_strdup_printf("--userExclude=%s", context->appdata->username));
320     g_ptr_array_add (context->argv,
321     g_strdup_printf("--ownerExclude=%s", context->appdata->username));
322     }
323    
324 harbaum 194 /* check if we need to add proxy config */
325     char *proxy = NULL;
326 harbaum 211
327 harbaum 194 if(context->appdata->proxy && context->appdata->proxy->host) {
328     if(context->appdata->proxy->use_authentication &&
329     context->appdata->proxy->authentication_user &&
330     context->appdata->proxy->authentication_password)
331     proxy = g_strdup_printf("--proxy=http://%s:%s@%s:%d",
332 harbaum 206 context->appdata->proxy->authentication_user,
333     context->appdata->proxy->authentication_password,
334     context->appdata->proxy->host,
335     context->appdata->proxy->port);
336 harbaum 194 else
337     proxy = g_strdup_printf("--proxy=http://%s:%d",
338 harbaum 206 context->appdata->proxy->host,
339     context->appdata->proxy->port);
340 harbaum 194
341 harbaum 211 } else {
342     /* use environment settings if preset (for scratchbox) */
343     const char *proxy_env = g_getenv("http_proxy");
344     if(proxy_env)
345     proxy = g_strdup_printf("--proxy=%s", proxy_env);
346     }
347    
348     if(proxy)
349 harbaum 206 g_ptr_array_add (context->argv, proxy);
350 harbaum 194
351 harbaum 206 /* convert coordinates into simple ascii format */
352     char n = (context->appdata->gt.lat >= 0)?'N':'S';
353     char e = (context->appdata->gt.lon >= 0)?'E':'W';
354     float lat = fabs(context->appdata->gt.lat);
355     float lon = fabs(context->appdata->gt.lon);
356     float lat_mint, lat_int, lat_frac = modff(lat, &lat_int);
357     float lon_mint, lon_int, lon_frac = modff(lon, &lon_int);
358     lat_frac = modff(lat_frac*60.0, &lat_mint);
359     lon_frac = modff(lon_frac*60.0, &lon_mint);
360 harbaum 194
361 harbaum 206 g_ptr_array_add (context->argv,
362     g_strdup_printf("%c%02u %02u.%03u %c%03u %02u.%03u",
363     n, (int)lat_int, (int)lat_mint, (int)(lat_frac*1000.0+0.5),
364     e, (int)lon_int, (int)lon_mint, (int)(lon_frac*1000.0+0.5)));
365    
366     g_ptr_array_add (context->argv, NULL);
367    
368 harbaum 200 /* show all entries */
369 harbaum 206 g_ptr_array_foreach(context->argv, arg_dsp, context);
370 harbaum 200
371 harbaum 206 g_thread_create((GThreadFunc)thread_worker, context, FALSE, &error);
372     if (error) {
373     appendf(&context->log, COLOR_ERR, "Error: %s\n", error->message);
374 harbaum 193 g_error_free(error);
375     }
376     }
377 harbaum 194
378 harbaum 196 /* show text window and display output of running geotoad */
379     static void gui_run(gt_context_t *context) {
380     GtkWidget *dialog = gtk_dialog_new_with_buttons(_("GeoToad - Run"),
381     GTK_WINDOW(context->appdata->window),
382 harbaum 194 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
383     GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
384     NULL);
385    
386     gtk_window_set_default_size(GTK_WINDOW(dialog), 640, 480);
387    
388     #ifndef USE_PANNABLE_AREA
389     GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
390     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
391     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
392     #else
393     GtkWidget *pannable_area = hildon_pannable_area_new();
394     #endif
395    
396     context->log.buffer = gtk_text_buffer_new(NULL);
397    
398     #ifndef USE_HILDON_TEXT_VIEW
399     context->log.view = gtk_text_view_new_with_buffer(context->log.buffer);
400     #else
401     context->log.view = hildon_text_view_new();
402     hildon_text_view_set_buffer(HILDON_TEXT_VIEW(context->log.view),
403     context->log.buffer);
404     #endif
405    
406     #ifndef USE_PANNABLE_AREA
407     gtk_container_add(GTK_CONTAINER(scrolled_window), context->log.view);
408     gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(scrolled_window),
409     GTK_SHADOW_IN);
410    
411     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
412     scrolled_window, TRUE, TRUE, 0);
413     #else
414     gtk_container_add(GTK_CONTAINER(pannable_area), context->log.view);
415     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
416     pannable_area, TRUE, TRUE, 0);
417     #endif
418    
419     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
420    
421     gtk_widget_show_all(dialog);
422    
423 harbaum 195 appendf(&context->log, COLOR_SYSTEM, "Running GeoToad\n");
424 harbaum 194 run(context);
425    
426     gtk_dialog_run(GTK_DIALOG(dialog));
427    
428     gtk_widget_destroy(dialog);
429     }
430 harbaum 196
431 harbaum 233 static void table_attach(GtkWidget *table, GtkWidget *child, int left, int top) {
432     gtk_table_attach_defaults(GTK_TABLE(table), child, left, left+1, top, top+1);
433 harbaum 198 }
434    
435 harbaum 233
436 harbaum 196 static gboolean gui_setup(gt_context_t *context) {
437 harbaum 198 appdata_t *appdata = context->appdata;
438 harbaum 196 gboolean ok = FALSE;
439    
440 harbaum 198 /* if no filename has been setup yet, create one */
441     if(!appdata->gt.filename && appdata->path) {
442     printf("creating path\n");
443     appdata->gt.filename =
444     g_strdup_printf("%s/gtoad.gpx", appdata->path);
445     }
446 harbaum 196
447 harbaum 233 if(appdata->gt.filename)
448     context->filename = g_strdup(appdata->gt.filename);
449    
450 harbaum 198 context->dialog = gtk_dialog_new_with_buttons(_("GeoToad - Setup"),
451     GTK_WINDOW(appdata->window),
452     GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
453     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
454     GTK_STOCK_OK, GTK_RESPONSE_OK,
455     NULL);
456    
457 harbaum 233 GtkWidget *table = gtk_table_new(5, 2, FALSE);
458    
459 harbaum 198 /* ------------------- Coordinates ------------------------- */
460    
461 harbaum 233 table_attach(table, left_label_new(_("Position:")), 0, 0);
462     table_attach(table, left_label_new(_("Distance:")), 0, 1);
463 harbaum 198
464     /* setup default positions */
465     pos_t *refpos = get_pos(appdata);
466     if((isnan(appdata->gt.lat) || isnan(appdata->gt.lat)) && refpos) {
467     appdata->gt.lat = refpos->lat;
468     appdata->gt.lon = refpos->lon;
469     }
470    
471 harbaum 233 GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
472 harbaum 198 context->lat = lat_entry_new(appdata->gt.lat);
473 harbaum 233 gtk_box_pack_start_defaults(GTK_BOX(hbox), context->lat);
474 harbaum 199 context->lon = lon_entry_new(appdata->gt.lon);
475 harbaum 233 gtk_box_pack_start_defaults(GTK_BOX(hbox), context->lon);
476 harbaum 221 GtkWidget *popup = preset_coordinate_picker(appdata, context->lat, context->lon);
477 harbaum 233 gtk_box_pack_start_defaults(GTK_BOX(hbox), popup);
478     table_attach(table, hbox, 1, 0);
479    
480 harbaum 252 hbox = gtk_hbox_new(FALSE, 0);
481     float dst = appdata->gt.distance; // distance is given in miles
482     if(!appdata->imperial) dst *= 1.609344;
483 harbaum 200 context->dst = dist_entry_new(dst, appdata->imperial);
484 harbaum 252 gtk_box_pack_start_defaults(GTK_BOX(hbox), context->dst);
485 harbaum 198
486 harbaum 252 context->no_of = check_button_new_with_label(_("No owned/found"));
487     check_button_set_active(context->no_of, appdata->gt.no_owned_found);
488     gtk_box_pack_start_defaults(GTK_BOX(hbox), context->no_of);
489    
490     table_attach(table, hbox, 1, 1);
491    
492 harbaum 198 /* ------------------- Username/Password ------------------------- */
493 harbaum 233 table_attach(table, left_label_new(_("Username:")), 0, 2);
494     table_attach(table, left_label_new(_("Password:")), 0, 3);
495 harbaum 196
496 harbaum 212 context->username = entry_new();
497     context->password = entry_new();
498 harbaum 196 gtk_entry_set_visibility(GTK_ENTRY(context->password), FALSE);
499    
500     /* set saved defaults */
501 harbaum 204 if(appdata->username)
502 harbaum 196 gtk_entry_set_text(GTK_ENTRY(context->username),
503 harbaum 204 appdata->username);
504 harbaum 196
505 harbaum 198 if(appdata->gt.password)
506 harbaum 196 gtk_entry_set_text(GTK_ENTRY(context->password),
507 harbaum 198 appdata->gt.password);
508 harbaum 196
509 harbaum 233 table_attach(table, context->username, 1, 2);
510     table_attach(table, context->password, 1, 3);
511 harbaum 196
512 harbaum 233 /* ------------------- file name ------------------------- */
513     gtk_table_attach_defaults(GTK_TABLE(table),
514     export_file(_("Save GPX file"), &context->filename),
515     0, 2, 4, 5);
516 harbaum 196
517 harbaum 233 /* ---------------------------------------------------------------- */
518     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox),
519     table);
520 harbaum 196
521 harbaum 233 gtk_dialog_set_default_response(GTK_DIALOG(context->dialog),
522     GTK_RESPONSE_OK);
523    
524 harbaum 198 gtk_widget_show_all(context->dialog);
525 harbaum 196
526 harbaum 198 if(gtk_dialog_run(GTK_DIALOG(context->dialog)) == GTK_RESPONSE_OK) {
527 harbaum 196
528 harbaum 200 /* parse coordinates */
529 harbaum 221 appdata->gt.lat = lat_entry_get(context->lat);
530     appdata->gt.lon = lon_entry_get(context->lon);
531 harbaum 200
532 harbaum 196 /* save values */
533 harbaum 204 if(appdata->username) g_free(appdata->username);
534     appdata->username =
535 harbaum 196 g_strdup(gtk_entry_get_text(GTK_ENTRY(context->username)));
536    
537 harbaum 198 if(appdata->gt.password) g_free(appdata->gt.password);
538     appdata->gt.password =
539 harbaum 196 g_strdup(gtk_entry_get_text(GTK_ENTRY(context->password)));
540    
541 harbaum 198 if(appdata->gt.filename) g_free(appdata->gt.filename);
542 harbaum 233 if(context->filename)
543     appdata->gt.filename = g_strdup(context->filename);
544 harbaum 198
545 harbaum 252 /* get distance in miles */
546     appdata->gt.distance = dist_entry_get(context->dst, TRUE);
547 harbaum 200
548 harbaum 252 /* get "no owned/found" state */
549     appdata->gt.no_owned_found = check_button_get_active(context->no_of);
550 harbaum 206
551     /* check for valid entries */
552     if(isnan(appdata->gt.lat) || isnan(appdata->gt.lon) ||
553     isnan(appdata->gt.distance) || !appdata->gt.filename ||
554     !appdata->username || !appdata->gt.password)
555 harbaum 211 errorf(_("The GeoToad setup is not complete."));
556 harbaum 206 else
557     ok = TRUE;
558 harbaum 196 }
559    
560 harbaum 198 gtk_widget_destroy(context->dialog);
561 harbaum 196
562     return ok;
563     }
564    
565     void geotoad(appdata_t *appdata) {
566     if(!geotoad_available()) {
567     errorf(_("GeoToad is not installed on this device.\n"
568     "You need to install it in order to be able to use it."));
569     return;
570     }
571    
572     gt_context_t *context = g_new0(gt_context_t, 1);
573     context->appdata = appdata;
574 harbaum 208 context->use_cnt++; // parent still uses this
575 harbaum 196
576 harbaum 206 context->update_mutex = g_mutex_new();
577     context->update_cond = g_cond_new();
578    
579 harbaum 196 if(gui_setup(context))
580     gui_run(context);
581 harbaum 208
582 harbaum 211 /* continue to process if something has actually been saved */
583     if(context->state == GT_STATE_SAVE_FOUND) {
584     /* download seems to be successful. Make sure the GUI is */
585     /* updated if required */
586    
587     gpx_t **gpx = &(appdata->gpx);
588     while(*gpx && strcmp((*gpx)->filename, appdata->gt.filename))
589     gpx = &(*gpx)->next;
590    
591 harbaum 223 /* return main GUI to GPX list */
592 harbaum 211 #ifdef USE_BREAD_CRUMB_TRAIL
593 harbaum 223 while(appdata->cur_gpx)
594     hildon_bread_crumb_trail_pop(HILDON_BREAD_CRUMB_TRAIL(appdata->bct));
595 harbaum 211 #elif defined(BCT)
596 harbaum 223 while(appdata->cur_gpx)
597     bct_pop(appdata->bct);
598 harbaum 211 #else
599 harbaum 223 HildonWindowStack *stack = hildon_window_stack_get_default();
600     gint num = hildon_window_stack_size(stack)-1;
601     while(num--) {
602     GtkWidget *top = hildon_window_stack_peek(stack);
603     gtk_widget_destroy(top);
604     }
605 harbaum 211 #endif
606    
607 harbaum 223 /* replace an existing entry or add to end of list */
608     if(*gpx) {
609 harbaum 211 GtkTreeIter iter;
610     g_assert(gpxlist_find(appdata, &iter, *gpx));
611    
612     gpx_t *next = (*gpx)->next;
613    
614     gpx_free(*gpx);
615     *gpx = gpx_parse(NULL, appdata->gt.filename, appdata->username);
616     (*gpx)->next = next;
617    
618     /* update gpxlist */
619     gpxlist_set(appdata->gpxstore, &iter, *gpx);
620    
621     /* select that row */
622     GtkTreeSelection *selection =
623     gtk_tree_view_get_selection(GTK_TREE_VIEW(appdata->gpxview));
624     gtk_tree_selection_select_iter(selection, &iter);
625     GtkTreePath *path =
626     gtk_tree_model_get_path(GTK_TREE_MODEL(appdata->gpxstore), &iter);
627     gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(appdata->gpxview),
628     path, NULL, TRUE, 0.0, 0.0);
629     gtk_tree_path_free(path);
630 harbaum 223 } else {
631     gpx_t *new = gpx_parse(NULL, appdata->gt.filename, appdata->username);
632     if(new) gpxlist_add(appdata, new);
633     }
634 harbaum 212 }
635 harbaum 211
636 harbaum 208 printf("main context free\n");
637     context_free(context);
638 harbaum 196 }
639    
640     gboolean geotoad_available(void) {
641     /* before doing anything make sure geotoad is installed */
642     return g_file_test(GEOTOAD, G_FILE_TEST_IS_EXECUTABLE);
643     }
644    
645