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
5
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.
10
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.
15
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
19 */
20
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
26 //
27 // Add a function to get all arguments
28
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32
33 #include "debug_tree.h"
34
35 #include "plugin.h"
36 #include "memory.h"
37
38 /*#define DEBUG*/
39 #include <libanjuta/anjuta-debug.h>
40
41 #include <glib/gi18n.h>
42
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include <assert.h>
47
48 /* Types
49 *---------------------------------------------------------------------------*/
50
51 enum _DataType
52 {
53 TYPE_ROOT,
54 TYPE_UNKNOWN,
55 TYPE_POINTER,
56 TYPE_ARRAY,
57 TYPE_STRUCT,
58 TYPE_VALUE,
59 TYPE_REFERENCE,
60 TYPE_NAME
61 };
62
63 typedef enum _DataType DataType;
64
65 enum {AUTO_UPDATE_WATCH = 1 << 0};
66
67 /* Common data */
68 typedef struct _CommonDebugTree CommonDebugTree;
69 typedef struct _DmaVariablePacket DmaVariablePacket;
70 typedef struct _DmaVariableData DmaVariableData;
71
72 struct _CommonDebugTree {
73 guint initialized;
74 DebugTree* current;
75 DebugTree* user;
76 GList *tree_list;
77 };
78
79 /* The debug tree object */
80 struct _DebugTree {
81 DmaDebuggerQueue *debugger;
82 AnjutaPlugin *plugin;
83 GtkWidget* view; /* the tree widget */
84 gboolean auto_expand;
85 };
86
87 struct _DmaVariablePacket {
88 DmaVariableData *data;
89 GtkTreeModel *model;
90 guint from;
91 GtkTreeRowReference* reference;
92 DmaDebuggerQueue *debugger;
93 DmaVariablePacket* next;
94 };
95
96 struct _DmaVariableData {
97 gboolean modified; /* Set by tree update */
98
99 /* Value from debugger */
100 gboolean changed; /* Set by global update */
101 gboolean exited; /* variable outside scope */
102 gboolean deleted; /* variable should be deleted */
103
104 gboolean auto_update;
105
106 DmaVariablePacket* packet;
107
108 gchar* name;
109 };
110
111 /* Constant
112 *---------------------------------------------------------------------------*/
113
114 #define UNKNOWN_VALUE "???"
115 #define UNKNOWN_TYPE "?"
116 #define AUTO_UPDATE 'U'
117
118 enum {
119 VARIABLE_COLUMN,
120 VALUE_COLUMN,
121 TYPE_COLUMN,
122 ROOT_COLUMN,
123 DTREE_ENTRY_COLUMN,
124 N_COLUMNS
125 };
126
127 static gchar *tree_title[] = {
128 N_("Variable"), N_("Value"), N_("Type")
129 };
130
131 /* Global variable
132 *---------------------------------------------------------------------------*/
133
134 static GList* gTreeList = NULL;
135
136 /* Helper functions
137 *---------------------------------------------------------------------------*/
138
139 static void
my_gtk_tree_model_foreach_child(GtkTreeModel * const model,GtkTreeIter * const parent,GtkTreeModelForeachFunc func,gpointer user_data)140 my_gtk_tree_model_foreach_child (GtkTreeModel *const model,
141 GtkTreeIter *const parent,
142 GtkTreeModelForeachFunc func,
143 gpointer user_data)
144 {
145 GtkTreeIter iter;
146 gboolean success = gtk_tree_model_iter_children(model, &iter, parent);
147
148 while(success)
149 {
150 success = (!func(model, NULL, &iter, user_data) &&
151 gtk_tree_model_iter_next (model, &iter));
152 }
153 }
154
155 static gint
my_gtk_tree_model_child_position(GtkTreeModel * model,GtkTreeIter * iter)156 my_gtk_tree_model_child_position (GtkTreeModel *model,
157 GtkTreeIter *iter)
158 {
159 GtkTreePath *path;
160 gint pos;
161
162 path = gtk_tree_model_get_path (model, iter);
163 if (path == NULL) return -1;
164
165 for (pos = 0; gtk_tree_path_prev (path); pos++);
166 gtk_tree_path_free (path);
167
168 return pos;
169 }
170
171 static gboolean
get_current_iter(GtkTreeView * view,GtkTreeIter * iter)172 get_current_iter (GtkTreeView *view, GtkTreeIter* iter)
173 {
174 GtkTreeSelection *selection;
175
176 selection = gtk_tree_view_get_selection (view);
177 return gtk_tree_selection_get_selected (selection, NULL, iter);
178 }
179
180 static DmaVariableData *
dma_variable_data_new(const gchar * const name,gboolean auto_update)181 dma_variable_data_new(const gchar *const name, gboolean auto_update)
182 {
183 DmaVariableData *data;
184
185 data = g_new0 (DmaVariableData, 1);
186 if (name != NULL)
187 {
188 data->name = g_strdup (name);
189 }
190
191 data->auto_update = auto_update;
192
193 return data;
194 }
195
196 static void
dma_variable_data_free(DmaVariableData * data)197 dma_variable_data_free(DmaVariableData * data)
198 {
199 DmaVariablePacket* pack;
200
201 /* Mark the data as invalid, the packet structure will
202 * be free later in the callback */
203 for (pack = data->packet; pack != NULL; pack = pack->next)
204 {
205 pack->data= NULL;
206 }
207
208 if (data->name != NULL)
209 {
210 g_free (data->name);
211 }
212
213 g_free(data);
214 }
215
216 /* ------------------------------------------------------------------ */
217
218 static DmaVariablePacket *
dma_variable_packet_new(GtkTreeModel * model,GtkTreeIter * iter,DmaDebuggerQueue * debugger,DmaVariableData * data,guint from)219 dma_variable_packet_new(GtkTreeModel *model,
220 GtkTreeIter *iter,
221 DmaDebuggerQueue *debugger,
222 DmaVariableData *data,
223 guint from)
224 {
225 GtkTreePath *path;
226
227 g_return_val_if_fail (model, NULL);
228 g_return_val_if_fail (iter, NULL);
229
230 DmaVariablePacket *pack = g_new (DmaVariablePacket, 1);
231
232 pack->data = data;
233 pack->from = from;
234 pack->model = GTK_TREE_MODEL (model);
235 path = gtk_tree_model_get_path(model, iter);
236 pack->reference = gtk_tree_row_reference_new (model, path);
237 gtk_tree_path_free (path);
238 pack->debugger = debugger;
239 pack->next = data->packet;
240 data->packet = pack;
241
242 return pack;
243 }
244
245 static void
dma_variable_packet_free(DmaVariablePacket * pack)246 dma_variable_packet_free (DmaVariablePacket* pack)
247 {
248 if (pack->data != NULL)
249 {
250 /* Remove from packet data list */
251 DmaVariablePacket **find;
252
253 for (find = &pack->data->packet; *find != NULL; find = &(*find)->next)
254 {
255 if (*find == pack)
256 {
257 *find = pack->next;
258 break;
259 }
260 }
261 }
262
263 gtk_tree_row_reference_free (pack->reference);
264
265 g_free (pack);
266 }
267
268 static gboolean
dma_variable_packet_get_iter(DmaVariablePacket * pack,GtkTreeIter * iter)269 dma_variable_packet_get_iter (DmaVariablePacket* pack, GtkTreeIter *iter)
270 {
271 GtkTreePath *path;
272 gboolean ok;
273
274 path = gtk_tree_row_reference_get_path (pack->reference);
275 ok = gtk_tree_model_get_iter (pack->model, iter, path);
276 gtk_tree_path_free (path);
277
278 return ok;
279 }
280
281 /* DebugTree private functions
282 *---------------------------------------------------------------------------*/
283
284 static void
debug_tree_cell_data_func(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * tree_model,GtkTreeIter * iter,gpointer data)285 debug_tree_cell_data_func (GtkTreeViewColumn *tree_column,
286 GtkCellRenderer *cell, GtkTreeModel *tree_model,
287 GtkTreeIter *iter, gpointer data)
288 {
289 gchar *value;
290 static const gchar *colors[] = {"black", "red"};
291 GValue gvalue = {0, };
292 DmaVariableData *node = NULL;
293
294 gtk_tree_model_get (tree_model, iter, VALUE_COLUMN, &value, -1);
295 g_value_init (&gvalue, G_TYPE_STRING);
296 g_value_set_static_string (&gvalue, value);
297 g_object_set_property (G_OBJECT (cell), "text", &gvalue);
298
299 gtk_tree_model_get (tree_model, iter, DTREE_ENTRY_COLUMN, &node, -1);
300
301 if (node)
302 {
303 g_value_reset (&gvalue);
304 g_value_set_static_string (&gvalue,
305 colors[(node && node->modified ? 1 : 0)]);
306
307 g_object_set_property (G_OBJECT (cell), "foreground", &gvalue);
308 }
309 g_free (value);
310 }
311
312 static gboolean
delete_child(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer user_data)313 delete_child(GtkTreeModel *model, GtkTreePath* path,
314 GtkTreeIter* iter, gpointer user_data)
315 {
316 DmaVariableData *data;
317 DmaDebuggerQueue *debugger = (DmaDebuggerQueue *)user_data;
318
319 g_return_val_if_fail (model,TRUE);
320 g_return_val_if_fail (iter,TRUE);
321
322 gtk_tree_model_get(model, iter, DTREE_ENTRY_COLUMN, &data, -1);
323
324 /* Dummy node (data == NULL) are used when child are not known */
325 if (data != NULL)
326 {
327 dma_variable_data_free(data);
328 my_gtk_tree_model_foreach_child (model, iter, delete_child, debugger);
329 }
330
331 return FALSE;
332 }
333
334 static gboolean
delete_parent(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer user_data)335 delete_parent(GtkTreeModel *model, GtkTreePath* path,
336 GtkTreeIter* iter, gpointer user_data)
337 {
338 DmaVariableData *data;
339 DmaDebuggerQueue *debugger = (DmaDebuggerQueue *)user_data;
340
341 g_return_val_if_fail (model,TRUE);
342 g_return_val_if_fail (iter,TRUE);
343
344 gtk_tree_model_get(model, iter, DTREE_ENTRY_COLUMN, &data, -1);
345
346 /* Dummy node (data == NULL) are used as a place holder in watch box */
347 if (data != NULL)
348 {
349 if (debugger)
350 {
351 if (data->name)
352 {
353 /* Object has been created in debugger and is not a child
354 * (destroyed with their parent) */
355 dma_queue_delete_variable (debugger, data->name);
356 }
357 }
358
359 dma_variable_data_free(data);
360
361 my_gtk_tree_model_foreach_child (model, iter, delete_child, debugger);
362 }
363
364 return FALSE;
365 }
366
367 static void
debug_tree_remove_children(GtkTreeModel * model,DmaDebuggerQueue * debugger,GtkTreeIter * parent,GtkTreeIter * first)368 debug_tree_remove_children (GtkTreeModel *model, DmaDebuggerQueue *debugger, GtkTreeIter* parent, GtkTreeIter* first)
369 {
370 gboolean child;
371 GtkTreeIter iter;
372
373 if (first != NULL)
374 {
375 /* Start with first child */
376 child = TRUE;
377 iter = *first;
378 }
379 else
380 {
381 /* Remove all children */
382 child = gtk_tree_model_iter_children(model, &iter, parent);
383 }
384
385 while (child)
386 {
387 delete_child (model, NULL, &iter, debugger);
388
389 child = gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
390 }
391 }
392
393 static void
debug_tree_model_add_dummy_children(GtkTreeModel * model,GtkTreeIter * parent)394 debug_tree_model_add_dummy_children (GtkTreeModel *model, GtkTreeIter *parent)
395 {
396 GtkTreeIter iter;
397
398 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, parent);
399 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
400 VARIABLE_COLUMN, "",
401 VALUE_COLUMN, "",
402 TYPE_COLUMN, "",
403 ROOT_COLUMN, parent == NULL ? TRUE : FALSE,
404 DTREE_ENTRY_COLUMN, NULL, -1);
405 }
406
407 static void
debug_tree_add_children(GtkTreeModel * model,DmaDebuggerQueue * debugger,GtkTreeIter * parent,guint from,const GList * children)408 debug_tree_add_children (GtkTreeModel *model, DmaDebuggerQueue *debugger, GtkTreeIter* parent, guint from, const GList *children)
409 {
410 GList *child;
411 GtkTreeIter iter;
412 gboolean valid;
413
414 valid = gtk_tree_model_iter_nth_child (model, &iter, parent, from);
415
416 /* Add new children */
417 for (child = g_list_first ((GList *)children); child != NULL; child = g_list_next (child))
418 {
419 IAnjutaDebuggerVariableObject *var = (IAnjutaDebuggerVariableObject *)child->data;
420 DmaVariableData *data;
421
422 if (!valid)
423 {
424 /* Add new tree node */
425 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, parent);
426
427 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
428 TYPE_COLUMN, var->type == NULL ? UNKNOWN_TYPE : var->type,
429 VALUE_COLUMN, var->value == NULL ? UNKNOWN_VALUE : var->value,
430 VARIABLE_COLUMN, var->expression,
431 ROOT_COLUMN, FALSE,
432 DTREE_ENTRY_COLUMN, NULL,-1);
433 data = NULL;
434 }
435 else
436 {
437 /* Update tree node */
438 if (var->type != NULL)
439 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, TYPE_COLUMN, var->type, -1);
440 if (var->value != NULL)
441 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, VALUE_COLUMN, var->value, -1);
442 if (var->expression != NULL)
443 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, VARIABLE_COLUMN, var->expression, -1);
444 gtk_tree_model_get(model, &iter, DTREE_ENTRY_COLUMN, &data, -1);
445
446 if (var->name == NULL)
447 {
448 /* Dummy node representing additional children */
449 if (data != NULL)
450 {
451 dma_variable_data_free (data);
452 gtk_tree_store_set(GTK_TREE_STORE (model), &iter, DTREE_ENTRY_COLUMN, NULL, -1);
453 data = NULL;
454 }
455 }
456 }
457
458 if ((var->name != NULL) && (data == NULL))
459 {
460 /* Create new data */
461 data = dma_variable_data_new(var->name, TRUE);
462 gtk_tree_store_set(GTK_TREE_STORE(model), &iter, DTREE_ENTRY_COLUMN, data, -1);
463 }
464
465 /* Clear all children if they exist */
466 debug_tree_remove_children (model, debugger, &iter, NULL);
467 if ((var->children != 0) || var->has_more || (var->name == NULL))
468 {
469 /* Add dummy children */
470 debug_tree_model_add_dummy_children (model, &iter);
471 }
472
473 valid = gtk_tree_model_iter_next (model, &iter);
474 }
475
476 /* Clear remaining old children */
477 if (valid) debug_tree_remove_children (model, debugger, parent, &iter);
478 }
479
480 /*---------------------------------------------------------------------------*/
481
482 static void
gdb_var_evaluate_expression(const gchar * value,gpointer user_data,GError * err)483 gdb_var_evaluate_expression (const gchar *value,
484 gpointer user_data, GError* err)
485 {
486 DmaVariablePacket *pack = (DmaVariablePacket *) user_data;
487 GtkTreeIter iter;
488
489 g_return_if_fail (pack != NULL);
490
491 if ((err != NULL)
492 || (pack->data == NULL)
493 || !dma_variable_packet_get_iter (pack, &iter))
494 {
495 /* Command failed or item has been deleted */
496 dma_variable_packet_free (pack);
497
498 return;
499 }
500
501 pack->data->changed = FALSE;
502 gtk_tree_store_set(GTK_TREE_STORE (pack->model), &iter, VALUE_COLUMN, value, -1);
503 dma_variable_packet_free (pack);
504 }
505
506 static void
gdb_var_list_children(const GList * children,gpointer user_data,GError * err)507 gdb_var_list_children (const GList *children, gpointer user_data, GError *err)
508 {
509 DmaVariablePacket *pack = (DmaVariablePacket *) user_data;
510 GtkTreeIter iter;
511
512 g_return_if_fail (pack != NULL);
513
514 if ((err != NULL)
515 || (pack->data == NULL)
516 || !dma_variable_packet_get_iter (pack, &iter))
517 {
518 /* Command failed or item has been deleted */
519 dma_variable_packet_free (pack);
520
521 return;
522 }
523
524 debug_tree_add_children (pack->model, pack->debugger, &iter, pack->from, children);
525
526 dma_variable_packet_free (pack);
527 }
528
529 static void
gdb_var_create(IAnjutaDebuggerVariableObject * variable,gpointer user_data,GError * err)530 gdb_var_create (IAnjutaDebuggerVariableObject *variable, gpointer user_data, GError *err)
531 {
532 DmaVariablePacket *pack = (DmaVariablePacket *) user_data;
533 GtkTreeIter iter;
534
535 g_return_if_fail (pack != NULL);
536
537 if (err != NULL)
538 {
539 /* Command failed */
540 dma_variable_packet_free (pack);
541
542 return;
543 }
544 if ((pack->data == NULL)
545 || !dma_variable_packet_get_iter (pack, &iter))
546 {
547 /* Item has been deleted, but not removed from debugger as it was not
548 * created at this time, so remove it now */
549 if ((pack->debugger) && (variable->name))
550 {
551 dma_queue_delete_variable (pack->debugger, variable->name);
552 }
553 dma_variable_packet_free (pack);
554
555 return;
556 }
557
558 DmaVariableData *data = pack->data;
559
560 if ((variable->name != NULL) && (data->name == NULL))
561 {
562 data->name = strdup (variable->name);
563 }
564 data->changed = TRUE;
565 data->deleted = FALSE;
566 data->exited = FALSE;
567
568 gtk_tree_store_set(GTK_TREE_STORE(pack->model), &iter,
569 TYPE_COLUMN, variable->type,
570 VALUE_COLUMN, variable->value, -1);
571
572
573 if ((variable->children == 0) && !variable->has_more)
574 {
575 debug_tree_remove_children (pack->model, pack->debugger, &iter, NULL);
576 }
577 else
578 {
579 debug_tree_model_add_dummy_children (pack->model, &iter);
580 }
581
582
583 /* Request value and/or children if they are missing
584 * reusing same packet if possible */
585 if (variable->value == NULL)
586 {
587 dma_queue_evaluate_variable (
588 pack->debugger,
589 variable->name,
590 (IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
591 pack);
592 }
593 else
594 {
595 dma_variable_packet_free (pack);
596 }
597 }
598
599 /* ------------------------------------------------------------------ */
600
601 static void
on_treeview_row_expanded(GtkTreeView * treeview,GtkTreeIter * iter,GtkTreePath * path,gpointer user_data)602 on_treeview_row_expanded (GtkTreeView *treeview,
603 GtkTreeIter *iter,
604 GtkTreePath *path,
605 gpointer user_data)
606 {
607 DebugTree *tree = (DebugTree *)user_data;
608
609 if (tree->debugger != NULL)
610 {
611 GtkTreeModel *const model = gtk_tree_view_get_model (treeview);
612 DmaVariableData *data;
613
614 gtk_tree_model_get (model, iter, DTREE_ENTRY_COLUMN, &data, -1);
615
616 if ((data != NULL) && (data->name != NULL))
617 {
618 /* Expand variable node */
619 GtkTreeIter child;
620
621 if (gtk_tree_model_iter_children (model, &child, iter))
622 {
623 DmaVariableData *child_data;
624
625 gtk_tree_model_get (model, &child, DTREE_ENTRY_COLUMN, &child_data, -1);
626 if ((child_data == NULL) || (child_data->name == NULL))
627 {
628 /* Dummy children, get the real children */
629 DmaVariablePacket *pack;
630
631 pack = dma_variable_packet_new(model, iter, tree->debugger, data, 0);
632 dma_queue_list_children (
633 tree->debugger,
634 data->name,
635 0,
636 (IAnjutaDebuggerCallback)gdb_var_list_children,
637 pack);
638 }
639 }
640 }
641 else
642 {
643 /* Dummy node representing additional children */
644 GtkTreeIter parent;
645
646 if (gtk_tree_model_iter_parent (model, &parent, iter))
647 {
648 gtk_tree_model_get (model, &parent, DTREE_ENTRY_COLUMN, &data, -1);
649 if ((data != NULL) && (data->name != NULL))
650 {
651 DmaVariablePacket *pack;
652 guint from;
653 gint pos;
654
655 pos = my_gtk_tree_model_child_position (model, iter);
656 from = pos < 0 ? 0 : pos;
657
658 pack = dma_variable_packet_new(model, &parent, tree->debugger, data, from);
659 dma_queue_list_children (
660 tree->debugger,
661 data->name,
662 from,
663 (IAnjutaDebuggerCallback)gdb_var_list_children,
664 pack);
665 }
666 }
667 }
668 }
669
670 return;
671 }
672
673 static void
on_debug_tree_variable_changed(GtkCellRendererText * cell,gchar * path_string,gchar * text,gpointer user_data)674 on_debug_tree_variable_changed (GtkCellRendererText *cell,
675 gchar *path_string,
676 gchar *text,
677 gpointer user_data)
678 {
679 DebugTree *tree = (DebugTree *)user_data;
680 GtkTreeIter iter;
681 GtkTreeModel * model;
682
683 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
684 if (gtk_tree_model_get_iter_from_string (model, &iter, path_string))
685 {
686 debug_tree_remove (tree, &iter);
687
688 if ((text != NULL) && (*text != '\0'))
689 {
690 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
691
692 var.expression = text;
693 debug_tree_add_watch (tree, &var, TRUE);
694 }
695 else
696 {
697 debug_tree_add_dummy (tree, NULL);
698 }
699 }
700 }
701
702 static void
on_debug_tree_value_changed(GtkCellRendererText * cell,gchar * path_string,gchar * text,gpointer user_data)703 on_debug_tree_value_changed (GtkCellRendererText *cell,
704 gchar *path_string,
705 gchar *text,
706 gpointer user_data)
707 {
708 DebugTree *tree = (DebugTree *)user_data;
709 GtkTreeIter iter;
710 GtkTreeModel * model;
711
712 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
713
714 if (gtk_tree_model_get_iter_from_string (model, &iter, path_string))
715 {
716 DmaVariableData *item;
717 DmaVariablePacket *tran;
718
719 gtk_tree_model_get (model, &iter, DTREE_ENTRY_COLUMN, &item, -1);
720 if ((item != NULL) && (item->name != NULL) && (tree->debugger != NULL))
721 {
722 /* Variable is valid */
723 dma_queue_assign_variable (tree->debugger, item->name, text);
724 tran = dma_variable_packet_new(model, &iter, tree->debugger, item, 0);
725 dma_queue_evaluate_variable (
726 tree->debugger,
727 item->name,
728 (IAnjutaDebuggerCallback) gdb_var_evaluate_expression,
729 tran);
730 }
731 }
732 }
733
734 static GtkWidget *
debug_tree_create(DebugTree * tree,GtkTreeView * view)735 debug_tree_create (DebugTree *tree, GtkTreeView *view)
736 {
737 GtkCellRenderer *renderer;
738 GtkTreeViewColumn *column;
739 GtkTreeModel * model = GTK_TREE_MODEL (gtk_tree_store_new
740 (N_COLUMNS,
741 G_TYPE_STRING,
742 G_TYPE_STRING,
743 G_TYPE_STRING,
744 G_TYPE_BOOLEAN,
745 G_TYPE_POINTER));
746
747 if (view == NULL)
748 {
749 view = GTK_TREE_VIEW (gtk_tree_view_new ());
750 }
751
752 gtk_tree_view_set_model (view, GTK_TREE_MODEL (model));
753
754 GtkTreeSelection *selection = gtk_tree_view_get_selection (view);
755 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
756 g_object_unref (G_OBJECT (model));
757
758 /* Columns */
759 column = gtk_tree_view_column_new ();
760 renderer = gtk_cell_renderer_text_new ();
761 gtk_tree_view_column_pack_start (column, renderer, TRUE);
762 gtk_tree_view_column_add_attribute (column, renderer, "text", VARIABLE_COLUMN);
763 gtk_tree_view_column_add_attribute (column, renderer, "editable", ROOT_COLUMN);
764 g_signal_connect(renderer, "edited", (GCallback) on_debug_tree_variable_changed, tree);
765 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
766 gtk_tree_view_column_set_resizable (column, TRUE);
767 gtk_tree_view_column_set_title (column, _(tree_title[0]));
768 gtk_tree_view_append_column (view, column);
769 gtk_tree_view_set_expander_column (view, column);
770
771 column = gtk_tree_view_column_new ();
772 renderer = gtk_cell_renderer_text_new ();
773 gtk_tree_view_column_pack_start (column, renderer, TRUE);
774 gtk_tree_view_column_set_cell_data_func (column, renderer,
775 debug_tree_cell_data_func, NULL, NULL);
776 gtk_tree_view_column_add_attribute (column, renderer, "text", VALUE_COLUMN);
777 g_object_set(renderer, "editable", TRUE, NULL);
778 g_signal_connect(renderer, "edited", (GCallback) on_debug_tree_value_changed, tree);
779 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
780 gtk_tree_view_column_set_resizable (column, TRUE);
781 gtk_tree_view_column_set_title (column, _(tree_title[1]));
782 gtk_tree_view_append_column (view, column);
783
784
785 column = gtk_tree_view_column_new ();
786 renderer = gtk_cell_renderer_text_new ();
787 gtk_tree_view_column_pack_start (column, renderer, TRUE);
788 gtk_tree_view_column_add_attribute (column, renderer, "text", TYPE_COLUMN);
789 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
790 gtk_tree_view_column_set_resizable (column, TRUE);
791 gtk_tree_view_column_set_title (column, _(tree_title[2]));
792 gtk_tree_view_append_column (view, column);
793
794 return GTK_WIDGET (view);
795 }
796
797 /* Public functions
798 *---------------------------------------------------------------------------*/
799
800 /* clear the display of the debug tree and reset the title */
801 void
debug_tree_remove_all(DebugTree * tree)802 debug_tree_remove_all (DebugTree *tree)
803 {
804 GtkTreeModel *model;
805
806 g_return_if_fail (tree);
807 g_return_if_fail (tree->view);
808
809 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
810 debug_tree_remove_model (tree, model);
811 }
812
813 static gboolean
debug_tree_find_name(const GtkTreeModel * model,GtkTreeIter * iter,const gchar * name)814 debug_tree_find_name (const GtkTreeModel *model, GtkTreeIter *iter, const gchar *name)
815 {
816 size_t len = 0;
817 GtkTreeIter parent_iter;
818 GtkTreeIter* parent = NULL;
819
820 for (;;)
821 {
822 const gchar *ptr;
823
824 /* Check if we look for a child variable */
825 ptr = strchr(name + len + 1, '.');
826 if (ptr != NULL)
827 {
828 /* Child variable */
829 gboolean search;
830
831 len = ptr - name;
832 for (search = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), iter, parent);
833 search != FALSE;
834 search = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), iter))
835 {
836 DmaVariableData *iData;
837 gtk_tree_model_get (GTK_TREE_MODEL (model), iter, DTREE_ENTRY_COLUMN, &iData, -1);
838
839 if ((iData != NULL) && (iData->name != NULL) && (name[len] == '.') && (strncmp (name, iData->name, len) == 0))
840 {
841 break;
842 }
843 }
844
845 if (search == TRUE)
846 {
847 parent_iter = *iter;
848 parent = &parent_iter;
849 continue;
850 }
851 else
852 {
853 return FALSE;
854 }
855 }
856 else
857 {
858 /* Variable without any child */
859 gboolean search;
860
861 for (search = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), iter, parent);
862 search != FALSE;
863 search = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), iter))
864 {
865 DmaVariableData *iData;
866 gtk_tree_model_get (GTK_TREE_MODEL (model), iter, DTREE_ENTRY_COLUMN, &iData, -1);
867
868 if ((iData != NULL) && (iData->name != NULL) && (strcmp (name, iData->name) == 0))
869 {
870 return TRUE;
871 }
872 }
873
874 return FALSE;
875 }
876 }
877 }
878
879 void
debug_tree_replace_list(DebugTree * tree,const GList * expressions)880 debug_tree_replace_list (DebugTree *tree, const GList *expressions)
881 {
882 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW(tree->view));
883 GtkTreeIter iter;
884 gboolean valid;
885 GList *list = g_list_copy ((GList *)expressions);
886
887 /* Keep in the tree only the variable in the list */
888 valid = gtk_tree_model_get_iter_first (model, &iter);
889 while (valid)
890 {
891 GList *find = NULL;
892 gchar *exp;
893 DmaVariableData *node;
894
895 gtk_tree_model_get (model, &iter,
896 VARIABLE_COLUMN, &exp,
897 DTREE_ENTRY_COLUMN, &node, -1);
898
899 if ((node->deleted == FALSE) && (node->exited == FALSE) && (exp != NULL))
900 {
901 find = g_list_find_custom (list, exp, (GCompareFunc)strcmp);
902 }
903
904 if (find)
905 {
906 /* Keep variable in tree, remove in add list */
907 list = g_list_delete_link (list, find);
908 valid = gtk_tree_model_iter_next (model, &iter);
909 }
910 else
911 {
912 /* Remove variable from the tree */
913 delete_parent(model, NULL, &iter, tree->debugger);
914 valid = gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
915 }
916 }
917
918 /* Create new variable */
919 while (list)
920 {
921 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
922
923 var.expression = (gchar *)(list->data);
924 debug_tree_add_watch (tree, &var, TRUE);
925
926 list = g_list_delete_link (list, list);
927 }
928 }
929
930 void
debug_tree_add_dummy(DebugTree * tree,GtkTreeIter * parent)931 debug_tree_add_dummy (DebugTree *tree, GtkTreeIter *parent)
932 {
933 GtkTreeModel* model = gtk_tree_view_get_model (GTK_TREE_VIEW(tree->view));
934
935 debug_tree_model_add_dummy_children (model, parent);
936 }
937
938 /* Get a IAnjutaVariable as argument in order to use the same function without
939 * variable object, currently only the expression field is set */
940
941 void
debug_tree_add_watch(DebugTree * tree,const IAnjutaDebuggerVariableObject * var,gboolean auto_update)942 debug_tree_add_watch (DebugTree *tree, const IAnjutaDebuggerVariableObject* var, gboolean auto_update)
943 {
944 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
945 GtkTreeIter iter;
946 DmaVariableData *data;
947
948 /* Allocate data */
949 data = dma_variable_data_new(var->name, auto_update);
950
951 /* Add node in tree */
952 gtk_tree_store_append(GTK_TREE_STORE(model), &iter, NULL);
953 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
954 TYPE_COLUMN, var->type == NULL ? UNKNOWN_TYPE : var->type,
955 VALUE_COLUMN, var->value == NULL ? UNKNOWN_VALUE : var->value,
956 VARIABLE_COLUMN, var->expression,
957 ROOT_COLUMN, TRUE,
958 DTREE_ENTRY_COLUMN, data, -1);
959
960 if (tree->debugger != NULL)
961 {
962 if ((var->value == NULL) || (var->children == -1))
963 {
964 if (var->name == NULL)
965 {
966 /* Need to create variable before to get value */
967 DmaVariablePacket *pack;
968
969 pack = dma_variable_packet_new(model, &iter, tree->debugger, data, 0);
970 dma_queue_create_variable (
971 tree->debugger,
972 var->expression,
973 (IAnjutaDebuggerCallback)gdb_var_create,
974 pack);
975 }
976 else
977 {
978 DEBUG_PRINT("%s", "You shouldn't read this, debug_tree_add_watch");
979 if (var->value == NULL)
980 {
981 /* Get value */
982 DmaVariablePacket *pack =
983
984 pack = dma_variable_packet_new(model, &iter, tree->debugger, data, 0);
985 dma_queue_evaluate_variable (
986 tree->debugger,
987 var->name,
988 (IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
989 pack);
990 }
991 }
992 }
993 }
994 }
995
996 static void
on_add_watch(gpointer data,gpointer user_data)997 on_add_watch (gpointer data, gpointer user_data)
998 {
999 DebugTree* this = (DebugTree *)user_data;
1000 gboolean auto_update = ((const gchar *)data)[0] & AUTO_UPDATE_WATCH ? TRUE : FALSE;
1001 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
1002
1003 var.expression = &((gchar *)data)[1];
1004 debug_tree_add_watch (this, &var, auto_update);
1005 }
1006
1007 void
debug_tree_add_full_watch_list(DebugTree * this,GList * expressions)1008 debug_tree_add_full_watch_list (DebugTree *this, GList *expressions)
1009 {
1010 g_list_foreach (expressions, on_add_watch, this);
1011 }
1012
1013 static void
on_add_manual_watch(gpointer data,gpointer user_data)1014 on_add_manual_watch (gpointer data, gpointer user_data)
1015 {
1016 DebugTree* this = (DebugTree *)user_data;
1017 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
1018
1019 var.expression = &((gchar *)data)[0];
1020 debug_tree_add_watch (this, &var, FALSE);
1021 }
1022
1023 static void
on_add_auto_watch(gpointer data,gpointer user_data)1024 on_add_auto_watch (gpointer data, gpointer user_data)
1025 {
1026 DebugTree* this = (DebugTree *)user_data;
1027 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, -1};
1028
1029 var.expression = &((gchar *)data)[0];
1030 debug_tree_add_watch (this, &var, TRUE);
1031 }
1032
1033 void
debug_tree_add_watch_list(DebugTree * this,GList * expressions,gboolean auto_update)1034 debug_tree_add_watch_list (DebugTree *this, GList *expressions, gboolean auto_update)
1035 {
1036 g_list_foreach (expressions, auto_update ? on_add_auto_watch : on_add_manual_watch, this);
1037 }
1038
1039 static void
on_debug_tree_changed(gpointer data,gpointer user_data)1040 on_debug_tree_changed (gpointer data, gpointer user_data)
1041 {
1042 IAnjutaDebuggerVariableObject *var = (IAnjutaDebuggerVariableObject *)data;
1043
1044 if (var->name != NULL)
1045 {
1046 /* Search corresponding variable in one tree */
1047 GList *list;
1048
1049 for (list = g_list_first (gTreeList); list != NULL; list = g_list_next (list))
1050 {
1051 DebugTree *tree = (DebugTree *)list->data;
1052
1053 GtkTreeIter iter;
1054 GtkTreeModel *model;
1055
1056 model = debug_tree_get_model (tree);
1057
1058 if (debug_tree_find_name (model, &iter, var->name))
1059 {
1060 DmaVariableData *data;
1061 gtk_tree_model_get (model, &iter, DTREE_ENTRY_COLUMN, &data, -1);
1062
1063 if (data != NULL)
1064 {
1065 data->changed = var->changed;
1066 data->exited = var->exited;
1067 data->deleted = var->deleted;
1068 }
1069
1070 return;
1071 }
1072 }
1073 }
1074 }
1075
1076 static gboolean
debug_tree_update_real(GtkTreeModel * model,DmaDebuggerQueue * debugger,GtkTreeIter * iter,gboolean force)1077 debug_tree_update_real (GtkTreeModel *model, DmaDebuggerQueue *debugger, GtkTreeIter* iter, gboolean force)
1078 {
1079 DmaVariableData *data = NULL;
1080 GtkTreeIter child;
1081 gboolean search;
1082 gboolean refresh = TRUE;
1083
1084 gtk_tree_model_get (model, iter, DTREE_ENTRY_COLUMN, &data, -1);
1085 if (data == NULL) return FALSE;
1086
1087
1088 if ((data->deleted) && (data->name != NULL) && (force || data->auto_update))
1089 {
1090 /* Variable deleted (by example if type change), try to recreate it */
1091 dma_queue_delete_variable (debugger, data->name);
1092 g_free (data->name);
1093 data->name = NULL;
1094 }
1095
1096 if (data->name == NULL)
1097 {
1098 /* Check is the variable creation is not pending */
1099 if (data->packet == NULL)
1100 {
1101 /* Variable need to be created first */
1102 gchar *exp;
1103 DmaVariablePacket *pack;
1104
1105 gtk_tree_model_get (model, iter, VARIABLE_COLUMN, &exp, -1);
1106 pack = dma_variable_packet_new(model, iter, debugger, data, 0);
1107 dma_queue_create_variable (
1108 debugger,
1109 exp,
1110 (IAnjutaDebuggerCallback)gdb_var_create,
1111 pack);
1112 g_free (exp);
1113 }
1114
1115 return FALSE;
1116 }
1117 else if (force || (data->auto_update && data->changed))
1118 {
1119 DmaVariablePacket *pack = dma_variable_packet_new(model, iter, debugger, data, 0);
1120 refresh = data->modified != (data->changed != FALSE);
1121 data->modified = (data->changed != FALSE);
1122 dma_queue_evaluate_variable (
1123 debugger,
1124 data->name,
1125 (IAnjutaDebuggerCallback)gdb_var_evaluate_expression,
1126 pack);
1127 data->changed = FALSE;
1128 }
1129 else
1130 {
1131 refresh = data->modified;
1132 data->modified = FALSE;
1133 }
1134
1135 /* update children */
1136 for (search = gtk_tree_model_iter_children(model, &child, iter);
1137 search == TRUE;
1138 search = gtk_tree_model_iter_next (model, &child))
1139 {
1140 if (debug_tree_update_real (model, debugger, &child, force))
1141 {
1142 refresh = data->modified == TRUE;
1143 data->modified = TRUE;
1144 }
1145 }
1146
1147 if (refresh)
1148 {
1149 GtkTreePath *path;
1150 path = gtk_tree_model_get_path (model, iter);
1151 gtk_tree_model_row_changed (model, path, iter);
1152 gtk_tree_path_free (path);
1153 }
1154
1155 return data->modified;
1156 }
1157
1158
1159 /* Get information from debugger and update variable with automatic update */
1160 static void
on_debug_tree_update_all(const GList * change,gpointer user_data,GError * err)1161 on_debug_tree_update_all (const GList *change, gpointer user_data, GError* err)
1162 {
1163 DmaDebuggerQueue *debugger = (DmaDebuggerQueue *)user_data;
1164 GList *list;
1165
1166 if (err != NULL) return;
1167
1168 // Update all variables information from debugger data
1169 g_list_foreach ((GList *)change, on_debug_tree_changed, NULL);
1170
1171 // Update all tree models
1172 for (list = g_list_first (gTreeList); list != NULL; list = g_list_next (list))
1173 {
1174 DebugTree* tree = (DebugTree*)list->data;
1175
1176 GtkTreeModel* model;
1177 GtkTreeIter iter;
1178 gboolean valid;
1179
1180 model = debug_tree_get_model (tree);
1181
1182 // Update this tree
1183 for (valid = gtk_tree_model_get_iter_first (model, &iter);
1184 valid;
1185 valid = gtk_tree_model_iter_next (model, &iter))
1186 {
1187 debug_tree_update_real (model, debugger, &iter, FALSE);
1188 }
1189 }
1190 }
1191
1192 void
debug_tree_update_all(DmaDebuggerQueue * debugger)1193 debug_tree_update_all (DmaDebuggerQueue *debugger)
1194 {
1195 dma_queue_update_variable (debugger,
1196 (IAnjutaDebuggerCallback)on_debug_tree_update_all,
1197 debugger);
1198 }
1199
1200 /* Update all variables in the specified tree */
1201 void
debug_tree_update_tree(DebugTree * this)1202 debug_tree_update_tree (DebugTree *this)
1203 {
1204 GtkTreeModel *model;
1205 GtkTreeIter iter;
1206 gboolean valid;
1207
1208 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1209
1210 // Update this tree
1211 for (valid = gtk_tree_model_get_iter_first (model, &iter);
1212 valid;
1213 valid = gtk_tree_model_iter_next (model, &iter))
1214 {
1215 debug_tree_update_real (model, this->debugger, &iter, TRUE);
1216 }
1217 }
1218
1219 GList*
debug_tree_get_full_watch_list(DebugTree * this)1220 debug_tree_get_full_watch_list (DebugTree *this)
1221 {
1222 GtkTreeIter iter;
1223 GtkTreeModel *model;
1224 GList* list = NULL;
1225
1226 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1227
1228 if (gtk_tree_model_get_iter_first (model, &iter) == TRUE)
1229 {
1230 do
1231 {
1232 DmaVariableData *data;
1233 gchar *exp;
1234 gchar *exp_with_flag;
1235
1236 gtk_tree_model_get(model, &iter, DTREE_ENTRY_COLUMN, &data,
1237 VARIABLE_COLUMN, &exp, -1);
1238
1239 if (data != NULL)
1240 {
1241 exp_with_flag = g_strconcat (" ", exp, NULL);
1242 exp_with_flag[0] = data->auto_update ? AUTO_UPDATE_WATCH : ' ';
1243 list = g_list_prepend (list, exp_with_flag);
1244 }
1245 g_free (exp);
1246 } while (gtk_tree_model_iter_next (model, &iter) == TRUE);
1247 }
1248
1249 list = g_list_reverse (list);
1250
1251 return list;
1252 }
1253
1254
1255 GtkWidget *
debug_tree_get_tree_widget(DebugTree * this)1256 debug_tree_get_tree_widget (DebugTree *this)
1257 {
1258 return this->view;
1259 }
1260
1261 gboolean
debug_tree_get_current(DebugTree * tree,GtkTreeIter * iter)1262 debug_tree_get_current (DebugTree *tree, GtkTreeIter* iter)
1263 {
1264 return get_current_iter (GTK_TREE_VIEW (tree->view), iter);
1265 }
1266
1267 /* Return TRUE if iter is still valid (point to next item) */
1268 gboolean
debug_tree_remove(DebugTree * tree,GtkTreeIter * iter)1269 debug_tree_remove (DebugTree *tree, GtkTreeIter* iter)
1270 {
1271 GtkTreeModel *model;
1272
1273 g_return_val_if_fail (tree, FALSE);
1274 g_return_val_if_fail (tree->view, FALSE);
1275 g_return_val_if_fail (iter, FALSE);
1276
1277 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1278
1279 delete_parent (model, NULL, iter, tree->debugger);
1280 return gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
1281 }
1282
1283 gboolean
debug_tree_update(DebugTree * tree,GtkTreeIter * iter,gboolean force)1284 debug_tree_update (DebugTree* tree, GtkTreeIter* iter, gboolean force)
1285 {
1286 if (tree->debugger != NULL)
1287 {
1288 GtkTreeModel *model;
1289
1290 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1291 return debug_tree_update_real (model, tree->debugger, iter, force);
1292 }
1293 else
1294 {
1295 return FALSE;
1296 }
1297 }
1298
1299 void
debug_tree_set_auto_update(DebugTree * this,GtkTreeIter * iter,gboolean state)1300 debug_tree_set_auto_update (DebugTree* this, GtkTreeIter* iter, gboolean state)
1301 {
1302 GtkTreeModel *model;
1303 DmaVariableData *data;
1304
1305 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1306 gtk_tree_model_get(model, iter, DTREE_ENTRY_COLUMN, &data, -1);
1307 if (data != NULL)
1308 {
1309 data->auto_update = state;
1310 }
1311 }
1312
1313 gboolean
debug_tree_get_auto_update(DebugTree * this,GtkTreeIter * iter)1314 debug_tree_get_auto_update (DebugTree* this, GtkTreeIter* iter)
1315 {
1316 GtkTreeModel *model;
1317 DmaVariableData *data;
1318
1319 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1320 gtk_tree_model_get(model, iter, DTREE_ENTRY_COLUMN, &data, -1);
1321
1322 if (data != NULL)
1323 {
1324 return data->auto_update;
1325 }
1326 else
1327 {
1328 return FALSE;
1329 }
1330 }
1331
1332 void
debug_tree_connect(DebugTree * this,DmaDebuggerQueue * debugger)1333 debug_tree_connect (DebugTree *this, DmaDebuggerQueue* debugger)
1334 {
1335 this->debugger = debugger;
1336 }
1337
1338 static gboolean
on_disconnect_variable(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer user_data)1339 on_disconnect_variable (GtkTreeModel *model,
1340 GtkTreePath *path,
1341 GtkTreeIter *iter,
1342 gpointer user_data)
1343 {
1344 DmaVariableData *data;
1345
1346 gtk_tree_model_get (model, iter, DTREE_ENTRY_COLUMN, &data, -1);
1347
1348 if (data != NULL)
1349 {
1350 g_free (data->name);
1351 data->name = NULL;
1352 }
1353
1354 return FALSE;
1355 }
1356
1357 void
debug_tree_disconnect(DebugTree * this)1358 debug_tree_disconnect (DebugTree *this)
1359 {
1360 GtkTreeModel *model;
1361
1362 this->debugger = NULL;
1363 model = gtk_tree_view_get_model (GTK_TREE_VIEW (this->view));
1364
1365 /* Remove all variable name */
1366 gtk_tree_model_foreach (model, on_disconnect_variable, NULL);
1367 }
1368
1369 GtkTreeModel *
debug_tree_get_model(DebugTree * tree)1370 debug_tree_get_model (DebugTree *tree)
1371 {
1372 return gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1373 }
1374
1375 void
debug_tree_set_model(DebugTree * tree,GtkTreeModel * model)1376 debug_tree_set_model (DebugTree *tree, GtkTreeModel *model)
1377 {
1378 gtk_tree_view_set_model (GTK_TREE_VIEW (tree->view), model);
1379 }
1380
1381 void
debug_tree_new_model(DebugTree * tree)1382 debug_tree_new_model (DebugTree *tree)
1383 {
1384 GtkTreeModel * model = GTK_TREE_MODEL (gtk_tree_store_new
1385 (N_COLUMNS,
1386 G_TYPE_STRING,
1387 G_TYPE_STRING,
1388 G_TYPE_STRING,
1389 G_TYPE_BOOLEAN,
1390 G_TYPE_POINTER));
1391
1392 gtk_tree_view_set_model (GTK_TREE_VIEW (tree->view), model);
1393 }
1394
1395 void
debug_tree_remove_model(DebugTree * tree,GtkTreeModel * model)1396 debug_tree_remove_model (DebugTree *tree, GtkTreeModel *model)
1397 {
1398 my_gtk_tree_model_foreach_child (model, NULL, delete_parent, tree->debugger);
1399 gtk_tree_store_clear (GTK_TREE_STORE (model));
1400 }
1401
1402 gchar *
debug_tree_get_selected(DebugTree * tree)1403 debug_tree_get_selected (DebugTree *tree)
1404 {
1405 GtkTreeIter iter;
1406 gchar *exp = NULL;
1407
1408 if (get_current_iter (GTK_TREE_VIEW (tree->view), &iter))
1409 {
1410 GtkTreeModel *model;
1411
1412 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1413 if (model != NULL)
1414 {
1415 gtk_tree_model_get(model, &iter, VARIABLE_COLUMN, &exp, -1);
1416 }
1417 }
1418
1419 return exp;
1420 }
1421
1422 gchar *
debug_tree_get_first(DebugTree * tree)1423 debug_tree_get_first (DebugTree *tree)
1424 {
1425 GtkTreeIter iter;
1426 gchar *exp = NULL;
1427 GtkTreeModel *model;
1428
1429 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1430 if (model != NULL)
1431 {
1432 if (gtk_tree_model_get_iter_first (model, &iter))
1433 {
1434 gtk_tree_model_get(model, &iter, VARIABLE_COLUMN, &exp, -1);
1435 }
1436 }
1437
1438 return exp;
1439 }
1440
1441 gchar*
debug_tree_find_variable_value(DebugTree * tree,const gchar * name)1442 debug_tree_find_variable_value (DebugTree *tree, const gchar *name)
1443 {
1444 GtkTreeModel *model;
1445 GtkTreeIter iter;
1446
1447 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree->view));
1448
1449 if (gtk_tree_model_get_iter_first (model, &iter))
1450 {
1451 gchar *exp;
1452 gchar *value;
1453 do
1454 {
1455 gtk_tree_model_get(model, &iter, VARIABLE_COLUMN, &exp,
1456 VALUE_COLUMN, &value, -1);
1457
1458 if (strcmp (exp, name) == 0)
1459 {
1460 return value;
1461 }
1462 } while (gtk_tree_model_iter_next (model, &iter));
1463 }
1464
1465 return NULL;
1466 }
1467
1468 /* Debugging functions
1469 *---------------------------------------------------------------------------*/
1470
1471 static void
debug_tree_dump_iter(GtkTreeModel * model,GtkTreeIter * iter,guint indent)1472 debug_tree_dump_iter (GtkTreeModel *model, GtkTreeIter *iter, guint indent)
1473 {
1474 gchar *expression;
1475 gchar *value;
1476 gchar *type;
1477 DmaVariableData *node;
1478 GtkTreeIter child;
1479 gboolean valid;
1480
1481 gtk_tree_model_get (model, iter,
1482 VARIABLE_COLUMN, &expression,
1483 VALUE_COLUMN, &value,
1484 TYPE_COLUMN, &type,
1485 DTREE_ENTRY_COLUMN, &node,
1486 -1);
1487 if (node != NULL)
1488 {
1489 g_message ("%*s %s | %s | %s | %s | %d%d%d%d%d", indent, "",
1490 expression, value, type, node->name,
1491 node->modified, node->changed, node->exited, node->deleted, node->auto_update);
1492 }
1493 else
1494 {
1495 g_message ("%*s %s | %s | %s | %s | %c%c%c%c%c", indent, "",
1496 expression, value, type, "???",
1497 '?','?','?','?','?');
1498 }
1499 g_free (expression);
1500 g_free (value);
1501 g_free (type);
1502
1503 for (valid = gtk_tree_model_iter_children (model, &child, iter);
1504 valid;
1505 valid = gtk_tree_model_iter_next (model, &child))
1506 {
1507 debug_tree_dump_iter (model, &child, indent + 4);
1508 }
1509 }
1510
1511 void
debug_tree_dump(void)1512 debug_tree_dump (void)
1513 {
1514 GList *list;
1515
1516 for (list = g_list_first (gTreeList); list != NULL; list = g_list_next (list))
1517 {
1518 DebugTree* tree = (DebugTree*)list->data;
1519
1520 GtkTreeModel* model;
1521 GtkTreeIter iter;
1522 gboolean valid;
1523
1524 model = debug_tree_get_model (tree);
1525 g_message ("Tree model %p MCEDU", model);
1526 for (valid = gtk_tree_model_get_iter_first (model, &iter);
1527 valid;
1528 valid = gtk_tree_model_iter_next (model, &iter))
1529 {
1530 debug_tree_dump_iter (model, &iter, 4);
1531 }
1532 }
1533 }
1534
1535 /* Constructor & Destructor
1536 *---------------------------------------------------------------------------*/
1537
1538 /* return a pointer to a newly allocated DebugTree object */
1539 DebugTree *
debug_tree_new_with_view(AnjutaPlugin * plugin,GtkTreeView * view)1540 debug_tree_new_with_view (AnjutaPlugin *plugin, GtkTreeView *view)
1541 {
1542 DebugTree *tree = g_new0 (DebugTree, 1);
1543
1544 tree->plugin = plugin;
1545 tree->view = debug_tree_create(tree, view);
1546 tree->auto_expand = FALSE;
1547
1548 /* Add this tree in list */
1549 gTreeList = g_list_prepend (gTreeList, tree);
1550
1551 /* Connect signal */
1552 g_signal_connect(GTK_TREE_VIEW (tree->view), "row_expanded", G_CALLBACK (on_treeview_row_expanded), tree);
1553
1554
1555 return tree;
1556 }
1557
1558
1559 /* return a pointer to a newly allocated DebugTree object */
1560 DebugTree *
debug_tree_new(AnjutaPlugin * plugin)1561 debug_tree_new (AnjutaPlugin* plugin)
1562 {
1563 return debug_tree_new_with_view (plugin, NULL);
1564 }
1565
1566 /* DebugTree destructor */
1567 void
debug_tree_free(DebugTree * tree)1568 debug_tree_free (DebugTree * tree)
1569 {
1570 g_return_if_fail (tree);
1571
1572 debug_tree_remove_all (tree);
1573
1574 /* Remove from list */
1575 gTreeList = g_list_remove (gTreeList, tree);
1576
1577 g_signal_handlers_disconnect_by_func (GTK_TREE_VIEW (tree->view),
1578 G_CALLBACK (on_treeview_row_expanded), tree);
1579
1580 gtk_widget_destroy (tree->view);
1581
1582
1583 g_free (tree);
1584 }
1585