1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
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
29 #include <glib/gi18n.h>
30 #include <gdk/gdkkeysyms.h>
31 #include <libanjuta/anjuta-shell.h>
32 #include <libanjuta/resources.h>
34 #include "utilities.h"
44 SIGNAL_COLUMN_DESCRIPTION
,
49 signals_update_controls (Signals
* ew
)
53 R
= dma_debugger_queue_get_state (ew
->debugger
) == IANJUTA_DEBUGGER_PROGRAM_STOPPED
;
54 Pr
= dma_debugger_queue_get_state (ew
->debugger
) == IANJUTA_DEBUGGER_PROGRAM_RUNNING
;
55 gtk_action_group_set_sensitive(ew
->action_group_program_stopped
, R
);
56 gtk_action_group_set_sensitive(ew
->action_group_program_running
, Pr
);
63 signals_update (const GList
* lines
, gpointer data
)
68 gchar sig
[32], stop
[10], print
[10], pass
[10];
73 sg
= (Signals
*) data
;
75 list
= gdb_util_remove_blank_lines (lines
);
76 if (g_list_length (list
) < 2)
82 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (sg
->widgets
.treeview
));
83 gtk_tree_view_set_model (GTK_TREE_VIEW (sg
->widgets
.treeview
), NULL
);
86 /* Skip the first two lines */
94 sscanf ((char *) node
->data
, "~%s %s %s %s", sig
, stop
, print
, pass
);
96 node
= g_list_next (node
);
100 /* Do not worry. This is used to avoid the last line */
103 for (j
= 0; j
< 4; j
++)
105 while (isspace (*str
))
107 while (!isspace (*str
))
110 while (isspace (*str
))
113 gtk_list_store_append (GTK_LIST_STORE (model
), &iter
);
114 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
115 SIGNAL_COLUMN_NAME
, sig
,
116 SIGNAL_COLUMN_STOP
, strcmp (stop
, "Yes") == 0,
117 SIGNAL_COLUMN_PRINT
, strcmp (print
, "Yes") == 0,
118 SIGNAL_COLUMN_PASS
, strcmp (pass
, "Yes") == 0,
119 SIGNAL_COLUMN_DESCRIPTION
, str
,
123 /* FIXME: do we need to free the char data as well? */
125 gtk_tree_view_set_model (GTK_TREE_VIEW (sg
->widgets
.treeview
), model
);
129 on_signals_delete_event(GtkWidget
* w
, GdkEvent
*event
, gpointer data
)
131 Signals
* cr
= (Signals
*) data
;
137 on_signals_key_press_event(GtkWidget
*widget
, GdkEventKey
*event
,
140 if (event
->keyval
== GDK_KEY_Escape
)
142 Signals
* cr
= (Signals
*) data
;
150 on_signals_send_activate (GtkMenuItem
*menuitem
, gpointer user_data
)
152 Signals
*s
= (Signals
*)user_data
;
155 GtkTreeSelection
*selection
;
159 if (dma_debugger_queue_get_state (s
->debugger
) != IANJUTA_DEBUGGER_PROGRAM_RUNNING
)
161 /* has FIXME in debugger.c in gdb plugin */
165 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (s
->widgets
.treeview
));
166 gtk_tree_selection_get_selected (selection
, &model
, &iter
);
167 gtk_tree_model_get (model
, &iter
,
168 SIGNAL_COLUMN_NAME
, &sig
,
170 debugger_signal(sig
, TRUE
);
176 on_signals_update_activate (GtkMenuItem
*menuitem
, gpointer user_data
)
178 Signals
*s
= (Signals
*)user_data
;
179 dma_queue_info_signal (
181 (IAnjutaDebuggerCallback
)signals_update
,
186 * Show popup menu on #GtkTreeView
189 on_signals_event (GtkWidget
*widget
, GdkEventButton
*bevent
, gpointer user_data
)
191 Signals
*ew
= (Signals
*)user_data
;
193 if (bevent
->type
!= GDK_BUTTON_PRESS
) return FALSE
;
194 if (bevent
->button
!= 3) return FALSE
;
196 signals_update_controls(ew
);
197 gtk_menu_popup (GTK_MENU(ew
->widgets
.menu
), NULL
,
199 bevent
->button
, bevent
->time
);
207 * @renderer: cell renderer on which the toggle happened
208 * @path: row in list where the change happened
209 * @sig: instance of #Signals
211 * Callback if one of the three boolean columns has been toggled by the
212 * user. If the debugged program is not stopped this function will
213 * do nothing. Function will fetch state of signal from list store, update the
214 * affected column and pass on the data to the debugging backend using
215 * dma_queue_handler_signal().
218 on_column_toggled(GtkCellRendererToggle
*renderer
, gchar
*path
, Signals
*sg
)
222 gboolean data
[SIGNAL_COLUMN_COUNT
];
225 if (dma_debugger_queue_get_state (sg
->debugger
) != IANJUTA_DEBUGGER_PROGRAM_STOPPED
)
230 column
= GPOINTER_TO_INT (g_object_get_data (G_OBJECT (renderer
), "__column_nr"));
232 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (sg
->widgets
.store
),
235 gtk_tree_model_get (GTK_TREE_MODEL (sg
->widgets
.store
),
237 SIGNAL_COLUMN_NAME
, &signal
,
238 SIGNAL_COLUMN_STOP
, &data
[SIGNAL_COLUMN_STOP
],
239 SIGNAL_COLUMN_PRINT
, &data
[SIGNAL_COLUMN_PRINT
],
240 SIGNAL_COLUMN_PASS
, &data
[SIGNAL_COLUMN_PASS
],
243 data
[column
] = !data
[column
];
245 gtk_list_store_set (sg
->widgets
.store
,
247 column
, data
[column
], -1);
248 dma_queue_handle_signal (sg
->debugger
, signal
,
249 data
[SIGNAL_COLUMN_STOP
],
250 data
[SIGNAL_COLUMN_PRINT
],
251 data
[SIGNAL_COLUMN_PASS
]);
256 signals_add_toggle_column (GtkTreeView
*tv
, const gchar
*title
, guint column_num
, Signals
*sg
)
258 GtkCellRenderer
*renderer
;
259 GtkTreeViewColumn
*column
;
261 renderer
= gtk_cell_renderer_toggle_new ();
262 column
= gtk_tree_view_column_new_with_attributes (title
,
264 "active", column_num
,
266 gtk_tree_view_append_column (tv
, column
);
267 g_object_set_data (G_OBJECT (renderer
), "__column_nr", GINT_TO_POINTER (column_num
));
268 g_signal_connect (G_OBJECT (renderer
),
269 "toggled", G_CALLBACK (on_column_toggled
), sg
);
273 signals_create_list_store_and_treeview(Signals
*sg
)
277 GtkCellRenderer
*renderer
;
278 GtkTreeViewColumn
*column
;
280 store
= gtk_list_store_new (SIGNAL_COLUMN_COUNT
,
288 w
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (store
));
290 renderer
= gtk_cell_renderer_text_new ();
291 column
= gtk_tree_view_column_new_with_attributes (_("Signal"),
293 "text", SIGNAL_COLUMN_NAME
,
295 gtk_tree_view_append_column (GTK_TREE_VIEW (w
), column
);
297 signals_add_toggle_column (GTK_TREE_VIEW (w
), _("Stop"), SIGNAL_COLUMN_STOP
, sg
);
298 signals_add_toggle_column (GTK_TREE_VIEW (w
), _("Print"), SIGNAL_COLUMN_PRINT
, sg
);
299 signals_add_toggle_column (GTK_TREE_VIEW (w
), _("Pass"), SIGNAL_COLUMN_PASS
, sg
);
301 renderer
= gtk_cell_renderer_text_new ();
302 column
= gtk_tree_view_column_new_with_attributes (_("Description"),
304 "text", SIGNAL_COLUMN_DESCRIPTION
,
306 gtk_tree_view_append_column (GTK_TREE_VIEW (w
), column
);
308 g_signal_connect (G_OBJECT (w
), "button-press-event",
309 G_CALLBACK (on_signals_event
), sg
);
315 *---------------------------------------------------------------------------*/
317 static GtkActionEntry actions_signals_program_running
[] = {
319 "ActionDmaSignalSend", /* Action name */
320 NULL
, /* Stock icon, if any */
321 N_("Send to process"), /* Display label */
322 NULL
, /* short-cut */
324 G_CALLBACK (on_signals_send_activate
) /* action callback */
328 static GtkActionEntry actions_signals_program_stopped
[] = {
330 "ActionDmaSignalUpdate",
335 G_CALLBACK (on_signals_update_activate
)
340 destroy_signals_gui (Signals
*sg
)
346 create_signals_gui (Signals
*sg
)
349 GtkWidget
*scrolledwindow4
;
353 window3
= gtk_window_new (GTK_WINDOW_TOPLEVEL
);
354 gtk_widget_set_size_request (window3
, 170, -1);
355 gtk_window_set_title (GTK_WINDOW (window3
), _("Kernel signals"));
356 gtk_window_set_wmclass (GTK_WINDOW (window3
), "signals", "Anjuta");
357 gtk_window_set_default_size (GTK_WINDOW (window3
), 240, 230);
359 scrolledwindow4
= gtk_scrolled_window_new (NULL
, NULL
);
360 gtk_widget_show (scrolledwindow4
);
361 gtk_container_add (GTK_CONTAINER (window3
), scrolledwindow4
);
362 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow4
),
363 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
365 tv
= signals_create_list_store_and_treeview (sg
);
366 gtk_widget_show (tv
);
367 gtk_container_add (GTK_CONTAINER (scrolledwindow4
), tv
);
368 g_signal_connect (G_OBJECT (window3
), "delete_event",
369 G_CALLBACK (on_signals_delete_event
),sg
);
370 g_signal_connect (G_OBJECT (window3
), "key-press-event",
371 G_CALLBACK (on_signals_key_press_event
), sg
);
373 sg
->widgets
.window
= window3
;
374 sg
->widgets
.treeview
= tv
;
375 sg
->widgets
.store
= GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (tv
)));
376 ui
= anjuta_shell_get_ui (sg
->plugin
->shell
, NULL
);
377 sg
->widgets
.menu
= gtk_ui_manager_get_widget (GTK_UI_MANAGER (ui
),
380 sg
->is_showing
= FALSE
;
382 sg
->win_height
= 320;
388 on_program_exited (Signals
* sg
)
390 g_signal_handlers_disconnect_by_func (sg
->plugin
, G_CALLBACK (on_program_exited
), sg
);
392 destroy_signals_gui(sg
);
396 on_program_started (Signals
* sg
)
398 create_signals_gui(sg
);
400 g_signal_connect_swapped (sg
->plugin
, "program-exited", G_CALLBACK (on_program_exited
), sg
);
404 *---------------------------------------------------------------------------*/
407 signals_clear (Signals
* sg
)
409 g_return_if_fail (sg
->widgets
.store
!= NULL
);
410 g_return_if_fail (GTK_IS_LIST_STORE(sg
->widgets
.store
));
412 gtk_list_store_clear (sg
->widgets
.store
);
416 signals_show (Signals
* sg
)
422 gdk_window_raise (gtk_widget_get_window (sg
->widgets
.window
));
426 gtk_window_move (GTK_WINDOW (sg
->widgets
.window
), sg
->win_pos_x
,
428 gtk_window_set_default_size (GTK_WINDOW (sg
->widgets
.window
),
429 sg
->win_width
, sg
->win_height
);
430 gtk_widget_show (sg
->widgets
.window
);
431 sg
->is_showing
= TRUE
;
432 dma_queue_info_signal (
434 (IAnjutaDebuggerCallback
)signals_update
,
441 signals_hide (Signals
* sg
)
447 if (sg
->is_showing
== FALSE
)
449 window
= gtk_widget_get_window (sg
->widgets
.window
);
450 gdk_window_get_root_origin (window
, &sg
->win_pos_x
,
452 gdk_window_get_geometry (window
, NULL
, NULL
, &sg
->win_width
,
454 gtk_widget_hide (sg
->widgets
.window
);
455 sg
->is_showing
= FALSE
;
459 /* Constructor & Destructor
460 *---------------------------------------------------------------------------*/
463 signals_new (DebugManagerPlugin
*plugin
)
468 sg
= g_new0 (Signals
, 1);
469 g_return_val_if_fail (sg
!= NULL
, NULL
);
471 sg
->plugin
= ANJUTA_PLUGIN (plugin
);
472 sg
->debugger
= dma_debug_manager_get_queue (plugin
);
474 ui
= anjuta_shell_get_ui (ANJUTA_PLUGIN(plugin
)->shell
, NULL
);
475 sg
->action_group_program_stopped
=
476 anjuta_ui_add_action_group_entries (ui
, "ActionGroupSignalsProgramStopped",
477 _("Signal operations"),
478 actions_signals_program_stopped
,
479 G_N_ELEMENTS (actions_signals_program_stopped
),
480 GETTEXT_PACKAGE
, TRUE
, sg
);
481 sg
->action_group_program_running
=
482 anjuta_ui_add_action_group_entries (ui
, "ActionGroupSignalsProgramRunning",
483 _("Signal operations"),
484 actions_signals_program_running
,
485 G_N_ELEMENTS (actions_signals_program_running
),
486 GETTEXT_PACKAGE
, TRUE
, sg
);
488 g_signal_connect_swapped (plugin
, "program-started", G_CALLBACK (on_program_started
), sg
);
494 signals_free (Signals
* sg
)
498 g_return_if_fail (sg
!= NULL
);
500 /* Disconnect from debugger */
501 g_signal_handlers_disconnect_matched (sg
->plugin
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, sg
);
503 /* Remove menu actions */
504 ui
= anjuta_shell_get_ui (sg
->plugin
->shell
, NULL
);
505 anjuta_ui_remove_action_group (ui
, sg
->action_group_program_stopped
);
506 anjuta_ui_remove_action_group (ui
, sg
->action_group_program_running
);
509 destroy_signals_gui (sg
);