[anjuta/symbol-db-model: 1/4] symbol-db: Added initial implementation of symbol-db tree model



commit 4c1be5509d4dac89c65ad4d4a24ddd0347844cc8
Author: Naba Kumar <naba gnome org>
Date:   Fri Mar 12 00:46:19 2010 +0200

    symbol-db: Added initial implementation of symbol-db tree model

 plugins/symbol-db/symbol-db-model.c |  826 +++++++++++++++++++++++++++++++++++
 plugins/symbol-db/symbol-db-model.h |   89 ++++
 2 files changed, 915 insertions(+), 0 deletions(-)
---
diff --git a/plugins/symbol-db/symbol-db-model.c b/plugins/symbol-db/symbol-db-model.c
new file mode 100644
index 0000000..e92369d
--- /dev/null
+++ b/plugins/symbol-db/symbol-db-model.c
@@ -0,0 +1,826 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * symbol-db-model.c
+ * Copyright (C) Naba Kumar 2010 <naba gnome org>
+ * 
+ * anjuta is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * anjuta is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <libgda/libgda.h>
+#include <libanjuta/anjuta-marshal.h>
+#include "symbol-db-model.h"
+
+#define SYMBOL_DB_MODEL_STAMP 5364558
+
+#define GET_PRIV(o) \
+	(G_TYPE_INSTANCE_GET_PRIVATE((o), SYMBOL_DB_TYPE_MODEL, SymbolDBModelPriv))
+
+/* Constants */
+
+#define SYMBOL_DB_MODEL_PAGE_SIZE 100
+
+typedef struct _SymbolDBModelPage SymbolDBModelPage;
+struct _SymbolDBModelPage
+{
+	gint ref_count;
+	gint begin_offset, end_offset;
+	SymbolDBModelPage *next;
+};
+
+typedef struct _SymbolDBModelNode SymbolDBModelNode;
+struct _SymbolDBModelNode {
+	guint ref_count;
+	
+	GValue *values;
+	SymbolDBModelPage *page_refs;
+	
+	/* Data structure */
+	gint level;
+	SymbolDBModelNode *parent;
+	gint offset;
+	guint n_children;
+	SymbolDBModelNode **children;
+};
+
+typedef struct {
+	gint n_columns;      /* Number of columns in the model */
+	GType *column_types; /* Type of each column in the model */
+	gint *query_columns; /* Corresponding GdaDataModel column */
+	gint node_id_column;
+	GHashTable *refed_nodes;
+	SymbolDBModelNode *root;
+} SymbolDBModelPriv;
+
+enum {
+	SIGNAL_GET_HAS_CHILD,
+	SIGNAL_GET_N_CHILDREN,
+	SIGNAL_GET_CHILDREN,
+	LAST_SIGNAL
+};
+
+static guint symbol_db_model_signals[LAST_SIGNAL] = { 0 };
+
+/* Declarations */
+
+static void symbol_db_model_tree_model_init (GtkTreeModelIface *iface);
+
+static gboolean symbol_db_model_get_query_value_at (SymbolDBModel *model,
+                                                    GdaDataModel *data_model,
+                                                    gint position, gint column,
+                                                    GValue *value);
+
+static gboolean symbol_db_model_get_query_value (SymbolDBModel *model,
+                                                 GdaDataModel *data_model,
+                                                 GdaDataModelIter *iter,
+                                                 gint column,
+                                                 GValue *value);
+
+static void symbol_db_model_ensure_node_children (SymbolDBModel *model,
+                                                  SymbolDBModelNode *parent);
+
+/* Class definition */
+G_DEFINE_TYPE_WITH_CODE (SymbolDBModel, symbol_db_model, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
+                                                symbol_db_model_tree_model_init))
+/* Node */
+
+#define symbol_db_model_node_get_child(node, offset) ((node)->children[(offset)])
+
+static SymbolDBModelNode *
+symbol_db_model_node_new (SymbolDBModel *model, SymbolDBModelNode *parent,
+                          gint child_offset, GdaDataModel *data_model,
+                          GdaDataModelIter *data_iter)
+{
+	gint i;
+	SymbolDBModelPriv *priv = GET_PRIV (model);
+	SymbolDBModelNode* node = g_new0 (SymbolDBModelNode, 1);
+	node->values = g_new0 (GValue, priv->n_columns);
+	for (i = 0; i < priv->n_columns; i++)
+	{
+		g_value_init (&(node->values[i]), priv->column_types[i]);
+		symbol_db_model_get_query_value (model,
+		                                 data_model,
+		                                 data_iter,
+		                                 i, &(node->values[i]));
+	}
+	node->offset = child_offset;
+	node->parent = parent;
+	node->level = parent->level + 1;
+	return node;
+}
+
+/* SymbolDBModel implementation */
+
+static gboolean
+symbol_db_model_iter_is_valid (GtkTreeModel *model, GtkTreeIter *iter)
+{
+	SymbolDBModelNode *parent_node;
+	gint offset;
+
+	g_return_val_if_fail (SYMBOL_DB_IS_MODEL (model), FALSE);
+	g_return_val_if_fail (iter->stamp == SYMBOL_DB_MODEL_STAMP, FALSE);
+	g_return_val_if_fail (iter != NULL, FALSE);
+
+	parent_node = (SymbolDBModelNode*) iter->user_data;
+	offset = GPOINTER_TO_INT (iter->user_data2);
+	
+	g_return_val_if_fail (parent_node != NULL, FALSE);
+	g_return_val_if_fail (parent_node->children != NULL, FALSE);
+	g_return_val_if_fail (offset >= 0 && offset < parent_node->n_children,
+	                      FALSE);
+	return TRUE;
+}
+
+static SymbolDBModelPage*
+symbol_db_model_page_fault (SymbolDBModel *model,
+                                  SymbolDBModelNode *parent_node,
+                                  gint child_offset)
+{
+	SymbolDBModelPage *page, *prev_page;
+	gint i;
+	GdaDataModelIter *data_iter;
+	GdaDataModel *data_model = NULL;
+
+	page = parent_node->page_refs;
+	
+	prev_page = NULL;
+	
+	/* Find the page which holds result for given child_offset */
+	while (page)
+	{
+		if (child_offset >= page->begin_offset &&
+		    child_offset < page->end_offset)
+		{
+			/* child_offset has associated page */
+			return page;
+		}
+		if (child_offset < page->begin_offset)
+		{
+			/* Insert point is here */
+			break;
+		}
+		prev_page = page;
+		page = page->next;
+	}
+
+	/* Insert after prev_page */
+
+	/* New page to cover current child_offset */
+	page = g_new0 (SymbolDBModelPage, 1);
+
+	/* Define page range */
+	page->begin_offset = child_offset - SYMBOL_DB_MODEL_PAGE_SIZE;
+	page->end_offset = child_offset + SYMBOL_DB_MODEL_PAGE_SIZE;
+
+	/* Insert the new page after prev_page */
+	if (prev_page)
+	{
+		page->next = prev_page->next;
+		prev_page->next = page;
+	}
+	else /* Insert at head */
+	{
+		page->next = parent_node->page_refs;
+		parent_node->page_refs = page;
+	}
+	
+	/* Adjust boundries not to overlap with preceeding or following page */
+	if (prev_page && prev_page->end_offset > page->begin_offset)
+		page->begin_offset = prev_page->end_offset;
+
+	if (page->next && page->end_offset >= page->next->begin_offset)
+		page->end_offset = page->next->begin_offset;
+
+	/* Adjust boundries not to preceed 0 index */
+	if (page->begin_offset < 0)
+		page->begin_offset = 0;
+	
+	/* Loada page from database */
+	g_signal_emit_by_name (model, "get-children", parent_node->level,
+	                       parent_node->values, page->begin_offset,
+	                       page->end_offset - page->begin_offset,
+	                       &data_model);
+
+	/* Fill up the page */
+	data_iter = gda_data_model_create_iter (data_model);
+	if (gda_data_model_iter_move_to_row (data_iter, 0))
+	{
+		for (i = page->begin_offset; i < page->end_offset; i++)
+		{
+			if (i >= parent_node->n_children)
+			{
+				/* FIXME: There are more rows in DB. Extend node */
+				break;
+			}
+			SymbolDBModelNode *node =
+				symbol_db_model_node_new (model, parent_node, i,
+				                          data_model, data_iter);
+			g_assert (symbol_db_model_node_get_child (parent_node, i) == NULL);
+			symbol_db_model_node_get_child (parent_node, i) = node;
+			if (!gda_data_model_iter_move_next (data_iter))
+			{
+				if (i < (page->end_offset - 1))
+				{
+					/* FIXME: There are fewer rows in DB. Shrink node */
+				}
+				break;
+			}
+		}
+	}
+	
+	g_object_unref (data_iter);
+	g_object_unref (data_model);
+	return page;
+}
+
+/* GtkTreeModel implementation */
+
+static GtkTreeModelFlags
+symbol_db_model_get_flags (GtkTreeModel *tree_model)
+{
+	return GTK_TREE_MODEL_ITERS_PERSIST;
+}
+
+static GType
+symbol_db_model_get_column_type (GtkTreeModel *tree_model,
+                                 gint index)
+{
+	SymbolDBModelPriv *priv = GET_PRIV (tree_model);
+	g_return_val_if_fail (index < priv->n_columns, G_TYPE_INVALID);
+	return priv->column_types [index];
+}
+
+static gint
+symbol_db_model_get_n_columns (GtkTreeModel *tree_model)
+{
+	SymbolDBModelPriv *priv;
+	priv = GET_PRIV (tree_model);
+	return priv->n_columns;
+}
+
+static gboolean
+symbol_db_model_get_iter (GtkTreeModel *tree_model,
+                          GtkTreeIter *iter,
+                          GtkTreePath *path)
+{
+	gint i;
+	SymbolDBModelNode *node, *parent_node;
+	gint depth, *indx;
+	SymbolDBModelPriv *priv;
+	
+	g_return_val_if_fail (SYMBOL_DB_IS_MODEL(tree_model), FALSE);
+	g_return_val_if_fail (iter != NULL, FALSE);
+	g_return_val_if_fail (path != NULL, FALSE);
+	
+	depth = gtk_tree_path_get_depth (path);
+	g_return_val_if_fail (depth > 0, FALSE);
+
+	priv = GET_PRIV (tree_model);
+	indx = gtk_tree_path_get_indices (path);
+
+	/* Ensure root expansion */
+	if (priv->root->n_children == 0) 
+		symbol_db_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model),
+		                                      priv->root);
+	if (priv->root->n_children == 0) 
+		return FALSE;
+
+	parent_node = NULL;
+	node = priv->root;
+	for (i = 0; i < depth; i++)
+	{
+		parent_node = node;
+		if (node->children == NULL || node->n_children <= 0)
+		{
+			/* No child available */
+			
+			/* FIXME: Do something more graceful like actually
+			 * expanding the node and proceeding further.
+			 */
+			break;
+		}
+		if (indx[i] >= node->n_children)
+		{
+			g_warning ("Invalid path to iter conversion; no children list found at depth %d", i);
+			break;
+		}
+		node = symbol_db_model_node_get_child (node, indx[i]);
+	}
+	if (i != depth)
+	{
+		g_warning ("Invalid path to iter conversion; no child found");
+		return FALSE;
+	}
+	iter->stamp = SYMBOL_DB_MODEL_STAMP;
+	iter->user_data = parent_node;
+	iter->user_data2 = GINT_TO_POINTER (indx[i-1]);
+
+	g_assert (symbol_db_model_iter_is_valid (tree_model, iter));
+
+	return TRUE;
+}
+
+static GtkTreePath*
+symbol_db_model_get_path (GtkTreeModel *tree_model,
+                          GtkTreeIter *iter)
+{
+	SymbolDBModelNode *node;
+	GtkTreePath* path;
+	SymbolDBModelPriv *priv;
+	gint offset;
+	
+	g_return_val_if_fail (symbol_db_model_iter_is_valid (tree_model, iter),
+	                      NULL);
+
+	priv = GET_PRIV (tree_model);
+	path = gtk_tree_path_new ();
+
+	node = (SymbolDBModelNode*)iter->user_data;
+	offset = GPOINTER_TO_INT (iter->user_data);
+	do {
+		gtk_tree_path_prepend_index (path, offset);
+		node = node->parent;
+		offset = node->offset;
+	} while (node);
+	return path;
+}
+
+static void
+symbol_db_model_get_value (GtkTreeModel *tree_model,
+                           GtkTreeIter *iter, gint column,
+                           GValue *value)
+{
+	SymbolDBModelPriv *priv;
+	SymbolDBModelNode *parent_node, *node;
+	SymbolDBModelPage *page;
+	gint offset;
+	
+	g_return_if_fail (symbol_db_model_iter_is_valid (tree_model, iter));
+
+	priv = GET_PRIV (tree_model);
+	
+	g_return_if_fail (column >= 0);
+	g_return_if_fail (column < priv->n_columns);
+	
+	parent_node = (SymbolDBModelNode*) iter->user_data;
+	offset = GPOINTER_TO_INT (iter->user_data2);
+
+	if (symbol_db_model_node_get_child (parent_node, offset) == NULL)
+		page = symbol_db_model_page_fault (SYMBOL_DB_MODEL (tree_model),
+		                                   parent_node, offset);
+	node = symbol_db_model_node_get_child (parent_node, offset);
+	g_value_init (value, priv->column_types[column]);
+	g_return_if_fail (node != NULL);
+	g_value_copy (&(node->values[column]), value);
+}
+
+static gboolean
+symbol_db_model_iter_next (GtkTreeModel *tree_model,
+                           GtkTreeIter *iter)
+{
+	SymbolDBModelNode *node;
+	gint offset;
+	
+	g_return_val_if_fail (iter != NULL, FALSE);
+	g_return_val_if_fail (iter->stamp == SYMBOL_DB_MODEL_STAMP, FALSE);
+	g_return_val_if_fail (iter->user_data != NULL, FALSE);
+	
+
+	node = (SymbolDBModelNode*)(iter->user_data);
+	offset = GPOINTER_TO_INT (iter->user_data2);
+	offset++;
+	
+	if (offset >= node->n_children)
+		return FALSE;
+	iter->user_data2 = GINT_TO_POINTER (offset);
+
+	g_assert (symbol_db_model_iter_is_valid (tree_model, iter));
+
+	return TRUE;
+}
+
+static gboolean
+symbol_db_model_iter_children (GtkTreeModel *tree_model,
+                               GtkTreeIter *iter,
+                               GtkTreeIter *parent)
+{
+	SymbolDBModelNode *node, *parent_node;
+	SymbolDBModelPriv *priv;
+
+	if (parent)
+	{
+		g_return_val_if_fail (symbol_db_model_iter_is_valid (tree_model,
+		                                                     parent),
+		                      FALSE);
+	}
+	
+	g_return_val_if_fail (SYMBOL_DB_IS_MODEL(tree_model), FALSE);
+	g_return_val_if_fail (iter != NULL, FALSE);
+
+	priv = GET_PRIV (tree_model);
+	if (parent == NULL)
+	{
+		node = priv->root;
+	}
+	else
+	{
+		gint offset;
+		parent_node = (SymbolDBModelNode*) parent->user_data;
+		offset = GPOINTER_TO_INT (parent->user_data2);
+		node = symbol_db_model_node_get_child (parent_node, offset);
+		g_return_val_if_fail (node != NULL, FALSE);
+	}
+	g_return_val_if_fail (node->children != NULL, FALSE);
+	g_return_val_if_fail (node->n_children > 0, FALSE);
+	
+	iter->user_data = node;
+	iter->user_data2 = GINT_TO_POINTER (0);
+	iter->stamp = SYMBOL_DB_MODEL_STAMP;
+
+	g_assert (symbol_db_model_iter_is_valid (tree_model, iter));
+
+	return TRUE;
+}
+
+static gboolean
+symbol_db_model_iter_has_child (GtkTreeModel *tree_model,
+                                GtkTreeIter *iter)
+{
+	gint offset;
+	SymbolDBModelNode *node, *parent_node;
+
+	g_return_val_if_fail (symbol_db_model_iter_is_valid (tree_model, iter),
+	                      FALSE);
+	
+	parent_node = (SymbolDBModelNode*) iter->user_data;
+	offset = GPOINTER_TO_INT (iter->user_data2);
+	
+	node = symbol_db_model_node_get_child (parent_node, offset);
+	if (node == NULL)
+	{
+		symbol_db_model_page_fault (SYMBOL_DB_MODEL (tree_model),
+		                            parent_node, offset);
+		node = symbol_db_model_node_get_child (parent_node, offset);
+		if (node == NULL)
+			return FALSE;
+	}
+
+	if (node->n_children <= 0)
+		symbol_db_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model),
+		                                      node);
+	return (node->n_children > 0);
+}
+
+static gint
+symbol_db_model_iter_n_children (GtkTreeModel *tree_model,
+                                 GtkTreeIter *iter)
+{
+	gint offset;
+	SymbolDBModelNode *node, *parent_node;
+	
+	g_return_val_if_fail (symbol_db_model_iter_is_valid (tree_model, iter),
+	                      FALSE);
+	
+	parent_node = (SymbolDBModelNode*) iter->user_data;
+	offset = GPOINTER_TO_INT (iter->user_data2);
+	
+	node = symbol_db_model_node_get_child (parent_node, offset);
+	if (node == NULL)
+		return 0;
+	return node->n_children;
+}
+
+static gboolean
+symbol_db_model_iter_nth_child (GtkTreeModel *tree_model,
+                                GtkTreeIter *iter,
+                                GtkTreeIter *parent,
+                                gint n)
+{
+	SymbolDBModelNode *node;
+	SymbolDBModelPriv *priv;
+	                           
+	g_return_val_if_fail (SYMBOL_DB_IS_MODEL(tree_model), FALSE);
+	g_return_val_if_fail (iter != NULL, FALSE);
+	g_return_val_if_fail (n >= 0, FALSE);
+
+	if (!symbol_db_model_iter_children (tree_model, iter, parent))
+		return FALSE;
+	
+	priv = GET_PRIV (tree_model);
+	node = (SymbolDBModelNode*) (iter->user_data);
+
+	g_return_val_if_fail (n < node->n_children, FALSE);
+	
+	iter->user_data2 = GINT_TO_POINTER (n);
+
+	g_assert (symbol_db_model_iter_is_valid (tree_model, iter));
+
+	return TRUE;
+}
+
+static gboolean
+symbol_db_model_iter_parent (GtkTreeModel *tree_model,
+                             GtkTreeIter *iter,
+                             GtkTreeIter *child)
+{
+	SymbolDBModelNode *parent_node;
+	
+	g_return_val_if_fail (symbol_db_model_iter_is_valid (tree_model, child),
+	                      FALSE);
+	
+	g_return_val_if_fail (iter != NULL, FALSE);
+	
+	parent_node = (SymbolDBModelNode*) child->user_data;
+	g_return_val_if_fail (parent_node->parent != NULL, FALSE);
+	
+	iter->user_data = parent_node->parent;
+	iter->user_data2 = GINT_TO_POINTER (parent_node->offset);
+	iter->stamp = SYMBOL_DB_MODEL_STAMP;
+
+	g_assert (symbol_db_model_iter_is_valid (tree_model, iter));
+
+	return TRUE;
+}
+
+static void
+symbol_db_model_ref_node (GtkTreeModel *tree_model, GtkTreeIter  *iter)
+{
+}
+
+static void
+symbol_db_model_unref_node (GtkTreeModel *tree_model, GtkTreeIter  *iter)
+{
+}
+
+static void
+symbol_db_model_tree_model_init (GtkTreeModelIface *iface)
+{
+	iface->get_flags = symbol_db_model_get_flags;
+	iface->get_n_columns = symbol_db_model_get_n_columns;
+	iface->get_column_type = symbol_db_model_get_column_type;
+	iface->get_iter = symbol_db_model_get_iter;
+	iface->get_path = symbol_db_model_get_path;
+	iface->get_value = symbol_db_model_get_value;
+	iface->iter_next = symbol_db_model_iter_next;
+	iface->iter_children = symbol_db_model_iter_children;
+	iface->iter_has_child = symbol_db_model_iter_has_child;
+	iface->iter_n_children = symbol_db_model_iter_n_children;
+	iface->iter_nth_child = symbol_db_model_iter_nth_child;
+	iface->iter_parent = symbol_db_model_iter_parent;
+	iface->ref_node = symbol_db_model_ref_node;
+	iface->ref_node = symbol_db_model_unref_node;
+}
+
+/* SymbolDBModel implementation */
+
+static void
+symbol_db_model_ensure_node_children (SymbolDBModel *model,
+                                      SymbolDBModelNode *potential_parent)
+{
+	gint n_children;
+
+	/* FIXME: Should we free (properly) existing children instead? */
+	g_return_if_fail (potential_parent->children == NULL);
+	g_return_if_fail (potential_parent->n_children == 0);
+	
+	g_signal_emit_by_name (model, "get-n-children",
+	                       potential_parent->level,
+	                       potential_parent->values,
+	                       &n_children);
+	
+	potential_parent->n_children = n_children;
+	potential_parent->children = g_new0 (SymbolDBModelNode*, n_children);
+}
+
+static gboolean
+symbol_db_model_get_query_value_real (SymbolDBModel *model,
+                                      GdaDataModel *data_model,
+                                      GdaDataModelIter *iter, gint column,
+                                      GValue *value)
+{
+	const GValue *ret;
+	SymbolDBModelPriv *priv = GET_PRIV (model);
+	gint query_column = priv->query_columns[column];
+
+	if (query_column < 0)
+		return FALSE;
+
+	ret = gda_data_model_iter_get_value_at (iter, query_column);
+	if (!ret)
+		return FALSE;
+
+	g_value_copy (ret, value);
+	return FALSE;
+}
+
+static gboolean
+symbol_db_model_get_query_value (SymbolDBModel *model,
+                                 GdaDataModel *data_model,
+                                 GdaDataModelIter *iter, gint column,
+                                 GValue *value)
+{
+	return SYMBOL_DB_MODEL_GET_CLASS(model)->get_query_value(model, data_model,
+	                                                         iter, column,
+	                                                         value);
+}
+
+static gboolean
+symbol_db_model_get_query_value_at_real (SymbolDBModel *model,
+                                         GdaDataModel *data_model,
+                                         gint position, gint column,
+                                         GValue *value)
+{
+	const GValue *ret;
+	SymbolDBModelPriv *priv = GET_PRIV (model);
+	gint query_column = priv->query_columns[column];
+	g_value_init (value, priv->column_types[column]);
+
+	if (query_column < 0)
+		return FALSE;
+
+	ret = gda_data_model_get_value_at (data_model, query_column, position,
+	                                   NULL);
+	if (!ret)
+		return FALSE;
+
+	g_value_copy (ret, value);
+	return FALSE;
+}
+
+static gboolean
+symbol_db_model_get_query_value_at (SymbolDBModel *model,
+                                    GdaDataModel *data_model,
+                                    gint position, gint column, GValue *value)
+{
+	return SYMBOL_DB_MODEL_GET_CLASS(model)->get_query_value_at (model,
+	                                                             data_model,
+	                                                             position,
+	                                                             column,
+	                                                             value);
+}
+
+/* Object implementation */
+
+static void
+symbol_db_model_finalize (GObject *object)
+{
+	/* FIXME */
+	G_OBJECT_CLASS (symbol_db_model_parent_class)->finalize (object);
+}
+
+static void
+symbol_db_model_set_property (GObject *object, guint prop_id,
+                              const GValue *value, GParamSpec *pspec)
+{
+	g_return_if_fail (SYMBOL_DB_IS_MODEL (object));
+	SymbolDBModel* model = SYMBOL_DB_MODEL(object);
+	SymbolDBModelPriv* priv = GET_PRIV (model);
+	
+	switch (prop_id)
+	{
+	}
+}
+
+static void
+symbol_db_model_get_property (GObject *object, guint prop_id, GValue *value,
+                              GParamSpec *pspec)
+{
+	g_return_if_fail (SYMBOL_DB_IS_MODEL (object));
+	SymbolDBModel* model = SYMBOL_DB_MODEL(object);
+	SymbolDBModelPriv* priv = GET_PRIV (model);
+	
+	switch (prop_id)
+	{
+	}
+}
+
+static void
+symbol_db_model_init (SymbolDBModel *object)
+{
+	SymbolDBModelPriv *priv = GET_PRIV (object);
+	priv->root = g_new0 (SymbolDBModelNode, 1);
+	priv->n_columns = 0;
+	priv->column_types = NULL;
+	priv->query_columns = NULL;
+}
+
+static void
+symbol_db_model_class_init (SymbolDBModelClass *klass)
+{
+	GObjectClass* object_class = G_OBJECT_CLASS (klass);
+
+	klass->get_query_value = symbol_db_model_get_query_value_real;
+	klass->get_query_value_at = symbol_db_model_get_query_value_at_real;
+	object_class->finalize = symbol_db_model_finalize;
+	object_class->set_property = symbol_db_model_set_property;
+	object_class->get_property = symbol_db_model_get_property;
+	
+	g_type_class_add_private (object_class, sizeof(SymbolDBModelPriv));
+
+	/* Signals */
+	symbol_db_model_signals[SIGNAL_GET_HAS_CHILD] =
+		g_signal_new ("get-has-child",
+		              G_TYPE_FROM_CLASS (klass),
+		              G_SIGNAL_RUN_LAST,
+		              0, NULL, NULL,
+					  anjuta_cclosure_marshal_BOOLEAN__INT_POINTER,
+		              G_TYPE_BOOLEAN,
+		              2,
+		              G_TYPE_INT,
+		              G_TYPE_POINTER);
+	symbol_db_model_signals[SIGNAL_GET_N_CHILDREN] =
+		g_signal_new ("get-n-children",
+		              G_TYPE_FROM_CLASS (klass),
+		              G_SIGNAL_RUN_LAST,
+		              0, NULL, NULL,
+					  anjuta_cclosure_marshal_INT__INT_POINTER,
+		              G_TYPE_INT,
+		              2,
+		              G_TYPE_INT,
+		              G_TYPE_POINTER);
+	symbol_db_model_signals[SIGNAL_GET_CHILDREN] =
+		g_signal_new ("get-children",
+		              G_TYPE_FROM_CLASS (klass),
+		              G_SIGNAL_RUN_LAST,
+		              0, NULL, NULL,
+					  anjuta_cclosure_marshal_OBJECT__INT_POINTER_INT_INT,
+		              GDA_TYPE_DATA_MODEL,
+		              4,
+		              G_TYPE_INT,
+		              G_TYPE_POINTER,
+		              G_TYPE_INT,
+		              G_TYPE_INT);
+}
+
+void
+symbol_db_model_set_columns (SymbolDBModel *model, gint n_columns,
+                             GType *types, gint *query_columns)
+{
+	SymbolDBModelPriv *priv;
+
+	g_return_if_fail (n_columns > 0);
+	priv = GET_PRIV (model);
+	
+	g_return_if_fail (priv->n_columns <= 0);
+	g_return_if_fail (priv->column_types == NULL);
+	g_return_if_fail (priv->query_columns == NULL);
+	
+	priv->n_columns = n_columns;
+	priv->column_types = g_new0(GType, n_columns);
+	priv->query_columns = g_new0(gint, n_columns);
+	memcpy (priv->column_types, types, n_columns * sizeof (GType));
+	memcpy (priv->query_columns, query_columns, n_columns * sizeof (gint));
+}
+
+GtkTreeModel *
+symbol_db_model_new (gint n_columns, ...)
+{
+	GtkTreeModel *model;
+	SymbolDBModelPriv *priv;
+	va_list args;
+	gint i;
+
+	g_return_val_if_fail (n_columns > 0, NULL);
+
+	model = g_object_new (SYMBOL_DB_TYPE_MODEL, NULL);
+	priv = GET_PRIV (model);
+	
+	priv->n_columns = n_columns;
+	priv->column_types = g_new0(GType, n_columns);
+	priv->query_columns = g_new0(gint, n_columns);
+	
+	va_start (args, n_columns);
+
+	for (i = 0; i < n_columns; i++)
+	{
+		priv->column_types[i] = va_arg (args, GType);
+		priv->query_columns[i] = va_arg (args, gint);
+	}
+	va_end (args);
+
+	return model;
+}
+
+GtkTreeModel*
+symbol_db_model_newv (gint n_columns, GType *types, gint *query_columns)
+{
+	GtkTreeModel *model;
+	g_return_val_if_fail (n_columns > 0, NULL);
+	model = g_object_new (SYMBOL_DB_TYPE_MODEL, NULL);
+	symbol_db_model_set_columns (SYMBOL_DB_MODEL (model), n_columns,
+	                             types, query_columns);
+	return model;
+}
+
diff --git a/plugins/symbol-db/symbol-db-model.h b/plugins/symbol-db/symbol-db-model.h
new file mode 100644
index 0000000..de6a8e7
--- /dev/null
+++ b/plugins/symbol-db/symbol-db-model.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * symbol-db-model.h
+ * Copyright (C) Naba Kumar 2010 <naba gnome org>
+ * 
+ * anjuta is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * anjuta is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SYMBOL_DB_MODEL_H_
+#define _SYMBOL_DB_MODEL_H_
+
+#include <glib-object.h>
+#include <gtk/gtktreemodel.h>
+#include <libgda/gda-data-model.h>
+#include "symbol-db-engine.h"
+
+G_BEGIN_DECLS
+
+#define SYMBOL_DB_TYPE_MODEL             (symbol_db_model_get_type ())
+#define SYMBOL_DB_MODEL(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), SYMBOL_DB_TYPE_MODEL, SymbolDBModel))
+#define SYMBOL_DB_MODEL_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), SYMBOL_DB_TYPE_MODEL, SymbolDBModelClass))
+#define SYMBOL_DB_IS_MODEL(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SYMBOL_DB_TYPE_MODEL))
+#define SYMBOL_DB_IS_MODEL_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), SYMBOL_DB_TYPE_MODEL))
+#define SYMBOL_DB_MODEL_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), SYMBOL_DB_TYPE_MODEL, SymbolDBModelClass))
+
+typedef struct _SymbolDBModelClass SymbolDBModelClass;
+typedef struct _SymbolDBModel SymbolDBModel;
+
+struct _SymbolDBModelClass
+{
+	GObjectClass parent_class;
+
+	/* Virtual methods */
+	gboolean (*get_query_value) (SymbolDBModel *model,
+	                             GdaDataModel *data_model,
+	                             GdaDataModelIter *iter, gint column,
+	                             GValue *value);
+	
+	gboolean (*get_query_value_at) (SymbolDBModel *model,
+	                                GdaDataModel *data_model, gint position,
+	                                gint column, GValue *value);
+
+	/* Pure virtual methods; alternatives to signals */
+	
+	gboolean (*get_has_child) (SymbolDBModel *model, gint tree_level,
+	                           GValue column_values[]);
+
+	gint (*get_n_children) (SymbolDBModel *model, gint tree_level,
+	                        GValue column_values[]);
+
+	GdaDataModel* (*get_children) (SymbolDBModel *model, gint tree_level,
+	                               GValue column_values[],
+	                               gint offset, gint limit);
+};
+
+struct _SymbolDBModel
+{
+	GObject parent_instance;
+};
+
+GType symbol_db_model_get_type (void) G_GNUC_CONST;
+
+/* Use this to create the model normally. The "..." part is alternatively GType
+ * and gint for column type and corresponding GdaDataModel column.
+ */
+GtkTreeModel* symbol_db_model_new (gint n_columns, ...);
+
+/* Normally used by bindings */
+GtkTreeModel* symbol_db_model_newv (gint n_columns, GType *types,
+                                    gint *data_cols);
+
+/* Used by derived classes */
+void symbol_db_model_set_columns (SymbolDBModel *model, gint n_columns,
+                                  GType *types, gint *data_cols);
+
+G_END_DECLS
+
+#endif /* _SYMBOL_DB_MODEL_H_ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]