Contents of /trunk/src/gconf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations)
Fri May 21 19:28:16 2010 UTC (13 years, 11 months ago) by harbaum
File MIME type: text/plain
File size: 16457 byte(s)
Map widget update
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 <stddef.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <math.h> // for isnan
24 #include "gpxview.h"
25
26 #define GCONF_PATH "/apps/gpxview/"
27 #define GCONF_KEY_GPX GCONF_PATH "gpx%d"
28 #define GCONF_KEY_CNT GCONF_PATH "entries"
29
30 #define GCONF_KEY_LOC_NAME GCONF_PATH "location%d/name"
31 #define GCONF_KEY_LOC_LAT GCONF_PATH "location%d/latitude"
32 #define GCONF_KEY_LOC_LON GCONF_PATH "location%d/longitude"
33 #define GCONF_KEY_LOC_CNT GCONF_PATH "location_entries"
34
35 #define GCONF_KEY_CLOSED GCONF_PATH "closed/%s"
36
37 #include <string.h>
38
39 enum {
40 STORE_STRING, STORE_FLOAT, STORE_INT, STORE_BOOL,
41 };
42
43 typedef struct {
44 char *key;
45 int type;
46 int offset;
47 } store_t;
48
49 #define OFFSET(a) offsetof(appdata_t, a)
50
51 static store_t store[] = {
52 { "image_path", STORE_STRING, OFFSET(image_path) },
53 { "path", STORE_STRING, OFFSET(path) },
54 { "geotext/text", STORE_STRING, OFFSET(geotext_text) },
55 { "geotext/shift", STORE_INT, OFFSET(geotext_shift) },
56 { "mmpoi_path", STORE_STRING, OFFSET(mmpoi_path) },
57 { "garmin_path", STORE_STRING, OFFSET(garmin_path) },
58 { "fnotes_path", STORE_STRING, OFFSET(fieldnotes_path) },
59 { "garmin_ign_found", STORE_BOOL, OFFSET(garmin_ign_found) },
60 { "active_location", STORE_INT, OFFSET(active_location) },
61 { "mmpoi_use_radius", STORE_BOOL, OFFSET(mmpoi_use_radius) },
62 { "mmpoi_radius", STORE_FLOAT, OFFSET(mmpoi_radius) },
63 { "mmpoi_ign_found", STORE_BOOL, OFFSET(mmpoi_dont_export_found) },
64 { "mmpoi_ign_disabl", STORE_BOOL, OFFSET(mmpoi_dont_export_disabled) },
65 { "use_gps", STORE_BOOL, OFFSET(use_gps) },
66 { "imperial", STORE_BOOL, OFFSET(imperial) },
67 { "compass_locked", STORE_BOOL, OFFSET(compass_locked) },
68 { "latitude", STORE_FLOAT, OFFSET(home.lat) },
69 { "longitude", STORE_FLOAT, OFFSET(home.lon) },
70 { "gps_lat", STORE_FLOAT, OFFSET(gps.lat) },
71 { "gps_lon", STORE_FLOAT, OFFSET(gps.lon) },
72 { "search_in", STORE_INT, OFFSET(search) },
73 { "search_days", STORE_INT, OFFSET(search_days) },
74 { "search_str", STORE_STRING, OFFSET(search_str) },
75 { "gpxlist_items", STORE_INT, OFFSET(gpxlist_items) },
76 { "cachelist_items", STORE_INT, OFFSET(cachelist_items) },
77 { "compass_damping", STORE_INT, OFFSET(compass_damping) },
78 { "cachelist_hide_found", STORE_BOOL, OFFSET(cachelist_hide_found) },
79 { "cachelist_update", STORE_BOOL, OFFSET(cachelist_update) },
80 { "disable_gcvote", STORE_BOOL, OFFSET(disable_gcvote) },
81 { "username", STORE_STRING, OFFSET(username) },
82 #ifdef USE_MAEMO
83 { "mmpoi_dontlaunch", STORE_BOOL, OFFSET(mmpoi_dontlaunch) },
84 { "cachelist_dss", STORE_BOOL, OFFSET(cachelist_disable_screensaver) },
85 { "goto_dss", STORE_BOOL, OFFSET(goto_disable_screensaver) },
86 #endif
87 #ifdef ENABLE_OSM_GPS_MAP
88 { "map_lat", STORE_FLOAT, OFFSET(map.pos.lat) },
89 { "map_lon", STORE_FLOAT, OFFSET(map.pos.lon) },
90 { "map_zoom", STORE_INT, OFFSET(map.zoom) },
91 { "map_source", STORE_INT, OFFSET(map.source) },
92 { "map_dpix", STORE_BOOL, OFFSET(map.dpix) },
93 #endif
94 #ifdef ESPEAK
95 { "espeak/enabled", STORE_BOOL, OFFSET(espeak.enabled) },
96 #endif
97
98 { "geotoad/password", STORE_STRING, OFFSET(gt.password) },
99 { "geotoad/filename", STORE_STRING, OFFSET(gt.filename) },
100 { "geotoad/distance", STORE_FLOAT, OFFSET(gt.distance) },
101 { "geotoad/lat", STORE_FLOAT, OFFSET(gt.lat) },
102 { "geotoad/lon", STORE_FLOAT, OFFSET(gt.lon) },
103 { "geotoad/flags", STORE_INT, OFFSET(gt.flags) },
104 { "geotoad/no_ownfnd",STORE_BOOL, OFFSET(gt.no_owned_found) },
105
106 { NULL, -1, -1 }
107 };
108
109 static char *get_basename(char *name) {
110 char *p = strrchr(name, '/');
111 if(!p) p = name;
112 else p = p+1;
113
114 g_assert(*p);
115
116 /* escape all non alnum characters */
117 p = g_strdup(p);
118 int i;
119 for(i=0;i<strlen(p);i++)
120 if(!isalnum(p[i]))
121 p[i] = '_';
122
123 return p;
124 }
125
126 void gconf_remove_closed_name(appdata_t *appdata, char *filename) {
127 if(!filename || !strlen(filename)) return;
128
129 char *key = g_strdup_printf(GCONF_KEY_CLOSED, get_basename(filename));
130 gconf_client_unset(appdata->gconf_client, key, NULL);
131 g_free(key);
132 }
133
134 void gconf_save_closed_name(appdata_t *appdata, char *filename, char *name) {
135 if(!filename || !strlen(filename)) return;
136
137 char *key = g_strdup_printf(GCONF_KEY_CLOSED, get_basename(filename));
138 gconf_client_set_string(appdata->gconf_client, key, name, NULL);
139 g_free(key);
140 }
141
142 char *gconf_restore_closed_name(appdata_t *appdata, char *filename) {
143 if(!filename || !strlen(filename)) return NULL;
144
145 char *key = g_strdup_printf(GCONF_KEY_CLOSED, get_basename(filename));
146 char *ret = gconf_client_get_string(appdata->gconf_client, key, NULL);
147 g_free(key);
148 return ret;
149 }
150
151 void gconf_save_state(appdata_t *appdata) {
152 int entries = 0;
153
154 printf("saving gconf state\n");
155
156 /* free proxy settings */
157 if(appdata->proxy) {
158 proxy_t *proxy = appdata->proxy;
159
160 if(proxy->authentication_password) g_free(proxy->authentication_password);
161 if(proxy->authentication_user) g_free(proxy->authentication_user);
162 if(proxy->host) g_free(proxy->host);
163 if(proxy->ignore_hosts) g_free(proxy->ignore_hosts);
164
165 g_free(proxy);
166 appdata->proxy = NULL;
167 }
168
169 gpx_t *gpx = appdata->gpx;
170 while(gpx) {
171 char str[128];
172 snprintf(str, sizeof(str), GCONF_KEY_GPX, entries++);
173 gconf_client_set_string(appdata->gconf_client, str, gpx->filename, NULL);
174 gpx = gpx->next;
175 }
176
177 gconf_client_set_int(appdata->gconf_client, GCONF_KEY_CNT, entries, NULL);
178
179 /* -------------- save locations (excl. home location) --------------- */
180 entries = 0;
181 location_t *loc = appdata->location;
182 while(loc) {
183 char str[128];
184 snprintf(str, sizeof(str), GCONF_KEY_LOC_NAME, entries);
185 gconf_client_set_string(appdata->gconf_client, str, loc->name, NULL);
186 snprintf(str, sizeof(str), GCONF_KEY_LOC_LAT, entries);
187 gconf_client_set_float(appdata->gconf_client, str, loc->pos.lat, NULL);
188 snprintf(str, sizeof(str), GCONF_KEY_LOC_LON, entries);
189 gconf_client_set_float(appdata->gconf_client, str, loc->pos.lon, NULL);
190 entries++;
191 loc = loc->next;
192 }
193
194 gconf_client_set_int(appdata->gconf_client, GCONF_KEY_LOC_CNT, entries, NULL);
195
196 /* store everything listed in the store table */
197 store_t *st = store;
198 while(st->key) {
199 void **ptr = ((void*)appdata) + st->offset;
200 char *key = g_strdup_printf(GCONF_PATH "%s", st->key);
201
202 switch(st->type) {
203 case STORE_STRING:
204 if((char*)(*ptr)) {
205 gconf_client_set_string(appdata->gconf_client, key, (char*)(*ptr), NULL);
206 }
207 g_free((char*)(*ptr));
208 *ptr = NULL;
209 break;
210
211 case STORE_BOOL:
212 gconf_client_set_bool(appdata->gconf_client, key, *((int*)ptr), NULL);
213 break;
214
215 case STORE_INT:
216 gconf_client_set_int(appdata->gconf_client, key, *((int*)ptr), NULL);
217 break;
218
219 case STORE_FLOAT:
220 if(!isnan(*((float*)ptr)))
221 gconf_client_set_float(appdata->gconf_client, key, *((float*)ptr), NULL);
222 break;
223
224 default:
225 printf("Unsupported type %d\n", st->type);
226 break;
227 }
228
229 g_free(key);
230 st++;
231 }
232 }
233
234 void gconf_load_state(appdata_t *appdata) {
235 gpx_t **gpx = &appdata->gpx;
236
237 while(*gpx) gpx = &((*gpx)->next);
238
239 gpx_dialog_t *dialog = NULL;
240
241 /* default positions are invalid */
242 appdata->home.lat = appdata->home.lon = NAN;
243 appdata->gps.lat = appdata->gps.lon = NAN;
244 appdata->geomath.lat = appdata->geomath.lon = NAN;
245
246 appdata->gt.lat = appdata->gt.lon = NAN;
247 appdata->gt.distance = 1.0; // in km/mil
248
249 /* ------------- get proxy settings -------------------- */
250 if(gconf_client_get_bool(appdata->gconf_client,
251 PROXY_KEY "use_http_proxy", NULL)) {
252 proxy_t *proxy = appdata->proxy = g_new0(proxy_t, 1);
253
254 /* get basic settings */
255 proxy->host = gconf_client_get_string(appdata->gconf_client,
256 PROXY_KEY "host", NULL);
257 proxy->port = gconf_client_get_int(appdata->gconf_client,
258 PROXY_KEY "port", NULL);
259 proxy->ignore_hosts =
260 gconf_client_get_string(appdata->gconf_client,
261 PROXY_KEY "ignore_hosts", NULL);
262
263 /* check for authentication */
264 proxy->use_authentication =
265 gconf_client_get_bool(appdata->gconf_client,
266 PROXY_KEY "use_authentication", NULL);
267
268 if(proxy->use_authentication) {
269 proxy->authentication_user =
270 gconf_client_get_string(appdata->gconf_client,
271 PROXY_KEY "authentication_user", NULL);
272 proxy->authentication_password =
273 gconf_client_get_string(appdata->gconf_client,
274 PROXY_KEY "authentication_password", NULL);
275 }
276 }
277
278 /* restore everything listed in the store table */
279 store_t *st = store;
280 while(st->key) {
281 void **ptr = ((void*)appdata) + st->offset;
282 char *key = g_strdup_printf(GCONF_PATH "%s", st->key);
283
284 /* check if key is present */
285 GConfValue *value = gconf_client_get(appdata->gconf_client, key, NULL);
286 if(value) {
287 gconf_value_free(value);
288
289 switch(st->type) {
290 case STORE_STRING: {
291 char **str = (char**)ptr;
292 *str = gconf_client_get_string(appdata->gconf_client, key, NULL);
293 } break;
294
295 case STORE_BOOL:
296 *((int*)ptr) = gconf_client_get_bool(appdata->gconf_client, key, NULL);
297 break;
298
299 case STORE_INT:
300 *((int*)ptr) = gconf_client_get_int(appdata->gconf_client, key, NULL);
301 break;
302
303 case STORE_FLOAT:
304 *((float*)ptr) = gconf_client_get_float(appdata->gconf_client, key, NULL);
305 break;
306
307 default:
308 printf("Unsupported type %d\n", st->type);
309 break;
310 }
311 }
312 g_free(key);
313 st++;
314 }
315
316 int i, entries = gconf_client_get_int(appdata->gconf_client,
317 GCONF_KEY_CNT, NULL);
318
319 if(entries)
320 dialog = gpx_busy_dialog_new(GTK_WIDGET(appdata->window));
321
322 for(i=0;i<entries;i++) {
323 char str[128];
324 snprintf(str, sizeof(str), GCONF_KEY_GPX, i);
325 char *fname = gconf_client_get_string(appdata->gconf_client, str, NULL);
326 if(fname) {
327 /* check if there's a valid name stored for this file. */
328 /* if yes it's a "closed" file */
329 char *name = gconf_restore_closed_name(appdata, fname);
330 if(name) {
331 *gpx = g_new0(gpx_t, 1);
332 (*gpx)->filename = fname;
333 (*gpx)->name = g_strdup(name);
334 (*gpx)->closed = TRUE;
335 } else {
336 if(g_file_test(fname, G_FILE_TEST_IS_DIR))
337 *gpx = gpx_parse_dir(dialog, fname, appdata->username);
338 else
339 *gpx = gpx_parse(dialog, fname, appdata->username);
340
341 if(!*gpx) {
342 /* restoring the gpx file failed, mark it as unusable, but save */
343 /* its presence for later use */
344
345 /* create "closed" entry to remember this file for next */
346 /* load attempt */
347 *gpx = g_new0(gpx_t, 1);
348 (*gpx)->filename = fname;
349 char *p = fname;
350 if(strrchr(fname, '/'))
351 p = strrchr(fname, '/')+1;
352
353 (*gpx)->name = g_strdup_printf(_("Failed to load: %s"), p);
354 (*gpx)->closed = TRUE;
355 } else
356 free(fname);
357 }
358 gpx = &((*gpx)->next);
359 }
360 }
361
362 gpx_busy_dialog_destroy(dialog);
363
364 /* ------------- load locations --------------------- */
365 entries = gconf_client_get_int(appdata->gconf_client,
366 GCONF_KEY_LOC_CNT, NULL);
367
368 location_t **loc = &appdata->location;
369 for(i=0;i<entries;i++) {
370 *loc = g_new0(location_t, 1);
371 if(*loc) {
372 char str[128];
373 snprintf(str, sizeof(str), GCONF_KEY_LOC_NAME, i);
374 (*loc)->name = gconf_client_get_string(appdata->gconf_client, str, NULL);
375 snprintf(str, sizeof(str), GCONF_KEY_LOC_LAT, i);
376 (*loc)->pos.lat = gconf_client_get_float(appdata->gconf_client, str, NULL);
377 snprintf(str, sizeof(str), GCONF_KEY_LOC_LON, i);
378 (*loc)->pos.lon = gconf_client_get_float(appdata->gconf_client, str, NULL);
379
380 loc = &((*loc)->next);
381 }
382 }
383
384 /* ----- set all kinds of defaults ------- */
385
386 if(!appdata->compass_damping) appdata->compass_damping = 1;
387
388 if(!appdata->mmpoi_radius)
389 appdata->mmpoi_radius = 100.0; // 100 km
390
391 if(!appdata->search)
392 appdata->search = SEARCH_NAME | SEARCH_ID;
393
394 if(!appdata->image_path) {
395 #ifdef USE_MAEMO
396 /* update cachelist by default */
397 appdata->cachelist_update = TRUE;
398 #endif
399
400 /* use gps by default */
401 appdata->use_gps = TRUE;
402
403 #ifndef USE_MAEMO
404 char *p = getenv("HOME");
405 if(p) {
406 /* build image path in home directory */
407 appdata->image_path =
408 malloc(strlen(p)+strlen(DEFAULT_IMAGE_PATH_HOME)+2);
409 strcpy(appdata->image_path, p);
410 if(appdata->image_path[strlen(appdata->image_path)-1] != '/')
411 strcat(appdata->image_path, "/");
412 strcat(appdata->image_path, DEFAULT_IMAGE_PATH_HOME);
413 } else
414 #endif
415 appdata->image_path = strdup(DEFAULT_IMAGE_PATH);
416
417 /* check if this path is actually accessible */
418 /* and change it to the current users home if not */
419 /* (this should only happen on scratchbox) */
420 if(!g_file_test(appdata->image_path, G_FILE_TEST_IS_DIR)) {
421 if(g_mkdir_with_parents(appdata->image_path, 0700) != 0) {
422 char *p = getenv("HOME");
423 if(!p) p = "/tmp/";
424
425 appdata->image_path =
426 g_strdup_printf("%s%s%s", p,
427 (p[strlen(p)-1]!='/')?"/":"",
428 DEFAULT_IMAGE_PATH_HOME);
429 printf("using alt path %s\n", appdata->image_path);
430 }
431 }
432
433 } else {
434 /* some versions old versions messed up the path */
435 if(appdata->image_path[strlen(appdata->image_path)-1] != '/') {
436 printf("adjusting image path\n");
437 appdata->image_path = realloc(appdata->image_path,
438 strlen(appdata->image_path)+2);
439 strcat(appdata->image_path, "/");
440 }
441 }
442
443 if(!appdata->mmpoi_path) {
444 char *p = getenv("HOME");
445 if(p) {
446 /* build mmpoi path in home directory */
447 appdata->mmpoi_path =
448 malloc(strlen(p)+strlen(DEFAULT_MMPOI_PATH)+2);
449 strcpy(appdata->mmpoi_path, p);
450 if(appdata->mmpoi_path[strlen(appdata->mmpoi_path)-1] != '/')
451 strcat(appdata->mmpoi_path, "/");
452 strcat(appdata->mmpoi_path, DEFAULT_MMPOI_PATH);
453 } else
454 appdata->mmpoi_path = strdup(DEFAULT_MMPOI_PATH);
455 }
456
457 if(!appdata->fieldnotes_path) {
458 char *p = getenv("HOME");
459 if(p) {
460 /* build fieldnotes path in home directory */
461 appdata->fieldnotes_path =
462 malloc(strlen(p)+strlen(DEFAULT_FIELDNOTES_PATH)+2);
463 strcpy(appdata->fieldnotes_path, p);
464 if(appdata->fieldnotes_path[strlen(appdata->fieldnotes_path)-1] != '/')
465 strcat(appdata->fieldnotes_path, "/");
466 strcat(appdata->fieldnotes_path, DEFAULT_FIELDNOTES_PATH);
467 } else
468 appdata->fieldnotes_path = strdup(DEFAULT_FIELDNOTES_PATH);
469 }
470
471 if(!appdata->garmin_path) {
472 char *p = getenv("HOME");
473 if(p) {
474 /* build image path in home directory */
475 appdata->garmin_path =
476 malloc(strlen(p)+strlen(DEFAULT_GARMIN_PATH)+2);
477 strcpy(appdata->garmin_path, p);
478 if(appdata->garmin_path[strlen(appdata->garmin_path)-1] != '/')
479 strcat(appdata->garmin_path, "/");
480 strcat(appdata->garmin_path, DEFAULT_GARMIN_PATH);
481 } else
482 appdata->garmin_path = strdup(DEFAULT_GARMIN_PATH);
483 }
484
485 /* make sure image path actually exists */
486 checkdir(appdata->image_path);
487
488 if(!appdata->gpxlist_items)
489 appdata->gpxlist_items = GPXLIST_ITEM_DEFAULT;
490
491 if(!appdata->cachelist_items)
492 appdata->cachelist_items = CACHELIST_ITEM_DEFAULT;
493
494 /* if there are no entries in the main list, try to add the */
495 /* "welcome" one */
496 if(!appdata->gpx) {
497 char *name = g_strdup(ICONPATH "welcome.gpx");
498 dialog = gpx_busy_dialog_new(GTK_WIDGET(appdata->window));
499 printf("No GPX file loaded, trying to load demo\n");
500 appdata->gpx = gpx_parse(dialog, name, appdata->username);
501 gpx_busy_dialog_destroy(dialog);
502 g_free(name);
503 }
504 }
505