1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Naba Kumar 2010 <naba@gnome.org>
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
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
{
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
51 /* List of currently active (cached) pages */
52 SymbolDBModelPage
*pages
;
56 SymbolDBModelNode
*parent
;
60 gint children_ref_count
;
61 gboolean has_child_ensured
;
63 gboolean children_ensured
;
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.
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
;
84 SIGNAL_GET_N_CHILDREN
,
89 static guint symbol_db_model_signals
[LAST_SIGNAL
] = { 0 };
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
,
102 static gboolean
sdb_model_get_query_value (SymbolDBModel
*model
,
103 GdaDataModel
*data_model
,
104 GdaDataModelIter
*iter
,
108 static gboolean
sdb_model_get_has_child (SymbolDBModel
*model
,
109 SymbolDBModelNode
*node
);
111 static gint
sdb_model_get_n_children (SymbolDBModel
*model
,
113 GValue column_values
[]);
115 static GdaDataModel
* sdb_model_get_children (SymbolDBModel
*model
,
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
))
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
);
149 return node
->children
[child_offset
];
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.
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 */
171 node
->children
= g_new0 (SymbolDBModelNode
*, node
->n_children
);
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.
193 sdb_model_node_cleanse (SymbolDBModelNode
*node
, gboolean force
)
195 SymbolDBModelPage
*page
, *next
;
198 g_return_val_if_fail (node
!= NULL
, FALSE
);
200 /* Can not cleanse a node if there are refed children */
203 g_return_val_if_fail (node
->children_ref_count
== 0, FALSE
);
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
);
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 */
232 g_slice_free (SymbolDBModelPage
, page
);
236 node
->children_ensured
= FALSE
;
237 node
->n_children
= 0;
240 g_free (node
->children
);
241 node
->children
= NULL
;
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
256 sdb_model_node_free (SymbolDBModelNode
*node
, gboolean force
)
258 if (!sdb_model_node_cleanse (node
, force
))
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.
274 sdb_model_node_remove_page (SymbolDBModelNode
*node
,
275 SymbolDBModelPage
*page
)
278 page
->prev
->next
= page
->next
;
280 node
->pages
= 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
299 sdb_model_node_insert_page (SymbolDBModelNode
*node
,
300 SymbolDBModelPage
*page
,
301 SymbolDBModelPage
*after
)
304 /* Insert the new page after "after" page */
307 page
->next
= after
->next
;
310 else /* Insert at head */
312 page
->next
= node
->pages
;
318 * symbold_db_model_node_find_child_page:
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
,
333 SymbolDBModelPage
**prev_page
)
335 SymbolDBModelPage
*page
;
341 /* Find the page which holds result for given child_offset */
344 if (child_offset
>= page
->begin_offset
&&
345 child_offset
< page
->end_offset
)
347 /* child_offset has associated page */
350 if (child_offset
< page
->begin_offset
)
352 /* Insert point is here */
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.
373 sdb_model_node_ref_child (SymbolDBModelNode
*node
)
375 g_return_if_fail (node
!= NULL
);
377 node
->children_ref_count
++;
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.
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
);
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
)
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
,
445 i
, &(node
->values
[i
]));
447 node
->offset
= child_offset
;
448 node
->parent
= parent
;
449 node
->level
= parent
->level
+ 1;
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
465 sdb_model_iter_is_valid (GtkTreeModel
*model
, GtkTreeIter
*iter
)
467 SymbolDBModelNode
*parent_node
;
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
,
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
,
501 SymbolDBModelPriv
*priv
;
502 SymbolDBModelPage
*page
, *prev_page
, *page_found
;
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
,
515 /* If model is frozen, can't fetch data from backend */
517 if (priv
->freeze_count
> 0)
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
,
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 */
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 */
574 g_object_unref (data_iter
);
576 g_object_unref (data_model
);
580 /* GtkTreeModel implementation */
582 static GtkTreeModelFlags
583 sdb_model_get_flags (GtkTreeModel
*tree_model
)
589 sdb_model_get_column_type (GtkTreeModel
*tree_model
,
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
];
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
;
606 sdb_model_get_iter (GtkTreeModel
*tree_model
,
611 SymbolDBModelNode
*node
, *parent_node
;
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
);
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
);
630 for (i
= 0; i
< depth
; i
++)
633 if (!node
->children_ensured
)
634 sdb_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model
),
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 */
644 if (indx
[i
] >= node
->n_children
)
646 g_warning ("Invalid path to iter conversion; no children list found at depth %d", i
);
649 node
= sdb_model_node_get_child (node
, indx
[i
]);
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
));
665 sdb_model_get_path (GtkTreeModel
*tree_model
,
668 SymbolDBModelNode
*node
;
672 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model
, iter
),
675 path
= gtk_tree_path_new ();
677 node
= (SymbolDBModelNode
*)iter
->user_data
;
678 offset
= GPOINTER_TO_INT (iter
->user_data2
);
680 gtk_tree_path_prepend_index (path
, offset
);
682 offset
= node
->offset
;
689 sdb_model_get_value (GtkTreeModel
*tree_model
,
690 GtkTreeIter
*iter
, gint column
,
693 SymbolDBModelPriv
*priv
;
694 SymbolDBModelNode
*parent_node
, *node
;
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
]);
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
);
725 sdb_model_iter_next (GtkTreeModel
*tree_model
,
728 SymbolDBModelNode
*node
;
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
);
740 if (offset
>= node
->n_children
)
742 iter
->user_data2
= GINT_TO_POINTER (offset
);
744 g_assert (sdb_model_iter_is_valid (tree_model
, iter
));
750 sdb_model_iter_children (GtkTreeModel
*tree_model
,
754 SymbolDBModelNode
*node
, *parent_node
;
755 SymbolDBModelPriv
*priv
;
759 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model
, parent
),
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
;
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
);
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
))
790 if (!node
->children_ensured
)
791 sdb_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model
),
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)
802 g_assert (sdb_model_iter_is_valid (tree_model
, iter
));
808 sdb_model_iter_has_child (GtkTreeModel
*tree_model
,
812 SymbolDBModelNode
*node
, *parent_node
;
814 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model
, iter
),
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() */
825 return sdb_model_get_has_child (SYMBOL_DB_MODEL (tree_model
), node
);
829 sdb_model_iter_n_children (GtkTreeModel
*tree_model
,
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
;
841 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model
, iter
), 0);
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
);
855 if (!node
->children_ensured
)
856 sdb_model_ensure_node_children (SYMBOL_DB_MODEL (tree_model
),
858 return node
->n_children
;
862 sdb_model_iter_nth_child (GtkTreeModel
*tree_model
,
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
))
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
));
888 sdb_model_iter_parent (GtkTreeModel
*tree_model
,
892 SymbolDBModelNode
*parent_node
;
894 g_return_val_if_fail (sdb_model_iter_is_valid (tree_model
, child
),
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
));
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
);
924 sdb_model_iter_unref (GtkTreeModel
*tree_model
, GtkTreeIter
*iter
)
926 SymbolDBModelNode
*parent_node
;
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
);
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 */
959 sdb_model_emit_has_child (SymbolDBModel
*model
, SymbolDBModelNode
*node
)
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
),
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.
985 sdb_model_ensure_node_children (SymbolDBModel
*model
,
986 SymbolDBModelNode
*node
,
987 gboolean emit_has_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
);
999 /* Can not ensure if model is frozen */
1000 if (priv
->freeze_count
> 0)
1003 /* Initialize children array and count */
1004 old_has_child
= node
->has_child
;
1006 sdb_model_get_n_children (model
, node
->level
,
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
;
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
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)
1044 GtkTreeIter iter
= {0};
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)
1068 GtkTreeIter iter
= {0};
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
);
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:
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.
1103 sdb_model_get_query_value_real (SymbolDBModel
*model
,
1104 GdaDataModel
*data_model
,
1105 GdaDataModelIter
*iter
, gint column
,
1109 SymbolDBModelPriv
*priv
= model
->priv
;
1110 gint query_column
= priv
->query_columns
[column
];
1112 if (query_column
< 0)
1115 ret
= gda_data_model_iter_get_value_at (iter
, query_column
);
1116 if (!ret
|| !G_IS_VALUE (ret
))
1119 g_value_copy (ret
, value
);
1124 sdb_model_get_query_value (SymbolDBModel
*model
,
1125 GdaDataModel
*data_model
,
1126 GdaDataModelIter
*iter
, gint column
,
1129 return SYMBOL_DB_MODEL_GET_CLASS(model
)->get_query_value(model
, data_model
,
1135 * sdb_model_get_query_value_at_real:
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.
1149 sdb_model_get_query_value_at_real (SymbolDBModel
*model
,
1150 GdaDataModel
*data_model
,
1151 gint position
, gint column
,
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)
1162 ret
= gda_data_model_get_value_at (data_model
, query_column
, position
,
1164 if (!ret
|| !G_IS_VALUE (ret
))
1167 g_value_copy (ret
, value
);
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
,
1184 * sdb_model_get_has_child_real:
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
1194 sdb_model_get_has_child_real (SymbolDBModel
*model
, gint tree_level
,
1195 GValue column_values
[])
1198 g_signal_emit_by_name (model
, "get-has_child", tree_level
, column_values
,
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
;
1211 SYMBOL_DB_MODEL_GET_CLASS(model
)->get_has_child (model
,
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:
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
1232 sdb_model_get_n_children_real (SymbolDBModel
*model
, gint tree_level
,
1233 GValue column_values
[])
1236 g_signal_emit_by_name (model
, "get-n-children", tree_level
, column_values
,
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
,
1250 * sdb_model_get_children_real:
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
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
,
1268 GdaDataModel
*data_model
;
1269 g_signal_emit_by_name (model
, "get-children", tree_level
,
1270 column_values
, offset
, limit
, &data_model
);
1274 static GdaDataModel
*
1275 sdb_model_get_children (SymbolDBModel
*model
, gint tree_level
,
1276 GValue column_values
[], gint offset
,
1279 return SYMBOL_DB_MODEL_GET_CLASS(model
)->
1280 get_children (model
, tree_level
, column_values
, offset
, limit
);
1283 /* Object implementation */
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
);
1298 G_OBJECT_CLASS (sdb_model_parent_class
)->finalize (object
);
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); */
1315 sdb_model_get_property (GObject
*object
, guint prop_id
, GValue
*value
,
1318 g_return_if_fail (SYMBOL_DB_IS_MODEL (object
));
1319 /* SymbolDBModel* model = SYMBOL_DB_MODEL(object);
1320 SymbolDBModelPriv* priv = GET_PRIV (model); */
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
;
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
;
1358 symbol_db_model_signals
[SIGNAL_GET_HAS_CHILD
] =
1359 g_signal_new ("get-has-child",
1360 G_TYPE_FROM_CLASS (klass
),
1363 symbol_db_cclosure_marshal_BOOLEAN__INT_POINTER
,
1368 symbol_db_model_signals
[SIGNAL_GET_N_CHILDREN
] =
1369 g_signal_new ("get-n-children",
1370 G_TYPE_FROM_CLASS (klass
),
1373 symbol_db_cclosure_marshal_INT__INT_POINTER
,
1378 symbol_db_model_signals
[SIGNAL_GET_CHILDREN
] =
1379 g_signal_new ("get-children",
1380 G_TYPE_FROM_CLASS (klass
),
1383 symbol_db_cclosure_marshal_OBJECT__INT_POINTER_INT_INT
,
1384 GDA_TYPE_DATA_MODEL
,
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
));
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
));
1415 symbol_db_model_new (gint n_columns
, ...)
1417 GtkTreeModel
*model
;
1418 SymbolDBModelPriv
*priv
;
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
);
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
);
1455 symbol_db_model_update (SymbolDBModel
*model
)
1457 SymbolDBModelPriv
*priv
;
1459 g_return_if_fail (SYMBOL_DB_IS_MODEL (model
));
1463 sdb_model_update_node_children (model
, priv
->root
, FALSE
);
1467 symbol_db_model_freeze (SymbolDBModel
*model
)
1469 SymbolDBModelPriv
*priv
;
1471 g_return_if_fail (SYMBOL_DB_IS_MODEL (model
));
1474 priv
->freeze_count
++;
1478 symbol_db_model_thaw (SymbolDBModel
*model
)
1480 SymbolDBModelPriv
*priv
;
1482 g_return_if_fail (SYMBOL_DB_IS_MODEL (model
));
1486 if (priv
->freeze_count
> 0)
1487 priv
->freeze_count
--;
1489 if (priv
->freeze_count
<= 0)
1490 symbol_db_model_update (model
);