Updated Spanish translation
[anjuta.git] / plugins / debug-manager / watch.c
blobb58a6dbf9607c226421802347b524c40a04f32c6
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * watch.c Copyright (C) 2000 Kh. Naba Kumar Singh
4 *
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)
8 * any later version.
9 *
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
13 * more details.
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
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
23 #include "watch.h"
25 #include "debug_tree.h"
26 #include "utilities.h"
28 #include <glib/gi18n.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>
34 /* Type
35 *---------------------------------------------------------------------------*/
37 struct _ExprWatch
39 AnjutaPlugin *plugin;
41 GtkWidget *scrolledwindow;
42 DebugTree *debug_tree;
43 DmaDebuggerQueue *debugger;
45 /* Menu action */
46 GtkActionGroup *action_group;
47 GtkActionGroup *toggle_group;
50 struct _InspectDialog
52 DebugTree *tree;
53 GtkWidget *treeview;
54 GtkWidget *dialog;
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 VALUE_TREE "watch_value_treeview"
66 #define NAME_ENTRY "add_watch_name_entry"
67 #define VALUE_ENTRY "value_entry"
68 #define AUTO_UPDATE_CHECK "auto_update_check"
71 enum targets {
72 TARGET_STRING,
73 TARGET_URL
76 static const GtkTargetEntry drag_targets[] = {
77 {"application-x/anjuta", GTK_TARGET_SAME_APP, TARGET_STRING},
78 { "STRING", GTK_TARGET_SAME_APP, TARGET_STRING },
79 { "text/plain", GTK_TARGET_SAME_APP, TARGET_STRING },
80 { "text/uri-list", GTK_TARGET_SAME_APP, TARGET_URL }
83 /* Private functions
84 *---------------------------------------------------------------------------*/
86 static void
87 debug_tree_inspect_evaluate_dialog (ExprWatch * ew, const gchar* expression)
89 GtkBuilder *bxml;
90 gint reply;
91 gchar *new_expr;
92 InspectDialog dlg;
93 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
95 bxml = anjuta_util_builder_new (GLADE_FILE, NULL);
96 if (!bxml) return;
97 anjuta_util_builder_get_objects (bxml,
98 INSPECT_EVALUATE_DIALOG, &dlg.dialog,
99 VALUE_TREE, &dlg.treeview,
100 NULL);
101 g_object_unref (bxml);
102 gtk_window_set_transient_for (GTK_WINDOW (dlg.dialog), NULL);
104 /* Create debug tree */
105 dlg.tree = debug_tree_new_with_view (ANJUTA_PLUGIN (ew->plugin), GTK_TREE_VIEW (dlg.treeview));
106 if (ew->debugger)
107 debug_tree_connect (dlg.tree, ew->debugger);
108 if (expression != NULL)
110 var.expression = (gchar *)expression;
111 debug_tree_add_watch (dlg.tree, &var, FALSE);
113 else
115 debug_tree_add_dummy (dlg.tree, NULL);
118 for(;;)
120 reply = gtk_dialog_run (GTK_DIALOG (dlg.dialog));
121 switch (reply)
123 case GTK_RESPONSE_OK:
124 /* Add in watch window */
125 new_expr = debug_tree_get_first (dlg.tree);
127 if ((new_expr != NULL) && (strlen(new_expr) != 0))
129 var.expression = new_expr;
130 debug_tree_add_watch (ew->debug_tree, &var, FALSE);
131 g_free (new_expr);
133 break;
134 default:
135 break;
137 break;
139 debug_tree_free (dlg.tree);
140 gtk_widget_destroy (dlg.dialog);
143 static void
144 debug_tree_add_watch_dialog (ExprWatch *ew, const gchar* expression)
146 GtkBuilder *bxml;
147 GtkWidget *dialog;
148 GtkWidget *name_entry;
149 GtkWidget *auto_update_check;
150 gint reply;
151 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
154 bxml = anjuta_util_builder_new (GLADE_FILE, NULL);
155 if (!bxml) return;
156 anjuta_util_builder_get_objects (bxml,
157 ADD_WATCH_DIALOG, &dialog,
158 AUTO_UPDATE_CHECK, &auto_update_check,
159 NAME_ENTRY, &name_entry,
160 NULL);
161 g_object_unref (bxml);
163 gtk_window_set_transient_for (GTK_WINDOW (dialog),
164 NULL);
166 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (auto_update_check), TRUE);
167 gtk_entry_set_text (GTK_ENTRY (name_entry), expression == NULL ? "" : expression);
169 reply = gtk_dialog_run (GTK_DIALOG (dialog));
170 if (reply == GTK_RESPONSE_OK)
172 var.expression = (gchar *)gtk_entry_get_text (GTK_ENTRY (name_entry));
173 debug_tree_add_watch (ew->debug_tree, &var,
174 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (auto_update_check)));
176 gtk_widget_destroy (dialog);
179 static void
180 debug_tree_change_watch_dialog (ExprWatch *ew, GtkTreeIter* iter)
182 #if 0
183 GladeXML *gxml;
184 GtkWidget *dialog;
185 GtkWidget *name_entry;
186 GtkWidget *value_entry;
187 gint reply;
188 TrimmableItem *item = NULL;
189 GtkTreeModel* model = NULL;
191 model = gtk_tree_view_get_model(d_tree->view);
192 gtk_tree_model_get (model, iter, ITEM_COLUMN, &item, -1);
194 gxml = glade_xml_new (GLADE_FILE, CHANGE_WATCH_DIALOG, NULL);
195 dialog = glade_xml_get_widget (gxml, CHANGE_WATCH_DIALOG);
196 gtk_window_set_transient_for (GTK_WINDOW (dialog),
197 NULL);
198 name_entry = glade_xml_get_widget (gxml, NAME_ENTRY);
199 value_entry = glade_xml_get_widget (gxml, VALUE_ENTRY);
200 g_object_unref (gxml);
202 gtk_widget_grab_focus (value_entry);
203 gtk_entry_set_text (GTK_ENTRY (name_entry), &item->name[1]);
204 gtk_entry_set_text (GTK_ENTRY (value_entry), item->value);
206 reply = gtk_dialog_run (GTK_DIALOG (dialog));
207 if (reply == GTK_RESPONSE_APPLY)
209 debug_tree_evaluate (d_tree, iter, gtk_entry_get_text (GTK_ENTRY (value_entry)));
211 gtk_widget_destroy (dialog);
212 #endif
215 static void
216 on_program_exited (ExprWatch *ew)
218 debug_tree_disconnect (ew->debug_tree);
220 /* Disconnect to other debugger signal */
221 g_signal_handlers_disconnect_by_func (ew->plugin, G_CALLBACK (on_program_exited), ew);
224 static void
225 on_program_started (ExprWatch *ew)
227 if (!dma_debugger_queue_is_supported (ew->debugger, HAS_VARIABLE)) return;
229 debug_tree_connect (ew->debug_tree, ew->debugger);
231 /* Connect to other debugger signal */
232 g_signal_connect_swapped (ew->plugin, "program-exited", G_CALLBACK (on_program_exited), ew);
235 /* Menu call backs
236 *---------------------------------------------------------------------------*/
238 static void
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);
254 if (g_regex_match_simple("^\\s*$", expression,G_REGEX_MULTILINE | G_REGEX_DOLLAR_ENDONLY, G_REGEX_MATCH_ANCHORED))
256 expression = NULL;
259 debug_tree_inspect_evaluate_dialog (ew, expression);
260 g_free (expression);
263 static void
264 on_debug_tree_add_watch (GtkAction *action, gpointer user_data)
266 ExprWatch * ew = (ExprWatch *)user_data;
268 debug_tree_add_watch_dialog (ew, NULL);
271 static void
272 on_debug_tree_remove_watch (GtkAction *action, gpointer user_data)
274 ExprWatch * ew = (ExprWatch *)user_data;
275 GtkTreeIter iter;
277 if (debug_tree_get_current (ew->debug_tree, &iter))
279 debug_tree_remove (ew->debug_tree, &iter);
283 static void
284 on_debug_tree_update_watch (GtkAction *action, gpointer user_data)
286 ExprWatch * ew = (ExprWatch *)user_data;
287 GtkTreeIter iter;
289 if (debug_tree_get_current (ew->debug_tree, &iter))
291 debug_tree_update (ew->debug_tree, &iter, TRUE);
295 static void
296 on_debug_tree_auto_update_watch (GtkAction *action, gpointer user_data)
298 ExprWatch * ew = (ExprWatch *)user_data;
299 GtkTreeIter iter;
301 if (debug_tree_get_current (ew->debug_tree, &iter))
303 gboolean state;
305 state = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
306 debug_tree_set_auto_update (ew->debug_tree, &iter, state);
310 static void
311 on_debug_tree_edit_watch (GtkAction *action, gpointer user_data)
313 ExprWatch * ew = (ExprWatch *)user_data;
314 GtkTreeIter iter;
316 if (debug_tree_get_current (ew->debug_tree, &iter))
318 debug_tree_change_watch_dialog (ew, &iter);
322 static void
323 on_debug_tree_update_all_watch (GtkAction *action, gpointer user_data)
325 ExprWatch * ew = (ExprWatch *)user_data;
327 debug_tree_update_tree (ew->debug_tree);
330 static void
331 on_debug_tree_remove_all_watch (GtkAction *action, gpointer user_data)
333 ExprWatch * ew = (ExprWatch *)user_data;
335 debug_tree_remove_all (ew->debug_tree);
338 static gboolean
339 on_debug_tree_button_press (GtkWidget *widget, GdkEventButton *bevent, gpointer user_data)
341 ExprWatch * ew = (ExprWatch *)user_data;
343 if (bevent->button == 3)
345 GtkAction *action;
346 AnjutaUI *ui;
347 GtkTreeIter iter;
348 GtkWidget *middle_click_menu;
350 ui = anjuta_shell_get_ui (ew->plugin->shell, NULL);
351 action = anjuta_ui_get_action (ui, "ActionGroupWatchToggle", "ActionDmaAutoUpdateWatch");
352 if (debug_tree_get_current (ew->debug_tree, &iter))
354 gtk_action_set_sensitive (GTK_ACTION (action), TRUE);
355 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), debug_tree_get_auto_update (ew->debug_tree, &iter));
357 else
359 gtk_action_set_sensitive (GTK_ACTION (action), FALSE);
362 action = anjuta_ui_get_action (ui, "ActionGroupWatch", "ActionDmaEditWatch");
363 gtk_action_set_sensitive (GTK_ACTION (action), FALSE); // FIXME: Not implemented
365 middle_click_menu = gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui), "/PopupWatch");
366 g_return_val_if_fail (middle_click_menu != NULL, FALSE);
367 gtk_menu_popup (GTK_MENU (middle_click_menu), NULL, NULL, NULL, NULL,
368 bevent->button, bevent->time);
371 return FALSE;
374 static void
375 on_debug_tree_drag_data_received (GtkWidget *widget,
376 GdkDragContext *context,
377 gint x,
378 gint y,
379 GtkSelectionData *selection_data,
380 guint info,
381 guint timestamp,
382 gpointer user_data)
384 const gchar* signal_data = (gchar*) gtk_selection_data_get_data (selection_data);
385 IAnjutaDebuggerVariableObject var = {NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, -1};
387 if (signal_data != NULL)
389 var.expression = (gchar *)signal_data;
390 debug_tree_add_watch (((ExprWatch *)user_data)->debug_tree, &var, FALSE);
393 gtk_drag_finish (context, FALSE, FALSE, timestamp);
395 return;
399 /* Actions table
400 *---------------------------------------------------------------------------*/
402 static GtkActionEntry actions_watch[] = {
404 "ActionDmaInspect", /* Action name */
405 GTK_STOCK_DIALOG_INFO, /* Stock icon, if any */
406 N_("Ins_pect/Evaluate…"), /* Display label */
407 NULL, /* short-cut */
408 N_("Inspect or evaluate an expression or variable"), /* Tooltip */
409 G_CALLBACK (on_debug_tree_inspect) /* action callback */
412 "ActionDmaAddWatch",
413 NULL,
414 N_("Add Watch…"),
415 NULL,
416 NULL,
417 G_CALLBACK (on_debug_tree_add_watch)
420 "ActionDmaRemoveWatch",
421 NULL,
422 N_("Remove Watch"),
423 NULL,
424 NULL,
425 G_CALLBACK (on_debug_tree_remove_watch)
428 "ActionDmaUpdateWatch",
429 NULL,
430 N_("Update Watch"),
431 NULL,
432 NULL,
433 G_CALLBACK (on_debug_tree_update_watch)
436 "ActionDmaEditWatch",
437 NULL,
438 N_("Change Value"),
439 NULL,
440 NULL,
441 G_CALLBACK (on_debug_tree_edit_watch)
444 "ActionDmaUpdateAllWatch",
445 NULL,
446 N_("Update all"),
447 NULL,
448 NULL,
449 G_CALLBACK (on_debug_tree_update_all_watch)
452 "ActionDmaRemoveAllWatch",
453 NULL,
454 N_("Remove all"),
455 NULL,
456 NULL,
457 G_CALLBACK (on_debug_tree_remove_all_watch)
461 static GtkToggleActionEntry toggle_watch[] = {
463 "ActionDmaAutoUpdateWatch", /* Action name */
464 NULL, /* Stock icon, if any */
465 N_("Automatic update"), /* Display label */
466 NULL, /* short-cut */
467 NULL, /* Tooltip */
468 G_CALLBACK (on_debug_tree_auto_update_watch), /* action callback */
469 FALSE /* Initial state */
473 static void
474 create_expr_watch_gui (ExprWatch * ew)
476 AnjutaUI *ui;
478 ew->debug_tree = debug_tree_new (ew->plugin);
479 ew->scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
480 gtk_widget_show (ew->scrolledwindow);
481 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (ew->scrolledwindow),
482 GTK_POLICY_AUTOMATIC,
483 GTK_POLICY_AUTOMATIC);
484 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (ew->scrolledwindow),
485 GTK_SHADOW_IN);
486 gtk_container_add (GTK_CONTAINER (ew->scrolledwindow), debug_tree_get_tree_widget (ew->debug_tree));
488 ui = anjuta_shell_get_ui (ew->plugin->shell, NULL);
489 ew->action_group =
490 anjuta_ui_add_action_group_entries (ui, "ActionGroupWatch",
491 _("Watch operations"),
492 actions_watch,
493 G_N_ELEMENTS (actions_watch),
494 GETTEXT_PACKAGE, TRUE, ew);
495 ew->toggle_group =
496 anjuta_ui_add_toggle_action_group_entries (ui, "ActionGroupWatchToggle",
497 _("Watch operations"),
498 toggle_watch,
499 G_N_ELEMENTS (toggle_watch),
500 GETTEXT_PACKAGE, TRUE, ew);
501 g_signal_connect (debug_tree_get_tree_widget (ew->debug_tree), "button-press-event", G_CALLBACK (on_debug_tree_button_press), ew);
503 gtk_drag_dest_set(debug_tree_get_tree_widget (ew->debug_tree), GTK_DEST_DEFAULT_ALL, drag_targets, sizeof (drag_targets) / sizeof (drag_targets[0]), GDK_ACTION_COPY|GDK_ACTION_MOVE|GDK_ACTION_LINK);
504 g_signal_connect (debug_tree_get_tree_widget (ew->debug_tree), "drag_data_received", G_CALLBACK (on_debug_tree_drag_data_received), ew);
506 gtk_widget_show_all (ew->scrolledwindow);
509 /* Public function
510 *---------------------------------------------------------------------------*/
512 gchar*
513 expr_watch_find_variable_value (ExprWatch *ew, const gchar *name)
515 return debug_tree_find_variable_value (ew->debug_tree, name);
518 /* Callback for saving session
519 *---------------------------------------------------------------------------*/
521 static void
522 on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, ExprWatch *ew)
524 GList *list;
526 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
527 return;
529 list = debug_tree_get_full_watch_list (ew->debug_tree);
530 if (list != NULL)
531 anjuta_session_set_string_list (session, "Debugger", "Watch", list);
532 g_list_foreach (list, (GFunc)g_free, NULL);
533 g_list_free (list);
536 static void
537 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, ExprWatch *ew)
539 GList *list;
541 if (phase != ANJUTA_SESSION_PHASE_NORMAL)
542 return;
544 debug_tree_remove_all (ew->debug_tree);
545 list = anjuta_session_get_string_list (session, "Debugger", "Watch");
546 if (list != NULL)
547 debug_tree_add_full_watch_list (ew->debug_tree, list);
550 /* Constructor & Destructor
551 *---------------------------------------------------------------------------*/
553 ExprWatch *
554 expr_watch_new (AnjutaPlugin *plugin)
556 ExprWatch *ew;
558 ew = g_new0 (ExprWatch, 1);
559 ew->plugin = plugin;
560 create_expr_watch_gui (ew);
561 ew->debugger = dma_debug_manager_get_queue (ANJUTA_PLUGIN_DEBUG_MANAGER (plugin));
563 /* Connect to Load and Save event */
564 g_signal_connect (ew->plugin->shell, "save-session",
565 G_CALLBACK (on_session_save), ew);
566 g_signal_connect (ew->plugin->shell, "load-session",
567 G_CALLBACK (on_session_load), ew);
569 /* Add watch window */
570 anjuta_shell_add_widget (ew->plugin->shell,
571 ew->scrolledwindow,
572 "AnjutaDebuggerWatch", _("Watches"),
573 "gdb-watch-icon", ANJUTA_SHELL_PLACEMENT_BOTTOM,
574 NULL);
576 /* Connect to debugger */
577 g_signal_connect_swapped (ew->plugin, "program-started", G_CALLBACK (on_program_started), ew);
579 return ew;
582 void
583 expr_watch_destroy (ExprWatch * ew)
585 AnjutaUI *ui;
587 g_return_if_fail (ew != NULL);
589 /* Disconnect from Load and Save event */
590 g_signal_handlers_disconnect_matched (ew->plugin->shell, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, ew);
591 g_signal_handlers_disconnect_matched (ew->plugin, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, ew);
593 ui = anjuta_shell_get_ui (ew->plugin->shell, NULL);
594 anjuta_ui_remove_action_group (ui, ew->action_group);
595 anjuta_ui_remove_action_group (ui, ew->toggle_group);
597 debug_tree_free (ew->debug_tree);
598 gtk_widget_destroy (ew->scrolledwindow);
599 g_free (ew);