]>
Commit | Line | Data |
---|---|---|
a7023a1b RN |
1 | /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ |
2 | /* | |
3 | * viking -- GPS Data and Topo Analyzer, Explorer, and Manager | |
4 | * | |
5 | * Copyright (C) 2013, Rob Norris <rw_norris@hotmail.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with this program; if not, write to the Free Software | |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 | * | |
21 | */ | |
22 | #include <gtk/gtk.h> | |
23 | #include <glib/gi18n.h> | |
24 | #include <string.h> | |
25 | #include <stdlib.h> | |
26 | #include <stdio.h> | |
27 | #include <glib/gstdio.h> | |
28 | #include "viklayer_defaults.h" | |
29 | #include "dir.h" | |
30 | #include "file.h" | |
31 | ||
32 | #define VIKING_LAYER_DEFAULTS_INI_FILE "viking_layer_defaults.ini" | |
33 | ||
34 | // A list of the parameter types in use | |
35 | static GPtrArray *paramsVD; | |
36 | ||
37 | static GKeyFile *keyfile; | |
38 | ||
39 | static gboolean loaded; | |
40 | ||
6cc5daf1 | 41 | static VikLayerParamData get_default_data_answer ( const gchar *group, const gchar *name, VikLayerParamType ptype, gpointer *success ) |
a7023a1b RN |
42 | { |
43 | VikLayerParamData data = VIK_LPD_BOOLEAN ( FALSE ); | |
44 | ||
45 | GError *error = NULL; | |
46 | ||
47 | switch ( ptype ) { | |
48 | case VIK_LAYER_PARAM_DOUBLE: { | |
49 | gdouble dd = g_key_file_get_double ( keyfile, group, name, &error ); | |
50 | if ( !error ) data.d = dd; | |
51 | break; | |
52 | } | |
53 | case VIK_LAYER_PARAM_UINT: { | |
54 | guint32 uu = g_key_file_get_integer ( keyfile, group, name, &error ); | |
55 | if ( !error ) data.u = uu; | |
56 | break; | |
57 | } | |
58 | case VIK_LAYER_PARAM_INT: { | |
59 | gint32 ii = g_key_file_get_integer ( keyfile, group, name, &error ); | |
60 | if ( !error ) data.i = ii; | |
61 | break; | |
62 | } | |
63 | case VIK_LAYER_PARAM_BOOLEAN: { | |
64 | gboolean bb = g_key_file_get_boolean ( keyfile, group, name, &error ); | |
65 | if ( !error ) data.b = bb; | |
66 | break; | |
67 | } | |
68 | case VIK_LAYER_PARAM_STRING: { | |
69 | gchar *str = g_key_file_get_string ( keyfile, group, name, &error ); | |
70 | if ( !error ) data.s = str; | |
71 | break; | |
72 | } | |
73 | //case VIK_LAYER_PARAM_STRING_LIST: { | |
74 | // gchar **str = g_key_file_get_string_list ( keyfile, group, name, &error ); | |
75 | // data.sl = str_to_glist (str); //TODO convert | |
76 | // break; | |
77 | //} | |
78 | case VIK_LAYER_PARAM_COLOR: { | |
79 | gchar *str = g_key_file_get_string ( keyfile, group, name, &error ); | |
80 | if ( !error ) { | |
81 | memset(&(data.c), 0, sizeof(data.c)); | |
82 | gdk_color_parse ( str, &(data.c) ); | |
83 | } | |
84 | g_free ( str ); | |
85 | break; | |
86 | } | |
87 | default: break; | |
88 | } | |
6cc5daf1 | 89 | *success = GINT_TO_POINTER (TRUE); |
a7023a1b | 90 | if ( error ) { |
873fc9e4 | 91 | g_warning ( "%s", error->message ); |
a7023a1b | 92 | g_error_free ( error ); |
6cc5daf1 | 93 | *success = GINT_TO_POINTER (FALSE); |
a7023a1b RN |
94 | } |
95 | ||
96 | return data; | |
97 | } | |
98 | ||
20144311 | 99 | static VikLayerParamData get_default_data ( const gchar *group, const gchar *name, VikLayerParamType ptype ) |
a7023a1b | 100 | { |
20144311 RN |
101 | gpointer success = GINT_TO_POINTER (TRUE); |
102 | // NB This should always succeed - don't worry about 'success' | |
6cc5daf1 | 103 | return get_default_data_answer ( group, name, ptype, &success ); |
a7023a1b RN |
104 | } |
105 | ||
106 | static void set_default_data ( VikLayerParamData data, const gchar *group, const gchar *name, VikLayerParamType ptype ) | |
107 | { | |
108 | switch ( ptype ) { | |
109 | case VIK_LAYER_PARAM_DOUBLE: | |
110 | g_key_file_set_double ( keyfile, group, name, data.d ); | |
111 | break; | |
112 | case VIK_LAYER_PARAM_UINT: | |
113 | g_key_file_set_integer ( keyfile, group, name, data.u ); | |
114 | break; | |
115 | case VIK_LAYER_PARAM_INT: | |
116 | g_key_file_set_integer ( keyfile, group, name, data.i ); | |
117 | break; | |
118 | case VIK_LAYER_PARAM_BOOLEAN: | |
119 | g_key_file_set_boolean ( keyfile, group, name, data.b ); | |
120 | break; | |
121 | case VIK_LAYER_PARAM_STRING: | |
122 | g_key_file_set_string ( keyfile, group, name, data.s ); | |
123 | break; | |
124 | case VIK_LAYER_PARAM_COLOR: { | |
125 | gchar *str = g_strdup_printf ( "#%.2x%.2x%.2x", (int)(data.c.red/256),(int)(data.c.green/256),(int)(data.c.blue/256)); | |
126 | g_key_file_set_string ( keyfile, group, name, str ); | |
127 | g_free ( str ); | |
128 | break; | |
129 | } | |
130 | default: break; | |
131 | } | |
132 | } | |
133 | ||
134 | static void defaults_run_setparam ( gpointer index_ptr, guint16 i, VikLayerParamData data, VikLayerParam *params ) | |
135 | { | |
136 | // Index is only an index into values from this layer | |
137 | gint index = GPOINTER_TO_INT ( index_ptr ); | |
138 | VikLayerParam *vlp = (VikLayerParam *)g_ptr_array_index(paramsVD,index+i); | |
139 | ||
140 | set_default_data ( data, vik_layer_get_interface(vlp->layer)->fixed_layer_name, vlp->name, vlp->type ); | |
141 | } | |
142 | ||
143 | static VikLayerParamData defaults_run_getparam ( gpointer index_ptr, guint16 i, gboolean notused2 ) | |
144 | { | |
145 | // Index is only an index into values from this layer | |
146 | gint index = GPOINTER_TO_INT ( index_ptr ); | |
147 | VikLayerParam *vlp = (VikLayerParam *)g_ptr_array_index(paramsVD,index+i); | |
148 | ||
149 | return get_default_data ( vik_layer_get_interface(vlp->layer)->fixed_layer_name, vlp->name, vlp->type ); | |
150 | } | |
151 | ||
20144311 RN |
152 | static void use_internal_defaults_if_missing_default ( VikLayerTypeEnum type ) |
153 | { | |
154 | VikLayerParam *params = vik_layer_get_interface(type)->params; | |
155 | if ( ! params ) | |
156 | return; | |
157 | ||
158 | guint16 params_count = vik_layer_get_interface(type)->params_count; | |
159 | guint16 i; | |
160 | // Process each parameter | |
161 | for ( i = 0; i < params_count; i++ ) { | |
162 | if ( params[i].group != VIK_LAYER_NOT_IN_PROPERTIES ) { | |
163 | gpointer success = GINT_TO_POINTER (FALSE); | |
164 | // Check current default is available | |
6cc5daf1 | 165 | get_default_data_answer ( vik_layer_get_interface(type)->fixed_layer_name, params[i].name, params[i].type, &success ); |
20144311 RN |
166 | // If no longer have a viable default |
167 | if ( ! GPOINTER_TO_INT (success) ) { | |
168 | // Reset value | |
169 | if ( params[i].default_value ) { | |
170 | VikLayerParamData paramd = params[i].default_value(); | |
171 | set_default_data ( paramd, vik_layer_get_interface(type)->fixed_layer_name, params[i].name, params[i].type ); | |
172 | } | |
173 | } | |
174 | } | |
175 | } | |
176 | } | |
177 | ||
178 | static gboolean defaults_load_from_file() | |
179 | { | |
180 | GKeyFileFlags flags = G_KEY_FILE_KEEP_COMMENTS; | |
181 | ||
182 | GError *error = NULL; | |
183 | ||
184 | gchar *fn = g_build_filename ( a_get_viking_dir(), VIKING_LAYER_DEFAULTS_INI_FILE, NULL ); | |
185 | ||
186 | if ( !g_key_file_load_from_file ( keyfile, fn, flags, &error ) ) { | |
187 | g_warning ( "%s: %s", error->message, fn ); | |
188 | g_free ( fn ); | |
189 | g_error_free ( error ); | |
190 | return FALSE; | |
191 | } | |
192 | ||
193 | g_free ( fn ); | |
194 | ||
195 | // Ensure if have a key file, then any missing values are set from the internal defaults | |
196 | VikLayerTypeEnum layer; | |
197 | for ( layer = 0; layer < VIK_LAYER_NUM_TYPES; layer++ ) { | |
198 | use_internal_defaults_if_missing_default ( layer ); | |
199 | } | |
200 | ||
201 | return TRUE; | |
202 | } | |
203 | ||
a7023a1b RN |
204 | /* TRUE on success */ |
205 | static gboolean layer_defaults_save_to_file() | |
206 | { | |
207 | gboolean answer = TRUE; | |
208 | GError *error = NULL; | |
209 | gchar *fn = g_build_filename ( a_get_viking_dir(), VIKING_LAYER_DEFAULTS_INI_FILE, NULL ); | |
210 | gsize size; | |
211 | ||
212 | gchar *keyfilestr = g_key_file_to_data ( keyfile, &size, &error ); | |
213 | ||
214 | if ( error ) { | |
873fc9e4 | 215 | g_warning ( "%s", error->message ); |
a7023a1b RN |
216 | g_error_free ( error ); |
217 | answer = FALSE; | |
218 | goto tidy; | |
219 | } | |
220 | ||
221 | // optionally could do: | |
222 | // g_file_set_contents ( fn, keyfilestr, size, &error ); | |
223 | // if ( error ) { | |
224 | // g_warning ( "%s: %s", error->message, fn ); | |
225 | // g_error_free ( error ); | |
226 | // answer = FALSE; | |
227 | // goto tidy; | |
228 | // } | |
229 | ||
230 | FILE *ff; | |
231 | if ( !(ff = g_fopen ( fn, "w")) ) { | |
232 | g_warning ( _("Could not open file: %s"), fn ); | |
233 | answer = FALSE; | |
234 | goto tidy; | |
235 | } | |
236 | // Layer defaults not that secret, but just incase... | |
237 | g_chmod ( fn, 0600 ); | |
238 | ||
239 | fputs ( keyfilestr, ff ); | |
240 | fclose ( ff ); | |
241 | ||
242 | tidy: | |
243 | g_free ( keyfilestr ); | |
244 | g_free ( fn ); | |
245 | ||
246 | return answer; | |
247 | } | |
248 | ||
249 | /** | |
250 | * a_layer_defaults_show_window: | |
251 | * @parent: The Window | |
252 | * @layername: The layer | |
253 | * | |
254 | * This displays a Window showing the default parameter values for the selected layer | |
255 | * It allows the parameters to be changed. | |
256 | * | |
257 | * Returns: %TRUE if the window is displayed (because there are parameters to view) | |
258 | */ | |
259 | gboolean a_layer_defaults_show_window ( GtkWindow *parent, const gchar *layername ) | |
260 | { | |
261 | if ( ! loaded ) { | |
262 | // since we can't load the file in a_defaults_init (no params registered yet), | |
263 | // do it once before we display the params. | |
264 | defaults_load_from_file(); | |
265 | loaded = TRUE; | |
266 | } | |
267 | ||
268 | VikLayerTypeEnum layer = vik_layer_type_from_string ( layername ); | |
269 | ||
270 | // Need to know where the params start and they finish for this layer | |
271 | ||
272 | // 1. inspect every registered param - see if it has the layer value required to determine overall size | |
273 | // [they are contiguous from the start index] | |
274 | // 2. copy the these params from the main list into a tmp struct | |
275 | // | |
276 | // Then pass this tmp struct to uibuilder for display | |
277 | ||
278 | guint layer_params_count = 0; | |
279 | ||
280 | gboolean found_first = FALSE; | |
281 | gint index = 0; | |
282 | int i; | |
283 | for ( i = 0; i < paramsVD->len; i++ ) { | |
284 | VikLayerParam *param = (VikLayerParam*)(g_ptr_array_index(paramsVD,i)); | |
285 | if ( param->layer == layer ) { | |
286 | layer_params_count++; | |
287 | if ( !found_first ) { | |
288 | index = i; | |
289 | found_first = TRUE; | |
290 | } | |
291 | } | |
292 | } | |
293 | ||
294 | // Have we any parameters to show! | |
295 | if ( !layer_params_count ) | |
296 | return FALSE; | |
297 | ||
298 | VikLayerParam *params = g_new(VikLayerParam,layer_params_count); | |
299 | for ( i = 0; i < layer_params_count; i++ ) { | |
300 | params[i] = *((VikLayerParam*)(g_ptr_array_index(paramsVD,i+index))); | |
301 | } | |
302 | ||
303 | gchar *title = g_strconcat ( layername, ": ", _("Layer Defaults"), NULL ); | |
304 | ||
305 | if ( a_uibuilder_properties_factory ( title, | |
306 | parent, | |
307 | params, | |
308 | layer_params_count, | |
309 | vik_layer_get_interface(layer)->params_groups, | |
310 | vik_layer_get_interface(layer)->params_groups_count, | |
db43cfa4 | 311 | (gboolean (*) (gpointer,guint16,VikLayerParamData,gpointer,gboolean)) defaults_run_setparam, |
a7023a1b RN |
312 | GINT_TO_POINTER ( index ), |
313 | params, | |
314 | defaults_run_getparam, | |
db43cfa4 RN |
315 | GINT_TO_POINTER ( index ), |
316 | NULL ) ) { | |
a7023a1b RN |
317 | // Save |
318 | layer_defaults_save_to_file(); | |
319 | } | |
320 | ||
321 | g_free ( title ); | |
322 | g_free ( params ); | |
323 | ||
324 | return TRUE; | |
325 | } | |
326 | ||
327 | /** | |
328 | * a_layer_defaults_register: | |
329 | * @vlp: The parameter | |
330 | * @defaultval: The default value | |
331 | * @layername: The layer in which the parameter resides | |
332 | * | |
333 | * Call this function on to set the default value for the particular parameter | |
334 | */ | |
335 | void a_layer_defaults_register (VikLayerParam *vlp, VikLayerParamData defaultval, const gchar *layername ) | |
336 | { | |
337 | /* copy value */ | |
338 | VikLayerParam *newvlp = g_new(VikLayerParam,1); | |
339 | *newvlp = *vlp; | |
340 | ||
341 | g_ptr_array_add ( paramsVD, newvlp ); | |
342 | ||
343 | set_default_data ( defaultval, layername, vlp->name, vlp->type ); | |
344 | } | |
345 | ||
346 | /** | |
347 | * a_layer_defaults_init: | |
348 | * | |
349 | * Call this function at startup | |
350 | */ | |
351 | void a_layer_defaults_init() | |
352 | { | |
353 | keyfile = g_key_file_new(); | |
354 | ||
355 | /* not copied */ | |
356 | paramsVD = g_ptr_array_new (); | |
357 | ||
358 | loaded = FALSE; | |
359 | } | |
360 | ||
361 | /** | |
362 | * a_layer_defaults_uninit: | |
363 | * | |
364 | * Call this function on program exit | |
365 | */ | |
366 | void a_layer_defaults_uninit() | |
367 | { | |
368 | g_key_file_free ( keyfile ); | |
919ed63e | 369 | g_ptr_array_foreach ( paramsVD, (GFunc)g_free, NULL ); |
a7023a1b RN |
370 | g_ptr_array_free ( paramsVD, TRUE ); |
371 | } | |
372 | ||
373 | /** | |
374 | * a_layer_defaults_get: | |
375 | * @layername: String name of the layer | |
376 | * @param_name: String name of the parameter | |
377 | * @param_type: The parameter type | |
378 | * | |
379 | * Call this function to get the default value for the parameter requested | |
380 | */ | |
381 | VikLayerParamData a_layer_defaults_get ( const gchar *layername, const gchar *param_name, VikLayerParamType param_type ) | |
382 | { | |
383 | if ( ! loaded ) { | |
384 | // since we can't load the file in a_defaults_init (no params registered yet), | |
385 | // do it once before we get the first key. | |
386 | defaults_load_from_file(); | |
387 | loaded = TRUE; | |
388 | } | |
389 | ||
390 | return get_default_data ( layername, param_name, param_type ); | |
391 | } | |
c1b01373 RN |
392 | |
393 | /** | |
394 | * a_layer_defaults_save: | |
395 | * | |
396 | * Call this function to save the current layer defaults | |
397 | * Normally should only be performed if any layer defaults have been changed via direct manipulation of the layer | |
398 | * rather than the user changing the preferences via the dialog window above | |
399 | * | |
400 | * This must only be performed once all layer parameters have been initialized | |
401 | * | |
402 | * Returns: %TRUE if saving was successful | |
403 | */ | |
404 | gboolean a_layer_defaults_save () | |
405 | { | |
406 | // Generate defaults | |
407 | VikLayerTypeEnum layer; | |
408 | for ( layer = 0; layer < VIK_LAYER_NUM_TYPES; layer++ ) { | |
409 | use_internal_defaults_if_missing_default ( layer ); | |
410 | } | |
411 | ||
412 | return layer_defaults_save_to_file(); | |
413 | } |