1 /* PSPPIRE - a graphical user interface for PSPP.
2 Copyright (C) 2009, 2010 Free Software Foundation
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17 /*
18 This module provides an interface for simple user preference config
19 parameters.
20 */
21
22 #include <config.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include <sys/stat.h>
26
27 #include <glib.h>
28
29 #include "psppire-conf.h"
30
31 G_DEFINE_TYPE (PsppireConf, psppire_conf, G_TYPE_OBJECT)
32
33 static void psppire_conf_finalize (GObject *object);
34 static void psppire_conf_dispose (GObject *object);
35
36 static GObjectClass *parent_class = NULL;
37
38 static void
conf_read(PsppireConf * conf)39 conf_read (PsppireConf *conf)
40 {
41 g_key_file_load_from_file (conf->keyfile,
42 conf->filename,
43 G_KEY_FILE_KEEP_COMMENTS,
44 NULL);
45 }
46
47 static gboolean
flush_conf(PsppireConf * conf)48 flush_conf (PsppireConf *conf)
49 {
50 gsize length = 0;
51
52 gchar *kf = g_key_file_to_data (conf->keyfile, &length, NULL);
53 GError *err = NULL;
54
55 if (! g_file_set_contents (conf->filename, kf, length, &err))
56 {
57 g_warning ("Cannot open %s for writing: %s", conf->filename, err->message);
58 g_error_free (err);
59 }
60
61 g_free (kf);
62 conf->idle = 0;
63 return FALSE;
64 }
65
66 static void
conf_write(PsppireConf * conf)67 conf_write (PsppireConf *conf)
68 {
69 if (conf->idle == 0)
70 conf->idle = g_idle_add_full (G_PRIORITY_LOW,
71 (GSourceFunc) flush_conf, conf, NULL);
72 }
73
74
75 static void
psppire_conf_dispose(GObject * object)76 psppire_conf_dispose (GObject *object)
77 {
78 }
79
80 static void
psppire_conf_finalize(GObject * object)81 psppire_conf_finalize (GObject *object)
82 {
83 PsppireConf *conf = PSPPIRE_CONF (object);
84 g_key_file_free (conf->keyfile);
85 g_free (conf->filename);
86 }
87
88
89 static PsppireConf *the_instance = NULL;
90
91 static GObject*
psppire_conf_construct(GType type,guint n_construct_params,GObjectConstructParam * construct_params)92 psppire_conf_construct (GType type,
93 guint n_construct_params,
94 GObjectConstructParam *construct_params)
95 {
96 GObject *object;
97
98 if (!the_instance)
99 {
100 object = G_OBJECT_CLASS (parent_class)->constructor (type,
101 n_construct_params,
102 construct_params);
103 the_instance = PSPPIRE_CONF (object);
104 }
105 else
106 object = g_object_ref (G_OBJECT (the_instance));
107
108 return object;
109 }
110
111 static void
psppire_conf_class_init(PsppireConfClass * class)112 psppire_conf_class_init (PsppireConfClass *class)
113 {
114 GObjectClass *object_class;
115
116 parent_class = g_type_class_peek_parent (class);
117 object_class = G_OBJECT_CLASS (class);
118
119 object_class->finalize = psppire_conf_finalize;
120 object_class->dispose = psppire_conf_dispose;
121 object_class->constructor = psppire_conf_construct;
122 }
123
124
125 static void
psppire_conf_init(PsppireConf * conf)126 psppire_conf_init (PsppireConf *conf)
127 {
128 const gchar *dirname;
129 struct stat s;
130
131 /* Get the name of the directory for user configuration files, then, if it
132 doesn't already exist, create it, since we might be the first program
133 to want to put files there. */
134 dirname = g_get_user_config_dir ();
135 if (stat (dirname, &s) == -1 && errno == ENOENT)
136 mkdir (dirname, 0700);
137
138 conf->filename = g_strdup_printf ("%s/%s", dirname, "psppirerc");
139
140 conf->keyfile = g_key_file_new ();
141
142 conf->idle = 0;
143 }
144
145
146 PsppireConf *
psppire_conf_new(void)147 psppire_conf_new (void)
148 {
149 return g_object_new (psppire_conf_get_type (), NULL);
150 }
151
152
153
154 gboolean
psppire_conf_get_int(PsppireConf * conf,const gchar * base,const gchar * name,gint * value)155 psppire_conf_get_int (PsppireConf *conf, const gchar *base,
156 const gchar *name, gint *value)
157 {
158 gboolean ok;
159 GError *err = NULL;
160 conf_read (conf);
161 *value = g_key_file_get_integer (conf->keyfile,
162 base,
163 name, &err);
164
165 ok = (err == NULL);
166 if (err != NULL)
167 g_error_free (err);
168
169 return ok;
170 }
171
172 gboolean
psppire_conf_get_boolean(PsppireConf * conf,const gchar * base,const gchar * name,gboolean * value)173 psppire_conf_get_boolean (PsppireConf *conf, const gchar *base,
174 const gchar *name, gboolean *value)
175 {
176 gboolean ok;
177 gboolean b;
178 GError *err = NULL;
179 conf_read (conf);
180 b = g_key_file_get_boolean (conf->keyfile,
181 base,
182 name, &err);
183
184 ok = (err == NULL);
185 if (err != NULL)
186 g_error_free (err);
187
188 if (ok)
189 *value = b;
190
191 return ok;
192 }
193
194
195
196 gboolean
psppire_conf_get_string(PsppireConf * conf,const gchar * base,const gchar * name,gchar ** value)197 psppire_conf_get_string (PsppireConf *conf, const gchar *base,
198 const gchar *name, gchar **value)
199 {
200 gboolean ok;
201 gchar *b;
202 GError *err = NULL;
203 conf_read (conf);
204 b = g_key_file_get_string (conf->keyfile,
205 base,
206 name, &err);
207
208 ok = (err == NULL);
209 if (err != NULL)
210 g_error_free (err);
211
212 if (ok)
213 *value = b;
214
215 return ok;
216 }
217
218
219
220
221 gboolean
psppire_conf_get_variant(PsppireConf * conf,const gchar * base,const gchar * name,GVariant ** v)222 psppire_conf_get_variant (PsppireConf *conf, const gchar *base,
223 const gchar *name, GVariant **v)
224 {
225 gboolean ok;
226 gchar *b;
227 GError *err = NULL;
228 conf_read (conf);
229 b = g_key_file_get_string (conf->keyfile,
230 base,
231 name, &err);
232
233 ok = (err == NULL);
234 if (err != NULL)
235 g_error_free (err);
236
237 if (ok)
238 {
239 *v = g_variant_parse (NULL, b, NULL, NULL, NULL);
240 g_free (b);
241 }
242
243 return ok;
244 }
245
246 gboolean
psppire_conf_get_enum(PsppireConf * conf,const gchar * base,const gchar * name,GType t,int * v)247 psppire_conf_get_enum (PsppireConf *conf, const gchar *base,
248 const gchar *name,
249 GType t,
250 int *v)
251 {
252 gboolean ok;
253 gchar *b;
254 GError *err = NULL;
255 conf_read (conf);
256 b = g_key_file_get_string (conf->keyfile,
257 base,
258 name, &err);
259
260 ok = (err == NULL);
261 if (err != NULL)
262 g_error_free (err);
263
264 if (ok)
265 {
266 GEnumClass *ec = g_type_class_ref (t);
267 GEnumValue *ev = g_enum_get_value_by_nick (ec, b);
268 *v = ev->value;
269 g_type_class_unref (ec);
270 g_free (b);
271 }
272
273 return ok;
274 }
275
276 void
psppire_conf_set_int(PsppireConf * conf,const gchar * base,const gchar * name,gint value)277 psppire_conf_set_int (PsppireConf *conf,
278 const gchar *base, const gchar *name,
279 gint value)
280 {
281 g_key_file_set_integer (conf->keyfile, base, name, value);
282 conf_write (conf);
283 }
284
285 void
psppire_conf_set_boolean(PsppireConf * conf,const gchar * base,const gchar * name,gboolean value)286 psppire_conf_set_boolean (PsppireConf *conf,
287 const gchar *base, const gchar *name,
288 gboolean value)
289 {
290 g_key_file_set_boolean (conf->keyfile, base, name, value);
291 conf_write (conf);
292 }
293
294
295 void
psppire_conf_set_string(PsppireConf * conf,const gchar * base,const gchar * name,const gchar * value)296 psppire_conf_set_string (PsppireConf *conf,
297 const gchar *base, const gchar *name,
298 const gchar *value)
299 {
300 g_key_file_set_string (conf->keyfile, base, name, value);
301 conf_write (conf);
302 }
303
304 void
psppire_conf_set_variant(PsppireConf * conf,const gchar * base,const gchar * name,GVariant * value)305 psppire_conf_set_variant (PsppireConf *conf,
306 const gchar *base, const gchar *name,
307 GVariant *value)
308 {
309 gchar *v = g_variant_print (value, FALSE);
310 g_key_file_set_string (conf->keyfile, base, name, v);
311 conf_write (conf);
312 g_free (v);
313 }
314
315 void
psppire_conf_set_enum(PsppireConf * conf,const gchar * base,const gchar * name,GType enum_type,int value)316 psppire_conf_set_enum (PsppireConf *conf,
317 const gchar *base, const gchar *name,
318 GType enum_type,
319 int value)
320 {
321 GEnumClass *ec = g_type_class_ref (enum_type);
322 GEnumValue *ev = g_enum_get_value (ec, value);
323
324 g_key_file_set_string (conf->keyfile, base, name,
325 ev->value_nick);
326
327 g_type_class_unref (ec);
328
329 conf_write (conf);
330 }
331
332
333
334 /*
335 A convenience function to set the geometry of a
336 window from from a saved config
337 */
338 void
psppire_conf_set_window_geometry(PsppireConf * conf,const gchar * base,GtkWindow * window)339 psppire_conf_set_window_geometry (PsppireConf *conf,
340 const gchar *base,
341 GtkWindow *window)
342 {
343 gint height, width;
344 gint x, y;
345 gboolean maximize;
346
347 if (psppire_conf_get_int (conf, base, "height", &height)
348 &&
349 psppire_conf_get_int (conf, base, "width", &width))
350 {
351 gtk_window_set_default_size (window, width, height);
352 }
353
354 if (psppire_conf_get_int (conf, base, "x", &x)
355 &&
356 psppire_conf_get_int (conf, base, "y", &y))
357 {
358 gtk_window_move (window, x, y);
359 }
360
361 if (psppire_conf_get_boolean (conf, base, "maximize", &maximize))
362 {
363 if (maximize)
364 gtk_window_maximize (window);
365 else
366 gtk_window_unmaximize (window);
367 }
368 }
369
370
371 /*
372 A convenience function to save the window geometry.
373 This should typically be called from a window's
374 "configure-event" and "window-state-event" signal handlers
375 */
376 void
psppire_conf_save_window_geometry(PsppireConf * conf,const gchar * base,GtkWindow * gtk_window)377 psppire_conf_save_window_geometry (PsppireConf *conf,
378 const gchar *base,
379 GtkWindow *gtk_window)
380 {
381 gboolean maximized;
382 GdkWindow *w;
383
384 w = gtk_widget_get_window (GTK_WIDGET (gtk_window));
385 if (w == NULL)
386 return;
387
388 maximized = (gdk_window_get_state (w) & GDK_WINDOW_STATE_MAXIMIZED) != 0;
389 psppire_conf_set_boolean (conf, base, "maximize", maximized);
390
391 if (!maximized)
392 {
393 gint x, y;
394
395 gint width = gdk_window_get_width (w);
396 gint height= gdk_window_get_height (w);
397
398 gdk_window_get_position (w, &x, &y);
399
400 psppire_conf_set_int (conf, base, "height", height);
401 psppire_conf_set_int (conf, base, "width", width);
402 psppire_conf_set_int (conf, base, "x", x);
403 psppire_conf_set_int (conf, base, "y", y);
404 }
405 }
406