update .gitignore for new automake files
[dconf.git] / editor / dconf-model.vala
blob8b43d609a1b90810bf4393a0413e13772ef99cd8
1 public class Key : GLib.Object
3 private SettingsModel model;
5 public Directory? parent;
7 public string name;
8 public string full_name;
10 public SchemaKey? schema;
12 public bool has_schema
14 get { return schema != null; }
17 public int index
19 get { return parent.keys.index (this); }
22 public string type_string
24 private set {}
25 public get
27 if (value != null)
29 if (value.is_of_type(VariantType.STRING) && has_schema && schema.enum_name != null)
30 return "<enum>";
31 else
32 return value.get_type_string();
34 else
35 return schema.type;
39 private Variant? _value;
40 public Variant value
42 get
44 update_value();
45 if (_value != null)
46 return _value;
47 else
48 return schema.default_value;
50 set
52 _value = value;
53 try
55 model.client.write_sync(full_name, value);
57 catch (GLib.Error e)
60 value_changed();
64 public Variant? get_min()
66 switch (value.classify ())
68 case Variant.Class.BYTE:
69 return new Variant.byte(0);
70 case Variant.Class.INT16:
71 return new Variant.int16(int16.MIN);
72 case Variant.Class.UINT16:
73 return new Variant.uint16(uint16.MIN);
74 case Variant.Class.INT32:
75 return new Variant.int32(int32.MIN);
76 case Variant.Class.UINT32:
77 return new Variant.uint32(uint32.MIN);
78 case Variant.Class.INT64:
79 return new Variant.int64(int64.MIN);
80 case Variant.Class.UINT64:
81 return new Variant.uint64(uint64.MIN);
82 case Variant.Class.DOUBLE:
83 return new Variant.double(double.MIN);
84 default:
85 return null;
89 public Variant? get_max()
91 switch (value.classify ())
93 case Variant.Class.BYTE:
94 return new Variant.byte(255);
95 case Variant.Class.INT16:
96 return new Variant.int16(int16.MAX);
97 case Variant.Class.UINT16:
98 return new Variant.uint16(uint16.MAX);
99 case Variant.Class.INT32:
100 return new Variant.int32(int32.MAX);
101 case Variant.Class.UINT32:
102 return new Variant.uint32(uint32.MAX);
103 case Variant.Class.INT64:
104 return new Variant.int64(int64.MAX);
105 case Variant.Class.UINT64:
106 return new Variant.uint64(uint64.MAX);
107 case Variant.Class.DOUBLE:
108 return new Variant.double(double.MAX);
109 default:
110 return null;
114 public bool is_default
116 get { update_value(); return _value == null; }
119 public signal void value_changed();
121 void item_changed (string key)
123 if ((key.has_suffix ("/") && full_name.has_prefix (key)) || key == full_name)
124 value_changed ();
127 public Key(SettingsModel model, Directory parent, string name, string full_name)
129 this.model = model;
130 this.parent = parent;
131 this.name = name;
132 this.full_name = full_name;
133 this.schema = model.schemas.keys.lookup(full_name);
135 model.item_changed.connect (item_changed);
138 public void set_to_default()
140 if (!has_schema)
141 return;
143 _value = null;
146 model.client.write_sync(full_name, null);
148 catch (GLib.Error e)
151 value_changed();
154 private void update_value()
156 _value = model.client.read(full_name);
160 public class Directory : GLib.Object
162 private SettingsModel model;
164 public string name;
165 public string full_name;
167 public Directory? parent;
169 private KeyModel _key_model;
170 public KeyModel key_model
172 get { update_children(); if (_key_model == null) _key_model = new KeyModel(this); return _key_model; }
173 private set {}
176 public int index
178 get { return parent.children.index (this); }
181 public GLib.HashTable<string, Directory> _child_map = new GLib.HashTable<string, Directory>(str_hash, str_equal);
182 public GLib.List<Directory> _children = new GLib.List<Directory>();
183 public GLib.List<Directory> children
185 get { update_children(); return _children; }
186 private set { }
189 public GLib.HashTable<string, Key> _key_map = new GLib.HashTable<string, Key>(str_hash, str_equal);
190 private GLib.List<Key> _keys = new GLib.List<Key>();
191 public GLib.List<Key> keys
193 get { update_children(); return _keys; }
194 private set { }
197 private bool have_children;
199 public Directory(SettingsModel model, Directory? parent, string name, string full_name)
201 this.model = model;
202 this.parent = parent;
203 this.name = name;
204 this.full_name = full_name;
207 public Directory get_child(string name)
209 Directory? directory = _child_map.lookup(name);
211 if (directory == null)
213 directory = new Directory(model, this, name, full_name + name + "/");
214 _children.insert_sorted(directory, compare_directories);
215 _child_map.insert(name, directory);
218 return directory;
221 private static int compare_directories(Directory a, Directory b)
223 return strcmp(a.name, b.name);
226 public Key get_key(string name)
228 Key? key = _key_map.lookup(name);
230 if (key == null)
232 key = new Key(model, this, name, full_name + name);
233 _keys.insert_sorted(key, compare_keys);
234 _key_map.insert(name, key);
237 return key;
240 public static int compare_keys(Key a, Key b)
242 return strcmp(a.name, b.name);
245 public void load_schema(Schema schema, string path)
247 if (path == "")
249 foreach (var schema_key in schema.keys.get_values())
250 get_key(schema_key.name);
252 else
254 string[] tokens = path.split("/", 2);
255 string name = tokens[0];
257 var directory = get_child(name);
258 directory.load_schema(schema, tokens[1]);
262 private void update_children()
264 if (have_children)
265 return;
266 have_children = true;
268 string[] items = model.client.list(full_name);
269 for (int i = 0; i < items.length; i++)
271 string item_name = full_name + items[i];
273 if (DConf.is_dir(item_name))
275 string dir_name = items[i][0:-1];
276 get_child(dir_name);
278 else
280 get_key(items[i]);
286 public class KeyModel: GLib.Object, Gtk.TreeModel
288 private Directory directory;
290 public KeyModel(Directory directory)
292 this.directory = directory;
293 foreach (var key in directory.keys)
294 key.value_changed.connect(key_changed_cb); // FIXME: Need to delete this callbacks
297 private void key_changed_cb(Key key)
299 Gtk.TreeIter iter;
300 if (!get_iter_first(out iter))
301 return;
305 if(get_key(iter) == key)
307 row_changed(get_path(iter), iter);
308 return;
310 } while(iter_next(ref iter));
313 public Gtk.TreeModelFlags get_flags()
315 return Gtk.TreeModelFlags.LIST_ONLY;
318 public int get_n_columns()
320 return 3;
323 public Type get_column_type(int index)
325 if (index == 0)
326 return typeof(Key);
327 else
328 return typeof(string);
331 private void set_iter(ref Gtk.TreeIter iter, Key key)
333 iter.stamp = 0;
334 iter.user_data = key;
335 iter.user_data2 = key;
336 iter.user_data3 = key;
339 public Key get_key(Gtk.TreeIter iter)
341 return (Key)iter.user_data;
344 public bool get_iter(out Gtk.TreeIter iter, Gtk.TreePath path)
346 iter = Gtk.TreeIter();
348 if (path.get_depth() != 1)
349 return false;
351 return iter_nth_child(out iter, null, path.get_indices()[0]);
354 public Gtk.TreePath? get_path(Gtk.TreeIter iter)
356 var path = new Gtk.TreePath();
357 path.append_index(get_key(iter).index);
358 return path;
361 public void get_value(Gtk.TreeIter iter, int column, out Value value)
363 Key key = get_key(iter);
365 if (column == 0)
366 value = key;
367 else if (column == 1)
368 value = key.name;
369 else if (column == 2)
371 if (key.value != null)
372 value = key.value.print(false);
373 else
374 value = "";
376 else if (column == 4)
378 if (key.is_default)
379 value = Pango.Weight.NORMAL;
380 else
381 value = Pango.Weight.BOLD;
383 else
384 value = 0;
387 public bool iter_next(ref Gtk.TreeIter iter)
389 int index = get_key(iter).index;
390 if (index >= directory.keys.length() - 1)
391 return false;
392 set_iter(ref iter, directory.keys.nth_data(index+1));
393 return true;
396 public bool iter_children(out Gtk.TreeIter iter, Gtk.TreeIter? parent)
398 iter = Gtk.TreeIter();
400 if (parent != null || directory.keys.length() == 0)
401 return false;
402 set_iter(ref iter, directory.keys.nth_data(0));
404 return true;
407 public bool iter_has_child(Gtk.TreeIter iter)
409 return false;
412 public int iter_n_children(Gtk.TreeIter? iter)
414 if (iter == null)
415 return (int)directory.keys.length();
416 else
417 return 0;
420 public bool iter_nth_child(out Gtk.TreeIter iter, Gtk.TreeIter? parent, int n)
422 iter = Gtk.TreeIter();
424 if (parent != null)
425 return false;
427 if (n >= directory.keys.length())
428 return false;
429 set_iter(ref iter, directory.keys.nth_data(n));
430 return true;
433 public bool iter_parent(out Gtk.TreeIter iter, Gtk.TreeIter child)
435 iter = Gtk.TreeIter();
436 return false;
439 public void ref_node(Gtk.TreeIter iter)
441 get_key(iter).ref();
444 public void unref_node(Gtk.TreeIter iter)
446 get_key(iter).unref();
450 public class EnumModel: GLib.Object, Gtk.TreeModel
452 private SchemaEnum schema_enum;
454 public EnumModel(SchemaEnum schema_enum)
456 this.schema_enum = schema_enum;
459 public Gtk.TreeModelFlags get_flags()
461 return Gtk.TreeModelFlags.LIST_ONLY;
464 public int get_n_columns()
466 return 2;
469 public Type get_column_type(int index)
471 if (index == 0)
472 return typeof(string);
473 else
474 return typeof(int);
477 private void set_iter(ref Gtk.TreeIter iter, SchemaValue value)
479 iter.stamp = 0;
480 iter.user_data = value;
481 iter.user_data2 = value;
482 iter.user_data3 = value;
485 public SchemaValue get_enum_value(Gtk.TreeIter iter)
487 return (SchemaValue)iter.user_data;
490 public bool get_iter(out Gtk.TreeIter iter, Gtk.TreePath path)
492 iter = Gtk.TreeIter();
494 if (path.get_depth() != 1)
495 return false;
497 return iter_nth_child(out iter, null, path.get_indices()[0]);
500 public Gtk.TreePath? get_path(Gtk.TreeIter iter)
502 var path = new Gtk.TreePath();
503 path.append_index((int)get_enum_value(iter).index);
504 return path;
507 public void get_value(Gtk.TreeIter iter, int column, out Value value)
509 if (column == 0)
510 value = get_enum_value(iter).nick;
511 else if (column == 1)
512 value = get_enum_value(iter).value;
513 else
514 value = 0;
517 public bool iter_next(ref Gtk.TreeIter iter)
519 uint index = get_enum_value(iter).index;
520 if (index >= schema_enum.values.length () - 1)
521 return false;
522 set_iter(ref iter, schema_enum.values.nth_data(index + 1));
523 return true;
526 public bool iter_children(out Gtk.TreeIter iter, Gtk.TreeIter? parent)
528 iter = Gtk.TreeIter();
530 if (parent != null || schema_enum.values.length() == 0)
531 return false;
533 set_iter(ref iter, schema_enum.values.nth_data(0));
535 return true;
538 public bool iter_has_child(Gtk.TreeIter iter)
540 return false;
543 public int iter_n_children(Gtk.TreeIter? iter)
545 if (iter == null)
546 return (int) schema_enum.values.length();
547 else
548 return 0;
551 public bool iter_nth_child(out Gtk.TreeIter iter, Gtk.TreeIter? parent, int n)
553 iter = Gtk.TreeIter();
555 if (parent != null)
556 return false;
558 if (n >= schema_enum.values.length())
559 return false;
560 set_iter(ref iter, schema_enum.values.nth_data(n));
561 return true;
564 public bool iter_parent(out Gtk.TreeIter iter, Gtk.TreeIter child)
566 iter = Gtk.TreeIter();
567 return false;
570 public void ref_node(Gtk.TreeIter iter)
572 get_enum_value(iter).ref();
575 public void unref_node(Gtk.TreeIter iter)
577 get_enum_value(iter).unref();
581 public class SettingsModel: GLib.Object, Gtk.TreeModel
583 public SchemaList schemas;
585 public DConf.Client client;
586 private Directory root;
588 public signal void item_changed (string key);
590 void watch_func (DConf.Client client, string path, string[] items, string? tag) {
591 foreach (var item in items) {
592 item_changed (path + item);
596 public SettingsModel()
598 client = new DConf.Client ();
599 client.changed.connect (watch_func);
600 root = new Directory(this, null, "/", "/");
601 client.watch_sync ("/");
603 schemas = new SchemaList();
606 var dirs = GLib.Environment.get_system_data_dirs();
608 /* Walk directories in reverse so the schemas in the
609 * directory which appears first in the XDG_DATA_DIRS are
610 * not overridden. */
611 for (int i = dirs.length - 1; i >= 0; i--)
613 var path = Path.build_filename (dirs[i], "glib-2.0", "schemas");
614 if (File.new_for_path (path).query_exists ())
615 schemas.load_directory (path);
618 var dir = GLib.Environment.get_variable ("GSETTINGS_SCHEMA_DIR");
619 if (dir != null)
620 schemas.load_directory(dir);
621 } catch (Error e) {
622 warning("Failed to parse schemas: %s", e.message);
625 /* Add keys for the values in the schemas */
626 foreach (var schema in schemas.schemas.get_values())
627 root.load_schema(schema, schema.path[1:schema.path.length]);
630 public Gtk.TreeModelFlags get_flags()
632 return 0;
635 public int get_n_columns()
637 return 2;
640 public Type get_column_type(int index)
642 if (index == 0)
643 return typeof(Directory);
644 else
645 return typeof(string);
648 private void set_iter(ref Gtk.TreeIter iter, Directory directory)
650 iter.stamp = 0;
651 iter.user_data = directory;
652 iter.user_data2 = directory;
653 iter.user_data3 = directory;
656 public Directory get_directory(Gtk.TreeIter? iter)
658 if (iter == null)
659 return root;
660 else
661 return (Directory)iter.user_data;
664 public bool get_iter(out Gtk.TreeIter iter, Gtk.TreePath path)
666 iter = Gtk.TreeIter();
668 if (!iter_nth_child(out iter, null, path.get_indices()[0]))
669 return false;
671 for (int i = 1; i < path.get_depth(); i++)
673 Gtk.TreeIter parent = iter;
674 if (!iter_nth_child(out iter, parent, path.get_indices()[i]))
675 return false;
678 return true;
681 public Gtk.TreePath? get_path(Gtk.TreeIter iter)
683 var path = new Gtk.TreePath();
684 for (var d = get_directory(iter); d != root; d = d.parent)
685 path.prepend_index((int)d.index);
686 return path;
689 public void get_value(Gtk.TreeIter iter, int column, out Value value)
691 if (column == 0)
692 value = get_directory(iter);
693 else
694 value = get_directory(iter).name;
697 public bool iter_next(ref Gtk.TreeIter iter)
699 var directory = get_directory(iter);
700 if (directory.index >= directory.parent.children.length() - 1)
701 return false;
702 set_iter(ref iter, directory.parent.children.nth_data(directory.index+1));
704 return true;
707 public bool iter_children(out Gtk.TreeIter iter, Gtk.TreeIter? parent)
709 iter = Gtk.TreeIter();
711 var directory = get_directory(parent);
712 if (directory.children.length() == 0)
713 return false;
714 set_iter(ref iter, directory.children.nth_data(0));
716 return true;
719 public bool iter_has_child(Gtk.TreeIter iter)
721 return get_directory(iter).children.length() > 0;
724 public int iter_n_children(Gtk.TreeIter? iter)
726 return (int) get_directory(iter).children.length();
729 public bool iter_nth_child(out Gtk.TreeIter iter, Gtk.TreeIter? parent, int n)
731 iter = Gtk.TreeIter();
733 var directory = get_directory(parent);
734 if (n >= directory.children.length())
735 return false;
736 set_iter(ref iter, directory.children.nth_data(n));
738 return true;
741 public bool iter_parent(out Gtk.TreeIter iter, Gtk.TreeIter child)
743 iter = Gtk.TreeIter();
745 var directory = get_directory(child);
746 if (directory.parent == root)
747 return false;
749 set_iter(ref iter, directory.parent);
751 return true;
754 public void ref_node(Gtk.TreeIter iter)
756 get_directory(iter).ref();
759 public void unref_node(Gtk.TreeIter iter)
761 get_directory(iter).unref();