1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20
21 #include "config.h"
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <signal.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31
32 #include <glib.h>
33 #include <glib/gi18n.h>
34 #include <glib/gstdio.h>
35 #include <glib-object.h>
36 #include <gio/gio.h>
37
38 #include "gdm-settings.h"
39
40 #include "gdm-settings-desktop-backend.h"
41
42 #define GDM_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SETTINGS, GdmSettingsPrivate))
43
44 struct GdmSettingsPrivate
45 {
46 GList *backends;
47 };
48
49 enum {
50 VALUE_CHANGED,
51 LAST_SIGNAL
52 };
53
54 static guint signals [LAST_SIGNAL] = { 0, };
55
56 static void gdm_settings_class_init (GdmSettingsClass *klass);
57 static void gdm_settings_init (GdmSettings *settings);
58 static void gdm_settings_finalize (GObject *object);
59
60 static gpointer settings_object = NULL;
61
G_DEFINE_TYPE(GdmSettings,gdm_settings,G_TYPE_OBJECT)62 G_DEFINE_TYPE (GdmSettings, gdm_settings, G_TYPE_OBJECT)
63
64 GQuark
65 gdm_settings_error_quark (void)
66 {
67 static GQuark ret = 0;
68 if (ret == 0) {
69 ret = g_quark_from_static_string ("gdm_settings_error");
70 }
71
72 return ret;
73 }
74
75 gboolean
gdm_settings_get_value(GdmSettings * settings,const char * key,char ** value,GError ** error)76 gdm_settings_get_value (GdmSettings *settings,
77 const char *key,
78 char **value,
79 GError **error)
80 {
81 GError *local_error;
82 gboolean res;
83 GList *l;
84
85 g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE);
86 g_return_val_if_fail (key != NULL, FALSE);
87
88 local_error = NULL;
89
90 for (l = settings->priv->backends; l; l = g_list_next (l)) {
91 GdmSettingsBackend *backend = l->data;
92
93 if (local_error) {
94 g_error_free (local_error);
95 local_error = NULL;
96 }
97
98 res = gdm_settings_backend_get_value (backend,
99 key,
100 value,
101 &local_error);
102 if (res)
103 break;
104 }
105 if (! res) {
106 g_propagate_error (error, local_error);
107 }
108
109 return res;
110 }
111
112 gboolean
gdm_settings_set_value(GdmSettings * settings,const char * key,const char * value,GError ** error)113 gdm_settings_set_value (GdmSettings *settings,
114 const char *key,
115 const char *value,
116 GError **error)
117 {
118 GError *local_error;
119 gboolean res;
120 GList *l;
121
122 g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE);
123 g_return_val_if_fail (key != NULL, FALSE);
124
125 g_debug ("Setting value %s", key);
126
127 local_error = NULL;
128
129 for (l = settings->priv->backends; l; l = g_list_next (l)) {
130 GdmSettingsBackend *backend = l->data;
131
132 if (local_error) {
133 g_error_free (local_error);
134 local_error = NULL;
135 }
136
137 res = gdm_settings_backend_set_value (backend,
138 key,
139 value,
140 &local_error);
141 if (res)
142 break;
143 }
144
145 if (! res) {
146 g_propagate_error (error, local_error);
147 }
148
149 return res;
150 }
151
152 static void
gdm_settings_class_init(GdmSettingsClass * klass)153 gdm_settings_class_init (GdmSettingsClass *klass)
154 {
155 GObjectClass *object_class = G_OBJECT_CLASS (klass);
156
157 object_class->finalize = gdm_settings_finalize;
158
159 signals [VALUE_CHANGED] =
160 g_signal_new ("value-changed",
161 G_TYPE_FROM_CLASS (object_class),
162 G_SIGNAL_RUN_LAST,
163 G_STRUCT_OFFSET (GdmSettingsClass, value_changed),
164 NULL,
165 NULL,
166 g_cclosure_marshal_generic,
167 G_TYPE_NONE,
168 3,
169 G_TYPE_STRING,
170 G_TYPE_STRING,
171 G_TYPE_STRING);
172
173 g_type_class_add_private (klass, sizeof (GdmSettingsPrivate));
174 }
175
176 static void
backend_value_changed(GdmSettingsBackend * backend,const char * key,const char * old_value,const char * new_value,GdmSettings * settings)177 backend_value_changed (GdmSettingsBackend *backend,
178 const char *key,
179 const char *old_value,
180 const char *new_value,
181 GdmSettings *settings)
182 {
183 g_debug ("Emitting value-changed %s %s %s", key, old_value, new_value);
184
185 /* proxy it to internal listeners */
186 g_signal_emit (settings, signals [VALUE_CHANGED], 0, key, old_value, new_value);
187 }
188
189 static void
gdm_settings_init(GdmSettings * settings)190 gdm_settings_init (GdmSettings *settings)
191 {
192 GList *l;
193 GdmSettingsBackend *backend;
194
195 settings->priv = GDM_SETTINGS_GET_PRIVATE (settings);
196
197 backend = gdm_settings_desktop_backend_new (GDM_CUSTOM_CONF);
198 if (backend)
199 settings->priv->backends = g_list_prepend (NULL, backend);
200
201 backend = gdm_settings_desktop_backend_new (GDM_RUNTIME_CONF);
202 if (backend)
203 settings->priv->backends = g_list_prepend (settings->priv->backends, backend);
204
205 for (l = settings->priv->backends; l; l = g_list_next (l)) {
206 backend = l->data;
207
208 g_signal_connect (backend,
209 "value-changed",
210 G_CALLBACK (backend_value_changed),
211 settings);
212 }
213 }
214
215 static void
gdm_settings_finalize(GObject * object)216 gdm_settings_finalize (GObject *object)
217 {
218 GdmSettings *settings;
219
220 g_return_if_fail (object != NULL);
221 g_return_if_fail (GDM_IS_SETTINGS (object));
222
223 settings = GDM_SETTINGS (object);
224
225 g_return_if_fail (settings->priv != NULL);
226
227 g_list_foreach (settings->priv->backends, (GFunc) g_object_unref, NULL);
228 g_list_free (settings->priv->backends);
229 settings->priv->backends = NULL;
230
231 settings_object = NULL;
232
233 G_OBJECT_CLASS (gdm_settings_parent_class)->finalize (object);
234 }
235
236 GdmSettings *
gdm_settings_new(void)237 gdm_settings_new (void)
238 {
239 if (settings_object != NULL) {
240 g_object_ref (settings_object);
241 } else {
242 settings_object = g_object_new (GDM_TYPE_SETTINGS, NULL);
243 }
244
245 return GDM_SETTINGS (settings_object);
246 }
247