]> git.street.me.uk Git - andy/viking.git/blob - src/settings.c
Fix needing to calculate bounds of *both* tracks when a track is split via the marker.
[andy/viking.git] / src / settings.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  /*
23   * Sort of like the globals file, but values are automatically saved via program use.
24   * Some settings are *not* intended to have any GUI controls.
25   * Other settings be can used to set other GUI elements.
26   *
27   * ATM This is implemented using the simple (for me!) GKeyFile API - AKA an .ini file
28   *  One might wish to consider the more modern alternative such as:
29   *            http://developer.gnome.org/gio/2.26/GSettings.html
30   * Since these settings are 'internal' I have no problem with them *not* being supported
31   *  between various Viking versions, should one switch to different API/storage methods.
32   * Indeed even the internal settings themselves can be liable to change.
33   */
34 #include <glib.h>
35 #include "dir.h"
36
37 static GKeyFile *keyfile;
38
39 #define VIKING_INI_FILE "viking.ini"
40
41 static gboolean settings_load_from_file()
42 {
43         GKeyFileFlags flags = G_KEY_FILE_KEEP_COMMENTS;
44
45         GError *error = NULL;
46
47         gchar *fn = g_build_filename ( a_get_viking_dir(), VIKING_INI_FILE, NULL );
48
49         if ( !g_key_file_load_from_file ( keyfile, fn, flags, &error ) ) {
50                 g_warning ( "%s: %s", error->message, fn );
51                 g_free ( fn );
52                 g_error_free ( error );
53                 return FALSE;
54         }
55
56         g_free ( fn );
57
58         return TRUE;
59 }
60
61 void a_settings_init()
62 {
63         keyfile = g_key_file_new();
64         settings_load_from_file();
65 }
66
67 /**
68  * a_settings_uninit:
69  *
70  *  ATM: The only time settings are saved is on program exit
71  *   Could change this to occur on window exit or dialog exit or have memory hash of values...?
72  */
73 void a_settings_uninit()
74 {
75         GError *error = NULL;
76         gchar *fn = g_build_filename ( a_get_viking_dir(), VIKING_INI_FILE, NULL );
77         gsize size;
78
79         gchar *keyfilestr = g_key_file_to_data ( keyfile, &size, &error );
80
81         if ( error ) {
82                 g_warning ( "%s", error->message );
83                 g_error_free ( error );
84                 goto tidy;
85         }
86
87         g_file_set_contents ( fn, keyfilestr, size, &error );
88         if ( error ) {
89                 g_warning ( "%s: %s", error->message, fn );
90                 g_error_free ( error );
91         }
92
93         g_key_file_free ( keyfile );
94  tidy:
95         g_free ( keyfilestr );
96         g_free ( fn );
97 }
98
99 // ATM, can't see a point in having any more than one group for various settings
100 #define VIKING_SETTINGS_GROUP "viking"
101
102 static gboolean settings_get_boolean ( const gchar *group, const gchar *name, gboolean *val )
103 {
104         GError *error = NULL;
105         gboolean success = TRUE;
106         gboolean bb = g_key_file_get_boolean ( keyfile, group, name, &error );
107         if ( error ) {
108                 // Only print on debug - as often may have requests for keys not in the file
109                 g_debug ( "%s", error->message );
110                 g_error_free ( error );
111                 success = FALSE;
112         }
113         *val = bb;
114         return success;
115 }
116
117 gboolean a_settings_get_boolean ( const gchar *name, gboolean *val )
118 {
119         return settings_get_boolean ( VIKING_SETTINGS_GROUP, name, val );
120 }
121
122 void a_settings_set_boolean ( const gchar *name, gboolean val )
123 {
124         g_key_file_set_boolean ( keyfile, VIKING_SETTINGS_GROUP, name, val );
125 }
126
127 static gboolean settings_get_string ( const gchar *group, const gchar *name, gchar **val )
128 {
129         GError *error = NULL;
130         gboolean success = TRUE;
131         gchar *str = g_key_file_get_string ( keyfile, group, name, &error );
132         if ( error ) {
133                 // Only print on debug - as often may have requests for keys not in the file
134                 g_debug ( "%s", error->message );
135                 g_error_free ( error );
136                 success = FALSE;
137         }
138         *val = str;
139         return success;
140 }
141
142 gboolean a_settings_get_string ( const gchar *name, gchar **val )
143 {
144         return settings_get_string ( VIKING_SETTINGS_GROUP, name, val );
145 }
146
147 void a_settings_set_string ( const gchar *name, const gchar *val )
148 {
149         g_key_file_set_string ( keyfile, VIKING_SETTINGS_GROUP, name, val );
150 }
151
152 static gboolean settings_get_integer ( const gchar *group, const gchar *name, gint *val )
153 {
154         GError *error = NULL;
155         gboolean success = TRUE;
156         gint ii = g_key_file_get_integer ( keyfile, group, name, &error );
157         if ( error ) {
158                 // Only print on debug - as often may have requests for keys not in the file
159                 g_debug ( "%s", error->message );
160                 g_error_free ( error );
161                 success = FALSE;
162         }
163         *val = ii;
164         return success;
165 }
166
167 gboolean a_settings_get_integer ( const gchar *name, gint *val )
168 {
169         return settings_get_integer ( VIKING_SETTINGS_GROUP, name, val );
170 }
171
172 void a_settings_set_integer ( const gchar *name, gint val )
173 {
174         g_key_file_set_integer ( keyfile, VIKING_SETTINGS_GROUP, name, val );
175 }
176
177 static gboolean settings_get_double ( const gchar *group, const gchar *name, gdouble *val )
178 {
179         GError *error = NULL;
180         gboolean success = TRUE;
181         gdouble dd = g_key_file_get_double ( keyfile, group, name, &error );
182         if ( error ) {
183                 // Only print on debug - as often may have requests for keys not in the file
184                 g_debug ( "%s", error->message );
185                 g_error_free ( error );
186                 success = FALSE;
187         }
188         *val = dd;
189         return success;
190 }
191
192 gboolean a_settings_get_double ( const gchar *name, gdouble *val )
193 {
194         return settings_get_double ( VIKING_SETTINGS_GROUP, name, val );
195 }
196
197 void a_settings_set_double ( const gchar *name, gdouble val )
198 {
199         g_key_file_set_double ( keyfile, VIKING_SETTINGS_GROUP, name, val );
200 }
201
202 static gboolean settings_get_integer_list ( const gchar *group, const gchar *name, gint **vals, gsize *length )
203 {
204         GError *error = NULL;
205         gboolean success = TRUE;
206         gint *ints = g_key_file_get_integer_list ( keyfile, group, name, length, &error );
207         if ( error ) {
208                 // Only print on debug - as often may have requests for keys not in the file
209                 g_debug ( "%s", error->message );
210                 g_error_free ( error );
211                 success = FALSE;
212         }
213         *vals = ints;
214         return success;
215 }
216
217 /*
218  * The returned list of integers should be freed when no longer needed
219  */
220 static gboolean a_settings_get_integer_list ( const gchar *name, gint **vals, gsize* length )
221 {
222         return settings_get_integer_list ( VIKING_SETTINGS_GROUP, name, vals, length );
223 }
224
225 static void a_settings_set_integer_list ( const gchar *name, gint vals[], gsize length )
226 {
227         g_key_file_set_integer_list ( keyfile, VIKING_SETTINGS_GROUP, name, vals, length );
228 }
229
230 gboolean a_settings_get_integer_list_contains ( const gchar *name, gint val )
231 {
232         gint* vals = NULL;
233         gsize length;
234         // Get current list and see if the value supplied is in the list
235         gboolean contains = FALSE;
236         // Get current list
237         if ( a_settings_get_integer_list ( name, &vals, &length ) ) {
238                 // See if it's not already there
239                 gint ii = 0;
240                 if ( vals && length ) {
241                         while ( ii < length ) {
242                                 if ( vals[ii] == val ) {
243                                         contains = TRUE;
244                                         break;
245                                 }
246                                 ii++;
247                         }
248                         // Free old array
249                         g_free (vals);
250                 }
251         }
252         return contains;
253 }
254
255 void a_settings_set_integer_list_containing ( const gchar *name, gint val )
256 {
257         gint* vals = NULL;
258         gsize length;
259         gboolean need_to_add = TRUE;
260         gint ii = 0;
261         // Get current list
262         if ( a_settings_get_integer_list ( name, &vals, &length ) ) {
263                 // See if it's not already there
264                 if ( vals && length ) {
265                         while ( ii < length ) {
266                                 if ( vals[ii] == val ) {
267                                         need_to_add = FALSE;
268                                         break;
269                                 }
270                                 ii++;
271                         }
272                 }
273         }
274         // Add value into array if necessary
275         if ( need_to_add ) {
276                 // NB not bothering to sort this 'list' ATM as there is not much to be gained
277                 guint new_length = length + 1;
278                 gint new_vals[new_length];
279                 // Copy array
280                 for ( ii = 0; ii < length; ii++ ) {
281                         new_vals[ii] = vals[ii];
282                 }
283                 new_vals[length] = val; // Set the new value
284                 // Apply
285                 a_settings_set_integer_list ( name, new_vals, new_length );
286                 // Free old array
287                 g_free (vals);
288         }
289 }