1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) Massimo Cora' 2007 <maxcvs@email.it>
6 * anjuta is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
13 * anjuta is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 * See the GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with anjuta. If not, write to:
20 * The Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301, USA.
26 #include <gdl/gdl-icons.h>
27 #include <libanjuta/resources.h>
28 #include <libanjuta/anjuta-utils.h>
29 #include <libanjuta/anjuta-debug.h>
30 #include "symbol-db-view.h"
31 #include "symbol-db-engine.h"
32 #include "symbol-db-engine-iterator.h"
33 #include "symbol-db-engine-iterator-node.h"
35 #define DUMMY_SYMBOL_ID G_MININT32+1
44 /* positive ids are used in real database */
46 ROOT_GLOBAL
= G_MAXINT32
49 struct _SymbolDBViewPriv
53 gint scan_end_handler
;
55 GtkTreeRowReference
*row_ref_global
;
56 GTree
*nodes_displayed
;
58 GTree
*expanding_gfunc_ids
;
61 typedef struct _WaitingForSymbol
{
63 gchar
*child_symbol_name
;
64 const GdkPixbuf
*pixbuf
;
68 typedef struct _NodeIdleExpand
{
70 SymbolDBEngineIterator
*iterator
;
72 GtkTreePath
*expanded_path
;
73 gint expanded_symbol_id
;
78 static GtkTreeViewClass
*parent_class
= NULL
;
79 static GHashTable
*pixbufs_hash
= NULL
;
81 trigger_on_symbol_inserted (SymbolDBView
*dbv
, gint symbol_id
);
85 gtree_compare_func (gconstpointer a
, gconstpointer b
, gpointer user_data
)
87 return (gint
)a
- (gint
)b
;
91 waiting_for_symbol_destroy (WaitingForSymbol
*wfs
)
93 g_return_if_fail (wfs
!= NULL
);
94 g_free (wfs
->child_symbol_name
);
98 static inline gboolean
99 sdb_view_get_iter_from_row_ref (SymbolDBView
*dbv
, GtkTreeRowReference
*row_ref
,
100 GtkTreeIter
*OUT_iter
)
105 /* no node displayed found */
109 path
= gtk_tree_row_reference_get_path (row_ref
);
112 DEBUG_PRINT ("sdb_view_get_iter_from_row_ref (): path is null, something "
117 if (gtk_tree_model_get_iter (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
118 OUT_iter
, path
) == FALSE
)
120 gtk_tree_path_free (path
);
123 gtk_tree_path_free (path
);
130 traverse_free_waiting_for (gpointer key
, gpointer value
, gpointer data
)
135 g_slist_foreach ((GSList
*)value
, (GFunc
)waiting_for_symbol_destroy
, NULL
);
136 g_slist_free ((GSList
*)value
);
141 symbol_db_view_clear_cache (SymbolDBView
*dbv
)
143 SymbolDBViewPriv
*priv
;
146 g_return_if_fail (dbv
!= NULL
);
150 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
152 g_object_unref (store
);
154 /* this will free alto the priv->row_ref* instances */
155 if (priv
->nodes_displayed
)
157 g_tree_destroy (priv
->nodes_displayed
);
158 priv
->nodes_displayed
= NULL
;
161 /* free the waiting_for structs before destroying the tree itself */
162 if (priv
->waiting_for
)
164 g_tree_foreach (priv
->waiting_for
, traverse_free_waiting_for
, NULL
);
165 g_tree_destroy (priv
->waiting_for
);
166 priv
->waiting_for
= NULL
;
169 gtk_tree_view_set_model (GTK_TREE_VIEW (dbv
), NULL
);
173 on_scan_end (SymbolDBEngine
*dbe
, gpointer data
)
176 SymbolDBViewPriv
*priv
;
178 dbv
= SYMBOL_DB_VIEW (data
);
179 g_return_if_fail (dbv
!= NULL
);
182 /* void the waiting_for symbols */
183 /* free the waiting_for structs before destroying the tree itself */
184 if (priv
->waiting_for
)
186 g_tree_foreach (priv
->waiting_for
, traverse_free_waiting_for
, data
);
187 g_tree_destroy (priv
->waiting_for
);
189 /* recreate it because there's a free_all_items function. And the
190 * one proposed by the doc is too complex.. create a list of the items
191 * and reparse them with g_tree_remove...
193 priv
->waiting_for
= g_tree_new_full ((GCompareDataFunc
)>ree_compare_func
,
201 static inline GtkTreeRowReference
*
202 do_add_root_symbol_to_view (SymbolDBView
*dbv
, const GdkPixbuf
*pixbuf
,
203 const gchar
* symbol_name
, gint symbol_id
)
205 SymbolDBViewPriv
*priv
;
207 GtkTreeIter child_iter
;
209 GtkTreeRowReference
*row_ref
;
211 g_return_val_if_fail (dbv
!= NULL
, NULL
);
215 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
217 gtk_tree_store_append (store
, &child_iter
, NULL
);
219 gtk_tree_store_set (store
, &child_iter
,
220 COLUMN_PIXBUF
, pixbuf
,
221 COLUMN_NAME
, symbol_name
,
222 COLUMN_SYMBOL_ID
, symbol_id
,
225 path
= gtk_tree_model_get_path (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
227 row_ref
= gtk_tree_row_reference_new (
228 gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)), path
);
229 gtk_tree_path_free (path
);
234 /* before calling this function be sure that parent_symbol_id is already into
235 * nodes_displayed GTree, or this will complain about it and will bail out
238 static inline GtkTreeRowReference
*
239 do_add_child_symbol_to_view (SymbolDBView
*dbv
, gint parent_symbol_id
,
240 const GdkPixbuf
*pixbuf
, const gchar
* symbol_name
,
243 SymbolDBViewPriv
*priv
;
246 GtkTreeIter iter
, child_iter
;
247 GtkTreeRowReference
*row_ref
;
251 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
253 /* look up the row ref in the hashtable, then get its associated gtktreeiter */
254 row_ref
= g_tree_lookup (priv
->nodes_displayed
, (gpointer
)parent_symbol_id
);
256 if (sdb_view_get_iter_from_row_ref (dbv
, row_ref
, &iter
) == FALSE
)
258 g_warning ("do_add_symbol_to_view (): something went wrong.");
262 /* append a new child &child_iter, with a parent of &iter */
263 gtk_tree_store_append (store
, &child_iter
, &iter
);
265 gtk_tree_store_set (store
, &child_iter
,
266 COLUMN_PIXBUF
, pixbuf
,
267 COLUMN_NAME
, symbol_name
,
268 COLUMN_SYMBOL_ID
, symbol_id
,
271 /* grab the row ref and return it */
272 path
= gtk_tree_model_get_path (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
274 row_ref
= gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
276 gtk_tree_path_free (path
);
282 add_waiting_for_symbol_to_view (SymbolDBView
*dbv
, WaitingForSymbol
*wfs
,
283 gint parent_symbol_id
)
285 SymbolDBViewPriv
*priv
;
286 gint symbol_id_added
;
287 GtkTreeRowReference
*child_tree_row_ref
;
289 g_return_if_fail (dbv
!= NULL
);
290 g_return_if_fail (wfs
!= NULL
);
294 child_tree_row_ref
= do_add_child_symbol_to_view (dbv
, parent_symbol_id
,
295 wfs
->pixbuf
, wfs
->child_symbol_name
, wfs
->child_symbol_id
);
297 symbol_id_added
= wfs
->child_symbol_id
;
299 /* add a new entry on gtree 'nodes_displayed' */
300 g_tree_insert (priv
->nodes_displayed
, (gpointer
)wfs
->child_symbol_id
,
303 /* and now trigger the inserted symbol... (recursive function). */
304 if (wfs
->child_symbol_id
!= parent_symbol_id
)
305 trigger_on_symbol_inserted (dbv
, wfs
->child_symbol_id
);
310 trigger_on_symbol_inserted (SymbolDBView
*dbv
, gint symbol_id
)
312 SymbolDBViewPriv
*priv
;
314 WaitingForSymbol
*wfs
;
316 g_return_if_fail (dbv
!= NULL
);
320 /* DEBUG_PRINT ("trigger_on_symbol_inserted (): triggering %d", symbol_id);*/
322 /* try to find a waiting for symbol */
323 slist
= g_tree_lookup (priv
->waiting_for
, (gpointer
)symbol_id
);
327 /* nothing waiting for us */
328 /*DEBUG_PRINT ("trigger_on_symbol_inserted (): no children waiting for us...");*/
333 gint length
= g_slist_length (slist
);
335 /* DEBUG_PRINT ("trigger_on_symbol_inserted (): consuming slist for parent %d",
338 for (i
=0; i
< length
-1; i
++)
340 wfs
= g_slist_nth_data (slist
, 0);
342 slist
= g_slist_remove (slist
, wfs
);
344 add_waiting_for_symbol_to_view (dbv
, wfs
, symbol_id
);
346 /* destroy the data structure */
347 waiting_for_symbol_destroy (wfs
);
350 /* remove the waiting for key/value */
351 g_tree_remove (priv
->waiting_for
, (gpointer
)symbol_id
);
352 g_slist_free (slist
);
358 add_new_waiting_for (SymbolDBView
*dbv
, gint parent_symbol_id
,
359 const gchar
* symbol_name
,
360 gint symbol_id
, const GdkPixbuf
*pixbuf
)
362 SymbolDBViewPriv
*priv
;
365 g_return_if_fail (dbv
!= NULL
);
368 /* check if we already have some children waiting for a
369 * specific father to be inserted, then add this symbol_id to the list
370 * (or create a new one)
372 WaitingForSymbol
*wfs
;
374 wfs
= g_new0 (WaitingForSymbol
, 1);
375 wfs
->child_symbol_id
= symbol_id
;
376 wfs
->child_symbol_name
= g_strdup (symbol_name
);
377 wfs
->pixbuf
= pixbuf
;
379 node
= g_tree_lookup (priv
->waiting_for
, (gpointer
)parent_symbol_id
);
382 /* no lists already set. Create one. */
384 slist
= g_slist_alloc ();
386 slist
= g_slist_prepend (slist
, wfs
);
388 /* add it to the binary tree. */
389 g_tree_insert (priv
->waiting_for
, (gpointer
)parent_symbol_id
,
396 slist
= (GSList
*)node
;
398 slist
= g_slist_prepend (slist
, wfs
);
400 g_tree_replace (priv
->waiting_for
, (gpointer
)parent_symbol_id
,
406 /* Put every GtkTreeView node of the subtree headed by 'parent_subtree_iter'
407 * into a waiting_for GTree.
408 * It's a recursive function.
411 do_recurse_subtree_and_invalidate (SymbolDBView
*dbv
,
412 GtkTreeIter
*parent_subtree_iter
,
413 gint parent_id_to_wait_for
)
416 const GdkPixbuf
*curr_pixbuf
;
418 gchar
*curr_symbol_name
;
420 SymbolDBViewPriv
*priv
;
422 g_return_if_fail (dbv
!= NULL
);
425 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
427 gtk_tree_model_get (GTK_TREE_MODEL (store
), parent_subtree_iter
,
428 COLUMN_SYMBOL_ID
, &curr_symbol_id
,
429 COLUMN_PIXBUF
, &curr_pixbuf
,
430 COLUMN_NAME
, &curr_symbol_name
, /* no strdup required */
433 /*DEBUG_PRINT ("do_recurse_subtree_and_invalidate (): curr_symbol_id %d,"
434 "parent_id_to_wait_for %d", curr_symbol_id, parent_id_to_wait_for);*/
436 while (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (store
),
437 parent_subtree_iter
))
440 gtk_tree_model_iter_children (GTK_TREE_MODEL (store
), &child
,
441 parent_subtree_iter
);
444 do_recurse_subtree_and_invalidate (dbv
, &child
, curr_symbol_id
);
447 /* add to waiting for */
448 add_new_waiting_for (dbv
, parent_id_to_wait_for
, curr_symbol_name
,
449 curr_symbol_id
, curr_pixbuf
);
451 gtk_tree_store_remove (store
, parent_subtree_iter
);
452 g_tree_remove (priv
->nodes_displayed
, (gpointer
) curr_symbol_id
);
454 /* don't forget to free this gchar */
455 g_free (curr_symbol_name
);
458 /* Add promptly a symbol to the gtktreeview or add it for a later add (waiting
462 prepare_for_adding (SymbolDBView
*dbv
, gint parent_symbol_id
,
463 const gchar
* symbol_name
, gint symbol_id
,
464 const GdkPixbuf
*pixbuf
, const gchar
* kind
)
466 SymbolDBViewPriv
*priv
;
468 g_return_if_fail (dbv
!= NULL
);
469 g_return_if_fail (kind
!= NULL
);
472 /* add to root if parent_symbol_id is <= 0 */
473 if (parent_symbol_id
<= 0)
475 GtkTreeRowReference
*curr_tree_row_ref
= NULL
;
477 /* ok, let's check the kind of the symbol. Based on that we'll retrieve
478 * the row_ref. It's quicker to check onlyl the first char than the whole
483 case 'n': /* namespace */
484 curr_tree_row_ref
= do_add_root_symbol_to_view (dbv
,
490 case 'c': /* class */
491 case 's': /* struct */
492 curr_tree_row_ref
= do_add_child_symbol_to_view (dbv
,
493 ROOT_GLOBAL
, pixbuf
, symbol_name
,
497 case 'u': /* union */
498 case 'f': /* function */
499 case 'v': /* variable */
500 case 't': /* typedef */
501 case 'e': /* enumerator */
505 /* Vars/Other may not be displayed already. Check it. */
506 node
= g_tree_lookup (priv
->nodes_displayed
, (gpointer
)-ROOT_GLOBAL
);
510 /* hey we found it */
511 /* note the negative: we'll store these under the vars/Other node */
512 curr_tree_row_ref
= do_add_child_symbol_to_view (dbv
,
513 -ROOT_GLOBAL
, pixbuf
, symbol_name
,
518 /* add it to the waiting_for trigger list */
519 add_new_waiting_for (dbv
, parent_symbol_id
, symbol_name
, symbol_id
,
526 if (curr_tree_row_ref
== NULL
)
531 /* we'll fake the gpointer to store an int */
532 g_tree_insert (priv
->nodes_displayed
, (gpointer
)symbol_id
,
535 /* let's trigger the insertion of the symbol_id, there may be some children
538 trigger_on_symbol_inserted (dbv
, symbol_id
);
546 case 'u': /* union */
547 case 'f': /* function */
548 case 'v': /* variable */
549 case 't': /* typedef */
550 case 'e': /* enumerator */
551 /* switch to negative! i.e. schedule to put it under the
554 parent_symbol_id
= -parent_symbol_id
;
556 default: /* let it as it is */
561 /* do we already have that parent_symbol displayed in gtktreeview?
562 * If that's the case add it as children.
564 node
= g_tree_lookup (priv
->nodes_displayed
, (gpointer
)parent_symbol_id
);
568 /* hey we found it */
569 GtkTreeRowReference
*child_row_ref
;
570 child_row_ref
= do_add_child_symbol_to_view (dbv
, parent_symbol_id
,
571 pixbuf
, symbol_name
, symbol_id
);
573 /* add the children_path to the GTree. */
574 g_tree_insert (priv
->nodes_displayed
, (gpointer
)symbol_id
,
576 trigger_on_symbol_inserted (dbv
, symbol_id
);
580 /* add it to the waiting_for trigger list */
581 add_new_waiting_for (dbv
, parent_symbol_id
, symbol_name
, symbol_id
,
588 on_symbol_inserted (SymbolDBEngine
*dbe
,
589 gint symbol_id
, gpointer data
)
591 SymbolDBEngineIterator
*iterator
;
594 /* it's not obligatory referred to a class inheritance */
595 gint parent_symbol_id
;
597 SymbolDBViewPriv
*priv
;
599 dbv
= SYMBOL_DB_VIEW (data
);
601 g_return_if_fail (dbv
!= NULL
);
605 /*DEBUG_PRINT ("on_symbol_inserted -global- %d", symbol_id);*/
606 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
608 parent_symbol_id
= symbol_db_engine_get_parent_scope_id_by_symbol_id (dbe
,
612 /*DEBUG_PRINT ("on_symbol_inserted parent_symbol_id detected %d", parent_symbol_id);*/
614 /* get the original symbol infos */
615 iterator
= symbol_db_engine_get_symbol_info_by_id (dbe
, symbol_id
,
620 if (iterator
!= NULL
)
622 SymbolDBEngineIteratorNode
*iter_node
;
623 const GdkPixbuf
*pixbuf
;
624 const gchar
* symbol_name
;
625 const gchar
* symbol_kind
;
626 const gchar
* symbol_access
;
627 SymbolDBEngineIterator
*iterator_for_children
;
629 iter_node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (iterator
);
631 /* check if what we want to add is on a global_scope and not only a local
632 * file scope e.g. static functions
634 if (symbol_db_engine_iterator_node_get_symbol_is_file_scope (iter_node
) == TRUE
)
636 /* DEBUG_PRINT ("on_symbol_inserted() -global- symbol %d is not global scope",
638 g_object_unref (iterator
);
642 symbol_kind
= symbol_db_engine_iterator_node_get_symbol_extra_string (
643 iter_node
, SYMINFO_KIND
);
645 symbol_access
= symbol_db_engine_iterator_node_get_symbol_extra_string (
646 iter_node
, SYMINFO_ACCESS
);
648 pixbuf
= symbol_db_view_get_pixbuf (symbol_kind
, symbol_access
);
649 symbol_name
= symbol_db_engine_iterator_node_get_symbol_name (iter_node
);
651 /* check if one of the children [if they exist] of symbol_id are already
652 * displayed. In that case we'll invalidate all of them.
653 * i.e. we're in an updating insertion.
655 iterator_for_children
=
656 symbol_db_engine_get_scope_members_by_symbol_id (dbe
, symbol_id
, -1,
660 if (iterator_for_children
== NULL
)
662 /* we don't have children */
666 /* hey there are some children here.. kill 'em all and put them on
672 GtkTreeIter child_iter
;
673 GtkTreeRowReference
*row_ref
;
674 SymbolDBEngineIteratorNode
*iter_node
;
676 iter_node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (iterator_for_children
);
679 symbol_db_engine_iterator_node_get_symbol_id (iter_node
);
681 row_ref
= g_tree_lookup (priv
->nodes_displayed
,
682 (gpointer
)curr_child_id
);
686 if (sdb_view_get_iter_from_row_ref (dbv
, row_ref
, &child_iter
) == FALSE
)
688 /* no node displayed found */
689 g_warning ("on_symbol_inserted (): row_ref something went wrong ?!");
693 /* put on waiting_for the subtree */
694 do_recurse_subtree_and_invalidate (dbv
, &child_iter
, symbol_id
);
695 } while (symbol_db_engine_iterator_move_next (iterator_for_children
)
698 g_object_unref (iterator_for_children
);
701 prepare_for_adding (dbv
, parent_symbol_id
, symbol_name
, symbol_id
, pixbuf
,
703 g_object_unref (iterator
);
708 do_recurse_subtree_and_remove (SymbolDBView
*dbv
,
709 GtkTreeIter
*parent_subtree_iter
)
712 const GdkPixbuf
*curr_pixbuf
;
714 gchar
*curr_symbol_name
;
716 SymbolDBViewPriv
*priv
;
718 g_return_if_fail (dbv
!= NULL
);
721 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
723 gtk_tree_model_get (GTK_TREE_MODEL (store
), parent_subtree_iter
,
724 COLUMN_SYMBOL_ID
, &curr_symbol_id
,
725 COLUMN_PIXBUF
, &curr_pixbuf
,
726 COLUMN_NAME
, &curr_symbol_name
, /* no strdup required */
729 while (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (store
), parent_subtree_iter
))
732 gtk_tree_model_iter_children (GTK_TREE_MODEL (store
), &child
, parent_subtree_iter
);
735 do_recurse_subtree_and_remove (dbv
, &child
);
738 gtk_tree_store_remove (store
, parent_subtree_iter
);
739 g_tree_remove (priv
->nodes_displayed
, (gpointer
) curr_symbol_id
);
741 /* don't forget to free this gchar */
742 g_free (curr_symbol_name
);
747 on_symbol_removed (SymbolDBEngine
*dbe
, gint symbol_id
, gpointer data
)
751 SymbolDBViewPriv
*priv
;
753 GtkTreeRowReference
*row_ref
;
755 dbv
= SYMBOL_DB_VIEW (data
);
757 g_return_if_fail (dbv
!= NULL
);
760 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
762 DEBUG_PRINT ("on_symbol_removed (): -global- %d", symbol_id
);
764 row_ref
= g_tree_lookup (priv
->nodes_displayed
, (gpointer
)symbol_id
);
765 if (sdb_view_get_iter_from_row_ref (dbv
, row_ref
, &iter
) == FALSE
)
770 do_recurse_subtree_and_remove (dbv
, &iter
);
774 * Add at most ONE dummy child to the parent_iter. This is done to let the parent_iter
775 * node be expandable.
776 * @param force If true a dummy symbol will be added even if it has no children on db.
779 sdb_view_do_add_hidden_dummy_child (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
780 GtkTreeIter
*parent_iter
, gint parent_symbol_id
,
783 SymbolDBEngineIterator
*child_iterator
;
785 SymbolDBViewPriv
*priv
;
787 g_return_if_fail (dbv
!= NULL
);
790 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
791 child_iterator
= symbol_db_engine_get_scope_members_by_symbol_id (dbe
,
795 SYMINFO_SIMPLE
| SYMINFO_ACCESS
| SYMINFO_KIND
);
797 if (child_iterator
!= NULL
|| force
== TRUE
)
799 /* hey we have something here... */
800 GtkTreeIter child_iter
;
802 gtk_tree_store_append (store
, &child_iter
, parent_iter
);
803 gtk_tree_store_set (store
, &child_iter
,
805 COLUMN_NAME
, _("Loading..."),
806 COLUMN_SYMBOL_ID
, DUMMY_SYMBOL_ID
,
810 g_object_unref (child_iterator
);
815 sdb_view_row_expanded_idle_destroy (gpointer data
)
817 NodeIdleExpand
*node_expand
;
821 g_return_if_fail (data
!= NULL
);
823 DEBUG_PRINT ("sdb_view_global_row_expanded_idle_destroy ()");
824 dbv
= node_expand
->dbv
;
825 dbe
= node_expand
->dbe
;
827 /* remove from the GTree the ids of the func expanding */
828 g_tree_remove (dbv
->priv
->expanding_gfunc_ids
,
829 (gpointer
)node_expand
->expanded_symbol_id
);
831 if (node_expand
->expanded_path
!= NULL
) {
832 gtk_tree_path_free (node_expand
->expanded_path
);
833 node_expand
->expanded_path
= NULL
;
835 g_object_unref (node_expand
->iterator
);
836 node_expand
->iterator
= NULL
;
837 g_free (node_expand
);
841 sdb_view_row_expanded_idle (gpointer data
)
843 NodeIdleExpand
*node_expand
;
846 SymbolDBEngineIterator
*iterator
;
847 const GdkPixbuf
*pixbuf
;
848 const gchar
* symbol_name
;
849 const gchar
* symbol_kind
;
850 const gchar
* symbol_access
;
853 SymbolDBEngineIteratorNode
*iter_node
;
855 GtkTreeRowReference
*curr_tree_row_ref
;
856 SymbolDBViewPriv
*priv
;
860 dbv
= node_expand
->dbv
;
861 iterator
= node_expand
->iterator
;
862 dbe
= node_expand
->dbe
;
865 if (iterator
== NULL
)
868 iter_node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (iterator
);
869 curr_symbol_id
= symbol_db_engine_iterator_node_get_symbol_id (iter_node
);
870 node
= g_tree_lookup (priv
->nodes_displayed
, (gpointer
)curr_symbol_id
);
874 /* already displayed */
875 return symbol_db_engine_iterator_move_next (iterator
);
878 symbol_name
= symbol_db_engine_iterator_node_get_symbol_name (iter_node
);
879 symbol_kind
= symbol_db_engine_iterator_node_get_symbol_extra_string (iter_node
,
881 symbol_access
= symbol_db_engine_iterator_node_get_symbol_extra_string (iter_node
,
883 pixbuf
= symbol_db_view_get_pixbuf (symbol_kind
, symbol_access
);
885 curr_tree_row_ref
= do_add_child_symbol_to_view (dbv
,
886 node_expand
->expanded_symbol_id
, pixbuf
,
887 symbol_name
, curr_symbol_id
);
888 if (curr_tree_row_ref
== NULL
)
890 return symbol_db_engine_iterator_move_next (iterator
);
893 /* we'll fake the gpointer to store an int */
894 g_tree_insert (priv
->nodes_displayed
, (gpointer
)curr_symbol_id
,
897 sdb_view_get_iter_from_row_ref (dbv
, curr_tree_row_ref
, &iter
);
899 /* check for children about this node... */
900 sdb_view_do_add_hidden_dummy_child (dbv
, dbe
, &iter
, curr_symbol_id
,
903 if (node_expand
->expanded_path
!= NULL
)
905 gtk_tree_view_expand_row (GTK_TREE_VIEW (dbv
),
906 node_expand
->expanded_path
,
908 gtk_tree_path_free (node_expand
->expanded_path
);
909 node_expand
->expanded_path
= NULL
;
912 if (symbol_db_engine_iterator_move_next (iterator
) == TRUE
)
917 if (g_tree_lookup (priv
->nodes_displayed
,
918 (gpointer
)-node_expand
->expanded_symbol_id
) == NULL
)
920 GtkTreeRowReference
*others_row_ref
;
921 GtkTreeIter others_dummy_node
;
922 others_row_ref
= do_add_child_symbol_to_view (dbv
,
923 node_expand
->expanded_symbol_id
,
924 symbol_db_view_get_pixbuf ("vars", "others"),
926 -node_expand
->expanded_symbol_id
);
928 /* insert a negative node ... */
929 g_tree_insert (priv
->nodes_displayed
,
930 (gpointer
)-node_expand
->expanded_symbol_id
,
933 /* ... and a dummy child */
934 sdb_view_get_iter_from_row_ref (dbv
, others_row_ref
, &others_dummy_node
);
936 sdb_view_do_add_hidden_dummy_child (dbv
, dbe
, &others_dummy_node
, 0,
945 sdb_view_namespace_row_expanded (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
946 GtkTreeIter
*expanded_iter
, gint expanded_symbol_id
)
948 SymbolDBViewPriv
*priv
;
949 SymbolDBEngineIterator
*iterator
;
951 GPtrArray
*filter_array
;
954 g_return_if_fail (dbv
!= NULL
);
957 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
959 DEBUG_PRINT ("sdb_view_namespace_row_expanded ");
961 /* check if there's another expanding idle_func running */
962 node
= g_tree_lookup (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
);
968 filter_array
= g_ptr_array_new ();
969 g_ptr_array_add (filter_array
, "class");
970 g_ptr_array_add (filter_array
, "struct");
972 /* get results from database */
973 iterator
= symbol_db_engine_get_scope_members_by_symbol_id_filtered (dbe
,
979 SYMINFO_SIMPLE
| SYMINFO_KIND
| SYMINFO_ACCESS
982 g_ptr_array_free (filter_array
, TRUE
);
984 if (iterator
!= NULL
)
986 NodeIdleExpand
*node_expand
;
989 node_expand
= g_new0 (NodeIdleExpand
, 1);
991 node_expand
->dbv
= dbv
;
992 node_expand
->iterator
= iterator
;
993 node_expand
->dbe
= dbe
;
994 node_expand
->expanded_path
=
995 gtk_tree_model_get_path (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
997 node_expand
->expanded_symbol_id
= expanded_symbol_id
;
999 /* be sure that the expanding process doesn't freeze the gui */
1000 idle_id
= g_idle_add_full (G_PRIORITY_LOW
,
1001 (GSourceFunc
) sdb_view_row_expanded_idle
,
1002 (gpointer
) node_expand
,
1003 (GDestroyNotify
) sdb_view_row_expanded_idle_destroy
);
1005 /* insert the idle_id into a g_tree */
1006 g_tree_insert (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
,
1013 sdb_view_global_row_expanded (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1014 GtkTreeIter
*expanded_iter
, gint expanded_symbol_id
)
1016 GtkTreeStore
*store
;
1017 SymbolDBViewPriv
*priv
;
1018 SymbolDBEngineIterator
*iterator
;
1019 GPtrArray
*filter_array
;
1021 g_return_if_fail (dbv
!= NULL
);
1025 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1027 filter_array
= g_ptr_array_new ();
1028 g_ptr_array_add (filter_array
, "class");
1029 g_ptr_array_add (filter_array
, "struct");
1031 DEBUG_PRINT ("sdb_view_global_row_expanded ()");
1033 /* check if there's another expanding idle_func running */
1034 node
= g_tree_lookup (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
);
1040 /* check for the presence of namespaces.
1041 * If that's the case then populate the root with a 'Global' node.
1043 iterator
= symbol_db_engine_get_global_members_filtered (dbe
, filter_array
, TRUE
,
1050 g_ptr_array_free (filter_array
, TRUE
);
1052 if (iterator
!= NULL
)
1054 NodeIdleExpand
*node_expand
;
1057 node_expand
= g_new0 (NodeIdleExpand
, 1);
1059 node_expand
->dbv
= dbv
;
1060 node_expand
->iterator
= iterator
;
1061 node_expand
->dbe
= dbe
;
1062 node_expand
->expanded_path
= gtk_tree_model_get_path (
1063 gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
1065 node_expand
->expanded_symbol_id
= expanded_symbol_id
;
1067 idle_id
= g_idle_add_full (G_PRIORITY_LOW
,
1068 (GSourceFunc
) sdb_view_row_expanded_idle
,
1069 (gpointer
) node_expand
,
1070 (GDestroyNotify
) sdb_view_row_expanded_idle_destroy
);
1072 /* insert the idle_id into a g_tree for (eventually) a later retrieval */
1073 DEBUG_PRINT ("Inserting into g_tree expanded_symbol_id %d and idle_id %d",
1074 expanded_symbol_id
, idle_id
);
1075 g_tree_insert (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
,
1081 sdb_view_vars_row_expanded (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1082 GtkTreeIter
*expanded_iter
, gint expanded_symbol_id
)
1084 SymbolDBViewPriv
*priv
;
1085 SymbolDBEngineIterator
*iterator
;
1086 GtkTreeStore
*store
;
1087 GPtrArray
*filter_array
;
1088 gint positive_symbol_expanded
;
1091 g_return_if_fail (dbv
!= NULL
);
1094 positive_symbol_expanded
= -expanded_symbol_id
;
1095 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1097 DEBUG_PRINT ("sdb_view_vars_row_expanded ()");
1099 /* check if there's another expanding idle_func running */
1100 node
= g_tree_lookup (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
);
1106 filter_array
= g_ptr_array_new ();
1107 g_ptr_array_add (filter_array
, "class");
1108 g_ptr_array_add (filter_array
, "struct");
1110 if (positive_symbol_expanded
== ROOT_GLOBAL
)
1112 iterator
= symbol_db_engine_get_global_members_filtered (dbe
, filter_array
,
1123 iterator
= symbol_db_engine_get_scope_members_by_symbol_id_filtered (dbe
,
1124 positive_symbol_expanded
,
1135 g_ptr_array_free (filter_array
, TRUE
);
1137 if (iterator
!= NULL
)
1139 NodeIdleExpand
*node_expand
;
1142 node_expand
= g_new0 (NodeIdleExpand
, 1);
1144 node_expand
->dbv
= dbv
;
1145 node_expand
->iterator
= iterator
;
1146 node_expand
->dbe
= dbe
;
1147 node_expand
->expanded_path
= gtk_tree_model_get_path (
1148 gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
1150 node_expand
->expanded_symbol_id
= expanded_symbol_id
;
1152 idle_id
= g_idle_add_full (G_PRIORITY_LOW
,
1153 (GSourceFunc
) sdb_view_row_expanded_idle
,
1154 (gpointer
) node_expand
,
1155 (GDestroyNotify
) sdb_view_row_expanded_idle_destroy
);
1157 /* insert the idle_id into a g_tree */
1158 g_tree_insert (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
,
1164 * Usually on a row expanded event we should perform the following steps:
1165 * 1. retrieve a list of scoped children.
1166 * 2. check if the nth children has already been displayed or not.
1167 * 3. if it isn't then append a child *and* check if that child has children itself.
1168 * using a dummy node we can achieve a performant population while setting an expand
1169 * mark on the child firstly appended.
1172 symbol_db_view_row_expanded (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1173 GtkTreeIter
*expanded_iter
)
1175 GtkTreeStore
*store
;
1176 gint expanded_symbol_id
;
1177 SymbolDBViewPriv
*priv
;
1178 SymbolDBEngineIterator
*iterator
;
1181 g_return_if_fail (dbv
!= NULL
);
1184 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1186 gtk_tree_model_get (GTK_TREE_MODEL (store
), expanded_iter
,
1187 COLUMN_SYMBOL_ID
, &expanded_symbol_id
, -1);
1189 /* remove the dummy item, if present */
1190 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (store
), expanded_iter
))
1194 gtk_tree_model_iter_children (GTK_TREE_MODEL (store
), &child
, expanded_iter
);
1196 gtk_tree_model_get (GTK_TREE_MODEL (store
), &child
,
1197 COLUMN_SYMBOL_ID
, &dummy_symbol
, -1);
1199 if (dummy_symbol
== DUMMY_SYMBOL_ID
)
1200 gtk_tree_store_remove (store
, &child
);
1203 /* Ok. Is the expanded node a 'namespace' one? A 'global' one? Or a
1204 * 'vars/etc' one? parse here the cases and if we're not there
1205 * go on with a classic expanding node algo.
1209 if (expanded_symbol_id
== ROOT_GLOBAL
)
1211 sdb_view_global_row_expanded (dbv
, dbe
, expanded_iter
, expanded_symbol_id
);
1216 /* To identify a vars/etc node we'll check if the expanded_symbol_id is negative.
1217 * If yes, we can have the parent namespace by making the id positive.
1219 if (expanded_symbol_id
< 0)
1221 sdb_view_vars_row_expanded (dbv
, dbe
, expanded_iter
, expanded_symbol_id
);
1226 /* Case namespace */
1227 iterator
= symbol_db_engine_get_symbol_info_by_id (dbe
, expanded_symbol_id
,
1229 if (iterator
!= NULL
)
1231 SymbolDBEngineIteratorNode
*iter_node
;
1232 const gchar
* symbol_kind
;
1234 iter_node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (iterator
);
1235 symbol_kind
= symbol_db_engine_iterator_node_get_symbol_extra_string (
1236 iter_node
, SYMINFO_KIND
);
1237 if (strcmp (symbol_kind
, "namespace") == 0)
1239 sdb_view_namespace_row_expanded (dbv
, dbe
, expanded_iter
,
1240 expanded_symbol_id
);
1241 g_object_unref (iterator
);
1244 g_object_unref (iterator
);
1247 /* Case Normal: go on with usual expanding */
1248 DEBUG_PRINT ("symbol_db_view_row_expanded (): expanded %d", expanded_symbol_id
);
1251 iterator
= symbol_db_engine_get_scope_members_by_symbol_id (dbe
,
1259 if (iterator
!= NULL
)
1262 gint curr_symbol_id
;
1263 SymbolDBEngineIteratorNode
*iter_node
;
1264 const GdkPixbuf
*pixbuf
;
1265 const gchar
* symbol_name
;
1266 GtkTreeIter child_iter
;
1268 GtkTreeRowReference
*child_row_ref
;
1271 iter_node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (iterator
);
1273 curr_symbol_id
= symbol_db_engine_iterator_node_get_symbol_id (iter_node
);
1276 * check if the curr_symbol_id is already displayed. In that case
1277 * skip to the next symbol
1279 node
= g_tree_lookup (priv
->nodes_displayed
, (gpointer
)curr_symbol_id
);
1287 /* ok we must display this symbol */
1288 pixbuf
= symbol_db_view_get_pixbuf (
1289 symbol_db_engine_iterator_node_get_symbol_extra_string (
1290 iter_node
, SYMINFO_KIND
),
1291 symbol_db_engine_iterator_node_get_symbol_extra_string (
1292 iter_node
, SYMINFO_ACCESS
));
1294 symbol_name
= symbol_db_engine_iterator_node_get_symbol_name (iter_node
);
1296 gtk_tree_store_append (store
, &child_iter
, expanded_iter
);
1298 gtk_tree_store_set (store
, &child_iter
,
1299 COLUMN_PIXBUF
, pixbuf
,
1300 COLUMN_NAME
, symbol_name
,
1301 COLUMN_SYMBOL_ID
, curr_symbol_id
,
1304 path
= gtk_tree_model_get_path (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
1306 child_row_ref
= gtk_tree_row_reference_new (
1307 gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)), path
);
1308 gtk_tree_path_free (path
);
1310 /* insert the just append row_ref into the GTree for a quick retrieval
1313 g_tree_insert (priv
->nodes_displayed
, (gpointer
)curr_symbol_id
,
1316 /* good. Let's check now for a child (B) of the just appended child (A).
1317 * Adding B (a dummy one for now) to A will make A expandable
1319 sdb_view_do_add_hidden_dummy_child (dbv
, dbe
, &child_iter
, curr_symbol_id
,
1322 } while (symbol_db_engine_iterator_move_next (iterator
) == TRUE
);
1324 g_object_unref (iterator
);
1327 /* force expand it */
1328 path
= gtk_tree_model_get_path (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
1330 gtk_tree_view_expand_row (GTK_TREE_VIEW (dbv
), path
, FALSE
);
1331 gtk_tree_path_free (path
);
1335 symbol_db_view_row_collapsed (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1336 GtkTreeIter
*collapsed_iter
)
1338 GtkTreeStore
*store
;
1339 gint collapsed_symbol_id
;
1340 SymbolDBViewPriv
*priv
;
1343 g_return_if_fail (dbv
!= NULL
);
1346 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1348 gtk_tree_model_get (GTK_TREE_MODEL (store
), collapsed_iter
,
1349 COLUMN_SYMBOL_ID
, &collapsed_symbol_id
, -1);
1351 /* do a quick check to see if the collapsed_symbol_id is listed into the
1352 * currently expanding symbols. If that's the case remove the gsource func.
1354 node
= g_tree_lookup (priv
->expanding_gfunc_ids
, (gpointer
)collapsed_symbol_id
);
1358 /* no expanding gfunc found. */
1362 g_source_remove ((gint
)node
);
1363 g_tree_remove (priv
->expanding_gfunc_ids
, (gpointer
)collapsed_symbol_id
);
1367 static GtkTreeStore
*
1368 sdb_view_create_new_store ()
1370 GtkTreeStore
*store
;
1371 store
= gtk_tree_store_new (COLUMN_MAX
, GDK_TYPE_PIXBUF
,
1372 G_TYPE_STRING
, G_TYPE_INT
);
1373 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store
),
1375 GTK_SORT_ASCENDING
);
1380 sdb_view_init (SymbolDBView
*object
)
1383 GtkTreeStore
*store
;
1384 GtkTreeViewColumn
*column
;
1385 GtkCellRenderer
*renderer
;
1386 GtkTreeSelection
*selection
;
1387 SymbolDBViewPriv
*priv
;
1389 dbv
= SYMBOL_DB_VIEW (object
);
1390 dbv
->priv
= g_new0 (SymbolDBViewPriv
, 1);
1394 /* initialize some priv data */
1395 priv
->insert_handler
= 0;
1396 priv
->remove_handler
= 0;
1397 priv
->nodes_displayed
= NULL
;
1398 priv
->waiting_for
= NULL
;
1400 priv
->row_ref_global
= NULL
;
1401 priv
->scan_end_handler
= 0;
1402 priv
->remove_handler
= 0;
1403 priv
->scan_end_handler
= 0;
1405 /* create a GTree where to store the row_expanding ids of the gfuncs.
1406 * we would be able then to g_source_remove them on row_collapsed
1408 priv
->expanding_gfunc_ids
= g_tree_new_full ((GCompareDataFunc
)>ree_compare_func
,
1411 /* Tree and his model */
1414 gtk_tree_view_set_model (GTK_TREE_VIEW (dbv
), GTK_TREE_MODEL (store
));
1415 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dbv
), FALSE
);
1417 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (dbv
));
1418 gtk_tree_selection_set_mode (selection
, GTK_SELECTION_SINGLE
);
1420 /* search through the tree interactively */
1421 gtk_tree_view_set_search_column (GTK_TREE_VIEW (dbv
), COLUMN_NAME
);
1422 gtk_tree_view_set_enable_search (GTK_TREE_VIEW (dbv
), TRUE
);
1425 column
= gtk_tree_view_column_new ();
1426 gtk_tree_view_column_set_sizing (column
,
1427 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1428 gtk_tree_view_column_set_title (column
, _("Symbol"));
1430 renderer
= gtk_cell_renderer_pixbuf_new ();
1431 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1432 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
1435 renderer
= gtk_cell_renderer_text_new ();
1436 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
1437 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
1440 gtk_tree_view_append_column (GTK_TREE_VIEW (dbv
), column
);
1441 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (dbv
), column
);
1446 sdb_view_finalize (GObject
*object
)
1448 SymbolDBView
*view
= SYMBOL_DB_VIEW (object
);
1449 SymbolDBViewPriv
*priv
= view
->priv
;
1451 DEBUG_PRINT ("finalizing symbol_db_view ()");
1453 symbol_db_view_clear_cache (view
);
1455 if (priv
->expanding_gfunc_ids
)
1456 g_tree_destroy (priv
->expanding_gfunc_ids
);
1460 /* dbe must be freed outside. */
1461 G_OBJECT_CLASS (parent_class
)->finalize (object
);
1465 sdb_view_class_init (SymbolDBViewClass
*klass
)
1467 SymbolDBViewClass
*sdbc
;
1468 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
1469 parent_class
= g_type_class_peek_parent (klass
);
1471 sdbc
= SYMBOL_DB_VIEW_CLASS (klass
);
1472 object_class
->finalize
= sdb_view_finalize
;
1476 symbol_db_view_get_type (void)
1478 static GType obj_type
= 0;
1482 static const GTypeInfo obj_info
= {
1483 sizeof (SymbolDBViewClass
),
1484 (GBaseInitFunc
) NULL
,
1485 (GBaseFinalizeFunc
) NULL
,
1486 (GClassInitFunc
) sdb_view_class_init
,
1487 (GClassFinalizeFunc
) NULL
,
1488 NULL
, /* class_data */
1489 sizeof (SymbolDBViewClass
),
1490 0, /* n_preallocs */
1491 (GInstanceInitFunc
) sdb_view_init
,
1492 NULL
/* value_table */
1494 obj_type
= g_type_register_static (GTK_TYPE_TREE_VIEW
,
1502 #define CREATE_SYM_ICON(N, F) \
1503 pix_file = anjuta_res_get_pixmap_file (F); \
1504 g_hash_table_insert (pixbufs_hash, \
1506 gdk_pixbuf_new_from_file (pix_file, NULL)); \
1510 sdb_view_load_symbol_pixbufs ()
1514 if (pixbufs_hash
!= NULL
)
1516 /* we already have loaded it */
1520 pixbufs_hash
= g_hash_table_new (g_str_hash
, g_str_equal
);
1522 CREATE_SYM_ICON ("class", "Icons.16x16.Class");
1523 CREATE_SYM_ICON ("enum", "Icons.16x16.Enum");
1524 CREATE_SYM_ICON ("enumerator", "Icons.16x16.Enum");
1525 CREATE_SYM_ICON ("function", "Icons.16x16.Method");
1526 CREATE_SYM_ICON ("interface", "Icons.16x16.Interface");
1527 CREATE_SYM_ICON ("macro", "Icons.16x16.Field");
1528 CREATE_SYM_ICON ("namespace", "Icons.16x16.NameSpace");
1529 CREATE_SYM_ICON ("none", "Icons.16x16.Literal");
1530 CREATE_SYM_ICON ("struct", "Icons.16x16.ProtectedStruct");
1531 CREATE_SYM_ICON ("typedef", "Icons.16x16.Reference");
1532 CREATE_SYM_ICON ("union", "Icons.16x16.PrivateStruct");
1533 CREATE_SYM_ICON ("variable", "Icons.16x16.Literal");
1534 CREATE_SYM_ICON ("prototype", "Icons.16x16.Interface");
1536 CREATE_SYM_ICON ("privateclass", "Icons.16x16.PrivateClass");
1537 CREATE_SYM_ICON ("privateenum", "Icons.16x16.PrivateEnum");
1538 CREATE_SYM_ICON ("privatefield", "Icons.16x16.PrivateField");
1539 CREATE_SYM_ICON ("privatefunction", "Icons.16x16.PrivateMethod");
1540 CREATE_SYM_ICON ("privateinterface", "Icons.16x16.PrivateInterface");
1541 CREATE_SYM_ICON ("privatemember", "Icons.16x16.PrivateProperty");
1542 CREATE_SYM_ICON ("privatemethod", "Icons.16x16.PrivateMethod");
1543 CREATE_SYM_ICON ("privateproperty", "Icons.16x16.PrivateProperty");
1544 CREATE_SYM_ICON ("privatestruct", "Icons.16x16.PrivateStruct");
1545 CREATE_SYM_ICON ("privateprototype", "Icons.16x16.PrivateInterface");
1547 CREATE_SYM_ICON ("protectedclass", "Icons.16x16.ProtectedClass");
1548 CREATE_SYM_ICON ("protectedenum", "Icons.16x16.ProtectedEnum");
1549 CREATE_SYM_ICON ("protectedfield", "Icons.16x16.ProtectedField");
1550 CREATE_SYM_ICON ("protectedmember", "Icons.16x16.ProtectedProperty");
1551 CREATE_SYM_ICON ("protectedmethod", "Icons.16x16.ProtectedMethod");
1552 CREATE_SYM_ICON ("protectedproperty", "Icons.16x16.ProtectedProperty");
1553 CREATE_SYM_ICON ("publicprototype", "Icons.16x16.ProtectedInterface");
1555 CREATE_SYM_ICON ("publicclass", "Icons.16x16.Class");
1556 CREATE_SYM_ICON ("publicenum", "Icons.16x16.Enum");
1557 CREATE_SYM_ICON ("publicfunction", "Icons.16x16.Method");
1558 CREATE_SYM_ICON ("publicmember", "Icons.16x16.Method");
1559 CREATE_SYM_ICON ("publicproperty", "Icons.16x16.Property");
1560 CREATE_SYM_ICON ("publicstruct", "Icons.16x16.Struct");
1561 CREATE_SYM_ICON ("publicprototype", "Icons.16x16.Interface");
1564 CREATE_SYM_ICON ("othersvars", "Icons.16x16.Event");
1565 CREATE_SYM_ICON ("globalglobal", "Icons.16x16.Event");
1569 * @return The pixbufs. It will initialize pixbufs first if they weren't before
1570 * @param node_access can be NULL.
1573 symbol_db_view_get_pixbuf (const gchar
*node_type
, const gchar
*node_access
)
1579 sdb_view_load_symbol_pixbufs ();
1582 g_return_val_if_fail (node_type
!= NULL
, NULL
);
1584 /* is there a better/quicker method to retrieve pixbufs? */
1585 if (node_access
!= NULL
)
1587 search_node
= g_strdup_printf ("%s%s", node_access
, node_type
);
1591 /* we will not free search_node gchar, so casting here is ok. */
1592 search_node
= (gchar
*)node_type
;
1594 pix
= GDK_PIXBUF (g_hash_table_lookup (pixbufs_hash
, search_node
));
1598 g_free (search_node
);
1603 DEBUG_PRINT ("symbol_db_view_get_pixbuf (): no pixbuf for %s %s",
1604 node_type
, node_access
);
1612 symbol_db_view_new (void)
1614 return GTK_WIDGET (g_object_new (SYMBOL_TYPE_DB_VIEW
, NULL
));
1618 symbol_db_view_get_file_and_line (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1619 GtkTreeIter
* iter
, gint
*OUT_line
, gchar
**OUT_file
)
1621 GtkTreeStore
*store
;
1623 g_return_val_if_fail (dbv
!= NULL
, FALSE
);
1624 g_return_val_if_fail (dbe
!= NULL
, FALSE
);
1625 g_return_val_if_fail (iter
!= NULL
, FALSE
);
1627 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1632 const gchar
* relative_file
;
1633 SymbolDBEngineIteratorNode
*node
;
1635 gtk_tree_model_get (GTK_TREE_MODEL
1637 COLUMN_SYMBOL_ID
, &symbol_id
, -1);
1639 /* getting line at click time with a query is faster than updating every
1640 * entry in the gtktreeview. We can be sure that the db is in a consistent
1641 * state and has all the last infos
1643 node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (
1644 symbol_db_engine_get_symbol_info_by_id (dbe
, symbol_id
,
1646 SYMINFO_FILE_PATH
));
1649 *OUT_line
= symbol_db_engine_iterator_node_get_symbol_file_pos (node
);
1651 symbol_db_engine_iterator_node_get_symbol_extra_string (node
,
1653 *OUT_file
= symbol_db_engine_get_full_local_path (dbe
, relative_file
);
1662 sdb_view_build_and_display_base_tree (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
)
1664 GtkTreeStore
*store
;
1665 SymbolDBViewPriv
*priv
;
1666 SymbolDBEngineIterator
*iterator
;
1667 gboolean we_have_namespaces
;
1668 GPtrArray
*filter_array
;
1669 GtkTreeRowReference
*global_tree_row_ref
;
1670 GtkTreeIter global_child_iter
;
1671 const GdkPixbuf
*global_pixbuf
;
1673 g_return_if_fail (dbv
!= NULL
);
1677 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1679 we_have_namespaces
= FALSE
;
1681 filter_array
= g_ptr_array_new ();
1682 g_ptr_array_add (filter_array
, "namespace");
1684 /* check for the presence of namespaces.
1685 * If that's the case then populate the root with a 'Global' node.
1687 iterator
= symbol_db_engine_get_global_members_filtered (dbe
, filter_array
, TRUE
,
1694 g_ptr_array_free (filter_array
, TRUE
);
1696 if (iterator
!= NULL
)
1698 we_have_namespaces
= TRUE
;
1701 gint curr_symbol_id
;
1702 SymbolDBEngineIteratorNode
*iter_node
;
1703 const GdkPixbuf
*pixbuf
;
1704 const gchar
* symbol_name
;
1705 GtkTreeRowReference
*curr_tree_row_ref
;
1706 GtkTreeIter child_iter
;
1708 iter_node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (iterator
);
1710 curr_symbol_id
= symbol_db_engine_iterator_node_get_symbol_id (iter_node
);
1712 pixbuf
= symbol_db_view_get_pixbuf (
1713 symbol_db_engine_iterator_node_get_symbol_extra_string (
1714 iter_node
, SYMINFO_KIND
),
1715 symbol_db_engine_iterator_node_get_symbol_extra_string (
1716 iter_node
, SYMINFO_ACCESS
));
1718 symbol_name
= symbol_db_engine_iterator_node_get_symbol_name (iter_node
);
1720 curr_tree_row_ref
= do_add_root_symbol_to_view (dbv
, pixbuf
,
1721 symbol_name
, curr_symbol_id
);
1722 if (curr_tree_row_ref
== NULL
)
1727 /* we'll fake the gpointer to store an int */
1728 g_tree_insert (priv
->nodes_displayed
, (gpointer
)curr_symbol_id
,
1731 if (sdb_view_get_iter_from_row_ref (dbv
, curr_tree_row_ref
,
1732 &child_iter
) == FALSE
)
1734 g_warning ("sdb_view_build_and_display_base_tree (): something "
1738 /* add a dummy child */
1739 sdb_view_do_add_hidden_dummy_child (dbv
, dbe
,
1740 &child_iter
, curr_symbol_id
, FALSE
);
1742 } while (symbol_db_engine_iterator_move_next (iterator
) == TRUE
);
1744 g_object_unref (iterator
);
1748 * Good. Add a 'Global' node to the store.
1750 global_pixbuf
= symbol_db_view_get_pixbuf ("global", "global");
1752 global_tree_row_ref
= do_add_root_symbol_to_view (dbv
, global_pixbuf
,
1753 "Global", ROOT_GLOBAL
);
1755 if (global_tree_row_ref
== NULL
)
1759 g_tree_insert (priv
->nodes_displayed
, (gpointer
)ROOT_GLOBAL
,
1760 global_tree_row_ref
);
1762 if (sdb_view_get_iter_from_row_ref (dbv
, global_tree_row_ref
,
1763 &global_child_iter
) == FALSE
)
1765 g_warning ("sdb_view_build_and_display_base_tree (): cannot retrieve iter for "
1770 /* add a dummy child */
1771 sdb_view_do_add_hidden_dummy_child (dbv
, dbe
,
1772 &global_child_iter
, ROOT_GLOBAL
, TRUE
);
1776 symbol_db_view_recv_signals_from_engine (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1777 gboolean enable_status
)
1779 SymbolDBViewPriv
*priv
;
1781 g_return_if_fail (dbv
!= NULL
);
1784 if (enable_status
== TRUE
)
1786 gtk_widget_set_sensitive (GTK_WIDGET (dbv
), TRUE
);
1787 /* connect some signals */
1788 if (priv
->insert_handler
<= 0)
1790 priv
->insert_handler
= g_signal_connect (G_OBJECT (dbe
), "symbol-inserted",
1791 G_CALLBACK (on_symbol_inserted
), dbv
);
1794 if (priv
->remove_handler
<= 0)
1796 priv
->remove_handler
= g_signal_connect (G_OBJECT (dbe
), "symbol-removed",
1797 G_CALLBACK (on_symbol_removed
), dbv
);
1800 if (priv
->scan_end_handler
<= 0)
1802 priv
->scan_end_handler
= g_signal_connect (G_OBJECT (dbe
), "scan-end",
1803 G_CALLBACK (on_scan_end
), dbv
);
1806 else /* disconnect them, if they were ever connected before */
1808 gtk_widget_set_sensitive (GTK_WIDGET (dbv
), FALSE
);
1810 if (priv
->insert_handler
>= 0)
1812 g_signal_handler_disconnect (G_OBJECT (dbe
), priv
->insert_handler
);
1813 priv
->insert_handler
= 0;
1816 if (priv
->remove_handler
>= 0)
1818 g_signal_handler_disconnect (G_OBJECT (dbe
), priv
->remove_handler
);
1819 priv
->remove_handler
= 0;
1822 if (priv
->scan_end_handler
>= 0)
1824 g_signal_handler_disconnect (G_OBJECT (dbe
), priv
->scan_end_handler
);
1825 priv
->scan_end_handler
= 0;
1831 symbol_db_view_open (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
)
1833 SymbolDBViewPriv
*priv
;
1834 GtkTreeStore
*store
;
1836 g_return_if_fail (dbv
!= NULL
);
1840 DEBUG_PRINT ("symbol_db_view_open ()");
1841 symbol_db_view_clear_cache (dbv
);
1843 store
= sdb_view_create_new_store ();
1844 gtk_tree_view_set_model (GTK_TREE_VIEW (dbv
), GTK_TREE_MODEL (store
));
1846 priv
->nodes_displayed
= g_tree_new_full ((GCompareDataFunc
)>ree_compare_func
,
1849 (GDestroyNotify
)>k_tree_row_reference_free
);
1851 priv
->waiting_for
= g_tree_new_full ((GCompareDataFunc
)>ree_compare_func
,
1856 sdb_view_build_and_display_base_tree (dbv
, dbe
);