Revert "Keep systems happy which do not have sys/resource.h"
[pspp] / src / ui / gui / psppire-conf.c
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 static void psppire_conf_init            (PsppireConf      *conf);
32 static void psppire_conf_class_init      (PsppireConfClass *class);
33
34 static void psppire_conf_finalize        (GObject   *object);
35 static void psppire_conf_dispose        (GObject   *object);
36
37 static GObjectClass *parent_class = NULL;
38
39
40 GType
41 psppire_conf_get_type (void)
42 {
43   static GType conf_type = 0;
44
45   if (!conf_type)
46     {
47       static const GTypeInfo conf_info =
48       {
49         sizeof (PsppireConfClass),
50         NULL,           /* base_init */
51         NULL,           /* base_finalize */
52         (GClassInitFunc) psppire_conf_class_init,
53         NULL,           /* class_finalize */
54         NULL,           /* class_data */
55         sizeof (PsppireConf),
56         0,
57         (GInstanceInitFunc) psppire_conf_init,
58       };
59
60       conf_type = g_type_register_static (G_TYPE_OBJECT,
61                                                 "PsppireConf",
62                                                 &conf_info, 0);
63     }
64
65   return conf_type;
66 }
67
68
69 static void
70 conf_read (PsppireConf *conf)
71 {
72   g_key_file_load_from_file (conf->keyfile,
73                              conf->filename,
74                              G_KEY_FILE_KEEP_COMMENTS,
75                              NULL);
76 }
77
78 static gboolean
79 flush_conf (PsppireConf *conf)
80 {
81   gsize length = 0;
82
83   gchar *kf = g_key_file_to_data  (conf->keyfile, &length, NULL);
84
85   if (! g_file_set_contents (conf->filename, kf, length, NULL))
86     {
87       g_warning ("Cannot open %s for writing", conf->filename);
88     }
89
90   g_free (kf);
91   conf->idle = 0;
92   return FALSE;
93 }
94
95 static void
96 conf_write (PsppireConf *conf)
97 {
98   if (conf->idle == 0)
99     conf->idle = g_idle_add_full (G_PRIORITY_LOW,
100                                   (GSourceFunc) flush_conf, conf, NULL);
101 }
102
103
104 static void
105 psppire_conf_dispose  (GObject *object)
106 {
107 }
108
109 static void
110 psppire_conf_finalize (GObject *object)
111 {
112   PsppireConf *conf = PSPPIRE_CONF (object);
113   g_key_file_free (conf->keyfile);
114   g_free (conf->filename);
115 }
116
117
118 static PsppireConf *the_instance = NULL;
119
120 static GObject*
121 psppire_conf_construct   (GType                  type,
122                                      guint                  n_construct_params,
123                                      GObjectConstructParam *construct_params)
124 {
125   GObject *object;
126
127   if (!the_instance)
128     {
129       object = G_OBJECT_CLASS (parent_class)->constructor (type,
130                                                            n_construct_params,
131                                                            construct_params);
132       the_instance = PSPPIRE_CONF (object);
133     }
134   else
135     object = g_object_ref (G_OBJECT (the_instance));
136
137   return object;
138 }
139
140 static void
141 psppire_conf_class_init (PsppireConfClass *class)
142 {
143   GObjectClass *object_class;
144
145   parent_class = g_type_class_peek_parent (class);
146   object_class = (GObjectClass*) class;
147
148   object_class->finalize = psppire_conf_finalize;
149   object_class->dispose = psppire_conf_dispose;
150   object_class->constructor = psppire_conf_construct;
151 }
152
153
154 static void
155 psppire_conf_init (PsppireConf *conf)
156 {
157   const gchar *dirname;
158   struct stat s;
159
160   /* Get the name of the directory for user configuration files, then, if it
161      doesn't already exist, create it, since we might be the first program
162      to want to put files there. */
163   dirname = g_get_user_config_dir ();
164   if (stat (dirname, &s) == -1 && errno == ENOENT)
165     mkdir (dirname, 0700);
166
167   conf->filename = g_strdup_printf ("%s/%s", dirname, "psppirerc");
168
169   conf->keyfile = g_key_file_new ();
170
171   conf->idle = 0;
172 }
173
174
175 PsppireConf *
176 psppire_conf_new (void)
177 {
178   return g_object_new (psppire_conf_get_type (), NULL);
179 }
180
181
182
183 gboolean
184 psppire_conf_get_int (PsppireConf *conf, const gchar *base,
185                       const gchar *name, gint *value)
186 {
187   gboolean ok;
188   GError *err = NULL;
189   conf_read (conf);
190   *value = g_key_file_get_integer (conf->keyfile,
191                                    base,
192                                    name, &err);
193
194   ok = (err == NULL);
195   if (err != NULL)
196     g_error_free (err);
197
198   return ok;
199 }
200
201 gboolean
202 psppire_conf_get_boolean (PsppireConf *conf, const gchar *base,
203                           const gchar *name, gboolean *value)
204 {
205   gboolean ok;
206   gboolean b;
207   GError *err = NULL;
208   conf_read (conf);
209   b = g_key_file_get_boolean (conf->keyfile,
210                               base,
211                               name, &err);
212
213   ok = (err == NULL);
214   if (err != NULL)
215     g_error_free (err);
216
217   if (ok)
218     *value = b;
219
220   return ok;
221 }
222
223
224
225 gboolean
226 psppire_conf_get_string (PsppireConf *conf, const gchar *base,
227                          const gchar *name, gchar **value)
228 {
229   gboolean ok;
230   gchar *b;
231   GError *err = NULL;
232   conf_read (conf);
233   b = g_key_file_get_string (conf->keyfile,
234                              base,
235                              name, &err);
236
237   ok = (err == NULL);
238   if (err != NULL)
239     g_error_free (err);
240
241   if (ok)
242     *value = b;
243
244   return ok;
245 }
246
247
248
249
250 gboolean
251 psppire_conf_get_variant (PsppireConf *conf, const gchar *base,
252                           const gchar *name, GVariant **v)
253 {
254   gboolean ok;
255   gchar *b;
256   GError *err = NULL;
257   conf_read (conf);
258   b = g_key_file_get_string (conf->keyfile,
259                              base,
260                              name, &err);
261
262   ok = (err == NULL);
263   if (err != NULL)
264     g_error_free (err);
265
266   if (ok)
267     {
268       *v = g_variant_parse (NULL, b, NULL, NULL, NULL);
269       g_free (b);
270     }
271
272   return ok;
273 }
274
275 gboolean
276 psppire_conf_get_enum (PsppireConf *conf, const gchar *base,
277                        const gchar *name,
278                        GType t,
279                        int *v)
280 {
281   gboolean ok;
282   gchar *b;
283   GError *err = NULL;
284   conf_read (conf);
285   b = g_key_file_get_string (conf->keyfile,
286                              base,
287                              name, &err);
288
289   ok = (err == NULL);
290   if (err != NULL)
291     g_error_free (err);
292
293   if (ok)
294     {
295       GEnumClass *ec = g_type_class_ref (t);
296       GEnumValue *ev = g_enum_get_value_by_nick (ec, b);
297       *v = ev->value;
298       g_type_class_unref (ec);
299       g_free (b);
300     }
301
302   return ok;
303 }
304
305 void
306 psppire_conf_set_int (PsppireConf *conf,
307                       const gchar *base, const gchar *name,
308                       gint value)
309 {
310   g_key_file_set_integer (conf->keyfile, base, name, value);
311   conf_write (conf);
312 }
313
314 void
315 psppire_conf_set_boolean (PsppireConf *conf,
316                           const gchar *base, const gchar *name,
317                           gboolean value)
318 {
319   g_key_file_set_boolean (conf->keyfile, base, name, value);
320   conf_write (conf);
321 }
322
323
324 void
325 psppire_conf_set_string (PsppireConf *conf,
326                          const gchar *base, const gchar *name,
327                          const gchar *value)
328 {
329   g_key_file_set_string (conf->keyfile, base, name, value);
330   conf_write (conf);
331 }
332
333 void
334 psppire_conf_set_variant (PsppireConf *conf,
335                                const gchar *base, const gchar *name,
336                                GVariant *value)
337 {
338   gchar *v = g_variant_print (value, FALSE);
339   g_key_file_set_string (conf->keyfile, base, name, v);
340   conf_write (conf);
341   g_free (v);
342 }
343
344 void
345 psppire_conf_set_enum (PsppireConf *conf,
346                        const gchar *base, const gchar *name,
347                        GType enum_type,
348                        int value)
349 {
350   GEnumClass *ec = g_type_class_ref (enum_type);
351   GEnumValue *ev = g_enum_get_value (ec, value);
352
353   g_key_file_set_string (conf->keyfile, base, name,
354                          ev->value_nick);
355
356   g_type_class_unref (ec);
357
358   conf_write (conf);
359 }
360
361
362
363 /*
364   A convenience function to set the geometry of a
365   window from from a saved config
366 */
367 void
368 psppire_conf_set_window_geometry (PsppireConf *conf,
369                                   const gchar *base,
370                                   GtkWindow *window)
371 {
372   gint height, width;
373   gint x, y;
374   gboolean maximize;
375
376   if (psppire_conf_get_int (conf, base, "height", &height)
377       &&
378       psppire_conf_get_int (conf, base, "width", &width))
379     {
380       gtk_window_set_default_size (window, width, height);
381     }
382
383   if (psppire_conf_get_int (conf, base, "x", &x)
384        &&
385        psppire_conf_get_int (conf, base, "y", &y))
386     {
387       gtk_window_move (window, x, y);
388     }
389
390   if (psppire_conf_get_boolean (conf, base, "maximize", &maximize))
391     {
392       if (maximize)
393         gtk_window_maximize (window);
394       else
395         gtk_window_unmaximize (window);
396     }
397 }
398
399
400 /*
401    A convenience function to save the window geometry.
402    This should typically be called from a window's
403    "configure-event" and "window-state-event" signal handlers
404  */
405 void
406 psppire_conf_save_window_geometry (PsppireConf *conf,
407                                    const gchar *base,
408                                    GtkWindow *gtk_window)
409 {
410   gboolean maximized;
411   GdkWindow *w;
412
413   w = gtk_widget_get_window (GTK_WIDGET (gtk_window));
414   if (w == NULL)
415     return;
416
417   maximized = (gdk_window_get_state (w) & GDK_WINDOW_STATE_MAXIMIZED) != 0;
418   psppire_conf_set_boolean (conf, base, "maximize", maximized);
419
420   if (!maximized)
421     {
422       gint x, y;
423
424       gint width = gdk_window_get_width (w);
425       gint height= gdk_window_get_height (w);
426
427       gdk_window_get_position (w, &x, &y);
428
429       psppire_conf_set_int (conf, base, "height", height);
430       psppire_conf_set_int (conf, base, "width", width);
431       psppire_conf_set_int (conf, base, "x", x);
432       psppire_conf_set_int (conf, base, "y", y);
433     }
434 }