1 public class Key
: GLib
.Object
3 private SettingsModel model
;
5 public Directory? parent
;
8 public string full_name
;
10 public SchemaKey? schema
;
12 public bool has_schema
14 get { return schema
!= null; }
19 get { return parent
.keys
.index (this
); }
22 public string type_string
29 if (value
.is_of_type(VariantType
.STRING
) && has_schema
&& schema
.enum_name
!= null)
32 return value
.get_type_string();
39 private Variant? _value
;
48 return schema
.default_value
;
55 model
.client
.write_sync(full_name
, value
);
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
);
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
);
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
)
127 public Key(SettingsModel model
, Directory parent
, string name
, string full_name
)
130 this
.parent
= parent
;
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()
146 model
.client
.write_sync(full_name
, null);
154 private void update_value()
156 _value
= model
.client
.read(full_name
);
160 public class Directory
: GLib
.Object
162 private SettingsModel model
;
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
; }
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
; }
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
; }
197 private bool have_children
;
199 public Directory(SettingsModel model
, Directory? parent
, string name
, string full_name
)
202 this
.parent
= parent
;
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
);
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
);
232 key
= new
Key(model
, this
, name
, full_name
+ name
);
233 _keys
.insert_sorted(key
, compare_keys
);
234 _key_map
.insert(name
, 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
)
249 foreach (var schema_key
in schema
.keys
.get_values())
250 get_key(schema_key
.name
);
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()
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];
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
)
300 if (!get_iter_first(out iter
))
305 if(get_key(iter
) == key
)
307 row_changed(get_path(iter
), iter
);
310 } while(iter_next(ref iter
));
313 public Gtk
.TreeModelFlags
get_flags()
315 return Gtk
.TreeModelFlags
.LIST_ONLY
;
318 public int get_n_columns()
323 public Type
get_column_type(int index
)
328 return typeof(string);
331 private void set_iter(ref Gtk
.TreeIter iter
, Key key
)
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)
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
);
361 public void get_value(Gtk
.TreeIter iter
, int column
, out Value value
)
363 Key key
= get_key(iter
);
367 else if (column
== 1)
369 else if (column
== 2)
371 if (key
.value
!= null)
372 value
= key
.value
.print(false);
376 else if (column
== 4)
379 value
= Pango
.Weight
.NORMAL
;
381 value
= Pango
.Weight
.BOLD
;
387 public bool iter_next(ref Gtk
.TreeIter iter
)
389 int index
= get_key(iter
).index
;
390 if (index
>= directory
.keys
.length() - 1)
392 set_iter(ref iter
, directory
.keys
.nth_data(index
+1));
396 public bool iter_children(out Gtk
.TreeIter iter
, Gtk
.TreeIter? parent
)
398 iter
= Gtk
.TreeIter();
400 if (parent
!= null || directory
.keys
.length() == 0)
402 set_iter(ref iter
, directory
.keys
.nth_data(0));
407 public bool iter_has_child(Gtk
.TreeIter iter
)
412 public int iter_n_children(Gtk
.TreeIter? iter
)
415 return (int)directory
.keys
.length();
420 public bool iter_nth_child(out Gtk
.TreeIter iter
, Gtk
.TreeIter? parent
, int n
)
422 iter
= Gtk
.TreeIter();
427 if (n
>= directory
.keys
.length())
429 set_iter(ref iter
, directory
.keys
.nth_data(n
));
433 public bool iter_parent(out Gtk
.TreeIter iter
, Gtk
.TreeIter child
)
435 iter
= Gtk
.TreeIter();
439 public void ref_node(Gtk
.TreeIter iter
)
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()
469 public Type
get_column_type(int index
)
472 return typeof(string);
477 private void set_iter(ref Gtk
.TreeIter iter
, SchemaValue value
)
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)
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
);
507 public void get_value(Gtk
.TreeIter iter
, int column
, out Value value
)
510 value
= get_enum_value(iter
).nick
;
511 else if (column
== 1)
512 value
= get_enum_value(iter
).value
;
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)
522 set_iter(ref iter
, schema_enum
.values
.nth_data(index
+ 1));
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)
533 set_iter(ref iter
, schema_enum
.values
.nth_data(0));
538 public bool iter_has_child(Gtk
.TreeIter iter
)
543 public int iter_n_children(Gtk
.TreeIter? iter
)
546 return (int) schema_enum
.values
.length();
551 public bool iter_nth_child(out Gtk
.TreeIter iter
, Gtk
.TreeIter? parent
, int n
)
553 iter
= Gtk
.TreeIter();
558 if (n
>= schema_enum
.values
.length())
560 set_iter(ref iter
, schema_enum
.values
.nth_data(n
));
564 public bool iter_parent(out Gtk
.TreeIter iter
, Gtk
.TreeIter child
)
566 iter
= Gtk
.TreeIter();
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
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");
620 schemas
.load_directory(dir
);
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()
635 public int get_n_columns()
640 public Type
get_column_type(int index
)
643 return typeof(Directory
);
645 return typeof(string);
648 private void set_iter(ref Gtk
.TreeIter iter
, Directory directory
)
651 iter
.user_data
= directory
;
652 iter
.user_data2
= directory
;
653 iter
.user_data3
= directory
;
656 public Directory
get_directory(Gtk
.TreeIter? iter
)
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]))
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
]))
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
);
689 public void get_value(Gtk
.TreeIter iter
, int column
, out Value value
)
692 value
= get_directory(iter
);
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)
702 set_iter(ref iter
, directory
.parent
.children
.nth_data(directory
.index
+1));
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)
714 set_iter(ref iter
, directory
.children
.nth_data(0));
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())
736 set_iter(ref iter
, directory
.children
.nth_data(n
));
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
)
749 set_iter(ref iter
, directory
.parent
);
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();