]> git.street.me.uk Git - andy/viking.git/blob - src/viklayer_defaults.c
Replace defunct IP to location lookup service.
[andy/viking.git] / src / viklayer_defaults.c
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
41 static VikLayerParamData get_default_data_answer ( const gchar *group, const gchar *name, VikLayerParamType ptype, gpointer *success )
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         }
89         *success = GINT_TO_POINTER (TRUE);
90         if ( error ) {
91                 g_warning ( "%s", error->message );
92                 g_error_free ( error );
93                 *success = GINT_TO_POINTER (FALSE);
94         }
95
96         return data;
97 }
98
99 static VikLayerParamData get_default_data ( const gchar *group, const gchar *name, VikLayerParamType ptype )
100 {
101         gpointer success = GINT_TO_POINTER (TRUE);
102         // NB This should always succeed - don't worry about 'success'
103         return get_default_data_answer ( group, name, ptype, &success );
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
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
165                         get_default_data_answer ( vik_layer_get_interface(type)->fixed_layer_name, params[i].name, params[i].type, &success );
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
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 ) {
215                 g_warning ( "%s", error->message );
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         if ( g_chmod ( fn, 0600 ) != 0 )
238                 g_warning ( "%s: Failed to set permissions on %s", __FUNCTION__, fn );
239
240         fputs ( keyfilestr, ff );
241         fclose ( ff );
242
243 tidy:
244         g_free ( keyfilestr );
245         g_free ( fn );
246
247         return answer;
248 }
249
250 /**
251  * a_layer_defaults_show_window:
252  * @parent:     The Window
253  * @layername:  The layer
254  *
255  * This displays a Window showing the default parameter values for the selected layer
256  * It allows the parameters to be changed.
257  *
258  * Returns: %TRUE if the window is displayed (because there are parameters to view)
259  */
260 gboolean a_layer_defaults_show_window ( GtkWindow *parent, const gchar *layername )
261 {
262         if ( ! loaded ) {
263                 // since we can't load the file in a_defaults_init (no params registered yet),
264                 // do it once before we display the params.
265                 defaults_load_from_file();
266                 loaded = TRUE;
267         }
268   
269     VikLayerTypeEnum layer = vik_layer_type_from_string ( layername );
270     
271     // Need to know where the params start and they finish for this layer
272
273     // 1. inspect every registered param - see if it has the layer value required to determine overall size
274     //    [they are contiguous from the start index]
275     // 2. copy the these params from the main list into a tmp struct
276     // 
277     // Then pass this tmp struct to uibuilder for display
278
279     guint layer_params_count = 0;
280     
281     gboolean found_first = FALSE;
282     gint index = 0;
283     int i;
284     for ( i = 0; i < paramsVD->len; i++ ) {
285                 VikLayerParam *param = (VikLayerParam*)(g_ptr_array_index(paramsVD,i));
286                 if ( param->layer == layer ) {
287                         layer_params_count++;
288                         if ( !found_first ) {
289                                 index = i;
290                                 found_first = TRUE;
291                         }
292                 }
293     }
294
295         // Have we any parameters to show!
296     if ( !layer_params_count )
297                 return FALSE;
298
299     VikLayerParam *params = g_new(VikLayerParam,layer_params_count);
300     for ( i = 0; i < layer_params_count; i++ ) {
301       params[i] = *((VikLayerParam*)(g_ptr_array_index(paramsVD,i+index)));
302     }
303
304     gchar *title = g_strconcat ( layername, ": ", _("Layer Defaults"), NULL );
305     
306         if ( a_uibuilder_properties_factory ( title,
307                                               parent,
308                                               params,
309                                               layer_params_count,
310                                               vik_layer_get_interface(layer)->params_groups,
311                                               vik_layer_get_interface(layer)->params_groups_count,
312                                               (gboolean (*) (gpointer,guint16,VikLayerParamData,gpointer,gboolean)) defaults_run_setparam,
313                                               GINT_TO_POINTER ( index ),
314                                               params,
315                                               defaults_run_getparam,
316                                               GINT_TO_POINTER ( index ),
317                                               NULL ) ) {
318                 // Save
319                 layer_defaults_save_to_file();
320     }
321     
322     g_free ( title );
323     g_free ( params );
324     
325     return TRUE;
326 }
327
328 /**
329  * a_layer_defaults_register:
330  * @vlp:        The parameter
331  * @defaultval: The default value
332  * @layername:  The layer in which the parameter resides
333  *
334  * Call this function on to set the default value for the particular parameter
335  */
336 void a_layer_defaults_register (VikLayerParam *vlp, VikLayerParamData defaultval, const gchar *layername )
337 {
338         /* copy value */
339         VikLayerParam *newvlp = g_new(VikLayerParam,1);
340         *newvlp = *vlp;
341
342         g_ptr_array_add ( paramsVD, newvlp );
343
344         set_default_data ( defaultval, layername, vlp->name, vlp->type );
345 }
346
347 /**
348  * a_layer_defaults_init:
349  *
350  * Call this function at startup
351  */
352 void a_layer_defaults_init()
353 {
354         keyfile = g_key_file_new();
355
356         /* not copied */
357         paramsVD = g_ptr_array_new ();
358
359         loaded = FALSE;
360 }
361
362 /**
363  * a_layer_defaults_uninit:
364  *
365  * Call this function on program exit
366  */
367 void a_layer_defaults_uninit()
368 {
369         g_key_file_free ( keyfile );    
370         g_ptr_array_foreach ( paramsVD, (GFunc)g_free, NULL );
371         g_ptr_array_free ( paramsVD, TRUE );
372 }
373
374 /**
375  * a_layer_defaults_get:
376  * @layername:  String name of the layer
377  * @param_name: String name of the parameter
378  * @param_type: The parameter type
379  *
380  * Call this function to get the default value for the parameter requested
381  */
382 VikLayerParamData a_layer_defaults_get ( const gchar *layername, const gchar *param_name, VikLayerParamType param_type )
383 {
384         if ( ! loaded ) {
385                 // since we can't load the file in a_defaults_init (no params registered yet),
386                 // do it once before we get the first key.
387                 defaults_load_from_file();
388                 loaded = TRUE;
389         }
390   
391         return get_default_data ( layername, param_name, param_type );
392 }
393
394 /**
395  * a_layer_defaults_save:
396  *
397  * Call this function to save the current layer defaults
398  * Normally should only be performed if any layer defaults have been changed via direct manipulation of the layer
399  *  rather than the user changing the preferences via the dialog window above
400  *
401  * This must only be performed once all layer parameters have been initialized
402  *
403  * Returns: %TRUE if saving was successful
404  */
405 gboolean a_layer_defaults_save ()
406 {
407         // Generate defaults
408         VikLayerTypeEnum layer;
409         for ( layer = 0; layer < VIK_LAYER_NUM_TYPES; layer++ ) {
410                 use_internal_defaults_if_missing_default ( layer );
411         }
412
413         return layer_defaults_save_to_file();
414 }