Integrate adding files with the file manager
[anjuta-git-plugin.git] / plugins / debug-manager / debug_tree.c
blob7af60aa9655a89a5fdcd25c5a4c4a2ab5a2ab3c6
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 debug_tree.c
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
21 // TODO:
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
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
33 #include "debug_tree.h"
35 #include "plugin.h"
36 #include "memory.h"
38 /*#define DEBUG*/
39 #include <libanjuta/anjuta-debug.h>
41 #include <glib/gi18n.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include <assert.h>
48 /* Types
49 *---------------------------------------------------------------------------*/
51 enum _DataType
53 TYPE_ROOT,
54 TYPE_UNKNOWN,
55 TYPE_POINTER,
56 TYPE_ARRAY,
57 TYPE_STRUCT,
58 TYPE_VALUE,
59 TYPE_REFERENCE,
60 TYPE_NAME
63 typedef enum _DataType DataType;
65 enum {AUTO_UPDATE_WATCH = 1 << 0};
67 /* Common data */
68 typedef struct _CommonDebugTree CommonDebugTree;
69 typedef struct _DmaVariablePacket DmaVariablePacket;
70 typedef struct _DmaVariableData DmaVariableData;
72 struct _CommonDebugTree {
73 guint initialized;
74 DebugTree* current;
75 DebugTree* user;
76 GList *tree_list;
79 /* The debug tree object */
80 struct _DebugTree {
81 DmaDebuggerQueue *debugger;
82 AnjutaPlugin *plugin;
83 GtkWidget* view; /* the tree widget */
84 gboolean auto_expand;
87 struct _DmaVariablePacket {
88 DmaVariableData *data;
89 GtkTreeModel *model;
90 GtkTreeRowReference* reference;
91 DebugTree *tree;
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;
106 gchar* name;
109 /* Constant
110 *---------------------------------------------------------------------------*/
112 #define UNKNOWN_VALUE "???"
113 #define UNKNOWN_TYPE "?"
114 #define AUTO_UPDATE 'U'
116 enum {
117 VARIABLE_COLUMN,
118 VALUE_COLUMN,
119 TYPE_COLUMN,
120 ROOT_COLUMN,
121 DTREE_ENTRY_COLUMN,
122 N_COLUMNS
125 static gchar *tree_title[] = {
126 N_("Variable"), N_("Value"), N_("Type")
129 /* Global variable
130 *---------------------------------------------------------------------------*/
132 static GList* gTreeList = NULL;
134 /* Helper functions
135 *---------------------------------------------------------------------------*/
137 static void
138 my_gtk_tree_model_foreach_child (GtkTreeModel *const model,
139 GtkTreeIter *const parent,
140 GtkTreeModelForeachFunc func,
141 gpointer user_data)
143 GtkTreeIter iter;
144 gboolean success = gtk_tree_model_iter_children(model, &iter, parent);
146 while(success)
148 success = (!func(model, NULL, &iter, user_data) &&
149 gtk_tree_model_iter_next (model, &iter));
153 static gboolean
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);
168 if (name != NULL)
170 data->name = g_strdup (name);
173 data->changed = TRUE;
174 data->auto_update = auto_update;
176 return data;
179 static void
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)
188 pack->data= NULL;
191 if (data->name != NULL)
193 g_free (data->name);
196 g_free(data);
199 /* ------------------------------------------------------------------ */
201 static DmaVariablePacket *
202 dma_variable_packet_new(GtkTreeModel *model,
203 GtkTreeIter *iter,
204 DebugTree *tree,
205 DmaVariableData *data)
207 GtkTreePath *path;
209 g_return_val_if_fail (model, NULL);
210 g_return_val_if_fail (iter, NULL);
212 DmaVariablePacket *pack = g_new (DmaVariablePacket, 1);
214 pack->data = data;
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);
219 pack->tree = tree;
220 pack->next = data->packet;
221 data->packet = pack;
223 return pack;
226 static void
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)
236 if (*find == pack)
238 *find = pack->next;
239 break;
244 gtk_tree_row_reference_free (pack->reference);
246 g_free (pack);
249 static gboolean
250 dma_variable_packet_get_iter (DmaVariablePacket* pack, GtkTreeIter *iter)
252 GtkTreePath *path;
253 gboolean ok;
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);
259 return ok;
262 /* DebugTree private functions
263 *---------------------------------------------------------------------------*/
265 static void
266 debug_tree_cell_data_func (GtkTreeViewColumn *tree_column,
267 GtkCellRenderer *cell, GtkTreeModel *tree_model,
268 GtkTreeIter *iter, gpointer data)
270 gchar *value;
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);
282 if (node)
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);
290 g_free (value);
293 static gboolean
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 */
306 if (data != NULL)
308 dma_variable_data_free(data);
309 my_gtk_tree_model_foreach_child (model, iter, delete_child, tree);
312 return FALSE;
315 static gboolean
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 */
328 if (data != NULL)
330 if (tree->debugger)
332 if (data->name)
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);
345 return FALSE;
349 static gboolean
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 */
361 data->deleted= TRUE;
363 return FALSE;
366 static void
367 debug_tree_remove_children (DebugTree *tree, GtkTreeIter* parent, GtkTreeIter* first)
369 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
370 gboolean child;
371 GtkTreeIter iter;
373 if (first != NULL)
375 /* Start with first child */
376 child = TRUE;
377 iter = *first;
379 else
381 /* Remove all children */
382 child = gtk_tree_model_iter_children(model, &iter, parent);
385 while (child)
387 delete_child (model, NULL, &iter, tree);
389 child = gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
393 static void
394 debug_tree_add_children (DebugTree *tree, GtkTreeIter* parent, const GList *children)
396 GList *child;
398 child = g_list_first ((GList *)children);
400 if (child == NULL)
402 /* Clear all children if they exist */
403 debug_tree_remove_children (tree, parent, NULL);
405 else
407 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
408 GtkTreeIter iter;
409 gboolean valid_iter;
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;
418 if (!valid_iter)
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,
426 ROOT_COLUMN, FALSE,
427 DTREE_ENTRY_COLUMN, NULL,-1);
428 data = NULL;
430 else
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);
442 if (data == NULL)
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);
448 else
450 data->changed = TRUE;
453 if (var->children == 0)
455 /* Clear all children if they exist */
456 debug_tree_remove_children (tree, &iter, NULL);
458 else
460 /* Add dummy children */
461 debug_tree_add_dummy (tree, &iter);
464 valid_iter = gtk_tree_model_iter_next (model, &iter);
466 if (valid_iter)
468 /* Remove trailing children */
469 debug_tree_remove_children (tree, parent, &iter);
474 static void
475 destroy_deleted (DebugTree *tree, GtkTreeModel* model)
477 DmaVariableData *data;
478 GtkTreeIter iter;
479 gboolean success;
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);
490 else
492 success = gtk_tree_model_iter_next (model, &iter);
497 /*---------------------------------------------------------------------------*/
499 static void
500 gdb_var_evaluate_expression (const gchar *value,
501 gpointer user_data, GError* err)
503 DmaVariablePacket *pack = (DmaVariablePacket *) user_data;
504 GtkTreeIter iter;
506 g_return_if_fail (pack != NULL);
508 if ((err != 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);
515 return;
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);
523 static void
524 gdb_var_list_children (const GList *children, gpointer user_data, GError *err)
526 DmaVariablePacket *pack = (DmaVariablePacket *) user_data;
527 GtkTreeIter iter;
529 g_return_if_fail (pack != NULL);
531 if ((err != 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);
538 return;
541 debug_tree_add_children (pack->tree, &iter, children);
543 dma_variable_packet_free (pack);
546 static void
547 gdb_var_create (IAnjutaDebuggerVariableObject *variable, gpointer user_data, GError *err)
549 DmaVariablePacket *pack = (DmaVariablePacket *) user_data;
550 GtkTreeIter iter;
552 g_return_if_fail (pack != NULL);
554 if (err != NULL)
556 /* Command failed */
557 dma_variable_packet_free (pack);
559 return;
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);
572 return;
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,
596 variable->name,
597 (IAnjutaDebuggerCallback)gdb_var_list_children,
598 pack_child);
600 else if (variable->children > 0)
602 debug_tree_add_dummy (pack->tree, &iter);
604 else
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,
616 variable->name,
617 (IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
618 pack);
620 else
622 dma_variable_packet_free (pack);
626 /* ------------------------------------------------------------------ */
628 static void
629 on_treeview_row_expanded (GtkTreeView *treeview,
630 GtkTreeIter *iter,
631 GtkTreePath *path,
632 gpointer user_data)
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 (
646 tree->debugger,
647 data->name,
648 (IAnjutaDebuggerCallback)gdb_var_list_children,
649 pack);
652 return;
655 static void
656 on_debug_tree_variable_changed (GtkCellRendererText *cell,
657 gchar *path_string,
658 gchar *text,
659 gpointer user_data)
661 DebugTree *tree = (DebugTree *)user_data;
662 GtkTreeIter iter;
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);
680 static void
681 on_debug_tree_value_changed (GtkCellRendererText *cell,
682 gchar *path_string,
683 gchar *text,
684 gpointer user_data)
686 DebugTree *tree = (DebugTree *)user_data;
687 GtkTreeIter iter;
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 (
704 tree->debugger,
705 item->name,
706 (IAnjutaDebuggerCallback) gdb_var_evaluate_expression,
707 tran);
712 static GtkWidget *
713 debug_tree_create (DebugTree *tree, GtkTreeView *view)
715 GtkCellRenderer *renderer;
716 GtkTreeViewColumn *column;
717 GtkTreeModel * model = GTK_TREE_MODEL (gtk_tree_store_new
718 (N_COLUMNS,
719 G_TYPE_STRING,
720 G_TYPE_STRING,
721 G_TYPE_STRING,
722 G_TYPE_BOOLEAN,
723 G_TYPE_POINTER));
725 if (view == NULL)
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));
736 /* Columns */
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);
772 /* Public functions
773 *---------------------------------------------------------------------------*/
775 /* clear the display of the debug tree and reset the title */
776 void
777 debug_tree_remove_all (DebugTree *tree)
779 GtkTreeModel *model;
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);
788 static gboolean
789 debug_tree_find_name (const GtkTreeModel *model, GtkTreeIter *iter, const gchar *name)
791 size_t len = 0;
792 GtkTreeIter parent_iter;
793 GtkTreeIter* parent = NULL;
795 for (;;)
797 const gchar *ptr;
799 /* Check if we look for a child variable */
800 ptr = strchr(name + len + 1, '.');
801 if (ptr != NULL)
803 /* Child variable */
804 gboolean search;
806 len = ptr - name;
807 for (search = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), iter, parent);
808 search != FALSE;
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))
816 break;
820 if (search == TRUE)
822 parent_iter = *iter;
823 parent = &parent_iter;
824 continue;
826 else
828 return FALSE;
831 else
833 /* Variable without any child */
834 gboolean search;
836 for (search = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), iter, parent);
837 search != FALSE;
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))
845 return TRUE;
849 return FALSE;
854 static gboolean
855 debug_tree_find_expression (const GtkTreeModel *model, GtkTreeIter *iter, const gchar *expression, const gchar *type)
857 gboolean search;
859 for (search = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), iter);
860 search;
861 search = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), iter))
863 gchar *exp;
864 gchar *typ;
865 DmaVariableData *node;
866 gboolean found;
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;
881 return FALSE;
884 static void
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};
891 GtkTreeIter iter;
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;
900 else
902 var.expression = (gchar *)expression;
903 debug_tree_add_watch (tree, &var, TRUE);
907 void
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);
920 void
921 debug_tree_add_dummy (DebugTree *tree, GtkTreeIter *parent)
923 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
924 GtkTreeIter iter;
926 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, parent);
927 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
928 VARIABLE_COLUMN, "",
929 VALUE_COLUMN, "",
930 TYPE_COLUMN, "",
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 */
938 void
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));
942 GtkTreeIter iter;
943 DmaVariableData *data;
945 /* Allocate 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,
954 ROOT_COLUMN, TRUE,
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 (
968 tree->debugger,
969 var->expression,
970 (IAnjutaDebuggerCallback)gdb_var_create,
971 pack);
973 else
975 DEBUG_PRINT("YOu shouldn't read this, debug_tree_add_watch");
976 if (var->value == NULL)
978 /* Get value */
979 DmaVariablePacket *pack =
981 pack = dma_variable_packet_new(model, &iter, tree, data);
982 dma_queue_evaluate_variable (
983 tree->debugger,
984 var->name,
985 (IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
986 pack);
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 (
995 tree->debugger,
996 var->name,
997 (IAnjutaDebuggerCallback)gdb_var_list_children,
998 pack);
1005 static void
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);
1016 void
1017 debug_tree_add_full_watch_list (DebugTree *this, GList *expressions)
1019 g_list_foreach (expressions, on_add_watch, this);
1022 static void
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);
1032 static void
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);
1042 void
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);
1048 static void
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 */
1056 GList *tree;
1058 for (tree = g_list_first (gTreeList); tree != NULL; tree = g_list_next (tree))
1060 GtkTreeIter iter;
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);
1070 if (data != NULL)
1072 data->changed = var->changed;
1073 data->exited = var->exited;
1074 data->deleted = var->deleted;
1077 return;
1083 static gboolean
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;
1100 return FALSE;
1103 static gboolean
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;
1108 GtkTreeIter child;
1109 gboolean search;
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 */
1121 gchar *exp;
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 (
1128 tree->debugger,
1129 exp,
1130 (IAnjutaDebuggerCallback)gdb_var_create,
1131 pack);
1132 g_free (exp);
1135 return FALSE;
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 (
1143 tree->debugger,
1144 data->name,
1145 (IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
1146 pack);
1148 else
1150 refresh = data->modified;
1151 data->modified = FALSE;
1154 /* update children */
1155 for (search = gtk_tree_model_iter_children(model, &child, iter);
1156 search == TRUE;
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;
1166 if (refresh)
1168 GtkTreePath *path;
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;
1177 static void
1178 on_debug_tree_update_all (const GList *change, gpointer user_data, GError* err)
1180 DebugTree *tree = (DebugTree *)user_data;
1181 GtkTreeModel *model;
1182 GtkTreeIter iter;
1184 if (err != NULL) return;
1186 // Mark all modified variables
1187 g_list_foreach ((GList *)change, on_debug_tree_changed, NULL);
1189 // Update this tree
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);
1207 void
1208 debug_tree_update_all (DebugTree* tree)
1210 if (tree->debugger != NULL)
1212 /* Update if debugger is connected */
1213 dma_queue_update_variable (
1214 tree->debugger,
1215 (IAnjutaDebuggerCallback)on_debug_tree_update_all,
1216 tree);
1220 GList*
1221 debug_tree_get_full_watch_list (DebugTree *this)
1223 GtkTreeIter iter;
1224 GtkTreeModel *model;
1225 GList* list = NULL;
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;
1234 gchar *exp;
1235 gchar *exp_with_flag;
1237 gtk_tree_model_get(model, &iter, DTREE_ENTRY_COLUMN, &data,
1238 VARIABLE_COLUMN, &exp, -1);
1240 if (data != NULL)
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);
1246 g_free (exp);
1247 } while (gtk_tree_model_iter_next (model, &iter) == TRUE);
1250 list = g_list_reverse (list);
1252 return list;
1256 GtkWidget *
1257 debug_tree_get_tree_widget (DebugTree *this)
1259 return this->view;
1262 gboolean
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) */
1269 gboolean
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);
1284 gboolean
1285 debug_tree_update (DebugTree* tree, GtkTreeIter* iter, gboolean force)
1287 if (tree->debugger != NULL)
1289 return debug_tree_update_real (tree, iter, force);
1291 else
1293 return FALSE;
1297 void
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);
1305 if (data != NULL)
1307 data->auto_update = state;
1311 gboolean
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);
1320 if (data != NULL)
1322 return data->auto_update;
1324 else
1326 return FALSE;
1330 void
1331 debug_tree_connect (DebugTree *this, DmaDebuggerQueue* debugger)
1333 this->debugger = debugger;
1336 void
1337 debug_tree_disconnect (DebugTree *this)
1339 this->debugger = NULL;
1342 GtkTreeModel *
1343 debug_tree_get_model (DebugTree *tree)
1345 return gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1348 void
1349 debug_tree_set_model (DebugTree *tree, GtkTreeModel *model)
1351 gtk_tree_view_set_model (GTK_TREE_VIEW (tree->view), model);
1354 void
1355 debug_tree_new_model (DebugTree *tree)
1357 GtkTreeModel * model = GTK_TREE_MODEL (gtk_tree_store_new
1358 (N_COLUMNS,
1359 G_TYPE_STRING,
1360 G_TYPE_STRING,
1361 G_TYPE_STRING,
1362 G_TYPE_BOOLEAN,
1363 G_TYPE_POINTER));
1365 gtk_tree_view_set_model (GTK_TREE_VIEW (tree->view), model);
1368 void
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));
1375 gchar *
1376 debug_tree_get_selected (DebugTree *tree)
1378 GtkTreeIter iter;
1379 gchar *exp = NULL;
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));
1386 if (model != NULL)
1388 gtk_tree_model_get(model, &iter, VARIABLE_COLUMN, &exp, -1);
1392 return exp;
1395 gchar *
1396 debug_tree_get_first (DebugTree *tree)
1398 GtkTreeIter iter;
1399 gchar *exp = NULL;
1400 GtkTreeModel *model;
1402 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1403 if (model != NULL)
1405 if (gtk_tree_model_get_iter_first (model, &iter))
1407 gtk_tree_model_get(model, &iter, VARIABLE_COLUMN, &exp, -1);
1411 return exp;
1414 gchar*
1415 debug_tree_find_variable_value (DebugTree *tree, const gchar *name)
1417 GtkTreeModel *model;
1418 GtkTreeIter iter;
1420 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1422 if (gtk_tree_model_get_iter_first (model, &iter))
1424 gchar *exp;
1425 gchar *value;
1428 gtk_tree_model_get(model, &iter, VARIABLE_COLUMN, &exp,
1429 VALUE_COLUMN, &value, -1);
1431 if (strcmp (exp, name) == 0)
1433 return value;
1435 } while (gtk_tree_model_iter_next (model, &iter));
1438 return NULL;
1441 /* Constructor & Destructor
1442 *---------------------------------------------------------------------------*/
1444 /* return a pointer to a newly allocated DebugTree object */
1445 DebugTree *
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);
1463 return tree;
1467 /* return a pointer to a newly allocated DebugTree object */
1468 DebugTree *
1469 debug_tree_new (AnjutaPlugin* plugin)
1471 return debug_tree_new_with_view (plugin, NULL);
1474 /* DebugTree destructor */
1475 void
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);
1494 g_free (tree);