Initial German translation of the build tutorial
[anjuta.git] / plugins / symbol-db / symbol-db-model.c
blob164e9ff691e9dd40a9b5ad1053a6ae78f3585f81
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * symbol-db-model.c
4 * Copyright (C) Naba Kumar 2010 <naba@gnome.org>
5 *
6 * anjuta is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * anjuta is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <gdk-pixbuf/gdk-pixbuf.h>
21 #include <libgda/libgda.h>
22 #include "symbol-db-marshal.h"
23 #include "symbol-db-model.h"
25 #define SYMBOL_DB_MODEL_STAMP 5364558
27 /* Constants */
29 #define SYMBOL_DB_MODEL_PAGE_SIZE 50
30 #define SYMBOL_DB_MODEL_ENSURE_CHILDREN_BATCH_SIZE 10
32 typedef struct _SymbolDBModelPage SymbolDBModelPage;
33 struct _SymbolDBModelPage
35 gint begin_offset, end_offset;
36 SymbolDBModelPage *prev;
37 SymbolDBModelPage *next;
40 typedef struct _SymbolDBModelNode SymbolDBModelNode;
41 struct _SymbolDBModelNode {
43 gint n_columns;
45 /* Column values of the node. This is an array of GValues of length
46 * n_column. and holds the values in order of columns given at
47 * object initialized.
49 GValue *values;
51 /* List of currently active (cached) pages */
52 SymbolDBModelPage *pages;
54 /* Data structure */
55 gint level;
56 SymbolDBModelNode *parent;
57 gint offset;
59 /* Children states */
60 gint children_ref_count;
61 gboolean has_child_ensured;
62 gboolean has_child;
63 gboolean children_ensured;
64 guint n_children;
65 SymbolDBModelNode **children;
68 struct _SymbolDBModelPriv {
69 /* Keeps track of model freeze count. When the model is frozen, it
70 * avoid retreiving data from backend. It does not freeze the frontend
71 * view at all and instead use empty data for the duration of freeze.
73 gint freeze_count;
75 gint n_columns; /* Number of columns in the model */
76 GType *column_types; /* Type of each column in the model */
77 gint *query_columns; /* Corresponding GdaDataModel column */
79 SymbolDBModelNode *root;
82 enum {
83 SIGNAL_GET_HAS_CHILD,
84 SIGNAL_GET_N_CHILDREN,
85 SIGNAL_GET_CHILDREN,
86 LAST_SIGNAL
89 static guint symbol_db_model_signals[LAST_SIGNAL] = { 0 };
91 /* Declarations */
93 static void sdb_model_node_free (SymbolDBModelNode *node, gboolean force);
95 static void sdb_model_tree_model_init (GtkTreeModelIface *iface);
97 static gboolean sdb_model_get_query_value_at (SymbolDBModel *model,
98 GdaDataModel *data_model,
99 gint position, gint column,
100 GValue *value);
102 static gboolean sdb_model_get_query_value (SymbolDBModel *model,
103 GdaDataModel *data_model,
104 GdaDataModelIter *iter,
105 gint column,
106 GValue *value);
108 static gboolean sdb_model_get_has_child (SymbolDBModel *model,
109 SymbolDBModelNode *node);
111 static gint sdb_model_get_n_children (SymbolDBModel *model,
112 gint tree_level,
113 GValue column_values[]);
115 static GdaDataModel* sdb_model_get_children (SymbolDBModel *model,
116 gint tree_level,
117 GValue column_values[],
118 gint offset, gint limit);
120 static void sdb_model_ensure_node_children (SymbolDBModel *model,
121 SymbolDBModelNode *parent,
122 gboolean emit_has_child,
123 gboolean fake_child);
125 /* Class definition */
126 G_DEFINE_TYPE_WITH_CODE (SymbolDBModel, sdb_model, G_TYPE_OBJECT,
127 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
128 sdb_model_tree_model_init))
129 /* Node */
132 * sdb_model_node_get_child:
133 * @node: The node whose child has to be fetched.
134 * @child_offset: Offset of the child of this node.
136 * Fetches the content of the @child_offset child of the @node. The return
137 * value can be NULL if the child hasn't been yet cached from backend. Only
138 * when the child node is in cache does this function return a child. If you
139 * you want to fetch the child from backend, call sdb_model_page_fault().
141 * Returns: The child node, or NULL if the child hasn't yet been cached.
143 static GNUC_INLINE SymbolDBModelNode*
144 sdb_model_node_get_child (SymbolDBModelNode *node, gint child_offset)
146 g_return_val_if_fail (node != NULL, NULL);
147 g_return_val_if_fail (child_offset >= 0 && child_offset < node->n_children, NULL);
148 if(node->children)
149 return node->children[child_offset];
150 return NULL;
154 * sdb_model_node_set_child:
155 * @node: The node whose child has to be set.
156 * @child_offset: Offset of the child to set.
157 * @val: Child node to set.
159 * Sets the child of @node at @child_offset to @val.
161 static void
162 sdb_model_node_set_child (SymbolDBModelNode *node, gint child_offset,
163 SymbolDBModelNode *val)
165 g_return_if_fail (node != NULL);
166 g_return_if_fail (node->children_ensured == TRUE);
167 g_return_if_fail (child_offset >= 0 && child_offset < node->n_children);
169 /* If children nodes array hasn't been allocated, now is the time */
170 if (!node->children)
171 node->children = g_new0 (SymbolDBModelNode*, node->n_children);
172 if (val)
174 g_warn_if_fail (node->children[child_offset] == NULL);
176 node->children[child_offset] = val;
180 * sdb_model_node_cleanse:
181 * @node: The node to cleanse
182 * @force: If forcefuly cleansed disregarding references to children
184 * It destroys all children of the node and resets the node to not
185 * children-ensured state. Any cache for children nodes is also destroyed.
186 * The node will be in children unensured state, which means the status
187 * of it's children would be unknown. Cleansing only happens if there are
188 * no referenced children nodes, unless it is forced with @force = TRUE.
190 * Returns: TRUE if successfully cleansed, otherwise FALSE.
192 static gboolean
193 sdb_model_node_cleanse (SymbolDBModelNode *node, gboolean force)
195 SymbolDBModelPage *page, *next;
196 gint i;
198 g_return_val_if_fail (node != NULL, FALSE);
200 /* Can not cleanse a node if there are refed children */
201 if (!force)
203 g_return_val_if_fail (node->children_ref_count == 0, FALSE);
206 if (node->children)
208 /* There should be no children with any ref. Children with ref count 0
209 * are floating children and can be destroyed.
211 for (i = 0; i < node->n_children; i++)
213 SymbolDBModelNode *child = sdb_model_node_get_child (node, i);
214 if (child)
216 if (!force)
218 /* Assert on nodes with ref count > 0 */
219 g_warn_if_fail (child->children_ref_count == 0);
221 sdb_model_node_free (child, force);
222 sdb_model_node_set_child (node, i, NULL);
227 /* Reset cached pages */
228 page = node->pages;
229 while (page)
231 next = page->next;
232 g_slice_free (SymbolDBModelPage, page);
233 page = next;
235 node->pages = NULL;
236 node->children_ensured = FALSE;
237 node->n_children = 0;
239 /* Destroy arrays */
240 g_free (node->children);
241 node->children = NULL;
243 return TRUE;
247 * sdb_model_node_free:
248 * @node: The node to free.
249 * @force: Force the free despite any referenced children
251 * Frees the node if there is no referenced children, unless @force is TRUE
252 * in which case it is freed anyways. All children recursively are also
253 * destroyed.
255 static void
256 sdb_model_node_free (SymbolDBModelNode *node, gboolean force)
258 if (!sdb_model_node_cleanse (node, force))
259 return;
261 g_slice_free1 (sizeof(GValue) * node->n_columns, node->values);
262 g_slice_free (SymbolDBModelNode, node);
266 * sdb_model_node_remove_page:
267 * @node: The node with the page
268 * @page: The page to remove
270 * Removes the cache @page from the @node. The associated nodes are all
271 * destroyed and set to NULL. They could be re-fetched later if needed.
273 static void
274 sdb_model_node_remove_page (SymbolDBModelNode *node,
275 SymbolDBModelPage *page)
277 if (page->prev)
278 page->prev->next = page->next;
279 else
280 node->pages = page->next;
282 if (page->next)
283 page->next->prev = page->prev;
285 /* FIXME: Destroy the page */
289 * sdb_model_node_insert_page:
290 * @node: The node for which the page is inserted
291 * @page: The page being inserted
292 * @after: The page after which @page is inserted
294 * Inserts the @page after @after page. The page should have been already
295 * fetched and their nodes (children of @node) should have been already
296 * created.
298 static void
299 sdb_model_node_insert_page (SymbolDBModelNode *node,
300 SymbolDBModelPage *page,
301 SymbolDBModelPage *after)
304 /* Insert the new page after "after" page */
305 if (after)
307 page->next = after->next;
308 after->next = page;
310 else /* Insert at head */
312 page->next = node->pages;
313 node->pages = page;
318 * symbold_db_model_node_find_child_page:
319 * @node: The node
320 * @child_offset: Offset of the child node.
321 * @prev_page: A pointer to page to return previous cache page found
323 * Find the cache page associated with child node of @node at @child_offset.
324 * If the page is found, it returns the page, otherwise NULL is returned. Also,
325 * if the page is found, prev_page pointer is set to the previous page to
326 * the one found (NULL if it's the first page in the list).
328 * Returns: The page associated with the child node, or NULL if not found.
330 static SymbolDBModelPage*
331 sdb_model_node_find_child_page (SymbolDBModelNode *node,
332 gint child_offset,
333 SymbolDBModelPage **prev_page)
335 SymbolDBModelPage *page;
337 page = node->pages;
339 *prev_page = NULL;
341 /* Find the page which holds result for given child_offset */
342 while (page)
344 if (child_offset >= page->begin_offset &&
345 child_offset < page->end_offset)
347 /* child_offset has associated page */
348 return page;
350 if (child_offset < page->begin_offset)
352 /* Insert point is here */
353 break;
355 *prev_page = page;
356 page = page->next;
358 return NULL;
362 * sdb_model_node_ref_child:
363 * @node: The node whose child is being referenced.
365 * References a child of @node and references all its parents recursively.
366 * A referenced node essentially means someone is holding a reference to it
367 * outside the model and we are supposed track its position. Currently, we
368 * don't track reference of nodes themselves but instead maitain their ref
369 * counts in parent @node. Ref counting is currently unused, so there is no
370 * practical thing happening using it at the moment.
372 static void
373 sdb_model_node_ref_child (SymbolDBModelNode *node)
375 g_return_if_fail (node != NULL);
377 node->children_ref_count++;
379 if (node->parent)
381 /* Increate associated ref count on parent */
382 sdb_model_node_ref_child (node->parent);
387 * sdb_model_node_unref_child:
388 * @node: The node whose child is being unrefed
389 * @child_offset: Offset of the child being unrefed
391 * Unrefs the child at @child_offset in @node. Also, unrefs its parents
392 * recursively. currently ref/unref is not used, see
393 * sdb_model_node_ref_child() for more details.
395 static void
396 sdb_model_node_unref_child (SymbolDBModelNode *node, gint child_offset)
398 g_return_if_fail (node != NULL);
399 g_return_if_fail (node->children_ref_count > 0);
401 node->children_ref_count--;
403 /* If ref count reaches 0, cleanse this node */
404 if (node->children_ref_count <= 0)
406 sdb_model_node_cleanse (node, FALSE);
409 if (node->parent)
411 /* Reduce ref count on parent as well */
412 sdb_model_node_unref_child (node->parent, node->offset);
417 * sdb_model_node_new:
418 * @model: The model for which the node is being created
419 * @parent: The parent node
420 * @child_offset: Offset of this node as child of @parent
421 * @data_model: The data model from which content of the node is fetched
422 * @data_iter: Iter for @data_model where the content of this node is found
424 * This creates a new node for @model as a child of @parent at @child_offset
425 * and initilizes the columns content from @data_model at @data_iter.
427 * Returns: The newly created node.
429 static SymbolDBModelNode *
430 sdb_model_node_new (SymbolDBModel *model, SymbolDBModelNode *parent,
431 gint child_offset, GdaDataModel *data_model,
432 GdaDataModelIter *data_iter)
434 gint i;
435 SymbolDBModelPriv *priv = model->priv;
436 SymbolDBModelNode* node = g_slice_new0 (SymbolDBModelNode);
437 node->n_columns = priv->n_columns;
438 node->values = g_slice_alloc0 (sizeof (GValue) * priv->n_columns);
439 for (i = 0; i < priv->n_columns; i++)
441 g_value_init (&(node->values[i]), priv->column_types[i]);
442 sdb_model_get_query_value (model,
443 data_model,
444 data_iter,
445 i, &(node->values[i]));
447 node->offset = child_offset;
448 node->parent = parent;
449 node->level = parent->level + 1;
450 return node;
453 /* SymbolDBModel implementation */
456 * sdb_model_iter_is_valid:
457 * @model: The tree model
458 * @iter: An iter for the model
460 * Checks if the iterator is valid for the model.
462 * Returns: TRUE if valid, FALSE if not
464 static gboolean
465 sdb_model_iter_is_valid (GtkTreeModel *model, GtkTreeIter *iter)
467 SymbolDBModelNode *parent_node;
468 gint offset;
470 g_return_val_if_fail (SYMBOL_DB_IS_MODEL (model), FALSE);
471 g_return_val_if_fail (iter != NULL, FALSE);
472 g_return_val_if_fail (iter->stamp == SYMBOL_DB_MODEL_STAMP, FALSE);
474 parent_node = (SymbolDBModelNode*) iter->user_data;
475 offset = GPOINTER_TO_INT (iter->user_data2);
477 g_return_val_if_fail (parent_node != NULL, FALSE);
478 g_return_val_if_fail (offset >= 0 && offset < parent_node->n_children,
479 FALSE);
480 return TRUE;
484 * sdb_model_page_fault:
485 * @parent_node: The node which needs children data fetched
486 * @child_offset: Offset of the child where page fault occured
488 * Page fault should happen on a child which is not yet available in cache
489 * and needs to be fetched from backend database. Fetch happens in a page
490 * size of SYMBOL_DB_MODEL_PAGE_SIZE chunks before and after the requested
491 * child node. Also, the page will adjust the boundry to any preceeding or
492 * or following pages so that they don't overlap.
494 * Returns: The newly fetched page
496 static SymbolDBModelPage*
497 sdb_model_page_fault (SymbolDBModel *model,
498 SymbolDBModelNode *parent_node,
499 gint child_offset)
501 SymbolDBModelPriv *priv;
502 SymbolDBModelPage *page, *prev_page, *page_found;
503 gint i;
504 GdaDataModelIter *data_iter;
505 GdaDataModel *data_model = NULL;
507 /* Insert after prev_page */
508 page_found = sdb_model_node_find_child_page (parent_node,
509 child_offset,
510 &prev_page);
512 if (page_found)
513 return page_found;
515 /* If model is frozen, can't fetch data from backend */
516 priv = model->priv;
517 if (priv->freeze_count > 0)
518 return NULL;
520 /* New page to cover current child_offset */
521 page = g_slice_new0 (SymbolDBModelPage);
523 /* Define page range */
524 page->begin_offset = child_offset - SYMBOL_DB_MODEL_PAGE_SIZE;
525 page->end_offset = child_offset + SYMBOL_DB_MODEL_PAGE_SIZE;
527 sdb_model_node_insert_page (parent_node, page, prev_page);
529 /* Adjust boundries not to overlap with preceeding or following page */
530 if (prev_page && prev_page->end_offset > page->begin_offset)
531 page->begin_offset = prev_page->end_offset;
533 if (page->next && page->end_offset >= page->next->begin_offset)
534 page->end_offset = page->next->begin_offset;
536 /* Adjust boundries not to preceed 0 index */
537 if (page->begin_offset < 0)
538 page->begin_offset = 0;
540 /* Load a page from database */
541 data_model = sdb_model_get_children (model, parent_node->level,
542 parent_node->values,
543 page->begin_offset,
544 page->end_offset - page->begin_offset);
546 /* Fill up the page */
547 data_iter = gda_data_model_create_iter (data_model);
548 if (gda_data_model_iter_move_to_row (data_iter, 0))
550 for (i = page->begin_offset; i < page->end_offset; i++)
552 if (i >= parent_node->n_children)
554 /* FIXME: There are more rows in DB. Extend node */
555 break;
557 SymbolDBModelNode *node =
558 sdb_model_node_new (model, parent_node, i,
559 data_model, data_iter);
560 g_assert (sdb_model_node_get_child (parent_node, i) == NULL);
561 sdb_model_node_set_child (parent_node, i, node);
562 if (!gda_data_model_iter_move_next (data_iter))
564 if (i < (page->end_offset - 1))
566 /* FIXME: There are fewer rows in DB. Shrink node */
568 break;
573 if (data_iter)
574 g_object_unref (data_iter);
575 if (data_model)
576 g_object_unref (data_model);
577 return page;
580 /* GtkTreeModel implementation */
582 static GtkTreeModelFlags
583 sdb_model_get_flags (GtkTreeModel *tree_model)
585 return 0;
588 static GType
589 sdb_model_get_column_type (GtkTreeModel *tree_model,
590 gint index)
592 SymbolDBModelPriv *priv = SYMBOL_DB_MODEL (tree_model)->priv;
593 g_return_val_if_fail (index < priv->n_columns, G_TYPE_INVALID);
594 return priv->column_types [index];
597 static gint
598 sdb_model_get_n_columns (GtkTreeModel *tree_model)
600 SymbolDBModelPriv *priv;
601 priv = SYMBOL_DB_MODEL (tree_model)->priv;
602 return priv->n_columns;
605 static gboolean
606 sdb_model_get_iter (GtkTreeModel *tree_model,
607 GtkTreeIter *iter,
608 GtkTreePath *path)
610 gint i;
611 SymbolDBModelNode *node, *parent_node;
612 gint depth, *indx;
613 SymbolDBModelPriv *priv;
615 g_return_val_if_fail (SYMBOL_DB_IS_MODEL(tree_model), FALSE);
616 g_return_val_if_fail (iter != NULL, FALSE);
617 g_return_val_if_fail (path != NULL, FALSE);
619 gchar *path_str = gtk_tree_path_to_string (path);
620 g_free (path_str);
622 depth = gtk_tree_path_get_depth (path);
623 g_return_val_if_fail (depth > 0, FALSE);
625 priv = SYMBOL_DB_MODEL (tree_model)->priv;
626 indx = gtk_tree_path_get_indices (path);
628 parent_node = NULL;
629 node = priv->root;
630 for (i = 0; i < depth; i++)
632 parent_node = node;
633 if (!node->children_ensured)
634 sdb_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model),
635 node, FALSE, FALSE);
636 if (node->n_children <= 0)
638 /* No child available. View thinks there is child.
639 * It's an inconsistent state. Do something fancy to fix it.
641 symbol_db_model_update (SYMBOL_DB_MODEL (tree_model)); /* Untested path */
642 break;
644 if (indx[i] >= node->n_children)
646 g_warning ("Invalid path to iter conversion; no children list found at depth %d", i);
647 break;
649 node = sdb_model_node_get_child (node, indx[i]);
651 if (i != depth)
653 return FALSE;
655 iter->stamp = SYMBOL_DB_MODEL_STAMP;
656 iter->user_data = parent_node;
657 iter->user_data2 = GINT_TO_POINTER (indx[i-1]);
659 g_assert (sdb_model_iter_is_valid (tree_model, iter));
661 return TRUE;
664 static GtkTreePath*
665 sdb_model_get_path (GtkTreeModel *tree_model,
666 GtkTreeIter *iter)
668 SymbolDBModelNode *node;
669 GtkTreePath* path;
670 gint offset;
672 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model, iter),
673 NULL);
675 path = gtk_tree_path_new ();
677 node = (SymbolDBModelNode*)iter->user_data;
678 offset = GPOINTER_TO_INT (iter->user_data2);
679 do {
680 gtk_tree_path_prepend_index (path, offset);
681 if (node)
682 offset = node->offset;
683 node = node->parent;
684 } while (node);
685 return path;
688 static void
689 sdb_model_get_value (GtkTreeModel *tree_model,
690 GtkTreeIter *iter, gint column,
691 GValue *value)
693 SymbolDBModelPriv *priv;
694 SymbolDBModelNode *parent_node, *node;
695 gint offset;
697 g_return_if_fail (sdb_model_iter_is_valid (tree_model, iter));
699 priv = SYMBOL_DB_MODEL (tree_model)->priv;
701 g_return_if_fail (column >= 0);
702 g_return_if_fail (column < priv->n_columns);
704 parent_node = (SymbolDBModelNode*) iter->user_data;
705 offset = GPOINTER_TO_INT (iter->user_data2);
707 if (sdb_model_node_get_child (parent_node, offset) == NULL)
708 sdb_model_page_fault (SYMBOL_DB_MODEL (tree_model),
709 parent_node, offset);
710 node = sdb_model_node_get_child (parent_node, offset);
711 g_value_init (value, priv->column_types[column]);
713 if (node == NULL)
714 return;
716 /* View accessed the node, so update any pending has-child status */
717 if (!node->has_child_ensured)
719 sdb_model_get_has_child (SYMBOL_DB_MODEL (tree_model), node);
721 g_value_copy (&(node->values[column]), value);
724 static gboolean
725 sdb_model_iter_next (GtkTreeModel *tree_model,
726 GtkTreeIter *iter)
728 SymbolDBModelNode *node;
729 gint offset;
731 g_return_val_if_fail (iter != NULL, FALSE);
732 g_return_val_if_fail (iter->stamp == SYMBOL_DB_MODEL_STAMP, FALSE);
733 g_return_val_if_fail (iter->user_data != NULL, FALSE);
736 node = (SymbolDBModelNode*)(iter->user_data);
737 offset = GPOINTER_TO_INT (iter->user_data2);
738 offset++;
740 if (offset >= node->n_children)
741 return FALSE;
742 iter->user_data2 = GINT_TO_POINTER (offset);
744 g_assert (sdb_model_iter_is_valid (tree_model, iter));
746 return TRUE;
749 static gboolean
750 sdb_model_iter_children (GtkTreeModel *tree_model,
751 GtkTreeIter *iter,
752 GtkTreeIter *parent)
754 SymbolDBModelNode *node, *parent_node;
755 SymbolDBModelPriv *priv;
757 if (parent)
759 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model, parent),
760 FALSE);
763 g_return_val_if_fail (SYMBOL_DB_IS_MODEL(tree_model), FALSE);
764 g_return_val_if_fail (iter != NULL, FALSE);
766 priv = SYMBOL_DB_MODEL (tree_model)->priv;
767 if (parent == NULL)
769 node = priv->root;
771 else
773 gint offset;
774 parent_node = (SymbolDBModelNode*) parent->user_data;
775 offset = GPOINTER_TO_INT (parent->user_data2);
776 node = sdb_model_node_get_child (parent_node, offset);
777 if (!node)
779 sdb_model_page_fault (SYMBOL_DB_MODEL (tree_model),
780 parent_node, offset);
781 node = sdb_model_node_get_child (parent_node, offset);
783 g_return_val_if_fail (node != NULL, FALSE);
786 /* Apparently view can call this funtion without testing has_child first */
787 if (!sdb_model_get_has_child (SYMBOL_DB_MODEL(tree_model), node))
788 return FALSE;
790 if (!node->children_ensured)
791 sdb_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model),
792 node, FALSE, TRUE);
794 iter->user_data = node;
795 iter->user_data2 = GINT_TO_POINTER (0);
796 iter->stamp = SYMBOL_DB_MODEL_STAMP;
798 /* View trying to access children of childless node seems typical */
799 if (node->n_children <= 0)
800 return FALSE;
802 g_assert (sdb_model_iter_is_valid (tree_model, iter));
804 return TRUE;
807 static gboolean
808 sdb_model_iter_has_child (GtkTreeModel *tree_model,
809 GtkTreeIter *iter)
811 gint offset;
812 SymbolDBModelNode *node, *parent_node;
814 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model, iter),
815 FALSE);
817 parent_node = (SymbolDBModelNode*) iter->user_data;
818 offset = GPOINTER_TO_INT (iter->user_data2);
820 node = sdb_model_node_get_child (parent_node, offset);
822 /* If node is not loaded, has-child is defered. See get_value() */
823 if (node == NULL)
824 return FALSE;
825 return sdb_model_get_has_child (SYMBOL_DB_MODEL (tree_model), node);
828 static gint
829 sdb_model_iter_n_children (GtkTreeModel *tree_model,
830 GtkTreeIter *iter)
832 gint offset;
833 SymbolDBModelPriv *priv;
834 SymbolDBModelNode *node, *parent_node;
836 g_return_val_if_fail (SYMBOL_DB_IS_MODEL (tree_model), 0);
837 priv = SYMBOL_DB_MODEL (tree_model)->priv;
839 if (iter)
841 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model, iter), 0);
844 if (iter == NULL)
845 node = priv->root;
846 else
848 parent_node = (SymbolDBModelNode*) iter->user_data;
849 offset = GPOINTER_TO_INT (iter->user_data2);
850 node = sdb_model_node_get_child (parent_node, offset);
853 if (node == NULL)
854 return 0;
855 if (!node->children_ensured)
856 sdb_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model),
857 node, FALSE, FALSE);
858 return node->n_children;
861 static gboolean
862 sdb_model_iter_nth_child (GtkTreeModel *tree_model,
863 GtkTreeIter *iter,
864 GtkTreeIter *parent,
865 gint n)
867 SymbolDBModelNode *node;
869 g_return_val_if_fail (SYMBOL_DB_IS_MODEL(tree_model), FALSE);
870 g_return_val_if_fail (iter != NULL, FALSE);
871 g_return_val_if_fail (n >= 0, FALSE);
873 if (!sdb_model_iter_children (tree_model, iter, parent))
874 return FALSE;
876 node = (SymbolDBModelNode*) (iter->user_data);
878 g_return_val_if_fail (n < node->n_children, FALSE);
880 iter->user_data2 = GINT_TO_POINTER (n);
882 g_assert (sdb_model_iter_is_valid (tree_model, iter));
884 return TRUE;
887 static gboolean
888 sdb_model_iter_parent (GtkTreeModel *tree_model,
889 GtkTreeIter *iter,
890 GtkTreeIter *child)
892 SymbolDBModelNode *parent_node;
894 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model, child),
895 FALSE);
897 g_return_val_if_fail (iter != NULL, FALSE);
899 parent_node = (SymbolDBModelNode*) child->user_data;
900 g_return_val_if_fail (parent_node->parent != NULL, FALSE);
902 iter->user_data = parent_node->parent;
903 iter->user_data2 = GINT_TO_POINTER (parent_node->offset);
904 iter->stamp = SYMBOL_DB_MODEL_STAMP;
906 g_assert (sdb_model_iter_is_valid (tree_model, iter));
908 return TRUE;
911 static void
912 sdb_model_iter_ref (GtkTreeModel *tree_model, GtkTreeIter *iter)
914 SymbolDBModelNode *parent_node;
916 g_return_if_fail (sdb_model_iter_is_valid (tree_model, iter));
918 parent_node = (SymbolDBModelNode*) iter->user_data;
920 sdb_model_node_ref_child (parent_node);
923 static void
924 sdb_model_iter_unref (GtkTreeModel *tree_model, GtkTreeIter *iter)
926 SymbolDBModelNode *parent_node;
927 gint child_offset;
929 g_return_if_fail (sdb_model_iter_is_valid (tree_model, iter));
931 parent_node = (SymbolDBModelNode*) iter->user_data;
932 child_offset = GPOINTER_TO_INT (iter->user_data2);
934 sdb_model_node_unref_child (parent_node, child_offset);
937 static void
938 sdb_model_tree_model_init (GtkTreeModelIface *iface)
940 iface->get_flags = sdb_model_get_flags;
941 iface->get_n_columns = sdb_model_get_n_columns;
942 iface->get_column_type = sdb_model_get_column_type;
943 iface->get_iter = sdb_model_get_iter;
944 iface->get_path = sdb_model_get_path;
945 iface->get_value = sdb_model_get_value;
946 iface->iter_next = sdb_model_iter_next;
947 iface->iter_children = sdb_model_iter_children;
948 iface->iter_has_child = sdb_model_iter_has_child;
949 iface->iter_n_children = sdb_model_iter_n_children;
950 iface->iter_nth_child = sdb_model_iter_nth_child;
951 iface->iter_parent = sdb_model_iter_parent;
952 iface->ref_node = sdb_model_iter_ref;
953 iface->unref_node = sdb_model_iter_unref;
956 /* SymbolDBModel implementation */
958 static void
959 sdb_model_emit_has_child (SymbolDBModel *model, SymbolDBModelNode *node)
961 GtkTreePath *path;
962 GtkTreeIter iter = {0};
964 iter.stamp = SYMBOL_DB_MODEL_STAMP;
965 iter.user_data = node->parent;
966 iter.user_data2 = GINT_TO_POINTER (node->offset);
968 path = sdb_model_get_path (GTK_TREE_MODEL (model), &iter);
969 gtk_tree_model_row_has_child_toggled (GTK_TREE_MODEL (model),
970 path, &iter);
971 gtk_tree_path_free (path);
975 * sdb_model_ensure_node_children:
976 * @model: The tree model
977 * @node: The node for which the children are being ensured
978 * @emit_has_child: Should it emit children status change signal to model
980 * When a node is initially created, there is no status of its children. This
981 * function determines the number of children of the node and initializes
982 * children array. They children node themselves are not initialized yet.
984 static void
985 sdb_model_ensure_node_children (SymbolDBModel *model,
986 SymbolDBModelNode *node,
987 gboolean emit_has_child,
988 gboolean fake_child)
990 SymbolDBModelPriv *priv;
991 gboolean old_has_child;
993 g_return_if_fail (node->n_children == 0);
994 g_return_if_fail (node->children == NULL);
995 g_return_if_fail (node->children_ensured == FALSE);
997 priv = model->priv;
999 /* Can not ensure if model is frozen */
1000 if (priv->freeze_count > 0)
1001 return;
1003 /* Initialize children array and count */
1004 old_has_child = node->has_child;
1005 node->n_children =
1006 sdb_model_get_n_children (model, node->level,
1007 node->values);
1008 node->has_child = (node->n_children > 0);
1009 node->children_ensured = TRUE;
1010 node->has_child_ensured = TRUE;
1012 if (fake_child && old_has_child && !node->has_child)
1014 node->n_children = 1;
1015 node->has_child = TRUE;
1016 return;
1019 if ((old_has_child != node->has_child) && node->parent)
1021 sdb_model_emit_has_child (model, node);
1026 * sdb_model_update_node_children:
1027 * @model: The model being updated
1028 * @node: The node being updated
1029 * @emit_has_child: Whether to emit has-child-changed signal
1031 * Updates the children of @node. All existing children are destroyed and
1032 * new ones fetched. Update signals are also emited for the views to know
1033 * about updates.
1035 static void
1036 sdb_model_update_node_children (SymbolDBModel *model,
1037 SymbolDBModelNode *node,
1038 gboolean emit_has_child)
1040 /* Delete all nodes */
1041 if (node->n_children > 0)
1043 GtkTreePath *path;
1044 GtkTreeIter iter = {0};
1045 gint i;
1047 /* Set the iter to first child */
1048 iter.stamp = SYMBOL_DB_MODEL_STAMP;
1049 iter.user_data = node;
1050 iter.user_data2 = GINT_TO_POINTER (0);
1052 /* Get path to it */
1053 path = sdb_model_get_path (GTK_TREE_MODEL (model), &iter);
1055 /* Delete all children */
1056 for (i = 0; i < node->n_children; i++)
1057 gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
1058 gtk_tree_path_free (path);
1061 sdb_model_node_cleanse (node, TRUE);
1062 sdb_model_ensure_node_children (model, node, emit_has_child, FALSE);
1064 /* Add all new nodes */
1065 if (node->n_children > 0)
1067 GtkTreePath *path;
1068 GtkTreeIter iter = {0};
1069 gint i;
1071 iter.stamp = SYMBOL_DB_MODEL_STAMP;
1072 iter.user_data = node;
1073 iter.user_data2 = 0;
1074 path = sdb_model_get_path (GTK_TREE_MODEL (model), &iter);
1075 if (path == NULL)
1076 path = gtk_tree_path_new_first ();
1077 for (i = 0; i < node->n_children; i++)
1079 iter.user_data2 = GINT_TO_POINTER (i);
1080 gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
1081 gtk_tree_path_next (path);
1083 gtk_tree_path_free (path);
1088 * sdb_model_get_query_value_real:
1089 * @model: The model
1090 * @data_model: The backend data model
1091 * @iter: The tree model iterator
1092 * @column: The model column
1093 * @value: Pointer to retun value
1095 * Retrieves model data at row @iter and column @column from backend data
1096 * model @data_model. This function retrieves the column data from its map
1097 * given at model initialization. It can be overriden in derived classes to
1098 * retrive custom column values (based on given data model at the given iter).
1100 * Returns: TRUE if @value set successfully, else FALSE.
1102 static gboolean
1103 sdb_model_get_query_value_real (SymbolDBModel *model,
1104 GdaDataModel *data_model,
1105 GdaDataModelIter *iter, gint column,
1106 GValue *value)
1108 const GValue *ret;
1109 SymbolDBModelPriv *priv = model->priv;
1110 gint query_column = priv->query_columns[column];
1112 if (query_column < 0)
1113 return FALSE;
1115 ret = gda_data_model_iter_get_value_at (iter, query_column);
1116 if (!ret || !G_IS_VALUE (ret))
1117 return FALSE;
1119 g_value_copy (ret, value);
1120 return TRUE;
1123 static gboolean
1124 sdb_model_get_query_value (SymbolDBModel *model,
1125 GdaDataModel *data_model,
1126 GdaDataModelIter *iter, gint column,
1127 GValue *value)
1129 return SYMBOL_DB_MODEL_GET_CLASS(model)->get_query_value(model, data_model,
1130 iter, column,
1131 value);
1135 * sdb_model_get_query_value_at_real:
1136 * @model: The model
1137 * @data_model: The backend data model where value is derived.
1138 * @position: Position of the row.
1139 * @column: The column being retrieved.
1140 * @value: Return value
1142 * Same as sdb_model_get_query_value_real() except it uses integer index
1143 * for row positioning instead of an iter. It will be used when some backend
1144 * data model does not support iter.
1146 * Returns: TRUE if @value set successfully, else FALSE.
1148 static gboolean
1149 sdb_model_get_query_value_at_real (SymbolDBModel *model,
1150 GdaDataModel *data_model,
1151 gint position, gint column,
1152 GValue *value)
1154 const GValue *ret;
1155 SymbolDBModelPriv *priv = model->priv;
1156 gint query_column = priv->query_columns[column];
1157 g_value_init (value, priv->column_types[column]);
1159 if (query_column < 0)
1160 return FALSE;
1162 ret = gda_data_model_get_value_at (data_model, query_column, position,
1163 NULL);
1164 if (!ret || !G_IS_VALUE (ret))
1165 return FALSE;
1167 g_value_copy (ret, value);
1168 return TRUE;
1171 static gboolean
1172 sdb_model_get_query_value_at (SymbolDBModel *model,
1173 GdaDataModel *data_model,
1174 gint position, gint column, GValue *value)
1176 return SYMBOL_DB_MODEL_GET_CLASS(model)->get_query_value_at (model,
1177 data_model,
1178 position,
1179 column,
1180 value);
1184 * sdb_model_get_has_child_real:
1185 * @model: The model
1186 * @tree_level: The tree level where the node is.
1187 * @column_values: The node column values.
1189 * Gets if the node has 1 or more children with given column values.
1191 * Returns: TRUE if node has children, otherwise FALSE
1193 static gboolean
1194 sdb_model_get_has_child_real (SymbolDBModel *model, gint tree_level,
1195 GValue column_values[])
1197 gboolean has_child;
1198 g_signal_emit_by_name (model, "get-has_child", tree_level, column_values,
1199 &has_child);
1200 return has_child;
1203 static gboolean
1204 sdb_model_get_has_child (SymbolDBModel *model, SymbolDBModelNode *node)
1206 if (node->has_child_ensured)
1207 return node->has_child;
1209 node->has_child_ensured = TRUE;
1210 node->has_child =
1211 SYMBOL_DB_MODEL_GET_CLASS(model)->get_has_child (model,
1212 node->level,
1213 node->values);
1214 if (node->has_child)
1216 sdb_model_emit_has_child (model, node);
1218 return node->has_child;
1222 * sdb_model_get_n_children_real:
1223 * @model: The model
1224 * @tree_level: The tree level where the node is.
1225 * @column_values: The node column values.
1227 * Gets the number of children of the node with given column values.
1229 * Returns: Number of children
1231 static gint
1232 sdb_model_get_n_children_real (SymbolDBModel *model, gint tree_level,
1233 GValue column_values[])
1235 gint n_children;
1236 g_signal_emit_by_name (model, "get-n-children", tree_level, column_values,
1237 &n_children);
1238 return n_children;
1241 static gint
1242 sdb_model_get_n_children (SymbolDBModel *model, gint tree_level,
1243 GValue column_values[])
1245 return SYMBOL_DB_MODEL_GET_CLASS(model)->get_n_children (model, tree_level,
1246 column_values);
1250 * sdb_model_get_children_real:
1251 * @model: The model
1252 * @tree_level: The tree level where the node is.
1253 * @column_values: The node column values.
1254 * @offset: Offset of the start row
1255 * @limit: Number of rows to fetch
1257 * Fetches the children data from backend database. The results are returned
1258 * as GdaDataModel. The children to fetch starts form @offset and retrieves
1259 * @limit amount.
1261 * Returns: Data model holding the rows data, or NULL if there is no data.
1263 static GdaDataModel*
1264 sdb_model_get_children_real (SymbolDBModel *model, gint tree_level,
1265 GValue column_values[], gint offset,
1266 gint limit)
1268 GdaDataModel *data_model;
1269 g_signal_emit_by_name (model, "get-children", tree_level,
1270 column_values, offset, limit, &data_model);
1271 return data_model;
1274 static GdaDataModel*
1275 sdb_model_get_children (SymbolDBModel *model, gint tree_level,
1276 GValue column_values[], gint offset,
1277 gint limit)
1279 return SYMBOL_DB_MODEL_GET_CLASS(model)->
1280 get_children (model, tree_level, column_values, offset, limit);
1283 /* Object implementation */
1285 static void
1286 sdb_model_finalize (GObject *object)
1288 SymbolDBModelPriv *priv;
1290 priv = SYMBOL_DB_MODEL (object)->priv;;
1291 g_free (priv->column_types);
1292 g_free (priv->query_columns);
1293 sdb_model_node_cleanse (priv->root, TRUE);
1294 g_slice_free (SymbolDBModelNode, priv->root);
1296 g_free (priv);
1298 G_OBJECT_CLASS (sdb_model_parent_class)->finalize (object);
1301 static void
1302 sdb_model_set_property (GObject *object, guint prop_id,
1303 const GValue *value, GParamSpec *pspec)
1305 g_return_if_fail (SYMBOL_DB_IS_MODEL (object));
1306 /* SymbolDBModel* model = SYMBOL_DB_MODEL(object);
1307 SymbolDBModelPriv* priv = GET_PRIV (model); */
1309 switch (prop_id)
1314 static void
1315 sdb_model_get_property (GObject *object, guint prop_id, GValue *value,
1316 GParamSpec *pspec)
1318 g_return_if_fail (SYMBOL_DB_IS_MODEL (object));
1319 /* SymbolDBModel* model = SYMBOL_DB_MODEL(object);
1320 SymbolDBModelPriv* priv = GET_PRIV (model); */
1322 switch (prop_id)
1327 static void
1328 sdb_model_init (SymbolDBModel *object)
1330 SymbolDBModelPriv *priv;
1332 priv = g_new0 (SymbolDBModelPriv, 1);
1333 object->priv = priv;
1335 priv->root = g_slice_new0 (SymbolDBModelNode);
1336 priv->freeze_count = 0;
1337 priv->n_columns = 0;
1338 priv->column_types = NULL;
1339 priv->query_columns = NULL;
1342 static void
1343 sdb_model_class_init (SymbolDBModelClass *klass)
1345 GObjectClass* object_class = G_OBJECT_CLASS (klass);
1347 klass->get_query_value = sdb_model_get_query_value_real;
1348 klass->get_query_value_at = sdb_model_get_query_value_at_real;
1349 klass->get_has_child = sdb_model_get_has_child_real;
1350 klass->get_n_children = sdb_model_get_n_children_real;
1351 klass->get_children = sdb_model_get_children_real;
1353 object_class->finalize = sdb_model_finalize;
1354 object_class->set_property = sdb_model_set_property;
1355 object_class->get_property = sdb_model_get_property;
1357 /* Signals */
1358 symbol_db_model_signals[SIGNAL_GET_HAS_CHILD] =
1359 g_signal_new ("get-has-child",
1360 G_TYPE_FROM_CLASS (klass),
1361 G_SIGNAL_RUN_LAST,
1362 0, NULL, NULL,
1363 symbol_db_cclosure_marshal_BOOLEAN__INT_POINTER,
1364 G_TYPE_BOOLEAN,
1366 G_TYPE_INT,
1367 G_TYPE_POINTER);
1368 symbol_db_model_signals[SIGNAL_GET_N_CHILDREN] =
1369 g_signal_new ("get-n-children",
1370 G_TYPE_FROM_CLASS (klass),
1371 G_SIGNAL_RUN_LAST,
1372 0, NULL, NULL,
1373 symbol_db_cclosure_marshal_INT__INT_POINTER,
1374 G_TYPE_INT,
1376 G_TYPE_INT,
1377 G_TYPE_POINTER);
1378 symbol_db_model_signals[SIGNAL_GET_CHILDREN] =
1379 g_signal_new ("get-children",
1380 G_TYPE_FROM_CLASS (klass),
1381 G_SIGNAL_RUN_LAST,
1382 0, NULL, NULL,
1383 symbol_db_cclosure_marshal_OBJECT__INT_POINTER_INT_INT,
1384 GDA_TYPE_DATA_MODEL,
1386 G_TYPE_INT,
1387 G_TYPE_POINTER,
1388 G_TYPE_INT,
1389 G_TYPE_INT);
1392 void
1393 symbol_db_model_set_columns (SymbolDBModel *model, gint n_columns,
1394 GType *types, gint *query_columns)
1396 SymbolDBModelPriv *priv;
1398 g_return_if_fail (n_columns > 0);
1399 g_return_if_fail (SYMBOL_DB_IS_MODEL (model));
1401 priv = model->priv;
1403 g_return_if_fail (priv->n_columns <= 0);
1404 g_return_if_fail (priv->column_types == NULL);
1405 g_return_if_fail (priv->query_columns == NULL);
1407 priv->n_columns = n_columns;
1408 priv->column_types = g_new0(GType, n_columns);
1409 priv->query_columns = g_new0(gint, n_columns);
1410 memcpy (priv->column_types, types, n_columns * sizeof (GType));
1411 memcpy (priv->query_columns, query_columns, n_columns * sizeof (gint));
1414 GtkTreeModel *
1415 symbol_db_model_new (gint n_columns, ...)
1417 GtkTreeModel *model;
1418 SymbolDBModelPriv *priv;
1419 va_list args;
1420 gint i;
1422 g_return_val_if_fail (n_columns > 0, NULL);
1424 model = g_object_new (SYMBOL_DB_TYPE_MODEL, NULL);
1425 priv = SYMBOL_DB_MODEL (model)->priv;
1427 priv->n_columns = n_columns;
1428 priv->column_types = g_new0(GType, n_columns);
1429 priv->query_columns = g_new0(gint, n_columns);
1431 va_start (args, n_columns);
1433 for (i = 0; i < n_columns; i++)
1435 priv->column_types[i] = va_arg (args, GType);
1436 priv->query_columns[i] = va_arg (args, gint);
1438 va_end (args);
1440 return model;
1443 GtkTreeModel*
1444 symbol_db_model_newv (gint n_columns, GType *types, gint *query_columns)
1446 GtkTreeModel *model;
1447 g_return_val_if_fail (n_columns > 0, NULL);
1448 model = g_object_new (SYMBOL_DB_TYPE_MODEL, NULL);
1449 symbol_db_model_set_columns (SYMBOL_DB_MODEL (model), n_columns,
1450 types, query_columns);
1451 return model;
1454 void
1455 symbol_db_model_update (SymbolDBModel *model)
1457 SymbolDBModelPriv *priv;
1459 g_return_if_fail (SYMBOL_DB_IS_MODEL (model));
1461 priv = model->priv;
1463 sdb_model_update_node_children (model, priv->root, FALSE);
1466 void
1467 symbol_db_model_freeze (SymbolDBModel *model)
1469 SymbolDBModelPriv *priv;
1471 g_return_if_fail (SYMBOL_DB_IS_MODEL (model));
1473 priv = model->priv;
1474 priv->freeze_count++;
1477 void
1478 symbol_db_model_thaw (SymbolDBModel *model)
1480 SymbolDBModelPriv *priv;
1482 g_return_if_fail (SYMBOL_DB_IS_MODEL (model));
1484 priv = model->priv;
1486 if (priv->freeze_count > 0)
1487 priv->freeze_count--;
1489 if (priv->freeze_count <= 0)
1490 symbol_db_model_update (model);