Contents of /trunk/src/gconf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 48 - (show annotations)
Fri Aug 7 07:57:33 2009 UTC (14 years, 9 months ago) by harbaum
File MIME type: text/plain
File size: 13006 byte(s)
Save map position
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 #ifdef USE_MAEMO
82 { "mmpoi_dontlaunch", STORE_BOOL, OFFSET(mmpoi_dontlaunch) },
83 { "cachelist_dss", STORE_BOOL, OFFSET(cachelist_disable_screensaver) },
84 { "goto_dss", STORE_BOOL, OFFSET(goto_disable_screensaver) },
85 { "cachelist_update", STORE_BOOL, OFFSET(cachelist_update) },
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 #endif
92 { NULL, -1, -1 }
93 };
94
95 static char *get_basename(char *name) {
96 char *p = strrchr(name, '/');
97 if(!p) p = name;
98 else p = p+1;
99
100 g_assert(*p);
101
102 /* escape all non alnum characters */
103 p = g_strdup(p);
104 int i;
105 for(i=0;i<strlen(p);i++)
106 if(!isalnum(p[i]))
107 p[i] = '_';
108
109 return p;
110 }
111
112 void gconf_remove_closed_name(appdata_t *appdata, char *filename) {
113 char *key = g_strdup_printf(GCONF_KEY_CLOSED, get_basename(filename));
114 gconf_client_unset(appdata->gconf_client, key, NULL);
115 g_free(key);
116 }
117
118 void gconf_save_closed_name(appdata_t *appdata, char *filename, char *name) {
119 char *key = g_strdup_printf(GCONF_KEY_CLOSED, get_basename(filename));
120 gconf_client_set_string(appdata->gconf_client, key, name, NULL);
121 g_free(key);
122 }
123
124 char *gconf_restore_closed_name(appdata_t *appdata, char *filename) {
125 char *key = g_strdup_printf(GCONF_KEY_CLOSED, get_basename(filename));
126 char *ret = gconf_client_get_string(appdata->gconf_client, key, NULL);
127 g_free(key);
128 return ret;
129 }
130
131 void gconf_save_state(appdata_t *appdata) {
132 int entries = 0;
133
134 gpx_t *gpx = appdata->gpx;
135 while(gpx) {
136 char str[128];
137 snprintf(str, sizeof(str), GCONF_KEY_GPX, entries++);
138 gconf_client_set_string(appdata->gconf_client, str, gpx->filename, NULL);
139 gpx = gpx->next;
140 }
141
142 gconf_client_set_int(appdata->gconf_client, GCONF_KEY_CNT, entries, NULL);
143
144 /* -------------- save locations (excl. home location) --------------- */
145 entries = 0;
146 location_t *loc = appdata->location;
147 while(loc) {
148 char str[128];
149 snprintf(str, sizeof(str), GCONF_KEY_LOC_NAME, entries);
150 gconf_client_set_string(appdata->gconf_client, str, loc->name, NULL);
151 snprintf(str, sizeof(str), GCONF_KEY_LOC_LAT, entries);
152 gconf_client_set_float(appdata->gconf_client, str, loc->pos.lat, NULL);
153 snprintf(str, sizeof(str), GCONF_KEY_LOC_LON, entries);
154 gconf_client_set_float(appdata->gconf_client, str, loc->pos.lon, NULL);
155 entries++;
156 loc = loc->next;
157 }
158
159 gconf_client_set_int(appdata->gconf_client, GCONF_KEY_LOC_CNT, entries, NULL);
160
161 /* store everything listed in the store table */
162 store_t *st = store;
163 while(st->key) {
164 void **ptr = ((void*)appdata) + st->offset;
165 char *key = g_strdup_printf(GCONF_PATH "%s", st->key);
166
167 switch(st->type) {
168 case STORE_STRING:
169 if((char*)(*ptr)) {
170 gconf_client_set_string(appdata->gconf_client, key, (char*)(*ptr), NULL);
171 }
172 break;
173
174 case STORE_BOOL:
175 gconf_client_set_bool(appdata->gconf_client, key, *((int*)ptr), NULL);
176 break;
177
178 case STORE_INT:
179 gconf_client_set_int(appdata->gconf_client, key, *((int*)ptr), NULL);
180 break;
181
182 case STORE_FLOAT:
183 if(!isnan(*((float*)ptr)))
184 gconf_client_set_float(appdata->gconf_client, key, *((float*)ptr), NULL);
185 break;
186
187 default:
188 printf("Unsupported type %d\n", st->type);
189 break;
190 }
191
192 g_free(key);
193 st++;
194 }
195 }
196
197 void gconf_load_state(appdata_t *appdata) {
198 gpx_t **gpx = &appdata->gpx;
199
200 while(*gpx) gpx = &((*gpx)->next);
201
202 gpx_dialog_t *dialog = NULL;
203
204 /* default positions are invalid */
205 appdata->home.lat = appdata->home.lon = NAN;
206 appdata->manual_goto.lat = appdata->manual_goto.lon = NAN;
207 appdata->gps.lat = appdata->gps.lon = NAN;
208
209 int i, entries = gconf_client_get_int(appdata->gconf_client,
210 GCONF_KEY_CNT, NULL);
211
212 if(entries)
213 dialog = gpx_busy_dialog_new(GTK_WIDGET(appdata->window));
214
215 for(i=0;i<entries;i++) {
216 char str[128];
217 snprintf(str, sizeof(str), GCONF_KEY_GPX, i);
218 char *fname = gconf_client_get_string(appdata->gconf_client, str, NULL);
219
220 if(fname) {
221 /* check if there's a valid name stored for this file. */
222 /* if yes it's a "closed" file */
223 char *name = gconf_restore_closed_name(appdata, fname);
224 if(name) {
225 *gpx = g_new0(gpx_t, 1);
226 (*gpx)->filename = fname;
227 (*gpx)->name = g_strdup(name);
228 (*gpx)->closed = TRUE;
229 } else {
230 if(g_file_test(fname, G_FILE_TEST_IS_DIR))
231 *gpx = gpx_parse_dir(dialog, fname);
232 else
233 *gpx = gpx_parse(dialog, fname);
234
235 free(fname);
236 }
237 }
238
239 /* use next gpx entry of this was loaded successfully */
240 if(*gpx)
241 gpx = &((*gpx)->next);
242 }
243
244 gpx_busy_dialog_destroy(dialog);
245
246 /* ------------- load locations --------------------- */
247 entries = gconf_client_get_int(appdata->gconf_client,
248 GCONF_KEY_LOC_CNT, NULL);
249
250 location_t **loc = &appdata->location;
251 for(i=0;i<entries;i++) {
252 *loc = g_new0(location_t, 1);
253 if(*loc) {
254 char str[128];
255 snprintf(str, sizeof(str), GCONF_KEY_LOC_NAME, i);
256 (*loc)->name = gconf_client_get_string(appdata->gconf_client, str, NULL);
257 snprintf(str, sizeof(str), GCONF_KEY_LOC_LAT, i);
258 (*loc)->pos.lat = gconf_client_get_float(appdata->gconf_client, str, NULL);
259 snprintf(str, sizeof(str), GCONF_KEY_LOC_LON, i);
260 (*loc)->pos.lon = gconf_client_get_float(appdata->gconf_client, str, NULL);
261
262 loc = &((*loc)->next);
263 }
264 }
265
266 /* restore everything listed in the store table */
267 store_t *st = store;
268 while(st->key) {
269 void **ptr = ((void*)appdata) + st->offset;
270 char *key = g_strdup_printf(GCONF_PATH "%s", st->key);
271
272 /* check if key is present */
273 GConfValue *value = gconf_client_get(appdata->gconf_client, key, NULL);
274 if(value) {
275 gconf_value_free(value);
276
277 switch(st->type) {
278 case STORE_STRING: {
279 char **str = (char**)ptr;
280 *str = gconf_client_get_string(appdata->gconf_client, key, NULL);
281 } break;
282
283 case STORE_BOOL:
284 *((int*)ptr) = gconf_client_get_bool(appdata->gconf_client, key, NULL);
285 break;
286
287 case STORE_INT:
288 *((int*)ptr) = gconf_client_get_int(appdata->gconf_client, key, NULL);
289 break;
290
291 case STORE_FLOAT:
292 *((float*)ptr) = gconf_client_get_float(appdata->gconf_client, key, NULL);
293 break;
294
295 default:
296 printf("Unsupported type %d\n", st->type);
297 break;
298 }
299 }
300 g_free(key);
301 st++;
302 }
303
304 /* ----- set all kinds of defaults ------- */
305
306 if(!appdata->compass_damping) appdata->compass_damping = 1;
307
308 if(!appdata->mmpoi_radius)
309 appdata->mmpoi_radius = 100.0; // 100 km
310
311 if(!appdata->search)
312 appdata->search = SEARCH_NAME | SEARCH_ID;
313
314 if(!appdata->image_path) {
315
316 /* use gps by default */
317 appdata->use_gps = TRUE;
318
319 #ifndef USE_MAEMO
320 char *p = getenv("HOME");
321 if(p) {
322 /* build image path in home directory */
323 appdata->image_path =
324 malloc(strlen(p)+strlen(DEFAULT_IMAGE_PATH_HOME)+2);
325 strcpy(appdata->image_path, p);
326 if(appdata->image_path[strlen(appdata->image_path)-1] != '/')
327 strcat(appdata->image_path, "/");
328 strcat(appdata->image_path, DEFAULT_IMAGE_PATH_HOME);
329 } else
330 #endif
331 appdata->image_path = strdup(DEFAULT_IMAGE_PATH);
332
333 } else {
334 /* some versions old versions messed up the path */
335 if(appdata->image_path[strlen(appdata->image_path)-1] != '/') {
336 printf("adjusting image path\n");
337 appdata->image_path = realloc(appdata->image_path,
338 strlen(appdata->image_path)+2);
339 strcat(appdata->image_path, "/");
340 }
341 }
342
343 if(!appdata->mmpoi_path) {
344 char *p = getenv("HOME");
345 if(p) {
346 /* build mmpoi path in home directory */
347 appdata->mmpoi_path =
348 malloc(strlen(p)+strlen(DEFAULT_MMPOI_PATH)+2);
349 strcpy(appdata->mmpoi_path, p);
350 if(appdata->mmpoi_path[strlen(appdata->mmpoi_path)-1] != '/')
351 strcat(appdata->mmpoi_path, "/");
352 strcat(appdata->mmpoi_path, DEFAULT_MMPOI_PATH);
353 } else
354 appdata->mmpoi_path = strdup(DEFAULT_MMPOI_PATH);
355 }
356
357 if(!appdata->fieldnotes_path) {
358 char *p = getenv("HOME");
359 if(p) {
360 /* build fieldnotes path in home directory */
361 appdata->fieldnotes_path =
362 malloc(strlen(p)+strlen(DEFAULT_FIELDNOTES_PATH)+2);
363 strcpy(appdata->fieldnotes_path, p);
364 if(appdata->fieldnotes_path[strlen(appdata->fieldnotes_path)-1] != '/')
365 strcat(appdata->fieldnotes_path, "/");
366 strcat(appdata->fieldnotes_path, DEFAULT_FIELDNOTES_PATH);
367 } else
368 appdata->fieldnotes_path = strdup(DEFAULT_FIELDNOTES_PATH);
369 }
370
371 if(!appdata->garmin_path) {
372 char *p = getenv("HOME");
373 if(p) {
374 /* build image path in home directory */
375 appdata->garmin_path =
376 malloc(strlen(p)+strlen(DEFAULT_GARMIN_PATH)+2);
377 strcpy(appdata->garmin_path, p);
378 if(appdata->garmin_path[strlen(appdata->garmin_path)-1] != '/')
379 strcat(appdata->garmin_path, "/");
380 strcat(appdata->garmin_path, DEFAULT_GARMIN_PATH);
381 } else
382 appdata->garmin_path = strdup(DEFAULT_GARMIN_PATH);
383 }
384
385 /* make sure image path actually exists */
386 checkdir(appdata->image_path);
387
388 if(!appdata->gpxlist_items)
389 appdata->gpxlist_items = GPXLIST_ITEM_DEFAULT;
390
391 if(!appdata->cachelist_items)
392 appdata->cachelist_items = CACHELIST_ITEM_DEFAULT;
393
394 /* if there are no entries in the main list, try to add the */
395 /* "welcome" one */
396 if(!appdata->gpx) {
397 char *name = g_strdup(ICONPATH "welcome.gpx");
398 dialog = gpx_busy_dialog_new(GTK_WIDGET(appdata->window));
399 printf("No GPX file loaded, trying to load demo\n");
400 appdata->gpx = gpx_parse(dialog, name);
401 gpx_busy_dialog_destroy(dialog);
402 g_free(name);
403 }
404 }
405