3 Copyright (C) 2000 Kh. Naba Kumar Singh
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "stack_trace.h"
34 #include <libanjuta/resources.h>
35 #include <libanjuta/anjuta-debug.h>
36 #include <libanjuta/interfaces/ianjuta-editor.h>
37 #include <libanjuta/interfaces/ianjuta-document-manager.h>
39 #include "utilities.h"
42 #define ANJUTA_PIXMAP_POINTER PACKAGE_PIXMAPS_DIR"/pointer.png"
44 typedef struct _StackTraceGui StackTraceGui
;
47 GtkWidget
*scrolledwindow
;
52 GtkWidget
*menu_update
;
59 IAnjutaDebugger
*debugger
;
60 GtkActionGroup
*action_group
;
61 StackTraceGui widgets
;
66 STACK_TRACE_ACTIVE_COLUMN
,
67 STACK_TRACE_FRAME_COLUMN
,
68 STACK_TRACE_FILE_COLUMN
,
69 STACK_TRACE_LINE_COLUMN
,
70 STACK_TRACE_FUNC_COLUMN
,
71 STACK_TRACE_ADDR_COLUMN
,
72 STACK_TRACE_ARGS_COLUMN
,
73 STACK_TRACE_URI_COLUMN
,
78 *---------------------------------------------------------------------------*/
81 get_current_iter (GtkTreeView
*view
, GtkTreeIter
* iter
)
83 GtkTreeSelection
*selection
;
85 selection
= gtk_tree_view_get_selection (view
);
86 return gtk_tree_selection_get_selected (selection
, NULL
, iter
);
90 * returns the current stack frame or -1 on error
93 get_current_index (StackTrace
* st
)
97 if (get_current_iter (st
->widgets
.clist
, &iter
))
102 model
= gtk_tree_view_get_model (st
->widgets
.clist
);
103 gtk_tree_model_get (model
, &iter
, STACK_TRACE_FRAME_COLUMN
, &frame_no
, -1);
114 *---------------------------------------------------------------------------*/
117 stack_trace_clear (StackTrace
* st
)
121 model
= gtk_tree_view_get_model (st
->widgets
.clist
);
122 gtk_list_store_clear (GTK_LIST_STORE (model
));
125 /* Callback functions
126 *---------------------------------------------------------------------------*/
129 on_stack_trace_updated (const GList
*stack
, gpointer data
)
135 st
= (StackTrace
*) data
;
136 stack_trace_clear (st
);
138 model
= GTK_LIST_STORE (gtk_tree_view_get_model (st
->widgets
.clist
));
140 for (node
= stack
; node
!= NULL
; node
= node
->next
)
144 IAnjutaDebuggerFrame
*frame
;
149 frame
= (IAnjutaDebuggerFrame
*)node
->data
;
151 gtk_list_store_append (model
, &iter
);
153 /* if we are on the current frame set iterator and pixmap correctly */
154 if (frame
->level
== st
->current_frame
)
155 pic
= gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER
, NULL
);
159 adr
= g_strdup_printf ("0x%x", frame
->address
);
162 uri
= g_strconcat ("file://", frame
->file
, NULL
);
163 file
= strrchr(uri
, '/') + 1;
168 file
= frame
->library
;
171 gtk_list_store_set(model
, &iter
,
172 STACK_TRACE_ACTIVE_COLUMN
, pic
,
173 STACK_TRACE_FRAME_COLUMN
, frame
->level
,
174 STACK_TRACE_FILE_COLUMN
, file
,
175 STACK_TRACE_LINE_COLUMN
, frame
->line
,
176 STACK_TRACE_FUNC_COLUMN
, frame
->function
,
177 STACK_TRACE_ADDR_COLUMN
, adr
,
178 STACK_TRACE_ARGS_COLUMN
, frame
->args
,
179 STACK_TRACE_URI_COLUMN
, uri
,
184 gdk_pixbuf_unref (pic
);
189 on_stack_trace_frame_changed (StackTrace
*st
, guint frame
, guint thread
)
194 st
->current_frame
= frame
;
196 model
= gtk_tree_view_get_model (st
->widgets
.clist
);
198 /* Clear old pointer */
199 if(gtk_tree_model_get_iter_first (model
, &iter
))
203 /* clear pixmap on the previous active frame */
204 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
205 STACK_TRACE_ACTIVE_COLUMN
, NULL
, -1);
206 } while (gtk_tree_model_iter_next (model
, &iter
));
209 /* Set pointer to current frame */
210 if (gtk_tree_model_iter_nth_child (model
, &iter
, NULL
, st
->current_frame
))
212 GdkPixbuf
*pointer_pix
= gdk_pixbuf_new_from_file (ANJUTA_PIXMAP_POINTER
, NULL
);
214 /* set pointer on this frame */
215 gtk_list_store_set (GTK_LIST_STORE(model
), &iter
,
216 STACK_TRACE_ACTIVE_COLUMN
, pointer_pix
,
218 gdk_pixbuf_unref (pointer_pix
);
223 on_stack_frame_set_activate (GtkAction
*action
, gpointer user_data
)
226 guint selected_frame
;
228 st
= (StackTrace
*) user_data
;
230 selected_frame
= get_current_index (st
);
232 /* No frame selected */
233 if (selected_frame
== -1)
236 /* current frame is already active */
237 if (selected_frame
== st
->current_frame
)
240 /* issue a command to switch active frame to new location */
241 ianjuta_debugger_set_frame (st
->debugger
, selected_frame
, NULL
);
245 on_stack_view_src_activate (GtkAction
*action
, gpointer user_data
)
248 GtkTreeSelection
*selection
;
254 StackTrace
* st
= (StackTrace
*) user_data
;
256 view
= st
->widgets
.clist
;
257 selection
= gtk_tree_view_get_selection (view
);
258 if (!gtk_tree_selection_get_selected (selection
, &model
, &iter
))
261 /* get the frame info */
262 gtk_tree_model_get (model
, &iter
,
263 STACK_TRACE_URI_COLUMN
, &uri
,
264 STACK_TRACE_LINE_COLUMN
, &line
,
267 goto_location_in_editor (st
->plugin
, uri
, line
);
272 on_stack_trace_row_activated (GtkTreeView
*treeview
,
274 GtkTreeViewColumn
*arg2
,
277 on_stack_frame_set_activate (NULL
, st
);
281 on_stack_trace_button_press (GtkWidget
*widget
, GdkEventButton
*bevent
, gpointer user_data
)
283 StackTrace
*st
= (StackTrace
*) user_data
;
285 if ((bevent
->type
== GDK_BUTTON_PRESS
) && (bevent
->button
== 3))
287 /* Right mouse click */
288 g_return_val_if_fail (st
->widgets
.menu
!= NULL
, FALSE
);
289 gtk_menu_popup (GTK_MENU (st
->widgets
.menu
), NULL
, NULL
, NULL
, NULL
,
290 bevent
->button
, bevent
->time
);
292 else if ((bevent
->type
== GDK_2BUTTON_PRESS
) && (bevent
->button
== 1))
294 /* Double left mouse click */
295 on_stack_view_src_activate (NULL
, user_data
);
302 stack_trace_update (StackTrace
*st
)
304 st
->current_frame
= 0;
305 ianjuta_debugger_list_frame (
307 (IAnjutaDebuggerCallback
)on_stack_trace_updated
,
313 *---------------------------------------------------------------------------*/
315 static GtkActionEntry actions_stack_trace
[] = {
317 "ActionDmaSetCurrentFrame", /* Action name */
318 NULL
, /* Stock icon, if any */
319 N_("Set current frame"), /* Display label */
320 NULL
, /* short-cut */
322 G_CALLBACK (on_stack_frame_set_activate
) /* action callback */
325 "ActionDmaJumpToFrame",
330 G_CALLBACK (on_stack_view_src_activate
)
335 create_stack_trace_gui(StackTrace
*st
)
338 GtkTreeSelection
*selection
;
339 GtkTreeViewColumn
*column
;
340 GtkCellRenderer
*renderer
;
343 g_return_if_fail (st
->widgets
.scrolledwindow
== NULL
);
345 /* Create tree view */
346 model
= GTK_TREE_MODEL(gtk_list_store_new (STACK_TRACE_N_COLUMNS
,
355 st
->widgets
.clist
= GTK_TREE_VIEW (gtk_tree_view_new_with_model (model
));
356 g_object_unref (G_OBJECT (model
));
358 selection
= gtk_tree_view_get_selection (st
->widgets
.clist
);
359 gtk_tree_selection_set_mode (selection
, GTK_SELECTION_SINGLE
);
362 column
= gtk_tree_view_column_new ();
363 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
364 gtk_tree_view_column_set_title (column
, _("Active"));
365 renderer
= gtk_cell_renderer_pixbuf_new ();
366 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
367 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
368 STACK_TRACE_ACTIVE_COLUMN
);
369 gtk_tree_view_append_column (st
->widgets
.clist
, column
);
370 gtk_tree_view_set_expander_column (st
->widgets
.clist
,
373 column
= gtk_tree_view_column_new ();
374 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
375 gtk_tree_view_column_set_title (column
, _("Frame"));
376 renderer
= gtk_cell_renderer_text_new ();
377 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
378 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
379 STACK_TRACE_FRAME_COLUMN
);
380 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
381 gtk_tree_view_append_column (st
->widgets
.clist
, column
);
382 gtk_tree_view_set_expander_column (st
->widgets
.clist
,
385 column
= gtk_tree_view_column_new ();
386 renderer
= gtk_cell_renderer_text_new ();
387 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
388 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
389 STACK_TRACE_FILE_COLUMN
);
390 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
391 gtk_tree_view_column_set_title (column
, _("File"));
392 gtk_tree_view_append_column (st
->widgets
.clist
, column
);
394 column
= gtk_tree_view_column_new ();
395 renderer
= gtk_cell_renderer_text_new ();
396 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
397 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
398 STACK_TRACE_LINE_COLUMN
);
399 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
400 gtk_tree_view_column_set_title (column
, _("Line"));
401 gtk_tree_view_append_column (st
->widgets
.clist
, column
);
403 column
= gtk_tree_view_column_new ();
404 renderer
= gtk_cell_renderer_text_new ();
405 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
406 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
407 STACK_TRACE_FUNC_COLUMN
);
408 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
409 gtk_tree_view_column_set_title (column
, _("Function"));
410 gtk_tree_view_append_column (st
->widgets
.clist
, column
);
412 column
= gtk_tree_view_column_new ();
413 renderer
= gtk_cell_renderer_text_new ();
414 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
415 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
416 STACK_TRACE_ADDR_COLUMN
);
417 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
418 gtk_tree_view_column_set_title (column
, _("Address"));
419 gtk_tree_view_append_column (st
->widgets
.clist
, column
);
421 column
= gtk_tree_view_column_new ();
422 renderer
= gtk_cell_renderer_text_new ();
423 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
424 gtk_tree_view_column_add_attribute (column
, renderer
, "text",
425 STACK_TRACE_ARGS_COLUMN
);
426 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
427 gtk_tree_view_column_set_title (column
, _("Arguments"));
428 gtk_tree_view_append_column (st
->widgets
.clist
, column
);
430 /* Create popup menu */
431 ui
= anjuta_shell_get_ui (st
->plugin
->shell
, NULL
);
432 st
->widgets
.menu
= GTK_MENU (gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui
), "/PopupStack"));
435 g_signal_connect (st
->widgets
.clist
, "button-press-event", G_CALLBACK (on_stack_trace_button_press
), st
);
436 g_signal_connect (st
->widgets
.clist
, "row-activated", G_CALLBACK (on_stack_trace_row_activated
), st
);
438 /* Add stack window */
439 st
->widgets
.scrolledwindow
= gtk_scrolled_window_new (NULL
, NULL
);
440 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (st
->widgets
.scrolledwindow
),
441 GTK_POLICY_AUTOMATIC
,
442 GTK_POLICY_AUTOMATIC
);
443 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (st
->widgets
.scrolledwindow
),
445 gtk_container_add (GTK_CONTAINER (st
->widgets
.scrolledwindow
),
446 GTK_WIDGET (st
->widgets
.clist
));
447 gtk_widget_show_all (st
->widgets
.scrolledwindow
);
449 anjuta_shell_add_widget (st
->plugin
->shell
,
450 st
->widgets
.scrolledwindow
,
451 "AnjutaDebuggerStack", _("Stack"),
452 "gdb-stack-icon", ANJUTA_SHELL_PLACEMENT_BOTTOM
,
458 destroy_stack_trace_gui (StackTrace
*st
)
460 if (st
->widgets
.scrolledwindow
!= NULL
)
462 gtk_widget_destroy (st
->widgets
.scrolledwindow
);
463 st
->widgets
.scrolledwindow
= NULL
;
468 on_program_stopped (StackTrace
*st
)
470 stack_trace_update (st
);
474 on_debugger_started (StackTrace
*st
)
476 create_stack_trace_gui (st
);
480 on_debugger_stopped (StackTrace
*st
)
482 stack_trace_clear (st
);
483 destroy_stack_trace_gui (st
);
487 *---------------------------------------------------------------------------*/
489 /* Constructor & Destructor
490 *---------------------------------------------------------------------------*/
493 stack_trace_new (IAnjutaDebugger
*debugger
, AnjutaPlugin
*plugin
)
498 st
= g_new0 (StackTrace
, 1);
499 if (st
== NULL
) return NULL
;
502 st
->debugger
= debugger
;
503 if (debugger
!= NULL
) g_object_ref (debugger
);
505 /* Register actions */
506 ui
= anjuta_shell_get_ui (st
->plugin
->shell
, NULL
);
508 anjuta_ui_add_action_group_entries (ui
, "ActionGroupStack",
509 _("Stack frame operations"),
511 G_N_ELEMENTS (actions_stack_trace
),
512 GETTEXT_PACKAGE
, TRUE
, st
);
514 g_signal_connect_swapped (st
->debugger
, "debugger-started", G_CALLBACK (on_debugger_started
), st
);
515 g_signal_connect_swapped (st
->debugger
, "debugger-stopped", G_CALLBACK (on_debugger_stopped
), st
);
516 g_signal_connect_swapped (st
->debugger
, "program-stopped", G_CALLBACK (on_program_stopped
), st
);
517 g_signal_connect_swapped (st
->debugger
, "frame-changed", G_CALLBACK (on_stack_trace_frame_changed
), st
);
523 stack_trace_free (StackTrace
* st
)
527 g_return_if_fail (st
!= NULL
);
529 /* Disconnect from debugger */
530 if (st
->debugger
!= NULL
)
532 g_signal_handlers_disconnect_by_func (st
->debugger
, G_CALLBACK (on_debugger_started
), st
);
533 g_signal_handlers_disconnect_by_func (st
->debugger
, G_CALLBACK (on_debugger_stopped
), st
);
534 g_signal_handlers_disconnect_by_func (st
->debugger
, G_CALLBACK (on_program_stopped
), st
);
535 g_signal_handlers_disconnect_by_func (st
->debugger
, G_CALLBACK (on_stack_trace_frame_changed
), st
);
536 g_object_unref (st
->debugger
);
539 /* Remove menu actions */
540 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN (st
->plugin
)->shell
, NULL
);
541 anjuta_ui_remove_action_group (ui
, st
->action_group
);
544 destroy_stack_trace_gui (st
);