02cc2751212a2a0de931fe7a2b9e722b342255e2
[pspp-builds.git] / 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 "psppire-conf.h"
28
29 static void psppire_conf_init            (PsppireConf      *conf);
30 static void psppire_conf_class_init      (PsppireConfClass *class);
31
32 static void psppire_conf_finalize        (GObject   *object);
33 static void psppire_conf_dispose        (GObject   *object);
34
35 static GObjectClass *parent_class = NULL;
36
37
38 GType
39 psppire_conf_get_type (void)
40 {
41   static GType conf_type = 0;
42
43   if (!conf_type)
44     {
45       static const GTypeInfo conf_info =
46       {
47         sizeof (PsppireConfClass),
48         NULL,           /* base_init */
49         NULL,           /* base_finalize */
50         (GClassInitFunc) psppire_conf_class_init,
51         NULL,           /* class_finalize */
52         NULL,           /* class_data */
53         sizeof (PsppireConf),
54         0,
55         (GInstanceInitFunc) psppire_conf_init,
56       };
57
58       conf_type = g_type_register_static (G_TYPE_OBJECT,
59                                                 "PsppireConf",
60                                                 &conf_info, 0);
61     }
62
63   return conf_type;
64 }
65
66
67 static void
68 conf_read (PsppireConf *conf)
69 {
70   g_key_file_load_from_file (conf->keyfile,
71                              conf->filename,
72                              G_KEY_FILE_KEEP_COMMENTS,
73                              NULL);
74 }
75
76 static void
77 conf_write (PsppireConf *conf)
78 {
79   gsize length = 0;
80
81   gchar *kf = g_key_file_to_data  (conf->keyfile, &length, NULL);
82
83   if ( ! g_file_set_contents (conf->filename, kf, length, NULL) )
84     {
85       g_warning ("Cannot open %s for writing", conf->filename);
86     }
87
88   g_free (kf);
89 }
90
91 static void
92 psppire_conf_dispose  (GObject *object)
93 {
94 }
95
96 static void
97 psppire_conf_finalize (GObject *object)
98 {
99   PsppireConf *conf = PSPPIRE_CONF (object);
100   g_key_file_free (conf->keyfile);
101   g_free (conf->filename);
102 }
103
104
105 static PsppireConf *the_instance = NULL;
106
107 static GObject*
108 psppire_conf_construct   (GType                  type,
109                                      guint                  n_construct_params,
110                                      GObjectConstructParam *construct_params)
111 {
112   GObject *object;
113
114   if (!the_instance)
115     {
116       object = G_OBJECT_CLASS (parent_class)->constructor (type,
117                                                            n_construct_params,
118                                                            construct_params);
119       the_instance = PSPPIRE_CONF (object);
120     }
121   else
122     object = g_object_ref (G_OBJECT (the_instance));
123
124   return object;
125 }
126
127 static void
128 psppire_conf_class_init (PsppireConfClass *class)
129 {
130   GObjectClass *object_class;
131
132   parent_class = g_type_class_peek_parent (class);
133   object_class = (GObjectClass*) class;
134
135   object_class->finalize = psppire_conf_finalize;
136   object_class->dispose = psppire_conf_dispose;
137   object_class->constructor = psppire_conf_construct;
138
139 }
140
141
142 static void
143 psppire_conf_init (PsppireConf *conf)
144 {
145   const gchar *dirname;
146   struct stat s;
147
148   /* Get the name of the directory for user configuration files, then, if it
149      doesn't already exist, create it, since we might be the first program
150      to want to put files there. */
151   dirname = g_get_user_config_dir ();
152   if (stat (dirname, &s) == -1 && errno == ENOENT)
153     mkdir (dirname, 0700);
154
155   conf->filename = g_strdup_printf ("%s/%s", dirname, "psppirerc");
156
157   conf->keyfile = g_key_file_new ();
158
159   conf->dispose_has_run = FALSE;
160 }
161
162
163 PsppireConf *
164 psppire_conf_new (void)
165 {
166   return g_object_new (psppire_conf_get_type (), NULL);
167 }
168
169
170
171 gboolean
172 psppire_conf_get_int (PsppireConf *conf, const gchar *base,
173                       const gchar *name, gint *value)
174 {
175   gboolean ok;
176   GError *err = NULL;
177   conf_read (conf);
178   *value = g_key_file_get_integer (conf->keyfile,
179                                    base,
180                                    name, &err);
181
182   ok = (err == NULL);
183   if ( err != NULL )
184     g_error_free (err);
185
186   return ok;
187 }
188
189 gboolean
190 psppire_conf_get_boolean (PsppireConf *conf, const gchar *base,
191                           const gchar *name, gboolean *value)
192 {
193   gboolean ok;
194   gboolean b;
195   GError *err = NULL;
196   conf_read (conf);
197   b = g_key_file_get_boolean (conf->keyfile,
198                               base,
199                               name, &err);
200
201   ok = (err == NULL);
202   if ( err != NULL )
203     g_error_free (err);
204
205   if (ok)
206     *value = b;
207
208   return ok;
209 }
210
211
212 void
213 psppire_conf_set_int (PsppireConf *conf,
214                       const gchar *base, const gchar *name,
215                       gint value)
216 {
217   g_key_file_set_integer (conf->keyfile, base, name, value);
218   conf_write (conf);
219 }
220
221 void
222 psppire_conf_set_boolean (PsppireConf *conf,
223                           const gchar *base, const gchar *name,
224                           gboolean value)
225 {
226   g_key_file_set_boolean (conf->keyfile, base, name, value);
227   conf_write (conf);
228 }
229
230 /*
231   A convenience function to set the geometry of a
232   window from from a saved config
233 */
234 void
235 psppire_conf_set_window_geometry (PsppireConf *conf,
236                                   const gchar *base,
237                                   GtkWindow *window)
238 {
239   gint height, width;
240   gint x, y;
241   gboolean maximize;
242
243   if (psppire_conf_get_int (conf, base, "height", &height)
244       &&
245       psppire_conf_get_int (conf, base, "width", &width) )
246     {
247       gtk_window_set_default_size (window, width, height);
248     }
249
250   if ( psppire_conf_get_int (conf, base, "x", &x)
251        &&
252        psppire_conf_get_int (conf, base, "y", &y) )
253     {
254       gtk_window_move (window, x, y);
255     }
256
257   if ( psppire_conf_get_boolean (conf, base, "maximize", &maximize))
258     {
259       if (maximize)
260         gtk_window_maximize (window);
261       else
262         gtk_window_unmaximize (window);
263     }
264 }
265
266
267 /*
268    A convenience function to save the window geometry.
269    This should typically be called from a window's
270    "configure-event" and "window-state-event" signal handlers
271  */
272 void
273 psppire_conf_save_window_geometry (PsppireConf *conf,
274                                    const gchar *base,
275                                    GtkWindow *gtk_window)
276 {
277   gboolean maximized;
278   GdkWindow *w;
279
280   w = gtk_widget_get_window (GTK_WIDGET (gtk_window));
281   if (w == NULL)
282     return;
283
284   maximized = (gdk_window_get_state (w) & GDK_WINDOW_STATE_MAXIMIZED) != 0;
285   psppire_conf_set_boolean (conf, base, "maximize", maximized);
286
287   if (!maximized)
288     {
289       gint width, height;
290       gint x, y;
291
292       gdk_drawable_get_size (w, &width, &height);
293       gdk_window_get_position (w, &x, &y);
294
295       psppire_conf_set_int (conf, base, "height", height);
296       psppire_conf_set_int (conf, base, "width", width);
297       psppire_conf_set_int (conf, base, "x", x);
298       psppire_conf_set_int (conf, base, "y", y);
299     }
300 }