1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 * watch.c Copyright (C) 2000 Kh. Naba Kumar Singh
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 59 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "debug_tree.h"
26 #include "utilities.h"
29 #include <libanjuta/anjuta-debug.h>
30 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
31 #include <libanjuta/interfaces/ianjuta-editor.h>
32 #include <libanjuta/interfaces/ianjuta-document-manager.h>
35 *---------------------------------------------------------------------------*/
41 GtkWidget
*scrolledwindow
;
42 DebugTree
*debug_tree
;
43 DmaDebuggerQueue
*debugger
;
46 GtkActionGroup
*action_group
;
47 GtkActionGroup
*toggle_group
;
57 typedef struct _InspectDialog InspectDialog
;
59 /* Widget and signal name found in glade file
60 *---------------------------------------------------------------------------*/
62 #define ADD_WATCH_DIALOG "add_watch_dialog"
63 #define CHANGE_WATCH_DIALOG "change_watch_dialog"
64 #define INSPECT_EVALUATE_DIALOG "watch_dialog"
65 #define NAME_ENTRY "name_entry"
66 #define VALUE_ENTRY "value_entry"
67 #define VALUE_TREE "value_treeview"
68 #define AUTO_UPDATE_CHECK "auto_update_check"
71 *---------------------------------------------------------------------------*/
75 on_entry_updated (const gchar
*value
, gpointer user_data
, GError
*err
)
77 GtkWidget
*entry
= GTK_WIDGET (user_data
);
79 gtk_entry_set_text (GTK_ENTRY (entry
), value
);
80 gtk_widget_unref (entry
);
85 debug_tree_inspect_evaluate_dialog (ExprWatch
* ew
, const gchar
* expression
)
90 // const gchar *value;
92 IAnjutaDebuggerVariableObject var
= {NULL
, NULL
, NULL
, NULL
, FALSE
, FALSE
, FALSE
, -1};
94 gxml
= glade_xml_new (GLADE_FILE
, INSPECT_EVALUATE_DIALOG
, NULL
);
95 dlg
.dialog
= glade_xml_get_widget (gxml
, INSPECT_EVALUATE_DIALOG
);
96 gtk_window_set_transient_for (GTK_WINDOW (dlg
.dialog
),
98 dlg
.treeview
= glade_xml_get_widget (gxml
, VALUE_TREE
);
99 g_object_unref (gxml
);
101 /* Create debug tree */
102 dlg
.tree
= debug_tree_new_with_view (ANJUTA_PLUGIN (ew
->plugin
), GTK_TREE_VIEW (dlg
.treeview
));
104 debug_tree_connect (dlg
.tree
, ew
->debugger
);
105 if (expression
!= NULL
)
107 var
.expression
= (gchar
*)expression
;
108 debug_tree_add_watch (dlg
.tree
, &var
, FALSE
);
112 debug_tree_add_dummy (dlg
.tree
, NULL
);
117 reply
= gtk_dialog_run (GTK_DIALOG (dlg
.dialog
));
120 case GTK_RESPONSE_OK
:
121 /* Add in watch window */
122 new_expr
= debug_tree_get_first (dlg
.tree
);
124 if (new_expr
!= NULL
)
126 var
.expression
= new_expr
;
127 debug_tree_add_watch (ew
->debug_tree
, &var
, FALSE
);
136 debug_tree_free (dlg
.tree
);
137 gtk_widget_destroy (dlg
.dialog
);
141 debug_tree_add_watch_dialog (ExprWatch
*ew
, const gchar
* expression
)
145 GtkWidget
*name_entry
;
146 GtkWidget
*auto_update_check
;
148 IAnjutaDebuggerVariableObject var
= {NULL
, NULL
, NULL
, NULL
, FALSE
, FALSE
, FALSE
, -1};
150 gxml
= glade_xml_new (GLADE_FILE
, ADD_WATCH_DIALOG
, NULL
);
151 dialog
= glade_xml_get_widget (gxml
, ADD_WATCH_DIALOG
);
152 gtk_window_set_transient_for (GTK_WINDOW (dialog
),
154 auto_update_check
= glade_xml_get_widget (gxml
, AUTO_UPDATE_CHECK
);
155 name_entry
= glade_xml_get_widget (gxml
, NAME_ENTRY
);
156 g_object_unref (gxml
);
158 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (auto_update_check
), TRUE
);
159 gtk_entry_set_text (GTK_ENTRY (name_entry
), expression
== NULL
? "" : expression
);
161 reply
= gtk_dialog_run (GTK_DIALOG (dialog
));
162 if (reply
== GTK_RESPONSE_OK
)
164 var
.expression
= (gchar
*)gtk_entry_get_text (GTK_ENTRY (name_entry
));
165 debug_tree_add_watch (ew
->debug_tree
, &var
,
166 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (auto_update_check
)));
168 gtk_widget_destroy (dialog
);
172 debug_tree_change_watch_dialog (ExprWatch
*ew
, GtkTreeIter
* iter
)
177 GtkWidget
*name_entry
;
178 GtkWidget
*value_entry
;
180 TrimmableItem
*item
= NULL
;
181 GtkTreeModel
* model
= NULL
;
183 model
= gtk_tree_view_get_model(d_tree
->view
);
184 gtk_tree_model_get (model
, iter
, ITEM_COLUMN
, &item
, -1);
186 gxml
= glade_xml_new (GLADE_FILE
, CHANGE_WATCH_DIALOG
, NULL
);
187 dialog
= glade_xml_get_widget (gxml
, CHANGE_WATCH_DIALOG
);
188 gtk_window_set_transient_for (GTK_WINDOW (dialog
),
190 name_entry
= glade_xml_get_widget (gxml
, NAME_ENTRY
);
191 value_entry
= glade_xml_get_widget (gxml
, VALUE_ENTRY
);
192 g_object_unref (gxml
);
194 gtk_widget_grab_focus (value_entry
);
195 gtk_entry_set_text (GTK_ENTRY (name_entry
), &item
->name
[1]);
196 gtk_entry_set_text (GTK_ENTRY (value_entry
), item
->value
);
198 reply
= gtk_dialog_run (GTK_DIALOG (dialog
));
199 if (reply
== GTK_RESPONSE_APPLY
)
201 debug_tree_evaluate (d_tree
, iter
, gtk_entry_get_text (GTK_ENTRY (value_entry
)));
203 gtk_widget_destroy (dialog
);
208 on_program_stopped (ExprWatch
*ew
)
210 debug_tree_update_all (ew
->debug_tree
);
214 on_program_exited (ExprWatch
*ew
)
216 debug_tree_disconnect (ew
->debug_tree
);
218 /* Disconnect to other debugger signal */
219 g_signal_handlers_disconnect_by_func (ew
->plugin
, G_CALLBACK (on_program_exited
), ew
);
220 g_signal_handlers_disconnect_by_func (ew
->plugin
, G_CALLBACK (on_program_stopped
), ew
);
224 on_program_started (ExprWatch
*ew
)
226 if (!dma_debugger_queue_is_supported (ew
->debugger
, HAS_VARIABLE
)) return;
228 debug_tree_connect (ew
->debug_tree
, ew
->debugger
);
230 /* Connect to other debugger signal */
231 g_signal_connect_swapped (ew
->plugin
, "program-exited", G_CALLBACK (on_program_exited
), ew
);
232 g_signal_connect_swapped (ew
->plugin
, "program-stopped", G_CALLBACK (on_program_stopped
), ew
);
236 *---------------------------------------------------------------------------*/
239 on_debug_tree_inspect (GtkAction
*action
, gpointer user_data
)
241 ExprWatch
* ew
= (ExprWatch
*)user_data
;
242 IAnjutaEditor
*te
= NULL
;
243 gchar
*expression
= NULL
;
245 /* Get current editor and line */
246 te
= dma_get_current_editor (ANJUTA_PLUGIN (ew
->plugin
));
247 if (te
== NULL
) return;
249 expression
= ianjuta_editor_selection_get (IANJUTA_EDITOR_SELECTION (te
), NULL
);
250 if (expression
== NULL
)
252 expression
= ianjuta_editor_get_current_word (IANJUTA_EDITOR (te
), NULL
);
255 debug_tree_inspect_evaluate_dialog (ew
, expression
);
260 on_debug_tree_add_watch (GtkAction
*action
, gpointer user_data
)
262 ExprWatch
* ew
= (ExprWatch
*)user_data
;
264 debug_tree_add_watch_dialog (ew
, NULL
);
268 on_debug_tree_remove_watch (GtkAction
*action
, gpointer user_data
)
270 ExprWatch
* ew
= (ExprWatch
*)user_data
;
273 if (debug_tree_get_current (ew
->debug_tree
, &iter
))
275 debug_tree_remove (ew
->debug_tree
, &iter
);
280 on_debug_tree_update_watch (GtkAction
*action
, gpointer user_data
)
282 ExprWatch
* ew
= (ExprWatch
*)user_data
;
285 if (debug_tree_get_current (ew
->debug_tree
, &iter
))
287 debug_tree_update (ew
->debug_tree
, &iter
, TRUE
);
292 on_debug_tree_auto_update_watch (GtkAction
*action
, gpointer user_data
)
294 ExprWatch
* ew
= (ExprWatch
*)user_data
;
297 if (debug_tree_get_current (ew
->debug_tree
, &iter
))
301 state
= gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action
));
302 debug_tree_set_auto_update (ew
->debug_tree
, &iter
, state
);
307 on_debug_tree_edit_watch (GtkAction
*action
, gpointer user_data
)
309 ExprWatch
* ew
= (ExprWatch
*)user_data
;
312 if (debug_tree_get_current (ew
->debug_tree
, &iter
))
314 debug_tree_change_watch_dialog (ew
, &iter
);
319 on_debug_tree_update_all_watch (GtkAction
*action
, gpointer user_data
)
321 ExprWatch
* ew
= (ExprWatch
*)user_data
;
323 debug_tree_update_all (ew
->debug_tree
);
327 on_debug_tree_remove_all_watch (GtkAction
*action
, gpointer user_data
)
329 ExprWatch
* ew
= (ExprWatch
*)user_data
;
331 debug_tree_remove_all (ew
->debug_tree
);
335 on_debug_tree_button_press (GtkWidget
*widget
, GdkEventButton
*bevent
, gpointer user_data
)
337 ExprWatch
* ew
= (ExprWatch
*)user_data
;
339 if (bevent
->button
== 3)
344 GtkWidget
*middle_click_menu
;
346 ui
= anjuta_shell_get_ui (ew
->plugin
->shell
, NULL
);
347 action
= anjuta_ui_get_action (ui
, "ActionGroupWatchToggle", "ActionDmaAutoUpdateWatch");
348 if (debug_tree_get_current (ew
->debug_tree
, &iter
))
350 gtk_action_set_sensitive (GTK_ACTION (action
), TRUE
);
351 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action
), debug_tree_get_auto_update (ew
->debug_tree
, &iter
));
355 gtk_action_set_sensitive (GTK_ACTION (action
), FALSE
);
358 action
= anjuta_ui_get_action (ui
, "ActionGroupWatch", "ActionDmaEditWatch");
359 gtk_action_set_sensitive (GTK_ACTION (action
), FALSE
); // FIXME: Not implemented
361 middle_click_menu
= gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui
), "/PopupWatch");
362 g_return_val_if_fail (middle_click_menu
!= NULL
, FALSE
);
363 gtk_menu_popup (GTK_MENU (middle_click_menu
), NULL
, NULL
, NULL
, NULL
,
364 bevent
->button
, bevent
->time
);
371 *---------------------------------------------------------------------------*/
373 static GtkActionEntry actions_watch
[] = {
375 "ActionDmaInspect", /* Action name */
376 GTK_STOCK_DIALOG_INFO
, /* Stock icon, if any */
377 N_("Ins_pect/Evaluate..."), /* Display label */
378 NULL
, /* short-cut */
379 N_("Inspect or evaluate an expression or variable"), /* Tooltip */
380 G_CALLBACK (on_debug_tree_inspect
) /* action callback */
388 G_CALLBACK (on_debug_tree_add_watch
)
391 "ActionDmaRemoveWatch",
396 G_CALLBACK (on_debug_tree_remove_watch
)
399 "ActionDmaUpdateWatch",
404 G_CALLBACK (on_debug_tree_update_watch
)
407 "ActionDmaEditWatch",
412 G_CALLBACK (on_debug_tree_edit_watch
)
415 "ActionDmaUpdateAllWatch",
420 G_CALLBACK (on_debug_tree_update_all_watch
)
423 "ActionDmaRemoveAllWatch",
428 G_CALLBACK (on_debug_tree_remove_all_watch
)
432 static GtkToggleActionEntry toggle_watch
[] = {
434 "ActionDmaAutoUpdateWatch", /* Action name */
435 NULL
, /* Stock icon, if any */
436 N_("Automatic update"), /* Display label */
437 NULL
, /* short-cut */
439 G_CALLBACK (on_debug_tree_auto_update_watch
), /* action callback */
440 FALSE
/* Initial state */
445 create_expr_watch_gui (ExprWatch
* ew
)
449 ew
->debug_tree
= debug_tree_new (ew
->plugin
);
450 ew
->scrolledwindow
= gtk_scrolled_window_new (NULL
, NULL
);
451 gtk_widget_show (ew
->scrolledwindow
);
452 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ew
->scrolledwindow
),
453 GTK_POLICY_AUTOMATIC
,
454 GTK_POLICY_AUTOMATIC
);
455 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (ew
->scrolledwindow
),
457 gtk_container_add (GTK_CONTAINER (ew
->scrolledwindow
), debug_tree_get_tree_widget (ew
->debug_tree
));
459 ui
= anjuta_shell_get_ui (ew
->plugin
->shell
, NULL
);
461 anjuta_ui_add_action_group_entries (ui
, "ActionGroupWatch",
462 _("Watch operations"),
464 G_N_ELEMENTS (actions_watch
),
465 GETTEXT_PACKAGE
, TRUE
, ew
);
467 anjuta_ui_add_toggle_action_group_entries (ui
, "ActionGroupWatchToggle",
468 _("Watch operations"),
470 G_N_ELEMENTS (toggle_watch
),
471 GETTEXT_PACKAGE
, TRUE
, ew
);
472 g_signal_connect (debug_tree_get_tree_widget (ew
->debug_tree
), "button-press-event", G_CALLBACK (on_debug_tree_button_press
), ew
);
474 gtk_widget_show_all (ew
->scrolledwindow
);
478 *---------------------------------------------------------------------------*/
481 expr_watch_find_variable_value (ExprWatch
*ew
, const gchar
*name
)
483 return debug_tree_find_variable_value (ew
->debug_tree
, name
);
486 /* Callback for saving session
487 *---------------------------------------------------------------------------*/
490 on_session_save (AnjutaShell
*shell
, AnjutaSessionPhase phase
, AnjutaSession
*session
, ExprWatch
*ew
)
494 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
497 list
= debug_tree_get_full_watch_list (ew
->debug_tree
);
499 anjuta_session_set_string_list (session
, "Debugger", "Watch", list
);
500 g_list_foreach (list
, (GFunc
)g_free
, NULL
);
505 on_session_load (AnjutaShell
*shell
, AnjutaSessionPhase phase
, AnjutaSession
*session
, ExprWatch
*ew
)
509 if (phase
!= ANJUTA_SESSION_PHASE_NORMAL
)
512 /* debug_tree_remove_all (ew->debug_tree); */
513 list
= anjuta_session_get_string_list (session
, "Debugger", "Watch");
515 debug_tree_add_full_watch_list (ew
->debug_tree
, list
);
518 /* Constructor & Destructor
519 *---------------------------------------------------------------------------*/
522 expr_watch_new (AnjutaPlugin
*plugin
)
526 ew
= g_new0 (ExprWatch
, 1);
528 create_expr_watch_gui (ew
);
529 ew
->debugger
= dma_debug_manager_get_queue (ANJUTA_PLUGIN_DEBUG_MANAGER (plugin
));
531 /* Connect to Load and Save event */
532 g_signal_connect (ew
->plugin
->shell
, "save-session",
533 G_CALLBACK (on_session_save
), ew
);
534 g_signal_connect (ew
->plugin
->shell
, "load-session",
535 G_CALLBACK (on_session_load
), ew
);
537 /* Add watch window */
538 anjuta_shell_add_widget (ew
->plugin
->shell
,
540 "AnjutaDebuggerWatch", _("Watches"),
541 "gdb-watch-icon", ANJUTA_SHELL_PLACEMENT_BOTTOM
,
544 /* Connect to debugger */
545 g_signal_connect_swapped (ew
->plugin
, "program-started", G_CALLBACK (on_program_started
), ew
);
551 expr_watch_destroy (ExprWatch
* ew
)
555 g_return_if_fail (ew
!= NULL
);
557 /* Disconnect from Load and Save event */
558 g_signal_handlers_disconnect_matched (ew
->plugin
->shell
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, ew
);
559 g_signal_handlers_disconnect_matched (ew
->plugin
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, ew
);
561 ui
= anjuta_shell_get_ui (ew
->plugin
->shell
, NULL
);
562 anjuta_ui_remove_action_group (ui
, ew
->action_group
);
563 anjuta_ui_remove_action_group (ui
, ew
->toggle_group
);
565 debug_tree_free (ew
->debug_tree
);
566 gtk_widget_destroy (ew
->scrolledwindow
);