Added byline
[anjuta.git] / plugins / debug-manager / signals.c
blob87e7dbc85f7b59f81d2510e1c070c18493f62c6c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 signals.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 <sys/stat.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <ctype.h>
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"
35 #include "signals.h"
38 enum _SignalColums
40 SIGNAL_COLUMN_NAME,
41 SIGNAL_COLUMN_STOP,
42 SIGNAL_COLUMN_PRINT,
43 SIGNAL_COLUMN_PASS,
44 SIGNAL_COLUMN_DESCRIPTION,
45 SIGNAL_COLUMN_COUNT
48 static void
49 signals_update_controls (Signals * ew)
51 gboolean R, Pr;
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);
60 * signals_update:
62 static void
63 signals_update (const GList * lines, gpointer data)
65 Signals *sg;
66 gint j, count;
67 gchar *str;
68 gchar sig[32], stop[10], print[10], pass[10];
69 GList *list, *node;
70 GtkTreeModel *model;
71 GtkTreeIter iter;
73 sg = (Signals *) data;
74 signals_clear (sg);
75 list = gdb_util_remove_blank_lines (lines);
76 if (g_list_length (list) < 2)
78 g_list_free (list);
79 return;
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);
84 node = list->next;
86 /* Skip the first two lines */
87 if (node)
88 node = node->next;
89 if (node)
90 node = node->next;
91 while (node)
93 count =
94 sscanf ((char *) node->data, "~%s %s %s %s", sig, stop, print, pass);
95 str = node->data;
96 node = g_list_next (node);
97 if (count != 4)
98 continue;
100 /* Do not worry. This is used to avoid the last line */
101 if (node == NULL)
102 break;
103 for (j = 0; j < 4; j++)
105 while (isspace (*str))
106 str++;
107 while (!isspace (*str))
108 str++;
110 while (isspace (*str))
111 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,
120 -1);
123 /* FIXME: do we need to free the char data as well? */
124 g_list_free (list);
125 gtk_tree_view_set_model (GTK_TREE_VIEW (sg->widgets.treeview), model);
128 static gint
129 on_signals_delete_event(GtkWidget* w, GdkEvent *event, gpointer data)
131 Signals* cr = (Signals*) data;
132 signals_hide (cr);
133 return TRUE;
136 static gboolean
137 on_signals_key_press_event(GtkWidget *widget, GdkEventKey *event,
138 gpointer data)
140 if (event->keyval == GDK_KEY_Escape)
142 Signals* cr = (Signals*) data;
143 signals_hide(cr);
144 return TRUE;
146 return FALSE;
149 static void
150 on_signals_send_activate (GtkMenuItem *menuitem, gpointer user_data)
152 Signals *s = (Signals*)user_data;
153 #if 0
154 gchar* sig;
155 GtkTreeSelection *selection;
156 GtkTreeModel *model;
157 GtkTreeIter iter;
158 #endif
159 if (dma_debugger_queue_get_state (s->debugger) != IANJUTA_DEBUGGER_PROGRAM_RUNNING)
160 return;
161 /* has FIXME in debugger.c in gdb plugin */
162 #if 0
164 signals_show (s);
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,
169 -1);
170 debugger_signal(sig, TRUE);
171 g_free (sig);
172 #endif
175 static void
176 on_signals_update_activate (GtkMenuItem *menuitem, gpointer user_data)
178 Signals *s = (Signals*)user_data;
179 dma_queue_info_signal (
180 s->debugger,
181 (IAnjutaDebuggerCallback)signals_update,
186 * Show popup menu on #GtkTreeView
188 static gboolean
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,
198 NULL, NULL, NULL,
199 bevent->button, bevent->time);
201 return TRUE;
205 * on_column_toggled:
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().
217 static void
218 on_column_toggled(GtkCellRendererToggle *renderer, gchar *path, Signals *sg)
220 GtkTreeIter iter;
221 gchar *signal;
222 gboolean data[SIGNAL_COLUMN_COUNT];
223 guint column;
225 if (dma_debugger_queue_get_state (sg->debugger) != IANJUTA_DEBUGGER_PROGRAM_STOPPED)
227 return;
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),
233 &iter,
234 path);
235 gtk_tree_model_get (GTK_TREE_MODEL (sg->widgets.store),
236 &iter,
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],
241 -1);
243 data[column] = !data[column];
245 gtk_list_store_set (sg->widgets.store,
246 &iter,
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]);
252 g_free (signal);
255 static void
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,
263 renderer,
264 "active", column_num,
265 NULL);
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);
272 static GtkWidget *
273 signals_create_list_store_and_treeview(Signals *sg)
275 GtkListStore *store;
276 GtkWidget *w;
277 GtkCellRenderer *renderer;
278 GtkTreeViewColumn *column;
280 store = gtk_list_store_new (SIGNAL_COLUMN_COUNT,
281 G_TYPE_STRING,
282 G_TYPE_BOOLEAN,
283 G_TYPE_BOOLEAN,
284 G_TYPE_BOOLEAN,
285 G_TYPE_STRING
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"),
292 renderer,
293 "text", SIGNAL_COLUMN_NAME,
294 NULL);
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"),
303 renderer,
304 "text", SIGNAL_COLUMN_DESCRIPTION,
305 NULL);
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);
311 return w;
314 /* Actions table
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 */
323 NULL, /* Tooltip */
324 G_CALLBACK (on_signals_send_activate) /* action callback */
328 static GtkActionEntry actions_signals_program_stopped[] = {
330 "ActionDmaSignalUpdate",
331 GTK_STOCK_REFRESH,
332 N_("Update"),
333 NULL,
334 NULL,
335 G_CALLBACK (on_signals_update_activate)
339 static void
340 destroy_signals_gui (Signals *sg)
345 static void
346 create_signals_gui (Signals *sg)
348 GtkWidget *window3;
349 GtkWidget *scrolledwindow4;
350 GtkWidget *tv;
351 AnjutaUI *ui;
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),
378 "/PopupSignals");
380 sg->is_showing = FALSE;
381 sg->win_width = 460;
382 sg->win_height = 320;
383 sg->win_pos_x = 150;
384 sg->win_pos_y = 130;
387 static void
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);
395 static void
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);
403 /* Public functions
404 *---------------------------------------------------------------------------*/
406 void
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);
415 void
416 signals_show (Signals * sg)
418 if (sg)
420 if (sg->is_showing)
422 gdk_window_raise (gtk_widget_get_window (sg->widgets.window));
424 else
426 gtk_window_move (GTK_WINDOW (sg->widgets.window), sg->win_pos_x,
427 sg->win_pos_y);
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 (
433 sg->debugger,
434 (IAnjutaDebuggerCallback)signals_update,
435 sg);
440 void
441 signals_hide (Signals * sg)
443 GdkWindow *window;
445 if (sg)
447 if (sg->is_showing == FALSE)
448 return;
449 window = gtk_widget_get_window (sg->widgets.window);
450 gdk_window_get_root_origin (window, &sg->win_pos_x,
451 &sg->win_pos_y);
452 gdk_window_get_geometry (window, NULL, NULL, &sg->win_width,
453 &sg->win_height);
454 gtk_widget_hide (sg->widgets.window);
455 sg->is_showing = FALSE;
459 /* Constructor & Destructor
460 *---------------------------------------------------------------------------*/
462 Signals *
463 signals_new (DebugManagerPlugin *plugin)
465 Signals *sg;
466 AnjutaUI *ui;
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);
490 return sg;
493 void
494 signals_free (Signals * sg)
496 AnjutaUI *ui;
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);
508 /* Destroy GUI */
509 destroy_signals_gui (sg);
511 g_free (sg);