GNOME Bugzilla – Bug 771968
Problem specifying a gschema key/type for a dictionary with variant (array) data.
Last modified: 2016-09-28 23:20:13 UTC
I have a problem, kind of exclusive: Either I can not located key in a dictionary in my gschema if I store it with type "a{sau}" what I actually want. Resulting in "key not found". Or I can not specify the type "a{sv}" or to be precise "a{s@au}" for the schema file. Resulting in glib-compile error / wrong type. I created a test variant (not using the gschema) of a similar type and can confirm, key not found. Then I created a test variant using a type "a{sv}" to build a test variant from "{'AC': <[1, 2, 3, 4, 5, 6, 7, 8]>, ..." and then I can located the key and access the data/array. But now I was not able to figure out how to specify the array type "au" and always get the default "ai" -- or how do I do this??? Now I assume I some how have to "enclose or box" my array within a variant for the dictionary data part, bu how to I specify this in my gschema xml file? I tried type="a{sv}" -- glib-compile error "wrong type". I tried type="a{s@au}" -- glib-compile error "wrong type". Not possible? What would be the proper syntax here? I read over and over the documentations, but can not find a hint. Thanks for any hints in advance. Below is some test code, I added a lot of checking to identify the issue. void DSPControl::get_tab_settings (const gchar *tab_key, gint &option_flags, gint &auto_flags, gint glock_data[6]) { g_print ("DSPControl::get_tab_settings -- Looking for key '%s' in probe-tab-options.\n", tab_key); /* in ...gschema.xml file and installed key. Looking OK in dconf-editor. But thus fails finding I the keys. <key name="probe-tab-options" type="a{sau}"> <default>{ "AC": [0,0, 0,0,0,0,0,0], "IV": [0,0, 0,0,0,0,0,0], "FZ": [0,0, 0,0,0,0,0,0], "PL": [0,0, 0,0,0,0,0,0], "LP": [0,0, 0,0,0,0,0,0], "SP": [0,0, 0,0,0,0,0,0], "TS": [0,0, 0,0,0,0,0,0], "LM": [0,0, 0,0,0,0,0,0], "TK": [0,0, 0,0,0,0,0,0], "AX": [0,0, 0,0,0,0,0,0], "AB": [0,0, 0,0,0,0,0,0]} </default> <summary> dictionary for probe tabs (AC, ...) containing a array of [STS,.. option-flags, auto-flags, glock-data[6]]] </summary> <description> data </description> </key> */ // THIS IS WHAT I NEED TO READ AND MANAGE/STORE // GVariantDict *dict = g_variant_dict_new (g_settings_get_value (hwi_settings, "probe-tab-options")); // --> does not work, no key found. But returns non zero dict. // GVariant *v = g_variant_new_parsed ("[{'AC', [0, 0, 0, 0, 0, 0, 0, 0]}, {'IV', [0, 0, 0, 0, 0, 0, 0, 0]}, {'FZ', [0, 0, 0, 0, 0, 0, 0, 0]}, {'PL', [0, 0, 0, 0, 0, 0, 0, 0]}, {'LP', [0, 0, 0, 0, 0, 0, 0, 0]}, {'SP', [0, 0, 0, 0, 0, 0, 0, 0]}, {'TS', [0, 0, 0, 0, 0, 0, 0, 0]}, {'LM', [0, 0, 0, 0, 0, 0, 0, 0]}, {'TK', [0, 0, 0, 0, 0, 0, 0, 0]}, {'AX', [0, 0, 0, 0, 0, 0, 0, 0]}, {'AB', [0, 0, 0, 0, 0, 0, 0, 0]}]"); // --> does not work, no key found. // GVariant *v = g_variant_new_parsed ("@a{sau} {'AC': [0, 0, 0, 0, 0, 0, 0, 0], 'IV': [0, 0, 0, 0, 0, 0, 0, 0], 'FZ': [0, 0, 0, 0, 0, 0, 0, 0], 'PL': [0, 0, 0, 0, 0, 0, 0, 0]}"); // --> this does not work, no key found GVariant *v = g_variant_new_parsed ("@a{sv} {'AC': <[1, 2, 3, 4, 5, 6, 7, 8]>, 'IV': <[2, 4, 8, 16, 32, 64, 128, 256]>, 'FZ': <[0, 1, 0, 1, 0, 1, 0, 99]>, 'PL': <[0, 0, 0, 0, 0, 0, 0, 0]>}"); // --> only this works, but how to specify data to be 'au' and NOT 'ai' ?? g_print ("Type is '%s'\n", g_variant_get_type (v)); g_print ("DSPControl::get_tab_settings -- creating test dict instead of 'probe-tab-options' from schema\n"); GVariantDict *dict = g_variant_dict_new (v); if (!dict){ g_print ("ERROR: DSPControl::get_tab_settings -- can't read dictionary 'probe-tab-options' a{sai}.\n"); return; } if (!g_variant_dict_contains (dict, tab_key)){ g_print ("ERROR: DSPControl::get_tab_settings -- can't find key '%s' in dict 'probe-tab-options'.\n", tab_key); return; } g_print ("DSPControl::get_tab_settings -- key '%s' found in dict 'probe-tab-options' :)\n", tab_key); GVariant *value = g_variant_dict_lookup_value (dict, tab_key, ((const GVariantType *) "au")); if (!value){ g_print ("ERROR: DSPControl::get_tab_settings -- can't get array 'au' data from key '%s' in 'probe-tab-options' dictionary.\n", tab_key); value = g_variant_dict_lookup_value (dict, tab_key, ((const GVariantType *) "ai")); if (!value){ g_print ("ERROR: DSPControl::get_tab_settings -- can't get array 'ai' data from key '%s' in 'probe-tab-options' dictionary.\n", tab_key); g_print ("DSPControl::get_tab_settings -- trying to unbox variant first...\n"); GVariant *variant = g_variant_dict_lookup_value (dict, tab_key, G_VARIANT_TYPE_VARIANT); if (!variant){ g_print ("ERROR: DSPControl::get_tab_settings -- can't unbox variant from key '%s' in 'probe-tab-options' dictionary.\n", tab_key); g_variant_dict_unref (dict); g_print ("ERROR: DSPControl::get_tab_settings -- all unpack attempts for '%s' failed.\n", tab_key); return; } else g_print ("DSPControl::get_tab_settings -- key '%s' found variant box :)\n", tab_key); value = g_variant_get_variant (variant); if (value) g_print ("DSPControl::get_tab_settings -- key '%s' unboxed variant from box :)\n", tab_key); } else g_print ("DSPControl::get_tab_settings -- key '%s' found array 'ai' :)\n", tab_key); } else g_print ("DSPControl::get_tab_settings -- key '%s' found array 'au' :)\n", tab_key); if (value){ guint32 *ai = NULL; gsize ni; ai = (guint32*) g_variant_get_fixed_array (value, &ni, sizeof (guint32)); g_assert_cmpint (ni, ==, 8); g_print ("["); for (int i=0; i<ni; ++i) g_print ("%u, ", ai[i]); g_print ("]\n"); option_flags = ai[0]; auto_flags = ai[1]; for (int i=0; i<6; ++i) glock_data [i] = ai[i+2]; // must free data for ourselves g_variant_unref (value); } else { g_print ("ERROR: DSPControl::get_tab_settings -- cant get array 'au' from key '%s' in 'probe-tab-options' dictionary.\n", tab_key); } GVariant *vto = g_variant_dict_end (dict); // testing storing if (vto) g_print ("DSPControl::get_tab_settings -- stored tab-setings dict to variant OK.\n"); else g_print ("ERROR DSPControl::get_tab_settings -- store tab-setings dict to variant failed.\n"); if (g_settings_is_writable (hwi_settings, "probe-tab-options")) g_print ("DSPControl::get_tab_settings -- is writable\n"); else g_print ("WARNING/ERROR DSPControl::get_tab_settings -- is NOT writable\n"); // this fails here, but because the type is not matching I assume if (g_settings_set_value (hwi_settings, "probe-tab-options", vto)) g_print ("DSPControl::get_tab_settings -- update probe-tab-options dict OK\n"); else g_print ("ERROR DSPControl::get_tab_settings -- update probe-tab-options dict failed.\n"); g_variant_dict_unref (dict); g_variant_unref (vto); }
Your problem is that GVariantDict only works with a{sv}. Your key has type a{asau}, which is different. You should see a warning like this when running your code: GLib-CRITICAL **: the GVariant format string '{sv}' has a type of '{sv}' but the given value has a type of '{sau}'
Yes, thank you, I must have missed the warning but figured that already via try and error. I have this in my schema <key name="probe-tab-options" type="a{sau}"> <default>{ "AC": [0,0, 0,0,0,0,0,0], ... </key> and would need some thing like (where v is of type au) to make GVariantDict happy. <key name="probe-tab-options" type="a{sv}"> <default>{ "AC": <[0,0, 0,0,0,0,0,0]>, ... </key> I tried that, not accepted by glib compile. I tried also type="a{s@au}". No luck and very hard to find details about. IF you have a solution on how I make be able to make sue of the GVariantDic utilities that I would very much appreciate. Else I's have to write my own code to do pretty much the same job.
FYI: The bug or problem is that I only can define a empty default in my gschema like this -- what then works fine with GVariantDict. <key name="probe-tab-options" type="a{sv}"> <default>{}</default> ... </key> the gschema xml file does not allow (the install/check fails if I try) to define any variant values using in my gschema.xml file -- the <> seam ti interfere with xml parsing?!?!?: <default>{'AC': <@at [0,0,0,0,0,0,0,0]>,<[...]>,... }</default> While I can in my code successfully parse this: GVariant *v_default = g_variant_new_parsed ("@a{sv} {'AC': <@at [1,2,3,0,0,0,0,18446744073709551615]>,...}"); to first time initialize my values what is not my work around. And finally store it to my key in gsettings. best -Percy