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