Contents of /trunk/src/gconf.c

Parent Directory Parent Directory | Revision Log Revision Log


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