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
,
984 g_ptr_array_free (filter_array
, TRUE
);
986 if (iterator
!= NULL
)
988 NodeIdleExpand
*node_expand
;
991 node_expand
= g_new0 (NodeIdleExpand
, 1);
993 node_expand
->dbv
= dbv
;
994 node_expand
->iterator
= iterator
;
995 node_expand
->dbe
= dbe
;
996 node_expand
->expanded_path
=
997 gtk_tree_model_get_path (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
999 node_expand
->expanded_symbol_id
= expanded_symbol_id
;
1001 /* be sure that the expanding process doesn't freeze the gui */
1002 idle_id
= g_idle_add_full (G_PRIORITY_LOW
,
1003 (GSourceFunc
) sdb_view_row_expanded_idle
,
1004 (gpointer
) node_expand
,
1005 (GDestroyNotify
) sdb_view_row_expanded_idle_destroy
);
1007 /* insert the idle_id into a g_tree */
1008 g_tree_insert (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
,
1015 sdb_view_global_row_expanded (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1016 GtkTreeIter
*expanded_iter
, gint expanded_symbol_id
)
1018 GtkTreeStore
*store
;
1019 SymbolDBViewPriv
*priv
;
1020 SymbolDBEngineIterator
*iterator
;
1021 GPtrArray
*filter_array
;
1023 g_return_if_fail (dbv
!= NULL
);
1027 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1029 DEBUG_PRINT ("sdb_view_global_row_expanded ()");
1031 /* check if there's another expanding idle_func running */
1032 node
= g_tree_lookup (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
);
1038 filter_array
= g_ptr_array_new ();
1039 g_ptr_array_add (filter_array
, "class");
1040 g_ptr_array_add (filter_array
, "struct");
1042 /* check for the presence of namespaces.
1043 * If that's the case then populate the root with a 'Global' node.
1045 iterator
= symbol_db_engine_get_global_members_filtered (dbe
, filter_array
,
1053 g_ptr_array_free (filter_array
, TRUE
);
1055 if (iterator
!= NULL
)
1057 NodeIdleExpand
*node_expand
;
1060 node_expand
= g_new0 (NodeIdleExpand
, 1);
1062 node_expand
->dbv
= dbv
;
1063 node_expand
->iterator
= iterator
;
1064 node_expand
->dbe
= dbe
;
1065 node_expand
->expanded_path
= gtk_tree_model_get_path (
1066 gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
1068 node_expand
->expanded_symbol_id
= expanded_symbol_id
;
1070 idle_id
= g_idle_add_full (G_PRIORITY_LOW
,
1071 (GSourceFunc
) sdb_view_row_expanded_idle
,
1072 (gpointer
) node_expand
,
1073 (GDestroyNotify
) sdb_view_row_expanded_idle_destroy
);
1075 /* insert the idle_id into a g_tree for (eventually) a later retrieval */
1076 DEBUG_PRINT ("Inserting into g_tree expanded_symbol_id %d and idle_id %d",
1077 expanded_symbol_id
, idle_id
);
1078 g_tree_insert (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
,
1084 sdb_view_vars_row_expanded (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1085 GtkTreeIter
*expanded_iter
, gint expanded_symbol_id
)
1087 SymbolDBViewPriv
*priv
;
1088 SymbolDBEngineIterator
*iterator
;
1089 GtkTreeStore
*store
;
1090 GPtrArray
*filter_array
;
1091 gint positive_symbol_expanded
;
1094 g_return_if_fail (dbv
!= NULL
);
1097 positive_symbol_expanded
= -expanded_symbol_id
;
1098 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1100 DEBUG_PRINT ("sdb_view_vars_row_expanded ()");
1102 /* check if there's another expanding idle_func running */
1103 node
= g_tree_lookup (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
);
1109 filter_array
= g_ptr_array_new ();
1110 g_ptr_array_add (filter_array
, "class");
1111 g_ptr_array_add (filter_array
, "struct");
1113 if (positive_symbol_expanded
== ROOT_GLOBAL
)
1115 iterator
= symbol_db_engine_get_global_members_filtered (dbe
, filter_array
,
1126 iterator
= symbol_db_engine_get_scope_members_by_symbol_id_filtered (dbe
,
1127 positive_symbol_expanded
,
1138 g_ptr_array_free (filter_array
, TRUE
);
1140 if (iterator
!= NULL
)
1142 NodeIdleExpand
*node_expand
;
1145 node_expand
= g_new0 (NodeIdleExpand
, 1);
1147 node_expand
->dbv
= dbv
;
1148 node_expand
->iterator
= iterator
;
1149 node_expand
->dbe
= dbe
;
1150 node_expand
->expanded_path
= gtk_tree_model_get_path (
1151 gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
1153 node_expand
->expanded_symbol_id
= expanded_symbol_id
;
1155 idle_id
= g_idle_add_full (G_PRIORITY_LOW
,
1156 (GSourceFunc
) sdb_view_row_expanded_idle
,
1157 (gpointer
) node_expand
,
1158 (GDestroyNotify
) sdb_view_row_expanded_idle_destroy
);
1160 /* insert the idle_id into a g_tree */
1161 g_tree_insert (priv
->expanding_gfunc_ids
, (gpointer
)expanded_symbol_id
,
1167 * Usually on a row expanded event we should perform the following steps:
1168 * 1. retrieve a list of scoped children.
1169 * 2. check if the nth children has already been displayed or not.
1170 * 3. if it isn't then append a child *and* check if that child has children itself.
1171 * using a dummy node we can achieve a performant population while setting an expand
1172 * mark on the child firstly appended.
1175 symbol_db_view_row_expanded (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1176 GtkTreeIter
*expanded_iter
)
1178 GtkTreeStore
*store
;
1179 gint expanded_symbol_id
;
1180 SymbolDBViewPriv
*priv
;
1181 SymbolDBEngineIterator
*iterator
;
1184 g_return_if_fail (dbv
!= NULL
);
1187 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1189 gtk_tree_model_get (GTK_TREE_MODEL (store
), expanded_iter
,
1190 COLUMN_SYMBOL_ID
, &expanded_symbol_id
, -1);
1192 /* remove the dummy item, if present */
1193 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (store
), expanded_iter
))
1197 gtk_tree_model_iter_children (GTK_TREE_MODEL (store
), &child
, expanded_iter
);
1199 gtk_tree_model_get (GTK_TREE_MODEL (store
), &child
,
1200 COLUMN_SYMBOL_ID
, &dummy_symbol
, -1);
1202 if (dummy_symbol
== DUMMY_SYMBOL_ID
)
1203 gtk_tree_store_remove (store
, &child
);
1206 /* Ok. Is the expanded node a 'namespace' one? A 'global' one? Or a
1207 * 'vars/etc' one? parse here the cases and if we're not there
1208 * go on with a classic expanding node algo.
1212 if (expanded_symbol_id
== ROOT_GLOBAL
)
1214 sdb_view_global_row_expanded (dbv
, dbe
, expanded_iter
, expanded_symbol_id
);
1219 /* To identify a vars/etc node we'll check if the expanded_symbol_id is negative.
1220 * If yes, we can have the parent namespace by making the id positive.
1222 if (expanded_symbol_id
< 0)
1224 sdb_view_vars_row_expanded (dbv
, dbe
, expanded_iter
, expanded_symbol_id
);
1229 /* Case namespace */
1230 iterator
= symbol_db_engine_get_symbol_info_by_id (dbe
, expanded_symbol_id
,
1232 if (iterator
!= NULL
)
1234 SymbolDBEngineIteratorNode
*iter_node
;
1235 const gchar
* symbol_kind
;
1237 iter_node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (iterator
);
1238 symbol_kind
= symbol_db_engine_iterator_node_get_symbol_extra_string (
1239 iter_node
, SYMINFO_KIND
);
1240 if (strcmp (symbol_kind
, "namespace") == 0)
1242 sdb_view_namespace_row_expanded (dbv
, dbe
, expanded_iter
,
1243 expanded_symbol_id
);
1244 g_object_unref (iterator
);
1247 g_object_unref (iterator
);
1250 /* Case Normal: go on with usual expanding */
1251 DEBUG_PRINT ("symbol_db_view_row_expanded (): expanded %d", expanded_symbol_id
);
1254 iterator
= symbol_db_engine_get_scope_members_by_symbol_id (dbe
,
1262 if (iterator
!= NULL
)
1265 gint curr_symbol_id
;
1266 SymbolDBEngineIteratorNode
*iter_node
;
1267 const GdkPixbuf
*pixbuf
;
1268 const gchar
* symbol_name
;
1269 GtkTreeIter child_iter
;
1271 GtkTreeRowReference
*child_row_ref
;
1274 iter_node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (iterator
);
1276 curr_symbol_id
= symbol_db_engine_iterator_node_get_symbol_id (iter_node
);
1279 * check if the curr_symbol_id is already displayed. In that case
1280 * skip to the next symbol
1282 node
= g_tree_lookup (priv
->nodes_displayed
, (gpointer
)curr_symbol_id
);
1290 /* ok we must display this symbol */
1291 pixbuf
= symbol_db_view_get_pixbuf (
1292 symbol_db_engine_iterator_node_get_symbol_extra_string (
1293 iter_node
, SYMINFO_KIND
),
1294 symbol_db_engine_iterator_node_get_symbol_extra_string (
1295 iter_node
, SYMINFO_ACCESS
));
1297 symbol_name
= symbol_db_engine_iterator_node_get_symbol_name (iter_node
);
1299 gtk_tree_store_append (store
, &child_iter
, expanded_iter
);
1301 gtk_tree_store_set (store
, &child_iter
,
1302 COLUMN_PIXBUF
, pixbuf
,
1303 COLUMN_NAME
, symbol_name
,
1304 COLUMN_SYMBOL_ID
, curr_symbol_id
,
1307 path
= gtk_tree_model_get_path (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
1309 child_row_ref
= gtk_tree_row_reference_new (
1310 gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)), path
);
1311 gtk_tree_path_free (path
);
1313 /* insert the just append row_ref into the GTree for a quick retrieval
1316 g_tree_insert (priv
->nodes_displayed
, (gpointer
)curr_symbol_id
,
1319 /* good. Let's check now for a child (B) of the just appended child (A).
1320 * Adding B (a dummy one for now) to A will make A expandable
1322 sdb_view_do_add_hidden_dummy_child (dbv
, dbe
, &child_iter
, curr_symbol_id
,
1325 } while (symbol_db_engine_iterator_move_next (iterator
) == TRUE
);
1327 g_object_unref (iterator
);
1330 /* force expand it */
1331 path
= gtk_tree_model_get_path (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)),
1333 gtk_tree_view_expand_row (GTK_TREE_VIEW (dbv
), path
, FALSE
);
1334 gtk_tree_path_free (path
);
1338 symbol_db_view_row_collapsed (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1339 GtkTreeIter
*collapsed_iter
)
1341 GtkTreeStore
*store
;
1342 gint collapsed_symbol_id
;
1343 SymbolDBViewPriv
*priv
;
1346 g_return_if_fail (dbv
!= NULL
);
1349 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1351 gtk_tree_model_get (GTK_TREE_MODEL (store
), collapsed_iter
,
1352 COLUMN_SYMBOL_ID
, &collapsed_symbol_id
, -1);
1354 /* do a quick check to see if the collapsed_symbol_id is listed into the
1355 * currently expanding symbols. If that's the case remove the gsource func.
1357 node
= g_tree_lookup (priv
->expanding_gfunc_ids
, (gpointer
)collapsed_symbol_id
);
1361 /* no expanding gfunc found. */
1365 g_source_remove ((gint
)node
);
1366 g_tree_remove (priv
->expanding_gfunc_ids
, (gpointer
)collapsed_symbol_id
);
1370 static GtkTreeStore
*
1371 sdb_view_create_new_store ()
1373 GtkTreeStore
*store
;
1374 store
= gtk_tree_store_new (COLUMN_MAX
, GDK_TYPE_PIXBUF
,
1375 G_TYPE_STRING
, G_TYPE_INT
);
1376 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store
),
1378 GTK_SORT_ASCENDING
);
1383 sdb_view_init (SymbolDBView
*object
)
1386 GtkTreeStore
*store
;
1387 GtkTreeViewColumn
*column
;
1388 GtkCellRenderer
*renderer
;
1389 GtkTreeSelection
*selection
;
1390 SymbolDBViewPriv
*priv
;
1392 dbv
= SYMBOL_DB_VIEW (object
);
1393 dbv
->priv
= g_new0 (SymbolDBViewPriv
, 1);
1397 /* initialize some priv data */
1398 priv
->insert_handler
= 0;
1399 priv
->remove_handler
= 0;
1400 priv
->nodes_displayed
= NULL
;
1401 priv
->waiting_for
= NULL
;
1403 priv
->row_ref_global
= NULL
;
1404 priv
->scan_end_handler
= 0;
1405 priv
->remove_handler
= 0;
1406 priv
->scan_end_handler
= 0;
1408 /* create a GTree where to store the row_expanding ids of the gfuncs.
1409 * we would be able then to g_source_remove them on row_collapsed
1411 priv
->expanding_gfunc_ids
= g_tree_new_full ((GCompareDataFunc
)>ree_compare_func
,
1414 /* Tree and his model */
1417 gtk_tree_view_set_model (GTK_TREE_VIEW (dbv
), GTK_TREE_MODEL (store
));
1418 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dbv
), FALSE
);
1420 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (dbv
));
1421 gtk_tree_selection_set_mode (selection
, GTK_SELECTION_SINGLE
);
1423 /* search through the tree interactively */
1424 gtk_tree_view_set_search_column (GTK_TREE_VIEW (dbv
), COLUMN_NAME
);
1425 gtk_tree_view_set_enable_search (GTK_TREE_VIEW (dbv
), TRUE
);
1428 column
= gtk_tree_view_column_new ();
1429 gtk_tree_view_column_set_sizing (column
,
1430 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1431 gtk_tree_view_column_set_title (column
, _("Symbol"));
1433 renderer
= gtk_cell_renderer_pixbuf_new ();
1434 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1435 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
1438 renderer
= gtk_cell_renderer_text_new ();
1439 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
1440 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
1443 gtk_tree_view_append_column (GTK_TREE_VIEW (dbv
), column
);
1444 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (dbv
), column
);
1449 sdb_view_finalize (GObject
*object
)
1451 SymbolDBView
*view
= SYMBOL_DB_VIEW (object
);
1452 SymbolDBViewPriv
*priv
= view
->priv
;
1454 DEBUG_PRINT ("finalizing symbol_db_view ()");
1456 symbol_db_view_clear_cache (view
);
1458 if (priv
->expanding_gfunc_ids
)
1459 g_tree_destroy (priv
->expanding_gfunc_ids
);
1463 /* dbe must be freed outside. */
1464 G_OBJECT_CLASS (parent_class
)->finalize (object
);
1468 sdb_view_class_init (SymbolDBViewClass
*klass
)
1470 SymbolDBViewClass
*sdbc
;
1471 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
1472 parent_class
= g_type_class_peek_parent (klass
);
1474 sdbc
= SYMBOL_DB_VIEW_CLASS (klass
);
1475 object_class
->finalize
= sdb_view_finalize
;
1479 symbol_db_view_get_type (void)
1481 static GType obj_type
= 0;
1485 static const GTypeInfo obj_info
= {
1486 sizeof (SymbolDBViewClass
),
1487 (GBaseInitFunc
) NULL
,
1488 (GBaseFinalizeFunc
) NULL
,
1489 (GClassInitFunc
) sdb_view_class_init
,
1490 (GClassFinalizeFunc
) NULL
,
1491 NULL
, /* class_data */
1492 sizeof (SymbolDBViewClass
),
1493 0, /* n_preallocs */
1494 (GInstanceInitFunc
) sdb_view_init
,
1495 NULL
/* value_table */
1497 obj_type
= g_type_register_static (GTK_TYPE_TREE_VIEW
,
1505 #define CREATE_SYM_ICON(N, F) \
1506 pix_file = anjuta_res_get_pixmap_file (F); \
1507 g_hash_table_insert (pixbufs_hash, \
1509 gdk_pixbuf_new_from_file (pix_file, NULL)); \
1513 sdb_view_load_symbol_pixbufs ()
1517 if (pixbufs_hash
!= NULL
)
1519 /* we already have loaded it */
1523 pixbufs_hash
= g_hash_table_new (g_str_hash
, g_str_equal
);
1525 CREATE_SYM_ICON ("class", "Icons.16x16.Class");
1526 CREATE_SYM_ICON ("enum", "Icons.16x16.Enum");
1527 CREATE_SYM_ICON ("enumerator", "Icons.16x16.Enum");
1528 CREATE_SYM_ICON ("function", "Icons.16x16.Method");
1529 CREATE_SYM_ICON ("interface", "Icons.16x16.Interface");
1530 CREATE_SYM_ICON ("macro", "Icons.16x16.Field");
1531 CREATE_SYM_ICON ("namespace", "Icons.16x16.NameSpace");
1532 CREATE_SYM_ICON ("none", "Icons.16x16.Literal");
1533 CREATE_SYM_ICON ("struct", "Icons.16x16.ProtectedStruct");
1534 CREATE_SYM_ICON ("typedef", "Icons.16x16.Reference");
1535 CREATE_SYM_ICON ("union", "Icons.16x16.PrivateStruct");
1536 CREATE_SYM_ICON ("variable", "Icons.16x16.Literal");
1537 CREATE_SYM_ICON ("prototype", "Icons.16x16.Interface");
1539 CREATE_SYM_ICON ("privateclass", "Icons.16x16.PrivateClass");
1540 CREATE_SYM_ICON ("privateenum", "Icons.16x16.PrivateEnum");
1541 CREATE_SYM_ICON ("privatefield", "Icons.16x16.PrivateField");
1542 CREATE_SYM_ICON ("privatefunction", "Icons.16x16.PrivateMethod");
1543 CREATE_SYM_ICON ("privateinterface", "Icons.16x16.PrivateInterface");
1544 CREATE_SYM_ICON ("privatemember", "Icons.16x16.PrivateProperty");
1545 CREATE_SYM_ICON ("privatemethod", "Icons.16x16.PrivateMethod");
1546 CREATE_SYM_ICON ("privateproperty", "Icons.16x16.PrivateProperty");
1547 CREATE_SYM_ICON ("privatestruct", "Icons.16x16.PrivateStruct");
1548 CREATE_SYM_ICON ("privateprototype", "Icons.16x16.PrivateInterface");
1550 CREATE_SYM_ICON ("protectedclass", "Icons.16x16.ProtectedClass");
1551 CREATE_SYM_ICON ("protectedenum", "Icons.16x16.ProtectedEnum");
1552 CREATE_SYM_ICON ("protectedfield", "Icons.16x16.ProtectedField");
1553 CREATE_SYM_ICON ("protectedmember", "Icons.16x16.ProtectedProperty");
1554 CREATE_SYM_ICON ("protectedmethod", "Icons.16x16.ProtectedMethod");
1555 CREATE_SYM_ICON ("protectedproperty", "Icons.16x16.ProtectedProperty");
1556 CREATE_SYM_ICON ("publicprototype", "Icons.16x16.ProtectedInterface");
1558 CREATE_SYM_ICON ("publicclass", "Icons.16x16.Class");
1559 CREATE_SYM_ICON ("publicenum", "Icons.16x16.Enum");
1560 CREATE_SYM_ICON ("publicfunction", "Icons.16x16.Method");
1561 CREATE_SYM_ICON ("publicmember", "Icons.16x16.Method");
1562 CREATE_SYM_ICON ("publicproperty", "Icons.16x16.Property");
1563 CREATE_SYM_ICON ("publicstruct", "Icons.16x16.Struct");
1564 CREATE_SYM_ICON ("publicprototype", "Icons.16x16.Interface");
1567 CREATE_SYM_ICON ("othersvars", "Icons.16x16.Event");
1568 CREATE_SYM_ICON ("globalglobal", "Icons.16x16.Event");
1572 * @return The pixbufs. It will initialize pixbufs first if they weren't before
1573 * @param node_access can be NULL.
1576 symbol_db_view_get_pixbuf (const gchar
*node_type
, const gchar
*node_access
)
1582 sdb_view_load_symbol_pixbufs ();
1585 g_return_val_if_fail (node_type
!= NULL
, NULL
);
1587 /* is there a better/quicker method to retrieve pixbufs? */
1588 if (node_access
!= NULL
)
1590 search_node
= g_strdup_printf ("%s%s", node_access
, node_type
);
1594 /* we will not free search_node gchar, so casting here is ok. */
1595 search_node
= (gchar
*)node_type
;
1597 pix
= GDK_PIXBUF (g_hash_table_lookup (pixbufs_hash
, search_node
));
1601 g_free (search_node
);
1606 DEBUG_PRINT ("symbol_db_view_get_pixbuf (): no pixbuf for %s %s",
1607 node_type
, node_access
);
1615 symbol_db_view_new (void)
1617 return GTK_WIDGET (g_object_new (SYMBOL_TYPE_DB_VIEW
, NULL
));
1621 symbol_db_view_get_file_and_line (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1622 GtkTreeIter
* iter
, gint
*OUT_line
, gchar
**OUT_file
)
1624 GtkTreeStore
*store
;
1626 g_return_val_if_fail (dbv
!= NULL
, FALSE
);
1627 g_return_val_if_fail (dbe
!= NULL
, FALSE
);
1628 g_return_val_if_fail (iter
!= NULL
, FALSE
);
1630 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1635 const gchar
* relative_file
;
1636 SymbolDBEngineIteratorNode
*node
;
1638 gtk_tree_model_get (GTK_TREE_MODEL
1640 COLUMN_SYMBOL_ID
, &symbol_id
, -1);
1642 /* getting line at click time with a query is faster than updating every
1643 * entry in the gtktreeview. We can be sure that the db is in a consistent
1644 * state and has all the last infos
1646 node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (
1647 symbol_db_engine_get_symbol_info_by_id (dbe
, symbol_id
,
1649 SYMINFO_FILE_PATH
));
1652 *OUT_line
= symbol_db_engine_iterator_node_get_symbol_file_pos (node
);
1654 symbol_db_engine_iterator_node_get_symbol_extra_string (node
,
1656 *OUT_file
= symbol_db_engine_get_full_local_path (dbe
, relative_file
);
1665 sdb_view_build_and_display_base_tree (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
)
1667 GtkTreeStore
*store
;
1668 SymbolDBViewPriv
*priv
;
1669 SymbolDBEngineIterator
*iterator
;
1670 gboolean we_have_namespaces
;
1671 GPtrArray
*filter_array
;
1672 GtkTreeRowReference
*global_tree_row_ref
;
1673 GtkTreeIter global_child_iter
;
1674 const GdkPixbuf
*global_pixbuf
;
1676 g_return_if_fail (dbv
!= NULL
);
1680 store
= GTK_TREE_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (dbv
)));
1682 we_have_namespaces
= FALSE
;
1684 filter_array
= g_ptr_array_new ();
1685 g_ptr_array_add (filter_array
, "namespace");
1687 /* check for the presence of namespaces.
1688 * If that's the case then populate the root with a 'Global' node.
1690 iterator
= symbol_db_engine_get_global_members_filtered (dbe
, filter_array
, TRUE
,
1697 g_ptr_array_free (filter_array
, TRUE
);
1699 if (iterator
!= NULL
)
1701 we_have_namespaces
= TRUE
;
1704 gint curr_symbol_id
;
1705 SymbolDBEngineIteratorNode
*iter_node
;
1706 const GdkPixbuf
*pixbuf
;
1707 const gchar
* symbol_name
;
1708 GtkTreeRowReference
*curr_tree_row_ref
;
1709 GtkTreeIter child_iter
;
1711 iter_node
= SYMBOL_DB_ENGINE_ITERATOR_NODE (iterator
);
1713 curr_symbol_id
= symbol_db_engine_iterator_node_get_symbol_id (iter_node
);
1715 pixbuf
= symbol_db_view_get_pixbuf (
1716 symbol_db_engine_iterator_node_get_symbol_extra_string (
1717 iter_node
, SYMINFO_KIND
),
1718 symbol_db_engine_iterator_node_get_symbol_extra_string (
1719 iter_node
, SYMINFO_ACCESS
));
1721 symbol_name
= symbol_db_engine_iterator_node_get_symbol_name (iter_node
);
1723 curr_tree_row_ref
= do_add_root_symbol_to_view (dbv
, pixbuf
,
1724 symbol_name
, curr_symbol_id
);
1725 if (curr_tree_row_ref
== NULL
)
1730 /* we'll fake the gpointer to store an int */
1731 g_tree_insert (priv
->nodes_displayed
, (gpointer
)curr_symbol_id
,
1734 if (sdb_view_get_iter_from_row_ref (dbv
, curr_tree_row_ref
,
1735 &child_iter
) == FALSE
)
1737 g_warning ("sdb_view_build_and_display_base_tree (): something "
1741 /* add a dummy child */
1742 sdb_view_do_add_hidden_dummy_child (dbv
, dbe
,
1743 &child_iter
, curr_symbol_id
, FALSE
);
1745 } while (symbol_db_engine_iterator_move_next (iterator
) == TRUE
);
1747 g_object_unref (iterator
);
1751 * Good. Add a 'Global' node to the store.
1753 global_pixbuf
= symbol_db_view_get_pixbuf ("global", "global");
1755 global_tree_row_ref
= do_add_root_symbol_to_view (dbv
, global_pixbuf
,
1756 "Global", ROOT_GLOBAL
);
1758 if (global_tree_row_ref
== NULL
)
1762 g_tree_insert (priv
->nodes_displayed
, (gpointer
)ROOT_GLOBAL
,
1763 global_tree_row_ref
);
1765 if (sdb_view_get_iter_from_row_ref (dbv
, global_tree_row_ref
,
1766 &global_child_iter
) == FALSE
)
1768 g_warning ("sdb_view_build_and_display_base_tree (): cannot retrieve iter for "
1773 /* add a dummy child */
1774 sdb_view_do_add_hidden_dummy_child (dbv
, dbe
,
1775 &global_child_iter
, ROOT_GLOBAL
, TRUE
);
1779 symbol_db_view_recv_signals_from_engine (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
,
1780 gboolean enable_status
)
1782 SymbolDBViewPriv
*priv
;
1784 g_return_if_fail (dbv
!= NULL
);
1787 if (enable_status
== TRUE
)
1789 gtk_widget_set_sensitive (GTK_WIDGET (dbv
), TRUE
);
1790 /* connect some signals */
1791 if (priv
->insert_handler
<= 0)
1793 priv
->insert_handler
= g_signal_connect (G_OBJECT (dbe
), "symbol-inserted",
1794 G_CALLBACK (on_symbol_inserted
), dbv
);
1797 if (priv
->remove_handler
<= 0)
1799 priv
->remove_handler
= g_signal_connect (G_OBJECT (dbe
), "symbol-removed",
1800 G_CALLBACK (on_symbol_removed
), dbv
);
1803 if (priv
->scan_end_handler
<= 0)
1805 priv
->scan_end_handler
= g_signal_connect (G_OBJECT (dbe
), "scan-end",
1806 G_CALLBACK (on_scan_end
), dbv
);
1809 else /* disconnect them, if they were ever connected before */
1811 gtk_widget_set_sensitive (GTK_WIDGET (dbv
), FALSE
);
1813 if (priv
->insert_handler
>= 0)
1815 g_signal_handler_disconnect (G_OBJECT (dbe
), priv
->insert_handler
);
1816 priv
->insert_handler
= 0;
1819 if (priv
->remove_handler
>= 0)
1821 g_signal_handler_disconnect (G_OBJECT (dbe
), priv
->remove_handler
);
1822 priv
->remove_handler
= 0;
1825 if (priv
->scan_end_handler
>= 0)
1827 g_signal_handler_disconnect (G_OBJECT (dbe
), priv
->scan_end_handler
);
1828 priv
->scan_end_handler
= 0;
1834 symbol_db_view_open (SymbolDBView
*dbv
, SymbolDBEngine
*dbe
)
1836 SymbolDBViewPriv
*priv
;
1837 GtkTreeStore
*store
;
1839 g_return_if_fail (dbv
!= NULL
);
1843 DEBUG_PRINT ("symbol_db_view_open ()");
1844 symbol_db_view_clear_cache (dbv
);
1846 store
= sdb_view_create_new_store ();
1847 gtk_tree_view_set_model (GTK_TREE_VIEW (dbv
), GTK_TREE_MODEL (store
));
1849 priv
->nodes_displayed
= g_tree_new_full ((GCompareDataFunc
)>ree_compare_func
,
1852 (GDestroyNotify
)>k_tree_row_reference_free
);
1854 priv
->waiting_for
= g_tree_new_full ((GCompareDataFunc
)>ree_compare_func
,
1859 sdb_view_build_and_display_base_tree (dbv
, dbe
);