2
A loader to turn JSON into dbusmenu menuitems
4
Copyright 2010 Canonical Ltd.
7
Ted Gould <ted@canonical.com>
9
This program is free software: you can redistribute it and/or modify it
10
under the terms of the GNU General Public License version 3, as published
11
by the Free Software Foundation.
13
This program is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranties of
15
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
16
PURPOSE. See the GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License along
19
with this program. If not, see <http://www.gnu.org/licenses/>.
22
#include "json-loader.h"
23
#include <dbus/dbus-gtype-specialized.h>
26
node2value (JsonNode * node)
32
GValue * value = g_new0(GValue, 1);
34
if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE) {
35
json_node_get_value(node, value);
39
if (JSON_NODE_TYPE(node) == JSON_NODE_ARRAY) {
40
JsonArray * array = json_node_get_array(node);
41
JsonNode * first = json_array_get_element(array, 0);
43
if (JSON_NODE_TYPE(first) == JSON_NODE_VALUE) {
44
GValue subvalue = {0};
45
json_node_get_value(first, &subvalue);
47
if (G_VALUE_TYPE(&subvalue) == G_TYPE_STRING) {
48
GArray * garray = g_array_sized_new(TRUE, TRUE, sizeof(gchar *), json_array_get_length(array));
49
g_value_init(value, G_TYPE_STRV);
50
g_value_take_boxed(value, garray->data);
53
for (i = 0; i < json_array_get_length(array); i++) {
54
const gchar * str = json_node_get_string(json_array_get_element(array, i));
55
gchar * dupstr = g_strdup(str);
56
g_array_append_val(garray, dupstr);
59
g_array_free(garray, FALSE);
61
GValueArray * varray = g_value_array_new(json_array_get_length(array));
62
g_value_init(value, G_TYPE_VALUE_ARRAY);
63
g_value_take_boxed(value, varray);
65
g_value_array_append(varray, &subvalue);
66
g_value_unset(&subvalue);
69
for (i = 1; i < json_array_get_length(array); i++) {
70
json_node_get_value(first, &subvalue);
71
g_value_array_append(varray, &subvalue);
72
g_value_unset(&subvalue);
77
GValue * subvalue = node2value(first);
78
GType type = dbus_g_type_get_collection("GPtrArray", G_VALUE_TYPE(subvalue));
79
gpointer * wrapper = dbus_g_type_specialized_construct(type);
81
g_value_init(value, type);
82
g_value_take_boxed(value, wrapper);
84
DBusGTypeSpecializedAppendContext ctx;
85
dbus_g_type_specialized_init_append(value, &ctx);
87
dbus_g_type_specialized_collection_append(&ctx, subvalue);
89
for (i = 1; i < json_array_get_length(array); i++) {
90
GValue * subvalue = node2value(node);
91
dbus_g_type_specialized_collection_append(&ctx, subvalue);
94
dbus_g_type_specialized_collection_end_append(&ctx);
98
if (JSON_NODE_TYPE(node) == JSON_NODE_OBJECT) {
99
JsonObject * obj = json_node_get_object(node);
101
GType type = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
102
GHashTable * hash = (GHashTable *)dbus_g_type_specialized_construct(type);
104
g_value_init(value, type);
105
g_value_take_boxed(value, hash);
107
DBusGTypeSpecializedAppendContext ctx;
108
dbus_g_type_specialized_init_append(value, &ctx);
110
GList * members = NULL;
111
for (members = json_object_get_members(obj); members != NULL; members = g_list_next(members)) {
112
const gchar * member = members->data;
114
JsonNode * lnode = json_object_get_member(obj, member);
115
GValue * value = node2value(lnode);
119
g_value_init(&name, G_TYPE_STRING);
120
g_value_set_static_string(&name, member);
122
dbus_g_type_specialized_map_append(&ctx, &name, value);
124
g_value_unset(&name);
125
g_value_unset(value);
135
set_props (DbusmenuMenuitem * mi, JsonObject * node)
137
if (node == NULL) return;
139
GList * members = NULL;
140
for (members = json_object_get_members(node); members != NULL; members = g_list_next(members)) {
141
const gchar * member = members->data;
143
if (!g_strcmp0(member, "id")) { continue; }
144
if (!g_strcmp0(member, "submenu")) { continue; }
146
JsonNode * lnode = json_object_get_member(node, member);
147
GValue * value = node2value(lnode);
150
dbusmenu_menuitem_property_set_value(mi, member, value);
151
g_value_unset(value);
160
dbusmenu_json_build_from_node (const JsonNode * cnode)
162
JsonNode * node = (JsonNode *)cnode; /* To match the jsonglib API :( */
164
if (node == NULL) return NULL;
165
if (JSON_NODE_TYPE(node) != JSON_NODE_OBJECT) return NULL;
167
JsonObject * layout = json_node_get_object(node);
169
DbusmenuMenuitem * local = NULL;
170
if (json_object_has_member(layout, "id")) {
171
JsonNode * node = json_object_get_member(layout, "id");
172
g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_VALUE, NULL);
173
local = dbusmenu_menuitem_new_with_id(json_node_get_int(node));
175
local = dbusmenu_menuitem_new();
178
set_props(local, layout);
180
if (json_object_has_member(layout, "submenu")) {
181
JsonNode * node = json_object_get_member(layout, "submenu");
182
g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_ARRAY, local);
183
JsonArray * array = json_node_get_array(node);
185
for (count = 0; count < json_array_get_length(array); count++) {
186
DbusmenuMenuitem * child = dbusmenu_json_build_from_node(json_array_get_element(array, count));
188
dbusmenu_menuitem_child_append(local, child);
193
/* g_debug("Layout to menu return: 0x%X", (unsigned int)local); */
198
dbusmenu_json_build_from_file (const gchar * filename)
200
JsonParser * parser = json_parser_new();
202
GError * error = NULL;
203
if (!json_parser_load_from_file(parser, filename, &error)) {
204
g_warning("Failed parsing file %s because: %s", filename, error->message);
209
JsonNode * root_node = json_parser_get_root(parser);
210
if (JSON_NODE_TYPE(root_node) != JSON_NODE_OBJECT) {
211
g_warning("Root node is not an object, fail. It's an: %s", json_node_type_name(root_node));
215
DbusmenuMenuitem * mi = dbusmenu_json_build_from_node(root_node);
217
g_object_unref(parser);