1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 Copyright (C) 2006 Sébastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 // Alloc string in DmaVariableData object, so treeview can use POINTER
23 // => no need to free data after getting the value
24 // => value can be access more easily if we have the tree viex
25 // => do the same for variable name
27 // Add a function to get all arguments
33 #include "debug_tree.h"
39 #include <libanjuta/anjuta-debug.h>
41 #include <glib/gi18n.h>
49 *---------------------------------------------------------------------------*/
63 typedef enum _DataType DataType
;
65 enum {AUTO_UPDATE_WATCH
= 1 << 0};
68 typedef struct _CommonDebugTree CommonDebugTree
;
69 typedef struct _DmaVariablePacket DmaVariablePacket
;
70 typedef struct _DmaVariableData DmaVariableData
;
72 struct _CommonDebugTree
{
79 /* The debug tree object */
81 DmaDebuggerQueue
*debugger
;
83 GtkWidget
* view
; /* the tree widget */
87 struct _DmaVariablePacket
{
88 DmaVariableData
*data
;
90 GtkTreeRowReference
* reference
;
92 DmaVariablePacket
* next
;
95 struct _DmaVariableData
{
96 guchar modified
; /* Set by tree update */
97 guchar changed
; /* Set by global update */
99 gboolean exited
; /* variable outside scope */
100 gboolean deleted
; /* variable should be deleted */
102 gboolean auto_update
;
104 DmaVariablePacket
* packet
;
110 *---------------------------------------------------------------------------*/
112 #define UNKNOWN_VALUE "???"
113 #define UNKNOWN_TYPE "?"
114 #define AUTO_UPDATE 'U'
125 static gchar
*tree_title
[] = {
126 N_("Variable"), N_("Value"), N_("Type")
130 *---------------------------------------------------------------------------*/
132 static GList
* gTreeList
= NULL
;
135 *---------------------------------------------------------------------------*/
138 my_gtk_tree_model_foreach_child (GtkTreeModel
*const model
,
139 GtkTreeIter
*const parent
,
140 GtkTreeModelForeachFunc func
,
144 gboolean success
= gtk_tree_model_iter_children(model
, &iter
, parent
);
148 success
= (!func(model
, NULL
, &iter
, user_data
) &&
149 gtk_tree_model_iter_next (model
, &iter
));
154 get_current_iter (GtkTreeView
*view
, GtkTreeIter
* iter
)
156 GtkTreeSelection
*selection
;
158 selection
= gtk_tree_view_get_selection (view
);
159 return gtk_tree_selection_get_selected (selection
, NULL
, iter
);
162 static DmaVariableData
*
163 dma_variable_data_new(const gchar
*const name
, gboolean auto_update
)
165 DmaVariableData
*data
;
167 data
= g_new0 (DmaVariableData
, 1);
170 data
->name
= g_strdup (name
);
173 data
->changed
= TRUE
;
174 data
->auto_update
= auto_update
;
180 dma_variable_data_free(DmaVariableData
* data
)
182 DmaVariablePacket
* pack
;
184 /* Mark the data as invalid, the packet structure will
185 * be free later in the callback */
186 for (pack
= data
->packet
; pack
!= NULL
; pack
= pack
->next
)
191 if (data
->name
!= NULL
)
199 /* ------------------------------------------------------------------ */
201 static DmaVariablePacket
*
202 dma_variable_packet_new(GtkTreeModel
*model
,
205 DmaVariableData
*data
)
209 g_return_val_if_fail (model
, NULL
);
210 g_return_val_if_fail (iter
, NULL
);
212 DmaVariablePacket
*pack
= g_new (DmaVariablePacket
, 1);
215 pack
->model
= GTK_TREE_MODEL (model
);
216 path
= gtk_tree_model_get_path(model
, iter
);
217 pack
->reference
= gtk_tree_row_reference_new (model
, path
);
218 gtk_tree_path_free (path
);
220 pack
->next
= data
->packet
;
227 dma_variable_packet_free (DmaVariablePacket
* pack
)
229 if (pack
->data
!= NULL
)
231 /* Remove from packet data list */
232 DmaVariablePacket
**find
;
234 for (find
= &pack
->data
->packet
; *find
!= NULL
; find
= &(*find
)->next
)
244 gtk_tree_row_reference_free (pack
->reference
);
250 dma_variable_packet_get_iter (DmaVariablePacket
* pack
, GtkTreeIter
*iter
)
255 path
= gtk_tree_row_reference_get_path (pack
->reference
);
256 ok
= gtk_tree_model_get_iter (pack
->model
, iter
, path
);
257 gtk_tree_path_free (path
);
262 /* DebugTree private functions
263 *---------------------------------------------------------------------------*/
266 debug_tree_cell_data_func (GtkTreeViewColumn
*tree_column
,
267 GtkCellRenderer
*cell
, GtkTreeModel
*tree_model
,
268 GtkTreeIter
*iter
, gpointer data
)
271 static const gchar
*colors
[] = {"black", "red"};
272 GValue gvalue
= {0, };
273 DmaVariableData
*node
= NULL
;
275 gtk_tree_model_get (tree_model
, iter
, VALUE_COLUMN
, &value
, -1);
276 g_value_init (&gvalue
, G_TYPE_STRING
);
277 g_value_set_static_string (&gvalue
, value
);
278 g_object_set_property (G_OBJECT (cell
), "text", &gvalue
);
280 gtk_tree_model_get (tree_model
, iter
, DTREE_ENTRY_COLUMN
, &node
, -1);
284 g_value_reset (&gvalue
);
285 g_value_set_static_string (&gvalue
,
286 colors
[(node
&& node
->modified
? 1 : 0)]);
288 g_object_set_property (G_OBJECT (cell
), "foreground", &gvalue
);
294 delete_child(GtkTreeModel
*model
, GtkTreePath
* path
,
295 GtkTreeIter
* iter
, gpointer user_data
)
297 DmaVariableData
*data
;
298 DebugTree
* tree
= (DebugTree
*)user_data
;
300 g_return_val_if_fail (model
,TRUE
);
301 g_return_val_if_fail (iter
,TRUE
);
303 gtk_tree_model_get(model
, iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
305 /* Dummy node (data == NULL) are used when child are not known */
308 dma_variable_data_free(data
);
309 my_gtk_tree_model_foreach_child (model
, iter
, delete_child
, tree
);
316 delete_parent(GtkTreeModel
*model
, GtkTreePath
* path
,
317 GtkTreeIter
* iter
, gpointer user_data
)
319 DmaVariableData
*data
;
320 DebugTree
* tree
= (DebugTree
*)user_data
;
322 g_return_val_if_fail (model
,TRUE
);
323 g_return_val_if_fail (iter
,TRUE
);
325 gtk_tree_model_get(model
, iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
327 /* Dummy node (data == NULL) are used as a place holder in watch box */
334 /* Object has been created in debugger and is not a child
335 * (destroyed with their parent) */
336 dma_queue_delete_variable (tree
->debugger
, data
->name
);
340 dma_variable_data_free(data
);
342 my_gtk_tree_model_foreach_child (model
, iter
, delete_child
, tree
);
350 set_deleted(GtkTreeModel
*model
, GtkTreePath
* path
,
351 GtkTreeIter
* iter
, gpointer user_data
)
353 DmaVariableData
*data
;
355 g_return_val_if_fail (model
,TRUE
);
356 g_return_val_if_fail (iter
,TRUE
);
358 gtk_tree_model_get(model
, iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
359 g_return_val_if_fail (data
, TRUE
); /* Use on root node only, data != NULL */
367 debug_tree_remove_children (DebugTree
*tree
, GtkTreeIter
* parent
, GtkTreeIter
* first
)
369 GtkTreeModel
*model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
375 /* Start with first child */
381 /* Remove all children */
382 child
= gtk_tree_model_iter_children(model
, &iter
, parent
);
387 delete_child (model
, NULL
, &iter
, tree
);
389 child
= gtk_tree_store_remove (GTK_TREE_STORE (model
), &iter
);
394 debug_tree_add_children (DebugTree
*tree
, GtkTreeIter
* parent
, const GList
*children
)
398 child
= g_list_first ((GList
*)children
);
402 /* Clear all children if they exist */
403 debug_tree_remove_children (tree
, parent
, NULL
);
407 GtkTreeModel
*model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
411 valid_iter
= gtk_tree_model_iter_children (model
, &iter
, parent
);
413 for (; child
!= NULL
; child
= g_list_next (child
))
415 IAnjutaDebuggerVariableObject
*var
= (IAnjutaDebuggerVariableObject
*)child
->data
;
416 DmaVariableData
*data
;
420 /* Add new tree node */
421 gtk_tree_store_append(GTK_TREE_STORE(model
), &iter
, parent
);
422 gtk_tree_store_set(GTK_TREE_STORE(model
), &iter
,
423 TYPE_COLUMN
, var
->type
== NULL
? UNKNOWN_TYPE
: var
->type
,
424 VALUE_COLUMN
, var
->value
== NULL
? UNKNOWN_VALUE
: var
->value
,
425 VARIABLE_COLUMN
, var
->expression
,
427 DTREE_ENTRY_COLUMN
, NULL
,-1);
432 /* Update tree node */
433 if (var
->type
!= NULL
)
434 gtk_tree_store_set(GTK_TREE_STORE(model
), &iter
, TYPE_COLUMN
, var
->type
, -1);
435 if (var
->value
!= NULL
)
436 gtk_tree_store_set(GTK_TREE_STORE(model
), &iter
, VALUE_COLUMN
, var
->value
, -1);
437 if (var
->expression
!= NULL
)
438 gtk_tree_store_set(GTK_TREE_STORE(model
), &iter
, VARIABLE_COLUMN
, var
->expression
, -1);
439 gtk_tree_model_get(model
, &iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
444 /* Create new data */
445 data
= dma_variable_data_new(var
->name
, FALSE
);
446 gtk_tree_store_set(GTK_TREE_STORE(model
), &iter
, DTREE_ENTRY_COLUMN
, data
, -1);
450 data
->changed
= TRUE
;
453 if (var
->children
== 0)
455 /* Clear all children if they exist */
456 debug_tree_remove_children (tree
, &iter
, NULL
);
460 /* Add dummy children */
461 debug_tree_add_dummy (tree
, &iter
);
464 valid_iter
= gtk_tree_model_iter_next (model
, &iter
);
468 /* Remove trailing children */
469 debug_tree_remove_children (tree
, parent
, &iter
);
475 destroy_deleted (DebugTree
*tree
, GtkTreeModel
* model
)
477 DmaVariableData
*data
;
481 g_return_if_fail (model
);
483 for (success
= gtk_tree_model_get_iter_first (model
, &iter
); success
== TRUE
; )
485 gtk_tree_model_get(model
, &iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
486 if ((data
!= NULL
) && (data
->deleted
== TRUE
))
488 success
= debug_tree_remove (tree
, &iter
);
492 success
= gtk_tree_model_iter_next (model
, &iter
);
497 /*---------------------------------------------------------------------------*/
500 gdb_var_evaluate_expression (const gchar
*value
,
501 gpointer user_data
, GError
* err
)
503 DmaVariablePacket
*pack
= (DmaVariablePacket
*) user_data
;
506 g_return_if_fail (pack
!= NULL
);
509 || (pack
->data
== NULL
)
510 || !dma_variable_packet_get_iter (pack
, &iter
))
512 /* Command failed or item has been deleted */
513 dma_variable_packet_free (pack
);
518 pack
->data
->changed
= FALSE
;
519 gtk_tree_store_set(GTK_TREE_STORE (pack
->model
), &iter
, VALUE_COLUMN
, value
, -1);
520 dma_variable_packet_free (pack
);
524 gdb_var_list_children (const GList
*children
, gpointer user_data
, GError
*err
)
526 DmaVariablePacket
*pack
= (DmaVariablePacket
*) user_data
;
529 g_return_if_fail (pack
!= NULL
);
532 || (pack
->data
== NULL
)
533 || !dma_variable_packet_get_iter (pack
, &iter
))
535 /* Command failed or item has been deleted */
536 dma_variable_packet_free (pack
);
541 debug_tree_add_children (pack
->tree
, &iter
, children
);
543 dma_variable_packet_free (pack
);
547 gdb_var_create (IAnjutaDebuggerVariableObject
*variable
, gpointer user_data
, GError
*err
)
549 DmaVariablePacket
*pack
= (DmaVariablePacket
*) user_data
;
552 g_return_if_fail (pack
!= NULL
);
557 dma_variable_packet_free (pack
);
561 if ((pack
->data
== NULL
)
562 || !dma_variable_packet_get_iter (pack
, &iter
))
564 /* Item has been deleted, but not removed from debugger as it was not
565 * created at this time, so remove it now */
566 if ((pack
->tree
->debugger
) && (variable
->name
))
568 dma_queue_delete_variable (pack
->tree
->debugger
, variable
->name
);
570 dma_variable_packet_free (pack
);
575 DmaVariableData
*data
= pack
->data
;
577 if ((variable
->name
!= NULL
) && (data
->name
== NULL
))
579 data
->name
= strdup (variable
->name
);
581 data
->changed
= TRUE
;
583 gtk_tree_store_set(GTK_TREE_STORE(pack
->model
), &iter
,
584 TYPE_COLUMN
, variable
->type
,
585 VALUE_COLUMN
, variable
->value
, -1);
588 if (variable
->children
== -1)
590 /* Find the number of children */
591 DmaVariablePacket
*pack_child
=
592 dma_variable_packet_new(pack
->model
, &iter
, pack
->tree
, data
);
594 dma_queue_list_children (
595 pack_child
->tree
->debugger
,
597 (IAnjutaDebuggerCallback
)gdb_var_list_children
,
600 else if (variable
->children
> 0)
602 debug_tree_add_dummy (pack
->tree
, &iter
);
606 debug_tree_remove_children (pack
->tree
, &iter
, NULL
);
610 /* Request value and/or children if they are missing
611 * reusing same packet if possible */
612 if (variable
->value
== NULL
)
614 dma_queue_evaluate_variable (
615 pack
->tree
->debugger
,
617 (IAnjutaDebuggerCallback
)gdb_var_evaluate_expression
,
622 dma_variable_packet_free (pack
);
626 /* ------------------------------------------------------------------ */
629 on_treeview_row_expanded (GtkTreeView
*treeview
,
634 DebugTree
*tree
= (DebugTree
*)user_data
;
635 GtkTreeModel
*const model
= gtk_tree_view_get_model (treeview
);
636 DmaVariableData
*data
;
638 gtk_tree_model_get (model
, iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
640 if ((data
!= NULL
) && (data
->name
!= NULL
) && (tree
->debugger
!= NULL
))
642 DmaVariablePacket
*pack
;
644 pack
= dma_variable_packet_new(model
, iter
, tree
, data
);
645 dma_queue_list_children (
648 (IAnjutaDebuggerCallback
)gdb_var_list_children
,
656 on_debug_tree_variable_changed (GtkCellRendererText
*cell
,
661 DebugTree
*tree
= (DebugTree
*)user_data
;
663 GtkTreeModel
* model
;
665 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
666 if (gtk_tree_model_get_iter_from_string (model
, &iter
, path_string
))
668 debug_tree_remove (tree
, &iter
);
670 if ((text
!= NULL
) && (*text
!= '\0'))
672 IAnjutaDebuggerVariableObject var
= {NULL
, NULL
, NULL
, NULL
, FALSE
, FALSE
, FALSE
, -1};
674 var
.expression
= text
;
675 debug_tree_add_watch (tree
, &var
, TRUE
);
681 on_debug_tree_value_changed (GtkCellRendererText
*cell
,
686 DebugTree
*tree
= (DebugTree
*)user_data
;
688 GtkTreeModel
* model
;
690 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
692 if (gtk_tree_model_get_iter_from_string (model
, &iter
, path_string
))
694 DmaVariableData
*item
;
695 DmaVariablePacket
*tran
;
697 gtk_tree_model_get (model
, &iter
, DTREE_ENTRY_COLUMN
, &item
, -1);
698 if ((item
!= NULL
) && (item
->name
!= NULL
) && (tree
->debugger
!= NULL
))
700 /* Variable is valid */
701 dma_queue_assign_variable (tree
->debugger
, item
->name
, text
);
702 tran
= dma_variable_packet_new(model
, &iter
, tree
, item
);
703 dma_queue_evaluate_variable (
706 (IAnjutaDebuggerCallback
) gdb_var_evaluate_expression
,
713 debug_tree_create (DebugTree
*tree
, GtkTreeView
*view
)
715 GtkCellRenderer
*renderer
;
716 GtkTreeViewColumn
*column
;
717 GtkTreeModel
* model
= GTK_TREE_MODEL (gtk_tree_store_new
727 view
= GTK_TREE_VIEW (gtk_tree_view_new ());
730 gtk_tree_view_set_model (view
, GTK_TREE_MODEL (model
));
732 GtkTreeSelection
*selection
= gtk_tree_view_get_selection (view
);
733 gtk_tree_selection_set_mode (selection
, GTK_SELECTION_SINGLE
);
734 g_object_unref (G_OBJECT (model
));
737 column
= gtk_tree_view_column_new ();
738 renderer
= gtk_cell_renderer_text_new ();
739 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
740 gtk_tree_view_column_add_attribute (column
, renderer
, "text", VARIABLE_COLUMN
);
741 gtk_tree_view_column_add_attribute (column
, renderer
, "editable", ROOT_COLUMN
);
742 g_signal_connect(renderer
, "edited", (GCallback
) on_debug_tree_variable_changed
, tree
);
743 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
744 gtk_tree_view_column_set_title (column
, _(tree_title
[0]));
745 gtk_tree_view_append_column (view
, column
);
746 gtk_tree_view_set_expander_column (view
, column
);
748 column
= gtk_tree_view_column_new ();
749 renderer
= gtk_cell_renderer_text_new ();
750 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
751 gtk_tree_view_column_set_cell_data_func (column
, renderer
,
752 debug_tree_cell_data_func
, NULL
, NULL
);
753 gtk_tree_view_column_add_attribute (column
, renderer
, "text", VALUE_COLUMN
);
754 g_object_set(renderer
, "editable", TRUE
, NULL
);
755 g_signal_connect(renderer
, "edited", (GCallback
) on_debug_tree_value_changed
, tree
);
756 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
757 gtk_tree_view_column_set_title (column
, _(tree_title
[1]));
758 gtk_tree_view_append_column (view
, column
);
761 column
= gtk_tree_view_column_new ();
762 renderer
= gtk_cell_renderer_text_new ();
763 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
764 gtk_tree_view_column_add_attribute (column
, renderer
, "text", TYPE_COLUMN
);
765 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
766 gtk_tree_view_column_set_title (column
, _(tree_title
[2]));
767 gtk_tree_view_append_column (view
, column
);
769 return GTK_WIDGET (view
);
773 *---------------------------------------------------------------------------*/
775 /* clear the display of the debug tree and reset the title */
777 debug_tree_remove_all (DebugTree
*tree
)
781 g_return_if_fail (tree
);
782 g_return_if_fail (tree
->view
);
784 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
785 debug_tree_remove_model (tree
, model
);
789 debug_tree_find_name (const GtkTreeModel
*model
, GtkTreeIter
*iter
, const gchar
*name
)
792 GtkTreeIter parent_iter
;
793 GtkTreeIter
* parent
= NULL
;
799 /* Check if we look for a child variable */
800 ptr
= strchr(name
+ len
+ 1, '.');
807 for (search
= gtk_tree_model_iter_children (GTK_TREE_MODEL (model
), iter
, parent
);
809 search
= gtk_tree_model_iter_next (GTK_TREE_MODEL (model
), iter
))
811 DmaVariableData
*iData
;
812 gtk_tree_model_get (GTK_TREE_MODEL (model
), iter
, DTREE_ENTRY_COLUMN
, &iData
, -1);
814 if ((iData
!= NULL
) && (iData
->name
!= NULL
) && (name
[len
] == '.') && (strncmp (name
, iData
->name
, len
) == 0))
823 parent
= &parent_iter
;
833 /* Variable without any child */
836 for (search
= gtk_tree_model_iter_children (GTK_TREE_MODEL (model
), iter
, parent
);
838 search
= gtk_tree_model_iter_next (GTK_TREE_MODEL (model
), iter
))
840 DmaVariableData
*iData
;
841 gtk_tree_model_get (GTK_TREE_MODEL (model
), iter
, DTREE_ENTRY_COLUMN
, &iData
, -1);
843 if ((iData
!= NULL
) && (iData
->name
!= NULL
) && (strcmp (name
, iData
->name
) == 0))
855 debug_tree_find_expression (const GtkTreeModel
*model
, GtkTreeIter
*iter
, const gchar
*expression
, const gchar
*type
)
859 for (search
= gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model
), iter
);
861 search
= gtk_tree_model_iter_next (GTK_TREE_MODEL (model
), iter
))
865 DmaVariableData
*node
;
868 gtk_tree_model_get (GTK_TREE_MODEL (model
), iter
, TYPE_COLUMN
, &typ
,
869 VARIABLE_COLUMN
, &exp
,
870 DTREE_ENTRY_COLUMN
, &node
, -1);
872 found
= ((type
== NULL
) || (strcmp (typ
, type
) == 0))
873 && ((expression
== NULL
) || (strcmp (exp
, expression
) == 0))
874 && (node
->exited
== FALSE
);
875 if (typ
!= NULL
) g_free (typ
);
876 if (exp
!= NULL
) g_free (exp
);
878 if (found
) return TRUE
;
885 on_replace_watch (gpointer data
, gpointer user_data
)
887 DebugTree
* tree
= (DebugTree
*)user_data
;
888 const gchar
*expression
= (const gchar
*)data
;
889 GtkTreeModel
*const model
= gtk_tree_view_get_model (GTK_TREE_VIEW(tree
->view
));
890 IAnjutaDebuggerVariableObject var
= {NULL
, NULL
, NULL
, NULL
, FALSE
, FALSE
, FALSE
, -1};
893 if (debug_tree_find_expression (model
, &iter
, expression
, NULL
))
895 DmaVariableData
*data
;
897 gtk_tree_model_get (model
, &iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
898 if (data
!= NULL
) data
->deleted
= FALSE
;
902 var
.expression
= (gchar
*)expression
;
903 debug_tree_add_watch (tree
, &var
, TRUE
);
908 debug_tree_replace_list (DebugTree
*tree
, const GList
*expressions
)
910 GtkTreeModel
* model
= gtk_tree_view_get_model (GTK_TREE_VIEW(tree
->view
));
912 /* Mark variables as deleted */
913 my_gtk_tree_model_foreach_child(model
, NULL
, set_deleted
, NULL
);
915 g_list_foreach ((GList
*)expressions
, on_replace_watch
, tree
);
917 destroy_deleted (tree
, model
);
921 debug_tree_add_dummy (DebugTree
*tree
, GtkTreeIter
*parent
)
923 GtkTreeModel
*model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
926 gtk_tree_store_append(GTK_TREE_STORE(model
), &iter
, parent
);
927 gtk_tree_store_set(GTK_TREE_STORE(model
), &iter
,
931 ROOT_COLUMN
, parent
== NULL
? TRUE
: FALSE
,
932 DTREE_ENTRY_COLUMN
, NULL
, -1);
935 /* Get a IAnjutaVariable as argument in order to use the same function without
936 * variable object, currently only the expression field is set */
939 debug_tree_add_watch (DebugTree
*tree
, const IAnjutaDebuggerVariableObject
* var
, gboolean auto_update
)
941 GtkTreeModel
*model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
943 DmaVariableData
*data
;
946 data
= dma_variable_data_new(var
->name
, auto_update
);
948 /* Add node in tree */
949 gtk_tree_store_append(GTK_TREE_STORE(model
), &iter
, NULL
);
950 gtk_tree_store_set(GTK_TREE_STORE(model
), &iter
,
951 TYPE_COLUMN
, var
->type
== NULL
? UNKNOWN_TYPE
: var
->type
,
952 VALUE_COLUMN
, var
->value
== NULL
? UNKNOWN_VALUE
: var
->value
,
953 VARIABLE_COLUMN
, var
->expression
,
955 DTREE_ENTRY_COLUMN
, data
, -1);
957 if (tree
->debugger
!= NULL
)
959 if ((var
->value
== NULL
) || (var
->children
== -1))
961 if (var
->name
== NULL
)
963 /* Need to create variable before to get value */
964 DmaVariablePacket
*pack
;
966 pack
= dma_variable_packet_new(model
, &iter
, tree
, data
);
967 dma_queue_create_variable (
970 (IAnjutaDebuggerCallback
)gdb_var_create
,
975 DEBUG_PRINT("YOu shouldn't read this, debug_tree_add_watch");
976 if (var
->value
== NULL
)
979 DmaVariablePacket
*pack
=
981 pack
= dma_variable_packet_new(model
, &iter
, tree
, data
);
982 dma_queue_evaluate_variable (
985 (IAnjutaDebuggerCallback
)gdb_var_evaluate_expression
,
988 if (var
->children
== -1)
990 /* Get number of children */
991 DmaVariablePacket
*pack
=
993 pack
= dma_variable_packet_new(model
, &iter
, tree
, data
);
994 dma_queue_list_children (
997 (IAnjutaDebuggerCallback
)gdb_var_list_children
,
1006 on_add_watch (gpointer data
, gpointer user_data
)
1008 DebugTree
* this = (DebugTree
*)user_data
;
1009 gboolean auto_update
= ((const gchar
*)data
)[0] & AUTO_UPDATE_WATCH
? TRUE
: FALSE
;
1010 IAnjutaDebuggerVariableObject var
= {NULL
, NULL
, NULL
, NULL
, FALSE
, FALSE
, FALSE
, -1};
1012 var
.expression
= &((gchar
*)data
)[1];
1013 debug_tree_add_watch (this, &var
, auto_update
);
1017 debug_tree_add_full_watch_list (DebugTree
*this, GList
*expressions
)
1019 g_list_foreach (expressions
, on_add_watch
, this);
1023 on_add_manual_watch (gpointer data
, gpointer user_data
)
1025 DebugTree
* this = (DebugTree
*)user_data
;
1026 IAnjutaDebuggerVariableObject var
= {NULL
, NULL
, NULL
, NULL
, FALSE
, FALSE
, FALSE
, -1};
1028 var
.expression
= &((gchar
*)data
)[0];
1029 debug_tree_add_watch (this, &var
, FALSE
);
1033 on_add_auto_watch (gpointer data
, gpointer user_data
)
1035 DebugTree
* this = (DebugTree
*)user_data
;
1036 IAnjutaDebuggerVariableObject var
= {NULL
, NULL
, NULL
, NULL
, FALSE
, FALSE
, -1};
1038 var
.expression
= &((gchar
*)data
)[0];
1039 debug_tree_add_watch (this, &var
, TRUE
);
1043 debug_tree_add_watch_list (DebugTree
*this, GList
*expressions
, gboolean auto_update
)
1045 g_list_foreach (expressions
, auto_update
? on_add_auto_watch
: on_add_manual_watch
, this);
1049 on_debug_tree_changed (gpointer data
, gpointer user_data
)
1051 IAnjutaDebuggerVariableObject
*var
= (IAnjutaDebuggerVariableObject
*)data
;
1053 if (var
->name
!= NULL
)
1055 /* Search corresponding variable in one tree */
1058 for (tree
= g_list_first (gTreeList
); tree
!= NULL
; tree
= g_list_next (tree
))
1061 GtkTreeModel
*model
;
1063 model
= GTK_TREE_MODEL (tree
->data
);
1065 if (debug_tree_find_name (model
, &iter
, var
->name
))
1067 DmaVariableData
*data
;
1068 gtk_tree_model_get (model
, &iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
1072 data
->changed
= var
->changed
;
1073 data
->exited
= var
->exited
;
1074 data
->deleted
= var
->deleted
;
1084 on_debug_tree_modified (GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
*iter
, gpointer user_data
)
1086 DmaVariableData
*data
= NULL
;
1088 gtk_tree_model_get (model
, iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
1090 if (data
!= NULL
) /* Avoid dummy node */
1092 if (data
->modified
!= data
->changed
)
1094 data
->modified
= data
->changed
;
1095 gtk_tree_model_row_changed (model
, path
, iter
);
1097 data
->changed
= FALSE
;
1104 debug_tree_update_real (DebugTree
* tree
, GtkTreeIter
* iter
, gboolean force
)
1106 GtkTreeModel
*model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
1107 DmaVariableData
*data
= NULL
;
1110 gboolean refresh
= TRUE
;
1112 gtk_tree_model_get (model
, iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
1113 if (data
== NULL
) return FALSE
;
1115 if (data
->name
== NULL
)
1117 /* Check is the variable creation is not pending */
1118 if (data
->packet
== NULL
)
1120 /* Variable need to be created first */
1122 DmaVariablePacket
*pack
;
1124 gtk_tree_model_get (model
, iter
, VARIABLE_COLUMN
, &exp
, -1);
1125 pack
= dma_variable_packet_new(model
, iter
, tree
, data
);
1126 data
->modified
= TRUE
;
1127 dma_queue_create_variable (
1130 (IAnjutaDebuggerCallback
)gdb_var_create
,
1137 else if (force
|| (data
->auto_update
&& data
->changed
))
1139 DmaVariablePacket
*pack
= dma_variable_packet_new(model
, iter
, tree
, data
);
1140 refresh
= data
->modified
!= (data
->changed
!= FALSE
);
1141 data
->modified
= (data
->changed
!= FALSE
);
1142 dma_queue_evaluate_variable (
1145 (IAnjutaDebuggerCallback
)gdb_var_evaluate_expression
,
1150 refresh
= data
->modified
;
1151 data
->modified
= FALSE
;
1154 /* update children */
1155 for (search
= gtk_tree_model_iter_children(model
, &child
, iter
);
1157 search
= gtk_tree_model_iter_next (model
, &child
))
1159 if (debug_tree_update_real (tree
, &child
, force
))
1161 refresh
= data
->modified
== TRUE
;
1162 data
->modified
= TRUE
;
1169 path
= gtk_tree_model_get_path (model
, iter
);
1170 gtk_tree_model_row_changed (model
, path
, iter
);
1171 gtk_tree_path_free (path
);
1174 return data
->modified
;
1178 on_debug_tree_update_all (const GList
*change
, gpointer user_data
, GError
* err
)
1180 DebugTree
*tree
= (DebugTree
*)user_data
;
1181 GtkTreeModel
*model
;
1184 if (err
!= NULL
) return;
1186 // Mark all modified variables
1187 g_list_foreach ((GList
*)change
, on_debug_tree_changed
, NULL
);
1190 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
1191 if (gtk_tree_model_get_iter_first (model
, &iter
) == TRUE
)
1195 DmaVariableData
*data
= NULL
;
1197 gtk_tree_model_get (model
, &iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
1199 debug_tree_update_real (tree
, &iter
, FALSE
);
1200 } while (gtk_tree_model_iter_next (model
, &iter
) == TRUE
);
1203 // Update modified mark
1204 gtk_tree_model_foreach (model
, on_debug_tree_modified
, NULL
);
1208 debug_tree_update_all (DebugTree
* tree
)
1210 if (tree
->debugger
!= NULL
)
1212 /* Update if debugger is connected */
1213 dma_queue_update_variable (
1215 (IAnjutaDebuggerCallback
)on_debug_tree_update_all
,
1221 debug_tree_get_full_watch_list (DebugTree
*this)
1224 GtkTreeModel
*model
;
1227 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (this->view
));
1229 if (gtk_tree_model_get_iter_first (model
, &iter
) == TRUE
)
1233 DmaVariableData
*data
;
1235 gchar
*exp_with_flag
;
1237 gtk_tree_model_get(model
, &iter
, DTREE_ENTRY_COLUMN
, &data
,
1238 VARIABLE_COLUMN
, &exp
, -1);
1242 exp_with_flag
= g_strconcat (" ", exp
, NULL
);
1243 exp_with_flag
[0] = data
->auto_update
? AUTO_UPDATE_WATCH
: ' ';
1244 list
= g_list_prepend (list
, exp_with_flag
);
1247 } while (gtk_tree_model_iter_next (model
, &iter
) == TRUE
);
1250 list
= g_list_reverse (list
);
1257 debug_tree_get_tree_widget (DebugTree
*this)
1263 debug_tree_get_current (DebugTree
*tree
, GtkTreeIter
* iter
)
1265 return get_current_iter (GTK_TREE_VIEW (tree
->view
), iter
);
1268 /* Return TRUE if iter is still valid (point to next item) */
1270 debug_tree_remove (DebugTree
*tree
, GtkTreeIter
* iter
)
1272 GtkTreeModel
*model
;
1274 g_return_val_if_fail (tree
, FALSE
);
1275 g_return_val_if_fail (tree
->view
, FALSE
);
1276 g_return_val_if_fail (iter
, FALSE
);
1278 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
1280 delete_parent (model
, NULL
, iter
, tree
);
1281 return gtk_tree_store_remove (GTK_TREE_STORE (model
), iter
);
1285 debug_tree_update (DebugTree
* tree
, GtkTreeIter
* iter
, gboolean force
)
1287 if (tree
->debugger
!= NULL
)
1289 return debug_tree_update_real (tree
, iter
, force
);
1298 debug_tree_set_auto_update (DebugTree
* this, GtkTreeIter
* iter
, gboolean state
)
1300 GtkTreeModel
*model
;
1301 DmaVariableData
*data
;
1303 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (this->view
));
1304 gtk_tree_model_get(model
, iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
1307 data
->auto_update
= state
;
1312 debug_tree_get_auto_update (DebugTree
* this, GtkTreeIter
* iter
)
1314 GtkTreeModel
*model
;
1315 DmaVariableData
*data
;
1317 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (this->view
));
1318 gtk_tree_model_get(model
, iter
, DTREE_ENTRY_COLUMN
, &data
, -1);
1322 return data
->auto_update
;
1331 debug_tree_connect (DebugTree
*this, DmaDebuggerQueue
* debugger
)
1333 this->debugger
= debugger
;
1337 debug_tree_disconnect (DebugTree
*this)
1339 this->debugger
= NULL
;
1343 debug_tree_get_model (DebugTree
*tree
)
1345 return gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
1349 debug_tree_set_model (DebugTree
*tree
, GtkTreeModel
*model
)
1351 gtk_tree_view_set_model (GTK_TREE_VIEW (tree
->view
), model
);
1355 debug_tree_new_model (DebugTree
*tree
)
1357 GtkTreeModel
* model
= GTK_TREE_MODEL (gtk_tree_store_new
1365 gtk_tree_view_set_model (GTK_TREE_VIEW (tree
->view
), model
);
1369 debug_tree_remove_model (DebugTree
*tree
, GtkTreeModel
*model
)
1371 my_gtk_tree_model_foreach_child (model
, NULL
, delete_parent
, tree
);
1372 gtk_tree_store_clear (GTK_TREE_STORE (model
));
1376 debug_tree_get_selected (DebugTree
*tree
)
1381 if (get_current_iter (GTK_TREE_VIEW (tree
->view
), &iter
))
1383 GtkTreeModel
*model
;
1385 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
1388 gtk_tree_model_get(model
, &iter
, VARIABLE_COLUMN
, &exp
, -1);
1396 debug_tree_get_first (DebugTree
*tree
)
1400 GtkTreeModel
*model
;
1402 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
1405 if (gtk_tree_model_get_iter_first (model
, &iter
))
1407 gtk_tree_model_get(model
, &iter
, VARIABLE_COLUMN
, &exp
, -1);
1415 debug_tree_find_variable_value (DebugTree
*tree
, const gchar
*name
)
1417 GtkTreeModel
*model
;
1420 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
1422 if (gtk_tree_model_get_iter_first (model
, &iter
))
1428 gtk_tree_model_get(model
, &iter
, VARIABLE_COLUMN
, &exp
,
1429 VALUE_COLUMN
, &value
, -1);
1431 if (strcmp (exp
, name
) == 0)
1435 } while (gtk_tree_model_iter_next (model
, &iter
));
1441 /* Constructor & Destructor
1442 *---------------------------------------------------------------------------*/
1444 /* return a pointer to a newly allocated DebugTree object */
1446 debug_tree_new_with_view (AnjutaPlugin
*plugin
, GtkTreeView
*view
)
1448 DebugTree
*tree
= g_new0 (DebugTree
, 1);
1449 GtkTreeModel
*model
;
1451 tree
->plugin
= plugin
;
1452 tree
->view
= debug_tree_create(tree
, view
);
1453 tree
->auto_expand
= FALSE
;
1455 /* Add this model in list */
1456 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
1457 gTreeList
= g_list_prepend (gTreeList
, model
);
1459 /* Connect signal */
1460 g_signal_connect(GTK_TREE_VIEW (tree
->view
), "row_expanded", G_CALLBACK (on_treeview_row_expanded
), tree
);
1467 /* return a pointer to a newly allocated DebugTree object */
1469 debug_tree_new (AnjutaPlugin
* plugin
)
1471 return debug_tree_new_with_view (plugin
, NULL
);
1474 /* DebugTree destructor */
1476 debug_tree_free (DebugTree
* tree
)
1478 GtkTreeModel
*model
;
1480 g_return_if_fail (tree
);
1482 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (tree
->view
));
1483 debug_tree_remove_all (tree
);
1485 /* Remove from list */
1486 gTreeList
= g_list_remove (gTreeList
, model
);
1488 g_signal_handlers_disconnect_by_func (GTK_TREE_VIEW (tree
->view
),
1489 G_CALLBACK (on_treeview_row_expanded
), tree
);
1491 gtk_widget_destroy (tree
->view
);