From 8acfeae8c85d402b1fe2357deeeae3cbb3ebb312 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch <p.janouch@gmail.com>
Date: Thu, 30 Aug 2012 07:39:40 +0200
Subject: Make child Categories point back to their parents.

---
 liblogdiag/ld-category-view.c |  3 ++
 liblogdiag/ld-category.c      | 83 +++++++++++++++++++++++++++++++++++++++++--
 liblogdiag/ld-category.h      |  3 ++
 3 files changed, 86 insertions(+), 3 deletions(-)

(limited to 'liblogdiag')

diff --git a/liblogdiag/ld-category-view.c b/liblogdiag/ld-category-view.c
index cc56158..80ed571 100644
--- a/liblogdiag/ld-category-view.c
+++ b/liblogdiag/ld-category-view.c
@@ -170,6 +170,9 @@ ld_category_view_set_category (LdCategoryView *self, LdCategory *category)
 		g_signal_connect_data (category, "children-changed",
 			G_CALLBACK (reload_category), self,
 			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);
 	}
 	reload_category (self);
diff --git a/liblogdiag/ld-category.c b/liblogdiag/ld-category.c
index 6a4cf8c..b15b6de 100644
--- a/liblogdiag/ld-category.c
+++ b/liblogdiag/ld-category.c
@@ -22,6 +22,7 @@
 
 /*
  * LdCategoryPrivate:
+ * @parent: the parent of this category.
  * @name: the name of this category.
  * @human_name: the localized human-readable name of this category.
  * @symbols: (element-type LdSymbol *): symbols in this category.
@@ -29,6 +30,7 @@
  */
 struct _LdCategoryPrivate
 {
+	LdCategory *parent;
 	gchar *name;
 	gchar *human_name;
 	GSList *symbols;
@@ -38,6 +40,7 @@ struct _LdCategoryPrivate
 enum
 {
 	PROP_0,
+	PROP_PARENT,
 	PROP_NAME,
 	PROP_HUMAN_NAME
 };
@@ -65,6 +68,16 @@ ld_category_class_init (LdCategoryClass *klass)
 	object_class->set_property = ld_category_set_property;
 	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:
  *
@@ -130,6 +143,9 @@ ld_category_get_property (GObject *object, guint property_id,
 	case PROP_HUMAN_NAME:
 		g_value_set_string (value, ld_category_get_human_name (self));
 		break;
+	case PROP_PARENT:
+		g_value_set_object (value, ld_category_get_parent (self));
+		break;
 	default:
 		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:
 		ld_category_set_human_name (self, g_value_get_string (value));
 		break;
+	case PROP_PARENT:
+		ld_category_set_parent (self, g_value_get_object (value));
+		break;
 	default:
 		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,
 		on_category_notify_name, self);
+	if (ld_category_get_parent (category) == self)
+		ld_category_set_parent (category, NULL);
 	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
 ld_category_finalize (GObject *gobject)
 {
@@ -170,6 +207,10 @@ ld_category_finalize (GObject *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)
 		g_free (self->priv->name);
 	if (self->priv->human_name)
@@ -349,6 +390,43 @@ ld_category_get_symbols (LdCategory *self)
 	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
 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);
 	self->priv->subcategories = g_slist_insert_before
 		(self->priv->subcategories, iter, category);
+	ld_category_set_parent (category, self);
 	g_object_ref (category);
 
 	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)))
 	{
-		g_signal_handlers_disconnect_by_func (category,
-			on_category_notify_name, self);
 		self->priv->subcategories
 			= g_slist_delete_link (self->priv->subcategories, link);
-		g_object_unref (category);
+		uninstall_category_cb (category, self);
 
 		g_signal_emit (self,
 			LD_CATEGORY_GET_CLASS (self)->children_changed_signal, 0);
diff --git a/liblogdiag/ld-category.h b/liblogdiag/ld-category.h
index 6b77596..59d6449 100644
--- a/liblogdiag/ld-category.h
+++ b/liblogdiag/ld-category.h
@@ -65,6 +65,9 @@ gboolean ld_category_insert_symbol (LdCategory *self,
 void ld_category_remove_symbol (LdCategory *self, LdSymbol *symbol);
 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);
 void ld_category_remove_child (LdCategory *self, LdCategory *category);
 const GSList *ld_category_get_children (LdCategory *self);
-- 
cgit v1.2.3-70-g09d2