Integrate adding files with the file manager
[anjuta-git-plugin.git] / plugins / debug-manager / stack_trace.c
blob1132dd39aea3e3a6d5d8d1674ba3b0270fda2af1
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 stack_trace.c
4 Copyright (C) 2000 Kh. Naba Kumar Singh
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
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
24 #include "stack_trace.h"
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <gnome.h>
32 /*#define DEBUG*/
33 #include <libanjuta/resources.h>
34 #include <libanjuta/anjuta-debug.h>
35 #include <libanjuta/interfaces/ianjuta-editor.h>
36 #include <libanjuta/interfaces/ianjuta-document-manager.h>
37 #include <libgnomevfs/gnome-vfs-utils.h>
39 #include "utilities.h"
40 #include "info.h"
41 #include "queue.h"
43 #define ANJUTA_PIXMAP_POINTER PACKAGE_PIXMAPS_DIR"/pointer.png"
45 typedef struct _DmaThreadStackTrace
47 GtkTreeModel *model;
48 gint thread;
49 guint last_update;
50 } DmaThreadStackTrace;
52 struct _StackTrace
54 DebugManagerPlugin *plugin;
55 DmaDebuggerQueue *debugger;
57 GtkActionGroup *action_group;
59 DmaThreadStackTrace* current;
60 GList *list;
62 gint current_frame;
63 guint current_update;
65 GtkTreeView *treeview;
66 GtkMenu *menu;
67 GtkWidget *scrolledwindow;
70 enum {
71 STACK_TRACE_ACTIVE_COLUMN,
72 STACK_TRACE_FRAME_COLUMN,
73 STACK_TRACE_FILE_COLUMN,
74 STACK_TRACE_LINE_COLUMN,
75 STACK_TRACE_FUNC_COLUMN,
76 STACK_TRACE_ADDR_COLUMN,
77 STACK_TRACE_ARGS_COLUMN,
78 STACK_TRACE_URI_COLUMN,
79 STACK_TRACE_COLOR_COLUMN,
80 STACK_TRACE_N_COLUMNS
83 /* Helpers functions
84 *---------------------------------------------------------------------------*/
86 static gboolean
87 get_current_iter (GtkTreeView *view, GtkTreeIter* iter)
89 GtkTreeSelection *selection;
91 selection = gtk_tree_view_get_selection (view);
92 return gtk_tree_selection_get_selected (selection, NULL, iter);
96 * returns the current stack frame or -1 on error
98 static gint
99 get_current_index (StackTrace* st)
101 GtkTreeIter iter;
103 if (get_current_iter (st->treeview, &iter))
105 GtkTreeModel *model;
106 gint frame_no;
108 model = gtk_tree_view_get_model (st->treeview);
109 gtk_tree_model_get (model, &iter, STACK_TRACE_FRAME_COLUMN, &frame_no, -1);
111 return frame_no;
113 else
115 return -1;
119 static gboolean
120 my_gtk_tree_model_get_iter_last(GtkTreeModel *model, GtkTreeIter *last)
122 gboolean exist;
123 GtkTreeIter iter;
125 exist = gtk_tree_model_get_iter_first(model, &iter);
126 if (!exist) return FALSE;
130 *last = iter;
131 exist = gtk_tree_model_iter_next(model, &iter);
133 while (exist);
135 return TRUE;
138 static gboolean
139 my_gtk_tree_model_iter_prev(GtkTreeModel *model, GtkTreeIter *iter)
141 GtkTreePath* path;
142 gboolean exist;
144 path = gtk_tree_model_get_path (model, iter);
145 exist = gtk_tree_path_prev (path);
146 if (exist)
148 exist = gtk_tree_model_get_iter (model, iter, path);
150 gtk_tree_path_free (path);
152 return exist;
155 static gint
156 my_gtk_tree_iter_compare(GtkTreeModel *model, GtkTreeIter *itera, GtkTreeIter *iterb)
158 GtkTreePath* patha;
159 GtkTreePath* pathb;
160 gint comp;
162 patha = gtk_tree_model_get_path (model, itera);
163 pathb = gtk_tree_model_get_path (model, iterb);
165 comp = gtk_tree_path_compare (patha, pathb);
167 gtk_tree_path_free (patha);
168 gtk_tree_path_free (pathb);
170 return comp;
173 /* Private functions
174 *---------------------------------------------------------------------------*/
176 static void
177 on_clear_stack_trace (gpointer data, gpointer user_data)
179 DmaThreadStackTrace *trace = (DmaThreadStackTrace *) data;
181 g_object_unref (G_OBJECT (trace->model));
182 g_free (trace);
185 static void
186 dma_thread_clear_all_stack_trace (StackTrace *self)
188 /* Clear all GtkListStore */
189 g_list_foreach (self->list, (GFunc)on_clear_stack_trace, NULL);
190 g_list_free (self->list);
192 self->current = NULL;
193 self->list = NULL;
196 static void
197 on_stack_trace_updated (const GList *stack, gpointer user_data, GError *error)
199 StackTrace *self = (StackTrace *)user_data;
200 const GList *node;
201 GtkListStore *model;
202 GtkTreeIter iter;
203 gboolean exist;
204 GdkPixbuf *pic;
206 if (error != NULL) return;
208 model = GTK_LIST_STORE (self->current->model);
210 pic = gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER, NULL);
212 exist = my_gtk_tree_model_get_iter_last (GTK_TREE_MODEL (model), &iter);
214 for (node = (const GList *)g_list_last((GList *)stack); node != NULL; node = node->prev)
216 IAnjutaDebuggerFrame *frame;
217 gchar *adr;
218 gchar *uri;
219 gchar *file;
221 frame = (IAnjutaDebuggerFrame *)node->data;
223 if (exist)
225 /* Check if it's the same stack frame */
226 gchar *adr;
227 gchar *args;
228 gulong address;
229 guint line;
230 gboolean same;
232 gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
233 STACK_TRACE_ADDR_COLUMN, &adr,
234 STACK_TRACE_LINE_COLUMN, &line,
235 STACK_TRACE_ARGS_COLUMN, &args,
236 -1);
237 address = adr != NULL ? strtoul (adr, NULL, 0) : 0;
238 same = (address == frame->address) && (line == frame->line);
239 if ((args == NULL) || (frame->args == NULL))
241 same = same && (args == frame->args);
243 else
245 same = same && (strcmp (args, frame->args) == 0);
247 g_free (adr);
248 g_free (args);
250 if (same)
252 /* Same frame, just change the color */
253 gtk_list_store_set (model, &iter,
254 STACK_TRACE_ACTIVE_COLUMN, frame->level == self->current_frame ? pic : NULL,
255 STACK_TRACE_FRAME_COLUMN, frame->level,
256 STACK_TRACE_COLOR_COLUMN, "black", -1);
258 /* Check previous frame */
259 exist = my_gtk_tree_model_iter_prev (GTK_TREE_MODEL (model), &iter);
260 if (!exist || (node->prev != NULL))
262 /* Last frame or Upper frame still exist */
263 continue;
265 /* Upper frame do not exist, remove all them */
268 /* New frame, remove all previous frame */
269 GtkTreeIter first;
271 gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &first);
272 while (my_gtk_tree_iter_compare (GTK_TREE_MODEL (model), &first, &iter) < 0)
274 gtk_list_store_remove (model, &first);
276 gtk_list_store_remove (model, &first);
278 if (same)
280 break;
282 else
284 exist = FALSE;
288 gtk_list_store_prepend (model, &iter);
290 adr = g_strdup_printf ("0x%lx", frame->address);
291 if (frame->file)
293 if (g_path_is_absolute (frame->file))
295 uri = gnome_vfs_get_uri_from_local_path(frame->file);
296 file = strrchr(frame->file, G_DIR_SEPARATOR) + 1;
298 else
300 uri = NULL;
301 file = frame->file;
304 else
306 uri = NULL;
307 file = frame->library;
310 gtk_list_store_set(model, &iter,
311 STACK_TRACE_ACTIVE_COLUMN, frame->level == self->current_frame ? pic : NULL,
312 STACK_TRACE_FRAME_COLUMN, frame->level,
313 STACK_TRACE_FILE_COLUMN, file,
314 STACK_TRACE_LINE_COLUMN, frame->line,
315 STACK_TRACE_FUNC_COLUMN, frame->function,
316 STACK_TRACE_ADDR_COLUMN, adr,
317 STACK_TRACE_ARGS_COLUMN, frame->args,
318 STACK_TRACE_URI_COLUMN, uri,
319 STACK_TRACE_COLOR_COLUMN, "red",
320 -1);
321 g_free (uri);
322 g_free (adr);
324 gdk_pixbuf_unref (pic);
328 static DmaThreadStackTrace*
329 dma_thread_create_new_stack_trace (StackTrace *self, gint thread)
331 DmaThreadStackTrace *trace;
332 GtkListStore *store;
334 /* Create new list store */
335 store = gtk_list_store_new (STACK_TRACE_N_COLUMNS,
336 GDK_TYPE_PIXBUF,
337 G_TYPE_UINT,
338 G_TYPE_STRING,
339 G_TYPE_UINT,
340 G_TYPE_STRING,
341 G_TYPE_STRING,
342 G_TYPE_STRING,
343 G_TYPE_STRING,
344 G_TYPE_STRING);
346 trace = g_new (DmaThreadStackTrace, 1);
347 trace->thread = thread;
348 trace->model = GTK_TREE_MODEL (store);
349 trace->last_update = self->current_update;
351 self->current = trace;
353 /* Ask debugger to get all frame data */
354 dma_queue_list_frame (
355 self->debugger,
356 (IAnjutaDebuggerCallback)on_stack_trace_updated,
357 self);
359 self->list = g_list_append (self->list, trace);
361 return trace;
364 static DmaThreadStackTrace*
365 dma_thread_update_stack_trace (StackTrace *self, DmaThreadStackTrace *trace)
367 trace->last_update = self->current_update;
369 /* Ask debugger to get all frame data */
370 dma_queue_list_frame (
371 self->debugger,
372 (IAnjutaDebuggerCallback)on_stack_trace_updated,
373 self);
375 return trace;
378 static gboolean
379 on_find_stack_trace (gconstpointer a, gconstpointer b)
381 const DmaThreadStackTrace *trace = (const DmaThreadStackTrace *)a;
382 guint thread = (gint)b;
384 return trace->thread != thread;
387 static void
388 dma_thread_set_stack_trace (StackTrace *self, gint thread)
390 GList *list;
391 DmaThreadStackTrace *trace;
393 if ((self->current == NULL) || (self->current->thread != thread) || (self->current->last_update != self->current_update))
395 self->current_frame = 0;
397 list = g_list_find_custom (self->list, (gconstpointer) thread, on_find_stack_trace);
399 if (list == NULL)
401 /* Create new stack trace */
402 trace = dma_thread_create_new_stack_trace(self, thread);
404 else
406 trace = (DmaThreadStackTrace *)list->data;
407 self->current = trace;
409 if (trace->last_update != self->current_update)
411 /* Update stack trace */
412 dma_thread_update_stack_trace (self, trace);
415 gtk_tree_view_set_model (self->treeview, trace->model);
419 /* Callback functions
420 *---------------------------------------------------------------------------*/
422 static void
423 on_frame_changed (StackTrace *self, guint frame, gint thread)
425 GtkTreeIter iter;
426 GtkTreeModel *model;
428 /* Change thread */
429 dma_thread_set_stack_trace (self, thread);
431 /* Change frame */
432 self->current_frame = frame;
434 model = self->current->model;
436 /* Clear old pointer */
437 if(gtk_tree_model_get_iter_first (model, &iter))
441 /* clear pixmap on the previous active frame */
442 gtk_list_store_set (GTK_LIST_STORE (model), &iter,
443 STACK_TRACE_ACTIVE_COLUMN, NULL, -1);
444 } while (gtk_tree_model_iter_next (model, &iter));
447 /* Set pointer to current frame */
448 if (gtk_tree_model_iter_nth_child (model, &iter, NULL, self->current_frame))
450 GdkPixbuf *pointer_pix = gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER, NULL);
452 /* set pointer on this frame */
453 gtk_list_store_set (GTK_LIST_STORE(model), &iter,
454 STACK_TRACE_ACTIVE_COLUMN, pointer_pix,
455 -1);
456 gdk_pixbuf_unref (pointer_pix);
460 static void
461 on_stack_frame_set_activate (GtkAction *action, gpointer user_data)
463 StackTrace *st;
464 guint selected_frame;
466 st = (StackTrace*) user_data;
468 selected_frame = get_current_index (st);
470 /* No frame selected */
471 if (selected_frame == -1)
472 return;
474 /* current frame is already active */
475 if (selected_frame == st->current_frame)
476 return;
478 /* issue a command to switch active frame to new location */
479 dma_queue_set_frame (st->debugger, selected_frame);
482 static void
483 on_stack_view_source_activate (GtkAction *action, gpointer user_data)
485 GtkTreeModel *model;
486 GtkTreeSelection *selection;
487 GtkTreeIter iter;
488 GtkTreeView *view;
489 gchar *uri;
490 guint line;
491 gchar *adr;
492 gulong address;
494 StackTrace* st = (StackTrace*) user_data;
496 view = st->treeview;
497 selection = gtk_tree_view_get_selection (view);
498 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
499 return;
501 /* get the frame info */
502 gtk_tree_model_get (model, &iter,
503 STACK_TRACE_URI_COLUMN, &uri,
504 STACK_TRACE_LINE_COLUMN, &line,
505 STACK_TRACE_ADDR_COLUMN, &adr,
506 -1);
508 address = adr != NULL ? strtoul (adr, NULL, 0) : 0;
509 g_signal_emit_by_name (st->plugin, "location-changed", address, uri, line);
510 g_free (uri);
511 g_free (adr);
514 static void
515 on_stack_trace_row_activated (GtkTreeView *treeview,
516 GtkTreePath *arg1,
517 GtkTreeViewColumn *arg2,
518 StackTrace *st)
520 on_stack_frame_set_activate (NULL, st);
523 static gboolean
524 on_stack_trace_button_press (GtkWidget *widget, GdkEventButton *bevent, gpointer user_data)
526 StackTrace *st = (StackTrace*) user_data;
528 if ((bevent->type == GDK_BUTTON_PRESS) && (bevent->button == 3))
530 /* Right mouse click */
531 g_return_val_if_fail (st->menu != NULL, FALSE);
532 gtk_menu_popup (GTK_MENU (st->menu), NULL, NULL, NULL, NULL,
533 bevent->button, bevent->time);
535 else if ((bevent->type == GDK_2BUTTON_PRESS) && (bevent->button == 1))
537 /* Double left mouse click */
538 on_stack_view_source_activate (NULL, user_data);
541 return FALSE;
544 /* Actions table
545 *---------------------------------------------------------------------------*/
547 static GtkActionEntry actions_stack_trace[] = {
549 "ActionDmaSetCurrentFrame", /* Action name */
550 NULL, /* Stock icon, if any */
551 N_("Set current frame"), /* Display label */
552 NULL, /* short-cut */
553 NULL, /* Tooltip */
554 G_CALLBACK (on_stack_frame_set_activate) /* action callback */
557 "ActionDmaJumpToFrame",
558 NULL,
559 N_("View Source"),
560 NULL,
561 NULL,
562 G_CALLBACK (on_stack_view_source_activate)
566 static void
567 create_stack_trace_gui(StackTrace *st)
569 GtkTreeModel* model;
570 GtkTreeSelection *selection;
571 GtkTreeViewColumn *column;
572 GtkCellRenderer *renderer;
573 AnjutaUI *ui;
575 g_return_if_fail (st->scrolledwindow == NULL);
577 /* Create tree view */
578 model = GTK_TREE_MODEL(gtk_list_store_new (STACK_TRACE_N_COLUMNS,
579 GDK_TYPE_PIXBUF,
580 G_TYPE_UINT,
581 G_TYPE_STRING,
582 G_TYPE_UINT,
583 G_TYPE_STRING,
584 G_TYPE_STRING,
585 G_TYPE_STRING,
586 G_TYPE_STRING,
587 G_TYPE_STRING));
588 st->treeview = GTK_TREE_VIEW (gtk_tree_view_new_with_model (model));
589 g_object_unref (G_OBJECT (model));
591 selection = gtk_tree_view_get_selection (st->treeview);
592 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
594 /* Columns */
595 column = gtk_tree_view_column_new ();
596 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
597 gtk_tree_view_column_set_title (column, _("Active"));
598 renderer = gtk_cell_renderer_pixbuf_new ();
599 gtk_tree_view_column_pack_start (column, renderer, TRUE);
600 gtk_tree_view_column_add_attribute (column, renderer, "pixbuf",
601 STACK_TRACE_ACTIVE_COLUMN);
602 gtk_tree_view_append_column (st->treeview, column);
603 gtk_tree_view_set_expander_column (st->treeview,
604 column);
606 column = gtk_tree_view_column_new ();
607 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
608 gtk_tree_view_column_set_title (column, _("Frame"));
609 renderer = gtk_cell_renderer_text_new ();
610 gtk_tree_view_column_pack_start (column, renderer, TRUE);
611 gtk_tree_view_column_add_attribute (column, renderer, "text",
612 STACK_TRACE_FRAME_COLUMN);
613 gtk_tree_view_column_add_attribute (column, renderer, "foreground",
614 STACK_TRACE_COLOR_COLUMN);
615 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
616 gtk_tree_view_append_column (st->treeview, column);
617 gtk_tree_view_set_expander_column (st->treeview,
618 column);
620 column = gtk_tree_view_column_new ();
621 renderer = gtk_cell_renderer_text_new ();
622 gtk_tree_view_column_pack_start (column, renderer, TRUE);
623 gtk_tree_view_column_add_attribute (column, renderer, "text",
624 STACK_TRACE_FILE_COLUMN);
625 gtk_tree_view_column_add_attribute (column, renderer, "foreground",
626 STACK_TRACE_COLOR_COLUMN);
627 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
628 gtk_tree_view_column_set_title (column, _("File"));
629 gtk_tree_view_append_column (st->treeview, column);
631 column = gtk_tree_view_column_new ();
632 renderer = gtk_cell_renderer_text_new ();
633 gtk_tree_view_column_pack_start (column, renderer, TRUE);
634 gtk_tree_view_column_add_attribute (column, renderer, "text",
635 STACK_TRACE_LINE_COLUMN);
636 gtk_tree_view_column_add_attribute (column, renderer, "foreground",
637 STACK_TRACE_COLOR_COLUMN);
638 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
639 gtk_tree_view_column_set_title (column, _("Line"));
640 gtk_tree_view_append_column (st->treeview, column);
642 column = gtk_tree_view_column_new ();
643 renderer = gtk_cell_renderer_text_new ();
644 gtk_tree_view_column_pack_start (column, renderer, TRUE);
645 gtk_tree_view_column_add_attribute (column, renderer, "text",
646 STACK_TRACE_FUNC_COLUMN);
647 gtk_tree_view_column_add_attribute (column, renderer, "foreground",
648 STACK_TRACE_COLOR_COLUMN);
649 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
650 gtk_tree_view_column_set_title (column, _("Function"));
651 gtk_tree_view_append_column (st->treeview, column);
653 if (dma_debugger_queue_is_supported (st->debugger, HAS_MEMORY))
655 /* Display address only if debugger has such concept */
656 column = gtk_tree_view_column_new ();
657 renderer = gtk_cell_renderer_text_new ();
658 gtk_tree_view_column_pack_start (column, renderer, TRUE);
659 gtk_tree_view_column_add_attribute (column, renderer, "text",
660 STACK_TRACE_ADDR_COLUMN);
661 gtk_tree_view_column_add_attribute (column, renderer, "foreground",
662 STACK_TRACE_COLOR_COLUMN);
663 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
664 gtk_tree_view_column_set_title (column, _("Address"));
665 gtk_tree_view_append_column (st->treeview, column);
668 column = gtk_tree_view_column_new ();
669 renderer = gtk_cell_renderer_text_new ();
670 gtk_tree_view_column_pack_start (column, renderer, TRUE);
671 gtk_tree_view_column_add_attribute (column, renderer, "text",
672 STACK_TRACE_ARGS_COLUMN);
673 gtk_tree_view_column_add_attribute (column, renderer, "foreground",
674 STACK_TRACE_COLOR_COLUMN);
675 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
676 gtk_tree_view_column_set_title (column, _("Arguments"));
677 gtk_tree_view_append_column (st->treeview, column);
679 /* Create popup menu */
680 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN(st->plugin)->shell, NULL);
681 st->menu = GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui), "/PopupStack"));
683 /* Connect signal */
684 g_signal_connect (st->treeview, "button-press-event", G_CALLBACK (on_stack_trace_button_press), st);
685 g_signal_connect (st->treeview, "row-activated", G_CALLBACK (on_stack_trace_row_activated), st);
687 /* Add stack window */
688 st->scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
689 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (st->scrolledwindow),
690 GTK_POLICY_AUTOMATIC,
691 GTK_POLICY_AUTOMATIC);
692 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (st->scrolledwindow),
693 GTK_SHADOW_IN);
694 gtk_container_add (GTK_CONTAINER (st->scrolledwindow),
695 GTK_WIDGET (st->treeview));
696 gtk_widget_show_all (st->scrolledwindow);
698 anjuta_shell_add_widget (ANJUTA_PLUGIN(st->plugin)->shell,
699 st->scrolledwindow,
700 "AnjutaDebuggerStack", _("Stack"),
701 "gdb-stack-icon", ANJUTA_SHELL_PLACEMENT_BOTTOM,
702 NULL);
706 static void
707 destroy_stack_trace_gui (StackTrace *st)
709 if (st->scrolledwindow != NULL)
711 gtk_widget_destroy (st->scrolledwindow);
712 st->scrolledwindow = NULL;
716 static void
717 on_program_moved (StackTrace *self, guint pid, gint thread)
719 self->current_update++;
720 dma_thread_set_stack_trace (self, thread);
723 static void
724 on_program_exited (StackTrace *self)
726 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_exited), self);
727 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_program_moved), self);
728 g_signal_handlers_disconnect_by_func (self->plugin, G_CALLBACK (on_frame_changed), self);
730 dma_thread_clear_all_stack_trace (self);
731 destroy_stack_trace_gui (self);
734 static void
735 on_program_started (StackTrace *self)
737 self->current_update = 0;
738 create_stack_trace_gui (self);
740 g_signal_connect_swapped (self->plugin, "program-exited", G_CALLBACK (on_program_exited), self);
741 g_signal_connect_swapped (self->plugin, "program-moved", G_CALLBACK (on_program_moved), self);
742 g_signal_connect_swapped (self->plugin, "frame-changed", G_CALLBACK (on_frame_changed), self);
745 /* Public functions
746 *---------------------------------------------------------------------------*/
748 /* Constructor & Destructor
749 *---------------------------------------------------------------------------*/
751 StackTrace *
752 stack_trace_new (DebugManagerPlugin *plugin)
754 StackTrace *st;
755 AnjutaUI *ui;
757 st = g_new0 (StackTrace, 1);
758 if (st == NULL) return NULL;
760 st->plugin = plugin;
761 st->debugger = dma_debug_manager_get_queue (plugin);
763 /* Register actions */
764 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN(st->plugin)->shell, NULL);
765 st->action_group =
766 anjuta_ui_add_action_group_entries (ui, "ActionGroupStack",
767 _("Stack frame operations"),
768 actions_stack_trace,
769 G_N_ELEMENTS (actions_stack_trace),
770 GETTEXT_PACKAGE, TRUE, st);
772 g_signal_connect_swapped (st->plugin, "program-started", G_CALLBACK (on_program_started), st);
774 return st;
777 void
778 stack_trace_free (StackTrace * st)
780 AnjutaUI *ui;
782 g_return_if_fail (st != NULL);
784 /* Disconnect from debugger */
785 g_signal_handlers_disconnect_matched (st->plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, st);
787 /* Remove menu actions */
788 ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (st->plugin)->shell, NULL);
789 anjuta_ui_remove_action_group (ui, st->action_group);
791 /* Destroy menu */
792 destroy_stack_trace_gui (st);
794 g_free (st);