]> git.street.me.uk Git - andy/viking.git/blame - src/settings.c
CID#34561+CID#34569: Check return values
[andy/viking.git] / src / settings.c
CommitLineData
66b23637
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 /*
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
37static GKeyFile *keyfile;
38
39#define VIKING_INI_FILE "viking.ini"
40
41static 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
61void 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 */
73void 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 ) {
873fc9e4 82 g_warning ( "%s", error->message );
66b23637 83 g_error_free ( error );
919ed63e 84 goto tidy;
66b23637
RN
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 );
919ed63e
RN
94 tidy:
95 g_free ( keyfilestr );
96 g_free ( fn );
66b23637
RN
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
102static 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
417a52e5 109 g_debug ( "%s", error->message );
66b23637
RN
110 g_error_free ( error );
111 success = FALSE;
112 }
113 *val = bb;
114 return success;
115}
116
117gboolean a_settings_get_boolean ( const gchar *name, gboolean *val )
118{
119 return settings_get_boolean ( VIKING_SETTINGS_GROUP, name, val );
120}
121
122void a_settings_set_boolean ( const gchar *name, gboolean val )
123{
124 g_key_file_set_boolean ( keyfile, VIKING_SETTINGS_GROUP, name, val );
125}
126
127static 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
417a52e5 134 g_debug ( "%s", error->message );
66b23637
RN
135 g_error_free ( error );
136 success = FALSE;
137 }
138 *val = str;
139 return success;
140}
141
142gboolean a_settings_get_string ( const gchar *name, gchar **val )
143{
144 return settings_get_string ( VIKING_SETTINGS_GROUP, name, val );
145}
146
147void 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
152static 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
417a52e5 159 g_debug ( "%s", error->message );
66b23637
RN
160 g_error_free ( error );
161 success = FALSE;
162 }
163 *val = ii;
164 return success;
165}
166
167gboolean a_settings_get_integer ( const gchar *name, gint *val )
168{
169 return settings_get_integer ( VIKING_SETTINGS_GROUP, name, val );
170}
171
172void a_settings_set_integer ( const gchar *name, gint val )
173{
174 g_key_file_set_integer ( keyfile, VIKING_SETTINGS_GROUP, name, val );
175}
176
177static 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
417a52e5 184 g_debug ( "%s", error->message );
66b23637
RN
185 g_error_free ( error );
186 success = FALSE;
187 }
188 *val = dd;
189 return success;
190}
191
192gboolean a_settings_get_double ( const gchar *name, gdouble *val )
193{
194 return settings_get_double ( VIKING_SETTINGS_GROUP, name, val );
195}
196
197void a_settings_set_double ( const gchar *name, gdouble val )
198{
199 g_key_file_set_double ( keyfile, VIKING_SETTINGS_GROUP, name, val );
200}
b03ae39b
RN
201
202static 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 */
220static 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
225static 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
230gboolean 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
255void 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}