Contents of /trunk/src/mm_poi.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 179 - (hide annotations)
Thu Nov 12 20:51:33 2009 UTC (14 years, 6 months ago) by harbaum
File MIME type: text/plain
File size: 19766 byte(s)
More icon work
1 harbaum 1 /*
2     * Copyright (C) 2008 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     #include <math.h>
23     #include <sqlite3.h>
24    
25     static const char *cache_type_icons[] = {
26     "traditional", "multi", "mystery", "virtual",
27     "webcam", "event", "letterbox", "earthcache",
28     "wherigo", "megaevent", "cito", "" };
29    
30     static const char *cache_type_str[] = {
31     "Traditional", "Multi", "Mystery","Virtual", "Webcam", "Event",
32     "Letterbox", "Earthcache", "Wherigo","Megaevent", "CITO",""};
33    
34     static const char *cache_type_desc[] = {
35     "Traditional Caches", "Multi-Caches", "Unknown Caches",
36     "Virtual Caches", "Webcam Caches", "Event Caches",
37     "Letterbox Hybrids", "Earthcaches", "Wherigo Caches",
38     "Mega-Event Caches", "Cache In Trash Out Events",""};
39    
40     static const char *mode_str[] = {
41     "???", "the cache listing", "the list of caches", "all GPX files" };
42    
43     static int callback(void *NotUsed, int argc, char **argv, char **azColName){
44     int i;
45     NotUsed=0;
46    
47     for(i=0; i<argc; i++){
48     printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
49     }
50     printf("\n");
51     return 0;
52     }
53    
54     char *escape(char *str) {
55     if(!str) return NULL;
56    
57     char *result = malloc(strlen(str)+1);
58     char *p = result;
59    
60     while(*str) {
61     if(*str != '\'') *p++=*str++;
62     else { *p++='`'; str++; }
63     }
64     *p = 0;
65    
66     return result;
67     }
68    
69     /* export a single cache to the database */
70     static void cache_export(sqlite3 *db, int id, cache_t *cache) {
71     char *zErrMsg = 0;
72     char cmd[256];
73    
74     // printf("exporting %s: %s\n", cache->id, cache->name);
75    
76     char *desc = escape(cache->id); // short_description
77     if(!desc) desc = strdup(_("<none>"));
78    
79     char *name = escape(cache->name);
80     if(!name) desc = strdup(_("<none>"));
81    
82     pos_t pos = gpx_cache_pos(cache);
83     char strlon[32], strlat[32];
84     g_ascii_dtostr(strlat, sizeof(strlat), pos.lat);
85     g_ascii_dtostr(strlon, sizeof(strlon), pos.lon);
86    
87     snprintf(cmd, sizeof(cmd),
88     "insert into poi values (%d,%s,%s,'%s','%s',%d)",
89     id, strlat, strlon, name, desc, cache->type+12);
90    
91     if(sqlite3_exec(db,cmd, callback, 0, &zErrMsg) != SQLITE_OK)
92     errorf(_("Creating POI entry:\n\n%s"), zErrMsg);
93    
94     if(desc) free(desc);
95     if(name) free(name);
96     }
97    
98     /* add a cache to the chain of caches to be exported */
99     static void chain_cache(gpx_t *gpx, cache_t *cache) {
100     cache_t **cur = &gpx->cache;
101    
102     /* search end of chain */
103     while(*cur) {
104     if(strcmp(cache->id, (*cur)->id) == 0)
105     return;
106    
107     cur = &(*cur)->next;
108     }
109    
110     *cur = malloc(sizeof(cache_t));
111     if(!(*cur)) return;
112    
113     memcpy(*cur, cache, sizeof(cache_t));
114     (*cur)->next = NULL;
115     }
116    
117     static gpx_t *export_list_create(appdata_t *appdata, int *mode) {
118     gpx_t *gpx = g_new0(gpx_t,1);
119     *mode = 0;
120    
121     if(!gpx) return gpx;
122    
123     #ifdef USE_MAEMO
124     if(appdata->cur_cache) {
125     printf("cache display, exporting cache only!\n");
126     /* appdata->cur_cache */
127     chain_cache(gpx, appdata->cur_cache);
128     *mode = 1;
129     } else if(appdata->search_results) {
130     printf("search result display, exporting entire search result\n");
131     cache_t *cache = appdata->search_results->cache;
132     while(cache) { chain_cache(gpx, cache); cache = cache->next; }
133     *mode = 2;
134     } else if(appdata->cur_gpx) {
135     printf("cachelist display, exporting entire cachelist\n");
136     cache_t *cache = appdata->cur_gpx->cache;
137     while(cache) { chain_cache(gpx, cache); cache = cache->next; }
138     *mode = 2;
139     } else
140     #endif
141     {
142     printf("gpxlist display, exporting all caches\n");
143     gpx_t *lgpx = appdata->gpx;
144     while(lgpx) {
145     /* make sure notes are imported */
146     if(!lgpx->notes_loaded) {
147     notes_load_all(appdata, lgpx);
148     lgpx->notes_loaded = TRUE;
149     }
150    
151     cache_t *cache = lgpx->cache;
152     while(cache) { chain_cache(gpx, cache); cache = cache->next; }
153     lgpx = lgpx->next;
154     }
155     *mode = 3;
156     }
157    
158     return gpx;
159     }
160    
161     static void export_list_free(gpx_t *gpx) {
162     printf("freeing export list\n");
163    
164     cache_t *cache = gpx->cache;
165     while(cache) {
166     cache_t *tmp = cache;
167     cache = cache->next;
168     free(tmp);
169     }
170     free(gpx);
171     }
172    
173     static int export_list_count(appdata_t *appdata, gpx_t *gpx) {
174     pos_t *refpos = get_pos(appdata);
175     int cnt = 0;
176    
177     cache_t *cache = gpx->cache;
178     while(cache) {
179     /* no disabled/archived if requested */
180     if(!(appdata->mmpoi_dont_export_disabled &&
181     (!cache->available || cache->archived))) {
182    
183     /* no found if requested */
184     if(!(appdata->mmpoi_dont_export_found &&
185     cache->notes && cache->notes->found)) {
186    
187     if(appdata->mmpoi_use_radius && !isnan(appdata->mmpoi_radius)) {
188     /* count all caches within given radius around current position */
189     if(gpx_pos_get_distance(*refpos, gpx_cache_pos(cache), 0) <
190     appdata->mmpoi_radius)
191     cnt++;
192     } else
193     cnt++;
194     }
195    
196     }
197    
198     cache = cache->next;
199     }
200     return cnt;
201     }
202    
203     typedef struct {
204     GtkWidget *use_radius;
205     GtkWidget *no_found;
206     GtkWidget *no_disabled;
207     GtkWidget *entry;
208     GtkWidget *info_label;
209     GtkWidget *dialog;
210     appdata_t *appdata;
211     guint handler_id;
212     int mode;
213     gpx_t *gpx;
214     GtkWidget *path_label;
215     #ifdef USE_MAEMO
216     GtkWidget *launch;
217     #endif
218     } export_context_t;
219    
220     static float distance_eval(GtkWidget *widget, export_context_t *context) {
221     char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
222     float val = distance_parse(p, context->appdata->imperial);
223     return val;
224     }
225    
226     static gboolean export_list_update(gpointer data) {
227     char str[256];
228     export_context_t *context = (export_context_t*)data;
229    
230     printf("updating list ...\n");
231    
232     int cnum = export_list_count(context->appdata, context->gpx);
233     printf("About to export %d caches\n", cnum);
234    
235     snprintf(str, sizeof(str),
236     _("This will export %d caches from %s."),
237     cnum, _(mode_str[context->mode]));
238    
239     gtk_label_set_text(GTK_LABEL(context->info_label), str);
240    
241     return FALSE;
242     }
243    
244     /* Our usual callback function */
245     static void export_update(GtkWidget *widget, gpointer data) {
246     export_context_t *context = (export_context_t *)data;
247    
248     if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(context->use_radius))) {
249     textbox_enable(context->entry);
250     context->appdata->mmpoi_use_radius = TRUE;
251     } else {
252     textbox_disable(context->entry);
253     context->appdata->mmpoi_use_radius = FALSE;
254     }
255    
256     context->appdata->mmpoi_dont_export_found =
257     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(context->no_found));
258    
259     context->appdata->mmpoi_dont_export_disabled =
260     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(context->no_disabled));
261    
262     export_list_update(context);
263     }
264    
265     static void export_radius_modified(GtkWidget *widget, gpointer data ) {
266     export_context_t *context = (export_context_t*)data;
267    
268     context->appdata->mmpoi_radius = distance_eval(context->entry, context);
269    
270     printf("Distance is %.2f km\n", context->appdata->mmpoi_radius);
271    
272     if(context->handler_id) {
273     printf("resetting running timer\n");
274     gtk_timeout_remove(context->handler_id);
275     context->handler_id = 0;
276     }
277    
278     if(!isnan(context->appdata->mmpoi_radius))
279     context->handler_id =
280     gtk_timeout_add(1000, export_list_update, context);
281     }
282    
283     /* Our usual callback function */
284     static void on_cancel(GtkWidget *widget, gpointer data) {
285     int *flag = (int*)data;
286     *flag = TRUE;
287     }
288    
289     static void on_browse(GtkWidget *widget, gpointer data) {
290     GtkWidget *dialog;
291    
292     export_context_t *context = (export_context_t*)data;
293    
294     printf("Browse\n");
295    
296     #ifdef USE_MAEMO
297     dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(context->dialog),
298     GTK_FILE_CHOOSER_ACTION_SAVE);
299     #else
300     dialog = gtk_file_chooser_dialog_new(_("Save POI database"),
301     GTK_WINDOW(context->dialog),
302     GTK_FILE_CHOOSER_ACTION_SAVE,
303     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
304     GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
305     NULL);
306     #endif
307    
308     printf("set filename <%s>\n", context->appdata->mmpoi_path);
309    
310     if(!g_file_test(context->appdata->mmpoi_path, G_FILE_TEST_EXISTS)) {
311     char *last_sep = strrchr(context->appdata->mmpoi_path, '/');
312     if(last_sep) {
313     *last_sep = 0; // seperate path from file
314    
315     /* the user just created a new document */
316     gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
317     context->appdata->mmpoi_path);
318     gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), last_sep+1);
319    
320     /* restore full filename */
321     *last_sep = '/';
322     }
323     } else
324     gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
325     context->appdata->mmpoi_path);
326    
327     if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_FM_OK) {
328     gchar *name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
329     if(name) {
330     free(context->appdata->mmpoi_path);
331     context->appdata->mmpoi_path = strdup(name);
332     gtk_label_set_text(GTK_LABEL(context->path_label),
333     context->appdata->mmpoi_path);
334     }
335     }
336    
337     gtk_widget_destroy (dialog);
338     }
339    
340     void mmpoi_export(appdata_t *appdata) {
341     sqlite3 *db;
342     char *zErrMsg = 0;
343     char cmd[256];
344     int rc, i;
345     char *old_mmpoi_path = strdup(appdata->mmpoi_path);
346    
347     export_context_t context;
348     memset(&context, 0, sizeof(export_context_t));
349     context.appdata = appdata;
350    
351     printf("export poi\n");
352    
353     /* first create a new faked gpx file containing all caches to */
354     /* be exported */
355     context.gpx = export_list_create(appdata, &context.mode);
356     if(!context.gpx) {
357     errorf(_("Out of memory"));
358     return;
359     }
360    
361     /* --------- do confirmation dialog ----------- */
362     context.dialog = gtk_dialog_new_with_buttons(_("Maemo Mapper POI export"),
363     GTK_WINDOW(appdata->window), GTK_DIALOG_MODAL,
364     GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
365     GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
366     NULL);
367    
368     #if defined(USE_MAEMO) && defined(HILDON_HELP)
369     hildon_help_dialog_help_enable(GTK_DIALOG(context.dialog),
370     HELP_ID_EXPORT, appdata->osso_context);
371     #endif
372    
373     GtkWidget *vbox = gtk_vbox_new(FALSE,0);
374    
375     /* ------------------ radius limit gui ------------------ */
376    
377     GtkWidget *label, *hbox = gtk_hbox_new(FALSE,2);
378     context.use_radius = gtk_check_button_new_with_label(
379     _("Limit export radius to:"));
380     context.entry = dist_entry_new(appdata->mmpoi_radius, appdata->imperial);
381    
382     gtk_box_pack_start_defaults(GTK_BOX(hbox), context.use_radius);
383     gtk_box_pack_start_defaults(GTK_BOX(hbox), context.entry);
384     gtk_box_pack_start_defaults(GTK_BOX(vbox), hbox);
385    
386     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(context.use_radius),
387     appdata->mmpoi_use_radius);
388    
389     /* Connect the "clicked" signal of the button to our callback */
390     gtk_signal_connect (GTK_OBJECT(context.use_radius), "clicked",
391     GTK_SIGNAL_FUNC(export_update), (gpointer)&context);
392    
393     g_signal_connect(G_OBJECT(context.entry), "changed",
394     G_CALLBACK(export_radius_modified), (gpointer)&context);
395    
396     /* ------------------ don't export found/disabled/archived -------------- */
397    
398     hbox = gtk_hbox_new(FALSE,2);
399    
400     label = gtk_label_new(_("Don't export"));
401     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
402     context.no_found = gtk_check_button_new_with_label(_("found"));
403     context.no_disabled = gtk_check_button_new_with_label(_("disabled/archived"));
404    
405     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(context.no_found),
406     appdata->mmpoi_dont_export_found);
407    
408     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(context.no_disabled),
409     appdata->mmpoi_dont_export_disabled);
410    
411     gtk_box_pack_start_defaults(GTK_BOX(hbox), label);
412     gtk_box_pack_start_defaults(GTK_BOX(hbox), context.no_found);
413     gtk_box_pack_start_defaults(GTK_BOX(hbox), context.no_disabled);
414    
415     gtk_signal_connect (GTK_OBJECT(context.no_found), "clicked",
416     GTK_SIGNAL_FUNC(export_update), (gpointer)&context);
417     gtk_signal_connect (GTK_OBJECT(context.no_disabled), "clicked",
418     GTK_SIGNAL_FUNC(export_update), (gpointer)&context);
419    
420     gtk_box_pack_start_defaults(GTK_BOX(vbox),hbox);
421    
422     /* ------------------ info text -------------- */
423    
424     context.info_label = gtk_label_new("");
425     gtk_label_set_line_wrap_mode(GTK_LABEL(context.info_label), PANGO_WRAP_WORD);
426     gtk_label_set_line_wrap(GTK_LABEL(context.info_label), TRUE);
427     gtk_misc_set_alignment(GTK_MISC(context.info_label), 0.f, 0.5f);
428     gtk_box_pack_start_defaults(GTK_BOX(vbox), context.info_label);
429    
430     export_update(NULL, &context);
431    
432     #ifdef USE_MAEMO
433     gtk_box_pack_start_defaults(GTK_BOX(vbox),
434     context.launch = gtk_check_button_new_with_label(
435     _("Launch Maemo Mapper after export")));
436     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(context.launch),
437     !appdata->mmpoi_dontlaunch);
438     #endif
439    
440     /* ------------------ path/file ------------------ */
441     gtk_box_pack_start_defaults(GTK_BOX(vbox), gtk_hseparator_new());
442    
443     hbox = gtk_hbox_new(FALSE, 0);
444     label = gtk_label_new(_("Export to:"));
445     gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE,0);
446     gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
447 harbaum 7 GtkWidget *button = gtk_button_new_with_label(_("Browse"));
448 harbaum 1 gtk_signal_connect(GTK_OBJECT(button), "clicked",
449     GTK_SIGNAL_FUNC(on_browse), (gpointer)&context);
450     gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE,0);
451     gtk_box_pack_start_defaults(GTK_BOX(vbox), hbox);
452    
453     context.path_label = gtk_label_new(appdata->mmpoi_path);
454     gtk_misc_set_alignment(GTK_MISC(context.path_label), 0.f, 0.5f);
455     gtk_label_set_ellipsize(GTK_LABEL(context.path_label), PANGO_ELLIPSIZE_MIDDLE);
456     gtk_box_pack_start_defaults(GTK_BOX(vbox), context.path_label);
457    
458     /* ------------------ info ------------------ */
459    
460     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context.dialog)->vbox), vbox);
461    
462     gtk_widget_show_all(context.dialog);
463    
464     if(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(context.dialog))) {
465     #ifdef USE_MAEMO
466     appdata->mmpoi_dontlaunch =
467     !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(context.launch));
468     #endif
469    
470     /* remove existing database */
471     remove(appdata->mmpoi_path);
472    
473     if(checkdir(appdata->mmpoi_path) != 0)
474     errorf(_("Unable to access or create output directory!"));
475     else {
476    
477     /* build a progress dialog which can even be stopped */
478    
479     GtkWidget *pbar, *wait_dialog = gtk_dialog_new();
480     gtk_dialog_set_has_separator(GTK_DIALOG(wait_dialog), FALSE);
481     gtk_window_set_default_size(GTK_WINDOW(wait_dialog), 250, 100);
482 harbaum 7 gtk_window_set_title(GTK_WINDOW(wait_dialog), _("Exporting"));
483 harbaum 1 gtk_window_set_modal(GTK_WINDOW(wait_dialog), TRUE);
484     gtk_window_set_transient_for(GTK_WINDOW(wait_dialog),
485     GTK_WINDOW(context.dialog));
486     gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(wait_dialog)->vbox),
487     pbar = gtk_progress_bar_new());
488    
489     GtkWidget *button = gtk_button_new_with_label(_("Cancel"));
490     int cancelled = 0;
491     gtk_signal_connect(GTK_OBJECT(button), "clicked",
492     GTK_SIGNAL_FUNC(on_cancel), (gpointer)&cancelled);
493     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(wait_dialog)->action_area),
494     button);
495    
496     gtk_widget_show_all(wait_dialog);
497    
498     /* ---------------------- copy icons --------------------- */
499     for(i=0;cache_type_icons[i][0];i++) {
500     char *src = malloc(strlen(ICONPATH)+strlen(cache_type_icons[i])+
501 harbaum 179 strlen("cache_type_.png")+1);
502     sprintf(src, ICONPATH "cache_type_%s.png", cache_type_icons[i]);
503 harbaum 1 if(!g_file_test(src, G_FILE_TEST_EXISTS))
504 harbaum 179 sprintf(src, "./icons/cache_type_%s.png", cache_type_icons[i]);
505 harbaum 1
506     if(g_file_test(src, G_FILE_TEST_EXISTS)) {
507     char *dest = malloc(strlen(appdata->mmpoi_path)+
508     strlen(cache_type_icons[i])+strlen(".jpg")+1);
509     strcpy(dest, appdata->mmpoi_path);
510     *(strrchr(dest, '/')+1) = 0;
511     sprintf(dest+strlen(dest), "%s.jpg", cache_type_icons[i]);
512    
513     /* read source file */
514     FILE *file = fopen(src, "rb");
515     fseek(file, 0, SEEK_END);
516     int len = ftell(file);
517     fseek(file, 0, SEEK_SET);
518     char *buffer = malloc(len);
519     fread(buffer, 1l, len, file);
520     fclose(file);
521    
522     /* write destination file */
523     file = fopen(dest, "wb");
524     fwrite(buffer, 1l, len, file);
525     fclose(file);
526    
527     free(buffer);
528     free(dest);
529     }
530    
531     free(src);
532     }
533    
534     /* ---------------------- database export --------------------- */
535    
536     printf("exporting to %s\n", appdata->mmpoi_path);
537     rc = sqlite3_open(appdata->mmpoi_path, &db);
538     if( rc ){
539     errorf(_("Can't open SQL database:\n\n%s"), sqlite3_errmsg(db));
540     sqlite3_close(db);
541     export_list_free(context.gpx);
542     return;
543     }
544    
545     /* create the table */
546     rc = sqlite3_exec(db, "create table category (cat_id integer PRIMARY "
547     "KEY, label text, desc text, enabled integer)",
548     callback, 0, &zErrMsg);
549     if( rc!=SQLITE_OK ) {
550     errorf(_("Creating cathegory table:\n\n%s"), zErrMsg);
551     sqlite3_close(db);
552     export_list_free(context.gpx);
553     return;
554     }
555    
556     /* create all types */
557     i = 0;
558     while(cache_type_str[i][0]) {
559     snprintf(cmd, sizeof(cmd),
560     "insert into category values (%d, '%s', '%s', 1)",
561     12+i, cache_type_str[i], cache_type_desc[i]);
562    
563     rc = sqlite3_exec(db, cmd, callback, 0, &zErrMsg);
564     if( rc != SQLITE_OK ){
565     errorf(_("Creating cathegory:\n\n%s"), zErrMsg);
566     sqlite3_close(db);
567     export_list_free(context.gpx);
568     return;
569     }
570     i++;
571     }
572    
573     rc = sqlite3_exec(db, "create table poi (poi_id integer PRIMARY KEY, "
574     "lat real, lon real, label text, desc text, "
575     "cat_id integer)", callback, 0, &zErrMsg);
576     if( rc!=SQLITE_OK ){
577     errorf(_("Creating POI table:\n\n%s"), zErrMsg);
578     sqlite3_close(db);
579     export_list_free(context.gpx);
580     return;
581     }
582    
583     pos_t *refpos = get_pos(appdata);
584    
585     /* export the caches */
586     int id = 1;
587     cache_t *cache = context.gpx->cache;
588     int total = export_list_count(appdata, context.gpx);
589    
590     while(cache && !cancelled) {
591    
592     /* no disabled/archived if requested */
593     if(!(appdata->mmpoi_dont_export_disabled &&
594     (!cache->available || cache->archived))) {
595    
596     /* no found if requested */
597     if(!(appdata->mmpoi_dont_export_found &&
598     cache->notes && cache->notes->found)) {
599    
600     if(appdata->mmpoi_use_radius && !isnan(appdata->mmpoi_radius)) {
601     /* count all caches within given radius around current position */
602     if(gpx_pos_get_distance(*refpos, gpx_cache_pos(cache), 0) <
603     appdata->mmpoi_radius) {
604     printf("%d exporting %s\n", id, cache->id);
605     cache_export(db, id++, cache);
606     }
607     } else {
608     printf("%d exporting %s\n", id, cache->id);
609     cache_export(db, id++, cache);
610     }
611     }
612     }
613     cache = cache->next;
614    
615     gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(pbar),
616     (float)(id-2)/(float)total);
617    
618     while(gtk_events_pending ())
619     gtk_main_iteration ();
620     }
621     sqlite3_close(db);
622    
623     gtk_widget_destroy(wait_dialog);
624    
625     #ifdef USE_MAEMO
626     if(!cancelled && !appdata->mmpoi_dontlaunch)
627     dbus_mm_set_position(appdata, NULL);
628     #endif
629     }
630     } else {
631     /* restore old mmpoi_path, in case it has been altered but not been used */
632     free(appdata->mmpoi_path);
633     appdata->mmpoi_path = strdup(old_mmpoi_path);
634     }
635    
636     gtk_widget_destroy(context.dialog);
637    
638     if(context.handler_id) {
639     printf("removing timer\n");
640     gtk_timeout_remove(context.handler_id);
641     }
642    
643     export_list_free(context.gpx);
644    
645     free(old_mmpoi_path);
646     }