2 * Copyright (C) 1999, 2000 Red Hat Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gconf-changeset.h"
21 #include "gconf-internals.h"
29 typedef struct _Change Change;
37 static Change* change_new (const gchar* key);
38 static void change_set (Change* c, GConfValue* value);
39 static void change_unset (Change* c);
40 static void change_destroy(Change* c);
42 struct _GConfChangeSet {
47 GDestroyNotify dnotify;
51 gconf_change_set_get_type (void)
53 static GType our_type = 0;
56 our_type = g_boxed_type_register_static ("GConfChangeSet",
57 (GBoxedCopyFunc) gconf_change_set_ref,
58 (GBoxedFreeFunc) gconf_change_set_unref);
64 gconf_change_set_new (void)
68 cs = g_new(GConfChangeSet, 1);
71 cs->hash = g_hash_table_new(g_str_hash, g_str_equal);
80 gconf_change_set_ref (GConfChangeSet* cs)
82 g_return_if_fail(cs != NULL);
88 gconf_change_set_unref (GConfChangeSet* cs)
90 g_return_if_fail(cs != NULL);
91 g_return_if_fail(cs->refcount > 0);
95 if (cs->refcount == 0)
97 if (cs->in_foreach > 0)
98 g_warning("GConfChangeSet refcount reduced to 0 during a foreach");
100 gconf_change_set_clear(cs);
102 g_hash_table_destroy(cs->hash);
109 gconf_change_set_set_user_data (GConfChangeSet *cs,
111 GDestroyNotify dnotify)
114 (* cs->dnotify) (cs->user_data);
116 cs->user_data = data;
117 cs->dnotify = dnotify;
121 gconf_change_set_get_user_data (GConfChangeSet *cs)
123 return cs->user_data;
127 get_change_unconditional (GConfChangeSet* cs,
132 c = g_hash_table_lookup(cs->hash, key);
138 g_hash_table_insert(cs->hash, c->key, c);
145 destroy_foreach (gpointer key, gpointer value, gpointer user_data)
153 return TRUE; /* remove from hash */
157 gconf_change_set_clear (GConfChangeSet* cs)
159 g_return_if_fail(cs != NULL);
161 g_hash_table_foreach_remove (cs->hash, destroy_foreach, NULL);
165 gconf_change_set_size (GConfChangeSet* cs)
167 g_return_val_if_fail(cs != NULL, 0);
169 return g_hash_table_size(cs->hash);
173 gconf_change_set_remove (GConfChangeSet* cs,
178 g_return_if_fail(cs != NULL);
179 g_return_if_fail(cs->in_foreach == 0);
181 c = g_hash_table_lookup(cs->hash, key);
185 g_hash_table_remove(cs->hash, c->key);
193 GConfChangeSetForeachFunc func;
198 foreach(gpointer key, gpointer value, gpointer user_data)
201 struct ForeachData* fd = user_data;
205 /* assumes that an UNSET change has a NULL value */
206 (* fd->func) (fd->cs, c->key, c->value, fd->user_data);
210 gconf_change_set_foreach (GConfChangeSet* cs,
211 GConfChangeSetForeachFunc func,
214 struct ForeachData fd;
216 g_return_if_fail(cs != NULL);
217 g_return_if_fail(func != NULL);
221 fd.user_data = user_data;
223 gconf_change_set_ref(cs);
227 g_hash_table_foreach(cs->hash, foreach, &fd);
231 gconf_change_set_unref(cs);
235 gconf_change_set_check_value (GConfChangeSet* cs, const gchar* key,
236 GConfValue** value_retloc)
240 g_return_val_if_fail(cs != NULL, FALSE);
242 c = g_hash_table_lookup(cs->hash, key);
248 if (value_retloc != NULL)
249 *value_retloc = c->value;
256 gconf_change_set_set_nocopy (GConfChangeSet* cs, const gchar* key,
261 g_return_if_fail(cs != NULL);
262 g_return_if_fail(value != NULL);
264 c = get_change_unconditional(cs, key);
266 change_set(c, value);
270 gconf_change_set_set (GConfChangeSet* cs, const gchar* key,
273 g_return_if_fail(value != NULL);
275 gconf_change_set_set_nocopy(cs, key, gconf_value_copy(value));
279 gconf_change_set_unset (GConfChangeSet* cs, const gchar* key)
283 g_return_if_fail(cs != NULL);
285 c = get_change_unconditional(cs, key);
291 gconf_change_set_set_float (GConfChangeSet* cs, const gchar* key,
296 g_return_if_fail(cs != NULL);
298 value = gconf_value_new(GCONF_VALUE_FLOAT);
299 gconf_value_set_float(value, val);
301 gconf_change_set_set_nocopy(cs, key, value);
305 gconf_change_set_set_int (GConfChangeSet* cs, const gchar* key,
310 g_return_if_fail(cs != NULL);
312 value = gconf_value_new(GCONF_VALUE_INT);
313 gconf_value_set_int(value, val);
315 gconf_change_set_set_nocopy(cs, key, value);
319 gconf_change_set_set_string (GConfChangeSet* cs, const gchar* key,
324 g_return_if_fail(cs != NULL);
325 g_return_if_fail(key != NULL);
326 g_return_if_fail(val != NULL);
328 value = gconf_value_new(GCONF_VALUE_STRING);
329 gconf_value_set_string(value, val);
331 gconf_change_set_set_nocopy(cs, key, value);
335 gconf_change_set_set_bool (GConfChangeSet* cs, const gchar* key,
340 g_return_if_fail(cs != NULL);
342 value = gconf_value_new(GCONF_VALUE_BOOL);
343 gconf_value_set_bool(value, val);
345 gconf_change_set_set_nocopy(cs, key, value);
349 gconf_change_set_set_schema (GConfChangeSet* cs, const gchar* key,
354 g_return_if_fail(cs != NULL);
356 value = gconf_value_new(GCONF_VALUE_SCHEMA);
357 gconf_value_set_schema(value, val);
359 gconf_change_set_set_nocopy(cs, key, value);
363 gconf_change_set_set_list (GConfChangeSet* cs, const gchar* key,
364 GConfValueType list_type,
367 GConfValue* value_list;
369 g_return_if_fail(cs != NULL);
370 g_return_if_fail(key != NULL);
371 g_return_if_fail(list_type != GCONF_VALUE_INVALID);
372 g_return_if_fail(list_type != GCONF_VALUE_LIST);
373 g_return_if_fail(list_type != GCONF_VALUE_PAIR);
375 value_list = gconf_value_list_from_primitive_list (list_type, list, NULL);
377 gconf_change_set_set_nocopy(cs, key, value_list);
382 gconf_change_set_set_pair (GConfChangeSet* cs, const gchar* key,
383 GConfValueType car_type, GConfValueType cdr_type,
384 gconstpointer address_of_car,
385 gconstpointer address_of_cdr)
389 g_return_if_fail(cs != NULL);
390 g_return_if_fail(key != NULL);
391 g_return_if_fail(car_type != GCONF_VALUE_INVALID);
392 g_return_if_fail(car_type != GCONF_VALUE_LIST);
393 g_return_if_fail(car_type != GCONF_VALUE_PAIR);
394 g_return_if_fail(cdr_type != GCONF_VALUE_INVALID);
395 g_return_if_fail(cdr_type != GCONF_VALUE_LIST);
396 g_return_if_fail(cdr_type != GCONF_VALUE_PAIR);
397 g_return_if_fail(address_of_car != NULL);
398 g_return_if_fail(address_of_cdr != NULL);
400 pair = gconf_value_pair_from_primitive_pair (car_type, cdr_type,
401 address_of_car, address_of_cdr,
404 gconf_change_set_set_nocopy(cs, key, pair);
413 change_new (const gchar* key)
417 c = g_new(Change, 1);
419 c->key = g_strdup(key);
420 c->type = CHANGE_INVALID;
427 change_destroy(Change* c)
429 g_return_if_fail(c != NULL);
434 gconf_value_free(c->value);
440 change_set (Change* c, GConfValue* value)
442 g_return_if_fail(value == NULL ||
443 GCONF_VALUE_TYPE_VALID(value->type));
445 c->type = CHANGE_SET;
447 if (value == c->value)
451 gconf_value_free(c->value);
457 change_unset (Change* c)
459 c->type = CHANGE_UNSET;
462 gconf_value_free(c->value);
468 * Actually send it upstream
475 gboolean remove_committed;
479 commit_foreach (GConfChangeSet* cs,
484 struct CommitData* cd = user_data;
486 g_assert(cd != NULL);
488 if (cd->error != NULL)
492 gconf_engine_set (cd->conf, key, value, &cd->error);
494 gconf_engine_unset (cd->conf, key, &cd->error);
496 if (cd->error == NULL && cd->remove_committed)
498 /* Bad bad bad; we keep the key reference, knowing that it's
499 valid until we modify the change set, to avoid string copies. */
500 cd->remove_list = g_slist_prepend(cd->remove_list, (gchar*)key);
505 gconf_engine_commit_change_set (GConfEngine* conf,
507 gboolean remove_committed,
510 struct CommitData cd;
513 g_return_val_if_fail(conf != NULL, FALSE);
514 g_return_val_if_fail(cs != NULL, FALSE);
515 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
519 cd.remove_list = NULL;
520 cd.remove_committed = remove_committed;
522 /* Because the commit could have lots of side
523 effects, this makes it safer */
524 gconf_change_set_ref(cs);
525 gconf_engine_ref(conf);
527 gconf_change_set_foreach(cs, commit_foreach, &cd);
529 tmp = cd.remove_list;
532 const gchar* key = tmp->data;
534 gconf_change_set_remove(cs, key);
536 /* key is now invalid due to our little evil trick */
538 tmp = g_slist_next(tmp);
541 g_slist_free(cd.remove_list);
543 gconf_change_set_unref(cs);
544 gconf_engine_unref(conf);
546 if (cd.error != NULL)
551 g_error_free(cd.error);
564 GConfChangeSet* revert_set;
568 revert_foreach (GConfChangeSet* cs,
573 struct RevertData* rd = user_data;
574 GConfValue* old_value;
575 GError* error = NULL;
577 g_assert(rd != NULL);
579 if (rd->error != NULL)
582 old_value = gconf_engine_get_without_default(rd->conf, key, &error);
587 g_warning("error creating revert set: %s", error->message);
592 if (old_value == NULL &&
594 return; /* this commit will have no effect. */
596 if (old_value == NULL)
597 gconf_change_set_unset(rd->revert_set, key);
599 gconf_change_set_set_nocopy(rd->revert_set, key, old_value);
604 gconf_engine_reverse_change_set (GConfEngine* conf,
608 struct RevertData rd;
610 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
614 rd.revert_set = gconf_change_set_new();
616 gconf_change_set_foreach(cs, revert_foreach, &rd);
618 if (rd.error != NULL)
623 g_error_free(rd.error);
626 return rd.revert_set;
630 gconf_engine_change_set_from_currentv (GConfEngine* conf,
634 GConfValue* old_value;
635 GConfChangeSet* new_set;
638 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
640 new_set = gconf_change_set_new();
644 while (*keyp != NULL)
646 GError* error = NULL;
647 const gchar* key = *keyp;
649 old_value = gconf_engine_get_without_default(conf, key, &error);
654 g_warning("error creating change set from current keys: %s", error->message);
659 if (old_value == NULL)
660 gconf_change_set_unset(new_set, key);
662 gconf_change_set_set_nocopy(new_set, key, old_value);
671 gconf_engine_change_set_from_current (GConfEngine* conf,
673 const gchar* first_key,
680 GConfChangeSet* retval;
684 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
686 va_start (args, first_key);
692 keys = g_slist_prepend(keys, (/*not-const*/gchar*)arg);
694 arg = va_arg (args, const gchar*);
699 vec = g_new0(const gchar*, g_slist_length(keys) + 1);
709 tmp = g_slist_next(tmp);
714 retval = gconf_engine_change_set_from_currentv(conf, vec, err);