mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 23:46:17 +01:00
rework GMenuProxy links
Only resolve the link at the point that we pull it through the API rather than at the point that we first are told about it. This reduces the lifespan of subscriptions and, more importantly, avoids a tricky reference cycle issue.
This commit is contained in:
parent
2c4ded15e5
commit
7a0faf66fe
@ -128,9 +128,10 @@
|
||||
* proxy is inactive, the change signal is ignored.
|
||||
*
|
||||
* GMenuProxyItem is just a pair of hashtables, one for the attributes
|
||||
* and one for the links of the item (mapping strings to
|
||||
* other GMenuProxy instances). XXX reconsider this since it means the
|
||||
* submenu proxies stay around forever.....
|
||||
* and one for the links of the item. Both map strings to GVariant
|
||||
* instances. In the case of links, the GVariant has type '(uu)' and is
|
||||
* turned into a GMenuProxy at the point that the user pulls it through
|
||||
* the API.
|
||||
*
|
||||
* Following the "empty is the same as non-existent" rule, the hashtable
|
||||
* of GSequence of GMenuProxyItem holds NULL for empty menus.
|
||||
@ -393,8 +394,7 @@ g_menu_proxy_item_free (gpointer data)
|
||||
}
|
||||
|
||||
static GMenuProxyItem *
|
||||
g_menu_proxy_group_create_item (GMenuProxyGroup *context,
|
||||
GVariant *description)
|
||||
g_menu_proxy_group_create_item (GVariant *description)
|
||||
{
|
||||
GMenuProxyItem *item;
|
||||
GVariantIter iter;
|
||||
@ -403,34 +403,13 @@ g_menu_proxy_group_create_item (GMenuProxyGroup *context,
|
||||
|
||||
item = g_slice_new (GMenuProxyItem);
|
||||
item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
|
||||
item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref);
|
||||
item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref);
|
||||
|
||||
g_variant_iter_init (&iter, description);
|
||||
while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
|
||||
if (key[0] == ':')
|
||||
{
|
||||
if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(uu)")))
|
||||
{
|
||||
guint group_id, menu_id;
|
||||
GMenuProxyGroup *group;
|
||||
GMenuProxy *proxy;
|
||||
|
||||
g_variant_get (value, "(uu)", &group_id, &menu_id);
|
||||
|
||||
/* save the hash lookup in a relatively common case */
|
||||
if (context->id != group_id)
|
||||
group = g_menu_proxy_group_get_from_path (context->path, group_id);
|
||||
else
|
||||
group = g_menu_proxy_group_ref (context);
|
||||
|
||||
proxy = g_menu_proxy_get_from_group (group, menu_id);
|
||||
|
||||
/* key + 1 to skip the ':' */
|
||||
g_hash_table_insert (item->links, g_strdup (key + 1), proxy);
|
||||
|
||||
g_menu_proxy_group_unref (group);
|
||||
}
|
||||
}
|
||||
/* key + 1 to skip the ':' */
|
||||
g_hash_table_insert (item->links, g_strdup (key + 1), g_variant_ref (value));
|
||||
else
|
||||
g_hash_table_insert (item->attributes, g_strdup (key), g_variant_ref (value));
|
||||
|
||||
@ -629,7 +608,7 @@ g_menu_proxy_group_changed (GMenuProxyGroup *group,
|
||||
|
||||
n_added = g_variant_iter_init (&iter, added);
|
||||
while (g_variant_iter_loop (&iter, "@a{sv}", &item))
|
||||
g_sequence_insert_before (point, g_menu_proxy_group_create_item (group, item));
|
||||
g_sequence_insert_before (point, g_menu_proxy_group_create_item (item));
|
||||
|
||||
if (g_sequence_get_length (items) == 0)
|
||||
{
|
||||
@ -757,7 +736,38 @@ g_menu_proxy_get_item_links (GMenuModel *model,
|
||||
item = g_sequence_get (iter);
|
||||
g_return_if_fail (item);
|
||||
|
||||
*table = g_hash_table_ref (item->links);
|
||||
*table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
|
||||
{
|
||||
GHashTableIter tmp;
|
||||
gpointer key;
|
||||
gpointer value;
|
||||
|
||||
g_hash_table_iter_init (&tmp, item->links);
|
||||
while (g_hash_table_iter_next (&tmp, &key, &value))
|
||||
{
|
||||
if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(uu)")))
|
||||
{
|
||||
guint group_id, menu_id;
|
||||
GMenuProxyGroup *group;
|
||||
GMenuProxy *link;
|
||||
|
||||
g_variant_get (value, "(uu)", &group_id, &menu_id);
|
||||
|
||||
/* save the hash lookup in a relatively common case */
|
||||
if (proxy->group->id != group_id)
|
||||
group = g_menu_proxy_group_get_from_path (proxy->group->path, group_id);
|
||||
else
|
||||
group = g_menu_proxy_group_ref (proxy->group);
|
||||
|
||||
link = g_menu_proxy_get_from_group (group, menu_id);
|
||||
|
||||
g_hash_table_insert (*table, g_strdup (key), link);
|
||||
|
||||
g_menu_proxy_group_unref (group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user