[anjuta/symbol-db-model] symbol-db: Update symbol model
- From: Naba Kumar <naba src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta/symbol-db-model] symbol-db: Update symbol model
- Date: Thu, 18 Mar 2010 20:46:10 +0000 (UTC)
commit c52777049de7b9a1afb44988015b5a2ea5a3d381
Author: Naba Kumar <naba gnome org>
Date: Thu Mar 18 20:34:59 2010 +0200
symbol-db: Update symbol model
plugins/symbol-db/symbol-db-model.c | 322 +++++++++++++++++++++++++++--------
plugins/symbol-db/symbol-db-model.h | 2 +
2 files changed, 251 insertions(+), 73 deletions(-)
---
diff --git a/plugins/symbol-db/symbol-db-model.c b/plugins/symbol-db/symbol-db-model.c
index c088e0c..2613642 100644
--- a/plugins/symbol-db/symbol-db-model.c
+++ b/plugins/symbol-db/symbol-db-model.c
@@ -58,9 +58,10 @@ struct _SymbolDBModelNode {
gint offset;
/* Children states */
+ gint children_ref_count;
+ GHashTable *refed_rows;
gboolean children_ensured;
guint n_children;
- gint children_ref_count;
SymbolDBModelNode **children;
};
@@ -68,8 +69,7 @@ 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;
-
+
/* Idle child-ensure queue */
GQueue *ensure_children_queue;
guint ensure_children_idle_id;
@@ -88,13 +88,14 @@ static guint symbol_db_model_signals[LAST_SIGNAL] = { 0 };
/* Declarations */
-static void symbol_db_model_node_free (SymbolDBModelNode *node);
+static void symbol_db_model_node_free (SymbolDBModelNode *node, gboolean force);
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,
@@ -112,9 +113,11 @@ static GdaDataModel* symbol_db_model_get_children (SymbolDBModel *model,
GValue column_values[],
gint offset, gint limit);
-static void symbol_db_model_node_ensure_children (SymbolDBModel *model,
+static void symbol_db_model_queue_ensure_node_children (SymbolDBModel *model,
+ SymbolDBModelNode *parent);
+
+static void symbol_db_model_ensure_node_children (SymbolDBModel *model,
SymbolDBModelNode *parent,
- gboolean queue_it,
gboolean emit_has_child);
/* Class definition */
@@ -146,7 +149,7 @@ symbol_db_model_node_set_child (SymbolDBModelNode *node, gint child_offset,
}
static gboolean
-symbol_db_model_node_cleanse (SymbolDBModelNode *node)
+symbol_db_model_node_cleanse (SymbolDBModelNode *node, gboolean force)
{
SymbolDBModelPage *page, *next;
gint i;
@@ -154,10 +157,13 @@ symbol_db_model_node_cleanse (SymbolDBModelNode *node)
g_return_val_if_fail (node != NULL, FALSE);
/* Can not cleanse a node if there are refed children */
- g_return_val_if_fail (node->children_ref_count == 0, FALSE);
-
- if (node->children_ensured)
- {
+ if (!force)
+ {
+ g_return_val_if_fail (node->children_ref_count == 0, FALSE);
+ }
+
+ if (node->children)
+ {
/* There should be no children with any ref. Children with ref count 0
* are floating children and can be destroyed.
*/
@@ -166,9 +172,12 @@ symbol_db_model_node_cleanse (SymbolDBModelNode *node)
SymbolDBModelNode *child = symbol_db_model_node_get_child (node, i);
if (child)
{
- /* Assert on nodes with ref count > 0 */
- g_warn_if_fail (child->children_ref_count == 0);
- symbol_db_model_node_free (child);
+ if (!force)
+ {
+ /* Assert on nodes with ref count > 0 */
+ g_warn_if_fail (child->children_ref_count == 0);
+ }
+ symbol_db_model_node_free (child, force);
symbol_db_model_node_set_child (node, i, NULL);
}
}
@@ -184,6 +193,9 @@ symbol_db_model_node_cleanse (SymbolDBModelNode *node)
}
node->pages = NULL;
node->children_ensured = FALSE;
+ node->n_children = 0;
+
+ /* Destroy arrays */
g_free (node->children);
node->children = NULL;
@@ -191,12 +203,13 @@ symbol_db_model_node_cleanse (SymbolDBModelNode *node)
}
static void
-symbol_db_model_node_free (SymbolDBModelNode *node)
+symbol_db_model_node_free (SymbolDBModelNode *node, gboolean force)
{
- if (!symbol_db_model_node_cleanse (node))
+ if (!symbol_db_model_node_cleanse (node, force))
return;
g_free (node->values);
+ g_hash_table_destroy (node->refed_rows);
g_free (node);
}
@@ -269,33 +282,50 @@ symbol_db_model_node_ref_child (SymbolDBModelNode *node)
g_return_if_fail (node != NULL);
node->children_ref_count++;
-
- /* Increate associated ref count on parent also */
+
if (node->parent)
+ {
+ /* If the node started having ref count greater than 1, then there
+ * are refed children, which means node is expanded. Tell parent.
+ */
+ if (node->children_ref_count >= 1)
+ {
+ g_hash_table_insert (node->parent->refed_rows,
+ GINT_TO_POINTER (node->offset),
+ GINT_TO_POINTER (node->offset));
+ }
+ /* Increate associated ref count on parents and hold refs to their rows */
symbol_db_model_node_ref_child (node->parent);
+ }
}
static void
symbol_db_model_node_unref_child (SymbolDBModelNode *node, gint child_offset)
{
- SymbolDBModelNode *parent_node;
- gint node_offset;
g_return_if_fail (node != NULL);
g_return_if_fail (node->children_ref_count > 0);
node->children_ref_count--;
- parent_node = node->parent;
- node_offset = node->offset;
-
+
/* If ref count reaches 0, cleanse this node */
if (node->children_ref_count <= 0)
{
- symbol_db_model_node_cleanse (node);
+ symbol_db_model_node_cleanse (node, FALSE);
}
- /* Reduce the associated ref count on parent also */
- if (parent_node)
- symbol_db_model_node_unref_child (parent_node, node_offset);
+ if (node->parent)
+ {
+ /* If the node has only one ref count, then it has no child
+ * referenced and therefore not expanded
+ */
+ if (node->children_ref_count <= 1)
+ {
+ g_hash_table_remove (node->parent->refed_rows,
+ GINT_TO_POINTER (node->offset));
+ }
+ /* Reduce ref count on parent as well */
+ symbol_db_model_node_unref_child (node->parent, node->offset);
+ }
}
static SymbolDBModelNode *
@@ -317,6 +347,7 @@ symbol_db_model_node_new (SymbolDBModel *model, SymbolDBModelNode *parent,
}
node->offset = child_offset;
node->parent = parent;
+ node->refed_rows = g_hash_table_new (g_direct_hash, g_direct_equal);
node->level = parent->level + 1;
return node;
}
@@ -348,15 +379,17 @@ symbol_db_model_page_fault (SymbolDBModel *model,
SymbolDBModelNode *parent_node,
gint child_offset)
{
- SymbolDBModelPage *page, *prev_page;
+ SymbolDBModelPage *page, *prev_page, *page_found;
gint i;
GdaDataModelIter *data_iter;
GdaDataModel *data_model = NULL;
/* Insert after prev_page */
- symbol_db_model_node_find_child_page (parent_node, child_offset,
- &prev_page);
-
+ page_found = symbol_db_model_node_find_child_page (parent_node,
+ child_offset,
+ &prev_page);
+ g_return_val_if_fail (page_found == NULL, page_found);
+
/* New page to cover current child_offset */
page = g_new0 (SymbolDBModelPage, 1);
@@ -421,7 +454,7 @@ symbol_db_model_page_fault (SymbolDBModel *model,
static GtkTreeModelFlags
symbol_db_model_get_flags (GtkTreeModel *tree_model)
{
- return GTK_TREE_MODEL_ITERS_PERSIST;
+ return 0;
}
static GType
@@ -470,8 +503,8 @@ symbol_db_model_get_iter (GtkTreeModel *tree_model,
{
parent_node = node;
if (!node->children_ensured)
- symbol_db_model_node_ensure_children (SYMBOL_DB_MODEL (tree_model),
- node, FALSE, FALSE);
+ symbol_db_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model),
+ node, FALSE);
if (node->children == NULL || node->n_children <= 0)
{
/* FIXME: No child available. View thinks there is child.
@@ -488,7 +521,7 @@ symbol_db_model_get_iter (GtkTreeModel *tree_model,
}
if (i != depth)
{
- g_warning ("Invalid path to iter conversion; no child found");
+ /* g_warning ("Invalid path to iter conversion; no child found"); */
return FALSE;
}
iter->stamp = SYMBOL_DB_MODEL_STAMP;
@@ -546,6 +579,7 @@ symbol_db_model_get_value (GtkTreeModel *tree_model,
parent_node = (SymbolDBModelNode*) iter->user_data;
offset = GPOINTER_TO_INT (iter->user_data2);
+ /* g_message ("Get value for %p->%d", parent_node, offset); */
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);
@@ -555,8 +589,8 @@ symbol_db_model_get_value (GtkTreeModel *tree_model,
/* View accessed the node, so update any pending has-child status */
if (!node->children_ensured)
- symbol_db_model_node_ensure_children (SYMBOL_DB_MODEL (tree_model),
- node, TRUE, TRUE);
+ symbol_db_model_queue_ensure_node_children (SYMBOL_DB_MODEL (tree_model),
+ node);
/* FIXME: We should also refresh children status even if children was
* ensured already.
@@ -621,8 +655,8 @@ symbol_db_model_iter_children (GtkTreeModel *tree_model,
g_return_val_if_fail (node != NULL, FALSE);
}
if (!node->children_ensured)
- symbol_db_model_node_ensure_children (SYMBOL_DB_MODEL (tree_model),
- node, FALSE, FALSE);
+ symbol_db_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model),
+ node, FALSE);
g_return_val_if_fail (node->children != NULL, FALSE);
g_return_val_if_fail (node->n_children > 0, FALSE);
@@ -776,8 +810,54 @@ symbol_db_model_tree_model_init (GtkTreeModelIface *iface)
/* SymbolDBModel implementation */
+static void
+symbol_db_model_ensure_node_children (SymbolDBModel *model,
+ SymbolDBModelNode *node,
+ gboolean emit_has_child)
+{
+ SymbolDBModelPriv *priv;
+ gint old_n_children;
+
+ g_return_if_fail (node->n_children == 0);
+ g_return_if_fail (node->children == NULL);
+ g_return_if_fail (node->children_ensured == FALSE);
+
+ priv = GET_PRIV (model);
+
+ old_n_children = node->n_children;
+
+ /* Initialize children array and count */
+ node->n_children =
+ symbol_db_model_get_n_children (model, node->level,
+ node->values);
+
+ node->children = g_new0 (SymbolDBModelNode*,
+ node->n_children);
+
+ node->children_ensured = TRUE;
+
+ /* g_message ("Ensuring node %p, emit = %d", node, emit_has_child); */
+
+ if (emit_has_child &&
+ ((old_n_children == 0 && node->n_children > 0) ||
+ (old_n_children > 0 && node->n_children == 0)))
+ {
+ GtkTreePath *path;
+ GtkTreeIter iter = {0};
+
+ iter.stamp = SYMBOL_DB_MODEL_STAMP;
+ iter.user_data = node->parent;
+ iter.user_data2 = GINT_TO_POINTER (node->offset);
+
+ path = symbol_db_model_get_path (GTK_TREE_MODEL (model), &iter);
+ gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model),
+ path, &iter);
+ gtk_tree_path_free (path);
+ }
+}
+
static gboolean
-on_symbol_db_ensure_children_idle (SymbolDBModel *model)
+on_symbol_db_ensure_node_children_idle (SymbolDBModel *model)
{
gint count;
SymbolDBModelNode *node;
@@ -788,7 +868,7 @@ on_symbol_db_ensure_children_idle (SymbolDBModel *model)
for (count = 0; count < SYMBOL_DB_MODEL_ENSURE_CHILDREN_BATCH_SIZE; count++)
{
node = g_queue_pop_head (priv->ensure_children_queue);
- symbol_db_model_node_ensure_children (model, node, FALSE, TRUE);
+ symbol_db_model_ensure_node_children (model, node, TRUE);
if (g_queue_get_length (priv->ensure_children_queue) <= 0)
{
priv->ensure_children_idle_id = 0;
@@ -799,57 +879,137 @@ on_symbol_db_ensure_children_idle (SymbolDBModel *model)
}
static void
-symbol_db_model_node_ensure_children (SymbolDBModel *model,
- SymbolDBModelNode *potential_parent,
- gboolean queue_it,
- gboolean emit_has_child)
+symbol_db_model_queue_ensure_node_children (SymbolDBModel *model,
+ SymbolDBModelNode *node)
{
SymbolDBModelPriv *priv;
- gint old_n_children;
- /* FIXME: Should we free (properly) existing children instead? */
- g_return_if_fail (potential_parent->children == NULL);
- g_return_if_fail (potential_parent->children_ensured == FALSE);
+ g_return_if_fail (node->children == NULL);
+ g_return_if_fail (node->children_ensured == FALSE);
priv = GET_PRIV (model);
- if (queue_it)
+ if (!g_queue_find (priv->ensure_children_queue, node))
{
- if (!g_queue_find (priv->ensure_children_queue, potential_parent))
- {
- g_queue_push_tail (priv->ensure_children_queue, potential_parent);
- if (!priv->ensure_children_idle_id)
- priv->ensure_children_idle_id =
- g_idle_add ((GSourceFunc)on_symbol_db_ensure_children_idle,
- model);
- }
- return;
+ g_queue_push_tail (priv->ensure_children_queue, node);
+ if (!priv->ensure_children_idle_id)
+ priv->ensure_children_idle_id =
+ g_idle_add ((GSourceFunc)on_symbol_db_ensure_node_children_idle,
+ model);
}
-
- old_n_children = potential_parent->n_children;
+}
- potential_parent->n_children =
- symbol_db_model_get_n_children (model, potential_parent->level,
- potential_parent->values);
+static void
+symbol_db_model_update_node_children (SymbolDBModel *model,
+ SymbolDBModelNode *node,
+ gboolean emit_has_child)
+{
+ SymbolDBModelPriv *priv;
+ gint old_n_children, i;
+ GList *expanded_row;
+ GList *expanded_rows = NULL;
+
+ g_return_if_fail (node->children_ensured == TRUE);
- potential_parent->children = g_new0 (SymbolDBModelNode*,
- potential_parent->n_children);
+ priv = GET_PRIV (model);
+
+ /* g_message ("Update node %p, emit = %d", node, emit_has_child); */
- potential_parent->children_ensured = TRUE;
- if (emit_has_child && potential_parent->n_children > 0)
+ /* Save the old children status */
+ old_n_children = node->n_children;
+ for (i = 0; i < node->n_children; i++)
+ {
+ SymbolDBModelNode *node =
+ symbol_db_model_node_get_child (node, i);
+ if (node && node->n_children > 0)
+ expanded_rows = g_list_prepend (expanded_rows,
+ GINT_TO_POINTER (i));
+ }
+ symbol_db_model_node_cleanse (node, TRUE);
+ symbol_db_model_ensure_node_children (model, node,
+ emit_has_child);
+
+ /* Check if nodes were removed, emit signals for them */
+ if (old_n_children > node->n_children)
{
GtkTreePath *path;
GtkTreeIter iter = {0};
+ gint i;
+ /* Set the iter to last valid child */
iter.stamp = SYMBOL_DB_MODEL_STAMP;
- iter.user_data = potential_parent->parent;
- iter.user_data2 = GINT_TO_POINTER (potential_parent->offset);
+ iter.user_data = node;
+ iter.user_data2 = GINT_TO_POINTER (node->n_children - 1);
+
+ /* Get path to it */
+ path = symbol_db_model_get_path (GTK_TREE_MODEL (model), &iter);
+ gtk_tree_path_next (path);
+ for (i = node->n_children; i < old_n_children; i++)
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ gtk_tree_path_free (path);
+ }
+
+ /* Check if nodes were added, emit signals for them */
+ if (old_n_children < node->n_children)
+ {
+ GtkTreePath *path;
+ GtkTreeIter iter = {0};
+ gint i;
+ iter.stamp = SYMBOL_DB_MODEL_STAMP;
+ iter.user_data = node;
+ iter.user_data2 = old_n_children > 0?
+ GINT_TO_POINTER (old_n_children) : GINT_TO_POINTER (0);
path = symbol_db_model_get_path (GTK_TREE_MODEL (model), &iter);
- gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model),
- path, &iter);
+ if (path == NULL)
+ path = gtk_tree_path_new_first ();
+ for (i = old_n_children; i < node->n_children; i++)
+ {
+ iter.user_data2 = GINT_TO_POINTER (i);
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_next (path);
+ }
+ gtk_tree_path_free (path);
+ }
+
+ /* Emit update signals for rest of the nodes */
+ if (MIN(old_n_children, node->n_children) > 0)
+ {
+ GtkTreePath *path;
+ GtkTreeIter iter = {0};
+ gint i;
+
+ iter.stamp = SYMBOL_DB_MODEL_STAMP;
+ iter.user_data = node;
+ path = gtk_tree_path_new_first ();
+ for (i = 0; i < MIN(old_n_children, node->n_children); i++)
+ {
+ iter.user_data2 = GINT_TO_POINTER (i);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_next (path);
+ }
gtk_tree_path_free (path);
}
- /* g_warn_if_fail (potential_parent->n_children == old_n_children); */
+
+ /* Notify children status change for expanded nodes */
+ for (expanded_row = expanded_rows; expanded_row;
+ expanded_row = expanded_row->next)
+ {
+ /* Only emit of valid rows, the rest are dead anyways */
+ if (GPOINTER_TO_INT (expanded_row->data) < node->n_children)
+ {
+ GtkTreePath *path;
+ GtkTreeIter iter = {0};
+
+ iter.stamp = SYMBOL_DB_MODEL_STAMP;
+ iter.user_data = node;
+ iter.user_data2 = expanded_row->data;
+ path = symbol_db_model_get_path (GTK_TREE_MODEL (model), &iter);
+ gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model),
+ path, &iter);
+ gtk_tree_path_free (path);
+ }
+ }
+ g_list_free (expanded_rows);
}
static gboolean
@@ -1068,6 +1228,8 @@ symbol_db_model_set_columns (SymbolDBModel *model, gint n_columns,
SymbolDBModelPriv *priv;
g_return_if_fail (n_columns > 0);
+ g_return_if_fail (SYMBOL_DB_IS_MODEL (model));
+
priv = GET_PRIV (model);
g_return_if_fail (priv->n_columns <= 0);
@@ -1120,3 +1282,17 @@ symbol_db_model_newv (gint n_columns, GType *types, gint *query_columns)
types, query_columns);
return model;
}
+
+void
+symbol_db_model_update (SymbolDBModel *model)
+{
+ SymbolDBModelPriv *priv;
+
+ g_return_if_fail (SYMBOL_DB_IS_MODEL (model));
+
+ /* g_message ("Symbol DB Model reset called"); */
+ priv = GET_PRIV (model);
+
+ if (priv->root->children_ensured)
+ symbol_db_model_update_node_children (model, priv->root, FALSE);
+}
diff --git a/plugins/symbol-db/symbol-db-model.h b/plugins/symbol-db/symbol-db-model.h
index de6a8e7..6fbb0e6 100644
--- a/plugins/symbol-db/symbol-db-model.h
+++ b/plugins/symbol-db/symbol-db-model.h
@@ -84,6 +84,8 @@ GtkTreeModel* symbol_db_model_newv (gint n_columns, GType *types,
void symbol_db_model_set_columns (SymbolDBModel *model, gint n_columns,
GType *types, gint *data_cols);
+void symbol_db_model_update (SymbolDBModel *model);
+
G_END_DECLS
#endif /* _SYMBOL_DB_MODEL_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]