Be able to use JSON dictionaries in config (#77)
* Initial implementation Added serialization and deserialization Co-Authored-By: nightly brew <93888516+nightly-brew@users.noreply.github.com> * Check if Generic T is a descendant of GLib.Object Co-authored-by: nightly brew <93888516+nightly-brew@users.noreply.github.com>
This commit is contained in:
@@ -26,6 +26,18 @@ namespace SwayNotificatonCenter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Category : Object {
|
||||||
|
public string ? sound { get; set; default = null; }
|
||||||
|
public string ? icon { get; set; default = null; }
|
||||||
|
|
||||||
|
public string to_string () {
|
||||||
|
string[] fields = {};
|
||||||
|
if (sound != null) fields += @"sound: $sound";
|
||||||
|
if (icon != null) fields += @"icon: $icon";
|
||||||
|
return string.joinv (", ", fields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class ConfigModel : Object, Json.Serializable {
|
public class ConfigModel : Object, Json.Serializable {
|
||||||
|
|
||||||
private static ConfigModel _instance;
|
private static ConfigModel _instance;
|
||||||
@@ -73,7 +85,7 @@ namespace SwayNotificatonCenter {
|
|||||||
stderr.printf (e.message + "\n");
|
stderr.printf (e.message + "\n");
|
||||||
}
|
}
|
||||||
_instance = m ?? new ConfigModel ();
|
_instance = m ?? new ConfigModel ();
|
||||||
debug (_instance.json_serialized ());
|
debug (_instance.to_string ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Properties */
|
/* Properties */
|
||||||
@@ -137,7 +149,7 @@ namespace SwayNotificatonCenter {
|
|||||||
*/
|
*/
|
||||||
public bool keyboard_shortcuts { get; set; default = true; }
|
public bool keyboard_shortcuts { get; set; default = true; }
|
||||||
|
|
||||||
/** Specifies if the notifcation image should be shown or not */
|
/** Specifies if the notification image should be shown or not */
|
||||||
public ImageVisibility image_visibility {
|
public ImageVisibility image_visibility {
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
@@ -196,8 +208,99 @@ namespace SwayNotificatonCenter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Categories settings */
|
||||||
|
public HashTable<string, Category> categories_settings {
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
default = new HashTable<string, Category>(str_hash, str_equal);
|
||||||
|
}
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the deserialization method based on the property name.
|
||||||
|
* Needed to parse those parameters of complex types like hashtables,
|
||||||
|
* which are not natively supported by the default deserialization function.
|
||||||
|
*/
|
||||||
|
public override bool deserialize_property (string property_name,
|
||||||
|
out Value value,
|
||||||
|
ParamSpec pspec,
|
||||||
|
Json.Node property_node) {
|
||||||
|
switch (property_name) {
|
||||||
|
case "categories-settings" :
|
||||||
|
bool status;
|
||||||
|
HashTable<string, Category> result =
|
||||||
|
extract_hashtable<Category>(
|
||||||
|
property_name,
|
||||||
|
property_node,
|
||||||
|
out status);
|
||||||
|
value = result;
|
||||||
|
return status;
|
||||||
|
default:
|
||||||
|
// Handles all other properties
|
||||||
|
return default_deserialize_property (
|
||||||
|
property_name, out value, pspec, property_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts and returns a GLib.Object from a nested JSON Object
|
||||||
|
*/
|
||||||
|
private HashTable<string, T> extract_hashtable<T>(string property_name,
|
||||||
|
Json.Node node,
|
||||||
|
out bool status) {
|
||||||
|
status = false;
|
||||||
|
var tmp_table = new HashTable<string, T>(str_hash, str_equal);
|
||||||
|
|
||||||
|
// Check if T is a descendant of GLib.Object
|
||||||
|
assert (typeof (T).is_a (Type.OBJECT));
|
||||||
|
|
||||||
|
if (node.get_node_type () != Json.NodeType.OBJECT) {
|
||||||
|
stderr.printf ("Node %s is not a json object!...\n",
|
||||||
|
property_name);
|
||||||
|
return tmp_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json.Object ? root_object = node.get_object ();
|
||||||
|
if (root_object == null) return tmp_table;
|
||||||
|
|
||||||
|
foreach (string * member in root_object.get_members ()) {
|
||||||
|
Json.Object * object = root_object.get_object_member (member);
|
||||||
|
if (object == null) {
|
||||||
|
stderr.printf (
|
||||||
|
"%s category is not a json object, skipping...\n",
|
||||||
|
member);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new GLib.Object with all of the properties of T
|
||||||
|
Object obj = Object.new (typeof (T));
|
||||||
|
foreach (var name in object->get_members ()) {
|
||||||
|
Value value = object->get_member (name).get_value ();
|
||||||
|
obj.set_property (name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp_table.insert (member, (T) obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = true;
|
||||||
|
return tmp_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Json.Object serialize_hashtable<T>(HashTable<string, T> table) {
|
||||||
|
var obj = new Json.Object ();
|
||||||
|
|
||||||
|
// Check if T is a descendant of GLib.Object
|
||||||
|
assert (typeof (T).is_a (Type.OBJECT));
|
||||||
|
|
||||||
|
if (table == null) return obj;
|
||||||
|
|
||||||
|
table.foreach ((key, value) => {
|
||||||
|
obj.set_member (key, Json.gobject_serialize (value as Object));
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when `Json.gobject_serialize (ConfigModel.instance)` is called
|
* Called when `Json.gobject_serialize (ConfigModel.instance)` is called
|
||||||
*/
|
*/
|
||||||
@@ -216,6 +319,11 @@ namespace SwayNotificatonCenter {
|
|||||||
var val = ((ImageVisibility) value.get_enum ()).parse ();
|
var val = ((ImageVisibility) value.get_enum ()).parse ();
|
||||||
node.set_string (val);
|
node.set_string (val);
|
||||||
break;
|
break;
|
||||||
|
case "categories-settings":
|
||||||
|
node = new Json.Node (Json.NodeType.OBJECT);
|
||||||
|
var table = (HashTable<string, Category>) value.get_boxed ();
|
||||||
|
node.set_object (serialize_hashtable<Category>(table));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
node.set_value (value);
|
node.set_value (value);
|
||||||
break;
|
break;
|
||||||
@@ -223,7 +331,7 @@ namespace SwayNotificatonCenter {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string json_serialized () {
|
public string to_string () {
|
||||||
var json = Json.gobject_serialize (ConfigModel.instance);
|
var json = Json.gobject_serialize (ConfigModel.instance);
|
||||||
return Json.to_string (json, true);
|
return Json.to_string (json, true);
|
||||||
}
|
}
|
||||||
@@ -297,7 +405,7 @@ namespace SwayNotificatonCenter {
|
|||||||
|
|
||||||
var file = File.new_for_path (path);
|
var file = File.new_for_path (path);
|
||||||
|
|
||||||
string data = ConfigModel.instance.json_serialized ();
|
string data = ConfigModel.instance.to_string ();
|
||||||
return file.replace_contents (
|
return file.replace_contents (
|
||||||
data.data,
|
data.data,
|
||||||
null,
|
null,
|
||||||
|
Reference in New Issue
Block a user