Make child Categories point back to their parents.

This commit is contained in:
Přemysl Eric Janouch 2012-08-30 07:39:40 +02:00
parent 47023938ca
commit 8acfeae8c8
3 changed files with 86 additions and 3 deletions

View File

@ -170,6 +170,9 @@ ld_category_view_set_category (LdCategoryView *self, LdCategory *category)
g_signal_connect_data (category, "children-changed", g_signal_connect_data (category, "children-changed",
G_CALLBACK (reload_category), self, G_CALLBACK (reload_category), self,
NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED); NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
g_signal_connect_data (category, "notify::parent",
G_CALLBACK (reload_category), self,
NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
g_object_ref (category); g_object_ref (category);
} }
reload_category (self); reload_category (self);

View File

@ -22,6 +22,7 @@
/* /*
* LdCategoryPrivate: * LdCategoryPrivate:
* @parent: the parent of this category.
* @name: the name of this category. * @name: the name of this category.
* @human_name: the localized human-readable name of this category. * @human_name: the localized human-readable name of this category.
* @symbols: (element-type LdSymbol *): symbols in this category. * @symbols: (element-type LdSymbol *): symbols in this category.
@ -29,6 +30,7 @@
*/ */
struct _LdCategoryPrivate struct _LdCategoryPrivate
{ {
LdCategory *parent;
gchar *name; gchar *name;
gchar *human_name; gchar *human_name;
GSList *symbols; GSList *symbols;
@ -38,6 +40,7 @@ struct _LdCategoryPrivate
enum enum
{ {
PROP_0, PROP_0,
PROP_PARENT,
PROP_NAME, PROP_NAME,
PROP_HUMAN_NAME PROP_HUMAN_NAME
}; };
@ -65,6 +68,16 @@ ld_category_class_init (LdCategoryClass *klass)
object_class->set_property = ld_category_set_property; object_class->set_property = ld_category_set_property;
object_class->finalize = ld_category_finalize; object_class->finalize = ld_category_finalize;
/**
* LdCategory:parent:
*
* The parent of this symbol category.
*/
pspec = g_param_spec_string ("parent", "Parent",
"The parent of this symbol category.",
"", G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_PARENT, pspec);
/** /**
* LdCategory:name: * LdCategory:name:
* *
@ -130,6 +143,9 @@ ld_category_get_property (GObject *object, guint property_id,
case PROP_HUMAN_NAME: case PROP_HUMAN_NAME:
g_value_set_string (value, ld_category_get_human_name (self)); g_value_set_string (value, ld_category_get_human_name (self));
break; break;
case PROP_PARENT:
g_value_set_object (value, ld_category_get_parent (self));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
} }
@ -150,6 +166,9 @@ ld_category_set_property (GObject *object, guint property_id,
case PROP_HUMAN_NAME: case PROP_HUMAN_NAME:
ld_category_set_human_name (self, g_value_get_string (value)); ld_category_set_human_name (self, g_value_get_string (value));
break; break;
case PROP_PARENT:
ld_category_set_parent (self, g_value_get_object (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
} }
@ -160,9 +179,27 @@ uninstall_category_cb (LdCategory *category, LdCategory *self)
{ {
g_signal_handlers_disconnect_by_func (category, g_signal_handlers_disconnect_by_func (category,
on_category_notify_name, self); on_category_notify_name, self);
if (ld_category_get_parent (category) == self)
ld_category_set_parent (category, NULL);
g_object_unref (category); g_object_unref (category);
} }
static void
parent_weak_notify (gpointer data, GObject *object)
{
LdCategory *self;
/* In practice this should never happen, for it would mean that
* we have a parent that have us as its child.
*/
self = (LdCategory *) data;
if (self->priv->parent)
{
self->priv->parent = NULL;
g_object_notify (G_OBJECT (self), "parent");
}
}
static void static void
ld_category_finalize (GObject *gobject) ld_category_finalize (GObject *gobject)
{ {
@ -170,6 +207,10 @@ ld_category_finalize (GObject *gobject)
self = LD_CATEGORY (gobject); self = LD_CATEGORY (gobject);
if (self->priv->parent)
g_object_weak_unref
(G_OBJECT (self->priv->parent), parent_weak_notify, self);
if (self->priv->name) if (self->priv->name)
g_free (self->priv->name); g_free (self->priv->name);
if (self->priv->human_name) if (self->priv->human_name)
@ -349,6 +390,43 @@ ld_category_get_symbols (LdCategory *self)
return self->priv->symbols; return self->priv->symbols;
} }
/**
* ld_category_set_parent:
* @self: an #LdCategory object.
* @parent: the new parent category.
*
* Set the parent of this category.
*/
void
ld_category_set_parent (LdCategory *self, LdCategory *parent)
{
g_return_if_fail (LD_IS_CATEGORY (self));
g_return_if_fail (parent == NULL || LD_IS_CATEGORY (parent));
if (self->priv->parent)
g_object_weak_unref
(G_OBJECT (self->priv->parent), parent_weak_notify, self);
self->priv->parent = parent;
if (parent)
g_object_weak_ref (G_OBJECT (parent), parent_weak_notify, self);
g_object_notify (G_OBJECT (self), "parent");
}
/**
* ld_category_get_parent:
* @self: an #LdCategory object.
*
* Return value: the parent of this category.
*/
LdCategory *
ld_category_get_parent (LdCategory *self)
{
g_return_val_if_fail (LD_IS_CATEGORY (self), NULL);
return self->priv->parent;
}
static void static void
on_category_notify_name (LdCategory *category, on_category_notify_name (LdCategory *category,
@ -404,6 +482,7 @@ ld_category_add_child (LdCategory *self, LdCategory *category)
G_CALLBACK (on_category_notify_name), self); G_CALLBACK (on_category_notify_name), self);
self->priv->subcategories = g_slist_insert_before self->priv->subcategories = g_slist_insert_before
(self->priv->subcategories, iter, category); (self->priv->subcategories, iter, category);
ld_category_set_parent (category, self);
g_object_ref (category); g_object_ref (category);
g_signal_emit (self, g_signal_emit (self,
@ -428,11 +507,9 @@ ld_category_remove_child (LdCategory *self, LdCategory *category)
if ((link = g_slist_find (self->priv->subcategories, category))) if ((link = g_slist_find (self->priv->subcategories, category)))
{ {
g_signal_handlers_disconnect_by_func (category,
on_category_notify_name, self);
self->priv->subcategories self->priv->subcategories
= g_slist_delete_link (self->priv->subcategories, link); = g_slist_delete_link (self->priv->subcategories, link);
g_object_unref (category); uninstall_category_cb (category, self);
g_signal_emit (self, g_signal_emit (self,
LD_CATEGORY_GET_CLASS (self)->children_changed_signal, 0); LD_CATEGORY_GET_CLASS (self)->children_changed_signal, 0);

View File

@ -65,6 +65,9 @@ gboolean ld_category_insert_symbol (LdCategory *self,
void ld_category_remove_symbol (LdCategory *self, LdSymbol *symbol); void ld_category_remove_symbol (LdCategory *self, LdSymbol *symbol);
const GSList *ld_category_get_symbols (LdCategory *self); const GSList *ld_category_get_symbols (LdCategory *self);
void ld_category_set_parent (LdCategory *self, LdCategory *parent);
LdCategory *ld_category_get_parent (LdCategory *self);
gboolean ld_category_add_child (LdCategory *self, LdCategory *category); gboolean ld_category_add_child (LdCategory *self, LdCategory *category);
void ld_category_remove_child (LdCategory *self, LdCategory *category); void ld_category_remove_child (LdCategory *self, LdCategory *category);
const GSList *ld_category_get_children (LdCategory *self); const GSList *ld_category_get_children (LdCategory *self);