Answering my own question in case anyone else can benefit from the information.
The code that I ended up with in order to encode the described
structure is the following:
void add_elem(GVariantBuilder *builder, struct tree_entry *elem)
{
GVariantBuilder *new, *child_builder, *children;
GVariant *new_dict, *new_array, *search;
GList *item;
/* This is the new dictionary that will be inserted into the
* 'children' array of the parent. The parent could be a regular
* element of the master list since both are using an array of
* dictionaries for the "children". */
new = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
/* This is the dictionary that will contain the child information.
* It only has one key - the id of the current element. */
child_builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
/* Construct and add the 'search' type information tuple to the
* current element's dictionary. */
search = g_variant_new("(us)", elem->search.type, elem->search.term);
g_variant_builder_add(child_builder, "{sv}", "search", search);
/* Construct the 'children' array for the child element. This is
* effectively the same as what we are doing for the master array. */
children = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
for (item = elem->children; item; item = item->next)
add_elem(children, item->data);
new_array = g_variant_builder_end(children);
g_variant_builder_unref(children);
/* Add the 'children' array to the current element dictionary. */
g_variant_builder_add(child_builder, "{sv}", "children", new_array);
new_dict = g_variant_builder_end(child_builder);
g_variant_builder_unref(child_builder);
/* Insert the new child into the top level dictionary describing the
* current element. */
g_variant_builder_add(new, "{sv}", elem->id, new_dict);
/* Insert this element into the parent's 'children' array. */
g_variant_builder_add(builder, "a{sv}", new);
}
builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
add_elem(builder, &root);
dict = g_variant_builder_end(builder);
On Tue, Feb 26, 2019 at 7:49 AM Mitko Haralanov <[email protected]> wrote:
>
> Does anyone have any pointers?
>
> Thank you.
>
> On Fri, Feb 22, 2019 at 11:58 AM Mitko Haralanov <[email protected]> wrote:
> >
> > Hi,
> >
> > I've been trying to figure out how to use GVariantBuilder to build a
> > complex structure with little success. The type of structure that I
> > would like to build is meant to partially encode a GtkTreeModel
> > structure. So, I thought that I could use GVariantBuilder to build a
> > structure of nested dictionaries.
> >
> > The structure roughly follows this model:
> > [
> > {
> > "id": { "key1": (<int>, <string>, ...), "children": [
> > { "id2" : { "key1" : (<int>, <string>, ...),
> > "children" : []},
> > { "id3" : { "key1" : (<int>, <string>, ...),
> > "children" : [
> > { ... }
> > ]}
> > ]}},
> > { "id" : ...}
> > ]
> >
> > This type of encoding can naturally be done with recursion and using
> > multiple GVariantBuilder's to add to the correct parent. However, I am
> > having difficulty with getting the formatting strings correct. As it
> > turns out, GLib insist on every dictionary entry being statically
> > typed meaning that the values for both "key1" and "children" has to be
> > of the same type. That seems to leave only 'v' as a valid format. So,
> > I have the following code (only important parts are pasted, not a
> > complete program):
> >
> > struct tree_entry_search {
> > uint32_t type;
> > const char *term;
> > };
> >
> > struct tree_entry {
> > const char *id;
> > struct tree_entry_search search;
> > GList *children;
> > };
> >
> > void add_elem(GVariantBuilder *builder, struct tree_entry *elem)
> > {
> > GVariantBuilder *new, *child_builder;
> > GVariant *new_dict, *new_array, *search;
> > GList *item;
> >
> > new = g_variant_builder_new(G_VARIANT_TYPE_DICTIONARY);
> > search = g_variant_new("(us)", elem->search.type,
> > elem->search.term);
> > g_variant_builder_add(new, "{sv}", "search", search);
> > child_builder = g_variant_builder_new(G_VARIANT_TYPE("av"));
> > for (item = elem->children; item; item = item->next)
> > add_elem(child_builder, item->data);
> > new_array = g_variant_builder_end(child_builder);
> > g_variant_builder_unref(child_builder);
> > g_variant_builder_add(new, "{sv}", "children", new_array);
> > new_dict = g_variant_builder_end(new);
> > g_variant_builder_unref(new);
> > g_variant_builder_add(builder, "{sv}", elem->id, new_dict);
> > }
> >
> > int main(void) {
> > ...
> > /* Build up a fake tree. */
> > root.id = g_strdup("uid1");
> > root.search.type = 1;
> > root.search.term = g_strdup("term1");
> > elem = g_new0(struct tree_entry, 1);
> > elem->id = g_strdup("uid2");
> > elem->search.type = 2;
> > elem->search.term = g_strdup("term2");
> > root.children = g_list_append(root.children, elem);
> > elem = g_new0(struct tree_entry, 1);
> > elem->id = g_strdup("uid3");
> > elem->search.type = 2;
> > elem->search.term = g_strdup("term3");
> > root.children = g_list_append(root.children, elem);
> > child = g_new0(struct tree_entry, 1);
> > child->id = g_strdup("uid4");
> > child->search.type = 3;
> > child->search.term = g_strdup("term4");
> > elem->children = g_list_append(elem->children, child);
> >
> > builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
> > add_elem(builder, &root);
> > dict = g_variant_builder_end(builder);
> > dictionary = g_variant_print(dict, TRUE);
> > printf("%s\n", dictionary);
> > ...
> > }
> >
> > But when I compile the above and run it, I get the following errors
> > when the tree is more than one level deep:
> >
> > (process:3873): GLib-CRITICAL **: 11:44:03.826:
> > g_variant_builder_add_value: assertion '!GVSB(builder)->expected_type
> > || g_variant_is_of_type (value, GVSB(builder)->expected_type)' failed
> >
> > (process:3873): GLib-CRITICAL **: 11:44:03.827:
> > g_variant_builder_add_value: assertion '!GVSB(builder)->expected_type
> > || g_variant_is_of_type (value, GVSB(builder)->expected_type)' failed
> >
> > (process:3873): GLib-CRITICAL **: 11:44:03.827:
> > g_variant_builder_add_value: assertion '!GVSB(builder)->expected_type
> > || g_variant_is_of_type (value, GVSB(builder)->expected_type)' failed
> >
> > What's the correct way to specify the builder and variant types so I
> > can build the nested dictionary structure?
> >
> > Thank you for the help.
_______________________________________________
gtk-list mailing list
[email protected]
https://mail.gnome.org/mailman/listinfo/gtk-list