Updated Portuguese translation
[anjuta.git] / plugins / gdb / preferences.c
blob86ead93563a3ab8eccf5c45ddcd80458a402d646
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
2 /* preferences.c
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.
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
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 */
48 enum {
49 GDB_PP_ACTIVE_COLUMN,
50 GDB_PP_FILENAME_COLUMN,
51 GDB_PP_REGISTER_COLUMN,
52 GDB_PP_N_COLUMNS
55 /* Node types
56 *---------------------------------------------------------------------------*/
58 typedef struct
60 GtkTreeView *treeview;
61 GtkListStore *model;
62 GtkWidget *remove_button;
63 GList **list;
64 } PreferenceDialog;
67 /* Private functions
68 *---------------------------------------------------------------------------*/
70 static gboolean
71 gdb_append_missing_register_function (GString *msg, GtkTreeModel *model, GtkTreeIter *iter)
73 gboolean active;
74 gchar *path;
75 gchar *function;
76 gboolean missing;
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'));
85 if (missing)
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);
91 g_free (path);
92 g_free (function);
94 return missing;
97 static void
98 gdb_check_register_function (PreferenceDialog *dlg, GtkTreeIter *iter)
100 GString *list;
102 list = g_string_new (NULL);
103 if (iter == NULL)
105 GtkTreeIter iter;
106 gboolean valid;
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);
114 else
116 gdb_append_missing_register_function (list, GTK_TREE_MODEL (dlg->model), iter);
119 if (list->len > 0)
121 gchar *msg;
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);
132 g_free (msg);
133 g_string_free (list, TRUE);
137 static gchar *
138 gdb_find_register_function (const gchar *path)
140 GFile *file;
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))
148 GRegex *regex;
149 GMatchInfo *match;
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);
158 g_free (content);
161 g_object_unref (file);
163 return function;
166 static gboolean
167 on_add_printer_in_list (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data)
169 GList** list = (GList **)user_data;
170 gchar *filepath;
171 gchar *function;
172 gboolean active;
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,
178 -1);
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);
185 return FALSE;
188 /* Call backs
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);
196 void
197 gdb_on_destroy_preferences (GtkWidget *object, gpointer user_data)
199 PreferenceDialog *dlg = (PreferenceDialog *)user_data;
200 GList *new_list;
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));
205 *(dlg->list) = NULL;
207 /* Replace with new one */
208 new_list = NULL;
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;
213 g_free (dlg);
216 void
217 gdb_on_printer_add (GtkButton *button, gpointer user_data)
219 PreferenceDialog *dlg = (PreferenceDialog *)user_data;
220 GtkWidget *chooser;
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,
228 NULL);
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)
236 GSList *filenames;
237 GSList *item;
239 filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (chooser));
241 for (item = filenames; item != NULL; item = g_slist_next (item))
243 GtkTreeIter iter;
244 gchar *path = (gchar *)item->data;
245 gchar *function;
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,
253 -1);
254 g_free (path);
255 g_free (function);
257 gdb_check_register_function (dlg, &iter);
259 g_slist_free (filenames);
261 gtk_widget_destroy (chooser);
264 void
265 gdb_on_printer_remove (GtkButton *button, gpointer user_data)
267 PreferenceDialog *dlg = (PreferenceDialog *)user_data;
268 GtkTreeIter iter;
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);
278 static void
279 gdb_on_printer_activate (GtkCellRendererToggle *cell_renderer, const gchar *path, gpointer user_data)
281 PreferenceDialog *dlg = (PreferenceDialog *)user_data;
282 GtkTreeIter iter;
284 if (gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dlg->model), &iter, path))
286 gboolean enable;
288 gtk_tree_model_get (GTK_TREE_MODEL (dlg->model), &iter, GDB_PP_ACTIVE_COLUMN, &enable, -1);
289 enable = !enable;
290 gtk_list_store_set (dlg->model, &iter, GDB_PP_ACTIVE_COLUMN, enable, -1);
294 static void
295 gdb_on_printer_function_changed (GtkCellRendererText *renderer,
296 gchar *path,
297 gchar *new_text,
298 gpointer user_data)
300 PreferenceDialog *dlg = (PreferenceDialog *)user_data;
301 GtkTreeIter iter;
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);
310 static void
311 gdb_on_printer_selection_changed (GtkTreeSelection *selection, gpointer user_data)
313 PreferenceDialog *dlg = (PreferenceDialog *)user_data;
314 GtkTreeIter iter;
315 GtkTreeSelection* sel;
316 gboolean selected;
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);
323 /* Public functions
324 *---------------------------------------------------------------------------*/
326 void
327 gdb_merge_preferences (AnjutaPreferences* prefs, GList **list)
329 GtkBuilder *bxml;
330 GtkCellRenderer *renderer;
331 GtkTreeViewColumn *column;
332 GtkTreeSelection *selection;
333 PreferenceDialog *dlg;
334 GList *item;
336 g_return_if_fail (list != NULL);
338 /* Create the preferences page */
339 bxml = anjuta_util_builder_new (BUILDER_FILE, NULL);
340 if (!bxml) return;
342 dlg = g_new0 (PreferenceDialog, 1);
344 /* Get widgets */
345 anjuta_util_builder_get_objects (bxml,
346 GDB_PRINTER_TREEVIEW, &dlg->treeview,
347 GDB_PRINTER_REMOVE_BUTTON, &dlg->remove_button,
348 NULL);
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);
382 /* Fill tree view */
383 dlg->list = list;
384 for (item = g_list_first (*list); item != NULL; item = g_list_next (item))
386 GdbPrettyPrinter *printer = (GdbPrettyPrinter *)item->data;
387 GtkTreeIter iter;
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,
393 -1);
396 anjuta_preferences_add_from_builder (prefs, bxml, NULL, GDB_PREFS_ROOT, _("Gdb Debugger"), ICON_FILE);
398 g_object_unref (bxml);
401 void
402 gdb_unmerge_preferences (AnjutaPreferences* prefs)
404 anjuta_preferences_remove_page(prefs, _("Gdb Debugger"));
407 GList *
408 gdb_load_pretty_printers (AnjutaSession *session)
410 GList *session_list;
411 GList *list = NULL;
412 GList *item;
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;
419 gchar *ptr;
421 printer = g_slice_new0 (GdbPrettyPrinter);
422 ptr = strchr (name, ':');
423 if (ptr != NULL)
425 if (*name == 'E') printer->enable = TRUE;
426 name = ptr + 1;
428 ptr = strrchr (name, ':');
429 if (ptr != NULL)
431 *ptr = '\0';
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);
442 return list;
445 gboolean
446 gdb_save_pretty_printers (AnjutaSession *session, GList *list)
448 GList *session_list = NULL;
449 GList *item;
451 for (item = g_list_first (list); item != NULL; item = g_list_next (item))
453 GdbPrettyPrinter *printer = (GdbPrettyPrinter *)item->data;
454 gchar *name;
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);
465 return FALSE;
468 void
469 gdb_pretty_printer_free (GdbPrettyPrinter *printer)
471 g_free (printer->path);
472 g_free (printer->function);
473 g_slice_free (GdbPrettyPrinter, printer);