1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
4 * Copyright (C) 2010 Sébastien Granjoux
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (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 GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
27 #include "preferences.h"
30 #include <libanjuta/anjuta-utils.h>
33 #define BUILDER_FILE PACKAGE_DATA_DIR"/glade/anjuta-gdb.ui"
35 #define BUILD_PREFS_DIALOG "preferences_dialog_build"
36 #define GDB_PREFS_ROOT "gdb_preferences_container"
37 #define GDB_PRINTER_TREEVIEW "printers_treeview"
38 #define GDB_PRINTER_REMOVE_BUTTON "remove_button"
41 #define ICON_FILE "anjuta-gdb.plugin.png"
43 #define GDB_SECTION "Gdb"
44 #define GDB_PRINTER_KEY "PrettyPrinter"
47 /* column of the printer list view */
50 GDB_PP_FILENAME_COLUMN
,
51 GDB_PP_REGISTER_COLUMN
,
56 *---------------------------------------------------------------------------*/
60 GtkTreeView
*treeview
;
62 GtkWidget
*remove_button
;
68 *---------------------------------------------------------------------------*/
71 gdb_append_missing_register_function (GString
*msg
, GtkTreeModel
*model
, GtkTreeIter
*iter
)
78 gtk_tree_model_get (model
, iter
,
79 GDB_PP_ACTIVE_COLUMN
, &active
,
80 GDB_PP_FILENAME_COLUMN
, &path
,
81 GDB_PP_REGISTER_COLUMN
, &function
, -1);
82 if (function
!= NULL
) function
= g_strstrip (function
);
84 missing
= active
&& ((function
== NULL
) || (*function
== '\0'));
87 g_string_append (msg
, path
);
88 g_string_append (msg
, "\n");
89 gtk_list_store_set (GTK_LIST_STORE (model
), iter
, GDB_PP_ACTIVE_COLUMN
, FALSE
, -1);
98 gdb_check_register_function (PreferenceDialog
*dlg
, GtkTreeIter
*iter
)
102 list
= g_string_new (NULL
);
108 for (valid
= gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dlg
->model
), &iter
);
109 valid
; valid
= gtk_tree_model_iter_next (GTK_TREE_MODEL (dlg
->model
), &iter
))
111 gdb_append_missing_register_function (list
, GTK_TREE_MODEL (dlg
->model
), &iter
);
116 gdb_append_missing_register_function (list
, GTK_TREE_MODEL (dlg
->model
), iter
);
123 /* Translators: pretty printer file is a script containing functions allowing gdb
124 * to display variable content in a simpler way, typically removing
125 * implementation details.
126 * The register function is an additional function in the script. It defines
127 * which function is used for each type of variables. */
128 msg
= g_strdup_printf(_("The register function hasn't been found automatically in the following pretty printer files:\n"
129 "%s\nYou need to fill yourself the register function columns before enabling the rows. "
130 "Most of the time the register function name contains the word \"register\"."), list
->str
);
131 anjuta_util_dialog_warning (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (dlg
->treeview
))), msg
);
133 g_string_free (list
, TRUE
);
138 gdb_find_register_function (const gchar
*path
)
141 gchar
*function
= NULL
;
142 gchar
*content
= NULL
;
144 file
= g_file_new_for_path (path
);
146 if (g_file_load_contents (file
, NULL
, &content
, NULL
, NULL
, NULL
))
151 regex
= g_regex_new ("^def\\s+(register\\w*)\\s*\\(\\w+\\)\\s*:", G_REGEX_CASELESS
| G_REGEX_MULTILINE
, 0, NULL
);
152 if (g_regex_match (regex
, content
, 0, &match
))
154 function
= g_match_info_fetch (match
, 1);
155 g_match_info_free (match
);
157 g_regex_unref (regex
);
161 g_object_unref (file
);
167 on_add_printer_in_list (GtkTreeModel
*model
, GtkTreePath
*path
, GtkTreeIter
*iter
, gpointer user_data
)
169 GList
** list
= (GList
**)user_data
;
173 GdbPrettyPrinter
*printer
;
175 gtk_tree_model_get (model
, iter
, GDB_PP_ACTIVE_COLUMN
, &active
,
176 GDB_PP_FILENAME_COLUMN
, &filepath
,
177 GDB_PP_REGISTER_COLUMN
, &function
,
179 printer
= g_slice_new0 (GdbPrettyPrinter
);
180 printer
->enable
= active
;
181 printer
->path
= filepath
;
182 printer
->function
= function
;
183 *list
= g_list_prepend (*list
, printer
);
189 *---------------------------------------------------------------------------*/
191 /* Gtk builder callbacks */
192 void gdb_on_printer_add (GtkButton
*button
, gpointer user_data
);
193 void gdb_on_printer_remove (GtkButton
*button
, gpointer user_data
);
194 void gdb_on_destroy_preferences (GtkWidget
*object
, gpointer user_data
);
197 gdb_on_destroy_preferences (GtkWidget
*object
, gpointer user_data
)
199 PreferenceDialog
*dlg
= (PreferenceDialog
*)user_data
;
202 /* Free previous list and replace with new one */
203 g_list_foreach (*(dlg
->list
), (GFunc
)gdb_pretty_printer_free
, NULL
);
204 g_list_free (*(dlg
->list
));
207 /* Replace with new one */
209 gtk_tree_model_foreach (GTK_TREE_MODEL (dlg
->model
), on_add_printer_in_list
, &new_list
);
210 new_list
= g_list_reverse (new_list
);
211 *(dlg
->list
) = new_list
;
217 gdb_on_printer_add (GtkButton
*button
, gpointer user_data
)
219 PreferenceDialog
*dlg
= (PreferenceDialog
*)user_data
;
221 GtkFileFilter
*filter
;
223 chooser
= gtk_file_chooser_dialog_new (_("Select a pretty printer file"),
224 GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button
))),
225 GTK_FILE_CHOOSER_ACTION_OPEN
,
226 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
227 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
229 filter
= gtk_file_filter_new ();
230 gtk_file_filter_add_mime_type (filter
, "text/x-python");
231 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser
), TRUE
);
232 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser
),filter
);
234 if (gtk_dialog_run (GTK_DIALOG (chooser
)) == GTK_RESPONSE_ACCEPT
)
239 filenames
= gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (chooser
));
241 for (item
= filenames
; item
!= NULL
; item
= g_slist_next (item
))
244 gchar
*path
= (gchar
*)item
->data
;
247 function
= gdb_find_register_function (path
);
249 gtk_list_store_append (dlg
->model
, &iter
);
250 gtk_list_store_set (dlg
->model
, &iter
, GDB_PP_ACTIVE_COLUMN
, TRUE
,
251 GDB_PP_FILENAME_COLUMN
, path
,
252 GDB_PP_REGISTER_COLUMN
, function
,
257 gdb_check_register_function (dlg
, &iter
);
259 g_slist_free (filenames
);
261 gtk_widget_destroy (chooser
);
265 gdb_on_printer_remove (GtkButton
*button
, gpointer user_data
)
267 PreferenceDialog
*dlg
= (PreferenceDialog
*)user_data
;
269 GtkTreeSelection
* sel
;
271 sel
= gtk_tree_view_get_selection (dlg
->treeview
);
272 if (gtk_tree_selection_get_selected (sel
, NULL
, &iter
))
274 gtk_list_store_remove (dlg
->model
, &iter
);
279 gdb_on_printer_activate (GtkCellRendererToggle
*cell_renderer
, const gchar
*path
, gpointer user_data
)
281 PreferenceDialog
*dlg
= (PreferenceDialog
*)user_data
;
284 if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dlg
->model
), &iter
, path
))
288 gtk_tree_model_get (GTK_TREE_MODEL (dlg
->model
), &iter
, GDB_PP_ACTIVE_COLUMN
, &enable
, -1);
290 gtk_list_store_set (dlg
->model
, &iter
, GDB_PP_ACTIVE_COLUMN
, enable
, -1);
295 gdb_on_printer_function_changed (GtkCellRendererText
*renderer
,
300 PreferenceDialog
*dlg
= (PreferenceDialog
*)user_data
;
303 if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dlg
->model
), &iter
, path
))
305 gchar
*function
= g_strstrip (new_text
);
306 gtk_list_store_set (dlg
->model
, &iter
, GDB_PP_REGISTER_COLUMN
, function
, -1);
311 gdb_on_printer_selection_changed (GtkTreeSelection
*selection
, gpointer user_data
)
313 PreferenceDialog
*dlg
= (PreferenceDialog
*)user_data
;
315 GtkTreeSelection
* sel
;
318 sel
= gtk_tree_view_get_selection (dlg
->treeview
);
319 selected
= gtk_tree_selection_get_selected (sel
, NULL
, &iter
);
320 gtk_widget_set_sensitive(dlg
->remove_button
, selected
);
324 *---------------------------------------------------------------------------*/
327 gdb_merge_preferences (AnjutaPreferences
* prefs
, GList
**list
)
330 GtkCellRenderer
*renderer
;
331 GtkTreeViewColumn
*column
;
332 GtkTreeSelection
*selection
;
333 PreferenceDialog
*dlg
;
336 g_return_if_fail (list
!= NULL
);
338 /* Create the preferences page */
339 bxml
= anjuta_util_builder_new (BUILDER_FILE
, NULL
);
342 dlg
= g_new0 (PreferenceDialog
, 1);
345 anjuta_util_builder_get_objects (bxml
,
346 GDB_PRINTER_TREEVIEW
, &dlg
->treeview
,
347 GDB_PRINTER_REMOVE_BUTTON
, &dlg
->remove_button
,
350 /* Create tree view */
351 dlg
->model
= gtk_list_store_new (GDB_PP_N_COLUMNS
,
352 G_TYPE_BOOLEAN
, G_TYPE_STRING
, G_TYPE_STRING
);
353 gtk_tree_view_set_model (dlg
->treeview
, GTK_TREE_MODEL (dlg
->model
));
354 g_object_unref (dlg
->model
);
356 renderer
= gtk_cell_renderer_toggle_new ();
357 g_signal_connect (G_OBJECT (renderer
), "toggled", G_CALLBACK (gdb_on_printer_activate
), dlg
);
358 column
= gtk_tree_view_column_new_with_attributes (_("Activate"), renderer
,
359 "active", GDB_PP_ACTIVE_COLUMN
, NULL
);
360 gtk_tree_view_append_column (dlg
->treeview
, column
);
362 renderer
= gtk_cell_renderer_text_new ();
363 column
= gtk_tree_view_column_new_with_attributes (_("File"), renderer
,
364 "text", GDB_PP_FILENAME_COLUMN
, NULL
);
365 gtk_tree_view_append_column (dlg
->treeview
, column
);
367 renderer
= gtk_cell_renderer_text_new ();
368 g_object_set(renderer
, "editable", TRUE
, NULL
);
369 g_signal_connect(renderer
, "edited", G_CALLBACK (gdb_on_printer_function_changed
), dlg
);
370 /* Translators: The "Register Function" column contains the name of a
371 * function used to register pretty printers in gdb. */
372 column
= gtk_tree_view_column_new_with_attributes (_("Register Function"), renderer
,
373 "text", GDB_PP_REGISTER_COLUMN
, NULL
);
374 gtk_tree_view_append_column (dlg
->treeview
, column
);
376 /* Connect all signals */
377 gtk_builder_connect_signals (bxml
, dlg
);
378 selection
= gtk_tree_view_get_selection (dlg
->treeview
);
379 g_signal_connect (G_OBJECT (selection
), "changed", G_CALLBACK (gdb_on_printer_selection_changed
), dlg
);
384 for (item
= g_list_first (*list
); item
!= NULL
; item
= g_list_next (item
))
386 GdbPrettyPrinter
*printer
= (GdbPrettyPrinter
*)item
->data
;
389 gtk_list_store_append (dlg
->model
, &iter
);
390 gtk_list_store_set (dlg
->model
, &iter
, GDB_PP_ACTIVE_COLUMN
, printer
->enable
? TRUE
: FALSE
,
391 GDB_PP_FILENAME_COLUMN
, printer
->path
,
392 GDB_PP_REGISTER_COLUMN
, printer
->function
,
396 anjuta_preferences_add_from_builder (prefs
, bxml
, NULL
, GDB_PREFS_ROOT
, _("Gdb Debugger"), ICON_FILE
);
398 g_object_unref (bxml
);
402 gdb_unmerge_preferences (AnjutaPreferences
* prefs
)
404 anjuta_preferences_remove_page(prefs
, _("Gdb Debugger"));
408 gdb_load_pretty_printers (AnjutaSession
*session
)
414 session_list
= anjuta_session_get_string_list (session
, GDB_SECTION
, GDB_PRINTER_KEY
);
415 for (item
= g_list_first (session_list
); item
!= NULL
; item
= g_list_next (item
))
417 GdbPrettyPrinter
*printer
;
418 gchar
*name
= (gchar
*)item
->data
;
421 printer
= g_slice_new0 (GdbPrettyPrinter
);
422 ptr
= strchr (name
, ':');
425 if (*name
== 'E') printer
->enable
= TRUE
;
428 ptr
= strrchr (name
, ':');
432 printer
->function
= g_strdup (ptr
+ 1);
434 printer
->path
= g_strdup (name
);
436 list
= g_list_prepend (list
, printer
);
439 g_list_foreach (session_list
, (GFunc
)g_free
, NULL
);
440 g_list_free (session_list
);
446 gdb_save_pretty_printers (AnjutaSession
*session
, GList
*list
)
448 GList
*session_list
= NULL
;
451 for (item
= g_list_first (list
); item
!= NULL
; item
= g_list_next (item
))
453 GdbPrettyPrinter
*printer
= (GdbPrettyPrinter
*)item
->data
;
456 name
= g_strconcat (printer
->enable
? "E:" : "D:", printer
->path
, ":", printer
->function
== NULL
? "" : printer
->function
, NULL
);
458 session_list
= g_list_prepend (session_list
, name
);
460 session_list
= g_list_reverse (session_list
);
461 anjuta_session_set_string_list (session
, GDB_SECTION
, GDB_PRINTER_KEY
, session_list
);
462 g_list_foreach (session_list
, (GFunc
)g_free
, NULL
);
463 g_list_free (session_list
);
469 gdb_pretty_printer_free (GdbPrettyPrinter
*printer
)
471 g_free (printer
->path
);
472 g_free (printer
->function
);
473 g_slice_free (GdbPrettyPrinter
, printer
);